gocui

package module
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Feb 2, 2023 License: BSD-3-Clause Imports: 20 Imported by: 0

README

GOCUI - Go Console User Interface

CircleCI CodeCov Go Report Card GolangCI GoDoc GitHub tag (latest SemVer)

Minimalist Go package aimed at creating Console User Interfaces. A community fork based on the amazing work of jroimartin

Features

  • Minimalist API.
  • Views (the "windows" in the GUI) implement the interface io.ReadWriter.
  • Support for overlapping views.
  • The GUI can be modified at runtime (concurrent-safe).
  • Global and view-level keybindings.
  • Mouse support.
  • Colored text.
  • Customizable editing mode.
  • Easy to build reusable widgets, complex layouts...

About fork

This fork has many improvements over the original work from jroimartin.

  • Written ontop of TCell
  • Better wide character support
  • Support for 1 Line height views
  • Better support for running in docker container
  • Customize frame colors
  • Improved code comments and quality
  • Many small improvements
  • Change Visibility of views

For information about this org see: awesome-gocui/about.

Installation

Execute:

$ go get github.com/awesome-gocui/gocui

Documentation

Execute:

$ go doc github.com/awesome-gocui/gocui

Or visit godoc.org to read it online.

Example

See the _example folder for more examples

package main

import (
	"fmt"
	"log"

	"github.com/awesome-gocui/gocui"
)

func main() {
	g, err := gocui.NewGui(gocui.OutputNormal, true)
	if err != nil {
		log.Panicln(err)
	}
	defer g.Close()

	g.SetManagerFunc(layout)

	if err := g.SetKeybinding("", gocui.KeyCtrlC, gocui.ModNone, quit); err != nil {
		log.Panicln(err)
	}

	if err := g.MainLoop(); err != nil && !gocui.IsQuit(err) {
		log.Panicln(err)
	}
}

func layout(g *gocui.Gui) error {
	maxX, maxY := g.Size()
	if v, err := g.SetView("hello", maxX/2-7, maxY/2, maxX/2+7, maxY/2+2, 0); err != nil {
		if !gocui.IsUnknownView(err) {
			return err
		}

		if _, err := g.SetCurrentView("hello"); err != nil {
			return err
		}

		fmt.Fprintln(v, "Hello world!")
	}

	return nil
}

func quit(g *gocui.Gui, v *gocui.View) error {
	return gocui.ErrQuit
}

Screenshots

r2cui

_examples/demo.go

_examples/dynamic.go

Projects using gocui

  • komanda-cli: IRC Client For Developers.
  • vuls: Agentless vulnerability scanner for Linux/FreeBSD.
  • wuzz: Interactive cli tool for HTTP inspection.
  • httplab: Interactive web server.
  • domainr: Tool that checks the availability of domains based on keywords.
  • gotime: Time tracker for projects and tasks.
  • claws: Interactive command line client for testing websockets.
  • terminews: Terminal based RSS reader.
  • diagram: Tool to convert ascii arts into hand drawn diagrams.
  • pody: CLI app to manage Pods in a Kubernetes cluster.
  • kubexp: Kubernetes client.
  • kcli: Tool for inspecting kafka topics/partitions/messages.
  • fac: git merge conflict resolver
  • jsonui: Interactive JSON explorer for your terminal.
  • cointop: Interactive terminal based UI application for tracking cryptocurrencies.
  • lazygit: simple terminal UI for git commands.
  • lazydocker: The lazier way to manage everything docker.

Note: if your project is not listed here, let us know! :)

Documentation

Overview

Package gocui allows to create console user interfaces.

Create a new GUI:

g, err := gocui.NewGui(gocui.OutputNormal, false)
if err != nil {
	// handle error
}
defer g.Close()

// Set GUI managers and key bindings
// ...

if err := g.MainLoop(); err != nil && !gocui.IsQuit(err) {
	// handle error
}

Set GUI managers:

g.SetManager(mgr1, mgr2)

Managers are in charge of GUI's layout and can be used to build widgets. On each iteration of the GUI's main loop, the Layout function of each configured manager is executed. Managers are used to set-up and update the application's main views, being possible to freely change them during execution. Also, it is important to mention that a main loop iteration is executed on each reported event (key-press, mouse event, window resize, etc).

GUIs are composed by Views, you can think of it as buffers. Views implement the io.ReadWriter interface, so you can just write to them if you want to modify their content. The same is valid for reading.

Create and initialize a view with absolute coordinates:

if v, err := g.SetView("viewname", 2, 2, 22, 7, 0); err != nil {
	if !gocui.IsUnknownView(err) {
		// handle error
	}
	fmt.Fprintln(v, "This is a new view")
	// ...
}

Views can also be created using relative coordinates:

maxX, maxY := g.Size()
if v, err := g.SetView("viewname", maxX/2-30, maxY/2, maxX/2+30, maxY/2+2, 0); err != nil {
	// ...
}

Configure keybindings:

if err := g.SetKeybinding("viewname", gocui.KeyEnter, gocui.ModNone, fcn); err != nil {
	// handle error
}

gocui implements full mouse support that can be enabled with:

g.Mouse = true

Mouse events are handled like any other keybinding:

if err := g.SetKeybinding("viewname", gocui.MouseLeft, gocui.ModNone, fcn); err != nil {
	// handle error
}

