Files
vamp/docs/development.md
T

7.2 KiB

Development

README

Local verification and implementation constraints. See architecture for ownership and frontend contracts.

Verify

cargo test
cargo clippy --all-targets -- -D warnings
cargo fmt --check
for file in src/ruby_*.rb examples/config.rb examples/plugins/greeting.rb; do
  ruby -c "$file" || exit
done
rubocop

Ruby types

Use YARD @param, @return, and @yieldparam annotations for Ruby APIs, and @type for locals where inference needs help. Examples annotate DSL block parameters before the call, without adding runtime assignments or dependencies. Vamp::Action / Vamp::Mode field types and the dynamically defined mode methods use Solargraph-supported directives.

Core action methods are generated from Rust's authoritative catalog at host startup. Their namespace is annotated, but static Solargraph analysis cannot enumerate those generated members: CLI typecheck can misidentify config.core.select as inherited Kernel#select. Do not maintain a second action list in Ruby comments; use the configuration action reference. Runtime catalog validation remains authoritative.

Ruby implementation and style

Rust embeds the Ruby implementation at compile time: ruby_values.rb owns value validation and core action/mode objects, ruby_config.rb owns configuration and editor contexts, ruby_plugin.rb owns registration and callbacks, and ruby_host.rb owns framed subprocess I/O. Rebuild the editor after changing these files; installed binaries do not load implementation files from the filesystem.

.rubocop.yml uses RuboCop defaults with double-quoted strings (including interpolation) and Ruby 2.6-compatible syntax. Ruby implementation and example files use frozen string literals. Narrow inline style exceptions retain physical STDIN/STDOUT/STDERR capture/redirection and native exception state at the process boundary; plugin output must not corrupt the protocol, and errors including SystemExit and Interrupt must discard effects and report a failure.

Test organization

Rust tests live alongside their modules; native LSP integration checks are in tests/lsp.rs.

  • Editor checks cover Unicode editing, multi-target state, undo/redo, saving failures, and modal paste acceptance and rejection atomicity.
  • Markdown navigation checks cover inline/reference destinations, escaped/percent-encoded paths, heading markup and duplicates, same-document fragments, dirty target reuse, failed navigation atomicity, primary-only following, and gf prefix cancellation/configuration overrides.
  • Jump-history checks cover cross-buffer/same-document navigation, search and picker recording, counts and repeated visits, bounded history, branch truncation, closed buffers, edited-coordinate clamping, dirty text/undo preservation, Ctrl+i/Tab aliases, and custom bindings. Real LSP fixtures cover definition round-trips and delayed replies after leaving and returning to the same source location.
  • Session and Ruby checks exercise real Ruby execution, command/capability ownership, effect validation, configuration fallback, plugin retirement, crash/timeout recovery, and inherited-pipe cleanup.
  • Unix terminal-hook checks use isolated child processes and real PTYs to keep process-global hooks out of the parallel runner. They cover raw/alternate-screen/mouse-capture cleanup on entry failure, normal return, I/O errors, and panics during frame construction, including original panic-payload propagation.
  • Redraw checks inspect actual Crossterm output during repeated scrolling: supporting terminals receive synchronized frames, terminals ignoring synchronization never paint with a visible hardware cursor, and the final caret remains visible. A protocol-state regression verifies that the terminal is not left in synchronized-output mode while the next frame is computed.
  • Wheel checks render document/panel views and cover three-row scrolling, unchanged carets/selections/text, first/last-page clamping, offscreen cursor hiding, no-op/custom-bound navigation reveal, manual persistence through idle/resize/palette updates, and floating/unfocused-docked explorer selection and focus preservation. Queued-input checks verify that the next frame shows ordered wheel steps without crossing a key or resize boundary.
  • Native LSP integration checks launch framed-protocol fixture subprocesses, covering initialization/settings, opt-in startup, synchronization, UTF-16/file-URI conversion, dirty targets, stale requests/diagnostics, and transport failures. Stack checks cover independent initialization, diagnostic merging/clearing, sibling failure isolation in active/parked buffers, same-revision rename/close identity, aggregate limits, first-server position routing, and both shutdowns. Semantic ordering uses protocol/file gates; elapsed deadlines only bound stuck subprocesses.
  • Hover regression checks cover content forms, sanitization, cancelled/superseded replies, invalid results, scrolling/dismissal, Unicode clipping, and preserved editing state. Rendered checks cover longer/wider documentation visibility, Markdown heading and fenced-code colors, scrolled color coordinates, and replacement content without stale highlighting.
  • Semantic-token checks cover full/range requests, legend/modifier remapping, UTF-16 boundaries and grapheme rounding, ASCII tab and Unicode column bounds, refresh/change coalescing, stale rename/close replies, null/empty/error fallback, primary/sibling retirement, and rendered cell precedence with syntax, diagnostics, search, selections, and carets.

Clipboard checks use isolated providers rather than reading or overwriting the desktop clipboard.

Performance and process limits

  • Undo uses full-buffer snapshots and movement scans the current line. This favors straightforward correctness over large-file performance.
  • Rapid-wheel verification must replay bursts against the running editor and measure arrival at the final viewport after input stops, not just individual frame duration. Cheap frames can still accumulate a visible backlog if each queued report requires its own redraw.
  • PTY throughput alone cannot prove terminal presentation stays smooth: capture the editor and terminal while the user reproduces a pause. Synchronized-output commands must not reach the terminal during frame computation, even when individual frames and queued-input catch-up appear fast.
  • Annotation coordinate validation fast-paths ASCII grapheme lengths using byte lengths with CRLF pair accounting, retaining Unicode segmentation for non-ASCII text. Validation remains atomic and still checks every token; large Unicode buffers or diagnostic batches can require foreground work.
  • Legacy synchronous plugin invocation may pause input for up to 500 ms before a host timeout. Async plugins opt into background replies; pending requests and transport queues are bounded. Config/plugin startup has a 2-second deadline per host. Buffer context/document snapshots must fit within a 4 MiB JSON frame; a too-large frame disables that plugin, not editing.

See syntax caches for the current full-tree highlighting ceiling.