shellSplit function
Splits a shell command tail into the words the shell would pass as
arguments, so --message "hello world" becomes two words rather than
three.
shellQuote round-trips the result: quoting each word back into a command reproduces the same argument list.
A backslash escapes the next character, except inside single quotes and
except on Windows, where cmd gives it no such meaning and it has to stay
a path separator.
ponytail: an unterminated quote takes the rest of the input as one word rather than failing.
Implementation
List<String> shellSplit(String input) {
final words = <String>[];
final current = StringBuffer();
var hasWord = false;
var escaped = false;
String? openQuote;
for (final char in input.split('')) {
if (escaped) {
current.write(char);
escaped = false;
} else if (!Platform.isWindows && char == r'\' && openQuote != "'") {
escaped = true;
hasWord = true;
} else if (openQuote == null && (char == ' ' || char == '\t')) {
if (hasWord) {
words.add(current.toString());
current.clear();
hasWord = false;
}
} else if (openQuote == null && (char == "'" || char == '"')) {
openQuote = char;
hasWord = true;
} else if (openQuote == char) {
openQuote = null;
} else {
current.write(char);
hasWord = true;
}
}
if (hasWord) words.add(current.toString());
return words;
}