renderTree function

List<String> renderTree(
  1. String root,
  2. List<StatEntry> entries, {
  3. required int maxDepth,
})

Renders entries (rooted at the start point root) as a tree-style listing: each line carries the aggregated size, directories are listed first, and subtrees deeper than maxDepth are collapsed (their line still reports the full aggregate). maxDepth == 0 means no depth limit.

Implementation

List<String> renderTree(
  String root,
  List<StatEntry> entries, {
  required int maxDepth,
}) {
  final rootNode = _TreeNode(root, isDir: true);
  for (final e in entries) {
    final rel = _treeRel(root, e.path);
    if (rel.isEmpty) {
      rootNode.isDir = e.isDir;
      rootNode.isLink = e.isLink;
      rootNode.size = e.size;
      continue;
    }
    final parts = rel.split('/');
    var node = rootNode;
    for (var i = 0; i < parts.length; i++) {
      final seg = parts[i];
      if (seg.isEmpty) continue;
      final leaf = i == parts.length - 1;
      final child = node.children.putIfAbsent(seg, () => _TreeNode(seg));
      if (leaf) {
        child.isDir = e.isDir;
        child.isLink = e.isLink;
        child.size = e.size;
      } else {
        child.isDir = true;
      }
      node = child;
    }
  }
  _treeTotals(rootNode);

  final lines = <String>['$root  [${_fmtBytes(rootNode.total)}]'];
  var dirs = 0;
  var files = 0;
  void walk(_TreeNode node, String prefix, int depth) {
    if (maxDepth != 0 && depth > maxDepth) return;
    final kids = node.children.values.toList()
      ..sort((a, b) {
        if (a.isDir != b.isDir) return a.isDir ? -1 : 1;
        return a.name.compareTo(b.name);
      });
    for (var i = 0; i < kids.length; i++) {
      final k = kids[i];
      final last = i == kids.length - 1;
      final label = k.isLink ? '${k.name} ->' : k.name;
      lines.add(
        '$prefix${last ? '└── ' : '├── '}$label  '
        '[${_fmtBytes(k.total)}]',
      );
      if (k.isDir) {
        dirs++;
      } else {
        files++;
      }
      if (k.isDir && k.children.isNotEmpty) {
        walk(k, '$prefix${last ? '    ' : '│   '}', depth + 1);
      }
    }
  }

  walk(rootNode, '', 1);
  lines
    ..add('')
    ..add(
      '$dirs director${dirs == 1 ? 'y' : 'ies'}, '
      '$files file${files == 1 ? '' : 's'}',
    );
  return lines;
}