diff --git a/main.go b/main.go index 7c7036b..631acd3 100644 --- a/main.go +++ b/main.go @@ -56,11 +56,14 @@ func main() { depsMode := flag.Bool("deps", false, "Enable dependency graph mode (function/import analysis)") diffMode := flag.Bool("diff", false, "Only show files changed vs main (or use --ref to specify branch)") diffRef := flag.String("ref", "main", "Branch/ref to compare against (use with --diff)") + depthLimit := flag.Int("depth", 0, "Limit tree depth (0 = unlimited)") jsonMode := flag.Bool("json", false, "Output JSON (for Python renderer compatibility)") debugMode := flag.Bool("debug", false, "Show debug info (gitignore loading, paths, etc.)") watchMode := flag.Bool("watch", false, "Live file watcher daemon (experimental)") importersMode := flag.String("importers", "", "Check file impact: who imports it, is it a hub?") helpMode := flag.Bool("help", false, "Show help") + // Short flag aliases + flag.IntVar(depthLimit, "d", 0, "Limit tree depth (shorthand)") flag.Parse() if *helpMode { @@ -75,6 +78,7 @@ func main() { fmt.Println(" --deps Dependency flow map (functions & imports)") fmt.Println(" --diff Only show files changed vs main") fmt.Println(" --ref Branch to compare against (default: main)") + fmt.Println(" --depth, -d Limit tree depth (0 = unlimited)") fmt.Println(" --importers Check file impact (who imports it, hub status)") fmt.Println() fmt.Println("Examples:") @@ -84,6 +88,7 @@ func main() { fmt.Println(" codemap --deps /path/to/proj # Dependency flow map") fmt.Println(" codemap --diff # Files changed vs main") fmt.Println(" codemap --diff --ref develop # Files changed vs develop") + fmt.Println(" codemap --depth 3 . # Show only 3 levels deep") fmt.Println(" codemap --importers scanner/types.go # Check file impact") fmt.Println() fmt.Println("Hooks (for Claude Code integration):") @@ -182,6 +187,7 @@ func main() { Files: files, DiffRef: activeDiffRef, Impact: impact, + Depth: *depthLimit, } // Render or output JSON diff --git a/render/tree.go b/render/tree.go index 3913518..dfd78d3 100644 --- a/render/tree.go +++ b/render/tree.go @@ -108,6 +108,7 @@ func Tree(project scanner.Project) { files := project.Files projectName := filepath.Base(project.Root) isDiffMode := project.DiffRef != "" + maxDepth := project.Depth // 0 = unlimited // Calculate stats totalFiles := len(files) @@ -192,7 +193,7 @@ func Tree(project scanner.Project) { // Build and render tree root := buildTreeStructure(files) fmt.Printf("%s%s%s\n", Bold, projectName, Reset) - printTreeNode(root, "", true, topLarge) + printTreeNode(root, "", true, topLarge, 1, maxDepth) // Print impact footer for diff mode if isDiffMode && len(project.Impact) > 0 { @@ -208,7 +209,13 @@ func Tree(project scanner.Project) { } // printTreeNode recursively prints tree nodes -func printTreeNode(node *treeNode, prefix string, isLast bool, topLarge map[string]bool) { +// currentDepth starts at 1 for the root level, maxDepth 0 means unlimited +func printTreeNode(node *treeNode, prefix string, isLast bool, topLarge map[string]bool, currentDepth, maxDepth int) { + // Check if we've exceeded depth limit + if maxDepth > 0 && currentDepth > maxDepth { + return + } + // Separate dirs and files var dirs, fileNodes []*treeNode for _, child := range node.children { @@ -289,7 +296,40 @@ func printTreeNode(node *treeNode, prefix string, isLast bool, topLarge map[stri if isLastDir { newPrefix = prefix + " " } - printTreeNode(current, newPrefix, isLastDir, topLarge) + + // Check if we're at max depth and there's more content below + if maxDepth > 0 && currentDepth >= maxDepth { + // Count hidden content + hiddenDirs := 0 + hiddenFiles := 0 + for _, c := range current.children { + if c.isFile { + hiddenFiles++ + } else { + hiddenDirs++ + } + } + if hiddenDirs > 0 || hiddenFiles > 0 { + var parts []string + if hiddenDirs > 0 { + if hiddenDirs == 1 { + parts = append(parts, "1 directory") + } else { + parts = append(parts, fmt.Sprintf("%d directories", hiddenDirs)) + } + } + if hiddenFiles > 0 { + if hiddenFiles == 1 { + parts = append(parts, "1 file") + } else { + parts = append(parts, fmt.Sprintf("%d files", hiddenFiles)) + } + } + fmt.Printf("%s└── %s... %s%s\n", newPrefix, Dim, strings.Join(parts, ", "), Reset) + } + } else { + printTreeNode(current, newPrefix, isLastDir, topLarge, currentDepth+1, maxDepth) + } } // Print files as a grid (multi-column layout like Python) diff --git a/scanner/types.go b/scanner/types.go index 78fb8d0..859da5d 100644 --- a/scanner/types.go +++ b/scanner/types.go @@ -23,6 +23,7 @@ type Project struct { Files []FileInfo `json:"files"` DiffRef string `json:"diff_ref,omitempty"` Impact []ImpactInfo `json:"impact,omitempty"` + Depth int `json:"depth,omitempty"` // Max tree depth (0 = unlimited) } // FileAnalysis holds extracted info about a single file for deps mode.