mirror of
https://github.com/neovim/neovim.git
synced 2025-09-05 19:08:15 +00:00
Compare commits
339 Commits
v0.11.0
...
c5262c4ca8
Author | SHA1 | Date | |
---|---|---|---|
![]() |
c5262c4ca8 | ||
![]() |
dd8e3d7aa5 | ||
![]() |
a7491e1457 | ||
![]() |
1063aff643 | ||
![]() |
e415fae42e | ||
![]() |
7b099d2b2b | ||
![]() |
cec0ecabd8 | ||
![]() |
edfb447ff8 | ||
![]() |
b032c2b53f | ||
![]() |
09f702bc13 | ||
![]() |
c4845f3a12 | ||
![]() |
a2603016ce | ||
![]() |
d70d469c04 | ||
![]() |
99817471d7 | ||
![]() |
4c5cb950c6 | ||
![]() |
ec8900f1e6 | ||
![]() |
a3590afba5 | ||
![]() |
e841d653af | ||
![]() |
6fd8ba05a6 | ||
![]() |
e6ea97a691 | ||
![]() |
3cf9dac2ba | ||
![]() |
8dd88056f1 | ||
![]() |
1bea812953 | ||
![]() |
fa64f2d09b | ||
![]() |
3ab06d5188 | ||
![]() |
37b2d42459 | ||
![]() |
53db7fc3ef | ||
![]() |
3343ee971b | ||
![]() |
abfbd155da | ||
![]() |
39ae9a9971 | ||
![]() |
5ec7d98857 | ||
![]() |
744d96bd76 | ||
![]() |
30b801eff2 | ||
![]() |
27282696fe | ||
![]() |
4b957a4d18 | ||
![]() |
819e545c28 | ||
![]() |
d21db345ef | ||
![]() |
bd4b45dd1b | ||
![]() |
6c2f06b537 | ||
![]() |
fb6c677d57 | ||
![]() |
e68d3ef886 | ||
![]() |
35a66f74c7 | ||
![]() |
ced4eed733 | ||
![]() |
e299430ff5 | ||
![]() |
53a0d99702 | ||
![]() |
a65c4be2de | ||
![]() |
30db74de66 | ||
![]() |
6fd842a4fd | ||
![]() |
7f1e112a32 | ||
![]() |
54c2ea142a | ||
![]() |
f4b4c27a35 | ||
![]() |
5551da79c1 | ||
![]() |
8f2d6f7ce2 | ||
![]() |
09b0003d38 | ||
![]() |
41fa343484 | ||
![]() |
2e4baa3679 | ||
![]() |
6b820258cd | ||
![]() |
990b320592 | ||
![]() |
a05b70baa6 | ||
![]() |
359d65c902 | ||
![]() |
62aae1084f | ||
![]() |
e534afa5ab | ||
![]() |
2124146164 | ||
![]() |
64afa93187 | ||
![]() |
e6a0f0ee71 | ||
![]() |
685302682a | ||
![]() |
5e7021eb1b | ||
![]() |
44b8255fa2 | ||
![]() |
407fc0bb16 | ||
![]() |
657540945c | ||
![]() |
9261aef2f3 | ||
![]() |
d185057bc7 | ||
![]() |
6cfaa9c204 | ||
![]() |
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 | ||
![]() |
a9a3981669 | ||
![]() |
478f5d0070 | ||
![]() |
95f96a3d1b | ||
![]() |
9909580df2 | ||
![]() |
66953b16a2 | ||
![]() |
448c2cec9d | ||
![]() |
c1d3777db2 | ||
![]() |
155529b91a | ||
![]() |
c633250cc0 | ||
![]() |
0c315feddf | ||
![]() |
646a8f663e | ||
![]() |
b9c9b15ad7 | ||
![]() |
fb71d631a5 | ||
![]() |
3b0c88a537 | ||
![]() |
1a6ddeee41 | ||
![]() |
4205fdee1d | ||
![]() |
248528c907 | ||
![]() |
b7de104d86 | ||
![]() |
cdd3f2a2e6 | ||
![]() |
a97713485d | ||
![]() |
12298be0fe | ||
![]() |
2435d72283 | ||
![]() |
e342b9a25a | ||
![]() |
4422b9bbd0 | ||
![]() |
dcd5e4574a | ||
![]() |
b694131c3b | ||
![]() |
4d87229789 | ||
![]() |
e4007551c4 | ||
![]() |
526444c4ff | ||
![]() |
8aa49a8e9b | ||
![]() |
2b14447803 | ||
![]() |
7384983721 | ||
![]() |
b8e5fd51fd | ||
![]() |
9da90af0f7 | ||
![]() |
b5158e8e92 | ||
![]() |
837faf7065 | ||
![]() |
c4a19bff4e | ||
![]() |
a92155b86b | ||
![]() |
6e51d39696 | ||
![]() |
4c1121bd33 | ||
![]() |
c158d41cec | ||
![]() |
2182272139 | ||
![]() |
29011e4d45 | ||
![]() |
91481ae7d5 | ||
![]() |
3df9db58dc | ||
![]() |
e3506ede27 | ||
![]() |
02bf23b4bf | ||
![]() |
cbf4906c11 | ||
![]() |
4cc97cf009 | ||
![]() |
c6ef13dc45 | ||
![]() |
1a2d0484ac | ||
![]() |
5829b5de0a | ||
![]() |
dd547ef1ea | ||
![]() |
91d11c8bc1 | ||
![]() |
1daea6e1fd | ||
![]() |
279a0e78c9 | ||
![]() |
5fc6bd6454 | ||
![]() |
2b2a90051e | ||
![]() |
1e8e74dbff | ||
![]() |
a4b6705e87 | ||
![]() |
f68e0fed26 | ||
![]() |
09fd22d5d7 | ||
![]() |
326eacef93 | ||
![]() |
02123bac0d | ||
![]() |
8d9b4d8c14 | ||
![]() |
55be20316a | ||
![]() |
12da443930 | ||
![]() |
837c9d0409 | ||
![]() |
70f3e15298 | ||
![]() |
7e884b78bf | ||
![]() |
89e0ea1788 | ||
![]() |
9056c01a95 | ||
![]() |
d2dd403693 | ||
![]() |
2084cda6f9 | ||
![]() |
7efb3ba6f7 | ||
![]() |
649bce6e73 | ||
![]() |
fcee5df0fc | ||
![]() |
2a04161a35 | ||
![]() |
adfd4b9f4f | ||
![]() |
056dbf3ea7 | ||
![]() |
c57a36cd59 | ||
![]() |
06df3e0c0d | ||
![]() |
a9afa6b152 | ||
![]() |
bbf912d72f | ||
![]() |
53def2a877 | ||
![]() |
c61e8c6e70 | ||
![]() |
6514e2c7ba | ||
![]() |
06c2886569 | ||
![]() |
2cd735d159 | ||
![]() |
ccb078bbb0 | ||
![]() |
5e4365b83d |
20
.github/scripts/env.ps1
vendored
20
.github/scripts/env.ps1
vendored
@@ -1,9 +1,17 @@
|
||||
# This script enables Developer Command Prompt
|
||||
# See https://github.com/microsoft/vswhere/wiki/Start-Developer-Command-Prompt#using-powershell
|
||||
$installationPath = vswhere.exe -latest -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath
|
||||
if ($installationPath -and (Test-Path "$installationPath\Common7\Tools\vsdevcmd.bat")) {
|
||||
& "${env:COMSPEC}" /s /c "`"$installationPath\Common7\Tools\vsdevcmd.bat`" -arch=x64 -no_logo && set" | ForEach-Object {
|
||||
$name, $value = $_ -split '=', 2
|
||||
"$name=$value" >> $env:GITHUB_ENV
|
||||
}
|
||||
if ($env:BUILD_ARCH -eq "arm64") {
|
||||
$arch = "arm64"
|
||||
$installationPath = vswhere.exe -latest -requires Microsoft.VisualStudio.Component.VC.Tools.arm64 -property installationPath
|
||||
} else {
|
||||
$arch = "x64"
|
||||
$installationPath = vswhere.exe -latest -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath
|
||||
}
|
||||
|
||||
if ($installationPath) {
|
||||
& "${env:COMSPEC}" /s /c "`"$installationPath\Common7\Tools\vsdevcmd.bat`" -arch=$arch -no_logo && set" |
|
||||
ForEach-Object {
|
||||
$name, $value = $_ -split '=', 2
|
||||
"$name=$value" >> $env:GITHUB_ENV
|
||||
}
|
||||
}
|
||||
|
15
.github/workflows/notes.md
vendored
15
.github/workflows/notes.md
vendored
@@ -2,21 +2,26 @@
|
||||
${NVIM_VERSION}
|
||||
```
|
||||
|
||||
## Release notes
|
||||
|
||||
- [Changelog](https://github.com/neovim/neovim/commit/${NVIM_COMMIT}) (fixes + features)
|
||||
- [News](./runtime/doc/news.txt) (`:help news` in Nvim)
|
||||
|
||||
## Install
|
||||
|
||||
### Windows
|
||||
|
||||
#### Zip
|
||||
|
||||
1. Download **nvim-win64.zip**
|
||||
1. Download **nvim-win64.zip** (or **nvim-win-arm64.zip** for ARM)
|
||||
2. Extract the zip
|
||||
3. Run `nvim.exe` on your CLI of choice
|
||||
3. Run `nvim.exe` in your terminal
|
||||
|
||||
#### MSI
|
||||
|
||||
1. Download **nvim-win64.msi**
|
||||
1. Download **nvim-win64.msi** (or **nvim-win-arm64.msi** for ARM)
|
||||
2. Run the MSI
|
||||
3. Run `nvim.exe` on your CLI of choice
|
||||
3. Run `nvim.exe` in your terminal
|
||||
|
||||
Note: On Windows "Server" you may need to [install vcruntime140.dll](https://learn.microsoft.com/en-us/cpp/windows/latest-supported-vc-redist?view=msvc-170).
|
||||
|
||||
@@ -75,5 +80,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
|
||||
|
46
.github/workflows/release.yml
vendored
46
.github/workflows/release.yml
vendored
@@ -132,27 +132,44 @@ jobs:
|
||||
|
||||
windows:
|
||||
needs: setup
|
||||
runs-on: windows-2019
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- runner: windows-2022
|
||||
arch: x86_64
|
||||
archive_name: nvim-win64
|
||||
- runner: windows-11-arm
|
||||
arch: arm64
|
||||
archive_name: nvim-win-arm64
|
||||
runs-on: ${{ matrix.runner }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
# Perform a full checkout #13471
|
||||
fetch-depth: 0
|
||||
- run: .github/scripts/env.ps1
|
||||
env:
|
||||
BUILD_ARCH: ${{ matrix.arch }}
|
||||
- name: Install Wix
|
||||
run: |
|
||||
Invoke-WebRequest -Uri "https://github.com/wixtoolset/wix3/releases/download/wix3141rtm/wix314-binaries.zip" -OutFile "wix314-binaries.zip"
|
||||
Expand-Archive -Path "wix314-binaries.zip" -DestinationPath "C:/wix"
|
||||
echo "C:\wix" >> $env:GITHUB_PATH
|
||||
- name: Build deps
|
||||
run: |
|
||||
cmake -S cmake.deps -B .deps -G Ninja -DCMAKE_BUILD_TYPE=${{ needs.setup.outputs.build_type }}
|
||||
cmake --build .deps
|
||||
- name: build package
|
||||
- name: Build package
|
||||
run: |
|
||||
cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=${{ needs.setup.outputs.build_type }}
|
||||
cmake --build build --target package
|
||||
- uses: actions/upload-artifact@v4
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: nvim-win64
|
||||
name: nvim-win-${{ matrix.arch }}
|
||||
path: |
|
||||
build/nvim-win64.msi
|
||||
build/nvim-win64.zip
|
||||
build/${{ matrix.archive_name }}.zip
|
||||
build/${{ matrix.archive_name }}.msi
|
||||
retention-days: 1
|
||||
|
||||
publish:
|
||||
@@ -193,25 +210,14 @@ 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 }}
|
||||
NVIM_COMMIT: ${{ github.sha }}
|
||||
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-win-x86_64/* nvim-win-arm64/*
|
||||
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-win-x86_64/* nvim-win-arm64/*
|
||||
|
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,8 +141,8 @@ 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 0)
|
||||
set(NVIM_VERSION_PRERELEASE "") # for package maintainers
|
||||
set(NVIM_VERSION_PATCH 5)
|
||||
set(NVIM_VERSION_PRERELEASE "-dev") # for package maintainers
|
||||
|
||||
# API level
|
||||
set(NVIM_API_LEVEL 13) # Bump this after any API/stdlib change.
|
||||
|
@@ -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
|
||||
```
|
||||
|
||||
|
10
INSTALL.md
10
INSTALL.md
@@ -66,11 +66,13 @@ Several Neovim GUIs are available from scoop (extras): [scoop.sh/#/apps?q=neovim
|
||||
You can then copy your spell files over (for English, located
|
||||
[here](https://github.com/vim/vim/blob/master/runtime/spell/en.utf-8.spl) and
|
||||
[here](https://github.com/vim/vim/blob/master/runtime/spell/en.utf-8.sug));
|
||||
- For Python plugins you need the `pynvim` module. "Virtual envs" are recommended. After activating the virtual env do `pip install pynvim` (in *both*). Edit your `init.vim` so that it contains the path to the env's Python executable:
|
||||
```vim
|
||||
let g:python3_host_prog='C:/Users/foo/Envs/neovim3/Scripts/python.exe'
|
||||
- For Python plugins you need the `pynvim` module. Installation via uv
|
||||
(https://docs.astral.sh/uv/) is recommended; the `--upgrade` switch ensures
|
||||
installation of the latest version:
|
||||
```
|
||||
- Run `:checkhealth` and read `:help provider-python`.
|
||||
uv tool install --upgrade pynvim
|
||||
```
|
||||
- Run `:checkhealth` and read `:help provider-python` for more details.
|
||||
- **init.vim ("vimrc"):** If you already have Vim installed you can copy `%userprofile%\_vimrc` to `%userprofile%\AppData\Local\nvim\init.vim` to use your Vim config with Neovim.
|
||||
|
||||
|
||||
|
@@ -73,7 +73,7 @@ if(HAS_OG_FLAG)
|
||||
set(DEFAULT_MAKE_CFLAGS CFLAGS+=-Og ${DEFAULT_MAKE_CFLAGS})
|
||||
endif()
|
||||
|
||||
set(DEPS_INCLUDE_FLAGS "-I${DEPS_INSTALL_DIR}/include -I${DEPS_INSTALL_DIR}/include/luajit-2.1")
|
||||
set(DEPS_INCLUDE_FLAGS "-I\"${DEPS_INSTALL_DIR}/include\" -I\"${DEPS_INSTALL_DIR}/include/luajit-2.1\"")
|
||||
|
||||
# If the macOS deployment target is not set manually (via $MACOSX_DEPLOYMENT_TARGET),
|
||||
# fall back to local system version. Needs to be done here and in top-level CMakeLists.txt.
|
||||
@@ -96,10 +96,10 @@ else()
|
||||
find_package(Lua 5.1 EXACT)
|
||||
if(LUAJIT_FOUND)
|
||||
set(LUA_ENGINE LuaJit)
|
||||
string(APPEND DEPS_INCLUDE_FLAGS " -I${LUAJIT_INCLUDE_DIR}")
|
||||
string(APPEND DEPS_INCLUDE_FLAGS " -I\"${LUAJIT_INCLUDE_DIR}\"")
|
||||
elseif(LUA_FOUND)
|
||||
set(LUA_ENGINE Lua)
|
||||
string(APPEND DEPS_INCLUDE_FLAGS " -I${LUA_INCLUDE_DIR}")
|
||||
string(APPEND DEPS_INCLUDE_FLAGS " -I\"${LUA_INCLUDE_DIR}\"")
|
||||
else()
|
||||
message(FATAL_ERROR "Could not find system lua or luajit")
|
||||
endif()
|
||||
|
@@ -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
|
||||
|
@@ -1,4 +1,4 @@
|
||||
if(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64")
|
||||
if(CMAKE_SYSTEM_PROCESSOR MATCHES "^(arm64|ARM64|aarch64)$")
|
||||
set(CMAKE_SYSTEM_PROCESSOR arm64)
|
||||
endif()
|
||||
|
||||
@@ -27,9 +27,13 @@ set(CPACK_RESOURCE_FILE_README ${PROJECT_SOURCE_DIR}/README.md)
|
||||
|
||||
|
||||
if(WIN32)
|
||||
set(CPACK_PACKAGE_FILE_NAME "nvim-win64")
|
||||
if(CMAKE_SYSTEM_PROCESSOR STREQUAL "arm64")
|
||||
set(CPACK_PACKAGE_FILE_NAME "nvim-win-arm64")
|
||||
else()
|
||||
set(CPACK_PACKAGE_FILE_NAME "nvim-win64")
|
||||
endif()
|
||||
|
||||
set(CPACK_GENERATOR ZIP WIX)
|
||||
|
||||
# WIX
|
||||
# CPACK_WIX_UPGRADE_GUID should be set, but should never change.
|
||||
# CPACK_WIX_PRODUCT_GUID should not be set (leave as default to auto-generate).
|
||||
|
@@ -5,11 +5,11 @@
|
||||
if exists('g:loaded_clipboard_provider')
|
||||
finish
|
||||
endif
|
||||
" Default to 1. provider#clipboard#Executable() may set 2.
|
||||
" Default to 0. provider#clipboard#Executable() may set 2.
|
||||
" To force a reload:
|
||||
" :unlet g:loaded_clipboard_provider
|
||||
" :runtime autoload/provider/clipboard.vim
|
||||
let g:loaded_clipboard_provider = 1
|
||||
let g:loaded_clipboard_provider = 0
|
||||
|
||||
let s:copy = {}
|
||||
let s:paste = {}
|
||||
@@ -67,6 +67,113 @@ function! s:set_osc52() abort
|
||||
return 'OSC 52'
|
||||
endfunction
|
||||
|
||||
function! s:set_pbcopy() abort
|
||||
let s:copy['+'] = ['pbcopy']
|
||||
let s:paste['+'] = ['pbpaste']
|
||||
let s:copy['*'] = s:copy['+']
|
||||
let s:paste['*'] = s:paste['+']
|
||||
let s:cache_enabled = 0
|
||||
return 'pbcopy'
|
||||
endfunction
|
||||
|
||||
function! s:set_wayland() abort
|
||||
let s:copy['+'] = ['wl-copy', '--type', 'text/plain']
|
||||
let s:paste['+'] = ['wl-paste', '--no-newline']
|
||||
let s:copy['*'] = ['wl-copy', '--primary', '--type', 'text/plain']
|
||||
let s:paste['*'] = ['wl-paste', '--no-newline', '--primary']
|
||||
return 'wl-copy'
|
||||
endfunction
|
||||
|
||||
function! s:set_wayclip() abort
|
||||
let s:copy['+'] = ['waycopy', '-t', 'text/plain']
|
||||
let s:paste['+'] = ['waypaste', '-t', 'text/plain']
|
||||
let s:copy['*'] = s:copy['+']
|
||||
let s:paste['*'] = s:paste['+']
|
||||
return 'wayclip'
|
||||
endfunction
|
||||
|
||||
function! s:set_xsel() abort
|
||||
let s:copy['+'] = ['xsel', '--nodetach', '-i', '-b']
|
||||
let s:paste['+'] = ['xsel', '-o', '-b']
|
||||
let s:copy['*'] = ['xsel', '--nodetach', '-i', '-p']
|
||||
let s:paste['*'] = ['xsel', '-o', '-p']
|
||||
return 'xsel'
|
||||
endfunction
|
||||
|
||||
function! s:set_xclip() abort
|
||||
let s:copy['+'] = ['xclip', '-quiet', '-i', '-selection', 'clipboard']
|
||||
let s:paste['+'] = ['xclip', '-o', '-selection', 'clipboard']
|
||||
let s:copy['*'] = ['xclip', '-quiet', '-i', '-selection', 'primary']
|
||||
let s:paste['*'] = ['xclip', '-o', '-selection', 'primary']
|
||||
return 'xclip'
|
||||
endfunction
|
||||
|
||||
function! s:set_lemonade() abort
|
||||
let s:copy['+'] = ['lemonade', 'copy']
|
||||
let s:paste['+'] = ['lemonade', 'paste']
|
||||
let s:copy['*'] = ['lemonade', 'copy']
|
||||
let s:paste['*'] = ['lemonade', 'paste']
|
||||
return 'lemonade'
|
||||
endfunction
|
||||
|
||||
function! s:set_doitclient() abort
|
||||
let s:copy['+'] = ['doitclient', 'wclip']
|
||||
let s:paste['+'] = ['doitclient', 'wclip', '-r']
|
||||
let s:copy['*'] = s:copy['+']
|
||||
let s:paste['*'] = s:paste['+']
|
||||
return 'doitclient'
|
||||
endfunction
|
||||
|
||||
function! s:set_win32yank() abort
|
||||
if has('wsl') && getftype(exepath('win32yank.exe')) == 'link'
|
||||
let win32yank = resolve(exepath('win32yank.exe'))
|
||||
else
|
||||
let win32yank = 'win32yank.exe'
|
||||
endif
|
||||
let s:copy['+'] = [win32yank, '-i', '--crlf']
|
||||
let s:paste['+'] = [win32yank, '-o', '--lf']
|
||||
let s:copy['*'] = s:copy['+']
|
||||
let s:paste['*'] = s:paste['+']
|
||||
return 'win32yank'
|
||||
endfunction
|
||||
|
||||
function! s:set_putclip() abort
|
||||
let s:copy['+'] = ['putclip']
|
||||
let s:paste['+'] = ['getclip']
|
||||
let s:copy['*'] = s:copy['+']
|
||||
let s:paste['*'] = s:paste['+']
|
||||
return 'putclip'
|
||||
endfunction
|
||||
|
||||
function! s:set_clip() abort
|
||||
let s:copy['+'] = ['clip']
|
||||
let s:paste['+'] = ['powershell', '-NoProfile', '-NoLogo', '-Command', 'Get-Clipboard']
|
||||
let s:copy['*'] = s:copy['+']
|
||||
let s:paste['*'] = s:paste['+']
|
||||
return 'clip'
|
||||
endfunction
|
||||
|
||||
function! s:set_termux() abort
|
||||
let s:copy['+'] = ['termux-clipboard-set']
|
||||
let s:paste['+'] = ['termux-clipboard-get']
|
||||
let s:copy['*'] = s:copy['+']
|
||||
let s:paste['*'] = s:paste['+']
|
||||
return 'termux-clipboard'
|
||||
endfunction
|
||||
|
||||
function! s:set_tmux() abort
|
||||
let tmux_v = v:lua.vim.version.parse(system(['tmux', '-V']))
|
||||
if !empty(tmux_v) && !v:lua.vim.version.lt(tmux_v, [3,2,0])
|
||||
let s:copy['+'] = ['tmux', 'load-buffer', '-w', '-']
|
||||
else
|
||||
let s:copy['+'] = ['tmux', 'load-buffer', '-']
|
||||
endif
|
||||
let s:paste['+'] = ['tmux', 'save-buffer', '-']
|
||||
let s:copy['*'] = s:copy['+']
|
||||
let s:paste['*'] = s:paste['+']
|
||||
return 'tmux'
|
||||
endfunction
|
||||
|
||||
let s:cache_enabled = 1
|
||||
let s:err = ''
|
||||
|
||||
@@ -78,9 +185,34 @@ function! provider#clipboard#Executable() abort
|
||||
" Setting g:clipboard to v:false explicitly opts-in to using the "builtin" clipboard providers below
|
||||
if exists('g:clipboard') && g:clipboard isnot# v:false
|
||||
if v:t_string ==# type(g:clipboard)
|
||||
" Handle string form of g:clipboard for all builtin providers
|
||||
if 'osc52' == g:clipboard
|
||||
" User opted-in to OSC 52 by manually setting g:clipboard.
|
||||
return s:set_osc52()
|
||||
elseif 'pbcopy' == g:clipboard
|
||||
return s:set_pbcopy()
|
||||
elseif 'wl-copy' == g:clipboard
|
||||
return s:set_wayland()
|
||||
elseif 'wayclip' == g:clipboard
|
||||
return s:set_wayclip()
|
||||
elseif 'xsel' == g:clipboard
|
||||
return s:set_xsel()
|
||||
elseif 'xclip' == g:clipboard
|
||||
return s:set_xclip()
|
||||
elseif 'lemonade' == g:clipboard
|
||||
return s:set_lemonade()
|
||||
elseif 'doitclient' == g:clipboard
|
||||
return s:set_doitclient()
|
||||
elseif 'win32yank' == g:clipboard
|
||||
return s:set_win32yank()
|
||||
elseif 'putclip' == g:clipboard
|
||||
return s:set_putclip()
|
||||
elseif 'clip' == g:clipboard
|
||||
return s:set_clip()
|
||||
elseif 'termux' == g:clipboard
|
||||
return s:set_termux()
|
||||
elseif 'tmux' == g:clipboard
|
||||
return s:set_tmux()
|
||||
endif
|
||||
endif
|
||||
|
||||
@@ -102,88 +234,29 @@ function! provider#clipboard#Executable() abort
|
||||
let s:cache_enabled = get(g:clipboard, 'cache_enabled', 0)
|
||||
return get(g:clipboard, 'name', 'g:clipboard')
|
||||
elseif has('mac')
|
||||
let s:copy['+'] = ['pbcopy']
|
||||
let s:paste['+'] = ['pbpaste']
|
||||
let s:copy['*'] = s:copy['+']
|
||||
let s:paste['*'] = s:paste['+']
|
||||
let s:cache_enabled = 0
|
||||
return 'pbcopy'
|
||||
return s:set_pbcopy()
|
||||
elseif !empty($WAYLAND_DISPLAY) && executable('wl-copy') && executable('wl-paste')
|
||||
let s:copy['+'] = ['wl-copy', '--type', 'text/plain']
|
||||
let s:paste['+'] = ['wl-paste', '--no-newline']
|
||||
let s:copy['*'] = ['wl-copy', '--primary', '--type', 'text/plain']
|
||||
let s:paste['*'] = ['wl-paste', '--no-newline', '--primary']
|
||||
return 'wl-copy'
|
||||
return s:set_wayland()
|
||||
elseif !empty($WAYLAND_DISPLAY) && executable('waycopy') && executable('waypaste')
|
||||
let s:copy['+'] = ['waycopy', '-t', 'text/plain']
|
||||
let s:paste['+'] = ['waypaste', '-t', 'text/plain']
|
||||
let s:copy['*'] = s:copy['+']
|
||||
let s:paste['*'] = s:paste['+']
|
||||
return 'wayclip'
|
||||
return s:set_wayclip()
|
||||
elseif !empty($DISPLAY) && executable('xsel') && s:cmd_ok('xsel -o -b')
|
||||
let s:copy['+'] = ['xsel', '--nodetach', '-i', '-b']
|
||||
let s:paste['+'] = ['xsel', '-o', '-b']
|
||||
let s:copy['*'] = ['xsel', '--nodetach', '-i', '-p']
|
||||
let s:paste['*'] = ['xsel', '-o', '-p']
|
||||
return 'xsel'
|
||||
return s:set_xsel()
|
||||
elseif !empty($DISPLAY) && executable('xclip')
|
||||
let s:copy['+'] = ['xclip', '-quiet', '-i', '-selection', 'clipboard']
|
||||
let s:paste['+'] = ['xclip', '-o', '-selection', 'clipboard']
|
||||
let s:copy['*'] = ['xclip', '-quiet', '-i', '-selection', 'primary']
|
||||
let s:paste['*'] = ['xclip', '-o', '-selection', 'primary']
|
||||
return 'xclip'
|
||||
return s:set_xclip()
|
||||
elseif executable('lemonade')
|
||||
let s:copy['+'] = ['lemonade', 'copy']
|
||||
let s:paste['+'] = ['lemonade', 'paste']
|
||||
let s:copy['*'] = ['lemonade', 'copy']
|
||||
let s:paste['*'] = ['lemonade', 'paste']
|
||||
return 'lemonade'
|
||||
return s:set_lemonade()
|
||||
elseif executable('doitclient')
|
||||
let s:copy['+'] = ['doitclient', 'wclip']
|
||||
let s:paste['+'] = ['doitclient', 'wclip', '-r']
|
||||
let s:copy['*'] = s:copy['+']
|
||||
let s:paste['*'] = s:paste['+']
|
||||
return 'doitclient'
|
||||
return s:set_doitclient()
|
||||
elseif executable('win32yank.exe')
|
||||
if has('wsl') && getftype(exepath('win32yank.exe')) == 'link'
|
||||
let win32yank = resolve(exepath('win32yank.exe'))
|
||||
else
|
||||
let win32yank = 'win32yank.exe'
|
||||
endif
|
||||
let s:copy['+'] = [win32yank, '-i', '--crlf']
|
||||
let s:paste['+'] = [win32yank, '-o', '--lf']
|
||||
let s:copy['*'] = s:copy['+']
|
||||
let s:paste['*'] = s:paste['+']
|
||||
return 'win32yank'
|
||||
return s:set_win32yank()
|
||||
elseif executable('putclip') && executable('getclip')
|
||||
let s:copy['+'] = ['putclip']
|
||||
let s:paste['+'] = ['getclip']
|
||||
let s:copy['*'] = s:copy['+']
|
||||
let s:paste['*'] = s:paste['+']
|
||||
return 'putclip'
|
||||
return s:set_putclip()
|
||||
elseif executable('clip') && executable('powershell')
|
||||
let s:copy['+'] = ['clip']
|
||||
let s:paste['+'] = ['powershell', '-NoProfile', '-NoLogo', '-Command', 'Get-Clipboard']
|
||||
let s:copy['*'] = s:copy['+']
|
||||
let s:paste['*'] = s:paste['+']
|
||||
return 'clip'
|
||||
return s:set_clip()
|
||||
elseif executable('termux-clipboard-set')
|
||||
let s:copy['+'] = ['termux-clipboard-set']
|
||||
let s:paste['+'] = ['termux-clipboard-get']
|
||||
let s:copy['*'] = s:copy['+']
|
||||
let s:paste['*'] = s:paste['+']
|
||||
return 'termux-clipboard'
|
||||
return s:set_termux()
|
||||
elseif executable('tmux') && (!empty($TMUX) || 0 == jobwait([jobstart(['tmux', 'list-buffers'])], 2000)[0])
|
||||
let tmux_v = v:lua.vim.version.parse(system(['tmux', '-V']))
|
||||
if !empty(tmux_v) && !v:lua.vim.version.lt(tmux_v, [3,2,0])
|
||||
let s:copy['+'] = ['tmux', 'load-buffer', '-w', '-']
|
||||
else
|
||||
let s:copy['+'] = ['tmux', 'load-buffer', '-']
|
||||
endif
|
||||
let s:paste['+'] = ['tmux', 'save-buffer', '-']
|
||||
let s:copy['*'] = s:copy['+']
|
||||
let s:paste['*'] = s:paste['+']
|
||||
return 'tmux'
|
||||
return s:set_tmux()
|
||||
elseif get(get(g:, 'termfeatures', {}), 'osc52') && &clipboard ==# ''
|
||||
" Don't use OSC 52 when 'clipboard' is set. It can be slow and cause a lot
|
||||
" of user prompts. Users can opt-in to it by setting g:clipboard manually.
|
||||
@@ -195,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
|
||||
@@ -221,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]
|
||||
@@ -284,4 +354,4 @@ function! provider#clipboard#Call(method, args) abort
|
||||
endfunction
|
||||
|
||||
" eval_has_provider() decides based on this variable.
|
||||
let g:loaded_clipboard_provider = empty(provider#clipboard#Executable()) ? 1 : 2
|
||||
let g:loaded_clipboard_provider = empty(provider#clipboard#Executable()) ? 0 : 2
|
||||
|
@@ -1,7 +1,7 @@
|
||||
if exists('g:loaded_node_provider')
|
||||
finish
|
||||
endif
|
||||
let g:loaded_node_provider = 1
|
||||
let g:loaded_node_provider = 0
|
||||
|
||||
function! s:is_minimum_version(version, min_version) abort
|
||||
if empty(a:version)
|
||||
@@ -152,7 +152,7 @@ endfunction
|
||||
|
||||
let s:err = ''
|
||||
let [s:prog, s:_] = provider#node#Detect()
|
||||
let g:loaded_node_provider = empty(s:prog) ? 1 : 2
|
||||
let g:loaded_node_provider = empty(s:prog) ? 0 : 2
|
||||
|
||||
if g:loaded_node_provider != 2
|
||||
let s:err = 'Cannot find the "neovim" node package. Try :checkhealth'
|
||||
|
@@ -11,5 +11,5 @@ function! provider#perl#Require(host) abort
|
||||
endfunction
|
||||
|
||||
let s:prog = v:lua.vim.provider.perl.detect()
|
||||
let g:loaded_perl_provider = empty(s:prog) ? 1 : 2
|
||||
let g:loaded_perl_provider = empty(s:prog) ? 0 : 2
|
||||
call v:lua.require'vim.provider.perl'.start()
|
||||
|
@@ -11,5 +11,5 @@ function! provider#python3#Require(host) abort
|
||||
endfunction
|
||||
|
||||
let s:prog = v:lua.vim.provider.python.detect_by_module('neovim')
|
||||
let g:loaded_python3_provider = empty(s:prog) ? 1 : 2
|
||||
let g:loaded_python3_provider = empty(s:prog) ? 0 : 2
|
||||
call v:lua.require'vim.provider.python'.start()
|
||||
|
@@ -11,6 +11,6 @@ function! provider#ruby#Call(method, args) abort
|
||||
endfunction
|
||||
|
||||
let s:prog = v:lua.vim.provider.ruby.detect()
|
||||
let g:loaded_ruby_provider = empty(s:prog) ? 1 : 2
|
||||
let g:loaded_ruby_provider = empty(s:prog) ? 0 : 2
|
||||
let s:plugin_path = expand('<sfile>:p:h') . '/script_host.rb'
|
||||
call v:lua.require'vim.provider.ruby'.start(s:plugin_path)
|
||||
|
@@ -77,49 +77,11 @@ function! tutor#TutorFolds()
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" Marks: {{{1
|
||||
|
||||
function! tutor#ApplyMarks()
|
||||
hi! link tutorExpect Special
|
||||
if exists('b:tutor_metadata') && has_key(b:tutor_metadata, 'expect')
|
||||
let b:tutor_sign_id = 1
|
||||
for expct in keys(b:tutor_metadata['expect'])
|
||||
let lnum = eval(expct)
|
||||
call matchaddpos('tutorExpect', [lnum])
|
||||
call tutor#CheckLine(lnum)
|
||||
endfor
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! tutor#ApplyMarksOnChanged()
|
||||
if exists('b:tutor_metadata') && has_key(b:tutor_metadata, 'expect')
|
||||
let lnum = line('.')
|
||||
if index(keys(b:tutor_metadata['expect']), string(lnum)) > -1
|
||||
call tutor#CheckLine(lnum)
|
||||
endif
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! tutor#CheckLine(line)
|
||||
if exists('b:tutor_metadata') && has_key(b:tutor_metadata, 'expect')
|
||||
let bufn = bufnr('%')
|
||||
let ctext = getline(a:line)
|
||||
let signs = sign_getplaced(bufn, {'lnum': a:line})[0].signs
|
||||
if !empty(signs)
|
||||
call sign_unplace('', {'id': signs[0].id})
|
||||
endif
|
||||
if b:tutor_metadata['expect'][string(a:line)] == -1 || ctext ==# b:tutor_metadata['expect'][string(a:line)]
|
||||
exe "sign place ".b:tutor_sign_id." line=".a:line." name=tutorok buffer=".bufn
|
||||
else
|
||||
exe "sign place ".b:tutor_sign_id." line=".a:line." name=tutorbad buffer=".bufn
|
||||
endif
|
||||
let b:tutor_sign_id+=1
|
||||
endif
|
||||
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 +94,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 +127,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 +163,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 +186,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
|
||||
lua require('nvim.tutor').apply_marks()
|
||||
augroup tutor_interactive
|
||||
autocmd! TextChanged,TextChangedI <buffer> lua require('nvim.tutor').apply_marks_on_changed()
|
||||
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' })
|
||||
<
|
||||
|
||||
@@ -2777,8 +2774,11 @@ nvim_buf_get_extmarks({buffer}, {ns_id}, {start}, {end}, {opts})
|
||||
vim.api.nvim_buf_get_extmarks(0, my_ns, {0,0}, {-1,-1}, {})
|
||||
<
|
||||
|
||||
If `end` is less than `start`, traversal works backwards. (Useful with
|
||||
`limit`, to get the first marks prior to a given position.)
|
||||
If `end` is less than `start`, marks are returned in reverse order.
|
||||
(Useful with `limit`, to get the first marks prior to a given position.)
|
||||
|
||||
Note: For a reverse range, `limit` does not actually affect the traversed
|
||||
range, just how many marks are returned
|
||||
|
||||
Note: when using extmark ranges (marks with a end_row/end_col position)
|
||||
the `overlap` option might be useful. Otherwise only the start position of
|
||||
@@ -3536,7 +3536,8 @@ nvim_open_win({buffer}, {enter}, {config}) *nvim_open_win()*
|
||||
the duration of the call.
|
||||
• fixed: If true when anchor is NW or SW, the float window
|
||||
would be kept fixed even if the window would be truncated.
|
||||
• hide: If true the floating window will be hidden.
|
||||
• hide: If true the floating window will be hidden and the
|
||||
cursor will be invisible when focused on it.
|
||||
• vertical: Split vertically |:vertical|.
|
||||
• split: Split direction: "left", "right", "above", "below".
|
||||
|
||||
@@ -3773,8 +3774,8 @@ nvim_create_autocmd({event}, {opts}) *nvim_create_autocmd()*
|
||||
• callback (function|string) optional: Lua function (or
|
||||
Vimscript function name, if string) called when the
|
||||
event(s) is triggered. Lua callback can return a truthy
|
||||
value (not `false` or `nil`) to delete the autocommand.
|
||||
Receives one argument, a table with these keys:
|
||||
value (not `false` or `nil`) to delete the autocommand, and
|
||||
receives one argument, a table with these keys:
|
||||
*event-args*
|
||||
• id: (number) autocommand id
|
||||
• event: (string) name of the triggered event
|
||||
|
@@ -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.
|
||||
@@ -574,8 +604,8 @@ Lua module: vim.diagnostic *diagnostic-api*
|
||||
*vim.diagnostic.Opts.Signs*
|
||||
|
||||
Fields: ~
|
||||
• {severity}? (`vim.diagnostic.SeverityFilter`) Only show virtual text
|
||||
for diagnostics matching the given severity
|
||||
• {severity}? (`vim.diagnostic.SeverityFilter`) Only show signs for
|
||||
diagnostics matching the given severity
|
||||
|diagnostic-severity|
|
||||
• {priority}? (`integer`, default: `10`) Base priority to use for
|
||||
signs. When {severity_sort} is used, the priority of a
|
||||
@@ -607,6 +637,9 @@ Lua module: vim.diagnostic *diagnostic-api*
|
||||
*vim.diagnostic.Opts.VirtualLines*
|
||||
|
||||
Fields: ~
|
||||
• {severity}? (`vim.diagnostic.SeverityFilter`) Only show virtual
|
||||
lines for diagnostics matching the given severity
|
||||
|diagnostic-severity|
|
||||
• {current_line}? (`boolean`, default: `false`) Only show diagnostics
|
||||
for the current line.
|
||||
• {format}? (`fun(diagnostic:vim.Diagnostic): string?`) A
|
||||
|
@@ -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|
|
||||
|
@@ -187,35 +187,28 @@ Run |:checkhealth| in Nvim for automatic diagnosis.
|
||||
|
||||
Other hints:
|
||||
|
||||
- The python `neovim` module was renamed to `pynvim` (long ago).
|
||||
- If you're using pyenv or virtualenv for the `pynvim` module
|
||||
https://pypi.org/project/pynvim/, you must set `g:python3_host_prog` to
|
||||
the virtualenv's interpreter path.
|
||||
- Read |provider-python|.
|
||||
- Read |provider-python| to learn how to install `pynvim`.
|
||||
- Be sure you have the latest version of the `pynvim` Python module: >bash
|
||||
|
||||
python -m pip install setuptools
|
||||
python -m pip install --upgrade pynvim
|
||||
python3 -m pip install --upgrade pynvim
|
||||
uv tool install --upgrade pynvim
|
||||
<
|
||||
See |provider-python| for other installation options.
|
||||
- If you're manually creating a Python virtual environment for the `pynvim` module
|
||||
https://pypi.org/project/pynvim/, you must set `g:python3_host_prog` to
|
||||
the virtualenv's interpreter path.
|
||||
- Try with `nvim -u NORC` to make sure your config (|init.vim|) isn't causing a
|
||||
problem. If you get `E117: Unknown function`, that means there's a runtime
|
||||
issue: |faq-runtime|.
|
||||
- The python `neovim` module was renamed to `pynvim` (long ago).
|
||||
|
||||
|
||||
:CHECKHEALTH REPORTS E5009: INVALID $VIMRUNTIME ~
|
||||
|
||||
This means `health#check()` couldn't load, which suggests that |$VIMRUNTIME|
|
||||
or 'runtimepath' is broken.
|
||||
This means |$VIMRUNTIME| or 'runtimepath' is broken.
|
||||
|
||||
- |$VIMRUNTIME| must point to Nvim's runtime files, not Vim's.
|
||||
- The |$VIMRUNTIME| directory contents should be readable by the current user.
|
||||
- Verify that `:echo &runtimepath` contains the $VIMRUNTIME path.
|
||||
- Check the output of: >vim
|
||||
|
||||
:call health#check()
|
||||
:verbose func health#check
|
||||
<
|
||||
|
||||
NEOVIM CAN'T FIND ITS RUNTIME ~
|
||||
|
||||
|
@@ -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()*
|
||||
|
@@ -373,11 +373,17 @@ To quote a block of ex-commands verbatim, place a greater than (>) character
|
||||
at the end of the line before the block and a less than (<) character as the
|
||||
first non-blank on a line following the block. Any line starting in column 1
|
||||
also implicitly stops the block of ex-commands before it. E.g. >
|
||||
function Example_Func()
|
||||
echo "Example"
|
||||
endfunction
|
||||
function Example_Func()
|
||||
echo "Example"
|
||||
endfunction
|
||||
<
|
||||
|
||||
To enable syntax highlighting for a block of code, place a language name
|
||||
annotation (e.g. "vim") after a greater than (>) character. E.g. >vim
|
||||
function Example_Func()
|
||||
echo "Example"
|
||||
endfunction
|
||||
<
|
||||
*help-notation*
|
||||
The following are highlighted differently in a Vim help file:
|
||||
- a special key name expressed either in <> notation as in <PageDown>, or
|
||||
as a Ctrl character as in CTRL-X
|
||||
|
@@ -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)
|
||||
@@ -129,7 +135,7 @@ following (in increasing priority):
|
||||
|
||||
1. Configuration defined for the `'*'` name.
|
||||
2. Configuration from the result of merging all tables returned by
|
||||
`lsp/<name>.lua` files in 'runtimepath' for a server of name `name`.
|
||||
`lsp/<config>.lua` files in 'runtimepath' for the config named `<config>`.
|
||||
3. Configurations defined anywhere else.
|
||||
|
||||
Note: The merge semantics of configurations follow the behaviour of
|
||||
@@ -250,8 +256,14 @@ FAQ *lsp-faq*
|
||||
" (async = false is the default for format)
|
||||
autocmd BufWritePre *.rs lua vim.lsp.buf.format({ async = false })
|
||||
<
|
||||
|
||||
- Q: How to avoid my own lsp/ folder being overridden?
|
||||
- A: Place your configs under "after/lsp/". Files in "after/lsp/" are loaded
|
||||
after those in "nvim/lsp/", so your settings will take precedence over
|
||||
the defaults provided by nvim-lspconfig. See also: |after-directory|
|
||||
|
||||
*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 +275,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 +303,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 +564,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 +584,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 +595,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 +619,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 +667,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 +696,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 +721,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 +922,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 +1061,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 +1208,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 +1235,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,125 +1299,138 @@ 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"; }
|
||||
• {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()|,
|
||||
passed to the language server on
|
||||
initialization. Hint: use
|
||||
make_client_capabilities() and modify its
|
||||
result.
|
||||
• Note: To send an empty dictionary use
|
||||
|vim.empty_dict()|, else it will be encoded
|
||||
as an array.
|
||||
• {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'; }
|
||||
<
|
||||
• {detached}? (`boolean`, default: true) Daemonize the server
|
||||
process so that it runs in a separate process
|
||||
group from Nvim. Nvim will shutdown the process
|
||||
on exit, but if Nvim fails to exit cleanly this
|
||||
could leave behind orphaned server processes.
|
||||
• {workspace_folders}? (`lsp.WorkspaceFolder[]`) List of workspace
|
||||
folders passed to the language server. For
|
||||
backwards compatibility rootUri and rootPath
|
||||
will be derived from the first workspace folder
|
||||
in this list. See `workspaceFolders` in the LSP
|
||||
spec.
|
||||
• {capabilities}? (`lsp.ClientCapabilities`) Map overriding the
|
||||
default capabilities defined by
|
||||
|vim.lsp.protocol.make_client_capabilities()|,
|
||||
passed to the language server on initialization.
|
||||
Hint: use make_client_capabilities() and modify
|
||||
its result.
|
||||
• Note: To send an empty dictionary use
|
||||
|vim.empty_dict()|, else it will be encoded as
|
||||
an array.
|
||||
• {handlers}? (`table<string,function>`) Map of language
|
||||
server method names to |lsp-handler|
|
||||
• {settings}? (`lsp.LSPObject`) Map with language server
|
||||
specific settings. See the {settings} in
|
||||
|vim.lsp.Client|.
|
||||
• {commands}? (`table<string,fun(command: lsp.Command, ctx: table)>`)
|
||||
Table that maps string of clientside commands to
|
||||
user-defined functions. Commands passed to
|
||||
`start()` 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
|
||||
• {flags}? (`table`) A table with flags for the client. The
|
||||
current (experimental) flags are:
|
||||
• {allow_incremental_sync}? (`boolean`, default:
|
||||
`true`) Allow using incremental sync for
|
||||
buffer edits
|
||||
• {debounce_text_changes} (`integer`, default:
|
||||
`150`) Debounce `didChange` notifications to
|
||||
the server by the given number in
|
||||
milliseconds. No debounce occurs if `nil`.
|
||||
• {exit_timeout} (`integer|false`, default:
|
||||
`false`) Milliseconds to wait for server to
|
||||
exit cleanly after sending the "shutdown"
|
||||
request before sending kill -15. If set to
|
||||
false, nvim exits immediately after sending
|
||||
the "shutdown" request to the server.
|
||||
• {root_dir}? (`string`) Directory where the LSP server will
|
||||
base its workspaceFolders, rootUri, and rootPath
|
||||
on initialization.
|
||||
• {commands}? (`table<string,fun(command: lsp.Command, ctx: 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.
|
||||
• {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`,
|
||||
default: `true`) Allow using incremental sync
|
||||
for buffer edits
|
||||
• {debounce_text_changes} (`integer`, default:
|
||||
`150`) Debounce `didChange` notifications to
|
||||
the server by the given number in
|
||||
milliseconds. No debounce occurs if `nil`.
|
||||
• {exit_timeout} (`integer|false`, default:
|
||||
`false`) Milliseconds to wait for server to
|
||||
exit cleanly after sending the "shutdown"
|
||||
request before sending kill -15. If set to
|
||||
false, nvim exits immediately after sending
|
||||
the "shutdown" request to the server.
|
||||
• {get_language_id}? (`fun(bufnr: integer, filetype: string): string`)
|
||||
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()*
|
||||
@@ -1539,7 +1616,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:
|
||||
@@ -2502,6 +2580,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.
|
||||
|
||||
|
@@ -10,19 +10,18 @@
|
||||
==============================================================================
|
||||
Introduction *lua-guide*
|
||||
|
||||
This guide will go through the basics of using Lua in Nvim. It is not meant
|
||||
to be a comprehensive encyclopedia of all available features, nor will it
|
||||
detail all intricacies. Think of it as a survival kit -- the bare minimum
|
||||
needed to know to comfortably get started on using Lua in Nvim.
|
||||
|
||||
An important thing to note is that this isn't a guide to the Lua language
|
||||
itself. Rather, this is a guide on how to configure and modify Nvim through
|
||||
the Lua language and the functions we provide to help with this. Take a look
|
||||
at |luaref| and |lua-concepts| if you'd like to learn more about Lua itself.
|
||||
Similarly, this guide assumes some familiarity with the basics of Nvim
|
||||
This guide introduces the basics of everyday usage of Lua to configure and
|
||||
operate Nvim. It assumes some familiarity with the (non-Lua) basics of Nvim
|
||||
(commands, options, mappings, autocommands), which are covered in the
|
||||
|user-manual|.
|
||||
|
||||
This is not a comprehensive encyclopedia of all available features. Think of
|
||||
it as a survival kit: the bare minimum needed to comfortably get started on
|
||||
using Lua in Nvim.
|
||||
|
||||
See |lua-plugin| for guidance on developing Lua plugins.
|
||||
See |luaref| and |lua-concepts| for details on the Lua programming language.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
Some words on the API *lua-guide-api*
|
||||
|
||||
@@ -93,10 +92,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'|.
|
||||
|
306
runtime/doc/lua-plugin.txt
Normal file
306
runtime/doc/lua-plugin.txt
Normal file
@@ -0,0 +1,306 @@
|
||||
*lua-plugin.txt* Nvim
|
||||
|
||||
NVIM REFERENCE MANUAL
|
||||
|
||||
Guide to developing Lua plugins for Nvim
|
||||
|
||||
|
||||
Type |gO| to see the table of contents.
|
||||
|
||||
==============================================================================
|
||||
Introduction *lua-plugin*
|
||||
|
||||
This document provides guidance for developing Nvim (Lua) plugins:
|
||||
|
||||
See |lua-guide| for guidance on using Lua to configure and operate Nvim.
|
||||
See |luaref| and |lua-concepts| for details on the Lua programming language.
|
||||
|
||||
==============================================================================
|
||||
Creating your first plugin *lua-plugin-new*
|
||||
|
||||
Any Vimscript or Lua code file that lives in the right directory,
|
||||
automatically is a "plugin". There's no maniest or "registration" required.
|
||||
|
||||
You can try it right now:
|
||||
|
||||
1. Visit your config directory: >
|
||||
:exe 'edit' stdpath('config')
|
||||
<
|
||||
2. Create a `plugin/foo.lua` file in there.
|
||||
3. Add something to it, like: >lua
|
||||
vim.print('Hello World')
|
||||
<
|
||||
4. Start `nvim` and notice that it prints "Hello World" in the messages area.
|
||||
Check `:messages` if you don't see it.
|
||||
|
||||
Besides `plugin/foo.lua`, which is always run at startup, you can define Lua
|
||||
modules in the `lua/` directory. Those modules aren't loaded until your
|
||||
`plugin/foo.lua`, the user, calls `require(…)`.
|
||||
|
||||
==============================================================================
|
||||
Type safety *lua-plugin-type-safety*
|
||||
|
||||
Lua, as a dynamically typed language, is great for configuration. It provides
|
||||
virtually immediate feedback.
|
||||
But for larger projects, this can be a double-edged sword, leaving your plugin
|
||||
susceptible to unexpected bugs at the wrong time.
|
||||
|
||||
You can leverage LuaCATS or "emmylua" annotations https://luals.github.io/wiki/annotations/
|
||||
along with lua-language-server ("LuaLS") https://luals.github.io/ to catch
|
||||
potential bugs in your CI before your plugin's users do. The Nvim codebase
|
||||
uses these annotations extensively.
|
||||
|
||||
TOOLS
|
||||
|
||||
- lua-typecheck-action https://github.com/marketplace/actions/lua-typecheck-action
|
||||
- lua-language-server https://luals.github.io
|
||||
|
||||
==============================================================================
|
||||
Keymaps *lua-plugin-keymaps*
|
||||
|
||||
Avoid creating excessive keymaps automatically. Doing so can conflict with
|
||||
user |mapping|s.
|
||||
|
||||
NOTE: An example for uncontroversial keymaps are buffer-local |mapping|s for
|
||||
specific file types or floating windows, or <Plug> mappings.
|
||||
|
||||
A common approach to allow keymap configuration is to define a declarative DSL
|
||||
https://en.wikipedia.org/wiki/Domain-specific_language via a `setup` function.
|
||||
|
||||
However, doing so means that
|
||||
|
||||
- You will have to implement and document it yourself.
|
||||
- Users will likely face inconsistencies if another plugin has a slightly
|
||||
different DSL.
|
||||
- |init.lua| scripts that call such a `setup` function may throw an error if
|
||||
the plugin is not installed or disabled.
|
||||
|
||||
As an alternative, you can provide |<Plug>| mappings to allow users to define
|
||||
their own keymaps with |vim.keymap.set()|.
|
||||
|
||||
- This requires one line of code in user configs.
|
||||
- Even if your plugin is not installed or disabled, creating the keymap won't
|
||||
throw an error.
|
||||
|
||||
Another option is to simply expose a Lua function or |user-commands|.
|
||||
|
||||
Some benefits of |<Plug>| mappings are that you can
|
||||
|
||||
- Enforce options like `expr = true`.
|
||||
- Use |vim.keymap|'s built-in mode handling to expose functionality only for
|
||||
specific |map-modes|.
|
||||
- Handle different |map-modes| differently with a single mapping, without
|
||||
adding mode checks to the underlying implementation.
|
||||
- Detect user-defined mappings through |hasmapto()| before creating defaults.
|
||||
|
||||
Some benefits of exposing a Lua function are:
|
||||
|
||||
- Extensibility, if the function takes an options table as an argument.
|
||||
- A cleaner UX, if there are many options and enumerating all combinations
|
||||
of options would result in a lot of |<Plug>| mappings.
|
||||
|
||||
NOTE: If your function takes an options table, users may still benefit
|
||||
from |<Plug>| mappings for the most common combinations.
|
||||
|
||||
KEYMAP EXAMPLE
|
||||
|
||||
In your plugin:
|
||||
>lua
|
||||
vim.keymap.set('n', '<Plug>(SayHello)', function()
|
||||
print('Hello from normal mode')
|
||||
end, { noremap = true })
|
||||
|
||||
vim.keymap.set('v', '<Plug>(SayHello)', function()
|
||||
print('Hello from visual mode')
|
||||
end, { noremap = true })
|
||||
<
|
||||
In the user's config:
|
||||
>lua
|
||||
vim.keymap.set({'n', 'v'}, '<leader>h', '<Plug>(SayHello)')
|
||||
<
|
||||
==============================================================================
|
||||
Initialization *lua-plugin-init*
|
||||
|
||||
Newcomers to Lua plugin development will often put all initialization logic in
|
||||
a single `setup` function, which takes a table of options.
|
||||
If you do this, users will be forced to call this function in order to use
|
||||
your plugin, even if they are happy with the default configuration.
|
||||
|
||||
Strictly separated configuration and smart initialization allow your plugin to
|
||||
work out of the box.
|
||||
|
||||
NOTE: A well designed plugin has minimal impact on startup time. See also
|
||||
|lua-plugin-lazy|.
|
||||
|
||||
Common approaches to a strictly separated configuration are:
|
||||
|
||||
- A Lua function, e.g. `setup(opts)` or `configure(opts)`, which only overrides the
|
||||
default configuration and does not contain any initialization logic.
|
||||
- A Vimscript compatible table (e.g. in the |vim.g| or |vim.b| namespace) that your
|
||||
plugin reads from and validates at initialization time.
|
||||
See also |lua-vim-variables|.
|
||||
|
||||
Typically, automatic initialization logic is done in a |plugin| or |ftplugin|
|
||||
script. See also |'runtimepath'|.
|
||||
|
||||
==============================================================================
|
||||
Lazy loading *lua-plugin-lazy*
|
||||
|
||||
Some users like to micro-manage "lazy loading" of plugins by explicitly
|
||||
configuring which commands and key mappings load the plugin.
|
||||
|
||||
Your plugin should not depend on every user micro-managing their configuration
|
||||
in such a way. Nvim has a mechanism for every plugin to do its own implicit
|
||||
lazy-loading (in Vimscript it's called |autoload|), via `autoload/`
|
||||
(Vimscript) and `lua/` (Lua). Plugin authors can provide "lazy loading" by
|
||||
providing a `plugin/<name>.lua` file which defines their commands and
|
||||
keymappings. This file should be small, and should not eagerly `require()` the
|
||||
rest of your plugin. Commands and mappings should do the `require()`.
|
||||
|
||||
Guidance:
|
||||
|
||||
- Plugins should arrange their "lazy" behavior once, instead of expecting every user to micromanage it.
|
||||
- Keep `plugin/<name>.lua` small, avoid eagerly calling `require()` on modules
|
||||
until a command or mapping is actually used.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
Defer require() calls *lua-plugin-defer-require*
|
||||
|
||||
`plugin/<name>.lua` scripts (|plugin|) are eagerly run at startup; this is
|
||||
intentional, so that plugins can setup the (minimal) commands and keymappings
|
||||
that users will use to invoke the plugin. This also means these "plugin/"
|
||||
files should NOT eagerly `require` Lua modules.
|
||||
|
||||
For example, instead of:
|
||||
>lua
|
||||
local foo = require('foo')
|
||||
vim.api.nvim_create_user_command('MyCommand', function()
|
||||
foo.do_something()
|
||||
end, { -- ... })
|
||||
<
|
||||
which calls `require('foo')` as soon as the module is loaded, you can
|
||||
lazy-load it by moving the `require` into the command's implementation:
|
||||
>lua
|
||||
vim.api.nvim_create_user_command('MyCommand', function()
|
||||
local foo = require('foo')
|
||||
foo.do_something()
|
||||
end, {
|
||||
-- ...
|
||||
})
|
||||
<
|
||||
Likewise, if a plugin uses a Lua module as an entrypoint, it should
|
||||
defer `require` calls too.
|
||||
|
||||
NOTE: For a Vimscript alternative to `require`, see |autoload|.
|
||||
|
||||
NOTE: If you are worried about eagerly creating user commands, autocommands or
|
||||
keymaps at startup: Plugin managers that provide abstractions for lazy-loading
|
||||
plugins on such events do the same amount of work. There is no performance
|
||||
benefit for users to define lazy-loading entrypoints in their configuration
|
||||
instead of plugins defining it in `plugin/<name>.lua`.
|
||||
|
||||
NOTE: You can use |--startuptime| to |profile| the impact a plugin has on
|
||||
startup time.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
Filetype-specific functionality *lua-plugin-filetype*
|
||||
|
||||
Consider making use of 'filetype' for any functionality that is specific to
|
||||
a filetype, by putting the initialization logic in a `ftplugin/{filetype}.lua`
|
||||
script.
|
||||
|
||||
FILETYPE EXAMPLE
|
||||
|
||||
A plugin tailored to Rust development might have initialization in
|
||||
`ftplugin/rust.lua`:
|
||||
>lua
|
||||
if not vim.g.loaded_my_rust_plugin then
|
||||
-- Initialize
|
||||
end
|
||||
-- NOTE: Using `vim.g.loaded_` prevents the plugin from initializing twice
|
||||
-- and allows users to prevent plugins from loading
|
||||
-- (in both Lua and Vimscript).
|
||||
vim.g.loaded_my_rust_plugin = true
|
||||
|
||||
local bufnr = vim.api.nvim_get_current_buf()
|
||||
-- do something specific to this buffer,
|
||||
-- e.g. add a |<Plug>| mapping or create a command
|
||||
vim.keymap.set('n', '<Plug>(MyPluginBufferAction)', function()
|
||||
print('Hello')
|
||||
end, { noremap = true, buffer = bufnr, })
|
||||
<
|
||||
==============================================================================
|
||||
Configuration *lua-plugin-config*
|
||||
|
||||
Once you have merged the default configuration with the user's config, you
|
||||
should validate configs.
|
||||
|
||||
Validations could include:
|
||||
|
||||
- Correct types, see |vim.validate()|
|
||||
- Unknown fields in the user config (e.g. due to typos).
|
||||
This can be tricky to implement, and may be better suited for a |health|
|
||||
check, to reduce overhead.
|
||||
|
||||
==============================================================================
|
||||
Troubleshooting *lua-plugin-troubleshooting*
|
||||
|
||||
HEALTH
|
||||
|
||||
Nvim's "health" framework gives plugins a simple way to report status checks
|
||||
to users. See |health-dev| for an example.
|
||||
|
||||
Basically, this just means your plugin will have a `lua/{plugin}/health.lua`
|
||||
file. |:checkhealth| will automatically find this file when it runs.
|
||||
|
||||
Some things to validate:
|
||||
|
||||
- User configuration
|
||||
- Proper initialization
|
||||
- Presence of Lua dependencies (e.g. other plugins)
|
||||
- Presence of external dependencies
|
||||
|
||||
MINIMAL CONFIG TEMPLATE
|
||||
|
||||
It can be useful to provide a template for a minimal configuration, along with
|
||||
a guide on how to use it to reproduce issues.
|
||||
|
||||
==============================================================================
|
||||
Versioning and releases *lua-plugin-versioning*
|
||||
|
||||
Consider:
|
||||
|
||||
- Use |vim.deprecate()| or a `---@deprecate` annotation when you need to
|
||||
communicate a (future) breaking change or discourged practice.
|
||||
- Using SemVer https://semver.org/ tags and releases to properly communicate
|
||||
bug fixes, new features, and breaking changes.
|
||||
- Automating versioning and releases in CI.
|
||||
- Publishing to luarocks https://luarocks.org, especially if your plugin
|
||||
has dependencies or components that need to be built; or if it could be a
|
||||
dependency for another plugin.
|
||||
|
||||
FURTHER READING
|
||||
|
||||
- Luarocks ❤️ Nvim https://github.com/nvim-neorocks/sample-luarocks-plugin
|
||||
|
||||
VERSIONING TOOLS
|
||||
|
||||
- luarocks-tag-release
|
||||
https://github.com/marketplace/actions/luarocks-tag-release
|
||||
- release-please-action
|
||||
https://github.com/marketplace/actions/release-please-action
|
||||
- semantic-release
|
||||
https://github.com/semantic-release/semantic-release
|
||||
|
||||
==============================================================================
|
||||
Documentation *lua-plugin-doc*
|
||||
|
||||
Provide vimdoc (see |help-writing|), so that users can read your plugin's
|
||||
documentation in Nvim, by entering `:h {plugin}` in |command-mode|.
|
||||
|
||||
DOCUMENTATION TOOLS
|
||||
|
||||
- panvimdoc https://github.com/kdheepak/panvimdoc
|
||||
|
||||
|
||||
vim:tw=78:ts=8:sw=4:sts=4:et:ft=help:norl:
|
@@ -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
|
||||
@@ -188,15 +188,19 @@ Examples: >lua
|
||||
==============================================================================
|
||||
IMPORTING LUA MODULES *lua-module-load*
|
||||
|
||||
Modules are searched for under the directories specified in 'runtimepath', in
|
||||
the order they appear. Any "." in the module name is treated as a directory
|
||||
separator when searching. For a module `foo.bar`, each directory is searched
|
||||
for `lua/foo/bar.lua`, then `lua/foo/bar/init.lua`. If no files are found,
|
||||
the directories are searched again for a shared library with a name matching
|
||||
`lua/foo/bar.?`, where `?` is a list of suffixes (such as `so` or `dll`) derived from
|
||||
the initial value of |package.cpath|. If still no files are found, Nvim falls
|
||||
back to Lua's default search mechanism. The first script found is run and
|
||||
`require()` returns the value returned by the script if any, else `true`.
|
||||
Modules are searched for under the directories specified in 'runtimepath' and
|
||||
|packages-runtimepath|, in the order they appear in the output of this command
|
||||
>vim
|
||||
:echo nvim_list_runtime_paths()
|
||||
<
|
||||
Any "." in the module name is treated as a directory separator when searching.
|
||||
For a module `foo.bar`, each directory is searched for `lua/foo/bar.lua`, then
|
||||
`lua/foo/bar/init.lua`. If no files are found, the directories are searched
|
||||
again for a shared library with a name matching `lua/foo/bar.?`, where `?` is
|
||||
a list of suffixes (such as `so` or `dll`) derived from the initial value of
|
||||
|package.cpath|. If still no files are found, Nvim falls back to Lua's default
|
||||
search mechanism. The first script found is run and `require()` returns the
|
||||
value returned by the script if any, else `true`.
|
||||
|
||||
The return value is cached after the first call to `require()` for each module,
|
||||
with subsequent calls returning the cached value without searching for, or
|
||||
@@ -214,56 +218,9 @@ and loads the first module found ("first wins"): >
|
||||
bar/lua/mod.so
|
||||
bar/lua/mod.dll
|
||||
<
|
||||
*lua-package-path*
|
||||
Nvim automatically adjusts |package.path| and |package.cpath| according to the
|
||||
effective 'runtimepath' value. Adjustment happens whenever 'runtimepath' is
|
||||
changed. `package.path` is adjusted by simply appending `/lua/?.lua` and
|
||||
`/lua/?/init.lua` to each directory from 'runtimepath' (`/` is actually the
|
||||
first character of `package.config`).
|
||||
|
||||
Similarly to |package.path|, modified directories from 'runtimepath' are also
|
||||
added to |package.cpath|. In this case, instead of appending `/lua/?.lua` and
|
||||
`/lua/?/init.lua` to each runtimepath, all unique `?`-containing suffixes of
|
||||
the existing |package.cpath| are used. Example:
|
||||
|
||||
- 1. Given that
|
||||
- 'runtimepath' contains `/foo/bar,/xxx;yyy/baz,/abc`;
|
||||
- initial |package.cpath| (defined at compile-time or derived from
|
||||
`$LUA_CPATH` / `$LUA_INIT`) contains `./?.so;/def/ghi/a?d/j/g.elf;/def/?.so`.
|
||||
- 2. It finds `?`-containing suffixes `/?.so`, `/a?d/j/g.elf` and `/?.so`, in
|
||||
order: parts of the path starting from the first path component containing
|
||||
question mark and preceding path separator.
|
||||
- 3. The suffix of `/def/?.so`, namely `/?.so` is not unique, as it’s the same
|
||||
as the suffix of the first path from |package.path| (i.e. `./?.so`). Which
|
||||
leaves `/?.so` and `/a?d/j/g.elf`, in this order.
|
||||
- 4. 'runtimepath' has three paths: `/foo/bar`, `/xxx;yyy/baz` and `/abc`. The
|
||||
second one contains a semicolon which is a paths separator so it is out,
|
||||
leaving only `/foo/bar` and `/abc`, in order.
|
||||
- 5. The cartesian product of paths from 4. and suffixes from 3. is taken,
|
||||
giving four variants. In each variant a `/lua` path segment is inserted
|
||||
between path and suffix, leaving:
|
||||
- `/foo/bar/lua/?.so`
|
||||
- `/foo/bar/lua/a?d/j/g.elf`
|
||||
- `/abc/lua/?.so`
|
||||
- `/abc/lua/a?d/j/g.elf`
|
||||
- 6. New paths are prepended to the original |package.cpath|.
|
||||
|
||||
The result will look like this: >
|
||||
|
||||
/foo/bar,/xxx;yyy/baz,/abc ('runtimepath')
|
||||
× ./?.so;/def/ghi/a?d/j/g.elf;/def/?.so (package.cpath)
|
||||
= /foo/bar/lua/?.so;/foo/bar/lua/a?d/j/g.elf;/abc/lua/?.so;/abc/lua/a?d/j/g.elf;./?.so;/def/ghi/a?d/j/g.elf;/def/?.so
|
||||
|
||||
Note:
|
||||
|
||||
- To track 'runtimepath' updates, paths added at previous update are
|
||||
remembered and removed at the next update, while all paths derived from the
|
||||
new 'runtimepath' are prepended as described above. This allows removing
|
||||
paths when path is removed from 'runtimepath', adding paths when they are
|
||||
added and reordering |package.path|/|package.cpath| content if 'runtimepath'
|
||||
was reordered.
|
||||
|
||||
- Although adjustments happen automatically, Nvim does not track current
|
||||
- Although 'runtimepath' is tracked, Nvim does not track current
|
||||
values of |package.path| or |package.cpath|. If you happen to delete some
|
||||
paths from there you can set 'runtimepath' to trigger an update: >vim
|
||||
let &runtimepath = &runtimepath
|
||||
@@ -683,6 +640,12 @@ vim.hl.range({bufnr}, {ns}, {higroup}, {start}, {finish}, {opts})
|
||||
• {timeout}? (`integer`, default: -1 no timeout) Time in ms
|
||||
before highlight is cleared
|
||||
|
||||
Return (multiple): ~
|
||||
(`uv.uv_timer_t?`) range_timer A timer which manages how much time the
|
||||
highlight has left
|
||||
(`fun()?`) range_clear A function which allows clearing the highlight
|
||||
manually. nil is returned if timeout is not specified
|
||||
|
||||
|
||||
==============================================================================
|
||||
VIM.DIFF *vim.diff*
|
||||
@@ -1503,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"' } })
|
||||
@@ -1524,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|
|
||||
@@ -1816,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
|
||||
@@ -2059,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
|
||||
|
||||
@@ -2152,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
|
||||
@@ -2407,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()*
|
||||
@@ -2707,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.
|
||||
|
||||
@@ -2935,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
|
||||
<
|
||||
|
||||
@@ -2977,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:
|
||||
@@ -2990,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
|
||||
@@ -3015,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: ~
|
||||
@@ -3041,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
|
||||
@@ -3124,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
|
||||
<
|
||||
|
||||
@@ -3188,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' })
|
||||
|
||||
@@ -3199,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: ~
|
||||
@@ -3208,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
|
||||
@@ -3774,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*
|
||||
|
||||
|
@@ -119,10 +119,6 @@ OPTIONS
|
||||
• Setting |hidden-options| now gives an error. In particular, setting
|
||||
'noshellslash' is now only allowed on Windows.
|
||||
|
||||
PLUGINS
|
||||
|
||||
• TODO
|
||||
|
||||
TREESITTER
|
||||
|
||||
• |Query:iter_matches()| correctly returns all matching nodes in a match
|
||||
@@ -136,12 +132,11 @@ TREESITTER
|
||||
if no languages are explicitly registered.
|
||||
• |vim.treesitter.language.add()| returns `true` if a parser was loaded
|
||||
successfully and `nil,errmsg` otherwise instead of throwing an error.
|
||||
• |vim.treesitter.get_parser()| and |vim.treesitter.start()| no longer parse
|
||||
the tree before returning. Scripts must call |LanguageTree:parse()| explicitly. >lua
|
||||
• |vim.treesitter.get_parser()| and |vim.treesitter.start()| no longer parse the
|
||||
tree before returning. Scripts must call |LanguageTree:parse()| explicitly. >lua
|
||||
local p = vim.treesitter.get_parser(0, 'c')
|
||||
p:parse()
|
||||
• |vim.treesitter.get_parser()| expects its buffer to be loaded.
|
||||
<
|
||||
|
||||
TUI
|
||||
|
||||
@@ -176,7 +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.hl.range()| now has a optional `timeout` field which allows for a timed highlight
|
||||
• |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
|
||||
|
||||
@@ -189,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.
|
||||
@@ -242,8 +242,7 @@ EDITOR
|
||||
• |hl-ComplMatchIns| shows matched text of the currently inserted completion.
|
||||
• |hl-PmenuMatch| and |hl-PmenuMatchSel| show matched text in completion popup.
|
||||
• |gO| now works in `help`, `checkhealth`, and `markdown` buffers.
|
||||
• Jump between sections in `help` and `checkhealth` buffers with `[[` and
|
||||
`]]`.
|
||||
• Jump between sections in `help` and `checkhealth` buffers with `[[` and `]]`.
|
||||
|
||||
EVENTS
|
||||
|
||||
@@ -283,12 +282,16 @@ LSP
|
||||
`codeAction/resolve` request.
|
||||
• 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
|
||||
|
||||
• Command-line completions for: `vim.g`, `vim.t`, `vim.w`, `vim.b`, `vim.v`,
|
||||
`vim.o`, `vim.wo`, `vim.bo`, `vim.opt`, `vim.opt_local`, `vim.opt_global`,
|
||||
and `vim.fn`.
|
||||
`vim.env` and `vim.fn`.
|
||||
• Documentation for |lua-bit|.
|
||||
• |gf| in Lua buffers can go to module in same repo, |runtime-search-path| and
|
||||
|package.path|.
|
||||
@@ -302,7 +305,10 @@ LUA
|
||||
• |vim.fs.relpath()| gets relative path compared to base path.
|
||||
• |vim.fs.dir()| and |vim.fs.find()| can now follow symbolic links,
|
||||
the behavior can be turn on using the new `follow` option.
|
||||
• |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
|
||||
|
||||
@@ -312,7 +318,9 @@ OPTIONS
|
||||
• 'messagesopt' configures |:messages| and |hit-enter| prompt.
|
||||
• 'tabclose' controls which tab page to focus when closing a tab page.
|
||||
• 'eventignorewin' to persistently ignore events in a window.
|
||||
• 'winborder' sets the default border for |floating-windows|
|
||||
• 'winborder' sets the default border for |floating-windows|.
|
||||
• 'winborder' "bold" style.
|
||||
• |g:clipboard| accepts a string name to force any builtin clipboard tool.
|
||||
|
||||
PERFORMANCE
|
||||
|
||||
@@ -345,6 +353,13 @@ 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|
|
||||
|
||||
• Simplify Python provider setup to a single step: `uv tool install pynvim`
|
||||
Nvim will detect the plugin's location without user configuration, even if
|
||||
unrelated Python virtual environments are activated.
|
||||
|provider-python|
|
||||
|
||||
STARTUP
|
||||
|
||||
@@ -439,6 +454,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:
|
||||
@@ -7155,12 +7167,13 @@ A jump table for the options with a short description can be found at |Q_op|.
|
||||
global
|
||||
Defines the default border style of floating windows. The default value
|
||||
is empty, which is equivalent to "none". Valid values include:
|
||||
- "bold": Bold line box.
|
||||
- "double": Double-line box.
|
||||
- "none": No border.
|
||||
- "single": A single line box.
|
||||
- "double": A double line box.
|
||||
- "rounded": Like "single", but with rounded corners ("╭" etc.).
|
||||
- "shadow": Drop shadow effect, by blending with the background.
|
||||
- "single": Single-line box.
|
||||
- "solid": Adds padding by a single whitespace cell.
|
||||
- "shadow": A drop shadow effect by blending with the background.
|
||||
|
||||
*'window'* *'wi'*
|
||||
'window' 'wi' number (default screen height - 1)
|
||||
|
@@ -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:
|
||||
|
@@ -11,7 +11,7 @@ the providers and how to install them.
|
||||
*E319*
|
||||
Use of a feature requiring a missing provider is an error: >
|
||||
|
||||
E319: No "foo" provider found. Run ":checkhealth provider"
|
||||
E319: No "foo" provider found. Run ":checkhealth vim.provider"
|
||||
|
||||
Run the |:checkhealth| command, and review the sections below.
|
||||
|
||||
@@ -35,22 +35,19 @@ if you already have it (some package managers install the module with Nvim
|
||||
itself).
|
||||
|
||||
For Python 3 plugins:
|
||||
1. Make sure Python 3.4+ is available in your $PATH.
|
||||
2. Install the module (try "python" if "python3" is missing): >bash
|
||||
python3 -m pip install --user --upgrade pynvim
|
||||
1. Make sure Python 3.9+ is available in your $PATH.
|
||||
2. Install either uv (https://docs.astral.sh/uv/) or pipx
|
||||
(https://pipx.pypa.io/stable/).
|
||||
3. Install the module: >bash
|
||||
uv tool install --upgrade pynvim
|
||||
# or:
|
||||
pipx install --upgrade pynvim
|
||||
|
||||
The pip `--upgrade` flag ensures that you get the latest version even if
|
||||
The `--upgrade` flag ensures that you get the latest version even if
|
||||
a previous version was already installed.
|
||||
|
||||
See also |python-virtualenv|.
|
||||
|
||||
Note: The old "neovim" module was renamed to "pynvim".
|
||||
https://github.com/neovim/neovim/wiki/Following-HEAD#20181118
|
||||
If you run into problems, uninstall _both_ then install "pynvim" again: >bash
|
||||
python -m pip uninstall neovim pynvim
|
||||
python -m pip install --user --upgrade pynvim
|
||||
|
||||
|
||||
PYTHON PROVIDER CONFIGURATION ~
|
||||
*g:python3_host_prog*
|
||||
Command to start Python 3 (executable, not directory). Setting this makes
|
||||
@@ -65,20 +62,18 @@ To disable Python 3 support: >vim
|
||||
|
||||
PYTHON VIRTUALENVS ~
|
||||
*python-virtualenv*
|
||||
If you plan to use per-project virtualenvs often, you should assign one
|
||||
virtualenv for Nvim and hard-code the interpreter path via
|
||||
|g:python3_host_prog| so that the "pynvim" package is not required
|
||||
for each virtualenv.
|
||||
|
||||
Example using pyenv: >bash
|
||||
pyenv install 3.4.4
|
||||
pyenv virtualenv 3.4.4 py3nvim
|
||||
pyenv activate py3nvim
|
||||
python3 -m pip install pynvim
|
||||
pyenv which python # Note the path
|
||||
The last command reports the interpreter path, add it to your init.vim: >vim
|
||||
let g:python3_host_prog = '/path/to/py3nvim/bin/python'
|
||||
Using pynvim 0.6.0+ installed via uv or pipx, Nvim will automatically detect
|
||||
pynvim even if other Python virtual environments are activated (technical
|
||||
note: via the "pynvim-python" global python tool). For older pynvim (or older
|
||||
Neovim), where detection involved finding the first Python interpreter and
|
||||
checking if it could import pynvim, automatic detection would fail when
|
||||
another virtual environment is active. Upgrading to the latest pynvim is the
|
||||
recommended solution to this; but if that's not an option, then you can set
|
||||
the variable |g:python3_host_prog| in `init.vim` to point to the full path to
|
||||
the Python interpreter where `pynvim` is installed, e.g.: >vim
|
||||
|
||||
let g:python3_host_prog = '/path/to/pynvim-venv/bin/python'
|
||||
<
|
||||
See also: https://github.com/zchee/deoplete-jedi/wiki/Setting-up-Python-for-Neovim
|
||||
|
||||
==============================================================================
|
||||
@@ -182,100 +177,112 @@ the "+" and/or "*" registers explicitly): >vim
|
||||
See 'clipboard' for details and options.
|
||||
|
||||
*clipboard-tool*
|
||||
The presence of a working clipboard tool implicitly enables the '+' and "*"
|
||||
registers. Nvim looks for these clipboard tools, in order of priority:
|
||||
The presence of a working clipboard tool implicitly enables the "+" and "*"
|
||||
registers. Nvim supports these clipboard tools, in order of priority:
|
||||
|
||||
- |g:clipboard| (unless unset or `false`)
|
||||
- pbcopy, pbpaste (macOS)
|
||||
- wl-copy, wl-paste (if $WAYLAND_DISPLAY is set)
|
||||
- waycopy, waypaste (if $WAYLAND_DISPLAY is set)
|
||||
- xsel (if $DISPLAY is set)
|
||||
- xclip (if $DISPLAY is set)
|
||||
- lemonade (for SSH) https://github.com/pocke/lemonade
|
||||
- doitclient (for SSH) https://www.chiark.greenend.org.uk/~sgtatham/doit/
|
||||
- *win32yank* (Windows)
|
||||
- putclip, getclip (Windows) https://cygwin.com/packages/summary/cygutils.html
|
||||
- clip, powershell (Windows) https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/clip
|
||||
- termux (via termux-clipboard-set, termux-clipboard-set)
|
||||
- tmux (if $TMUX is set)
|
||||
- |g:clipboard| : User override (if set to a dict or any string "name" below;
|
||||
e.g. `g:clipboard="tmux"` forces tmux clipboard and skips auto-detection).
|
||||
- "pbcopy" : pbcopy, pbpaste (macOS)
|
||||
- "wl-copy" : wl-copy, wl-paste (if $WAYLAND_DISPLAY is set)
|
||||
- "wayclip" : waycopy, waypaste (if $WAYLAND_DISPLAY is set)
|
||||
- "xsel" : xsel (if $DISPLAY is set)
|
||||
- "xclip" : xclip (if $DISPLAY is set)
|
||||
- "lemonade" : lemonade (for SSH) https://github.com/pocke/lemonade
|
||||
- "doitclient": doitclient (for SSH) https://www.chiark.greenend.org.uk/~sgtatham/doit/
|
||||
- "win32yank" : *win32yank* (Windows)
|
||||
- "putclip" : putclip, getclip (Windows) https://cygwin.com/packages/summary/cygutils.html
|
||||
- "clip" : clip, powershell (Windows) https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/clip
|
||||
- "termux" : termux (via termux-clipboard-set, termux-clipboard-set)
|
||||
- "tmux" : tmux (if $TMUX is set)
|
||||
- "osc52" : |clipboard-osc52| (if supported by your terminal)
|
||||
|
||||
*g:clipboard*
|
||||
To configure a custom clipboard tool, set g:clipboard to a dictionary.
|
||||
For example this configuration integrates the tmux clipboard: >vim
|
||||
|
||||
let g:clipboard = {
|
||||
\ 'name': 'myClipboard',
|
||||
\ 'copy': {
|
||||
\ '+': ['tmux', 'load-buffer', '-'],
|
||||
\ '*': ['tmux', 'load-buffer', '-'],
|
||||
\ },
|
||||
\ 'paste': {
|
||||
\ '+': ['tmux', 'save-buffer', '-'],
|
||||
\ '*': ['tmux', 'save-buffer', '-'],
|
||||
\ },
|
||||
\ 'cache_enabled': 1,
|
||||
\ }
|
||||
To configure a custom clipboard tool, set `g:clipboard` to a string name (from
|
||||
the above |clipboard-tool| list), or dict (to explicitly specify the shell
|
||||
commands or |lambda| functions).
|
||||
|
||||
If "cache_enabled" is |TRUE| then when a selection is copied Nvim will cache
|
||||
the selection until the copy command process dies. When pasting, if the copy
|
||||
process has not died the cached selection is applied.
|
||||
|
||||
g:clipboard can also use functions (see |lambda|) instead of strings.
|
||||
For example this configuration uses the g:foo variable as a fake clipboard:
|
||||
>vim
|
||||
|
||||
let g:clipboard = {
|
||||
\ 'name': 'myClipboard',
|
||||
\ 'copy': {
|
||||
\ '+': {lines, regtype -> extend(g:, {'foo': [lines, regtype]}) },
|
||||
\ '*': {lines, regtype -> extend(g:, {'foo': [lines, regtype]}) },
|
||||
\ },
|
||||
\ 'paste': {
|
||||
\ '+': {-> get(g:, 'foo', [])},
|
||||
\ '*': {-> get(g:, 'foo', [])},
|
||||
\ },
|
||||
\ }
|
||||
|
||||
The "copy" function stores a list of lines and the register type. The "paste"
|
||||
function returns the clipboard as a `[lines, regtype]` list, where `lines` is
|
||||
a list of lines and `regtype` is a register type conforming to |setreg()|.
|
||||
|
||||
Example: set to "osc52" to force OSC52, skipping auto-detection of terminal
|
||||
support: >vim
|
||||
|
||||
let g:clipboard = 'osc52'
|
||||
|
||||
Example: set to "wayclip" to force waycopy/waypaste: >vim
|
||||
|
||||
let g:clipboard = 'wayclip'
|
||||
|
||||
Example: set to a dict which integrates the tmux clipboard: >vim
|
||||
|
||||
let g:clipboard = {
|
||||
\ 'name': 'myClipboard',
|
||||
\ 'copy': {
|
||||
\ '+': ['tmux', 'load-buffer', '-'],
|
||||
\ '*': ['tmux', 'load-buffer', '-'],
|
||||
\ },
|
||||
\ 'paste': {
|
||||
\ '+': ['tmux', 'save-buffer', '-'],
|
||||
\ '*': ['tmux', 'save-buffer', '-'],
|
||||
\ },
|
||||
\ 'cache_enabled': 1,
|
||||
\ }
|
||||
|
||||
|
||||
Example: set to a dict which uses g:foo as a fake clipboard: >vim
|
||||
|
||||
let g:clipboard = {
|
||||
\ 'name': 'myClipboard',
|
||||
\ 'copy': {
|
||||
\ '+': {lines, regtype -> extend(g:, {'foo': [lines, regtype]}) },
|
||||
\ '*': {lines, regtype -> extend(g:, {'foo': [lines, regtype]}) },
|
||||
\ },
|
||||
\ 'paste': {
|
||||
\ '+': {-> get(g:, 'foo', [])},
|
||||
\ '*': {-> get(g:, 'foo', [])},
|
||||
\ },
|
||||
\ }
|
||||
<
|
||||
*clipboard-wsl*
|
||||
For Windows WSL, try this g:clipboard definition:
|
||||
>vim
|
||||
let g:clipboard = {
|
||||
\ 'name': 'WslClipboard',
|
||||
\ 'copy': {
|
||||
\ '+': 'clip.exe',
|
||||
\ '*': 'clip.exe',
|
||||
\ },
|
||||
\ 'paste': {
|
||||
\ '+': 'powershell.exe -NoLogo -NoProfile -c [Console]::Out.Write($(Get-Clipboard -Raw).tostring().replace("`r", ""))',
|
||||
\ '*': 'powershell.exe -NoLogo -NoProfile -c [Console]::Out.Write($(Get-Clipboard -Raw).tostring().replace("`r", ""))',
|
||||
\ },
|
||||
\ 'cache_enabled': 0,
|
||||
\ }
|
||||
\ 'name': 'WslClipboard',
|
||||
\ 'copy': {
|
||||
\ '+': 'clip.exe',
|
||||
\ '*': 'clip.exe',
|
||||
\ },
|
||||
\ 'paste': {
|
||||
\ '+': 'powershell.exe -NoLogo -NoProfile -c [Console]::Out.Write($(Get-Clipboard -Raw).tostring().replace("`r", ""))',
|
||||
\ '*': 'powershell.exe -NoLogo -NoProfile -c [Console]::Out.Write($(Get-Clipboard -Raw).tostring().replace("`r", ""))',
|
||||
\ },
|
||||
\ 'cache_enabled': 0,
|
||||
\ }
|
||||
<
|
||||
*clipboard-osc52*
|
||||
Nvim bundles a clipboard provider that allows copying to the system clipboard
|
||||
using OSC 52. OSC 52 is an Operating System Command control sequence that
|
||||
causes the terminal emulator to write to or read from the system clipboard.
|
||||
using OSC 52, an "Operating System Command" control-sequence that causes the
|
||||
terminal emulator to write to or read from the system clipboard.
|
||||
|
||||
When Nvim is running in the |TUI|, it will automatically attempt to determine if
|
||||
the host terminal emulator supports OSC 52. If it does, then Nvim will use OSC
|
||||
52 for copying and pasting if no other |clipboard-tool| is found and when
|
||||
'clipboard' is unset. NOTE: Using a terminal multiplexer (e.g. tmux) may
|
||||
inhibit automatic OSC 52 support detection.
|
||||
When Nvim is running in the |TUI|, it automatically detects host terminal
|
||||
support for OSC 52. If successful, then Nvim will use OSC 52 for copying and
|
||||
pasting if no other |clipboard-tool| is found and when 'clipboard' is unset.
|
||||
NOTE: Using a terminal multiplexer (e.g. tmux) may inhibit automatic OSC 52
|
||||
support detection.
|
||||
|
||||
*g:termfeatures*
|
||||
To disable the automatic detection, set the "osc52" key of |g:termfeatures| to
|
||||
|v:false| in the |config| file. Example: >lua
|
||||
false early in your |config|. Example: >lua
|
||||
local termfeatures = vim.g.termfeatures or {}
|
||||
termfeatures.osc52 = false
|
||||
vim.g.termfeatures = termfeatures
|
||||
<
|
||||
To force Nvim to always use the OSC 52 provider you can use the following
|
||||
|g:clipboard| definition: >lua
|
||||
To force Nvim to use the OSC 52 provider you can set |g:clipboard|: >lua
|
||||
|
||||
vim.g.clipboard = 'osc52'
|
||||
|
||||
@@ -292,7 +299,7 @@ Which is equivalent to: >lua
|
||||
},
|
||||
}
|
||||
<
|
||||
Note that not all terminal emulators support reading from the system clipboard
|
||||
Note: not all terminal emulators support reading from the system clipboard
|
||||
(and even for those that do, users should be aware of the security
|
||||
implications), so using OSC 52 for pasting may not be possible (and not
|
||||
necessary, because you can |paste| instead using your system paste function).
|
||||
|
@@ -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`.
|
||||
|
@@ -25,9 +25,9 @@ Table of contents: |usr_toc.txt|
|
||||
==============================================================================
|
||||
*02.1* Running Vim for the First Time
|
||||
|
||||
To start Vim, enter this command: >
|
||||
To start Nvim, enter this command: >
|
||||
|
||||
gvim file.txt
|
||||
nvim file.txt
|
||||
|
||||
On Unix you can type this at any command prompt. If you are running Microsoft
|
||||
Windows, open a Command Prompt and enter the command. In either case, Vim
|
||||
@@ -50,20 +50,6 @@ screen, a message line indicates the file is named file.txt and shows that you
|
||||
are creating a new file. The message information is temporary and other
|
||||
information overwrites it.
|
||||
|
||||
|
||||
THE VIM COMMAND
|
||||
|
||||
The gvim command causes the editor to create a new window for editing. If you
|
||||
use this command: >
|
||||
|
||||
vim file.txt
|
||||
|
||||
the editing occurs inside your command window. In other words, if you are
|
||||
running inside an xterm, the editor uses your xterm window. If you are using
|
||||
the command prompt under Microsoft Windows, the editing occurs inside this
|
||||
window. The text in the window will look the same for both versions, but with
|
||||
gvim you have extra features, like a menu bar. More about that later.
|
||||
|
||||
==============================================================================
|
||||
*02.2* Inserting text
|
||||
|
||||
@@ -580,7 +566,7 @@ Summary: *help-summary* >
|
||||
:help quote:
|
||||
|
||||
13) Vim Script is available at >
|
||||
:help eval.txt
|
||||
:help vimeval.txt
|
||||
< Certain aspects of the language are available at :h expr-X where "X" is a
|
||||
single letter. E.g. >
|
||||
:help expr-!
|
||||
@@ -660,10 +646,13 @@ Summary: *help-summary* >
|
||||
command switch of Vim use: >
|
||||
:help -f
|
||||
|
||||
24) Optional features always start with "+". To find out about the
|
||||
conceal feature use: >
|
||||
:help +conceal
|
||||
|
||||
24) Lua language and Nvim's Lua standard library are available at >vim
|
||||
:help lua.txt
|
||||
< Guide to using Lua in Nvim is available at >vim
|
||||
:help lua-guide.txt
|
||||
< Lua 5.1 reference manual is available at >vim
|
||||
:help luaref.txt
|
||||
<
|
||||
25) Documentation for included filetype specific functionality is usually
|
||||
available in the form ft-<filetype>-<functionality>. So >
|
||||
:help ft-c-syntax
|
||||
|
@@ -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|.
|
||||
|
||||
@@ -110,7 +110,7 @@ append({lnum}, {text}) *append()*
|
||||
<
|
||||
|
||||
Parameters: ~
|
||||
• {lnum} (`integer`)
|
||||
• {lnum} (`integer|string`)
|
||||
• {text} (`string|string[]`)
|
||||
|
||||
Return: ~
|
||||
@@ -1047,7 +1047,7 @@ cindent({lnum}) *cindent()*
|
||||
To get or set indent of lines in a string, see |vim.text.indent()|.
|
||||
|
||||
Parameters: ~
|
||||
• {lnum} (`integer`)
|
||||
• {lnum} (`integer|string`)
|
||||
|
||||
Return: ~
|
||||
(`integer`)
|
||||
@@ -1637,7 +1637,7 @@ diff_filler({lnum}) *diff_filler()*
|
||||
Returns 0 if the current window is not in diff mode.
|
||||
|
||||
Parameters: ~
|
||||
• {lnum} (`integer`)
|
||||
• {lnum} (`integer|string`)
|
||||
|
||||
Return: ~
|
||||
(`integer`)
|
||||
@@ -1654,7 +1654,7 @@ diff_hlID({lnum}, {col}) *diff_hlID()*
|
||||
syntax information about the highlighting.
|
||||
|
||||
Parameters: ~
|
||||
• {lnum} (`integer`)
|
||||
• {lnum} (`integer|string`)
|
||||
• {col} (`integer`)
|
||||
|
||||
Return: ~
|
||||
@@ -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
|
||||
@@ -2563,7 +2564,7 @@ foldclosed({lnum}) *foldclosed()*
|
||||
line, "'m" mark m, etc.
|
||||
|
||||
Parameters: ~
|
||||
• {lnum} (`integer`)
|
||||
• {lnum} (`integer|string`)
|
||||
|
||||
Return: ~
|
||||
(`integer`)
|
||||
@@ -2576,7 +2577,7 @@ foldclosedend({lnum}) *foldclosedend()*
|
||||
line, "'m" mark m, etc.
|
||||
|
||||
Parameters: ~
|
||||
• {lnum} (`integer`)
|
||||
• {lnum} (`integer|string`)
|
||||
|
||||
Return: ~
|
||||
(`integer`)
|
||||
@@ -2594,7 +2595,7 @@ foldlevel({lnum}) *foldlevel()*
|
||||
line, "'m" mark m, etc.
|
||||
|
||||
Parameters: ~
|
||||
• {lnum} (`integer`)
|
||||
• {lnum} (`integer|string`)
|
||||
|
||||
Return: ~
|
||||
(`integer`)
|
||||
@@ -2629,7 +2630,7 @@ foldtextresult({lnum}) *foldtextresult()*
|
||||
Useful when exporting folded text, e.g., to HTML.
|
||||
|
||||
Parameters: ~
|
||||
• {lnum} (`integer`)
|
||||
• {lnum} (`integer|string`)
|
||||
|
||||
Return: ~
|
||||
(`string`)
|
||||
@@ -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>
|
||||
@@ -5706,7 +5711,7 @@ line2byte({lnum}) *line2byte()*
|
||||
Also see |byte2line()|, |go| and |:goto|.
|
||||
|
||||
Parameters: ~
|
||||
• {lnum} (`integer`)
|
||||
• {lnum} (`integer|string`)
|
||||
|
||||
Return: ~
|
||||
(`integer`)
|
||||
@@ -5719,7 +5724,7 @@ lispindent({lnum}) *lispindent()*
|
||||
When {lnum} is invalid, -1 is returned.
|
||||
|
||||
Parameters: ~
|
||||
• {lnum} (`integer`)
|
||||
• {lnum} (`integer|string`)
|
||||
|
||||
Return: ~
|
||||
(`integer`)
|
||||
@@ -6090,7 +6095,7 @@ mapset({dict})
|
||||
<
|
||||
|
||||
Parameters: ~
|
||||
• {dict} (`boolean`)
|
||||
• {dict} (`table<string,any>`)
|
||||
|
||||
Return: ~
|
||||
(`any`)
|
||||
@@ -6990,7 +6995,7 @@ nextnonblank({lnum}) *nextnonblank()*
|
||||
See also |prevnonblank()|.
|
||||
|
||||
Parameters: ~
|
||||
• {lnum} (`integer`)
|
||||
• {lnum} (`integer|string`)
|
||||
|
||||
Return: ~
|
||||
(`integer`)
|
||||
@@ -7124,7 +7129,7 @@ prevnonblank({lnum}) *prevnonblank()*
|
||||
Also see |nextnonblank()|.
|
||||
|
||||
Parameters: ~
|
||||
• {lnum} (`integer`)
|
||||
• {lnum} (`integer|string`)
|
||||
|
||||
Return: ~
|
||||
(`integer`)
|
||||
@@ -7392,7 +7397,8 @@ printf({fmt}, {expr1} ...) *printf()*
|
||||
< 1.41
|
||||
|
||||
You will get an overflow error |E1510|, when the field-width
|
||||
or precision will result in a string longer than 6400 chars.
|
||||
or precision will result in a string longer than 1 MB
|
||||
(1024*1024 = 1048576) chars.
|
||||
|
||||
*E1500*
|
||||
You cannot mix positional and non-positional arguments: >vim
|
||||
@@ -8937,7 +8943,7 @@ setline({lnum}, {text}) *setline()*
|
||||
< Note: The '[ and '] marks are not set.
|
||||
|
||||
Parameters: ~
|
||||
• {lnum} (`integer`)
|
||||
• {lnum} (`integer|string`)
|
||||
• {text} (`any`)
|
||||
|
||||
Return: ~
|
||||
@@ -10851,7 +10857,7 @@ synID({lnum}, {col}, {trans}) *synID()*
|
||||
<
|
||||
|
||||
Parameters: ~
|
||||
• {lnum} (`integer`)
|
||||
• {lnum} (`integer|string`)
|
||||
• {col} (`integer`)
|
||||
• {trans} (`0|1`)
|
||||
|
||||
@@ -10956,7 +10962,7 @@ synconcealed({lnum}, {col}) *synconcealed()*
|
||||
mechanisms |syntax-vs-match|.
|
||||
|
||||
Parameters: ~
|
||||
• {lnum} (`integer`)
|
||||
• {lnum} (`integer|string`)
|
||||
• {col} (`integer`)
|
||||
|
||||
Return: ~
|
||||
@@ -10982,7 +10988,7 @@ synstack({lnum}, {col}) *synstack()*
|
||||
valid positions.
|
||||
|
||||
Parameters: ~
|
||||
• {lnum} (`integer`)
|
||||
• {lnum} (`integer|string`)
|
||||
• {col} (`integer`)
|
||||
|
||||
Return: ~
|
||||
@@ -11972,14 +11978,13 @@ windowsversion() *windowsversion()*
|
||||
(`string`)
|
||||
|
||||
winheight({nr}) *winheight()*
|
||||
The result is a Number, which is the height of window {nr}.
|
||||
{nr} can be the window number or the |window-ID|.
|
||||
When {nr} is zero, the height of the current window is
|
||||
returned. When window {nr} doesn't exist, -1 is returned.
|
||||
An existing window always has a height of zero or more.
|
||||
This excludes any window toolbar line.
|
||||
Gets the height of |window-ID| {nr} (zero for "current
|
||||
window"), excluding any 'winbar' and 'statusline'. Returns -1
|
||||
if window {nr} doesn't exist. An existing window always has
|
||||
a height of zero or more.
|
||||
|
||||
Examples: >vim
|
||||
echo "The current window has " .. winheight(0) .. " lines."
|
||||
echo "Current window has " .. winheight(0) .. " lines."
|
||||
<
|
||||
|
||||
Parameters: ~
|
||||
@@ -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
|
||||
@@ -12146,18 +12151,21 @@ winsaveview() *winsaveview()*
|
||||
(`vim.fn.winsaveview.ret`)
|
||||
|
||||
winwidth({nr}) *winwidth()*
|
||||
The result is a Number, which is the width of window {nr}.
|
||||
{nr} can be the window number or the |window-ID|.
|
||||
When {nr} is zero, the width of the current window is
|
||||
returned. When window {nr} doesn't exist, -1 is returned.
|
||||
An existing window always has a width of zero or more.
|
||||
Examples: >vim
|
||||
echo "The current window has " .. winwidth(0) .. " columns."
|
||||
Gets the width of |window-ID| {nr} (zero for "current
|
||||
window"), including columns (|sign-column|, 'statuscolumn',
|
||||
etc.). Returns -1 if window {nr} doesn't exist. An existing
|
||||
window always has a width of zero or more.
|
||||
|
||||
Example: >vim
|
||||
echo "Current window has " .. winwidth(0) .. " columns."
|
||||
if winwidth(0) <= 50
|
||||
50 wincmd |
|
||||
endif
|
||||
< For getting the terminal or screen size, see the 'columns'
|
||||
option.
|
||||
<
|
||||
To get the buffer "viewport", use |getwininfo()|: >vim
|
||||
:echo getwininfo(win_getid())[0].width - getwininfo(win_getid())[0].textoff
|
||||
<
|
||||
To get the Nvim screen size, see the 'columns' option.
|
||||
|
||||
Parameters: ~
|
||||
• {nr} (`integer`)
|
@@ -69,8 +69,9 @@ If a window is focusable, it is part of the "navigation stack", that is,
|
||||
editor commands such as :windo, |CTRL-W|, etc., will consider the window as
|
||||
one that can be made the "current window". A non-focusable window will be
|
||||
skipped by such commands (though it can be explicitly focused by
|
||||
|nvim_set_current_win()|). Non-focusable windows are not listed by |:tabs|, and
|
||||
are not counted by the default 'tabline'.
|
||||
|nvim_set_current_win()|). Non-focusable windows are not listed by |:tabs|,
|
||||
or counted by the default 'tabline'. Their buffer content is not included
|
||||
in 'complete' "w" completion.
|
||||
|
||||
Windows (especially floating windows) can have many other |api-win_config|
|
||||
properties such as "hide" and "fixed" which also affect behavior.
|
||||
@@ -438,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.
|
||||
@@ -1272,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 [!].
|
||||
@@ -1284,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.
|
||||
@@ -1304,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|.
|
||||
@@ -1322,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')
|
@@ -3,6 +3,7 @@
|
||||
" Maintainer: Romain Lafourcade <romainlafourcade@gmail.com>
|
||||
" Last Change: 2024 Apr 21
|
||||
" 2024 May 24 by Riley Bruins <ribru17@gmail.com> ('commentstring')
|
||||
" 2025 Aug 29 by Vim project, add try/catch around json_decode(), #18141
|
||||
|
||||
if exists("b:did_ftplugin")
|
||||
finish
|
||||
@@ -52,13 +53,19 @@ function! s:CollectPathsFromConfig() abort
|
||||
endif
|
||||
endif
|
||||
|
||||
let paths_from_config = config_json
|
||||
try
|
||||
let paths_from_config = config_json
|
||||
\ ->readfile()
|
||||
\ ->filter({ _, val -> val =~ '^\s*[\[\]{}"0-9]' })
|
||||
\ ->join()
|
||||
\ ->json_decode()
|
||||
\ ->get('compilerOptions', {})
|
||||
\ ->get('paths', {})
|
||||
catch /^Vim\%((\a\+)\)\=:E491:/ " invalid json
|
||||
let paths_from_config = {}
|
||||
catch /^Vim\%((\a\+)\)\=:E474:/ " invalid json in Nvim
|
||||
let paths_from_config = {}
|
||||
endtry
|
||||
|
||||
if !empty(paths_from_config)
|
||||
let b:astro_paths = paths_from_config
|
||||
|
@@ -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()
|
||||
|
@@ -1,7 +1,8 @@
|
||||
" Vim filetype plugin file
|
||||
" Language: gpg(1) configuration file
|
||||
" Maintainer: This runtime file is looking for a new maintainer.
|
||||
" Previous Maintainer: Nikolai Weibull <now@bitwi.se>
|
||||
" Latest Revision: 2024-09-19 (simplify keywordprg #15696)
|
||||
" Latest Revision: 2025-07-22 (use :hor term #17822)
|
||||
|
||||
if exists("b:did_ftplugin")
|
||||
finish
|
||||
@@ -17,7 +18,7 @@ setlocal comments=:# commentstring=#\ %s formatoptions-=t formatoptions+=croql
|
||||
|
||||
if has('unix') && executable('less') && exists(':terminal') == 2
|
||||
command -buffer -nargs=1 GpgKeywordPrg
|
||||
\ silent exe ':term ' . 'env LESS= MANPAGER="less --pattern=''' . escape('^\s+--' . <q-args> . '\b', '\') . ''' --hilite-search" man ' . 'gpg'
|
||||
\ silent exe ':hor term ' . 'env LESS= MANPAGER="less --pattern=''' . escape('^\s+--' . <q-args> . '\b', '\') . ''' --hilite-search" man ' . 'gpg'
|
||||
setlocal iskeyword+=-
|
||||
setlocal keywordprg=:GpgKeywordPrg
|
||||
let b:undo_ftplugin .= '| setlocal keywordprg< iskeyword< | sil! delc -buffer GpgKeywordPrg'
|
||||
|
@@ -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:
|
||||
|
@@ -2,7 +2,7 @@
|
||||
" Language: modules.conf(5) configuration file
|
||||
" Maintainer: This runtime file is looking for a new maintainer.
|
||||
" Previous Maintainer: Nikolai Weibull <now@bitwi.se>
|
||||
" Latest Revision: 2024-09-20 (remove erroneous endif)
|
||||
" Latest Revision: 2025-07-22 (use :hor term #17822)
|
||||
|
||||
if exists("b:did_ftplugin")
|
||||
finish
|
||||
@@ -19,7 +19,7 @@ setlocal formatoptions-=t formatoptions+=croql
|
||||
|
||||
if has('unix') && executable('less') && exists(':terminal') == 2
|
||||
command -buffer -nargs=1 ModconfKeywordPrg
|
||||
\ silent exe ':term ' . 'env LESS= MANPAGER="less --pattern=''' . escape('^\s{,8}' . <q-args> . '\b', '\') . ''' --hilite-search" man ' . 'modprobe.d'
|
||||
\ silent exe ':hor term ' . 'env LESS= MANPAGER="less --pattern=''' . escape('^\s{,8}' . <q-args> . '\b', '\') . ''' --hilite-search" man ' . 'modprobe.d'
|
||||
setlocal iskeyword+=-
|
||||
setlocal keywordprg=:ModconfKeywordPrg
|
||||
let b:undo_ftplugin .= '| setlocal keywordprg< iskeyword< | sil! delc -buffer ModconfKeywordPrg'
|
||||
|
@@ -1,7 +1,8 @@
|
||||
" Vim filetype plugin file
|
||||
" Language: mutt RC File
|
||||
" Maintainer: This runtime file is looking for a new maintainer.
|
||||
" Previous Maintainer: Nikolai Weibull <now@bitwi.se>
|
||||
" Latest Revision: 2024-09-19 (simplify keywordprg #15696)
|
||||
" Latest Revision: 2025-07-22 (use :hor term #17822)
|
||||
|
||||
if exists("b:did_ftplugin")
|
||||
finish
|
||||
@@ -20,7 +21,7 @@ let &l:include = '^\s*source\>'
|
||||
|
||||
if has('unix') && executable('less') && exists(':terminal') == 2
|
||||
command -buffer -nargs=1 MuttrcKeywordPrg
|
||||
\ silent exe 'term ' . 'env LESS= MANPAGER="less --pattern=''' . escape('^\s+' . <q-args> . '\b', '\') . ''' --hilite-search" man ' . 'muttrc'
|
||||
\ silent exe 'hor term ' . 'env LESS= MANPAGER="less --pattern=''' . escape('^\s+' . <q-args> . '\b', '\') . ''' --hilite-search" man ' . 'muttrc'
|
||||
setlocal iskeyword+=-
|
||||
setlocal keywordprg=:MuttrcKeywordPrg
|
||||
let b:undo_ftplugin .= '| setlocal keywordprg< iskeyword< | sil! delc -buffer MuttrcKeywordPrg'
|
||||
|
@@ -5,6 +5,7 @@
|
||||
" 2024 Jan 14 by Vim Project (browsefilter)
|
||||
" 2024 May 23 by Riley Bruins <ribru17@gmail.com> ('commentstring')
|
||||
" 2024 Sep 19 by Konfekt (simplify keywordprg #15696)
|
||||
" 2025 Jul 22 by phanium (use :hor term #17822)
|
||||
|
||||
" Only do this when not done yet for this buffer
|
||||
if exists("b:did_ftplugin") | finish | endif
|
||||
@@ -51,7 +52,7 @@ endif
|
||||
|
||||
if exists('s:pwsh_cmd')
|
||||
if exists(':terminal') == 2
|
||||
command! -buffer -nargs=1 GetHelp silent exe 'term ' . s:pwsh_cmd . ' -NoLogo -NoProfile -NonInteractive -ExecutionPolicy RemoteSigned -Command Get-Help -Full "<args>"' . (executable('less') ? ' | less' : '')
|
||||
command! -buffer -nargs=1 GetHelp silent exe 'hor term ' . s:pwsh_cmd . ' -NoLogo -NoProfile -NonInteractive -ExecutionPolicy RemoteSigned -Command Get-Help -Full "<args>"' . (executable('less') ? ' | less' : '')
|
||||
else
|
||||
command! -buffer -nargs=1 GetHelp echo system(s:pwsh_cmd . ' -NoLogo -NoProfile -NonInteractive -ExecutionPolicy RemoteSigned -Command Get-Help -Full <args>')
|
||||
endif
|
||||
|
@@ -3,6 +3,7 @@
|
||||
" Maintainer: Doug Kearns <dougkearns@gmail.com>
|
||||
" Previous Maintainer: Nikolai Weibull <now@bitwi.se>
|
||||
" Last Change: 2024 Sep 19 (simplify keywordprg #15696)
|
||||
" 2024 Jul 22 by Vim project (use :hor term #17822)
|
||||
|
||||
if exists("b:did_ftplugin")
|
||||
finish
|
||||
@@ -36,7 +37,7 @@ endif
|
||||
|
||||
if has('unix') && executable('less') && exists(':terminal') == 2
|
||||
command -buffer -nargs=1 ReadlineKeywordPrg
|
||||
\ silent exe 'term ' . 'env LESS= MANPAGER="less --pattern=''' . escape('^\s+' . <q-args> . '\b', '\') . ''' --hilite-search" man ' . '3 readline'
|
||||
\ silent exe 'hor term ' . 'env LESS= MANPAGER="less --pattern=''' . escape('^\s+' . <q-args> . '\b', '\') . ''' --hilite-search" man ' . '3 readline'
|
||||
setlocal iskeyword+=-
|
||||
setlocal keywordprg=:ReadlineKeywordPrg
|
||||
let b:undo_ftplugin .= '| setlocal keywordprg< iskeyword< | sil! delc -buffer ReadlineKeywordPrg'
|
||||
|
@@ -7,6 +7,7 @@
|
||||
" Last Change: 2024 Sep 19 by Vim Project (compiler shellcheck)
|
||||
" 2024 Dec 29 by Vim Project (improve setting shellcheck compiler)
|
||||
" 2025 Mar 09 by Vim Project (set b:match_skip)
|
||||
" 2025 Jul 22 by phanium (use :hor term #17822)
|
||||
|
||||
if exists("b:did_ftplugin")
|
||||
finish
|
||||
@@ -53,7 +54,7 @@ let s:is_kornshell = get(b:, "is_kornshell", get(g:, "is_kornshell", 0))
|
||||
|
||||
if s:is_bash
|
||||
if exists(':terminal') == 2
|
||||
command! -buffer -nargs=1 ShKeywordPrg silent exe ':term bash -c "help "<args>" 2>/dev/null || man "<args>""'
|
||||
command! -buffer -nargs=1 ShKeywordPrg silent exe ':hor term bash -c "help "<args>" 2>/dev/null || man "<args>""'
|
||||
else
|
||||
command! -buffer -nargs=1 ShKeywordPrg echo system('bash -c "help <args>" 2>/dev/null || MANPAGER= man "<args>"')
|
||||
endif
|
||||
|
@@ -2,7 +2,7 @@
|
||||
" Language: OpenSSH client configuration file
|
||||
" Maintainer: This runtime file is looking for a new maintainer.
|
||||
" Previous Maintainer: Nikolai Weibull <now@bitwi.se>
|
||||
" Latest Revision: 2024-09-19 (simplify keywordprg #15696)
|
||||
" Latest Revision: 2025-07-22 (use :hor term #17822)
|
||||
|
||||
if exists("b:did_ftplugin")
|
||||
finish
|
||||
@@ -17,7 +17,7 @@ let b:undo_ftplugin = 'setlocal com< cms< fo<'
|
||||
|
||||
if has('unix') && executable('less') && exists(':terminal') == 2
|
||||
command -buffer -nargs=1 SshconfigKeywordPrg
|
||||
\ silent exe 'term ' . 'env LESS= MANPAGER="less --pattern=''' . escape('^\s+' . <q-args> . '$', '\') . ''' --hilite-search" man ' . 'ssh_config'
|
||||
\ silent exe 'hor term ' . 'env LESS= MANPAGER="less --pattern=''' . escape('^\s+' . <q-args> . '$', '\') . ''' --hilite-search" man ' . 'ssh_config'
|
||||
setlocal iskeyword+=-
|
||||
setlocal keywordprg=:SshconfigKeywordPrg
|
||||
let b:undo_ftplugin .= '| setlocal keywordprg< iskeyword< | sil! delc -buffer SshconfigKeywordPrg'
|
||||
|
@@ -2,7 +2,7 @@
|
||||
" Language: sudoers(5) configuration files
|
||||
" Maintainer: This runtime file is looking for a new maintainer.
|
||||
" Previous Maintainer: Nikolai Weibull <now@bitwi.se>
|
||||
" Latest Revision: 2024-09-19 (simplify keywordprg #15696)
|
||||
" Latest Revision: 2025-07-22 (use :hor term #17822)
|
||||
|
||||
if exists("b:did_ftplugin")
|
||||
finish
|
||||
@@ -18,7 +18,7 @@ setlocal comments=:# commentstring=#\ %s formatoptions-=t formatoptions+=croql
|
||||
|
||||
if has('unix') && executable('less') && exists(':terminal') == 2
|
||||
command -buffer -nargs=1 SudoersKeywordPrg
|
||||
\ silent exe ':term ' . 'env LESS= MANPAGER="less --pattern=''' . escape('\b' . <q-args> . '\b', '\') . ''' --hilite-search" man ' . 'sudoers'
|
||||
\ silent exe ':hor term ' . 'env LESS= MANPAGER="less --pattern=''' . escape('\b' . <q-args> . '\b', '\') . ''' --hilite-search" man ' . 'sudoers'
|
||||
setlocal iskeyword+=-
|
||||
setlocal keywordprg=:SudoersKeywordPrg
|
||||
let b:undo_ftplugin .= '| setlocal keywordprg< iskeyword< | sil! delc -buffer SudoersKeywordPrg'
|
||||
|
@@ -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
|
||||
|
@@ -2,7 +2,7 @@
|
||||
" Language: udev(8) rules file
|
||||
" Maintainer: This runtime file is looking for a new maintainer.
|
||||
" Previous Maintainer: Nikolai Weibull <now@bitwi.se>
|
||||
" Latest Revision: 2024-09-19 (simplify keywordprg #15696)
|
||||
" Latest Revision: 2025-07-22 (use :hor term #17822)
|
||||
|
||||
if exists("b:did_ftplugin")
|
||||
finish
|
||||
@@ -18,7 +18,7 @@ setlocal comments=:# commentstring=#\ %s formatoptions-=t formatoptions+=croql
|
||||
|
||||
if has('unix') && executable('less') && exists(':terminal') == 2
|
||||
command -buffer -nargs=1 UdevrulesKeywordPrg
|
||||
\ silent exe ':term ' . 'env LESS= MANPAGER="less --pattern=''' . escape('^\s{,8}' . <q-args> . '\b', '\') . ''' --hilite-search" man ' . 'udev'
|
||||
\ silent exe ':hor term ' . 'env LESS= MANPAGER="less --pattern=''' . escape('^\s{,8}' . <q-args> . '\b', '\') . ''' --hilite-search" man ' . 'udev'
|
||||
setlocal iskeyword+=-
|
||||
setlocal keywordprg=:UdevrulesKeywordPrg
|
||||
let b:undo_ftplugin .= '| setlocal keywordprg< iskeyword< | sil! delc -buffer UdevrulesKeywordPrg'
|
||||
|
@@ -5,6 +5,8 @@
|
||||
" Latest Revision: 2024 Sep 19
|
||||
" License: Vim (see :h license)
|
||||
" Repository: https://github.com/chrisbra/vim-zsh
|
||||
" Last Change:
|
||||
" 2025 Jul 23 by Vim Project (use :hor term #17822)
|
||||
|
||||
if exists("b:did_ftplugin")
|
||||
finish
|
||||
@@ -20,7 +22,7 @@ let b:undo_ftplugin = "setl com< cms< fo< "
|
||||
|
||||
if executable('zsh') && &shell !~# '/\%(nologin\|false\)$'
|
||||
if exists(':terminal') == 2
|
||||
command! -buffer -nargs=1 ZshKeywordPrg silent exe ':term zsh -c "autoload -Uz run-help; run-help <args>"'
|
||||
command! -buffer -nargs=1 ZshKeywordPrg silent exe ':hor term zsh -c "autoload -Uz run-help; run-help <args>"'
|
||||
else
|
||||
command! -buffer -nargs=1 ZshKeywordPrg echo system('MANPAGER= zsh -c "autoload -Uz run-help; run-help <args> 2>/dev/null"')
|
||||
endif
|
||||
|
@@ -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
|
||||
|
@@ -8,6 +8,10 @@ local M = {}
|
||||
--- @param env? table<string,string|number>
|
||||
--- @return string
|
||||
local function system(cmd, silent, env)
|
||||
if vim.fn.executable(cmd[1]) == 0 then
|
||||
error(string.format('executable not found: "%s"', cmd[1]), 0)
|
||||
end
|
||||
|
||||
local r = vim.system(cmd, { env = env, timeout = 10000 }):wait()
|
||||
|
||||
if not silent then
|
||||
@@ -577,7 +581,10 @@ function M.man_complete(arg_lead, cmd_line)
|
||||
return {}
|
||||
end
|
||||
|
||||
local pages = get_paths(name, sect)
|
||||
local ok, pages = pcall(get_paths, name, sect)
|
||||
if not ok then
|
||||
return nil
|
||||
end
|
||||
|
||||
-- We check for duplicates in case the same manpage in different languages
|
||||
-- was found.
|
||||
@@ -803,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
|
||||
|
86
runtime/lua/nvim/tutor.lua
Normal file
86
runtime/lua/nvim/tutor.lua
Normal file
@@ -0,0 +1,86 @@
|
||||
---@class nvim.TutorMetadata
|
||||
---@field expect table<string, string|-1>
|
||||
|
||||
---@alias nvim.TutorExtmarks table<string, string>
|
||||
|
||||
---@type nvim.TutorExtmarks?
|
||||
vim.b.tutor_extmarks = vim.b.tutor_extmarks
|
||||
|
||||
---@type nvim.TutorMetadata?
|
||||
vim.b.tutor_metadata = vim.b.tutor_metadata
|
||||
|
||||
local sign_text_correct = '✓'
|
||||
local sign_text_incorrect = '✗'
|
||||
local tutor_mark_ns = vim.api.nvim_create_namespace('nvim.tutor.mark')
|
||||
local tutor_hl_ns = vim.api.nvim_create_namespace('nvim.tutor.hl')
|
||||
|
||||
local M = {}
|
||||
|
||||
---@param line integer 1-based
|
||||
local function check_line(line)
|
||||
if vim.b.tutor_metadata and vim.b.tutor_metadata.expect and vim.b.tutor_extmarks then
|
||||
local ctext = vim.fn.getline(line)
|
||||
|
||||
---@type vim.api.keyset.get_extmark_item[]
|
||||
local extmarks = vim
|
||||
.iter(vim.api.nvim_buf_get_extmarks(
|
||||
0,
|
||||
tutor_mark_ns,
|
||||
{ line - 1, 0 },
|
||||
{ line - 1, -1 }, -- the extmark can move to col > 0 if users insert text there
|
||||
{ details = true }
|
||||
))
|
||||
:filter(function(extmark)
|
||||
return not extmark[4].invalid
|
||||
end)
|
||||
:totable()
|
||||
|
||||
for _, extmark in ipairs(extmarks) do
|
||||
local mark_id = extmark[1]
|
||||
local expct = vim.b.tutor_extmarks[tostring(mark_id)]
|
||||
local expect = vim.b.tutor_metadata.expect[expct]
|
||||
local is_correct = expect == -1 or ctext == expect
|
||||
|
||||
vim.api.nvim_buf_set_extmark(0, tutor_mark_ns, line - 1, 0, {
|
||||
id = mark_id,
|
||||
sign_text = is_correct and sign_text_correct or sign_text_incorrect,
|
||||
sign_hl_group = is_correct and 'tutorOK' or 'tutorX',
|
||||
invalidate = true,
|
||||
})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function M.apply_marks()
|
||||
vim.cmd [[hi! link tutorExpect Special]]
|
||||
if vim.b.tutor_metadata and vim.b.tutor_metadata.expect then
|
||||
vim.b.tutor_extmarks = {}
|
||||
for expct, _ in pairs(vim.b.tutor_metadata.expect) do
|
||||
---@diagnostic disable-next-line: assign-type-mismatch
|
||||
local lnum = tonumber(expct) ---@type integer
|
||||
vim.api.nvim_buf_set_extmark(0, tutor_hl_ns, lnum - 1, 0, {
|
||||
line_hl_group = 'tutorExpect',
|
||||
invalidate = true,
|
||||
})
|
||||
|
||||
local mark_id = vim.api.nvim_buf_set_extmark(0, tutor_mark_ns, lnum - 1, 0, {})
|
||||
|
||||
-- Cannot edit field of a Vimscript dictionary from Lua directly, see `:h lua-vim-variables`
|
||||
---@type nvim.TutorExtmarks
|
||||
local tutor_extmarks = vim.b.tutor_extmarks
|
||||
tutor_extmarks[tostring(mark_id)] = expct
|
||||
vim.b.tutor_extmarks = tutor_extmarks
|
||||
|
||||
check_line(lnum)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function M.apply_marks_on_changed()
|
||||
if vim.b.tutor_metadata and vim.b.tutor_metadata.expect and vim.b.tutor_extmarks then
|
||||
local lnum = vim.fn.line('.')
|
||||
check_line(lnum)
|
||||
end
|
||||
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()' })
|
||||
@@ -622,10 +626,10 @@ do
|
||||
end
|
||||
vim.wo[0][0].winhighlight = winhl .. 'StatusLine:StatusLineTerm,StatusLineNC:StatusLineTermNC'
|
||||
|
||||
vim.keymap.set('n', '[[', function()
|
||||
vim.keymap.set({ 'n', 'x', 'o' }, '[[', function()
|
||||
jump_to_prompt(nvim_terminal_prompt_ns, 0, args.buf, -vim.v.count1)
|
||||
end, { buffer = args.buf, desc = 'Jump [count] shell prompts backward' })
|
||||
vim.keymap.set('n', ']]', function()
|
||||
vim.keymap.set({ 'n', 'x', 'o' }, ']]', function()
|
||||
jump_to_prompt(nvim_terminal_prompt_ns, 0, args.buf, vim.v.count1)
|
||||
end, { buffer = args.buf, desc = 'Jump [count] shell prompts forward' })
|
||||
end,
|
||||
|
@@ -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
|
||||
|
||||
|
@@ -200,7 +200,9 @@ function vim.show_pos(bufnr, row, col, filter)
|
||||
capture,
|
||||
string.format(
|
||||
'priority: %d language: %s',
|
||||
capture.metadata.priority or vim.hl.priorities.treesitter,
|
||||
capture.metadata.priority
|
||||
or (capture.metadata[capture.id] and capture.metadata[capture.id].priority)
|
||||
or vim.hl.priorities.treesitter,
|
||||
capture.lang
|
||||
)
|
||||
)
|
||||
|
19
runtime/lua/vim/_meta/api.lua
generated
19
runtime/lua/vim/_meta/api.lua
generated
@@ -369,8 +369,11 @@ function vim.api.nvim_buf_get_extmark_by_id(buffer, ns_id, id, opts) end
|
||||
--- vim.api.nvim_buf_get_extmarks(0, my_ns, {0,0}, {-1,-1}, {})
|
||||
--- ```
|
||||
---
|
||||
--- If `end` is less than `start`, traversal works backwards. (Useful
|
||||
--- with `limit`, to get the first marks prior to a given position.)
|
||||
--- If `end` is less than `start`, marks are returned in reverse order.
|
||||
--- (Useful with `limit`, to get the first marks prior to a given position.)
|
||||
---
|
||||
--- Note: For a reverse range, `limit` does not actually affect the traversed
|
||||
--- range, just how many marks are returned
|
||||
---
|
||||
--- Note: when using extmark ranges (marks with a end_row/end_col position)
|
||||
--- the `overlap` option might be useful. Otherwise only the start position
|
||||
@@ -939,8 +942,8 @@ function vim.api.nvim_create_augroup(name, opts) end
|
||||
--- - desc (string) optional: description (for documentation and troubleshooting).
|
||||
--- - callback (function|string) optional: Lua function (or Vimscript function name, if
|
||||
--- string) called when the event(s) is triggered. Lua callback can return a truthy
|
||||
--- value (not `false` or `nil`) to delete the autocommand. Receives one argument,
|
||||
--- a table with these keys: [event-args]()
|
||||
--- value (not `false` or `nil`) to delete the autocommand, and receives one argument, a
|
||||
--- table with these keys: [event-args]()
|
||||
--- - id: (number) autocommand id
|
||||
--- - event: (string) name of the triggered event `autocmd-events`
|
||||
--- - group: (number|nil) autocommand group id, if any
|
||||
@@ -1659,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' })
|
||||
--- ```
|
||||
---
|
||||
@@ -1840,7 +1840,8 @@ function vim.api.nvim_open_term(buffer, opts) end
|
||||
--- the call.
|
||||
--- - fixed: If true when anchor is NW or SW, the float window
|
||||
--- would be kept fixed even if the window would be truncated.
|
||||
--- - hide: If true the floating window will be hidden.
|
||||
--- - hide: If true the floating window will be hidden and the cursor will be invisible when
|
||||
--- focused on it.
|
||||
--- - vertical: Split vertically `:vertical`.
|
||||
--- - split: Split direction: "left", "right", "above", "below".
|
||||
--- @return integer # |window-ID|, or 0 on error
|
||||
|
@@ -184,14 +184,14 @@
|
||||
--- @field signs vim.fn.sign[]
|
||||
|
||||
--- @class vim.fn.sign_place.dict
|
||||
--- @field lnum? integer
|
||||
--- @field lnum? integer|string
|
||||
--- @field priority? integer
|
||||
|
||||
--- @class vim.fn.sign_placelist.list.item
|
||||
--- @field buffer integer|string
|
||||
--- @field group? string
|
||||
--- @field id? integer
|
||||
--- @field lnum integer
|
||||
--- @field lnum? integer|string
|
||||
--- @field name string
|
||||
--- @field priority? integer
|
||||
|
||||
@@ -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
|
||||
|
54
runtime/lua/vim/_meta/options.lua
generated
54
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:
|
||||
@@ -7834,14 +7849,15 @@ vim.wo.winbl = vim.wo.winblend
|
||||
|
||||
--- Defines the default border style of floating windows. The default value
|
||||
--- is empty, which is equivalent to "none". Valid values include:
|
||||
--- - "bold": Bold line box.
|
||||
--- - "double": Double-line box.
|
||||
--- - "none": No border.
|
||||
--- - "single": A single line box.
|
||||
--- - "double": A double line box.
|
||||
--- - "rounded": Like "single", but with rounded corners ("╭" etc.).
|
||||
--- - "shadow": Drop shadow effect, by blending with the background.
|
||||
--- - "single": Single-line box.
|
||||
--- - "solid": Adds padding by a single whitespace cell.
|
||||
--- - "shadow": A drop shadow effect by blending with the background.
|
||||
---
|
||||
--- @type ''|'double'|'single'|'shadow'|'rounded'|'solid'|'none'
|
||||
--- @type ''|'double'|'single'|'shadow'|'rounded'|'solid'|'bold'|'none'
|
||||
vim.o.winborder = ""
|
||||
vim.go.winborder = vim.o.winborder
|
||||
|
||||
|
88
runtime/lua/vim/_meta/vimfn.lua
generated
88
runtime/lua/vim/_meta/vimfn.lua
generated
@@ -85,7 +85,7 @@ function vim.fn.api_info() end
|
||||
--- let failed = append(0, ["Chapter 1", "the beginning"])
|
||||
--- <
|
||||
---
|
||||
--- @param lnum integer
|
||||
--- @param lnum integer|string
|
||||
--- @param text string|string[]
|
||||
--- @return 0|1
|
||||
function vim.fn.append(lnum, text) end
|
||||
@@ -907,7 +907,7 @@ function vim.fn.chdir(dir) end
|
||||
---
|
||||
--- To get or set indent of lines in a string, see |vim.text.indent()|.
|
||||
---
|
||||
--- @param lnum integer
|
||||
--- @param lnum integer|string
|
||||
--- @return integer
|
||||
function vim.fn.cindent(lnum) end
|
||||
|
||||
@@ -1244,7 +1244,7 @@ function vim.fn.ctxset(context, index) end
|
||||
--- @return any
|
||||
function vim.fn.ctxsize() end
|
||||
|
||||
--- @param lnum integer
|
||||
--- @param lnum integer|string
|
||||
--- @param col? integer
|
||||
--- @param off? integer
|
||||
--- @return any
|
||||
@@ -1441,7 +1441,7 @@ function vim.fn.did_filetype() end
|
||||
--- line, "'m" mark m, etc.
|
||||
--- Returns 0 if the current window is not in diff mode.
|
||||
---
|
||||
--- @param lnum integer
|
||||
--- @param lnum integer|string
|
||||
--- @return integer
|
||||
function vim.fn.diff_filler(lnum) end
|
||||
|
||||
@@ -1455,7 +1455,7 @@ function vim.fn.diff_filler(lnum) end
|
||||
--- The highlight ID can be used with |synIDattr()| to obtain
|
||||
--- syntax information about the highlighting.
|
||||
---
|
||||
--- @param lnum integer
|
||||
--- @param lnum integer|string
|
||||
--- @param col integer
|
||||
--- @return any
|
||||
function vim.fn.diff_hlID(lnum, col) end
|
||||
@@ -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
|
||||
@@ -2282,7 +2283,7 @@ function vim.fn.fnamemodify(fname, mods) end
|
||||
--- {lnum} is used like with |getline()|. Thus "." is the current
|
||||
--- line, "'m" mark m, etc.
|
||||
---
|
||||
--- @param lnum integer
|
||||
--- @param lnum integer|string
|
||||
--- @return integer
|
||||
function vim.fn.foldclosed(lnum) end
|
||||
|
||||
@@ -2292,7 +2293,7 @@ function vim.fn.foldclosed(lnum) end
|
||||
--- {lnum} is used like with |getline()|. Thus "." is the current
|
||||
--- line, "'m" mark m, etc.
|
||||
---
|
||||
--- @param lnum integer
|
||||
--- @param lnum integer|string
|
||||
--- @return integer
|
||||
function vim.fn.foldclosedend(lnum) end
|
||||
|
||||
@@ -2307,7 +2308,7 @@ function vim.fn.foldclosedend(lnum) end
|
||||
--- {lnum} is used like with |getline()|. Thus "." is the current
|
||||
--- line, "'m" mark m, etc.
|
||||
---
|
||||
--- @param lnum integer
|
||||
--- @param lnum integer|string
|
||||
--- @return integer
|
||||
function vim.fn.foldlevel(lnum) end
|
||||
|
||||
@@ -2338,7 +2339,7 @@ function vim.fn.foldtext() end
|
||||
--- line, "'m" mark m, etc.
|
||||
--- Useful when exporting folded text, e.g., to HTML.
|
||||
---
|
||||
--- @param lnum integer
|
||||
--- @param lnum integer|string
|
||||
--- @return string
|
||||
function vim.fn.foldtextresult(lnum) end
|
||||
|
||||
@@ -3284,7 +3285,7 @@ function vim.fn.getjumplist(winnr, tabnr) end
|
||||
--- @return string
|
||||
function vim.fn.getline(lnum, end_) end
|
||||
|
||||
--- @param lnum integer
|
||||
--- @param lnum integer|string
|
||||
--- @param end_ true|number|string|table
|
||||
--- @return string|string[]
|
||||
function vim.fn.getline(lnum, end_) end
|
||||
@@ -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>
|
||||
@@ -5170,7 +5175,7 @@ function vim.fn.line(expr, winid) end
|
||||
--- |getline()|. When {lnum} is invalid -1 is returned.
|
||||
--- Also see |byte2line()|, |go| and |:goto|.
|
||||
---
|
||||
--- @param lnum integer
|
||||
--- @param lnum integer|string
|
||||
--- @return integer
|
||||
function vim.fn.line2byte(lnum) end
|
||||
|
||||
@@ -5180,7 +5185,7 @@ function vim.fn.line2byte(lnum) end
|
||||
--- relevant. {lnum} is used just like in |getline()|.
|
||||
--- When {lnum} is invalid, -1 is returned.
|
||||
---
|
||||
--- @param lnum integer
|
||||
--- @param lnum integer|string
|
||||
--- @return integer
|
||||
function vim.fn.lispindent(lnum) end
|
||||
|
||||
@@ -5479,7 +5484,7 @@ function vim.fn.mapnew(expr1, expr2) end
|
||||
|
||||
--- @param mode string
|
||||
--- @param abbr? boolean
|
||||
--- @param dict? boolean
|
||||
--- @param dict? table<string,any>
|
||||
--- @return any
|
||||
function vim.fn.mapset(mode, abbr, dict) end
|
||||
|
||||
@@ -5519,7 +5524,7 @@ function vim.fn.mapset(mode, abbr, dict) end
|
||||
--- endfor
|
||||
--- <
|
||||
---
|
||||
--- @param dict boolean
|
||||
--- @param dict table<string,any>
|
||||
--- @return any
|
||||
function vim.fn.mapset(dict) end
|
||||
|
||||
@@ -6352,7 +6357,7 @@ function vim.fn.msgpackparse(data) end
|
||||
--- {lnum} is used like with |getline()|.
|
||||
--- See also |prevnonblank()|.
|
||||
---
|
||||
--- @param lnum integer
|
||||
--- @param lnum integer|string
|
||||
--- @return integer
|
||||
function vim.fn.nextnonblank(lnum) end
|
||||
|
||||
@@ -6451,7 +6456,7 @@ function vim.fn.pow(x, y) end
|
||||
--- {lnum} is used like with |getline()|.
|
||||
--- Also see |nextnonblank()|.
|
||||
---
|
||||
--- @param lnum integer
|
||||
--- @param lnum integer|string
|
||||
--- @return integer
|
||||
function vim.fn.prevnonblank(lnum) end
|
||||
|
||||
@@ -6717,7 +6722,8 @@ function vim.fn.prevnonblank(lnum) end
|
||||
--- < 1.41
|
||||
---
|
||||
--- You will get an overflow error |E1510|, when the field-width
|
||||
--- or precision will result in a string longer than 6400 chars.
|
||||
--- or precision will result in a string longer than 1 MB
|
||||
--- (1024*1024 = 1048576) chars.
|
||||
---
|
||||
--- *E1500*
|
||||
--- You cannot mix positional and non-positional arguments: >vim
|
||||
@@ -8060,7 +8066,7 @@ function vim.fn.setcmdline(str, pos) end
|
||||
--- @return any
|
||||
function vim.fn.setcmdpos(pos) end
|
||||
|
||||
--- @param lnum integer
|
||||
--- @param lnum integer|string
|
||||
--- @param col? integer
|
||||
--- @param off? integer
|
||||
--- @return any
|
||||
@@ -8139,7 +8145,7 @@ function vim.fn.setfperm(fname, mode) end
|
||||
---
|
||||
--- <Note: The '[ and '] marks are not set.
|
||||
---
|
||||
--- @param lnum integer
|
||||
--- @param lnum integer|string
|
||||
--- @param text any
|
||||
--- @return any
|
||||
function vim.fn.setline(lnum, text) end
|
||||
@@ -9895,7 +9901,7 @@ function vim.fn.swapname(buf) end
|
||||
--- echo synIDattr(synID(line("."), col("."), 1), "name")
|
||||
--- <
|
||||
---
|
||||
--- @param lnum integer
|
||||
--- @param lnum integer|string
|
||||
--- @param col integer
|
||||
--- @param trans 0|1
|
||||
--- @return integer
|
||||
@@ -9991,7 +9997,7 @@ function vim.fn.synIDtrans(synID) end
|
||||
--- since syntax and matching highlighting are two different
|
||||
--- mechanisms |syntax-vs-match|.
|
||||
---
|
||||
--- @param lnum integer
|
||||
--- @param lnum integer|string
|
||||
--- @param col integer
|
||||
--- @return [integer, string, integer]
|
||||
function vim.fn.synconcealed(lnum, col) end
|
||||
@@ -10014,7 +10020,7 @@ function vim.fn.synconcealed(lnum, col) end
|
||||
--- character in a line and the first column in an empty line are
|
||||
--- valid positions.
|
||||
---
|
||||
--- @param lnum integer
|
||||
--- @param lnum integer|string
|
||||
--- @param col integer
|
||||
--- @return integer[]
|
||||
function vim.fn.synstack(lnum, col) end
|
||||
@@ -10878,14 +10884,13 @@ function vim.fn.wincol() end
|
||||
--- @return string
|
||||
function vim.fn.windowsversion() end
|
||||
|
||||
--- The result is a Number, which is the height of window {nr}.
|
||||
--- {nr} can be the window number or the |window-ID|.
|
||||
--- When {nr} is zero, the height of the current window is
|
||||
--- returned. When window {nr} doesn't exist, -1 is returned.
|
||||
--- An existing window always has a height of zero or more.
|
||||
--- This excludes any window toolbar line.
|
||||
--- Gets the height of |window-ID| {nr} (zero for "current
|
||||
--- window"), excluding any 'winbar' and 'statusline'. Returns -1
|
||||
--- if window {nr} doesn't exist. An existing window always has
|
||||
--- a height of zero or more.
|
||||
---
|
||||
--- Examples: >vim
|
||||
--- echo "The current window has " .. winheight(0) .. " lines."
|
||||
--- echo "Current window has " .. winheight(0) .. " lines."
|
||||
--- <
|
||||
---
|
||||
--- @param nr integer
|
||||
@@ -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
|
||||
@@ -11037,18 +11042,21 @@ function vim.fn.winrestview(dict) end
|
||||
--- @return vim.fn.winsaveview.ret
|
||||
function vim.fn.winsaveview() end
|
||||
|
||||
--- The result is a Number, which is the width of window {nr}.
|
||||
--- {nr} can be the window number or the |window-ID|.
|
||||
--- When {nr} is zero, the width of the current window is
|
||||
--- returned. When window {nr} doesn't exist, -1 is returned.
|
||||
--- An existing window always has a width of zero or more.
|
||||
--- Examples: >vim
|
||||
--- echo "The current window has " .. winwidth(0) .. " columns."
|
||||
--- Gets the width of |window-ID| {nr} (zero for "current
|
||||
--- window"), including columns (|sign-column|, 'statuscolumn',
|
||||
--- etc.). Returns -1 if window {nr} doesn't exist. An existing
|
||||
--- window always has a width of zero or more.
|
||||
---
|
||||
--- Example: >vim
|
||||
--- echo "Current window has " .. winwidth(0) .. " columns."
|
||||
--- if winwidth(0) <= 50
|
||||
--- 50 wincmd |
|
||||
--- endif
|
||||
--- <For getting the terminal or screen size, see the 'columns'
|
||||
--- option.
|
||||
--- <
|
||||
--- To get the buffer "viewport", use |getwininfo()|: >vim
|
||||
--- :echo getwininfo(win_getid())[0].width - getwininfo(win_getid())[0].textoff
|
||||
--- <
|
||||
--- To get the Nvim screen size, see the 'columns' option.
|
||||
---
|
||||
--- @param nr integer
|
||||
--- @return integer
|
||||
|
@@ -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(pid_or_err)
|
||||
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
|
||||
|
@@ -241,6 +241,10 @@ end
|
||||
|
||||
--- @class vim.diagnostic.Opts.VirtualLines
|
||||
---
|
||||
--- Only show virtual lines for diagnostics matching the given
|
||||
--- severity |diagnostic-severity|
|
||||
--- @field severity? vim.diagnostic.SeverityFilter
|
||||
---
|
||||
--- Only show diagnostics for the current line.
|
||||
--- (default: `false`)
|
||||
--- @field current_line? boolean
|
||||
@@ -252,7 +256,7 @@ end
|
||||
|
||||
--- @class vim.diagnostic.Opts.Signs
|
||||
---
|
||||
--- Only show virtual text for diagnostics matching the given
|
||||
--- Only show signs for diagnostics matching the given
|
||||
--- severity |diagnostic-severity|
|
||||
--- @field severity? vim.diagnostic.SeverityFilter
|
||||
---
|
||||
@@ -1438,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 {}
|
||||
|
@@ -2427,8 +2427,26 @@ local pattern = {
|
||||
['^%.?gtkrc'] = starsetf('gtkrc'),
|
||||
['/doc/.*%.txt$'] = function(_, bufnr)
|
||||
local line = M._getline(bufnr, -1)
|
||||
local ml = line:find('^vim:') or line:find('%svim:')
|
||||
if ml and M._matchregex(line:sub(ml), [[\<\(ft\|filetype\)=help\>]]) then
|
||||
if
|
||||
M._findany(line, {
|
||||
'^vim:ft=help[:%s]',
|
||||
'^vim:ft=help$',
|
||||
'^vim:filetype=help[:%s]',
|
||||
'^vim:filetype=help$',
|
||||
'^vim:.*[:%s]ft=help[:%s]',
|
||||
'^vim:.*[:%s]ft=help$',
|
||||
'^vim:.*[:%s]filetype=help[:%s]',
|
||||
'^vim:.*[:%s]filetype=help$',
|
||||
'%svim:ft=help[:%s]',
|
||||
'%svim:ft=help$',
|
||||
'%svim:filetype=help[:%s]',
|
||||
'%svim:filetype=help$',
|
||||
'%svim:.*[:%s]ft=help[:%s]',
|
||||
'%svim:.*[:%s]ft=help$',
|
||||
'%svim:.*[:%s]filetype=help[:%s]',
|
||||
'%svim:.*[:%s]filetype=help$',
|
||||
})
|
||||
then
|
||||
return 'help'
|
||||
end
|
||||
end,
|
||||
@@ -2587,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)
|
||||
@@ -275,7 +286,7 @@ end
|
||||
---
|
||||
--- @param msg string
|
||||
function M.ok(msg)
|
||||
local input = format_report_message('OK', msg)
|
||||
local input = format_report_message('✅ OK', msg)
|
||||
collect_output(input)
|
||||
end
|
||||
|
||||
@@ -284,8 +295,9 @@ end
|
||||
--- @param msg string
|
||||
--- @param ... string|string[] Optional advice
|
||||
function M.warn(msg, ...)
|
||||
local input = format_report_message('WARNING', msg, ...)
|
||||
local input = format_report_message('⚠️ WARNING', msg, ...)
|
||||
collect_output(input)
|
||||
check_summary['warn'] = check_summary['warn'] + 1
|
||||
end
|
||||
|
||||
--- Reports an error.
|
||||
@@ -293,8 +305,9 @@ end
|
||||
--- @param msg string
|
||||
--- @param ... string|string[] Optional advice
|
||||
function M.error(msg, ...)
|
||||
local input = format_report_message('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),
|
||||
'',
|
||||
}
|
||||
|
||||
@@ -449,14 +484,19 @@ function M._check(mods, plugin_names)
|
||||
vim.print('')
|
||||
|
||||
-- Quit with 'q' inside healthcheck buffers.
|
||||
vim.keymap.set('n', 'q', function()
|
||||
if not pcall(vim.cmd.close) then
|
||||
vim.cmd.bdelete()
|
||||
vim._with({ buf = bufnr }, function()
|
||||
if vim.fn.maparg('q', 'n', false, false) == '' then
|
||||
vim.keymap.set('n', 'q', function()
|
||||
if not pcall(vim.cmd.close) then
|
||||
vim.cmd.bdelete()
|
||||
end
|
||||
end, { buffer = bufnr, silent = true, noremap = true, nowait = true })
|
||||
end
|
||||
end, { buffer = bufnr, silent = true, noremap = true, nowait = true })
|
||||
end)
|
||||
|
||||
-- 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.',
|
||||
@@ -318,9 +318,11 @@ local function check_tmux()
|
||||
'$TERM differs from the tmux `default-terminal` setting. Colors might look wrong.',
|
||||
{ '$TERM may have been set by some rc (.bashrc, .zshrc, ...).' }
|
||||
)
|
||||
elseif not vim.regex([[\v(tmux-256color|screen-256color)]]):match_str(vim.env.TERM) then
|
||||
elseif
|
||||
not vim.regex([[\v(tmux-256color|tmux-direct|screen-256color)]]):match_str(vim.env.TERM)
|
||||
then
|
||||
health.error(
|
||||
'$TERM should be "screen-256color" or "tmux-256color" in tmux. Colors might look wrong.',
|
||||
'$TERM should be "screen-256color", "tmux-256color", or "tmux-direct" in tmux. Colors might look wrong.',
|
||||
{
|
||||
'Set default-terminal in ~/.tmux.conf:\nset-option -g default-terminal "screen-256color"',
|
||||
suggest_faq,
|
||||
|
@@ -17,9 +17,6 @@ M.priorities = {
|
||||
user = 200,
|
||||
}
|
||||
|
||||
local range_timer --- @type uv.uv_timer_t?
|
||||
local range_hl_clear --- @type fun()?
|
||||
|
||||
--- @class vim.hl.range.Opts
|
||||
--- @inlinedoc
|
||||
---
|
||||
@@ -47,6 +44,10 @@ local range_hl_clear --- @type fun()?
|
||||
---@param start integer[]|string Start of region as a (line, column) tuple or string accepted by |getpos()|
|
||||
---@param finish integer[]|string End of region as a (line, column) tuple or string accepted by |getpos()|
|
||||
---@param opts? vim.hl.range.Opts
|
||||
--- @return uv.uv_timer_t? range_timer A timer which manages how much time the
|
||||
--- highlight has left
|
||||
--- @return fun()? range_clear A function which allows clearing the highlight manually.
|
||||
--- nil is returned if timeout is not specified
|
||||
function M.range(bufnr, ns, higroup, start, finish, opts)
|
||||
opts = opts or {}
|
||||
local regtype = opts.regtype or 'v'
|
||||
@@ -108,38 +109,41 @@ function M.range(bufnr, ns, higroup, start, finish, opts)
|
||||
end
|
||||
end
|
||||
|
||||
if range_timer and not range_timer:is_closing() then
|
||||
range_timer:close()
|
||||
assert(range_hl_clear)
|
||||
range_hl_clear()
|
||||
end
|
||||
|
||||
range_hl_clear = function()
|
||||
range_timer = nil
|
||||
range_hl_clear = nil
|
||||
pcall(vim.api.nvim_buf_clear_namespace, bufnr, ns, 0, -1)
|
||||
pcall(vim.api.nvim__ns_set, { wins = {} })
|
||||
end
|
||||
|
||||
local extmarks = {} --- @type integer[]
|
||||
for _, res in ipairs(region) do
|
||||
local start_row = res[1][2] - 1
|
||||
local start_col = res[1][3] - 1
|
||||
local end_row = res[2][2] - 1
|
||||
local end_col = res[2][3]
|
||||
api.nvim_buf_set_extmark(bufnr, ns, start_row, start_col, {
|
||||
hl_group = higroup,
|
||||
end_row = end_row,
|
||||
end_col = end_col,
|
||||
priority = priority,
|
||||
strict = false,
|
||||
})
|
||||
table.insert(
|
||||
extmarks,
|
||||
api.nvim_buf_set_extmark(bufnr, ns, start_row, start_col, {
|
||||
hl_group = higroup,
|
||||
end_row = end_row,
|
||||
end_col = end_col,
|
||||
priority = priority,
|
||||
strict = false,
|
||||
})
|
||||
)
|
||||
end
|
||||
|
||||
local range_hl_clear = function()
|
||||
if not api.nvim_buf_is_valid(bufnr) then
|
||||
return
|
||||
end
|
||||
for _, mark in ipairs(extmarks) do
|
||||
api.nvim_buf_del_extmark(bufnr, ns, mark)
|
||||
end
|
||||
end
|
||||
|
||||
if timeout ~= -1 then
|
||||
range_timer = vim.defer_fn(range_hl_clear, timeout)
|
||||
local range_timer = vim.defer_fn(range_hl_clear, timeout)
|
||||
return range_timer, range_hl_clear
|
||||
end
|
||||
end
|
||||
|
||||
local yank_timer --- @type uv.uv_timer_t?
|
||||
local yank_hl_clear --- @type fun()?
|
||||
local yank_ns = api.nvim_create_namespace('nvim.hlyank')
|
||||
|
||||
--- Highlight the yanked text during a |TextYankPost| event.
|
||||
@@ -179,8 +183,14 @@ function M.on_yank(opts)
|
||||
local bufnr = vim.api.nvim_get_current_buf()
|
||||
local winid = vim.api.nvim_get_current_win()
|
||||
|
||||
if yank_timer and not yank_timer:is_closing() then
|
||||
yank_timer:close()
|
||||
assert(yank_hl_clear)
|
||||
yank_hl_clear()
|
||||
end
|
||||
|
||||
vim.api.nvim__ns_set(yank_ns, { wins = { winid } })
|
||||
M.range(bufnr, yank_ns, higroup, "'[", "']", {
|
||||
yank_timer, yank_hl_clear = M.range(bufnr, yank_ns, higroup, "'[", "']", {
|
||||
regtype = event.regtype,
|
||||
inclusive = true,
|
||||
priority = opts.priority or M.priorities.user,
|
||||
|
@@ -957,6 +957,9 @@ end
|
||||
|
||||
---@private
|
||||
function ArrayIter:last()
|
||||
if self._head >= self._tail then
|
||||
return nil
|
||||
end
|
||||
local inc = self._head < self._tail and 1 or -1
|
||||
local v = self._table[self._tail - inc]
|
||||
self._head = self._tail
|
||||
|
@@ -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.
|
||||
---
|
||||
@@ -362,6 +383,19 @@ local function invalidate_enabled_config(name)
|
||||
end
|
||||
end
|
||||
|
||||
--- @param name any
|
||||
local function validate_config_name(name)
|
||||
validate('name', name, function(value)
|
||||
if type(value) ~= 'string' then
|
||||
return false
|
||||
end
|
||||
if value ~= '*' and value:match('%*') then
|
||||
return false, 'LSP config name cannot contain wildcard ("*")'
|
||||
end
|
||||
return true
|
||||
end, 'non-wildcard string')
|
||||
end
|
||||
|
||||
--- @nodoc
|
||||
--- @class vim.lsp.config
|
||||
--- @field [string] vim.lsp.Config
|
||||
@@ -371,11 +405,16 @@ lsp.config = setmetatable({ _configs = {} }, {
|
||||
--- @param name string
|
||||
--- @return vim.lsp.Config
|
||||
__index = function(self, name)
|
||||
validate('name', name, 'string')
|
||||
validate_config_name(name)
|
||||
|
||||
local rconfig = lsp._enabled_configs[name] or {}
|
||||
|
||||
if not rconfig.resolved_config then
|
||||
if name == '*' then
|
||||
rconfig.resolved_config = lsp.config._configs['*'] or {}
|
||||
return rconfig.resolved_config
|
||||
end
|
||||
|
||||
-- Resolve configs from lsp/*.lua
|
||||
-- Calls to vim.lsp.config in lsp/* have a lower precedence than calls from other sites.
|
||||
local rtp_config --- @type vim.lsp.Config?
|
||||
@@ -385,12 +424,12 @@ lsp.config = setmetatable({ _configs = {} }, {
|
||||
--- @type vim.lsp.Config?
|
||||
rtp_config = vim.tbl_deep_extend('force', rtp_config or {}, config)
|
||||
else
|
||||
log.warn(string.format('%s does not return a table, ignoring', v))
|
||||
log.warn(('%s does not return a table, ignoring'):format(v))
|
||||
end
|
||||
end
|
||||
|
||||
if not rtp_config and not self._configs[name] then
|
||||
log.warn(string.format('%s does not have a configuration', name))
|
||||
log.warn(('%s does not have a configuration'):format(name))
|
||||
return
|
||||
end
|
||||
|
||||
@@ -410,8 +449,9 @@ lsp.config = setmetatable({ _configs = {} }, {
|
||||
--- @param name string
|
||||
--- @param cfg vim.lsp.Config
|
||||
__newindex = function(self, name, cfg)
|
||||
validate('name', name, 'string')
|
||||
validate('cfg', cfg, 'table')
|
||||
validate_config_name(name)
|
||||
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,
|
||||
@@ -420,8 +460,9 @@ lsp.config = setmetatable({ _configs = {} }, {
|
||||
--- @param name string
|
||||
--- @param cfg vim.lsp.Config
|
||||
__call = function(self, name, cfg)
|
||||
validate('name', name, 'string')
|
||||
validate('cfg', cfg, 'table')
|
||||
validate_config_name(name)
|
||||
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,
|
||||
@@ -480,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
|
||||
@@ -502,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' })
|
||||
|
||||
@@ -528,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
|
||||
@@ -564,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`.
|
||||
@@ -611,10 +706,23 @@ 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
|
||||
|
||||
if
|
||||
not config.root_dir
|
||||
and (not config.workspace_folders or #config.workspace_folders == 0)
|
||||
and config.workspace_required
|
||||
then
|
||||
log.info(
|
||||
('skipping config "%s": workspace_required=true, no workspace found'):format(config.name)
|
||||
)
|
||||
return
|
||||
end
|
||||
|
||||
for _, client in pairs(all_clients) do
|
||||
if reuse_client(client, config) then
|
||||
if opts.attach == false then
|
||||
@@ -1181,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
|
||||
@@ -215,7 +215,13 @@ local function get_locations(method, opts)
|
||||
vim.fn.settagstack(vim.fn.win_getid(win), { items = tagstack }, 't')
|
||||
|
||||
vim.bo[b].buflisted = true
|
||||
local w = opts.reuse_win and vim.fn.win_findbuf(b)[1] or win
|
||||
local w = win
|
||||
if opts.reuse_win then
|
||||
w = vim.fn.win_findbuf(b)[1] or w
|
||||
if w ~= win then
|
||||
api.nvim_set_current_win(w)
|
||||
end
|
||||
end
|
||||
api.nvim_win_set_buf(w, b)
|
||||
api.nvim_win_set_cursor(w, { item.lnum, item.col - 1 })
|
||||
vim._with({ win = w }, function()
|
||||
@@ -303,6 +309,7 @@ end
|
||||
--- @param results table<integer,{err: lsp.ResponseError?, result: lsp.SignatureHelp?}>
|
||||
local function process_signature_help_results(results)
|
||||
local signatures = {} --- @type [vim.lsp.Client,lsp.SignatureInformation][]
|
||||
local active_signature = 1
|
||||
|
||||
-- Pre-process results
|
||||
for client_id, r in pairs(results) do
|
||||
@@ -317,15 +324,19 @@ local function process_signature_help_results(results)
|
||||
else
|
||||
local result = r.result --- @type lsp.SignatureHelp
|
||||
if result and result.signatures and result.signatures[1] then
|
||||
for _, sig in ipairs(result.signatures) do
|
||||
for i, sig in ipairs(result.signatures) do
|
||||
sig.activeParameter = sig.activeParameter or result.activeParameter
|
||||
signatures[#signatures + 1] = { client, sig }
|
||||
local idx = #signatures + 1
|
||||
if (result.activeSignature or 0) + 1 == i then
|
||||
active_signature = idx
|
||||
end
|
||||
signatures[idx] = { client, sig }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return signatures
|
||||
return signatures, active_signature
|
||||
end
|
||||
|
||||
local sig_help_ns = api.nvim_create_namespace('nvim.lsp.signature_help')
|
||||
@@ -341,6 +352,7 @@ function M.signature_help(config)
|
||||
|
||||
config = config and vim.deepcopy(config) or {}
|
||||
config.focus_id = method
|
||||
local user_title = config.title
|
||||
|
||||
lsp.buf_request_all(0, method, client_positional_params(), function(results, ctx)
|
||||
if api.nvim_get_current_buf() ~= ctx.bufnr then
|
||||
@@ -348,19 +360,19 @@ function M.signature_help(config)
|
||||
return
|
||||
end
|
||||
|
||||
local signatures = process_signature_help_results(results)
|
||||
local signatures, active_signature = process_signature_help_results(results)
|
||||
|
||||
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
|
||||
|
||||
local ft = vim.bo[ctx.bufnr].filetype
|
||||
local total = #signatures
|
||||
local can_cycle = total > 1 and config.focusable
|
||||
local idx = 0
|
||||
local can_cycle = total > 1 and config.focusable ~= false
|
||||
local idx = active_signature - 1
|
||||
|
||||
--- @param update_win? integer
|
||||
local function show_signature(update_win)
|
||||
@@ -375,15 +387,19 @@ function M.signature_help(config)
|
||||
return
|
||||
end
|
||||
|
||||
local sfx = can_cycle and string.format(' (%d/%d) (<C-s> to cycle)', idx, total) or ''
|
||||
local title = string.format('Signature Help: %s%s', client.name, sfx)
|
||||
if config.border then
|
||||
config.title = title
|
||||
else
|
||||
table.insert(lines, 1, '# ' .. title)
|
||||
if hl then
|
||||
hl[1] = hl[1] + 1
|
||||
hl[3] = hl[3] + 1
|
||||
-- Show title only if there are multiple clients or multiple signatures.
|
||||
if total > 1 then
|
||||
local sfx = total > 1
|
||||
and string.format(' (%d/%d)%s', idx, total, can_cycle and ' (<C-s> to cycle)' or '')
|
||||
or ''
|
||||
config.title = user_title or string.format('Signature Help: %s%s', client.name, sfx)
|
||||
-- If no border is set, render title inside the window.
|
||||
if not (config.border or vim.o.winborder ~= '') then
|
||||
table.insert(lines, 1, '# ' .. config.title)
|
||||
if hl then
|
||||
hl[1] = hl[1] + 1
|
||||
hl[3] = hl[3] + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -427,7 +443,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,
|
||||
@@ -957,7 +973,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()
|
||||
@@ -981,7 +997,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.
|
||||
@@ -1198,8 +1214,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,38 +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[]
|
||||
--- 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
|
||||
@@ -70,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
|
||||
@@ -166,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
|
||||
@@ -203,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[]
|
||||
@@ -392,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),
|
||||
@@ -458,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,
|
||||
@@ -675,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,
|
||||
@@ -685,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
|
||||
@@ -799,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
|
||||
@@ -930,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,
|
||||
|
@@ -111,8 +111,8 @@ local function check_watcher()
|
||||
watchfunc_name = 'libuv-watch'
|
||||
elseif watchfunc == vim._watch.watchdirs then
|
||||
watchfunc_name = 'libuv-watchdirs'
|
||||
elseif watchfunc == vim._watch.inotifywait then
|
||||
watchfunc_name = 'inotifywait'
|
||||
elseif watchfunc == vim._watch.inotify then
|
||||
watchfunc_name = 'inotify'
|
||||
else
|
||||
local nm = debug.getinfo(watchfunc, 'S').source
|
||||
watchfunc_name = string.format('Custom (%s)', nm)
|
||||
@@ -187,26 +187,32 @@ local function check_enabled_configs()
|
||||
local config = vim.lsp.config[name]
|
||||
local text = {} --- @type string[]
|
||||
text[#text + 1] = ('%s:'):format(name)
|
||||
for k, v in
|
||||
vim.spairs(config --[[@as table<string,any>]])
|
||||
do
|
||||
local v_str --- @type string?
|
||||
if k == 'name' then
|
||||
v_str = nil
|
||||
elseif k == 'filetypes' or k == 'root_markers' then
|
||||
v_str = table.concat(v, ', ')
|
||||
elseif type(v) == 'function' then
|
||||
v_str = func_tostring(v)
|
||||
else
|
||||
v_str = vim.inspect(v, { newline = '\n ' })
|
||||
end
|
||||
if not config then
|
||||
report_warn(
|
||||
("'%s' config not found. Ensure that vim.lsp.config('%s') was called."):format(name, name)
|
||||
)
|
||||
else
|
||||
for k, v in
|
||||
vim.spairs(config --[[@as table<string,any>]])
|
||||
do
|
||||
local v_str --- @type string?
|
||||
if k == 'name' then
|
||||
v_str = nil
|
||||
elseif k == 'filetypes' then
|
||||
v_str = table.concat(v, ', ')
|
||||
elseif type(v) == 'function' then
|
||||
v_str = func_tostring(v)
|
||||
else
|
||||
v_str = vim.inspect(v, { newline = '\n ' })
|
||||
end
|
||||
|
||||
if k == 'cmd' and type(v) == 'table' and vim.fn.executable(v[1]) == 0 then
|
||||
report_warn(("'%s' is not executable. Configuration will not be used."):format(v[1]))
|
||||
end
|
||||
if k == 'cmd' and type(v) == 'table' and vim.fn.executable(v[1]) == 0 then
|
||||
report_warn(("'%s' is not executable. Configuration will not be used."):format(v[1]))
|
||||
end
|
||||
|
||||
if v_str then
|
||||
text[#text + 1] = ('- %s: %s'):format(k, v_str)
|
||||
if v_str then
|
||||
text[#text + 1] = ('- %s: %s'):format(k, v_str)
|
||||
end
|
||||
end
|
||||
end
|
||||
text[#text + 1] = ''
|
||||
|
@@ -94,10 +94,10 @@ function M.on_refresh(err, _, ctx)
|
||||
for _, bufnr in ipairs(vim.lsp.get_buffers_by_client_id(ctx.client_id)) do
|
||||
for _, winid in ipairs(api.nvim_list_wins()) do
|
||||
if api.nvim_win_get_buf(winid) == bufnr then
|
||||
if bufstates[bufnr] then
|
||||
if bufstates[bufnr] and bufstates[bufnr].enabled then
|
||||
bufstates[bufnr].applied = {}
|
||||
util._refresh(ms.textDocument_inlayHint, { bufnr = bufnr })
|
||||
end
|
||||
util._refresh(ms.textDocument_inlayHint, { bufnr = bufnr })
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@@ -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,
|
||||
},
|
||||
|
@@ -24,6 +24,7 @@ local border_size = {
|
||||
rounded = { 2, 2 },
|
||||
solid = { 2, 2 },
|
||||
shadow = { 1, 1 },
|
||||
bold = { 2, 2 },
|
||||
}
|
||||
|
||||
--- Check the border given by opts or the default border for the additional
|
||||
@@ -744,6 +745,10 @@ function M.convert_signature_help_to_markdown_lines(signature_help, ft, triggers
|
||||
if type(doc) == 'string' then
|
||||
signature.documentation = { kind = 'plaintext', value = doc }
|
||||
end
|
||||
-- Add delimiter if there is documentation to display
|
||||
if signature.documentation.value ~= '' then
|
||||
contents[#contents + 1] = '---'
|
||||
end
|
||||
M.convert_input_to_markdown_lines(signature.documentation, contents)
|
||||
end
|
||||
if signature.parameters and #signature.parameters > 0 then
|
||||
@@ -860,7 +865,7 @@ function M.make_floating_popup_options(width, height, opts)
|
||||
col = 1
|
||||
end
|
||||
|
||||
local title = (opts.border and opts.title) and opts.title or nil
|
||||
local title = ((opts.border or vim.o.winborder ~= '') and opts.title) and opts.title or nil
|
||||
local title_pos --- @type 'left'|'center'|'right'?
|
||||
|
||||
if title then
|
||||
@@ -1138,10 +1143,8 @@ function M.stylize_markdown(bufnr, contents, opts)
|
||||
-- Clean up
|
||||
contents = vim.split(table.concat(contents, '\n'), '\n', { trimempty = true })
|
||||
|
||||
local stripped = {}
|
||||
local stripped = {} --- @type string[]
|
||||
local highlights = {} --- @type {ft:string,start:integer,finish:integer}[]
|
||||
-- keep track of lnums that contain markdown
|
||||
local markdown_lines = {} --- @type table<integer,boolean>
|
||||
|
||||
local i = 1
|
||||
while i <= #contents do
|
||||
@@ -1156,7 +1159,7 @@ function M.stylize_markdown(bufnr, contents, opts)
|
||||
i = i + 1
|
||||
break
|
||||
end
|
||||
table.insert(stripped, line)
|
||||
stripped[#stripped + 1] = line
|
||||
i = i + 1
|
||||
end
|
||||
table.insert(highlights, {
|
||||
@@ -1166,30 +1169,23 @@ function M.stylize_markdown(bufnr, contents, opts)
|
||||
})
|
||||
-- add a separator, but not on the last line
|
||||
if opts.separator and i < #contents then
|
||||
table.insert(stripped, '---')
|
||||
markdown_lines[#stripped] = true
|
||||
stripped[#stripped + 1] = '---'
|
||||
end
|
||||
else
|
||||
-- strip any empty lines or separators prior to this separator in actual markdown
|
||||
if line:match('^---+$') then
|
||||
while
|
||||
markdown_lines[#stripped]
|
||||
stripped[#stripped]
|
||||
and (stripped[#stripped]:match('^%s*$') or stripped[#stripped]:match('^---+$'))
|
||||
do
|
||||
markdown_lines[#stripped] = false
|
||||
table.remove(stripped, #stripped)
|
||||
stripped[#stripped] = nil
|
||||
end
|
||||
end
|
||||
-- add the line if its not an empty line following a separator
|
||||
if
|
||||
not (
|
||||
line:match('^%s*$')
|
||||
and markdown_lines[#stripped]
|
||||
and stripped[#stripped]:match('^---+$')
|
||||
)
|
||||
not (line:match('^%s*$') and stripped[#stripped] and stripped[#stripped]:match('^---+$'))
|
||||
then
|
||||
table.insert(stripped, line)
|
||||
markdown_lines[#stripped] = true
|
||||
stripped[#stripped + 1] = line
|
||||
end
|
||||
i = i + 1
|
||||
end
|
||||
@@ -1220,7 +1216,7 @@ function M.stylize_markdown(bufnr, contents, opts)
|
||||
|
||||
local sep_line = string.rep('─', math.min(width, opts.wrap_at or width))
|
||||
|
||||
for l in pairs(markdown_lines) do
|
||||
for l in ipairs(stripped) do
|
||||
if stripped[l]:match('^---+$') then
|
||||
stripped[l] = sep_line
|
||||
end
|
||||
@@ -1348,26 +1344,34 @@ end
|
||||
---
|
||||
---@param events table list of events
|
||||
---@param winnr integer window id of preview window
|
||||
---@param bufnrs table list of buffers where the preview window will remain visible
|
||||
---@param floating_bufnr integer floating preview buffer
|
||||
---@param bufnr integer buffer that opened the floating preview buffer
|
||||
---@see autocmd-events
|
||||
local function close_preview_autocmd(events, winnr, bufnrs)
|
||||
local function close_preview_autocmd(events, winnr, floating_bufnr, bufnr)
|
||||
local augroup = api.nvim_create_augroup('nvim.preview_window_' .. winnr, {
|
||||
clear = true,
|
||||
})
|
||||
|
||||
-- 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 = bufnr,
|
||||
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, { floating_bufnr, bufnr })
|
||||
end
|
||||
end)
|
||||
end,
|
||||
})
|
||||
|
||||
if #events > 0 then
|
||||
api.nvim_create_autocmd(events, {
|
||||
group = augroup,
|
||||
buffer = bufnrs[2],
|
||||
buffer = bufnr,
|
||||
callback = function()
|
||||
close_preview_window(winnr)
|
||||
end,
|
||||
@@ -1614,7 +1618,7 @@ function M.open_floating_preview(contents, syntax, opts)
|
||||
'<cmd>bdelete<cr>',
|
||||
{ silent = true, noremap = true, nowait = true }
|
||||
)
|
||||
close_preview_autocmd(opts.close_events, floating_winnr, { floating_bufnr, bufnr })
|
||||
close_preview_autocmd(opts.close_events, floating_winnr, floating_bufnr, bufnr)
|
||||
|
||||
-- save focus_id
|
||||
if opts.focus_id then
|
||||
@@ -1801,7 +1805,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[]
|
||||
|
@@ -107,9 +107,22 @@ local function provider_disabled(provider)
|
||||
return false
|
||||
end
|
||||
|
||||
--- Checks the hygiene of a `g:loaded_xx_provider` variable.
|
||||
local function check_loaded_var(var)
|
||||
if vim.g[var] == 1 then
|
||||
health.error(('`g:%s=1` may have been set by mistake.'):format(var), {
|
||||
('Remove `vim.g.%s=1` from your config.'):format(var),
|
||||
'To disable the provider, set this to 0, not 1.',
|
||||
'If you want to enable the provider but skip automatic detection, set the respective `g:…_host_prog` var. See :help provider',
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
local function clipboard()
|
||||
health.start('Clipboard (optional)')
|
||||
|
||||
check_loaded_var('loaded_clipboard_provider')
|
||||
|
||||
if
|
||||
os.getenv('TMUX')
|
||||
and vim.fn.executable('tmux') == 1
|
||||
@@ -144,6 +157,8 @@ end
|
||||
local function node()
|
||||
health.start('Node.js provider (optional)')
|
||||
|
||||
check_loaded_var('loaded_node_provider')
|
||||
|
||||
if provider_disabled('node') then
|
||||
return
|
||||
end
|
||||
@@ -247,6 +262,8 @@ end
|
||||
local function perl()
|
||||
health.start('Perl provider (optional)')
|
||||
|
||||
check_loaded_var('loaded_perl_provider')
|
||||
|
||||
if provider_disabled('perl') then
|
||||
return
|
||||
end
|
||||
@@ -256,7 +273,7 @@ local function perl()
|
||||
if not perl_exec then
|
||||
health.warn(assert(perl_warnings), {
|
||||
'See :help provider-perl for more information.',
|
||||
'You may disable this provider (and warning) by adding `let g:loaded_perl_provider = 0` to your init.vim',
|
||||
'You can disable this provider (and warning) by adding `let g:loaded_perl_provider = 0` to your init.vim',
|
||||
})
|
||||
health.warn('No usable perl executable found')
|
||||
return
|
||||
@@ -547,7 +564,7 @@ local function version_info(python)
|
||||
|
||||
local nvim_path_base = vim.fn.fnamemodify(nvim_path, [[:~:h]])
|
||||
local version_status = 'unknown; ' .. nvim_path_base
|
||||
if is_bad_response(nvim_version) and is_bad_response(pypi_version) then
|
||||
if not is_bad_response(nvim_version) and not is_bad_response(pypi_version) then
|
||||
if vim.version.lt(nvim_version, pypi_version) then
|
||||
version_status = 'outdated; from ' .. nvim_path_base
|
||||
else
|
||||
@@ -561,6 +578,8 @@ end
|
||||
local function python()
|
||||
health.start('Python 3 provider (optional)')
|
||||
|
||||
check_loaded_var('loaded_python3_provider')
|
||||
|
||||
local python_exe = ''
|
||||
local virtual_env = os.getenv('VIRTUAL_ENV')
|
||||
local venv = virtual_env and vim.fn.resolve(virtual_env) or ''
|
||||
@@ -595,7 +614,7 @@ local function python()
|
||||
if pythonx_warnings then
|
||||
health.warn(pythonx_warnings, {
|
||||
'See :help provider-python for more information.',
|
||||
'You may disable this provider (and warning) by adding `let g:loaded_python3_provider = 0` to your init.vim',
|
||||
'You can disable this provider (and warning) by adding `let g:loaded_python3_provider = 0` to your init.vim',
|
||||
})
|
||||
elseif pyname and pyname ~= '' and python_exe == '' then
|
||||
if not vim.g[host_prog_var] then
|
||||
@@ -705,10 +724,9 @@ local function python()
|
||||
local message = 'Detected pip upgrade failure: Python executable can import "pynvim" but not "neovim": '
|
||||
.. pynvim_exe
|
||||
local advice = {
|
||||
'Use that Python version to reinstall "pynvim" and optionally "neovim".',
|
||||
'Use that Python version to uninstall any "pynvim" or "neovim", e.g.:',
|
||||
pynvim_exe .. ' -m pip uninstall pynvim neovim',
|
||||
pynvim_exe .. ' -m pip install pynvim',
|
||||
pynvim_exe .. ' -m pip install neovim # only if needed by third-party software',
|
||||
'Then see :help provider-python for "pynvim" installation steps.',
|
||||
}
|
||||
health.error(message, advice)
|
||||
end
|
||||
@@ -734,7 +752,7 @@ local function python()
|
||||
if is_bad_response(current) then
|
||||
health.error(
|
||||
'pynvim is not installed.\nError: ' .. current,
|
||||
'Run in shell: ' .. python_exe .. ' -m pip install pynvim'
|
||||
'See :help provider-python for "pynvim" installation steps.'
|
||||
)
|
||||
end
|
||||
|
||||
@@ -840,6 +858,8 @@ end
|
||||
local function ruby()
|
||||
health.start('Ruby provider (optional)')
|
||||
|
||||
check_loaded_var('loaded_ruby_provider')
|
||||
|
||||
if provider_disabled('ruby') then
|
||||
return
|
||||
end
|
||||
@@ -860,7 +880,7 @@ local function ruby()
|
||||
'Run `gem environment` to ensure the gem bin directory is in $PATH.',
|
||||
'If you are using rvm/rbenv/chruby, try "rehashing".',
|
||||
'See :help g:ruby_host_prog for non-standard gem installations.',
|
||||
'You may disable this provider (and warning) by adding `let g:loaded_ruby_provider = 0` to your init.vim',
|
||||
'You can disable this provider (and warning) by adding `let g:loaded_ruby_provider = 0` to your init.vim',
|
||||
})
|
||||
return
|
||||
end
|
||||
|
@@ -1,5 +1,5 @@
|
||||
local M = {}
|
||||
local min_version = '3.7'
|
||||
local min_version = '3.9'
|
||||
local s_err ---@type string?
|
||||
local s_host ---@type string?
|
||||
|
||||
@@ -83,6 +83,10 @@ function M.detect_by_module(module)
|
||||
return vim.fn.exepath(vim.fn.expand(python_exe, true)), nil
|
||||
end
|
||||
|
||||
if vim.fn.executable('pynvim-python') == 1 then
|
||||
return 'pynvim-python'
|
||||
end
|
||||
|
||||
local errors = {}
|
||||
for _, exe in ipairs(python_candidates) do
|
||||
local error = check_for_module(exe, module)
|
||||
|
@@ -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
|
||||
|
@@ -119,7 +119,7 @@ local Tabstop = {}
|
||||
function Tabstop.new(index, bufnr, range, choices)
|
||||
local extmark_id = vim.api.nvim_buf_set_extmark(bufnr, snippet_ns, range[1], range[2], {
|
||||
right_gravity = true,
|
||||
end_right_gravity = true,
|
||||
end_right_gravity = false,
|
||||
end_line = range[3],
|
||||
end_col = range[4],
|
||||
hl_group = hl_group,
|
||||
@@ -170,7 +170,7 @@ function Tabstop:set_right_gravity(right_gravity)
|
||||
local range = self:get_range()
|
||||
self.extmark_id = vim.api.nvim_buf_set_extmark(self.bufnr, snippet_ns, range[1], range[2], {
|
||||
right_gravity = right_gravity,
|
||||
end_right_gravity = true,
|
||||
end_right_gravity = not right_gravity,
|
||||
end_line = range[3],
|
||||
end_col = range[4],
|
||||
hl_group = hl_group,
|
||||
@@ -257,10 +257,21 @@ local M = { session = nil }
|
||||
local function display_choices(tabstop)
|
||||
assert(tabstop.choices, 'Tabstop has no choices')
|
||||
|
||||
local text = tabstop:get_text()
|
||||
local found_text = false
|
||||
|
||||
local start_col = tabstop:get_range()[2] + 1
|
||||
local matches = {} --- @type table[]
|
||||
for _, choice in ipairs(tabstop.choices) do
|
||||
matches[#matches + 1] = { word = choice }
|
||||
if choice ~= text then
|
||||
matches[#matches + 1] = { word = choice }
|
||||
else
|
||||
found_text = true
|
||||
end
|
||||
end
|
||||
|
||||
if found_text then
|
||||
table.insert(matches, 1, text)
|
||||
end
|
||||
|
||||
vim.defer_fn(function()
|
||||
@@ -278,17 +289,6 @@ local function select_tabstop(tabstop)
|
||||
vim.api.nvim_feedkeys(keys, 'n', true)
|
||||
end
|
||||
|
||||
--- NOTE: We don't use `vim.api.nvim_win_set_cursor` here because it causes the cursor to end
|
||||
--- at the end of the selection instead of the start.
|
||||
---
|
||||
--- @param row integer
|
||||
--- @param col integer
|
||||
local function move_cursor_to(row, col)
|
||||
local line = vim.fn.getline(row) --[[ @as string ]]
|
||||
col = math.max(vim.fn.strchars(line:sub(1, col)) - 1, 0)
|
||||
feedkeys(string.format('%sG0%s', row, string.rep('<Right>', col)))
|
||||
end
|
||||
|
||||
local range = tabstop:get_range()
|
||||
local mode = vim.fn.mode()
|
||||
|
||||
@@ -309,17 +309,21 @@ local function select_tabstop(tabstop)
|
||||
vim.cmd.startinsert({ bang = range[4] >= #vim.api.nvim_get_current_line() })
|
||||
end
|
||||
if tabstop.choices then
|
||||
vim.fn.cursor(range[3] + 1, range[4] + 1)
|
||||
display_choices(tabstop)
|
||||
end
|
||||
else
|
||||
-- Else, select the tabstop's text.
|
||||
if mode ~= 'n' then
|
||||
feedkeys('<Esc>')
|
||||
end
|
||||
move_cursor_to(range[1] + 1, range[2] + 1)
|
||||
feedkeys('v')
|
||||
move_cursor_to(range[3] + 1, range[4])
|
||||
feedkeys('o<c-g><c-r>_')
|
||||
-- Need this exact order so cannot mix regular API calls with feedkeys, which
|
||||
-- are not executed immediately. Use <Cmd> to set the cursor position.
|
||||
local keys = {
|
||||
mode ~= 'n' and '<Esc>' or '',
|
||||
('<Cmd>call cursor(%s,%s)<CR>'):format(range[1] + 1, range[2] + 1),
|
||||
'v',
|
||||
('<Cmd>call cursor(%s,%s)<CR>'):format(range[3] + 1, range[4]),
|
||||
'o<c-g><c-r>_',
|
||||
}
|
||||
feedkeys(table.concat(keys))
|
||||
end
|
||||
end
|
||||
|
||||
|
@@ -40,10 +40,6 @@ local heading_queries = {
|
||||
]],
|
||||
}
|
||||
|
||||
local function hash_tick(bufnr)
|
||||
return tostring(vim.b[bufnr].changedtick)
|
||||
end
|
||||
|
||||
---@class TS.Heading
|
||||
---@field bufnr integer
|
||||
---@field lnum integer
|
||||
@@ -53,7 +49,7 @@ end
|
||||
--- Extract headings from buffer
|
||||
--- @param bufnr integer buffer to extract headings from
|
||||
--- @return TS.Heading[]
|
||||
local get_headings = vim.func._memoize(hash_tick, function(bufnr)
|
||||
local get_headings = function(bufnr)
|
||||
local lang = ts.language.get_lang(vim.bo[bufnr].filetype)
|
||||
if not lang then
|
||||
return {}
|
||||
@@ -85,11 +81,13 @@ local get_headings = vim.func._memoize(hash_tick, function(bufnr)
|
||||
end
|
||||
end
|
||||
return headings
|
||||
end)
|
||||
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
|
||||
@@ -105,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>
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user