aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.clang-format2
-rw-r--r--.github/ISSUE_TEMPLATE/bug_report.yml46
-rw-r--r--.github/ISSUE_TEMPLATE/config.yml5
-rw-r--r--.github/ISSUE_TEMPLATE/feature_request.yml3
-rw-r--r--.github/ISSUE_TEMPLATE/lsp_bug_report.yml50
-rw-r--r--.github/workflows/ci.yml1
-rw-r--r--.github/workflows/release.yml12
-rw-r--r--.github/workflows/squash-typos.yml5
-rw-r--r--CONTRIBUTING.md89
-rw-r--r--README.md4
-rw-r--r--cmake/FindLibLUV.cmake2
-rw-r--r--contrib/flake.nix7
-rw-r--r--runtime/autoload/man.vim18
-rw-r--r--runtime/doc/autocmd.txt2
-rw-r--r--runtime/doc/change.txt6
-rw-r--r--runtime/doc/develop.txt14
-rw-r--r--runtime/doc/eval.txt1
-rw-r--r--runtime/doc/insert.txt6
-rw-r--r--runtime/doc/lsp.txt117
-rw-r--r--runtime/doc/lua.txt74
-rw-r--r--runtime/doc/nvim_terminal_emulator.txt4
-rw-r--r--runtime/doc/options.txt33
-rw-r--r--runtime/doc/treesitter.txt12
-rw-r--r--runtime/doc/various.txt20
-rw-r--r--runtime/doc/vim_diff.txt15
-rw-r--r--runtime/filetype.vim12
-rw-r--r--runtime/ftplugin/julia.vim92
-rw-r--r--runtime/ftplugin/man.vim14
-rw-r--r--runtime/indent/julia.vim491
-rw-r--r--runtime/lua/vim/F.lua4
-rw-r--r--runtime/lua/vim/highlight.lua14
-rw-r--r--runtime/lua/vim/lsp.lua303
-rw-r--r--runtime/lua/vim/lsp/buf.lua86
-rw-r--r--runtime/lua/vim/lsp/codelens.lua8
-rw-r--r--runtime/lua/vim/lsp/diagnostic.lua258
-rw-r--r--runtime/lua/vim/lsp/handlers.lua28
-rw-r--r--runtime/lua/vim/lsp/log.lua10
-rw-r--r--runtime/lua/vim/lsp/protocol.lua13
-rw-r--r--runtime/lua/vim/lsp/rpc.lua132
-rw-r--r--runtime/lua/vim/lsp/util.lua314
-rw-r--r--runtime/lua/vim/shared.lua138
-rw-r--r--runtime/lua/vim/treesitter.lua23
-rw-r--r--runtime/lua/vim/treesitter/highlighter.lua12
-rw-r--r--runtime/lua/vim/treesitter/language.lua8
-rw-r--r--runtime/lua/vim/treesitter/languagetree.lua34
-rw-r--r--runtime/lua/vim/treesitter/query.lua68
-rw-r--r--runtime/lua/vim/uri.lua24
-rw-r--r--runtime/plugin/man.vim2
-rw-r--r--runtime/syntax/julia.vim550
-rw-r--r--runtime/syntax/man.vim6
-rw-r--r--runtime/syntax/scala.vim5
-rwxr-xr-xscripts/release.sh15
-rw-r--r--scripts/squash_typos.py177
-rwxr-xr-xsrc/clint.py2
-rw-r--r--src/nvim/README.md104
-rw-r--r--src/nvim/api/private/dispatch.c6
-rw-r--r--src/nvim/api/private/handle.c40
-rw-r--r--src/nvim/api/private/handle.h24
-rw-r--r--src/nvim/api/private/helpers.c3
-rw-r--r--src/nvim/api/private/helpers.h8
-rw-r--r--src/nvim/api/ui.c38
-rw-r--r--src/nvim/api/vim.c16
-rw-r--r--src/nvim/api/vim.h2
-rw-r--r--src/nvim/autocmd.c10
-rw-r--r--src/nvim/buffer.c9
-rw-r--r--src/nvim/buffer_defs.h4
-rw-r--r--src/nvim/change.c2
-rw-r--r--src/nvim/channel.c19
-rw-r--r--src/nvim/channel.h4
-rw-r--r--src/nvim/decoration.c11
-rw-r--r--src/nvim/edit.c7
-rw-r--r--src/nvim/eval.c19
-rw-r--r--src/nvim/ex_cmds.c46
-rw-r--r--src/nvim/ex_cmds2.c2
-rw-r--r--src/nvim/ex_getln.c23
-rw-r--r--src/nvim/extmark.c44
-rw-r--r--src/nvim/fileio.c2
-rw-r--r--src/nvim/fold.c4
-rw-r--r--src/nvim/generators/gen_api_dispatch.lua2
-rw-r--r--src/nvim/generators/gen_options.lua6
-rw-r--r--src/nvim/getchar.c28
-rw-r--r--src/nvim/highlight.c58
-rw-r--r--src/nvim/lua/executor.c23
-rw-r--r--src/nvim/lua/treesitter.c66
-rw-r--r--src/nvim/lua/vim.lua57
-rw-r--r--src/nvim/lua/xdiff.c334
-rw-r--r--src/nvim/lua/xdiff.h12
-rw-r--r--src/nvim/main.c8
-rw-r--r--src/nvim/map.c49
-rw-r--r--src/nvim/map.h22
-rw-r--r--src/nvim/marktree.c7
-rw-r--r--src/nvim/marktree.h2
-rw-r--r--src/nvim/memline.c57
-rw-r--r--src/nvim/msgpack_rpc/channel.c18
-rw-r--r--src/nvim/msgpack_rpc/channel_defs.h2
-rw-r--r--src/nvim/normal.c14
-rw-r--r--src/nvim/ops.c30
-rw-r--r--src/nvim/options.lua731
-rw-r--r--src/nvim/os/env.c15
-rw-r--r--src/nvim/os_unix.c1
-rw-r--r--src/nvim/runtime.c33
-rw-r--r--src/nvim/screen.c193
-rw-r--r--src/nvim/search.c238
-rw-r--r--src/nvim/spell.c6
-rw-r--r--src/nvim/spellfile.c2
-rw-r--r--src/nvim/syntax.c321
-rw-r--r--src/nvim/tag.c94
-rw-r--r--src/nvim/terminal.c39
-rw-r--r--src/nvim/testdir/setup.vim9
-rw-r--r--src/nvim/testdir/test42.inbin2373 -> 2387 bytes
-rw-r--r--src/nvim/testdir/test_autocmd.vim3
-rw-r--r--src/nvim/testdir/test_command_count.vim2
-rw-r--r--src/nvim/testdir/test_cursorline.vim22
-rw-r--r--src/nvim/testdir/test_diffmode.vim35
-rw-r--r--src/nvim/testdir/test_filetype.vim20
-rw-r--r--src/nvim/testdir/test_gf.vim2
-rw-r--r--src/nvim/testdir/test_ins_complete.vim2
-rw-r--r--src/nvim/testdir/test_join.vim2
-rw-r--r--src/nvim/testdir/test_match.vim5
-rw-r--r--src/nvim/testdir/test_mksession.vim2
-rw-r--r--src/nvim/testdir/test_normal.vim2
-rw-r--r--src/nvim/testdir/test_options.vim2
-rw-r--r--src/nvim/testdir/test_quickfix.vim2
-rw-r--r--src/nvim/testdir/test_tagjump.vim12
-rw-r--r--src/nvim/testdir/test_window_cmd.vim2
-rw-r--r--src/nvim/undo.c30
-rw-r--r--src/nvim/version.c5
-rw-r--r--src/nvim/window.c364
-rw-r--r--test/functional/api/buffer_updates_spec.lua10
-rw-r--r--test/functional/api/window_spec.lua18
-rw-r--r--test/functional/autocmd/termxx_spec.lua13
-rw-r--r--test/functional/eval/buf_functions_spec.lua10
-rw-r--r--test/functional/eval/match_functions_spec.lua15
-rw-r--r--test/functional/ex_cmds/drop_spec.lua1
-rw-r--r--test/functional/ex_cmds/quickfix_commands_spec.lua1
-rw-r--r--test/functional/fixtures/shell-test.c17
-rw-r--r--test/functional/helpers.lua14
-rw-r--r--test/functional/legacy/007_ball_buffer_list_spec.lua5
-rw-r--r--test/functional/legacy/008_autocommands_spec.lua3
-rw-r--r--test/functional/legacy/011_autocommands_spec.lua4
-rw-r--r--test/functional/legacy/012_directory_spec.lua1
-rw-r--r--test/functional/legacy/arglist_spec.lua2
-rw-r--r--test/functional/legacy/cdo_spec.lua4
-rw-r--r--test/functional/legacy/fixeol_spec.lua4
-rw-r--r--test/functional/lua/buffer_updates_spec.lua16
-rw-r--r--test/functional/lua/xdiff_spec.lua112
-rw-r--r--test/functional/normal/K_spec.lua6
-rw-r--r--test/functional/plugin/lsp_spec.lua2
-rw-r--r--test/functional/plugin/shada_spec.lua6
-rw-r--r--test/functional/treesitter/node_spec.lua62
-rw-r--r--test/functional/ui/float_spec.lua3
-rw-r--r--test/functional/ui/highlight_spec.lua91
-rw-r--r--test/functional/ui/tabline_spec.lua1
-rw-r--r--test/helpers.lua10
-rw-r--r--test/unit/preprocess.lua4
155 files changed, 4756 insertions, 2508 deletions
diff --git a/.clang-format b/.clang-format
index ff61915aac..c86f5a3ddf 100644
--- a/.clang-format
+++ b/.clang-format
@@ -1,6 +1,6 @@
BasedOnStyle: Google
Language: Cpp
-ColumnLimit: 80
+ColumnLimit: 100
IndentWidth: 2
TabWidth: 2
UseTab: Never
diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml
index e9384c1982..fa8d05f6b5 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.yml
+++ b/.github/ISSUE_TEMPLATE/bug_report.yml
@@ -6,62 +6,68 @@ 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).
+ _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 such as "How do I...?" belong on the [Neovim Discourse](https://neovim.discourse.group/c/7-category/7) and will be closed.
- type: input
attributes:
- label: "Neovim Version"
- description: "`nvim --version`:"
+ label: "Neovim version (nvim -v)"
+ placeholder: "0.6.0 commit db1b0ee3b30f"
validations:
required: true
- type: input
attributes:
- label: "Operating system/version:"
+ label: "Vim (not Nvim) behaves the same?"
+ description: "Does `vim -u DEFAULTS` have the same issue? Note the exact Vim version (`8.x.yyyy`)."
+ placeholder: "no, vim 7.3.432"
validations:
required: true
- type: input
attributes:
- label: "Terminal name/version:"
+ label: "Operating system/version"
+ placeholder: "macOS 11.5"
validations:
required: true
- type: input
attributes:
- label: "TERM environment variable"
- description: "echo `$TERM`:"
+ label: "Terminal name/version"
+ placeholder: "xterm 3.1"
+ validations:
+ required: true
+ - type: input
+ attributes:
+ label: "$TERM environment variable"
+ placeholder: "echo $TERM"
validations:
required: true
- type: input
attributes:
label: "Installation"
- description: "How did you install neovim: build from repo / system package manager / appimage / homebrew / snap / chocolatey / other (please specify)?"
+ description: "How did you install neovim: build from repo / system package manager / appimage / homebrew / snap / chocolatey / other (describe)?"
placeholder: "Arch User Repository (AUR)"
validations:
required: true
- type: textarea
attributes:
- label: "Steps to reproduce"
+ label: "How to reproduce the issue"
description: |
- Steps to reproduce using `nvim -u NORC` and/or `nvim -u NONE` (please test both).
- If you are reporting build failures, please list the exact sequence of steps including all CMake flags (if any).
- validations:
- required: true
-
- - type: input
- attributes:
- label: "Vim"
- description: "Does Vim behave differently when called with `vim -u DEFAULTS`? (Please add the specific version, including patch level, of Vim that you tested.)"
+ - Steps to reproduce using `nvim -u NORC` or `nvim -u NONE` (try both).
+ - For build failures: list the exact steps including CMake flags (if any).
+ - For shell-related problems: try `env -i TERM=ansi-256color "$(which nvim)"`.
+ placeholder: |
+ nvim -u NONE
+ :edit foo
+ yiwp
validations:
required: true
- type: textarea
attributes:
label: "Expected behavior"
- description: "A description of the behavior you expected. May optionally include logs, images, or videos."
+ description: "Describe the behavior you expect. May include logs, images, or videos."
validations:
required: true
-
- type: textarea
attributes:
label: "Actual behavior"
diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml
new file mode 100644
index 0000000000..796707be03
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/config.yml
@@ -0,0 +1,5 @@
+blank_issues_enabled: true
+contact_links:
+ - name: Question
+ url: https://neovim.discourse.group/
+ about: Ask questions about configuration and usage of Neovim
diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml
index a9ed2824cb..2b6fa3daf4 100644
--- a/.github/ISSUE_TEMPLATE/feature_request.yml
+++ b/.github/ISSUE_TEMPLATE/feature_request.yml
@@ -11,7 +11,8 @@ body:
- type: input
attributes:
label: "Feature already in Vim?"
- description: "Does the feature already exist in Vim? If possible, please specify which version of Vim it was introduced in."
+ description: "Does the feature already exist in Vim? If possible, specify which version (or commit) that introduced it."
+ placeholder: "Yes, Vim 7.3.432"
- type: textarea
attributes:
diff --git a/.github/ISSUE_TEMPLATE/lsp_bug_report.yml b/.github/ISSUE_TEMPLATE/lsp_bug_report.yml
index ba1905329b..b5b7687bf8 100644
--- a/.github/ISSUE_TEMPLATE/lsp_bug_report.yml
+++ b/.github/ISSUE_TEMPLATE/lsp_bug_report.yml
@@ -1,69 +1,61 @@
-name: Language server client bug report
-description: Report a built-in lsp problem in Neovim
+name: Language server (LSP) client bug
+description: Report an issue with Neovim LSP
labels: [bug, lsp]
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 such as "How do I...?" or "Why isn't X language server/feature working?" belong on the [Neovim Discourse](https://neovim.discourse.group/c/7-category/7) 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://github.com/neovim/neovim/wiki/FAQ). Usage questions such as "How do I...?" or "Why isn't X language server/feature working?" belong on the [Neovim Discourse](https://neovim.discourse.group/c/7-category/7) and will be closed.
- type: input
attributes:
- label: "Neovim Version"
- description: "`nvim --version`:"
+ label: "Neovim version (nvim -v)"
+ placeholder: "0.6.0 commit db1b0ee3b30f"
validations:
required: true
- type: input
attributes:
- label: "Language server name/version:"
+ label: "Language server name/version"
+ placeholder: "rls 0.5.2"
validations:
required: true
- type: input
attributes:
- label: "Operating system/version:"
+ label: "Operating system/version"
+ placeholder: "emacs 23"
validations:
required: true
- type: textarea
attributes:
- label: Checkhealth
+ label: ':checkhealth'
description: |
- Paste the results from `nvim -c ":checkhealth nvim lspconfig"` here:
+ Paste the results from `nvim -c ":checkhealth nvim lspconfig"`
render: markdown
- - type: markdown
- attributes:
- value: |
- Note: if the issue is with an autocompletion or other LSP plugin, please report it at that plugin's issue tracker. Download the minimal config with `wget https://raw.githubusercontent.com/neovim/nvim-lspconfig/master/test/minimal_init.lua` and modify it to include any specific commands or servers pertaining to your issues.
- type: textarea
attributes:
- label: "Steps to reproduce"
+ label: 'Steps to reproduce using "nvim -u minimal_init.lua"'
description: |
- Steps to reproduce using `nvim -u minimal_init.lua`:
+ - Download the minimal config with `curl -LO https://raw.githubusercontent.com/neovim/nvim-lspconfig/master/test/minimal_init.lua` and modify it to include any specific commands or servers pertaining to your issues.
+ - _Note_: if the issue is with an autocompletion or other LSP plugin, report to that plugin's issue tracker.
validations:
required: true
- type: textarea
attributes:
label: "Expected behavior"
- description: "A description of the behavior you expected. May optionally include logs, images, or videos."
+ description: "Describe the behavior you expect. May include logs, images, or videos."
- type: textarea
attributes:
label: "Actual behavior"
- - type: markdown
- attributes:
- value: |
- Please upload `lsp.log` before and after the problem in a [secret gist](https://gist.github.com/). Paste the url to the gist in the text field below.
-
- You can set the log level by adding the Lua command
- `vim.lsp.set_log_level("debug")`
- after setting up LSP in your config.
-
- You can find the location of the log with the command
- `:lua print(vim.lsp.get_log_path())`
-
- type: input
attributes:
- label: "Link to uploaded log file"
+ label: "Log file"
+ placeholder: "https://gist.github.com/prakhar1989/1b0a2c9849b2e1e912fb"
+ description: |
+ - Upload `lsp.log` before and after the problem in a [secret gist](https://gist.github.com/). Paste the URL to the gist.
+ - You can set the log level by adding `vim.lsp.set_log_level("debug")` after setting up LSP in your config.
+ - You can find the location of the log with `:lua print(vim.lsp.get_log_path())`
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 3b89730434..f75320048b 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -3,6 +3,7 @@ on:
push:
branches: '**'
pull_request:
+ types: [opened, synchronize, reopened, ready_for_review]
branches:
- 'master'
- 'release-[0-9]+.[0-9]+'
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index ff7562bf20..c6d3eaf42b 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -28,10 +28,14 @@ jobs:
run: |
sudo apt-get update
sudo apt-get install -y autoconf automake build-essential cmake gcc-11 gettext gperf libtool-bin locales ninja-build pkg-config unzip
+ - 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
+ - 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
- name: Build release
id: build
run: |
- CC=gcc-11 make CMAKE_BUILD_TYPE=RelWithDebInfo CMAKE_EXTRA_FLAGS="-DCMAKE_INSTALL_PREFIX:PATH="
+ CC=gcc-11 make CMAKE_BUILD_TYPE=${NVIM_BUILD_TYPE} CMAKE_EXTRA_FLAGS="-DCMAKE_INSTALL_PREFIX:PATH="
printf '::set-output name=version::%s\n' "$(./build/bin/nvim --version | head -n 3 | sed -z 's/\n/%0A/g')"
printf '::set-output name=release::%s\n' "$(./build/bin/nvim --version | head -n 1)"
make DESTDIR="$GITHUB_WORKSPACE/build/release/nvim-linux64" install
@@ -80,9 +84,13 @@ jobs:
brew update >/dev/null
brew upgrade
brew install automake ninja
+ - 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
+ - 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
- name: Build release
run: |
- make CMAKE_BUILD_TYPE=Release CMAKE_EXTRA_FLAGS="-DCMAKE_INSTALL_PREFIX:PATH= -DCMAKE_OSX_DEPLOYMENT_TARGET=10.11"
+ make CMAKE_BUILD_TYPE=${NVIM_BUILD_TYPE} CMAKE_EXTRA_FLAGS="-DCMAKE_INSTALL_PREFIX:PATH= -DCMAKE_OSX_DEPLOYMENT_TARGET=10.11"
make DESTDIR="$GITHUB_WORKSPACE/build/release/nvim-osx64" install
- name: Create package
run: |
diff --git a/.github/workflows/squash-typos.yml b/.github/workflows/squash-typos.yml
index 6f5e24a9b6..6779589dc6 100644
--- a/.github/workflows/squash-typos.yml
+++ b/.github/workflows/squash-typos.yml
@@ -1,7 +1,7 @@
name: Squash Typo Pull Requests
on:
- pull_request:
+ pull_request_target:
types: labeled
concurrency:
group: ${{ github.workflow }}
@@ -21,7 +21,6 @@ jobs:
- uses: actions/checkout@v2
with:
fetch-depth: 0
- ref: master
- uses: actions/setup-python@v2
- name: Setup git config
@@ -30,3 +29,5 @@ jobs:
git config --global user.email 'marvim@users.noreply.github.com'
- run: python scripts/squash_typos.py
+ env:
+ PR_NUMBER: ${{ github.event.number }}
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 56b200050f..da222bbc90 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -11,6 +11,7 @@ low-risk/isolated tasks:
- Try a [good first issue](../../labels/good-first-issue) or [complexity:low] issue.
- Fix bugs found by [Clang](#clang-scan-build), [PVS](#pvs-studio) or
[Coverity](#coverity).
+- [Improve documentation][wiki-contribute-help]
Reporting problems
------------------
@@ -18,17 +19,17 @@ Reporting problems
- [Check the FAQ][wiki-faq].
- [Search existing issues][github-issues] (including closed!)
- Update Neovim to the latest version to see if your problem persists.
-- Disable plugins incrementally, to narrow down the cause of the issue.
+- [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.
-- [Bisect][git-bisect] to the cause of a regression, if you are able. This is _extremely_ helpful.
-- Check `$NVIM_LOG_FILE`, if it exists.
+- Check the logs. `:edit $NVIM_LOG_FILE`
- Include `cmake --system-information` for build-related issues.
Developer guidelines
--------------------
-- Nvim contributors should read `:help dev`.
+- Nvim developers should read `:help dev`.
- External UI developers should read `:help dev-ui`.
- API client developers should read `:help dev-api-client`.
- Nvim developers are _strongly encouraged_ to install `ninja` for faster builds.
@@ -37,13 +38,12 @@ Developer guidelines
make distclean
make # Nvim build system uses ninja automatically, if available.
```
-- [Improve documentation][wiki-contribute-help]
Pull requests (PRs)
---------------------
-- To avoid duplicate work, create a `[WIP]` pull request as soon as possible.
-- Your PR must include **test coverage.** See [test/README.md][run-tests].
+- To avoid duplicate work, create a draft pull request.
+- Your PR must include [test coverage][run-tests].
- Avoid cosmetic changes to unrelated files in the same commit.
- Use a [feature branch][git-feature-branch] instead of the master branch.
- Use a **rebase workflow** for small PRs.
@@ -62,21 +62,25 @@ Pull requests (PRs)
- During a squash/fixup, use `exec make -C build unittest` between each
pick/edit/reword.
-### Stages: WIP, RFC, RDY
+### Stages: Draft and Ready for review
-Pull requests have three stages: `[WIP]` (Work In Progress), `[RFC]` (Request
-For Comment) and `[RDY]` (Ready).
+Pull requests have two stages: Draft and Ready for review.
-1. `[RFC]` is assumed by default, **do not** put "RFC" in the PR title (it adds
- noise to merge commit messages).
-2. Add `[WIP]` to the PR title if you are _not_ requesting feedback and the work
- is still in flux.
-3. Add `[RDY]` to the PR title if you are _done_ and only waiting on merge.
+1. [Create a Draft PR][pr-draft] while you are _not_ requesting feedback as
+ you are still working on the PR.
+ - You can skip this if your PR is ready for review.
+2. [Change your PR to ready][pr-ready] when the PR is ready for review.
+ - You can convert back to Draft at any time.
+
+Do __not__ add labels like `[RFC]` or `[WIP]` in the title to indicate the
+state of your PR: this just adds noise. Non-Draft PRs are assumed to be open
+for comments; if you want feedback from specific people, `@`-mention them in
+a comment.
### Commit messages
Follow the [conventional commits guidelines][conventional_commits] to *make reviews easier* and to make
-the VCS/git logs more valuable. The general structure of a commit message is as follows:
+the VCS/git logs more valuable. The general structure of a commit message is:
```
<type>([optional scope]): <description>
@@ -86,43 +90,27 @@ the VCS/git logs more valuable. The general structure of a commit message is as
[optional footer(s)]
```
-- Prefix the commit subject with one of the following _types_:
- - `build`: all changes related to the build system (involving scripts, configurations or tools) and package dependencies.
- - `ci`: all changes related to the continuous integration and deployment system - involving scripts, configurations or tools.
- - `docs`: all documentation changes. This includes both external documentation for users as well as internal documentation for developers.
- - `feat`: new abilities or functionality.
- - `fix`: a bug fix.
- - `perf`: performance improvements.
- - `refactor`: modification of the code base which neither adds a feature nor fixes a bug - such as removing redundant code, simplifying code, renaming variables, etc.
- - `revert`: revert previous commits.
- - `test`: all changes related to tests such as refactoring existing tests or adding new tests.
- - `vim-patch`: all patches from upstream Vim. The commit messages for patches has [slightly different rules](https://github.com/neovim/neovim/wiki/Merging-patches-from-upstream-Vim#pull-requests) as not to interfere with existing scripts.
- - `chore`: Lastly, if none of the types above fits you may use `chore` as the type.
-
-- Append optional scope to _type_ such as `(lsp)`, `(treesitter)`, `(float)`, ...
-
-- The _description_ shouldn't start with a capital letter or end in a period.
-
+- Prefix the commit subject with one of these [_types_](https://github.com/commitizen/conventional-commit-types/blob/master/index.json):
+ - `build`, `ci`, `docs`, `feat`, `fix`, `perf`, `refactor`, `revert`, `test`, `vim-patch`, `chore`
+ - You can **ignore this for "fixup" commits** or any commits you expect to be squashed.
+- Append optional scope to _type_ such as `(lsp)`, `(treesitter)`, `(float)`, …
+- _Description_ shouldn't start with a capital letter or end in a period.
+- Use the _imperative voice_: "Fix bug" rather than "Fixed bug" or "Fixes bug."
- Try to keep the first line under 72 characters.
+- A blank line must follow the subject.
+- Breaking API changes must be indicated by
+ 1. "!" after the type/scope, and
+ 2. a "BREAKING CHANGE" footer describing the change.
+ Example:
+ ```
+ refactor(provider)!: drop support for Python 2
-- A blank line must separate the subject from the description.
-
-- A breaking API change must be indicated by appending `!` after the type/scope and at the very beginning of the footer with a **BREAKING CHANGE**.
-
- Example:
-
- ```
- refactor(provider)!: drop support for Python 2
-
- BREAKING CHANGE: refactor to use Python 3 features since Python 2 is no longer supported.
- ```
-
-- Use the _imperative voice_: "Fix bug" rather than "Fixed bug" or "Fixes bug."
+ BREAKING CHANGE: refactor to use Python 3 features since Python 2 is no longer supported.
+ ```
### Automated builds (CI)
-Each pull request must pass the automated builds on [Travis CI], [sourcehut]
-and [AppVeyor].
+Each pull request must pass the automated builds on [sourcehut] and [GitHub Actions].
- CI builds are compiled with [`-Werror`][gcc-warnings], so compiler warnings
will fail the build.
@@ -276,11 +264,12 @@ as context, use the `-W` argument as well.
[wiki-faq]: https://github.com/neovim/neovim/wiki/FAQ
[review-checklist]: https://github.com/neovim/neovim/wiki/Code-review-checklist
[3174]: https://github.com/neovim/neovim/issues/3174
-[Travis CI]: https://travis-ci.org/neovim/neovim
[sourcehut]: https://builds.sr.ht/~jmk
-[AppVeyor]: https://ci.appveyor.com/project/neovim/neovim
+[GitHub Actions]: https://github.com/neovim/neovim/actions
[Merge a Vim patch]: https://github.com/neovim/neovim/wiki/Merging-patches-from-upstream-Vim
[Clang report]: https://neovim.io/doc/reports/clang/
[complexity:low]: https://github.com/neovim/neovim/issues?q=is%3Aopen+is%3Aissue+label%3Acomplexity%3Alow
[master error list]: https://raw.githubusercontent.com/neovim/doc/gh-pages/reports/clint/errors.json
[wiki-contribute-help]: https://github.com/neovim/neovim/wiki/contribute-%3Ahelp
+[pr-draft]: https://docs.github.com/en/github/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request
+[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
diff --git a/README.md b/README.md
index ac56e3ba00..ba8e7bff37 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
[![Neovim](https://raw.githubusercontent.com/neovim/neovim.github.io/master/logos/neovim-logo-300x87.png)](https://neovim.io)
[Documentation](https://neovim.io/doc/general/) |
-[Chat](https://gitter.im/neovim/neovim) |
+[Chat](https://app.element.io/#/room/#neovim:matrix.org) |
[Twitter](https://twitter.com/Neovim)
[![GitHub CI](https://github.com/neovim/neovim/workflows/CI/badge.svg)](https://github.com/neovim/neovim/actions?query=workflow%3A%22CI%22)
@@ -64,7 +64,7 @@ To install to a non-default location:
make CMAKE_INSTALL_PREFIX=/full/path/
make install
-To inspect the build, these CMake features are useful:
+CMake hints for inspecting the build:
- `cmake --build build --target help` lists all build targets.
- `build/CMakeCache.txt` (or `cmake -LAH build/`) contains the resolved values of all CMake variables.
diff --git a/cmake/FindLibLUV.cmake b/cmake/FindLibLUV.cmake
index af25c2ddaa..23b62b66d3 100644
--- a/cmake/FindLibLUV.cmake
+++ b/cmake/FindLibLUV.cmake
@@ -15,7 +15,7 @@ find_path(LIBLUV_INCLUDE_DIR luv/luv.h
PATHS ${PC_LIBLUV_INCLUDEDIR} ${PC_LIBLUV_INCLUDE_DIRS})
# Explicitly look for luv.so. #10407
-list(APPEND LIBLUV_NAMES luv luv_a libluv_a luv${CMAKE_SHARED_LIBRARY_SUFFIX})
+list(APPEND LIBLUV_NAMES luv_a luv libluv_a luv${CMAKE_SHARED_LIBRARY_SUFFIX})
find_library(LIBLUV_LIBRARY NAMES ${LIBLUV_NAMES}
HINTS ${PC_LIBLUV_LIBDIR} ${PC_LIBLUV_LIBRARY_DIRS})
diff --git a/contrib/flake.nix b/contrib/flake.nix
index c601377cd0..d07067a7a1 100644
--- a/contrib/flake.nix
+++ b/contrib/flake.nix
@@ -106,9 +106,10 @@
clang-tools # for clangd to find the correct headers
];
- shellHook = ''
+ shellHook = oa.shellHook + ''
export NVIM_PYTHON_LOG_LEVEL=DEBUG
export NVIM_LOG_FILE=/tmp/nvim.log
+ export ASAN_SYMBOLIZER_PATH=${pkgs.llvm_11}/bin/llvm-symbolizer
# ASAN_OPTIONS=detect_leaks=1
export ASAN_OPTIONS="log_path=./test.log:abort_on_error=1"
@@ -118,6 +119,10 @@
# when running the functionaltests
mkdir -p outputs/out/share/nvim/syntax
touch outputs/out/share/nvim/syntax/syntax.vim
+
+ # for treesitter functionaltests
+ mkdir -p runtime/parser
+ cp -f ${pkgs.tree-sitter.builtGrammars.tree-sitter-c}/parser runtime/parser/c.so
'';
});
});
diff --git a/runtime/autoload/man.vim b/runtime/autoload/man.vim
index 4f556e6e87..8bf95651b7 100644
--- a/runtime/autoload/man.vim
+++ b/runtime/autoload/man.vim
@@ -65,6 +65,7 @@ function! man#open_page(count, mods, ...) abort
let b:man_sect = sect
endfunction
+" Called when a man:// buffer is opened.
function! man#read_page(ref) abort
try
let [sect, name] = s:extract_sect_and_name_ref(a:ref)
@@ -121,6 +122,15 @@ function! s:system(cmd, ...) abort
return opts.stdout
endfunction
+function! s:set_options(pager) abort
+ setlocal filetype=man
+ setlocal noswapfile buftype=nofile bufhidden=hide
+ setlocal nomodified readonly nomodifiable
+ if a:pager
+ nnoremap <silent> <buffer> <nowait> q :lclose<CR>:q<CR>
+ endif
+endfunction
+
function! s:get_page(path) abort
" Disable hard-wrap by using a big $MANWIDTH (max 1000 on some systems #9065).
" Soft-wrap: ftplugin/man.vim sets wrap/breakindent/….
@@ -134,9 +144,7 @@ function! s:get_page(path) abort
endfunction
function! s:put_page(page) abort
- setlocal modifiable
- setlocal noreadonly
- setlocal noswapfile
+ setlocal modifiable noreadonly noswapfile
silent keepjumps %delete _
silent put =a:page
while getline(1) =~# '^\s*$'
@@ -148,7 +156,7 @@ function! s:put_page(page) abort
silent! keeppatterns keepjumps %s/\s\{199,}/\=repeat(' ', 10)/g
1
lua require("man").highlight_man_page()
- setlocal filetype=man
+ call s:set_options(v:false)
endfunction
function! man#show_toc() abort
@@ -397,6 +405,7 @@ function! s:format_candidate(path, psect) abort
endif
endfunction
+" Called when Nvim is invoked as $MANPAGER.
function! man#init_pager() abort
" https://github.com/neovim/neovim/issues/6828
let og_modifiable = &modifiable
@@ -420,6 +429,7 @@ function! man#init_pager() abort
execute 'silent file man://'.tolower(fnameescape(ref))
endif
+ call s:set_options(v:true)
let &l:modifiable = og_modifiable
endfunction
diff --git a/runtime/doc/autocmd.txt b/runtime/doc/autocmd.txt
index 87c2e11a1e..03e182cb33 100644
--- a/runtime/doc/autocmd.txt
+++ b/runtime/doc/autocmd.txt
@@ -914,6 +914,8 @@ TermLeave After leaving |Terminal-mode|.
After TermClose.
*TermClose*
TermClose When a |terminal| job ends.
+ Sets these |v:event| keys:
+ status
*TermResponse*
TermResponse After the response to t_RV is received from
the terminal. The value of |v:termresponse|
diff --git a/runtime/doc/change.txt b/runtime/doc/change.txt
index 6be87af8a9..aed3acab67 100644
--- a/runtime/doc/change.txt
+++ b/runtime/doc/change.txt
@@ -986,9 +986,9 @@ inside of strings can change! Also see 'softtabstop' option. >
*Y*
["x]Y yank [count] lines [into register x] (synonym for
- yy, |linewise|). If you like "Y" to work from the
- cursor to the end of line (which is more logical,
- but not Vi-compatible) use ":map Y y$".
+ yy, |linewise|).
+ *Y-default*
+ Mapped to "y$" by default. |default-mappings|
*zy*
["x]zy{motion} Yank {motion} text [into register x]. Only differs
diff --git a/runtime/doc/develop.txt b/runtime/doc/develop.txt
index aec0178da2..60a3f870a9 100644
--- a/runtime/doc/develop.txt
+++ b/runtime/doc/develop.txt
@@ -46,7 +46,7 @@ NVIM IS... WELL DOCUMENTED *design-documented*
item is easier to find.
-NVIM IS... HIGH SPEED AND SMALL IN SIZE *design-speed-size*
+NVIM IS... FAST AND SMALL *design-speed-size*
Keep Nvim small and fast.
- Computers are becoming faster and bigger each year. Vim can grow too, but
@@ -191,8 +191,8 @@ definitions. The |lua-vim| :help is generated from the docstrings.
Docstring format:
- Lines in the main description start with `---`
-- Special tokens start with `--@` followed by the token name:
- `--@see`, `--@param`, `--@returns`
+- Special tokens start with `---@` followed by the token name:
+ `---@see`, `---@param`, `---@returns`
- Limited markdown is supported.
- List-items start with `-` (useful to nest or "indent")
- Use `<pre>` for code samples.
@@ -211,11 +211,11 @@ vim.paste in src/nvim/lua/vim.lua like this: >
--- end)()
--- </pre>
---
- --@see |paste|
+ ---@see |paste|
---
- --@param lines ...
- --@param phase ...
- --@returns false if client should cancel the paste.
+ ---@param lines ...
+ ---@param phase ...
+ ---@returns false if client should cancel the paste.
LUA *dev-lua*
diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt
index f70eb9e759..87240831a2 100644
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -1675,6 +1675,7 @@ v:event Dictionary of event data for the current |autocommand|. Valid
|v:false| if not.
changed_window Is |v:true| if the 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
diff --git a/runtime/doc/insert.txt b/runtime/doc/insert.txt
index c8a4168ab2..bb00c77ca8 100644
--- a/runtime/doc/insert.txt
+++ b/runtime/doc/insert.txt
@@ -68,12 +68,18 @@ CTRL-A Insert previously inserted text.
CTRL-W Delete the word before the cursor (see |i_backspacing| about
joining lines). See the section "word motions",
|word-motions|, for the definition of a word.
+ *i_CTRL-W-default*
+ By default, sets a new undo point before deleting.
+ |default-mappings|
*i_CTRL-U*
CTRL-U Delete all entered characters before the cursor in the current
line. If there are no newly entered characters and
'backspace' is not empty, delete all characters before the
cursor in the current line.
See |i_backspacing| about joining lines.
+ *i_CTRL-U-default*
+ By default, sets a new undo point before deleting.
+ |default-mappings|
*i_CTRL-I* *i_<Tab>* *i_Tab*
<Tab> or CTRL-I Insert a tab. If the 'expandtab' option is on, the
equivalent number of spaces is inserted (use CTRL-V <Tab> to
diff --git a/runtime/doc/lsp.txt b/runtime/doc/lsp.txt
index 7e589c095b..b04d9c267a 100644
--- a/runtime/doc/lsp.txt
+++ b/runtime/doc/lsp.txt
@@ -766,15 +766,6 @@ get_log_path() *vim.lsp.get_log_path()*
Return: ~
(String) Path to logfile.
-init({client}, {bufnr}) *vim.lsp.init()*
- client_id → state
-
- state pending_change?: function that the timer starts to
- trigger didChange pending_changes: list of tables with the
- pending changesets; for incremental_sync only
- use_incremental_sync: bool buffers?: table (bufnr → lines);
- for incremental sync only timer?: uv_timer
-
omnifunc({findstart}, {base}) *vim.lsp.omnifunc()*
Implements 'omnifunc' compatible LSP completion.
@@ -828,9 +819,9 @@ start_client({config}) *vim.lsp.start_client()*
table.
Parameters: ~
- {root_dir} (required, string) Directory where
- the LSP server will base its rootUri
- on initialization.
+ {root_dir} (string) Directory where the LSP
+ server will base its rootUri on
+ initialization.
{cmd} (required, string or list treated
like |jobstart()|) Base command that
initiates the LSP client.
@@ -1267,7 +1258,7 @@ enable({bufnr}, {client_id}) *vim.lsp.diagnostic.enable()*
the given client. The default is to enable
diagnostics for all attached clients.
-get({bufnr}, {client_id}) *vim.lsp.diagnostic.get()*
+get({bufnr}, {client_id}, {predicate}) *vim.lsp.diagnostic.get()*
Return associated diagnostics for bufnr
Parameters: ~
@@ -1275,6 +1266,8 @@ get({bufnr}, {client_id}) *vim.lsp.diagnostic.get()*
{client_id} number|nil If nil, then return all of the
diagnostics. Else, return just the
diagnostics associated with the client_id.
+ {predicate} function|nil Optional function for filtering
+ diagnostics
get_all({client_id}) *vim.lsp.diagnostic.get_all()*
Get all diagnostics for clients
@@ -1319,18 +1312,18 @@ get_line_diagnostics({bufnr}, {line_nr}, {opts}, {client_id})
Get the diagnostics by line
Parameters: ~
- {bufnr} number The buffer number
- {line_nr} number The line number
- {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.
- {client_id} number the client id
+ {bufnr} number|nil The buffer number
+ {line_nr} number|nil The line number
+ {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.
+ {client_id|nil} number the client id
Return: ~
table Table with map of line number to list of
@@ -1517,11 +1510,6 @@ reset({client_id}, {buffer_client_map}) *vim.lsp.diagnostic.reset()*
{buffer_client_map} table map of buffers to active
clients
- *vim.lsp.diagnostic.restore_extmarks()*
-restore_extmarks({bufnr}, {last})
- Parameters: ~
- {last} number last line that was changed
-
save({diagnostics}, {bufnr}, {client_id}) *vim.lsp.diagnostic.save()*
Save diagnostics to the current buffer.
@@ -1533,10 +1521,6 @@ save({diagnostics}, {bufnr}, {client_id}) *vim.lsp.diagnostic.save()*
{bufnr} number
{client_id} number
- *vim.lsp.diagnostic.save_extmarks()*
-save_extmarks({bufnr}, {client_id})
- TODO: Documentation
-
set_loclist({opts}) *vim.lsp.diagnostic.set_loclist()*
Sets the location list
@@ -1665,9 +1649,9 @@ set_virtual_text({diagnostics}, {bufnr}, {client_id}, {diagnostic_ns}, {opts})
E.g. "Warning" means { "Error",
"Warning" } will be valid.
- *vim.lsp.diagnostic.show_line_diagnostics()*
-show_line_diagnostics({opts}, {bufnr}, {line_nr}, {client_id})
- Open a floating window with the diagnostics from {line_nr}
+ *vim.lsp.diagnostic.show_diagnostics()*
+show_diagnostics({opts}, {diagnostics})
+ Open a floating window with the provided diagnostics
The floating window can be customized with the following
highlight groups: >
@@ -1679,20 +1663,52 @@ show_line_diagnostics({opts}, {bufnr}, {line_nr}, {client_id})
<
Parameters: ~
+ {opts} table Configuration table
+ • show_header (boolean, default true): Show
+ "Diagnostics:" header
+ • all opts for
+ |vim.lsp.util.open_floating_preview()|
+ can be used here
+ {diagnostics} table: The diagnostics to display
+
+ Return: ~
+ table {popup_bufnr, win_id}
+
+ *vim.lsp.diagnostic.show_line_diagnostics()*
+show_line_diagnostics({opts}, {buf_nr}, {line_nr}, {client_id})
+ Parameters: ~
{opts} table Configuration table
- • show_header (boolean, default true): Show
- "Diagnostics:" header.
- • Plus all the opts for
+ • all opts for
|vim.lsp.diagnostic.get_line_diagnostics()|
- and |vim.lsp.util.open_floating_preview()|
- can be used here.
- {bufnr} number The buffer number
- {line_nr} number The line number
+ and |show_diagnostics()| can be used here
+ {buf_nr} number|nil The buffer number
+ {line_nr} number|nil The line number
{client_id} number|nil the client id
Return: ~
table {popup_bufnr, win_id}
+ *vim.lsp.diagnostic.show_position_diagnostics()*
+show_position_diagnostics({opts}, {buf_nr}, {position})
+ Parameters: ~
+ {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.
+
+ • all opts for |show_diagnostics()| can be
+ used here
+ {buf_nr} number|nil The buffer number
+ {position} table|nil The (0,0)-indexed position
+
+ Return: ~
+ table {popup_bufnr, win_id}
+
==============================================================================
Lua module: vim.lsp.codelens *lsp-codelens*
@@ -1941,7 +1957,9 @@ diagnostics_to_items({diagnostics_by_bufnr}, {predicate})
Parameters: ~
{diagnostics_by_bufnr} table bufnr -> Diagnostic []
{predicate} an optional function to filter the
- diagnostics.
+ diagnostics. If present, only
+ diagnostic items matching will be
+ included.
Return: ~
table (A list of items)
@@ -1974,6 +1992,8 @@ get_effective_tabstop({bufnr}) *vim.lsp.util.get_effective_tabstop()*
|softtabstop|
get_line({uri}, {row}) *vim.lsp.util.get_line()*
+ Gets the zero-indexed line from the given uri.
+
Parameters: ~
{uri} string uri of the resource to get the line from
{row} number zero-indexed line number
@@ -1982,6 +2002,8 @@ get_line({uri}, {row}) *vim.lsp.util.get_line()*
string the line at row in filename
get_lines({uri}, {rows}) *vim.lsp.util.get_lines()*
+ Gets the zero-indexed lines from the given uri.
+
Parameters: ~
{uri} string uri of the resource to get the lines from
{rows} number[] zero-indexed line numbers
@@ -1989,9 +2011,6 @@ get_lines({uri}, {rows}) *vim.lsp.util.get_lines()*
Return: ~
table<number string> a table mapping rows to lines
-get_markdown_fences() *vim.lsp.util.get_markdown_fences()*
- TODO: Documentation
-
get_progress_messages() *vim.lsp.util.get_progress_messages()*
TODO: Documentation
@@ -2172,6 +2191,8 @@ preview_location({location}, {opts}) *vim.lsp.util.preview_location()*
or nil
rename({old_fname}, {new_fname}, {opts}) *vim.lsp.util.rename()*
+ Rename old_fname to new_fname
+
Parameters: ~
{opts} (table)
diff --git a/runtime/doc/lua.txt b/runtime/doc/lua.txt
index 1bbfde1980..3df57a3460 100644
--- a/runtime/doc/lua.txt
+++ b/runtime/doc/lua.txt
@@ -620,6 +620,73 @@ regex:match_line({bufnr}, {line_idx}[, {start}, {end}]) *regex:match_line()*
indices will be relative {start}.
------------------------------------------------------------------------------
+VIM.DIFF *lua-diff*
+
+vim.diff({a}, {b}, {opts}) *vim.diff()*
+ Run diff on strings {a} and {b}. Any indices returned by this
+ function, either directly or via callback arguments, are
+ 1-based.
+
+ Examples: >
+ vim.diff('a\n', 'b\nc\n')
+ -->
+ @@ -1 +1,2 @@
+ -a
+ +b
+ +c
+
+ vim.diff('a\n', 'b\nc\n', {result_type = 'indices'})
+ -->
+ {
+ {1, 1, 1, 2}
+ }
+<
+ Parameters: ~
+ {a} First string to compare
+ {b} Second string to compare
+ {opts} 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.
+ • `algorithm` (string):
+ Diff algorithm to use. Values:
+ • "myers" the default algorithm
+ • "minimal" spend extra time to generate the
+ smallest 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
+ • `ignore_whitespace_change` (boolean):
+ Ignore whitespace change
+ • `ignore_whitespace_change_at_eol` (boolean)
+ Ignore whitespace change at end-of-line.
+ • `ignore_cr_at_eol` (boolean)
+ Ignore carriage return at end-of-line
+ • `ignore_blank_lines` (boolean)
+ Ignore blank lines
+ • `indent_heuristic` (boolean):
+ Use the indent heuristic for the internal
+ diff library.
+
+ Return: ~
+ See {opts.result_type}. nil if {opts.on_hunk} is given.
+
+------------------------------------------------------------------------------
VIM *lua-builtin*
vim.api.{func}({...}) *vim.api*
@@ -1114,7 +1181,9 @@ make_dict_accessor({scope}) *vim.make_dict_accessor()*
TODO: Documentation
notify({msg}, {log_level}, {_opts}) *vim.notify()*
- Notification provider without a runtime, writes to :Messages
+ Notification provider
+
+ Without a runtime, writes to :Messages
Parameters: ~
{msg} Content of the notification to show to the
@@ -1123,6 +1192,9 @@ notify({msg}, {log_level}, {_opts}) *vim.notify()*
{opts} Dictionary with optional options (timeout,
etc)
+ See also: ~
+ :help nvim_notify
+
paste({lines}, {phase}) *vim.paste()*
Paste handler, invoked by |nvim_paste()| when a conforming UI
(such as the |TUI|) pastes text into the editor.
diff --git a/runtime/doc/nvim_terminal_emulator.txt b/runtime/doc/nvim_terminal_emulator.txt
index 6dbc54463c..e0589ba7b8 100644
--- a/runtime/doc/nvim_terminal_emulator.txt
+++ b/runtime/doc/nvim_terminal_emulator.txt
@@ -134,6 +134,10 @@ Example: >
programs can set this by emitting an escape sequence.
- |'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: >
+ autocmd TermClose * if !v:event.status | exe 'bdelete! '..expand('<abuf>') | endif
Use |jobwait()| to check if the terminal job has finished: >
let running = jobwait([&channel], 0)[0] == -1
diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt
index f0ce15ac0f..364d4c5167 100644
--- a/runtime/doc/options.txt
+++ b/runtime/doc/options.txt
@@ -3078,19 +3078,18 @@ A jump table for the options with a short description can be found at |Q_op|.
See |help-translated|.
*'hidden'* *'hid'* *'nohidden'* *'nohid'*
-'hidden' 'hid' boolean (default off)
- global
- When off a buffer is unloaded when it is |abandon|ed. When on a
- buffer becomes hidden when it is |abandon|ed. If the buffer is still
- displayed in another window, it does not become hidden, of course.
- The commands that move through the buffer list sometimes make a buffer
- hidden although the 'hidden' option is off: When the buffer is
- modified, 'autowrite' is off or writing is not possible, and the '!'
- flag was used. See also |windows.txt|.
- To only make one buffer hidden use the 'bufhidden' option.
- This option is set for one command with ":hide {command}" |:hide|.
- WARNING: It's easy to forget that you have changes in hidden buffers.
- Think twice when using ":q!" or ":qa!".
+'hidden' 'hid' boolean (default on)
+ global
+ When off a buffer is unloaded (including loss of undo information)
+ when it is |abandon|ed. When on a buffer becomes hidden when it is
+ |abandon|ed. A buffer displayed in another window does not become
+ hidden, of course.
+ Commands that move through the buffer list sometimes hide a buffer
+ although the 'hidden' option is off: when the buffer is modified,
+ 'autowrite' is off or writing is not possible, and the '!' flag was
+ used. See also |windows|.
+ To hide a specific buffer use the 'bufhidden' option.
+ 'hidden' is set for one command with ":hide {command}" |:hide|.
*'history'* *'hi'*
'history' 'hi' number (Vim default: 10000, Vi default: 0)
@@ -3213,7 +3212,7 @@ A jump table for the options with a short description can be found at |Q_op|.
option to a valid keymap name.
*'inccommand'* *'icm'*
-'inccommand' 'icm' string (default "")
+'inccommand' 'icm' string (default "nosplit")
global
"nosplit": Shows the effects of a command incrementally, as you type.
@@ -3498,7 +3497,7 @@ A jump table for the options with a short description can be found at |Q_op|.
|jumplist-stack|
*'joinspaces'* *'js'* *'nojoinspaces'* *'nojs'*
-'joinspaces' 'js' boolean (default on)
+'joinspaces' 'js' boolean (default off)
global
Insert two spaces after a '.', '?' and '!' with a join command.
Otherwise only one space is inserted.
@@ -6116,7 +6115,7 @@ A jump table for the options with a short description can be found at |Q_op|.
specify special kinds of buffers. See |special-buffers|.
*'switchbuf'* *'swb'*
-'switchbuf' 'swb' string (default "")
+'switchbuf' 'swb' string (default "uselast")
global
This option controls the behavior when switching between buffers.
Possible values (comma separated list):
@@ -6700,7 +6699,7 @@ A jump table for the options with a short description can be found at |Q_op|.
security reasons.
*'viewoptions'* *'vop'*
-'viewoptions' 'vop' string (default: "folds,options,cursor,curdir")
+'viewoptions' 'vop' string (default: "folds,cursor,curdir")
global
Changes the effect of the |:mkview| command. It is a comma separated
list of words. Each word enables saving and restoring something:
diff --git a/runtime/doc/treesitter.txt b/runtime/doc/treesitter.txt
index 906e2d716a..379523722e 100644
--- a/runtime/doc/treesitter.txt
+++ b/runtime/doc/treesitter.txt
@@ -86,6 +86,18 @@ Node methods *lua-treesitter-node*
tsnode:parent() *tsnode:parent()*
Get the node's immediate parent.
+tsnode:next_sibling() *tsnode:next_sibling()*
+ Get the node's next sibling.
+
+tsnode:prev_sibling() *tsnode:prev_sibling()*
+ Get the node's previous sibling.
+
+tsnode:next_named_sibling() *tsnode:next_named_sibling()*
+ Get the node's next named sibling.
+
+tsnode:prev_named_sibling() *tsnode:prev_named_sibling()*
+ Get the node's previous named sibling.
+
tsnode:iter_children() *tsnode:iter_children()*
Iterates over all the direct children of {tsnode}, regardless of
wether they are named or not.
diff --git a/runtime/doc/various.txt b/runtime/doc/various.txt
index ec91b6e29a..62e1e130ee 100644
--- a/runtime/doc/various.txt
+++ b/runtime/doc/various.txt
@@ -14,6 +14,10 @@ Various commands *various*
*CTRL-L*
CTRL-L Clears and redraws the screen. The redraw may happen
later, after processing typeahead.
+ *CTRL-L-default*
+ By default, also clears search highlighting
+ |:nohlsearch| and updates diffs |:diffupdate|.
+ |default-mappings|
*:mod* *:mode*
:mod[e] Clears and redraws the screen.
@@ -456,20 +460,14 @@ defined while executing a function, user command or autocommand, the script in
which it was defined is reported.
*K*
-[count]K Run a program to lookup the keyword under the
- cursor. The name of the program is given with the
- 'keywordprg' (kp) option (default is "man"). The
- keyword is formed of letters, numbers and the
- characters in 'iskeyword'. The keyword under or
- right of the cursor is used. The same can be done
- with the command >
- :!{program} {keyword}
+[count]K Runs the program given by 'keywordprg' to lookup the
+ |word| (defined by 'iskeyword') under or right of the
+ cursor. Default is "man". Works like this: >
+ :tabnew | terminal {program} {keyword}
< Special cases:
- If 'keywordprg' begins with ":" it is invoked as
a Vim command with [count].
- - If 'keywordprg' is empty, the ":help" command is
- used. It's a good idea to include more characters
- in 'iskeyword' then, to be able to find more help.
+ - If 'keywordprg' is empty, |:help| is used.
- When 'keywordprg' is equal to "man", a [count]
before "K" is inserted after the "man" command and
before the keyword. For example, using "2K" while
diff --git a/runtime/doc/vim_diff.txt b/runtime/doc/vim_diff.txt
index 2c53620049..166c0c17aa 100644
--- a/runtime/doc/vim_diff.txt
+++ b/runtime/doc/vim_diff.txt
@@ -41,9 +41,11 @@ the differences.
- 'fillchars' defaults (in effect) to "vert:│,fold:·,sep:│"
- 'formatoptions' defaults to "tcqj"
- 'fsync' is disabled
+- 'hidden' is enabled
- 'history' defaults to 10000 (the maximum)
- 'hlsearch' is enabled
- 'incsearch' is enabled
+- 'joinspaces' is disabled
- 'langnoremap' is enabled
- 'langremap' is disabled
- 'laststatus' defaults to 2 (statusline is always shown)
@@ -56,12 +58,13 @@ the differences.
- 'sidescroll' defaults to 1
- 'smarttab' is enabled
- 'startofline' is disabled
+- 'switchbuf' defaults to "uselast"
- 'tabpagemax' defaults to 50
- 'tags' defaults to "./tags;,tags"
- 'ttimeoutlen' defaults to 50
- 'ttyfast' is always set
-- 'viewoptions' includes "unix,slash"
- 'undodir' defaults to ~/.local/share/nvim/undo (|xdg|), auto-created
+- 'viewoptions' includes "unix,slash", excludes "options"
- 'viminfo' includes "!"
- 'wildmenu' is enabled
- 'wildoptions' defaults to "pum,tagfile"
@@ -72,6 +75,14 @@ the differences.
- |g:vimsyn_embed| defaults to "l" to enable Lua highlighting
+
+Default Mappings: *default-mappings*
+
+nnoremap Y y$
+nnoremap <C-L> <Cmd>nohlsearch<Bar>diffupdate<CR><C-L>
+inoremap <C-U> <C-G>u<C-U>
+inoremap <C-W> <C-G>u<C-W>
+
==============================================================================
3. New Features *nvim-features*
@@ -150,6 +161,7 @@ Commands:
|:drop| is always available
|:Man| is available by default, with many improvements such as completion
|:sign-define| accepts a `numhl` argument, to highlight the line number
+ |:match| can be invoked before highlight group is defined
Events:
|Signal|
@@ -167,6 +179,7 @@ Functions:
|msgpackdump()|, |msgpackparse()| provide msgpack de/serialization
|stdpath()|
|system()|, |systemlist()| can run {cmd} directly (without 'shell')
+ |matchadd()| can be called before highlight group is defined
Highlight groups:
|highlight-blend| controls blend level for a highlight group
diff --git a/runtime/filetype.vim b/runtime/filetype.vim
index f012c7cb4b..333da58128 100644
--- a/runtime/filetype.vim
+++ b/runtime/filetype.vim
@@ -533,8 +533,13 @@ au BufNewFile,BufRead *.drac,*.drc,*lvs,*lpe setf dracula
" Datascript
au BufNewFile,BufRead *.ds setf datascript
-" dsl
-au BufNewFile,BufRead *.dsl setf dsl
+" dsl: DSSSL or Structurizr
+au BufNewFile,BufRead *.dsl
+ \ if getline(1) =~ '^\s*<\!' |
+ \ setf dsl |
+ \ else |
+ \ setf structurizr |
+ \ endif
" DTD (Document Type Definition for XML)
au BufNewFile,BufRead *.dtd setf dtd
@@ -870,6 +875,9 @@ au BufNewFile,BufRead *.ipynb setf json
" JSONC
au BufNewFile,BufRead *.jsonc setf jsonc
+" Julia
+au BufNewFile,BufRead *.jl setf julia
+
" Kixtart
au BufNewFile,BufRead *.kix setf kix
diff --git a/runtime/ftplugin/julia.vim b/runtime/ftplugin/julia.vim
new file mode 100644
index 0000000000..32e364e436
--- /dev/null
+++ b/runtime/ftplugin/julia.vim
@@ -0,0 +1,92 @@
+" Vim filetype plugin file
+" Language: Julia
+" Maintainer: Carlo Baldassi <carlobaldassi@gmail.com>
+" Homepage: https://github.com/JuliaEditorSupport/julia-vim
+" Last Change: 2014 may 29
+" adapted from upstream 2021 Aug 4
+
+if exists("b:did_ftplugin")
+ finish
+endif
+let b:did_ftplugin = 1
+
+let s:save_cpo = &cpo
+set cpo-=C
+
+setlocal include=^\\s*\\%(reload\\\|include\\)\\>
+setlocal suffixesadd=.jl
+setlocal comments=:#
+setlocal commentstring=#\ %s
+setlocal cinoptions+=#1
+setlocal define=^\\s*macro\\>
+setlocal fo-=t fo+=croql
+
+let b:julia_vim_loaded = 1
+
+let b:undo_ftplugin = "setlocal include< suffixesadd< comments< commentstring<"
+ \ . " define< fo< shiftwidth< expandtab< indentexpr< indentkeys< cinoptions< completefunc<"
+ \ . " | unlet! b:julia_vim_loaded"
+
+" MatchIt plugin support
+if exists("loaded_matchit")
+ let b:match_ignorecase = 0
+
+ " note: begin_keywords must contain all blocks, in order
+ " for nested-structures-skipping to work properly
+ " note: 'mutable struct' and 'struct' are defined separately because
+ " using \? puts the cursor on 'struct' instead of 'mutable' for some reason
+ let b:julia_begin_keywords = '\%(\.\s*\|@\)\@<!\<\%(function\|macro\|begin\|mutable\s\+struct\|\%(mutable\s\+\)\@<!struct\|\%(abstract\|primitive\)\s\+type\|let\|do\|\%(bare\)\?module\|quote\|if\|for\|while\|try\)\>'
+ " note: the following regex not only recognizes macros, but also local/global keywords.
+ " the purpose is recognizing things like `@inline myfunction()`
+ " or `global myfunction(...)` etc, for matchit and block movement functionality
+ let s:macro_regex = '\%(@\%([#(]\@!\S\)\+\|\<\%(local\|global\)\)\s\+'
+ let s:nomacro = '\%(' . s:macro_regex . '\)\@<!'
+ let s:yesmacro = s:nomacro . '\%('. s:macro_regex . '\)\+'
+ let b:julia_begin_keywordsm = '\%(' . s:yesmacro . b:julia_begin_keywords . '\)\|'
+ \ . '\%(' . s:nomacro . b:julia_begin_keywords . '\)'
+ let b:julia_end_keywords = '\<end\>'
+
+ " note: this function relies heavily on the syntax file
+ function! JuliaGetMatchWords()
+ let [l,c] = [line('.'),col('.')]
+ let attr = synIDattr(synID(l, c, 1),"name")
+ let c1 = c
+ while attr == 'juliaMacro' || expand('<cword>') =~# '\<\%(global\|local\)\>'
+ normal! W
+ if line('.') > l || col('.') == c1
+ call cursor(l, c)
+ return ''
+ endif
+ let attr = synIDattr(synID(l, col('.'), 1),"name")
+ let c1 = col('.')
+ endwhile
+ call cursor(l, c)
+ if attr == 'juliaConditional'
+ return b:julia_begin_keywordsm . ':\<\%(elseif\|else\)\>:' . b:julia_end_keywords
+ elseif attr =~# '\<\%(juliaRepeat\|juliaRepKeyword\)\>'
+ return b:julia_begin_keywordsm . ':\<\%(break\|continue\)\>:' . b:julia_end_keywords
+ elseif attr == 'juliaBlKeyword'
+ return b:julia_begin_keywordsm . ':' . b:julia_end_keywords
+ elseif attr == 'juliaException'
+ return b:julia_begin_keywordsm . ':\<\%(catch\|finally\)\>:' . b:julia_end_keywords
+ endif
+ return '\<\>:\<\>'
+ endfunction
+
+ let b:match_words = 'JuliaGetMatchWords()'
+
+ " we need to skip everything within comments, strings and
+ " the 'begin' and 'end' keywords when they are used as a range rather than as
+ " the delimiter of a block
+ let b:match_skip = 'synIDattr(synID(line("."),col("."),0),"name") =~# '
+ \ . '"\\<julia\\%(Comprehension\\%(For\\|If\\)\\|RangeKeyword\\|Comment\\%([LM]\\|Delim\\)\\|\\%([bs]\\|Shell\\|Printf\\|Doc\\)\\?String\\|StringPrefixed\\|DocStringM\\(Raw\\)\\?\\|RegEx\\|SymbolS\\?\\|Dotted\\)\\>"'
+
+ let b:undo_ftplugin = b:undo_ftplugin
+ \ . " | unlet! b:match_words b:match_skip b:match_ignorecase"
+ \ . " | unlet! b:julia_begin_keywords b:julia_end_keywords"
+ \ . " | delfunction JuliaGetMatchWords"
+
+endif
+
+let &cpo = s:save_cpo
+unlet s:save_cpo
diff --git a/runtime/ftplugin/man.vim b/runtime/ftplugin/man.vim
index 5d3e00d033..fce12012b5 100644
--- a/runtime/ftplugin/man.vim
+++ b/runtime/ftplugin/man.vim
@@ -6,14 +6,6 @@ if exists('b:did_ftplugin') || &filetype !=# 'man'
endif
let b:did_ftplugin = 1
-let s:pager = !exists('b:man_sect')
-
-if s:pager
- call man#init_pager()
-endif
-
-setlocal noswapfile buftype=nofile bufhidden=hide
-setlocal nomodified readonly nomodifiable
setlocal noexpandtab tabstop=8 softtabstop=8 shiftwidth=8
setlocal wrap breakindent linebreak
@@ -32,11 +24,7 @@ if !exists('g:no_plugin_maps') && !exists('g:no_man_maps')
nnoremap <silent> <buffer> k gk
nnoremap <silent> <buffer> gO :call man#show_toc()<CR>
nnoremap <silent> <buffer> <2-LeftMouse> :Man<CR>
- if s:pager
- nnoremap <silent> <buffer> <nowait> q :lclose<CR>:q<CR>
- else
- nnoremap <silent> <buffer> <nowait> q :lclose<CR><C-W>c
- endif
+ nnoremap <silent> <buffer> <nowait> q :lclose<CR><C-W>c
endif
if get(g:, 'ft_man_folding_enable', 0)
diff --git a/runtime/indent/julia.vim b/runtime/indent/julia.vim
new file mode 100644
index 0000000000..a90cff49e4
--- /dev/null
+++ b/runtime/indent/julia.vim
@@ -0,0 +1,491 @@
+" Vim indent file
+" Language: Julia
+" Maintainer: Carlo Baldassi <carlobaldassi@gmail.com>
+" Homepage: https://github.com/JuliaEditorSupport/julia-vim
+" Last Change: 2016 jun 16
+" Notes: originally based on Bram Molenaar's indent file for vim
+
+setlocal autoindent
+
+setlocal indentexpr=GetJuliaIndent()
+setlocal indentkeys+==end,=else,=catch,=finally,),],}
+setlocal indentkeys-=0#
+setlocal indentkeys-=:
+setlocal indentkeys-=0{
+setlocal indentkeys-=0}
+setlocal nosmartindent
+
+" Only define the function once.
+if exists("*GetJuliaIndent")
+ finish
+endif
+
+let s:skipPatternsBasic = '\<julia\%(Comment\%([LM]\|Delim\)\)\>'
+let s:skipPatterns = '\<julia\%(Comprehension\%(For\|If\)\|RangeKeyword\|Comment\%([LM]\|Delim\)\|\%([bs]\|Shell\|Printf\|Doc\)\?String\|StringPrefixed\|DocStringM\(Raw\)\?\|RegEx\|SymbolS\?\|Macro\|Dotted\)\>'
+
+function JuliaMatch(lnum, str, regex, st, ...)
+ let s = a:st
+ let e = a:0 > 0 ? a:1 : -1
+ let basic_skip = a:0 > 1 ? a:2 : 'all'
+ let skip = basic_skip ==# 'basic' ? s:skipPatternsBasic : s:skipPatterns
+ while 1
+ let f = match(a:str, '\C' . a:regex, s)
+ if e >= 0 && f >= e
+ return -1
+ endif
+ if f >= 0
+ let attr = synIDattr(synID(a:lnum,f+1,1),"name")
+ let attrT = synIDattr(synID(a:lnum,f+1,0),"name")
+ if attr =~# skip || attrT =~# skip
+ let s = f+1
+ continue
+ endif
+ endif
+ break
+ endwhile
+ return f
+endfunction
+
+function GetJuliaNestingStruct(lnum, ...)
+ " Auxiliary function to inspect the block structure of a line
+ let line = getline(a:lnum)
+ let s = a:0 > 0 ? a:1 : 0
+ let e = a:0 > 1 ? a:2 : -1
+ let blocks_stack = []
+ let num_closed_blocks = 0
+ while 1
+ let fb = JuliaMatch(a:lnum, line, '\<\%(if\|else\%(if\)\?\|while\|for\|try\|catch\|finally\|\%(staged\)\?function\|macro\|begin\|mutable\s\+struct\|\%(mutable\s\+\)\@<!struct\|\%(abstract\|primitive\)\s\+type\|let\|\%(bare\)\?module\|quote\|do\)\>', s, e)
+ let fe = JuliaMatch(a:lnum, line, '\<end\>', s, e)
+
+ if fb < 0 && fe < 0
+ " No blocks found
+ break
+ end
+
+ if fb >= 0 && (fb < fe || fe < 0)
+ " The first occurrence is an opening block keyword
+ " Note: some keywords (elseif,else,catch,finally) are both
+ " closing blocks and opening new ones
+
+ let i = JuliaMatch(a:lnum, line, '\<if\>', s)
+ if i >= 0 && i == fb
+ let s = i+1
+ call add(blocks_stack, 'if')
+ continue
+ endif
+ let i = JuliaMatch(a:lnum, line, '\<elseif\>', s)
+ if i >= 0 && i == fb
+ let s = i+1
+ if len(blocks_stack) > 0 && blocks_stack[-1] == 'if'
+ let blocks_stack[-1] = 'elseif'
+ elseif (len(blocks_stack) > 0 && blocks_stack[-1] != 'elseif') || len(blocks_stack) == 0
+ call add(blocks_stack, 'elseif')
+ let num_closed_blocks += 1
+ endif
+ continue
+ endif
+ let i = JuliaMatch(a:lnum, line, '\<else\>', s)
+ if i >= 0 && i == fb
+ let s = i+1
+ if len(blocks_stack) > 0 && blocks_stack[-1] =~# '\<\%(else\)\=if\>'
+ let blocks_stack[-1] = 'else'
+ else
+ call add(blocks_stack, 'else')
+ let num_closed_blocks += 1
+ endif
+ continue
+ endif
+
+ let i = JuliaMatch(a:lnum, line, '\<try\>', s)
+ if i >= 0 && i == fb
+ let s = i+1
+ call add(blocks_stack, 'try')
+ continue
+ endif
+ let i = JuliaMatch(a:lnum, line, '\<catch\>', s)
+ if i >= 0 && i == fb
+ let s = i+1
+ if len(blocks_stack) > 0 && blocks_stack[-1] == 'try'
+ let blocks_stack[-1] = 'catch'
+ else
+ call add(blocks_stack, 'catch')
+ let num_closed_blocks += 1
+ endif
+ continue
+ endif
+ let i = JuliaMatch(a:lnum, line, '\<finally\>', s)
+ if i >= 0 && i == fb
+ let s = i+1
+ if len(blocks_stack) > 0 && (blocks_stack[-1] == 'try' || blocks_stack[-1] == 'catch')
+ let blocks_stack[-1] = 'finally'
+ else
+ call add(blocks_stack, 'finally')
+ let num_closed_blocks += 1
+ endif
+ continue
+ endif
+
+ let i = JuliaMatch(a:lnum, line, '\<\%(bare\)\?module\>', s)
+ if i >= 0 && i == fb
+ let s = i+1
+ if i == 0
+ call add(blocks_stack, 'col1module')
+ else
+ call add(blocks_stack, 'other')
+ endif
+ continue
+ endif
+
+ let i = JuliaMatch(a:lnum, line, '\<\%(while\|for\|function\|macro\|begin\|\%(mutable\s\+\)\?struct\|\%(abstract\|primitive\)\s\+type\|let\|quote\|do\)\>', s)
+ if i >= 0 && i == fb
+ if match(line, '\C\<\%(mutable\|abstract\|primitive\)', i) != -1
+ let s = i+11
+ else
+ let s = i+1
+ endif
+ call add(blocks_stack, 'other')
+ continue
+ endif
+
+ " Note: it should be impossible to get here
+ break
+
+ else
+ " The first occurrence is an 'end'
+
+ let s = fe+1
+ if len(blocks_stack) == 0
+ let num_closed_blocks += 1
+ else
+ call remove(blocks_stack, -1)
+ endif
+ continue
+
+ endif
+
+ " Note: it should be impossible to get here
+ break
+ endwhile
+ let num_open_blocks = len(blocks_stack) - count(blocks_stack, 'col1module')
+ return [num_open_blocks, num_closed_blocks]
+endfunction
+
+function GetJuliaNestingBrackets(lnum, c)
+ " Auxiliary function to inspect the brackets structure of a line
+ let line = getline(a:lnum)[0 : (a:c - 1)]
+ let s = 0
+ let brackets_stack = []
+ let last_closed_bracket = -1
+ while 1
+ let fb = JuliaMatch(a:lnum, line, '[([{]', s)
+ let fe = JuliaMatch(a:lnum, line, '[])}]', s)
+
+ if fb < 0 && fe < 0
+ " No brackets found
+ break
+ end
+
+ if fb >= 0 && (fb < fe || fe < 0)
+ " The first occurrence is an opening bracket
+
+ let i = JuliaMatch(a:lnum, line, '(', s)
+ if i >= 0 && i == fb
+ let s = i+1
+ call add(brackets_stack, ['par',i])
+ continue
+ endif
+
+ let i = JuliaMatch(a:lnum, line, '\[', s)
+ if i >= 0 && i == fb
+ let s = i+1
+ call add(brackets_stack, ['sqbra',i])
+ continue
+ endif
+
+ let i = JuliaMatch(a:lnum, line, '{', s)
+ if i >= 0 && i == fb
+ let s = i+1
+ call add(brackets_stack, ['curbra',i])
+ continue
+ endif
+
+ " Note: it should be impossible to get here
+ break
+
+ else
+ " The first occurrence is a closing bracket
+
+ let i = JuliaMatch(a:lnum, line, ')', s)
+ if i >= 0 && i == fe
+ let s = i+1
+ if len(brackets_stack) > 0 && brackets_stack[-1][0] == 'par'
+ call remove(brackets_stack, -1)
+ else
+ let last_closed_bracket = i + 1
+ endif
+ continue
+ endif
+
+ let i = JuliaMatch(a:lnum, line, ']', s)
+ if i >= 0 && i == fe
+ let s = i+1
+ if len(brackets_stack) > 0 && brackets_stack[-1][0] == 'sqbra'
+ call remove(brackets_stack, -1)
+ else
+ let last_closed_bracket = i + 1
+ endif
+ continue
+ endif
+
+ let i = JuliaMatch(a:lnum, line, '}', s)
+ if i >= 0 && i == fe
+ let s = i+1
+ if len(brackets_stack) > 0 && brackets_stack[-1][0] == 'curbra'
+ call remove(brackets_stack, -1)
+ else
+ let last_closed_bracket = i + 1
+ endif
+ continue
+ endif
+
+ " Note: it should be impossible to get here
+ break
+
+ endif
+
+ " Note: it should be impossible to get here
+ break
+ endwhile
+ let first_open_bracket = -1
+ let last_open_bracket = -1
+ let infuncargs = 0
+ if len(brackets_stack) > 0
+ let first_open_bracket = brackets_stack[0][1]
+ let last_open_bracket = brackets_stack[-1][1]
+ if brackets_stack[-1][0] == 'par' && IsFunctionArgPar(a:lnum, last_open_bracket+1)
+ let infuncargs = 1
+ endif
+ endif
+ return [first_open_bracket, last_open_bracket, last_closed_bracket, infuncargs]
+endfunction
+
+let s:bracketBlocks = '\<julia\%(\%(\%(Printf\)\?Par\|SqBra\%(Idx\)\?\|CurBra\)Block\|ParBlockInRange\|StringVars\%(Par\|SqBra\|CurBra\)\|Dollar\%(Par\|SqBra\)\|QuotedParBlockS\?\)\>'
+
+function IsInBrackets(lnum, c)
+ let stack = map(synstack(a:lnum, a:c), 'synIDattr(v:val, "name")')
+ call filter(stack, 'v:val =~# s:bracketBlocks')
+ return len(stack) > 0
+endfunction
+
+function IsInDocString(lnum)
+ let stack = map(synstack(a:lnum, 1), 'synIDattr(v:val, "name")')
+ call filter(stack, 'v:val =~# "\\<juliaDocString\\(Delim\\|M\\\(Raw\\)\\?\\)\\?\\>"')
+ return len(stack) > 0
+endfunction
+
+function IsInContinuationImportLine(lnum)
+ let stack = map(synstack(a:lnum, 1), 'synIDattr(v:val, "name")')
+ call filter(stack, 'v:val =~# "\\<juliaImportLine\\>"')
+ if len(stack) == 0
+ return 0
+ endif
+ return JuliaMatch(a:lnum, getline(a:lnum), '\<\%(import\|using\|export\)\>', indent(a:lnum)) == -1
+endfunction
+
+function IsFunctionArgPar(lnum, c)
+ if a:c == 0
+ return 0
+ endif
+ let stack = map(synstack(a:lnum, a:c-1), 'synIDattr(v:val, "name")')
+ return len(stack) >= 2 && stack[-2] ==# 'juliaFunctionDef'
+endfunction
+
+function JumpToMatch(lnum, last_closed_bracket)
+ " we use the % command to skip back (tries to ues matchit if possible,
+ " otherwise resorts to vim's default, which is buggy but better than
+ " nothing)
+ call cursor(a:lnum, a:last_closed_bracket)
+ let percmap = maparg("%", "n")
+ if exists("g:loaded_matchit") && percmap =~# 'Match\%(it\|_wrapper\)'
+ normal %
+ else
+ normal! %
+ end
+endfunction
+
+" Auxiliary function to find a line which does not start in the middle of a
+" multiline bracketed expression, to be used as reference for block
+" indentation.
+function LastBlockIndent(lnum)
+ let lnum = a:lnum
+ let ind = 0
+ while lnum > 0
+ let ind = indent(lnum)
+ if ind == 0
+ return [lnum, 0]
+ endif
+ if !IsInBrackets(lnum, 1)
+ break
+ endif
+ let lnum = prevnonblank(lnum - 1)
+ endwhile
+ return [max([lnum,1]), ind]
+endfunction
+
+function GetJuliaIndent()
+ " Do not alter doctrings indentation
+ if IsInDocString(v:lnum)
+ return -1
+ endif
+
+ " Find a non-blank line above the current line.
+ let lnum = prevnonblank(v:lnum - 1)
+
+ " At the start of the file use zero indent.
+ if lnum == 0
+ return 0
+ endif
+
+ let ind = -1
+ let st = -1
+ let lim = -1
+
+ " Multiline bracketed expressions take precedence
+ let align_brackets = get(g:, "julia_indent_align_brackets", 1)
+ let align_funcargs = get(g:, "julia_indent_align_funcargs", 0)
+ let c = len(getline(lnum)) + 1
+ while IsInBrackets(lnum, c)
+ let [first_open_bracket, last_open_bracket, last_closed_bracket, infuncargs] = GetJuliaNestingBrackets(lnum, c)
+
+ " First scenario: the previous line has a hanging open bracket:
+ " set the indentation to match the opening bracket (plus an extra space)
+ " unless we're in a function arguments list or alignment is disabled, in
+ " which case we just add an extra indent
+ if last_open_bracket != -1
+ if (!infuncargs && align_brackets) || (infuncargs && align_funcargs)
+ let st = last_open_bracket
+ let ind = virtcol([lnum, st + 1])
+ else
+ let ind = indent(lnum) + shiftwidth()
+ endif
+
+ " Second scenario: some multiline bracketed expression was closed in the
+ " previous line. But since we know we are still in a bracketed expression,
+ " we need to find the line where the bracket was opened
+ elseif last_closed_bracket != -1
+ call JumpToMatch(lnum, last_closed_bracket)
+ if line(".") == lnum
+ " something wrong here, give up
+ let ind = indent(lnum)
+ else
+ let lnum = line(".")
+ let c = col(".") - 1
+ if c == 0
+ " uhm, give up
+ let ind = 0
+ else
+ " we skipped a bracket set, keep searching for an opening bracket
+ let lim = c
+ continue
+ endif
+ endif
+
+ " Third scenario: nothing special: keep the indentation
+ else
+ let ind = indent(lnum)
+ endif
+
+ " Does the current line start with a closing bracket? Then depending on
+ " the situation we align it with the opening one, or we let the rest of
+ " the code figure it out (the case in which we're closing a function
+ " argument list is special-cased)
+ if JuliaMatch(v:lnum, getline(v:lnum), '[])}]', indent(v:lnum)) == indent(v:lnum) && ind > 0
+ if !align_brackets && !align_funcargs
+ call JumpToMatch(v:lnum, indent(v:lnum))
+ return indent(line("."))
+ elseif (align_brackets && getline(v:lnum)[indent(v:lnum)] != ')') || align_funcargs
+ return ind - 1
+ else " must be a ')' and align_brackets==1 and align_funcargs==0
+ call JumpToMatch(v:lnum, indent(v:lnum))
+ if IsFunctionArgPar(line("."), col("."))
+ let ind = -1
+ else
+ return ind - 1
+ endif
+ endif
+ endif
+
+ break
+ endwhile
+
+ if ind == -1
+ " We are not in a multiline bracketed expression. Thus we look for a
+ " previous line to use as a reference
+ let [lnum,ind] = LastBlockIndent(lnum)
+ let c = len(getline(lnum)) + 1
+ if IsInBrackets(lnum, c)
+ let [first_open_bracket, last_open_bracket, last_closed_bracket, infuncargs] = GetJuliaNestingBrackets(lnum, c)
+ let lim = first_open_bracket
+ endif
+ end
+
+ " Analyse the reference line
+ let [num_open_blocks, num_closed_blocks] = GetJuliaNestingStruct(lnum, st, lim)
+ " Increase indentation for each newly opened block in the reference line
+ let ind += shiftwidth() * num_open_blocks
+
+ " Analyse the current line
+ let [num_open_blocks, num_closed_blocks] = GetJuliaNestingStruct(v:lnum)
+ " Decrease indentation for each closed block in the current line
+ let ind -= shiftwidth() * num_closed_blocks
+
+ " Additional special case: multiline import/using/export statements
+
+ let prevline = getline(lnum)
+ " Are we in a multiline import/using/export statement, right below the
+ " opening line?
+ if IsInContinuationImportLine(v:lnum) && !IsInContinuationImportLine(lnum)
+ if get(g:, 'julia_indent_align_import', 1)
+ " if the opening line has a colon followed by non-comments, use it as
+ " reference point
+ let cind = JuliaMatch(lnum, prevline, ':', indent(lnum), lim)
+ if cind >= 0
+ let nonwhiteind = JuliaMatch(lnum, prevline, '\S', cind+1, -1, 'basic')
+ if nonwhiteind >= 0
+ " return match(prevline, '\S', cind+1) " a bit overkill...
+ return cind + 2
+ endif
+ else
+ " if the opening line is not a naked import/using/export statement, use
+ " it as reference
+ let iind = JuliaMatch(lnum, prevline, '\<import\|using\|export\>', indent(lnum), lim)
+ if iind >= 0
+ " assuming whitespace after using... so no `using(XYZ)` please!
+ let nonwhiteind = JuliaMatch(lnum, prevline, '\S', iind+6, -1, 'basic')
+ if nonwhiteind >= 0
+ return match(prevline, '\S', iind+6)
+ endif
+ endif
+ endif
+ endif
+ let ind += shiftwidth()
+
+ " Or did we just close a multiline import/using/export statement?
+ elseif !IsInContinuationImportLine(v:lnum) && IsInContinuationImportLine(lnum)
+ " find the starting line of the statement
+ let ilnum = 0
+ for iln in range(lnum-1, 1, -1)
+ if !IsInContinuationImportLine(iln)
+ let ilnum = iln
+ break
+ endif
+ endfor
+ if ilnum == 0
+ " something went horribly wrong, give up
+ let ind = indent(lnum)
+ endif
+ let ind = indent(ilnum)
+ endif
+
+ return ind
+endfunction
diff --git a/runtime/lua/vim/F.lua b/runtime/lua/vim/F.lua
index 7925ff6e44..09467eb8c6 100644
--- a/runtime/lua/vim/F.lua
+++ b/runtime/lua/vim/F.lua
@@ -2,8 +2,8 @@ local F = {}
--- Returns {a} if it is not nil, otherwise returns {b}.
---
---@param a
---@param b
+---@param a
+---@param b
function F.if_nil(a, b)
if a == nil then return b end
return a
diff --git a/runtime/lua/vim/highlight.lua b/runtime/lua/vim/highlight.lua
index 0012dce081..4cb1994419 100644
--- a/runtime/lua/vim/highlight.lua
+++ b/runtime/lua/vim/highlight.lua
@@ -2,7 +2,7 @@ local api = vim.api
local highlight = {}
---@private
+---@private
function highlight.create(higroup, hi_info, default)
local options = {}
-- TODO: Add validation
@@ -12,7 +12,7 @@ function highlight.create(higroup, hi_info, default)
vim.cmd(string.format([[highlight %s %s %s]], default and "default" or "", higroup, table.concat(options, " ")))
end
---@private
+---@private
function highlight.link(higroup, link_to, force)
vim.cmd(string.format([[highlight%s link %s %s]], force and "!" or " default", higroup, link_to))
end
@@ -20,11 +20,11 @@ end
--- Highlight range between two positions
---
---@param bufnr number of buffer to apply highlighting to
---@param ns namespace to add highlight to
---@param higroup highlight group to use for highlighting
---@param rtype type of range (:help setreg, default charwise)
---@param inclusive boolean indicating whether the range is end-inclusive (default false)
+---@param bufnr number of buffer to apply highlighting to
+---@param ns namespace to add highlight to
+---@param higroup highlight group to use for highlighting
+---@param rtype type of range (:help setreg, default charwise)
+---@param inclusive boolean indicating whether the range is end-inclusive (default false)
function highlight.range(bufnr, ns, higroup, start, finish, rtype, inclusive)
rtype = rtype or 'v'
inclusive = inclusive or false
diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua
index 87ecc3eeea..df48c10881 100644
--- a/runtime/lua/vim/lsp.lua
+++ b/runtime/lua/vim/lsp.lua
@@ -55,21 +55,21 @@ lsp._request_name_to_capability = {
-- TODO improve handling of scratch buffers with LSP attached.
---@private
+---@private
--- Concatenates and writes a list of strings to the Vim error buffer.
---
---@param {...} (List of strings) List to write to the buffer
+---@param {...} (List of strings) List to write to the buffer
local function err_message(...)
nvim_err_writeln(table.concat(vim.tbl_flatten{...}))
nvim_command("redraw")
end
---@private
+---@private
--- Returns the buffer number for the given {bufnr}.
---
---@param bufnr (number) Buffer number to resolve. Defaults to the current
+---@param bufnr (number) Buffer number to resolve. Defaults to the current
---buffer if not given.
---@returns bufnr (number) Number of requested buffer
+---@returns bufnr (number) Number of requested buffer
local function resolve_bufnr(bufnr)
validate { bufnr = { bufnr, 'n', true } }
if bufnr == nil or bufnr == 0 then
@@ -78,21 +78,21 @@ local function resolve_bufnr(bufnr)
return bufnr
end
---@private
+---@private
--- Called by the client when trying to call a method that's not
--- supported in any of the servers registered for the current buffer.
---@param method (string) name of the method
+---@param method (string) name of the method
function lsp._unsupported_method(method)
local msg = string.format("method %s is not supported by any of the servers registered for the current buffer", method)
log.warn(msg)
return lsp.rpc_response_error(protocol.ErrorCodes.MethodNotFound, msg)
end
---@private
+---@private
--- Checks whether a given path is a directory.
---
---@param filename (string) path to check
---@returns true if {filename} exists and is a directory, false otherwise
+---@param filename (string) path to check
+---@returns 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)
@@ -108,10 +108,10 @@ local valid_encodings = {
}
local client_index = 0
---@private
+---@private
--- Returns a new, unused client id.
---
---@returns (number) client id
+---@returns (number) client id
local function next_client_id()
client_index = client_index + 1
return client_index
@@ -124,11 +124,11 @@ local uninitialized_clients = {}
-- Tracks all buffers attached to a client.
local all_client_active_buffers = {}
---@private
+---@private
--- Invokes a function for each LSP client attached to the buffer {bufnr}.
---
---@param bufnr (Number) of buffer
---@param fn (function({client}, {client_id}, {bufnr}) Function to run on
+---@param bufnr (Number) of buffer
+---@param fn (function({client}, {client_id}, {bufnr}) Function to run on
---each client attached to that buffer.
local function for_each_buffer_client(bufnr, fn)
validate {
@@ -154,11 +154,11 @@ lsp.client_errors = tbl_extend("error", lsp_rpc.client_errors, vim.tbl_add_rever
ON_INIT_CALLBACK_ERROR = table.maxn(lsp_rpc.client_errors) + 1;
})
---@private
+---@private
--- Normalizes {encoding} to valid LSP encoding names.
---
---@param encoding (string) Encoding to normalize
---@returns (string) normalized encoding name
+---@param encoding (string) Encoding to normalize
+---@returns (string) normalized encoding name
local function validate_encoding(encoding)
validate {
encoding = { encoding, 's' };
@@ -167,13 +167,13 @@ local function validate_encoding(encoding)
or error(string.format("Invalid offset encoding %q. Must be one of: 'utf-8', 'utf-16', 'utf-32'", encoding))
end
---@internal
+---@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 (List)
---@returns (string) the command
---@returns (list of strings) its arguments
+---@param input (List)
+---@returns (string) the command
+---@returns (list of strings) its arguments
function lsp._cmd_parts(input)
vim.validate{cmd={
input,
@@ -192,12 +192,12 @@ function lsp._cmd_parts(input)
return cmd, cmd_args
end
---@private
+---@private
--- Augments a validator function with support for optional (nil) values.
---
---@param fn (function(v)) The original validator function; should return a
+---@param fn (function(v)) The original validator function; should return a
---bool.
---@returns (function(v)) The augmented function. Also returns true if {v} is
+---@returns (function(v)) The augmented function. Also returns true if {v} is
---`nil`.
local function optional_validator(fn)
return function(v)
@@ -205,20 +205,20 @@ local function optional_validator(fn)
end
end
---@private
+---@private
--- Validates a client configuration as given to |vim.lsp.start_client()|.
---
---@param config (table)
---@returns (table) "Cleaned" config, containing only the command, its
+---@param config (table)
+---@returns (table) "Cleaned" config, containing only the command, its
---arguments, and a valid encoding.
---
---@see |vim.lsp.start_client()|
+---@see |vim.lsp.start_client()|
local function validate_client_config(config)
validate {
config = { config, 't' };
}
validate {
- root_dir = { config.root_dir, is_dir, "directory" };
+ root_dir = { config.root_dir, optional_validator(is_dir), "directory" };
handlers = { config.handlers, "t", true };
capabilities = { config.capabilities, "t", true };
cmd_cwd = { config.cmd_cwd, optional_validator(is_dir), "directory" };
@@ -253,11 +253,11 @@ local function validate_client_config(config)
}
end
---@private
+---@private
--- Returns full text of buffer {bufnr} as a string.
---
---@param bufnr (number) Buffer handle, or 0 for current.
---@returns Buffer text as string.
+---@param bufnr (number) Buffer handle, or 0 for current.
+---@returns Buffer text as string.
local function buf_get_full_text(bufnr)
local text = table.concat(nvim_buf_get_lines(bufnr, 0, -1, true), '\n')
if nvim_buf_get_option(bufnr, 'eol') then
@@ -266,14 +266,14 @@ local function buf_get_full_text(bufnr)
return text
end
---@private
+---@private
--- Memoizes a function. On first run, the function return value is saved and
--- immediately returned on subsequent runs. If the function returns a multival,
--- only the first returned value will be memoized and returned. The function will only be run once,
--- even if it has side-effects.
---
---@param fn (function) Function to run
---@returns (function) Memoized function
+---@param fn (function) Function to run
+---@returns (function) Memoized function
local function once(fn)
local value
local ran = false
@@ -289,6 +289,7 @@ end
local changetracking = {}
do
+ --@private
--- client_id → state
---
--- state
@@ -425,11 +426,11 @@ do
end
---@private
+---@private
--- Default handler for the 'textDocument/didOpen' LSP notification.
---
---@param bufnr (Number) Number of the buffer, or 0 for current
---@param client Client object
+---@param bufnr (Number) Number of the buffer, or 0 for current
+---@param client Client object
local function text_document_did_open_handler(bufnr, client)
changetracking.init(client, bufnr)
if not client.resolved_capabilities.text_document_open_close then
@@ -547,16 +548,16 @@ end
---
--- The following parameters describe fields in the {config} table.
---
---@param root_dir: (required, string) Directory where the LSP server will base
+---@param root_dir: (string) Directory where the LSP server will base
--- its rootUri on initialization.
---
---@param cmd: (required, string or list treated like |jobstart()|) Base command
+---@param cmd: (required, string or list treated like |jobstart()|) Base command
--- that initiates the LSP client.
---
---@param cmd_cwd: (string, default=|getcwd()|) Directory to launch
+---@param cmd_cwd: (string, default=|getcwd()|) Directory to launch
--- the `cmd` process. Not related to `root_dir`.
---
---@param cmd_env: (table) Environment flags to pass to the LSP on
+---@param cmd_env: (table) Environment flags to pass to the LSP on
--- spawn. Can be specified using keys like a map or as a list with `k=v`
--- pairs or both. Non-string values are coerced to string.
--- Example:
@@ -564,7 +565,7 @@ end
--- { "PRODUCTION=true"; "TEST=123"; PORT = 8080; HOST = "0.0.0.0"; }
--- </pre>
---
---@param capabilities Map overriding the default capabilities defined by
+---@param 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.
@@ -572,41 +573,41 @@ end
--- `{[vim.type_idx]=vim.types.dictionary}`, else it will be encoded as an
--- array.
---
---@param handlers Map of language server method names to |lsp-handler|
+---@param handlers Map of language server method names to |lsp-handler|
---
---@param settings Map with language server specific settings. These are
+---@param settings Map with language server specific settings. These are
--- returned to the language server if requested via `workspace/configuration`.
--- Keys are case-sensitive.
---
---@param init_options Values to pass in the initialization request
+---@param init_options Values to pass in the initialization request
--- as `initializationOptions`. See `initialize` in the LSP spec.
---
---@param name (string, default=client-id) Name in log messages.
+---@param name (string, default=client-id) Name in log messages.
--
---@param workspace_folders (table) List of workspace folders passed to the
+---@param workspace_folders (table) List of workspace folders passed to the
--- language server. Defaults to root_dir if not set. See `workspaceFolders` in
--- the LSP spec
---
---@param get_language_id function(bufnr, filetype) -> language ID as string.
+---@param get_language_id function(bufnr, filetype) -> language ID as string.
--- Defaults to the filetype.
---
---@param offset_encoding (default="utf-16") One of "utf-8", "utf-16",
+---@param 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.
---
---@param on_error Callback with parameters (code, ...), invoked
+---@param 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.client_errors| for possible errors.
--- Use `vim.lsp.client_errors[code]` to get human-friendly name.
---
---@param before_init Callback with parameters (initialize_params, config)
+---@param 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.
---
---@param on_init Callback (client, initialize_result) invoked after LSP
+---@param 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
@@ -616,24 +617,24 @@ end
--- `workspace/didChangeConfiguration` notification should be sent
--- to the server during on_init.
---
---@param on_exit Callback (code, signal, client_id) invoked on client
+---@param 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
---
---@param on_attach Callback (client, bufnr) invoked when client
+---@param on_attach Callback (client, bufnr) invoked when client
--- attaches to a buffer.
---
---@param trace: "off" | "messages" | "verbose" | nil passed directly to the language
+---@param trace: "off" | "messages" | "verbose" | nil passed directly to the language
--- server in the initialize request. Invalid/empty values will default to "off"
---@param flags: A table with flags for the client. The current (experimental) flags are:
+---@param 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 nil): Debounce didChange
--- notifications to the server by the given number in milliseconds. No debounce
--- occurs if nil
---
---@returns Client id. |vim.lsp.get_client_by_id()| Note: client may not be
+---@returns 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)
@@ -656,22 +657,22 @@ function lsp.start_client(config)
local dispatch = {}
- --@private
+ ---@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
- --@returns (fn) The handler for the given method, if defined, or the default from |vim.lsp.handlers|
+ ---@param method (string) LSP method name
+ ---@returns (fn) 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
+ ---@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.
+ ---@param method (string) LSP method name
+ ---@param params (table) The parameters for that method.
function dispatch.notification(method, params)
local _ = log.debug() and log.debug('notification', method, params)
local handler = resolve_handler(method)
@@ -681,11 +682,11 @@ function lsp.start_client(config)
end
end
- --@private
+ ---@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
+ ---@param method (string) LSP method name
+ ---@param params (table) The parameters for that method
function dispatch.server_request(method, params)
local _ = log.debug() and log.debug('server_request', method, params)
local handler = resolve_handler(method)
@@ -697,12 +698,12 @@ function lsp.start_client(config)
return nil, lsp.rpc_response_error(protocol.ErrorCodes.MethodNotFound)
end
- --@private
+ ---@private
--- Invoked when the client operation throws an error.
---
- --@param code (number) Error code
- --@param err (...) Other arguments may be passed depending on the error kind
- --@see |vim.lsp.client_errors| for possible errors. Use
+ ---@param code (number) Error code
+ ---@param err (...) Other arguments may be passed depending on the error kind
+ ---@see |vim.lsp.client_errors| for possible errors. Use
---`vim.lsp.client_errors[code]` to get a human-friendly name.
function dispatch.on_error(code, err)
local _ = log.error() and log.error(log_prefix, "on_error", { code = lsp.client_errors[code], err = err })
@@ -716,11 +717,11 @@ function lsp.start_client(config)
end
end
- --@private
+ ---@private
--- Invoked on client exit.
---
- --@param code (number) exit code of the process
- --@param signal (number) the signal used to terminate (if any)
+ ---@param code (number) exit code of the process
+ ---@param signal (number) the signal used to terminate (if any)
function dispatch.on_exit(code, signal)
active_clients[client_id] = nil
uninitialized_clients[client_id] = nil
@@ -765,14 +766,14 @@ function lsp.start_client(config)
-- Store the uninitialized_clients for cleanup in case we exit before initialize finishes.
uninitialized_clients[client_id] = client;
- --@private
+ ---@private
local function initialize()
local valid_traces = {
off = 'off'; messages = 'messages'; verbose = 'verbose';
}
local version = vim.version()
- if not config.workspace_folders then
+ if config.root_dir and not config.workspace_folders then
config.workspace_folders = {{
uri = vim.uri_from_fname(config.root_dir);
name = string.format("%s", config.root_dir);
@@ -797,7 +798,7 @@ function lsp.start_client(config)
rootPath = config.root_dir;
-- The rootUri of the workspace. Is null if no folder is open. If both
-- `rootPath` and `rootUri` are set `rootUri` wins.
- rootUri = vim.uri_from_fname(config.root_dir);
+ rootUri = config.root_dir and vim.uri_from_fname(config.root_dir);
-- User provided initialization options.
initializationOptions = config.init_options;
-- The capabilities provided by the client (editor or tool)
@@ -868,23 +869,23 @@ function lsp.start_client(config)
end)
end
- --@private
+ ---@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) LSP request params.
- --@param handler (function, optional) Response |lsp-handler| for this method.
- --@param bufnr (number) Buffer handle (0 for current).
- --@returns ({status}, [request_id]): {status} is a bool indicating
+ ---@param method (string) LSP method name.
+ ---@param params (table) LSP request params.
+ ---@param handler (function, optional) Response |lsp-handler| for this method.
+ ---@param bufnr (number) Buffer handle (0 for current).
+ ---@returns ({status}, [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()|
+ ---@see |vim.lsp.buf_request()|
function client.request(method, params, handler, bufnr)
if not handler then
handler = resolve_handler(method)
@@ -899,21 +900,21 @@ function lsp.start_client(config)
end)
end
- --@private
+ ---@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 (number, optional, default=1000) Maximum time in
+ ---@param method (string) LSP method name.
+ ---@param params (table) LSP request params.
+ ---@param timeout_ms (number, optional, default=1000) Maximum time in
---milliseconds to wait for a result.
- --@param bufnr (number) Buffer handle (0 for current).
- --@returns { err=err, result=result }, a dictionary, where `err` and `result` come from the |lsp-handler|.
+ ---@param bufnr (number) Buffer handle (0 for current).
+ ---@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`.
- --@see |vim.lsp.buf_request_sync()|
+ ---@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)
@@ -935,25 +936,25 @@ function lsp.start_client(config)
return request_result
end
- --@private
+ ---@private
--- Sends a notification to an LSP server.
---
- --@param method (string) LSP method name.
- --@param params (optional, table) LSP request params.
- --@param bufnr (number) Buffer handle, or 0 for current.
- --@returns {status} (bool) true if the notification was successful.
+ ---@param method (string) LSP method name.
+ ---@param params (optional, table) LSP request params.
+ ---@param bufnr (number) Buffer handle, or 0 for current.
+ ---@returns {status} (bool) true if the notification was successful.
---If it is false, then it will always be false
---(the client has shutdown).
function client.notify(...)
return rpc.notify(...)
end
- --@private
+ ---@private
--- Cancels a request with a given request id.
---
- --@param id (number) id of request to cancel
- --@returns true if any client returns true; false otherwise
- --@see |vim.lsp.client.notify()|
+ ---@param id (number) id of request to cancel
+ ---@returns true if any client returns true; false otherwise
+ ---@see |vim.lsp.client.notify()|
function client.cancel_request(id)
validate{id = {id, 'n'}}
return rpc.notify("$/cancelRequest", { id = id })
@@ -962,14 +963,14 @@ function lsp.start_client(config)
-- Track this so that we can escalate automatically if we've alredy tried a
-- graceful shutdown
local graceful_shutdown_failed = false
- --@private
+ ---@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 (bool, optional)
+ ---@param force (bool, optional)
function client.stop(force)
lsp.diagnostic.reset(client_id, all_buffer_active_clients)
@@ -999,18 +1000,18 @@ function lsp.start_client(config)
end)
end
- --@private
+ ---@private
--- Checks whether a client is stopped.
---
- --@returns (bool) true if client is stopped or in the process of being
+ ---@returns (bool) true if client is stopped or in the process of being
---stopped; false otherwise
function client.is_stopped()
return rpc.handle:is_closing()
end
- --@private
+ ---@private
--- Runs the on_attach function from the client's config if it was defined.
- --@param bufnr (number) Buffer number
+ ---@param bufnr (number) Buffer number
function client._on_attach(bufnr)
text_document_did_open_handler(bufnr, client)
if config.on_attach then
@@ -1024,8 +1025,8 @@ function lsp.start_client(config)
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)
+---@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
@@ -1075,8 +1076,8 @@ end
---
--- Without calling this, the server won't be notified of changes to a buffer.
---
---- @param bufnr (number) Buffer handle, or 0 for current
---- @param client_id (number) Client id
+---@param bufnr (number) Buffer handle, or 0 for current
+---@param client_id (number) Client id
function lsp.buf_attach_client(bufnr, client_id)
validate {
bufnr = {bufnr, 'n', true};
@@ -1157,17 +1158,17 @@ end
--- Gets a client by id, or nil if the id is invalid.
--- The returned client may not yet be fully initialized.
--
---@param client_id client id number
+---@param client_id client id number
---
---@returns |vim.lsp.client| object, or nil
+---@returns |vim.lsp.client| object, or nil
function lsp.get_client_by_id(client_id)
return active_clients[client_id] or uninitialized_clients[client_id]
end
--- Returns list of buffers attached to client_id.
--
---@param client_id client id
---@returns list of buffer ids
+---@param client_id client id
+---@returns list of buffer ids
function lsp.get_buffers_by_client_id(client_id)
local active_client_buffers = all_client_active_buffers[client_id]
if active_client_buffers then
@@ -1189,8 +1190,8 @@ end
--- By default asks the server to shutdown, unless stop was requested
--- already for this client, then force-shutdown is attempted.
---
---@param client_id client id or |vim.lsp.client| object, or list thereof
---@param force boolean (optional) shutdown forcefully
+---@param client_id client id or |vim.lsp.client| object, or list thereof
+---@param force boolean (optional) shutdown forcefully
function lsp.stop_client(client_id, force)
local ids = type(client_id) == 'table' and client_id or {client_id}
for _, id in ipairs(ids) do
@@ -1206,7 +1207,7 @@ end
--- Gets all active clients.
---
---@returns Table of |vim.lsp.client| objects
+---@returns Table of |vim.lsp.client| objects
function lsp.get_active_clients()
return vim.tbl_values(active_clients)
end
@@ -1237,13 +1238,13 @@ nvim_command("autocmd VimLeavePre * lua vim.lsp._vim_exit_handler()")
--- Sends an async request for all active clients attached to the
--- buffer.
---
---@param bufnr (number) Buffer handle, or 0 for current.
---@param method (string) LSP method name
---@param params (optional, table) Parameters to send to the server
---@param handler (optional, function) See |lsp-handler|
+---@param bufnr (number) Buffer handle, or 0 for current.
+---@param method (string) LSP method name
+---@param params (optional, table) Parameters to send to the server
+---@param handler (optional, function) See |lsp-handler|
-- If nil, follows resolution strategy defined in |lsp-handler-configuration|
--
---@returns 2-tuple:
+---@returns 2-tuple:
--- - Map of client-id:request-id pairs for all successful requests.
--- - Function which can be used to cancel all the requests. You could instead
--- iterate all clients and call their `cancel_request()` methods.
@@ -1295,14 +1296,14 @@ end
---Parameters are the same as |vim.lsp.buf_request()| but the return result and callback are
---different.
---
---@param bufnr (number) Buffer handle, or 0 for current.
---@param method (string) LSP method name
---@param params (optional, table) Parameters to send to the server
---@param callback (function) The callback to call when all requests are finished.
+---@param bufnr (number) Buffer handle, or 0 for current.
+---@param method (string) LSP method name
+---@param params (optional, table) Parameters to send to the server
+---@param callback (function) The callback to call when all requests are finished.
-- Unlike `buf_request`, this will collect all the responses from each server instead of handling them.
-- A map of client_id:request_result will be provided to the callback
--
---@returns (function) A function that will cancel all requests which is the same as the one returned from `buf_request`.
+---@returns (function) A function that will cancel all requests which is the same as the one returned from `buf_request`.
function lsp.buf_request_all(bufnr, method, params, callback)
local request_results = {}
local result_count = 0
@@ -1336,13 +1337,13 @@ end
--- Parameters are the same as |vim.lsp.buf_request()| but the return result is
--- different. Wait maximum of {timeout_ms} (default 1000) ms.
---
---@param bufnr (number) Buffer handle, or 0 for current.
---@param method (string) LSP method name
---@param params (optional, table) Parameters to send to the server
---@param timeout_ms (optional, number, default=1000) Maximum time in
+---@param bufnr (number) Buffer handle, or 0 for current.
+---@param method (string) LSP method name
+---@param params (optional, table) Parameters to send to the server
+---@param timeout_ms (optional, number, default=1000) Maximum time in
--- milliseconds to wait for a result.
---
---@returns Map of client_id:request_result. On timeout, cancel or error,
+---@returns Map of client_id:request_result. On timeout, cancel or error,
--- returns `(nil, err)` where `err` is a string describing the failure
--- reason.
function lsp.buf_request_sync(bufnr, method, params, timeout_ms)
@@ -1365,11 +1366,11 @@ function lsp.buf_request_sync(bufnr, method, params, timeout_ms)
end
--- Send a notification to a server
---@param bufnr [number] (optional): The number of the buffer
---@param method [string]: Name of the request method
---@param params [string]: Arguments to send to the server
+---@param bufnr [number] (optional): The number of the buffer
+---@param method [string]: Name of the request method
+---@param params [string]: Arguments to send to the server
---
---@returns true if any client returns true; false otherwise
+---@returns true if any client returns true; false otherwise
function lsp.buf_notify(bufnr, method, params)
validate {
bufnr = { bufnr, 'n', true };
@@ -1384,14 +1385,14 @@ end
--- Implements 'omnifunc' compatible LSP completion.
---
---@see |complete-functions|
---@see |complete-items|
---@see |CompleteDone|
+---@see |complete-functions|
+---@see |complete-items|
+---@see |CompleteDone|
---
---@param findstart 0 or 1, decides behavior
---@param base If findstart=0, text to match against
+---@param findstart 0 or 1, decides behavior
+---@param base If findstart=0, text to match against
---
---@returns (number) Decided by `findstart`:
+---@returns (number) Decided by `findstart`:
--- - 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)
@@ -1437,8 +1438,8 @@ end
---Checks whether a client is stopped.
---
---@param client_id (Number)
---@returns true if client is stopped, false otherwise.
+---@param client_id (Number)
+---@returns true if client is stopped, false otherwise.
function lsp.client_is_stopped(client_id)
return active_clients[client_id] == nil
end
@@ -1446,7 +1447,7 @@ end
--- Gets a map of client_id:client pairs for the given buffer, where each value
--- is a |vim.lsp.client| object.
---
---@param bufnr (optional, number): Buffer handle, or 0 for current
+---@param bufnr (optional, number): Buffer handle, or 0 for current
function lsp.buf_get_clients(bufnr)
bufnr = resolve_bufnr(bufnr)
local result = {}
@@ -1471,9 +1472,9 @@ lsp.log_levels = log.levels
---
--- Use `lsp.log_levels` for reverse lookup.
---
---@see |vim.lsp.log_levels|
+---@see |vim.lsp.log_levels|
---
---@param level [number|string] the case insensitive level name or number
+---@param level [number|string] the case insensitive level name or number
function lsp.set_log_level(level)
if type(level) == 'string' or type(level) == 'number' then
log.set_level(level)
@@ -1483,7 +1484,7 @@ function lsp.set_log_level(level)
end
--- Gets the path of the logfile used by the LSP client.
---@returns (String) Path to logfile.
+---@returns (String) Path to logfile.
function lsp.get_log_path()
return log.get_filename()
end
@@ -1494,8 +1495,8 @@ function lsp.for_each_buffer_client(bufnr, fn)
end
--- Function to manage overriding defaults for LSP handlers.
---@param handler (function) See |lsp-handler|
---@param override_config (table) Table containing the keys to override behavior of the {handler}
+---@param handler (function) 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, method, params, client_id, bufnr, config)
return handler(err, method, params, client_id, bufnr, vim.tbl_deep_extend("force", config or {}, override_config))
diff --git a/runtime/lua/vim/lsp/buf.lua b/runtime/lua/vim/lsp/buf.lua
index 29f8d6c3bc..250af0a0a7 100644
--- a/runtime/lua/vim/lsp/buf.lua
+++ b/runtime/lua/vim/lsp/buf.lua
@@ -5,7 +5,7 @@ local util = require 'vim.lsp.util'
local M = {}
---@private
+---@private
--- Returns nil if {status} is false or nil, otherwise returns the rest of the
--- arguments.
local function ok_or_nil(status, ...)
@@ -13,31 +13,31 @@ local function ok_or_nil(status, ...)
return ...
end
---@private
+---@private
--- Swallows errors.
---
---@param fn Function to run
---@param ... Function arguments
---@returns Result of `fn(...)` if there are no errors, otherwise nil.
+---@param fn Function to run
+---@param ... Function arguments
+---@returns Result of `fn(...)` if there are no errors, otherwise nil.
--- Returns nil if errors occur during {fn}, otherwise returns
local function npcall(fn, ...)
return ok_or_nil(pcall(fn, ...))
end
---@private
+---@private
--- Sends an async request to all active clients attached to the current
--- buffer.
---
---@param method (string) LSP method name
---@param params (optional, table) Parameters to send to the server
---@param handler (optional, functionnil) See |lsp-handler|. Follows |lsp-handler-resolution|
+---@param method (string) LSP method name
+---@param params (optional, table) Parameters to send to the server
+---@param handler (optional, functionnil) See |lsp-handler|. Follows |lsp-handler-resolution|
--
---@returns 2-tuple:
+---@returns 2-tuple:
--- - Map of client-id:request-id pairs for all successful requests.
--- - Function which can be used to cancel all the requests. You could instead
--- iterate all clients and call their `cancel_request()` methods.
---
---@see |vim.lsp.buf_request()|
+---@see |vim.lsp.buf_request()|
local function request(method, params, handler)
validate {
method = {method, 's'};
@@ -49,7 +49,7 @@ end
--- Checks whether the language servers attached to the current buffer are
--- ready.
---
---@returns `true` if server responds.
+---@returns `true` if server responds.
function M.server_ready()
return not not vim.lsp.buf_notify(0, "window/progress", {})
end
@@ -62,7 +62,7 @@ function M.hover()
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.
+---@note Many servers do not implement this method. Generally, see |vim.lsp.buf.definition()| instead.
---
function M.declaration()
local params = util.make_position_params()
@@ -100,22 +100,22 @@ end
--- Retrieves the completion items at the current cursor position. Can only be
--- called in Insert mode.
---
---@param context (context support not yet implemented) Additional information
+---@param context (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)
---
---@see |vim.lsp.protocol.constants.CompletionTriggerKind|
+---@see |vim.lsp.protocol.constants.CompletionTriggerKind|
function M.completion(context)
local params = util.make_position_params()
params.context = context
return request('textDocument/completion', params)
end
---@private
+---@private
--- If there is more than one client that supports the given method,
--- asks the user to select one.
--
---@returns The client that the user selected or nil
+---@returns The client that the user selected or nil
local function select_client(method)
local clients = vim.tbl_values(vim.lsp.buf_get_clients());
clients = vim.tbl_filter(function (client)
@@ -146,11 +146,11 @@ end
--- Formats the current buffer.
---
---@param options (optional, table) Can be used to specify FormattingOptions.
+---@param options (optional, table) Can be used to specify FormattingOptions.
--- Some unspecified options will be automatically derived from the current
--- Neovim options.
--
---@see https://microsoft.github.io/language-server-protocol/specification#textDocument_formatting
+---@see https://microsoft.github.io/language-server-protocol/specification#textDocument_formatting
function M.formatting(options)
local client = select_client("textDocument/formatting")
if client == nil then return end
@@ -168,9 +168,9 @@ end
--- vim.api.nvim_command[[autocmd BufWritePre <buffer> lua vim.lsp.buf.formatting_sync()]]
--- </pre>
---
---@param options Table with valid `FormattingOptions` entries
---@param timeout_ms (number) Request timeout
---@see |vim.lsp.buf.formatting_seq_sync|
+---@param options Table with valid `FormattingOptions` entries
+---@param timeout_ms (number) Request timeout
+---@see |vim.lsp.buf.formatting_seq_sync|
function M.formatting_sync(options, timeout_ms)
local client = select_client("textDocument/formatting")
if client == nil then return end
@@ -195,9 +195,9 @@ end
--- vim.api.nvim_command[[autocmd BufWritePre <buffer> lua vim.lsp.buf.formatting_seq_sync()]]
--- </pre>
---
---@param options (optional, table) `FormattingOptions` entries
---@param timeout_ms (optional, number) Request timeout
---@param order (optional, table) List of client names. Formatting is requested from clients
+---@param options (optional, table) `FormattingOptions` entries
+---@param timeout_ms (optional, number) Request timeout
+---@param order (optional, table) List of client names. Formatting is requested from clients
---in the following order: first all clients that are not in the `order` list, then
---the remaining clients in the order as they occur in the `order` list.
function M.formatting_seq_sync(options, timeout_ms, order)
@@ -230,10 +230,10 @@ end
--- Formats a given range.
---
---@param options Table with valid `FormattingOptions` entries.
---@param start_pos ({number, number}, optional) mark-indexed position.
+---@param options Table with valid `FormattingOptions` entries.
+---@param start_pos ({number, number}, optional) mark-indexed position.
---Defaults to the start of the last visual selection.
---@param end_pos ({number, number}, optional) mark-indexed position.
+---@param end_pos ({number, number}, optional) mark-indexed position.
---Defaults to the end of the last visual selection.
function M.range_formatting(options, start_pos, end_pos)
local client = select_client("textDocument/rangeFormatting")
@@ -246,7 +246,7 @@ end
--- Renames all references to the symbol under the cursor.
---
---@param new_name (string) If not provided, the user will be prompted for a new
+---@param new_name (string) If not provided, the user will be prompted for a new
---name using |input()|.
function M.rename(new_name)
-- TODO(ashkan) use prepareRename
@@ -260,8 +260,8 @@ end
--- Lists all the references to the symbol under the cursor in the quickfix window.
---
---@param context (table) Context for the request
---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_references
+---@param context (table) Context for the request
+---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_references
function M.references(context)
validate { context = { context, 't', true } }
local params = util.make_position_params()
@@ -279,7 +279,7 @@ function M.document_symbol()
request('textDocument/documentSymbol', params)
end
---@private
+---@private
local function pick_call_hierarchy_item(call_hierarchy_items)
if not call_hierarchy_items then return end
if #call_hierarchy_items == 1 then
@@ -297,7 +297,7 @@ local function pick_call_hierarchy_item(call_hierarchy_items)
return choice
end
---@private
+---@private
local function call_hierarchy(method)
local params = util.make_position_params()
request('textDocument/prepareCallHierarchy', params, function(err, _, result)
@@ -389,7 +389,7 @@ 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, optional)
+---@param query (string, optional)
function M.workspace_symbol(query)
query = query or npcall(vfn.input, "Query: ")
local params = {query = query}
@@ -424,7 +424,7 @@ end
--- Requests code actions from all clients and calls the handler exactly once
--- with all aggregated results
---@private
+---@private
local function code_action_request(params)
local bufnr = vim.api.nvim_get_current_buf()
local method = 'textDocument/codeAction'
@@ -439,9 +439,9 @@ end
--- Selects a code action from the input list that is available at the current
--- cursor position.
---
---@param context: (table, optional) Valid `CodeActionContext` object
---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_codeAction
+---
+---@param context: (table, optional) Valid `CodeActionContext` object
+---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_codeAction
function M.code_action(context)
validate { context = { context, 't', true } }
context = context or { diagnostics = vim.lsp.diagnostic.get_line_diagnostics() }
@@ -452,10 +452,10 @@ end
--- Performs |vim.lsp.buf.code_action()| for a given range.
---
---@param context: (table, optional) Valid `CodeActionContext` object
---@param start_pos ({number, number}, optional) mark-indexed position.
+---@param context: (table, optional) Valid `CodeActionContext` object
+---@param start_pos ({number, number}, optional) mark-indexed position.
---Defaults to the start of the last visual selection.
---@param end_pos ({number, number}, optional) mark-indexed position.
+---@param end_pos ({number, number}, optional) mark-indexed position.
---Defaults to the end of the last visual selection.
function M.range_code_action(context, start_pos, end_pos)
validate { context = { context, 't', true } }
@@ -467,8 +467,8 @@ end
--- Executes an LSP server command.
---
---@param command A valid `ExecuteCommandParams` object
---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_executeCommand
+---@param command A valid `ExecuteCommandParams` object
+---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_executeCommand
function M.execute_command(command)
validate {
command = { command.command, 's' },
diff --git a/runtime/lua/vim/lsp/codelens.lua b/runtime/lua/vim/lsp/codelens.lua
index fe581e42ad..ca5a44077e 100644
--- a/runtime/lua/vim/lsp/codelens.lua
+++ b/runtime/lua/vim/lsp/codelens.lua
@@ -22,11 +22,11 @@ local namespaces = setmetatable({}, {
end;
})
---@private
+---@private
M.__namespaces = namespaces
---@private
+---@private
local function execute_lens(lens, bufnr, client_id)
local line = lens.range.start.line
api.nvim_buf_clear_namespace(bufnr, namespaces[client_id], line, line + 1)
@@ -151,7 +151,7 @@ function M.save(lenses, bufnr, client_id)
end
---@private
+---@private
local function resolve_lenses(lenses, bufnr, client_id, callback)
lenses = lenses or {}
local num_lens = vim.tbl_count(lenses)
@@ -160,7 +160,7 @@ local function resolve_lenses(lenses, bufnr, client_id, callback)
return
end
- --@private
+ ---@private
local function countdown()
num_lens = num_lens - 1
if num_lens == 0 then
diff --git a/runtime/lua/vim/lsp/diagnostic.lua b/runtime/lua/vim/lsp/diagnostic.lua
index 5efd8d74a7..45aeb17465 100644
--- a/runtime/lua/vim/lsp/diagnostic.lua
+++ b/runtime/lua/vim/lsp/diagnostic.lua
@@ -8,7 +8,7 @@ local util = require('vim.lsp.util')
local if_nil = vim.F.if_nil
---@class DiagnosticSeverity
+---@class DiagnosticSeverity
local DiagnosticSeverity = protocol.DiagnosticSeverity
local to_severity = function(severity)
@@ -46,14 +46,14 @@ end
---@brief lsp-diagnostic
---
---@class Diagnostic
---@field range Range
---@field message string
---@field severity DiagnosticSeverity|nil
---@field code number | string
---@field source string
---@field tags DiagnosticTag[]
---@field relatedInformation DiagnosticRelatedInformation[]
+---@class Diagnostic
+---@field range Range
+---@field message string
+---@field severity DiagnosticSeverity|nil
+---@field code number | string
+---@field source string
+---@field tags DiagnosticTag[]
+---@field relatedInformation DiagnosticRelatedInformation[]
local M = {}
@@ -167,12 +167,12 @@ end
local _diagnostic_namespaces = _make_namespace_table("vim_lsp_diagnostics", true)
local _sign_namespaces = _make_namespace_table("vim_lsp_signs", false)
---@private
+---@private
function M._get_diagnostic_namespace(client_id)
return _diagnostic_namespaces[client_id]
end
---@private
+---@private
function M._get_sign_namespace(client_id)
return _sign_namespaces[client_id]
end
@@ -255,7 +255,7 @@ local _diagnostic_counts = function(diagnostics)
return counts
end
---@private
+---@private
--- Set the different diagnostic cache after `textDocument/publishDiagnostics`
---@param diagnostics Diagnostic[]
---@param bufnr number
@@ -291,7 +291,7 @@ local function set_diagnostic_cache(diagnostics, bufnr, client_id)
end
---@private
+---@private
--- Clear the cached diagnostics
---@param bufnr number
---@param client_id number
@@ -362,11 +362,12 @@ end
---@param bufnr number
---@param client_id number|nil If nil, then return all of the diagnostics.
--- Else, return just the diagnostics associated with the client_id.
-function M.get(bufnr, client_id)
+---@param predicate function|nil Optional function for filtering diagnostics
+function M.get(bufnr, client_id, predicate)
if client_id == nil then
local all_diagnostics = {}
for iter_client_id, _ in pairs(diagnostic_cache[bufnr]) do
- local iter_diagnostics = M.get(bufnr, iter_client_id)
+ local iter_diagnostics = M.get(bufnr, iter_client_id, predicate)
for _, diagnostic in ipairs(iter_diagnostics) do
table.insert(all_diagnostics, diagnostic)
@@ -376,19 +377,26 @@ function M.get(bufnr, client_id)
return all_diagnostics
end
- return diagnostic_cache[bufnr][client_id] or {}
+ predicate = predicate or function(_) return true end
+ local client_diagnostics = {}
+ for _, diagnostic in ipairs(diagnostic_cache[bufnr][client_id] or {}) do
+ if predicate(diagnostic) then
+ table.insert(client_diagnostics, diagnostic)
+ end
+ end
+ return client_diagnostics
end
--- Get the diagnostics by line
---
----@param bufnr number The buffer number
----@param line_nr number The line number
+---@param bufnr number|nil The buffer number
+---@param line_nr number|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 client_id number the client id
+---@param client_id|nil number the client id
---@return table Table with map of line number to list of diagnostics.
-- Structured: { [1] = {...}, [5] = {.... } }
function M.get_line_diagnostics(bufnr, line_nr, opts, client_id)
@@ -464,63 +472,64 @@ end
-- }}}
-- Diagnostic Movements {{{
---- Helper function to iterate through all of the diagnostic lines
----@return table list of diagnostics
-local _iter_diagnostic_lines = function(start, finish, step, bufnr, opts, client_id)
- if bufnr == nil then
- bufnr = vim.api.nvim_get_current_buf()
- end
-
+--- Helper function to find the next diagnostic relative to a position
+---@return table the next diagnostic if found
+local _next_diagnostic = function(position, search_forward, bufnr, opts, client_id)
+ position[1] = position[1] - 1
+ bufnr = bufnr or vim.api.nvim_get_current_buf()
local wrap = if_nil(opts.wrap, true)
-
- local search = function(search_start, search_finish, search_step)
- for line_nr = search_start, search_finish, search_step do
- local line_diagnostics = M.get_line_diagnostics(bufnr, line_nr, opts, client_id)
- if line_diagnostics and not vim.tbl_isempty(line_diagnostics) then
- return line_diagnostics
+ local line_count = vim.api.nvim_buf_line_count(bufnr)
+ for i = 0, line_count do
+ local offset = i * (search_forward and 1 or -1)
+ local line_nr = position[1] + offset
+ if line_nr < 0 or line_nr >= line_count then
+ if not wrap then
+ return
end
+ line_nr = (line_nr + line_count) % line_count
end
- end
-
- local result = search(start, finish, step)
-
- if wrap then
- local wrap_start, wrap_finish
- if step == 1 then
- wrap_start, wrap_finish = 1, start
- else
- wrap_start, wrap_finish = vim.api.nvim_buf_line_count(bufnr), start
- end
-
- if not result then
- result = search(wrap_start, wrap_finish, step)
+ local line_diagnostics = M.get_line_diagnostics(bufnr, line_nr, opts, client_id)
+ if line_diagnostics and not vim.tbl_isempty(line_diagnostics) then
+ local sort_diagnostics, is_next
+ if search_forward then
+ sort_diagnostics = function(a, b) return a.range.start.character < b.range.start.character end
+ is_next = function(diagnostic) return diagnostic.range.start.character > position[2] end
+ else
+ sort_diagnostics = function(a, b) return a.range.start.character > b.range.start.character end
+ is_next = function(diagnostic) return diagnostic.range.start.character < position[2] end
+ end
+ table.sort(line_diagnostics, sort_diagnostics)
+ if i == 0 then
+ for _, v in pairs(line_diagnostics) do
+ if is_next(v) then
+ return v
+ end
+ end
+ else
+ return line_diagnostics[1]
+ end
end
end
-
- return result
end
---@private
---- Helper function to ierate through diagnostic lines and return a position
+---@private
+--- Helper function to return a position from a diagnostic
---
---@return table {row, col}
-local function _iter_diagnostic_lines_pos(opts, line_diagnostics)
+local function _diagnostic_pos(opts, diagnostic)
opts = opts or {}
local win_id = opts.win_id or vim.api.nvim_get_current_win()
local bufnr = vim.api.nvim_win_get_buf(win_id)
- if line_diagnostics == nil or vim.tbl_isempty(line_diagnostics) then
- return false
- end
+ if not diagnostic then return false end
- local iter_diagnostic = line_diagnostics[1]
- return to_position(iter_diagnostic.range.start, bufnr)
+ return to_position(diagnostic.range.start, bufnr)
end
---@private
+---@private
-- Move to the diagnostic position
-local function _iter_diagnostic_move_pos(name, opts, pos)
+local function _diagnostic_move_pos(name, opts, pos)
opts = opts or {}
local enable_popup = if_nil(opts.enable_popup, true)
@@ -536,7 +545,7 @@ local function _iter_diagnostic_move_pos(name, opts, pos)
if enable_popup then
-- This is a bit weird... I'm surprised that we need to wait til the next tick to do this.
vim.schedule(function()
- M.show_line_diagnostics(opts.popup_opts, vim.api.nvim_win_get_buf(win_id))
+ M.show_position_diagnostics(opts.popup_opts, vim.api.nvim_win_get_buf(win_id))
end)
end
end
@@ -552,14 +561,14 @@ function M.get_prev(opts)
local bufnr = vim.api.nvim_win_get_buf(win_id)
local cursor_position = opts.cursor_position or vim.api.nvim_win_get_cursor(win_id)
- return _iter_diagnostic_lines(cursor_position[1] - 2, 0, -1, bufnr, opts, opts.client_id)
+ return _next_diagnostic(cursor_position, false, bufnr, opts, opts.client_id)
end
--- Return the pos, {row, col}, for the prev diagnostic in the current buffer.
---@param opts table See |vim.lsp.diagnostic.goto_next()|
---@return table Previous diagnostic position
function M.get_prev_pos(opts)
- return _iter_diagnostic_lines_pos(
+ return _diagnostic_pos(
opts,
M.get_prev(opts)
)
@@ -568,7 +577,7 @@ end
--- Move to the previous diagnostic
---@param opts table See |vim.lsp.diagnostic.goto_next()|
function M.goto_prev(opts)
- return _iter_diagnostic_move_pos(
+ return _diagnostic_move_pos(
"DiagnosticPrevious",
opts,
M.get_prev_pos(opts)
@@ -585,14 +594,14 @@ function M.get_next(opts)
local bufnr = vim.api.nvim_win_get_buf(win_id)
local cursor_position = opts.cursor_position or vim.api.nvim_win_get_cursor(win_id)
- return _iter_diagnostic_lines(cursor_position[1], vim.api.nvim_buf_line_count(bufnr), 1, bufnr, opts, opts.client_id)
+ return _next_diagnostic(cursor_position, true, bufnr, opts, opts.client_id)
end
--- Return the pos, {row, col}, for the next diagnostic in the current buffer.
---@param opts table See |vim.lsp.diagnostic.goto_next()|
---@return table Next diagnostic position
function M.get_next_pos(opts)
- return _iter_diagnostic_lines_pos(
+ return _diagnostic_pos(
opts,
M.get_next(opts)
)
@@ -617,7 +626,7 @@ end
--- - {win_id}: (number, default 0)
--- - Window ID
function M.goto_next(opts)
- return _iter_diagnostic_move_pos(
+ return _diagnostic_move_pos(
"DiagnosticNext",
opts,
M.get_next_pos(opts)
@@ -849,7 +858,7 @@ end
--- Callback scheduled for after leaving insert mode
---
--- Used to handle
---@private
+---@private
function M._execute_scheduled_display(bufnr, client_id)
local args = _bufs_waiting_to_update[bufnr][client_id]
if not args then
@@ -915,20 +924,20 @@ end
-- Diagnostic Private Highlight Utilies {{{
--- Get the severity highlight name
---@private
+---@private
function M._get_severity_highlight_name(severity)
return virtual_text_highlight_map[severity]
end
--- Get floating severity highlight name
---@private
+---@private
function M._get_floating_severity_highlight_name(severity)
return floating_highlight_map[severity]
end
--- This should be called to update the highlights for the LSP client.
function M._define_default_signs_and_highlights()
- --@private
+ ---@private
local function define_default_sign(name, properties)
if vim.tbl_isempty(vim.fn.sign_getdefined(name)) then
vim.fn.sign_define(name, properties)
@@ -1045,8 +1054,8 @@ function M.on_publish_diagnostics(_, _, params, client_id, _, config)
end
-- restores the extmarks set by M.display
---- @param last number last line that was changed
--- @private
+---@param last number last line that was changed
+---@private
local function restore_extmarks(bufnr, last)
for client_id, extmarks in pairs(diagnostic_cache_extmarks[bufnr]) do
local ns = M._get_diagnostic_namespace(client_id)
@@ -1075,7 +1084,7 @@ local function restore_extmarks(bufnr, last)
end
-- caches the extmarks set by M.display
--- @private
+---@private
local function save_extmarks(bufnr, client_id)
bufnr = bufnr == 0 and api.nvim_get_current_buf() or bufnr
if not diagnostic_attached_buffers[bufnr] then
@@ -1092,7 +1101,7 @@ local function save_extmarks(bufnr, client_id)
diagnostic_cache_extmarks[bufnr][client_id] = api.nvim_buf_get_extmarks(bufnr, ns, 0, -1, {details = true})
end
---@private
+---@private
--- Display diagnostics for the buffer, given a configuration.
function M.display(diagnostics, bufnr, client_id, config)
if diagnostic_disabled[bufnr][client_id] then
@@ -1178,10 +1187,10 @@ end
--- for redrawing diagnostics after making changes in diagnostics
--- configuration. |lsp-handler-configuration|
---
---- @param bufnr (optional, number): Buffer handle, defaults to current
---- @param client_id (optional, number): Redraw diagnostics for the given
---- client. The default is to redraw diagnostics for all attached
---- clients.
+---@param bufnr (optional, number): Buffer handle, defaults to current
+---@param client_id (optional, number): Redraw diagnostics for the given
+--- client. The default is to redraw diagnostics for all attached
+--- clients.
function M.redraw(bufnr, client_id)
bufnr = get_bufnr(bufnr)
if not client_id then
@@ -1208,7 +1217,7 @@ end
-- }}}
-- Diagnostic User Functions {{{
---- Open a floating window with the diagnostics from {line_nr}
+--- Open a floating window with the provided diagnostics
---
--- The floating window can be customized with the following highlight groups:
--- <pre>
@@ -1218,32 +1227,21 @@ end
--- LspDiagnosticsFloatingHint
--- </pre>
---@param opts table Configuration table
---- - show_header (boolean, default true): Show "Diagnostics:" header.
---- - Plus all the opts for |vim.lsp.diagnostic.get_line_diagnostics()|
---- and |vim.lsp.util.open_floating_preview()| can be used here.
----@param bufnr number The buffer number
----@param line_nr number The line number
----@param client_id number|nil the client id
+--- - show_header (boolean, default true): Show "Diagnostics:" header
+--- - all opts for |vim.lsp.util.open_floating_preview()| can be used here
+---@param diagnostics table: The diagnostics to display
---@return table {popup_bufnr, win_id}
-function M.show_line_diagnostics(opts, bufnr, line_nr, client_id)
- opts = opts or {}
-
- local show_header = if_nil(opts.show_header, true)
-
- bufnr = bufnr or 0
- line_nr = line_nr or (vim.api.nvim_win_get_cursor(0)[1] - 1)
-
+local function show_diagnostics(opts, diagnostics)
+ if vim.tbl_isempty(diagnostics) then return end
local lines = {}
local highlights = {}
+ local show_header = if_nil(opts.show_header, true)
if show_header then
table.insert(lines, "Diagnostics:")
table.insert(highlights, {0, "Bold"})
end
- local line_diagnostics = M.get_line_diagnostics(bufnr, line_nr, opts, client_id)
- if vim.tbl_isempty(line_diagnostics) then return end
-
- for i, diagnostic in ipairs(line_diagnostics) do
+ for i, diagnostic in ipairs(diagnostics) do
local prefix = string.format("%d. ", i)
local hiname = M._get_floating_severity_highlight_name(diagnostic.severity)
assert(hiname, 'unknown severity: ' .. tostring(diagnostic.severity))
@@ -1257,7 +1255,6 @@ function M.show_line_diagnostics(opts, bufnr, line_nr, client_id)
end
end
- opts.focus_id = "line_diagnostics"
local popup_bufnr, winnr = util.open_floating_preview(lines, 'plaintext', opts)
for i, hi in ipairs(highlights) do
local prefixlen, hiname = unpack(hi)
@@ -1268,6 +1265,57 @@ function M.show_line_diagnostics(opts, bufnr, line_nr, client_id)
return popup_bufnr, winnr
end
+--- Open a floating window with the diagnostics from {position}
+
+---@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.
+--- - all opts for |show_diagnostics()| can be used here
+---@param buf_nr number|nil The buffer number
+---@param position table|nil The (0,0)-indexed position
+---@return table {popup_bufnr, win_id}
+function M.show_position_diagnostics(opts, buf_nr, position)
+ opts = opts or {}
+ opts.focus_id = "position_diagnostics"
+ buf_nr = buf_nr or vim.api.nvim_get_current_buf()
+ if not position then
+ local curr_position = vim.api.nvim_win_get_cursor(0)
+ curr_position[1] = curr_position[1] - 1
+ position = curr_position
+ end
+ local match_position_predicate = function(diag)
+ return position[1] == diag.range['start'].line and
+ position[2] >= diag.range['start'].character and
+ (position[2] <= diag.range['end'].character or position[1] < diag.range['end'].line)
+ end
+ local position_diagnostics = M.get(buf_nr, nil, match_position_predicate)
+ if opts.severity then
+ position_diagnostics = filter_to_severity_limit(opts.severity, position_diagnostics)
+ elseif opts.severity_limit then
+ position_diagnostics = filter_by_severity_limit(opts.severity_limit, position_diagnostics)
+ end
+ table.sort(position_diagnostics, function(a, b) return a.severity < b.severity end)
+ return show_diagnostics(opts, position_diagnostics)
+end
+
+--- Open a floating window with the diagnostics from {line_nr}
+
+---@param opts table Configuration table
+--- - all opts for |vim.lsp.diagnostic.get_line_diagnostics()| and
+--- |show_diagnostics()| can be used here
+---@param buf_nr number|nil The buffer number
+---@param line_nr number|nil The line number
+---@param client_id number|nil the client id
+---@return table {popup_bufnr, win_id}
+function M.show_line_diagnostics(opts, buf_nr, line_nr, client_id)
+ opts = opts or {}
+ opts.focus_id = "line_diagnostics"
+ line_nr = line_nr or (vim.api.nvim_win_get_cursor(0)[1] - 1)
+ local line_diagnostics = M.get_line_diagnostics(buf_nr, line_nr, opts, client_id)
+ return show_diagnostics(opts, line_diagnostics)
+end
--- Clear diagnotics and diagnostic cache
---
@@ -1362,10 +1410,10 @@ function M.set_loclist(opts)
end
--- Disable diagnostics for the given buffer and client
---- @param bufnr (optional, number): Buffer handle, defaults to current
---- @param client_id (optional, number): Disable diagnostics for the given
---- client. The default is to disable diagnostics for all attached
---- clients.
+---@param bufnr (optional, number): Buffer handle, defaults to current
+---@param client_id (optional, number): Disable diagnostics for the given
+--- client. The default is to disable diagnostics for all attached
+--- clients.
-- Note that when diagnostics are disabled for a buffer, the server will still
-- send diagnostic information and the client will still process it. The
-- diagnostics are simply not displayed to the user.
@@ -1381,10 +1429,10 @@ function M.disable(bufnr, client_id)
end
--- Enable diagnostics for the given buffer and client
---- @param bufnr (optional, number): Buffer handle, defaults to current
---- @param client_id (optional, number): Enable diagnostics for the given
---- client. The default is to enable diagnostics for all attached
---- clients.
+---@param bufnr (optional, number): Buffer handle, defaults to current
+---@param client_id (optional, number): Enable diagnostics for the given
+--- client. The default is to enable diagnostics for all attached
+--- clients.
function M.enable(bufnr, client_id)
if not client_id then
return vim.lsp.for_each_buffer_client(bufnr, function(client)
diff --git a/runtime/lua/vim/lsp/handlers.lua b/runtime/lua/vim/lsp/handlers.lua
index b7f1ea0ab6..befb9fcec3 100644
--- a/runtime/lua/vim/lsp/handlers.lua
+++ b/runtime/lua/vim/lsp/handlers.lua
@@ -9,9 +9,9 @@ local M = {}
-- FIXME: DOC: Expose in vimdocs
---@private
+---@private
--- Writes to error buffer.
---@param ... (table of strings) Will be concatenated before being written
+---@param ... (table of strings) Will be concatenated before being written
local function err_message(...)
vim.notify(table.concat(vim.tbl_flatten{...}), vim.log.levels.ERROR)
api.nvim_command("redraw")
@@ -22,7 +22,7 @@ M['workspace/executeCommand'] = function()
-- Error handling is done implicitly by wrapping all handlers; see end of this file
end
---@private
+---@private
local function progress_handler(_, _, params, client_id)
local client = vim.lsp.get_client_by_id(client_id)
local client_name = client and client.name or string.format("id=%d", client_id)
@@ -189,7 +189,7 @@ end
---@private
+---@private
--- Return a function that converts LSP responses to list items and opens the list
---
--- The returned function has an optional {config} parameter that accepts a table
@@ -197,8 +197,8 @@ end
---
--- loclist: (boolean) use the location list (default is to use the quickfix list)
---
---- @param map_result function `((resp, bufnr) -> list)` to convert the response
---- @param entity name of the resource used in a `not found` error message
+---@param map_result function `((resp, bufnr) -> list)` to convert the response
+---@param entity name of the resource used in a `not found` error message
local function response_to_list(map_result, entity)
return function(_, _, result, _, bufnr, config)
if not result or vim.tbl_isempty(result) then
@@ -289,11 +289,11 @@ end
--see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_hover
M['textDocument/hover'] = M.hover
---@private
+---@private
--- Jumps to a location. Used as a handler for multiple LSP methods.
---@param _ (not used)
---@param method (string) LSP method name
---@param result (table) result of LSP method; a location or a list of locations.
+---@param _ (not used)
+---@param method (string) LSP method name
+---@param result (table) result of LSP method; a location or a list of locations.
---(`textDocument/definition` can return `Location` or `Location[]`
local function location_handler(_, method, result)
if result == nil or vim.tbl_isempty(result) then
@@ -377,13 +377,13 @@ M['textDocument/documentHighlight'] = function(_, _, result, _, bufnr, _)
util.buf_highlight_references(bufnr, result)
end
---@private
+---@private
---
--- Displays call hierarchy in the quickfix window.
---
---@param direction `"from"` for incoming calls and `"to"` for outgoing calls
---@returns `CallHierarchyIncomingCall[]` if {direction} is `"from"`,
---@returns `CallHierarchyOutgoingCall[]` if {direction} is `"to"`,
+---@param direction `"from"` for incoming calls and `"to"` for outgoing calls
+---@returns `CallHierarchyIncomingCall[]` if {direction} is `"from"`,
+---@returns `CallHierarchyOutgoingCall[]` if {direction} is `"to"`,
local make_call_hierarchy_handler = function(direction)
return function(_, _, result)
if not result then return end
diff --git a/runtime/lua/vim/lsp/log.lua b/runtime/lua/vim/lsp/log.lua
index 73fafb9715..a2d5c3a774 100644
--- a/runtime/lua/vim/lsp/log.lua
+++ b/runtime/lua/vim/lsp/log.lua
@@ -18,14 +18,14 @@ local log_date_format = "%FT%H:%M:%S%z"
do
local path_sep = vim.loop.os_uname().version:match("Windows") and "\\" or "/"
- --@private
+ ---@private
local function path_join(...)
return table.concat(vim.tbl_flatten{...}, path_sep)
end
local logfilename = path_join(vim.fn.stdpath('cache'), 'lsp.log')
--- Returns the log filename.
- --@returns (string) log filename
+ ---@returns (string) log filename
function log.get_filename()
return logfilename
end
@@ -77,7 +77,7 @@ end
vim.tbl_add_reverse_lookup(log.levels)
--- Sets the current log level.
---@param level (string or number) One of `vim.lsp.log.levels`
+---@param level (string or number) One of `vim.lsp.log.levels`
function log.set_level(level)
if type(level) == 'string' then
current_log_level = assert(log.levels[level:upper()], string.format("Invalid log level: %q", level))
@@ -89,8 +89,8 @@ function log.set_level(level)
end
--- Checks whether the level is sufficient for logging.
---@param level number log level
---@returns (bool) true if would log, false if not
+---@param level number log level
+---@returns (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 6d02b9ba74..27703b4503 100644
--- a/runtime/lua/vim/lsp/protocol.lua
+++ b/runtime/lua/vim/lsp/protocol.lua
@@ -5,14 +5,14 @@ local if_nil = vim.F.if_nil
local protocol = {}
--[=[
---@private
+---@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
+---@private
function transform_schema_to_table()
transform_schema_comments()
nvim.command [[silent! '<,'>s/: \S\+//]]
@@ -1003,8 +1003,7 @@ function protocol.resolve_capabilities(server_capabilities)
elseif type(server_capabilities.declarationProvider) == 'boolean' then
general_properties.declaration = server_capabilities.declarationProvider
elseif type(server_capabilities.declarationProvider) == 'table' then
- -- TODO: support more detailed declarationProvider options.
- general_properties.declaration = false
+ general_properties.declaration = server_capabilities.declarationProvider
else
error("The server sent invalid declarationProvider")
end
@@ -1014,8 +1013,7 @@ function protocol.resolve_capabilities(server_capabilities)
elseif type(server_capabilities.typeDefinitionProvider) == 'boolean' then
general_properties.type_definition = server_capabilities.typeDefinitionProvider
elseif type(server_capabilities.typeDefinitionProvider) == 'table' then
- -- TODO: support more detailed typeDefinitionProvider options.
- general_properties.type_definition = false
+ general_properties.type_definition = server_capabilities.typeDefinitionProvider
else
error("The server sent invalid typeDefinitionProvider")
end
@@ -1025,8 +1023,7 @@ function protocol.resolve_capabilities(server_capabilities)
elseif type(server_capabilities.implementationProvider) == 'boolean' then
general_properties.implementation = server_capabilities.implementationProvider
elseif type(server_capabilities.implementationProvider) == 'table' then
- -- TODO(ashkan) support more detailed implementation options.
- general_properties.implementation = false
+ general_properties.implementation = server_capabilities.implementationProvider
else
error("The server sent invalid implementationProvider")
end
diff --git a/runtime/lua/vim/lsp/rpc.lua b/runtime/lua/vim/lsp/rpc.lua
index 4c5f02af9d..eedb708118 100644
--- a/runtime/lua/vim/lsp/rpc.lua
+++ b/runtime/lua/vim/lsp/rpc.lua
@@ -5,11 +5,11 @@ local protocol = require('vim.lsp.protocol')
local validate, schedule, schedule_wrap = vim.validate, vim.schedule, vim.schedule_wrap
-- TODO replace with a better implementation.
---@private
+---@private
--- Encodes to JSON.
---
---@param data (table) Data to encode
---@returns (string) Encoded object
+---@param data (table) Data to encode
+---@returns (string) Encoded object
local function json_encode(data)
local status, result = pcall(vim.fn.json_encode, data)
if status then
@@ -18,11 +18,11 @@ local function json_encode(data)
return nil, result
end
end
---@private
+---@private
--- Decodes from JSON.
---
---@param data (string) Data to decode
---@returns (table) Decoded JSON object
+---@param data (string) Data to decode
+---@returns (table) Decoded JSON object
local function json_decode(data)
local status, result = pcall(vim.fn.json_decode, data)
if status then
@@ -32,10 +32,10 @@ local function json_decode(data)
end
end
---@private
+---@private
--- Checks whether a given path exists and is a directory.
---@param filename (string) path to check
---@returns (bool)
+---@param filename (string) path to check
+---@returns (bool)
local function is_dir(filename)
local stat = vim.loop.fs_stat(filename)
return stat and stat.type == 'directory' or false
@@ -43,7 +43,7 @@ end
local NIL = vim.NIL
---@private
+---@private
local recursive_convert_NIL
recursive_convert_NIL = function(v, tbl_processed)
if v == NIL then
@@ -63,15 +63,15 @@ recursive_convert_NIL = function(v, tbl_processed)
return v
end
---@private
+---@private
--- Returns its argument, but converts `vim.NIL` to Lua `nil`.
---@param v (any) Argument
---@returns (any)
+---@param v (any) Argument
+---@returns (any)
local function convert_NIL(v)
return recursive_convert_NIL(v, {})
end
---@private
+---@private
--- Merges current process env with the given env and returns the result as
--- a list of "k=v" strings.
---
@@ -81,8 +81,8 @@ end
--- in: { PRODUCTION="false", PATH="/usr/bin/", PORT=123, HOST="0.0.0.0", }
--- out: { "PRODUCTION=false", "PATH=/usr/bin/", "PORT=123", "HOST=0.0.0.0", }
--- </pre>
---@param env (table) table of environment variable assignments
---@returns (table) list of `"k=v"` strings
+---@param env (table) table of environment variable assignments
+---@returns (table) list of `"k=v"` strings
local function env_merge(env)
if env == nil then
return env
@@ -97,11 +97,11 @@ local function env_merge(env)
return final_env
end
---@private
+---@private
--- Embeds the given string into a table and correctly computes `Content-Length`.
---
---@param encoded_message (string)
---@returns (table) table containing encoded message and `Content-Length` attribute
+---@param encoded_message (string)
+---@returns (table) table containing encoded message and `Content-Length` attribute
local function format_message_with_content_length(encoded_message)
return table.concat {
'Content-Length: '; tostring(#encoded_message); '\r\n\r\n';
@@ -109,11 +109,11 @@ local function format_message_with_content_length(encoded_message)
}
end
---@private
+---@private
--- Parses an LSP Message's header
---
---@param header: The header to parse.
---@returns Parsed headers
+---@param header: The header to parse.
+---@returns Parsed headers
local function parse_headers(header)
if type(header) ~= 'string' then
return nil
@@ -141,7 +141,7 @@ end
-- case insensitive pattern.
local header_start_pattern = ("content"):gsub("%w", function(c) return "["..c..c:upper().."]" end)
---@private
+---@private
--- The actual workhorse.
local function request_parser_loop()
local buffer = '' -- only for header part
@@ -203,8 +203,8 @@ local client_errors = vim.tbl_add_reverse_lookup {
--- 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
+---@returns (string) The formatted error message
local function format_rpc_error(err)
validate {
err = { err, 't' };
@@ -233,9 +233,9 @@ end
--- Creates an RPC response object/table.
---
---@param code RPC error code defined in `vim.lsp.protocol.ErrorCodes`
---@param message (optional) arbitrary message to send to server
---@param data (optional) arbitrary data to send to server
+---@param code RPC error code defined in `vim.lsp.protocol.ErrorCodes`
+---@param message (optional) arbitrary message to send to server
+---@param data (optional) arbitrary data to send to server
local function rpc_response_error(code, message, data)
-- TODO should this error or just pick a sane error (like InternalError)?
local code_name = assert(protocol.ErrorCodes[code], 'Invalid RPC error code')
@@ -250,38 +250,38 @@ end
local default_dispatchers = {}
---@private
+---@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
+---@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
+---@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
---@returns `nil` and `vim.lsp.protocol.ErrorCodes.MethodNotFound`.
+---@param method (string) The invoked LSP method
+---@param params (table): Parameters for the invoked LSP method
+---@returns `nil` and `vim.lsp.protocol.ErrorCodes.MethodNotFound`.
function default_dispatchers.server_request(method, params)
local _ = log.debug() and log.debug('server_request', method, params)
return nil, rpc_response_error(protocol.ErrorCodes.MethodNotFound)
end
---@private
+---@private
--- Default dispatcher for when a client exits.
---
---@param code (number): Exit code
---@param signal (number): Number describing the signal used to terminate (if
+---@param code (number): Exit code
+---@param signal (number): 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
---@private
+---@private
--- Default dispatcher for client errors.
---
---@param code (number): Error code
---@param err (any): Details about the error
+---@param code (number): 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:', client_errors[code], err)
@@ -290,25 +290,25 @@ end
--- Starts an LSP server process and create an LSP RPC client object to
--- interact with it.
---
---@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, optional) Dispatchers for LSP message types. Valid
+---@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, optional) Dispatchers for LSP message types. Valid
---dispatcher names are:
--- - `"notification"`
--- - `"server_request"`
--- - `"on_error"`
--- - `"on_exit"`
---@param extra_spawn_params (table, optional) Additional context for the LSP
+---@param extra_spawn_params (table, optional) 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
---@returns Client RPC object.
+---@returns Client RPC object.
---
---@returns Methods:
+---@returns Methods:
--- - `notify()` |vim.lsp.rpc.notify()|
--- - `request()` |vim.lsp.rpc.request()|
---
---@returns Members:
+---@returns Members:
--- - {pid} (number) The LSP server's PID.
--- - {handle} A handle for low-level interaction with the LSP server process
--- |vim.loop|.
@@ -358,10 +358,10 @@ local function start(cmd, cmd_args, dispatchers, extra_spawn_params)
local handle, pid
do
- --@private
+ ---@private
--- Callback for |vim.loop.spawn()| Closes all streams and runs the `on_exit` dispatcher.
- --@param code (number) Exit code
- --@param signal (number) Signal that was used to terminate (if any)
+ ---@param code (number) Exit code
+ ---@param signal (number) Signal that was used to terminate (if any)
local function onexit(code, signal)
stdin:close()
stdout:close()
@@ -385,12 +385,12 @@ local function start(cmd, cmd_args, dispatchers, extra_spawn_params)
end
end
- --@private
+ ---@private
--- Encodes {payload} into a JSON-RPC message and sends it to the remote
--- process.
---
- --@param payload (table) Converted into a JSON string, see |json_encode()|
- --@returns true if the payload could be scheduled, false if the main event-loop is in the process of closing.
+ ---@param payload (table) Converted into a JSON string, see |json_encode()|
+ ---@returns true if the payload could be scheduled, false if the main event-loop is in the process of closing.
local function encode_and_send(payload)
local _ = log.debug() and log.debug("rpc.send.payload", payload)
if handle == nil or handle:is_closing() then return false end
@@ -406,9 +406,9 @@ local function start(cmd, cmd_args, dispatchers, extra_spawn_params)
-- `start()`
--
--- Sends a notification to the LSP server.
- --@param method (string) The invoked LSP method
- --@param params (table): Parameters for the invoked LSP method
- --@returns (bool) `true` if notification could be sent, `false` if not
+ ---@param method (string) The invoked LSP method
+ ---@param params (table): Parameters for the invoked LSP method
+ ---@returns (bool) `true` if notification could be sent, `false` if not
local function notify(method, params)
return encode_and_send {
jsonrpc = "2.0";
@@ -417,7 +417,7 @@ local function start(cmd, cmd_args, dispatchers, extra_spawn_params)
}
end
- --@private
+ ---@private
--- sends an error object to the remote LSP process.
local function send_response(request_id, err, result)
return encode_and_send {
@@ -433,10 +433,10 @@ local function start(cmd, cmd_args, dispatchers, extra_spawn_params)
--
--- Sends a request to the LSP server and runs {callback} upon response.
---
- --@param method (string) The invoked LSP method
- --@param params (table) Parameters for the invoked LSP method
- --@param callback (function) Callback to invoke
- --@returns (bool, number) `(true, message_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 (function) Callback to invoke
+ ---@returns (bool, number) `(true, message_id)` if request could be sent, `false` if not
local function request(method, params, callback)
validate {
callback = { callback, 'f' };
@@ -463,13 +463,13 @@ local function start(cmd, cmd_args, dispatchers, extra_spawn_params)
end
end)
- --@private
+ ---@private
local function on_error(errkind, ...)
assert(client_errors[errkind])
-- TODO what to do if this fails?
pcall(dispatchers.on_error, errkind, ...)
end
- --@private
+ ---@private
local function pcall_handler(errkind, status, head, ...)
if not status then
on_error(errkind, head, ...)
@@ -477,7 +477,7 @@ local function start(cmd, cmd_args, dispatchers, extra_spawn_params)
end
return status, head, ...
end
- --@private
+ ---@private
local function try_call(errkind, fn, ...)
return pcall_handler(errkind, pcall(fn, ...))
end
@@ -486,7 +486,7 @@ local function start(cmd, cmd_args, dispatchers, extra_spawn_params)
-- time and log them. This would require storing the timestamp. I could call
-- them with an error then, perhaps.
- --@private
+ ---@private
local function handle_body(body)
local decoded, err = json_decode(body)
if not decoded then
diff --git a/runtime/lua/vim/lsp/util.lua b/runtime/lua/vim/lsp/util.lua
index d682fdc17e..a4b3298fd8 100644
--- a/runtime/lua/vim/lsp/util.lua
+++ b/runtime/lua/vim/lsp/util.lua
@@ -40,10 +40,10 @@ local loclist_type_map = {
}
---@private
--- Check the border given by opts or the default border for the additional
--- size it adds to a float.
---@returns size of border in height and width
+---@private
+--- Check the border given by opts or the default border for the additional
+--- size it adds to a float.
+---@returns size of border in height and width
local function get_border_size(opts)
local border = opts and opts.border or default_border
local height = 0
@@ -86,7 +86,7 @@ local function get_border_size(opts)
return { height = height, width = width }
end
---@private
+---@private
local function split_lines(value)
return split(value, '\n', true)
end
@@ -95,11 +95,11 @@ end
---
--- CAUTION: Changes in-place!
---
---@param lines (table) Original list of strings
---@param A (table) Start position; a 2-tuple of {line, col} numbers
---@param B (table) End position; a 2-tuple of {line, col} numbers
---@param new_lines A list of strings to replace the original
---@returns (table) The modified {lines} object
+---@param lines (table) Original list of strings
+---@param A (table) Start position; a 2-tuple of {line, col} numbers
+---@param B (table) End position; a 2-tuple of {line, col} numbers
+---@param new_lines A list of strings to replace the original
+---@returns (table) The modified {lines} object
function M.set_lines(lines, A, B, new_lines)
-- 0-indexing to 1-indexing
local i_0 = A[1] + 1
@@ -133,7 +133,7 @@ function M.set_lines(lines, A, B, new_lines)
return lines
end
---@private
+---@private
local function sort_by_key(fn)
return function(a,b)
local ka, kb = fn(a), fn(b)
@@ -147,12 +147,12 @@ local function sort_by_key(fn)
return false
end
end
---@private
+---@private
local edit_sort_key = sort_by_key(function(e)
return {e.A[1], e.A[2], e.i}
end)
---@private
+---@private
--- Position is a https://microsoft.github.io/language-server-protocol/specifications/specification-current/#position
--- Returns a zero-indexed column, since set_lines() does the conversion to
--- 1-indexed
@@ -238,8 +238,8 @@ function M.get_progress_messages()
end
--- Applies a list of text edits to a buffer.
---@param text_edits (table) list of `TextEdit` objects
---@param buf_nr (number) Buffer id
+---@param text_edits (table) list of `TextEdit` objects
+---@param buf_nr (number) Buffer id
---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textEdit
function M.apply_text_edits(text_edits, bufnr)
if not next(text_edits) then return end
@@ -295,11 +295,11 @@ end
-- function M.glob_to_regex(glob)
-- end
---@private
+---@private
--- Finds the first line and column of the difference between old and new lines
---@param old_lines table list of lines
---@param new_lines table list of lines
---@returns (int, int) start_line_idx and start_col_idx of range
+---@param old_lines table list of lines
+---@param new_lines table list of lines
+---@returns (int, int) start_line_idx and start_col_idx of range
local function first_difference(old_lines, new_lines, start_line_idx)
local line_count = math.min(#old_lines, #new_lines)
if line_count == 0 then return 1, 1 end
@@ -325,12 +325,12 @@ local function first_difference(old_lines, new_lines, start_line_idx)
end
---@private
+---@private
--- Finds the last line and column of the differences between old and new lines
---@param old_lines table list of lines
---@param new_lines table list of lines
---@param start_char integer First different character idx of range
---@returns (int, int) end_line_idx and end_col_idx of range
+---@param old_lines table list of lines
+---@param new_lines table list of lines
+---@param start_char integer First different character idx of range
+---@returns (int, int) end_line_idx and end_col_idx of range
local function last_difference(old_lines, new_lines, start_char, end_line_idx)
local line_count = math.min(#old_lines, #new_lines)
if line_count == 0 then return 0,0 end
@@ -369,14 +369,14 @@ local function last_difference(old_lines, new_lines, start_char, end_line_idx)
end
---@private
+---@private
--- Get the text of the range defined by start and end line/column
---@param lines table list of lines
---@param start_char integer First different character idx of range
---@param end_char integer Last different character idx of range
---@param start_line integer First different line idx of range
---@param end_line integer Last different line idx of range
---@returns string text extracted from defined region
+---@param lines table list of lines
+---@param start_char integer First different character idx of range
+---@param end_char integer Last different character idx of range
+---@param start_line integer First different line idx of range
+---@param end_line integer Last different line idx of range
+---@returns string text extracted from defined region
local function extract_text(lines, start_line, start_char, end_line, end_char)
if start_line == #lines + end_line + 1 then
if end_line == 0 then return '' end
@@ -396,14 +396,14 @@ local function extract_text(lines, start_line, start_char, end_line, end_char)
return result
end
---@private
+---@private
--- Compute the length of the substituted range
---@param lines table list of lines
---@param start_char integer First different character idx of range
---@param end_char integer Last different character idx of range
---@param start_line integer First different line idx of range
---@param end_line integer Last different line idx of range
---@returns (int, int) end_line_idx and end_col_idx of range
+---@param lines table list of lines
+---@param start_char integer First different character idx of range
+---@param end_char integer Last different character idx of range
+---@param start_line integer First different line idx of range
+---@param end_line integer Last different line idx of range
+---@returns (int, int) end_line_idx and end_col_idx of range
local function compute_length(lines, start_line, start_char, end_line, end_char)
local adj_end_line = #lines + end_line + 1
local adj_end_char
@@ -424,12 +424,12 @@ local function compute_length(lines, start_line, start_char, end_line, end_char)
end
--- Returns the range table for the difference between old and new lines
---@param old_lines table list of lines
---@param new_lines table list of lines
---@param start_line_idx int line to begin search for first difference
---@param end_line_idx int line to begin search for last difference
---@param offset_encoding string encoding requested by language server
---@returns table start_line_idx and start_col_idx of range
+---@param old_lines table list of lines
+---@param new_lines table list of lines
+---@param start_line_idx int line to begin search for first difference
+---@param end_line_idx int line to begin search for last difference
+---@param offset_encoding string encoding requested by language server
+---@returns table start_line_idx and start_col_idx of range
function M.compute_diff(old_lines, new_lines, start_line_idx, end_line_idx, offset_encoding)
local start_line, start_char = first_difference(old_lines, new_lines, start_line_idx)
local end_line, end_char = last_difference(vim.list_slice(old_lines, start_line, #old_lines),
@@ -469,9 +469,9 @@ end
--- Can be used to extract the completion items from a
--- `textDocument/completion` request, which may return one of
--- `CompletionItem[]`, `CompletionList` or null.
---@param result (table) The result of a `textDocument/completion` request
---@returns (table) List of completion items
---@see https://microsoft.github.io/language-server-protocol/specification#textDocument_completion
+---@param result (table) The result of a `textDocument/completion` request
+---@returns (table) List of completion items
+---@see https://microsoft.github.io/language-server-protocol/specification#textDocument_completion
function M.extract_completion_items(result)
if type(result) == 'table' and result.items then
-- result is a `CompletionList`
@@ -515,12 +515,12 @@ function M.apply_text_document_edit(text_document_edit, index)
M.apply_text_edits(text_document_edit.edits, bufnr)
end
---@private
+---@private
--- Recursively parses snippets in a completion entry.
---
---@param input (string) Snippet text to parse for snippets
---@param inner (bool) Whether this function is being called recursively
---@returns 2-tuple of strings: The first is the parsed result, the second is the
+---@param input (string) Snippet text to parse for snippets
+---@param inner (bool) Whether this function is being called recursively
+---@returns 2-tuple of strings: The first is the parsed result, the second is the
---unparsed rest of the input
local function parse_snippet_rec(input, inner)
local res = ""
@@ -577,28 +577,28 @@ end
--- Parses snippets in a completion entry.
---
---@param input (string) unparsed snippet
---@returns (string) parsed snippet
+---@param input (string) unparsed snippet
+---@returns (string) parsed snippet
function M.parse_snippet(input)
local res, _ = parse_snippet_rec(input, false)
return res
end
---@private
+---@private
--- Sorts by CompletionItem.sortText.
---
---@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
local function sort_completion_items(items)
table.sort(items, function(a, b)
return (a.sortText or a.label) < (b.sortText or b.label)
end)
end
---@private
+---@private
--- Returns text that should be inserted when selecting completion item. The
--- precedence is as follows: textEdit.newText > insertText > label
---@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
local function get_completion_word(item)
if item.textEdit ~= nil and item.textEdit.newText ~= nil and item.textEdit.newText ~= "" then
local insert_text_format = protocol.InsertTextFormat[item.insertTextFormat]
@@ -618,7 +618,7 @@ local function get_completion_word(item)
return item.label
end
---@private
+---@private
--- Some language servers return complementary candidates whose prefixes do not
--- match are also returned. So we exclude completion candidates whose prefix
--- does not match.
@@ -633,9 +633,9 @@ end
--- the client must handle it properly even if it receives a value outside the
--- specification.
---
---@param completion_item_kind (`vim.lsp.protocol.completionItemKind`)
---@returns (`vim.lsp.protocol.completionItemKind`)
---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_completion
+---@param completion_item_kind (`vim.lsp.protocol.completionItemKind`)
+---@returns (`vim.lsp.protocol.completionItemKind`)
+---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_completion
function M._get_completion_item_kind_name(completion_item_kind)
return protocol.CompletionItemKind[completion_item_kind] or "Unknown"
end
@@ -643,12 +643,12 @@ end
--- Turns the result of a `textDocument/completion` request into vim-compatible
--- |complete-items|.
---
---@param result The result of a `textDocument/completion` call, e.g. from
+---@param result The result of a `textDocument/completion` call, e.g. from
---|vim.lsp.buf.completion()|, which may be one of `CompletionItem[]`,
--- `CompletionList` or `null`
---@param prefix (string) the prefix to filter the completion items
---@returns { matches = complete-items table, incomplete = bool }
---@see |complete-items|
+---@param prefix (string) the prefix to filter the completion items
+---@returns { matches = complete-items table, incomplete = bool }
+---@see |complete-items|
function M.text_document_completion_list_to_complete_items(result, prefix)
local items = M.extract_completion_items(result)
if vim.tbl_isempty(items) then
@@ -698,8 +698,8 @@ end
--- Rename old_fname to new_fname
---
---@param opts (table)
+---
+---@param opts (table)
-- overwrite? bool
-- ignoreIfExists? bool
function M.rename(old_fname, new_fname, opts)
@@ -754,8 +754,8 @@ end
--- Applies a `WorkspaceEdit`.
---
---@param workspace_edit (table) `WorkspaceEdit`
--- @see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_applyEdit
+---@param workspace_edit (table) `WorkspaceEdit`
+--see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_applyEdit
function M.apply_workspace_edit(workspace_edit)
if workspace_edit.documentChanges then
for idx, change in ipairs(workspace_edit.documentChanges) do
@@ -794,10 +794,10 @@ end
--- window for `textDocument/hover`, for parsing the result of
--- `textDocument/signatureHelp`, and potentially others.
---
---@param input (`MarkedString` | `MarkedString[]` | `MarkupContent`)
---@param contents (table, optional, default `{}`) List of strings to extend with converted lines
---@returns {contents}, extended with lines of converted markdown.
---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_hover
+---@param input (`MarkedString` | `MarkedString[]` | `MarkupContent`)
+---@param contents (table, optional, default `{}`) List of strings to extend with converted lines
+---@returns {contents}, extended with lines of converted markdown.
+---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_hover
function M.convert_input_to_markdown_lines(input, contents)
contents = contents or {}
-- MarkedString variation 1
@@ -844,11 +844,11 @@ end
--- Converts `textDocument/SignatureHelp` response to markdown lines.
---
---@param signature_help Response of `textDocument/SignatureHelp`
---@param ft optional filetype that will be use as the `lang` for the label markdown code block
---@param triggers optional list of trigger characters from the lsp server. used to better determine parameter offsets
---@returns list of lines of converted markdown.
---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_signatureHelp
+---@param signature_help Response of `textDocument/SignatureHelp`
+---@param ft optional filetype that will be use as the `lang` for the label markdown code block
+---@param triggers optional list of trigger characters from the lsp server. used to better determine parameter offsets
+---@returns list of lines of converted markdown.
+---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_signatureHelp
function M.convert_signature_help_to_markdown_lines(signature_help, ft, triggers)
if not signature_help.signatures then
return
@@ -943,10 +943,10 @@ end
--- Creates a table with sensible default options for a floating window. The
--- table can be passed to |nvim_open_win()|.
---
---@param width (number) window width (in character cells)
---@param height (number) window height (in character cells)
---@param opts (table, optional)
---@returns (table) Options
+---@param width (number) window width (in character cells)
+---@param height (number) window height (in character cells)
+---@param opts (table, optional)
+---@returns (table) Options
function M.make_floating_popup_options(width, height, opts)
validate {
opts = { opts, 't', true };
@@ -997,8 +997,8 @@ end
--- Jumps to a location.
---
---@param location (`Location`|`LocationLink`)
---@returns `true` if the jump succeeded
+---@param location (`Location`|`LocationLink`)
+---@returns `true` if the jump succeeded
function M.jump_to_location(location)
-- location may be Location or LocationLink
local uri = location.uri or location.targetUri
@@ -1028,8 +1028,8 @@ end
--- - for Location, range is shown (e.g., function definition)
--- - for LocationLink, targetRange is shown (e.g., body of function definition)
---
---@param location a single `Location` or `LocationLink`
---@returns (bufnr,winnr) buffer and window number of floating window or nil
+---@param location a single `Location` or `LocationLink`
+---@returns (bufnr,winnr) buffer and window number of floating window or nil
function M.preview_location(location, opts)
-- location may be LocationLink or Location (more useful for the former)
local uri = location.targetUri or location.uri
@@ -1052,7 +1052,7 @@ function M.preview_location(location, opts)
return M.open_floating_preview(contents, syntax, opts)
end
---@private
+---@private
local function find_window_by_var(name, value)
for _, win in ipairs(api.nvim_list_wins()) do
if npcall(api.nvim_win_get_var, win, name) == value then
@@ -1088,10 +1088,10 @@ function M._trim(contents, opts)
return contents
end
--- Generates a table mapping markdown code block lang to vim syntax,
--- based on g:markdown_fenced_languages
--- @return a table of lang -> syntax mappings
--- @private
+--- Generates a table mapping markdown code block lang to vim syntax,
+--- based on g:markdown_fenced_languages
+---@return a table of lang -> syntax mappings
+---@private
local function get_markdown_fences()
local fences = {}
for _, fence in pairs(vim.g.markdown_fenced_languages or {}) do
@@ -1227,7 +1227,7 @@ function M.stylize_markdown(bufnr, contents, opts)
vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, stripped)
local idx = 1
- --@private
+ ---@private
-- keep track of syntaxes we already inlcuded.
-- no need to include the same syntax more than once
local langs = {}
@@ -1276,26 +1276,26 @@ end
--- Creates autocommands to close a preview window when events happen.
---
---@param events (table) list of events
---@param winnr (number) window id of preview window
---@see |autocmd-events|
+---@param events (table) list of events
+---@param winnr (number) window id of preview window
+---@see |autocmd-events|
function M.close_preview_autocmd(events, winnr)
if #events > 0 then
api.nvim_command("autocmd "..table.concat(events, ',').." <buffer> ++once lua pcall(vim.api.nvim_win_close, "..winnr..", true)")
end
end
---@internal
+---@internal
--- Computes size of float needed to show contents (with optional wrapping)
---
---@param contents table of lines to show in window
---@param opts dictionary with optional fields
--- - height of floating window
--- - width of floating window
--- - wrap_at character to wrap at for computing height
--- - max_width maximal width of floating window
--- - max_height maximal height of floating window
---@returns width,height size of float
+---@param contents table of lines to show in window
+---@param opts dictionary with optional fields
+--- - height of floating window
+--- - width of floating window
+--- - wrap_at character to wrap at for computing height
+--- - max_width maximal width of floating window
+--- - max_height maximal height of floating window
+---@returns width,height size of float
function M._make_floating_popup_size(contents, opts)
validate {
contents = { contents, 't' };
@@ -1362,9 +1362,9 @@ end
--- 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 dictionary with optional fields
+---@param contents table of lines to show in window
+---@param syntax string of syntax to set for opened buffer
+---@param opts dictionary with optional fields
--- - height of floating window
--- - width of floating window
--- - wrap boolean enable wrapping of long lines (defaults to true)
@@ -1378,7 +1378,7 @@ end
--- - focus_id if a popup with this id is opened, then focus it
--- - close_events list of events that closes the floating window
--- - focusable (boolean, default true): Make float focusable
---@returns bufnr,winnr buffer and window number of the newly created floating
+---@returns bufnr,winnr buffer and window number of the newly created floating
---preview window
function M.open_floating_preview(contents, syntax, opts)
validate {
@@ -1474,7 +1474,7 @@ do --[[ References ]]
--- Removes document highlights from a buffer.
---
- --@param bufnr buffer id
+ ---@param bufnr buffer id
function M.buf_clear_references(bufnr)
validate { bufnr = {bufnr, 'n', true} }
api.nvim_buf_clear_namespace(bufnr, reference_ns, 0, -1)
@@ -1482,8 +1482,8 @@ do --[[ References ]]
--- Shows a list of document highlights for a certain buffer.
---
- --@param bufnr buffer id
- --@param references List of `DocumentHighlight` objects to highlight
+ ---@param bufnr buffer id
+ ---@param references List of `DocumentHighlight` objects to highlight
---@see https://microsoft.github.io/language-server-protocol/specifications/specification-3-17/#documentHighlight
function M.buf_highlight_references(bufnr, references)
validate { bufnr = {bufnr, 'n', true} }
@@ -1505,24 +1505,24 @@ local position_sort = sort_by_key(function(v)
return {v.start.line, v.start.character}
end)
--- Gets the zero-indexed line from the given uri.
+--- Gets the zero-indexed line from the given uri.
+---@param uri string uri of the resource to get the line from
+---@param row number zero-indexed line number
+---@return string the line at row in filename
-- For non-file uris, we load the buffer and get the line.
-- If a loaded buffer exists, then that is used.
-- Otherwise we get the line using libuv which is a lot faster than loading the buffer.
---@param uri string uri of the resource to get the line from
---@param row number zero-indexed line number
---@return string the line at row in filename
function M.get_line(uri, row)
return M.get_lines(uri, { row })[row]
end
--- Gets the zero-indexed lines from the given uri.
+--- Gets the zero-indexed lines from the given uri.
+---@param uri string uri of the resource to get the lines from
+---@param rows number[] zero-indexed line numbers
+---@return table<number string> a table mapping rows to lines
-- For non-file uris, we load the buffer and get the lines.
-- If a loaded buffer exists, then that is used.
-- Otherwise we get the lines using libuv which is a lot faster than loading the buffer.
---@param uri string uri of the resource to get the lines from
---@param rows number[] zero-indexed line numbers
---@return table<number string> a table mapping rows to lines
function M.get_lines(uri, rows)
rows = type(rows) == "table" and rows or { rows }
@@ -1590,8 +1590,8 @@ end
--- Returns the items with the byte position calculated correctly and in sorted
--- order, for display in quickfix and location lists.
---
---@param locations (table) list of `Location`s or `LocationLink`s
---@returns (table) list of items
+---@param locations (table) list of `Location`s or `LocationLink`s
+---@returns (table) list of items
function M.locations_to_items(locations)
local items = {}
local grouped = setmetatable({}, {
@@ -1648,7 +1648,7 @@ end
--- Can be obtained with e.g. |vim.lsp.util.locations_to_items()|.
--- Defaults to current window.
---
---@param items (table) list of items
+---@param items (table) list of items
function M.set_loclist(items, win_id)
vim.fn.setloclist(win_id or 0, {}, ' ', {
title = 'Language Server';
@@ -1659,7 +1659,7 @@ end
--- Fills quickfix list with given list of items.
--- Can be obtained with e.g. |vim.lsp.util.locations_to_items()|.
---
---@param items (table) list of items
+---@param items (table) list of items
function M.set_qflist(items)
vim.fn.setqflist({}, ' ', {
title = 'Language Server';
@@ -1676,9 +1676,9 @@ end
--- Converts symbols to quickfix list items.
---
---@param symbols DocumentSymbol[] or SymbolInformation[]
+---@param symbols DocumentSymbol[] or SymbolInformation[]
function M.symbols_to_items(symbols, bufnr)
- --@private
+ ---@private
local function _symbols_to_items(_symbols, _items, _bufnr)
for _, symbol in ipairs(_symbols) do
if symbol.location then -- SymbolInformation type
@@ -1714,8 +1714,8 @@ function M.symbols_to_items(symbols, bufnr)
end
--- Removes empty lines from the beginning and end.
---@param lines (table) list of lines to trim
---@returns (table) trimmed list of lines
+---@param lines (table) list of lines to trim
+---@returns (table) trimmed list of lines
function M.trim_empty_lines(lines)
local start = 1
for i = 1, #lines do
@@ -1739,8 +1739,8 @@ end
---
--- CAUTION: Modifies the input in-place!
---
---@param lines (table) list of lines
---@returns (string) filetype or 'markdown' if it was unchanged.
+---@param lines (table) list of lines
+---@returns (string) filetype or 'markdown' if it was unchanged.
function M.try_trim_markdown_code_blocks(lines)
local language_id = lines[1]:match("^```(.*)")
if language_id then
@@ -1763,7 +1763,7 @@ function M.try_trim_markdown_code_blocks(lines)
end
local str_utfindex = vim.str_utfindex
---@private
+---@private
local function make_position_param()
local row, col = unpack(api.nvim_win_get_cursor(0))
row = row - 1
@@ -1777,8 +1777,8 @@ end
--- Creates a `TextDocumentPositionParams` object for the current buffer and cursor position.
---
---@returns `TextDocumentPositionParams` object
---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocumentPositionParams
+---@returns `TextDocumentPositionParams` object
+---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocumentPositionParams
function M.make_position_params()
return {
textDocument = M.make_text_document_params();
@@ -1791,7 +1791,7 @@ end
--- `textDocument/codeAction`, `textDocument/colorPresentation`,
--- `textDocument/rangeFormatting`.
---
---@returns { textDocument = { uri = `current_file_uri` }, range = { start =
+---@returns { textDocument = { uri = `current_file_uri` }, range = { start =
---`current_position`, end = `current_position` } }
function M.make_range_params()
local position = make_position_param()
@@ -1804,11 +1804,11 @@ end
--- Using the given range in the current buffer, creates an object that
--- is similar to |vim.lsp.util.make_range_params()|.
---
---@param start_pos ({number, number}, optional) mark-indexed position.
+---@param start_pos ({number, number}, optional) mark-indexed position.
---Defaults to the start of the last visual selection.
---@param end_pos ({number, number}, optional) mark-indexed position.
+---@param end_pos ({number, number}, optional) mark-indexed position.
---Defaults to the end of the last visual selection.
---@returns { textDocument = { uri = `current_file_uri` }, range = { start =
+---@returns { textDocument = { uri = `current_file_uri` }, range = { start =
---`start_position`, end = `end_position` } }
function M.make_given_range_params(start_pos, end_pos)
validate {
@@ -1844,23 +1844,23 @@ end
--- Creates a `TextDocumentIdentifier` object for the current buffer.
---
---@returns `TextDocumentIdentifier`
---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocumentIdentifier
+---@returns `TextDocumentIdentifier`
+---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocumentIdentifier
function M.make_text_document_params()
return { uri = vim.uri_from_bufnr(0) }
end
--- Create the workspace params
---@param added
---@param removed
+---@param added
+---@param removed
function M.make_workspace_params(added, removed)
return { event = { added = added; removed = removed; } }
end
--- Returns visual width of tabstop.
---
---@see |softtabstop|
---@param bufnr (optional, number): Buffer handle, defaults to current
---@returns (number) tabstop visual width
+---@see |softtabstop|
+---@param bufnr (optional, number): Buffer handle, defaults to current
+---@returns (number) tabstop visual width
function M.get_effective_tabstop(bufnr)
validate { bufnr = {bufnr, 'n', true} }
local bo = bufnr and vim.bo[bufnr] or vim.bo
@@ -1870,9 +1870,9 @@ end
--- Creates a `DocumentFormattingParams` object for the current buffer and cursor position.
---
---@param options Table with valid `FormattingOptions` entries
---@returns `DocumentFormattingParams` object
---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_formatting
+---@param options Table with valid `FormattingOptions` entries
+---@returns `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} }
options = vim.tbl_extend('keep', options or {}, {
@@ -1887,10 +1887,10 @@ end
--- Returns the UTF-32 and UTF-16 offsets for a position in a certain buffer.
---
---@param buf buffer id (0 for current)
---@param row 0-indexed line
---@param col 0-indexed byte offset in line
---@returns (number, number) UTF-32 and UTF-16 index of the character in line {row} column {col} in buffer {buf}
+---@param buf buffer id (0 for current)
+---@param row 0-indexed line
+---@param col 0-indexed byte offset in line
+---@returns (number, number) UTF-32 and UTF-16 index of the character in line {row} column {col} in buffer {buf}
function M.character_offset(bufnr, row, col)
local uri = vim.uri_from_bufnr(bufnr)
local line = M.get_line(uri, row)
@@ -1903,9 +1903,9 @@ end
--- Helper function to return nested values in language server settings
---
---@param settings a table of language server settings
---@param section a string indicating the field of the settings table
---@returns (table or string) The value of settings accessed via section
+---@param settings a table of language server settings
+---@param section a string indicating the field of the settings table
+---@returns (table or string) The value of settings accessed via section
function M.lookup_section(settings, section)
for part in vim.gsplit(section, '.', true) do
settings = settings[part]
@@ -1920,10 +1920,10 @@ end
--- Convert diagnostics grouped by bufnr to a list of items for use in the
--- quickfix or location list.
---
---@param diagnostics_by_bufnr table bufnr -> Diagnostic[]
---@param predicate an optional function to filter the diagnostics.
--- If present, only diagnostic items matching will be included.
---@return table (A list of items)
+---@param diagnostics_by_bufnr table bufnr -> Diagnostic[]
+---@param predicate an optional function to filter the diagnostics.
+--- If present, only diagnostic items matching will be included.
+---@return table (A list of items)
function M.diagnostics_to_items(diagnostics_by_bufnr, predicate)
local items = {}
for bufnr, diagnostics in pairs(diagnostics_by_bufnr or {}) do
diff --git a/runtime/lua/vim/shared.lua b/runtime/lua/vim/shared.lua
index 33c2b2c46c..032b2b2cb5 100644
--- a/runtime/lua/vim/shared.lua
+++ b/runtime/lua/vim/shared.lua
@@ -12,8 +12,8 @@ local vim = vim or {}
--- same functions as those in the input table. Userdata and threads are not
--- copied and will throw an error.
---
---@param orig Table to copy
---@returns New table of copied keys and (nested) values.
+---@param orig Table to copy
+---@returns New table of copied keys and (nested) values.
function vim.deepcopy(orig) end -- luacheck: no unused
vim.deepcopy = (function()
local function _id(v)
@@ -52,14 +52,14 @@ end)()
--- Splits a string at each instance of a separator.
---
---@see |vim.split()|
---@see https://www.lua.org/pil/20.2.html
---@see http://lua-users.org/wiki/StringLibraryTutorial
+---@see |vim.split()|
+---@see https://www.lua.org/pil/20.2.html
+---@see http://lua-users.org/wiki/StringLibraryTutorial
---
---@param s String to split
---@param sep Separator string or pattern
---@param plain If `true` use `sep` literally (passed to String.find)
---@returns Iterator over the split components
+---@param s String to split
+---@param sep Separator string or pattern
+---@param plain If `true` use `sep` literally (passed to String.find)
+---@returns Iterator over the split components
function vim.gsplit(s, sep, plain)
vim.validate{s={s,'s'},sep={sep,'s'},plain={plain,'b',true}}
@@ -101,12 +101,12 @@ end
--- split(x*yz*o, "*", true) --> {'x','yz','o'}
--- </pre>
--
---@see |vim.gsplit()|
+---@see |vim.gsplit()|
---
---@param s String to split
---@param sep Separator string or pattern
---@param plain If `true` use `sep` literally (passed to String.find)
---@returns List-like table of the split components.
+---@param s String to split
+---@param sep Separator string or pattern
+---@param plain If `true` use `sep` literally (passed to String.find)
+---@returns List-like table of the split components.
function vim.split(s,sep,plain)
local t={} for c in vim.gsplit(s, sep, plain) do table.insert(t,c) end
return t
@@ -115,10 +115,10 @@ end
--- Return a list of all keys used in a table.
--- However, the order of the return table of keys is not guaranteed.
---
---@see From https://github.com/premake/premake-core/blob/master/src/base/table.lua
+---@see From https://github.com/premake/premake-core/blob/master/src/base/table.lua
---
---@param t Table
---@returns list of keys
+---@param t Table
+---@returns list of keys
function vim.tbl_keys(t)
assert(type(t) == 'table', string.format("Expected table, got %s", type(t)))
@@ -132,8 +132,8 @@ end
--- Return a list of all values used in a table.
--- However, the order of the return table of values is not guaranteed.
---
---@param t Table
---@returns list of values
+---@param t Table
+---@returns list of values
function vim.tbl_values(t)
assert(type(t) == 'table', string.format("Expected table, got %s", type(t)))
@@ -146,8 +146,8 @@ end
--- Apply a function to all values of a table.
---
---@param func function or callable table
---@param t table
+---@param func function or callable table
+---@param t table
function vim.tbl_map(func, t)
vim.validate{func={func,'c'},t={t,'t'}}
@@ -160,8 +160,8 @@ end
--- Filter a table using a predicate function
---
---@param func function or callable table
---@param t table
+---@param func function or callable table
+---@param t table
function vim.tbl_filter(func, t)
vim.validate{func={func,'c'},t={t,'t'}}
@@ -176,9 +176,9 @@ end
--- Checks if a list-like (vector) table contains `value`.
---
---@param t Table to check
---@param value Value to compare
---@returns true if `t` contains `value`
+---@param t Table to check
+---@param value Value to compare
+---@returns true if `t` contains `value`
function vim.tbl_contains(t, value)
vim.validate{t={t,'t'}}
@@ -192,16 +192,16 @@ end
--- Checks if a table is empty.
---
---@see https://github.com/premake/premake-core/blob/master/src/base/table.lua
+---@see https://github.com/premake/premake-core/blob/master/src/base/table.lua
---
---@param t Table to check
+---@param t Table to check
function vim.tbl_isempty(t)
assert(type(t) == 'table', string.format("Expected table, got %s", type(t)))
return next(t) == nil
end
--- we only merge empty tables or tables that are not a list
---@private
+---@private
local function can_merge(v)
return type(v) == "table" and (vim.tbl_isempty(v) or not vim.tbl_islist(v))
end
@@ -242,26 +242,26 @@ end
--- Merges two or more map-like tables.
---
---@see |extend()|
+---@see |extend()|
---
---@param behavior Decides what to do if a key is found in more than one map:
+---@param behavior 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
---@param ... Two or more map-like tables.
+---@param ... Two or more map-like tables.
function vim.tbl_extend(behavior, ...)
return tbl_extend(behavior, false, ...)
end
--- Merges recursively two or more map-like tables.
---
---@see |tbl_extend()|
+---@see |tbl_extend()|
---
---@param behavior Decides what to do if a key is found in more than one map:
+---@param behavior 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
---@param ... Two or more map-like tables.
+---@param ... Two or more map-like tables.
function vim.tbl_deep_extend(behavior, ...)
return tbl_extend(behavior, true, ...)
end
@@ -292,7 +292,7 @@ end
--- `tbl_add_reverse_lookup { A = 1 } == { [1] = 'A', A = 1 }`
--
--Do note that it *modifies* the input.
---@param o table The table to add the reverse to.
+---@param o table The table to add the reverse to.
function vim.tbl_add_reverse_lookup(o)
local keys = vim.tbl_keys(o)
for _, k in ipairs(keys) do
@@ -309,13 +309,13 @@ end
---
--- NOTE: This mutates dst!
---
---@see |vim.tbl_extend()|
+---@see |vim.tbl_extend()|
---
---@param dst list which will be modified and appended to.
---@param src list from which values will be inserted.
---@param start Start index on src. defaults to 1
---@param finish Final index on src. defaults to #src
---@returns dst
+---@param dst list which will be modified and appended to.
+---@param src list from which values will be inserted.
+---@param start Start index on src. defaults to 1
+---@param finish Final index on src. defaults to #src
+---@returns dst
function vim.list_extend(dst, src, start, finish)
vim.validate {
dst = {dst, 't'};
@@ -332,10 +332,10 @@ end
--- Creates a copy of a list-like table such that any nested tables are
--- "unrolled" and appended to the result.
---
---@see From https://github.com/premake/premake-core/blob/master/src/base/table.lua
+---@see From https://github.com/premake/premake-core/blob/master/src/base/table.lua
---
---@param t List-like table
---@returns Flattened copy of the given list-like table.
+---@param t List-like table
+---@returns Flattened copy of the given list-like table.
function vim.tbl_flatten(t)
local result = {}
local function _tbl_flatten(_t)
@@ -359,8 +359,8 @@ end
--- |vim.empty_dict()| or returned as a dict-like |API| or Vimscript result,
--- for example from |rpcrequest()| or |vim.fn|.
---
---@param t Table
---@returns `true` if array-like table, else `false`.
+---@param t Table
+---@returns `true` if array-like table, else `false`.
function vim.tbl_islist(t)
if type(t) ~= 'table' then
return false
@@ -395,9 +395,9 @@ end
--- vim.tbl_count({ 1, 2 }) => 2
--- </pre>
---
---@see https://github.com/Tieske/Penlight/blob/master/lua/pl/tablex.lua
---@param t Table
---@returns Number that is the number of the value in table
+---@see https://github.com/Tieske/Penlight/blob/master/lua/pl/tablex.lua
+---@param t Table
+---@returns Number that is the number of the value in table
function vim.tbl_count(t)
vim.validate{t={t,'t'}}
@@ -408,10 +408,10 @@ end
--- Creates a copy of a table containing only elements from start to end (inclusive)
---
---@param list table table
---@param start integer Start range of slice
---@param finish integer End range of slice
---@returns Copy of table sliced from start to finish (inclusive)
+---@param list table table
+---@param start integer Start range of slice
+---@param finish integer End range of slice
+---@returns Copy of table sliced from start to finish (inclusive)
function vim.list_slice(list, start, finish)
local new_list = {}
for i = start or 1, finish or #list do
@@ -422,9 +422,9 @@ end
--- Trim whitespace (Lua pattern "%s") from both sides of a string.
---
---@see https://www.lua.org/pil/20.2.html
---@param s String to trim
---@returns String with whitespace removed from its beginning and end
+---@see https://www.lua.org/pil/20.2.html
+---@param s String to trim
+---@returns String with whitespace removed from its beginning and end
function vim.trim(s)
vim.validate{s={s,'s'}}
return s:match('^%s*(.*%S)') or ''
@@ -432,9 +432,9 @@ end
--- Escapes magic chars in a Lua pattern.
---
---@see https://github.com/rxi/lume
---@param s String to escape
---@returns %-escaped pattern string
+---@see https://github.com/rxi/lume
+---@param s String to escape
+---@returns %-escaped pattern string
function vim.pesc(s)
vim.validate{s={s,'s'}}
return s:gsub('[%(%)%.%%%+%-%*%?%[%]%^%$]', '%%%1')
@@ -442,9 +442,9 @@ end
--- Tests if `s` starts with `prefix`.
---
---@param s (string) a string
---@param prefix (string) a prefix
---@return (boolean) true if `prefix` is a prefix of s
+---@param s (string) a string
+---@param prefix (string) a prefix
+---@return (boolean) true if `prefix` is a prefix of s
function vim.startswith(s, prefix)
vim.validate { s = {s, 's'}; prefix = {prefix, 's'}; }
return s:sub(1, #prefix) == prefix
@@ -452,9 +452,9 @@ end
--- Tests if `s` ends with `suffix`.
---
---@param s (string) a string
---@param suffix (string) a suffix
---@return (boolean) true if `suffix` is a suffix of s
+---@param s (string) a string
+---@param suffix (string) a suffix
+---@return (boolean) true if `suffix` is a suffix of s
function vim.endswith(s, suffix)
vim.validate { s = {s, 's'}; suffix = {suffix, 's'}; }
return #suffix == 0 or s:sub(-#suffix) == suffix
@@ -486,7 +486,7 @@ end
--- => error('arg1: expected even number, got 3')
--- </pre>
---
---@param opt Map of parameter names to validations. Each key is a parameter
+---@param opt Map of parameter names to validations. 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
@@ -570,8 +570,8 @@ do
end
--- Returns true if object `f` can be called as a function.
---
---@param f Any object
---@return true if `f` is callable, else false
+---@param f Any object
+---@return true if `f` is callable, else false
function vim.is_callable(f)
if type(f) == 'function' then return true end
local m = getmetatable(f)
diff --git a/runtime/lua/vim/treesitter.lua b/runtime/lua/vim/treesitter.lua
index de997b2d86..66999c5f7f 100644
--- a/runtime/lua/vim/treesitter.lua
+++ b/runtime/lua/vim/treesitter.lua
@@ -20,6 +20,9 @@ setmetatable(M, {
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
end
})
@@ -28,9 +31,9 @@ setmetatable(M, {
---
--- It is not recommended to use this, use vim.treesitter.get_parser() instead.
---
---- @param bufnr The buffer the parser will be tied to
---- @param lang The language of the parser
---- @param opts Options to pass to the created language tree
+---@param bufnr The buffer the parser will be tied to
+---@param lang The language of the parser
+---@param opts Options to pass to the created language tree
function M._create_parser(bufnr, lang, opts)
language.require_language(lang)
if bufnr == 0 then
@@ -71,11 +74,11 @@ end
--- If needed this will create the parser.
--- Unconditionnally attach the provided callback
---
---- @param bufnr The buffer the parser should be tied to
---- @param lang The filetype of this parser
---- @param opts Options object to pass to the created language tree
+---@param bufnr The buffer the parser should be tied to
+---@param lang The filetype of this parser
+---@param opts Options object to pass to the created language tree
---
---- @returns The parser
+---@returns The parser
function M.get_parser(bufnr, lang, opts)
opts = opts or {}
@@ -97,9 +100,9 @@ end
--- Gets a string parser
---
---- @param str The string to parse
---- @param lang The language of this string
---- @param opts Options to pass to the created language tree
+---@param str The string to parse
+---@param lang The language of this string
+---@param opts Options to pass to the created language tree
function M.get_string_parser(str, lang, opts)
vim.validate {
str = { str, 'string' },
diff --git a/runtime/lua/vim/treesitter/highlighter.lua b/runtime/lua/vim/treesitter/highlighter.lua
index e003cf577a..22b528838c 100644
--- a/runtime/lua/vim/treesitter/highlighter.lua
+++ b/runtime/lua/vim/treesitter/highlighter.lua
@@ -85,8 +85,10 @@ function TSHighlighterQuery.new(lang, query_string)
hl = _link_default_highlight_once(lang .. hl, hl)
end
- rawset(table, capture, hl)
- return hl
+ local id = a.nvim_get_hl_id_by_name(hl)
+
+ rawset(table, capture, id)
+ return id
end
})
@@ -120,8 +122,8 @@ end
--- Creates a new highlighter using @param tree
---
---- @param tree The language tree to use for highlighting
---- @param opts Table used to configure the highlighter
+---@param tree The language tree to use for highlighting
+---@param opts Table used to configure the highlighter
--- - queries: Table to overwrite queries used by the highlighter
function TSHighlighter.new(tree, opts)
local self = setmetatable({}, TSHighlighter)
@@ -215,7 +217,7 @@ end
--- Gets the query used for @param lang
---
---- @param lang A language used by the highlighter.
+---@param lang A language used by the highlighter.
function TSHighlighter:get_query(lang)
if not self._queries[lang] then
self._queries[lang] = TSHighlighterQuery.new(lang)
diff --git a/runtime/lua/vim/treesitter/language.lua b/runtime/lua/vim/treesitter/language.lua
index 6dc37c7848..89ddd6cd5a 100644
--- a/runtime/lua/vim/treesitter/language.lua
+++ b/runtime/lua/vim/treesitter/language.lua
@@ -6,9 +6,9 @@ local M = {}
---
--- Parsers are searched in the `parser` runtime directory.
---
---- @param lang The language the parser should parse
---- @param path Optional path the parser is located at
---- @param silent Don't throw an error if language not found
+---@param lang The language the parser should parse
+---@param path Optional path the parser is located at
+---@param silent Don't throw an error if language not found
function M.require_language(lang, path, silent)
if vim._ts_has_language(lang) then
return true
@@ -40,7 +40,7 @@ end
---
--- Inspecting provides some useful informations on the language like node names, ...
---
---- @param lang The language.
+---@param lang The language.
function M.inspect_language(lang)
M.require_language(lang)
return vim._ts_inspect_language(lang)
diff --git a/runtime/lua/vim/treesitter/languagetree.lua b/runtime/lua/vim/treesitter/languagetree.lua
index 899d90e464..7e392f72a4 100644
--- a/runtime/lua/vim/treesitter/languagetree.lua
+++ b/runtime/lua/vim/treesitter/languagetree.lua
@@ -9,12 +9,12 @@ LanguageTree.__index = LanguageTree
--- The language can contain child languages with in its range,
--- hence the tree.
---
---- @param source Can be a bufnr or a string of text to parse
---- @param lang The language this tree represents
---- @param opts Options table
---- @param opts.injections A table of language to injection query strings.
---- This is useful for overriding the built-in runtime file
---- searching for the injection language query per language.
+---@param source Can be a bufnr or a string of text to parse
+---@param lang The language this tree represents
+---@param opts Options table
+---@param opts.injections A table of language to injection query strings.
+--- This is useful for overriding the built-in runtime file
+--- searching for the injection language query per language.
function LanguageTree.new(source, lang, opts)
language.require_language(lang)
opts = opts or {}
@@ -171,8 +171,8 @@ end
--- Invokes the callback for each LanguageTree and it's children recursively
---
---- @param fn The function to invoke. This is invoked with arguments (tree: LanguageTree, lang: string)
---- @param include_self Whether to include the invoking tree in the results.
+---@param fn The function to invoke. This is invoked with arguments (tree: LanguageTree, lang: string)
+---@param include_self Whether to include the invoking tree in the results.
function LanguageTree:for_each_child(fn, include_self)
if include_self then
fn(self, self._lang)
@@ -187,8 +187,8 @@ end
---
--- Note, this includes the invoking language tree's trees as well.
---
---- @param fn The callback to invoke. The callback is invoked with arguments
---- (tree: TSTree, languageTree: LanguageTree)
+---@param fn The callback to invoke. The callback is invoked with arguments
+--- (tree: TSTree, languageTree: LanguageTree)
function LanguageTree:for_each_tree(fn)
for _, tree in ipairs(self._trees) do
fn(tree, self)
@@ -203,7 +203,7 @@ end
---
--- If the language already exists as a child, it will first be removed.
---
---- @param lang The language to add.
+---@param lang The language to add.
function LanguageTree:add_child(lang)
if self._children[lang] then
self:remove_child(lang)
@@ -219,7 +219,7 @@ end
--- Removes a child language from this tree.
---
---- @param lang The language to remove.
+---@param lang The language to remove.
function LanguageTree:remove_child(lang)
local child = self._children[lang]
@@ -259,7 +259,7 @@ end
---
--- Note, this call invalidates the tree and requires it to be parsed again.
---
---- @param regions A list of regions this tree should manage and parse.
+---@param regions A list of regions this tree should manage and parse.
function LanguageTree:set_included_regions(regions)
-- TODO(vigoux): I don't think string parsers are useful for now
if type(self._source) == "number" then
@@ -299,7 +299,7 @@ end
---
--- TODO: Allow for an offset predicate to tailor the injection range
--- instead of using the entire nodes range.
---- @private
+---@private
function LanguageTree:_get_injections()
if not self._injection_query then return {} end
@@ -449,7 +449,7 @@ function LanguageTree:_on_detach(...)
end
--- Registers callbacks for the parser
---- @param cbs An `nvim_buf_attach`-like table argument with the following keys :
+---@param cbs An `nvim_buf_attach`-like table argument with the following keys :
--- `on_bytes` : see `nvim_buf_attach`, but this will be called _after_ the parsers callback.
--- `on_changedtree` : a callback that will be called every time the tree has syntactical changes.
--- it will only be passed one argument, that is a table of the ranges (as node ranges) that
@@ -497,7 +497,7 @@ end
---
--- This goes down the tree to recursively check childs.
---
---- @param range A range, that is a `{ start_line, start_col, end_line, end_col }` table.
+---@param range A range, that is a `{ start_line, start_col, end_line, end_col }` table.
function LanguageTree:contains(range)
for _, tree in pairs(self._trees) do
if tree_contains(tree, range) then
@@ -510,7 +510,7 @@ end
--- Gets the appropriate language that contains @param range
---
---- @param range A text range, see |LanguageTree:contains|
+---@param range A text range, see |LanguageTree:contains|
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 4ecd91d295..66da179ea3 100644
--- a/runtime/lua/vim/treesitter/query.lua
+++ b/runtime/lua/vim/treesitter/query.lua
@@ -36,9 +36,9 @@ end
--- Gets the list of files used to make up a query
---
---- @param lang The language
---- @param query_name The name of the query to load
---- @param is_included Internal parameter, most of the time left as `nil`
+---@param lang The language
+---@param query_name The name of the query to load
+---@param is_included Internal parameter, most of the time left as `nil`
function M.get_query_files(lang, query_name, is_included)
local query_path = string.format('queries/%s/%s.scm', lang, query_name)
local lang_files = dedupe_files(a.nvim_get_runtime_file(query_path, true))
@@ -112,19 +112,19 @@ local explicit_queries = setmetatable({}, {
--- This allows users to override any runtime files and/or configuration
--- set by plugins.
---
---- @param lang string: The language to use for the query
---- @param query_name string: The name of the query (i.e. "highlights")
---- @param text string: The query text (unparsed).
+---@param lang string: The language to use for the query
+---@param query_name string: The name of the query (i.e. "highlights")
+---@param text string: The query text (unparsed).
function M.set_query(lang, query_name, text)
explicit_queries[lang][query_name] = M.parse_query(lang, text)
end
--- Returns the runtime query {query_name} for {lang}.
---
---- @param lang The language to use for the query
---- @param query_name The name of the query (i.e. "highlights")
+---@param lang The language to use for the query
+---@param query_name The name of the query (i.e. "highlights")
---
---- @return The corresponding query, parsed.
+---@return The corresponding query, parsed.
function M.get_query(lang, query_name)
if explicit_queries[lang][query_name] then
return explicit_queries[lang][query_name]
@@ -151,10 +151,10 @@ end
--- -` info.captures` also points to `captures`.
--- - `info.patterns` contains information about predicates.
---
---- @param lang The language
---- @param query A string containing the query (s-expr syntax)
+---@param lang The language
+---@param query A string containing the query (s-expr syntax)
---
---- @returns The query
+---@returns The query
function M.parse_query(lang, query)
language.require_language(lang)
local self = setmetatable({}, Query)
@@ -168,8 +168,8 @@ end
--- Gets the text corresponding to a given node
---
---- @param node the node
---- @param bsource The buffer or string from which the node is extracted
+---@param node the node
+---@param bsource The buffer or string from which the node is extracted
function M.get_node_text(node, source)
local start_row, start_col, start_byte = node:start()
local end_row, end_col, end_byte = node:end_()
@@ -327,9 +327,9 @@ local directive_handlers = {
--- Adds a new predicate to be used in queries
---
---- @param name the name of the predicate, without leading #
---- @param handler the handler function to be used
---- signature will be (match, pattern, bufnr, predicate)
+---@param name the name of the predicate, without leading #
+---@param handler the handler function to be used
+--- signature will be (match, pattern, bufnr, predicate)
function M.add_predicate(name, handler, force)
if predicate_handlers[name] and not force then
error(string.format("Overriding %s", name))
@@ -340,9 +340,9 @@ end
--- Adds a new directive to be used in queries
---
---- @param name the name of the directive, without leading #
---- @param handler the handler function to be used
---- signature will be (match, pattern, bufnr, predicate)
+---@param name the name of the directive, without leading #
+---@param handler the handler function to be used
+--- signature will be (match, pattern, bufnr, predicate)
function M.add_directive(name, handler, force)
if directive_handlers[name] and not force then
error(string.format("Overriding %s", name))
@@ -351,12 +351,12 @@ function M.add_directive(name, handler, force)
directive_handlers[name] = handler
end
---- @return The list of supported directives.
+---@return The list of supported directives.
function M.list_directives()
return vim.tbl_keys(directive_handlers)
end
---- @return The list of supported predicates.
+---@return The list of supported predicates.
function M.list_predicates()
return vim.tbl_keys(predicate_handlers)
end
@@ -465,13 +465,13 @@ end
--- end
--- </pre>
---
---- @param node The node under which the search will occur
---- @param source The source buffer or string to exctract text from
---- @param start The starting line of the search
---- @param stop The stopping line of the search (end-exclusive)
+---@param node The node under which the search will occur
+---@param source The source buffer or string to exctract text from
+---@param start The starting line of the search
+---@param stop The stopping line of the search (end-exclusive)
---
---- @returns The matching capture id
---- @returns The captured node
+---@returns The matching capture id
+---@returns The captured node
function Query:iter_captures(node, source, start, stop)
if type(source) == "number" and source == 0 then
source = vim.api.nvim_get_current_buf()
@@ -522,13 +522,13 @@ end
--- end
--- </pre>
---
---- @param node The node under which the search will occur
---- @param source The source buffer or string to search
---- @param start The starting line of the search
---- @param stop The stopping line of the search (end-exclusive)
+---@param node The node under which the search will occur
+---@param source The source buffer or string to search
+---@param start The starting line of the search
+---@param stop The stopping line of the search (end-exclusive)
---
---- @returns The matching pattern id
---- @returns The matching match
+---@returns The matching pattern id
+---@returns The matching match
function Query:iter_matches(node, source, start, stop)
if type(source) == "number" and source == 0 then
source = vim.api.nvim_get_current_buf()
diff --git a/runtime/lua/vim/uri.lua b/runtime/lua/vim/uri.lua
index 82c9a31464..a3e79a0f2b 100644
--- a/runtime/lua/vim/uri.lua
+++ b/runtime/lua/vim/uri.lua
@@ -9,7 +9,7 @@ do
local schar = string.char
--- Convert hex to char
- --@private
+ ---@private
local function hex_to_char(hex)
return schar(tonumber(hex, 16))
end
@@ -38,7 +38,7 @@ do
tohex = function(b) return string.format("%02x", b) end
end
- --@private
+ ---@private
local function percent_encode_char(char)
return "%"..tohex(sbyte(char), 2)
end
@@ -50,14 +50,14 @@ do
end
---@private
+---@private
local function is_windows_file_uri(uri)
return uri:match('^file:/+[a-zA-Z]:') ~= nil
end
--- Get a URI from a file path.
---@param path (string): Path to file
---@return URI
+---@param path (string): Path to file
+---@return URI
local function uri_from_fname(path)
local volume_path, fname = path:match("^([a-zA-Z]:)(.*)")
local is_windows = volume_path ~= nil
@@ -77,8 +77,8 @@ end
local URI_SCHEME_PATTERN = '^([a-zA-Z]+[a-zA-Z0-9+-.]*):.*'
--- Get a URI from a bufnr
---@param bufnr (number): Buffer number
---@return URI
+---@param bufnr (number): Buffer number
+---@return URI
local function uri_from_bufnr(bufnr)
local fname = vim.api.nvim_buf_get_name(bufnr)
local scheme = fname:match(URI_SCHEME_PATTERN)
@@ -90,8 +90,8 @@ local function uri_from_bufnr(bufnr)
end
--- Get a filename from a URI
---@param uri (string): The URI
---@return Filename
+---@param uri (string): The URI
+---@return Filename
local function uri_to_fname(uri)
local scheme = assert(uri:match(URI_SCHEME_PATTERN), 'URI must contain a scheme: ' .. uri)
if scheme ~= 'file' then
@@ -109,9 +109,9 @@ local function uri_to_fname(uri)
end
--- Return or create a buffer for a uri.
---@param uri (string): The URI
---@return bufnr.
---@note Creates buffer but does not load it
+---@param uri (string): The URI
+---@return bufnr.
+---@note Creates buffer but does not load it
local function uri_to_bufnr(uri)
local scheme = assert(uri:match(URI_SCHEME_PATTERN), 'URI must contain a scheme: ' .. uri)
if scheme == 'file' then
diff --git a/runtime/plugin/man.vim b/runtime/plugin/man.vim
index 689aa32ef3..f814fbad3b 100644
--- a/runtime/plugin/man.vim
+++ b/runtime/plugin/man.vim
@@ -6,7 +6,7 @@ endif
let g:loaded_man = 1
command! -bang -bar -range=-1 -complete=customlist,man#complete -nargs=* Man
- \ if <bang>0 | set ft=man |
+ \ if <bang>0 | call man#init_pager() |
\ else | call man#open_page(<count>, <q-mods>, <f-args>) | endif
augroup man
diff --git a/runtime/syntax/julia.vim b/runtime/syntax/julia.vim
new file mode 100644
index 0000000000..2c2d36a97a
--- /dev/null
+++ b/runtime/syntax/julia.vim
@@ -0,0 +1,550 @@
+" Vim syntax file
+" Language: julia
+" Maintainer: Carlo Baldassi <carlobaldassi@gmail.com>
+" Homepage: https://github.com/JuliaEditorSupport/julia-vim
+" Last Change: 2013 feb 11
+
+if version < 600
+ syntax clear
+elseif exists("b:current_syntax")
+ finish
+endif
+
+let s:cpo_save = &cpo
+set cpo&vim
+
+if version < 704
+ " this is used to disable regex syntax like `\@3<='
+ " on older vim versions
+ function! s:d(x)
+ return ''
+ endfunction
+else
+ function! s:d(x)
+ return string(a:x)
+ endfunction
+endif
+
+scriptencoding utf-8
+
+let s:julia_spellcheck_strings = get(g:, "julia_spellcheck_strings", 0)
+let s:julia_spellcheck_docstrings = get(g:, "julia_spellcheck_docstrings", 1)
+let s:julia_spellcheck_comments = get(g:, "julia_spellcheck_comments", 1)
+
+let s:julia_highlight_operators = get(g:, "julia_highlight_operators", 1)
+
+" List of characters, up to \UFF, which cannot be used in identifiers.
+" (It includes operator characters; we don't consider them identifiers.)
+" This is used mostly in lookbehinds with `\@<=`, e.g. when we need to check
+" that that we're not in the middle of an identifier.
+" It doesn't include a few characters (spaces and all closing parentheses)
+" because those may or may not be valid in the lookbehind on a case-by-case
+" basis.
+let s:nonid_chars = '\U00-\U08' . '\U0A-\U1F'
+ \ . '\U21-\U28' . '\U2A-\U2F' . '\U3A-\U40' . '\U5B-\U5E' . '\U60' . '\U7B\U7C'
+ \ . '\U7E-\UA1' . '\UA7\UA8' . '\UAB-\UAD' . '\UAF\UB1\UB4' . '\UB6-\UB8' . '\UBB\UBF' . '\UD7\UF7'
+
+" The complete list
+let s:nonidS_chars = '[:space:])\U5D}' . s:nonid_chars
+
+
+" List of all valid operator chars up to \UFF (NOTE: they must all be included
+" in s:nonidS_chars, so that if we include that, then this is redundant)
+" It does not include '!' since it can be used in an identifier.
+" The list contains the following characters: '%&*+-/<=>\\^|~¬±×÷'
+let s:op_chars = '\U25\U26\U2A\U2B\U2D\U2F\U3C-\U3E\U5C\U5E\U7C\U7E\UAC\UB1\UD7\UF7'
+
+" List of all valid operator chars above \UFF
+" Written with ranges for performance reasons
+" The list contains the following characters: '…⁝⅋←↑→↓↔↚↛↜↝↞↠↢↣↤↦↩↪↫↬↮↶↷↺↻↼↽⇀⇁⇄⇆⇇⇉⇋⇌⇍⇎⇏⇐⇒⇔⇚⇛⇜⇝⇠⇢⇴⇵⇶⇷⇸⇹⇺⇻⇼⇽⇾⇿∈∉∊∋∌∍∓∔∗∘∙√∛∜∝∤∥∦∧∨∩∪∷∸∺∻∽∾≀≁≂≃≄≅≆≇≈≉≊≋≌≍≎≏≐≑≒≓≔≕≖≗≘≙≚≛≜≝≞≟≠≡≢≣≤≥≦≧≨≩≪≫≬≭≮≯≰≱≲≳≴≵≶≷≸≹≺≻≼≽≾≿⊀⊁⊂⊃⊄⊅⊆⊇⊈⊉⊊⊋⊍⊎⊏⊐⊑⊒⊓⊔⊕⊖⊗⊘⊙⊚⊛⊜⊞⊟⊠⊡⊢⊣⊩⊬⊮⊰⊱⊲⊳⊴⊵⊶⊷⊻⊼⊽⋄⋅⋆⋇⋉⋊⋋⋌⋍⋎⋏⋐⋑⋒⋓⋕⋖⋗⋘⋙⋚⋛⋜⋝⋞⋟⋠⋡⋢⋣⋤⋥⋦⋧⋨⋩⋪⋫⋬⋭⋮⋯⋰⋱⋲⋳⋴⋵⋶⋷⋸⋹⋺⋻⋼⋽⋾⋿⌿▷⟂⟈⟉⟑⟒⟕⟖⟗⟰⟱⟵⟶⟷⟹⟺⟻⟼⟽⟾⟿⤀⤁⤂⤃⤄⤅⤆⤇⤈⤉⤊⤋⤌⤍⤎⤏⤐⤑⤒⤓⤔⤕⤖⤗⤘⤝⤞⤟⤠⥄⥅⥆⥇⥈⥉⥊⥋⥌⥍⥎⥏⥐⥑⥒⥓⥔⥕⥖⥗⥘⥙⥚⥛⥜⥝⥞⥟⥠⥡⥢⥣⥤⥥⥦⥧⥨⥩⥪⥫⥬⥭⥮⥯⥰⦷⦸⦼⦾⦿⧀⧁⧡⧣⧤⧥⧴⧶⧷⧺⧻⨇⨈⨝⨟⨢⨣⨤⨥⨦⨧⨨⨩⨪⨫⨬⨭⨮⨰⨱⨲⨳⨴⨵⨶⨷⨸⨹⨺⨻⨼⨽⩀⩁⩂⩃⩄⩅⩊⩋⩌⩍⩎⩏⩐⩑⩒⩓⩔⩕⩖⩗⩘⩚⩛⩜⩝⩞⩟⩠⩡⩢⩣⩦⩧⩪⩫⩬⩭⩮⩯⩰⩱⩲⩳⩴⩵⩶⩷⩸⩹⩺⩻⩼⩽⩾⩿⪀⪁⪂⪃⪄⪅⪆⪇⪈⪉⪊⪋⪌⪍⪎⪏⪐⪑⪒⪓⪔⪕⪖⪗⪘⪙⪚⪛⪜⪝⪞⪟⪠⪡⪢⪣⪤⪥⪦⪧⪨⪩⪪⪫⪬⪭⪮⪯⪰⪱⪲⪳⪴⪵⪶⪷⪸⪹⪺⪻⪼⪽⪾⪿⫀⫁⫂⫃⫄⫅⫆⫇⫈⫉⫊⫋⫌⫍⫎⫏⫐⫑⫒⫓⫔⫕⫖⫗⫘⫙⫛⫷⫸⫹⫺⬰⬱⬲⬳⬴⬵⬶⬷⬸⬹⬺⬻⬼⬽⬾⬿⭀⭁⭂⭃⭄⭇⭈⭉⭊⭋⭌←↑→↓'
+let s:op_chars_wc = '\U2026\U205D\U214B\U2190-\U2194\U219A-\U219E\U21A0\U21A2-\U21A4\U21A6\U21A9-\U21AC\U21AE\U21B6\U21B7\U21BA-\U21BD\U21C0\U21C1\U21C4\U21C6\U21C7\U21C9\U21CB-\U21D0\U21D2\U21D4\U21DA-\U21DD\U21E0\U21E2\U21F4-\U21FF\U2208-\U220D\U2213\U2214\U2217-\U221D\U2224-\U222A\U2237\U2238\U223A\U223B\U223D\U223E\U2240-\U228B\U228D-\U229C\U229E-\U22A3\U22A9\U22AC\U22AE\U22B0-\U22B7\U22BB-\U22BD\U22C4-\U22C7\U22C9-\U22D3\U22D5-\U22FF\U233F\U25B7\U27C2\U27C8\U27C9\U27D1\U27D2\U27D5-\U27D7\U27F0\U27F1\U27F5-\U27F7\U27F9-\U27FF\U2900-\U2918\U291D-\U2920\U2944-\U2970\U29B7\U29B8\U29BC\U29BE-\U29C1\U29E1\U29E3-\U29E5\U29F4\U29F6\U29F7\U29FA\U29FB\U2A07\U2A08\U2A1D\U2A1F\U2A22-\U2A2E\U2A30-\U2A3D\U2A40-\U2A45\U2A4A-\U2A58\U2A5A-\U2A63\U2A66\U2A67\U2A6A-\U2AD9\U2ADB\U2AF7-\U2AFA\U2B30-\U2B44\U2B47-\U2B4C\UFFE9-\UFFEC'
+
+" Full operators regex
+let s:operators = '\%(' . '\.\%([-+*/^÷%|&⊻]\|//\|\\\|>>\|>>>\?\)\?=' .
+ \ '\|' . '[:<>]=\|||\|&&\||>\|<|\|[<>:]:\|<<\|>>>\?\|//\|[-=]>\|\.\.\.\?' .
+ \ '\|' . '\.\?[!' . s:op_chars . s:op_chars_wc . ']' .
+ \ '\)'
+
+
+" Characters that can be used to start an identifier. Above \UBF we don't
+" bother checking. (If a UTF8 operator is used, it will take precedence anyway.)
+let s:id_charsH = '\%([A-Za-z_\UA2-\UA6\UA9\UAA\UAE\UB0\UB5\UBA]\|[^\U00-\UBF]\)'
+" Characters that can appear in an identifier, starting in 2nd position. Above
+" \UBF we check for operators since we need to stop the identifier if one
+" appears. We don't check for invalid characters though.
+let s:id_charsW = '\%([0-9A-Za-z_!\UA2-\UA6\UA9\UAA\UAE-\UB0\UB2-\UB5\UB8-\UBA\UBC-\UBE]\|[^\U00-\UBF]\@=[^' . s:op_chars_wc . ']\)'
+
+" A valid julia identifier, more or less
+let s:idregex = '\%(' . s:id_charsH . s:id_charsW . '*\)'
+
+
+
+syn case match
+
+syntax cluster juliaExpressions contains=@juliaParItems,@juliaStringItems,@juliaKeywordItems,@juliaBlocksItems,@juliaTypesItems,@juliaConstItems,@juliaMacroItems,@juliaSymbolItems,@juliaOperatorItems,@juliaNumberItems,@juliaCommentItems,@juliaErrorItems,@juliaSyntaxRegions
+syntax cluster juliaExprsPrintf contains=@juliaExpressions,@juliaPrintfItems
+syntax cluster juliaExprsNodot contains=@juliaParItems,@juliaStringItems,@juliaMacroItems,@juliaSymbolItems,@juliaOperatorItems,@juliaCommentItems,juliaIdSymbol
+
+syntax cluster juliaParItems contains=juliaParBlock,juliaSqBraIdxBlock,juliaSqBraBlock,juliaCurBraBlock,juliaQuotedParBlock,juliaQuotedQMarkPar
+syntax cluster juliaKeywordItems contains=juliaKeyword,juliaWhereKeyword,juliaImportLine,juliaInfixKeyword,juliaRepKeyword
+syntax cluster juliaBlocksItems contains=juliaConditionalBlock,juliaWhileBlock,juliaForBlock,juliaBeginBlock,juliaFunctionBlock,juliaMacroBlock,juliaQuoteBlock,juliaTypeBlock,juliaImmutableBlock,juliaExceptionBlock,juliaLetBlock,juliaDoBlock,juliaModuleBlock,juliaStructBlock,juliaMutableStructBlock,juliaAbstractBlock,juliaPrimitiveBlock
+syntax cluster juliaTypesItems contains=juliaBaseTypeBasic,juliaBaseTypeNum,juliaBaseTypeC,juliaBaseTypeError,juliaBaseTypeIter,juliaBaseTypeString,juliaBaseTypeArray,juliaBaseTypeDict,juliaBaseTypeSet,juliaBaseTypeIO,juliaBaseTypeProcess,juliaBaseTypeRange,juliaBaseTypeRegex,juliaBaseTypeFact,juliaBaseTypeFact,juliaBaseTypeSort,juliaBaseTypeRound,juliaBaseTypeSpecial,juliaBaseTypeRandom,juliaBaseTypeDisplay,juliaBaseTypeTime,juliaBaseTypeOther
+
+syntax cluster juliaConstItems contains=juliaConstNum,juliaConstBool,juliaConstEnv,juliaConstMMap,juliaConstC,juliaConstGeneric,juliaConstIO,juliaPossibleEuler
+
+syntax cluster juliaMacroItems contains=juliaPossibleMacro,juliaDollarVar,juliaDollarPar,juliaDollarSqBra
+syntax cluster juliaSymbolItems contains=juliaPossibleSymbol
+syntax cluster juliaNumberItems contains=juliaNumbers
+syntax cluster juliaStringItems contains=juliaChar,juliaString,juliabString,juliasString,juliaShellString,juliaDocString,juliaRegEx
+syntax cluster juliaPrintfItems contains=juliaPrintfParBlock,juliaPrintfString
+syntax cluster juliaOperatorItems contains=juliaOperator,juliaRangeOperator,juliaCTransOperator,juliaTernaryRegion,juliaColon,juliaSemicolon,juliaComma
+syntax cluster juliaCommentItems contains=juliaCommentL,juliaCommentM
+syntax cluster juliaErrorItems contains=juliaErrorPar,juliaErrorEnd,juliaErrorElse,juliaErrorCatch,juliaErrorFinally
+
+syntax cluster juliaSyntaxRegions contains=juliaIdSymbol,juliaTypeOperatorR2,juliaTypeOperatorR3,juliaWhereR,juliaDotted
+
+syntax cluster juliaSpellcheckStrings contains=@spell
+syntax cluster juliaSpellcheckDocStrings contains=@spell
+syntax cluster juliaSpellcheckComments contains=@spell
+
+if !s:julia_spellcheck_docstrings
+ syntax cluster juliaSpellcheckDocStrings remove=@spell
+endif
+if !s:julia_spellcheck_strings
+ syntax cluster juliaSpellcheckStrings remove=@spell
+endif
+if !s:julia_spellcheck_comments
+ syntax cluster juliaSpellcheckComments remove=@spell
+endif
+
+syntax match juliaSemicolon display ";"
+syntax match juliaComma display ","
+syntax match juliaColon display ":"
+
+" A dot can introduce a sort of 'environment' such that words after it are not
+" recognized as keywords. This has low precedence so that it can be overridden
+" by operators
+syntax match juliaDotted transparent "\.\s*[^])}.]" contains=@juliaExprsNodot
+syntax match juliaDottedT contained transparent "\.\s*[^])}.]" contains=@juliaExprsNodot,juliaType
+
+syntax match juliaErrorPar display "[])}]"
+syntax match juliaErrorEnd display "\<end\>"
+syntax match juliaErrorElse display "\<\%(else\|elseif\)\>"
+syntax match juliaErrorCatch display "\<catch\>"
+syntax match juliaErrorFinally display "\<finally\>"
+syntax match juliaErrorSemicol display contained ";"
+
+syntax region juliaParBlock matchgroup=juliaParDelim start="(" end=")" contains=@juliaExpressions,juliaComprehensionFor
+syntax region juliaParBlockInRange matchgroup=juliaParDelim contained start="(" end=")" contains=@juliaExpressions,juliaParBlockInRange,juliaRangeKeyword,juliaComprehensionFor
+syntax region juliaSqBraIdxBlock matchgroup=juliaParDelim start="\[" end="\]" contains=@juliaExpressions,juliaParBlockInRange,juliaRangeKeyword,juliaComprehensionFor,juliaSymbolS,juliaQuotedParBlockS,juliaQuotedQMarkParS
+exec 'syntax region juliaSqBraBlock matchgroup=juliaParDelim start="\%(^\|\s\|' . s:operators . '\)\@'.s:d(3).'<=\[" end="\]" contains=@juliaExpressions,juliaComprehensionFor,juliaSymbolS,juliaQuotedParBlockS,juliaQuotedQMarkParS'
+syntax region juliaCurBraBlock matchgroup=juliaParDelim start="{" end="}" contains=juliaType,juliaDottedT,@juliaExpressions
+
+exec 'syntax match juliaType contained "\%(' . s:idregex . '\.\)*\zs' . s:idregex . '"'
+
+" This is a generic identifier followed by some symbol, either a type
+" operator (<: or >:), or an open parenthesis, or an open curly bracket.
+" It's used to recognize one of the contained regions looking for identifiers
+" only once. Once recognized, those regions no longer need to use the
+" expensive s:idregex.
+exec 'syntax match juliaIdSymbol transparent "' . s:idregex . '\%(\s*[<>]:\|\.\?(\|{\|\"\)\@=" contains=juliaFunctionCall,juliaParamType,juliaStringPrefixed,juliaTypeOperatorR1'
+
+syntax match juliaFunctionCall contained "[^{([:space:]<>\"]\+(\@=" nextgroup=juliaParBlock
+
+exec 'syntax match juliaFunctionDef contained transparent "\%(\<\%(function\|macro\)\)\@'.s:d(8).'<=\s\+\zs' . s:idregex . '\%(\.' . s:idregex . '\)*\ze\s*\%((\|\send\>\|$\)" contains=juliaFunctionName'
+exec 'syntax match juliaFunctionName contained "\%(\<\%(function\|macro\)\s\+\)\@'.s:d(20).'<=\%(' . s:idregex . '\.\)*\zs' . s:idregex . '"'
+
+exec 'syntax match juliaStructR contained transparent "\%(\<\%(\%(mutable\s\+\)\?struct\|\%(abstract\|primitive\)\s\+type\)\s\+\)\@'.s:d(20).'<=\%(' . s:idregex . '\.\)*' . s:idregex . '\>\(\s*(\)\@!" contains=juliaType'
+
+syntax match juliaKeyword display "\<\%(return\|local\|global\|const\)\>"
+syntax match juliaInfixKeyword display "\%(=\s*\)\@<!\<\%(in\|isa\)\>\S\@!\%(\s*=\)\@!"
+
+" The import/export/using keywords introduce a sort of special parsing
+" environment with its own rules
+exec 'syntax region juliaImportLine matchgroup=juliaKeyword excludenl start="\<\%(import\|using\|export\)\>" skip="\%(\%(\<\%(import\|using\|export\)\>\)\|^\)\@'.s:d(6).'<=$" end="$" end="\%([])}]\)\@=" contains=@juliaExpressions,juliaAsKeyword,@juliaContinuationItems,juliaMacroName'
+syntax match juliaAsKeyword display contained "\<as\>"
+
+syntax match juliaRepKeyword display "\<\%(break\|continue\)\>"
+syntax region juliaConditionalBlock matchgroup=juliaConditional start="\<if\>" end="\<end\>" contains=@juliaExpressions,juliaConditionalEIBlock,juliaConditionalEBlock fold
+syntax region juliaConditionalEIBlock matchgroup=juliaConditional transparent contained start="\<elseif\>" end="\<\%(end\|else\|elseif\)\>"me=s-1 contains=@juliaExpressions,juliaConditionalEIBlock,juliaConditionalEBlock
+syntax region juliaConditionalEBlock matchgroup=juliaConditional transparent contained start="\<else\>" end="\<end\>"me=s-1 contains=@juliaExpressions
+syntax region juliaWhileBlock matchgroup=juliaRepeat start="\<while\>" end="\<end\>" contains=@juliaExpressions fold
+syntax region juliaForBlock matchgroup=juliaRepeat start="\<for\>" end="\<end\>" contains=@juliaExpressions,juliaOuter fold
+syntax region juliaBeginBlock matchgroup=juliaBlKeyword start="\<begin\>" end="\<end\>" contains=@juliaExpressions fold
+syntax region juliaFunctionBlock matchgroup=juliaBlKeyword start="\<function\>" end="\<end\>" contains=@juliaExpressions,juliaFunctionDef fold
+syntax region juliaMacroBlock matchgroup=juliaBlKeyword start="\<macro\>" end="\<end\>" contains=@juliaExpressions,juliaFunctionDef fold
+syntax region juliaQuoteBlock matchgroup=juliaBlKeyword start="\<quote\>" end="\<end\>" contains=@juliaExpressions fold
+syntax region juliaStructBlock matchgroup=juliaBlKeyword start="\<struct\>" end="\<end\>" contains=@juliaExpressions,juliaStructR fold
+syntax region juliaMutableStructBlock matchgroup=juliaBlKeyword start="\<mutable\s\+struct\>" end="\<end\>" contains=@juliaExpressions,juliaStructR fold
+syntax region juliaLetBlock matchgroup=juliaBlKeyword start="\<let\>" end="\<end\>" contains=@juliaExpressions fold
+syntax region juliaDoBlock matchgroup=juliaBlKeyword start="\<do\>" end="\<end\>" contains=@juliaExpressions fold
+syntax region juliaModuleBlock matchgroup=juliaBlKeyword start="\<\%(bare\)\?module\>" end="\<end\>" contains=@juliaExpressions fold
+syntax region juliaExceptionBlock matchgroup=juliaException start="\<try\>" end="\<end\>" contains=@juliaExpressions,juliaCatchBlock,juliaFinallyBlock fold
+syntax region juliaCatchBlock matchgroup=juliaException transparent contained start="\<catch\>" end="\<end\>"me=s-1 contains=@juliaExpressions,juliaFinallyBlock
+syntax region juliaFinallyBlock matchgroup=juliaException transparent contained start="\<finally\>" end="\<end\>"me=s-1 contains=@juliaExpressions
+syntax region juliaAbstractBlock matchgroup=juliaBlKeyword start="\<abstract\s\+type\>" end="\<end\>" fold contains=@juliaExpressions,juliaStructR
+syntax region juliaPrimitiveBlock matchgroup=juliaBlKeyword start="\<primitive\s\+type\>" end="\<end\>" fold contains=@juliaExpressions,juliaStructR
+
+exec 'syntax region juliaComprehensionFor matchgroup=juliaComprehensionFor transparent contained start="\%([^[:space:],;:({[]\_s*\)\@'.s:d(80).'<=\<for\>" end="\ze[]);]" contains=@juliaExpressions,juliaComprehensionIf,juliaComprehensionFor'
+syntax match juliaComprehensionIf contained "\<if\>"
+
+exec 'syntax match juliaOuter contained "\<outer\ze\s\+' . s:idregex . '\>"'
+
+syntax match juliaRangeKeyword contained "\<\%(begin\|end\)\>"
+
+syntax match juliaBaseTypeBasic display "\<\%(\%(N\|Named\)\?Tuple\|Symbol\|Function\|Union\%(All\)\?\|Type\%(Name\|Var\)\?\|Any\|ANY\|Vararg\|Ptr\|Exception\|Module\|Expr\|DataType\|\%(LineNumber\|Quote\)Node\|\%(Weak\|Global\)\?Ref\|Method\|Pair\|Val\|Nothing\|Some\|Missing\)\>"
+syntax match juliaBaseTypeNum display "\<\%(U\?Int\%(8\|16\|32\|64\|128\)\?\|Float\%(16\|32\|64\)\|Complex\|Bool\|Char\|Number\|Signed\|Unsigned\|Integer\|AbstractFloat\|Real\|Rational\|\%(Abstract\)\?Irrational\|Enum\|BigInt\|BigFloat\|MathConst\|ComplexF\%(16\|32\|64\)\)\>"
+syntax match juliaBaseTypeC display "\<\%(FileOffset\|C\%(u\?\%(char\|short\|int\|long\(long\)\?\|w\?string\)\|float\|double\|\%(ptrdiff\|s\?size\|wchar\|off\|u\?intmax\)_t\|void\)\)\>"
+syntax match juliaBaseTypeError display "\<\%(\%(Bounds\|Divide\|Domain\|\%(Stack\)\?Overflow\|EOF\|Undef\%(Ref\|Var\)\|System\|Type\|Parse\|Argument\|Key\|Load\|Method\|Inexact\|OutOfMemory\|Init\|Assertion\|ReadOnlyMemory\|StringIndex\)Error\|\%(Interrupt\|Error\|ProcessExited\|Captured\|Composite\|InvalidState\|Missing\|\%(Process\|Task\)Failed\)Exception\|DimensionMismatch\|SegmentationFault\)\>"
+syntax match juliaBaseTypeIter display "\<\%(EachLine\|Enumerate\|Cartesian\%(Index\|Range\)\|LinSpace\|CartesianIndices\)\>"
+syntax match juliaBaseTypeString display "\<\%(DirectIndex\|Sub\|Rep\|Rev\|Abstract\|Substitution\)\?String\>"
+syntax match juliaBaseTypeArray display "\<\%(\%(Sub\)\?Array\|\%(Abstract\|Dense\|Strided\)\?\%(Array\|Matrix\|Vec\%(tor\|OrMat\)\)\|SparseMatrixCSC\|\%(AbstractSparse\|Bit\|Shared\)\%(Array\|Vector\|Matrix\)\|\%\(D\|Bid\|\%(Sym\)\?Trid\)iagonal\|Hermitian\|Symmetric\|UniformScaling\|\%(Lower\|Upper\)Triangular\|\%(Sparse\|Row\)Vector\|VecElement\|Conj\%(Array\|Matrix\|Vector\)\|Index\%(Cartesian\|Linear\|Style\)\|PermutedDimsArray\|Broadcasted\|Adjoint\|Transpose\|LinearIndices\)\>"
+syntax match juliaBaseTypeDict display "\<\%(WeakKey\|Id\|Abstract\)\?Dict\>"
+syntax match juliaBaseTypeSet display "\<\%(\%(Abstract\|Bit\)\?Set\)\>"
+syntax match juliaBaseTypeIO display "\<\%(IO\%(Stream\|Buffer\|Context\)\?\|RawFD\|StatStruct\|FileMonitor\|PollingFileWatcher\|Timer\|Base64\%(Decode\|Encode\)Pipe\|\%(UDP\|TCP\)Socket\|\%(Abstract\)\?Channel\|BufferStream\|ReentrantLock\|GenericIOBuffer\)\>"
+syntax match juliaBaseTypeProcess display "\<\%(Pipe\|Cmd\|PipeBuffer\)\>"
+syntax match juliaBaseTypeRange display "\<\%(Dims\|RangeIndex\|\%(Abstract\|Lin\|Ordinal\|Step\|\%(Abstract\)\?Unit\)Range\|Colon\|ExponentialBackOff\|StepRangeLen\)\>"
+syntax match juliaBaseTypeRegex display "\<Regex\%(Match\)\?\>"
+syntax match juliaBaseTypeFact display "\<\%(Factorization\|BunchKaufman\|\%(Cholesky\|QR\)\%(Pivoted\)\?\|\%(Generalized\)\?\%(Eigen\|SVD\|Schur\)\|Hessenberg\|LDLt\|LQ\|LU\)\>"
+syntax match juliaBaseTypeSort display "\<\%(Insertion\|\(Partial\)\?Quick\|Merge\)Sort\>"
+syntax match juliaBaseTypeRound display "\<Round\%(ingMode\|FromZero\|Down\|Nearest\%(Ties\%(Away\|Up\)\)\?\|ToZero\|Up\)\>"
+syntax match juliaBaseTypeSpecial display "\<\%(LocalProcess\|ClusterManager\)\>"
+syntax match juliaBaseTypeRandom display "\<\%(AbstractRNG\|MersenneTwister\|RandomDevice\)\>"
+syntax match juliaBaseTypeDisplay display "\<\%(Text\(Display\)\?\|\%(Abstract\)\?Display\|MIME\|HTML\)\>"
+syntax match juliaBaseTypeTime display "\<\%(Date\%(Time\)\?\|DateFormat\)\>"
+syntax match juliaBaseTypeOther display "\<\%(RemoteRef\|Task\|Condition\|VersionNumber\|IPv[46]\|SerializationState\|WorkerConfig\|Future\|RemoteChannel\|IPAddr\|Stack\%(Trace\|Frame\)\|\(Caching\|Worker\)Pool\|AbstractSerializer\)\>"
+
+syntax match juliaConstNum display "\%(\<\%(\%(NaN\|Inf\)\%(16\|32\|64\)\?\|pi\|π\)\>\)"
+" Note: recognition of ℯ, which Vim does not consider a valid identifier, is
+" complicated. We detect possible uses by just looking for the character (for
+" performance) and then check that it's actually used by its own.
+" (This also tries to detect preceding number constants; it does so in a crude
+" way.)
+syntax match juliaPossibleEuler "ℯ" contains=juliaEuler
+exec 'syntax match juliaEuler contained "\%(\%(^\|[' . s:nonidS_chars . s:op_chars_wc . ']\)\%(.\?[0-9][.0-9eEf_]*\d\)\?\)\@'.s:d(80).'<=ℯ\ze[' . s:nonidS_chars . s:op_chars_wc . ']"'
+syntax match juliaConstBool display "\<\%(true\|false\)\>"
+syntax match juliaConstEnv display "\<\%(ARGS\|ENV\|ENDIAN_BOM\|LOAD_PATH\|VERSION\|PROGRAM_FILE\|DEPOT_PATH\)\>"
+syntax match juliaConstIO display "\<\%(std\%(out\|in\|err\)\|devnull\)\>"
+syntax match juliaConstC display "\<\%(C_NULL\)\>"
+syntax match juliaConstGeneric display "\<\%(nothing\|Main\|undef\|missing\)\>"
+
+syntax match juliaParamType contained "[^{([:space:]<>\"]\+\ze{" nextgroup=juliaCurBraBlock
+
+syntax match juliaPossibleMacro transparent "@" contains=juliaMacroCall,juliaMacroCallP,juliaPrintfMacro,juliaDocMacro,juliaDocMacroPre
+
+exec 'syntax match juliaMacro contained "@' . s:idregex . '\%(\.' . s:idregex . '\)*"'
+syntax match juliaMacro contained "@[!.~$%^*/\\|<>+-]\ze[^0-9]"
+exec 'syntax region juliaMacroCall contained transparent start="\(@' . s:idregex . '\%(\.' . s:idregex . '\)*\)\@=\1\%([^(]\|$\)" end="\ze\%([])};#]\|$\|\<for\>\|\<end\>\)" contains=@juliaExpressions,juliaMacro,juliaSymbolS,juliaQuotedParBlockS'
+exec 'syntax region juliaMacroCall contained transparent start="\(@.\)\@=\1\%([^(]\|$\)" end="\ze\%([])};#]\|$\|\<for\>\|\<end\>\)" contains=@juliaExpressions,juliaMacro,juliaSymbolS,juliaQuotedParBlockS'
+exec 'syntax region juliaMacroCallP contained transparent start="@' . s:idregex . '\%(\.' . s:idregex . '\)*(" end=")\@'.s:d(1).'<=" contains=juliaMacro,juliaParBlock'
+exec 'syntax region juliaMacroCallP contained transparent start="@.(" end=")\@'.s:d(1).'<=" contains=juliaMacro,juliaParBlock'
+
+exec 'syntax match juliaNumbers transparent "\%(^\|[' . s:nonidS_chars . s:op_chars_wc . ']\)\@'.s:d(1).'<=\d\|\.\d\|im\>" contains=juliaNumber,juliaFloat,juliaComplexUnit'
+
+"integer regexes
+let s:dec_regex = '\d\%(_\?\d\)*\%(\>\|im\>\|\ze\D\)'
+let s:hex_regex = '0x\x\%(_\?\x\)*\%(\>\|im\>\|\ze\X\)'
+let s:bin_regex = '0b[01]\%(_\?[01]\)*\%(\>\|im\>\|\ze[^01]\)'
+let s:oct_regex = '0o\o\%(_\?\o\)*\%(\>\|im\>\|\ze\O\)'
+
+let s:int_regex = '\%(' . s:hex_regex .
+ \ '\|' . s:bin_regex .
+ \ '\|' . s:oct_regex .
+ \ '\|' . s:dec_regex .
+ \ '\)'
+
+"floating point regexes
+" starting with a dot, optional exponent
+let s:float_regex1 = '\.\d\%(_\?\d\)*\%([eEf][-+]\?\d\+\)\?\%(\>\|im\>\|\ze\D\)'
+" with dot, optional exponent
+let s:float_regex2 = '\d\%(_\?\d\)*\.\%(\d\%(_\?\d\)*\)\?\%([eEf][-+]\?\d\+\)\?\%(\>\|im\>\|\ze\D\)'
+" without dot, with exponent
+let s:float_regex3 = '\d\%(_\?\d\)*[eEf][-+]\?\d\+\%(\>\|im\>\|\ze\D\)'
+
+"hex floating point numbers
+" starting with a dot
+let s:hexfloat_regex1 = '0x\.\%\(\x\%(_\?\x\)*\)\?[pP][-+]\?\d\+\%(\>\|im\>\|\ze\X\)'
+" starting with a digit
+let s:hexfloat_regex2 = '0x\x\%(_\?\x\)*\%\(\.\%\(\x\%(_\?\x\)*\)\?\)\?[pP][-+]\?\d\+\%(\>\|im\>\|\ze\X\)'
+
+let s:float_regex = '\%(' . s:float_regex3 .
+ \ '\|' . s:float_regex2 .
+ \ '\|' . s:float_regex1 .
+ \ '\|' . s:hexfloat_regex2 .
+ \ '\|' . s:hexfloat_regex1 .
+ \ '\)'
+
+exec 'syntax match juliaNumber contained "' . s:int_regex . '" contains=juliaComplexUnit'
+exec 'syntax match juliaFloat contained "' . s:float_regex . '" contains=juliaComplexUnit'
+syntax match juliaComplexUnit display contained "\<im\>"
+
+syntax match juliaRangeOperator display ":"
+exec 'syntax match juliaOperator "' . s:operators . '"'
+
+exec 'syntax region juliaTernaryRegion matchgroup=juliaTernaryOperator start="\s\zs?\ze\s" skip="\%(:\(:\|[^:[:space:]'."'".'"({[]\+\s*\ze:\)\|\%(?\s*\)\@'.s:d(6).'<=:(\)" end=":" contains=@juliaExpressions,juliaErrorSemicol'
+
+let s:interp_dollar = '\([' . s:nonidS_chars . s:op_chars_wc . '!]\|^\)\@'.s:d(1).'<=\$'
+
+exec 'syntax match juliaDollarVar display contained "' . s:interp_dollar . s:idregex . '"'
+exec 'syntax region juliaDollarPar matchgroup=juliaDollarVar contained start="' .s:interp_dollar . '(" end=")" contains=@juliaExpressions'
+exec 'syntax region juliaDollarSqBra matchgroup=juliaDollarVar contained start="' .s:interp_dollar . '\[" end="\]" contains=@juliaExpressions,juliaComprehensionFor,juliaSymbolS,juliaQuotedParBlockS'
+
+syntax match juliaChar "'\\\?.'" contains=juliaSpecialChar
+syntax match juliaChar display "'\\\o\{3\}'" contains=juliaOctalEscapeChar
+syntax match juliaChar display "'\\x\x\{2\}'" contains=juliaHexEscapeChar
+syntax match juliaChar display "'\\u\x\{1,4\}'" contains=juliaUniCharSmall
+syntax match juliaChar display "'\\U\x\{1,8\}'" contains=juliaUniCharLarge
+
+exec 'syntax match juliaCTransOperator "[[:space:]}' . s:nonid_chars . s:op_chars_wc . '!]\@'.s:d(1).'<!\.\?' . "'" . 'ᵀ\?"'
+
+" TODO: some of these might be specialized; the rest could be just left to the
+" generic juliaStringPrefixed fallback
+syntax region juliaString matchgroup=juliaStringDelim start=+\z("\(""\)\?\)+ skip=+\%(\\\\\)*\\"+ end=+\z1+ contains=@juliaStringVars,@juliaSpecialChars,@juliaSpellcheckStrings
+syntax region juliaStringPrefixed contained matchgroup=juliaStringDelim start=+[^{([:space:]<>"]\+\z("\(""\)\?\)+ skip=+\%(\\\\\)*\\"+ end=+\z1+ contains=@juliaSpecialCharsRaw
+syntax region juliabString matchgroup=juliaStringDelim start=+\<b\z("\(""\)\?\)+ skip=+\%(\\\\\)*\\"+ end=+\z1+ contains=@juliaSpecialChars
+syntax region juliasString matchgroup=juliaStringDelim start=+\<s\z("\(""\)\?\)+ skip=+\%(\\\\\)*\\"+ end=+\z1+ contains=@juliaSpecialChars
+
+syntax region juliaDocString matchgroup=juliaDocStringDelim fold start=+^"""+ skip=+\%(\\\\\)*\\"+ end=+"""+ contains=@juliaStringVars,@juliaSpecialChars,@juliaSpellcheckDocStrings
+
+exec 'syntax region juliaPrintfMacro contained transparent start="@s\?printf(" end=")\@'.s:d(1).'<=" contains=juliaMacro,juliaPrintfParBlock'
+syntax region juliaPrintfMacro contained transparent start="@s\?printf\s\+" end="\ze\%([])};#]\|$\|\<for\>\)" contains=@juliaExprsPrintf,juliaMacro,juliaSymbolS,juliaQuotedParBlockS
+syntax region juliaPrintfParBlock contained matchgroup=juliaParDelim start="(" end=")" contains=@juliaExprsPrintf
+syntax region juliaPrintfString contained matchgroup=juliaStringDelim start=+"+ skip=+\%(\\\\\)*\\"+ end=+"+ contains=@juliaSpecialChars,@juliaPrintfChars
+
+exec 'syntax region juliaDocMacroPre contained transparent start=+@doc\s\+\%(' . s:idregex . '\%(\.' . s:idregex . '\)*\)\z("\%(""\)\?\)+ skip=+\%(\\\\\)*\\"+ end=+\(\z1\)\@'.s:d(3).'<=+ contains=juliaMacro,juliaDocStringMRaw'
+exec 'syntax region juliaDocMacro contained transparent start=+@doc\s\+\z("\%(""\)\?\)+ skip=+\%(\\\\\)*\\"+ end=+\(\z1\)\@'.s:d(3).'<=+ contains=juliaMacro,juliaDocStringM'
+syntax region juliaDocStringMRaw contained fold matchgroup=juliaDocStringDelim fold start=+\z\("\(""\)\?\)+ skip=+\%(\\\\\)*\\"+ end=+\z1+ contains=@juliaSpellcheckDocStrings
+syntax region juliaDocStringM contained fold matchgroup=juliaDocStringDelim fold start=+\z\("\(""\)\?\)+ skip=+\%(\\\\\)*\\"+ end=+\z1+ contains=@juliaStringVars,@juliaSpecialChars,@juliaSpellcheckDocStrings
+
+syntax region juliaShellString matchgroup=juliaStringDelim start=+`+ skip=+\%(\\\\\)*\\`+ end=+`+ contains=@juliaStringVars,juliaSpecialChar
+
+syntax cluster juliaStringVars contains=juliaStringVarsPar,juliaStringVarsSqBra,juliaStringVarsCurBra,juliaStringVarsPla
+syntax region juliaStringVarsPar contained matchgroup=juliaStringVarDelim start="$(" end=")" contains=@juliaExpressions
+syntax region juliaStringVarsSqBra contained matchgroup=juliaStringVarDelim start="$\[" end="\]" contains=@juliaExpressions,juliaComprehensionFor,juliaSymbolS,juliaQuotedParBlockS
+syntax region juliaStringVarsCurBra contained matchgroup=juliaStringVarDelim start="${" end="}" contains=@juliaExpressions
+exec 'syntax match juliaStringVarsPla contained "\$' . s:idregex . '"'
+
+" TODO improve RegEx
+syntax region juliaRegEx matchgroup=juliaStringDelim start=+\<r\z("\(""\)\?\)+ skip=+\%(\\\\\)*\\"+ end=+\z1[imsx]*+
+
+syntax cluster juliaSpecialChars contains=juliaSpecialChar,juliaDoubleBackslash,juliaEscapedQuote,juliaOctalEscapeChar,juliaHexEscapeChar,juliaUniCharSmall,juliaUniCharLarge
+syntax match juliaSpecialChar display contained "\\."
+syntax match juliaOctalEscapeChar display contained "\\\o\{3\}"
+syntax match juliaHexEscapeChar display contained "\\x\x\{2\}"
+syntax match juliaUniCharSmall display contained "\\u\x\{1,4\}"
+syntax match juliaUniCharLarge display contained "\\U\x\{1,8\}"
+syntax cluster juliaSpecialCharsRaw contains=juliaDoubleBackslash,juliaEscapedQuote
+syntax match juliaDoubleBackslash contained "\\\\"
+syntax match juliaEscapedQuote contained "\\\""
+
+syntax cluster juliaPrintfChars contains=juliaErrorPrintfFmt,juliaPrintfFmt
+syntax match juliaErrorPrintfFmt display contained "\\\?%."
+syntax match juliaPrintfFmt display contained "%\%(\d\+\$\)\=[-+' #0]*\%(\d*\|\*\|\*\d\+\$\)\%(\.\%(\d*\|\*\|\*\d\+\$\)\)\=\%([hlLjqzt]\|ll\|hh\)\=[aAbdiuoxXDOUfFeEgGcCsSpn]"
+syntax match juliaPrintfFmt display contained "%%"
+syntax match juliaPrintfFmt display contained "\\%\%(\d\+\$\)\=[-+' #0]*\%(\d*\|\*\|\*\d\+\$\)\%(\.\%(\d*\|\*\|\*\d\+\$\)\)\=\%([hlLjqzt]\|ll\|hh\)\=[aAbdiuoxXDOUfFeEgGcCsSpn]"hs=s+1
+syntax match juliaPrintfFmt display contained "\\%%"hs=s+1
+
+" this is used to restrict the search for Symbols to when colons appear at all
+" (for performance reasons)
+syntax match juliaPossibleSymbol transparent ":\ze[^:]" contains=juliaSymbol,juliaQuotedParBlock,juliaQuotedQMarkPar,juliaColon
+
+let s:quotable = '\%(' . s:idregex . '\|' . s:operators . '\|[?.]\|' . s:float_regex . '\|' . s:int_regex . '\)'
+let s:quoting_colon = '\%(\%(^\s*\|\s\{6,\}\|[' . s:nonid_chars . s:op_chars_wc . ']\s*\)\@'.s:d(6).'<=\|\%(\<\%(return\|if\|else\%(if\)\?\|while\|try\|begin\)\s\+\)\@'.s:d(9).'<=\)\zs:'
+let s:quoting_colonS = '\s\@'.s:d(1).'<=:'
+
+" note: juliaSymbolS only works within whitespace-sensitive contexts,
+" such as in macro calls without parentheses, or within square brackets.
+" It is used to override the recognition of expressions like `a :b` as
+" ranges rather than symbols in those contexts.
+" (Note that such `a :b` expressions only allows at most 5 spaces between
+" the identifier and the colon anyway.)
+
+exec 'syntax match juliaSymbol contained "' . s:quoting_colon . s:quotable . '"'
+exec 'syntax match juliaSymbolS contained "' . s:quoting_colonS . s:quotable . '"'
+
+" same as above for quoted expressions such as :(expr)
+exec 'syntax region juliaQuotedParBlock matchgroup=juliaQParDelim start="' . s:quoting_colon . '(" end=")" contains=@juliaExpressions'
+exec 'syntax match juliaQuotedQMarkPar "' . s:quoting_colon . '(\s*?\s*)" contains=juliaQuotedQMark'
+exec 'syntax region juliaQuotedParBlockS matchgroup=juliaQParDelim contained start="' . s:quoting_colonS . '(" end=")" contains=@juliaExpressions'
+
+
+syntax match juliaTypeOperatorR1 contained "[^{([:space:]<>\"]\+\%(\s*[<>]:\)\@="
+
+" force precedence over Symbols
+syntax match juliaTypeOperator contained "[<>:]:"
+exec 'syntax match juliaTypeOperatorR2 transparent "[<>:]:\s*\%(' . s:idregex . '\.\)*' . s:idregex . '" contains=juliaTypeOperator,juliaType,juliaDottedT,@juliaExpressions nextgroup=juliaTypeOperator'
+syntax match juliaIsaKeyword contained "\<isa\>"
+exec 'syntax match juliaTypeOperatorR3 transparent "\<isa\s\+\%(' . s:idregex . '\.\)*' . s:idregex . '" contains=juliaIsaKeyword,juliaType,juliaDottedT,@juliaExpressions nextgroup=juliaIsaKeyword'
+
+syntax match juliaWhereKeyword "\<where\>"
+exec 'syntax match juliaWhereR transparent "\<where\s\+' . s:idregex . '" contains=juliaWhereKeyword,juliaType,juliaDottedT,juliaIdSymbol'
+
+syntax region juliaCommentL matchgroup=juliaCommentDelim excludenl start="#\ze\%([^=]\|$\)" end="$" contains=juliaTodo,@juliaSpellcheckComments
+syntax region juliaCommentM matchgroup=juliaCommentDelim fold start="#=\ze\%([^#]\|$\)" end="=#" contains=juliaTodo,juliaCommentM,@juliaSpellcheckComments
+syntax keyword juliaTodo contained TODO FIXME XXX
+
+" detect an end-of-line with only whitespace or comments before it
+let s:eol = '\s*\%(\%(\%(#=\%(=#\@!\|[^=]\|\n\)\{-}=#\)\s*\)\+\)\?\%(#=\@!.*\)\?\n'
+
+" a trailing comma, or colon, or an empty line in an import/using/export
+" multi-line command. Used to recognize the as keyword, and for indentation
+" (this needs to take precedence over normal commas and colons, and comments)
+syntax cluster juliaContinuationItems contains=juliaContinuationComma,juliaContinuationColon,juliaContinuationNone
+exec 'syntax region juliaContinuationComma matchgroup=juliaComma contained start=",\ze'.s:eol.'" end="\n\+\ze." contains=@juliaCommentItems'
+exec 'syntax region juliaContinuationColon matchgroup=juliaColon contained start=":\ze'.s:eol.'" end="\n\+\ze." contains=@juliaCommentItems'
+exec 'syntax region juliaContinuationNone matchgroup=NONE contained start="\%(\<\%(import\|using\|export\)\>\|^\)\@'.s:d(6).'<=\ze'.s:eol.'" end="\n\+\ze." contains=@juliaCommentItems,juliaAsKeyword'
+exec 'syntax match juliaMacroName contained "@' . s:idregex . '\%(\.' . s:idregex . '\)*"'
+
+" the following are disabled by default, but
+" can be enabled by entering e.g.
+" :hi link juliaParDelim Delimiter
+hi def link juliaParDelim juliaNone
+hi def link juliaSemicolon juliaNone
+hi def link juliaComma juliaNone
+hi def link juliaFunctionCall juliaNone
+
+hi def link juliaColon juliaOperator
+
+hi def link juliaFunctionName juliaFunction
+hi def link juliaFunctionName1 juliaFunction
+hi def link juliaMacroName juliaMacro
+
+
+hi def link juliaKeyword Keyword
+hi def link juliaWhereKeyword Keyword
+hi def link juliaInfixKeyword Keyword
+hi def link juliaIsaKeyword Keyword
+hi def link juliaAsKeyword Keyword
+hi def link juliaRepKeyword Keyword
+hi def link juliaBlKeyword Keyword
+hi def link juliaConditional Conditional
+hi def link juliaRepeat Repeat
+hi def link juliaException Exception
+hi def link juliaOuter Keyword
+hi def link juliaBaseTypeBasic Type
+hi def link juliaBaseTypeNum Type
+hi def link juliaBaseTypeC Type
+hi def link juliaBaseTypeError Type
+hi def link juliaBaseTypeIter Type
+hi def link juliaBaseTypeString Type
+hi def link juliaBaseTypeArray Type
+hi def link juliaBaseTypeDict Type
+hi def link juliaBaseTypeSet Type
+hi def link juliaBaseTypeIO Type
+hi def link juliaBaseTypeProcess Type
+hi def link juliaBaseTypeRange Type
+hi def link juliaBaseTypeRegex Type
+hi def link juliaBaseTypeFact Type
+hi def link juliaBaseTypeSort Type
+hi def link juliaBaseTypeRound Type
+hi def link juliaBaseTypeSpecial Type
+hi def link juliaBaseTypeRandom Type
+hi def link juliaBaseTypeDisplay Type
+hi def link juliaBaseTypeTime Type
+hi def link juliaBaseTypeOther Type
+
+hi def link juliaType Type
+hi def link juliaParamType Type
+hi def link juliaTypeOperatorR1 Type
+
+" NOTE: deprecated constants are not highlighted as such. For once,
+" one can still legitimately use them by importing Base.MathConstants.
+" Plus, one-letter variables like `e` and `γ` can be used with other
+" meanings.
+hi def link juliaConstNum Constant
+hi def link juliaEuler Constant
+
+hi def link juliaConstEnv Constant
+hi def link juliaConstC Constant
+hi def link juliaConstLimits Constant
+hi def link juliaConstGeneric Constant
+hi def link juliaRangeKeyword Constant
+hi def link juliaConstBool Boolean
+hi def link juliaConstIO Boolean
+
+hi def link juliaComprehensionFor Keyword
+hi def link juliaComprehensionIf Keyword
+
+hi def link juliaDollarVar Identifier
+
+hi def link juliaFunction Function
+hi def link juliaMacro Macro
+hi def link juliaSymbol Identifier
+hi def link juliaSymbolS Identifier
+hi def link juliaQParDelim Identifier
+hi def link juliaQuotedQMarkPar Identifier
+hi def link juliaQuotedQMark juliaOperatorHL
+
+hi def link juliaNumber Number
+hi def link juliaFloat Float
+hi def link juliaComplexUnit Constant
+
+hi def link juliaChar Character
+
+hi def link juliaString String
+hi def link juliaStringPrefixed juliaString
+hi def link juliabString juliaString
+hi def link juliasString juliaString
+hi def link juliavString juliaString
+hi def link juliarString juliaString
+hi def link juliaipString juliaString
+hi def link juliabigString juliaString
+hi def link juliaMIMEString juliaString
+hi def link juliarawString juliaString
+hi def link juliatestString juliaString
+hi def link juliahtmlString juliaString
+hi def link juliaint128String juliaString
+hi def link juliaPrintfString juliaString
+hi def link juliaShellString juliaString
+hi def link juliaDocString juliaString
+hi def link juliaDocStringM juliaDocString
+hi def link juliaDocStringMRaw juliaDocString
+hi def link juliaStringDelim juliaString
+hi def link juliaDocStringDelim juliaDocString
+hi def link juliaStringVarsPla Identifier
+hi def link juliaStringVarDelim Identifier
+
+hi def link juliaRegEx String
+
+hi def link juliaSpecialChar SpecialChar
+hi def link juliaOctalEscapeChar SpecialChar
+hi def link juliaHexEscapeChar SpecialChar
+hi def link juliaUniCharSmall SpecialChar
+hi def link juliaUniCharLarge SpecialChar
+hi def link juliaDoubleBackslash SpecialChar
+hi def link juliaEscapedQuote SpecialChar
+
+hi def link juliaPrintfFmt SpecialChar
+
+if s:julia_highlight_operators
+ hi! def link juliaOperatorHL Operator
+else
+ hi! def link juliaOperatorHL juliaNone
+endif
+hi def link juliaOperator juliaOperatorHL
+hi def link juliaRangeOperator juliaOperatorHL
+hi def link juliaCTransOperator juliaOperatorHL
+hi def link juliaTernaryOperator juliaOperatorHL
+hi def link juliaTypeOperator juliaOperatorHL
+
+hi def link juliaCommentL Comment
+hi def link juliaCommentM Comment
+hi def link juliaCommentDelim Comment
+hi def link juliaTodo Todo
+
+hi def link juliaErrorPar juliaError
+hi def link juliaErrorEnd juliaError
+hi def link juliaErrorElse juliaError
+hi def link juliaErrorCatch juliaError
+hi def link juliaErrorFinally juliaError
+hi def link juliaErrorSemicol juliaError
+hi def link juliaErrorPrintfFmt juliaError
+
+hi def link juliaError Error
+
+syntax sync fromstart
+
+let b:current_syntax = "julia"
+
+let &cpo = s:cpo_save
+unlet s:cpo_save
diff --git a/runtime/syntax/man.vim b/runtime/syntax/man.vim
index a01bd1c0e7..7772d2d6aa 100644
--- a/runtime/syntax/man.vim
+++ b/runtime/syntax/man.vim
@@ -27,11 +27,7 @@ if &filetype != 'man'
finish
endif
-if !exists('b:man_sect')
- call man#init_pager()
-endif
-
-if b:man_sect =~# '^[023]'
+if get(b:, 'man_sect', '') =~# '^[023]'
syntax case match
syntax include @c $VIMRUNTIME/syntax/c.vim
syntax match manCFuncDefinition display '\<\h\w*\>\ze\(\s\|\n\)*(' contained
diff --git a/runtime/syntax/scala.vim b/runtime/syntax/scala.vim
index c5a175fd77..89a936ad17 100644
--- a/runtime/syntax/scala.vim
+++ b/runtime/syntax/scala.vim
@@ -3,7 +3,8 @@
" Maintainer: Derek Wyatt
" URL: https://github.com/derekwyatt/vim-scala
" License: Same as Vim
-" Last Change: 20 May 2016
+" Last Change: 2021 Aug 11
+" by Jesse Atkinson, PR #8746
" ----------------------------------------------------------------------------
if !exists('main_syntax')
@@ -66,7 +67,7 @@ syn match scalaChar /'\\u[A-Fa-f0-9]\{4}'/ contains=scalaUnicodeChar
syn match scalaEscapedChar /\\[\\"'ntbrf]/
syn match scalaUnicodeChar /\\u[A-Fa-f0-9]\{4}/
hi link scalaChar Character
-hi link scalaEscapedChar Function
+hi link scalaEscapedChar Special
hi link scalaUnicodeChar Special
syn match scalaOperator "||"
diff --git a/scripts/release.sh b/scripts/release.sh
index 4d1484b77a..4ec959d697 100755
--- a/scripts/release.sh
+++ b/scripts/release.sh
@@ -12,6 +12,7 @@
# - CMakeLists.txt: Unset NVIM_VERSION_PRERELEASE
# - CMakeLists.txt: Unset NVIM_API_PRERELEASE
# - Create test/functional/fixtures/api_level_N.mpack
+# - Add date and version to runtime/nvim.appdata.xml
# - Tag the commit.
# Create the "version bump" commit:
# - CMakeLists.txt: Set NVIM_VERSION_PRERELEASE to "-dev"
@@ -62,6 +63,10 @@ _do_release_commit() {
git add test/functional/fixtures/api_level_$__API_LEVEL.mpack
fi
+ $__sed -i.bk 's,(<releases>),\1\
+ <release date="'"${__DATE}"'" version="'"${__VERSION}"'"/>,' runtime/nvim.appdata.xml
+ git add runtime/nvim.appdata.xml
+
if ! test "$ARG1" = '--use-current-commit' ; then
echo "Building changelog since ${__LAST_TAG}..."
@@ -75,14 +80,12 @@ _do_release_commit() {
_do_bump_commit() {
$__sed -i.bk 's/(NVIM_VERSION_PRERELEASE) ""/\1 "-dev"/' CMakeLists.txt
$__sed -i.bk 's/set\((NVIM_VERSION_PATCH) [[:digit:]]/set(\1 ?/' CMakeLists.txt
- $__sed -i.bk 's,(<releases>),\1\
- <release date="'"${__DATE}"'" version="xxx"/>,' runtime/nvim.appdata.xml
rm CMakeLists.txt.bk
rm runtime/nvim.appdata.xml.bk
nvim +'/NVIM_VERSION' +1new +'exe "norm! iUpdate version numbers!!!"' \
- -O CMakeLists.txt runtime/nvim.appdata.xml
+ -O CMakeLists.txt
- git add CMakeLists.txt runtime/nvim.appdata.xml
+ git add CMakeLists.txt
git commit -m "$__BUMP_MSG"
}
@@ -92,11 +95,7 @@ fi
_do_bump_commit
echo "
Next steps:
- - Update runtime/nvim.appdata.xml on _master_
- Run tests/CI (version_spec.lua)!
- Push the tag:
git push --follow-tags
- - Update the 'stable' tag:
- git push --force upstream HEAD^:refs/tags/stable
- git fetch --tags
- Update website: index.html"
diff --git a/scripts/squash_typos.py b/scripts/squash_typos.py
index e7ee2e24a8..26be6010a2 100644
--- a/scripts/squash_typos.py
+++ b/scripts/squash_typos.py
@@ -7,17 +7,16 @@ This script squashes a PR tagged with the "typo" label into a single, dedicated
"""
import subprocess
+import sys
import os
-import re
def get_authors_and_emails_from_pr():
"""
- For a given PR number, returns all contributing authors and their emails
- for that PR. This includes co-authors, meaning that if two authors are
- credited for a single commit, which is possible with GitHub, then both will
- get credited.
+ Return all contributing authors and their emails for the PR on current branch.
+ This includes co-authors, meaning that if two authors are credited for a
+ single commit, which is possible with GitHub, then both will get credited.
"""
@@ -33,44 +32,85 @@ def get_authors_and_emails_from_pr():
text=True,
).splitlines()
- return [(author, mail) for author, mail in zip(authors, emails)]
+ authors_and_emails_unique = {
+ (author, mail) for author, mail in zip(authors, emails)
+ }
+ return sorted(authors_and_emails_unique)
-def rebase_onto_pr(pr, squash_branch):
+
+def rebase_squash_branch_onto_pr():
"""
- Add all commits from PR into current branch. This is done by rebasing
- current branch onto the PR.
+ Rebase current branch onto the PR.
"""
# Check out the pull request.
- subprocess.call(["gh", "pr", "checkout", pr])
+ subprocess.call(["gh", "pr", "checkout", os.environ["PR_NUMBER"]])
- pr_branch_name = subprocess.check_output(
- ["git", "branch", "--show-current"], text=True
- ).strip()
+ # Rebase onto master
+ default_branch = f"{os.environ['GITHUB_BASE_REF']}"
+ subprocess.check_call(["git", "rebase", default_branch])
# Change back to the original branch.
- subprocess.call(["git", "switch", squash_branch])
+ subprocess.call(["git", "switch", "-"])
+
+ # Rebase onto the pull request, aka include the commits in the pull request
+ # in the current branch. Abort with error message if rebase fails.
- # Rebase onto the pull request, aka include the commits in the pull
- # request in the current branch.
- subprocess.call(["git", "rebase", pr_branch_name])
+ try:
+ subprocess.check_call(["git", "rebase", "-"])
+ except subprocess.CalledProcessError:
+ subprocess.call(["git", "rebase", "--abort"])
+ squash_url = subprocess.check_output(
+ ["gh", "pr", "view", "--json", "url", "--jq", ".url"], text=True
+ ).strip()
+
+ subprocess.call(
+ [
+ "gh",
+ "pr",
+ "comment",
+ os.environ["PR_NUMBER"],
+ "--body",
+ f"Your edit conflicts with an already scheduled fix \
+ ({squash_url}). Please check that batch PR whether your fix is \
+ already included; if not, then please wait until the batch PR \
+ is merged and then rebase your PR on top of master.",
+ ]
+ )
+
+ sys.exit(
+ f"\n\nERROR: Your edit conflicts with an already scheduled fix \
+{squash_url} \n\n"
+ )
+
+
+def rebase_squash_branch_onto_master():
+ """
+
+ Rebase current branch onto the master i.e. make sure current branch is up
+ to date. Abort on error.
+
+ """
+
+ default_branch = f"{os.environ['GITHUB_BASE_REF']}"
+ subprocess.check_call(["git", "rebase", default_branch])
def squash_all_commits():
"""
- Squash all commits into a single commit. Credit all authors by name and
- email.
+ Squash all commits on the PR into a single commit. Credit all authors by
+ name and email.
"""
- authors_and_emails = get_authors_and_emails_from_pr()
- subprocess.call(["git", "reset", "--soft", f"{os.environ['GITHUB_BASE_REF']}"])
+ default_branch = f"{os.environ['GITHUB_BASE_REF']}"
+ subprocess.call(["git", "reset", "--soft", default_branch])
- authors_and_emails = sorted(set(authors_and_emails))
+ authors_and_emails = get_authors_and_emails_from_pr()
commit_message_coauthors = "\n" + "\n".join(
[f"Co-authored-by: {i[0]} <{i[1]}>" for i in authors_and_emails]
)
@@ -80,6 +120,12 @@ def squash_all_commits():
def force_push(branch):
+ """
+
+ Like the name implies, force push <branch>.
+
+ """
+
gh_actor = os.environ["GITHUB_ACTOR"]
gh_token = os.environ["GITHUB_TOKEN"]
gh_repo = os.environ["GITHUB_REPOSITORY"]
@@ -94,55 +140,84 @@ def force_push(branch):
)
-def main():
- squash_branch = "marvim/squash-typos"
- all_pr_urls = ""
+def checkout_branch(branch):
+ """
+
+ Create and checkout <branch>. Check if branch exists on remote, if so then
+ sync local branch to remote.
- pr_number = re.sub(r"\D", "", os.environ["GITHUB_REF"])
+ Return True if remote branch exists, else False.
+
+ """
+
+ # FIXME I'm not sure why the local branch isn't tracking the remote branch
+ # automatically. This works but I'm pretty sure it can be done in a more
+ # "elegant" fashion
show_ref_output = subprocess.check_output(["git", "show-ref"], text=True).strip()
- if squash_branch in show_ref_output:
- subprocess.call(
- ["git", "checkout", "-b", squash_branch, f"origin/{squash_branch}"]
- )
- squash_branch_exists = True
+ if branch in show_ref_output:
+ subprocess.call(["git", "checkout", "-b", branch, f"origin/{branch}"])
+ return True
+
+ subprocess.call(["git", "checkout", "-b", branch])
+ return False
+
+
+def get_all_pr_urls(squash_branch_exists):
+ """
+
+ Return a list of URLs for the pull requests with the typo fixes. If a
+ squash branch exists then extract the URLs from the body text.
+ """
+
+ all_pr_urls = ""
+ if squash_branch_exists:
all_pr_urls += subprocess.check_output(
["gh", "pr", "view", "--json", "body", "--jq", ".body"], text=True
)
- else:
- subprocess.call(["git", "checkout", "-b", squash_branch])
- squash_branch_exists = False
all_pr_urls += subprocess.check_output(
- ["gh", "pr", "view", pr_number, "--json", "url", "--jq", ".url"], text=True
+ ["gh", "pr", "view", os.environ["PR_NUMBER"], "--json", "url", "--jq", ".url"],
+ text=True,
).strip()
- rebase_onto_pr(pr_number, squash_branch)
+ return all_pr_urls
+
+
+def main():
+ squash_branch = "marvim/squash-typos"
+
+ squash_branch_exists = checkout_branch(squash_branch)
+
+ rebase_squash_branch_onto_master()
+ force_push(squash_branch)
+
+ rebase_squash_branch_onto_pr()
force_push(squash_branch)
- subprocess.call(["gh", "pr", "close", pr_number])
+ subprocess.call(
+ [
+ "gh",
+ "pr",
+ "create",
+ "--fill",
+ "--head",
+ squash_branch,
+ "--title",
+ "chore: typo fixes (automated)",
+ ]
+ )
squash_all_commits()
force_push(squash_branch)
- if not squash_branch_exists:
- subprocess.call(
- [
- "gh",
- "pr",
- "create",
- "--fill",
- "--head",
- squash_branch,
- "--title",
- "Dedicated PR for all typo fixes.",
- ]
- )
-
+ all_pr_urls = get_all_pr_urls(squash_branch_exists)
subprocess.call(["gh", "pr", "edit", "--add-label", "typo", "--body", all_pr_urls])
+ subprocess.call(["gh", "pr", "close", os.environ["PR_NUMBER"]])
+
if __name__ == "__main__":
main()
diff --git a/src/clint.py b/src/clint.py
index 4a5e435bbd..e7d76366b0 100755
--- a/src/clint.py
+++ b/src/clint.py
@@ -264,7 +264,7 @@ _error_suppressions_2 = set()
# The allowed line length of files.
# This is set by --linelength flag.
-_line_length = 80
+_line_length = 100
# The allowed extensions for file names
# This is set by --extensions flag.
diff --git a/src/nvim/README.md b/src/nvim/README.md
index affc5c79cc..4efb42b896 100644
--- a/src/nvim/README.md
+++ b/src/nvim/README.md
@@ -75,8 +75,108 @@ Logs will be written to `${HOME}/logs/*san.PID` then.
For more information: https://github.com/google/sanitizers/wiki/SanitizerCommonFlags
-TUI debugging
--------------
+Debug: Performance
+------------------
+
+### Profiling (easy)
+
+For debugging performance bottlenecks in any code, there is a simple (and very
+effective) approach:
+
+1. Run the slow code in a loop.
+2. Break execution ~5 times and save the stacktrace.
+3. The cause of the bottleneck will (almost always) appear in most of the stacktraces.
+
+### Profiling (fancy)
+
+For more advanced profiling, consider `perf` + `flamegraph`.
+
+### USDT profiling (powerful)
+
+Or you can use USDT probes via `NVIM_PROBE` ([#12036](https://github.com/neovim/neovim/pull/12036)).
+
+> USDT is basically a way to define stable probe points in userland binaries.
+> The benefit of bcc is the ability to define logic to go along with the probe
+> points.
+
+Tools:
+- bpftrace provides an awk-like language to the kernel bytecode, BPF.
+- BCC provides a subset of C. Provides more complex logic than bpftrace, but takes a bit more effort.
+
+Example using bpftrace to track slow vim functions, and print out any files
+that were opened during the trace. At the end, it prints a histogram of
+function timing:
+
+ #!/usr/bin/env bpftrace
+
+ BEGIN {
+ @depth = -1;
+ }
+
+ tracepoint:sched:sched_process_fork /@pidmap[args->parent_pid]/ {
+ @pidmap[args->child_pid] = 1;
+ }
+
+ tracepoint:sched:sched_process_exit /@pidmap[args->pid]/ {
+ delete(@pidmap[args->pid]);
+ }
+
+ usdt:build/bin/nvim:neovim:eval__call_func__entry {
+ @pidmap[pid] = 1;
+ @depth++;
+ @funcentry[@depth] = nsecs;
+ }
+
+ usdt:build/bin/nvim:neovim:eval__call_func__return {
+ $func = str(arg0);
+ $msecs = (nsecs - @funcentry[@depth]) / 1000000;
+
+ @time_histo = hist($msecs);
+
+ if ($msecs >= 1000) {
+ printf("%u ms for %s\n", $msecs, $func);
+ print(@files);
+ }
+
+ clear(@files);
+ delete(@funcentry[@depth]);
+ @depth--;
+ }
+
+ tracepoint:syscalls:sys_enter_open,
+ tracepoint:syscalls:sys_enter_openat {
+ if (@pidmap[pid] == 1 && @depth >= 0) {
+ @files[str(args->filename)] = count();
+ }
+ }
+
+ END {
+ clear(@depth);
+ }
+
+ $ sudo bpftrace funcslower.bt
+ 1527 ms for Slower
+ @files[/usr/lib/libstdc++.so.6]: 2
+ @files[/etc/fish/config.fish]: 2
+ <snip>
+
+ ^C
+ @time_histo:
+ [0] 71430 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
+ [1] 346 | |
+ [2, 4) 208 | |
+ [4, 8) 91 | |
+ [8, 16) 22 | |
+ [16, 32) 85 | |
+ [32, 64) 7 | |
+ [64, 128) 0 | |
+ [128, 256) 0 | |
+ [256, 512) 6 | |
+ [512, 1K) 1 | |
+ [1K, 2K) 5 | |
+
+Debug: TUI
+----------
### TUI troubleshoot
diff --git a/src/nvim/api/private/dispatch.c b/src/nvim/api/private/dispatch.c
index eae4581f42..9f16da4078 100644
--- a/src/nvim/api/private/dispatch.c
+++ b/src/nvim/api/private/dispatch.c
@@ -21,12 +21,12 @@
#include "nvim/api/window.h"
#include "nvim/api/deprecated.h"
-static Map(String, MsgpackRpcRequestHandler) *methods = NULL;
+static Map(String, MsgpackRpcRequestHandler) methods = MAP_INIT;
static void msgpack_rpc_add_method_handler(String method,
MsgpackRpcRequestHandler handler)
{
- map_put(String, MsgpackRpcRequestHandler)(methods, method, handler);
+ map_put(String, MsgpackRpcRequestHandler)(&methods, method, handler);
}
/// @param name API method name
@@ -37,7 +37,7 @@ MsgpackRpcRequestHandler msgpack_rpc_get_handler_for(const char *name,
{
String m = { .data = (char *)name, .size = name_len };
MsgpackRpcRequestHandler rv =
- map_get(String, MsgpackRpcRequestHandler)(methods, m);
+ map_get(String, MsgpackRpcRequestHandler)(&methods, m);
if (!rv.fn) {
api_set_error(error, kErrorTypeException, "Invalid method: %.*s",
diff --git a/src/nvim/api/private/handle.c b/src/nvim/api/private/handle.c
deleted file mode 100644
index eb96192af2..0000000000
--- a/src/nvim/api/private/handle.c
+++ /dev/null
@@ -1,40 +0,0 @@
-// This is an open source non-commercial project. Dear PVS-Studio, please check
-// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
-
-#include <assert.h>
-#include <stdint.h>
-
-#include "nvim/vim.h"
-#include "nvim/map.h"
-#include "nvim/api/private/handle.h"
-
-#define HANDLE_INIT(name) name##_handles = pmap_new(handle_T)()
-
-#define HANDLE_IMPL(type, name) \
- static PMap(handle_T) *name##_handles = NULL; /* NOLINT */ \
- \
- type *handle_get_##name(handle_T handle) \
- { \
- return pmap_get(handle_T)(name##_handles, handle); \
- } \
- \
- void handle_register_##name(type *name) \
- { \
- pmap_put(handle_T)(name##_handles, name->handle, name); \
- } \
- \
- void handle_unregister_##name(type *name) \
- { \
- pmap_del(handle_T)(name##_handles, name->handle); \
- }
-
-HANDLE_IMPL(buf_T, buffer)
-HANDLE_IMPL(win_T, window)
-HANDLE_IMPL(tabpage_T, tabpage)
-
-void handle_init(void)
-{
- HANDLE_INIT(buffer);
- HANDLE_INIT(window);
- HANDLE_INIT(tabpage);
-}
diff --git a/src/nvim/api/private/handle.h b/src/nvim/api/private/handle.h
deleted file mode 100644
index 26e9dc3314..0000000000
--- a/src/nvim/api/private/handle.h
+++ /dev/null
@@ -1,24 +0,0 @@
-#ifndef NVIM_API_PRIVATE_HANDLE_H
-#define NVIM_API_PRIVATE_HANDLE_H
-
-#include "nvim/vim.h"
-#include "nvim/buffer_defs.h"
-#include "nvim/api/private/defs.h"
-
-#define HANDLE_DECLS(type, name) \
- type *handle_get_##name(handle_T handle); \
- void handle_register_##name(type *name); \
- void handle_unregister_##name(type *name);
-
-// handle_get_buffer handle_register_buffer, handle_unregister_buffer
-HANDLE_DECLS(buf_T, buffer)
-// handle_get_window handle_register_window, handle_unregister_window
-HANDLE_DECLS(win_T, window)
-// handle_get_tabpage handle_register_tabpage, handle_unregister_tabpage
-HANDLE_DECLS(tabpage_T, tabpage)
-
-void handle_init(void);
-
-
-#endif // NVIM_API_PRIVATE_HANDLE_H
-
diff --git a/src/nvim/api/private/helpers.c b/src/nvim/api/private/helpers.c
index 3ec6151090..eedcfd69b8 100644
--- a/src/nvim/api/private/helpers.c
+++ b/src/nvim/api/private/helpers.c
@@ -9,7 +9,6 @@
#include "nvim/api/private/helpers.h"
#include "nvim/api/private/defs.h"
-#include "nvim/api/private/handle.h"
#include "nvim/api/vim.h"
#include "nvim/msgpack_rpc/helpers.h"
#include "nvim/lua/executor.h"
@@ -1725,7 +1724,7 @@ const char *describe_ns(NS ns_id)
{
String name;
handle_T id;
- map_foreach(namespace_ids, name, id, {
+ map_foreach(&namespace_ids, name, id, {
if ((NS)id == ns_id && name.size) {
return name.data;
}
diff --git a/src/nvim/api/private/helpers.h b/src/nvim/api/private/helpers.h
index 055abb797f..ecce6afa26 100644
--- a/src/nvim/api/private/helpers.h
+++ b/src/nvim/api/private/helpers.h
@@ -101,6 +101,14 @@
#define api_free_window(value)
#define api_free_tabpage(value)
+EXTERN PMap(handle_T) buffer_handles INIT(= MAP_INIT);
+EXTERN PMap(handle_T) window_handles INIT(= MAP_INIT);
+EXTERN PMap(handle_T) tabpage_handles INIT(= MAP_INIT);
+
+#define handle_get_buffer(h) pmap_get(handle_T)(&buffer_handles, (h))
+#define handle_get_window(h) pmap_get(handle_T)(&window_handles, (h))
+#define handle_get_tabpage(h) pmap_get(handle_T)(&tabpage_handles, (h))
+
/// Structure used for saving state for :try
///
/// Used when caller is supposed to be operating when other VimL code is being
diff --git a/src/nvim/api/ui.c b/src/nvim/api/ui.c
index 63e6ad883a..713980ca68 100644
--- a/src/nvim/api/ui.c
+++ b/src/nvim/api/ui.c
@@ -37,24 +37,18 @@ typedef struct {
bool wildmenu_active;
} UIData;
-static PMap(uint64_t) *connected_uis = NULL;
-
-void remote_ui_init(void)
- FUNC_API_NOEXPORT
-{
- connected_uis = pmap_new(uint64_t)();
-}
+static PMap(uint64_t) connected_uis = MAP_INIT;
void remote_ui_disconnect(uint64_t channel_id)
FUNC_API_NOEXPORT
{
- UI *ui = pmap_get(uint64_t)(connected_uis, channel_id);
+ UI *ui = pmap_get(uint64_t)(&connected_uis, channel_id);
if (!ui) {
return;
}
UIData *data = ui->data;
api_free_array(data->buffer); // Destroy pending screen updates.
- pmap_del(uint64_t)(connected_uis, channel_id);
+ pmap_del(uint64_t)(&connected_uis, channel_id);
xfree(ui->data);
ui->data = NULL; // Flag UI as "stopped".
ui_detach_impl(ui, channel_id);
@@ -73,7 +67,7 @@ void remote_ui_wait_for_attach(void)
}
LOOP_PROCESS_EVENTS_UNTIL(&main_loop, channel->events, -1,
- pmap_has(uint64_t)(connected_uis, CHAN_STDIO));
+ pmap_has(uint64_t)(&connected_uis, CHAN_STDIO));
}
/// Activates UI events on the channel.
@@ -95,7 +89,7 @@ void nvim_ui_attach(uint64_t channel_id, Integer width, Integer height,
Dictionary options, Error *err)
FUNC_API_SINCE(1) FUNC_API_REMOTE_ONLY
{
- if (pmap_has(uint64_t)(connected_uis, channel_id)) {
+ if (pmap_has(uint64_t)(&connected_uis, channel_id)) {
api_set_error(err, kErrorTypeException,
"UI already attached to channel: %" PRId64, channel_id);
return;
@@ -172,7 +166,7 @@ void nvim_ui_attach(uint64_t channel_id, Integer width, Integer height,
data->wildmenu_active = false;
ui->data = data;
- pmap_put(uint64_t)(connected_uis, channel_id, ui);
+ pmap_put(uint64_t)(&connected_uis, channel_id, ui);
ui_attach_impl(ui, channel_id);
}
@@ -195,7 +189,7 @@ void ui_attach(uint64_t channel_id, Integer width, Integer height,
void nvim_ui_detach(uint64_t channel_id, Error *err)
FUNC_API_SINCE(1) FUNC_API_REMOTE_ONLY
{
- if (!pmap_has(uint64_t)(connected_uis, channel_id)) {
+ if (!pmap_has(uint64_t)(&connected_uis, channel_id)) {
api_set_error(err, kErrorTypeException,
"UI not attached to channel: %" PRId64, channel_id);
return;
@@ -208,7 +202,7 @@ void nvim_ui_try_resize(uint64_t channel_id, Integer width,
Integer height, Error *err)
FUNC_API_SINCE(1) FUNC_API_REMOTE_ONLY
{
- if (!pmap_has(uint64_t)(connected_uis, channel_id)) {
+ if (!pmap_has(uint64_t)(&connected_uis, channel_id)) {
api_set_error(err, kErrorTypeException,
"UI not attached to channel: %" PRId64, channel_id);
return;
@@ -220,7 +214,7 @@ void nvim_ui_try_resize(uint64_t channel_id, Integer width,
return;
}
- UI *ui = pmap_get(uint64_t)(connected_uis, channel_id);
+ UI *ui = pmap_get(uint64_t)(&connected_uis, channel_id);
ui->width = (int)width;
ui->height = (int)height;
ui_refresh();
@@ -230,12 +224,12 @@ void nvim_ui_set_option(uint64_t channel_id, String name,
Object value, Error *error)
FUNC_API_SINCE(1) FUNC_API_REMOTE_ONLY
{
- if (!pmap_has(uint64_t)(connected_uis, channel_id)) {
+ if (!pmap_has(uint64_t)(&connected_uis, channel_id)) {
api_set_error(error, kErrorTypeException,
"UI not attached to channel: %" PRId64, channel_id);
return;
}
- UI *ui = pmap_get(uint64_t)(connected_uis, channel_id);
+ UI *ui = pmap_get(uint64_t)(&connected_uis, channel_id);
ui_set_option(ui, false, name, value, error);
}
@@ -310,7 +304,7 @@ void nvim_ui_try_resize_grid(uint64_t channel_id, Integer grid, Integer width,
Integer height, Error *err)
FUNC_API_SINCE(6) FUNC_API_REMOTE_ONLY
{
- if (!pmap_has(uint64_t)(connected_uis, channel_id)) {
+ if (!pmap_has(uint64_t)(&connected_uis, channel_id)) {
api_set_error(err, kErrorTypeException,
"UI not attached to channel: %" PRId64, channel_id);
return;
@@ -328,7 +322,7 @@ void nvim_ui_try_resize_grid(uint64_t channel_id, Integer grid, Integer width,
void nvim_ui_pum_set_height(uint64_t channel_id, Integer height, Error *err)
FUNC_API_SINCE(6) FUNC_API_REMOTE_ONLY
{
- if (!pmap_has(uint64_t)(connected_uis, channel_id)) {
+ if (!pmap_has(uint64_t)(&connected_uis, channel_id)) {
api_set_error(err, kErrorTypeException,
"UI not attached to channel: %" PRId64, channel_id);
return;
@@ -339,7 +333,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);
+ UI *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");
@@ -369,13 +363,13 @@ void nvim_ui_pum_set_bounds(uint64_t channel_id, Float width, Float height,
Float row, Float col, Error *err)
FUNC_API_SINCE(7) FUNC_API_REMOTE_ONLY
{
- if (!pmap_has(uint64_t)(connected_uis, channel_id)) {
+ if (!pmap_has(uint64_t)(&connected_uis, channel_id)) {
api_set_error(err, kErrorTypeException,
"UI not attached to channel: %" PRId64, channel_id);
return;
}
- UI *ui = pmap_get(uint64_t)(connected_uis, channel_id);
+ UI *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");
diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c
index ec13bdd0e2..2536249de5 100644
--- a/src/nvim/api/vim.c
+++ b/src/nvim/api/vim.c
@@ -58,22 +58,16 @@
# include "api/vim.c.generated.h"
#endif
-void api_vim_init(void)
- FUNC_API_NOEXPORT
-{
- namespace_ids = map_new(String, handle_T)();
-}
-
void api_vim_free_all_mem(void)
FUNC_API_NOEXPORT
{
String name;
handle_T id;
- map_foreach(namespace_ids, name, id, {
+ map_foreach(&namespace_ids, name, id, {
(void)id;
xfree(name.data);
})
- map_free(String, handle_T)(namespace_ids);
+ map_destroy(String, handle_T)(&namespace_ids);
}
/// Executes Vimscript (multiline block of Ex-commands), like anonymous
@@ -1571,14 +1565,14 @@ void nvim_set_current_tabpage(Tabpage tabpage, Error *err)
Integer nvim_create_namespace(String name)
FUNC_API_SINCE(5)
{
- handle_T id = map_get(String, handle_T)(namespace_ids, name);
+ handle_T id = map_get(String, handle_T)(&namespace_ids, name);
if (id > 0) {
return id;
}
id = next_namespace_id++;
if (name.size > 0) {
String name_alloc = copy_string(name);
- map_put(String, handle_T)(namespace_ids, name_alloc, id);
+ map_put(String, handle_T)(&namespace_ids, name_alloc, id);
}
return (Integer)id;
}
@@ -1593,7 +1587,7 @@ Dictionary nvim_get_namespaces(void)
String name;
handle_T id;
- map_foreach(namespace_ids, name, id, {
+ map_foreach(&namespace_ids, name, id, {
PUT(retval, name.data, INTEGER_OBJ(id));
})
diff --git a/src/nvim/api/vim.h b/src/nvim/api/vim.h
index d6873da6d2..4fd353ce5c 100644
--- a/src/nvim/api/vim.h
+++ b/src/nvim/api/vim.h
@@ -6,7 +6,7 @@
#include "nvim/api/private/defs.h"
#include "nvim/map.h"
-EXTERN Map(String, handle_T) *namespace_ids INIT(= NULL);
+EXTERN Map(String, handle_T) namespace_ids INIT(= MAP_INIT);
EXTERN handle_T next_namespace_id INIT(= 1);
#ifdef INCLUDE_GENERATED_DECLARATIONS
diff --git a/src/nvim/autocmd.c b/src/nvim/autocmd.c
index 145f6f5601..417953eb14 100644
--- a/src/nvim/autocmd.c
+++ b/src/nvim/autocmd.c
@@ -5,7 +5,7 @@
#include "nvim/autocmd.h"
-#include "nvim/api/private/handle.h"
+#include "nvim/api/private/helpers.h"
#include "nvim/ascii.h"
#include "nvim/buffer.h"
#include "nvim/charset.h"
@@ -1150,7 +1150,7 @@ void aucmd_prepbuf(aco_save_T *aco, buf_T *buf)
block_autocmds(); // We don't want BufEnter/WinEnter autocommands.
if (need_append) {
win_append(lastwin, aucmd_win);
- handle_register_window(aucmd_win);
+ pmap_put(handle_T)(&window_handles, aucmd_win->handle, aucmd_win);
win_config_float(aucmd_win, aucmd_win->w_float_config);
}
// Prevent chdir() call in win_enter_ext(), through do_autochdir()
@@ -1191,7 +1191,7 @@ void aucmd_restbuf(aco_save_T *aco)
win_found:
win_remove(curwin, NULL);
- handle_unregister_window(curwin);
+ pmap_del(handle_T)(&window_handles, curwin->handle);
if (curwin->w_grid_alloc.chars != NULL) {
ui_comp_remove_grid(&curwin->w_grid_alloc);
ui_call_win_hide(curwin->w_grid_alloc.handle);
@@ -1724,7 +1724,7 @@ BYPASS_AU:
void block_autocmds(void)
{
// Remember the value of v:termresponse.
- if (is_autocmd_blocked()) {
+ if (!is_autocmd_blocked()) {
old_termresponse = get_vim_var_str(VV_TERMRESPONSE);
}
autocmd_blocked++;
@@ -1737,7 +1737,7 @@ void unblock_autocmds(void)
// When v:termresponse was set while autocommands were blocked, trigger
// the autocommands now. Esp. useful when executing a shell command
// during startup (nvim -d).
- if (is_autocmd_blocked()
+ if (!is_autocmd_blocked()
&& get_vim_var_str(VV_TERMRESPONSE) != old_termresponse) {
apply_autocmds(EVENT_TERMRESPONSE, NULL, NULL, false, curbuf);
}
diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c
index 587ef74b35..fdb3ffdc7e 100644
--- a/src/nvim/buffer.c
+++ b/src/nvim/buffer.c
@@ -24,7 +24,6 @@
#include <inttypes.h>
#include <assert.h>
-#include "nvim/api/private/handle.h"
#include "nvim/api/private/helpers.h"
#include "nvim/api/vim.h"
#include "nvim/ascii.h"
@@ -532,7 +531,7 @@ bool close_buffer(win_T *win, buf_T *buf, int action, bool abort_if_last)
}
if (buf->terminal) {
- terminal_close(buf->terminal, NULL);
+ terminal_close(buf->terminal, -1);
}
// Always remove the buffer when there is no file name.
@@ -757,7 +756,7 @@ void buf_freeall(buf_T *buf, int flags)
*/
static void free_buffer(buf_T *buf)
{
- handle_unregister_buffer(buf);
+ pmap_del(handle_T)(&buffer_handles, buf->b_fnum);
buf_free_count++;
// b:changedtick uses an item in buf_T.
free_buffer_stuff(buf, kBffClearWinInfo);
@@ -1841,7 +1840,7 @@ buf_T *buflist_new(char_u *ffname_arg, char_u *sfname_arg, linenr_T lnum,
lastbuf = buf;
buf->b_fnum = top_file_num++;
- handle_register_buffer(buf);
+ pmap_put(handle_T)(&buffer_handles, buf->b_fnum, buf);
if (top_file_num < 0) { // wrap around (may cause duplicates)
EMSG(_("W14: Warning: List of file names overflow"));
if (emsg_silent == 0) {
@@ -4253,7 +4252,7 @@ int build_stl_str_hl(
if (*fmt_p == '#') {
stl_items[curitem].type = Highlight;
stl_items[curitem].start = out_p;
- stl_items[curitem].minwid = -syn_namen2id(t, (int)(fmt_p - t));
+ stl_items[curitem].minwid = -syn_name2id_len(t, (size_t)(fmt_p - t));
curitem++;
fmt_p++;
}
diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h
index b03d69a04c..0ae8dd3664 100644
--- a/src/nvim/buffer_defs.h
+++ b/src/nvim/buffer_defs.h
@@ -863,8 +863,8 @@ struct file_buffer {
int b_mapped_ctrl_c; // modes where CTRL-C is mapped
MarkTree b_marktree[1];
- Map(uint64_t, ExtmarkItem) *b_extmark_index;
- Map(uint64_t, ExtmarkNs) *b_extmark_ns; // extmark namespaces
+ Map(uint64_t, ExtmarkItem) b_extmark_index[1];
+ Map(uint64_t, ExtmarkNs) b_extmark_ns[1]; // extmark namespaces
// array of channel_id:s which have asked to receive updates for this
// buffer.
diff --git a/src/nvim/change.c b/src/nvim/change.c
index 41e1e3911b..13b86e9244 100644
--- a/src/nvim/change.c
+++ b/src/nvim/change.c
@@ -1837,7 +1837,7 @@ void truncate_line(int fixpos)
/// Delete "nlines" lines at the cursor.
/// Saves the lines for undo first if "undo" is true.
-void del_lines(long nlines, int undo)
+void del_lines(long nlines, bool undo)
{
long n;
linenr_T first = curwin->w_cursor.lnum;
diff --git a/src/nvim/channel.c b/src/nvim/channel.c
index a0db1bcdfd..6f12d2eab8 100644
--- a/src/nvim/channel.c
+++ b/src/nvim/channel.c
@@ -32,13 +32,9 @@ static uint64_t next_chan_id = CHAN_STDERR+1;
/// Teardown the module
void channel_teardown(void)
{
- if (!channels) {
- return;
- }
-
Channel *channel;
- map_foreach_value(channels, channel, {
+ map_foreach_value(&channels, channel, {
channel_close(channel->id, kChannelPartAll, NULL);
});
}
@@ -152,7 +148,6 @@ bool channel_close(uint64_t id, ChannelPart part, const char **error)
/// Initializes the module
void channel_init(void)
{
- channels = pmap_new(uint64_t)();
channel_alloc(kChannelStreamStderr);
rpc_init();
}
@@ -177,7 +172,7 @@ Channel *channel_alloc(ChannelStreamType type)
chan->exit_status = -1;
chan->streamtype = type;
assert(chan->id <= VARNUMBER_MAX);
- pmap_put(uint64_t)(channels, chan->id, chan);
+ pmap_put(uint64_t)(&channels, chan->id, chan);
return chan;
}
@@ -249,7 +244,7 @@ static void free_channel_event(void **argv)
callback_reader_free(&chan->on_stderr);
callback_free(&chan->on_exit);
- pmap_del(uint64_t)(channels, chan->id);
+ pmap_del(uint64_t)(&channels, chan->id);
multiqueue_free(chan->events);
xfree(chan);
}
@@ -259,7 +254,7 @@ static void channel_destroy_early(Channel *chan)
if ((chan->id != --next_chan_id)) {
abort();
}
- pmap_del(uint64_t)(channels, chan->id);
+ pmap_del(uint64_t)(&channels, chan->id);
chan->id = 0;
if ((--chan->refcount != 0)) {
@@ -698,9 +693,7 @@ static void channel_process_exit_cb(Process *proc, int status, void *data)
{
Channel *chan = data;
if (chan->term) {
- char msg[sizeof("\r\n[Process exited ]") + NUMBUFLEN];
- snprintf(msg, sizeof msg, "\r\n[Process exited %d]", proc->status);
- terminal_close(chan->term, msg);
+ terminal_close(chan->term, status);
}
// If process did not exit, we only closed the handle of a detached process.
@@ -901,7 +894,7 @@ Array channel_all_info(void)
{
Channel *channel;
Array ret = ARRAY_DICT_INIT;
- map_foreach_value(channels, channel, {
+ map_foreach_value(&channels, channel, {
ADD(ret, DICTIONARY_OBJ(channel_info(channel->id)));
});
return ret;
diff --git a/src/nvim/channel.h b/src/nvim/channel.h
index df858e1602..9bc0df3615 100644
--- a/src/nvim/channel.h
+++ b/src/nvim/channel.h
@@ -89,7 +89,7 @@ struct Channel {
bool callback_scheduled;
};
-EXTERN PMap(uint64_t) *channels INIT(= NULL);
+EXTERN PMap(uint64_t) channels INIT(= MAP_INIT);
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "channel.h.generated.h"
@@ -98,7 +98,7 @@ EXTERN PMap(uint64_t) *channels INIT(= NULL);
/// @returns Channel with the id or NULL if not found
static inline Channel *find_channel(uint64_t id)
{
- return pmap_get(uint64_t)(channels, id);
+ return pmap_get(uint64_t)(&channels, id);
}
static inline Stream *channel_instream(Channel *chan)
diff --git a/src/nvim/decoration.c b/src/nvim/decoration.c
index 74cb9a26b7..5168ed6d0f 100644
--- a/src/nvim/decoration.c
+++ b/src/nvim/decoration.c
@@ -13,12 +13,7 @@
# include "decoration.c.generated.h"
#endif
-static PMap(uint64_t) *hl_decors;
-
-void decor_init(void)
-{
- hl_decors = pmap_new(uint64_t)();
-}
+static PMap(uint64_t) hl_decors;
/// Add highlighting to a buffer, bounded by two cursor positions,
/// with an offset.
@@ -77,7 +72,7 @@ void bufhl_add_hl_pos_offset(buf_T *buf,
Decoration *decor_hl(int hl_id)
{
assert(hl_id > 0);
- Decoration **dp = (Decoration **)pmap_ref(uint64_t)(hl_decors,
+ Decoration **dp = (Decoration **)pmap_ref(uint64_t)(&hl_decors,
(uint64_t)hl_id, true);
if (*dp) {
return *dp;
@@ -150,7 +145,7 @@ bool decor_redraw_reset(buf_T *buf, DecorState *state)
}
}
kv_size(state->active) = 0;
- return buf->b_extmark_index;
+ return map_size(buf->b_extmark_index);
}
diff --git a/src/nvim/edit.c b/src/nvim/edit.c
index fec8da2c3c..ffe60ab043 100644
--- a/src/nvim/edit.c
+++ b/src/nvim/edit.c
@@ -1652,8 +1652,8 @@ static void init_prompt(int cmdchar_todo)
check_cursor();
}
-// Return TRUE if the cursor is in the editable position of the prompt line.
-int prompt_curpos_editable(void)
+/// @return true if the cursor is in the editable position of the prompt line.
+bool prompt_curpos_editable(void)
{
return curwin->w_cursor.lnum == curbuf->b_ml.ml_line_count
&& curwin->w_cursor.col >= (int)STRLEN(prompt_text());
@@ -8124,8 +8124,7 @@ static bool ins_bs(int c, int mode, int *inserted_space_p)
// again when auto-formatting.
if (has_format_option(FO_AUTO)
&& has_format_option(FO_WHITE_PAR)) {
- char_u *ptr = ml_get_buf(curbuf, curwin->w_cursor.lnum,
- TRUE);
+ char_u *ptr = ml_get_buf(curbuf, curwin->w_cursor.lnum, true);
int len;
len = (int)STRLEN(ptr);
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index 472b43a387..5603fbb082 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -267,7 +267,7 @@ static partial_T *vvlua_partial;
#endif
static uint64_t last_timer_id = 1;
-static PMap(uint64_t) *timers = NULL;
+static PMap(uint64_t) timers = MAP_INIT;
static const char *const msgpack_type_names[] = {
[kMPNil] = "nil",
@@ -328,7 +328,6 @@ void eval_init(void)
{
vimvars[VV_VERSION].vv_nr = VIM_VERSION_100;
- timers = pmap_new(uint64_t)();
struct vimvar *p;
init_var_dict(&globvardict, &globvars_var, VAR_DEF_SCOPE);
@@ -5096,7 +5095,7 @@ bool garbage_collect(bool testing)
// Channels
{
Channel *data;
- map_foreach_value(channels, data, {
+ map_foreach_value(&channels, data, {
set_ref_in_callback_reader(&data->on_data, copyID, NULL, NULL);
set_ref_in_callback_reader(&data->on_stderr, copyID, NULL, NULL);
set_ref_in_callback(&data->on_exit, copyID, NULL, NULL);
@@ -5106,7 +5105,7 @@ bool garbage_collect(bool testing)
// Timers
{
timer_T *timer;
- map_foreach_value(timers, timer, {
+ map_foreach_value(&timers, timer, {
set_ref_in_callback(&timer->callback, copyID, NULL, NULL);
})
}
@@ -7519,7 +7518,7 @@ static bool set_ref_in_callback_reader(CallbackReader *reader, int copyID,
timer_T *find_timer_by_nr(varnumber_T xx)
{
- return pmap_get(uint64_t)(timers, xx);
+ return pmap_get(uint64_t)(&timers, xx);
}
void add_timer_info(typval_T *rettv, timer_T *timer)
@@ -7546,9 +7545,9 @@ void add_timer_info(typval_T *rettv, timer_T *timer)
void add_timer_info_all(typval_T *rettv)
{
- tv_list_alloc_ret(rettv, timers->table->n_occupied);
+ tv_list_alloc_ret(rettv, map_size(&timers));
timer_T *timer;
- map_foreach_value(timers, timer, {
+ map_foreach_value(&timers, timer, {
if (!timer->stopped) {
add_timer_info(rettv, timer);
}
@@ -7628,7 +7627,7 @@ uint64_t timer_start(const long timeout,
timer->tw.blockable = true;
time_watcher_start(&timer->tw, timer_due_cb, timeout, timeout);
- pmap_put(uint64_t)(timers, timer->timer_id, timer);
+ pmap_put(uint64_t)(&timers, timer->timer_id, timer);
return timer->timer_id;
}
@@ -7650,7 +7649,7 @@ static void timer_close_cb(TimeWatcher *tw, void *data)
timer_T *timer = (timer_T *)data;
multiqueue_free(timer->tw.events);
callback_free(&timer->callback);
- pmap_del(uint64_t)(timers, timer->timer_id);
+ pmap_del(uint64_t)(&timers, timer->timer_id);
timer_decref(timer);
}
@@ -7664,7 +7663,7 @@ static void timer_decref(timer_T *timer)
void timer_stop_all(void)
{
timer_T *timer;
- map_foreach_value(timers, timer, {
+ map_foreach_value(&timers, timer, {
timer_stop(timer);
})
}
diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c
index 041140211e..f7a1327c87 100644
--- a/src/nvim/ex_cmds.c
+++ b/src/nvim/ex_cmds.c
@@ -715,7 +715,7 @@ sortend:
void ex_retab(exarg_T *eap)
{
linenr_T lnum;
- int got_tab = FALSE;
+ bool got_tab = false;
long num_spaces = 0;
long num_tabs;
long len;
@@ -766,10 +766,11 @@ void ex_retab(exarg_T *eap)
start_vcol = vcol;
start_col = col;
}
- if (ptr[col] == ' ')
+ if (ptr[col] == ' ') {
num_spaces++;
- else
- got_tab = TRUE;
+ } else {
+ got_tab = true;
+ }
} else {
if (got_tab || (eap->forceit && num_spaces > 1)) {
/* Retabulate this string of white-space */
@@ -824,7 +825,7 @@ void ex_retab(exarg_T *eap)
col = start_col + len;
}
}
- got_tab = FALSE;
+ got_tab = false;
num_spaces = 0;
}
if (ptr[col] == NUL)
@@ -1386,11 +1387,11 @@ static void do_filter(
* Adjust '[ and '] (set by buf_write()).
*/
curwin->w_cursor.lnum = line1;
- del_lines(linecount, TRUE);
- curbuf->b_op_start.lnum -= linecount; /* adjust '[ */
- curbuf->b_op_end.lnum -= linecount; /* adjust '] */
- write_lnum_adjust(-linecount); /* adjust last line
- for next write */
+ del_lines(linecount, true);
+ curbuf->b_op_start.lnum -= linecount; // adjust '[
+ curbuf->b_op_end.lnum -= linecount; // adjust ']
+ write_lnum_adjust(-linecount); // adjust last line
+ // for next write
foldUpdate(curwin, curbuf->b_op_start.lnum, curbuf->b_op_end.lnum);
} else {
/*
@@ -2763,8 +2764,8 @@ int do_ecmd(
}
}
- /* Check if cursors in other windows on the same buffer are still valid */
- check_lnums(FALSE);
+ // Check if cursors in other windows on the same buffer are still valid
+ check_lnums(false);
/*
* Did not read the file, need to show some info about the file.
@@ -3835,7 +3836,7 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout,
_("replace with %s (y/n/a/q/l/^E/^Y)?"), sub);
msg_no_more = FALSE;
msg_scroll = i;
- showruler(TRUE);
+ showruler(true);
ui_cursor_goto(msg_row, msg_col);
RedrawingDisabled = temp;
@@ -5171,21 +5172,21 @@ void fix_help_buffer(void)
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(curbuf, lnum, TRUE);
+ // blank-out a '<' in the first column
+ line = ml_get_buf(curbuf, lnum, true);
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(curbuf, lnum, TRUE);
+ // blank-out a '>' in the last column (start of example)
+ line = ml_get_buf(curbuf, lnum, true);
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(curbuf, lnum, TRUE);
+ // blank-out a '~' at the end of line (header marker)
+ line = ml_get_buf(curbuf, lnum, true);
line[len - 1] = ' ';
}
}
@@ -5204,10 +5205,11 @@ void fix_help_buffer(void)
&& TOLOWER_ASC(fname[7]) == 'x'
&& fname[8] == NUL)
) {
- for (lnum = 1; lnum < curbuf->b_ml.ml_line_count; ++lnum) {
- line = ml_get_buf(curbuf, lnum, FALSE);
- if (strstr((char *)line, "*local-additions*") == NULL)
+ for (lnum = 1; lnum < curbuf->b_ml.ml_line_count; lnum++) {
+ line = ml_get_buf(curbuf, lnum, false);
+ if (strstr((char *)line, "*local-additions*") == NULL) {
continue;
+ }
/* Go through all directories in 'runtimepath', skipping
* $VIMRUNTIME. */
diff --git a/src/nvim/ex_cmds2.c b/src/nvim/ex_cmds2.c
index a49b0c15e1..e06a62e0f6 100644
--- a/src/nvim/ex_cmds2.c
+++ b/src/nvim/ex_cmds2.c
@@ -1460,7 +1460,7 @@ bool dialog_close_terminal(buf_T *buf)
int ret = vim_dialog_yesnocancel(VIM_QUESTION, NULL, buff, 1);
- return (ret == VIM_YES) ? true : false;
+ return ret == VIM_YES;
}
/// Return true if the buffer "buf" can be abandoned, either by making it
diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c
index af8a23f5cc..0f98c9cd34 100644
--- a/src/nvim/ex_getln.c
+++ b/src/nvim/ex_getln.c
@@ -5734,18 +5734,13 @@ HistoryType get_histtype(const char *const name, const size_t len,
static int last_maptick = -1; /* last seen maptick */
-/*
- * Add the given string to the given history. If the string is already in the
- * history then it is moved to the front. "histype" may be one of he HIST_
- * values.
- */
-void
-add_to_history (
- int histype,
- char_u *new_entry,
- int in_map, /* consider maptick when inside a mapping */
- int sep /* separator character used (search hist) */
-)
+/// Add the given string to the given history. If the string is already in the
+/// history then it is moved to the front. "histype" may be one of he HIST_
+/// values.
+///
+/// @parma in_map consider maptick when inside a mapping
+/// @param sep separator character used (search hist)
+void add_to_history(int histype, char_u *new_entry, int in_map, int sep)
{
histentry_T *hisptr;
@@ -6259,8 +6254,8 @@ static int open_cmdwin(void)
const int histtype = hist_char2type(cmdwin_type);
if (histtype == HIST_CMD || histtype == HIST_DEBUG) {
if (p_wc == TAB) {
- add_map((char_u *)"<buffer> <Tab> <C-X><C-V>", INSERT);
- add_map((char_u *)"<buffer> <Tab> a<C-X><C-V>", NORMAL);
+ add_map((char_u *)"<buffer> <Tab> <C-X><C-V>", INSERT, false);
+ add_map((char_u *)"<buffer> <Tab> a<C-X><C-V>", NORMAL, false);
}
set_option_value("ft", 0L, "vim", OPT_LOCAL);
}
diff --git a/src/nvim/extmark.c b/src/nvim/extmark.c
index 4b2dccd8a4..b4f22dbf33 100644
--- a/src/nvim/extmark.c
+++ b/src/nvim/extmark.c
@@ -48,20 +48,7 @@
#endif
static ExtmarkNs *buf_ns_ref(buf_T *buf, uint64_t ns_id, bool put) {
- if (!buf->b_extmark_ns) {
- if (!put) {
- return NULL;
- }
- buf->b_extmark_ns = map_new(uint64_t, ExtmarkNs)();
- buf->b_extmark_index = map_new(uint64_t, ExtmarkItem)();
- }
-
- ExtmarkNs *ns = map_ref(uint64_t, ExtmarkNs)(buf->b_extmark_ns, ns_id, put);
- if (put && ns->map == NULL) {
- ns->map = map_new(uint64_t, uint64_t)();
- ns->free_id = 1;
- }
- return ns;
+ return map_ref(uint64_t, ExtmarkNs)(buf->b_extmark_ns, ns_id, put);
}
@@ -195,7 +182,7 @@ bool extmark_clear(buf_T *buf, uint64_t ns_id,
int l_row, colnr_T l_col,
int u_row, colnr_T u_col)
{
- if (!buf->b_extmark_ns) {
+ if (!map_size(buf->b_extmark_ns)) {
return false;
}
@@ -215,12 +202,9 @@ bool extmark_clear(buf_T *buf, uint64_t ns_id,
}
// the value is either zero or the lnum (row+1) if highlight was present.
- static Map(uint64_t, ssize_t) *delete_set = NULL;
+ static Map(uint64_t, ssize_t) delete_set = MAP_INIT;
typedef struct { Decoration *decor; int row1; } DecorItem;
static kvec_t(DecorItem) decors;
- if (delete_set == NULL) {
- delete_set = map_new(uint64_t, ssize_t)();
- }
MarkTreeIter itr[1] = { 0 };
marktree_itr_get(buf->b_marktree, l_row, l_col, itr);
@@ -231,7 +215,7 @@ bool extmark_clear(buf_T *buf, uint64_t ns_id,
|| (mark.row == u_row && mark.col > u_col)) {
break;
}
- ssize_t *del_status = map_ref(uint64_t, ssize_t)(delete_set, mark.id,
+ ssize_t *del_status = map_ref(uint64_t, ssize_t)(&delete_set, mark.id,
false);
if (del_status) {
marktree_del_itr(buf->b_marktree, itr, false);
@@ -240,7 +224,7 @@ bool extmark_clear(buf_T *buf, uint64_t ns_id,
decor_redraw(buf, it.row1, mark.row, it.decor);
decor_free(it.decor);
}
- map_del(uint64_t, ssize_t)(delete_set, mark.id);
+ map_del(uint64_t, ssize_t)(&delete_set, mark.id);
continue;
}
@@ -261,7 +245,7 @@ bool extmark_clear(buf_T *buf, uint64_t ns_id,
kv_push(decors,
((DecorItem) { .decor = item.decor, .row1 = mark.row }));
}
- map_put(uint64_t, ssize_t)(delete_set, other, decor_id);
+ map_put(uint64_t, ssize_t)(&delete_set, other, decor_id);
} else if (item.decor) {
decor_redraw(buf, mark.row, mark.row, item.decor);
decor_free(item.decor);
@@ -276,7 +260,7 @@ bool extmark_clear(buf_T *buf, uint64_t ns_id,
}
uint64_t id;
ssize_t decor_id;
- map_foreach(delete_set, id, decor_id, {
+ map_foreach(&delete_set, id, decor_id, {
mtpos_t pos = marktree_lookup(buf->b_marktree, id, itr);
assert(itr->node);
marktree_del_itr(buf->b_marktree, itr, false);
@@ -286,7 +270,7 @@ bool extmark_clear(buf_T *buf, uint64_t ns_id,
decor_free(it.decor);
}
});
- map_clear(uint64_t, ssize_t)(delete_set);
+ map_clear(uint64_t, ssize_t)(&delete_set);
kv_size(decors) = 0;
return marks_cleared;
}
@@ -383,7 +367,7 @@ ExtmarkInfo extmark_from_id(buf_T *buf, uint64_t ns_id, uint64_t id)
// free extmarks from the buffer
void extmark_free_all(buf_T *buf)
{
- if (!buf->b_extmark_ns) {
+ if (!map_size(buf->b_extmark_ns)) {
return;
}
@@ -395,17 +379,17 @@ void extmark_free_all(buf_T *buf)
map_foreach(buf->b_extmark_ns, id, ns, {
(void)id;
- map_free(uint64_t, uint64_t)(ns.map);
+ map_destroy(uint64_t, uint64_t)(ns.map);
});
- map_free(uint64_t, ExtmarkNs)(buf->b_extmark_ns);
- buf->b_extmark_ns = NULL;
+ map_destroy(uint64_t, ExtmarkNs)(buf->b_extmark_ns);
+ map_init(uint64_t, ExtmarkNs, buf->b_extmark_ns);
map_foreach(buf->b_extmark_index, id, item, {
(void)id;
decor_free(item.decor);
});
- map_free(uint64_t, ExtmarkItem)(buf->b_extmark_index);
- buf->b_extmark_index = NULL;
+ map_destroy(uint64_t, ExtmarkItem)(buf->b_extmark_index);
+ map_init(uint64_t, ExtmarkItem, buf->b_extmark_index);
}
diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c
index ee8be8429f..3d058e1d09 100644
--- a/src/nvim/fileio.c
+++ b/src/nvim/fileio.c
@@ -11,7 +11,7 @@
#include <fcntl.h>
#include "nvim/vim.h"
-#include "nvim/api/private/handle.h"
+#include "nvim/api/private/helpers.h"
#include "nvim/ascii.h"
#include "nvim/fileio.h"
#include "nvim/buffer.h"
diff --git a/src/nvim/fold.c b/src/nvim/fold.c
index 6989c29d57..51a8a85aa0 100644
--- a/src/nvim/fold.c
+++ b/src/nvim/fold.c
@@ -2961,7 +2961,7 @@ static void foldlevelIndent(fline_T *flp)
linenr_T lnum = flp->lnum + flp->off;
buf = flp->wp->w_buffer;
- s = skipwhite(ml_get_buf(buf, lnum, FALSE));
+ s = skipwhite(ml_get_buf(buf, lnum, false));
/* empty line or lines starting with a character in 'foldignore': level
* depends on surrounding lines */
@@ -3123,7 +3123,7 @@ static void foldlevelMarker(fline_T *flp)
flp->start = 0;
flp->lvl_next = flp->lvl;
- s = ml_get_buf(flp->wp->w_buffer, flp->lnum + flp->off, FALSE);
+ s = ml_get_buf(flp->wp->w_buffer, flp->lnum + flp->off, false);
while (*s) {
if (*s == cstart
&& STRNCMP(s + 1, startmarker, foldstartmarkerlen - 1) == 0) {
diff --git a/src/nvim/generators/gen_api_dispatch.lua b/src/nvim/generators/gen_api_dispatch.lua
index 1d41cabfa4..c14b465f92 100644
--- a/src/nvim/generators/gen_api_dispatch.lua
+++ b/src/nvim/generators/gen_api_dispatch.lua
@@ -321,8 +321,6 @@ end
output:write([[
void msgpack_rpc_init_method_table(void)
{
- methods = map_new(String, MsgpackRpcRequestHandler)();
-
]])
for i = 1, #functions do
diff --git a/src/nvim/generators/gen_options.lua b/src/nvim/generators/gen_options.lua
index 9f91160034..0454c54faf 100644
--- a/src/nvim/generators/gen_options.lua
+++ b/src/nvim/generators/gen_options.lua
@@ -119,10 +119,10 @@ local get_value = function(v)
end
local get_defaults = function(d,n)
- if (d.vi == nil and d.vim == nil) or (d.vi ~= nil and d.vim ~= nil) then
- error("option '"..n.."' should have one and only one default value")
+ if d == nil then
+ error("option '"..n.."' should have a default value")
end
- return get_value(d.vim or d.vi)
+ return get_value(d)
end
local defines = {}
diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c
index f955fe8859..28f58e2c34 100644
--- a/src/nvim/getchar.c
+++ b/src/nvim/getchar.c
@@ -52,7 +52,6 @@
#include "nvim/os/input.h"
#include "nvim/os/os.h"
#include "nvim/os/fileio.h"
-#include "nvim/api/private/handle.h"
/// Index in scriptin
@@ -841,6 +840,14 @@ static void init_typebuf(void)
}
}
+void init_default_mappings(void)
+{
+ add_map((char_u *)"Y y$", NORMAL, true);
+ add_map((char_u *)"<C-L> <Cmd>nohlsearch<Bar>diffupdate<CR><C-L>", NORMAL, true);
+ add_map((char_u *)"<C-U> <C-G>u<C-U>", INSERT, true);
+ add_map((char_u *)"<C-W> <C-G>u<C-W>", INSERT, true);
+}
+
// Insert a string in position 'offset' in the typeahead buffer (for "@r"
// and ":normal" command, vgetorpeek() and check_termcode())
//
@@ -1162,7 +1169,7 @@ void may_sync_undo(void)
{
if ((!(State & (INSERT + CMDLINE)) || arrow_used)
&& scriptin[curscript] == NULL)
- u_sync(FALSE);
+ u_sync(false);
}
/*
@@ -4357,18 +4364,23 @@ check_map (
}
-/*
- * Add a mapping "map" for mode "mode".
- * Need to put string in allocated memory, because do_map() will modify it.
- */
-void add_map(char_u *map, int mode)
+/// Add a mapping. Unlike @ref do_map this copies the {map} argument, so
+/// static or read-only strings can be used.
+///
+/// @param map C-string containing the arguments of the map/abbrev command,
+/// i.e. everything except the initial `:[X][nore]map`.
+/// @param mode Bitflags representing the mode in which to set the mapping.
+/// See @ref get_map_mode.
+/// @param nore If true, make a non-recursive mapping.
+void add_map(char_u *map, int mode, bool nore)
{
char_u *s;
char_u *cpo_save = p_cpo;
p_cpo = (char_u *)""; // Allow <> notation
+ // Need to put string in allocated memory, because do_map() will modify it.
s = vim_strsave(map);
- (void)do_map(0, s, mode, FALSE);
+ (void)do_map(nore ? 2 : 0, s, mode, false);
xfree(s);
p_cpo = cpo_save;
}
diff --git a/src/nvim/highlight.c b/src/nvim/highlight.c
index 29ee7aae56..7341ac9393 100644
--- a/src/nvim/highlight.c
+++ b/src/nvim/highlight.c
@@ -25,22 +25,16 @@ static bool hlstate_active = false;
static kvec_t(HlEntry) attr_entries = KV_INITIAL_VALUE;
-static Map(HlEntry, int) *attr_entry_ids;
-static Map(int, int) *combine_attr_entries;
-static Map(int, int) *blend_attr_entries;
-static Map(int, int) *blendthrough_attr_entries;
+static Map(HlEntry, int) attr_entry_ids = MAP_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;
/// highlight entries private to a namespace
-static Map(ColorKey, ColorItem) *ns_hl;
+static Map(ColorKey, ColorItem) ns_hl;
void highlight_init(void)
{
- attr_entry_ids = map_new(HlEntry, int)();
- combine_attr_entries = map_new(int, int)();
- blend_attr_entries = map_new(int, int)();
- blendthrough_attr_entries = map_new(int, int)();
- ns_hl = map_new(ColorKey, ColorItem)();
-
// index 0 is no attribute, add dummy entry:
kv_push(attr_entries, ((HlEntry){ .attr = HLATTRS_INIT, .kind = kHlUnknown,
.id1 = 0, .id2 = 0 }));
@@ -71,7 +65,7 @@ static int get_attr_entry(HlEntry entry)
entry.id2 = 0;
}
- int id = map_get(HlEntry, int)(attr_entry_ids, entry);
+ int id = map_get(HlEntry, int)(&attr_entry_ids, entry);
if (id > 0) {
return id;
}
@@ -104,7 +98,7 @@ static int get_attr_entry(HlEntry entry)
id = (int)next_id;
kv_push(attr_entries, entry);
- map_put(HlEntry, int)(attr_entry_ids, entry, id);
+ map_put(HlEntry, int)(&attr_entry_ids, entry, id);
Array inspect = hl_inspect(id);
@@ -154,7 +148,7 @@ void ns_hl_def(NS ns_id, int hl_id, HlAttrs attrs, int link_id)
{
DecorProvider *p = get_decor_provider(ns_id, true);
if ((attrs.rgb_ae_attr & HL_DEFAULT)
- && map_has(ColorKey, ColorItem)(ns_hl, ColorKey(ns_id, hl_id))) {
+ && map_has(ColorKey, ColorItem)(&ns_hl, ColorKey(ns_id, hl_id))) {
return;
}
int attr_id = link_id > 0 ? -1 : hl_get_syn_attr(ns_id, hl_id, attrs);
@@ -162,7 +156,7 @@ void ns_hl_def(NS ns_id, int hl_id, HlAttrs attrs, int link_id)
.link_id = link_id,
.version = p->hl_valid,
.is_default = (attrs.rgb_ae_attr & HL_DEFAULT) };
- map_put(ColorKey, ColorItem)(ns_hl, ColorKey(ns_id, hl_id), it);
+ map_put(ColorKey, ColorItem)(&ns_hl, ColorKey(ns_id, hl_id), it);
}
int ns_get_hl(NS ns_id, int hl_id, bool link, bool nodefault)
@@ -177,7 +171,7 @@ int ns_get_hl(NS ns_id, int hl_id, bool link, bool nodefault)
}
DecorProvider *p = get_decor_provider(ns_id, true);
- ColorItem it = map_get(ColorKey, ColorItem)(ns_hl, ColorKey(ns_id, hl_id));
+ ColorItem it = map_get(ColorKey, ColorItem)(&ns_hl, ColorKey(ns_id, hl_id));
// TODO(bfredl): map_ref true even this?
bool valid_cache = it.version >= p->hl_valid;
@@ -220,7 +214,7 @@ int ns_get_hl(NS ns_id, int hl_id, bool link, bool nodefault)
it.attr_id = fallback ? -1 : hl_get_syn_attr((int)ns_id, hl_id, attrs);
it.version = p->hl_valid-tmp;
it.is_default = attrs.rgb_ae_attr & HL_DEFAULT;
- map_put(ColorKey, ColorItem)(ns_hl, ColorKey(ns_id, hl_id), it);
+ map_put(ColorKey, ColorItem)(&ns_hl, ColorKey(ns_id, hl_id), it);
}
if (it.is_default && nodefault) {
@@ -395,28 +389,28 @@ void clear_hl_tables(bool reinit)
{
if (reinit) {
kv_size(attr_entries) = 1;
- map_clear(HlEntry, int)(attr_entry_ids);
- map_clear(int, int)(combine_attr_entries);
- map_clear(int, int)(blend_attr_entries);
- map_clear(int, int)(blendthrough_attr_entries);
+ map_clear(HlEntry, int)(&attr_entry_ids);
+ map_clear(int, int)(&combine_attr_entries);
+ map_clear(int, int)(&blend_attr_entries);
+ map_clear(int, int)(&blendthrough_attr_entries);
memset(highlight_attr_last, -1, sizeof(highlight_attr_last));
highlight_attr_set_all();
highlight_changed();
screen_invalidate_highlights();
} else {
kv_destroy(attr_entries);
- map_free(HlEntry, int)(attr_entry_ids);
- map_free(int, int)(combine_attr_entries);
- map_free(int, int)(blend_attr_entries);
- map_free(int, int)(blendthrough_attr_entries);
- map_free(ColorKey, ColorItem)(ns_hl);
+ map_destroy(HlEntry, int)(&attr_entry_ids);
+ map_destroy(int, int)(&combine_attr_entries);
+ map_destroy(int, int)(&blend_attr_entries);
+ map_destroy(int, int)(&blendthrough_attr_entries);
+ map_destroy(ColorKey, ColorItem)(&ns_hl);
}
}
void hl_invalidate_blends(void)
{
- map_clear(int, int)(blend_attr_entries);
- map_clear(int, int)(blendthrough_attr_entries);
+ map_clear(int, int)(&blend_attr_entries);
+ map_clear(int, int)(&blendthrough_attr_entries);
highlight_changed();
update_window_hl(curwin, true);
}
@@ -437,7 +431,7 @@ int hl_combine_attr(int char_attr, int prim_attr)
// TODO(bfredl): could use a struct for clearer intent.
int combine_tag = (char_attr << 16) + prim_attr;
- int id = map_get(int, int)(combine_attr_entries, combine_tag);
+ int id = map_get(int, int)(&combine_attr_entries, combine_tag);
if (id > 0) {
return id;
}
@@ -494,7 +488,7 @@ int hl_combine_attr(int char_attr, int prim_attr)
id = get_attr_entry((HlEntry){ .attr = new_en, .kind = kHlCombine,
.id1 = char_attr, .id2 = prim_attr });
if (id > 0) {
- map_put(int, int)(combine_attr_entries, combine_tag, id);
+ map_put(int, int)(&combine_attr_entries, combine_tag, id);
}
return id;
@@ -550,8 +544,8 @@ int hl_blend_attrs(int back_attr, int front_attr, bool *through)
int combine_tag = (back_attr << 16) + front_attr;
Map(int, int) *map = (*through
- ? blendthrough_attr_entries
- : blend_attr_entries);
+ ? &blendthrough_attr_entries
+ : &blend_attr_entries);
int id = map_get(int, int)(map, combine_tag);
if (id > 0) {
return id;
diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c
index cb3cb6e73e..b00c4282be 100644
--- a/src/nvim/lua/executor.c
+++ b/src/nvim/lua/executor.c
@@ -13,7 +13,6 @@
#include "nvim/func_attr.h"
#include "nvim/api/private/defs.h"
#include "nvim/api/private/helpers.h"
-#include "nvim/api/private/handle.h"
#include "nvim/api/vim.h"
#include "nvim/msgpack_rpc/channel.h"
#include "nvim/vim.h"
@@ -40,6 +39,7 @@
#include "nvim/lua/converter.h"
#include "nvim/lua/executor.h"
#include "nvim/lua/treesitter.h"
+#include "nvim/lua/xdiff.h"
#include "luv/luv.h"
@@ -68,7 +68,8 @@ typedef struct {
}
#if __has_feature(address_sanitizer)
- PMap(handle_T) *nlua_ref_markers = NULL;
+ static PMap(handle_T) nlua_ref_markers = MAP_INIT;
+ static bool nlua_track_refs = false;
# define NLUA_TRACK_REFS
#endif
@@ -517,6 +518,10 @@ static int nlua_state_init(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL
// internal vim._treesitter... API
nlua_add_treesitter(lstate);
+ // vim.diff
+ lua_pushcfunction(lstate, &nlua_xdl_diff);
+ lua_setfield(lstate, -2, "diff");
+
lua_setglobal(lstate, "vim");
{
@@ -564,7 +569,7 @@ void nlua_init(void)
#ifdef NLUA_TRACK_REFS
const char *env = os_getenv("NVIM_LUA_NOTRACK");
if (!env || !*env) {
- nlua_ref_markers = pmap_new(handle_T)();
+ nlua_track_refs = true;
}
#endif
@@ -595,10 +600,10 @@ void nlua_free_all_mem(void)
fprintf(stderr, "%d lua references were leaked!", nlua_refcount);
}
- if (nlua_ref_markers) {
+ if (nlua_track_refs) {
// in case there are leaked luarefs, leak the associated memory
// to get LeakSanitizer stacktraces on exit
- pmap_free(handle_T)(nlua_ref_markers);
+ pmap_destroy(handle_T)(&nlua_ref_markers);
}
#endif
@@ -997,9 +1002,9 @@ LuaRef nlua_ref(lua_State *lstate, int index)
if (ref > 0) {
nlua_refcount++;
#ifdef NLUA_TRACK_REFS
- if (nlua_ref_markers) {
+ if (nlua_track_refs) {
// dummy allocation to make LeakSanitizer track our luarefs
- pmap_put(handle_T)(nlua_ref_markers, ref, xmalloc(3));
+ pmap_put(handle_T)(&nlua_ref_markers, ref, xmalloc(3));
}
#endif
}
@@ -1013,8 +1018,8 @@ void nlua_unref(lua_State *lstate, LuaRef ref)
nlua_refcount--;
#ifdef NLUA_TRACK_REFS
// NB: don't remove entry from map to track double-unref
- if (nlua_ref_markers) {
- xfree(pmap_get(handle_T)(nlua_ref_markers, ref));
+ if (nlua_track_refs) {
+ xfree(pmap_get(handle_T)(&nlua_ref_markers, ref));
}
#endif
luaL_unref(lstate, LUA_REGISTRYINDEX, ref);
diff --git a/src/nvim/lua/treesitter.c b/src/nvim/lua/treesitter.c
index 1425baacf0..ed475c324f 100644
--- a/src/nvim/lua/treesitter.c
+++ b/src/nvim/lua/treesitter.c
@@ -18,7 +18,7 @@
#include "tree_sitter/api.h"
#include "nvim/lua/treesitter.h"
-#include "nvim/api/private/handle.h"
+#include "nvim/api/private/helpers.h"
#include "nvim/memline.h"
#include "nvim/buffer.h"
@@ -80,6 +80,10 @@ static struct luaL_Reg node_meta[] = {
{ "parent", node_parent },
{ "iter_children", node_iter_children },
{ "_rawquery", node_rawquery },
+ { "next_sibling", node_next_sibling },
+ { "prev_sibling", node_prev_sibling },
+ { "next_named_sibling", node_next_named_sibling },
+ { "prev_named_sibling", node_prev_named_sibling },
{ NULL, NULL }
};
@@ -101,7 +105,7 @@ static struct luaL_Reg treecursor_meta[] = {
{ NULL, NULL }
};
-static PMap(cstr_t) *langs;
+static PMap(cstr_t) langs = MAP_INIT;
static void build_meta(lua_State *L, const char *tname, const luaL_Reg *meta)
{
@@ -119,8 +123,6 @@ static void build_meta(lua_State *L, const char *tname, const luaL_Reg *meta)
/// all global state is stored in the regirstry of the lua_State
void tslua_init(lua_State *L)
{
- langs = pmap_new(cstr_t)();
-
// type metatables
build_meta(L, TS_META_PARSER, parser_meta);
build_meta(L, TS_META_TREE, tree_meta);
@@ -133,7 +135,7 @@ void tslua_init(lua_State *L)
int tslua_has_language(lua_State *L)
{
const char *lang_name = luaL_checkstring(L, 1);
- lua_pushboolean(L, pmap_has(cstr_t)(langs, lang_name));
+ lua_pushboolean(L, pmap_has(cstr_t)(&langs, lang_name));
return 1;
}
@@ -142,7 +144,7 @@ int tslua_add_language(lua_State *L)
const char *path = luaL_checkstring(L, 1);
const char *lang_name = luaL_checkstring(L, 2);
- if (pmap_has(cstr_t)(langs, lang_name)) {
+ if (pmap_has(cstr_t)(&langs, lang_name)) {
return 0;
}
@@ -185,7 +187,7 @@ int tslua_add_language(lua_State *L)
TREE_SITTER_LANGUAGE_VERSION, lang_version);
}
- pmap_put(cstr_t)(langs, xstrdup(lang_name), lang);
+ pmap_put(cstr_t)(&langs, xstrdup(lang_name), lang);
lua_pushboolean(L, true);
return 1;
@@ -195,7 +197,7 @@ int tslua_inspect_lang(lua_State *L)
{
const char *lang_name = luaL_checkstring(L, 1);
- TSLanguage *lang = pmap_get(cstr_t)(langs, lang_name);
+ TSLanguage *lang = pmap_get(cstr_t)(&langs, lang_name);
if (!lang) {
return luaL_error(L, "no such language: %s", lang_name);
}
@@ -243,7 +245,7 @@ int tslua_push_parser(lua_State *L)
// Gather language name
const char *lang_name = luaL_checkstring(L, 1);
- TSLanguage *lang = pmap_get(cstr_t)(langs, lang_name);
+ TSLanguage *lang = pmap_get(cstr_t)(&langs, lang_name);
if (!lang) {
return luaL_error(L, "no such language: %s", lang_name);
}
@@ -992,6 +994,50 @@ static int node_parent(lua_State *L)
return 1;
}
+static int node_next_sibling(lua_State *L)
+{
+ TSNode node;
+ if (!node_check(L, 1, &node)) {
+ return 0;
+ }
+ TSNode sibling = ts_node_next_sibling(node);
+ push_node(L, sibling, 1);
+ return 1;
+}
+
+static int node_prev_sibling(lua_State *L)
+{
+ TSNode node;
+ if (!node_check(L, 1, &node)) {
+ return 0;
+ }
+ TSNode sibling = ts_node_prev_sibling(node);
+ push_node(L, sibling, 1);
+ return 1;
+}
+
+static int node_next_named_sibling(lua_State *L)
+{
+ TSNode node;
+ if (!node_check(L, 1, &node)) {
+ return 0;
+ }
+ TSNode sibling = ts_node_next_named_sibling(node);
+ push_node(L, sibling, 1);
+ return 1;
+}
+
+static int node_prev_named_sibling(lua_State *L)
+{
+ TSNode node;
+ if (!node_check(L, 1, &node)) {
+ return 0;
+ }
+ TSNode sibling = ts_node_prev_named_sibling(node);
+ push_node(L, sibling, 1);
+ return 1;
+}
+
/// assumes the match table being on top of the stack
static void set_match(lua_State *L, TSQueryMatch *match, int nodeidx)
{
@@ -1127,7 +1173,7 @@ int tslua_parse_query(lua_State *L)
}
const char *lang_name = lua_tostring(L, 1);
- TSLanguage *lang = pmap_get(cstr_t)(langs, lang_name);
+ TSLanguage *lang = pmap_get(cstr_t)(&langs, lang_name);
if (!lang) {
return luaL_error(L, "no such language: %s", lang_name);
}
diff --git a/src/nvim/lua/vim.lua b/src/nvim/lua/vim.lua
index 8cecaa51dd..ed435439a4 100644
--- a/src/nvim/lua/vim.lua
+++ b/src/nvim/lua/vim.lua
@@ -178,8 +178,8 @@ end
--- Return a human-readable representation of the given object.
---
---@see https://github.com/kikito/inspect.lua
---@see https://github.com/mpeterv/vinspect
+---@see https://github.com/kikito/inspect.lua
+---@see https://github.com/mpeterv/vinspect
local function inspect(object, options) -- luacheck: no unused
error(object, options) -- Stub for gen_vimdoc.py
end
@@ -203,15 +203,15 @@ do
--- end)(vim.paste)
--- </pre>
---
- --@see |paste|
+ ---@see |paste|
---
- --@param lines |readfile()|-style list of lines to paste. |channel-lines|
- --@param phase -1: "non-streaming" paste: the call contains all lines.
+ ---@param lines |readfile()|-style list of lines to paste. |channel-lines|
+ ---@param phase -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)
- --@returns false if client should cancel the paste.
+ ---@returns false if client should cancel the paste.
function vim.paste(lines, phase)
local call = vim.api.nvim_call_function
local now = vim.loop.now()
@@ -279,7 +279,7 @@ function vim.schedule_wrap(cb)
end
--- <Docs described in |vim.empty_dict()| >
---@private
+---@private
function vim.empty_dict()
return setmetatable({}, vim._empty_dict_mt)
end
@@ -338,12 +338,12 @@ end
--- Get a table of lines with start, end columns for a region marked by two points
---
---@param bufnr number of buffer
---@param pos1 (line, column) tuple marking beginning of region
---@param pos2 (line, column) tuple marking end of region
---@param regtype type of selection (:help setreg)
---@param inclusive boolean indicating whether the selection is end-inclusive
---@return region lua table of the form {linenr = {startcol,endcol}}
+---@param bufnr number of buffer
+---@param pos1 (line, column) tuple marking beginning of region
+---@param pos2 (line, column) tuple marking end of region
+---@param regtype type of selection (:help setreg)
+---@param inclusive boolean indicating whether the selection is end-inclusive
+---@return region lua table of the form {linenr = {startcol,endcol}}
function vim.region(bufnr, pos1, pos2, regtype, inclusive)
if not vim.api.nvim_buf_is_loaded(bufnr) then
vim.fn.bufload(bufnr)
@@ -390,9 +390,9 @@ end
--- Use to do a one-shot timer that calls `fn`
--- Note: The {fn} is |schedule_wrap|ped automatically, so API functions are
--- safe to call.
---@param fn Callback to call once `timeout` expires
---@param timeout Number of milliseconds to wait before calling `fn`
---@return timer luv timer object
+---@param fn Callback to call once `timeout` expires
+---@param timeout Number of milliseconds to wait before calling `fn`
+---@return timer luv timer object
function vim.defer_fn(fn, timeout)
vim.validate { fn = { fn, 'c', true}; }
local timer = vim.loop.new_timer()
@@ -408,11 +408,12 @@ end
--- Notification provider
---- without a runtime, writes to :Messages
--- see :help nvim_notify
---@param msg Content of the notification to show to the user
---@param log_level Optional log level
---@param opts Dictionary with optional options (timeout, etc)
+---
+--- Without a runtime, writes to :Messages
+---@see :help nvim_notify
+---@param msg Content of the notification to show to the user
+---@param log_level Optional log level
+---@param opts Dictionary with optional options (timeout, etc)
function vim.notify(msg, log_level, _opts)
if log_level == vim.log.levels.ERROR then
@@ -429,21 +430,21 @@ local on_keystroke_callbacks = {}
--- Register a lua {fn} with an {id} to be run after every keystroke.
---
---@param fn function: Function to call. It should take one argument, which is a string.
+---@param fn function: Function to call. It should take one argument, which is a string.
--- The string will contain the literal keys typed.
--- See |i_CTRL-V|
---
--- If {fn} is nil, it removes the callback for the associated {ns_id}
---@param ns_id number? Namespace ID. If not passed or 0, will generate and return a new
+---@param ns_id number? Namespace ID. If not passed or 0, will generate and return a new
--- namespace ID from |nvim_create_namesapce()|
---
---@return number Namespace ID associated with {fn}
+---@return number Namespace ID associated with {fn}
---
---@note {fn} will be automatically removed if an error occurs while calling.
+---@note {fn} will be automatically removed if an error occurs while calling.
--- This is to prevent the annoying situation of every keystroke erroring
--- while trying to remove a broken callback.
---@note {fn} will not be cleared from |nvim_buf_clear_namespace()|
---@note {fn} will receive the keystrokes after mappings have been evaluated
+---@note {fn} will not be cleared from |nvim_buf_clear_namespace()|
+---@note {fn} will receive the keystrokes after mappings have been evaluated
function vim.register_keystroke_callback(fn, ns_id)
vim.validate {
fn = { fn, 'c', true},
@@ -459,7 +460,7 @@ function vim.register_keystroke_callback(fn, ns_id)
end
--- Function that executes the keystroke callbacks.
---@private
+---@private
function vim._log_keystroke(char)
local failed_ns_ids = {}
local failed_messages = {}
diff --git a/src/nvim/lua/xdiff.c b/src/nvim/lua/xdiff.c
new file mode 100644
index 0000000000..d50f874a82
--- /dev/null
+++ b/src/nvim/lua/xdiff.c
@@ -0,0 +1,334 @@
+#include <lua.h>
+#include <lualib.h>
+#include <lauxlib.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+
+#include "nvim/vim.h"
+#include "nvim/xdiff/xdiff.h"
+#include "nvim/lua/xdiff.h"
+#include "nvim/lua/converter.h"
+#include "nvim/lua/executor.h"
+#include "nvim/api/private/helpers.h"
+
+typedef enum {
+ kNluaXdiffModeUnified = 0,
+ kNluaXdiffModeOnHunkCB,
+ kNluaXdiffModeLocations,
+} NluaXdiffMode;
+
+typedef struct {
+ lua_State *lstate;
+ Error *err;
+} hunkpriv_t;
+
+#ifdef INCLUDE_GENERATED_DECLARATIONS
+# include "lua/xdiff.c.generated.h"
+#endif
+
+static int write_string(void *priv, mmbuffer_t *mb, int nbuf)
+{
+ luaL_Buffer *buf = (luaL_Buffer *)priv;
+ for (int i = 0; i < nbuf; i++) {
+ const long size = mb[i].size;
+ for (long total = 0; total < size; total += LUAL_BUFFERSIZE) {
+ const int tocopy = MIN((int)(size - total), LUAL_BUFFERSIZE);
+ char *p = luaL_prepbuffer(buf);
+ if (!p) {
+ return -1;
+ }
+ memcpy(p, mb[i].ptr + total, (unsigned)tocopy);
+ luaL_addsize(buf, (unsigned)tocopy);
+ }
+ }
+ return 0;
+}
+
+// hunk_func callback used when opts.hunk_lines = true
+static int hunk_locations_cb(long start_a, long count_a,
+ long start_b, long count_b, void *cb_data)
+{
+ // Mimic extra offsets done by xdiff, see:
+ // src/nvim/xdiff/xemit.c:284
+ // src/nvim/xdiff/xutils.c:(356,368)
+ if (count_a > 0) {
+ start_a += 1;
+ }
+ if (count_b > 0) {
+ start_b += 1;
+ }
+
+ lua_State * lstate = (lua_State *)cb_data;
+ lua_createtable(lstate, 0, 0);
+
+ lua_pushinteger(lstate, start_a);
+ lua_rawseti(lstate, -2, 1);
+ lua_pushinteger(lstate, count_a);
+ lua_rawseti(lstate, -2, 2);
+ lua_pushinteger(lstate, start_b);
+ lua_rawseti(lstate, -2, 3);
+ lua_pushinteger(lstate, count_b);
+ lua_rawseti(lstate, -2, 4);
+
+ lua_rawseti(lstate, -2, (signed)lua_objlen(lstate, -2)+1);
+
+ return 0;
+}
+
+// hunk_func callback used when opts.on_hunk is given
+static int call_on_hunk_cb(long start_a, long count_a,
+ long start_b, long count_b, void *cb_data)
+{
+ // Mimic extra offsets done by xdiff, see:
+ // src/nvim/xdiff/xemit.c:284
+ // src/nvim/xdiff/xutils.c:(356,368)
+ if (count_a > 0) {
+ start_a += 1;
+ }
+ if (count_b > 0) {
+ start_b += 1;
+ }
+
+ hunkpriv_t *priv = (hunkpriv_t *)cb_data;
+ lua_State * lstate = priv->lstate;
+ Error *err = priv->err;
+ const int fidx = lua_gettop(lstate);
+ lua_pushvalue(lstate, fidx);
+ lua_pushinteger(lstate, start_a);
+ lua_pushinteger(lstate, count_a);
+ lua_pushinteger(lstate, start_b);
+ lua_pushinteger(lstate, count_b);
+
+ if (lua_pcall(lstate, 4, 1, 0) != 0) {
+ api_set_error(err, kErrorTypeException,
+ "error running function on_hunk: %s",
+ lua_tostring(lstate, -1));
+ return -1;
+ }
+
+ int r = 0;
+ if (lua_isnumber(lstate, -1)) {
+ r = (int)lua_tonumber(lstate, -1);
+ }
+
+ lua_pop(lstate, 1);
+ lua_settop(lstate, fidx);
+ return r;
+}
+
+static mmfile_t get_string_arg(lua_State *lstate, int idx)
+{
+ if (lua_type(lstate, idx) != LUA_TSTRING) {
+ luaL_argerror(lstate, idx, "expected string");
+ }
+ mmfile_t mf;
+ mf.ptr = (char *)lua_tolstring(lstate, idx, (size_t *)&mf.size);
+ 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, Error *err)
+{
+ const DictionaryOf(LuaRef) opts = nlua_pop_Dictionary(lstate, true, 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)) {
+ } 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)) {
+ cfg->flags |= XDF_NEED_MINIMAL;
+ } else if (strequal("patience", v->data.string.data)) {
+ cfg->flags |= XDF_PATIENCE_DIFF;
+ } else if (strequal("histogram", v->data.string.data)) {
+ cfg->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 = v->data.integer;
+ } else if (strequal("interhunkctxlen", k.data)) {
+ if (check_xdiff_opt(v->type, kObjectTypeInteger, "interhunkctxlen",
+ err)) {
+ goto exit_1;
+ }
+ cfg->interhunkctxlen = v->data.integer;
+ } 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;
+ }
+ }
+
+ if (key_used) {
+ continue;
+ }
+
+ api_set_error(err, kErrorTypeValidation, "unexpected key: %s", k.data);
+ goto exit_1;
+ }
+ }
+
+ if (had_on_hunk) {
+ mode = kNluaXdiffModeOnHunkCB;
+ cfg->hunk_func = call_on_hunk_cb;
+ } else if (had_result_type_indices) {
+ mode = kNluaXdiffModeLocations;
+ cfg->hunk_func = hunk_locations_cb;
+ }
+
+exit_1:
+ api_free_dictionary(opts);
+ return mode;
+}
+
+int nlua_xdl_diff(lua_State *lstate)
+{
+ if (lua_gettop(lstate) < 2) {
+ return luaL_error(lstate, "Expected at least 2 arguments");
+ }
+ mmfile_t ma = get_string_arg(lstate, 1);
+ mmfile_t mb = get_string_arg(lstate, 2);
+
+ Error err = ERROR_INIT;
+
+ xdemitconf_t cfg;
+ xpparam_t params;
+ xdemitcb_t ecb;
+
+ memset(&cfg , 0, sizeof(cfg));
+ memset(&params, 0, sizeof(params));
+ memset(&ecb , 0, sizeof(ecb));
+
+ NluaXdiffMode mode = kNluaXdiffModeUnified;
+
+ if (lua_gettop(lstate) == 3) {
+ if (lua_type(lstate, 3) != LUA_TTABLE) {
+ return luaL_argerror(lstate, 3, "expected table");
+ }
+
+ mode = process_xdl_diff_opts(lstate, &cfg, &params, &err);
+
+ if (ERROR_SET(&err)) {
+ goto exit_0;
+ }
+ }
+
+ luaL_Buffer buf;
+ hunkpriv_t *priv = NULL;
+ switch (mode) {
+ case kNluaXdiffModeUnified:
+ luaL_buffinit(lstate, &buf);
+ ecb.priv = &buf;
+ ecb.outf = write_string;
+ break;
+ case kNluaXdiffModeOnHunkCB:
+ priv = xmalloc(sizeof(*priv));
+ priv->lstate = lstate;
+ priv->err = &err;
+ ecb.priv = priv;
+ break;
+ case kNluaXdiffModeLocations:
+ lua_createtable(lstate, 0, 0);
+ ecb.priv = lstate;
+ break;
+ }
+
+ if (xdl_diff(&ma, &mb, &params, &cfg, &ecb) == -1) {
+ if (!ERROR_SET(&err)) {
+ api_set_error(&err, kErrorTypeException,
+ "Error while performing diff operation");
+ }
+ }
+
+ XFREE_CLEAR(priv);
+
+exit_0:
+ if (ERROR_SET(&err)) {
+ luaL_where(lstate, 1);
+ lua_pushstring(lstate, err.msg);
+ api_clear_error(&err);
+ lua_concat(lstate, 2);
+ return lua_error(lstate);
+ } else if (mode == kNluaXdiffModeUnified) {
+ luaL_pushresult(&buf);
+ return 1;
+ } else if (mode == kNluaXdiffModeLocations) {
+ return 1;
+ }
+ return 0;
+}
diff --git a/src/nvim/lua/xdiff.h b/src/nvim/lua/xdiff.h
new file mode 100644
index 0000000000..cae7c98e81
--- /dev/null
+++ b/src/nvim/lua/xdiff.h
@@ -0,0 +1,12 @@
+#ifndef NVIM_LUA_XDIFF_H
+#define NVIM_LUA_XDIFF_H
+
+#include <lua.h>
+#include <lualib.h>
+#include <lauxlib.h>
+
+#ifdef INCLUDE_GENERATED_DECLARATIONS
+# include "lua/xdiff.h.generated.h"
+#endif
+
+#endif // NVIM_LUA_XDIFF_H
diff --git a/src/nvim/main.c b/src/nvim/main.c
index 252aa81825..9fc82a75af 100644
--- a/src/nvim/main.c
+++ b/src/nvim/main.c
@@ -78,7 +78,6 @@
#include "nvim/api/ui.h"
#include "nvim/api/private/defs.h"
#include "nvim/api/private/helpers.h"
-#include "nvim/api/private/handle.h"
#include "nvim/api/private/dispatch.h"
#ifndef WIN32
# include "nvim/os/pty_process_unix.h"
@@ -126,8 +125,6 @@ void event_init(void)
signal_init();
// finish mspgack-rpc initialization
channel_init();
- remote_ui_init();
- api_vim_init();
terminal_init();
ui_init();
}
@@ -160,8 +157,6 @@ void early_init(mparm_T *paramp)
{
env_init();
fs_init();
- handle_init();
- decor_init();
eval_init(); // init global variables
init_path(argv0 ? argv0 : "nvim");
init_normal_cmds(); // Init the table of Normal mode commands.
@@ -314,6 +309,9 @@ int main(int argc, char **argv)
init_highlight(true, false); // Default highlight groups.
TIME_MSG("init highlight");
+ init_default_mappings(); // Default mappings.
+ TIME_MSG("init default mappings");
+
// Set the break level after the terminal is initialized.
debug_break_level = params.use_debug_break_level;
diff --git a/src/nvim/map.c b/src/nvim/map.c
index 7d97b7f13d..ccd332192e 100644
--- a/src/nvim/map.c
+++ b/src/nvim/map.c
@@ -54,56 +54,48 @@
INITIALIZER_DECLARE(T, U, __VA_ARGS__); \
__KHASH_IMPL(T##_##U##_map,, T, U, 1, T##_hash, T##_eq) \
\
- Map(T, U) *map_##T##_##U##_new() \
+ void map_##T##_##U##_destroy(Map(T, U) *map) \
{ \
- Map(T, U) *rv = xmalloc(sizeof(Map(T, U))); \
- rv->table = kh_init(T##_##U##_map); \
- return rv; \
- } \
- \
- void map_##T##_##U##_free(Map(T, U) *map) \
- { \
- kh_destroy(T##_##U##_map, map->table); \
- xfree(map); \
+ kh_dealloc(T##_##U##_map, &map->table); \
} \
\
U map_##T##_##U##_get(Map(T, U) *map, T key) \
{ \
khiter_t k; \
\
- if ((k = kh_get(T##_##U##_map, map->table, key)) == kh_end(map->table)) { \
+ if ((k = kh_get(T##_##U##_map, &map->table, key)) == kh_end(&map->table)) { \
return INITIALIZER(T, U); \
} \
\
- return kh_val(map->table, k); \
+ return kh_val(&map->table, k); \
} \
\
bool map_##T##_##U##_has(Map(T, U) *map, T key) \
{ \
- return kh_get(T##_##U##_map, map->table, key) != kh_end(map->table); \
+ return kh_get(T##_##U##_map, &map->table, key) != kh_end(&map->table); \
} \
\
T map_##T##_##U##_key(Map(T, U) *map, T key) \
{ \
khiter_t k; \
\
- if ((k = kh_get(T##_##U##_map, map->table, key)) == kh_end(map->table)) { \
+ if ((k = kh_get(T##_##U##_map, &map->table, key)) == kh_end(&map->table)) { \
abort(); /* Caller must check map_has(). */ \
} \
\
- return kh_key(map->table, k); \
+ return kh_key(&map->table, k); \
} \
U map_##T##_##U##_put(Map(T, U) *map, T key, U value) \
{ \
int ret; \
U rv = INITIALIZER(T, U); \
- khiter_t k = kh_put(T##_##U##_map, map->table, key, &ret); \
+ khiter_t k = kh_put(T##_##U##_map, &map->table, key, &ret); \
\
if (!ret) { \
- rv = kh_val(map->table, k); \
+ rv = kh_val(&map->table, k); \
} \
\
- kh_val(map->table, k) = value; \
+ kh_val(&map->table, k) = value; \
return rv; \
} \
\
@@ -112,18 +104,18 @@
int ret; \
khiter_t k; \
if (put) { \
- k = kh_put(T##_##U##_map, map->table, key, &ret); \
+ k = kh_put(T##_##U##_map, &map->table, key, &ret); \
if (ret) { \
- kh_val(map->table, k) = INITIALIZER(T, U); \
+ kh_val(&map->table, k) = INITIALIZER(T, U); \
} \
} else { \
- k = kh_get(T##_##U##_map, map->table, key); \
- if (k == kh_end(map->table)) { \
+ k = kh_get(T##_##U##_map, &map->table, key); \
+ if (k == kh_end(&map->table)) { \
return NULL; \
} \
} \
\
- return &kh_val(map->table, k); \
+ return &kh_val(&map->table, k); \
} \
\
U map_##T##_##U##_del(Map(T, U) *map, T key) \
@@ -131,9 +123,9 @@
U rv = INITIALIZER(T, U); \
khiter_t k; \
\
- if ((k = kh_get(T##_##U##_map, map->table, key)) != kh_end(map->table)) { \
- rv = kh_val(map->table, k); \
- kh_del(T##_##U##_map, map->table, k); \
+ if ((k = kh_get(T##_##U##_map, &map->table, key)) != kh_end(&map->table)) { \
+ rv = kh_val(&map->table, k); \
+ kh_del(T##_##U##_map, &map->table, k); \
} \
\
return rv; \
@@ -141,7 +133,7 @@
\
void map_##T##_##U##_clear(Map(T, U) *map) \
{ \
- kh_clear(T##_##U##_map, map->table); \
+ kh_clear(T##_##U##_map, &map->table); \
}
static inline khint_t String_hash(String s)
@@ -194,11 +186,12 @@ static inline bool ColorKey_eq(ColorKey ae1, ColorKey ae2)
MAP_IMPL(int, int, DEFAULT_INITIALIZER)
MAP_IMPL(cstr_t, ptr_t, DEFAULT_INITIALIZER)
+MAP_IMPL(cstr_t, int, DEFAULT_INITIALIZER)
MAP_IMPL(ptr_t, ptr_t, DEFAULT_INITIALIZER)
MAP_IMPL(uint64_t, ptr_t, DEFAULT_INITIALIZER)
MAP_IMPL(uint64_t, ssize_t, SSIZE_INITIALIZER)
MAP_IMPL(uint64_t, uint64_t, DEFAULT_INITIALIZER)
-#define EXTMARK_NS_INITIALIZER { 0, 0 }
+#define EXTMARK_NS_INITIALIZER { { MAP_INIT }, 1 }
MAP_IMPL(uint64_t, ExtmarkNs, EXTMARK_NS_INITIALIZER)
#define EXTMARK_ITEM_INITIALIZER { 0, 0, NULL }
MAP_IMPL(uint64_t, ExtmarkItem, EXTMARK_ITEM_INITIALIZER)
diff --git a/src/nvim/map.h b/src/nvim/map.h
index 7bd3d31330..d6515878a2 100644
--- a/src/nvim/map.h
+++ b/src/nvim/map.h
@@ -18,11 +18,12 @@
KHASH_DECLARE(T##_##U##_map, T, U) \
\
typedef struct { \
- khash_t(T##_##U##_map) *table; \
+ khash_t(T##_##U##_map) table; \
} Map(T, U); \
\
Map(T, U) *map_##T##_##U##_new(void); \
void map_##T##_##U##_free(Map(T, U) *map); \
+ void map_##T##_##U##_destroy(Map(T, U) *map); \
U map_##T##_##U##_get(Map(T, U) *map, T key); \
bool map_##T##_##U##_has(Map(T, U) *map, T key); \
T map_##T##_##U##_key(Map(T, U) *map, T key); \
@@ -36,6 +37,7 @@
//
MAP_DECLS(int, int)
MAP_DECLS(cstr_t, ptr_t)
+MAP_DECLS(cstr_t, int)
MAP_DECLS(ptr_t, ptr_t)
MAP_DECLS(uint64_t, ptr_t)
MAP_DECLS(uint64_t, ssize_t)
@@ -44,7 +46,7 @@ MAP_DECLS(uint64_t, uint64_t)
// NB: this is the only way to define a struct both containing and contained
// in a map...
typedef struct ExtmarkNs { // For namespacing extmarks
- Map(uint64_t, uint64_t) *map; // For fast lookup
+ Map(uint64_t, uint64_t) map[1]; // For fast lookup
uint64_t free_id; // For automatically assigning id's
} ExtmarkNs;
@@ -57,8 +59,10 @@ MAP_DECLS(String, handle_T)
MAP_DECLS(ColorKey, ColorItem)
-#define map_new(T, U) map_##T##_##U##_new
-#define map_free(T, U) map_##T##_##U##_free
+#define MAP_INIT { { 0, 0, 0, 0, NULL, NULL, NULL } }
+#define map_init(k, v, map) do { *(map) = (Map(k, v))MAP_INIT; } while (false)
+
+#define map_destroy(T, U) map_##T##_##U##_destroy
#define map_get(T, U) map_##T##_##U##_get
#define map_has(T, U) map_##T##_##U##_has
#define map_key(T, U) map_##T##_##U##_key
@@ -67,10 +71,9 @@ MAP_DECLS(ColorKey, ColorItem)
#define map_del(T, U) map_##T##_##U##_del
#define map_clear(T, U) map_##T##_##U##_clear
-#define map_size(map) ((map)->table->size)
+#define map_size(map) ((map)->table.size)
-#define pmap_new(T) map_new(T, ptr_t)
-#define pmap_free(T) map_free(T, ptr_t)
+#define pmap_destroy(T) map_destroy(T, ptr_t)
#define pmap_get(T) map_get(T, ptr_t)
#define pmap_has(T) map_has(T, ptr_t)
#define pmap_key(T) map_key(T, ptr_t)
@@ -79,12 +82,13 @@ MAP_DECLS(ColorKey, ColorItem)
/// @see pmap_del2
#define pmap_del(T) map_del(T, ptr_t)
#define pmap_clear(T) map_clear(T, ptr_t)
+#define pmap_init(k, map) map_init(k, ptr_t, map)
#define map_foreach(map, key, value, block) \
- kh_foreach(map->table, key, value, block)
+ kh_foreach(&(map)->table, key, value, block)
#define map_foreach_value(map, value, block) \
- kh_foreach_value(map->table, value, block)
+ kh_foreach_value(&(map)->table, value, block)
void pmap_del2(PMap(cstr_t) *map, const char *key);
diff --git a/src/nvim/marktree.c b/src/nvim/marktree.c
index d0d843cbf8..a04f250fc3 100644
--- a/src/nvim/marktree.c
+++ b/src/nvim/marktree.c
@@ -250,7 +250,6 @@ void marktree_put_key(MarkTree *b, int row, int col, uint64_t id)
if (!b->root) {
b->root = (mtnode_t *)xcalloc(1, ILEN);
- b->id2node = pmap_new(uint64_t)();
b->n_nodes++;
}
mtnode_t *r, *s;
@@ -547,9 +546,9 @@ void marktree_clear(MarkTree *b)
marktree_free_node(b->root);
b->root = NULL;
}
- if (b->id2node) {
- pmap_free(uint64_t)(b->id2node);
- b->id2node = NULL;
+ if (b->id2node->table.keys) {
+ pmap_destroy(uint64_t)(b->id2node);
+ pmap_init(uint64_t, b->id2node);
}
b->n_keys = 0;
b->n_nodes = 0;
diff --git a/src/nvim/marktree.h b/src/nvim/marktree.h
index 3b83e3c44d..7af23765c3 100644
--- a/src/nvim/marktree.h
+++ b/src/nvim/marktree.h
@@ -63,7 +63,7 @@ typedef struct {
uint64_t next_id;
// TODO(bfredl): the pointer to node could be part of the larger
// Map(uint64_t, ExtmarkItem) essentially;
- PMap(uint64_t) *id2node;
+ PMap(uint64_t) id2node[1];
} MarkTree;
diff --git a/src/nvim/memline.c b/src/nvim/memline.c
index 8229b8f6bc..4d435bc99f 100644
--- a/src/nvim/memline.c
+++ b/src/nvim/memline.c
@@ -382,7 +382,7 @@ error:
*/
void ml_setname(buf_T *buf)
{
- int success = FALSE;
+ bool success = false;
memfile_T *mfp;
char_u *fname;
char_u *dirp;
@@ -418,7 +418,7 @@ void ml_setname(buf_T *buf)
/* if the file name is the same we don't have to do anything */
if (fnamecmp(fname, mfp->mf_fname) == 0) {
xfree(fname);
- success = TRUE;
+ success = true;
break;
}
/* need to close the swap file before renaming */
@@ -429,7 +429,7 @@ void ml_setname(buf_T *buf)
/* try to rename the swap file */
if (vim_rename(mfp->mf_fname, fname) == 0) {
- success = TRUE;
+ success = true;
mf_free_fnames(mfp);
mf_set_fnames(mfp, fname);
ml_upd_block0(buf, UB_SAME_DIR);
@@ -758,12 +758,12 @@ void ml_recover(bool checkext)
blocknr_T bnum;
int page_count;
int len;
- int directly;
+ bool directly;
linenr_T lnum;
char_u *p;
int i;
long error;
- int cannot_open;
+ bool cannot_open;
linenr_T line_count;
bool has_error;
int idx;
@@ -771,7 +771,7 @@ void ml_recover(bool checkext)
int txt_start;
off_T size;
int called_from_main;
- int serious_error = TRUE;
+ bool serious_error = true;
long mtime;
int attr;
int orig_file_status = NOTDONE;
@@ -791,10 +791,10 @@ void ml_recover(bool checkext)
&& vim_strchr((char_u *)"abcdefghijklmnopqrstuvw",
TOLOWER_ASC(fname[len - 2])) != NULL
&& ASCII_ISALPHA(fname[len - 1])) {
- directly = TRUE;
- fname_used = vim_strsave(fname); /* make a copy for mf_open() */
+ directly = true;
+ fname_used = vim_strsave(fname); // make a copy for mf_open()
} else {
- directly = FALSE;
+ directly = false;
/* count the number of matching swap files */
len = recover_names(fname, FALSE, 0, NULL);
@@ -1018,12 +1018,13 @@ void ml_recover(bool checkext)
buf->b_ml.ml_stack = NULL;
buf->b_ml.ml_stack_size = 0; /* no stack yet */
- if (curbuf->b_ffname == NULL)
- cannot_open = TRUE;
- else
- cannot_open = FALSE;
+ if (curbuf->b_ffname == NULL) {
+ cannot_open = true;
+ } else {
+ cannot_open = false;
+ }
- serious_error = FALSE;
+ serious_error = false;
for (; !got_int; line_breakcheck()) {
if (hp != NULL)
mf_put(mfp, hp, false, false); /* release previous block */
@@ -1796,7 +1797,7 @@ theend:
*/
char_u *ml_get(linenr_T lnum)
{
- return ml_get_buf(curbuf, lnum, FALSE);
+ return ml_get_buf(curbuf, lnum, false);
}
/*
@@ -2096,7 +2097,7 @@ static int ml_append_int(
int total_moved = 0; /* init to shut up gcc */
DATA_BL *dp_right, *dp_left;
int stack_idx;
- int in_left;
+ bool in_left;
int lineadd;
blocknr_T bnum_left, bnum_right;
linenr_T lnum_left, lnum_right;
@@ -2113,22 +2114,22 @@ static int ml_append_int(
*/
if (db_idx < 0) { /* left block is new, right block is existing */
lines_moved = 0;
- in_left = TRUE;
- /* space_needed does not change */
- } else { /* left block is existing, right block is new */
+ in_left = true;
+ // space_needed does not change
+ } else { // left block is existing, right block is new
lines_moved = line_count - db_idx - 1;
- if (lines_moved == 0)
- in_left = FALSE; /* put new line in right block */
- /* space_needed does not change */
- else {
+ if (lines_moved == 0) {
+ in_left = false; // put new line in right block
+ // space_needed does not change
+ } else {
data_moved = ((dp->db_index[db_idx]) & DB_INDEX_MASK) -
dp->db_txt_start;
total_moved = data_moved + lines_moved * INDEX_SIZE;
if ((int)dp->db_free + total_moved >= space_needed) {
- in_left = TRUE; /* put new line in left block */
+ in_left = true; // put new line in left block
space_needed = total_moved;
} else {
- in_left = FALSE; /* put new line in right block */
+ in_left = false; // put new line in right block
space_needed += total_moved;
}
}
@@ -2761,7 +2762,7 @@ static void ml_flush_line(buf_T *buf)
int start;
int count;
int i;
- static int entered = FALSE;
+ static bool entered = false;
if (buf->b_ml.ml_line_lnum == 0 || buf->b_ml.ml_mfp == NULL)
return; /* nothing to do */
@@ -2770,7 +2771,7 @@ static void ml_flush_line(buf_T *buf)
/* This code doesn't work recursively. */
if (entered)
return;
- entered = TRUE;
+ entered = true;
buf->flush_count++;
@@ -2833,7 +2834,7 @@ static void ml_flush_line(buf_T *buf)
}
xfree(new_line);
- entered = FALSE;
+ entered = false;
}
buf->b_ml.ml_line_lnum = 0;
diff --git a/src/nvim/msgpack_rpc/channel.c b/src/nvim/msgpack_rpc/channel.c
index a2d8859c68..e5743f345b 100644
--- a/src/nvim/msgpack_rpc/channel.c
+++ b/src/nvim/msgpack_rpc/channel.c
@@ -38,7 +38,7 @@
#define log_server_msg(...)
#endif
-static PMap(cstr_t) *event_strings = NULL;
+static PMap(cstr_t) event_strings = MAP_INIT;
static msgpack_sbuffer out_buffer;
#ifdef INCLUDE_GENERATED_DECLARATIONS
@@ -48,7 +48,6 @@ static msgpack_sbuffer out_buffer;
void rpc_init(void)
{
ch_before_blocking_events = multiqueue_new_child(main_loop.events);
- event_strings = pmap_new(cstr_t)();
msgpack_sbuffer_init(&out_buffer);
}
@@ -60,7 +59,6 @@ void rpc_start(Channel *channel)
RpcState *rpc = &channel->rpc;
rpc->closed = false;
rpc->unpacker = msgpack_unpacker_new(MSGPACK_UNPACKER_INIT_BUFFER_SIZE);
- rpc->subscribed_events = pmap_new(cstr_t)();
rpc->next_request_id = 1;
rpc->info = (Dictionary)ARRAY_DICT_INIT;
kv_init(rpc->call_stack);
@@ -183,11 +181,11 @@ void rpc_subscribe(uint64_t id, char *event)
abort();
}
- char *event_string = pmap_get(cstr_t)(event_strings, event);
+ char *event_string = pmap_get(cstr_t)(&event_strings, event);
if (!event_string) {
event_string = xstrdup(event);
- pmap_put(cstr_t)(event_strings, event_string, event_string);
+ pmap_put(cstr_t)(&event_strings, event_string, event_string);
}
pmap_put(cstr_t)(channel->rpc.subscribed_events, event_string, event_string);
@@ -497,7 +495,7 @@ static void broadcast_event(const char *name, Array args)
kvec_t(Channel *) subscribed = KV_INITIAL_VALUE;
Channel *channel;
- map_foreach_value(channels, channel, {
+ map_foreach_value(&channels, channel, {
if (channel->is_rpc
&& pmap_has(cstr_t)(channel->rpc.subscribed_events, name)) {
kv_push(subscribed, channel);
@@ -528,7 +526,7 @@ end:
static void unsubscribe(Channel *channel, char *event)
{
- char *event_string = pmap_get(cstr_t)(event_strings, event);
+ char *event_string = pmap_get(cstr_t)(&event_strings, event);
if (!event_string) {
WLOG("RPC: ch %" PRIu64 ": tried to unsubscribe unknown event '%s'",
channel->id, event);
@@ -536,7 +534,7 @@ static void unsubscribe(Channel *channel, char *event)
}
pmap_del(cstr_t)(channel->rpc.subscribed_events, event_string);
- map_foreach_value(channels, channel, {
+ map_foreach_value(&channels, channel, {
if (channel->is_rpc
&& pmap_has(cstr_t)(channel->rpc.subscribed_events, event_string)) {
return;
@@ -544,7 +542,7 @@ static void unsubscribe(Channel *channel, char *event)
});
// Since the string is no longer used by other channels, release it's memory
- pmap_del(cstr_t)(event_strings, event_string);
+ pmap_del(cstr_t)(&event_strings, event_string);
xfree(event_string);
}
@@ -583,7 +581,7 @@ void rpc_free(Channel *channel)
unsubscribe(channel, event_string);
});
- pmap_free(cstr_t)(channel->rpc.subscribed_events);
+ pmap_destroy(cstr_t)(channel->rpc.subscribed_events);
kv_destroy(channel->rpc.call_stack);
api_free_dictionary(channel->rpc.info);
}
diff --git a/src/nvim/msgpack_rpc/channel_defs.h b/src/nvim/msgpack_rpc/channel_defs.h
index 6ef8c027f0..de328af1ce 100644
--- a/src/nvim/msgpack_rpc/channel_defs.h
+++ b/src/nvim/msgpack_rpc/channel_defs.h
@@ -27,7 +27,7 @@ typedef struct {
} RequestEvent;
typedef struct {
- PMap(cstr_t) *subscribed_events;
+ PMap(cstr_t) subscribed_events[1];
bool closed;
msgpack_unpacker *unpacker;
uint32_t next_request_id;
diff --git a/src/nvim/normal.c b/src/nvim/normal.c
index e42ec92a4c..ffcf659d28 100644
--- a/src/nvim/normal.c
+++ b/src/nvim/normal.c
@@ -4931,7 +4931,8 @@ static void nv_ident(cmdarg_T *cap)
snprintf(buf, buf_size, ".,.+%" PRId64, (int64_t)(cap->count0 - 1));
}
- STRCAT(buf, "! ");
+ do_cmdline_cmd("tabnew");
+ STRCAT(buf, "terminal ");
if (cap->count0 == 0 && isman_s) {
STRCAT(buf, "man");
} else {
@@ -5028,6 +5029,17 @@ static void nv_ident(cmdarg_T *cap)
g_tag_at_cursor = true;
do_cmdline_cmd(buf);
g_tag_at_cursor = false;
+
+ if (cmdchar == 'K' && !kp_ex && !kp_help) {
+ // Start insert mode in terminal buffer
+ restart_edit = 'i';
+
+ add_map((char_u *)"<buffer> <esc> <Cmd>call jobstop(&channel)<CR>", TERM_FOCUS, true);
+ do_cmdline_cmd("autocmd TermClose <buffer> "
+ " if !v:event.status |"
+ " exec 'bdelete! ' .. expand('<abuf>') |"
+ " endif");
+ }
}
xfree(buf);
diff --git a/src/nvim/ops.c b/src/nvim/ops.c
index a6eda26d75..a06db4a551 100644
--- a/src/nvim/ops.c
+++ b/src/nvim/ops.c
@@ -1121,18 +1121,13 @@ static void put_reedit_in_typebuf(int silent)
}
}
-/*
- * Insert register contents "s" into the typeahead buffer, so that it will be
- * executed again.
- * When "esc" is TRUE it is to be taken literally: Escape CSI characters and
- * no remapping.
- */
-static int put_in_typebuf(
- char_u *s,
- bool esc,
- bool colon, // add ':' before the line
- int silent
-)
+/// Insert register contents "s" into the typeahead buffer, so that it will be
+/// executed again.
+///
+/// @param esc when true then it is to be taken literally: Escape CSI
+/// characters and no remapping.
+/// @param colon add ':' before the line
+static int put_in_typebuf(char_u *s, bool esc, bool colon, int silent)
{
int retval = OK;
@@ -1567,8 +1562,8 @@ int op_delete(oparg_T *oap)
if (oap->line_count > 1) {
lnum = curwin->w_cursor.lnum;
- ++curwin->w_cursor.lnum;
- del_lines(oap->line_count - 1, TRUE);
+ curwin->w_cursor.lnum++;
+ del_lines(oap->line_count - 1, true);
curwin->w_cursor.lnum = lnum;
}
if (u_save_cursor() == FAIL)
@@ -1593,7 +1588,7 @@ int op_delete(oparg_T *oap)
u_clearline(); // "U" command not possible after "2cc"
}
} else {
- del_lines(oap->line_count, TRUE);
+ del_lines(oap->line_count, true);
beginline(BL_WHITE | BL_FIX);
u_clearline(); /* "U" command not possible after "dd" */
}
@@ -3449,8 +3444,9 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
(int)y_size-1, lastsize, totsize,
kExtmarkUndo);
} else if (y_type == kMTLineWise && flags & PUT_LINE_SPLIT) {
- extmark_splice(curbuf, (int)new_cursor.lnum-1, col, 0, 0, 0,
- (int)y_size+1, 0, totsize+1, kExtmarkUndo);
+ // Account for last pasted NL + last NL
+ extmark_splice(curbuf, (int)new_cursor.lnum-1, col + 1, 0, 0, 0,
+ (int)y_size+1, 0, totsize+2, kExtmarkUndo);
}
}
diff --git a/src/nvim/options.lua b/src/nvim/options.lua
index 8a45cb69fa..df2a8edc04 100644
--- a/src/nvim/options.lua
+++ b/src/nvim/options.lua
@@ -6,7 +6,7 @@
-- type='number', list=nil, scope={'global'},
-- deny_duplicates=nil,
-- enable_if=nil,
--- defaults={condition=nil, if_true={vi=224, vim=0}, if_false=nil},
+-- defaults={condition=nil, if_true=224, if_false=nil},
-- secure=nil, gettext=nil, noglob=nil, normal_fname_chars=nil,
-- pri_mkrc=nil, deny_in_modelines=nil, normal_dname_chars=nil,
-- modelineexpr=nil,
@@ -21,7 +21,6 @@
-- scopes: global, buffer, window
-- redraw options: statuslines, current_window, curent_window_only,
-- current_buffer, all_windows, everything, curswant
--- default: {vi=…[, vim=…]}
-- defaults: {condition=#if condition, if_true=default, if_false=default}
-- #if condition:
-- string: #ifdef string
@@ -57,14 +56,14 @@ return {
type='number', scope={'global'},
redraw={'curswant'},
varname='p_aleph',
- defaults={if_true={vi=224}}
+ defaults={if_true=224}
},
{
full_name='arabic', abbreviation='arab',
short_desc=N_("Arabic as a default second language"),
type='bool', scope={'window'},
redraw={'curswant'},
- defaults={if_true={vi=false}}
+ defaults={if_true=false}
},
{
full_name='arabicshape', abbreviation='arshape',
@@ -73,14 +72,14 @@ return {
redraw={'all_windows', 'ui_option'},
varname='p_arshape',
- defaults={if_true={vi=true}}
+ defaults={if_true=true}
},
{
full_name='allowrevins', abbreviation='ari',
short_desc=N_("allow CTRL-_ in Insert and Command-line mode"),
type='bool', scope={'global'},
varname='p_ari',
- defaults={if_true={vi=false}}
+ defaults={if_true=false}
},
{
full_name='ambiwidth', abbreviation='ambw',
@@ -88,42 +87,42 @@ return {
type='string', scope={'global'},
redraw={'all_windows', 'ui_option'},
varname='p_ambw',
- defaults={if_true={vi="single"}}
+ defaults={if_true="single"}
},
{
full_name='autochdir', abbreviation='acd',
short_desc=N_("change directory to the file in the current window"),
type='bool', scope={'global'},
varname='p_acd',
- defaults={if_true={vi=false}}
+ defaults={if_true=false}
},
{
full_name='autoindent', abbreviation='ai',
short_desc=N_("take indent for new line from previous line"),
type='bool', scope={'buffer'},
varname='p_ai',
- defaults={if_true={vim=true}}
+ defaults={if_true=true}
},
{
full_name='autoread', abbreviation='ar',
short_desc=N_("autom. read file when changed outside of Vim"),
type='bool', scope={'global', 'buffer'},
varname='p_ar',
- defaults={if_true={vim=true}}
+ defaults={if_true=true}
},
{
full_name='autowrite', abbreviation='aw',
short_desc=N_("automatically write file if changed"),
type='bool', scope={'global'},
varname='p_aw',
- defaults={if_true={vi=false}}
+ defaults={if_true=false}
},
{
full_name='autowriteall', abbreviation='awa',
short_desc=N_("as 'autowrite', but works with more commands"),
type='bool', scope={'global'},
varname='p_awa',
- defaults={if_true={vi=false}}
+ defaults={if_true=false}
},
{
full_name='background', abbreviation='bg',
@@ -131,7 +130,7 @@ return {
type='string', scope={'global'},
redraw={'all_windows'},
varname='p_bg',
- defaults={if_true={vim="dark"}}
+ defaults={if_true="dark"}
},
{
full_name='backspace', abbreviation='bs',
@@ -139,14 +138,14 @@ return {
type='string', list='onecomma', scope={'global'},
deny_duplicates=true,
varname='p_bs',
- defaults={if_true={vim="indent,eol,start"}}
+ defaults={if_true="indent,eol,start"}
},
{
full_name='backup', abbreviation='bk',
short_desc=N_("keep backup file after overwriting a file"),
type='bool', scope={'global'},
varname='p_bk',
- defaults={if_true={vi=false}}
+ defaults={if_true=false}
},
{
full_name='backupcopy', abbreviation='bkc',
@@ -156,8 +155,8 @@ return {
varname='p_bkc',
defaults={
condition='UNIX',
- if_true={vim="auto"},
- if_false={vim="auto"}
+ if_true="auto",
+ if_false="auto"
},
},
{
@@ -168,7 +167,7 @@ return {
secure=true,
expand='nodefault',
varname='p_bdir',
- defaults={if_true={vi=''}}
+ defaults={if_true=''}
},
{
full_name='backupext', abbreviation='bex',
@@ -176,7 +175,7 @@ return {
type='string', scope={'global'},
normal_fname_chars=true,
varname='p_bex',
- defaults={if_true={vi="~"}}
+ defaults={if_true="~"}
},
{
full_name='backupskip', abbreviation='bsk',
@@ -184,7 +183,7 @@ return {
type='string', list='onecomma', scope={'global'},
deny_duplicates=true,
varname='p_bsk',
- defaults={if_true={vi=""}}
+ defaults={if_true=""}
},
{
full_name='belloff', abbreviation='bo',
@@ -192,7 +191,7 @@ return {
type='string', list='comma', scope={'global'},
deny_duplicates=true,
varname='p_bo',
- defaults={if_true={vi="all"}}
+ defaults={if_true="all"}
},
{
full_name='binary', abbreviation='bin',
@@ -200,7 +199,7 @@ return {
type='bool', scope={'buffer'},
redraw={'statuslines'},
varname='p_bin',
- defaults={if_true={vi=false}}
+ defaults={if_true=false}
},
{
full_name='bomb',
@@ -209,7 +208,7 @@ return {
no_mkrc=true,
redraw={'statuslines'},
varname='p_bomb',
- defaults={if_true={vi=false}}
+ defaults={if_true=false}
},
{
full_name='breakat', abbreviation='brk',
@@ -217,14 +216,14 @@ return {
type='string', list='flags', scope={'global'},
redraw={'all_windows'},
varname='p_breakat',
- defaults={if_true={vi=" \t!@*-+;:,./?"}}
+ defaults={if_true=" \t!@*-+;:,./?"}
},
{
full_name='breakindent', abbreviation='bri',
short_desc=N_("wrapped line repeats indent"),
type='bool', scope={'window'},
redraw={'current_window'},
- defaults={if_true={vi=false}}
+ defaults={if_true=false}
},
{
full_name='breakindentopt', abbreviation='briopt',
@@ -233,7 +232,7 @@ return {
deny_duplicates=true,
alloced=true,
redraw={'current_buffer'},
- defaults={if_true={vi=""}},
+ defaults={if_true=""},
},
{
full_name='browsedir', abbreviation='bsdir',
@@ -248,7 +247,7 @@ return {
noglob=true,
alloced=true,
varname='p_bh',
- defaults={if_true={vi=""}}
+ defaults={if_true=""}
},
{
full_name='buflisted', abbreviation='bl',
@@ -256,7 +255,7 @@ return {
type='bool', scope={'buffer'},
noglob=true,
varname='p_bl',
- defaults={if_true={vi=1}}
+ defaults={if_true=1}
},
{
full_name='buftype', abbreviation='bt',
@@ -265,7 +264,7 @@ return {
noglob=true,
alloced=true,
varname='p_bt',
- defaults={if_true={vi=""}}
+ defaults={if_true=""}
},
{
full_name='casemap', abbreviation='cmp',
@@ -273,7 +272,7 @@ return {
type='string', list='onecomma', scope={'global'},
deny_duplicates=true,
varname='p_cmp',
- defaults={if_true={vi="internal,keepascii"}}
+ defaults={if_true="internal,keepascii"}
},
{
full_name='cdpath', abbreviation='cd',
@@ -283,14 +282,14 @@ return {
expand=true,
secure=true,
varname='p_cdpath',
- defaults={if_true={vi=",,"}}
+ defaults={if_true=",,"}
},
{
full_name='cedit',
short_desc=N_("used to open the command-line window"),
type='string', scope={'global'},
varname='p_cedit',
- defaults={if_true={vim=macros('CTRL_F_STR')}}
+ defaults={if_true=macros('CTRL_F_STR')}
},
{
full_name='channel',
@@ -299,7 +298,7 @@ return {
no_mkrc=true,
nodefault=true,
varname='p_channel',
- defaults={if_true={vi=0}}
+ defaults={if_true=0}
},
{
full_name='charconvert', abbreviation='ccv',
@@ -307,14 +306,14 @@ return {
type='string', scope={'global'},
secure=true,
varname='p_ccv',
- defaults={if_true={vi=""}}
+ defaults={if_true=""}
},
{
full_name='cindent', abbreviation='cin',
short_desc=N_("do C program indenting"),
type='bool', scope={'buffer'},
varname='p_cin',
- defaults={if_true={vi=false}}
+ defaults={if_true=false}
},
{
full_name='cinkeys', abbreviation='cink',
@@ -323,7 +322,7 @@ return {
deny_duplicates=true,
alloced=true,
varname='p_cink',
- defaults={if_true={vi=indentkeys_default}}
+ defaults={if_true=indentkeys_default}
},
{
full_name='cinoptions', abbreviation='cino',
@@ -332,7 +331,7 @@ return {
deny_duplicates=true,
alloced=true,
varname='p_cino',
- defaults={if_true={vi=""}}
+ defaults={if_true=""}
},
{
full_name='cinwords', abbreviation='cinw',
@@ -341,7 +340,7 @@ return {
deny_duplicates=true,
alloced=true,
varname='p_cinw',
- defaults={if_true={vi="if,else,while,do,for,switch"}}
+ defaults={if_true="if,else,while,do,for,switch"}
},
{
full_name='clipboard', abbreviation='cb',
@@ -349,7 +348,7 @@ return {
type='string', list='onecomma', scope={'global'},
deny_duplicates=true,
varname='p_cb',
- defaults={if_true={vi=""}}
+ defaults={if_true=""}
},
{
full_name='cmdheight', abbreviation='ch',
@@ -357,14 +356,14 @@ return {
type='number', scope={'global'},
redraw={'all_windows'},
varname='p_ch',
- defaults={if_true={vi=1}}
+ defaults={if_true=1}
},
{
full_name='cmdwinheight', abbreviation='cwh',
short_desc=N_("height of the command-line window"),
type='number', scope={'global'},
varname='p_cwh',
- defaults={if_true={vi=7}}
+ defaults={if_true=7}
},
{
full_name='colorcolumn', abbreviation='cc',
@@ -372,7 +371,7 @@ return {
type='string', list='onecomma', scope={'window'},
deny_duplicates=true,
redraw={'current_window'},
- defaults={if_true={vi=""}}
+ defaults={if_true=""}
},
{
full_name='columns', abbreviation='co',
@@ -381,7 +380,7 @@ return {
no_mkrc=true,
redraw={'everything'},
varname='p_columns',
- defaults={if_true={vi=macros('DFLT_COLS')}}
+ defaults={if_true=macros('DFLT_COLS')}
},
{
full_name='comments', abbreviation='com',
@@ -391,7 +390,7 @@ return {
alloced=true,
redraw={'curswant'},
varname='p_com',
- defaults={if_true={vi="s1:/*,mb:*,ex:*/,://,b:#,:%,:XCOMM,n:>,fb:-"}}
+ defaults={if_true="s1:/*,mb:*,ex:*/,://,b:#,:%,:XCOMM,n:>,fb:-"}
},
{
full_name='commentstring', abbreviation='cms',
@@ -400,7 +399,7 @@ return {
alloced=true,
redraw={'curswant'},
varname='p_cms',
- defaults={if_true={vi="/*%s*/"}}
+ defaults={if_true="/*%s*/"}
},
{
full_name='compatible', abbreviation='cp',
@@ -410,7 +409,7 @@ return {
varname='p_force_off',
-- pri_mkrc isn't needed here, optval_default()
-- always returns TRUE for 'compatible'
- defaults={if_true={vim=false}}
+ defaults={if_true=false}
},
{
full_name='complete', abbreviation='cpt',
@@ -419,7 +418,7 @@ return {
deny_duplicates=true,
alloced=true,
varname='p_cpt',
- defaults={if_true={vim=".,w,b,u,t"}}
+ defaults={if_true=".,w,b,u,t"}
},
{
full_name='concealcursor', abbreviation='cocu',
@@ -427,14 +426,14 @@ return {
type='string', scope={'window'},
alloced=true,
redraw={'current_window'},
- defaults={if_true={vi=""}}
+ defaults={if_true=""}
},
{
full_name='conceallevel', abbreviation='cole',
short_desc=N_("whether concealable text is shown or hidden"),
type='number', scope={'window'},
redraw={'current_window'},
- defaults={if_true={vi=0}}
+ defaults={if_true=0}
},
{
full_name='completefunc', abbreviation='cfu',
@@ -443,7 +442,7 @@ return {
secure=true,
alloced=true,
varname='p_cfu',
- defaults={if_true={vi=""}}
+ defaults={if_true=""}
},
{
full_name='completeopt', abbreviation='cot',
@@ -451,28 +450,28 @@ return {
type='string', list='onecomma', scope={'global'},
deny_duplicates=true,
varname='p_cot',
- defaults={if_true={vi="menu,preview"}}
+ defaults={if_true="menu,preview"}
},
{
full_name='completeslash', abbreviation='csl',
type='string', scope={'buffer'},
varname='p_csl',
enable_if='BACKSLASH_IN_FILENAME',
- defaults={if_true={vi=""}}
+ defaults={if_true=""}
},
{
full_name='confirm', abbreviation='cf',
short_desc=N_("ask what to do about unsaved/read-only files"),
type='bool', scope={'global'},
varname='p_confirm',
- defaults={if_true={vi=false}}
+ defaults={if_true=false}
},
{
full_name='copyindent', abbreviation='ci',
short_desc=N_("make 'autoindent' use existing indent structure"),
type='bool', scope={'buffer'},
varname='p_ci',
- defaults={if_true={vi=false}}
+ defaults={if_true=false}
},
{
full_name='cpoptions', abbreviation='cpo',
@@ -480,14 +479,14 @@ return {
type='string', list='flags', scope={'global'},
redraw={'all_windows'},
varname='p_cpo',
- defaults={if_true={vim=macros('CPO_VIM')}}
+ defaults={if_true=macros('CPO_VIM')}
},
{
full_name='cscopepathcomp', abbreviation='cspc',
short_desc=N_("how many components of the path to show"),
type='number', scope={'global'},
varname='p_cspc',
- defaults={if_true={vi=0}}
+ defaults={if_true=0}
},
{
full_name='cscopeprg', abbreviation='csprg',
@@ -496,7 +495,7 @@ return {
secure=true,
expand=true,
varname='p_csprg',
- defaults={if_true={vi="cscope"}}
+ defaults={if_true="cscope"}
},
{
full_name='cscopequickfix', abbreviation='csqf',
@@ -504,56 +503,56 @@ return {
type='string', list='onecomma', scope={'global'},
deny_duplicates=true,
varname='p_csqf',
- defaults={if_true={vi=""}}
+ defaults={if_true=""}
},
{
full_name='cscoperelative', abbreviation='csre',
short_desc=N_("Use cscope.out path basename as prefix"),
type='bool', scope={'global'},
varname='p_csre',
- defaults={if_true={vi=0}}
+ defaults={if_true=0}
},
{
full_name='cscopetag', abbreviation='cst',
short_desc=N_("use cscope for tag commands"),
type='bool', scope={'global'},
varname='p_cst',
- defaults={if_true={vi=0}}
+ defaults={if_true=0}
},
{
full_name='cscopetagorder', abbreviation='csto',
short_desc=N_("determines \":cstag\" search order"),
type='number', scope={'global'},
varname='p_csto',
- defaults={if_true={vi=0}}
+ defaults={if_true=0}
},
{
full_name='cscopeverbose', abbreviation='csverb',
short_desc=N_("give messages when adding a cscope database"),
type='bool', scope={'global'},
varname='p_csverbose',
- defaults={if_true={vi=1}}
+ defaults={if_true=1}
},
{
full_name='cursorbind', abbreviation='crb',
short_desc=N_("move cursor in window as it moves in other windows"),
type='bool', scope={'window'},
pv_name='p_crbind',
- defaults={if_true={vi=false}}
+ defaults={if_true=false}
},
{
full_name='cursorcolumn', abbreviation='cuc',
short_desc=N_("highlight the screen column of the cursor"),
type='bool', scope={'window'},
redraw={'current_window_only'},
- defaults={if_true={vi=false}}
+ defaults={if_true=false}
},
{
full_name='cursorline', abbreviation='cul',
short_desc=N_("highlight the screen line of the cursor"),
type='bool', scope={'window'},
redraw={'current_window_only'},
- defaults={if_true={vi=false}}
+ defaults={if_true=false}
},
{
full_name='cursorlineopt', abbreviation='culopt',
@@ -561,14 +560,14 @@ return {
type='string', list='onecomma', scope={'window'},
deny_duplicates=true,
redraw={'current_window_only'},
- defaults={if_true={vi="both"}}
+ defaults={if_true="both"}
},
{
full_name='debug',
short_desc=N_("to \"msg\" to see all error messages"),
type='string', scope={'global'},
varname='p_debug',
- defaults={if_true={vi=""}}
+ defaults={if_true=""}
},
{
full_name='define', abbreviation='def',
@@ -577,14 +576,14 @@ return {
alloced=true,
redraw={'curswant'},
varname='p_def',
- defaults={if_true={vi="^\\s*#\\s*define"}}
+ defaults={if_true="^\\s*#\\s*define"}
},
{
full_name='delcombine', abbreviation='deco',
short_desc=N_("delete combining characters on their own"),
type='bool', scope={'global'},
varname='p_deco',
- defaults={if_true={vi=false}}
+ defaults={if_true=false}
},
{
full_name='dictionary', abbreviation='dict',
@@ -594,7 +593,7 @@ return {
normal_dname_chars=true,
expand=true,
varname='p_dict',
- defaults={if_true={vi=""}}
+ defaults={if_true=""}
},
{
full_name='diff',
@@ -602,7 +601,7 @@ return {
type='bool', scope={'window'},
noglob=true,
redraw={'current_window'},
- defaults={if_true={vi=false}}
+ defaults={if_true=false}
},
{
full_name='diffexpr', abbreviation='dex',
@@ -611,7 +610,7 @@ return {
secure=true,
redraw={'curswant'},
varname='p_dex',
- defaults={if_true={vi=""}}
+ defaults={if_true=""}
},
{
full_name='diffopt', abbreviation='dip',
@@ -621,14 +620,14 @@ return {
alloced=true,
redraw={'current_window'},
varname='p_dip',
- defaults={if_true={vi="internal,filler,closeoff"}}
+ defaults={if_true="internal,filler,closeoff"}
},
{
full_name='digraph', abbreviation='dg',
short_desc=N_("enable the entering of digraphs in Insert mode"),
type='bool', scope={'global'},
varname='p_dg',
- defaults={if_true={vi=false}}
+ defaults={if_true=false}
},
{
full_name='directory', abbreviation='dir',
@@ -638,7 +637,7 @@ return {
secure=true,
expand='nodefault',
varname='p_dir',
- defaults={if_true={vi=''}}
+ defaults={if_true=''}
},
{
full_name='display', abbreviation='dy',
@@ -647,21 +646,21 @@ return {
deny_duplicates=true,
redraw={'all_windows'},
varname='p_dy',
- defaults={if_true={vim="lastline,msgsep"}}
+ defaults={if_true="lastline,msgsep"}
},
{
full_name='eadirection', abbreviation='ead',
short_desc=N_("in which direction 'equalalways' works"),
type='string', scope={'global'},
varname='p_ead',
- defaults={if_true={vi="both"}}
+ defaults={if_true="both"}
},
{
full_name='edcompatible', abbreviation='ed',
short_desc=N_("No description"),
type='bool', scope={'global'},
varname='p_force_off',
- defaults={if_true={vi=false}}
+ defaults={if_true=false}
},
{
full_name='emoji', abbreviation='emo',
@@ -669,7 +668,7 @@ return {
type='bool', scope={'global'},
redraw={'all_windows', 'ui_option'},
varname='p_emoji',
- defaults={if_true={vi=true}}
+ defaults={if_true=true}
},
{
full_name='encoding', abbreviation='enc',
@@ -677,7 +676,7 @@ return {
type='string', scope={'global'},
deny_in_modelines=true,
varname='p_enc',
- defaults={if_true={vi=macros('ENC_DFLT')}}
+ defaults={if_true=macros('ENC_DFLT')}
},
{
full_name='endofline', abbreviation='eol',
@@ -686,7 +685,7 @@ return {
no_mkrc=true,
redraw={'statuslines'},
varname='p_eol',
- defaults={if_true={vi=true}}
+ defaults={if_true=true}
},
{
full_name='equalalways', abbreviation='ea',
@@ -694,7 +693,7 @@ return {
type='bool', scope={'global'},
redraw={'all_windows'},
varname='p_ea',
- defaults={if_true={vi=true}}
+ defaults={if_true=true}
},
{
full_name='equalprg', abbreviation='ep',
@@ -703,14 +702,14 @@ return {
secure=true,
expand=true,
varname='p_ep',
- defaults={if_true={vi=""}}
+ defaults={if_true=""}
},
{
full_name='errorbells', abbreviation='eb',
short_desc=N_("ring the bell for error messages"),
type='bool', scope={'global'},
varname='p_eb',
- defaults={if_true={vi=false}}
+ defaults={if_true=false}
},
{
full_name='errorfile', abbreviation='ef',
@@ -719,7 +718,7 @@ return {
secure=true,
expand=true,
varname='p_ef',
- defaults={if_true={vi=macros('DFLT_ERRORFILE')}}
+ defaults={if_true=macros('DFLT_ERRORFILE')}
},
{
full_name='errorformat', abbreviation='efm',
@@ -727,7 +726,7 @@ return {
type='string', list='onecomma', scope={'global', 'buffer'},
deny_duplicates=true,
varname='p_efm',
- defaults={if_true={vi=macros('DFLT_EFM')}}
+ defaults={if_true=macros('DFLT_EFM')}
},
{
full_name='eventignore', abbreviation='ei',
@@ -735,14 +734,14 @@ return {
type='string', list='onecomma', scope={'global'},
deny_duplicates=true,
varname='p_ei',
- defaults={if_true={vi=""}}
+ defaults={if_true=""}
},
{
full_name='expandtab', abbreviation='et',
short_desc=N_("use spaces when <Tab> is inserted"),
type='bool', scope={'buffer'},
varname='p_et',
- defaults={if_true={vi=false}}
+ defaults={if_true=false}
},
{
full_name='exrc', abbreviation='ex',
@@ -750,7 +749,7 @@ return {
type='bool', scope={'global'},
secure=true,
varname='p_exrc',
- defaults={if_true={vi=false}}
+ defaults={if_true=false}
},
{
full_name='fileencoding', abbreviation='fenc',
@@ -760,7 +759,7 @@ return {
alloced=true,
redraw={'statuslines', 'current_buffer'},
varname='p_fenc',
- defaults={if_true={vi=""}}
+ defaults={if_true=""}
},
{
full_name='fileencodings', abbreviation='fencs',
@@ -768,7 +767,7 @@ return {
type='string', list='onecomma', scope={'global'},
deny_duplicates=true,
varname='p_fencs',
- defaults={if_true={vi="ucs-bom,utf-8,default,latin1"}}
+ defaults={if_true="ucs-bom,utf-8,default,latin1"}
},
{
full_name='fileformat', abbreviation='ff',
@@ -778,7 +777,7 @@ return {
alloced=true,
redraw={'curswant', 'statuslines'},
varname='p_ff',
- defaults={if_true={vi=macros('DFLT_FF')}}
+ defaults={if_true=macros('DFLT_FF')}
},
{
full_name='fileformats', abbreviation='ffs',
@@ -786,7 +785,7 @@ return {
type='string', list='onecomma', scope={'global'},
deny_duplicates=true,
varname='p_ffs',
- defaults={if_true={vim=macros('DFLT_FFS_VIM')}}
+ defaults={if_true=macros('DFLT_FFS_VIM')}
},
{
full_name='fileignorecase', abbreviation='fic',
@@ -795,8 +794,8 @@ return {
varname='p_fic',
defaults={
condition='CASE_INSENSITIVE_FILENAME',
- if_true={vi=true},
- if_false={vi=false},
+ if_true=true,
+ if_false=false,
}
},
{
@@ -808,7 +807,7 @@ return {
alloced=true,
expand=true,
varname='p_ft',
- defaults={if_true={vi=""}}
+ defaults={if_true=""}
},
{
full_name='fillchars', abbreviation='fcs',
@@ -818,7 +817,7 @@ return {
alloced=true,
redraw={'current_window'},
varname='p_fcs',
- defaults={if_true={vi=''}}
+ defaults={if_true=''}
},
{
full_name='fixendofline', abbreviation='fixeol',
@@ -826,7 +825,7 @@ return {
type='bool', scope={'buffer'},
redraw={'statuslines'},
varname='p_fixeol',
- defaults={if_true={vi=true}}
+ defaults={if_true=true}
},
{
full_name='foldclose', abbreviation='fcl',
@@ -835,7 +834,7 @@ return {
deny_duplicates=true,
redraw={'current_window'},
varname='p_fcl',
- defaults={if_true={vi=""}}
+ defaults={if_true=""}
},
{
full_name='foldcolumn', abbreviation='fdc',
@@ -843,14 +842,14 @@ return {
type='string', scope={'window'},
alloced=true,
redraw={'current_window'},
- defaults={if_true={vi="0"}}
+ defaults={if_true="0"}
},
{
full_name='foldenable', abbreviation='fen',
short_desc=N_("set to display all folds open"),
type='bool', scope={'window'},
redraw={'current_window'},
- defaults={if_true={vi=true}}
+ defaults={if_true=true}
},
{
full_name='foldexpr', abbreviation='fde',
@@ -859,7 +858,7 @@ return {
modelineexpr=true,
alloced=true,
redraw={'current_window'},
- defaults={if_true={vi="0"}}
+ defaults={if_true="0"}
},
{
full_name='foldignore', abbreviation='fdi',
@@ -867,14 +866,14 @@ return {
type='string', scope={'window'},
alloced=true,
redraw={'current_window'},
- defaults={if_true={vi="#"}}
+ defaults={if_true="#"}
},
{
full_name='foldlevel', abbreviation='fdl',
short_desc=N_("close folds with a level higher than this"),
type='number', scope={'window'},
redraw={'current_window'},
- defaults={if_true={vi=0}}
+ defaults={if_true=0}
},
{
full_name='foldlevelstart', abbreviation='fdls',
@@ -882,7 +881,7 @@ return {
type='number', scope={'global'},
redraw={'curswant'},
varname='p_fdls',
- defaults={if_true={vi=-1}}
+ defaults={if_true=-1}
},
{
full_name='foldmarker', abbreviation='fmr',
@@ -891,7 +890,7 @@ return {
deny_duplicates=true,
alloced=true,
redraw={'current_window'},
- defaults={if_true={vi="{{{,}}}"}}
+ defaults={if_true="{{{,}}}"}
},
{
full_name='foldmethod', abbreviation='fdm',
@@ -899,21 +898,21 @@ return {
type='string', scope={'window'},
alloced=true,
redraw={'current_window'},
- defaults={if_true={vi="manual"}}
+ defaults={if_true="manual"}
},
{
full_name='foldminlines', abbreviation='fml',
short_desc=N_("minimum number of lines for a fold to be closed"),
type='number', scope={'window'},
redraw={'current_window'},
- defaults={if_true={vi=1}}
+ defaults={if_true=1}
},
{
full_name='foldnestmax', abbreviation='fdn',
short_desc=N_("maximum fold depth"),
type='number', scope={'window'},
redraw={'current_window'},
- defaults={if_true={vi=20}}
+ defaults={if_true=20}
},
{
full_name='foldopen', abbreviation='fdo',
@@ -922,7 +921,7 @@ return {
deny_duplicates=true,
redraw={'curswant'},
varname='p_fdo',
- defaults={if_true={vi="block,hor,mark,percent,quickfix,search,tag,undo"}}
+ defaults={if_true="block,hor,mark,percent,quickfix,search,tag,undo"}
},
{
full_name='foldtext', abbreviation='fdt',
@@ -931,7 +930,7 @@ return {
modelineexpr=true,
alloced=true,
redraw={'current_window'},
- defaults={if_true={vi="foldtext()"}}
+ defaults={if_true="foldtext()"}
},
{
full_name='formatexpr', abbreviation='fex',
@@ -940,7 +939,7 @@ return {
modelineexpr=true,
alloced=true,
varname='p_fex',
- defaults={if_true={vi=""}}
+ defaults={if_true=""}
},
{
full_name='formatoptions', abbreviation='fo',
@@ -948,7 +947,7 @@ return {
type='string', list='flags', scope={'buffer'},
alloced=true,
varname='p_fo',
- defaults={if_true={vim=macros('DFLT_FO_VIM')}}
+ defaults={if_true=macros('DFLT_FO_VIM')}
},
{
full_name='formatlistpat', abbreviation='flp',
@@ -956,7 +955,7 @@ return {
type='string', scope={'buffer'},
alloced=true,
varname='p_flp',
- defaults={if_true={vi="^\\s*\\d\\+[\\]:.)}\\t ]\\s*"}}
+ defaults={if_true="^\\s*\\d\\+[\\]:.)}\\t ]\\s*"}
},
{
full_name='formatprg', abbreviation='fp',
@@ -965,7 +964,7 @@ return {
secure=true,
expand=true,
varname='p_fp',
- defaults={if_true={vi=""}}
+ defaults={if_true=""}
},
{
full_name='fsync', abbreviation='fs',
@@ -973,14 +972,14 @@ return {
type='bool', scope={'global'},
secure=true,
varname='p_fs',
- defaults={if_true={vi=false}}
+ defaults={if_true=false}
},
{
full_name='gdefault', abbreviation='gd',
short_desc=N_("the \":substitute\" flag 'g' is default on"),
type='bool', scope={'global'},
varname='p_gd',
- defaults={if_true={vi=false}}
+ defaults={if_true=false}
},
{
full_name='grepformat', abbreviation='gfm',
@@ -988,7 +987,7 @@ return {
type='string', list='onecomma', scope={'global'},
deny_duplicates=true,
varname='p_gefm',
- defaults={if_true={vi=macros('DFLT_GREPFORMAT')}}
+ defaults={if_true=macros('DFLT_GREPFORMAT')}
},
{
full_name='grepprg', abbreviation='gp',
@@ -1001,8 +1000,8 @@ return {
condition='WIN32',
-- Add an extra file name so that grep will always
-- insert a file name in the match line. */
- if_true={vi="findstr /n $* nul"},
- if_false={vi="grep -n $* /dev/null"}
+ if_true="findstr /n $* nul",
+ if_false="grep -n $* /dev/null"
}
},
{
@@ -1011,7 +1010,7 @@ return {
type='string', list='onecomma', scope={'global'},
deny_duplicates=true,
varname='p_guicursor',
- defaults={if_true={vi="n-v-c-sm:block,i-ci-ve:ver25,r-cr-o:hor20"}}
+ defaults={if_true="n-v-c-sm:block,i-ci-ve:ver25,r-cr-o:hor20"}
},
{
full_name='guifont', abbreviation='gfn',
@@ -1020,7 +1019,7 @@ return {
deny_duplicates=true,
varname='p_guifont',
redraw={'ui_option'},
- defaults={if_true={vi=""}}
+ defaults={if_true=""}
},
{
full_name='guifontwide', abbreviation='gfw',
@@ -1029,7 +1028,7 @@ return {
deny_duplicates=true,
redraw={'ui_option'},
varname='p_guifontwide',
- defaults={if_true={vi=""}}
+ defaults={if_true=""}
},
{
full_name='guioptions', abbreviation='go',
@@ -1060,14 +1059,14 @@ return {
secure=true,
expand=true,
varname='p_hf',
- defaults={if_true={vi=macros('DFLT_HELPFILE')}}
+ defaults={if_true=macros('DFLT_HELPFILE')}
},
{
full_name='helpheight', abbreviation='hh',
short_desc=N_("minimum height of a new help window"),
type='number', scope={'global'},
varname='p_hh',
- defaults={if_true={vi=20}}
+ defaults={if_true=20}
},
{
full_name='helplang', abbreviation='hlg',
@@ -1075,14 +1074,14 @@ return {
type='string', list='onecomma', scope={'global'},
deny_duplicates=true,
varname='p_hlg',
- defaults={if_true={vi=""}}
+ defaults={if_true=""}
},
{
full_name='hidden', abbreviation='hid',
short_desc=N_("don't unload buffer when it is |abandon|ed"),
type='bool', scope={'global'},
varname='p_hid',
- defaults={if_true={vi=false}}
+ defaults={if_true=true}
},
{
full_name='highlight', abbreviation='hl',
@@ -1090,28 +1089,28 @@ return {
type='string', list='onecomma', scope={'global'},
deny_duplicates=true,
varname='p_hl',
- defaults={if_true={vi=macros('HIGHLIGHT_INIT')}}
+ defaults={if_true=macros('HIGHLIGHT_INIT')}
},
{
full_name='history', abbreviation='hi',
short_desc=N_("number of command-lines that are remembered"),
type='number', scope={'global'},
varname='p_hi',
- defaults={if_true={vim=10000}}
+ defaults={if_true=10000}
},
{
full_name='hkmap', abbreviation='hk',
short_desc=N_("Hebrew keyboard mapping"),
type='bool', scope={'global'},
varname='p_hkmap',
- defaults={if_true={vi=false}}
+ defaults={if_true=false}
},
{
full_name='hkmapp', abbreviation='hkp',
short_desc=N_("phonetic Hebrew keyboard mapping"),
type='bool', scope={'global'},
varname='p_hkmapp',
- defaults={if_true={vi=false}}
+ defaults={if_true=false}
},
{
full_name='hlsearch', abbreviation='hls',
@@ -1119,14 +1118,14 @@ return {
type='bool', scope={'global'},
redraw={'all_windows'},
varname='p_hls',
- defaults={if_true={vim=true}}
+ defaults={if_true=true}
},
{
full_name='icon',
short_desc=N_("Vim set the text of the window icon"),
type='bool', scope={'global'},
varname='p_icon',
- defaults={if_true={vi=false}}
+ defaults={if_true=false}
},
{
full_name='iconstring',
@@ -1134,28 +1133,28 @@ return {
type='string', scope={'global'},
modelineexpr=true,
varname='p_iconstring',
- defaults={if_true={vi=""}}
+ defaults={if_true=""}
},
{
full_name='ignorecase', abbreviation='ic',
short_desc=N_("ignore case in search patterns"),
type='bool', scope={'global'},
varname='p_ic',
- defaults={if_true={vi=false}}
+ defaults={if_true=false}
},
{
full_name='imcmdline', abbreviation='imc',
short_desc=N_("use IM when starting to edit a command line"),
type='bool', scope={'global'},
enable_if=false,
- defaults={if_true={vi=false}}
+ defaults={if_true=false}
},
{
full_name='imdisable', abbreviation='imd',
short_desc=N_("do not use the IM in any mode"),
type='bool', scope={'global'},
enable_if=false,
- defaults={if_true={vi=false}}
+ defaults={if_true=false}
},
{
full_name='iminsert', abbreviation='imi',
@@ -1163,7 +1162,7 @@ return {
type='number', scope={'buffer'},
varname='p_iminsert', pv_name='p_imi',
defaults={
- if_true={vi=macros('B_IMODE_NONE')},
+ if_true=macros('B_IMODE_NONE'),
}
},
{
@@ -1172,7 +1171,7 @@ return {
type='number', scope={'buffer'},
varname='p_imsearch', pv_name='p_ims',
defaults={
- if_true={vi=macros('B_IMODE_USE_INSERT')},
+ if_true=macros('B_IMODE_USE_INSERT'),
}
},
{
@@ -1181,7 +1180,7 @@ return {
type='string', scope={'global'},
redraw={'all_windows'},
varname='p_icm',
- defaults={if_true={vi=""}}
+ defaults={if_true="nosplit"}
},
{
full_name='include', abbreviation='inc',
@@ -1189,7 +1188,7 @@ return {
type='string', scope={'global', 'buffer'},
alloced=true,
varname='p_inc',
- defaults={if_true={vi="^\\s*#\\s*include"}}
+ defaults={if_true="^\\s*#\\s*include"}
},
{
full_name='includeexpr', abbreviation='inex',
@@ -1198,14 +1197,14 @@ return {
modelineexpr=true,
alloced=true,
varname='p_inex',
- defaults={if_true={vi=""}}
+ defaults={if_true=""}
},
{
full_name='incsearch', abbreviation='is',
short_desc=N_("highlight match while typing search pattern"),
type='bool', scope={'global'},
varname='p_is',
- defaults={if_true={vim=true}}
+ defaults={if_true=true}
},
{
full_name='indentexpr', abbreviation='inde',
@@ -1214,7 +1213,7 @@ return {
modelineexpr=true,
alloced=true,
varname='p_inde',
- defaults={if_true={vi=""}}
+ defaults={if_true=""}
},
{
full_name='indentkeys', abbreviation='indk',
@@ -1223,21 +1222,21 @@ return {
deny_duplicates=true,
alloced=true,
varname='p_indk',
- defaults={if_true={vi=indentkeys_default}}
+ defaults={if_true=indentkeys_default}
},
{
full_name='infercase', abbreviation='inf',
short_desc=N_("adjust case of match for keyword completion"),
type='bool', scope={'buffer'},
varname='p_inf',
- defaults={if_true={vi=false}}
+ defaults={if_true=false}
},
{
full_name='insertmode', abbreviation='im',
short_desc=N_("start the edit of a file in Insert mode"),
type='bool', scope={'global'},
varname='p_im',
- defaults={if_true={vi=false}}
+ defaults={if_true=false}
},
{
full_name='isfname', abbreviation='isf',
@@ -1249,8 +1248,8 @@ return {
condition='BACKSLASH_IN_FILENAME',
-- Excluded are: & and ^ are special in cmd.exe
-- ( and ) are used in text separating fnames */
- if_true={vi="@,48-57,/,\\,.,-,_,+,,,#,$,%,{,},[,],:,@-@,!,~,="},
- if_false={vi="@,48-57,/,.,-,_,+,,,#,$,%,~,="}
+ if_true="@,48-57,/,\\,.,-,_,+,,,#,$,%,{,},[,],:,@-@,!,~,=",
+ if_false="@,48-57,/,.,-,_,+,,,#,$,%,~,="
}
},
{
@@ -1261,8 +1260,8 @@ return {
varname='p_isi',
defaults={
condition='WIN32',
- if_true={vi="@,48-57,_,128-167,224-235"},
- if_false={vi="@,48-57,_,192-255"}
+ if_true="@,48-57,_,128-167,224-235",
+ if_false="@,48-57,_,192-255"
}
},
{
@@ -1272,7 +1271,7 @@ return {
deny_duplicates=true,
alloced=true,
varname='p_isk',
- defaults={if_true={vim="@,48-57,_,192-255"}}
+ defaults={if_true="@,48-57,_,192-255"}
},
{
full_name='isprint', abbreviation='isp',
@@ -1281,7 +1280,7 @@ return {
deny_duplicates=true,
redraw={'all_windows'},
varname='p_isp',
- defaults={if_true={vi="@,161-255"}
+ defaults={if_true="@,161-255"
}
},
{
@@ -1289,7 +1288,7 @@ return {
short_desc=N_("two spaces after a period with a join command"),
type='bool', scope={'global'},
varname='p_js',
- defaults={if_true={vi=true}}
+ defaults={if_true=false}
},
{
full_name='jumpoptions', abbreviation='jop',
@@ -1297,7 +1296,7 @@ return {
type='string', list='onecomma', scope={'global'},
deny_duplicates=true,
varname='p_jop',
- defaults={if_true={vim=''}}
+ defaults={if_true=''}
},
{
full_name='keymap', abbreviation='kmp',
@@ -1308,7 +1307,7 @@ return {
alloced=true,
redraw={'statuslines', 'current_buffer'},
varname='p_keymap', pv_name='p_kmap',
- defaults={if_true={vi=""}}
+ defaults={if_true=""}
},
{
full_name='keymodel', abbreviation='km',
@@ -1316,7 +1315,7 @@ return {
type='string', list='onecomma', scope={'global'},
deny_duplicates=true,
varname='p_km',
- defaults={if_true={vi=""}}
+ defaults={if_true=""}
},
{
full_name='keywordprg', abbreviation='kp',
@@ -1326,7 +1325,7 @@ return {
expand=true,
varname='p_kp',
defaults={
- if_true={vi=":Man"},
+ if_true=":Man",
}
},
{
@@ -1336,7 +1335,7 @@ return {
deny_duplicates=true,
secure=true,
varname='p_langmap',
- defaults={if_true={vi=""}}
+ defaults={if_true=""}
},
{
full_name='langmenu', abbreviation='lm',
@@ -1344,21 +1343,21 @@ return {
type='string', scope={'global'},
normal_fname_chars=true,
varname='p_lm',
- defaults={if_true={vi=""}}
+ defaults={if_true=""}
},
{
full_name='langnoremap', abbreviation='lnr',
short_desc=N_("do not apply 'langmap' to mapped characters"),
type='bool', scope={'global'},
varname='p_lnr',
- defaults={if_true={vim=true}}
+ defaults={if_true=true}
},
{
full_name='langremap', abbreviation='lrm',
short_desc=N_('No description'),
type='bool', scope={'global'},
varname='p_lrm',
- defaults={if_true={vim=false}}
+ defaults={if_true=false}
},
{
full_name='laststatus', abbreviation='ls',
@@ -1366,21 +1365,21 @@ return {
type='number', scope={'global'},
redraw={'all_windows'},
varname='p_ls',
- defaults={if_true={vim=2}}
+ defaults={if_true=2}
},
{
full_name='lazyredraw', abbreviation='lz',
short_desc=N_("don't redraw while executing macros"),
type='bool', scope={'global'},
varname='p_lz',
- defaults={if_true={vi=false}}
+ defaults={if_true=false}
},
{
full_name='linebreak', abbreviation='lbr',
short_desc=N_("wrap long lines at a blank"),
type='bool', scope={'window'},
redraw={'current_window'},
- defaults={if_true={vi=false}}
+ defaults={if_true=false}
},
{
full_name='lines',
@@ -1389,7 +1388,7 @@ return {
no_mkrc=true,
redraw={'everything'},
varname='p_lines',
- defaults={if_true={vi=macros('DFLT_ROWS')}}
+ defaults={if_true=macros('DFLT_ROWS')}
},
{
full_name='linespace', abbreviation='lsp',
@@ -1397,14 +1396,14 @@ return {
type='number', scope={'global'},
redraw={'ui_option'},
varname='p_linespace',
- defaults={if_true={vi=0}}
+ defaults={if_true=0}
},
{
full_name='lisp',
short_desc=N_("indenting for Lisp"),
type='bool', scope={'buffer'},
varname='p_lisp',
- defaults={if_true={vi=false}}
+ defaults={if_true=false}
},
{
full_name='lispwords', abbreviation='lw',
@@ -1412,14 +1411,14 @@ return {
type='string', list='onecomma', scope={'global', 'buffer'},
deny_duplicates=true,
varname='p_lispwords', pv_name='p_lw',
- defaults={if_true={vi=macros('LISPWORD_VALUE')}}
+ defaults={if_true=macros('LISPWORD_VALUE')}
},
{
full_name='list',
short_desc=N_("<Tab> and <EOL>"),
type='bool', scope={'window'},
redraw={'current_window'},
- defaults={if_true={vi=false}}
+ defaults={if_true=false}
},
{
full_name='listchars', abbreviation='lcs',
@@ -1429,21 +1428,21 @@ return {
alloced=true,
redraw={'current_window'},
varname='p_lcs',
- defaults={if_true={vim="tab:> ,trail:-,nbsp:+"}}
+ defaults={if_true="tab:> ,trail:-,nbsp:+"}
},
{
full_name='loadplugins', abbreviation='lpl',
short_desc=N_("load plugin scripts when starting up"),
type='bool', scope={'global'},
varname='p_lpl',
- defaults={if_true={vi=true}}
+ defaults={if_true=true}
},
{
full_name='magic',
short_desc=N_("special characters in search patterns"),
type='bool', scope={'global'},
varname='p_magic',
- defaults={if_true={vi=true}}
+ defaults={if_true=true}
},
{
full_name='makeef', abbreviation='mef',
@@ -1452,14 +1451,14 @@ return {
secure=true,
expand=true,
varname='p_mef',
- defaults={if_true={vi=""}}
+ defaults={if_true=""}
},
{
full_name='makeencoding', abbreviation='menc',
short_desc=N_("Converts the output of external commands"),
type='string', scope={'global', 'buffer'},
varname='p_menc',
- defaults={if_true={vi=""}}
+ defaults={if_true=""}
},
{
full_name='makeprg', abbreviation='mp',
@@ -1468,7 +1467,7 @@ return {
secure=true,
expand=true,
varname='p_mp',
- defaults={if_true={vi="make"}}
+ defaults={if_true="make"}
},
{
full_name='matchpairs', abbreviation='mps',
@@ -1477,49 +1476,49 @@ return {
deny_duplicates=true,
alloced=true,
varname='p_mps',
- defaults={if_true={vi="(:),{:},[:]"}}
+ defaults={if_true="(:),{:},[:]"}
},
{
full_name='matchtime', abbreviation='mat',
short_desc=N_("tenths of a second to show matching paren"),
type='number', scope={'global'},
varname='p_mat',
- defaults={if_true={vi=5}}
+ defaults={if_true=5}
},
{
full_name='maxcombine', abbreviation='mco',
short_desc=N_("maximum nr of combining characters displayed"),
type='number', scope={'global'},
varname='p_mco',
- defaults={if_true={vi=6}}
+ defaults={if_true=6}
},
{
full_name='maxfuncdepth', abbreviation='mfd',
short_desc=N_("maximum recursive depth for user functions"),
type='number', scope={'global'},
varname='p_mfd',
- defaults={if_true={vi=100}}
+ defaults={if_true=100}
},
{
full_name='maxmapdepth', abbreviation='mmd',
short_desc=N_("maximum recursive depth for mapping"),
type='number', scope={'global'},
varname='p_mmd',
- defaults={if_true={vi=1000}}
+ defaults={if_true=1000}
},
{
full_name='maxmempattern', abbreviation='mmp',
short_desc=N_("maximum memory (in Kbyte) used for pattern search"),
type='number', scope={'global'},
varname='p_mmp',
- defaults={if_true={vi=1000}}
+ defaults={if_true=1000}
},
{
full_name='menuitems', abbreviation='mis',
short_desc=N_("maximum number of items in a menu"),
type='number', scope={'global'},
varname='p_mis',
- defaults={if_true={vi=25}}
+ defaults={if_true=25}
},
{
full_name='mkspellmem', abbreviation='msm',
@@ -1528,14 +1527,14 @@ return {
secure=true,
expand=true,
varname='p_msm',
- defaults={if_true={vi="460000,2000,500"}}
+ defaults={if_true="460000,2000,500"}
},
{
full_name='modeline', abbreviation='ml',
short_desc=N_("recognize modelines at start or end of file"),
type='bool', scope={'buffer'},
varname='p_ml',
- defaults={if_true={vim=true}}
+ defaults={if_true=true}
},
{
full_name='modelineexpr', abbreviation='mle',
@@ -1543,14 +1542,14 @@ return {
type='bool', scope={'global'},
secure=true,
varname='p_mle',
- defaults={if_true={vi=false}}
+ defaults={if_true=false}
},
{
full_name='modelines', abbreviation='mls',
short_desc=N_("number of lines checked for modelines"),
type='number', scope={'global'},
varname='p_mls',
- defaults={if_true={vi=5}}
+ defaults={if_true=5}
},
{
full_name='modifiable', abbreviation='ma',
@@ -1558,7 +1557,7 @@ return {
type='bool', scope={'buffer'},
noglob=true,
varname='p_ma',
- defaults={if_true={vi=true}}
+ defaults={if_true=true}
},
{
full_name='modified', abbreviation='mod',
@@ -1567,21 +1566,21 @@ return {
no_mkrc=true,
redraw={'statuslines'},
varname='p_mod',
- defaults={if_true={vi=false}}
+ defaults={if_true=false}
},
{
full_name='more',
short_desc=N_("listings when the whole screen is filled"),
type='bool', scope={'global'},
varname='p_more',
- defaults={if_true={vim=true}}
+ defaults={if_true=true}
},
{
full_name='mouse',
short_desc=N_("the use of mouse clicks"),
type='string', list='flags', scope={'global'},
varname='p_mouse',
- defaults={if_true={vim=""}}
+ defaults={if_true=""}
},
{
full_name='mousefocus', abbreviation='mousef',
@@ -1589,21 +1588,21 @@ return {
type='bool', scope={'global'},
redraw={'ui_option'},
varname='p_mousef',
- defaults={if_true={vi=false}}
+ defaults={if_true=false}
},
{
full_name='mousehide', abbreviation='mh',
short_desc=N_("hide mouse pointer while typing"),
type='bool', scope={'global'},
enable_if=false,
- defaults={if_true={vi=true}}
+ defaults={if_true=true}
},
{
full_name='mousemodel', abbreviation='mousem',
short_desc=N_("changes meaning of mouse buttons"),
type='string', scope={'global'},
varname='p_mousem',
- defaults={if_true={vi="extend"}}
+ defaults={if_true="extend"}
},
{
full_name='mouseshape', abbreviation='mouses',
@@ -1617,7 +1616,7 @@ return {
short_desc=N_("max time between mouse double-click"),
type='number', scope={'global'},
varname='p_mouset',
- defaults={if_true={vi=500}}
+ defaults={if_true=500}
},
{
full_name='nrformats', abbreviation='nf',
@@ -1626,21 +1625,21 @@ return {
deny_duplicates=true,
alloced=true,
varname='p_nf',
- defaults={if_true={vim="bin,hex"}}
+ defaults={if_true="bin,hex"}
},
{
full_name='number', abbreviation='nu',
short_desc=N_("print the line number in front of each line"),
type='bool', scope={'window'},
redraw={'current_window'},
- defaults={if_true={vi=false}}
+ defaults={if_true=false}
},
{
full_name='numberwidth', abbreviation='nuw',
short_desc=N_("number of columns used for the line number"),
type='number', scope={'window'},
redraw={'current_window'},
- defaults={if_true={vim=4}}
+ defaults={if_true=4}
},
{
full_name='omnifunc', abbreviation='ofu',
@@ -1649,14 +1648,14 @@ return {
secure=true,
alloced=true,
varname='p_ofu',
- defaults={if_true={vi=""}}
+ defaults={if_true=""}
},
{
full_name='opendevice', abbreviation='odev',
short_desc=N_("allow reading/writing devices on MS-Windows"),
type='bool', scope={'global'},
enable_if=false,
- defaults={if_true={vim=false}}
+ defaults={if_true=false}
},
{
full_name='operatorfunc', abbreviation='opfunc',
@@ -1664,7 +1663,7 @@ return {
type='string', scope={'global'},
secure=true,
varname='p_opfunc',
- defaults={if_true={vi=""}}
+ defaults={if_true=""}
},
{
full_name='packpath', abbreviation='pp',
@@ -1674,14 +1673,14 @@ return {
secure=true,
expand=true,
varname='p_pp',
- defaults={if_true={vi=''}}
+ defaults={if_true=''}
},
{
full_name='paragraphs', abbreviation='para',
short_desc=N_("nroff macros that separate paragraphs"),
type='string', scope={'global'},
varname='p_para',
- defaults={if_true={vi="IPLPPPQPP TPHPLIPpLpItpplpipbp"}}
+ defaults={if_true="IPLPPPQPP TPHPLIPpLpItpplpipbp"}
},
{
full_name='paste',
@@ -1689,14 +1688,14 @@ return {
type='bool', scope={'global'},
pri_mkrc=true,
varname='p_paste',
- defaults={if_true={vi=false}}
+ defaults={if_true=false}
},
{
full_name='pastetoggle', abbreviation='pt',
short_desc=N_("key code that causes 'paste' to toggle"),
type='string', scope={'global'},
varname='p_pt',
- defaults={if_true={vi=""}}
+ defaults={if_true=""}
},
{
full_name='patchexpr', abbreviation='pex',
@@ -1704,7 +1703,7 @@ return {
type='string', scope={'global'},
secure=true,
varname='p_pex',
- defaults={if_true={vi=""}}
+ defaults={if_true=""}
},
{
full_name='patchmode', abbreviation='pm',
@@ -1712,7 +1711,7 @@ return {
type='string', scope={'global'},
normal_fname_chars=true,
varname='p_pm',
- defaults={if_true={vi=""}}
+ defaults={if_true=""}
},
{
full_name='path', abbreviation='pa',
@@ -1721,21 +1720,21 @@ return {
deny_duplicates=true,
expand=true,
varname='p_path',
- defaults={if_true={vi=".,/usr/include,,"}}
+ defaults={if_true=".,/usr/include,,"}
},
{
full_name='preserveindent', abbreviation='pi',
short_desc=N_("preserve the indent structure when reindenting"),
type='bool', scope={'buffer'},
varname='p_pi',
- defaults={if_true={vi=false}}
+ defaults={if_true=false}
},
{
full_name='previewheight', abbreviation='pvh',
short_desc=N_("height of the preview window"),
type='number', scope={'global'},
varname='p_pvh',
- defaults={if_true={vi=12}}
+ defaults={if_true=12}
},
{
full_name='previewwindow', abbreviation='pvw',
@@ -1743,7 +1742,7 @@ return {
type='bool', scope={'window'},
noglob=true,
redraw={'statuslines'},
- defaults={if_true={vi=false}}
+ defaults={if_true=false}
},
{
full_name='printdevice', abbreviation='pdev',
@@ -1751,14 +1750,14 @@ return {
type='string', scope={'global'},
secure=true,
varname='p_pdev',
- defaults={if_true={vi=""}}
+ defaults={if_true=""}
},
{
full_name='printencoding', abbreviation='penc',
short_desc=N_("encoding to be used for printing"),
type='string', scope={'global'},
varname='p_penc',
- defaults={if_true={vi=""}}
+ defaults={if_true=""}
},
{
full_name='printexpr', abbreviation='pexpr',
@@ -1766,35 +1765,35 @@ return {
type='string', scope={'global'},
secure=true,
varname='p_pexpr',
- defaults={if_true={vi=""}}
+ defaults={if_true=""}
},
{
full_name='printfont', abbreviation='pfn',
short_desc=N_("name of the font to be used for :hardcopy"),
type='string', scope={'global'},
varname='p_pfn',
- defaults={if_true={vi="courier"}}
+ defaults={if_true="courier"}
},
{
full_name='printheader', abbreviation='pheader',
short_desc=N_("format of the header used for :hardcopy"),
type='string', scope={'global'},
varname='p_header',
- defaults={if_true={vi="%<%f%h%m%=Page %N"}}
+ defaults={if_true="%<%f%h%m%=Page %N"}
},
{
full_name='printmbcharset', abbreviation='pmbcs',
short_desc=N_("CJK character set to be used for :hardcopy"),
type='string', scope={'global'},
varname='p_pmcs',
- defaults={if_true={vi=""}}
+ defaults={if_true=""}
},
{
full_name='printmbfont', abbreviation='pmbfn',
short_desc=N_("font names to be used for CJK output of :hardcopy"),
type='string', scope={'global'},
varname='p_pmfn',
- defaults={if_true={vi=""}}
+ defaults={if_true=""}
},
{
full_name='printoptions', abbreviation='popt',
@@ -1802,14 +1801,14 @@ return {
type='string', list='onecomma', scope={'global'},
deny_duplicates=true,
varname='p_popt',
- defaults={if_true={vi=""}}
+ defaults={if_true=""}
},
{
full_name='prompt',
short_desc=N_("enable prompt in Ex mode"),
type='bool', scope={'global'},
varname='p_force_on',
- defaults={if_true={vi=true}}
+ defaults={if_true=true}
},
{
full_name='pumblend', abbreviation='pb',
@@ -1817,21 +1816,21 @@ return {
type='number', scope={'global'},
redraw={'ui_option'},
varname='p_pb',
- defaults={if_true={vi=0}}
+ defaults={if_true=0}
},
{
full_name='pumheight', abbreviation='ph',
short_desc=N_("maximum height of the popup menu"),
type='number', scope={'global'},
varname='p_ph',
- defaults={if_true={vi=0}}
+ defaults={if_true=0}
},
{
full_name='pumwidth', abbreviation='pw',
short_desc=N_("minimum width of the popup menu"),
type='number', scope={'global'},
varname='p_pw',
- defaults={if_true={vi=15}}
+ defaults={if_true=15}
},
{
full_name='pyxversion', abbreviation='pyx',
@@ -1839,14 +1838,14 @@ return {
type='number', scope={'global'},
secure=true,
varname='p_pyx',
- defaults={if_true={vi=0}}
+ defaults={if_true=0}
},
{
full_name='quickfixtextfunc', abbreviation='qftf',
short_desc=N_("customize the quickfix window"),
type='string', scope={'global'},
varname='p_qftf',
- defaults={if_true={vi=""}}
+ defaults={if_true=""}
},
{
full_name='quoteescape', abbreviation='qe',
@@ -1854,7 +1853,7 @@ return {
type='string', scope={'buffer'},
alloced=true,
varname='p_qe',
- defaults={if_true={vi="\\"}}
+ defaults={if_true="\\"}
},
{
full_name='readonly', abbreviation='ro',
@@ -1863,63 +1862,63 @@ return {
noglob=true,
redraw={'statuslines'},
varname='p_ro',
- defaults={if_true={vi=false}}
+ defaults={if_true=false}
},
{
full_name='redrawdebug', abbreviation='rdb',
short_desc=N_("Changes the way redrawing works (debug)"),
type='string', list='onecomma', scope={'global'},
varname='p_rdb',
- defaults={if_true={vi=''}}
+ defaults={if_true=''}
},
{
full_name='redrawtime', abbreviation='rdt',
short_desc=N_("timeout for 'hlsearch' and |:match| highlighting"),
type='number', scope={'global'},
varname='p_rdt',
- defaults={if_true={vi=2000}}
+ defaults={if_true=2000}
},
{
full_name='regexpengine', abbreviation='re',
short_desc=N_("default regexp engine to use"),
type='number', scope={'global'},
varname='p_re',
- defaults={if_true={vi=0}}
+ defaults={if_true=0}
},
{
full_name='relativenumber', abbreviation='rnu',
short_desc=N_("show relative line number in front of each line"),
type='bool', scope={'window'},
redraw={'current_window'},
- defaults={if_true={vi=false}}
+ defaults={if_true=false}
},
{
full_name='remap',
short_desc=N_("mappings to work recursively"),
type='bool', scope={'global'},
varname='p_remap',
- defaults={if_true={vi=true}}
+ defaults={if_true=true}
},
{
full_name='report',
short_desc=N_("for reporting nr. of lines changed"),
type='number', scope={'global'},
varname='p_report',
- defaults={if_true={vi=2}}
+ defaults={if_true=2}
},
{
full_name='revins', abbreviation='ri',
short_desc=N_("inserting characters will work backwards"),
type='bool', scope={'global'},
varname='p_ri',
- defaults={if_true={vi=false}}
+ defaults={if_true=false}
},
{
full_name='rightleft', abbreviation='rl',
short_desc=N_("window is right-to-left oriented"),
type='bool', scope={'window'},
redraw={'current_window'},
- defaults={if_true={vi=false}}
+ defaults={if_true=false}
},
{
full_name='rightleftcmd', abbreviation='rlc',
@@ -1927,7 +1926,7 @@ return {
type='string', scope={'window'},
alloced=true,
redraw={'current_window'},
- defaults={if_true={vi="search"}}
+ defaults={if_true="search"}
},
{
full_name='ruler', abbreviation='ru',
@@ -1935,7 +1934,7 @@ return {
type='bool', scope={'global'},
redraw={'statuslines'},
varname='p_ru',
- defaults={if_true={vi=true}}
+ defaults={if_true=true}
},
{
full_name='rulerformat', abbreviation='ruf',
@@ -1945,7 +1944,7 @@ return {
modelineexpr=true,
redraw={'statuslines'},
varname='p_ruf',
- defaults={if_true={vi=""}}
+ defaults={if_true=""}
},
{
full_name='runtimepath', abbreviation='rtp',
@@ -1955,7 +1954,7 @@ return {
secure=true,
expand='nodefault',
varname='p_rtp',
- defaults={if_true={vi=''}}
+ defaults={if_true=''}
},
{
full_name='scroll', abbreviation='scr',
@@ -1963,7 +1962,7 @@ return {
type='number', scope={'window'},
no_mkrc=true,
pv_name='p_scroll',
- defaults={if_true={vi=0}}
+ defaults={if_true=0}
},
{
full_name='scrollback', abbreviation='scbk',
@@ -1971,21 +1970,21 @@ return {
type='number', scope={'buffer'},
varname='p_scbk',
redraw={'current_buffer'},
- defaults={if_true={vi=-1}}
+ defaults={if_true=-1}
},
{
full_name='scrollbind', abbreviation='scb',
short_desc=N_("scroll in window as other windows scroll"),
type='bool', scope={'window'},
pv_name='p_scbind',
- defaults={if_true={vi=false}}
+ defaults={if_true=false}
},
{
full_name='scrolljump', abbreviation='sj',
short_desc=N_("minimum number of lines to scroll"),
type='number', scope={'global'},
varname='p_sj',
- defaults={if_true={vi=1}}
+ defaults={if_true=1}
},
{
full_name='scrolloff', abbreviation='so',
@@ -1993,7 +1992,7 @@ return {
type='number', scope={'global', 'window'},
redraw={'all_windows'},
varname='p_so',
- defaults={if_true={vi=0}}
+ defaults={if_true=0}
},
{
full_name='scrollopt', abbreviation='sbo',
@@ -2001,14 +2000,14 @@ return {
type='string', list='onecomma', scope={'global'},
deny_duplicates=true,
varname='p_sbo',
- defaults={if_true={vi="ver,jump"}}
+ defaults={if_true="ver,jump"}
},
{
full_name='sections', abbreviation='sect',
short_desc=N_("nroff macros that separate sections"),
type='string', scope={'global'},
varname='p_sections',
- defaults={if_true={vi="SHNHH HUnhsh"}}
+ defaults={if_true="SHNHH HUnhsh"}
},
{
full_name='secure',
@@ -2016,14 +2015,14 @@ return {
type='bool', scope={'global'},
secure=true,
varname='p_secure',
- defaults={if_true={vi=false}}
+ defaults={if_true=false}
},
{
full_name='selection', abbreviation='sel',
short_desc=N_("what type of selection to use"),
type='string', scope={'global'},
varname='p_sel',
- defaults={if_true={vi="inclusive"}}
+ defaults={if_true="inclusive"}
},
{
full_name='selectmode', abbreviation='slm',
@@ -2031,7 +2030,7 @@ return {
type='string', list='onecomma', scope={'global'},
deny_duplicates=true,
varname='p_slm',
- defaults={if_true={vi=""}}
+ defaults={if_true=""}
},
{
full_name='sessionoptions', abbreviation='ssop',
@@ -2039,9 +2038,7 @@ return {
type='string', list='onecomma', scope={'global'},
deny_duplicates=true,
varname='p_ssop',
- defaults={if_true={
- vim="blank,buffers,curdir,folds,help,tabpages,winsize"
- }}
+ defaults={if_true="blank,buffers,curdir,folds,help,tabpages,winsize"}
},
{
full_name='shada', abbreviation='sd',
@@ -2050,7 +2047,7 @@ return {
deny_duplicates=true,
secure=true,
varname='p_shada',
- defaults={if_true={vim="!,'100,<50,s10,h"}}
+ defaults={if_true="!,'100,<50,s10,h"}
},
{
full_name='shadafile', abbreviation='sdf',
@@ -2060,7 +2057,7 @@ return {
secure=true,
expand=true,
varname='p_shadafile',
- defaults={if_true={vi=""}}
+ defaults={if_true=""}
},
{
full_name='shell', abbreviation='sh',
@@ -2071,8 +2068,8 @@ return {
varname='p_sh',
defaults={
condition='WIN32',
- if_true={vi="cmd.exe"},
- if_false={vi="sh"}
+ if_true="cmd.exe",
+ if_false="sh"
}
},
{
@@ -2083,8 +2080,8 @@ return {
varname='p_shcf',
defaults={
condition='WIN32',
- if_true={vi="/s /c"},
- if_false={vi="-c"}
+ if_true="/s /c",
+ if_false="-c"
}
},
{
@@ -2095,8 +2092,8 @@ return {
varname='p_sp',
defaults={
condition='WIN32',
- if_true={vi=">%s 2>&1"},
- if_false={vi="| tee"},
+ if_true=">%s 2>&1",
+ if_false="| tee",
}
},
{
@@ -2105,7 +2102,7 @@ return {
type='string', scope={'global'},
secure=true,
varname='p_shq',
- defaults={if_true={vi=""}}
+ defaults={if_true=""}
},
{
full_name='shellredir', abbreviation='srr',
@@ -2115,8 +2112,8 @@ return {
varname='p_srr',
defaults={
condition='WIN32',
- if_true={vi=">%s 2>&1"},
- if_false={vi=">"}
+ if_true=">%s 2>&1",
+ if_false=">"
}
},
{
@@ -2125,14 +2122,14 @@ return {
type='bool', scope={'global'},
varname='p_ssl',
enable_if='BACKSLASH_IN_FILENAME',
- defaults={if_true={vi=false}}
+ defaults={if_true=false}
},
{
full_name='shelltemp', abbreviation='stmp',
short_desc=N_("whether to use a temp file for shell commands"),
type='bool', scope={'global'},
varname='p_stmp',
- defaults={if_true={vim=true}}
+ defaults={if_true=true}
},
{
full_name='shellxquote', abbreviation='sxq',
@@ -2142,8 +2139,8 @@ return {
varname='p_sxq',
defaults={
condition='WIN32',
- if_true={vi="\""},
- if_false={vi=""},
+ if_true="\"",
+ if_false="",
}
},
{
@@ -2152,28 +2149,28 @@ return {
type='string', scope={'global'},
secure=true,
varname='p_sxe',
- defaults={if_true={vi=""}}
+ defaults={if_true=""}
},
{
full_name='shiftround', abbreviation='sr',
short_desc=N_("round indent to multiple of shiftwidth"),
type='bool', scope={'global'},
varname='p_sr',
- defaults={if_true={vi=false}}
+ defaults={if_true=false}
},
{
full_name='shiftwidth', abbreviation='sw',
short_desc=N_("number of spaces to use for (auto)indent step"),
type='number', scope={'buffer'},
varname='p_sw',
- defaults={if_true={vi=8}}
+ defaults={if_true=8}
},
{
full_name='shortmess', abbreviation='shm',
short_desc=N_("list of flags, reduce length of messages"),
type='string', list='flags', scope={'global'},
varname='p_shm',
- defaults={if_true={vim="filnxtToOF"}}
+ defaults={if_true="filnxtToOF"}
},
{
full_name='showbreak', abbreviation='sbr',
@@ -2181,35 +2178,35 @@ return {
type='string', scope={'global'},
redraw={'all_windows'},
varname='p_sbr',
- defaults={if_true={vi=""}}
+ defaults={if_true=""}
},
{
full_name='showcmd', abbreviation='sc',
short_desc=N_("show (partial) command in status line"),
type='bool', scope={'global'},
varname='p_sc',
- defaults={if_true={vim=true}}
+ defaults={if_true=true}
},
{
full_name='showfulltag', abbreviation='sft',
short_desc=N_("show full tag pattern when completing tag"),
type='bool', scope={'global'},
varname='p_sft',
- defaults={if_true={vi=false}}
+ defaults={if_true=false}
},
{
full_name='showmatch', abbreviation='sm',
short_desc=N_("briefly jump to matching bracket if insert one"),
type='bool', scope={'global'},
varname='p_sm',
- defaults={if_true={vi=false}}
+ defaults={if_true=false}
},
{
full_name='showmode', abbreviation='smd',
short_desc=N_("message on status line to show current mode"),
type='bool', scope={'global'},
varname='p_smd',
- defaults={if_true={vim=true}}
+ defaults={if_true=true}
},
{
full_name='showtabline', abbreviation='stal',
@@ -2217,14 +2214,14 @@ return {
type='number', scope={'global'},
redraw={'all_windows', 'ui_option'},
varname='p_stal',
- defaults={if_true={vi=1}}
+ defaults={if_true=1}
},
{
full_name='sidescroll', abbreviation='ss',
short_desc=N_("minimum number of columns to scroll horizontal"),
type='number', scope={'global'},
varname='p_ss',
- defaults={if_true={vi=1}}
+ defaults={if_true=1}
},
{
full_name='sidescrolloff', abbreviation='siso',
@@ -2232,7 +2229,7 @@ return {
type='number', scope={'global', 'window'},
redraw={'all_windows'},
varname='p_siso',
- defaults={if_true={vi=0}}
+ defaults={if_true=0}
},
{
full_name='signcolumn', abbreviation='scl',
@@ -2240,42 +2237,42 @@ return {
type='string', scope={'window'},
alloced=true,
redraw={'current_window'},
- defaults={if_true={vi="auto"}}
+ defaults={if_true="auto"}
},
{
full_name='smartcase', abbreviation='scs',
short_desc=N_("no ignore case when pattern has uppercase"),
type='bool', scope={'global'},
varname='p_scs',
- defaults={if_true={vi=false}}
+ defaults={if_true=false}
},
{
full_name='smartindent', abbreviation='si',
short_desc=N_("smart autoindenting for C programs"),
type='bool', scope={'buffer'},
varname='p_si',
- defaults={if_true={vi=false}}
+ defaults={if_true=false}
},
{
full_name='smarttab', abbreviation='sta',
short_desc=N_("use 'shiftwidth' when inserting <Tab>"),
type='bool', scope={'global'},
varname='p_sta',
- defaults={if_true={vim=true}}
+ defaults={if_true=true}
},
{
full_name='softtabstop', abbreviation='sts',
short_desc=N_("number of spaces that <Tab> uses while editing"),
type='number', scope={'buffer'},
varname='p_sts',
- defaults={if_true={vi=0}}
+ defaults={if_true=0}
},
{
full_name='spell',
short_desc=N_("spell checking"),
type='bool', scope={'window'},
redraw={'current_window'},
- defaults={if_true={vi=false}}
+ defaults={if_true=false}
},
{
full_name='spellcapcheck', abbreviation='spc',
@@ -2284,7 +2281,7 @@ return {
alloced=true,
redraw={'current_buffer'},
varname='p_spc',
- defaults={if_true={vi="[.?!]\\_[\\])'\" ]\\+"}}
+ defaults={if_true="[.?!]\\_[\\])'\" ]\\+"}
},
{
full_name='spellfile', abbreviation='spf',
@@ -2295,7 +2292,7 @@ return {
alloced=true,
expand=true,
varname='p_spf',
- defaults={if_true={vi=""}}
+ defaults={if_true=""}
},
{
full_name='spelllang', abbreviation='spl',
@@ -2306,7 +2303,7 @@ return {
expand=true,
redraw={'current_buffer'},
varname='p_spl',
- defaults={if_true={vi="en"}}
+ defaults={if_true="en"}
},
{
full_name='spellsuggest', abbreviation='sps',
@@ -2316,7 +2313,7 @@ return {
secure=true,
expand=true,
varname='p_sps',
- defaults={if_true={vi="best"}}
+ defaults={if_true="best"}
},
{
full_name='spelloptions', abbreviation='spo',
@@ -2325,21 +2322,21 @@ return {
secure=true,
expand=true,
varname='p_spo',
- defaults={if_true={vim=""}}
+ defaults={if_true=""}
},
{
full_name='splitbelow', abbreviation='sb',
short_desc=N_("new window from split is below the current one"),
type='bool', scope={'global'},
varname='p_sb',
- defaults={if_true={vi=false}}
+ defaults={if_true=false}
},
{
full_name='splitright', abbreviation='spr',
short_desc=N_("new window is put right of the current one"),
type='bool', scope={'global'},
varname='p_spr',
- defaults={if_true={vi=false}}
+ defaults={if_true=false}
},
{
full_name='startofline', abbreviation='sol',
@@ -2347,7 +2344,7 @@ return {
type='bool', scope={'global'},
vim=false,
varname='p_sol',
- defaults={if_true={vi=false}}
+ defaults={if_true=false}
},
{
full_name='statusline', abbreviation='stl',
@@ -2357,7 +2354,7 @@ return {
modelineexpr=true,
redraw={'statuslines'},
varname='p_stl',
- defaults={if_true={vi=""}}
+ defaults={if_true=""}
},
{
full_name='suffixes', abbreviation='su',
@@ -2365,7 +2362,7 @@ return {
type='string', list='onecomma', scope={'global'},
deny_duplicates=true,
varname='p_su',
- defaults={if_true={vi=".bak,~,.o,.h,.info,.swp,.obj"}}
+ defaults={if_true=".bak,~,.o,.h,.info,.swp,.obj"}
},
{
full_name='suffixesadd', abbreviation='sua',
@@ -2374,7 +2371,7 @@ return {
deny_duplicates=true,
alloced=true,
varname='p_sua',
- defaults={if_true={vi=""}}
+ defaults={if_true=""}
},
{
full_name='swapfile', abbreviation='swf',
@@ -2382,7 +2379,7 @@ return {
type='bool', scope={'buffer'},
redraw={'statuslines'},
varname='p_swf',
- defaults={if_true={vi=true}}
+ defaults={if_true=true}
},
{
full_name='switchbuf', abbreviation='swb',
@@ -2390,7 +2387,7 @@ return {
type='string', list='onecomma', scope={'global'},
deny_duplicates=true,
varname='p_swb',
- defaults={if_true={vi=""}}
+ defaults={if_true="uselast"}
},
{
full_name='synmaxcol', abbreviation='smc',
@@ -2398,7 +2395,7 @@ return {
type='number', scope={'buffer'},
redraw={'current_buffer'},
varname='p_smc',
- defaults={if_true={vi=3000}}
+ defaults={if_true=3000}
},
{
full_name='syntax', abbreviation='syn',
@@ -2408,14 +2405,14 @@ return {
normal_fname_chars=true,
alloced=true,
varname='p_syn',
- defaults={if_true={vi=""}}
+ defaults={if_true=""}
},
{
full_name='tagfunc', abbreviation='tfu',
short_desc=N_("function used to perform tag searches"),
type='string', scope={'buffer'},
varname='p_tfu',
- defaults={if_true={vi=""}}
+ defaults={if_true=""}
},
{
full_name='tabline', abbreviation='tal',
@@ -2424,14 +2421,14 @@ return {
modelineexpr=true,
redraw={'all_windows'},
varname='p_tal',
- defaults={if_true={vi=""}}
+ defaults={if_true=""}
},
{
full_name='tabpagemax', abbreviation='tpm',
short_desc=N_("maximum number of tab pages for |-p| and \"tab all\""),
type='number', scope={'global'},
varname='p_tpm',
- defaults={if_true={vim=50}}
+ defaults={if_true=50}
},
{
full_name='tabstop', abbreviation='ts',
@@ -2439,35 +2436,35 @@ return {
type='number', scope={'buffer'},
redraw={'current_buffer'},
varname='p_ts',
- defaults={if_true={vi=8}}
+ defaults={if_true=8}
},
{
full_name='tagbsearch', abbreviation='tbs',
short_desc=N_("use binary searching in tags files"),
type='bool', scope={'global'},
varname='p_tbs',
- defaults={if_true={vi=true}}
+ defaults={if_true=true}
},
{
full_name='tagcase', abbreviation='tc',
short_desc=N_("how to handle case when searching in tags files"),
type='string', scope={'global', 'buffer'},
varname='p_tc',
- defaults={if_true={vim="followic"}}
+ defaults={if_true="followic"}
},
{
full_name='taglength', abbreviation='tl',
short_desc=N_("number of significant characters for a tag"),
type='number', scope={'global'},
varname='p_tl',
- defaults={if_true={vi=0}}
+ defaults={if_true=0}
},
{
full_name='tagrelative', abbreviation='tr',
short_desc=N_("file names in tag file are relative"),
type='bool', scope={'global'},
varname='p_tr',
- defaults={if_true={vim=true}}
+ defaults={if_true=true}
},
{
full_name='tags', abbreviation='tag',
@@ -2476,27 +2473,27 @@ return {
deny_duplicates=true,
expand=true,
varname='p_tags',
- defaults={if_true={vi="./tags;,tags"}}
+ defaults={if_true="./tags;,tags"}
},
{
full_name='tagstack', abbreviation='tgst',
short_desc=N_("push tags onto the tag stack"),
type='bool', scope={'global'},
varname='p_tgst',
- defaults={if_true={vi=true}}
+ defaults={if_true=true}
},
{
full_name='termbidi', abbreviation='tbidi',
short_desc=N_("terminal takes care of bi-directionality"),
type='bool', scope={'global'},
varname='p_tbidi',
- defaults={if_true={vi=false}}
+ defaults={if_true=false}
},
{
full_name='termencoding', abbreviation='tenc',
short_desc=N_("Terminal encodig"),
type='string', scope={'global'},
- defaults={if_true={vi=""}}
+ defaults={if_true=""}
},
{
full_name='termguicolors', abbreviation='tgc',
@@ -2504,21 +2501,21 @@ return {
type='bool', scope={'global'},
redraw={'ui_option'},
varname='p_tgc',
- defaults={if_true={vi=false}}
+ defaults={if_true=false}
},
{
full_name='termpastefilter', abbreviation='tpf',
type='string', list='onecomma', scope={'global'},
deny_duplicates=true,
varname='p_tpf',
- defaults={if_true={vim="BS,HT,ESC,DEL"}}
+ defaults={if_true="BS,HT,ESC,DEL"}
},
{
full_name='terse',
short_desc=N_("hides notification of search wrap"),
type='bool', scope={'global'},
varname='p_terse',
- defaults={if_true={vi=false}}
+ defaults={if_true=false}
},
{
full_name='textwidth', abbreviation='tw',
@@ -2526,7 +2523,7 @@ return {
type='number', scope={'buffer'},
redraw={'current_buffer'},
varname='p_tw',
- defaults={if_true={vi=0}}
+ defaults={if_true=0}
},
{
full_name='thesaurus', abbreviation='tsr',
@@ -2536,42 +2533,42 @@ return {
normal_dname_chars=true,
expand=true,
varname='p_tsr',
- defaults={if_true={vi=""}}
+ defaults={if_true=""}
},
{
full_name='tildeop', abbreviation='top',
short_desc=N_("tilde command \"~\" behaves like an operator"),
type='bool', scope={'global'},
varname='p_to',
- defaults={if_true={vi=false}}
+ defaults={if_true=false}
},
{
full_name='timeout', abbreviation='to',
short_desc=N_("time out on mappings and key codes"),
type='bool', scope={'global'},
varname='p_timeout',
- defaults={if_true={vi=true}}
+ defaults={if_true=true}
},
{
full_name='timeoutlen', abbreviation='tm',
short_desc=N_("time out time in milliseconds"),
type='number', scope={'global'},
varname='p_tm',
- defaults={if_true={vi=1000}}
+ defaults={if_true=1000}
},
{
full_name='title',
short_desc=N_("Vim set the title of the window"),
type='bool', scope={'global'},
varname='p_title',
- defaults={if_true={vi=false}}
+ defaults={if_true=false}
},
{
full_name='titlelen',
short_desc=N_("of 'columns' used for window title"),
type='number', scope={'global'},
varname='p_titlelen',
- defaults={if_true={vi=85}}
+ defaults={if_true=85}
},
{
full_name='titleold',
@@ -2580,7 +2577,7 @@ return {
secure=true,
no_mkrc=true,
varname='p_titleold',
- defaults={if_true={vi=""}}
+ defaults={if_true=""}
},
{
full_name='titlestring',
@@ -2588,7 +2585,7 @@ return {
type='string', scope={'global'},
modelineexpr=true,
varname='p_titlestring',
- defaults={if_true={vi=""}}
+ defaults={if_true=""}
},
{
full_name='ttimeout',
@@ -2596,7 +2593,7 @@ return {
type='bool', scope={'global'},
redraw={'ui_option'},
varname='p_ttimeout',
- defaults={if_true={vi=true}}
+ defaults={if_true=true}
},
{
full_name='ttimeoutlen', abbreviation='ttm',
@@ -2604,7 +2601,7 @@ return {
type='number', scope={'global'},
redraw={'ui_option'},
varname='p_ttm',
- defaults={if_true={vi=50}}
+ defaults={if_true=50}
},
{
full_name='ttyfast', abbreviation='tf',
@@ -2612,7 +2609,7 @@ return {
type='bool', scope={'global'},
no_mkrc=true,
varname='p_force_on',
- defaults={if_true={vi=true}}
+ defaults={if_true=true}
},
{
full_name='undodir', abbreviation='udir',
@@ -2622,49 +2619,49 @@ return {
secure=true,
expand='nodefault',
varname='p_udir',
- defaults={if_true={vi=''}}
+ defaults={if_true=''}
},
{
full_name='undofile', abbreviation='udf',
short_desc=N_("save undo information in a file"),
type='bool', scope={'buffer'},
varname='p_udf',
- defaults={if_true={vi=false}}
+ defaults={if_true=false}
},
{
full_name='undolevels', abbreviation='ul',
short_desc=N_("maximum number of changes that can be undone"),
type='number', scope={'global', 'buffer'},
varname='p_ul',
- defaults={if_true={vi=1000}}
+ defaults={if_true=1000}
},
{
full_name='undoreload', abbreviation='ur',
short_desc=N_("max nr of lines to save for undo on a buffer reload"),
type='number', scope={'global'},
varname='p_ur',
- defaults={if_true={vi=10000}}
+ defaults={if_true=10000}
},
{
full_name='updatecount', abbreviation='uc',
short_desc=N_("after this many characters flush swap file"),
type='number', scope={'global'},
varname='p_uc',
- defaults={if_true={vi=200}}
+ defaults={if_true=200}
},
{
full_name='updatetime', abbreviation='ut',
short_desc=N_("after this many milliseconds flush swap file"),
type='number', scope={'global'},
varname='p_ut',
- defaults={if_true={vi=4000}}
+ defaults={if_true=4000}
},
{
full_name='varsofttabstop', abbreviation='vsts',
short_desc=N_("list of numbers of spaces that <Tab> uses while editing"),
type='string', list='comma', scope={'buffer'},
varname='p_vsts',
- defaults={if_true={vi=""}}
+ defaults={if_true=""}
},
{
full_name='vartabstop', abbreviation='vts',
@@ -2672,14 +2669,14 @@ return {
type='string', list='comma', scope={'buffer'},
varname='p_vts',
redraw={'current_buffer'},
- defaults={if_true={vi=""}}
+ defaults={if_true=""}
},
{
full_name='verbose', abbreviation='vbs',
short_desc=N_("give informative messages"),
type='number', scope={'global'},
varname='p_verbose',
- defaults={if_true={vi=0}}
+ defaults={if_true=0}
},
{
full_name='verbosefile', abbreviation='vfile',
@@ -2688,7 +2685,7 @@ return {
secure=true,
expand=true,
varname='p_vfile',
- defaults={if_true={vi=""}}
+ defaults={if_true=""}
},
{
full_name='viewdir', abbreviation='vdir',
@@ -2697,7 +2694,7 @@ return {
secure=true,
expand='nodefault',
varname='p_vdir',
- defaults={if_true={vi=''}}
+ defaults={if_true=''}
},
{
full_name='viewoptions', abbreviation='vop',
@@ -2705,7 +2702,7 @@ return {
type='string', list='onecomma', scope={'global'},
deny_duplicates=true,
varname='p_vop',
- defaults={if_true={vi="folds,options,cursor,curdir"}}
+ defaults={if_true="folds,cursor,curdir"}
},
{
-- Alias for "shada".
@@ -2726,42 +2723,42 @@ return {
deny_duplicates=true,
redraw={'curswant'},
varname='p_ve',
- defaults={if_true={vim=""}}
+ defaults={if_true=""}
},
{
full_name='visualbell', abbreviation='vb',
short_desc=N_("use visual bell instead of beeping"),
type='bool', scope={'global'},
varname='p_vb',
- defaults={if_true={vi=false}}
+ defaults={if_true=false}
},
{
full_name='warn',
short_desc=N_("for shell command when buffer was changed"),
type='bool', scope={'global'},
varname='p_warn',
- defaults={if_true={vi=true}}
+ defaults={if_true=true}
},
{
full_name='whichwrap', abbreviation='ww',
short_desc=N_("allow specified keys to cross line boundaries"),
type='string', list='flagscomma', scope={'global'},
varname='p_ww',
- defaults={if_true={vim="b,s"}}
+ defaults={if_true="b,s"}
},
{
full_name='wildchar', abbreviation='wc',
short_desc=N_("command-line character for wildcard expansion"),
type='number', scope={'global'},
varname='p_wc',
- defaults={if_true={vim=imacros('TAB')}}
+ defaults={if_true=imacros('TAB')}
},
{
full_name='wildcharm', abbreviation='wcm',
short_desc=N_("like 'wildchar' but also works when mapped"),
type='number', scope={'global'},
varname='p_wcm',
- defaults={if_true={vi=0}}
+ defaults={if_true=0}
},
{
full_name='wildignore', abbreviation='wig',
@@ -2769,21 +2766,21 @@ return {
type='string', list='onecomma', scope={'global'},
deny_duplicates=true,
varname='p_wig',
- defaults={if_true={vi=""}}
+ defaults={if_true=""}
},
{
full_name='wildignorecase', abbreviation='wic',
short_desc=N_("ignore case when completing file names"),
type='bool', scope={'global'},
varname='p_wic',
- defaults={if_true={vi=false}}
+ defaults={if_true=false}
},
{
full_name='wildmenu', abbreviation='wmnu',
short_desc=N_("use menu for command line completion"),
type='bool', scope={'global'},
varname='p_wmnu',
- defaults={if_true={vim=true}}
+ defaults={if_true=true}
},
{
full_name='wildmode', abbreviation='wim',
@@ -2791,7 +2788,7 @@ return {
type='string', list='onecomma', scope={'global'},
deny_duplicates=false,
varname='p_wim',
- defaults={if_true={vim="full"}}
+ defaults={if_true="full"}
},
{
full_name='wildoptions', abbreviation='wop',
@@ -2799,21 +2796,21 @@ return {
type='string', list='onecomma', scope={'global'},
deny_duplicates=true,
varname='p_wop',
- defaults={if_true={vim='pum,tagfile'}}
+ defaults={if_true='pum,tagfile'}
},
{
full_name='winaltkeys', abbreviation='wak',
short_desc=N_("when the windows system handles ALT keys"),
type='string', scope={'global'},
varname='p_wak',
- defaults={if_true={vi="menu"}}
+ defaults={if_true="menu"}
},
{
full_name='winblend', abbreviation='winbl',
short_desc=N_("Controls transparency level for floating windows"),
type='number', scope={'window'},
redraw={'current_window'},
- defaults={if_true={vi=0}}
+ defaults={if_true=0}
},
{
full_name='winhighlight', abbreviation='winhl',
@@ -2821,105 +2818,105 @@ return {
type='string', scope={'window'},
alloced=true,
redraw={'current_window'},
- defaults={if_true={vi=""}}
+ defaults={if_true=""}
},
{
full_name='window', abbreviation='wi',
short_desc=N_("nr of lines to scroll for CTRL-F and CTRL-B"),
type='number', scope={'global'},
varname='p_window',
- defaults={if_true={vi=0}}
+ defaults={if_true=0}
},
{
full_name='winheight', abbreviation='wh',
short_desc=N_("minimum number of lines for the current window"),
type='number', scope={'global'},
varname='p_wh',
- defaults={if_true={vi=1}}
+ defaults={if_true=1}
},
{
full_name='winfixheight', abbreviation='wfh',
short_desc=N_("keep window height when opening/closing windows"),
type='bool', scope={'window'},
redraw={'statuslines'},
- defaults={if_true={vi=false}}
+ defaults={if_true=false}
},
{
full_name='winfixwidth', abbreviation='wfw',
short_desc=N_("keep window width when opening/closing windows"),
type='bool', scope={'window'},
redraw={'statuslines'},
- defaults={if_true={vi=false}}
+ defaults={if_true=false}
},
{
full_name='winminheight', abbreviation='wmh',
short_desc=N_("minimum number of lines for any window"),
type='number', scope={'global'},
varname='p_wmh',
- defaults={if_true={vi=1}}
+ defaults={if_true=1}
},
{
full_name='winminwidth', abbreviation='wmw',
short_desc=N_("minimal number of columns for any window"),
type='number', scope={'global'},
varname='p_wmw',
- defaults={if_true={vi=1}}
+ defaults={if_true=1}
},
{
full_name='winwidth', abbreviation='wiw',
short_desc=N_("minimal number of columns for current window"),
type='number', scope={'global'},
varname='p_wiw',
- defaults={if_true={vi=20}}
+ defaults={if_true=20}
},
{
full_name='wrap',
short_desc=N_("lines wrap and continue on the next line"),
type='bool', scope={'window'},
redraw={'current_window'},
- defaults={if_true={vi=true}}
+ defaults={if_true=true}
},
{
full_name='wrapmargin', abbreviation='wm',
short_desc=N_("chars from the right where wrapping starts"),
type='number', scope={'buffer'},
varname='p_wm',
- defaults={if_true={vi=0}}
+ defaults={if_true=0}
},
{
full_name='wrapscan', abbreviation='ws',
short_desc=N_("searches wrap around the end of the file"),
type='bool', scope={'global'},
varname='p_ws',
- defaults={if_true={vi=true}}
+ defaults={if_true=true}
},
{
full_name='write',
short_desc=N_("to a file is allowed"),
type='bool', scope={'global'},
varname='p_write',
- defaults={if_true={vi=true}}
+ defaults={if_true=true}
},
{
full_name='writeany', abbreviation='wa',
short_desc=N_("write to file with no need for \"!\" override"),
type='bool', scope={'global'},
varname='p_wa',
- defaults={if_true={vi=false}}
+ defaults={if_true=false}
},
{
full_name='writebackup', abbreviation='wb',
short_desc=N_("make a backup before overwriting a file"),
type='bool', scope={'global'},
varname='p_wb',
- defaults={if_true={vi=true}}
+ defaults={if_true=true}
},
{
full_name='writedelay', abbreviation='wd',
short_desc=N_("delay this many msec for each char (for debug)"),
type='number', scope={'global'},
varname='p_wd',
- defaults={if_true={vi=0}}
+ defaults={if_true=0}
},
}
}
diff --git a/src/nvim/os/env.c b/src/nvim/os/env.c
index 008f5ef63b..92b5e14824 100644
--- a/src/nvim/os/env.c
+++ b/src/nvim/os/env.c
@@ -35,12 +35,11 @@
// Because `uv_os_getenv` requires allocating, we must manage a map to maintain
// the behavior of `os_getenv`.
-static PMap(cstr_t) *envmap;
+static PMap(cstr_t) envmap = MAP_INIT;
static uv_mutex_t mutex;
void env_init(void)
{
- envmap = pmap_new(cstr_t)();
uv_mutex_init(&mutex);
}
@@ -66,8 +65,8 @@ const char *os_getenv(const char *name)
}
uv_mutex_lock(&mutex);
int r = 0;
- if (pmap_has(cstr_t)(envmap, name)
- && !!(e = (char *)pmap_get(cstr_t)(envmap, name))) {
+ if (pmap_has(cstr_t)(&envmap, name)
+ && !!(e = (char *)pmap_get(cstr_t)(&envmap, name))) {
if (e[0] != '\0') {
// Found non-empty cached env var.
// NOTE: This risks incoherence if an in-process library changes the
@@ -75,7 +74,7 @@ const char *os_getenv(const char *name)
// that turns out to be a problem, we can just remove this codepath.
goto end;
}
- pmap_del2(envmap, name);
+ pmap_del2(&envmap, name);
}
e = xmalloc(size);
r = uv_os_getenv(name, e, &size);
@@ -88,7 +87,7 @@ const char *os_getenv(const char *name)
e = NULL;
goto end;
}
- pmap_put(cstr_t)(envmap, xstrdup(name), e);
+ pmap_put(cstr_t)(&envmap, xstrdup(name), e);
end:
// Must do this before ELOG, log.c may call os_setenv.
uv_mutex_unlock(&mutex);
@@ -157,7 +156,7 @@ int os_setenv(const char *name, const char *value, int overwrite)
assert(r != UV_EINVAL);
// Destroy the old map item. Do this AFTER uv_os_setenv(), because `value`
// could be a previous os_getenv() result.
- pmap_del2(envmap, name);
+ pmap_del2(&envmap, name);
// Must do this before ELOG, log.c may call os_setenv.
uv_mutex_unlock(&mutex);
if (r != 0) {
@@ -174,7 +173,7 @@ int os_unsetenv(const char *name)
return -1;
}
uv_mutex_lock(&mutex);
- pmap_del2(envmap, name);
+ pmap_del2(&envmap, name);
int r = uv_os_unsetenv(name);
// Must do this before ELOG, log.c may call os_setenv.
uv_mutex_unlock(&mutex);
diff --git a/src/nvim/os_unix.c b/src/nvim/os_unix.c
index be4bd9709b..44274e8f1d 100644
--- a/src/nvim/os_unix.c
+++ b/src/nvim/os_unix.c
@@ -7,7 +7,6 @@
#include <stdbool.h>
#include <string.h>
-#include "nvim/api/private/handle.h"
#include "nvim/vim.h"
#include "nvim/ascii.h"
#include "nvim/os_unix.h"
diff --git a/src/nvim/runtime.c b/src/nvim/runtime.c
index c3cd210538..4da81f29e3 100644
--- a/src/nvim/runtime.c
+++ b/src/nvim/runtime.c
@@ -403,8 +403,10 @@ theend:
return retval;
}
-/// Load scripts in "plugin" and "ftdetect" directories of the package.
-static int load_pack_plugin(char_u *fname)
+/// Load scripts in "plugin" directory of the package.
+/// For opt packages, also load scripts in "ftdetect" (start packages already
+/// load these from filetype.vim)
+static int load_pack_plugin(bool opt, char_u *fname)
{
static const char *ftpat = "%s/ftdetect/*.vim"; // NOLINT
@@ -421,7 +423,7 @@ static int load_pack_plugin(char_u *fname)
// If runtime/filetype.vim wasn't loaded yet, the scripts will be
// found when it loads.
- if (eval_to_number(cmd) > 0) {
+ if (opt && eval_to_number(cmd) > 0) {
do_cmdline_cmd("augroup filetypedetect");
vim_snprintf((char *)pat, len, ftpat, ffname);
source_all_matches(pat);
@@ -441,7 +443,7 @@ static int APP_ADD_DIR;
static int APP_LOAD;
static int APP_BOTH;
-static void add_pack_plugin(char_u *fname, void *cookie)
+static void add_pack_plugin(bool opt, char_u *fname, void *cookie)
{
if (cookie != &APP_LOAD) {
char *buf = xmalloc(MAXPATHL);
@@ -465,17 +467,27 @@ static void add_pack_plugin(char_u *fname, void *cookie)
}
if (cookie != &APP_ADD_DIR) {
- load_pack_plugin(fname);
+ load_pack_plugin(opt, fname);
}
}
+static void add_start_pack_plugin(char_u *fname, void *cookie)
+{
+ add_pack_plugin(false, fname, cookie);
+}
+
+static void add_opt_pack_plugin(char_u *fname, void *cookie)
+{
+ add_pack_plugin(true, fname, cookie);
+}
+
/// Add all packages in the "start" directory to 'runtimepath'.
void add_pack_start_dirs(void)
{
do_in_path(p_pp, (char_u *)"pack/*/start/*", DIP_ALL + DIP_DIR, // NOLINT
- add_pack_plugin, &APP_ADD_DIR);
+ add_start_pack_plugin, &APP_ADD_DIR);
do_in_path(p_pp, (char_u *)"start/*", DIP_ALL + DIP_DIR, // NOLINT
- add_pack_plugin, &APP_ADD_DIR);
+ add_start_pack_plugin, &APP_ADD_DIR);
}
/// Load plugins from all packages in the "start" directory.
@@ -483,9 +495,9 @@ void load_start_packages(void)
{
did_source_packages = true;
do_in_path(p_pp, (char_u *)"pack/*/start/*", DIP_ALL + DIP_DIR, // NOLINT
- add_pack_plugin, &APP_LOAD);
+ add_start_pack_plugin, &APP_LOAD);
do_in_path(p_pp, (char_u *)"start/*", DIP_ALL + DIP_DIR, // NOLINT
- add_pack_plugin, &APP_LOAD);
+ add_start_pack_plugin, &APP_LOAD);
}
// ":packloadall"
@@ -522,7 +534,8 @@ void ex_packadd(exarg_T *eap)
res = do_in_path(p_pp, (char_u *)pat,
DIP_ALL + DIP_DIR
+ (round == 2 && res == FAIL ? DIP_ERR : 0),
- add_pack_plugin, eap->forceit ? &APP_ADD_DIR : &APP_BOTH);
+ round == 1 ? add_start_pack_plugin : add_opt_pack_plugin,
+ eap->forceit ? &APP_ADD_DIR : &APP_BOTH);
xfree(pat);
}
}
diff --git a/src/nvim/screen.c b/src/nvim/screen.c
index 38ed2816ba..208ae3488f 100644
--- a/src/nvim/screen.c
+++ b/src/nvim/screen.c
@@ -324,8 +324,7 @@ void update_curbuf(int type)
/// @param type set to a NOT_VALID to force redraw of entire screen
int update_screen(int type)
{
- static int did_intro = FALSE;
- int did_one;
+ static bool did_intro = false;
// Don't do anything if the screen structures are (not yet) valid.
// A VimResized autocmd can invoke redrawing in the middle of a resize,
@@ -578,7 +577,7 @@ int update_screen(int type)
* Go from top to bottom through the windows, redrawing the ones that need
* it.
*/
- did_one = FALSE;
+ bool did_one = false;
search_hl.rm.regprog = NULL;
@@ -597,7 +596,7 @@ int update_screen(int type)
if (wp->w_redr_type != 0) {
if (!did_one) {
- did_one = TRUE;
+ did_one = true;
start_search_hl();
}
win_update(wp, &providers);
@@ -635,7 +634,7 @@ int update_screen(int type)
/* May put up an introductory message when not editing a file */
if (!did_intro)
maybe_intro_message();
- did_intro = TRUE;
+ did_intro = true;
for (size_t i = 0; i < kv_size(providers); i++) {
DecorProvider *p = kv_A(providers, i);
@@ -747,8 +746,7 @@ static void win_update(win_T *wp, Providers *providers)
updating. 0 when no mid area updating. */
int bot_start = 999; /* first row of the bot area that needs
updating. 999 when no bot area updating */
- int scrolled_down = FALSE; /* TRUE when scrolled down when
- w_topline got smaller a bit */
+ bool scrolled_down = false; // true when scrolled down when w_topline got smaller a bit
bool top_to_mod = false; // redraw above mod_top
int row; /* current window row to display */
@@ -756,8 +754,8 @@ static void win_update(win_T *wp, Providers *providers)
int idx; /* current index in w_lines[] */
int srow; /* starting row of the current line */
- int eof = FALSE; /* if TRUE, we hit the end of the file */
- int didline = FALSE; /* if TRUE, we finished the last line */
+ bool eof = false; // if true, we hit the end of the file
+ bool didline = false; // if true, we finished the last line
int i;
long j;
static bool recursive = false; // being called recursively
@@ -1339,7 +1337,7 @@ static void win_update(win_T *wp, Providers *providers)
/* stop updating when hit the end of the file */
if (lnum > buf->b_ml.ml_line_count) {
- eof = TRUE;
+ eof = true;
break;
}
@@ -1596,7 +1594,7 @@ static void win_update(win_T *wp, Providers *providers)
}
if (lnum > buf->b_ml.ml_line_count) {
- eof = TRUE;
+ eof = true;
break;
}
}
@@ -1841,10 +1839,10 @@ static void win_draw_end(win_T *wp, int c1, int c2, bool draw_margin, int row,
}
-/*
- * Advance **color_cols and return TRUE when there are columns to draw.
- */
-static int advance_color_col(int vcol, int **color_cols)
+/// Advance **color_cols
+///
+/// @return true when there are columns to draw.
+static bool advance_color_col(int vcol, int **color_cols)
{
while (**color_cols >= 0 && vcol > **color_cols)
++*color_cols;
@@ -2062,7 +2060,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
int has_syntax = FALSE; /* this buffer has syntax highl. */
int save_did_emsg;
int eol_hl_off = 0; // 1 if highlighted char after EOL
- int draw_color_col = false; // highlight colorcolumn
+ bool draw_color_col = false; // highlight colorcolumn
int *color_cols = NULL; // pointer to according columns array
bool has_spell = false; // this buffer has spell checking
# define SPWORDLEN 150
@@ -2139,7 +2137,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
int syntax_seqnr = 0;
int prev_syntax_id = 0;
int conceal_attr = win_hl_attr(wp, HLF_CONCEAL);
- int is_concealing = false;
+ bool is_concealing = false;
int boguscols = 0; ///< nonexistent columns added to
///< force wrapping
int vcol_off = 0; ///< offset for concealed characters
@@ -2381,13 +2379,12 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
&& wp->w_p_culopt_flags != CULOPT_NBR) {
cul_screenline = (wp->w_p_wrap
&& (wp->w_p_culopt_flags & CULOPT_SCRLINE));
- cul_attr = win_hl_attr(wp, HLF_CUL);
- HlAttrs ae = syn_attr2entry(cul_attr);
-
- // We make a compromise here (#7383):
- // * low-priority CursorLine if fg is not set
- // * high-priority ("same as Vim" priority) CursorLine if fg is set
if (!cul_screenline) {
+ cul_attr = win_hl_attr(wp, HLF_CUL);
+ HlAttrs ae = syn_attr2entry(cul_attr);
+ // We make a compromise here (#7383):
+ // * low-priority CursorLine if fg is not set
+ // * high-priority ("same as Vim" priority) CursorLine if fg is set
if (ae.rgb_fg_color == -1 && ae.cterm_fg_color == 0) {
line_attr_lowprio = cul_attr;
} else {
@@ -2399,7 +2396,6 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
}
}
} else {
- cul_attr = 0;
margin_columns_win(wp, &left_curline_col, &right_curline_col);
}
area_highlighting = true;
@@ -2432,7 +2428,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
line_attr_lowprio_save = line_attr_lowprio;
}
- line = ml_get_buf(wp->w_buffer, lnum, FALSE);
+ line = ml_get_buf(wp->w_buffer, lnum, false);
ptr = line;
if (has_spell && !number_only) {
@@ -2564,8 +2560,8 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
wp->w_cursor.col = linecol;
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, FALSE);
+ // spell_move_to() may call ml_get() and make "line" invalid
+ line = ml_get_buf(wp->w_buffer, lnum, false);
ptr = line + linecol;
if (len == 0 || (int)wp->w_cursor.col > ptr - line) {
@@ -2700,6 +2696,12 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
// Skip this quickly when working on the text.
if (draw_state != WL_LINE) {
+ if (cul_screenline) {
+ cul_attr = 0;
+ line_attr = line_attr_save;
+ line_attr_lowprio = line_attr_lowprio_save;
+ }
+
if (draw_state == WL_CMDLINE - 1 && n_extra == 0) {
draw_state = WL_CMDLINE;
if (cmdwin_type != 0 && wp == curwin) {
@@ -2855,9 +2857,6 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
if (diff_hlf != (hlf_T)0) {
char_attr = win_hl_attr(wp, diff_hlf);
- if (cul_attr) {
- char_attr = hl_combine_attr(char_attr, cul_attr);
- }
}
p_extra = NULL;
c_extra = ' ';
@@ -2943,21 +2942,20 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
}
}
- if (cul_screenline) {
- if (draw_state == WL_LINE
- && vcol >= left_curline_col
- && vcol < right_curline_col) {
- cul_attr = win_hl_attr(wp, HLF_CUL);
- HlAttrs ae = syn_attr2entry(cul_attr);
- if (ae.rgb_fg_color == -1 && ae.cterm_fg_color == 0) {
- line_attr_lowprio = cul_attr;
+ if (cul_screenline && draw_state == WL_LINE
+ && vcol >= left_curline_col
+ && vcol < right_curline_col) {
+ cul_attr = win_hl_attr(wp, HLF_CUL);
+ HlAttrs ae = syn_attr2entry(cul_attr);
+ if (ae.rgb_fg_color == -1 && ae.cterm_fg_color == 0) {
+ line_attr_lowprio = cul_attr;
+ } else {
+ if (!(State & INSERT) && bt_quickfix(wp->w_buffer)
+ && qf_current_entry(wp) == lnum) {
+ line_attr = hl_combine_attr(cul_attr, line_attr);
} else {
line_attr = cul_attr;
}
- } else {
- cul_attr = 0;
- line_attr = line_attr_save;
- line_attr_lowprio = line_attr_lowprio_save;
}
}
@@ -3095,9 +3093,9 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
shl == &search_hl ? NULL : cur);
pos_inprogress = !(cur == NULL || cur->pos.cur == 0);
- /* Need to get the line again, a multi-line regexp
- * may have made it invalid. */
- line = ml_get_buf(wp->w_buffer, lnum, FALSE);
+ // Need to get the line again, a multi-line regexp
+ // may have made it invalid.
+ line = ml_get_buf(wp->w_buffer, lnum, false);
ptr = line + v;
if (shl->lnum == lnum) {
@@ -3408,9 +3406,9 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
} else
did_emsg = save_did_emsg;
- /* Need to get the line again, a multi-line regexp may
- * have made it invalid. */
- line = ml_get_buf(wp->w_buffer, lnum, FALSE);
+ // Need to get the line again, a multi-line regexp may
+ // have made it invalid.
+ line = ml_get_buf(wp->w_buffer, lnum, false);
ptr = line + v;
if (!attr_pri) {
@@ -3834,7 +3832,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
n_extra = 0;
n_attr = 0;
} else if (n_skip == 0) {
- is_concealing = TRUE;
+ is_concealing = true;
n_skip = 1;
}
mb_c = c;
@@ -3847,7 +3845,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
}
} else {
prev_syntax_id = 0;
- is_concealing = FALSE;
+ is_concealing = false;
}
if (n_skip > 0 && did_decrement_ptr) {
@@ -4953,12 +4951,12 @@ win_redr_status_matches (
int fillchar;
int attr;
int i;
- int highlight = TRUE;
+ bool highlight = true;
char_u *selstart = NULL;
int selstart_col = 0;
char_u *selend = NULL;
static int first_match = 0;
- int add_left = FALSE;
+ bool add_left = false;
char_u *s;
int emenu;
int l;
@@ -4970,7 +4968,7 @@ win_redr_status_matches (
if (match == -1) { /* don't show match but original text */
match = 0;
- highlight = FALSE;
+ highlight = false;
}
/* count 1 for the ending ">" */
clen = status_match_len(xp, L_MATCH(match)) + 3;
@@ -4979,7 +4977,7 @@ win_redr_status_matches (
else if (match < first_match) {
/* jumping left, as far as we can go */
first_match = match;
- add_left = TRUE;
+ add_left = true;
} else {
/* check if match fits on the screen */
for (i = first_match; i < match; ++i)
@@ -4997,8 +4995,9 @@ win_redr_status_matches (
break;
}
}
- if (i == num_matches)
- add_left = TRUE;
+ if (i == num_matches) {
+ add_left = true;
+ }
}
}
if (add_left)
@@ -5090,7 +5089,7 @@ win_redr_status_matches (
save_p_wmh = p_wmh;
p_ls = 2;
p_wmh = 0;
- last_status(FALSE);
+ last_status(false);
}
wild_menu_showing = WM_SHOWN;
}
@@ -5215,7 +5214,7 @@ static void win_redr_status(win_T *wp)
grid_puts(&default_grid, NameBuff, row,
(int)(this_ru_col - STRLEN(NameBuff) - 1), attr);
- win_redr_ruler(wp, TRUE);
+ win_redr_ruler(wp, true);
}
/*
@@ -5238,14 +5237,14 @@ static void win_redr_status(win_T *wp)
*/
static void redraw_custom_statusline(win_T *wp)
{
- static int entered = false;
+ static bool entered = false;
int saved_did_emsg = did_emsg;
/* When called recursively return. This can happen when the statusline
* contains an expression that triggers a redraw. */
if (entered)
return;
- entered = TRUE;
+ entered = true;
did_emsg = false;
win_redr_custom(wp, false);
@@ -5261,12 +5260,11 @@ static void redraw_custom_statusline(win_T *wp)
entered = false;
}
-/*
- * Return TRUE if the status line of window "wp" is connected to the status
- * line of the window right of it. If not, then it's a vertical separator.
- * Only call if (wp->w_vsep_width != 0).
- */
-int stl_connected(win_T *wp)
+/// Only call if (wp->w_vsep_width != 0).
+///
+/// @return true if the status line of window "wp" is connected to the status
+/// line of the window right of it. If not, then it's a vertical separator.
+bool stl_connected(win_T *wp)
{
frame_T *fr;
@@ -5276,30 +5274,28 @@ int stl_connected(win_T *wp)
if (fr->fr_next != NULL)
break;
} else {
- if (fr->fr_next != NULL)
- return TRUE;
+ if (fr->fr_next != NULL) {
+ return true;
+ }
}
fr = fr->fr_parent;
}
- return FALSE;
+ return false;
}
-/*
- * Get the value to show for the language mappings, active 'keymap'.
- */
-int
-get_keymap_str (
- win_T *wp,
- char_u *fmt, // format string containing one %s item
- char_u *buf, // buffer for the result
- int len // length of buffer
-)
+/// Get the value to show for the language mappings, active 'keymap'.
+///
+/// @param fmt format string containing one %s item
+/// @param buf buffer for the result
+/// @param len length of buffer
+bool get_keymap_str(win_T *wp, char_u *fmt, char_u *buf, int len)
{
char_u *p;
- if (wp->w_buffer->b_p_iminsert != B_IMODE_LMAP)
- return FALSE;
+ if (wp->w_buffer->b_p_iminsert != B_IMODE_LMAP) {
+ return false;
+ }
{
buf_T *old_curbuf = curbuf;
@@ -5339,7 +5335,7 @@ win_redr_custom (
bool draw_ruler
)
{
- static int entered = FALSE;
+ static bool entered = false;
int attr;
int curattr;
int row;
@@ -5365,7 +5361,7 @@ win_redr_custom (
* Avoid trouble by not allowing recursion. */
if (entered)
return;
- entered = TRUE;
+ entered = true;
/* setup environment for the task at hand */
if (wp == NULL) {
@@ -5500,7 +5496,7 @@ win_redr_custom (
}
theend:
- entered = FALSE;
+ entered = false;
}
static void win_redr_border(win_T *wp)
@@ -6065,7 +6061,7 @@ next_search_hl (
char_u *ml;
matchcol = shl->rm.startpos[0].col;
- ml = ml_get_buf(shl->buf, lnum, FALSE) + matchcol;
+ ml = ml_get_buf(shl->buf, lnum, false) + matchcol;
if (*ml == NUL) {
++matchcol;
shl->lnum = 0;
@@ -7333,11 +7329,10 @@ int messaging(void)
return !(p_lz && char_avail() && !KeyTyped);
}
-/*
- * Show current status info in ruler and various other places
- * If always is FALSE, only show ruler if position has changed.
- */
-void showruler(int always)
+/// Show current status info in ruler and various other places
+///
+/// @param always if false, only show ruler if position has changed.
+void showruler(bool always)
{
if (!always && !redrawing())
return;
@@ -7357,7 +7352,7 @@ void showruler(int always)
draw_tabline();
}
-static void win_redr_ruler(win_T *wp, int always)
+static void win_redr_ruler(win_T *wp, bool always)
{
static bool did_show_ext_ruler = false;
@@ -7619,11 +7614,11 @@ static void margin_columns_win(win_T *wp, int *left_col, int *right_col)
/// Set dimensions of the Nvim application "shell".
void screen_resize(int width, int height)
{
- static int busy = FALSE;
+ static bool recursive = false;
// Avoid recursiveness, can happen when setting the window size causes
// another window-changed signal.
- if (updating_screen || busy) {
+ if (updating_screen || recursive) {
return;
}
@@ -7643,7 +7638,7 @@ void screen_resize(int width, int height)
if (curwin->w_buffer == NULL)
return;
- ++busy;
+ recursive = true;
Rows = height;
Columns = width;
@@ -7662,7 +7657,7 @@ void screen_resize(int width, int height)
/* The window layout used to be adjusted here, but it now happens in
* screenalloc() (also invoked from screenclear()). That is because the
- * "busy" check above may skip this, but not screenalloc(). */
+ * "recursive" check above may skip this, but not screenalloc(). */
if (State != ASKMORE && State != EXTERNCMD && State != CONFIRM) {
screenclear();
@@ -7694,8 +7689,9 @@ void screen_resize(int width, int height)
ui_comp_set_screen_valid(true);
repeat_message();
} else {
- if (curwin->w_p_scb)
- do_check_scrollbind(TRUE);
+ if (curwin->w_p_scb) {
+ do_check_scrollbind(true);
+ }
if (State & CMDLINE) {
redraw_popupmenu = false;
update_screen(NOT_VALID);
@@ -7720,7 +7716,7 @@ void screen_resize(int width, int height)
}
ui_flush();
}
- busy--;
+ recursive = false;
}
/// Check if the new Nvim application "shell" dimensions are valid.
@@ -7778,4 +7774,3 @@ win_T *get_win_by_grid_handle(handle_T handle)
return NULL;
}
-
diff --git a/src/nvim/search.c b/src/nvim/search.c
index e5d545b185..b0ee41b245 100644
--- a/src/nvim/search.c
+++ b/src/nvim/search.c
@@ -98,7 +98,7 @@ static int saved_spats_last_idx = 0;
static bool saved_spats_no_hlsearch = false;
static char_u *mr_pattern = NULL; // pattern used by search_regcomp()
-static int mr_pattern_alloced = false; // mr_pattern was allocated
+static bool mr_pattern_alloced = false; // mr_pattern was allocated
/*
* Type used by find_pattern_in_path() to remember which included files have
@@ -159,19 +159,21 @@ search_regcomp(
pat = spats[i].pat;
magic = spats[i].magic;
no_smartcase = spats[i].no_scs;
- } else if (options & SEARCH_HIS) /* put new pattern in history */
- add_to_history(HIST_SEARCH, pat, TRUE, NUL);
+ } else if (options & SEARCH_HIS) { // put new pattern in history
+ add_to_history(HIST_SEARCH, pat, true, NUL);
+ }
if (mr_pattern_alloced) {
xfree(mr_pattern);
- mr_pattern_alloced = FALSE;
+ mr_pattern_alloced = false;
}
if (curwin->w_p_rl && *curwin->w_p_rlc == 's') {
mr_pattern = reverse_text(pat);
- mr_pattern_alloced = TRUE;
- } else
+ mr_pattern_alloced = true;
+ } else {
mr_pattern = pat;
+ }
/*
* Save the currently used pattern in the appropriate place,
@@ -293,7 +295,7 @@ void free_search_patterns(void)
if (mr_pattern_alloced) {
xfree(mr_pattern);
- mr_pattern_alloced = FALSE;
+ mr_pattern_alloced = false;
mr_pattern = NULL;
}
}
@@ -556,12 +558,12 @@ int searchit(
int at_first_line;
int extra_col;
int start_char_len;
- int match_ok;
+ bool match_ok;
long nmatched;
int submatch = 0;
bool first_match = true;
int save_called_emsg = called_emsg;
- int break_loop = false;
+ bool break_loop = false;
linenr_T stop_lnum = 0; // stop after this line number when != 0
proftime_T *tm = NULL; // timeout limit or NULL
int *timed_out = NULL; // set when timed out or NULL
@@ -659,11 +661,12 @@ int searchit(
matchpos = regmatch.startpos[0];
endpos = regmatch.endpos[0];
submatch = first_submatch(&regmatch);
- /* "lnum" may be past end of buffer for "\n\zs". */
- if (lnum + matchpos.lnum > buf->b_ml.ml_line_count)
+ // "lnum" may be past end of buffer for "\n\zs".
+ if (lnum + matchpos.lnum > buf->b_ml.ml_line_count) {
ptr = (char_u *)"";
- else
- ptr = ml_get_buf(buf, lnum + matchpos.lnum, FALSE);
+ } else {
+ ptr = ml_get_buf(buf, lnum + matchpos.lnum, false);
+ }
/*
* Forward search in the first line: match should be after
@@ -671,14 +674,12 @@ int searchit(
* match (this is vi compatible) or on the next char.
*/
if (dir == FORWARD && at_first_line) {
- match_ok = TRUE;
- /*
- * When the match starts in a next line it's certainly
- * past the start position.
- * When match lands on a NUL the cursor will be put
- * one back afterwards, compare with that position,
- * otherwise "/$" will get stuck on end of line.
- */
+ match_ok = true;
+ // When the match starts in a next line it's certainly
+ // past the start position.
+ // When match lands on a NUL the cursor will be put
+ // one back afterwards, compare with that position,
+ // otherwise "/$" will get stuck on end of line.
while (matchpos.lnum == 0
&& (((options & SEARCH_END) && first_match)
? (nmatched == 1
@@ -696,7 +697,7 @@ int searchit(
if (nmatched > 1) {
/* end is in next line, thus no match in
* this line */
- match_ok = FALSE;
+ match_ok = false;
break;
}
matchcol = endpos.col;
@@ -750,7 +751,7 @@ int searchit(
* When putting the new cursor at the end, compare
* relative to the end of the match.
*/
- match_ok = FALSE;
+ match_ok = false;
for (;; ) {
/* Remember a position that is before the start
* position, we use it if it's the last match in
@@ -842,10 +843,9 @@ int searchit(
pos->lnum = lnum + endpos.lnum;
pos->col = endpos.col;
if (endpos.col == 0) {
- if (pos->lnum > 1) { /* just in case */
- --pos->lnum;
- pos->col = (colnr_T)STRLEN(ml_get_buf(buf,
- pos->lnum, FALSE));
+ if (pos->lnum > 1) { // just in case
+ pos->lnum--;
+ pos->col = (colnr_T)STRLEN(ml_get_buf(buf, pos->lnum, false));
}
} else {
pos->col--;
@@ -888,7 +888,7 @@ int searchit(
if ((options & SEARCH_PEEK)
&& ((lnum - pos->lnum) & 0x3f) == 0
&& char_avail()) {
- break_loop = TRUE;
+ break_loop = true;
break;
}
@@ -962,9 +962,10 @@ int searchit(
/* A pattern like "\n\zs" may go past the last line. */
if (pos->lnum > buf->b_ml.ml_line_count) {
pos->lnum = buf->b_ml.ml_line_count;
- pos->col = (int)STRLEN(ml_get_buf(buf, pos->lnum, FALSE));
- if (pos->col > 0)
- --pos->col;
+ pos->col = (int)STRLEN(ml_get_buf(buf, pos->lnum, false));
+ if (pos->col > 0) {
+ pos->col--;
+ }
}
return submatch + 1;
@@ -1465,7 +1466,7 @@ int search_for_exact_line(buf_T *buf, pos_T *pos, Direction dir, char_u *pat)
break;
if (start == 0)
start = pos->lnum;
- ptr = ml_get_buf(buf, pos->lnum, FALSE);
+ ptr = ml_get_buf(buf, pos->lnum, false);
p = skipwhite(ptr);
pos->col = (colnr_T) (p - ptr);
@@ -1506,7 +1507,7 @@ int searchc(cmdarg_T *cap, int t_cmd)
int col;
char_u *p;
int len;
- int stop = TRUE;
+ bool stop = true;
if (c != NUL) { /* normal search: remember args for repeat */
if (!KeyStuffed) { /* don't remember when redoing */
@@ -1539,8 +1540,9 @@ int searchc(cmdarg_T *cap, int t_cmd)
/* Force a move of at least one char, so ";" and "," will move the
* cursor, even if the cursor is right in front of char we are looking
* at. */
- if (vim_strchr(p_cpo, CPO_SCOLON) == NULL && count == 1 && t_cmd)
- stop = FALSE;
+ if (vim_strchr(p_cpo, CPO_SCOLON) == NULL && count == 1 && t_cmd) {
+ stop = false;
+ }
}
if (dir == BACKWARD)
@@ -1620,7 +1622,7 @@ static bool check_prevcol(char_u *linep, int col, int ch, int *prevcol)
if (prevcol) {
*prevcol = col;
}
- return (col >= 0 && linep[col] == ch) ? true : false;
+ return col >= 0 && linep[col] == ch;
}
/*
@@ -2257,22 +2259,25 @@ static int check_linecomment(const char_u *line)
const char_u *p = line; // scan from start
// skip Lispish one-line comments
if (curbuf->b_p_lisp) {
- if (vim_strchr(p, ';') != NULL) { /* there may be comments */
- int in_str = FALSE; /* inside of string */
+ if (vim_strchr(p, ';') != NULL) { // there may be comments
+ bool in_str = false; // inside of string
while ((p = vim_strpbrk(p, (char_u *)"\";")) != NULL) {
if (*p == '"') {
if (in_str) {
- if (*(p - 1) != '\\') /* skip escaped quote */
- in_str = FALSE;
+ if (*(p - 1) != '\\') { // skip escaped quote
+ in_str = false;
+ }
} else if (p == line || ((p - line) >= 2
- /* skip #\" form */
- && *(p - 1) != '\\' && *(p - 2) != '#'))
- in_str = TRUE;
+ // skip #\" form
+ && *(p - 1) != '\\' && *(p - 2) != '#')) {
+ in_str = true;
+ }
} else if (!in_str && ((p - line) < 2
- || (*(p - 1) != '\\' && *(p - 2) != '#')))
- break; /* found! */
- ++p;
+ || (*(p - 1) != '\\' && *(p - 2) != '#'))) {
+ break; // found!
+ }
+ p++;
}
} else
p = NULL;
@@ -2855,17 +2860,13 @@ finished:
return OK;
}
-/*
- * Move back to the end of the word.
- *
- * Returns FAIL if start of the file was reached.
- */
-int
-bckend_word(
- long count,
- int bigword, /* TRUE for "B" */
- int eol /* TRUE: stop at end of line. */
-)
+/// Move back to the end of the word.
+///
+/// @param bigword TRUE for "B"
+/// @param eol if true, then stop at end of line.
+///
+/// @return FAIL if start of the file was reached.
+int bckend_word(long count, int bigword, bool eol)
{
int sclass; /* starting class */
int i;
@@ -2903,16 +2904,17 @@ bckend_word(
return OK;
}
-/*
- * Skip a row of characters of the same class.
- * Return TRUE when end-of-file reached, FALSE otherwise.
- */
-static int skip_chars(int cclass, int dir)
+/// Skip a row of characters of the same class.
+///
+/// @return true when end-of-file reached, false otherwise.
+static bool skip_chars(int cclass, int dir)
{
- while (cls() == cclass)
- if ((dir == FORWARD ? inc_cursor() : dec_cursor()) == -1)
- return TRUE;
- return FALSE;
+ while (cls() == cclass) {
+ if ((dir == FORWARD ? inc_cursor() : dec_cursor()) == -1) {
+ return true;
+ }
+ }
+ return false;
}
/*
@@ -2947,14 +2949,10 @@ static void find_first_blank(pos_T *posp)
}
}
-/*
- * Skip count/2 sentences and count/2 separating white spaces.
- */
-static void
-findsent_forward(
- long count,
- int at_start_sent /* cursor is at start of sentence */
-)
+/// Skip count/2 sentences and count/2 separating white spaces.
+///
+/// @param at_start_sent cursor is at start of sentence
+static void findsent_forward(long count, bool at_start_sent)
{
while (count--) {
findsent(FORWARD, 1L);
@@ -3053,8 +3051,9 @@ current_word(
if (bck_word(1L, bigword, TRUE) == FAIL)
return FAIL;
} else {
- if (bckend_word(1L, bigword, TRUE) == FAIL)
+ if (bckend_word(1L, bigword, true) == FAIL) {
return FAIL;
+ }
(void)incl(&curwin->w_cursor);
}
} else {
@@ -3126,9 +3125,9 @@ int current_sent(oparg_T *oap, long count, int include)
{
pos_T start_pos;
pos_T pos;
- int start_blank;
+ bool start_blank;
int c;
- int at_start_sent;
+ bool at_start_sent;
long ncount;
start_pos = curwin->w_cursor;
@@ -3148,23 +3147,24 @@ extend:
* - in a sentence or just after it
* - at the start of a sentence
*/
- at_start_sent = TRUE;
+ at_start_sent = true;
decl(&pos);
while (lt(pos, curwin->w_cursor)) {
c = gchar_pos(&pos);
if (!ascii_iswhite(c)) {
- at_start_sent = FALSE;
+ at_start_sent = false;
break;
}
incl(&pos);
}
if (!at_start_sent) {
findsent(BACKWARD, 1L);
- if (equalpos(curwin->w_cursor, start_pos))
- at_start_sent = TRUE; /* exactly at start of sentence */
- else
- /* inside a sentence, go to its end (start of next) */
+ if (equalpos(curwin->w_cursor, start_pos)) {
+ at_start_sent = true; // exactly at start of sentence
+ } else {
+ // inside a sentence, go to its end (start of next)
findsent(FORWARD, 1L);
+ }
}
if (include) /* "as" gets twice as much as "is" */
count *= 2;
@@ -3185,13 +3185,13 @@ extend:
* - in a sentence
*/
incl(&pos);
- at_start_sent = TRUE;
- if (!equalpos(pos, curwin->w_cursor)) { /* not just before a sentence */
- at_start_sent = FALSE;
+ at_start_sent = true;
+ if (!equalpos(pos, curwin->w_cursor)) { // not just before a sentence
+ at_start_sent = false;
while (lt(pos, curwin->w_cursor)) {
c = gchar_pos(&pos);
if (!ascii_iswhite(c)) {
- at_start_sent = TRUE;
+ at_start_sent = true;
break;
}
incl(&pos);
@@ -3218,10 +3218,10 @@ extend:
while (c = gchar_pos(&pos), ascii_iswhite(c))
incl(&pos);
if (equalpos(pos, curwin->w_cursor)) {
- start_blank = TRUE;
- find_first_blank(&start_pos); /* go back to first blank */
+ start_blank = true;
+ find_first_blank(&start_pos); // go back to first blank
} else {
- start_blank = FALSE;
+ start_blank = false;
findsent(BACKWARD, 1L);
start_pos = curwin->w_cursor;
}
@@ -3232,10 +3232,11 @@ extend:
if (start_blank)
--ncount;
}
- if (ncount > 0)
- findsent_forward(ncount, TRUE);
- else
+ if (ncount > 0) {
+ findsent_forward(ncount, true);
+ } else {
decl(&curwin->w_cursor);
+ }
if (include) {
/*
@@ -3293,7 +3294,7 @@ current_block(
pos_T *end_pos;
pos_T old_start, old_end;
char_u *save_cpo;
- int sol = FALSE; /* '{' at start of line */
+ bool sol = false; // '{' at start of line
old_pos = curwin->w_cursor;
old_end = curwin->w_cursor; /* remember where we started */
@@ -3351,7 +3352,7 @@ current_block(
sol = (curwin->w_cursor.col == 0);
decl(&curwin->w_cursor);
while (inindent(1)) {
- sol = TRUE;
+ sol = true;
if (decl(&curwin->w_cursor) != 0) {
break;
}
@@ -3410,11 +3411,10 @@ current_block(
}
-/*
- * Return TRUE if the cursor is on a "<aaa>" tag. Ignore "<aaa/>".
- * When "end_tag" is TRUE return TRUE if the cursor is on "</aaa>".
- */
-static int in_html_tag(int end_tag)
+/// @param end_tag when true, return true if the cursor is on "</aaa>".
+///
+/// @return true if the cursor is on a "<aaa>" tag. Ignore "<aaa/>".
+static bool in_html_tag(bool end_tag)
{
char_u *line = get_cursor_line_ptr();
char_u *p;
@@ -3444,14 +3444,16 @@ static int in_html_tag(int end_tag)
return *p == '/';
}
- /* check that there is no '/' after the '<' */
- if (*p == '/')
- return FALSE;
+ // check that there is no '/' after the '<'
+ if (*p == '/') {
+ return false;
+ }
/* check that the matching '>' is not preceded by '/' */
for (;; ) {
- if (inc(&pos) < 0)
- return FALSE;
+ if (inc(&pos) < 0) {
+ return false;
+ }
c = *ml_get_pos(&pos);
if (c == '>')
break;
@@ -3502,16 +3504,20 @@ current_tagblock(
if (inc_cursor() != 0)
break;
- if (in_html_tag(FALSE)) {
- /* cursor on start tag, move to its '>' */
- while (*get_cursor_pos_ptr() != '>')
- if (inc_cursor() < 0)
+ if (in_html_tag(false)) {
+ // cursor on start tag, move to its '>'
+ while (*get_cursor_pos_ptr() != '>') {
+ if (inc_cursor() < 0) {
break;
- } else if (in_html_tag(TRUE)) {
- /* cursor on end tag, move to just before it */
- while (*get_cursor_pos_ptr() != '<')
- if (dec_cursor() < 0)
+ }
+ }
+ } else if (in_html_tag(true)) {
+ // cursor on end tag, move to just before it
+ while (*get_cursor_pos_ptr() != '<') {
+ if (dec_cursor() < 0) {
break;
+ }
+ }
dec_cursor();
old_end = curwin->w_cursor;
}
@@ -4667,7 +4673,7 @@ find_pattern_in_path(
char_u *line;
char_u *p;
char_u save_char;
- int define_matched;
+ bool define_matched;
regmatch_T regmatch;
regmatch_T incl_regmatch;
regmatch_T def_regmatch;
@@ -4904,7 +4910,7 @@ find_pattern_in_path(
*/
p = line;
search_line:
- define_matched = FALSE;
+ define_matched = false;
if (def_regmatch.regprog != NULL
&& vim_regexec(&def_regmatch, line, (colnr_T)0)) {
/*
@@ -4915,7 +4921,7 @@ search_line:
p = def_regmatch.endp[0];
while (*p && !vim_iswordc(*p))
p++;
- define_matched = TRUE;
+ define_matched = true;
}
/*
diff --git a/src/nvim/spell.c b/src/nvim/spell.c
index 28276884b0..610a359141 100644
--- a/src/nvim/spell.c
+++ b/src/nvim/spell.c
@@ -1399,7 +1399,7 @@ spell_move_to (
clearpos(&found_pos);
while (!got_int) {
- line = ml_get_buf(wp->w_buffer, lnum, FALSE);
+ line = ml_get_buf(wp->w_buffer, lnum, false);
len = STRLEN(line);
if (buflen < len + MAXWLEN + 2) {
@@ -1425,7 +1425,7 @@ spell_move_to (
// Need to get the line again, may have looked at the previous
// one.
- line = ml_get_buf(wp->w_buffer, lnum, FALSE);
+ line = ml_get_buf(wp->w_buffer, lnum, false);
}
// Copy the line into "buf" and append the start of the next line if
@@ -1433,7 +1433,7 @@ spell_move_to (
STRCPY(buf, line);
if (lnum < wp->w_buffer->b_ml.ml_line_count)
spell_cat_line(buf + STRLEN(buf),
- ml_get_buf(wp->w_buffer, lnum + 1, FALSE),
+ ml_get_buf(wp->w_buffer, lnum + 1, false),
MAXWLEN);
p = buf + skip;
endp = buf + len;
diff --git a/src/nvim/spellfile.c b/src/nvim/spellfile.c
index 15271e831c..8b95178c84 100644
--- a/src/nvim/spellfile.c
+++ b/src/nvim/spellfile.c
@@ -5035,7 +5035,7 @@ static void sug_write(spellinfo_T *spin, char_u *fname)
for (linenr_T lnum = 1; lnum <= wcount; ++lnum) {
// <sugline>: <sugnr> ... NUL
- char_u *line = ml_get_buf(spin->si_spellbuf, lnum, FALSE);
+ char_u *line = ml_get_buf(spin->si_spellbuf, lnum, false);
size_t len = STRLEN(line) + 1;
if (fwrite(line, len, 1, fd) == 0) {
EMSG(_(e_write));
diff --git a/src/nvim/syntax.c b/src/nvim/syntax.c
index e9ee63970c..bdbbc4aacf 100644
--- a/src/nvim/syntax.c
+++ b/src/nvim/syntax.c
@@ -53,9 +53,9 @@ static bool did_syntax_onoff = false;
/// Structure that stores information about a highlight group.
/// The ID of a highlight group is also called group ID. It is the index in
/// the highlight_ga array PLUS ONE.
-struct hl_group {
+typedef struct hl_group {
char_u *sg_name; ///< highlight group name
- char_u *sg_name_u; ///< uppercase of sg_name
+ char *sg_name_u; ///< uppercase of sg_name
bool sg_cleared; ///< "hi clear" was used
int sg_attr; ///< Screen attr @see ATTR_ENTRY
int sg_link; ///< link to this highlight group ID
@@ -80,7 +80,7 @@ struct hl_group {
char *sg_rgb_sp_name; ///< RGB special color name
int sg_blend; ///< blend level (0-100 inclusive), -1 if unset
-};
+} HlGroup;
/// \addtogroup SG_SET
/// @{
@@ -91,6 +91,7 @@ struct hl_group {
// builtin |highlight-groups|
static garray_T highlight_ga = GA_EMPTY_INIT_VALUE;
+Map(cstr_t, int) highlight_unames = MAP_INIT;
static inline struct hl_group * HL_TABLE(void)
{
@@ -364,24 +365,24 @@ static reg_extmatch_T *next_match_extmatch = NULL;
* The current state (within the line) of the recognition engine.
* When current_state.ga_itemsize is 0 the current state is invalid.
*/
-static win_T *syn_win; // current window for highlighting
-static buf_T *syn_buf; // current buffer for highlighting
-static synblock_T *syn_block; // current buffer for highlighting
-static proftime_T *syn_tm; // timeout limit
-static linenr_T current_lnum = 0; // lnum of current state
-static colnr_T current_col = 0; // column of current state
-static int current_state_stored = 0; // TRUE if stored current state
- // after setting current_finished
-static int current_finished = 0; // current line has been finished
-static garray_T current_state // current stack of state_items
+static win_T *syn_win; // current window for highlighting
+static buf_T *syn_buf; // current buffer for highlighting
+static synblock_T *syn_block; // current buffer for highlighting
+static proftime_T *syn_tm; // timeout limit
+static linenr_T current_lnum = 0; // lnum of current state
+static colnr_T current_col = 0; // column of current state
+static bool current_state_stored = false; // true if stored current state
+ // after setting current_finished
+static bool current_finished = false; // current line has been finished
+static garray_T current_state // current stack of state_items
= GA_EMPTY_INIT_VALUE;
-static int16_t *current_next_list = NULL; // when non-zero, nextgroup list
-static int current_next_flags = 0; // flags for current_next_list
-static int current_line_id = 0; // unique number for current line
+static int16_t *current_next_list = NULL; // when non-zero, nextgroup list
+static int current_next_flags = 0; // flags for current_next_list
+static int current_line_id = 0; // unique number for current line
#define CUR_STATE(idx) ((stateitem_T *)(current_state.ga_data))[idx]
-static int syn_time_on = FALSE;
+static bool syn_time_on = false;
# define IF_SYN_TIME(p) (p)
// Set the timeout used for syntax highlighting.
@@ -809,7 +810,7 @@ static void syn_sync(win_T *wp, linenr_T start_lnum, synstate_T *last_valid)
cur_si = &CUR_STATE(current_state.ga_len - 1);
cur_si->si_h_startpos.lnum = found_current_lnum;
cur_si->si_h_startpos.col = found_current_col;
- update_si_end(cur_si, (int)current_col, TRUE);
+ update_si_end(cur_si, (int)current_col, true);
check_keepend();
}
current_col = found_m_endpos.col;
@@ -880,7 +881,7 @@ static int syn_match_linecont(linenr_T lnum)
*/
static void syn_start_line(void)
{
- current_finished = FALSE;
+ current_finished = false;
current_col = 0;
/*
@@ -888,7 +889,7 @@ static void syn_start_line(void)
* previous line and regions that have "keepend".
*/
if (!GA_EMPTY(&current_state)) {
- syn_update_ends(TRUE);
+ syn_update_ends(true);
check_state_ends();
}
@@ -897,15 +898,13 @@ static void syn_start_line(void)
next_seqnr = 1;
}
-/*
- * Check for items in the stack that need their end updated.
- * When "startofline" is TRUE the last item is always updated.
- * When "startofline" is FALSE the item with "keepend" is forcefully updated.
- */
-static void syn_update_ends(int startofline)
+/// Check for items in the stack that need their end updated.
+///
+/// @param startofline if true the last item is always updated.
+/// if false the item with "keepend" is forcefully updated.
+static void syn_update_ends(bool startofline)
{
stateitem_T *cur_si;
- int seen_keepend;
if (startofline) {
/* Check for a match carried over from a previous line with a
@@ -940,8 +939,8 @@ static void syn_update_ends(int startofline)
if (CUR_STATE(i).si_flags & HL_EXTEND)
break;
- seen_keepend = FALSE;
- for (; i < current_state.ga_len; ++i) {
+ bool seen_keepend = false;
+ for (; i < current_state.ga_len; i++) {
cur_si = &CUR_STATE(i);
if ((cur_si->si_flags & HL_KEEPEND)
|| (seen_keepend && !startofline)
@@ -952,8 +951,9 @@ static void syn_update_ends(int startofline)
if (!(cur_si->si_flags & HL_MATCHCONT))
update_si_end(cur_si, (int)current_col, !startofline);
- if (!startofline && (cur_si->si_flags & HL_KEEPEND))
- seen_keepend = TRUE;
+ if (!startofline && (cur_si->si_flags & HL_KEEPEND)) {
+ seen_keepend = true;
+ }
}
}
check_keepend();
@@ -1151,17 +1151,15 @@ static void syn_stack_apply_changes_block(synblock_T *block, buf_T *buf)
}
}
-/*
- * Reduce the number of entries in the state stack for syn_buf.
- * Returns TRUE if at least one entry was freed.
- */
-static int syn_stack_cleanup(void)
+/// Reduce the number of entries in the state stack for syn_buf.
+///
+/// @return true if at least one entry was freed.
+static bool syn_stack_cleanup(void)
{
synstate_T *p, *prev;
disptick_T tick;
- int above;
int dist;
- int retval = FALSE;
+ bool retval = false;
if (syn_block->b_sst_first == NULL) {
return retval;
@@ -1179,16 +1177,17 @@ static int syn_stack_cleanup(void)
* "b_sst_lasttick" (the display tick wraps around).
*/
tick = syn_block->b_sst_lasttick;
- above = FALSE;
+ bool above = false;
prev = syn_block->b_sst_first;
for (p = prev->sst_next; p != NULL; prev = p, p = p->sst_next) {
if (prev->sst_lnum + dist > p->sst_lnum) {
if (p->sst_tick > syn_block->b_sst_lasttick) {
if (!above || p->sst_tick < tick)
tick = p->sst_tick;
- above = TRUE;
- } else if (!above && p->sst_tick < tick)
+ above = true;
+ } else if (!above && p->sst_tick < tick) {
tick = p->sst_tick;
+ }
}
}
@@ -1203,7 +1202,7 @@ static int syn_stack_cleanup(void)
prev->sst_next = p->sst_next;
syn_stack_free_entry(syn_block, p);
p = prev;
- retval = TRUE;
+ retval = true;
}
}
return retval;
@@ -1339,7 +1338,7 @@ static synstate_T *store_current_state(void)
sp->sst_tick = display_tick;
sp->sst_change_lnum = 0;
}
- current_state_stored = TRUE;
+ current_state_stored = true;
return sp;
}
@@ -1384,11 +1383,10 @@ static void load_current_state(synstate_T *from)
current_lnum = from->sst_lnum;
}
-/*
- * Compare saved state stack "*sp" with the current state.
- * Return TRUE when they are equal.
- */
-static int syn_stack_equal(synstate_T *sp)
+/// Compare saved state stack "*sp" with the current state.
+///
+/// @return true when they are equal.
+static bool syn_stack_equal(synstate_T *sp)
{
bufstate_T *bp;
reg_extmatch_T *six, *bsx;
@@ -1396,7 +1394,7 @@ static int syn_stack_equal(synstate_T *sp)
/* First a quick check if the stacks have the same size end nextlist. */
if (sp->sst_stacksize != current_state.ga_len
|| sp->sst_next_list != current_next_list) {
- return FALSE;
+ return false;
}
/* Need to compare all states on both stacks. */
@@ -1443,10 +1441,11 @@ static int syn_stack_equal(synstate_T *sp)
if (j != NSUBEXP)
break;
}
- if (i < 0)
- return TRUE;
+ if (i < 0) {
+ return true;
+ }
- return FALSE;
+ return false;
}
/*
@@ -1489,14 +1488,13 @@ static void validate_current_state(void)
ga_set_growsize(&current_state, 3);
}
-/*
- * Return TRUE if the syntax at start of lnum changed since last time.
- * This will only be called just after get_syntax_attr() for the previous
- * line, to check if the next line needs to be redrawn too.
- */
-int syntax_check_changed(linenr_T lnum)
+/// This will only be called just after get_syntax_attr() for the previous
+/// line, to check if the next line needs to be redrawn too.
+///
+/// @return true if the syntax at start of lnum changed since last time.
+bool syntax_check_changed(linenr_T lnum)
{
- int retval = TRUE;
+ bool retval = true;
synstate_T *sp;
/*
@@ -1519,8 +1517,9 @@ int syntax_check_changed(linenr_T lnum)
* Compare the current state with the previously saved state of
* the line.
*/
- if (syn_stack_equal(sp))
- retval = FALSE;
+ if (syn_stack_equal(sp)) {
+ retval = false;
+ }
/*
* Store the current state in b_sst_array[] for later use.
@@ -1677,15 +1676,15 @@ static int syn_current_attr(
(void)push_next_match();
}
- current_finished = TRUE;
- current_state_stored = FALSE;
+ current_finished = true;
+ current_state_stored = false;
return 0;
}
/* if the current or next character is NUL, we will finish the line now */
if (line[current_col] == NUL || line[current_col + 1] == NUL) {
- current_finished = TRUE;
- current_state_stored = FALSE;
+ current_finished = true;
+ current_state_stored = false;
}
/*
@@ -2151,16 +2150,14 @@ static int syn_current_attr(
}
-/*
- * Check if we already matched pattern "idx" at the current column.
- */
-static int did_match_already(int idx, garray_T *gap)
+/// @return true if we already matched pattern "idx" at the current column.
+static bool did_match_already(int idx, garray_T *gap)
{
for (int i = current_state.ga_len; --i >= 0; ) {
if (CUR_STATE(i).si_m_startcol == (int)current_col
&& CUR_STATE(i).si_m_lnum == (int)current_lnum
&& CUR_STATE(i).si_idx == idx) {
- return TRUE;
+ return true;
}
}
@@ -2168,11 +2165,11 @@ static int did_match_already(int idx, garray_T *gap)
* stack, and can only be matched once anyway. */
for (int i = gap->ga_len; --i >= 0; ) {
if (((int *)(gap->ga_data))[i] == idx) {
- return TRUE;
+ return true;
}
}
- return FALSE;
+ return false;
}
/*
@@ -2208,8 +2205,8 @@ static stateitem_T *push_next_match(void)
cur_si->si_next_list = spp->sp_next_list;
cur_si->si_extmatch = ref_extmatch(next_match_extmatch);
if (spp->sp_type == SPTYPE_START && !(spp->sp_flags & HL_ONELINE)) {
- /* Try to find the end pattern in the current line */
- update_si_end(cur_si, (int)(next_match_m_endpos.col), TRUE);
+ // Try to find the end pattern in the current line
+ update_si_end(cur_si, (int)(next_match_m_endpos.col), true);
check_keepend();
} else {
cur_si->si_m_endpos = next_match_m_endpos;
@@ -2315,9 +2312,10 @@ static void check_state_ends(void)
break;
if (had_extend && keepend_level >= 0) {
- syn_update_ends(FALSE);
- if (GA_EMPTY(&current_state))
+ syn_update_ends(false);
+ if (GA_EMPTY(&current_state)) {
break;
+ }
}
cur_si = &CUR_STATE(current_state.ga_len - 1);
@@ -2335,7 +2333,7 @@ static void check_state_ends(void)
&& SYN_ITEMS(syn_block)[cur_si->si_idx].sp_type
== SPTYPE_START
&& !(cur_si->si_flags & (HL_MATCH | HL_KEEPEND))) {
- update_si_end(cur_si, (int)current_col, TRUE);
+ update_si_end(cur_si, (int)current_col, true);
check_keepend();
if ((current_next_flags & HL_HAS_EOL)
&& keepend_level < 0
@@ -2451,18 +2449,14 @@ static void check_keepend(void)
}
}
-/*
- * Update an entry in the current_state stack for a start-skip-end pattern.
- * This finds the end of the current item, if it's in the current line.
- *
- * Return the flags for the matched END.
- */
-static void
-update_si_end(
- stateitem_T *sip,
- int startcol, /* where to start searching for the end */
- int force /* when TRUE overrule a previous end */
-)
+/// Update an entry in the current_state stack for a start-skip-end pattern.
+/// This finds the end of the current item, if it's in the current line.
+///
+/// @param startcol where to start searching for the end
+/// @param force when true overrule a previous end
+///
+/// @return the flags for the matched END.
+static void update_si_end(stateitem_T *sip, int startcol, bool force)
{
lpos_T hl_endpos;
lpos_T end_endpos;
@@ -2570,7 +2564,7 @@ find_endpos(
regmmatch_T best_regmatch; /* startpos/endpos of best match */
lpos_T pos;
char_u *line;
- int had_match = false;
+ bool had_match = false;
char_u buf_chartab[32]; // chartab array for syn option iskeyword
/* just in case we are invoked for a keyword */
@@ -2752,7 +2746,7 @@ find_endpos(
*flagsp = spp->sp_flags;
- had_match = TRUE;
+ had_match = true;
break;
}
@@ -2815,12 +2809,12 @@ syn_add_end_off(
col = regmatch->endpos[0].col;
off = spp->sp_offsets[idx];
}
- /* Don't go past the end of the line. Matters for "rs=e+2" when there
- * is a matchgroup. Watch out for match with last NL in the buffer. */
- if (result->lnum > syn_buf->b_ml.ml_line_count)
+ // Don't go past the end of the line. Matters for "rs=e+2" when there
+ // is a matchgroup. Watch out for match with last NL in the buffer.
+ if (result->lnum > syn_buf->b_ml.ml_line_count) {
col = 0;
- else if (off != 0) {
- base = ml_get_buf(syn_buf, result->lnum, FALSE);
+ } else if (off != 0) {
+ base = ml_get_buf(syn_buf, result->lnum, false);
p = base + col;
if (off > 0) {
while (off-- > 0 && *p != NUL) {
@@ -2866,10 +2860,10 @@ syn_add_start_off(
if (result->lnum > syn_buf->b_ml.ml_line_count) {
/* a "\n" at the end of the pattern may take us below the last line */
result->lnum = syn_buf->b_ml.ml_line_count;
- col = (int)STRLEN(ml_get_buf(syn_buf, result->lnum, FALSE));
+ col = (int)STRLEN(ml_get_buf(syn_buf, result->lnum, false));
}
if (off != 0) {
- base = ml_get_buf(syn_buf, result->lnum, FALSE);
+ base = ml_get_buf(syn_buf, result->lnum, false);
p = base + col;
if (off > 0) {
while (off-- && *p != NUL) {
@@ -2890,7 +2884,7 @@ syn_add_start_off(
*/
static char_u *syn_getcurline(void)
{
- return ml_get_buf(syn_buf, current_lnum, FALSE);
+ return ml_get_buf(syn_buf, current_lnum, false);
}
/*
@@ -2902,7 +2896,7 @@ static int syn_regexec(regmmatch_T *rmp, linenr_T lnum, colnr_T col, syn_time_T
int r;
int timed_out = 0;
proftime_T pt;
- const int l_syn_time_on = syn_time_on;
+ const bool l_syn_time_on = syn_time_on;
if (l_syn_time_on) {
pt = profile_start();
@@ -3372,7 +3366,7 @@ static void syn_cmd_clear(exarg_T *eap, int syncing)
XFREE_CLEAR(SYN_CLSTR(curwin->w_s)[scl_id].scl_list);
}
} else {
- id = syn_namen2id(arg, (int)(arg_end - arg));
+ id = syn_name2id_len(arg, (int)(arg_end - arg));
if (id == 0) {
EMSG2(_(e_nogroup), arg);
break;
@@ -3542,7 +3536,7 @@ syn_cmd_list(
else
syn_list_cluster(id - SYNID_CLUSTER);
} else {
- int id = syn_namen2id(arg, (int)(arg_end - arg));
+ int id = syn_name2id_len(arg, (int)(arg_end - arg));
if (id == 0) {
EMSG2(_(e_nogroup), arg);
} else {
@@ -4241,7 +4235,7 @@ static void syn_cmd_include(exarg_T *eap, int syncing)
char_u *errormsg = NULL;
int prev_toplvl_grp;
int prev_syn_inc_tag;
- int source = FALSE;
+ bool source = false;
eap->nextcmd = find_nextcmd(arg);
if (eap->skip)
@@ -4541,9 +4535,9 @@ syn_cmd_region(
int pat_count = 0; /* nr of syn_patterns found */
int syn_id;
int matchgroup_id = 0;
- int not_enough = FALSE; /* not enough arguments */
- int illegal = FALSE; /* illegal arguments */
- int success = FALSE;
+ bool not_enough = false; // not enough arguments
+ bool illegal = false; // illegal arguments
+ bool success = false;
syn_opt_arg_T syn_opt_arg;
int conceal_char = NUL;
@@ -4601,7 +4595,7 @@ syn_cmd_region(
}
rest = skipwhite(rest + 1);
if (*rest == NUL) {
- not_enough = TRUE;
+ not_enough = true;
break;
}
@@ -4612,7 +4606,7 @@ syn_cmd_region(
else {
matchgroup_id = syn_check_group(rest, (int)(p - rest));
if (matchgroup_id == 0) {
- illegal = TRUE;
+ illegal = true;
break;
}
}
@@ -4706,8 +4700,8 @@ syn_cmd_region(
}
redraw_curbuf_later(SOME_VALID);
- syn_stack_free_all(curwin->w_s); /* Need to recompute all syntax. */
- success = TRUE; /* don't free the progs and patterns now */
+ syn_stack_free_all(curwin->w_s); // Need to recompute all syntax.
+ success = true; // don't free the progs and patterns now
}
}
}
@@ -5859,16 +5853,17 @@ int syn_get_foldlevel(win_T *wp, long lnum)
*/
void ex_syntime(exarg_T *eap)
{
- if (STRCMP(eap->arg, "on") == 0)
- syn_time_on = TRUE;
- else if (STRCMP(eap->arg, "off") == 0)
- syn_time_on = FALSE;
- else if (STRCMP(eap->arg, "clear") == 0)
+ if (STRCMP(eap->arg, "on") == 0) {
+ syn_time_on = true;
+ } else if (STRCMP(eap->arg, "off") == 0) {
+ syn_time_on = false;
+ } else if (STRCMP(eap->arg, "clear") == 0) {
syntime_clear();
- else if (STRCMP(eap->arg, "report") == 0)
+ } else if (STRCMP(eap->arg, "report") == 0) {
syntime_report();
- else
+ } else {
EMSG2(_(e_invarg2), eap->arg);
+ }
}
static void syn_clear_time(syn_time_T *st)
@@ -6420,7 +6415,7 @@ void init_highlight(bool both, bool reset)
do_highlight(pp[i], reset, true);
}
} else if (!had_both) {
- // Don't do anything before the call with both == TRUE from main().
+ // Don't do anything before the call with both == true from main().
// Not everything has been setup then, and that call will overrule
// everything anyway.
return;
@@ -6461,7 +6456,7 @@ int load_colors(char_u *name)
{
char_u *buf;
int retval = FAIL;
- static int recursive = false;
+ static bool recursive = false;
// When being called recursively, this is probably because setting
// 'background' caused the highlighting to be reloaded. This means it is
@@ -6635,7 +6630,7 @@ void do_highlight(const char *line, const bool forceit, const bool init)
// ":highlight {group-name}": list highlighting for one group.
if (!doclear && !dolink && ends_excmd((uint8_t)(*linep))) {
- id = syn_namen2id((const char_u *)line, (int)(name_end - line));
+ id = syn_name2id_len((const char_u *)line, (int)(name_end - line));
if (id == 0) {
emsgf(_("E411: highlight group not found: %s"), line);
} else {
@@ -7113,6 +7108,7 @@ void free_highlight(void)
xfree(HL_TABLE()[i].sg_name_u);
}
ga_clear(&highlight_ga);
+ map_destroy(cstr_t, int)(&highlight_unames);
}
#endif
@@ -7130,11 +7126,10 @@ void restore_cterm_colors(void)
cterm_normal_bg_color = 0;
}
-/*
- * Return TRUE if highlight group "idx" has any settings.
- * When "check_link" is TRUE also check for an existing link.
- */
-static int hl_has_settings(int idx, int check_link)
+/// @param check_link if true also check for an existing link.
+///
+/// @return TRUE if highlight group "idx" has any settings.
+static int hl_has_settings(int idx, bool check_link)
{
return HL_TABLE()[idx].sg_cleared == 0
&& (HL_TABLE()[idx].sg_attr != 0
@@ -7470,26 +7465,35 @@ static void set_hl_attr(int idx)
}
}
+int syn_name2id(const char_u *name)
+ FUNC_ATTR_NONNULL_ALL
+{
+ return syn_name2id_len(name, STRLEN(name));
+}
+
/// Lookup a highlight group name and return its ID.
///
/// @param highlight name e.g. 'Cursor', 'Normal'
/// @return the highlight id, else 0 if \p name does not exist
-int syn_name2id(const char_u *name)
+int syn_name2id_len(const char_u *name, size_t len)
FUNC_ATTR_NONNULL_ALL
{
- int i;
- char_u name_u[200];
-
- /* Avoid using stricmp() too much, it's slow on some systems */
- /* Avoid alloc()/free(), these are slow too. ID names over 200 chars
- * don't deserve to be found! */
- STRLCPY(name_u, name, 200);
- vim_strup(name_u);
- for (i = highlight_ga.ga_len; --i >= 0; )
- if (HL_TABLE()[i].sg_name_u != NULL
- && STRCMP(name_u, HL_TABLE()[i].sg_name_u) == 0)
- break;
- return i + 1;
+ char name_u[201];
+
+ if (len == 0 || len > 200) {
+ // ID names over 200 chars don't deserve to be found!
+ return 0;
+ }
+
+ // Avoid using stricmp() too much, it's slow on some systems */
+ // Avoid alloc()/free(), these are slow too.
+ memcpy(name_u, name, len);
+ name_u[len] = '\0';
+ vim_strup((char_u *)name_u);
+
+ // map_get(..., int) returns 0 when no key is present, which is
+ // the expected value for missing highlight group.
+ return map_get(cstr_t, int)(&highlight_unames, name_u);
}
/// Lookup a highlight group name and return its attributes.
@@ -7524,17 +7528,6 @@ char_u *syn_id2name(int id)
return HL_TABLE()[id - 1].sg_name;
}
-/*
- * Like syn_name2id(), but take a pointer + length argument.
- */
-int syn_namen2id(const char_u *linep, int len)
-{
- char_u *name = vim_strnsave(linep, len);
- int id = syn_name2id(name);
- xfree(name);
-
- return id;
-}
/// Find highlight group name in the table and return its ID.
/// If it doesn't exist yet, a new entry is created.
@@ -7543,14 +7536,11 @@ int syn_namen2id(const char_u *linep, int len)
/// @param len length of \p pp
///
/// @return 0 for failure else the id of the group
-int syn_check_group(const char_u *pp, int len)
+int syn_check_group(const char_u *name, int len)
{
- char_u *name = vim_strnsave(pp, len);
- int id = syn_name2id(name);
+ int id = syn_name2id_len(name, len);
if (id == 0) { // doesn't exist yet
- id = syn_add_group(name);
- } else {
- xfree(name);
+ return syn_add_group(vim_strnsave(name, len));
}
return id;
}
@@ -7593,7 +7583,7 @@ static int syn_add_group(char_u *name)
return 0;
}
- char_u *const name_up = vim_strsave_up(name);
+ char *const name_up = (char *)vim_strsave_up(name);
// Append another syntax_highlight entry.
struct hl_group* hlgp = GA_APPEND_VIA_PTR(struct hl_group, &highlight_ga);
@@ -7605,7 +7595,11 @@ static int syn_add_group(char_u *name)
hlgp->sg_blend = -1;
hlgp->sg_name_u = name_up;
- return highlight_ga.ga_len; /* ID is index plus one */
+ int id = highlight_ga.ga_len; // ID is index plus one
+
+ map_put(cstr_t, int)(&highlight_unames, name_up, id);
+
+ return id;
}
/// When, just after calling syn_add_group(), an error is discovered, this
@@ -7613,8 +7607,10 @@ static int syn_add_group(char_u *name)
static void syn_unadd_group(void)
{
highlight_ga.ga_len--;
- xfree(HL_TABLE()[highlight_ga.ga_len].sg_name);
- xfree(HL_TABLE()[highlight_ga.ga_len].sg_name_u);
+ HlGroup *item = &HL_TABLE()[highlight_ga.ga_len];
+ map_del(cstr_t, int)(&highlight_unames, item->sg_name_u);
+ xfree(item->sg_name);
+ xfree(item->sg_name_u);
}
@@ -7875,8 +7871,9 @@ const char *get_highlight_name(expand_T *const xp, int idx)
/// Obtain a highlight group name.
-/// When "skip_cleared" is TRUE don't return a cleared entry.
-const char *get_highlight_name_ext(expand_T *xp, int idx, int skip_cleared)
+///
+/// @param skip_cleared if true don't return a cleared entry.
+const char *get_highlight_name_ext(expand_T *xp, int idx, bool skip_cleared)
FUNC_ATTR_WARN_UNUSED_RESULT
{
if (idx < 0) {
diff --git a/src/nvim/tag.c b/src/nvim/tag.c
index d6c6b064b2..61d48eb4bf 100644
--- a/src/nvim/tag.c
+++ b/src/nvim/tag.c
@@ -1371,12 +1371,12 @@ find_tags(
tagname_T tn; /* info for get_tagfname() */
int first_file; /* trying first tag file */
tagptrs_T tagp;
- int did_open = FALSE; /* did open a tag file */
- int stop_searching = FALSE; /* stop when match found or error */
- int retval = FAIL; /* return value */
- int is_static; /* current tag line is static */
- int is_current; /* file name matches */
- int eof = FALSE; /* found end-of-file */
+ bool did_open = false; // did open a tag file
+ bool stop_searching = false; // stop when match found or error
+ int retval = FAIL; // return value
+ int is_static; // current tag line is static
+ int is_current; // file name matches
+ bool eof = false; // found end-of-file
char_u *p;
char_u *s;
int i;
@@ -1429,12 +1429,12 @@ find_tags(
vimconv_T vimconv;
int findall = (mincount == MAXCOL || mincount == TAG_MANY);
- /* find all matching tags */
- int sort_error = FALSE; /* tags file not sorted */
- int linear; /* do a linear search */
- int sortic = FALSE; /* tag file sorted in nocase */
- int line_error = FALSE; /* syntax error */
- int has_re = (flags & TAG_REGEXP); /* regexp used */
+ // find all matching tags
+ bool sort_error = false; // tags file not sorted
+ int linear; // do a linear search
+ bool sortic = false; // tag file sorted in nocase
+ bool line_error = false; // syntax error
+ int has_re = (flags & TAG_REGEXP); // regexp used
int help_only = (flags & TAG_HELP);
int name_only = (flags & TAG_NAMES);
int noic = (flags & TAG_NOIC);
@@ -1621,7 +1621,7 @@ find_tags(
verbose_leave();
}
}
- did_open = TRUE; /* remember that we found at least one file */
+ did_open = true; // remember that we found at least one file
state = TS_START; /* we're at the start of the file */
@@ -1638,13 +1638,13 @@ find_tags(
if ((flags & TAG_INS_COMP)) /* Double brackets for gcc */
ins_compl_check_keys(30, false);
if (got_int || compl_interrupted) {
- stop_searching = TRUE;
+ stop_searching = true;
break;
}
/* When mincount is TAG_MANY, stop when enough matches have been
* found (for completion). */
if (mincount == TAG_MANY && match_count >= TAG_MANY) {
- stop_searching = TRUE;
+ stop_searching = true;
retval = OK;
break;
}
@@ -1795,7 +1795,7 @@ line_read_in:
state = TS_BINARY;
else if (tag_file_sorted == '2') {
state = TS_BINARY;
- sortic = TRUE;
+ sortic = true;
orgpat.regmatch.rm_ic = (p_ic || !noic);
} else
state = TS_LINEAR;
@@ -1878,8 +1878,9 @@ parse_line:
i = (int)tagp.tagname[0];
if (sortic)
i = TOUPPER_ASC(tagp.tagname[0]);
- if (i < search_info.low_char || i > search_info.high_char)
- sort_error = TRUE;
+ if (i < search_info.low_char || i > search_info.high_char) {
+ sort_error = true;
+ }
/*
* Compare the current tag with the searched tag.
@@ -1970,7 +1971,7 @@ parse_line:
i = parse_tag_line(lbuf,
&tagp);
if (i == FAIL) {
- line_error = TRUE;
+ line_error = true;
break;
}
@@ -2175,7 +2176,7 @@ parse_line:
tag_file_sorted = NUL;
if (sort_error) {
EMSG2(_("E432: Tags file not sorted: %s"), tag_fname);
- sort_error = FALSE;
+ sort_error = false;
}
/*
@@ -2183,7 +2184,7 @@ parse_line:
*/
if (match_count >= mincount) {
retval = OK;
- stop_searching = TRUE;
+ stop_searching = true;
}
if (stop_searching || use_cscope)
@@ -3060,24 +3061,26 @@ expand_tags (
)
{
int i;
- int c;
- int tagnmflag;
- char_u tagnm[100];
+ int extra_flag;
+ char_u *name_buf;
+ size_t name_buf_size = 100;
tagptrs_T t_p;
int ret;
- if (tagnames)
- tagnmflag = TAG_NAMES;
- else
- tagnmflag = 0;
+ name_buf = xmalloc(name_buf_size);
+
+ if (tagnames) {
+ extra_flag = TAG_NAMES;
+ } else {
+ extra_flag = 0;
+ }
if (pat[0] == '/') {
ret = find_tags(pat + 1, num_file, file,
- TAG_REGEXP | tagnmflag | TAG_VERBOSE | TAG_NO_TAGFUNC,
+ TAG_REGEXP | extra_flag | TAG_VERBOSE | TAG_NO_TAGFUNC,
TAG_MANY, curbuf->b_ffname);
} else {
ret = find_tags(pat, num_file, file,
- TAG_REGEXP | tagnmflag | TAG_VERBOSE
- | TAG_NO_TAGFUNC | TAG_NOIC,
+ TAG_REGEXP | extra_flag | TAG_VERBOSE | TAG_NO_TAGFUNC | TAG_NOIC,
TAG_MANY, curbuf->b_ffname);
}
if (ret == OK && !tagnames) {
@@ -3085,18 +3088,29 @@ expand_tags (
* "<tagname>\0<kind>\0<filename>\0"
*/
for (i = 0; i < *num_file; i++) {
+ size_t len;
+
parse_match((*file)[i], &t_p);
- c = (int)(t_p.tagname_end - t_p.tagname);
- memmove(tagnm, t_p.tagname, (size_t)c);
- tagnm[c++] = 0;
- tagnm[c++] = (t_p.tagkind != NULL && *t_p.tagkind)
- ? *t_p.tagkind : 'f';
- tagnm[c++] = 0;
- memmove((*file)[i] + c, t_p.fname, t_p.fname_end - t_p.fname);
- (*file)[i][c + (t_p.fname_end - t_p.fname)] = 0;
- memmove((*file)[i], tagnm, (size_t)c);
+ len = t_p.tagname_end - t_p.tagname;
+ if (len > name_buf_size - 3) {
+ char_u *buf;
+
+ name_buf_size = len + 3;
+ buf = xrealloc(name_buf, name_buf_size);
+ name_buf = buf;
+ }
+
+ memmove(name_buf, t_p.tagname, len);
+ name_buf[len++] = 0;
+ name_buf[len++] = (t_p.tagkind != NULL && *t_p.tagkind)
+ ? *t_p.tagkind : 'f';
+ name_buf[len++] = 0;
+ memmove((*file)[i] + len, t_p.fname, t_p.fname_end - t_p.fname);
+ (*file)[i][len + (t_p.fname_end - t_p.fname)] = 0;
+ memmove((*file)[i], name_buf, len);
}
}
+ xfree(name_buf);
return ret;
}
diff --git a/src/nvim/terminal.c b/src/nvim/terminal.c
index c07a956dde..3335fa500a 100644
--- a/src/nvim/terminal.c
+++ b/src/nvim/terminal.c
@@ -76,7 +76,6 @@
#include "nvim/event/time.h"
#include "nvim/os/input.h"
#include "nvim/api/private/helpers.h"
-#include "nvim/api/private/handle.h"
typedef struct terminal_state {
VimState state;
@@ -153,11 +152,10 @@ static VTermScreenCallbacks vterm_screen_callbacks = {
.sb_popline = term_sb_pop,
};
-static PMap(ptr_t) *invalidated_terminals;
+static PMap(ptr_t) invalidated_terminals = MAP_INIT;
void terminal_init(void)
{
- invalidated_terminals = pmap_new(ptr_t)();
time_watcher_init(&main_loop, &refresh_timer, NULL);
// refresh_timer_cb will redraw the screen which can call vimscript
refresh_timer.events = multiqueue_new_child(main_loop.events);
@@ -168,8 +166,10 @@ void terminal_teardown(void)
time_watcher_stop(&refresh_timer);
multiqueue_free(refresh_timer.events);
time_watcher_close(&refresh_timer, NULL);
- pmap_free(ptr_t)(invalidated_terminals);
- invalidated_terminals = NULL;
+ pmap_destroy(ptr_t)(&invalidated_terminals);
+ // terminal_destroy might be called after terminal_teardown is invoked
+ // make sure it is in an empty, valid state
+ pmap_init(ptr_t, &invalidated_terminals);
}
// public API {{{
@@ -260,7 +260,7 @@ Terminal *terminal_open(buf_T *buf, TerminalOptions opts)
return rv;
}
-void terminal_close(Terminal *term, char *msg)
+void terminal_close(Terminal *term, int status)
{
if (term->closed) {
return;
@@ -278,8 +278,8 @@ void terminal_close(Terminal *term, char *msg)
buf_T *buf = handle_get_buffer(term->buf_handle);
term->closed = true;
- if (!msg || exiting) {
- // If no msg was given, this was called by close_buffer(buffer.c). Or if
+ if (status == -1 || exiting) {
+ // If status is -1, this was called by close_buffer(buffer.c). Or if
// exiting, we must inform the buffer the terminal no longer exists so that
// close_buffer() doesn't call this again.
term->buf_handle = 0;
@@ -291,11 +291,16 @@ void terminal_close(Terminal *term, char *msg)
term->opts.close_cb(term->opts.data);
}
} else {
+ char msg[sizeof("\r\n[Process exited ]") + NUMBUFLEN];
+ snprintf(msg, sizeof msg, "\r\n[Process exited %d]", status);
terminal_receive(term, msg, strlen(msg));
}
- if (buf) {
+ if (buf && !is_autocmd_blocked()) {
+ dict_T *dict = get_vim_var_dict(VV_EVENT);
+ tv_dict_add_nr(dict, S_LEN("status"), status);
apply_autocmds(EVENT_TERMCLOSE, NULL, NULL, false, buf);
+ tv_dict_clear(dict);
}
}
@@ -521,14 +526,12 @@ void terminal_destroy(Terminal *term)
}
if (!term->refcount) {
- // might be destroyed after terminal_teardown is invoked
- if (invalidated_terminals
- && pmap_has(ptr_t)(invalidated_terminals, term)) {
+ if (pmap_has(ptr_t)(&invalidated_terminals, term)) {
// flush any pending changes to the buffer
block_autocmds();
refresh_terminal(term);
unblock_autocmds();
- pmap_del(ptr_t)(invalidated_terminals, term);
+ pmap_del(ptr_t)(&invalidated_terminals, term);
}
for (size_t i = 0; i < term->sb_current; i++) {
xfree(term->sb_buffer[i]);
@@ -865,7 +868,7 @@ static int term_sb_push(int cols, const VTermScreenCell *cells, void *data)
}
memcpy(sbrow->cells, cells, sizeof(cells[0]) * c);
- pmap_put(ptr_t)(invalidated_terminals, term, NULL);
+ pmap_put(ptr_t)(&invalidated_terminals, term, NULL);
return 1;
}
@@ -906,7 +909,7 @@ static int term_sb_pop(int cols, VTermScreenCell *cells, void *data)
}
xfree(sbrow);
- pmap_put(ptr_t)(invalidated_terminals, term, NULL);
+ pmap_put(ptr_t)(&invalidated_terminals, term, NULL);
return 1;
}
@@ -1208,7 +1211,7 @@ static void invalidate_terminal(Terminal *term, int start_row, int end_row)
term->invalid_end = MAX(term->invalid_end, end_row);
}
- pmap_put(ptr_t)(invalidated_terminals, term, NULL);
+ pmap_put(ptr_t)(&invalidated_terminals, term, NULL);
if (!refresh_pending) {
time_watcher_start(&refresh_timer, refresh_timer_cb, REFRESH_DELAY, 0);
refresh_pending = true;
@@ -1250,10 +1253,10 @@ static void refresh_timer_cb(TimeWatcher *watcher, void *data)
void *stub; (void)(stub);
// don't process autocommands while updating terminal buffers
block_autocmds();
- map_foreach(invalidated_terminals, term, stub, {
+ map_foreach(&invalidated_terminals, term, stub, {
refresh_terminal(term);
});
- pmap_clear(ptr_t)(invalidated_terminals);
+ pmap_clear(ptr_t)(&invalidated_terminals);
unblock_autocmds();
}
diff --git a/src/nvim/testdir/setup.vim b/src/nvim/testdir/setup.vim
index fcbc28fdc0..b3df8c63e6 100644
--- a/src/nvim/testdir/setup.vim
+++ b/src/nvim/testdir/setup.vim
@@ -12,6 +12,7 @@ set directory^=.
set fillchars=vert:\|,fold:-
set laststatus=1
set listchars=eol:$
+set joinspaces
set nohidden smarttab noautoindent noautoread complete-=i noruler noshowcmd
set nrformats+=octal
set shortmess-=F
@@ -21,6 +22,14 @@ set undodir^=.
set wildoptions=
set startofline
set sessionoptions+=options
+set viewoptions+=options
+set switchbuf=
+
+" Unmap Nvim default mappings.
+unmap Y
+unmap <C-L>
+iunmap <C-U>
+iunmap <C-W>
" Prevent Nvim log from writing to stderr.
let $NVIM_LOG_FILE = exists($NVIM_LOG_FILE) ? $NVIM_LOG_FILE : 'Xnvim.log'
diff --git a/src/nvim/testdir/test42.in b/src/nvim/testdir/test42.in
index d9057e72fb..456f9ddb07 100644
--- a/src/nvim/testdir/test42.in
+++ b/src/nvim/testdir/test42.in
Binary files differ
diff --git a/src/nvim/testdir/test_autocmd.vim b/src/nvim/testdir/test_autocmd.vim
index ad28118f16..015979e1be 100644
--- a/src/nvim/testdir/test_autocmd.vim
+++ b/src/nvim/testdir/test_autocmd.vim
@@ -998,6 +998,7 @@ func Test_bufunload_all()
endfunc
au BufUnload * call UnloadAllBufs()
au VimLeave * call writefile(['Test Finished'], 'Xout')
+ set nohidden
edit Xxx1
split Xxx2
q
@@ -1955,7 +1956,7 @@ func Test_autocmd_sigusr1()
let g:sigusr1_passed = 0
au Signal SIGUSR1 let g:sigusr1_passed = 1
- call system('/bin/kill -s usr1 ' . getpid())
+ call system('kill -s usr1 ' . getpid())
call WaitForAssert({-> assert_true(g:sigusr1_passed)})
au! Signal
diff --git a/src/nvim/testdir/test_command_count.vim b/src/nvim/testdir/test_command_count.vim
index 55b230373f..c7dddf4164 100644
--- a/src/nvim/testdir/test_command_count.vim
+++ b/src/nvim/testdir/test_command_count.vim
@@ -33,7 +33,7 @@ func Test_command_count_0()
delcommand RangeBuffers
delcommand RangeBuffersAll
- set hidden&
+ set nohidden
set swapfile&
endfunc
diff --git a/src/nvim/testdir/test_cursorline.vim b/src/nvim/testdir/test_cursorline.vim
index 4a0f2665fe..39d8b901ed 100644
--- a/src/nvim/testdir/test_cursorline.vim
+++ b/src/nvim/testdir/test_cursorline.vim
@@ -192,7 +192,29 @@ func Test_cursorline_screenline()
call term_sendkeys(buf, "gj")
call term_wait(buf)
call VerifyScreenDump(buf, 'Test_'. filename. '_18', {})
+ call term_sendkeys(buf, ":set breakindent& foldcolumn& signcolumn&\<cr>")
endif
+ " showbreak should not be highlighted with CursorLine when 'number' is off
+ call term_sendkeys(buf, "gg0")
+ call term_sendkeys(buf, ":set list cursorlineopt=screenline listchars=space:-\<cr>")
+ call term_sendkeys(buf, ":set nonumber\<cr>")
+ call VerifyScreenDump(buf, 'Test_'. filename. '_19', {})
+ call term_sendkeys(buf, "fagj")
+ call term_wait(buf)
+ call VerifyScreenDump(buf, 'Test_'. filename. '_20', {})
+ call term_sendkeys(buf, "gj")
+ call term_wait(buf)
+ call VerifyScreenDump(buf, 'Test_'. filename. '_21', {})
+ call term_sendkeys(buf, "gj")
+ call term_wait(buf)
+ call VerifyScreenDump(buf, 'Test_'. filename. '_22', {})
+ call term_sendkeys(buf, "gj")
+ call term_wait(buf)
+ call VerifyScreenDump(buf, 'Test_'. filename. '_23', {})
+ call term_sendkeys(buf, "gj")
+ call term_wait(buf)
+ call VerifyScreenDump(buf, 'Test_'. filename. '_24', {})
+ call term_sendkeys(buf, ":set list& cursorlineopt& listchars&\<cr>")
call StopVimInTerminal(buf)
call delete(filename)
diff --git a/src/nvim/testdir/test_diffmode.vim b/src/nvim/testdir/test_diffmode.vim
index 8a709d3f0d..efa7f552e0 100644
--- a/src/nvim/testdir/test_diffmode.vim
+++ b/src/nvim/testdir/test_diffmode.vim
@@ -540,7 +540,7 @@ func Test_diffopt_hiddenoff()
bwipe!
bwipe!
- set hidden& diffopt&
+ set nohidden diffopt&
endfunc
func Test_diffoff_hidden()
@@ -577,7 +577,7 @@ func Test_diffoff_hidden()
bwipe!
bwipe!
- set hidden& diffopt&
+ set nohidden diffopt&
endfunc
func Test_setting_cursor()
@@ -990,6 +990,37 @@ func Test_diff_with_cursorline()
call delete('Xtest_diff_cursorline')
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')
+ let buf = RunVimInTerminal('-S Xtest_diff_cursorline_breakindent', {})
+
+ call term_sendkeys(buf, "gg0")
+ call VerifyScreenDump(buf, 'Test_diff_with_cul_bri_01', {})
+ call term_sendkeys(buf, "j")
+ call VerifyScreenDump(buf, 'Test_diff_with_cul_bri_02', {})
+ call term_sendkeys(buf, "j")
+ call VerifyScreenDump(buf, 'Test_diff_with_cul_bri_03', {})
+ call term_sendkeys(buf, "j")
+ call VerifyScreenDump(buf, 'Test_diff_with_cul_bri_04', {})
+
+ " clean up
+ call StopVimInTerminal(buf)
+ call delete('Xtest_diff_cursorline_breakindent')
+endfunc
+
func Test_diff_with_syntax()
CheckScreendump
diff --git a/src/nvim/testdir/test_filetype.vim b/src/nvim/testdir/test_filetype.vim
index 4ab58cd084..4d29d18330 100644
--- a/src/nvim/testdir/test_filetype.vim
+++ b/src/nvim/testdir/test_filetype.vim
@@ -151,7 +151,6 @@ let s:filename_checks = {
\ 'dosini': ['.editorconfig', '/etc/pacman.conf', '/etc/yum.conf', 'file.ini', 'npmrc', '.npmrc', 'php.ini', 'php.ini-5', 'php.ini-file', '/etc/yum.repos.d/file', 'any/etc/pacman.conf', 'any/etc/yum.conf', 'any/etc/yum.repos.d/file', 'file.wrap'],
\ 'dot': ['file.dot', 'file.gv'],
\ 'dracula': ['file.drac', 'file.drc', 'filelvs', 'filelpe', 'drac.file', 'lpe', 'lvs', 'some-lpe', 'some-lvs'],
- \ 'dsl': ['file.dsl'],
\ 'dtd': ['file.dtd'],
\ 'dts': ['file.dts', 'file.dtsi'],
\ 'dune': ['jbuild', 'dune', 'dune-project', 'dune-workspace'],
@@ -263,6 +262,7 @@ let s:filename_checks = {
\ 'json': ['file.json', 'file.jsonp', 'file.json-patch', 'file.webmanifest', 'Pipfile.lock', 'file.ipynb'],
\ 'jsonc': ['file.jsonc'],
\ 'jsp': ['file.jsp'],
+ \ 'julia': ['file.jl'],
\ 'kconfig': ['Kconfig', 'Kconfig.debug', 'Kconfig.file'],
\ 'kivy': ['file.kv'],
\ 'kix': ['file.kix'],
@@ -754,6 +754,7 @@ func Test_pp_file()
split Xfile.pp
call assert_equal('pascal', &filetype)
bwipe!
+ unlet g:filetype_pp
" Test dist#ft#FTpp()
call writefile(['{ pascal comment'], 'Xfile.pp')
@@ -807,4 +808,21 @@ func Test_ex_file()
filetype off
endfunc
+func Test_dsl_file()
+ filetype on
+
+ call writefile([' <!doctype dsssl-spec ['], 'dslfile.dsl')
+ split dslfile.dsl
+ call assert_equal('dsl', &filetype)
+ bwipe!
+
+ call writefile(['workspace {'], 'dslfile.dsl')
+ split dslfile.dsl
+ call assert_equal('structurizr', &filetype)
+ bwipe!
+
+ call delete('dslfile.dsl')
+ filetype off
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_gf.vim b/src/nvim/testdir/test_gf.vim
index ee548037ba..43efd6248e 100644
--- a/src/nvim/testdir/test_gf.vim
+++ b/src/nvim/testdir/test_gf.vim
@@ -145,7 +145,7 @@ func Test_gf_visual()
bwipe!
call delete('Xtest_gf_visual')
- set hidden&
+ set nohidden
endfunc
func Test_gf_error()
diff --git a/src/nvim/testdir/test_ins_complete.vim b/src/nvim/testdir/test_ins_complete.vim
index 3da3648fec..0fb026f6b0 100644
--- a/src/nvim/testdir/test_ins_complete.vim
+++ b/src/nvim/testdir/test_ins_complete.vim
@@ -95,7 +95,7 @@ func Test_ins_complete()
call delete('Xtest11.one')
call delete('Xtest11.two')
call delete('Xtestdata')
- set cpt& cot& def& tags& tagbsearch& hidden&
+ set cpt& cot& def& tags& tagbsearch& nohidden
cd ..
call delete('Xdir', 'rf')
endfunc
diff --git a/src/nvim/testdir/test_join.vim b/src/nvim/testdir/test_join.vim
index ac6ef8f29f..ecb969d10a 100644
--- a/src/nvim/testdir/test_join.vim
+++ b/src/nvim/testdir/test_join.vim
@@ -51,7 +51,7 @@ func Test_join_marks()
/^This line/;'}-join
call assert_equal([0, 4, 11, 0], getpos("'["))
- call assert_equal([0, 4, 67, 0], getpos("']"))
+ call assert_equal([0, 4, 66, 0], getpos("']"))
enew!
endfunc
diff --git a/src/nvim/testdir/test_match.vim b/src/nvim/testdir/test_match.vim
index fed7240eb2..505a052a19 100644
--- a/src/nvim/testdir/test_match.vim
+++ b/src/nvim/testdir/test_match.vim
@@ -157,7 +157,10 @@ func Test_match_error()
endfunc
func Test_matchadd_error()
- call assert_fails("call matchadd('GroupDoesNotExist', 'X')", 'E28:')
+ call clearmatches()
+ " Nvim: not an error anymore:
+ call matchadd('GroupDoesNotExist', 'X')
+ call assert_equal([{'group': 'GroupDoesNotExist', 'pattern': 'X', 'priority': 10, 'id': 13}], getmatches())
call assert_fails("call matchadd('Search', '\\(')", 'E475:')
call assert_fails("call matchadd('Search', 'XXX', 1, 123, 1)", 'E715:')
call assert_fails("call matchadd('Error', 'XXX', 1, 3)", 'E798:')
diff --git a/src/nvim/testdir/test_mksession.vim b/src/nvim/testdir/test_mksession.vim
index fbe764bbf2..c96c6a9678 100644
--- a/src/nvim/testdir/test_mksession.vim
+++ b/src/nvim/testdir/test_mksession.vim
@@ -307,7 +307,7 @@ func Test_mksession_buffer_count()
call delete('Xbaz')
call delete('Xtest_mks.out')
%bwipe!
- set hidden&
+ set nohidden
endfunc
if has('extra_search')
diff --git a/src/nvim/testdir/test_normal.vim b/src/nvim/testdir/test_normal.vim
index 5c413d1e16..aff22f5d01 100644
--- a/src/nvim/testdir/test_normal.vim
+++ b/src/nvim/testdir/test_normal.vim
@@ -1227,7 +1227,7 @@ func Test_normal23_K()
set iskeyword-=\|
" Only expect "man" to work on Unix
- if !has("unix")
+ if !has("unix") || has('nvim') " Nvim K uses :terminal. #15398
let &keywordprg = k
bw!
return
diff --git a/src/nvim/testdir/test_options.vim b/src/nvim/testdir/test_options.vim
index 8796af7a20..72c151142d 100644
--- a/src/nvim/testdir/test_options.vim
+++ b/src/nvim/testdir/test_options.vim
@@ -539,7 +539,7 @@ func Test_copy_winopt()
call assert_equal(4,&numberwidth)
bw!
- set hidden&
+ set nohidden
endfunc
func Test_shortmess_F()
diff --git a/src/nvim/testdir/test_quickfix.vim b/src/nvim/testdir/test_quickfix.vim
index 5090584e41..283e7bbafe 100644
--- a/src/nvim/testdir/test_quickfix.vim
+++ b/src/nvim/testdir/test_quickfix.vim
@@ -1911,7 +1911,7 @@ func Test_switchbuf()
enew | only
set switchbuf=useopen
cexpr "Xqftestfile1:1:10"
- call assert_equal('', &switchbuf)
+ call assert_equal('uselast', &switchbuf)
call delete('Xqftestfile1')
call delete('Xqftestfile2')
diff --git a/src/nvim/testdir/test_tagjump.vim b/src/nvim/testdir/test_tagjump.vim
index 68dcfb6890..0fa7f85f0d 100644
--- a/src/nvim/testdir/test_tagjump.vim
+++ b/src/nvim/testdir/test_tagjump.vim
@@ -170,7 +170,7 @@ func Test_tag_symbolic()
call assert_equal('Xtest.c', expand('%:t'))
call assert_equal(2, col('.'))
- set hidden&
+ set nohidden
set tags&
enew!
call delete('Xtags')
@@ -548,6 +548,16 @@ func Test_tag_line_toolong()
call assert_equal('Xsomewhere', expand('%'))
call assert_equal(3, getcurpos()[1])
+ " expansion on command line works with long lines when &wildoptions contains
+ " 'tagfile'
+ set wildoptions=tagfile
+ call writefile([
+ \ 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa file /^pattern$/;" f'
+ \ ], 'Xtags')
+ call feedkeys(":tag \<Tab>", 'tx')
+ " Should not crash
+ call assert_true(v:true)
+
call delete('Xtags')
call delete('Xsomewhere')
set tags&
diff --git a/src/nvim/testdir/test_window_cmd.vim b/src/nvim/testdir/test_window_cmd.vim
index a522705238..039de0c623 100644
--- a/src/nvim/testdir/test_window_cmd.vim
+++ b/src/nvim/testdir/test_window_cmd.vim
@@ -608,7 +608,7 @@ func Test_window_prevwin()
" reset
q
call delete('tmp.txt')
- set hidden&vim autoread&vim
+ set nohidden autoread&vim
delfunc Fun_RenewFile
endfunc
diff --git a/src/nvim/undo.c b/src/nvim/undo.c
index 3096fe84c0..e1a7dbb2d3 100644
--- a/src/nvim/undo.c
+++ b/src/nvim/undo.c
@@ -1297,8 +1297,8 @@ void u_write_undo(const char *const name, const bool forceit, buf_T *const buf,
goto theend;
}
- /* Undo must be synced. */
- u_sync(TRUE);
+ // Undo must be synced.
+ u_sync(true);
/*
* Write the header.
@@ -1783,7 +1783,7 @@ void u_undo(int count)
* be compatible.
*/
if (curbuf->b_u_synced == false) {
- u_sync(TRUE);
+ u_sync(true);
count = 1;
}
@@ -1943,9 +1943,10 @@ void undo_time(long step, bool sec, bool file, bool absolute)
bool above = false;
bool did_undo = true;
- /* First make sure the current undoable change is synced. */
- if (curbuf->b_u_synced == false)
- u_sync(TRUE);
+ // First make sure the current undoable change is synced.
+ if (curbuf->b_u_synced == false) {
+ u_sync(true);
+ }
u_newcount = 0;
u_oldcount = 0;
@@ -2601,13 +2602,10 @@ static void u_undo_end(
msgbuf);
}
-/*
- * u_sync: stop adding to the current entry list
- */
-void
-u_sync(
- int force // Also sync when no_u_sync is set.
-)
+/// u_sync: stop adding to the current entry list
+///
+/// @param force if true, also sync when no_u_sync is set.
+void u_sync(bool force)
{
// Skip it when already synced or syncing is disabled.
if (curbuf->b_u_synced || (!force && no_u_sync > 0)) {
@@ -2764,13 +2762,13 @@ void u_find_first_changed(void)
return;
for (lnum = 1; lnum < curbuf->b_ml.ml_line_count
- && lnum <= uep->ue_size; ++lnum)
- if (STRCMP(ml_get_buf(curbuf, lnum, FALSE),
- uep->ue_array[lnum - 1]) != 0) {
+ && lnum <= uep->ue_size; lnum++) {
+ if (STRCMP(ml_get_buf(curbuf, lnum, false), uep->ue_array[lnum - 1]) != 0) {
clearpos(&(uhp->uh_cursor));
uhp->uh_cursor.lnum = lnum;
return;
}
+ }
if (curbuf->b_ml.ml_line_count != uep->ue_size) {
/* lines added or deleted at the end, put the cursor there */
clearpos(&(uhp->uh_cursor));
diff --git a/src/nvim/version.c b/src/nvim/version.c
index 48ef71613e..7c197f1b7f 100644
--- a/src/nvim/version.c
+++ b/src/nvim/version.c
@@ -39,7 +39,10 @@ NVIM_VERSION_PRERELEASE
char *Version = VIM_VERSION_SHORT;
char *longVersion = NVIM_VERSION_LONG;
char *version_buildtype = "Build type: " NVIM_VERSION_BUILD_TYPE;
+// Reproducible builds: omit compile info in Release builds. #15424
+#ifndef NDEBUG
char *version_cflags = "Compilation: " NVIM_VERSION_CFLAGS;
+#endif
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "version.c.generated.h"
@@ -2143,7 +2146,9 @@ void list_version(void)
MSG(longVersion);
MSG(version_buildtype);
list_lua_version();
+#ifndef NDEBUG
MSG(version_cflags);
+#endif
#ifdef HAVE_PATHDEF
diff --git a/src/nvim/window.c b/src/nvim/window.c
index fe6ab5af55..eddbe14da2 100644
--- a/src/nvim/window.c
+++ b/src/nvim/window.c
@@ -5,7 +5,6 @@
#include <inttypes.h>
#include <stdbool.h>
-#include "nvim/api/private/handle.h"
#include "nvim/api/private/helpers.h"
#include "nvim/vim.h"
#include "nvim/ascii.h"
@@ -905,7 +904,7 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir)
int new_size = size;
int i;
int need_status = 0;
- int do_equal = FALSE;
+ bool do_equal = false;
int needed;
int available;
int oldwin_height = 0;
@@ -991,9 +990,10 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir)
new_size = wmw1;
}
- /* if it doesn't fit in the current window, need win_equal() */
- if (oldwin->w_width - new_size - 1 < p_wmw)
- do_equal = TRUE;
+ // if it doesn't fit in the current window, need win_equal()
+ if (oldwin->w_width - new_size - 1 < p_wmw) {
+ do_equal = true;
+ }
// We don't like to take lines for the new window from a
// 'winfixwidth' window. Take them from a window to the left or right
@@ -1010,9 +1010,9 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir)
while (frp != NULL) {
if (frp->fr_win != oldwin && frp->fr_win != NULL
&& (frp->fr_win->w_width > new_size
- || frp->fr_win->w_width > oldwin->w_width
- - new_size - 1)) {
- do_equal = TRUE;
+ || frp->fr_win->w_width > (oldwin->w_width
+ - new_size - 1))) {
+ do_equal = true;
break;
}
frp = frp->fr_next;
@@ -1075,9 +1075,10 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir)
new_size = wmh1;
}
- /* if it doesn't fit in the current window, need win_equal() */
- if (oldwin_height - new_size - STATUS_HEIGHT < p_wmh)
- do_equal = TRUE;
+ // if it doesn't fit in the current window, need win_equal()
+ if (oldwin_height - new_size - STATUS_HEIGHT < p_wmh) {
+ do_equal = true;
+ }
/* We don't like to take lines for the new window from a
* 'winfixheight' window. Take them from a window above or below
@@ -1106,7 +1107,7 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir)
&& (frp->fr_win->w_height > new_size
|| frp->fr_win->w_height > oldwin_height - new_size
- STATUS_HEIGHT)) {
- do_equal = TRUE;
+ do_equal = true;
break;
}
frp = frp->fr_next;
@@ -1121,19 +1122,19 @@ 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)))) {
- /* new window below/right of current one */
- if (new_wp == NULL)
- wp = win_alloc(oldwin, FALSE);
- else
+ && ((flags & WSP_VERT) ? p_spr : p_sb)))) {
+ // new window below/right of current one
+ if (new_wp == NULL) {
+ wp = win_alloc(oldwin, false);
+ } else {
win_append(oldwin, wp);
+ }
} else {
- if (new_wp == NULL)
- wp = win_alloc(oldwin->w_prev, FALSE);
- else
+ if (new_wp == NULL) {
+ wp = win_alloc(oldwin->w_prev, false);
+ } else {
win_append(oldwin->w_prev, wp);
+ }
}
if (new_wp == NULL) {
@@ -1248,11 +1249,12 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir)
frame_add_vsep(curfrp);
/* Set width of neighbor frame */
frame_new_width(curfrp, curfrp->fr_width
- - (new_size + ((flags & WSP_TOP) != 0)), flags & WSP_TOP,
- FALSE);
- } else
+ - (new_size + ((flags & WSP_TOP) != 0)), flags & WSP_TOP,
+ false);
+ } else {
win_new_width(oldwin, oldwin->w_width - (new_size + 1));
- if (before) { /* new window left of current one */
+ }
+ if (before) { // new window left of current one
wp->w_wincol = oldwin->w_wincol;
oldwin->w_wincol += new_size + 1;
} else /* new window right of current one */
@@ -1439,7 +1441,7 @@ static void win_init_some(win_T *newp, win_T *oldp)
win_copy_options(oldp, newp);
}
-/// Return TRUE if "win" is floating window in the current tab page.
+/// Return true if "win" is floating window in the current tab page.
///
/// @param win window to check
bool win_valid_floating(const win_T *win)
@@ -1517,17 +1519,14 @@ int win_count(void)
return count;
}
-/*
- * Make "count" windows on the screen.
- * Return actual number of windows on the screen.
- * Must be called when there is just one window, filling the whole screen
- * (excluding the command line).
- */
-int
-make_windows (
- int count,
- int vertical /* split windows vertically if TRUE */
-)
+/// Make "count" windows on the screen.
+/// Must be called when there is just one window, filling the whole screen
+/// (excluding the command line).
+///
+/// @param vertical split windows vertically if true
+///
+/// @return actual number of windows on the screen.
+int make_windows(int count, bool vertical)
{
int maxcount;
int todo;
@@ -1552,8 +1551,9 @@ make_windows (
/*
* add status line now, otherwise first window will be too big
*/
- if (count > 1)
- last_status(TRUE);
+ if (count > 1) {
+ last_status(true);
+ }
/*
* Don't execute autocommands while creating the windows. Must do that
@@ -1786,8 +1786,8 @@ static void win_totop(int size, int flags)
(void)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 */
+ last_status(false); // may need to remove last status line
+ (void)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);
@@ -1898,7 +1898,7 @@ static void win_equal_rec(
int room = 0;
int new_size;
int has_next_curwin = 0;
- int hnc;
+ bool hnc;
if (topfr->fr_layout == FR_LEAF) {
/* Set the width/height of this frame.
@@ -2002,17 +2002,20 @@ static void win_equal_rec(
wincount = (n + (fr->fr_next == NULL ? extra_sep : 0))
/ (p_wmw + 1);
m = frame_minwidth(fr, next_curwin);
- if (has_next_curwin)
+ if (has_next_curwin) {
hnc = frame_has_win(fr, next_curwin);
- else
- hnc = FALSE;
- if (hnc) /* don't count next_curwin */
- --wincount;
- if (totwincount == 0)
+ } else {
+ hnc = false;
+ }
+ if (hnc) { // don't count next_curwin
+ wincount--;
+ }
+ if (totwincount == 0) {
new_size = room;
- else
+ } else {
new_size = (wincount * room + (totwincount / 2)) / totwincount;
- if (hnc) { /* add next_curwin size */
+ }
+ if (hnc) { // add next_curwin size
next_curwin_size -= p_wiw - (m - n);
new_size += next_curwin_size;
room -= new_size - next_curwin_size;
@@ -2123,17 +2126,20 @@ static void win_equal_rec(
wincount = (n + (fr->fr_next == NULL ? extra_sep : 0))
/ (p_wmh + 1);
m = frame_minheight(fr, next_curwin);
- if (has_next_curwin)
+ if (has_next_curwin) {
hnc = frame_has_win(fr, next_curwin);
- else
- hnc = FALSE;
- if (hnc) /* don't count next_curwin */
- --wincount;
- if (totwincount == 0)
+ } else {
+ hnc = false;
+ }
+ if (hnc) { // don't count next_curwin
+ wincount--;
+ }
+ if (totwincount == 0) {
new_size = room;
- else
+ } else {
new_size = (wincount * room + (totwincount / 2)) / totwincount;
- if (hnc) { /* add next_curwin size */
+ }
+ if (hnc) { // add next_curwin size
next_curwin_size -= p_wh - (m - n);
new_size += next_curwin_size;
room -= new_size - next_curwin_size;
@@ -2311,8 +2317,8 @@ static bool close_last_window_tabpage(win_T *win, bool free_buf,
int win_close(win_T *win, bool free_buf)
{
win_T *wp;
- int other_buffer = FALSE;
- int close_curwin = FALSE;
+ bool other_buffer = false;
+ bool close_curwin = false;
int dir;
bool help_window = false;
tabpage_T *prev_curtab = curtab;
@@ -2377,7 +2383,7 @@ int win_close(win_T *win, bool free_buf)
* to be the last one left, return now.
*/
if (wp->w_buffer != curbuf) {
- other_buffer = TRUE;
+ other_buffer = true;
win->w_closing = true;
apply_autocmds(EVENT_BUFLEAVE, NULL, NULL, FALSE, curbuf);
if (!win_valid(win))
@@ -2516,7 +2522,7 @@ int win_close(win_T *win, bool free_buf)
}
}
curbuf = curwin->w_buffer;
- close_curwin = TRUE;
+ close_curwin = true;
// The cursor position may be invalid if the buffer changed after last
// using the window.
@@ -2545,7 +2551,7 @@ int win_close(win_T *win, bool free_buf)
* If last window has a status line now and we don't want one,
* remove the status line.
*/
- last_status(FALSE);
+ last_status(false);
/* After closing the help window, try restoring the window layout from
* before it was opened. */
@@ -2598,7 +2604,7 @@ void win_close_othertab(win_T *win, int free_buf, tabpage_T *tp)
{
int dir;
tabpage_T *ptp = NULL;
- int free_tp = FALSE;
+ bool free_tp = false;
// Get here with win->w_buffer == NULL when win_close() detects the tab page
// changed.
@@ -2703,7 +2709,11 @@ static win_T *win_free_mem(
// When deleting the current window of another tab page select a new
// current window.
if (tp != NULL && win == tp->tp_curwin) {
- tp->tp_curwin = wp;
+ if (win_valid(tp->tp_prevwin) && tp->tp_prevwin != win) {
+ tp->tp_curwin = tp->tp_prevwin;
+ } else {
+ tp->tp_curwin = tp->tp_firstwin;
+ }
}
return wp;
@@ -2798,7 +2808,7 @@ winframe_remove (
}
}
frame_new_height(frp2, frp2->fr_height + frp_close->fr_height,
- frp2 == frp_close->fr_next ? TRUE : FALSE, FALSE);
+ frp2 == frp_close->fr_next, false);
*dirp = 'v';
} else {
/* When 'winfixwidth' is set, try to find another frame in the column
@@ -2827,7 +2837,7 @@ winframe_remove (
}
}
frame_new_width(frp2, frp2->fr_width + frp_close->fr_width,
- frp2 == frp_close->fr_next ? TRUE : FALSE, FALSE);
+ frp2 == frp_close->fr_next, false);
*dirp = 'h';
}
@@ -2983,18 +2993,14 @@ static bool frame_has_win(const frame_T *frp, const win_T *wp)
return false;
}
-/*
- * Set a new height for a frame. Recursively sets the height for contained
- * frames and windows. Caller must take care of positions.
- */
-static void
-frame_new_height (
- frame_T *topfrp,
- int height,
- int topfirst, /* resize topmost contained frame first */
- int wfh /* obey 'winfixheight' when there is a choice;
- may cause the height not to be set */
-)
+/// Set a new height for a frame. Recursively sets the height for contained
+/// frames and windows. Caller must take care of positions.
+///
+/// @param topfirst resize topmost contained frame first.
+/// @param wfh obey 'winfixheight' when there is a choice;
+/// may cause the height not to be set.
+static void frame_new_height(frame_T *topfrp, int height, bool topfirst,
+ bool wfh)
FUNC_ATTR_NONNULL_ALL
{
frame_T *frp;
@@ -3170,18 +3176,14 @@ static void frame_add_statusline(frame_T *frp)
}
}
-/*
- * Set width of a frame. Handles recursively going through contained frames.
- * May remove separator line for windows at the right side (for win_close()).
- */
-static void
-frame_new_width (
- frame_T *topfrp,
- int width,
- int leftfirst, /* resize leftmost contained frame first */
- int wfw /* obey 'winfixwidth' when there is a choice;
- may cause the width not to be set */
-)
+/// Set width of a frame. Handles recursively going through contained frames.
+/// May remove separator line for windows at the right side (for win_close()).
+///
+/// @param leftfirst resize leftmost contained frame first.
+/// @param wfw obey 'winfixwidth' when there is a choice;
+/// may cause the width not to be set.
+static void frame_new_width(frame_T *topfrp, int width, bool leftfirst,
+ bool wfw)
{
frame_T *frp;
int extra_cols;
@@ -3538,7 +3540,7 @@ void win_alloc_aucmd_win(void)
*/
static int win_alloc_firstwin(win_T *oldwin)
{
- curwin = win_alloc(NULL, FALSE);
+ curwin = win_alloc(NULL, false);
if (oldwin == NULL) {
/* Very first window, need to create an empty buffer for it and
* initialize from scratch. */
@@ -3602,7 +3604,7 @@ static tabpage_T *alloc_tabpage(void)
static int last_tp_handle = 0;
tabpage_T *tp = xcalloc(1, sizeof(tabpage_T));
tp->handle = ++last_tp_handle;
- handle_register_tabpage(tp);
+ pmap_put(handle_T)(&tabpage_handles, tp->handle, tp);
// Init t: variables.
tp->tp_vars = tv_dict_alloc();
@@ -3617,7 +3619,7 @@ void free_tabpage(tabpage_T *tp)
{
int idx;
- handle_unregister_tabpage(tp);
+ pmap_del(handle_T)(&tabpage_handles, tp->handle);
diff_clear(tp);
for (idx = 0; idx < SNAP_COUNT; ++idx)
clear_snapshot(tp, idx);
@@ -4342,13 +4344,13 @@ void win_enter(win_T *wp, bool undo_sync)
win_enter_ext(wp, undo_sync, false, false, true, true);
}
-/*
- * Make window wp the current window.
- * Can be called with "curwin_invalid" TRUE, which means that curwin has just
- * been closed and isn't valid.
- */
-static void win_enter_ext(win_T *wp, bool undo_sync, int curwin_invalid,
- int trigger_new_autocmds, bool trigger_enter_autocmds,
+/// Make window wp the current window.
+///
+/// @param curwin_invalid curwin has just been closed and
+/// isn't valid when true.
+static void win_enter_ext(win_T *wp, bool undo_sync, bool curwin_invalid,
+ bool trigger_new_autocmds,
+ bool trigger_enter_autocmds,
bool trigger_leave_autocmds)
{
int other_buffer = FALSE;
@@ -4376,7 +4378,7 @@ static void win_enter_ext(win_T *wp, bool undo_sync, int curwin_invalid,
// sync undo before leaving the current buffer
if (undo_sync && curbuf != wp->w_buffer) {
- u_sync(FALSE);
+ u_sync(false);
}
// Might need to scroll the old window before switching, e.g., when the
@@ -4536,11 +4538,9 @@ win_T *buf_jump_open_tab(buf_T *buf)
return NULL;
}
-/*
- * Allocate a window structure and link it in the window list when "hidden" is
- * FALSE.
- */
-static win_T *win_alloc(win_T *after, int hidden)
+/// @param hidden allocate a window structure and link it in the window if
+// false.
+static win_T *win_alloc(win_T *after, bool hidden)
{
static int last_win_id = LOWEST_WIN_ID - 1;
@@ -4548,7 +4548,7 @@ static win_T *win_alloc(win_T *after, int hidden)
win_T *new_wp = xcalloc(1, sizeof(win_T));
new_wp->handle = ++last_win_id;
- handle_register_window(new_wp);
+ pmap_put(handle_T)(&window_handles, new_wp->handle, new_wp);
grid_assign_handle(&new_wp->w_grid_alloc);
@@ -4619,7 +4619,7 @@ win_free (
int i;
wininfo_T *wip;
- handle_unregister_window(wp);
+ pmap_del(handle_T)(&window_handles, wp->handle);
clearFolding(wp);
/* reduce the reference count to the argument list. */
@@ -4830,9 +4830,10 @@ void shell_new_rows(void)
/* First try setting the heights of windows with 'winfixheight'. If
* that doesn't result in the right height, forget about that option. */
- frame_new_height(topframe, h, FALSE, TRUE);
- if (!frame_check_height(topframe, h))
- frame_new_height(topframe, h, FALSE, FALSE);
+ frame_new_height(topframe, h, false, true);
+ if (!frame_check_height(topframe, h)) {
+ frame_new_height(topframe, h, false, false);
+ }
(void)win_comp_pos(); // recompute w_winrow and w_wincol
win_reconfig_floats(); // The size of floats might change
@@ -5078,8 +5079,9 @@ static void frame_setheight(frame_T *curfrp, int height)
/* topframe: can only change the command line */
if (height > ROWS_AVAIL)
height = ROWS_AVAIL;
- if (height > 0)
- frame_new_height(curfrp, height, FALSE, FALSE);
+ if (height > 0) {
+ frame_new_height(curfrp, height, false, false);
+ }
} else if (curfrp->fr_parent->fr_layout == FR_ROW) {
/* Row of frames: Also need to resize frames left and right of this
* one. First check for the minimal height of these. */
@@ -5161,7 +5163,7 @@ static void frame_setheight(frame_T *curfrp, int height)
/*
* set the current frame to the new height
*/
- frame_new_height(curfrp, height, FALSE, FALSE);
+ frame_new_height(curfrp, height, false, false);
/*
* First take lines from the frames after the current frame. If
@@ -5184,16 +5186,15 @@ static void frame_setheight(frame_T *curfrp, int height)
if (frp->fr_height - room_reserved > take)
room_reserved = frp->fr_height - take;
take -= frp->fr_height - room_reserved;
- frame_new_height(frp, room_reserved, FALSE, FALSE);
+ frame_new_height(frp, room_reserved, false, false);
room_reserved = 0;
}
} else {
if (frp->fr_height - take < h) {
take -= frp->fr_height - h;
- frame_new_height(frp, h, FALSE, FALSE);
+ frame_new_height(frp, h, false, false);
} else {
- frame_new_height(frp, frp->fr_height - take,
- FALSE, FALSE);
+ frame_new_height(frp, frp->fr_height - take, false, false);
take = 0;
}
}
@@ -5324,7 +5325,7 @@ static void frame_setwidth(frame_T *curfrp, int width)
/*
* set the current frame to the new width
*/
- frame_new_width(curfrp, width, FALSE, FALSE);
+ frame_new_width(curfrp, width, false, false);
/*
* First take lines from the frames right of the current frame. If
@@ -5347,16 +5348,15 @@ static void frame_setwidth(frame_T *curfrp, int width)
if (frp->fr_width - room_reserved > take)
room_reserved = frp->fr_width - take;
take -= frp->fr_width - room_reserved;
- frame_new_width(frp, room_reserved, FALSE, FALSE);
+ frame_new_width(frp, room_reserved, false, false);
room_reserved = 0;
}
} else {
if (frp->fr_width - take < w) {
take -= frp->fr_width - w;
- frame_new_width(frp, w, FALSE, FALSE);
+ frame_new_width(frp, w, false, false);
} else {
- frame_new_width(frp, frp->fr_width - take,
- FALSE, FALSE);
+ frame_new_width(frp, frp->fr_width - take, false, false);
take = 0;
}
}
@@ -5409,16 +5409,14 @@ void win_setminwidth(void)
}
}
-/*
- * Status line of dragwin is dragged "offset" lines down (negative is up).
- */
+/// Status line of dragwin is dragged "offset" lines down (negative is up).
void win_drag_status_line(win_T *dragwin, int offset)
{
frame_T *curfr;
frame_T *fr;
int room;
int row;
- int up; /* if TRUE, drag status line up, otherwise down */
+ bool up; // if true, drag status line up, otherwise down
int n;
fr = dragwin->w_frame;
@@ -5444,8 +5442,8 @@ void win_drag_status_line(win_T *dragwin, int offset)
fr = fr->fr_parent;
}
- if (offset < 0) { /* drag up */
- up = TRUE;
+ if (offset < 0) { // drag up
+ up = true;
offset = -offset;
/* sum up the room of the current frame and above it */
if (fr == curfr) {
@@ -5459,12 +5457,10 @@ void win_drag_status_line(win_T *dragwin, int offset)
break;
}
}
- fr = curfr->fr_next; /* put fr at frame that grows */
- } else { /* drag down */
- up = FALSE;
- /*
- * Only dragging the last status line can reduce p_ch.
- */
+ fr = curfr->fr_next; // put fr at frame that grows
+ } else { // drag down
+ up = false;
+ // Only dragging the last status line can reduce p_ch.
room = Rows - cmdline_row;
if (curfr->fr_next == NULL)
room -= 1;
@@ -5488,8 +5484,9 @@ void win_drag_status_line(win_T *dragwin, int offset)
* Grow frame fr by "offset" lines.
* Doesn't happen when dragging the last status line up.
*/
- if (fr != NULL)
- frame_new_height(fr, fr->fr_height + offset, up, FALSE);
+ if (fr != NULL) {
+ frame_new_height(fr, fr->fr_height + offset, up, false);
+ }
if (up)
fr = curfr; /* current frame gets smaller */
@@ -5503,9 +5500,9 @@ void win_drag_status_line(win_T *dragwin, int offset)
n = frame_minheight(fr, NULL);
if (fr->fr_height - offset <= n) {
offset -= fr->fr_height - n;
- frame_new_height(fr, n, !up, FALSE);
+ frame_new_height(fr, n, !up, false);
} else {
- frame_new_height(fr, fr->fr_height - offset, !up, FALSE);
+ frame_new_height(fr, fr->fr_height - offset, !up, false);
break;
}
if (up)
@@ -5535,7 +5532,7 @@ void win_drag_vsep_line(win_T *dragwin, int offset)
frame_T *curfr;
frame_T *fr;
int room;
- int left; /* if TRUE, drag separator line left, otherwise right */
+ bool left; // if true, drag separator line left, otherwise right
int n;
fr = dragwin->w_frame;
@@ -5564,8 +5561,8 @@ void win_drag_vsep_line(win_T *dragwin, int offset)
}
}
- if (offset < 0) { /* drag left */
- left = TRUE;
+ if (offset < 0) { // drag left
+ left = true;
offset = -offset;
/* sum up the room of the current frame and left of it */
room = 0;
@@ -5574,10 +5571,10 @@ void win_drag_vsep_line(win_T *dragwin, int offset)
if (fr == curfr)
break;
}
- fr = curfr->fr_next; /* put fr at frame that grows */
- } else { /* drag right */
- left = FALSE;
- /* sum up the room of frames right of the current one */
+ fr = curfr->fr_next; // put fr at frame that grows
+ } else { // drag right
+ left = false;
+ // sum up the room of frames right of the current one
room = 0;
FOR_ALL_FRAMES(fr, curfr->fr_next) {
room += fr->fr_width - frame_minwidth(fr, NULL);
@@ -5600,8 +5597,8 @@ void win_drag_vsep_line(win_T *dragwin, int offset)
return; // Safety check, should not happen.
}
- /* grow frame fr by offset lines */
- frame_new_width(fr, fr->fr_width + offset, left, FALSE);
+ // grow frame fr by offset lines
+ frame_new_width(fr, fr->fr_width + offset, left, false);
/* shrink other frames: current and at the left or at the right */
if (left)
@@ -5613,9 +5610,9 @@ void win_drag_vsep_line(win_T *dragwin, int offset)
n = frame_minwidth(fr, NULL);
if (fr->fr_width - offset <= n) {
offset -= fr->fr_width - n;
- frame_new_width(fr, n, !left, FALSE);
+ frame_new_width(fr, n, !left, false);
} else {
- frame_new_width(fr, fr->fr_width - offset, !left, FALSE);
+ frame_new_width(fr, fr->fr_width - offset, !left, false);
break;
}
if (left)
@@ -5927,7 +5924,7 @@ void command_height(void)
*/
static void frame_add_height(frame_T *frp, int n)
{
- frame_new_height(frp, frp->fr_height + n, FALSE, FALSE);
+ frame_new_height(frp, frp->fr_height + n, false, false);
for (;; ) {
frp = frp->fr_parent;
if (frp == NULL)
@@ -6092,21 +6089,18 @@ file_name_in_line (
return find_file_name_in_path(ptr, len, options, count, rel_fname);
}
-/*
- * Add or remove a status line for the bottom window(s), according to the
- * value of 'laststatus'.
- */
-void
-last_status (
- int morewin /* pretend there are two or more windows */
-)
+/// Add or remove a status line for the bottom window(s), according to the
+/// value of 'laststatus'.
+///
+/// @param morewin pretend there are two or more windows if true.
+void last_status(bool morewin)
{
/* Don't make a difference between horizontal or vertical split. */
last_status_rec(topframe, (p_ls == 2
|| (p_ls == 1 && (morewin || !one_window()))));
}
-static void last_status_rec(frame_T *fr, int statusline)
+static void last_status_rec(frame_T *fr, bool statusline)
{
frame_T *fp;
win_T *wp;
@@ -6135,7 +6129,7 @@ static void last_status_rec(frame_T *fr, int statusline)
}
wp->w_status_height = 1;
if (fp != fr) {
- frame_new_height(fp, fp->fr_height - 1, FALSE, FALSE);
+ frame_new_height(fp, fp->fr_height - 1, false, false);
frame_fix_height(wp);
(void)win_comp_pos();
} else
@@ -6214,12 +6208,11 @@ bool only_one_window(void) FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
return count <= 1;
}
-/*
- * Correct the cursor line number in other windows. Used after changing the
- * current buffer, and before applying autocommands.
- * When "do_curwin" is TRUE, also check current window.
- */
-void check_lnums(int do_curwin)
+/// Correct the cursor line number in other windows. Used after changing the
+/// current buffer, and before applying autocommands.
+///
+/// @param do_curwin when true, also check current window.
+void check_lnums(bool do_curwin)
{
FOR_ALL_TAB_WINDOWS(tp, wp) {
if ((do_curwin || wp != curwin) && wp->w_buffer == curbuf) {
@@ -6367,8 +6360,8 @@ static win_T *restore_snapshot_rec(frame_T *sn, frame_T *fr)
fr->fr_height = sn->fr_height;
fr->fr_width = sn->fr_width;
if (fr->fr_layout == FR_LEAF) {
- frame_new_height(fr, fr->fr_height, FALSE, FALSE);
- frame_new_width(fr, fr->fr_width, FALSE, FALSE);
+ frame_new_height(fr, fr->fr_height, false, false);
+ frame_new_width(fr, fr->fr_width, false, false);
wp = sn->fr_win;
}
if (sn->fr_next != NULL) {
@@ -6406,15 +6399,16 @@ static win_T *get_snapshot_focus(int idx)
return win_valid(sn->fr_win) ? sn->fr_win : NULL;
}
-/*
- * Set "win" to be the curwin and "tp" to be the current tab page.
- * restore_win() MUST be called to undo, also when FAIL is returned.
- * No autocommands will be executed until restore_win() is called.
- * When "no_display" is TRUE the display won't be affected, no redraw is
- * triggered, another tabpage access is limited.
- * Returns FAIL if switching to "win" failed.
- */
-int switch_win(win_T **save_curwin, tabpage_T **save_curtab, win_T *win, tabpage_T *tp, int no_display)
+/// Set "win" to be the curwin and "tp" to be the current tab page.
+/// restore_win() MUST be called to undo, also when FAIL is returned.
+/// No autocommands will be executed until restore_win() is called.
+///
+/// @param no_display if true the display won't be affected, no redraw is
+/// triggered, another tabpage access is limited.
+///
+/// @return FAIL if switching to "win" failed.
+int switch_win(win_T **save_curwin, tabpage_T **save_curtab, win_T *win,
+ tabpage_T *tp, bool no_display)
{
block_autocmds();
return switch_win_noblock(save_curwin, save_curtab, win, tp, no_display);
@@ -6422,7 +6416,7 @@ int switch_win(win_T **save_curwin, tabpage_T **save_curtab, win_T *win, tabpage
// As switch_win() but without blocking autocommands.
int switch_win_noblock(win_T **save_curwin, tabpage_T **save_curtab,
- win_T *win, tabpage_T *tp, int no_display)
+ win_T *win, tabpage_T *tp, bool no_display)
{
*save_curwin = curwin;
if (tp != NULL) {
@@ -6543,8 +6537,7 @@ int match_add(win_T *wp, const char *const grp, const char *const pat,
cur = cur->next;
}
}
- if ((hlg_id = syn_name2id((const char_u *)grp)) == 0) {
- EMSG2(_(e_nogroup), grp);
+ if ((hlg_id = syn_check_group((const char_u *)grp, strlen(grp))) == 0) {
return -1;
}
if (pat != NULL && (regprog = vim_regcomp((char_u *)pat, RE_MAGIC)) == NULL) {
@@ -6695,8 +6688,9 @@ fail:
/// Delete match with ID 'id' in the match list of window 'wp'.
-/// Print error messages if 'perr' is TRUE.
-int match_delete(win_T *wp, int id, int perr)
+///
+/// @param perr print error messages if true.
+int match_delete(win_T *wp, int id, bool perr)
{
matchitem_T *cur = wp->w_match_head;
matchitem_T *prev = cur;
diff --git a/test/functional/api/buffer_updates_spec.lua b/test/functional/api/buffer_updates_spec.lua
index 05ca0d5f4d..c9c9be5406 100644
--- a/test/functional/api/buffer_updates_spec.lua
+++ b/test/functional/api/buffer_updates_spec.lua
@@ -159,9 +159,8 @@ describe('API: buffer events:', function()
tick = tick + 1
expectn('nvim_buf_lines_event', {b, tick, 29, 29, firstfour, false})
- -- create a new empty buffer and wipe out the old one ... this will
- -- turn off buffer events
- command('enew!')
+ -- delete the current buffer to turn off buffer events
+ command('bdelete!')
expectn('nvim_buf_detach_event', {b})
-- add a line at the start of an empty file
@@ -269,7 +268,7 @@ describe('API: buffer events:', function()
'original foo'}, false})
-- type text into the first line of a blank file, one character at a time
- command('enew!')
+ command('bdelete!')
tick = 2
expectn('nvim_buf_detach_event', {b})
local bnew = nvim('get_current_buf')
@@ -666,7 +665,8 @@ describe('API: buffer events:', function()
tick = tick + 1
expectn('nvim_buf_changedtick_event', {b, tick})
- -- close our buffer by creating a new one
+ -- close our buffer and create a new one
+ command('bdelete')
command('enew')
expectn('nvim_buf_detach_event', {b})
diff --git a/test/functional/api/window_spec.lua b/test/functional/api/window_spec.lua
index bb72b63b6c..c49d6405f4 100644
--- a/test/functional/api/window_spec.lua
+++ b/test/functional/api/window_spec.lua
@@ -311,7 +311,8 @@ describe('API/win', function()
eq({newwin}, meths.list_wins())
end)
- it('handles changed buffer', function()
+ it("handles changed buffer when 'hidden' is unset", function()
+ command('set nohidden')
local oldwin = meths.get_current_win()
insert('text')
command('new')
@@ -346,6 +347,21 @@ describe('API/win', function()
eq(2, #meths.list_wins())
eq('', funcs.getcmdwintype())
end)
+
+ it('closing current (float) window of another tabpage #15313', function()
+ command('tabedit')
+ eq(2, eval('tabpagenr()'))
+ local win = meths.open_win(0, true, {
+ relative='editor', row=10, col=10, width=50, height=10
+ })
+ local tabpage = eval('tabpagenr()')
+ command('tabprevious')
+ eq(1, eval('tabpagenr()'))
+ meths.win_close(win, false)
+
+ eq(1001, meths.tabpage_get_win(tabpage).id)
+ helpers.assert_alive()
+ end)
end)
describe('hide', function()
diff --git a/test/functional/autocmd/termxx_spec.lua b/test/functional/autocmd/termxx_spec.lua
index b12c24b58d..1e8f981437 100644
--- a/test/functional/autocmd/termxx_spec.lua
+++ b/test/functional/autocmd/termxx_spec.lua
@@ -13,7 +13,7 @@ describe('autocmd TermClose', function()
before_each(function()
clear()
nvim('set_option', 'shell', nvim_dir .. '/shell-test')
- nvim('set_option', 'shellcmdflag', 'EXE')
+ command('set shellcmdflag=EXE shellredir= shellpipe= shellquote= shellxquote=')
end)
it('triggers when fast-exiting terminal job stops', function()
@@ -90,6 +90,17 @@ describe('autocmd TermClose', function()
retry(nil, nil, function() eq('3', eval('g:abuf')) end)
feed('<c-c>:qa!<cr>')
end)
+
+ it('exposes v:event.status', function()
+ command('set shellcmdflag=EXIT')
+ command('autocmd TermClose * let g:status = v:event.status')
+
+ command('terminal 0')
+ retry(nil, nil, function() eq(0, eval('g:status')) end)
+
+ command('terminal 42')
+ retry(nil, nil, function() eq(42, eval('g:status')) end)
+ end)
end)
it('autocmd TermEnter, TermLeave', function()
diff --git a/test/functional/eval/buf_functions_spec.lua b/test/functional/eval/buf_functions_spec.lua
index 06841a4521..e957e5f5af 100644
--- a/test/functional/eval/buf_functions_spec.lua
+++ b/test/functional/eval/buf_functions_spec.lua
@@ -221,9 +221,9 @@ describe('getbufvar() function', function()
eq(0, funcs.getbufvar(1, '&l:autoindent'))
eq(0, funcs.getbufvar(1, '&g:autoindent'))
-- Also works with global-only options
- eq(0, funcs.getbufvar(1, '&hidden'))
- eq(0, funcs.getbufvar(1, '&l:hidden'))
- eq(0, funcs.getbufvar(1, '&g:hidden'))
+ eq(1, funcs.getbufvar(1, '&hidden'))
+ eq(1, funcs.getbufvar(1, '&l:hidden'))
+ eq(1, funcs.getbufvar(1, '&g:hidden'))
-- Also works with window-local options
eq(0, funcs.getbufvar(1, '&number'))
eq(0, funcs.getbufvar(1, '&l:number'))
@@ -279,9 +279,9 @@ describe('setbufvar() function', function()
eq(false, winmeths.get_option(windows[3], 'number'))
eq(false, winmeths.get_option(meths.get_current_win(), 'number'))
- eq(false, meths.get_option('hidden'))
- funcs.setbufvar(1, '&hidden', true)
eq(true, meths.get_option('hidden'))
+ funcs.setbufvar(1, '&hidden', 0)
+ eq(false, meths.get_option('hidden'))
eq(false, bufmeths.get_option(buf1, 'autoindent'))
funcs.setbufvar(1, '&autoindent', true)
diff --git a/test/functional/eval/match_functions_spec.lua b/test/functional/eval/match_functions_spec.lua
index f399ef47d3..9f168c913a 100644
--- a/test/functional/eval/match_functions_spec.lua
+++ b/test/functional/eval/match_functions_spec.lua
@@ -6,7 +6,6 @@ local clear = helpers.clear
local funcs = helpers.funcs
local command = helpers.command
local exc_exec = helpers.exc_exec
-local pcall_err = helpers.pcall_err
before_each(clear)
@@ -40,13 +39,13 @@ describe('setmatches()', function()
}}, funcs.getmatches())
end)
- it('fails with -1 if highlight group is not defined', function()
- eq('Vim:E28: No such highlight group name: 1',
- pcall_err(funcs.setmatches, {{group=1, pattern=2, id=3, priority=4}}))
- eq({}, funcs.getmatches())
- eq('Vim:E28: No such highlight group name: 1',
- pcall_err(funcs.setmatches, {{group=1, pos1={2}, pos2={6}, id=3, priority=4, conceal=5}}))
- eq({}, funcs.getmatches())
+ 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())
end)
end)
diff --git a/test/functional/ex_cmds/drop_spec.lua b/test/functional/ex_cmds/drop_spec.lua
index ef53fe75e3..9d84a2d4f6 100644
--- a/test/functional/ex_cmds/drop_spec.lua
+++ b/test/functional/ex_cmds/drop_spec.lua
@@ -55,6 +55,7 @@ describe(":drop", function()
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")
diff --git a/test/functional/ex_cmds/quickfix_commands_spec.lua b/test/functional/ex_cmds/quickfix_commands_spec.lua
index 06dafa9ab9..c956a2df2d 100644
--- a/test/functional/ex_cmds/quickfix_commands_spec.lua
+++ b/test/functional/ex_cmds/quickfix_commands_spec.lua
@@ -47,6 +47,7 @@ for _, c in ipairs({'l', 'c'}) do
eq(('%s-2.res'):format(file), funcs.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(
diff --git a/test/functional/fixtures/shell-test.c b/test/functional/fixtures/shell-test.c
index b95e563932..4196716799 100644
--- a/test/functional/fixtures/shell-test.c
+++ b/test/functional/fixtures/shell-test.c
@@ -19,7 +19,7 @@ static void flush_wait(void)
static void help(void)
{
- puts("A simple implementation of a shell for testing termopen().");
+ puts("Fake shell");
puts("");
puts("Usage:");
puts(" shell-test --help");
@@ -42,6 +42,8 @@ static void help(void)
puts(" 96: foo bar");
puts(" shell-test INTERACT");
puts(" Prints \"interact $ \" to stderr, and waits for \"exit\" input.");
+ puts(" shell-test EXIT {code}");
+ puts(" Exits immediately with exit code \"{code}\".");
}
int main(int argc, char **argv)
@@ -103,7 +105,6 @@ int main(int argc, char **argv)
char input[256];
char cmd[100];
int arg;
- int input_argc;
while (1) {
fprintf(stderr, "interact $ ");
@@ -112,8 +113,7 @@ int main(int argc, char **argv)
break; // EOF
}
- input_argc = sscanf(input, "%99s %d", cmd, &arg);
- if(1 == input_argc) {
+ if(1 == sscanf(input, "%99s %d", cmd, &arg)) {
arg = 0;
}
if (strcmp(cmd, "exit") == 0) {
@@ -122,6 +122,15 @@ int main(int argc, char **argv)
fprintf(stderr, "command not found: %s\n", cmd);
}
}
+ } else if (strcmp(argv[1], "EXIT") == 0) {
+ int code = 1;
+ if (argc >= 3) {
+ if (sscanf(argv[2], "%d", &code) != 1) {
+ fprintf(stderr, "Invalid exit code: %s\n", argv[2]);
+ return 2;
+ }
+ }
+ return code;
} else {
fprintf(stderr, "Unknown first argument: %s\n", argv[1]);
return 3;
diff --git a/test/functional/helpers.lua b/test/functional/helpers.lua
index 03ef441ef3..92d802d62d 100644
--- a/test/functional/helpers.lua
+++ b/test/functional/helpers.lua
@@ -38,10 +38,16 @@ module.nvim_prog = (
module.nvim_set = (
'set shortmess+=IS background=light noswapfile noautoindent startofline'
..' laststatus=1 undodir=. directory=. viewdir=. backupdir=.'
- ..' belloff= wildoptions-=pum noshowcmd noruler nomore redrawdebug=invalid')
+ ..' belloff= wildoptions-=pum joinspaces noshowcmd noruler nomore redrawdebug=invalid')
module.nvim_argv = {
module.nvim_prog, '-u', 'NONE', '-i', 'NONE',
- '--cmd', module.nvim_set, '--embed'}
+ '--cmd', module.nvim_set,
+ '--cmd', 'unmap Y',
+ '--cmd', 'unmap <C-L>',
+ '--cmd', 'iunmap <C-U>',
+ '--cmd', 'iunmap <C-W>',
+ '--embed'}
+
-- Directory containing nvim.
module.nvim_dir = module.nvim_prog:gsub("[/\\][^/\\]+$", "")
if module.nvim_dir == module.nvim_prog then
@@ -416,7 +422,7 @@ end
-- Builds an argument list for use in clear().
--
---@see clear() for parameters.
+---@see clear() for parameters.
function module.new_argv(...)
local args = {unpack(module.nvim_argv)}
table.insert(args, '--headless')
@@ -567,7 +573,7 @@ function module.buf_lines(bufnr)
return module.exec_lua("return vim.api.nvim_buf_get_lines((...), 0, -1, false)", bufnr)
end
---@see buf_lines()
+---@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')
diff --git a/test/functional/legacy/007_ball_buffer_list_spec.lua b/test/functional/legacy/007_ball_buffer_list_spec.lua
index a180e73301..d4e4547c43 100644
--- a/test/functional/legacy/007_ball_buffer_list_spec.lua
+++ b/test/functional/legacy/007_ball_buffer_list_spec.lua
@@ -8,6 +8,9 @@ describe(':ball', function()
setup(clear)
it('is working', function()
+ -- Must disable 'hidden' so that the BufReadPost autocmd is triggered
+ -- when Xxx2 is reloaded
+ feed_command('set nohidden')
insert([[
start of test file Xxx
this is a test
@@ -18,7 +21,7 @@ describe(':ball', function()
feed('gg')
-- Write test file Xxx1
- feed('A1:.,/end of/w! Xxx1<cr>')
+ feed('A1<esc>:.,/end of/w! Xxx1<cr>')
feed_command('sp Xxx1')
feed_command('close')
diff --git a/test/functional/legacy/008_autocommands_spec.lua b/test/functional/legacy/008_autocommands_spec.lua
index 939404cb5e..002f037d09 100644
--- a/test/functional/legacy/008_autocommands_spec.lua
+++ b/test/functional/legacy/008_autocommands_spec.lua
@@ -71,6 +71,9 @@ describe('autocommands that delete and unload buffers:', function()
au BufUnload * call CloseAll()
au VimLeave * call WriteToOut()
]])
+ -- Must disable 'hidden' so that the BufUnload autocmd is triggered between
+ -- each :edit
+ command('set nohidden')
command('silent! edit Xxx2')
command('silent! edit Xxx1')
command('silent! edit Makefile') -- an existing file
diff --git a/test/functional/legacy/011_autocommands_spec.lua b/test/functional/legacy/011_autocommands_spec.lua
index 7b6f2f63e9..0fa9290f3c 100644
--- a/test/functional/legacy/011_autocommands_spec.lua
+++ b/test/functional/legacy/011_autocommands_spec.lua
@@ -129,13 +129,11 @@ describe('file reading, writing and bufnew and filter autocommands', function()
-- Will load Xtest.c.
feed_command('e! foo.c')
feed_command("au FileAppendPre *.out '[,']s/new/NEW/")
- feed_command('au FileAppendPost *.out !cat Xtest.c >>test.out')
+ feed_command('au FileAppendPost *.out !cat Xtest.c >test.out')
-- Append it to the output file.
feed_command('w>>test.out')
-- Discard all prompts and messages.
feed('<C-L>')
- -- Expect the decompressed file in the buffer.
- feed_command('e test.out')
expect([[
/*
diff --git a/test/functional/legacy/012_directory_spec.lua b/test/functional/legacy/012_directory_spec.lua
index 48dd24db9e..f666e51469 100644
--- a/test/functional/legacy/012_directory_spec.lua
+++ b/test/functional/legacy/012_directory_spec.lua
@@ -80,6 +80,7 @@ describe("'directory' option", function()
eq({ "Xtest1.swp", "Xtest3" }, ls_dir_sorted("Xtest2"))
meths.set_option('directory', 'Xtest.je')
+ command('bdelete')
command('edit Xtest2/Xtest3')
eq(true, curbufmeths.get_option('swapfile'))
poke_eventloop()
diff --git a/test/functional/legacy/arglist_spec.lua b/test/functional/legacy/arglist_spec.lua
index 67c5750033..6a2e86ccb4 100644
--- a/test/functional/legacy/arglist_spec.lua
+++ b/test/functional/legacy/arglist_spec.lua
@@ -156,10 +156,12 @@ describe('argument list commands', function()
eq({'a', 'b', 'a', 'c'}, eval('argv()'))
command('0argedit x')
eq({'x', 'a', 'b', 'a', 'c'}, eval('argv()'))
+ command('set nohidden')
command('enew! | set modified')
assert_fails('argedit y', 'E37:')
command('argedit! y')
eq({'x', 'y', 'y', 'a', 'b', 'a', 'c'}, eval('argv()'))
+ command('set hidden')
command('%argd')
command('argedit a b')
eq({'a', 'b'}, eval('argv()'))
diff --git a/test/functional/legacy/cdo_spec.lua b/test/functional/legacy/cdo_spec.lua
index 5e46431cc1..8b3216cbfd 100644
--- a/test/functional/legacy/cdo_spec.lua
+++ b/test/functional/legacy/cdo_spec.lua
@@ -91,7 +91,8 @@ describe('cdo', function()
exe "silent! 4,5" . XdoCmd
call assert_equal([], l)
- " Run commands from an unsaved buffer
+ " Run commands from an unsaved buffer when 'hidden' is unset
+ set nohidden
let v:errmsg=''
let l = []
enew
@@ -108,6 +109,7 @@ describe('cdo', function()
if subst_count != 1 || getline('.') != 'xLine1'
call add(v:errors, 'Abort command on error test failed')
endif
+ set hidden
let l = []
exe "2,2" . Xdo . "! call add(l, GetRuler())"
diff --git a/test/functional/legacy/fixeol_spec.lua b/test/functional/legacy/fixeol_spec.lua
index 50236e8617..d3ff86d349 100644
--- a/test/functional/legacy/fixeol_spec.lua
+++ b/test/functional/legacy/fixeol_spec.lua
@@ -23,8 +23,6 @@ describe('fixeol', function()
it('is working', function()
-- First write two test files – with and without trailing EOL.
- -- Use Unix fileformat for consistency.
- feed_command('set ff=unix')
feed_command('enew!')
feed('awith eol<esc>:w! XXEol<cr>')
feed_command('enew!')
@@ -40,7 +38,7 @@ describe('fixeol', function()
feed_command('e! XXNoEol')
feed('ostays without<esc>:set nofixeol<cr>')
feed_command('w! XXTestNoEol')
- feed_command('bwipe XXEol XXNoEol XXTestEol XXTestNoEol')
+ feed_command('bwipe! XXEol XXNoEol XXTestEol XXTestNoEol')
feed_command('set fixeol')
-- Append "END" to each file so that we can see what the last written char was.
diff --git a/test/functional/lua/buffer_updates_spec.lua b/test/functional/lua/buffer_updates_spec.lua
index a5b613f0b2..073927bf22 100644
--- a/test/functional/lua/buffer_updates_spec.lua
+++ b/test/functional/lua/buffer_updates_spec.lua
@@ -978,6 +978,22 @@ describe('lua: nvim_buf_attach on_bytes', function()
}
end)
+ it("visual paste", function()
+ local check_events= setup_eventcheck(verify, { "aaa {", "b", "}" })
+ -- Setting up
+ feed[[jdd]]
+ check_events {
+ { "test1", "bytes", 1, 3, 1, 0, 6, 1, 0, 2, 0, 0, 0 };
+ }
+
+ -- Actually testing
+ 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("nvim_buf_set_lines", function()
local check_events = setup_eventcheck(verify, {"AAA", "BBB"})
diff --git a/test/functional/lua/xdiff_spec.lua b/test/functional/lua/xdiff_spec.lua
new file mode 100644
index 0000000000..4f28f84c01
--- /dev/null
+++ b/test/functional/lua/xdiff_spec.lua
@@ -0,0 +1,112 @@
+local helpers = require('test.functional.helpers')(after_each)
+local clear = helpers.clear
+local exec_lua = helpers.exec_lua
+local eq = helpers.eq
+local pcall_err = helpers.pcall_err
+
+describe('xdiff bindings', function()
+ before_each(function()
+ clear()
+ end)
+
+ describe('can diff text', function()
+ before_each(function()
+ exec_lua[[
+ a1 = 'Hello\n'
+ b1 = 'Helli\n'
+
+ a2 = 'Hello\nbye\nfoo\n'
+ b2 = 'Helli\nbye\nbar\nbaz\n'
+ ]]
+ end)
+
+ it('with no callback', function()
+
+ eq(
+ table.concat({
+ '@@ -1 +1 @@',
+ '-Hello',
+ '+Helli',
+ ''
+ }, '\n'),
+ exec_lua("return vim.diff(a1, b1)")
+ )
+
+ eq(
+ table.concat({
+ '@@ -1 +1 @@',
+ '-Hello',
+ '+Helli',
+ '@@ -3 +3,2 @@',
+ '-foo',
+ '+bar',
+ '+baz',
+ ''
+ }, '\n'),
+ exec_lua("return vim.diff(a2, b2)")
+ )
+
+ end)
+
+ it('with callback', function()
+ exec_lua([[on_hunk = function(sa, ca, sb, cb)
+ exp[#exp+1] = {sa, ca, sb, cb}
+ end]])
+
+ 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[[
+ 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[[
+ exp = {}
+ assert(vim.diff(a2, b2, {on_hunk = on_hunk, result_type='indices'}) == nil)
+ return exp
+ ]])
+ end)
+
+ it('with error callback', function()
+ exec_lua([[on_hunk = function(sa, ca, sb, cb)
+ error('ERROR1')
+ end]])
+
+ eq([[Error executing lua: [string "<nvim>"]:0: 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}, {3, 1, 3, 2}},
+ exec_lua([[return vim.diff(a2, b2, {result_type = 'indices'})]]))
+ end)
+
+ end)
+
+ it('can handle bad args', function()
+ eq([[Error executing lua: [string "<nvim>"]:0: Expected at least 2 arguments]],
+ pcall_err(exec_lua, [[vim.diff('a')]]))
+
+ eq([[Error executing lua: [string "<nvim>"]:0: bad argument #1 to 'diff' (expected string)]],
+ pcall_err(exec_lua, [[vim.diff(1, 2)]]))
+
+ eq([[Error executing lua: [string "<nvim>"]:0: bad argument #3 to 'diff' (expected table)]],
+ pcall_err(exec_lua, [[vim.diff('a', 'b', true)]]))
+
+ eq([[Error executing lua: [string "<nvim>"]:0: unexpected key: bad_key]],
+ pcall_err(exec_lua, [[vim.diff('a', 'b', { bad_key = true })]]))
+
+ eq([[Error executing lua: [string "<nvim>"]:0: on_hunk is not a function]],
+ pcall_err(exec_lua, [[vim.diff('a', 'b', { on_hunk = true })]]))
+
+ end)
+end)
diff --git a/test/functional/normal/K_spec.lua b/test/functional/normal/K_spec.lua
index 174313d80e..40f36491e4 100644
--- a/test/functional/normal/K_spec.lua
+++ b/test/functional/normal/K_spec.lua
@@ -1,6 +1,6 @@
local helpers = require('test.functional.helpers')(after_each)
-local eq, clear, eval, feed =
- helpers.eq, helpers.clear, helpers.eval, helpers.feed
+local eq, clear, eval, feed, retry =
+ helpers.eq, helpers.clear, helpers.eval, helpers.feed, helpers.retry
describe('K', function()
local test_file = 'K_spec_out'
@@ -31,7 +31,7 @@ describe('K', function()
-- K on the text "K_spec_out" resolves to `!echo fnord >> K_spec_out`.
feed('i'..test_file..'<ESC>K')
- feed('<CR>') -- Press ENTER
+ retry(nil, nil, function() eq(1, eval('filereadable("'..test_file..'")')) end)
eq({'fnord'}, eval("readfile('"..test_file.."')"))
end)
diff --git a/test/functional/plugin/lsp_spec.lua b/test/functional/plugin/lsp_spec.lua
index 863176bfa9..3c4d01ae74 100644
--- a/test/functional/plugin/lsp_spec.lua
+++ b/test/functional/plugin/lsp_spec.lua
@@ -266,6 +266,8 @@ describe('LSP', function()
if isCI() then
pending('hangs the build on CI #14028, re-enable with freeze timeout #14204')
return
+ elseif helpers.skip_fragile(pending) then
+ return
end
local expected_handlers = {
{NIL, "shutdown", {}, 1, NIL};
diff --git a/test/functional/plugin/shada_spec.lua b/test/functional/plugin/shada_spec.lua
index 5663f248bf..a4d78682ad 100644
--- a/test/functional/plugin/shada_spec.lua
+++ b/test/functional/plugin/shada_spec.lua
@@ -2161,6 +2161,12 @@ describe('plugin/shada.vim', function()
reset()
wshada('\004\000\009\147\000\196\002ab\196\001a')
wshada_tmp('\004\000\009\147\000\196\002ab\196\001b')
+
+ -- Need to set nohidden so that the buffer containing 'fname' is not unloaded
+ -- after loading 'fname_tmp', otherwise the '++opt not supported' test below
+ -- won't work since the BufReadCmd autocmd won't be triggered.
+ nvim_command('set nohidden')
+
nvim_command('edit ' .. fname)
eq({
'History entry with timestamp ' .. epoch .. ':',
diff --git a/test/functional/treesitter/node_spec.lua b/test/functional/treesitter/node_spec.lua
new file mode 100644
index 0000000000..21c287644e
--- /dev/null
+++ b/test/functional/treesitter/node_spec.lua
@@ -0,0 +1,62 @@
+local helpers = require('test.functional.helpers')(after_each)
+
+local clear = helpers.clear
+local eq = helpers.eq
+local exec_lua = helpers.exec_lua
+local insert = helpers.insert
+local pending_c_parser = helpers.pending_c_parser
+
+before_each(clear)
+
+local function lua_eval(lua_expr)
+ return exec_lua("return " .. lua_expr)
+end
+
+describe('treesitter node API', function()
+ clear()
+
+ if pending_c_parser(pending) then
+ return
+ end
+
+ it('can move between siblings', function()
+ insert([[
+ int main(int x, int y, int z) {
+ return x + y * z
+ }
+ ]])
+
+ exec_lua([[
+ query = require"vim.treesitter.query"
+ parser = vim.treesitter.get_parser(0, "c")
+ tree = parser:parse()[1]
+ root = tree:root()
+ lang = vim.treesitter.inspect_language('c')
+
+ function node_text(node)
+ return query.get_node_text(node, 0)
+ end
+ ]])
+
+ exec_lua 'node = root:descendant_for_range(0, 11, 0, 16)'
+ eq('int x', lua_eval('node_text(node)'))
+
+ exec_lua 'node = node:next_sibling()'
+ eq(',', lua_eval('node_text(node)'))
+
+ exec_lua 'node = node:next_sibling()'
+ eq('int y', lua_eval('node_text(node)'))
+
+ exec_lua 'node = node:prev_sibling()'
+ eq(',', lua_eval('node_text(node)'))
+
+ exec_lua 'node = node:prev_sibling()'
+ eq('int x', lua_eval('node_text(node)'))
+
+ exec_lua 'node = node:next_named_sibling()'
+ eq('int y', lua_eval('node_text(node)'))
+
+ exec_lua 'node = node:prev_named_sibling()'
+ eq('int x', lua_eval('node_text(node)'))
+ end)
+end)
diff --git a/test/functional/ui/float_spec.lua b/test/functional/ui/float_spec.lua
index 51ee922d23..be22d9a403 100644
--- a/test/functional/ui/float_spec.lua
+++ b/test/functional/ui/float_spec.lua
@@ -74,7 +74,8 @@ describe('float window', function()
funcs.win_execute(win, 'bwipe!')
end)
- it('win_execute() call commands that not allowed' , function()
+ 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})
diff --git a/test/functional/ui/highlight_spec.lua b/test/functional/ui/highlight_spec.lua
index 7471255345..499aeba6ec 100644
--- a/test/functional/ui/highlight_spec.lua
+++ b/test/functional/ui/highlight_spec.lua
@@ -912,6 +912,97 @@ describe('CursorLine highlight', function()
]])
end)
+ it("'cursorlineopt' screenline", function()
+ 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};
+ })
+ screen:attach()
+
+ feed_command('set wrap cursorline cursorlineopt=screenline')
+ feed_command('set showbreak=>>>')
+ feed_command('highlight clear NonText')
+ feed_command('highlight clear CursorLine')
+ feed_command('highlight NonText guifg=Yellow gui=NONE')
+ feed_command('highlight LineNr guifg=Red guibg=Green gui=NONE')
+ feed_command('highlight CursorLine guifg=Black guibg=White gui=NONE')
+ feed_command('highlight CursorLineNr guifg=Green guibg=Red gui=NONE')
+
+ feed('30iø<esc>o<esc>30ia<esc>')
+
+ -- CursorLine should not apply to 'showbreak' when 'cursorlineopt' contains "screenline"
+ screen:expect([[
+ øøøøøøøøøøøøøøøøøøøø|
+ {2:>>>}øøøøøøøøøø |
+ aaaaaaaaaaaaaaaaaaaa|
+ {2:>>>}{1:aaaaaaaaa^a }|
+ |
+ ]])
+ feed('gk')
+ screen:expect([[
+ øøøøøøøøøøøøøøøøøøøø|
+ {2:>>>}øøøøøøøøøø |
+ {1:aaaaaaaaaaaa^aaaaaaaa}|
+ {2:>>>}aaaaaaaaaa |
+ |
+ ]])
+ feed('k')
+ screen:expect([[
+ {1:øøøøøøøøøøøø^øøøøøøøø}|
+ {2:>>>}øøøøøøøøøø |
+ aaaaaaaaaaaaaaaaaaaa|
+ {2:>>>}aaaaaaaaaa |
+ |
+ ]])
+
+ -- CursorLineNr should not apply to line number when 'cursorlineopt' does not contain "number"
+ feed_command('set relativenumber numberwidth=2')
+ screen:expect([[
+ {3:0 }{1:øøøøøøøøøøøø^øøøøøø}|
+ {3: }{2:>>>}øøøøøøøøøøøø |
+ {3:1 }aaaaaaaaaaaaaaaaaa|
+ {3: }{2:>>>}aaaaaaaaaaaa |
+ |
+ ]])
+
+ -- CursorLineNr should apply to line number when 'cursorlineopt' contains "number"
+ feed_command('set cursorlineopt+=number')
+ screen:expect([[
+ {4:0 }{1:øøøøøøøøøøøø^øøøøøø}|
+ {3: }{2:>>>}øøøøøøøøøøøø |
+ {3:1 }aaaaaaaaaaaaaaaaaa|
+ {3: }{2:>>>}aaaaaaaaaaaa |
+ |
+ ]])
+ feed('gj')
+ screen:expect([[
+ {4:0 }øøøøøøøøøøøøøøøøøø|
+ {3: }{2:>>>}{1:øøøøøøøøø^øøø }|
+ {3:1 }aaaaaaaaaaaaaaaaaa|
+ {3: }{2:>>>}aaaaaaaaaaaa |
+ |
+ ]])
+ feed('gj')
+ screen:expect([[
+ {3:1 }øøøøøøøøøøøøøøøøøø|
+ {3: }{2:>>>}øøøøøøøøøøøø |
+ {4:0 }{1:aaaaaaaaaaaa^aaaaaa}|
+ {3: }{2:>>>}aaaaaaaaaaaa |
+ |
+ ]])
+ feed('gj')
+ screen:expect([[
+ {3:1 }øøøøøøøøøøøøøøøøøø|
+ {3: }{2:>>>}øøøøøøøøøøøø |
+ {4:0 }aaaaaaaaaaaaaaaaaa|
+ {3: }{2:>>>}{1:aaaaaaaaa^aaa }|
+ |
+ ]])
+ end)
+
it('always updated. vim-patch:8.1.0849', function()
local screen = Screen.new(50,5)
screen:set_default_attr_ids({
diff --git a/test/functional/ui/tabline_spec.lua b/test/functional/ui/tabline_spec.lua
index ab8d63cda1..809486d4db 100644
--- a/test/functional/ui/tabline_spec.lua
+++ b/test/functional/ui/tabline_spec.lua
@@ -69,6 +69,7 @@ describe('ui/ext_tabline', function()
command("bnext")
local expected_buffers = {
+ {buffer = { id = 1 }, name = '[No Name]'},
{buffer = { id = 2 }, name = 'another-buffer'},
}
screen:expect{grid=[[
diff --git a/test/helpers.lua b/test/helpers.lua
index 12d9f19187..469aee53f0 100644
--- a/test/helpers.lua
+++ b/test/helpers.lua
@@ -58,9 +58,9 @@ local check_logs_useless_lines = {
--- Invokes `fn` and includes the tail of `logfile` in the error message if it
--- fails.
---
---@param logfile Log file, defaults to $NVIM_LOG_FILE or '.nvimlog'
---@param fn Function to invoke
---@param ... Function arguments
+---@param logfile Log file, defaults to $NVIM_LOG_FILE or '.nvimlog'
+---@param fn Function to invoke
+---@param ... Function arguments
local function dumplog(logfile, fn, ...)
-- module.validate({
-- logfile={logfile,'s',true},
@@ -102,8 +102,8 @@ end
--- Asserts that `pat` matches one or more lines in the tail of $NVIM_LOG_FILE.
---
---@param pat (string) Lua pattern to search for in the log file.
---@param logfile (string, default=$NVIM_LOG_FILE) full path to log file.
+---@param pat (string) Lua pattern to search for in the log file.
+---@param logfile (string, default=$NVIM_LOG_FILE) full path to log file.
function module.assert_log(pat, logfile)
logfile = logfile or os.getenv('NVIM_LOG_FILE') or '.nvimlog'
local nrlines = 10
diff --git a/test/unit/preprocess.lua b/test/unit/preprocess.lua
index 3786bc2122..1073855a7d 100644
--- a/test/unit/preprocess.lua
+++ b/test/unit/preprocess.lua
@@ -89,10 +89,6 @@ local Gcc = {
get_defines_extra_flags = {'-std=c99', '-dM', '-E'},
get_declarations_extra_flags = {'-std=c99', '-P', '-E'},
}
-if ffi.abi("32bit") then
- table.insert(Gcc.get_defines_extra_flags, '-m32')
- table.insert(Gcc.get_declarations_extra_flags, '-m32')
-end
function Gcc:define(name, args, val)
local define = '-D' .. name