gotui

package module
v0.0.0-...-a33e0d3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 11, 2025 License: MIT Imports: 10 Imported by: 0

README

gotui

gotui is a cross-platform and fully-customizable terminal dashboard and widget library built on top of tcell. It is a modern fork of termui, inspired by blessed-contrib, tui-rs, and ratatui and written purely in Go by Carsen Klock.

Logo

Note

This is a modern fork of termui for 2025, heavily upgraded to support TrueColor, modern terminal events, and new layouts.

Versions

gotui is compatible with Go 1.24+.

Features

  • Backend: Native tcell support for TrueColor (24-bit RGB), mouse events, and resize handling.
  • Gauges: Progress bars and gauges.
  • Charts:
    • BarChart: Stacked and standard bar charts.
    • PieChart: Pie and Donut charts.
    • RadarChart: Spider/Radar charts.
    • TreeMap: Hierarchical data visualization.
    • FunnelChart: Process flow/conversion charts.
    • Sparkline: Mini sparklines.
    • Plot: Line, Scatter, and Braille-mode charts.
  • Maps:
    • World Map: High-resolution world map example using the generic Canvas widget (see _examples/canvas.go).
  • New Widgets:
    • LineGauge: Thin, character-based progress bar with alignment options.
    • Logo: Pixel-perfect block-style logo renderer.
  • Layout:
    • Grid: Responsive grid layout.
    • Tabs: Tabbed navigation.
    • Interactive: Calendar, Tables, Input, TextArea.
  • Styling:
    • Full RGB Color support.
    • Border titles (Top and Bottom) with alignment (Left, Center, Right).
    • Rich styling parser for text.
    • Collapsed Borders: Support for merging adjacent block borders using BorderCollapse.
  • Compatibility: Works with modern terminals (iTerm2, Kitty, Alacritty, Ghostty).

Installation

Go modules

It is not necessary to go get gotui, since Go will automatically manage any imported dependencies for you.

go get github.com/metaspartan/gotui

Hello World

package main

import (
	"log"

	ui "github.com/metaspartan/gotui"
	"github.com/metaspartan/gotui/widgets"
)

func main() {
	if err := ui.Init(); err != nil {
		log.Fatalf("failed to initialize gotui: %v", err)
	}
	defer ui.Close()

	p := widgets.NewParagraph()
	p.Text = "Hello World!"
	p.SetRect(0, 0, 25, 5)

	ui.Render(p)

	for e := range ui.PollEvents() {
		if e.Type == ui.KeyboardEvent {
			break
		}
	}
}

Widgets

Run an example with go run _examples/{example}.go or run each example consecutively with make run-examples.

Uses

(Submit your projects via a PR)

Acknowledgments

Author(s)

gotui Author: Carsen Klock - X

termui Author: Zack Guo - Github

License

MIT

Documentation

Overview

Package gotui is a library for creating terminal user interfaces (TUIs) using widgets.

Index

Constants

View Source
const (
	BorderTop    = 1 // 0001
	BorderRight  = 2 // 0010
	BorderBottom = 4 // 0100
	BorderLeft   = 8 // 1000
)

Border Connections Bitmask

View Source
const (
	DOT      = '•'
	ELLIPSES = '…'

	UP_ARROW   = '▲'
	DOWN_ARROW = '▼'

	COLLAPSED = '+'
	EXPANDED  = '−'
)
View Source
const (
	TOP_LEFT     = '┌'
	TOP_RIGHT    = '┐'
	BOTTOM_LEFT  = '└'
	BOTTOM_RIGHT = '┘'

	ROUNDED_TOP_LEFT     = '╭'
	ROUNDED_TOP_RIGHT    = '╮'
	ROUNDED_BOTTOM_LEFT  = '╰'
	ROUNDED_BOTTOM_RIGHT = '╯'

	VERTICAL_LINE   = '│'
	HORIZONTAL_LINE = '─'

	VERTICAL_LEFT   = '┤'
	VERTICAL_RIGHT  = '├'
	HORIZONTAL_UP   = '┴'
	HORIZONTAL_DOWN = '┬'

	QUOTA_LEFT  = '«'
	QUOTA_RIGHT = '»'

	VERTICAL_DASH   = '┊'
	HORIZONTAL_DASH = '┈'
)
View Source
const (
	// Add CROSS if missing from symbols
	CROSS = '┼'
)

