diff --git a/src/tools/hashline-edit/constants.ts b/src/tools/hashline-edit/constants.ts index 4ecf66c46..2eac4d9c2 100644 --- a/src/tools/hashline-edit/constants.ts +++ b/src/tools/hashline-edit/constants.ts @@ -7,5 +7,4 @@ export const HASHLINE_DICT = Array.from({ length: 256 }, (_, i) => { }) export const HASHLINE_REF_PATTERN = /^([0-9]+)#([ZPMQVRWSNKTXJBYH]{2})$/ -export const HASHLINE_OUTPUT_PATTERN = /^([0-9]+)#([ZPMQVRWSNKTXJBYH]{2}):(.*)$/ -export const HASHLINE_LEGACY_REF_PATTERN = /^([0-9]+):([0-9a-fA-F]{2,})$/ +export const HASHLINE_OUTPUT_PATTERN = /^([0-9]+)#([ZPMQVRWSNKTXJBYH]{2})\|(.*)$/ diff --git a/src/tools/hashline-edit/edit-operation-primitives.ts b/src/tools/hashline-edit/edit-operation-primitives.ts index 43904011c..cd93e923d 100644 --- a/src/tools/hashline-edit/edit-operation-primitives.ts +++ b/src/tools/hashline-edit/edit-operation-primitives.ts @@ -80,7 +80,7 @@ export function applyInsertAfter( const result = [...lines] const newLines = stripInsertAnchorEcho(lines[line - 1], toNewLines(text)) if (newLines.length === 0) { - throw new Error(`insert_after requires non-empty text for ${anchor}`) + throw new Error(`append (anchored) requires non-empty text for ${anchor}`) } result.splice(line, 0, ...newLines) return result @@ -97,38 +97,12 @@ export function applyInsertBefore( const result = [...lines] const newLines = stripInsertBeforeEcho(lines[line - 1], toNewLines(text)) if (newLines.length === 0) { - throw new Error(`insert_before requires non-empty text for ${anchor}`) + throw new Error(`prepend (anchored) requires non-empty text for ${anchor}`) } result.splice(line - 1, 0, ...newLines) return result } -export function applyInsertBetween( - lines: string[], - afterAnchor: string, - beforeAnchor: string, - text: string | string[], - options?: EditApplyOptions -): string[] { - if (shouldValidate(options)) { - validateLineRef(lines, afterAnchor) - validateLineRef(lines, beforeAnchor) - } - const { line: afterLine } = parseLineRef(afterAnchor) - const { line: beforeLine } = parseLineRef(beforeAnchor) - if (beforeLine <= afterLine) { - throw new Error(`insert_between requires after_line (${afterLine}) < before_line (${beforeLine})`) - } - - const result = [...lines] - const newLines = stripInsertBoundaryEcho(lines[afterLine - 1], lines[beforeLine - 1], toNewLines(text)) - if (newLines.length === 0) { - throw new Error(`insert_between requires non-empty text for ${afterAnchor}..${beforeAnchor}`) - } - result.splice(beforeLine - 1, 0, ...newLines) - return result -} - export function applyAppend(lines: string[], text: string | string[]): string[] { const normalized = toNewLines(text) if (normalized.length === 0) { diff --git a/src/tools/hashline-edit/edit-operations.test.ts b/src/tools/hashline-edit/edit-operations.test.ts index eb0adbaf0..1940b9e46 100644 --- a/src/tools/hashline-edit/edit-operations.test.ts +++ b/src/tools/hashline-edit/edit-operations.test.ts @@ -1,6 +1,6 @@ import { describe, expect, it } from "bun:test" -import { applyHashlineEdits, applyInsertAfter, applyReplaceLines, applySetLine } from "./edit-operations" -import { applyAppend, applyInsertBetween, applyPrepend } from "./edit-operation-primitives" +import { applyHashlineEdits } from "./edit-operations" +import { applyAppend, applyInsertAfter, applyPrepend, applyReplaceLines, applySetLine } from "./edit-operation-primitives" import { computeLineHash } from "./hash-computation" import type { HashlineEdit } from "./types" @@ -56,16 +56,6 @@ describe("hashline edit operations", () => { expect(result).toEqual("line 1\nbefore 2\nline 2\nline 3") }) - it("applies insert_between with dual anchors", () => { - //#given - const lines = ["line 1", "line 2", "line 3"] - - //#when - const result = applyInsertBetween(lines, anchorFor(lines, 1), anchorFor(lines, 2), ["between"]).join("\n") - - //#then - expect(result).toEqual("line 1\nbetween\nline 2\nline 3") - }) it("throws when insert_after receives empty text array", () => { //#given @@ -85,13 +75,6 @@ describe("hashline edit operations", () => { ).toThrow(/non-empty/i) }) - it("throws when insert_between receives empty text array", () => { - //#given - const lines = ["line 1", "line 2"] - - //#when / #then - expect(() => applyInsertBetween(lines, anchorFor(lines, 1), anchorFor(lines, 2), [])).toThrow(/non-empty/i) - }) it("applies mixed edits in one pass", () => { //#given @@ -215,15 +198,6 @@ describe("hashline edit operations", () => { expect(result).toEqual(["before", "new 1", "new 2", "after"]) }) - it("throws when insert_between payload contains only boundary echoes", () => { - //#given - const lines = ["line 1", "line 2", "line 3"] - - //#when / #then - expect(() => applyInsertBetween(lines, anchorFor(lines, 1), anchorFor(lines, 2), ["line 1", "line 2"])).toThrow( - /non-empty/i - ) - }) it("restores indentation for first replace_lines entry", () => { //#given diff --git a/src/tools/hashline-edit/edit-operations.ts b/src/tools/hashline-edit/edit-operations.ts index 8558b51db..fae662d15 100644 --- a/src/tools/hashline-edit/edit-operations.ts +++ b/src/tools/hashline-edit/edit-operations.ts @@ -88,9 +88,3 @@ export function applyHashlineEdits(content: string, edits: HashlineEdit[]): stri return applyHashlineEditsWithReport(content, edits).content } -export { - applySetLine, - applyReplaceLines, - applyInsertAfter, - applyInsertBefore, -} from "./edit-operation-primitives" diff --git a/src/tools/hashline-edit/index.ts b/src/tools/hashline-edit/index.ts index 97a0ba7b2..b38d63d35 100644 --- a/src/tools/hashline-edit/index.ts +++ b/src/tools/hashline-edit/index.ts @@ -16,9 +16,5 @@ export type { export { NIBBLE_STR, HASHLINE_DICT, HASHLINE_REF_PATTERN, HASHLINE_OUTPUT_PATTERN } from "./constants" export { applyHashlineEdits, - applyInsertAfter, - applyInsertBefore, - applyReplaceLines, - applySetLine, } from "./edit-operations" export { createHashlineEditTool } from "./tools" diff --git a/src/tools/hashline-edit/validation.test.ts b/src/tools/hashline-edit/validation.test.ts index fc401cbf9..cf2457ab3 100644 --- a/src/tools/hashline-edit/validation.test.ts +++ b/src/tools/hashline-edit/validation.test.ts @@ -61,46 +61,3 @@ describe("validateLineRef", () => { .toThrow(/>>>\s+2#[ZPMQVRWSNKTXJBYH]{2}\|two/) }) }) - -describe("legacy LINE:HEX backward compatibility", () => { - it("parses legacy LINE:HEX ref", () => { - //#given - const ref = "42:ab" - - //#when - const result = parseLineRef(ref) - - //#then - expect(result).toEqual({ line: 42, hash: "ab" }) - }) - - it("parses legacy LINE:HEX ref with uppercase hex", () => { - //#given - const ref = "10:FF" - - //#when - const result = parseLineRef(ref) - - //#then - expect(result).toEqual({ line: 10, hash: "FF" }) - }) - - it("legacy ref fails validation with hash mismatch, not parse error", () => { - //#given - const lines = ["function hello() {"] - - //#when / #then - expect(() => validateLineRef(lines, "1:ab")).toThrow(/>>>\s+1#[ZPMQVRWSNKTXJBYH]{2}\|/) - }) - - it("extracts legacy ref from content with markers", () => { - //#given - const ref = ">>> 42:ab|const x = 1" - - //#when - const result = parseLineRef(ref) - - //#then - expect(result).toEqual({ line: 42, hash: "ab" }) - }) -}) diff --git a/src/tools/hashline-edit/validation.ts b/src/tools/hashline-edit/validation.ts index f81ccbaa4..72a332866 100644 --- a/src/tools/hashline-edit/validation.ts +++ b/src/tools/hashline-edit/validation.ts @@ -1,5 +1,5 @@ import { computeLineHash } from "./hash-computation" -import { HASHLINE_REF_PATTERN, HASHLINE_LEGACY_REF_PATTERN } from "./constants" +import { HASHLINE_REF_PATTERN } from "./constants" export interface LineRef { line: number @@ -13,16 +13,13 @@ interface HashMismatch { const MISMATCH_CONTEXT = 2 -const LINE_REF_EXTRACT_PATTERN = /([0-9]+#[ZPMQVRWSNKTXJBYH]{2}|[0-9]+:[0-9a-fA-F]{2,})/ +const LINE_REF_EXTRACT_PATTERN = /([0-9]+#[ZPMQVRWSNKTXJBYH]{2})/ function normalizeLineRef(ref: string): string { const trimmed = ref.trim() if (HASHLINE_REF_PATTERN.test(trimmed)) { return trimmed } - if (HASHLINE_LEGACY_REF_PATTERN.test(trimmed)) { - return trimmed - } const extracted = trimmed.match(LINE_REF_EXTRACT_PATTERN) if (extracted) { @@ -41,13 +38,6 @@ export function parseLineRef(ref: string): LineRef { hash: match[2], } } - const legacyMatch = normalized.match(HASHLINE_LEGACY_REF_PATTERN) - if (legacyMatch) { - return { - line: Number.parseInt(legacyMatch[1], 10), - hash: legacyMatch[2], - } - } throw new Error( `Invalid line reference format: "${ref}". Expected format: "LINE#ID" (e.g., "42#VK")` )