github.com/hugorut/terraform@v1.1.3/src/terminal/streams.go (about) 1 // Package terminal encapsulates some platform-specific logic for detecting 2 // if we're running in a terminal and, if so, properly configuring that 3 // terminal to meet the assumptions that the rest of Terraform makes. 4 // 5 // Specifically, Terraform requires a Terminal which supports virtual terminal 6 // sequences and which accepts UTF-8-encoded text. 7 // 8 // This is an abstraction only over the platform-specific detection of and 9 // possibly initialization of terminals. It's not intended to provide 10 // higher-level abstractions of the sort provided by packages like termcap or 11 // curses; ultimately we just assume that terminals are "standard" VT100-like 12 // terminals and use a subset of control codes that works across the various 13 // platforms we support. Our approximate target is "xterm-compatible" 14 // virtual terminals. 15 package terminal 16 17 import ( 18 "fmt" 19 "os" 20 ) 21 22 // Streams represents a collection of three streams that each may or may not 23 // be connected to a terminal. 24 // 25 // If a stream is connected to a terminal then there are more possibilities 26 // available, such as detecting the current terminal width. If we're connected 27 // to something else, such as a pipe or a file on disk, the stream will 28 // typically provide placeholder values or do-nothing stubs for 29 // terminal-requiring operatons. 30 // 31 // Note that it's possible for only a subset of the streams to be connected 32 // to a terminal. For example, this happens if the user runs Terraform with 33 // I/O redirection where Stdout might refer to a regular disk file while Stderr 34 // refers to a terminal, or various other similar combinations. 35 type Streams struct { 36 Stdout *OutputStream 37 Stderr *OutputStream 38 Stdin *InputStream 39 } 40 41 // Init tries to initialize a terminal, if Terraform is running in one, and 42 // returns an object describing what it was able to set up. 43 // 44 // An error for this function indicates that the current execution context 45 // can't meet Terraform's assumptions. For example, on Windows Init will return 46 // an error if Terraform is running in a Windows Console that refuses to 47 // activate UTF-8 mode, which can happen if we're running on an unsupported old 48 // version of Windows. 49 // 50 // Note that the success of this function doesn't mean that we're actually 51 // running in a terminal. It could also represent successfully detecting that 52 // one or more of the input/output streams is not a terminal. 53 func Init() (*Streams, error) { 54 // These configure* functions are platform-specific functions in other 55 // files that use //+build constraints to vary based on target OS. 56 57 stderr, err := configureOutputHandle(os.Stderr) 58 if err != nil { 59 return nil, err 60 } 61 stdout, err := configureOutputHandle(os.Stdout) 62 if err != nil { 63 return nil, err 64 } 65 stdin, err := configureInputHandle(os.Stdin) 66 if err != nil { 67 return nil, err 68 } 69 70 return &Streams{ 71 Stdout: stdout, 72 Stderr: stderr, 73 Stdin: stdin, 74 }, nil 75 } 76 77 // Print is a helper for conveniently calling fmt.Fprint on the Stdout stream. 78 func (s *Streams) Print(a ...interface{}) (n int, err error) { 79 return fmt.Fprint(s.Stdout.File, a...) 80 } 81 82 // Printf is a helper for conveniently calling fmt.Fprintf on the Stdout stream. 83 func (s *Streams) Printf(format string, a ...interface{}) (n int, err error) { 84 return fmt.Fprintf(s.Stdout.File, format, a...) 85 } 86 87 // Println is a helper for conveniently calling fmt.Fprintln on the Stdout stream. 88 func (s *Streams) Println(a ...interface{}) (n int, err error) { 89 return fmt.Fprintln(s.Stdout.File, a...) 90 } 91 92 // Eprint is a helper for conveniently calling fmt.Fprint on the Stderr stream. 93 func (s *Streams) Eprint(a ...interface{}) (n int, err error) { 94 return fmt.Fprint(s.Stderr.File, a...) 95 } 96 97 // Eprintf is a helper for conveniently calling fmt.Fprintf on the Stderr stream. 98 func (s *Streams) Eprintf(format string, a ...interface{}) (n int, err error) { 99 return fmt.Fprintf(s.Stderr.File, format, a...) 100 } 101 102 // Eprintln is a helper for conveniently calling fmt.Fprintln on the Stderr stream. 103 func (s *Streams) Eprintln(a ...interface{}) (n int, err error) { 104 return fmt.Fprintln(s.Stderr.File, a...) 105 }