tview
GitHub概要
rivo/tview
Terminal UI library with rich, interactive widgets — written in Golang
スター12,396
ウォッチ121
フォーク628
作成日:2017年12月15日
言語:Go
ライセンス:MIT License
トピックス
golangterminal-baseduser-interface
スター履歴
データ取得日時: 2025/7/25 11:09
tview
tviewは、Go言語向けのリッチなTUIライブラリで、低レベルライブラリであるtcell上に構築されています。テーブル、フォーム、リスト、モーダルなどの豊富なウィジェットを提供し、k9sなどの人気ツールで採用されています。
特徴
豊富なウィジェットセット
- 基本ウィジェット: Box、Button、Checkbox、DropDown
- 入力ウィジェット: InputField、TextArea、Form
- 表示ウィジェット: List、Table、TreeView、TextView
- レイアウト: Flex、Grid、Pages、Modal
- 特殊ウィジェット: ProgressBar、Application
使いやすいAPI
- 直感的な設計: ウィジェットベースのシンプルなAPI
- チェーンメソッド: 設定を連続して記述可能
- イベントハンドリング: コールバックベースのシンプルなイベント処理
- フォーカス管理: 自動的なフォーカス切り替え
クロスプラットフォーム
- OSサポート: Windows、macOS、Linux
- ターミナル互換: 多様なターミナルエミュレータで動作
- Unicodeサポート: 完全なUnicode対応
- マウスサポート: マウスイベントの処理
パフォーマンス
- 効率的なレンダリング: tcellによる高速描画
- 差分更新: 必要な部分のみ再描画
- 軽量: 最小限のメモリ使用
- スレッドセーフ: 並行処理に対応
基本的な使用方法
インストール
go get github.com/rivo/tview
Hello World
package main
import (
"github.com/rivo/tview"
)
func main() {
// アプリケーションの作成
app := tview.NewApplication()
// テキストボックスの作成
box := tview.NewBox().
SetBorder(true).
SetTitle("Hello, tview!").
SetTitleAlign(tview.AlignCenter)
// アプリケーションの実行
if err := app.SetRoot(box, true).Run(); err != nil {
panic(err)
}
}
フォームの作成
package main
import (
"github.com/gdamore/tcell/v2"
"github.com/rivo/tview"
)
func main() {
app := tview.NewApplication()
// フォームの作成
form := tview.NewForm().
AddInputField("Name", "", 20, nil, nil).
AddPasswordField("Password", "", 20, '*', nil).
AddCheckbox("Remember me", false, nil).
AddDropDown("Role", []string{"Admin", "User", "Guest"}, 1, nil).
AddButton("Save", func() {
// 保存処理
app.Stop()
}).
AddButton("Cancel", func() {
app.Stop()
})
form.SetBorder(true).
SetTitle("Login Form").
SetTitleAlign(tview.AlignLeft)
// ESCキーで終了
app.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey {
if event.Key() == tcell.KeyEscape {
app.Stop()
}
return event
})
if err := app.SetRoot(form, true).EnableMouse(true).Run(); err != nil {
panic(err)
}
}
テーブルの使用
package main
import (
"fmt"
"github.com/gdamore/tcell/v2"
"github.com/rivo/tview"
)
func main() {
app := tview.NewApplication()
// テーブルの作成
table := tview.NewTable().
SetBorders(true).
SetSelectable(true, false)
// ヘッダーの設定
headers := []string{"ID", "Name", "Age", "City"}
for i, header := range headers {
table.SetCell(0, i,
tview.NewTableCell(header).
SetTextColor(tcell.ColorYellow).
SetAlign(tview.AlignCenter).
SetSelectable(false))
}
// データの設定
data := [][]string{
{"1", "Alice", "30", "New York"},
{"2", "Bob", "25", "Los Angeles"},
{"3", "Charlie", "35", "Chicago"},
{"4", "Diana", "28", "Boston"},
}
for r, row := range data {
for c, cell := range row {
table.SetCell(r+1, c,
tview.NewTableCell(cell).
SetAlign(tview.AlignLeft))
}
}
// 選択イベント
table.SetSelectedFunc(func(row, column int) {
if row > 0 {
name := table.GetCell(row, 1).Text
app.Stop()
fmt.Printf("Selected: %s\n", name)
}
})
// レイアウト
flex := tview.NewFlex().
AddItem(table, 0, 1, true).
SetDirection(tview.FlexRow)
if err := app.SetRoot(flex, true).EnableMouse(true).Run(); err != nil {
panic(err)
}
}
レイアウトの構築
package main
import (
"github.com/rivo/tview"
)
func main() {
app := tview.NewApplication()
// サイドバー
sidebar := tview.NewList().
AddItem("Home", "Go to home", 'h', nil).
AddItem("Settings", "Configure app", 's', nil).
AddItem("Quit", "Exit application", 'q', func() {
app.Stop()
})
sidebar.SetBorder(true).SetTitle("Menu")
// メインコンテンツ
main := tview.NewTextView().
SetText("Welcome to tview!\n\nThis is the main content area.").
SetDynamicColors(true).
SetRegions(true).
SetWordWrap(true)
main.SetBorder(true).SetTitle("Content")
// フッター
footer := tview.NewTextView().
SetText("Press 'q' to quit | Tab to switch focus").
SetTextAlign(tview.AlignCenter)
footer.SetBorder(true)
// Flexレイアウト
flex := tview.NewFlex().
AddItem(sidebar, 20, 0, true).
AddItem(tview.NewFlex().SetDirection(tview.FlexRow).
AddItem(main, 0, 1, false).
AddItem(footer, 3, 0, false),
0, 1, false)
if err := app.SetRoot(flex, true).EnableMouse(true).Run(); err != nil {
panic(err)
}
}
高度な機能
モーダルダイアログ
func showModal(app *tview.Application, message string) {
modal := tview.NewModal().
SetText(message).
AddButtons([]string{"OK", "Cancel"}).
SetDoneFunc(func(buttonIndex int, buttonLabel string) {
if buttonLabel == "OK" {
// OKボタンの処理
}
app.SetRoot(mainView, true)
})
app.SetRoot(modal, false)
}
ツリービュー
func createTreeView() *tview.TreeView {
root := tview.NewTreeNode("Root").
SetColor(tcell.ColorRed)
tree := tview.NewTreeView().
SetRoot(root).
SetCurrentNode(root)
// 子ノードの追加
addNode := func(target *tview.TreeNode, name string) *tview.TreeNode {
node := tview.NewTreeNode(name).
SetReference(name).
SetSelectable(true)
target.AddChild(node)
return node
}
// ツリー構造の構築
node1 := addNode(root, "First")
addNode(node1, "Child 1")
addNode(node1, "Child 2")
node2 := addNode(root, "Second")
addNode(node2, "Child A")
addNode(node2, "Child B")
// 選択イベント
tree.SetSelectedFunc(func(node *tview.TreeNode) {
reference := node.GetReference()
if reference != nil {
node.SetColor(tcell.ColorGreen)
}
})
return tree
}
ページ切り替え
func createPages() *tview.Pages {
pages := tview.NewPages()
// ページ1
page1 := tview.NewTextView().
SetText("This is page 1").
SetTextAlign(tview.AlignCenter)
page1.SetBorder(true).SetTitle("Page 1")
// ページ2
page2 := tview.NewTextView().
SetText("This is page 2").
SetTextAlign(tview.AlignCenter)
page2.SetBorder(true).SetTitle("Page 2")
// ページを追加
pages.AddPage("page1", page1, true, true)
pages.AddPage("page2", page2, true, false)
return pages
}
プログレスバー
func createProgressBar() *tview.Box {
progressBar := tview.NewBox().
SetBorder(true).
SetTitle("Progress")
// カスタム描画関数
progressBar.SetDrawFunc(func(screen tcell.Screen, x, y, width, height int) (int, int, int, int) {
// プログレスの計算
progress := 0.7 // 70%
filled := int(float64(width) * progress)
// プログレスバーの描画
for i := 0; i < width; i++ {
if i < filled {
screen.SetContent(x+i, y+height/2, '█', nil, tcell.StyleDefault.Foreground(tcell.ColorGreen))
} else {
screen.SetContent(x+i, y+height/2, '░', nil, tcell.StyleDefault.Foreground(tcell.ColorGray))
}
}
return x, y, width, height
})
return progressBar
}
エコシステム
人気プロジェクトでの採用
- k9s: Kubernetes CLI
- lazydocker: Docker TUI
- wtf: ダッシュボードアプリ
- dry: Docker管理ツール
関連プロジェクト
- tcell: 低レベルターミナルライブラリ
- cview: tviewのフォーク(コンカレント性重視)
利点
- 豊富なウィジェット: 実用的なウィジェットが揃っている
- 簡単なAPI: 直感的で学習しやすい
- 安定性: 多くのプロダクションアプリで実績
- クロスプラットフォーム: 主要OSすべてで動作
- パフォーマンス: 効率的な描画
制約事項
- カスタマイズ性: ウィジェットの外観カスタマイズが限定的
- アーキテクチャ: 特定の設計パターンに従う必要がある
- 拡張性: カスタムウィジェットの作成が複雑
他のライブラリとの比較
| 項目 | tview | Bubble Tea | termui |
|---|---|---|---|
| ウィジェット | 非常に豊富 | コンポーネント系 | ダッシュボード系 |
| 学習コスト | 低 | 中 | 低〜中 |
| 柔軟性 | 中 | 非常に高 | 中 |
| コミュニティ | 大きい | 非常に大きい | 中程度 |
| 用途 | 汎用 | 汎用 | ダッシュボード |
まとめ
tviewは、Go言語でリッチなTUIアプリケーションを素早く構築したい開発者に最適なライブラリです。豊富なウィジェットセット、簡単なAPI、クロスプラットフォーム対応により、エンタープライズアプリケーションからシンプルなツールまで幅広い用途に対応できます。特に、フォームやテーブルを中心としたデータ駆動のアプリケーション開発に優れています。