Variables

View Source
var (
	BARS = [...]rune{' ', '▁', '▂', '▃', '▄', '▅', '▆', '▇', '█'}

	SHADED_BLOCKS = [...]rune{' ', '░', '▒', '▓', '█'}

	IRREGULAR_BLOCKS = [...]rune{
		' ', '▘', '▝', '▀', '▖', '▌', '▞', '▛',
		'▗', '▚', '▐', '▜', '▄', '▙', '▟', '█',
	}

	BRAILLE_OFFSET = '\u2800'
	BRAILLE        = [4][2]rune{
		{'\u0001', '\u0008'},
		{'\u0002', '\u0010'},
		{'\u0004', '\u0020'},
		{'\u0040', '\u0080'},
	}

	DOUBLE_BRAILLE = map[[2]int]rune{
		[2]int{0, 0}: '⣀',
		[2]int{0, 1}: '⡠',
		[2]int{0, 2}: '⡐',
		[2]int{0, 3}: '⡈',

		[2]int{1, 0}: '⢄',
		[2]int{1, 1}: '⠤',
		[2]int{1, 2}: '⠔',
		[2]int{1, 3}: '⠌',

		[2]int{2, 0}: '⢂',
		[2]int{2, 1}: '⠢',
		[2]int{2, 2}: '⠒',
		[2]int{2, 3}: '⠊',

		[2]int{3, 0}: '⢁',
		[2]int{3, 1}: '⠡',
		[2]int{3, 2}: '⠑',
		[2]int{3, 3}: '⠉',
	}

	SINGLE_BRAILLE_LEFT  = [4]rune{'\u2840', '⠄', '⠂', '⠁'}
	SINGLE_BRAILLE_RIGHT = [4]rune{'\u2880', '⠠', '⠐', '⠈'}
)
View Source
var CellClear = Cell{
	Rune:  ' ',
	Style: StyleClear,
}
View Source
var Screen tcell.Screen
View Source
var StyleClear = Style{
	Fg:       ColorClear,
	Bg:       ColorClear,
	Modifier: ModifierClear,
}

StyleClear represents a default Style, with no colors or modifiers

View Source
var StyleParserColorMap = map[string]Color{
	"red":        ColorRed,
	"blue":       ColorBlue,
	"black":      ColorBlack,
	"cyan":       ColorCyan,
	"yellow":     ColorYellow,
	"white":      ColorWhite,
	"clear":      ColorClear,
	"green":      ColorGreen,
	"magenta":    ColorMagenta,
	"grey":       ColorGrey,
	"darkgrey":   ColorDarkGrey,
	"lightgrey":  ColorLightGrey,
	"silver":     ColorSilver,
	"orange":     ColorOrange,
	"purple":     ColorPurple,
	"pink":       ColorPink,
	"coral":      ColorCoral,
	"crimson":    ColorCrimson,
	"gold":       ColorGold,
	"teal":       ColorTeal,
	"turquoise":  ColorTurquoise,
	"indigo":     ColorIndigo,
	"violet":     ColorViolet,
	"olive":      ColorOlive,
	"navy":       ColorNavy,
	"aliceblue":  ColorAliceBlue,
	"beige":      ColorBeige,
	"brown":      ColorBrown,
	"darkblue":   ColorDarkBlue,
	"darkcyan":   ColorDarkCyan,
	"darkgreen":  ColorDarkGreen,
	"darkred":    ColorDarkRed,
	"hotpink":    ColorHotPink,
	"lightblue":  ColorLightBlue,
	"lightgreen": ColorLightGreen,
	"lime":       ColorLime,
	"maroon":     ColorMaroon,
	"mintcream":  ColorMintCream,
	"mistyrose":  ColorMistyRose,
	"orchid":     ColorOrchid,
	"plum":       ColorPlum,
	"salmon":     ColorSalmon,
	"seagreen":   ColorSeaGreen,
	"skyblue":    ColorSkyBlue,
	"slateblue":  ColorSlateBlue,
	"tan":        ColorTan,
	"tomato":     ColorTomato,
	"wheat":      ColorWheat,
}

