長條貓窩

Back

(Legacy)

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
go

Init 函式定義只在建立 model 時要執行的 cmd,Update 定義每個 tick 都會執行的程式,View 將 model 繪製成字串。

cmd#

cmd 需要符合以下定義

type tea.Msg interface{}
func () tea.Msg
go

cmd 的功能是為了執行 IO 操作而不阻礙畫面,因此 cmd 會被放在 gorutine 中非同步執行,而 Update 不會。 如果在 InitUpdate 中要回傳多個 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 的 InitUpdate,所以請記得在 model 的 InitUpdate 中,要記得把兩個函數的執行傳遞下去

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

Bubbletea
https://blog.simbafs.cc/blog/bubbletea/
Author Simba Fs
Published at January 8, 2023