getTextTruncatedWidth function

({bool ellipsed, int index, bool truncated, num width}) getTextTruncatedWidth(
  1. String input, {
  2. num limit = double.infinity,
  3. String ellipsis = '',
  4. num? ellipsisWidth,
  5. num controlWidth = 0,
  6. num tabWidth = 8,
  7. num emojiWidth = 2,
  8. num regularWidth = 1,
  9. num? wideWidth,
})

Implementation

({num width, int index, bool truncated, bool ellipsed}) getTextTruncatedWidth(
  String input, {
  /*------------- Truncation ----------------*/
  num limit = double.infinity,
  String ellipsis = '',
  num? ellipsisWidth,
  /*------------- Special Width ----------------*/
  num controlWidth = 0,
  num tabWidth = 8,
  /*------------- Other Width ----------------*/
  num emojiWidth = 2,
  num regularWidth = 1,
  num? wideWidth,
}) {
  ellipsisWidth ??= ellipsis.isNotEmpty
      ? getTextTruncatedWidth(
          ellipsis,
          controlWidth: controlWidth,
          tabWidth: tabWidth,
          emojiWidth: emojiWidth,
          regularWidth: regularWidth,
          wideWidth: wideWidth,
        ).width
      : 0;
  const ansiWidth = 0, fullWideWidth = 2;
  wideWidth ??= fullWideWidth;

  final blocks = [
    (_latinPattern, regularWidth),
    (_ansiPattern, ansiWidth),
    (_controlPattern, controlWidth),
    (_tabPattern, tabWidth),
    (_emojiPattern, emojiWidth),
    (_cjktWidePattern, wideWidth),
  ];
  int indexPrev = 0,
      index = 0,
      length = input.length,
      lengthExtra = 0,
      unmatchedStart = 0,
      unmatchedEnd = 0,
      truncationIndex = length;
  num truncationLimit = math.max(0, limit - ellipsisWidth),
      width = 0,
      widthExtra = 0;
  bool truncationEnabled = false;

  parser:
  while (true) {
    if (unmatchedEnd > unmatchedStart ||
        (index >= length && index > indexPrev)) {
      String unmatched = input.safeSubstring(unmatchedStart, unmatchedEnd);
      if (unmatched.isEmpty) unmatched = input.safeSubstring(indexPrev, index);

      lengthExtra = 0;
      for (final char in unmatched.replaceAll(_modifierPattern, '').split('')) {
        final charCode = char.safeCodeUnitAt(0);
        // dart format off
        // ignore: curly_braces_in_flow_control_structures
        if (_isFullWidth(charCode)) widthExtra = fullWideWidth;
        // ignore: curly_braces_in_flow_control_structures
        else if (_isWideNotCjktNoEmmoji(charCode)) widthExtra = wideWidth;
        // ignore: curly_braces_in_flow_control_structures
        else widthExtra = regularWidth;
        // dart format on
        if ((width + widthExtra) > truncationLimit) {
          truncationIndex = math.min(
            truncationIndex,
            math.max(unmatchedStart, indexPrev) + lengthExtra,
          );
        }

        if ((width + widthExtra) > limit) {
          truncationEnabled = true;
          break parser;
        }

        lengthExtra += char.length;
        width += widthExtra;
      }

      unmatchedStart = unmatchedEnd = 0;
    }

    if (index >= length) break parser;
    for (final (blockPattern, blockWidth) in blocks) {
      if (blockPattern.matchAsPrefix(input, index) case final Match match) {
        lengthExtra = blockPattern == _cjktWidePattern
            ? _getCodePointLength(input.safeSubstring(index, match.end))
            : blockPattern == _emojiPattern
            ? 1
            : match.end - index;
        widthExtra = lengthExtra * blockWidth;

        if ((width + widthExtra) > truncationLimit) {
          truncationIndex = math.min(
            truncationIndex,
            index + ((truncationLimit - width) / blockWidth).safeFloor(),
          );
        }

        if ((width + widthExtra) > limit) {
          truncationEnabled = true;
          break parser;
        }

        width += widthExtra;
        unmatchedStart = indexPrev;
        unmatchedEnd = index;
        index = indexPrev = match.end;

        continue parser;
      }
    }

    index += 1;
  }

  return (
    width: (truncationEnabled ? truncationLimit : width),
    index: truncationEnabled ? truncationIndex : length,
    truncated: truncationEnabled,
    ellipsed: truncationEnabled && limit >= ellipsisWidth,
  );
}