Liking cljdoc? Tell your friends :D

com.blockether.vis.internal.foundation.editing.patch

Pure hashline primitives for content-addressed reading and editing.

Public surface: split-content-lines / char-offset-at-line line-hash / lines->anchors text -> lineno:hash / {ln anchor} render-hashline-block / -range-block tuples -> <hash>| text gutter indices-matching-hash / resolve-anchor-edit-span self-locating range replace

Pure hashline primitives for content-addressed reading and editing.

Public surface:
  split-content-lines / char-offset-at-line
  line-hash / lines->anchors              text -> lineno:hash / {ln anchor}
  render-hashline-block / -range-block   tuples -> `<hash>| text` gutter
  indices-matching-hash / resolve-anchor-edit-span  self-locating range replace
raw docstring

anchor->lineclj

(anchor->line anchor)

Parse the line number out of a <lineno>:<hash> anchor.

Parse the line number out of a `<lineno>:<hash>` anchor.
sourceraw docstring

anchor-map->tuplesclj

(anchor-map->tuples m)

Inverse of lines->anchor-map: {anchor {"text" text}}[[ln text]…] tuples, the line number parsed from each <lineno>:<hash> key and the text pulled from the value's "text", sorted by line. For the channel/human gutter and internal consumers that need tuples.

Inverse of `lines->anchor-map`: `{anchor {"text" text}}` → `[[ln text]…]`
tuples, the line number parsed from each `<lineno>:<hash>` key and the text
pulled from the value's `"text"`, sorted by line. For the channel/human
gutter and internal consumers that need tuples.
sourceraw docstring

anchor-value-textclj

(anchor-value-text v)

Extract the line text from an :anchors / before / after map VALUE. Every model-facing anchor value is a {"text" <line>} map (see lines->anchor-map).

Extract the line text from an `:anchors` / `before` / `after` map VALUE.
Every model-facing anchor value is a `{"text" <line>}` map (see
`lines->anchor-map`).
sourceraw docstring

char-offset-at-lineclj

(char-offset-at-line content line-idx)

Char offset in content where 0-based line line-idx starts. Returns (count content) if line-idx reaches past the last line. Public so the anchor patch planner can map line indices back to char positions for substring splicing.

Char offset in `content` where 0-based line `line-idx` starts.
Returns `(count content)` if `line-idx` reaches past the last line.
Public so the anchor patch planner can map line indices back to char
positions for substring splicing.
sourceraw docstring

hash-line-drift-toleranceclj

How far (in lines) a content hash may sit from its stated line number before resolve-one-anchor calls the anchor MISPLACED and refuses. The common path never needs it — within one patch batch every hunk resolves against the file's ORIGINAL snapshot, so the stated line number is exact and the fast path fires. This window only forgives small drift when the model reuses anchors across patch calls without re-reading; anything larger (the ~200-line gap of a genuinely wrong/stale anchor — the corruption this whole scheme exists to stop) is refused so the model re-reads. Deliberately tight: a false refuse costs one re-read, a false accept corrupts the file.

How far (in lines) a content hash may sit from its stated line number
before `resolve-one-anchor` calls the anchor MISPLACED and refuses. The
common path never needs it — within one patch batch every hunk resolves
against the file's ORIGINAL snapshot, so the stated line number is exact and
the fast path fires. This window only forgives small drift when the model
reuses anchors across patch calls without re-reading; anything larger (the
~200-line gap of a genuinely wrong/stale anchor — the corruption this whole
scheme exists to stop) is refused so the model re-reads. Deliberately tight:
a false refuse costs one re-read, a false accept corrupts the file.
sourceraw docstring

hash-widthclj

Hex chars in a line's content hash. The line number locates; this hash verifies within hash-line-drift-tolerance. Three hex chars keep anchors compact while the line coordinate disambiguates collisions.

Hex chars in a line's content hash. The line number locates; this hash
verifies within `hash-line-drift-tolerance`. Three hex chars keep anchors
compact while the line coordinate disambiguates collisions.
sourceraw docstring

hashline-anchor-sepclj

Separator between the line number and the content hash inside an anchor (<lineno>:<hash>). A single char so the gutter stays narrow.

