一种有趣、实用且具有状态的构建终端应用程序的方式。这是一个基于Elm架构的Go框架。泡泡茶非常适合构建简单和复杂的终端应用程序,无论是内联、全窗口还是两者的混合。
<p> <img src="https://yellow-cdn.veclightyear.com/835a84d5/bcef421b-fd4b-4adb-be05-60479a594ca3.gif" width="100%" alt="泡泡茶示例"> </p>泡泡茶已在生产环境中使用,并包含了我们在开发过程中添加的许多功能和性能优化。其中包括基于标准帧率的渲染器、与主渲染器一起工作的高性能可滚动区域渲染器以及鼠标支持。
要开始使用,请参阅下面的教程、[示例][examples]、[文档][docs]、视频教程以及一些常见的资源。
请务必查看Bubbles,这是一个用于泡泡茶的常用UI组件库。
<p> <a href="https://github.com/charmbracelet/bubbles"><img src="https://yellow-cdn.veclightyear.com/835a84d5/0ea27b6f-c629-4e08-afde-8a27f234e7f1.png" width="174" alt="Bubbles徽章"></a> <a href="https://github.com/charmbracelet/bubbles"><img src="https://yellow-cdn.veclightyear.com/835a84d5/047ba67d-e78e-471f-84da-e4dfc28bf319.gif" width="400" alt="Bubbles中的文本输入示例"></a> </p>泡泡茶基于Elm架构的函数式设计范式,这与Go语言非常契合。这是一种令人愉悦的构建应用程序的方式。
本教程假设您已经具备Go 语言的工作知识。
顺便说一下,这个程序的未注释源代码可在GitHub上获得。
在本教程中,我们将制作一个购物清单。
首先,我们定义包并导入一些库。我们唯一的外部导入将是泡泡茶库,我们将其简称为tea。
package main import ( "fmt" "os" tea "github.com/charmbracelet/bubbletea" )
泡泡茶程序由描述应用程序状态的模型和该模型上的三个简单方法组成:
让我们从定义我们的模型开始,它将存储我们应用程序的状态。它可以是任何类型,但通常结构体最有意义。
type model struct { choices []string // 待办事项列表中的项目 cursor int // 光标指向的待办事项 selected map[int]struct{} // 被选中的待办事项 }
接下来,我们将定义应用程序的初始状态。在这个例子中,我们定义了一个函数来返回我们的初始模型,但我们也可以在其他地方将初始模型定义为变量。
func initialModel() model { return model{ // 我们的待办事项列表是一个购物清单 choices: []string{"买胡萝卜", "买芹菜", "买大头菜"}, // 一个表示哪些选项被选中的映射。我们将这个映射用作数学集合。 // 键指的是上面`choices`切片的索引。 selected: make(map[int]struct{}), } }
接下来,我们定义Init方法。Init可以返回一个Cmd来执行一些初始I/O操作。现在,我们不需要进行任何I/O操作,所以对于命令,我们只返回nil,这意味着"现在不需要I/O操作"。
func (m model) Init() tea.Cmd { // 只返回`nil`,意味着"现在不需要I/O操作,谢谢"。 return nil }
接下来是update方法。当"有事情发生"时,update函数会被调用。它的工作是查看发生了什么,并相应地返回一个更新后的模型。它还可以返回一个Cmd来触发更多事件,但现在不用担心这部分。
在我们的例子中,当用户按下向下箭头键时,Update的工作是注意到向下箭头被按下,并相应地移动光标(或不移动)。
"发生的事情"以Msg的形式出现,可以是任何类型。消息是某些I/O操作的结果,比如按键、定时器滴答或服务器响应。
我们通常使用类型switch来确定收到了哪种类型的Msg,但您也可以使用类型断言。
现 在,我们只处理tea.KeyMsg消息,当按下键时,这些消息会自动发送到update函数。
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { switch msg := msg.(type) { // 是按键操作吗? case tea.KeyMsg: // 好的,实际按下的是哪个键? switch msg.String() { // 这些键应该退出程序。 case "ctrl+c", "q": return m, tea.Quit // "上"和"k"键向上移动光标 case "up", "k": if m.cursor > 0 { m.cursor-- } // "下"和"j"键向下移动光标 case "down", "j": if m.cursor < len(m.choices)-1 { m.cursor++ } // "回车"键和空格键(字面上的空格)切换 // 光标所指项目的选中状态。 case "enter", " ": _, ok := m.selected[m.cursor] if ok { delete(m.selected, m.cursor) } else { m.selected[m.cursor] = struct{}{} } } } // 将更新后的模型返回给泡泡茶运行时进行处理。 // 注意我们没有返回命令。 return m, nil }
您可能注意到上面的<kbd>ctrl+c</kbd>和<kbd>q</kbd>与模型一起返回了一个tea.Quit命令。这是一个特殊命令,它指示泡泡茶运行时退出,结束程序。
最后,是时候渲染我们的UI了。在所有方法中,视图是最简单的。我们查看模型的当前状态,并使用它返回一个string。那个字符串就是我们的UI!
因为视图描述了应用程序的整个UI,所以您不必担心重绘逻辑之类的东西。泡泡茶会为您处理这些。
func (m model) View() string { // 标题 s := "我们应该在市场上买什么?\n\n" // 遍历我们的选项 for i, choice := range m.choices { // 光标是否指向这个选项? cursor := " " // 无光标 if m.cursor == i { cursor = ">" // 有光标! } // 这个选项是否被选中? checked := " " // 未选中 if _, ok := m.selected[i]; ok { checked = "x" // 已选中! } // 渲染行 s += fmt.Sprintf("%s [%s] %s\n", cursor, checked, choice) } // 页脚 s += "\n按q退出。\n" // 发送UI进行渲染 return s }
最后一步是简单地运行我们的程序。我们将初始模型传递给tea.NewProgram并让它运行:
func main() { p := tea.NewProgram(initialModel()) if _, err := p.Run(); err != nil { fmt.Printf("哎呀,出错了:%v", err) os.Exit(1) } }
本教程介绍了构建交互式终端UI的基础知识,但在实际应用中,您还需要执行I/O操作。要了解这方面的内容,请查看[命令教程][cmd]。这很简单。
还有几个[泡泡茶示例][examples]可供参考,当然,还有[Go文档][docs]。 [cmd]: http://github.com/charmbracelet/bubbletea/tree/master/tutorials/commands/ [examples]: http://github.com/charmbracelet/bubbletea/tree/master/examples [docs]: https://pkg.go.dev/github.com/charmbracelet/bubbletea?tab=doc
由于 Bubble Tea 应用会接管标准输入和标准输出,你需要在无头模式下运行 delve,然后连接到它:
# 启动调试器 $ dlv debug --headless --api-version=2 --listen=127.0.0.1:43000 . API 服务器监听于:127.0.0.1:43000 # 从另一个终端连接到它 $ dlv connect 127.0.0.1:43000
如果你没有明确提供 --listen 标志,每次运行时使用的端口都会变化,所以传入这个参数可以让调试器更容易从脚本或你选择的 IDE 中使用。
另外,我们传入 --api-version=2,因为 delve 出于向后兼容的原因默认使用版本 1。然而,delve 建议所有新的开发都使用版本 2,而且某些客户端可能不再支持版本 1。
更多信息,请参阅 Delve 文档。
你不能真的在 Bubble Tea 中将日志记录到标准输出,因为你的 TUI 正忙于占用它!但是,你可以通过在启动 Bubble Tea 程序之前包含类似以下内容来将日志记录到文件:
if len(os.Getenv("DEBUG")) > 0 { f, err := tea.LogToFile("debug.log", "debug") if err != nil { fmt.Println("fatal:", err) os.Exit(1) } defer f.Close() }
要实时查看正在记录的内容,在运行程序的同时,在另一个窗口中运行 tail -f debug.log。
要查看一些生产环境中的 Bubble Tea 程序,请参阅:
我们很乐意听到您对这个项目的看法。欢迎给我们留言!
Bubble Tea 基于 Evan Czaplicki 等人的 The Elm Architecture 范式和 TJ Holowaychuk 的优秀作品 go-tea。它受到过去许多伟大的字符界面的启发。
Charm 的一部分。
<a href="https://charm.sh/"><img alt="Charm标志" src="https://yellow-cdn.veclightyear.com/835a84d5/0dd6719c-974e-4502-a35f-e97502724013.jpg" width="400"></a>
Charm热爱开源 • Charm loves open source • نحنُ نحب المصادر المفتوحة


职场AI,就用扣子
AI办公助手,复杂任务高效处理。办公效率低?扣子空间AI助手支持播客生成、PPT制作、网页开发及报告写作,覆盖科研、商业、舆情等领域的专家Agent 7x24小时响应,生活工作无缝切换,提升50%效率!


多风格AI绘画神器
堆友平台由阿里巴巴设计团队创建,作为一款AI驱动的设计工具,专为设计师提供一站式增长服务。功能覆盖海量3D素材、AI绘画、实时渲染以及专业抠图,显著提升设计品质和效率。平台不仅提供工具,还是一个促进创意交流和个人发展的空间,界面友好,适合所有级别的设计师和创意工作者。


零代码AI应用开发平台
零代码AI应用开发平台,用户只需一句话简单描述需求,AI能自动生成小程序、APP或H5网页应用,无需编写代码。


免费创建高清无水印Sora视频
Vora是一个免费创建高清无水印Sora视频的AI工具


最适合小白的AI自动化工作流平台
无需编码,轻松生成可复用、可变现的AI自动化工作流

大模型驱动的Excel数据处理工具
基于大模型交互的表格处理系统,允许用户通过对话方式完成数据整理和可视化分析。系统采用机器学习算法解析用户指令,自动执行排序、公式计算和数据透视等操作,支持多种文件格式导入导出。数据处理响应速度保持在0.8秒以内,支持超过100万行数据的即时分析。


AI辅助编程,代码自动修复
Trae是一种自适应的集成开发环境(IDE),通过自动化和多元协作改变开发流程。利用Trae,团队能够更快速、精确地编写和部署代码,从而提高编程效率和项目交付速度。Trae具备上下文感知和代码自动完成功能,是提升开发效率的理想工具。


AI论文写作指导平台
AIWritePaper论文写作是一站式AI论文写作辅助工具,简化了选题、文献检索至论文撰写的整个过程。通过简单设定,平台可快速生成高质量论文大纲和全文,配合图表、参考文献等一应俱全,同时提供开题报告和答辩PPT等增值服务,保障数据安全,有效提升写作效率和论文质量。


AI一键生成PPT,就用博思AIPPT!
博思AIPPT,新一代的AI生成PPT平台,支持智能生成PPT、AI美化PPT、文本&链接生成PPT、导入Word/PDF/Markdown文档生成PPT等,内置海量精美PPT模板,涵盖商务、教育、科技等不同风格,同时针对每个页面提供多种版式,一键自适应切换,完美适配各种办公场景。


AI赋能电商视觉革命,一站式智能商拍平台
潮际好麦深耕服装行业,是国内AI试衣效果最好的软件。使用先进AIGC能力为电商卖家批量提供优质的、低成本的商拍图。合作品牌有Shein、Lazada、安踏、百丽等65个国内外头部品牌,以及国内10万+淘宝、天猫、京东等主流平台的品牌商家,为卖家节省将近85%的出图成本,提升约3倍出图效率,让品牌能够快速上架。
最新AI工具、AI资讯
独家AI资源、AI项目落地

微信扫一扫关注公众号