# vimwiki → nuwiki Parity Gaps Tracking document for closing the gap between nuwiki and the original [vimwiki](https://github.com/vimwiki/vimwiki) plugin across **configuration**, **commands**, and **key mappings**. Source of truth for upstream: vimwiki `master` — `autoload/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) - [x] **Vim client split/tab link-follow commands** — `VimwikiSplitLink`, `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); `` repointed to tab-drop. - [x] **`gl` 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). - [x] **`gl` / `gL` 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` previously held (the only prior entry point). Normal-mode only. ## Regressions (reported by users — verify, then fix) - [x] **`` 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, `` opened the target in a **new tab** instead of the current window; (b) on **both** vim-lsp and coc, `` 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 ``, `tab drop` for ``. `: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). - [x] **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) - [x] **`wt` collision** — upstream = today-in-new-tab; nuwiki bound both `wt` and `wm` to tomorrow's diary. _Fix:_ `wt` now calls `diary_today_tab` (today in a new tab), `wm` 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 hardcoded** — `toc_header` / `toc_header_level`, `links_header`, `tags_header` (+levels). _Fix:_ `crates/nuwiki-lsp/src/config.rs` + server TOC/generate renderers. - [ ] **On-save autoregen family** — `auto_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`** — `w` hardcoded across the map layer. _Fix:_ `plugin/nuwiki.vim`, `lua/nuwiki/keymaps.lua`, `ftplugin/vimwiki.vim`. - [x] **`` badd-link** — was mouse-only (``) / command-only (`:VimwikiBaddLink`); upstream binds `` → `VimwikiBaddLink` (confirmed against upstream `ftplugin/vimwiki.vim`). _Fix:_ added normal-mode `` → `badd_link` in the links group of both clients (`lua/nuwiki/keymaps.lua`, `ftplugin/vimwiki.vim`; docs + README updated). Covered by `map[n].` in both keymap harnesses. - [x] **`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`** — **wrongly removed** in `c63ec67`. The removal treated it as a server concern and hardwired the weekly diary to ISO-Monday (`crates/nuwiki-core/src/date.rs` `monday_of_iso_week`), but choosing which weekday the diary week begins on is a **client-side concern** and it **matters for parity** — non-Monday users lose the upstream option entirely. _Fix:_ restore the config key client-side (`lua/nuwiki/config.lua`) and thread the week-start through to the diary date logic instead of hardcoding Monday. ## 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_align` — `gqq` (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` lacks `-bang` ("rebuild all" variant). - [ ] `: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. - [x] **`VimwikiColorize` / `NuwikiColorize` drop their argument in the Neovim branch** — both are `-nargs=1`, but the Neovim defs called `colorize()` with no `` (`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 ``. 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 `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`. - [x] **Colour spans aren't concealed** — a colorized word shows the literal `` 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 ``/`` 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** — Vim branch → `table_move_left/right`; Neovim branch → `table_move_column_left/right`. Harmless today (each name exists in its own impl) but a divergence to converge. - [ ] **`NuwikiTabIndex` lacks `-count` in the Neovim branch** (`:452`) while its siblings (`VimwikiTabIndex`, `NuwikiIndex`, and the Vim-branch `NuwikiTabIndex`) all carry it — `vim.v.count` is still read, so a count is honored inconsistently. - [ ] **`VimwikiToggleListItem` / `Increment` / `DecrementListItem` lack `-range`** (both branches) vs upstream's `-range` (`:350`) — no visual-range checkbox toggle / symbol cycle. - [ ] **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 `` 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)_ — `VimwikiNormalizeLink` lacks upstream's `-nargs=?`; `VimwikiCheckLinks` lacks `-range`; `VimwikiColorize` is `-nargs=1` vs upstream `-nargs=*`. Cosmetic. ### 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_template` — `color_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 `` normalize-link (visual `+` covers the same intent). - [ ] Insert `` 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. - [ ] **`` (Cmd+Return) tab-drop alias** _(new, 2026-05-31 re-audit)_ — upstream binds both `` and the macOS `` to `VimwikiTabDropLink`; nuwiki binds only `` (both clients). Niche (macOS GUI). _Fix:_ `lua/nuwiki/keymaps.lua`, `ftplugin/vimwiki.vim` alongside ``. - [ ] **`wm` missing from the Vim *global* map block** _(new)_ — present buffer-locally in both clients, but `plugin/nuwiki.vim`'s global `w*` family (usable from non-wiki buffers) binds `w`/`y`/`t`/`i` but not `m` (tomorrow), which upstream binds globally. _Fix:_ `plugin/nuwiki.vim`. --- ## 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.` + the `g:nuwiki_no__mappings` globals. - `use_calendar` — no calendar.vim integration. - `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, ``-family create-on-follow, `` badd, `wt`/`m`, `VimwikiColorize` arg+range, colour-span conceal — confirmed present and correct in **both** clients. New gaps from that pass (diary-note `-count`, `-complete` specs, ``, global `wm`, plus `global_ext`/`syntax`-name notes) were added above; no previously-closed item regressed.