extractHeredocs function

List<HeredocInfo> extractHeredocs(
  1. String input
)

Extract heredoc information from a command string.

Parses << DELIM ... DELIM and <<- DELIM ... DELIM patterns. The delimiter may optionally be quoted with single or double quotes, which suppresses variable expansion inside the heredoc.

Implementation

List<HeredocInfo> extractHeredocs(String input) {
  final results = <HeredocInfo>[];
  final lines = input.split('\n');

  var i = 0;
  while (i < lines.length) {
    final line = lines[i];
    final markers = _findHeredocMarkers(line);

    for (final marker in markers) {
      final stripTabs = marker.strip;
      var delimiter = marker.delimiter;
      var quoted = false;

      // Check for quoting on the delimiter.
      if ((delimiter.startsWith("'") && delimiter.endsWith("'")) ||
          (delimiter.startsWith('"') && delimiter.endsWith('"'))) {
        quoted = true;
        delimiter = delimiter.substring(1, delimiter.length - 1);
      }

      // Collect content until we find the delimiter on its own line.
      final content = StringBuffer();
      var j = i + 1;
      while (j < lines.length) {
        final contentLine = lines[j];
        final trimmed = stripTabs
            ? contentLine.replaceAll(RegExp(r'^\t+'), '')
            : contentLine;
        if (trimmed == delimiter) break;
        if (content.isNotEmpty) content.write('\n');
        content.write(stripTabs ? trimmed : contentLine);
        j++;
      }

      results.add(
        HeredocInfo(
          delimiter: delimiter,
          content: content.toString(),
          stripTabs: stripTabs,
          quoted: quoted,
        ),
      );

      // Advance past the closing delimiter.
      if (j < lines.length) i = j;
    }

    i++;
  }

  return results;
}