Separator between the line number and the content hash inside an anchor
(`<lineno>:<hash>`). A single char so the gutter stays narrow.
sourceraw docstring

hashline-gutterclj

Separator between the anchor and the line text in rendered output.

Separator between the anchor and the line text in rendered output.
sourceraw docstring

indices-matching-hashclj

(indices-matching-hash lines h)

0-based indices of lines whose content line-hash equals the bare hash h. Pure content match — the line-number coordinate is applied separately by resolve-one-anchor, so this just answers "which lines carry this content".

0-based indices of `lines` whose content `line-hash` equals the bare hash
`h`. Pure content match — the line-number coordinate is applied separately
by `resolve-one-anchor`, so this just answers "which lines carry this
content".
sourceraw docstring

line-anchorclj

(line-anchor ln text)

The editable anchor for a line: <line-number>:<content-hash> (e.g. 325:0e3). The line number LOCATES the line; the hash VERIFIES its content. patch :from_anchor parses this back via resolve-anchor-range, matching the line number against live content and refusing if the hash no longer agrees (the line changed) or that content now lives far from the stated line (a misattributed / stale anchor). Two coordinates, so a single reused hash can no longer silently land an edit on the wrong line.

The editable anchor for a line: `<line-number>:<content-hash>` (e.g.
`325:0e3`). The line number LOCATES the line; the hash VERIFIES its
content. `patch :from_anchor` parses this back via `resolve-anchor-range`,
matching the line number against live content and refusing if the hash no
longer agrees (the line changed) or that content now lives far from the
stated line (a misattributed / stale anchor). Two coordinates, so a single
reused hash can no longer silently land an edit on the wrong line.
sourceraw docstring

line-hashclj

(line-hash line)

Stable hash-width-hex-char content hash of line (trimmed). Folds the spec'd String/hashCode algorithm over the whitespace-trimmed line, so it is deterministic across JVM runs. The line coordinate disambiguates identical hashes.

Hot path: runs once per line on every cat render AND every patch resolve. Formats with Integer/toHexString + a left-pad rather than java.util.Formatter, which benches ~1.5x slower; the trimmed String/hashCode is a JIT intrinsic so we lean on it instead of a hand loop.

Stable `hash-width`-hex-char content hash of `line` (trimmed). Folds
the spec'd `String/hashCode` algorithm over the whitespace-trimmed
line, so it is deterministic across JVM runs. The line coordinate
disambiguates identical hashes.

Hot path: runs once per line on every `cat` render AND every patch
resolve. Formats with `Integer/toHexString` + a left-pad rather than
java.util.Formatter, which benches ~1.5x slower; the trimmed
`String/hashCode` is a JIT intrinsic so we lean on it instead of a
hand loop.
sourceraw docstring

lines->anchor-mapclj

(lines->anchor-map tuples)

Ordered {anchor {"text" line}} map for [[ln text]…] tuples: a REAL java.util.LinkedHashMap (natively insertion-ordered), built in line order — each KEY is the line's <lineno>:<hash> line-anchor, each VALUE a {"text" <line>} map. This MIRRORS rg's hit value, so a consumer reads v["text"] uniformly across cat and rg (the whole point of the shape). Being an ordered hashmap (not a Clojure map), it stays in file order across the Clojure → JSON/charred → GraalPy dict boundary at ANY size, with NO comparator. EVERY line is keyed (blanks included, so the read stays gap-free); duplicate text differs by line number, so keys are unique. THE single model-facing line payload cat returns; the key IS the patch :from_anchor.

Ordered `{anchor {"text" line}}` map for `[[ln text]…]` tuples: a REAL
`java.util.LinkedHashMap` (natively insertion-ordered), built in line order
— each KEY is the line's `<lineno>:<hash>` `line-anchor`, each VALUE a
`{"text" <line>}` map. This MIRRORS rg's hit value, so a consumer reads
`v["text"]` uniformly across `cat` and `rg` (the whole point of the shape).
Being an ordered hashmap (not a Clojure map), it stays in file order across
the Clojure → JSON/charred → GraalPy dict boundary at ANY size, with NO
comparator. EVERY line is keyed (blanks included, so the read stays
gap-free); duplicate text differs by line number, so keys are unique. THE
single model-facing line payload `cat` returns; the key IS the
`patch :from_anchor`.
sourceraw docstring

