diff options
| -rw-r--r-- | bootstrap-win/neovim-dict.ps1 | 58 | ||||
| -rw-r--r-- | bootstrap-win/neovim.ps1 | 199 | ||||
| -rw-r--r-- | install-win.ps1 | 113 | ||||
| -rw-r--r-- | neovim-windows-setup.md | 113 | ||||
| -rw-r--r-- | nvim/lua/config/usercmds.lua | 12 | ||||
| -rw-r--r-- | readme.md | 16 | ||||
| -rw-r--r-- | windows/bin/gmake.cmd | 11 | ||||
| -rw-r--r-- | windows/bin/nvim-update.cmd | 2 |
8 files changed, 521 insertions, 3 deletions
diff --git a/bootstrap-win/neovim-dict.ps1 b/bootstrap-win/neovim-dict.ps1 new file mode 100644 index 0000000..5aeb117 --- /dev/null +++ b/bootstrap-win/neovim-dict.ps1 | |||
| @@ -0,0 +1,58 @@ | |||
| 1 | #Requires -Version 5.1 | ||
| 2 | <# | ||
| 3 | Windows-natives Pendant zu bootstrap/neovim-dict.sh. | ||
| 4 | Laedt die deutschen Rechtschreib-Woerterbuecher fuer Neovim herunter. | ||
| 5 | |||
| 6 | Aufruf: | ||
| 7 | .\bootstrap-win\neovim-dict.ps1 | ||
| 8 | #> | ||
| 9 | |||
| 10 | $ErrorActionPreference = "Stop" | ||
| 11 | |||
| 12 | function Write-Ok($msg) { | ||
| 13 | Write-Host "OK $msg" -ForegroundColor Green | ||
| 14 | } | ||
| 15 | |||
| 16 | function Write-Step($msg) { | ||
| 17 | Write-Host "==> $msg" -ForegroundColor Cyan | ||
| 18 | } | ||
| 19 | |||
| 20 | function Write-SkipMsg($msg) { | ||
| 21 | Write-Host "- $msg bereits vorhanden" -ForegroundColor DarkGray | ||
| 22 | } | ||
| 23 | |||
| 24 | $SpellDir = Join-Path $env:LOCALAPPDATA "nvim-data\site\spell" | ||
| 25 | |||
| 26 | $Urls = @( | ||
| 27 | "https://ftp.nluug.nl/pub/vim/runtime/spell/de.utf-8.spl", | ||
| 28 | "https://ftp.nluug.nl/pub/vim/runtime/spell/de.utf-8.sug" | ||
| 29 | ) | ||
| 30 | |||
| 31 | function Get-SpellFile([string]$Url) { | ||
| 32 | $fileName = Split-Path -Leaf $Url | ||
| 33 | $dest = Join-Path $SpellDir $fileName | ||
| 34 | |||
| 35 | if (Test-Path $dest) { | ||
| 36 | Write-SkipMsg $fileName | ||
| 37 | return | ||
| 38 | } | ||
| 39 | |||
| 40 | Write-Step "Lade $fileName herunter" | ||
| 41 | Invoke-WebRequest -Uri $Url -OutFile $dest | ||
| 42 | Write-Ok $fileName | ||
| 43 | } | ||
| 44 | |||
| 45 | function Main { | ||
| 46 | if (-not (Test-Path $SpellDir)) { | ||
| 47 | New-Item -ItemType Directory -Path $SpellDir -Force | Out-Null | ||
| 48 | } | ||
| 49 | |||
| 50 | foreach ($url in $Urls) { | ||
| 51 | Get-SpellFile $url | ||
| 52 | } | ||
| 53 | |||
| 54 | Write-Host "" | ||
| 55 | Write-Host "Woerterbuecher fuer Neovim installiert!" -ForegroundColor Green | ||
| 56 | } | ||
| 57 | |||
| 58 | Main | ||
diff --git a/bootstrap-win/neovim.ps1 b/bootstrap-win/neovim.ps1 new file mode 100644 index 0000000..32e2db7 --- /dev/null +++ b/bootstrap-win/neovim.ps1 | |||
| @@ -0,0 +1,199 @@ | |||
| 1 | #Requires -Version 5.1 | ||
| 2 | <# | ||
| 3 | Windows-natives Pendant zu bootstrap/neovim.sh - nutzt winget/npm statt | ||
| 4 | brew/pkg, daher eigenstaendiges Skript ohne Git-Bash-/WSL-Abhaengigkeit. | ||
| 5 | |||
| 6 | Aufruf (keine Admin-Rechte noetig): | ||
| 7 | .\bootstrap-win\neovim.ps1 | ||
| 8 | |||
| 9 | yamlfmt, gawk und xmllint sind bewusst nicht enthalten (siehe | ||
| 10 | neovim-windows-setup.md). Fehlgeschlagene Installationen werden als | ||
| 11 | Warnung gemeldet, das Skript bricht nicht ab. | ||
| 12 | #> | ||
| 13 | |||
| 14 | $ErrorActionPreference = "Stop" | ||
| 15 | $script:Failures = @() | ||
| 16 | |||
| 17 | function Write-Ok($msg) { | ||
| 18 | Write-Host "OK $msg" -ForegroundColor Green | ||
| 19 | } | ||
| 20 | |||
| 21 | function Write-Step($msg) { | ||
| 22 | Write-Host "==> $msg" -ForegroundColor Cyan | ||
| 23 | } | ||
| 24 | |||
| 25 | function Write-Skip($msg) { | ||
| 26 | Write-Host "- $msg bereits vorhanden" -ForegroundColor DarkGray | ||
| 27 | } | ||
| 28 | |||
| 29 | function Write-Warn($msg) { | ||
| 30 | Write-Host "! $msg" -ForegroundColor Yellow | ||
| 31 | $script:Failures += $msg | ||
| 32 | } | ||
| 33 | |||
| 34 | function Test-CommandExists([string]$Name) { | ||
| 35 | return [bool](Get-Command $Name -ErrorAction SilentlyContinue) | ||
| 36 | } | ||
| 37 | |||
| 38 | function Find-BinaryDirectory([string]$Binary) { | ||
| 39 | # Deckt den Fall ab, dass winget (v.a. --silent) korrekt installiert, | ||
| 40 | # aber die PATH-Registrierung ausgelassen hat (beobachtet bei LLVM.LLVM). | ||
| 41 | $searchRoots = @( | ||
| 42 | $env:ProgramFiles, | ||
| 43 | ${env:ProgramFiles(x86)}, | ||
| 44 | (Join-Path $env:LOCALAPPDATA "Programs") | ||
| 45 | ) | Where-Object { $_ -and (Test-Path $_) } | ||
| 46 | |||
| 47 | foreach ($root in $searchRoots) { | ||
| 48 | $found = Get-ChildItem -Path $root -Recurse -Depth 4 -Filter "$Binary.exe" -File -ErrorAction SilentlyContinue | Select-Object -First 1 | ||
| 49 | if ($found) { | ||
| 50 | return $found.DirectoryName | ||
| 51 | } | ||
| 52 | } | ||
| 53 | |||
| 54 | return $null | ||
| 55 | } | ||
| 56 | |||
| 57 | function Add-ToUserPath([string]$Dir) { | ||
| 58 | $userPath = [Environment]::GetEnvironmentVariable("PATH", "User") | ||
| 59 | $entries = $userPath -split ";" | ||
| 60 | |||
| 61 | if ($entries -contains $Dir) { | ||
| 62 | return $false | ||
| 63 | } | ||
| 64 | |||
| 65 | [Environment]::SetEnvironmentVariable("PATH", "$userPath;$Dir", "User") | ||
| 66 | $env:PATH = "$env:PATH;$Dir" | ||
| 67 | return $true | ||
| 68 | } | ||
| 69 | |||
| 70 | function Install-WingetPackage([string]$Binary, [string]$Id) { | ||
| 71 | if (Test-CommandExists $Binary) { | ||
| 72 | Write-Skip $Binary | ||
| 73 | return | ||
| 74 | } | ||
| 75 | |||
| 76 | Write-Step "winget install $Id" | ||
| 77 | $output = winget install --id $Id -e --source winget --accept-package-agreements --accept-source-agreements --silent 2>&1 | ||
| 78 | |||
| 79 | if ($LASTEXITCODE -ne 0) { | ||
| 80 | $text = $output -join " " | ||
| 81 | $lastLine = ($output | Select-Object -Last 3) -join " / " | ||
| 82 | |||
| 83 | if ($text -match "bereits ein vorhandenes Paket|already installed|No applicable update") { | ||
| 84 | # Installiert, aber nicht im PATH - Binary suchen und PATH ergaenzen. | ||
| 85 | $dir = Find-BinaryDirectory $Binary | ||
| 86 | |||
| 87 | if ($dir) { | ||
| 88 | Add-ToUserPath $dir | Out-Null | ||
| 89 | if (Test-CommandExists $Binary) { | ||
| 90 | Write-Ok "$Id ('$Binary' in $dir gefunden, User-PATH ergaenzt)" | ||
| 91 | } else { | ||
| 92 | Write-Warn "${Id}: $dir zum User-PATH hinzugefuegt, aber '$Binary' laesst sich immer noch nicht ausfuehren - manuell pruefen." | ||
| 93 | } | ||
| 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." | ||
| 96 | } | ||
| 97 | } else { | ||
| 98 | Write-Warn "winget install $Id fehlgeschlagen (Binary '$Binary' nicht gefunden): $lastLine -- Pruefen mit: winget search $Id" | ||
| 99 | } | ||
| 100 | return | ||
| 101 | } | ||
| 102 | |||
| 103 | Write-Ok $Id | ||
| 104 | } | ||
| 105 | |||
| 106 | function Install-NpmPackage([string]$Binary, [string]$Package) { | ||
| 107 | if (Test-CommandExists $Binary) { | ||
| 108 | Write-Skip $Binary | ||
| 109 | return | ||
| 110 | } | ||
| 111 | |||
| 112 | if (-not (Test-CommandExists "npm")) { | ||
| 113 | Write-Warn "npm wurde nicht gefunden - kann '$Package' nicht installieren." | ||
| 114 | return | ||
| 115 | } | ||
| 116 | |||
| 117 | Write-Step "npm install -g $Package" | ||
| 118 | npm install -g $Package | Out-Null | ||
| 119 | |||
| 120 | if ($LASTEXITCODE -ne 0) { | ||
| 121 | Write-Warn "npm install -g $Package fehlgeschlagen." | ||
| 122 | return | ||
| 123 | } | ||
| 124 | |||
| 125 | Write-Ok $Package | ||
| 126 | } | ||
| 127 | |||
| 128 | function Test-Prerequisites { | ||
| 129 | if (-not (Test-CommandExists "winget")) { | ||
| 130 | Write-Host "Fehler: winget wurde nicht gefunden. 'App Installer' aus dem Microsoft Store installieren." -ForegroundColor Red | ||
| 131 | exit 1 | ||
| 132 | } | ||
| 133 | } | ||
| 134 | |||
| 135 | function Update-SessionPath { | ||
| 136 | # Registry-PATH-Aenderungen durch winget/npm wirken erst nach diesem Refresh. | ||
| 137 | $machine = [Environment]::GetEnvironmentVariable("PATH", "Machine") | ||
| 138 | $user = [Environment]::GetEnvironmentVariable("PATH", "User") | ||
| 139 | $env:PATH = "$machine;$user" | ||
| 140 | } | ||
| 141 | |||
| 142 | function Install-Prerequisites { | ||
| 143 | Install-WingetPackage -Binary "git" -Id "Git.Git" | ||
| 144 | Install-WingetPackage -Binary "node" -Id "OpenJS.NodeJS.LTS" | ||
| 145 | Update-SessionPath | ||
| 146 | } | ||
| 147 | |||
| 148 | function Install-Formatters { | ||
| 149 | Install-WingetPackage -Binary "jq" -Id "jqlang.jq" | ||
| 150 | Install-NpmPackage -Binary "prettier" -Package "prettier" | ||
| 151 | Install-WingetPackage -Binary "ruff" -Id "astral-sh.ruff" | ||
| 152 | Install-WingetPackage -Binary "shfmt" -Id "mvdan.shfmt" | ||
| 153 | Install-WingetPackage -Binary "stylua" -Id "JohnnyMorganz.StyLua" | ||
| 154 | |||
| 155 | # yamlfmt, gawk, xmllint: kein winget-Paket gefunden, siehe neovim-windows-setup.md. | ||
| 156 | } | ||
| 157 | |||
| 158 | function Install-Tools { | ||
| 159 | Install-WingetPackage -Binary "rg" -Id "BurntSushi.ripgrep.MSVC" | ||
| 160 | Install-WingetPackage -Binary "fd" -Id "sharkdp.fd" | ||
| 161 | Install-NpmPackage -Binary "tree-sitter" -Package "tree-sitter-cli" | ||
| 162 | |||
| 163 | # MSVC (cl.exe) ist bereits vorhanden, kein winget-Paket noetig - Neovim | ||
| 164 | # dafuer aber aus einer "Developer PowerShell for VS" starten. | ||
| 165 | Install-WingetPackage -Binary "make" -Id "ezwinports.make" | ||
| 166 | } | ||
| 167 | |||
| 168 | function Install-Lsp { | ||
| 169 | Install-NpmPackage -Binary "basedpyright-langserver" -Package "basedpyright" | ||
| 170 | Install-NpmPackage -Binary "bash-language-server" -Package "bash-language-server" | ||
| 171 | Install-WingetPackage -Binary "clangd" -Id "LLVM.LLVM" | ||
| 172 | Install-WingetPackage -Binary "shellcheck" -Id "koalaman.shellcheck" | ||
| 173 | Install-NpmPackage -Binary "vscode-html-language-server" -Package "vscode-langservers-extracted" | ||
| 174 | Install-NpmPackage -Binary "vscode-json-language-server" -Package "vscode-langservers-extracted" | ||
| 175 | Install-WingetPackage -Binary "lua-language-server" -Id "LuaLS.lua-language-server" | ||
| 176 | Install-NpmPackage -Binary "prisma-language-server" -Package "@prisma/language-server" | ||
| 177 | Install-NpmPackage -Binary "vtsls" -Package "@vtsls/language-server" | ||
| 178 | } | ||
| 179 | |||
| 180 | function Main { | ||
| 181 | Test-Prerequisites | ||
| 182 | |||
| 183 | Install-Prerequisites | ||
| 184 | Install-Formatters | ||
| 185 | Install-Tools | ||
| 186 | Install-Lsp | ||
| 187 | |||
| 188 | Write-Host "" | ||
| 189 | if ($script:Failures.Count -eq 0) { | ||
| 190 | Write-Host "Bootstrap abgeschlossen." -ForegroundColor Green | ||
| 191 | } else { | ||
| 192 | Write-Host "Bootstrap abgeschlossen, mit $($script:Failures.Count) Warnung(en):" -ForegroundColor Yellow | ||
| 193 | foreach ($f in $script:Failures) { | ||
| 194 | Write-Host " - $f" -ForegroundColor Yellow | ||
| 195 | } | ||
| 196 | } | ||
| 197 | } | ||
| 198 | |||
| 199 | Main | ||
diff --git a/install-win.ps1 b/install-win.ps1 new file mode 100644 index 0000000..aa77243 --- /dev/null +++ b/install-win.ps1 | |||
| @@ -0,0 +1,113 @@ | |||
| 1 | #Requires -Version 5.1 | ||
| 2 | <# | ||
| 3 | Windows-natives Pendant zu install.sh - kopiert (statt zu verlinken) die | ||
| 4 | relevanten Konfigurationen an ihre nativen Windows-Zielorte. Keine | ||
| 5 | Admin-Rechte noetig (keine Symlinks). | ||
| 6 | |||
| 7 | Aufruf: | ||
| 8 | .\install-win.ps1 | ||
| 9 | #> | ||
| 10 | |||
| 11 | $ErrorActionPreference = "Stop" | ||
| 12 | |||
| 13 | function Write-Ok($msg) { | ||
| 14 | Write-Host "OK $msg" -ForegroundColor Green | ||
| 15 | } | ||
| 16 | |||
| 17 | function Write-Step($msg) { | ||
| 18 | Write-Host "==> $msg" -ForegroundColor Cyan | ||
| 19 | } | ||
| 20 | |||
| 21 | function Write-SkipMsg($msg) { | ||
| 22 | Write-Host "- $msg" -ForegroundColor DarkGray | ||
| 23 | } | ||
| 24 | |||
| 25 | $RepoRoot = $PSScriptRoot | ||
| 26 | |||
| 27 | $NvimSrc = Join-Path $RepoRoot "nvim" | ||
| 28 | $NvimDst = Join-Path $env:LOCALAPPDATA "nvim" | ||
| 29 | |||
| 30 | $GitConfigSrc = Join-Path $RepoRoot "git\config" | ||
| 31 | $GitConfigDst = Join-Path $env:USERPROFILE ".gitconfig" | ||
| 32 | |||
| 33 | $GitUp2partsSrc = Join-Path $RepoRoot "git\config-up2parts" | ||
| 34 | $GitXdgDir = Join-Path $env:USERPROFILE ".config\git" | ||
| 35 | $GitUp2partsDst = Join-Path $GitXdgDir "config-up2parts" | ||
| 36 | |||
| 37 | $NpmrcSrc = Join-Path $RepoRoot "npm\npmrc" | ||
| 38 | $NpmrcDst = Join-Path $env:USERPROFILE ".npmrc" | ||
| 39 | |||
| 40 | function Copy-NvimConfig { | ||
| 41 | Write-Step "nvim -> $NvimDst" | ||
| 42 | |||
| 43 | if (Test-Path $NvimDst) { | ||
| 44 | Remove-Item -Recurse -Force $NvimDst | ||
| 45 | } | ||
| 46 | |||
| 47 | Copy-Item -Recurse -Force $NvimSrc $NvimDst | ||
| 48 | Write-Ok $NvimDst | ||
| 49 | } | ||
| 50 | |||
| 51 | function Copy-GitConfig { | ||
| 52 | Write-Step "git\config -> $GitConfigDst" | ||
| 53 | Copy-Item -Force $GitConfigSrc $GitConfigDst | ||
| 54 | Write-Ok $GitConfigDst | ||
| 55 | |||
| 56 | if (-not (Test-Path $GitXdgDir)) { | ||
| 57 | New-Item -ItemType Directory -Path $GitXdgDir -Force | Out-Null | ||
| 58 | } | ||
| 59 | |||
| 60 | Write-Step "git\config-up2parts -> $GitUp2partsDst" | ||
| 61 | Copy-Item -Force $GitUp2partsSrc $GitUp2partsDst | ||
| 62 | Write-Ok "$GitUp2partsDst (wird per includeIf aus .gitconfig eingebunden)" | ||
| 63 | } | ||
| 64 | |||
| 65 | function Copy-Npmrc { | ||
| 66 | if (Test-Path $NpmrcDst) { | ||
| 67 | Write-SkipMsg "$NpmrcDst existiert bereits, uebersprungen" | ||
| 68 | return | ||
| 69 | } | ||
| 70 | |||
| 71 | # HOME ist unter Windows i.d.R. nicht gesetzt, ${HOME} in npm/npmrc wuerde | ||
| 72 | # nicht expandieren - Zeile daher auskommentieren statt zweite npmrc-Datei | ||
| 73 | # zu pflegen. | ||
| 74 | Write-Step "npm\npmrc -> $NpmrcDst (prefix-Zeile auskommentiert)" | ||
| 75 | $lines = Get-Content -Path $NpmrcSrc | ForEach-Object { | ||
| 76 | if ($_ -match "^\s*prefix\s*=") { | ||
| 77 | "; $_ (unter Windows auskommentiert)" | ||
| 78 | } else { | ||
| 79 | $_ | ||
| 80 | } | ||
| 81 | } | ||
| 82 | Set-Content -Path $NpmrcDst -Value $lines | ||
| 83 | Write-Ok $NpmrcDst | ||
| 84 | } | ||
| 85 | |||
| 86 | function Add-BinToUserPath { | ||
| 87 | $binDir = Join-Path $RepoRoot "windows\bin" | ||
| 88 | $userPath = [Environment]::GetEnvironmentVariable("PATH", "User") | ||
| 89 | $entries = $userPath -split ";" | ||
| 90 | |||
| 91 | if ($entries -contains $binDir) { | ||
| 92 | Write-SkipMsg "$binDir bereits im User-PATH" | ||
| 93 | return | ||
| 94 | } | ||
| 95 | |||
| 96 | Write-Step "$binDir zum User-PATH hinzufuegen (enthaelt gmake.cmd)" | ||
| 97 | [Environment]::SetEnvironmentVariable("PATH", "$userPath;$binDir", "User") | ||
| 98 | Write-Ok "$binDir (wirkt erst in neuen Terminal-Sitzungen)" | ||
| 99 | } | ||
| 100 | |||
| 101 | function Main { | ||
| 102 | Copy-NvimConfig | ||
| 103 | Copy-GitConfig | ||
| 104 | Copy-Npmrc | ||
| 105 | Add-BinToUserPath | ||
| 106 | |||
| 107 | Write-Host "" | ||
| 108 | Write-Host "Fertig. Dateien wurden KOPIERT, nicht verlinkt." -ForegroundColor Green | ||
| 109 | Write-Host "Nach Aenderungen im Repo dieses Skript erneut ausfuehren." | ||
| 110 | Write-Host "Neues Terminal oeffnen, damit PATH-Aenderungen wirksam werden." -ForegroundColor Yellow | ||
| 111 | } | ||
| 112 | |||
| 113 | Main | ||
diff --git a/neovim-windows-setup.md b/neovim-windows-setup.md new file mode 100644 index 0000000..c925f59 --- /dev/null +++ b/neovim-windows-setup.md | |||
| @@ -0,0 +1,113 @@ | |||
| 1 | # Neovim-Setup unter Windows (nativ) | ||
| 2 | |||
| 3 | Checkliste für die Übernahme der bestehenden `nvim/`-Config aus dem Dotfiles-Repo auf ein natives Windows-System (kein WSL). Repo selbst bleibt unverändert. | ||
| 4 | |||
| 5 | Alle Windows-Skripte in diesem Repo sind reines PowerShell (kein Git Bash, kein WSL) – mit einer Ausnahme: `windows\bin\gmake.cmd` ist ein trivialer Ein-Zeiler-Wrapper, für den sich eine `.ps1`-Datei nicht lohnt. | ||
| 6 | |||
| 7 | ## 0. Von Hand zu erledigen (nicht durch Skripte abgedeckt) | ||
| 8 | |||
| 9 | - **`winget` selbst muss vorhanden sein** ("App Installer" aus dem Microsoft Store) – `bootstrap-win/neovim.ps1` prüft das und bricht mit klarer Meldung ab, kann `winget` aber nicht selbst nachinstallieren. | ||
| 10 | - **Nach jedem Skript-Lauf ein neues Terminal öffnen**, bevor `nvim` das erste Mal gestartet wird. PATH-Änderungen (durch winget/npm-Installer oder `install-win.ps1`) landen in der Registry, aber die aktuell offene Shell bekommt das nicht automatisch mit. | ||
| 11 | - **PATH-Registrierung stichprobenartig prüfen** – manche winget-Pakete tragen sich nicht automatisch in den PATH ein (im Praxistest z. B. `LLVM.LLVM`: bereits installiert, aber `clangd` nicht im PATH, vermutlich weil der `--silent`-Installer die PATH-Registrierung überspringt). Nach einem neuen Terminal kurz `Get-Command clangd, jq, make` aufrufen; fehlt eins, dessen Installationsordner (bei LLVM z. B. `C:\Program Files\LLVM\bin`) manuell zum User-PATH hinzufügen (gleiches Muster wie `Add-BinToUserPath` in `install-win.ps1`). | ||
| 12 | - **yamlfmt, gawk, xmllint (libxml2) manuell installieren, falls benötigt** – im Praxistest bestätigt, dass es dafür keine winget-Pakete gibt ("Es wurde kein Paket gefunden, das den Eingabekriterien entspricht"), deshalb absichtlich nicht in `bootstrap-win/neovim.ps1` enthalten. Betrifft nur die Formatierung von awk-, xml/xsd- und yaml-Dateien (`conform.nvim` fällt sonst auf LSP-Formatierung zurück). Bekannte Alternativen: yamlfmt via `go install github.com/google/yamlfmt/cmd/yamlfmt@latest` (falls Go installiert) oder Binary von den GitHub-Releases; für gawk/xmllint keine verifizierte Windows-native Quelle gefunden, ggf. `winget search gawk` / `winget search libxml2` selbst prüfen. | ||
| 13 | - **Reihenfolge**: `install-win.ps1` und `bootstrap-win/neovim.ps1` sind unabhängig voneinander, `bootstrap-win/neovim-dict.ps1` ebenso. Empfehlenswert: erst Neovim/Git/Node (Abschnitt 1) installieren, dann beide Bootstrap-Skripte laufen lassen, dann neues Terminal öffnen, dann `nvim` starten (lädt beim ersten Start automatisch alle Lua-Plugins via `lazy.nvim` – Internetverbindung nötig). | ||
| 14 | - **Neovim immer aus einer "Developer PowerShell for VS" starten** (Startmenü-Eintrag, den Visual Studio/die Build Tools mitbringen), nicht aus normalem Windows Terminal/PowerShell. `cl.exe` (MSVC) braucht die `INCLUDE`/`LIB`-Umgebungsvariablen aus `vcvarsall.bat`, die nur in dieser Developer-Shell gesetzt sind – siehe Abschnitt 4. | ||
| 15 | |||
| 16 | ## 1. Grundwerkzeuge installieren | ||
| 17 | |||
| 18 | Execution Policy einmalig setzen, sonst starten die `.ps1`-Skripte in diesem Repo gar nicht (Alternative pro Aufruf: `powershell -ExecutionPolicy Bypass -File .\skript.ps1`): | ||
| 19 | |||
| 20 | ```powershell | ||
| 21 | Set-ExecutionPolicy -Scope CurrentUser RemoteSigned | ||
| 22 | winget install Neovim.Neovim | ||
| 23 | winget install Git.Git | ||
| 24 | winget install OpenJS.NodeJS.LTS | ||
| 25 | winget install dandavison.delta | ||
| 26 | ``` | ||
| 27 | |||
| 28 | `delta` wird von `git/config` als Pager vorausgesetzt (`pager = delta`, `diffFilter = delta --color-only`). War auch unter macOS/FreeBSD nie Teil von `bootstrap/neovim.sh` – wurde dort offenbar immer manuell installiert. | ||
| 29 | |||
| 30 | (Kein Python nötig – der Python-Provider ist in `options.lua` deaktiviert. Auch kein separater C-Compiler nötig – MSVC ist auf den Zielsystemen bereits vorhanden, siehe Abschnitt 3 bzw. 4.) | ||
| 31 | |||
| 32 | ## 2. Konfiguration einrichten (Windows-nativer Weg) | ||
| 33 | |||
| 34 | `install-win.ps1` im Repo-Root ausführen: | ||
| 35 | |||
| 36 | ```powershell | ||
| 37 | .\install-win.ps1 | ||
| 38 | ``` | ||
| 39 | |||
| 40 | Es kopiert (keine Symlinks, keine Admin-Rechte nötig): | ||
| 41 | |||
| 42 | - `nvim/` → `%LOCALAPPDATA%\nvim` | ||
| 43 | - `git/config` → `%USERPROFILE%\.gitconfig` | ||
| 44 | - `git/config-up2parts` → `%USERPROFILE%\.config\git\config-up2parts` (Pfad ist im `includeIf` von `git/config` hartkodiert) | ||
| 45 | - `npm/npmrc` → `%USERPROFILE%\.npmrc` (nur falls dort noch keine Datei existiert) – die Zeile `prefix=${HOME}/.local` wird dabei auskommentiert: `HOME` ist unter Windows i. d. R. nicht gesetzt, npm nutzt dort ohnehin schon von Haus aus `%APPDATA%\npm` als Präfix | ||
| 46 | |||
| 47 | Nach Änderungen im Repo `install-win.ps1` erneut ausführen, um die Kopien zu aktualisieren. | ||
| 48 | |||
| 49 | ## 3. Externe Abhängigkeiten | ||
| 50 | |||
| 51 | `bootstrap/neovim.sh` bricht unter Windows sofort ab (`Nicht unterstütztes Betriebssystem`). Stattdessen `bootstrap-win/neovim.ps1` ausführen (reines PowerShell, kein Git Bash/WSL nötig): | ||
| 52 | |||
| 53 | ```powershell | ||
| 54 | .\bootstrap-win\neovim.ps1 | ||
| 55 | ``` | ||
| 56 | |||
| 57 | Installiert per `winget`/`npm`: Git, Node, Formatter (jq, prettier, ruff, shfmt, stylua), Tools (ripgrep, fd, tree-sitter-cli, make über `ezwinports.make`) und LSP-Server (basedpyright, bash-language-server, clangd, shellcheck, vscode-langservers-extracted, lua-language-server, prisma, vtsls). Im Praxistest (24.07.2026) erfolgreich; yamlfmt/gawk/xmllint bewusst nicht enthalten (siehe Abschnitt 0). Einzelne Pakete, die trotzdem fehlschlagen, werden als Warnung gemeldet statt das Skript abzubrechen, inklusive der letzten Zeilen der winget-Fehlermeldung. | ||
| 58 | |||
| 59 | Kein C-Compiler-Paket enthalten: MSVC ist auf den Zielsystemen bereits vorhanden, `nvim-treesitter` nutzt `cl.exe`. Dafür muss Neovim aber aus einer "Developer PowerShell for VS" gestartet werden (siehe Abschnitt 4). | ||
| 60 | |||
| 61 | `windows\bin` (enthält `gmake.cmd`, Wrapper für `opt.makeprg = "gmake"`) danach einmalig zum PATH hinzufügen (PowerShell, User-Scope – nicht `setx PATH "%PATH%;..."` verwenden, das würde den kompletten Prozess-PATH inkl. System-Anteil dauerhaft in den User-PATH kopieren): | ||
| 62 | |||
| 63 | ```powershell | ||
| 64 | $userPath = [Environment]::GetEnvironmentVariable("PATH", "User") | ||
| 65 | [Environment]::SetEnvironmentVariable("PATH", "$userPath;$env:USERPROFILE\dotfiles\windows\bin", "User") | ||
| 66 | ``` | ||
| 67 | |||
| 68 | ## 4. Bekannte Stolpersteine | ||
| 69 | |||
| 70 | - **C-Compiler für `nvim-treesitter` (MSVC)**: `cl.exe` findet `nvim-treesitter` automatisch, aber nur wenn `INCLUDE`/`LIB` gesetzt sind – das passiert ausschließlich in einer "Developer PowerShell for VS" bzw. "x64 Native Tools Command Prompt", nicht in einer normalen PowerShell/Windows Terminal-Sitzung. Ohne das schlägt die Parser-Kompilierung mit einer Meldung wie "cannot find `<header>`.h" fehl, obwohl `cl.exe` selbst gefunden wird. Neovim also immer aus dieser Developer-Shell heraus starten. | ||
| 71 | |||
| 72 | ## 5. Verifizieren | ||
| 73 | |||
| 74 | ``` | ||
| 75 | nvim | ||
| 76 | :checkhealth | ||
| 77 | ``` | ||
| 78 | |||
| 79 | `:checkhealth` zeigt fehlende Provider/Tools direkt an – guter letzter Schritt nach der Installation. | ||
| 80 | |||
| 81 | ## 6. Aktualisieren | ||
| 82 | |||
| 83 | Pendant zu `brew update && brew upgrade` (macOS) bzw. `pkg update && pkg upgrade` (FreeBSD): | ||
| 84 | |||
| 85 | ```powershell | ||
| 86 | winget source update # Paketquellen aktualisieren | ||
| 87 | winget upgrade --all # alle winget-Pakete aktualisieren | ||
| 88 | ``` | ||
| 89 | |||
| 90 | Vorschau, was aktualisiert würde, ohne etwas zu ändern: | ||
| 91 | |||
| 92 | ```powershell | ||
| 93 | winget list --upgrade-available | ||
| 94 | ``` | ||
| 95 | |||
| 96 | Einzelnes Paket gezielt aktualisieren (IDs siehe `bootstrap-win/neovim.ps1`): | ||
| 97 | |||
| 98 | ```powershell | ||
| 99 | winget upgrade LLVM.LLVM | ||
| 100 | ``` | ||
| 101 | |||
| 102 | Zwei Besonderheiten gegenüber brew/pkg: | ||
| 103 | |||
| 104 | - Manche Pakete melden nicht immer zuverlässig eine neue Version (z. B. ältere/portable Pakete). `winget upgrade --all --include-unknown` bezieht auch diese mit ein, installiert dabei aber unter Umständen unnötig neu. | ||
| 105 | - Ein Paket dauerhaft von `--all` ausnehmen: `winget pin add <id>` (Pendant zu `brew pin`). | ||
| 106 | |||
| 107 | Die npm-Pakete (`prettier`, `basedpyright`, `bash-language-server`, `vtsls`, `@prisma/language-server`, `vscode-langservers-extracted`) laufen außerhalb von winget und werden separat aktualisiert: | ||
| 108 | |||
| 109 | ```powershell | ||
| 110 | npm update -g | ||
| 111 | ``` | ||
| 112 | |||
| 113 | `bootstrap-win/neovim.ps1` erneut auszuführen aktualisiert nichts – `Install-WingetPackage`/`Install-NpmPackage` überspringen ein Paket, sobald das Binary gefunden wird (siehe `Write-Skip`). Für Updates immer die Befehle oben verwenden. | ||
diff --git a/nvim/lua/config/usercmds.lua b/nvim/lua/config/usercmds.lua index 9abc50f..529b370 100644 --- a/nvim/lua/config/usercmds.lua +++ b/nvim/lua/config/usercmds.lua | |||
| @@ -66,8 +66,16 @@ local function enable_lsp() | |||
| 66 | vim.cmd("edit") -- triggert Reattach bei vielen Setups | 66 | vim.cmd("edit") -- triggert Reattach bei vielen Setups |
| 67 | end | 67 | end |
| 68 | 68 | ||
| 69 | vim.api.nvim_create_user_command("SonarScan", run_sonar, {}) | 69 | -- sonar-scanner/scripts/sonarqube.sh sind POSIX-only (kein Windows-Pendant), |
| 70 | vim.api.nvim_create_user_command("SonarIssues", load_sonar_issues, {}) | 70 | -- deshalb Kommandos unter Windows gar nicht erst registrieren statt sie |
| 71 | -- dort fehlschlagen zu lassen. | ||
| 72 | local is_windows = vim.fn.has("win32") == 1 | ||
| 73 | |||
| 74 | if not is_windows then | ||
| 75 | vim.api.nvim_create_user_command("SonarScan", run_sonar, {}) | ||
| 76 | vim.api.nvim_create_user_command("SonarIssues", load_sonar_issues, {}) | ||
| 77 | end | ||
| 78 | |||
| 71 | vim.api.nvim_create_user_command("LspOff", disable_lsp, {}) | 79 | vim.api.nvim_create_user_command("LspOff", disable_lsp, {}) |
| 72 | vim.api.nvim_create_user_command("LspOffBuffer", disable_lsp_buffer, {}) | 80 | vim.api.nvim_create_user_command("LspOffBuffer", disable_lsp_buffer, {}) |
| 73 | vim.api.nvim_create_user_command("LspOn", enable_lsp, {}) | 81 | vim.api.nvim_create_user_command("LspOn", enable_lsp, {}) |
| @@ -1,9 +1,11 @@ | |||
| 1 | # Dotfiles | 1 | # Dotfiles |
| 2 | 2 | ||
| 3 | My personal dotfiles for macOS and FreeBSD. | 3 | My personal dotfiles for macOS, FreeBSD and Windows (Beta). |
| 4 | 4 | ||
| 5 | ## Setup | 5 | ## Setup |
| 6 | 6 | ||
| 7 | ### macOS / FreeBSD | ||
| 8 | |||
| 7 | Create the symbolic links: | 9 | Create the symbolic links: |
| 8 | 10 | ||
| 9 | ```sh | 11 | ```sh |
| @@ -17,6 +19,18 @@ Bootstrap the Neovim environment: | |||
| 17 | ./bootstrap/neovim-dict.sh | 19 | ./bootstrap/neovim-dict.sh |
| 18 | ``` | 20 | ``` |
| 19 | 21 | ||
| 22 | ### Windows | ||
| 23 | |||
| 24 | Native PowerShell, no WSL/Git Bash required: | ||
| 25 | |||
| 26 | ```powershell | ||
| 27 | .\install-win.ps1 | ||
| 28 | .\bootstrap-win\neovim.ps1 | ||
| 29 | .\bootstrap-win\neovim-dict.ps1 | ||
| 30 | ``` | ||
| 31 | |||
| 32 | See [neovim-windows-setup.md](neovim-windows-setup.md) for prerequisites (execution policy, MSVC Developer PowerShell for `nvim-treesitter`, ...) and known caveats. | ||
| 33 | |||
| 20 | ## Included configuration | 34 | ## Included configuration |
| 21 | 35 | ||
| 22 | - [abook] | 36 | - [abook] |
diff --git a/windows/bin/gmake.cmd b/windows/bin/gmake.cmd new file mode 100644 index 0000000..89f3a29 --- /dev/null +++ b/windows/bin/gmake.cmd | |||
| @@ -0,0 +1,11 @@ | |||
| 1 | @echo off | ||
| 2 | rem Wrapper, damit opt.makeprg = "gmake" (aus nvim/lua/config/options.lua) | ||
| 3 | rem unter Windows funktioniert, ohne die bestehende Config anzupassen. | ||
| 4 | rem Reicht alle Argumente an das im PATH gefundene "make" weiter. | ||
| 5 | rem | ||
| 6 | rem Einmalig einrichten: dieses Verzeichnis (windows\bin) zum PATH | ||
| 7 | rem hinzufuegen, z.B. ueber: | ||
| 8 | rem setx PATH "%PATH%;%USERPROFILE%\dotfiles\windows\bin" | ||
| 9 | |||
| 10 | make %* | ||
| 11 | exit /b %ERRORLEVEL% | ||
diff --git a/windows/bin/nvim-update.cmd b/windows/bin/nvim-update.cmd new file mode 100644 index 0000000..7e8260e --- /dev/null +++ b/windows/bin/nvim-update.cmd | |||
| @@ -0,0 +1,2 @@ | |||
| 1 | @echo off | ||
| 2 | nvim --headless "+Lazy! sync" "+qa" | ||
