Commit Graph

2 Commits

Author SHA1 Message Date
gffranco f1d046fad1 phase 14: list/heading edit commands + CommandOutcome split
CI / cargo fmt --check (push) Successful in 20s
CI / cargo clippy (push) Successful in 1m11s
CI / cargo test (push) Successful in 1m11s
Six new executeCommand entries — the cheap surgical edits that account
for the bulk of vimwiki users' daily keymap traffic. Heavier commands
(table.align/moveColumn/insert, list.changeSymbol/changeLevel/renumber/
removeDone, link.normalize, colorize) are deferred for a follow-up
since each needs its own structural rewriter.

CommandOutcome split:
- `Edit(WorkspaceEdit)` — server applies via apply_edit.
- `Value(Value)` — returned verbatim to the client (used by
  read-only queries like nextTask).
- execute_command handler in lib.rs dispatches both cases.

New commands:
- nuwiki.list.toggleCheckbox — [ ] ↔ [X]; mid-states snap to [X];
  rejected reverts to [ ].
- nuwiki.list.cycleCheckbox — [ ] → [.] → [o] → [O] → [X] → [ ];
  rejected resets to [ ].
- nuwiki.list.rejectCheckbox — toggle the [-] rejected marker.
- nuwiki.list.nextTask — returns Location of the first unfinished
  task after the cursor; wraps to the start of the doc when none
  found below. Only items with checkboxes count.
- nuwiki.heading.addLevel — = → ==; clamps at 6.
- nuwiki.heading.removeLevel — == → =; clamps at 1 (no-op on h1).

Pure ops:
- ops::toggle_state / cycle_state / reject_state — checkbox state
  transitions.
- ops::checkbox_edit / next_task / heading_change_level —
  end-to-end edit producers. Tests drive these directly without
  spinning up a Backend.
- ops::rewrite_heading_with_level — text-level rewrite preserving
  the leading whitespace that marks a centered heading (lives
  outside the heading span, so the edit doesn't touch it).
- ops::find_list_item_at / find_checkbox_span / item_in_list —
  AST + source-text helpers, pub for downstream tooling.

Tests (21 new):
- State transitions: round-trip, progression, dash toggle.
- checkbox_edit: empty → done, partial → cycle, reject path,
  no-op on plain item, no-op off list, nested-sublist resolution.
- heading_change_level: h2→h3, level-6 cap, h3→h2, h1 no-op,
  off-heading no-op, span boundary semantics.
- next_task: first-unfinished, wrap-around, all-done returns
  None, plain items ignored.
- COMMANDS list ↔ handler match.

All 211 prior tests still pass.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 17:41:11 +00:00
gffranco cb4bfae5e7 phase 13: workspace/rename + executeCommand router + nuwiki.file.delete
CI / cargo fmt --check (push) Successful in 29s
CI / cargo clippy (push) Successful in 1m15s
CI / cargo test (push) Successful in 1m15s
Server-side rename with cross-document link rewriting (P11's
read_or_open delivers on its promise) and the first executeCommand
entry. Plus the routing infrastructure that Phases 14-17 will hang
their own commands off of.

commands.rs:
- commands::execute(backend, name, args) dispatches by command name
  and returns the WorkspaceEdit to apply.
- COMMANDS const slice is the source of truth for what's advertised
  in ExecuteCommandOptions.commands.
- First entry: nuwiki.file.delete with args { uri: <Url> } returning
  a WorkspaceEdit with a DeleteFile op.

rename.rs:
- compute_rename(backend, target_uri, new_name, utf8):
  1. Resolve the wiki via wiki_for_uri.
  2. Build new URI from wiki.root + new_name + extension.
  3. Snapshot the index's backlinks for the old page name before
     releasing the read lock so we don't hold it across awaits.
  4. For each backlink, read_or_open the source (live state or
     disk + reparse) and validate the cached span against current
     text.
  5. Rewrite the [[...]] segment with rewrite_wikilink_target,
     preserving anchor and description.
  6. Add the RenameFile op so the builder emits it before the text
     edits in documentChanges ordering.
- build_new_uri handles subdirectory paths and avoids double-
  appending the file extension.
- rewrite_wikilink_target is pub so other tooling can call it.

lib.rs:
- Capabilities: rename_provider + execute_command_provider listing
  commands::COMMANDS.
- New rename handler: cursor-on-wikilink renames the linked page,
  else the buffer's file. Delegates to rename::compute_rename.
- New execute_command handler dispatches via commands::execute, then
  pushes the resulting WorkspaceEdit through client.apply_edit. On
  unknown command or bad args, logs and returns null.
- read_or_open loses its allow(dead_code) attribute now that Phase
  13 calls it.
- rename_target_uri helper shares index-resolution with goto_def.

Tests (11 new in phase13_rename_commands.rs):
- rewrite_wikilink_target: plain, with description, with anchor,
  with both, subdirectory path, non-wikilink-text rejection.
- build_new_uri: under root, with subdirectory, extension dedup,
  empty path segments skipped.
- nuwiki.file.delete builder smoke test (DocumentChanges + DeleteFile).

All 211 v1.0+Phase 11+12 tests still pass.

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