shout/src/update.ts
Chris Wanstrath 24981c6cc0 Merge branch 'code-cleanup'
# Conflicts:
#	src/parse.ts
#	src/run.ts
#	src/update.ts
2026-03-13 14:08:37 -07:00

87 lines
2.7 KiB
TypeScript

import type { CommandResult } from "./run.ts"
import type { ShoutFile } from "./parse.ts"
import { matchOutput } from "./match.ts"
import { isCommentLine } from "./parse.ts"
import { trimTrailingEmpty } from "./utils.ts"
export function rewriteFile(
file: ShoutFile,
results: CommandResult[],
originalContent: string,
): string {
const lines = originalContent.split("\n")
const output: string[] = []
let cmdIdx = 0
for (let i = 0; i < lines.length; i++) {
const line = lines[i]!
if (isCommentLine(line)) {
// Preserve comment lines as-is
output.push(line)
} else if (line.startsWith("$ ") && !line.startsWith("\\$ ")) {
// Emit the command line as-is
output.push(line)
const cmd = file.commands[cmdIdx]
const result = results[cmdIdx]
if (!cmd || !result) {
cmdIdx++
continue
}
// Skip past old expected output lines in the original
let j = i + 1
while (j < lines.length && !isCommentLine(lines[j]!) && !(lines[j]!.startsWith("$ ") && !lines[j]!.startsWith("\\$ "))) {
j++
}
// Collect old expected lines (before trimming trailing blanks for separator)
const oldExpectedRaw = lines.slice(i + 1, j)
// Check if old expected output had an exit code marker
const oldTrimmed = trimTrailingEmpty(oldExpectedRaw)
let oldExitMarker: string | null = null
if (oldTrimmed.length > 0) {
const last = oldTrimmed[oldTrimmed.length - 1]!
if (/^\[(\d+|\*)\]$/.test(last)) {
oldExitMarker = last
}
}
// Determine how many trailing blank lines the original had
let trailingBlanks = 0
for (let k = oldExpectedRaw.length - 1; k >= 0; k--) {
if (oldExpectedRaw[k] === "") trailingBlanks++
else break
}
// If wildcards match, keep original expected output
if (matchOutput(cmd.expected, result.actual)) {
// Output original lines as-is
for (const ol of oldExpectedRaw) output.push(ol)
} else {
// Replace with actual output (escape lines starting with "$ ")
for (const al of result.actual) output.push(escapeDollar(al))
// Re-add exit code marker if it existed
if (oldExitMarker) output.push(oldExitMarker)
// Preserve trailing blank lines as separators
for (let k = 0; k < trailingBlanks; k++) output.push("")
}
// Skip original expected output lines (we already handled them)
i = j - 1
cmdIdx++
} else if (cmdIdx === 0) {
// Lines before first command (shouldn't normally exist but preserve them)
output.push(line)
}
}
return output.join("\n")
}
function escapeDollar(line: string): string {
return line.startsWith("$ ") ? "\\" + line : line
}