92 lines
2.1 KiB
Go
92 lines
2.1 KiB
Go
package bundle
|
||
|
||
import (
|
||
"fmt"
|
||
"os"
|
||
"strings"
|
||
|
||
"cliprepo/internal/config"
|
||
"github.com/atotto/clipboard"
|
||
)
|
||
|
||
const maxFileSize = 1 * 1024 * 1024 // 1MB
|
||
|
||
// Build 根据 config 中定义的 bundle key,将多个文件内容聚合成一个字符串
|
||
//
|
||
// 设计用途:
|
||
// 用于 CLI 工具中快速“打包”一组文件内容,例如:
|
||
// cliprepo bundle api
|
||
// => 输出 api 相关的一组代码文件内容,方便复制/分享/提交 prompt
|
||
//
|
||
// 行为特点:
|
||
// 1. 从 cliprepo.yaml 中读取 bundles 配置
|
||
// 2. 根据 key 找到对应文件列表
|
||
// 3. 逐个读取文件内容并拼接
|
||
// 4. 自动跳过异常文件(不存在 / 读取失败)
|
||
// 5. 自动过滤过大的文件(> 1MB)
|
||
//
|
||
// 输出格式:
|
||
//
|
||
// ===== path/to/file =====
|
||
// <file content>
|
||
//
|
||
// ===== path/to/another =====
|
||
// <file content>
|
||
func Build(key string) (string, error) {
|
||
// 读取配置文件(cliprepo.yaml)
|
||
cfg, err := config.Load()
|
||
if err != nil {
|
||
return "", err
|
||
}
|
||
|
||
// 获取对应 bundle 的文件列表
|
||
files, ok := cfg.Bundles[key]
|
||
if !ok {
|
||
return "", fmt.Errorf("bundle not found: %s", key)
|
||
}
|
||
|
||
var builder strings.Builder
|
||
|
||
// 遍历 bundle 中的所有文件路径
|
||
for _, file := range files {
|
||
// 获取文件信息(用于判断大小 / 是否存在)
|
||
info, err := os.Stat(file)
|
||
if err != nil {
|
||
// 文件不存在或无法访问时跳过
|
||
continue
|
||
}
|
||
|
||
// 跳过过大的文件,避免 CLI 输出过载或内存占用过高
|
||
if info.Size() > maxFileSize {
|
||
continue
|
||
}
|
||
|
||
// 读取文件内容
|
||
data, err := os.ReadFile(file)
|
||
if err != nil {
|
||
// 读取失败直接跳过,不中断整个 bundle 构建
|
||
continue
|
||
}
|
||
|
||
// 写入文件分隔标记,便于阅读结构
|
||
builder.WriteString(fmt.Sprintf("===== %s =====\n", file))
|
||
|
||
// 写入文件内容
|
||
builder.Write(data)
|
||
builder.WriteString("\n\n")
|
||
}
|
||
|
||
return builder.String(), nil
|
||
}
|
||
|
||
// Copy 将 bundle 内容写入系统剪贴板
|
||
//
|
||
// 常见使用场景:
|
||
// CLI 一键复制 bundle 输出,用于:
|
||
// - prompt 输入
|
||
// - 代码审查
|
||
// - 远程分享
|
||
// - AI 上下文输入
|
||
func Copy(content string) error {
|
||
return clipboard.WriteAll(content)
|
||
} |