Files
yoyo/taolun.md
titor 95338962cb
All checks were successful
Release / build (push) Successful in 6m28s
fix: Windows 交叉编译添加 CGO_ENABLED=0
2026-04-08 03:14:30 +08:00

31 KiB
Raw Blame History

讨论记录 (taolun.md)

本文档记录开发过程中的重要讨论,以时间轴方式存储,便于版本追溯。

使用说明

  • 每次重要讨论后更新此文件
  • 使用上下文压缩总结,突出重点
  • 格式:时间 - 版本号 - 主题

时间轴记录

[2026-03-28 22:30] 版本 0.0.1 - 确定技术栈

原因: 项目启动,需要确定技术栈 分析:

  • 比较Go、Deno+TS、Node.js+TS
  • Go优势原生二进制、性能好、CLI工具友好
  • 用户不会Go但愿意学习

解决方案:

  • 使用Go语言开发
  • 采用面向对象设计模式
  • 支持多个大模型厂商

相关决策:

  • 项目结构采用cmd/internal/布局
  • 使用YAML配置文件
  • 实现工厂模式和策略模式

关联版本: changelog.md#0.0.1


[2026-03-28 23:00] 版本 0.0.1 - 设计OOP架构

原因: 用户要求面向对象开发模式 分析:

  • Go不是传统OOP语言但可通过结构体和接口实现
  • 需要三个核心类:配置、厂商、翻译器

解决方案:

  • Config类:全局配置管理
  • Provider接口:厂商抽象
  • Translator类:核心翻译逻辑
  • ProviderFactory:工厂模式创建厂商实例

相关链接:


[2026-03-28 23:30] 版本 0.0.1 - 制定开发规范

原因: 建立规范的开发流程 分析:

  • 需要记录讨论过程、版本变更和知识积累
  • 版本号需要遵循语义化版本规范

解决方案:

  • 创建taolun.md记录讨论
  • 创建changelog.md记录版本
  • 创建memory.md记录知识纠正
  • 版本号格式:大版本.新功能.小修复(00-99)

关联文档:


[2026-03-28 23:45] 版本 0.0.1 - 创建项目初衷文档

原因: 需要一个地方记录项目初衷和愿景 分析:

  • 项目需要明确的目标和方向
  • 创始人需要记录个人想法和灵感
  • 与其他文档taolun.md、changelog.md、memory.md区分

解决方案:

  • 创建why.md文件专门记录项目初衷
  • 规定只能由项目所有者编辑
  • 提供基本结构建议,但不强制内容

文档规范:

  • 文件位置:项目根目录
  • 权限:仅用户可编辑
  • 内容:项目愿景、目标、个人笔记等

关联文档:


[2026-03-28 23:50] 版本 0.0.2 - 实现核心架构

原因: 开始实现项目核心功能 分析:

  • 根据OOP设计模式实现三个核心类
  • 需要先实现配置加载和厂商接口
  • 创建基本的CLI入口点

解决方案:

  1. Config类实现

    • 支持YAML配置文件加载
    • 环境变量替换
    • 配置验证和默认值
  2. Provider接口实现

    • 定义统一的翻译接口
    • 工厂模式创建厂商实例
    • 实现硅基流动厂商作为示例
  3. Translator类实现

    • 核心翻译逻辑
    • Prompt管理
    • 超时控制
  4. CLI入口点

    • 命令行参数解析
    • 配置加载
    • 翻译执行

技术细节:

  • 使用gopkg.in/yaml.v3处理YAML
  • 实现工厂模式注册机制
  • 使用context处理超时和取消
  • 添加基本单元测试

关联文档:


[2026-03-29 00:00] 版本 0.0.3 - 环境变量加载修复

原因: 测试CLI时发现环境变量没有正确加载 分析:

  • 配置文件中使用${ENV_VAR}语法
  • Go的os.ExpandEnv只在加载时替换
  • 需要先加载.env文件到环境变量