StyleParserColorMap can be modified to add custom color parsing to text

View Source
var Theme = RootTheme{
	Default: NewStyle(ColorWhite),

	Block: BlockTheme{
		Title:  NewStyle(ColorWhite),
		Border: NewStyle(ColorWhite),
	},

	BarChart: BarChartTheme{
		Bars:   StandardColors,
		Nums:   StandardStyles,
		Labels: StandardStyles,
	},

	Paragraph: ParagraphTheme{
		Text: NewStyle(ColorWhite),
	},

	PieChart: PieChartTheme{
		Slices: StandardColors,
	},

	List: ListTheme{
		Text: NewStyle(ColorWhite),
	},

	Tree: TreeTheme{
		Text:      NewStyle(ColorWhite),
		Collapsed: COLLAPSED,
		Expanded:  EXPANDED,
	},

	StackedBarChart: StackedBarChartTheme{
		Bars:   StandardColors,
		Nums:   StandardStyles,
		Labels: StandardStyles,
	},

	Gauge: GaugeTheme{
		Bar:   ColorWhite,
		Label: NewStyle(ColorWhite),
	},

	Sparkline: SparklineTheme{
		Title: NewStyle(ColorWhite),
		Line:  ColorWhite,
	},

	Plot: PlotTheme{
		Lines: StandardColors,
		Axes:  ColorWhite,
	},

	Table: TableTheme{
		Text: NewStyle(ColorWhite),
	},

	Tab: TabTheme{
		Active:   NewStyle(ColorRed),
		Inactive: NewStyle(ColorWhite),
	},
}

Theme holds the default Styles and Colors for all widgets. You can set default widget Styles by modifying the Theme before creating the widgets.

Functions

func AbsInt

func AbsInt(x int) int

func CellsToString

func CellsToString(cells []Cell) string

func Clear

func Clear()

func Close

func Close()

Close closes tcell.

func FloorFloat64

func FloorFloat64(x float64) float64

func GetMaxFloat64From2dSlice

func GetMaxFloat64From2dSlice(slices [][]float64) (float64, error)

func GetMaxFloat64FromSlice

func GetMaxFloat64FromSlice(slice []float64) (float64, error)

func GetMaxIntFromSlice

func GetMaxIntFromSlice(slice []int) (int, error)

func Init

func Init() error

Init initializes tcell and is required to render anything. After initialization, the library must be finalized with `Close`.

func InterfaceSlice

func InterfaceSlice(slice interface{}) []interface{}

InterfaceSlice takes an []interface{} represented as an interface{} and converts it https://stackoverflow.com/questions/12753805/type-converting-slices-of-interfaces-in-go

func MaxFloat64

func MaxFloat64(x, y float64) float64

func MaxInt

func MaxInt(x, y int) int

func MinFloat64

func MinFloat64(x, y float64) float64

func MinInt

func MinInt(x, y int) int

func PollEvents

func PollEvents() <-chan Event

PollEvents gets events from tcell, converts them, then sends them to each of its channels.

func Render

func Render(items ...Drawable)

func ResolveBorderRune

func ResolveBorderRune(existing, newRune rune) rune

ResolveBorderRune merges an existing rune with a new one.

func RoundFloat64

