splitLiveShellLine function

List<String> splitLiveShellLine(
  1. String line
)

Splits a shell line into words the way a POSIX shell does: whitespace separates words, quotes group them, a backslash escapes the next character, and # at the start of a word begins a comment.

Throws a FormatException when a quote isn't closed.

Implementation

List<String> splitLiveShellLine(String line) {
  final List<String> words = [];
  final StringBuffer word = StringBuffer();
  bool inWord = false;
  String? quote;

  for (int i = 0; i < line.length; i++) {
    final String char = line[i];
    if (quote != null) {
      if (char == quote) {
        quote = null;
      } else if (quote == '"' &&
          char == r'\' &&
          i + 1 < line.length &&
          r'"\$`'.contains(line[i + 1])) {
        word.write(line[++i]);
      } else {
        word.write(char);
      }
      continue;
    }
    if (char == "'" || char == '"') {
      quote = char;
      inWord = true;
    } else if (char == r'\' && i + 1 < line.length) {
      word.write(line[++i]);
      inWord = true;
    } else if (char.trim().isEmpty) {
      if (inWord) {
        words.add(word.toString());
        word.clear();
        inWord = false;
      }
    } else if (char == '#' && !inWord) {
      break;
    } else {
      word.write(char);
      inWord = true;
    }
  }

  if (quote != null) {
    throw FormatException('Missing a closing $quote.');
  }
  if (inWord) words.add(word.toString());
  return words;
}