splitByAsciiWhitespacePreservingGroups function
Split on ASCII whitespace, but do not split inside parentheses ()/[]
or within single/double quotes.
Implementation
List<String> splitByAsciiWhitespacePreservingGroups(String input) {
if (input.isEmpty) return const <String>[];
final List<String> out = <String>[];
final StringBuffer buf = StringBuffer();
int parenDepth = 0;
int bracketDepth = 0;
String? quote;
bool escape = false;
void flush() {
if (buf.isEmpty) return;
final String token = buf.toString().trim();
buf.clear();
if (token.isNotEmpty) out.add(token);
}
for (int i = 0; i < input.length; i++) {
final String ch = input[i];
final int cu = input.codeUnitAt(i);
if (quote != null) {
buf.write(ch);
if (escape) {
escape = false;
} else if (ch == '\\') {
escape = true;
} else if (ch == quote) {
quote = null;
}
continue;
}
if (ch == '"' || ch == '\'') {
quote = ch;
buf.write(ch);
continue;
}
if (ch == '(') {
parenDepth++;
buf.write(ch);
continue;
}
if (ch == ')') {
parenDepth = parenDepth > 0 ? parenDepth - 1 : 0;
buf.write(ch);
continue;
}
if (ch == '[') {
bracketDepth++;
buf.write(ch);
continue;
}
if (ch == ']') {
bracketDepth = bracketDepth > 0 ? bracketDepth - 1 : 0;
buf.write(ch);
continue;
}
if (parenDepth == 0 && bracketDepth == 0 && isAsciiWhitespaceCodeUnit(cu)) {
flush();
continue;
}
buf.write(ch);
}
flush();
return out;
}