IMPORTANT: Views can only be created, destroyed or updated in three ways: from the Layout function within managers, from keybinding callbacks or via *Gui.Update(). The reason for this is that it allows gocui to be concurrent-safe. So, if you want to update your GUI from a goroutine, you must use *Gui.Update(). For example:

g.Update(func(g *gocui.Gui) error {
	v, err := g.View("viewname")
	if err != nil {
		// handle error
	}
	v.Clear()
	fmt.Fprintln(v, "Writing from different goroutines")
	return nil
})

By default, gocui provides a basic editing mode. This mode can be extended and customized creating a new Editor and assigning it to *View.Editor:

type Editor interface {
	Edit(v *View, key Key, ch rune, mod Modifier)
}

DefaultEditor can be taken as example to create your own custom Editor:

var DefaultEditor Editor = EditorFunc(simpleEditor)

func simpleEditor(v *View, key Key, ch rune, mod Modifier) {
	switch {
	case ch != 0 && mod == 0:
		v.EditWrite(ch)
	case key == KeySpace:
		v.EditWrite(' ')
	case key == KeyBackspace || key == KeyBackspace2:
		v.EditDelete(true)
	// ...
	}
}

Colored text:

Views allow to add colored text using ANSI colors. For example:

fmt.Fprintln(v, "\x1b[0;31mHello world")

For more information, see the examples in folder "_examples/".

Index

Constants

View Source
const (
	// ColorDefault is used to leave the Color unchanged from whatever system or teminal default may exist.
	ColorDefault = Attribute(tcell.ColorDefault)

	// AttrIsValidColor is used to indicate the color value is actually
	// valid (initialized).  This is useful to permit the zero value
	// to be treated as the default.
	AttrIsValidColor = Attribute(tcell.ColorValid)

	// AttrIsRGBColor is used to indicate that the Attribute value is RGB value of color.
	// The lower order 3 bytes are RGB.
	// (It's not a color in basic ANSI range 256).
	AttrIsRGBColor = Attribute(tcell.ColorIsRGB)

	// AttrColorBits is a mask where color is located in Attribute
	AttrColorBits = 0xffffffffff // roughly 5 bytes, tcell uses 4 bytes and half-byte as a special flags for color (rest is reserved for future)

	// AttrStyleBits is a mask where character attributes (e.g.: bold, italic, underline) are located in Attribute
	AttrStyleBits = 0xffffff0000000000 // remaining 3 bytes in the 8 bytes Attribute (tcell is not using it, so we should be fine)
)
View Source
const (
	KeyF1         Key = Key(tcell.KeyF1)
	KeyF2             = Key(tcell.KeyF2)
	KeyF3             = Key(tcell.KeyF3)
	KeyF4             = Key(tcell.KeyF4)
	KeyF5             = Key(tcell.KeyF5)
	KeyF6             = Key(tcell.KeyF6)
	KeyF7             = Key(tcell.KeyF7)
	KeyF8             = Key(tcell.KeyF8)
	KeyF9             = Key(tcell.KeyF9)
	KeyF10            = Key(tcell.KeyF10)
	KeyF11            = Key(tcell.KeyF11)
	KeyF12            = Key(tcell.KeyF12)
	KeyInsert         = Key(tcell.KeyInsert)
	KeyDelete         = Key(tcell.KeyDelete)
	KeyHome           = Key(tcell.KeyHome)
	KeyEnd            = Key(tcell.KeyEnd)
	KeyPgdn           = Key(tcell.KeyPgDn)
	KeyPgup           = Key(tcell.KeyPgUp)
	KeyArrowUp        = Key(tcell.KeyUp)
	KeyArrowDown      = Key(tcell.KeyDown)
	KeyArrowLeft      = Key(tcell.KeyLeft)
	KeyArrowRight     = Key(tcell.KeyRight)
)

Special keys.

