renderDiff method

String renderDiff(
  1. ScreenBuffer? previous
)

Emits the ANSI needed to turn previous into this frame, rewriting only the cells that changed. When previous is null (or a different size) the whole frame is drawn.

The returned string positions the cursor as needed and ends with an SGR reset; the caller is responsible for any final cursor placement.

Implementation

String renderDiff(ScreenBuffer? previous) {
  final reusable =
      previous != null &&
      previous.width == width &&
      previous.height == height;
  final out = StringBuffer();
  Style? current; // the SGR currently active in `out`.

  for (var y = 0; y < height; y++) {
    var x = 0;
    while (x < width) {
      final cell = _cells[_index(x, y)];
      final unchanged = reusable && previous._cells[_index(x, y)] == cell;
      if (unchanged) {
        x++;
        continue;
      }
      // Start of a changed run: move the cursor here (1-based) and paint
      // until the cells match `previous` again (or the row ends).
      out.write('\x1b[${y + 1};${x + 1}H');
      while (x < width) {
        final c = _cells[_index(x, y)];
        if (reusable && previous._cells[_index(x, y)] == c) break;
        if (current != c.style) {
          out.write(c.style.sgr);
          current = c.style;
        }
        out.write(c.char);
        x++;
      }
    }
  }
  if (current != null) out.write('\x1b[0m');
  return out.toString();
}