Files
nuwiki/development/vimwiki-gap.md
T
gffranco 624bccbe50
CI / cargo fmt --check (push) Successful in 24s
CI / cargo clippy (push) Successful in 21s
CI / cargo test (push) Successful in 28s
CI / editor keymaps (push) Successful in 1m31s
fix(client): honor count on Neovim Index; log third re-audit findings
Third audit pass (config/mappings/commands vs vimwiki master) confirmed all
recent range/bang/visual and diary-week work is present and correct in both
clients, with no regressions, and that Neovim does bind the text objects.

It surfaced one real oversight: the Neovim Vimwiki/NuwikiIndex commands still
read vim.v.count (always 0 in command context) instead of <count> — the same
bug the TabIndex fix addressed, but Index was missed. Fixed both to <count>,
so :2NuwikiIndex now opens wiki 2.

Gap doc updated: new open item (VimwikiSplitLink/VSplitLink missing upstream
-nargs=*), mouse-maps-opt-in recorded as an intentional divergence, and the
third-pass summary. Suites green — nvim 274, vim 266+18.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-31 18:24:22 +00:00

19 KiB

vimwiki → nuwiki Parity Gaps

Tracking document for closing the gap between nuwiki and the original vimwiki plugin across configuration, commands, and key mappings.

Source of truth for upstream: vimwiki masterautoload/vimwiki/vars.vim (option defaults), plugin/vimwiki.vim + ftplugin/vimwiki.vim (commands/mappings), doc/vimwiki.txt (prose).

Audited 2026-05-31. Check items off as they land. Each row cites the nuwiki fix site.


P1 — Core workflow gaps (fix first)

  • Vim client split/tab link-follow commandsVimwikiSplitLink, VimwikiVSplitLink, VimwikiGoBackLink, VimwikiTabnewLink, VimwikiTabDropLink exist only in the Neovim branch. Vim users lose split-window link following and back-navigation. Fix: ftplugin/vimwiki.vim (Vim branch) — commands added + :Nuwiki* aliases; follow_link_drop() helper in autoload/nuwiki/commands.vim; true :tab drop tab-reuse wired in both clients (lua/nuwiki/commands.lua open_uri 'tabdrop' case); <C-S-CR> repointed to tab-drop.
  • gl<symbol> change-symbol mappings — upstream's one-key bullet/number symbol change (gl* gl# gl- gl1 gla gli … plus gL…) has no nuwiki keymap; only :…ChangeSymbol* commands exist. Fix: added normal-mode gl{-,*,#,1,i,I,a,A} (item) + gL… (whole list) in lua/nuwiki/keymaps.lua lists group and ftplugin/vimwiki.vim Vim-branch lists block, wired to the existing list_change_symbol. 1) stays command-only (upstream shadows it with 1.); normal-mode only (server acts on cursor item / whole list, not a visual range).
  • gl<Space> / gL<Space> semantics diverge — upstream = remove checkbox from item / list siblings; nuwiki rebound to remove done items. Same keys, different effect (parity trap). Fix: bound bare gl/gL to remove-checkbox-item / -in-list for exact upstream parity (lua/nuwiki/keymaps.lua lists block, ftplugin/vimwiki.vim Vim-branch lists block); they share the gl… prefix so they fire after timeoutlen, just like upstream. Remove-done is now command-only: :NuwikiRemoveDone (current list) gained a -bang so :NuwikiRemoveDone! reaches the whole-buffer sweep that gL<Space> previously held (the only prior entry point). Normal-mode only.

