8c3a0ca2fe
Update error messages to match current op schema: - insert_after → append (anchored) - insert_before → prepend (anchored)
127 lines
3.7 KiB
TypeScript
127 lines
3.7 KiB
TypeScript
import { autocorrectReplacementLines } from "./autocorrect-replacement-lines"
|
|
import {
|
|
restoreLeadingIndent,
|
|
stripInsertAnchorEcho,
|
|
stripInsertBeforeEcho,
|
|
stripInsertBoundaryEcho,
|
|
stripRangeBoundaryEcho,
|
|
toNewLines,
|
|
} from "./edit-text-normalization"
|
|
import { parseLineRef, validateLineRef } from "./validation"
|
|
|
|
interface EditApplyOptions {
|
|
skipValidation?: boolean
|
|
}
|
|
|
|
function shouldValidate(options?: EditApplyOptions): boolean {
|
|
return options?.skipValidation !== true
|
|
}
|
|
|
|
export function applySetLine(
|
|
lines: string[],
|
|
anchor: string,
|
|
newText: string | string[],
|
|
options?: EditApplyOptions
|
|
): string[] {
|
|
if (shouldValidate(options)) validateLineRef(lines, anchor)
|
|
const { line } = parseLineRef(anchor)
|
|
const result = [...lines]
|
|
const originalLine = lines[line - 1] ?? ""
|
|
const corrected = autocorrectReplacementLines([originalLine], toNewLines(newText))
|
|
const replacement = corrected.map((entry, idx) => {
|
|
if (idx !== 0) return entry
|
|
return restoreLeadingIndent(originalLine, entry)
|
|
})
|
|
result.splice(line - 1, 1, ...replacement)
|
|
return result
|
|
}
|
|
|
|
export function applyReplaceLines(
|
|
lines: string[],
|
|
startAnchor: string,
|
|
endAnchor: string,
|
|
newText: string | string[],
|
|
options?: EditApplyOptions
|
|
): string[] {
|
|
if (shouldValidate(options)) {
|
|
validateLineRef(lines, startAnchor)
|
|
validateLineRef(lines, endAnchor)
|
|
}
|
|
|
|
const { line: startLine } = parseLineRef(startAnchor)
|
|
const { line: endLine } = parseLineRef(endAnchor)
|
|
|
|
if (startLine > endLine) {
|
|
throw new Error(
|
|
`Invalid range: start line ${startLine} cannot be greater than end line ${endLine}`
|
|
)
|
|
}
|
|
|
|
const result = [...lines]
|
|
const originalRange = lines.slice(startLine - 1, endLine)
|
|
const stripped = stripRangeBoundaryEcho(lines, startLine, endLine, toNewLines(newText))
|
|
const corrected = autocorrectReplacementLines(originalRange, stripped)
|
|
const restored = corrected.map((entry, idx) => {
|
|
if (idx !== 0) return entry
|
|
return restoreLeadingIndent(lines[startLine - 1] ?? "", entry)
|
|
})
|
|
result.splice(startLine - 1, endLine - startLine + 1, ...restored)
|
|
return result
|
|
}
|
|
|
|
export function applyInsertAfter(
|
|
lines: string[],
|
|
anchor: string,
|
|
text: string | string[],
|
|
options?: EditApplyOptions
|
|
): string[] {
|
|
if (shouldValidate(options)) validateLineRef(lines, anchor)
|
|
const { line } = parseLineRef(anchor)
|
|
const result = [...lines]
|
|
const newLines = stripInsertAnchorEcho(lines[line - 1], toNewLines(text))
|
|
if (newLines.length === 0) {
|
|
throw new Error(`append (anchored) requires non-empty text for ${anchor}`)
|
|
}
|
|
result.splice(line, 0, ...newLines)
|
|
return result
|
|
}
|
|
|
|
export function applyInsertBefore(
|
|
lines: string[],
|
|
anchor: string,
|
|
text: string | string[],
|
|
options?: EditApplyOptions
|
|
): string[] {
|
|
if (shouldValidate(options)) validateLineRef(lines, anchor)
|
|
const { line } = parseLineRef(anchor)
|
|
const result = [...lines]
|
|
const newLines = stripInsertBeforeEcho(lines[line - 1], toNewLines(text))
|
|
if (newLines.length === 0) {
|
|
throw new Error(`prepend (anchored) requires non-empty text for ${anchor}`)
|
|
}
|
|
result.splice(line - 1, 0, ...newLines)
|
|
return result
|
|
}
|
|
|
|
export function applyAppend(lines: string[], text: string | string[]): string[] {
|
|
const normalized = toNewLines(text)
|
|
if (normalized.length === 0) {
|
|
throw new Error("append requires non-empty text")
|
|
}
|
|
if (lines.length === 1 && lines[0] === "") {
|
|
return [...normalized]
|
|
}
|
|
return [...lines, ...normalized]
|
|
}
|
|
|
|
export function applyPrepend(lines: string[], text: string | string[]): string[] {
|
|
const normalized = toNewLines(text)
|
|
if (normalized.length === 0) {
|
|
throw new Error("prepend requires non-empty text")
|
|
}
|
|
if (lines.length === 1 && lines[0] === "") {
|
|
return [...normalized]
|
|
}
|
|
return [...normalized, ...lines]
|
|
}
|