Skip to content

Latest commit

 

History

History
87 lines (71 loc) · 3.64 KB

File metadata and controls

87 lines (71 loc) · 3.64 KB

HPATCH/2 applies one complete target-bearing edit script atomically. Do not call this tool in parallel with other tools. Rejection or cancellation changes nothing.

Use hgrep as replacement of rg or grep. Use hread as replacement of cat or sed. Both return complete lines with current LINE:HASH references for HPATCH/2 targets; hgrep prefixes each match with its quoted path. Never guess or reconstruct a row.

Commands:

in PATH
new PATH
mv PATH
rm
type TARGET VALUE
type- TARGET VALUE
type+ TARGET VALUE

Targets:

LINE:HASH                         complete logical line
LINE:HASH..LINE:HASH              inclusive complete-line range
LINE:HASH "TEXT" [N]              first N exact matches from that row through EOF

type replaces. An empty target-bearing type value deletes every target span, including terminators owned by line and range targets. type- inserts before while preserving the target; type+ inserts after while preserving it. A text target defaults to one match; every requested non-overlapping match must exist or the script rejects.

Use inline JSON-compatible strings for short or single-line values. Include \n when a before/after insertion must form a complete new line:

in parser.go
type- 37:8c2f "// parseCommand parses one physical script line.\n"

Use the fixed <<PATCH frame for multiline or escape-heavy values:

in service.go
type 20:2ff7..28:d10b <<PATCH
func calculateResult(input Input) (Result, error) {
	return computeFreshResult(input), nil
}
PATCH

Create a file with at most one immediately following targetless initializer:

new internal/target.go
type <<PATCH
package internal
PATCH

Every existing file has one immutable baseline for the complete invocation. Pending edits do not shift later targets. When inspected files are ready, batch all short supporting edits that share a failure domain into one call with repeated in PATH sections; do not issue one call per file. Keep unrelated large <<PATCH values in separate calls, with at most one syntax-sensitive multiline Go declaration or function replacement per call; short supporting edits for that same change may remain with it. Prefer the smallest mutation that expresses the semantic change. When a formatter owns formatting, alignment, or indentation, do not replace surrounding lines merely to reproduce its output; let the formatter apply those changes. For example, add one struct field with one insertion rather than replacing the declaration. Preserve required indentation prefixes in indentation-sensitive languages such as Python. Content introduced by a mutation is not targetable in the same call. Before a later invocation targets a file changed by a successful call, discard its saved references and hread only the required region again; do not reread a file that needs no further edit.

Nonempty line and range type replacements preserve the target's final LF, CRLF, or CR when the value omits a terminator. Explicit terminators are authoritative. An empty target-bearing type value removes owned terminators. type- and type+ insert byte-exact values and do not synthesize newlines.

Overlapping replacements/deletions and insertions strictly inside them reject. Boundary insertions are valid. Multiple insertions at the same boundary render in script order.

Changed Go files are parsed and formatted before success; do not run redundant gofmt. Paths remain within the routed workspace root, and parents for new or mv must exist. After rejection, use the router's indexed command or multiline-value-row correction only when the rows still belong to the same baseline; reread stale rows instead of guessing.