diff --git a/.gitea/workflows/release.yaml b/.gitea/workflows/release.yaml index 3773e41..800abb2 100644 --- a/.gitea/workflows/release.yaml +++ b/.gitea/workflows/release.yaml @@ -25,12 +25,13 @@ jobs: - name: Build run: | + chmod +x ./build.sh for p in linux/amd64 linux/arm64 darwin/amd64 darwin/arm64 windows/amd64; do os=${p%/*} arch=${p#*/} ext="" [ "$os" = "windows" ] && ext=".exe" - GOOS=$os GOARCH=$arch go build -buildvcs=false -o "yoo-${os}-${arch}${ext}" ./cmd/yoyo + ./build.sh "$p" -o "yoo-${os}-${arch}${ext}" done - name: Checksums diff --git a/build.sh b/build.sh index 7671399..d37badb 100755 --- a/build.sh +++ b/build.sh @@ -1,3 +1,94 @@ #!/bin/bash -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 \ No newline at end of file +set -e + +cd "$(dirname "$0")" + +VERSION=$(git describe --tags --always --dirty 2>/dev/null || echo "dev") + +show_help() { + echo "YOYO 编译脚本" + echo "" + echo "用法:" + echo " ./build.sh 构建当前平台,输出 yoyo" + echo " ./build.sh <平台> 交叉编译指定平台" + echo " ./build.sh -h 显示帮助" + echo "" + echo "参数:" + echo " -h 显示帮助信息" + echo " -o <文件名> 指定输出文件名" + echo "" + echo "支持的平台:" + echo " linux/amd64, linux/arm64" + echo " darwin/amd64, darwin/arm64" + echo " windows/amd64" + echo "" + echo "示例:" + echo " ./build.sh # 构建当前平台" + echo " ./build.sh linux/amd64 # 编译 Linux x64" + echo " ./build.sh darwin/arm64 # 编译 macOS ARM" + echo " ./build.sh windows/amd64 -o app.exe # 编译 Windows x64,自定义输出名" + echo "" + echo "输出文件名格式: yoo--[.exe]" + echo " yoo-linux-amd64" + echo " yoo-darwin-arm64" + echo " yoo-windows-amd64.exe" +} + +OUTPUT_NAME="yoyo" + +while [[ $# -gt 0 ]]; do + case $1 in + -h|--help) + show_help + exit 0 + ;; + -o|--output) + OUTPUT_NAME="$2" + shift 2 + ;; + linux/amd64) + GOOS=linux GOARCH=amd64 + PLATFORM="linux-amd64" + shift + ;; + linux/arm64) + GOOS=linux GOARCH=arm64 + PLATFORM="linux-arm64" + shift + ;; + darwin/amd64) + GOOS=darwin GOARCH=amd64 + PLATFORM="darwin-amd64" + shift + ;; + darwin/arm64) + GOOS=darwin GOARCH=arm64 + PLATFORM="darwin-arm64" + shift + ;; + windows/amd64) + GOOS=windows GOARCH=amd64 + PLATFORM="windows-amd64" + if [[ "$OUTPUT_NAME" == "yoyo" ]]; then + OUTPUT_NAME="yoo-windows-amd64.exe" + fi + shift + ;; + *) + echo "未知平台: $1" + show_help + exit 1 + ;; + esac +done + +echo "Building yoyo version: $VERSION" + +if [ -n "$GOOS" ]; then + echo "Target: $PLATFORM" + go build -ldflags "-s -w -X github.com/titor/fanyi/internal/logo.version=${VERSION}" -o "$OUTPUT_NAME" ./cmd/yoyo +else + go build -ldflags "-s -w -X github.com/titor/fanyi/internal/logo.version=${VERSION}" -o "$OUTPUT_NAME" ./cmd/yoyo +fi + +echo "Build complete: ./$OUTPUT_NAME" \ No newline at end of file diff --git a/changelog.md b/changelog.md index 0419cf1..2d0caa6 100644 --- a/changelog.md +++ b/changelog.md @@ -70,6 +70,31 @@ ## 版本历史 +### 0.7.1 (2026-04-08) - TUI界面改进 +**类型**: 优化版本 +**状态**: 开发中 + +**改进内容**: +- ✅ 添加帮助信息栏目 - 使用 bubbles help 组件,位于界面底部 +- ✅ 帮助按键绑定 - Ctrl+H 切换帮助显示 +- ✅ Logo 版本号注入 - 使用 build.sh + ldflags 自动注入 git 版本 +- ✅ 翻译卡片样式 - 翻译结果 Padding(1,3,1,3) 增加上方空隙 +- ✅ Viewport 上方内边距 - 第一个翻译卡片显示时增加上方空白 + +**构建脚本改进**: +- ✅ 扩展 build.sh 支持跨平台编译 +- ✅ 添加 -h 帮助选项 +- ✅ 支持 -o 自定义输出文件名 +- ✅ 支持平台: linux/amd64, linux/arm64, darwin/amd64, darwin/arm64, windows/amd64 + +**讨论记录**: +- [帮助功能和样式改进](taolun.md#2026-04-08-tui界面帮助功能与样式改进) + +**下一步**: +- 实现模块8: 弹出框组件 + +--- + ### 0.7.0 (2026-04-06) - TUI界面改进 **类型**: 功能版本 **状态**: 开发中 diff --git a/internal/tui/keys.go b/internal/tui/keys.go index 29cbe51..2d82700 100644 --- a/internal/tui/keys.go +++ b/internal/tui/keys.go @@ -12,6 +12,7 @@ type KeyMap struct { ScrollDown key.Binding ScrollTop key.Binding ScrollBottom key.Binding + Help key.Binding } func NewKeyMap() KeyMap { @@ -44,5 +45,21 @@ func NewKeyMap() KeyMap { key.WithKeys("end"), key.WithHelp("End", "底部"), ), + Help: key.NewBinding( + key.WithKeys("ctrl+h"), + key.WithHelp("Ctrl+H", "帮助"), + ), + } +} + +func (k KeyMap) ShortHelp() []key.Binding { + return []key.Binding{k.Help, k.Quit} +} + +func (k KeyMap) FullHelp() [][]key.Binding { + return [][]key.Binding{ + {k.Quit, k.Clear, k.SwitchLang}, + {k.ScrollUp, k.ScrollDown, k.ScrollTop, k.ScrollBottom}, + {k.Help}, } } diff --git a/internal/tui/model.go b/internal/tui/model.go index 298ce5c..fd2e114 100644 --- a/internal/tui/model.go +++ b/internal/tui/model.go @@ -7,6 +7,8 @@ import ( "strings" "time" + "charm.land/bubbles/v2/help" + "charm.land/bubbles/v2/key" "charm.land/bubbles/v2/spinner" "charm.land/bubbles/v2/textarea" "charm.land/bubbles/v2/viewport" @@ -33,6 +35,7 @@ type model struct { input textarea.Model viewport viewport.Model spinner spinner.Model + help help.Model keys KeyMap targetLang string @@ -67,16 +70,22 @@ func NewApp(cfg *config.Config, t *translator.Translator) *tea.Program { sp.Spinner = spinner.MiniDot sp.Style = lipgloss.NewStyle().Foreground(lipgloss.Color("#8B5CF6")) - return tea.NewProgram(model{ + hp := help.New() + + m := model{ config: cfg, translator: t, messages: make([]ChatMessage, 0), input: ta, viewport: vp, spinner: sp, + help: hp, keys: keys, targetLang: getDefaultLang(cfg), - }) + } + + p := tea.NewProgram(m) + return p } func getDefaultLang(cfg *config.Config) string { @@ -100,6 +109,7 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { case tea.WindowSizeMsg: m.width = msg.Width m.height = msg.Height + m.help.SetWidth(msg.Width) m.updateLayout() case translateMsg: @@ -137,6 +147,9 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { case "end": m.viewport.GotoBottom() } + if key.Matches(msg, m.keys.Help) { + m.help.ShowAll = !m.help.ShowAll + } } m.input, cmd = m.input.Update(msg) @@ -206,7 +219,12 @@ func (m *model) updateLayout() { m.input.SetWidth(contentWidth) m.viewport.SetWidth(contentWidth) - m.viewport.SetHeight(m.height - 12) + + helpLines := 2 + if m.help.ShowAll { + helpLines = 4 + } + m.viewport.SetHeight(m.height - 12 - helpLines) if m.viewport.Height() < 5 { m.viewport.SetHeight(10) } @@ -217,6 +235,10 @@ func (m *model) updateLayout() { func (m *model) updateViewportContent() { var b strings.Builder + if len(m.messages) > 0 { + b.WriteString("\n") + } + for _, msg := range m.messages { b.WriteString(m.renderTranslationCard(msg)) } @@ -252,7 +274,7 @@ func (m *model) renderTranslationCard(msg ChatMessage) string { Render(msg.Error) outputBlock = lipgloss.NewStyle(). Foreground(lipgloss.Color("#F87171")). - Padding(0, 3, 1, 3). + Padding(1, 3, 1, 3). Width(m.viewport.Width()). Render(outputContent) } else { @@ -260,7 +282,7 @@ func (m *model) renderTranslationCard(msg ChatMessage) string { Width(m.viewport.Width() - 2). Render(msg.Output) outputBlock = lipgloss.NewStyle(). - Padding(0, 3, 1, 3). + Padding(1, 3, 1, 3). Width(m.viewport.Width()). Render(outputContent) } @@ -299,9 +321,9 @@ func (m model) View() tea.View { messages := m.viewport.View() inputArea := m.renderInputArea() infoBar := m.renderInfoBar() - spinnerView := m.renderSpinner() + helpView := m.help.View(m.keys) - content := header + "\n" + messages + inputArea + infoBar + spinnerView + content := header + "\n" + messages + inputArea + infoBar + helpView v := tea.NewView(content) v.AltScreen = true return v diff --git a/taolun.md b/taolun.md index 7a16e39..ee93ff5 100644 --- a/taolun.md +++ b/taolun.md @@ -874,8 +874,52 @@ go build -ldflags "-X github.com/titor/fanyi/internal/logo.version=${VERSION}" - ``` _ _ _____ _____ ( \/ ( _ ( _ ) - \ / )(_)( )(_)( + \ / )(_)( )(_)( (__)(_____(_____( 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#071-2026-04-08---tui界面改进) + **关联版本**: [changelog.md#1.1.1](changelog.md#111-2026-04-08) \ No newline at end of file