Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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> Branch to compare against (default: main)")
fmt.Println(" --depth, -d <n> Limit tree depth (0 = unlimited)")
fmt.Println(" --importers <file> Check file impact (who imports it, hub status)")
fmt.Println()
fmt.Println("Examples:")
Expand All @@ -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):")
Expand Down Expand Up @@ -182,6 +187,7 @@ func main() {
Files: files,
DiffRef: activeDiffRef,
Impact: impact,
Depth: *depthLimit,
}

// Render or output JSON
Expand Down
46 changes: 43 additions & 3 deletions render/tree.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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 {
Expand All @@ -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 {
Expand Down Expand Up @@ -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)
Expand Down
1 change: 1 addition & 0 deletions scanner/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
Loading