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.
§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 content::Content;pub use geom::visual_col_to_char_col;pub use wrap::Wrap;
Modules§
- content
- Per-document text content. Arc-shareable across multiple
crate::Bufferviews. - geom
- Pure geometry helpers for host-driven mouse translation.
- wrap
- Soft-wrap helpers shared between the renderer, viewport scroll, and the buffer’s vertical motion code.
Structs§
- Buffer
- Per-window view onto a
Content. - Fold
- A contiguous range of rows that the host can collapse to a single fold-marker line.
- Position
- A
(row, col)location inside acrate::Buffer. - 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. - 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.
Functions§
- is_
big_ viewport_ jump truewhen a viewport scroll fromprev_toptocur_toplands past the over-provisioned band computed byover_provisioned_range.- 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. - over_
provisioned_ range - Compute an over-provisioned row range for ahead-of-scroll work
(syntax highlight, diagnostics gather, etc.): one viewport above +
the current viewport + one viewport below, clamped to
[0, line_count).
Type Aliases§
- Buffer
Id - Stable per-buffer identifier carried through async pipelines (syntax, git-signs, format-worker) so workers can multiplex per-buffer state without holding buffer references.
- 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.