View Source
const (
	KeyCtrlTilde      = Key(tcell.KeyF64) // arbitrary assignment
	KeyCtrlSpace      = Key(tcell.KeyCtrlSpace)
	KeyCtrlA          = Key(tcell.KeyCtrlA)
	KeyCtrlB          = Key(tcell.KeyCtrlB)
	KeyCtrlC          = Key(tcell.KeyCtrlC)
	KeyCtrlD          = Key(tcell.KeyCtrlD)
	KeyCtrlE          = Key(tcell.KeyCtrlE)
	KeyCtrlF          = Key(tcell.KeyCtrlF)
	KeyCtrlG          = Key(tcell.KeyCtrlG)
	KeyBackspace      = Key(tcell.KeyBackspace)
	KeyCtrlH          = Key(tcell.KeyCtrlH)
	KeyTab            = Key(tcell.KeyTab)
	KeyBacktab        = Key(tcell.KeyBacktab)
	KeyCtrlI          = Key(tcell.KeyCtrlI)
	KeyCtrlJ          = Key(tcell.KeyCtrlJ)
	KeyCtrlK          = Key(tcell.KeyCtrlK)
	KeyCtrlL          = Key(tcell.KeyCtrlL)
	KeyLF             = Key(tcell.KeyLF)
	KeyEnter          = Key(tcell.KeyEnter)
	KeyCtrlM          = Key(tcell.KeyCtrlM)
	KeyCtrlN          = Key(tcell.KeyCtrlN)
	KeyCtrlO          = Key(tcell.KeyCtrlO)
	KeyCtrlP          = Key(tcell.KeyCtrlP)
	KeyCtrlQ          = Key(tcell.KeyCtrlQ)
	KeyCtrlR          = Key(tcell.KeyCtrlR)
	KeyCtrlS          = Key(tcell.KeyCtrlS)
	KeyCtrlT          = Key(tcell.KeyCtrlT)
	KeyCtrlU          = Key(tcell.KeyCtrlU)
	KeyCtrlV          = Key(tcell.KeyCtrlV)
	KeyCtrlW          = Key(tcell.KeyCtrlW)
	KeyCtrlX          = Key(tcell.KeyCtrlX)
	KeyCtrlY          = Key(tcell.KeyCtrlY)
	KeyCtrlZ          = Key(tcell.KeyCtrlZ)
	KeyEsc            = Key(tcell.KeyEscape)
	KeyCtrlUnderscore = Key(tcell.KeyCtrlUnderscore)
	KeySpace          = Key(32)
	KeyBackspace2     = Key(tcell.KeyBackspace2)
	KeyCtrl8          = Key(tcell.KeyBackspace2) // same key as in termbox-go

	KeyAltEnter       = Key(tcell.KeyF64) // arbitrary assignments
	MouseLeft         = Key(tcell.KeyF63)
	MouseRight        = Key(tcell.KeyF62)
	MouseMiddle       = Key(tcell.KeyF61)
	MouseRelease      = Key(tcell.KeyF60)
	MouseWheelUp      = Key(tcell.KeyF59)
	MouseWheelDown    = Key(tcell.KeyF58)
	MouseWheelLeft    = Key(tcell.KeyF57)
	MouseWheelRight   = Key(tcell.KeyF56)
	KeyCtrl2          = Key(tcell.KeyNUL) // termbox defines theses
	KeyCtrl3          = Key(tcell.KeyEscape)
	KeyCtrl4          = Key(tcell.KeyCtrlBackslash)
	KeyCtrl5          = Key(tcell.KeyCtrlRightSq)
	KeyCtrl6          = Key(tcell.KeyCtrlCarat)
	KeyCtrl7          = Key(tcell.KeyCtrlUnderscore)
	KeyCtrlSlash      = Key(tcell.KeyCtrlUnderscore)
	KeyCtrlRsqBracket = Key(tcell.KeyCtrlRightSq)
	KeyCtrlBackslash  = Key(tcell.KeyCtrlBackslash)
	KeyCtrlLsqBracket = Key(tcell.KeyCtrlLeftSq)
)

Keys combinations.

View Source
const (
	ModNone   Modifier = Modifier(0)
	ModAlt             = Modifier(tcell.ModAlt)
	ModMotion          = Modifier(2) // just picking an arbitrary number here that doesn't clash with tcell.ModAlt

)

Modifiers.

View Source
const (
	NOT_DRAGGING int = iota
	MAYBE_DRAGGING
	DRAGGING
)
View Source
const (
	WHITESPACES     = " \t"
	WORD_SEPARATORS = "*?_+-.[]~=/&;!#$%^(){}<>"
)
View Source
const (
	TOP    = 1 // view is overlapping at top edge
	BOTTOM = 2 // view is overlapping at bottom edge
	LEFT   = 4 // view is overlapping at left edge
	RIGHT  = 8 // view is overlapping at right edge
)

Constants for overlapping edges

AttrAll represents all the text effect attributes turned on

Variables

View Source
var (
	// ErrAlreadyBlacklisted is returned when the keybinding is already blacklisted.
	ErrAlreadyBlacklisted = standardErrors.New("keybind already blacklisted")

	// ErrBlacklisted is returned when the keybinding being parsed / used is blacklisted.
	ErrBlacklisted = standardErrors.New("keybind blacklisted")

	// ErrNotBlacklisted is returned when a keybinding being whitelisted is not blacklisted.
	ErrNotBlacklisted = standardErrors.New("keybind not blacklisted")

	// ErrNoSuchKeybind is returned when the keybinding being parsed does not exist.
	ErrNoSuchKeybind = standardErrors.New("no such keybind")

	// ErrUnknownView allows to assert if a View must be initialized.
	ErrUnknownView = standardErrors.New("unknown view")

	// ErrQuit is used to decide if the MainLoop finished successfully.
	ErrQuit = standardErrors.New("quit")
)
View Source
var ErrInvalidPoint = errors.New("invalid point")

ErrInvalidPoint is returned when client passed invalid coordinates of a cell. Most likely client has passed negative coordinates of a cell.

View Source
var Screen tcell.Screen

We probably don't want this being a global variable for YOLO for now

Functions

func IsMouseKey

func IsMouseKey(key interface{}) bool

func IsQuit

func IsQuit(err error) bool

IsQuit reports whether the contents of an error is "quit".

func IsUnknownView

func IsUnknownView(err error) bool

IsUnknownView reports whether the contents of an error is "unknown view".

func Loader

func Loader() cell

Loader can show a loading animation

func MustParseAll

func MustParseAll(input []string) map[interface{}]Modifier

MustParseAll takes an array of strings and returns a map of all keybindings. It will panic if any error occured.

func ParseAll

func ParseAll(input []string) (map[interface{}]Modifier, error)

ParseAll takes an array of strings and returns a map of all keybindings.

func SimpleEditor

func SimpleEditor(v *View, key Key, ch rune, mod Modifier) bool

SimpleEditor is used as the default gocui editor.

Types

type Attribute

type Attribute uint64

Attribute affects the presentation of characters, such as color, boldness, etc.

