mirror of
https://github.com/rclone/rclone.git
synced 2024-12-19 17:34:05 +08:00
125 lines
3.0 KiB
Go
125 lines
3.0 KiB
Go
// Package terminal provides VT100 terminal codes and a windows
|
|
// implementation of that.
|
|
package terminal
|
|
|
|
import (
|
|
"context"
|
|
"io"
|
|
"os"
|
|
"runtime"
|
|
"sync"
|
|
|
|
colorable "github.com/mattn/go-colorable"
|
|
"github.com/rclone/rclone/fs"
|
|
)
|
|
|
|
// 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"
|
|
|
|
ChangeTitle = "\033]0;"
|
|
BEL = "\007"
|
|
)
|
|
|
|
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() {
|
|
ci := fs.GetConfig(context.Background())
|
|
|
|
f := os.Stdout
|
|
if !IsTerminal(int(f.Fd())) {
|
|
// If stdout is not a tty, remove escape codes EXCEPT if terminal color mode equals "ALWAYS"
|
|
if ci.TerminalColorMode == fs.TerminalColorModeAlways {
|
|
Out = colorable.NewColorable(f)
|
|
} else {
|
|
Out = colorable.NewNonColorable(f)
|
|
}
|
|
} else if runtime.GOOS == "windows" && os.Getenv("TERM") != "" {
|
|
// If TERM is set just use stdout
|
|
Out = f
|
|
} else if ci.TerminalColorMode == fs.TerminalColorModeNever {
|
|
Out = colorable.NewNonColorable(f)
|
|
} else {
|
|
Out = colorable.NewColorable(f)
|
|
}
|
|
})
|
|
}
|
|
|
|
// WriteString writes the string passed in to the terminal
|
|
func WriteString(s string) {
|
|
Write([]byte(s))
|
|
}
|
|
|
|
// Out is an io.Writer which can be used to write to the terminal
|
|
// e.g. 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)
|
|
}
|
|
|
|
// EnableColorsStdout enable colors if possible.
|
|
// This enables virtual terminal processing on Windows 10 console,
|
|
// adding native support for VT100 escape codes. When this terminal
|
|
// package is used for output, the result is that the colorable library
|
|
// don't have to decode the escapes and explicitly write text with color
|
|
// formatting to the console using Windows API functions, but can simply
|
|
// relay everything to stdout.
|
|
func EnableColorsStdout() {
|
|
_ = colorable.EnableColorsStdout(nil)
|
|
}
|