unfiltered walker tree

This commit is contained in:
2026-09-15 11:16:27 +01:00
parent 6c365e9cde
commit 4396a6f619
4 changed files with 252 additions and 175 deletions
+54 -108
View File
@@ -52,11 +52,15 @@ func Write(result *walker.Result, outputPath string, appendMode bool, singleFile
}
if !singleFile {
root := tree.Build(result.Entries)
treeRoot, err := tree.BuildFullTree(result.AbsRoot, result.Cfg)
if err != nil {
return fmt.Errorf("cannot build tree: %w", err)
}
rootName := filepath.Base(result.AbsRoot)
sb.WriteString("## Directory Tree\n\n")
sb.WriteString(fenceChars + "\n")
sb.WriteString(renderTreeForLLM(root, rootName))
sb.WriteString(renderTreeWithLegend(treeRoot, rootName))
sb.WriteString(fenceChars + "\n\n")
}
@@ -117,13 +121,9 @@ func WriteSlices(result *walker.Result, outputDir, repoName string) ([]string, e
}
}
var generated []string
indexBasename := "index_" + repoName + ".md"
rootPath := filepath.Join(outputDir, indexBasename)
generated = append(generated, rootPath)
if err := writeRootSlice(rootPath, absRoot, rootName, repoName, rootFiles, topLevelDirs, result.OmitTest, result.Commit, result.Instructions); err != nil {
return nil, fmt.Errorf("failed to write root slice: %w", err)
treeRoot, err := tree.BuildFullTree(absRoot, result.Cfg)
if err != nil {
return nil, fmt.Errorf("cannot build full tree: %w", err)
}
var dirNames []string
@@ -132,6 +132,21 @@ func WriteSlices(result *walker.Result, outputDir, repoName string) ([]string, e
}
sort.Strings(dirNames)
for _, dirName := range dirNames {
if node, ok := treeRoot.Children[dirName]; ok {
node.Ref = filepath.Join(dirName, dirName+"_"+repoName+".md")
}
}
var generated []string
indexBasename := "index_" + repoName + ".md"
rootPath := filepath.Join(outputDir, indexBasename)
generated = append(generated, rootPath)
if err := writeRootSlice(rootPath, absRoot, rootName, repoName, rootFiles, topLevelDirs, result.OmitTest, result.Commit, result.Instructions, treeRoot); err != nil {
return nil, fmt.Errorf("failed to write root slice: %w", err)
}
for _, dirName := range dirNames {
sliceName := strings.TrimSuffix(dirName, "/") + "_" + repoName + ".md"
sliceDir := filepath.Join(outputDir, dirName)
@@ -144,17 +159,7 @@ func WriteSlices(result *walker.Result, outputDir, repoName string) ([]string, e
absDir := filepath.Join(absRoot, dirName)
dirEntries := topLevelDirs[dirName]
treeEntries := make([]walker.Entry, len(dirEntries))
for i, e := range dirEntries {
sepIdx := strings.Index(e.RelPath, string(filepath.Separator))
if sepIdx >= 0 {
treeEntries[i] = walker.Entry{RelPath: e.RelPath[sepIdx+1:], Size: e.Size}
} else {
treeEntries[i] = e
}
}
if err := writeDirSlice(slicePath, absDir, absRoot, dirName, treeEntries, dirEntries, indexBasename, result.OmitTest, result.Commit); err != nil {
if err := writeDirSlice(slicePath, absDir, absRoot, dirName, dirEntries, indexBasename, result.OmitTest, result.Commit, treeRoot); err != nil {
return nil, fmt.Errorf("failed to write slice %s: %w", sliceName, err)
}
}
@@ -162,7 +167,7 @@ func WriteSlices(result *walker.Result, outputDir, repoName string) ([]string, e
return generated, nil
}
func writeRootSlice(path, absRoot, rootName, repoName string, rootFiles []walker.Entry, topLevelDirs map[string][]walker.Entry, omitTest bool, commit *git.CommitInfo, instContent string) error {
func writeRootSlice(path, absRoot, rootName, repoName string, rootFiles []walker.Entry, topLevelDirs map[string][]walker.Entry, omitTest bool, commit *git.CommitInfo, instContent string, treeRoot *tree.Node) error {
f, err := os.Create(path)
if err != nil {
return fmt.Errorf("cannot create root file: %w", err)
@@ -179,10 +184,9 @@ func writeRootSlice(path, absRoot, rootName, repoName string, rootFiles []walker
sb.WriteString("\n")
}
treeLines := buildTreeWithRefs(rootName, repoName, topLevelDirs, rootFiles)
sb.WriteString("## Directory Tree\n\n")
sb.WriteString(fenceChars + "\n")
sb.WriteString(treeLines)
sb.WriteString(renderTreeWithLegend(treeRoot, rootName))
sb.WriteString(fenceChars + "\n\n")
sb.WriteString("## Vertical Slices Index\n\n")
@@ -238,7 +242,7 @@ func writeRootSlice(path, absRoot, rootName, repoName string, rootFiles []walker
return err
}
func writeDirSlice(path, absDir, absRoot, dirName string, treeEntries, fileEntries []walker.Entry, rootFileName string, omitTest bool, commit *git.CommitInfo) error {
func writeDirSlice(path, absDir, absRoot, dirName string, fileEntries []walker.Entry, rootFileName string, omitTest bool, commit *git.CommitInfo, treeRoot *tree.Node) error {
f, err := os.Create(path)
if err != nil {
return fmt.Errorf("cannot create slice file: %w", err)
@@ -254,8 +258,7 @@ func writeDirSlice(path, absDir, absRoot, dirName string, treeEntries, fileEntri
sb.WriteString("## Directory Tree\n\n")
sb.WriteString(fenceChars + "\n")
sliceTree := buildTreeFromEntries(dirName, treeEntries)
sb.WriteString(sliceTree)
sb.WriteString(renderTreeWithLegend(treeRoot, filepath.Base(absRoot)))
sb.WriteString(fenceChars + "\n\n")
if len(fileEntries) > 0 {
@@ -287,93 +290,16 @@ func writeDirSlice(path, absDir, absRoot, dirName string, treeEntries, fileEntri
return err
}
func buildTreeWithRefs(rootName, repoName string, topLevelDirs map[string][]walker.Entry, rootFiles []walker.Entry) string {
var sb strings.Builder
sb.WriteString(rootName)
sb.WriteString("/\n")
var dirNames []string
for k := range topLevelDirs {
dirNames = append(dirNames, k)
}
sort.Strings(dirNames)
sort.Slice(rootFiles, func(i, j int) bool {
return rootFiles[i].RelPath < rootFiles[j].RelPath
})
type treeItem struct {
name string
isDir bool
sliceRef string
}
items := make([]treeItem, 0, len(dirNames)+len(rootFiles))
for _, d := range dirNames {
sliceRef := filepath.Join(d, strings.TrimSuffix(d, "/")+"_"+repoName+".md")
items = append(items, treeItem{
name: d,
isDir: true,
sliceRef: sliceRef,
})
}
for _, rf := range rootFiles {
items = append(items, treeItem{
name: rf.RelPath,
isDir: false,
})
}
sort.Slice(items, func(i, j int) bool {
return items[i].name < items[j].name
})
for _, item := range items {
sb.WriteString("+- ")
sb.WriteString(item.name)
if item.isDir {
sb.WriteString("/")
sb.WriteString(" -> see ")
sb.WriteString(item.sliceRef)
}
sb.WriteString("\n")
}
return sb.String()
}
func buildTreeFromEntries(rootName string, entries []walker.Entry) string {
root := &tree.Node{IsDir: true, Children: make(map[string]*tree.Node)}
for _, e := range entries {
parts := strings.Split(e.RelPath, string(filepath.Separator))
cur := root
for i, part := range parts {
isLeaf := i == len(parts)-1
if _, ok := cur.Children[part]; !ok {
node := &tree.Node{Name: part, IsDir: !isLeaf}
if !isLeaf {
node.Children = make(map[string]*tree.Node)
}
cur.Children[part] = node
}
cur = cur.Children[part]
}
}
func renderTreeWithLegend(root *tree.Node, rootName string) string {
var sb strings.Builder
sb.WriteString(rootName)
sb.WriteString("/\n")
renderNodeLLM(&sb, root, "")
return sb.String()
}
func renderTreeForLLM(root *tree.Node, rootName string) string {
var sb strings.Builder
sb.WriteString(rootName)
sb.WriteString("/\n")
renderNodeLLM(&sb, root, "")
if hasAnyAnnotation(root) {
sb.WriteString("Legend: ~ ignored | ~ tests omitted | ~ omitted | ~ exceeded --max-depth\n")
}
return sb.String()
}
@@ -395,6 +321,14 @@ func renderNodeLLM(sb *strings.Builder, node *tree.Node, prefix string) {
if child.IsDir {
sb.WriteString("/")
}
if child.Annotation != "" {
sb.WriteString(" ~ ")
sb.WriteString(child.Annotation)
}
if child.Ref != "" {
sb.WriteString(" -> see ")
sb.WriteString(child.Ref)
}
sb.WriteString("\n")
if child.IsDir && child.Children != nil {
@@ -409,6 +343,18 @@ func renderNodeLLM(sb *strings.Builder, node *tree.Node, prefix string) {
}
}
func hasAnyAnnotation(node *tree.Node) bool {
if node.Annotation != "" {
return true
}
for _, child := range node.Children {
if hasAnyAnnotation(child) {
return true
}
}
return false
}
func readFile(path string) (string, error) {
data, err := os.ReadFile(path)
if err != nil {