ansiToTextSpan function

TextSpan ansiToTextSpan(
  1. String source, {
  2. TextStyle? baseStyle,
})

Converts a string that contains ANSI/ASCII escape codes (SGR sequences) into a TextSpan. Only the most frequently‑used codes are handled (colors, bold, italic, underline, reset). Unknown codes are ignored.

Example:

RichText(
  text: ansiToTextSpan('\x1B[31mHello \x1B[1;34mWorld\x1B[0m!'),
)

Implementation

TextSpan ansiToTextSpan(String source, {TextStyle? baseStyle}) {
  source = _normalizeControlChars(source);
  // 1⃣  Remove cursor‑movement / clear‑screen sequences we can’t show.
  source = _stripNonSgrCsi(source);

  // 2⃣  Parse the remaining SGR codes exactly as before.
  final sgr = RegExp(r'(\x1B|\u001B)\[([0-9;]*)m');

  final List<InlineSpan> spans = [];
  TextStyle current = baseStyle ?? const TextStyle();
  int last = 0;

  for (final m in sgr.allMatches(source)) {
    if (m.start > last) {
      spans.add(
        TextSpan(text: source.substring(last, m.start), style: current),
      );
    }

    final params = m[2]!.isEmpty
        ? <int>[0]
        : m[2]!.split(';').where((s) => s.isNotEmpty).map(int.parse).toList();
    _applySgr(params, (t) => current = t(current)); // mutates `current`

    last = m.end;
  }
  if (last < source.length) {
    spans.add(TextSpan(text: source.substring(last), style: current));
  }

  return TextSpan(style: baseStyle, children: spans);
}