func RoundFloat64(x float64) float64

func SplitCells

func SplitCells(cells []Cell, r rune) [][]Cell

func SumFloat64Slice

func SumFloat64Slice(data []float64) float64

func SumIntSlice

func SumIntSlice(slice []int) int

func TerminalDimensions

func TerminalDimensions() (int, int)

func TrimString

func TrimString(s string, w int) string

TrimString trims a string to a max length and adds '…' to the end if it was trimmed.

Types

type Alignment

type Alignment uint
const (
	AlignLeft Alignment = iota
	AlignCenter
	AlignRight
)
const (
	AlignTop    Alignment = 0
	AlignMiddle Alignment = 1
	AlignBottom Alignment = 2
)

type BarChartTheme

type BarChartTheme struct {
	Bars   []Color
	Nums   []Style
	Labels []Style
}

type Block

type Block struct {
	Border      bool
	BorderStyle Style

	BorderLeft, BorderRight, BorderTop, BorderBottom bool

	BorderCollapse bool
	BorderRounded  bool

	PaddingLeft, PaddingRight, PaddingTop, PaddingBottom int

	image.Rectangle
	Inner image.Rectangle

	Title                string
	TitleLeft            string
	TitleRight           string
	TitleStyle           Style
	TitleAlignment       Alignment
	TitleBottom          string
	TitleBottomLeft      string
	TitleBottomRight     string
	TitleBottomStyle     Style
	TitleBottomAlignment Alignment

	sync.Mutex
}

Block is the base struct inherited by most widgets. Block manages size, position, border, and title. It implements all 3 of the methods needed for the `Drawable` interface. Custom widgets will override the Draw method.

func NewBlock

func NewBlock() *Block

func (*Block) Draw

func (b *Block) Draw(buf *Buffer)

Draw implements the Drawable interface.

func (*Block) GetRect

func (b *Block) GetRect() image.Rectangle

GetRect implements the Drawable interface.

func (*Block) SetRect

func (b *Block) SetRect(x1, y1, x2, y2 int)

SetRect implements the Drawable interface.

type BlockTheme

type BlockTheme struct {
	Title  Style
	Border Style
}

type Buffer

type Buffer struct {
	image.Rectangle
	CellMap map[image.Point]Cell
}

Buffer represents a section of a terminal and is a renderable rectangle of cells.

func NewBuffer

func NewBuffer(r image.Rectangle) *Buffer

func (*Buffer) Fill

func (b *Buffer) Fill(c Cell, rect image.Rectangle)

func (*Buffer) GetCell

func (b *Buffer) GetCell(p image.Point) Cell

func (*Buffer) SetCell

func (b *Buffer) SetCell(c Cell, p image.Point)

func (*Buffer) SetString

func (b *Buffer) SetString(s string, style Style, p image.Point)

type Canvas

type Canvas struct {
	Block
	drawille.Canvas
}

func NewCanvas

func NewCanvas() *Canvas

func (*Canvas) Draw

func (c *Canvas) Draw(buf *Buffer)

func (*Canvas) SetLine

func (c *Canvas) SetLine(p0, p1 image.Point, color Color)

func (*Canvas) SetPoint

func (c *Canvas) SetPoint(p image.Point, color Color)

type Cell

type Cell struct {
	Rune  rune
	Style Style
}

Cell represents a viewable terminal cell

func NewCell

func NewCell(rune rune, args ...interface{}) Cell

NewCell takes 1 to 2 arguments 1st argument = rune 2nd argument = optional style

func ParseStyles

func ParseStyles(s string, defaultStyle Style) []Cell

ParseStyles parses a string for embedded Styles and returns []Cell with the correct styling. Uses defaultStyle for any text without an embedded style. Syntax is of the form [text](fg:<color>,mod:<attribute>,bg:<color>). Ordering does not matter. All fields are optional.

func RunesToStyledCells

