在命令行中做事很酷,可以使您觉得自己像黑客电影中的英雄。但是,它也可以通过单色雪崩的文字感觉到老式的感觉,或者用所有命令线标志和美元标志前缀和不同的方式吓倒了。
。但是,命令行不是使用终端的唯一方法,也有 tuis ,终端用户界面,这给您的程序带来了更友好的感觉。我真的很喜欢Tuis,因为他们觉得自己像是新的和旧的。在Go中,最近的Bubble Tea库和all of Charm Bracelet's other tools,由于使制作Tuis变得容易引起了很多关注。
到目前为止,泡泡茶的优势是:
- 使用与浏览器UI框架共享的Elm architecture,因此,如果您已经完成了一些React,Vue或Elm,它会感到熟悉
- ELM体系结构不仅是现代前端开发人员熟悉的,而且是组织UI代码的好方法,因此它有利于简单地构建应用程序并以可管理的方式构建其逻辑
- 因为它正在走,所以语言的一致语法有利于阅读他人的代码 来学习
在本系列中,如果您正在执行#100DEVS或其中一个程序中的程序,我将从头开始构建一个基本的TUI应用程序,以记录您每天在代码中学习的内容#100Daysofcode家族。在我写这篇文章时,尚未完成,因此每个教程都将关注特定概念。大约路线图将是:
- ð£编写一个简单的Hello World应用程序,并了解其架构的工作原理
- ð构建我们的第一个真正的泡泡茶组件,菜单
- - 使用类似于CSS的Lipgloss库 ,使我们的菜单看起来很酷。
- ð将路由添加到我们的应用程序显示不同页面
- ð«§使用其他人使用的泡泡茶组件,使用Bubbles库
- ð将我们的登机手机保存到JSON文件
,请准备好您的终端和Boba大小的稻草,因为没有进一步的ADO是时候跳入泡泡茶了!
ð§编写我们的第一个基本应用
作为第一步,我们将在泡泡茶中制作一个“ Hello World”应用程序,您可以通过按CTRL+C退出,这也将向我们介绍泡泡茶应用的每个部分。
首先,在一个名为“ Code-Journal”的新目录中,运行:
go mod init
go get github.com/charmbracelet/bubbletea
然后,创建一个名为app.go
的文件,并添加以下代码:
package main
import (
tea "github.com/charmbracelet/bubbletea"
)
func main() {
p := tea.NewProgram(
newSimplePage("This app is under construction"),
)
if err := p.Start(); err != nil {
panic(err)
}
}
然后,让我们制作另一个名为simple_page.go
的文件,该文件包含我们的第一个UI,一个简单的页面,仅显示一些文本:
package main
import (
"fmt"
"strings"
tea "github.com/charmbracelet/bubbletea"
)
// MODEL DATA
type simplePage struct { text string }
func newSimplePage(text string) simplePage {
return simplePage{text: text}
}
func (s simplePage) Init() tea.Cmd { return nil }
// VIEW
func (s simplePage) View() string {
textLen := len(s.text)
topAndBottomBar := strings.Repeat("*", textLen + 4)
return fmt.Sprintf(
"%s\n* %s *\n%s\n\nPress Ctrl+C to exit",
topAndBottomBar, s.text, topAndBottomBar,
)
}
// UPDATE
func (s simplePage) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
switch msg.(type) {
case tea.KeyMsg:
switch msg.(tea.KeyMsg).String() {
case "ctrl+c":
return s, tea.Quit
}
}
return s, nil
}
在分解代码之前,让我们运行它,看看它的作用。在您的终端中,运行:
go build
./code-journal
您应该看到这样的东西:
酷!您的第一个泡泡茶应用程序正在运行。现在让我们仔细研究代码。
ð§模型是泡泡茶的主要接口
主函数通过使用simplePage
模型创建新程序来启动程序。
func main() {
p := tea.NewProgram(
newSimplePage("This app is under construction"),
)
if err := p.Start(); err != nil {
panic(err)
}
}
我们称为tea.NewProgram
,其签名是:
func NewProgram(initialModel Model) *Program
然后调用该程序的启动方法启动我们的应用程序。但是什么是initialModel
?
Model
是泡泡茶的主要接口。它有三种方法:
type Model interface {
Init() Cmd
Update(msg Msg) (Model, Cmd)
View() string
}
应用程序启动时,Init
方法是调用的,返回tea.Cmd
。 Cmd
或多或少是“幕后发生的东西”,例如加载数据或流动时间。但是对于当前的教程,我们没有任何背景内容,所以我们的init
方法只是返回nil
。
func (s simplePage) Init() tea.Cmd { return nil }
接下来,我们有了View
方法。气泡茶的酷抽象之一是您的整个UI的显示是字符串!,而View
是您制作该字符串的地方。
func (s simplePage) View() string {
textLen := len(s.text)
topAndBottomBar := strings.Repeat("*", textLen + 4)
return fmt.Sprintf(
"%s\n* %s *\n%s\n\nPress Ctrl+C to exit",
topAndBottomBar, s.text, topAndBottomBar,
)
}
因此,我们将simplePage
的文本放入由星号制成的盒子中,底部有一条消息,说“按Ctrl+C退出”
但是,如果我们无法处理用户输入,我们将无法退出应用程序,因此这就是我们的Update
方法的所在地。
func (s simplePage) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
switch msg.(type) {
case tea.KeyMsg:
switch msg.(tea.KeyMsg).String() {
case "ctrl+c":
return s, tea.Quit
}
}
return s, nil
}
Update
方法接收tea.Msg
并返回一个新的tea.Model
,有时是tea.Cmd
(例如,如果操作导致检索一些数据或计时器删除)。
a tea.Msg
的类型签名是
type Msg interface {}
因此,它可以是任何类型,并且可以携带尽可能多或少的数据。如果您在那里完成了前端,则有点像JavaScript中的浏览器事件;计时器事件不会携带任何数据,单击事件告诉您点击的内容,等等。
。我们处理的消息是tea.KeyMsg
,它代表键盘输入。我们正在检查用户是否按CTRL+C,如果是这样,我们返回tea.Quit
命令,该命令是类型tea.Cmd
,并告诉Bubble Tea退出应用程序。
对于任何其他类型的输入,我们什么都不做。我们只是返回模型。但是,如果我们在做类似UI导航之类的事情,那么我们将更改模型上的某些字段,然后返回,从而导致UI更新。这就是我们将在下一个教程中看到的内容,在该教程中,我们将制作菜单组件!