uilive is a go library for updating terminal output in realtime

Overview

uilive GoDoc Build Status

uilive is a go library for updating terminal output in realtime. It provides a buffered io.Writer that is flushed at a timed interval. uilive powers uiprogress.

Usage Example

Calling uilive.New() will create a new writer. To start rendering, simply call writer.Start() and update the ui by writing to the writer. Full source for the below example is in example/main.go.

writer := uilive.New()
// start listening for updates and render
writer.Start()

for i := 0; i <= 100; i++ {
  fmt.Fprintf(writer, "Downloading.. (%d/%d) GB\n", i, 100)
  time.Sleep(time.Millisecond * 5)
}

fmt.Fprintln(writer, "Finished: Downloaded 100GB")
writer.Stop() // flush and stop rendering

The above will render

example

Installation

$ go get -v github.com/gosuri/uilive
Comments
  • Fix windows build

    Fix windows build

    This includes:

    • fix non-linux builds
    • fix Travis-CI build
    • add Travis-CI build on OSX
    • add Travis-CI cross-build for Windows

    At the current state, the library faisl to build on windows, which causes any dependent packages that build on windows to fail too.

    opened by hoijui 12
  • clearLines not working

    clearLines not working

    Hi Greg,

    I was playing with uilive and am having troubles, not sure if it is my terminal or somethings else is wrong, perhaps you have an idea.

    Basically when I run go run ./example/main.go I end up with:

    $ go run ./example/main.go
    Finished: Downloaded 100GB50) GB
    

    So the previous output is not actually getting cleared, despite the \033[2K CSI code being printed and I still see the 50) GB from the "Downloading" prints.

    Oddly the \033[J code (clear to end of screen) seems to work, so when I change clearLines to look like this it works fine:

    func (w *Writer) clearLines() {
        fmt.Fprint(w.Out, strings.Repeat("\033[A", w.lineCount), "\033[J")
    }
    

    I am running on OSX Sierra, but I tried in iterm2 and terminal both with and without tmux and I get the same results with the original code.

    Any ideas? Thanks! -Cory

    opened by coryb 5
  • Fixed overflow when width of buffer exceeds screen width | This doesn…

    Fixed overflow when width of buffer exceeds screen width | This doesn…

    Fixed overflow when width of buffer exceeds screen width. This doesnt work for windows. This gets the terminal size and validates if buffer width exceeds screen width.

    opened by apoorvam 5
  • Library should not call os.exit()

    Library should not call os.exit()

    With the latest commit if the tool fails to open /dev/tty (to get window size) then it calls os.exit(). A library should not call os.exit! When my command line tool (that doesn't use this as a direct dependency) was run from an environment where there wasn't a tty it just exited. No error, no problem. I had to do an strace just to see that it was right after trying to open /dev/tty.

    opened by jasoncorbett 4
  • New goroutine

    New goroutine

    How do you make this work with new go routines?

    progressWrite := uilive.New()
    progressWrite.Start()
    
    for i := 0; i <= 100; i++ {
    	go func() {
    		fmt.Fprintf(progressWrite, "Downloading.. (%d/%d) GB\n", i, 100)
    		time.Sleep(time.Millisecond * 20)
    	}()
    }
    
    opened by brianvoe 4
  • Broken lines

    Broken lines

    Hi, I thought I've finally found a lib which makes it easy to use single-line prints, but this lib suffers from the same issue I've seen in many other libs.

    demo:

    writer := uilive.New()
    // start listening for updates and render
    writer.Start()
    
    for i := 0; i <= 100; i++ {
      fmt.Fprintf(writer, "Downloading.. (%d/%d) GB\n", i, 100)
      time.Sleep(time.Millisecond * 5)
    }
    
    fmt.Fprintln(writer, "Finished")
    writer.Stop() // flush and stop rendering
    

    try fmt.Fprintln(writer, "Finished") instead of fmt.Fprintln(writer, "Finished: Downloaded 100GB"). meaning: print a last message which is shorter than the previous one.

    I get:

    Finisheding.. (100/100) GB
    
    opened by omani 3
  • Outputting to multiple lines

    Outputting to multiple lines

    This is more a question than an issue.

    I'd like to output and update the status of a list of tasks:

    e.g.

    Task1... Done
    Task2... Done
    Task3... Running
    Task4... 
    

    I've attempted to do this using multiple Fprintf statements as follows:

    w := uilive.New()
    w.Start()
    
    for i := 0; i <= 60; i++ {
      var t1, t2, t3, t4 string
    
      if i > 2 {
        t1 = "Done     "
        t2 = "Running"
      }
      if i > 5 {
        t1 = "Done     "
        t2 = "Done     "
        t3 = "Running"
      }
      if i > 7 {
        t1 = "Done     "
        t2 = "Done     "
        t3 = "Done     "
        t4 = "Running"
      }
      if i > 9 {
        t1 = "Done     "
        t2 = "Done     "
        t3 = "Done     "
        t4 = "Done     "
      }
    
      fmt.Fprintf(w, "Task1...  %s\n", t1)
      fmt.Fprintf(w, "Task2...  %s\n", t2)
      fmt.Fprintf(w, "Task3...  %s\n", t3)
      fmt.Fprintf(w, "Task4...  %s\n", t4)
      time.Sleep(time.Second)
    }
    
    w.Stop()
    

    This initially appears to work fine however on some iterations various tasks disappear and then reappear.

    e.g.

    # I get this
    Task3...  Done
    Task4...  Done
    
    # instead of
    Task1...  Done
    Task2...  Done
    Task3...  Done
    Task4...  Done
    

    Am I using this incorrectly or could this possibly be a bug?

    opened by g3kk0 3
  • Latest commit breaks Windows build

    Latest commit breaks Windows build

    # github.com/gosuri/uilive
    ..\..\..\go\pkg\mod\github.com\gosuri\[email protected]\terminal_size.go:34:27: not enough arguments in call to syscall.Syscall
    ..\..\..\go\pkg\mod\github.com\gosuri\[email protected]\terminal_size.go:34:28: undefined: syscall.SYS_IOCTL
    ..\..\..\go\pkg\mod\github.com\gosuri\[email protected]\terminal_size.go:35:21: undefined: syscall.TIOCGWINSZ
    ..\..\..\go\pkg\mod\github.com\gosuri\[email protected]\writer_windows.go:49:12: undefined: isatty
    ..\..\..\go\pkg\mod\github.com\gosuri\[email protected]\writer_windows.go:53:28: undefined: strings
    
    opened by paralin 2
  • getTermSize return 0 when no tty with process

    getTermSize return 0 when no tty with process

    when program is started by supervisord, there's no tty associated its process.
    os.Exit(1) makes process failed.

    The fix is to return 0 windows size when there's no tty.

    opened by Honglei-Cong 2
  • glitch when the writer RefreshInterval is too little

    glitch when the writer RefreshInterval is too little

    When the RefreshInterval is too little like time.Nanosecond little or 0, you should use writer.Wait() to be able to use the library, but still the text glitches a little. And when you do not use the writer.Wait(), the library isn't able to replace the text and start to act almost like a regular fmt.Println.

    package main
    
    import (
            "fmt"
    
            "github.com/gosuri/uilive"
    )
    
    func main() {
            writer := uilive.New()
    
            // start listening for updates and render
            writer.RefreshInterval = 0
    
            writer.Start()
    
            for _, f := range []string{"Foo.zip", "Bar.iso"} {
                    for i := 0; i <= 5000000; i++ {
                            fmt.Fprintf(writer, "Downloading %s.. (%d/%d) GB\n", f, i, 50)
                            writer.Wait()
                    }
                    fmt.Fprintf(writer.Bypass(), "Downloaded %s\n", f)
            }
    
            fmt.Fprintln(writer, "Finished: Downloaded 100GB")
            writer.Stop() // flush and stop rendering
    }
    
    opened by renannprado 2
  • Added bypass writer which allows data to be written to the underlying output

    Added bypass writer which allows data to be written to the underlying output

    I'm not sure if this is something you actually want, but I've found it convenient to still be able to output log messages while the uiprogress output is running. At the moment, any 'normal' output gets overwritten by the next refresh of the uilive buffer, and you end up with lots of progress bars left behind due to the output getting out of sync.

    By clearing the uilive.Writer lines and resetting the line count, log output (for example) can be written to the underlying output without being overwritten by the next update from the buffer.

    I've also exposed a similar method on the uiprogress.Progress object, which I will create a PR for.

    opened by kothar 2
  • fixbug terminal_size.go

    fixbug terminal_size.go

    ttysize structure has long been obsolete, the ioctl for ttysize was unsupported by kernel 2.6.16, change windowSize to winsize.

    windowSize struct is 32bit but winsize is 64bit, which will cause cross border error.

    opened by xq840622 0
  • Syscall in getTermSize() corrupts package variable of a different library

    Syscall in getTermSize() corrupts package variable of a different library

    Hi.

    I am developing a CLI application which uses uilive v0.0.4 to output execution statistics to the console at runtime. Everything was fine until I decided to use sniper as a key-value storage for my app. It turned out that one of the sniper package variables got corrupted (changes it's value from 12 to 0) after calling uilive.New(). Without calling uilive.New() sniper works perfectly fine.

    I traced the issue down to the IOCTL syscall in getTermSize() function in terminal_size.go:

    //...
    var sz windowSize
    
    func getTermSize() (int, int) {
           //...
           // `sniper` package variable is fine here
    	_, _, _ = syscall.Syscall(syscall.SYS_IOCTL,
    		out.Fd(), uintptr(syscall.TIOCGWINSZ), uintptr(unsafe.Pointer(&sz)))
            // `sniper` package variable is reset to 0 
    	return int(sz.cols), int(sz.rows)
    }Ubuntu 20.04 LTS x64
    

    I am not sure what goes wrong exactly, but it looks like using an unsafe.Pointer to the sz package variable somehow messes up the memory contents. I can't say if any other package variables are affected.

    I managed to fix the issue by simply moving package variables from terminal_size.go into the getTermSize() function body, making them local (and they kinda should be local, there are no usages of them outside of terminal_size.go):

    // +build !windows
    
    package uilive
    
    import (
    	"os"
    	"runtime"
    	"syscall"
    	"unsafe"
    )
    
    type windowSize struct {
    	rows    uint16
    	cols    uint16
    }
    
    func getTermSize() (int, int) {
    	var (
    		out *os.File
    		err error
    		sz  windowSize
    	)
    	if runtime.GOOS == "openbsd" {
    		out, err = os.OpenFile("/dev/tty", os.O_RDWR, 0)
    		if err != nil {
    			return 0, 0
    		}
    	} else {
    		out, err = os.OpenFile("/dev/tty", os.O_WRONLY, 0)
    		if err != nil {
    			return 0, 0
    		}
    	}
    	_, _, _ = syscall.Syscall(syscall.SYS_IOCTL,
    		out.Fd(), uintptr(syscall.TIOCGWINSZ), uintptr(unsafe.Pointer(&sz)))
    	return int(sz.cols), int(sz.rows)
    }
    

    What do you think? Please help me out.

    Env specs: ||| |---|---| |OS|Ubuntu 20.04 LTS x64| |Kernel|5.7.7-050707-generic| |Go|1.15.7|

    PR: #39

    P.S.: big thanks for the library, it's awesome :)

    opened by VoIdemar 0
  • Adding ppc64le architecture support on travis-ci

    Adding ppc64le architecture support on travis-ci

    Hi, I had added ppc64le(Linux on Power) architecture support on travis-ci in the PR and looks like its been successfully added. I believe it is ready for the final review and merge. The travis ci build logs can be verified from the link below. https://travis-ci.com/github/kishorkunal-raj/uilive/builds/191399390

    Reason behind running tests on ppc64le: This package is included in the ppc64le versions of RHEL and Ubuntu - this allows the top of tree to be tested continuously as it is for Intel, making it easier to catch any possible regressions on ppc64le before the distros begin their clones and builds. This reduces the work in integrating this package into future versions of RHEL/Ubuntu.

    Please have a look.

    Regards, Kishor Kunal Raj

    opened by kishorkunal-raj 1
  • Combining with uitable causes leading whitespace

    Combining with uitable causes leading whitespace

    Just come across your trio of console UI libraries, they look awesome!

    One bug I've found is when combining this with uitable. Here's my code:

    	writer := uilive.New()
    	bufferedWriter := writer.Bypass()
    	writer.Start()
    
    	for i := 0; i <= 100; i++ {
    		table := uitable.New()
    		table.MaxColWidth = 50
    
    		table.AddRow("Operation", "Progress", "%%")
    		table.AddRow("Downloading", fmt.Sprintf("%d/%d", i, 100), fmt.Sprintf("%d", i/100))
    		table.AddRow("And another", fmt.Sprintf("%d/%d", i*2, 1000), fmt.Sprintf("%d", (i*2)/1000))
    
    		fmt.Fprintf(bufferedWriter, table.String())
    		writer.Flush()
    		time.Sleep(time.Millisecond * 500)
    	}
    
    	fmt.Fprintln(writer, "Finished: Downloaded 100GB")
    	writer.Stop() // flush and stop rendering
    

    And here's some output:

                                      Operation  	Progress	%
    Downloading	35/100  	0 
    And another	70/1000 	0
    

    As you can see the top row of the table is indented by spaces. Is this easy to fix? As you can see above I am using .Newline(). I did also try writing direct to writer, but that still causes the bug. If I use .Bypass() then the indent goes away but then the table is echoed many times to the terminal as it updates. Removing .Flush() makes no difference.

    opened by jtyers 0
Releases(v0.0.4)
  • v0.0.4(Jan 3, 2020)

    • Fix getTermSize() for Windows via #29 by @vnlitvinov
    • Change Out type to io.Writer via #15 by @maplain
    • Allow Start to be called immediately after Stop via #19 by @genevieve
    Source code(tar.gz)
    Source code(zip)
  • v0.0.2(Apr 11, 2019)

    • Fixes an issue where the last line is being overwritten when the width of the buffer exceeds screen width (#3)
    • Fixes a glitch when the writer RefreshInterval is too little (#9)
    • Support for outputting to newline (#14)
    Source code(tar.gz)
    Source code(zip)
Owner
Greg Osuri
Founder & CEO, Akash Network / Overclock Labs
Greg Osuri
Intuitive package for prettifying terminal/console output. http://godoc.org/github.com/ttacon/chalk

chalk Chalk is a go package for styling console/terminal output. Check out godoc for some example usage: http://godoc.org/github.com/ttacon/chalk The

Trey Tacon 416 Nov 24, 2022
Small library for simple and convenient formatted stylized output to the console.

cfmt cfmt is a small library for simple and convenient formatted stylized output to the console, providing an interface that is exactly the same as th

Makhnev Petr 52 Oct 28, 2022
✨ #PTerm is a modern go module to beautify console output. Featuring charts, progressbars, tables, trees, and many more 🚀 It's completely configurable and 100% cross-platform compatible.

?? PTerm | Pretty Terminal Printer A golang module to print pretty text Show Demo Code PTerm.sh | Installation | Documentation | Quick Start | Example

null 3.1k Nov 25, 2022
Console Text Colors - The non-invasive cross-platform terminal color library does not need to modify the Print method

ctc - Console Text Colors The non-invasive cross-platform terminal color library does not need to modify the Print method Virtual unix-like environmen

null 41 Nov 9, 2022
A go library to render progress bars in terminal applications

uiprogress A Go library to render progress bars in terminal applications. It provides a set of flexible features with a customizable API. Progress bar

Greg Osuri 2k Nov 20, 2022
A go library to improve readability in terminal apps using tabular data

uitable uitable is a go library for representing data as tables for terminal applications. It provides primitives for sizing and wrapping columns to i

Greg Osuri 681 Nov 20, 2022
An ANSI colour terminal package for Go

colourize An ANSI colour terminal package for Go. Supports all ANSI colours and emphasis. Not compatible with Windows systems. Installation go get gi

Trey Bastian 26 Sep 26, 2022
Simple tables in terminal with Go

Simple tables in terminal with Go This package allows to generate and display ascii tables in the terminal, f.e.: +----+------------------+-----------

Alexey Popov 399 Nov 20, 2022
Terminal based dashboard.

Termdash is a cross-platform customizable terminal based dashboard. The feature set is inspired by the gizak/termui project, which in turn was inspire

Jakub Sobon 2.2k Nov 27, 2022
Golang terminal dashboard

termui termui is a cross-platform and fully-customizable terminal dashboard and widget library built on top of termbox-go. It is inspired by blessed-c

Zack Guo 12.2k Nov 24, 2022
Yet Another CLi Spinner; providing over 70 easy to use and customizable terminal spinners for multiple OSes

Yet Another CLi Spinner (for Go) Package yacspin provides yet another CLi spinner for Go, taking inspiration (and some utility code) from the https://

Tim Heckman 385 Nov 18, 2022
Terminal string styling for go done right, with full and painless Windows 10 support.

GChalk GChalk is a library heavily inspired by chalk, the popular Node.js terminal color library, and using go ports of supports-color and ansi-styles

Jason Walton 317 Nov 8, 2022
A tiny library for super simple Golang tables

Tabby A tiny library for super simple Golang tables Get Tabby go get github.com/cheynewallace/tabby Import Tabby import "github.com/cheynewallace/tabb

Cheyne Wallace 324 Nov 11, 2022
Stonks is a terminal based stock visualizer and tracker that displays realtime stocks in graph format in a terminal.

Stonks is a terminal based stock visualizer and tracker. Installation Requirements: golang >= 1.13 Manual Clone the repo Run make && make install Pack

Eric Moynihan 516 Nov 16, 2022
A tiny markup language for terminal output. Makes formatting output in CLI apps easier!

tml - Terminal Markup Language A Go module (and standalone binary) to make the output of coloured/formatted text in the terminal easier and more reada

Liam Galvin 703 Nov 26, 2022
Pi-hole data right from your terminal. Live updating view, query history extraction and more!

Pi-CLI Pi-CLI is a command line program used to view data from a Pi-Hole instance directly in your terminal.

Reece Mercer 40 Oct 1, 2022
A Go library for fetching, parsing, and updating RSS feeds.

rss RSS is a small library for simplifying the parsing of RSS and Atom feeds. The package could do with more testing, but it conforms to the RSS 1.0,

Jamie Hall 373 Nov 24, 2022
A simple tool to extract Fronius solar data logger output and output Influx line protocol

telegraf-exec-fronius This is a simple tool to extract Fronius solar data logger output and output Influx line protocol; it is designed to be used wit

Steve Hoeksema 1 Jan 8, 2022
🎨 Terminal color rendering library, support 8/16 colors, 256 colors, RGB color rendering output, support Print/Sprintf methods, compatible with Windows.

?? Terminal color rendering library, support 8/16 colors, 256 colors, RGB color rendering output, support Print/Sprintf methods, compatible with Windows. GO CLI 控制台颜色渲染工具库,支持16色,256色,RGB色彩渲染输出,使用类似于 Print/Sprintf,兼容并支持 Windows 环境的色彩渲染

Gookit 1.2k Nov 30, 2022