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 }