--pick flag

This commit is contained in:
2026-09-15 11:42:41 +01:00
parent c72c0d0b79
commit b63f0ba927
4 changed files with 198 additions and 7 deletions
+153 -5
View File
@@ -10,6 +10,7 @@ import (
"unicode/utf8"
"git.flo.fo/FLO/dirmd/internal/config"
"git.flo.fo/FLO/dirmd/internal/filter"
"git.flo.fo/FLO/dirmd/internal/git"
"git.flo.fo/FLO/dirmd/internal/instructions"
"git.flo.fo/FLO/dirmd/internal/tree"
@@ -150,7 +151,17 @@ func WriteSlices(result *walker.Result, outputDir, repoName string) ([]string, e
rootSlicePath := filepath.Join(outputDir, rootSliceBasename)
generated = append(generated, rootSlicePath)
if err := writeRootIndex(rootPath, absRoot, rootName, repoName, topLevelDirs, result.Commit, result.Instructions, treeRoot, result.Cfg); err != nil {
pickInfos := make([]PickInfo, 0)
if len(result.Cfg.PickPaths) > 0 {
pickInfos, err = writePickFiles(absRoot, absRoot, outputDir, result.Cfg, result.OmitTest, result.Commit, treeRoot, result.Cfg.SmallTree)
if err != nil {
return nil, fmt.Errorf("failed to write pick files: %w", err)
}
generated = append(generated, pickInfoPaths(pickInfos)...)
}
if err := writeRootIndex(rootPath, absRoot, rootName, repoName, topLevelDirs, result.Commit, result.Instructions, treeRoot, result.Cfg, pickInfos); err != nil {
return nil, fmt.Errorf("failed to write root index: %w", err)
}
@@ -178,7 +189,137 @@ func WriteSlices(result *walker.Result, outputDir, repoName string) ([]string, e
return generated, nil
}
func writeRootIndex(path, absRoot, rootName, repoName string, topLevelDirs map[string][]walker.Entry, commit *git.CommitInfo, instContent string, treeRoot *tree.Node, cfg *config.Config) error {
type PickInfo struct {
RelPath string
FileType string
SliceDir string
}
func pickInfoPaths(picks []PickInfo) []string {
var paths []string
for _, p := range picks {
paths = append(paths, filepath.Join(p.SliceDir, p.FileType))
}
return paths
}
func writePickFiles(absRoot, baseRoot, outputDir string, cfg *config.Config, omitTest bool, commit *git.CommitInfo, treeRoot *tree.Node, smallTree bool) ([]PickInfo, error) {
var pickInfos []PickInfo
for _, pickPath := range cfg.PickPaths {
fullPath := filepath.Join(absRoot, pickPath)
info, err := os.Stat(fullPath)
if err != nil {
return nil, fmt.Errorf("cannot access pick path %s: %w", pickPath, err)
}
if info.IsDir() {
return nil, fmt.Errorf("pick path must be a file: %s", pickPath)
}
// Validate file passes filters
name := filepath.Base(pickPath)
filter := &filter.Filter{
MaxSize: cfg.MaxSize,
Extensions: cfg.Extensions,
Ignores: cfg.Ignores,
OmitTest: cfg.OmitTest,
FrontendOnly: cfg.FrontendOnly,
OmitMd: cfg.OmitMd,
}
if filter.ShouldSkipFile(fullPath, name, info) {
return nil, fmt.Errorf("pick path %s filtered by active rules", pickPath)
}
// Determine slice dir from first path segment
parts := strings.Split(pickPath, string(filepath.Separator))
sliceDir := outputDir
if len(parts) > 1 {
sliceDir = filepath.Join(outputDir, parts[0])
if err := os.MkdirAll(sliceDir, 0755); err != nil {
return nil, fmt.Errorf("cannot create pick slice directory %s: %w", sliceDir, err)
}
} else {
// Root-level pick
sliceDir = outputDir
}
sliceName := filepath.Base(pickPath) + ".md"
pickPathOut := filepath.Join(sliceDir, sliceName)
if err := writePickFile(pickPathOut, absRoot, pickPath, omitTest, commit, cfg, treeRoot, smallTree); err != nil {
return nil, fmt.Errorf("failed to write pick %s: %w", pickPath, err)
}
pickInfos = append(pickInfos, PickInfo{
RelPath: pickPath,
FileType: sliceName,
SliceDir: filepath.Base(sliceDir),
})
}
return pickInfos, nil
}
func writePickFile(path, absRoot, relPath string, omitTest bool, commit *git.CommitInfo, cfg *config.Config, treeRoot *tree.Node, smallTree bool) error {
f, err := os.Create(path)
if err != nil {
return fmt.Errorf("cannot create pick file: %w", err)
}
defer f.Close()
var sb strings.Builder
fmt.Fprintf(&sb, "# %s [SLICE]\n", filepath.Join(absRoot, relPath))
fmt.Fprintf(&sb, "> Generated: %s\n", time.Now().Format(time.RFC3339))
sb.WriteString(git.FormatCommitLine(commit))
sb.WriteString(FormatFlags(cfg))
fullPath := filepath.Join(absRoot, relPath)
content, err := readFileForOutput(fullPath, omitTest)
if err != nil {
return fmt.Errorf("cannot read pick file %s: %w", relPath, err)
}
language := extToLang(filepath.Ext(relPath))
lines := countLines(content)
if smallTree {
breadcrumb := tree.RenderBreadcrumb(absRoot, relPath)
fmt.Fprintf(&sb, "Tree: %s\n\n", breadcrumb)
} else {
sb.WriteString("## Directory Tree\n\n")
sb.WriteString(fenceChars + "\n")
sb.WriteString(renderTreeWithLegend(treeRoot, filepath.Base(absRoot)))
sb.WriteString(fenceChars + "\n\n")
}
fmt.Fprintf(&sb, "--- FILE: ./%s (%d bytes, %d lines) ---\n", relPath, infoSize(fullPath), lines)
sb.WriteString(fenceChars)
if language != "" {
sb.WriteString(language)
}
sb.WriteString("\n")
sb.WriteString(content)
if !strings.HasSuffix(content, "\n") {
sb.WriteString("\n")
}
sb.WriteString(fmt.Sprintf("%s\n--- END FILE ---\n\n", fenceChars))
_, err = f.WriteString(sb.String())
return err
}
func infoSize(path string) int64 {
info, err := os.Stat(path)
if err != nil {
return 0
}
return info.Size()
}
func writeRootIndex(path, absRoot, rootName, repoName string, topLevelDirs map[string][]walker.Entry, commit *git.CommitInfo, instContent string, treeRoot *tree.Node, cfg *config.Config, picks []PickInfo) error {
f, err := os.Create(path)
if err != nil {
return fmt.Errorf("cannot create root index: %w", err)
@@ -207,11 +348,9 @@ func writeRootIndex(path, absRoot, rootName, repoName string, topLevelDirs map[s
sb.WriteString("| Slice File | Directory | Files | Total Bytes |\n")
sb.WriteString("|------------|-----------|-------|-------------|\n")
// First row: root slice
rootSliceFile := "root_" + repoName + ".md"
rootFileCount := 0
rootFileCount := len(topLevelDirs)
rootTotalBytes := int64(0)
// We'll calculate this in the caller, for now placeholder
fmt.Fprintf(&sb, "| %s | (root) | %d | %d |\n", rootSliceFile, rootFileCount, rootTotalBytes)
for _, dirName := range sortedKeys(topLevelDirs) {
@@ -226,6 +365,15 @@ func writeRootIndex(path, absRoot, rootName, repoName string, topLevelDirs map[s
}
sb.WriteString("\n")
if len(picks) > 0 {
sb.WriteString("## Picks\n\n")
sb.WriteString("These files were explicitly selected via --pick flags.\n\n")
for _, p := range picks {
fmt.Fprintf(&sb, "- `%s` (%s)\n", p.RelPath, p.SliceDir)
}
sb.WriteString("\n")
}
_, err = f.WriteString(sb.String())
return err
}