Commit Graph

55 Commits

Author SHA1 Message Date
gffranco 04df170791 feat(vim): :Vimwiki* / :Nuwiki* commands for plain Vim via vim-lsp
CI / cargo fmt --check (push) Successful in 30s
CI / cargo clippy (push) Successful in 1m16s
CI / cargo test (push) Successful in 1m27s
The Phase 19 ftplugin only registered the command surface on Neovim
and finished early for plain Vim, leaving `start-vim.sh` users with
only commentstring + suffixesadd — exactly the "no commands" report.

`autoload/nuwiki/commands.vim` now ships the Vim-side dispatch:
- `s:exec` sends `workspace/executeCommand` through vim-lsp's
  `lsp#send_request`. Optional callback for commands that return data.
- `s:open_uri_from` reads `{ uri }` out of the LSP response and runs
  `:edit` (or `:tabedit` for the tab variants).
- `s:results_to_qf` lifts `checkLinks` / `findOrphans` / `tags.search`
  arrays into the quickfix list and opens `:copen` — same UX as the
  Neovim path.
- `s:open_browser` fires `open` / `xdg-open` after `export.browse`.
- §13.1 deferred commands stub out with a "not yet implemented"
  notification so users get the same signal as on Neovim.

`ftplugin/vimwiki.vim` defines the same `:Vimwiki*` / `:Nuwiki*`
command set on the plain-Vim path, each delegating to its
`nuwiki#commands#…` autoload counterpart. `:VimwikiFollowLink` /
`:VimwikiBacklinks` map straight to vim-lsp's `:LspDefinition` /
`:LspReferences`. coc.nvim users can still use `:CocCommand` directly
and ignore the aliases entirely.

Verified with `vim -e -s -u .vimrc index.wiki`:
  filetype=vimwiki, did_ftplugin=1,
  :VimwikiTOC, :NuwikiIndex, :VimwikiToggleListItem all defined.

