* Parse a heredoc delimiter word starting at position `start` in `command`. * The delimiter may be: * - Unquoted: `EOF` -- bare identifier characters * - Single-quoted: `'EOF'` -- literal body, strip outer quotes * - Double-quoted: `"EOF"` -- expandable body, strip outer quote
(command: string, start: number)
| 143 | * of the first character after the delimiter token. |
| 144 | */ |
| 145 | function parseHeredocDelimiter(command: string, start: number): { delimiter: string; endIndex: number } { |
| 146 | let i = start |
| 147 | let delimiter = "" |
| 148 | |
| 149 | if (command[i] === "'") { |
| 150 | i++ // skip opening ' |
| 151 | while (i < command.length && command[i] !== "'" && command[i] !== "\n") { |
| 152 | delimiter += command[i++] |
| 153 | } |
| 154 | if (command[i] === "'") i++ // consume closing ' |
| 155 | } else if (command[i] === '"') { |
| 156 | i++ // skip opening " |
| 157 | while (i < command.length && command[i] !== '"' && command[i] !== "\n") { |
| 158 | delimiter += command[i++] |
| 159 | } |
| 160 | if (command[i] === '"') i++ // consume closing " |
| 161 | } else if (command[i] === "\\") { |
| 162 | i++ // skip backslash |
| 163 | while (i < command.length && command[i] !== "\n" && command[i] !== " " && command[i] !== "\t") { |
| 164 | delimiter += command[i++] |
| 165 | } |
| 166 | } else { |
| 167 | while (i < command.length && command[i] !== "\n" && command[i] !== " " && command[i] !== "\t") { |
| 168 | delimiter += command[i++] |
| 169 | } |
| 170 | } |
| 171 | |
| 172 | return { delimiter, endIndex: i } |
| 173 | } |
| 174 | |
| 175 | /** |
| 176 | * Single shared state-machine walk used by both `findUnterminatedQuote` and |
no outgoing calls
no test coverage detected