rclone/lib/terminal/terminal.go

111 lines
2.4 KiB
Go

// Package terminal provides VT100 terminal codes and a windows
// implementation of that.
package terminal
import (
"io"
"os"
"runtime"
"sync"
colorable "github.com/mattn/go-colorable"
"golang.org/x/crypto/ssh/terminal"
)
// VT100 codes
const (
EraseLine = "\x1b[2K"
MoveToStartOfLine = "\x1b[1G"
MoveUp = "\x1b[1A"
Reset = "\x1b[0m"
Bright = "\x1b[1m"
Dim = "\x1b[2m"
Underscore = "\x1b[4m"
Blink = "\x1b[5m"
Reverse = "\x1b[7m"
Hidden = "\x1b[8m"
BlackFg = "\x1b[30m"
RedFg = "\x1b[31m"
GreenFg = "\x1b[32m"
YellowFg = "\x1b[33m"
BlueFg = "\x1b[34m"
MagentaFg = "\x1b[35m"
CyanFg = "\x1b[36m"
WhiteFg = "\x1b[37m"
BlackBg = "\x1b[40m"
RedBg = "\x1b[41m"
GreenBg = "\x1b[42m"
YellowBg = "\x1b[43m"
BlueBg = "\x1b[44m"
MagentaBg = "\x1b[45m"
CyanBg = "\x1b[46m"
WhiteBg = "\x1b[47m"
HiBlackFg = "\x1b[90m"
HiRedFg = "\x1b[91m"
HiGreenFg = "\x1b[92m"
HiYellowFg = "\x1b[93m"
HiBlueFg = "\x1b[94m"
HiMagentaFg = "\x1b[95m"
HiCyanFg = "\x1b[96m"
HiWhiteFg = "\x1b[97m"
HiBlackBg = "\x1b[100m"
HiRedBg = "\x1b[101m"
HiGreenBg = "\x1b[102m"
HiYellowBg = "\x1b[103m"
HiBlueBg = "\x1b[104m"
HiMagentaBg = "\x1b[105m"
HiCyanBg = "\x1b[106m"
HiWhiteBg = "\x1b[107m"
)
var (
// make sure that start is only called once
once sync.Once
)
// Start the terminal - must be called before use
func Start() {
once.Do(func() {
f := os.Stdout
if !terminal.IsTerminal(int(f.Fd())) {
// If stdout not a tty then remove escape codes
Out = colorable.NewNonColorable(f)
} else if runtime.GOOS == "windows" && os.Getenv("TERM") != "" {
// If TERM is set just use stdout
Out = f
} else {
Out = colorable.NewColorable(f)
}
})
}
// WriteString writes the string passed in to the terminal
func WriteString(s string) {
Write([]byte(s))
}
// GetSize reads the dimensions of the current terminal or returns a
// sensible default
func GetSize() (w, h int) {
w, h, err := terminal.GetSize(int(os.Stdout.Fd()))
if err != nil {
w, h = 80, 25
}
return w, h
}
// Out is an io.Writer which can be used to write to the terminal
// eg for use with fmt.Fprintf(terminal.Out, "terminal fun: %d\n", n)
var Out io.Writer
// Write sends out to the VT100 terminal.
// It will initialise the terminal if this is the first call.
func Write(out []byte) {
Start()
_, _ = Out.Write(out)
}