* Format files as a tree structure
(
files: { path: string; language: string; nodeCount: number }[],
includeMetadata: boolean,
maxDepth?: number
)
| 4539 | * Format files as a tree structure |
| 4540 | */ |
| 4541 | private formatFilesTree( |
| 4542 | files: { path: string; language: string; nodeCount: number }[], |
| 4543 | includeMetadata: boolean, |
| 4544 | maxDepth?: number |
| 4545 | ): string { |
| 4546 | // Build tree structure |
| 4547 | interface TreeNode { |
| 4548 | name: string; |
| 4549 | children: Map<string, TreeNode>; |
| 4550 | file?: { language: string; nodeCount: number }; |
| 4551 | } |
| 4552 | |
| 4553 | const root: TreeNode = { name: '', children: new Map() }; |
| 4554 | |
| 4555 | for (const file of files) { |
| 4556 | const parts = file.path.split('/'); |
| 4557 | let current = root; |
| 4558 | |
| 4559 | for (let i = 0; i < parts.length; i++) { |
| 4560 | const part = parts[i]; |
| 4561 | if (!part) continue; |
| 4562 | |
| 4563 | if (!current.children.has(part)) { |
| 4564 | current.children.set(part, { name: part, children: new Map() }); |
| 4565 | } |
| 4566 | current = current.children.get(part)!; |
| 4567 | |
| 4568 | // If this is the last part, it's a file |
| 4569 | if (i === parts.length - 1) { |
| 4570 | current.file = { language: file.language, nodeCount: file.nodeCount }; |
| 4571 | } |
| 4572 | } |
| 4573 | } |
| 4574 | |
| 4575 | // Render tree |
| 4576 | const lines: string[] = [`**Project Structure (${files.length} files)**`, '']; |
| 4577 | |
| 4578 | const renderNode = (node: TreeNode, prefix: string, isLast: boolean, depth: number): void => { |
| 4579 | if (maxDepth !== undefined && depth > maxDepth) return; |
| 4580 | |
| 4581 | const connector = isLast ? '└── ' : '├── '; |
| 4582 | const childPrefix = isLast ? ' ' : '│ '; |
| 4583 | |
| 4584 | if (node.name) { |
| 4585 | let line = prefix + connector + node.name; |
| 4586 | if (node.file && includeMetadata) { |
| 4587 | line += ` (${node.file.language}, ${node.file.nodeCount} symbols)`; |
| 4588 | } |
| 4589 | lines.push(line); |
| 4590 | } |
| 4591 | |
| 4592 | const children = [...node.children.values()]; |
| 4593 | // Sort: directories first, then files, both alphabetically |
| 4594 | children.sort((a, b) => { |
| 4595 | const aIsDir = a.children.size > 0 && !a.file; |
| 4596 | const bIsDir = b.children.size > 0 && !b.file; |
| 4597 | if (aIsDir !== bIsDir) return aIsDir ? -1 : 1; |
| 4598 | return a.name.localeCompare(b.name); |
no test coverage detected