From b8f09ed9ea5731ce1ac6ba232fbd1c3809420ed8 Mon Sep 17 00:00:00 2001 From: Emma Thorpe Date: Wed, 10 Jun 2026 15:31:29 +0100 Subject: [PATCH 1/2] chore(flake): add nixvim input Declarative Neovim, on the nixos-26.05 release branch and following our nixpkgs to keep a single nixpkgs in the closure. Consumed by lyrathorpe/home/editor.nix. Co-Authored-By: Claude Opus 4.8 (1M context) --- flake.lock | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ flake.nix | 8 ++++++++ 2 files changed, 68 insertions(+) diff --git a/flake.lock b/flake.lock index 73f2769..1453b12 100644 --- a/flake.lock +++ b/flake.lock @@ -106,6 +106,27 @@ "type": "github" } }, + "flake-parts_2": { + "inputs": { + "nixpkgs-lib": [ + "nixvim", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1778716662, + "narHash": "sha256-m1Yf0wZ8j1OHjTc2UwHwyQRSnNeSgLJOd7q5Y45hzi4=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "f7c1a2d347e4c52d5fb8d10cb4d94b5884e546fb", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "flake-parts", + "type": "github" + } + }, "git-hooks": { "inputs": { "flake-compat": "flake-compat", @@ -303,6 +324,29 @@ "type": "github" } }, + "nixvim": { + "inputs": { + "flake-parts": "flake-parts_2", + "nixpkgs": [ + "nixpkgs" + ], + "systems": "systems" + }, + "locked": { + "lastModified": 1781038653, + "narHash": "sha256-MxUVyE7A5QMJXOEFQhOHsqs4UPhujeDgdFhguE7Wmic=", + "owner": "nix-community", + "repo": "nixvim", + "rev": "e7ce6708cc5b6275406a8feee06ca50c5cafd6bf", + "type": "github" + }, + "original": { + "owner": "nix-community", + "ref": "nixos-26.05", + "repo": "nixvim", + "type": "github" + } + }, "root": { "inputs": { "firefox-addons": "firefox-addons", @@ -316,9 +360,25 @@ "nixos-wsl": "nixos-wsl", "nixpkgs": "nixpkgs", "nixpkgs-unstable": "nixpkgs-unstable", + "nixvim": "nixvim", "treefmt-nix": "treefmt-nix" } }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, "treefmt-nix": { "inputs": { "nixpkgs": [ diff --git a/flake.nix b/flake.nix index ed4a090..2773163 100644 --- a/flake.nix +++ b/flake.nix @@ -46,6 +46,14 @@ url = "github:cachix/git-hooks.nix"; inputs.nixpkgs.follows = "nixpkgs"; }; + # Declarative Neovim (the editor; see lyrathorpe/home/editor.nix). Release + # branch matched to the pinned nixpkgs (26.05); follows our nixpkgs to keep a + # single nixpkgs in the closure. editor.nix sets programs.nixvim.nixpkgs.source + # to this same input so the home module doesn't warn about the pin. + nixvim = { + url = "github:nix-community/nixvim/nixos-26.05"; + inputs.nixpkgs.follows = "nixpkgs"; + }; }; outputs = -- 2.52.0 From 55bce14bf323f1307c4b89776bb6e9e6b4a15602 Mon Sep 17 00:00:00 2001 From: Emma Thorpe Date: Wed, 10 Jun 2026 15:31:40 +0100 Subject: [PATCH 2/2] feat(nvim): migrate editor from vim to Neovim (parity + LSP) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rewrite editor.nix on programs.nixvim, keeping every prior feature: file tree (nvim-tree, toggle ,,), indent guides (indent-blankline), fugitive, vim-tmux-navigator, Catppuccin Mocha, 2-space hard tabs, and the *Jenkinsfile=groovy rule. Replace the inert ALE with a real LSP stack — nvim-lspconfig, nvim-cmp completion, and tree-sitter for highlighting. Leader is Space; LSP keymaps gd/gr/K/rn/ca. Universal servers: nil (Nix), lua_ls, pyright (Python), terraformls. The work box (work.nix) additionally enables omnisharp (C#) and helm_ls (Helm), so the heavy omnisharp closure stays off the personal machines. default.nix drops VISUAL=vim so nixvim's defaultEditor owns $EDITOR/$VISUAL. README and KEYBINDINGS updated (and two stale references corrected). Co-Authored-By: Claude Opus 4.8 (1M context) --- lyrathorpe/home/KEYBINDINGS.md | 21 ++++++ lyrathorpe/home/README.md | 37 ++++++++-- lyrathorpe/home/default.nix | 7 +- lyrathorpe/home/editor.nix | 120 +++++++++++++++++++++++++++------ lyrathorpe/home/work.nix | 9 +++ 5 files changed, 165 insertions(+), 29 deletions(-) diff --git a/lyrathorpe/home/KEYBINDINGS.md b/lyrathorpe/home/KEYBINDINGS.md index b768d01..c92d1d8 100644 --- a/lyrathorpe/home/KEYBINDINGS.md +++ b/lyrathorpe/home/KEYBINDINGS.md @@ -9,6 +9,7 @@ rebuild, never the generated dotfiles. | Sway (compositor) | [`sway.nix`](./sway.nix) `config.keybindings` + `config.modes`, plus the home-manager Sway module's built-in defaults | | tmux | [`shell.nix`](./shell.nix) `programs.tmux` | | zsh line editor | [`shell.nix`](./shell.nix) `programs.zsh.historySubstringSearch` | +| Neovim | [`editor.nix`](./editor.nix) `programs.nixvim` | | foot (terminal) | foot package defaults — only colours are themed (in `sway.nix`) | **Conventions** @@ -167,6 +168,26 @@ Only colours are themed; these are foot's default key bindings. --- +## Neovim + +Leader is **`Space`**. `Ctrl`+`h/j/k/l` is shared with tmux (see above): it moves +across vim splits and tmux panes seamlessly. Everything else is stock vim, plus: + +| Shortcut | Action | +| ---------------------- | --------------------------------------------------------- | +| `,``,` | Toggle the file tree (nvim-tree) — comma pressed twice | +| `Ctrl`+`h`/`j`/`k`/`l` | Move between vim splits / tmux panes (vim-tmux-navigator) | +| `gd` | Go to definition (LSP) | +| `gr` | List references (LSP) | +| `K` | Hover documentation (LSP) | +| `rn` | Rename symbol (LSP; `` is `Space`) | +| `ca` | Code action (LSP) | + +LSP covers Nix, Lua, Python and Terraform (the work box adds C# and Helm); +completion (nvim-cmp) appears as you type. `:Git` opens fugitive. + +--- + ## zsh | Shortcut | Action | diff --git a/lyrathorpe/home/README.md b/lyrathorpe/home/README.md index 6a402f0..5606fd2 100644 --- a/lyrathorpe/home/README.md +++ b/lyrathorpe/home/README.md @@ -10,12 +10,12 @@ Keyboard shortcuts have their own reference: [`KEYBINDINGS.md`](./KEYBINDINGS.md | ------------------------------------- | ----------------------------------------------------- | | zsh, CLI tools, tmux, ssh, auto-tmux | [`shell.nix`](./shell.nix) | | git (+ delta, commitizen) | [`git.nix`](./git.nix) | -| vim | [`editor.nix`](./editor.nix) | +| Neovim (nixvim) + LSP | [`editor.nix`](./editor.nix) | | GUI apps, GTK/Firefox theming, cursor | [`desktop.nix`](./desktop.nix) (graphical hosts only) | Shared by every host via [`default.nix`](./default.nix); the work box also layers -[`../../system/modules/work/default.nix`](../../system/modules/work/default.nix) -on top (work email, its own ssh config, extra packages). +[`work.nix`](./work.nix) on top (work email, its own ssh config, extra packages, +and the C#/Helm language servers). --- @@ -53,8 +53,9 @@ on top (work email, its own ssh config, extra packages). driven from the shared `../catppuccin-mocha.nix` palette / the catppuccin/bat theme. -**Env & defaults:** `xdg.enable` on; `PAGER`/`MANPAGER` (bat)/`VISUAL` set in -`default.nix`; `xdg.mimeApps` maps web→Firefox, directories→nemo (`desktop.nix`). +**Env & defaults:** `xdg.enable` on; `PAGER`/`MANPAGER` (bat) set in `default.nix` +(the editor owns `$EDITOR`/`$VISUAL`); `xdg.mimeApps` maps web→Firefox, +directories→nemo (`desktop.nix`). ## tmux @@ -90,6 +91,32 @@ Darwin config). foot uses it as its main font automatically. iTerm2's font is a GUI setting — set it to _JetBrainsMono Nerd Font_ (Settings → Profiles → Text → Font) so the tmux statusline glyphs render instead of `?`. +## Editor (Neovim) + +`nvim` — aliased to `vi`/`vim`, and set as `$EDITOR`/`$VISUAL` — is configured +declaratively with **nixvim**, so the same plugins and config are baked in on +every host. Migrated from plain vim; the practical gain is a real LSP stack in +place of the old (inert) ALE. + +| Feature | Notes | +| ------------- | -------------------------------------------------------------------------------------- | +| Colorscheme | Catppuccin Mocha (matches the terminal and the rest of the desktop) | +| File tree | nvim-tree, toggled with `,,` (comma twice; was nerdtree) | +| Indent guides | indent-blankline, on by default (was vim-indent-guides) | +| Git | fugitive (`:Git …`) | +| Pane nav | vim-tmux-navigator — `Ctrl`+`h/j/k/l` moves across vim splits and tmux panes | +| Syntax | tree-sitter (nix, lua, bash, markdown, groovy) — replaces `syntax enable` | +| LSP | nvim-cmp completion + servers `nil` (Nix), `lua_ls`, `pyright` (Python), `terraformls` | +| Indentation | 2-wide hard tabs (`noexpandtab`, `tabstop`/`shiftwidth` = 2); line numbers on | +| Filetypes | `*Jenkinsfile` → groovy | + +Leader is `Space`. LSP keymaps (`gd`, `gr`, `K`, `rn`, `ca`) and +the file-tree toggle are listed in +[`KEYBINDINGS.md`](./KEYBINDINGS.md#neovim). Add a universal language server by +enabling it under `programs.nixvim.plugins.lsp.servers` in `editor.nix`; +host-specific ones go in that host's module — the work box (`work.nix`) adds +`omnisharp` (C#) and `helm_ls` (Helm), kept off the personal machines. + ## git Pager is **delta**. **commitizen** is installed on every host; `cz` defaults to diff --git a/lyrathorpe/home/default.nix b/lyrathorpe/home/default.nix index d07a9c7..c9fa8d6 100644 --- a/lyrathorpe/home/default.nix +++ b/lyrathorpe/home/default.nix @@ -15,11 +15,10 @@ # defaults match the conventional ~/.config, ~/.cache, ~/.local/share. xdg.enable = true; - # Editor itself comes from vim.defaultEditor (sets $EDITOR). Round out the - # rest of the standard env. desktop.nix adds its own Wayland session vars; - # home-manager merges the two attrsets, so these do not clash. + # Editor ($EDITOR and $VISUAL) comes from nixvim's defaultEditor (editor.nix). + # Round out the rest of the standard env. desktop.nix adds its own Wayland + # session vars; home-manager merges the two attrsets, so these do not clash. home.sessionVariables = { - VISUAL = "vim"; PAGER = "less -FRX"; # -F quit-if-one-screen, -R raw colour, -X no clear # Render man pages through bat (themed): col strips backspace overstrike, # bat -l man -p highlights without its own pager decorations. diff --git a/lyrathorpe/home/editor.nix b/lyrathorpe/home/editor.nix index 188375d..8e98a69 100644 --- a/lyrathorpe/home/editor.nix +++ b/lyrathorpe/home/editor.nix @@ -1,29 +1,109 @@ -# Editor: vim as the default $EDITOR. Wanted on every host. -{ pkgs, ... }: +# Editor: Neovim via nixvim. Migrated from plain vim with feature parity (file +# tree, indent guides, fugitive, tmux-navigator, Catppuccin Mocha, 2-space hard +# tabs, Jenkinsfile=groovy) plus a real LSP stack in place of the inert ALE. +# Wanted on every host; vi/vim/$EDITOR all launch nvim. +{ inputs, ... }: { - programs.vim = { + imports = [ inputs.nixvim.homeModules.nixvim ]; + + programs.nixvim = { enable = true; + viAlias = true; + vimAlias = true; defaultEditor = true; - plugins = with pkgs.vimPlugins; [ - nerdtree - ale - vim-fugitive - vim-indent-guides - catppuccin-vim - vim-tmux-navigator # Ctrl-h/j/k/l moves between vim splits and tmux panes - ]; - settings = { + + # Build against our (followed) nixpkgs; set explicitly so the module doesn't + # warn that its pinned nixpkgs was overridden by the input `follows`. + nixpkgs.source = inputs.nixpkgs; + + globals.mapleader = " "; + + opts = { expandtab = false; tabstop = 2; shiftwidth = 2; + termguicolors = true; + background = "dark"; + number = true; }; - extraConfig = '' - let g:indent_guides_enable_on_vim_startup = 1 - syntax enable - set termguicolors - set background=dark - colorscheme catppuccin_mocha - au BufNewFile,BufRead *Jenkinsfile setf groovy - ''; + + colorschemes.catppuccin = { + enable = true; + settings.flavour = "mocha"; + }; + + plugins = { + nvim-tree.enable = true; # file explorer (was nerdtree) + web-devicons.enable = true; # nvim-tree icons (explicit; else auto-enabled with a warning) + indent-blankline.enable = true; # indent guides (was vim-indent-guides) + fugitive.enable = true; # git (was vim-fugitive) + tmux-navigator.enable = true; # Ctrl-h/j/k/l across vim splits and tmux panes + + # Highlighting/indent — the Neovim-native replacement for `syntax enable`. + treesitter = { + enable = true; + settings.ensure_installed = [ + "nix" + "lua" + "bash" + "markdown" + "groovy" + "c_sharp" # C# + "python" + "terraform" # also covers HCL + "yaml" # Helm chart templates/values + ]; + }; + + # LSP + completion, replacing the (inert) ALE. + lsp = { + enable = true; + # Universal servers. Host-specific ones are enabled in their own module: + # C# (omnisharp) and Helm (helm_ls) live in work.nix (EDaaS only). + servers = { + nil_ls.enable = true; # Nix + lua_ls.enable = true; # Lua (editing this config) + pyright.enable = true; # Python + terraformls.enable = true; # Terraform + }; + keymaps.lspBuf = { + gd = "definition"; + gr = "references"; + K = "hover"; + "rn" = "rename"; + "ca" = "code_action"; + }; + }; + cmp = { + enable = true; + autoEnableSources = true; + settings.sources = [ + { name = "nvim_lsp"; } + { name = "buffer"; } + { name = "path"; } + ]; + }; + }; + + keymaps = [ + { + mode = "n"; + key = ",,"; + action = "NvimTreeToggle"; + options.desc = "Toggle file tree"; + } + ]; + + # au BufNewFile,BufRead *Jenkinsfile setf groovy + autoCmd = [ + { + event = [ + "BufNewFile" + "BufRead" + ]; + pattern = [ "*Jenkinsfile" ]; + command = "setf groovy"; + } + ]; }; } diff --git a/lyrathorpe/home/work.nix b/lyrathorpe/home/work.nix index 5314e51..27d54ea 100644 --- a/lyrathorpe/home/work.nix +++ b/lyrathorpe/home/work.nix @@ -52,4 +52,13 @@ programs.go = { enable = true; }; + + # LSP servers only relevant to work: C# (omnisharp) and Helm charts (helm_ls). + # The shared editor (lyrathorpe/home/editor.nix) carries the universal ones; + # these are gated to this host so the heavy omnisharp closure stays off the + # personal machines. Tree-sitter grammars (highlighting) remain global there. + programs.nixvim.plugins.lsp.servers = { + omnisharp.enable = true; + helm_ls.enable = true; + }; } -- 2.52.0