func RunesToStyledCells(runes []rune, style Style) []Cell

func TrimCells

func TrimCells(cells []Cell, w int) []Cell

func WrapCells

func WrapCells(cells []Cell, width uint) []Cell

WrapCells takes []Cell and inserts Cells containing '\n' wherever a linebreak should go.

type CellWithX

type CellWithX struct {
	X    int
	Cell Cell
}

func BuildCellWithXArray

func BuildCellWithXArray(cells []Cell) []CellWithX

type Color

type Color = tcell.Color

Color is an integer from -1 to 255 -1 = ColorClear 0-255 = Xterm colors

const (
	// Standard Colors
	ColorBlack   Color = tcell.ColorBlack
	ColorRed     Color = tcell.ColorRed
	ColorGreen   Color = tcell.ColorGreen
	ColorYellow  Color = tcell.ColorYellow
	ColorBlue    Color = tcell.ColorBlue
	ColorMagenta Color = tcell.ColorDarkMagenta // Termui legacy mapping
	ColorCyan    Color = tcell.ColorLightCyan   // Termui legacy mapping
	ColorWhite   Color = tcell.ColorWhite

	// Extended Colors (Common)
	ColorGrey       Color = tcell.ColorGrey
	ColorDarkGrey   Color = tcell.ColorDarkGrey
	ColorLightGrey  Color = tcell.ColorLightGrey
	ColorSilver     Color = tcell.ColorSilver
	ColorOrange     Color = tcell.ColorOrange
	ColorPurple     Color = tcell.ColorPurple
	ColorPink       Color = tcell.ColorPink
	ColorCoral      Color = tcell.ColorCoral
	ColorCrimson    Color = tcell.ColorCrimson
	ColorGold       Color = tcell.ColorGold
	ColorTeal       Color = tcell.ColorTeal
	ColorTurquoise  Color = tcell.ColorTurquoise
	ColorIndigo     Color = tcell.ColorIndigo
	ColorViolet     Color = tcell.ColorViolet
	ColorOlive      Color = tcell.ColorOlive
	ColorNavy       Color = tcell.ColorNavy
	ColorAliceBlue  Color = tcell.ColorAliceBlue
	ColorBeige      Color = tcell.ColorBeige
	ColorBrown      Color = tcell.ColorBrown
	ColorDarkBlue   Color = tcell.ColorDarkBlue
	ColorDarkCyan   Color = tcell.ColorDarkCyan
	ColorDarkGreen  Color = tcell.ColorDarkGreen
	ColorDarkRed    Color = tcell.ColorDarkRed
	ColorHotPink    Color = tcell.ColorHotPink
	ColorLightBlue  Color = tcell.ColorLightBlue
	ColorLightGreen Color = tcell.ColorLightGreen
	ColorLime       Color = tcell.ColorLime
	ColorMaroon     Color = tcell.ColorMaroon
	ColorMintCream  Color = tcell.ColorMintCream
	ColorMistyRose  Color = tcell.ColorMistyRose
	ColorOrchid     Color = tcell.ColorOrchid
	ColorPlum       Color = tcell.ColorPlum
	ColorSalmon     Color = tcell.ColorSalmon
	ColorSeaGreen   Color = tcell.ColorSeaGreen
	ColorSkyBlue    Color = tcell.ColorSkyblue
	ColorSlateBlue  Color = tcell.ColorSlateBlue
	ColorTan        Color = tcell.ColorTan
	ColorTomato     Color = tcell.ColorTomato
	ColorWheat      Color = tcell.ColorWheat
)

Basic terminal colors

const ColorClear Color = tcell.ColorDefault

ColorClear clears the Fg or Bg color of a Style

func NewColorRGB

func NewColorRGB(r, g, b int32) Color

NewColorRGB returns a new Color with the given RGB values

func NewRGBColor

func NewRGBColor(r, g, b int32) Color

NewRGBColor is a convenience alias for NewColorRGB

