A Go package for building tview terminal UI applications from YAML configuration files.
tviewyaml allows you to define your terminal UI layouts, widgets, and interactions in YAML files instead of writing Go code. This makes it easier to:
- Design and prototype terminal UIs quickly
- Separate UI structure from application logic
- Modify layouts without recompiling
- Create reusable UI components
go get github.com/cassdeckard/tviewyaml- Declarative UI: Define your entire UI structure in YAML
- Rich Widget Support: Lists, Forms, Tables, Trees, Grids, Flex layouts, and more
- Template Functions: Built-in functions for page navigation, modals, and custom callbacks
- Color Support: Easy color configuration with named colors
- Validation: Built-in configuration validation
- Box
- TextView
- Button
- List
- Flex (horizontal/vertical layouts)
- Form (with InputField, Checkbox, Dropdown, Button)
- Table
- TreeView
- Grid
- Modal
- Pages
application:
name: "My TView App"
enableMouse: true
globalKeyBindings:
- key: "Escape"
action: '{{ switchToPage "main" }}'
- key: "Ctrl+Q"
action: '{{ stopApp }}'
root:
type: pages
pages:
- name: main
ref: main.yaml
- name: settings
ref: settings.yamltype: list
title: Main Menu
border: true
titleAlign: center
listItems:
- mainText: Start Application
secondaryText: Launch the main app
shortcut: "s"
onSelected: "{{ showSimpleModal \"Application Started!\" \"OK\" }}"
- mainText: Settings
secondaryText: Configure application
shortcut: "c"
onSelected: "{{ switchToPage \"settings\" }}"
- mainText: Exit
secondaryText: Quit the application
shortcut: "q"
onSelected: "{{ stopApp }}"package main
import (
"log"
"github.com/cassdeckard/tviewyaml"
)
func main() {
// Create app from YAML config directory using the Builder pattern
app, err := tviewyaml.NewAppBuilder("./config").
Build()
if err != nil {
log.Fatal(err)
}
// Run the application
if err := app.Run(); err != nil {
log.Fatal(err)
}
}The root configuration file defines application-level settings and the root view:
application: Top-level application configurationname: Application name (optional)enableMouse: Enable mouse support (optional, defaults to true)globalKeyBindings: Array of global keyboard shortcutskey: Key string (e.g., "Escape", "Ctrl+Q", "F1")action: Template expression to execute
root: The root view definition (currently must be type "pages")type: View type (currently only "pages" supported)pages: Array of page references
The example/ directory contains a comprehensive demonstration application showcasing all widget types and features. This is the best way to learn how to use tviewyaml.
cd example
go run main.goThe example application demonstrates:
- Layouts: Flex (horizontal/vertical), Grid (responsive)
- Widgets: Box, Button, Checkbox, Dropdown, Form, InputField, List, Modal, Table, TextView, TreeView
- Features: Borders, titles, colors, text alignment, dynamic colors, regions
- Callbacks: Page navigation, modals, form submissions, app control
- Patterns: Nested layouts, complex forms, data tables, hierarchical trees
- Use arrow keys and Tab to navigate between items
- Press shortcut keys (shown in the main menu) to jump to specific demos
- Press ESC to return to the main menu from any page
See the example README for detailed information about each demonstration.
Built-in template functions for callbacks:
switchToPage "pageName"- Navigate to a different pageremovePage "pageName"- Remove a page from the stackstopApp- Exit the applicationshowSimpleModal "text" "button1" "button2"- Show a modal dialognoop- No operation (placeholder callback)
You can register custom template functions using the Builder API. Each function is defined by:
- Name: String identifier used in templates (e.g.,
"myCustomFunc") - MinArgs: Minimum number of arguments (non-negative integer)
- MaxArgs: Maximum number of arguments (
nilfor unlimited/variadic) - Validator: Optional validation function (called after argument count is validated)
- Handler: Function that executes the template logic
package main
import (
"log"
"github.com/cassdeckard/tviewyaml"
"github.com/cassdeckard/tviewyaml/template"
)
func main() {
// Helper to create *int for maxArgs
intPtr := func(i int) *int { return &i }
app, err := tviewyaml.NewAppBuilder("./config").
WithTemplateFunction("logMessage", 1, intPtr(1), nil,
func(ctx *template.Context, message string) {
log.Printf("Custom log: %s", message)
},
).
WithTemplateFunction("switchAndLog", 2, intPtr(2), nil,
func(ctx *template.Context, pageName, logMsg string) {
log.Printf("Switching to %s: %s", pageName, logMsg)
ctx.Pages.SwitchToPage(pageName)
},
).
Build()
if err != nil {
log.Fatal(err)
}
if err := app.Run(); err != nil {
log.Fatal(err)
}
}Then use in your YAML:
onSelected: "{{ logMessage \"Button clicked!\" }}"
onSelected: "{{ switchAndLog \"settings\" \"User opened settings\" }}"app, err := tviewyaml.NewAppBuilder("./config").
WithTemplateFunction("multiLog", 1, nil, nil,
func(ctx *template.Context, args []string) {
// Variadic - accepts 1 or more arguments
for i, arg := range args {
log.Printf("Arg %d: %s", i, arg)
}
},
).
Build()Use in YAML:
onSelected: "{{ multiLog \"first\" \"second\" \"third\" }}"app, err := tviewyaml.NewAppBuilder("./config").
WithTemplateFunction("switchToExistingPage", 1, intPtr(1),
func(ctx *template.Context, args []string) error {
pageName := args[0]
// Validate that the page exists
if !pageExists(ctx.Pages, pageName) {
return fmt.Errorf("page %q does not exist", pageName)
}
return nil
},
func(ctx *template.Context, pageName string) {
ctx.Pages.SwitchToPage(pageName)
},
).
Build()Note: The validator is only called after argument count validation passes. Use it for semantic validation like checking if a page exists or validating argument format.
github.com/cassdeckard/tviewyaml/
├── app.go # Application builder (deprecated CreateApp)
├── builder.go # AppBuilder with Builder pattern API
├── builder/ # UI builder components
│ ├── builder.go
│ ├── callbacks.go
│ ├── factory.go
│ └── properties.go
├── config/ # Configuration loading and types
│ ├── loader.go
│ ├── types.go
│ └── validator.go
├── keys/ # Key binding parsing
│ └── keys.go # ParseKey for key string parsing
└── template/ # Template execution
├── builtins.go # Built-in template functions
├── context.go
├── executor.go
├── keybinding.go # MatchesKeyBinding for key event matching
└── registry.go # Function registry system
Contributions are welcome! Please feel free to submit a Pull Request.
This package is published at github.com/cassdeckard/tviewyaml.
To use it in your projects:
go get github.com/cassdeckard/tviewyamlTo publish a new version:
- Tag the release:
git tag v0.1.0 - Push the tag:
git push origin v0.1.0 - Go will automatically make it available via the module proxy
Built on top of the excellent tview library by rivo.