/** * Glob Compressor - Compress file listing while preserving useful structure * * Strategies: * - Collapse deep directory paths * - Group by directory with counts * - Prioritize recently modified files * - Show file type distribution */ function parseFilePath(path) { const parts = path.split('/'); const name = parts.pop() || ''; const dir = parts.join('/') || '.'; const ext = name.includes('.') ? name.split('.').pop()?.toLowerCase() || '' : ''; return { path, dir, name, ext }; } function collapseDirectory(dir, depth) { const parts = dir.split('/').filter(p => p); if (parts.length <= depth) { return dir; } // Keep first and last N parts const keep = Math.floor(depth / 2); const start = parts.slice(0, keep); const end = parts.slice(-keep); return [...start, '...', ...end].join('/'); } function groupByDirectory(files) { const grouped = new Map(); for (const file of files) { const existing = grouped.get(file.dir) || []; existing.push(file); grouped.set(file.dir, existing); } return grouped; } function groupByExtension(files) { const counts = new Map(); for (const file of files) { const ext = file.ext || '(no extension)'; counts.set(ext, (counts.get(ext) || 0) + 1); } return counts; } export function compressGlob(paths, options = {}) { const { maxFiles = 30, collapseDepth = 4, showCounts = true, groupByExtension: showExtensions = true, } = options; const originalCount = paths.length; if (originalCount === 0) { return { content: 'No files found.', originalCount: 0, compressedCount: 0, directories: 0, savings: '0%', }; } const files = paths.map(parseFilePath); const byDir = groupByDirectory(files); const directories = byDir.size; const result = []; // Show extension distribution if configured if (showExtensions && originalCount > 10) { const extCounts = groupByExtension(files); const sorted = Array.from(extCounts.entries()) .sort((a, b) => b[1] - a[1]) .slice(0, 5); result.push('**File types:**'); for (const [ext, count] of sorted) { result.push(` .${ext}: ${count}`); } result.push(''); } // Sort directories by file count (most files first) const sortedDirs = Array.from(byDir.entries()) .sort((a, b) => b[1].length - a[1].length); let totalShown = 0; let dirsShown = 0; for (const [dir, dirFiles] of sortedDirs) { if (totalShown >= maxFiles) { const remainingDirs = sortedDirs.length - dirsShown; const remainingFiles = originalCount - totalShown; if (remainingDirs > 0) { result.push(`\n... [${remainingFiles} more files in ${remainingDirs} directories]`); } break; } const collapsedDir = collapseDirectory(dir, collapseDepth); const fileCount = dirFiles.length; // For directories with many files, show summary if (fileCount > 5) { result.push(`📁 ${collapsedDir}/ (${fileCount} files)`); // Show first few files const sample = dirFiles.slice(0, 3); for (const file of sample) { result.push(` ${file.name}`); totalShown++; } if (fileCount > 3) { result.push(` ... [${fileCount - 3} more]`); } } else { // Show all files for small directories result.push(`📁 ${collapsedDir}/`); for (const file of dirFiles) { result.push(` ${file.name}`); totalShown++; if (totalShown >= maxFiles) break; } } dirsShown++; result.push(''); } // Summary line if (showCounts) { result.unshift(`**Found ${originalCount} files in ${directories} directories**\n`); } const compressedCount = totalShown; const savings = ((1 - result.length / (originalCount + directories)) * 100).toFixed(1); return { content: result.join('\n').trim(), originalCount, compressedCount, directories, savings: `${savings}%`, }; }