const (
	ColorBlack Attribute = AttrIsValidColor + iota
	ColorRed
	ColorGreen
	ColorYellow
	ColorBlue
	ColorMagenta
	ColorCyan
	ColorWhite
)

Color attributes. These colors are compatible with tcell.Color type and can be expanded like:

g.FgColor := gocui.Attribute(tcell.ColorLime)
const (
	AttrBold Attribute = 1 << (40 + iota)
	AttrBlink
	AttrReverse
	AttrUnderline
	AttrDim
	AttrItalic
	AttrStrikeThrough
	AttrNone Attribute = 0 // Just normal text.
)

Attributes are not colors, but effects (e.g.: bold, dim) which affect the display of text. They can be combined.

func Get256Color

func Get256Color(color int32) Attribute

Get256Color creates Attribute which stores ANSI color (0-255)

func GetColor

func GetColor(color string) Attribute

GetColor creates a Color from a color name (W3C name). A hex value may be supplied as a string in the format "#ffffff".

func GetRGBColor

func GetRGBColor(color int32) Attribute

GetRGBColor creates Attribute which stores RGB color. Color is passed as 24bit RGB value, where R << 16 | G << 8 | B

func NewRGBColor

func NewRGBColor(r, g, b int32) Attribute

NewRGBColor creates Attribute which stores RGB color.

func (Attribute) Hex

func (a Attribute) Hex() int32

Hex returns the color's hexadecimal RGB 24-bit value with each component consisting of a single byte, ala R << 16 | G << 8 | B. If the color is unknown or unset, -1 is returned.

This function produce the same output as `tcell.Hex()` with additional support for `termbox-go` colors (to 256).

func (Attribute) IsValidColor

func (a Attribute) IsValidColor() bool

IsValidColor indicates if the Attribute is a valid color value (has been set).

func (Attribute) RGB

func (a Attribute) RGB() (int32, int32, int32)

RGB returns the red, green, and blue components of the color, with each component represented as a value 0-255. If the color is unknown or unset, -1 is returned for each component.

This function produce the same output as `tcell.RGB()` with additional support for `termbox-go` colors (to 256).

type Editor

type Editor interface {
	Edit(v *View, key Key, ch rune, mod Modifier) bool
}

Editor interface must be satisfied by gocui editors.

var DefaultEditor Editor = EditorFunc(SimpleEditor)

DefaultEditor is the default editor.

type EditorFunc

type EditorFunc func(v *View, key Key, ch rune, mod Modifier) bool

The EditorFunc type is an adapter to allow the use of ordinary functions as Editors. If f is a function with the appropriate signature, EditorFunc(f) is an Editor object that calls f.

func (EditorFunc) Edit

func (f EditorFunc) Edit(v *View, key Key, ch rune, mod Modifier) bool

Edit calls f(v, key, ch, mod)

type GocuiEvent

type GocuiEvent struct {
	Type   gocuiEventType
	Mod    Modifier
	Key    Key
	Ch     rune
	Width  int
	Height int
	Err    error
	MouseX int
	MouseY int
	N      int
}

GocuiEvent represents events like a keys, mouse actions, or window resize.

The 'Mod', 'Key' and 'Ch' fields are valid if 'Type' is 'eventKey'.
The 'MouseX' and 'MouseY' fields are valid if 'Type' is 'eventMouse'.
The 'Width' and 'Height' fields are valid if 'Type' is 'eventResize'.
The 'Err' field is valid if 'Type' is 'eventError'.

type Gui

type Gui struct {
	RecordingConfig
	Recording *Recording
	// ReplayedEvents is for passing pre-recorded input events, for the purposes of testing
	ReplayedEvents replayedEvents
	PlayMode       PlayMode
	StartTime      time.Time

	// BgColor and FgColor allow to configure the background and foreground
	// colors of the GUI.
	BgColor, FgColor, FrameColor Attribute

	// SelBgColor and SelFgColor allow to configure the background and
	// foreground colors of the frame of the current view.
	SelBgColor, SelFgColor, SelFrameColor Attribute

	// If Highlight is true, Sel{Bg,Fg}Colors will be used to draw the
	// frame of the current view.
	Highlight bool

	// If ShowListFooter is true then show list footer (i.e. the part that says we're at item 5 out of 10)
	ShowListFooter bool

	// If Cursor is true then the cursor is enabled.
	Cursor bool

	// If Mouse is true then mouse events will be enabled.
	Mouse bool

	// If InputEsc is true, when ESC sequence is in the buffer and it doesn't
	// match any known sequence, ESC means KeyEsc.
	InputEsc bool

	// SupportOverlaps is true when we allow for view edges to overlap with other
	// view edges
	SupportOverlaps bool

	Mutexes GuiMutexes

	OnSearchEscape func() error
	// these keys must either be of type Key of rune
	SearchEscapeKey    interface{}
	NextSearchMatchKey interface{}
	PrevSearchMatchKey interface{}
	// contains filtered or unexported fields
}

Gui represents the whole User Interface, including the views, layouts and keybindings.

func NewGui

func NewGui(mode OutputMode, supportOverlaps bool, playMode PlayMode, headless bool, runeReplacements map[rune]string) (*Gui, error)

NewGui returns a new Gui object with a given output mode.

func (*Gui) BlacklistKeybinding

func (g *Gui) BlacklistKeybinding(k Key) error

BlackListKeybinding adds a keybinding to the blacklist

func (*Gui) Close

func (g *Gui) Close()

Close finalizes the library. It should be called after a successful initialization and when gocui is not needed anymore.