Regressions (reported by users — verify, then fix)

  • <CR> link-follow: wrong window placement + no create-on-follow on the Vim clients — two related Vim-branch bugs (Neovim path was already correct): (a) on coc.nvim, <CR> opened the target in a new tab instead of the current window; (b) on both vim-lsp and coc, <CR> on a link to a not-yet-created page failed to open/create it. Root cause: the Vim follow path delegated to the LSP client's jump UI (:LspDefinition / CocActionAsync('jumpDefinition')). Those fetch the target's text before jumping — vim-lsp readfile()s it for the quickfix entry (autoload/lsp/utils/location.vim), which throws E484 for a missing file and aborts the jump (→ no create-on-follow); coc, lacking an explicit open command, fell back to the user's coc.preferences.jumpCommand (→ new tab). The server itself was correct throughout — verified over JSON-RPC that textDocument/definition returns a synthesised location for missing pages and resolves existing links. Fix: stop delegating. nuwiki#commands#follow_link_or_create() / follow_link_drop() now resolve textDocument/definition directly and open the URI ourselves via a shared s:open_definition(open_cmd) helper (autoload/nuwiki/commands.vim) — :edit for <CR>, tab drop for <C-S-CR>. :edit opens a buffer for a missing path (save creates it, matching vimwiki) and gives exact current-window placement regardless of the user's coc jumpCommand. Covered by cr.follow_opens_missing_page_in_current_window in development/tests/test-keymaps-vim.vim; manually reproducible via development/start-vim.sh (vim-lsp) and development/start-vim-coc.sh (coc).
  • coc.nvim reported valid links as broken / couldn't resolve — only via the new development/start-vim-coc.sh launcher: its generated coc-settings.json registered the server with command/filetypes but no initializationOptions, so wiki_root never reached the server and it resolved links against its default (~/vimwiki). Fix: the launcher now emits initializationOptions and settings.nuwiki mirroring the vim-lsp client (autoload/nuwiki/lsp.vim s:settings()). Verified with a headless coc.nvim run: [[Notes]] resolves, only genuinely-missing links warn. (Shipped plugin only — no production code change; coc users configure their own coc-settings.json per the README snippet.)

