export function splitShellArgs(raw: string): string[] | null { const tokens: string[] = []; let buf = ""; let inSingle = false; let inDouble = false; let escaped = false; const pushToken = () => { if (buf.length > 0) { tokens.push(buf); buf = ""; } }; for (let i = 0; i < raw.length; i += 1) { const ch = raw[i]; if (escaped) { buf += ch; escaped = false; continue; } if (!inSingle && !inDouble && ch === "\\") { escaped = true; continue; } if (inSingle) { if (ch === "'") { inSingle = false; } else { buf += ch; } continue; } if (inDouble) { if (ch === '"') { inDouble = false; } else { buf += ch; } continue; } if (ch === "'") { inSingle = true; continue; } if (ch === '"') { inDouble = true; continue; } if (/\s/.test(ch)) { pushToken(); continue; } buf += ch; } if (escaped || inSingle || inDouble) { return null; } pushToken(); return tokens; }