styleDiff function
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';
}