renderUnifiedDiff function

String renderUnifiedDiff(
  1. List<DiffOp> ops, {
  2. DiffOutputFormat format = DiffOutputFormat.plain,
  3. int contextLines = 3,
})

Renders a list of DiffOp to a unified-diff-style string.

ops is typically from MyersDiffUtils.diffLines. contextLines limits how many unchanged lines are shown in a run of equal ops (first and last contextLines each); use a large value to show all.

Implementation

String renderUnifiedDiff(
  List<DiffOp> ops, {
  DiffOutputFormat format = DiffOutputFormat.plain,
  // ignore: avoid_unused_parameters - reserved for context hunk size
  int contextLines = 3,
}) {
  final StringBuffer out = StringBuffer();
  for (final DiffOp op in ops) {
    final String raw = op.text;
    if (raw.isEmpty) continue;
    final List<String> lines = raw.endsWith('\n')
        ? raw
              .replaceRange(raw.length - 1, raw.length, '')
              .split('\n')
              .map((String l) => '$l\n')
              // ignore: saropa_lints/avoid_large_list_copy -- needs an independent mutable copy to rewrite the last line below
              .toList()
        // ignore: saropa_lints/avoid_large_list_copy -- needs an independent mutable copy to rewrite the last line below
        : raw.split('\n').map((String l) => '$l\n').toList();
    if (!raw.endsWith('\n') && lines.isNotEmpty) {
      lines[lines.length - 1] = lines.last.replaceFirst(RegExp(r'\n$'), '');
    }
    final List<String> toEmit = op.kind == DiffOpKind.equal && lines.length > 2 * contextLines
        ? <String>[
            ...lines.take(contextLines),
            '${_kDiffPrefixSpace} ... ${lines.length - 2 * contextLines} lines omitted ...\n',
            ...lines.skip(lines.length - contextLines),
          ]
        : lines;
    for (final String line in toEmit) {
      switch (op.kind) {
        case DiffOpKind.equal:
          out.write(_prefix(format, _kDiffPrefixSpace, line, null));
          break;
        case DiffOpKind.delete:
          out.write(_prefix(format, _kDiffPrefixMinus, line, _kColorRed));
          break;
        case DiffOpKind.insert:
          out.write(_prefix(format, _kDiffPrefixPlus, line, _kColorGreen));
          break;
      }
    }
  }
  return out.toString();
}