解决方案:

  1. 添加github.com/joho/godotenv依赖
  2. 在main函数开始时调用godotenv.Load()
  3. 更新memory.md记录踩坑经验

技术细节:

  • godotenv会自动查找当前目录的.env文件
  • 如果文件不存在会返回错误,可以忽略
  • 不影响已有的环境变量

关联文档:


[2026-03-29 10:00] 版本 0.2.0 - 语言代码解析设计

原因: 用户需要通过 --lang 参数指定目标语言,支持多种语言代码格式 分析:

  • 需要支持标准BCP47格式zh-CNen-US
  • 需要支持简短别名(如 cnen
  • 需要支持中文名称(如 chineseenglish
  • 需要智能解析和错误提示

解决方案:

  1. 创建 internal/lang/lang.go 模块
  2. 实现语言代码映射表和解析函数
  3. 支持大小写不敏感和模糊匹配
  4. 提供语言名称获取和建议功能

技术细节:

  • 使用 map[string]string 存储语言代码映射
  • 实现 ParseLanguageCode() 函数进行智能解析
  • 支持30+种语言和变体
  • 添加完整的单元测试

关联文档:


[2026-03-29 10:30] 版本 0.2.0 - onboard配置向导

原因: 用户需要友好的配置界面,特别是第一次使用时 分析:

  • 需要交互式配置向导
  • 需要支持选择厂商、输入API密钥、设置默认值
  • 需要生成标准的YAML配置文件
  • 需要支持强制重新配置

解决方案:

  1. 使用 github.com/AlecAivazis/survey/v2
  2. 实现分步配置流程:选择厂商 → 配置厂商 → 全局设置 → 保存
  3. 提供友好的错误处理和用户提示
  4. 支持 --force 参数强制重新配置

技术细节:

  • 使用 survey.Selectsurvey.Inputsurvey.Confirm 组件
  • 实现厂商默认配置和自定义选项
  • 生成完整的配置文件包含所有必要字段
  • 支持配置文件存在性检查

关联文档:


[2026-03-29 11:00] 版本 0.2.0 - 分阶段迁移策略

原因: 需要平衡开发便利性和最终上线需求 分析:

  • 开发阶段需要简单配置方式(.env + configs/config.yaml
  • 上线前需要迁移到用户配置目录(~/.config/yoo/yoo.yml
  • 需要平滑的迁移路径和向后兼容性

解决方案:

  1. 第一阶段(当前): 继续使用 .env + configs/config.yaml
  2. 第二阶段(上线前): 实现配置文件路径查找和迁移工具
  3. 第三阶段(最终): 移除 .env 依赖,完全使用配置文件

技术细节:

  • 配置文件路径优先级:命令行 > 环境变量 > 用户目录 > 当前目录
  • 保持向后兼容性,支持旧配置格式
  • 提供配置验证和错误提示
  • 实现配置迁移工具(计划)

关联文档:


[2026-03-29 12:00] 版本 0.4.0 - 管道符功能

原因: 用户需要与其他命令行工具联合使用 分析:

  • 用户希望支持管道符功能,如 cat a.txt | yoyo | grep "who are you"
  • 需要检测管道输入并从stdin读取内容
  • 需要控制统计信息输出,避免污染管道输出
  • 需要保持向后兼容性

解决方案:

  1. 管道输入检测: 实现 isPipeInput() 函数,使用 os.Stdin.Stat() 检测管道
  2. stdin读取: 实现 readFromStdin() 函数,使用 bufio.Scanner 读取所有输入
  3. 静默模式: 添加 --quiet-q 参数,控制统计信息输出
  4. 输出重定向: 将统计信息输出到stderr避免污染管道输出

技术细节:

  • 使用 os.ModeCharDevice 检测是否为管道设备
  • 使用 strings.Join() 合并多行输入为单个字符串
  • 统计信息输出到 os.Stderr 而不是 os.Stdout
  • 修复 content/filter.go 中的正则表达式转义问题

使用示例:

# 基本管道功能
echo "Hello world" | yoyo
cat file.txt | yoyo --lang=en

# 静默模式
echo "Hello world" | yoyo -q
echo "Hello world" | yoyo --quiet

# 与其他命令组合
cat file.txt | yoyo | grep "你好"
yoyo "Hello" | wc -l

关联文档:


[2026-03-29 15:00] 版本 0.5.0 - 本地缓存功能设计

原因: 用户希望减少API调用添加本地缓存功能 分析:

  • 需要存储翻译结果避免重复调用API
  • 需要设计缓存键策略,确保缓存准确性
  • 需要考虑数据库选择、事务处理、性能优化
  • 需要设计缓存管理策略

解决方案:

  1. 数据库选择: 使用SQLite

    • 轻量级,无需服务器
    • 支持ACID事务
    • Go生态支持良好 (github.com/mattn/go-sqlite3)
    • 适合嵌入式应用
  2. 缓存键设计:

    • 使用文本内容 + 源语言 + 目标语言
    • 生成SHA256哈希作为缓存键
    • 规范化输入:移除多余空白字符,统一语言代码格式
  3. 事务处理:

    • 使用事务保证数据一致性
    • 插入操作在事务中执行
    • 查询操作不需要显式事务
  4. 保存时机:

    • 在输出结果之前保存到数据库
    • 确保数据持久化
    • 异步保存,不阻塞翻译结果返回
  5. 性能优化:

    • 为缓存键创建索引
    • 使用哈希键减少存储空间
    • 限制缓存表大小(可配置)
    • 使用WAL模式提高并发性能
  6. 缓存策略:

    • 采用组合策略:数量限制+时间过期
    • 默认启用缓存功能
    • 提供手动清理命令
  7. 存储位置:

    • 数据库文件存储在用户配置目录 ~/.config/yoyo/cache.db
    • 符合XDG规范
    • 支持自定义路径配置

技术细节:

  • 使用 github.com/mattn/go-sqlite3 驱动
  • 实现 internal/cache/cache.go 模块
  • 缓存表结构:id, cache_key, original_text, translated_text, from_lang, to_lang, model, prompt, created_at
  • 缓存键生成:sha256(text + "|" + fromLang + "|" + toLang)
  • 查询缓存时使用 SELECT translated_text FROM cache WHERE cache_key = ?
  • 插入缓存时使用 INSERT OR IGNORE INTO cache (...) VALUES (...)

关联文档:


[2026-03-29 20:00] 版本 0.5.1 - 缓存功能修复

原因: 缓存功能测试中发现的问题 分析:

  1. VACUUM事务错误: 缓存清空命令中VACUUM不能在事务中执行
  2. NULL值转换错误: 缓存统计查询在空表时MIN(created_at)返回NULL导致转换错误
  3. 过期清理策略: 当expire_days=0时清理逻辑不工作

解决方案:

  1. 修复VACUUM事务错误:

    • 将VACUUM移到事务之外执行
    • 先删除记录再执行VACUUM
  2. 修复NULL值转换错误:

    • 使用 sql.NullStringsql.NullFloat64 类型
    • 检查 Valid 字段判断是否为NULL
    • 只在有记录时才查询时间范围
  3. 修复过期清理策略:

    • 当cleanupTTL为0时清理所有记录
    • 添加条件判断:if c.cleanupTTL == 0 { ... }

技术细节:

// 修复VACUUM事务错误
func (c *SQLiteCache) Clear(ctx context.Context) error {
    // 先删除所有记录
    _, err := c.db.ExecContext(ctx, `DELETE FROM translation_cache`)
    if err != nil {
        return fmt.Errorf("清空缓存失败: %w", err)
    }
    // 然后执行VACUUM不能在事务中执行
    _, err = c.db.ExecContext(ctx, `VACUUM`)
    if err != nil {
        return fmt.Errorf("清理数据库失败: %w", err)
    }
    return nil
}

// 修复NULL值转换错误
var oldestStr, newestStr sql.NullString
var avgTokens sql.NullFloat64
err = c.db.QueryRowContext(ctx, `SELECT MIN(created_at), MAX(created_at), AVG(total_tokens) FROM translation_cache`).Scan(&oldestStr, &newestStr, &avgTokens)

if oldestStr.Valid {
    stats.OldestRecord, _ = time.Parse("2006-01-02 15:04:05", oldestStr.String)
}

关联文档:


[2026-04-06 10:00] 版本 0.6.0 - TUI界面模块拆分计划

原因: 当前TUI目录(tui/components、tui/theme)已创建但完全为空,需要从零实现终端交互界面 分析:

  • 采用分模块逐步实现策略减少Token消耗和上下文负担
  • 每次只实现一个模块,完成后再进入下一个
  • 讨论内容仅保存到taolun.md/changelog.md/memory.md不新增md文件

解决方案 - TUI模块拆分:

步骤 模块 内容 预计工作量
1 TUI框架搭建 选择库(bubbletea)、基础App结构、运行循环
2 输入组件 文本输入框、光标、基础编辑
3 翻译显示区 结果展示、格式化、滚动
4 状态栏/主题 底部状态栏、语言选择、主题配色
5 快捷键系统 退出、清空、切换语言等
6 集成翻译 对接现有Translator、加载动画

技术选型:

  • 优先使用 charmbracelet/bubbletea (Elm架构、Go生态最流行)
  • 配合 charmbracelet/lipgloss 实现样式和主题
  • 配合 charmbracelet/bubbles/textinput 实现输入框

当前状态: 模块1已完成模块2待实现

关联文档:


[2026-04-06 10:30] 版本 0.6.0 - 模块1: TUI框架搭建 (已完成)

原因: 实现TUI界面的第一步建立基础框架结构 分析:

  • 需要创建基本的App结构和model
  • 需要支持config和translator的注入
  • 需要修复main.go中版本检查顺序问题

解决方案:

  1. 创建 internal/tui/app.go 基础文件
  2. 定义model结构体包含config和translator字段
  3. 实现Init/Update/View三个基本方法
  4. 添加bubbletea、bubbles、lipgloss依赖
  5. 修复main.go中--version在interactive之前检查

技术实现:

type model struct {
    config      *config.Config
    translator  *translator.Translator
}

func NewApp(cfg *config.Config, t *translator.Translator) *tea.Program {
    return tea.NewProgram(model{...})
}

下一步: 实现模块2: 输入组件

关联文档:


[2026-04-06 11:00] 版本 0.6.0 - 模块2: 输入组件 (已完成)

原因: 实现TUI输入功能 分析:

  • 使用bubbletea的textinput组件
  • 需要焦点管理和键盘事件处理

解决方案:

  1. 添加textinput字段到model
  2. 初始化时设置placeholder和prompt
  3. Update中处理KeyMsg
  4. View中渲染输入框
  5. 支持Ctrl+C和Esc退出

技术实现:

type model struct {
    textInput textinput.Model
}

func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
    switch msg := msg.(type) {
    case tea.KeyMsg:
        if msg.Type == tea.KeyCtrlC || msg.Type == tea.KeyEsc {
            return m, tea.Quit
        }
    }
    m.textInput, cmd = m.textInput.Update(msg)
    return m, cmd
}

下一步: 实现模块3: 翻译显示区

关联文档:


[2026-04-06 11:30] 版本 0.6.0 - 模块3: 翻译显示区 (已完成)

原因: 添加翻译结果显示区域 分析:

  • 需要定义结果展示区域
  • 需要为不同区域定义不同样式

解决方案:

  1. 添加result字段到model
  2. 定义headerStyle、resultStyle、helpStyle
  3. 实现renderResult()辅助方法
  4. View中组合各个区域

下一步: 实现模块4: 状态栏/主题

关联文档:


[2026-04-06 12:00] 版本 0.6.0 - 模块4: 状态栏/主题 (已完成)

原因: 添加底部状态栏和主题配色 分析:

  • 需要显示当前目标语言
  • 需要完善配色方案
  • 需要定义状态栏样式

解决方案:

  1. 添加targetLang字段到model
  2. 定义statusBarStyle、langStyle等新样式
  3. 实现renderStatusBar()方法
  4. View中渲染状态栏

下一步: 实现模块5: 快捷键系统

关联文档:


[2026-04-06 12:30] 版本 0.6.0 - 模块5: 快捷键系统 (已完成)

原因: 添加键盘快捷键提升用户体验 分析:

  • 需要常用操作快捷键
  • 需要清晰显示快捷键提示

解决方案:

  1. 添加Ctrl+L: 清空输入和结果
  2. 添加Ctrl+T: 循环切换语言
  3. 添加keyStyle样式高亮快捷键
  4. 更新帮助提示显示所有快捷键

快捷键列表:

  • Ctrl+L: 清空输入框和翻译结果
  • Ctrl+T: 循环切换目标语言 (zh-CN→en-US→ja→ko→...)
  • Ctrl+C/Esc: 退出程序
  • Enter: 翻译 (后续模块实现)

下一步: 实现模块6: 集成翻译

关联文档:


[2026-04-06 13:00] 版本 0.6.0 - 模块6: 集成翻译 (已完成)

原因: 将Translator集成到TUI实现真正的翻译功能 分析:

  • 需要在Enter键时调用翻译API
  • 需要异步执行避免阻塞UI
  • 需要显示loading状态和错误处理

解决方案:

  1. 添加translateMsg消息类型处理异步结果
  2. 添加loading和errMsg字段
  3. 实现doTranslate()函数执行异步翻译
  4. Update中处理translateMsg消息
  5. View中显示loading状态或错误信息

技术实现:

type translateMsg struct {
    result string
    err    error
}

func (m model) doTranslate(text, toLang string) tea.Cmd {
    return func() tea.Msg {
        result, err := m.translator.Translate(...)
        if err != nil {
            return translateMsg{err: err}
        }
        return translateMsg{result: result.Translated}
    }
}

下一步: 测试TUI界面、优化体验

关联文档:


[2026-04-06 14:00] 版本 0.7.0 - TUI界面改进计划

原因: TUI基础功能完成后讨论改进方向和用户体验优化 分析:

  • 当前单行textinput无法输入多行文本
  • 快捷键固定显示在底部不够美观
  • 缺少命令菜单系统
  • 长翻译结果无法滚动

解决方案 - 新增模块:

步骤 模块 内容
7 多行输入 textarea组件替换textinput
8 弹出框组件 通用modal支持快捷键帮助
9 斜杠命令菜单 / 触发命令选择器类似opencode
10 翻译结果滚动 viewport组件
11 复制功能 clipboard集成
12 状态栏扩展 耗时、token用量

斜杠命令设计:

命令 功能
/help 显示快捷键帮助
/clear 清空内容
/copy 复制翻译结果
/lang 切换语言
/history 翻译历史
/quit 退出

设计亮点:

  1. 隐藏底部快捷键提示,改为按 ? 或 F1 弹出帮助框
  2. 输入 / 触发命令菜单,上下键选择,回车执行
  3. 命令菜单支持模糊匹配
  4. modal组件通用化可复用于其他弹窗场景

关联文档:


[2026-04-06 14:30] 版本 0.7.0 - 模块7: 多行输入 (已完成)

原因: 当前textinput只支持单行需要支持多行文本输入 分析:

  • 长段落、多行文本无法输入
  • 需要换用bubbles的textarea组件

解决方案:

  1. 将textinput替换为textarea
  2. 调整样式和布局宽50高5
  3. 底部状态栏提示按 / 显示命令

技术实现:

  • 使用 github.com/charmbracelet/bubbles/textarea
  • textarea.SetWidth(50)、SetHeight(5) 设置尺寸
  • 移除底部固定快捷键提示,改为按需显示
  • 隐藏行号: ShowLineNumbers = false
  • 移除左侧提示符: Prompt = ""
  • Enter执行翻译Ctrl+J换行

下一步: 实现模块8: 弹出框组件

关联文档:


[2026-04-06 15:00] 版本 0.8.0 - TUI重构: 聊天风格界面

原因: 用户希望使用类似 charmbracelet/crush 的聊天风格界面 分析:

  • 当前界面:标题在上 → 输入框在中 → 结果在下
  • 期望界面:标题在上 → 聊天消息区域(可滚动历史)→ 输入框固定底部 → 状态栏最底部
  • 原文+译文成对显示,类似聊天软件

解决方案:

  1. 界面布局重构:

    ┌─────────────────────────────────────────┐
    │  ✦ YOYO 翻译              [Ctrl+C退出] │
    ├─────────────────────────────────────────┤
    │  (聊天消息区域,可滚动查看历史)         │
    │  ── 用户输入 ──                          │
    │  Hello world                            │
    │  ── 翻译结果 ──                          │
    │  你好世界                                │
    │  ...                                    │
    ├─────────────────────────────────────────┤
    │  输入框...                        [回车] │
    ├─────────────────────────────────────────┤
    │  目标:zh-CN │ 模型:gpt-3.5 │ Tokens:125  │
    └─────────────────────────────────────────┘
    
  2. 技术方案:

    • 消息结构:原文+译文成对显示
    • 底部固定输入框textarea
    • 状态栏显示完整信息
    • Ctrl+J 换行Enter 发送
    • 自动调整输入框高度

下一步: 模块1: 创建TUI模块结构

关联文档:


[2026-04-06 16:00] 版本 0.8.0 - 输入框踩坑与修复

原因: Ctrl+J换行后第一行被遮住显示错乱 分析:

  • 换行后 textarea 内部渲染3行但只显示2行
  • 第一行内容往上滚动被遮住光标在第2行第3行是空行
  • 尝试多种方案均无效移除Width限制、设置SetWidth/SetHeight顺序、动态调整高度

解决方案:

  1. 放弃动态调整高度方案固定高度为5行
  2. 超过5行时textarea内部自动滚动光标始终可见

技术细节:

  • textarea内部使用viewport组件频繁SetHeight导致滚动位置错乱
  • 使用 FocusedStyle/BlurredStyle + Style.Base 设置背景色

代码变更:

ta.SetWidth(60)
ta.SetHeight(5)  // 固定高度,不动态调整

下一步: 完善其他UI功能

关联文档:


[2026-04-07 10:00] 版本 0.8.1 - 翻译结果卡片组件设计

原因: 用户希望改进翻译结果显示样式使用lipgloss构建更美观的组件 分析:

  • 当前翻译结果显示比较简单,只有标签和内容
  • 需要设计一个结构化的翻译卡片组件
  • 组件需要显示Tokens、翻译时间、模型名称等元信息

解决方案:

  1. 卡片组件结构:

    ┌─ 标题栏 ─────────────────────────────────────────┐
    │ Tokens: 150  │  耗时: 1.2s  │  模型: gpt-4        │
    └─────────────────────────────────────────────────┘
    ┌─ 用户输入 ───────────────────────────────────────┐
    │ ██████████ 碳黑背景 ████████████████████████████  │
    └─────────────────────────────────────────────────┘
    ┌─ 翻译结果 ───────────────────────────────────────┐
    │ AI 翻译的文本内容...                              │
    └─────────────────────────────────────────────────┘
    
  2. 技术实现:

    • 使用 lipgloss.Div() 和 lipgloss.JoinVertical() 构建组件
    • 背景色: #1A1A1A (碳黑色)
    • 用户输入区域: 纯背景色,无边框
    • 组件间距: 5px marginBottom
  3. 样式定义:

    • CardStyle: 卡片容器marginBottom(5)
    • CardMetaStyle: 元信息行样式,#6B7280 灰色
    • CardInputStyle: 用户输入,#1A1A1A 背景 + #E5E7EB 文字
    • CardOutputStyle: 翻译结果,白色文字

下一步: 实现组件代码

关联文档:


[2026-04-07] 版本 1.0.0-beta - Logo和信息栏改造

原因: 用户希望改进TUI界面的视觉效果使标题更独特输入框和信息栏更美观

分析:

  • 原标题 "✦ YOYO 翻译" 过于简单
  • 输入框需要更好的视觉分隔
  • 需要添加翻译状态动画

解决方案:

  1. 标题Logo:

    • 使用ASCII艺术 "l_ _ _____ _____"
    • 实现紫色→粉色渐变效果 (ANSI True Color)
    • 右侧显示版本号 [v1.0.0-beta]
  2. 输入框改造:

    • 去掉边框
    • 上下使用紫色 ::: 分隔符
    • Ctrl+J 启用换行
  3. 信息栏改造:

    • 合并显示:语言(红色) + 模型名(白色) + 缓存记录(碳黑)
    • 翻译时显示 Spinner 动画 (MiniDot)
  4. 翻译卡片优化:

    • 图标边距调整

版本号规则:

  • 版本号需与 git 标签、changelog.md 中的版本号保持三方同步
  • 遵循语义化版本:主版本.次版本.修订版本
  • beta版使用 -beta 后缀

关联版本: changelog.md#1.0.0-beta


[2026-04-07] 版本 1.1.0 - 配置路径修复和huh迁移

原因:

  1. 管道模式下(如 cd /docs && cat readme.md | yoyo)找不到配置文件
  2. onboard配置保存到错误的相对路径
  3. 希望用 charmbracelet/huh 替代 survey 获得更好的UX

分析:

  • 所有配置路径硬编码为 configs/config.yaml相对CWD
  • 从不同目录运行程序时路径解析失败
  • survey库API较老huh提供更现代的表单体验

解决方案:

  1. 新增 internal/config/path.go 路径解析工具
  2. 配置查找优先级:--config > ~/.config/yoyo/config.yaml > ./configs/config.yaml
  3. onboard保存到 ~/.config/yoyo/config.yaml
  4. .env从 ~/.config/yoyo/.env 加载
  5. onboard使用huh重写Form+Group模式链式API泛型支持

技术细节:

// 路径解析
config.ResolveConfigPath(userPath)  // 智能查找配置
config.GetUserConfigPath()          // ~/.config/yoyo/config.yaml
config.GetUserEnvPath()             // ~/.config/yoyo/.env

huh迁移要点:

  • survey.Selecthuh.NewSelect[string]().Options(huh.NewOption(...)...)
  • survey.Inputhuh.NewInput().Value(&var).Validate(fn)
  • survey.Confirmhuh.NewConfirm().Affirmative("是").Negative("否")
  • 分步表单 → huh.NewForm(huh.NewGroup(...), huh.NewGroup(...))

关联版本: changelog.md#1.1.0


[2026-04-08 00:40] 版本 1.1.1 - Logo模块化与渐变色统一

原因:

  1. --help -h -? --version 在默认交互式模式下无响应
  2. 帮助信息头部需要彩色logo展示

问题分析:

  1. 交互模式判断优先于help/version检查导致flags被忽略
  2. 帮助信息使用硬编码版本号 YOYO翻译工具 v1.1.0无logo

解决方案:

  1. 修复flag检查顺序在进入交互模式前先检查 -h --help -? --version
  2. 新增 internal/logo/logo.go 模块统一管理logo
  3. 编译时通过 ldflags 注入版本号
  4. 渐变色使用与TUI一致的紫→青色方案

技术实现:

// logo模块核心函数
func GradientText(text string, startColor, endColor string) string { ... }
func GetLogoPattern() string  // 返回4行ascii art
func GetVersionSuffix() string  // 返回 " (v1.1.1-dirty )" 或 " ( )"
func PrintLogoWithVersion()  // 打印完整logo--help/--version使用

build.sh版本注入:

VERSION=$(git describe --tags --always --dirty 2>/dev/null || echo "")
go build -ldflags "-X github.com/titor/fanyi/internal/logo.version=${VERSION}" -o yoyo ./cmd/yoyo

TUI整合:

  • 移除 internal/tui/model.go 中的本地 logoPatterngradientText
  • 直接调用 logo.GradientText(logo.GetLogoPattern(), "#B413DC", "#00C8C8")
  • 移除 [Ctrl+C 退出] 显示

最终输出格式(所有位置统一):

 _  _ _____ _____
( \/ (  _  (  _  )
 \  / )(_)( )(_)( 
 (__)(_____(_____( v1.1.1-dirty )

[2026-04-08] TUI界面帮助功能与样式改进

原因:

  1. 用户需要在TUI底部添加帮助信息栏
  2. 优化翻译卡片的显示样式

分析:

  • 使用 bubbletea 的 help 组件实现帮助栏
  • 翻译卡片需要与输入区域保持间距

解决方案:

  1. 帮助功能实现:

    • 导入 charm.land/bubbles/v2/help
    • model 结构体添加 help help.Model 字段
    • KeyMap 实现 ShortHelp()FullHelp() 接口
    • 按键绑定: Help -> Ctrl+H (原 ? 和 ctrl+? 不兼容)
    • View 中添加 help.View(m.keys) 到底部
  2. 翻译卡片样式:

    • 翻译结果 outputBlock 的 Padding 从 (0,3,1,3) 改为 (1,3,1,3) 增加上方空隙
    • viewport 内容区域第一个卡片前添加 "\n" 作为上边距
  3. 版本号注入:

    • 扩展 build.sh 支持跨平台编译
    • 添加 -h 帮助选项
    • 添加 -o 自定义输出文件名
    • release.yaml 使用 build.sh 构建

按键绑定历史:

  • 初始: ? → shift+? 切换,且会输入到文本框
  • 尝试: ctrl+? → 不兼容,无响应
  • 最终: ctrl+h → 正常工作

相关文件:

  • internal/tui/keys.go - KeyMap 定义和 ShortHelp/FullHelp
  • internal/tui/model.go - help 组件集成、样式调整
  • build.sh - 跨平台编译支持
  • .gitea/workflows/release.yaml - CI 构建脚本

关联版本: changelog.md#0.7.1

关联版本: changelog.md#1.1.1


[2026-04-08] 版本号管理规则制定

原因: 版本号历史混乱,需要规范化管理

讨论内容:

  1. 版本现状分析:

    • 历史标签混乱: v0.0.1 → v1.1.1 → v6.0 等
    • changelog 中版本状态标记混乱
  2. 确定版本规则:

    • 当前版本: v1.2.0 (TUI基础功能完成)
    • 采用简化分支策略: main + feature 分支
    • 合并时使用 --no-ff 保留分支历史
    • 在 AGENTS.md 中详细定义版本号规则
  3. v1.2.0 发布标准:

    • TUI交互界面
    • 多行输入
    • 翻译卡片展示
    • 状态栏
    • 帮助信息
    • 版本注入
    • 跨平台编译
    • CI构建
  4. 保留历史标签:

    • 过去的版本作为来时的路,不再删除
    • 从现在开始规范维护

相关文件:

  • AGENTS.md - 版本号管理规则(扩展)
  • changelog.md - 版本历史整理
  • build.sh - 跨平台编译脚本

关联版本: changelog.md#v1.2.0


[2026-04-08] Windows 交叉编译修复

问题: 交叉编译的 Windows 版本在 Windows 上提示"不支持16位应用程序"

原因:

  • Linux CI 交叉编译 Windows 时,缺少 CGO_ENABLED=0 参数
  • 原生编译go build 在 Windows 上)没有这个问题

解决方案:

  • 在 build.sh 的 windows/amd64 分支添加 CGO_ENABLED=0
  • 统一使用 CGO_ENABLED=0 进行构建

相关文件:

  • build.sh - 添加 CGO_ENABLED=0

关联版本: changelog.md#v1.2.0