truncatePath function

String truncatePath(
  1. String path,
  2. int maxLength
)

Truncate a path in the middle if too long (width-aware).

Implementation

String truncatePath(String path, int maxLength) {
  if (path.length <= maxLength) return path;

  const separator = '/';
  const ellipsis = '\u2026';
  const ellipsisWidth = 1;
  const separatorWidth = 1;

  final parts = path.split(separator);
  final first = parts.first;
  final last = parts.last;

  if (parts.length == 1) {
    if (path.length <= maxLength) return path;
    return '${path.substring(0, maxLength - 1)}$ellipsis';
  }

  if (first.isEmpty &&
      ellipsisWidth + separatorWidth + last.length >= maxLength) {
    final truncLen = math.max(1, maxLength - separatorWidth);
    return '$separator${last.length <= truncLen ? last : '${last.substring(0, truncLen - 1)}$ellipsis'}';
  }

  if (first.isNotEmpty &&
      ellipsisWidth * 2 + separatorWidth + last.length >= maxLength) {
    final truncLen = math.max(1, maxLength - ellipsisWidth - separatorWidth);
    return '$ellipsis$separator${last.length <= truncLen ? last : '${last.substring(0, truncLen - 1)}$ellipsis'}';
  }

  if (parts.length == 2) {
    final availableForFirst =
        maxLength - ellipsisWidth - separatorWidth - last.length;
    final truncFirst = availableForFirst > 0 && availableForFirst < first.length
        ? first.substring(0, availableForFirst)
        : first;
    return '$truncFirst$ellipsis$separator$last';
  }

  var available =
      maxLength -
      first.length -
      last.length -
      ellipsisWidth -
      2 * separatorWidth;

  if (available <= 0) {
    final availableForFirst = math.max(
      0,
      maxLength - last.length - ellipsisWidth - 2 * separatorWidth,
    );
    final truncFirst = availableForFirst < first.length && availableForFirst > 0
        ? first.substring(0, availableForFirst)
        : first;
    return '$truncFirst$separator$ellipsis$separator$last';
  }

  final middleParts = <String>[];
  for (var i = parts.length - 2; i > 0; i--) {
    final part = parts[i];
    if (part.length + separatorWidth <= available) {
      middleParts.insert(0, part);
      available -= part.length + separatorWidth;
    } else {
      break;
    }
  }

  if (middleParts.isEmpty) {
    return '$first$separator$ellipsis$separator$last';
  }

  return '$first$separator$ellipsis$separator${middleParts.join(separator)}$separator$last';
}