func (*Gui) CopyContent

func (g *Gui) CopyContent(fromView *View, toView *View)

replaces the content in toView with the content in fromView

func (*Gui) CurrentView

func (g *Gui) CurrentView() *View

CurrentView returns the currently focused view, or nil if no view owns the focus.

func (*Gui) DeleteAllKeybindings

func (g *Gui) DeleteAllKeybindings()

DeleteKeybindings deletes all keybindings of view.

func (*Gui) DeleteKeybinding

func (g *Gui) DeleteKeybinding(viewname string, key interface{}, mod Modifier) error

DeleteKeybinding deletes a keybinding.

func (*Gui) DeleteView

func (g *Gui) DeleteView(name string) error

DeleteView deletes a view by name.

func (*Gui) DeleteViewKeybindings

func (g *Gui) DeleteViewKeybindings(viewname string)

DeleteKeybindings deletes all keybindings of view.

func (*Gui) MainLoop

func (g *Gui) MainLoop() error

MainLoop runs the main loop until an error is returned. A successful finish should return ErrQuit.

func (*Gui) Resume

func (g *Gui) Resume() error

func (*Gui) Rune

func (g *Gui) Rune(x, y int) (rune, error)

Rune returns the rune contained in the cell at the given position. It checks if the position is valid.

func (*Gui) SetCurrentView

func (g *Gui) SetCurrentView(name string) (*View, error)

SetCurrentView gives the focus to a given view.

func (*Gui) SetKeybinding

func (g *Gui) SetKeybinding(viewname string, key interface{}, mod Modifier, handler func(*Gui, *View) error) error

SetKeybinding creates a new keybinding. If viewname equals to "" (empty string) then the keybinding will apply to all views. key must be a rune or a Key.

When mouse keys are used (MouseLeft, MouseRight, ...), modifier might not work correctly. It behaves differently on different platforms. Somewhere it doesn't register Alt key press, on others it might report Ctrl as Alt. It's not consistent and therefore it's not recommended to use with mouse keys.

func (*Gui) SetManager

func (g *Gui) SetManager(managers ...Manager)

SetManager sets the given GUI managers. It deletes all views and keybindings.

func (*Gui) SetManagerFunc

func (g *Gui) SetManagerFunc(manager func(*Gui) error)

SetManagerFunc sets the given manager function. It deletes all views and keybindings.

func (*Gui) SetRune

func (g *Gui) SetRune(v *View, x, y int, ch rune, fgColor, bgColor Attribute) error

SetRune writes a rune at the given point, relative to the top-left corner of the terminal. It checks if the position is valid and applies the given colors.

func (*Gui) SetTabClickBinding

func (g *Gui) SetTabClickBinding(viewName string, handler tabClickHandler) error

SetTabClickBinding sets a binding for a tab click event

func (*Gui) SetView

func (g *Gui) SetView(name string, x0, y0, x1, y1 int, overlaps byte) (*View, error)

SetView creates a new view with its top-left corner at (x0, y0) and the bottom-right one at (x1, y1). If a view with the same name already exists, its dimensions are updated; otherwise, the error ErrUnknownView is returned, which allows to assert if the View must be initialized. It checks if the position is valid.

func (*Gui) SetViewBeneath

func (g *Gui) SetViewBeneath(name string, aboveViewName string, height int) (*View, error)

SetViewBeneath sets a view stacked beneath another view

func (*Gui) SetViewClickBinding

func (g *Gui) SetViewClickBinding(binding *ViewMouseBinding) error

func (*Gui) SetViewOnBottom

func (g *Gui) SetViewOnBottom(name string) (*View, error)

SetViewOnBottom sets the given view on bottom of the existing ones.

func (*Gui) SetViewOnTop

func (g *Gui) SetViewOnTop(name string) (*View, error)

SetViewOnTop sets the given view on top of the existing ones.

func (*Gui) SetViewOnTopOf

func (g *Gui) SetViewOnTopOf(toMove string, other string) error

func (*Gui) Size

func (g *Gui) Size() (x, y int)

Size returns the terminal's size.

func (*Gui) StartTicking

func (g *Gui) StartTicking(ctx context.Context)

func (*Gui) Suspend

func (g *Gui) Suspend() error

func (*Gui) Update

func (g *Gui) Update(f func(*Gui) error)

Update executes the passed function. This method can be called safely from a goroutine in order to update the GUI. It is important to note that the passed function won't be executed immediately, instead it will be added to the user events queue. Given that Update spawns a goroutine, the order in which the user events will be handled is not guaranteed.

func (*Gui) UpdateAsync

func (g *Gui) UpdateAsync(f func(*Gui) error)

UpdateAsync is a version of Update that does not spawn a go routine, it can be a bit more efficient in cases where Update is called many times like when tailing a file. In general you should use Update()

func (*Gui) View

func (g *Gui) View(name string) (*View, error)

View returns a pointer to the view with the given name, or error ErrUnknownView if a view with that name does not exist.

func (*Gui) ViewPosition

func (g *Gui) ViewPosition(name string) (x0, y0, x1, y1 int, err error)

ViewPosition returns the coordinates of the view with the given name, or error ErrUnknownView if a view with that name does not exist.

func (*Gui) Views

func (g *Gui) Views() []*View

Views returns all the views in the GUI.

func (*Gui) VisibleViewByPosition

func (g *Gui) VisibleViewByPosition(x, y int) (*View, error)

