fix(ftplugin): load on .wiki buffers without manual filetype override
CI / cargo fmt --check (push) Successful in 35s
CI / cargo clippy (push) Successful in 1m12s
CI / cargo test (push) Successful in 1m26s

Three reasons the plugin wasn't activating on `nvim --clean -u init.lua
foo.wiki`:

1. **File-name mismatch.** Vim's filetype-plugin runtime looks for
   `ftplugin/<filetype>.vim` matching the *filetype name*. Our
   filetype is `vimwiki` (per `ftdetect`) but the file was named
   `ftplugin/nuwiki.vim` — so `:runtime! ftplugin/vimwiki.vim` from
   the built-in FileType autocmd never found it, and none of the
   `:Vimwiki*` / `:Nuwiki*` commands got defined. Same wart on the
   syntax side. Renamed:
   - `ftplugin/nuwiki.vim`  → `ftplugin/vimwiki.vim`
   - `syntax/nuwiki.vim`    → `syntax/vimwiki.vim`

2. **`setfiletype` deferred to Neovim's bundled rule.** Neovim ships
   a default `*.wiki → mediawiki` rule via `vim.filetype.add`, and
   `:setfiletype vimwiki` is a no-op once a filetype has been set.
   - `ftdetect/nuwiki.vim` now uses `set filetype=vimwiki` (force).
   - `lua/nuwiki/init.lua`'s `setup()` also calls
     `vim.filetype.add({ extension = { wiki = 'vimwiki', ... } })`
     so the modern table-based detection picks us before the
     bundled rule fires. Honours `config.options.file_extension`
     so a user with a custom extension gets covered automatically.

3. **`foldmethod`/`foldexpr` are window-local options.**
   `ftplugin.lua` was setting them with `nvim_set_option_value({ buf
   = bufnr })`, which threw `'buf' cannot be passed for window-local
   option 'foldmethod'` and aborted the rest of the per-buffer
   attach. Switched to `vim.opt_local.*` (window-aware), applied on
   the current window when the ftplugin fires, and re-applied via a
   `BufWinEnter` autocmd so `:split` / `:vsplit` keep the fold mode.

Verified end-to-end with:

  nvim --clean -u init.lua sample.wiki
  → filetype = vimwiki
  → :VimwikiTOC, :NuwikiIndex, … all defined
  → foldmethod = expr, foldexpr = v:lua.vim.lsp.foldexpr()
  → ftdetect, plugin, ftplugin, syntax all in :scriptnames

Total 377 tests still pass.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-11 22:16:57 +00:00
parent cf94f99d3c
commit 09b9bd98a3
5 changed files with 46 additions and 28 deletions
+6 -1
View File
@@ -3,5 +3,10 @@
" Users who configure a custom `file_extension` in setup() should add their " Users who configure a custom `file_extension` in setup() should add their
" own `:autocmd BufRead,BufNewFile *.myext setfiletype vimwiki` mapping; " own `:autocmd BufRead,BufNewFile *.myext setfiletype vimwiki` mapping;
" we hardcode `.wiki` since ftdetect runs before any user setup() call. " we hardcode `.wiki` since ftdetect runs before any user setup() call.
"
" Use `set filetype=…` (not `setfiletype`) so we override Neovim's bundled
" `*.wiki → mediawiki` rule. Users who actually want MediaWiki on .wiki
" can override this with their own autocmd at a later runtimepath entry,
" or with `vim.filetype.add` in Neovim.
autocmd! BufRead,BufNewFile *.wiki setfiletype vimwiki autocmd! BufRead,BufNewFile *.wiki set filetype=vimwiki
+25 -26
View File
@@ -9,34 +9,33 @@ local function setup_folding(bufnr, folding_mode)
if folding_mode == 'off' then if folding_mode == 'off' then
return return
end end
if folding_mode == 'expr' then -- `foldmethod` / `foldexpr` / `foldtext` are window-local options.
vim.api.nvim_set_option_value('foldmethod', 'expr', { buf = bufnr }) -- The ftplugin runs during BufRead → FileType, by which time the
vim.api.nvim_set_option_value( -- buffer is displayed in the current window. `vim.opt_local` writes
'foldexpr', -- to the current window's view of the option.
'v:lua.require("nuwiki.folding").expr()', local apply = function()
{ buf = bufnr } if folding_mode == 'expr'
) or not (vim.fn.has('nvim-0.11') == 1 and vim.lsp.foldexpr)
vim.api.nvim_set_option_value( then
'foldtext', vim.opt_local.foldmethod = 'expr'
'v:lua.require("nuwiki.folding").foldtext()', vim.opt_local.foldexpr = 'v:lua.require("nuwiki.folding").expr()'
{ buf = bufnr } vim.opt_local.foldtext = 'v:lua.require("nuwiki.folding").foldtext()'
)
return
end
-- folding_mode == 'lsp' (default): rely on the server's
-- `foldingRange` capability. Neovim 0.11+ enables it automatically
-- via `vim.lsp.foldexpr`. Older versions get the regex fallback.
if vim.fn.has('nvim-0.11') == 1 and vim.lsp.foldexpr then
vim.api.nvim_set_option_value('foldmethod', 'expr', { buf = bufnr })
vim.api.nvim_set_option_value(
'foldexpr',
'v:lua.vim.lsp.foldexpr()',
{ buf = bufnr }
)
else else
-- Pre-0.11 — degrade to the regex fallback so users still get folds. -- LSP-backed folding via Neovim 0.11+'s built-in foldexpr.
setup_folding(bufnr, 'expr') vim.opt_local.foldmethod = 'expr'
vim.opt_local.foldexpr = 'v:lua.vim.lsp.foldexpr()'
end end
end
-- Set on the current window first (the one that triggered the
-- ftplugin). Also re-apply on any future split that views this
-- buffer, so `<C-w>v` / `:split` preserves the fold method.
apply()
vim.api.nvim_create_autocmd('BufWinEnter', {
buffer = bufnr,
group = vim.api.nvim_create_augroup('nuwiki_folding_' .. bufnr, { clear = true }),
callback = apply,
})
end end
function M.attach(bufnr) function M.attach(bufnr)
+14
View File
@@ -15,6 +15,20 @@ local lsp = require('nuwiki.lsp')
function M.setup(opts) function M.setup(opts)
config.apply(opts or {}) config.apply(opts or {})
-- Neovim 0.7+ resolves filetypes via `vim.filetype.match` before any
-- `ftdetect/*.vim` autocmd fires, and its bundled rule for `*.wiki`
-- returns `mediawiki`. Register an authoritative rule here so this
-- plugin's filetype (vimwiki) wins.
if vim.filetype and vim.filetype.add then
local extensions = { wiki = 'vimwiki' }
local ext = (config.options.file_extension or '.wiki'):gsub('^%.', '')
if ext ~= 'wiki' and ext ~= '' then
extensions[ext] = 'vimwiki'
end
vim.filetype.add({ extension = extensions })
end
lsp.register() lsp.register()
end end