lines->anchorsclj

(lines->anchors tuples)

{line-number anchor} map of every non-blank line in tuples, where each anchor is <line-number>:<content-hash> (line-anchor). The canonical :anchors payload cat returns — the SINGLE place it is built (read-file / read-file-ranges / tail-file / rg all route here). Blank lines are omitted: the model only ever sees anchors it can actually edit by. Line numbers come straight from the [ln text] tuples, so a windowed read (range / tail / by-hash) carries the file's real line numbers with NO second full-file pass — the #N file-wide-ordinal scheme (and its whole-file rescan) is gone now that the line number, not the hash, disambiguates duplicate lines.

`{line-number anchor}` map of every non-blank line in `tuples`, where each
anchor is `<line-number>:<content-hash>` (`line-anchor`). The canonical
`:anchors` payload `cat` returns — the SINGLE place it is built (read-file /
read-file-ranges / tail-file / rg all route here). Blank lines are omitted:
the model only ever sees anchors it can actually edit by. Line numbers come
straight from the `[ln text]` tuples, so a windowed read (range / tail /
by-hash) carries the file's real line numbers with NO second full-file pass
— the `#N` file-wide-ordinal scheme (and its whole-file rescan) is gone now
that the line number, not the hash, disambiguates duplicate lines.
sourceraw docstring

render-lineno-blockclj

(render-lineno-block tuples)

Render [line-number text] tuples as a HUMAN line-number gutter <ln>│ <text>, line numbers right-aligned to the widest number in the block. Unlike render-hashline-block (the MODEL surface, whose gutter is the editable :from_anchor anchor), this is the channel/TUI display surface: humans navigate by line number, not by content hash.

Render `[line-number text]` tuples as a HUMAN line-number gutter
`<ln>│ <text>`, line numbers right-aligned to the widest number in
the block. Unlike `render-hashline-block` (the MODEL surface, whose
gutter is the editable `:from_anchor` anchor), this is the channel/TUI
display surface: humans navigate by line number, not by content hash.
sourceraw docstring

render-lineno-range-blockclj

(render-lineno-range-block ranges)

render-lineno-block analogue for :ranges windows — -- range S-E -- headers followed by the human line-number gutter for each window.

`render-lineno-block` analogue for `:ranges` windows — `-- range S-E --`
headers followed by the human line-number gutter for each window.
sourceraw docstring

resolve-anchor-edit-spanclj

(resolve-anchor-edit-span current from_anchor to_anchor replace)

Resolve a content-addressed line-range edit to a CHAR SPAN against current, WITHOUT building new content: {:start S :end E :replacement R :applied-line N} or {:error {:reason KW …}}. Lets a multi-edit batch resolve every anchor against the ORIGINAL snapshot and splice all spans together atomically, so an earlier edit can't drift a later edit's hash/ordinal. to_anchor defaults to from_anchor (single line). The stated line is tried first and only then small drift is considered; duplicate hashes at other lines do not make an exact lineno:hash anchor ambiguous.

Resolve a content-addressed line-range edit to a CHAR SPAN against `current`,
WITHOUT building new content: `{:start S :end E :replacement R :applied-line N}`
or `{:error {:reason KW …}}`. Lets a multi-edit batch resolve every anchor
against the ORIGINAL snapshot and splice all spans together atomically, so an
earlier edit can't drift a later edit's hash/ordinal. `to_anchor` defaults to
`from_anchor` (single line). The stated line is tried first and only then
small drift is considered; duplicate hashes at other lines do not make an
exact `lineno:hash` anchor ambiguous.
sourceraw docstring

resolve-anchor-rangeclj

(resolve-anchor-range current from_anchor to_anchor)