VisibleViewByPosition returns a pointer to a view matching the given position, or error ErrUnknownView if a view in that position does not exist.

func (*Gui) WhitelistKeybinding

func (g *Gui) WhitelistKeybinding(k Key) error

WhiteListKeybinding removes a keybinding from the blacklist

type GuiMutexes

type GuiMutexes struct {
	ViewsMutex sync.Mutex
	// contains filtered or unexported fields
}

type Key

type Key tcell.Key

Key represents special keys or keys combinations.

type Manager

type Manager interface {
	// Layout is called every time the GUI is redrawn, it must contain the
	// base views and its initializations.
	Layout(*Gui) error
}

A Manager is in charge of GUI's layout and can be used to build widgets.

type ManagerFunc

type ManagerFunc func(*Gui) error

The ManagerFunc type is an adapter to allow the use of ordinary functions as Managers. If f is a function with the appropriate signature, ManagerFunc(f) is an Manager object that calls f.

func (ManagerFunc) Layout

func (f ManagerFunc) Layout(g *Gui) error

Layout calls f(g)

type Modifier

type Modifier tcell.ModMask

Modifier allows to define special keys combinations. They can be used in combination with Keys or Runes when a new keybinding is defined.

func MustParse

func MustParse(input string) (interface{}, Modifier)

MustParse takes the input string and returns a Key / rune and a Modifier. It will panic if any error occured.

func Parse

func Parse(input string) (interface{}, Modifier, error)

Parse takes the input string and extracts the keybinding. Returns a Key / rune, a Modifier and an error.

type OutputMode

type OutputMode int

OutputMode represents an output mode, which determines how colors are used.

const (
	// OutputNormal provides 8-colors terminal mode.
	OutputNormal OutputMode = iota

	// Output256 provides 256-colors terminal mode.
	Output256

	// Output216 provides 216 ansi color terminal mode.
	Output216

	// OutputGrayscale provides greyscale terminal mode.
	OutputGrayscale

	// OutputTrue provides 24bit color terminal mode.
	// This mode is recommended even if your terminal doesn't support
	// such mode. The colors are represented exactly as you
	// write them (no clamping or truncating). `tcell` should take care
	// of what your terminal can do.
	OutputTrue
)

type PlayMode

type PlayMode int
const (
	NORMAL PlayMode = iota
	RECORDING
	REPLAYING
	// for the new form of integration tests
	REPLAYING_NEW
)

type Recording

type Recording struct {
	KeyEvents    []*TcellKeyEventWrapper
	ResizeEvents []*TcellResizeEventWrapper
}

type RecordingConfig

type RecordingConfig struct {
	Speed  float64
	Leeway int
}

type TcellKeyEventWrapper

type TcellKeyEventWrapper struct {
	Timestamp int64
	Mod       tcell.ModMask
	Key       tcell.Key
	Ch        rune
}

this wrapper struct has public keys so we can easily serialize/deserialize to JSON

func NewTcellKeyEventWrapper

func NewTcellKeyEventWrapper(event *tcell.EventKey, timestamp int64) *TcellKeyEventWrapper

type TcellResizeEventWrapper

type TcellResizeEventWrapper struct {
	Timestamp int64
	Width     int
	Height    int
}

func NewTcellResizeEventWrapper

func NewTcellResizeEventWrapper(event *tcell.EventResize, timestamp int64) *TcellResizeEventWrapper

type TextArea

type TextArea struct {
	// contains filtered or unexported fields
}

func (*TextArea) BackSpaceChar

func (self *TextArea) BackSpaceChar()

func (*TextArea) BackSpaceWord

func (self *TextArea) BackSpaceWord()

func (*TextArea) Clear

func (self *TextArea) Clear()

func (*TextArea) DeleteChar

func (self *TextArea) DeleteChar()

func (*TextArea) DeleteToEndOfLine

func (self *TextArea) DeleteToEndOfLine()

func (*TextArea) DeleteToStartOfLine

func (self *TextArea) DeleteToStartOfLine()

func (*TextArea) GetContent

func (self *TextArea) GetContent() string

func (*TextArea) GetCursorXY

func (self *TextArea) GetCursorXY() (int, int)

func (*TextArea) GoToEndOfLine

func (self *TextArea) GoToEndOfLine()

func (*TextArea) GoToStartOfLine

func (self *TextArea) GoToStartOfLine()

func (*TextArea) MoveCursorDown

func (self *TextArea) MoveCursorDown()

func (*TextArea) MoveCursorLeft

func (self *TextArea) MoveCursorLeft()

func (*TextArea) MoveCursorRight

func (self *TextArea) MoveCursorRight()

func (*TextArea) MoveCursorUp

func (self *TextArea) MoveCursorUp()

func (*TextArea) MoveLeftWord

func (self *TextArea) MoveLeftWord()

func (*TextArea) MoveRightWord

func (self *TextArea) MoveRightWord()

func (*TextArea) SetCursor2D

func (self *TextArea) SetCursor2D(x int, y int)

takes an x,y position and maps it to a 1D cursor position

func (*TextArea) SetCursorAtEnd

func (self *TextArea) SetCursorAtEnd()

func (*TextArea) ToggleOverwrite

func (self *TextArea) ToggleOverwrite()

func (*TextArea) TypeRune

func (self *TextArea) TypeRune(r rune)

func (*TextArea) TypeString

func (self *TextArea) TypeString(str string)

func (*TextArea) Yank

func (self *TextArea) Yank()

type View

