github.com/sijibomii/docker@v0.0.0-20231230191044-5cf6ca554647/pkg/term/windows/console.go (about) 1 // +build windows 2 3 package windows 4 5 import ( 6 "io" 7 "os" 8 "syscall" 9 10 "github.com/Azure/go-ansiterm/winterm" 11 12 ansiterm "github.com/Azure/go-ansiterm" 13 "github.com/Sirupsen/logrus" 14 "io/ioutil" 15 ) 16 17 // ConEmuStreams returns prepared versions of console streams, 18 // for proper use in ConEmu terminal. 19 // The ConEmu terminal emulates ANSI on output streams well by default. 20 func ConEmuStreams() (stdIn io.ReadCloser, stdOut, stdErr io.Writer) { 21 if IsConsole(os.Stdin.Fd()) { 22 stdIn = newAnsiReader(syscall.STD_INPUT_HANDLE) 23 } else { 24 stdIn = os.Stdin 25 } 26 27 stdOut = os.Stdout 28 stdErr = os.Stderr 29 30 // WARNING (BEGIN): sourced from newAnsiWriter 31 32 logFile := ioutil.Discard 33 34 if isDebugEnv := os.Getenv(ansiterm.LogEnv); isDebugEnv == "1" { 35 logFile, _ = os.Create("ansiReaderWriter.log") 36 } 37 38 logger = &logrus.Logger{ 39 Out: logFile, 40 Formatter: new(logrus.TextFormatter), 41 Level: logrus.DebugLevel, 42 } 43 44 // WARNING (END): sourced from newAnsiWriter 45 46 return stdIn, stdOut, stdErr 47 } 48 49 // ConsoleStreams returns a wrapped version for each standard stream referencing a console, 50 // that handles ANSI character sequences. 51 func ConsoleStreams() (stdIn io.ReadCloser, stdOut, stdErr io.Writer) { 52 if IsConsole(os.Stdin.Fd()) { 53 stdIn = newAnsiReader(syscall.STD_INPUT_HANDLE) 54 } else { 55 stdIn = os.Stdin 56 } 57 58 if IsConsole(os.Stdout.Fd()) { 59 stdOut = newAnsiWriter(syscall.STD_OUTPUT_HANDLE) 60 } else { 61 stdOut = os.Stdout 62 } 63 64 if IsConsole(os.Stderr.Fd()) { 65 stdErr = newAnsiWriter(syscall.STD_ERROR_HANDLE) 66 } else { 67 stdErr = os.Stderr 68 } 69 70 return stdIn, stdOut, stdErr 71 } 72 73 // GetHandleInfo returns file descriptor and bool indicating whether the file is a console. 74 func GetHandleInfo(in interface{}) (uintptr, bool) { 75 switch t := in.(type) { 76 case *ansiReader: 77 return t.Fd(), true 78 case *ansiWriter: 79 return t.Fd(), true 80 } 81 82 var inFd uintptr 83 var isTerminal bool 84 85 if file, ok := in.(*os.File); ok { 86 inFd = file.Fd() 87 isTerminal = IsConsole(inFd) 88 } 89 return inFd, isTerminal 90 } 91 92 // IsConsole returns true if the given file descriptor is a Windows Console. 93 // The code assumes that GetConsoleMode will return an error for file descriptors that are not a console. 94 func IsConsole(fd uintptr) bool { 95 _, e := winterm.GetConsoleMode(fd) 96 return e == nil 97 }