Skip to main content

Crate diffler

Crate diffler 

Source
Expand description

diffler binary internals, exposed as a library so the integration tests can drive the full app (event pump + MCP server) headlessly. The public surface is the binary’s: nothing here is a stable API.

Modules§

app
Application state and event handling. App::handle is a pure-ish state transition (no terminal IO) so the whole shell is unit-testable; rendering reads the state in ui::draw. Per-screen state and handlers live in the status, log, and diff submodules.
ci
Provider-agnostic CI run/job/log acquisition, plus the host glue that picks a provider for the repo and maps a normalized RunDetail onto the graph model. Adapters (providers/) implement ForgeProvider over each forge (via gh/glab/curl through the CommandRunner seam) and never touch the terminal.
clipboard
System clipboard. Two mechanisms, used together for reach without native build deps (so the static musl binaries stay clean): an OSC52 escape sequence — written to the terminal by the main loop after a draw, never from rendering — which the terminal forwards even over ssh/tmux; and a best-effort pipe to the platform clipboard CLI, covering terminals that don’t honor OSC52.
config
Layered TOML configuration: defaults → global file → project file → CLI.
editor
$EDITOR integration. The TUI loop owns the terminal, so opening an editor is a request: App queues an EditorRequest, the main loop suspends the terminal, runs the subprocess, restores the screen, and hands the outcome back to App::editor_finished.
event
Terminal event pump: crossterm’s async stream plus a periodic tick, multiplexed onto one channel. Kept thin — all decisions live in App::handle, which is what the tests drive.
graph
A navigable orthogonal node-graph component for ratatui, plus the host glue mapping the app theme onto its palette. The component is IO-free (no terminal setup, event loop, or network); the host builds a Model (from CI, …), pushes it into a GraphView, renders it, and reacts to GraphActions.
keymap
Key bindings: neogit-style defaults per screen, overridable from [keys.*] config sections, with multi-key sequence resolution.
lsp
Language-server access for the blast-radius view: which callers a changed symbol has beyond the diff. One client per language, spawned on demand.
mcp
Embedded MCP server: agents read review comments, answer them in place, and long-poll for the human’s feedback. Tool handlers never touch the review directly — every call is sent through the app event channel as an McpRequest and answered by App::handle_mcp on the main loop, so the app stays the single owner of all state (no locks).
search
Vim-style / search. A pane feeds Search its rows as (row index, text); the search holds the query, matches, and active match, and drives incremental highlight + n/N navigation. Matching is plain substring with smartcase: case-insensitive unless the query has an uppercase letter.
theme
Color themes. github-dark is the default; ui.theme selects a built-in, each pairing its palette with a matching syntax-highlight theme.
transient
Magit/neogit-style transient menus: a top-level prefix key opens a transient whose own keys are pure leaves (immediate actions). The model is data, not closures, so resolution and the which-key panel layout stay pure and unit-testable; the app owns the live transient state and timer.
tree
The shared sidebar row vocabulary (TreeRow/TreeNode) and pure directory-trie flattening, used by the diff sidebar and the status sections. visible_rows turns a file list (repo-relative paths, in input order) into visible rows honoring fold state — directories before files at each level, input order preserved within a kind, folded directories hiding their subtree. It only ever emits Dir and File rows; Section rows are composed by the diff sidebar’s review layout on top of the same vocabulary. No rendering and no app state, so the navigation math is fully unit-testable.
ui
Rendering. draw never computes review state; it reads App (the diff view additionally fills its lazy highlight cache and follows the cursor with its scroll offset, which is why it takes &mut App).
watch
Filesystem watcher: debounced notify events on the repo become AppEvent::RepoChanged. Noise sources (the session store, lockfiles, git’s object database) are filtered out so staging or saving a comment does not echo back as a repo change.