Skip to content

v0.3.0: TUI-only binary (vcd) - #2

Merged
JDonaghy merged 10 commits into
mainfrom
develop
Mar 9, 2026
Merged

v0.3.0: TUI-only binary (vcd)#2
JDonaghy merged 10 commits into
mainfrom
develop

Conversation

@JDonaghy

@JDonaghy JDonaghy commented Mar 9, 2026

Copy link
Copy Markdown
Owner

Summary

  • Add vcd binary target — TUI-only build with no GTK4/Relm4/pangocairo/gio dependency
  • GTK deps gated behind gui Cargo feature (default on), --no-default-features builds headless
  • Release workflow builds and publishes both vimcode-linux-x86_64 and vcd-linux-x86_64
  • Version bump to 0.3.0

Build commands

cargo build --release                                    # GUI (unchanged)
cargo build --release --bin vcd --no-default-features    # TUI-only

Test plan

  • cargo clippy -- -D warnings passes
  • cargo test passes (pre-existing bracket_matching failures only)
  • cargo build --bin vcd --no-default-features compiles without GTK on system
  • CI passes on this PR
  • Merging creates GitHub Release with both binaries

🤖 Generated with Claude Code

JDonaghy and others added 10 commits March 7, 2026 18:15
…pat batch 4

VSCode theme support: drop .json theme files into ~/.config/vimcode/themes/,
apply with :colorscheme <name>. Parses VSCode colors + tokenColors (JSONC with
comment stripping), maps ~25 UI keys + ~15 TextMate scopes to Theme struct.

TUI crash fix: byte_to_char_idx panicked on multi-byte UTF-8 chars (e.g. ─);
now uses floor_char_boundary() to snap to valid char boundaries.

Swap recovery fix: R/D/A keys didn't work in TUI because
handle_swap_recovery_key only checked key_name (empty for regular chars);
now also checks unicode. Message prompt preserved when swap_recovery pending.

TUI sidebar navigation: Ctrl-W h/l navigates between toolbar, sidebar, and
editor. sidebar_sel_bg/sidebar_sel_bg_inactive theme colors for focused vs
unfocused selection. Clicking editor area clears all sidebar/toolbar focus.

Vim compat batch 4: 10 new commands (97% → 98%) — Ctrl-G, gi, Ctrl-W r/R,
[*/]*  comment nav, do/dp diff obtain/put, o_CTRL-V force blockwise.
21 integration tests.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…lorscheme

Replace read-only TUI settings panel with full interactive form matching
GTK version: searchable categories, bool toggles, enum cycling, inline
string/int editing, Ctrl+V paste. Move SettingType/SettingDef/SETTING_DEFS
to settings.rs (core-accessible). Add DynamicEnum variant so colorscheme
picker includes custom VSCode themes. Breadcrumbs bar with tree-sitter
symbol hierarchy. 10 settings panel + 14 breadcrumbs integration tests.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…wildmenu

