* Checks if a bash command is expected to produce no stdout on success. * Used to show "Done" instead of "(No output)" in the UI.
(command: string)
| 176 | * Used to show "Done" instead of "(No output)" in the UI. |
| 177 | */ |
| 178 | function isSilentBashCommand(command: string): boolean { |
| 179 | let partsWithOperators: string[]; |
| 180 | try { |
| 181 | partsWithOperators = splitCommandWithOperators(command); |
| 182 | } catch { |
| 183 | return false; |
| 184 | } |
| 185 | if (partsWithOperators.length === 0) { |
| 186 | return false; |
| 187 | } |
| 188 | let hasNonFallbackCommand = false; |
| 189 | let lastOperator: string | null = null; |
| 190 | let skipNextAsRedirectTarget = false; |
| 191 | for (const part of partsWithOperators) { |
| 192 | if (skipNextAsRedirectTarget) { |
| 193 | skipNextAsRedirectTarget = false; |
| 194 | continue; |
| 195 | } |
| 196 | if (part === '>' || part === '>>' || part === '>&') { |
| 197 | skipNextAsRedirectTarget = true; |
| 198 | continue; |
| 199 | } |
| 200 | if (part === '||' || part === '&&' || part === '|' || part === ';') { |
| 201 | lastOperator = part; |
| 202 | continue; |
| 203 | } |
| 204 | const baseCommand = part.trim().split(/\s+/)[0]; |
| 205 | if (!baseCommand) { |
| 206 | continue; |
| 207 | } |
| 208 | if (lastOperator === '||' && BASH_SEMANTIC_NEUTRAL_COMMANDS.has(baseCommand)) { |
| 209 | continue; |
| 210 | } |
| 211 | hasNonFallbackCommand = true; |
| 212 | if (!BASH_SILENT_COMMANDS.has(baseCommand)) { |
| 213 | return false; |
| 214 | } |
| 215 | } |
| 216 | return hasNonFallbackCommand; |
| 217 | } |
| 218 | |
| 219 | // Commands that should not be auto-backgrounded |
| 220 | const DISALLOWED_AUTO_BACKGROUND_COMMANDS = ['sleep' // Sleep should run in foreground unless explicitly backgrounded by user |
no test coverage detected