-
Notifications
You must be signed in to change notification settings - Fork 787
Home
termui is initialized with:
if err := ui.Init(); err != nil {
log.Fatalf("failed to initialize termui: %v", err)
}
defer ui.Close()
which basically wraps the termbox-go Init()
function and sets some sane defaults like 256 color support and mouse support. Close
also wraps the termbox-go Close
function. Initializing termui sets up the terminal to display widgets that you create and Close
resets terminal settings to their normal state.
There are several built in widgets, and custom widgets can also be created. To use a built-in widget, you simply give it data to render, optionally customize its rendering options, then pass it to ui.Render
. Each widget has unique rendering options, but they all inherit from Block
which provides addition common options for managing border, padding, and a title.
A common approach for using widgets is to create a struct that inherits from a renderable widget, and also implements an update
method that updates the data to render.
To implement a custom widget, you can inherit from Block
, and create a custom Draw(Buffer)
method. The Draw(Buffer)
method allows a widget to draw its contents onto a provided Buffer
object. Buffer
s represent a rectangular region of a terminal, and contain Cells
which represent individual terminal cells. Cell
s hold a character and a Style
, and a Style
contains foreground and background colors and any modifications like underline, etc. There are various constructor methods to use for each of these objects, e.g. NewCell()
.
Note: Block.Inner
should be used to calculate the position of where to put Cell
s in the Buffer
. e.g.: to draw an 'a' in the top left corner of the Buffer
, you should do:
buf.SetCell(NewCell('a'), image.Pt(self.Inner.Min.X, self.Inner.Min.Y))
Widgets inherit from Block
which provides methods for positioning and resizing widgets.
To position a widget absolutely, call the SetRect(x0, y0, x1, y1)
method which defines the area that the widget draws to.
To position widgets in a relative way, you can create a Grid
which stores widgets in rows and columns that take up a percentage of the screen. The Grid
sizes the widgets initially, and also resizes them when the terminal resizes.
termui
provides event handling for keypresses, mouse actions, and screen resizing. termui.PollEvents()
returns a channel that converts and propogates events originating from termbox. Event types are detailed in events.go.
To update widget data on an interval, use Go's built in tickers.
Event loop example:
uiEvents := ui.PollEvents()
ticker := time.NewTicker(time.Second).C
for {
select {
case e := <-uiEvents:
switch e.ID { // event string/identifier
case "q", "<C-c>": // press 'q' or 'C-c' to quit
return
case "<MouseLeft>":
payload := e.Payload.(ui.Mouse)
x, y := payload.X, payload.Y
case "<Resize>":
payload := e.Payload.(ui.Resize)
width, height := payload.Width, payload.Height
}
switch e.Type {
case ui.KeyboardEvent: // handle all key presses
eventID = e.ID // keypress string
}
// use Go's built-in tickers for updating and drawing data
case <-ticker:
drawFunction()
}
}
Each widget has fields that determine what its colors should be. Widgets inhereit their colors from termui.Theme
which holds the default colors for every widget. You can either set the colors of a widget after instantiating it, or change the default widget colors in termui.Theme
for all new widgets to inherit from.
The 2 ways of representing color in termui are either with Color
or Style
. A Color
is a regular terminal color from -1 to 255, with -1 being clear. A Style
holds a foreground color, background color, and also an optional modifier, such as reverse, underline, or bold.
Rendering widgets or a Grid
works by calling the termui.Render(Drawable)
function. Any struct that implements Drawable
can be rendered. Drawable
requires the GetRect
and SetRect
methods for widget sizing and the Draw(Buffer)
method which renders the widget. GetRect
and SetRect
are implemented by Block
so you don't have to worry about that if you inherit from it. Render
works by creating a Buffer
, filling it with empty Cell
s, passing the Buffer
to the widget through its Draw
method, and then iterating over the drawn Cell
s which are then passed to termbox-go. Grid
's Draw
method works by having each of its widgets Draw
to the Buffer
that it is given.