Sessions 148-150: Netrw in-buffer file browser (:Explore/:Sexplore/:Vexplore),
wildmenu tab-completion for commands, MRU tab switcher with Alt+t binding
(TUI+GTK), modifier-release auto-confirm via GDK polling, sans-serif UI font
for tab bar and popup, and three tab-click bugs fixed (breadcrumbs y-offset,
Pango-measured hit zones replacing monospace approximation, editor_bottom
layout mismatch). Tab bar clicks now skip expensive cursor_move hooks and
defer sidebar tree highlight for instant response.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
VSCode-style tab drag-and-drop: drag tab to edge for new split, drag to
center to move between groups, drag within tab bar to reorder. DropZone/
TabDragState core types, 7 engine methods, GTK overlay rendering. Tab bar
draw order fix (windows before tab bars, dividers before tab bars). New
vim-code.svg gradient logo, removed old icon files. 15 tests.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Visual paste (p/P) in visual mode replaces selection with register
content; register selection ("x) in visual mode; Ctrl+Shift+V clipboard
paste in Normal/Visual for TUI+GTK. Fix TUI tab bar invisible when
breadcrumbs enabled (wrong y-offset in multi-group path). Fix Ctrl-W h/l
to navigate between editor groups before overflowing to sidebar. Fix
pre-existing test failure from swap_scan_stale opening stale swaps.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Extended plugin API with cursor write, settings access, state queries,
buffer insert/delete, register write, 7 new autocmd events, set_mode()
refactor, visual/command keymap fallbacks. Bundled Commentary extension
(gcc/gc/:Commentary, 40+ language comment strings, undo support).
User-configurable keymaps in settings.json ("mode keys :command" format,
multi-key sequences, {count} substitution, :map/:unmap commands).
52 new tests (2809 total).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add "User Keymaps" row to the Settings sidebar (new BufferEditor setting
type). Pressing Enter opens a scratch buffer pre-filled with current
keymaps (one per line, `mode keys :command` format). :w validates each
line, rejects invalid entries with line-specific errors, updates
settings.keymaps, rebuilds user keymaps, and saves to disk. Also
accessible via :Keymaps command. Tab title shows [Keymaps]. Buffer reuse
on re-open. GTK "Edit…" button + count label; TUI "N defined ▸" display.
11 integration tests.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
toggle_comment_range() was calling buffer_mut().delete_range() and
buffer_mut().insert() directly, bypassing undo recording. The undo group
was started/finished but contained no operations, so pressing u after
visual gc said "already at oldest change". Replaced with
delete_with_undo()/insert_with_undo() which properly record operations.
Added 2 undo tests for gcc and visual gc in tests/extensions.rs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…0 VSCode mode

Unified three separate comment implementations (Lua plugin, toggle_comment_range,
vscode_toggle_line_comment) into src/core/comment.rs with 46+ language table,
two-pass toggle algorithm, and override chain (plugin > manifest > built-in > #).
Rewired gcc, visual gc, and Ctrl+/ to use new core. Added :Comment command
(:Commentary alias), vimcode.set_comment_style() plugin API, CommentConfig on
extension manifests. Fixed Ctrl+/ in GTK (key name "slash") and TUI (byte 0x1F
mapping). VSCode mode: Ctrl+Q quit, F10 menu toggle, menu visible by default.
50 new tests (19 unit + 31 integration).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add `vcd` binary target built with `--no-default-features` that excludes
GTK4/Relm4/pangocairo/gio, allowing installation on headless servers.
Cargo features gate GUI deps as optional. Release workflow builds and
publishes both binaries.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@JDonaghy
JDonaghy merged commit aab4cc0 into main Mar 9, 2026
4 checks passed
JDonaghy added a commit that referenced this pull request Apr 21, 2026
Three coordinated changes that make quadraui consumable by a future
non-vimcode app without depending on vimcode infrastructure:

1. **Move design docs into the crate** (`git mv`).
   - `docs/UI_CRATE_DESIGN.md`        → `quadraui/docs/UI_CRATE_DESIGN.md`
   - `docs/DECISIONS_quadraui_primitives.md` → `quadraui/docs/DECISIONS.md`
   The §10 plugin invariants and the "which primitive vs that one"
   rationale now live in the crate that defines them. Light edits to
   strip vimcode-specific language ("already working in src/gtk/" →
   "reference implementation in vimcode's src/gtk/"). PLAN.md +
   PROJECT_STATE.md path references updated.

2. **`quadraui/BACKEND.md`** (new, ~470 lines). Implementer's guide
   for anyone wanting to wire quadraui to a new render target:

   - Mental model (immediate-mode-shaped data flow, no retained tree).
   - The three contracts (owned-data / measurer-parameterised /
     per-primitive). Names the patterns that previously lived only in
     vimcode's `NATIVE_GUI_LESSONS.md` §12-14.
   - Two-pass paint pattern with per-backend wiring notes (TUI loop,
     GTK inline, Win-GUI WM_PAINT). Calls out the GTK idle_add trap
     so the next backend implementer doesn't repeat it.
   - Click-intercept hierarchy (modal → popup → chrome → editor) —
     promotes vimcode's NATIVE_GUI_LESSONS.md §10 lesson into a
     quadraui-level rule.
   - Walkthrough of the new TUI example.
   - Backend-implementer checklist (per-primitive + cross-cutting +
     testing).
   - "When to extend quadraui itself" — the inflection points for
     adding fields vs new primitives vs leaving as app code.

3. **`quadraui/examples/tui_demo.rs`** (new, ~370 lines). A
   self-contained runnable demo using ratatui directly. Exercises:

   - `TabBar` contract end-to-end (pre-measure → fit_active_scroll_offset
     → write back → two-pass paint when state changes).
   - `StatusBar` contract end-to-end (fit_right_start → render visible
     slice → focused-segment highlighting via per-frame state passed
     beside the primitive).
   - Event flow (keys → state mutation → next frame reflects change).

   Adds `ratatui` + `crossterm` as dev-dependencies. Resize the
   terminal narrow + wide while many tabs are open to see both
   contracts in action. Run via `cargo run --example tui_demo`.

The crate's lib.rs and README.md now reference BACKEND.md and the
runnable example. Self-contained from the consumer's perspective —
no required reading lives outside `quadraui/`.

Per Option 3 of the standalone-vs-monorepo discussion: docs are
written as if quadraui were already extracted, so the eventual
`git subtree split` (when app #2 starts) is a mechanical move.
References to vimcode's source tree are framed as "see also" not
"primary reading."

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
JDonaghy added a commit that referenced this pull request Apr 21, 2026
Same demo app as `tui_demo.rs`, rendered with gtk4 + Cairo + Pango.
Identical AppState struct, identical primitive builders, identical
event handlers — only the `draw_*` functions and the main loop
differ. Side-by-side comparison is the fastest way for a backend
implementer to see which parts are app code and which are backend
code.

Why this matters for app #2: TUI uses cell counts (the easy case
where units match the engine's defaults). GTK uses Pango pixel
widths — every non-TUI backend (Win-GUI, macOS, web canvas, wgpu)
needs the pixel-unit measurer pattern. Without a working example
of that pattern, an implementer has to read vimcode's 16k-line
source to figure it out. With this example, they have ~430 lines
of self-contained code that demonstrates exactly the patterns
BACKEND.md describes.

Three patterns demonstrated that the TUI demo can't show:

- **Pixel-unit per-tab measurement**: the per-tab full slot width
  is `TAB_PAD + label_px + TAB_INNER_GAP + close_px + TAB_PAD +
  TAB_OUTER_GAP`. Pre-measured into a Vec<f64>, fed to
  `fit_active_scroll_offset` via a closure that returns
  `tab_widths[i] as usize`. The unit is pixels — same unit
  `available_width` (bar pixel width minus reserved buttons) uses.
- **Two-pass paint inline within `set_draw_func`**: pass 1 paints
  with the immutable engine borrow, the post-paint phase mutates
  app state via RefCell::borrow_mut after the immutable borrow
  drops, pass 2 overdraws the same Cairo context if state changed.
  Critically: NO `idle_add_local_once` (its starvation under
  continuous resize is the lesson #158 layered fixes cost five
  iterations to internalise).
- **Per-frame interaction state passed alongside the primitive**:
  the focused status segment's bold styling comes from a separate
  `focused_id` parameter, not stored on the primitive struct.

Cargo wiring: gtk4 + pangocairo are optional dependencies behind a
new `gtk-example` feature. Default `cargo build` / `cargo test`
work on platforms without GTK4 system libraries (Windows, headless
macOS, etc.). To run:

    cargo run --example gtk_demo --features gtk-example

(needs libgtk-4-dev / gtk4-devel / Homebrew gtk4 installed.)

BACKEND.md §5 (minimal backend walkthrough) now points at both
demos with a "read both before implementing a new backend" framing.
README mirrors that. lib.rs intro lists both with their feature
requirements.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant