mirror of
https://github.com/neovim/neovim.git
synced 2025-09-06 03:18:16 +00:00
Compare commits
334 Commits
marvim/ci-
...
7b099d2b2b
Author | SHA1 | Date | |
---|---|---|---|
![]() |
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 |
@@ -18,7 +18,6 @@ Checks: >
|
||||
-bugprone-not-null-terminated-result,
|
||||
-bugprone-suspicious-memory-comparison,
|
||||
-bugprone-switch-missing-default-case,
|
||||
-bugprone-tagged-union-member-count,
|
||||
-cert-env33-c,
|
||||
-cert-err33-c,
|
||||
-cert-err34-c,
|
||||
@@ -64,7 +63,6 @@ Checks: >
|
||||
|
||||
Aliases. These are just duplicates of other warnings and should always be ignored,
|
||||
-bugprone-narrowing-conversions,
|
||||
-cert-arr39-c,
|
||||
-cert-dcl37-c,
|
||||
-cert-dcl51-cpp,
|
||||
-cert-exp42-c,
|
||||
|
25
.emmyrc.json
25
.emmyrc.json
@@ -1,25 +0,0 @@
|
||||
{
|
||||
"$schema": "https://raw.githubusercontent.com/EmmyLuaLs/emmylua-analyzer-rust/refs/heads/main/crates/emmylua_code_analysis/resources/schema.json",
|
||||
"format": {
|
||||
"externalTool": {
|
||||
"program": "stylua",
|
||||
"args": [
|
||||
"-",
|
||||
"--stdin-filepath",
|
||||
"${file}"
|
||||
]
|
||||
}
|
||||
},
|
||||
"diagnostics": {
|
||||
"disable": [
|
||||
"unnecessary-if"
|
||||
]
|
||||
},
|
||||
"codeAction": {
|
||||
"insertSpace": true
|
||||
},
|
||||
"strict": {
|
||||
"typeCall": true,
|
||||
"arrayIndex": true
|
||||
}
|
||||
}
|
0
.gitattributes
vendored
Normal file → Executable file
0
.gitattributes
vendored
Normal file → Executable file
5
.github/pull_request_template.md
vendored
5
.github/pull_request_template.md
vendored
@@ -1,5 +0,0 @@
|
||||
<!--
|
||||
Thank you for contributing to Neovim!
|
||||
If this is your first time, check out https://github.com/neovim/neovim/blob/master/CONTRIBUTING.md#pull-requests-prs
|
||||
for our PR guidelines.
|
||||
-->
|
14
.github/scripts/env.ps1
vendored
14
.github/scripts/env.ps1
vendored
@@ -1,16 +1,8 @@
|
||||
# This script enables Developer Command Prompt
|
||||
# See https://github.com/microsoft/vswhere/wiki/Start-Developer-Command-Prompt#using-powershell
|
||||
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 {
|
||||
$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
|
||||
}
|
||||
|
2
.github/scripts/reviewers_add.js
vendored
2
.github/scripts/reviewers_add.js
vendored
@@ -57,7 +57,6 @@ module.exports = async ({ github, context }) => {
|
||||
|
||||
if (labels.includes("lsp")) {
|
||||
reviewers.add("MariaSolOs");
|
||||
reviewers.add("ribru17");
|
||||
}
|
||||
|
||||
if (labels.includes("netrw")) {
|
||||
@@ -90,7 +89,6 @@ module.exports = async ({ github, context }) => {
|
||||
reviewers.add("clason");
|
||||
reviewers.add("lewis6991");
|
||||
reviewers.add("wookayin");
|
||||
reviewers.add("ribru17");
|
||||
}
|
||||
|
||||
if (labels.includes("tui")) {
|
||||
|
4
.github/workflows/backport.yml
vendored
4
.github/workflows/backport.yml
vendored
@@ -11,9 +11,9 @@ jobs:
|
||||
if: github.event.pull_request.merged
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/create-github-app-token@v2
|
||||
- uses: actions/create-github-app-token@v1
|
||||
id: app-token
|
||||
with:
|
||||
app-id: ${{ vars.BACKPORT_APP }}
|
||||
|
6
.github/workflows/build.yml
vendored
6
.github/workflows/build.yml
vendored
@@ -28,7 +28,7 @@ jobs:
|
||||
test: [ubuntu-latest, macos-latest, windows-latest]
|
||||
runs-on: ${{ matrix.test }}
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v4
|
||||
- uses: ./.github/actions/setup
|
||||
- run: |
|
||||
cmake -S cmake.deps --preset ci -D ENABLE_WASMTIME=ON
|
||||
@@ -44,7 +44,7 @@ jobs:
|
||||
CMAKE_URL: 'https://cmake.org/files/v3.16/cmake-3.16.0-Linux-x86_64.sh'
|
||||
CMAKE_VERSION: '3.16.0'
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v4
|
||||
- uses: ./.github/actions/setup
|
||||
|
||||
- name: Install minimum required version of cmake
|
||||
@@ -73,7 +73,7 @@ jobs:
|
||||
name: Test USE_EXISTING_SRC_DIR=ON builds with no network access
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v4
|
||||
- uses: ./.github/actions/setup
|
||||
|
||||
- name: Build bundled dependencies
|
||||
|
2
.github/workflows/codeql.yml
vendored
2
.github/workflows/codeql.yml
vendored
@@ -22,7 +22,7 @@ jobs:
|
||||
security-events: write
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v4
|
||||
- uses: ./.github/actions/setup
|
||||
|
||||
- name: Initialize CodeQL
|
||||
|
2
.github/workflows/coverity.yml
vendored
2
.github/workflows/coverity.yml
vendored
@@ -8,7 +8,7 @@ jobs:
|
||||
scan:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v4
|
||||
- uses: ./.github/actions/setup
|
||||
|
||||
- name: Download Coverity
|
||||
|
2
.github/workflows/docs.yml
vendored
2
.github/workflows/docs.yml
vendored
@@ -10,7 +10,7 @@ jobs:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v4
|
||||
- uses: ./.github/actions/setup
|
||||
|
||||
- name: Generate docs
|
||||
|
2
.github/workflows/labeler_pr.yml
vendored
2
.github/workflows/labeler_pr.yml
vendored
@@ -9,7 +9,7 @@ jobs:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/labeler@v5
|
||||
with:
|
||||
configuration-path: .github/scripts/labeler_configuration.yml
|
||||
|
2
.github/workflows/lintcommit.yml
vendored
2
.github/workflows/lintcommit.yml
vendored
@@ -9,7 +9,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event.pull_request.draft == false
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
|
2
.github/workflows/news.yml
vendored
2
.github/workflows/news.yml
vendored
@@ -9,7 +9,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event.pull_request.draft == false && !contains(github.event.pull_request.labels.*.name, 'ci:skip-news')
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
|
17
.github/workflows/notes.md
vendored
17
.github/workflows/notes.md
vendored
@@ -2,26 +2,21 @@
|
||||
${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** (or **nvim-win-arm64.zip** for ARM)
|
||||
1. Download **nvim-win64.zip**
|
||||
2. Extract the zip
|
||||
3. Run `nvim.exe` in your terminal
|
||||
3. Run `nvim.exe` on your CLI of choice
|
||||
|
||||
#### MSI
|
||||
|
||||
1. Download **nvim-win64.msi** (or **nvim-win-arm64.msi** for ARM)
|
||||
1. Download **nvim-win64.msi**
|
||||
2. Run the MSI
|
||||
3. Run `nvim.exe` in your terminal
|
||||
3. Run `nvim.exe` on your CLI of choice
|
||||
|
||||
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).
|
||||
|
||||
@@ -41,7 +36,7 @@ Note: On Windows "Server" you may need to [install vcruntime140.dll](https://lea
|
||||
|
||||
### Linux (x86_64)
|
||||
|
||||
If your system does not have the required glibc version, try the (unsupported) [builds for older glibc](https://github.com/neovim/neovim-releases).
|
||||
If your system does not have the [required glibc version](https://neovim.io/doc/user/support.html#supported-platforms), try the (unsupported) [builds for older glibc](https://github.com/neovim/neovim-releases).
|
||||
|
||||
#### AppImage
|
||||
|
||||
@@ -59,7 +54,7 @@ If your system does not have the required glibc version, try the (unsupported) [
|
||||
2. Extract: `tar xzvf nvim-linux-x86_64.tar.gz`
|
||||
3. Run `./nvim-linux-x86_64/bin/nvim`
|
||||
|
||||
### Linux (arm64)
|
||||
### Linux (arm64) - Untested
|
||||
|
||||
#### AppImage
|
||||
|
||||
|
44
.github/workflows/release.yml
vendored
44
.github/workflows/release.yml
vendored
@@ -55,7 +55,7 @@ jobs:
|
||||
outputs:
|
||||
version: ${{ steps.build.outputs.version }}
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
# Perform a full checkout #13471
|
||||
fetch-depth: 0
|
||||
@@ -101,7 +101,7 @@ jobs:
|
||||
env:
|
||||
MACOSX_DEPLOYMENT_TARGET: 11.0
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
# Perform a full checkout #13471
|
||||
fetch-depth: 0
|
||||
@@ -132,44 +132,27 @@ jobs:
|
||||
|
||||
windows:
|
||||
needs: setup
|
||||
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 }}
|
||||
runs-on: windows-2022
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- 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
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: nvim-win-${{ matrix.arch }}
|
||||
name: nvim-win64
|
||||
path: |
|
||||
build/${{ matrix.archive_name }}.zip
|
||||
build/${{ matrix.archive_name }}.msi
|
||||
build/nvim-win64.msi
|
||||
build/nvim-win64.zip
|
||||
retention-days: 1
|
||||
|
||||
publish:
|
||||
@@ -183,9 +166,9 @@ jobs:
|
||||
steps:
|
||||
# Must perform checkout first, since it deletes the target directory
|
||||
# before running, and would therefore delete the downloaded artifacts
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/download-artifact@v5
|
||||
- uses: actions/download-artifact@v4
|
||||
|
||||
- name: Install dependencies
|
||||
run: sudo apt-get update && sudo apt-get install -y gettext-base
|
||||
@@ -213,11 +196,10 @@ jobs:
|
||||
- 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"
|
||||
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-win-x86_64/* nvim-win-arm64/*
|
||||
gh release create stable $PRERELEASE --notes-file "$RUNNER_TEMP/notes.md" --title "$SUBJECT" --target $GITHUB_SHA nvim-macos-x86_64/* nvim-macos-arm64/* nvim-linux-x86_64/* nvim-linux-arm64/* nvim-appimage-x86_64/* nvim-appimage-arm64/* nvim-win64/*
|
||||
fi
|
||||
gh release create $TAG_NAME $PRERELEASE --notes-file "$RUNNER_TEMP/notes.md" --title "$SUBJECT" --target $GITHUB_SHA nvim-macos-x86_64/* nvim-macos-arm64/* nvim-linux-x86_64/* nvim-linux-arm64/* nvim-appimage-x86_64/* nvim-appimage-arm64/* nvim-win-x86_64/* nvim-win-arm64/*
|
||||
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/*
|
||||
|
4
.github/workflows/response.yml
vendored
4
.github/workflows/response.yml
vendored
@@ -13,7 +13,7 @@ jobs:
|
||||
issues: write
|
||||
pull-requests: write
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
@@ -27,7 +27,7 @@ jobs:
|
||||
issues: write
|
||||
pull-requests: write
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
|
2
.github/workflows/reviewers_add.yml
vendored
2
.github/workflows/reviewers_add.yml
vendored
@@ -10,7 +10,7 @@ jobs:
|
||||
permissions:
|
||||
pull-requests: write
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v4
|
||||
- name: 'Request reviewers'
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
|
2
.github/workflows/reviewers_remove.yml
vendored
2
.github/workflows/reviewers_remove.yml
vendored
@@ -8,7 +8,7 @@ jobs:
|
||||
permissions:
|
||||
pull-requests: write
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v4
|
||||
- name: 'Remove reviewers'
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
|
42
.github/workflows/test.yml
vendored
42
.github/workflows/test.yml
vendored
@@ -28,17 +28,17 @@ env:
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
runs-on: ubuntu-24.04-arm
|
||||
runs-on: ubuntu-24.04
|
||||
timeout-minutes: 10
|
||||
env:
|
||||
CC: clang
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v4
|
||||
- uses: ./.github/actions/setup
|
||||
|
||||
- name: Install stylua
|
||||
run: |
|
||||
wget --directory-prefix="$BIN_DIR" https://github.com/JohnnyMorganz/StyLua/releases/latest/download/stylua-linux-aarch64.zip
|
||||
wget --directory-prefix="$BIN_DIR" https://github.com/JohnnyMorganz/StyLua/releases/latest/download/stylua-linux-x86_64.zip
|
||||
(cd "$BIN_DIR"; unzip stylua*.zip)
|
||||
|
||||
- name: Build third-party deps
|
||||
@@ -82,12 +82,12 @@ jobs:
|
||||
run: cmake --build build --target lintc-uncrustify
|
||||
|
||||
clang-analyzer:
|
||||
runs-on: ubuntu-24.04-arm
|
||||
runs-on: ubuntu-24.04
|
||||
timeout-minutes: 20
|
||||
env:
|
||||
CC: clang
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v4
|
||||
- uses: ./.github/actions/setup
|
||||
- name: Build third-party deps
|
||||
run: |
|
||||
@@ -111,7 +111,7 @@ jobs:
|
||||
{ runner: ubuntu-24.04, os: ubuntu, flavor: asan, cc: clang, flags: -D ENABLE_ASAN_UBSAN=ON },
|
||||
{ runner: ubuntu-24.04, os: ubuntu, flavor: tsan, cc: clang, flags: -D ENABLE_TSAN=ON },
|
||||
{ runner: ubuntu-24.04, os: ubuntu, flavor: release, cc: gcc, flags: -D CMAKE_BUILD_TYPE=Release -D ENABLE_TRANSLATIONS=ON },
|
||||
{ runner: ubuntu-24.04-arm, os: ubuntu, flavor: arm, cc: clang, flags: -D CMAKE_BUILD_TYPE=RelWithDebInfo },
|
||||
# { runner: ubuntu-24.04-arm, os: ubuntu, flavor: arm, cc: gcc, flags: -D CMAKE_BUILD_TYPE=RelWithDebInfo },
|
||||
{ runner: macos-13, os: macos, flavor: intel, cc: clang, flags: -D CMAKE_FIND_FRAMEWORK=NEVER, deps_flags: -D CMAKE_FIND_FRAMEWORK=NEVER },
|
||||
{ runner: macos-15, os: macos, flavor: arm, cc: clang, flags: -D CMAKE_FIND_FRAMEWORK=NEVER, deps_flags: -D CMAKE_FIND_FRAMEWORK=NEVER },
|
||||
{ runner: ubuntu-24.04, os: ubuntu, flavor: puc-lua, cc: gcc, deps_flags: -D USE_BUNDLED_LUAJIT=OFF -D USE_BUNDLED_LUA=ON, flags: -D PREFER_LUA=ON },
|
||||
@@ -124,17 +124,12 @@ jobs:
|
||||
build: { flavor: puc-lua }
|
||||
- test: oldtest
|
||||
build: { flavor: tsan }
|
||||
- test: unittest
|
||||
build: { runner: ubuntu-24.04-arm }
|
||||
- test: oldtest
|
||||
build: { runner: ubuntu-24.04-arm }
|
||||
runs-on: ${{ matrix.build.runner }}
|
||||
timeout-minutes: 45
|
||||
env:
|
||||
CC: ${{ matrix.build.cc }}
|
||||
NVIM_TEST_INTEG: ${{ matrix.build.flavor == 'release' && '1' || '0' }}
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v4
|
||||
- uses: ./.github/actions/setup
|
||||
with:
|
||||
install_flags: "--test"
|
||||
@@ -206,35 +201,16 @@ jobs:
|
||||
name: Show logs
|
||||
run: cat $(find "$LOG_DIR" -type f)
|
||||
|
||||
zig-build:
|
||||
runs-on: ubuntu-24.04
|
||||
timeout-minutes: 45
|
||||
name: build using zig build (linux)
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: mlugg/setup-zig@v2
|
||||
with:
|
||||
version: 0.14.1
|
||||
- run: sudo apt-get install -y inotify-tools
|
||||
- run: zig build test_nlua0
|
||||
- run: zig build nvim && ./zig-out/bin/nvim --version
|
||||
- run: zig build unittest
|
||||
- run: zig build functionaltest
|
||||
# `zig build nvim` uses a lua script for doctags in order to support cross-compiling
|
||||
# compare with the builtin generator that they match
|
||||
- run: cd runtime; ../zig-out/bin/nvim -u NONE -i NONE -e --headless -c "helptags ++t doc" -c quit
|
||||
- run: diff -u runtime/doc/tags zig-out/runtime/doc/tags
|
||||
|
||||
windows:
|
||||
uses: ./.github/workflows/test_windows.yml
|
||||
|
||||
with-external-deps:
|
||||
runs-on: ubuntu-24.04-arm
|
||||
runs-on: ubuntu-24.04
|
||||
timeout-minutes: 10
|
||||
env:
|
||||
CC: gcc
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v4
|
||||
- uses: ./.github/actions/setup
|
||||
|
||||
- name: Install dependencies
|
||||
|
2
.github/workflows/test_windows.yml
vendored
2
.github/workflows/test_windows.yml
vendored
@@ -18,7 +18,7 @@ jobs:
|
||||
matrix:
|
||||
test: [functional, old]
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v4
|
||||
- uses: ./.github/actions/setup
|
||||
|
||||
- name: Build deps
|
||||
|
4
.github/workflows/vim_patches.yml
vendored
4
.github/workflows/vim_patches.yml
vendored
@@ -15,11 +15,11 @@ jobs:
|
||||
VERSION_BRANCH: marvim/ci-version-update
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
repository: vim/vim
|
||||
path: ${{ env.VIM_SOURCE_DIR }}
|
||||
|
3
.gitignore
vendored
3
.gitignore
vendored
@@ -10,8 +10,7 @@ compile_commands.json
|
||||
/.idea/
|
||||
|
||||
# Build/deps dir
|
||||
/.zig-cache/
|
||||
/zig-out/
|
||||
/build/
|
||||
/.deps/
|
||||
/tmp/
|
||||
/.clangd/
|
||||
|
@@ -49,7 +49,6 @@ exclude_files = {
|
||||
'runtime/lua/vim/_meta/vimfn.lua',
|
||||
'runtime/lua/vim/_meta/api.lua',
|
||||
'runtime/lua/vim/re.lua',
|
||||
'runtime/lua/uv/_meta.lua',
|
||||
'runtime/lua/coxpcall.lua',
|
||||
'src/nvim/eval.lua',
|
||||
}
|
||||
|
@@ -5,12 +5,13 @@
|
||||
},
|
||||
"workspace": {
|
||||
"library": [
|
||||
"${3rd}/busted/library"
|
||||
"runtime/lua",
|
||||
"${3rd}/busted/library",
|
||||
"${3rd}/luv/library"
|
||||
],
|
||||
"ignoreDir": [
|
||||
".deps",
|
||||
"build",
|
||||
"test"
|
||||
"test",
|
||||
"_vim9script.lua"
|
||||
],
|
||||
"checkThirdParty": "Disable"
|
||||
},
|
||||
|
@@ -1,8 +0,0 @@
|
||||
# Alternative settings for special snowflakes like: decorations_spec.lua, multigrid_spec.lua, etc.
|
||||
|
||||
column_width = 140
|
||||
line_endings = "Unix"
|
||||
indent_type = "Spaces"
|
||||
indent_width = 2
|
||||
quote_style = "AutoPreferSingle"
|
||||
call_parentheses = "Input"
|
@@ -1,15 +1,14 @@
|
||||
build/
|
||||
.deps/
|
||||
runtime/lua/coxpcall.lua
|
||||
runtime/lua/uv/_meta.lua
|
||||
runtime/lua/vim/_meta
|
||||
runtime/lua/vim/re.lua
|
||||
/build/
|
||||
/.deps/
|
||||
/runtime/lua/coxpcall.lua
|
||||
/runtime/lua/vim/_meta
|
||||
/runtime/lua/vim/re.lua
|
||||
|
||||
# These are formatted explicitly by the "formatlua2" build task.
|
||||
test/functional/ui/decorations_spec.lua
|
||||
test/functional/ui/float_spec.lua
|
||||
test/functional/ui/multigrid_spec.lua
|
||||
test/functional/fixtures/lua/syntax_error.lua
|
||||
test/functional/legacy/030_fileformats_spec.lua
|
||||
test/functional/legacy/044_099_regexp_multibyte_magic_spec.lua
|
||||
test/functional/legacy/093_mksession_cursor_cols_latin1_spec.lua
|
||||
/test/functional/fixtures/lua/syntax_error.lua
|
||||
/test/functional/legacy/030_fileformats_spec.lua
|
||||
/test/functional/legacy/044_099_regexp_multibyte_magic_spec.lua
|
||||
/test/functional/legacy/093_mksession_cursor_cols_latin1_spec.lua
|
||||
/test/functional/lua/luaeval_spec.lua
|
||||
|
53
BUILD.md
53
BUILD.md
@@ -165,40 +165,11 @@ https://github.com/cascent/neovim-cygwin was built on Cygwin 2.9.0. Newer `libuv
|
||||
mingw32-make install
|
||||
```
|
||||
|
||||
### Windows WSL
|
||||
|
||||
Build Ubuntu/Debian linux binary on [WSL](https://learn.microsoft.com/en-us/windows/wsl/install) (Windows Subsystem for Linux).
|
||||
|
||||
```bash
|
||||
# Install build prerequisites
|
||||
sudo apt-get install ninja-build gettext cmake build-essential
|
||||
|
||||
# Build the linux binary in WSL
|
||||
make CMAKE_BUILD_TYPE=RelWithDebInfo
|
||||
|
||||
# Install the linux binary in WSL (with `<arch>` either `x86_64` or `arm64`)
|
||||
cd build && cpack -G DEB && sudo dpkg -i nvim-linux-<arch>.deb
|
||||
|
||||
# Verify the installation
|
||||
nvim --version && which nvim # should be debug build in /usr/bin/nvim
|
||||
```
|
||||
|
||||
**Note**: If you encounter linker errors or segfaults during the build, Windows libraries in your PATH may be interfering. Use a clean PATH to avoid conflicts:
|
||||
|
||||
```bash
|
||||
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" make CMAKE_BUILD_TYPE=RelWithDebInfo
|
||||
```
|
||||
|
||||
## Localization
|
||||
|
||||
### Localization build
|
||||
|
||||
Translations are turned off by default. Enable by building Nvim with the CMake flag `ENABLE_TRANSLATIONS=ON`.
|
||||
Doing this will create `.mo` files in `build/src/nvim/po`. Example:
|
||||
|
||||
```
|
||||
make CMAKE_EXTRA_FLAGS="-DENABLE_TRANSLATIONS=ON"
|
||||
```
|
||||
A normal build will create `.mo` files in `build/src/nvim/po`.
|
||||
|
||||
* If you see `msgfmt: command not found`, you need to install [`gettext`](http://en.wikipedia.org/wiki/Gettext). On most systems, the package is just called `gettext`.
|
||||
|
||||
@@ -252,7 +223,7 @@ rebuild:
|
||||
|
||||
## Third-party dependencies
|
||||
|
||||
Reference the [Debian package](https://packages.debian.org/sid/source/neovim) (or alternatively, the [Homebrew formula](https://github.com/Homebrew/homebrew-core/blob/master/Formula/n/neovim.rb)) for the precise list of dependencies/versions.
|
||||
Reference the [Debian package](https://packages.debian.org/sid/source/neovim) (or alternatively, the [Homebrew formula](https://github.com/Homebrew/homebrew-core/blob/master/Formula/neovim.rb)) for the precise list of dependencies/versions.
|
||||
|
||||
To build the bundled dependencies using CMake:
|
||||
|
||||
@@ -302,7 +273,7 @@ podman run \
|
||||
-v "$PWD:/workdir" \
|
||||
-w /workdir \
|
||||
alpine:latest \
|
||||
bash -c 'apk add build-base cmake coreutils curl gettext-tiny-dev git && make CMAKE_EXTRA_FLAGS="-DSTATIC_BUILD=1"'
|
||||
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:
|
||||
@@ -346,31 +317,31 @@ Platform-specific requirements are listed below.
|
||||
### Ubuntu / Debian
|
||||
|
||||
```sh
|
||||
sudo apt-get install ninja-build gettext cmake curl build-essential git
|
||||
sudo apt-get install ninja-build gettext cmake curl build-essential
|
||||
```
|
||||
|
||||
### RHEL / Fedora
|
||||
|
||||
```
|
||||
sudo dnf -y install ninja-build cmake gcc make gettext curl glibc-gconv-extra git
|
||||
sudo dnf -y install ninja-build cmake gcc make gettext curl glibc-gconv-extra
|
||||
```
|
||||
|
||||
### openSUSE
|
||||
|
||||
```
|
||||
sudo zypper install ninja cmake gcc-c++ gettext-tools curl git
|
||||
sudo zypper install ninja cmake gcc-c++ gettext-tools curl
|
||||
```
|
||||
|
||||
### Arch Linux
|
||||
|
||||
```
|
||||
sudo pacman -S base-devel cmake ninja curl git
|
||||
sudo pacman -S base-devel cmake ninja curl
|
||||
```
|
||||
|
||||
### Alpine Linux
|
||||
|
||||
```
|
||||
apk add build-base cmake coreutils curl gettext-tiny-dev git
|
||||
apk add build-base cmake coreutils curl gettext-tiny-dev
|
||||
```
|
||||
|
||||
### Void Linux
|
||||
@@ -434,7 +405,7 @@ or a specific SHA1 like `--override-input neovim-src github:neovim/neovim/89dc8f
|
||||
### FreeBSD
|
||||
|
||||
```
|
||||
sudo pkg install cmake gmake sha wget gettext curl git
|
||||
sudo pkg install cmake gmake sha wget gettext curl
|
||||
```
|
||||
|
||||
If you get an error regarding a `sha256sum` mismatch, where the actual SHA-256 hash is `e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855`, then this is your issue (that's the `sha256sum` of an empty file).
|
||||
@@ -442,7 +413,7 @@ If you get an error regarding a `sha256sum` mismatch, where the actual SHA-256 h
|
||||
### OpenBSD
|
||||
|
||||
```sh
|
||||
doas pkg_add gmake cmake curl gettext-tools git
|
||||
doas pkg_add gmake cmake curl gettext-tools
|
||||
```
|
||||
|
||||
Build can sometimes fail when using the top level `Makefile`, apparently due to some third-party component (see [#2445-comment](https://github.com/neovim/neovim/issues/2445#issuecomment-108124236)). The following instructions use CMake:
|
||||
@@ -467,7 +438,7 @@ gmake
|
||||
2. Install [Homebrew](http://brew.sh)
|
||||
3. Install Neovim build dependencies:
|
||||
```
|
||||
brew install ninja cmake gettext curl git
|
||||
brew install ninja cmake gettext curl
|
||||
```
|
||||
- **Note**: If you see Wget certificate errors (for older macOS versions less than 10.10):
|
||||
```sh
|
||||
@@ -485,7 +456,7 @@ gmake
|
||||
2. Install [MacPorts](http://www.macports.org)
|
||||
3. Install Neovim build dependencies:
|
||||
```
|
||||
sudo port install ninja cmake gettext git
|
||||
sudo port install ninja cmake gettext
|
||||
```
|
||||
- **Note**: If you see Wget certificate errors (for older macOS versions less than 10.10):
|
||||
```sh
|
||||
|
@@ -35,11 +35,6 @@ include(InstallHelpers)
|
||||
include(PreventInTreeBuilds)
|
||||
include(Util)
|
||||
|
||||
if(NOT PROJECT_SOURCE_DIR STREQUAL PROJECT_BINARY_DIR)
|
||||
# Auto-create a .gitignore in the specified "build" directory.
|
||||
file(GENERATE OUTPUT .gitignore CONTENT "*")
|
||||
endif()
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# User settings
|
||||
#-------------------------------------------------------------------------------
|
||||
@@ -145,19 +140,19 @@ endif()
|
||||
# If not in a git repo (e.g., a tarball) these tokens define the complete
|
||||
# version string, else they are combined with the result of `git describe`.
|
||||
set(NVIM_VERSION_MAJOR 0)
|
||||
set(NVIM_VERSION_MINOR 12)
|
||||
set(NVIM_VERSION_PATCH 0)
|
||||
set(NVIM_VERSION_MINOR 11)
|
||||
set(NVIM_VERSION_PATCH 5)
|
||||
set(NVIM_VERSION_PRERELEASE "-dev") # for package maintainers
|
||||
|
||||
# API level
|
||||
set(NVIM_API_LEVEL 14) # Bump this after any API/stdlib change.
|
||||
set(NVIM_API_LEVEL 13) # Bump this after any API/stdlib change.
|
||||
set(NVIM_API_LEVEL_COMPAT 0) # Adjust this after a _breaking_ API change.
|
||||
set(NVIM_API_PRERELEASE true)
|
||||
set(NVIM_API_PRERELEASE false)
|
||||
|
||||
# We _want_ assertions in RelWithDebInfo build-type.
|
||||
if(CMAKE_C_FLAGS_RELWITHDEBINFO MATCHES DNDEBUG)
|
||||
string(REPLACE "-DNDEBUG" "-DRELDEBUG" CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO}")
|
||||
string(REPLACE "/DNDEBUG" "/DRELDEBUG" CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO}")
|
||||
string(REPLACE "-DNDEBUG" "" CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO}")
|
||||
string(REPLACE "/DNDEBUG" "" CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO}")
|
||||
string(REPLACE " " " " CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO}") # Remove duplicate whitespace
|
||||
endif()
|
||||
|
||||
@@ -241,7 +236,7 @@ set(STYLUA_DIRS runtime scripts src test contrib)
|
||||
add_glob_target(
|
||||
TARGET lintlua-luacheck
|
||||
COMMAND $<TARGET_FILE:nvim_bin>
|
||||
FLAGS -ll ${PROJECT_SOURCE_DIR}/test/lua_runner.lua ${CMAKE_BINARY_DIR}/usr/share/lua/5.1 luacheck -q
|
||||
FLAGS -ll ${PROJECT_SOURCE_DIR}/test/lua_runner.lua ${CMAKE_BINARY_DIR}/usr luacheck -q
|
||||
GLOB_DIRS runtime scripts src test
|
||||
GLOB_PAT *.lua
|
||||
TOUCH_STRATEGY PER_DIR)
|
||||
@@ -254,16 +249,6 @@ add_glob_target(
|
||||
GLOB_DIRS ${STYLUA_DIRS}
|
||||
GLOB_PAT *.lua
|
||||
TOUCH_STRATEGY PER_DIR)
|
||||
# Special handling of some files (which are ignored in .styluaignore).
|
||||
# Workaround because stylua doesn't(?) support file-specific settings.
|
||||
add_custom_target(lintlua-stylua2
|
||||
COMMAND ${STYLUA_PRG} --config-path "${PROJECT_SOURCE_DIR}/.stylua2.toml"
|
||||
--color=always --check
|
||||
"${PROJECT_SOURCE_DIR}/test/functional/ui/decorations_spec.lua"
|
||||
"${PROJECT_SOURCE_DIR}/test/functional/ui/float_spec.lua"
|
||||
"${PROJECT_SOURCE_DIR}/test/functional/ui/multigrid_spec.lua"
|
||||
)
|
||||
add_dependencies(lintlua-stylua lintlua-stylua2)
|
||||
|
||||
add_custom_target(lintlua)
|
||||
add_dependencies(lintlua lintlua-luacheck lintlua-stylua)
|
||||
@@ -277,7 +262,7 @@ add_glob_target(
|
||||
TOUCH_STRATEGY PER_DIR)
|
||||
|
||||
add_custom_target(lintcommit
|
||||
COMMAND $<TARGET_FILE:nvim_bin> --clean -l ${PROJECT_SOURCE_DIR}/scripts/lintcommit.lua main)
|
||||
COMMAND $<TARGET_FILE:nvim_bin> -u NONE -l ${PROJECT_SOURCE_DIR}/scripts/lintcommit.lua main)
|
||||
add_dependencies(lintcommit nvim_bin)
|
||||
|
||||
add_custom_target(lint)
|
||||
@@ -291,15 +276,7 @@ add_glob_target(
|
||||
GLOB_DIRS ${STYLUA_DIRS}
|
||||
GLOB_PAT *.lua
|
||||
TOUCH_STRATEGY PER_DIR)
|
||||
# Special handling of some files (which are ignored in .styluaignore).
|
||||
# Workaround because stylua doesn't(?) support file-specific settings.
|
||||
add_custom_target(formatlua2
|
||||
COMMAND ${STYLUA_PRG} --config-path "${PROJECT_SOURCE_DIR}/.stylua2.toml"
|
||||
"${PROJECT_SOURCE_DIR}/test/functional/ui/decorations_spec.lua"
|
||||
"${PROJECT_SOURCE_DIR}/test/functional/ui/float_spec.lua"
|
||||
"${PROJECT_SOURCE_DIR}/test/functional/ui/multigrid_spec.lua"
|
||||
)
|
||||
add_dependencies(formatlua formatlua2)
|
||||
|
||||
add_custom_target(format)
|
||||
add_dependencies(format formatc formatlua)
|
||||
|
||||
@@ -346,13 +323,13 @@ else()
|
||||
add_custom_target(lua_dev_deps)
|
||||
endif()
|
||||
|
||||
if (CMAKE_SYSTEM_PROCESSOR MATCHES "arm|aarch")
|
||||
if (CMAKE_SYSTEM_PROCESSOR MATCHES arm64)
|
||||
set(LUALS_ARCH arm64)
|
||||
else()
|
||||
set(LUALS_ARCH x64)
|
||||
endif()
|
||||
|
||||
set(LUALS_VERSION 3.15.0)
|
||||
set(LUALS_VERSION 3.13.9)
|
||||
set(LUALS "lua-language-server-${LUALS_VERSION}-${CMAKE_SYSTEM_NAME}-${LUALS_ARCH}")
|
||||
set(LUALS_TARBALL ${LUALS}.tar.gz)
|
||||
set(LUALS_URL https://github.com/LuaLS/lua-language-server/releases/download/${LUALS_VERSION}/${LUALS_TARBALL})
|
||||
|
@@ -299,7 +299,7 @@ types, etc. See [:help dev-lua-doc][dev-lua-doc].
|
||||
- If possible, add type information (`table`, `string`, `number`, ...). Multiple valid types are separated by a bar (`string|table`). Indicate optional parameters via `type|nil`.
|
||||
- If a function in your Lua module should _not_ be documented, add `@nodoc`.
|
||||
- If the function is internal or otherwise non-public add `@private`.
|
||||
- Private functions usually should be underscore-prefixed (named "_foo", not "foo"). Prefixing with an underscore implies `@nodoc`.
|
||||
- Private functions usually should be underscore-prefixed (named "_foo", not "foo").
|
||||
- Mark deprecated functions with `@deprecated`.
|
||||
|
||||
Third-party dependencies
|
||||
|
@@ -62,7 +62,7 @@ Several Neovim GUIs are available from scoop (extras): [scoop.sh/#/apps?q=neovim
|
||||
|
||||
- Add the `bin` folder (e.g. `C:\Program Files\nvim\bin`) to your PATH.
|
||||
- This makes it easy to run `nvim` from anywhere.
|
||||
- If `:set spell` does not work, create the `%LOCALAPPDATA%/nvim-data/site/spell` folder.
|
||||
- If `:set spell` does not work, create the `C:/Users/foo/AppData/Local/nvim/site/spell` folder.
|
||||
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));
|
||||
|
@@ -289,8 +289,3 @@ IV) It is not allowed to remove this license from the distribution of the Vim
|
||||
license for previous Vim releases instead of the license that they came
|
||||
with, at your option.
|
||||
|
||||
====
|
||||
|
||||
In addition, different license conditions may apply to some runtime files
|
||||
included with Vim; these will be specified in the header of each respective
|
||||
file.
|
||||
|
@@ -81,7 +81,7 @@ When a (non-experimental) feature is slated to be removed it should:
|
||||
as described for Lua features.
|
||||
- `vim.deprecate(…, 'x.y.z')` where major version `x` is greater than the
|
||||
current Nvim major version, is always treated as _soft_ deprecation.
|
||||
2. Be _hard_ deprecated in a release following the release in which it was soft deprecated.
|
||||
2. Be _hard_ deprecated in a following a release in which it was soft deprecated.
|
||||
- Use of the deprecated feature will still work but should issue a warning.
|
||||
- Features implemented in C will need bespoke implementations to communicate
|
||||
to users that the feature is deprecated.
|
||||
@@ -127,9 +127,7 @@ Some can be auto-bumped by `scripts/bump_deps.lua`.
|
||||
* [LuaJIT](https://github.com/LuaJIT/LuaJIT)
|
||||
* [Lua](https://www.lua.org/download.html)
|
||||
* [Luv](https://github.com/luvit/luv)
|
||||
* When bumping, also sync
|
||||
- [our bundled meta file](https://github.com/neovim/neovim/blob/master/runtime/lua/uv/_meta.lua) with [the upstream meta file](https://github.com/luvit/luv/blob/master/docs/meta.lua);
|
||||
- [our bundled documentation](https://github.com/neovim/neovim/blob/master/runtime/doc/luvref.txt) with [the upstream documentation](https://github.com/luvit/luv/blob/master/docs/docs.md).
|
||||
* When bumping, also sync [our bundled documentation](https://github.com/neovim/neovim/blob/master/runtime/doc/luvref.txt) with [the upstream documentation](https://github.com/luvit/luv/blob/master/docs.md).
|
||||
* [gettext](https://ftp.gnu.org/pub/gnu/gettext/)
|
||||
* [libiconv](https://ftp.gnu.org/pub/gnu/libiconv)
|
||||
* [libuv](https://github.com/libuv/libuv)
|
||||
@@ -154,7 +152,7 @@ These dependencies are "vendored" (inlined), we must update the sources manually
|
||||
* `src/nvim/tui/terminfo_defs.h`: terminfo definitions
|
||||
* Run `scripts/update_terminfo.sh` to update these definitions.
|
||||
* `runtime/lua/vim/lsp/_meta/protocol.lua`: LSP specification
|
||||
* Run `src/gen/gen_lsp.lua` to update.
|
||||
* Run `scripts/gen_lsp.lua` to update.
|
||||
* `runtime/lua/vim/_meta/lpeg.lua`: LPeg definitions.
|
||||
* Refer to [`LuaCATS/lpeg`](https://github.com/LuaCATS/lpeg) for updates.
|
||||
* Update the git SHA revision from which the documentation was taken.
|
||||
|
6
Makefile
6
Makefile
@@ -182,9 +182,3 @@ appimage-%:
|
||||
bash scripts/genappimage.sh $*
|
||||
|
||||
.PHONY: test clean distclean nvim libnvim cmake deps install appimage checkprefix benchmark $(FORMAT) $(LINT) $(TEST)
|
||||
|
||||
.PHONY: emmylua-check
|
||||
emmylua-check:
|
||||
-emmylua_check runtime/lua \
|
||||
--config .luarc.json \
|
||||
--config .emmyrc.json
|
||||
|
462
build.zig
462
build.zig
@@ -1,462 +0,0 @@
|
||||
const std = @import("std");
|
||||
const LazyPath = std.Build.LazyPath;
|
||||
const build_lua = @import("src/build_lua.zig");
|
||||
const gen = @import("src/gen/gen_steps.zig");
|
||||
const runtime = @import("runtime/gen_runtime.zig");
|
||||
const tests = @import("test/run_tests.zig");
|
||||
|
||||
const version = struct {
|
||||
const major = 0;
|
||||
const minor = 12;
|
||||
const patch = 0;
|
||||
const prerelease = "-dev";
|
||||
|
||||
const api_level = 14;
|
||||
const api_level_compat = 0;
|
||||
const api_prerelease = true;
|
||||
};
|
||||
|
||||
// TODO(bfredl): this is for an upstream issue
|
||||
pub fn lazyArtifact(d: *std.Build.Dependency, name: []const u8) ?*std.Build.Step.Compile {
|
||||
var found: ?*std.Build.Step.Compile = null;
|
||||
for (d.builder.install_tls.step.dependencies.items) |dep_step| {
|
||||
const inst = dep_step.cast(std.Build.Step.InstallArtifact) orelse continue;
|
||||
if (std.mem.eql(u8, inst.artifact.name, name)) {
|
||||
if (found != null) std.debug.panic("artifact name '{s}' is ambiguous", .{name});
|
||||
found = inst.artifact;
|
||||
}
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
pub fn build(b: *std.Build) !void {
|
||||
const target = b.standardTargetOptions(.{});
|
||||
const optimize = b.standardOptimizeOption(.{});
|
||||
|
||||
const t = target.result;
|
||||
const os_tag = t.os.tag;
|
||||
const is_windows = (os_tag == .windows);
|
||||
const is_linux = (os_tag == .linux);
|
||||
const is_darwin = os_tag.isDarwin();
|
||||
const modern_unix = is_darwin or os_tag.isBSD() or is_linux;
|
||||
|
||||
const cross_compiling = b.option(bool, "cross", "cross compile") orelse false;
|
||||
// TODO(bfredl): option to set nlua0 target explicitly when cross compiling?
|
||||
const target_host = if (cross_compiling) b.graph.host else target;
|
||||
const optimize_host = .ReleaseSafe;
|
||||
|
||||
// puc lua 5.1 is not ReleaseSafe "safe"
|
||||
const optimize_lua = if (optimize == .Debug or optimize == .ReleaseSafe) .ReleaseSmall else optimize;
|
||||
|
||||
const arch = t.cpu.arch;
|
||||
const default_luajit = (is_linux and arch == .x86_64) or (is_darwin and arch == .aarch64);
|
||||
const use_luajit = b.option(bool, "luajit", "use luajit") orelse default_luajit;
|
||||
const host_use_luajit = if (cross_compiling) false else use_luajit;
|
||||
const E = enum { luajit, lua51 };
|
||||
|
||||
const ziglua = b.dependency("zlua", .{
|
||||
.target = target,
|
||||
.optimize = optimize_lua,
|
||||
.lang = if (use_luajit) E.luajit else E.lua51,
|
||||
.shared = false,
|
||||
});
|
||||
|
||||
const ziglua_host = if (cross_compiling) b.dependency("zlua", .{
|
||||
.target = target_host,
|
||||
.optimize = optimize_lua,
|
||||
.lang = if (host_use_luajit) E.luajit else E.lua51,
|
||||
.shared = false,
|
||||
}) else ziglua;
|
||||
|
||||
const lpeg = b.dependency("lpeg", .{});
|
||||
|
||||
const iconv = if (is_windows or is_darwin) b.lazyDependency("libiconv", .{ .target = target, .optimize = optimize }) else null;
|
||||
|
||||
// this is currently not necessary, as ziglua currently doesn't use lazy dependencies
|
||||
// to circumvent ziglua.artifact() failing in a bad way.
|
||||
const lua = lazyArtifact(ziglua, "lua") orelse return;
|
||||
if (cross_compiling) {
|
||||
_ = lazyArtifact(ziglua_host, "lua") orelse return;
|
||||
}
|
||||
// const lua = ziglua.artifact("lua");
|
||||
|
||||
const libuv_dep = b.dependency("libuv", .{ .target = target, .optimize = optimize });
|
||||
const libuv = libuv_dep.artifact("uv");
|
||||
const libluv = try build_lua.build_libluv(b, target, optimize, lua, libuv);
|
||||
|
||||
const libluv_host = if (cross_compiling) libluv_host: {
|
||||
const libuv_dep_host = b.dependency("libuv", .{ .target = target_host, .optimize = optimize_host });
|
||||
const libuv_host = libuv_dep_host.artifact("uv");
|
||||
break :libluv_host try build_lua.build_libluv(b, target_host, optimize_host, ziglua_host.artifact("lua"), libuv_host);
|
||||
} else libluv;
|
||||
|
||||
const utf8proc = b.dependency("utf8proc", .{ .target = target, .optimize = optimize });
|
||||
const unibilium = b.dependency("unibilium", .{ .target = target, .optimize = optimize });
|
||||
// TODO(bfredl): fix upstream bugs with UBSAN
|
||||
const treesitter = b.dependency("treesitter", .{ .target = target, .optimize = .ReleaseFast });
|
||||
|
||||
const nlua0 = build_lua.build_nlua0(b, target_host, optimize_host, host_use_luajit, ziglua_host, lpeg, libluv_host);
|
||||
|
||||
// usual caveat emptor: might need to force a rebuild if the only change is
|
||||
// addition of new .c files, as those are not seen by any hash
|
||||
const subdirs = [_][]const u8{
|
||||
"", // src/nvim itself
|
||||
"os/",
|
||||
"api/",
|
||||
"api/private/",
|
||||
"msgpack_rpc/",
|
||||
"tui/",
|
||||
"tui/termkey/",
|
||||
"event/",
|
||||
"eval/",
|
||||
"lib/",
|
||||
"lua/",
|
||||
"viml/",
|
||||
"viml/parser/",
|
||||
"vterm/",
|
||||
};
|
||||
|
||||
// source names _relative_ src/nvim/, not including other src/ subdircs
|
||||
var nvim_sources = try std.ArrayList(gen.SourceItem).initCapacity(b.allocator, 100);
|
||||
var nvim_headers = try std.ArrayList([]u8).initCapacity(b.allocator, 100);
|
||||
|
||||
// both source headers and the {module}.h.generated.h files
|
||||
var api_headers = try std.ArrayList(std.Build.LazyPath).initCapacity(b.allocator, 10);
|
||||
|
||||
// TODO(bfredl): these should just become subdirs..
|
||||
const windows_only = [_][]const u8{ "pty_proc_win.c", "pty_proc_win.h", "pty_conpty_win.c", "pty_conpty_win.h", "os_win_console.c", "win_defs.h" };
|
||||
const unix_only = [_][]const u8{ "unix_defs.h", "pty_proc_unix.c", "pty_proc_unix.h" };
|
||||
const exclude_list = if (is_windows) &unix_only else &windows_only;
|
||||
|
||||
const src_dir = b.build_root.handle;
|
||||
for (subdirs) |s| {
|
||||
var dir = try src_dir.openDir(b.fmt("src/nvim/{s}", .{s}), .{ .iterate = true });
|
||||
defer dir.close();
|
||||
var it = dir.iterateAssumeFirstIteration();
|
||||
const api_export = std.mem.eql(u8, s, "api/");
|
||||
const os_check = std.mem.eql(u8, s, "os/");
|
||||
entries: while (try it.next()) |entry| {
|
||||
if (entry.name.len < 3) continue;
|
||||
if (entry.name[0] < 'a' or entry.name[0] > 'z') continue;
|
||||
if (os_check) {
|
||||
for (exclude_list) |name| {
|
||||
if (std.mem.eql(u8, name, entry.name)) {
|
||||
continue :entries;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (std.mem.eql(u8, ".c", entry.name[entry.name.len - 2 ..])) {
|
||||
try nvim_sources.append(.{ .name = b.fmt("{s}{s}", .{ s, entry.name }), .api_export = api_export });
|
||||
}
|
||||
if (std.mem.eql(u8, ".h", entry.name[entry.name.len - 2 ..])) {
|
||||
try nvim_headers.append(b.fmt("{s}{s}", .{ s, entry.name }));
|
||||
if (api_export and !std.mem.eql(u8, "ui_events.in.h", entry.name)) {
|
||||
try api_headers.append(b.path(b.fmt("src/nvim/{s}{s}", .{ s, entry.name })));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const support_unittests = use_luajit;
|
||||
|
||||
const gen_config = b.addWriteFiles();
|
||||
|
||||
const version_lua = gen_config.add("nvim_version.lua", lua_version_info(b));
|
||||
|
||||
var config_str = b.fmt("zig build -Doptimize={s}", .{@tagName(optimize)});
|
||||
if (cross_compiling) {
|
||||
config_str = b.fmt("{s} -Dcross -Dtarget={s} (host: {s})", .{ config_str, try t.linuxTriple(b.allocator), try b.graph.host.result.linuxTriple(b.allocator) });
|
||||
}
|
||||
|
||||
const versiondef_step = b.addConfigHeader(.{ .style = .{ .cmake = b.path("cmake.config/versiondef.h.in") } }, .{
|
||||
.NVIM_VERSION_MAJOR = version.major,
|
||||
.NVIM_VERSION_MINOR = version.minor,
|
||||
.NVIM_VERSION_PATCH = version.patch,
|
||||
.NVIM_VERSION_PRERELEASE = version.prerelease,
|
||||
.NVIM_VERSION_MEDIUM = "",
|
||||
.VERSION_STRING = "TODO", // TODO(bfredl): not sure what to put here. summary already in "config_str"
|
||||
.CONFIG = config_str,
|
||||
});
|
||||
_ = gen_config.addCopyFile(versiondef_step.getOutput(), "auto/versiondef.h"); // run_preprocessor() workaronnd
|
||||
|
||||
const ptrwidth = t.ptrBitWidth() / 8;
|
||||
const sysconfig_step = b.addConfigHeader(.{ .style = .{ .cmake = b.path("cmake.config/config.h.in") } }, .{
|
||||
.SIZEOF_INT = t.cTypeByteSize(.int),
|
||||
.SIZEOF_INTMAX_T = t.cTypeByteSize(.longlong), // TODO
|
||||
.SIZEOF_LONG = t.cTypeByteSize(.long),
|
||||
.SIZEOF_SIZE_T = ptrwidth,
|
||||
.SIZEOF_VOID_PTR = ptrwidth,
|
||||
|
||||
.PROJECT_NAME = "nvim",
|
||||
|
||||
.HAVE__NSGETENVIRON = is_darwin,
|
||||
.HAVE_FD_CLOEXEC = modern_unix,
|
||||
.HAVE_FSEEKO = modern_unix,
|
||||
.HAVE_LANGINFO_H = modern_unix,
|
||||
.HAVE_NL_LANGINFO_CODESET = modern_unix,
|
||||
.HAVE_NL_MSG_CAT_CNTR = t.isGnuLibC(),
|
||||
.HAVE_PWD_FUNCS = modern_unix,
|
||||
.HAVE_READLINK = modern_unix,
|
||||
.HAVE_STRNLEN = modern_unix,
|
||||
.HAVE_STRCASECMP = modern_unix,
|
||||
.HAVE_STRINGS_H = modern_unix,
|
||||
.HAVE_STRNCASECMP = modern_unix,
|
||||
.HAVE_STRPTIME = modern_unix,
|
||||
.HAVE_XATTR = is_linux,
|
||||
.HAVE_SYS_SDT_H = false,
|
||||
.HAVE_SYS_UTSNAME_H = modern_unix,
|
||||
.HAVE_SYS_WAIT_H = false, // unused
|
||||
.HAVE_TERMIOS_H = modern_unix,
|
||||
.HAVE_WORKING_LIBINTL = t.isGnuLibC(),
|
||||
.UNIX = modern_unix,
|
||||
.CASE_INSENSITIVE_FILENAME = is_darwin or is_windows,
|
||||
.HAVE_SYS_UIO_H = modern_unix,
|
||||
.HAVE_READV = modern_unix,
|
||||
.HAVE_DIRFD_AND_FLOCK = modern_unix,
|
||||
.HAVE_FORKPTY = modern_unix and !is_darwin, // also on Darwin but we lack the headers :(
|
||||
.HAVE_BE64TOH = modern_unix and !is_darwin,
|
||||
.ORDER_BIG_ENDIAN = t.cpu.arch.endian() == .big,
|
||||
.ENDIAN_INCLUDE_FILE = "endian.h",
|
||||
.HAVE_EXECINFO_BACKTRACE = modern_unix and !t.isMuslLibC(),
|
||||
.HAVE_BUILTIN_ADD_OVERFLOW = true,
|
||||
.HAVE_WIMPLICIT_FALLTHROUGH_FLAG = true,
|
||||
.HAVE_BITSCANFORWARD64 = null,
|
||||
|
||||
.VTERM_TEST_FILE = "test/vterm_test_output", // TODO(bfredl): revisit when porting libvterm tests
|
||||
});
|
||||
|
||||
_ = gen_config.addCopyFile(sysconfig_step.getOutput(), "auto/config.h"); // run_preprocessor() workaronnd
|
||||
_ = gen_config.add("auto/pathdef.h", b.fmt(
|
||||
\\char *default_vim_dir = "/usr/local/share/nvim";
|
||||
\\char *default_vimruntime_dir = "";
|
||||
\\char *default_lib_dir = "/usr/local/lib/nvim";
|
||||
, .{}));
|
||||
|
||||
// TODO(bfredl): include git version when available
|
||||
const medium = b.fmt("v{}.{}.{}{s}+zig", .{ version.major, version.minor, version.patch, version.prerelease });
|
||||
const versiondef_git = gen_config.add("auto/versiondef_git.h", b.fmt(
|
||||
\\#define NVIM_VERSION_MEDIUM "{s}"
|
||||
\\#define NVIM_VERSION_BUILD "???"
|
||||
\\
|
||||
, .{medium}));
|
||||
|
||||
// TODO(zig): using getEmittedIncludeTree() is ugly af. we want unittests
|
||||
// to reuse the std.build.Module include_path thing
|
||||
const unittest_include_path = [_]LazyPath{
|
||||
b.path("src/"),
|
||||
gen_config.getDirectory(),
|
||||
lua.getEmittedIncludeTree(),
|
||||
libuv.getEmittedIncludeTree(),
|
||||
libluv.getEmittedIncludeTree(),
|
||||
utf8proc.artifact("utf8proc").getEmittedIncludeTree(),
|
||||
unibilium.artifact("unibilium").getEmittedIncludeTree(),
|
||||
treesitter.artifact("tree-sitter").getEmittedIncludeTree(),
|
||||
if (iconv) |dep| dep.artifact("iconv").getEmittedIncludeTree() else b.path("UNUSED_PATH/"),
|
||||
};
|
||||
|
||||
const gen_headers, const funcs_data = try gen.nvim_gen_sources(b, nlua0, &nvim_sources, &nvim_headers, &api_headers, versiondef_git, version_lua);
|
||||
|
||||
const test_config_step = b.addWriteFiles();
|
||||
_ = test_config_step.add("test/cmakeconfig/paths.lua", try test_config(b));
|
||||
|
||||
const test_gen_step = b.step("gen_headers", "debug: output generated headers");
|
||||
const config_install = b.addInstallDirectory(.{ .source_dir = gen_config.getDirectory(), .install_dir = .prefix, .install_subdir = "config/" });
|
||||
test_gen_step.dependOn(&config_install.step);
|
||||
test_gen_step.dependOn(&b.addInstallDirectory(.{ .source_dir = gen_headers.getDirectory(), .install_dir = .prefix, .install_subdir = "headers/" }).step);
|
||||
|
||||
const nvim_exe = b.addExecutable(.{
|
||||
.name = "nvim",
|
||||
.root_module = b.createModule(.{
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
}),
|
||||
});
|
||||
nvim_exe.rdynamic = true; // -E
|
||||
|
||||
nvim_exe.linkLibrary(lua);
|
||||
nvim_exe.linkLibrary(libuv);
|
||||
nvim_exe.linkLibrary(libluv);
|
||||
if (iconv) |dep| nvim_exe.linkLibrary(dep.artifact("iconv"));
|
||||
nvim_exe.linkLibrary(utf8proc.artifact("utf8proc"));
|
||||
nvim_exe.linkLibrary(unibilium.artifact("unibilium"));
|
||||
nvim_exe.linkLibrary(treesitter.artifact("tree-sitter"));
|
||||
if (is_windows) {
|
||||
nvim_exe.linkSystemLibrary("netapi32");
|
||||
}
|
||||
nvim_exe.addIncludePath(b.path("src"));
|
||||
nvim_exe.addIncludePath(gen_config.getDirectory());
|
||||
nvim_exe.addIncludePath(gen_headers.getDirectory());
|
||||
build_lua.add_lua_modules(nvim_exe.root_module, lpeg, use_luajit, false);
|
||||
|
||||
var unit_test_sources = try std.ArrayList([]u8).initCapacity(b.allocator, 10);
|
||||
if (support_unittests) {
|
||||
var unit_test_fixtures = try src_dir.openDir("test/unit/fixtures/", .{ .iterate = true });
|
||||
defer unit_test_fixtures.close();
|
||||
var it = unit_test_fixtures.iterateAssumeFirstIteration();
|
||||
while (try it.next()) |entry| {
|
||||
if (entry.name.len < 3) continue;
|
||||
if (std.mem.eql(u8, ".c", entry.name[entry.name.len - 2 ..])) {
|
||||
try unit_test_sources.append(b.fmt("test/unit/fixtures/{s}", .{entry.name}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const src_paths = try b.allocator.alloc([]u8, nvim_sources.items.len + unit_test_sources.items.len);
|
||||
for (nvim_sources.items, 0..) |s, i| {
|
||||
src_paths[i] = b.fmt("src/nvim/{s}", .{s.name});
|
||||
}
|
||||
@memcpy(src_paths[nvim_sources.items.len..], unit_test_sources.items);
|
||||
|
||||
const flags = [_][]const u8{
|
||||
"-std=gnu99",
|
||||
"-DZIG_BUILD",
|
||||
"-D_GNU_SOURCE",
|
||||
if (support_unittests) "-DUNIT_TESTING" else "",
|
||||
if (use_luajit) "" else "-DNVIM_VENDOR_BIT",
|
||||
if (is_windows) "-DMSWIN" else "",
|
||||
if (is_windows) "-DWIN32_LEAN_AND_MEAN" else "",
|
||||
if (is_windows) "-DUTF8PROC_STATIC" else "",
|
||||
};
|
||||
nvim_exe.addCSourceFiles(.{ .files = src_paths, .flags = &flags });
|
||||
|
||||
nvim_exe.addCSourceFiles(.{ .files = &.{
|
||||
"src/xdiff/xdiffi.c",
|
||||
"src/xdiff/xemit.c",
|
||||
"src/xdiff/xhistogram.c",
|
||||
"src/xdiff/xpatience.c",
|
||||
"src/xdiff/xprepare.c",
|
||||
"src/xdiff/xutils.c",
|
||||
"src/cjson/lua_cjson.c",
|
||||
"src/cjson/fpconv.c",
|
||||
"src/cjson/strbuf.c",
|
||||
}, .flags = &flags });
|
||||
|
||||
const nvim_exe_step = b.step("nvim_bin", "only the binary (not a fully working install!)");
|
||||
const nvim_exe_install = b.addInstallArtifact(nvim_exe, .{});
|
||||
|
||||
nvim_exe_step.dependOn(&nvim_exe_install.step);
|
||||
|
||||
const gen_runtime = try runtime.nvim_gen_runtime(b, nlua0, funcs_data);
|
||||
const runtime_install = b.addInstallDirectory(.{ .source_dir = gen_runtime.getDirectory(), .install_dir = .prefix, .install_subdir = "runtime/" });
|
||||
|
||||
const nvim = b.step("nvim", "build the editor");
|
||||
|
||||
nvim.dependOn(&nvim_exe_install.step);
|
||||
nvim.dependOn(&runtime_install.step);
|
||||
|
||||
const lua_dev_deps = b.dependency("lua_dev_deps", .{});
|
||||
|
||||
const test_deps = b.step("test_deps", "test prerequisites");
|
||||
test_deps.dependOn(&nvim_exe_install.step);
|
||||
test_deps.dependOn(&runtime_install.step);
|
||||
|
||||
test_deps.dependOn(test_fixture(b, "shell-test", null, target, optimize));
|
||||
test_deps.dependOn(test_fixture(b, "tty-test", libuv, target, optimize));
|
||||
test_deps.dependOn(test_fixture(b, "pwsh-test", null, target, optimize));
|
||||
test_deps.dependOn(test_fixture(b, "printargs-test", null, target, optimize));
|
||||
test_deps.dependOn(test_fixture(b, "printenv-test", null, target, optimize));
|
||||
test_deps.dependOn(test_fixture(b, "streams-test", libuv, target, optimize));
|
||||
|
||||
const parser_c = b.dependency("treesitter_c", .{ .target = target, .optimize = optimize });
|
||||
test_deps.dependOn(add_ts_parser(b, "c", parser_c.path("."), false, target, optimize));
|
||||
const parser_markdown = b.dependency("treesitter_markdown", .{ .target = target, .optimize = optimize });
|
||||
test_deps.dependOn(add_ts_parser(b, "markdown", parser_markdown.path("tree-sitter-markdown/"), true, target, optimize));
|
||||
test_deps.dependOn(add_ts_parser(b, "markdown_inline", parser_markdown.path("tree-sitter-markdown-inline/"), true, target, optimize));
|
||||
const parser_vim = b.dependency("treesitter_vim", .{ .target = target, .optimize = optimize });
|
||||
test_deps.dependOn(add_ts_parser(b, "vim", parser_vim.path("."), true, target, optimize));
|
||||
const parser_vimdoc = b.dependency("treesitter_vimdoc", .{ .target = target, .optimize = optimize });
|
||||
test_deps.dependOn(add_ts_parser(b, "vimdoc", parser_vimdoc.path("."), false, target, optimize));
|
||||
const parser_lua = b.dependency("treesitter_lua", .{ .target = target, .optimize = optimize });
|
||||
test_deps.dependOn(add_ts_parser(b, "lua", parser_lua.path("."), true, target, optimize));
|
||||
const parser_query = b.dependency("treesitter_query", .{ .target = target, .optimize = optimize });
|
||||
test_deps.dependOn(add_ts_parser(b, "query", parser_query.path("."), false, target, optimize));
|
||||
|
||||
const unit_headers: ?[]const LazyPath = if (support_unittests) &(unittest_include_path ++ .{gen_headers.getDirectory()}) else null;
|
||||
|
||||
try tests.test_steps(b, nvim_exe, test_deps, lua_dev_deps.path("."), test_config_step.getDirectory(), unit_headers);
|
||||
}
|
||||
|
||||
pub fn test_fixture(
|
||||
b: *std.Build,
|
||||
name: []const u8,
|
||||
libuv: ?*std.Build.Step.Compile,
|
||||
target: std.Build.ResolvedTarget,
|
||||
optimize: std.builtin.OptimizeMode,
|
||||
) *std.Build.Step {
|
||||
const fixture = b.addExecutable(.{
|
||||
.name = name,
|
||||
.root_module = b.createModule(.{
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
}),
|
||||
});
|
||||
const source = if (std.mem.eql(u8, name, "pwsh-test")) "shell-test" else name;
|
||||
fixture.addCSourceFile(.{ .file = b.path(b.fmt("./test/functional/fixtures/{s}.c", .{source})) });
|
||||
fixture.linkLibC();
|
||||
if (libuv) |uv| fixture.linkLibrary(uv);
|
||||
return &b.addInstallArtifact(fixture, .{}).step;
|
||||
}
|
||||
|
||||
pub fn add_ts_parser(
|
||||
b: *std.Build,
|
||||
name: []const u8,
|
||||
parser_dir: LazyPath,
|
||||
scanner: bool,
|
||||
target: std.Build.ResolvedTarget,
|
||||
optimize: std.builtin.OptimizeMode,
|
||||
) *std.Build.Step {
|
||||
const parser = b.addLibrary(.{
|
||||
.name = name,
|
||||
.root_module = b.createModule(.{
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
}),
|
||||
.linkage = .dynamic,
|
||||
});
|
||||
parser.addCSourceFile(.{ .file = parser_dir.path(b, "src/parser.c") });
|
||||
if (scanner) parser.addCSourceFile(.{ .file = parser_dir.path(b, "src/scanner.c") });
|
||||
parser.addIncludePath(parser_dir.path(b, "src"));
|
||||
parser.linkLibC();
|
||||
|
||||
const parser_install = b.addInstallArtifact(parser, .{ .dest_sub_path = b.fmt("parser/{s}.so", .{name}) });
|
||||
return &parser_install.step;
|
||||
}
|
||||
|
||||
pub fn lua_version_info(b: *std.Build) []u8 {
|
||||
const v = version;
|
||||
return b.fmt(
|
||||
\\return {{
|
||||
\\ {{"major", {}}},
|
||||
\\ {{"minor", {}}},
|
||||
\\ {{"patch", {}}},
|
||||
\\ {{"prerelease", {}}},
|
||||
\\ {{"api_level", {}}},
|
||||
\\ {{"api_compatible", {}}},
|
||||
\\ {{"api_prerelease", {}}},
|
||||
\\}}
|
||||
, .{ v.major, v.minor, v.patch, v.prerelease.len > 0, v.api_level, v.api_level_compat, v.api_prerelease });
|
||||
}
|
||||
|
||||
pub fn test_config(b: *std.Build) ![]u8 {
|
||||
var buf: [std.fs.max_path_bytes]u8 = undefined;
|
||||
const src_path = try b.build_root.handle.realpath(".", &buf);
|
||||
|
||||
// we don't use test/cmakeconfig/paths.lua.in because it contains cmake specific logic
|
||||
return b.fmt(
|
||||
\\local M = {{}}
|
||||
\\
|
||||
\\M.apple_sysroot = ""
|
||||
\\M.translations_enabled = "$ENABLE_TRANSLATIONS" == "ON"
|
||||
\\M.is_asan = "$ENABLE_ASAN_UBSAN" == "ON"
|
||||
\\M.is_zig_build = true
|
||||
\\M.vterm_test_file = "test/vterm_test_output"
|
||||
\\M.test_build_dir = "{[bin_dir]s}" -- bull
|
||||
\\M.test_source_path = "{[src_path]s}"
|
||||
\\M.test_lua_prg = ""
|
||||
\\M.test_luajit_prg = ""
|
||||
\\ -- include path passed on the cmdline, see test/lua_runner.lua
|
||||
\\M.include_paths = _G.c_include_path or {{}}
|
||||
\\
|
||||
\\return M
|
||||
, .{ .bin_dir = b.install_path, .src_path = src_path });
|
||||
}
|
@@ -1,72 +0,0 @@
|
||||
.{
|
||||
.name = .neovim,
|
||||
.fingerprint = 0x66eb090879307a38,
|
||||
.version = "0.12.0",
|
||||
.minimum_zig_version = "0.14.0",
|
||||
|
||||
.dependencies = .{
|
||||
.zlua = .{
|
||||
.url = "git+https://github.com/natecraddock/ziglua#6889b2d90ee6ae96810a9f04ec7c62d9aa91d088",
|
||||
.hash = "zlua-0.1.0-hGRpCxctBQDEQgDArJ0Kc4RDIsD-Hw3pw9pPPw_kGmmY",
|
||||
},
|
||||
.lpeg = .{
|
||||
.url = "https://github.com/neovim/deps/raw/d495ee6f79e7962a53ad79670cb92488abe0b9b4/opt/lpeg-1.1.0.tar.gz",
|
||||
.hash = "N-V-__8AAMnaAwCEutreuREG3QayBVEZqUTDQFY1Nsrv2OIt",
|
||||
},
|
||||
.luv = .{
|
||||
.url = "git+https://github.com/luvit/luv?ref=1.51.0-1#4c9fbc6cf6f3338bb0e0426710cf885ee557b540",
|
||||
.hash = "N-V-__8AAMlNDwCY07jUoMiq3iORXdZy0uFWKiHsy8MaDBJA",
|
||||
},
|
||||
.lua_compat53 = .{
|
||||
.url = "https://github.com/lunarmodules/lua-compat-5.3/archive/v0.13.tar.gz",
|
||||
.hash = "N-V-__8AADi-AwDnVoXwDCQvv2wcYOmN0bJLqZ44J3lwoQY2",
|
||||
},
|
||||
.treesitter = .{
|
||||
.url = "git+https://github.com/tree-sitter/tree-sitter#d87921bb9c39b0b06c811f2082f9a9991cdca027",
|
||||
.hash = "tree_sitter-0.26.0-Tw2sRxO7CwC0NyDrSygSi7UXRHMNUFEF8GRq6dK81lRF",
|
||||
},
|
||||
.libuv = .{
|
||||
.url = "git+https://github.com/allyourcodebase/libuv#a2dfd385bd2a00d6d290fda85a40a55a9d6cffc5",
|
||||
.hash = "libuv-1.51.0-htqqv6liAADxBLIBCZT-qUh_3nRRwtNYsOFQOUmrd_sx",
|
||||
},
|
||||
.utf8proc = .{ .path = "./deps/utf8proc/" },
|
||||
.unibilium = .{ .path = "./deps/unibilium/" },
|
||||
.libiconv = .{
|
||||
.url = "git+https://github.com/allyourcodebase/libiconv#9def4c8a1743380e85bcedb80f2c15b455e236f3",
|
||||
.hash = "libiconv-1.18.0-p9sJwWnqAACzVYeWgXB5r5lOQ74XwTPlptixV0JPRO28",
|
||||
.lazy = true,
|
||||
},
|
||||
.lua_dev_deps = .{
|
||||
.url = "https://github.com/neovim/deps/raw/06ef2b58b0876f8de1a3f5a710473dcd7afff251/opt/lua-dev-deps.tar.gz",
|
||||
.hash = "N-V-__8AAGevEQCHAkCozca5AIdN9DFc3Luf3g3r2AcbyOrm",
|
||||
},
|
||||
.treesitter_c = .{
|
||||
.url = "git+https://github.com/tree-sitter/tree-sitter-c?ref=v0.24.1#7fa1be1b694b6e763686793d97da01f36a0e5c12",
|
||||
.hash = "N-V-__8AANxPSABzw3WBTSH_YkwaGAfrK6PBqAMqQedkDDim",
|
||||
},
|
||||
.treesitter_markdown = .{
|
||||
.url = "git+https://github.com/tree-sitter-grammars/tree-sitter-markdown?ref=v0.5.0#afaa4138517363362f54c89330c9d79391e81168",
|
||||
.hash = "N-V-__8AAIIZUwD3CGdyI2DiHu7Suj2jIF_EAVlM6REFGwju",
|
||||
},
|
||||
.treesitter_lua = .{
|
||||
.url = "git+https://github.com/tree-sitter-grammars/tree-sitter-lua?ref=v0.4.0#4569d1c361129e71a205b94a05e158bd71b1709f",
|
||||
.hash = "N-V-__8AAEF5CABqSL9zqc03aQsT6Nni54ZCcL98pnuDL2D3",
|
||||
},
|
||||
.treesitter_vim = .{
|
||||
.url = "git+https://github.com/tree-sitter-grammars/tree-sitter-vim?ref=v0.7.0#3dd4747082d1b717b8978211c06ef7b6cd16125b",
|
||||
.hash = "N-V-__8AAMArVAB4uo2wg2XRs8HBviQ4Pq366cC_iRolX4Vc",
|
||||
},
|
||||
.treesitter_vimdoc = .{
|
||||
.url = "git+https://github.com/neovim/tree-sitter-vimdoc?ref=v4.0.0#9f6191a98702edc1084245abd5523279d4b681fb",
|
||||
.hash = "N-V-__8AAI4YCgD7OqxCEAmz2RqT_ohl6eA4F0fGMtLIe7nb",
|
||||
},
|
||||
.treesitter_query = .{
|
||||
.url = "git+https://github.com/tree-sitter-grammars/tree-sitter-query?ref=v0.6.2#8a43889f89fd0667289936341bff3a77bafade17",
|
||||
.hash = "N-V-__8AAARLBACBLGiXGFTijEzLv8AwiqT_kJpmVjir1BgX",
|
||||
},
|
||||
},
|
||||
.paths = .{
|
||||
// TODO(bfredl): explicitly list the subdirs which actually are used
|
||||
"",
|
||||
},
|
||||
}
|
@@ -12,10 +12,6 @@
|
||||
#endif
|
||||
|
||||
#define NVIM_VERSION_CFLAGS "${VERSION_STRING}"
|
||||
#ifdef ZIG_BUILD
|
||||
# define NVIM_VERSION_BUILD_TYPE "${CONFIG}"
|
||||
#else
|
||||
# define NVIM_VERSION_BUILD_TYPE "$<CONFIG>"
|
||||
#endif
|
||||
#define NVIM_VERSION_BUILD_TYPE "$<CONFIG>"
|
||||
|
||||
#endif // AUTO_VERSIONDEF_H
|
||||
|
@@ -42,7 +42,7 @@ if(APPLE)
|
||||
endif()
|
||||
|
||||
if(UNIX)
|
||||
BuildLuajit(INSTALL_COMMAND ${BUILDCMD_UNIX}
|
||||
BuildLuaJit(INSTALL_COMMAND ${BUILDCMD_UNIX}
|
||||
CC=${DEPS_C_COMPILER} PREFIX=${DEPS_INSTALL_DIR}
|
||||
${DEPLOYMENT_TARGET} install)
|
||||
|
||||
@@ -53,7 +53,7 @@ elseif(MINGW)
|
||||
else()
|
||||
set(LUAJIT_MAKE_PRG ${CMAKE_MAKE_PROGRAM})
|
||||
endif()
|
||||
BuildLuajit(BUILD_COMMAND ${LUAJIT_MAKE_PRG} CC=${DEPS_C_COMPILER}
|
||||
BuildLuaJit(BUILD_COMMAND ${LUAJIT_MAKE_PRG} CC=${DEPS_C_COMPILER}
|
||||
PREFIX=${DEPS_INSTALL_DIR}
|
||||
CFLAGS+=-DLUA_USE_APICHECK
|
||||
CFLAGS+=-funwind-tables
|
||||
@@ -75,7 +75,7 @@ elseif(MINGW)
|
||||
)
|
||||
elseif(MSVC)
|
||||
|
||||
BuildLuajit(
|
||||
BuildLuaJit(
|
||||
BUILD_COMMAND ${CMAKE_COMMAND} -E chdir ${DEPS_BUILD_DIR}/src/luajit/src ${DEPS_BUILD_DIR}/src/luajit/src/msvcbuild.bat
|
||||
INSTALL_COMMAND ${CMAKE_COMMAND} -E make_directory ${DEPS_BIN_DIR}
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${DEPS_BUILD_DIR}/src/luajit/src/luajit.exe ${DEPS_BIN_DIR}
|
||||
|
@@ -1,8 +1,8 @@
|
||||
LIBUV_URL https://github.com/libuv/libuv/archive/v1.51.0.tar.gz
|
||||
LIBUV_SHA256 27e55cf7083913bfb6826ca78cde9de7647cded648d35f24163f2d31bb9f51cd
|
||||
LIBUV_URL https://github.com/libuv/libuv/archive/v1.50.0.tar.gz
|
||||
LIBUV_SHA256 b1ec56444ee3f1e10c8bd3eed16ba47016ed0b94fe42137435aaf2e0bd574579
|
||||
|
||||
LUAJIT_URL https://github.com/luajit/luajit/archive/871db2c84ecefd70a850e03a6c340214a81739f0.tar.gz
|
||||
LUAJIT_SHA256 ab3f16d82df6946543565cfb0d2810d387d79a3a43e0431695b03466188e2680
|
||||
LUAJIT_URL https://github.com/luajit/luajit/archive/538a82133ad6fddfd0ca64de167c4aca3bc1a2da.tar.gz
|
||||
LUAJIT_SHA256 7acbc36be8f21072422eb9a5e5fc468d0eaa55bec1b70260d651e845684621e2
|
||||
|
||||
LUA_URL https://www.lua.org/ftp/lua-5.1.5.tar.gz
|
||||
LUA_SHA256 2640fc56a795f29d28ef15e13c34a47e223960b0240e8cb0a82d9b0738695333
|
||||
@@ -10,8 +10,8 @@ LUA_SHA256 2640fc56a795f29d28ef15e13c34a47e223960b0240e8cb0a82d9b0738695333
|
||||
UNIBILIUM_URL https://github.com/neovim/unibilium/archive/v2.1.2.tar.gz
|
||||
UNIBILIUM_SHA256 370ecb07fbbc20d91d1b350c55f1c806b06bf86797e164081ccc977fc9b3af7a
|
||||
|
||||
LUV_URL https://github.com/luvit/luv/archive/1.51.0-1.tar.gz
|
||||
LUV_SHA256 d4a11178ae8e16ba5886799ea91905dd9b0b479c75aebd67866d37373e41526f
|
||||
LUV_URL https://github.com/luvit/luv/archive/1.50.0-1.tar.gz
|
||||
LUV_SHA256 bb4f0570571e40c1d2a7644f6f9c1309a6ccdb19bf4d397e8d7bfd0c6b88e613
|
||||
|
||||
LPEG_URL https://github.com/neovim/deps/raw/d495ee6f79e7962a53ad79670cb92488abe0b9b4/opt/lpeg-1.1.0.tar.gz
|
||||
LPEG_SHA256 4b155d67d2246c1ffa7ad7bc466c1ea899bbc40fef0257cc9c03cecbaed4352a
|
||||
@@ -46,13 +46,13 @@ TREESITTER_QUERY_URL https://github.com/tree-sitter-grammars/tree-sitter-query/a
|
||||
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.8.tar.gz
|
||||
TREESITTER_SHA256 178b575244d967f4920a4642408dc4edf6de96948d37d7f06e5b78acee9c0b4e
|
||||
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
|
||||
|
||||
UNCRUSTIFY_URL https://github.com/uncrustify/uncrustify/archive/uncrustify-0.81.0.tar.gz
|
||||
UNCRUSTIFY_SHA256 484623dc16b92206adc6ac0770077c6c67c6e441102148c2a121a19549330ff9
|
||||
UNCRUSTIFY_URL https://github.com/uncrustify/uncrustify/archive/uncrustify-0.80.1.tar.gz
|
||||
UNCRUSTIFY_SHA256 0e2616ec2f78e12816388c513f7060072ff7942b42f1175eb28b24cb75aaec48
|
||||
LUA_DEV_DEPS_URL https://github.com/neovim/deps/raw/06ef2b58b0876f8de1a3f5a710473dcd7afff251/opt/lua-dev-deps.tar.gz
|
||||
LUA_DEV_DEPS_SHA256 49f8399e453103064a23c65534f266f3067cda716b6502f016bfafeed5799354
|
||||
|
@@ -1,4 +1,4 @@
|
||||
if(CMAKE_SYSTEM_PROCESSOR MATCHES "^(arm64|ARM64|aarch64)$")
|
||||
if(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64")
|
||||
set(CMAKE_SYSTEM_PROCESSOR arm64)
|
||||
endif()
|
||||
|
||||
@@ -27,13 +27,9 @@ set(CPACK_RESOURCE_FILE_README ${PROJECT_SOURCE_DIR}/README.md)
|
||||
|
||||
|
||||
if(WIN32)
|
||||
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).
|
||||
|
@@ -7,7 +7,6 @@ set(ENV{XDG_DATA_HOME} ${BUILD_DIR}/Xtest_xdg/share)
|
||||
set(ENV{XDG_STATE_HOME} ${BUILD_DIR}/Xtest_xdg/state)
|
||||
unset(ENV{XDG_DATA_DIRS})
|
||||
unset(ENV{NVIM}) # Clear $NVIM in case tests are running from Nvim. #11009
|
||||
unset(ENV{TMUX}) # Nvim TUI shouldn't think it's running in tmux. #34173
|
||||
|
||||
# TODO(dundargoc): The CIRRUS_CI environment variable isn't passed to here from
|
||||
# the main CMakeLists.txt, so we have to manually pass it to this script and
|
||||
@@ -69,7 +68,7 @@ endif()
|
||||
execute_process(
|
||||
# Note: because of "-ll" (low-level interpreter mode), some modules like
|
||||
# _editor.lua are not loaded.
|
||||
COMMAND ${NVIM_PRG} -ll ${WORKING_DIR}/test/lua_runner.lua ${DEPS_INSTALL_DIR}/share/lua/5.1/ busted -v -o test.busted.outputHandlers.nvim
|
||||
COMMAND ${NVIM_PRG} -ll ${WORKING_DIR}/test/lua_runner.lua ${DEPS_INSTALL_DIR} busted -v -o test.busted.outputHandlers.nvim
|
||||
--lazy --helper=${TEST_DIR}/${TEST_TYPE}/preload.lua
|
||||
--lpath=${BUILD_DIR}/?.lua
|
||||
--lpath=${WORKING_DIR}/src/?.lua
|
||||
@@ -79,6 +78,7 @@ execute_process(
|
||||
${TEST_PATH}
|
||||
TIMEOUT $ENV{TEST_TIMEOUT}
|
||||
WORKING_DIRECTORY ${WORKING_DIR}
|
||||
ERROR_VARIABLE err
|
||||
RESULT_VARIABLE res
|
||||
${EXTRA_ARGS})
|
||||
|
||||
@@ -87,6 +87,11 @@ file(REMOVE_RECURSE ${RM_FILES})
|
||||
|
||||
if(res)
|
||||
message(STATUS "Tests exited non-zero: ${res}")
|
||||
if("${err}" STREQUAL "")
|
||||
message(STATUS "No output to stderr.")
|
||||
else()
|
||||
message(STATUS "Output to stderr:\n${err}")
|
||||
endif()
|
||||
|
||||
# Dump the logfile on CI (if not displayed and moved already).
|
||||
if(CI_BUILD)
|
||||
|
30
deps/unibilium/build.zig
vendored
30
deps/unibilium/build.zig
vendored
@@ -1,30 +0,0 @@
|
||||
const std = @import("std");
|
||||
|
||||
pub fn build(b: *std.Build) !void {
|
||||
const target = b.standardTargetOptions(.{});
|
||||
const optimize = b.standardOptimizeOption(.{});
|
||||
|
||||
const upstream = b.dependency("unibilium", .{});
|
||||
const lib = b.addLibrary(.{
|
||||
.name = "unibilium",
|
||||
.linkage = .static,
|
||||
.root_module = b.createModule(.{
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
}),
|
||||
});
|
||||
|
||||
lib.addIncludePath(upstream.path(""));
|
||||
|
||||
lib.installHeader(upstream.path("unibilium.h"), "unibilium.h");
|
||||
|
||||
lib.linkLibC();
|
||||
|
||||
lib.addCSourceFiles(.{ .root = upstream.path(""), .files = &.{
|
||||
"unibilium.c",
|
||||
"uninames.c",
|
||||
"uniutil.c",
|
||||
}, .flags = &.{"-DTERMINFO_DIRS=\"/etc/terminfo:/usr/share/terminfo\""} });
|
||||
|
||||
b.installArtifact(lib);
|
||||
}
|
12
deps/unibilium/build.zig.zon
vendored
12
deps/unibilium/build.zig.zon
vendored
@@ -1,12 +0,0 @@
|
||||
.{
|
||||
.name = "unibilium",
|
||||
.version = "2.1.2",
|
||||
.paths = .{""},
|
||||
|
||||
.dependencies = .{
|
||||
.unibilium = .{
|
||||
.url = "git+https://github.com/neovim/unibilium?ref=v2.1.2#bfcb0350129dd76893bc90399cf37c45812268a2",
|
||||
.hash = "N-V-__8AADO1CgCggvx73yptnBlXbEm7TjOSO6VGIqc0CvYR",
|
||||
},
|
||||
},
|
||||
}
|
27
deps/utf8proc/build.zig
vendored
27
deps/utf8proc/build.zig
vendored
@@ -1,27 +0,0 @@
|
||||
const std = @import("std");
|
||||
|
||||
pub fn build(b: *std.Build) !void {
|
||||
const target = b.standardTargetOptions(.{});
|
||||
const optimize = b.standardOptimizeOption(.{});
|
||||
|
||||
const upstream = b.dependency("utf8proc", .{});
|
||||
const lib = b.addLibrary(.{
|
||||
.name = "utf8proc",
|
||||
.linkage = .static,
|
||||
.root_module = b.createModule(.{
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
}),
|
||||
});
|
||||
|
||||
lib.addIncludePath(upstream.path(""));
|
||||
lib.installHeader(upstream.path("utf8proc.h"), "utf8proc.h");
|
||||
|
||||
lib.linkLibC();
|
||||
|
||||
lib.addCSourceFiles(.{ .root = upstream.path(""), .files = &.{
|
||||
"utf8proc.c",
|
||||
}, .flags = &.{"-DUTF8PROC_STATIC"} });
|
||||
|
||||
b.installArtifact(lib);
|
||||
}
|
12
deps/utf8proc/build.zig.zon
vendored
12
deps/utf8proc/build.zig.zon
vendored
@@ -1,12 +0,0 @@
|
||||
.{
|
||||
.name = "utf8proc",
|
||||
.version = "2.10.0",
|
||||
.paths = .{""},
|
||||
|
||||
.dependencies = .{
|
||||
.utf8proc = .{
|
||||
.url = "git+https://github.com/JuliaStrings/utf8proc?ref=v2.10.0#a1b99daa2a3393884220264c927a48ba1251a9c6",
|
||||
.hash = "N-V-__8AAPJfKADYDOC95xuKyudrlob6eFqgzfFl8NbpOoU9",
|
||||
},
|
||||
},
|
||||
}
|
@@ -12,17 +12,12 @@ get_directory_property(LUA_GEN_DEPS DIRECTORY ${PROJECT_SOURCE_DIR}/src/nvim DEF
|
||||
|
||||
add_custom_command(OUTPUT ${GENERATED_SYN_VIM}
|
||||
COMMAND ${LUA_GEN} ${SYN_VIM_GENERATOR} ${GENERATED_SYN_VIM} ${FUNCS_DATA}
|
||||
${PROJECT_SOURCE_DIR}/src/nvim/options.lua
|
||||
${PROJECT_SOURCE_DIR}/src/nvim/auevents.lua
|
||||
${PROJECT_SOURCE_DIR}/src/nvim/ex_cmds.lua
|
||||
${PROJECT_SOURCE_DIR}/src/nvim/vvars.lua
|
||||
DEPENDS
|
||||
${LUA_GEN_DEPS}
|
||||
${SYN_VIM_GENERATOR}
|
||||
${PROJECT_SOURCE_DIR}/src/nvim/ex_cmds.lua
|
||||
${PROJECT_SOURCE_DIR}/src/nvim/auevents.lua
|
||||
${PROJECT_SOURCE_DIR}/src/nvim/options.lua
|
||||
${PROJECT_SOURCE_DIR}/src/nvim/vvars.lua
|
||||
${PROJECT_SOURCE_DIR}/src/nvim/eval.c
|
||||
${FUNCS_DATA}
|
||||
)
|
||||
|
859
runtime/autoload/ccomplete.lua
Normal file
859
runtime/autoload/ccomplete.lua
Normal file
@@ -0,0 +1,859 @@
|
||||
----------------------------------------
|
||||
-- This file is generated via github.com/tjdevries/vim9jit
|
||||
-- For any bugs, please first consider reporting there.
|
||||
----------------------------------------
|
||||
|
||||
-- Ignore "value assigned to a local variable is unused" because
|
||||
-- we can't guarantee that local variables will be used by plugins
|
||||
-- luacheck: ignore
|
||||
--- @diagnostic disable
|
||||
|
||||
local vim9 = require('_vim9script')
|
||||
local M = {}
|
||||
local prepended = nil
|
||||
local grepCache = nil
|
||||
local Complete = nil
|
||||
local GetAddition = nil
|
||||
local Tag2item = nil
|
||||
local Dict2info = nil
|
||||
local ParseTagline = nil
|
||||
local Tagline2item = nil
|
||||
local Tagcmd2extra = nil
|
||||
local Nextitem = nil
|
||||
local StructMembers = nil
|
||||
local SearchMembers = nil
|
||||
-- vim9script
|
||||
|
||||
-- # Vim completion script
|
||||
-- # Language: C
|
||||
-- # Maintainer: The Vim Project <https://github.com/vim/vim>
|
||||
-- # Last Change: 2023 Aug 10
|
||||
-- # Rewritten in Vim9 script by github user lacygoill
|
||||
-- # Former Maintainer: Bram Moolenaar <Bram@vim.org>
|
||||
|
||||
prepended = ''
|
||||
grepCache = vim.empty_dict()
|
||||
|
||||
-- # This function is used for the 'omnifunc' option.
|
||||
|
||||
Complete = function(findstart, abase)
|
||||
findstart = vim9.bool(findstart)
|
||||
if vim9.bool(findstart) then
|
||||
-- # Locate the start of the item, including ".", "->" and "[...]".
|
||||
local line = vim9.fn.getline('.')
|
||||
local start = vim9.fn.charcol('.') - 1
|
||||
local lastword = -1
|
||||
while start > 0 do
|
||||
if vim9.ops.RegexpMatches(vim9.index(line, vim9.ops.Minus(start, 1)), '\\w') then
|
||||
start = start - 1
|
||||
elseif
|
||||
vim9.bool(vim9.ops.RegexpMatches(vim9.index(line, vim9.ops.Minus(start, 1)), '\\.'))
|
||||
then
|
||||
if lastword == -1 then
|
||||
lastword = start
|
||||
end
|
||||
start = start - 1
|
||||
elseif
|
||||
vim9.bool(
|
||||
start > 1
|
||||
and vim9.index(line, vim9.ops.Minus(start, 2)) == '-'
|
||||
and vim9.index(line, vim9.ops.Minus(start, 1)) == '>'
|
||||
)
|
||||
then
|
||||
if lastword == -1 then
|
||||
lastword = start
|
||||
end
|
||||
start = vim9.ops.Minus(start, 2)
|
||||
elseif vim9.bool(vim9.index(line, vim9.ops.Minus(start, 1)) == ']') then
|
||||
-- # Skip over [...].
|
||||
local n = 0
|
||||
start = start - 1
|
||||
while start > 0 do
|
||||
start = start - 1
|
||||
if vim9.index(line, start) == '[' then
|
||||
if n == 0 then
|
||||
break
|
||||
end
|
||||
n = n - 1
|
||||
elseif vim9.bool(vim9.index(line, start) == ']') then
|
||||
n = n + 1
|
||||
end
|
||||
end
|
||||
else
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
-- # Return the column of the last word, which is going to be changed.
|
||||
-- # Remember the text that comes before it in prepended.
|
||||
if lastword == -1 then
|
||||
prepended = ''
|
||||
return vim9.fn.byteidx(line, start)
|
||||
end
|
||||
prepended = vim9.slice(line, start, vim9.ops.Minus(lastword, 1))
|
||||
return vim9.fn.byteidx(line, lastword)
|
||||
end
|
||||
|
||||
-- # Return list of matches.
|
||||
|
||||
local base = prepended .. abase
|
||||
|
||||
-- # Don't do anything for an empty base, would result in all the tags in the
|
||||
-- # tags file.
|
||||
if base == '' then
|
||||
return {}
|
||||
end
|
||||
|
||||
-- # init cache for vimgrep to empty
|
||||
grepCache = {}
|
||||
|
||||
-- # Split item in words, keep empty word after "." or "->".
|
||||
-- # "aa" -> ['aa'], "aa." -> ['aa', ''], "aa.bb" -> ['aa', 'bb'], etc.
|
||||
-- # We can't use split, because we need to skip nested [...].
|
||||
-- # "aa[...]" -> ['aa', '[...]'], "aa.bb[...]" -> ['aa', 'bb', '[...]'], etc.
|
||||
local items = {}
|
||||
local s = 0
|
||||
local arrays = 0
|
||||
while 1 do
|
||||
local e = vim9.fn.charidx(base, vim9.fn.match(base, '\\.\\|->\\|\\[', s))
|
||||
if e < 0 then
|
||||
if s == 0 or vim9.index(base, vim9.ops.Minus(s, 1)) ~= ']' then
|
||||
vim9.fn.add(items, vim9.slice(base, s, nil))
|
||||
end
|
||||
break
|
||||
end
|
||||
if s == 0 or vim9.index(base, vim9.ops.Minus(s, 1)) ~= ']' then
|
||||
vim9.fn.add(items, vim9.slice(base, s, vim9.ops.Minus(e, 1)))
|
||||
end
|
||||
if vim9.index(base, e) == '.' then
|
||||
-- # skip over '.'
|
||||
s = vim9.ops.Plus(e, 1)
|
||||
elseif vim9.bool(vim9.index(base, e) == '-') then
|
||||
-- # skip over '->'
|
||||
s = vim9.ops.Plus(e, 2)
|
||||
else
|
||||
-- # Skip over [...].
|
||||
local n = 0
|
||||
s = e
|
||||
e = e + 1
|
||||
while e < vim9.fn.strcharlen(base) do
|
||||
if vim9.index(base, e) == ']' then
|
||||
if n == 0 then
|
||||
break
|
||||
end
|
||||
n = n - 1
|
||||
elseif vim9.bool(vim9.index(base, e) == '[') then
|
||||
n = n + 1
|
||||
end
|
||||
e = e + 1
|
||||
end
|
||||
e = e + 1
|
||||
vim9.fn.add(items, vim9.slice(base, s, vim9.ops.Minus(e, 1)))
|
||||
arrays = arrays + 1
|
||||
s = e
|
||||
end
|
||||
end
|
||||
|
||||
-- # Find the variable items[0].
|
||||
-- # 1. in current function (like with "gd")
|
||||
-- # 2. in tags file(s) (like with ":tag")
|
||||
-- # 3. in current file (like with "gD")
|
||||
local res = {}
|
||||
if vim9.fn.searchdecl(vim9.index(items, 0), false, true) == 0 then
|
||||
-- # Found, now figure out the type.
|
||||
-- # TODO: join previous line if it makes sense
|
||||
local line = vim9.fn.getline('.')
|
||||
local col = vim9.fn.charcol('.')
|
||||
if vim9.fn.stridx(vim9.slice(line, nil, vim9.ops.Minus(col, 1)), ';') >= 0 then
|
||||
-- # Handle multiple declarations on the same line.
|
||||
local col2 = vim9.ops.Minus(col, 1)
|
||||
while vim9.index(line, col2) ~= ';' do
|
||||
col2 = col2 - 1
|
||||
end
|
||||
line = vim9.slice(line, vim9.ops.Plus(col2, 1), nil)
|
||||
col = vim9.ops.Minus(col, col2)
|
||||
end
|
||||
if vim9.fn.stridx(vim9.slice(line, nil, vim9.ops.Minus(col, 1)), ',') >= 0 then
|
||||
-- # Handle multiple declarations on the same line in a function
|
||||
-- # declaration.
|
||||
local col2 = vim9.ops.Minus(col, 1)
|
||||
while vim9.index(line, col2) ~= ',' do
|
||||
col2 = col2 - 1
|
||||
end
|
||||
if
|
||||
vim9.ops.RegexpMatches(
|
||||
vim9.slice(line, vim9.ops.Plus(col2, 1), vim9.ops.Minus(col, 1)),
|
||||
' *[^ ][^ ]* *[^ ]'
|
||||
)
|
||||
then
|
||||
line = vim9.slice(line, vim9.ops.Plus(col2, 1), nil)
|
||||
col = vim9.ops.Minus(col, col2)
|
||||
end
|
||||
end
|
||||
if vim9.fn.len(items) == 1 then
|
||||
-- # Completing one word and it's a local variable: May add '[', '.' or
|
||||
-- # '->'.
|
||||
local match = vim9.index(items, 0)
|
||||
local kind = 'v'
|
||||
if vim9.fn.match(line, '\\<' .. match .. '\\s*\\[') > 0 then
|
||||
match = match .. '['
|
||||
else
|
||||
res = Nextitem(vim9.slice(line, nil, vim9.ops.Minus(col, 1)), { '' }, 0, true)
|
||||
if vim9.fn.len(res) > 0 then
|
||||
-- # There are members, thus add "." or "->".
|
||||
if vim9.fn.match(line, '\\*[ \\t(]*' .. match .. '\\>') > 0 then
|
||||
match = match .. '->'
|
||||
else
|
||||
match = match .. '.'
|
||||
end
|
||||
end
|
||||
end
|
||||
res = { { ['match'] = match, ['tagline'] = '', ['kind'] = kind, ['info'] = line } }
|
||||
elseif vim9.bool(vim9.fn.len(items) == vim9.ops.Plus(arrays, 1)) then
|
||||
-- # Completing one word and it's a local array variable: build tagline
|
||||
-- # from declaration line
|
||||
local match = vim9.index(items, 0)
|
||||
local kind = 'v'
|
||||
local tagline = '\t/^' .. line .. '$/'
|
||||
res = { { ['match'] = match, ['tagline'] = tagline, ['kind'] = kind, ['info'] = line } }
|
||||
else
|
||||
-- # Completing "var.", "var.something", etc.
|
||||
res =
|
||||
Nextitem(vim9.slice(line, nil, vim9.ops.Minus(col, 1)), vim9.slice(items, 1, nil), 0, true)
|
||||
end
|
||||
end
|
||||
|
||||
if vim9.fn.len(items) == 1 or vim9.fn.len(items) == vim9.ops.Plus(arrays, 1) then
|
||||
-- # Only one part, no "." or "->": complete from tags file.
|
||||
local tags = {}
|
||||
if vim9.fn.len(items) == 1 then
|
||||
tags = vim9.fn.taglist('^' .. base)
|
||||
else
|
||||
tags = vim9.fn.taglist('^' .. vim9.index(items, 0) .. '$')
|
||||
end
|
||||
|
||||
vim9.fn_mut('filter', {
|
||||
vim9.fn_mut('filter', {
|
||||
tags,
|
||||
function(_, v)
|
||||
return vim9.ternary(vim9.fn.has_key(v, 'kind'), function()
|
||||
return v.kind ~= 'm'
|
||||
end, true)
|
||||
end,
|
||||
}, { replace = 0 }),
|
||||
function(_, v)
|
||||
return vim9.ops.Or(
|
||||
vim9.ops.Or(
|
||||
vim9.prefix['Bang'](vim9.fn.has_key(v, 'static')),
|
||||
vim9.prefix['Bang'](vim9.index(v, 'static'))
|
||||
),
|
||||
vim9.fn.bufnr('%') == vim9.fn.bufnr(vim9.index(v, 'filename'))
|
||||
)
|
||||
end,
|
||||
}, { replace = 0 })
|
||||
|
||||
res = vim9.fn.extend(
|
||||
res,
|
||||
vim9.fn.map(tags, function(_, v)
|
||||
return Tag2item(v)
|
||||
end)
|
||||
)
|
||||
end
|
||||
|
||||
if vim9.fn.len(res) == 0 then
|
||||
-- # Find the variable in the tags file(s)
|
||||
local diclist = vim9.fn.filter(
|
||||
vim9.fn.taglist('^' .. vim9.index(items, 0) .. '$'),
|
||||
function(_, v)
|
||||
return vim9.ternary(vim9.fn.has_key(v, 'kind'), function()
|
||||
return v.kind ~= 'm'
|
||||
end, true)
|
||||
end
|
||||
)
|
||||
|
||||
res = {}
|
||||
|
||||
for _, i in vim9.iter(vim9.fn.range(vim9.fn.len(diclist))) do
|
||||
-- # New ctags has the "typeref" field. Patched version has "typename".
|
||||
if vim9.bool(vim9.fn.has_key(vim9.index(diclist, i), 'typename')) then
|
||||
res = vim9.fn.extend(
|
||||
res,
|
||||
StructMembers(
|
||||
vim9.index(vim9.index(diclist, i), 'typename'),
|
||||
vim9.slice(items, 1, nil),
|
||||
true
|
||||
)
|
||||
)
|
||||
elseif vim9.bool(vim9.fn.has_key(vim9.index(diclist, i), 'typeref')) then
|
||||
res = vim9.fn.extend(
|
||||
res,
|
||||
StructMembers(
|
||||
vim9.index(vim9.index(diclist, i), 'typeref'),
|
||||
vim9.slice(items, 1, nil),
|
||||
true
|
||||
)
|
||||
)
|
||||
end
|
||||
|
||||
-- # For a variable use the command, which must be a search pattern that
|
||||
-- # shows the declaration of the variable.
|
||||
if vim9.index(vim9.index(diclist, i), 'kind') == 'v' then
|
||||
local line = vim9.index(vim9.index(diclist, i), 'cmd')
|
||||
if vim9.slice(line, nil, 1) == '/^' then
|
||||
local col =
|
||||
vim9.fn.charidx(line, vim9.fn.match(line, '\\<' .. vim9.index(items, 0) .. '\\>'))
|
||||
res = vim9.fn.extend(
|
||||
res,
|
||||
Nextitem(
|
||||
vim9.slice(line, 2, vim9.ops.Minus(col, 1)),
|
||||
vim9.slice(items, 1, nil),
|
||||
0,
|
||||
true
|
||||
)
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if vim9.fn.len(res) == 0 and vim9.fn.searchdecl(vim9.index(items, 0), true) == 0 then
|
||||
-- # Found, now figure out the type.
|
||||
-- # TODO: join previous line if it makes sense
|
||||
local line = vim9.fn.getline('.')
|
||||
local col = vim9.fn.charcol('.')
|
||||
res =
|
||||
Nextitem(vim9.slice(line, nil, vim9.ops.Minus(col, 1)), vim9.slice(items, 1, nil), 0, true)
|
||||
end
|
||||
|
||||
-- # If the last item(s) are [...] they need to be added to the matches.
|
||||
local last = vim9.fn.len(items) - 1
|
||||
local brackets = ''
|
||||
while last >= 0 do
|
||||
if vim9.index(vim9.index(items, last), 0) ~= '[' then
|
||||
break
|
||||
end
|
||||
brackets = vim9.index(items, last) .. brackets
|
||||
last = last - 1
|
||||
end
|
||||
|
||||
return vim9.fn.map(res, function(_, v)
|
||||
return Tagline2item(v, brackets)
|
||||
end)
|
||||
end
|
||||
M['Complete'] = Complete
|
||||
|
||||
GetAddition = function(line, match, memarg, bracket)
|
||||
bracket = vim9.bool(bracket)
|
||||
-- # Guess if the item is an array.
|
||||
if vim9.bool(vim9.ops.And(bracket, vim9.fn.match(line, match .. '\\s*\\[') > 0)) then
|
||||
return '['
|
||||
end
|
||||
|
||||
-- # Check if the item has members.
|
||||
if vim9.fn.len(SearchMembers(memarg, { '' }, false)) > 0 then
|
||||
-- # If there is a '*' before the name use "->".
|
||||
if vim9.fn.match(line, '\\*[ \\t(]*' .. match .. '\\>') > 0 then
|
||||
return '->'
|
||||
else
|
||||
return '.'
|
||||
end
|
||||
end
|
||||
return ''
|
||||
end
|
||||
|
||||
Tag2item = function(val)
|
||||
-- # Turn the tag info "val" into an item for completion.
|
||||
-- # "val" is is an item in the list returned by taglist().
|
||||
-- # If it is a variable we may add "." or "->". Don't do it for other types,
|
||||
-- # such as a typedef, by not including the info that GetAddition() uses.
|
||||
local res = vim9.convert.decl_dict({ ['match'] = vim9.index(val, 'name') })
|
||||
|
||||
res[vim9.index_expr('extra')] =
|
||||
Tagcmd2extra(vim9.index(val, 'cmd'), vim9.index(val, 'name'), vim9.index(val, 'filename'))
|
||||
|
||||
local s = Dict2info(val)
|
||||
if s ~= '' then
|
||||
res[vim9.index_expr('info')] = s
|
||||
end
|
||||
|
||||
res[vim9.index_expr('tagline')] = ''
|
||||
if vim9.bool(vim9.fn.has_key(val, 'kind')) then
|
||||
local kind = vim9.index(val, 'kind')
|
||||
res[vim9.index_expr('kind')] = kind
|
||||
if kind == 'v' then
|
||||
res[vim9.index_expr('tagline')] = '\t' .. vim9.index(val, 'cmd')
|
||||
res[vim9.index_expr('dict')] = val
|
||||
elseif vim9.bool(kind == 'f') then
|
||||
res[vim9.index_expr('match')] = vim9.index(val, 'name') .. '('
|
||||
end
|
||||
end
|
||||
|
||||
return res
|
||||
end
|
||||
|
||||
Dict2info = function(dict)
|
||||
-- # Use all the items in dictionary for the "info" entry.
|
||||
local info = ''
|
||||
|
||||
for _, k in vim9.iter(vim9.fn_mut('sort', { vim9.fn.keys(dict) }, { replace = 0 })) do
|
||||
info = info .. k .. vim9.fn['repeat'](' ', 10 - vim9.fn.strlen(k))
|
||||
if k == 'cmd' then
|
||||
info = info
|
||||
.. vim9.fn.substitute(
|
||||
vim9.fn.matchstr(vim9.index(dict, 'cmd'), '/^\\s*\\zs.*\\ze$/'),
|
||||
'\\\\\\(.\\)',
|
||||
'\\1',
|
||||
'g'
|
||||
)
|
||||
else
|
||||
local dictk = vim9.index(dict, k)
|
||||
if vim9.fn.typename(dictk) ~= 'string' then
|
||||
info = info .. vim9.fn.string(dictk)
|
||||
else
|
||||
info = info .. dictk
|
||||
end
|
||||
end
|
||||
info = info .. '\n'
|
||||
end
|
||||
|
||||
return info
|
||||
end
|
||||
|
||||
ParseTagline = function(line)
|
||||
-- # Parse a tag line and return a dictionary with items like taglist()
|
||||
local l = vim9.fn.split(line, '\t')
|
||||
local d = vim.empty_dict()
|
||||
if vim9.fn.len(l) >= 3 then
|
||||
d[vim9.index_expr('name')] = vim9.index(l, 0)
|
||||
d[vim9.index_expr('filename')] = vim9.index(l, 1)
|
||||
d[vim9.index_expr('cmd')] = vim9.index(l, 2)
|
||||
local n = 2
|
||||
if vim9.ops.RegexpMatches(vim9.index(l, 2), '^/') then
|
||||
-- # Find end of cmd, it may contain Tabs.
|
||||
while n < vim9.fn.len(l) and vim9.ops.NotRegexpMatches(vim9.index(l, n), '/;"$') do
|
||||
n = n + 1
|
||||
d[vim9.index_expr('cmd')] = vim9.index(d, 'cmd') .. ' ' .. vim9.index(l, n)
|
||||
end
|
||||
end
|
||||
|
||||
for _, i in vim9.iter(vim9.fn.range(vim9.ops.Plus(n, 1), vim9.fn.len(l) - 1)) do
|
||||
if vim9.index(l, i) == 'file:' then
|
||||
d[vim9.index_expr('static')] = 1
|
||||
elseif vim9.bool(vim9.ops.NotRegexpMatches(vim9.index(l, i), ':')) then
|
||||
d[vim9.index_expr('kind')] = vim9.index(l, i)
|
||||
else
|
||||
d[vim9.index_expr(vim9.fn.matchstr(vim9.index(l, i), '[^:]*'))] =
|
||||
vim9.fn.matchstr(vim9.index(l, i), ':\\zs.*')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return d
|
||||
end
|
||||
|
||||
Tagline2item = function(val, brackets)
|
||||
-- # Turn a match item "val" into an item for completion.
|
||||
-- # "val['match']" is the matching item.
|
||||
-- # "val['tagline']" is the tagline in which the last part was found.
|
||||
local line = vim9.index(val, 'tagline')
|
||||
local add = GetAddition(line, vim9.index(val, 'match'), { val }, brackets == '')
|
||||
local res = vim9.convert.decl_dict({ ['word'] = vim9.index(val, 'match') .. brackets .. add })
|
||||
|
||||
if vim9.bool(vim9.fn.has_key(val, 'info')) then
|
||||
-- # Use info from Tag2item().
|
||||
res[vim9.index_expr('info')] = vim9.index(val, 'info')
|
||||
else
|
||||
-- # Parse the tag line and add each part to the "info" entry.
|
||||
local s = Dict2info(ParseTagline(line))
|
||||
if s ~= '' then
|
||||
res[vim9.index_expr('info')] = s
|
||||
end
|
||||
end
|
||||
|
||||
if vim9.bool(vim9.fn.has_key(val, 'kind')) then
|
||||
res[vim9.index_expr('kind')] = vim9.index(val, 'kind')
|
||||
elseif vim9.bool(add == '(') then
|
||||
res[vim9.index_expr('kind')] = 'f'
|
||||
else
|
||||
local s = vim9.fn.matchstr(line, '\\t\\(kind:\\)\\=\\zs\\S\\ze\\(\\t\\|$\\)')
|
||||
if s ~= '' then
|
||||
res[vim9.index_expr('kind')] = s
|
||||
end
|
||||
end
|
||||
|
||||
if vim9.bool(vim9.fn.has_key(val, 'extra')) then
|
||||
res[vim9.index_expr('menu')] = vim9.index(val, 'extra')
|
||||
return res
|
||||
end
|
||||
|
||||
-- # Isolate the command after the tag and filename.
|
||||
local s = vim9.fn.matchstr(
|
||||
line,
|
||||
'[^\\t]*\\t[^\\t]*\\t\\zs\\(/^.*$/\\|[^\\t]*\\)\\ze\\(;"\\t\\|\\t\\|$\\)'
|
||||
)
|
||||
if s ~= '' then
|
||||
res[vim9.index_expr('menu')] = Tagcmd2extra(
|
||||
s,
|
||||
vim9.index(val, 'match'),
|
||||
vim9.fn.matchstr(line, '[^\\t]*\\t\\zs[^\\t]*\\ze\\t')
|
||||
)
|
||||
end
|
||||
return res
|
||||
end
|
||||
|
||||
Tagcmd2extra = function(cmd, name, fname)
|
||||
-- # Turn a command from a tag line to something that is useful in the menu
|
||||
local x = ''
|
||||
if vim9.ops.RegexpMatches(cmd, '^/^') then
|
||||
-- # The command is a search command, useful to see what it is.
|
||||
x = vim9.fn.substitute(
|
||||
vim9.fn.substitute(
|
||||
vim9.fn.matchstr(cmd, '^/^\\s*\\zs.*\\ze$/'),
|
||||
'\\<' .. name .. '\\>',
|
||||
'@@',
|
||||
''
|
||||
),
|
||||
'\\\\\\(.\\)',
|
||||
'\\1',
|
||||
'g'
|
||||
) .. ' - ' .. fname
|
||||
elseif vim9.bool(vim9.ops.RegexpMatches(cmd, '^\\d*$')) then
|
||||
-- # The command is a line number, the file name is more useful.
|
||||
x = fname .. ' - ' .. cmd
|
||||
else
|
||||
-- # Not recognized, use command and file name.
|
||||
x = cmd .. ' - ' .. fname
|
||||
end
|
||||
return x
|
||||
end
|
||||
|
||||
Nextitem = function(lead, items, depth, all)
|
||||
all = vim9.bool(all)
|
||||
-- # Find composing type in "lead" and match items[0] with it.
|
||||
-- # Repeat this recursively for items[1], if it's there.
|
||||
-- # When resolving typedefs "depth" is used to avoid infinite recursion.
|
||||
-- # Return the list of matches.
|
||||
|
||||
-- # Use the text up to the variable name and split it in tokens.
|
||||
local tokens = vim9.fn.split(lead, '\\s\\+\\|\\<')
|
||||
|
||||
-- # Try to recognize the type of the variable. This is rough guessing...
|
||||
local res = {}
|
||||
|
||||
local body = function(_, tidx)
|
||||
-- # Skip tokens starting with a non-ID character.
|
||||
if vim9.ops.NotRegexpMatches(vim9.index(tokens, tidx), '^\\h') then
|
||||
return vim9.ITER_CONTINUE
|
||||
end
|
||||
|
||||
-- # Recognize "struct foobar" and "union foobar".
|
||||
-- # Also do "class foobar" when it's C++ after all (doesn't work very well
|
||||
-- # though).
|
||||
if
|
||||
(
|
||||
vim9.index(tokens, tidx) == 'struct'
|
||||
or vim9.index(tokens, tidx) == 'union'
|
||||
or vim9.index(tokens, tidx) == 'class'
|
||||
) and vim9.ops.Plus(tidx, 1) < vim9.fn.len(tokens)
|
||||
then
|
||||
res = StructMembers(
|
||||
vim9.index(tokens, tidx) .. ':' .. vim9.index(tokens, vim9.ops.Plus(tidx, 1)),
|
||||
items,
|
||||
all
|
||||
)
|
||||
return vim9.ITER_BREAK
|
||||
end
|
||||
|
||||
-- # TODO: add more reserved words
|
||||
if
|
||||
vim9.fn.index(
|
||||
{ 'int', 'short', 'char', 'float', 'double', 'static', 'unsigned', 'extern' },
|
||||
vim9.index(tokens, tidx)
|
||||
) >= 0
|
||||
then
|
||||
return vim9.ITER_CONTINUE
|
||||
end
|
||||
|
||||
-- # Use the tags file to find out if this is a typedef.
|
||||
local diclist = vim9.fn.taglist('^' .. vim9.index(tokens, tidx) .. '$')
|
||||
|
||||
local body = function(_, tagidx)
|
||||
local item = vim9.convert.decl_dict(vim9.index(diclist, tagidx))
|
||||
|
||||
-- # New ctags has the "typeref" field. Patched version has "typename".
|
||||
if vim9.bool(vim9.fn.has_key(item, 'typeref')) then
|
||||
res = vim9.fn.extend(res, StructMembers(vim9.index(item, 'typeref'), items, all))
|
||||
return vim9.ITER_CONTINUE
|
||||
end
|
||||
if vim9.bool(vim9.fn.has_key(item, 'typename')) then
|
||||
res = vim9.fn.extend(res, StructMembers(vim9.index(item, 'typename'), items, all))
|
||||
return vim9.ITER_CONTINUE
|
||||
end
|
||||
|
||||
-- # Only handle typedefs here.
|
||||
if vim9.index(item, 'kind') ~= 't' then
|
||||
return vim9.ITER_CONTINUE
|
||||
end
|
||||
|
||||
-- # Skip matches local to another file.
|
||||
if
|
||||
vim9.bool(
|
||||
vim9.ops.And(
|
||||
vim9.ops.And(vim9.fn.has_key(item, 'static'), vim9.index(item, 'static')),
|
||||
vim9.fn.bufnr('%') ~= vim9.fn.bufnr(vim9.index(item, 'filename'))
|
||||
)
|
||||
)
|
||||
then
|
||||
return vim9.ITER_CONTINUE
|
||||
end
|
||||
|
||||
-- # For old ctags we recognize "typedef struct aaa" and
|
||||
-- # "typedef union bbb" in the tags file command.
|
||||
local cmd = vim9.index(item, 'cmd')
|
||||
local ei = vim9.fn.charidx(cmd, vim9.fn.matchend(cmd, 'typedef\\s\\+'))
|
||||
if ei > 1 then
|
||||
local cmdtokens = vim9.fn.split(vim9.slice(cmd, ei, nil), '\\s\\+\\|\\<')
|
||||
if vim9.fn.len(cmdtokens) > 1 then
|
||||
if
|
||||
vim9.index(cmdtokens, 0) == 'struct'
|
||||
or vim9.index(cmdtokens, 0) == 'union'
|
||||
or vim9.index(cmdtokens, 0) == 'class'
|
||||
then
|
||||
local name = ''
|
||||
-- # Use the first identifier after the "struct" or "union"
|
||||
|
||||
for _, ti in vim9.iter(vim9.fn.range((vim9.fn.len(cmdtokens) - 1))) do
|
||||
if vim9.ops.RegexpMatches(vim9.index(cmdtokens, ti), '^\\w') then
|
||||
name = vim9.index(cmdtokens, ti)
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if name ~= '' then
|
||||
res = vim9.fn.extend(
|
||||
res,
|
||||
StructMembers(vim9.index(cmdtokens, 0) .. ':' .. name, items, all)
|
||||
)
|
||||
end
|
||||
elseif vim9.bool(depth < 10) then
|
||||
-- # Could be "typedef other_T some_T".
|
||||
res = vim9.fn.extend(
|
||||
res,
|
||||
Nextitem(vim9.index(cmdtokens, 0), items, vim9.ops.Plus(depth, 1), all)
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return vim9.ITER_DEFAULT
|
||||
end
|
||||
|
||||
for _, tagidx in vim9.iter(vim9.fn.range(vim9.fn.len(diclist))) do
|
||||
local nvim9_status, nvim9_ret = body(_, tagidx)
|
||||
if nvim9_status == vim9.ITER_BREAK then
|
||||
break
|
||||
elseif nvim9_status == vim9.ITER_RETURN then
|
||||
return nvim9_ret
|
||||
end
|
||||
end
|
||||
|
||||
if vim9.fn.len(res) > 0 then
|
||||
return vim9.ITER_BREAK
|
||||
end
|
||||
|
||||
return vim9.ITER_DEFAULT
|
||||
end
|
||||
|
||||
for _, tidx in vim9.iter(vim9.fn.range(vim9.fn.len(tokens))) do
|
||||
local nvim9_status, nvim9_ret = body(_, tidx)
|
||||
if nvim9_status == vim9.ITER_BREAK then
|
||||
break
|
||||
elseif nvim9_status == vim9.ITER_RETURN then
|
||||
return nvim9_ret
|
||||
end
|
||||
end
|
||||
|
||||
return res
|
||||
end
|
||||
|
||||
StructMembers = function(atypename, items, all)
|
||||
all = vim9.bool(all)
|
||||
|
||||
-- # Search for members of structure "typename" in tags files.
|
||||
-- # Return a list with resulting matches.
|
||||
-- # Each match is a dictionary with "match" and "tagline" entries.
|
||||
-- # When "all" is true find all, otherwise just return 1 if there is any member.
|
||||
|
||||
-- # Todo: What about local structures?
|
||||
local fnames = vim9.fn.join(vim9.fn.map(vim9.fn.tagfiles(), function(_, v)
|
||||
return vim9.fn.escape(v, ' \\#%')
|
||||
end))
|
||||
if fnames == '' then
|
||||
return {}
|
||||
end
|
||||
|
||||
local typename = atypename
|
||||
local qflist = {}
|
||||
local cached = 0
|
||||
local n = ''
|
||||
if vim9.bool(vim9.prefix['Bang'](all)) then
|
||||
n = '1'
|
||||
if vim9.bool(vim9.fn.has_key(grepCache, typename)) then
|
||||
qflist = vim9.index(grepCache, typename)
|
||||
cached = 1
|
||||
end
|
||||
else
|
||||
n = ''
|
||||
end
|
||||
if vim9.bool(vim9.prefix['Bang'](cached)) then
|
||||
while 1 do
|
||||
vim.api.nvim_command(
|
||||
'silent! keepjumps noautocmd '
|
||||
.. n
|
||||
.. 'vimgrep '
|
||||
.. '/\\t'
|
||||
.. typename
|
||||
.. '\\(\\t\\|$\\)/j '
|
||||
.. fnames
|
||||
)
|
||||
|
||||
qflist = vim9.fn.getqflist()
|
||||
if vim9.fn.len(qflist) > 0 or vim9.fn.match(typename, '::') < 0 then
|
||||
break
|
||||
end
|
||||
-- # No match for "struct:context::name", remove "context::" and try again.
|
||||
typename = vim9.fn.substitute(typename, ':[^:]*::', ':', '')
|
||||
end
|
||||
|
||||
if vim9.bool(vim9.prefix['Bang'](all)) then
|
||||
-- # Store the result to be able to use it again later.
|
||||
grepCache[vim9.index_expr(typename)] = qflist
|
||||
end
|
||||
end
|
||||
|
||||
-- # Skip over [...] items
|
||||
local idx = 0
|
||||
local target = ''
|
||||
while 1 do
|
||||
if idx >= vim9.fn.len(items) then
|
||||
target = ''
|
||||
break
|
||||
end
|
||||
if vim9.index(vim9.index(items, idx), 0) ~= '[' then
|
||||
target = vim9.index(items, idx)
|
||||
break
|
||||
end
|
||||
idx = idx + 1
|
||||
end
|
||||
-- # Put matching members in matches[].
|
||||
local matches = {}
|
||||
|
||||
for _, l in vim9.iter(qflist) do
|
||||
local memb = vim9.fn.matchstr(vim9.index(l, 'text'), '[^\\t]*')
|
||||
if vim9.ops.RegexpMatches(memb, '^' .. target) then
|
||||
-- # Skip matches local to another file.
|
||||
if
|
||||
vim9.fn.match(vim9.index(l, 'text'), '\tfile:') < 0
|
||||
or vim9.fn.bufnr('%')
|
||||
== vim9.fn.bufnr(vim9.fn.matchstr(vim9.index(l, 'text'), '\\t\\zs[^\\t]*'))
|
||||
then
|
||||
local item =
|
||||
vim9.convert.decl_dict({ ['match'] = memb, ['tagline'] = vim9.index(l, 'text') })
|
||||
|
||||
-- # Add the kind of item.
|
||||
local s =
|
||||
vim9.fn.matchstr(vim9.index(l, 'text'), '\\t\\(kind:\\)\\=\\zs\\S\\ze\\(\\t\\|$\\)')
|
||||
if s ~= '' then
|
||||
item[vim9.index_expr('kind')] = s
|
||||
if s == 'f' then
|
||||
item[vim9.index_expr('match')] = memb .. '('
|
||||
end
|
||||
end
|
||||
|
||||
vim9.fn.add(matches, item)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if vim9.fn.len(matches) > 0 then
|
||||
-- # Skip over next [...] items
|
||||
idx = idx + 1
|
||||
while 1 do
|
||||
if idx >= vim9.fn.len(items) then
|
||||
return matches
|
||||
end
|
||||
if vim9.index(vim9.index(items, idx), 0) ~= '[' then
|
||||
break
|
||||
end
|
||||
idx = idx + 1
|
||||
end
|
||||
|
||||
-- # More items following. For each of the possible members find the
|
||||
-- # matching following members.
|
||||
return SearchMembers(matches, vim9.slice(items, idx, nil), all)
|
||||
end
|
||||
|
||||
-- # Failed to find anything.
|
||||
return {}
|
||||
end
|
||||
|
||||
SearchMembers = function(matches, items, all)
|
||||
all = vim9.bool(all)
|
||||
|
||||
-- # For matching members, find matches for following items.
|
||||
-- # When "all" is true find all, otherwise just return 1 if there is any member.
|
||||
local res = {}
|
||||
|
||||
for _, i in vim9.iter(vim9.fn.range(vim9.fn.len(matches))) do
|
||||
local typename = ''
|
||||
local line = ''
|
||||
if vim9.bool(vim9.fn.has_key(vim9.index(matches, i), 'dict')) then
|
||||
if vim9.bool(vim9.fn.has_key(vim9.index(vim9.index(matches, i), 'dict'), 'typename')) then
|
||||
typename = vim9.index(vim9.index(vim9.index(matches, i), 'dict'), 'typename')
|
||||
elseif vim9.bool(vim9.fn.has_key(vim9.index(vim9.index(matches, i), 'dict'), 'typeref')) then
|
||||
typename = vim9.index(vim9.index(vim9.index(matches, i), 'dict'), 'typeref')
|
||||
end
|
||||
line = '\t' .. vim9.index(vim9.index(vim9.index(matches, i), 'dict'), 'cmd')
|
||||
else
|
||||
line = vim9.index(vim9.index(matches, i), 'tagline')
|
||||
local eb = vim9.fn.matchend(line, '\\ttypename:')
|
||||
local e = vim9.fn.charidx(line, eb)
|
||||
if e < 0 then
|
||||
eb = vim9.fn.matchend(line, '\\ttyperef:')
|
||||
e = vim9.fn.charidx(line, eb)
|
||||
end
|
||||
if e > 0 then
|
||||
-- # Use typename field
|
||||
typename = vim9.fn.matchstr(line, '[^\\t]*', eb)
|
||||
end
|
||||
end
|
||||
|
||||
if typename ~= '' then
|
||||
res = vim9.fn.extend(res, StructMembers(typename, items, all))
|
||||
else
|
||||
-- # Use the search command (the declaration itself).
|
||||
local sb = vim9.fn.match(line, '\\t\\zs/^')
|
||||
local s = vim9.fn.charidx(line, sb)
|
||||
if s > 0 then
|
||||
local e = vim9.fn.charidx(
|
||||
line,
|
||||
vim9.fn.match(line, '\\<' .. vim9.index(vim9.index(matches, i), 'match') .. '\\>', sb)
|
||||
)
|
||||
if e > 0 then
|
||||
res =
|
||||
vim9.fn.extend(res, Nextitem(vim9.slice(line, s, vim9.ops.Minus(e, 1)), items, 0, all))
|
||||
end
|
||||
end
|
||||
end
|
||||
if vim9.bool(vim9.ops.And(vim9.prefix['Bang'](all), vim9.fn.len(res) > 0)) then
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
return res
|
||||
end
|
||||
|
||||
-- #}}}1
|
||||
|
||||
-- # vim: noet sw=2 sts=2
|
||||
return M
|
@@ -1,682 +1,8 @@
|
||||
" Vim completion script
|
||||
" Language: C
|
||||
" Maintainer: Bram Moolenaar <Bram@vim.org>
|
||||
" Last Change: 2020 Nov 14
|
||||
|
||||
let s:cpo_save = &cpo
|
||||
set cpo&vim
|
||||
|
||||
" This function is used for the 'omnifunc' option.
|
||||
func ccomplete#Complete(findstart, base)
|
||||
if a:findstart
|
||||
" Locate the start of the item, including ".", "->" and "[...]".
|
||||
let line = getline('.')
|
||||
let start = col('.') - 1
|
||||
let lastword = -1
|
||||
while start > 0
|
||||
if line[start - 1] =~ '\w'
|
||||
let start -= 1
|
||||
elseif line[start - 1] =~ '\.'
|
||||
if lastword == -1
|
||||
let lastword = start
|
||||
endif
|
||||
let start -= 1
|
||||
elseif start > 1 && line[start - 2] == '-' && line[start - 1] == '>'
|
||||
if lastword == -1
|
||||
let lastword = start
|
||||
endif
|
||||
let start -= 2
|
||||
elseif line[start - 1] == ']'
|
||||
" Skip over [...].
|
||||
let n = 0
|
||||
let start -= 1
|
||||
while start > 0
|
||||
let start -= 1
|
||||
if line[start] == '['
|
||||
if n == 0
|
||||
break
|
||||
endif
|
||||
let n -= 1
|
||||
elseif line[start] == ']' " nested []
|
||||
let n += 1
|
||||
endif
|
||||
endwhile
|
||||
else
|
||||
break
|
||||
endif
|
||||
endwhile
|
||||
|
||||
" Return the column of the last word, which is going to be changed.
|
||||
" Remember the text that comes before it in s:prepended.
|
||||
if lastword == -1
|
||||
let s:prepended = ''
|
||||
return start
|
||||
endif
|
||||
let s:prepended = strpart(line, start, lastword - start)
|
||||
return lastword
|
||||
endif
|
||||
|
||||
" Return list of matches.
|
||||
|
||||
let base = s:prepended . a:base
|
||||
|
||||
" Don't do anything for an empty base, would result in all the tags in the
|
||||
" tags file.
|
||||
if base == ''
|
||||
return []
|
||||
endif
|
||||
|
||||
" init cache for vimgrep to empty
|
||||
let s:grepCache = {}
|
||||
|
||||
" Split item in words, keep empty word after "." or "->".
|
||||
" "aa" -> ['aa'], "aa." -> ['aa', ''], "aa.bb" -> ['aa', 'bb'], etc.
|
||||
" We can't use split, because we need to skip nested [...].
|
||||
" "aa[...]" -> ['aa', '[...]'], "aa.bb[...]" -> ['aa', 'bb', '[...]'], etc.
|
||||
let items = []
|
||||
let s = 0
|
||||
let arrays = 0
|
||||
while 1
|
||||
let e = match(base, '\.\|->\|\[', s)
|
||||
if e < 0
|
||||
if s == 0 || base[s - 1] != ']'
|
||||
call add(items, strpart(base, s))
|
||||
endif
|
||||
break
|
||||
endif
|
||||
if s == 0 || base[s - 1] != ']'
|
||||
call add(items, strpart(base, s, e - s))
|
||||
endif
|
||||
if base[e] == '.'
|
||||
let s = e + 1 " skip over '.'
|
||||
elseif base[e] == '-'
|
||||
let s = e + 2 " skip over '->'
|
||||
else
|
||||
" Skip over [...].
|
||||
let n = 0
|
||||
let s = e
|
||||
let e += 1
|
||||
while e < len(base)
|
||||
if base[e] == ']'
|
||||
if n == 0
|
||||
break
|
||||
endif
|
||||
let n -= 1
|
||||
elseif base[e] == '[' " nested [...]
|
||||
let n += 1
|
||||
endif
|
||||
let e += 1
|
||||
endwhile
|
||||
let e += 1
|
||||
call add(items, strpart(base, s, e - s))
|
||||
let arrays += 1
|
||||
let s = e
|
||||
endif
|
||||
endwhile
|
||||
|
||||
if complete_check()
|
||||
" return v:none
|
||||
return []
|
||||
endif
|
||||
|
||||
" Find the variable items[0].
|
||||
" 1. in current function (like with "gd")
|
||||
" 2. in tags file(s) (like with ":tag")
|
||||
" 3. in current file (like with "gD")
|
||||
let res = []
|
||||
if searchdecl(items[0], 0, 1) == 0
|
||||
" Found, now figure out the type.
|
||||
" TODO: join previous line if it makes sense
|
||||
let line = getline('.')
|
||||
let col = col('.')
|
||||
if stridx(strpart(line, 0, col), ';') != -1
|
||||
" Handle multiple declarations on the same line.
|
||||
let col2 = col - 1
|
||||
while line[col2] != ';'
|
||||
if complete_check()
|
||||
return res
|
||||
endif
|
||||
let col2 -= 1
|
||||
endwhile
|
||||
let line = strpart(line, col2 + 1)
|
||||
let col -= col2
|
||||
endif
|
||||
if stridx(strpart(line, 0, col), ',') != -1
|
||||
" Handle multiple declarations on the same line in a function
|
||||
" declaration.
|
||||
let col2 = col - 1
|
||||
while line[col2] != ','
|
||||
if complete_check()
|
||||
return res
|
||||
endif
|
||||
let col2 -= 1
|
||||
endwhile
|
||||
if strpart(line, col2 + 1, col - col2 - 1) =~ ' *[^ ][^ ]* *[^ ]'
|
||||
let line = strpart(line, col2 + 1)
|
||||
let col -= col2
|
||||
endif
|
||||
endif
|
||||
if len(items) == 1
|
||||
" Completing one word and it's a local variable: May add '[', '.' or
|
||||
" '->'.
|
||||
let match = items[0]
|
||||
let kind = 'v'
|
||||
if match(line, '\<' . match . '\s*\[') > 0
|
||||
let match .= '['
|
||||
else
|
||||
let res = s:Nextitem(strpart(line, 0, col), [''], 0, 1)
|
||||
if len(res) > 0
|
||||
" There are members, thus add "." or "->".
|
||||
if match(line, '\*[ \t(]*' . match . '\>') > 0
|
||||
let match .= '->'
|
||||
else
|
||||
let match .= '.'
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
let res = [{'match': match, 'tagline' : '', 'kind' : kind, 'info' : line}]
|
||||
elseif len(items) == arrays + 1
|
||||
" Completing one word and it's a local array variable: build tagline
|
||||
" from declaration line
|
||||
let match = items[0]
|
||||
let kind = 'v'
|
||||
let tagline = "\t/^" . line . '$/'
|
||||
let res = [{'match': match, 'tagline' : tagline, 'kind' : kind, 'info' : line}]
|
||||
else
|
||||
" Completing "var.", "var.something", etc.
|
||||
let res = s:Nextitem(strpart(line, 0, col), items[1:], 0, 1)
|
||||
endif
|
||||
endif
|
||||
|
||||
if len(items) == 1 || len(items) == arrays + 1
|
||||
" Only one part, no "." or "->": complete from tags file.
|
||||
if len(items) == 1
|
||||
let tags = taglist('^' . base)
|
||||
else
|
||||
let tags = taglist('^' . items[0] . '$')
|
||||
endif
|
||||
|
||||
" Remove members, these can't appear without something in front.
|
||||
call filter(tags, 'has_key(v:val, "kind") ? v:val["kind"] != "m" : 1')
|
||||
|
||||
" Remove static matches in other files.
|
||||
call filter(tags, '!has_key(v:val, "static") || !v:val["static"] || bufnr("%") == bufnr(v:val["filename"])')
|
||||
|
||||
call extend(res, map(tags, 's:Tag2item(v:val)'))
|
||||
endif
|
||||
|
||||
if len(res) == 0
|
||||
" Find the variable in the tags file(s)
|
||||
let diclist = taglist('^' . items[0] . '$')
|
||||
|
||||
" Remove members, these can't appear without something in front.
|
||||
call filter(diclist, 'has_key(v:val, "kind") ? v:val["kind"] != "m" : 1')
|
||||
|
||||
let res = []
|
||||
for i in range(len(diclist))
|
||||
if complete_check()
|
||||
return res
|
||||
endif
|
||||
" New ctags has the "typeref" field. Patched version has "typename".
|
||||
if has_key(diclist[i], 'typename')
|
||||
call extend(res, s:StructMembers(diclist[i]['typename'], items[1:], 1))
|
||||
elseif has_key(diclist[i], 'typeref')
|
||||
call extend(res, s:StructMembers(diclist[i]['typeref'], items[1:], 1))
|
||||
endif
|
||||
|
||||
" For a variable use the command, which must be a search pattern that
|
||||
" shows the declaration of the variable.
|
||||
if diclist[i]['kind'] == 'v'
|
||||
let line = diclist[i]['cmd']
|
||||
if line[0] == '/' && line[1] == '^'
|
||||
let col = match(line, '\<' . items[0] . '\>')
|
||||
call extend(res, s:Nextitem(strpart(line, 2, col - 2), items[1:], 0, 1))
|
||||
endif
|
||||
endif
|
||||
endfor
|
||||
endif
|
||||
|
||||
if len(res) == 0 && searchdecl(items[0], 1) == 0
|
||||
" Found, now figure out the type.
|
||||
" TODO: join previous line if it makes sense
|
||||
let line = getline('.')
|
||||
let col = col('.')
|
||||
let res = s:Nextitem(strpart(line, 0, col), items[1:], 0, 1)
|
||||
endif
|
||||
|
||||
" If the last item(s) are [...] they need to be added to the matches.
|
||||
let last = len(items) - 1
|
||||
let brackets = ''
|
||||
while last >= 0
|
||||
if complete_check()
|
||||
return res
|
||||
endif
|
||||
if items[last][0] != '['
|
||||
break
|
||||
endif
|
||||
let brackets = items[last] . brackets
|
||||
let last -= 1
|
||||
endwhile
|
||||
|
||||
return map(res, 's:Tagline2item(v:val, brackets)')
|
||||
endfunc
|
||||
|
||||
func s:GetAddition(line, match, memarg, bracket)
|
||||
" Guess if the item is an array.
|
||||
if a:bracket && match(a:line, a:match . '\s*\[') > 0
|
||||
return '['
|
||||
endif
|
||||
|
||||
" Check if the item has members.
|
||||
if len(s:SearchMembers(a:memarg, [''], 0)) > 0
|
||||
" If there is a '*' before the name use "->".
|
||||
if match(a:line, '\*[ \t(]*' . a:match . '\>') > 0
|
||||
return '->'
|
||||
else
|
||||
return '.'
|
||||
endif
|
||||
endif
|
||||
return ''
|
||||
endfunc
|
||||
|
||||
" Turn the tag info "val" into an item for completion.
|
||||
" "val" is is an item in the list returned by taglist().
|
||||
" If it is a variable we may add "." or "->". Don't do it for other types,
|
||||
" such as a typedef, by not including the info that s:GetAddition() uses.
|
||||
func s:Tag2item(val)
|
||||
let res = {'match': a:val['name']}
|
||||
|
||||
let res['extra'] = s:Tagcmd2extra(a:val['cmd'], a:val['name'], a:val['filename'])
|
||||
|
||||
let s = s:Dict2info(a:val)
|
||||
if s != ''
|
||||
let res['info'] = s
|
||||
endif
|
||||
|
||||
let res['tagline'] = ''
|
||||
if has_key(a:val, "kind")
|
||||
let kind = a:val['kind']
|
||||
let res['kind'] = kind
|
||||
if kind == 'v'
|
||||
let res['tagline'] = "\t" . a:val['cmd']
|
||||
let res['dict'] = a:val
|
||||
elseif kind == 'f'
|
||||
let res['match'] = a:val['name'] . '('
|
||||
endif
|
||||
endif
|
||||
|
||||
return res
|
||||
endfunc
|
||||
|
||||
" Use all the items in dictionary for the "info" entry.
|
||||
func s:Dict2info(dict)
|
||||
let info = ''
|
||||
for k in sort(keys(a:dict))
|
||||
if complete_check()
|
||||
return info
|
||||
endif
|
||||
let info .= k . repeat(' ', 10 - len(k))
|
||||
if k == 'cmd'
|
||||
let info .= substitute(matchstr(a:dict['cmd'], '/^\s*\zs.*\ze$/'), '\\\(.\)', '\1', 'g')
|
||||
else
|
||||
let info .= a:dict[k]
|
||||
endif
|
||||
let info .= "\n"
|
||||
endfor
|
||||
return info
|
||||
endfunc
|
||||
|
||||
" Parse a tag line and return a dictionary with items like taglist()
|
||||
func s:ParseTagline(line)
|
||||
let l = split(a:line, "\t")
|
||||
let d = {}
|
||||
if len(l) >= 3
|
||||
let d['name'] = l[0]
|
||||
let d['filename'] = l[1]
|
||||
let d['cmd'] = l[2]
|
||||
let n = 2
|
||||
if l[2] =~ '^/'
|
||||
" Find end of cmd, it may contain Tabs.
|
||||
while n < len(l) && l[n] !~ '/;"$'
|
||||
let n += 1
|
||||
let d['cmd'] .= " " . l[n]
|
||||
endwhile
|
||||
endif
|
||||
for i in range(n + 1, len(l) - 1)
|
||||
if complete_check()
|
||||
return d
|
||||
endif
|
||||
if l[i] == 'file:'
|
||||
let d['static'] = 1
|
||||
elseif l[i] !~ ':'
|
||||
let d['kind'] = l[i]
|
||||
else
|
||||
let d[matchstr(l[i], '[^:]*')] = matchstr(l[i], ':\zs.*')
|
||||
endif
|
||||
endfor
|
||||
endif
|
||||
|
||||
return d
|
||||
endfunc
|
||||
|
||||
" Turn a match item "val" into an item for completion.
|
||||
" "val['match']" is the matching item.
|
||||
" "val['tagline']" is the tagline in which the last part was found.
|
||||
func s:Tagline2item(val, brackets)
|
||||
let line = a:val['tagline']
|
||||
let add = s:GetAddition(line, a:val['match'], [a:val], a:brackets == '')
|
||||
let res = {'word': a:val['match'] . a:brackets . add }
|
||||
|
||||
if has_key(a:val, 'info')
|
||||
" Use info from Tag2item().
|
||||
let res['info'] = a:val['info']
|
||||
else
|
||||
" Parse the tag line and add each part to the "info" entry.
|
||||
let s = s:Dict2info(s:ParseTagline(line))
|
||||
if s != ''
|
||||
let res['info'] = s
|
||||
endif
|
||||
endif
|
||||
|
||||
if has_key(a:val, 'kind')
|
||||
let res['kind'] = a:val['kind']
|
||||
elseif add == '('
|
||||
let res['kind'] = 'f'
|
||||
else
|
||||
let s = matchstr(line, '\t\(kind:\)\=\zs\S\ze\(\t\|$\)')
|
||||
if s != ''
|
||||
let res['kind'] = s
|
||||
endif
|
||||
endif
|
||||
|
||||
if has_key(a:val, 'extra')
|
||||
let res['menu'] = a:val['extra']
|
||||
return res
|
||||
endif
|
||||
|
||||
" Isolate the command after the tag and filename.
|
||||
let s = matchstr(line, '[^\t]*\t[^\t]*\t\zs\(/^.*$/\|[^\t]*\)\ze\(;"\t\|\t\|$\)')
|
||||
if s != ''
|
||||
let res['menu'] = s:Tagcmd2extra(s, a:val['match'], matchstr(line, '[^\t]*\t\zs[^\t]*\ze\t'))
|
||||
endif
|
||||
return res
|
||||
endfunc
|
||||
|
||||
" Turn a command from a tag line to something that is useful in the menu
|
||||
func s:Tagcmd2extra(cmd, name, fname)
|
||||
if a:cmd =~ '^/^'
|
||||
" The command is a search command, useful to see what it is.
|
||||
let x = matchstr(a:cmd, '^/^\s*\zs.*\ze$/')
|
||||
let x = substitute(x, '\<' . a:name . '\>', '@@', '')
|
||||
let x = substitute(x, '\\\(.\)', '\1', 'g')
|
||||
let x = x . ' - ' . a:fname
|
||||
elseif a:cmd =~ '^\d*$'
|
||||
" The command is a line number, the file name is more useful.
|
||||
let x = a:fname . ' - ' . a:cmd
|
||||
else
|
||||
" Not recognized, use command and file name.
|
||||
let x = a:cmd . ' - ' . a:fname
|
||||
endif
|
||||
return x
|
||||
endfunc
|
||||
|
||||
" Find composing type in "lead" and match items[0] with it.
|
||||
" Repeat this recursively for items[1], if it's there.
|
||||
" When resolving typedefs "depth" is used to avoid infinite recursion.
|
||||
" Return the list of matches.
|
||||
func s:Nextitem(lead, items, depth, all)
|
||||
|
||||
" Use the text up to the variable name and split it in tokens.
|
||||
let tokens = split(a:lead, '\s\+\|\<')
|
||||
|
||||
" Try to recognize the type of the variable. This is rough guessing...
|
||||
let res = []
|
||||
for tidx in range(len(tokens))
|
||||
if complete_check()
|
||||
return res
|
||||
endif
|
||||
|
||||
" Skip tokens starting with a non-ID character.
|
||||
if tokens[tidx] !~ '^\h'
|
||||
continue
|
||||
endif
|
||||
|
||||
" Recognize "struct foobar" and "union foobar".
|
||||
" Also do "class foobar" when it's C++ after all (doesn't work very well
|
||||
" though).
|
||||
if (tokens[tidx] == 'struct' || tokens[tidx] == 'union' || tokens[tidx] == 'class') && tidx + 1 < len(tokens)
|
||||
let res = s:StructMembers(tokens[tidx] . ':' . tokens[tidx + 1], a:items, a:all)
|
||||
break
|
||||
endif
|
||||
|
||||
" TODO: add more reserved words
|
||||
if index(['int', 'short', 'char', 'float', 'double', 'static', 'unsigned', 'extern'], tokens[tidx]) >= 0
|
||||
continue
|
||||
endif
|
||||
|
||||
" Use the tags file to find out if this is a typedef.
|
||||
let diclist = taglist('^' . tokens[tidx] . '$')
|
||||
for tagidx in range(len(diclist))
|
||||
|
||||
if complete_check()
|
||||
return res
|
||||
endif
|
||||
|
||||
let item = diclist[tagidx]
|
||||
|
||||
" New ctags has the "typeref" field. Patched version has "typename".
|
||||
if has_key(item, 'typeref')
|
||||
call extend(res, s:StructMembers(item['typeref'], a:items, a:all))
|
||||
continue
|
||||
endif
|
||||
if has_key(item, 'typename')
|
||||
call extend(res, s:StructMembers(item['typename'], a:items, a:all))
|
||||
continue
|
||||
endif
|
||||
|
||||
" Only handle typedefs here.
|
||||
if item['kind'] != 't'
|
||||
continue
|
||||
endif
|
||||
|
||||
" Skip matches local to another file.
|
||||
if has_key(item, 'static') && item['static'] && bufnr('%') != bufnr(item['filename'])
|
||||
continue
|
||||
endif
|
||||
|
||||
" For old ctags we recognize "typedef struct aaa" and
|
||||
" "typedef union bbb" in the tags file command.
|
||||
let cmd = item['cmd']
|
||||
let ei = matchend(cmd, 'typedef\s\+')
|
||||
if ei > 1
|
||||
let cmdtokens = split(strpart(cmd, ei), '\s\+\|\<')
|
||||
if len(cmdtokens) > 1
|
||||
if cmdtokens[0] == 'struct' || cmdtokens[0] == 'union' || cmdtokens[0] == 'class'
|
||||
let name = ''
|
||||
" Use the first identifier after the "struct" or "union"
|
||||
for ti in range(len(cmdtokens) - 1)
|
||||
if cmdtokens[ti] =~ '^\w'
|
||||
let name = cmdtokens[ti]
|
||||
break
|
||||
endif
|
||||
endfor
|
||||
if name != ''
|
||||
call extend(res, s:StructMembers(cmdtokens[0] . ':' . name, a:items, a:all))
|
||||
endif
|
||||
elseif a:depth < 10
|
||||
" Could be "typedef other_T some_T".
|
||||
call extend(res, s:Nextitem(cmdtokens[0], a:items, a:depth + 1, a:all))
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endfor
|
||||
if len(res) > 0
|
||||
break
|
||||
endif
|
||||
endfor
|
||||
|
||||
return res
|
||||
endfunc
|
||||
|
||||
|
||||
" Search for members of structure "typename" in tags files.
|
||||
" Return a list with resulting matches.
|
||||
" Each match is a dictionary with "match" and "tagline" entries.
|
||||
" When "all" is non-zero find all, otherwise just return 1 if there is any
|
||||
" member.
|
||||
func s:StructMembers(typename, items, all)
|
||||
" Todo: What about local structures?
|
||||
let fnames = join(map(tagfiles(), 'escape(v:val, " \\#%")'))
|
||||
if fnames == ''
|
||||
return []
|
||||
endif
|
||||
|
||||
let typename = a:typename
|
||||
let qflist = []
|
||||
let cached = 0
|
||||
if a:all == 0
|
||||
let n = '1' " stop at first found match
|
||||
if has_key(s:grepCache, a:typename)
|
||||
let qflist = s:grepCache[a:typename]
|
||||
let cached = 1
|
||||
endif
|
||||
else
|
||||
let n = ''
|
||||
endif
|
||||
if !cached
|
||||
while 1
|
||||
if complete_check()
|
||||
return []
|
||||
endif
|
||||
exe 'silent! keepj noautocmd ' . n . 'vimgrep /\t' . typename . '\(\t\|$\)/j ' . fnames
|
||||
|
||||
let qflist = getqflist()
|
||||
if len(qflist) > 0 || match(typename, "::") < 0
|
||||
break
|
||||
endif
|
||||
" No match for "struct:context::name", remove "context::" and try again.
|
||||
let typename = substitute(typename, ':[^:]*::', ':', '')
|
||||
endwhile
|
||||
|
||||
if a:all == 0
|
||||
" Store the result to be able to use it again later.
|
||||
let s:grepCache[a:typename] = qflist
|
||||
endif
|
||||
endif
|
||||
|
||||
" Skip over [...] items
|
||||
let idx = 0
|
||||
while 1
|
||||
if complete_check()
|
||||
return []
|
||||
endif
|
||||
if idx >= len(a:items)
|
||||
let target = '' " No further items, matching all members
|
||||
break
|
||||
endif
|
||||
if a:items[idx][0] != '['
|
||||
let target = a:items[idx]
|
||||
break
|
||||
endif
|
||||
let idx += 1
|
||||
endwhile
|
||||
" Put matching members in matches[].
|
||||
let matches = []
|
||||
for l in qflist
|
||||
let memb = matchstr(l['text'], '[^\t]*')
|
||||
if memb =~ '^' . target
|
||||
" Skip matches local to another file.
|
||||
if match(l['text'], "\tfile:") < 0 || bufnr('%') == bufnr(matchstr(l['text'], '\t\zs[^\t]*'))
|
||||
let item = {'match': memb, 'tagline': l['text']}
|
||||
|
||||
" Add the kind of item.
|
||||
let s = matchstr(l['text'], '\t\(kind:\)\=\zs\S\ze\(\t\|$\)')
|
||||
if s != ''
|
||||
let item['kind'] = s
|
||||
if s == 'f'
|
||||
let item['match'] = memb . '('
|
||||
endif
|
||||
endif
|
||||
|
||||
call add(matches, item)
|
||||
endif
|
||||
endif
|
||||
endfor
|
||||
|
||||
if len(matches) > 0
|
||||
" Skip over next [...] items
|
||||
let idx += 1
|
||||
while 1
|
||||
if complete_check()
|
||||
return matches
|
||||
endif
|
||||
if idx >= len(a:items)
|
||||
return matches " No further items, return the result.
|
||||
endif
|
||||
if a:items[idx][0] != '['
|
||||
break
|
||||
endif
|
||||
let idx += 1
|
||||
endwhile
|
||||
|
||||
" More items following. For each of the possible members find the
|
||||
" matching following members.
|
||||
return s:SearchMembers(matches, a:items[idx :], a:all)
|
||||
endif
|
||||
|
||||
" Failed to find anything.
|
||||
return []
|
||||
endfunc
|
||||
|
||||
" For matching members, find matches for following items.
|
||||
" When "all" is non-zero find all, otherwise just return 1 if there is any
|
||||
" member.
|
||||
func s:SearchMembers(matches, items, all)
|
||||
let res = []
|
||||
for i in range(len(a:matches))
|
||||
if complete_check()
|
||||
return res
|
||||
endif
|
||||
let typename = ''
|
||||
if has_key(a:matches[i], 'dict')
|
||||
if has_key(a:matches[i].dict, 'typename')
|
||||
let typename = a:matches[i].dict['typename']
|
||||
elseif has_key(a:matches[i].dict, 'typeref')
|
||||
let typename = a:matches[i].dict['typeref']
|
||||
endif
|
||||
let line = "\t" . a:matches[i].dict['cmd']
|
||||
else
|
||||
let line = a:matches[i]['tagline']
|
||||
let e = matchend(line, '\ttypename:')
|
||||
if e < 0
|
||||
let e = matchend(line, '\ttyperef:')
|
||||
endif
|
||||
if e > 0
|
||||
" Use typename field
|
||||
let typename = matchstr(line, '[^\t]*', e)
|
||||
endif
|
||||
endif
|
||||
|
||||
if typename != ''
|
||||
call extend(res, s:StructMembers(typename, a:items, a:all))
|
||||
else
|
||||
" Use the search command (the declaration itself).
|
||||
let s = match(line, '\t\zs/^')
|
||||
if s > 0
|
||||
let e = match(line, '\<' . a:matches[i]['match'] . '\>', s)
|
||||
if e > 0
|
||||
call extend(res, s:Nextitem(strpart(line, s, e - s), a:items, 0, a:all))
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
if a:all == 0 && len(res) > 0
|
||||
break
|
||||
endif
|
||||
endfor
|
||||
return res
|
||||
endfunc
|
||||
|
||||
let &cpo = s:cpo_save
|
||||
unlet s:cpo_save
|
||||
|
||||
" vim: noet sw=2 sts=2
|
||||
" Generated vim file by vim9jit. Please do not edit
|
||||
let s:path = expand("<script>")
|
||||
let s:lua_path = fnamemodify(s:path, ":r") . ".lua"
|
||||
let s:nvim_module = luaeval('require("_vim9script").autoload(_A)', s:lua_path)
|
||||
|
||||
function! ccomplete#Complete(findstart, abase) abort
|
||||
return s:nvim_module.Complete(a:findstart, a:abase)
|
||||
endfunction
|
||||
|
@@ -2,21 +2,6 @@
|
||||
" Maintainer: Gregory Anders
|
||||
" Last Change: 2024-09-03
|
||||
" Based on: https://github.com/hashivim/vim-terraform
|
||||
" License: ISC
|
||||
"
|
||||
" Copyright (c) 2014-2016 Mark Cornick <mark@markcornick.com>
|
||||
"
|
||||
" Permission to use, copy, modify, and/or distribute this software for any purpose
|
||||
" with or without fee is hereby granted, provided that the above copyright notice
|
||||
" and this permission notice appear in all copies.
|
||||
"
|
||||
" THE SOFTWARE IS PROVIDED 'AS IS' AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||
" REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
" FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
" INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
" OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
" TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
||||
" THIS SOFTWARE.
|
||||
|
||||
function! hcl#indentexpr(lnum)
|
||||
" Beginning of the file should have no indent
|
||||
|
@@ -1,192 +0,0 @@
|
||||
" HTML folding script, :h ft-html-plugin
|
||||
" Latest Change: 2025 May 10
|
||||
" Original Author: Aliaksei Budavei <0x000c70@gmail.com>
|
||||
|
||||
function! htmlfold#MapBalancedTags() abort
|
||||
" Describe only _a capturable-name prefix_ for start and end patterns of
|
||||
" a tag so that start tags with attributes spanning across lines can also be
|
||||
" matched with a single call of "getline()".
|
||||
let tag = '\m\c</\=\([0-9A-Za-z-]\+\)'
|
||||
let names = []
|
||||
let pairs = []
|
||||
let ends = []
|
||||
let pos = getpos('.')
|
||||
|
||||
try
|
||||
call cursor(1, 1)
|
||||
let [lnum, cnum] = searchpos(tag, 'cnW')
|
||||
|
||||
" Pair up nearest non-inlined tags in scope.
|
||||
while lnum > 0
|
||||
let name_attr = synIDattr(synID(lnum, cnum, 0), 'name')
|
||||
|
||||
if name_attr ==# 'htmlTag' || name_attr ==# 'htmlScriptTag'
|
||||
let name = get(matchlist(getline(lnum), tag, (cnum - 1)), 1, '')
|
||||
|
||||
if !empty(name)
|
||||
call insert(names, tolower(name), 0)
|
||||
call insert(pairs, [lnum, -1], 0)
|
||||
endif
|
||||
elseif name_attr ==# 'htmlEndTag'
|
||||
let name = get(matchlist(getline(lnum), tag, (cnum - 1)), 1, '')
|
||||
|
||||
if !empty(name)
|
||||
let idx = index(names, tolower(name))
|
||||
|
||||
if idx >= 0
|
||||
" Dismiss inlined balanced tags and opened-only tags.
|
||||
if pairs[idx][0] != lnum
|
||||
let pairs[idx][1] = lnum
|
||||
call add(ends, lnum)
|
||||
endif
|
||||
|
||||
" Claim a pair.
|
||||
let names[: idx] = repeat([''], (idx + 1))
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
" Advance the cursor, at "<", past "</a", "<a>", etc.
|
||||
call cursor(lnum, (cnum + 3))
|
||||
let [lnum, cnum] = searchpos(tag, 'cnW')
|
||||
endwhile
|
||||
finally
|
||||
call setpos('.', pos)
|
||||
endtry
|
||||
|
||||
if empty(ends)
|
||||
return {}
|
||||
endif
|
||||
|
||||
let folds = {}
|
||||
let pending_end = ends[0]
|
||||
let level = 0
|
||||
|
||||
while !empty(pairs)
|
||||
let [start, end] = remove(pairs, -1)
|
||||
|
||||
if end < 0
|
||||
continue
|
||||
endif
|
||||
|
||||
if start >= pending_end
|
||||
" Mark a sibling tag.
|
||||
call remove(ends, 0)
|
||||
|
||||
while start >= ends[0]
|
||||
" Mark a parent tag.
|
||||
call remove(ends, 0)
|
||||
let level -= 1
|
||||
endwhile
|
||||
|
||||
let pending_end = ends[0]
|
||||
else
|
||||
" Mark a child tag.
|
||||
let level += 1
|
||||
endif
|
||||
|
||||
" Flatten the innermost inlined folds.
|
||||
let folds[start] = get(folds, start, ('>' . level))
|
||||
let folds[end] = get(folds, end, ('<' . level))
|
||||
endwhile
|
||||
|
||||
return folds
|
||||
endfunction
|
||||
|
||||
" See ":help vim9-mix".
|
||||
if !has("vim9script")
|
||||
finish
|
||||
endif
|
||||
|
||||
def! g:htmlfold#MapBalancedTags(): dict<string>
|
||||
# Describe only _a capturable-name prefix_ for start and end patterns of
|
||||
# a tag so that start tags with attributes spanning across lines can also be
|
||||
# matched with a single call of "getline()".
|
||||
const tag: string = '\m\c</\=\([0-9A-Za-z-]\+\)'
|
||||
var names: list<string> = []
|
||||
var pairs: list<list<number>> = []
|
||||
var ends: list<number> = []
|
||||
const pos: list<number> = getpos('.')
|
||||
|
||||
try
|
||||
cursor(1, 1)
|
||||
var [lnum: number, cnum: number] = searchpos(tag, 'cnW')
|
||||
|
||||
# Pair up nearest non-inlined tags in scope.
|
||||
while lnum > 0
|
||||
const name_attr: string = synIDattr(synID(lnum, cnum, 0), 'name')
|
||||
|
||||
if name_attr ==# 'htmlTag' || name_attr ==# 'htmlScriptTag'
|
||||
const name: string = get(matchlist(getline(lnum), tag, (cnum - 1)), 1, '')
|
||||
|
||||
if !empty(name)
|
||||
insert(names, tolower(name), 0)
|
||||
insert(pairs, [lnum, -1], 0)
|
||||
endif
|
||||
elseif name_attr ==# 'htmlEndTag'
|
||||
const name: string = get(matchlist(getline(lnum), tag, (cnum - 1)), 1, '')
|
||||
|
||||
if !empty(name)
|
||||
const idx: number = index(names, tolower(name))
|
||||
|
||||
if idx >= 0
|
||||
# Dismiss inlined balanced tags and opened-only tags.
|
||||
if pairs[idx][0] != lnum
|
||||
pairs[idx][1] = lnum
|
||||
add(ends, lnum)
|
||||
endif
|
||||
|
||||
# Claim a pair.
|
||||
names[: idx] = repeat([''], (idx + 1))
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
# Advance the cursor, at "<", past "</a", "<a>", etc.
|
||||
cursor(lnum, (cnum + 3))
|
||||
[lnum, cnum] = searchpos(tag, 'cnW')
|
||||
endwhile
|
||||
finally
|
||||
setpos('.', pos)
|
||||
endtry
|
||||
|
||||
if empty(ends)
|
||||
return {}
|
||||
endif
|
||||
|
||||
var folds: dict<string> = {}
|
||||
var pending_end: number = ends[0]
|
||||
var level: number = 0
|
||||
|
||||
while !empty(pairs)
|
||||
const [start: number, end: number] = remove(pairs, -1)
|
||||
|
||||
if end < 0
|
||||
continue
|
||||
endif
|
||||
|
||||
if start >= pending_end
|
||||
# Mark a sibling tag.
|
||||
remove(ends, 0)
|
||||
|
||||
while start >= ends[0]
|
||||
# Mark a parent tag.
|
||||
remove(ends, 0)
|
||||
level -= 1
|
||||
endwhile
|
||||
|
||||
pending_end = ends[0]
|
||||
else
|
||||
# Mark a child tag.
|
||||
level += 1
|
||||
endif
|
||||
|
||||
# Flatten the innermost inlined folds.
|
||||
folds[start] = get(folds, start, ('>' .. level))
|
||||
folds[end] = get(folds, end, ('<' .. level))
|
||||
endwhile
|
||||
|
||||
return folds
|
||||
enddef
|
||||
|
||||
" vim: fdm=syntax sw=2 ts=8 noet
|
@@ -85,10 +85,10 @@ function! s:set_wayland() abort
|
||||
endfunction
|
||||
|
||||
function! s:set_wayclip() abort
|
||||
let s:copy['+'] = ['waycopy']
|
||||
let s:paste['+'] = ['waypaste']
|
||||
let s:copy['*'] = ['waycopy', '-p']
|
||||
let s:paste['*'] = ['waypaste', '-p']
|
||||
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
|
||||
|
||||
|
@@ -1,8 +1,5 @@
|
||||
" Author: Stephen Sugden <stephen@stephensugden.com>
|
||||
" Last Modified: 2023-09-11
|
||||
" Last Change:
|
||||
" 2025 Mar 31 by Vim project (rename s:RustfmtConfigOptions())
|
||||
" 2025 Jul 14 by Vim project (don't parse rustfmt version automatically #17745)
|
||||
"
|
||||
" Adapted from https://github.com/fatih/vim-go
|
||||
" For bugs, patches and license go to https://github.com/rust-lang/rust.vim
|
||||
@@ -24,12 +21,6 @@ if !exists("g:rustfmt_fail_silently")
|
||||
endif
|
||||
|
||||
function! rustfmt#DetectVersion()
|
||||
let s:rustfmt_version = "0"
|
||||
let s:rustfmt_help = ""
|
||||
let s:rustfmt_unstable_features = ""
|
||||
if !get(g:, 'rustfmt_detect_version', 0)
|
||||
return s:rustfmt_version
|
||||
endif
|
||||
" Save rustfmt '--help' for feature inspection
|
||||
silent let s:rustfmt_help = system(g:rustfmt_command . " --help")
|
||||
let s:rustfmt_unstable_features = s:rustfmt_help =~# "--unstable-features"
|
||||
@@ -38,7 +29,9 @@ function! rustfmt#DetectVersion()
|
||||
silent let l:rustfmt_version_full = system(g:rustfmt_command . " --version")
|
||||
let l:rustfmt_version_list = matchlist(l:rustfmt_version_full,
|
||||
\ '\vrustfmt ([0-9]+[.][0-9]+[.][0-9]+)')
|
||||
if len(l:rustfmt_version_list) >= 3
|
||||
if len(l:rustfmt_version_list) < 3
|
||||
let s:rustfmt_version = "0"
|
||||
else
|
||||
let s:rustfmt_version = l:rustfmt_version_list[1]
|
||||
endif
|
||||
return s:rustfmt_version
|
||||
@@ -68,13 +61,7 @@ function! s:RustfmtWriteMode()
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! rustfmt#RustfmtConfigOptions()
|
||||
let default = '--edition 2018'
|
||||
|
||||
if !get(g:, 'rustfmt_find_toml', 0)
|
||||
return default
|
||||
endif
|
||||
|
||||
function! s:RustfmtConfigOptions()
|
||||
let l:rustfmt_toml = findfile('rustfmt.toml', expand('%:p:h') . ';')
|
||||
if l:rustfmt_toml !=# ''
|
||||
return '--config-path '.shellescape(fnamemodify(l:rustfmt_toml, ":p"))
|
||||
@@ -86,7 +73,7 @@ function! rustfmt#RustfmtConfigOptions()
|
||||
endif
|
||||
|
||||
" Default to edition 2018 in case no rustfmt.toml was found.
|
||||
return default
|
||||
return '--edition 2018'
|
||||
endfunction
|
||||
|
||||
function! s:RustfmtCommandRange(filename, line1, line2)
|
||||
@@ -97,7 +84,7 @@ function! s:RustfmtCommandRange(filename, line1, line2)
|
||||
|
||||
let l:arg = {"file": shellescape(a:filename), "range": [a:line1, a:line2]}
|
||||
let l:write_mode = s:RustfmtWriteMode()
|
||||
let l:rustfmt_config = rustfmt#RustfmtConfigOptions()
|
||||
let l:rustfmt_config = s:RustfmtConfigOptions()
|
||||
|
||||
" FIXME: When --file-lines gets to be stable, add version range checking
|
||||
" accordingly.
|
||||
@@ -112,7 +99,7 @@ endfunction
|
||||
|
||||
function! s:RustfmtCommand()
|
||||
let write_mode = g:rustfmt_emit_files ? '--emit=stdout' : '--write-mode=display'
|
||||
let config = rustfmt#RustfmtConfigOptions()
|
||||
let config = s:RustfmtConfigOptions()
|
||||
return join([g:rustfmt_command, write_mode, config, g:rustfmt_options])
|
||||
endfunction
|
||||
|
||||
|
@@ -12,11 +12,6 @@
|
||||
" 2025 Feb 28 by Vim Project: add support for bzip3 (#16755)
|
||||
" 2025 Mar 01 by Vim Project: fix syntax error in tar#Read()
|
||||
" 2025 Mar 02 by Vim Project: escape the filename before using :read
|
||||
" 2025 Mar 02 by Vim Project: determine the compression using readblob()
|
||||
" instead of shelling out to file(1)
|
||||
" 2025 Apr 16 by Vim Project: decouple from netrw by adding s:WinPath()
|
||||
" 2025 May 19 by Vim Project: restore working directory after read/write
|
||||
" 2025 Jul 13 by Vim Project: warn with path traversal attacks
|
||||
"
|
||||
" Contains many ideas from Michael Toren's <tar.vim>
|
||||
"
|
||||
@@ -35,9 +30,9 @@ if &cp || exists("g:loaded_tar")
|
||||
finish
|
||||
endif
|
||||
let g:loaded_tar= "v32b"
|
||||
if !has('nvim-0.12') && v:version < 900
|
||||
if v:version < 702
|
||||
echohl WarningMsg
|
||||
echo "***warning*** this version of tar needs vim 9.0"
|
||||
echo "***warning*** this version of tar needs vim 7.2"
|
||||
echohl Normal
|
||||
finish
|
||||
endif
|
||||
@@ -47,10 +42,10 @@ set cpo&vim
|
||||
" ---------------------------------------------------------------------
|
||||
" Default Settings: {{{1
|
||||
if !exists("g:tar_browseoptions")
|
||||
let g:tar_browseoptions= "tf"
|
||||
let g:tar_browseoptions= "Ptf"
|
||||
endif
|
||||
if !exists("g:tar_readoptions")
|
||||
let g:tar_readoptions= "pxf"
|
||||
let g:tar_readoptions= "pPxf"
|
||||
endif
|
||||
if !exists("g:tar_cmd")
|
||||
let g:tar_cmd= "tar"
|
||||
@@ -59,7 +54,6 @@ if !exists("g:tar_writeoptions")
|
||||
let g:tar_writeoptions= "uf"
|
||||
endif
|
||||
if !exists("g:tar_delfile")
|
||||
" Note: not supported on BSD
|
||||
let g:tar_delfile="--delete -f"
|
||||
endif
|
||||
if !exists("g:netrw_cygwin")
|
||||
@@ -108,26 +102,10 @@ if !exists("g:tar_shq")
|
||||
endif
|
||||
endif
|
||||
|
||||
let g:tar_secure=' -- '
|
||||
let g:tar_leading_pat='^\%([.]\{,2\}/\)\+'
|
||||
|
||||
" ----------------
|
||||
" Functions: {{{1
|
||||
" ----------------
|
||||
|
||||
" ---------------------------------------------------------------------
|
||||
" s:Msg: {{{2
|
||||
fun! s:Msg(func, severity, msg)
|
||||
redraw!
|
||||
if a:severity =~? 'error'
|
||||
echohl Error
|
||||
else
|
||||
echohl WarningMsg
|
||||
endif
|
||||
echo $"***{a:severity}*** ({a:func}) {a:msg}"
|
||||
echohl None
|
||||
endfunc
|
||||
|
||||
" ---------------------------------------------------------------------
|
||||
" tar#Browse: {{{2
|
||||
fun! tar#Browse(tarfile)
|
||||
@@ -136,14 +114,16 @@ fun! tar#Browse(tarfile)
|
||||
|
||||
" sanity checks
|
||||
if !executable(g:tar_cmd)
|
||||
call s:Msg('tar#Browse', 'error', $"{g:tar_cmd} not available on your system")
|
||||
redraw!
|
||||
echohl Error | echo '***error*** (tar#Browse) "'.g:tar_cmd.'" not available on your system'
|
||||
let &report= repkeep
|
||||
return
|
||||
endif
|
||||
if !filereadable(a:tarfile)
|
||||
if a:tarfile !~# '^\a\+://'
|
||||
" if it's an url, don't complain, let url-handlers such as vim do its thing
|
||||
call s:Msg('tar#Browse', 'error', $"File not readable<{a:tarfile}>")
|
||||
redraw!
|
||||
echohl Error | echo "***error*** (tar#Browse) File not readable<".a:tarfile.">" | echohl None
|
||||
endif
|
||||
let &report= repkeep
|
||||
return
|
||||
@@ -164,7 +144,7 @@ fun! tar#Browse(tarfile)
|
||||
let lastline= line("$")
|
||||
call setline(lastline+1,'" tar.vim version '.g:loaded_tar)
|
||||
call setline(lastline+2,'" Browsing tarfile '.a:tarfile)
|
||||
call setline(lastline+3,'" Select a file with cursor and press ENTER, "x" to extract a file')
|
||||
call setline(lastline+3,'" Select a file with cursor and press ENTER')
|
||||
keepj $put =''
|
||||
keepj sil! 0d
|
||||
keepj $
|
||||
@@ -181,19 +161,23 @@ fun! tar#Browse(tarfile)
|
||||
|
||||
elseif tarfile =~# '\.\(tgz\)$' || tarfile =~# '\.\(tbz\)$' || tarfile =~# '\.\(txz\)$' ||
|
||||
\ tarfile =~# '\.\(tzst\)$' || tarfile =~# '\.\(tlz4\)$'
|
||||
let header= s:Header(tarfile)
|
||||
if has("unix") && executable("file")
|
||||
let filekind= system("file ".shellescape(tarfile,1))
|
||||
else
|
||||
let filekind= ""
|
||||
endif
|
||||
|
||||
if header =~? 'bzip2'
|
||||
if filekind =~ "bzip2"
|
||||
exe "sil! r! bzip2 -d -c -- ".shellescape(tarfile,1)." | ".g:tar_cmd." -".g:tar_browseoptions." - "
|
||||
elseif header =~? 'bzip3'
|
||||
elseif filekind =~ "bzip3"
|
||||
exe "sil! r! bzip3 -d -c -- ".shellescape(tarfile,1)." | ".g:tar_cmd." -".g:tar_browseoptions." - "
|
||||
elseif header =~? 'xz'
|
||||
elseif filekind =~ "XZ"
|
||||
exe "sil! r! xz -d -c -- ".shellescape(tarfile,1)." | ".g:tar_cmd." -".g:tar_browseoptions." - "
|
||||
elseif header =~? 'zstd'
|
||||
elseif filekind =~ "Zstandard"
|
||||
exe "sil! r! zstd --decompress --stdout -- ".shellescape(tarfile,1)." | ".g:tar_cmd." -".g:tar_browseoptions." - "
|
||||
elseif header =~? 'lz4'
|
||||
elseif filekind =~ "LZ4"
|
||||
exe "sil! r! lz4 --decompress --stdout -- ".shellescape(tarfile,1)." | ".g:tar_cmd." -".g:tar_browseoptions." - "
|
||||
elseif header =~? 'gzip'
|
||||
else
|
||||
exe "sil! r! gzip -d -c -- ".shellescape(tarfile,1)." | ".g:tar_cmd." -".g:tar_browseoptions." - "
|
||||
endif
|
||||
|
||||
@@ -219,18 +203,28 @@ fun! tar#Browse(tarfile)
|
||||
exe "sil! r! ".g:tar_cmd." -".g:tar_browseoptions." ".shellescape(tarfile,1)
|
||||
endif
|
||||
if v:shell_error != 0
|
||||
call s:Msg('tar#Browse', 'warning', $"please check your g:tar_browseoptions '<{g:tar_browseoptions}>'")
|
||||
redraw!
|
||||
echohl WarningMsg | echo "***warning*** (tar#Browse) please check your g:tar_browseoptions<".g:tar_browseoptions.">"
|
||||
return
|
||||
endif
|
||||
|
||||
" remove tar: Removing leading '/' from member names
|
||||
" Note: the message could be localized
|
||||
if search('^tar: ') > 0 || search(g:tar_leading_pat) > 0
|
||||
call append(3,'" Note: Path Traversal Attack detected!')
|
||||
let b:leading_slash = 1
|
||||
" remove the message output
|
||||
sil g/^tar: /d
|
||||
endif
|
||||
"
|
||||
" The following should not be neccessary, since in case of errors the
|
||||
" previous if statement should have caught the problem (because tar exited
|
||||
" with a non-zero exit code).
|
||||
" if line("$") == curlast || ( line("$") == (curlast + 1) &&
|
||||
" \ getline("$") =~# '\c\<\%(warning\|error\|inappropriate\|unrecognized\)\>' &&
|
||||
" \ getline("$") =~ '\s' )
|
||||
" redraw!
|
||||
" echohl WarningMsg | echo "***warning*** (tar#Browse) ".a:tarfile." doesn't appear to be a tar file" | echohl None
|
||||
" keepj sil! %d
|
||||
" let eikeep= &ei
|
||||
" set ei=BufReadCmd,FileReadCmd
|
||||
" exe "r ".fnameescape(a:tarfile)
|
||||
" let &ei= eikeep
|
||||
" keepj sil! 1d
|
||||
" call Dret("tar#Browse : a:tarfile<".a:tarfile.">")
|
||||
" return
|
||||
" endif
|
||||
|
||||
" set up maps supported for tar
|
||||
setlocal noma nomod ro
|
||||
@@ -249,7 +243,12 @@ fun! s:TarBrowseSelect()
|
||||
let repkeep= &report
|
||||
set report=10
|
||||
let fname= getline(".")
|
||||
let ls= get(b:, 'leading_slash', 0)
|
||||
|
||||
if !exists("g:tar_secure") && fname =~ '^\s*-\|\s\+-'
|
||||
redraw!
|
||||
echohl WarningMsg | echo '***warning*** (tar#BrowseSelect) rejecting tarfile member<'.fname.'> because of embedded "-"'
|
||||
return
|
||||
endif
|
||||
|
||||
" sanity check
|
||||
if fname =~ '^"'
|
||||
@@ -271,8 +270,7 @@ fun! s:TarBrowseSelect()
|
||||
wincmd _
|
||||
endif
|
||||
let s:tblfile_{winnr()}= curfile
|
||||
let b:leading_slash= ls
|
||||
call tar#Read("tarfile:".tarfile.'::'.fname)
|
||||
call tar#Read("tarfile:".tarfile.'::'.fname,1)
|
||||
filetype detect
|
||||
set nomod
|
||||
exe 'com! -buffer -nargs=? -complete=file TarDiff :call tar#Diff(<q-args>,"'.fnameescape(fname).'")'
|
||||
@@ -282,18 +280,26 @@ endfun
|
||||
|
||||
" ---------------------------------------------------------------------
|
||||
" tar#Read: {{{2
|
||||
fun! tar#Read(fname)
|
||||
fun! tar#Read(fname,mode)
|
||||
let repkeep= &report
|
||||
set report=10
|
||||
let tarfile = substitute(a:fname,'tarfile:\(.\{-}\)::.*$','\1','')
|
||||
let fname = substitute(a:fname,'tarfile:.\{-}::\(.*\)$','\1','')
|
||||
" be careful not to execute special crafted files
|
||||
let escape_file = fname->substitute(g:tar_leading_pat, '', '')->fnameescape()
|
||||
let escape_file = fname->fnameescape()
|
||||
|
||||
" changing the directory to the temporary earlier to allow tar to extract the file with permissions intact
|
||||
if !exists("*mkdir")
|
||||
redraw!
|
||||
echohl Error | echo "***error*** (tar#Write) sorry, mkdir() doesn't work on your system" | echohl None
|
||||
let &report= repkeep
|
||||
return
|
||||
endif
|
||||
|
||||
let curdir= getcwd()
|
||||
let b:curdir= curdir
|
||||
let tmpdir= tempname()
|
||||
let b:tmpdir= tmpdir
|
||||
let b:curdir= tmpdir
|
||||
let b:tmpdir= curdir
|
||||
if tmpdir =~ '\.'
|
||||
let tmpdir= substitute(tmpdir,'\.[^.]*$','','e')
|
||||
endif
|
||||
@@ -301,9 +307,10 @@ fun! tar#Read(fname)
|
||||
|
||||
" attempt to change to the indicated directory
|
||||
try
|
||||
exe "lcd ".fnameescape(tmpdir)
|
||||
exe "cd ".fnameescape(tmpdir)
|
||||
catch /^Vim\%((\a\+)\)\=:E344/
|
||||
call s:Msg('tar#Read', 'error', "cannot lcd to temporary directory")
|
||||
redraw!
|
||||
echohl Error | echo "***error*** (tar#Write) cannot cd to temporary directory" | Echohl None
|
||||
let &report= repkeep
|
||||
return
|
||||
endtry
|
||||
@@ -313,7 +320,7 @@ fun! tar#Read(fname)
|
||||
call s:Rmdir("_ZIPVIM_")
|
||||
endif
|
||||
call mkdir("_ZIPVIM_")
|
||||
lcd _ZIPVIM_
|
||||
cd _ZIPVIM_
|
||||
|
||||
if has("win32unix") && executable("cygpath")
|
||||
" assuming cygwin
|
||||
@@ -349,66 +356,72 @@ fun! tar#Read(fname)
|
||||
endif
|
||||
endif
|
||||
|
||||
if exists("g:tar_secure")
|
||||
let tar_secure= " -- "
|
||||
else
|
||||
let tar_secure= " "
|
||||
endif
|
||||
|
||||
if tarfile =~# '\.bz2$'
|
||||
exe "sil! r! bzip2 -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".g:tar_secure.shellescape(fname,1).decmp
|
||||
exe "sil! r! bzip2 -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp
|
||||
exe "read ".escape_file
|
||||
elseif tarfile =~# '\.bz3$'
|
||||
exe "sil! r! bzip3 -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".g:tar_secure.shellescape(fname,1).decmp
|
||||
exe "sil! r! bzip3 -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp
|
||||
exe "read ".escape_file
|
||||
elseif tarfile =~# '\.\(gz\)$'
|
||||
exe "sil! r! gzip -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".g:tar_secure.shellescape(fname,1).decmp
|
||||
exe "sil! r! gzip -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp
|
||||
exe "read ".escape_file
|
||||
elseif tarfile =~# '\(\.tgz\|\.tbz\|\.txz\)'
|
||||
let filekind= s:Header(tarfile)
|
||||
if filekind =~? "bzip2"
|
||||
exe "sil! r! bzip2 -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".g:tar_secure.shellescape(fname,1).decmp
|
||||
if has("unix") && executable("file")
|
||||
let filekind= system("file ".shellescape(tarfile,1))
|
||||
else
|
||||
let filekind= ""
|
||||
endif
|
||||
if filekind =~ "bzip2"
|
||||
exe "sil! r! bzip2 -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp
|
||||
exe "read ".escape_file
|
||||
elseif filekind =~ "bzip3"
|
||||
exe "sil! r! bzip3 -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".g:tar_secure.shellescape(fname,1).decmp
|
||||
exe "sil! r! bzip3 -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp
|
||||
exe "read ".escape_file
|
||||
elseif filekind =~? "xz"
|
||||
exe "sil! r! xz -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".g:tar_secure.shellescape(fname,1).decmp
|
||||
elseif filekind =~ "XZ"
|
||||
exe "sil! r! xz -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp
|
||||
exe "read ".escape_file
|
||||
elseif filekind =~? "zstd"
|
||||
exe "sil! r! zstd --decompress --stdout -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".g:tar_secure.shellescape(fname,1).decmp
|
||||
elseif filekind =~ "Zstandard"
|
||||
exe "sil! r! zstd --decompress --stdout -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp
|
||||
exe "read ".escape_file
|
||||
elseif filekind =~? "gzip"
|
||||
exe "sil! r! gzip -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".g:tar_secure.shellescape(fname,1).decmp
|
||||
else
|
||||
exe "sil! r! gzip -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp
|
||||
exe "read ".escape_file
|
||||
endif
|
||||
|
||||
elseif tarfile =~# '\.lrp$'
|
||||
exe "sil! r! cat -- ".shellescape(tarfile,1)." | gzip -d -c - | ".g:tar_cmd." -".g:tar_readoptions." - ".g:tar_secure.shellescape(fname,1).decmp
|
||||
exe "sil! r! cat -- ".shellescape(tarfile,1)." | gzip -d -c - | ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp
|
||||
exe "read ".escape_file
|
||||
elseif tarfile =~# '\.lzma$'
|
||||
exe "sil! r! lzma -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".g:tar_secure.shellescape(fname,1).decmp
|
||||
exe "sil! r! lzma -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp
|
||||
exe "read ".escape_file
|
||||
elseif tarfile =~# '\.\(xz\|txz\)$'
|
||||
exe "sil! r! xz --decompress --stdout -- ".shellescape(tarfile,1)." | ".g:tar_cmd." -".g:tar_readoptions." - ".g:tar_secure.shellescape(fname,1).decmp
|
||||
exe "sil! r! xz --decompress --stdout -- ".shellescape(tarfile,1)." | ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp
|
||||
exe "read ".escape_file
|
||||
elseif tarfile =~# '\.\(lz4\|tlz4\)$'
|
||||
exe "sil! r! lz4 --decompress --stdout -- ".shellescape(tarfile,1)." | ".g:tar_cmd." -".g:tar_readoptions." - ".g:tar_secure.shellescape(fname,1).decmp
|
||||
exe "sil! r! lz4 --decompress --stdout -- ".shellescape(tarfile,1)." | ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp
|
||||
exe "read ".escape_file
|
||||
else
|
||||
if tarfile =~ '^\s*-'
|
||||
" A file name starting with a dash is taken as an option. Prepend ./ to avoid that.
|
||||
let tarfile = substitute(tarfile, '-', './-', '')
|
||||
endif
|
||||
exe "silent r! ".g:tar_cmd." -".g:tar_readoptions.shellescape(tarfile,1)." ".g:tar_secure.shellescape(fname,1).decmp
|
||||
exe "silent r! ".g:tar_cmd." -".g:tar_readoptions.shellescape(tarfile,1)." ".tar_secure.shellescape(fname,1).decmp
|
||||
exe "read ".escape_file
|
||||
endif
|
||||
if get(b:, 'leading_slash', 0)
|
||||
sil g/^tar: /d
|
||||
endif
|
||||
|
||||
redraw!
|
||||
|
||||
if v:shell_error != 0
|
||||
lcd ..
|
||||
if v:shell_error != 0
|
||||
cd ..
|
||||
call s:Rmdir("_ZIPVIM_")
|
||||
exe "lcd ".fnameescape(curdir)
|
||||
call s:Msg('tar#Read', 'error', $"sorry, unable to open or extract {tarfile} with {fname}")
|
||||
exe "cd ".fnameescape(curdir)
|
||||
echohl Error | echo "***error*** (tar#Read) sorry, unable to open or extract ".tarfile." with ".fname | echohl None
|
||||
endif
|
||||
|
||||
if doro
|
||||
@@ -417,54 +430,40 @@ fun! tar#Read(fname)
|
||||
endif
|
||||
|
||||
let b:tarfile= a:fname
|
||||
exe "file tarfile::".fnameescape(fname)
|
||||
|
||||
" cleanup
|
||||
keepj sil! 0d
|
||||
set nomod
|
||||
|
||||
let &report= repkeep
|
||||
exe "lcd ".fnameescape(curdir)
|
||||
silent exe "file tarfile::". fname->fnameescape()
|
||||
endfun
|
||||
|
||||
" ---------------------------------------------------------------------
|
||||
" tar#Write: {{{2
|
||||
fun! tar#Write(fname)
|
||||
let pwdkeep= getcwd()
|
||||
let repkeep= &report
|
||||
set report=10
|
||||
" temporary buffer variable workaround because too fucking tired. but it works now
|
||||
let curdir= b:curdir
|
||||
let tmpdir= b:tmpdir
|
||||
|
||||
if !exists("g:tar_secure") && a:fname =~ '^\s*-\|\s\+-'
|
||||
redraw!
|
||||
echohl WarningMsg | echo '***warning*** (tar#Write) rejecting tarfile member<'.a:fname.'> because of embedded "-"'
|
||||
return
|
||||
endif
|
||||
|
||||
" sanity checks
|
||||
if !executable(g:tar_cmd)
|
||||
redraw!
|
||||
let &report= repkeep
|
||||
return
|
||||
endif
|
||||
|
||||
let tarfile = substitute(b:tarfile,'tarfile:\(.\{-}\)::.*$','\1','')
|
||||
let fname = substitute(b:tarfile,'tarfile:.\{-}::\(.*\)$','\1','')
|
||||
|
||||
if get(b:, 'leading_slash', 0)
|
||||
call s:Msg('tar#Write', 'error', $"sorry, not attempting to update {tarfile} with {fname}")
|
||||
let &report= repkeep
|
||||
return
|
||||
endif
|
||||
|
||||
if !isdirectory(fnameescape(tmpdir))
|
||||
call mkdir(fnameescape(tmpdir), 'p')
|
||||
endif
|
||||
exe $"lcd {fnameescape(tmpdir)}"
|
||||
if isdirectory("_ZIPVIM_")
|
||||
call s:Rmdir("_ZIPVIM_")
|
||||
endif
|
||||
call mkdir("_ZIPVIM_")
|
||||
lcd _ZIPVIM_
|
||||
let dir = fnamemodify(fname, ':p:h')
|
||||
if dir !~# '_ZIPVIM_$'
|
||||
call mkdir(dir)
|
||||
endif
|
||||
|
||||
" handle compressed archives
|
||||
if tarfile =~# '\.bz2'
|
||||
call system("bzip2 -d -- ".shellescape(tarfile,0))
|
||||
@@ -500,10 +499,10 @@ fun! tar#Write(fname)
|
||||
let tarfile = substitute(tarfile,'\.lzma','','e')
|
||||
let compress= "lzma -- ".shellescape(tarfile,0)
|
||||
endif
|
||||
" Note: no support for name.tar.tbz/.txz/.tgz/.tlz4/.tzst
|
||||
|
||||
if v:shell_error != 0
|
||||
call s:Msg('tar#Write', 'error', $"sorry, unable to update {tarfile} with {fname}")
|
||||
redraw!
|
||||
echohl Error | echo "***error*** (tar#Write) sorry, unable to update ".tarfile." with ".fname | echohl None
|
||||
else
|
||||
|
||||
if fname =~ '/'
|
||||
@@ -521,22 +520,28 @@ fun! tar#Write(fname)
|
||||
let tarfile = substitute(tarfile, '-', './-', '')
|
||||
endif
|
||||
|
||||
" don't overwrite a file forcefully
|
||||
exe "w ".fnameescape(fname)
|
||||
if exists("g:tar_secure")
|
||||
let tar_secure= " -- "
|
||||
else
|
||||
let tar_secure= " "
|
||||
endif
|
||||
exe "w! ".fnameescape(fname)
|
||||
if has("win32unix") && executable("cygpath")
|
||||
let tarfile = substitute(system("cygpath ".shellescape(tarfile,0)),'\n','','e')
|
||||
endif
|
||||
|
||||
" delete old file from tarfile
|
||||
" Note: BSD tar does not support --delete flag
|
||||
call system(g:tar_cmd." ".g:tar_delfile." ".shellescape(tarfile,0).g:tar_secure.shellescape(fname,0))
|
||||
call system(g:tar_cmd." ".g:tar_delfile." ".shellescape(tarfile,0).tar_secure.shellescape(fname,0))
|
||||
if v:shell_error != 0
|
||||
call s:Msg('tar#Write', 'error', $"sorry, unable to update {fnameescape(tarfile)} with {fnameescape(fname)} --delete not supported?")
|
||||
redraw!
|
||||
echohl Error | echo "***error*** (tar#Write) sorry, unable to update ".fnameescape(tarfile)." with ".fnameescape(fname) | echohl None
|
||||
else
|
||||
|
||||
" update tarfile with new file
|
||||
call system(g:tar_cmd." -".g:tar_writeoptions." ".shellescape(tarfile,0).g:tar_secure.shellescape(fname,0))
|
||||
call system(g:tar_cmd." -".g:tar_writeoptions." ".shellescape(tarfile,0).tar_secure.shellescape(fname,0))
|
||||
if v:shell_error != 0
|
||||
call s:Msg('tar#Write', 'error', $"sorry, unable to update {fnameescape(tarfile)} with {fnameescape(fname)}")
|
||||
redraw!
|
||||
echohl Error | echo "***error*** (tar#Write) sorry, unable to update ".fnameescape(tarfile)." with ".fnameescape(fname) | echohl None
|
||||
elseif exists("compress")
|
||||
call system(compress)
|
||||
if exists("tgz")
|
||||
@@ -562,9 +567,9 @@ fun! tar#Write(fname)
|
||||
endif
|
||||
|
||||
" cleanup and restore current directory
|
||||
lcd ..
|
||||
cd ..
|
||||
call s:Rmdir("_ZIPVIM_")
|
||||
exe "lcd ".fnameescape(pwdkeep)
|
||||
exe "cd ".fnameescape(curdir)
|
||||
setlocal nomod
|
||||
|
||||
let &report= repkeep
|
||||
@@ -577,7 +582,6 @@ fun! tar#Diff(userfname,fname)
|
||||
if a:userfname != ""
|
||||
let fname= a:userfname
|
||||
endif
|
||||
exe "lcd ".fnameescape(b:tmpdir). '/_ZIPVIM_'
|
||||
if filereadable(fname)
|
||||
" sets current file (from tarball) for diff'ing
|
||||
" splits window vertically
|
||||
@@ -601,6 +605,12 @@ fun! tar#Extract()
|
||||
set report=10
|
||||
let fname= getline(".")
|
||||
|
||||
if !exists("g:tar_secure") && fname =~ '^\s*-\|\s\+-'
|
||||
redraw!
|
||||
echohl WarningMsg | echo '***warning*** (tar#BrowseSelect) rejecting tarfile member<'.fname.'> because of embedded "-"'
|
||||
return
|
||||
endif
|
||||
|
||||
" sanity check
|
||||
if fname =~ '^"'
|
||||
let &report= repkeep
|
||||
@@ -610,20 +620,20 @@ fun! tar#Extract()
|
||||
let tarball = expand("%")
|
||||
let tarbase = substitute(tarball,'\..*$','','')
|
||||
|
||||
let extractcmd= s:WinPath(g:tar_extractcmd)
|
||||
let extractcmd= netrw#WinPath(g:tar_extractcmd)
|
||||
if filereadable(tarbase.".tar")
|
||||
call system(extractcmd." ".shellescape(tarbase).".tar ".shellescape(fname))
|
||||
if v:shell_error != 0
|
||||
call s:Msg('tar#Extract', 'error', $"{extractcmd} {tarbase}.tar {fname}: failed!")
|
||||
echohl Error | echo "***error*** ".extractcmd." ".tarbase.".tar ".fname.": failed!" | echohl NONE
|
||||
else
|
||||
echo "***note*** successfully extracted ". fname
|
||||
echo "***note*** successfully extracted ".fname
|
||||
endif
|
||||
|
||||
elseif filereadable(tarbase.".tgz")
|
||||
let extractcmd= substitute(extractcmd,"-","-z","")
|
||||
call system(extractcmd." ".shellescape(tarbase).".tgz ".shellescape(fname))
|
||||
if v:shell_error != 0
|
||||
call s:Msg('tar#Extract', 'error', $"{extractcmd} {tarbase}.tgz {fname}: failed!")
|
||||
echohl Error | echo "***error*** ".extractcmd." ".tarbase.".tgz ".fname.": failed!" | echohl NONE
|
||||
else
|
||||
echo "***note*** successfully extracted ".fname
|
||||
endif
|
||||
@@ -632,7 +642,7 @@ fun! tar#Extract()
|
||||
let extractcmd= substitute(extractcmd,"-","-z","")
|
||||
call system(extractcmd." ".shellescape(tarbase).".tar.gz ".shellescape(fname))
|
||||
if v:shell_error != 0
|
||||
call s:Msg('tar#Extract', 'error', $"{extractcmd} {tarbase}.tar.gz {fname}: failed!")
|
||||
echohl Error | echo "***error*** ".extractcmd." ".tarbase.".tar.gz ".fname.": failed!" | echohl NONE
|
||||
else
|
||||
echo "***note*** successfully extracted ".fname
|
||||
endif
|
||||
@@ -641,7 +651,7 @@ fun! tar#Extract()
|
||||
let extractcmd= substitute(extractcmd,"-","-j","")
|
||||
call system(extractcmd." ".shellescape(tarbase).".tbz ".shellescape(fname))
|
||||
if v:shell_error != 0
|
||||
call s:Msg('tar#Extract', 'error', $"{extractcmd} {tarbase}.tbz {fname}: failed!")
|
||||
echohl Error | echo "***error*** ".extractcmd."j ".tarbase.".tbz ".fname.": failed!" | echohl NONE
|
||||
else
|
||||
echo "***note*** successfully extracted ".fname
|
||||
endif
|
||||
@@ -650,7 +660,7 @@ fun! tar#Extract()
|
||||
let extractcmd= substitute(extractcmd,"-","-j","")
|
||||
call system(extractcmd." ".shellescape(tarbase).".tar.bz2 ".shellescape(fname))
|
||||
if v:shell_error != 0
|
||||
call s:Msg('tar#Extract', 'error', $"{extractcmd} {tarbase}.tar.bz2 {fname}: failed!")
|
||||
echohl Error | echo "***error*** ".extractcmd."j ".tarbase.".tar.bz2 ".fname.": failed!" | echohl NONE
|
||||
else
|
||||
echo "***note*** successfully extracted ".fname
|
||||
endif
|
||||
@@ -659,7 +669,7 @@ fun! tar#Extract()
|
||||
let extractcmd= substitute(extractcmd,"-","-j","")
|
||||
call system(extractcmd." ".shellescape(tarbase).".tar.bz3 ".shellescape(fname))
|
||||
if v:shell_error != 0
|
||||
call s:Msg('tar#Extract', 'error', $"{extractcmd} {tarbase}.tar.bz3 {fname}: failed!")
|
||||
echohl Error | echo "***error*** ".extractcmd."j ".tarbase.".tar.bz3 ".fname.": failed!" | echohl NONE
|
||||
else
|
||||
echo "***note*** successfully extracted ".fname
|
||||
endif
|
||||
@@ -668,7 +678,7 @@ fun! tar#Extract()
|
||||
let extractcmd= substitute(extractcmd,"-","-J","")
|
||||
call system(extractcmd." ".shellescape(tarbase).".txz ".shellescape(fname))
|
||||
if v:shell_error != 0
|
||||
call s:Msg('tar#Extract', 'error', $"{extractcmd} {tarbase}.txz {fname}: failed!")
|
||||
echohl Error | echo "***error*** ".extractcmd." ".tarbase.".txz ".fname.": failed!" | echohl NONE
|
||||
else
|
||||
echo "***note*** successfully extracted ".fname
|
||||
endif
|
||||
@@ -677,7 +687,7 @@ fun! tar#Extract()
|
||||
let extractcmd= substitute(extractcmd,"-","-J","")
|
||||
call system(extractcmd." ".shellescape(tarbase).".tar.xz ".shellescape(fname))
|
||||
if v:shell_error != 0
|
||||
call s:Msg('tar#Extract', 'error', $"{extractcmd} {tarbase}.tar.xz {fname}: failed!")
|
||||
echohl Error | echo "***error*** ".extractcmd." ".tarbase.".tar.xz ".fname.": failed!" | echohl NONE
|
||||
else
|
||||
echo "***note*** successfully extracted ".fname
|
||||
endif
|
||||
@@ -686,7 +696,7 @@ fun! tar#Extract()
|
||||
let extractcmd= substitute(extractcmd,"-","--zstd","")
|
||||
call system(extractcmd." ".shellescape(tarbase).".tzst ".shellescape(fname))
|
||||
if v:shell_error != 0
|
||||
call s:Msg('tar#Extract', 'error', $"{extractcmd} {tarbase}.tzst {fname}: failed!")
|
||||
echohl Error | echo "***error*** ".extractcmd." ".tarbase.".tzst ".fname.": failed!" | echohl NONE
|
||||
else
|
||||
echo "***note*** successfully extracted ".fname
|
||||
endif
|
||||
@@ -695,7 +705,7 @@ fun! tar#Extract()
|
||||
let extractcmd= substitute(extractcmd,"-","--zstd","")
|
||||
call system(extractcmd." ".shellescape(tarbase).".tar.zst ".shellescape(fname))
|
||||
if v:shell_error != 0
|
||||
call s:Msg('tar#Extract', 'error', $"{extractcmd} {tarbase}.tar.zst {fname}: failed!")
|
||||
echohl Error | echo "***error*** ".extractcmd." ".tarbase.".tar.zst ".fname.": failed!" | echohl NONE
|
||||
else
|
||||
echo "***note*** successfully extracted ".fname
|
||||
endif
|
||||
@@ -704,7 +714,7 @@ fun! tar#Extract()
|
||||
let extractcmd= substitute(extractcmd,"-","-I lz4","")
|
||||
call system(extractcmd." ".shellescape(tarbase).".tlz4 ".shellescape(fname))
|
||||
if v:shell_error != 0
|
||||
call s:Msg('tar#Extract', 'error', $"{extractcmd} {tarbase}.tlz4 {fname}: failed!")
|
||||
echohl Error | echo "***error*** ".extractcmd." ".tarbase.".tlz4 ".fname.": failed!" | echohl NONE
|
||||
else
|
||||
echo "***note*** successfully extracted ".fname
|
||||
endif
|
||||
@@ -713,7 +723,7 @@ fun! tar#Extract()
|
||||
let extractcmd= substitute(extractcmd,"-","-I lz4","")
|
||||
call system(extractcmd." ".shellescape(tarbase).".tar.lz4".shellescape(fname))
|
||||
if v:shell_error != 0
|
||||
call s:Msg('tar#Extract', 'error', $"{extractcmd} {tarbase}.tar.lz4 {fname}: failed!")
|
||||
echohl Error | echo "***error*** ".extractcmd." ".tarbase.".tar.lz4 ".fname.": failed!" | echohl NONE
|
||||
else
|
||||
echo "***note*** successfully extracted ".fname
|
||||
endif
|
||||
@@ -726,50 +736,15 @@ endfun
|
||||
" ---------------------------------------------------------------------
|
||||
" s:Rmdir: {{{2
|
||||
fun! s:Rmdir(fname)
|
||||
call delete(a:fname, 'rf')
|
||||
endfun
|
||||
|
||||
" s:FileHeader: {{{2
|
||||
fun! s:Header(fname)
|
||||
let header= readblob(a:fname, 0, 6)
|
||||
" Nvim: see https://github.com/neovim/neovim/pull/34968
|
||||
if header[0:2] == 0z425A68 " bzip2 header
|
||||
return "bzip2"
|
||||
elseif header[0:2] == 0z425A33 " bzip3 header
|
||||
return "bzip3"
|
||||
elseif header == 0zFD377A58.5A00 " xz header
|
||||
return "xz"
|
||||
elseif header[0:3] == 0z28B52FFD " zstd header
|
||||
return "zstd"
|
||||
elseif header[0:3] == 0z04224D18 " lz4 header
|
||||
return "lz4"
|
||||
elseif (header[0:1] == 0z1F9D ||
|
||||
\ header[0:1] == 0z1F8B ||
|
||||
\ header[0:1] == 0z1F9E ||
|
||||
\ header[0:1] == 0z1FA0 ||
|
||||
\ header[0:1] == 0z1F1E)
|
||||
return "gzip"
|
||||
endif
|
||||
return "unknown"
|
||||
endfun
|
||||
|
||||
" ---------------------------------------------------------------------
|
||||
" s:WinPath: {{{2
|
||||
fun! s:WinPath(path)
|
||||
if (!g:netrw_cygwin || &shell !~ '\%(\<bash\>\|\<zsh\>\)\%(\.exe\)\=$') && has("win32")
|
||||
" remove cygdrive prefix, if present
|
||||
let path = substitute(a:path, '/cygdrive/\(.\)', '\1:', '')
|
||||
" remove trailing slash (Win95)
|
||||
let path = substitute(path, '\(\\\|/\)$', '', 'g')
|
||||
" remove escaped spaces
|
||||
let path = substitute(path, '\ ', ' ', 'g')
|
||||
" convert slashes to backslashes
|
||||
let path = substitute(path, '/', '\', 'g')
|
||||
if has("unix")
|
||||
call system("/bin/rm -rf -- ".shellescape(a:fname,0))
|
||||
elseif has("win32") || has("win95") || has("win64") || has("win16")
|
||||
if &shell =~? "sh$"
|
||||
call system("/bin/rm -rf -- ".shellescape(a:fname,0))
|
||||
else
|
||||
let path = a:path
|
||||
call system("del /S ".shellescape(a:fname,0))
|
||||
endif
|
||||
endif
|
||||
|
||||
return path
|
||||
endfun
|
||||
|
||||
" =====================================================================
|
||||
|
@@ -15,7 +15,6 @@
|
||||
" 2024 Aug 18 by Vim Project: correctly handle special globbing chars
|
||||
" 2024 Aug 21 by Vim Project: simplify condition to detect MS-Windows
|
||||
" 2025 Mar 11 by Vim Project: handle filenames with leading '-' correctly
|
||||
" 2025 Jul 12 by Vim Project: drop ../ on write to prevent path traversal attacks
|
||||
" License: Vim License (see vim's :help license)
|
||||
" Copyright: Copyright (C) 2005-2019 Charles E. Campbell {{{1
|
||||
" Permission is hereby granted to use and distribute this code,
|
||||
@@ -72,9 +71,8 @@ fun! s:Mess(group, msg)
|
||||
echohl Normal
|
||||
endfun
|
||||
|
||||
if !has('nvim-0.10') && v:version < 901
|
||||
" required for defer
|
||||
call s:Mess('WarningMsg', "***warning*** this version of zip needs vim 9.1 or later")
|
||||
if v:version < 702
|
||||
call s:Mess('WarningMsg', "***warning*** this version of zip needs vim 7.2 or later")
|
||||
finish
|
||||
endif
|
||||
" sanity checks
|
||||
@@ -237,7 +235,6 @@ endfun
|
||||
" zip#Write: {{{2
|
||||
fun! zip#Write(fname)
|
||||
let dict = s:SetSaneOpts()
|
||||
let need_rename = 0
|
||||
defer s:RestoreOpts(dict)
|
||||
|
||||
" sanity checks
|
||||
@@ -245,6 +242,10 @@ fun! zip#Write(fname)
|
||||
call s:Mess('Error', "***error*** (zip#Write) sorry, your system doesn't appear to have the ".g:zip_zipcmd." program")
|
||||
return
|
||||
endif
|
||||
if !exists("*mkdir")
|
||||
call s:Mess('Error', "***error*** (zip#Write) sorry, mkdir() doesn't work on your system")
|
||||
return
|
||||
endif
|
||||
|
||||
let curdir= getcwd()
|
||||
let tmpdir= tempname()
|
||||
@@ -272,11 +273,6 @@ fun! zip#Write(fname)
|
||||
let zipfile = substitute(a:fname,'^.\{-}zipfile://\(.\{-}\)::[^\\].*$','\1','')
|
||||
let fname = substitute(a:fname,'^.\{-}zipfile://.\{-}::\([^\\].*\)$','\1','')
|
||||
endif
|
||||
if fname =~ '^[.]\{1,2}/'
|
||||
call system(g:zip_zipcmd." -d ".s:Escape(fnamemodify(zipfile,":p"),0)." ".s:Escape(fname,0))
|
||||
let fname = fname->substitute('^\([.]\{1,2}/\)\+', '', 'g')
|
||||
let need_rename = 1
|
||||
endif
|
||||
|
||||
if fname =~ '/'
|
||||
let dirpath = substitute(fname,'/[^/]\+$','','e')
|
||||
@@ -289,8 +285,7 @@ fun! zip#Write(fname)
|
||||
let zipfile= curdir.'/'.zipfile
|
||||
endif
|
||||
|
||||
" don't overwrite files forcefully
|
||||
exe "w ".fnameescape(fname)
|
||||
exe "w! ".fnameescape(fname)
|
||||
if has("win32unix") && executable("cygpath")
|
||||
let zipfile = substitute(system("cygpath ".s:Escape(zipfile,0)),'\n','','e')
|
||||
endif
|
||||
@@ -316,9 +311,6 @@ fun! zip#Write(fname)
|
||||
let &binary = binkeep
|
||||
q!
|
||||
unlet s:zipfile_{winnr()}
|
||||
elseif need_rename
|
||||
exe $"sil keepalt file {fnameescape($"zipfile://{zipfile}::{fname}")}"
|
||||
call s:Mess('Warning', "***error*** (zip#Browse) Path Traversal Attack detected, dropping relative path")
|
||||
endif
|
||||
|
||||
" cleanup and restore current directory
|
||||
@@ -327,6 +319,7 @@ fun! zip#Write(fname)
|
||||
call s:ChgDir(curdir,s:WARNING,"(zip#Write) unable to return to ".curdir."!")
|
||||
call delete(tmpdir, "rf")
|
||||
setlocal nomod
|
||||
|
||||
endfun
|
||||
|
||||
" ---------------------------------------------------------------------
|
||||
@@ -344,9 +337,6 @@ fun! zip#Extract()
|
||||
if fname =~ '/$'
|
||||
call s:Mess('Error', "***error*** (zip#Extract) Please specify a file, not a directory")
|
||||
return
|
||||
elseif fname =~ '^[.]\?[.]/'
|
||||
call s:Mess('Error', "***error*** (zip#Browse) Path Traversal Attack detected, not extracting!")
|
||||
return
|
||||
endif
|
||||
if filereadable(fname)
|
||||
call s:Mess('Error', "***error*** (zip#Extract) <" .. fname .."> already exists in directory, not overwriting!")
|
||||
@@ -378,6 +368,7 @@ fun! zip#Extract()
|
||||
else
|
||||
echomsg "***note*** successfully extracted ".fname
|
||||
endif
|
||||
|
||||
endfun
|
||||
|
||||
" ---------------------------------------------------------------------
|
||||
|
@@ -47,7 +47,6 @@ hi('WildMenu', { fg = 'Black', bg = 'Yellow', ctermfg = 'Black', cterm
|
||||
hi('VertSplit', { link = 'Normal' })
|
||||
hi('WinSeparator', { link = 'VertSplit' })
|
||||
hi('WinBarNC', { link = 'WinBar' })
|
||||
hi('DiffTextAdd', { link = 'DiffText' })
|
||||
hi('EndOfBuffer', { link = 'NonText' })
|
||||
hi('LineNrAbove', { link = 'LineNr' })
|
||||
hi('LineNrBelow', { link = 'LineNr' })
|
||||
@@ -62,8 +61,6 @@ hi('PmenuMatchSel', { link = 'PmenuSel' })
|
||||
hi('PmenuExtra', { link = 'Pmenu' })
|
||||
hi('PmenuExtraSel', { link = 'PmenuSel' })
|
||||
hi('ComplMatchIns', {})
|
||||
hi('ComplHint', { link = 'NonText' })
|
||||
hi('ComplHintMore', { link = 'MoreMsg' })
|
||||
hi('Substitute', { link = 'Search' })
|
||||
hi('Whitespace', { link = 'NonText' })
|
||||
hi('MsgSeparator', { link = 'StatusLine' })
|
||||
@@ -136,7 +133,6 @@ hi('DiagnosticDeprecated', { sp = 'Red', strikethrough = true, cterm =
|
||||
hi('DiagnosticUnnecessary', { link = 'Comment' })
|
||||
hi('LspInlayHint', { link = 'NonText' })
|
||||
hi('SnippetTabstop', { link = 'Visual' })
|
||||
hi('SnippetTabstopActive', { link = 'SnippetTabstop' })
|
||||
|
||||
-- Text
|
||||
hi('@markup.raw', { link = 'Comment' })
|
||||
|
@@ -1,25 +0,0 @@
|
||||
" Vim compiler file
|
||||
" Language: Gleam
|
||||
" Maintainer: Kirill Morozov <kirill@robotix.pro>
|
||||
" Based On: https://github.com/gleam-lang/gleam.vim
|
||||
" Last Change: 2025 Apr 21
|
||||
|
||||
if exists('current_compiler')
|
||||
finish
|
||||
endif
|
||||
let current_compiler = "gleam_build"
|
||||
|
||||
CompilerSet makeprg=gleam\ build
|
||||
|
||||
" Example error message:
|
||||
"
|
||||
" error: Unknown variable
|
||||
" ┌─ /home/michael/root/projects/tutorials/gleam/try/code/src/main.gleam:19:18
|
||||
" │
|
||||
" 19 │ Ok(tuple(name, spot))
|
||||
" │ ^^^^ did you mean `sport`?
|
||||
"
|
||||
" The name `spot` is not in scope here.
|
||||
CompilerSet errorformat=%Eerror:\ %m,%Wwarning:\ %m,%C\ %#┌─%#\ %f:%l:%c\ %#-%#
|
||||
|
||||
" vim: sw=2 sts=2 et
|
@@ -2,7 +2,6 @@
|
||||
" Compiler: Pandoc
|
||||
" Maintainer: Konfekt
|
||||
" Last Change: 2024 Nov 19
|
||||
" 2025 May 15 Update the title regex for CompilerSet #17321
|
||||
"
|
||||
" Expects output file extension, say `:make html` or `:make pdf`.
|
||||
" Passes additional arguments to pandoc, say `:make html --self-contained`.
|
||||
@@ -52,7 +51,7 @@ endfunction
|
||||
|
||||
execute 'CompilerSet makeprg=pandoc'..escape(
|
||||
\ ' --standalone'..
|
||||
\ (s:PandocFiletype(&filetype) ==# 'markdown' && (getline(1) =~# '^%\s\+\S\+' || (search('^title:\s\+\S\+', 'cnw') > 0)) ?
|
||||
\ (s:PandocFiletype(&filetype) ==# 'markdown' && (getline(1) =~# '^%\s\+\S\+' || (search('^title:\s+\S+', 'cnw') > 0)) ?
|
||||
\ '' : ' --metadata title=%:t:r:S')..
|
||||
\ ' '..s:PandocLang()..
|
||||
\ ' --from='..s:PandocFiletype(&filetype)..
|
||||
|
@@ -1,12 +0,0 @@
|
||||
" Vim compiler file
|
||||
" Compiler: PHPStan
|
||||
" Maintainer: Dietrich Moerman <dietrich.moerman@gmail.com>
|
||||
" Last Change: 2025 Jul 17
|
||||
|
||||
if exists("current_compiler")
|
||||
finish
|
||||
endif
|
||||
let current_compiler = "phpstan"
|
||||
|
||||
CompilerSet makeprg=composer\ exec\ --\ phpstan\ analyse\ -v\ --no-progress\ --error-format=raw
|
||||
CompilerSet errorformat=%f:%l:%m,%-G%.%#
|
3251
runtime/doc/api.txt
3251
runtime/doc/api.txt
File diff suppressed because it is too large
Load Diff
@@ -73,16 +73,11 @@ Or use `:execute`: >
|
||||
Note that special characters (e.g., "%", "<cword>") in the ":autocmd"
|
||||
arguments are not expanded when the autocommand is defined. These will be
|
||||
expanded when the Event is recognized, and the {cmd} is executed. The only
|
||||
exception is that "<sfile>" (unlike "<script>") is expanded when the autocmd
|
||||
is defined. Example:
|
||||
exception is that "<sfile>" is expanded when the autocmd is defined. Example:
|
||||
>
|
||||
:au BufNewFile,BufRead *.html so <sfile>:h/html.vim
|
||||
|
||||
Here Vim expands <sfile> to the name of the file containing this line.
|
||||
However, <sfile> works differently in a function, in which case it's better to
|
||||
use `:execute` with <script> to achieve the same purpose:
|
||||
>
|
||||
:exe $'au BufNewFile,BufRead *.html so {expand("<script>:h")}/html.vim'
|
||||
|
||||
`:autocmd` adds to the list of autocommands regardless of whether they are
|
||||
already present. When your .vimrc file is sourced twice, the autocommands
|
||||
@@ -262,7 +257,7 @@ BufLeave Before leaving to another buffer. Also when
|
||||
Not used for ":qa" or ":q" when exiting Vim.
|
||||
*BufModifiedSet*
|
||||
BufModifiedSet After the `'modified'` value of a buffer has
|
||||
been changed. Special-case of |OptionSet|.
|
||||
been changed.
|
||||
*BufNew*
|
||||
BufNew After creating a new buffer (except during
|
||||
startup, see |VimEnter|) or renaming an
|
||||
@@ -306,7 +301,6 @@ BufUnload Before unloading a buffer, when the text in
|
||||
going to exit.
|
||||
NOTE: Current buffer "%" is not the target
|
||||
buffer "<afile>", "<abuf>". |<buffer=abuf>|
|
||||
*E1546*
|
||||
Do not switch buffers or windows!
|
||||
Not triggered when exiting and v:dying is 2 or
|
||||
more.
|
||||
@@ -350,8 +344,7 @@ BufWriteCmd Before writing the whole buffer to a file.
|
||||
The buffer contents should not be changed.
|
||||
When the command resets 'modified' the undo
|
||||
information is adjusted to mark older undo
|
||||
states as 'modified', like |:write| does. Use
|
||||
the |'[| and |']| marks for the range of lines.
|
||||
states as 'modified', like |:write| does.
|
||||
|Cmd-event|
|
||||
*BufWritePost*
|
||||
BufWritePost After writing the whole buffer to a file
|
||||
@@ -407,16 +400,6 @@ CmdlineLeave Before leaving the command-line (including
|
||||
Note: `abort` can only be changed from false
|
||||
to true: cannot execute an already aborted
|
||||
cmdline by changing it to false.
|
||||
*CmdlineLeavePre*
|
||||
CmdlineLeavePre Just before leaving the command line, and
|
||||
before |CmdlineLeave|. Useful for capturing
|
||||
completion info with |cmdcomplete_info()|, as
|
||||
this information is cleared before
|
||||
|CmdlineLeave| is triggered. Triggered for
|
||||
non-interactive use of ":" in a mapping, but
|
||||
not when using |<Cmd>|. Also triggered when
|
||||
abandoning the command line by typing CTRL-C
|
||||
or <Esc>. <afile> is set to |cmdline-char|.
|
||||
*CmdwinEnter*
|
||||
CmdwinEnter After entering the command-line window.
|
||||
Useful for setting options specifically for
|
||||
@@ -494,16 +477,27 @@ CompleteDone After Insert mode completion is done. Either
|
||||
- "accept": completion was
|
||||
accepted by |complete_CTRL-Y|.
|
||||
- "cancel": completion was
|
||||
stopped by |complete_CTRL-E|.
|
||||
stopped by |complete_CTRL-E.
|
||||
- "discard": completion was
|
||||
abandoned for other reason.
|
||||
|
||||
*CursorHold*
|
||||
CursorHold When there is no user input for 'updatetime'
|
||||
duration, in Normal-mode. Not triggered while
|
||||
waiting for a command argument or movement
|
||||
after an operator, nor while |recording|
|
||||
a macro. See |CursorHold-example|.
|
||||
CursorHold When the user doesn't press a key for the time
|
||||
specified with 'updatetime'. Not triggered
|
||||
until the user has pressed a key (i.e. doesn't
|
||||
fire every 'updatetime' ms if you leave Vim to
|
||||
make some coffee. :) See |CursorHold-example|
|
||||
for previewing tags.
|
||||
This event is only triggered in Normal mode.
|
||||
It is not triggered when waiting for a command
|
||||
argument to be typed, or a movement after an
|
||||
operator.
|
||||
While recording the CursorHold event is not
|
||||
triggered. |q|
|
||||
*<CursorHold>*
|
||||
Internally the autocommand is triggered by the
|
||||
<CursorHold> key. In an expression mapping
|
||||
|getchar()| may see this character.
|
||||
|
||||
Note: Interactive commands cannot be used for
|
||||
this event. There is no hit-enter prompt,
|
||||
@@ -654,14 +648,14 @@ FileType When the 'filetype' option has been set. The
|
||||
FileWriteCmd Before writing to a file, when not writing the
|
||||
whole buffer. Should do the writing to the
|
||||
file. Should not change the buffer. Use the
|
||||
|'[| and |']| marks for the range of lines.
|
||||
'[ and '] marks for the range of lines.
|
||||
|Cmd-event|
|
||||
*FileWritePost*
|
||||
FileWritePost After writing to a file, when not writing the
|
||||
whole buffer.
|
||||
*FileWritePre*
|
||||
FileWritePre Before writing to a file, when not writing the
|
||||
whole buffer. Use the |'[| and |']| marks for the
|
||||
whole buffer. Use the '[ and '] marks for the
|
||||
range of lines.
|
||||
*FilterReadPost*
|
||||
FilterReadPost After reading a file from a filter command.
|
||||
@@ -788,31 +782,6 @@ ModeChanged After changing the mode. The pattern is
|
||||
:au ModeChanged [vV\x16]*:* let &l:rnu = mode() =~# '^[vV\x16]'
|
||||
:au ModeChanged *:[vV\x16]* let &l:rnu = mode() =~# '^[vV\x16]'
|
||||
:au WinEnter,WinLeave * let &l:rnu = mode() =~# '^[vV\x16]'
|
||||
Progress *Progress*
|
||||
After a progress message is created or updated via
|
||||
`nvim_echo`. The pattern is matched against
|
||||
title of the message. The |event-data| contains:
|
||||
id: id of the message
|
||||
text: text of the message
|
||||
title: title of the progress message
|
||||
status: status of the progress message
|
||||
percent: how much progress has been
|
||||
made for this progress item
|
||||
Usage example:
|
||||
>
|
||||
vim.api.nvim_create_autocmd('Progress', {
|
||||
pattern={"term"},
|
||||
callback = function(ev)
|
||||
print(string.format('event fired: %s', vim.inspect(ev)))
|
||||
end
|
||||
})
|
||||
local id = vim.api.nvim_echo({{'searching...'}}, true,
|
||||
{kind='progress', status='running', percent=10, title="term"})
|
||||
vim.api.nvim_echo({{'searching'}}, true,
|
||||
{id = id, kind='progress', status='running', percent=50, title="term"})
|
||||
vim.api.nvim_echo({{'done'}}, true,
|
||||
{id = id, kind='progress', status='success', percent=100, title="term"})
|
||||
|
||||
< *OptionSet*
|
||||
OptionSet After setting an option (except during
|
||||
|startup|). The |autocmd-pattern| is matched
|
||||
@@ -853,10 +822,6 @@ OptionSet After setting an option (except during
|
||||
always use |:noautocmd| to prevent triggering
|
||||
OptionSet.
|
||||
|
||||
Note: Not triggered by the 'modified' option;
|
||||
the |BufModifiedSet| event may be used to
|
||||
handle that.
|
||||
|
||||
Non-recursive: |:set| in the autocommand does
|
||||
not trigger OptionSet again.
|
||||
|
||||
@@ -1069,7 +1034,7 @@ TermRequest When a |:terminal| child process emits an OSC,
|
||||
autocommand defined without |autocmd-nested|.
|
||||
|
||||
*TermResponse*
|
||||
TermResponse When Nvim receives a DA1, OSC, DCS, or APC response from
|
||||
TermResponse When Nvim receives an OSC or DCS response from
|
||||
the host terminal. Sets |v:termresponse|. The
|
||||
|event-data| is a table with the following fields:
|
||||
|
||||
@@ -1093,7 +1058,7 @@ TermResponse When Nvim receives a DA1, OSC, DCS, or APC response from
|
||||
local r, g, b = resp:match("\027%]4;1;rgb:(%w+)/(%w+)/(%w+)")
|
||||
end,
|
||||
})
|
||||
vim.api.nvim_ui_send("\027]4;1;?\027\\")
|
||||
io.stdout:write("\027]4;1;?\027\\")
|
||||
<
|
||||
*TextChanged*
|
||||
TextChanged After a change was made to the text in the
|
||||
@@ -1221,13 +1186,6 @@ WinScrolled After any window in the current tab page
|
||||
or changed width or height. See
|
||||
|win-scrolled-resized|.
|
||||
|
||||
Note: This can not be skipped with
|
||||
`:noautocmd`, because it triggers after
|
||||
processing normal commands when Vim is back in
|
||||
the main loop. If you want to disable this,
|
||||
consider setting the 'eventignore' option
|
||||
instead.
|
||||
|
||||
The pattern is matched against the |window-ID|
|
||||
of the first window that scrolled or resized.
|
||||
Both <amatch> and <afile> are set to the
|
||||
|
@@ -22,13 +22,13 @@ For inserting text see |insert.txt|.
|
||||
"dl".
|
||||
The <Del> key does not take a [count]. Instead, it
|
||||
deletes the last character of the count.
|
||||
See 'whichwrap' for deleting a line break (join
|
||||
See |'whichwrap'| for deleting a line break (join
|
||||
lines).
|
||||
|
||||
*X* *dh*
|
||||
["x]X Delete [count] characters before the cursor [into
|
||||
register x] (not |linewise|). Does the same as "dh".
|
||||
Also see 'whichwrap'.
|
||||
Also see |'whichwrap'|.
|
||||
|
||||
*d*
|
||||
["x]d{motion} Delete text that {motion} moves over [into register
|
||||
@@ -141,8 +141,8 @@ the 'joinspaces' option is on, these commands insert two spaces after a '.',
|
||||
The 'B' and 'M' flags in 'formatoptions' change the behavior for inserting
|
||||
spaces before and after a multibyte character |fo-table|.
|
||||
|
||||
The |'[| mark is set at the end of the first line that was joined, |']| at the
|
||||
end of the resulting line.
|
||||
The '[ mark is set at the end of the first line that was joined, '] at the end
|
||||
of the resulting line.
|
||||
|
||||
|
||||
==============================================================================
|
||||
@@ -583,9 +583,9 @@ with ".". Vim does not recognize a comment (starting with '"') after the
|
||||
={motion} Filter {motion} lines through the external program
|
||||
given with the 'equalprg' option. When the 'equalprg'
|
||||
option is empty (this is the default), use the
|
||||
internal formatting function |C-indenting| and 'lisp'.
|
||||
But when 'indentexpr' is not empty, it will be used
|
||||
instead |indent-expression|.
|
||||
internal formatting function |C-indenting| and
|
||||
|'lisp'|. But when 'indentexpr' is not empty, it will
|
||||
be used instead |indent-expression|.
|
||||
|
||||
*==*
|
||||
== Filter [count] lines like with ={motion}.
|
||||
@@ -644,9 +644,8 @@ original user.
|
||||
Repeat last :substitute with same search pattern and
|
||||
substitute string, but without the same flags. You
|
||||
may add [flags], see |:s_flags|.
|
||||
Note that after `:substitute` the '&' and '#' flags
|
||||
can't be used, they're recognized as a pattern
|
||||
separator.
|
||||
Note that after `:substitute` the '&' flag can't be
|
||||
used, it's recognized as a pattern separator.
|
||||
The space between `:substitute` and the 'c', 'g',
|
||||
'i', 'I' and 'r' flags isn't required, but in scripts
|
||||
it's a good idea to keep it to avoid confusion.
|
||||
@@ -949,26 +948,22 @@ This replaces each 'E' character with a euro sign. Read more in |<Char->|.
|
||||
|
||||
4.3 Changing tabs *change-tabs*
|
||||
*:ret* *:retab* *:retab!*
|
||||
:[range]ret[ab][!] [-indentonly] [{new-tabstop}]
|
||||
:[range]ret[ab][!] [new_tabstop]
|
||||
Replace all sequences of white-space containing a
|
||||
<Tab> with new strings of white-space using
|
||||
{new-tabstop}. If you do not specify {new-tabstop} or
|
||||
it is zero, Vim uses the current value of 'tabstop'.
|
||||
<Tab> with new strings of white-space using the new
|
||||
tabstop value given. If you do not specify a new
|
||||
tabstop size or it is zero, Vim uses the current value
|
||||
of 'tabstop'.
|
||||
The current value of 'tabstop' is always used to
|
||||
compute the width of existing tabs.
|
||||
With !, Vim also replaces strings of only normal
|
||||
spaces with tabs where appropriate.
|
||||
With 'expandtab' on, Vim replaces all tabs with the
|
||||
appropriate number of spaces.
|
||||
This command sets 'tabstop' to {new-tabstop} and if
|
||||
performed on the whole file, which is default, should
|
||||
not make any visible change.
|
||||
|
||||
When [-indentonly] is specified, only the leading
|
||||
white-space will be targeted. Any other consecutive
|
||||
white-space will not be changed.
|
||||
|
||||
Warning: This command modifies any <Tab> characters
|
||||
This command sets 'tabstop' to the new value given,
|
||||
and if performed on the whole file, which is default,
|
||||
should not make any visible change.
|
||||
Careful: This command modifies any <Tab> characters
|
||||
inside of strings in a C program. Use "\t" to avoid
|
||||
this (that's a good habit anyway).
|
||||
`:retab!` may also change a sequence of spaces by
|
||||
@@ -1110,11 +1105,6 @@ inside of strings can change! Also see 'softtabstop' option. >
|
||||
:[line]pu[t]! [x] Put the text [from register x] before [line] (default
|
||||
current line).
|
||||
|
||||
*:ip* *:iput*
|
||||
:[line]ip[ut] [x] like |:put|, but adjust indent to the current line
|
||||
|
||||
:[line]ip[ut]! [x] like |:put|!, but adjust indent to the current line
|
||||
|
||||
["x]]p or *]p* *]<MiddleMouse>*
|
||||
["x]]<MiddleMouse> Like "p", but adjust the indent to the current line.
|
||||
Using the mouse only works when 'mouse' contains 'n'
|
||||
@@ -1149,27 +1139,27 @@ the ":put" command, Vim always inserts the text in the next line. You can
|
||||
exchange two characters with the command sequence "xp". You can exchange two
|
||||
lines with the command sequence "ddp". You can exchange two words with the
|
||||
command sequence "deep" (start with the cursor in the blank space before the
|
||||
first word). You can use the |']| or |`]| command after the put command to
|
||||
move the cursor to the end of the inserted text, or use |'[| or |`[| to move
|
||||
first word). You can use the "']" or "`]" command after the put command to
|
||||
move the cursor to the end of the inserted text, or use "'[" or "`[" to move
|
||||
the cursor to the start.
|
||||
|
||||
*put-Visual-mode*
|
||||
*put-Visual-mode* *v_p* *v_P*
|
||||
When using a put command like |p| or |P| in Visual mode, Vim will try to
|
||||
replace the selected text with the contents of the register. How this
|
||||
works depends on the type of selection and the text. With blockwise selection
|
||||
it also depends on the size of the block and whether the corners are on an
|
||||
existing character. (Implementation detail: it actually works by first
|
||||
putting the register after the selection and then deleting the selection.)
|
||||
*v_p*
|
||||
|p| in Visual mode puts text and sets the default register (unnamed,
|
||||
selection, or clipboard) to the previously-selected text. Useful if you want
|
||||
to put that text somewhere else. But you cannot repeat the same change.
|
||||
*v_P*
|
||||
|P| in Visual mode puts text without setting the default register. You can
|
||||
repeat the change, but the deleted text cannot be used. If you do need it you
|
||||
can use |p| with another register. E.g., yank the text to copy, Visually
|
||||
select the text to replace and use "0p . You can repeat this as many times as
|
||||
you like, and the unnamed register will be changed each time.
|
||||
replace the selected text with the contents of the register. Whether this
|
||||
works well depends on the type of selection and the type of the text in the
|
||||
register. With blockwise selection it also depends on the size of the block
|
||||
and whether the corners are on an existing character. (Implementation detail:
|
||||
it actually works by first putting the register after the selection and then
|
||||
deleting the selection.)
|
||||
With |p| the previously selected text is put in the unnamed register (and
|
||||
possibly the selection and/or clipboard). This is useful if you want to put
|
||||
that text somewhere else. But you cannot repeat the same change.
|
||||
With |P| the unnamed register is not changed (and neither the selection or
|
||||
clipboard), you can repeat the same change. But the deleted text cannot be
|
||||
used. If you do need it you can use |p| with another register. E.g., yank
|
||||
the text to copy, Visually select the text to replace and use "0p . You can
|
||||
repeat this as many times as you like, and the unnamed register will be
|
||||
changed each time.
|
||||
*blockwise-put*
|
||||
When a register contains text from one line (characterwise), using a
|
||||
blockwise Visual selection, putting that register will paste that text
|
||||
@@ -1249,18 +1239,6 @@ mapped. E.g. |%| is mapped by the matchit plugin.
|
||||
With each successive deletion or change, Vim shifts the previous contents
|
||||
of register 1 into register 2, 2 into 3, and so forth, losing the previous
|
||||
contents of register 9.
|
||||
*yankring*
|
||||
To also store yanks (not only deletions) in registers 1-9, try this: >lua
|
||||
-- Yank-ring: store yanked text in registers 1-9.
|
||||
vim.api.nvim_create_autocmd('TextYankPost', {
|
||||
callback = function()
|
||||
if vim.v.event.operator == 'y' then
|
||||
for i = 9, 1, -1 do -- Shift all numbered registers.
|
||||
vim.fn.setreg(tostring(i), vim.fn.getreg(tostring(i - 1)))
|
||||
end
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
3. Small delete register "- *quote_-* *quote-*
|
||||
This register contains text from commands that delete less than one line,
|
||||
@@ -1839,7 +1817,6 @@ And a few warnings:
|
||||
|
||||
Vim has a sorting function and a sorting command. The sorting function can be
|
||||
found here: |sort()|, |uniq()|.
|
||||
Also see |:uniq|.
|
||||
|
||||
*:sor* *:sort*
|
||||
:[range]sor[t][!] [b][f][i][l][n][o][r][u][x] [/{pattern}/]
|
||||
@@ -1849,7 +1826,7 @@ Also see |:uniq|.
|
||||
With [!] the order is reversed.
|
||||
|
||||
With [i] case is ignored.
|
||||
*:sort-l*
|
||||
|
||||
With [l] sort uses the current collation locale.
|
||||
Implementation details: strcoll() is used to compare
|
||||
strings. See |:language| to check or set the collation
|
||||
@@ -1881,14 +1858,13 @@ Also see |:uniq|.
|
||||
|
||||
With [b] sorting is done on the first binary number in
|
||||
the line (after or inside a {pattern} match).
|
||||
*:sort-u* *:sort-uniq*
|
||||
|
||||
With [u] (u stands for unique) only keep the first of
|
||||
a sequence of identical lines (ignoring case when [i]
|
||||
is used). Without this flag, a sequence of identical
|
||||
lines will be kept in their original order.
|
||||
Note that leading and trailing white space may cause
|
||||
lines to be different.
|
||||
When you just want to make things unique, use |:uniq|.
|
||||
|
||||
When /{pattern}/ is specified and there is no [r] flag
|
||||
the text matched with {pattern} is skipped, so that
|
||||
@@ -1935,55 +1911,4 @@ The sorting can be interrupted, but if you interrupt it too late in the
|
||||
process you may end up with duplicated lines. This also depends on the system
|
||||
library function used.
|
||||
|
||||
==============================================================================
|
||||
8. Deduplicating text *deduplicating* *unique*
|
||||
|
||||
Vim has a deduplicating function and a deduplicating command. The
|
||||
deduplicating function can be found here: |uniq()|.
|
||||
Also see |:sort-uniq|.
|
||||
|
||||
*:uni* *:uniq*
|
||||
:[range]uni[q][!] [i][l][r][u] [/{pattern}/]
|
||||
Remove duplicate lines that are adjacent to each other
|
||||
in [range]. When no range is given, all lines are
|
||||
processed.
|
||||
|
||||
With [i] case is ignored when comparing lines.
|
||||
|
||||
With [l] comparison uses the current collation locale.
|
||||
See |:sort-l| for more details.
|
||||
|
||||
With [r] comparison is done on the text that matches
|
||||
/{pattern}/ instead of the full line.
|
||||
|
||||
With [u] only keep lines that do not repeat (i.e., are
|
||||
not immediately followed by the same line).
|
||||
|
||||
With [!] only keep lines that are immediately followed
|
||||
by a duplicate.
|
||||
|
||||
If both [!] and [u] are given, [u] is ignored and [!]
|
||||
takes effect.
|
||||
|
||||
When /{pattern}/ is specified and [r] is not used, the
|
||||
text matched with {pattern} is skipped and comparison
|
||||
is done on what comes after the match.
|
||||
'ignorecase' applies to the pattern, but 'smartcase'
|
||||
is not used.
|
||||
Instead of the slash any non-letter can be used.
|
||||
|
||||
For example, to remove adjacent duplicate lines based
|
||||
on the second comma-separated field: >
|
||||
:uniq /[^,]*,/
|
||||
< Or to keep only unique lines ignoring the first 5
|
||||
characters: >
|
||||
:uniq u /.\{5}/
|
||||
< If {pattern} is empty (e.g. // is used), the last
|
||||
search pattern is used.
|
||||
|
||||
Note that leading and trailing white space may cause
|
||||
lines to be considered different.
|
||||
To remove all duplicates regardless of position, use
|
||||
|:sort-u| or external tools.
|
||||
|
||||
vim:tw=78:ts=8:noet:ft=help:norl:
|
||||
|
@@ -177,85 +177,84 @@ Put this in `uppercase.vim` and run: >bash
|
||||
==============================================================================
|
||||
5. Using a prompt buffer *prompt-buffer*
|
||||
|
||||
Prompt buffers provide a "prompt" interface: they are like regular buffers,
|
||||
except only the last section of the buffer is editable, and the user can
|
||||
"submit" the prompt by hitting Enter. Useful for implementing:
|
||||
|
||||
- chat UI
|
||||
- REPL or shell plugins
|
||||
- advanced "picker" plugins
|
||||
If you want to type input for the job in a Vim window you have a few options:
|
||||
- Use a normal buffer and handle all possible commands yourself.
|
||||
This will be complicated, since there are so many possible commands.
|
||||
- Use a terminal window. This works well if what you type goes directly to
|
||||
the job and the job output is directly displayed in the window.
|
||||
See |terminal|.
|
||||
- Use a window with a prompt buffer. This works well when entering a line for
|
||||
the job in Vim while displaying (possibly filtered) output from the job.
|
||||
|
||||
A prompt buffer is created by setting 'buftype' to "prompt". You would
|
||||
normally only do that in a newly created buffer: >vim
|
||||
normally only do that in a newly created buffer.
|
||||
|
||||
:set buftype=prompt
|
||||
The user can edit and enter one line of text at the very last line of the
|
||||
buffer. When pressing Enter in the prompt line the callback set with
|
||||
|prompt_setcallback()| is invoked. It would normally send the line to a job.
|
||||
Another callback would receive the output from the job and display it in the
|
||||
buffer, below the prompt (and above the next prompt).
|
||||
|
||||
The user can edit and enter text at the end of the buffer. Pressing Enter in
|
||||
the prompt section invokes the |prompt_setcallback()| callback, which is
|
||||
typically expected to process the prompt and show results by appending to the
|
||||
buffer. To input multiline text, use Shift+Enter to add a new line without
|
||||
submitting the prompt, or just |put| or |paste| multiline text.
|
||||
Only the text in the last line, after the prompt, is editable. The rest of the
|
||||
buffer is not modifiable with Normal mode commands. It can be modified by
|
||||
calling functions, such as |append()|. Using other commands may mess up the
|
||||
buffer.
|
||||
|
||||
Only the "prompt" part of the buffer user-editable, given by the |':| mark.
|
||||
The rest of the buffer is not modifiable with Normal mode commands, though it
|
||||
can be modified by functions such as |append()|. Using other commands may
|
||||
mess up the buffer.
|
||||
After setting 'buftype' to "prompt" Vim does not automatically start Insert
|
||||
mode, use `:startinsert` if you want to enter Insert mode, so that the user
|
||||
can start typing a line.
|
||||
|
||||
After setting `buftype=prompt`:
|
||||
- Nvim unsets the 'comments' option.
|
||||
- Nvim does not automatically start Insert mode (use `:startinsert` if you
|
||||
want to enter Insert mode)
|
||||
|
||||
The prompt prefix defaults to "% ", but can be set with |prompt_setprompt()|.
|
||||
You can get the effective prompt prefix for with |prompt_getprompt()|.
|
||||
The text of the prompt can be set with the |prompt_setprompt()| function. If
|
||||
no prompt is set with |prompt_setprompt()|, "% " is used. You can get the
|
||||
effective prompt text for a buffer, with |prompt_getprompt()|.
|
||||
|
||||
The user can go to Normal mode and navigate through the buffer. This can be
|
||||
useful to see older output or copy text.
|
||||
|
||||
By default during prompt insert-mode, the CTRL-W key can be used to start
|
||||
a window command, such as CTRL-W w to switch to the next window. (Use
|
||||
Shift-CTRL-W to delete a word). When leaving the window Insert mode will be
|
||||
stopped. When coming back to the prompt window Insert mode will be restored.
|
||||
The CTRL-W key can be used to start a window command, such as CTRL-W w to
|
||||
switch to the next window. This also works in Insert mode (use Shift-CTRL-W
|
||||
to delete a word). When leaving the window Insert mode will be stopped. When
|
||||
coming back to the prompt window Insert mode will be restored.
|
||||
|
||||
Any command that starts Insert mode, such as "a", "i", "A" and "I", will move
|
||||
the cursor to the last line. "A" will move to the end of the line, "I" to the
|
||||
start of the line.
|
||||
|
||||
Example: start a shell in the background and prompt for the next shell
|
||||
command, displaying shell output above the prompt: >vim
|
||||
Here is an example for Unix. It starts a shell in the background and prompts
|
||||
for the next shell command. Output from the shell is displayed above the
|
||||
prompt. >vim
|
||||
|
||||
" Handles a line of user input.
|
||||
func OnSubmit(text)
|
||||
" Function handling a line of text that has been typed.
|
||||
func TextEntered(text)
|
||||
" Send the text to a shell with Enter appended.
|
||||
call chansend(g:shell_job, [a:text, ''])
|
||||
endfunc
|
||||
|
||||
" Handles output from the shell.
|
||||
func OnOutput(channel, msg, name)
|
||||
" Add shell output above the prompt.
|
||||
call append(line('$') - 1, a:msg)
|
||||
" Function handling output from the shell: Add it above the prompt.
|
||||
func GotOutput(channel, msg, name)
|
||||
call append(line("$") - 1, a:msg)
|
||||
endfunc
|
||||
|
||||
" Handles the shell exit.
|
||||
" Function handling the shell exits: close the window.
|
||||
func JobExit(job, status, event)
|
||||
quit!
|
||||
endfunc
|
||||
|
||||
" Start a shell in the background.
|
||||
let shell_job = jobstart(['/bin/sh'], #{
|
||||
\ on_stdout: function('OnOutput'),
|
||||
\ on_stderr: function('OnOutput'),
|
||||
let shell_job = jobstart(["/bin/sh"], #{
|
||||
\ on_stdout: function('GotOutput'),
|
||||
\ on_stderr: function('GotOutput'),
|
||||
\ on_exit: function('JobExit'),
|
||||
\ })
|
||||
|
||||
new
|
||||
set buftype=prompt
|
||||
let buf = bufnr('')
|
||||
call prompt_setcallback(buf, function('OnSubmit'))
|
||||
call prompt_setprompt(buf, 'shell command: ')
|
||||
call prompt_setcallback(buf, function("TextEntered"))
|
||||
call prompt_setprompt(buf, "shell command: ")
|
||||
|
||||
" Start accepting shell commands.
|
||||
" start accepting shell commands
|
||||
startinsert
|
||||
<
|
||||
|
||||
vim:tw=78:ts=8:et:sw=4:ft=help:norl:
|
||||
vim:tw=78:ts=8:noet:ft=help:norl:
|
||||
|
@@ -142,16 +142,13 @@ CTRL-R {register} *c_CTRL-R* *c_<C-R>*
|
||||
typing CTRL-R and the second character '"' will be displayed
|
||||
to indicate that you are expected to enter the name of a
|
||||
register.
|
||||
When used with named or clipboard registers (A-Z,a-z,0-9,+)
|
||||
text is inserted literally like pasting with "p". For other
|
||||
registers, the text is inserted as if you typed it, but
|
||||
mappings and abbreviations are not used. Command-line
|
||||
completion through 'wildchar' is not triggered though. And
|
||||
characters that end the command line are inserted literally
|
||||
(<Esc>, <CR>, <NL>, <C-C>). A <BS> or CTRL-W could still end
|
||||
the command line though, and remaining characters will then be
|
||||
interpreted in another mode, which might not be what you
|
||||
intended.
|
||||
The text is inserted as if you typed it, but mappings and
|
||||
abbreviations are not used. Command-line completion through
|
||||
'wildchar' is not triggered though. And characters that end
|
||||
the command line are inserted literally (<Esc>, <CR>, <NL>,
|
||||
<C-C>). A <BS> or CTRL-W could still end the command line
|
||||
though, and remaining characters will then be interpreted in
|
||||
another mode, which might not be what you intended.
|
||||
Special registers:
|
||||
'"' the unnamed register, containing the text of
|
||||
the last delete or yank
|
||||
@@ -179,9 +176,7 @@ CTRL-R {register} *c_CTRL-R* *c_<C-R>*
|
||||
sure the expression evaluates to an empty
|
||||
string. E.g.: >
|
||||
<C-R><C-R>=setcmdpos(2)[-1]<CR>
|
||||
< You can use this to insert a register as
|
||||
typed with CTRL-R =@reg.
|
||||
See |registers| about registers.
|
||||
< See |registers| about registers.
|
||||
Implementation detail: When using the |expression| register
|
||||
and invoking setcmdpos(), this sets the position before
|
||||
inserting the resulting string. Use CTRL-R CTRL-R to set the
|
||||
@@ -393,7 +388,7 @@ CTRL-D List names that match the pattern in front of the cursor.
|
||||
to the end.
|
||||
The 'wildoptions' option can be set to "tagfile" to list the
|
||||
file of matching tags.
|
||||
*c_CTRL-I* *c_wildchar* *c_<Tab>* */_<Tab>*
|
||||
*c_CTRL-I* *c_wildchar* *c_<Tab>*
|
||||
'wildchar' option
|
||||
A match is done on the pattern in front of the cursor. The
|
||||
match (if there are several, the first match) is inserted
|
||||
@@ -403,10 +398,6 @@ CTRL-D List names that match the pattern in front of the cursor.
|
||||
again and there were multiple matches, the next
|
||||
match is inserted. After the last match, the first is used
|
||||
again (wrap around).
|
||||
|
||||
In search context use <CTRL-V><Tab> or "\t" to search for a
|
||||
literal <Tab> instead of triggering completion.
|
||||
|
||||
The behavior can be changed with the 'wildmode' option.
|
||||
*c_<S-Tab>*
|
||||
<S-Tab> Like 'wildchar' or <Tab>, but begin with the last match and
|
||||
@@ -439,7 +430,7 @@ CTRL-G When 'incsearch' is set, entering a search pattern for "/" or
|
||||
"?" and the current match is displayed then CTRL-G will move
|
||||
to the next match (does not take |search-offset| into account)
|
||||
Use CTRL-T to move to the previous match. Hint: on a regular
|
||||
keyboard G is below T.
|
||||
keyboard T is above G.
|
||||
*c_CTRL-T* */_CTRL-T*
|
||||
CTRL-T When 'incsearch' is set, entering a search pattern for "/" or
|
||||
"?" and the current match is displayed then CTRL-T will move
|
||||
@@ -456,8 +447,6 @@ When repeating 'wildchar' or CTRL-N you cycle through the matches, eventually
|
||||
ending up back to what was typed. If the first match is not what you wanted,
|
||||
you can use <S-Tab> or CTRL-P to go straight back to what you typed.
|
||||
|
||||
See also |wildtrigger()|.
|
||||
|
||||
The 'wildmenu' option can be set to show the matches just above the command
|
||||
line.
|
||||
|
||||
@@ -575,6 +564,7 @@ that see the '"' as part of their argument:
|
||||
:menu (and the like)
|
||||
:mkspell
|
||||
:normal
|
||||
:ownsyntax
|
||||
:popup
|
||||
:registers
|
||||
:return
|
||||
@@ -947,6 +937,14 @@ Note: these are typed literally, they are not special keys!
|
||||
events).
|
||||
When the match is with a file name, it is expanded to the
|
||||
full path.
|
||||
*:<sfile>* *<sfile>*
|
||||
<sfile> When executing a `:source` command, is replaced with the
|
||||
file name of the sourced file. *E498*
|
||||
When executing a function, is replaced with the call stack,
|
||||
as with <stack> (this is for backwards compatibility, using
|
||||
<stack> or <script> is preferred).
|
||||
Note that filename-modifiers are useless when <sfile> is
|
||||
not used inside a script.
|
||||
*:<stack>* *<stack>*
|
||||
<stack> is replaced with the call stack, using
|
||||
"function {function-name}[{lnum}]" for a function line
|
||||
@@ -954,7 +952,7 @@ Note: these are typed literally, they are not special keys!
|
||||
".." in between items. E.g.:
|
||||
"function {function-name1}[{lnum}]..{function-name2}[{lnum}]"
|
||||
If there is no call stack you get error *E489* .
|
||||
*:<script>* *<script>* *E498*
|
||||
*:<script>* *<script>*
|
||||
<script> When executing a `:source` command, is replaced with the file
|
||||
name of the sourced file. When executing a function, is
|
||||
replaced with the file name of the script where it is
|
||||
@@ -973,7 +971,7 @@ Note: these are typed literally, they are not special keys!
|
||||
*filename-modifiers*
|
||||
*:_%:* *::8* *::p* *::.* *::~* *::h* *::t* *::r* *::e* *::s* *::gs* *::S*
|
||||
*%:8* *%:p* *%:.* *%:~* *%:h* *%:t* *%:r* *%:e* *%:s* *%:gs* *%:S*
|
||||
The file name modifiers can be used after "%", "#", "#n", "<cfile>", "<script>",
|
||||
The file name modifiers can be used after "%", "#", "#n", "<cfile>", "<sfile>",
|
||||
"<afile>" or "<abuf>". They are also used with the |fnamemodify()| function.
|
||||
These modifiers can be given, in this order:
|
||||
:p Make file name a full path. Must be the first modifier. Also
|
||||
@@ -1244,10 +1242,8 @@ Example: >
|
||||
:au CmdwinLeave : let &cpt = b:cpt_save
|
||||
This sets 'complete' to use completion in the current window for |i_CTRL-N|.
|
||||
Another example: >
|
||||
:au CmdwinEnter [/\?] startinsert
|
||||
:au CmdwinEnter [/?] startinsert
|
||||
This will make Vim start in Insert mode in the command-line window.
|
||||
Note: The "?" needs to be escaped, as this is a |file-pattern|. See also
|
||||
|cmdline-autocompletion|.
|
||||
|
||||
*cmdline-char* *cmdwin-char*
|
||||
The character used for the pattern indicates the type of command-line:
|
||||
|
@@ -160,4 +160,5 @@ In WinDbg: choose Open Crash Dump on the File menu. Follow the instructions in
|
||||
Visual Studio 2017 Community Edition can be downloaded for free from:
|
||||
https://visualstudio.microsoft.com/downloads/
|
||||
|
||||
=========================================================================
|
||||
vim:tw=78:ts=8:noet:ft=help:norl:
|
||||
|
@@ -12,42 +12,6 @@ They should not be used in new scripts, and old scripts should be updated.
|
||||
==============================================================================
|
||||
Deprecated features
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
DEPRECATED IN 0.12 *deprecated-0.12*
|
||||
|
||||
API
|
||||
|
||||
• todo
|
||||
|
||||
DIAGNOSTICS
|
||||
|
||||
• "float" in |vim.diagnostic.JumpOpts|. Use "on_jump" instead.
|
||||
• "float" in |vim.diagnostic.Opts.Jump|. Use "on_jump" instead.
|
||||
|
||||
HIGHLIGHTS
|
||||
|
||||
• *:ownsyntax* *w:current_syntax* Use 'winhighlight' instead.
|
||||
|
||||
LSP
|
||||
|
||||
• *vim.lsp.client_is_stopped()* Use |vim.lsp.get_client_by_id()| instead.
|
||||
• *vim.lsp.util.stylize_markdown()* Use |vim.treesitter.start()| with
|
||||
`vim.wo.conceallevel = 2`.
|
||||
• *vim.lsp.log.should_log()* Use |vim.lsp.log.set_format_func()| instead
|
||||
and return `nil` to omit entries from the logfile.
|
||||
• *vim.lsp.semantic_tokens.start()* Use `vim.lsp.semantic_tokens.enable(true)` instead
|
||||
• *vim.lsp.semantic_tokens.stop()* Use `vim.lsp.semantic_tokens.enable(false)` instead
|
||||
• *vim.lsp.set_log_level()* Use `vim.lsp.log.set_level()` instead
|
||||
• *vim.lsp.get_log_path()* Use `vim.lsp.log.get_filename()` instead
|
||||
|
||||
LUA
|
||||
|
||||
• *vim.diff()* Renamed to |vim.text.diff()|
|
||||
|
||||
VIMSCRIPT
|
||||
|
||||
• todo
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
DEPRECATED IN 0.11 *deprecated-0.11*
|
||||
|
||||
@@ -102,7 +66,7 @@ LUA
|
||||
• vim.validate(opts: table) Use form 1. See |vim.validate()|.
|
||||
|
||||
VIMSCRIPT
|
||||
• *termopen()* Use |jobstart()| with `{term: v:true}`.
|
||||
• *termopen()* Use |jobstart() with `{term: v:true}`.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
DEPRECATED IN 0.10 *deprecated-0.10*
|
||||
@@ -334,12 +298,13 @@ UI EXTENSIONS
|
||||
• *term_background* Unused. The terminal background color is now detected
|
||||
by the Nvim core directly instead of the TUI.
|
||||
|
||||
VIMSCRIPT
|
||||
• *<sfile>* Use |<script>| or |<stack>| instead.
|
||||
VARIABLES
|
||||
• *b:terminal_job_pid* Use `jobpid(&channel)` instead.
|
||||
• *b:terminal_job_id* Use `&channel` instead. To access in non-current buffer:
|
||||
• Lua: `vim.bo[bufnr].channel`
|
||||
• Vimscript: `getbufvar(bufnr, '&channel')`
|
||||
|
||||
VIMSCRIPT
|
||||
• *buffer_exists()* Obsolete name for |bufexists()|.
|
||||
• *buffer_name()* Obsolete name for |bufname()|.
|
||||
• *buffer_number()* Obsolete name for |bufnr()|.
|
||||
|
@@ -53,27 +53,6 @@ Other references:
|
||||
- https://github.com/neovim/neovim/pull/21605
|
||||
|
||||
|
||||
==============================================================================
|
||||
API
|
||||
|
||||
*dev-api-fast*
|
||||
API functions and Vimscript "eval" functions may be marked as |api-fast| which
|
||||
means they are safe to call in Lua callbacks and other scenarios. A functions
|
||||
CANNOT be marked as "fast" if could trigger `os_breakcheck()`, which may
|
||||
"yield" the current execution and start a new execution of code not expecting
|
||||
this:
|
||||
- accidentally recursing into a function not expecting this.
|
||||
- changing (global) state without restoring it before returning to the
|
||||
"yielded" callsite.
|
||||
|
||||
In practice, this means any code that could trigger `os_breakcheck()` cannot
|
||||
be "fast". For example, commit 3940c435e405 fixed such a bug with
|
||||
`nvim__get_runtime` by explicitly disallowing `os_breakcheck()` via the
|
||||
`EW_NOBREAK` flag.
|
||||
|
||||
Common examples of non-fast code: regexp matching, wildcard expansion,
|
||||
expression evaluation.
|
||||
|
||||
|
||||
==============================================================================
|
||||
|
||||
|
@@ -255,7 +255,8 @@ functions. >c
|
||||
|
||||
Integration with declarations generator ~
|
||||
|
||||
Every C file must contain #include of the generated header file.
|
||||
Every C file must contain #include of the generated header file, guarded by
|
||||
#ifdef INCLUDE_GENERATED_DECLARATIONS.
|
||||
|
||||
Include must go after other #includes and typedefs in .c files and after
|
||||
everything else in header files. It is allowed to omit #include in a .c file
|
||||
@@ -271,7 +272,9 @@ contain only non-static function declarations. >c
|
||||
|
||||
typedef int FooType;
|
||||
|
||||
#include "foo.c.generated.h"
|
||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||
# include "foo.c.generated.h"
|
||||
#endif
|
||||
|
||||
…
|
||||
|
||||
@@ -281,7 +284,9 @@ contain only non-static function declarations. >c
|
||||
|
||||
…
|
||||
|
||||
#include "foo.h.generated.h"
|
||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||
# include "foo.h.generated.h"
|
||||
#endif
|
||||
|
||||
|
||||
64-bit Portability ~
|
||||
@@ -896,8 +901,8 @@ Return Values ~
|
||||
|
||||
Do not needlessly surround the `return` expression with parentheses.
|
||||
|
||||
Use parentheses in `return expr;` only where you would also use them in
|
||||
`x = expr;`. >c
|
||||
Use parentheses in `return expr`; only where you would use them in `x =
|
||||
expr;`. >c
|
||||
|
||||
return result;
|
||||
return (some_long_condition && another_condition);
|
||||
|
@@ -171,8 +171,8 @@ USING GDBSERVER IN TMUX
|
||||
Consider using a custom makefile
|
||||
https://github.com/neovim/neovim/blob/master/BUILD.md#custom-makefile to
|
||||
quickly start debugging sessions using the `gdbserver` method mentioned above.
|
||||
This example `local.mk` will create the debugging session when you type
|
||||
`make debug`.
|
||||
This example `local.mk` will create the debugging session when you type `make
|
||||
debug`.
|
||||
>make
|
||||
.PHONY: dbg-start dbg-attach debug build
|
||||
|
||||
|
@@ -201,7 +201,7 @@ Docstring format:
|
||||
- Markdown is supported.
|
||||
- Tags are written as `[tag]()`.
|
||||
- References are written as `[tag]`
|
||||
- Use "```" for code samples.
|
||||
- Use ``` for code samples.
|
||||
Code samples can be annotated as `vim` or `lua`
|
||||
|
||||
Example: the help for |nvim_open_win()| is generated from a docstring defined
|
||||
@@ -245,7 +245,7 @@ Docstring format:
|
||||
- Markdown is supported.
|
||||
- Tags are written as `[tag]()`.
|
||||
- References are written as `[tag]`
|
||||
- Use "```" for code samples.
|
||||
- Use ``` for code samples.
|
||||
Code samples can be annotated as `vim` or `lua`
|
||||
- Use `@since <api-level>` to note the |api-level| when the function became
|
||||
"stable". If `<api-level>` is greater than the current stable release (or
|
||||
@@ -353,7 +353,7 @@ Where possible, these patterns apply to _both_ Lua and the API:
|
||||
- Examples: |vim.lsp.codelens.clear()| |vim.diagnostic.enable()|
|
||||
- Any function signature that accepts a callback (example: |table.foreach()|)
|
||||
should place it as the LAST parameter (after opts), if possible (or ALWAYS
|
||||
for |continuation|s——functions called exactly once).
|
||||
for "continuation callbacks"—functions called exactly once).
|
||||
- Improves readability by placing the less "noisy" arguments near the start.
|
||||
- Consistent with luv.
|
||||
- Useful for future async lib which transforms functions of the form
|
||||
@@ -426,9 +426,6 @@ Use existing common {verb} names (actions) if possible:
|
||||
- add: Appends or inserts into a collection
|
||||
- attach: Listens to something to get events from it (TODO: rename to "on"?)
|
||||
- call: Calls a function
|
||||
- callback |continuation|: Function parameter (NOT a field) that
|
||||
returns the result of an async function. Use the "on_…"
|
||||
naming-convention for all other callbacks and event handlers.
|
||||
- cancel: Cancels or dismisses an event or interaction, typically
|
||||
user-initiated and without error. (Compare "abort", which
|
||||
cancels and signals error/failure.)
|
||||
@@ -447,12 +444,8 @@ Use existing common {verb} names (actions) if possible:
|
||||
- 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.
|
||||
- on_…: Handles events or async results, or registers such
|
||||
a handler. |dev-name-events|
|
||||
- open: Opens something (a buffer, window, …)
|
||||
- parse: Parses something into a structured form
|
||||
- request: Calls a remote (network, RPC) operation.
|
||||
- send: Writes data or a message to a channel.
|
||||
- set: Sets a thing (or group of things)
|
||||
- start: Spin up a long-lived process. Prefer "enable" except when
|
||||
"start" is obviously more appropriate.
|
||||
@@ -463,7 +456,7 @@ 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()`.
|
||||
- is_disabled: Prefer `is_enabled()`.
|
||||
- list: Redundant with "get"
|
||||
- notify: Redundant with "print", "echo"
|
||||
- show: Redundant with "print", "echo"
|
||||
@@ -484,6 +477,7 @@ everywhere, not "buffer" in some places and "buf" in others.
|
||||
|
||||
Do NOT use these deprecated nouns:
|
||||
- buffer Use "buf" instead
|
||||
- callback Use on_foo instead
|
||||
- command Use "cmd" instead
|
||||
- window Use "win" instead
|
||||
|
||||
@@ -501,14 +495,6 @@ Use this format to name API (RPC) events: >
|
||||
Example: >
|
||||
nvim_buf_changedtick_event
|
||||
<
|
||||
*continuation*
|
||||
A "continuation" is implemented as a callback function that returns the result
|
||||
of an async function and is called exactly once. Often accepts `err` as the
|
||||
first parameter, to avoid erroring on the main thread. Example: >
|
||||
foo(…, callback: fun(err, …))
|
||||
Use the name `callback` only for a continuation. All other callbacks and event
|
||||
handlers should be named with the |dev-name-events| "on_…" convention.
|
||||
|
||||
*dev-api-name*
|
||||
Use this format to name new RPC |API| functions: >
|
||||
nvim_{topic}_{verb}_{arbitrary-qualifiers}
|
||||
@@ -682,8 +668,6 @@ External UIs are expected to implement these common features:
|
||||
the user).
|
||||
- Support the text decorations/attributes given by |ui-event-hl_attr_define|.
|
||||
The "url" attr should be presented as a clickable hyperlink.
|
||||
- Handle the "restart" UI event so that |:restart| works.
|
||||
- Detect capslock and show an indicator if capslock is active.
|
||||
|
||||
|
||||
vim:tw=78:ts=8:sw=4:et:ft=help:norl:
|
||||
|
@@ -190,28 +190,6 @@ the `virtual_lines` handler with the following keymap: >lua
|
||||
end, { desc = 'Toggle diagnostic virtual_lines' })
|
||||
<
|
||||
|
||||
*diagnostic-on-jump-example*
|
||||
You can use the `on_jump` option from |vim.diagnostic.jump()| to show the
|
||||
diagnostic that was jumped to using a specific handler. For example, the
|
||||
following uses the `virtual_lines` handler when jumping to a diagnostic: >lua
|
||||
|
||||
local virt_lines_ns = vim.api.nvim_create_namespace 'on_diagnostic_jump'
|
||||
|
||||
--- @param diagnostic? vim.Diagnostic
|
||||
--- @param bufnr integer
|
||||
local function on_jump(diagnostic, bufnr)
|
||||
if not diagnostic then return end
|
||||
|
||||
vim.diagnostic.show(
|
||||
virt_lines_ns,
|
||||
bufnr,
|
||||
{ diagnostic },
|
||||
{ virtual_lines = { current_line = true }, virtual_text = false }
|
||||
)
|
||||
end
|
||||
|
||||
vim.diagnostic.config({ jump = { on_jump = on_jump } })
|
||||
<
|
||||
*diagnostic-loclist-example*
|
||||
Whenever the |location-list| is opened, the following `show` handler will show
|
||||
the most recent diagnostics: >lua
|
||||
@@ -440,43 +418,27 @@ Example: >lua
|
||||
Lua module: vim.diagnostic *diagnostic-api*
|
||||
|
||||
*vim.Diagnostic*
|
||||
Extends: |vim.Diagnostic.Set|
|
||||
|
||||
*diagnostic-structure*
|
||||
|
||||
Diagnostics use the same indexing as the rest of the Nvim API (i.e.
|
||||
0-based rows and columns). |api-indexing|
|
||||
|
||||
Fields: ~
|
||||
• {bufnr} (`integer`) Buffer number
|
||||
• {end_lnum} (`integer`) The final line of the diagnostic (0-indexed)
|
||||
• {col} (`integer`) The starting column of the diagnostic
|
||||
(0-indexed)
|
||||
• {end_col} (`integer`) The final column of the diagnostic
|
||||
(0-indexed)
|
||||
• {severity} (`vim.diagnostic.Severity`) The severity of the
|
||||
diagnostic |vim.diagnostic.severity|
|
||||
• {namespace}? (`integer`)
|
||||
|
||||
*vim.Diagnostic.Set*
|
||||
Diagnostics use the same indexing as the rest of the Nvim API (i.e.
|
||||
0-based rows and columns). |api-indexing|
|
||||
|
||||
Fields: ~
|
||||
• {bufnr}? (`integer`) Buffer number
|
||||
• {lnum} (`integer`) The starting line of the diagnostic
|
||||
(0-indexed)
|
||||
• {col}? (`integer`, default: `0`) The starting column of the
|
||||
diagnostic (0-indexed)
|
||||
• {end_lnum}? (`integer`, default: `lnum`) The final line of the
|
||||
diagnostic (0-indexed)
|
||||
• {end_col}? (`integer`, default: `col`) The final column of the
|
||||
diagnostic (0-indexed)
|
||||
• {severity}? (`vim.diagnostic.Severity`, default: `vim.diagnostic.severity.ERROR`)
|
||||
The severity of the diagnostic |vim.diagnostic.severity|
|
||||
• {end_lnum}? (`integer`) The final line of the diagnostic (0-indexed)
|
||||
• {col} (`integer`) The starting column of the diagnostic
|
||||
(0-indexed)
|
||||
• {end_col}? (`integer`) The final column of the diagnostic
|
||||
(0-indexed)
|
||||
• {severity}? (`vim.diagnostic.Severity`) The severity of the
|
||||
diagnostic |vim.diagnostic.severity|
|
||||
• {message} (`string`) The diagnostic text
|
||||
• {source}? (`string`) The source of the diagnostic
|
||||
• {code}? (`string|integer`) The diagnostic code
|
||||
• {user_data}? (`any`) arbitrary data plugins can add
|
||||
• {namespace}? (`integer`)
|
||||
|
||||
*vim.diagnostic.GetOpts*
|
||||
A table with the following keys:
|
||||
@@ -488,9 +450,6 @@ Lua module: vim.diagnostic *diagnostic-api*
|
||||
specified line number.
|
||||
• {severity}? (`vim.diagnostic.SeverityFilter`) See
|
||||
|diagnostic-severity|.
|
||||
• {enabled}? (`boolean`, default: `nil`) Limit diagnostics to only
|
||||
enabled or disabled. If nil, enablement is ignored. See
|
||||
|vim.diagnostic.enable()|
|
||||
|
||||
*vim.diagnostic.JumpOpts*
|
||||
Extends: |vim.diagnostic.GetOpts|
|
||||
@@ -516,9 +475,13 @@ Lua module: vim.diagnostic *diagnostic-api*
|
||||
file or not. Similar to 'wrapscan'.
|
||||
• {severity}? (`vim.diagnostic.SeverityFilter`) See
|
||||
|diagnostic-severity|.
|
||||
• {on_jump}? (`fun(diagnostic:vim.Diagnostic?, bufnr:integer)`)
|
||||
Optional callback invoked with the diagnostic that was
|
||||
jumped to.
|
||||
• {float}? (`boolean|vim.diagnostic.Opts.Float`, default: `false`)
|
||||
If `true`, call |vim.diagnostic.open_float()| after
|
||||
moving. If a table, pass the table as the {opts}
|
||||
parameter to |vim.diagnostic.open_float()|. Unless
|
||||
overridden, the float will show diagnostics at the new
|
||||
cursor position (as if "cursor" were passed to the
|
||||
"scope" option).
|
||||
• {winid}? (`integer`, default: `0`) Window ID
|
||||
|
||||
*vim.diagnostic.NS*
|
||||
@@ -572,8 +535,7 @@ Lua module: vim.diagnostic *diagnostic-api*
|
||||
Fields: ~
|
||||
• {bufnr}? (`integer`, default: current buffer) Buffer number
|
||||
to show diagnostics from.
|
||||
• {namespace}? (`integer|integer[]`) Limit diagnostics to the given
|
||||
namespace(s).
|
||||
• {namespace}? (`integer`) Limit diagnostics to the given namespace
|
||||
• {scope}? (`'line'|'buffer'|'cursor'|'c'|'l'|'b'`, default:
|
||||
`line`) Show diagnostics from the whole buffer
|
||||
(`buffer"`, the current cursor line (`line`), or the
|
||||
@@ -631,8 +593,8 @@ Lua module: vim.diagnostic *diagnostic-api*
|
||||
*vim.diagnostic.Opts.Jump*
|
||||
|
||||
Fields: ~
|
||||
• {on_jump}? (`fun(diagnostic:vim.Diagnostic?, bufnr:integer)`)
|
||||
Default value of the {on_jump} parameter of
|
||||
• {float}? (`boolean|vim.diagnostic.Opts.Float`, default: false)
|
||||
Default value of the {float} parameter of
|
||||
|vim.diagnostic.jump()|.
|
||||
• {wrap}? (`boolean`, default: true) Default value of the {wrap}
|
||||
parameter of |vim.diagnostic.jump()|.
|
||||
@@ -692,12 +654,8 @@ Lua module: vim.diagnostic *diagnostic-api*
|
||||
• {severity}? (`vim.diagnostic.SeverityFilter`) Only show
|
||||
virtual text for diagnostics matching the given
|
||||
severity |diagnostic-severity|
|
||||
• {current_line}? (`boolean`) Show or hide diagnostics based on
|
||||
the current cursor line. If `true`, only
|
||||
diagnostics on the current cursor line are
|
||||
shown. If `false`, all diagnostics are shown
|
||||
except on the current cursor line. If `nil`, all
|
||||
diagnostics are shown. (default `nil`)
|
||||
• {current_line}? (`boolean`) Only show diagnostics for the
|
||||
current line. (default `false`)
|
||||
• {source}? (`boolean|"if_many"`) Include the diagnostic
|
||||
source in virtual text. Use `'if_many'` to only
|
||||
show sources if there is more than one
|
||||
@@ -956,7 +914,7 @@ set({namespace}, {bufnr}, {diagnostics}, {opts}) *vim.diagnostic.set()*
|
||||
Parameters: ~
|
||||
• {namespace} (`integer`) The diagnostic namespace
|
||||
• {bufnr} (`integer`) Buffer number
|
||||
• {diagnostics} (`vim.Diagnostic.Set[]`) See |vim.Diagnostic.Set|.
|
||||
• {diagnostics} (`vim.Diagnostic[]`) See |vim.Diagnostic|.
|
||||
• {opts} (`vim.diagnostic.Opts?`) Display options to pass to
|
||||
|vim.diagnostic.show()|. See |vim.diagnostic.Opts|.
|
||||
|
||||
@@ -965,8 +923,8 @@ setloclist({opts}) *vim.diagnostic.setloclist()*
|
||||
|
||||
Parameters: ~
|
||||
• {opts} (`table?`) Configuration table with the following keys:
|
||||
• {namespace}? (`integer[]|integer`) Only add diagnostics from
|
||||
the given namespace(s).
|
||||
• {namespace}? (`integer`) Only add diagnostics from the given
|
||||
namespace.
|
||||
• {winnr}? (`integer`, default: `0`) Window number to set
|
||||
location list for.
|
||||
• {open}? (`boolean`, default: `true`) Open the location list
|
||||
@@ -975,19 +933,14 @@ setloclist({opts}) *vim.diagnostic.setloclist()*
|
||||
"Diagnostics".
|
||||
• {severity}? (`vim.diagnostic.SeverityFilter`) See
|
||||
|diagnostic-severity|.
|
||||
• {format}? (`fun(diagnostic:vim.Diagnostic): string?`) A
|
||||
function that takes a diagnostic as input and returns a
|
||||
string or nil. If the return value is nil, the diagnostic is
|
||||
not displayed in the location list. Else the output text is
|
||||
used to display the diagnostic.
|
||||
|
||||
setqflist({opts}) *vim.diagnostic.setqflist()*
|
||||
Add all diagnostics to the quickfix list.
|
||||
|
||||
Parameters: ~
|
||||
• {opts} (`table?`) Configuration table with the following keys:
|
||||
• {namespace}? (`integer[]|integer`) Only add diagnostics from
|
||||
the given namespace(s).
|
||||
• {namespace}? (`integer`) Only add diagnostics from the given
|
||||
namespace.
|
||||
• {open}? (`boolean`, default: `true`) Open quickfix list
|
||||
after setting.
|
||||
• {title}? (`string`) Title of quickfix list. Defaults to
|
||||
@@ -995,11 +948,6 @@ setqflist({opts}) *vim.diagnostic.setqflist()*
|
||||
title, it's updated. If not, a new quickfix list is created.
|
||||
• {severity}? (`vim.diagnostic.SeverityFilter`) See
|
||||
|diagnostic-severity|.
|
||||
• {format}? (`fun(diagnostic:vim.Diagnostic): string?`) A
|
||||
function that takes a diagnostic as input and returns a
|
||||
string or nil. If the return value is nil, the diagnostic is
|
||||
not displayed in the quickfix list. Else the output text is
|
||||
used to display the diagnostic.
|
||||
|
||||
*vim.diagnostic.show()*
|
||||
show({namespace}, {bufnr}, {diagnostics}, {opts})
|
||||
@@ -1019,23 +967,6 @@ show({namespace}, {bufnr}, {diagnostics}, {opts})
|
||||
• {opts} (`vim.diagnostic.Opts?`) Display options. See
|
||||
|vim.diagnostic.Opts|.
|
||||
|
||||
status({bufnr}) *vim.diagnostic.status()*
|
||||
Returns formatted string with diagnostics for the current buffer. The
|
||||
severities with 0 diagnostics are left out. Example `E:2 W:3 I:4 H:5`
|
||||
|
||||
To customise appearance, set diagnostic signs text with >lua
|
||||
vim.diagnostic.config({
|
||||
signs = { text = { [vim.diagnostic.severity.ERROR] = 'e', ... } }
|
||||
})
|
||||
<
|
||||
|
||||
Parameters: ~
|
||||
• {bufnr} (`integer?`) Buffer number to get diagnostics from. Defaults
|
||||
to 0 for the current buffer
|
||||
|
||||
Return: ~
|
||||
(`string`)
|
||||
|
||||
toqflist({diagnostics}) *vim.diagnostic.toqflist()*
|
||||
Convert a list of diagnostics to a list of quickfix items that can be
|
||||
passed to |setqflist()| or |setloclist()|.
|
||||
|
@@ -214,28 +214,14 @@ The diffs are highlighted with these groups:
|
||||
|hl-DiffAdd| DiffAdd Added (inserted) lines. These lines exist in
|
||||
this buffer but not in another.
|
||||
|hl-DiffChange| DiffChange Changed lines.
|
||||
|hl-DiffText| DiffText Changed text inside a Changed line. Exact
|
||||
behavior depends on the `inline:` setting in
|
||||
'diffopt'.
|
||||
With `inline:` set to "simple", Vim finds the
|
||||
first character that is different, and the
|
||||
last character that is different (searching
|
||||
from the end of the line). The text in
|
||||
between is highlighted. This means that parts
|
||||
in the middle that are still the same are
|
||||
highlighted anyway. The 'diffopt' flags
|
||||
"iwhite" and "icase" are used here.
|
||||
With `inline:` set to "char" or "word", Vim
|
||||
uses the internal diff library to perform a
|
||||
detailed diff between the changed blocks and
|
||||
highlight the exact difference between the
|
||||
two. Will respect any 'diffopt' flag that
|
||||
affects internal diff.
|
||||
Not used when `inline:` is set to "none".
|
||||
|hl-DiffTextAdd| DiffTextAdd Added text inside a Changed line. Similar to
|
||||
DiffText, but used when there is no
|
||||
corresponding text in other buffers. Not used
|
||||
when `inline:` is set to "simple" or "none".
|
||||
|hl-DiffText| DiffText Changed text inside a Changed line. Vim
|
||||
finds the first character that is different,
|
||||
and the last character that is different
|
||||
(searching from the end of the line). The
|
||||
text in between is highlighted. This means
|
||||
that parts in the middle that are still the
|
||||
same are highlighted anyway. The 'diffopt'
|
||||
flags "iwhite" and "icase" are used here.
|
||||
|hl-DiffDelete| DiffDelete Deleted lines. Also called filler lines,
|
||||
because they don't really exist in this
|
||||
buffer.
|
||||
@@ -292,20 +278,18 @@ that the buffers will be equal within the specified range.
|
||||
|
||||
|
||||
When no [range] is given, the diff at the cursor position or just above it is
|
||||
affected. There can be deleted lines below the last line of the buffer. When
|
||||
the cursor is on the last line in the buffer and there is no diff above this
|
||||
line, and no [range] is given, the diff below the cursor position will be used
|
||||
instead.
|
||||
affected. When [range] is used, Vim tries to only put or get the specified
|
||||
lines. When there are deleted lines, this may not always be possible.
|
||||
|
||||
When [range] is used, Vim tries to only put or get the specified lines. When
|
||||
there are deleted lines, they will be used if they are between the lines
|
||||
specified by [range].
|
||||
There can be deleted lines below the last line of the buffer. When the cursor
|
||||
is on the last line in the buffer and there is no diff above this line, the
|
||||
":diffget" and "do" commands will obtain lines from the other buffer.
|
||||
|
||||
To be able to put or get those lines to/from another buffer in a [range] it's
|
||||
allowed to use 0 and the last line number plus one. This command gets all
|
||||
diffs from the other buffer: >
|
||||
To be able to get those lines from another buffer in a [range] it's allowed to
|
||||
use the last line number plus one. This command gets all diffs from the other
|
||||
buffer: >
|
||||
|
||||
:0,$+1diffget
|
||||
:1,$+1diffget
|
||||
|
||||
Note that deleted lines are displayed, but not counted as text lines. You
|
||||
can't move the cursor into them. To fill the deleted lines with the lines
|
||||
@@ -324,131 +308,9 @@ name or a part of a buffer name. Examples:
|
||||
diff mode (e.g., "file.c.v2")
|
||||
|
||||
==============================================================================
|
||||
5. Diff anchors *diff-anchors*
|
||||
5. Diff options *diff-options*
|
||||
|
||||
Diff anchors allow you to control where the diff algorithm aligns and
|
||||
synchronize text across files. Each anchor matches each other in each file,
|
||||
allowing you to control the output of a diff.
|
||||
|
||||
This is useful when a change involves complicated edits. For example, if a
|
||||
function was moved to another location and further edited. By default, the
|
||||
algorithm aims to create the smallest diff, which results in that entire
|
||||
function being considered to be deleted and added on the other side, making it
|
||||
hard to see what the actual edit on it was. You can use diff anchors to pin
|
||||
that function so the diff algorithm will align based on it.
|
||||
|
||||
To use it, set anchors using 'diffanchors' which is a comma-separated list of
|
||||
{address} in each file, and then add "anchor" to 'diffopt'. Internaly, Vim
|
||||
splits each file up into sections split by the anchors. It performs the diff
|
||||
on each pair of sections separately before merging the results back.
|
||||
|
||||
Setting 'diffanchors' will update the diff immediately. If an anchor is tied
|
||||
to a mark, and you change what the mark is pointed to, you need to manually
|
||||
call |:diffupdate| afterwards to get the updated diff results.
|
||||
|
||||
Example:
|
||||
|
||||
Let's say we have the following files, side-by-side. We are interested in the
|
||||
change that happened to the function `foo()`, which was both edited and moved.
|
||||
|
||||
File A: >
|
||||
int foo() {
|
||||
int n = 1;
|
||||
return n;
|
||||
}
|
||||
|
||||
int g = 1;
|
||||
|
||||
int bar(int a) {
|
||||
a *= 2;
|
||||
a += 3;
|
||||
return a;
|
||||
}
|
||||
<File B: >
|
||||
int bar(int a) {
|
||||
a *= 2;
|
||||
a += 3;
|
||||
return a;
|
||||
}
|
||||
|
||||
int foo() {
|
||||
int n = 999;
|
||||
return n;
|
||||
}
|
||||
|
||||
int g = 1;
|
||||
<
|
||||
A normal diff will usually align the diff result as such: >
|
||||
|
||||
int foo() { |----------------
|
||||
int n = 1; |----------------
|
||||
return n; |----------------
|
||||
} |----------------
|
||||
|----------------
|
||||
int g = 1; |----------------
|
||||
|----------------
|
||||
int bar(int a) {|int bar(int a) {
|
||||
a *= 2; | a *= 2;
|
||||
a += 3; | a += 3;
|
||||
return a; | return a;
|
||||
} |}
|
||||
----------------|
|
||||
----------------|int foo() {
|
||||
----------------| int n = 999;
|
||||
----------------| return n;
|
||||
----------------|}
|
||||
----------------|
|
||||
----------------|int g = 1;
|
||||
<
|
||||
What we want is to instead ask the diff to align on `foo()`: >
|
||||
|
||||
----------------|int bar(int a) {
|
||||
----------------| a *= 2;
|
||||
----------------| a += 3;
|
||||
----------------| return a;
|
||||
----------------|}
|
||||
----------------|
|
||||
int foo() { |int foo() {
|
||||
int n = 1; | int n = 999;
|
||||
return n; | return n;
|
||||
} |}
|
||||
|
|
||||
int g = 1; |int g = 1;
|
||||
|----------------
|
||||
int bar(int a) {|----------------
|
||||
a *= 2; |----------------
|
||||
a += 3; |----------------
|
||||
return a; |----------------
|
||||
} |----------------
|
||||
<
|
||||
|
||||
Below are some ways of setting diff anchors to get the above result. In each
|
||||
example, 'diffopt' needs to have `anchor` set for this to take effect.
|
||||
|
||||
Marks: Set the |'a| mark on the `int foo()` lines in each file first before
|
||||
setting the anchors: >
|
||||
set diffanchors='a
|
||||
|
||||
Pattern: Specify the anchor using a |pattern| (see |:/|). Here, we make sure
|
||||
to always start search from line 1 for consistency: >
|
||||
set diffanchors=1/int\ foo(/
|
||||
<
|
||||
Selection: Use visual mode to select the entire `foo()` function body in each
|
||||
file. Here, we use two anchors. This does a better job of making sure only
|
||||
the function bodies are anchored against each other but not the lines after
|
||||
it. Note the `'>+1` below. The "+1" is necessary as we want the split to
|
||||
happen below the last line of the function, not above: >
|
||||
set diffanchors='<,'>+1
|
||||
<
|
||||
Manually set two anchors using line numbers via buffer-local options: >
|
||||
setlocal diffanchors=1,5
|
||||
wincmd w
|
||||
setlocal diffanchors=7,11
|
||||
<
|
||||
==============================================================================
|
||||
6. Diff options *diff-options*
|
||||
|
||||
Also see 'diffopt' and the "diff" item of 'fillchars'.
|
||||
Also see |'diffopt'| and the "diff" item of |'fillchars'|.
|
||||
|
||||
*diff-slow* *diff_translations*
|
||||
For very long lines, the diff syntax highlighting might be slow, especially
|
||||
|
@@ -1094,8 +1094,8 @@ the 1', 2' and 3' digraphs.
|
||||
⌕ TR 2315 8981 TELEPHONE RECORDER
|
||||
⌠ Iu 2320 8992 TOP HALF INTEGRAL
|
||||
⌡ Il 2321 8993 BOTTOM HALF INTEGRAL
|
||||
⟨ <[ 27E8 10040 LEFT MATHEMATICAL ANGLE BRACKET
|
||||
⟩ ]> 27E9 10041 RIGHT MATHEMATICAL ANGLE BRACKET
|
||||
〈 </ 2329 9001 LEFT-POINTING ANGLE BRACKET
|
||||
〉 /> 232A 9002 RIGHT-POINTING ANGLE BRACKET
|
||||
␣ Vs 2423 9251 OPEN BOX
|
||||
⑀ 1h 2440 9280 OCR HOOK
|
||||
⑁ 3h 2441 9281 OCR CHAIR
|
||||
|
@@ -630,7 +630,7 @@ list of the current window.
|
||||
buffer.
|
||||
Also see |++opt| and |+cmd|.
|
||||
|
||||
:[count]arge[dit][!] [++opt] [+cmd] {name} ... *:arge* *:argedit*
|
||||
:[count]arge[dit][!] [++opt] [+cmd] {name} .. *:arge* *:argedit*
|
||||
Add {name}s to the argument list and edit it.
|
||||
There is no check for duplicates, it is possible to
|
||||
add a file to the argument list twice |:argded|.
|
||||
@@ -645,7 +645,7 @@ list of the current window.
|
||||
edited. No check for duplicates is done.
|
||||
Also see |++opt| and |+cmd|.
|
||||
|
||||
:[count]arga[dd] {name} ... *:arga* *:argadd* *E479*
|
||||
:[count]arga[dd] {name} .. *:arga* *:argadd* *E479*
|
||||
:[count]arga[dd] *E1156*
|
||||
Add the {name}s to the argument list. When {name} is
|
||||
omitted add the current buffer name to the argument
|
||||
@@ -676,7 +676,7 @@ list of the current window.
|
||||
If your current file is a duplicate, your current file
|
||||
will change to the original file index.
|
||||
|
||||
:argd[elete] {pattern} ... *:argd* *:argdelete* *E480* *E610*
|
||||
:argd[elete] {pattern} .. *:argd* *:argdelete* *E480* *E610*
|
||||
Delete files from the argument list that match the
|
||||
{pattern}s. {pattern} is used like a file pattern,
|
||||
see |file-pattern|. "%" can be used to delete the
|
||||
@@ -960,9 +960,8 @@ Note: When the 'write' option is off, you are not able to write any file.
|
||||
executed like with ":!{cmd}", any '!' is replaced with
|
||||
the previous command |:!|.
|
||||
|
||||
The default [range] for the ":w" command is the whole buffer (1,$). The |'[|
|
||||
and |']| marks will be set to the [range] being used for the write command.
|
||||
If you write the whole buffer, it is no longer considered changed. When you
|
||||
The default [range] for the ":w" command is the whole buffer (1,$). If you
|
||||
write the whole buffer, it is no longer considered changed. When you
|
||||
write it to a different file with ":w somefile" it depends on the "+" flag in
|
||||
'cpoptions'. When included, the write command will reset the 'modified' flag,
|
||||
even though the buffer itself may still be different from its file.
|
||||
@@ -1242,10 +1241,10 @@ MULTIPLE WINDOWS AND BUFFERS *window-exit*
|
||||
*:confirm* *:conf*
|
||||
:conf[irm] {command} Execute {command}, and use a dialog when an
|
||||
operation has to be confirmed. Can be used on the
|
||||
|:edit|, |:restart|, |:q|, |:qa| and |:w| commands
|
||||
(the latter to override a read-only setting), and any
|
||||
commands that can fail because of unsaved changes,
|
||||
such as |:only|, |:buffer|, |:bdelete|, etc.
|
||||
|:edit|, |:q|, |:qa| and |:w| commands (the latter to
|
||||
override a read-only setting), and any commands that
|
||||
can fail because of unsaved changes, such as |:only|,
|
||||
|:buffer|, |:bdelete|, etc.
|
||||
|
||||
Examples: >
|
||||
:confirm w foo
|
||||
@@ -1316,15 +1315,9 @@ b:browsefilter variable. You would most likely set b:browsefilter in a
|
||||
filetype plugin, so that the browse dialog would contain entries related to
|
||||
the type of file you are currently editing. Disadvantage: This makes it
|
||||
difficult to start editing a file of a different type. To overcome this, you
|
||||
can add the following as the final filter on Windows: >
|
||||
|
||||
All Files\t(*.*)\t*\n
|
||||
<
|
||||
Or the following on other platforms, so that the user can still access any
|
||||
desired file: >
|
||||
|
||||
All Files\t(*)\t*\n
|
||||
<
|
||||
may want to add "All Files (*.*)\t*\n" as the final filter on Windows or "All
|
||||
Files (*)\t*\n" on other platforms, so that the user can still access any
|
||||
desired file.
|
||||
|
||||
To avoid setting browsefilter when Vim does not actually support it, you can
|
||||
use has("browsefilter"): >
|
||||
@@ -1356,7 +1349,7 @@ exist, the next-higher scope in the hierarchy applies.
|
||||
|
||||
:cd[!] {path} Change the current directory to {path}.
|
||||
If {path} is relative, it is searched for in the
|
||||
directories listed in 'cdpath'.
|
||||
directories listed in |'cdpath'|.
|
||||
Clear any window-local directory.
|
||||
Does not change the meaning of an already opened file,
|
||||
because its full path name is remembered. Files from
|
||||
|
@@ -449,7 +449,10 @@ grow and enhance it. Changing the rules of Lua gains nothing in this context.
|
||||
|
||||
WILL NEOVIM TRANSLATE VIMSCRIPT TO LUA, INSTEAD OF EXECUTING VIMSCRIPT DIRECTLY? ~
|
||||
|
||||
We have no plans for transpiling Vimscript. It was explored in https://github.com/tjdevries/vim9jit
|
||||
- We are experimenting with vim9jit https://github.com/tjdevries/vim9jit to
|
||||
transpile Vim9script (Vim9's Vimscript variant) to Lua and have used this to
|
||||
port Vim9 plugins https://github.com/neovim/neovim/pull/21662 to Nvim Lua.
|
||||
- We have no plans for transpiling legacy Vimscript.
|
||||
|
||||
|
||||
ARE PLUGIN AUTHORS ENCOURAGED TO PORT THEIR PLUGINS FROM VIMSCRIPT TO LUA? DO YOU PLAN ON SUPPORTING VIMSCRIPT INDEFINITELY? (#1152) ~
|
||||
@@ -464,8 +467,4 @@ emphatically a fork of Vim in order to leverage the work already spent on
|
||||
thousands of Vim plugins, while enabling new types of plugins and
|
||||
integrations.
|
||||
|
||||
That being said, reimplementing legacy plugins in Lua in order to make use of
|
||||
Nvim API and to integrate with Nvim-specific features such as treesitter can
|
||||
be worthwhile.
|
||||
|
||||
vim:tw=78:ts=8:noet:ft=help:norl:
|
||||
|
@@ -156,8 +156,6 @@ variables can be used to overrule the filetype used for certain extensions:
|
||||
`*.inc` g:filetype_inc
|
||||
`*.lsl` g:filetype_lsl
|
||||
`*.m` g:filetype_m |ft-mathematica-syntax|
|
||||
`*[mM]makefile,*.mk,*.mak,[mM]akefile*`
|
||||
g:make_flavor |ft-make-syntax|
|
||||
`*.markdown,*.mdown,*.mkd,*.mkdn,*.mdwn,*.md`
|
||||
g:filetype_md |ft-pandoc-syntax|
|
||||
`*.mod` g:filetype_mod
|
||||
@@ -264,7 +262,7 @@ D. If your filetype can only be detected by inspecting the contents of the
|
||||
item of the 'runtimepath' option. Example for Unix: >
|
||||
:!mkdir -p ~/.config/nvim
|
||||
<
|
||||
2. Create a Vim script file for doing this. Example: >
|
||||
2. Create a vim script file for doing this. Example: >
|
||||
if did_filetype() " filetype already set..
|
||||
finish " ..don't do these checks
|
||||
endif
|
||||
@@ -625,16 +623,6 @@ possibilities: >
|
||||
The `:Cycle` command is also mapped to the CTRL-A and CTRL-X keys.
|
||||
For details, see `git-rebase --help`.
|
||||
|
||||
GLEAM *ft-gleam-plugin*
|
||||
|
||||
By default the following options are set for the recommended gleam style: >
|
||||
|
||||
setlocal expandtab shiftwidth=2 softtabstop=2
|
||||
|
||||
To disable this behavior, set the following variable in your vimrc: >
|
||||
|
||||
let g:gleam_recommended_style = 0
|
||||
|
||||
GO *ft-go-plugin*
|
||||
|
||||
By default the following options are set, based on Golang official docs: >
|
||||
@@ -661,32 +649,6 @@ HARE *ft-hare*
|
||||
Since the text for this plugin is rather long it has been put in a separate
|
||||
file: |ft_hare.txt|.
|
||||
|
||||
HTML *ft-html-plugin*
|
||||
|
||||
Tag folding poses a few difficulties. Many elements, e.g. `blockquote`, are
|
||||
always delimited by start and end tags; end tags for some elements, e.g. `p`,
|
||||
can be omitted in certain contexts; void elements, e.g. `hr`, have no end tag.
|
||||
Although the rules for supporting omissible end tags are ad-hoc and involved
|
||||
[0], they apply to elements in scope. Assuming syntactical wellformedness, an
|
||||
end tag can be associated with its nearest matching start tag discoverable in
|
||||
scope [1] and towards the beginning of a file, whereas all unbalanced tags and
|
||||
inlined tags can be disregarded. Having syntax highlighting in effect, tag
|
||||
folding using the |fold-expr| method can be enabled with: >
|
||||
let g:html_expr_folding = 1
|
||||
<
|
||||
By default, tag folding will be redone from scratch after each occurrence of
|
||||
a |TextChanged| or an |InsertLeave| event. Such frequency may not be desired,
|
||||
especially for large files, and this recomputation can be disabled with: >
|
||||
let g:html_expr_folding_without_recomputation = 1
|
||||
doautocmd FileType
|
||||
<
|
||||
To force another recomputation, do: >
|
||||
unlet! b:foldsmap
|
||||
normal zx
|
||||
<
|
||||
[0] https://html.spec.whatwg.org/multipage/syntax.html#optional-tags
|
||||
[1] https://en.wikipedia.org/wiki/Dangling_else
|
||||
|
||||
IDRIS2 *ft-idris2-plugin*
|
||||
|
||||
By default the following options are set: >
|
||||
@@ -823,8 +785,8 @@ Variables:
|
||||
For example in C one usually wants section 3 or 2: >
|
||||
:let b:man_default_sections = '3,2'
|
||||
*g:man_hardwrap* Hard-wrap to $MANWIDTH or window width if $MANWIDTH is
|
||||
empty or larger than the window width. Enabled by
|
||||
default. Set |FALSE| to enable soft wrapping.
|
||||
empty. Enabled by default. Set |FALSE| to enable soft
|
||||
wrapping.
|
||||
|
||||
To use Nvim as a manpager: >bash
|
||||
export MANPAGER='nvim +Man!'
|
||||
@@ -1155,13 +1117,6 @@ functions with [[ and ]]. Move around comments with ]" and [".
|
||||
The mappings can be disabled with: >
|
||||
let g:no_vim_maps = 1
|
||||
|
||||
YAML *ft-yaml-plugin*
|
||||
By default, the YAML filetype plugin enables the following options: >
|
||||
setlocal shiftwidth=2 softtabstop=2
|
||||
|
||||
To disable this, set the following variable: >
|
||||
let g:yaml_recommended_style = 0
|
||||
|
||||
|
||||
ZIG *ft-zig-plugin*
|
||||
|
||||
|
@@ -632,17 +632,14 @@ what you type!
|
||||
When using an operator, a closed fold is included as a whole. Thus "dl"
|
||||
deletes the whole closed fold under the cursor.
|
||||
|
||||
For Ex commands that operate on buffer lines, the range is adjusted to always
|
||||
For Ex commands that work on buffer lines the range is adjusted to always
|
||||
start at the first line of a closed fold and end at the last line of a closed
|
||||
fold. Thus, this command: >
|
||||
fold. Thus this command: >
|
||||
:s/foo/bar/g
|
||||
when used with the cursor on a closed fold, will replace "foo" with "bar" in
|
||||
all lines of the fold.
|
||||
This does not happen for |:folddoopen| and |:folddoclosed|.
|
||||
|
||||
Note that for some Ex commands like |:source| the range is only adjusted when
|
||||
using a two line specifiers [range].
|
||||
|
||||
When editing a buffer that has been edited before, the last used folding
|
||||
settings are used again. For manual folding the defined folds are restored.
|
||||
For all folding methods the manually opened and closed folds are restored.
|
||||
@@ -650,4 +647,5 @@ If this buffer has been edited in this window, the values from back then are
|
||||
used. Otherwise the values from the window where the buffer was edited last
|
||||
are used.
|
||||
|
||||
==============================================================================
|
||||
vim:tw=78:ts=8:noet:ft=help:norl:
|
||||
|
@@ -76,8 +76,8 @@ The Ada plug-in provides support for:
|
||||
- user completion (|i_CTRL-X_CTRL-U|)
|
||||
- tag searches (|tagsrch.txt|)
|
||||
- Quick Fix (|quickfix.txt|)
|
||||
- backspace handling ('backspace')
|
||||
- comment handling ('comments', 'commentstring')
|
||||
- backspace handling (|'backspace'|)
|
||||
- comment handling (|'comments'|, |'commentstring'|)
|
||||
|
||||
The plug-in only activates the features of the Ada mode whenever an Ada
|
||||
file is opened and adds Ada related entries to the main and pop-up menu.
|
||||
@@ -197,7 +197,7 @@ g:gnat.Project_File string
|
||||
|
||||
*g:gnat.Make_Command*
|
||||
g:gnat.Make_Command string
|
||||
External command used for |g:gnat.Make()| ('makeprg').
|
||||
External command used for |g:gnat.Make()| (|'makeprg'|).
|
||||
|
||||
*g:gnat.Pretty_Program*
|
||||
g:gnat.Pretty_Program string
|
||||
@@ -213,7 +213,7 @@ g:gnat.Tags_Command string
|
||||
|
||||
*g:gnat.Error_Format*
|
||||
g:gnat.Error_Format string
|
||||
Error format ('errorformat')
|
||||
Error format (|'errorformat'|)
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
4.2 Dec Ada ~
|
||||
@@ -243,11 +243,11 @@ g:decada.Unit_Name() function
|
||||
|
||||
*g:decada.Make_Command*
|
||||
g:decada.Make_Command string
|
||||
External command used for |g:decada.Make()| ('makeprg').
|
||||
External command used for |g:decada.Make()| (|'makeprg'|).
|
||||
|
||||
*g:decada.Error_Format*
|
||||
g:decada.Error_Format string
|
||||
Error format ('errorformat').
|
||||
Error format (|'errorformat'|).
|
||||
|
||||
==============================================================================
|
||||
5. References ~
|
||||
@@ -507,4 +507,6 @@ taglist.vim
|
||||
The GNU Ada Project distribution (http://gnuada.sourceforge.net) of Vim
|
||||
contains all of the above.
|
||||
|
||||
vim:tw=78:ts=8:noet:ft=help:norl:
|
||||
==============================================================================
|
||||
vim: textwidth=78 nowrap tabstop=8 shiftwidth=4 softtabstop=4 noexpandtab
|
||||
vim: filetype=help
|
||||
|
@@ -73,4 +73,5 @@ The maximum search depth can be set to any integer, but using values higher
|
||||
than 2 is not recommended, and will likely provide no tangible benefit in most
|
||||
situations.
|
||||
|
||||
==============================================================================
|
||||
vim:tw=78:ts=8:noet:ft=help:norl:
|
||||
|
@@ -60,4 +60,5 @@ Many other distributions are available for Windows like
|
||||
https://chocolatey.org/packages/less/. Make sure `less` is in a directory
|
||||
listed in the `PATH` environment variable, which chocolatey above does.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
vim:ft=help:
|
||||
|
@@ -160,18 +160,7 @@ g:rustfmt_emit_files ~
|
||||
provided) instead of '--write-mode=overwrite'. >vim
|
||||
let g:rustfmt_emit_files = 0
|
||||
<
|
||||
*g:rustfmt_detect_version*
|
||||
g:rustfmt_detect_version ~
|
||||
When set to 1, will try to parse the version output from "rustfmt".
|
||||
Disabled by default for performance reasons >vim
|
||||
let g:rustfmt_detect_version = 1
|
||||
<
|
||||
*g:rustfmt_find_toml*
|
||||
g:rustfmt_emit_files ~
|
||||
When set to 1, will try to find "rustfmt.toml" file by searching from
|
||||
current path upwards. Disabled by default for performance reasons >vim
|
||||
let g:rustfmt_find_toml = 1
|
||||
<
|
||||
|
||||
*g:rust_playpen_url*
|
||||
g:rust_playpen_url ~
|
||||
Set this option to override the url for the playpen to use: >vim
|
||||
@@ -486,4 +475,4 @@ MAPPINGS *rust-mappings*
|
||||
This plugin defines mappings for |[[| and |]]| to support hanging indents.
|
||||
|
||||
|
||||
vim:tw=78:sw=4:noet:ts=8:ft=help:norl:
|
||||
vim:tw=78:sw=4:noet:ts=8:ft=help:norl:
|
||||
|
@@ -172,7 +172,7 @@ with comments: >
|
||||
------------------------------------------------------------------------------
|
||||
1.4 Macros *sql-macros*
|
||||
|
||||
Vim's feature to find macro definitions, 'define', is supported using this
|
||||
Vim's feature to find macro definitions, |'define'|, is supported using this
|
||||
regular expression: >
|
||||
\c\<\(VARIABLE\|DECLARE\|IN\|OUT\|INOUT\)\>
|
||||
|
||||
@@ -249,7 +249,7 @@ key to complete the optional parameter.
|
||||
After typing the function name and a space, you can use the completion to
|
||||
supply a parameter. The function takes the name of the Vim script you want to
|
||||
source. Using the |cmdline-completion| feature, the SQLSetType function will
|
||||
search the 'runtimepath' for all Vim scripts with a name containing "sql".
|
||||
search the |'runtimepath'| for all Vim scripts with a name containing "sql".
|
||||
This takes the guess work out of the spelling of the names. The following are
|
||||
examples: >
|
||||
:SQLSetType
|
||||
@@ -412,7 +412,7 @@ Here are some examples of the entries which are pulled from the syntax files: >
|
||||
|
||||
Dynamic mode populates the popups with data directly from a database. In
|
||||
order for the dynamic feature to be enabled you must have the dbext.vim
|
||||
plugin installed, (https://www.vim.org/scripts/script.php?script_id=356).
|
||||
plugin installed, (https://vim.sourceforge.net/script.php?script_id=356).
|
||||
|
||||
Dynamic mode is used by several features of the SQL completion plugin.
|
||||
After installing the dbext plugin see the dbext-tutorial for additional
|
||||
@@ -496,7 +496,7 @@ depending on the syntax file you are using. The SQL Anywhere syntax file
|
||||
Dynamic features ~
|
||||
|
||||
To take advantage of the dynamic features you must first install the
|
||||
dbext.vim plugin (https://www.vim.org/scripts/script.php?script_id=356). It
|
||||
dbext.vim plugin (https://vim.sourceforge.net/script.php?script_id=356). It
|
||||
also comes with a tutorial. From the SQL completion plugin's perspective,
|
||||
the main feature dbext provides is a connection to a database. dbext
|
||||
connection profiles are the most efficient mechanism to define connection
|
||||
@@ -760,7 +760,7 @@ Step 1 ~
|
||||
Begins by editing a Perl file. Vim automatically sets the filetype to
|
||||
"perl". By default, Vim runs the appropriate filetype file
|
||||
ftplugin/perl.vim. If you are using the syntax completion plugin by following
|
||||
the directions at |ft-syntax-omni| then the 'omnifunc' option has been set to
|
||||
the directions at |ft-syntax-omni| then the |'omnifunc'| option has been set to
|
||||
"syntax#Complete". Pressing <C-X><C-O> will display the omni popup containing
|
||||
the syntax items for Perl.
|
||||
|
||||
@@ -772,7 +772,7 @@ maps for SQL completion, see |sql-completion-maps|. Now these maps have
|
||||
been created and the SQL completion plugin has been initialized. All SQL
|
||||
syntax items have been cached in preparation. The SQL filetype script detects
|
||||
we are attempting to use two different completion plugins. Since the SQL maps
|
||||
begin with <C-C>, the maps will toggle the 'omnifunc' when in use. So you
|
||||
begin with <C-C>, the maps will toggle the |'omnifunc'| when in use. So you
|
||||
can use <C-X><C-O> to continue using the completion for Perl (using the syntax
|
||||
completion plugin) and <C-C> to use the SQL completion features.
|
||||
|
||||
|
@@ -17,8 +17,6 @@ TUI and GUI (assuming the UI supports the given feature). See |TUI| for notes
|
||||
specific to the terminal UI. Help tags with the "gui-" prefix refer to UI
|
||||
features, whereas help tags with the "ui-" prefix refer to the |ui-protocol|.
|
||||
|
||||
Type |gO| to see the table of contents.
|
||||
|
||||
==============================================================================
|
||||
Third-party GUIs *third-party-guis* *vscode*
|
||||
|
||||
@@ -36,6 +34,8 @@ a Nvim GUI.
|
||||
- VimR (macOS) https://github.com/qvacua/vimr
|
||||
- Others https://github.com/neovim/neovim/wiki/Related-projects#gui
|
||||
|
||||
Type |gO| to see the table of contents.
|
||||
|
||||
==============================================================================
|
||||
Starting the GUI *gui-config* *gui-start*
|
||||
|
||||
@@ -64,50 +64,7 @@ Stop or detach the current UI
|
||||
the channel to be closed, it may be (incorrectly) reported as
|
||||
an error.
|
||||
|
||||
Note: Not supported on Windows yet.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
Restart Nvim
|
||||
|
||||
*:restart*
|
||||
:restart [+cmd] [command]
|
||||
Restarts Nvim.
|
||||
|
||||
1. Stops Nvim using `:qall!` (or |+cmd|, if given).
|
||||
2. Starts a new Nvim server using the same |v:argv|,
|
||||
optionally running [command] at startup. |-c|
|
||||
3. Attaches the current UI to the new Nvim server. Other UIs
|
||||
(if any) will not reattach on restart (this may change in
|
||||
the future).
|
||||
|
||||
Use with `:confirm` to prompt if changes have been made.
|
||||
|
||||
Example: stop with `:qall!`, then restart: >
|
||||
:restart +qall!
|
||||
< Example: restart and restore the current session: >
|
||||
:mksession! Session.vim | restart source Session.vim
|
||||
< Example: restart and update plugins: >
|
||||
:restart +qall! lua vim.pack.update()
|
||||
<
|
||||
Note: Only works if the UI and server are on the same system.
|
||||
Note: If the UI hasn't implemented the "restart" UI event,
|
||||
this command is equivalent to `:qall!`.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
Connect UI to a different server
|
||||
|
||||
*:connect*
|
||||
|
||||
:connect {address}
|
||||
Detaches the UI from the server it is currently attached to
|
||||
and attaches it to the server at {address} instead.
|
||||
|
||||
Note: If the current UI hasn't implemented the "connect" UI
|
||||
event, this command is equivalent to |:detach|.
|
||||
|
||||
:connect! {address}
|
||||
Same as |:connect| but it also stops the detached server if
|
||||
no other UI is currently attached to it.
|
||||
Note: Not supported on Windows, currently.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
GUI commands
|
||||
|
@@ -112,6 +112,7 @@ API (EXTENSIBILITY/SCRIPTING/PLUGINS)
|
||||
|channel| Nvim asynchronous IO
|
||||
|vimscript| Vimscript reference
|
||||
|vimscript-functions| Vimscript functions
|
||||
|testing.txt| Vimscript testing functions
|
||||
|remote-plugin| Nvim remote plugins
|
||||
|health| Health checking
|
||||
|
||||
|
@@ -337,7 +337,7 @@ in such a modeline, that can have undesired consequences.
|
||||
|
||||
TAGS
|
||||
|
||||
To define a help tag, place the name between asterisks ("*tag-name*"). The
|
||||
To define a help tag, place the name between asterisks (*tag-name*). The
|
||||
tag-name should be different from all the Vim help tag names and ideally
|
||||
should begin with the name of the Vim plugin. The tag name is usually right
|
||||
aligned on a line.
|
||||
@@ -397,10 +397,4 @@ highlighting. So do these:
|
||||
You can find the details in $VIMRUNTIME/syntax/help.vim
|
||||
|
||||
|
||||
FILETYPE COMPLETION *ft-help-omni*
|
||||
|
||||
To get completion for help tags when writing a tag reference, you can use the
|
||||
|i_CTRL-X_CTRL-O| command.
|
||||
|
||||
|
||||
vim:tw=78:ts=8:noet:ft=help:norl:
|
||||
|
@@ -268,4 +268,5 @@ These are also available via the "main" package:
|
||||
$main::curwin The current Window object.
|
||||
$main::curbuf The current Buffer object.
|
||||
|
||||
==============================================================================
|
||||
vim:tw=78:ts=8:noet:ft=help:norl:
|
||||
|
@@ -645,6 +645,6 @@ To check if `pyx*` functions and commands are available: >vim
|
||||
if has('pythonx')
|
||||
echo 'pyx* commands are available. (Python ' .. &pyx .. ')'
|
||||
endif
|
||||
<
|
||||
|
||||
==============================================================================
|
||||
vim:tw=78:ts=8:noet:ft=help:norl:
|
||||
|
@@ -189,4 +189,5 @@ evaluate Ruby expressions and pass their values to Vim script.
|
||||
The Ruby value "true", "false" and "nil" are converted to v:true, v:false and
|
||||
v:null, respectively.
|
||||
|
||||
==============================================================================
|
||||
vim:tw=78:ts=8:noet:ft=help:norl:
|
||||
|
@@ -146,7 +146,6 @@ commands in CTRL-X submode *i_CTRL-X_index*
|
||||
|i_CTRL-X_CTRL-N| CTRL-X CTRL-N next completion
|
||||
|i_CTRL-X_CTRL-O| CTRL-X CTRL-O omni completion
|
||||
|i_CTRL-X_CTRL-P| CTRL-X CTRL-P previous completion
|
||||
|i_CTRL-X_CTRL-R| CTRL-X CTRL-R complete contents from registers
|
||||
|i_CTRL-X_CTRL-S| CTRL-X CTRL-S spelling suggestions
|
||||
|i_CTRL-X_CTRL-T| CTRL-X CTRL-T complete identifiers from thesaurus
|
||||
|i_CTRL-X_CTRL-Y| CTRL-X CTRL-Y scroll down
|
||||
@@ -516,7 +515,7 @@ tag command action in op-pending and Visual mode ~
|
||||
tag command action in Normal mode ~
|
||||
------------------------------------------------------------------------------ ~
|
||||
|CTRL-W_CTRL-B| CTRL-W CTRL-B same as "CTRL-W b"
|
||||
|CTRL-W_CTRL-C| CTRL-W CTRL-C no-op
|
||||
|CTRL-W_CTRL-C| CTRL-W CTRL-C same as "CTRL-W c"
|
||||
|CTRL-W_CTRL-D| CTRL-W CTRL-D same as "CTRL-W d"
|
||||
|CTRL-W_CTRL-F| CTRL-W CTRL-F same as "CTRL-W f"
|
||||
CTRL-W CTRL-G same as "CTRL-W g .."
|
||||
@@ -1017,7 +1016,7 @@ tag command action in Command-line editing mode ~
|
||||
|c_CTRL-D| CTRL-D list completions that match the pattern in
|
||||
front of the cursor
|
||||
|c_CTRL-E| CTRL-E cursor to end of command-line
|
||||
'cedit' CTRL-F default value for 'cedit': opens the
|
||||
|'cedit'| CTRL-F default value for 'cedit': opens the
|
||||
command-line window; otherwise not used
|
||||
|c_CTRL-G| CTRL-G next match when 'incsearch' is active
|
||||
|c_<BS>| <BS> delete the character in front of the cursor
|
||||
@@ -1266,7 +1265,6 @@ tag command action ~
|
||||
|:delcommand| :delc[ommand] delete user-defined command
|
||||
|:delfunction| :delf[unction] delete a user function
|
||||
|:delmarks| :delm[arks] delete marks
|
||||
|:detach| :detach detach the current UI
|
||||
|:diffupdate| :dif[fupdate] update 'diff' buffers
|
||||
|:diffget| :diffg[et] remove differences in current buffer
|
||||
|:diffoff| :diffo[ff] switch off diff mode
|
||||
@@ -1350,8 +1348,6 @@ tag command action ~
|
||||
|:inoreabbrev| :inorea[bbrev] like ":noreabbrev" but for Insert mode
|
||||
|:inoremenu| :inoreme[nu] like ":noremenu" but for Insert mode
|
||||
|:intro| :int[ro] print the introductory message
|
||||
|:iput| :ip[ut] like |:put|, but adjust the indent to the
|
||||
current line
|
||||
|:isearch| :is[earch] list one line where identifier matches
|
||||
|:isplit| :isp[lit] split window and jump to definition of
|
||||
identifier
|
||||
@@ -1473,6 +1469,7 @@ tag command action ~
|
||||
|:options| :opt[ions] open the options-window
|
||||
|:ounmap| :ou[nmap] like ":unmap" but for Operator-pending mode
|
||||
|:ounmenu| :ounme[nu] remove menu for Operator-pending mode
|
||||
|:ownsyntax| :ow[nsyntax] set new local syntax highlight for this window
|
||||
|:packadd| :pa[ckadd] add a plugin from 'packpath'
|
||||
|:packloadall| :packl[oadall] load all packages under 'packpath'
|
||||
|:pbuffer| :pb[uffer] edit buffer in the preview window
|
||||
@@ -1525,7 +1522,6 @@ tag command action ~
|
||||
|:redrawtabline| :redrawt[abline] force a redraw of the tabline
|
||||
|:registers| :reg[isters] display the contents of registers
|
||||
|:resize| :res[ize] change current window height
|
||||
|:restart| :restart restart the Nvim server
|
||||
|:retab| :ret[ab] change tab size
|
||||
|:return| :retu[rn] return from a user function
|
||||
|:rewind| :rew[ind] go to the first file in the argument list
|
||||
@@ -1667,7 +1663,6 @@ tag command action ~
|
||||
|:unabbreviate| :una[bbreviate] remove abbreviation
|
||||
|:unhide| :unh[ide] open a window for each loaded file in the
|
||||
buffer list
|
||||
|:uniq| :uni[q] uniq lines
|
||||
|:unlet| :unl[et] delete variable
|
||||
|:unlockvar| :unlo[ckvar] unlock variables
|
||||
|:unmap| :unm[ap] remove mapping
|
||||
|
@@ -29,7 +29,7 @@ use "CTRL-V 003" to insert a CTRL-C. Note: When CTRL-V is mapped you can
|
||||
often use CTRL-Q instead |i_CTRL-Q|.
|
||||
|
||||
If you are working in a special language mode when inserting text, see the
|
||||
'langmap' option, 'langmap', on how to avoid switching this mode on and off
|
||||
'langmap' option, |'langmap'|, on how to avoid switching this mode on and off
|
||||
all the time.
|
||||
|
||||
char action ~
|
||||
@@ -103,10 +103,8 @@ CTRL-P Find previous keyword (see |i_CTRL-P|).
|
||||
CTRL-R {register} *i_CTRL-R*
|
||||
Insert the contents of a register. Between typing CTRL-R and
|
||||
the second character, '"' will be displayed to indicate that
|
||||
you are expected to enter the name of a register. When used
|
||||
with named or clipboard registers (A-Z,a-z,0-9,+) text is
|
||||
inserted literally like pasting with "p". For other registers,
|
||||
the text is inserted as if you typed it, but mappings and
|
||||
you are expected to enter the name of a register.
|
||||
The text is inserted as if you typed it, but mappings and
|
||||
abbreviations are not used. If you have options like
|
||||
'textwidth', 'formatoptions', or 'autoindent' set, this will
|
||||
influence what will be inserted. This is different from what
|
||||
@@ -133,8 +131,6 @@ CTRL-R {register} *i_CTRL-R*
|
||||
special keys. E.g., you can use this to move
|
||||
the cursor up:
|
||||
CTRL-R ="\<Up>"
|
||||
you can use this to insert a register as
|
||||
typed with CTRL-R =@reg.
|
||||
Use CTRL-R CTRL-R to insert text literally.
|
||||
When the result is a |List| the items are used
|
||||
as lines. They can have line breaks inside
|
||||
@@ -273,17 +269,15 @@ The effect of the <BS>, CTRL-W, and CTRL-U depend on the 'backspace' option
|
||||
|
||||
item action ~
|
||||
indent allow backspacing over autoindent
|
||||
eol allow backspacing over line breaks (join lines)
|
||||
start allow backspacing over the start of insert; CTRL-W and CTRL-U stop
|
||||
once at the start of insert.
|
||||
nostop like start, except CTRL-W and CTRL-U do not stop at the start of
|
||||
insert.
|
||||
eol allow backspacing over end-of-line (join lines)
|
||||
start allow backspacing over the start position of insert; CTRL-W and
|
||||
CTRL-U stop once at the start position
|
||||
|
||||
When 'backspace' is empty, Vi compatible backspacing is used. You cannot
|
||||
backspace over autoindent, before column 1 or before where insert started.
|
||||
|
||||
For backwards compatibility the values "0", "1", "2" and "3" are also allowed,
|
||||
see 'backspace'.
|
||||
see |'backspace'|.
|
||||
|
||||
If the 'backspace' option does contain "eol" and the cursor is in column 1
|
||||
when one of the three keys is used, the current line is joined with the
|
||||
@@ -516,7 +510,7 @@ paragraph, no matter where the cursor currently is. Or you can use Visual
|
||||
mode: hit "v", move to the end of the block, and type "gq". See also |gq|.
|
||||
|
||||
==============================================================================
|
||||
4. 'expandtab', 'softtabstop' and 'smarttab' options *ins-expandtab*
|
||||
4. 'expandtab', 'smarttab' and 'softtabstop' options *ins-expandtab*
|
||||
|
||||
If the 'expandtab' option is on, spaces will be used to fill the amount of
|
||||
whitespace of the tab. If you want to enter a real <Tab>, type CTRL-V first
|
||||
@@ -527,6 +521,13 @@ number of characters in the line increases. Backspacing will delete one
|
||||
space at a time. The original character will be put back for only one space
|
||||
that you backspace over (the last one).
|
||||
|
||||
*ins-smarttab*
|
||||
When the 'smarttab' option is on, a <Tab> inserts 'shiftwidth' positions at
|
||||
the beginning of a line and 'tabstop' positions in other places. This means
|
||||
that often spaces instead of a <Tab> character are inserted. When 'smarttab'
|
||||
is off, a <Tab> always inserts 'tabstop' positions, and 'shiftwidth' is only
|
||||
used for ">>" and the like.
|
||||
|
||||
*ins-softtabstop*
|
||||
When the 'softtabstop' option is non-zero, a <Tab> inserts 'softtabstop'
|
||||
positions, and a <BS> used to delete white space, will delete 'softtabstop'
|
||||
@@ -541,13 +542,6 @@ the cursor. Otherwise you cannot always delete a single character before the
|
||||
cursor. You will have to delete 'softtabstop' characters first, and then type
|
||||
extra spaces to get where you want to be.
|
||||
|
||||
*ins-smarttab*
|
||||
When the 'smarttab' option is on, the <Tab> key indents by 'shiftwidth' if the
|
||||
cursor is in leading whitespace. The <BS> key has the opposite effect. This
|
||||
behaves as if 'softtabstop' were set to the value of 'shiftwidth'. This option
|
||||
allows the user to set 'softtabstop' to a value other than 'shiftwidth' and
|
||||
still use the <Tab> key for indentation.
|
||||
|
||||
==============================================================================
|
||||
5. Replace mode *Replace* *Replace-mode* *mode-replace*
|
||||
|
||||
@@ -605,7 +599,7 @@ In 'list' mode, Virtual Replace mode acts as if it was not in 'list' mode,
|
||||
unless "L" is in 'cpoptions'.
|
||||
|
||||
Note that the only situations for which characters beyond the cursor should
|
||||
appear to move are in List mode 'list', and occasionally when 'wrap' is set
|
||||
appear to move are in List mode |'list'|, and occasionally when 'wrap' is set
|
||||
(and the line changes length to become shorter or wider than the width of the
|
||||
screen). In other cases spaces may be inserted to avoid following characters
|
||||
to move.
|
||||
@@ -634,8 +628,7 @@ Completion can be done for:
|
||||
10. User defined completion |i_CTRL-X_CTRL-U|
|
||||
11. omni completion |i_CTRL-X_CTRL-O|
|
||||
12. Spelling suggestions |i_CTRL-X_s|
|
||||
13. completions from 'complete' |i_CTRL-N| |i_CTRL-P|
|
||||
14. contents from registers |i_CTRL-X_CTRL-R|
|
||||
13. keywords in 'complete' |i_CTRL-N| |i_CTRL-P|
|
||||
|
||||
Additionally, |i_CTRL-X_CTRL-Z| stops completion without changing the text.
|
||||
|
||||
@@ -645,9 +638,6 @@ and one of the CTRL-X commands. You exit CTRL-X mode by typing a key that is
|
||||
not a valid CTRL-X mode command. Valid keys are the CTRL-X command itself,
|
||||
CTRL-N (next), and CTRL-P (previous).
|
||||
|
||||
By default, the possible completions are showed in a menu and the first
|
||||
completion is inserted into the text. This can be adjusted with 'completeopt'.
|
||||
|
||||
To get the current completion information, |complete_info()| can be used.
|
||||
Also see the 'infercase' option if you want to adjust the case of the match.
|
||||
|
||||
@@ -661,11 +651,10 @@ When completion is active you can use CTRL-E to stop it and go back to the
|
||||
originally typed text. The CTRL-E will not be inserted.
|
||||
|
||||
*complete_CTRL-Y*
|
||||
When the popup menu is displayed, CTRL-Y stops completion and accepts the
|
||||
currently selected entry. Typing a space, Enter, or some other unprintable
|
||||
character will leave completion mode and insert that typed character. If you
|
||||
want to use <Enter> to accept a completion item, use this mapping: >vim
|
||||
inoremap <expr> <cr> pumvisible() ? '<c-y>' : '<cr>'
|
||||
When the popup menu is displayed you can use CTRL-Y to stop completion and
|
||||
accept the currently selected entry. The CTRL-Y is not inserted. Typing a
|
||||
space, Enter, or some other unprintable character will leave completion mode
|
||||
and insert that typed character.
|
||||
|
||||
When the popup menu is displayed there are a few more special keys, see
|
||||
|popupmenu-keys|.
|
||||
@@ -1009,25 +998,6 @@ CTRL-X CTRL-V Guess what kind of item is in front of the cursor and
|
||||
completion, for example: >
|
||||
:imap <Tab> <C-X><C-V>
|
||||
|
||||
Completing contents from registers *compl-register-words*
|
||||
*i_CTRL-X_CTRL-R*
|
||||
CTRL-X CTRL-R Guess what kind of item is in front of the cursor from
|
||||
all registers and find the first match for it.
|
||||
Further use of CTRL-R (without CTRL-X) will insert the
|
||||
register content, see |i_CTRL-R|.
|
||||
'ignorecase' applies to the matching.
|
||||
|
||||
CTRL-N Search forwards for next match. This match replaces
|
||||
the previous one.
|
||||
|
||||
CTRL-P Search backwards for previous match. This match
|
||||
replaces the previous one.
|
||||
|
||||
CTRL-X CTRL-R Further use of CTRL-X CTRL-R will copy the line
|
||||
following the previous expansion in other contexts
|
||||
unless a double CTRL-X is used (e.g. this switches
|
||||
from completing register words to register contents).
|
||||
|
||||
User defined completion *compl-function*
|
||||
|
||||
Completion is done by a function that can be defined by the user with the
|
||||
@@ -1088,23 +1058,25 @@ CTRL-X s Locate the word in front of the cursor and find the
|
||||
previous one.
|
||||
|
||||
|
||||
Completing from different sources *compl-generic*
|
||||
Completing keywords from different sources *compl-generic*
|
||||
|
||||
*i_CTRL-N*
|
||||
CTRL-N Find the next match for a word ending at the cursor,
|
||||
using the sources specified in the 'complete' option.
|
||||
All sources complete from keywords, except functions,
|
||||
which may complete from non-keyword. The matched
|
||||
text is inserted before the cursor.
|
||||
CTRL-N Find next match for words that start with the
|
||||
keyword in front of the cursor, looking in places
|
||||
specified with the 'complete' option. The found
|
||||
keyword is inserted in front of the cursor.
|
||||
|
||||
*i_CTRL-P*
|
||||
CTRL-P Same as CTRL-N, but find the previous match.
|
||||
CTRL-P Find previous match for words that start with the
|
||||
keyword in front of the cursor, looking in places
|
||||
specified with the 'complete' option. The found
|
||||
keyword is inserted in front of the cursor.
|
||||
|
||||
CTRL-N Search forward through the matches and insert the
|
||||
next one.
|
||||
CTRL-N Search forward for next matching keyword. This
|
||||
keyword replaces the previous matching keyword.
|
||||
|
||||
CTRL-P Search backward through the matches and insert the
|
||||
previous one.
|
||||
CTRL-P Search backwards for next matching keyword. This
|
||||
keyword replaces the previous matching keyword.
|
||||
|
||||
CTRL-X CTRL-N or
|
||||
CTRL-X CTRL-P Further use of CTRL-X CTRL-N or CTRL-X CTRL-P will
|
||||
@@ -1118,25 +1090,26 @@ Stop completion *compl-stop*
|
||||
CTRL-X CTRL-Z Stop completion without changing the text.
|
||||
|
||||
|
||||
AUTOCOMPLETION *ins-autocompletion*
|
||||
AUTO-COMPLETION *compl-autocomplete*
|
||||
|
||||
Vim can display a completion menu as you type, similar to using |i_CTRL-N|,
|
||||
but triggered automatically. See 'autocomplete'. The menu items are collected
|
||||
from the sources listed in the 'complete' option, in order.
|
||||
|
||||
A decaying timeout keeps Vim responsive. Sources earlier in the 'complete'
|
||||
list get more time (higher priority), but all sources receive at least a small
|
||||
time slice.
|
||||
|
||||
This mode is fully compatible with other completion modes. You can invoke
|
||||
any of them at any time by typing |CTRL-X|, which temporarily suspends
|
||||
autocompletion. To use |i_CTRL-N| or |i_CTRL-X_CTRL-N| specifically, press
|
||||
|CTRL-E| first to dismiss the popup menu (see |complete_CTRL-E|).
|
||||
|
||||
See also 'autocomplete', 'autocompletetimeout' and 'autocompletedelay'.
|
||||
|
||||
To get LSP-driven auto-completion, see |lsp-completion|.
|
||||
To get LSP-driven auto-completion, see |lsp-completion|. To get basic
|
||||
auto-completion without installing plugins or LSP, try this: >lua
|
||||
|
||||
local triggers = {'.'}
|
||||
vim.api.nvim_create_autocmd('InsertCharPre', {
|
||||
buffer = vim.api.nvim_get_current_buf(),
|
||||
callback = function()
|
||||
if vim.fn.pumvisible() == 1 or vim.fn.state('m') == 'm' then
|
||||
return
|
||||
end
|
||||
local char = vim.v.char
|
||||
if vim.list_contains(triggers, char) then
|
||||
local key = vim.keycode('<C-x><C-n>')
|
||||
vim.api.nvim_feedkeys(key, 'm', false)
|
||||
end
|
||||
end
|
||||
})
|
||||
<
|
||||
|
||||
FUNCTIONS FOR FINDING COMPLETIONS *complete-functions*
|
||||
|
||||
@@ -1189,9 +1162,6 @@ For example, the function can contain this: >
|
||||
let matches = ... list of words ...
|
||||
return {'words': matches, 'refresh': 'always'}
|
||||
<
|
||||
If looking for matches is time-consuming, |complete_check()| may be used to
|
||||
maintain responsiveness.
|
||||
|
||||
*complete-items*
|
||||
Each list item can either be a string or a Dictionary. When it is a string it
|
||||
is used as the completion. When it is a Dictionary it can contain these
|
||||
@@ -1326,7 +1296,6 @@ use all space available.
|
||||
The 'pumwidth' option can be used to set a minimum width. The default is 15
|
||||
characters.
|
||||
|
||||
*compl-states*
|
||||
There are three states:
|
||||
1. A complete match has been inserted, e.g., after using CTRL-N or CTRL-P.
|
||||
2. A cursor key has been used to select another match. The match was not
|
||||
|
@@ -89,7 +89,7 @@ To uninstall Nvim:
|
||||
- Scoop (Windows): `scoop uninstall neovim`
|
||||
|
||||
==============================================================================
|
||||
Sponsor Vim/Nvim development *sponsor*
|
||||
Sponsor Vim/Nvim development *sponsor* *register*
|
||||
|
||||
Fixing bugs and adding new features takes a lot of time and effort. To show
|
||||
your appreciation for the work and motivate developers to continue working on
|
||||
@@ -605,7 +605,7 @@ status messages will only be used if an option is on: >
|
||||
command characters 'showcmd' on off
|
||||
cursor position 'ruler' off off
|
||||
|
||||
The current mode is "-- INSERT --" or "-- REPLACE --", see 'showmode'. The
|
||||
The current mode is "-- INSERT --" or "-- REPLACE --", see |'showmode'|. The
|
||||
command characters are those that you typed but were not used yet.
|
||||
|
||||
If you have a slow terminal you can switch off the status messages to speed
|
||||
@@ -711,4 +711,5 @@ Arbitrary code registered via |:UpdateRemotePlugins|, that runs in a separate
|
||||
process and communicates with Nvim via the |api|.
|
||||
|
||||
|
||||
==============================================================================
|
||||
vim:tw=78:ts=8:et:sw=4:ft=help:norl:
|
||||
|
@@ -140,4 +140,5 @@ A job may be killed at any time with the |jobstop()| function:
|
||||
<
|
||||
Individual streams can be closed without killing the job, see |chanclose()|.
|
||||
|
||||
==============================================================================
|
||||
vim:tw=78:ts=8:noet:ft=help:norl:
|
||||
|
1580
runtime/doc/lsp.txt
1580
runtime/doc/lsp.txt
File diff suppressed because it is too large
Load Diff
@@ -376,7 +376,8 @@ strongly advised not to rely on undefined or implementation-defined behavior.
|
||||
==============================================================================
|
||||
COPYRIGHT
|
||||
|
||||
Lua BitOp is Copyright (C) 2008-2025 Mike Pall.
|
||||
Lua BitOp is Copyright (C) 2008-2012 Mike Pall.
|
||||
Lua BitOp is free software, released under the MIT license.
|
||||
|
||||
==============================================================================
|
||||
vim:tw=78:ts=4:sw=4:sts=4:et:ft=help:norl:
|
||||
|
@@ -10,18 +10,19 @@
|
||||
==============================================================================
|
||||
Introduction *lua-guide*
|
||||
|
||||
This guide introduces the basics of everyday Lua usage for configuring and
|
||||
controlling Nvim. It assumes some familiarity with the (non-Lua) basics of
|
||||
Nvim (commands, options, mappings, autocommands), which are covered in the
|
||||
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
|
||||
(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*
|
||||
|
||||
@@ -29,17 +30,16 @@ The purpose of this guide is to introduce the different ways of interacting
|
||||
with Nvim through Lua (the "API"). This API consists of three different
|
||||
layers:
|
||||
|
||||
1. The "Vim API" inherited from Vim: |Ex-commands| and |vimscript-functions|
|
||||
as well as |user-function|s in Vimscript. These are accessed through
|
||||
|vim.cmd()| and |vim.fn| respectively, which are discussed under
|
||||
|lua-guide-vimscript| below.
|
||||
1. The "Vim API" inherited from Vim: |Ex-commands| and |builtin-functions| as
|
||||
well as |user-function|s in Vimscript. These are accessed through |vim.cmd()|
|
||||
and |vim.fn| respectively, which are discussed under |lua-guide-vimscript|
|
||||
below.
|
||||
|
||||
2. The "Nvim API" written in C for use in remote plugins and GUIs; see |api|.
|
||||
These functions are accessed through |vim.api|.
|
||||
These functions are accessed through |vim.api|.
|
||||
|
||||
3. The "Lua API" written in and specifically for Lua. These are any other
|
||||
functions accessible through `vim.*` not mentioned already; see
|
||||
|lua-stdlib|.
|
||||
functions accessible through `vim.*` not mentioned already; see |lua-stdlib|.
|
||||
|
||||
This distinction is important, as API functions inherit behavior from their
|
||||
original layer: For example, Nvim API functions always need all arguments to
|
||||
@@ -121,6 +121,7 @@ Let's assume you have the following directory structure:
|
||||
|-- syntax/
|
||||
|-- init.vim
|
||||
<
|
||||
|
||||
Then the following Lua code will load `myluamodule.lua`:
|
||||
>lua
|
||||
require("myluamodule")
|
||||
@@ -133,6 +134,7 @@ Similarly, loading `other_modules/anothermodule.lua` is done via
|
||||
-- or
|
||||
require('other_modules.anothermodule')
|
||||
<
|
||||
|
||||
Note how "submodules" are just subdirectories; the `.` is equivalent to the
|
||||
path separator `/` (even on Windows).
|
||||
|
||||
@@ -164,7 +166,7 @@ the cache manually first:
|
||||
<
|
||||
------------------------------------------------------------------------------
|
||||
See also:
|
||||
• |lua-module-load|: how `require()` finds modules
|
||||
• |lua-module-load|
|
||||
• |pcall()|
|
||||
|
||||
==============================================================================
|
||||
@@ -223,7 +225,7 @@ Vimscript are automatically converted:
|
||||
|
||||
vim.fn.jobstart('ls', { on_stdout = print_stdout })
|
||||
<
|
||||
This works for both |vimscript-functions| and |user-function|s.
|
||||
This works for both |builtin-functions| and |user-function|s.
|
||||
|
||||
Note that hashes (`#`) are not valid characters for identifiers in Lua, so,
|
||||
e.g., |autoload| functions have to be called with this syntax:
|
||||
@@ -232,9 +234,10 @@ e.g., |autoload| functions have to be called with this syntax:
|
||||
<
|
||||
------------------------------------------------------------------------------
|
||||
See also:
|
||||
• |vimscript-functions|: descriptions of all Vimscript functions
|
||||
• |function-list|: Vimscript functions grouped by topic
|
||||
• |builtin-functions|: alphabetic list of all Vimscript functions
|
||||
• |function-list|: list of all Vimscript functions grouped by topic
|
||||
• |:runtime|: run all Lua scripts matching a pattern in |'runtimepath'|
|
||||
• |package.path|: list of all paths searched by `require()`
|
||||
|
||||
==============================================================================
|
||||
Variables *lua-guide-variables*
|
||||
@@ -527,6 +530,7 @@ Examples:
|
||||
callback = function() print("My Plugin Works!") end,
|
||||
})
|
||||
<
|
||||
|
||||
Nvim will always call a Lua function with a single table containing information
|
||||
about the triggered autocommand. The most useful keys are
|
||||
• `match`: a string that matched the `pattern` (see |<amatch>|)
|
||||
|
@@ -1,313 +0,0 @@
|
||||
*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 manifest or "registration" step.
|
||||
|
||||
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`, or 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)
|
||||
|
||||
vim.keymap.set('v', '<Plug>(SayHello)', function()
|
||||
print('Hello from visual mode')
|
||||
end)
|
||||
<
|
||||
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, { 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*
|
||||
|
||||
While developing a plugin, you can use the |:restart| command to see the
|
||||
result of code changes in your plugin.
|
||||
|
||||
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 discouraged 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|. The
|
||||
help-tags (the right-aligned "search keywords" in the help documents) are
|
||||
regenerated using the |:helptags| command.
|
||||
|
||||
DOCUMENTATION TOOLS
|
||||
|
||||
- panvimdoc https://github.com/kdheepak/panvimdoc
|
||||
|
||||
|
||||
vim:tw=78:ts=8:sw=4:sts=4:et:ft=help:norl:
|
3412
runtime/doc/lua.txt
3412
runtime/doc/lua.txt
File diff suppressed because it is too large
Load Diff
@@ -1654,8 +1654,8 @@ lua_Alloc *lua_Alloc*
|
||||
`NULL` if and only if it cannot fill the request. When `nsize` is not
|
||||
zero and `osize` is zero, the allocator should behave like `malloc`.
|
||||
When `nsize` and `osize` are not zero, the allocator behaves like
|
||||
`realloc`. Lua assumes that the allocator never fails when
|
||||
`osize >= nsize`.
|
||||
`realloc`. Lua assumes that the allocator never fails when `osize >=
|
||||
nsize`.
|
||||
|
||||
Here is a simple implementation for the allocator function. It is used
|
||||
in the auxiliary library by `luaL_newstate` (see
|
||||
@@ -3567,8 +3567,8 @@ collectgarbage({opt} [, {arg}]) *collectgarbage()*
|
||||
`true` if the step finished a collection cycle.
|
||||
`"setpause"` sets {arg} /100 as the new value for the `pause` of
|
||||
the collector (see |lua-gc|).
|
||||
`"setstepmul"` sets {arg} /100 as the new value for the
|
||||
`step multiplier` of the collector (see |lua-gc|).
|
||||
`"setstepmul"` sets {arg} /100 as the new value for the `step
|
||||
multiplier` of the collector (see |lua-gc|).
|
||||
|
||||
dofile({filename}) *dofile()*
|
||||
Opens the named file and executes its contents as a Lua chunk. When
|
||||
@@ -4785,8 +4785,8 @@ debug.sethook([{thread},] {hook}, {mask} [, {count}]) *debug.sethook()*
|
||||
When called without arguments, the `debug.sethook` turns off the hook.
|
||||
|
||||
When the hook is called, its first parameter is a string describing
|
||||
the event that triggered its call: `"call"`, `"return"` (or
|
||||
`"tail return"`), `"line"`, and `"count"`. For line events, the hook also
|
||||
the event that triggered its call: `"call"`, `"return"` (or `"tail
|
||||
return"`), `"line"`, and `"count"`. For line events, the hook also
|
||||
gets the new line number as its second parameter. Inside a hook, you
|
||||
can call `getinfo` with level 2 to get more information about the
|
||||
running function (level 0 is the `getinfo` function, and level 1 is
|
||||
@@ -4885,4 +4885,5 @@ Christian Habermann's CRefVim project
|
||||
Adapted for bundled Nvim documentation; the original plugin can be found at
|
||||
https://www.vim.org/scripts/script.php?script_id=1291
|
||||
|
||||
vim:tw=78:ts=4:ft=help:norl:et
|
||||
------------------------------------------------------------------------------
|
||||
vi:tw=78:ts=4:ft=help:norl:et
|
||||
|
@@ -220,12 +220,6 @@ TTY Modes ~
|
||||
- `TTY_MODE_NORMAL`: "normal"
|
||||
- `TTY_MODE_RAW`: "raw"
|
||||
- `TTY_MODE_IO`: "io"
|
||||
`TTY_MODE_RAW_VT`: "raw_vt"
|
||||
|
||||
FS Modification Times ~
|
||||
|
||||
- `FS_UTIME_NOW`: "now"
|
||||
- `FS_UTIME_OMIT`: "omit"
|
||||
|
||||
==============================================================================
|
||||
ERROR HANDLING *luv-error-handling*
|
||||
@@ -2202,7 +2196,7 @@ uv.pipe_bind2({pipe}, {name}, {flags}) *uv.pipe_bind2()*
|
||||
|
||||
Returns: `0` or `fail`
|
||||
|
||||
Note:
|
||||
*Note*:
|
||||
1. Paths on Unix get truncated to sizeof(sockaddr_un.sun_path)
|
||||
bytes, typically between 92 and 108 bytes.
|
||||
2. New in version 1.46.0.
|
||||
@@ -2235,7 +2229,7 @@ uv.pipe_connect2(pipe, name, [flags], [callback]) *uv.pipe_connect2()*
|
||||
|
||||
Returns: `uv_connect_t userdata` or `fail`
|
||||
|
||||
Note:
|
||||
*Note*:
|
||||
1. Paths on Unix get truncated to sizeof(sockaddr_un.sun_path)
|
||||
bytes, typically between 92 and 108 bytes.
|
||||
2. New in version 1.46.0.
|
||||
@@ -3282,12 +3276,12 @@ uv.fs_fchmod({fd}, {mode} [, {callback}]) *uv.fs_fchmod()*
|
||||
|
||||
Returns (async version): `uv_fs_t userdata`
|
||||
|
||||
uv.fs_utime({path} [, {atime}, {mtime}, {callback}]) *uv.fs_utime()*
|
||||
uv.fs_utime({path}, {atime}, {mtime} [, {callback}]) *uv.fs_utime()*
|
||||
|
||||
Parameters:
|
||||
- `path`: `string`
|
||||
- `atime`: `number` or `string` or `nil`
|
||||
- `mtime`: `number` or `string` or `nil`
|
||||
- `atime`: `number`
|
||||
- `mtime`: `number`
|
||||
- `callback`: `callable` (async version) or `nil` (sync
|
||||
version)
|
||||
- `err`: `nil` or `string`
|
||||
@@ -3295,66 +3289,39 @@ uv.fs_utime({path} [, {atime}, {mtime}, {callback}]) *uv.fs_utime()*
|
||||
|
||||
Equivalent to `utime(2)`.
|
||||
|
||||
See |luv-constants| for supported FS Modification Time
|
||||
constants.
|
||||
|
||||
Passing `"now"` or `uv.constants.FS_UTIME_NOW` as the atime or
|
||||
mtime sets the timestamp to the current time.
|
||||
|
||||
Passing `nil`, `"omit"`, or `uv.constants.FS_UTIME_OMIT` as
|
||||
the atime or mtime leaves the timestamp untouched.
|
||||
|
||||
Returns (sync version): `boolean` or `fail`
|
||||
|
||||
Returns (async version): `uv_fs_t userdata`
|
||||
|
||||
uv.fs_futime({fd} [, {atime}, {mtime}, {callback}]) *uv.fs_futime()*
|
||||
uv.fs_futime({fd}, {atime}, {mtime} [, {callback}]) *uv.fs_futime()*
|
||||
|
||||
Parameters:
|
||||
- `fd`: `integer`
|
||||
- `atime`: `number` or `string` or `nil`
|
||||
- `mtime`: `number` or `string` or `nil`
|
||||
- `atime`: `number`
|
||||
- `mtime`: `number`
|
||||
- `callback`: `callable` (async version) or `nil` (sync
|
||||
version)
|
||||
- `err`: `nil` or `string`
|
||||
- `success`: `boolean` or `nil`
|
||||
|
||||
Equivalent to `futimes(3)`.
|
||||
|
||||
See |luv-constants| for supported FS Modification Time
|
||||
constants.
|
||||
|
||||
Passing `"now"` or `uv.constants.FS_UTIME_NOW` as the atime or
|
||||
mtime sets the timestamp to the current time.
|
||||
|
||||
Passing `nil`, `"omit"`, or `uv.constants.FS_UTIME_OMIT` as
|
||||
the atime or mtime leaves the timestamp untouched.
|
||||
Equivalent to `futime(2)`.
|
||||
|
||||
Returns (sync version): `boolean` or `fail`
|
||||
|
||||
Returns (async version): `uv_fs_t userdata`
|
||||
|
||||
uv.fs_lutime({path} [, {atime}, {mtime}, {callback}]) *uv.fs_lutime()*
|
||||
uv.fs_lutime({path}, {atime}, {mtime} [, {callback}]) *uv.fs_lutime()*
|
||||
|
||||
Parameters:
|
||||
- `path`: `string`
|
||||
- `atime`: `number` or `string` or `nil`
|
||||
- `mtime`: `number` or `string` or `nil`
|
||||
- `atime`: `number`
|
||||
- `mtime`: `number`
|
||||
- `callback`: `callable` (async version) or `nil` (sync
|
||||
version)
|
||||
- `err`: `nil` or `string`
|
||||
- `success`: `boolean` or `nil`
|
||||
|
||||
Equivalent to `lutimes(3)`.
|
||||
|
||||
See |luv-constants| for supported FS Modification Time
|
||||
constants.
|
||||
|
||||
Passing `"now"` or `uv.constants.FS_UTIME_NOW` as the atime or
|
||||
mtime sets the timestamp to the current time.
|
||||
|
||||
Passing `nil`, `"omit"`, or `uv.constants.FS_UTIME_OMIT` as
|
||||
the atime or mtime leaves the timestamp untouched.
|
||||
Equivalent to `lutime(2)`.
|
||||
|
||||
Returns (sync version): `boolean` or `fail`
|
||||
|
||||
@@ -3915,70 +3882,6 @@ uv.sleep({msec}) *uv.sleep()*
|
||||
|
||||
Returns: Nothing.
|
||||
|
||||
uv.new_sem([{value}]) *uv.new_sem()*
|
||||
|
||||
Parameters:
|
||||
- `value`: `integer` or `nil`
|
||||
|
||||
Creates a new semaphore with the specified initial value. A
|
||||
semaphore is safe to share across threads. It represents an
|
||||
unsigned integer value that can incremented and decremented
|
||||
atomically but any attempt to make it negative will "wait"
|
||||
until the value can be decremented by another thread
|
||||
incrementing it.
|
||||
|
||||
The initial value must be a non-negative integer.
|
||||
|
||||
Returns: `luv_sem_t userdata` or `fail`
|
||||
|
||||
Note: A semaphore must be shared between threads, any
|
||||
`uv.sem_wait()` on a single thread that blocks will deadlock.
|
||||
|
||||
uv.sem_post({sem}) *uv.sem_post()*
|
||||
|
||||
> method form `sem:post()`
|
||||
|
||||
Parameters:
|
||||
- `sem`: `luv_sem_t userdata`
|
||||
|
||||
Increments (unlocks) a semaphore, if the semaphore's value
|
||||
consequently becomes greater than zero then another thread
|
||||
blocked in a sem_wait call will be woken and proceed to
|
||||
decrement the semaphore.
|
||||
|
||||
Returns: Nothing.
|
||||
|
||||
uv.sem_wait({sem}) *uv.sem_wait()*
|
||||
|
||||
> method form `sem:wait()`
|
||||
|
||||
Parameters:
|
||||
- `sem`: `luv_sem_t userdata`
|
||||
|
||||
Decrements (locks) a semaphore, if the semaphore's value is
|
||||
greater than zero then the value is decremented and the call
|
||||
returns immediately. If the semaphore's value is zero then the
|
||||
call blocks until the semaphore's value rises above zero or
|
||||
the call is interrupted by a signal.
|
||||
|
||||
Returns: Nothing.
|
||||
|
||||
uv.sem_trywait({sem}) *uv.sem_trywait()*
|
||||
|
||||
> method form `sem:trywait()`
|
||||
|
||||
Parameters:
|
||||
- `sem`: `luv_sem_t userdata`
|
||||
|
||||
The same as `uv.sem_wait()` but returns immediately if the
|
||||
semaphore is not available.
|
||||
|
||||
If the semaphore's value was decremented then `true` is
|
||||
returned, otherwise the semaphore has a value of zero and
|
||||
`false` is returned.
|
||||
|
||||
Returns: `boolean`
|
||||
|
||||
==============================================================================
|
||||
MISCELLANEOUS UTILITIES *luv-miscellaneous-utilities*
|
||||
|
||||
|
@@ -1390,13 +1390,13 @@ completion can be enabled:
|
||||
-complete=compiler compilers
|
||||
-complete=diff_buffer diff buffer names
|
||||
-complete=dir directory names
|
||||
-complete=dir_in_path directory names in 'cdpath'
|
||||
-complete=dir_in_path directory names in |'cdpath'|
|
||||
-complete=environment environment variable names
|
||||
-complete=event autocommand events
|
||||
-complete=expression Vim expression
|
||||
-complete=file file and directory names
|
||||
-complete=file_in_path file and directory names in 'path'
|
||||
-complete=filetype filetype names 'filetype'
|
||||
-complete=file_in_path file and directory names in |'path'|
|
||||
-complete=filetype filetype names |'filetype'|
|
||||
-complete=function function name
|
||||
-complete=help help subjects
|
||||
-complete=highlight highlight groups
|
||||
@@ -1410,14 +1410,13 @@ completion can be enabled:
|
||||
-complete=messages |:messages| suboptions
|
||||
-complete=option options
|
||||
-complete=packadd optional package |pack-add| names
|
||||
-complete=retab |:retab| suboptions
|
||||
-complete=runtime file and directory names in 'runtimepath'
|
||||
-complete=runtime file and directory names in |'runtimepath'|
|
||||
-complete=scriptnames sourced script names
|
||||
-complete=shellcmd Shell command
|
||||
-complete=shellcmdline First is a shell command and subsequent ones
|
||||
are filenames. The same behavior as |:!cmd|
|
||||
-complete=sign |:sign| suboptions
|
||||
-complete=syntax syntax file names 'syntax'
|
||||
-complete=syntax syntax file names |'syntax'|
|
||||
-complete=syntime |:syntime| suboptions
|
||||
-complete=tag tags
|
||||
-complete=tag_listfiles tags, file names are shown when CTRL-D is hit
|
||||
|
@@ -476,7 +476,7 @@ and what the keymaps are to get those characters:
|
||||
|
||||
glyph encoding keymap ~
|
||||
Char UTF-8 cp1255 hebrew hebrewp name ~
|
||||
א 0x5d0 0xe0 t a alef
|
||||
א 0x5d0 0xe0 t a ´alef
|
||||
ב 0x5d1 0xe1 c b bet
|
||||
ג 0x5d2 0xe2 d g gimel
|
||||
ד 0x5d3 0xe3 s d dalet
|
||||
@@ -494,7 +494,7 @@ Char UTF-8 cp1255 hebrew hebrewp name ~
|
||||
ן 0x5df 0xef i N nun sofit
|
||||
נ 0x5e0 0xf0 b n nun
|
||||
ס 0x5e1 0xf1 x s samech
|
||||
ע 0x5e2 0xf2 g u ayin
|
||||
ע 0x5e2 0xf2 g u `ayin
|
||||
ף 0x5e3 0xf3 ; P pe sofit
|
||||
פ 0x5e4 0xf4 p p pe
|
||||
ץ 0x5e5 0xf5 . X tsadi sofit
|
||||
@@ -556,8 +556,8 @@ Char UTF-8 hebrew name
|
||||
ב֯ 0x5af CC masora circle
|
||||
|
||||
Combining forms:
|
||||
ﬠ 0xfb20 X` Alternative ayin
|
||||
ﬡ 0xfb21 X' Alternative alef
|
||||
ﬠ 0xfb20 X` Alternative `ayin
|
||||
ﬡ 0xfb21 X' Alternative ´alef
|
||||
ﬢ 0xfb22 X-d Alternative dalet
|
||||
ﬣ 0xfb23 X-h Alternative he
|
||||
ﬤ 0xfb24 X-k Alternative kaf
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user