Files
nuwiki/development/vimwiki-gap.md
T
gffranco 773bbdb6a6
CI / cargo fmt --check (push) Successful in 26s
CI / cargo clippy (push) Successful in 28s
CI / cargo test (push) Successful in 34s
CI / editor keymaps (push) Successful in 1m40s
docs(gap): record re-audit findings (3 new command gaps + 3 refinements)
Three parallel audits (commands/mappings/configs) re-verified all recent fixes
PASS across every context and surfaced new command-attribute gaps, each
confirmed against the code:

New P3 command gaps:
- VimwikiChangeSymbolTo / VimwikiListChangeSymbolI lack -range (upstream has it)
  → E481 on a visual selection.
- VimwikiGenerateLinks lacks -nargs=? (upstream optional rel-path arg) → E488.
- NuwikiGenerateTags missing (Vimwiki form + NuwikiGenerateTagLinks exist) —
  :Vimwiki*↔:Nuwiki* asymmetry.

Refinements to existing P3 items:
- TableAlignQ/W: also bare vs upstream -nargs=? (E488 with an arg).
- VimwikiSearch/VWS: also -nargs=1 vs upstream -nargs=*.
- diary -count: VimwikiDiaryIndex is an additional instance to fold in.
- color_dic: note the empty-default vs upstream-palette divergence (doc-accurate,
  not a doc↔code mismatch) next to color_tag_template.

Mappings + configs audits: clean — no new gaps, all recent work consistent,
subgroup descriptions match code. Tally now 30 done / 27 open (all P3).

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

