mirror of
https://github.com/neovim/neovim.git
synced 2024-09-17 20:58:20 -04:00
Compare commits
53 Commits
5e0d065614
...
0313615e9d
Author | SHA1 | Date | |
---|---|---|---|
|
0313615e9d | ||
|
9f15a18fa5 | ||
|
4ffc20c951 | ||
|
a2070ba877 | ||
|
be5cf33836 | ||
|
a060c13f55 | ||
|
758504ec73 | ||
|
4f788f78f8 | ||
|
ca9f6f5694 | ||
|
1dd6a56409 | ||
|
77dd1837ae | ||
|
5e5b004da4 | ||
|
7db83d47b2 | ||
|
d62b3fa623 | ||
|
f1e51528d2 | ||
|
15e77a56b7 | ||
|
af6537bc66 | ||
|
eee52d3427 | ||
|
d6f7fa14c5 | ||
|
5b1b765610 | ||
|
b0e85010fe | ||
|
ba7a52dedc | ||
|
56ae85a33c | ||
|
e39b6d0c52 | ||
|
50cd5ed360 | ||
|
4ddd999f65 | ||
|
095f731af0 | ||
|
01e82eba20 | ||
|
47cd532bf1 | ||
|
1bc7e18aa8 | ||
|
6d86a6fe44 | ||
|
a757195a60 | ||
|
d85f180f26 | ||
|
7bb0dd08db | ||
|
cf140fb25b | ||
|
74e695d227 | ||
|
9d48266bed | ||
|
2cd76a758b | ||
|
17b298b7c8 | ||
|
5ca330859c | ||
|
e35ae6fbc2 | ||
|
bf9e92c81c | ||
|
7367838359 | ||
|
38bb0e1da8 | ||
|
c2433589dc | ||
|
0892c080d1 | ||
|
6f49ed58c3 | ||
|
a9df0c5ce6 | ||
|
28d1640dd6 | ||
|
65b1fd00a7 | ||
|
eca72def1f | ||
|
7421a4d8b5 | ||
|
b7e3003106 |
@ -58,6 +58,11 @@ aa4f9c5341f5280f16cce0630ea54b84eef717b3
|
||||
6ff245732a5a8ab821598a38fb0c5805e6bd3779
|
||||
abf758a2977c4e6cab4dfa217f56da853d85851c
|
||||
cb84f5ee530f0f32b92bed5b4ad41344e8b551aa
|
||||
f98b8d2d44d289263b1a3b33b6a7f20644ef671c
|
||||
544ef994df72c3cbe0dca6b856ce2dcbc5169767
|
||||
45fe4d11add933df76a2ea4bf52ce8904f4a778b
|
||||
517f0cc634b985057da5b95cf4ad659ee456a77e
|
||||
04f2f864e270e772c6326cefdf24947f0130e492
|
||||
|
||||
# typos
|
||||
d238b8f6003d34cae7f65ff7585b48a2cd9449fb
|
||||
|
9
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
9
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
@ -8,11 +8,11 @@ body:
|
||||
value: |
|
||||
*Before reporting:*
|
||||
- Confirm the problem is reproducible on [**master**](https://github.com/neovim/neovim/releases/nightly) or [**latest stable**](https://github.com/neovim/neovim/releases/stable) release
|
||||
- run `make distclean` when encountering build issues
|
||||
- search [existing issues](https://github.com/neovim/neovim/issues?q=is%3Aissue+is%3Aopen+label%3Abug)
|
||||
- check the [FAQ](https://github.com/neovim/neovim/wiki/FAQ)
|
||||
- Run `make distclean` when encountering build issues
|
||||
- Search [existing issues](https://github.com/neovim/neovim/issues?q=is%3Aissue+is%3Aopen+label%3Abug,bug-crash) (including [closed](https://github.com/neovim/neovim/issues?q=is%3Aissue+is%3Aclosed+label%3Abug%2Cbug-crash))
|
||||
- Read the [FAQ](https://neovim.io/doc/user/faq.html) and ["Reporting Problems" in CONTRIBUTING.md](https://github.com/neovim/neovim/blob/master/CONTRIBUTING.md#reporting-problems).
|
||||
|
||||
Usage or "How to" questions belong on the [stackoverflow](https://vi.stackexchange.com/) and will be closed.
|
||||
Usage or "How to" questions belong on [stackoverflow](https://vi.stackexchange.com/) and will be closed.
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: "Problem"
|
||||
@ -24,6 +24,7 @@ body:
|
||||
label: "Steps to reproduce"
|
||||
description: |
|
||||
- For build failures: list the exact steps including CMake flags (if any).
|
||||
- If the bug pertains to crashing (or segfault), please include a [stacktrace](https://neovim.io/doc/user/dev_tools.html#dev-tools-backtrace).
|
||||
- For startup or shell-related problems: try `env -i TERM=ansi-256color "$(which nvim)"`.
|
||||
- Use the provided [minimal reproduction template](https://github.com/neovim/neovim/blob/master/contrib/minimal.lua) to create a minimal configuration. After you fill it out with necessary information, run with `nvim --clean -u minimal.lua`.
|
||||
- Please do **not** include a package manager in the reproduction steps.
|
||||
|
2
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
2
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
@ -6,7 +6,7 @@ body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Before requesting: search [existing issues](https://github.com/neovim/neovim/labels/enhancement) and check the [FAQ](https://github.com/neovim/neovim/wiki/FAQ).
|
||||
Before requesting: search [existing feature requests](https://github.com/neovim/neovim/labels/enhancement) and check the [FAQ](https://neovim.io/doc/user/faq.html).
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
|
2
.github/ISSUE_TEMPLATE/lsp_bug_report.yml
vendored
2
.github/ISSUE_TEMPLATE/lsp_bug_report.yml
vendored
@ -6,7 +6,7 @@ body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
_Before reporting:_ search [existing issues](https://github.com/neovim/neovim/issues?q=is%3Aissue+is%3Aopen+label%3Abug) and check the [FAQ](https://github.com/neovim/neovim/wiki/FAQ). Usage questions or "Why isn't X language server/feature working?" belong on [stackoverflow](https://vi.stackexchange.com/) and will be closed.
|
||||
_Before reporting:_ search [existing issues](https://github.com/neovim/neovim/issues?q=is%3Aissue+is%3Aopen+label%3Abug) and check the [FAQ](https://neovim.io/doc/user/faq.html). Usage questions or "Why isn't X language server/feature working?" belong on [stackoverflow](https://vi.stackexchange.com/) and will be closed.
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
|
5
.github/workflows/docs.yml
vendored
5
.github/workflows/docs.yml
vendored
@ -7,6 +7,8 @@ on:
|
||||
- 'src/nvim/eval.lua'
|
||||
- 'runtime/lua/**.lua'
|
||||
- 'runtime/doc/**'
|
||||
- 'scripts/gen_vimdoc.py'
|
||||
- 'scripts/gen_help_html.lua'
|
||||
jobs:
|
||||
docs:
|
||||
runs-on: ubuntu-latest
|
||||
@ -30,3 +32,6 @@ jobs:
|
||||
echo "::error::The doc generation produces the following changes:"
|
||||
git diff --color --exit-code
|
||||
fi
|
||||
|
||||
- name: Validate docs
|
||||
run: make lintdoc
|
||||
|
2
.github/workflows/notes.md
vendored
2
.github/workflows/notes.md
vendored
@ -48,7 +48,7 @@ https://github.com/neovim/neovim-releases.
|
||||
|
||||
### Other
|
||||
|
||||
- Install by [package manager](https://github.com/neovim/neovim/wiki/Installing-Neovim)
|
||||
- Install by [package manager](https://github.com/neovim/neovim/blob/master/INSTALL.md#install-from-package)
|
||||
|
||||
## SHA256 Checksums
|
||||
|
||||
|
@ -161,6 +161,7 @@ endif()
|
||||
|
||||
option(ENABLE_ASAN_UBSAN "Enable Clang address & undefined behavior sanitizer for nvim binary." OFF)
|
||||
option(ENABLE_MSAN "Enable Clang memory sanitizer for nvim binary." OFF)
|
||||
# TSAN exists to test Luv threads.
|
||||
option(ENABLE_TSAN "Enable Clang thread sanitizer for nvim binary." OFF)
|
||||
|
||||
if((ENABLE_ASAN_UBSAN AND ENABLE_MSAN)
|
||||
@ -263,7 +264,7 @@ add_custom_target(lintcommit
|
||||
add_dependencies(lintcommit nvim_bin)
|
||||
|
||||
add_custom_target(lint)
|
||||
add_dependencies(lint lintc lintlua lintsh lintcommit)
|
||||
add_dependencies(lint lintc lintlua lintsh lintcommit lintdoc)
|
||||
|
||||
# Format
|
||||
add_glob_target(
|
||||
|
@ -24,8 +24,8 @@ Reporting problems
|
||||
- If a specific configuration or plugin is necessary to recreate the problem, use the minimal template in `contrib/minimal.lua` with `nvim --clean -u contrib/minimal.lua` after making the necessary changes.
|
||||
- [Bisect](https://neovim.io/doc/user/starting.html#bisect) your config: disable plugins incrementally, to narrow down the cause of the issue.
|
||||
- [Bisect][git-bisect] Neovim's source code to find the cause of a regression, if you can. This is _extremely_ helpful.
|
||||
- When reporting a crash, [include a stacktrace](https://neovim.io/doc/user/faq.html#backtrace-linux).
|
||||
- Use [ASAN/UBSAN](#clang-sanitizers-asan-and-ubsan) to get detailed errors for segfaults and undefined behavior.
|
||||
- When reporting a crash, [include a stacktrace](https://neovim.io/doc/user/dev_tools.html#dev-tools-backtrace).
|
||||
- Use [ASAN/UBSAN](#sanitizers-asan-and-ubsan) to get detailed errors for segfaults and undefined behavior.
|
||||
- Check the logs. `:edit $NVIM_LOG_FILE`
|
||||
- Include `cmake --system-information` for build-related issues.
|
||||
|
||||
@ -265,6 +265,12 @@ Many `:help` docs are autogenerated from (C or Lua) docstrings. To generate the
|
||||
make doc
|
||||
```
|
||||
|
||||
To validate the documentation files, run:
|
||||
|
||||
```bash
|
||||
make lintdoc
|
||||
```
|
||||
|
||||
If you need to modify or debug the documentation flow, these are the main files:
|
||||
- `./scripts/gen_vimdoc.py`:
|
||||
Main doc generator. Drives doxygen to generate xml files, and scrapes those
|
||||
@ -282,6 +288,8 @@ If you need to modify or debug the documentation flow, these are the main files:
|
||||
src/nvim/options.lua => runtime/doc/options.txt
|
||||
```
|
||||
|
||||
- `./scripts/lintdoc.lua`: Validation and linting of documentation files.
|
||||
|
||||
### Lua docstrings
|
||||
|
||||
Use [LuaLS] annotations in Lua docstrings to annotate parameter types, return
|
||||
|
@ -225,6 +225,15 @@ https://github.com/neovim/neovim-backup
|
||||
trying to produce images that work in the broadest number of environments,
|
||||
and therefore want to use older releases.
|
||||
|
||||
### Special labels
|
||||
|
||||
Some github labels are used to trigger certain jobs:
|
||||
|
||||
* `backport release-x.y` - backport to release branch
|
||||
* `ci-s390x` - enable s390x CI
|
||||
* `needs:response` - Close PR after a certain amount of time if author doesn't
|
||||
respond
|
||||
|
||||
See also
|
||||
--------
|
||||
|
||||
|
2
Makefile
2
Makefile
@ -117,7 +117,7 @@ functionaltest-lua: | nvim
|
||||
$(BUILD_TOOL) -C build functionaltest
|
||||
|
||||
FORMAT=formatc formatlua format
|
||||
LINT=lintlua lintsh lintc clang-analyzer lintcommit lint
|
||||
LINT=lintlua lintsh lintc clang-analyzer lintcommit lintdoc lint
|
||||
TEST=functionaltest unittest
|
||||
generated-sources benchmark $(FORMAT) $(LINT) $(TEST) doc: | build/.ran-cmake
|
||||
$(CMAKE) --build build --target $@
|
||||
|
@ -231,7 +231,7 @@ if vim.o.background == 'light' then
|
||||
hi('SpellRare', { sp = 'Magenta', undercurl = true, ctermbg = 'LightMagenta' })
|
||||
hi('TabLine', { bg = 'LightGrey', underline = true, ctermfg = 'Black', ctermbg = 'LightGrey', cterm = { underline = true } })
|
||||
hi('Title', { fg = 'Magenta', bold = true, ctermfg = 'DarkMagenta' })
|
||||
hi('Visual', { bg = 'LightGrey', ctermbg = 'LightGrey' })
|
||||
hi('Visual', { bg = 'LightGrey', ctermfg = 'White', ctermbg = 'DarkGrey' })
|
||||
hi('WarningMsg', { fg = 'Red', ctermfg = 'DarkRed' })
|
||||
hi('Comment', { fg = 'Blue', ctermfg = 'DarkBlue' })
|
||||
hi('Constant', { fg = 'Magenta', ctermfg = 'DarkRed' })
|
||||
@ -270,7 +270,7 @@ else
|
||||
hi('SpellRare', { sp = 'Magenta', undercurl = true, ctermbg = 'Magenta' })
|
||||
hi('TabLine', { bg = 'DarkGrey', underline = true, ctermfg = 'White', ctermbg = 'DarkGrey', cterm = { underline = true } })
|
||||
hi('Title', { fg = 'Magenta', bold = true, ctermfg = 'LightMagenta' })
|
||||
hi('Visual', { bg = 'DarkGrey', ctermbg = 'DarkGrey' })
|
||||
hi('Visual', { bg = '#575757', ctermfg = 'Black', ctermbg = 'Grey' })
|
||||
hi('WarningMsg', { fg = 'Red', ctermfg = 'LightRed' })
|
||||
hi('Comment', { fg = '#80a0ff', ctermfg = 'Cyan' })
|
||||
hi('Constant', { fg = '#ffa0a0', ctermfg = 'Magenta' })
|
||||
|
@ -3336,6 +3336,13 @@ nvim_tabpage_set_var({tabpage}, {name}, {value})
|
||||
• {name} Variable name
|
||||
• {value} Variable value
|
||||
|
||||
nvim_tabpage_set_win({tabpage}, {win}) *nvim_tabpage_set_win()*
|
||||
Sets the current window in a tabpage
|
||||
|
||||
Parameters: ~
|
||||
• {tabpage} Tabpage handle, or 0 for current tabpage
|
||||
• {win} Window handle, must already belong to {tabpage}
|
||||
|
||||
|
||||
==============================================================================
|
||||
Autocmd Functions *api-autocmd*
|
||||
|
2
runtime/doc/builtin.txt
generated
2
runtime/doc/builtin.txt
generated
@ -2079,6 +2079,8 @@ getbufinfo([{dict}]) *getbufinfo()*
|
||||
bufnr Buffer number.
|
||||
changed TRUE if the buffer is modified.
|
||||
changedtick Number of changes made to the buffer.
|
||||
command TRUE if the buffer belongs to the
|
||||
command-line window |cmdwin|.
|
||||
hidden TRUE if the buffer is hidden.
|
||||
lastused Timestamp in seconds, like
|
||||
|localtime()|, when the buffer was
|
||||
|
@ -649,7 +649,7 @@ list of the current window.
|
||||
list.
|
||||
If [count] is omitted, the {name}s are added just
|
||||
after the current entry in the argument list.
|
||||
Otherwise they are added after the [count]'th file.
|
||||
Otherwise they are added after the [count]th file.
|
||||
If the argument list is "a b c", and "b" is the
|
||||
current argument, then these commands result in:
|
||||
command new argument list ~
|
||||
|
@ -687,7 +687,7 @@ To disable this behavior, set the following variable in your vimrc: >
|
||||
QUERY *ft-query-plugin*
|
||||
|
||||
|
||||
Linting of tree-sitter queries for installed parsers using
|
||||
Linting of treesitter queries for installed parsers using
|
||||
|vim.treesitter.query.lint()| is enabled by default on `BufEnter` and
|
||||
`BufWrite`. To change the events that trigger linting, use >lua
|
||||
|
||||
|
@ -253,6 +253,14 @@ arguments separated by " " (space) instead of "\t" (tab).
|
||||
:lua print(_VERSION)
|
||||
< To see the LuaJIT version: >vim
|
||||
:lua =jit.version
|
||||
<
|
||||
:{range}lua
|
||||
Executes buffer lines in {range} as Lua code. Unlike |:source|, this
|
||||
always treats the lines as Lua code.
|
||||
|
||||
Example: select the following code and type ":lua<Enter>" to execute it: >lua
|
||||
print(string.format(
|
||||
'unix time: %s', os.time()))
|
||||
<
|
||||
*:lua-heredoc*
|
||||
:lua << [trim] [{endmarker}]
|
||||
@ -266,10 +274,8 @@ arguments separated by " " (space) instead of "\t" (tab).
|
||||
function! CurrentLineInfo()
|
||||
lua << EOF
|
||||
local linenr = vim.api.nvim_win_get_cursor(0)[1]
|
||||
local curline = vim.api.nvim_buf_get_lines(
|
||||
0, linenr - 1, linenr, false)[1]
|
||||
print(string.format("Current line [%d] has %d bytes",
|
||||
linenr, #curline))
|
||||
local curline = vim.api.nvim_buf_get_lines(0, linenr - 1, linenr, false)[1]
|
||||
print(string.format('Line [%d] has %d bytes', linenr, #curline))
|
||||
EOF
|
||||
endfunction
|
||||
<
|
||||
@ -613,7 +619,7 @@ vim.highlight.on_yank({opts}) *vim.highlight.on_yank()*
|
||||
vim.highlight.priorities *vim.highlight.priorities*
|
||||
Table with default priorities used for highlighting:
|
||||
• `syntax`: `50`, used for standard syntax highlighting
|
||||
• `treesitter`: `100`, used for tree-sitter-based highlighting
|
||||
• `treesitter`: `100`, used for treesitter-based highlighting
|
||||
• `semantic_tokens`: `125`, used for LSP semantic token highlighting
|
||||
• `diagnostics`: `150`, used for code analysis such as diagnostics
|
||||
• `user`: `200`, used for user-triggered highlights such as LSP document
|
||||
@ -3901,18 +3907,22 @@ Iter:flatten({depth}) *Iter:flatten()*
|
||||
(`Iter`)
|
||||
|
||||
Iter:fold({init}, {f}) *Iter:fold()*
|
||||
Folds ("reduces") an iterator into a single value.
|
||||
Folds ("reduces") an iterator into a single value. *Iter:reduce()*
|
||||
|
||||
Examples: >lua
|
||||
-- Create a new table with only even values
|
||||
local t = { a = 1, b = 2, c = 3, d = 4 }
|
||||
local it = vim.iter(t)
|
||||
it:filter(function(k, v) return v % 2 == 0 end)
|
||||
it:fold({}, function(t, k, v)
|
||||
t[k] = v
|
||||
return t
|
||||
end)
|
||||
-- { b = 2, d = 4 }
|
||||
vim.iter({ a = 1, b = 2, c = 3, d = 4 })
|
||||
:filter(function(k, v) return v % 2 == 0 end)
|
||||
:fold({}, function(acc, k, v)
|
||||
acc[k] = v
|
||||
return acc
|
||||
end) --> { b = 2, d = 4 }
|
||||
|
||||
-- Get the "maximum" item of an iterable.
|
||||
vim.iter({ -99, -4, 3, 42, 0, 0, 7 })
|
||||
:fold({}, function(acc, v)
|
||||
acc.max = math.max(v, acc.max or v) return acc
|
||||
end) --> { max = 42 }
|
||||
<
|
||||
|
||||
Parameters: ~
|
||||
|
@ -256,7 +256,7 @@ g<End> Like |g$| but to the last non-blank character
|
||||
|exclusive| motion. Ceci n'est pas une pipe.
|
||||
|
||||
*f*
|
||||
f{char} To [count]'th occurrence of {char} to the right. The
|
||||
f{char} To [count]th occurrence of {char} to the right. The
|
||||
cursor is placed on {char} |inclusive|.
|
||||
{char} can be entered as a digraph |digraph-arg|.
|
||||
When 'encoding' is set to Unicode, composing
|
||||
@ -266,18 +266,18 @@ f{char} To [count]'th occurrence of {char} to the right. The
|
||||
|i_CTRL-^|.
|
||||
|
||||
*F*
|
||||
F{char} To the [count]'th occurrence of {char} to the left.
|
||||
F{char} To the [count]th occurrence of {char} to the left.
|
||||
The cursor is placed on {char} |exclusive|.
|
||||
{char} can be entered like with the |f| command.
|
||||
|
||||
*t*
|
||||
t{char} Till before [count]'th occurrence of {char} to the
|
||||
t{char} Till before [count]th occurrence of {char} to the
|
||||
right. The cursor is placed on the character left of
|
||||
{char} |inclusive|.
|
||||
{char} can be entered like with the |f| command.
|
||||
|
||||
*T*
|
||||
T{char} Till after [count]'th occurrence of {char} to the
|
||||
T{char} Till after [count]th occurrence of {char} to the
|
||||
left. The cursor is placed on the character right of
|
||||
{char} |exclusive|.
|
||||
{char} can be entered like with the |f| command.
|
||||
@ -604,14 +604,14 @@ ib "inner block", select [count] blocks, from "[count] [("
|
||||
|
||||
a> *v_a>* *v_a<* *a>* *a<*
|
||||
a< "a <> block", select [count] <> blocks, from the
|
||||
[count]'th unmatched '<' backwards to the matching
|
||||
[count]th unmatched '<' backwards to the matching
|
||||
'>', including the '<' and '>'. The |cpo-M| option flag
|
||||
is used to handle escaped '<' and '>'.
|
||||
When used in Visual mode it is made charwise.
|
||||
|
||||
i> *v_i>* *v_i<* *i>* *i<*
|
||||
i< "inner <> block", select [count] <> blocks, from
|
||||
the [count]'th unmatched '<' backwards to the matching
|
||||
the [count]th unmatched '<' backwards to the matching
|
||||
'>', excluding the '<' and '>'. It's an error to
|
||||
select an empty inner block like "<>". The |cpo-M|
|
||||
option flag is used to handle escaped '<' and '>'.
|
||||
@ -619,14 +619,14 @@ i< "inner <> block", select [count] <> blocks, from
|
||||
|
||||
*v_at* *at*
|
||||
at "a tag block", select [count] tag blocks, from the
|
||||
[count]'th unmatched "<aaa>" backwards to the matching
|
||||
[count]th unmatched "<aaa>" backwards to the matching
|
||||
"</aaa>", including the "<aaa>" and "</aaa>".
|
||||
See |tag-blocks| about the details.
|
||||
When used in Visual mode it is made charwise.
|
||||
|
||||
*v_it* *it*
|
||||
it "inner tag block", select [count] tag blocks, from the
|
||||
[count]'th unmatched "<aaa>" backwards to the matching
|
||||
[count]th unmatched "<aaa>" backwards to the matching
|
||||
"</aaa>", excluding the "<aaa>" and "</aaa>".
|
||||
See |tag-blocks| about the details.
|
||||
When used in Visual mode it is made charwise.
|
||||
|
@ -4,7 +4,7 @@
|
||||
NVIM REFERENCE MANUAL
|
||||
|
||||
|
||||
Notable changes in Nvim 0.9 from 0.8 *news-0.9*
|
||||
Notable changes in Nvim 0.9 since 0.8 *news-0.9*
|
||||
|
||||
Type |gO| to see the table of contents.
|
||||
|
||||
|
@ -4,9 +4,9 @@
|
||||
NVIM REFERENCE MANUAL
|
||||
|
||||
|
||||
Notable changes in Nvim 0.10 from 0.9 *news*
|
||||
Notable changes since Nvim 0.9 *news*
|
||||
|
||||
For changes in Nvim 0.9, see |news-0.9|.
|
||||
For changes in the previous release, see |news-0.9|.
|
||||
|
||||
Type |gO| to see the table of contents.
|
||||
|
||||
@ -120,10 +120,13 @@ The following changes may require adaptations in user config or plugins.
|
||||
==============================================================================
|
||||
BREAKING CHANGES IN HEAD *news-breaking-dev*
|
||||
|
||||
The following breaking changes were made during the development cycle to
|
||||
unreleased features on Nvim HEAD.
|
||||
====== Remove this section before release. ======
|
||||
|
||||
• ...
|
||||
The following breaking changes were made during the development cycle to
|
||||
UNRELEASED features on Nvim HEAD (the unreleased "master" branch).
|
||||
|
||||
• Removed `vim.treesitter.foldtext` as transparent foldtext is now supported
|
||||
https://github.com/neovim/neovim/pull/20750
|
||||
• ...
|
||||
|
||||
==============================================================================
|
||||
@ -181,6 +184,8 @@ The following new APIs and features were added.
|
||||
swapfile is owned by a running Nvim process, instead of prompting. If you
|
||||
always want the swapfile dialog, delete the default SwapExists handler:
|
||||
`autocmd! nvim_swapfile`. |default-autocmds|
|
||||
• Navigating the |jumplist| with CTRL+O, CTRL+I behaves more intuitively
|
||||
when deleting buffers, and avoids "invalid buffer" cases. #25461
|
||||
|
||||
• LSP
|
||||
• LSP method names are available in |vim.lsp.protocol.Methods|.
|
||||
@ -223,8 +228,6 @@ The following new APIs and features were added.
|
||||
• |vim.treesitter.query.edit()| allows live editing of treesitter
|
||||
queries.
|
||||
• Improved error messages for query parsing.
|
||||
• |vim.treesitter.foldtext()| applies treesitter highlighting to
|
||||
foldtext.
|
||||
|
||||
• |vim.ui.open()| opens URIs using the system default handler (macOS `open`,
|
||||
Windows `explorer`, Linux `xdg-open`, etc.)
|
||||
@ -305,6 +308,8 @@ The following new APIs and features were added.
|
||||
highlight attribute. The TUI will display URLs using the OSC 8 control
|
||||
sequence, enabling clickable text in supporting terminals.
|
||||
|
||||
• Added |nvim_tabpage_set_win()| to set the current window of a tabpage.
|
||||
|
||||
==============================================================================
|
||||
CHANGED FEATURES *news-changed*
|
||||
|
||||
@ -341,6 +346,9 @@ The following changes to existing APIs or features add new behavior.
|
||||
• |:source| without arguments treats a buffer with its 'filetype' set to "lua"
|
||||
as Lua code regardless of its extension.
|
||||
|
||||
• |:lua| with a |[range]| executes that range in the current buffer as Lua code
|
||||
regardless of its extension.
|
||||
|
||||
• |:checkhealth| buffer now implements |folding|. The initial folding status is
|
||||
defined by the 'foldenable' option.
|
||||
|
||||
|
@ -126,6 +126,41 @@ color index is just forwarded.
|
||||
Editor highlighting (|syntax-highlighting|, |highlight-groups|, etc.) has
|
||||
higher precedence: it is applied after terminal colors are resolved.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
EVENTS *terminal-events*
|
||||
|
||||
Applications running in a :terminal buffer can send requests, which Nvim
|
||||
exposes via the |TermRequest| event.
|
||||
|
||||
OSC 7: change working directory *terminal-osc7*
|
||||
|
||||
To handle OSC 7 emitted from :terminal processes, this code will :cd to the
|
||||
directory indicated in the request. >lua
|
||||
|
||||
vim.api.nvim_create_autocmd({ 'TermRequest' }, {
|
||||
desc = 'Handles OSC 7 dir change requests',
|
||||
callback = function(ev)
|
||||
if string.sub(vim.v.termrequest, 1, 4) == '\x1b]7;' then
|
||||
local dir = string.gsub(vim.v.termrequest, '\x1b]7;file://[^/]*', '')
|
||||
if vim.fn.isdirectory(dir) == 0 then
|
||||
vim.notify('invalid dir: '..dir)
|
||||
return
|
||||
end
|
||||
vim.api.nvim_buf_set_var(ev.buf, 'osc7_dir', dir)
|
||||
if vim.o.autochdir and vim.api.nvim_get_current_buf() == ev.buf then
|
||||
vim.cmd.cd(dir)
|
||||
end
|
||||
end
|
||||
end
|
||||
})
|
||||
vim.api.nvim_create_autocmd({ 'BufEnter', 'WinEnter', 'DirChanged' }, {
|
||||
callback = function(ev)
|
||||
if vim.b.osc7_dir and vim.fn.isdirectory(vim.b.osc7_dir) == 1 then
|
||||
vim.cmd.cd(vim.b.osc7_dir)
|
||||
end
|
||||
end
|
||||
})
|
||||
|
||||
==============================================================================
|
||||
Status Variables *terminal-status*
|
||||
|
||||
|
@ -6816,6 +6816,7 @@ A jump table for the options with a short description can be found at |Q_op|.
|
||||
|
||||
Level Messages ~
|
||||
----------------------------------------------------------------------
|
||||
1 Enables Lua tracing (see above). Does not produce messages.
|
||||
2 When a file is ":source"'ed, or |shada| file is read or written.
|
||||
3 UI info, terminal capabilities.
|
||||
4 Shell commands.
|
||||
|
@ -15,36 +15,36 @@ explanations are in chapter 27 |usr_27.txt|.
|
||||
1. Search commands *search-commands*
|
||||
|
||||
*/*
|
||||
/{pattern}[/]<CR> Search forward for the [count]'th occurrence of
|
||||
/{pattern}[/]<CR> Search forward for the [count]th occurrence of
|
||||
{pattern} |exclusive|.
|
||||
|
||||
/{pattern}/{offset}<CR> Search forward for the [count]'th occurrence of
|
||||
/{pattern}/{offset}<CR> Search forward for the [count]th occurrence of
|
||||
{pattern} and go |{offset}| lines up or down.
|
||||
|linewise|.
|
||||
|
||||
*/<CR>*
|
||||
/<CR> Search forward for the [count]'th occurrence of the
|
||||
/<CR> Search forward for the [count]th occurrence of the
|
||||
latest used pattern |last-pattern| with latest used
|
||||
|{offset}|.
|
||||
|
||||
//{offset}<CR> Search forward for the [count]'th occurrence of the
|
||||
//{offset}<CR> Search forward for the [count]th occurrence of the
|
||||
latest used pattern |last-pattern| with new
|
||||
|{offset}|. If {offset} is empty no offset is used.
|
||||
|
||||
*?*
|
||||
?{pattern}[?]<CR> Search backward for the [count]'th previous
|
||||
?{pattern}[?]<CR> Search backward for the [count]th previous
|
||||
occurrence of {pattern} |exclusive|.
|
||||
|
||||
?{pattern}?{offset}<CR> Search backward for the [count]'th previous
|
||||
?{pattern}?{offset}<CR> Search backward for the [count]th previous
|
||||
occurrence of {pattern} and go |{offset}| lines up or
|
||||
down |linewise|.
|
||||
|
||||
*?<CR>*
|
||||
?<CR> Search backward for the [count]'th occurrence of the
|
||||
?<CR> Search backward for the [count]th occurrence of the
|
||||
latest used pattern |last-pattern| with latest used
|
||||
|{offset}|.
|
||||
|
||||
??{offset}<CR> Search backward for the [count]'th occurrence of the
|
||||
??{offset}<CR> Search backward for the [count]th occurrence of the
|
||||
latest used pattern |last-pattern| with new
|
||||
|{offset}|. If {offset} is empty no offset is used.
|
||||
|
||||
@ -59,7 +59,7 @@ N Repeat the latest "/" or "?" [count] times in
|
||||
opposite direction. |last-pattern|
|
||||
|
||||
*star* *E348* *E349*
|
||||
* Search forward for the [count]'th occurrence of the
|
||||
* Search forward for the [count]th occurrence of the
|
||||
word nearest to the cursor. The word used for the
|
||||
search is the first of:
|
||||
1. the keyword under the cursor |'iskeyword'|
|
||||
|
@ -213,7 +213,7 @@ N is used to indicate an optional count that can be given before the command.
|
||||
*Q_ta* Using tags
|
||||
|
||||
|:ta| :ta[g][!] {tag} jump to tag {tag}
|
||||
|:ta| :[count]ta[g][!] jump to [count]'th newer tag in tag list
|
||||
|:ta| :[count]ta[g][!] jump to [count]th newer tag in tag list
|
||||
|CTRL-]| CTRL-] jump to the tag under cursor, unless changes
|
||||
have been made
|
||||
|:ts| :ts[elect][!] [tag] list matching tags and select one to jump to
|
||||
@ -224,10 +224,10 @@ N is used to indicate an optional count that can be given before the command.
|
||||
|
||||
|:tags| :tags print tag list
|
||||
|CTRL-T| N CTRL-T jump back from Nth older tag in tag list
|
||||
|:po| :[count]po[p][!] jump back from [count]'th older tag in tag list
|
||||
|:tnext| :[count]tn[ext][!] jump to [count]'th next matching tag
|
||||
|:tp| :[count]tp[revious][!] jump to [count]'th previous matching tag
|
||||
|:tr| :[count]tr[ewind][!] jump to [count]'th matching tag
|
||||
|:po| :[count]po[p][!] jump back from [count]th older tag in tag list
|
||||
|:tnext| :[count]tn[ext][!] jump to [count]th next matching tag
|
||||
|:tp| :[count]tp[revious][!] jump to [count]th previous matching tag
|
||||
|:tr| :[count]tr[ewind][!] jump to [count]th matching tag
|
||||
|:tl| :tl[ast][!] jump to last matching tag
|
||||
|
||||
|:ptag| :pt[ag] {tag} open a preview window to show tag {tag}
|
||||
|
@ -192,11 +192,11 @@ Using Vim scripts *using-scripts*
|
||||
For writing a Vim script, see chapter 41 of the user manual |usr_41.txt|.
|
||||
|
||||
*:so* *:source* *load-vim-script*
|
||||
:[range]so[urce] [file] Runs |Ex| commands or Lua code (".lua" files) from
|
||||
:[range]so[urce] [file] Runs |Ex-commands| or Lua code (".lua" files) from
|
||||
[file].
|
||||
If no [file], the current buffer is used, and it is
|
||||
treated as Lua code if its 'filetype' is "lua" or its
|
||||
file name ends with ".lua".
|
||||
If no [file], the current buffer is used and treated
|
||||
as Lua code if 'filetype' is "lua" or its filename
|
||||
ends with ".lua".
|
||||
Triggers the |SourcePre| autocommand.
|
||||
*:source!*
|
||||
:[range]so[urce]! {file}
|
||||
|
@ -17,16 +17,26 @@ changes. This documentation may also not fully reflect the latest changes.
|
||||
==============================================================================
|
||||
PARSER FILES *treesitter-parsers*
|
||||
|
||||
Parsers are the heart of tree-sitter. They are libraries that tree-sitter will
|
||||
search for in the `parser` runtime directory. By default, Nvim bundles parsers
|
||||
for C, Lua, Vimscript, Vimdoc and Treesitter query files, but parsers can be
|
||||
installed via a plugin like https://github.com/nvim-treesitter/nvim-treesitter
|
||||
or even manually.
|
||||
Parsers are the heart of treesitter. They are libraries that treesitter will
|
||||
search for in the `parser` runtime directory.
|
||||
|
||||
Nvim includes these parsers:
|
||||
|
||||
- C
|
||||
- Lua
|
||||
- Markdown
|
||||
- Vimscript
|
||||
- Vimdoc
|
||||
- Treesitter query files |ft-query-plugin|
|
||||
|
||||
You can install more parsers manually, or with a plugin like
|
||||
https://github.com/nvim-treesitter/nvim-treesitter .
|
||||
|
||||
Parsers are searched for as `parser/{lang}.*` in any 'runtimepath' directory.
|
||||
If multiple parsers for the same language are found, the first one is used.
|
||||
(NOTE: This typically implies the priority "user config > plugins > bundled".)
|
||||
A parser can also be loaded manually using a full path: >lua
|
||||
|
||||
To load a parser from its filepath: >lua
|
||||
|
||||
vim.treesitter.language.add('python', { path = "/path/to/python.so" })
|
||||
<
|
||||
@ -43,7 +53,7 @@ TREESITTER TREES *treesitter-tree*
|
||||
|
||||
A "treesitter tree" represents the parsed contents of a buffer, which can be
|
||||
used to perform further analysis. It is a |userdata| reference to an object
|
||||
held by the tree-sitter library.
|
||||
held by the treesitter library.
|
||||
|
||||
An instance `TSTree` of a treesitter tree supports the following methods.
|
||||
|
||||
@ -59,7 +69,7 @@ TREESITTER NODES *treesitter-node*
|
||||
|
||||
A "treesitter node" represents one specific element of the parsed contents of
|
||||
a buffer, which can be captured by a |Query| for, e.g., highlighting. It is
|
||||
a |userdata| reference to an object held by the tree-sitter library.
|
||||
a |userdata| reference to an object held by the treesitter library.
|
||||
|
||||
An instance `TSNode` of a treesitter node supports the following methods.
|
||||
|
||||
@ -563,7 +573,7 @@ Conceals specified in this way respect 'conceallevel'.
|
||||
*treesitter-highlight-priority*
|
||||
Treesitter uses |nvim_buf_set_extmark()| to set highlights with a default
|
||||
priority of 100. This enables plugins to set a highlighting priority lower or
|
||||
higher than tree-sitter. It is also possible to change the priority of an
|
||||
higher than treesitter. It is also possible to change the priority of an
|
||||
individual query pattern manually by setting its `"priority"` metadata
|
||||
attribute: >query
|
||||
|
||||
@ -624,17 +634,17 @@ associated with patterns:
|
||||
VIM.TREESITTER *lua-treesitter*
|
||||
|
||||
The remainder of this document is a reference manual for the `vim.treesitter`
|
||||
Lua module, which is the main interface for Nvim's tree-sitter integration.
|
||||
Lua module, which is the main interface for Nvim's treesitter integration.
|
||||
Most of the following content is automatically generated from the function
|
||||
documentation.
|
||||
|
||||
|
||||
*vim.treesitter.language_version*
|
||||
The latest parser ABI version that is supported by the bundled tree-sitter
|
||||
The latest parser ABI version that is supported by the bundled treesitter
|
||||
library.
|
||||
|
||||
*vim.treesitter.minimum_language_version*
|
||||
The earliest parser ABI version that is supported by the bundled tree-sitter
|
||||
The earliest parser ABI version that is supported by the bundled treesitter
|
||||
library.
|
||||
|
||||
==============================================================================
|
||||
@ -652,16 +662,6 @@ foldexpr({lnum}) *vim.treesitter.foldexpr()*
|
||||
Return: ~
|
||||
(`string`)
|
||||
|
||||
foldtext() *vim.treesitter.foldtext()*
|
||||
Returns the highlighted content of the first line of the fold or falls
|
||||
back to |foldtext()| if no treesitter parser is found. Can be set directly
|
||||
to 'foldtext': >lua
|
||||
vim.wo.foldtext = 'v:lua.vim.treesitter.foldtext()'
|
||||
<
|
||||
|
||||
Return: ~
|
||||
(`{ [1]: string, [2]: string[] }[]|string`)
|
||||
|
||||
*vim.treesitter.get_captures_at_cursor()*
|
||||
get_captures_at_cursor({winnr})
|
||||
Returns a list of highlight capture names under the cursor
|
||||
@ -907,10 +907,7 @@ get_lang({filetype}) *vim.treesitter.language.get_lang()*
|
||||
(`string?`)
|
||||
|
||||
inspect({lang}) *vim.treesitter.language.inspect()*
|
||||
Inspects the provided language.
|
||||
|
||||
Inspecting provides some useful information on the language like node
|
||||
names, ...
|
||||
Gets some useful information on the language like node names, ...
|
||||
|
||||
Parameters: ~
|
||||
• {lang} (`string`) Language
|
||||
|
11
runtime/ftplugin/hurl.vim
Normal file
11
runtime/ftplugin/hurl.vim
Normal file
@ -0,0 +1,11 @@
|
||||
" Vim filetype plugin file
|
||||
" Language: hurl
|
||||
" Maintainer: Melker Ulander <melker.ulander@pm.me>
|
||||
" Last Changed: 2024 01 26
|
||||
|
||||
if exists("b:did_ftplugin") | finish | endif
|
||||
|
||||
let b:did_ftplugin = 1
|
||||
setlocal commentstring=#\ %s
|
||||
|
||||
let b:undo_ftplugin = "setlocal commentstring<"
|
@ -1,5 +1,5 @@
|
||||
-- Neovim filetype plugin file
|
||||
-- Language: Tree-sitter query
|
||||
-- Language: Treesitter query
|
||||
-- Last Change: 2023 Aug 23
|
||||
|
||||
if vim.b.did_ftplugin == 1 then
|
||||
|
@ -49,18 +49,17 @@ setlocal isk+=#
|
||||
" Use :help to lookup the keyword under the cursor with K.
|
||||
setlocal keywordprg=:help
|
||||
|
||||
" if "\n" .. getline(1, 10)->join("\n") =~# '\n\s*vim9\%[script]\>'
|
||||
if "\n" .. join(getline(1, 10), "\n") =~# '\n\s*vim9\%[script]\>'
|
||||
" Set 'comments' to format dashed lists in comments
|
||||
setlocal com=sO:#\ -,mO:#\ \ ,eO:##,:#
|
||||
" Comments starts with # in Vim9 script
|
||||
" Comments starts with # in Vim9 script. We have to guess which one to use.
|
||||
if "\n" .. getline(1, 10)->join("\n") =~# '\n\s*vim9\%[script]\>'
|
||||
setlocal commentstring=#%s
|
||||
else
|
||||
setlocal com=sO:\"\ -,mO:\"\ \ ,eO:\"\",:\"
|
||||
" Comments starts with a double quote in legacy script
|
||||
setlocal commentstring=\"%s
|
||||
endif
|
||||
|
||||
" Set 'comments' to format dashed lists in comments, both in Vim9 and legacy
|
||||
" script.
|
||||
setlocal com=sO:#\ -,mO:#\ \ ,eO:##,:#\\\ ,:#,sO:\"\ -,mO:\"\ \ ,eO:\"\",:\"\\\ ,:\"
|
||||
|
||||
|
||||
" Format comments to be up to 78 characters long
|
||||
if &tw == 0
|
||||
|
@ -1,5 +1,5 @@
|
||||
-- Neovim indent file
|
||||
-- Language: Tree-sitter query
|
||||
-- Language: Treesitter query
|
||||
-- Last Change: 2022 Mar 29
|
||||
|
||||
-- it's a lisp!
|
||||
|
@ -23,9 +23,15 @@ local function check_runtime()
|
||||
health.start('Runtime')
|
||||
-- Files from an old installation.
|
||||
local bad_files = {
|
||||
['plugin/man.vim'] = false,
|
||||
['scripts.vim'] = false,
|
||||
['plugin/health.vim'] = false,
|
||||
['autoload/health/nvim.vim'] = false,
|
||||
['autoload/health/provider.vim'] = false,
|
||||
['autoload/man.vim'] = false,
|
||||
['plugin/man.vim'] = false,
|
||||
['queries/help/highlights.scm'] = false,
|
||||
['queries/help/injections.scm'] = false,
|
||||
['scripts.vim'] = false,
|
||||
['syntax/syncolor.vim'] = false,
|
||||
}
|
||||
local bad_files_msg = ''
|
||||
for k, _ in pairs(bad_files) do
|
||||
@ -42,10 +48,10 @@ local function check_runtime()
|
||||
if not ok then
|
||||
health.error(
|
||||
string.format(
|
||||
'$VIMRUNTIME has files from an old installation (this can cause weird behavior):\n%s',
|
||||
'Found old files in $VIMRUNTIME (this can cause weird behavior):\n%s',
|
||||
bad_files_msg
|
||||
),
|
||||
{ 'Delete $VIMRUNTIME (or uninstall Nvim), then reinstall Nvim.' }
|
||||
{ 'Delete the $VIMRUNTIME directory (or uninstall Nvim), then reinstall Nvim.' }
|
||||
)
|
||||
end
|
||||
end
|
||||
|
@ -255,7 +255,7 @@ function M.check()
|
||||
'See :help provider-python for more information.',
|
||||
'You may disable this provider (and warning) by adding `let g:loaded_python3_provider = 0` to your init.vim',
|
||||
})
|
||||
elseif pyname ~= '' and python_exe == '' then
|
||||
elseif pyname and pyname ~= '' and python_exe == '' then
|
||||
if not vim.g[host_prog_var] then
|
||||
local message = string.format(
|
||||
'`g:%s` is not set. Searching for %s in the environment.',
|
||||
@ -343,7 +343,7 @@ function M.check()
|
||||
end
|
||||
end
|
||||
|
||||
if python_exe == '' and pyname ~= '' then
|
||||
if pyname and python_exe == '' and pyname ~= '' then
|
||||
-- An error message should have already printed.
|
||||
health.error('`' .. pyname .. '` was not found.')
|
||||
elseif python_exe ~= '' and not check_bin(python_exe) then
|
||||
|
@ -22,7 +22,7 @@ function M.check()
|
||||
|
||||
local ruby_detect_table = require('vim.provider.ruby').detect()
|
||||
local host = ruby_detect_table[1]
|
||||
if host:find('^%s*$') then
|
||||
if (not host) or host:find('^%s*$') then
|
||||
health.warn('`neovim-ruby-host` not found.', {
|
||||
'Run `gem install neovim` to ensure the neovim RubyGem is installed.',
|
||||
'Run `gem environment` to ensure the gem bin directory is in $PATH.',
|
||||
|
@ -157,7 +157,7 @@ do
|
||||
|
||||
vim.api.nvim_create_autocmd('TermRequest', {
|
||||
group = nvim_terminal_augroup,
|
||||
desc = 'Respond to OSC foreground/background color requests',
|
||||
desc = 'Handles OSC foreground/background color requests',
|
||||
callback = function(args)
|
||||
local fg_request = args.data == '\027]10;?'
|
||||
local bg_request = args.data == '\027]11;?'
|
||||
|
34
runtime/lua/vim/_meta/api.lua
generated
34
runtime/lua/vim/_meta/api.lua
generated
@ -320,7 +320,7 @@ function vim.api.nvim_buf_get_commands(buffer, opts) end
|
||||
--- • details: Whether to include the details dict
|
||||
--- • hl_name: Whether to include highlight group name instead
|
||||
--- of id, true if omitted
|
||||
--- @return integer[]
|
||||
--- @return vim.api.keyset.get_extmark_item
|
||||
function vim.api.nvim_buf_get_extmark_by_id(buffer, ns_id, id, opts) end
|
||||
|
||||
--- Gets `extmarks` in "traversal order" from a `charwise` region defined by
|
||||
@ -376,14 +376,14 @@ function vim.api.nvim_buf_get_extmark_by_id(buffer, ns_id, id, opts) end
|
||||
--- if their start position is less than `start`
|
||||
--- • type: Filter marks by type: "highlight", "sign",
|
||||
--- "virt_text" and "virt_lines"
|
||||
--- @return any[]
|
||||
--- @return vim.api.keyset.get_extmark_item[]
|
||||
function vim.api.nvim_buf_get_extmarks(buffer, ns_id, start, end_, opts) end
|
||||
|
||||
--- Gets a list of buffer-local `mapping` definitions.
|
||||
---
|
||||
--- @param buffer integer Buffer handle, or 0 for current buffer
|
||||
--- @param mode string Mode short-name ("n", "i", "v", ...)
|
||||
--- @return table<string,any>[]
|
||||
--- @return vim.api.keyset.keymap[]
|
||||
function vim.api.nvim_buf_get_keymap(buffer, mode) end
|
||||
|
||||
--- Gets a line-range from the buffer.
|
||||
@ -1153,7 +1153,7 @@ function vim.api.nvim_get_all_options_info() end
|
||||
--- • buffer: Buffer number or list of buffer numbers for buffer
|
||||
--- local autocommands `autocmd-buflocal`. Cannot be used with
|
||||
--- {pattern}
|
||||
--- @return any[]
|
||||
--- @return vim.api.keyset.get_autocmds.ret[]
|
||||
function vim.api.nvim_get_autocmds(opts) end
|
||||
|
||||
--- Gets information about a channel.
|
||||
@ -1179,7 +1179,7 @@ function vim.api.nvim_get_color_by_name(name) end
|
||||
--- Keys are color names (e.g. "Aqua") and values are 24-bit RGB color values
|
||||
--- (e.g. 65535).
|
||||
---
|
||||
--- @return table<string,any>
|
||||
--- @return table<string,integer>
|
||||
function vim.api.nvim_get_color_map() end
|
||||
|
||||
--- Gets a map of global (non-buffer-local) Ex commands.
|
||||
@ -1229,7 +1229,7 @@ function vim.api.nvim_get_current_win() end
|
||||
--- instead of effective definition `:hi-link`.
|
||||
--- • create: (boolean, default true) When highlight group
|
||||
--- doesn't exist create it.
|
||||
--- @return table<string,any>
|
||||
--- @return vim.api.keyset.hl_info
|
||||
function vim.api.nvim_get_hl(ns_id, opts) end
|
||||
|
||||
--- @deprecated
|
||||
@ -1264,7 +1264,7 @@ function vim.api.nvim_get_hl_ns(opts) end
|
||||
--- Gets a list of global (non-buffer-local) `mapping` definitions.
|
||||
---
|
||||
--- @param mode string Mode short-name ("n", "i", "v", ...)
|
||||
--- @return table<string,any>[]
|
||||
--- @return vim.api.keyset.keymap[]
|
||||
function vim.api.nvim_get_keymap(mode) end
|
||||
|
||||
--- Returns a `(row, col, buffer, buffername)` tuple representing the position
|
||||
@ -1274,18 +1274,18 @@ function vim.api.nvim_get_keymap(mode) end
|
||||
---
|
||||
--- @param name string Mark name
|
||||
--- @param opts vim.api.keyset.empty Optional parameters. Reserved for future use.
|
||||
--- @return any[]
|
||||
--- @return vim.api.keyset.get_mark
|
||||
function vim.api.nvim_get_mark(name, opts) end
|
||||
|
||||
--- Gets the current mode. `mode()` "blocking" is true if Nvim is waiting for
|
||||
--- input.
|
||||
---
|
||||
--- @return table<string,any>
|
||||
--- @return vim.api.keyset.get_mode
|
||||
function vim.api.nvim_get_mode() end
|
||||
|
||||
--- Gets existing, non-anonymous `namespace`s.
|
||||
---
|
||||
--- @return table<string,any>
|
||||
--- @return table<string,integer>
|
||||
function vim.api.nvim_get_namespaces() end
|
||||
|
||||
--- @deprecated
|
||||
@ -1295,7 +1295,7 @@ function vim.api.nvim_get_option(name) end
|
||||
|
||||
--- @deprecated
|
||||
--- @param name string
|
||||
--- @return table<string,any>
|
||||
--- @return vim.api.keyset.get_option_info
|
||||
function vim.api.nvim_get_option_info(name) end
|
||||
|
||||
--- Gets the option information for one option from arbitrary buffer or window
|
||||
@ -1325,7 +1325,7 @@ function vim.api.nvim_get_option_info(name) end
|
||||
--- • win: `window-ID`. Used for getting window local options.
|
||||
--- • buf: Buffer number. Used for getting buffer local options.
|
||||
--- Implies {scope} is "local".
|
||||
--- @return table<string,any>
|
||||
--- @return vim.api.keyset.get_option_info
|
||||
function vim.api.nvim_get_option_info2(name, opts) end
|
||||
|
||||
--- Gets the value of an option. The behavior of this function matches that of
|
||||
@ -1637,7 +1637,7 @@ function vim.api.nvim_out_write(str) end
|
||||
---
|
||||
--- @param str string Command line string to parse. Cannot contain "\n".
|
||||
--- @param opts vim.api.keyset.empty Optional parameters. Reserved for future use.
|
||||
--- @return table<string,any>
|
||||
--- @return vim.api.keyset.parse_cmd
|
||||
function vim.api.nvim_parse_cmd(str, opts) end
|
||||
|
||||
--- Parse a Vimscript expression.
|
||||
@ -1952,6 +1952,12 @@ function vim.api.nvim_tabpage_list_wins(tabpage) end
|
||||
--- @param value any Variable value
|
||||
function vim.api.nvim_tabpage_set_var(tabpage, name, value) end
|
||||
|
||||
--- Sets the current window in a tabpage
|
||||
---
|
||||
--- @param tabpage integer Tabpage handle, or 0 for current tabpage
|
||||
--- @param win integer Window handle, must already belong to {tabpage}
|
||||
function vim.api.nvim_tabpage_set_win(tabpage, win) end
|
||||
|
||||
--- Calls a function with window as temporary current window.
|
||||
---
|
||||
--- @param window integer Window handle, or 0 for current window
|
||||
@ -1985,7 +1991,7 @@ function vim.api.nvim_win_get_buf(window) end
|
||||
--- `relative` is empty for normal windows.
|
||||
---
|
||||
--- @param window integer Window handle, or 0 for current window
|
||||
--- @return table<string,any>
|
||||
--- @return vim.api.keyset.float_config
|
||||
function vim.api.nvim_win_get_config(window) end
|
||||
|
||||
--- Gets the (1,0)-indexed, buffer-relative cursor position for a given window
|
||||
|
1
runtime/lua/vim/_meta/api_keysets.lua
generated
1
runtime/lua/vim/_meta/api_keysets.lua
generated
@ -274,6 +274,7 @@ error('Cannot require a meta file')
|
||||
--- @field ui_watched? boolean
|
||||
--- @field undo_restore? boolean
|
||||
--- @field url? string
|
||||
--- @field _subpriority? integer
|
||||
|
||||
--- @class vim.api.keyset.user_command
|
||||
--- @field addr? any
|
||||
|
167
runtime/lua/vim/_meta/api_keysets_extra.lua
Normal file
167
runtime/lua/vim/_meta/api_keysets_extra.lua
Normal file
@ -0,0 +1,167 @@
|
||||
--- @meta _
|
||||
error('Cannot require a meta file')
|
||||
|
||||
--- Extra types we can't generate keysets for
|
||||
|
||||
--- @class vim.api.keyset.extmark_details
|
||||
--- @field ns_id integer
|
||||
--- @field right_gravity boolean
|
||||
---
|
||||
--- @field end_row? integer
|
||||
--- @field end_col? integer
|
||||
--- @field end_right_gravity? integer
|
||||
---
|
||||
--- @field priority? integer
|
||||
---
|
||||
--- @field undo_restore? false
|
||||
--- @field invalidate? true
|
||||
--- @field invalid? true
|
||||
---
|
||||
--- @field hl_group? string
|
||||
--- @field hl_eol? boolean
|
||||
---
|
||||
--- @field conceal? boolean
|
||||
--- @field spell? boolean
|
||||
--- @field ui_watched? boolean
|
||||
--- @field url? boolean
|
||||
--- @field hl_mode? string
|
||||
---
|
||||
--- @field virt_text? {[1]: string, [2]: string}[]
|
||||
--- @field virt_text_hide? boolean
|
||||
--- @field virt_text_repeat_linebreak? boolean
|
||||
--- @field virt_text_win_col? integer
|
||||
--- @field virt_text_pos? string
|
||||
---
|
||||
--- @field virt_lines? {[1]: string, [2]: string}[][]
|
||||
--- @field virt_lines_above? boolean
|
||||
--- @field virt_lines_leftcol? boolean
|
||||
---
|
||||
--- @field sign_text? string
|
||||
--- @field sign_name? string
|
||||
--- @field sign_hl_group? string
|
||||
--- @field number_hl_group? string
|
||||
--- @field line_hl_group? string
|
||||
--- @field cursorline_hl_group? string
|
||||
|
||||
--- @class vim.api.keyset.get_extmark_item
|
||||
--- @field [1] integer row
|
||||
--- @field [2] integer col
|
||||
--- @field [3] vim.api.keyset.extmark_details?
|
||||
|
||||
--- @class vim.api.keyset.get_mark
|
||||
--- @field [1] integer row
|
||||
--- @field [2] integer col
|
||||
--- @field [3] integer buffer
|
||||
--- @field [4] string buffername
|
||||
|
||||
--- @class vim.api.keyset.get_autocmds.ret
|
||||
--- @field id? integer
|
||||
--- @field group? integer
|
||||
--- @field group_name? integer
|
||||
--- @field desc? string
|
||||
--- @field event? string
|
||||
--- @field command? string
|
||||
--- @field callback? function
|
||||
--- @field once? boolean
|
||||
--- @field pattern? string
|
||||
--- @field buflocal? boolean
|
||||
--- @field buffer? integer
|
||||
|
||||
--- @class vim.api.keyset.command_info
|
||||
--- @field name string
|
||||
--- @field definition string
|
||||
--- @field script_id integer
|
||||
--- @field bang boolean
|
||||
--- @field bar boolean
|
||||
--- @field register boolean
|
||||
--- @field keepscript boolean
|
||||
--- @field preview boolean
|
||||
--- @field nargs string
|
||||
--- @field complete? string
|
||||
--- @field complete_arg? string
|
||||
--- @field count? string
|
||||
--- @field range? string
|
||||
--- @field addr? string
|
||||
|
||||
--- @class vim.api.keyset.hl_info.base
|
||||
--- @field reverse? true
|
||||
--- @field bold? true
|
||||
--- @field italic? true
|
||||
--- @field underline? true
|
||||
--- @field undercurl? true
|
||||
--- @field underdouble? true
|
||||
--- @field underdotted? true
|
||||
--- @field underdashed? true
|
||||
--- @field standout? true
|
||||
--- @field strikethrough? true
|
||||
--- @field altfont? true
|
||||
--- @field nocombine? true
|
||||
|
||||
--- @class vim.api.keyset.hl_info.cterm : vim.api.keyset.hl_info.base
|
||||
--- @field ctermfg? integer
|
||||
--- @field ctermbg? integer
|
||||
--- @field foreground? integer
|
||||
--- @field background? integer
|
||||
|
||||
--- @class vim.api.keyset.hl_info : vim.api.keyset.hl_info.base
|
||||
--- @field fg? integer
|
||||
--- @field bg? integer
|
||||
--- @field sp? integer
|
||||
--- @field default? true
|
||||
--- @field link? string
|
||||
--- @field blend? integer
|
||||
--- @field cterm? vim.api.keyset.hl_info.cterm
|
||||
|
||||
--- @class vim.api.keyset.get_mode
|
||||
--- @field blocking boolean
|
||||
--- @field mode string
|
||||
|
||||
--- @class vim.api.keyset.get_option_info
|
||||
--- @field name string
|
||||
--- @field shortname string
|
||||
--- @field scope 'buf'|'win'|'global'
|
||||
--- @field global_local boolean
|
||||
--- @field commalist boolean
|
||||
--- @field flaglist boolean
|
||||
--- @field was_set boolean
|
||||
--- @field last_set_id integer
|
||||
--- @field last_set_linenr integer
|
||||
--- @field last_set_chan integer
|
||||
--- @field type 'string'|'boolean'|'number'
|
||||
--- @field default string|boolean|integer
|
||||
--- @field allow_duplicates boolean
|
||||
|
||||
--- @class vim.api.keyset.parse_cmd.mods
|
||||
--- @field filter { force: boolean, pattern: string }
|
||||
--- @field silent boolean
|
||||
--- @field emsg_silent boolean
|
||||
--- @field unsilent boolean
|
||||
--- @field sandbox boolean
|
||||
--- @field noautocmd boolean
|
||||
--- @field tab integer
|
||||
--- @field verbose integer
|
||||
--- @field browse boolean
|
||||
--- @field confirm boolean
|
||||
--- @field hide boolean
|
||||
--- @field keepalt boolean
|
||||
--- @field keepjumps boolean
|
||||
--- @field keepmarks boolean
|
||||
--- @field keeppatterns boolean
|
||||
--- @field lockmarks boolean
|
||||
--- @field noswapfile boolean
|
||||
--- @field vertical boolean
|
||||
--- @field horizontal boolean
|
||||
--- @field split ''|'botright'|'topleft'|'belowright'|'aboveleft'
|
||||
|
||||
--- @class vim.api.keyset.parse_cmd
|
||||
--- @field addr 'line'|'arg'|'buf'|'load'|'win'|'tab'|'qf'|'none'|'?'
|
||||
--- @field args string[]
|
||||
--- @field bang boolean
|
||||
--- @field cmd string
|
||||
--- @field magic {bar: boolean, file: boolean}
|
||||
--- @field mods vim.api.keyset.parse_cmd.mods
|
||||
--- @field nargs '0'|'1'|'?'|'+'|'*'
|
||||
--- @field nextcmd string
|
||||
--- @field range? integer[]
|
||||
--- @field count? integer
|
||||
--- @field reg? string
|
1
runtime/lua/vim/_meta/options.lua
generated
1
runtime/lua/vim/_meta/options.lua
generated
@ -7441,6 +7441,7 @@ vim.bo.vts = vim.bo.vartabstop
|
||||
---
|
||||
--- Level Messages ~
|
||||
--- ----------------------------------------------------------------------
|
||||
--- 1 Enables Lua tracing (see above). Does not produce messages.
|
||||
--- 2 When a file is ":source"'ed, or `shada` file is read or written.
|
||||
--- 3 UI info, terminal capabilities.
|
||||
--- 4 Shell commands.
|
||||
|
2
runtime/lua/vim/_meta/vimfn.lua
generated
2
runtime/lua/vim/_meta/vimfn.lua
generated
@ -2562,6 +2562,8 @@ function vim.fn.getbufinfo(buf) end
|
||||
--- bufnr Buffer number.
|
||||
--- changed TRUE if the buffer is modified.
|
||||
--- changedtick Number of changes made to the buffer.
|
||||
--- command TRUE if the buffer belongs to the
|
||||
--- command-line window |cmdwin|.
|
||||
--- hidden TRUE if the buffer is hidden.
|
||||
--- lastused Timestamp in seconds, like
|
||||
--- |localtime()|, when the buffer was
|
||||
|
@ -1909,7 +1909,7 @@ local pattern = {
|
||||
['.*baseq[2-3]/.*%.cfg'] = 'quake',
|
||||
['.*quake[1-3]/.*%.cfg'] = 'quake',
|
||||
['.*id1/.*%.cfg'] = 'quake',
|
||||
['.*/queries/.*%.scm'] = 'query', -- tree-sitter queries (Neovim only)
|
||||
['.*/queries/.*%.scm'] = 'query', -- treesitter queries (Neovim only)
|
||||
['.*,v'] = 'rcs',
|
||||
['%.reminders.*'] = starsetf('remind'),
|
||||
['[rR]akefile.*'] = starsetf('ruby'),
|
||||
|
@ -26,7 +26,7 @@ local M = {}
|
||||
|
||||
--- Table with default priorities used for highlighting:
|
||||
--- - `syntax`: `50`, used for standard syntax highlighting
|
||||
--- - `treesitter`: `100`, used for tree-sitter-based highlighting
|
||||
--- - `treesitter`: `100`, used for treesitter-based highlighting
|
||||
--- - `semantic_tokens`: `125`, used for LSP semantic token highlighting
|
||||
--- - `diagnostics`: `150`, used for code analysis such as diagnostics
|
||||
--- - `user`: `200`, used for user-triggered highlights such as LSP document
|
||||
|
@ -445,20 +445,24 @@ function Iter.join(self, delim)
|
||||
return table.concat(self:totable(), delim)
|
||||
end
|
||||
|
||||
--- Folds ("reduces") an iterator into a single value.
|
||||
--- Folds ("reduces") an iterator into a single value. \*Iter:reduce()\*
|
||||
---
|
||||
--- Examples:
|
||||
---
|
||||
--- ```lua
|
||||
--- -- Create a new table with only even values
|
||||
--- local t = { a = 1, b = 2, c = 3, d = 4 }
|
||||
--- local it = vim.iter(t)
|
||||
--- it:filter(function(k, v) return v % 2 == 0 end)
|
||||
--- it:fold({}, function(t, k, v)
|
||||
--- t[k] = v
|
||||
--- return t
|
||||
--- end)
|
||||
--- -- { b = 2, d = 4 }
|
||||
--- vim.iter({ a = 1, b = 2, c = 3, d = 4 })
|
||||
--- :filter(function(k, v) return v % 2 == 0 end)
|
||||
--- :fold({}, function(acc, k, v)
|
||||
--- acc[k] = v
|
||||
--- return acc
|
||||
--- end) --> { b = 2, d = 4 }
|
||||
---
|
||||
--- -- Get the "maximum" item of an iterable.
|
||||
--- vim.iter({ -99, -4, 3, 42, 0, 0, 7 })
|
||||
--- :fold({}, function(acc, v)
|
||||
--- acc.max = math.max(v, acc.max or v) return acc
|
||||
--- end) --> { max = 42 }
|
||||
--- ```
|
||||
---
|
||||
---@generic A
|
||||
|
@ -6,7 +6,7 @@ local M = {}
|
||||
|
||||
---@class lsp.inlay_hint.bufstate
|
||||
---@field version? integer
|
||||
---@field client_hint? table<integer, table<integer, lsp.InlayHint[]>> client_id -> (lnum -> hints)
|
||||
---@field client_hints? table<integer, table<integer, lsp.InlayHint[]>> client_id -> (lnum -> hints)
|
||||
---@field applied table<integer, integer> Last version of hints applied to this line
|
||||
---@field enabled boolean Whether inlay hints are enabled for this buffer
|
||||
---@type table<integer, lsp.inlay_hint.bufstate>
|
||||
@ -39,11 +39,11 @@ function M.on_inlayhint(err, result, ctx, _)
|
||||
if not bufstate or not bufstate.enabled then
|
||||
return
|
||||
end
|
||||
if not (bufstate.client_hint and bufstate.version) then
|
||||
bufstate.client_hint = vim.defaulttable()
|
||||
if not (bufstate.client_hints and bufstate.version) then
|
||||
bufstate.client_hints = vim.defaulttable()
|
||||
bufstate.version = ctx.version
|
||||
end
|
||||
local hints_by_client = bufstate.client_hint
|
||||
local hints_by_client = bufstate.client_hints
|
||||
local client = assert(vim.lsp.get_client_by_id(client_id))
|
||||
|
||||
local new_hints_by_lnum = vim.defaulttable()
|
||||
@ -162,7 +162,7 @@ function M.get(filter)
|
||||
end
|
||||
|
||||
local bufstate = bufstates[bufnr]
|
||||
if not (bufstate and bufstate.client_hint) then
|
||||
if not (bufstate and bufstate.client_hints) then
|
||||
return {}
|
||||
end
|
||||
|
||||
@ -185,7 +185,7 @@ function M.get(filter)
|
||||
--- @type vim.lsp.inlay_hint.get.ret[]
|
||||
local hints = {}
|
||||
for _, client in pairs(clients) do
|
||||
local hints_by_lnum = bufstate.client_hint[client.id]
|
||||
local hints_by_lnum = bufstate.client_hints[client.id]
|
||||
if hints_by_lnum then
|
||||
for lnum = range.start.line, range['end'].line do
|
||||
local line_hints = hints_by_lnum[lnum] or {}
|
||||
@ -218,11 +218,11 @@ local function clear(bufnr)
|
||||
return
|
||||
end
|
||||
local bufstate = bufstates[bufnr]
|
||||
local client_lens = (bufstate or {}).client_hint or {}
|
||||
local client_lens = (bufstate or {}).client_hints or {}
|
||||
local client_ids = vim.tbl_keys(client_lens) --- @type integer[]
|
||||
for _, iter_client_id in ipairs(client_ids) do
|
||||
if bufstate then
|
||||
bufstate.client_hint[iter_client_id] = {}
|
||||
bufstate.client_hints[iter_client_id] = {}
|
||||
end
|
||||
end
|
||||
api.nvim_buf_clear_namespace(bufnr, namespace, 0, -1)
|
||||
@ -319,7 +319,7 @@ api.nvim_set_decoration_provider(namespace, {
|
||||
if bufstate.version ~= util.buf_versions[bufnr] then
|
||||
return
|
||||
end
|
||||
local hints_by_client = assert(bufstate.client_hint)
|
||||
local hints_by_client = assert(bufstate.client_hints)
|
||||
|
||||
for lnum = topline, botline do
|
||||
if bufstate.applied[lnum] ~= bufstate.version then
|
||||
|
@ -517,16 +517,4 @@ function M.foldexpr(lnum)
|
||||
return require('vim.treesitter._fold').foldexpr(lnum)
|
||||
end
|
||||
|
||||
--- Returns the highlighted content of the first line of the fold or falls back to |foldtext()|
|
||||
--- if no treesitter parser is found. Can be set directly to 'foldtext':
|
||||
---
|
||||
--- ```lua
|
||||
--- vim.wo.foldtext = 'v:lua.vim.treesitter.foldtext()'
|
||||
--- ```
|
||||
---
|
||||
---@return { [1]: string, [2]: string[] }[] | string
|
||||
function M.foldtext()
|
||||
return require('vim.treesitter._fold').foldtext()
|
||||
end
|
||||
|
||||
return M
|
||||
|
@ -397,97 +397,4 @@ api.nvim_create_autocmd('OptionSet', {
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
---@package
|
||||
---@return { [1]: string, [2]: string[] }[]|string
|
||||
function M.foldtext()
|
||||
local foldstart = vim.v.foldstart
|
||||
local bufnr = api.nvim_get_current_buf()
|
||||
|
||||
---@type boolean, LanguageTree
|
||||
local ok, parser = pcall(ts.get_parser, bufnr)
|
||||
if not ok then
|
||||
return vim.fn.foldtext()
|
||||
end
|
||||
|
||||
local query = ts.query.get(parser:lang(), 'highlights')
|
||||
if not query then
|
||||
return vim.fn.foldtext()
|
||||
end
|
||||
|
||||
local tree = parser:parse({ foldstart - 1, foldstart })[1]
|
||||
|
||||
local line = api.nvim_buf_get_lines(bufnr, foldstart - 1, foldstart, false)[1]
|
||||
if not line then
|
||||
return vim.fn.foldtext()
|
||||
end
|
||||
|
||||
---@type { [1]: string, [2]: string[], range: { [1]: integer, [2]: integer } }[] | { [1]: string, [2]: string[] }[]
|
||||
local result = {}
|
||||
|
||||
local line_pos = 0
|
||||
|
||||
for id, node, metadata in query:iter_captures(tree:root(), 0, foldstart - 1, foldstart) do
|
||||
local name = query.captures[id]
|
||||
local start_row, start_col, end_row, end_col = node:range()
|
||||
|
||||
local priority = tonumber(metadata.priority or vim.highlight.priorities.treesitter)
|
||||
|
||||
if start_row == foldstart - 1 and end_row == foldstart - 1 then
|
||||
-- check for characters ignored by treesitter
|
||||
if start_col > line_pos then
|
||||
table.insert(result, {
|
||||
line:sub(line_pos + 1, start_col),
|
||||
{},
|
||||
range = { line_pos, start_col },
|
||||
})
|
||||
end
|
||||
line_pos = end_col
|
||||
|
||||
local text = line:sub(start_col + 1, end_col)
|
||||
table.insert(result, { text, { { '@' .. name, priority } }, range = { start_col, end_col } })
|
||||
end
|
||||
end
|
||||
|
||||
local i = 1
|
||||
while i <= #result do
|
||||
-- find first capture that is not in current range and apply highlights on the way
|
||||
local j = i + 1
|
||||
while
|
||||
j <= #result
|
||||
and result[j].range[1] >= result[i].range[1]
|
||||
and result[j].range[2] <= result[i].range[2]
|
||||
do
|
||||
for k, v in ipairs(result[i][2]) do
|
||||
if not vim.tbl_contains(result[j][2], v) then
|
||||
table.insert(result[j][2], k, v)
|
||||
end
|
||||
end
|
||||
j = j + 1
|
||||
end
|
||||
|
||||
-- remove the parent capture if it is split into children
|
||||
if j > i + 1 then
|
||||
table.remove(result, i)
|
||||
else
|
||||
-- highlights need to be sorted by priority, on equal prio, the deeper nested capture (earlier
|
||||
-- in list) should be considered higher prio
|
||||
if #result[i][2] > 1 then
|
||||
table.sort(result[i][2], function(a, b)
|
||||
return a[2] < b[2]
|
||||
end)
|
||||
end
|
||||
|
||||
result[i][2] = vim.tbl_map(function(tbl)
|
||||
return tbl[1]
|
||||
end, result[i][2])
|
||||
result[i] = { result[i][1], result[i][2] }
|
||||
|
||||
i = i + 1
|
||||
end
|
||||
end
|
||||
|
||||
return result
|
||||
end
|
||||
|
||||
return M
|
||||
|
@ -14,7 +14,7 @@ local M = {}
|
||||
local TSTreeView = {}
|
||||
|
||||
---@class TSP.Node
|
||||
---@field node TSNode Tree-sitter node
|
||||
---@field node TSNode Treesitter node
|
||||
---@field field string? Node field
|
||||
---@field depth integer Depth of this node in the tree
|
||||
---@field text string? Text displayed in the inspector for this node. Not computed until the
|
||||
|
@ -138,9 +138,7 @@ function M.register(lang, filetype)
|
||||
end
|
||||
end
|
||||
|
||||
--- Inspects the provided language.
|
||||
---
|
||||
--- Inspecting provides some useful information on the language like node names, ...
|
||||
--- Gets some useful information on the language like node names, ...
|
||||
---
|
||||
---@param lang string Language
|
||||
---@return table
|
||||
|
@ -1,6 +1,10 @@
|
||||
local tty = vim.iter(vim.api.nvim_list_uis()):any(function(ui)
|
||||
return ui.chan == 1 and ui.stdout_tty
|
||||
end)
|
||||
local tty = false
|
||||
for _, ui in ipairs(vim.api.nvim_list_uis()) do
|
||||
if ui.chan == 1 and ui.stdout_tty then
|
||||
tty = true
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if not tty or vim.g.clipboard ~= nil or vim.o.clipboard ~= '' or not os.getenv('SSH_TTY') then
|
||||
return
|
||||
|
@ -1,9 +1,9 @@
|
||||
" Vim syntax file
|
||||
" Language: ANT build file (xml)
|
||||
" Maintainer: Johannes Zellner <johannes@zellner.org>
|
||||
" Last Change: Tue Apr 27 13:05:59 CEST 2004
|
||||
" Filenames: build.xml
|
||||
" $Id: ant.vim,v 1.1 2004/06/13 18:13:18 vimboss Exp $
|
||||
" Language: ANT build file (xml)
|
||||
" Maintainer: Doug Kearns <dougkearns@gmail.com>
|
||||
" Previous Maintainer: Johannes Zellner <johannes@zellner.org>
|
||||
" Last Change: 2024 Jan 27
|
||||
" Filenames: build.xml
|
||||
|
||||
" Quit when a syntax file was already loaded
|
||||
if exists("b:current_syntax")
|
||||
@ -44,48 +44,48 @@ call AntSyntaxScript('jpython', 'python.vim')
|
||||
|
||||
syn cluster xmlTagHook add=antElement
|
||||
|
||||
syn keyword antElement display WsdlToDotnet addfiles and ant antcall antstructure apply archives arg argument
|
||||
syn keyword antElement display assertions attrib attribute available basename bcc blgenclient bootclasspath
|
||||
syn keyword antElement display borland bottom buildnumber buildpath buildpathelement bunzip2 bzip2 cab
|
||||
syn keyword antElement display catalogpath cc cccheckin cccheckout cclock ccmcheckin ccmcheckintask ccmcheckout
|
||||
syn keyword antElement display ccmcreatetask ccmkattr ccmkbl ccmkdir ccmkelem ccmklabel ccmklbtype
|
||||
syn keyword antElement display ccmreconfigure ccrmtype ccuncheckout ccunlock ccupdate checksum chgrp chmod
|
||||
syn keyword antElement display chown classconstants classes classfileset classpath commandline comment
|
||||
syn keyword antElement display compilerarg compilerclasspath concat concatfilter condition copy copydir
|
||||
syn keyword antElement display copyfile coveragepath csc custom cvs cvschangelog cvspass cvstagdiff cvsversion
|
||||
syn keyword antElement display daemons date defaultexcludes define delete deletecharacters deltree depend
|
||||
syn keyword antElement display depends dependset depth description different dirname dirset disable dname
|
||||
syn keyword antElement display doclet doctitle dtd ear echo echoproperties ejbjar element enable entity entry
|
||||
syn keyword antElement display env equals escapeunicode exclude excludepackage excludesfile exec execon
|
||||
syn keyword antElement display existing expandproperties extdirs extension extensionSet extensionset factory
|
||||
syn keyword antElement display fail filelist filename filepath fileset filesmatch filetokenizer filter
|
||||
syn keyword antElement display filterchain filterreader filters filterset filtersfile fixcrlf footer format
|
||||
syn keyword antElement display from ftp generic genkey get gjdoc grant group gunzip gzip header headfilter http
|
||||
syn keyword antElement display ignoreblank ilasm ildasm import importtypelib include includesfile input iplanet
|
||||
syn keyword antElement display iplanet-ejbc isfalse isreference isset istrue jar jarlib-available
|
||||
syn keyword antElement display jarlib-manifest jarlib-resolve java javac javacc javadoc javadoc2 jboss jdepend
|
||||
syn keyword antElement display jjdoc jjtree jlink jonas jpcoverage jpcovmerge jpcovreport jsharpc jspc
|
||||
syn keyword antElement display junitreport jvmarg lib libfileset linetokenizer link loadfile loadproperties
|
||||
syn keyword antElement display location macrodef mail majority manifest map mapper marker mergefiles message
|
||||
syn keyword antElement display metainf method mimemail mkdir mmetrics modified move mparse none not options or
|
||||
syn keyword antElement display os outputproperty package packageset parallel param patch path pathconvert
|
||||
syn keyword antElement display pathelement patternset permissions prefixlines present presetdef project
|
||||
syn keyword antElement display property propertyfile propertyref propertyset pvcs pvcsproject record reference
|
||||
syn keyword antElement display regexp rename renameext replace replacefilter replaceregex replaceregexp
|
||||
syn keyword antElement display replacestring replacetoken replacetokens replacevalue replyto report resource
|
||||
syn keyword antElement display revoke rmic root rootfileset rpm scp section selector sequential serverdeploy
|
||||
syn keyword antElement display setproxy signjar size sleep socket soscheckin soscheckout sosget soslabel source
|
||||
syn keyword antElement display sourcepath sql src srcfile srcfilelist srcfiles srcfileset sshexec stcheckin
|
||||
syn keyword antElement display stcheckout stlabel stlist stringtokenizer stripjavacomments striplinebreaks
|
||||
syn keyword antElement display striplinecomments style subant substitution support symlink sync sysproperty
|
||||
syn keyword antElement display syspropertyset tabstospaces tag taglet tailfilter tar tarfileset target
|
||||
syn keyword antElement display targetfile targetfilelist targetfileset taskdef tempfile test testlet text title
|
||||
syn keyword antElement display to token tokenfilter touch transaction translate triggers trim tstamp type
|
||||
syn keyword antElement display typedef unjar untar unwar unzip uptodate url user vbc vssadd vsscheckin
|
||||
syn keyword antElement display vsscheckout vsscp vsscreate vssget vsshistory vsslabel waitfor war wasclasspath
|
||||
syn keyword antElement display webapp webinf weblogic weblogictoplink websphere whichresource wlclasspath
|
||||
syn keyword antElement display wljspc wsdltodotnet xmlcatalog xmlproperty xmlvalidate xslt zip zipfileset
|
||||
syn keyword antElement display zipgroupfileset
|
||||
syn keyword antElement WsdlToDotnet addfiles and ant antcall antstructure apply archives arg argument
|
||||
syn keyword antElement assertions attrib attribute available basename bcc blgenclient bootclasspath
|
||||
syn keyword antElement borland bottom buildnumber buildpath buildpathelement bunzip2 bzip2 cab
|
||||
syn keyword antElement catalogpath cc cccheckin cccheckout cclock ccmcheckin ccmcheckintask ccmcheckout
|
||||
syn keyword antElement ccmcreatetask ccmkattr ccmkbl ccmkdir ccmkelem ccmklabel ccmklbtype
|
||||
syn keyword antElement ccmreconfigure ccrmtype ccuncheckout ccunlock ccupdate checksum chgrp chmod
|
||||
syn keyword antElement chown classconstants classes classfileset classpath commandline comment
|
||||
syn keyword antElement compilerarg compilerclasspath concat concatfilter condition copy copydir
|
||||
syn keyword antElement copyfile coveragepath csc custom cvs cvschangelog cvspass cvstagdiff cvsversion
|
||||
syn keyword antElement daemons date defaultexcludes define delete deletecharacters deltree depend
|
||||
syn keyword antElement depends dependset depth description different dirname dirset disable dname
|
||||
syn keyword antElement doclet doctitle dtd ear echo echoproperties ejbjar element enable entity entry
|
||||
syn keyword antElement env equals escapeunicode exclude excludepackage excludesfile exec execon
|
||||
syn keyword antElement existing expandproperties extdirs extension extensionSet extensionset factory
|
||||
syn keyword antElement fail filelist filename filepath fileset filesmatch filetokenizer filter
|
||||
syn keyword antElement filterchain filterreader filters filterset filtersfile fixcrlf footer format
|
||||
syn keyword antElement from ftp generic genkey get gjdoc grant group gunzip gzip header headfilter http
|
||||
syn keyword antElement ignoreblank ilasm ildasm import importtypelib include includesfile input iplanet
|
||||
syn keyword antElement iplanet-ejbc isfalse isreference isset istrue jar jarlib-available
|
||||
syn keyword antElement jarlib-manifest jarlib-resolve java javac javacc javadoc javadoc2 jboss jdepend
|
||||
syn keyword antElement jjdoc jjtree jlink jonas jpcoverage jpcovmerge jpcovreport jsharpc jspc
|
||||
syn keyword antElement junitreport jvmarg lib libfileset linetokenizer link loadfile loadproperties
|
||||
syn keyword antElement location macrodef mail majority manifest map mapper marker mergefiles message
|
||||
syn keyword antElement metainf method mimemail mkdir mmetrics modified move mparse none not options or
|
||||
syn keyword antElement os outputproperty package packageset parallel param patch path pathconvert
|
||||
syn keyword antElement pathelement patternset permissions prefixlines present presetdef project
|
||||
syn keyword antElement property propertyfile propertyref propertyset pvcs pvcsproject record reference
|
||||
syn keyword antElement regexp rename renameext replace replacefilter replaceregex replaceregexp
|
||||
syn keyword antElement replacestring replacetoken replacetokens replacevalue replyto report resource
|
||||
syn keyword antElement revoke rmic root rootfileset rpm scp section selector sequential serverdeploy
|
||||
syn keyword antElement setproxy signjar size sleep socket soscheckin soscheckout sosget soslabel source
|
||||
syn keyword antElement sourcepath sql src srcfile srcfilelist srcfiles srcfileset sshexec stcheckin
|
||||
syn keyword antElement stcheckout stlabel stlist stringtokenizer stripjavacomments striplinebreaks
|
||||
syn keyword antElement striplinecomments style subant substitution support symlink sync sysproperty
|
||||
syn keyword antElement syspropertyset tabstospaces tag taglet tailfilter tar tarfileset target
|
||||
syn keyword antElement targetfile targetfilelist targetfileset taskdef tempfile test testlet text title
|
||||
syn keyword antElement to token tokenfilter touch transaction translate triggers trim tstamp type
|
||||
syn keyword antElement typedef unjar untar unwar unzip uptodate url user vbc vssadd vsscheckin
|
||||
syn keyword antElement vsscheckout vsscp vsscreate vssget vsshistory vsslabel waitfor war wasclasspath
|
||||
syn keyword antElement webapp webinf weblogic weblogictoplink websphere whichresource wlclasspath
|
||||
syn keyword antElement wljspc wsdltodotnet xmlcatalog xmlproperty xmlvalidate xslt zip zipfileset
|
||||
syn keyword antElement zipgroupfileset
|
||||
|
||||
hi def link antElement Statement
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
" Language: Mail file
|
||||
" Previous Maintainer: Felix von Leitner <leitner@math.fu-berlin.de>
|
||||
" Maintainer: GI <a@b.c>, where a='gi1242+vim', b='gmail', c='com'
|
||||
" Last Change: Thu 18 Jan 2024 06:34:38 PM EST
|
||||
" Last Change: Thu 25 Jan 2024 10:34:02 AM EST
|
||||
|
||||
" Quit when a syntax file was already loaded
|
||||
if exists("b:current_syntax")
|
||||
@ -64,7 +64,7 @@ syn match mailURL contains=@NoSpell `\v<(((https?|ftp|gopher)://|(mailto|file|ne
|
||||
syn match mailEmail contains=@NoSpell "\v[_=a-z\./+0-9-]+\@[a-z0-9._-]+\a{2}"
|
||||
|
||||
" Don't spell emojis
|
||||
syn match mailEmoji contains=@NoSpell "\v[\U1f300-\U1f64f\U1f900-\U1f9ff]"
|
||||
syn match mailEmoji contains=@NoSpell "\%#=2\v[\U1f300-\U1f64f\U1f900-\U1f9ff]"
|
||||
|
||||
" Make sure quote markers in regions (header / signature) have correct color
|
||||
syn match mailQuoteExp1 contained "\v^(\> ?)"
|
||||
|
@ -1,5 +1,5 @@
|
||||
-- Neovim syntax file
|
||||
-- Language: Tree-sitter query
|
||||
-- Language: Treesitter query
|
||||
-- Last Change: 2022 Apr 13
|
||||
|
||||
-- it's a lisp!
|
||||
|
@ -204,7 +204,7 @@ syn keyword vimAugroupKey contained aug[roup]
|
||||
|
||||
" Operators: {{{2
|
||||
" =========
|
||||
syn cluster vimOperGroup contains=vimEnvvar,vimFunc,vimFuncVar,vimOper,vimOperParen,vimNumber,vimString,vimType,vimRegister,vimContinue,vim9Comment,vimVar
|
||||
syn cluster vimOperGroup contains=vimEnvvar,vimFunc,vimFuncVar,vimOper,vimOperParen,vimNumber,vimString,vimType,vimRegister,@vimContinue,vim9Comment,vimVar
|
||||
syn match vimOper "||\|&&\|[-+*/%.!]" skipwhite nextgroup=vimString,vimSpecFile
|
||||
syn match vimOper "\%#=1\(==\|!=\|>=\|<=\|=\~\|!\~\|>\|<\|=\|!\~#\)[?#]\{0,2}" skipwhite nextgroup=vimString,vimSpecFile
|
||||
syn match vimOper "\(\<is\|\<isnot\)[?#]\{0,2}\>" skipwhite nextgroup=vimString,vimSpecFile
|
||||
@ -311,6 +311,12 @@ syn match vimString contained +"[^"]*\\$+ skipnl nextgroup=vimStringCont
|
||||
syn match vimStringCont contained +\(\\\\\|.\)\{-}[^\\]"+
|
||||
syn match vimEscape contained "\\."
|
||||
|
||||
syn region vimString start=+$'+ end=+'+ skip=+''+ oneline contains=vimStringInterpolationBrace,vimStringInterpolationExpr
|
||||
syn region vimString start=+$"+ end=+"+ oneline contains=@vimStringGroup,vimStringInterpolationBrace,vimStringInterpolationExpr
|
||||
syn region vimStringInterpolationExpr matchgroup=vimOperParen start=+{+ end=+}+ oneline contains=vimFunc,vimFuncVar,vimOper,vimNotation,vimOperParen,vimString,vimVar
|
||||
syn match vimStringInterpolationBrace "{{"
|
||||
syn match vimStringInterpolationBrace "}}"
|
||||
|
||||
" Substitutions: {{{2
|
||||
" =============
|
||||
syn cluster vimSubstList contains=vimPatSep,vimPatRegion,vimPatSepErr,vimSubstTwoBS,vimSubstRange,vimNotation
|
||||
@ -476,16 +482,22 @@ syn match vimNormCmds contained ".*$"
|
||||
|
||||
" Syntax: {{{2
|
||||
"=======
|
||||
syn match vimGroupList contained "@\=[^ \t,]*" contains=vimGroupSpecial,vimPatSep
|
||||
syn match vimGroupList contained "@\=[^ \t,]*," nextgroup=vimGroupList contains=vimGroupSpecial,vimPatSep
|
||||
syn match vimGroupList contained "[^[:space:],]\+\%(\s*,\s*[^[:space:],]\+\)*" contains=vimGroupSpecial
|
||||
syn region vimGroupList contained start=/^\s*["#]\\ \|^\s*\\\|[^[:space:],]\+\s*,/ skip=/\s*\n\s*\\\|\s*\n\s*["#]\\ \|^\s*\\\|^\s*["#]\\ / end=/[^[:space:],]\s*$\|[^[:space:],]\ze\s\+\w/ contains=@vimContinue,vimGroupSpecial
|
||||
syn keyword vimGroupSpecial contained ALL ALLBUT CONTAINED TOP
|
||||
|
||||
if !exists("g:vimsyn_noerror") && !exists("g:vimsyn_novimsynerror")
|
||||
syn match vimSynError contained "\i\+"
|
||||
syn match vimSynError contained "\i\+=" nextgroup=vimGroupList
|
||||
endif
|
||||
syn match vimSynContains contained "\<contain\(s\|edin\)=" nextgroup=vimGroupList
|
||||
syn match vimSynKeyContainedin contained "\<containedin=" nextgroup=vimGroupList
|
||||
syn match vimSynNextgroup contained "nextgroup=" nextgroup=vimGroupList
|
||||
syn match vimSynContains contained "\<contain\%(s\|edin\)=" skipwhite skipnl nextgroup=vimGroupList
|
||||
syn match vimSynKeyContainedin contained "\<containedin=" skipwhite skipnl nextgroup=vimGroupList
|
||||
syn match vimSynNextgroup contained "\<nextgroup=" skipwhite skipnl nextgroup=vimGroupList
|
||||
if has("conceal")
|
||||
" no whitespace allowed after '='
|
||||
syn match vimSynCchar contained "\<cchar=" nextgroup=vimSynCcharValue
|
||||
syn match vimSynCcharValue contained "\S"
|
||||
endif
|
||||
|
||||
syn match vimSyntax "\<sy\%[ntax]\>" contains=vimCommand skipwhite nextgroup=vimSynType,vimComment,vim9Comment
|
||||
syn match vimAuSyntax contained "\s+sy\%[ntax]" contains=vimCommand skipwhite nextgroup=vimSynType,vimComment,vim9Comment
|
||||
@ -503,9 +515,9 @@ syn keyword vimSynType contained clear skipwhite nextgroup=vimGroupList
|
||||
|
||||
" Syntax: cluster {{{2
|
||||
syn keyword vimSynType contained cluster skipwhite nextgroup=vimClusterName
|
||||
syn region vimClusterName contained matchgroup=vimGroupName start="\h\w*" skip="\\\\\|\\|" matchgroup=vimSep end="$\||" contains=vimGroupAdd,vimGroupRem,vimSynContains,vimSynError
|
||||
syn match vimGroupAdd contained "add=" nextgroup=vimGroupList
|
||||
syn match vimGroupRem contained "remove=" nextgroup=vimGroupList
|
||||
syn region vimClusterName contained keepend matchgroup=vimGroupName start="\h\w*\>" skip=+\\\\\|\\\|\n\s*\\\|\n\s*"\\ + matchgroup=vimCmdSep end="$\||" contains=@vimContinue,vimGroupAdd,vimGroupRem,vimSynContains,vimSynError
|
||||
syn match vimGroupAdd contained keepend "\<add=" skipwhite skipnl nextgroup=vimGroupList
|
||||
syn match vimGroupRem contained keepend "\<remove=" skipwhite skipnl nextgroup=vimGroupList
|
||||
syn cluster vimFuncBodyList add=vimSynType,vimGroupAdd,vimGroupRem
|
||||
|
||||
" Syntax: foldlevel {{{2
|
||||
@ -525,35 +537,31 @@ syn keyword vimSynType contained include skipwhite nextgroup=vimGroupList
|
||||
syn cluster vimFuncBodyList add=vimSynType
|
||||
|
||||
" Syntax: keyword {{{2
|
||||
syn cluster vimSynKeyGroup contains=vimSynNextgroup,vimSynKeyOpt,vimSynKeyContainedin
|
||||
syn cluster vimSynKeyGroup contains=@vimContinue,vimSynCchar,vimSynNextgroup,vimSynKeyOpt,vimSynKeyContainedin
|
||||
syn keyword vimSynType contained keyword skipwhite nextgroup=vimSynKeyRegion
|
||||
syn region vimSynKeyRegion contained oneline keepend matchgroup=vimGroupName start="\h\w*" skip="\\\\\|\\|" matchgroup=vimSep end="|\|$" contains=@vimSynKeyGroup
|
||||
syn region vimSynKeyRegion contained keepend matchgroup=vimGroupName start="\h\w*\>" skip=+\\\\\|\\|\|\n\s*\\\|\n\s*"\\ + matchgroup=vimCmdSep end="|\|$" contains=@vimSynKeyGroup
|
||||
syn match vimSynKeyOpt contained "\%#=1\<\(conceal\|contained\|transparent\|skipempty\|skipwhite\|skipnl\)\>"
|
||||
syn cluster vimFuncBodyList add=vimSynType
|
||||
|
||||
" Syntax: match {{{2
|
||||
syn cluster vimSynMtchGroup contains=vimMtchComment,vimSynContains,vimSynError,vimSynMtchOpt,vimSynNextgroup,vimSynRegPat,vimNotation,vim9Comment
|
||||
syn cluster vimSynMtchGroup contains=@vimContinue,vimSynCchar,vimSynContains,vimSynError,vimSynMtchOpt,vimSynNextgroup,vimSynRegPat,vimNotation,vimMtchComment
|
||||
syn keyword vimSynType contained match skipwhite nextgroup=vimSynMatchRegion
|
||||
syn region vimSynMatchRegion contained keepend matchgroup=vimGroupName start="\h\w*" matchgroup=vimSep end="|\|$" contains=@vimSynMtchGroup
|
||||
syn region vimSynMatchRegion contained keepend matchgroup=vimGroupName start="\h\w*\>" skip=+\\\\\|\\|\|\n\s*\\\|\n\s*"\\ + matchgroup=vimCmdSep end="|\|$" contains=@vimSynMtchGroup
|
||||
syn match vimSynMtchOpt contained "\%#=1\<\(conceal\|transparent\|contained\|excludenl\|keepend\|skipempty\|skipwhite\|display\|extend\|skipnl\|fold\)\>"
|
||||
if has("conceal")
|
||||
syn match vimSynMtchOpt contained "\<cchar=" nextgroup=vimSynMtchCchar
|
||||
syn match vimSynMtchCchar contained "\S"
|
||||
endif
|
||||
syn cluster vimFuncBodyList add=vimSynMtchGroup
|
||||
|
||||
" Syntax: off and on {{{2
|
||||
syn keyword vimSynType contained enable list manual off on reset
|
||||
|
||||
" Syntax: region {{{2
|
||||
syn cluster vimSynRegPatGroup contains=vimPatSep,vimNotPatSep,vimSynPatRange,vimSynNotPatRange,vimSubstSubstr,vimPatRegion,vimPatSepErr,vimNotation
|
||||
syn cluster vimSynRegGroup contains=vimSynContains,vimSynNextgroup,vimSynRegOpt,vimSynReg,vimSynMtchGrp
|
||||
syn cluster vimSynRegPatGroup contains=@vimContinue,vimPatSep,vimNotPatSep,vimSynPatRange,vimSynNotPatRange,vimSubstSubstr,vimPatRegion,vimPatSepErr,vimNotation
|
||||
syn cluster vimSynRegGroup contains=@vimContinue,vimSynCchar,vimSynContains,vimSynNextgroup,vimSynRegOpt,vimSynReg,vimSynMtchGrp
|
||||
syn keyword vimSynType contained region skipwhite nextgroup=vimSynRegion
|
||||
syn region vimSynRegion contained keepend matchgroup=vimGroupName start="\h\w*" skip="\\\\\|\\|" end="|\|$" contains=@vimSynRegGroup
|
||||
syn region vimSynRegion contained keepend matchgroup=vimGroupName start="\h\w*" skip=+\\\\\|\\\|\n\s*\\\|\n\s*"\\ + end="|\|$" contains=@vimSynRegGroup
|
||||
syn match vimSynRegOpt contained "\%#=1\<\(conceal\(ends\)\=\|transparent\|contained\|excludenl\|skipempty\|skipwhite\|display\|keepend\|oneline\|extend\|skipnl\|fold\)\>"
|
||||
syn match vimSynReg contained "\(start\|skip\|end\)="he=e-1 nextgroup=vimSynRegPat
|
||||
syn match vimSynReg contained "\<\%(start\|skip\|end\)=" nextgroup=vimSynRegPat
|
||||
syn match vimSynMtchGrp contained "matchgroup=" nextgroup=vimGroup,vimHLGroup,vimOnlyHLGroup,nvimHLGroup
|
||||
syn region vimSynRegPat contained extend start="\z([-`~!@#$%^&*_=+;:'",./?]\)" skip="\\\\\|\\\z1" end="\z1" contains=@vimSynRegPatGroup skipwhite nextgroup=vimSynPatMod,vimSynReg
|
||||
syn region vimSynRegPat contained extend start="\z([-`~!@#$%^&*_=+;:'",./?]\)" skip=/\\\\\|\\\z1\|\n\s*\\\|\n\s*"\\ / end="\z1" contains=@vimSynRegPatGroup skipwhite nextgroup=vimSynPatMod,vimSynReg
|
||||
syn match vimSynPatMod contained "\%#=1\(hs\|ms\|me\|hs\|he\|rs\|re\)=[se]\([-+]\d\+\)\="
|
||||
syn match vimSynPatMod contained "\%#=1\(hs\|ms\|me\|hs\|he\|rs\|re\)=[se]\([-+]\d\+\)\=," nextgroup=vimSynPatMod
|
||||
syn match vimSynPatMod contained "lc=\d\+"
|
||||
@ -642,10 +650,14 @@ syn match vimCtrlChar "[--]"
|
||||
|
||||
" Beginners - Patterns that involve ^ {{{2
|
||||
" =========
|
||||
syn match vimLineComment +^[ \t:]*".*$+ contains=@vimCommentGroup,vimCommentString,vimCommentTitle
|
||||
syn match vimLineComment +^[ \t:]*".*$+ contains=@vimCommentGroup,vimCommentString,vimCommentTitle,vimComment
|
||||
syn match vimLineComment +^[ \t:]*"\("[^"]*"\|[^"]\)*$+ contains=@vimCommentGroup,vimCommentString,vimCommentTitle
|
||||
syn match vim9LineComment +^[ \t:]\+#.*$+ contains=@vimCommentGroup,vimCommentString,vimCommentTitle
|
||||
syn match vimCommentTitle '"\s*\%([sS]:\|\h\w*#\)\=\u\w*\(\s\+\u\w*\)*:'hs=s+1 contained contains=vimCommentTitleLeader,vimTodo,@vimCommentGroup
|
||||
syn match vimContinue "^\s*\\"
|
||||
" Note: Look-behind to work around nextgroup skipnl consuming leading whitespace and preventing a match
|
||||
syn match vimContinue "^\s*\zs\\"
|
||||
syn match vimContinueComment '^\s*\zs["#]\\ .*' contained
|
||||
syn cluster vimContinue contains=vimContinue,vimContinueComment
|
||||
syn region vimString start="^\s*\\\z(['"]\)" skip='\\\\\|\\\z1' end="\z1" oneline keepend contains=@vimStringGroup,vimContinue
|
||||
syn match vimCommentTitleLeader '"\s\+'ms=s+1 contained
|
||||
|
||||
@ -889,6 +901,7 @@ if !exists("skip_vim_syntax_inits")
|
||||
hi def link vimCondHL vimCommand
|
||||
hi def link vimConst vimCommand
|
||||
hi def link vimContinue Special
|
||||
hi def link vimContinueComment vimComment
|
||||
hi def link vimCtrlChar SpecialChar
|
||||
hi def link vimEchoHLNone vimGroup
|
||||
hi def link vimEchoHL vimCommand
|
||||
@ -984,6 +997,7 @@ if !exists("skip_vim_syntax_inits")
|
||||
hi def link vimStringCont vimString
|
||||
hi def link vimString String
|
||||
hi def link vimStringEnd vimString
|
||||
hi def link vimStringInterpolationBrace vimEscape
|
||||
hi def link vimSubst1 vimSubst
|
||||
hi def link vimSubstDelim Delimiter
|
||||
hi def link vimSubstFlags Special
|
||||
@ -1004,6 +1018,8 @@ if !exists("skip_vim_syntax_inits")
|
||||
hi def link vimSynFoldMethod Type
|
||||
hi def link vimSynKeyContainedin vimSynContains
|
||||
hi def link vimSynKeyOpt vimSynOption
|
||||
hi def link vimSynCchar vimSynOption
|
||||
hi def link vimSynCcharValue Character
|
||||
hi def link vimSynMtchGrp vimSynOption
|
||||
hi def link vimSynMtchOpt vimSynOption
|
||||
hi def link vimSynNextgroup vimSynOption
|
||||
|
@ -1,3 +1,5 @@
|
||||
#!/usr/bin/env -S nvim -l
|
||||
|
||||
-- Generator for various vimdoc and Lua type files
|
||||
|
||||
local DEP_API_METADATA = 'build/api_metadata.mpack'
|
||||
@ -17,6 +19,31 @@ local DEP_API_DOC = 'runtime/doc/api.mpack'
|
||||
--- @field remote boolean
|
||||
--- @field since integer
|
||||
|
||||
local LUA_API_RETURN_OVERRIDES = {
|
||||
nvim_buf_get_command = 'table<string,vim.api.keyset.command_info>',
|
||||
nvim_buf_get_extmark_by_id = 'vim.api.keyset.get_extmark_item',
|
||||
nvim_buf_get_extmarks = 'vim.api.keyset.get_extmark_item[]',
|
||||
nvim_buf_get_keymap = 'vim.api.keyset.keymap[]',
|
||||
nvim_get_autocmds = 'vim.api.keyset.get_autocmds.ret[]',
|
||||
nvim_get_color_map = 'table<string,integer>',
|
||||
nvim_get_command = 'table<string,vim.api.keyset.command_info>',
|
||||
nvim_get_keymap = 'vim.api.keyset.keymap[]',
|
||||
nvim_get_mark = 'vim.api.keyset.get_mark',
|
||||
|
||||
-- Can also return table<string,vim.api.keyset.hl_info>, however we need to
|
||||
-- pick one to get some benefit.
|
||||
-- REVISIT lewrus01 (26/01/24): we can maybe add
|
||||
-- @overload fun(ns: integer, {}): table<string,vim.api.keyset.hl_info>
|
||||
nvim_get_hl = 'vim.api.keyset.hl_info',
|
||||
|
||||
nvim_get_mode = 'vim.api.keyset.get_mode',
|
||||
nvim_get_namespaces = 'table<string,integer>',
|
||||
nvim_get_option_info = 'vim.api.keyset.get_option_info',
|
||||
nvim_get_option_info2 = 'vim.api.keyset.get_option_info',
|
||||
nvim_parse_cmd = 'vim.api.keyset.parse_cmd',
|
||||
nvim_win_get_config = 'vim.api.keyset.float_config',
|
||||
}
|
||||
|
||||
local LUA_META_HEADER = {
|
||||
'--- @meta _',
|
||||
'-- THIS FILE IS GENERATED',
|
||||
@ -289,11 +316,9 @@ local function render_api_meta(_f, fun, write)
|
||||
end
|
||||
end
|
||||
if fun.returns ~= '' then
|
||||
if fun.returns_desc then
|
||||
write('--- @return ' .. fun.returns .. ' : ' .. fun.returns_desc)
|
||||
else
|
||||
write('--- @return ' .. fun.returns)
|
||||
end
|
||||
local ret_desc = fun.returns_desc and ' : ' .. fun.returns_desc or ''
|
||||
local ret = LUA_API_RETURN_OVERRIDES[fun.name] or fun.returns
|
||||
write('--- @return ' .. ret .. ret_desc)
|
||||
end
|
||||
local param_str = table.concat(param_names, ', ')
|
||||
|
||||
|
@ -2,32 +2,38 @@
|
||||
--
|
||||
-- NOTE: :helptags checks for duplicate tags, whereas this script checks _links_ (to tags).
|
||||
--
|
||||
-- USAGE (For CI/local testing purposes): Simply `make lintdoc` or `scripts/lintdoc.lua`, which
|
||||
-- basically does the following:
|
||||
-- 1. :helptags ALL
|
||||
-- 2. nvim -V1 -es +"lua require('scripts.gen_help_html').run_validate()" +q
|
||||
-- 3. nvim -V1 -es +"lua require('scripts.gen_help_html').test_gen()" +q
|
||||
--
|
||||
-- USAGE (GENERATE HTML):
|
||||
-- 1. Run `make helptags` first; this script depends on vim.fn.taglist().
|
||||
-- 2. nvim -V1 -es --clean +"lua require('scripts.gen_help_html').gen('./build/runtime/doc/', 'target/dir/')"
|
||||
-- 1. `:helptags ALL` first; this script depends on vim.fn.taglist().
|
||||
-- 2. nvim -V1 -es --clean +"lua require('scripts.gen_help_html').gen('./runtime/doc', 'target/dir/')" +q
|
||||
-- - Read the docstring at gen().
|
||||
-- 3. cd target/dir/ && jekyll serve --host 0.0.0.0
|
||||
-- 4. Visit http://localhost:4000/…/help.txt.html
|
||||
--
|
||||
-- USAGE (VALIDATE):
|
||||
-- 1. nvim -V1 -es +"lua require('scripts.gen_help_html').validate()"
|
||||
-- 1. nvim -V1 -es +"lua require('scripts.gen_help_html').validate('./runtime/doc')" +q
|
||||
-- - validate() is 10x faster than gen(), so it is used in CI.
|
||||
--
|
||||
-- SELF-TEST MODE:
|
||||
-- 1. nvim -V1 -es +"lua require('scripts.gen_help_html')._test()"
|
||||
-- 1. nvim -V1 -es +"lua require('scripts.gen_help_html')._test()" +q
|
||||
--
|
||||
-- NOTES:
|
||||
-- * gen() and validate() are the primary entrypoints. validate() only exists because gen() is too
|
||||
-- slow (~1 min) to run in per-commit CI.
|
||||
-- * gen() and validate() are the primary (programmatic) entrypoints. validate() only exists
|
||||
-- because gen() is too slow (~1 min) to run in per-commit CI.
|
||||
-- * visit_node() is the core function used by gen() to traverse the document tree and produce HTML.
|
||||
-- * visit_validate() is the core function used by validate().
|
||||
-- * Files in `new_layout` will be generated with a "flow" layout instead of preformatted/fixed-width layout.
|
||||
|
||||
local tagmap = nil
|
||||
local helpfiles = nil
|
||||
local invalid_links = {}
|
||||
local invalid_urls = {}
|
||||
local invalid_spelling = {}
|
||||
local tagmap = nil ---@type table<string, string>
|
||||
local helpfiles = nil ---@type string[]
|
||||
local invalid_links = {} ---@type table<string, any>
|
||||
local invalid_urls = {} ---@type table<string, any>
|
||||
local invalid_spelling = {} ---@type table<string, table<string, string>>
|
||||
local spell_dict = {
|
||||
Neovim = 'Nvim',
|
||||
NeoVim = 'Nvim',
|
||||
@ -36,9 +42,14 @@ local spell_dict = {
|
||||
VimL = 'Vimscript',
|
||||
vimL = 'Vimscript',
|
||||
viml = 'Vimscript',
|
||||
['tree-sitter'] = 'treesitter',
|
||||
['Tree-sitter'] = 'Treesitter',
|
||||
}
|
||||
--- specify the list of keywords to ignore (i.e. allow), or true to disable spell check completely.
|
||||
--- @type table<string, true|string[]>
|
||||
local spell_ignore_files = {
|
||||
['backers.txt'] = 'true',
|
||||
['backers.txt'] = true,
|
||||
['news.txt'] = { 'tree-sitter' }, -- in news, may refer to the upstream "tree-sitter" library
|
||||
}
|
||||
local language = nil
|
||||
|
||||
@ -102,8 +113,9 @@ local function tofile(fname, text)
|
||||
end
|
||||
end
|
||||
|
||||
---@type fun(s: string): string
|
||||
local function html_esc(s)
|
||||
return s:gsub('&', '&'):gsub('<', '<'):gsub('>', '>')
|
||||
return (s:gsub('&', '&'):gsub('<', '<'):gsub('>', '>'))
|
||||
end
|
||||
|
||||
local function url_encode(s)
|
||||
@ -118,7 +130,7 @@ local function url_encode(s)
|
||||
end
|
||||
|
||||
local function expandtabs(s)
|
||||
return s:gsub('\t', (' '):rep(8))
|
||||
return s:gsub('\t', (' '):rep(8)) --[[ @as string ]]
|
||||
end
|
||||
|
||||
local function to_titlecase(s)
|
||||
@ -142,6 +154,7 @@ local function is_blank(s)
|
||||
return not not s:find([[^[\t ]*$]])
|
||||
end
|
||||
|
||||
---@type fun(s: string, dir?:0|1|2): string
|
||||
local function trim(s, dir)
|
||||
return vim.fn.trim(s, '\r\t\n ', dir or 0)
|
||||
end
|
||||
@ -150,7 +163,8 @@ end
|
||||
---
|
||||
--- TODO: fix this in the parser instead... https://github.com/neovim/tree-sitter-vimdoc
|
||||
---
|
||||
--- @returns (fixed_url, removed_chars) where `removed_chars` is in the order found in the input.
|
||||
--- @param url string
|
||||
--- @return string, string (fixed_url, removed_chars) where `removed_chars` is in the order found in the input.
|
||||
local function fix_url(url)
|
||||
local removed_chars = ''
|
||||
local fixed_url = url
|
||||
@ -262,6 +276,9 @@ local function trim_indent(s)
|
||||
end
|
||||
|
||||
--- Gets raw buffer text in the node's range (+/- an offset), as a newline-delimited string.
|
||||
---@param node TSNode
|
||||
---@param bufnr integer
|
||||
---@param offset integer
|
||||
local function getbuflinestr(node, bufnr, offset)
|
||||
local line1, _, line2, _ = node:range()
|
||||
line1 = line1 - offset
|
||||
@ -272,8 +289,12 @@ end
|
||||
|
||||
--- Gets the whitespace just before `node` from the raw buffer text.
|
||||
--- Needed for preformatted `old` lines.
|
||||
---@param node TSNode
|
||||
---@param bufnr integer
|
||||
---@return string
|
||||
local function getws(node, bufnr)
|
||||
local line1, c1, line2, _ = node:range()
|
||||
---@type string
|
||||
local raw = vim.fn.getbufline(bufnr, line1 + 1, line2 + 1)[1]
|
||||
local text_before = raw:sub(1, c1)
|
||||
local leading_ws = text_before:match('%s+$') or ''
|
||||
@ -310,9 +331,10 @@ local function ignore_parse_error(fname, s)
|
||||
return s:find("^[`'|*]")
|
||||
end
|
||||
|
||||
---@param node TSNode
|
||||
local function has_ancestor(node, ancestor_name)
|
||||
local p = node
|
||||
while true do
|
||||
local p = node ---@type TSNode?
|
||||
while p do
|
||||
p = p:parent()
|
||||
if not p or p:type() == 'help_file' then
|
||||
break
|
||||
@ -324,6 +346,7 @@ local function has_ancestor(node, ancestor_name)
|
||||
end
|
||||
|
||||
--- Gets the first matching child node matching `name`.
|
||||
---@param node TSNode
|
||||
local function first(node, name)
|
||||
for c, _ in node:iter_children() do
|
||||
if c:named() and c:type() == name then
|
||||
@ -357,6 +380,11 @@ local function validate_url(text, fname)
|
||||
end
|
||||
|
||||
--- Traverses the tree at `root` and checks that |tag| links point to valid helptags.
|
||||
---@param root TSNode
|
||||
---@param level integer
|
||||
---@param lang_tree TSTree
|
||||
---@param opt table
|
||||
---@param stats table
|
||||
local function visit_validate(root, level, lang_tree, opt, stats)
|
||||
level = level or 0
|
||||
local node_name = (root.named and root:named()) and root:type() or nil
|
||||
@ -391,9 +419,18 @@ local function visit_validate(root, level, lang_tree, opt, stats)
|
||||
then
|
||||
local text_nopunct = vim.fn.trim(text, '.,', 0) -- Ignore some punctuation.
|
||||
local fname_basename = assert(vim.fs.basename(opt.fname))
|
||||
if spell_dict[text_nopunct] and not spell_ignore_files[fname_basename] then
|
||||
invalid_spelling[text_nopunct] = invalid_spelling[text_nopunct] or {}
|
||||
invalid_spelling[text_nopunct][fname_basename] = node_text(root:parent())
|
||||
if spell_dict[text_nopunct] then
|
||||
local should_ignore = (
|
||||
spell_ignore_files[fname_basename] == true
|
||||
or vim.tbl_contains(
|
||||
(spell_ignore_files[fname_basename] or {}) --[[ @as string[] ]],
|
||||
text_nopunct
|
||||
)
|
||||
)
|
||||
if not should_ignore then
|
||||
invalid_spelling[text_nopunct] = invalid_spelling[text_nopunct] or {}
|
||||
invalid_spelling[text_nopunct][fname_basename] = node_text(root:parent())
|
||||
end
|
||||
end
|
||||
elseif node_name == 'url' then
|
||||
local fixed_url, _ = fix_url(trim(text))
|
||||
@ -405,6 +442,8 @@ end
|
||||
|
||||
-- Fix tab alignment issues caused by concealed characters like |, `, * in tags
|
||||
-- and code blocks.
|
||||
---@param text string
|
||||
---@param next_node_text string
|
||||
local function fix_tab_after_conceal(text, next_node_text)
|
||||
-- Vim tabs take into account the two concealed characters even though they
|
||||
-- are invisible, so we need to add back in the two spaces if this is
|
||||
@ -415,7 +454,18 @@ local function fix_tab_after_conceal(text, next_node_text)
|
||||
return text
|
||||
end
|
||||
|
||||
---@class (exact) nvim.gen_help_html.heading
|
||||
---@field name string
|
||||
---@field subheadings nvim.gen_help_html.heading[]
|
||||
---@field tag string
|
||||
|
||||
-- Generates HTML from node `root` recursively.
|
||||
---@param root TSNode
|
||||
---@param level integer
|
||||
---@param lang_tree TSTree
|
||||
---@param headings nvim.gen_help_html.heading[]
|
||||
---@param opt table
|
||||
---@param stats table
|
||||
local function visit_node(root, level, lang_tree, headings, opt, stats)
|
||||
level = level or 0
|
||||
|
||||
@ -433,7 +483,6 @@ local function visit_node(root, level, lang_tree, headings, opt, stats)
|
||||
-- Parent kind (string).
|
||||
local parent = root:parent() and root:parent():type() or nil
|
||||
local text = ''
|
||||
local trimmed
|
||||
-- Gets leading whitespace of `node`.
|
||||
local function ws(node)
|
||||
node = node or root
|
||||
@ -451,6 +500,7 @@ local function visit_node(root, level, lang_tree, headings, opt, stats)
|
||||
return string.format('%s%s', ws_, vim.treesitter.get_node_text(node, opt.buf))
|
||||
end
|
||||
|
||||
local trimmed ---@type string
|
||||
if root:named_child_count() == 0 or node_name == 'ERROR' then
|
||||
text = node_text()
|
||||
trimmed = html_esc(trim(text))
|
||||
@ -485,7 +535,9 @@ local function visit_node(root, level, lang_tree, headings, opt, stats)
|
||||
local tagname = tagnode and url_encode(node_text(tagnode:child(1), false))
|
||||
or to_heading_tag(hname)
|
||||
if node_name == 'h1' or #headings == 0 then
|
||||
table.insert(headings, { name = hname, subheadings = {}, tag = tagname })
|
||||
---@type nvim.gen_help_html.heading
|
||||
local heading = { name = hname, subheadings = {}, tag = tagname }
|
||||
headings[#headings + 1] = heading
|
||||
else
|
||||
table.insert(
|
||||
headings[#headings].subheadings,
|
||||
@ -555,11 +607,17 @@ local function visit_node(root, level, lang_tree, headings, opt, stats)
|
||||
s = fix_tab_after_conceal(s, node_text(root:next_sibling()))
|
||||
end
|
||||
return s
|
||||
elseif vim.list_contains({ 'codespan', 'keycode' }, node_name) then
|
||||
elseif vim.list_contains({ 'codespan', 'keycode', 'optional' }, node_name) then
|
||||
if root:has_error() then
|
||||
return text
|
||||
end
|
||||
local s = ('%s<code>%s</code>'):format(ws(), trimmed)
|
||||
local class = node_name == 'optional' and ' class="optional"' or ''
|
||||
local s = (
|
||||
node_name == 'keycode'
|
||||
-- TODO: use <kbd>. Currently has a layout issue, example: ":help _".
|
||||
and ('%s<code>%s</code>'):format(ws(), trimmed)
|
||||
or ('%s<code%s>%s</code>'):format(ws(), class, trimmed)
|
||||
)
|
||||
if opt.old and node_name == 'codespan' then
|
||||
s = fix_tab_after_conceal(s, node_text(root:next_sibling()))
|
||||
end
|
||||
@ -575,7 +633,7 @@ local function visit_node(root, level, lang_tree, headings, opt, stats)
|
||||
if is_blank(text) then
|
||||
return ''
|
||||
end
|
||||
local code
|
||||
local code ---@type string
|
||||
if language then
|
||||
code = ('<pre><code class="language-%s">%s</code></pre>'):format(
|
||||
language,
|
||||
@ -656,8 +714,10 @@ local function visit_node(root, level, lang_tree, headings, opt, stats)
|
||||
end
|
||||
end
|
||||
|
||||
local function get_helpfiles(include)
|
||||
local dir = './build/runtime/doc'
|
||||
--- @param dir string e.g. '$VIMRUNTIME/doc'
|
||||
--- @param include string[]|nil
|
||||
--- @return string[]
|
||||
local function get_helpfiles(dir, include)
|
||||
local rv = {}
|
||||
for f, type in vim.fs.dir(dir) do
|
||||
if
|
||||
@ -698,13 +758,15 @@ end
|
||||
---
|
||||
--- @param fname string help file to parse
|
||||
--- @param parser_path string? path to non-default vimdoc.so
|
||||
--- @returns lang_tree, bufnr
|
||||
--- @return LanguageTree, integer (lang_tree, bufnr)
|
||||
local function parse_buf(fname, parser_path)
|
||||
local buf
|
||||
local buf ---@type integer
|
||||
if type(fname) == 'string' then
|
||||
vim.cmd('split ' .. vim.fn.fnameescape(fname)) -- Filename.
|
||||
buf = vim.api.nvim_get_current_buf()
|
||||
else
|
||||
-- Left for debugging
|
||||
---@diagnostic disable-next-line: no-unknown
|
||||
buf = fname
|
||||
vim.cmd('sbuffer ' .. tostring(fname)) -- Buffer number.
|
||||
end
|
||||
@ -721,7 +783,7 @@ end
|
||||
---
|
||||
--- @param fname string help file to validate
|
||||
--- @param parser_path string? path to non-default vimdoc.so
|
||||
--- @returns { invalid_links: number, parse_errors: string[] }
|
||||
--- @return { invalid_links: number, parse_errors: string[] }
|
||||
local function validate_one(fname, parser_path)
|
||||
local stats = {
|
||||
parse_errors = {},
|
||||
@ -742,7 +804,8 @@ end
|
||||
--- @param old boolean Preformat paragraphs (for old :help files which are full of arbitrary whitespace)
|
||||
--- @param parser_path string? path to non-default vimdoc.so
|
||||
---
|
||||
--- @returns html, stats
|
||||
--- @return string html
|
||||
--- @return table stats
|
||||
local function gen_one(fname, to_fname, old, commit, parser_path)
|
||||
local stats = {
|
||||
noise_lines = {},
|
||||
@ -750,6 +813,7 @@ local function gen_one(fname, to_fname, old, commit, parser_path)
|
||||
first_tags = {}, -- Track the first few tags in doc.
|
||||
}
|
||||
local lang_tree, buf = parse_buf(fname, parser_path)
|
||||
---@type nvim.gen_help_html.heading[]
|
||||
local headings = {} -- Headings (for ToC). 2-dimensional: h1 contains h2/h3.
|
||||
local title = to_titlecase(basename_noext(fname))
|
||||
|
||||
@ -883,6 +947,7 @@ local function gen_one(fname, to_fname, old, commit, parser_path)
|
||||
main
|
||||
)
|
||||
|
||||
---@type string
|
||||
local toc = [[
|
||||
<div class="col-narrow toc">
|
||||
<div><a href="index.html">Main</a></div>
|
||||
@ -896,6 +961,7 @@ local function gen_one(fname, to_fname, old, commit, parser_path)
|
||||
n = n + 1 + #h1.subheadings
|
||||
end
|
||||
for _, h1 in ipairs(headings) do
|
||||
---@type string
|
||||
toc = toc .. ('<div class="help-toc-h1"><a href="#%s">%s</a>\n'):format(h1.tag, h1.name)
|
||||
if n < 30 or #headings < 10 then -- Show subheadings only if there aren't too many.
|
||||
for _, h2 in ipairs(h1.subheadings) do
|
||||
@ -953,11 +1019,13 @@ local function gen_css(fname)
|
||||
local css = [[
|
||||
:root {
|
||||
--code-color: #004b4b;
|
||||
--kbd-color: red;
|
||||
--tag-color: #095943;
|
||||
}
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--code-color: #00c243;
|
||||
--kbd-color: red;
|
||||
--tag-color: #00b7b7;
|
||||
}
|
||||
}
|
||||
@ -1027,7 +1095,7 @@ local function gen_css(fname)
|
||||
/* Tabs are used for alignment in old docs, so we must match Vim's 8-char expectation. */
|
||||
tab-size: 8;
|
||||
white-space: pre;
|
||||
font-size: 16px;
|
||||
font-size: 15px;
|
||||
font-family: ui-monospace,SFMono-Regular,SF Mono,Menlo,Consolas,Liberation Mono,monospace;
|
||||
}
|
||||
.old-help-para pre {
|
||||
@ -1086,7 +1154,14 @@ local function gen_css(fname)
|
||||
}
|
||||
code {
|
||||
color: var(--code-color);
|
||||
font-size: 16px;
|
||||
font-size: 15px;
|
||||
}
|
||||
code.optional {
|
||||
color: yellow;
|
||||
}
|
||||
kbd {
|
||||
/* color: var(--kbd-color); */
|
||||
font-size: 15px;
|
||||
}
|
||||
pre {
|
||||
/* Tabs are used in codeblocks only for indentation, not alignment, so we can aggressively shrink them. */
|
||||
@ -1095,7 +1170,7 @@ local function gen_css(fname)
|
||||
line-height: 1.3; /* Important for ascii art. */
|
||||
overflow: visible;
|
||||
/* font-family: ui-monospace,SFMono-Regular,SF Mono,Menlo,Consolas,Liberation Mono,monospace; */
|
||||
font-size: 16px;
|
||||
font-size: 15px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
pre:last-child {
|
||||
@ -1113,25 +1188,34 @@ local function gen_css(fname)
|
||||
tofile(fname, css)
|
||||
end
|
||||
|
||||
function M._test()
|
||||
tagmap = get_helptags('./build/runtime/doc')
|
||||
helpfiles = get_helpfiles()
|
||||
-- Testing
|
||||
|
||||
local function ok(cond, expected, actual)
|
||||
local function ok(cond, expected, actual, message)
|
||||
assert(
|
||||
(not expected and not actual) or (expected and actual),
|
||||
'if "expected" is given, "actual" is also required'
|
||||
)
|
||||
if expected then
|
||||
assert(
|
||||
(not expected and not actual) or (expected and actual),
|
||||
'if "expected" is given, "actual" is also required'
|
||||
cond,
|
||||
('%sexpected %s, got: %s'):format(
|
||||
message and (message .. '\n') or '',
|
||||
vim.inspect(expected),
|
||||
vim.inspect(actual)
|
||||
)
|
||||
)
|
||||
if expected then
|
||||
assert(cond, ('expected %s, got: %s'):format(vim.inspect(expected), vim.inspect(actual)))
|
||||
return cond
|
||||
else
|
||||
return assert(cond)
|
||||
end
|
||||
end
|
||||
local function eq(expected, actual)
|
||||
return ok(expected == actual, expected, actual)
|
||||
return cond
|
||||
else
|
||||
return assert(cond)
|
||||
end
|
||||
end
|
||||
local function eq(expected, actual, message)
|
||||
return ok(vim.deep_equal(expected, actual), expected, actual, message)
|
||||
end
|
||||
|
||||
function M._test()
|
||||
tagmap = get_helptags('$VIMRUNTIME/doc')
|
||||
helpfiles = get_helpfiles(vim.fn.expand('$VIMRUNTIME/doc'))
|
||||
|
||||
ok(vim.tbl_count(tagmap) > 3000, '>3000', vim.tbl_count(tagmap))
|
||||
ok(
|
||||
@ -1169,20 +1253,25 @@ function M._test()
|
||||
eq('https://example.com', fixed_url)
|
||||
eq('', removed_chars)
|
||||
|
||||
print('all tests passed')
|
||||
print('all tests passed.\n')
|
||||
end
|
||||
|
||||
--- @class nvim.gen_help_html.gen_result
|
||||
--- @field helpfiles string[] list of generated HTML files, from the source docs {include}
|
||||
--- @field err_count integer number of parse errors in :help docs
|
||||
--- @field invalid_links table<string, any>
|
||||
|
||||
--- Generates HTML from :help docs located in `help_dir` and writes the result in `to_dir`.
|
||||
---
|
||||
--- Example:
|
||||
---
|
||||
--- gen('./build/runtime/doc', '/path/to/neovim.github.io/_site/doc/', {'api.txt', 'autocmd.txt', 'channel.txt'}, nil)
|
||||
--- gen('$VIMRUNTIME/doc', '/path/to/neovim.github.io/_site/doc/', {'api.txt', 'autocmd.txt', 'channel.txt'}, nil)
|
||||
---
|
||||
--- @param help_dir string Source directory containing the :help files. Must run `make helptags` first.
|
||||
--- @param to_dir string Target directory where the .html files will be written.
|
||||
--- @param include table|nil Process only these filenames. Example: {'api.txt', 'autocmd.txt', 'channel.txt'}
|
||||
--- @param include string[]|nil Process only these filenames. Example: {'api.txt', 'autocmd.txt', 'channel.txt'}
|
||||
---
|
||||
--- @returns info dict
|
||||
--- @return nvim.gen_help_html.gen_result result
|
||||
function M.gen(help_dir, to_dir, include, commit, parser_path)
|
||||
vim.validate {
|
||||
help_dir = {
|
||||
@ -1207,7 +1296,7 @@ function M.gen(help_dir, to_dir, include, commit, parser_path)
|
||||
local err_count = 0
|
||||
ensure_runtimepath()
|
||||
tagmap = get_helptags(vim.fn.expand(help_dir))
|
||||
helpfiles = get_helpfiles(include)
|
||||
helpfiles = get_helpfiles(help_dir, include)
|
||||
to_dir = vim.fn.expand(to_dir)
|
||||
parser_path = parser_path and vim.fn.expand(parser_path) or nil
|
||||
|
||||
@ -1233,6 +1322,7 @@ function M.gen(help_dir, to_dir, include, commit, parser_path)
|
||||
print(('total errors: %d'):format(err_count))
|
||||
print(('invalid tags:\n%s'):format(vim.inspect(invalid_links)))
|
||||
|
||||
--- @type nvim.gen_help_html.gen_result
|
||||
return {
|
||||
helpfiles = helpfiles,
|
||||
err_count = err_count,
|
||||
@ -1240,13 +1330,21 @@ function M.gen(help_dir, to_dir, include, commit, parser_path)
|
||||
}
|
||||
end
|
||||
|
||||
-- Validates all :help files found in `help_dir`:
|
||||
-- - checks that |tag| links point to valid helptags.
|
||||
-- - recursively counts parse errors ("ERROR" nodes)
|
||||
--
|
||||
-- This is 10x faster than gen(), for use in CI.
|
||||
--
|
||||
-- @returns results dict
|
||||
--- @class nvim.gen_help_html.validate_result
|
||||
--- @field helpfiles integer number of generated helpfiles
|
||||
--- @field err_count integer number of parse errors
|
||||
--- @field parse_errors table<string, string[]>
|
||||
--- @field invalid_links table<string, any> invalid tags in :help docs
|
||||
--- @field invalid_urls table<string, any> invalid URLs in :help docs
|
||||
--- @field invalid_spelling table<string, table<string, string>> invalid spelling in :help docs
|
||||
|
||||
--- Validates all :help files found in `help_dir`:
|
||||
--- - checks that |tag| links point to valid helptags.
|
||||
--- - recursively counts parse errors ("ERROR" nodes)
|
||||
---
|
||||
--- This is 10x faster than gen(), for use in CI.
|
||||
---
|
||||
--- @return nvim.gen_help_html.validate_result result
|
||||
function M.validate(help_dir, include, parser_path)
|
||||
vim.validate {
|
||||
help_dir = {
|
||||
@ -1265,15 +1363,15 @@ function M.validate(help_dir, include, parser_path)
|
||||
'valid vimdoc.{so,dll} filepath',
|
||||
},
|
||||
}
|
||||
local err_count = 0
|
||||
local files_to_errors = {}
|
||||
local err_count = 0 ---@type integer
|
||||
local files_to_errors = {} ---@type table<string, string[]>
|
||||
ensure_runtimepath()
|
||||
tagmap = get_helptags(vim.fn.expand(help_dir))
|
||||
helpfiles = get_helpfiles(include)
|
||||
helpfiles = get_helpfiles(help_dir, include)
|
||||
parser_path = parser_path and vim.fn.expand(parser_path) or nil
|
||||
|
||||
for _, f in ipairs(helpfiles) do
|
||||
local helpfile = vim.fs.basename(f)
|
||||
local helpfile = assert(vim.fs.basename(f))
|
||||
local rv = validate_one(f, parser_path)
|
||||
print(('validated (%-4s errors): %s'):format(#rv.parse_errors, helpfile))
|
||||
if #rv.parse_errors > 0 then
|
||||
@ -1285,14 +1383,65 @@ function M.validate(help_dir, include, parser_path)
|
||||
err_count = err_count + #rv.parse_errors
|
||||
end
|
||||
|
||||
---@type nvim.gen_help_html.validate_result
|
||||
return {
|
||||
helpfiles = #helpfiles,
|
||||
err_count = err_count,
|
||||
parse_errors = files_to_errors,
|
||||
invalid_links = invalid_links,
|
||||
invalid_urls = invalid_urls,
|
||||
invalid_spelling = invalid_spelling,
|
||||
parse_errors = files_to_errors,
|
||||
}
|
||||
end
|
||||
|
||||
--- Validates vimdoc files on $VIMRUNTIME. and print human-readable error messages if fails.
|
||||
---
|
||||
--- If this fails, try these steps (in order):
|
||||
--- 1. Fix/cleanup the :help docs.
|
||||
--- 2. Fix the parser: https://github.com/neovim/tree-sitter-vimdoc
|
||||
--- 3. File a parser bug, and adjust the tolerance of this test in the meantime.
|
||||
---
|
||||
--- @param help_dir? string e.g. '$VIMRUNTIME/doc' or './runtime/doc'
|
||||
function M.run_validate(help_dir)
|
||||
help_dir = vim.fn.expand(help_dir or '$VIMRUNTIME/doc')
|
||||
print('doc path = ' .. vim.uv.fs_realpath(help_dir))
|
||||
|
||||
local rv = M.validate(help_dir)
|
||||
|
||||
-- Check that we actually found helpfiles.
|
||||
ok(rv.helpfiles > 100, '>100 :help files', rv.helpfiles)
|
||||
|
||||
eq({}, rv.parse_errors, 'no parse errors')
|
||||
eq(0, rv.err_count, 'no parse errors')
|
||||
eq({}, rv.invalid_links, 'invalid tags in :help docs')
|
||||
eq({}, rv.invalid_urls, 'invalid URLs in :help docs')
|
||||
eq(
|
||||
{},
|
||||
rv.invalid_spelling,
|
||||
'invalid spelling in :help docs (see spell_dict in scripts/gen_help_html.lua)'
|
||||
)
|
||||
end
|
||||
|
||||
--- Test-generates HTML from docs.
|
||||
---
|
||||
--- 1. Test that gen_help_html.lua actually works.
|
||||
--- 2. Test that parse errors did not increase wildly. Because we explicitly test only a few
|
||||
--- :help files, we can be precise about the tolerances here.
|
||||
--- @param help_dir? string e.g. '$VIMRUNTIME/doc' or './runtime/doc'
|
||||
function M.test_gen(help_dir)
|
||||
local tmpdir = assert(vim.fs.dirname(vim.fn.tempname()))
|
||||
help_dir = vim.fn.expand(help_dir or '$VIMRUNTIME/doc')
|
||||
print('doc path = ' .. vim.uv.fs_realpath(help_dir))
|
||||
|
||||
local rv = M.gen(
|
||||
help_dir,
|
||||
tmpdir,
|
||||
-- Because gen() is slow (~30s), this test is limited to a few files.
|
||||
{ 'pi_health.txt', 'help.txt', 'index.txt', 'nvim.txt' }
|
||||
)
|
||||
eq(4, #rv.helpfiles)
|
||||
eq(0, rv.err_count, 'parse errors in :help docs')
|
||||
eq({}, rv.invalid_links, 'invalid tags in :help docs')
|
||||
end
|
||||
|
||||
return M
|
||||
|
20
scripts/lintdoc.lua
Executable file
20
scripts/lintdoc.lua
Executable file
@ -0,0 +1,20 @@
|
||||
#!/usr/bin/env -S nvim -l
|
||||
|
||||
-- Validate vimdoc files on $VIMRUNTIME/doc, and test generating HTML docs.
|
||||
-- Checks for duplicate/missing tags, parse errors, and invalid links/urls/spellings.
|
||||
-- See also `make lintdoc`.
|
||||
--
|
||||
-- Usage:
|
||||
-- $ nvim -l scripts/lintdoc.lua
|
||||
-- $ make lintdoc
|
||||
|
||||
print('Running lintdoc ...')
|
||||
|
||||
-- gen_help_html requires :helptags to be generated on $VIMRUNTIME/doc
|
||||
-- :helptags checks for duplicate tags.
|
||||
vim.cmd [[ helptags ALL ]]
|
||||
|
||||
require('scripts.gen_help_html').run_validate()
|
||||
require('scripts.gen_help_html').test_gen()
|
||||
|
||||
print('lintdoc PASSED.')
|
@ -953,3 +953,10 @@ add_custom_target(doc-eval DEPENDS ${GEN_EVAL_TOUCH})
|
||||
add_custom_target(doc-vim DEPENDS ${VIMDOC_FILES})
|
||||
add_custom_target(doc)
|
||||
add_dependencies(doc doc-vim doc-eval)
|
||||
|
||||
add_custom_target(lintdoc
|
||||
COMMAND ${CMAKE_COMMAND} -E env "VIMRUNTIME=${NVIM_RUNTIME_DIR}"
|
||||
$<TARGET_FILE:nvim_bin> --clean -l scripts/lintdoc.lua
|
||||
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
|
||||
USES_TERMINAL)
|
||||
add_dependencies(lintdoc nvim)
|
||||
|
@ -748,20 +748,32 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer
|
||||
col2 = c;
|
||||
}
|
||||
|
||||
DecorPriority subpriority = DECOR_PRIORITY_BASE;
|
||||
if (HAS_KEY(opts, set_extmark, _subpriority)) {
|
||||
VALIDATE_RANGE((opts->_subpriority >= 0 && opts->_subpriority <= UINT16_MAX),
|
||||
"_subpriority", {
|
||||
goto error;
|
||||
});
|
||||
subpriority = (DecorPriority)opts->_subpriority;
|
||||
}
|
||||
|
||||
if (kv_size(virt_text.data.virt_text)) {
|
||||
decor_range_add_virt(&decor_state, r, c, line2, col2, decor_put_vt(virt_text, NULL), true);
|
||||
decor_range_add_virt(&decor_state, r, c, line2, col2, decor_put_vt(virt_text, NULL), true,
|
||||
subpriority);
|
||||
}
|
||||
if (kv_size(virt_lines.data.virt_lines)) {
|
||||
decor_range_add_virt(&decor_state, r, c, line2, col2, decor_put_vt(virt_lines, NULL), true);
|
||||
decor_range_add_virt(&decor_state, r, c, line2, col2, decor_put_vt(virt_lines, NULL), true,
|
||||
subpriority);
|
||||
}
|
||||
if (url != NULL) {
|
||||
DecorSignHighlight sh = DECOR_SIGN_HIGHLIGHT_INIT;
|
||||
sh.url = url;
|
||||
decor_range_add_sh(&decor_state, r, c, line2, col2, &sh, true, 0, 0);
|
||||
decor_range_add_sh(&decor_state, r, c, line2, col2, &sh, true, 0, 0, subpriority);
|
||||
}
|
||||
if (has_hl) {
|
||||
DecorSignHighlight sh = decor_sh_from_inline(hl);
|
||||
decor_range_add_sh(&decor_state, r, c, line2, col2, &sh, true, (uint32_t)ns_id, id);
|
||||
decor_range_add_sh(&decor_state, r, c, line2, col2, &sh, true, (uint32_t)ns_id, id,
|
||||
subpriority);
|
||||
}
|
||||
} else {
|
||||
if (opts->ephemeral) {
|
||||
|
@ -55,6 +55,8 @@ typedef struct {
|
||||
Boolean ui_watched;
|
||||
Boolean undo_restore;
|
||||
String url;
|
||||
|
||||
Integer _subpriority;
|
||||
} Dict(set_extmark);
|
||||
|
||||
typedef struct {
|
||||
|
@ -151,7 +151,7 @@ bool try_end(Error *err)
|
||||
if (should_free) {
|
||||
xfree(msg);
|
||||
}
|
||||
} else if (did_throw) {
|
||||
} else if (did_throw || need_rethrow) {
|
||||
if (*current_exception->throw_name != NUL) {
|
||||
if (current_exception->throw_lnum != 0) {
|
||||
api_set_error(err, kErrorTypeException, "%s, line %" PRIdLINENR ": %s",
|
||||
|
@ -122,6 +122,37 @@ Window nvim_tabpage_get_win(Tabpage tabpage, Error *err)
|
||||
abort();
|
||||
}
|
||||
|
||||
/// Sets the current window in a tabpage
|
||||
///
|
||||
/// @param tabpage Tabpage handle, or 0 for current tabpage
|
||||
/// @param win Window handle, must already belong to {tabpage}
|
||||
/// @param[out] err Error details, if any
|
||||
void nvim_tabpage_set_win(Tabpage tabpage, Window win, Error *err)
|
||||
FUNC_API_SINCE(12)
|
||||
{
|
||||
tabpage_T *tp = find_tab_by_handle(tabpage, err);
|
||||
if (!tp) {
|
||||
return;
|
||||
}
|
||||
|
||||
win_T *wp = find_window_by_handle(win, err);
|
||||
if (!wp) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!tabpage_win_valid(tp, wp)) {
|
||||
api_set_error(err, kErrorTypeException, "Window does not belong to tabpage %d", tp->handle);
|
||||
return;
|
||||
}
|
||||
|
||||
if (tp == curtab) {
|
||||
win_enter(wp, true);
|
||||
} else if (tp->tp_curwin != wp) {
|
||||
tp->tp_prevwin = tp->tp_curwin;
|
||||
tp->tp_curwin = wp;
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets the tabpage number
|
||||
///
|
||||
/// @param tabpage Tabpage handle, or 0 for current tabpage
|
||||
|
@ -1022,7 +1022,7 @@ Integer nvim_open_term(Buffer buffer, Dict(open_term) *opts, Error *err)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (cmdwin_type != 0 && buf == curbuf) {
|
||||
if (buf == cmdwin_buf) {
|
||||
api_set_error(err, kErrorTypeException, "%s", e_cmdwin);
|
||||
return 0;
|
||||
}
|
||||
|
@ -181,7 +181,7 @@ Window nvim_open_win(Buffer buffer, Boolean enter, Dict(float_config) *config, E
|
||||
if (!buf) {
|
||||
return 0;
|
||||
}
|
||||
if (cmdwin_type != 0 && (enter || buf == curbuf)) {
|
||||
if ((cmdwin_type != 0 && enter) || buf == cmdwin_buf) {
|
||||
api_set_error(err, kErrorTypeException, "%s", e_cmdwin);
|
||||
return 0;
|
||||
}
|
||||
|
@ -61,7 +61,7 @@ void nvim_win_set_buf(Window window, Buffer buffer, Error *err)
|
||||
if (!win || !buf) {
|
||||
return;
|
||||
}
|
||||
if (cmdwin_type != 0 && (win == curwin || win == cmdwin_old_curwin || buf == curbuf)) {
|
||||
if (win == cmdwin_win || win == cmdwin_old_curwin || buf == cmdwin_buf) {
|
||||
api_set_error(err, kErrorTypeException, "%s", e_cmdwin);
|
||||
return;
|
||||
}
|
||||
|
@ -1183,6 +1183,32 @@ static int empty_curbuf(bool close_others, int forceit, int action)
|
||||
return retval;
|
||||
}
|
||||
|
||||
/// Remove every jump list entry referring to a given buffer.
|
||||
/// This function will also adjust the current jump list index.
|
||||
void buf_remove_from_jumplist(buf_T *deleted_buf)
|
||||
{
|
||||
// Remove all jump list entries that match the deleted buffer.
|
||||
for (int i = curwin->w_jumplistlen - 1; i >= 0; i--) {
|
||||
buf_T *buf = buflist_findnr(curwin->w_jumplist[i].fmark.fnum);
|
||||
|
||||
if (buf == deleted_buf) {
|
||||
// Found an entry that we want to delete.
|
||||
curwin->w_jumplistlen -= 1;
|
||||
|
||||
// If the current jump list index behind the entry we want to
|
||||
// delete, move it back by one.
|
||||
if (curwin->w_jumplistidx > i && curwin->w_jumplistidx > 0) {
|
||||
curwin->w_jumplistidx -= 1;
|
||||
}
|
||||
|
||||
// Actually remove the entry from the jump list.
|
||||
for (int d = i; d < curwin->w_jumplistlen; d++) {
|
||||
curwin->w_jumplist[d] = curwin->w_jumplist[d + 1];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Implementation of the commands for the buffer list.
|
||||
///
|
||||
/// action == DOBUF_GOTO go to specified buffer
|
||||
@ -1205,6 +1231,7 @@ int do_buffer(int action, int start, int dir, int count, int forceit)
|
||||
{
|
||||
buf_T *buf;
|
||||
buf_T *bp;
|
||||
bool update_jumplist = true;
|
||||
bool unload = (action == DOBUF_UNLOAD || action == DOBUF_DEL
|
||||
|| action == DOBUF_WIPE);
|
||||
|
||||
@ -1362,7 +1389,11 @@ int do_buffer(int action, int start, int dir, int count, int forceit)
|
||||
|
||||
// If the buffer to be deleted is not the current one, delete it here.
|
||||
if (buf != curbuf) {
|
||||
// Remove the buffer to be deleted from the jump list.
|
||||
buf_remove_from_jumplist(buf);
|
||||
|
||||
close_windows(buf, false);
|
||||
|
||||
if (buf != curbuf && bufref_valid(&bufref) && buf->b_nwindows <= 0) {
|
||||
close_buffer(NULL, buf, action, false, false);
|
||||
}
|
||||
@ -1382,40 +1413,53 @@ int do_buffer(int action, int start, int dir, int count, int forceit)
|
||||
if (au_new_curbuf.br_buf != NULL && bufref_valid(&au_new_curbuf)) {
|
||||
buf = au_new_curbuf.br_buf;
|
||||
} else if (curwin->w_jumplistlen > 0) {
|
||||
int jumpidx = curwin->w_jumplistidx - 1;
|
||||
if (jumpidx < 0) {
|
||||
jumpidx = curwin->w_jumplistlen - 1;
|
||||
}
|
||||
// Remove the current buffer from the jump list.
|
||||
buf_remove_from_jumplist(curbuf);
|
||||
|
||||
forward = jumpidx;
|
||||
while (jumpidx != curwin->w_jumplistidx) {
|
||||
buf = buflist_findnr(curwin->w_jumplist[jumpidx].fmark.fnum);
|
||||
if (buf != NULL) {
|
||||
// Skip current and unlisted bufs. Also skip a quickfix
|
||||
// buffer, it might be deleted soon.
|
||||
if (buf == curbuf || !buf->b_p_bl || bt_quickfix(buf)) {
|
||||
buf = NULL;
|
||||
} else if (buf->b_ml.ml_mfp == NULL) {
|
||||
// skip unloaded buf, but may keep it for later
|
||||
if (bp == NULL) {
|
||||
bp = buf;
|
||||
// It's possible that we removed all jump list entries, in that case we need to try another
|
||||
// approach
|
||||
if (curwin->w_jumplistlen > 0) {
|
||||
// If the index is the same as the length, the current position was not yet added to the jump
|
||||
// list. So we can safely go back to the last entry and search from there.
|
||||
if (curwin->w_jumplistidx == curwin->w_jumplistlen) {
|
||||
curwin->w_jumplistidx = curwin->w_jumplistlen - 1;
|
||||
}
|
||||
|
||||
int jumpidx = curwin->w_jumplistidx;
|
||||
|
||||
forward = jumpidx;
|
||||
do {
|
||||
buf = buflist_findnr(curwin->w_jumplist[jumpidx].fmark.fnum);
|
||||
|
||||
if (buf != NULL) {
|
||||
// Skip unlisted bufs. Also skip a quickfix
|
||||
// buffer, it might be deleted soon.
|
||||
if (!buf->b_p_bl || bt_quickfix(buf)) {
|
||||
buf = NULL;
|
||||
} else if (buf->b_ml.ml_mfp == NULL) {
|
||||
// skip unloaded buf, but may keep it for later
|
||||
if (bp == NULL) {
|
||||
bp = buf;
|
||||
}
|
||||
buf = NULL;
|
||||
}
|
||||
buf = NULL;
|
||||
}
|
||||
}
|
||||
if (buf != NULL) { // found a valid buffer: stop searching
|
||||
break;
|
||||
}
|
||||
// advance to older entry in jump list
|
||||
if (!jumpidx && curwin->w_jumplistidx == curwin->w_jumplistlen) {
|
||||
break;
|
||||
}
|
||||
if (--jumpidx < 0) {
|
||||
jumpidx = curwin->w_jumplistlen - 1;
|
||||
}
|
||||
if (jumpidx == forward) { // List exhausted for sure
|
||||
break;
|
||||
}
|
||||
if (buf != NULL) { // found a valid buffer: stop searching
|
||||
curwin->w_jumplistidx = jumpidx;
|
||||
update_jumplist = false;
|
||||
break;
|
||||
}
|
||||
// advance to older entry in jump list
|
||||
if (!jumpidx && curwin->w_jumplistidx == curwin->w_jumplistlen) {
|
||||
break;
|
||||
}
|
||||
if (--jumpidx < 0) {
|
||||
jumpidx = curwin->w_jumplistlen - 1;
|
||||
}
|
||||
if (jumpidx == forward) { // List exhausted for sure
|
||||
break;
|
||||
}
|
||||
} while (jumpidx != curwin->w_jumplistidx);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1511,7 +1555,7 @@ int do_buffer(int action, int start, int dir, int count, int forceit)
|
||||
}
|
||||
|
||||
// Go to the other buffer.
|
||||
set_curbuf(buf, action);
|
||||
set_curbuf(buf, action, update_jumplist);
|
||||
|
||||
if (action == DOBUF_SPLIT) {
|
||||
RESET_BINDING(curwin); // reset 'scrollbind' and 'cursorbind'
|
||||
@ -1533,14 +1577,17 @@ int do_buffer(int action, int start, int dir, int count, int forceit)
|
||||
/// DOBUF_UNLOAD unload it
|
||||
/// DOBUF_DEL delete it
|
||||
/// DOBUF_WIPE wipe it out
|
||||
void set_curbuf(buf_T *buf, int action)
|
||||
void set_curbuf(buf_T *buf, int action, bool update_jumplist)
|
||||
{
|
||||
buf_T *prevbuf;
|
||||
int unload = (action == DOBUF_UNLOAD || action == DOBUF_DEL
|
||||
|| action == DOBUF_WIPE);
|
||||
OptInt old_tw = curbuf->b_p_tw;
|
||||
|
||||
setpcmark();
|
||||
if (update_jumplist) {
|
||||
setpcmark();
|
||||
}
|
||||
|
||||
if ((cmdmod.cmod_flags & CMOD_KEEPALT) == 0) {
|
||||
curwin->w_alt_fnum = curbuf->b_fnum; // remember alternate file
|
||||
}
|
||||
@ -3675,7 +3722,7 @@ void ex_buffer_all(exarg_T *eap)
|
||||
|
||||
// Open the buffer in this window.
|
||||
swap_exists_action = SEA_DIALOG;
|
||||
set_curbuf(buf, DOBUF_GOTO);
|
||||
set_curbuf(buf, DOBUF_GOTO, false);
|
||||
if (!bufref_valid(&bufref)) {
|
||||
// Autocommands deleted the buffer.
|
||||
swap_exists_action = SEA_NONE;
|
||||
@ -4012,6 +4059,9 @@ char *buf_spname(buf_T *buf)
|
||||
if (buf->b_fname != NULL) {
|
||||
return buf->b_fname;
|
||||
}
|
||||
if (buf == cmdwin_buf) {
|
||||
return _("[Command Line]");
|
||||
}
|
||||
if (bt_prompt(buf)) {
|
||||
return _("[Prompt]");
|
||||
}
|
||||
@ -4129,6 +4179,7 @@ void wipe_buffer(buf_T *buf, bool aucmd)
|
||||
/// - Always considered 'nomodified'
|
||||
///
|
||||
/// @param bufnr Buffer to switch to, or 0 to create a new buffer.
|
||||
/// @param bufname Buffer name, or NULL.
|
||||
///
|
||||
/// @see curbufIsChanged()
|
||||
///
|
||||
@ -4138,9 +4189,11 @@ int buf_open_scratch(handle_T bufnr, char *bufname)
|
||||
if (do_ecmd((int)bufnr, NULL, NULL, NULL, ECMD_ONE, ECMD_HIDE, NULL) == FAIL) {
|
||||
return FAIL;
|
||||
}
|
||||
apply_autocmds(EVENT_BUFFILEPRE, NULL, NULL, false, curbuf);
|
||||
setfname(curbuf, bufname, NULL, true);
|
||||
apply_autocmds(EVENT_BUFFILEPOST, NULL, NULL, false, curbuf);
|
||||
if (bufname != NULL) {
|
||||
apply_autocmds(EVENT_BUFFILEPRE, NULL, NULL, false, curbuf);
|
||||
setfname(curbuf, bufname, NULL, true);
|
||||
apply_autocmds(EVENT_BUFFILEPOST, NULL, NULL, false, curbuf);
|
||||
}
|
||||
set_option_value_give_err(kOptBufhidden, STATIC_CSTR_AS_OPTVAL("hide"), OPT_LOCAL);
|
||||
set_option_value_give_err(kOptBuftype, STATIC_CSTR_AS_OPTVAL("nofile"), OPT_LOCAL);
|
||||
set_option_value_give_err(kOptSwapfile, BOOLEAN_OPTVAL(false), OPT_LOCAL);
|
||||
|
@ -713,7 +713,7 @@ struct file_buffer {
|
||||
|
||||
// Measurements of the deleted or replaced region since the last update
|
||||
// event. Some consumers of buffer changes need to know the byte size (like
|
||||
// tree-sitter) or the corresponding UTF-32/UTF-16 size (like LSP) of the
|
||||
// treesitter) or the corresponding UTF-32/UTF-16 size (like LSP) of the
|
||||
// deleted text.
|
||||
size_t deleted_bytes;
|
||||
size_t deleted_bytes2;
|
||||
|
@ -449,18 +449,21 @@ static void decor_range_add_from_inline(DecorState *state, int start_row, int st
|
||||
if (decor.ext) {
|
||||
DecorVirtText *vt = decor.data.ext.vt;
|
||||
while (vt) {
|
||||
decor_range_add_virt(state, start_row, start_col, end_row, end_col, vt, owned);
|
||||
decor_range_add_virt(state, start_row, start_col, end_row, end_col, vt, owned,
|
||||
DECOR_PRIORITY_BASE);
|
||||
vt = vt->next;
|
||||
}
|
||||
uint32_t idx = decor.data.ext.sh_idx;
|
||||
while (idx != DECOR_ID_INVALID) {
|
||||
DecorSignHighlight *sh = &kv_A(decor_items, idx);
|
||||
decor_range_add_sh(state, start_row, start_col, end_row, end_col, sh, owned, ns, mark_id);
|
||||
decor_range_add_sh(state, start_row, start_col, end_row, end_col, sh, owned, ns, mark_id,
|
||||
DECOR_PRIORITY_BASE);
|
||||
idx = sh->next;
|
||||
}
|
||||
} else {
|
||||
DecorSignHighlight sh = decor_sh_from_inline(decor.data.hl);
|
||||
decor_range_add_sh(state, start_row, start_col, end_row, end_col, &sh, owned, ns, mark_id);
|
||||
decor_range_add_sh(state, start_row, start_col, end_row, end_col, &sh, owned, ns, mark_id,
|
||||
DECOR_PRIORITY_BASE);
|
||||
}
|
||||
}
|
||||
|
||||
@ -470,7 +473,8 @@ static void decor_range_insert(DecorState *state, DecorRange range)
|
||||
size_t index;
|
||||
for (index = kv_size(state->active) - 1; index > 0; index--) {
|
||||
DecorRange item = kv_A(state->active, index - 1);
|
||||
if (item.priority <= range.priority) {
|
||||
if ((item.priority < range.priority)
|
||||
|| ((item.priority == range.priority) && (item.subpriority <= range.subpriority))) {
|
||||
break;
|
||||
}
|
||||
kv_A(state->active, index) = kv_A(state->active, index - 1);
|
||||
@ -479,7 +483,7 @@ static void decor_range_insert(DecorState *state, DecorRange range)
|
||||
}
|
||||
|
||||
void decor_range_add_virt(DecorState *state, int start_row, int start_col, int end_row, int end_col,
|
||||
DecorVirtText *vt, bool owned)
|
||||
DecorVirtText *vt, bool owned, DecorPriority subpriority)
|
||||
{
|
||||
bool is_lines = vt->flags & kVTIsLines;
|
||||
DecorRange range = {
|
||||
@ -489,13 +493,15 @@ void decor_range_add_virt(DecorState *state, int start_row, int start_col, int e
|
||||
.attr_id = 0,
|
||||
.owned = owned,
|
||||
.priority = vt->priority,
|
||||
.subpriority = subpriority,
|
||||
.draw_col = -10,
|
||||
};
|
||||
decor_range_insert(state, range);
|
||||
}
|
||||
|
||||
void decor_range_add_sh(DecorState *state, int start_row, int start_col, int end_row, int end_col,
|
||||
DecorSignHighlight *sh, bool owned, uint32_t ns, uint32_t mark_id)
|
||||
DecorSignHighlight *sh, bool owned, uint32_t ns, uint32_t mark_id,
|
||||
DecorPriority subpriority)
|
||||
{
|
||||
if (sh->flags & kSHIsSign) {
|
||||
return;
|
||||
@ -508,6 +514,7 @@ void decor_range_add_sh(DecorState *state, int start_row, int start_col, int end
|
||||
.attr_id = 0,
|
||||
.owned = owned,
|
||||
.priority = sh->priority,
|
||||
.subpriority = subpriority,
|
||||
.draw_col = -10,
|
||||
};
|
||||
|
||||
@ -629,9 +636,9 @@ next_mark:
|
||||
} else if (item.data.sh.flags & kSHSpellOff) {
|
||||
spell = kFalse;
|
||||
}
|
||||
}
|
||||
if (active && item.data.sh.url != NULL) {
|
||||
attr = hl_add_url(attr, item.data.sh.url);
|
||||
if (item.data.sh.url != NULL) {
|
||||
attr = hl_add_url(attr, item.data.sh.url);
|
||||
}
|
||||
}
|
||||
if (item.start_row == state->row && item.start_col <= col
|
||||
&& decor_virt_pos(&item) && item.draw_col == -10) {
|
||||
|
@ -48,6 +48,8 @@ typedef struct {
|
||||
int attr_id; ///< cached lookup of inl.hl_id if it was a highlight
|
||||
bool owned; ///< ephemeral decoration, free memory immediately
|
||||
DecorPriority priority;
|
||||
DecorPriority subpriority; ///< Secondary priority value used for ordering (#27131).
|
||||
///< Reflects the order of patterns/captures in the query file.
|
||||
DecorRangeKind kind;
|
||||
/// Screen column to draw the virtual text.
|
||||
/// When -1, the virtual text may be drawn after deciding where.
|
||||
|
@ -1219,7 +1219,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int col_rows, s
|
||||
statuscol.draw = true;
|
||||
statuscol.sattrs = wlv.sattrs;
|
||||
statuscol.foldinfo = foldinfo;
|
||||
statuscol.width = win_col_off(wp) - (cmdwin_type != 0 && wp == curwin);
|
||||
statuscol.width = win_col_off(wp) - (wp == cmdwin_win);
|
||||
statuscol.use_cul = use_cursor_line_highlight(wp, lnum);
|
||||
statuscol.sign_cul_id = statuscol.use_cul ? sign_cul_attr : 0;
|
||||
statuscol.num_attr = sign_num_attr > 0 ? syn_id2attr(sign_num_attr) : 0;
|
||||
@ -1511,7 +1511,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int col_rows, s
|
||||
|
||||
assert(wlv.off == 0);
|
||||
|
||||
if (cmdwin_type != 0 && wp == curwin) {
|
||||
if (wp == cmdwin_win) {
|
||||
// Draw the cmdline character.
|
||||
draw_col_fill(&wlv, schar_from_ascii(cmdwin_type), 1, win_hl_attr(wp, HLF_AT));
|
||||
}
|
||||
|
@ -3219,6 +3219,8 @@ M.funcs = {
|
||||
bufnr Buffer number.
|
||||
changed TRUE if the buffer is modified.
|
||||
changedtick Number of changes made to the buffer.
|
||||
command TRUE if the buffer belongs to the
|
||||
command-line window |cmdwin|.
|
||||
hidden TRUE if the buffer is hidden.
|
||||
lastused Timestamp in seconds, like
|
||||
|localtime()|, when the buffer was
|
||||
|
@ -494,6 +494,7 @@ static dict_T *get_buffer_info(buf_T *buf)
|
||||
tv_dict_add_nr(dict, S_LEN("changed"), bufIsChanged(buf));
|
||||
tv_dict_add_nr(dict, S_LEN("changedtick"), buf_get_changedtick(buf));
|
||||
tv_dict_add_nr(dict, S_LEN("hidden"), buf->b_ml.ml_mfp != NULL && buf->b_nwindows == 0);
|
||||
tv_dict_add_nr(dict, S_LEN("command"), buf == cmdwin_buf);
|
||||
|
||||
// Get a reference to buffer variables
|
||||
tv_dict_add_dict(dict, S_LEN("variables"), buf->b_vars);
|
||||
|
@ -755,7 +755,7 @@ void f_win_gettype(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
|
||||
rettv->vval.v_string = xstrdup("preview");
|
||||
} else if (wp->w_floating) {
|
||||
rettv->vval.v_string = xstrdup("popup");
|
||||
} else if (wp == curwin && cmdwin_type != 0) {
|
||||
} else if (wp == cmdwin_win) {
|
||||
rettv->vval.v_string = xstrdup("command");
|
||||
} else if (bt_quickfix(wp->w_buffer)) {
|
||||
rettv->vval.v_string = xstrdup((wp->w_llist_ref != NULL ? "loclist" : "quickfix"));
|
||||
|
@ -2305,10 +2305,19 @@ int do_ecmd(int fnum, char *ffname, char *sfname, exarg_T *eap, linenr_T newlnum
|
||||
// If the current buffer was empty and has no file name, curbuf
|
||||
// is returned by buflist_new(), nothing to do here.
|
||||
if (buf != curbuf) {
|
||||
// Should only be possible to get here if the cmdwin is closed, or
|
||||
// if it's opening and its buffer hasn't been set yet (the new
|
||||
// buffer is for it).
|
||||
assert(cmdwin_buf == NULL);
|
||||
|
||||
const int save_cmdwin_type = cmdwin_type;
|
||||
win_T *const save_cmdwin_win = cmdwin_win;
|
||||
win_T *const save_cmdwin_old_curwin = cmdwin_old_curwin;
|
||||
|
||||
// BufLeave applies to the old buffer.
|
||||
cmdwin_type = 0;
|
||||
cmdwin_win = NULL;
|
||||
cmdwin_old_curwin = NULL;
|
||||
|
||||
// Be careful: The autocommands may delete any buffer and change
|
||||
// the current buffer.
|
||||
@ -2324,7 +2333,11 @@ int do_ecmd(int fnum, char *ffname, char *sfname, exarg_T *eap, linenr_T newlnum
|
||||
const bufref_T save_au_new_curbuf = au_new_curbuf;
|
||||
set_bufref(&au_new_curbuf, buf);
|
||||
apply_autocmds(EVENT_BUFLEAVE, NULL, NULL, false, curbuf);
|
||||
|
||||
cmdwin_type = save_cmdwin_type;
|
||||
cmdwin_win = save_cmdwin_win;
|
||||
cmdwin_old_curwin = save_cmdwin_old_curwin;
|
||||
|
||||
if (!bufref_valid(&au_new_curbuf)) {
|
||||
// New buffer has been deleted.
|
||||
delbuf_msg(new_name); // Frees new_name.
|
||||
|
@ -1612,7 +1612,7 @@ module.cmds = {
|
||||
},
|
||||
{
|
||||
command = 'lua',
|
||||
flags = bit.bor(RANGE, EXTRA, NEEDARG, CMDWIN, LOCK_OK),
|
||||
flags = bit.bor(RANGE, EXTRA, CMDWIN, LOCK_OK),
|
||||
addr_type = 'ADDR_LINES',
|
||||
func = 'ex_lua',
|
||||
},
|
||||
|
@ -405,7 +405,7 @@ buf_found:
|
||||
|
||||
// Open the changed buffer in the current window.
|
||||
if (buf != curbuf) {
|
||||
set_curbuf(buf, unload ? DOBUF_UNLOAD : DOBUF_GOTO);
|
||||
set_curbuf(buf, unload ? DOBUF_UNLOAD : DOBUF_GOTO, true);
|
||||
}
|
||||
|
||||
theend:
|
||||
|
@ -309,6 +309,33 @@ static void msg_verbose_cmd(linenr_T lnum, char *cmd)
|
||||
no_wait_return--;
|
||||
}
|
||||
|
||||
static int cmdline_call_depth = 0; ///< recursiveness
|
||||
|
||||
/// Start executing an Ex command line.
|
||||
///
|
||||
/// @return FAIL if too recursive, OK otherwise.
|
||||
static int do_cmdline_start(void)
|
||||
{
|
||||
assert(cmdline_call_depth >= 0);
|
||||
// It's possible to create an endless loop with ":execute", catch that
|
||||
// here. The value of 200 allows nested function calls, ":source", etc.
|
||||
// Allow 200 or 'maxfuncdepth', whatever is larger.
|
||||
if (cmdline_call_depth >= 200 && cmdline_call_depth >= p_mfd) {
|
||||
return FAIL;
|
||||
}
|
||||
cmdline_call_depth++;
|
||||
start_batch_changes();
|
||||
return OK;
|
||||
}
|
||||
|
||||
/// End executing an Ex command line.
|
||||
static void do_cmdline_end(void)
|
||||
{
|
||||
cmdline_call_depth--;
|
||||
assert(cmdline_call_depth >= 0);
|
||||
end_batch_changes();
|
||||
}
|
||||
|
||||
/// Execute a simple command line. Used for translated commands like "*".
|
||||
int do_cmdline_cmd(const char *cmd)
|
||||
{
|
||||
@ -359,7 +386,6 @@ int do_cmdline(char *cmdline, LineGetter fgetline, void *cookie, int flags)
|
||||
char *(*cmd_getline)(int, void *, int, bool);
|
||||
void *cmd_cookie;
|
||||
struct loop_cookie cmd_loop_cookie;
|
||||
static int call_depth = 0; // recursiveness
|
||||
|
||||
// For every pair of do_cmdline()/do_one_cmd() calls, use an extra memory
|
||||
// location for storing error messages to be converted to an exception.
|
||||
@ -371,10 +397,7 @@ int do_cmdline(char *cmdline, LineGetter fgetline, void *cookie, int flags)
|
||||
msg_list = &private_msg_list;
|
||||
private_msg_list = NULL;
|
||||
|
||||
// It's possible to create an endless loop with ":execute", catch that
|
||||
// here. The value of 200 allows nested function calls, ":source", etc.
|
||||
// Allow 200 or 'maxfuncdepth', whatever is larger.
|
||||
if (call_depth >= 200 && call_depth >= p_mfd) {
|
||||
if (do_cmdline_start() == FAIL) {
|
||||
emsg(_(e_command_too_recursive));
|
||||
// When converting to an exception, we do not include the command name
|
||||
// since this is not an error of the specific command.
|
||||
@ -382,8 +405,6 @@ int do_cmdline(char *cmdline, LineGetter fgetline, void *cookie, int flags)
|
||||
msg_list = saved_msg_list;
|
||||
return FAIL;
|
||||
}
|
||||
call_depth++;
|
||||
start_batch_changes();
|
||||
|
||||
ga_init(&lines_ga, (int)sizeof(wcmd_T), 10);
|
||||
|
||||
@ -884,8 +905,7 @@ int do_cmdline(char *cmdline, LineGetter fgetline, void *cookie, int flags)
|
||||
|
||||
did_endif = false; // in case do_cmdline used recursively
|
||||
|
||||
call_depth--;
|
||||
end_batch_changes();
|
||||
do_cmdline_end();
|
||||
return retval;
|
||||
}
|
||||
|
||||
@ -1669,9 +1689,13 @@ static int execute_cmd0(int *retv, exarg_T *eap, const char **errormsg, bool pre
|
||||
/// @param preview Execute command preview callback instead of actual command
|
||||
int execute_cmd(exarg_T *eap, CmdParseInfo *cmdinfo, bool preview)
|
||||
{
|
||||
const char *errormsg = NULL;
|
||||
int retv = 0;
|
||||
if (do_cmdline_start() == FAIL) {
|
||||
emsg(_(e_command_too_recursive));
|
||||
return retv;
|
||||
}
|
||||
|
||||
const char *errormsg = NULL;
|
||||
#undef ERROR
|
||||
#define ERROR(msg) \
|
||||
do { \
|
||||
@ -1738,9 +1762,12 @@ end:
|
||||
if (errormsg != NULL && *errormsg != NUL) {
|
||||
emsg(errormsg);
|
||||
}
|
||||
|
||||
// Undo command modifiers
|
||||
undo_cmdmod(&cmdmod);
|
||||
cmdmod = save_cmdmod;
|
||||
|
||||
do_cmdline_end();
|
||||
return retv;
|
||||
#undef ERROR
|
||||
}
|
||||
|
@ -219,6 +219,9 @@ static int cedit_key = -1; ///< key value of 'cedit' option
|
||||
static handle_T cmdpreview_bufnr = 0;
|
||||
static int cmdpreview_ns = 0;
|
||||
|
||||
static const char e_active_window_or_buffer_changed_or_deleted[]
|
||||
= N_("E199: Active window or buffer changed or deleted");
|
||||
|
||||
static void save_viewstate(win_T *wp, viewstate_T *vs)
|
||||
FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
@ -4323,23 +4326,50 @@ static int open_cmdwin(void)
|
||||
ga_clear(&winsizes);
|
||||
return K_IGNORE;
|
||||
}
|
||||
// win_split() autocommands may have messed with the old window or buffer.
|
||||
// Treat it as abandoning this command-line.
|
||||
if (!win_valid(old_curwin) || curwin == old_curwin || !bufref_valid(&old_curbuf)
|
||||
|| old_curwin->w_buffer != old_curbuf.br_buf) {
|
||||
beep_flush();
|
||||
ga_clear(&winsizes);
|
||||
return Ctrl_C;
|
||||
}
|
||||
// Don't let quitting the More prompt make this fail.
|
||||
got_int = false;
|
||||
|
||||
// Set "cmdwin_type" before any autocommands may mess things up.
|
||||
// Set "cmdwin_..." variables before any autocommands may mess things up.
|
||||
cmdwin_type = get_cmdline_type();
|
||||
cmdwin_level = ccline.level;
|
||||
cmdwin_win = curwin;
|
||||
cmdwin_old_curwin = old_curwin;
|
||||
|
||||
// Create empty command-line buffer.
|
||||
if (buf_open_scratch(0, _("[Command Line]")) == FAIL) {
|
||||
// Some autocommand messed it up?
|
||||
win_close(curwin, true, false);
|
||||
ga_clear(&winsizes);
|
||||
// Create empty command-line buffer. Be especially cautious of BufLeave
|
||||
// autocommands from do_ecmd(), as cmdwin restrictions do not apply to them!
|
||||
const int newbuf_status = buf_open_scratch(0, NULL);
|
||||
const bool cmdwin_valid = win_valid(cmdwin_win);
|
||||
if (newbuf_status == FAIL || !cmdwin_valid || curwin != cmdwin_win || !win_valid(old_curwin)
|
||||
|| !bufref_valid(&old_curbuf) || old_curwin->w_buffer != old_curbuf.br_buf) {
|
||||
if (newbuf_status == OK) {
|
||||
set_bufref(&bufref, curbuf);
|
||||
}
|
||||
if (cmdwin_valid && !last_window(cmdwin_win)) {
|
||||
win_close(cmdwin_win, true, false);
|
||||
}
|
||||
// win_close() autocommands may have already deleted the buffer.
|
||||
if (newbuf_status == OK && bufref_valid(&bufref) && bufref.br_buf != curbuf) {
|
||||
close_buffer(NULL, bufref.br_buf, DOBUF_WIPE, false, false);
|
||||
}
|
||||
|
||||
cmdwin_type = 0;
|
||||
cmdwin_level = 0;
|
||||
cmdwin_win = NULL;
|
||||
cmdwin_old_curwin = NULL;
|
||||
beep_flush();
|
||||
ga_clear(&winsizes);
|
||||
return Ctrl_C;
|
||||
}
|
||||
cmdwin_buf = curbuf;
|
||||
|
||||
// Command-line buffer has bufhidden=wipe, unlike a true "scratch" buffer.
|
||||
set_option_value_give_err(kOptBufhidden, STATIC_CSTR_AS_OPTVAL("wipe"), OPT_LOCAL);
|
||||
curbuf->b_p_ma = true;
|
||||
@ -4434,15 +4464,18 @@ static int open_cmdwin(void)
|
||||
|
||||
cmdwin_type = 0;
|
||||
cmdwin_level = 0;
|
||||
cmdwin_buf = NULL;
|
||||
cmdwin_win = NULL;
|
||||
cmdwin_old_curwin = NULL;
|
||||
|
||||
exmode_active = save_exmode;
|
||||
|
||||
// Safety check: The old window or buffer was deleted: It's a bug when
|
||||
// this happens!
|
||||
if (!win_valid(old_curwin) || !bufref_valid(&old_curbuf)) {
|
||||
// Safety check: The old window or buffer was changed or deleted: It's a bug
|
||||
// when this happens!
|
||||
if (!win_valid(old_curwin) || !bufref_valid(&old_curbuf)
|
||||
|| old_curwin->w_buffer != old_curbuf.br_buf) {
|
||||
cmdwin_result = Ctrl_C;
|
||||
emsg(_("E199: Active window or buffer deleted"));
|
||||
emsg(_(e_active_window_or_buffer_changed_or_deleted));
|
||||
} else {
|
||||
win_T *wp;
|
||||
// autocmds may abort script processing
|
||||
|
@ -366,6 +366,7 @@ static int put_view(FILE *fd, win_T *wp, int add_edit, unsigned *flagp, int curr
|
||||
|
||||
if (put_line(fd, "enew | setl bt=help") == FAIL
|
||||
|| fprintf(fd, "help %s", curtag) < 0 || put_eol(fd) == FAIL) {
|
||||
xfree(fname_esc);
|
||||
return FAIL;
|
||||
}
|
||||
} else if (wp->w_buffer->b_ffname != NULL
|
||||
|
@ -70,9 +70,10 @@ void extmark_set(buf_T *buf, uint32_t ns_id, uint32_t *idp, int row, colnr_T col
|
||||
extmark_del_id(buf, ns_id, id);
|
||||
} else {
|
||||
assert(marktree_itr_valid(itr));
|
||||
bool invalid = mt_invalid(old_mark);
|
||||
if (old_mark.pos.row == row && old_mark.pos.col == col) {
|
||||
// not paired: we can revise in place
|
||||
if (mt_decor_any(old_mark)) {
|
||||
if (!invalid && mt_decor_any(old_mark)) {
|
||||
mt_itr_rawkey(itr).flags &= (uint16_t) ~MT_FLAG_DECOR_SIGNTEXT;
|
||||
buf_decor_remove(buf, row, row, mt_decor(old_mark), true);
|
||||
}
|
||||
@ -82,7 +83,9 @@ void extmark_set(buf_T *buf, uint32_t ns_id, uint32_t *idp, int row, colnr_T col
|
||||
goto revised;
|
||||
}
|
||||
marktree_del_itr(buf->b_marktree, itr, false);
|
||||
buf_decor_remove(buf, old_mark.pos.row, old_mark.pos.row, mt_decor(old_mark), true);
|
||||
if (!invalid) {
|
||||
buf_decor_remove(buf, old_mark.pos.row, old_mark.pos.row, mt_decor(old_mark), true);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
*ns = MAX(*ns, id);
|
||||
|
@ -1146,10 +1146,10 @@ static void gotchars(const uint8_t *chars, size_t len)
|
||||
maptick++;
|
||||
}
|
||||
|
||||
/// Record a <Nop> key.
|
||||
void gotchars_nop(void)
|
||||
/// Record an <Ignore> key.
|
||||
void gotchars_ignore(void)
|
||||
{
|
||||
uint8_t nop_buf[3] = { K_SPECIAL, KS_EXTRA, KE_NOP };
|
||||
uint8_t nop_buf[3] = { K_SPECIAL, KS_EXTRA, KE_IGNORE };
|
||||
gotchars(nop_buf, 3);
|
||||
}
|
||||
|
||||
@ -2746,9 +2746,9 @@ static int vgetorpeek(bool advance)
|
||||
}
|
||||
|
||||
if (timedout && c == ESC) {
|
||||
// When recording there will be no timeout. Add a <Nop> after the ESC
|
||||
// to avoid that it forms a key code with following characters.
|
||||
gotchars_nop();
|
||||
// When recording there will be no timeout. Add an <Ignore> after the
|
||||
// ESC to avoid that it forms a key code with following characters.
|
||||
gotchars_ignore();
|
||||
}
|
||||
|
||||
vgetc_busy--;
|
||||
|
@ -752,6 +752,8 @@ EXTERN bool km_startsel INIT( = false);
|
||||
EXTERN int cmdwin_type INIT( = 0); ///< type of cmdline window or 0
|
||||
EXTERN int cmdwin_result INIT( = 0); ///< result of cmdline window or 0
|
||||
EXTERN int cmdwin_level INIT( = 0); ///< cmdline recursion level
|
||||
EXTERN buf_T *cmdwin_buf INIT( = NULL); ///< buffer of cmdline window or NULL
|
||||
EXTERN win_T *cmdwin_win INIT( = NULL); ///< window of cmdline window or NULL
|
||||
EXTERN win_T *cmdwin_old_curwin INIT( = NULL); ///< curwin before opening cmdline window or NULL
|
||||
|
||||
EXTERN char no_lines_msg[] INIT( = N_("--No lines in buffer--"));
|
||||
|
@ -701,6 +701,9 @@ void get_local_additions(void)
|
||||
const char *const f1 = fnames[i1];
|
||||
const char *const t1 = path_tail(f1);
|
||||
const char *const e1 = strrchr(t1, '.');
|
||||
if (e1 == NULL) {
|
||||
continue;
|
||||
}
|
||||
if (path_fnamecmp(e1, ".txt") != 0
|
||||
&& path_fnamecmp(e1, fname + 4) != 0) {
|
||||
// Not .txt and not .abx, remove it.
|
||||
@ -715,7 +718,7 @@ void get_local_additions(void)
|
||||
}
|
||||
const char *const t2 = path_tail(f2);
|
||||
const char *const e2 = strrchr(t2, '.');
|
||||
if (e1 == NULL || e2 == NULL) {
|
||||
if (e2 == NULL) {
|
||||
continue;
|
||||
}
|
||||
if (e1 - f1 != e2 - f2
|
||||
|
@ -310,7 +310,7 @@ static const char *highlight_init_light[] = {
|
||||
"Normal guifg=NvimDarkGrey2 guibg=NvimLightGrey2 ctermfg=NONE ctermbg=NONE",
|
||||
|
||||
// UI
|
||||
"Added guifg=NvimDarGreen ctermfg=2",
|
||||
"Added guifg=NvimDarkGreen ctermfg=2",
|
||||
"Changed guifg=NvimDarkCyan ctermfg=6",
|
||||
"ColorColumn guibg=NvimLightGrey4 cterm=reverse",
|
||||
"Conceal guifg=NvimLightGrey4",
|
||||
|
@ -2760,9 +2760,11 @@ static int info_add_completion_info(list_T *li)
|
||||
|
||||
// Skip the element with the CP_ORIGINAL_TEXT flag at the beginning, in case of
|
||||
// forward completion, or at the end, in case of backward completion.
|
||||
match = forward ? match->cp_next
|
||||
: (compl_no_select && match_at_original_text(match)
|
||||
? match->cp_prev : match->cp_prev->cp_prev);
|
||||
match = (forward || match->cp_prev == NULL
|
||||
? match->cp_next
|
||||
: (compl_no_select && match_at_original_text(match)
|
||||
? match->cp_prev
|
||||
: match->cp_prev->cp_prev));
|
||||
|
||||
while (match != NULL && !match_at_original_text(match)) {
|
||||
dict_T *di = tv_dict_alloc();
|
||||
|
@ -1641,27 +1641,38 @@ bool nlua_is_deferred_safe(void)
|
||||
return in_fast_callback == 0;
|
||||
}
|
||||
|
||||
/// Run lua string
|
||||
/// Executes Lua code.
|
||||
///
|
||||
/// Used for :lua.
|
||||
/// Implements `:lua` and `:lua ={expr}`.
|
||||
///
|
||||
/// @param eap Vimscript command being run.
|
||||
/// @param eap Vimscript `:lua {code}`, `:{range}lua`, or `:lua ={expr}` command.
|
||||
void ex_lua(exarg_T *const eap)
|
||||
FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
// ":{range}lua"
|
||||
if (eap->addr_count > 0 || *eap->arg == NUL) {
|
||||
if (eap->addr_count > 0 && *eap->arg == NUL) {
|
||||
cmd_source_buffer(eap, true);
|
||||
} else {
|
||||
semsg(_(e_invarg2), "exactly one of {chunk} or {range} required");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
size_t len;
|
||||
char *code = script_get(eap, &len);
|
||||
if (eap->skip || code == NULL) {
|
||||
xfree(code);
|
||||
return;
|
||||
}
|
||||
// When =expr is used transform it to vim.print(expr)
|
||||
|
||||
// ":lua {code}", ":={expr}" or ":lua ={expr}"
|
||||
//
|
||||
// When "=expr" is used transform it to "vim.print(expr)".
|
||||
if (eap->cmdidx == CMD_equal || code[0] == '=') {
|
||||
size_t off = (eap->cmdidx == CMD_equal) ? 0 : 1;
|
||||
len += sizeof("vim.print()") - 1 - off;
|
||||
// code_buf needs to be 1 char larger then len for null byte in the end.
|
||||
// lua nlua_typval_exec doesn't expect null terminated string so len
|
||||
// needs to end before null byte.
|
||||
// `nlua_typval_exec` doesn't expect NUL-terminated string so `len` must end before NUL byte.
|
||||
char *code_buf = xmallocz(len);
|
||||
vim_snprintf(code_buf, len + 1, "vim.print(%s)", code + off);
|
||||
xfree(code);
|
||||
@ -1673,11 +1684,11 @@ void ex_lua(exarg_T *const eap)
|
||||
xfree(code);
|
||||
}
|
||||
|
||||
/// Run lua string for each line in range
|
||||
/// Executes Lua code for-each line in a buffer range.
|
||||
///
|
||||
/// Used for :luado.
|
||||
/// Implements `:luado`.
|
||||
///
|
||||
/// @param eap Vimscript command being run.
|
||||
/// @param eap Vimscript `:luado {code}` command.
|
||||
void ex_luado(exarg_T *const eap)
|
||||
FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
@ -1721,10 +1732,15 @@ void ex_luado(exarg_T *const eap)
|
||||
nlua_error(lstate, _("E5110: Error executing lua: %.*s"));
|
||||
return;
|
||||
}
|
||||
|
||||
buf_T *const was_curbuf = curbuf;
|
||||
|
||||
for (linenr_T l = eap->line1; l <= eap->line2; l++) {
|
||||
// Check the line number, the command may have deleted lines.
|
||||
if (l > curbuf->b_ml.ml_line_count) {
|
||||
break;
|
||||
}
|
||||
|
||||
lua_pushvalue(lstate, -1);
|
||||
const char *const old_line = ml_get_buf(curbuf, l);
|
||||
// Get length of old_line here as calling Lua code may free it.
|
||||
@ -1735,6 +1751,13 @@ void ex_luado(exarg_T *const eap)
|
||||
nlua_error(lstate, _("E5111: Error calling lua: %.*s"));
|
||||
break;
|
||||
}
|
||||
|
||||
// Catch the command switching to another buffer.
|
||||
// Check the line number, the command may have deleted lines.
|
||||
if (curbuf != was_curbuf || l > curbuf->b_ml.ml_line_count) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (lua_isstring(lstate, -1)) {
|
||||
size_t new_line_len;
|
||||
const char *const new_line = lua_tolstring(lstate, -1, &new_line_len);
|
||||
@ -1749,16 +1772,17 @@ void ex_luado(exarg_T *const eap)
|
||||
}
|
||||
lua_pop(lstate, 1);
|
||||
}
|
||||
|
||||
lua_pop(lstate, 1);
|
||||
check_cursor();
|
||||
redraw_curbuf_later(UPD_NOT_VALID);
|
||||
}
|
||||
|
||||
/// Run lua file
|
||||
/// Executes Lua code from a file location.
|
||||
///
|
||||
/// Used for :luafile.
|
||||
/// Implements `:luafile`.
|
||||
///
|
||||
/// @param eap Vimscript command being run.
|
||||
/// @param eap Vimscript `:luafile {file}` command.
|
||||
void ex_luafile(exarg_T *const eap)
|
||||
FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
|
@ -1,5 +1,5 @@
|
||||
// lua bindings for tree-sitter.
|
||||
// NB: this file mostly contains a generic lua interface for tree-sitter
|
||||
// lua bindings for treesitter.
|
||||
// NB: this file mostly contains a generic lua interface for treesitter
|
||||
// trees and nodes, and could be broken out as a reusable lua package
|
||||
|
||||
#include <assert.h>
|
||||
|
@ -1326,18 +1326,18 @@ retnomove:
|
||||
&& !sep_line_offset
|
||||
&& (wp->w_p_rl
|
||||
? col < wp->w_width_inner - fdc
|
||||
: col >= fdc + (cmdwin_type == 0 && wp == curwin ? 0 : 1))
|
||||
: col >= fdc + (wp != cmdwin_win ? 0 : 1))
|
||||
&& (flags & MOUSE_MAY_STOP_VIS)))) {
|
||||
end_visual_mode();
|
||||
redraw_curbuf_later(UPD_INVERTED); // delete the inversion
|
||||
}
|
||||
if (cmdwin_type != 0 && wp != curwin) {
|
||||
if (cmdwin_type != 0 && wp != cmdwin_win) {
|
||||
// A click outside the command-line window: Use modeless
|
||||
// selection if possible. Allow dragging the status lines.
|
||||
sep_line_offset = 0;
|
||||
row = 0;
|
||||
col += wp->w_wincol;
|
||||
wp = curwin;
|
||||
wp = cmdwin_win;
|
||||
}
|
||||
// Only change window focus when not clicking on or dragging the
|
||||
// status line. Do change focus when releasing the mouse button
|
||||
|
@ -760,7 +760,7 @@ int win_col_off(win_T *wp)
|
||||
{
|
||||
return ((wp->w_p_nu || wp->w_p_rnu || *wp->w_p_stc != NUL)
|
||||
? (number_width(wp) + (*wp->w_p_stc == NUL)) : 0)
|
||||
+ ((cmdwin_type == 0 || wp != curwin) ? 0 : 1)
|
||||
+ ((wp != cmdwin_win) ? 0 : 1)
|
||||
+ win_fdccol_count(wp) + (wp->w_scwidth * SIGN_WIDTH);
|
||||
}
|
||||
|
||||
|
@ -845,10 +845,10 @@ static void normal_get_additional_char(NormalState *s)
|
||||
no_mapping++;
|
||||
// Vim may be in a different mode when the user types the next key,
|
||||
// but when replaying a recording the next key is already in the
|
||||
// typeahead buffer, so record a <Nop> before that to prevent the
|
||||
// vpeekc() above from applying wrong mappings when replaying.
|
||||
// typeahead buffer, so record an <Ignore> before that to prevent
|
||||
// the vpeekc() above from applying wrong mappings when replaying.
|
||||
no_u_sync++;
|
||||
gotchars_nop();
|
||||
gotchars_ignore();
|
||||
no_u_sync--;
|
||||
}
|
||||
}
|
||||
|
@ -9300,6 +9300,7 @@ return {
|
||||
|
||||
Level Messages ~
|
||||
----------------------------------------------------------------------
|
||||
1 Enables Lua tracing (see above). Does not produce messages.
|
||||
2 When a file is ":source"'ed, or |shada| file is read or written.
|
||||
3 UI info, terminal capabilities.
|
||||
4 Shell commands.
|
||||
|
@ -1779,7 +1779,7 @@ freeall:
|
||||
static void cmd_source(char *fname, exarg_T *eap)
|
||||
{
|
||||
if (eap != NULL && *fname == NUL) {
|
||||
cmd_source_buffer(eap);
|
||||
cmd_source_buffer(eap, false);
|
||||
} else if (eap != NULL && eap->forceit) {
|
||||
// ":source!": read Normal mode commands
|
||||
// Need to execute the commands directly. This is required at least
|
||||
@ -1989,7 +1989,7 @@ static int source_using_linegetter(void *cookie, LineGetter fgetline, const char
|
||||
return retval;
|
||||
}
|
||||
|
||||
static void cmd_source_buffer(const exarg_T *const eap)
|
||||
void cmd_source_buffer(const exarg_T *const eap, bool ex_lua)
|
||||
FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
if (curbuf == NULL) {
|
||||
@ -2012,9 +2012,10 @@ static void cmd_source_buffer(const exarg_T *const eap)
|
||||
.buf = ga.ga_data,
|
||||
.offset = 0,
|
||||
};
|
||||
if (strequal(curbuf->b_p_ft, "lua")
|
||||
if (ex_lua || strequal(curbuf->b_p_ft, "lua")
|
||||
|| (curbuf->b_fname && path_with_extension(curbuf->b_fname, "lua"))) {
|
||||
nlua_source_using_linegetter(get_str_line, (void *)&cookie, ":source (no file)");
|
||||
char *name = ex_lua ? ":{range}lua" : ":source (no file)";
|
||||
nlua_source_using_linegetter(get_str_line, (void *)&cookie, name);
|
||||
} else {
|
||||
source_using_linegetter((void *)&cookie, get_str_line, ":source (no file)");
|
||||
}
|
||||
|
@ -151,14 +151,14 @@ void win_redr_status(win_T *wp)
|
||||
}
|
||||
|
||||
grid_line_start(&default_grid, is_stl_global ? (Rows - (int)p_ch - 1) : W_ENDROW(wp));
|
||||
int col = is_stl_global ? 0 : wp->w_wincol;
|
||||
const int off = is_stl_global ? 0 : wp->w_wincol;
|
||||
|
||||
int width = grid_line_puts(col, p, -1, attr);
|
||||
grid_line_fill(width + col, this_ru_col + col, fillchar, attr);
|
||||
int width = grid_line_puts(off, p, -1, attr);
|
||||
grid_line_fill(off + width, off + this_ru_col, fillchar, attr);
|
||||
|
||||
if (get_keymap_str(wp, "<%s>", NameBuff, MAXPATHL)
|
||||
&& this_ru_col - len > (int)(strlen(NameBuff) + 1)) {
|
||||
grid_line_puts((int)((size_t)this_ru_col - strlen(NameBuff) - 1), NameBuff, -1, attr);
|
||||
&& this_ru_col - len > (int)strlen(NameBuff) + 1) {
|
||||
grid_line_puts(off + this_ru_col - (int)strlen(NameBuff) - 1, NameBuff, -1, attr);
|
||||
}
|
||||
|
||||
win_redr_ruler(wp);
|
||||
@ -168,7 +168,7 @@ void win_redr_status(win_T *wp)
|
||||
const int sc_width = MIN(10, this_ru_col - len - 2);
|
||||
|
||||
if (sc_width > 0) {
|
||||
grid_line_puts(wp->w_wincol + this_ru_col - sc_width - 1, showcmd_buf, sc_width, attr);
|
||||
grid_line_puts(off + this_ru_col - sc_width - 1, showcmd_buf, sc_width, attr);
|
||||
}
|
||||
}
|
||||
|
||||
@ -615,8 +615,8 @@ void win_redr_ruler(win_T *wp)
|
||||
}
|
||||
}
|
||||
|
||||
int w = grid_line_puts(this_ru_col + off, buffer, -1, attr);
|
||||
grid_line_fill(this_ru_col + off + w, off + width, fillchar, attr);
|
||||
int w = grid_line_puts(off + this_ru_col, buffer, -1, attr);
|
||||
grid_line_fill(off + this_ru_col + w, off + width, fillchar, attr);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -93,6 +93,7 @@
|
||||
#include "nvim/types_defs.h"
|
||||
#include "nvim/ui.h"
|
||||
#include "nvim/vim_defs.h"
|
||||
#include "nvim/window.h"
|
||||
|
||||
typedef struct {
|
||||
VimState state;
|
||||
@ -615,6 +616,8 @@ static int terminal_check(VimState *state)
|
||||
curbuf->b_locked--;
|
||||
}
|
||||
|
||||
may_trigger_win_scrolled_resized();
|
||||
|
||||
if (need_maketitle) { // Update title in terminal-mode. #7248
|
||||
maketitle();
|
||||
}
|
||||
|
@ -763,7 +763,7 @@ int comp_textwidth(bool ff)
|
||||
// The width is the window width minus 'wrapmargin' minus all the
|
||||
// things that add to the margin.
|
||||
textwidth = curwin->w_width_inner - (int)curbuf->b_p_wm;
|
||||
if (cmdwin_type != 0) {
|
||||
if (curbuf == cmdwin_buf) {
|
||||
textwidth -= 1;
|
||||
}
|
||||
textwidth -= win_fdccol_count(curwin);
|
||||
|
@ -269,6 +269,10 @@ static void tui_query_kitty_keyboard(TUIData *tui)
|
||||
out(tui, S_LEN("\x1b[?u\x1b[c"));
|
||||
}
|
||||
|
||||
/// Enable the alternate screen and emit other control sequences to start the TUI.
|
||||
///
|
||||
/// This is also called when the TUI is resumed after being suspended. We reinitialize all state
|
||||
/// from terminfo just in case the controlling terminal has changed (#27177).
|
||||
static void terminfo_start(TUIData *tui)
|
||||
{
|
||||
tui->scroll_region_is_full_screen = true;
|
||||
@ -418,6 +422,7 @@ static void terminfo_start(TUIData *tui)
|
||||
flush_buf(tui);
|
||||
}
|
||||
|
||||
/// Disable the alternate screen and prepare for the TUI to close.
|
||||
static void terminfo_stop(TUIData *tui)
|
||||
{
|
||||
// Destroy output stuff
|
||||
@ -489,7 +494,7 @@ static void tui_terminal_after_startup(TUIData *tui)
|
||||
flush_buf(tui);
|
||||
}
|
||||
|
||||
/// stop the terminal but allow it to restart later (like after suspend)
|
||||
/// Stop the terminal but allow it to restart later (like after suspend)
|
||||
static void tui_terminal_stop(TUIData *tui)
|
||||
{
|
||||
if (uv_is_closing((uv_handle_t *)&tui->output_handle)) {
|
||||
|
@ -1557,7 +1557,7 @@ bool win_valid(const win_T *win) FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
|
||||
/// Check if "win" is a pointer to an existing window in tabpage "tp".
|
||||
///
|
||||
/// @param win window to check
|
||||
static bool tabpage_win_valid(const tabpage_T *tp, const win_T *win)
|
||||
bool tabpage_win_valid(const tabpage_T *tp, const win_T *win)
|
||||
FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
|
||||
{
|
||||
if (win == NULL) {
|
||||
@ -2485,7 +2485,7 @@ bool can_close_in_cmdwin(win_T *win, Error *err)
|
||||
FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
if (cmdwin_type != 0) {
|
||||
if (win == curwin) {
|
||||
if (win == cmdwin_win) {
|
||||
cmdwin_result = Ctrl_C;
|
||||
return false;
|
||||
} else if (win == cmdwin_old_curwin) {
|
||||
@ -2553,6 +2553,7 @@ static bool close_last_window_tabpage(win_T *win, bool free_buf, tabpage_T *prev
|
||||
/// "abort_if_last" is passed to close_buffer(): abort closing if all other
|
||||
/// windows are closed.
|
||||
static void win_close_buffer(win_T *win, int action, bool abort_if_last)
|
||||
FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
// Free independent synblock before the buffer is freed.
|
||||
if (win->w_buffer != NULL) {
|
||||
@ -2590,6 +2591,7 @@ static void win_close_buffer(win_T *win, int action, bool abort_if_last)
|
||||
// Called by :quit, :close, :xit, :wq and findtag().
|
||||
// Returns FAIL when the window was not closed.
|
||||
int win_close(win_T *win, bool free_buf, bool force)
|
||||
FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
tabpage_T *prev_curtab = curtab;
|
||||
frame_T *win_frame = win->w_floating ? NULL : win->w_frame->fr_parent;
|
||||
@ -2888,6 +2890,7 @@ static void do_autocmd_winclosed(win_T *win)
|
||||
// Caller must check if buffer is hidden and whether the tabline needs to be
|
||||
// updated.
|
||||
void win_close_othertab(win_T *win, int free_buf, tabpage_T *tp)
|
||||
FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
// Get here with win->w_buffer == NULL when win_close() detects the tab page
|
||||
// changed.
|
||||
@ -2989,6 +2992,7 @@ void win_close_othertab(win_T *win, int free_buf, tabpage_T *tp)
|
||||
///
|
||||
/// @return a pointer to the window that got the freed up space.
|
||||
static win_T *win_free_mem(win_T *win, int *dirp, tabpage_T *tp)
|
||||
FUNC_ATTR_NONNULL_ARG(1)
|
||||
{
|
||||
win_T *wp;
|
||||
tabpage_T *win_tp = tp == NULL ? curtab : tp;
|
||||
@ -3007,6 +3011,7 @@ static win_T *win_free_mem(win_T *win, int *dirp, tabpage_T *tp)
|
||||
wp = firstwin;
|
||||
}
|
||||
} else {
|
||||
assert(tp != curtab);
|
||||
if (tabpage_win_valid(tp, tp->tp_prevwin) && tp->tp_prevwin != win) {
|
||||
wp = tp->tp_prevwin;
|
||||
} else {
|
||||
@ -3030,6 +3035,9 @@ void win_free_all(void)
|
||||
{
|
||||
// avoid an error for switching tabpage with the cmdline window open
|
||||
cmdwin_type = 0;
|
||||
cmdwin_buf = NULL;
|
||||
cmdwin_win = NULL;
|
||||
cmdwin_old_curwin = NULL;
|
||||
|
||||
while (first_tabpage->tp_next != NULL) {
|
||||
tabpage_close(true);
|
||||
@ -3076,7 +3084,10 @@ void win_free_all(void)
|
||||
///
|
||||
/// @return a pointer to the window that got the freed up space.
|
||||
win_T *winframe_remove(win_T *win, int *dirp, tabpage_T *tp)
|
||||
FUNC_ATTR_NONNULL_ARG(1, 2)
|
||||
{
|
||||
assert(tp == NULL || tp != curtab);
|
||||
|
||||
// If there is only one window there is nothing to remove.
|
||||
if (tp == NULL ? ONE_WINDOW : tp->tp_firstwin == tp->tp_lastwin) {
|
||||
return NULL;
|
||||
@ -3223,7 +3234,10 @@ win_T *winframe_remove(win_T *win, int *dirp, tabpage_T *tp)
|
||||
/// @return a pointer to the frame that will receive the empty screen space that
|
||||
/// is left over after "win" is closed.
|
||||
static frame_T *win_altframe(win_T *win, tabpage_T *tp)
|
||||
FUNC_ATTR_NONNULL_ARG(1)
|
||||
{
|
||||
assert(tp == NULL || tp != curtab);
|
||||
|
||||
if (tp == NULL ? ONE_WINDOW : tp->tp_firstwin == tp->tp_lastwin) {
|
||||
return alt_tabpage()->tp_curwin->w_frame;
|
||||
}
|
||||
@ -3287,6 +3301,7 @@ static tabpage_T *alt_tabpage(void)
|
||||
|
||||
// Find the left-upper window in frame "frp".
|
||||
win_T *frame2win(frame_T *frp)
|
||||
FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
while (frp->fr_win == NULL) {
|
||||
frp = frp->fr_child;
|
||||
@ -5139,7 +5154,10 @@ void win_append(win_T *after, win_T *wp)
|
||||
///
|
||||
/// @param tp tab page "win" is in, NULL for current
|
||||
void win_remove(win_T *wp, tabpage_T *tp)
|
||||
FUNC_ATTR_NONNULL_ARG(1)
|
||||
{
|
||||
assert(tp == NULL || tp != curtab);
|
||||
|
||||
if (wp->w_prev != NULL) {
|
||||
wp->w_prev->w_next = wp->w_next;
|
||||
} else if (tp == NULL) {
|
||||
@ -5367,7 +5385,7 @@ static int check_window_scroll_resize(int *size_count, win_T **first_scroll_win,
|
||||
|
||||
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
|
||||
// Skip floating windows that do not have a snapshot (usually because they are newly-created),
|
||||
// as unlike split windows, creating floating windows do not cause other windows to resize.
|
||||
// as unlike split windows, creating floating windows doesn't cause other windows to resize.
|
||||
if (wp->w_floating && wp->w_last_topline == 0) {
|
||||
wp->w_last_topline = wp->w_topline;
|
||||
wp->w_last_topfill = wp->w_topfill;
|
||||
|
@ -1798,6 +1798,36 @@ describe('API/extmarks', function()
|
||||
eq(1, #extmarks)
|
||||
eq('https://example.com', extmarks[1][4].url)
|
||||
end)
|
||||
|
||||
it('respects priority', function()
|
||||
screen = Screen.new(15, 10)
|
||||
screen:attach()
|
||||
|
||||
set_extmark(ns, marks[1], 0, 0, {
|
||||
hl_group = 'Comment',
|
||||
end_col = 2,
|
||||
priority = 20,
|
||||
})
|
||||
|
||||
-- Extmark defined after first extmark but has lower priority, first extmark "wins"
|
||||
set_extmark(ns, marks[2], 0, 0, {
|
||||
hl_group = 'String',
|
||||
end_col = 2,
|
||||
priority = 10,
|
||||
})
|
||||
|
||||
screen:expect {
|
||||
grid = [[
|
||||
{1:12}34^5 |
|
||||
{2:~ }|*8
|
||||
|
|
||||
]],
|
||||
attr_ids = {
|
||||
[1] = { foreground = Screen.colors.Blue1 },
|
||||
[2] = { foreground = Screen.colors.Blue1, bold = true },
|
||||
},
|
||||
}
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('Extmarks buffer api with many marks', function()
|
||||
|
@ -12,15 +12,19 @@ describe('api/tabpage', function()
|
||||
|
||||
describe('list_wins and get_win', function()
|
||||
it('works', function()
|
||||
helpers.command('tabnew')
|
||||
helpers.command('vsplit')
|
||||
command('tabnew')
|
||||
command('vsplit')
|
||||
local tab1, tab2 = unpack(api.nvim_list_tabpages())
|
||||
local win1, win2, win3 = unpack(api.nvim_list_wins())
|
||||
eq({ win1 }, api.nvim_tabpage_list_wins(tab1))
|
||||
eq(win1, api.nvim_tabpage_get_win(tab1))
|
||||
eq({ win2, win3 }, api.nvim_tabpage_list_wins(tab2))
|
||||
eq(win2, api.nvim_tabpage_get_win(tab2))
|
||||
api.nvim_set_current_win(win3)
|
||||
eq(win3, api.nvim_tabpage_get_win(tab2))
|
||||
command('tabprev')
|
||||
eq(win1, api.nvim_tabpage_get_win(tab1))
|
||||
eq(win3, api.nvim_tabpage_get_win(tab2))
|
||||
end)
|
||||
|
||||
it('validates args', function()
|
||||
@ -28,6 +32,62 @@ describe('api/tabpage', function()
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('set_win', function()
|
||||
it('works', function()
|
||||
command('tabnew')
|
||||
command('vsplit')
|
||||
local tab1, tab2 = unpack(api.nvim_list_tabpages())
|
||||
local win1, win2, win3 = unpack(api.nvim_list_wins())
|
||||
eq({ win1 }, api.nvim_tabpage_list_wins(tab1))
|
||||
eq({ win2, win3 }, api.nvim_tabpage_list_wins(tab2))
|
||||
eq(win2, api.nvim_tabpage_get_win(tab2))
|
||||
api.nvim_tabpage_set_win(tab2, win3)
|
||||
eq(win3, api.nvim_tabpage_get_win(tab2))
|
||||
end)
|
||||
|
||||
it('works in non-current tabpages', function()
|
||||
command('tabnew')
|
||||
command('vsplit')
|
||||
local tab1, tab2 = unpack(api.nvim_list_tabpages())
|
||||
local win1, win2, win3 = unpack(api.nvim_list_wins())
|
||||
eq({ win1 }, api.nvim_tabpage_list_wins(tab1))
|
||||
eq({ win2, win3 }, api.nvim_tabpage_list_wins(tab2))
|
||||
eq(win2, api.nvim_tabpage_get_win(tab2))
|
||||
eq(win2, api.nvim_get_current_win())
|
||||
|
||||
command('tabprev')
|
||||
|
||||
eq(tab1, api.nvim_get_current_tabpage())
|
||||
|
||||
eq(win2, api.nvim_tabpage_get_win(tab2))
|
||||
api.nvim_tabpage_set_win(tab2, win3)
|
||||
eq(win3, api.nvim_tabpage_get_win(tab2))
|
||||
|
||||
command('tabnext')
|
||||
eq(win3, api.nvim_get_current_win())
|
||||
end)
|
||||
|
||||
it('throws an error when the window does not belong to the tabpage', function()
|
||||
command('tabnew')
|
||||
command('vsplit')
|
||||
local tab1, tab2 = unpack(api.nvim_list_tabpages())
|
||||
local win1, win2, win3 = unpack(api.nvim_list_wins())
|
||||
eq({ win1 }, api.nvim_tabpage_list_wins(tab1))
|
||||
eq({ win2, win3 }, api.nvim_tabpage_list_wins(tab2))
|
||||
eq(win2, api.nvim_get_current_win())
|
||||
|
||||
eq(
|
||||
string.format('Window does not belong to tabpage %d', tab2),
|
||||
pcall_err(api.nvim_tabpage_set_win, tab2, win1)
|
||||
)
|
||||
|
||||
eq(
|
||||
string.format('Window does not belong to tabpage %d', tab1),
|
||||
pcall_err(api.nvim_tabpage_set_win, tab1, win3)
|
||||
)
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('{get,set,del}_var', function()
|
||||
it('works', function()
|
||||
api.nvim_tabpage_set_var(0, 'lua', { 1, 2, { ['3'] = 1 } })
|
||||
@ -64,12 +124,12 @@ describe('api/tabpage', function()
|
||||
local tabs = api.nvim_list_tabpages()
|
||||
eq(1, api.nvim_tabpage_get_number(tabs[1]))
|
||||
|
||||
helpers.command('tabnew')
|
||||
command('tabnew')
|
||||
local tab1, tab2 = unpack(api.nvim_list_tabpages())
|
||||
eq(1, api.nvim_tabpage_get_number(tab1))
|
||||
eq(2, api.nvim_tabpage_get_number(tab2))
|
||||
|
||||
helpers.command('-tabmove')
|
||||
command('-tabmove')
|
||||
eq(2, api.nvim_tabpage_get_number(tab1))
|
||||
eq(1, api.nvim_tabpage_get_number(tab2))
|
||||
end)
|
||||
@ -77,11 +137,11 @@ describe('api/tabpage', function()
|
||||
|
||||
describe('is_valid', function()
|
||||
it('works', function()
|
||||
helpers.command('tabnew')
|
||||
command('tabnew')
|
||||
local tab = api.nvim_list_tabpages()[2]
|
||||
api.nvim_set_current_tabpage(tab)
|
||||
ok(api.nvim_tabpage_is_valid(tab))
|
||||
helpers.command('tabclose')
|
||||
command('tabclose')
|
||||
ok(not api.nvim_tabpage_is_valid(tab))
|
||||
end)
|
||||
end)
|
||||
|
@ -399,6 +399,19 @@ describe('API', function()
|
||||
]],
|
||||
}
|
||||
end)
|
||||
|
||||
it('errors properly when command too recursive', function()
|
||||
exec_lua([[
|
||||
_G.success = false
|
||||
vim.api.nvim_create_user_command('Test', function()
|
||||
vim.api.nvim_exec2('Test', {})
|
||||
_G.success = true
|
||||
end, {})
|
||||
]])
|
||||
pcall_err(command, 'Test')
|
||||
assert_alive()
|
||||
eq(false, exec_lua('return _G.success'))
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('nvim_command', function()
|
||||
@ -4560,6 +4573,7 @@ describe('API', function()
|
||||
line6
|
||||
]]
|
||||
end)
|
||||
|
||||
it('works with count', function()
|
||||
insert [[
|
||||
line1
|
||||
@ -4577,6 +4591,7 @@ describe('API', function()
|
||||
line6
|
||||
]]
|
||||
end)
|
||||
|
||||
it('works with register', function()
|
||||
insert [[
|
||||
line1
|
||||
@ -4599,11 +4614,13 @@ describe('API', function()
|
||||
line6
|
||||
]]
|
||||
end)
|
||||
|
||||
it('works with bang', function()
|
||||
api.nvim_create_user_command('Foo', 'echo "<bang>"', { bang = true })
|
||||
eq('!', api.nvim_cmd({ cmd = 'Foo', bang = true }, { output = true }))
|
||||
eq('', api.nvim_cmd({ cmd = 'Foo', bang = false }, { output = true }))
|
||||
end)
|
||||
|
||||
it('works with modifiers', function()
|
||||
-- with silent = true output is still captured
|
||||
eq(
|
||||
@ -4659,6 +4676,7 @@ describe('API', function()
|
||||
feed(':call<CR><CR>')
|
||||
eq('E471: Argument required', api.nvim_cmd({ cmd = 'messages' }, { output = true }))
|
||||
end)
|
||||
|
||||
it('works with magic.file', function()
|
||||
exec_lua([[
|
||||
vim.api.nvim_create_user_command("Foo", function(opts)
|
||||
@ -4673,6 +4691,7 @@ describe('API', function()
|
||||
)
|
||||
)
|
||||
end)
|
||||
|
||||
it('splits arguments correctly', function()
|
||||
exec([[
|
||||
function! FooFunc(...)
|
||||
@ -4695,6 +4714,7 @@ describe('API', function()
|
||||
)
|
||||
)
|
||||
end)
|
||||
|
||||
it('splits arguments correctly for Lua callback', function()
|
||||
api.nvim_exec_lua(
|
||||
[[
|
||||
@ -4721,6 +4741,7 @@ describe('API', function()
|
||||
)
|
||||
)
|
||||
end)
|
||||
|
||||
it('works with buffer names', function()
|
||||
command('edit foo.txt | edit bar.txt')
|
||||
api.nvim_cmd({ cmd = 'buffer', args = { 'foo.txt' } }, {})
|
||||
@ -4728,6 +4749,7 @@ describe('API', function()
|
||||
api.nvim_cmd({ cmd = 'buffer', args = { 'bar.txt' } }, {})
|
||||
eq('bar.txt', fn.fnamemodify(api.nvim_buf_get_name(0), ':t'))
|
||||
end)
|
||||
|
||||
it('triggers CmdUndefined event if command is not found', function()
|
||||
api.nvim_exec_lua(
|
||||
[[
|
||||
@ -4742,13 +4764,16 @@ describe('API', function()
|
||||
)
|
||||
eq('foo', api.nvim_cmd({ cmd = 'Foo' }, { output = true }))
|
||||
end)
|
||||
|
||||
it('errors if command is not implemented', function()
|
||||
eq('Command not implemented: winpos', pcall_err(api.nvim_cmd, { cmd = 'winpos' }, {}))
|
||||
end)
|
||||
|
||||
it('works with empty arguments list', function()
|
||||
api.nvim_cmd({ cmd = 'update' }, {})
|
||||
api.nvim_cmd({ cmd = 'buffer', count = 0 }, {})
|
||||
end)
|
||||
|
||||
it("doesn't suppress errors when used in keymapping", function()
|
||||
api.nvim_exec_lua(
|
||||
[[
|
||||
@ -4760,6 +4785,7 @@ describe('API', function()
|
||||
feed('[l')
|
||||
neq(nil, string.find(eval('v:errmsg'), 'E5108:'))
|
||||
end)
|
||||
|
||||
it('handles 0 range #19608', function()
|
||||
api.nvim_buf_set_lines(0, 0, -1, false, { 'aa' })
|
||||
api.nvim_cmd({ cmd = 'delete', range = { 0 } }, {})
|
||||
@ -4767,12 +4793,14 @@ describe('API', function()
|
||||
eq({ 'aa' }, api.nvim_buf_get_lines(0, 0, 1, false))
|
||||
assert_alive()
|
||||
end)
|
||||
|
||||
it('supports filename expansion', function()
|
||||
api.nvim_cmd({ cmd = 'argadd', args = { '%:p:h:t', '%:p:h:t' } }, {})
|
||||
local arg = fn.expand('%:p:h:t')
|
||||
eq({ arg, arg }, fn.argv())
|
||||
end)
|
||||
it("'make' command works when argument count isn't 1 #19696", function()
|
||||
|
||||
it(":make command works when argument count isn't 1 #19696", function()
|
||||
command('set makeprg=echo')
|
||||
command('set shellquote=')
|
||||
matches('^:!echo ', api.nvim_cmd({ cmd = 'make' }, { output = true }))
|
||||
@ -4789,6 +4817,7 @@ describe('API', function()
|
||||
)
|
||||
assert_alive()
|
||||
end)
|
||||
|
||||
it("doesn't display messages when output=true", function()
|
||||
local screen = Screen.new(40, 6)
|
||||
screen:attach()
|
||||
@ -4817,31 +4846,37 @@ describe('API', function()
|
||||
]],
|
||||
}
|
||||
end)
|
||||
|
||||
it('works with non-String args', function()
|
||||
eq('2', api.nvim_cmd({ cmd = 'echo', args = { 2 } }, { output = true }))
|
||||
eq('1', api.nvim_cmd({ cmd = 'echo', args = { true } }, { output = true }))
|
||||
end)
|
||||
|
||||
describe('first argument as count', function()
|
||||
it('works', function()
|
||||
command('vsplit | enew')
|
||||
api.nvim_cmd({ cmd = 'bdelete', args = { api.nvim_get_current_buf() } }, {})
|
||||
eq(1, api.nvim_get_current_buf())
|
||||
end)
|
||||
|
||||
it('works with :sleep using milliseconds', function()
|
||||
local start = uv.now()
|
||||
api.nvim_cmd({ cmd = 'sleep', args = { '100m' } }, {})
|
||||
ok(uv.now() - start <= 300)
|
||||
end)
|
||||
end)
|
||||
|
||||
it(':call with unknown function does not crash #26289', function()
|
||||
eq(
|
||||
'Vim:E117: Unknown function: UnknownFunc',
|
||||
pcall_err(api.nvim_cmd, { cmd = 'call', args = { 'UnknownFunc()' } }, {})
|
||||
)
|
||||
end)
|
||||
|
||||
it(':throw does not crash #24556', function()
|
||||
eq('42', pcall_err(api.nvim_cmd, { cmd = 'throw', args = { '42' } }, {}))
|
||||
end)
|
||||
|
||||
it('can use :return #24556', function()
|
||||
exec([[
|
||||
func Foo()
|
||||
@ -4854,5 +4889,18 @@ describe('API', function()
|
||||
eq('before', api.nvim_get_var('pos'))
|
||||
eq({ 1, 2, 3 }, api.nvim_get_var('result'))
|
||||
end)
|
||||
|
||||
it('errors properly when command too recursive #27210', function()
|
||||
exec_lua([[
|
||||
_G.success = false
|
||||
vim.api.nvim_create_user_command('Test', function()
|
||||
vim.api.nvim_cmd({ cmd = 'Test' }, {})
|
||||
_G.success = true
|
||||
end, {})
|
||||
]])
|
||||
pcall_err(command, 'Test')
|
||||
assert_alive()
|
||||
eq(false, exec_lua('return _G.success'))
|
||||
end)
|
||||
end)
|
||||
end)
|
||||
|
@ -1,18 +1,20 @@
|
||||
local helpers = require('test.functional.helpers')(after_each)
|
||||
local Screen = require('test.functional.ui.screen')
|
||||
local clear, curbuf, curbuf_contents, curwin, eq, neq, ok, feed, insert, eval =
|
||||
local clear, curbuf, curbuf_contents, curwin, eq, neq, matches, ok, feed, insert, eval =
|
||||
helpers.clear,
|
||||
helpers.api.nvim_get_current_buf,
|
||||
helpers.curbuf_contents,
|
||||
helpers.api.nvim_get_current_win,
|
||||
helpers.eq,
|
||||
helpers.neq,
|
||||
helpers.matches,
|
||||
helpers.ok,
|
||||
helpers.feed,
|
||||
helpers.insert,
|
||||
helpers.eval
|
||||
local poke_eventloop = helpers.poke_eventloop
|
||||
local exec = helpers.exec
|
||||
local exec_lua = helpers.exec_lua
|
||||
local fn = helpers.fn
|
||||
local request = helpers.request
|
||||
local NIL = vim.NIL
|
||||
@ -51,7 +53,7 @@ describe('API/win', function()
|
||||
eq('Invalid window id: 23', pcall_err(api.nvim_win_set_buf, 23, api.nvim_get_current_buf()))
|
||||
end)
|
||||
|
||||
it('disallowed in cmdwin if win={old_}curwin or buf=curbuf', function()
|
||||
it('disallowed in cmdwin if win=cmdwin_{old_cur}win or buf=cmdwin_buf', function()
|
||||
local new_buf = api.nvim_create_buf(true, true)
|
||||
local old_win = api.nvim_get_current_win()
|
||||
local new_win = api.nvim_open_win(new_buf, false, {
|
||||
@ -74,6 +76,36 @@ describe('API/win', function()
|
||||
'E11: Invalid in command-line window; <CR> executes, CTRL-C quits',
|
||||
pcall_err(api.nvim_win_set_buf, new_win, 0)
|
||||
)
|
||||
matches(
|
||||
'E11: Invalid in command%-line window; <CR> executes, CTRL%-C quits$',
|
||||
pcall_err(
|
||||
exec_lua,
|
||||
[[
|
||||
local cmdwin_buf = vim.api.nvim_get_current_buf()
|
||||
local new_win, new_buf = ...
|
||||
vim.api.nvim_buf_call(new_buf, function()
|
||||
vim.api.nvim_win_set_buf(new_win, cmdwin_buf)
|
||||
end)
|
||||
]],
|
||||
new_win,
|
||||
new_buf
|
||||
)
|
||||
)
|
||||
matches(
|
||||
'E11: Invalid in command%-line window; <CR> executes, CTRL%-C quits$',
|
||||
pcall_err(
|
||||
exec_lua,
|
||||
[[
|
||||
local cmdwin_win = vim.api.nvim_get_current_win()
|
||||
local new_win, new_buf = ...
|
||||
vim.api.nvim_win_call(new_win, function()
|
||||
vim.api.nvim_win_set_buf(cmdwin_win, new_buf)
|
||||
end)
|
||||
]],
|
||||
new_win,
|
||||
new_buf
|
||||
)
|
||||
)
|
||||
|
||||
local next_buf = api.nvim_create_buf(true, true)
|
||||
api.nvim_win_set_buf(new_win, next_buf)
|
||||
@ -546,6 +578,7 @@ describe('API/win', function()
|
||||
it('in cmdline-window #9767', function()
|
||||
command('split')
|
||||
eq(2, #api.nvim_list_wins())
|
||||
local oldbuf = api.nvim_get_current_buf()
|
||||
local oldwin = api.nvim_get_current_win()
|
||||
local otherwin = api.nvim_open_win(0, false, {
|
||||
relative = 'editor',
|
||||
@ -570,6 +603,46 @@ describe('API/win', function()
|
||||
api.nvim_win_close(0, true)
|
||||
eq(2, #api.nvim_list_wins())
|
||||
eq('', fn.getcmdwintype())
|
||||
|
||||
-- Closing curwin in context of a different window shouldn't close cmdwin.
|
||||
otherwin = api.nvim_open_win(0, false, {
|
||||
relative = 'editor',
|
||||
row = 10,
|
||||
col = 10,
|
||||
width = 10,
|
||||
height = 10,
|
||||
})
|
||||
feed('q:')
|
||||
exec_lua(
|
||||
[[
|
||||
vim.api.nvim_win_call(..., function()
|
||||
vim.api.nvim_win_close(0, true)
|
||||
end)
|
||||
]],
|
||||
otherwin
|
||||
)
|
||||
eq(false, api.nvim_win_is_valid(otherwin))
|
||||
eq(':', fn.getcmdwintype())
|
||||
-- Closing cmdwin in context of a non-previous window is still OK.
|
||||
otherwin = api.nvim_open_win(oldbuf, false, {
|
||||
relative = 'editor',
|
||||
row = 10,
|
||||
col = 10,
|
||||
width = 10,
|
||||
height = 10,
|
||||
})
|
||||
exec_lua(
|
||||
[[
|
||||
local otherwin, cmdwin = ...
|
||||
vim.api.nvim_win_call(otherwin, function()
|
||||
vim.api.nvim_win_close(cmdwin, true)
|
||||
end)
|
||||
]],
|
||||
otherwin,
|
||||
api.nvim_get_current_win()
|
||||
)
|
||||
eq('', fn.getcmdwintype())
|
||||
eq(true, api.nvim_win_is_valid(otherwin))
|
||||
end)
|
||||
|
||||
it('closing current (float) window of another tabpage #15313', function()
|
||||
@ -646,6 +719,7 @@ describe('API/win', function()
|
||||
api.nvim_win_hide(0)
|
||||
eq('', fn.getcmdwintype())
|
||||
|
||||
local old_buf = api.nvim_get_current_buf()
|
||||
local old_win = api.nvim_get_current_win()
|
||||
local other_win = api.nvim_open_win(0, false, {
|
||||
relative = 'win',
|
||||
@ -663,6 +737,45 @@ describe('API/win', function()
|
||||
-- Can close other windows.
|
||||
api.nvim_win_hide(other_win)
|
||||
eq(false, api.nvim_win_is_valid(other_win))
|
||||
|
||||
-- Closing curwin in context of a different window shouldn't close cmdwin.
|
||||
other_win = api.nvim_open_win(old_buf, false, {
|
||||
relative = 'editor',
|
||||
row = 10,
|
||||
col = 10,
|
||||
width = 10,
|
||||
height = 10,
|
||||
})
|
||||
exec_lua(
|
||||
[[
|
||||
vim.api.nvim_win_call(..., function()
|
||||
vim.api.nvim_win_hide(0)
|
||||
end)
|
||||
]],
|
||||
other_win
|
||||
)
|
||||
eq(false, api.nvim_win_is_valid(other_win))
|
||||
eq(':', fn.getcmdwintype())
|
||||
-- Closing cmdwin in context of a non-previous window is still OK.
|
||||
other_win = api.nvim_open_win(old_buf, false, {
|
||||
relative = 'editor',
|
||||
row = 10,
|
||||
col = 10,
|
||||
width = 10,
|
||||
height = 10,
|
||||
})
|
||||
exec_lua(
|
||||
[[
|
||||
local otherwin, cmdwin = ...
|
||||
vim.api.nvim_win_call(otherwin, function()
|
||||
vim.api.nvim_win_hide(cmdwin)
|
||||
end)
|
||||
]],
|
||||
other_win,
|
||||
api.nvim_get_current_win()
|
||||
)
|
||||
eq('', fn.getcmdwintype())
|
||||
eq(true, api.nvim_win_is_valid(other_win))
|
||||
end)
|
||||
end)
|
||||
|
||||
@ -1055,7 +1168,7 @@ describe('API/win', function()
|
||||
eq(1, fn.exists('g:fired'))
|
||||
end)
|
||||
|
||||
it('disallowed in cmdwin if enter=true or buf=curbuf', function()
|
||||
it('disallowed in cmdwin if enter=true or buf=cmdwin_buf', function()
|
||||
local new_buf = api.nvim_create_buf(true, true)
|
||||
feed('q:')
|
||||
eq(
|
||||
@ -1078,6 +1191,20 @@ describe('API/win', function()
|
||||
height = 5,
|
||||
})
|
||||
)
|
||||
matches(
|
||||
'E11: Invalid in command%-line window; <CR> executes, CTRL%-C quits$',
|
||||
pcall_err(
|
||||
exec_lua,
|
||||
[[
|
||||
local cmdwin_buf = vim.api.nvim_get_current_buf()
|
||||
vim.api.nvim_buf_call(vim.api.nvim_create_buf(false, true), function()
|
||||
vim.api.nvim_open_win(cmdwin_buf, false, {
|
||||
relative='editor', row=5, col=5, width=5, height=5,
|
||||
})
|
||||
end)
|
||||
]]
|
||||
)
|
||||
)
|
||||
|
||||
eq(
|
||||
new_buf,
|
||||
|
@ -39,6 +39,23 @@ describe('WinResized', function()
|
||||
eq(2, eval('g:resized'))
|
||||
eq({ windows = { 1002, 1001, 1000 } }, eval('g:v_event'))
|
||||
end)
|
||||
|
||||
it('is triggered in terminal mode #21197 #27207', function()
|
||||
exec([[
|
||||
autocmd TermOpen * startinsert
|
||||
let g:resized = 0
|
||||
autocmd WinResized * let g:resized += 1
|
||||
]])
|
||||
eq(0, eval('g:resized'))
|
||||
|
||||
command('vsplit term://')
|
||||
eq({ mode = 't', blocking = false }, api.nvim_get_mode())
|
||||
eq(1, eval('g:resized'))
|
||||
|
||||
command('split')
|
||||
eq({ mode = 't', blocking = false }, api.nvim_get_mode())
|
||||
eq(2, eval('g:resized'))
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('WinScrolled', function()
|
||||
|
@ -1078,7 +1078,24 @@ describe('completion', function()
|
||||
]])
|
||||
end)
|
||||
|
||||
it('does not crash if text is changed by first call to complete function #17489', function()
|
||||
-- oldtest: Test_complete_changed_complete_info()
|
||||
it('no crash calling complete_info() in CompleteChanged', function()
|
||||
source([[
|
||||
set completeopt=menuone
|
||||
autocmd CompleteChanged * call complete_info(['items'])
|
||||
call feedkeys("iii\<cr>\<c-p>")
|
||||
]])
|
||||
screen:expect([[
|
||||
ii |
|
||||
ii^ |
|
||||
{2:ii }{0: }|
|
||||
{0:~ }|*4
|
||||
{3:-- Keyword completion (^N^P) The only match} |
|
||||
]])
|
||||
assert_alive()
|
||||
end)
|
||||
|
||||
it('no crash if text changed by first call to complete function #17489', function()
|
||||
source([[
|
||||
func Complete(findstart, base) abort
|
||||
if a:findstart
|
||||
@ -1097,7 +1114,7 @@ describe('completion', function()
|
||||
assert_alive()
|
||||
end)
|
||||
|
||||
it('does not crash when using i_CTRL-X_CTRL-V to complete non-existent colorscheme', function()
|
||||
it('no crash using i_CTRL-X_CTRL-V to complete non-existent colorscheme', function()
|
||||
feed('icolorscheme NOSUCHCOLORSCHEME<C-X><C-V>')
|
||||
expect('colorscheme NOSUCHCOLORSCHEME')
|
||||
assert_alive()
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user