Expand description
§hjkl-buffer
Rope-backed text buffer with vim-shaped semantics: charwise/linewise/
blockwise selection, motions matching vim edge cases (no h wrap, $
clamp, sticky col on j/k), folds, viewport, and search.
Extracted from sqeel-buffer with full git history.
§Features
ratatui(off by default): enables therendermodule with a direct cell-writeratatui::widgets::Widgetimpl forBufferviaBufferView.
§Pre-1.0 stability
Pre-1.0: signatures may shift between patch versions. The invariants documented on each type and function are the load-bearing semantics — they will not silently change without a CHANGELOG entry and a deliberate version bump.
§Why so many invariants?
Most of them follow from one rule: the engine layer treats
Buffer as the source of truth for text content. Any divergence
between cached state (engine-side selections, undo stacks, search matches)
and the buffer’s lines() is a bug. The invariants documented on each type
are the contract that lets the engine cache aggressively without risking
that divergence.
Open issues: https://github.com/kryptic-sh/hjkl/issues.
§Testing your Buffer use
Property tests are encouraged for any non-trivial caller. The crate ships
its own test suite; reuse Buffer::from_str to construct fixtures from
inline strings.
Things worth proving:
- After any sequence of valid edits + their inverses, the buffer returns to
its original
lines(). - For any valid
Positionand motion call, the resulting cursor is itself valid. Buffer::dirty_genstrictly increases across mutations and stays constant across read-only queries.
Re-exports§
pub use wrap::Wrap;
Modules§
- wrap
- Soft-wrap helpers shared between the renderer, viewport scroll, and the buffer’s vertical motion code.
Structs§
- Buffer
- In-memory text buffer + cursor.
- Buffer
View - Render-time wrapper around
&Bufferthat carries the optionalSelection+ aStyleResolver. Created per draw, dropped when the frame is done — cheap, holds only refs. - Conceal
- Render-time substitution that hides a byte range and paints
replacementin its place. The buffer’s content stays unchanged; only the rendered cells differ. Used by hosts to pretty-print URLs, conceal markdown markers, etc. - Diag
Overlay - A char-column range on a document row that should be styled with an overlay (e.g. an underline for LSP diagnostics). Applied in a post-paint pass so it composes on top of syntax and selection colours.
- Fold
- A contiguous range of rows that the host can collapse to a single fold-marker line.
- Gutter
- Configuration for the line-number gutter rendered to the left of
the text area.
widthis the total cell count reserved (including any trailing spacer); the renderer right-aligns the 1-based row number into the leftmostwidth - 1cells. - Position
- A
(row, col)location inside acrate::Buffer. - Sign
- Single-cell marker painted into the leftmost gutter column for a
document row. Used by hosts to surface LSP diagnostics, git diff
signs, etc. Higher
prioritywins when multiple signs land on the same row. - Span
- One styled byte range on a buffer row.
- Viewport
- Where the buffer is scrolled to and how big the visible area is.
Enums§
- Edit
- One unit of buffer mutation. Constructed by the caller (vim
engine, ex command, …) and handed to
Buffer::apply_edit. - Gutter
Numbers - Controls what numbers are rendered in the gutter.
- Motion
Kind - Granularity of a delete; preserved through undo so a linewise delete doesn’t come back as a charwise one.
- Selection
- First-class vim selection. Each variant carries the kind directly
rather than relying on a single char-range primitive with separate
“treat as line / block” overlays — that’s the whole point of
owning the buffer model. Anchor is where the user pressed
v/V/Ctrl-V; head moves with the cursor and is updated viaSelection::extend_to.
Traits§
- Style
Resolver - Resolves an opaque
crate::Span::styleid to a real ratatui style. The buffer doesn’t know about colours; the host (sqeel-vim or any future user) keeps a lookup table.
Functions§
- is_
keyword_ char - Match
cagainst a vim-styleiskeywordspec. Tokens are comma-separated; understood forms:@(any alphabetic),_(literal underscore),N-M(decimal char-code range, inclusive), bare integerN(single char code), single ASCII punctuation char (literal). Unknown tokens are ignored.
Type Aliases§
- RowSpan
- Bounds of a selection on a particular row, expressed as inclusive
char-column range.
Nonemeans the row is outside the selection.Some((0, usize::MAX))is the convention for “whole row” — the renderer caps it at the row’s actual length.