Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 22 additions & 1 deletion .github/actions/setup-nvim/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ description: >-
inputs:
version:
description: Neovim release to install
default: 0.11.4 # keep in sync with the Neovim you run locally
default: 0.12.6 # keep in sync with the Neovim you run locally
tree-sitter-version:
description: tree-sitter CLI release, which nvim-treesitter uses to compile parsers
default: 0.27.1

runs:
using: composite
Expand All @@ -31,6 +34,24 @@ runs:
& "$bin\nvim.exe" --version
$bin >> $env:GITHUB_PATH

- name: Install tree-sitter CLI ${{ inputs.tree-sitter-version }}
# Mason installs it too, but only after startup; having it on PATH lets parsers install right away.
shell: pwsh
env:
TS_VERSION: ${{ inputs.tree-sitter-version }}
run: |
$bin = Join-Path $env:RUNNER_TEMP tree-sitter-bin
New-Item -ItemType Directory $bin -Force | Out-Null
$gz = Join-Path $env:RUNNER_TEMP tree-sitter.gz
Invoke-WebRequest "https://github.com/tree-sitter/tree-sitter/releases/download/v$env:TS_VERSION/tree-sitter-windows-x64.gz" -OutFile $gz
$in = [IO.File]::OpenRead($gz)
$out = [IO.File]::Create((Join-Path $bin tree-sitter.exe))
$unzip = [IO.Compression.GZipStream]::new($in, [IO.Compression.CompressionMode]::Decompress)
$unzip.CopyTo($out)
$unzip.Dispose(); $out.Dispose(); $in.Dispose()
& (Join-Path $bin tree-sitter.exe) --version
$bin >> $env:GITHUB_PATH

- name: Provide make
# telescope-fzf-native and LuaSnip build with `make`; the runner image only ships mingw32-make.
shell: pwsh
Expand Down
3 changes: 2 additions & 1 deletion .github/copilot-instructions.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Copilot instructions

Personal Neovim config (Lua, lazy.nvim), used on Windows with pwsh for C#/.NET, Go and Vite/React work. CI checks are described in `README.md`.
Personal Neovim config (Lua, lazy.nvim) for Neovim 0.12+, used on Windows with pwsh for C#/.NET, Go and Vite/React work. CI checks are described in `README.md`.

## Layout

Expand All @@ -9,6 +9,7 @@ Personal Neovim config (Lua, lazy.nvim), used on Windows with pwsh for C#/.NET,
- Language servers are installed and enabled by mason-lspconfig (`lazy/lsp/mason.lua`) and configured with `vim.lsp.config` (`lazy/lsp/lspconfig.lua`).
- Per-filetype settings go in `after/ftplugin/<filetype>.lua`.
- `lazy-lock.json` pins every plugin's commit. `tests/smoke.lua` is the headless startup test.
- Treesitter uses nvim-treesitter's `main` branch: it only installs parsers (`lazy/treesitter.lua`), and Neovim's built-in treesitter does highlighting, started per buffer from a FileType autocmd. There is no `nvim-treesitter.configs`.
- `.github/agents/pr-reviewer.agent.md` defines the AI PR reviewer; the workflows that run it are `.github/workflows/pr-review*.md`.

## Git
Expand Down
7 changes: 6 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@ This is my Neovim setup largely based and expanded on Josean Martinez's [blog po

Other than small retouch the setup is virtually identitcal to Josean's setup, checkout his video for more detailed explanation on the setup.

## Requirements

- Neovim 0.12 or later.
- A C compiler on `PATH` (e.g. gcc from MinGW) to build treesitter parsers and telescope-fzf-native. nvim-treesitter also needs the `tree-sitter` CLI, which Mason installs; on a fresh machine parsers install once Mason has it.

## Updates

- **Plugins**: `.github/workflows/plugin-update.yml` runs `:Lazy update` every Monday (or on demand from the Actions tab), commits the new `lazy-lock.json` to `simonk/dev/plugin-update`, and opens or refreshes an *Update plugins* PR that links each plugin's changes. CI runs on that PR, so the smoke test covers the new commits; merge it if it's green. The workflow force-pushes the branch each week, but leaves it alone once it has a commit from anyone else, so you can push a fix to it. It needs **Allow GitHub Actions to create and approve pull requests** turned on in Settings → Actions → General.
Expand All @@ -13,7 +18,7 @@ Other than small retouch the setup is virtually identitcal to Josean's setup, ch
Every pull request (and push to `main`) runs `.github/workflows/ci.yml`:

