This is an introduction to using tview (or cview) to create rich terminal-based user interfaces with Go.

Primitives

The Primitive interface is as follows:

type Primitive interface { Draw ( screen tcell . Screen ) GetRect () ( int , int , int , int ) SetRect ( x , y , width , height int ) InputHandler () func ( event * tcell . EventKey , setFocus func ( p Primitive )) Focus ( delegate func ( p Primitive )) Blur () GetFocusable () Focusable }

Box is the only primitive implemented. It has a size, padding amount, optional border, optional title and background color.

Widgets

Widgets are structs which embed a Box and build upon it.

From the TextView declaration:

type TextView struct { * Box // The text buffer. buffer [] string // The text alignment, one of AlignLeft, AlignCenter, or AlignRight. align int // ... }

Some widgets allow nesting other widgets within them, such as Grid.

Most widget commands may be chained together:

nameLabel := tview . NewTextView (). SetTextAlign ( tview . AlignRight ). SetDynamicColors ( true ). SetWrap ( true ). SetWordWrap ( true ). SetText ( "Please enter your name:" )

New widgets may be defined, as documented in the Primitive demo.

Widget Elements

Button is a labeled box that triggers an action when selected.

button := tview . NewButton ( "OK" ). SetSelectedFunc ( func () { pressedOK () })

Checkbox holds a label and boolean value which may be checked and unchecked.

checkbox := tview . NewCheckbox (). SetLabel ( "Toggle value with Enter: " )

DropDown holds one or more options which may be selected as a dropdown list.

dropdown := tview . NewDropDown (). SetLabel ( "Select an option with Enter: " ). SetOptions ([] string { "Foo" , "Bar" , "Baz" }, nil )

InputField is a box where text may be entered.

inputField := tview . NewInputField (). SetLabel ( "Name: " ). SetPlaceholder ( "John Smith" ). SetFieldWidth ( 14 ). SetDoneFunc ( func ( key tcell . Key ) { processName () })

Modal is a centered message window which may have one or more buttons.

modal := tview . NewModal (). SetText ( "Are you sure you want to exit?" ). AddButtons ([] string { "Cancel" , "Quit" }). SetDoneFunc ( func ( buttonIndex int , buttonLabel string ) { if buttonIndex == 1 { app . Stop () } })

TextView is a box containing text. Colored text is supported when enabled.

textView := tview . NewTextView (). SetWrap ( true ). SetWordWrap ( true ). SetText ( "Hello, World!" )

Widget Containers

Flex is a flexbox layout container.

See the Flex demo for example usage.

Grid is a grid layout container.

See the Grid demo for example usage.

Form displays one or more form elements in a vertical or horizontal layout.

See the Form demo for example usage.

List displays one or more widgets as a selectable list.

See the List demo for example usage.

Pages displays one or more widgets at a time.

See the Pages demo for example usage.

Table displays one or more widgets in rows and columns.

See the Table demo for example usage.

TreeView displays one or more widgets in a tree.

See the TreeView demo for example usage.

Thread Safety

Most tview functions cannot safely be called from any thread except the main one.

Using either of the following functions, we can queue a function to be executed in the main thread.

The only difference between the two is that QueueUpdateDraw calls Application.Draw after the queued function returns.

One exception is TextView.Write, which may safely be called from multiple goroutines.

Below is an example of setting a new root primitive from another goroutine.

app . QueueUpdateDraw ( func () { app . SetRoot ( appGrid , true ) })

Example Application

A tview application is constructed of a running Application with at least one root widget.

To display a primitive (and its contents), we call Application.SetRoot.

This function has two arguments, a primitive which will become the root of the screen, and a boolean which controls whether the primitive will be resized to fit the screen.

In this example, the root is a Grid containing a label, an input and a submit button. For a more complex example, see netris.

Install tview if you haven’t already:

go get -u github.com/rivo/tview

Then create a file named greet.go: