mirror of
https://github.com/neovim/neovim
synced 2025-07-23 14:51:52 +00:00
Compare commits
175 Commits
Author | SHA1 | Date | |
---|---|---|---|
b2684d9f66 | |||
7da0c46e1b | |||
91ef8606f2 | |||
89959ab9dc | |||
adf31505d8 | |||
f9f0345eba | |||
6f8efea940 | |||
388b559848 | |||
c97ad3cb41 | |||
2ddb5d21bb | |||
6889f9168b | |||
2d3a4154c5 | |||
87ba1d7465 | |||
0ab089add4 | |||
2d13ae0dd4 | |||
730a5e0599 | |||
85c9014c09 | |||
282f9fb816 | |||
d1214da08f | |||
f0f163b267 | |||
2df746e4e8 | |||
b9dbdfef0e | |||
0f81af53b0 | |||
a80bdf0d9b | |||
37fb09c162 | |||
e732cbe36c | |||
2d3517012a | |||
41ceefe804 | |||
7b2119dbd9 | |||
ef68eae09a | |||
43804477ca | |||
bfcf541a9e | |||
28531d18f0 | |||
d5cbc99358 | |||
db3b856779 | |||
e6eb910496 | |||
7286e514f2 | |||
ae05e0399b | |||
4621527f59 | |||
638bc951b2 | |||
0613faf596 | |||
203d4f916d | |||
68d204462c | |||
70b4e7948f | |||
ee06d0e64d | |||
1976ca68b5 | |||
4303337c77 | |||
ecf5164d2d | |||
6396bfb29f | |||
ea8db9003b | |||
ff8acfffd2 | |||
9ffa94b07b | |||
1077374380 | |||
3d5be364bc | |||
ce292026ea | |||
742ea00742 | |||
a34b8e42df | |||
77eb278adf | |||
d0a24ea03e | |||
ec84c8df0e | |||
c4a760c734 | |||
902c946bcd | |||
0f1cada0f7 | |||
c5bc0289ed | |||
d28ad6e03f | |||
b0ced63e43 | |||
0eec4a8ecc | |||
36c6f488e4 | |||
5d0766ddce | |||
718b3ffe74 | |||
7184230e94 | |||
d9b9514e8e | |||
dfeec113be | |||
8183eb32e1 | |||
8d3b7b57c8 | |||
c0201909c7 | |||
a03057560a | |||
95e5c9f33e | |||
07d9197840 | |||
c13eba5254 | |||
d32a4dd4b0 | |||
7ef602d470 | |||
9d8c5119e2 | |||
f7b1b0595d | |||
25a869a097 | |||
243c15ea83 | |||
33cec55a26 | |||
e0ddf93bb0 | |||
aa6136f956 | |||
222b3d5021 | |||
0d66963089 | |||
f2c4305114 | |||
d519b77d2b | |||
d9c10ea753 | |||
1eb33f7d00 | |||
92dc936ca7 | |||
68677eb477 | |||
f4a79230c8 | |||
a73904168a | |||
58460e2d52 | |||
3a0d37681f | |||
4cb2b19197 | |||
d1ca551983 | |||
5e0ef6afc7 | |||
cefc91a82e | |||
334d8f506f | |||
ff83c712cf | |||
b07bffdc47 | |||
b868257ef9 | |||
e304677993 | |||
4e5af2f5a6 | |||
917f496f75 | |||
a242902430 | |||
12ae7aa846 | |||
27abf5c81b | |||
d50f71d2f1 | |||
f623fad9c4 | |||
3e83a33108 | |||
0c2bf55e90 | |||
6b140ae899 | |||
1921dda92e | |||
30fa1c5f8c | |||
6417ba0c2f | |||
3c102303f5 | |||
034d3c8f6c | |||
9965cfb84c | |||
bdd8498ed7 | |||
8daffd0cbb | |||
fd8e0ae62d | |||
a56dcbbad7 | |||
6a87b57c06 | |||
5c6ee251a6 | |||
0db89468d7 | |||
dc87a0d80a | |||
c753e70abb | |||
0ed06d7271 | |||
e512c9589e | |||
47686a1454 | |||
3b3cf1d7ef | |||
472d41b5b6 | |||
216c56b7e0 | |||
968947b3c3 | |||
9b3426691c | |||
4e43264cd3 | |||
3a4d3934c4 | |||
2b2a3449f7 | |||
6b69b3217b | |||
cf73f21c07 | |||
e5e69f758d | |||
901eeeb2e6 | |||
6563c6bde7 | |||
465c181581 | |||
710d561f88 | |||
81233a41d7 | |||
c4b9bdbdf4 | |||
560c6ca947 | |||
4b6caa913c | |||
0fbc78caa1 | |||
533ec6d492 | |||
9dfb429e93 | |||
051e14d347 | |||
714622fb45 | |||
4296511087 | |||
f9c7a69cec | |||
fa292e6f61 | |||
bc66a5ff6f | |||
f25f6c8d13 | |||
ad7211ac8f | |||
95ee908c40 | |||
d68d212ad4 | |||
3273c595c0 | |||
3db39ed21f | |||
f184c562c5 | |||
32842b0ee3 | |||
4f0e828190 |
2
.github/workflows/notes.md
vendored
2
.github/workflows/notes.md
vendored
@ -75,5 +75,3 @@ If your system does not have the [required glibc version](https://neovim.io/doc/
|
||||
### Other
|
||||
|
||||
- Install by [package manager](https://github.com/neovim/neovim/blob/master/INSTALL.md#install-from-package)
|
||||
|
||||
## SHA256 Checksums
|
||||
|
18
.github/workflows/release.yml
vendored
18
.github/workflows/release.yml
vendored
@ -132,7 +132,7 @@ jobs:
|
||||
|
||||
windows:
|
||||
needs: setup
|
||||
runs-on: windows-2019
|
||||
runs-on: windows-2022
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
@ -193,25 +193,13 @@ jobs:
|
||||
echo 'PRERELEASE=') >> $GITHUB_ENV
|
||||
gh release delete stable --yes || true
|
||||
git push origin :stable || true
|
||||
# `sha256sum` outputs <sha> <path>, so we cd into each dir to drop the
|
||||
# containing folder from the output.
|
||||
- run: |
|
||||
for i in nvim-*; do
|
||||
(
|
||||
cd $i || exit
|
||||
sha256sum * >> $GITHUB_WORKSPACE/shasum.txt
|
||||
)
|
||||
done
|
||||
- name: Publish release
|
||||
env:
|
||||
NVIM_VERSION: ${{ needs.linux.outputs.version }}
|
||||
DEBUG: api
|
||||
run: |
|
||||
envsubst < "$GITHUB_WORKSPACE/.github/workflows/notes.md" > "$RUNNER_TEMP/notes.md"
|
||||
echo '```' >> "$RUNNER_TEMP/notes.md"
|
||||
cat shasum.txt >> "$RUNNER_TEMP/notes.md"
|
||||
echo '```' >> "$RUNNER_TEMP/notes.md"
|
||||
if [ "$TAG_NAME" != "nightly" ]; then
|
||||
gh release create stable $PRERELEASE --notes-file "$RUNNER_TEMP/notes.md" --title "$SUBJECT" --target $GITHUB_SHA nvim-macos-x86_64/* nvim-macos-arm64/* nvim-linux-x86_64/* nvim-linux-arm64/* nvim-appimage-x86_64/* nvim-appimage-arm64/* nvim-win64/* shasum.txt
|
||||
gh release create stable $PRERELEASE --notes-file "$RUNNER_TEMP/notes.md" --title "$SUBJECT" --target $GITHUB_SHA nvim-macos-x86_64/* nvim-macos-arm64/* nvim-linux-x86_64/* nvim-linux-arm64/* nvim-appimage-x86_64/* nvim-appimage-arm64/* nvim-win64/*
|
||||
fi
|
||||
gh release create $TAG_NAME $PRERELEASE --notes-file "$RUNNER_TEMP/notes.md" --title "$SUBJECT" --target $GITHUB_SHA nvim-macos-x86_64/* nvim-macos-arm64/* nvim-linux-x86_64/* nvim-linux-arm64/* nvim-appimage-x86_64/* nvim-appimage-arm64/* nvim-win64/* shasum.txt
|
||||
gh release create $TAG_NAME $PRERELEASE --notes-file "$RUNNER_TEMP/notes.md" --title "$SUBJECT" --target $GITHUB_SHA nvim-macos-x86_64/* nvim-macos-arm64/* nvim-linux-x86_64/* nvim-linux-arm64/* nvim-appimage-x86_64/* nvim-appimage-arm64/* nvim-win64/*
|
||||
|
23
BUILD.md
23
BUILD.md
@ -259,6 +259,29 @@ cmake --build build
|
||||
- Using `ninja` is strongly recommended.
|
||||
4. If treesitter parsers are not bundled, they need to be available in a `parser/` runtime directory (e.g. `/usr/share/nvim/runtime/parser/`).
|
||||
|
||||
### How to build static binary (on Linux)
|
||||
|
||||
1. Use a linux distribution which uses musl C. We will use Alpine Linux but any distro with musl should work. (glibc does not support static linking)
|
||||
2. Run make passing the `STATIC_BUILD` variable: `make CMAKE_EXTRA_FLAGS="-DSTATIC_BUILD=1"`
|
||||
|
||||
In case you are not using Alpine Linux you can use a container to do the build the binary:
|
||||
|
||||
```bash
|
||||
podman run \
|
||||
--rm \
|
||||
-it \
|
||||
-v "$PWD:/workdir" \
|
||||
-w /workdir \
|
||||
alpine:latest \
|
||||
bash -c 'apk add build-base cmake coreutils curl gettext-tiny-dev && make CMAKE_EXTRA_FLAGS="-DSTATIC_BUILD=1"'
|
||||
```
|
||||
|
||||
The resulting binary in `build/bin/nvim` will have all the dependencies statically linked:
|
||||
|
||||
```
|
||||
build/bin/nvim: ELF 64-bit LSB executable, ARM aarch64, version 1 (SYSV), statically linked, BuildID[sha1]=b93fa8e678d508ac0a76a2e3da20b119105f1b2d, with debug_info, not stripped
|
||||
```
|
||||
|
||||
#### Debian 10 (Buster) example:
|
||||
|
||||
```sh
|
||||
|
@ -141,7 +141,7 @@ endif()
|
||||
# version string, else they are combined with the result of `git describe`.
|
||||
set(NVIM_VERSION_MAJOR 0)
|
||||
set(NVIM_VERSION_MINOR 11)
|
||||
set(NVIM_VERSION_PATCH 1)
|
||||
set(NVIM_VERSION_PATCH 3)
|
||||
set(NVIM_VERSION_PRERELEASE "") # for package maintainers
|
||||
|
||||
# API level
|
||||
|
@ -273,7 +273,7 @@ If you need to modify or debug the documentation flow, these are the main files:
|
||||
runtime/lua/vim/* => runtime/doc/lua.txt
|
||||
runtime/lua/vim/lsp/ => runtime/doc/lsp.txt
|
||||
src/nvim/api/* => runtime/doc/api.txt
|
||||
src/nvim/eval.lua => runtime/doc/builtin.txt
|
||||
src/nvim/eval.lua => runtime/doc/vimfn.txt
|
||||
src/nvim/options.lua => runtime/doc/options.txt
|
||||
```
|
||||
|
||||
|
@ -7,5 +7,6 @@ ExternalProject_Add(wasmtime
|
||||
-D WASMTIME_FASTEST_RUNTIME=ON # build with full LTO
|
||||
-D WASMTIME_DISABLE_ALL_FEATURES=ON # don't need all that crap...
|
||||
-D WASMTIME_FEATURE_CRANELIFT=ON # ...except this one (compiles wasm to platform code)
|
||||
-D WASMTIME_FEATURE_GC_DRC=ON # ...and this one (needed by ts to create engines)
|
||||
USES_TERMINAL_BUILD TRUE
|
||||
${EXTERNALPROJECT_OPTIONS})
|
||||
|
@ -34,20 +34,20 @@ LIBICONV_SHA256 8f74213b56238c85a50a5329f77e06198771e70dd9a739779f4c02f65d971313
|
||||
UTF8PROC_URL https://github.com/JuliaStrings/utf8proc/archive/v2.10.0.tar.gz
|
||||
UTF8PROC_SHA256 6f4f1b639daa6dca9f80bc5db1233e9cbaa31a67790887106160b33ef743f136
|
||||
|
||||
TREESITTER_C_URL https://github.com/tree-sitter/tree-sitter-c/archive/v0.23.4.tar.gz
|
||||
TREESITTER_C_SHA256 b66c5043e26d84e5f17a059af71b157bcf202221069ed220aa1696d7d1d28a7a
|
||||
TREESITTER_LUA_URL https://github.com/tree-sitter-grammars/tree-sitter-lua/archive/v0.3.0.tar.gz
|
||||
TREESITTER_LUA_SHA256 a34cc70abfd8d2d4b0fabf01403ea05f848e1a4bc37d8a4bfea7164657b35d31
|
||||
TREESITTER_VIM_URL https://github.com/tree-sitter-grammars/tree-sitter-vim/archive/v0.5.0.tar.gz
|
||||
TREESITTER_VIM_SHA256 90019d12d2da0751c027124f27f5335babf069a050457adaed53693b5e9cf10a
|
||||
TREESITTER_VIMDOC_URL https://github.com/neovim/tree-sitter-vimdoc/archive/v3.0.1.tar.gz
|
||||
TREESITTER_VIMDOC_SHA256 76b65e5bee9ff78eb21256619b1995aac4d80f252c19e1c710a4839481ded09e
|
||||
TREESITTER_QUERY_URL https://github.com/tree-sitter-grammars/tree-sitter-query/archive/v0.5.1.tar.gz
|
||||
TREESITTER_QUERY_SHA256 fe8c712880a529d454347cd4c58336ac2db22243bae5055bdb5844fb3ea56192
|
||||
TREESITTER_MARKDOWN_URL https://github.com/tree-sitter-grammars/tree-sitter-markdown/archive/v0.4.1.tar.gz
|
||||
TREESITTER_MARKDOWN_SHA256 e0fdb2dca1eb3063940122e1475c9c2b069062a638c95939e374c5427eddee9f
|
||||
TREESITTER_URL https://github.com/tree-sitter/tree-sitter/archive/v0.25.3.tar.gz
|
||||
TREESITTER_SHA256 862fac52653bc7bc9d2cd0630483e6bdf3d02bcd23da956ca32663c4798a93e3
|
||||
TREESITTER_C_URL https://github.com/tree-sitter/tree-sitter-c/archive/v0.24.1.tar.gz
|
||||
TREESITTER_C_SHA256 25dd4bb3dec770769a407e0fc803f424ce02c494a56ce95fedc525316dcf9b48
|
||||
TREESITTER_LUA_URL https://github.com/tree-sitter-grammars/tree-sitter-lua/archive/v0.4.0.tar.gz
|
||||
TREESITTER_LUA_SHA256 b0977aced4a63bb75f26725787e047b8f5f4a092712c840ea7070765d4049559
|
||||
TREESITTER_VIM_URL https://github.com/tree-sitter-grammars/tree-sitter-vim/archive/v0.7.0.tar.gz
|
||||
TREESITTER_VIM_SHA256 44eabc31127c4feacda19f2a05a5788272128ff561ce01093a8b7a53aadcc7b2
|
||||
TREESITTER_VIMDOC_URL https://github.com/neovim/tree-sitter-vimdoc/archive/v4.0.0.tar.gz
|
||||
TREESITTER_VIMDOC_SHA256 8096794c0f090b2d74b7bff94548ac1be3285b929ec74f839bd9b3ff4f4c6a0b
|
||||
TREESITTER_QUERY_URL https://github.com/tree-sitter-grammars/tree-sitter-query/archive/v0.6.2.tar.gz
|
||||
TREESITTER_QUERY_SHA256 90682e128d048fbf2a2a17edca947db71e326fa0b3dba4136e041e096538b4eb
|
||||
TREESITTER_MARKDOWN_URL https://github.com/tree-sitter-grammars/tree-sitter-markdown/archive/v0.5.0.tar.gz
|
||||
TREESITTER_MARKDOWN_SHA256 14c2c948ccf0e9b606eec39b09286c59dddf28307849f71b7ce2b1d1ef06937e
|
||||
TREESITTER_URL https://github.com/tree-sitter/tree-sitter/archive/v0.25.6.tar.gz
|
||||
TREESITTER_SHA256 ac6ed919c6d849e8553e246d5cd3fa22661f6c7b6497299264af433f3629957c
|
||||
|
||||
WASMTIME_URL https://github.com/bytecodealliance/wasmtime/archive/v29.0.1.tar.gz
|
||||
WASMTIME_SHA256 b94b6c6fd6aebaf05d4c69c1b12b5dc217b0d42c1a95f435b33af63dddfa5304
|
||||
|
@ -268,13 +268,11 @@ function! provider#clipboard#Executable() abort
|
||||
endfunction
|
||||
|
||||
function! s:clipboard.get(reg) abort
|
||||
if type(s:paste[a:reg]) == v:t_func
|
||||
return s:paste[a:reg]()
|
||||
elseif s:selections[a:reg].owner > 0
|
||||
if s:selections[a:reg].owner > 0
|
||||
return s:selections[a:reg].data
|
||||
end
|
||||
|
||||
let clipboard_data = s:try_cmd(s:paste[a:reg])
|
||||
let clipboard_data = type(s:paste[a:reg]) == v:t_func ? s:paste[a:reg]() : s:try_cmd(s:paste[a:reg])
|
||||
if match(&clipboard, '\v(unnamed|unnamedplus)') >= 0
|
||||
\ && type(clipboard_data) == v:t_list
|
||||
\ && get(s:selections[a:reg].data, 0, []) ==# clipboard_data
|
||||
@ -294,13 +292,12 @@ function! s:clipboard.set(lines, regtype, reg) abort
|
||||
return 0
|
||||
end
|
||||
|
||||
if type(s:copy[a:reg]) == v:t_func
|
||||
call s:copy[a:reg](a:lines, a:regtype)
|
||||
return 0
|
||||
end
|
||||
|
||||
if s:cache_enabled == 0
|
||||
call s:try_cmd(s:copy[a:reg], a:lines)
|
||||
if s:cache_enabled == 0 || type(s:copy[a:reg]) == v:t_func
|
||||
if type(s:copy[a:reg]) == v:t_func
|
||||
call s:copy[a:reg](a:lines, a:regtype)
|
||||
else
|
||||
call s:try_cmd(s:copy[a:reg], a:lines)
|
||||
endif
|
||||
"Cache it anyway we can compare it later to get regtype of the yank
|
||||
let s:selections[a:reg] = copy(s:selection)
|
||||
let s:selections[a:reg].data = [a:lines, a:regtype]
|
||||
|
@ -120,6 +120,8 @@ endfunction
|
||||
" Tutor Cmd: {{{1
|
||||
|
||||
function! s:Locale()
|
||||
" Make sure l:lang exists before returning.
|
||||
let l:lang = 'en_US'
|
||||
if exists('v:lang') && v:lang =~ '\a\a'
|
||||
let l:lang = v:lang
|
||||
elseif $LC_ALL =~ '\a\a'
|
||||
@ -132,8 +134,6 @@ function! s:Locale()
|
||||
endif
|
||||
elseif $LANG =~ '\a\a'
|
||||
let l:lang = $LANG
|
||||
else
|
||||
let l:lang = 'en_US'
|
||||
endif
|
||||
return split(l:lang, '_')
|
||||
endfunction
|
||||
@ -167,15 +167,21 @@ function! s:Sort(a, b)
|
||||
return retval
|
||||
endfunction
|
||||
|
||||
function! s:GlobTutorials(name)
|
||||
" returns a list of all tutor files matching the given name
|
||||
function! tutor#GlobTutorials(name, locale)
|
||||
let locale = a:locale
|
||||
" pack/*/start/* are not reported in &rtp
|
||||
let rtp = nvim_list_runtime_paths()
|
||||
\ ->map({_, v -> escape(v:lua.vim.fs.normalize(v), ',')})
|
||||
\ ->join(',')
|
||||
" search for tutorials:
|
||||
" 1. non-localized
|
||||
let l:tutors = s:GlobPath(&rtp, 'tutor/'.a:name.'.tutor')
|
||||
let l:tutors = s:GlobPath(rtp, 'tutor/'.a:name.'.tutor')
|
||||
" 2. localized for current locale
|
||||
let l:locale_tutors = s:GlobPath(&rtp, 'tutor/'.s:Locale()[0].'/'.a:name.'.tutor')
|
||||
let l:locale_tutors = s:GlobPath(rtp, 'tutor/'.locale.'/'.a:name.'.tutor')
|
||||
" 3. fallback to 'en'
|
||||
if len(l:locale_tutors) == 0
|
||||
let l:locale_tutors = s:GlobPath(&rtp, 'tutor/en/'.a:name.'.tutor')
|
||||
let l:locale_tutors = s:GlobPath(rtp, 'tutor/en/'.a:name.'.tutor')
|
||||
endif
|
||||
call extend(l:tutors, l:locale_tutors)
|
||||
return uniq(sort(l:tutors, 's:Sort'), 's:Sort')
|
||||
@ -197,7 +203,7 @@ function! tutor#TutorCmd(tutor_name)
|
||||
let l:tutor_name = fnamemodify(l:tutor_name, ':r')
|
||||
endif
|
||||
|
||||
let l:tutors = s:GlobTutorials(l:tutor_name)
|
||||
let l:tutors = tutor#GlobTutorials(l:tutor_name, s:Locale()[0])
|
||||
|
||||
if len(l:tutors) == 0
|
||||
echom "No tutorial with that name found"
|
||||
@ -220,15 +226,37 @@ function! tutor#TutorCmd(tutor_name)
|
||||
|
||||
call tutor#SetupVim()
|
||||
exe "edit ".l:to_open
|
||||
call tutor#EnableInteractive(v:true)
|
||||
call tutor#ApplyTransform()
|
||||
endfunction
|
||||
|
||||
function! tutor#TutorCmdComplete(lead,line,pos)
|
||||
let l:tutors = s:GlobTutorials('*')
|
||||
let l:tutors = tutor#GlobTutorials('*', s:Locale()[0])
|
||||
let l:names = uniq(sort(map(l:tutors, 'fnamemodify(v:val, ":t:r")'), 's:Sort'))
|
||||
return join(l:names, "\n")
|
||||
endfunction
|
||||
|
||||
" Enables/disables interactive mode.
|
||||
function! tutor#EnableInteractive(enable)
|
||||
let enable = a:enable
|
||||
if enable
|
||||
setlocal buftype=nofile
|
||||
setlocal concealcursor+=inv
|
||||
setlocal conceallevel=2
|
||||
call tutor#ApplyMarks()
|
||||
augroup tutor_interactive
|
||||
autocmd! TextChanged,TextChangedI <buffer> call tutor#ApplyMarksOnChanged()
|
||||
augroup END
|
||||
else
|
||||
setlocal buftype<
|
||||
setlocal concealcursor<
|
||||
setlocal conceallevel<
|
||||
if exists('#tutor_interactive')
|
||||
autocmd! tutor_interactive * <buffer>
|
||||
endif
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! tutor#ApplyTransform()
|
||||
if has('win32')
|
||||
sil! %s/{unix:(\(.\{-}\)),win:(\(.\{-}\))}/\2/g
|
||||
|
@ -1183,10 +1183,7 @@ nvim_open_term({buffer}, {opts}) *nvim_open_term()*
|
||||
ANSI termcodes, so you can use Nvim as a "scrollback pager" (for terminals
|
||||
like kitty): *ansi-colorize* *terminal-scrollback-pager* >lua
|
||||
vim.api.nvim_create_user_command('TermHl', function()
|
||||
local b = vim.api.nvim_create_buf(false, true)
|
||||
local chan = vim.api.nvim_open_term(b, {})
|
||||
vim.api.nvim_chan_send(chan, table.concat(vim.api.nvim_buf_get_lines(0, 0, -1, false), '\n'))
|
||||
vim.api.nvim_win_set_buf(0, b)
|
||||
vim.api.nvim_open_term(0, {})
|
||||
end, { desc = 'Highlights ANSI termcodes in curbuf' })
|
||||
<
|
||||
|
||||
|
@ -311,7 +311,7 @@ Nvim's filetype detection behavior matches Vim, but is implemented as part of
|
||||
|vim.filetype| (see `$VIMRUNTIME/lua/vim/filetype.lua`). The logic is encoded in
|
||||
three tables, listed in order of precedence (the first match is returned):
|
||||
1. `filename` for literal full path or basename lookup;
|
||||
2. `pattern` for matching filenames or paths against |lua-patterns|, optimized
|
||||
2. `pattern` for matching filenames or paths against |lua-pattern|s, optimized
|
||||
for fast lookup;
|
||||
3. `extension` for literal extension lookup.
|
||||
|
||||
|
@ -441,6 +441,7 @@ Use existing common {verb} names (actions) if possible:
|
||||
- get: Gets things. Two variants (overloads):
|
||||
1. `get<T>(id: int): T` returns one item.
|
||||
2. `get<T>(filter: dict): T[]` returns a list.
|
||||
- has: Checks for the presence of an item, feature, etc.
|
||||
- inspect: Presents a high-level, often interactive, view
|
||||
- is_enabled: Checks if functionality is enabled.
|
||||
- open: Opens something (a buffer, window, …)
|
||||
@ -452,6 +453,7 @@ Use existing common {verb} names (actions) if possible:
|
||||
- try_{verb}: Best-effort operation, failure returns null or error obj
|
||||
|
||||
Do NOT use these deprecated verbs:
|
||||
- contains: Prefer "has".
|
||||
- disable: Prefer `enable(enable: boolean)`.
|
||||
- exit: Prefer "cancel" (or "stop" if appropriate).
|
||||
- is_disabled: Prefer `is_enabled()`.
|
||||
|
@ -69,6 +69,16 @@ Functions that take a severity as an optional parameter (e.g.
|
||||
<
|
||||
This form allows users to filter for specific severities
|
||||
|
||||
==============================================================================
|
||||
DEFAULTS *diagnostic-defaults*
|
||||
|
||||
These diagnostic keymaps are created unconditionally when Nvim starts:
|
||||
- `]d` jumps to the next diagnostic in the buffer. |]d-default|
|
||||
- `[d` jumps to the previous diagnostic in the buffer. |[d-default|
|
||||
- `]D` jumps to the last diagnostic in the buffer. |]D-default|
|
||||
- `[D` jumps to the first diagnostic in the buffer. |[D-default|
|
||||
- `<C-w>d` shows diagnostic at cursor in a floating window. |CTRL-W_d-default|
|
||||
|
||||
==============================================================================
|
||||
HANDLERS *diagnostic-handlers*
|
||||
|
||||
@ -269,6 +279,26 @@ DiagnosticVirtualTextHint
|
||||
DiagnosticVirtualTextOk
|
||||
Used for "Ok" diagnostic virtual text.
|
||||
|
||||
*hl-DiagnosticVirtualLinesError*
|
||||
DiagnosticVirtualLinesError
|
||||
Used for "Error" diagnostic virtual lines.
|
||||
|
||||
*hl-DiagnosticVirtualLinesWarn*
|
||||
DiagnosticVirtualLinesWarn
|
||||
Used for "Warn" diagnostic virtual lines.
|
||||
|
||||
*hl-DiagnosticVirtualLinesInfo*
|
||||
DiagnosticVirtualLinesInfo
|
||||
Used for "Info" diagnostic virtual lines.
|
||||
|
||||
*hl-DiagnosticVirtualLinesHint*
|
||||
DiagnosticVirtualLinesHint
|
||||
Used for "Hint" diagnostic virtual lines.
|
||||
|
||||
*hl-DiagnosticVirtualLinesOk*
|
||||
DiagnosticVirtualLinesOk
|
||||
Used for "Ok" diagnostic virtual lines.
|
||||
|
||||
*hl-DiagnosticUnderlineError*
|
||||
DiagnosticUnderlineError
|
||||
Used to underline "Error" diagnostics.
|
||||
|
@ -714,11 +714,14 @@ list of the current window.
|
||||
omitted the current entry is used.
|
||||
Also see |++opt| and |+cmd|.
|
||||
|
||||
:[count]n[ext] [++opt] [+cmd] *:n* *:ne* *:next* *]a* *E165* *E163*
|
||||
:[count]n[ext] [++opt] [+cmd] *:n* *:ne* *:next* *E165* *E163*
|
||||
Edit [count] next file. This fails when changes have
|
||||
been made and Vim does not want to |abandon| the
|
||||
current buffer. Also see |++opt| and |+cmd|.
|
||||
|
||||
*]a*
|
||||
]a Mapped to |:next|. |default-mappings|
|
||||
|
||||
:[count]n[ext]! [++opt] [+cmd]
|
||||
Edit [count] next file, discard any changes to the
|
||||
buffer. Also see |++opt| and |+cmd|.
|
||||
@ -740,16 +743,22 @@ list of the current window.
|
||||
any changes to the buffer. Also see |++opt| and
|
||||
|+cmd|.
|
||||
|
||||
:[count]prev[ious] [count] [++opt] [+cmd] *:prev* *:previous* *[a*
|
||||
:[count]prev[ious] [count] [++opt] [+cmd] *:prev* *:previous*
|
||||
Same as :Next. Also see |++opt| and |+cmd|.
|
||||
|
||||
*:rew* *:rewind* *[A*
|
||||
*[a*
|
||||
[a Mapped to |:previous|. |default-mappings|
|
||||
|
||||
*:rew* *:rewind*
|
||||
:rew[ind] [++opt] [+cmd]
|
||||
Start editing the first file in the argument list.
|
||||
This fails when changes have been made and Vim does
|
||||
not want to |abandon| the current buffer.
|
||||
Also see |++opt| and |+cmd|.
|
||||
|
||||
*[A*
|
||||
[A Mapped to |:rewind|. |default-mappings|
|
||||
|
||||
:rew[ind]! [++opt] [+cmd]
|
||||
Start editing the first file in the argument list.
|
||||
Discard any changes to the buffer. Also see |++opt|
|
||||
@ -759,13 +768,16 @@ list of the current window.
|
||||
:fir[st][!] [++opt] [+cmd]
|
||||
Other name for ":rewind".
|
||||
|
||||
*:la* *:last* *]A*
|
||||
*:la* *:last*
|
||||
:la[st] [++opt] [+cmd]
|
||||
Start editing the last file in the argument list.
|
||||
This fails when changes have been made and Vim does
|
||||
not want to |abandon| the current buffer.
|
||||
Also see |++opt| and |+cmd|.
|
||||
|
||||
*]A*
|
||||
]A Mapped to |:last|. |default-mappings|
|
||||
|
||||
:la[st]! [++opt] [+cmd]
|
||||
Start editing the last file in the argument list.
|
||||
Discard any changes to the buffer. Also see |++opt|
|
||||
|
@ -9,18 +9,18 @@
|
||||
==============================================================================
|
||||
Checkhealth *vim.health* *health*
|
||||
|
||||
|
||||
vim.health is a minimal framework to help users troubleshoot configuration and
|
||||
any other environment conditions that a plugin might care about. Nvim ships
|
||||
with healthchecks for configuration, performance, python support, ruby
|
||||
support, clipboard support, and more.
|
||||
|
||||
To run all healthchecks, use: >vim
|
||||
|
||||
:checkhealth
|
||||
:checkhealth
|
||||
<
|
||||
|
||||
Plugin authors are encouraged to write new healthchecks. |health-dev|
|
||||
|
||||
|
||||
COMMANDS *health-commands*
|
||||
|
||||
*:che* *:checkhealth*
|
||||
@ -56,7 +56,6 @@ Local mappings in the healthcheck buffer:
|
||||
q Closes the window.
|
||||
|
||||
Global configuration:
|
||||
|
||||
*g:health*
|
||||
g:health Dictionary with the following optional keys:
|
||||
- `style` (`'float'|nil`) Set to "float" to display :checkhealth in
|
||||
@ -65,16 +64,26 @@ g:health Dictionary with the following optional keys:
|
||||
Example: >lua
|
||||
vim.g.health = { style = 'float' }
|
||||
|
||||
|
||||
Local configuration:
|
||||
|
||||
Checkhealth sets its buffer filetype to "checkhealth". You can customize the
|
||||
buffer by handling the |FileType| event. For example if you don't want emojis
|
||||
in the health report: >vim
|
||||
autocmd FileType checkhealth :set modifiable | silent! %s/\v( ?[^\x00-\x7F])//g
|
||||
<
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
Create a healthcheck *health-dev*
|
||||
|
||||
Healthchecks are functions that check the user environment, configuration, or
|
||||
any other prerequisites that a plugin cares about. Nvim ships with
|
||||
healthchecks in:
|
||||
- $VIMRUNTIME/autoload/health/
|
||||
- $VIMRUNTIME/lua/vim/lsp/health.lua
|
||||
- $VIMRUNTIME/lua/vim/treesitter/health.lua
|
||||
- and more...
|
||||
• $VIMRUNTIME/autoload/health/
|
||||
• $VIMRUNTIME/lua/vim/lsp/health.lua
|
||||
• $VIMRUNTIME/lua/vim/treesitter/health.lua
|
||||
• and more...
|
||||
|
||||
To add a new healthcheck for your own plugin, simply create a "health.lua"
|
||||
module on 'runtimepath' that returns a table with a "check()" function. Then
|
||||
@ -82,35 +91,35 @@ module on 'runtimepath' that returns a table with a "check()" function. Then
|
||||
|
||||
For example if your plugin is named "foo", define your healthcheck module at
|
||||
one of these locations (on 'runtimepath'):
|
||||
- lua/foo/health/init.lua
|
||||
- lua/foo/health.lua
|
||||
• lua/foo/health/init.lua
|
||||
• lua/foo/health.lua
|
||||
|
||||
If your plugin also provides a submodule named "bar" for which you want
|
||||
a separate healthcheck, define the healthcheck at one of these locations:
|
||||
- lua/foo/bar/health/init.lua
|
||||
- lua/foo/bar/health.lua
|
||||
If your plugin also provides a submodule named "bar" for which you want a
|
||||
separate healthcheck, define the healthcheck at one of these locations:
|
||||
• lua/foo/bar/health/init.lua
|
||||
• lua/foo/bar/health.lua
|
||||
|
||||
All such health modules must return a Lua table containing a `check()`
|
||||
function.
|
||||
|
||||
Copy this sample code into `lua/foo/health.lua`, replacing "foo" in the path
|
||||
with your plugin name: >lua
|
||||
local M = {}
|
||||
|
||||
local M = {}
|
||||
M.check = function()
|
||||
vim.health.start("foo report")
|
||||
-- make sure setup function parameters are ok
|
||||
if check_setup() then
|
||||
vim.health.ok("Setup is correct")
|
||||
else
|
||||
vim.health.error("Setup is incorrect")
|
||||
end
|
||||
-- do some more checking
|
||||
-- ...
|
||||
end
|
||||
|
||||
M.check = function()
|
||||
vim.health.start("foo report")
|
||||
-- make sure setup function parameters are ok
|
||||
if check_setup() then
|
||||
vim.health.ok("Setup is correct")
|
||||
else
|
||||
vim.health.error("Setup is incorrect")
|
||||
end
|
||||
-- do some more checking
|
||||
-- ...
|
||||
end
|
||||
|
||||
return M
|
||||
return M
|
||||
<
|
||||
|
||||
|
||||
error({msg}, {...}) *vim.health.error()*
|
||||
|
@ -1923,7 +1923,7 @@ These commands are used to start inserting text. You can end insert mode with
|
||||
<Esc>. See |mode-ins-repl| for the other special characters in Insert mode.
|
||||
The effect of [count] takes place after Insert mode is exited.
|
||||
|
||||
The following commands insert text, but stay in normal mode:
|
||||
The following |default-mappings| insert text, but stay in normal mode:
|
||||
|
||||
*]<Space>*
|
||||
]<Space> Insert an empty line below the cursor without leaving
|
||||
|
@ -28,38 +28,42 @@ Follow these steps to get LSP features:
|
||||
upstream installation instructions. You can find language servers here:
|
||||
https://microsoft.github.io/language-server-protocol/implementors/servers/
|
||||
|
||||
2. Use |vim.lsp.config()| to define a configuration for an LSP client.
|
||||
Example: >lua
|
||||
vim.lsp.config['luals'] = {
|
||||
-- Command and arguments to start the server.
|
||||
cmd = { 'lua-language-server' },
|
||||
2. Use |vim.lsp.config()| to define a configuration for an LSP client
|
||||
(see https://github.com/neovim/nvim-lspconfig for examples).
|
||||
Example: >lua
|
||||
vim.lsp.config['luals'] = {
|
||||
-- Command and arguments to start the server.
|
||||
cmd = { 'lua-language-server' },
|
||||
|
||||
-- Filetypes to automatically attach to.
|
||||
filetypes = { 'lua' },
|
||||
-- Filetypes to automatically attach to.
|
||||
filetypes = { 'lua' },
|
||||
|
||||
-- Sets the "root directory" to the parent directory of the file in the
|
||||
-- current buffer that contains either a ".luarc.json" or a
|
||||
-- ".luarc.jsonc" file. Files that share a root directory will reuse
|
||||
-- the connection to the same LSP server.
|
||||
root_markers = { '.luarc.json', '.luarc.jsonc' },
|
||||
-- Sets the "root directory" to the parent directory of the file in the
|
||||
-- current buffer that contains either a ".luarc.json" or a
|
||||
-- ".luarc.jsonc" file. Files that share a root directory will reuse
|
||||
-- the connection to the same LSP server.
|
||||
-- Nested lists indicate equal priority, see |vim.lsp.Config|.
|
||||
root_markers = { { '.luarc.json', '.luarc.jsonc' }, '.git' },
|
||||
|
||||
-- Specific settings to send to the server. The schema for this is
|
||||
-- defined by the server. For example the schema for lua-language-server
|
||||
-- can be found here https://raw.githubusercontent.com/LuaLS/vscode-lua/master/setting/schema.json
|
||||
settings = {
|
||||
Lua = {
|
||||
runtime = {
|
||||
version = 'LuaJIT',
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
-- Specific settings to send to the server. The schema for this is
|
||||
-- defined by the server. For example the schema for lua-language-server
|
||||
-- can be found here https://raw.githubusercontent.com/LuaLS/vscode-lua/master/setting/schema.json
|
||||
settings = {
|
||||
Lua = {
|
||||
runtime = {
|
||||
version = 'LuaJIT',
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
<
|
||||
3. Use |vim.lsp.enable()| to enable a configuration.
|
||||
Example: >lua
|
||||
vim.lsp.enable('luals')
|
||||
<
|
||||
4. Restart Nvim, or use ":edit" to reload the buffer.
|
||||
4. Open a code file matching one of the `filetypes` specified in the config.
|
||||
Note: Depending on the LSP server, you may need to ensure your project has
|
||||
a |lsp-root_markers| file so the workspace can be recognized.
|
||||
|
||||
5. Check that LSP is active ("attached") for the buffer: >vim
|
||||
:checkhealth vim.lsp
|
||||
@ -76,6 +80,18 @@ listed below, if (1) the language server supports the functionality and (2)
|
||||
the options are empty or were set by the builtin runtime (ftplugin) files. The
|
||||
options are not restored when the LSP client is stopped or detached.
|
||||
|
||||
GLOBAL DEFAULTS
|
||||
*grr* *gra* *grn* *gri* *grt* *i_CTRL-S*
|
||||
These GLOBAL keymaps are created unconditionally when Nvim starts:
|
||||
- "grn" is mapped in Normal mode to |vim.lsp.buf.rename()|
|
||||
- "gra" is mapped in Normal and Visual mode to |vim.lsp.buf.code_action()|
|
||||
- "grr" is mapped in Normal mode to |vim.lsp.buf.references()|
|
||||
- "gri" is mapped in Normal mode to |vim.lsp.buf.implementation()|
|
||||
- "grt" is mapped in Normal mode to |vim.lsp.buf.type_definition()|
|
||||
- "gO" is mapped in Normal mode to |vim.lsp.buf.document_symbol()|
|
||||
- CTRL-S is mapped in Insert mode to |vim.lsp.buf.signature_help()|
|
||||
|
||||
BUFFER-LOCAL DEFAULTS
|
||||
- 'omnifunc' is set to |vim.lsp.omnifunc()|, use |i_CTRL-X_CTRL-O| to trigger
|
||||
completion.
|
||||
- 'tagfunc' is set to |vim.lsp.tagfunc()|. This enables features like
|
||||
@ -87,21 +103,11 @@ options are not restored when the LSP client is stopped or detached.
|
||||
- |K| is mapped to |vim.lsp.buf.hover()| unless |'keywordprg'| is customized or
|
||||
a custom keymap for `K` exists.
|
||||
|
||||
*grr* *gra* *grn* *gri* *i_CTRL-S*
|
||||
Some keymaps are created unconditionally when Nvim starts:
|
||||
- "grn" is mapped in Normal mode to |vim.lsp.buf.rename()|
|
||||
- "gra" is mapped in Normal and Visual mode to |vim.lsp.buf.code_action()|
|
||||
- "grr" is mapped in Normal mode to |vim.lsp.buf.references()|
|
||||
- "gri" is mapped in Normal mode to |vim.lsp.buf.implementation()|
|
||||
- "gO" is mapped in Normal mode to |vim.lsp.buf.document_symbol()|
|
||||
- CTRL-S is mapped in Insert mode to |vim.lsp.buf.signature_help()|
|
||||
DISABLING DEFAULTS *lsp-defaults-disable*
|
||||
You can remove GLOBAL keymaps at any time using |vim.keymap.del()| or
|
||||
|:unmap|. See also |gr-default|.
|
||||
|
||||
If not wanted, these keymaps can be removed at any time using
|
||||
|vim.keymap.del()| or |:unmap| (see also |gr-default|).
|
||||
|
||||
*lsp-defaults-disable*
|
||||
To override or delete any of the above defaults, set or unset the options on
|
||||
|LspAttach|: >lua
|
||||
To remove or override BUFFER-LOCAL defaults, define a |LspAttach| handler: >lua
|
||||
|
||||
vim.api.nvim_create_autocmd('LspAttach', {
|
||||
callback = function(args)
|
||||
@ -251,7 +257,7 @@ FAQ *lsp-faq*
|
||||
autocmd BufWritePre *.rs lua vim.lsp.buf.format({ async = false })
|
||||
<
|
||||
*lsp-vs-treesitter*
|
||||
- Q: How do LSP and Treesitter compare?
|
||||
- Q: How do LSP, Treesitter and Ctags compare?
|
||||
- A: LSP requires a client and language server. The language server uses
|
||||
semantic analysis to understand code at a project level. This provides
|
||||
language servers with the ability to rename across files, find
|
||||
@ -263,6 +269,11 @@ FAQ *lsp-faq*
|
||||
like syntax highlighting, simple goto-definitions, scope analysis and
|
||||
more.
|
||||
|
||||
A |ctags|-like program can generate a |tags| file that allows Nvim to
|
||||
jump to definitions, provide simple completions via |i_CTRL-X_CTRL-]|
|
||||
command. It is not as featureful and doesn't have semantic understanding,
|
||||
but it is fast, lightweight and useful for navigating polyglot projects.
|
||||
|
||||
================================================================================
|
||||
LSP API *lsp-api*
|
||||
|
||||
@ -286,38 +297,33 @@ They are also listed below.
|
||||
|
||||
- `'callHierarchy/incomingCalls'`
|
||||
- `'callHierarchy/outgoingCalls'`
|
||||
- `'textDocument/codeAction'`
|
||||
- `'client/registerCapability'`
|
||||
- `'client/unregisterCapability'`
|
||||
- `'signature_help'`
|
||||
- `'textDocument/codeLens'`
|
||||
- `'textDocument/completion'`
|
||||
- `'textDocument/declaration'`
|
||||
- `'textDocument/definition'`
|
||||
- `'textDocument/diagnostic'`
|
||||
- `'textDocument/documentHighlight'`
|
||||
- `'textDocument/documentSymbol'`
|
||||
- `'textDocument/foldingRange'`
|
||||
- `'textDocument/formatting'`
|
||||
- `'textDocument/hover'`
|
||||
- `'textDocument/implementation'`
|
||||
- `'textDocument/inlayHint'`
|
||||
- `'textDocument/prepareTypeHierarchy'`
|
||||
- `'textDocument/publishDiagnostics'`
|
||||
- `'textDocument/rangeFormatting'`
|
||||
- `'textDocument/rangesFormatting'`
|
||||
- `'textDocument/references'`
|
||||
- `'textDocument/rename'`
|
||||
- `'textDocument/semanticTokens/full'`
|
||||
- `'textDocument/semanticTokens/full/delta'`
|
||||
- `'textDocument/signatureHelp'`
|
||||
- `'textDocument/typeDefinition*'`
|
||||
- `'typeHierarchy/subtypes'`
|
||||
- `'typeHierarchy/supertypes'`
|
||||
- `'window/logMessage'`
|
||||
- `'window/showMessage'`
|
||||
- `'window/showDocument'`
|
||||
- `'window/showMessage'`
|
||||
- `'window/showMessageRequest'`
|
||||
- `'window/workDoneProgress/create'`
|
||||
- `'workspace/applyEdit'`
|
||||
- `'workspace/configuration'`
|
||||
- `'workspace/executeCommand'`
|
||||
- `'workspace/inlayHint/refresh'`
|
||||
- `'workspace/semanticTokens/refresh'`
|
||||
- `'workspace/symbol'`
|
||||
- `'workspace/workspaceFolders'`
|
||||
|
||||
@ -552,10 +558,19 @@ LspAttach *LspAttach*
|
||||
|autocmd-pattern| is the buffer name. The client ID is passed in the
|
||||
Lua handler |event-data| argument.
|
||||
|
||||
Example: >lua
|
||||
vim.api.nvim_create_autocmd('LspAttach', {
|
||||
callback = function(ev)
|
||||
local client = vim.lsp.get_client_by_id(ev.data.client_id)
|
||||
-- ...
|
||||
end
|
||||
})
|
||||
<
|
||||
Note: If the LSP server performs dynamic registration, capabilities may be
|
||||
registered any time _after_ LspAttach. In that case you may want to handle
|
||||
the "registerCapability" event. Example: >lua
|
||||
the "registerCapability" event.
|
||||
|
||||
Example: >lua
|
||||
vim.lsp.handlers['client/registerCapability'] = (function(overridden)
|
||||
return function(err, res, ctx)
|
||||
local result = overridden(err, res, ctx)
|
||||
@ -563,8 +578,10 @@ LspAttach *LspAttach*
|
||||
if not client then
|
||||
return
|
||||
end
|
||||
-- Call your custom on_attach logic...
|
||||
-- my_on_attach(client, vim.api.nvim_get_current_buf())
|
||||
for bufnr, _ in pairs(client.attached_buffers) do
|
||||
-- Call your custom on_attach logic...
|
||||
-- my_on_attach(client, bufnr)
|
||||
end
|
||||
return result
|
||||
end
|
||||
end)(vim.lsp.handlers['client/registerCapability'])
|
||||
@ -572,8 +589,9 @@ LspAttach *LspAttach*
|
||||
LspDetach *LspDetach*
|
||||
Just before an LSP client detaches from a buffer. The |autocmd-pattern| is
|
||||
the buffer name. The client ID is passed in the Lua handler |event-data|
|
||||
argument. Example: >lua
|
||||
argument.
|
||||
|
||||
Example: >lua
|
||||
vim.api.nvim_create_autocmd('LspDetach', {
|
||||
callback = function(args)
|
||||
-- Get the detaching client
|
||||
@ -595,8 +613,9 @@ LspNotify *LspNotify*
|
||||
LSP server.
|
||||
|
||||
The client_id, LSP method, and parameters are sent in the Lua handler
|
||||
|event-data| table argument. Example: >lua
|
||||
|event-data| table argument.
|
||||
|
||||
Example: >lua
|
||||
vim.api.nvim_create_autocmd('LspNotify', {
|
||||
callback = function(args)
|
||||
local bufnr = args.buf
|
||||
@ -642,8 +661,9 @@ LspRequest *LspRequest*
|
||||
The Lua handler |event-data| argument has the client ID, request ID, and
|
||||
request (described at |vim.lsp.Client|, {requests} field). If the request
|
||||
type is `complete`, the request will be deleted from the client's pending
|
||||
requests table after processing the event handlers. Example: >lua
|
||||
requests table after processing the event handlers.
|
||||
|
||||
Example: >lua
|
||||
vim.api.nvim_create_autocmd('LspRequest', {
|
||||
callback = function(args)
|
||||
local bufnr = args.buf
|
||||
@ -670,8 +690,9 @@ LspTokenUpdate *LspTokenUpdate*
|
||||
when an existing token becomes visible for the first time. The
|
||||
|autocmd-pattern| is the buffer name. The Lua handler |event-data|
|
||||
argument has the client ID and token (see
|
||||
|vim.lsp.semantic_tokens.get_at_pos()|). Example: >lua
|
||||
|vim.lsp.semantic_tokens.get_at_pos()|).
|
||||
|
||||
Example: >lua
|
||||
vim.api.nvim_create_autocmd('LspTokenUpdate', {
|
||||
callback = function(args)
|
||||
local token = args.data.token
|
||||
@ -694,28 +715,52 @@ Lua module: vim.lsp *lsp-core*
|
||||
|
||||
|
||||
Fields: ~
|
||||
• {cmd}? (`string[]|fun(dispatchers: vim.lsp.rpc.Dispatchers): vim.lsp.rpc.PublicClient`)
|
||||
See `cmd` in |vim.lsp.ClientConfig|.
|
||||
• {cmd}? (`string[]|fun(dispatchers: vim.lsp.rpc.Dispatchers, config: vim.lsp.ClientConfig): vim.lsp.rpc.PublicClient`)
|
||||
See `cmd` in |vim.lsp.ClientConfig|. See also
|
||||
`reuse_client` to dynamically decide (per-buffer)
|
||||
when `cmd` should be re-invoked.
|
||||
• {filetypes}? (`string[]`) Filetypes the client will attach to, if
|
||||
activated by `vim.lsp.enable()`. If not provided,
|
||||
then the client will attach to all filetypes.
|
||||
• {root_markers}? (`string[]`) Directory markers (.e.g. '.git/') where
|
||||
the LSP server will base its workspaceFolders,
|
||||
rootUri, and rootPath on initialization. Unused if
|
||||
`root_dir` is provided.
|
||||
• {root_dir}? (`string|fun(bufnr: integer, cb:fun(root_dir?:string))`)
|
||||
Directory where the LSP server will base its
|
||||
workspaceFolders, rootUri, and rootPath on
|
||||
initialization. If a function, it is passed the
|
||||
buffer number and a callback argument which must be
|
||||
called with the value of root_dir to use. The LSP
|
||||
server will not be started until the callback is
|
||||
called.
|
||||
activated by `vim.lsp.enable()`. If not provided, the
|
||||
client will attach to all filetypes.
|
||||
• {reuse_client}? (`fun(client: vim.lsp.Client, config: vim.lsp.ClientConfig): boolean`)
|
||||
Predicate used to decide if a client should be
|
||||
Predicate which decides if a client should be
|
||||
re-used. Used on all running clients. The default
|
||||
implementation re-uses a client if name and root_dir
|
||||
matches.
|
||||
• {root_dir}? (`string|fun(bufnr: integer, on_dir:fun(root_dir?:string))`)
|
||||
*lsp-root_dir()* Decides the workspace root: the
|
||||
directory where the LSP server will base its
|
||||
workspaceFolders, rootUri, and rootPath on
|
||||
initialization. The function form must call the
|
||||
`on_dir` callback to provide the root dir, or LSP
|
||||
will not be activated for the buffer. Thus a
|
||||
`root_dir()` function can dynamically decide
|
||||
per-buffer whether to activate (or skip) LSP. See
|
||||
example at |vim.lsp.enable()|.
|
||||
• {root_markers}? (`(string|string[])[]`) *lsp-root_markers*
|
||||
Filename(s) (".git/", "package.json", …) used to
|
||||
decide the workspace root. Unused if `root_dir` is
|
||||
defined. The list order decides priority. To indicate
|
||||
"equal priority", specify names in a nested list
|
||||
`{ { 'a.txt', 'b.lua' }, ... }`.
|
||||
|
||||
For each item, Nvim will search upwards (from the
|
||||
buffer file) for that marker, or list of markers;
|
||||
search stops at the first directory containing that
|
||||
marker, and the directory is used as the root dir
|
||||
(workspace folder).
|
||||
|
||||
Example: Find the first ancestor directory containing
|
||||
file or directory "stylua.toml"; if not found, find
|
||||
the first ancestor containing ".git": >lua
|
||||
root_markers = { 'stylua.toml', '.git' }
|
||||
<
|
||||
|
||||
Example: Find the first ancestor directory containing
|
||||
EITHER "stylua.toml" or ".luarc.json"; if not found,
|
||||
find the first ancestor containing ".git": >lua
|
||||
root_markers = { { 'stylua.toml', '.luarc.json' }, '.git' }
|
||||
<
|
||||
|
||||
|
||||
buf_attach_client({bufnr}, {client_id}) *vim.lsp.buf_attach_client()*
|
||||
@ -871,19 +916,36 @@ config({name}, {cfg}) *vim.lsp.config()*
|
||||
• {cfg} (`vim.lsp.Config`) See |vim.lsp.Config|.
|
||||
|
||||
enable({name}, {enable}) *vim.lsp.enable()*
|
||||
Enable an LSP server to automatically start when opening a buffer.
|
||||
|
||||
Uses configuration defined with `vim.lsp.config`.
|
||||
Auto-starts LSP when a buffer is opened, based on the |lsp-config|
|
||||
`filetypes`, `root_markers`, and `root_dir` fields.
|
||||
|
||||
Examples: >lua
|
||||
vim.lsp.enable('clangd')
|
||||
vim.lsp.enable('clangd')
|
||||
vim.lsp.enable({'luals', 'pyright'})
|
||||
<
|
||||
|
||||
vim.lsp.enable({'luals', 'pyright'})
|
||||
Example: *lsp-restart* Passing `false` stops and detaches the client(s).
|
||||
Thus you can "restart" LSP by disabling and re-enabling a given config: >lua
|
||||
vim.lsp.enable('clangd', false)
|
||||
vim.lsp.enable('clangd', true)
|
||||
<
|
||||
|
||||
Example: To dynamically decide whether LSP is activated, define a
|
||||
|lsp-root_dir()| function which calls `on_dir()` only when you want that
|
||||
config to activate: >lua
|
||||
vim.lsp.config('lua_ls', {
|
||||
root_dir = function(bufnr, on_dir)
|
||||
if not vim.fn.bufname(bufnr):match('%.txt$') then
|
||||
on_dir(vim.fn.getcwd())
|
||||
end
|
||||
end
|
||||
})
|
||||
<
|
||||
|
||||
Parameters: ~
|
||||
• {name} (`string|string[]`) Name(s) of client(s) to enable.
|
||||
• {enable} (`boolean?`) `true|nil` to enable, `false` to disable.
|
||||
• {enable} (`boolean?`) `true|nil` to enable, `false` to disable
|
||||
(actively stops and detaches clients as needed)
|
||||
|
||||
foldclose({kind}, {winid}) *vim.lsp.foldclose()*
|
||||
Close all {kind} of folds in the the window with {winid}.
|
||||
@ -993,6 +1055,18 @@ get_log_path() *vim.lsp.get_log_path()*
|
||||
Return: ~
|
||||
(`string`) path to log file
|
||||
|
||||
is_enabled({name}) *vim.lsp.is_enabled()*
|
||||
Checks if the given LSP config is enabled (globally, not per-buffer).
|
||||
|
||||
Unlike `vim.lsp.config['…']`, this does not have the side-effect of
|
||||
resolving the config.
|
||||
|
||||
Parameters: ~
|
||||
• {name} (`string`) Config name
|
||||
|
||||
Return: ~
|
||||
(`boolean`)
|
||||
|
||||
omnifunc({findstart}, {base}) *vim.lsp.omnifunc()*
|
||||
Implements 'omnifunc' compatible LSP completion.
|
||||
|
||||
@ -1128,65 +1202,17 @@ Lua module: vim.lsp.client *lsp-client*
|
||||
*vim.lsp.Client*
|
||||
|
||||
Fields: ~
|
||||
• {id} (`integer`) The id allocated to the client.
|
||||
• {name} (`string`) If a name is specified on creation,
|
||||
that will be used. Otherwise it is just the
|
||||
client id. This is used for logs and messages.
|
||||
• {rpc} (`vim.lsp.rpc.PublicClient`) RPC client
|
||||
object, for low level interaction with the
|
||||
client. See |vim.lsp.rpc.start()|.
|
||||
• {offset_encoding} (`string`) Called "position encoding" in LSP
|
||||
spec, the encoding used for communicating with
|
||||
the server. You can modify this in the
|
||||
`config`'s `on_init` method before text is
|
||||
sent to the server.
|
||||
• {handlers} (`table<string,lsp.Handler>`) The handlers
|
||||
used by the client as described in
|
||||
|lsp-handler|.
|
||||
• {requests} (`table<integer,{ type: string, bufnr: integer, method: string}?>`)
|
||||
The current pending requests in flight to the
|
||||
server. Entries are key-value pairs with the
|
||||
key being the request id while the value is a
|
||||
table with `type`, `bufnr`, and `method`
|
||||
key-value pairs. `type` is either "pending"
|
||||
for an active request, or "cancel" for a
|
||||
cancel request. It will be "complete"
|
||||
ephemerally while executing |LspRequest|
|
||||
autocmds when replies are received from the
|
||||
server.
|
||||
• {config} (`vim.lsp.ClientConfig`) copy of the table
|
||||
that was passed by the user to
|
||||
|vim.lsp.start()|. See |vim.lsp.ClientConfig|.
|
||||
• {server_capabilities} (`lsp.ServerCapabilities?`) Response from the
|
||||
server sent on `initialize` describing the
|
||||
server's capabilities.
|
||||
• {server_info} (`lsp.ServerInfo?`) Response from the server
|
||||
sent on `initialize` describing information
|
||||
about the server.
|
||||
• {progress} (`vim.lsp.Client.Progress`) A ring buffer
|
||||
(|vim.ringbuf()|) containing progress messages
|
||||
sent by the server. See
|
||||
|vim.lsp.Client.Progress|.
|
||||
• {initialized} (`true?`)
|
||||
• {workspace_folders} (`lsp.WorkspaceFolder[]?`) The workspace
|
||||
folders configured in the client when the
|
||||
server starts. This property is only available
|
||||
if the client supports workspace folders. It
|
||||
can be `null` if the client supports workspace
|
||||
folders but none are configured.
|
||||
• {root_dir} (`string?`)
|
||||
• {attached_buffers} (`table<integer,true>`)
|
||||
• {capabilities} (`lsp.ClientCapabilities`) Capabilities
|
||||
provided by the client (editor or tool), at
|
||||
startup.
|
||||
• {commands} (`table<string,fun(command: lsp.Command, ctx: table)>`)
|
||||
Table of command name to function which is
|
||||
called if any LSP action (code action, code
|
||||
lenses, ...) triggers the command. Client
|
||||
commands take precedence over the global
|
||||
command registry.
|
||||
• {settings} (`lsp.LSPObject`) Map with language server
|
||||
specific settings. These are returned to the
|
||||
language server if requested via
|
||||
`workspace/configuration`. Keys are
|
||||
case-sensitive.
|
||||
Client commands. See |vim.lsp.ClientConfig|.
|
||||
• {config} (`vim.lsp.ClientConfig`) Copy of the config
|
||||
passed to |vim.lsp.start()|. See
|
||||
|vim.lsp.ClientConfig|.
|
||||
• {dynamic_capabilities} (`lsp.DynamicCapabilities`) Capabilities
|
||||
provided at runtime (after startup).
|
||||
• {flags} (`table`) A table with flags for the client.
|
||||
The current (experimental) flags are:
|
||||
• {allow_incremental_sync}? (`boolean`,
|
||||
@ -1203,9 +1229,41 @@ Lua module: vim.lsp.client *lsp-client*
|
||||
false, nvim exits immediately after sending
|
||||
the "shutdown" request to the server.
|
||||
• {get_language_id} (`fun(bufnr: integer, filetype: string): string`)
|
||||
• {capabilities} (`lsp.ClientCapabilities`) The capabilities
|
||||
provided by the client (editor or tool)
|
||||
• {dynamic_capabilities} (`lsp.DynamicCapabilities`)
|
||||
See |vim.lsp.ClientConfig|.
|
||||
• {handlers} (`table<string,lsp.Handler>`) See
|
||||
|vim.lsp.ClientConfig|.
|
||||
• {id} (`integer`) The id allocated to the client.
|
||||
• {initialized} (`true?`)
|
||||
• {name} (`string`) See |vim.lsp.ClientConfig|.
|
||||
• {offset_encoding} (`string`) See |vim.lsp.ClientConfig|.
|
||||
• {progress} (`vim.lsp.Client.Progress`) A ring buffer
|
||||
(|vim.ringbuf()|) containing progress messages
|
||||
sent by the server. See
|
||||
|vim.lsp.Client.Progress|.
|
||||
• {requests} (`table<integer,{ type: string, bufnr: integer, method: string}?>`)
|
||||
The current pending requests in flight to the
|
||||
server. Entries are key-value pairs with the
|
||||
key being the request id while the value is a
|
||||
table with `type`, `bufnr`, and `method`
|
||||
key-value pairs. `type` is either "pending"
|
||||
for an active request, or "cancel" for a
|
||||
cancel request. It will be "complete"
|
||||
ephemerally while executing |LspRequest|
|
||||
autocmds when replies are received from the
|
||||
server.
|
||||
• {root_dir} (`string?`) See |vim.lsp.ClientConfig|.
|
||||
• {rpc} (`vim.lsp.rpc.PublicClient`) RPC client
|
||||
object, for low level interaction with the
|
||||
client. See |vim.lsp.rpc.start()|.
|
||||
• {server_capabilities} (`lsp.ServerCapabilities?`) Response from the
|
||||
server sent on `initialize` describing the
|
||||
server's capabilities.
|
||||
• {server_info} (`lsp.ServerInfo?`) Response from the server
|
||||
sent on `initialize` describing server
|
||||
information (e.g. version).
|
||||
• {settings} (`lsp.LSPObject`) See |vim.lsp.ClientConfig|.
|
||||
• {workspace_folders} (`lsp.WorkspaceFolder[]?`) See
|
||||
|vim.lsp.ClientConfig|.
|
||||
• {request} (`fun(self: vim.lsp.Client, method: string, params: table?, handler: lsp.Handler?, bufnr: integer?): boolean, integer?`)
|
||||
See |Client:request()|.
|
||||
• {request_sync} (`fun(self: vim.lsp.Client, method: string, params: table, timeout_ms: integer?, bufnr: integer?): {err: lsp.ResponseError?, result:any}?, string?`)
|
||||
@ -1235,40 +1293,13 @@ Lua module: vim.lsp.client *lsp-client*
|
||||
*vim.lsp.ClientConfig*
|
||||
|
||||
Fields: ~
|
||||
• {cmd} (`string[]|fun(dispatchers: vim.lsp.rpc.Dispatchers): vim.lsp.rpc.PublicClient`)
|
||||
command string[] that launches the language
|
||||
server (treated as in |jobstart()|, must be
|
||||
absolute or on `$PATH`, shell constructs like
|
||||
"~" are not expanded), or function that creates
|
||||
an RPC client. Function receives a
|
||||
`dispatchers` table and returns a table with
|
||||
member functions `request`, `notify`,
|
||||
`is_closing` and `terminate`. See
|
||||
|vim.lsp.rpc.request()|,
|
||||
|vim.lsp.rpc.notify()|. For TCP there is a
|
||||
builtin RPC client factory:
|
||||
|vim.lsp.rpc.connect()|
|
||||
• {cmd_cwd}? (`string`, default: cwd) Directory to launch
|
||||
the `cmd` process. Not related to `root_dir`.
|
||||
• {cmd_env}? (`table`) Environment flags to pass to the LSP
|
||||
on spawn. Must be specified using a table.
|
||||
Non-string values are coerced to string.
|
||||
Example: >lua
|
||||
{ PORT = 8080; HOST = "0.0.0.0"; }
|
||||
<
|
||||
• {detached}? (`boolean`, default: true) Daemonize the server
|
||||
process so that it runs in a separate process
|
||||
group from Nvim. Nvim will shutdown the process
|
||||
on exit, but if Nvim fails to exit cleanly this
|
||||
could leave behind orphaned server processes.
|
||||
• {workspace_folders}? (`lsp.WorkspaceFolder[]`) List of workspace
|
||||
folders passed to the language server. For
|
||||
backwards compatibility rootUri and rootPath
|
||||
will be derived from the first workspace folder
|
||||
in this list. See `workspaceFolders` in the LSP
|
||||
spec.
|
||||
• {workspace_required}? (`boolean`) (default false) Server requires a
|
||||
workspace (no "single file" support).
|
||||
• {before_init}? (`fun(params: lsp.InitializeParams, config: vim.lsp.ClientConfig)`)
|
||||
Callback invoked before the LSP "initialize"
|
||||
phase, where `params` contains the parameters
|
||||
being sent to the server and `config` is the
|
||||
config that was passed to |vim.lsp.start()|.
|
||||
You can use this to modify parameters before
|
||||
they are sent.
|
||||
• {capabilities}? (`lsp.ClientCapabilities`) Map overriding the
|
||||
default capabilities defined by
|
||||
|vim.lsp.protocol.make_client_capabilities()|,
|
||||
@ -1279,68 +1310,40 @@ Lua module: vim.lsp.client *lsp-client*
|
||||
• Note: To send an empty dictionary use
|
||||
|vim.empty_dict()|, else it will be encoded
|
||||
as an array.
|
||||
• {handlers}? (`table<string,function>`) Map of language
|
||||
server method names to |lsp-handler|
|
||||
• {settings}? (`lsp.LSPObject`) Map with language server
|
||||
specific settings. See the {settings} in
|
||||
|vim.lsp.Client|.
|
||||
• {cmd} (`string[]|fun(dispatchers: vim.lsp.rpc.Dispatchers, config: vim.lsp.ClientConfig): vim.lsp.rpc.PublicClient`)
|
||||
Command `string[]` that launches the language
|
||||
server (treated as in |jobstart()|, must be
|
||||
absolute or on `$PATH`, shell constructs like
|
||||
"~" are not expanded), or function that creates
|
||||
an RPC client. Function receives a
|
||||
`dispatchers` table and the resolved `config`,
|
||||
and must return a table with member functions
|
||||
`request`, `notify`, `is_closing` and
|
||||
`terminate`. See |vim.lsp.rpc.request()|,
|
||||
|vim.lsp.rpc.notify()|. For TCP there is a
|
||||
builtin RPC client factory:
|
||||
|vim.lsp.rpc.connect()|
|
||||
• {cmd_cwd}? (`string`, default: cwd) Directory to launch
|
||||
the `cmd` process. Not related to `root_dir`.
|
||||
• {cmd_env}? (`table`) Environment variables passed to the
|
||||
LSP process on spawn. Non-string values are
|
||||
coerced to string. Example: >lua
|
||||
{ PORT = 8080; HOST = '0.0.0.0'; }
|
||||
<
|
||||
• {commands}? (`table<string,fun(command: lsp.Command, ctx: table)>`)
|
||||
Table that maps string of clientside commands
|
||||
to user-defined functions. Commands passed to
|
||||
Client commands. Map of command names to
|
||||
user-defined functions. Commands passed to
|
||||
`start()` take precedence over the global
|
||||
command registry. Each key must be a unique
|
||||
command name, and the value is a function which
|
||||
is called if any LSP action (code action, code
|
||||
lenses, ...) triggers the command.
|
||||
• {init_options}? (`lsp.LSPObject`) Values to pass in the
|
||||
initialization request as
|
||||
`initializationOptions`. See `initialize` in
|
||||
the LSP spec.
|
||||
• {name}? (`string`, default: client-id) Name in log
|
||||
messages.
|
||||
• {get_language_id}? (`fun(bufnr: integer, filetype: string): string`)
|
||||
Language ID as string. Defaults to the buffer
|
||||
filetype.
|
||||
• {offset_encoding}? (`'utf-8'|'utf-16'|'utf-32'`) Called "position
|
||||
encoding" in LSP spec, the encoding that the
|
||||
LSP server expects. Client does not verify this
|
||||
is correct.
|
||||
• {on_error}? (`fun(code: integer, err: string)`) Callback
|
||||
invoked when the client operation throws an
|
||||
error. `code` is a number describing the error.
|
||||
Other arguments may be passed depending on the
|
||||
error kind. See `vim.lsp.rpc.client_errors` for
|
||||
possible errors. Use
|
||||
`vim.lsp.rpc.client_errors[code]` to get
|
||||
human-friendly name.
|
||||
• {before_init}? (`fun(params: lsp.InitializeParams, config: vim.lsp.ClientConfig)`)
|
||||
Callback invoked before the LSP "initialize"
|
||||
phase, where `params` contains the parameters
|
||||
being sent to the server and `config` is the
|
||||
config that was passed to |vim.lsp.start()|.
|
||||
You can use this to modify parameters before
|
||||
they are sent.
|
||||
• {on_init}? (`elem_or_list<fun(client: vim.lsp.Client, init_result: lsp.InitializeResult)>`)
|
||||
Callback invoked after LSP "initialize", where
|
||||
`result` is a table of `capabilities` and
|
||||
anything else the server may send. For example,
|
||||
clangd sends `init_result.offsetEncoding` if
|
||||
`capabilities.offsetEncoding` was sent to it.
|
||||
You can only modify the
|
||||
`client.offset_encoding` here before any
|
||||
notifications are sent.
|
||||
• {on_exit}? (`elem_or_list<fun(code: integer, signal: integer, client_id: integer)>`)
|
||||
Callback invoked on client exit.
|
||||
• code: exit code of the process
|
||||
• signal: number describing the signal used to
|
||||
terminate (if any)
|
||||
• client_id: client handle
|
||||
• {on_attach}? (`elem_or_list<fun(client: vim.lsp.Client, bufnr: integer)>`)
|
||||
Callback invoked when client attaches to a
|
||||
buffer.
|
||||
• {trace}? (`'off'|'messages'|'verbose'`, default: "off")
|
||||
Passed directly to the language server in the
|
||||
initialize request. Invalid/empty values will
|
||||
lenses, …) triggers the command.
|
||||
• {detached}? (`boolean`, default: `true`) Daemonize the
|
||||
server process so that it runs in a separate
|
||||
process group from Nvim. Nvim will shutdown the
|
||||
process on exit, but if Nvim fails to exit
|
||||
cleanly this could leave behind orphaned server
|
||||
processes.
|
||||
• {flags}? (`table`) A table with flags for the client.
|
||||
The current (experimental) flags are:
|
||||
• {allow_incremental_sync}? (`boolean`,
|
||||
@ -1356,9 +1359,72 @@ Lua module: vim.lsp.client *lsp-client*
|
||||
request before sending kill -15. If set to
|
||||
false, nvim exits immediately after sending
|
||||
the "shutdown" request to the server.
|
||||
• {get_language_id}? (`fun(bufnr: integer, filetype: string): string`)
|
||||
Language ID as string. Defaults to the buffer
|
||||
filetype.
|
||||
• {handlers}? (`table<string,function>`) Map of LSP method
|
||||
names to |lsp-handler|s.
|
||||
• {init_options}? (`lsp.LSPObject`) Values to pass in the
|
||||
initialization request as
|
||||
`initializationOptions`. See `initialize` in
|
||||
the LSP spec.
|
||||
• {name}? (`string`, default: client-id) Name in logs and
|
||||
user messages.
|
||||
• {offset_encoding}? (`'utf-8'|'utf-16'|'utf-32'`) Called "position
|
||||
encoding" in LSP spec. The encoding that the
|
||||
LSP server expects, used for communication. Not
|
||||
validated. Can be modified in `on_init` before
|
||||
text is sent to the server.
|
||||
• {on_attach}? (`elem_or_list<fun(client: vim.lsp.Client, bufnr: integer)>`)
|
||||
Callback invoked when client attaches to a
|
||||
buffer.
|
||||
• {on_error}? (`fun(code: integer, err: string)`) Callback
|
||||
invoked when the client operation throws an
|
||||
error. `code` is a number describing the error.
|
||||
Other arguments may be passed depending on the
|
||||
error kind. See `vim.lsp.rpc.client_errors` for
|
||||
possible errors. Use
|
||||
`vim.lsp.rpc.client_errors[code]` to get
|
||||
human-friendly name.
|
||||
• {on_exit}? (`elem_or_list<fun(code: integer, signal: integer, client_id: integer)>`)
|
||||
Callback invoked on client exit.
|
||||
• code: exit code of the process
|
||||
• signal: number describing the signal used to
|
||||
terminate (if any)
|
||||
• client_id: client handle
|
||||
• {on_init}? (`elem_or_list<fun(client: vim.lsp.Client, init_result: lsp.InitializeResult)>`)
|
||||
Callback invoked after LSP "initialize", where
|
||||
`result` is a table of `capabilities` and
|
||||
anything else the server may send. For example,
|
||||
clangd sends `init_result.offsetEncoding` if
|
||||
`capabilities.offsetEncoding` was sent to it.
|
||||
You can only modify the
|
||||
`client.offset_encoding` here before any
|
||||
notifications are sent.
|
||||
• {root_dir}? (`string`) Directory where the LSP server will
|
||||
base its workspaceFolders, rootUri, and
|
||||
rootPath on initialization.
|
||||
• {settings}? (`lsp.LSPObject`) Map of language
|
||||
server-specific settings, decided by the
|
||||
client. Sent to the LS if requested via
|
||||
`workspace/configuration`. Keys are
|
||||
case-sensitive.
|
||||
• {trace}? (`'off'|'messages'|'verbose'`, default: "off")
|
||||
Passed directly to the language server in the
|
||||
initialize request. Invalid/empty values will
|
||||
• {workspace_folders}? (`lsp.WorkspaceFolder[]`) List of workspace
|
||||
folders passed to the language server. For
|
||||
backwards compatibility rootUri and rootPath
|
||||
are derived from the first workspace folder in
|
||||
this list. Can be `null` if the client supports
|
||||
workspace folders but none are configured. See
|
||||
`workspaceFolders` in LSP spec.
|
||||
• {workspace_required}? (`boolean`, default: `false`) Server requires a
|
||||
workspace (no "single file" support). Note:
|
||||
Without a workspace, cross-file features
|
||||
(navigation, hover) may or may not work
|
||||
depending on the language server, even if the
|
||||
server doesn't require a workspace.
|
||||
|
||||
|
||||
Client:cancel_request({id}) *Client:cancel_request()*
|
||||
@ -1544,7 +1610,8 @@ clear_references() *vim.lsp.buf.clear_references()*
|
||||
Removes document highlights from current buffer.
|
||||
|
||||
code_action({opts}) *vim.lsp.buf.code_action()*
|
||||
Selects a code action available at the current cursor position.
|
||||
Selects a code action (LSP: "textDocument/codeAction" request) available
|
||||
at cursor position.
|
||||
|
||||
Parameters: ~
|
||||
• {opts} (`table?`) A table with the following fields:
|
||||
@ -2507,6 +2574,27 @@ symbols_to_items({symbols}, {bufnr}, {position_encoding})
|
||||
==============================================================================
|
||||
Lua module: vim.lsp.log *lsp-log*
|
||||
|
||||
The `vim.lsp.log` module provides logging for the Nvim LSP client.
|
||||
|
||||
When debugging language servers, it is helpful to enable extra-verbose logging
|
||||
of the LSP client RPC events. Example: >lua
|
||||
vim.lsp.set_log_level 'trace'
|
||||
require('vim.lsp.log').set_format_func(vim.inspect)
|
||||
<
|
||||
|
||||
Then try to run the language server, and open the log with: >vim
|
||||
:lua vim.cmd('tabnew ' .. vim.lsp.get_log_path())
|
||||
<
|
||||
|
||||
(Or use `:LspLog` if you have nvim-lspconfig installed.)
|
||||
|
||||
Note:
|
||||
• Remember to DISABLE verbose logging ("debug" or "trace" level), else you may
|
||||
encounter performance issues.
|
||||
• "ERROR" messages containing "stderr" only indicate that the log was sent to
|
||||
stderr. Many servers send harmless messages via stderr.
|
||||
|
||||
|
||||
get_filename() *vim.lsp.log.get_filename()*
|
||||
Returns the log filename.
|
||||
|
||||
|
@ -93,10 +93,9 @@ Finally, you can include Lua code in a Vimscript file by putting it inside a
|
||||
Using Lua files on startup *lua-guide-config*
|
||||
|
||||
Nvim supports using `init.vim` or `init.lua` as the configuration file, but
|
||||
not both at the same time. This should be placed in your |config| directory,
|
||||
which is typically `~/.config/nvim` for Linux, BSD, or macOS, and
|
||||
`~/AppData/Local/nvim/` for Windows. Note that you can use Lua in `init.vim`
|
||||
and Vimscript in `init.lua`, which will be covered below.
|
||||
not both at the same time. This should be placed in your |config| directory
|
||||
(run `:echo stdpath('config')` to see where it is). Note that you can also use
|
||||
Lua in `init.vim` and Vimscript in `init.lua`, which will be covered below.
|
||||
|
||||
If you'd like to run any other Lua script on |startup| automatically, then you
|
||||
can simply put it in `plugin/` in your |'runtimepath'|.
|
||||
|
@ -171,7 +171,7 @@ added. But visually, this small bit of sugar gets reasonably close to a
|
||||
|
||||
*lua-regex*
|
||||
Lua intentionally does not support regular expressions, instead it has limited
|
||||
|lua-patterns| which avoid the performance pitfalls of extended regex. Lua
|
||||
|lua-pattern|s which avoid the performance pitfalls of extended regex. Lua
|
||||
scripts can also use Vim regex via |vim.regex()|.
|
||||
|
||||
Examples: >lua
|
||||
@ -1466,20 +1466,21 @@ Lua module: vim *lua-vim*
|
||||
vim.cmd({command}) *vim.cmd()*
|
||||
Executes Vimscript (|Ex-commands|).
|
||||
|
||||
Note that `vim.cmd` can be indexed with a command name to return a
|
||||
callable function to the command.
|
||||
Can be indexed with a command name to get a function, thus you can write
|
||||
`vim.cmd.echo(…)` instead of `vim.cmd{cmd='echo',…}`.
|
||||
|
||||
Example: >lua
|
||||
Examples: >lua
|
||||
-- Single command:
|
||||
vim.cmd('echo 42')
|
||||
-- Multiline script:
|
||||
vim.cmd([[
|
||||
augroup My_group
|
||||
augroup my.group
|
||||
autocmd!
|
||||
autocmd FileType c setlocal cindent
|
||||
augroup END
|
||||
]])
|
||||
|
||||
-- Ex command :echo "foo"
|
||||
-- Note string literals need to be double quoted.
|
||||
-- Ex command :echo "foo". Note: string literals must be double-quoted.
|
||||
vim.cmd('echo "foo"')
|
||||
vim.cmd { cmd = 'echo', args = { '"foo"' } }
|
||||
vim.cmd.echo({ args = { '"foo"' } })
|
||||
@ -1487,22 +1488,20 @@ vim.cmd({command}) *vim.cmd()*
|
||||
|
||||
-- Ex command :write! myfile.txt
|
||||
vim.cmd('write! myfile.txt')
|
||||
vim.cmd { cmd = 'write', args = { "myfile.txt" }, bang = true }
|
||||
vim.cmd.write { args = { "myfile.txt" }, bang = true }
|
||||
vim.cmd.write { "myfile.txt", bang = true }
|
||||
vim.cmd { cmd = 'write', args = { 'myfile.txt' }, bang = true }
|
||||
vim.cmd.write { args = { 'myfile.txt' }, bang = true }
|
||||
vim.cmd.write { 'myfile.txt', bang = true }
|
||||
|
||||
-- Ex command :colorscheme blue
|
||||
vim.cmd('colorscheme blue')
|
||||
vim.cmd.colorscheme('blue')
|
||||
-- Ex command :vertical resize +2
|
||||
vim.cmd.resize({ '+2', mods = { vertical = true } })
|
||||
<
|
||||
|
||||
Parameters: ~
|
||||
• {command} (`string|table`) Command(s) to execute. If a string,
|
||||
executes multiple lines of Vimscript at once. In this case,
|
||||
it is an alias to |nvim_exec2()|, where `opts.output` is
|
||||
set to false. Thus it works identical to |:source|. If a
|
||||
table, executes a single command. In this case, it is an
|
||||
alias to |nvim_cmd()| where `opts` is empty.
|
||||
• {command} (`string|table`) Command(s) to execute.
|
||||
• The string form supports multiline Vimscript (alias to
|
||||
|nvim_exec2()|, behaves like |:source|).
|
||||
• The table form executes a single command (alias to
|
||||
|nvim_cmd()|).
|
||||
|
||||
See also: ~
|
||||
• |ex-cmd-index|
|
||||
@ -1779,7 +1778,9 @@ vim.system({cmd}, {opts}, {on_exit}) *vim.system()*
|
||||
the new process. Inherits the current environment with
|
||||
`NVIM` set to |v:servername|.
|
||||
• clear_env: (boolean) `env` defines the job environment
|
||||
exactly, instead of merging current environment.
|
||||
exactly, instead of merging current environment. Note: if
|
||||
`env` is `nil`, the current environment is used but
|
||||
without `NVIM` set.
|
||||
• stdin: (string|string[]|boolean) If `true`, then a pipe
|
||||
to stdin is opened and can be written to via the
|
||||
`write()` method to SystemObj. If string or string[] then
|
||||
@ -2022,7 +2023,7 @@ vim.gsplit({s}, {sep}, {opts}) *vim.gsplit()*
|
||||
See also: ~
|
||||
• |string.gmatch()|
|
||||
• |vim.split()|
|
||||
• |lua-patterns|
|
||||
• |lua-pattern|s
|
||||
• https://www.lua.org/pil/20.2.html
|
||||
• http://lua-users.org/wiki/StringLibraryTutorial
|
||||
|
||||
@ -2115,7 +2116,7 @@ vim.list_slice({list}, {start}, {finish}) *vim.list_slice()*
|
||||
(`any[]`) Copy of table sliced from start to finish (inclusive)
|
||||
|
||||
vim.pesc({s}) *vim.pesc()*
|
||||
Escapes magic chars in |lua-patterns|.
|
||||
Escapes magic chars in |lua-pattern|s.
|
||||
|
||||
Parameters: ~
|
||||
• {s} (`string`) String to escape
|
||||
@ -2370,7 +2371,7 @@ vim.trim({s}) *vim.trim()*
|
||||
(`string`) String with whitespace removed from its beginning and end
|
||||
|
||||
See also: ~
|
||||
• |lua-patterns|
|
||||
• |lua-pattern|s
|
||||
• https://www.lua.org/pil/20.2.html
|
||||
|
||||
*vim.validate()*
|
||||
@ -2670,7 +2671,7 @@ vim.filetype.add({filetypes}) *vim.filetype.add()*
|
||||
Filetype mappings can be added either by extension or by filename (either
|
||||
the "tail" or the full file path). The full file path is checked first,
|
||||
followed by the file name. If a match is not found using the filename,
|
||||
then the filename is matched against the list of |lua-patterns| (sorted by
|
||||
then the filename is matched against the list of |lua-pattern|s (sorted by
|
||||
priority) until a match is found. Lastly, if pattern matching does not
|
||||
find a filetype, then the file extension is used.
|
||||
|
||||
@ -2898,7 +2899,7 @@ Use |uv.fs_stat()| to check a file's type, and whether it exists.
|
||||
|
||||
Example: >lua
|
||||
if vim.uv.fs_stat(file) then
|
||||
vim.print("file exists")
|
||||
vim.print('file exists')
|
||||
end
|
||||
<
|
||||
|
||||
@ -2940,11 +2941,13 @@ vim.fs.dir({path}, {opts}) *vim.fs.dir()*
|
||||
iterate over. The path is first normalized
|
||||
|vim.fs.normalize()|.
|
||||
• {opts} (`table?`) Optional keyword arguments:
|
||||
• depth: integer|nil How deep the traverse (default 1)
|
||||
• skip: (fun(dir_name: string): boolean)|nil Predicate to
|
||||
• {depth}? (`integer`, default: `1`) How deep the traverse.
|
||||
• {skip}? (`fun(dir_name: string): boolean`) Predicate to
|
||||
control traversal. Return false to stop searching the
|
||||
current directory. Only useful when depth > 1
|
||||
• follow: boolean|nil Follow symbolic links. (default: false)
|
||||
current directory. Only useful when depth > 1 Return an
|
||||
iterator over the items located in {path}
|
||||
• {follow}? (`boolean`, default: `false`) Follow symbolic
|
||||
links.
|
||||
|
||||
Return: ~
|
||||
(`Iterator`) over items in {path}. Each iteration yields two values:
|
||||
@ -2953,7 +2956,8 @@ vim.fs.dir({path}, {opts}) *vim.fs.dir()*
|
||||
"fifo", "socket", "char", "block", "unknown".
|
||||
|
||||
vim.fs.dirname({file}) *vim.fs.dirname()*
|
||||
Return the parent directory of the given path
|
||||
Gets the parent directory of the given path (not expanded/resolved, the
|
||||
caller must do that).
|
||||
|
||||
Attributes: ~
|
||||
Since: 0.8.0
|
||||
@ -2978,16 +2982,17 @@ vim.fs.find({names}, {opts}) *vim.fs.find()*
|
||||
narrow the search to find only that type.
|
||||
|
||||
Examples: >lua
|
||||
-- list all test directories under the runtime directory
|
||||
local test_dirs = vim.fs.find(
|
||||
{'test', 'tst', 'testdir'},
|
||||
{limit = math.huge, type = 'directory', path = './runtime/'}
|
||||
-- List all test directories under the runtime directory.
|
||||
local dirs = vim.fs.find(
|
||||
{ 'test', 'tst', 'testdir' },
|
||||
{ limit = math.huge, type = 'directory', path = './runtime/' }
|
||||
)
|
||||
|
||||
-- get all files ending with .cpp or .hpp inside lib/
|
||||
local cpp_hpp = vim.fs.find(function(name, path)
|
||||
-- Get all "lib/*.cpp" and "lib/*.hpp" files, using Lua patterns.
|
||||
-- Or use `vim.glob.to_lpeg(…):match(…)` for glob/wildcard matching.
|
||||
local files = vim.fs.find(function(name, path)
|
||||
return name:match('.*%.[ch]pp$') and path:match('[/\\]lib$')
|
||||
end, {limit = math.huge, type = 'file'})
|
||||
end, { limit = math.huge, type = 'file' })
|
||||
<
|
||||
|
||||
Attributes: ~
|
||||
@ -3004,7 +3009,7 @@ vim.fs.find({names}, {opts}) *vim.fs.find()*
|
||||
|
||||
The function should return `true` if the given item is
|
||||
considered a match.
|
||||
• {opts} (`table`) Optional keyword arguments:
|
||||
• {opts} (`table?`) Optional keyword arguments:
|
||||
• {path}? (`string`) Path to begin searching from. If
|
||||
omitted, the |current-directory| is used.
|
||||
• {upward}? (`boolean`, default: `false`) Search upward
|
||||
@ -3087,19 +3092,20 @@ vim.fs.normalize({path}, {opts}) *vim.fs.normalize()*
|
||||
(`string`) Normalized path
|
||||
|
||||
vim.fs.parents({start}) *vim.fs.parents()*
|
||||
Iterate over all the parents of the given path.
|
||||
Iterate over all the parents of the given path (not expanded/resolved, the
|
||||
caller must do that).
|
||||
|
||||
Example: >lua
|
||||
local root_dir
|
||||
for dir in vim.fs.parents(vim.api.nvim_buf_get_name(0)) do
|
||||
if vim.fn.isdirectory(dir .. "/.git") == 1 then
|
||||
if vim.fn.isdirectory(dir .. '/.git') == 1 then
|
||||
root_dir = dir
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if root_dir then
|
||||
print("Found git repository at", root_dir)
|
||||
print('Found git repository at', root_dir)
|
||||
end
|
||||
<
|
||||
|
||||
@ -3151,7 +3157,7 @@ vim.fs.root({source}, {marker}) *vim.fs.root()*
|
||||
If the buffer is unnamed (has no backing file) or has a non-empty
|
||||
'buftype' then the search begins from Nvim's |current-directory|.
|
||||
|
||||
Example: >lua
|
||||
Examples: >lua
|
||||
-- Find the root of a Python project, starting from file 'main.py'
|
||||
vim.fs.root(vim.fs.joinpath(vim.env.PWD, 'main.py'), {'pyproject.toml', 'setup.py' })
|
||||
|
||||
@ -3162,6 +3168,10 @@ vim.fs.root({source}, {marker}) *vim.fs.root()*
|
||||
vim.fs.root(0, function(name, path)
|
||||
return name:match('%.csproj$') ~= nil
|
||||
end)
|
||||
|
||||
-- Find the first ancestor directory containing EITHER "stylua.toml" or ".luarc.json"; if
|
||||
-- not found, find the first ancestor containing ".git":
|
||||
vim.fs.root(0, { { 'stylua.toml', '.luarc.json' }, '.git' })
|
||||
<
|
||||
|
||||
Attributes: ~
|
||||
@ -3171,10 +3181,13 @@ vim.fs.root({source}, {marker}) *vim.fs.root()*
|
||||
• {source} (`integer|string`) Buffer number (0 for current buffer) or
|
||||
file path (absolute or relative to the |current-directory|)
|
||||
to begin the search from.
|
||||
• {marker} (`string|string[]|fun(name: string, path: string): boolean`)
|
||||
A marker, or list of markers, to search for. If a function,
|
||||
the function is called for each evaluated item and should
|
||||
return true if {name} and {path} are a match.
|
||||
• {marker} (`(string|string[]|fun(name: string, path: string): boolean)[]|string|fun(name: string, path: string): boolean`)
|
||||
Filename, function, or list thereof, that decides how to
|
||||
find the root. To indicate "equal priority", specify items
|
||||
in a nested list `{ { 'a.txt', 'b.lua' }, … }`. A function
|
||||
item must return true if `name` and `path` are a match. Each
|
||||
item (which may itself be a nested list) is evaluated
|
||||
in-order against all ancestors, until a match is found.
|
||||
|
||||
Return: ~
|
||||
(`string?`) Directory path containing one of the given markers, or nil
|
||||
@ -3737,19 +3750,25 @@ vim.regex({re}) *vim.regex()*
|
||||
Lua module: vim.secure *vim.secure*
|
||||
|
||||
vim.secure.read({path}) *vim.secure.read()*
|
||||
Attempt to read the file at {path} prompting the user if the file should
|
||||
be trusted. The user's choice is persisted in a trust database at
|
||||
If {path} is a file: attempt to read the file, prompting the user if the
|
||||
file should be trusted.
|
||||
|
||||
If {path} is a directory: return true if the directory is trusted
|
||||
(non-recursive), prompting the user as necessary.
|
||||
|
||||
The user's choice is persisted in a trust database at
|
||||
$XDG_STATE_HOME/nvim/trust.
|
||||
|
||||
Attributes: ~
|
||||
Since: 0.9.0
|
||||
|
||||
Parameters: ~
|
||||
• {path} (`string`) Path to a file to read.
|
||||
• {path} (`string`) Path to a file or directory to read.
|
||||
|
||||
Return: ~
|
||||
(`string?`) The contents of the given file if it exists and is
|
||||
trusted, or nil otherwise.
|
||||
(`boolean|string?`) If {path} is not trusted or does not exist,
|
||||
returns `nil`. Otherwise, returns the contents of {path} if it is a
|
||||
file, or true if {path} is a directory.
|
||||
|
||||
See also: ~
|
||||
• |:trust|
|
||||
|
@ -4150,7 +4150,7 @@ string.upper({s}) *string.upper()*
|
||||
locale.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
5.4.1 Patterns *lua-patterns*
|
||||
5.4.1 Patterns *lua-pattern*
|
||||
|
||||
A character class is used to represent a set of characters. The following
|
||||
combinations are allowed in describing a character class:
|
||||
@ -4207,6 +4207,7 @@ A pattern item may be
|
||||
- a single character class followed by `+`, which matches 1 or more
|
||||
repetitions of characters in the class. These repetition items will
|
||||
always match the longest possible sequence;
|
||||
*lua-nongreedy*
|
||||
- a single character class followed by `-`, which also matches 0 or
|
||||
more repetitions of characters in the class. Unlike `*`, these
|
||||
repetition items will always match the shortest possible sequence;
|
||||
@ -4221,7 +4222,7 @@ A pattern item may be
|
||||
`y` where the count reaches 0. For instance, the item `%b()` matches
|
||||
expressions with balanced parentheses.
|
||||
|
||||
PATTERN *lua-pattern*
|
||||
PATTERN
|
||||
|
||||
A pattern is a sequence of pattern items. A `^` at the beginning of a pattern
|
||||
anchors the match at the beginning of the subject string. A `$` at the end of
|
||||
|
@ -19,12 +19,7 @@ For changing the language of messages and menus see |mlang.txt|.
|
||||
==============================================================================
|
||||
Getting started *mbyte-first*
|
||||
|
||||
This is a summary of the multibyte features in Vim. If you are lucky it works
|
||||
as described and you can start using Vim without much trouble. If something
|
||||
doesn't work you will have to read the rest. Don't be surprised if it takes
|
||||
quite a bit of work and experimenting to make Vim use all the multibyte
|
||||
features. Unfortunately, every system has its own way to deal with multibyte
|
||||
languages and it is quite complicated.
|
||||
This is a summary of the multibyte features in Nvim.
|
||||
|
||||
|
||||
LOCALE
|
||||
@ -54,14 +49,14 @@ See |mbyte-locale| for details.
|
||||
|
||||
ENCODING
|
||||
|
||||
Nvim always uses UTF-8 internally. Thus 'encoding' option is always set
|
||||
to "utf-8" and cannot be changed.
|
||||
Nvim always uses UTF-8 internally. Thus 'encoding' is always set to "utf-8"
|
||||
and cannot be changed.
|
||||
|
||||
All the text that is used inside Vim will be in UTF-8. Not only the text in
|
||||
the buffers, but also in registers, variables, etc.
|
||||
|
||||
You can edit files in different encodings than UTF-8. Nvim
|
||||
will convert the file when you read it and convert it back when you write it.
|
||||
You can edit files in different encodings than UTF-8. Nvim will convert the
|
||||
file when you read it and convert it back when you write it.
|
||||
See 'fileencoding', 'fileencodings' and |++enc|.
|
||||
|
||||
|
||||
@ -184,9 +179,9 @@ You could make a small shell script for this.
|
||||
==============================================================================
|
||||
Encoding *mbyte-encoding*
|
||||
|
||||
In Nvim UTF-8 is always used internally to encode characters.
|
||||
This applies to all the places where text is used, including buffers (files
|
||||
loaded into memory), registers and variables.
|
||||
UTF-8 is always used internally to encode characters. This applies to all the
|
||||
places where text is used, including buffers (files loaded into memory),
|
||||
registers and variables.
|
||||
|
||||
*charset* *codeset*
|
||||
Charset is another name for encoding. There are subtle differences, but these
|
||||
@ -609,25 +604,25 @@ Combining forms:
|
||||
Using UTF-8 *mbyte-utf8* *UTF-8* *utf-8* *utf8*
|
||||
*Unicode* *unicode*
|
||||
The Unicode character set was designed to include all characters from other
|
||||
character sets. Therefore it is possible to write text in any language using
|
||||
Unicode (with a few rarely used languages excluded). And it's mostly possible
|
||||
to mix these languages in one file, which is impossible with other encodings.
|
||||
character sets. Therefore it is possible to write text in (almost) any
|
||||
language using Unicode. And it's mostly possible to mix these languages in
|
||||
one file, which is impossible with other encodings.
|
||||
|
||||
Unicode can be encoded in several ways. The most popular one is UTF-8, which
|
||||
uses one or more bytes for each character and is backwards compatible with
|
||||
ASCII. On MS-Windows UTF-16 is also used (previously UCS-2), which uses
|
||||
16-bit words. Vim can support all of these encodings, but always uses UTF-8
|
||||
ASCII. On MS-Windows UTF-16 is also used (previously UCS-2), which uses
|
||||
16-bit words. Nvim supports all of these encodings, but always uses UTF-8
|
||||
internally.
|
||||
|
||||
Vim has comprehensive UTF-8 support. It works well in:
|
||||
- xterm with UTF-8 support enabled
|
||||
- MS-Windows GUI
|
||||
- several other platforms
|
||||
|
||||
Double-width characters are supported. Works best with 'guifontwide'. When
|
||||
Nvim supports double-width characters; works best with 'guifontwide'. When
|
||||
using only 'guifont' the wide characters are drawn in the normal width and
|
||||
a space to fill the gap.
|
||||
|
||||
EMOJI *emoji*
|
||||
|
||||
You can list emoji characters using this script: >vim
|
||||
:source $VIMRUNTIME/scripts/emoji_list.lua
|
||||
<
|
||||
*bom-bytes*
|
||||
When reading a file a BOM (Byte Order Mark) can be used to recognize the
|
||||
Unicode encoding:
|
||||
@ -698,7 +693,7 @@ You need to specify a font to be used. For double-wide characters another
|
||||
font is required, which is exactly twice as wide. There are three ways to do
|
||||
this:
|
||||
|
||||
1. Set 'guifont' and let Vim find a matching 'guifontwide'
|
||||
1. Set 'guifont' and let Nvim find a matching 'guifontwide'
|
||||
2. Set 'guifont' and 'guifontwide'
|
||||
|
||||
See the documentation for each option for details. Example: >
|
||||
@ -730,7 +725,7 @@ COMMAND ARGUMENTS *utf-8-char-arg*
|
||||
|
||||
Commands like |f|, |F|, |t| and |r| take an argument of one character. For
|
||||
UTF-8 this argument may include one or two composing characters. These need
|
||||
to be produced together with the base character, Vim doesn't wait for the next
|
||||
to be produced together with the base character, Nvim doesn't wait for the next
|
||||
character to be typed to find out if it is a composing character or not.
|
||||
Using 'keymap' or |:lmap| is a nice way to type these characters.
|
||||
|
||||
@ -741,7 +736,6 @@ searching for a character with a composing character, this will only find
|
||||
matches with that composing character. It was implemented this way, because
|
||||
not everybody is able to type a composing character.
|
||||
|
||||
|
||||
==============================================================================
|
||||
Overview of options *mbyte-options*
|
||||
|
||||
|
@ -171,6 +171,11 @@ API
|
||||
aligned text that truncates before covering up buffer text.
|
||||
• `virt_lines_overflow` field accepts value `scroll` to enable horizontal
|
||||
scrolling for virtual lines with 'nowrap'.
|
||||
• |vim.secure.read()| now returns `true` for trusted directories. Previously
|
||||
it would return `nil`, which made it impossible to tell if the directory was
|
||||
actually trusted.
|
||||
• Added |vim.lsp.is_enabled()| to check if a given LSP config has been enabled
|
||||
by |vim.lsp.enable()|.
|
||||
|
||||
DEFAULTS
|
||||
|
||||
@ -183,6 +188,7 @@ DEFAULTS
|
||||
• |gri| in Normal mode maps to |vim.lsp.buf.implementation()|
|
||||
• |gO| in Normal mode maps to |vim.lsp.buf.document_symbol()|
|
||||
• |gra| in Normal and Visual mode maps to |vim.lsp.buf.code_action()|
|
||||
• |grt| in Normal mode maps to |vim.lsp.buf.type_definition()|
|
||||
• CTRL-S in Insert and Select mode maps to |vim.lsp.buf.signature_help()|
|
||||
• Mouse |popup-menu| includes an "Open in web browser" item when you right-click
|
||||
on a URL.
|
||||
@ -277,6 +283,9 @@ LSP
|
||||
• The `textDocument/completion` request now includes the completion context in
|
||||
its parameters.
|
||||
• |vim.lsp.Config| gained `workspace_required`.
|
||||
• `root_markers` in |vim.lsp.Config| can now be ordered by priority.
|
||||
• The function form of `cmd` in a vim.lsp.Config or vim.lsp.ClientConfig
|
||||
receives the resolved config as the second arg: `cmd(dispatchers, config)`.
|
||||
|
||||
LUA
|
||||
|
||||
@ -299,6 +308,7 @@ LUA
|
||||
• |vim.hl.range()| now has a optional `timeout` field which allows for multiple
|
||||
timed highlights.
|
||||
• |vim.text.indent()| indents/dedents text.
|
||||
• |vim.fs.root()| can define "equal priority" via nested lists.
|
||||
|
||||
OPTIONS
|
||||
|
||||
@ -343,6 +353,8 @@ PLUGINS
|
||||
• 'commentstring' values can now be specified in a Treesitter capture's
|
||||
`bo.commentstring` metadata field, providing finer grained support for
|
||||
languages like `JSX`.
|
||||
• Customize :checkhealth by handling a `FileType checkhealth` event.
|
||||
|health-usage|
|
||||
|
||||
STARTUP
|
||||
|
||||
@ -437,6 +449,7 @@ UI
|
||||
• |ui-messages| content chunks now also contain the highlight group ID.
|
||||
• |:checkhealth| can display in a floating window, controlled by the
|
||||
|g:health| variable.
|
||||
• |:checkhealth| shows a summary in the header for every healthcheck.
|
||||
|
||||
VIMSCRIPT
|
||||
|
||||
|
@ -11,15 +11,43 @@ not a clone: compatibility with Vim (especially editor and Vimscript features,
|
||||
except |Vim9script|) is maintained where possible. See |vim-differences| for
|
||||
the complete reference.
|
||||
|
||||
If you already use Vim, see |nvim-from-vim| for a quickstart. If you just
|
||||
installed Nvim and have never used it before, watch this 10-minute
|
||||
video: https://youtu.be/TQn2hJeHQbM .
|
||||
- If you already use Vim, see |nvim-from-vim| for a quickstart.
|
||||
- If you have never used Vim or Nvim before, see below.
|
||||
|
||||
Type |gO| to see the table of contents.
|
||||
|
||||
==============================================================================
|
||||
What now? *nvim-quickstart*
|
||||
|
||||
To learn how to use Vim in 30 minutes, try the tutorial: >vim
|
||||
|
||||
:Tutor<Enter>
|
||||
<
|
||||
Type |gO| to see the table of contents.
|
||||
Or watch this 10-minute video: https://youtu.be/TQn2hJeHQbM .
|
||||
|
||||
To customize Nvim, you will need a config file. Create your |init.lua| by
|
||||
copying the "example_init.lua" file: >vim
|
||||
|
||||
:exe 'edit' stdpath('config') .. '/init.lua'
|
||||
:read $VIMRUNTIME/example_init.lua
|
||||
<
|
||||
See |lua-guide| for practical notes on using Lua to configure Nvim.
|
||||
|
||||
"IDE" features in Nvim are provided by |LSP|.
|
||||
|
||||
If you are just trying out Nvim for a few minutes, and want to see the
|
||||
extremes of what it can do, try one of these popular "extension packs" or
|
||||
"distributions" (Note: Nvim is not affiliated with these projects, and does
|
||||
not support them):
|
||||
|
||||
- *lazyvim* https://www.lazyvim.org/
|
||||
- *nvchad* https://nvchad.com/
|
||||
- *kickstart* https://github.com/nvim-lua/kickstart.nvim
|
||||
- Not recommended; use `$VIMRUNTIME/example_init.lua` instead.
|
||||
|
||||
However, we recommend (eventually) taking time to learn Nvim from its stock
|
||||
configuration, and incrementally setting options and adding plugins to your
|
||||
|config| as you discover a need.
|
||||
|
||||
==============================================================================
|
||||
Transitioning from Vim *nvim-from-vim*
|
||||
@ -72,21 +100,5 @@ the same Nvim configuration on all of your machines, by creating
|
||||
~/AppData/Local/nvim/init.vim containing just this line: >vim
|
||||
source ~/.config/nvim/init.vim
|
||||
|
||||
==============================================================================
|
||||
What next? *nvim-quickstart*
|
||||
|
||||
If you are just trying out Nvim for a few minutes, and want to see the
|
||||
extremes of what it can do, try one of these popular "extension packs" or
|
||||
"distributions" (Note: Nvim is not affiliated with these projects, and does
|
||||
not support them):
|
||||
|
||||
- *kickstart* https://github.com/nvim-lua/kickstart.nvim
|
||||
- *lazyvim* https://www.lazyvim.org/
|
||||
- *nvchad* https://nvchad.com/
|
||||
|
||||
However, in general, we recommend (eventually) taking time to learn Nvim from
|
||||
its stock configuration, and incrementally setting options and adding plugins
|
||||
to your |config| as you find an explicit need to do so.
|
||||
|
||||
==============================================================================
|
||||
vim:tw=78:ts=8:et:ft=help:norl:
|
||||
|
@ -2357,10 +2357,18 @@ A jump table for the options with a short description can be found at |Q_op|.
|
||||
in the |trust| list. Use |:trust| to manage trusted files. See also
|
||||
|vim.secure.read()|.
|
||||
|
||||
To get its own location, Lua exrc files can use |debug.getinfo()|.
|
||||
|
||||
Compare 'exrc' to |editorconfig|:
|
||||
- 'exrc' can execute any code; editorconfig only specifies settings.
|
||||
- 'exrc' is Nvim-specific; editorconfig works in other editors.
|
||||
|
||||
To achieve project-local LSP configuration:
|
||||
1. Enable 'exrc'.
|
||||
2. Place LSP configs at ".nvim/lsp/*.lua" in your project root.
|
||||
3. Create ".nvim.lua" in your project root directory with this line: >lua
|
||||
vim.cmd[[set runtimepath+=.nvim]]
|
||||
<
|
||||
This option cannot be set from a |modeline| or in the |sandbox|, for
|
||||
security reasons.
|
||||
|
||||
@ -5004,9 +5012,14 @@ A jump table for the options with a short description can be found at |Q_op|.
|
||||
the end of line the line break still isn't included.
|
||||
When "exclusive" is used, cursor position in visual mode will be
|
||||
adjusted for inclusive motions |inclusive-motion-selection-exclusive|.
|
||||
Note that when "exclusive" is used and selecting from the end
|
||||
backwards, you cannot include the last character of a line, when
|
||||
starting in Normal mode and 'virtualedit' empty.
|
||||
|
||||
Note:
|
||||
- When "exclusive" is used and selecting from the end backwards, you
|
||||
cannot include the last character of a line, when starting in Normal
|
||||
mode and 'virtualedit' empty.
|
||||
- when "exclusive" is used with a single character visual selection,
|
||||
Vim will behave as if the 'selection' is inclusive (in other words,
|
||||
you cannot visually select an empty region).
|
||||
|
||||
*'selectmode'* *'slm'*
|
||||
'selectmode' 'slm' string (default "")
|
||||
@ -5946,8 +5959,7 @@ A jump table for the options with a short description can be found at |Q_op|.
|
||||
*'statusline'* *'stl'* *E540* *E542*
|
||||
'statusline' 'stl' string (default "")
|
||||
global or local to window |global-local|
|
||||
When non-empty, this option determines the content of the status line.
|
||||
Also see |status-line|.
|
||||
Sets the |status-line|.
|
||||
|
||||
The option consists of printf style '%' items interspersed with
|
||||
normal text. Each status line item is of the form:
|
||||
|
@ -4,6 +4,8 @@
|
||||
vim-tutor-mode provides a system to follow and create interactive tutorials
|
||||
for vim and third party plugins. It replaces the venerable `vimtutor` system.
|
||||
|
||||
Original Author: Felipe Morales <https://github.com/fmoralesc>
|
||||
|
||||
==============================================================================
|
||||
1. Usage *vim-tutor-usage*
|
||||
|
||||
@ -39,12 +41,5 @@ to be detected by the :Tutor command.
|
||||
It is recommended to use a less formal style when writing tutorials than in
|
||||
regular documentation (unless the content requires it).
|
||||
|
||||
============================================================================
|
||||
3. Contributing
|
||||
|
||||
Development of the plugin is done over at github [1]. Feel free to report
|
||||
issues and make suggestions.
|
||||
|
||||
[1]: https://github.com/fmoralesc/vim-tutor-mode
|
||||
|
||||
" vim: set ft=help :
|
||||
=============================================================================
|
||||
vim:tw=78:ts=8:noet:ft=help:norl:
|
||||
|
@ -91,28 +91,40 @@ processing a quickfix or location list command, it will be aborted.
|
||||
:ll[!] [nr] Same as ":cc", except the location list for the
|
||||
:[nr]ll[!] current window is used instead of the quickfix list.
|
||||
|
||||
*:cn* *:cne* *:cnext* *E553* *]q*
|
||||
*:cn* *:cne* *:cnext* *E553*
|
||||
:[count]cn[ext][!] Display the [count] next error in the list that
|
||||
includes a file name. If there are no file names at
|
||||
all, go to the [count] next error. See |:cc| for
|
||||
[!] and 'switchbuf'.
|
||||
|
||||
*:lne* *:lnext* *]l*
|
||||
*]q*
|
||||
]q Mapped to |:cnext|. |default-mappings|
|
||||
|
||||
*:lne* *:lnext*
|
||||
:[count]lne[xt][!] Same as ":cnext", except the location list for the
|
||||
current window is used instead of the quickfix list.
|
||||
|
||||
:[count]cN[ext][!] *:cp* *:cprevious* *:cprev* *:cN* *:cNext* *[q*
|
||||
*]l*
|
||||
]l Mapped to |:lnext|. |default-mappings|
|
||||
|
||||
:[count]cN[ext][!] *:cp* *:cprevious* *:cprev* *:cN* *:cNext*
|
||||
:[count]cp[revious][!] Display the [count] previous error in the list that
|
||||
includes a file name. If there are no file names at
|
||||
all, go to the [count] previous error. See |:cc| for
|
||||
[!] and 'switchbuf'.
|
||||
|
||||
*[q*
|
||||
[q Mapped to |:cprevious|. |default-mappings|
|
||||
|
||||
:[count]lN[ext][!] *:lp* *:lprevious* *:lprev* *:lN* *:lNext* *[l*
|
||||
|
||||
:[count]lN[ext][!] *:lp* *:lprevious* *:lprev* *:lN* *:lNext*
|
||||
:[count]lp[revious][!] Same as ":cNext" and ":cprevious", except the location
|
||||
list for the current window is used instead of the
|
||||
quickfix list.
|
||||
|
||||
*[l*
|
||||
[l Mapped to |:lprevious|. |default-mappings|
|
||||
|
||||
*:cabo* *:cabove*
|
||||
:[count]cabo[ve] Go to the [count] error above the current line in the
|
||||
current buffer. If [count] is omitted, then 1 is
|
||||
@ -171,52 +183,76 @@ processing a quickfix or location list command, it will be aborted.
|
||||
:[count]laf[ter] Same as ":cafter", except the location list for the
|
||||
current window is used instead of the quickfix list.
|
||||
|
||||
*:cnf* *:cnfile* *]CTRL-Q*
|
||||
*:cnf* *:cnfile*
|
||||
:[count]cnf[ile][!] Display the first error in the [count] next file in
|
||||
the list that includes a file name. If there are no
|
||||
file names at all or if there is no next file, go to
|
||||
the [count] next error. See |:cc| for [!] and
|
||||
'switchbuf'.
|
||||
|
||||
*:lnf* *:lnfile* *]CTRL-L*
|
||||
*]CTRL-Q*
|
||||
]CTRL-Q Mapped to |:cnfile|. |default-mappings|
|
||||
|
||||
*:lnf* *:lnfile*
|
||||
:[count]lnf[ile][!] Same as ":cnfile", except the location list for the
|
||||
current window is used instead of the quickfix list.
|
||||
|
||||
:[count]cNf[ile][!] *:cpf* *:cpfile* *:cNf* *:cNfile* *[CTRL-Q*
|
||||
*]CTRL-L*
|
||||
]CTRL-L Mapped to |:lnfile|. |default-mappings|
|
||||
|
||||
:[count]cNf[ile][!] *:cpf* *:cpfile* *:cNf* *:cNfile*
|
||||
:[count]cpf[ile][!] Display the last error in the [count] previous file in
|
||||
the list that includes a file name. If there are no
|
||||
file names at all or if there is no next file, go to
|
||||
the [count] previous error. See |:cc| for [!] and
|
||||
'switchbuf'.
|
||||
|
||||
*[CTRL-Q*
|
||||
[CTRL-Q Mapped to |:cpfile|. |default-mappings|
|
||||
|
||||
:[count]lNf[ile][!] *:lpf* *:lpfile* *:lNf* *:lNfile* *[CTRL-L*
|
||||
|
||||
:[count]lNf[ile][!] *:lpf* *:lpfile* *:lNf* *:lNfile*
|
||||
:[count]lpf[ile][!] Same as ":cNfile" and ":cpfile", except the location
|
||||
list for the current window is used instead of the
|
||||
quickfix list.
|
||||
|
||||
*:crewind* *:cr* *[Q*
|
||||
*[CTRL-L*
|
||||
[CTRL-L Mapped to |:lpfile|. |default-mappings|
|
||||
|
||||
*:crewind* *:cr*
|
||||
:cr[ewind][!] [nr] Display error [nr]. If [nr] is omitted, the FIRST
|
||||
error is displayed. See |:cc|.
|
||||
|
||||
*:lrewind* *:lr* *[L*
|
||||
*[Q*
|
||||
[Q Mapped to |:crewind|. |default-mappings|
|
||||
|
||||
*:lrewind* *:lr*
|
||||
:lr[ewind][!] [nr] Same as ":crewind", except the location list for the
|
||||
current window is used instead of the quickfix list.
|
||||
|
||||
*[L*
|
||||
[L Mapped to |:lrewind|. |default-mappings|
|
||||
|
||||
*:cfirst* *:cfir*
|
||||
:cfir[st][!] [nr] Same as ":crewind".
|
||||
|
||||
*:lfirst* *:lfir*
|
||||
:lfir[st][!] [nr] Same as ":lrewind".
|
||||
|
||||
*:clast* *:cla* *]Q*
|
||||
*:clast* *:cla*
|
||||
:cla[st][!] [nr] Display error [nr]. If [nr] is omitted, the LAST
|
||||
error is displayed. See |:cc|.
|
||||
|
||||
*:llast* *:lla* *]L*
|
||||
*]Q*
|
||||
]Q Mapped to |:clast|.
|
||||
|
||||
*:llast* *:lla*
|
||||
:lla[st][!] [nr] Same as ":clast", except the location list for the
|
||||
current window is used instead of the quickfix list.
|
||||
|
||||
*]L*
|
||||
]L Mapped to |:llast|.
|
||||
|
||||
*:cq* *:cquit*
|
||||
:cq[uit][!]
|
||||
:{N}cq[uit][!]
|
||||
|
@ -1382,8 +1382,8 @@ The $XDG_CONFIG_HOME, $XDG_DATA_HOME, $XDG_RUNTIME_DIR, $XDG_STATE_HOME,
|
||||
$XDG_CACHE_HOME, $XDG_CONFIG_DIRS and $XDG_DATA_DIRS environment variables
|
||||
are used if defined, else default values (listed below) are used.
|
||||
|
||||
Throughout the help pages these defaults are used as placeholders, e.g.
|
||||
"~/.config" is understood to mean "$XDG_CONFIG_HOME or ~/.config".
|
||||
Note: In the help these defaults are used as placeholders, e.g. "~/.config" is
|
||||
understood as "$XDG_CONFIG_HOME or ~/.config".
|
||||
|
||||
CONFIG DIRECTORY (DEFAULT) ~
|
||||
*$XDG_CONFIG_HOME* Nvim: stdpath("config")
|
||||
@ -1437,12 +1437,17 @@ configuration files in `$XDG_CONFIG_HOME/foo` instead of
|
||||
`$XDG_CONFIG_HOME/nvim`. `$NVIM_APPNAME` must be a name, such as "foo", or a
|
||||
relative path, such as "foo/bar".
|
||||
|
||||
Note: In the help wherever `$XDG_CONFIG_…/nvim` is mentioned it is understood
|
||||
as `$XDG_CONFIG_…/$NVIM_APPNAME`.
|
||||
|
||||
*state-isolation*
|
||||
One use-case for $NVIM_APPNAME is to "isolate" Nvim applications.
|
||||
Alternatively, for true isolation, on Linux you can use cgroups namespaces: >
|
||||
systemd-run --user -qt -p PrivateUsers=yes -p BindPaths=/home/user/profile_xy:/home/user/.config/nvim nvim
|
||||
|
||||
Note: Throughout the help pages, wherever `$XDG_CONFIG_…/nvim` is mentioned it
|
||||
is understood to mean `$XDG_CONFIG_…/$NVIM_APPNAME`.
|
||||
<
|
||||
*stateless*
|
||||
To run Nvim without creating any directories or data files: >
|
||||
NVIM_LOG_FILE=/dev/null nvim -n -i NONE
|
||||
|
||||
LOG FILE *log* *$NVIM_LOG_FILE* *E5430*
|
||||
Besides 'debug' and 'verbose', Nvim keeps a general log file for internal
|
||||
|
@ -274,27 +274,39 @@ g CTRL-] Like CTRL-], but use ":tjump" instead of ":tag".
|
||||
{Visual}g CTRL-] Same as "g CTRL-]", but use the highlighted text as
|
||||
the identifier.
|
||||
|
||||
*:tn* *:tnext* *]t*
|
||||
*:tn* *:tnext*
|
||||
:[count]tn[ext][!] Jump to [count] next matching tag (default 1). See
|
||||
|tag-!| for [!].
|
||||
|
||||
*:tp* *:tprevious* *[t*
|
||||
*]t*
|
||||
]t Mapped to |:tnext|. |default-mappings|
|
||||
|
||||
*:tp* *:tprevious*
|
||||
:[count]tp[revious][!] Jump to [count] previous matching tag (default 1).
|
||||
See |tag-!| for [!].
|
||||
|
||||
*[t*
|
||||
[t Mapped to |:tprevious|. |default-mappings|
|
||||
|
||||
*:tN* *:tNext*
|
||||
:[count]tN[ext][!] Same as ":tprevious".
|
||||
|
||||
*:tr* *:trewind* *[T*
|
||||
*:tr* *:trewind*
|
||||
:[count]tr[ewind][!] Jump to first matching tag. If [count] is given, jump
|
||||
to [count]th matching tag. See |tag-!| for [!].
|
||||
|
||||
*[T*
|
||||
[T Mapped to |:trewind|. |default-mappings|
|
||||
|
||||
*:tf* *:tfirst*
|
||||
:[count]tf[irst][!] Same as ":trewind".
|
||||
|
||||
*:tl* *:tlast* *]T*
|
||||
*:tl* *:tlast*
|
||||
:tl[ast][!] Jump to last matching tag. See |tag-!| for [!].
|
||||
|
||||
*]T*
|
||||
]T Mapped to |:tlast|. |default-mappings|
|
||||
|
||||
*:lt* *:ltag*
|
||||
:lt[ag][!] [name] Jump to tag [name] and add the matching tags to a new
|
||||
location list for the current window. [name] can be
|
||||
@ -335,12 +347,18 @@ the same as above, with a "p" prepended.
|
||||
:ptj[ump][!] [name] Does ":tjump[!] [name]" and shows the new tag in a
|
||||
"Preview" window. See |:ptag| for more info.
|
||||
|
||||
*:ptn* *:ptnext* *]CTRL-T*
|
||||
*:ptn* *:ptnext*
|
||||
:[count]ptn[ext][!] ":tnext" in the preview window. See |:ptag|.
|
||||
|
||||
*:ptp* *:ptprevious* *[CTRL-T*
|
||||
*]CTRL-T*
|
||||
]CTRL-T Mapped to |:ptnext|. |default-mappings|
|
||||
|
||||
*:ptp* *:ptprevious*
|
||||
:[count]ptp[revious][!] ":tprevious" in the preview window. See |:ptag|.
|
||||
|
||||
*[CTRL-T*
|
||||
[CTRL-T Mapped to |:ptprevious|. |default-mappings|
|
||||
|
||||
*:ptN* *:ptNext*
|
||||
:[count]ptN[ext][!] Same as ":ptprevious".
|
||||
|
||||
|
@ -120,7 +120,7 @@ The following predicates are built in:
|
||||
match.
|
||||
|
||||
`lua-match?` *treesitter-predicate-lua-match?*
|
||||
Match |lua-patterns| against the text corresponding to a node,
|
||||
Match |lua-pattern|s against the text corresponding to a node,
|
||||
similar to `match?`
|
||||
|
||||
`any-lua-match?` *treesitter-predicate-any-lua-match?*
|
||||
@ -573,7 +573,10 @@ parent tree. The language injection query allows you to specify these
|
||||
“injections” using the following captures:
|
||||
|
||||
• `@injection.content` - indicates that the captured node should have its
|
||||
contents re-parsed using another language.
|
||||
contents re-parsed using another language. If there are multiple
|
||||
`@injection.content` captures in one pattern, all ranges will be
|
||||
collected and parsed as one tree. This allows query authors to create
|
||||
"scoped" injections with injection query quantifiers.
|
||||
• `@injection.language` - indicates that the captured node’s text may
|
||||
contain the name of a language that should be used to re-parse the
|
||||
`@injection.content`.
|
||||
|
@ -103,11 +103,11 @@ g8 Print the hex values of the bytes used in the
|
||||
*gx*
|
||||
gx Opens the current filepath or URL (decided by
|
||||
|<cfile>|, 'isfname') at cursor using the system
|
||||
default handler, by calling |vim.ui.open()|.
|
||||
default handler. Mapped to |vim.ui.open()|.
|
||||
|
||||
*v_gx*
|
||||
{Visual}gx Opens the selected text using the system default
|
||||
handler, by calling |vim.ui.open()|.
|
||||
handler. Mapped to |vim.ui.open()|.
|
||||
|
||||
*:p* *:pr* *:print* *E749*
|
||||
:[range]p[rint] [flags]
|
||||
@ -611,6 +611,8 @@ to look up the value of 'commentstring' corresponding to the cursor position.
|
||||
(This can be different from the buffer's 'commentstring' in case of
|
||||
|treesitter-language-injections|.)
|
||||
|
||||
The following |default-mappings| are defined:
|
||||
|
||||
*gc* *gc-default*
|
||||
gc{motion} Comment or uncomment lines covered by {motion}.
|
||||
|
||||
|
@ -134,7 +134,8 @@ To remove only the "How-to disable mouse" menu item (and its separator): >vim
|
||||
DEFAULT MAPPINGS
|
||||
*default-mappings*
|
||||
Nvim creates the following default mappings at |startup|. You can disable any
|
||||
of these in your config by simply removing the mapping, e.g. ":unmap Y".
|
||||
of these in your config by simply removing the mapping, e.g. ":unmap Y". If
|
||||
you never want any default mappings, call |:mapclear| early in your config.
|
||||
|
||||
- Y |Y-default|
|
||||
- <C-U> |i_CTRL-U-default|
|
||||
@ -152,6 +153,7 @@ of these in your config by simply removing the mapping, e.g. ":unmap Y".
|
||||
- |grr|
|
||||
- |gra|
|
||||
- |gri|
|
||||
- |grt|
|
||||
- |gO|
|
||||
- <C-S> |i_CTRL-S|
|
||||
- ]d |]d-default|
|
||||
@ -383,6 +385,7 @@ Options:
|
||||
- 'showcmdloc' cannot be set to empty.
|
||||
- 'signcolumn' can show multiple signs (dynamic or fixed columns)
|
||||
- 'statuscolumn' full control of columns using 'statusline' format
|
||||
- 'statusline' default is exposed as a statusline expression.
|
||||
- 'splitkeep' cannot be set to empty.
|
||||
- 'tabline' middle-click on tabpage label closes tabpage,
|
||||
and %@Func@foo%X can call any function on mouse-click
|
||||
@ -854,9 +857,8 @@ Startup:
|
||||
Test functions:
|
||||
- test_alloc_fail()
|
||||
- test_autochdir()
|
||||
- test_disable_char_avail()
|
||||
- test_feedinput()
|
||||
- test_garbagecollect_soon
|
||||
- test_garbagecollect_soon()
|
||||
- test_getvalue()
|
||||
- test_ignore_error()
|
||||
- test_null_blob()
|
||||
@ -874,6 +876,8 @@ Test functions:
|
||||
- test_setmouse()
|
||||
- test_settime()
|
||||
- test_srand_seed()
|
||||
- test_unknown()
|
||||
- test_void()
|
||||
|
||||
TUI:
|
||||
*t_xx* *termcap-options* *t_AB* *t_Sb* *t_vb* *t_SI*
|
||||
|
@ -1,10 +1,10 @@
|
||||
*eval.txt* Nvim
|
||||
*vimeval.txt* Nvim
|
||||
|
||||
|
||||
VIM REFERENCE MANUAL by Bram Moolenaar
|
||||
|
||||
|
||||
Expression evaluation *vimscript* *expression* *expr* *E15* *eval*
|
||||
Expression evaluation *vimscript* *expression* *expr* *E15* *eval* *eval.txt*
|
||||
|
||||
Using expressions is introduced in chapter 41 of the user manual |usr_41.txt|.
|
||||
|
@ -1,10 +1,10 @@
|
||||
*builtin.txt* Nvim
|
||||
*vimfn.txt* Nvim
|
||||
|
||||
|
||||
NVIM REFERENCE MANUAL
|
||||
|
||||
|
||||
Builtin functions *vimscript-functions* *builtin-functions*
|
||||
Vimscript functions *vimscript-functions* *builtin-functions* *builtin.txt*
|
||||
|
||||
For functions grouped by what they are used for see |function-list|.
|
||||
|
||||
@ -2040,7 +2040,8 @@ expand({string} [, {nosuf} [, {list}]]) *expand()*
|
||||
<SID> "<SNR>123_" where "123" is the
|
||||
current script ID |<SID>|
|
||||
<script> sourced script file, or script file
|
||||
where the current function was defined
|
||||
where the current function was defined.
|
||||
Use |debug.getinfo()| in Lua scripts.
|
||||
<stack> call stack
|
||||
<cword> word under the cursor
|
||||
<cWORD> WORD under the cursor
|
||||
@ -3244,7 +3245,7 @@ getcharsearch() *getcharsearch()*
|
||||
Return: ~
|
||||
(`table`)
|
||||
|
||||
getcharstr([{expr}]) *getcharstr()*
|
||||
getcharstr([{expr} [, {opts}]]) *getcharstr()*
|
||||
The same as |getchar()|, except that this always returns a
|
||||
String, and "number" isn't allowed in {opts}.
|
||||
|
||||
@ -4093,6 +4094,10 @@ getregion({pos1}, {pos2} [, {opts}]) *getregion()*
|
||||
- It is evaluated in current window context, which makes a
|
||||
difference if the buffer is displayed in a window with
|
||||
different 'virtualedit' or 'list' values.
|
||||
- When specifying an exclusive selection and {pos1} and {pos2}
|
||||
are equal, the returned list contains a single character as
|
||||
if selection is inclusive, to match the behavior of an empty
|
||||
exclusive selection in Visual mode.
|
||||
|
||||
Examples: >vim
|
||||
xnoremap <CR>
|
||||
@ -12029,7 +12034,7 @@ winlayout([{tabnr}]) *winlayout()*
|
||||
• {tabnr} (`integer?`)
|
||||
|
||||
Return: ~
|
||||
(`any[]`)
|
||||
(`vim.fn.winlayout.ret`)
|
||||
|
||||
winline() *winline()*
|
||||
The result is a Number, which is the screen line of the cursor
|
@ -439,18 +439,17 @@ CTRL-W l Move cursor to Nth window right of current one. Uses the
|
||||
|
||||
CTRL-W w *CTRL-W_w* *CTRL-W_CTRL-W*
|
||||
CTRL-W CTRL-W Without count: move cursor to the |focusable| window
|
||||
below/right of the current one. If there is no (focusable)
|
||||
window below or right, go to top-left window. With count: go
|
||||
to Nth window (windows are numbered from top-left to
|
||||
bottom-right). To obtain the window number see |bufwinnr()|
|
||||
and |winnr()|. When N is larger than the number of windows go
|
||||
to the last window.
|
||||
below/right of the current one. If none, go to the top-left
|
||||
window. With count: go to Nth window (numbered top-left to
|
||||
bottom-right), skipping unfocusable windows. To obtain the
|
||||
window number see |bufwinnr()| and |winnr()|. When N is
|
||||
larger than the number of windows go to the last focusable
|
||||
window.
|
||||
|
||||
*CTRL-W_W*
|
||||
CTRL-W W Without count: move cursor to the |focusable| window
|
||||
above/left of current one. If there is no window above or
|
||||
left, go to bottom-right window. With count: go to Nth
|
||||
window, like with CTRL-W w.
|
||||
above/left of current one. If none, go to the bottom-right
|
||||
window. With count: go to Nth window, like CTRL-W w.
|
||||
|
||||
CTRL-W t *CTRL-W_t* *CTRL-W_CTRL-T*
|
||||
CTRL-W CTRL-T Move cursor to top-left window.
|
||||
@ -1273,7 +1272,7 @@ list of buffers. |unlisted-buffer|
|
||||
:w foobar | sp #
|
||||
< Also see |+cmd|.
|
||||
|
||||
:[N]bn[ext][!] [+cmd] [N] *:bn* *:bnext* *]b* *E87*
|
||||
:[N]bn[ext][!] [+cmd] [N] *:bn* *:bnext* *E87*
|
||||
Go to [N]th next buffer in buffer list. [N] defaults to one.
|
||||
Wraps around the end of the buffer list.
|
||||
See |:buffer-!| for [!].
|
||||
@ -1285,13 +1284,20 @@ list of buffers. |unlisted-buffer|
|
||||
the way when you're browsing code/text buffers. The next three
|
||||
commands also work like this.
|
||||
|
||||
*]b*
|
||||
]b Mapped to |:bnext|. |default-mappings|
|
||||
|
||||
*:sbn* *:sbnext*
|
||||
:[N]sbn[ext] [+cmd] [N]
|
||||
Split window and go to [N]th next buffer in buffer list.
|
||||
Wraps around the end of the buffer list. Uses 'switchbuf'
|
||||
Also see |+cmd|.
|
||||
|
||||
:[N]bN[ext][!] [+cmd] [N] *:bN* *:bNext* *:bp* *:bprevious* *[b* *E88*
|
||||
:[N]bN[ext][!] [+cmd] [N] *:bN* *:bNext* *:bp* *:bprevious* *E88*
|
||||
|
||||
*[b*
|
||||
[b Mapped to |:bprevious|. |default-mappings|
|
||||
|
||||
:[N]bp[revious][!] [+cmd] [N]
|
||||
Go to [N]th previous buffer in buffer list. [N] defaults to
|
||||
one. Wraps around the start of the buffer list.
|
||||
@ -1305,11 +1311,14 @@ list of buffers. |unlisted-buffer|
|
||||
Uses 'switchbuf'.
|
||||
Also see |+cmd|.
|
||||
|
||||
:br[ewind][!] [+cmd] *:br* *:bre* *:brewind* *[B*
|
||||
:br[ewind][!] [+cmd] *:br* *:bre* *:brewind*
|
||||
Go to first buffer in buffer list. If the buffer list is
|
||||
empty, go to the first unlisted buffer.
|
||||
See |:buffer-!| for [!].
|
||||
|
||||
*[B*
|
||||
[B Mapped to |:brewind|. |default-mappings|
|
||||
|
||||
:bf[irst] [+cmd] *:bf* *:bfirst*
|
||||
Same as |:brewind|.
|
||||
Also see |+cmd|.
|
||||
@ -1323,11 +1332,14 @@ list of buffers. |unlisted-buffer|
|
||||
:sbf[irst] [+cmd] *:sbf* *:sbfirst*
|
||||
Same as ":sbrewind".
|
||||
|
||||
:bl[ast][!] [+cmd] *:bl* *:blast* *]B*
|
||||
:bl[ast][!] [+cmd] *:bl* *:blast*
|
||||
Go to last buffer in buffer list. If the buffer list is
|
||||
empty, go to the last unlisted buffer.
|
||||
See |:buffer-!| for [!].
|
||||
|
||||
*]B*
|
||||
]B Mapped to |:blast|. |default-mappings|
|
||||
|
||||
:sbl[ast] [+cmd] *:sbl* *:sblast*
|
||||
Split window and go to last buffer in buffer list. If the
|
||||
buffer list is empty, go to the last unlisted buffer.
|
||||
|
88
runtime/example_init.lua
Normal file
88
runtime/example_init.lua
Normal file
@ -0,0 +1,88 @@
|
||||
-- Set <space> as the leader key
|
||||
-- See `:help mapleader`
|
||||
-- NOTE: Must happen before plugins are loaded (otherwise wrong leader will be used)
|
||||
vim.g.mapleader = ' '
|
||||
|
||||
-- [[ Setting options ]] See `:h vim.o`
|
||||
-- NOTE: You can change these options as you wish!
|
||||
-- For more options, you can see `:help option-list`
|
||||
-- To see documentation for an option, you can use `:h 'optionname'`, for example `:h 'number'`
|
||||
-- (Note the single quotes)
|
||||
|
||||
-- Print the line number in front of each line
|
||||
vim.o.number = true
|
||||
|
||||
-- Use relative line numbers, so that it is easier to jump with j, k. This will affect the 'number'
|
||||
-- option above, see `:h number_relativenumber`
|
||||
vim.o.relativenumber = true
|
||||
|
||||
-- Sync clipboard between OS and Neovim. Schedule the setting after `UiEnter` because it can
|
||||
-- increase startup-time. Remove this option if you want your OS clipboard to remain independent.
|
||||
-- See `:help 'clipboard'`
|
||||
vim.api.nvim_create_autocmd('UIEnter', {
|
||||
callback = function()
|
||||
vim.o.clipboard = 'unnamedplus'
|
||||
end,
|
||||
})
|
||||
|
||||
-- Case-insensitive searching UNLESS \C or one or more capital letters in the search term
|
||||
vim.o.ignorecase = true
|
||||
vim.o.smartcase = true
|
||||
|
||||
-- Highlight the line where the cursor is on
|
||||
vim.o.cursorline = true
|
||||
|
||||
-- Minimal number of screen lines to keep above and below the cursor.
|
||||
vim.o.scrolloff = 10
|
||||
|
||||
-- Show <tab> and trailing spaces
|
||||
vim.o.list = true
|
||||
|
||||
-- if performing an operation that would fail due to unsaved changes in the buffer (like `:q`),
|
||||
-- instead raise a dialog asking if you wish to save the current file(s) See `:help 'confirm'`
|
||||
vim.o.confirm = true
|
||||
|
||||
-- [[ Set up keymaps ]] See `:h vim.keymap.set()`, `:h mapping`, `:h keycodes`
|
||||
|
||||
-- Use <Esc> to exit terminal mode
|
||||
vim.keymap.set('t', '<Esc>', '<C-\\><C-n>')
|
||||
|
||||
-- Map <A-j>, <A-k>, <A-h>, <A-l> to navigate between windows in any modes
|
||||
vim.keymap.set({ 't', 'i' }, '<A-h>', '<C-\\><C-n><C-w>h')
|
||||
vim.keymap.set({ 't', 'i' }, '<A-j>', '<C-\\><C-n><C-w>j')
|
||||
vim.keymap.set({ 't', 'i' }, '<A-k>', '<C-\\><C-n><C-w>k')
|
||||
vim.keymap.set({ 't', 'i' }, '<A-l>', '<C-\\><C-n><C-w>l')
|
||||
vim.keymap.set({ 'n' }, '<A-h>', '<C-w>h')
|
||||
vim.keymap.set({ 'n' }, '<A-j>', '<C-w>j')
|
||||
vim.keymap.set({ 'n' }, '<A-k>', '<C-w>k')
|
||||
vim.keymap.set({ 'n' }, '<A-l>', '<C-w>l')
|
||||
|
||||
-- [[ Basic Autocommands ]].
|
||||
-- See `:h lua-guide-autocommands`, `:h autocmd`, `:h nvim_create_autocmd()`
|
||||
|
||||
-- Highlight when yanking (copying) text.
|
||||
-- Try it with `yap` in normal mode. See `:h vim.hl.on_yank()`
|
||||
vim.api.nvim_create_autocmd('TextYankPost', {
|
||||
desc = 'Highlight when yanking (copying) text',
|
||||
callback = function()
|
||||
vim.hl.on_yank()
|
||||
end,
|
||||
})
|
||||
|
||||
-- [[ Create user commands ]]
|
||||
-- See `:h nvim_create_user_command()` and `:h user-commands`
|
||||
|
||||
-- Create a command `:GitBlameLine` that print the git blame for the current line
|
||||
vim.api.nvim_create_user_command('GitBlameLine', function()
|
||||
local line_number = vim.fn.line('.') -- Get the current line number. See `:h line()`
|
||||
local filename = vim.api.nvim_buf_get_name(0)
|
||||
print(vim.fn.system({ 'git', 'blame', '-L', line_number .. ',+1', filename }))
|
||||
end, { desc = 'Print the git blame for the current line' })
|
||||
|
||||
-- [[ Add optional packages ]]
|
||||
-- Nvim comes bundled with a set of packages that are not enabled by
|
||||
-- default. You can enable any of them by using the `:packadd` command.
|
||||
|
||||
-- For example, to add the "nohlsearch" package to automatically turn off search highlighting after
|
||||
-- 'updatetime' and when going to insert mode
|
||||
vim.cmd('packadd! nohlsearch')
|
@ -1,5 +1,5 @@
|
||||
vim.keymap.set('n', 'gO', function()
|
||||
require('vim.treesitter._headings').show_toc()
|
||||
require('vim.treesitter._headings').show_toc(6)
|
||||
end, { buffer = 0, silent = true, desc = 'Show an Outline of the current buffer' })
|
||||
|
||||
vim.keymap.set('n', ']]', function()
|
||||
|
@ -5,7 +5,9 @@
|
||||
" Contributor: Dorai Sitaram <ds26@gte.com>
|
||||
" C.D. MacEachern <craig.daniel.maceachern@gmail.com>
|
||||
" Phạm Bình An <phambinhanctb2004@gmail.com>
|
||||
" Last Change: 2025 Feb 27
|
||||
" @konfekt
|
||||
" Last Change: 2025 Apr 04
|
||||
" 2025 May 06 by Vim Project update 'path' setting #17267
|
||||
|
||||
if exists("b:did_ftplugin")
|
||||
finish
|
||||
@ -28,6 +30,7 @@ set cpo&vim
|
||||
setlocal comments=:---,:--
|
||||
setlocal commentstring=--\ %s
|
||||
setlocal formatoptions-=t formatoptions+=croql
|
||||
setlocal path-=. " Lua doesn't support importing module in path related to current file like JS
|
||||
|
||||
let &l:define = '\<function\|\<local\%(\s\+function\)\='
|
||||
|
||||
@ -35,7 +38,7 @@ let &l:include = '\<\%(\%(do\|load\)file\|require\)\s*('
|
||||
setlocal includeexpr=s:LuaInclude(v:fname)
|
||||
setlocal suffixesadd=.lua
|
||||
|
||||
let b:undo_ftplugin = "setl cms< com< def< fo< inc< inex< sua<"
|
||||
let b:undo_ftplugin = "setl cms< com< def< fo< inc< inex< sua< pa<"
|
||||
|
||||
if exists("loaded_matchit") && !exists("b:match_words")
|
||||
let b:match_ignorecase = 0
|
||||
@ -78,4 +81,7 @@ function s:LuaInclude(fname) abort
|
||||
return fname
|
||||
endfunction
|
||||
|
||||
let &cpo = s:cpo_save
|
||||
unlet s:cpo_save
|
||||
|
||||
" vim: nowrap sw=2 sts=2 ts=8 noet:
|
||||
|
@ -1,19 +1,18 @@
|
||||
" vim: fdm=marker
|
||||
" Tutor filetype plugin
|
||||
" Language: Tutor (the new tutor plugin)
|
||||
" Maintainer: This runtime file is looking for a new maintainer.
|
||||
" Last Change: 2025 May 10
|
||||
" Contributors: Phạm Bình An <phambinhanctb2004@gmail.com>
|
||||
" Original Author: Felipe Morales <hel.sheep@gmail.com>
|
||||
" Last Change:
|
||||
" 2025 May 10 set b:undo_ftplugin
|
||||
" 2025 May 12 update b:undo_ftplugin
|
||||
|
||||
" Base: {{{1
|
||||
call tutor#SetupVim()
|
||||
|
||||
" Buffer Settings: {{{1
|
||||
setlocal noreadonly
|
||||
if !exists('g:tutor_debug') || g:tutor_debug == 0
|
||||
setlocal buftype=nofile
|
||||
setlocal concealcursor+=inv
|
||||
setlocal conceallevel=2
|
||||
else
|
||||
setlocal buftype=
|
||||
setlocal concealcursor&
|
||||
setlocal conceallevel=0
|
||||
endif
|
||||
setlocal noundofile
|
||||
|
||||
setlocal keywordprg=:help
|
||||
@ -39,7 +38,7 @@ call tutor#SetNormalMappings()
|
||||
sign define tutorok text=✓ texthl=tutorOK
|
||||
sign define tutorbad text=✗ texthl=tutorX
|
||||
|
||||
if !exists('g:tutor_debug') || g:tutor_debug == 0
|
||||
call tutor#ApplyMarks()
|
||||
autocmd! TextChanged,TextChangedI <buffer> call tutor#ApplyMarksOnChanged()
|
||||
endif
|
||||
let b:undo_ftplugin = "setl foldmethod< foldexpr< foldlevel< undofile< keywordprg< iskeyword< |"
|
||||
\ . "call tutor#EnableInteractive(v:false) |"
|
||||
|
||||
" vim: fdm=marker
|
||||
|
@ -3,6 +3,7 @@
|
||||
" Maintainer: See https://github.com/HerringtonDarkholme/yats.vim
|
||||
" Last Change: 2019 Oct 18
|
||||
" 2023 Aug 28 by Vim Project (undo_indent)
|
||||
" 2025 Jun 05 by Vim Project (remove Fixedgq() formatexp, #17452)
|
||||
" Acknowledgement: Based off of vim-ruby maintained by Nikolai Weibull http://vim-ruby.rubyforge.org
|
||||
|
||||
" 0. Initialization {{{1
|
||||
@ -18,10 +19,9 @@ setlocal nosmartindent
|
||||
|
||||
" Now, set up our indentation expression and keys that trigger it.
|
||||
setlocal indentexpr=GetTypescriptIndent()
|
||||
setlocal formatexpr=Fixedgq(v:lnum,v:count)
|
||||
setlocal indentkeys=0{,0},0),0],0\,,!^F,o,O,e
|
||||
|
||||
let b:undo_indent = "setlocal formatexpr< indentexpr< indentkeys< smartindent<"
|
||||
let b:undo_indent = "setlocal indentexpr< indentkeys< smartindent<"
|
||||
|
||||
" Only define the function once.
|
||||
if exists("*GetTypescriptIndent")
|
||||
@ -443,64 +443,3 @@ endfunction
|
||||
|
||||
let &cpo = s:cpo_save
|
||||
unlet s:cpo_save
|
||||
|
||||
function! Fixedgq(lnum, count)
|
||||
let l:tw = &tw ? &tw : 80
|
||||
|
||||
let l:count = a:count
|
||||
let l:first_char = indent(a:lnum) + 1
|
||||
|
||||
if mode() == 'i' " gq was not pressed, but tw was set
|
||||
return 1
|
||||
endif
|
||||
|
||||
" This gq is only meant to do code with strings, not comments
|
||||
if s:IsLineComment(a:lnum, l:first_char) || s:IsInMultilineComment(a:lnum, l:first_char)
|
||||
return 1
|
||||
endif
|
||||
|
||||
if len(getline(a:lnum)) < l:tw && l:count == 1 " No need for gq
|
||||
return 1
|
||||
endif
|
||||
|
||||
" Put all the lines on one line and do normal splitting after that
|
||||
if l:count > 1
|
||||
while l:count > 1
|
||||
let l:count -= 1
|
||||
normal J
|
||||
endwhile
|
||||
endif
|
||||
|
||||
let l:winview = winsaveview()
|
||||
|
||||
call cursor(a:lnum, l:tw + 1)
|
||||
let orig_breakpoint = searchpairpos(' ', '', '\.', 'bcW', '', a:lnum)
|
||||
call cursor(a:lnum, l:tw + 1)
|
||||
let breakpoint = searchpairpos(' ', '', '\.', 'bcW', s:skip_expr, a:lnum)
|
||||
|
||||
" No need for special treatment, normal gq handles edgecases better
|
||||
if breakpoint[1] == orig_breakpoint[1]
|
||||
call winrestview(l:winview)
|
||||
return 1
|
||||
endif
|
||||
|
||||
" Try breaking after string
|
||||
if breakpoint[1] <= indent(a:lnum)
|
||||
call cursor(a:lnum, l:tw + 1)
|
||||
let breakpoint = searchpairpos('\.', '', ' ', 'cW', s:skip_expr, a:lnum)
|
||||
endif
|
||||
|
||||
|
||||
if breakpoint[1] != 0
|
||||
call feedkeys("r\<CR>")
|
||||
else
|
||||
let l:count = l:count - 1
|
||||
endif
|
||||
|
||||
" run gq on new lines
|
||||
if l:count == 1
|
||||
call feedkeys("gqq")
|
||||
endif
|
||||
|
||||
return 0
|
||||
endfunction
|
||||
|
@ -245,7 +245,7 @@ local function parse_line(line)
|
||||
end
|
||||
|
||||
--- @type string?
|
||||
local glob = (line:match('%b[]') or ''):match('^%s*%[(.*)%]%s*$')
|
||||
local glob = line:match('^%s*%[(.*)%]%s*$')
|
||||
if glob then
|
||||
return glob
|
||||
end
|
||||
|
@ -810,6 +810,8 @@ function M.show_toc()
|
||||
fn.setloclist(0, {}, 'a', { title = 'Table of contents' })
|
||||
vim.cmd.lopen()
|
||||
vim.w.qf_toc = bufname
|
||||
-- reload syntax file after setting qf_toc variable
|
||||
vim.bo.filetype = 'qf'
|
||||
end
|
||||
|
||||
return M
|
||||
|
@ -191,7 +191,7 @@ do
|
||||
--- client is attached. If no client is attached, or if a server does not support a capability, an
|
||||
--- error message is displayed rather than exhibiting different behavior.
|
||||
---
|
||||
--- See |grr|, |grn|, |gra|, |gri|, |gO|, |i_CTRL-S|.
|
||||
--- See |grr|, |grn|, |gra|, |gri|, |grt| |gO|, |i_CTRL-S|.
|
||||
do
|
||||
vim.keymap.set('n', 'grn', function()
|
||||
vim.lsp.buf.rename()
|
||||
@ -209,6 +209,10 @@ do
|
||||
vim.lsp.buf.implementation()
|
||||
end, { desc = 'vim.lsp.buf.implementation()' })
|
||||
|
||||
vim.keymap.set('n', 'grt', function()
|
||||
vim.lsp.buf.type_definition()
|
||||
end, { desc = 'vim.lsp.buf.type_definition()' })
|
||||
|
||||
vim.keymap.set('n', 'gO', function()
|
||||
vim.lsp.buf.document_symbol()
|
||||
end, { desc = 'vim.lsp.buf.document_symbol()' })
|
||||
|
@ -106,7 +106,7 @@ local utfs = {
|
||||
--- - env: table<string,string> Set environment variables for the new process. Inherits the
|
||||
--- current environment with `NVIM` set to |v:servername|.
|
||||
--- - clear_env: (boolean) `env` defines the job environment exactly, instead of merging current
|
||||
--- environment.
|
||||
--- environment. Note: if `env` is `nil`, the current environment is used but without `NVIM` set.
|
||||
--- - stdin: (string|string[]|boolean) If `true`, then a pipe to stdin is opened and can be written
|
||||
--- to via the `write()` method to SystemObj. If string or string[] then will be written to stdin
|
||||
--- and closed. Defaults to `false`.
|
||||
@ -399,22 +399,23 @@ local VIM_CMD_ARG_MAX = 20
|
||||
|
||||
--- Executes Vimscript (|Ex-commands|).
|
||||
---
|
||||
--- Note that `vim.cmd` can be indexed with a command name to return a callable function to the
|
||||
--- command.
|
||||
--- Can be indexed with a command name to get a function, thus you can write `vim.cmd.echo(…)`
|
||||
--- instead of `vim.cmd{cmd='echo',…}`.
|
||||
---
|
||||
--- Example:
|
||||
--- Examples:
|
||||
---
|
||||
--- ```lua
|
||||
--- -- Single command:
|
||||
--- vim.cmd('echo 42')
|
||||
--- -- Multiline script:
|
||||
--- vim.cmd([[
|
||||
--- augroup My_group
|
||||
--- augroup my.group
|
||||
--- autocmd!
|
||||
--- autocmd FileType c setlocal cindent
|
||||
--- augroup END
|
||||
--- ]])
|
||||
---
|
||||
--- -- Ex command :echo "foo"
|
||||
--- -- Note string literals need to be double quoted.
|
||||
--- -- Ex command :echo "foo". Note: string literals must be double-quoted.
|
||||
--- vim.cmd('echo "foo"')
|
||||
--- vim.cmd { cmd = 'echo', args = { '"foo"' } }
|
||||
--- vim.cmd.echo({ args = { '"foo"' } })
|
||||
@ -422,22 +423,19 @@ local VIM_CMD_ARG_MAX = 20
|
||||
---
|
||||
--- -- Ex command :write! myfile.txt
|
||||
--- vim.cmd('write! myfile.txt')
|
||||
--- vim.cmd { cmd = 'write', args = { "myfile.txt" }, bang = true }
|
||||
--- vim.cmd.write { args = { "myfile.txt" }, bang = true }
|
||||
--- vim.cmd.write { "myfile.txt", bang = true }
|
||||
--- vim.cmd { cmd = 'write', args = { 'myfile.txt' }, bang = true }
|
||||
--- vim.cmd.write { args = { 'myfile.txt' }, bang = true }
|
||||
--- vim.cmd.write { 'myfile.txt', bang = true }
|
||||
---
|
||||
--- -- Ex command :colorscheme blue
|
||||
--- vim.cmd('colorscheme blue')
|
||||
--- vim.cmd.colorscheme('blue')
|
||||
--- -- Ex command :vertical resize +2
|
||||
--- vim.cmd.resize({ '+2', mods = { vertical = true } })
|
||||
--- ```
|
||||
---
|
||||
---@diagnostic disable-next-line: undefined-doc-param
|
||||
---@param command string|table Command(s) to execute.
|
||||
--- If a string, executes multiple lines of Vimscript at once. In this
|
||||
--- case, it is an alias to |nvim_exec2()|, where `opts.output` is set
|
||||
--- to false. Thus it works identical to |:source|.
|
||||
--- If a table, executes a single command. In this case, it is an alias
|
||||
--- to |nvim_cmd()| where `opts` is empty.
|
||||
--- - The string form supports multiline Vimscript (alias to |nvim_exec2()|, behaves
|
||||
--- like |:source|).
|
||||
--- - The table form executes a single command (alias to |nvim_cmd()|).
|
||||
---@see |ex-cmd-index|
|
||||
vim.cmd = setmetatable({}, {
|
||||
__call = function(_, command)
|
||||
|
@ -3,13 +3,15 @@ local M = {}
|
||||
--- @param module string
|
||||
---@return string
|
||||
function M.includeexpr(module)
|
||||
local fname = module:gsub('%.', '/')
|
||||
module = module:gsub('%.', '/')
|
||||
|
||||
local root = vim.fs.root(vim.api.nvim_buf_get_name(0), 'lua') or vim.fn.getcwd()
|
||||
for _, suf in ipairs { '.lua', '/init.lua' } do
|
||||
local path = vim.fs.joinpath(root, 'lua', fname .. suf)
|
||||
if vim.uv.fs_stat(path) then
|
||||
return path
|
||||
for _, fname in ipairs { module, vim.fs.joinpath(root, 'lua', module) } do
|
||||
for _, suf in ipairs { '.lua', '/init.lua' } do
|
||||
local path = fname .. suf
|
||||
if vim.uv.fs_stat(path) then
|
||||
return path
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
5
runtime/lua/vim/_meta/api.lua
generated
5
runtime/lua/vim/_meta/api.lua
generated
@ -1662,10 +1662,7 @@ function vim.api.nvim_notify(msg, log_level, opts) end
|
||||
---
|
||||
--- ```lua
|
||||
--- vim.api.nvim_create_user_command('TermHl', function()
|
||||
--- local b = vim.api.nvim_create_buf(false, true)
|
||||
--- local chan = vim.api.nvim_open_term(b, {})
|
||||
--- vim.api.nvim_chan_send(chan, table.concat(vim.api.nvim_buf_get_lines(0, 0, -1, false), '\n'))
|
||||
--- vim.api.nvim_win_set_buf(0, b)
|
||||
--- vim.api.nvim_open_term(0, {})
|
||||
--- end, { desc = 'Highlights ANSI termcodes in curbuf' })
|
||||
--- ```
|
||||
---
|
||||
|
@ -297,3 +297,18 @@
|
||||
--- A list of dictionaries with information about
|
||||
--- undo blocks.
|
||||
--- @field entries vim.fn.undotree.entry[]
|
||||
|
||||
--- @class vim.fn.winlayout.leaf
|
||||
--- @field [1] "leaf" Node type
|
||||
--- @field [2] integer winid
|
||||
|
||||
--- @class vim.fn.winlayout.branch
|
||||
--- @field [1] "row" | "col" Node type
|
||||
--- @field [2] (vim.fn.winlayout.leaf|vim.fn.winlayout.branch)[] children
|
||||
|
||||
--- @class vim.fn.winlayout.empty
|
||||
|
||||
--- @alias vim.fn.winlayout.ret
|
||||
--- | vim.fn.winlayout.leaf
|
||||
--- | vim.fn.winlayout.branch
|
||||
--- | vim.fn.winlayout.empty
|
||||
|
45
runtime/lua/vim/_meta/options.lua
generated
45
runtime/lua/vim/_meta/options.lua
generated
@ -655,8 +655,8 @@ vim.bo.bl = vim.bo.buflisted
|
||||
--- "acwrite" implies that the buffer name is not related to a file, like
|
||||
--- "nofile", but it will be written. Thus, in contrast to "nofile" and
|
||||
--- "nowrite", ":w" does work and a modified buffer can't be abandoned
|
||||
--- without saving. For writing there must be matching `BufWriteCmd|,
|
||||
--- |FileWriteCmd` or `FileAppendCmd` autocommands.
|
||||
--- without saving. For writing there must be matching `BufWriteCmd`,
|
||||
--- `FileWriteCmd` or `FileAppendCmd` autocommands.
|
||||
---
|
||||
--- @type ''|'acwrite'|'help'|'nofile'|'nowrite'|'quickfix'|'terminal'|'prompt'
|
||||
vim.o.buftype = ""
|
||||
@ -2015,10 +2015,21 @@ vim.bo.et = vim.bo.expandtab
|
||||
--- in the `trust` list. Use `:trust` to manage trusted files. See also
|
||||
--- `vim.secure.read()`.
|
||||
---
|
||||
--- To get its own location, Lua exrc files can use `debug.getinfo()`.
|
||||
---
|
||||
--- Compare 'exrc' to `editorconfig`:
|
||||
--- - 'exrc' can execute any code; editorconfig only specifies settings.
|
||||
--- - 'exrc' is Nvim-specific; editorconfig works in other editors.
|
||||
---
|
||||
--- To achieve project-local LSP configuration:
|
||||
--- 1. Enable 'exrc'.
|
||||
--- 2. Place LSP configs at ".nvim/lsp/*.lua" in your project root.
|
||||
--- 3. Create ".nvim.lua" in your project root directory with this line:
|
||||
---
|
||||
--- ```lua
|
||||
--- vim.cmd[[set runtimepath+=.nvim]]
|
||||
--- ```
|
||||
---
|
||||
--- This option cannot be set from a `modeline` or in the `sandbox`, for
|
||||
--- security reasons.
|
||||
---
|
||||
@ -3151,8 +3162,8 @@ vim.o.ims = vim.o.imsearch
|
||||
vim.bo.imsearch = vim.o.imsearch
|
||||
vim.bo.ims = vim.bo.imsearch
|
||||
|
||||
--- When nonempty, shows the effects of `:substitute`, `:smagic|,
|
||||
--- |:snomagic` and user commands with the `:command-preview` flag as you
|
||||
--- When nonempty, shows the effects of `:substitute`, `:smagic`,
|
||||
--- `:snomagic` and user commands with the `:command-preview` flag as you
|
||||
--- type.
|
||||
---
|
||||
--- Possible values:
|
||||
@ -3491,8 +3502,8 @@ vim.go.js = vim.go.joinspaces
|
||||
--- when navigating backwards in the jumplist and then
|
||||
--- jumping to a location. `jumplist-stack`
|
||||
---
|
||||
--- view When moving through the jumplist, `changelist|,
|
||||
--- |alternate-file` or using `mark-motions` try to
|
||||
--- view When moving through the jumplist, `changelist`,
|
||||
--- `alternate-file` or using `mark-motions` try to
|
||||
--- restore the `mark-view` in which the action occurred.
|
||||
---
|
||||
--- clean Remove unloaded buffers from the jumplist.
|
||||
@ -5239,9 +5250,14 @@ vim.go.sect = vim.go.sections
|
||||
--- the end of line the line break still isn't included.
|
||||
--- When "exclusive" is used, cursor position in visual mode will be
|
||||
--- adjusted for inclusive motions `inclusive-motion-selection-exclusive`.
|
||||
--- Note that when "exclusive" is used and selecting from the end
|
||||
--- backwards, you cannot include the last character of a line, when
|
||||
--- starting in Normal mode and 'virtualedit' empty.
|
||||
---
|
||||
--- Note:
|
||||
--- - When "exclusive" is used and selecting from the end backwards, you
|
||||
--- cannot include the last character of a line, when starting in Normal
|
||||
--- mode and 'virtualedit' empty.
|
||||
--- - when "exclusive" is used with a single character visual selection,
|
||||
--- Vim will behave as if the 'selection' is inclusive (in other words,
|
||||
--- you cannot visually select an empty region).
|
||||
---
|
||||
--- @type 'inclusive'|'exclusive'|'old'
|
||||
vim.o.selection = "inclusive"
|
||||
@ -5627,8 +5643,8 @@ vim.go.ssl = vim.go.shellslash
|
||||
--- and the 'shell' command does not need to support redirection.
|
||||
--- The advantage of using a temp file is that the file type and encoding
|
||||
--- can be detected.
|
||||
--- The `FilterReadPre`, `FilterReadPost` and `FilterWritePre|,
|
||||
--- |FilterWritePost` autocommands event are not triggered when
|
||||
--- The `FilterReadPre`, `FilterReadPost` and `FilterWritePre`,
|
||||
--- `FilterWritePost` autocommands event are not triggered when
|
||||
--- 'shelltemp' is off.
|
||||
--- `system()` does not respect this option, it always uses pipes.
|
||||
---
|
||||
@ -6198,8 +6214,8 @@ vim.bo.spo = vim.bo.spelloptions
|
||||
---
|
||||
--- expr:{expr} Evaluate expression {expr}. Use a function to avoid
|
||||
--- trouble with spaces. Best is to call a function
|
||||
--- without arguments, see `expr-option-function|.
|
||||
--- |v:val` holds the badly spelled word. The expression
|
||||
--- without arguments, see `expr-option-function`.
|
||||
--- `v:val` holds the badly spelled word. The expression
|
||||
--- must evaluate to a List of Lists, each with a
|
||||
--- suggestion and a score.
|
||||
--- Example:
|
||||
@ -6343,8 +6359,7 @@ vim.o.stc = vim.o.statuscolumn
|
||||
vim.wo.statuscolumn = vim.o.statuscolumn
|
||||
vim.wo.stc = vim.wo.statuscolumn
|
||||
|
||||
--- When non-empty, this option determines the content of the status line.
|
||||
--- Also see `status-line`.
|
||||
--- Sets the `status-line`.
|
||||
---
|
||||
--- The option consists of printf style '%' items interspersed with
|
||||
--- normal text. Each status line item is of the form:
|
||||
|
9
runtime/lua/vim/_meta/vimfn.lua
generated
9
runtime/lua/vim/_meta/vimfn.lua
generated
@ -1801,7 +1801,8 @@ function vim.fn.exp(expr) end
|
||||
--- <SID> "<SNR>123_" where "123" is the
|
||||
--- current script ID |<SID>|
|
||||
--- <script> sourced script file, or script file
|
||||
--- where the current function was defined
|
||||
--- where the current function was defined.
|
||||
--- Use |debug.getinfo()| in Lua scripts.
|
||||
--- <stack> call stack
|
||||
--- <cword> word under the cursor
|
||||
--- <cWORD> WORD under the cursor
|
||||
@ -3692,6 +3693,10 @@ function vim.fn.getreginfo(regname) end
|
||||
--- - It is evaluated in current window context, which makes a
|
||||
--- difference if the buffer is displayed in a window with
|
||||
--- different 'virtualedit' or 'list' values.
|
||||
--- - When specifying an exclusive selection and {pos1} and {pos2}
|
||||
--- are equal, the returned list contains a single character as
|
||||
--- if selection is inclusive, to match the behavior of an empty
|
||||
--- exclusive selection in Visual mode.
|
||||
---
|
||||
--- Examples: >vim
|
||||
--- xnoremap <CR>
|
||||
@ -10929,7 +10934,7 @@ function vim.fn.winheight(nr) end
|
||||
--- <
|
||||
---
|
||||
--- @param tabnr? integer
|
||||
--- @return any[]
|
||||
--- @return vim.fn.winlayout.ret
|
||||
function vim.fn.winlayout(tabnr) end
|
||||
|
||||
--- The result is a Number, which is the screen line of the cursor
|
||||
|
@ -210,12 +210,15 @@ end
|
||||
--- @param clear_env? boolean
|
||||
--- @return string[]?
|
||||
local function setup_env(env, clear_env)
|
||||
if clear_env then
|
||||
return env
|
||||
if not env and clear_env then
|
||||
return
|
||||
end
|
||||
|
||||
--- @type table<string,string|number>
|
||||
env = vim.tbl_extend('force', base_env(), env or {})
|
||||
env = env or {}
|
||||
if not clear_env then
|
||||
--- @type table<string,string|number>
|
||||
env = vim.tbl_extend('force', base_env(), env)
|
||||
end
|
||||
|
||||
local renv = {} --- @type string[]
|
||||
for k, v in pairs(env) do
|
||||
@ -245,7 +248,13 @@ local function spawn(cmd, opts, on_exit, on_error)
|
||||
local handle, pid_or_err = uv.spawn(cmd, opts, on_exit)
|
||||
if not handle then
|
||||
on_error()
|
||||
error(('%s: "%s"'):format(pid_or_err, cmd))
|
||||
if opts.cwd and not uv.fs_stat(opts.cwd) then
|
||||
error(("%s (cwd): '%s'"):format(pid_or_err, opts.cwd))
|
||||
elseif vim.fn.executable(cmd) == 0 then
|
||||
error(("%s (cmd): '%s'"):format(pid_or_err, cmd))
|
||||
else
|
||||
error(pid_or_err)
|
||||
end
|
||||
end
|
||||
return handle, pid_or_err --[[@as integer]]
|
||||
end
|
||||
|
@ -1442,6 +1442,7 @@ M.handlers.signs = {
|
||||
vim.validate('bufnr', bufnr, 'number')
|
||||
vim.validate('diagnostics', diagnostics, vim.islist, 'a list of diagnostics')
|
||||
vim.validate('opts', opts, 'table', true)
|
||||
vim.validate('opts.signs', (opts and opts or {}).signs, 'table', true)
|
||||
|
||||
bufnr = vim._resolve_bufnr(bufnr)
|
||||
opts = opts or {}
|
||||
|
@ -2605,7 +2605,7 @@ end
|
||||
--- Filetype mappings can be added either by extension or by filename (either
|
||||
--- the "tail" or the full file path). The full file path is checked first,
|
||||
--- followed by the file name. If a match is not found using the filename, then
|
||||
--- the filename is matched against the list of |lua-patterns| (sorted by priority)
|
||||
--- the filename is matched against the list of |lua-pattern|s (sorted by priority)
|
||||
--- until a match is found. Lastly, if pattern matching does not find a
|
||||
--- filetype, then the file extension is used.
|
||||
---
|
||||
|
@ -6,7 +6,7 @@
|
||||
---
|
||||
--- >lua
|
||||
--- if vim.uv.fs_stat(file) then
|
||||
--- vim.print("file exists")
|
||||
--- vim.print('file exists')
|
||||
--- end
|
||||
--- <
|
||||
|
||||
@ -19,21 +19,21 @@ local sysname = uv.os_uname().sysname:lower()
|
||||
local iswin = not not (sysname:find('windows') or sysname:find('mingw'))
|
||||
local os_sep = iswin and '\\' or '/'
|
||||
|
||||
--- Iterate over all the parents of the given path.
|
||||
--- Iterate over all the parents of the given path (not expanded/resolved, the caller must do that).
|
||||
---
|
||||
--- Example:
|
||||
---
|
||||
--- ```lua
|
||||
--- local root_dir
|
||||
--- for dir in vim.fs.parents(vim.api.nvim_buf_get_name(0)) do
|
||||
--- if vim.fn.isdirectory(dir .. "/.git") == 1 then
|
||||
--- if vim.fn.isdirectory(dir .. '/.git') == 1 then
|
||||
--- root_dir = dir
|
||||
--- break
|
||||
--- end
|
||||
--- end
|
||||
---
|
||||
--- if root_dir then
|
||||
--- print("Found git repository at", root_dir)
|
||||
--- print('Found git repository at', root_dir)
|
||||
--- end
|
||||
--- ```
|
||||
---
|
||||
@ -55,7 +55,7 @@ function M.parents(start)
|
||||
start
|
||||
end
|
||||
|
||||
--- Return the parent directory of the given path
|
||||
--- Gets the parent directory of the given path (not expanded/resolved, the caller must do that).
|
||||
---
|
||||
---@since 10
|
||||
---@generic T : string|nil
|
||||
@ -124,6 +124,23 @@ function M.joinpath(...)
|
||||
return (path:gsub('//+', '/'))
|
||||
end
|
||||
|
||||
--- @class vim.fs.dir.Opts
|
||||
--- @inlinedoc
|
||||
---
|
||||
--- How deep the traverse.
|
||||
--- (default: `1`)
|
||||
--- @field depth? integer
|
||||
---
|
||||
--- Predicate to control traversal.
|
||||
--- Return false to stop searching the current directory.
|
||||
--- Only useful when depth > 1
|
||||
--- Return an iterator over the items located in {path}
|
||||
--- @field skip? (fun(dir_name: string): boolean)
|
||||
---
|
||||
--- Follow symbolic links.
|
||||
--- (default: `false`)
|
||||
--- @field follow? boolean
|
||||
|
||||
---@alias Iterator fun(): string?, string?
|
||||
|
||||
--- Return an iterator over the items located in {path}
|
||||
@ -131,13 +148,7 @@ end
|
||||
---@since 10
|
||||
---@param path (string) An absolute or relative path to the directory to iterate
|
||||
--- over. The path is first normalized |vim.fs.normalize()|.
|
||||
--- @param opts table|nil Optional keyword arguments:
|
||||
--- - depth: integer|nil How deep the traverse (default 1)
|
||||
--- - skip: (fun(dir_name: string): boolean)|nil Predicate
|
||||
--- to control traversal. Return false to stop searching the current directory.
|
||||
--- Only useful when depth > 1
|
||||
--- - follow: boolean|nil Follow symbolic links. (default: false)
|
||||
---
|
||||
---@param opts? vim.fs.dir.Opts Optional keyword arguments:
|
||||
---@return Iterator over items in {path}. Each iteration yields two values: "name" and "type".
|
||||
--- "name" is the basename of the item relative to {path}.
|
||||
--- "type" is one of the following:
|
||||
@ -234,16 +245,17 @@ end
|
||||
--- Examples:
|
||||
---
|
||||
--- ```lua
|
||||
--- -- list all test directories under the runtime directory
|
||||
--- local test_dirs = vim.fs.find(
|
||||
--- {'test', 'tst', 'testdir'},
|
||||
--- {limit = math.huge, type = 'directory', path = './runtime/'}
|
||||
--- -- List all test directories under the runtime directory.
|
||||
--- local dirs = vim.fs.find(
|
||||
--- { 'test', 'tst', 'testdir' },
|
||||
--- { limit = math.huge, type = 'directory', path = './runtime/' }
|
||||
--- )
|
||||
---
|
||||
--- -- get all files ending with .cpp or .hpp inside lib/
|
||||
--- local cpp_hpp = vim.fs.find(function(name, path)
|
||||
--- -- Get all "lib/*.cpp" and "lib/*.hpp" files, using Lua patterns.
|
||||
--- -- Or use `vim.glob.to_lpeg(…):match(…)` for glob/wildcard matching.
|
||||
--- local files = vim.fs.find(function(name, path)
|
||||
--- return name:match('.*%.[ch]pp$') and path:match('[/\\]lib$')
|
||||
--- end, {limit = math.huge, type = 'file'})
|
||||
--- end, { limit = math.huge, type = 'file' })
|
||||
--- ```
|
||||
---
|
||||
---@since 10
|
||||
@ -255,7 +267,7 @@ end
|
||||
---
|
||||
--- The function should return `true` if the given item is considered a match.
|
||||
---
|
||||
---@param opts vim.fs.find.Opts Optional keyword arguments:
|
||||
---@param opts? vim.fs.find.Opts Optional keyword arguments:
|
||||
---@return (string[]) # Normalized paths |vim.fs.normalize()| of all matching items
|
||||
function M.find(names, opts)
|
||||
opts = opts or {}
|
||||
@ -374,7 +386,7 @@ end
|
||||
--- If the buffer is unnamed (has no backing file) or has a non-empty 'buftype' then the search
|
||||
--- begins from Nvim's |current-directory|.
|
||||
---
|
||||
--- Example:
|
||||
--- Examples:
|
||||
---
|
||||
--- ```lua
|
||||
--- -- Find the root of a Python project, starting from file 'main.py'
|
||||
@ -387,14 +399,21 @@ end
|
||||
--- vim.fs.root(0, function(name, path)
|
||||
--- return name:match('%.csproj$') ~= nil
|
||||
--- end)
|
||||
---
|
||||
--- -- Find the first ancestor directory containing EITHER "stylua.toml" or ".luarc.json"; if
|
||||
--- -- not found, find the first ancestor containing ".git":
|
||||
--- vim.fs.root(0, { { 'stylua.toml', '.luarc.json' }, '.git' })
|
||||
--- ```
|
||||
---
|
||||
--- @since 12
|
||||
--- @param source integer|string Buffer number (0 for current buffer) or file path (absolute or
|
||||
--- relative to the |current-directory|) to begin the search from.
|
||||
--- @param marker (string|string[]|fun(name: string, path: string): boolean) A marker, or list
|
||||
--- of markers, to search for. If a function, the function is called for each
|
||||
--- evaluated item and should return true if {name} and {path} are a match.
|
||||
--- @param marker (string|string[]|fun(name: string, path: string): boolean)[]|string|fun(name: string, path: string): boolean
|
||||
--- Filename, function, or list thereof, that decides how to find the root. To
|
||||
--- indicate "equal priority", specify items in a nested list `{ { 'a.txt', 'b.lua' }, … }`.
|
||||
--- A function item must return true if `name` and `path` are a match. Each item
|
||||
--- (which may itself be a nested list) is evaluated in-order against all ancestors,
|
||||
--- until a match is found.
|
||||
--- @return string? # Directory path containing one of the given markers, or nil if no directory was
|
||||
--- found.
|
||||
function M.root(source, marker)
|
||||
@ -414,16 +433,19 @@ function M.root(source, marker)
|
||||
error('invalid type for argument "source": expected string or buffer number')
|
||||
end
|
||||
|
||||
local paths = M.find(marker, {
|
||||
upward = true,
|
||||
path = vim.fn.fnamemodify(path, ':p:h'),
|
||||
})
|
||||
local markers = type(marker) == 'table' and marker or { marker }
|
||||
for _, mark in ipairs(markers) do
|
||||
local paths = M.find(mark, {
|
||||
upward = true,
|
||||
path = vim.fn.fnamemodify(path, ':p:h'),
|
||||
})
|
||||
|
||||
if #paths == 0 then
|
||||
return nil
|
||||
if #paths ~= 0 then
|
||||
return vim.fs.dirname(paths[1])
|
||||
end
|
||||
end
|
||||
|
||||
return vim.fs.dirname(paths[1])
|
||||
return nil
|
||||
end
|
||||
|
||||
--- Split a Windows path into a prefix and a body, such that the body can be processed like a POSIX
|
||||
|
@ -1,16 +1,16 @@
|
||||
--- @brief
|
||||
---<pre>help
|
||||
--- vim.health is a minimal framework to help users troubleshoot configuration and
|
||||
--- any other environment conditions that a plugin might care about. Nvim ships
|
||||
--- with healthchecks for configuration, performance, python support, ruby
|
||||
--- support, clipboard support, and more.
|
||||
---
|
||||
--- To run all healthchecks, use: >vim
|
||||
--- vim.health is a minimal framework to help users troubleshoot configuration and any other
|
||||
--- environment conditions that a plugin might care about. Nvim ships with healthchecks for
|
||||
--- configuration, performance, python support, ruby support, clipboard support, and more.
|
||||
---
|
||||
--- :checkhealth
|
||||
--- <
|
||||
--- To run all healthchecks, use:
|
||||
--- ```vim
|
||||
--- :checkhealth
|
||||
--- ```
|
||||
--- Plugin authors are encouraged to write new healthchecks. |health-dev|
|
||||
---
|
||||
---<pre>help
|
||||
--- COMMANDS *health-commands*
|
||||
---
|
||||
--- *:che* *:checkhealth*
|
||||
@ -46,7 +46,6 @@
|
||||
--- q Closes the window.
|
||||
---
|
||||
--- Global configuration:
|
||||
---
|
||||
--- *g:health*
|
||||
--- g:health Dictionary with the following optional keys:
|
||||
--- - `style` (`'float'|nil`) Set to "float" to display :checkhealth in
|
||||
@ -55,57 +54,69 @@
|
||||
--- Example: >lua
|
||||
--- vim.g.health = { style = 'float' }
|
||||
---
|
||||
---</pre>
|
||||
---
|
||||
--- Local configuration:
|
||||
---
|
||||
--- Checkhealth sets its buffer filetype to "checkhealth". You can customize the buffer by handling
|
||||
--- the |FileType| event. For example if you don't want emojis in the health report:
|
||||
--- ```vim
|
||||
--- autocmd FileType checkhealth :set modifiable | silent! %s/\v( ?[^\x00-\x7F])//g
|
||||
--- ```
|
||||
---
|
||||
---<pre>help
|
||||
--- --------------------------------------------------------------------------------
|
||||
--- Create a healthcheck *health-dev*
|
||||
---</pre>
|
||||
---
|
||||
--- Healthchecks are functions that check the user environment, configuration, or
|
||||
--- any other prerequisites that a plugin cares about. Nvim ships with
|
||||
--- healthchecks in:
|
||||
--- - $VIMRUNTIME/autoload/health/
|
||||
--- - $VIMRUNTIME/lua/vim/lsp/health.lua
|
||||
--- - $VIMRUNTIME/lua/vim/treesitter/health.lua
|
||||
--- - and more...
|
||||
--- Healthchecks are functions that check the user environment, configuration, or any other
|
||||
--- prerequisites that a plugin cares about. Nvim ships with healthchecks in:
|
||||
--- - $VIMRUNTIME/autoload/health/
|
||||
--- - $VIMRUNTIME/lua/vim/lsp/health.lua
|
||||
--- - $VIMRUNTIME/lua/vim/treesitter/health.lua
|
||||
--- - and more...
|
||||
---
|
||||
--- To add a new healthcheck for your own plugin, simply create a "health.lua"
|
||||
--- module on 'runtimepath' that returns a table with a "check()" function. Then
|
||||
--- |:checkhealth| will automatically find and invoke the function.
|
||||
--- To add a new healthcheck for your own plugin, simply create a "health.lua" module on
|
||||
--- 'runtimepath' that returns a table with a "check()" function. Then |:checkhealth| will
|
||||
--- automatically find and invoke the function.
|
||||
---
|
||||
--- For example if your plugin is named "foo", define your healthcheck module at
|
||||
--- one of these locations (on 'runtimepath'):
|
||||
--- - lua/foo/health/init.lua
|
||||
--- - lua/foo/health.lua
|
||||
--- - lua/foo/health/init.lua
|
||||
--- - lua/foo/health.lua
|
||||
---
|
||||
--- If your plugin also provides a submodule named "bar" for which you want
|
||||
--- a separate healthcheck, define the healthcheck at one of these locations:
|
||||
--- - lua/foo/bar/health/init.lua
|
||||
--- - lua/foo/bar/health.lua
|
||||
--- If your plugin also provides a submodule named "bar" for which you want a separate healthcheck,
|
||||
--- define the healthcheck at one of these locations:
|
||||
--- - lua/foo/bar/health/init.lua
|
||||
--- - lua/foo/bar/health.lua
|
||||
---
|
||||
--- All such health modules must return a Lua table containing a `check()`
|
||||
--- function.
|
||||
--- All such health modules must return a Lua table containing a `check()` function.
|
||||
---
|
||||
--- Copy this sample code into `lua/foo/health.lua`, replacing "foo" in the path
|
||||
--- with your plugin name: >lua
|
||||
--- Copy this sample code into `lua/foo/health.lua`, replacing "foo" in the path with your plugin
|
||||
--- name:
|
||||
---
|
||||
--- local M = {}
|
||||
--- ```lua
|
||||
--- local M = {}
|
||||
---
|
||||
--- M.check = function()
|
||||
--- vim.health.start("foo report")
|
||||
--- -- make sure setup function parameters are ok
|
||||
--- if check_setup() then
|
||||
--- vim.health.ok("Setup is correct")
|
||||
--- else
|
||||
--- vim.health.error("Setup is incorrect")
|
||||
--- end
|
||||
--- -- do some more checking
|
||||
--- -- ...
|
||||
--- end
|
||||
--- M.check = function()
|
||||
--- vim.health.start("foo report")
|
||||
--- -- make sure setup function parameters are ok
|
||||
--- if check_setup() then
|
||||
--- vim.health.ok("Setup is correct")
|
||||
--- else
|
||||
--- vim.health.error("Setup is incorrect")
|
||||
--- end
|
||||
--- -- do some more checking
|
||||
--- -- ...
|
||||
--- end
|
||||
---
|
||||
--- return M
|
||||
---</pre>
|
||||
--- return M
|
||||
--- ```
|
||||
|
||||
local M = {}
|
||||
|
||||
local s_output = {} ---@type string[]
|
||||
local check_summary = { warn = 0, error = 0 }
|
||||
|
||||
-- From a path return a list [{name}, {func}, {type}] representing a healthcheck
|
||||
local function filepath_to_healthcheck(path)
|
||||
@ -286,6 +297,7 @@ end
|
||||
function M.warn(msg, ...)
|
||||
local input = format_report_message('⚠️ WARNING', msg, ...)
|
||||
collect_output(input)
|
||||
check_summary['warn'] = check_summary['warn'] + 1
|
||||
end
|
||||
|
||||
--- Reports an error.
|
||||
@ -295,6 +307,7 @@ end
|
||||
function M.error(msg, ...)
|
||||
local input = format_report_message('❌ ERROR', msg, ...)
|
||||
collect_output(input)
|
||||
check_summary['error'] = check_summary['error'] + 1
|
||||
end
|
||||
|
||||
local path2name = function(path)
|
||||
@ -341,6 +354,23 @@ M._complete = function()
|
||||
return rv
|
||||
end
|
||||
|
||||
--- Gets the results heading for the current report section.
|
||||
---
|
||||
---@return string
|
||||
local function get_summary()
|
||||
local s = ''
|
||||
local errors = check_summary['error']
|
||||
local warns = check_summary['warn']
|
||||
|
||||
s = s .. (warns > 0 and (' %2d ⚠️'):format(warns) or '')
|
||||
s = s .. (errors > 0 and (' %2d ❌'):format(errors) or '')
|
||||
if errors == 0 and warns == 0 then
|
||||
s = s .. '✅'
|
||||
end
|
||||
|
||||
return s
|
||||
end
|
||||
|
||||
--- Runs the specified healthchecks.
|
||||
--- Runs all discovered healthchecks if plugin_names is empty.
|
||||
---
|
||||
@ -353,25 +383,29 @@ function M._check(mods, plugin_names)
|
||||
|
||||
local emptybuf = vim.fn.bufnr('$') == 1 and vim.fn.getline(1) == '' and 1 == vim.fn.line('$')
|
||||
|
||||
local bufnr = vim.api.nvim_create_buf(true, true)
|
||||
local bufnr ---@type integer
|
||||
if
|
||||
vim.g.health
|
||||
and type(vim.g.health) == 'table'
|
||||
and vim.tbl_get(vim.g.health, 'style') == 'float'
|
||||
then
|
||||
local max_height = math.floor(vim.o.lines * 0.8)
|
||||
local available_lines = vim.o.lines - 12
|
||||
local max_height = math.min(math.floor(vim.o.lines * 0.8), available_lines)
|
||||
local max_width = 80
|
||||
local float_bufnr, float_winid = vim.lsp.util.open_floating_preview({}, '', {
|
||||
local float_winid
|
||||
bufnr, float_winid = vim.lsp.util.open_floating_preview({}, '', {
|
||||
height = max_height,
|
||||
width = max_width,
|
||||
offset_x = math.floor((vim.o.columns - max_width) / 2),
|
||||
offset_y = math.floor((vim.o.lines - max_height) / 2) - 1,
|
||||
offset_y = math.floor((available_lines - max_height) / 2),
|
||||
relative = 'editor',
|
||||
close_events = {},
|
||||
})
|
||||
vim.api.nvim_set_current_win(float_winid)
|
||||
vim.bo[float_bufnr].modifiable = true
|
||||
vim.bo[bufnr].modifiable = true
|
||||
vim.wo[float_winid].list = false
|
||||
else
|
||||
bufnr = vim.api.nvim_create_buf(true, true)
|
||||
-- When no command modifiers are used:
|
||||
-- - If the current buffer is empty, open healthcheck directly.
|
||||
-- - If not specified otherwise open healthcheck in a tab.
|
||||
@ -383,7 +417,6 @@ function M._check(mods, plugin_names)
|
||||
vim.cmd.bwipe('health://')
|
||||
end
|
||||
vim.cmd.file('health://')
|
||||
vim.cmd.setfiletype('checkhealth')
|
||||
|
||||
-- This should only happen when doing `:checkhealth vim`
|
||||
if next(healthchecks) == nil then
|
||||
@ -397,9 +430,9 @@ function M._check(mods, plugin_names)
|
||||
local func = value[1]
|
||||
local type = value[2]
|
||||
s_output = {}
|
||||
check_summary = { warn = 0, error = 0 }
|
||||
|
||||
if func == '' then
|
||||
s_output = {}
|
||||
M.error('No healthcheck found for "' .. name .. '" plugin.')
|
||||
end
|
||||
if type == 'v' then
|
||||
@ -420,10 +453,12 @@ function M._check(mods, plugin_names)
|
||||
M.error('The healthcheck report for "' .. name .. '" plugin is empty.')
|
||||
end
|
||||
|
||||
local report = get_summary()
|
||||
local replen = vim.fn.strwidth(report)
|
||||
local header = {
|
||||
string.rep('=', 78),
|
||||
-- Example: `foo.health: [ …] require("foo.health").check()`
|
||||
('%s: %s%s'):format(name, (' '):rep(76 - name:len() - func:len()), func),
|
||||
-- Example: `foo.health: [ …] 1 ⚠️ 5 ❌`
|
||||
('%s: %s%s'):format(name, (' '):rep(76 - name:len() - replen), report),
|
||||
'',
|
||||
}
|
||||
|
||||
@ -461,6 +496,7 @@ function M._check(mods, plugin_names)
|
||||
|
||||
-- Once we're done writing checks, set nomodifiable.
|
||||
vim.bo[bufnr].modifiable = false
|
||||
vim.cmd.setfiletype('checkhealth')
|
||||
end
|
||||
|
||||
return M
|
||||
|
@ -87,9 +87,9 @@ local function check_config()
|
||||
health.error(
|
||||
'Locale does not support UTF-8. Unicode characters may not display correctly.'
|
||||
.. ('\n$LANG=%s $LC_ALL=%s $LC_CTYPE=%s'):format(
|
||||
vim.env.LANG,
|
||||
vim.env.LC_ALL,
|
||||
vim.env.LC_CTYPE
|
||||
vim.env.LANG or '',
|
||||
vim.env.LC_ALL or '',
|
||||
vim.env.LC_CTYPE or ''
|
||||
),
|
||||
{
|
||||
'If using tmux, try the -u option.',
|
||||
|
@ -147,7 +147,7 @@ end
|
||||
--- @param config vim.lsp.ClientConfig
|
||||
--- @return boolean
|
||||
local function reuse_client_default(client, config)
|
||||
if client.name ~= config.name then
|
||||
if client.name ~= config.name or client:is_stopped() then
|
||||
return false
|
||||
end
|
||||
|
||||
@ -275,26 +275,47 @@ end
|
||||
--- @class vim.lsp.Config : vim.lsp.ClientConfig
|
||||
---
|
||||
--- See `cmd` in [vim.lsp.ClientConfig].
|
||||
--- @field cmd? string[]|fun(dispatchers: vim.lsp.rpc.Dispatchers): vim.lsp.rpc.PublicClient
|
||||
--- See also `reuse_client` to dynamically decide (per-buffer) when `cmd` should be re-invoked.
|
||||
--- @field cmd? string[]|fun(dispatchers: vim.lsp.rpc.Dispatchers, config: vim.lsp.ClientConfig): vim.lsp.rpc.PublicClient
|
||||
---
|
||||
--- Filetypes the client will attach to, if activated by `vim.lsp.enable()`.
|
||||
--- If not provided, then the client will attach to all filetypes.
|
||||
--- Filetypes the client will attach to, if activated by `vim.lsp.enable()`. If not provided, the
|
||||
--- client will attach to all filetypes.
|
||||
--- @field filetypes? string[]
|
||||
---
|
||||
--- Directory markers (.e.g. '.git/') where the LSP server will base its workspaceFolders,
|
||||
--- rootUri, and rootPath on initialization. Unused if `root_dir` is provided.
|
||||
--- @field root_markers? string[]
|
||||
---
|
||||
--- Directory where the LSP server will base its workspaceFolders, rootUri, and
|
||||
--- rootPath on initialization. If a function, it is passed the buffer number
|
||||
--- and a callback argument which must be called with the value of root_dir to
|
||||
--- use. The LSP server will not be started until the callback is called.
|
||||
--- @field root_dir? string|fun(bufnr: integer, cb:fun(root_dir?:string))
|
||||
---
|
||||
--- Predicate used to decide if a client should be re-used. Used on all
|
||||
--- running clients. The default implementation re-uses a client if name and
|
||||
--- root_dir matches.
|
||||
--- Predicate which decides if a client should be re-used. Used on all running clients. The default
|
||||
--- implementation re-uses a client if name and root_dir matches.
|
||||
--- @field reuse_client? fun(client: vim.lsp.Client, config: vim.lsp.ClientConfig): boolean
|
||||
---
|
||||
--- [lsp-root_dir()]()
|
||||
--- Decides the workspace root: the directory where the LSP server will base its workspaceFolders,
|
||||
--- rootUri, and rootPath on initialization. The function form must call the `on_dir` callback to
|
||||
--- provide the root dir, or LSP will not be activated for the buffer. Thus a `root_dir()` function
|
||||
--- can dynamically decide per-buffer whether to activate (or skip) LSP.
|
||||
--- See example at |vim.lsp.enable()|.
|
||||
--- @field root_dir? string|fun(bufnr: integer, on_dir:fun(root_dir?:string))
|
||||
---
|
||||
--- [lsp-root_markers]()
|
||||
--- Filename(s) (".git/", "package.json", …) used to decide the workspace root. Unused if `root_dir`
|
||||
--- is defined. The list order decides priority. To indicate "equal priority", specify names in
|
||||
--- a nested list `{ { 'a.txt', 'b.lua' }, ... }`.
|
||||
---
|
||||
--- For each item, Nvim will search upwards (from the buffer file) for that marker, or list of
|
||||
--- markers; search stops at the first directory containing that marker, and the directory is used
|
||||
--- as the root dir (workspace folder).
|
||||
---
|
||||
--- Example: Find the first ancestor directory containing file or directory "stylua.toml"; if not
|
||||
--- found, find the first ancestor containing ".git":
|
||||
--- ```lua
|
||||
--- root_markers = { 'stylua.toml', '.git' }
|
||||
--- ```
|
||||
---
|
||||
--- Example: Find the first ancestor directory containing EITHER "stylua.toml" or ".luarc.json"; if
|
||||
--- not found, find the first ancestor containing ".git":
|
||||
--- ```lua
|
||||
--- root_markers = { { 'stylua.toml', '.luarc.json' }, '.git' }
|
||||
--- ```
|
||||
---
|
||||
--- @field root_markers? (string|string[])[]
|
||||
|
||||
--- Update the configuration for an LSP client.
|
||||
---
|
||||
@ -429,7 +450,8 @@ lsp.config = setmetatable({ _configs = {} }, {
|
||||
--- @param cfg vim.lsp.Config
|
||||
__newindex = function(self, name, cfg)
|
||||
validate_config_name(name)
|
||||
validate('cfg', cfg, 'table')
|
||||
local msg = ('table (hint: to resolve a config, use vim.lsp.config["%s"])'):format(name)
|
||||
validate('cfg', cfg, 'table', msg)
|
||||
invalidate_enabled_config(name)
|
||||
self._configs[name] = cfg
|
||||
end,
|
||||
@ -439,7 +461,8 @@ lsp.config = setmetatable({ _configs = {} }, {
|
||||
--- @param cfg vim.lsp.Config
|
||||
__call = function(self, name, cfg)
|
||||
validate_config_name(name)
|
||||
validate('cfg', cfg, 'table')
|
||||
local msg = ('table (hint: to resolve a config, use vim.lsp.config["%s"])'):format(name)
|
||||
validate('cfg', cfg, 'table', msg)
|
||||
invalidate_enabled_config(name)
|
||||
self[name] = vim.tbl_deep_extend('force', self._configs[name] or {}, cfg)
|
||||
end,
|
||||
@ -498,6 +521,17 @@ local function lsp_enable_callback(bufnr)
|
||||
return
|
||||
end
|
||||
|
||||
-- Stop any clients that no longer apply to this buffer.
|
||||
local clients = lsp.get_clients({ bufnr = bufnr, _uninitialized = true })
|
||||
for _, client in ipairs(clients) do
|
||||
if
|
||||
lsp.is_enabled(client.name) and not can_start(bufnr, client.name, lsp.config[client.name])
|
||||
then
|
||||
lsp.buf_detach_client(bufnr, client.id)
|
||||
end
|
||||
end
|
||||
|
||||
-- Start any clients that apply to this buffer.
|
||||
for name in vim.spairs(lsp._enabled_configs) do
|
||||
local config = lsp.config[name]
|
||||
if config and can_start(bufnr, name, config) then
|
||||
@ -520,20 +554,40 @@ local function lsp_enable_callback(bufnr)
|
||||
end
|
||||
end
|
||||
|
||||
--- Enable an LSP server to automatically start when opening a buffer.
|
||||
---
|
||||
--- Uses configuration defined with `vim.lsp.config`.
|
||||
--- Auto-starts LSP when a buffer is opened, based on the |lsp-config| `filetypes`, `root_markers`,
|
||||
--- and `root_dir` fields.
|
||||
---
|
||||
--- Examples:
|
||||
---
|
||||
--- ```lua
|
||||
--- vim.lsp.enable('clangd')
|
||||
--- vim.lsp.enable('clangd')
|
||||
--- vim.lsp.enable({'luals', 'pyright'})
|
||||
--- ```
|
||||
---
|
||||
--- vim.lsp.enable({'luals', 'pyright'})
|
||||
--- Example: [lsp-restart]() Passing `false` stops and detaches the client(s). Thus you can
|
||||
--- "restart" LSP by disabling and re-enabling a given config:
|
||||
---
|
||||
--- ```lua
|
||||
--- vim.lsp.enable('clangd', false)
|
||||
--- vim.lsp.enable('clangd', true)
|
||||
--- ```
|
||||
---
|
||||
--- Example: To _dynamically_ decide whether LSP is activated, define a |lsp-root_dir()| function
|
||||
--- which calls `on_dir()` only when you want that config to activate:
|
||||
---
|
||||
--- ```lua
|
||||
--- vim.lsp.config('lua_ls', {
|
||||
--- root_dir = function(bufnr, on_dir)
|
||||
--- if not vim.fn.bufname(bufnr):match('%.txt$') then
|
||||
--- on_dir(vim.fn.getcwd())
|
||||
--- end
|
||||
--- end
|
||||
--- })
|
||||
--- ```
|
||||
---
|
||||
--- @param name string|string[] Name(s) of client(s) to enable.
|
||||
--- @param enable? boolean `true|nil` to enable, `false` to disable.
|
||||
--- @param enable? boolean `true|nil` to enable, `false` to disable (actively stops and detaches
|
||||
--- clients as needed)
|
||||
function lsp.enable(name, enable)
|
||||
validate('name', name, { 'string', 'table' })
|
||||
|
||||
@ -546,21 +600,44 @@ function lsp.enable(name, enable)
|
||||
end
|
||||
|
||||
if not next(lsp._enabled_configs) then
|
||||
-- If there are no remaining LSPs enabled, remove the enable autocmd.
|
||||
if lsp_enable_autocmd_id then
|
||||
api.nvim_del_autocmd(lsp_enable_autocmd_id)
|
||||
lsp_enable_autocmd_id = nil
|
||||
end
|
||||
return
|
||||
else
|
||||
-- Only ever create autocmd once to reuse computation of config merging.
|
||||
lsp_enable_autocmd_id = lsp_enable_autocmd_id
|
||||
or api.nvim_create_autocmd('FileType', {
|
||||
group = api.nvim_create_augroup('nvim.lsp.enable', {}),
|
||||
callback = function(args)
|
||||
lsp_enable_callback(args.buf)
|
||||
end,
|
||||
})
|
||||
end
|
||||
|
||||
-- Only ever create autocmd once to reuse computation of config merging.
|
||||
lsp_enable_autocmd_id = lsp_enable_autocmd_id
|
||||
or api.nvim_create_autocmd('FileType', {
|
||||
group = api.nvim_create_augroup('nvim.lsp.enable', {}),
|
||||
callback = function(args)
|
||||
lsp_enable_callback(args.buf)
|
||||
end,
|
||||
})
|
||||
-- Ensure any pre-existing buffers start/stop their LSP clients.
|
||||
if enable ~= false then
|
||||
if vim.v.vim_did_enter == 1 then
|
||||
vim.cmd.doautoall('nvim.lsp.enable FileType')
|
||||
end
|
||||
else
|
||||
for _, nm in ipairs(names) do
|
||||
for _, client in ipairs(lsp.get_clients({ name = nm })) do
|
||||
client:stop()
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- Checks if the given LSP config is enabled (globally, not per-buffer).
|
||||
---
|
||||
--- Unlike `vim.lsp.config['…']`, this does not have the side-effect of resolving the config.
|
||||
---
|
||||
--- @param name string Config name
|
||||
--- @return boolean
|
||||
function lsp.is_enabled(name)
|
||||
return lsp._enabled_configs[name] ~= nil
|
||||
end
|
||||
|
||||
--- @class vim.lsp.start.Opts
|
||||
@ -582,7 +659,7 @@ end
|
||||
--- Suppress error reporting if the LSP server fails to start (default false).
|
||||
--- @field silent? boolean
|
||||
---
|
||||
--- @field package _root_markers? string[]
|
||||
--- @field package _root_markers? (string|string[])[]
|
||||
|
||||
--- Create a new LSP client and start a language server or reuses an already
|
||||
--- running client if one is found matching `name` and `root_dir`.
|
||||
@ -629,7 +706,9 @@ function lsp.start(config, opts)
|
||||
local bufnr = vim._resolve_bufnr(opts.bufnr)
|
||||
|
||||
if not config.root_dir and opts._root_markers then
|
||||
validate('root_markers', opts._root_markers, 'table')
|
||||
config = vim.deepcopy(config)
|
||||
|
||||
config.root_dir = vim.fs.root(bufnr, opts._root_markers)
|
||||
end
|
||||
|
||||
@ -1210,7 +1289,9 @@ function lsp.buf_request(bufnr, method, params, handler, on_unsupported)
|
||||
local function _cancel_all_requests()
|
||||
for client_id, request_id in pairs(client_request_ids) do
|
||||
local client = all_clients[client_id]
|
||||
client:cancel_request(request_id)
|
||||
if client.requests[request_id] then
|
||||
client:cancel_request(request_id)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -3,6 +3,13 @@ local log = require('vim.lsp.log')
|
||||
local ms = require('vim.lsp.protocol').Methods
|
||||
local api = vim.api
|
||||
|
||||
---@type table<lsp.FoldingRangeKind, true>
|
||||
local supported_fold_kinds = {
|
||||
['comment'] = true,
|
||||
['imports'] = true,
|
||||
['region'] = true,
|
||||
}
|
||||
|
||||
local M = {}
|
||||
|
||||
---@class (private) vim.lsp.folding_range.BufState
|
||||
@ -39,7 +46,7 @@ local function renew(bufnr)
|
||||
---@type table<integer, string?>
|
||||
local row_text = {}
|
||||
|
||||
for _, ranges in pairs(bufstate.client_ranges) do
|
||||
for client_id, ranges in pairs(bufstate.client_ranges) do
|
||||
for _, range in ipairs(ranges) do
|
||||
local start_row = range.startLine
|
||||
local end_row = range.endLine
|
||||
@ -49,9 +56,14 @@ local function renew(bufnr)
|
||||
|
||||
local kind = range.kind
|
||||
if kind then
|
||||
local kinds = row_kinds[start_row] or {}
|
||||
kinds[kind] = true
|
||||
row_kinds[start_row] = kinds
|
||||
-- Ignore unsupported fold kinds.
|
||||
if supported_fold_kinds[kind] then
|
||||
local kinds = row_kinds[start_row] or {}
|
||||
kinds[kind] = true
|
||||
row_kinds[start_row] = kinds
|
||||
else
|
||||
log.info(('Unknown fold kind "%s" from client %d'):format(kind, client_id))
|
||||
end
|
||||
end
|
||||
|
||||
for row = start_row, end_row do
|
||||
|
@ -71,7 +71,7 @@ function M.hover(config)
|
||||
|
||||
if vim.tbl_isempty(results1) then
|
||||
if config.silent ~= true then
|
||||
vim.notify('No information available')
|
||||
vim.notify('No information available', vim.log.levels.INFO)
|
||||
end
|
||||
return
|
||||
end
|
||||
@ -363,7 +363,7 @@ function M.signature_help(config)
|
||||
|
||||
if not next(signatures) then
|
||||
if config.silent ~= true then
|
||||
print('No signature help available')
|
||||
vim.notify('No signature help available', vim.log.levels.INFO)
|
||||
end
|
||||
return
|
||||
end
|
||||
@ -440,7 +440,7 @@ end
|
||||
---
|
||||
---@see vim.lsp.protocol.CompletionTriggerKind
|
||||
function M.completion(context)
|
||||
vim.depends('vim.lsp.buf.completion', 'vim.lsp.completion.trigger', '0.12')
|
||||
vim.deprecate('vim.lsp.buf.completion', 'vim.lsp.completion.trigger', '0.12')
|
||||
return lsp.buf_request(
|
||||
0,
|
||||
ms.textDocument_completion,
|
||||
@ -970,7 +970,7 @@ function M.add_workspace_folder(workspace_folder)
|
||||
return
|
||||
end
|
||||
if vim.fn.isdirectory(workspace_folder) == 0 then
|
||||
print(workspace_folder, ' is not a valid directory')
|
||||
vim.notify(workspace_folder .. ' is not a valid directory')
|
||||
return
|
||||
end
|
||||
local bufnr = api.nvim_get_current_buf()
|
||||
@ -994,7 +994,7 @@ function M.remove_workspace_folder(workspace_folder)
|
||||
for _, client in pairs(lsp.get_clients({ bufnr = bufnr })) do
|
||||
client:_remove_workspace_folder(workspace_folder)
|
||||
end
|
||||
print(workspace_folder, 'is not currently part of the workspace')
|
||||
vim.notify(workspace_folder .. 'is not currently part of the workspace')
|
||||
end
|
||||
|
||||
--- Lists all symbols in the current workspace in the quickfix window.
|
||||
@ -1211,8 +1211,7 @@ local function on_code_action_results(results, opts)
|
||||
vim.ui.select(actions, select_opts, on_user_choice)
|
||||
end
|
||||
|
||||
--- Selects a code action available at the current
|
||||
--- cursor position.
|
||||
--- Selects a code action (LSP: "textDocument/codeAction" request) available at cursor position.
|
||||
---
|
||||
---@param opts? vim.lsp.buf.code_action.Opts
|
||||
---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_codeAction
|
||||
|
@ -30,41 +30,11 @@ local validate = vim.validate
|
||||
--- @field exit_timeout integer|false
|
||||
|
||||
--- @class vim.lsp.ClientConfig
|
||||
--- command string[] that launches the language
|
||||
--- server (treated as in |jobstart()|, must be absolute or on `$PATH`, shell constructs like
|
||||
--- "~" are not expanded), or function that creates an RPC client. Function receives
|
||||
--- a `dispatchers` table and returns a table with member functions `request`, `notify`,
|
||||
--- `is_closing` and `terminate`.
|
||||
--- See |vim.lsp.rpc.request()|, |vim.lsp.rpc.notify()|.
|
||||
--- For TCP there is a builtin RPC client factory: |vim.lsp.rpc.connect()|
|
||||
--- @field cmd string[]|fun(dispatchers: vim.lsp.rpc.Dispatchers): vim.lsp.rpc.PublicClient
|
||||
---
|
||||
--- Directory to launch the `cmd` process. Not related to `root_dir`.
|
||||
--- (default: cwd)
|
||||
--- @field cmd_cwd? string
|
||||
---
|
||||
--- Environment flags to pass to the LSP on spawn.
|
||||
--- Must be specified using a table.
|
||||
--- Non-string values are coerced to string.
|
||||
--- Example:
|
||||
--- ```lua
|
||||
--- { PORT = 8080; HOST = "0.0.0.0"; }
|
||||
--- ```
|
||||
--- @field cmd_env? table
|
||||
---
|
||||
--- Daemonize the server process so that it runs in a separate process group from Nvim.
|
||||
--- Nvim will shutdown the process on exit, but if Nvim fails to exit cleanly this could leave
|
||||
--- behind orphaned server processes.
|
||||
--- (default: true)
|
||||
--- @field detached? boolean
|
||||
---
|
||||
--- List of workspace folders passed to the language server.
|
||||
--- For backwards compatibility rootUri and rootPath will be derived from the first workspace
|
||||
--- folder in this list. See `workspaceFolders` in the LSP spec.
|
||||
--- @field workspace_folders? lsp.WorkspaceFolder[]
|
||||
---
|
||||
--- (default false) Server requires a workspace (no "single file" support).
|
||||
--- @field workspace_required? boolean
|
||||
--- Callback invoked before the LSP "initialize" phase, where `params` contains the parameters
|
||||
--- being sent to the server and `config` is the config that was passed to |vim.lsp.start()|.
|
||||
--- You can use this to modify parameters before they are sent.
|
||||
--- @field before_init? fun(params: lsp.InitializeParams, config: vim.lsp.ClientConfig)
|
||||
---
|
||||
--- Map overriding the default capabilities defined by |vim.lsp.protocol.make_client_capabilities()|,
|
||||
--- passed to the language server on initialization. Hint: use make_client_capabilities() and modify
|
||||
@ -73,93 +43,143 @@ local validate = vim.validate
|
||||
--- array.
|
||||
--- @field capabilities? lsp.ClientCapabilities
|
||||
---
|
||||
--- Map of language server method names to |lsp-handler|
|
||||
--- @field handlers? table<string,function>
|
||||
--- Command `string[]` that launches the language server (treated as in |jobstart()|, must be
|
||||
--- absolute or on `$PATH`, shell constructs like "~" are not expanded), or function that creates an
|
||||
--- RPC client. Function receives a `dispatchers` table and the resolved `config`, and must return
|
||||
--- a table with member functions `request`, `notify`, `is_closing` and `terminate`.
|
||||
--- See |vim.lsp.rpc.request()|, |vim.lsp.rpc.notify()|.
|
||||
--- For TCP there is a builtin RPC client factory: |vim.lsp.rpc.connect()|
|
||||
--- @field cmd string[]|fun(dispatchers: vim.lsp.rpc.Dispatchers, config: vim.lsp.ClientConfig): vim.lsp.rpc.PublicClient
|
||||
---
|
||||
--- Map with language server specific settings.
|
||||
--- See the {settings} in |vim.lsp.Client|.
|
||||
--- @field settings? lsp.LSPObject
|
||||
--- Directory to launch the `cmd` process. Not related to `root_dir`.
|
||||
--- (default: cwd)
|
||||
--- @field cmd_cwd? string
|
||||
---
|
||||
--- Table that maps string of clientside commands to user-defined functions.
|
||||
--- Commands passed to `start()` take precedence over the global command registry. Each key
|
||||
--- must be a unique command name, and the value is a function which is called if any LSP action
|
||||
--- (code action, code lenses, ...) triggers the command.
|
||||
--- Environment variables passed to the LSP process on spawn. Non-string values are coerced to
|
||||
--- string.
|
||||
--- Example:
|
||||
--- ```lua
|
||||
--- { PORT = 8080; HOST = '0.0.0.0'; }
|
||||
--- ```
|
||||
--- @field cmd_env? table
|
||||
---
|
||||
--- Client commands. Map of command names to user-defined functions. Commands passed to `start()`
|
||||
--- take precedence over the global command registry. Each key must be a unique command name, and
|
||||
--- the value is a function which is called if any LSP action (code action, code lenses, …) triggers
|
||||
--- the command.
|
||||
--- @field commands? table<string,fun(command: lsp.Command, ctx: table)>
|
||||
---
|
||||
--- Daemonize the server process so that it runs in a separate process group from Nvim.
|
||||
--- Nvim will shutdown the process on exit, but if Nvim fails to exit cleanly this could leave
|
||||
--- behind orphaned server processes.
|
||||
--- (default: `true`)
|
||||
--- @field detached? boolean
|
||||
---
|
||||
--- A table with flags for the client. The current (experimental) flags are:
|
||||
--- @field flags? vim.lsp.Client.Flags
|
||||
---
|
||||
--- Language ID as string. Defaults to the buffer filetype.
|
||||
--- @field get_language_id? fun(bufnr: integer, filetype: string): string
|
||||
---
|
||||
--- Map of LSP method names to |lsp-handler|s.
|
||||
--- @field handlers? table<string,function>
|
||||
---
|
||||
--- Values to pass in the initialization request as `initializationOptions`. See `initialize` in
|
||||
--- the LSP spec.
|
||||
--- @field init_options? lsp.LSPObject
|
||||
---
|
||||
--- Name in log messages.
|
||||
--- Name in logs and user messages.
|
||||
--- (default: client-id)
|
||||
--- @field name? string
|
||||
---
|
||||
--- Language ID as string. Defaults to the buffer filetype.
|
||||
--- @field get_language_id? fun(bufnr: integer, filetype: string): string
|
||||
---
|
||||
--- Called "position encoding" in LSP spec, the encoding that the LSP server expects.
|
||||
--- Client does not verify this is correct.
|
||||
--- Called "position encoding" in LSP spec. The encoding that the LSP server expects, used for
|
||||
--- communication. Not validated. Can be modified in `on_init` before text is sent to the server.
|
||||
--- @field offset_encoding? 'utf-8'|'utf-16'|'utf-32'
|
||||
---
|
||||
--- Callback invoked when client attaches to a buffer.
|
||||
--- @field on_attach? elem_or_list<fun(client: vim.lsp.Client, bufnr: integer)>
|
||||
---
|
||||
--- Callback invoked when the client operation throws an error. `code` is a number describing the error.
|
||||
--- Other arguments may be passed depending on the error kind. See `vim.lsp.rpc.client_errors`
|
||||
--- for possible errors. Use `vim.lsp.rpc.client_errors[code]` to get human-friendly name.
|
||||
--- @field on_error? fun(code: integer, err: string)
|
||||
---
|
||||
--- Callback invoked before the LSP "initialize" phase, where `params` contains the parameters
|
||||
--- being sent to the server and `config` is the config that was passed to |vim.lsp.start()|.
|
||||
--- You can use this to modify parameters before they are sent.
|
||||
--- @field before_init? fun(params: lsp.InitializeParams, config: vim.lsp.ClientConfig)
|
||||
---
|
||||
--- Callback invoked after LSP "initialize", where `result` is a table of `capabilities` and
|
||||
--- anything else the server may send. For example, clangd sends `init_result.offsetEncoding` if
|
||||
--- `capabilities.offsetEncoding` was sent to it. You can only modify the `client.offset_encoding`
|
||||
--- here before any notifications are sent.
|
||||
--- @field on_init? elem_or_list<fun(client: vim.lsp.Client, init_result: lsp.InitializeResult)>
|
||||
---
|
||||
--- Callback invoked on client exit.
|
||||
--- - code: exit code of the process
|
||||
--- - signal: number describing the signal used to terminate (if any)
|
||||
--- - client_id: client handle
|
||||
--- @field on_exit? elem_or_list<fun(code: integer, signal: integer, client_id: integer)>
|
||||
---
|
||||
--- Callback invoked when client attaches to a buffer.
|
||||
--- @field on_attach? elem_or_list<fun(client: vim.lsp.Client, bufnr: integer)>
|
||||
--- Callback invoked after LSP "initialize", where `result` is a table of `capabilities` and
|
||||
--- anything else the server may send. For example, clangd sends `init_result.offsetEncoding` if
|
||||
--- `capabilities.offsetEncoding` was sent to it. You can only modify the `client.offset_encoding`
|
||||
--- here before any notifications are sent.
|
||||
--- @field on_init? elem_or_list<fun(client: vim.lsp.Client, init_result: lsp.InitializeResult)>
|
||||
---
|
||||
--- Directory where the LSP server will base its workspaceFolders, rootUri, and rootPath on initialization.
|
||||
--- @field root_dir? string
|
||||
---
|
||||
--- Map of language server-specific settings, decided by the client. Sent to the LS if requested via
|
||||
--- `workspace/configuration`. Keys are case-sensitive.
|
||||
--- @field settings? lsp.LSPObject
|
||||
---
|
||||
--- Passed directly to the language server in the initialize request. Invalid/empty values will
|
||||
--- (default: "off")
|
||||
--- @field trace? 'off'|'messages'|'verbose'
|
||||
---
|
||||
--- A table with flags for the client. The current (experimental) flags are:
|
||||
--- @field flags? vim.lsp.Client.Flags
|
||||
--- List of workspace folders passed to the language server. For backwards compatibility rootUri and
|
||||
--- rootPath are derived from the first workspace folder in this list. Can be `null` if the client
|
||||
--- supports workspace folders but none are configured. See `workspaceFolders` in LSP spec.
|
||||
--- @field workspace_folders? lsp.WorkspaceFolder[]
|
||||
---
|
||||
--- Directory where the LSP server will base its workspaceFolders, rootUri, and rootPath on initialization.
|
||||
--- @field root_dir? string
|
||||
--- Server requires a workspace (no "single file" support). Note: Without
|
||||
--- a workspace, cross-file features (navigation, hover) may or may not work depending on the
|
||||
--- language server, even if the server doesn't require a workspace.
|
||||
--- (default: `false`)
|
||||
--- @field workspace_required? boolean
|
||||
|
||||
--- @class vim.lsp.Client.Progress: vim.Ringbuf<{token: integer|string, value: any}>
|
||||
--- @field pending table<lsp.ProgressToken,lsp.LSPAny>
|
||||
|
||||
--- @class vim.lsp.Client
|
||||
---
|
||||
--- @field attached_buffers table<integer,true>
|
||||
---
|
||||
--- Capabilities provided by the client (editor or tool), at startup.
|
||||
--- @field capabilities lsp.ClientCapabilities
|
||||
---
|
||||
--- Client commands. See [vim.lsp.ClientConfig].
|
||||
--- @field commands table<string,fun(command: lsp.Command, ctx: table)>
|
||||
---
|
||||
--- Copy of the config passed to |vim.lsp.start()|.
|
||||
--- @field config vim.lsp.ClientConfig
|
||||
---
|
||||
--- Capabilities provided at runtime (after startup).
|
||||
--- @field dynamic_capabilities lsp.DynamicCapabilities
|
||||
---
|
||||
--- A table with flags for the client. The current (experimental) flags are:
|
||||
--- @field flags vim.lsp.Client.Flags
|
||||
---
|
||||
--- See [vim.lsp.ClientConfig].
|
||||
--- @field get_language_id fun(bufnr: integer, filetype: string): string
|
||||
---
|
||||
--- See [vim.lsp.ClientConfig].
|
||||
--- @field handlers table<string,lsp.Handler>
|
||||
---
|
||||
--- The id allocated to the client.
|
||||
--- @field id integer
|
||||
---
|
||||
--- If a name is specified on creation, that will be used. Otherwise it is just
|
||||
--- the client id. This is used for logs and messages.
|
||||
--- @field initialized true?
|
||||
---
|
||||
--- See [vim.lsp.ClientConfig].
|
||||
--- @field name string
|
||||
---
|
||||
--- RPC client object, for low level interaction with the client.
|
||||
--- See |vim.lsp.rpc.start()|.
|
||||
--- @field rpc vim.lsp.rpc.PublicClient
|
||||
---
|
||||
--- Called "position encoding" in LSP spec,
|
||||
--- the encoding used for communicating with the server.
|
||||
--- You can modify this in the `config`'s `on_init` method
|
||||
--- before text is sent to the server.
|
||||
--- See [vim.lsp.ClientConfig].
|
||||
--- @field offset_encoding string
|
||||
---
|
||||
--- The handlers used by the client as described in |lsp-handler|.
|
||||
--- @field handlers table<string,lsp.Handler>
|
||||
--- A ring buffer (|vim.ringbuf()|) containing progress messages
|
||||
--- sent by the server.
|
||||
--- @field progress vim.lsp.Client.Progress
|
||||
---
|
||||
--- The current pending requests in flight to the server. Entries are key-value
|
||||
--- pairs with the key being the request id while the value is a table with
|
||||
@ -169,34 +189,25 @@ local validate = vim.validate
|
||||
--- are received from the server.
|
||||
--- @field requests table<integer,{ type: string, bufnr: integer, method: string}?>
|
||||
---
|
||||
--- copy of the table that was passed by the user
|
||||
--- to |vim.lsp.start()|.
|
||||
--- @field config vim.lsp.ClientConfig
|
||||
---
|
||||
--- Response from the server sent on `initialize` describing the server's
|
||||
--- capabilities.
|
||||
--- @field server_capabilities lsp.ServerCapabilities?
|
||||
---
|
||||
--- Response from the server sent on `initialize` describing information about
|
||||
--- the server.
|
||||
--- @field server_info lsp.ServerInfo?
|
||||
---
|
||||
--- A ring buffer (|vim.ringbuf()|) containing progress messages
|
||||
--- sent by the server.
|
||||
--- @field progress vim.lsp.Client.Progress
|
||||
---
|
||||
--- @field initialized true?
|
||||
---
|
||||
--- The workspace folders configured in the client when the server starts.
|
||||
--- This property is only available if the client supports workspace folders.
|
||||
--- It can be `null` if the client supports workspace folders but none are
|
||||
--- configured.
|
||||
--- @field workspace_folders lsp.WorkspaceFolder[]?
|
||||
--- See [vim.lsp.ClientConfig].
|
||||
--- @field root_dir string?
|
||||
---
|
||||
--- @field attached_buffers table<integer,true>
|
||||
--- RPC client object, for low level interaction with the client.
|
||||
--- See |vim.lsp.rpc.start()|.
|
||||
--- @field rpc vim.lsp.rpc.PublicClient
|
||||
---
|
||||
--- Response from the server sent on `initialize` describing the server's capabilities.
|
||||
--- @field server_capabilities lsp.ServerCapabilities?
|
||||
---
|
||||
--- Response from the server sent on `initialize` describing server information (e.g. version).
|
||||
--- @field server_info lsp.ServerInfo?
|
||||
---
|
||||
--- See [vim.lsp.ClientConfig].
|
||||
--- @field settings lsp.LSPObject
|
||||
---
|
||||
--- See [vim.lsp.ClientConfig].
|
||||
--- @field workspace_folders lsp.WorkspaceFolder[]?
|
||||
---
|
||||
--- @field private _log_prefix string
|
||||
---
|
||||
--- Track this so that we can escalate automatically if we've already tried a
|
||||
--- graceful shutdown
|
||||
@ -206,26 +217,8 @@ local validate = vim.validate
|
||||
--- trace = "off" | "messages" | "verbose";
|
||||
--- @field private _trace 'off'|'messages'|'verbose'
|
||||
---
|
||||
--- Table of command name to function which is called if any LSP action
|
||||
--- (code action, code lenses, ...) triggers the command.
|
||||
--- Client commands take precedence over the global command registry.
|
||||
--- @field commands table<string,fun(command: lsp.Command, ctx: table)>
|
||||
---
|
||||
--- Map with language server specific settings. These are returned to the
|
||||
--- language server if requested via `workspace/configuration`. Keys are
|
||||
--- case-sensitive.
|
||||
--- @field settings lsp.LSPObject
|
||||
---
|
||||
--- A table with flags for the client. The current (experimental) flags are:
|
||||
--- @field flags vim.lsp.Client.Flags
|
||||
---
|
||||
--- @field get_language_id fun(bufnr: integer, filetype: string): string
|
||||
---
|
||||
--- The capabilities provided by the client (editor or tool)
|
||||
--- @field capabilities lsp.ClientCapabilities
|
||||
--- @field private registrations table<string,lsp.Registration[]>
|
||||
--- @field dynamic_capabilities lsp.DynamicCapabilities
|
||||
---
|
||||
--- @field private _log_prefix string
|
||||
--- @field private _before_init_cb? vim.lsp.client.before_init_cb
|
||||
--- @field private _on_attach_cbs vim.lsp.client.on_attach_cb[]
|
||||
--- @field private _on_init_cbs vim.lsp.client.on_init_cb[]
|
||||
@ -395,6 +388,7 @@ function Client.create(config)
|
||||
capabilities = config.capabilities,
|
||||
workspace_folders = lsp._get_workspace_folders(config.workspace_folders or config.root_dir),
|
||||
root_dir = config.root_dir,
|
||||
_is_stopping = false,
|
||||
_before_init_cb = config.before_init,
|
||||
_on_init_cbs = vim._ensure_list(config.on_init),
|
||||
_on_exit_cbs = vim._ensure_list(config.on_exit),
|
||||
@ -461,7 +455,7 @@ function Client.create(config)
|
||||
-- Start the RPC client.
|
||||
local config_cmd = config.cmd
|
||||
if type(config_cmd) == 'function' then
|
||||
self.rpc = config_cmd(dispatchers)
|
||||
self.rpc = config_cmd(dispatchers, config)
|
||||
else
|
||||
self.rpc = lsp.rpc.start(config_cmd, dispatchers, {
|
||||
cwd = config.cmd_cwd,
|
||||
@ -678,6 +672,12 @@ function Client:request(method, params, handler, bufnr)
|
||||
bufnr = vim._resolve_bufnr(bufnr)
|
||||
local version = lsp.util.buf_versions[bufnr]
|
||||
log.debug(self._log_prefix, 'client.request', self.id, method, params, handler, bufnr)
|
||||
|
||||
-- Detect if request resolved synchronously (only possible with in-process servers).
|
||||
local already_responded = false
|
||||
local request_registered = false
|
||||
|
||||
-- NOTE: rpc.request might call an in-process (Lua) server, thus may be synchronous.
|
||||
local success, request_id = self.rpc.request(method, params, function(err, result)
|
||||
handler(err, result, {
|
||||
method = method,
|
||||
@ -688,11 +688,15 @@ function Client:request(method, params, handler, bufnr)
|
||||
})
|
||||
end, function(request_id)
|
||||
-- Called when the server sends a response to the request (including cancelled acknowledgment).
|
||||
self:_process_request(request_id, 'complete')
|
||||
if request_registered then
|
||||
self:_process_request(request_id, 'complete')
|
||||
end
|
||||
already_responded = true
|
||||
end)
|
||||
|
||||
if success and request_id then
|
||||
if success and request_id and not already_responded then
|
||||
self:_process_request(request_id, 'pending', bufnr, method)
|
||||
request_registered = true
|
||||
end
|
||||
|
||||
return success, request_id
|
||||
@ -802,12 +806,13 @@ end
|
||||
---
|
||||
--- @param force? boolean
|
||||
function Client:stop(force)
|
||||
local rpc = self.rpc
|
||||
|
||||
if rpc.is_closing() then
|
||||
if self:is_stopped() then
|
||||
return
|
||||
end
|
||||
|
||||
self._is_stopping = true
|
||||
local rpc = self.rpc
|
||||
|
||||
vim.lsp._watchfiles.cancel(self.id)
|
||||
|
||||
if force or not self.initialized or self._graceful_shutdown_failed then
|
||||
@ -933,7 +938,7 @@ end
|
||||
--- @return boolean # true if client is stopped or in the process of being
|
||||
--- stopped; false otherwise
|
||||
function Client:is_stopped()
|
||||
return self.rpc.is_closing()
|
||||
return self.rpc.is_closing() or self._is_stopping
|
||||
end
|
||||
|
||||
--- Execute a lsp command, either via client command function (if available)
|
||||
|
@ -370,7 +370,7 @@ end
|
||||
local function adjust_start_col(lnum, line, items, encoding)
|
||||
local min_start_char = nil
|
||||
for _, item in pairs(items) do
|
||||
if item.textEdit and item.textEdit.range.start.line == lnum then
|
||||
if item.textEdit and item.textEdit.range and item.textEdit.range.start.line == lnum then
|
||||
if min_start_char and min_start_char ~= item.textEdit.range.start.character then
|
||||
return nil
|
||||
end
|
||||
@ -506,14 +506,19 @@ local function trigger(bufnr, clients, ctx)
|
||||
local matches = {}
|
||||
local server_start_boundary --- @type integer?
|
||||
for client_id, response in pairs(responses) do
|
||||
local client = lsp.get_client_by_id(client_id)
|
||||
if response.err then
|
||||
vim.notify_once(response.err.message, vim.log.levels.WARN)
|
||||
local msg = ('%s: %s %s'):format(
|
||||
client and client.name or 'UNKNOWN',
|
||||
response.err.code or 'NO_CODE',
|
||||
response.err.message
|
||||
)
|
||||
vim.notify_once(msg, vim.log.levels.WARN)
|
||||
end
|
||||
|
||||
local result = response.result
|
||||
if result then
|
||||
Context.isIncomplete = Context.isIncomplete or result.isIncomplete
|
||||
local client = lsp.get_client_by_id(client_id)
|
||||
local encoding = client and client.offset_encoding or 'utf-16'
|
||||
local client_matches
|
||||
client_matches, server_start_boundary = M._convert_results(
|
||||
|
@ -93,12 +93,16 @@ local function diagnostic_lsp_to_vim(diagnostics, bufnr, client_id)
|
||||
message = diagnostic.message.value
|
||||
end
|
||||
local line = buf_lines and buf_lines[start.line + 1] or ''
|
||||
local end_line = line
|
||||
if _end.line > start.line then
|
||||
end_line = buf_lines and buf_lines[_end.line + 1] or ''
|
||||
end
|
||||
--- @type vim.Diagnostic
|
||||
return {
|
||||
lnum = start.line,
|
||||
col = vim.str_byteindex(line, position_encoding, start.character, false),
|
||||
end_lnum = _end.line,
|
||||
end_col = vim.str_byteindex(line, position_encoding, _end.character, false),
|
||||
end_col = vim.str_byteindex(end_line, position_encoding, _end.character, false),
|
||||
severity = severity_lsp_to_vim(diagnostic.severity),
|
||||
message = message,
|
||||
source = diagnostic.source,
|
||||
|
@ -1,4 +1,25 @@
|
||||
-- Logger for language client plugin.
|
||||
--- @brief
|
||||
--- The `vim.lsp.log` module provides logging for the Nvim LSP client.
|
||||
---
|
||||
--- When debugging language servers, it is helpful to enable extra-verbose logging of the LSP client
|
||||
--- RPC events. Example:
|
||||
--- ```lua
|
||||
--- vim.lsp.set_log_level 'trace'
|
||||
--- require('vim.lsp.log').set_format_func(vim.inspect)
|
||||
--- ```
|
||||
---
|
||||
--- Then try to run the language server, and open the log with:
|
||||
--- ```vim
|
||||
--- :lua vim.cmd('tabnew ' .. vim.lsp.get_log_path())
|
||||
--- ```
|
||||
---
|
||||
--- (Or use `:LspLog` if you have nvim-lspconfig installed.)
|
||||
---
|
||||
--- Note:
|
||||
--- - Remember to DISABLE verbose logging ("debug" or "trace" level), else you may encounter
|
||||
--- performance issues.
|
||||
--- - "ERROR" messages containing "stderr" only indicate that the log was sent to stderr. Many
|
||||
--- servers send harmless messages via stderr.
|
||||
|
||||
local log = {}
|
||||
|
||||
|
@ -162,14 +162,13 @@ local constants = {
|
||||
MethodNotFound = -32601,
|
||||
InvalidParams = -32602,
|
||||
InternalError = -32603,
|
||||
serverErrorStart = -32099,
|
||||
serverErrorEnd = -32000,
|
||||
ServerNotInitialized = -32002,
|
||||
UnknownErrorCode = -32001,
|
||||
-- Defined by the protocol.
|
||||
RequestCancelled = -32800,
|
||||
ContentModified = -32801,
|
||||
ServerCancelled = -32802,
|
||||
RequestFailed = -32803,
|
||||
},
|
||||
|
||||
-- Describes the content type that a client supports in various
|
||||
@ -329,6 +328,7 @@ end
|
||||
--- capabilities.
|
||||
--- @return lsp.ClientCapabilities
|
||||
function protocol.make_client_capabilities()
|
||||
---@type lsp.ClientCapabilities
|
||||
return {
|
||||
general = {
|
||||
positionEncodings = {
|
||||
@ -340,6 +340,9 @@ function protocol.make_client_capabilities()
|
||||
textDocument = {
|
||||
diagnostic = {
|
||||
dynamicRegistration = false,
|
||||
tagSupport = {
|
||||
valueSet = get_value_set(constants.DiagnosticTag),
|
||||
},
|
||||
},
|
||||
inlayHint = {
|
||||
dynamicRegistration = true,
|
||||
@ -436,6 +439,9 @@ function protocol.make_client_capabilities()
|
||||
foldingRange = {
|
||||
dynamicRegistration = false,
|
||||
lineFoldingOnly = true,
|
||||
foldingRangeKind = {
|
||||
valueSet = { 'comment', 'imports', 'region' },
|
||||
},
|
||||
foldingRange = {
|
||||
collapsedText = true,
|
||||
},
|
||||
|
@ -1349,10 +1349,17 @@ local function close_preview_autocmd(events, winnr, bufnrs)
|
||||
|
||||
-- close the preview window when entered a buffer that is not
|
||||
-- the floating window buffer or the buffer that spawned it
|
||||
api.nvim_create_autocmd('BufEnter', {
|
||||
api.nvim_create_autocmd('BufLeave', {
|
||||
group = augroup,
|
||||
buffer = bufnrs[1],
|
||||
callback = function()
|
||||
close_preview_window(winnr, bufnrs)
|
||||
vim.schedule(function()
|
||||
-- When jumping to the quickfix window from the preview window,
|
||||
-- do not close the preview window.
|
||||
if api.nvim_get_option_value('filetype', { buf = 0 }) ~= 'qf' then
|
||||
close_preview_window(winnr, bufnrs)
|
||||
end
|
||||
end)
|
||||
end,
|
||||
})
|
||||
|
||||
@ -1793,7 +1800,7 @@ function M.symbols_to_items(symbols, bufnr, position_encoding)
|
||||
'symbols_to_items must be called with valid position encoding',
|
||||
vim.log.levels.WARN
|
||||
)
|
||||
position_encoding = vim.lsp.get_clients({ bufnr = 0 })[1].offset_encoding
|
||||
position_encoding = vim.lsp.get_clients({ bufnr = bufnr })[1].offset_encoding
|
||||
end
|
||||
|
||||
local items = {} --- @type vim.quickfix.entry[]
|
||||
|
@ -21,6 +21,50 @@ local function read_trust()
|
||||
return trust
|
||||
end
|
||||
|
||||
--- If {fullpath} is a file, read the contents of {fullpath} (or the contents of {bufnr}
|
||||
--- if given) and returns the contents and a hash of the contents.
|
||||
---
|
||||
--- If {fullpath} is a directory, then nothing is read from the filesystem, and
|
||||
--- `contents = true` and `hash = "directory"` is returned instead.
|
||||
---
|
||||
---@param fullpath (string) Path to a file or directory to read.
|
||||
---@param bufnr (number?) The number of the buffer.
|
||||
---@return string|boolean? contents the contents of the file, or true if it's a directory
|
||||
---@return string? hash the hash of the contents, or "directory" if it's a directory
|
||||
local function compute_hash(fullpath, bufnr)
|
||||
local contents ---@type string|boolean?
|
||||
local hash ---@type string
|
||||
if vim.fn.isdirectory(fullpath) == 1 then
|
||||
return true, 'directory'
|
||||
end
|
||||
|
||||
if bufnr then
|
||||
local newline = vim.bo[bufnr].fileformat == 'unix' and '\n' or '\r\n'
|
||||
contents =
|
||||
table.concat(vim.api.nvim_buf_get_lines(bufnr --[[@as integer]], 0, -1, false), newline)
|
||||
if vim.bo[bufnr].endofline then
|
||||
contents = contents .. newline
|
||||
end
|
||||
else
|
||||
do
|
||||
local f = io.open(fullpath, 'r')
|
||||
if not f then
|
||||
return nil, nil
|
||||
end
|
||||
contents = f:read('*a')
|
||||
f:close()
|
||||
end
|
||||
|
||||
if not contents then
|
||||
return nil, nil
|
||||
end
|
||||
end
|
||||
|
||||
hash = vim.fn.sha256(contents)
|
||||
|
||||
return contents, hash
|
||||
end
|
||||
|
||||
--- Writes provided {trust} table to trust database at
|
||||
--- $XDG_STATE_HOME/nvim/trust.
|
||||
---
|
||||
@ -37,17 +81,22 @@ local function write_trust(trust)
|
||||
f:close()
|
||||
end
|
||||
|
||||
--- Attempt to read the file at {path} prompting the user if the file should be
|
||||
--- trusted. The user's choice is persisted in a trust database at
|
||||
--- If {path} is a file: attempt to read the file, prompting the user if the file should be
|
||||
--- trusted.
|
||||
---
|
||||
--- If {path} is a directory: return true if the directory is trusted (non-recursive), prompting
|
||||
--- the user as necessary.
|
||||
---
|
||||
--- The user's choice is persisted in a trust database at
|
||||
--- $XDG_STATE_HOME/nvim/trust.
|
||||
---
|
||||
---@since 11
|
||||
---@see |:trust|
|
||||
---
|
||||
---@param path (string) Path to a file to read.
|
||||
---@param path (string) Path to a file or directory to read.
|
||||
---
|
||||
---@return (string|nil) The contents of the given file if it exists and is
|
||||
--- trusted, or nil otherwise.
|
||||
---@return (boolean|string|nil) If {path} is not trusted or does not exist, returns `nil`. Otherwise,
|
||||
--- returns the contents of {path} if it is a file, or true if {path} is a directory.
|
||||
function M.read(path)
|
||||
vim.validate('path', path, 'string')
|
||||
local fullpath = vim.uv.fs_realpath(vim.fs.normalize(path))
|
||||
@ -62,26 +111,25 @@ function M.read(path)
|
||||
return nil
|
||||
end
|
||||
|
||||
local contents ---@type string?
|
||||
do
|
||||
local f = io.open(fullpath, 'r')
|
||||
if not f then
|
||||
return nil
|
||||
end
|
||||
contents = f:read('*a')
|
||||
f:close()
|
||||
local contents, hash = compute_hash(fullpath, nil)
|
||||
if not contents then
|
||||
return nil
|
||||
end
|
||||
|
||||
local hash = vim.fn.sha256(contents)
|
||||
if trust[fullpath] == hash then
|
||||
-- File already exists in trust database
|
||||
return contents
|
||||
end
|
||||
|
||||
local dir_msg = ''
|
||||
if hash == 'directory' then
|
||||
dir_msg = ' DIRECTORY trust is decided only by its name, not its contents.'
|
||||
end
|
||||
|
||||
-- File either does not exist in trust database or the hash does not match
|
||||
local ok, result = pcall(
|
||||
vim.fn.confirm,
|
||||
string.format('%s is not trusted.', fullpath),
|
||||
string.format('%s is not trusted.%s', fullpath, dir_msg),
|
||||
'&ignore\n&view\n&deny\n&allow',
|
||||
1
|
||||
)
|
||||
@ -169,13 +217,10 @@ function M.trust(opts)
|
||||
local trust = read_trust()
|
||||
|
||||
if action == 'allow' then
|
||||
local newline = vim.bo[bufnr].fileformat == 'unix' and '\n' or '\r\n'
|
||||
local contents =
|
||||
table.concat(vim.api.nvim_buf_get_lines(bufnr --[[@as integer]], 0, -1, false), newline)
|
||||
if vim.bo[bufnr].endofline then
|
||||
contents = contents .. newline
|
||||
local contents, hash = compute_hash(fullpath, bufnr)
|
||||
if not contents then
|
||||
return false, string.format('could not read path: %s', fullpath)
|
||||
end
|
||||
local hash = vim.fn.sha256(contents)
|
||||
|
||||
trust[fullpath] = hash
|
||||
elseif action == 'deny' then
|
||||
|
@ -95,7 +95,7 @@ end
|
||||
---
|
||||
--- @see |string.gmatch()|
|
||||
--- @see |vim.split()|
|
||||
--- @see |lua-patterns|
|
||||
--- @see |lua-pattern|s
|
||||
--- @see https://www.lua.org/pil/20.2.html
|
||||
--- @see http://lua-users.org/wiki/StringLibraryTutorial
|
||||
---
|
||||
@ -784,7 +784,7 @@ end
|
||||
|
||||
--- Trim whitespace (Lua pattern "%s") from both sides of a string.
|
||||
---
|
||||
---@see |lua-patterns|
|
||||
---@see |lua-pattern|s
|
||||
---@see https://www.lua.org/pil/20.2.html
|
||||
---@param s string String to trim
|
||||
---@return string String with whitespace removed from its beginning and end
|
||||
@ -793,7 +793,7 @@ function vim.trim(s)
|
||||
return s:match('^%s*(.*%S)') or ''
|
||||
end
|
||||
|
||||
--- Escapes magic chars in |lua-patterns|.
|
||||
--- Escapes magic chars in |lua-pattern|s.
|
||||
---
|
||||
---@see https://github.com/rxi/lume
|
||||
---@param s string String to escape
|
||||
@ -854,7 +854,7 @@ do
|
||||
--- @param param_name string
|
||||
--- @param val any
|
||||
--- @param validator vim.validate.Validator
|
||||
--- @param message? string
|
||||
--- @param message? string "Expected" message
|
||||
--- @param allow_alias? boolean Allow short type names: 'n', 's', 't', 'b', 'f', 'c'
|
||||
--- @return string?
|
||||
local function is_valid(param_name, val, validator, message, allow_alias)
|
||||
@ -866,18 +866,18 @@ do
|
||||
end
|
||||
|
||||
if not is_type(val, expected) then
|
||||
return string.format('%s: expected %s, got %s', param_name, expected, type(val))
|
||||
return ('%s: expected %s, got %s'):format(param_name, message or expected, type(val))
|
||||
end
|
||||
elseif vim.is_callable(validator) then
|
||||
-- Check user-provided validation function
|
||||
local valid, opt_msg = validator(val)
|
||||
if not valid then
|
||||
local err_msg =
|
||||
string.format('%s: expected %s, got %s', param_name, message or '?', tostring(val))
|
||||
|
||||
if opt_msg then
|
||||
err_msg = string.format('%s. Info: %s', err_msg, opt_msg)
|
||||
end
|
||||
local err_msg = ('%s: expected %s, got %s'):format(
|
||||
param_name,
|
||||
message or '?',
|
||||
tostring(val)
|
||||
)
|
||||
err_msg = opt_msg and ('%s. Info: %s'):format(err_msg, opt_msg) or err_msg
|
||||
|
||||
return err_msg
|
||||
end
|
||||
|
@ -83,9 +83,11 @@ local get_headings = function(bufnr)
|
||||
return headings
|
||||
end
|
||||
|
||||
--- @param qf_height? integer height of loclist window
|
||||
--- Shows an Outline (table of contents) of the current buffer, in the loclist.
|
||||
function M.show_toc()
|
||||
function M.show_toc(qf_height)
|
||||
local bufnr = api.nvim_get_current_buf()
|
||||
local bufname = api.nvim_buf_get_name(bufnr)
|
||||
local headings = get_headings(bufnr)
|
||||
if #headings == 0 then
|
||||
return
|
||||
@ -101,7 +103,10 @@ function M.show_toc()
|
||||
end
|
||||
vim.fn.setloclist(0, headings, ' ')
|
||||
vim.fn.setloclist(0, {}, 'a', { title = 'Table of contents' })
|
||||
vim.cmd.lopen()
|
||||
vim.cmd.lopen({ count = qf_height })
|
||||
vim.w.qf_toc = bufname
|
||||
-- reload syntax file after setting qf_toc variable
|
||||
vim.bo.filetype = 'qf'
|
||||
end
|
||||
|
||||
--- Jump to section
|
||||
|
@ -18,11 +18,14 @@ error('Cannot require a meta file')
|
||||
---@field captures string[]
|
||||
---@field patterns table<integer, (integer|string)[][]>
|
||||
---
|
||||
---@class TSLangMetadata
|
||||
---@field major_version integer
|
||||
---@field minor_version integer
|
||||
---@field patch_version integer
|
||||
---
|
||||
---@class TSLangInfo
|
||||
---@field abi_version integer
|
||||
---@field major_version? integer
|
||||
---@field minor_version? integer
|
||||
---@field patch_version? integer
|
||||
---@field metadata? TSLangMetadata -- ABI 15 only
|
||||
---@field state_count integer
|
||||
---@field fields string[]
|
||||
---@field symbols table<string,boolean>
|
||||
|
@ -26,6 +26,7 @@ function TSTree:root() end
|
||||
---@param end_col_old integer
|
||||
---@param end_row_new integer
|
||||
---@param end_col_new integer
|
||||
---@return TSTree
|
||||
---@nodoc
|
||||
function TSTree:edit(start_byte, end_byte_old, end_byte_new, start_row, start_col, end_row_old, end_col_old, end_row_new, end_col_new) end
|
||||
|
||||
|
@ -451,6 +451,8 @@ function M.inspect_tree(opts)
|
||||
end,
|
||||
})
|
||||
|
||||
api.nvim_buf_set_keymap(b, 'n', 'q', '<C-w>c', { desc = 'Close language tree window' })
|
||||
|
||||
local group = api.nvim_create_augroup('nvim.treesitter.dev', {})
|
||||
|
||||
api.nvim_create_autocmd('CursorMoved', {
|
||||
|
@ -63,15 +63,16 @@ end
|
||||
---@field active table<integer,vim.treesitter.highlighter>
|
||||
---@field bufnr integer
|
||||
---@field private orig_spelloptions string
|
||||
--- A map of highlight states.
|
||||
--- A map from window ID to highlight states.
|
||||
--- This state is kept during rendering across each line update.
|
||||
---@field private _highlight_states vim.treesitter.highlighter.State[]
|
||||
---@field private _highlight_states table<integer, vim.treesitter.highlighter.State[]>
|
||||
---@field private _queries table<string,vim.treesitter.highlighter.Query>
|
||||
---@field _conceal_line boolean?
|
||||
---@field _conceal_checked table<integer, boolean>
|
||||
---@field tree vim.treesitter.LanguageTree
|
||||
---@field private redraw_count integer
|
||||
---@field parsing boolean true if we are parsing asynchronously
|
||||
--- A map from window ID to whether we are currently parsing that window asynchronously
|
||||
---@field parsing table<integer, boolean>
|
||||
local TSHighlighter = {
|
||||
active = {},
|
||||
}
|
||||
@ -131,6 +132,8 @@ function TSHighlighter.new(tree, opts)
|
||||
self.redraw_count = 0
|
||||
self._conceal_checked = {}
|
||||
self._queries = {}
|
||||
self._highlight_states = {}
|
||||
self.parsing = {}
|
||||
|
||||
-- Queries for a specific language can be overridden by a custom
|
||||
-- string query... if one is not provided it will be looked up by file.
|
||||
@ -184,11 +187,12 @@ function TSHighlighter:destroy()
|
||||
end
|
||||
end
|
||||
|
||||
---@param win integer
|
||||
---@param srow integer
|
||||
---@param erow integer exclusive
|
||||
---@private
|
||||
function TSHighlighter:prepare_highlight_states(srow, erow)
|
||||
self._highlight_states = {}
|
||||
function TSHighlighter:prepare_highlight_states(win, srow, erow)
|
||||
self._highlight_states[win] = {}
|
||||
|
||||
self.tree:for_each_tree(function(tstree, tree)
|
||||
if not tstree then
|
||||
@ -211,7 +215,7 @@ function TSHighlighter:prepare_highlight_states(srow, erow)
|
||||
|
||||
-- _highlight_states should be a list so that the highlights are added in the same order as
|
||||
-- for_each_tree traversal. This ensures that parents' highlight don't override children's.
|
||||
table.insert(self._highlight_states, {
|
||||
table.insert(self._highlight_states[win], {
|
||||
tstree = tstree,
|
||||
next_row = 0,
|
||||
iter = nil,
|
||||
@ -220,10 +224,11 @@ function TSHighlighter:prepare_highlight_states(srow, erow)
|
||||
end)
|
||||
end
|
||||
|
||||
---@param win integer
|
||||
---@param fn fun(state: vim.treesitter.highlighter.State)
|
||||
---@package
|
||||
function TSHighlighter:for_each_highlight_state(fn)
|
||||
for _, state in ipairs(self._highlight_states) do
|
||||
function TSHighlighter:for_each_highlight_state(win, fn)
|
||||
for _, state in ipairs(self._highlight_states[win] or {}) do
|
||||
fn(state)
|
||||
end
|
||||
end
|
||||
@ -307,13 +312,14 @@ local function get_spell(capture_name)
|
||||
end
|
||||
|
||||
---@param self vim.treesitter.highlighter
|
||||
---@param win integer
|
||||
---@param buf integer
|
||||
---@param line integer
|
||||
---@param on_spell boolean
|
||||
---@param on_conceal boolean
|
||||
local function on_line_impl(self, buf, line, on_spell, on_conceal)
|
||||
local function on_line_impl(self, win, buf, line, on_spell, on_conceal)
|
||||
self._conceal_checked[line] = true
|
||||
self:for_each_highlight_state(function(state)
|
||||
self:for_each_highlight_state(win, function(state)
|
||||
local root_node = state.tstree:root()
|
||||
local root_start_row, _, root_end_row, _ = root_node:range()
|
||||
|
||||
@ -380,6 +386,7 @@ local function on_line_impl(self, buf, line, on_spell, on_conceal)
|
||||
api.nvim_buf_set_extmark(buf, ns, start_row, 0, {
|
||||
end_line = end_row,
|
||||
conceal_lines = '',
|
||||
invalidate = true,
|
||||
})
|
||||
end
|
||||
end
|
||||
@ -392,23 +399,24 @@ local function on_line_impl(self, buf, line, on_spell, on_conceal)
|
||||
end
|
||||
|
||||
---@private
|
||||
---@param _win integer
|
||||
---@param win integer
|
||||
---@param buf integer
|
||||
---@param line integer
|
||||
function TSHighlighter._on_line(_, _win, buf, line, _)
|
||||
function TSHighlighter._on_line(_, win, buf, line, _)
|
||||
local self = TSHighlighter.active[buf]
|
||||
if not self then
|
||||
return
|
||||
end
|
||||
|
||||
on_line_impl(self, buf, line, false, false)
|
||||
on_line_impl(self, win, buf, line, false, false)
|
||||
end
|
||||
|
||||
---@private
|
||||
---@param win integer
|
||||
---@param buf integer
|
||||
---@param srow integer
|
||||
---@param erow integer
|
||||
function TSHighlighter._on_spell_nav(_, _, buf, srow, _, erow, _)
|
||||
function TSHighlighter._on_spell_nav(_, win, buf, srow, _, erow, _)
|
||||
local self = TSHighlighter.active[buf]
|
||||
if not self then
|
||||
return
|
||||
@ -416,30 +424,31 @@ function TSHighlighter._on_spell_nav(_, _, buf, srow, _, erow, _)
|
||||
|
||||
-- Do not affect potentially populated highlight state. Here we just want a temporary
|
||||
-- empty state so the C code can detect whether the region should be spell checked.
|
||||
local highlight_states = self._highlight_states
|
||||
self:prepare_highlight_states(srow, erow)
|
||||
local highlight_states = self._highlight_states[win]
|
||||
self:prepare_highlight_states(win, srow, erow)
|
||||
|
||||
for row = srow, erow do
|
||||
on_line_impl(self, buf, row, true, false)
|
||||
on_line_impl(self, win, buf, row, true, false)
|
||||
end
|
||||
self._highlight_states = highlight_states
|
||||
self._highlight_states[win] = highlight_states
|
||||
end
|
||||
|
||||
---@private
|
||||
---@param win integer
|
||||
---@param buf integer
|
||||
---@param row integer
|
||||
function TSHighlighter._on_conceal_line(_, _, buf, row)
|
||||
function TSHighlighter._on_conceal_line(_, win, buf, row)
|
||||
local self = TSHighlighter.active[buf]
|
||||
if not self or not self._conceal_line or self._conceal_checked[row] then
|
||||
return
|
||||
end
|
||||
|
||||
-- Do not affect potentially populated highlight state.
|
||||
local highlight_states = self._highlight_states
|
||||
local highlight_states = self._highlight_states[win]
|
||||
self.tree:parse({ row, row })
|
||||
self:prepare_highlight_states(row, row)
|
||||
on_line_impl(self, buf, row, false, true)
|
||||
self._highlight_states = highlight_states
|
||||
self:prepare_highlight_states(win, row, row)
|
||||
on_line_impl(self, win, buf, row, false, true)
|
||||
self._highlight_states[win] = highlight_states
|
||||
end
|
||||
|
||||
---@private
|
||||
@ -459,20 +468,38 @@ end
|
||||
---@param buf integer
|
||||
---@param topline integer
|
||||
---@param botline integer
|
||||
function TSHighlighter._on_win(_, _, buf, topline, botline)
|
||||
function TSHighlighter._on_win(_, win, buf, topline, botline)
|
||||
local self = TSHighlighter.active[buf]
|
||||
if not self or self.parsing then
|
||||
if not self then
|
||||
return false
|
||||
end
|
||||
self.parsing = self.tree:parse({ topline, botline + 1 }, function(_, trees)
|
||||
if trees and self.parsing then
|
||||
self.parsing = false
|
||||
api.nvim__redraw({ buf = buf, valid = false, flush = false })
|
||||
end
|
||||
end) == nil
|
||||
self.redraw_count = self.redraw_count + 1
|
||||
self:prepare_highlight_states(topline, botline)
|
||||
return #self._highlight_states > 0
|
||||
self.parsing[win] = self.parsing[win]
|
||||
or nil
|
||||
== self.tree:parse({ topline, botline + 1 }, function(_, trees)
|
||||
if trees and self.parsing[win] then
|
||||
self.parsing[win] = false
|
||||
if api.nvim_win_is_valid(win) then
|
||||
api.nvim__redraw({ win = win, valid = false, flush = false })
|
||||
end
|
||||
end
|
||||
end)
|
||||
if not self.parsing[win] then
|
||||
self.redraw_count = self.redraw_count + 1
|
||||
self:prepare_highlight_states(win, topline, botline)
|
||||
else
|
||||
self:for_each_highlight_state(win, function(state)
|
||||
-- TODO(ribru17): Inefficient. Eventually all marks should be applied in on_buf, and all
|
||||
-- non-folded ranges of each open window should be merged, and iterators should only be
|
||||
-- created over those regions. This would also fix #31777.
|
||||
--
|
||||
-- Currently this is not possible because the parser discards previously parsed injection
|
||||
-- trees upon parsing a different region.
|
||||
state.iter = nil
|
||||
state.next_row = 0
|
||||
end)
|
||||
end
|
||||
local hl_states = self._highlight_states[win] or {}
|
||||
return #hl_states > 0
|
||||
end
|
||||
|
||||
api.nvim_set_decoration_provider(ns, {
|
||||
|
@ -956,7 +956,9 @@ function LanguageTree:_get_injection(match, metadata)
|
||||
local ft = vim.filetype.match({ filename = text })
|
||||
lang = ft and resolve_lang(ft)
|
||||
elseif name == 'injection.content' then
|
||||
ranges = get_node_ranges(node, self._source, metadata[id], include_children)
|
||||
for _, range in ipairs(get_node_ranges(node, self._source, metadata[id], include_children)) do
|
||||
ranges[#ranges + 1] = range
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -1080,8 +1082,8 @@ function LanguageTree:_edit(
|
||||
end_row_new,
|
||||
end_col_new
|
||||
)
|
||||
for _, tree in pairs(self._trees) do
|
||||
tree:edit(
|
||||
for i, tree in pairs(self._trees) do
|
||||
self._trees[i] = tree:edit(
|
||||
start_byte,
|
||||
end_byte_old,
|
||||
end_byte_new,
|
||||
@ -1268,12 +1270,13 @@ end
|
||||
local function tree_contains(tree, range)
|
||||
local tree_ranges = tree:included_ranges(false)
|
||||
|
||||
return Range.contains({
|
||||
tree_ranges[1][1],
|
||||
tree_ranges[1][2],
|
||||
tree_ranges[#tree_ranges][3],
|
||||
tree_ranges[#tree_ranges][4],
|
||||
}, range)
|
||||
for _, tree_range in ipairs(tree_ranges) do
|
||||
if Range.contains(tree_range, range) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
--- Determines whether {range} is contained in the |LanguageTree|.
|
||||
|
@ -979,8 +979,7 @@ function Query:iter_captures(node, source, start, stop, opts)
|
||||
|
||||
start, stop = value_or_node_range(start, stop, node)
|
||||
|
||||
-- Copy the tree to ensure it is valid during the entire lifetime of the iterator
|
||||
local tree = node:tree():copy()
|
||||
local tree = node:tree()
|
||||
local cursor = vim._create_ts_querycursor(node, self.query, start, stop, opts)
|
||||
|
||||
-- For faster checks that a match is not in the cache.
|
||||
@ -1079,8 +1078,7 @@ function Query:iter_matches(node, source, start, stop, opts)
|
||||
|
||||
start, stop = value_or_node_range(start, stop, node)
|
||||
|
||||
-- Copy the tree to ensure it is valid during the entire lifetime of the iterator
|
||||
local tree = node:tree():copy()
|
||||
local tree = node:tree()
|
||||
local cursor = vim._create_ts_querycursor(node, self.query, start, stop, opts)
|
||||
|
||||
local function iter()
|
||||
|
@ -238,8 +238,8 @@ function VersionRange:has(version)
|
||||
version = setmetatable(vim.deepcopy(version, true), Version)
|
||||
end
|
||||
if version then
|
||||
if version.prerelease ~= self.from.prerelease then
|
||||
return false
|
||||
if self.from == self.to then
|
||||
return version == self.from
|
||||
end
|
||||
return version >= self.from and (self.to == nil or version < self.to)
|
||||
end
|
||||
@ -310,9 +310,7 @@ function M.range(spec) -- Adapted from https://github.com/folke/lazy.nvim
|
||||
local from = semver --- @type vim.Version?
|
||||
local to = vim.deepcopy(semver, true) --- @type vim.Version?
|
||||
---@diagnostic disable: need-check-nil
|
||||
if mods == '' or mods == '=' then
|
||||
to.patch = to.patch + 1
|
||||
elseif mods == '<' then
|
||||
if mods == '<' then
|
||||
from = M._version({})
|
||||
elseif mods == '<=' then
|
||||
from = M._version({})
|
||||
|
@ -26,6 +26,8 @@
|
||||
</screenshots>
|
||||
|
||||
<releases>
|
||||
<release date="2025-07-12" version="0.11.3"/>
|
||||
<release date="2025-05-30" version="0.11.2"/>
|
||||
<release date="2025-04-26" version="0.11.1"/>
|
||||
<release date="2025-03-26" version="0.11.0"/>
|
||||
<release date="2025-01-29" version="0.10.4"/>
|
||||
|
@ -78,7 +78,7 @@ Comment[wa]=Asspougnî des fitchîs tecses
|
||||
Comment[zh_CN]=编辑文本文件
|
||||
Comment[zh_TW]=編輯文字檔
|
||||
TryExec=nvim
|
||||
Exec=nvim "%F"
|
||||
Exec=nvim %F
|
||||
Terminal=true
|
||||
Type=Application
|
||||
Keywords=Text;editor;
|
||||
|
@ -1,3 +1,9 @@
|
||||
" Tutor: New Style Tutor Plugin :h vim-tutor-mode
|
||||
" Maintainer: This runtime file is looking for a new maintainer.
|
||||
" Contributors: Phạm Bình An <phambinhanctb2004@gmail.com>
|
||||
" Original Author: Felipe Morales <hel.sheep@gmail.com>
|
||||
" Date: 2025 May 12
|
||||
|
||||
if exists('g:loaded_tutor_mode_plugin') || &compatible
|
||||
finish
|
||||
endif
|
||||
|
@ -127,6 +127,7 @@
|
||||
"eval"
|
||||
"sign"
|
||||
"abort"
|
||||
"substitute"
|
||||
] @keyword
|
||||
|
||||
(map_statement
|
||||
@ -252,6 +253,9 @@
|
||||
(heredoc
|
||||
(parameter) @keyword)
|
||||
|
||||
(script
|
||||
(parameter) @keyword)
|
||||
|
||||
[
|
||||
(marker_definition)
|
||||
(endmarker)
|
||||
@ -313,6 +317,9 @@
|
||||
(binary_operation
|
||||
"." @operator)
|
||||
|
||||
(lua_statement
|
||||
"=" @keyword)
|
||||
|
||||
; Punctuation
|
||||
[
|
||||
"("
|
||||
|
@ -14,8 +14,8 @@ syn keyword DiagnosticError ERROR[:]
|
||||
syn keyword DiagnosticWarn WARNING[:]
|
||||
syn keyword DiagnosticOk OK[:]
|
||||
" Note: hs=e starts higlighting on the title line (instead of the "===" line).
|
||||
syn match helpSectionDelim /^======*\n.*$/hs=e
|
||||
highlight helpSectionDelim gui=reverse cterm=reverse
|
||||
syn match healthHeadingChar "=" conceal cchar= contained containedin=helpSectionDelim
|
||||
syn match healthSectionDelim /^======*\n.*$/hs=e
|
||||
highlight default healthSectionDelim gui=reverse cterm=reverse
|
||||
syn match healthHeadingChar "=" conceal cchar= contained containedin=healthSectionDelim
|
||||
|
||||
let b:current_syntax = "checkhealth"
|
||||
|
@ -19,7 +19,7 @@ syn match qfError "error" contained
|
||||
syn cluster qfType contains=qfError
|
||||
|
||||
" Hide file name and line number for help outline (TOC).
|
||||
if has_key(w:, 'qf_toc') || get(w:, 'quickfix_title') =~# '\<TOC$'
|
||||
if has_key(w:, 'qf_toc') || get(w:, 'quickfix_title') =~# '\<TOC$\|\<Table of contents\>'
|
||||
setlocal conceallevel=3 concealcursor=nc
|
||||
syn match Ignore "^[^|]*|[^|]*| " conceal
|
||||
endif
|
||||
|
@ -1,5 +1,7 @@
|
||||
# Welcome to the Neovim Tutorial
|
||||
|
||||
# Chapter 1
|
||||
|
||||
Neovim is a very powerful editor that has many commands, too many to explain in
|
||||
a tutorial such as this. This tutorial is designed to describe enough of the
|
||||
commands that you will be able to easily use Neovim as an all-purpose editor.
|
||||
@ -464,7 +466,7 @@ Now go on to the next lesson.
|
||||
# Lesson 4.1: CURSOR LOCATION AND FILE STATUS
|
||||
|
||||
** Type `<C-g>`{normal} to show your location in a file and the file status.
|
||||
Type `G`{normal} to move to a line in the file. **
|
||||
Type `{count}G`{normal} to move to line {count} in the file. **
|
||||
|
||||
NOTE: Read the entire lesson before executing any of these steps!!
|
||||
|
||||
@ -905,26 +907,7 @@ You can find help on just about any subject, by giving an argument to the
|
||||
:help insert-index
|
||||
:help user-manual
|
||||
~~~
|
||||
# Lesson 7.2: CREATE A STARTUP SCRIPT
|
||||
|
||||
** Enable Neovim features. **
|
||||
|
||||
Neovim is a very configurable editor. You can customise it any way you like.
|
||||
To start using more features create an "init.vim" file.
|
||||
|
||||
1. Start editing the "init.vim" file.
|
||||
|
||||
`:call mkdir(stdpath('config'),'p')`{vim}
|
||||
`:exe 'edit' stdpath('config').'/init.vim'`{vim}
|
||||
|
||||
2. Write the file with:
|
||||
|
||||
`:w`{vim}
|
||||
|
||||
You can add all your preferred settings to this "init.vim" file.
|
||||
For more information type `:help init.vim`{vim}.
|
||||
|
||||
# Lesson 7.3: COMPLETION
|
||||
# Lesson 7.2: COMPLETION
|
||||
|
||||
** Command line completion with `<C-d>`{normal} and `<Tab>`{normal}. **
|
||||
|
||||
@ -934,14 +917,46 @@ For more information type `:help init.vim`{vim}.
|
||||
|
||||
3. Press `<C-d>`{normal} and Neovim will show a list of commands beginning with "e".
|
||||
|
||||
4. Press `<Tab>`{normal} and Neovim will complete the command name to ":edit".
|
||||
4. Press `<Tab>`{normal} and Neovim will show a menu with possible completions
|
||||
(or complete the match, if the entered command is unique, e.g.
|
||||
":ed`<Tab>`{normal}" will be completed to ":edit").
|
||||
|
||||
5. Now add a space and the start of an existing file name: `:edit FIL`{vim}
|
||||
5. Use `<Tab>`{normal} or `<C-n>`{normal} to go to the next match. Or use
|
||||
`<S-Tab>`{normal} or `<C-p>`{normal} to go to the previous match.
|
||||
|
||||
6. Press `<Tab>`{normal}. Neovim will complete the name ("FIL" -> "FILE", if it is unique).
|
||||
6. Choose the entry `edit`{vim}. Now you can see that the word `edit`{vim}
|
||||
have been automatically inserted to the command line.
|
||||
|
||||
7. Now add a space and the start of an existing file name: `:edit FIL`{vim}
|
||||
|
||||
8. Press `<Tab>`{normal}. Vim will show a completion menu with list of file
|
||||
names that start with `FIL`
|
||||
|
||||
NOTE: Completion works for many commands. It is especially useful for `:help`{vim}.
|
||||
|
||||
# Lesson 7.3: CONFIGURING NVIM
|
||||
|
||||
Neovim is a very configurable editor. You can customise it any way you like. To
|
||||
start using more features, create a vimrc file, which can be "init.lua" if you
|
||||
want to use Lua, or "init.vim" if you want to use Vimscript. We'll use
|
||||
"init.lua" in this lesson.
|
||||
|
||||
1. Start editing the "init.lua" file.
|
||||
|
||||
`:exe 'edit' stdpath('config')..'/init.lua'`{vim}
|
||||
|
||||
2. Copy the example configuration in Lua to your "init.lua" file.
|
||||
|
||||
`:read $VIMRUNTIME/example_init.lua`{vim}
|
||||
|
||||
3. Write the file (also creates any missing parent directories):
|
||||
|
||||
`:w ++p`{vim}
|
||||
|
||||
4. Next time you start Neovim, you can quickly open this vimrc file with:
|
||||
|
||||
`:e $MYVIMRC`{vim}
|
||||
|
||||
# Lesson 7 SUMMARY
|
||||
|
||||
1. Type `:help`{vim}
|
||||
@ -953,13 +968,21 @@ NOTE: Completion works for many commands. It is especially useful for `:help`{vi
|
||||
|
||||
4. Type `:q`{vim} to close the help window
|
||||
|
||||
5. Create an init.vim startup script to keep your preferred settings.
|
||||
5. While in command mode, press `<C-d>`{normal} to see possible completions.
|
||||
Press `<Tab>`{normal} to use the completion menu and select a match.
|
||||
|
||||
6. While in command mode, press `<C-d>`{normal} to see possible completions.
|
||||
Press `<Tab>`{normal} to use one completion.
|
||||
6. Create your configuration file to save your preferred settings. You can
|
||||
revisit it with `:e $MYVIMRC`{vim}.
|
||||
|
||||
# What's next?
|
||||
|
||||
Run `:help nvim-quickstart`{vim} for more information on extending Nvim.
|
||||
|
||||
# CONCLUSION
|
||||
|
||||
This concludes Chapter 1 of the Vim Tutor. Consider continuing with
|
||||
[Chapter 2](@tutor:vim-02-beginner).
|
||||
|
||||
This was intended to give a brief overview of the Neovim editor, just enough to
|
||||
allow you to use it fairly easily. It is far from complete as Neovim has
|
||||
many many more commands. Consult the help often.
|
||||
|
@ -1,44 +1,44 @@
|
||||
{
|
||||
"expect": {
|
||||
"103": "The cow jumped over the moon.",
|
||||
"125": "There is some text missing from this line.",
|
||||
"126": "There is some text missing from this line.",
|
||||
"145": "There is some text missing from this line.",
|
||||
"146": "There is some text missing from this line.",
|
||||
"147": "There is also some text missing here.",
|
||||
"148": "There is also some text missing here.",
|
||||
"216": "There are some words that don't belong in this sentence.",
|
||||
"232": "Somebody typed the end of this line twice.",
|
||||
"271": -1,
|
||||
"290": "This line of words is cleaned up.",
|
||||
"307": "1) Roses are red,",
|
||||
"308": "3) Violets are blue,",
|
||||
"309": "6) Sugar is sweet",
|
||||
"310": "7) And so are you.",
|
||||
"311": "7) And so are you.",
|
||||
"105": "The cow jumped over the moon.",
|
||||
"127": "There is some text missing from this line.",
|
||||
"128": "There is some text missing from this line.",
|
||||
"147": "There is some text missing from this line.",
|
||||
"148": "There is some text missing from this line.",
|
||||
"149": "There is also some text missing here.",
|
||||
"150": "There is also some text missing here.",
|
||||
"218": "There are some words that don't belong in this sentence.",
|
||||
"234": "Somebody typed the end of this line twice.",
|
||||
"273": -1,
|
||||
"292": "This line of words is cleaned up.",
|
||||
"309": "1) Roses are red,",
|
||||
"310": "3) Violets are blue,",
|
||||
"311": "6) Sugar is sweet",
|
||||
"312": "7) And so are you.",
|
||||
"313": "7) And so are you.",
|
||||
"333": "Fix the errors on this line and replace them with undo.",
|
||||
"379": -1,
|
||||
"380": -1,
|
||||
"314": "7) And so are you.",
|
||||
"315": "7) And so are you.",
|
||||
"335": "Fix the errors on this line and replace them with undo.",
|
||||
"381": -1,
|
||||
"382": -1,
|
||||
"398": "When this line was typed in, someone pressed some wrong keys!",
|
||||
"399": "When this line was typed in, someone pressed some wrong keys!",
|
||||
"419": "This line has a few words that need changing using the change operator.",
|
||||
"420": "This line has a few words that need changing using the change operator.",
|
||||
"440": "The end of this line needs to be corrected using the c$ command.",
|
||||
"441": "The end of this line needs to be corrected using the c$ command.",
|
||||
"504": -1,
|
||||
"523": -1,
|
||||
"546": "Usually the best time to see the flowers is in the spring.",
|
||||
"741": -1,
|
||||
"746": -1,
|
||||
"762": "This line will allow you to practice appending text to a line.",
|
||||
"763": "This line will allow you to practice appending text to a line.",
|
||||
"783": "Adding 123 to 456 gives you 579.",
|
||||
"784": "Adding 123 to 456 gives you 579.",
|
||||
"810": "a) This is the first item.",
|
||||
"811": "b) This is the second item."
|
||||
"383": -1,
|
||||
"384": -1,
|
||||
"400": "When this line was typed in, someone pressed some wrong keys!",
|
||||
"401": "When this line was typed in, someone pressed some wrong keys!",
|
||||
"421": "This line has a few words that need changing using the change operator.",
|
||||
"422": "This line has a few words that need changing using the change operator.",
|
||||
"442": "The end of this line needs to be corrected using the c$ command.",
|
||||
"443": "The end of this line needs to be corrected using the c$ command.",
|
||||
"506": -1,
|
||||
"525": -1,
|
||||
"548": "Usually the best time to see the flowers is in the spring.",
|
||||
"743": -1,
|
||||
"748": -1,
|
||||
"764": "This line will allow you to practice appending text to a line.",
|
||||
"765": "This line will allow you to practice appending text to a line.",
|
||||
"785": "Adding 123 to 456 gives you 579.",
|
||||
"786": "Adding 123 to 456 gives you 579.",
|
||||
"812": "a) This is the first item.",
|
||||
"813": "b) This is the second item."
|
||||
}
|
||||
}
|
||||
|
194
runtime/tutor/en/vim-02-beginner.tutor
Normal file
194
runtime/tutor/en/vim-02-beginner.tutor
Normal file
@ -0,0 +1,194 @@
|
||||
# Welcome to the Neovim Tutorial
|
||||
|
||||
# Chapter 2
|
||||
|
||||
Hic Sunt Dracones: if this is your first exposure to vim and you
|
||||
intended to avail yourself of the introductory chapter, kindly type
|
||||
on the command line of the Vim editor
|
||||
~~~ cmd
|
||||
:Tutor vim-01-beginner
|
||||
~~~
|
||||
Or just open the [first chapter](@tutor:vim-01-beginner) of the tutor at the link.
|
||||
|
||||
The approximate time required to complete this chapter is 8-10 minutes,
|
||||
depending upon how much time is spent with experimentation.
|
||||
|
||||
|
||||
# Lesson 2.1.1: THE NAMED REGISTERS
|
||||
|
||||
** Store two yanked words concurrently and then paste them **
|
||||
|
||||
1. Move the cursor to the line below marked ✓
|
||||
|
||||
2. Navigate to any point on the word 'Edward' and type `"ayiw`{normal}
|
||||
|
||||
**MNEMONIC**: *into register(") named (a) (y)ank (i)nner (w)ord*
|
||||
|
||||
3. Navigate forward to the word 'cookie' (`fk`{normal} or `2fc`{normal}
|
||||
or `$2b`{normal} or `/co`{normal} `<ENTER>`{normal}) and type `"byiw`{normal}
|
||||
|
||||
4. Navigate to any point on the word 'Vince' and type `ciw<CTRL-r>a<ESC>`{normal}
|
||||
|
||||
**MNEMONIC**: *(c)hange (i)nner (w)ord with <contents of (r)egister> named (a)*
|
||||
|
||||
5. Navigate to any point on the word 'cake' and type `ciw<CTRL-r>b<ESC>`{normal}
|
||||
|
||||
a) Edward will henceforth be in charge of the cookie rations
|
||||
b) In this capacity, Vince will have sole cake discretionary powers
|
||||
|
||||
NOTE: Delete also works into registers, i.e. `"sdiw`{normal} will delete
|
||||
the word under the cursor into register s.
|
||||
|
||||
REFERENCE: [Registers](registers)
|
||||
[Named Registers](quotea)
|
||||
[Motion](text-objects)
|
||||
[CTRL-R](i_CTRL-R)
|
||||
|
||||
|
||||
# Lesson 2.1.2: THE EXPRESSION REGISTER
|
||||
|
||||
** Insert the results of calculations on the fly **
|
||||
|
||||
1. Move the cursor to the line below marked ✗
|
||||
|
||||
2. Navigate to any point on the supplied number
|
||||
|
||||
3. Type `ciw<CTRL-r>=`{normal}60\*60\*24 `<ENTER>`{normal}
|
||||
|
||||
4. On the next line, enter insert mode and add today's date with
|
||||
`<CTRL-r>=`{normal}`system('date')`{vim} `<ENTER>`{normal}
|
||||
|
||||
NOTE: All calls to system are OS dependent, e.g. on Windows use
|
||||
`system('date /t')`{vim} or `:r!date /t`{vim}
|
||||
|
||||
I have forgotten the exact number of seconds in a day, is it 84600?
|
||||
Today's date is:
|
||||
|
||||
NOTE: the same can be achieved with `:pu=`{normal}`system('date')`{vim}
|
||||
or, with fewer keystrokes `:r!date`{vim}
|
||||
|
||||
REFERENCE: [Expression Register](quote=)
|
||||
|
||||
|
||||
# Lesson 2.1.3: THE NUMBERED REGISTERS
|
||||
|
||||
** Press `yy`{normal} and `dd`{normal} to witness their effect on the registers **
|
||||
|
||||
1. Move the cursor to the line below marked ✓
|
||||
|
||||
2. yank the zeroth line, then inspect registers with `:reg`{vim} `<ENTER>`{normal}
|
||||
|
||||
3. delete line 0. with `"cdd`{normal}, then inspect registers
|
||||
(Where do you expect line 0 to be?)
|
||||
|
||||
4. continue deleting each successive line, inspecting `:reg`{vim} as you go
|
||||
|
||||
NOTE: You should notice that old full-line deletions move down the list
|
||||
as new full-line deletions are added
|
||||
|
||||
5. Now (p)aste the following registers in order; c, 7, 4, 8, 2. i.e. `"7p`{normal}
|
||||
|
||||
0. This
|
||||
9. wobble
|
||||
8. secret
|
||||
7. is
|
||||
6. on
|
||||
5. axis
|
||||
4. a
|
||||
3. war
|
||||
2. message
|
||||
1. tribute
|
||||
|
||||
|
||||
NOTE: Whole line deletions (`dd`{normal}) are much longer lived in the
|
||||
numbered registers than whole line yanks, or deletions involving
|
||||
smaller movements
|
||||
|
||||
REFERENCE: [Numbered Registers](quote0)
|
||||
|
||||
|
||||
# Lesson 2.1.4: THE BEAUTY OF MARKS
|
||||
|
||||
** Code monkey arithmetic avoidance **
|
||||
|
||||
NOTE: a common conundrum when coding is moving around large chunks of code.
|
||||
The following technique helps avoid number line calculations associated
|
||||
with operations like `"a147d`{normal} or `:945,1091d a`{vim} or even worse
|
||||
using `i<CTRL-r>=`{normal}1091-945 `<ENTER>`{normal} first
|
||||
|
||||
1. Move the cursor to the line below marked ✓
|
||||
|
||||
2. Go to the first line of the function and mark it with `ma`{normal}
|
||||
|
||||
NOTE: exact position on line is NOT important!
|
||||
|
||||
3. Navigate to the end of the line and then the end of the code block
|
||||
with `$%`{normal}
|
||||
|
||||
4. Delete the block into register a with `"ad'a`{normal}
|
||||
|
||||
**MNEMONIC**: *into register(") named (a) put the (d)eletion from the cursor to
|
||||
the LINE containing mark(') (a)*
|
||||
|
||||
5. Paste the block between BBB and CCC `"ap`{normal}
|
||||
|
||||
NOTE: practice this operation multiple times to become fluent `ma$%"ad'a`{normal}
|
||||
|
||||
~~~ cmd
|
||||
AAA
|
||||
function itGotRealBigRealFast() {
|
||||
if ( somethingIsTrue ) {
|
||||
doIt()
|
||||
}
|
||||
// the taxonomy of our function has changed and it
|
||||
// no longer makes alphabetical sense in its current position
|
||||
|
||||
// imagine hundreds of lines of code
|
||||
|
||||
// naively you could navigate to the start and end and record or
|
||||
// remember each line number
|
||||
}
|
||||
BBB
|
||||
CCC
|
||||
~~~
|
||||
|
||||
NOTE: marks and registers do not share a namespace, therefore register a is
|
||||
completely independent of mark a. This is not true of registers and
|
||||
macros.
|
||||
|
||||
REFERENCE: [Marks](marks)
|
||||
[Mark Motions](mark-motions) (difference between ' and \`)
|
||||
|
||||
|
||||
# Lesson 2.1 SUMMARY
|
||||
|
||||
1. To store (yank, delete) text into, and retrieve (paste) from, a total of
|
||||
26 registers (a-z)
|
||||
2. Yank a whole word from anywhere within a word: `yiw`{normal}
|
||||
3. Change a whole word from anywhere within a word: `ciw`{normal}
|
||||
4. Insert text directly from registers in insert mode: `<CTRL-r>a`{normal}
|
||||
|
||||
5. Insert the results of simple arithmetic operations:
|
||||
`<CTRL-r>=`{normal}60\*60 `<ENTER>`{normal} in insert mode
|
||||
6. Insert the results of system calls:
|
||||
`<CTRL-r>=`{normal}`system('ls -1')`{vim} in insert mode
|
||||
|
||||
7. Inspect registers with `:reg`{vim}
|
||||
8. Learn the final destination of whole line deletions: `dd`{normal} in
|
||||
the numbered registers, i.e. descending from register 1 - 9. Appreciate
|
||||
that whole line deletions are preserved in the numbered registers longer
|
||||
than any other operation
|
||||
9. Learn the final destination of all yanks in the numbered registers and
|
||||
how ephemeral they are
|
||||
|
||||
10. Place marks from command mode `m[a-zA-Z0-9]`{normal}
|
||||
11. Move line-wise to a mark with `'`{normal}
|
||||
|
||||
|
||||
# CONCLUSION
|
||||
|
||||
This concludes chapter two of the Vim Tutor. It is a work in progress.
|
||||
|
||||
This chapter was written by Paul D. Parker.
|
||||
|
||||
Modified for vim-tutor-mode by Restorer.
|
10
runtime/tutor/en/vim-02-beginner.tutor.json
Normal file
10
runtime/tutor/en/vim-02-beginner.tutor.json
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"expect": {
|
||||
"36": -1,
|
||||
"37": "b) In this capacity, Edward will have sole cookie discretionary powers",
|
||||
"64": "I have forgotten the exact number of seconds in a day, is it 86400",
|
||||
"65": -1,
|
||||
"91": -1,
|
||||
"138": -1
|
||||
}
|
||||
}
|
@ -31,7 +31,7 @@ NOTE: 以下の練習用コマンドにはこの文章を変更するものも
|
||||
また、次のようにコマンドを実行するよう求められることや、(後で詳しく説明します。)
|
||||
|
||||
`:help`{vim} `<Enter>`{normal}
|
||||
|
||||
|
||||
キーシークエンスを押すこともあります。
|
||||
~~~ normal
|
||||
<Esc>0f<Space>d3wP$P
|
||||
@ -465,8 +465,8 @@ NOTE: タイプ中の間違いはバックスペースキーを使って直す
|
||||
|
||||
# レッスン 4.1: 位置とファイルの情報
|
||||
|
||||
** ファイル内での位置とファイルの状態を表示するには `<C-g>`{normal} をタイプします。ファイ
|
||||
ル内のある行に移動するには `G`{normal} をタイプします。 **
|
||||
** ファイル内での位置とファイルの状態を表示するには `<C-g>`{normal} をタイプします。
|
||||
ファイル内の{count}行に移動するには `{count}G`{normal} をタイプします。 **
|
||||
|
||||
NOTE: ステップを実行する前に、このレッスン全てに目を通しましょう!!
|
||||
|
||||
@ -875,7 +875,7 @@ NOTE: 1つの検索コマンドだけ大文字小文字の区別をやめたい
|
||||
~~~
|
||||
# レッスン 7.1: ヘルプコマンド
|
||||
|
||||
** Use the online help system. **
|
||||
** オンラインヘルプシステムを使用する **
|
||||
|
||||
Neovim には広範にわたるオンラインヘルプシステムがあります。
|
||||
|
||||
@ -895,27 +895,7 @@ Neovim には広範にわたるオンラインヘルプシステムがありま
|
||||
:help insert-index
|
||||
:help user-manual
|
||||
~~~
|
||||
|
||||
# レッスン 7.2: 起動スクリプトの作成
|
||||
|
||||
** Neovim の特徴を発揮する **
|
||||
|
||||
Neovim はとても自由度の高いエディタです。あなたの好きなようにカスタマイズするこ
|
||||
とができます。より多くの機能を使いはじめるには "init.vim" ファイルを作成します。
|
||||
|
||||
1. "init.vim" ファイルの編集を開始します。
|
||||
|
||||
`:call mkdir(stdpath('config'),'p')`{vim}
|
||||
`:exe 'edit' stdpath('config').'/init.vim'`{vim}
|
||||
|
||||
2. 以下のようにしてファイルを保存します。
|
||||
|
||||
`:w`{vim}
|
||||
|
||||
この "init.vim" ファイルへ、お好みの設定を追加することができます。
|
||||
より多くの情報を得るには `:help init.vim`{vim} とタイプします。
|
||||
|
||||
# レッスン 7.3: 補完
|
||||
# レッスン 7.2: 補完
|
||||
|
||||
** `<C-d>`{normal} と `<Tab>`{normal} でコマンドラインを補完する **
|
||||
|
||||
@ -925,14 +905,45 @@ Neovim はとても自由度の高いエディタです。あなたの好きな
|
||||
|
||||
3. `<C-d>`{normal} を押すと Neovim は "e" から始まるコマンドの一覧を表示します。
|
||||
|
||||
4. `<Tab>`{normal} とタイプすると Neoim は ":edit" というコマンド名を補完します。
|
||||
4. `<Tab>`{normal} を押すと、Neovim は可能な補完候補のメニューを表示します
|
||||
(または、ただの一つのマッチがあるときは、補完します。
|
||||
例: ":ed`<Tab>`{normal}" は":edit"に補完されます)。
|
||||
|
||||
5. さらに空白と、既存のファイル名の始まりを加えます: `:edit FIL`{vim}
|
||||
5. 次のマッチに移動するには `<Tab>`{normal} または `<C-n>`{normal}を使用し、
|
||||
前のマッチに移動するには `<S-Tab>`{normal} または `<C-p>`{normal}を使用します。
|
||||
|
||||
6. `<Tab>`{normal} を押すと Neovim は名前を補完します。("FIL" -> "FILE"、重複しない場合)
|
||||
6. `edit`{vim} を選択すると、コマンドラインに`edit` が挿入されます。
|
||||
|
||||
7. さらに空白と、既存のファイル名の始まりを加えます: `:edit FIL`{vim}
|
||||
|
||||
8. `<Tab>`{normal}を押すと、Vim は `FIL` で始まるファイル名の候補リストを含む補完メニューを
|
||||
表示します。
|
||||
|
||||
NOTE: 補完は多くのコマンドで動作します。特に `:help`{vim} の際に役立ちます。
|
||||
|
||||
# レッスン 7.3: 設定ファイルの作成
|
||||
|
||||
Neovim はとても自由度の高いエディタです。あなたの好きなようにカスタマイズするこ
|
||||
とができます。より多くの機能を使い始めるには設定ファイルを作成します。 Lua を使
|
||||
いたい場合は "init.lua" にし、Vimscript を使いたい場合は "init.vim" にします。
|
||||
このレッスンでは "init.lua" を使います。
|
||||
|
||||
1. `"init.lua"` ファイルを編集します。
|
||||
|
||||
`:exe 'edit' stdpath('config')..'/init.lua'`{vim}
|
||||
|
||||
2. Lua の例の設定を "init.lua" にコピーします。
|
||||
|
||||
`:read $VIMRUNTIME/example_init.lua`{vim}
|
||||
|
||||
3. ファイルを書き込みます(必要に応じて親ディレクトリも作成されます):
|
||||
|
||||
`:w ++p`{vim}
|
||||
|
||||
4. 次回 Neovim を起動したときに、以下のコマンドでこの設定ファイルを開けます:
|
||||
|
||||
`:e $MYVIMRC`{vim}
|
||||
|
||||
# レッスン 7 要約
|
||||
|
||||
1. ヘルプウィンドウを開くには `:help`{vim} とするか `<F1>`{normal} を押す。
|
||||
@ -943,11 +954,12 @@ NOTE: 補完は多くのコマンドで動作します。特に `:help`{vim} の
|
||||
|
||||
4. ヘルプウィンドウを閉じるには `:q`{vim} とタイプする。
|
||||
|
||||
5. お好みの設定を保つには init.vim 起動スクリプトを作成する。
|
||||
|
||||
6. : command で可能な補完を見るには `<C-d>`{normal} をタイプする。
|
||||
5. コマンドラインモードで可能な補完を見るには `<C-d>`{normal} をタイプする。
|
||||
補完を使用するには `<Tab>`{normal} を押す。
|
||||
|
||||
6. お好みの設定を保つには設定ファイルを作成する。作成した設定ファイルは
|
||||
`:e $MYVIMRC`{vim} でいつでも開き直せます。
|
||||
|
||||
# おわりに
|
||||
|
||||
これにて Neovim のチュートリアルを終わります。エディタを簡単に、しかも充分に使う
|
||||
|
@ -17,15 +17,8 @@ Table of contents:
|
||||
|
||||
## SETTING UP *setting-up*
|
||||
|
||||
First, you'll need to enable "debug" mode
|
||||
~~~ cmd
|
||||
:let g:tutor_debug = 1
|
||||
~~~
|
||||
This will allow saving changes to the tutor files and will disable conceals, so
|
||||
you can more easily check your changes.
|
||||
|
||||
After this, create a new .tutor file (we will be practicing on this very file, so you
|
||||
don't need to do this now):
|
||||
Create a new .tutor file (we will be practicing on this very file, so you don't
|
||||
need to do this now):
|
||||
~~~ cmd
|
||||
:e new-tutorial.tutor
|
||||
~~~
|
||||
|
@ -1,35 +1,35 @@
|
||||
{
|
||||
"expect": {
|
||||
"63": "This is text with **important information**",
|
||||
"64": "This is text with **important information**",
|
||||
"71": "TODO: Document '&variable'",
|
||||
"72": "TODO: Document '&variable'",
|
||||
"78": "# This is a level 1 header",
|
||||
"79": "# This is a level 1 header",
|
||||
"80": "### This is a level 3 header",
|
||||
"81": "### This is a level 3 header",
|
||||
"82": "# This is a header with a label {*label*}",
|
||||
"83": "# This is a header with a label {*label*}",
|
||||
"108": "A link to help for the ['breakindent']('breakindent') option",
|
||||
"109": "A link to help for the ['breakindent']('breakindent') option",
|
||||
"123": "A link to the [Links](*links*) section",
|
||||
"124": "A link to the [Links](*links*) section",
|
||||
"139": "A link to [the vim-tutor-mode tutorial](@tutor:tutor)",
|
||||
"140": "A link to [the vim-tutor-mode tutorial](@tutor:tutor)",
|
||||
"157": "~~~ viml",
|
||||
"158": "echom 'the value of &number is'.string(&number)",
|
||||
"159": "~~~",
|
||||
"161": "~~~ viml",
|
||||
"162": "echom 'the value of &number is'.string(&number)",
|
||||
"163": "~~~",
|
||||
"188": "~~~ normal",
|
||||
"189": "d2w",
|
||||
"190": "~~~",
|
||||
"192": "~~~ normal",
|
||||
"193": "d2w",
|
||||
"194": "~~~",
|
||||
"206": "`d2w`{normal}",
|
||||
"207": "`d2w`{normal}",
|
||||
"244": -1
|
||||
"56": "This is text with **important information**",
|
||||
"57": "This is text with **important information**",
|
||||
"64": "TODO: Document '&variable'",
|
||||
"65": "TODO: Document '&variable'",
|
||||
"71": "# This is a level 1 header",
|
||||
"72": "# This is a level 1 header",
|
||||
"73": "### This is a level 3 header",
|
||||
"74": "### This is a level 3 header",
|
||||
"75": "# This is a header with a label {*label*}",
|
||||
"76": "# This is a header with a label {*label*}",
|
||||
"101": "A link to help for the ['breakindent']('breakindent') option",
|
||||
"102": "A link to help for the ['breakindent']('breakindent') option",
|
||||
"116": "A link to the [Links](*links*) section",
|
||||
"117": "A link to the [Links](*links*) section",
|
||||
"132": "A link to [the vim-tutor-mode tutorial](@tutor:tutor)",
|
||||
"133": "A link to [the vim-tutor-mode tutorial](@tutor:tutor)",
|
||||
"150": "~~~ viml",
|
||||
"151": "echom 'the value of &number is'.string(&number)",
|
||||
"152": "~~~",
|
||||
"154": "~~~ viml",
|
||||
"155": "echom 'the value of &number is'.string(&number)",
|
||||
"156": "~~~",
|
||||
"181": "~~~ normal",
|
||||
"182": "d2w",
|
||||
"183": "~~~",
|
||||
"185": "~~~ normal",
|
||||
"186": "d2w",
|
||||
"187": "~~~",
|
||||
"199": "`d2w`{normal}",
|
||||
"200": "`d2w`{normal}",
|
||||
"237": -1
|
||||
}
|
||||
}
|
||||
|
@ -293,6 +293,10 @@ preprocess_patch() {
|
||||
LC_ALL=C sed -Ee 's/( [ab]\/src\/nvim)\/option\.h/\1\/option_vars.h/g' \
|
||||
"$file" > "$file".tmp && mv "$file".tmp "$file"
|
||||
|
||||
# Rename runtime/doc/eval.txt to runtime/doc/vimeval.txt
|
||||
LC_ALL=C sed -Ee 's/( [ab]\/runtime\/doc)\/eval\.txt/\1\/vimeval.txt/g' \
|
||||
"$file" > "$file".tmp && mv "$file".tmp "$file"
|
||||
|
||||
# Rename version*.txt to news.txt
|
||||
LC_ALL=C sed -Ee 's/( [ab]\/runtime\/doc)\/version[0-9]+\.txt/\1\/news.txt/g' \
|
||||
"$file" > "$file".tmp && mv "$file".tmp "$file"
|
||||
|
2
src/cjson/lua_cjson.c
vendored
2
src/cjson/lua_cjson.c
vendored
@ -82,7 +82,7 @@
|
||||
#define DEFAULT_ENCODE_INVALID_NUMBERS 0
|
||||
#define DEFAULT_DECODE_INVALID_NUMBERS 1
|
||||
#define DEFAULT_ENCODE_KEEP_BUFFER 1
|
||||
#define DEFAULT_ENCODE_NUMBER_PRECISION 14
|
||||
#define DEFAULT_ENCODE_NUMBER_PRECISION 16
|
||||
#define DEFAULT_ENCODE_EMPTY_TABLE_AS_OBJECT 0
|
||||
#define DEFAULT_DECODE_ARRAY_WITH_ARRAY_MT 0
|
||||
#define DEFAULT_ENCODE_ESCAPE_FORWARD_SLASH 1
|
||||
|
@ -359,11 +359,11 @@ local function norm_text(x, special)
|
||||
x = x:gsub([=[%|?(nvim_[^.()| ]+)%(?%)?%|?]=], 'vim.api.%1')
|
||||
-- TODO: Remove backticks when LuaLS resolves: https://github.com/LuaLS/lua-language-server/issues/2889
|
||||
-- "|foo|" => "`:help foo`"
|
||||
x = x:gsub([=[|([^ ]+)|]=], '`:help %1`')
|
||||
x = x:gsub([=[|([^%s|]+)|]=], '`:help %1`')
|
||||
end
|
||||
|
||||
return (
|
||||
x:gsub('|([^ ]+)|', '`%1`')
|
||||
x:gsub('|([^%s|]+)|', '`%1`')
|
||||
:gsub('\n*>lua', '\n\n```lua')
|
||||
:gsub('\n*>vim', '\n\n```vim')
|
||||
:gsub('\n+<$', '\n```')
|
||||
@ -949,17 +949,17 @@ local CONFIG = {
|
||||
render = render_api_keyset_meta,
|
||||
},
|
||||
{
|
||||
path = 'runtime/doc/builtin.txt',
|
||||
path = 'runtime/doc/vimfn.txt',
|
||||
funcs = get_eval_meta,
|
||||
render = render_eval_doc,
|
||||
header = {
|
||||
'*builtin.txt* Nvim',
|
||||
'*vimfn.txt* Nvim',
|
||||
'',
|
||||
'',
|
||||
'\t\t NVIM REFERENCE MANUAL',
|
||||
'',
|
||||
'',
|
||||
'Builtin functions\t\t*vimscript-functions* *builtin-functions*',
|
||||
'Vimscript functions\t*vimscript-functions* *builtin-functions* *builtin.txt*',
|
||||
'',
|
||||
'For functions grouped by what they are used for see |function-list|.',
|
||||
'',
|
||||
|
@ -92,7 +92,7 @@ local redirects = {
|
||||
|
||||
-- TODO: These known invalid |links| require an update to the relevant docs.
|
||||
local exclude_invalid = {
|
||||
["'string'"] = 'eval.txt',
|
||||
["'string'"] = 'vimeval.txt',
|
||||
Query = 'treesitter.txt',
|
||||
matchit = 'vim_diff.txt',
|
||||
['set!'] = 'treesitter.txt',
|
||||
|
@ -742,7 +742,11 @@ endif()
|
||||
|
||||
target_sources(nlua0 PUBLIC ${NLUA0_SOURCES})
|
||||
|
||||
if(STATIC_BUILD)
|
||||
target_link_options(nvim_bin PRIVATE -static-libgcc -static-libstdc++ -static)
|
||||
endif()
|
||||
target_link_libraries(nvim_bin PRIVATE main_lib PUBLIC libuv)
|
||||
|
||||
install_helper(TARGETS nvim_bin)
|
||||
if(MSVC)
|
||||
install(FILES $<TARGET_PDB_FILE:nvim_bin> DESTINATION ${CMAKE_INSTALL_BINDIR} OPTIONAL)
|
||||
@ -975,7 +979,7 @@ add_target(doc-eval
|
||||
${PROJECT_SOURCE_DIR}/src/nvim/eval.lua
|
||||
${PROJECT_SOURCE_DIR}/src/nvim/options.lua
|
||||
${PROJECT_SOURCE_DIR}/src/nvim/vvars.lua
|
||||
${NVIM_RUNTIME_DIR}/doc/builtin.txt
|
||||
${NVIM_RUNTIME_DIR}/doc/vimfn.txt
|
||||
)
|
||||
|
||||
add_custom_target(doc)
|
||||
|
@ -62,7 +62,7 @@ Object nvim_execute_lua(String code, Array args, Arena *arena, Error *err)
|
||||
FUNC_API_DEPRECATED_SINCE(7)
|
||||
FUNC_API_REMOTE_ONLY
|
||||
{
|
||||
return nlua_exec(code, args, kRetObject, arena, err);
|
||||
return nlua_exec(code, NULL, args, kRetObject, arena, err);
|
||||
}
|
||||
|
||||
/// Gets the buffer number
|
||||
|
@ -45,6 +45,7 @@
|
||||
# include "ui_events_remote.generated.h" // IWYU pragma: export
|
||||
#endif
|
||||
|
||||
// TODO(bfredl): just make UI:s owned by their channels instead
|
||||
static PMap(uint64_t) connected_uis = MAP_INIT;
|
||||
|
||||
static char *mpack_array_dyn16(char **buf)
|
||||
@ -71,14 +72,33 @@ static void remote_ui_destroy(RemoteUI *ui)
|
||||
xfree(ui);
|
||||
}
|
||||
|
||||
void remote_ui_disconnect(uint64_t channel_id)
|
||||
/// Removes the client on the given channel from the list of UIs.
|
||||
///
|
||||
/// @param err if non-NULL and there is no UI on the channel, set an error
|
||||
/// @param send_error_exit send an "error_exit" event with 0 status first
|
||||
void remote_ui_disconnect(uint64_t channel_id, Error *err, bool send_error_exit)
|
||||
{
|
||||
RemoteUI *ui = pmap_get(uint64_t)(&connected_uis, channel_id);
|
||||
if (!ui) {
|
||||
if (err != NULL) {
|
||||
api_set_error(err, kErrorTypeException,
|
||||
"UI not attached to channel: %" PRId64, channel_id);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (send_error_exit) {
|
||||
MAXSIZE_TEMP_ARRAY(args, 1);
|
||||
ADD_C(args, INTEGER_OBJ(0));
|
||||
push_call(ui, "error_exit", args);
|
||||
ui_flush_buf(ui, false);
|
||||
}
|
||||
pmap_del(uint64_t)(&connected_uis, channel_id, NULL);
|
||||
ui_detach_impl(ui, channel_id);
|
||||
Channel *chan = find_channel(channel_id);
|
||||
if (chan && chan->rpc.ui == ui) {
|
||||
chan->rpc.ui = NULL;
|
||||
}
|
||||
|
||||
remote_ui_destroy(ui);
|
||||
}
|
||||
|
||||
@ -176,6 +196,7 @@ void nvim_ui_attach(uint64_t channel_id, Integer width, Integer height, Dict opt
|
||||
ui->nevents_pos = NULL;
|
||||
ui->nevents = 0;
|
||||
ui->flushed_events = false;
|
||||
ui->incomplete_event = false;
|
||||
ui->ncalls_pos = NULL;
|
||||
ui->ncalls = 0;
|
||||
ui->ncells_pending = 0;
|
||||
@ -192,6 +213,11 @@ void nvim_ui_attach(uint64_t channel_id, Integer width, Integer height, Dict opt
|
||||
current_ui = channel_id;
|
||||
ui_attach_impl(ui, channel_id);
|
||||
|
||||
Channel *chan = find_channel(channel_id);
|
||||
if (chan) {
|
||||
chan->rpc.ui = ui;
|
||||
}
|
||||
|
||||
may_trigger_vim_suspend_resume(false);
|
||||
}
|
||||
|
||||
@ -231,12 +257,7 @@ void nvim_ui_set_focus(uint64_t channel_id, Boolean gained, Error *error)
|
||||
void nvim_ui_detach(uint64_t channel_id, Error *err)
|
||||
FUNC_API_SINCE(1) FUNC_API_REMOTE_ONLY
|
||||
{
|
||||
if (!map_has(uint64_t, &connected_uis, channel_id)) {
|
||||
api_set_error(err, kErrorTypeException,
|
||||
"UI not attached to channel: %" PRId64, channel_id);
|
||||
return;
|
||||
}
|
||||
remote_ui_disconnect(channel_id);
|
||||
remote_ui_disconnect(channel_id, err, false);
|
||||
}
|
||||
|
||||
// TODO(bfredl): use me to detach a specific ui from the server
|
||||
@ -536,7 +557,7 @@ static void prepare_call(RemoteUI *ui, const char *name)
|
||||
{
|
||||
if (ui->packer.startptr
|
||||
&& (BUF_POS(ui) > UI_BUF_SIZE - EVENT_BUF_SIZE || ui->ncells_pending >= 500)) {
|
||||
ui_flush_buf(ui);
|
||||
ui_flush_buf(ui, false);
|
||||
}
|
||||
|
||||
if (ui->packer.startptr == NULL) {
|
||||
@ -578,7 +599,7 @@ static void push_call(RemoteUI *ui, const char *name, Array args)
|
||||
static void ui_flush_callback(PackerBuffer *packer)
|
||||
{
|
||||
RemoteUI *ui = packer->anydata;
|
||||
ui_flush_buf(ui);
|
||||
ui_flush_buf(ui, true);
|
||||
ui_alloc_buf(ui);
|
||||
}
|
||||
|
||||
@ -804,7 +825,7 @@ void remote_ui_raw_line(RemoteUI *ui, Integer grid, Integer row, Integer startco
|
||||
mpack_w2(&lenpos, nelem);
|
||||
// We only ever set the wrap field on the final "grid_line" event for the line.
|
||||
mpack_bool(buf, false);
|
||||
ui_flush_buf(ui);
|
||||
ui_flush_buf(ui, false);
|
||||
|
||||
prepare_call(ui, "grid_line");
|
||||
mpack_array(buf, 5);
|
||||
@ -877,11 +898,12 @@ void remote_ui_raw_line(RemoteUI *ui, Integer grid, Integer row, Integer startco
|
||||
///
|
||||
/// This might happen multiple times before the actual ui_flush, if the
|
||||
/// total redraw size is large!
|
||||
static void ui_flush_buf(RemoteUI *ui)
|
||||
static void ui_flush_buf(RemoteUI *ui, bool incomplete_event)
|
||||
{
|
||||
if (!ui->packer.startptr || !BUF_POS(ui)) {
|
||||
return;
|
||||
}
|
||||
ui->incomplete_event = incomplete_event;
|
||||
|
||||
flush_event(ui);
|
||||
if (ui->nevents_pos != NULL) {
|
||||
@ -912,11 +934,16 @@ void remote_ui_flush(RemoteUI *ui)
|
||||
remote_ui_cursor_goto(ui, ui->cursor_row, ui->cursor_col);
|
||||
}
|
||||
push_call(ui, "flush", (Array)ARRAY_DICT_INIT);
|
||||
ui_flush_buf(ui);
|
||||
ui_flush_buf(ui, false);
|
||||
ui->flushed_events = false;
|
||||
}
|
||||
}
|
||||
|
||||
void remote_ui_flush_pending_data(RemoteUI *ui)
|
||||
{
|
||||
ui_flush_buf(ui, false);
|
||||
}
|
||||
|
||||
static Array translate_contents(RemoteUI *ui, Array contents, Arena *arena)
|
||||
{
|
||||
Array new_contents = arena_array(arena, contents.size);
|
||||
|
@ -173,5 +173,13 @@ void msg_history_show(Array entries)
|
||||
void msg_history_clear(void)
|
||||
FUNC_API_SINCE(10) FUNC_API_REMOTE_ONLY;
|
||||
|
||||
// This UI event is currently undocumented.
|
||||
// - When the server needs to intentionally exit with an exit code, and there is no
|
||||
// message in server stderr for the user, this event is sent with positive `status`
|
||||
// argument, to indicate that the UI should exit normally with `status`.
|
||||
// - When the server has crashed or there is a message in server stderr for the user,
|
||||
// this event is not sent, and the UI should make server stderr visible.
|
||||
// - When :detach is used on the server, this event is sent with a zero `status`
|
||||
// argument, to indicate that the UI shouldn't wait for server exit.
|
||||
void error_exit(Integer status)
|
||||
FUNC_API_SINCE(12);
|
||||
FUNC_API_SINCE(12) FUNC_API_CLIENT_IMPL;
|
||||
|
@ -514,7 +514,7 @@ Object nvim_exec_lua(String code, Array args, Arena *arena, Error *err)
|
||||
FUNC_API_REMOTE_ONLY
|
||||
{
|
||||
// TODO(bfredl): convert directly from msgpack to lua and then back again
|
||||
return nlua_exec(code, args, kRetObject, arena, err);
|
||||
return nlua_exec(code, NULL, args, kRetObject, arena, err);
|
||||
}
|
||||
|
||||
/// Calculates the number of display cells occupied by `text`.
|
||||
@ -989,10 +989,7 @@ Buffer nvim_create_buf(Boolean listed, Boolean scratch, Error *err)
|
||||
///
|
||||
/// ```lua
|
||||
/// vim.api.nvim_create_user_command('TermHl', function()
|
||||
/// local b = vim.api.nvim_create_buf(false, true)
|
||||
/// local chan = vim.api.nvim_open_term(b, {})
|
||||
/// vim.api.nvim_chan_send(chan, table.concat(vim.api.nvim_buf_get_lines(0, 0, -1, false), '\n'))
|
||||
/// vim.api.nvim_win_set_buf(0, b)
|
||||
/// vim.api.nvim_open_term(0, {})
|
||||
/// end, { desc = 'Highlights ANSI termcodes in curbuf' })
|
||||
/// ```
|
||||
///
|
||||
@ -2360,6 +2357,8 @@ void nvim__redraw(Dict(redraw) *opts, Error *err)
|
||||
// Redraw pending screen updates when explicitly requested or when determined
|
||||
// that it is necessary to properly draw other requested components.
|
||||
if (opts->flush && !cmdpreview) {
|
||||
validate_cursor(curwin);
|
||||
update_topline(curwin);
|
||||
update_screen();
|
||||
}
|
||||
|
||||
|
@ -235,8 +235,9 @@ Window nvim_open_win(Buffer buffer, Boolean enter, Dict(win_config) *config, Err
|
||||
|
||||
win_T *wp = NULL;
|
||||
tabpage_T *tp = curtab;
|
||||
win_T *parent = NULL;
|
||||
if (config->win != -1) {
|
||||
assert(curwin != NULL);
|
||||
win_T *parent = config->win == 0 ? curwin : NULL;
|
||||
if (config->win > 0) {
|
||||
parent = find_window_by_handle(fconfig.window, err);
|
||||
if (!parent) {
|
||||
// find_window_by_handle has already set the error
|
||||
@ -408,8 +409,8 @@ void nvim_win_set_config(Window window, Dict(win_config) *config, Error *err)
|
||||
if (!parse_win_config(win, config, &fconfig, !was_split || to_split, err)) {
|
||||
return;
|
||||
}
|
||||
win_T *parent = NULL;
|
||||
if (config->win != -1) {
|
||||
win_T *parent = config->win == 0 ? curwin : NULL;
|
||||
if (config->win > 0) {
|
||||
parent = find_window_by_handle(fconfig.window, err);
|
||||
if (!parent) {
|
||||
return;
|
||||
|
@ -525,7 +525,7 @@ void check_arg_idx(win_T *win)
|
||||
}
|
||||
}
|
||||
|
||||
/// ":args", ":argslocal" and ":argsglobal".
|
||||
/// ":args", ":arglocal" and ":argglobal".
|
||||
void ex_args(exarg_T *eap)
|
||||
{
|
||||
if (eap->cmdidx != CMD_args) {
|
||||
|
@ -1268,9 +1268,10 @@ void aucmd_prepbuf(aco_save_T *aco, buf_T *buf)
|
||||
{
|
||||
win_T *win;
|
||||
bool need_append = true; // Append `aucmd_win` to the window list.
|
||||
const bool same_buffer = buf == curbuf;
|
||||
|
||||
// Find a window that is for the new buffer
|
||||
if (buf == curbuf) { // be quick when buf is curbuf
|
||||
if (same_buffer) { // be quick when buf is curbuf
|
||||
win = curwin;
|
||||
} else {
|
||||
win = NULL;
|
||||
@ -1360,9 +1361,11 @@ void aucmd_prepbuf(aco_save_T *aco, buf_T *buf)
|
||||
aco->new_curwin_handle = curwin->handle;
|
||||
set_bufref(&aco->new_curbuf, curbuf);
|
||||
|
||||
// disable the Visual area, the position may be invalid in another buffer
|
||||
aco->save_VIsual_active = VIsual_active;
|
||||
VIsual_active = false;
|
||||
if (!same_buffer) {
|
||||
// disable the Visual area, position may be invalid in another buffer
|
||||
VIsual_active = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// Cleanup after executing autocommands for a (hidden) buffer.
|
||||
@ -1635,11 +1638,12 @@ bool apply_autocmds_group(event_T event, char *fname, char *fname_io, bool force
|
||||
// into "buf" are ignoring the event.
|
||||
if (buf == curbuf && event_names[event].event <= 0) {
|
||||
win_ignore = event_ignored(event, curwin->w_p_eiw);
|
||||
} else if (buf != NULL && event_names[event].event <= 0) {
|
||||
for (size_t i = 0; i < kv_size(buf->b_wininfo); i++) {
|
||||
WinInfo *wip = kv_A(buf->b_wininfo, i);
|
||||
if (wip->wi_win != NULL && wip->wi_win->w_buffer == buf) {
|
||||
win_ignore = event_ignored(event, wip->wi_win->w_p_eiw);
|
||||
} else if (buf != NULL && event_names[event].event <= 0 && buf->b_nwindows > 0) {
|
||||
win_ignore = true;
|
||||
FOR_ALL_TAB_WINDOWS(tp, wp) {
|
||||
if (wp->w_buffer == buf && !event_ignored(event, wp->w_p_eiw)) {
|
||||
win_ignore = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -480,11 +480,6 @@ static bool can_unload_buffer(buf_T *buf)
|
||||
return can_unload;
|
||||
}
|
||||
|
||||
bool buf_locked(buf_T *buf)
|
||||
{
|
||||
return buf->b_locked || buf->b_locked_split;
|
||||
}
|
||||
|
||||
/// Close the link to a buffer.
|
||||
///
|
||||
/// @param win If not NULL, set b_last_cursor.
|
||||
@ -1300,11 +1295,17 @@ static int do_buffer_ext(int action, int start, int dir, int count, int flags)
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
if (action == DOBUF_GOTO
|
||||
&& buf != curbuf
|
||||
&& !check_can_set_curbuf_forceit((flags & DOBUF_FORCEIT) ? true : false)) {
|
||||
// disallow navigating to another buffer when 'winfixbuf' is applied
|
||||
return FAIL;
|
||||
if (action == DOBUF_GOTO && buf != curbuf) {
|
||||
if (!check_can_set_curbuf_forceit((flags & DOBUF_FORCEIT) != 0)) {
|
||||
// disallow navigating to another buffer when 'winfixbuf' is applied
|
||||
return FAIL;
|
||||
}
|
||||
if (buf->b_locked_split) {
|
||||
// disallow navigating to a closing buffer, which like splitting,
|
||||
// can result in more windows displaying it
|
||||
emsg(_(e_cannot_switch_to_a_closing_buffer));
|
||||
return FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
if ((action == DOBUF_GOTO || action == DOBUF_SPLIT) && (buf->b_flags & BF_DUMMY)) {
|
||||
@ -1772,6 +1773,10 @@ void enter_buffer(buf_T *buf)
|
||||
}
|
||||
curbuf->b_last_used = time(NULL);
|
||||
|
||||
if (curbuf->terminal != NULL) {
|
||||
terminal_check_size(curbuf->terminal);
|
||||
}
|
||||
|
||||
redraw_later(curwin, UPD_NOT_VALID);
|
||||
}
|
||||
|
||||
@ -1899,18 +1904,21 @@ buf_T *buflist_new(char *ffname_arg, char *sfname_arg, linenr_T lnum, int flags)
|
||||
// buffer.)
|
||||
buf = NULL;
|
||||
if ((flags & BLN_CURBUF) && curbuf_reusable()) {
|
||||
bufref_T bufref;
|
||||
|
||||
assert(curbuf != NULL);
|
||||
buf = curbuf;
|
||||
set_bufref(&bufref, buf);
|
||||
// It's like this buffer is deleted. Watch out for autocommands that
|
||||
// change curbuf! If that happens, allocate a new buffer anyway.
|
||||
buf_freeall(buf, BFA_WIPE | BFA_DEL);
|
||||
if (buf != curbuf) { // autocommands deleted the buffer!
|
||||
return NULL;
|
||||
}
|
||||
if (aborting()) { // autocmds may abort script processing
|
||||
xfree(ffname);
|
||||
return NULL;
|
||||
}
|
||||
if (!bufref_valid(&bufref)) {
|
||||
buf = NULL; // buf was deleted; allocate a new buffer
|
||||
}
|
||||
}
|
||||
if (buf != curbuf || curbuf == NULL) {
|
||||
buf = xcalloc(1, sizeof(buf_T));
|
||||
|
@ -366,7 +366,7 @@ struct file_buffer {
|
||||
int b_locked; // Buffer is being closed or referenced, don't
|
||||
// let autocommands wipe it out.
|
||||
int b_locked_split; // Buffer is being closed, don't allow opening
|
||||
// a new window with it.
|
||||
// it in more windows.
|
||||
int b_ro_locked; // Non-zero when the buffer can't be changed.
|
||||
// Used for FileChangedRO
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user