// Frontend: Functions for terminal output // Copyright (C) 2021 Simon Ruderich // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . package frontend import ( "fmt" "regexp" ) type Color int const ( _ Color = iota ColorRed ColorGreen ColorCyan ColorMagenta ) func ColorString(isTTY bool, color Color, x string) string { if !isTTY { return x } var code string switch color { case ColorRed: code = "31" case ColorGreen: code = "32" case ColorMagenta: code = "35" case ColorCyan: code = "36" default: panic(fmt.Sprintf("invalid color %v", color)) } // TODO: check terminal support return "\033[" + code + "m" + x + "\033[0m" } var escapeRegexp = regexp.MustCompile(`[\x00-\x08\x0B-\x1F\x7F]`) // EscapeControlCharacters escapes all ASCII control characters (except // newline and tab) by replacing them with their hex value. If the output is // to a TTY then the escaped characters are colored. // // This function must be used when displaying any input from remote hosts to // prevent terminal escape code injections. func EscapeControlCharacters(isTTY bool, x string) string { return escapeRegexp.ReplaceAllStringFunc(x, func(x string) string { if len(x) != 1 { panic("invalid escapeRegexp") } if x == "\r" { x = "\\r" // occurs often and more readable than \x0D } else { x = fmt.Sprintf("\\x%02X", x[0]) } return ColorString(isTTY, ColorMagenta, x) }) }