type View struct {

	// Visible specifies whether the view is visible.
	Visible bool

	// BgColor and FgColor allow to configure the background and foreground
	// colors of the View.
	BgColor, FgColor Attribute

	// SelBgColor and SelFgColor are used to configure the background and
	// foreground colors of the selected line, when it is highlighted.
	SelBgColor, SelFgColor Attribute

	// If Editable is true, keystrokes will be added to the view's internal
	// buffer at the cursor position.
	Editable bool

	// Editor allows to define the editor that manages the editing mode,
	// including keybindings or cursor behaviour. DefaultEditor is used by
	// default.
	Editor Editor

	// Overwrite enables or disables the overwrite mode of the view.
	Overwrite bool

	// If Highlight is true, Sel{Bg,Fg}Colors will be used
	// for the line under the cursor position.
	Highlight bool

	// If Frame is true, a border will be drawn around the view.
	Frame bool

	// FrameColor allow to configure the color of the Frame when it is not highlighted.
	FrameColor Attribute

	// FrameRunes allows to define custom runes for the frame edges.
	// The rune slice can be defined with 3 different lengths.
	// If slice doesn't match these lengths, default runes will be used instead of missing one.
	//
	// 2 runes with only horizontal and vertical edges.
	//  []rune{'─', '│'}
	//  []rune{'═','║'}
	// 6 runes with horizontal, vertical edges and top-left, top-right, bottom-left, bottom-right cornes.
	//  []rune{'─', '│', '┌', '┐', '└', '┘'}
	//  []rune{'═','║','╔','╗','╚','╝'}
	// 11 runes which can be used with `gocui.Gui.SupportOverlaps` property.
	//  []rune{'─', '│', '┌', '┐', '└', '┘', '├', '┤', '┬', '┴', '┼'}
	//  []rune{'═','║','╔','╗','╚','╝','╠','╣','╦','╩','╬'}
	FrameRunes []rune

	// If Wrap is true, the content that is written to this View is
	// automatically wrapped when it is longer than its width. If true the
	// view's x-origin will be ignored.
	Wrap bool

	// If Autoscroll is true, the View will automatically scroll down when the
	// text overflows. If true the view's y-origin will be ignored.
	Autoscroll bool

	// If Frame is true, Title allows to configure a title for the view.
	Title string

	Tabs     []string
	TabIndex int

	// TitleColor allow to configure the color of title and subtitle for the view.
	TitleColor Attribute

	// If Frame is true, Subtitle allows to configure a subtitle for the view.
	Subtitle string

	// If Mask is true, the View will display the mask instead of the real
	// content
	Mask rune

	// Overlaps describes which edges are overlapping with another view's edges
	Overlaps byte

	// If HasLoader is true, the message will be appended with a spinning loader animation
	HasLoader bool

	// IgnoreCarriageReturns tells us whether to ignore '\r' characters
	IgnoreCarriageReturns bool

	// ParentView is the view which catches events bubbled up from the given view if there's no matching handler
	ParentView *View

	// ConstrainContentsToParent will prevent this view from rendering outside of the parent's dimensions
	ConstrainContentsToParent bool

	// KeybindOnEdit should be set to true when you want to execute keybindings even when the view is editable
	// (this is usually not the case)
	KeybindOnEdit bool

	TextArea *TextArea

	// something like '1 of 20' for a list view
	Footer string

	// if true, the user can scroll all the way past the last item until it appears at the top of the view
	CanScrollPastBottom bool
	// contains filtered or unexported fields
}

A View is a window. It maintains its own internal buffer and cursor position.

func (*View) Buffer

func (v *View) Buffer() string

Buffer returns a string with the contents of the view's internal buffer.

func (*View) BufferLines

func (v *View) BufferLines() []string

BufferLines returns the lines in the view's internal buffer.

func (*View) Clear

func (v *View) Clear()

Clear empties the view's internal buffer. And resets reading and writing offsets.

func (*View) ClearSearch

func (v *View) ClearSearch()

func (*View) ClearTextArea

func (v *View) ClearTextArea()

func (*View) Cursor

func (v *View) Cursor() (x, y int)

Cursor returns the cursor position of the view.

func (*View) CursorX

func (v *View) CursorX() int

func (*View) CursorY

func (v *View) CursorY() int

func (*View) Dimensions

func (v *View) Dimensions() (int, int, int, int)

Dimensions returns the dimensions of the View

func (*View) FlushStaleCells

func (v *View) FlushStaleCells()

This is for when we've done a restart for the sake of avoiding a flicker and we've reached the end of the new content to display: we need to clear the remaining content from the previous round. We do this by setting v.viewLines to nil so that we just render the new content from v.lines directly

func (*View) FocusPoint

func (v *View) FocusPoint(cx int, cy int)

func (*View) GetClickedTabIndex

func (v *View) GetClickedTabIndex(x int) int

GetClickedTabIndex tells us which tab was clicked

func (*View) Height

func (v *View) Height() int

func (*View) InnerHeight

func (v *View) InnerHeight() int

func (*View) InnerWidth

func (v *View) InnerWidth() int

if a view has a frame, that leaves less space for its writeable area

func (*View) IsSearching

func (v *View) IsSearching() bool

func (*View) IsTainted

func (v *View) IsTainted() bool

IsTainted tells us if the view is tainted

func (*View) Line

func (v *View) Line(y int) (string, error)

Line returns a string with the line of the view's internal buffer at the position corresponding to the point (x, y).

