unfiltered walker tree
This commit is contained in:
+54
-108
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user