From 3012507fccb3c5c1b3eb28f2204c3c0004352497 Mon Sep 17 00:00:00 2001 From: Zayden Jung Date: Sat, 16 May 2026 03:55:00 +0800 Subject: [PATCH] a version with known bug fixed but not sure any more obscure ones --- .cliprepo.yaml | 14 +++--- cmd/run.go | 77 ++++++++++++++++++++++++++------ internal/resolver/resolver.go | 83 +++++++++++++++++++++++++++++++++++ internal/utils/glob.go | 44 +++---------------- 4 files changed, 160 insertions(+), 58 deletions(-) create mode 100644 internal/resolver/resolver.go diff --git a/.cliprepo.yaml b/.cliprepo.yaml index 1fa6799..1bb05bd 100644 --- a/.cliprepo.yaml +++ b/.cliprepo.yaml @@ -5,12 +5,14 @@ prompts: preset: "下面的代码来自文件 {{path}}:\n---\n{{content}}" preset: - all: - - "cmd/*" - - "internal/tree/*" - - "internal/utils/*" - - "internal/config/*" - - "main.go" + all: + - "*" + # - "cmd/*" + # - "internal/tree/*" + # - "internal/utils/*" + # - "internal/config/*" + # - "internal/resolver/*" + # - "main.go" internal: - "internal/tree/*" diff --git a/cmd/run.go b/cmd/run.go index 272779b..ab19931 100644 --- a/cmd/run.go +++ b/cmd/run.go @@ -4,14 +4,16 @@ import ( "fmt" "os" "path/filepath" + "sort" "strings" "cliprepo/internal/config" + "cliprepo/internal/resolver" "cliprepo/internal/tree" "cliprepo/internal/utils" - "github.com/spf13/cobra" "github.com/atotto/clipboard" + "github.com/spf13/cobra" ) var delineate string @@ -35,29 +37,74 @@ var runCmd = &cobra.Command{ } var builder strings.Builder - - // builder.WriteString("===== PROJECT TREE =====\n") builder.WriteString(treeStr) builder.WriteString("\n\n") - // 2. preset files - var patterns []string + // 2. resolver (GLOBAL FILE REGISTRY) + r := resolver.New(".") raw, ok := cfg.Preset[delineate] if !ok { return fmt.Errorf("preset not found: %s", delineate) } - patterns = append(patterns, raw...) + patterns := []string(raw) - files, err := utils.ExpandGlob(patterns) - if err != nil { - return err + var files []string + + for _, pattern := range patterns { + + // ========================= + // FULL REPO SCAN + // ========================= + if pattern == "*" { + all, err := r.WalkAll() + if err != nil { + return err + } + files = append(files, all...) + continue + } + + // ========================= + // recursive glob support + // ========================= + if strings.Contains(pattern, "**") { + matches, err := utils.ExpandGlob([]string{pattern}) + if err != nil { + return err + } + + for _, m := range matches { + r.AddFile(m, &files) + } + continue + } + + // ========================= + // normal glob + // ========================= + matches, err := utils.ExpandGlob([]string{pattern}) + if err != nil { + return err + } + + for _, m := range matches { + r.AddFile(m, &files) + } } - // 3. template - template := cfg.Prompts.Preset + // 3. dedup + stable order + files = r.Unique(files) + sort.Strings(files) + // 4. template + template := cfg.Prompts.Preset + if template == "" { + template = "The following code is from file {{path}}:\n---\n{{content}}" + } + + // 5. render for _, file := range files { content, err := os.ReadFile(file) @@ -65,13 +112,14 @@ var runCmd = &cobra.Command{ continue } - path := file + // 先初始化 filePath 变量,避免作用域及同名包冲突 + filePath := file if cfg.Config.PathMode == "absolute" { abs, _ := filepath.Abs(file) - path = abs + filePath = abs } - block := strings.ReplaceAll(template, "{{path}}", path) + block := strings.ReplaceAll(template, "{{path}}", filePath) block = strings.ReplaceAll(block, "{{content}}", string(content)) builder.WriteString(block) @@ -80,6 +128,7 @@ var runCmd = &cobra.Command{ result := builder.String() + // 6. output if useClipboard { return clipboard.WriteAll(result) } diff --git a/internal/resolver/resolver.go b/internal/resolver/resolver.go new file mode 100644 index 0000000..4f9ace8 --- /dev/null +++ b/internal/resolver/resolver.go @@ -0,0 +1,83 @@ +package resolver + +import ( + "cliprepo/internal/tree" + "os" + "path/filepath" +) + +type Resolver struct { + root string + seen map[string]struct{} +} + +func New(root string) *Resolver { + return &Resolver{ + root: root, + seen: make(map[string]struct{}), + } +} + +// WalkAll 遍历所有文件,并自动跳过 .git 和 .gitignore 中的文件 +func (r *Resolver) WalkAll() ([]string, error) { + var result []string + ig, _ := tree.Load(r.root) + + err := filepath.Walk(r.root, func(path string, info os.FileInfo, err error) error { + if err != nil { + return nil + } + + // 显式跳过 .git 目录 + if info.IsDir() && info.Name() == ".git" { + return filepath.SkipDir + } + + rel, _ := filepath.Rel(r.root, path) + + // 遵循 .gitignore 规则 + if ig != nil && ig.MatchesPath(rel) { + if info.IsDir() { + return filepath.SkipDir + } + return nil + } + + if info.IsDir() { + return nil + } + + r.add(rel, &result) + return nil + }) + + return result, err +} + +func (r *Resolver) AddFile(path string, result *[]string) { + r.add(path, result) +} + +func (r *Resolver) add(path string, result *[]string) { + if _, ok := r.seen[path]; ok { + return + } + r.seen[path] = struct{}{} + *result = append(*result, path) +} + +// Unique 保留此方法供 run.go 调用 +func (r *Resolver) Unique(in []string) []string { + seen := make(map[string]struct{}) + out := make([]string, 0, len(in)) + + for _, f := range in { + if _, ok := seen[f]; ok { + continue + } + seen[f] = struct{}{} + out = append(out, f) + } + + return out +} \ No newline at end of file diff --git a/internal/utils/glob.go b/internal/utils/glob.go index 920f6f5..a4049da 100644 --- a/internal/utils/glob.go +++ b/internal/utils/glob.go @@ -3,52 +3,20 @@ package utils import ( "os" "path/filepath" - "strings" + // "strings" ) func ExpandGlob(patterns []string) ([]string, error) { var result []string - seen := make(map[string]struct{}) for _, pattern := range patterns { if pattern == "*" { - filepath.Walk(".", func(path string, info os.FileInfo, err error) error { - if err != nil { - return nil - } - if info.IsDir() { - return nil - } - add(path, seen, &result) - return nil - }) - continue - } - - isRecursive := strings.Contains(pattern, "**") - - if isRecursive { - root := strings.Split(pattern, "**")[0] - if root == "" { - root = "." + files, err := filepath.Glob("**") // fallback + if err != nil { + return nil, err } - - filepath.Walk(root, func(path string, info os.FileInfo, err error) error { - if err != nil || info.IsDir() { - return nil - } - - matched, _ := filepath.Match( - strings.Replace(pattern, "**", "*", 1), - path, - ) - - if matched { - add(path, seen, &result) - } - return nil - }) + result = append(result, files...) continue } @@ -62,7 +30,7 @@ func ExpandGlob(patterns []string) ([]string, error) { if err != nil || info.IsDir() { continue } - add(m, seen, &result) + result = append(result, m) } }