4ea76365cd
Move the hash-anchored edit core (hash computation, validation, edit operations, text normalization, chunk formatter, diff utilities, and a runtime-aware xxHash32 binding) into a new @oh-my-opencode/hashline-core workspace package. The src/tools/hashline-edit/ surface becomes a set of thin re-export shims, so existing import paths in the plugin keep working while the pure logic lives behind a stable package boundary that has no opencode runtime dependencies. Tests: bun test packages/hashline-core src/tools/hashline-edit
57 lines
1.7 KiB
TypeScript
57 lines
1.7 KiB
TypeScript
import { parseLineRef } from "./validation"
|
|
import type { HashlineEdit } from "./types"
|
|
|
|
export function getEditLineNumber(edit: HashlineEdit): number {
|
|
switch (edit.op) {
|
|
case "replace":
|
|
return parseLineRef(edit.end ?? edit.pos).line
|
|
case "append":
|
|
return edit.pos ? parseLineRef(edit.pos).line : Number.NEGATIVE_INFINITY
|
|
case "prepend":
|
|
return edit.pos ? parseLineRef(edit.pos).line : Number.NEGATIVE_INFINITY
|
|
default:
|
|
return Number.POSITIVE_INFINITY
|
|
}
|
|
}
|
|
|
|
export function collectLineRefs(edits: HashlineEdit[]): string[] {
|
|
return edits.flatMap((edit) => {
|
|
switch (edit.op) {
|
|
case "replace":
|
|
return edit.end ? [edit.pos, edit.end] : [edit.pos]
|
|
case "append":
|
|
case "prepend":
|
|
return edit.pos ? [edit.pos] : []
|
|
default:
|
|
return []
|
|
}
|
|
})
|
|
}
|
|
|
|
export function detectOverlappingRanges(edits: HashlineEdit[]): string | null {
|
|
const ranges: { start: number; end: number; idx: number }[] = []
|
|
for (let i = 0; i < edits.length; i++) {
|
|
const edit = edits[i]
|
|
if (edit.op !== "replace" || !edit.end) continue
|
|
const start = parseLineRef(edit.pos).line
|
|
const end = parseLineRef(edit.end).line
|
|
ranges.push({ start, end, idx: i })
|
|
}
|
|
if (ranges.length < 2) return null
|
|
|
|
ranges.sort((a, b) => a.start - b.start || a.end - b.end)
|
|
for (let i = 1; i < ranges.length; i++) {
|
|
const prev = ranges[i - 1]
|
|
const curr = ranges[i]
|
|
if (curr.start <= prev.end) {
|
|
return (
|
|
`Overlapping range edits detected: ` +
|
|
`edit ${prev.idx + 1} (lines ${prev.start}-${prev.end}) overlaps with ` +
|
|
`edit ${curr.idx + 1} (lines ${curr.start}-${curr.end}). ` +
|
|
`Use pos-only replace for single-line edits.`
|
|
)
|
|
}
|
|
}
|
|
return null
|
|
}
|