터미널 앱을 구축하는 재미 있고 기능적이며 상태를 저장하는 방법입니다. Elm 아키텍처를 기반으로 하는 Go 프레임워크입니다. Bubble Tea는 인라인, 전체 창 또는 둘의 혼합 등 간단하고 복잡한 터미널 애플리케이션에 매우 적합합니다.
Bubble Tea는 프로덕션에서 사용 중이며 그 과정에서 추가된 다양한 기능과 성능 최적화가 포함되어 있습니다. 그 중에는 표준 프레임 속도 기반 렌더러, 메인 렌더러와 함께 작동하는 고성능 스크롤 가능 영역용 렌더러 및 마우스 지원이 있습니다.
시작하려면 아래 튜토리얼, 예제, 문서, 비디오 튜토리얼 및 몇 가지 공통 리소스를 참조하십시오.
Bubble Tea의 일반적인 UI 구성 요소 라이브러리인 Bubbles를 꼭 확인하세요.
Bubble Tea는 Go와 잘 작동하는 The Elm Architecture의 기능적 디자인 패러다임을 기반으로 합니다. 이는 애플리케이션을 구축하는 즐거운 방법입니다.
이 튜토리얼에서는 귀하가 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도 수행해야 합니다. 이에 대해 알아보려면 Command Tutorial을 살펴보세요. 꽤 간단합니다.
또한 여러 가지 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에서 디버거를 더 쉽게 사용할 수 있습니다.
또한 이전 버전과의 호환성을 위해 delve의 기본값은 버전 1이므로 --api-version=2
를 전달합니다. 그러나 Delve는 모든 새로운 개발에 버전 2를 사용할 것을 권장하며 일부 클라이언트는 더 이상 버전 1에서 작동하지 않을 수 있습니다. 자세한 내용은 Delve 설명서를 참조하세요.
TUI가 그것을 차지하느라 바빠서 Bubble Tea를 사용하여 stdout에 실제로 로그인할 수 없습니다! 그러나 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로 구축된 애플리케이션이 8,000개가 넘습니다! 여기에 몇 가지가 있습니다.
Bubble Tea로 구축된 더 많은 애플리케이션을 보려면 Charm & Friends를 참조하세요. 버블티로 만든 멋진 음식을 공유하고 싶으신가요? PR을 환영합니다!
기여를 참조하세요.
우리는 이 프로젝트에 대한 귀하의 생각을 듣고 싶습니다. 언제든지 메모를 남겨주세요!
Bubble Tea는 Evan Czaplicki 등의 The Elm Architecture 패러다임과 TJ Holowaychuk의 뛰어난 고티를 기반으로 합니다. 과거의 수많은 위대한 Zeichenorientierte Benutzerschnittstellen 에서 영감을 얻었습니다.
MIT
매력의 일부.
Charm热爱开源 • Charm은 오픈소스를 좋아합니다. • نحنُ نحب المصادر المتوحة