aboutsummaryrefslogtreecommitdiff
path: root/bootstrap-win/neovim.ps1
diff options
context:
space:
mode:
authorThomas Schmucker <ts@its1.de>2026-08-05 15:35:52 +0200
committerThomas Schmucker <ts@its1.de>2026-08-05 15:35:52 +0200
commit4da2c55e7c97fb47a6656416c9d12543a830c8b1 (patch)
tree9722b13ebd84a921fc1607d532ab1f57b0d35c01 /bootstrap-win/neovim.ps1
parentbcabbcad7424b40ff178c3a27917c504bf1923e0 (diff)
downloaddotfiles-4da2c55e7c97fb47a6656416c9d12543a830c8b1.tar.gz
dotfiles-4da2c55e7c97fb47a6656416c9d12543a830c8b1.tar.bz2
dotfiles-4da2c55e7c97fb47a6656416c9d12543a830c8b1.zip
npmrc: Einstellungen für Pre- und Post-Skripte bei npm-Paketen angepasst
Diffstat (limited to 'bootstrap-win/neovim.ps1')
-rw-r--r--bootstrap-win/neovim.ps1456
1 files changed, 224 insertions, 232 deletions
diff --git a/bootstrap-win/neovim.ps1 b/bootstrap-win/neovim.ps1
index aa17dcf..7779107 100644
--- a/bootstrap-win/neovim.ps1
+++ b/bootstrap-win/neovim.ps1
@@ -1,232 +1,224 @@
1#Requires -Version 5.1 1#Requires -Version 5.1
2<# 2<#
3 Windows-natives Pendant zu bootstrap/neovim.sh - nutzt winget/npm statt 3 Windows-natives Pendant zu bootstrap/neovim.sh - nutzt winget/npm statt
4 brew/pkg, daher eigenstaendiges Skript ohne Git-Bash-/WSL-Abhaengigkeit. 4 brew/pkg, daher eigenstaendiges Skript ohne Git-Bash-/WSL-Abhaengigkeit.
5 5
6 Aufruf (keine Admin-Rechte noetig): 6 Aufruf (keine Admin-Rechte noetig):
7 .\bootstrap-win\neovim.ps1 7 .\bootstrap-win\neovim.ps1
8 8
9 yamlfmt, gawk und xmllint sind bewusst nicht enthalten (siehe 9 yamlfmt, gawk und xmllint sind bewusst nicht enthalten (siehe
10 neovim-windows-setup.md). Fehlgeschlagene Installationen werden als 10 neovim-windows-setup.md). Fehlgeschlagene Installationen werden als
11 Warnung gemeldet, das Skript bricht nicht ab. 11 Warnung gemeldet, das Skript bricht nicht ab.
12#> 12#>
13 13
14$ErrorActionPreference = "Stop" 14$ErrorActionPreference = "Stop"
15$script:Failures = @() 15$script:Failures = @()
16 16
17function Write-Ok($msg) { 17function Write-Ok($msg) {
18 Write-Host "OK $msg" -ForegroundColor Green 18 Write-Host "OK $msg" -ForegroundColor Green
19} 19}
20 20
21function Write-Step($msg) { 21function Write-Step($msg) {
22 Write-Host "==> $msg" -ForegroundColor Cyan 22 Write-Host "==> $msg" -ForegroundColor Cyan
23} 23}
24 24
25function Write-Skip($msg) { 25function Write-Skip($msg) {
26 Write-Host "- $msg bereits vorhanden" -ForegroundColor DarkGray 26 Write-Host "- $msg bereits vorhanden" -ForegroundColor DarkGray
27} 27}
28 28
29function Write-Warn($msg) { 29function Write-Warn($msg) {
30 Write-Host "! $msg" -ForegroundColor Yellow 30 Write-Host "! $msg" -ForegroundColor Yellow
31 $script:Failures += $msg 31 $script:Failures += $msg
32} 32}
33 33
34function Test-CommandExists([string]$Name) { 34function Test-CommandExists([string]$Name) {
35 return [bool](Get-Command $Name -ErrorAction SilentlyContinue) 35 return [bool](Get-Command $Name -ErrorAction SilentlyContinue)
36} 36}
37 37
38function Find-BinaryDirectory([string]$Binary) { 38function Find-BinaryDirectory([string]$Binary) {
39 # Deckt den Fall ab, dass winget (v.a. --silent) korrekt installiert, 39 # Deckt den Fall ab, dass winget (v.a. --silent) korrekt installiert,
40 # aber die PATH-Registrierung ausgelassen hat (beobachtet bei LLVM.LLVM). 40 # aber die PATH-Registrierung ausgelassen hat (beobachtet bei LLVM.LLVM).
41 $searchRoots = @( 41 $searchRoots = @(
42 $env:ProgramFiles, 42 $env:ProgramFiles,
43 ${env:ProgramFiles(x86)}, 43 ${env:ProgramFiles(x86)},
44 (Join-Path $env:LOCALAPPDATA "Programs") 44 (Join-Path $env:LOCALAPPDATA "Programs")
45 ) | Where-Object { $_ -and (Test-Path $_) } 45 ) | Where-Object { $_ -and (Test-Path $_) }
46 46
47 foreach ($root in $searchRoots) { 47 foreach ($root in $searchRoots) {
48 $found = Get-ChildItem -Path $root -Recurse -Depth 4 -Filter "$Binary.exe" -File -ErrorAction SilentlyContinue | Select-Object -First 1 48 $found = Get-ChildItem -Path $root -Recurse -Depth 4 -Filter "$Binary.exe" -File -ErrorAction SilentlyContinue | Select-Object -First 1
49 if ($found) { 49 if ($found) {
50 return $found.DirectoryName 50 return $found.DirectoryName
51 } 51 }
52 } 52 }
53 53
54 return $null 54 return $null
55} 55}
56 56
57function Add-ToUserPath([string]$Dir) { 57function Add-ToUserPath([string]$Dir) {
58 $userPath = [Environment]::GetEnvironmentVariable("PATH", "User") 58 $userPath = [Environment]::GetEnvironmentVariable("PATH", "User")
59 $entries = $userPath -split ";" 59 $entries = $userPath -split ";"
60 60
61 if ($entries -contains $Dir) { 61 if ($entries -contains $Dir) {
62 return $false 62 return $false
63 } 63 }
64 64
65 [Environment]::SetEnvironmentVariable("PATH", "$userPath;$Dir", "User") 65 [Environment]::SetEnvironmentVariable("PATH", "$userPath;$Dir", "User")
66 $env:PATH = "$env:PATH;$Dir" 66 $env:PATH = "$env:PATH;$Dir"
67 return $true 67 return $true
68} 68}
69 69
70function Install-WingetPackage([string]$Binary, [string]$Id) { 70function Install-WingetPackage([string]$Binary, [string]$Id) {
71 if (Test-CommandExists $Binary) { 71 if (Test-CommandExists $Binary) {
72 Write-Skip $Binary 72 Write-Skip $Binary
73 return 73 return
74 } 74 }
75 75
76 Write-Step "winget install $Id" 76 Write-Step "winget install $Id"
77 $output = winget install --id $Id -e --source winget --accept-package-agreements --accept-source-agreements --silent 2>&1 77 $output = winget install --id $Id -e --source winget --accept-package-agreements --accept-source-agreements --silent 2>&1
78 78
79 if ($LASTEXITCODE -ne 0) { 79 if ($LASTEXITCODE -ne 0) {
80 $text = $output -join " " 80 $text = $output -join " "
81 $lastLine = ($output | Select-Object -Last 3) -join " / " 81 $lastLine = ($output | Select-Object -Last 3) -join " / "
82 82
83 if ($text -match "bereits ein vorhandenes Paket|already installed|No applicable update") { 83 if ($text -match "bereits ein vorhandenes Paket|already installed|No applicable update") {
84 # Installiert, aber nicht im PATH - Binary suchen und PATH ergaenzen. 84 # Installiert, aber nicht im PATH - Binary suchen und PATH ergaenzen.
85 $dir = Find-BinaryDirectory $Binary 85 $dir = Find-BinaryDirectory $Binary
86 86
87 if ($dir) { 87 if ($dir) {
88 Add-ToUserPath $dir | Out-Null 88 Add-ToUserPath $dir | Out-Null
89 if (Test-CommandExists $Binary) { 89 if (Test-CommandExists $Binary) {
90 Write-Ok "$Id ('$Binary' in $dir gefunden, User-PATH ergaenzt)" 90 Write-Ok "$Id ('$Binary' in $dir gefunden, User-PATH ergaenzt)"
91 } else { 91 } else {
92 Write-Warn "${Id}: $dir zum User-PATH hinzugefuegt, aber '$Binary' laesst sich immer noch nicht ausfuehren - manuell pruefen." 92 Write-Warn "${Id}: $dir zum User-PATH hinzugefuegt, aber '$Binary' laesst sich immer noch nicht ausfuehren - manuell pruefen."
93 } 93 }
94 } else { 94 } else {
95 Write-Warn "$Id ist laut winget bereits installiert, aber '$Binary' wurde nicht gefunden und konnte auch nicht automatisch lokalisiert werden (durchsucht: Program Files, Program Files (x86), $env:LOCALAPPDATA\Programs). Installationsordner manuell suchen und zum PATH hinzufuegen." 95 Write-Warn "$Id ist laut winget bereits installiert, aber '$Binary' wurde nicht gefunden und konnte auch nicht automatisch lokalisiert werden (durchsucht: Program Files, Program Files (x86), $env:LOCALAPPDATA\Programs). Installationsordner manuell suchen und zum PATH hinzufuegen."
96 } 96 }
97 } else { 97 } else {
98 Write-Warn "winget install $Id fehlgeschlagen (Binary '$Binary' nicht gefunden): $lastLine -- Pruefen mit: winget search $Id" 98 Write-Warn "winget install $Id fehlgeschlagen (Binary '$Binary' nicht gefunden): $lastLine -- Pruefen mit: winget search $Id"
99 } 99 }
100 return 100 return
101 } 101 }
102 102
103 Write-Ok $Id 103 Write-Ok $Id
104} 104}
105 105
106function Test-BinaryRuns([string]$Binary, [string[]]$VerifyArgs) { 106function Test-BinaryRuns([string]$Binary, [string[]]$VerifyArgs) {
107 # Einige npm-Pakete (z.B. tree-sitter-cli) installieren nur einen JS-Shim 107 # Einige npm-Pakete (z.B. tree-sitter-cli) installieren nur einen JS-Shim
108 # und laden die eigentliche native Binary per Post-Install-Skript separat 108 # und laden die eigentliche native Binary per Post-Install-Skript separat
109 # von GitHub herunter. Schlaegt dieser Download fehl (Proxy, ignore-scripts, 109 # von GitHub herunter. Schlaegt dieser Download fehl (Proxy, npm
110 # Antivirus-Quarantaene), landet der Shim trotzdem im PATH und 110 # allow-scripts-Policy, Antivirus-Quarantaene), landet der Shim trotzdem
111 # Test-CommandExists meldet faelschlich Erfolg. Deshalb hier tatsaechlich 111 # im PATH und Test-CommandExists meldet faelschlich Erfolg. Deshalb hier
112 # ausfuehren statt nur pruefen, ob der Befehlsname aufloesbar ist. 112 # tatsaechlich ausfuehren statt nur pruefen, ob der Befehlsname
113 try { 113 # aufloesbar ist.
114 & $Binary @VerifyArgs *> $null 114 try {
115 return $LASTEXITCODE -eq 0 115 & $Binary @VerifyArgs *> $null
116 } catch { 116 return $LASTEXITCODE -eq 0
117 return $false 117 } catch {
118 } 118 return $false
119} 119 }
120 120}
121function Install-NpmPackage([string]$Binary, [string]$Package, [string[]]$VerifyArgs = $null, [switch]$AllowScripts) { 121
122 if (Test-CommandExists $Binary) { 122function Install-NpmPackage([string]$Binary, [string]$Package, [string[]]$VerifyArgs = $null) {
123 if ($VerifyArgs -and -not (Test-BinaryRuns $Binary $VerifyArgs)) { 123 if (Test-CommandExists $Binary) {
124 Write-Warn "'$Binary' ist im PATH, laesst sich aber nicht ausfuehren - vermutlich hat der Post-Install-Download von '$Package' nicht geklappt (Proxy/ignore-scripts pruefen). 'npm uninstall -g $Package' und neu installieren." 124 if ($VerifyArgs -and -not (Test-BinaryRuns $Binary $VerifyArgs)) {
125 } else { 125 Write-Warn "'$Binary' ist im PATH, laesst sich aber nicht ausfuehren - vermutlich hat der Post-Install-Download von '$Package' nicht geklappt (Proxy/npm allow-scripts-Policy pruefen: 'npm config get allow-scripts'). 'npm uninstall -g $Package' und neu installieren."
126 Write-Skip $Binary 126 } else {
127 } 127 Write-Skip $Binary
128 return 128 }
129 } 129 return
130 130 }
131 if (-not (Test-CommandExists "npm")) { 131
132 Write-Warn "npm wurde nicht gefunden - kann '$Package' nicht installieren." 132 if (-not (Test-CommandExists "npm")) {
133 return 133 Write-Warn "npm wurde nicht gefunden - kann '$Package' nicht installieren."
134 } 134 return
135 135 }
136 # -AllowScripts: fuer Pakete wie tree-sitter-cli, deren Post-Install-Skript 136
137 # die eigentliche native Binary von GitHub nachlaedt. Die globale 137 Write-Step "npm install -g $Package"
138 # ignore-scripts=true in der npmrc wuerde das verhindern; --no-ignore-scripts 138 npm install -g $Package | Out-Null
139 # hebt das nur fuer diesen einen Aufruf auf, ohne die npmrc anzufassen. 139
140 $npmArgs = @("install", "-g", $Package) 140 if ($LASTEXITCODE -ne 0) {
141 if ($AllowScripts) { 141 Write-Warn "npm install -g $Package fehlgeschlagen."
142 $npmArgs += "--no-ignore-scripts" 142 return
143 } 143 }
144 144
145 Write-Step "npm $($npmArgs -join ' ')" 145 if ($VerifyArgs -and -not (Test-BinaryRuns $Binary $VerifyArgs)) {
146 npm @npmArgs | Out-Null 146 Write-Warn "npm install -g $Package war erfolgreich, aber '$Binary' laesst sich nicht ausfuehren - vermutlich hat der Post-Install-Download der nativen Binary nicht geklappt (Proxy/npm allow-scripts-Policy pruefen: 'npm config get allow-scripts')."
147 147 return
148 if ($LASTEXITCODE -ne 0) { 148 }
149 Write-Warn "npm install -g $Package fehlgeschlagen." 149
150 return 150 Write-Ok $Package
151 } 151}
152 152
153 if ($VerifyArgs -and -not (Test-BinaryRuns $Binary $VerifyArgs)) { 153function Test-Prerequisites {
154 Write-Warn "npm install -g $Package war erfolgreich, aber '$Binary' laesst sich nicht ausfuehren - vermutlich hat der Post-Install-Download der nativen Binary nicht geklappt (Proxy/ignore-scripts pruefen)." 154 if (-not (Test-CommandExists "winget")) {
155 return 155 Write-Host "Fehler: winget wurde nicht gefunden. 'App Installer' aus dem Microsoft Store installieren." -ForegroundColor Red
156 } 156 exit 1
157 157 }
158 Write-Ok $Package 158}
159} 159
160 160function Update-SessionPath {
161function Test-Prerequisites { 161 # Registry-PATH-Aenderungen durch winget/npm wirken erst nach diesem Refresh.
162 if (-not (Test-CommandExists "winget")) { 162 $machine = [Environment]::GetEnvironmentVariable("PATH", "Machine")
163 Write-Host "Fehler: winget wurde nicht gefunden. 'App Installer' aus dem Microsoft Store installieren." -ForegroundColor Red 163 $user = [Environment]::GetEnvironmentVariable("PATH", "User")
164 exit 1 164 $env:PATH = "$machine;$user"
165 } 165}
166} 166
167 167function Install-Prerequisites {
168function Update-SessionPath { 168 Install-WingetPackage -Binary "git" -Id "Git.Git"
169 # Registry-PATH-Aenderungen durch winget/npm wirken erst nach diesem Refresh. 169 Install-WingetPackage -Binary "node" -Id "OpenJS.NodeJS.LTS"
170 $machine = [Environment]::GetEnvironmentVariable("PATH", "Machine") 170 Update-SessionPath
171 $user = [Environment]::GetEnvironmentVariable("PATH", "User") 171}
172 $env:PATH = "$machine;$user" 172
173} 173function Install-Formatters {
174 174 Install-WingetPackage -Binary "jq" -Id "jqlang.jq"
175function Install-Prerequisites { 175 Install-NpmPackage -Binary "prettier" -Package "prettier"
176 Install-WingetPackage -Binary "git" -Id "Git.Git" 176 Install-WingetPackage -Binary "ruff" -Id "astral-sh.ruff"
177 Install-WingetPackage -Binary "node" -Id "OpenJS.NodeJS.LTS" 177 Install-WingetPackage -Binary "shfmt" -Id "mvdan.shfmt"
178 Update-SessionPath 178 Install-WingetPackage -Binary "stylua" -Id "JohnnyMorganz.StyLua"
179} 179
180 180 # yamlfmt, gawk, xmllint: kein winget-Paket gefunden, siehe neovim-windows-setup.md.
181function Install-Formatters { 181}
182 Install-WingetPackage -Binary "jq" -Id "jqlang.jq" 182
183 Install-NpmPackage -Binary "prettier" -Package "prettier" 183function Install-Tools {
184 Install-WingetPackage -Binary "ruff" -Id "astral-sh.ruff" 184 Install-WingetPackage -Binary "rg" -Id "BurntSushi.ripgrep.MSVC"
185 Install-WingetPackage -Binary "shfmt" -Id "mvdan.shfmt" 185 Install-WingetPackage -Binary "fd" -Id "sharkdp.fd"
186 Install-WingetPackage -Binary "stylua" -Id "JohnnyMorganz.StyLua" 186 Install-NpmPackage -Binary "tree-sitter" -Package "tree-sitter-cli" -VerifyArgs @("--version")
187 187
188 # yamlfmt, gawk, xmllint: kein winget-Paket gefunden, siehe neovim-windows-setup.md. 188 # MSVC (cl.exe) ist bereits vorhanden, kein winget-Paket noetig - Neovim
189} 189 # dafuer aber aus einer "Developer PowerShell for VS" starten.
190 190 Install-WingetPackage -Binary "make" -Id "ezwinports.make"
191function Install-Tools { 191}
192 Install-WingetPackage -Binary "rg" -Id "BurntSushi.ripgrep.MSVC" 192
193 Install-WingetPackage -Binary "fd" -Id "sharkdp.fd" 193function Install-Lsp {
194 Install-NpmPackage -Binary "tree-sitter" -Package "tree-sitter-cli" -VerifyArgs @("--version") -AllowScripts 194 Install-NpmPackage -Binary "basedpyright-langserver" -Package "basedpyright"
195 195 Install-NpmPackage -Binary "bash-language-server" -Package "bash-language-server"
196 # MSVC (cl.exe) ist bereits vorhanden, kein winget-Paket noetig - Neovim 196 Install-WingetPackage -Binary "clangd" -Id "LLVM.LLVM"
197 # dafuer aber aus einer "Developer PowerShell for VS" starten. 197 Install-WingetPackage -Binary "shellcheck" -Id "koalaman.shellcheck"
198 Install-WingetPackage -Binary "make" -Id "ezwinports.make" 198 Install-NpmPackage -Binary "vscode-html-language-server" -Package "vscode-langservers-extracted"
199} 199 Install-NpmPackage -Binary "vscode-json-language-server" -Package "vscode-langservers-extracted"
200 200 Install-WingetPackage -Binary "lua-language-server" -Id "LuaLS.lua-language-server"
201function Install-Lsp { 201 Install-NpmPackage -Binary "prisma-language-server" -Package "@prisma/language-server"
202 Install-NpmPackage -Binary "basedpyright-langserver" -Package "basedpyright" 202 Install-NpmPackage -Binary "vtsls" -Package "@vtsls/language-server"
203 Install-NpmPackage -Binary "bash-language-server" -Package "bash-language-server" 203}
204 Install-WingetPackage -Binary "clangd" -Id "LLVM.LLVM" 204
205 Install-WingetPackage -Binary "shellcheck" -Id "koalaman.shellcheck" 205function Main {
206 Install-NpmPackage -Binary "vscode-html-language-server" -Package "vscode-langservers-extracted" 206 Test-Prerequisites
207 Install-NpmPackage -Binary "vscode-json-language-server" -Package "vscode-langservers-extracted" 207
208 Install-WingetPackage -Binary "lua-language-server" -Id "LuaLS.lua-language-server" 208 Install-Prerequisites
209 Install-NpmPackage -Binary "prisma-language-server" -Package "@prisma/language-server" 209 Install-Formatters
210 Install-NpmPackage -Binary "vtsls" -Package "@vtsls/language-server" 210 Install-Tools
211} 211 Install-Lsp
212 212
213function Main { 213 Write-Host ""
214 Test-Prerequisites 214 if ($script:Failures.Count -eq 0) {
215 215 Write-Host "Neovim-Bootstrap abgeschlossen." -ForegroundColor Green
216 Install-Prerequisites 216 } else {
217 Install-Formatters 217 Write-Host "Neovim-Bootstrap abgeschlossen, mit $($script:Failures.Count) Warnung(en):" -ForegroundColor Yellow
218 Install-Tools 218 foreach ($f in $script:Failures) {
219 Install-Lsp 219 Write-Host " - $f" -ForegroundColor Yellow
220 220 }
221 Write-Host "" 221 }
222 if ($script:Failures.Count -eq 0) { 222}
223 Write-Host "Neovim-Bootstrap abgeschlossen." -ForegroundColor Green 223
224 } else { 224Main
225 Write-Host "Neovim-Bootstrap abgeschlossen, mit $($script:Failures.Count) Warnung(en):" -ForegroundColor Yellow
226 foreach ($f in $script:Failures) {
227 Write-Host " - $f" -ForegroundColor Yellow
228 }
229 }
230}
231
232Main