( prev: ParseEntry | undefined, kept: ParseEntry[], index: number, )
| 1141 | |
| 1142 | // Helper: Check if '(' is part of command substitution |
| 1143 | function detectCommandSubstitution( |
| 1144 | prev: ParseEntry | undefined, |
| 1145 | kept: ParseEntry[], |
| 1146 | index: number, |
| 1147 | ): boolean { |
| 1148 | if (!prev || typeof prev !== 'string') return false |
| 1149 | if (prev === '$') return true // Standalone $ |
| 1150 | |
| 1151 | if (prev.endsWith('$')) { |
| 1152 | // Check for variable assignment pattern (e.g., result=$) |
| 1153 | if (prev.includes('=') && prev.endsWith('=$')) { |
| 1154 | return true // Variable assignment with command substitution |
| 1155 | } |
| 1156 | |
| 1157 | // Look for text immediately after closing ) |
| 1158 | let depth = 1 |
| 1159 | for (let j = index + 1; j < kept.length && depth > 0; j++) { |
| 1160 | if (isOperator(kept[j], '(')) depth++ |
| 1161 | if (isOperator(kept[j], ')') && --depth === 0) { |
| 1162 | const after = kept[j + 1] |
| 1163 | return !!(after && typeof after === 'string' && !after.startsWith(' ')) |
| 1164 | } |
| 1165 | } |
| 1166 | } |
| 1167 | return false |
| 1168 | } |
| 1169 | |
| 1170 | // Helper: Check if string needs quoting |
| 1171 | function needsQuoting(str: string): boolean { |
no test coverage detected