463 lines
31 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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); `<C-S-CR>` repointed to tab-drop.
- [x] **`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).
- [x] **`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)
- [x] **`<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).
- [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] **`<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`.
- [x] **Generated-section captions hardcoded** — TOC/links/tags headings and
their levels were hardcoded (`= Contents =`, `= Generated Links =`, `= Tags =`,
all level 1). _Fix:_ added per-wiki `toc_header`/`toc_header_level`,
`links_header`/`links_header_level`, `tags_header`/`tags_header_level`
(defaults `Contents`/`Generated Links`/`Generated Tags`, level 1 — matching
upstream; this also corrects the tags index heading from `Tags`
`Generated Tags`). A `caption_line(name, level)` helper emits the markers; the
text + level thread through `toc_edit`/`links_edit`/`tag_links_edit` (+ the
auto_toc save hook) and `find_section_range` matches the configured text so
regen stays idempotent. Tests: `captions_honour_custom_header_and_level`
(`link_health.rs`) + config round-trip in `index_and_config.rs`.
- [x] **On-save autoregen family** — added per-wiki `auto_generate_links`,
`auto_generate_tags`, `auto_diary_index` (all default `false`, like upstream),
wired into the `did_save` hook (`crates/nuwiki-lsp/src/lib.rs`) mirroring
`auto_toc`: regen runs only when the section already exists
(`links_rebuild_edit` / `tag_links_rebuild_edit`), and `auto_diary_index`
regenerates the diary index when a dated diary *entry* is saved
(`diary_generate_index_edit`, which handles an open/closed/absent index file).
`auto_tags` is an **intentional divergence** (see below): nuwiki re-indexes on
every change, so tag metadata is always fresh — there's no on-disk metadata
file to update on save. Tests: `links_rebuild_edit_only_acts_when_section_present`
(`link_health.rs`), `tag_links_rebuild_edit_only_acts_when_index_present`
(`commands_tags.rs`), config round-trip + defaults (`index_and_config.rs`).
- [x] **`listsym_rejected`** — the rejected glyph was a hardcoded `const '-'`.
_Fix:_ `ListSyms` gained a `rejected` field + `new_with_rejected()`
(`crates/nuwiki-core/src/listsyms.rs`); per-wiki `listsym_rejected` key (default
`-`) added to `WikiConfig`; `WikiConfig::list_syms()` builds the palette with
it, used by the parse path (`lib.rs`) and the toggle/cycle commands — so a
custom rejected glyph both lexes and round-trips. Tests:
`listsyms::custom_rejected_glyph_is_honoured` + config round-trip in
`index_and_config.rs`.
- [x] **`custom_wiki2html` (+`_args`)** and **`base_url`** — external HTML
converter hook + export URL prefix. _Fix:_ `HtmlConfig` (`config.rs`) gained
`custom_wiki2html`, `custom_wiki2html_args`, `base_url` (all default `""`,
round-tripped through `RawWiki`/`From`/defaults). `write_page`
(`commands.rs`) now takes a `force` flag and, when `custom_wiki2html` is set,
hands the page to `run_custom_wiki2html()` — which shells out via `sh -c`
with vimwiki's exact arg order (`<cmd> <force> <syntax> <ext> <out_dir>
<in_file> <css> <tpl_path> <tpl_default> <tpl_ext> <root_path> <args>`, `-`
for empty optionals) instead of the built-in renderer. `force` is threaded
through `export_current` (false), `export_all` (its own flag), and the
`did_save` auto-export path (false). `write_rss` now prefixes the channel +
item links with `base_url` (`<base_url><diary_rel_path>/<date>.html`) when
set, falling back to the entry's `file://` URI otherwise. Tests:
`write_page_invokes_custom_wiki2html_converter`,
`write_rss_uses_base_url_for_public_links` (`html_export.rs`), config
round-trip + defaults (`index_and_config.rs`).
- [x] **`map_prefix`** — `<Leader>w` was hardcoded across the map layer.
_Fix:_ mirror vimwiki's `g:vimwiki_map_prefix` with a configurable prefix
(Neovim `map_prefix` setup option, default `'<Leader>w'`; Vim
`g:nuwiki_map_prefix`). The whole wiki command family is now built from the
prefix — both entry-point globals (`lua/nuwiki/init.lua`,
`plugin/nuwiki.vim`, via `:exe`) and buffer-local maps
(`lua/nuwiki/keymaps.lua`, `ftplugin/vimwiki.vim`). Setting a custom prefix
relocates `<prefix>{w,t,s,i,n,d,r,c,h,hh,ha}` and `<prefix><Leader>{w,y,t,m,
i}` and leaves nothing under the old `<Leader>w*`. Tests: new
`test-keymaps-vim-prefix.vim` harness (21 cases, driven by
`test-keymaps-vim.sh`) + `map_prefix.relocates_wiki_family`
(`test-keymaps.lua`). Docs: README, `doc/nuwiki.txt`, lua config comment.
- [x] **`<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.
- [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.
- [x] **`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_align``gqq`
(align) vs `gww` (align w/o resize) distinction lost. _(Re-audit 2026-05-31:
also note the attr differs — both are defined bare in all four contexts vs
upstream's `-nargs=?`, so `:VimwikiTableAlignQ 2` raises E488.)_
- [x] `VimwikiTable` was `-nargs=1` vs upstream `-nargs=*` (couldn't pass
cols+rows). _Fix:_ all four defs (Vim+Neovim × Vimwiki+Nuwiki) are now
`-nargs=*` and forward `<f-args>` to `table_insert` (which already parsed
cols/rows). Covered by `cmd.VimwikiTable_passes_cols_and_rows`
(`test-keymaps.lua`, asserts a `:VimwikiTable 4 3` → 4-col, 3-row table) and
`cmd.VimwikiTable_accepts_cols_rows` (`test-keymaps-vim.vim`, no E488).
Follow-up (same pass): the no-arg **default cols** diverged (nuwiki `3` vs
upstream `5`; rows `2` already matched — confirmed against upstream
`vimwiki#tbl#create`). Aligned both backing fns to default 5 cols.
- [x] `VimwikiListChangeLvl` was `-nargs=?` (range-less) vs upstream
`-range -nargs=+`. _Fix:_ all four defs are now `-range -nargs=+` passing
`<line1>, <line2>, <f-args>`; `list_change_lvl(line1, line2, direction,
[plus_children])` (both clients) parses the required direction + optional
subtree flag and applies the level change to every list item in the range
via the existing `over_range` helper. Covered by
`cmd.ListChangeLvl_range_indents` (`test-keymaps.lua`) and
`cmd.VimwikiListChangeLvl_accepts_range_and_args` (`test-keymaps-vim.vim`,
no E481/E488).
- [x] **Neovim `follow_link_or_create` "botched"** _(new, 2026-05-31
command-attribute audit; FALSE ALARM — verified + tidied)_ — the audit
mis-read the function. `lua/nuwiki/commands.lua` had a single, correct
definition that already did the bare-word → `[[link]]` wrap (via
`wrap_cword_as_wikilink`) and was dispatched by the `<CR>` keymap — there was
no dead `pos_args()` code and no `s:wrap_word_under_cursor` (that name doesn't
exist). The only real artifact was two separate `vim.lsp.buf.definition()`
call sites for the "inside a wikilink" and "nothing to wrap" branches.
_Done:_ collapsed to one tail call (`if not cursor_inside_wikilink() and
wrap_cword_as_wikilink() then return end; vim.lsp.buf.definition()`) —
behaviour identical (wrap still skipped when already inside a link, via
short-circuit), just tidier. No `<CR>` behaviour change.
- [x] **Neovim `*Link` Ex-commands skip the bare-word wrap** _(new, same audit;
broader than first noted)_ — not just Split/VSplit: all eight Neovim
Ex-command link defs (`Vimwiki/Nuwiki` × `FollowLink`/`SplitLink`/
`VSplitLink`/`TabnewLink`) dispatched to raw `lua vim.lsp.buf.definition()`,
bypassing the wrap + create-on-follow that the Vim commands and the Neovim
`<CR>` family provide. _Fix:_ all eight now call
`lua require('nuwiki.commands').follow_link_or_create()` (keeping their
`split`/`vsplit`/`tabnew` prefixes); `TabDropLink` already used
`follow_link_drop` and is unchanged. Covered by
`cmd.VimwikiFollowLink_wraps_bare_word` +
`cmd.VimwikiSplitLink_wraps_bare_word` (`test-keymaps.lua`).
- [x] `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.
_(Re-audit 2026-05-31: also `-nargs=1` in all four contexts vs upstream
`-nargs=*`.)_
- [ ] **`VimwikiChangeSymbolTo` / `VimwikiListChangeSymbolI` lack `-range`**
_(new, 2026-05-31 re-audit)_ — upstream both carry `-range -nargs=1`; nuwiki
defines them `-nargs=1` only (both branches), so `:'<,'>VimwikiChangeSymbolTo X`
over a visual selection raises `E481: No range allowed`. (Internally
consistent across nuwiki's four contexts; purely an upstream-parity gap.)
`ChangeSymbolInListTo` is correctly range-less. _Fix:_ add `-range` + a
`*_range` loop, mirroring the `ToggleListItem`/`IncrementListItem` range work.
- [ ] **`VimwikiGenerateLinks` lacks `-nargs=?`** _(new, 2026-05-31 re-audit)_
upstream takes an optional rel-path arg (`-nargs=?`); nuwiki defines it bare in
all four contexts, so `:VimwikiGenerateLinks foo` raises `E488`. Low impact
(the arg is rarely used). _Fix:_ `ftplugin/vimwiki.vim` + thread an optional
path into `links_generate`.
- [ ] **`NuwikiGenerateTags` missing** _(new, 2026-05-31 re-audit)_ — the
`:Nuwiki*` surface lacks a `GenerateTags` alias although `:VimwikiGenerateTags`
exists (both branches) and `NuwikiGenerateTagLinks` (same handler) is present.
Internal `:Vimwiki*``:Nuwiki*` asymmetry; trivial. _Fix:_ add the two
`NuwikiGenerateTags` defs (Vim + Neovim) mirroring `VimwikiGenerateTags`.
- [ ] `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
`<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`.
- [x] **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`).
- [x] **`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.
- [x] **`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.)
- [x] **`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. _Fix:_ `ftplugin/vimwiki.vim` diary block (both
branches) + thread the count into `diary_today/yesterday/tomorrow` + server
diary commands (accept an optional `wiki` selector). _(The `Index`/`TabIndex`
half is done: all four defs now use upstream's `-count=0` instead of bare
`-count`; `wiki_index`/`wiki_tab_index` already map the count to the wiki
number.)_ _(Re-audit 2026-05-31: `VimwikiDiaryIndex` is an additional instance
— bare in all four contexts vs upstream `-count=0` — fold it into this fix.)_
- [x] **`-complete=` specs** _(new; done 2026-05-31 command-attribute pass)_
upstream attaches command-line completion to several commands; nuwiki had
none, so `<Tab>` at the `:` line never completed page / tag / colour names.
_Fix:_ new `autoload/nuwiki/complete.vim` with pure client-side, synchronous
completers (config + filesystem, never the LSP, so they work under vim-lsp,
coc and Neovim alike), wired via `-complete=customlist,…` into all branches:
- `nuwiki#complete#pages``VimwikiGoto`/`NuwikiGoto` (globs every wiki
root's `*<ext>` files → root-relative page names).
- `nuwiki#complete#colors``VimwikiColorize`/`NuwikiColorize` (keys from a
configured `color_dic` + colours already used in buffer `color:…` spans).
- `nuwiki#complete#tags``VimwikiSearchTags`/`GenerateTagLinks`/
`GenerateTags` (+ Nuwiki forms) — scans the wikis' files for `:tag:` runs
(the tag index lives in the server, which a synchronous completer can't
query; the file scan reads the same source the server indexes).
**Divergence (documented):** no file completer for `VimwikiRenameFile`
upstream completes a new-name arg because it renames itself, but nuwiki
delegates renaming to the LSP rename request (`:LspRename`/coc), which drives
its own prompt and takes no filename argument. Covered by
`complete.pages_globs_and_filters`, `complete.tags_scans_wiki_files`,
`complete.colors_from_buffer_spans` (`test-keymaps-vim.vim`).
- [x] **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).
- [x] **`VimwikiSplitLink` / `VimwikiVSplitLink` lack `-nargs=*`** _(new,
2026-05-31 third re-audit; corrected during the 2026-05-31 command-attribute
pass)_ — the earlier note was wrong: upstream's optional args are NOT a target
link but `reuse_other_split_window` (a:1) and `move_cursor` (a:2) — the link
is always the one under the cursor (`vimwiki#base#follow_link`). nuwiki's defs
took no args, so `:VimwikiSplitLink 0 1` (upstream muscle memory / migrated
scripts) raised E488. _Fix:_ all eight defs (both clients × Split/VSplit ×
Vimwiki/Nuwiki) are now `-nargs=*`, restoring signature parity. **Divergence
(documented):** the two flags are *accepted but not acted on* — nuwiki always
opens a fresh split and follows in it, because the follow is an async LSP
jump and honoring `move_cursor`/`reuse` would require threading a completion
callback through that path (disproportionate for this rarely-used arg form;
the no-arg case — the 99% path — is fully equivalent). Covered by
`cmd.VimwikiSplitLink_accepts_args` (`test-keymaps-vim.vim`, no E488).
### 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.
Related divergence _(2026-05-31 config re-audit)_: nuwiki's `color_dic`
defaults to **empty** while upstream ships a populated palette
(`default`/`red`/…). Documented accurately on the nuwiki side (so it's not a
doc↔code mismatch); the renderer falls back to `class="color-<name>"`. Decide
whether to seed a default palette or keep empty-by-design.
- [ ] `rss_max_items` / `rss_name``:Rss` output hardcoded. _Fix:_ `HtmlConfig`.
- [ ] **RSS feed structure fidelity** _(new, 2026-05-31 base_url audit)_ —
nuwiki's `write_rss` is intentionally minimal (title/link/guid). Upstream
emits more: channel `<link>` points at the diary index page
(`base_url + diary_rel_path + diary_index + .html`, nuwiki uses bare
`base_url`); per-item `<guid isPermaLink="false">` holds the bare date
basename (nuwiki uses the full URL, no attribute); plus `<atom:link rel=
"self">`, channel/item `<pubDate>` (from mtime), and a `<![CDATA[…]]>`
rendered-HTML body per item. `base_url`'s *scope* is faithful (RSS-only,
not inter-page links) and the `custom_wiki2html` arg contract is an exact
match — only the feed document shape diverges.
- [ ] `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.
- [x] **`<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.
- [x] **`<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.
- [x] **`<Leader>w<Leader>m` missing from the Neovim *global* map block**
_(new, 2026-05-31 map_prefix audit)_ — the same collision survived in
`lua/nuwiki/init.lua`'s `_setup_global_mappings`: `<prefix><Leader>t` was
bound to tomorrow and `<prefix><Leader>m` (tomorrow) was absent entirely.
Fixed so `<prefix><Leader>t` opens today in a new tab and `<prefix><Leader>m`
is tomorrow — now consistent with the Vim global side + upstream. Covered by
`global_maps.diary_tab_and_tomorrow_targets` (`test-keymaps.lua`).
---
## 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.
- `auto_tags` (upstream `0`) — upstream auto-updates an on-disk tag *metadata*
file on save. nuwiki has no such file: the LSP re-indexes tags on every
`didChange`, so tag search/jump/completion are always fresh. The setting's
intent is therefore always satisfied (the `auto_generate_tags` regen of the
in-buffer links section is the configurable on-save piece).
- 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.