liveterm

package module
v2.5.0 Latest Latest
Warning

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

Go to latest
Published: Sep 9, 2024 License: MIT Imports: 12 Imported by: 1

README

liveterm

PkgGoDev

liveterm is a go library for updating terminal output in realtime. It is a fork of the really usefull uilive.

Major differences are:

  • Switch from an async push update model to a sync pull update model
  • Better handling of cleaning the right amount of lines with terminal resizes
  • Helpers to get up to date terminal size to help user formats its data
    • Size is automatically updated if terminal is resized, simply call the helper at the beginning of your formating fx (see the example)
  • Support for incomplete lines
    • User can push raw bytes even if not ended by \n
    • Cursor will stay at the end of the line (instead of the beginning of a new line)
    • But the line will be erased properly anyway
  • Support for runes (Unicode / UTF-8)
    • A rune can has length (byte representation) different from its column (printing) representation
    • For example a rune with a 3 bytes representation can only use 2 columns on the terminal
    • Computing the actual lines printed to the terminal (especially when the original lines overflow and create new ones) in order to erase them after can not rely on bytes len with unicode
    • So lines lenght are based on unicode rune width instead of byte len in uilive
  • (invisible) Support for ANSI terminal sequences (for example, colors)
    • Runes composing them should not be taken into account when computing runes width for a line
    • As the terminal will not print them...
    • ...even if they should normaly have a rune width when printed outside a terminal sequence !
    • Counting them would produce an wrong line width/count and disturb the computed lines number to erase

Be sure to check liveprogress as well !

Update model

uilive

uilive works with an async push based approach:

  • You write (aka "push") to a buffer within uilive writer
  • Writing to this buffer triggers a mutex lock/unlock
  • When ticks kick in, uilive read its internal buffer and update the terminal with it

This can cause performance issue when your data change very frequently:

  • Let's say you update the buffer 1,000,000 times per second
  • But your ui update frequency is 100 milliseconds
  • Between each ui update, the internal buffer is modified 100,000 times, 99,999 for nothing
  • This is wasted ressources and can cause slowdown because of the mutex constant locking/unlocking

You could throttle your data update with your own ticker but you will end up with 2 tickers on both side, not in sync. Why not use only one ?

liveterm

With liveterm I wanted a more efficient, sync pull based approach:

  • You register a function that returns the data you want to be (re)printed
  • At each tick, liveterm will call that function to get up to date data before printing it
  • Between each tick, liveterm sleeps and no buffer or mutex are used for nothing

Usage Example

Full source for the below example is in example/main.go.

Simplified:

// Change default configuration if needed
liveterm.RefreshInterval = 100 * time.Millisecond
liveterm.Output = os.Stdout

// Set the function that will return the data to be displayed
// This can be done or changed even after Start() has been called
liveterm.SetSingleLineUpdateFx(getStatsFx)

// Start live printing
liveterm.Start()

// [ ... ]

// Let's write something to stdout while liveterm is running
fmt.Fprintf(liveterm.Bypass(),
	"This is a message that will be displayed on stdout while the counter is running\n")

// [ ... ]

// Release stdout
liveterm.Stop(false)

Example output

Installation

$ go get -v github.com/hekmon/liveterm/v2

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	// Config (must be changed before calling Start())
	RefreshInterval           = 100 * time.Millisecond // RefreshInterval defines the time between each output refresh
	Output          io.Writer = os.Stdout              // Terminal Output
	HideCursor                = false                  // HideCursor defines if the cursor should be hidden or not during rendering (between Start() and Stop())
)

Functions

func Bypass

func Bypass() io.Writer

Bypass creates an io.Writer which allow to write permalent stuff to the terminal while liveterm is running. Do not forget to include a final '\n' when writting to it.

func ForceUpdate

func ForceUpdate()

ForceUpdate forces an update of the terminal with dynamic data between ticks.

func GetTermProfil added in v2.1.0

func GetTermProfil() termenv.Profile

GetTermProfil has a typo in its name, it is kept for backward compatibility. Deprecated: please use GetTermProfile() instead.

func GetTermProfile added in v2.2.0

func GetTermProfile() termenv.Profile

GetTermProfile returns the termenv profile used by liveterm. It can be used to create styles and colors that will be compatible with the terminal within your updater function. If Start() has not been called yet, it will return the termenv profile of the current Output config value.

func GetTermSize

func GetTermSize() (cols, rows int)

GetTermSize returns the last known terminal size. It is either updated automatically on terminal resize on Unix like systems or updated at each refresh/update interval for windows.

func HasDarkBackground added in v2.4.0

func HasDarkBackground() bool

HasDarkBackground returns whether terminal uses a dark-ish background. If Start() has not been called yet, it will return the current value of the Output config value.

func Hyperlink(link, name string) string

Hyperlink creates a hyperlink.

func Notify added in v2.4.0

func Notify(title, body string)

Notify triggers a notification.

func SetMultiLinesUpdateFx

func SetMultiLinesUpdateFx(fx func() []string)

SetMultiLinesDataFx sets the function that will be called to get data update. There is no need to end each line with a '\n' as it will be added automatically.

func SetRawUpdateFx

func SetRawUpdateFx(fx func() []byte)

SetRawUpdateFx sets the function that will be called to get data update.

func SetSingleLineUpdateFx

func SetSingleLineUpdateFx(fx func() string)

SetSingleLineUpdateFx sets the function that will be called to get data update. There is no need to end each line with a '\n' as it will be added automatically.

func Start

func Start() (err error)

Start starts the updater in a non-blocking manner. After calling Start(), the output (stdout or stderr) should not be used directly anymore. See Bypass() if you need to print regular things while liveterm is running.

func Stop

func Stop(clear bool) (err error)

Stop stops the worker that updates the terminal. Clear will erase dynamic data from the terminal before stopping, otherwise it will update term one last time before stopping. Choosen output (stdout or stderr) can be used again directly after this call.

Types

This section is empty.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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