charmbracelet/bubbletea#
charmbracelet/bubbletea 是一個類似於 HTML,但是他是用在終端機中建立純文字的使用者界面。
model#
model 是 bubbletea 中最基本的元件,對應到 HTML 中就是 tag,一個 model 需要有以下三個方法
type model struct {}
func (m model) Init() tea.Cmd
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd)
func (m model) View() string
goInit
函式定義只在建立 model 時要執行的 cmd,Update
定義每個 tick 都會執行的程式,View
將 model 繪製成字串。
cmd#
cmd 需要符合以下定義
type tea.Msg interface{}
func () tea.Msg
gocmd 的功能是為了執行 IO 操作而不阻礙畫面,因此 cmd 會被放在 gorutine 中非同步執行,而 Update
不會。
如果在 Init
、Update
中要回傳多個 cmd,可以用 tea.Batch(cmd...)
把他們包起來
如果你的 cmd 需要傳入參數,例如 readFile(filename)
,可以定義成
type textMsg string
func readFile(filename string) tea.Cmd {
return func() tea.Msg {
b, err := iotuil.ReadFile(filename)
if err != nil {
return textMsg("error")
}
return textMsg(b)
}
}
go狀態#
在 model 定義狀態就在 struct 中直接新增欄位就可以了,要注意的是如果在 Update
中要存取子 model 的狀態,請把 Update
傳遞下去並在子 model 的 Update
中存取狀態
子 model 和 Init/Update 傳遞#
定義子 model
type model struct {
username textinput.Model
password textinput.Model
}
go因為 bubbletea 只負責執行 model 的 Init
和 Update
,所以請記得在 model 的 Init
和 Update
中,要記得把兩個函數的執行傳遞下去
func (m model) Init tea.Cmd {
return tea.Batch(
m.username.Init(),
m.password.Init(),
)
}
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
var cmds []tea.Cmd = make([]tea.Cmd, 2)
m.username, cmds[0] = m.usrename.Update(msg)
m.password, cmds[1] = m.password.Update(msg)
return m, tea.Batch(cmds...)
}
go問題#
如果子 model 變多,那對於傳遞的管理就會變得很複雜,要想的方法解決,需要可以一次管理不同類型的 model
心得#
Update
中只接收和自己有關的 msg,和自己無關的就傳遞下去,絕對不操作不屬於自己的屬性,不然會出 bug