Files
cliprepo/internal/tree/tree.go
T
2026-05-15 23:54:10 +08:00

77 lines
1.9 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package tree
import (
"fmt"
"os"
"path/filepath"
"strings"
"cliprepo/internal/gitignore"
"github.com/atotto/clipboard"
)
// Generate 从 root 目录开始遍历文件树,并生成类似 `tree` 命令的目录结构字符串
//
// 功能特点:
// 1. 递归遍历目录
// 2. 支持 .gitignore 规则过滤
// 3. 输出树形结构字符串
func Generate(root string) (string, error) {
// 加载 gitignore 规则(如果失败则忽略错误,默认不过滤)
ig, _ := gitignore.Load(root)
var builder strings.Builder
// 递归遍历目录结构
err := filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
// 根目录特殊处理,统一显示为 "."
if path == root {
builder.WriteString(".\n")
return nil
}
// 转换为相对路径,便于匹配 gitignore 和计算层级
rel, _ := filepath.Rel(root, path)
// 如果路径匹配 gitignore 规则,则跳过
// 如果是目录,则直接跳过整个子树
if ig.MatchesPath(rel) {
if info.IsDir() {
return filepath.SkipDir
}
return nil
}
// 计算当前节点在目录树中的层级
// 通过路径分隔符数量判断深度
level := strings.Count(rel, string(os.PathSeparator))
// 根据层级生成缩进
prefix := strings.Repeat("│ ", level)
// 写入当前节点(文件或目录)
builder.WriteString(fmt.Sprintf("%s├── %s\n", prefix, info.Name()))
return nil
})
return builder.String(), err
}
// Copy 将生成的字符串写入系统剪贴板
//
// 常用于 CLI 工具:直接复制 tree 输出结果
func Copy(content string) error {
return clipboard.WriteAll(content)
}
// Write 将内容写入指定文件路径
//
// 如果文件存在则覆盖
// 权限默认设置为 0644rw-r--r--
func Write(path, content string) error {
return os.WriteFile(path, []byte(content), 0644)
}