func (*View) LinesHeight

func (v *View) LinesHeight() int

LinesHeight is the count of view lines (i.e. lines excluding wrapping)

func (*View) Name

func (v *View) Name() string

Name returns the name of the view.

func (*View) Origin

func (v *View) Origin() (x, y int)

Origin returns the origin position of the view.

func (*View) OriginX

func (v *View) OriginX() int

func (*View) OriginY

func (v *View) OriginY() int

func (*View) OverwriteLines

func (v *View) OverwriteLines(y int, content string)

only call this function if you don't care where v.wx and v.wy end up

func (*View) Read

func (v *View) Read(p []byte) (n int, err error)

Read reads data into p from the current reading position set by SetReadPos. It returns the number of bytes read into p. At EOF, err will be io.EOF.

func (*View) ReadPos

func (v *View) ReadPos() (x, y int)

ReadPos returns the current read position of the view's internal buffer.

func (*View) RenderTextArea

func (v *View) RenderTextArea()

func (*View) Reset

func (v *View) Reset()

similar to Rewind but clears lines. Also similar to Clear but doesn't reset viewLines

func (*View) Rewind

func (v *View) Rewind()

Rewind sets read and write pos to (0, 0).

func (*View) ScrollDown

func (v *View) ScrollDown(amount int)

ensures we don't scroll past the end of the view's content

func (*View) ScrollLeft

func (v *View) ScrollLeft(amount int)

func (*View) ScrollRight

func (v *View) ScrollRight(amount int)

not applying any limits to this

func (*View) ScrollUp

func (v *View) ScrollUp(amount int)

func (*View) Search

func (v *View) Search(str string) error

func (*View) SelectSearchResult

func (v *View) SelectSearchResult(index int) error

func (*View) SelectedLine

func (v *View) SelectedLine() string

expected to only be used in tests

func (*View) SelectedLineIdx

func (v *View) SelectedLineIdx() int

func (*View) SelectedPoint

func (v *View) SelectedPoint() (int, int)

func (*View) SetContent

func (v *View) SetContent(str string)

func (*View) SetCursor

func (v *View) SetCursor(x, y int) error

SetCursor sets the cursor position of the view at the given point, relative to the view. It checks if the position is valid.

func (*View) SetHighlight

func (v *View) SetHighlight(y int, on bool) error

SetHighlight toggles highlighting of separate lines, for custom lists or multiple selection in views.

func (*View) SetOnSelectItem

func (v *View) SetOnSelectItem(onSelectItem func(int, int, int) error)

func (*View) SetOrigin

func (v *View) SetOrigin(x, y int) error

SetOrigin sets the origin position of the view's internal buffer, so the buffer starts to be printed from this point, which means that it is linked with the origin point of view. It can be used to implement Horizontal and Vertical scrolling with just incrementing or decrementing ox and oy.

func (*View) SetOriginX

func (v *View) SetOriginX(x int) error

func (*View) SetOriginY

func (v *View) SetOriginY(y int) error

func (*View) SetReadPos

func (v *View) SetReadPos(x, y int) error

SetReadPos sets the read position of the view's internal buffer. So the next Read call would read from the specified position.

func (*View) SetWritePos

func (v *View) SetWritePos(x, y int) error

SetWritePos sets the write position of the view's internal buffer. So the next Write call would write directly to the specified position.

func (*View) Size

func (v *View) Size() (x, y int)

Size returns the number of visible columns and rows in the View.

func (*View) ViewBuffer

func (v *View) ViewBuffer() string

ViewBuffer returns a string with the contents of the view's buffer that is shown to the user.

func (*View) ViewBufferLines

func (v *View) ViewBufferLines() []string

ViewBufferLines returns the lines in the view's internal buffer that is shown to the user.

func (*View) ViewLinesHeight

func (v *View) ViewLinesHeight() int

ViewLinesHeight is the count of view lines (i.e. lines including wrapping)

func (*View) Width

func (v *View) Width() int

func (*View) Word

func (v *View) Word(x, y int) (string, error)

Word returns a string with the word of the view's internal buffer at the position corresponding to the point (x, y).

func (*View) Write

func (v *View) Write(p []byte) (n int, err error)

Write appends a byte slice into the view's internal buffer. Because View implements the io.Writer interface, it can be passed as parameter of functions like fmt.Fprintf, fmt.Fprintln, io.Copy, etc. Clear must be called to clear the view's buffer.

func (*View) WritePos

func (v *View) WritePos() (x, y int)

WritePos returns the current write position of the view's internal buffer.

func (*View) WriteRunes

func (v *View) WriteRunes(p []rune)

func (*View) WriteString

func (v *View) WriteString(s string)

exported functions use the mutex. Non-exported functions are for internal use and a calling function should use a mutex

type ViewMouseBinding

type ViewMouseBinding struct {
	// the view that is clicked
	ViewName string

	// the view that has focus when the click occurs.
	FocusedView string

	Handler func(ViewMouseBindingOpts) error

	Modifier Modifier

	// must be a mouse key
	Key Key
}

TODO: would be good to define inbound and outbound click handlers e.g. clicking on a file is an inbound thing where we don't care what context you're in when it happens, whereas clicking on the main view from the files view is an outbound click with a specific handler. But this requires more thinking about where handlers should live.

type ViewMouseBindingOpts

type ViewMouseBindingOpts struct {
	X int // i.e. origin x + cursor x
	Y int // i.e. origin y + cursor y
}

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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