gselect 是一个 基于 Golang + Bubble Tea 的交互式命令行选择器, 以 单选为核心,用于补全 shell 脚本中缺失的“美观、稳定、可控”的交互选择能力。
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

5.1 KiB

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 友好

    • 输出可直接被 $(...)mapfileread 使用
    • 不输出多余日志
  4. 接口极简

    • 参数少
    • 行为直观
    • 无配置文件依赖

3. 使用方式总览

3.1 基础用法(默认单选)

printf "apple\nbanana\norange\n" | gselect

用户交互:

  • ↑ ↓ 移动
  • Enter 确认
  • Esc / Ctrl+C 取消

stdout:

banana

exit code:

  • 0:成功选择
  • 1:用户取消 / 无选择

4. 输入规范(stdin)

4.1 输入格式

  • 每行一个选项
  • 空行忽略
  • 原样显示,不做 trim / escape
option A
option B
option C

4.2 可选 Key-Value 输入(扩展)

Apple|apple
Banana|banana

启用参数:

gselect --kv
  • UI 显示:Apple
  • 输出结果:apple

5. 输出规范(stdout)

5.1 默认输出

  • 输出 选中项的值
  • 单行文本
  • 不包含换行以外的任何字符
banana

5.2 输出索引

gselect --index

stdout:

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
--version 显示版本
--help 帮助信息

7.2 参数示例

设置标题

gselect --title "Select a branch"

默认选中

gselect --default "banana"
gselect --default-index 1

输出索引

gselect --index

禁用搜索

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 核心数据结构(建议)

type Item struct {
    Label string
    Value string
    Index int
}
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 基础

choice=$(ls | gselect) || exit 1
echo "$choice"

11.2 Git 分支选择

branch=$(git branch --format='%(refname:short)' | gselect)
git checkout "$branch"

11.3 输出索引

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 单选器。