Resolve from_anchor (and to_anchor, defaulting to from_anchor for a single line) against LIVE current. Each is a <line-number>:<hash> anchor: the line number LOCATES it, the hash VERIFIES the content still matches AND sits near the stated line (else :hashline-misplaced — the wrong-line guard). Both coordinates are REQUIRED; a bare hash with no line number is refused (:hashline-malformed). Returns {:from-line N :to-line N} (1-based, INCLUSIVE) or {:error {:reason KW …}}.

Shared by resolve-anchor-edit-span (WRITE — patch :from_anchor) and the cat :anchor READ path so both address lines identically.

Resolve `from_anchor` (and `to_anchor`, defaulting to `from_anchor` for a single
line) against LIVE `current`. Each is a `<line-number>:<hash>` anchor: the
line number LOCATES it, the hash VERIFIES the content still matches AND sits
near the stated line (else `:hashline-misplaced` — the wrong-line guard). Both
coordinates are REQUIRED; a bare hash with no line number is refused
(`:hashline-malformed`). Returns `{:from-line N :to-line N}` (1-based,
INCLUSIVE) or `{:error {:reason KW …}}`.

Shared by `resolve-anchor-edit-span` (WRITE — patch :from_anchor) and the cat
`:anchor` READ path so both address lines identically.
sourceraw docstring

resolve-anchor-range-readclj

(resolve-anchor-range-read current from_anchor to_anchor)

READ-tolerant twin of resolve-anchor-range for the cat :anchor path. A read is NON-DESTRUCTIVE, so a stale/missing hash must not block the look the way it (correctly) blocks a WRITE. Each anchor still resolves by CONTENT first — following small drift exactly like the write path — but when its hash matches no live line the anchor's LINE NUMBER is used as a fallback (a read can safely show whatever now sits at that line). Returns {:from-line N :to-line N :stale? BOOL} (1-based, INCLUSIVE; lines are ordered so the window never inverts; :stale? is true when any hash was missing/misplaced and its line number was used) — or {:error …} ONLY for a genuinely unlocatable anchor (:hashline-malformed — no line number — or :hashline-line-out-of-range — a line outside the file).

READ-tolerant twin of `resolve-anchor-range` for the `cat :anchor` path. A read
is NON-DESTRUCTIVE, so a stale/missing hash must not block the look the way it
(correctly) blocks a WRITE. Each anchor still resolves by CONTENT first —
following small drift exactly like the write path — but when its hash matches no
live line the anchor's LINE NUMBER is used as a fallback (a read can safely show
whatever now sits at that line). Returns `{:from-line N :to-line N :stale? BOOL}`
(1-based, INCLUSIVE; lines are ordered so the window never inverts; `:stale?` is
true when any hash was missing/misplaced and its line number was used) — or
`{:error …}` ONLY for a genuinely unlocatable anchor (`:hashline-malformed` — no
line number — or `:hashline-line-out-of-range` — a line outside the file).
sourceraw docstring

split-content-linesclj

(split-content-lines s)

Split a file blob into a vec of lines. Trailing empty element (from a final newline) is dropped, matching the convention used by the anchor patch planner.

Split a file blob into a vec of lines. Trailing empty element (from a
final newline) is dropped, matching the convention used by the
anchor patch planner.
sourceraw docstring

tuples->rangesclj

(tuples->ranges tuples)

Split flat [[ln text]…] tuples into contiguous :ranges windows [{:range [start end] :lines [[ln text]…]}…], breaking the run whenever the line number jumps by more than 1. Produces exactly the shape render-lineno-range-block / render-hashline-range-block consume, so a flat tuple list (e.g. grouped grep hits) renders with the same -- range S-E -- gap headers as a native multi-range read.

Split flat `[[ln text]…]` tuples into contiguous `:ranges` windows
`[{:range [start end] :lines [[ln text]…]}…]`, breaking the run whenever
the line number jumps by more than 1. Produces exactly the shape
`render-lineno-range-block` / `render-hashline-range-block` consume, so a
flat tuple list (e.g. grouped grep hits) renders with the same
`-- range S-E --` gap headers as a native multi-range read.
sourceraw docstring

cljdoc builds & hosts documentation for Clojure/Script libraries

Keyboard shortcuts
Ctrl+kJump to recent docs
Move to previous article
Move to next article
Ctrl+/Jump to the search field
× close