Bubble Tea:用 Go 写终端 UI,这事没那么难

Bubble Tea:用 Go 写终端 UI,这事没那么难

文章目录

  • Bubble Tea:用 Go 写终端 UI,这事没那么难
    • Elm 架构在终端里的落地
    • 周边生态
    • 谁在用
    • 安装和快速上手

Bubble Tea:用 Go 写终端 UI,这事没那么难

Bubble Tea 在 GitHub 上拿了 43,400 Star。

charmbracelet 团队出的这个 Go 框架,专门用来写终端应用。它基于 Elm 架构,把终端程序拆成 Model、Update、View 三层,写起来清晰,维护起来也省事。

Elm 架构在终端里的落地

Elm 架构的核心思路是把应用分成三块:Model 管状态,Update 处理消息,View 负责渲染。Bubble Tea 把这套搬到了终端环境里。

写一个终端程序,定义一个 struct 当 Model,然后实现三个方法就行。Init 返回初始命令,Update 收到键盘输入或系统消息后更新状态,View 根据当前状态输出界面。三个方法各管各的,不会互相干扰。

框架把终端渲染、事件循环这些脏活都包了。内置的渲染器是基于单元格的,性能不错,还自带颜色降采样。键盘和鼠标事件处理也是原生的,剪贴板操作同样内置。开发者只需要管业务逻辑。

行内模式和全屏模式都支持,也能混着用。写个简单的命令行工具用行内模式,写个复杂的交互式应用切全屏,不用换框架。

周边生态

Bubble Tea 不是一个人在战斗。

Bubbles 是配套的组件库,文本输入框、列表、表格、进度条这些常见 UI 组件都有现成的,不用自己从头写。Lip Gloss 管样式和布局,终端里的排版问题它来解决。Harmonica 是动画库,做平滑过渡效果用的。BubbleZone 处理鼠标事件的区域追踪,鼠标点哪响应哪。

这几个库组合起来,写终端 UI 的体验跟写 Web 前端有点像,组件化、样式分离、状态管理一套流程。

谁在用

Bubble Tea 的 dependents 页面显示有超过 18,000 个应用在用它。

大厂也没少用。微软 Azure 的 Aztify 把 Azure 资源导入 Terraform,AWS 的 eks-node-viewer 可视化 EKS 集群节点使用情况,NVIDIA 的 container-canary 做容器验证,CockroachDB 的命令行工具也是用它写的。

社区项目里,chezmoi 管多台机器的 dotfiles,circumflex 在终端里读 Hacker News,gh-dash 是 GitHub CLI 的扩展,Superfile 是个文件管理器。还有 Glow 读 Markdown,Huh? 做交互式表单,Wishlist 当 SSH 跳板机。

覆盖的场景很广,从 DevOps 工具到日常小工具都有。

安装和快速上手

go get charm.land/bubbletea/v2

一个最简单的程序,Model 是个 struct,Init 返回 nil,Update 处理按键,View 输出文本:

typemodelstruct{choices[]stringcursorintselectedmap[int]struct{}}func(m model)Init()tea.Cmd{returnnil}func(m model)Update(msg tea.Msg)(tea.Model,tea.Cmd){switchmsg:=msg.(type){casetea.KeyPressMsg:switchmsg.String(){case"ctrl+c","q":returnm,tea.Quitcase"up","k":ifm.cursor>0{m.cursor--}case"down","j":ifm.cursor<len(m.choices)-1{m.cursor++}}}returnm,nil}func(m model)View()tea.View{s:="What should we buy?\n\n"fori,choice:=rangem.choices{cursor:=" "ifm.cursor==i{cursor=">"}checked:=" "if_,ok:=m.selected[i];ok{checked="x"}s+=fmt.Sprintf("%s [%s] %s\n",cursor,checked,choice)}returntea.NewView(s)}funcmain(){p:=tea.NewProgram(initialModel())if_,err:=p.Run();err!=nil{fmt.Println(err)os.Exit(1)}}

跑起来就是一个带光标移动和选择的列表。加上 Bubbles 组件库,能做出更复杂的界面。

调试的时候 stdout 被 TUI 占着,可以用tea.LogToFile写日志文件,Delve 调试器要开 headless 模式。这些细节官方文档里都有。

如果你在用 Go 写命令行工具,Bubble Tea 值得试试。43,000 多个 Star 不是白来的。

oFile` 写日志文件,Delve 调试器要开 headless 模式。这些细节官方文档里都有。

如果你在用 Go 写命令行工具,Bubble Tea 值得试试。43,000 多个 Star 不是白来的。