- **StyLua**: `stylua --check .` using `.stylua.toml`. Fix locally with `stylua .`.
- **Startup smoke test (Windows)**: installs every plugin from `lazy-lock.json` into empty directories, opens a Lua and a C# buffer, loads all plugins, and fails on any error. It also checks wiring that wouldn't raise an error: every mason-lspconfig server name resolves to an LSP config, Go/TSX/Lua buffers get the expected formatter, files without a formatter get trailing whitespace trimmed (patches excepted), and web filetypes use 2-space indents. Mason package download failures are ignored because they depend on the network, not the config; language servers aren't installed in headless runs, so they're never started.
- **Startup smoke test (Windows)**: installs every plugin from `lazy-lock.json` and every treesitter parser into empty directories, opens a Lua and a C# buffer, loads all plugins, and fails on any error. It also checks wiring that wouldn't raise an error: every mason-lspconfig server name resolves to an LSP config, Go/TSX/Lua buffers get the expected formatter and treesitter highlighting, files without a formatter get trailing whitespace trimmed (patches excepted), and web filetypes use 2-space indents. Mason package download failures are ignored because they depend on the network, not the config; language servers aren't installed in headless runs, so they're never started.

Run the smoke test locally from this directory:

Expand Down
70 changes: 35 additions & 35 deletions lazy-lock.json
Original file line number Diff line number Diff line change
@@ -1,56 +1,56 @@
{
"Comment.nvim": { "branch": "master", "commit": "e30b7f2008e52442154b66f7c519bfd2f1e32acb" },
"FixCursorHold.nvim": { "branch": "master", "commit": "1900f89dc17c603eec29960f57c00bd9ae696495" },
"LuaSnip": { "branch": "master", "commit": "458560534a73f7f8d7a11a146c801db00b081df0" },
"alpha-nvim": { "branch": "main", "commit": "a9d8fb72213c8b461e791409e7feabb74eb6ce73" },
"auto-session": { "branch": "main", "commit": "62437532b38495551410b3f377bcf4aaac574ebe" },
"LuaSnip": { "branch": "master", "commit": "642b0c595e11608b4c18219e93b88d7637af27bc" },
"alpha-nvim": { "branch": "main", "commit": "4ba26e41990c11620c96c0e1cff20eab65efde4a" },
"auto-session": { "branch": "main", "commit": "02a5588f677970a9bc784115c62bef9e5855499b" },
"bufferline.nvim": { "branch": "main", "commit": "655133c3b4c3e5e05ec549b9f8cc2894ac6f51b3" },
"cmp-buffer": { "branch": "main", "commit": "b74fab3656eea9de20a9b8116afa3cfc4ec09657" },
"cmp-nvim-lsp": { "branch": "main", "commit": "cbc7b02bb99fae35cb42f514762b89b5126651ef" },
"cmp-path": { "branch": "main", "commit": "c642487086dbd9a93160e1679a1327be111cbc25" },
"cmp_luasnip": { "branch": "master", "commit": "98d9cb5c2c38532bd9bdb481067b20fea8f32e90" },
"conform.nvim": { "branch": "master", "commit": "086a40dc7ed8242c03be9f47fbcee68699cc2395" },
"conform.nvim": { "branch": "master", "commit": "016802de402556da54c36bd7359b441266b01cdd" },
"copilot-cmp": { "branch": "master", "commit": "15fc12af3d0109fa76b60b5cffa1373697e261d1" },
"copilot.lua": { "branch": "master", "commit": "0552b44fceedf0c4cba2cd4953d3976633b2509a" },
"copilot.lua": { "branch": "master", "commit": "3f1f8cc30783ca905224eadebaa6ddfd73c28828" },
"dressing.nvim": { "branch": "master", "commit": "2d7c2db2507fa3c4956142ee607431ddb2828639" },
"fidget.nvim": { "branch": "main", "commit": "7fa433a83118a70fe24c1ce88d5f0bd3453c0970" },
"friendly-snippets": { "branch": "main", "commit": "6cd7280adead7f586db6fccbd15d2cac7e2188b9" },
"gitsigns.nvim": { "branch": "main", "commit": "7c4faa3540d0781a28588cafbd4dd187a28ac6e3" },
"indent-blankline.nvim": { "branch": "master", "commit": "d28a3f70721c79e3c5f6693057ae929f3d9c0a03" },
"lazy.nvim": { "branch": "main", "commit": "306a05526ada86a7b30af95c5cc81ffba93fef97" },
"fidget.nvim": { "branch": "main", "commit": "9e0201673e08e997e7cf52afca5565c70bd117f3" },
"friendly-snippets": { "branch": "main", "commit": "b4d01b0fdf3c9a549961c2f9ffe8dc09be166219" },
"gitsigns.nvim": { "branch": "main", "commit": "fd780920613e541cbdfac41bf711583ed49f9249" },
"indent-blankline.nvim": { "branch": "master", "commit": "f1e186e44d3b7f9ae918008e2c28ce37c6023d2d" },
"lazy.nvim": { "branch": "main", "commit": "85c7ff3711b730b4030d03144f6db6375044ae82" },
"lazydev.nvim": { "branch": "main", "commit": "ff2cbcba459b637ec3fd165a2be59b7bbaeedf0d" },
"lazygit.nvim": { "branch": "main", "commit": "a04ad0dbc725134edbee3a5eea29290976695357" },
"lazygit.nvim": { "branch": "main", "commit": "9ffc6103926718f7070fb4017694543cd7dc9718" },
"lspkind.nvim": { "branch": "master", "commit": "c7274c48137396526b59d86232eabcdc7fed8a32" },
"lualine.nvim": { "branch": "master", "commit": "47f91c416daef12db467145e16bed5bbfe00add8" },
"mason-lspconfig.nvim": { "branch": "main", "commit": "a676ab7282da8d651e175118bcf54483ca11e46d" },
"lualine.nvim": { "branch": "master", "commit": "221ce6b2d999187044529f49da6554a92f740a96" },
"mason-lspconfig.nvim": { "branch": "main", "commit": "00b5473cca4db5b410ff4bae724e3b6e21f2687f" },
"mason-nvim-dap.nvim": { "branch": "main", "commit": "9a10e096703966335bd5c46c8c875d5b0690dade" },
"mason-tool-installer.nvim": { "branch": "main", "commit": "443f1ef8b5e6bf47045cb2217b6f748a223cf7dc" },
"mason.nvim": { "branch": "main", "commit": "44d1e90e1f66e077268191e3ee9d2ac97cc18e65" },
"neotest": { "branch": "master", "commit": "deadfb1af5ce458742671ad3a013acb9a6b41178" },
"neotest-golang": { "branch": "main", "commit": "ad6ae703e18874eb66fee539224eac2dd9cc0890" },
"neotest-vstest": { "branch": "main", "commit": "78de83604052c5ff6a6bddf579f4f646ee8254c7" },
"nvim-autopairs": { "branch": "master", "commit": "59bce2eef357189c3305e25bc6dd2d138c1683f5" },
"nvim-cmp": { "branch": "main", "commit": "da88697d7f45d16852c6b2769dc52387d1ddc45f" },
"nvim-dap": { "branch": "master", "commit": "a9d8cb68ee7184111dc66156c4a2ebabfbe01bc5" },
"mason.nvim": { "branch": "main", "commit": "2a6940af80375532e5e9e7c1f2fc6319a1b7a69d" },
"neotest": { "branch": "master", "commit": "27bf921498043f7ecd821d6db68d05de244bbd02" },
"neotest-golang": { "branch": "main", "commit": "05cd7bf89a146cf1fa2848a9fe277a1e68a3a51d" },
"neotest-vstest": { "branch": "main", "commit": "de30c7978937d07e6d29ab7807a00fad1c61120b" },
"nvim-autopairs": { "branch": "master", "commit": "3172f40c16563db871a58f20d205c710ad782311" },
"nvim-cmp": { "branch": "main", "commit": "2ffe79f1f021def8dd1fcd81deb16f1bb0d989f3" },
"nvim-dap": { "branch": "master", "commit": "cfa2d58f4537aca6ca83e2de1a0d9f1491121264" },
"nvim-dap-go": { "branch": "main", "commit": "b4421153ead5d726603b02743ea40cf26a51ed5f" },
"nvim-dap-ui": { "branch": "master", "commit": "cf91d5e2d07c72903d052f5207511bf7ecdb7122" },
"nvim-dap-ui": { "branch": "master", "commit": "cc9dd33aade7f20bae414d0cba163bc60d4d4b43" },
"nvim-dap-virtual-text": { "branch": "master", "commit": "fbdb48c2ed45f4a8293d0d483f7730d24467ccb6" },
"nvim-lint": { "branch": "master", "commit": "606b823a57b027502a9ae00978ebf4f5d5158098" },
"nvim-lsp-file-operations": { "branch": "master", "commit": "b9c795d3973e8eec22706af14959bc60c579e771" },
"nvim-lspconfig": { "branch": "master", "commit": "702f69fb167e9119f14adc4dfd4fcadf4d1b07a0" },
"nvim-nio": { "branch": "master", "commit": "21f5324bfac14e22ba26553caf69ec76ae8a7662" },
"nvim-surround": { "branch": "main", "commit": "61319d4bd1c5e336e197defa15bd104c51f0fb29" },
"nvim-tree.lua": { "branch": "master", "commit": "e16cd38962bc40c22a51ee004aa4f43726d74a16" },
"nvim-treesitter": { "branch": "master", "commit": "42fc28ba918343ebfd5565147a42a26580579482" },
"nvim-ts-autotag": { "branch": "main", "commit": "8e1c0a389f20bf7f5b0dd0e00306c1247bda2595" },
"nvim-ts-context-commentstring": { "branch": "main", "commit": "1b212c2eee76d787bbea6aa5e92a2b534e7b4f8f" },
"nvim-web-devicons": { "branch": "master", "commit": "d7462543c9e366c0d196c7f67a945eaaf5d99414" },
"plenary.nvim": { "branch": "master", "commit": "b9fd5226c2f76c951fc8ed5923d85e4de065e509" },
"nvim-lint": { "branch": "master", "commit": "f6230a5c06ba59e6059c14637f1dbe29a7978b9b" },
"nvim-lsp-file-operations": { "branch": "master", "commit": "ba0c27cd0dbee7b421ba7b31a4cb68770032b9fd" },
"nvim-lspconfig": { "branch": "master", "commit": "45a3a444b710511c39abca3b60bb6e23a21e3de5" },
"nvim-nio": { "branch": "master", "commit": "edcc181a875301dd21840189aa2f2f9ad69fc172" },
"nvim-surround": { "branch": "main", "commit": "2e93e154de9ff326def6480a4358bfc149d5da2c" },
"nvim-tree.lua": { "branch": "master", "commit": "355bcc85a48f45b3e728219f10b880d569928965" },
"nvim-treesitter": { "branch": "main", "commit": "ca581c3436fc2b236847f5b739ebc263739e5ca6" },
"nvim-ts-autotag": { "branch": "main", "commit": "d7220b55e16ed3c04e88086256def5d282429493" },
"nvim-ts-context-commentstring": { "branch": "main", "commit": "6141a40173c6efa98242dc951ed4b6f892c97027" },
"nvim-web-devicons": { "branch": "master", "commit": "ec309a0eaff6ea967e58c275996155ab5c16938d" },
"plenary.nvim": { "branch": "master", "commit": "74b06c6c75e4eeb3108ec01852001636d85a932b" },
"substitute.nvim": { "branch": "main", "commit": "0d2077398552f069abccbd964a26dd7cd26882cd" },
"telescope-fzf-native.nvim": { "branch": "main", "commit": "6fea601bd2b694c6f2ae08a6c6fab14930c60e2c" },
"telescope.nvim": { "branch": "master", "commit": "5255aa27c422de944791318024167ad5d40aad20" },
"telescope-fzf-native.nvim": { "branch": "main", "commit": "b25b749b9db64d375d782094e2b9dce53ad53a40" },
"telescope.nvim": { "branch": "master", "commit": "40aedd8a68c78a656a10a8d62d80c54af59420fb" },
"todo-comments.nvim": { "branch": "main", "commit": "31e3c38ce9b29781e4422fc0322eb0a21f4e8668" },
"tokyonight.nvim": { "branch": "main", "commit": "5da1b76e64daf4c5d410f06bcb6b9cb640da7dfd" },
"tokyonight.nvim": { "branch": "main", "commit": "cdc07ac78467a233fd62c493de29a17e0cf2b2b6" },
"trouble.nvim": { "branch": "main", "commit": "bd67efe408d4816e25e8491cc5ad4088e708a69a" },
"vim-maximizer": { "branch": "master", "commit": "2e54952fe91e140a2e69f35f22131219fcd9c5f1" },
"vim-tmux-navigator": { "branch": "master", "commit": "e41c431a0c7b7388ae7ba341f01a0d217eb3a432" },
Expand Down
1 change: 1 addition & 0 deletions lua/simonkdev/lazy/lsp/mason.lua
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ return {
"stylua",
"eslint_d",
"goimports",
"tree-sitter-cli", -- nvim-treesitter compiles parsers with it (treesitter.lua)
},
})
end,
Expand Down
3 changes: 1 addition & 2 deletions lua/simonkdev/lazy/testing.lua
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@ return {
"antoinemadec/FixCursorHold.nvim",
"nvim-treesitter/nvim-treesitter",
"Nsidorenco/neotest-vstest",
-- v2 requires nvim-treesitter's main branch; this config is still on master (see treesitter.lua).
{ "fredrikaverpil/neotest-golang", version = "^1" },
{ "fredrikaverpil/neotest-golang", version = "^2" },
},
config = function()
require("neotest").setup({
Expand Down
124 changes: 67 additions & 57 deletions lua/simonkdev/lazy/treesitter.lua
Original file line number Diff line number Diff line change
@@ -1,62 +1,72 @@
-- nvim-treesitter's main branch only installs parsers and queries. Highlighting is Neovim's own and has to be
-- started per buffer (FileType autocmd below). Compiling parsers needs the tree-sitter CLI and a C compiler;
-- Mason installs the CLI (lsp/mason.lua).
return {
"nvim-treesitter/nvim-treesitter",
-- upstream's default branch is now the incompatible `main` rewrite (no nvim-treesitter.configs)
branch = "master",
event = { "BufReadPre", "BufNewFile" },
build = ":TSUpdate",
dependencies = {
"windwp/nvim-ts-autotag",
},
-- Use the 'opts' table for a more declarative setup
opts = {
ensure_installed = {
"c",
"c_sharp",
"lua",
"vim",
"vimdoc",
"javascript",
"typescript",
"python",
"go",
"gomod",
"gosum",
"gowork",
"css",
"html",
"json",
"yaml",
"xml",
"powershell",
"java",
"gitignore",
"dockerfile",
"tsx",
"markdown",
"markdown_inline",
"query",
},
highlight = {
enable = true,
},
indent = {
enable = true,
},
autotag = {
enable = true,
},
incremental_selection = {
enable = true,
keymaps = {
init_selection = "<C-space>",
node_incremental = "<C-space>",
scope_incremental = false,
node_decremental = "<bs>",
{
"nvim-treesitter/nvim-treesitter",
branch = "main",
lazy = false, -- doesn't support lazy-loading
build = ":TSUpdate",
opts = {
ensure_installed = {
"c",
"c_sharp",
"lua",
"vim",
"vimdoc",
"javascript",
"typescript",
"python",
"go",
"gomod",
"gosum",
"gowork",
"css",
"html",
"json",
"yaml",
"xml",
"powershell",
"java",
"gitignore",
"dockerfile",
"tsx",
"markdown",
"markdown_inline",
"query",
},
},
config = function(_, opts)
local ts = require("nvim-treesitter")

-- A no-op for installed parsers. On a fresh machine the CLI shows up once Mason has installed it.
local function install()
if vim.fn.executable("tree-sitter") == 1 then
ts.install(opts.ensure_installed)
end
end
install()
vim.api.nvim_create_autocmd("User", { pattern = "MasonToolsUpdateCompleted", callback = install })

vim.api.nvim_create_autocmd("FileType", {
group = vim.api.nvim_create_augroup("simonkdev_treesitter", { clear = true }),
callback = function(args)
-- Fails when there's no parser for the filetype; those keep regex highlighting.
if pcall(vim.treesitter.start, args.buf) then
vim.bo[args.buf].indentexpr = "v:lua.require'nvim-treesitter'.indentexpr()"
end
end,
})

-- Neovim 0.12 selects treesitter nodes with `an` (outward) and `in` (inward) in visual mode.
vim.keymap.set("n", "<C-space>", "van", { remap = true, desc = "Select treesitter node" })
vim.keymap.set("x", "<C-space>", "an", { remap = true, desc = "Expand selection" })
vim.keymap.set("x", "<bs>", "in", { remap = true, desc = "Shrink selection" })
end,
},
{
"windwp/nvim-ts-autotag",
event = { "BufReadPre", "BufNewFile" },
opts = {},
},
-- Add a config function to ensure autotag is enabled
config = function(_, opts)
require("nvim-treesitter.configs").setup(opts)
end,
}
4 changes: 4 additions & 0 deletions lua/simonkdev/lazy_init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ if not (vim.uv or vim.loop).fs_stat(lazypath) then
end
vim.opt.rtp:prepend(lazypath)

-- lazy.nvim puts stdpath("data")/site on the runtimepath, but Neovim drops it if it doesn't exist yet.
-- nvim-treesitter installs parsers there, so on a fresh machine they'd only load after a restart.
vim.fn.mkdir(vim.fn.stdpath("data") .. "/site", "p")

require("lazy").setup({
{ import = "simonkdev.lazy" },
{ import = "simonkdev.lazy.lsp" },
Expand Down
Loading
Loading