Total 377 tests still pass.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 22:23:06 +00:00
gffranco 09b9bd98a3 fix(ftplugin): load on .wiki buffers without manual filetype override
CI / cargo fmt --check (push) Successful in 35s
CI / cargo clippy (push) Successful in 1m12s
CI / cargo test (push) Successful in 1m26s
Three reasons the plugin wasn't activating on `nvim --clean -u init.lua
foo.wiki`:

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

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

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

Verified end-to-end with:

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

Total 377 tests still pass.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 22:16:57 +00:00
gffranco 63e5b6d514 phase 19: editor glue v2
CI / cargo fmt --check (push) Successful in 21s
CI / cargo clippy (push) Successful in 1m8s
CI / cargo test (push) Successful in 1m18s
Server-side:
- New `folding.rs` module with `folding_ranges(ast, total_lines)`.
  Emits one fold per top-level heading (start → line before the
  next same-or-higher-level heading, or EOF) plus one per top-level
  list block. Nested headings fold inside their parent thanks to the
  level-aware end-line computation; sublists fold implicitly via
  their parent item's source span. `FoldingRangeKind::Region` is set
  on every fold so collapsing UIs render them as section folds.
- `Backend::folding_range` handler wires the module into
  `textDocument/foldingRange`; `ServerCapabilities.folding_range_provider`
  advertises it.
- `folding::line_count` exposed for the handler and tests; treats a
  trailing newline as a virtual empty line (the line LSP positions
  use for EOF).

Editor glue (Neovim primary, Vim minimal):
- `lua/nuwiki/commands.lua` — async `workspace/executeCommand`
  wrappers for every server command shipped through Phase 18. The
  open-* family handles `{ uri }` responses by opening the file
  (with `tab` / `split` variants). `check_links` and `find_orphans`
  hand results to `setqflist` + `:copen` for quickfix-style review.
  §13.1-deferred commands (`list.changeSymbol`, table rewriters,
  `link.pasteWikilink/pasteUrl`, `colorize`) stub out with
  `vim.notify` so users get a clear "not yet implemented" signal
  instead of an LSP "unknown command" error.
- `lua/nuwiki/keymaps.lua` — buffer-local default mappings. Subgroups
  (`list_editing`, `header_nav`, `diary`, `html_export`,
  `text_objects`) flip independently via the new
  `mappings.<group>` config. Heading promote/demote uses `g=`/`g-`
  to avoid clobbering Vim's built-in `=`/`-` operators.
- `lua/nuwiki/textobjects.lua` — `ah`/`ih` (around/inside heading)
  using a buffer scan for the heading-block boundary. The four
  remaining text objects from SPEC §12.10 wait until §13.1 lands
  the table/list rewriters they share infrastructure with.
- `lua/nuwiki/folding.lua` — pure regex `foldexpr` + `foldtext`
  fallback for clients without `foldingRange`. Same heading-block
  model as the server.
- `lua/nuwiki/ftplugin.lua` — single per-buffer attach entry point.
  `folding = 'lsp'` (default) uses Neovim 0.11+'s `vim.lsp.foldexpr`,
  falling back to the regex on older versions; `'expr'` forces the
  fallback; `'off'` skips folding setup.
- `lua/nuwiki/config.lua` — extends defaults with `mappings = {...}`
  (P10 keymap layer) and `folding` (P14 resolved).
- `ftplugin/nuwiki.vim` — declares every `:Vimwiki*` / `:Nuwiki*`
  command from SPEC §12.10 by inlining `lua require(...).fn()`
  bodies (no script-local function indirection so commands stay
  callable after re-source). Plain-Vim users get only the buffer
  options; they're expected to drive the LSP via vim-lsp / coc's
  built-in commands.

Health check (§12.10 additions):
- `:checkhealth nuwiki` now reports the count of `executeCommand`
  entries the server advertises, whether `foldingRange` capability
  was negotiated, and whether the configured HTML output directory
  exists + is writable. Default keymap subgroup status is also
  surfaced.

Tests: 8 new in `phase19_folding.rs` covering empty docs, single
heading → EOF, sibling headings each getting their own fold,
nested heading bounded by parent, top-level list folds, single-line
heading non-fold, fold-kind classification, and `line_count`
semantics. Total 377 tests pass; fmt + clippy clean.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 21:57:05 +00:00
gffranco ee61d40872 phase 9: editor glue — plugin, LSP wiring, install, health, docs
CI / cargo fmt --check (push) Successful in 30s
CI / cargo clippy (push) Successful in 1m23s
CI / cargo test (push) Successful in 1m29s
P5 + P6 resolved (SPEC §11): Neovim 0.11+ and Vim 9.1+.

Universal Vim entry:
- plugin/nuwiki.vim dispatches Vim vs Neovim. Neovim path waits for
  the user's `require('nuwiki').setup()` call; Vim path starts the
  LSP client on `FileType vimwiki` and exposes `:NuwikiInstall`.
- ftdetect/nuwiki.vim associates `*.wiki` with the `vimwiki` filetype.
- ftplugin/nuwiki.vim sets commentstring + comments + formatoptions +
  suffixesadd + iskeyword, with a clean `b:undo_ftplugin`.
- syntax/nuwiki.vim ships default `@vimwiki*` highlight links for the
  semantic-token legend (with `level1..6` + `centered` modifiers),
  plus a minimal regex fallback so static highlighting works before
  the LSP attaches.

Lua glue (Neovim 0.11+):
- init.lua exposes setup() / install() / health() — wiring only per
  SPEC §6.2.
- config.lua holds the §7.5 schema (wiki_root / file_extension /
  syntax / log_level) and a tbl_deep_extend apply().
- lsp.lua registers via `vim.lsp.config{} + vim.lsp.enable` on 0.11+;
  falls back to a FileType autocmd calling `vim.lsp.start` on older
  builds. Root dir walks up for `.git` / `.nuwiki`, then uses
  wiki_root.
- install.lua does target-triple detection (Linux gnu/musl x x86_64/
  aarch64, macOS arm/x86, Windows), curl+tar download from the
  release URL, cp/chmod into bin/, with a cargo fallback. Honours
  `g:nuwiki_build_from_source`.
- health.lua implements `:checkhealth nuwiki` per §7.6.

VimL glue (Vim 9.1+):
- autoload/nuwiki/lsp.vim follows §7.4 preference order:
  vim-lsp (calls `lsp#register_server`) → coc.nvim (prints the
  coc-settings.json snippet) → error.
- scripts/download_bin.vim mirrors the Lua installer for Dein /
  vim-plug build hooks — same target triples, same download →
  fallback → cargo build chain.

Help: doc/nuwiki.txt with tags for install (lazy.nvim / vim-plug /
Dein), config options, health, LSP feature list, `:NuwikiInstall`.

Rust workspace unchanged this phase; 172 tests still green locally.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 00:38:09 +00:00
gffranco cf336ee839 phase 0: scaffold workspace, plugin layout, and CI
CI / cargo fmt --check (push) Successful in 46s
CI / cargo clippy (push) Successful in 1m33s
CI / cargo test (push) Successful in 53s
Lay down the empty repo skeleton defined in SPEC.md §5 so subsequent
phases have somewhere to land:

- Cargo workspace (resolver v2, edition 2021, MSRV 1.83) with
  nuwiki-core, nuwiki-lsp, nuwiki-ls — dep direction matches §6.2.
- Vim/Neovim plugin directory layout (plugin, lua, autoload, ftdetect,
  ftplugin, syntax, doc, scripts) with header-only stubs.
- .gitea/workflows/ci.yaml running fmt, clippy -D warnings, and tests
  pinned to Rust 1.83.
- README, dual MIT/Apache-2.0 license texts, .gitignore.

Verified: cargo check / fmt --check / clippy / test all clean.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 16:01:58 +00:00