func SelectColor

func SelectColor(colors []Color, index int) Color

type Drawable

type Drawable interface {
	GetRect() image.Rectangle
	SetRect(int, int, int, int)
	Draw(*Buffer)
	sync.Locker
}

type Event

type Event struct {
	Type    EventType
	ID      string
	Payload interface{}
}

type EventType

type EventType uint
const (
	KeyboardEvent EventType = iota
	MouseEvent
	ResizeEvent
)

type GaugeTheme

type GaugeTheme struct {
	Bar   Color
	Label Style
}

type Grid

type Grid struct {
	Block
	Items []*GridItem
}

func NewGrid

func NewGrid() *Grid

func (*Grid) Draw

func (g *Grid) Draw(buf *Buffer)

func (*Grid) Set

func (g *Grid) Set(entries ...interface{})

Set is used to add Columns and Rows to the grid. It recursively searches the GridItems, adding leaves to the grid and calculating the dimensions of the leaves.

type GridItem

type GridItem struct {
	Type        gridItemType
	XRatio      float64
	YRatio      float64
	WidthRatio  float64
	HeightRatio float64
	Entry       interface{} // Entry.type == GridBufferer if IsLeaf else []GridItem
	IsLeaf      bool
	// contains filtered or unexported fields
}

GridItem represents either a Row or Column in a grid. Holds sizing information and either an []GridItems or a widget.

func NewCol

func NewCol(ratio float64, i ...interface{}) GridItem

NewCol takes a height percentage and either a widget or a Row or Column

func NewRow

func NewRow(ratio float64, i ...interface{}) GridItem

NewRow takes a width percentage and either a widget or a Row or Column

type ListTheme

type ListTheme struct {
	Text Style
}

type Modifier

type Modifier = tcell.AttrMask
const (
	// ModifierClear clears any modifiers
	ModifierClear     Modifier = 0
	ModifierBold      Modifier = tcell.AttrBold
	ModifierUnderline Modifier = tcell.AttrUnderline
	ModifierReverse   Modifier = tcell.AttrReverse
)

type Mouse

type Mouse struct {
	Drag bool
	X    int
	Y    int
}

Mouse payload.

type ParagraphTheme

type ParagraphTheme struct {
	Text Style
}

type PieChartTheme

type PieChartTheme struct {
	Slices []Color
}

type PlotTheme

type PlotTheme struct {
	Lines []Color
	Axes  Color
}

type Resize

type Resize struct {
	Width  int
	Height int
}

Resize payload.

type RootTheme

type RootTheme struct {
	Default Style

	Block BlockTheme

	BarChart        BarChartTheme
	Gauge           GaugeTheme
	Plot            PlotTheme
	List            ListTheme
	Tree            TreeTheme
	Paragraph       ParagraphTheme
	PieChart        PieChartTheme
	Sparkline       SparklineTheme
	StackedBarChart StackedBarChartTheme
	Tab             TabTheme
	Table           TableTheme
}

type SparklineTheme

type SparklineTheme struct {
	Title Style
	Line  Color
}

type StackedBarChartTheme

type StackedBarChartTheme struct {
	Bars   []Color
	Nums   []Style
	Labels []Style
}

type Style

type Style struct {
	Fg       Color
	Bg       Color
	Modifier Modifier
}

Style represents the style of one terminal cell

func NewStyle

func NewStyle(fg Color, args ...interface{}) Style

NewStyle takes 1 to 3 arguments 1st argument = Fg 2nd argument = optional Bg 3rd argument = optional Modifier

func SelectStyle

func SelectStyle(styles []Style, index int) Style

type TabTheme

type TabTheme struct {
	Active   Style
	Inactive Style
}

type TableTheme

type TableTheme struct {
	Text Style
}

type TreeTheme

type TreeTheme struct {
	Text      Style
	Collapsed rune
	Expanded  rune
}

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL