Skip to main content

Crate hjkl_buffer

Crate hjkl_buffer 

Source
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 the render module with a direct cell-write ratatui::widgets::Widget impl for Buffer via BufferView.

§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 Position and motion call, the resulting cursor is itself valid.
  • Buffer::dirty_gen strictly 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.
BufferView
Render-time wrapper around &Buffer that carries the optional Selection + a StyleResolver. Created per draw, dropped when the frame is done — cheap, holds only refs.
Conceal
Render-time substitution that hides a byte range and paints replacement in its place. The buffer’s content stays unchanged; only the rendered cells differ. Used by hosts to pretty-print URLs, conceal markdown markers, etc.
DiagOverlay
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. width is the total cell count reserved (including any trailing spacer); the renderer right-aligns the 1-based row number into the leftmost width - 1 cells.
Position
A (row, col) location inside a crate::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 priority wins 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.
GutterNumbers
Controls what numbers are rendered in the gutter.
MotionKind
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 via Selection::extend_to.

Traits§

StyleResolver
Resolves an opaque crate::Span::style id 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 c against a vim-style iskeyword spec. Tokens are comma-separated; understood forms: @ (any alphabetic), _ (literal underscore), N-M (decimal char-code range, inclusive), bare integer N (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. None means 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.