e319b4a935511063efdb76a02b7bdf192936301f
193 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
e319b4a935 |
docs(gap): record 2026-06-03 codebase-review findings (R1-R18)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
e6e3f70dd2 |
feat(render): list_ignore_newline / text_ignore_newline = false → <br>
Implements the deferred half of these options: a soft line break inside a
paragraph / list item can render as <br /> instead of a space.
- Parser: soft breaks now emit a dedicated InlineNode::SoftBreak node
(parse_inline_seq K::Newline + the list-continuation synthetic join) instead
of collapsing to Text(" "). Added SoftBreakNode + the variant.
- All inline consumers treat SoftBreak as whitespace: AST visitor (no-op),
text extraction (index.rs + lib.rs → space), nav/semantic_tokens span_of_inline,
semantic emit (skip like Text), parser span_of_inline.
- Renderer: render_inlines_break renders top-level SoftBreaks as the
context-specific string; render_paragraph uses text_ignore_newline,
render_list_item uses list_ignore_newline; default render_inline → space.
with_newline_handling builder; export.rs wires both from HtmlConfig.
Default (true/true = upstream default) behaviour is unchanged (space). Updated
3 core tests + 1 parser test that asserted the old Text(" ") shape to treat
SoftBreak as whitespace. New test render_page_html_ignore_newline_controls_soft_breaks.
Gap doc: P3 Config item closed — only the deferred markdown cluster remains.
Full rust suite + clippy clean; Neovim 307, Vim 301/18/21.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
||
|
|
1246c99c3c |
fix(config): address P3 config-batch audit findings
Parallel-agent audit of the config batch found: - cycle_bullets used find_marker_span's third element as an indent column, but it's the ABSOLUTE byte offset after the marker — so depth (and the rotated glyph) was wrong for any item not near offset 0 (tests passed by coincidence). Fixed to use the marker span's column (the indentation). Regression test now places the list deep in the document. - :VimwikiColorize interpolated the colour into the template via an unescaped replacement: Lua gsub treats `%` specially, Vim substitute() treats `&`/`\`. Lua now uses a function replacement (verbatim); Vim escapes `\&~`. - render_swapped_table applied table_reduce_last_col before the column swap, so a swap involving the last column moved the narrow slot — now clamped after. - Fixed a stale toc_link_format doc comment (format 1 = [[#anchor]], not a full parent path). Verified-correct by the audit (no change needed): RSS rfc822/cdata/fidelity, prune_orphan_html reverse-mapping + guards, write_escaped_allowing/match_allowed_tag (multibyte-safe), substitute_emoji (byte-boundary-safe), resolve_target_uri create_link/dir_link ordering, all config defaults + From/constructors. Full rust suite + clippy clean; Neovim 307, Vim 301/18/21. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
f5420bd1da |
docs(gap): close the P3 Config section + record divergences/deferrals
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
a63d3dd7cf |
feat(config): P3 config batch — group 7 (user_htmls pruning)
allToHtml now prunes orphan HTML files (no corresponding wiki source) under html_path — export_ops::prune_orphan_html walks the output tree, maps each <rel>.html back to <root>/<rel>.<ext>, and deletes those with no source, skipping the CSS file and any basename in user_htmls. Gated on !html_filename_parameterization (slugified names can't be reverse-mapped), mirroring upstream; the pruned paths are reported in the command result. hl_headers / hl_cb_checked are NOT implemented as toggles: nuwiki already highlights headers per-level (@vimwikiHeading.level1..6) and checkboxes always-on via LSP semantic tokens, which supersedes the upstream opt-in toggles (default off) — same class as the maxhi divergence. Documented in the gap doc rather than degrading the existing highlighting. Test: prune_orphan_html_deletes_sourceless_keeps_protected. Full rust suite + clippy clean. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
5cc47b0a42 |
test(rss): fix commands_coverage assertion for the new <rss xmlns:atom> tag
Follow-up to the RSS-fidelity change: the `<rss version="2.0">` substring now carries the xmlns:atom attribute, so match the open-tag prefix instead. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
4a19f180f2 |
feat(config): P3 config batch — group 6 (RSS fidelity + rss_name/rss_max_items)
write_rss now emits upstream's full RSS 2.0 structure: - xmlns:atom on <rss>; channel <link> points at the diary index page (base_url + diary_rel + diary_index + .html), not bare base_url. - <atom:link rel="self"> to base_url + rss_name. - channel + per-item <pubDate> (RFC-822, derived from the diary date; 1970-01-01=Thu weekday math via to_days_epoch). - per-item <guid isPermaLink="false"> holding the bare date. - per-item <![CDATA[ rendered page body ]]> (render_entry_body reads+parses the entry and renders body-only with the wiki's colour/valid-tag/emoji opts; cdata_safe splits any literal ]]>). - rss_name drives the output filename; rss_max_items caps the feed (0 = unlimited). Tests: updated write_rss_uses_base_url_for_public_links for the new channel link/guid/atom/pubDate; new write_rss_honours_rss_name_and_max_items. Full rust suite + clippy clean. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
5d1ac09245 |
feat(config): P3 config batch — group 4 (valid_html_tags, emoji, color_tag_template)
- valid_html_tags: HTML export now passes the allowlisted inline tags through verbatim (b/i/sub/sup/kbd/div/center/strong/em/...) and escapes the rest, via a render-time tag-aware escaper (write_escaped_allowing/match_allowed_tag) — mirroring upstream's s:safe_html_line regex rather than a parser change. `span` is always allowed so colour spans render. - emoji_enable: render-time `:alias:` -> glyph substitution (curated common set), default on; with_emoji builder + substitute_emoji/emoji_for. - color_tag_template: :VimwikiColorize now wraps via a configurable template (g:nuwiki_color_tag_template / setup color_tag_template), splitting on __CONTENT__ with __COLORFG__ -> colour; both clients. Colour spans render in export via the valid_html_tags span passthrough. Default template reproduces the prior `<span style="color:NAME">` output (harness colorize tests green). Renderer gets with_valid_html_tags + with_emoji; export.rs wires both from HtmlConfig. Tests: valid_html_tags passthrough + escape, emoji on/off (html_export.rs). Full rust suite + both harnesses green (Neovim 307, Vim 301/18/21); clippy clean. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
dcb5d89c0c |
feat(config): P3 config batch — group 3 (cycle_bullets)
cycle_bullets (default off): when an unordered list item changes indent level (gll/glh), rotate its glyph through the configured bullet_types as a depth-keyed ring buffer — change_level_edit gains cycle_bullets + bullet_types params, locates the marker via find_marker_span, and rewrites the glyph to bullet_types[new_depth % len] for single-char unordered markers. Ordered markers are untouched. list_change_level reads both from the wiki config. Tests: cycle_bullets_rotates_glyph_on_indent + cycle_bullets_off_leaves_glyph. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
87d14310fc |
feat(config): P3 config batch — group 2 (create_link, dir_link, auto_header)
- create_link (default true): server resolve_target_uri now only synthesises a missing-page URI when create_link is set; when off, following a link to a non-existent page returns no location (no-op). - dir_link: a [[dir/]] link now resolves to <dir>/<dir_link><ext> when dir_link is set, else opens the directory itself. Uses the already-parsed LinkTarget.is_directory. - auto_header (default off): new wiki pages get a `= Stem =` header derived from the filename, skipping the wiki index + diary index. Client-side BufNewFile autocmd in both clients (init.lua + plugin/nuwiki.vim), with auto_header handlers in both command layers (trailing-slash-robust root matching). Tests: cmd.auto_header_inserts + cmd.auto_header_skips_diary_index (nvim) / cmd.auto_header_skips_index (vim). Full rust suite + both harnesses green (Neovim 307, Vim 301/18/21). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
b2f2fc88bd |
feat(config): P3 config batch — group 1 (clean config + plumbing)
Config plumbing for the whole config batch (HtmlConfig + WikiConfig fields, RawWiki deserialization, From/defaults) plus these behaviors: - rss_name / rss_max_items: HtmlConfig fields (wired into write_rss in the RSS group). - toc_link_format: build_toc_text emits [[#anchor]] (no description) for 1, [[#anchor|title]] for 0. - generated_links_caption: build_links_text emits [[page|FirstHeading]] from a page->heading map (ops::page_captions) when enabled. - table_reduce_last_col: column_widths clamps the last column to width 1 when set; threaded through table_align_edit/table_move_column_edit + commands. - color_dic now ships a populated default palette (red/green/blue/...). - commentstring aligned to upstream's no-space `%%%s`. - auto_chdir (default off): :lcd into the owning wiki root on buffer enter; both clients (ftplugin.lua setup_auto_chdir + Vim NuwikiAutoChdir augroup), with config.wiki_root_for / nuwiki#commands#wiki_root_for resolvers. Also seeded HtmlConfig fields for later groups (valid_html_tags, list/text_ignore_newline, emoji_enable, user_htmls, color_tag_template) and WikiConfig (create_link, dir_link, bullet_types, cycle_bullets). Tests: toc_link_format, generated_links_caption, table_reduce_last_col, config defaults + JSON round-trip for every new key. Full rust suite + both keymap harnesses green. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
03005d0931 |
fix(insert): pumvisible() guard on smart_return/smart_shift_return (audit follow-up)
The mappings re-audit confirmed the two new bindings (visual <CR> normalize, insert <S-CR> multiline item) are correct — column math matches upstream's s:text_begin, auto-indent handling sound, no parity gaps or regressions. It flagged one low-severity item shared with the pre-existing smart_return: neither guarded the completion popup. Upstream maps <CR>/<S-CR> as `pumvisible() ? '<CR>' : …`. Added that guard to both smart_return and smart_shift_return (both clients) so a <CR>/<S-CR> accepts the completion instead of continuing the list when the popup is open. Left as a documented minor divergence: <S-CR> on an *empty* bullet emits the aligned no-marker continuation rather than upstream's "blank line above, keep marker" (niche). Neovim 305, Vim 299/18/21 pass. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
724712121d |
feat(parity): close the entire P3 Mappings section
Both remaining mapping gaps (client-side, both clients):
- Visual <CR>: upstream binds it to NormalizeLinkVisualCR (== visual `+`).
Added `x <CR>` -> normalize_link(true) (wrap the selection as a wikilink)
in both clients.
- Insert <S-CR>: upstream's multiline-list-item continuation (VimwikiReturn
2 2 -> kbd_cr with no new marker). New smart_shift_return (both clients,
<expr> insert mapping): on a list item returns <CR> + spaces aligning under
the item text (marker width + 1, +4 for a `[ ] ` checkbox), no marker; off a
list item, a plain <CR>. Mirrors smart_return's auto-indent handling.
Tests: map.visual_cr_wraps_selection + map.insert_shift_cr_multiline
(test-keymaps.lua, the latter exercising the handler directly since <S-CR>
doesn't round-trip headless feedkeys), and map.visual_cr_wraps_selection +
cr.shift_cr_multiline{,_checkbox} (test-keymaps-vim.vim). Docs (README +
doc/nuwiki.txt) and the gap doc updated. Neovim 305, Vim 299/18/21 pass.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
||
|
|
305324c6e9 |
Merge remote-tracking branch 'origin/calendar-support' into feature-gap
# Conflicts: # development/vimwiki-gap.md |
||
|
|
6deba47106 |
fix(search): graceful no-match + NuwikiSearch alias (re-audit follow-up)
Re-audit of the just-landed command work found one real bug I introduced
and a convention gap:
- VimwikiSearch / VWS raised a raw E480 on a no-match search; upstream
reports it gracefully. Both clients now catch it (try/catch in Vim,
pcall in Neovim) and emit "nuwiki: no match for <pat>".
- Added a NuwikiSearch alias alongside VimwikiSearch/VWS (every other
command carries a Nuwiki* form).
Gap-doc note corrected: nuwiki's search populates + opens the location
list (shows all matches) where upstream jumps to the first match — logged
as a minor presentation divergence rather than claiming exact parity.
Config + mappings re-audits came back clean (no new gaps, no regressions;
table-mapping rewire verified non-recursive, gLH/gLL/gLR present).
Tests: cmd.VimwikiSearch_no_match_graceful, surface.{Vimwiki,Nuwiki}Search.
Neovim 301, Vim 294/18/21 pass.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
||
|
|
a11b742fc1 |
feat(parity): close the entire P3 Commands section
All six remaining command gaps (client-side; no server change):
- VimwikiRenameFile: bare -> -nargs=? (arg accepted-ignored; rename still
delegates to the LSP rename prompt). No more E488.
- VimwikiVar / NuwikiVar: get/set the client config (upstream vimwiki#vars#cmd).
No arg prints config (Vim: g:nuwiki_*; Neovim: resolved setup() opts), one arg
gets a key, two+ sets it. Global command, both clients.
- VimwikiReturn / NuwikiReturn: command form of the smart <CR> continuation —
enters insert at EOL and fires the <CR> mapping (return_cmd / vimwiki_return).
Upstream's mode-flag args accepted but unused.
- VimwikiTableAlignQ vs AlignW: corrected — upstream's gqq/gww are identical on
a table; the only difference is the non-table fallback (native `normal! gqq`
vs `gww`). New table_align_or_cmd(cmd) aligns on a table row, else runs
`normal! <cmd>`. Q/gqq/gq1 -> gqq; W/gww/gw1 -> gww; NuwikiTableAlign -> gqq.
- VimwikiSearch / VWS: scope the lvimgrep to the current wiki's root (resolved
client-side) over <root>/**/*<ext>, not CWD `**`; empty pattern reuses the
last search. Both clients.
- VimwikiIndex family: add global Vimwiki/NuwikiIndex + TabIndex entry points
(plugin/nuwiki.vim + init.lua _setup_global_commands, with -count), so a wiki
opens from any buffer. Buffer-local copies still shadow inside wiki buffers.
Tests: surface.{Vimwiki,Nuwiki}{Return,Var}, cmd.VimwikiVar_sets_*,
cmd.global_entry_points (both harnesses). Docs (README + doc/nuwiki.txt) and the
gap doc updated. Neovim 299, Vim 291/18/21 pass.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
||
|
|
3865b8bf0e |
fix(parity): fifth-pass re-audit — VimwikiGoto nargs, autowriteall, table_auto_fmt
Closes the actionable fifth-pass findings (gap doc updated): - VimwikiGoto / NuwikiGoto: -nargs=1 -> -nargs=* in all four defs. Was a real bug — `:VimwikiGoto` raised E471, `:VimwikiGoto My Page` raised E488, and the handler's empty-arg prompt fallback was unreachable. Both clients already prompt on empty, so -nargs=* (keeping -complete=pages) restores upstream behavior. - autowriteall (upstream default ON): while a wiki buffer is current, mirror Vim's global 'autowriteall' (auto-save on page switch / :make), restoring the prior value on leave. Neovim via ftplugin.lua setup_autowriteall (BufEnter/BufLeave) gated by the `autowriteall` setup option; Vim via the NuwikiAutoWriteAll augroup gated by g:nuwiki_autowriteall. - table_auto_fmt (upstream default ON): re-align the table under the cursor on InsertLeave. Both clients, gated by `table_auto_fmt` / g:nuwiki_table_auto_fmt, guarded on the cursor line containing `|` before the async table_align. Also logged (no code): VimwikiRenameFile missing -nargs=? (subsumed by the LSP-rename divergence), table_reduce_last_col, user_htmls, hl_headers/ hl_cb_checked, and a commentstring value-mismatch note. Mappings audit clean. The Neovim harness disables table_auto_fmt in setup (its async re-align would perturb the deterministic table-nav keystroke cases); its wiring is verified on a throwaway scratch buffer instead. Docs (README + doc/nuwiki.txt) updated. Tests: cmd.VimwikiGoto_accepts_multiword, config.autowriteall_applied, config.table_auto_fmt_autocmd. Neovim 293, Vim 285/18/21 pass. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
c161f9d21a |
feat(parity): P3 quick-wins — ShowVersion, gLH/gLL/gLR, Search/Align nargs
Closes four low-risk P3 parity items (gap doc updated):
- VimwikiShowVersion / NuwikiShowVersion: new global command (both clients)
echoing g:nuwiki_version (0.1.0) + the host editor, via
nuwiki#commands#show_version / commands.show_version.
- gLH / gLL / gLR: upstream's case-variant aliases of gLh/gLl/gLr (dedent /
indent whole item, renumber all lists) added in both clients.
- VimwikiSearch / VWS: -nargs=1 -> -nargs=* (Vim + Neovim), so a multi-word
search no longer raises E488 and an empty invocation reuses the last search
pattern. (The lvimgrep-vs-vimwiki-engine difference stays open.)
- VimwikiTableAlignQ / AlignW / NuwikiTableAlign: bare -> -nargs=?, so
`:VimwikiTableAlignQ 2` no longer raises E488 (optional column arg is
accepted-and-ignored; the gqq-align vs gww-align-without-resize split
stays open).
Docs (doc/nuwiki.txt + README) updated for the command and the aliases.
Tests: surface.{Vimwiki,Nuwiki}ShowVersion, map[n].gL{H,L,R} (both
harnesses), cmd.search_and_tablealign_nargs (vim). Neovim 291, Vim
282/18/21 pass.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
||
|
|
9441fe918c |
fix(parity): close the 2026-06-02 re-audit config/command findings
Implements the remaining fourth-pass findings (gap doc updated):
- list_margin: rework to upstream's buffer-side meaning. Drop the
nuwiki-only HTML em-margin (renderer field/method + render_page_html
param removed) and prepend max(0, list_margin) leading spaces to every
generated bullet in build_toc_text / build_links_text /
build_tag_links_text / diary::build_index_body; headings stay at col 0.
From<RawWiki> derives 0 for markdown wikis when unset. Negatives can't
resolve 'shiftwidth' server-side, so they collapse to zero indent
(documented divergence).
- diary_months: per-wiki Vec<String> (default 12 English names), threaded
into the diary-index month labels; missing/empty slots fall back to the
English name.
- diary_caption_level: widen u8 -> i8 so vimwiki's -1 (min: -1) parses;
build_index_body clamps < 0 to base tree level 0.
- VimwikiRemoveDone: regain upstream's -range. All four defs are now
-bang -range, dispatched via remove_done(bang, range, l1, l2) in both
clients: ! -> whole buffer, explicit range -> new list_remove_done_range
({range:[l1-1,l2-1]}), else current list. Server remove_done_edit gained
an Option<(u32,u32)> range that filters whole-doc victims by start line.
markdown_header_style is deferred: the generators emit vimwiki syntax only
(caption_line never writes markdown headers), so there's no markdown header
to attach the style to. Logged as the "generated-content is vimwiki-only"
intentional divergence pending a later markdown generated-content effort.
Tests: list_margin indent, markdown list_margin-0 default, diary_months
custom + fallback, negative caption_level clamp/parse, ranged remove-done
(server + both keymap harnesses). 553 lsp/core tests pass; clippy clean.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
||
|
|
079e7246ac |
fix(lists): VimwikiToggleRejectedListItem -range parity (P3)
Upstream's :VimwikiToggleRejectedListItem is -range and binds glx in visual mode; nuwiki's four defs were bare, so a ranged invocation raised E481 and acted cursor-only. Same -range class already fixed for ToggleListItem/Increment/Decrement -- ToggleRejected was missed. All four defs (Vim+Neovim x Vimwiki*/Nuwiki*) are now -range, routed through a new reject_list_item_range(l1, l2) looping over_range in both clients, mirroring toggle_list_item_range. Visual glx stays cursor-only, consistent with its <C-Space>/gln/glp siblings. Also logs the 2026-06-02 re-audit findings in development/vimwiki-gap.md: RemoveDone lost -range (low pri); config gaps list_margin semantics/markdown-default, diary_months, markdown_header_style, diary_caption_level=-1; and the path_html/template_path default-location divergences. Mappings audit came back clean. Tests: cmd.reject_list_item_range (test-keymaps.lua), cmd.VimwikiToggleRejectedListItem_accepts_range (test-keymaps-vim.vim). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
d8d1e9e39e |
docs(gap): check off html_header_numbering
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
79b502fa5c |
feat(html): html_header_numbering section numbering for HTML export
Mirror vimwiki's html_header_numbering / html_header_numbering_sym: top-level headings at or below the start level get a dotted section number (1, 1.1, 1.2, ...) with a configurable trailing symbol. Off by default (level 0). Nested headings in lists/quotes stay unnumbered, matching upstream's document-level-only scan. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
21f583beef |
docs(calendar): fix stale comments and integration docs
- diary.vim: correct calendar_action doc comment (dir is used for split direction; only week is unused) - calendar-vim-integration.md: use real nuwiki var names (g:nuwiki_use_calendar / g:nuwiki_no_calendar / g:nuwiki_wikis), document auto-detect wiring and calendar-window close behavior; drop the non-existent refresh-on-close autocmd - vimwiki-gap.md: remove stale 'no calendar.vim integration' entry now that the integration is implemented |
||
|
|
87ba4c1764 |
test(calendar): add Vim + Neovim integration harnesses
Add headless harnesses covering the calendar-vim integration, wired into CI alongside the existing keymap/config suites: - test-calendar-vim.sh/.vim (+ -optout.vim): pure-VimL diary hooks (calendar_sign markers, calendar_action path resolution from wiki root, calendar window close), plugin/nuwiki.vim hook auto-wiring that overrides calendar-vim's defaults, and opt-out via g:nuwiki_use_calendar and g:nuwiki_no_calendar. Uses a stub calendar-vim on the runtimepath. - test-calendar.sh/.lua: Neovim setup() wiring + window-close under the real window API, and opt-out via use_calendar = false. Fixes surfaced by the suite: - diary.vim: new diary entries set filetype 'vimwiki' (was the raw extension, e.g. 'wiki'); the stray FileType autocmd also blocked the calendar window from closing. - init.lua: drop the redundant Neovim FileType autocmd (plugin/nuwiki.vim already wires both editors) and translate use_calendar=false into g:nuwiki_no_calendar so the opt-out actually disables wiring. |
||
|
|
7a3e11cfeb |
feat(calendar): integrate calendar-vim with wiki diary paths
Wire g:calendar_action/g:calendar_sign to nuwiki diary hooks that resolve diary paths from the wiki root config instead of calendar-vim's default ~/diary. Auto-detected on FileType vimwiki when calendar-vim is present; opt out with g:nuwiki_use_calendar=0 or g:nuwiki_no_calendar. - autoload/nuwiki/diary.vim: calendar_action/calendar_sign using wiki cfg; open diary in the previous window and close the calendar window after. - autoload/vimwiki/diary.vim: vimwiki# aliases for drop-in compatibility. - plugin/nuwiki.vim + lua/nuwiki/init.lua: auto-wire hooks, overwriting calendar-vim's defaults while respecting user-set custom hooks. - lua/nuwiki/config.lua: add use_calendar option (on by default). - development/start-*.sh + _common.sh: clone calendar-vim, fix vimrc var expansion, pass wiki root to the Vim/Neovim clients. |
||
|
|
88114a65a4 |
test: land the vim diary -count cases + dedup the lua one (follow-up to 2da2168)
2da2168's diary test edits landed unevenly: the lua
cmd.VimwikiMakeDiaryNote_has_count case got inserted twice, and the two vim
cases (cmd.Vimwiki{MakeDiaryNote,DiaryIndex}_accepts_count) the commit message
referenced never landed (the Edit had no-matched). Remove the lua duplicate and
add the two vim cases before the harness wrap-up. lua 284, vim 274/18/21, all
0 failed.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
||
|
|
2da2168d88 |
fix(diary): complete the -count wiki selector (repair 874bdd0)
|
||
|
|
874bdd0c02 |
feat(diary): -count wiki selector for diary-note + index commands (P3)
Closes the last command-cluster gap. Upstream's diary-note family
(:Vimwiki{Make,TabMake,MakeYesterday,MakeTomorrow}DiaryNote + VimwikiDiaryIndex,
and the Nuwiki* forms) carry -count=0 where the count selects the wiki number;
nuwiki's were bare. Implemented as a real end-to-end selector, reusing existing
infrastructure:
- Server (commands.rs): OptUriArg gained an optional `wiki` selector;
resolve_diary_wiki(backend, uri, wiki) now prefers it (via the existing
resolve_wiki_selector, which already handles a 0-indexed wiki number) over
the buffer URI. Used by diary_open_relative + diary_open_index.
- Clients: s:diary_open / _diary_open (both) and diary_today/today_tab/
yesterday/tomorrow/index take a count and send {wiki: count-1} when >0. All
22 diary-note + DiaryIndex command defs across the 4 contexts are now
-count=0 passing <count>. diary_next/prev ignore the count.
Tests: cmd.VimwikiMakeDiaryNote_has_count (test-keymaps.lua) +
cmd.Vimwiki{MakeDiaryNote,DiaryIndex}_accepts_count (test-keymaps-vim.vim).
Workspace test/clippy/fmt clean with CI flags; lua 284, vim 272/18/21.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
||
|
|
f0c07f0c28 |
feat(commands): ChangeSymbolTo -range, GenerateLinks path filter, NuwikiGenerateTags
Closes the three new command gaps from the 2026-05-31 re-audit (all real,
client-side, both clients x Vimwiki/Nuwiki):
- VimwikiChangeSymbolTo / ListChangeSymbolI / NuwikiChangeSymbol are now
-range -nargs=1 via a new list_change_symbol_range(symbol,l1,l2) helper that
loops over_range; was -nargs=1 only -> E481 on a visual selection.
ChangeSymbolInListTo / ChangeSymbolInList stay range-less and keep
whole_list=true.
- VimwikiGenerateLinks / NuwikiGenerateLinks are now -nargs=?; with an arg the
client dispatches the existing server command nuwiki.links.generateForPath
({path}) for real subtree-scoped link generation, else nuwiki.links.generate.
Was bare -> E488 on an arg.
- Added NuwikiGenerateTags (Vim + Neovim) mirroring VimwikiGenerateTags, with
-nargs=? -complete=...tags - closes the :Vimwiki*<->:Nuwiki* alias asymmetry.
Tests: cmd.ChangeSymbolTo_range_sets_marker, cmd.GenerateLinks_accepts_optional_path,
cmd.NuwikiGenerateTags_exists (test-keymaps.lua, 283 pass) +
cmd.VimwikiChangeSymbolTo_accepts_range, cmd.VimwikiGenerateLinks_accepts_path,
cmd.NuwikiGenerateTags_exists (test-keymaps-vim.vim, 272/18/21). fmt clean.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
||
|
|
f616915581 |
feat(commands): ChangeSymbolTo -range, GenerateLinks path filter, NuwikiGenerateTags
Closes the three new command gaps from the 2026-05-31 re-audit (all real,
client-side, both clients × Vimwiki/Nuwiki):
- VimwikiChangeSymbolTo / ListChangeSymbolI / NuwikiChangeSymbol are now
-range -nargs=1 via a new list_change_symbol_range(symbol,l1,l2) helper that
loops over_range; was -nargs=1 only → E481 on a visual selection.
ChangeSymbolInListTo/InList stay range-less.
Bonus: the Neovim VimwikiChangeSymbolInListTo + NuwikiChangeSymbolInList defs
passed whole_list=false, changing only the current item — corrected to true.
- VimwikiGenerateLinks / NuwikiGenerateLinks are now -nargs=?; with an arg the
client dispatches the existing server command nuwiki.links.generateForPath
({path}) for real subtree-scoped link generation, else nuwiki.links.generate.
Was bare → E488 on an arg.
- Added NuwikiGenerateTags (Vim + Neovim) mirroring VimwikiGenerateTags, with
-nargs=? -complete=…tags — closes the :Vimwiki*↔:Nuwiki* alias asymmetry.
Tests: cmd.ChangeSymbolTo_range_sets_marker, cmd.GenerateLinks_accepts_optional_path,
cmd.NuwikiGenerateTags_exists (test-keymaps.lua, 283 pass) +
cmd.VimwikiChangeSymbolTo_accepts_range, cmd.VimwikiGenerateLinks_accepts_path,
cmd.NuwikiGenerateTags_exists (test-keymaps-vim.vim, 272/18/21). fmt clean.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
||
|
|
773bbdb6a6 |
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> |
||
|
|
23f5a74086 |
test: add the Neovim *Link wrap cases referenced by 2b3bc48
The previous commit's test-insert Edit silently no-matched (wrong anchor text), so cmd.VimwikiFollowLink_wraps_bare_word and cmd.VimwikiSplitLink_wraps_bare_word were referenced in the commit message and gap doc but never added. Add them now at the correct anchor; the lua harness goes 278 → 280, both new cases pass. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
2b3bc48b75 |
fix(commands): route Neovim *Link Ex-commands through follow_link_or_create
Audit follow-up on the two link-path items flagged during the command-attribute pass: - REAL (bug #2): all eight Neovim Ex-command link defs (Vimwiki/Nuwiki × FollowLink/SplitLink/VSplitLink/TabnewLink) dispatched to raw `lua vim.lsp.buf.definition()`, bypassing the bare-word → [[link]] wrap + create-on-follow that the Vim commands and the Neovim <CR> family already do. All eight now call follow_link_or_create() (keeping their split/vsplit/tabnew prefixes). TabDropLink already used follow_link_drop and is unchanged. - FALSE ALARM (bug #1): the audit's claim that lua follow_link_or_create was "botched" (double definition() with dead pos_args code, no wrap) was a mis-read — it was a single correct definition that already wrapped bare words and is dispatched by <CR>. Tidied anyway: collapsed its two definition() call sites into one tail call; behaviour is identical (wrap still skipped when already inside a link, via short-circuit). Tests: cmd.VimwikiFollowLink_wraps_bare_word + cmd.VimwikiSplitLink_wraps_bare_word (test-keymaps.lua). Both harnesses green (lua 280, vim 269/18/21, 0 failed); gap doc corrected for both entries. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
3b3d8ca782 |
feat(commands): command-line completion for Goto/Colorize/tag commands (P3)
Upstream attaches -complete= to several commands; nuwiki had none, so <Tab>
at the : line never completed page/tag/colour names. New
autoload/nuwiki/complete.vim adds pure client-side, synchronous completers
(config + filesystem, never the LSP — so they work under vim-lsp, coc and
Neovim), wired via -complete=customlist into all command contexts:
- nuwiki#complete#pages → VimwikiGoto/NuwikiGoto (glob wiki roots for page names)
- nuwiki#complete#colors → VimwikiColorize/NuwikiColorize (color_dic keys +
colours already used in buffer color:… spans)
- nuwiki#complete#tags → VimwikiSearchTags/GenerateTagLinks/GenerateTags (+Nuwiki)
(scan wiki files for :tag: runs — the tag index is server-side and a
synchronous completer can't query it, so we read the same source it indexes)
Documented divergence: no file completer for VimwikiRenameFile — nuwiki
delegates renaming to the LSP rename request (no filename arg to complete),
unlike upstream which renames itself.
Tests: complete.{pages_globs_and_filters,tags_scans_wiki_files,
colors_from_buffer_spans} (test-keymaps-vim.vim). Both harnesses green.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
||
|
|
efea225240 |
fix(commands): VimwikiTable default 5 cols (parity) + map audit findings
Verification audit of the command-attribute pass confirmed all four changes (Table, Index/TabIndex, ListChangeLvl, SplitLink) faithful with no regressions, and surfaced three pre-existing items: - VimwikiTable no-arg default cols was 3 vs upstream's 5 (rows 2 already matched, confirmed against vimwiki#tbl#create). Aligned both backing fns (autoload + lua) to default 5 cols. - Mapped (not fixed here — core <CR> behavior, out of attribute scope): the Neovim lua follow_link_or_create double-calls definition() with dead code and never wraps a bare word into [[link]] (the Vim side does); and the Neovim Split/VSplitLink dispatch to raw definition() instead of follow_link_or_create. Both logged in development/vimwiki-gap.md. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
acaaf107b4 |
feat(commands): VimwikiSplitLink/VSplitLink -nargs=* signature parity (P3)
Upstream's :Vimwiki[V]SplitLink take optional reuse_other_split_window + move_cursor flags (the link is always the one under the cursor); nuwiki's defs took no args, so `:VimwikiSplitLink 0 1` raised E488. All eight defs (both clients × Split/VSplit × Vimwiki/Nuwiki) are now -nargs=*, restoring signature parity for migrated configs/scripts. Documented divergence: the two flags are accepted but not acted on — nuwiki always opens a fresh split and follows in it. Honoring move_cursor/reuse would require threading a completion callback through the async LSP follow path, disproportionate for this rarely-used arg form; the no-arg path (99% case) is fully equivalent. The gap-doc note (which wrongly described the args as a "target link") is corrected. Test: cmd.VimwikiSplitLink_accepts_args (test-keymaps-vim.vim, no E488). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
4710ba03c8 |
feat(commands): VimwikiListChangeLvl -range -nargs=+ (P3 parity)
Upstream is `-range -nargs=+` (change_level(line1, line2, direction, plus_children)); nuwiki was -nargs=? and range-less, so `:1,3VimwikiListChangeLvl increase 0` raised E481/E488 and the level change never spanned a selection. All four defs (Vim+Neovim × Vimwiki+Nuwiki) are now -range -nargs=+ and forward <line1>, <line2>, <f-args>. list_change_lvl(line1, line2, direction, [plus_children]) (both clients) parses the required direction + optional subtree flag and applies the change to every list item in the range via the existing over_range helper. Tests: cmd.ListChangeLvl_range_indents (test-keymaps.lua) + cmd.VimwikiListChangeLvl_accepts_range_and_args (test-keymaps-vim.vim). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
fe116088bb |
chore: untrack .claude/ session artifact, add to .gitignore
`git add -A` in the previous commit accidentally swept in .claude/scheduled_tasks.lock — a Claude Code local runtime artifact. Remove it from the index and gitignore the .claude/ dir so it can't recur. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
a7f7e8e61f |
feat(commands): VimwikiTable -nargs=* + Index/TabIndex -count=0 (P3 parity)
Two command-attribute parity fixes (audited against upstream vimwiki master): - VimwikiTable / NuwikiTable were -nargs=1 and called table_insert() with no args, so `:VimwikiTable 4 3` raised E488 and cols/rows were unreachable. All four defs (Vim+Neovim × Vimwiki+Nuwiki) are now -nargs=* and forward <f-args>; the backing table_insert already parsed cols (a:1) + rows (a:2). - VimwikiIndex/TabIndex (and Nuwiki forms) switch from bare -count to upstream's -count=0. Behavior is unchanged (both default count to 0; wiki_index already maps a count to the 1-indexed wiki number) — this just matches the upstream declaration exactly. Tests: cmd.VimwikiTable_passes_cols_and_rows (test-keymaps.lua — asserts a 4-col/3-row table) and cmd.VimwikiTable_accepts_cols_rows (test-keymaps-vim.vim — no E488). gap doc updated. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
724c12ac16 |
style: rustfmt the custom_wiki2html test assert (fixes red CI)
The custom_wiki2html test added in
|
||
|
|
8dc4050b76 |
fix(commands)+docs: even out :NuwikiUISelect; exhaustive subgroup key lists
- ftplugin/vimwiki.vim: add buffer-local :NuwikiUISelect to the Vim path (it previously existed only on the Neovim path, contradicting the docs' "buffer-local on every .wiki buffer" claim — a global fallback masked it). Now symmetric with :VimwikiUISelect. - Make every keymap subgroup description list all of its bindings instead of trailing with "…": the README mappings-subgroups table, the README config-example comments, the README g:nuwiki_no_<group>_mappings rows, the doc/nuwiki.txt group→keys list, and the lua/nuwiki/config.lua comment. Also fixes the doc list that had dropped aH/iH from text_objects and adds the mouse group. Each notes that the <Leader>w prefix follows map_prefix. helptags validates (no dup tags); all keymap suites pass (266+18+21 Vim, 275 Lua); :NuwikiUISelect confirmed defined on a Vim .wiki buffer. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
3e82f59f12 |
docs: fix stale README + help file (audit)
A three-agent audit cross-checked README.md and doc/nuwiki.txt against the actual config, commands, and mappings in code. Fixes: Mappings: - doc/nuwiki.txt wrongly described <Leader>ww as "open today's diary" — it opens the wiki index (diary-today is <Leader>w<Leader>w). Corrected, and the missing <Leader>wt (wiki index in a tab) row added. - README feature bullet referenced <Leader>ww for the diary; fixed to <Leader>w<Leader>w. - Both keymap listings now note <Leader>w is the default map_prefix. Config globals: - README globals table was missing real, code-read globals: g:nuwiki_syntax, g:nuwiki_diary_rel_path, g:nuwiki_wikis, g:nuwiki_map_prefix, g:nuwiki_binary_path, g:nuwiki_build_from_source. Added. - doc/nuwiki.txt globals section gained g:nuwiki_diary_rel_path and g:nuwiki_link_severity (both read in autoload but undocumented). - doc/nuwiki.txt per-wiki list gained template_date_format, html_filename_parameterization, color_dic, list_margin (in README only). Commands: - doc/nuwiki.txt was missing a whole list/task/table command group plus :NuwikiFindOrphans, :NuwikiNormalizeLink, :NuwikiColorize, :NuwikiPasteLink/PasteUrl/CatUrl. Added, matching README's descriptions. No default-value mismatches and no phantom (documented-but-nonexistent) entries were found. helptags validates with no duplicate tags. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
2a8e2b9ea9 |
fix(keymaps): correct Neovim global diary tab/tomorrow maps (map_prefix audit)
A map_prefix parity audit against upstream vimwiki found the Neovim global entry-point block in lua/nuwiki/init.lua carried the same collision the Vim global + buffer-local maps were already fixed for: <prefix><Leader>t was bound to tomorrow and <prefix><Leader>m (tomorrow) was missing entirely. Now <prefix><Leader>t opens today in a new tab and <prefix><Leader>m is tomorrow — consistent with plugin/nuwiki.vim, the buffer-local maps, and upstream (VimwikiTabMakeDiaryNote / VimwikiMakeTomorrowDiaryNote). Adds global_maps.diary_tab_and_tomorrow_targets to test-keymaps.lua (queries in a scratch buffer so buffer-local maps don't shadow the globals). Logs the fix plus a new "RSS feed structure fidelity" gap (the audit confirmed the custom_wiki2html arg contract and base_url scope are faithful; only the RSS document shape diverges) in development/vimwiki-gap.md. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
feedd30c4d |
feat(keymaps): configurable map_prefix for the wiki command family (P2)
Mirror vimwiki's g:vimwiki_map_prefix. The whole <Leader>w* family was
hardcoded across the map layer; it is now built from a configurable prefix:
- Neovim: `map_prefix` setup() option (default '<Leader>w'), read by
lua/nuwiki/keymaps.lua (buffer-local) and lua/nuwiki/init.lua (global
entry points).
- Vim: g:nuwiki_map_prefix, applied via :exe in plugin/nuwiki.vim (global)
and ftplugin/vimwiki.vim (buffer-local).
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}, leaving nothing under the old <Leader>w*.
Non-prefix maps (<CR>, gl*, headers, …) are untouched.
Tests: new test-keymaps-vim-prefix.vim harness (21 cases, wired into
test-keymaps-vim.sh) + map_prefix.relocates_wiki_family in test-keymaps.lua.
Docs: README, doc/nuwiki.txt, lua config comment, vimwiki-gap.md ticked.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
||
|
|
23aec3e6c7 |
feat(config): custom_wiki2html external converter + base_url for RSS (P2)
Add three per-wiki HtmlConfig keys mirroring vimwiki globals: - custom_wiki2html / custom_wiki2html_args: when set, export shells out to the external converter 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. - base_url: when set, diary RSS item + channel links become <base_url><diary_rel_path>/<date>.html instead of file:// URIs. write_page() gains a `force` flag threaded through export_current (false), export_all (its own flag) and the did_save auto-export path (false). 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). Docs: README, doc/nuwiki.txt, lua config comment, vimwiki-gap.md item ticked. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
09b5a2bd46 |
feat(config): on-save autoregen family — links/tags/diary-index (P2)
Added per-wiki auto_generate_links, auto_generate_tags, auto_diary_index (default false, like upstream), wired into the did_save hook mirroring auto_toc: - auto_generate_links / auto_generate_tags rebuild the Generated Links / Generated Tags section ONLY when it already exists (new links_rebuild_edit / tag_links_rebuild_edit, like toc_rebuild_edit) — never inserts one into a page that lacks it. - auto_diary_index regenerates the diary index page when a dated diary entry (not the index itself) is saved, via diary_generate_index_edit (handles the index file open / on-disk / absent). auto_tags is recorded as an intentional divergence: nuwiki re-indexes tags on every change, so the tag metadata is always fresh (no on-disk file to update). Tests: links_rebuild_edit_only_acts_when_section_present, tag_links_rebuild_edit_only_acts_when_index_present, config round-trip + defaults. README/doc/lua comment updated. fmt/clippy clean; 0 Rust failures. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
3fd04b0efa |
fix(lsp): section-range termination is level-aware (caption audit follow-up)
The post-captions audit found find_section_range terminated a generated section only at the next *level-1* heading. With a custom non-1 *_header_level (e.g. a level-2 Generated Tags index) a following same-level section could be absorbed into the replaced span. Terminate at the next heading of level <= the matched section's level instead, which keeps the deeper `level+1` sub-groups inside while stopping at a sibling/parent. Test: find_section_range_stops_at_same_level_sibling. 0 failures, clippy clean. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
545367c3f6 |
feat(config): configurable generated-section captions (P2)
TOC / links / tags section headings (and their levels) were hardcoded. Added per-wiki toc_header/toc_header_level, links_header/links_header_level, tags_header/tags_header_level — defaults Contents / Generated Links / Generated Tags at level 1, matching upstream (also fixes the tags index heading: Tags -> Generated Tags). A caption_line(name, level) helper emits the `=`-markers; the configured text + level thread through toc_edit / links_edit / tag_links_edit and the auto_toc save hook. find_section_range matches the configured text, so regeneration stays idempotent at any level. Tests: captions_honour_custom_header_and_level (link_health) + config round-trip + default assertions (index_and_config); existing tag/toc/links tests updated for the new arity and the Generated Tags default. fmt/clippy clean (8-arg ops get allow(too_many_arguments), matching the codebase precedent); 0 Rust test failures; config-parity green. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
2d3db458fb |
feat(config): make listsym_rejected configurable (P2)
The rejected/cancelled checkbox glyph was a hardcoded `const REJECTED = '-'`. ListSyms now carries a `rejected` field (new_with_rejected); a per-wiki `listsym_rejected` key (default `-`) is added to WikiConfig, and WikiConfig::list_syms() builds the palette with it. Routed the three config-driven ListSyms construction sites (parse path in lib.rs + the toggle/cycle commands) through list_syms(), so a custom rejected glyph both lexes and round-trips. Tests: listsyms::custom_rejected_glyph_is_honoured + config round-trip. README/doc/lua config comment updated. fmt clean; 0 Rust test failures. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
624bccbe50 |
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> |