建立終端應用程式的有趣、實用且有狀態的方式。基於 Elm 架構的 Go 框架。 Bubble Tea 非常適合簡單且複雜的終端應用程序,無論是內聯、全視窗還是兩者的混合。
Bubble Tea 已在生產中使用,並包含我們在過程中添加的許多功能和性能優化。其中包括基於標準幀速率的渲染器、與主渲染器一起工作的高效能可滾動區域的渲染器以及滑鼠支援。
要開始使用,請參閱下面的教學、範例、文件、影片教學課程和一些常用資源。
請務必查看 Bubbles,這是 Bubble Tea 的常見 UI 元件庫。
Bubble Tea 基於 Elm 架構的功能設計範式,剛好與 Go 配合得很好。這是建立應用程式的一種令人愉快的方式。
本教學假設您具備 Go 的應用知識。
順便說一句,該程式的未註釋原始程式碼可以在 GitHub 上找到。
在本教學中,我們將製作一份購物清單。
首先,我們將定義我們的套件並導入一些庫。我們唯一的外部導入是 Bubble Tea 庫,我們簡稱為tea
。
package main
import (
"fmt"
"os"
tea "github.com/charmbracelet/bubbletea"
)
Bubble Tea 程式由一個描述應用程式狀態的模型和該模型上的三個簡單方法組成:
因此,讓我們先定義儲存應用程式狀態的模型。它可以是任何類型,但struct
通常最有意義。
type model struct {
choices [] string // items on the to-do list
cursor int // which to-do list item our cursor is pointing at
selected map [ int ] struct {} // which to-do items are selected
}
接下來,我們將定義應用程式的初始狀態。在本例中,我們定義一個函數來傳回初始模型,但是,我們也可以在其他地方輕鬆地將初始模型定義為變數。
func initialModel () model {
return model {
// Our to-do list is a grocery list
choices : [] string { "Buy carrots" , "Buy celery" , "Buy kohlrabi" },
// A map which indicates which choices are selected. We're using
// the map like a mathematical set. The keys refer to the indexes
// of the `choices` slice, above.
selected : make ( map [ int ] struct {}),
}
}
接下來,我們定義Init
方法。 Init
可以傳回一個可以執行一些初始 I/O 的Cmd
。目前,我們不需要執行任何 I/O,因此對於命令,我們只需返回nil
,即「無命令」。
func ( m model ) Init () tea. Cmd {
// Just return `nil`, which means "no I/O right now, please."
return nil
}
接下來是更新方法。當「事情發生」時,更新函數就會被呼叫。它的工作是查看發生的情況並返回更新的模型作為回應。它還可以返回一個Cmd
來使更多的事情發生,但現在不用擔心這部分。
在我們的例子中,當使用者按下向下箭頭時, Update
的工作是注意到向下箭頭被按下並相應地(或不移動)遊標。
「發生了什麼事」以Msg
的形式出現,可以是任何類型。訊息是發生的某些 I/O 的結果,例如按鍵、計時器滴答或伺服器的回應。
我們通常使用類型開關來確定收到的Msg
類型,但您也可以使用類型斷言。
現在,我們只處理tea.KeyMsg
訊息,當按下按鍵時,這些訊息會自動傳送到更新函數。
func ( m model ) Update ( msg tea. Msg ) (tea. Model , tea. Cmd ) {
switch msg := msg .( type ) {
// Is it a key press?
case tea. KeyMsg :
// Cool, what was the actual key pressed?
switch msg . String () {
// These keys should exit the program.
case "ctrl+c" , "q" :
return m , tea . Quit
// The "up" and "k" keys move the cursor up
case "up" , "k" :
if m . cursor > 0 {
m . cursor --
}
// The "down" and "j" keys move the cursor down
case "down" , "j" :
if m . cursor < len ( m . choices ) - 1 {
m . cursor ++
}
// The "enter" key and the spacebar (a literal space) toggle
// the selected state for the item that the cursor is pointing at.
case "enter" , " " :
_ , ok := m . selected [ m . cursor ]
if ok {
delete ( m . selected , m . cursor )
} else {
m . selected [ m . cursor ] = struct {}{}
}
}
}
// Return the updated model to the Bubble Tea runtime for processing.
// Note that we're not returning a command.
return m , nil
}
您可能已經注意到上面的ctrl+c和q傳回帶有模型的tea.Quit
指令。這是一個特殊的命令,它指示 Bubble Tea 運行時退出,退出程式。
最後,是時候渲染我們的 UI 了。在所有方法中,視圖是最簡單的。我們查看模型的當前狀態並使用它返回string
。該字串就是我們的 UI!
因為視圖描述了應用程式的整個 UI,所以您不必擔心重繪邏輯之類的事情。珍珠奶茶為您照顧一切。
func ( m model ) View () string {
// The header
s := "What should we buy at the market? n n "
// Iterate over our choices
for i , choice := range m . choices {
// Is the cursor pointing at this choice?
cursor := " " // no cursor
if m . cursor == i {
cursor = ">" // cursor!
}
// Is this choice selected?
checked := " " // not selected
if _ , ok := m . selected [ i ]; ok {
checked = "x" // selected!
}
// Render the row
s += fmt . Sprintf ( "%s [%s] %s n " , cursor , checked , choice )
}
// The footer
s += " n Press q to quit. n "
// Send the UI for rendering
return s
}
最後一步是簡單地運行我們的程式。我們將初始模型傳遞給tea.NewProgram
並讓它撕裂:
func main () {
p := tea . NewProgram ( initialModel ())
if _ , err := p . Run (); err != nil {
fmt . Printf ( "Alas, there's been an error: %v" , err )
os . Exit ( 1 )
}
}
本教學涵蓋了建立互動式終端 UI 的基礎知識,但在現實世界中,您還需要執行 I/O。若要了解相關內容,請查看命令教學。這很簡單。
還有一些可用的 Bubble Tea 範例,當然還有 Go Docs。
由於 Bubble Tea 應用程式控制了 stdin 和 stdout,因此您需要在無頭模式下運行 delve,然後連接到它:
# Start the debugger
$ dlv debug --headless --api-version=2 --listen=127.0.0.1:43000 .
API server listening at: 127.0.0.1:43000
# Connect to it from another terminal
$ dlv connect 127.0.0.1:43000
如果您沒有明確提供--listen
標誌,則每次執行所使用的連接埠都會有所不同,因此傳遞該連接埠將使偵錯器更容易從腳本或您選擇的 IDE 中使用。
此外,我們傳入--api-version=2
是因為出於向後相容性原因 delve 預設為版本 1。但是,delve 建議對所有新開發使用版本 2,並且某些客戶端可能不再使用版本 1。
您無法真正使用 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
。
有超過 8k 個使用 Bubble Tea 建立的應用程式!這是其中的一小部分。
有關使用 Bubble Tea 構建的更多應用程序,請參閱 Charm & Friends。您有什麼用珍珠奶茶製作的很酷的東西想分享嗎?歡迎 PR!
請參閱貢獻。
我們很想聽聽您對此項目的想法。請隨時給我們留言!
Bubble Tea 是基於 Evan Czaplicki 等人的 The Elm Architecture 範例以及 TJ Holowaychuk 的優秀 go-tea。它的靈感來自過去許多偉大的Zeichenorientierte Benutzerschnittstellen 。
麻省理工學院
魅力的一部分。
Charm 熱愛開源 • Charm 熱愛開源 • Charm 熱愛開源