# gselect —— 交互式 CLI 单选器 **Product Requirements Document (PRD)** --- ## 1. 产品概述 ### 1.1 产品定位 `gselect` 是一个 **基于 Golang + Bubble Tea 的交互式命令行选择器**, 以 **单选为核心**,用于补全 shell 脚本中缺失的“美观、稳定、可控”的交互选择能力。 *其定位类似于 **`fzf`**,但目标是:* * **更简单** * **更容易嵌入 shell 脚本** * **更容易维护与二次开发** --- ### 1.2 目标用户 * 运维工程师 * 后端 / 工具链开发者 * 编写 shell / bash / zsh / fish 脚本的用户 * CLI 工具作者 --- ### 1.3 非目标 * 不做复杂 TUI 框架 * 不做 REPL * 不做表格 / 分屏 / 树状 UI * 不支持鼠标操作 * 不做插件系统 --- ## 2. 设计原则(强约束) 1. **Unix 风格** * stdin 输入 * stdout 输出 * exit code 表达状态 2. **单选优先** * 单选是默认行为 * 多选只是可选扩展 3. **Shell 友好** * 输出可直接被 `$(...)`、`mapfile`、`read` 使用 * 不输出多余日志 4. **接口极简** * 参数少 * 行为直观 * 无配置文件依赖 --- ## 3. 使用方式总览 ### 3.1 基础用法(默认单选) ```bash printf "apple\nbanana\norange\n" | gselect ``` 用户交互: * ↑ ↓ 移动 * Enter 确认 * Esc / Ctrl+C 取消 stdout: ```text banana ``` exit code: * `0`:成功选择 * `1`:用户取消 / 无选择 --- ## 4. 输入规范(stdin) ### 4.1 输入格式 * 每行一个选项 * 空行忽略 * 原样显示,不做 trim / escape ```text option A option B option C ``` --- ### 4.2 可选 Key-Value 输入(扩展) ```text Apple|apple Banana|banana ``` 启用参数: ```bash gselect --kv ``` * UI 显示:`Apple` * 输出结果:`apple` --- ## 5. 输出规范(stdout) ### 5.1 默认输出 * 输出 **选中项的值** * 单行文本 * 不包含换行以外的任何字符 ```text banana ``` --- ### 5.2 输出索引 ```bash gselect --index ``` stdout: ```text 1 ``` (索引从 `0` 开始) --- ## 6. 退出状态(exit code) | code | 含义 | | ---- | ------------------ | | 0 | 用户成功选择 | | 1 | 用户取消(Esc / Ctrl+C) | | 2 | 输入为空 / 无可选项 | | 3 | 参数错误 | --- ## 7. 命令行参数设计 ### 7.1 参数一览 | 参数 | 说明 | | ----------------- | ----------------- | | `--title` | 顶部标题 | | `--index` | 输出索引而非值 | | `--default` | 默认选中值 | | `--default-index` | 默认选中索引 | | `--no-search` | 禁用搜索过滤 | | `--kv` | 启用 label|value 模式 | | `--version` | 显示版本 | | `--help` | 帮助信息 | --- ### 7.2 参数示例 #### 设置标题 ```bash gselect --title "Select a branch" ``` #### 默认选中 ```bash gselect --default "banana" gselect --default-index 1 ``` #### 输出索引 ```bash gselect --index ``` #### 禁用搜索 ```bash gselect --no-search ``` --- ## 8. 交互设计 ### 8.1 键位定义(固定,不可配置) | 键 | 行为 | | ------ | --------- | | ↑ / k | 上移 | | ↓ / j | 下移 | | Enter | 确认 | | Esc | 取消 | | Ctrl+C | 取消 | | 字符输入 | 搜索过滤(如启用) | --- ### 8.2 搜索行为 * 默认启用 * 子串匹配(不要求 fuzzy) * 实时过滤 * 可通过 `--no-search` 禁用 --- ## 9. UI 设计规范 ### 9.1 技术选型 * `bubbletea` * `bubbles/list` * `lipgloss` --- ### 9.2 UI 元素 * 顶部:标题(可选) * 中部:列表 * 底部:简要提示(↑↓ Enter Esc) --- ### 9.3 风格要求 * 简洁 * 对比清晰 * 不使用 Emoji * 颜色适配暗色终端 --- ## 10. 内部模型(设计指导) ### 10.1 核心数据结构(建议) ```go type Item struct { Label string Value string Index int } ``` ```go type Model struct { List list.Model Selected *Item Cancelled bool } ``` --- ### 10.2 退出逻辑 * Enter → 输出 → `os.Exit(0)` * Esc / Ctrl+C → `os.Exit(1)` * 无输入 → `os.Exit(2)` --- ## 11. Shell 使用示例 ### 11.1 基础 ```bash choice=$(ls | gselect) || exit 1 echo "$choice" ``` --- ### 11.2 Git 分支选择 ```bash branch=$(git branch --format='%(refname:short)' | gselect) git checkout "$branch" ``` --- ### 11.3 输出索引 ```bash idx=$(printf "a\nb\nc\n" | gselect --index) ``` --- ## 12. 非功能性要求 * 启动时间 < 50ms * 单文件二进制 * 无运行时依赖 * 支持 Linux / macOS * Go ≥ 1.21 --- ## 13. 未来扩展(不在本期) * 多选模式 * 自定义分隔符 * 预览窗 * JSON 输入 --- ## 14. 成功标准(验收) * 可在 shell 中稳定使用 * Ctrl+C 不污染终端 * stdout 可直接被脚本消费 * 用户无需文档即可理解基本操作 --- ## 15. 一句话总结 > **一个“像 fzf 一样好用,但更简单、更可控、更适合脚本”的 CLI 单选器。**