styleDiff function

String styleDiff(
  1. UvStyle? from,
  2. UvStyle? to
)

Returns the SGR diff needed to transition from from to to.

Implementation

String styleDiff(UvStyle? from, UvStyle? to) {
  if (from == null && to == null) return '';
  if (from != null && to != null && from == to) return '';
  if (from == null) return styleToSgr(to ?? const UvStyle());

  final simple = _simpleRgbStyleDiff(from, to);
  if (simple != null) return simple;

  if (to == null || to.isZero) {
    // Resetting all styles is cheaper than calculating diffs.
    return UvAnsi.resetStyle;
  }

  final codes = <String>[];

  if (from.fg != to.fg) {
    codes.add(_colorDiffCode(to.fg, _ColorTarget.fg));
  }
  if (from.bg != to.bg) {
    codes.add(_colorDiffCode(to.bg, _ColorTarget.bg));
  }
  if (from.underlineColor != to.underlineColor) {
    codes.add(_colorDiffCode(to.underlineColor, _ColorTarget.underline));
  }

  final fromBold = (from.attrs & Attr.bold) != 0;
  final fromFaint = (from.attrs & Attr.faint) != 0;
  final fromItalic = (from.attrs & Attr.italic) != 0;
  final fromUnderline = from.underline != UnderlineStyle.none;
  final fromBlink = (from.attrs & Attr.blink) != 0;
  final fromRapidBlink = (from.attrs & Attr.rapidBlink) != 0;
  final fromReverse = (from.attrs & Attr.reverse) != 0;
  final fromConceal = (from.attrs & Attr.conceal) != 0;
  final fromStrikethrough = (from.attrs & Attr.strikethrough) != 0;

  final toBold = (to.attrs & Attr.bold) != 0;
  final toFaint = (to.attrs & Attr.faint) != 0;
  final toItalic = (to.attrs & Attr.italic) != 0;
  final toUnderline = to.underline != UnderlineStyle.none;
  final toBlink = (to.attrs & Attr.blink) != 0;
  final toRapidBlink = (to.attrs & Attr.rapidBlink) != 0;
  final toReverse = (to.attrs & Attr.reverse) != 0;
  final toConceal = (to.attrs & Attr.conceal) != 0;
  final toStrikethrough = (to.attrs & Attr.strikethrough) != 0;

  var boldChanged = fromBold != toBold;
  var faintChanged = fromFaint != toFaint;
  if (boldChanged || faintChanged) {
    if ((fromBold && !toBold) || (fromFaint && !toFaint)) {
      codes.add('22');
      boldChanged = true;
      faintChanged = true;
    }
  }

  final italicChanged = fromItalic != toItalic;
  if (italicChanged && !toItalic) {
    codes.add('23');
  }

  final underlineChanged =
      (fromUnderline != toUnderline) || (from.underline != to.underline);
  if (underlineChanged && !toUnderline) {
    codes.add('24');
  }

  var blinkChanged = fromBlink != toBlink;
  var rapidBlinkChanged = fromRapidBlink != toRapidBlink;
  if (blinkChanged || rapidBlinkChanged) {
    if ((fromBlink && !toBlink) || (fromRapidBlink && !toRapidBlink)) {
      codes.add('25');
      blinkChanged = true;
      rapidBlinkChanged = true;
    }
  }

  final reverseChanged = fromReverse != toReverse;
  if (reverseChanged && !toReverse) {
    codes.add('27');
  }

  final concealChanged = fromConceal != toConceal;
  if (concealChanged && !toConceal) {
    codes.add('28');
  }

  final strikethroughChanged = fromStrikethrough != toStrikethrough;
  if (strikethroughChanged && !toStrikethrough) {
    codes.add('29');
  }

  if (boldChanged && toBold) codes.add('1');
  if (faintChanged && toFaint) codes.add('2');
  if (italicChanged && toItalic) codes.add('3');
  if (underlineChanged &&
      toUnderline &&
      to.underline == UnderlineStyle.single) {
    codes.add('4');
  }
  if (blinkChanged && toBlink) codes.add('5');
  if (rapidBlinkChanged && toRapidBlink) codes.add('6');
  if (reverseChanged && toReverse) codes.add('7');
  if (concealChanged && toConceal) codes.add('8');
  if (strikethroughChanged && toStrikethrough) codes.add('9');

  if (underlineChanged &&
      toUnderline &&
      to.underline != UnderlineStyle.single) {
    codes.add(switch (to.underline) {
      UnderlineStyle.none => '24',
      UnderlineStyle.single => '4',
      UnderlineStyle.double => '4:2',
      UnderlineStyle.curly => '4:3',
      UnderlineStyle.dotted => '4:4',
      UnderlineStyle.dashed => '4:5',
    });
  }

  if (codes.isEmpty) return '';
  return '\x1b[${codes.join(';')}m';
}