github.com/criteo/command-launcher@v0.0.0-20230407142452-fb616f546e98/internal/console/console.go (about) 1 package console 2 3 import ( 4 "fmt" 5 "os" 6 "runtime" 7 "strings" 8 9 "github.com/fatih/color" 10 ps "github.com/mitchellh/go-ps" 11 log "github.com/sirupsen/logrus" 12 ) 13 14 var ( 15 colorWarn = color.New(color.FgHiYellow).Add(color.BgBlack) 16 isAnsiSequenceSupported = checkAnsiSequenceSupported() 17 ) 18 19 func processName() string { 20 if runtime.GOOS == "windows" { 21 return "cdt.exe" 22 } 23 24 return "cdt" 25 } 26 27 func parentName() (string, error) { 28 parent, err := ps.FindProcess(os.Getppid()) 29 if err != nil { 30 return "", err 31 } 32 33 if parent.Executable() == processName() { 34 parent, err = ps.FindProcess(parent.PPid()) 35 if err != nil { 36 return "", err 37 } 38 } 39 40 return parent.Executable(), nil 41 } 42 43 func checkAnsiSequenceSupported() bool { 44 maybeSupported := !color.NoColor 45 // The Powershell console does not support the escape ANSI chars 46 if runtime.GOOS == "windows" && maybeSupported { 47 parent, err := parentName() 48 if err != nil { 49 maybeSupported = false 50 } else { 51 log.Debugf("Parent Process name %s", parent) 52 maybeSupported = strings.ToLower(parent) != "powershell.exe" 53 } 54 } 55 56 log.Debugf("ANSI sequences are supported by the console: %t", maybeSupported) 57 return maybeSupported 58 } 59 60 // When the ANSI sequence is supported, the console will display the colors and cursor moves 61 // 62 // On Windows, when cdt runs in a powershell console, the ANSI sequences are not supported. 63 func IsAnsiSequenceSupported() bool { 64 return isAnsiSequenceSupported 65 } 66 67 // Color code 68 // 69 // Blue: for highlighted informative text 70 // Magenta: for interactive questions, reminder 71 // Yellow: for warning 72 // Red: for errors 73 74 // highlight informative text in the output so that 75 // user can distinguish different steps in the output 76 // for example: highlight the command used under the hood 77 // see: hotfix create, hotfix review 78 func Highlight(format string, a ...interface{}) { 79 if isAnsiSequenceSupported { 80 color.Blue(format, a...) 81 } else { 82 fmt.Printf(format, a...) 83 } 84 } 85 86 // usually used as a reminder, a question, or additional 87 // information that need the user interact, but not mandatory. 88 // for example: ask for user to update 89 func Reminder(format string, a ...interface{}) { 90 if isAnsiSequenceSupported { 91 color.Magenta(format, a...) 92 } else { 93 fmt.Printf(format, a...) 94 } 95 } 96 97 // usually used as warning message 98 func Warn(format string, a ...interface{}) { 99 if isAnsiSequenceSupported { 100 colorWarn.Printf(format, a...) 101 } else { 102 fmt.Printf(format, a...) 103 } 104 } 105 106 // usually used as error message 107 func Error(format string, a ...interface{}) { 108 if isAnsiSequenceSupported { 109 color.Red(format, a...) 110 } else { 111 fmt.Printf(format, a...) 112 } 113 } 114 115 // usually used as success message 116 func Success(format string, a ...interface{}) { 117 if isAnsiSequenceSupported { 118 color.Green(format, a...) 119 } else { 120 fmt.Printf(format, a...) 121 } 122 }