f9d50f677d
This ensures the virtual terminal processing mode is enabled on the rclone process for Windows 10 consoles (by using Windows Console API functions GetConsoleMode/SetConsoleMode and flag ENABLE_VIRTUAL_TERMINAL_PROCESSING), which adds native support for ANSI/VT100 escape sequences. This mode is default in many cases, e.g. when using the Windows Terminal application, but in other cases it is not, and the default can also be controlled with registry setting (see below), and therefore configuring it on the process seem to be the only reliable way of ensuring it is enabled when supported. [HKEY_CURRENT_USER\Console] "VirtualTerminalLevel"=dword:00000001
124 lines
3 KiB
Go
124 lines
3 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 explicitely write text with color
|
|
// formatting to the console using Windows API functions, but can simply
|
|
// relay everything to stdout.
|
|
func EnableColorsStdout() {
|
|
_ = colorable.EnableColorsStdout(nil)
|
|
}
|