From c1f484bc87c16eb2d3ed0bacf2613f74dbde770d Mon Sep 17 00:00:00 2001 From: Michael Barton Date: Fri, 27 Feb 2026 15:01:54 -0800 Subject: [PATCH] fix(nvim): work around R.nvim cwd change on rout parser build failure R.nvim's check_rout_parser() changes directory into resources/tree-sitter-rout to build the rout parser, but when the build fails the early return statements skip the chdir(cwdir) restore call, leaving nvim stuck in the plugin directory. The build fails because the tree-sitter-rout submodule gitlink is absent from older pinned commits so grammar.js is never present. Upstream bug: https://github.com/R-nvim/R.nvim/issues/466 Changes: - nvim/lua/plugins/language.lua: add lazy.nvim build function that clones tree-sitter-rout directly if grammar.js is missing, so the parser build succeeds and cwd is properly restored - ansible/tasks/neovim.yml: add provisioning task that does the same clone for fresh machine setup, idempotent via grammar.js existence check - Makefile: add nvim-check target that boots nvim headlessly across R/py/lua/md filetypes and fails on any startup errors or warnings; add to all: chain Both workarounds include TODO markers referencing the upstream issue to remove once R-nvim/R.nvim#466 is merged and R.nvim is updated past the fix commit. Made-with: Cursor --- Makefile | 32 +++++++++++++++++++++++++++++++- ansible/tasks/neovim.yml | 13 +++++++++++++ nvim/lua/plugins/language.lua | 18 ++++++++++++++++++ 3 files changed, 62 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 3fd83fe..2a8ebbc 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -all: fmt apply +all: fmt apply nvim-check apply: uv run ansible-playbook -i ~/.dotfiles/ansible/inventory.ini ~/.dotfiles/ansible/dotfiles.yml @@ -13,3 +13,33 @@ fmt_check: nvim-health: nvim --headless "+checkhealth" +qa + +# Smoke test: boot nvim with representative filetypes and fail on startup errors/warnings. +# Catches plugin misconfigurations (e.g. missing tree-sitter parsers, broken submodules) +# that produce warnings in :messages but pass :checkhealth. +NVIM_CHECK_FILETYPES := R py lua md +NVIM_CHECK_TMPDIR := /tmp/_nvim_check +NVIM_CHECK_TIMEOUT := 30 + +nvim-check: + @mkdir -p $(NVIM_CHECK_TMPDIR) + @fail=0; \ + for ft in $(NVIM_CHECK_FILETYPES); do \ + tmpfile="$(NVIM_CHECK_TMPDIR)/test.$$ft"; \ + msgfile="$(NVIM_CHECK_TMPDIR)/messages_$$ft.txt"; \ + touch "$$tmpfile"; \ + timeout $(NVIM_CHECK_TIMEOUT) nvim --headless \ + +"edit $$tmpfile" \ + +"sleep 3" \ + +"redir! > $$msgfile | silent messages | redir END" \ + +"qall!" 2>/dev/null || true; \ + if grep -qiE '(error|warning)' "$$msgfile" 2>/dev/null; then \ + echo "FAIL [$$ft]: startup errors detected"; \ + cat "$$msgfile"; \ + fail=1; \ + else \ + echo "PASS [$$ft]: clean startup"; \ + fi; \ + done; \ + rm -rf $(NVIM_CHECK_TMPDIR); \ + [ "$$fail" -eq 0 ] || (echo "nvim-check: some filetypes had errors" && exit 1) diff --git a/ansible/tasks/neovim.yml b/ansible/tasks/neovim.yml index 76f91ae..9f80556 100644 --- a/ansible/tasks/neovim.yml +++ b/ansible/tasks/neovim.yml @@ -46,3 +46,16 @@ - "+qa" tags: - nvim + +- name: Clone tree-sitter-rout parser source into R.nvim resources + # TODO: Remove once https://github.com/R-nvim/R.nvim/issues/466 is fixed and merged -- see + # nvim/lua/plugins/language.lua for full context. Idempotent: skipped if grammar.js exists. + ansible.builtin.shell: | + target="{{ ansible_env.HOME }}/.local/share/nvim/lazy/R.nvim/resources/tree-sitter-rout" + grammar="$target/grammar.js" + if [ ! -f "$grammar" ]; then + rm -rf "$target" + git clone https://github.com/R-nvim/tree-sitter-rout "$target" + fi + tags: + - nvim diff --git a/nvim/lua/plugins/language.lua b/nvim/lua/plugins/language.lua index ae5841a..9df596b 100644 --- a/nvim/lua/plugins/language.lua +++ b/nvim/lua/plugins/language.lua @@ -1,4 +1,22 @@ return { + { + "R-nvim/R.nvim", + -- TODO: Remove this build workaround once https://github.com/R-nvim/R.nvim/issues/466 is + -- fixed and merged to main, then advance past that commit with `:Lazy update R.nvim`. + -- The upstream bug: check_rout_parser() calls vim.uv.chdir() into resources/tree-sitter-rout + -- but early `return` on build failure skips the chdir(cwdir) restore, leaving nvim stuck in + -- the plugin directory. Root cause is that the tree-sitter-rout submodule gitlink is absent + -- from older pinned commits, so `git submodule update` is a no-op and grammar.js is missing. + -- Workaround: clone the source directly so the build succeeds and cwd is properly restored. + -- Removal check: delete this block, run `make nvim-check`, confirm PASS [R]: clean startup. + build = function() + local target = vim.fn.stdpath("data") .. "/lazy/R.nvim/resources/tree-sitter-rout" + if vim.fn.filereadable(target .. "/grammar.js") == 0 then + vim.fn.system({ "rm", "-rf", target }) + vim.fn.system({ "git", "clone", "https://github.com/R-nvim/tree-sitter-rout", target }) + end + end, + }, { "nvim-treesitter/nvim-treesitter", opts = {