* Build the human-readable error message for an unterminated quote. * Includes a short excerpt of the command around the opening delimiter * so the agent has enough context to locate and fix the problem.
(quoteType: QuoteType, openIndex: number, command: string)
| 56 | * so the agent has enough context to locate and fix the problem. |
| 57 | */ |
| 58 | function unterminatedQuoteMessage(quoteType: QuoteType, openIndex: number, command: string): string { |
| 59 | const labels: Record<QuoteType, string> = { |
| 60 | "posix-single": "single quote (')", |
| 61 | "ansi-c": "ANSI-C quote ($')", |
| 62 | double: 'double quote (")', |
| 63 | locale: 'locale quote ($")', |
| 64 | heredoc: "heredoc (<<)", |
| 65 | } |
| 66 | const snippetStart = Math.max(0, openIndex - 10) |
| 67 | const snippetEnd = Math.min(command.length, openIndex + 20) |
| 68 | const prefix = snippetStart > 0 ? "..." : "" |
| 69 | const suffix = snippetEnd < command.length ? "..." : "" |
| 70 | const excerpt = prefix + command.slice(snippetStart, snippetEnd).replace(/\r?\n/g, "\\n") + suffix |
| 71 | return `Malformed command: unterminated ${labels[quoteType]} at position ${openIndex} -- near: \`${excerpt}\`. ` |
| 72 | } |
| 73 | |
| 74 | /** |
| 75 | * Scan a command string left-to-right with a small state machine and report the |
no test coverage detected