P2 — Moderate (real users hit these)

  • <Leader>w<Leader>t collision — upstream = today-in-new-tab; nuwiki bound both <Leader>w<Leader>t and <Leader>w<Leader>m to tomorrow's diary. Fix: <Leader>w<Leader>t now calls diary_today_tab (today in a new tab), <Leader>w<Leader>m stays tomorrow — exact upstream parity (lua/nuwiki/keymaps.lua, ftplugin/vimwiki.vim; docs + README updated). Covered by diary.leader_t_opens_today_in_tab / diary.leader_m_opens_tomorrow.
  • Generated-section captions hardcodedtoc_header / toc_header_level, links_header, tags_header (+levels). Fix: crates/nuwiki-lsp/src/config.rs + server TOC/generate renderers.
  • On-save autoregen familyauto_diary_index, auto_generate_links, auto_generate_tags, auto_tags (only auto_toc / auto_export exist). Fix: config.rs RawWiki/WikiConfig + the didSave path.
  • listsym_rejected — rejected glyph - is hardcoded. Fix: config.rs WikiConfig.
  • custom_wiki2html (+_args) and base_url — external HTML converter hook + export URL prefix. Fix: config.rs HtmlConfig.
  • map_prefix<Leader>w hardcoded across the map layer. Fix: plugin/nuwiki.vim, lua/nuwiki/keymaps.lua, ftplugin/vimwiki.vim.
  • <M-CR> badd-link — was mouse-only (<MiddleMouse>) / command-only (:VimwikiBaddLink); upstream binds <M-CR>VimwikiBaddLink (confirmed against upstream ftplugin/vimwiki.vim). Fix: added normal-mode <M-CR>badd_link in the links group of both clients (lua/nuwiki/keymaps.lua, ftplugin/vimwiki.vim; docs + README updated). Covered by map[n].<M-CR> in both keymap harnesses.
  • diary_caption_level default divergence — nuwiki defaulted to 1, upstream 0. Fix: wiki_defaults() in crates/nuwiki-lsp/src/config.rs now defaults diary_caption_level: 0 (year captions top-level, months one below), still per-wiki overridable. Test defaults_carry_vimwiki_per_wiki_keys updated.
  • diary_start_week_day — removed in c63ec67 (weekly diary hardwired to ISO-Monday). Restored as a configurable choice so migrators keep upstream behaviour while new wikis can use ISO weeks. New per-wiki key diary_weekly_style: iso (default — YYYY-Www, Monday-based, nuwiki's original) or date/vimwiki (YYYY-MM-DD of the week-start day, upstream parity, honouring the restored diary_start_week_day = monday..sunday). Impl: nuwiki_core::date::{WeeklyStyle, WeekStart, DiaryCalendar} own the today/next/prev logic; WikiConfig::diary_calendar() builds it from config; the diary commands (commands.rs diary_open_relative + next/prev pivot) use it. Defaults keep existing nuwiki weekly files working (no breaking change). Covered by calendar tests in crates/nuwiki-core/tests/diary.rs and the config round-trip in crates/nuwiki-lsp/tests/index_and_config.rs.

P3 — Niche / low impact

Commands

  • VimwikiVar — config-var get/set introspection. Fix: plugin/nuwiki.vim.
  • VimwikiShowVersion — print version (trivial). Fix: plugin/nuwiki.vim.
  • VimwikiReturn — no Ex-command (mapping-driven only). Fix: ftplugin/vimwiki.vim.
  • VimwikiTableAlignQ vs AlignW collapsed to one table_aligngqq (align) vs gww (align w/o resize) distinction lost.
  • VimwikiTable is -nargs=1 vs upstream -nargs=* (can't pass cols+rows).
  • VimwikiListChangeLvl is -nargs=? vs upstream -range -nargs=+.
  • VimwikiRebuildTags -bang ("rebuild all") — :…RebuildTags! now passes { all: true }; the server (tags_rebuild) re-indexes every configured wiki (via wikis_snapshot()) instead of just the current one. -bang added to all four command defs.
  • :VimwikiSearch / VWS uses lvimgrep, not vimwiki's search engine.
  • VimwikiIndex family is buffer-local in nuwiki (upstream defines globally in plugin/); only :…UISelect is a global entry point.
  • VimwikiColorize / NuwikiColorize drop their argument in the Neovim branch — both are -nargs=1, but the Neovim defs called colorize() with no <q-args> (ftplugin/vimwiki.vim:445,517) while the Vim branch passes it. The color name was silently ignored under Neovim (real bug, not just parity). Fix: Neovim command defs now pass <q-args>. While verifying, found a second bug: colorize() inferred visual-vs-normal from vim.fn.visualmode(), which returns the last session visual mode with stale '</'> marks — so the normal-mode command wrapped a leftover selection instead of the cword. colorize(color, visual) now takes an explicit visual flag; the command and normal mapping always wrap the cword. Third bug: the commands were not -range, so selecting text and running :VimwikiColorize (which Vim turns into :'<,'>VimwikiColorize) raised E481: No range allowed. All four command defs are now -range and pass the range to the handler — a ranged (visual) invocation wraps the '</'> selection on both clients; the x-mode <Leader>wc mapping passes the visual flag directly. Covered by cmd.VimwikiColorize_uses_arg, cmd.Colorize_ignores_stale_visual_selection, colorize.visual_wraps_selection, cmd.Colorize_range_wraps_selection in test-keymaps.lua and colorize.{command_wraps_cword,visual_wraps_selection, ranged_command_no_error} in test-keymaps-vim.vim.
  • Colour spans aren't concealed — a colorized word shows the literal <span style="color:…">…</span> markup instead of just the coloured text. Fix: autoload/nuwiki/colors.vim nuwiki#colors#refresh() scans the buffer and defines, per colour, a syntax region that conceals the <span …>/</span> tags (concealends) and paints the wrapped text in the span's actual colour (guifg/ctermfg). Wired from the syntax file (initial + on :colorscheme reload), an ftplugin TextChanged autocmd, and directly from colorize() for immediate effect. The LSP @vimwikiColor token no longer links to Constant so it doesn't override the real colour on the concealed text in Neovim. Works in Vim, coc, and Neovim (pure syntax + :highlight, no LSP needed). Covered by colorize.conceal_hides_tags_shows_text (both harnesses) and colorize.command_conceals_immediately (test-keymaps-vim.vim).
  • VimwikiTableMoveColumn{Left,Right} dispatch to different backing names per client — converged: the Vim-branch commands now call nuwiki#commands#table_move_column_left/right (existing aliases over the table_move_left/right impls), matching the Neovim branch.
  • NuwikiTabIndex lacks -count in the Neovim branch — added -count; also switched the Neovim Index/TabIndex family (Vimwiki/NuwikiTabIndex and Vimwiki/NuwikiIndex) from vim.v.count (always 0 in command context) to <count>, so a :2NuwikiIndex / :3NuwikiTabIndex count is now honored. (The Index half was caught by the 2026-05-31 second re-audit and fixed then.)
  • VimwikiToggleListItem / Increment / DecrementListItem -range — all three (both branches) are now -range; the client loops the per-line op over [<line1>, <line2>] (toggle_list_item_range / list_cycle_symbol_range). The server edits are version-less single-line, so each line's edit applies independently — no server protocol change needed. Covered by cmd.toggle_list_item_range in test-keymaps.lua.
  • Diary-note family lacks -count (new, 2026-05-31 re-audit) — upstream's :Vimwiki{Make,TabMake,MakeYesterday,MakeTomorrow}DiaryNote carry -count=0 (the count selects the wiki number); nuwiki's diary-note commands declare no count in either branch, and Index/TabIndex use bare -count vs upstream -count=0. Fix: ftplugin/vimwiki.vim diary block (both branches) + thread the count into diary_today/yesterday/tomorrow.
  • No -complete= specs (new) — upstream attaches command-line completion to VimwikiGoto (links), VimwikiRenameFile (files), VimwikiColorize (colours), and the tag commands. nuwiki defines none, so <Tab> completion of page / tag / colour names at the : line is unavailable. Fix: ftplugin/vimwiki.vim (both branches) — VimL completers or LSP-backed.
  • Minor command-attribute gaps (new) — all now real, not cosmetic: VimwikiNormalizeLink is -nargs=? and with 1 wraps the '</'> selection (wrap_visual_as_wikilink, both clients; the x-mode + passes it too); VimwikiCheckLinks is -range and a ranged invocation filters the report to the current buffer's selected lines; VimwikiColorize -nargs=1-nargs=* (bare :VimwikiColorize prompts). Covered by normalize.visual_wraps_selection (vim) / cmd.normalize_link_visual_wraps_selection (nvim).
  • VimwikiSplitLink / VimwikiVSplitLink lack -nargs=* (new, 2026-05-31 third re-audit) — upstream both take an optional target link to follow in the split; nuwiki's defs (both branches) take no args, so you can't pass a link to the split-follow. Low impact (the arg path is rarely used). Fix: ftplugin/vimwiki.vim both branches + thread a target through follow_link_or_create.

Config

  • auto_header — auto H1-from-filename on new page (server-side).
  • create_link — toggle to suppress link-target creation.
  • dir_link — index file to open when following a directory link.
  • auto_chdir:cd into wiki root on open (client-side).
  • bullet_types / cycle_bullets — custom bullet glyphs + wrap-around.
  • commentstring ('%%%s') — comment toggling/text-objects.
  • color_tag_templatecolor_dic present; template regex missing.
  • rss_max_items / rss_name:Rss output hardcoded. Fix: HtmlConfig.
  • emoji_enable — emoji substitution.
  • html_header_numbering (+_sym) — numbered HTML headers.
  • valid_html_tags — allowed inline HTML tags in export.
  • generated_links_caption, toc_link_format, markdown_link_ext.
  • list_ignore_newline / text_ignore_newline — export newline handling.

Mappings

  • Visual <CR> normalize-link (visual + covers the same intent).
  • Insert <S-CR> multiline list item.
  • gLH / gLL / gLR — upstream binds these as case-variant aliases of gLh / gLl / gLr (same actions: dedent / indent whole item, renumber all lists; upstream ftplugin/vimwiki.vim:553,555,561). nuwiki has the lowercase forms but not the uppercase-suffix aliases. Cosmetic — same effect, redundant keys.
  • <D-CR> (Cmd+Return) tab-drop alias (new, 2026-05-31 re-audit) — added <D-CR>follow_link_drop alongside <C-S-CR> in both clients (lua/nuwiki/keymaps.lua, ftplugin/vimwiki.vim); docs updated. Covered by map[n].<D-CR> in both harnesses.
  • <Leader>w<Leader>m missing from the Vim global map block (new)plugin/nuwiki.vim's global family now binds <Leader>w<Leader>m (tomorrow) and <Leader>w<Leader>t opens today in a new tab (was the same collision the buffer-local maps had). Covered by map[n].<Leader>w<Leader>m in both harnesses.

Intentional divergences (no action — architectural)

These upstream options have no nuwiki equivalent by design, because nuwiki is an LSP-backed reimplementation rather than a pure-VimL plugin. Listed so future audits don't re-flag them.

  • nested_syntaxes / automatic_nested_syntaxes — code-fence languages are auto-detected from the fence tag (syntax/vimwiki.vim); always on, no toggle.
  • maxhi — existence-based link highlighting; superseded by LSP diagnostics.
  • conceal* (conceallevel, conceal_onechar_markers, …) — semantic tokens replace conceal.
  • ext2syntax — syntax chosen by extension / syntax key automatically.
  • folding (upstream string) — nuwiki uses folding = 'lsp' | 'expr' | 'off' backed by LSP foldingRange.
  • key_mappings (dict) — replaced by Lua mappings.<group> + the g:nuwiki_no_<group>_mappings globals.
  • use_calendar — no calendar.vim integration.
  • Mouse maps (<2-LeftMouse>, <MiddleMouse>, …) — upstream binds them unconditionally; nuwiki ships them opt-in (mappings.mouse / g:nuwiki_mouse_mappings). Deliberate, so they're not always-on.
  • global_ext (upstream 1) — nuwiki's ftdetect always maps the configured wiki extension(s) to the vimwiki filetype regardless of location; there's no per-wiki "only inside the root" toggle. Effectively always-on, like nested_syntaxes.
  • syntax default name — nuwiki defaults the per-wiki syntax to vimwiki (its primary syntax) where upstream defaults to default; a naming difference, not a behavioural one.
  • CJK_length, listing_hl*, schemes_*, w32_dir_enc, menu, rx_todo / tag_format — syntax internals, menu, or Vim/Win shims.

Notes

  • Audit confidence: upstream defaults pulled from vimwiki master; a couple of values (CJK_length, links_space_char) were summarized loosely but don't affect the gap list.
  • nuwiki adds some commands with no upstream equivalent (e.g. :NuwikiFindOrphans) — additive, not divergences.
  • Re-audited 2026-05-31 (config / mappings / commands, three parallel agents against vimwiki master). All recent P1/P2/P3 fixes — split/tab link-follow, gl/gL change-symbol + bare-gl/gL remove-checkbox, <CR>-family create-on-follow, <M-CR> badd, <Leader>w<Leader>t/m, VimwikiColorize arg+range, colour-span conceal — confirmed present and correct in both clients. New gaps from that pass (diary-note -count, -complete specs, <D-CR>, global <Leader>w<Leader>m, plus global_ext/syntax-name notes) were added above; no previously-closed item regressed.
  • Re-audited again 2026-05-31 (third pass) after the range/bang/visual and diary-week work. All those fixes confirmed in both clients; no regressions. Confirmed Neovim does bind the text objects (nuwiki.textobjects.attach). Found + fixed an oversight (Neovim Vimwiki/NuwikiIndex still read vim.v.count; now <count>, completing the TabIndex fix). New gaps logged: VimwikiSplitLink/VSplitLink missing -nargs=*; mouse-maps-opt-in noted as an intentional divergence. Config pass found no new gaps; all shipped defaults match upstream except the documented syntax-name divergence.