// 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) }