aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/ISSUE_TEMPLATE/bug_report.yml46
-rw-r--r--.github/ISSUE_TEMPLATE/config.yml2
-rw-r--r--.github/ISSUE_TEMPLATE/feature_request.yml3
-rw-r--r--.github/ISSUE_TEMPLATE/lsp_bug_report.yml50
-rw-r--r--CONTRIBUTING.md79
-rw-r--r--README.md4
-rw-r--r--runtime/doc/autocmd.txt2
-rw-r--r--runtime/doc/develop.txt14
-rw-r--r--runtime/doc/eval.txt1
-rw-r--r--runtime/doc/lsp.txt22
-rw-r--r--runtime/doc/lua.txt74
-rw-r--r--runtime/doc/nvim_terminal_emulator.txt4
-rw-r--r--runtime/doc/options.txt21
-rw-r--r--runtime/doc/various.txt16
-rw-r--r--runtime/filetype.vim9
-rw-r--r--runtime/lua/vim/F.lua4
-rw-r--r--runtime/lua/vim/highlight.lua14
-rw-r--r--runtime/lua/vim/lsp.lua296
-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.lua70
-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.lua4
-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.lua20
-rw-r--r--runtime/lua/vim/treesitter/highlighter.lua6
-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--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.c6
-rw-r--r--src/nvim/buffer.c7
-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.c42
-rw-r--r--src/nvim/ex_getln.c19
-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/getchar.c1
-rw-r--r--src/nvim/highlight.c58
-rw-r--r--src/nvim/lua/executor.c23
-rw-r--r--src/nvim/lua/treesitter.c18
-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.c6
-rw-r--r--src/nvim/map.c48
-rw-r--r--src/nvim/map.h21
-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.c25
-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.c147
-rw-r--r--src/nvim/search.c236
-rw-r--r--src/nvim/spell.c6
-rw-r--r--src/nvim/spellfile.c2
-rw-r--r--src/nvim/syntax.c251
-rw-r--r--src/nvim/tag.c43
-rw-r--r--src/nvim/terminal.c39
-rw-r--r--src/nvim/testdir/test_filetype.vim18
-rw-r--r--src/nvim/testdir/test_normal.vim2
-rw-r--r--src/nvim/undo.c6
-rw-r--r--src/nvim/window.c17
-rw-r--r--test/functional/api/window_spec.lua15
-rw-r--r--test/functional/autocmd/termxx_spec.lua13
-rw-r--r--test/functional/fixtures/shell-test.c17
-rw-r--r--test/functional/helpers.lua4
-rw-r--r--test/functional/lua/xdiff_spec.lua112
-rw-r--r--test/functional/normal/K_spec.lua6
-rw-r--r--test/helpers.lua10
95 files changed, 2148 insertions, 1592 deletions
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
index 35b9e23489..796707be03 100644
--- a/.github/ISSUE_TEMPLATE/config.yml
+++ b/.github/ISSUE_TEMPLATE/config.yml
@@ -2,4 +2,4 @@ blank_issues_enabled: true
contact_links:
- name: Question
url: https://neovim.discourse.group/
- about: Please ask and answer questions about Neovim on Discourse.
+ 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/CONTRIBUTING.md b/CONTRIBUTING.md
index 7e362ddd82..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 draft 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.
@@ -68,21 +68,19 @@ Pull requests have two stages: Draft and Ready for review.
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.
-You can convert the state of your PR back to Draft (or Ready for review) at any
-time. You can also skip the Draft stage if your PR is ready for review from the
-beginning.
-
-Do __not__ add any labels like `[RFC]` or `[WIP]` in the title to indicate the
+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 by default; if you want feedback from specific people, `@`-ping
-them in a comment.
+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>
@@ -92,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.
@@ -282,9 +264,8 @@ 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
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/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/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 a76298c86c..e02d80252f 100644
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -1641,6 +1641,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/lsp.txt b/runtime/doc/lsp.txt
index 4d32be97d3..b04d9c267a 100644
--- a/runtime/doc/lsp.txt
+++ b/runtime/doc/lsp.txt
@@ -1510,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.
@@ -1526,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
@@ -1966,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)
@@ -1999,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
@@ -2007,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
@@ -2014,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
@@ -2197,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 fd1bedd8ef..28667d5bd1 100644
--- a/runtime/doc/lua.txt
+++ b/runtime/doc/lua.txt
@@ -616,6 +616,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', {hunk_lines = true})
+ -->
+ {
+ {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*
@@ -1110,7 +1177,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
@@ -1119,6 +1188,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 10b849aa3e..364d4c5167 100644
--- a/runtime/doc/options.txt
+++ b/runtime/doc/options.txt
@@ -3080,17 +3080,16 @@ A jump table for the options with a short description can be found at |Q_op|.
*'hidden'* *'hid'* *'nohidden'* *'nohid'*
'hidden' 'hid' boolean (default on)
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!".
+ 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)
diff --git a/runtime/doc/various.txt b/runtime/doc/various.txt
index 162909ce45..62e1e130ee 100644
--- a/runtime/doc/various.txt
+++ b/runtime/doc/various.txt
@@ -460,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/filetype.vim b/runtime/filetype.vim
index 9c75a49ac1..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
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 ca8db73d43..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,14 +205,14 @@ 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' };
@@ -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
@@ -426,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
@@ -548,16 +548,16 @@ end
---
--- The following parameters describe fields in the {config} table.
---
---@param root_dir: (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:
@@ -565,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.
@@ -573,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
@@ -617,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)
@@ -657,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)
@@ -682,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)
@@ -698,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 })
@@ -717,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
@@ -766,7 +766,7 @@ 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';
@@ -869,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)
@@ -900,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)
@@ -936,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 })
@@ -963,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)
@@ -1000,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
@@ -1025,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
@@ -1076,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};
@@ -1158,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
@@ -1190,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
@@ -1207,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
@@ -1238,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.
@@ -1296,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
@@ -1337,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)
@@ -1366,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 };
@@ -1385,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)
@@ -1438,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
@@ -1447,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 = {}
@@ -1472,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)
@@ -1484,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
@@ -1495,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 a244e3d6a4..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
@@ -512,7 +512,7 @@ local _next_diagnostic = function(position, search_forward, bufnr, opts, client_
end
end
---@private
+---@private
--- Helper function to return a position from a diagnostic
---
---@return table {row, col}
@@ -527,7 +527,7 @@ local function _diagnostic_pos(opts, diagnostic)
return to_position(diagnostic.range.start, bufnr)
end
---@private
+---@private
-- Move to the diagnostic position
local function _diagnostic_move_pos(name, opts, pos)
opts = opts or {}
@@ -858,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
@@ -924,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)
@@ -1054,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)
@@ -1084,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
@@ -1101,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
@@ -1187,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
@@ -1410,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.
@@ -1429,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..ded8af5773 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\+//]]
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..a09e0a9cf7 100644
--- a/runtime/lua/vim/treesitter.lua
+++ b/runtime/lua/vim/treesitter.lua
@@ -28,9 +28,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 +71,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 +97,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 bf5bd791c3..22b528838c 100644
--- a/runtime/lua/vim/treesitter/highlighter.lua
+++ b/runtime/lua/vim/treesitter/highlighter.lua
@@ -122,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)
@@ -217,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/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 400dbb126c..90c43a1b04 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
@@ -1568,14 +1562,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;
}
@@ -1590,7 +1584,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 bec9808183..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);
diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c
index 29d4fc786a..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) {
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 789936fdff..5e18a77b6d 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -265,7 +265,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",
@@ -326,7 +326,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);
@@ -4883,7 +4882,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);
@@ -4893,7 +4892,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);
})
}
@@ -7304,7 +7303,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)
@@ -7331,9 +7330,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);
}
@@ -7413,7 +7412,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;
}
@@ -7435,7 +7434,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);
}
@@ -7449,7 +7448,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 0c099085a0..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 {
/*
@@ -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_getln.c b/src/nvim/ex_getln.c
index 7cab3eb650..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;
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/getchar.c b/src/nvim/getchar.c
index 2b6c5b9f37..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
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 5799c3ee98..cbc2273bc9 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 2dfcd9a958..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"
@@ -105,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)
{
@@ -123,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);
@@ -137,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;
}
@@ -146,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;
}
@@ -189,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;
@@ -199,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);
}
@@ -247,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);
}
@@ -1175,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 136608afdf..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,13 +157,10 @@ 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.
highlight_init();
- syntax_init();
#ifdef WIN32
OSVERSIONINFO ovi;
diff --git a/src/nvim/map.c b/src/nvim/map.c
index 86dc257e40..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)
@@ -199,7 +191,7 @@ 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 a35a2c1672..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); \
@@ -45,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;
@@ -58,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
@@ -68,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)
@@ -80,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 2a530db934..7b2f77a6f9 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..178b454e4e 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" */
}
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 e4030b76a3..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
@@ -2430,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) {
@@ -2562,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) {
@@ -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)
@@ -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 b712e09861..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)
@@ -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 1d45df8ebd..bdbbc4aacf 100644
--- a/src/nvim/syntax.c
+++ b/src/nvim/syntax.c
@@ -91,7 +91,7 @@ typedef struct hl_group {
// builtin |highlight-groups|
static garray_T highlight_ga = GA_EMPTY_INIT_VALUE;
-Map(cstr_t, int) *highlight_unames;
+Map(cstr_t, int) highlight_unames = MAP_INIT;
static inline struct hl_group * HL_TABLE(void)
{
@@ -365,31 +365,26 @@ 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)
-void syntax_init(void)
-{
- highlight_unames = map_new(cstr_t, int)();
-}
-
// Set the timeout used for syntax highlighting.
// Use NULL to reset, no timeout.
void syn_set_timeout(proftime_T *tm)
@@ -815,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;
@@ -886,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;
/*
@@ -894,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();
}
@@ -903,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
@@ -946,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)
@@ -958,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();
@@ -1157,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;
@@ -1185,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;
+ }
}
}
@@ -1209,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;
@@ -1345,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;
}
@@ -1390,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;
@@ -1402,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. */
@@ -1449,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;
}
/*
@@ -1495,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;
/*
@@ -1525,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.
@@ -1683,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;
}
/*
@@ -2157,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;
}
}
@@ -2174,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;
}
/*
@@ -2214,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;
@@ -2321,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);
@@ -2341,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
@@ -2457,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;
@@ -2576,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 */
@@ -2758,7 +2746,7 @@ find_endpos(
*flagsp = spp->sp_flags;
- had_match = TRUE;
+ had_match = true;
break;
}
@@ -2821,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) {
@@ -2872,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) {
@@ -2896,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);
}
/*
@@ -2908,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();
@@ -4247,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)
@@ -4547,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;
@@ -4607,7 +4595,7 @@ syn_cmd_region(
}
rest = skipwhite(rest + 1);
if (*rest == NUL) {
- not_enough = TRUE;
+ not_enough = true;
break;
}
@@ -4618,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;
}
}
@@ -4712,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
}
}
}
@@ -5865,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)
@@ -6426,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;
@@ -6467,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
@@ -7119,7 +7108,7 @@ void free_highlight(void)
xfree(HL_TABLE()[i].sg_name_u);
}
ga_clear(&highlight_ga);
- map_free(cstr_t, int)(highlight_unames);
+ map_destroy(cstr_t, int)(&highlight_unames);
}
#endif
@@ -7137,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
@@ -7505,7 +7493,7 @@ int syn_name2id_len(const char_u *name, size_t len)
// 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);
+ return map_get(cstr_t, int)(&highlight_unames, name_u);
}
/// Lookup a highlight group name and return its attributes.
@@ -7609,7 +7597,7 @@ static int syn_add_group(char_u *name)
int id = highlight_ga.ga_len; // ID is index plus one
- map_put(cstr_t, int)(highlight_unames, name_up, id);
+ map_put(cstr_t, int)(&highlight_unames, name_up, id);
return id;
}
@@ -7620,7 +7608,7 @@ static void syn_unadd_group(void)
{
highlight_ga.ga_len--;
HlGroup *item = &HL_TABLE()[highlight_ga.ga_len];
- map_del(cstr_t, int)(highlight_unames, item->sg_name_u);
+ map_del(cstr_t, int)(&highlight_unames, item->sg_name_u);
xfree(item->sg_name);
xfree(item->sg_name_u);
}
@@ -7883,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..a971849f4c 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)
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/test_filetype.vim b/src/nvim/testdir/test_filetype.vim
index c155dbad50..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'],
@@ -809,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_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/undo.c b/src/nvim/undo.c
index c4b48a6ee2..e1a7dbb2d3 100644
--- a/src/nvim/undo.c
+++ b/src/nvim/undo.c
@@ -2762,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/window.c b/src/nvim/window.c
index fefbab822e..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"
@@ -2605,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.
@@ -2710,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;
@@ -3601,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();
@@ -3616,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);
@@ -4545,7 +4548,7 @@ static win_T *win_alloc(win_T *after, bool hidden)
win_T *new_wp = xcalloc(1, sizeof(win_T));
new_wp->handle = ++last_win_id;
- handle_register_window(new_wp);
+ pmap_put(handle_T)(&window_handles, new_wp->handle, new_wp);
grid_assign_handle(&new_wp->w_grid_alloc);
@@ -4616,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. */
diff --git a/test/functional/api/window_spec.lua b/test/functional/api/window_spec.lua
index e4aa1dae8e..c49d6405f4 100644
--- a/test/functional/api/window_spec.lua
+++ b/test/functional/api/window_spec.lua
@@ -347,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/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 5974e8897f..92d802d62d 100644
--- a/test/functional/helpers.lua
+++ b/test/functional/helpers.lua
@@ -422,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')
@@ -573,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/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/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