-
Notifications
You must be signed in to change notification settings - Fork 72
/
iostreams.go
112 lines (92 loc) · 2.19 KB
/
iostreams.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
package iostreams
import (
"io"
"os"
"github.com/fatih/color"
"github.com/mattn/go-isatty"
)
// IOStreams is a type which defines the
// streams for the program
type IOStreams struct {
In io.ReadCloser
Out io.Writer
ErrOut io.Writer
originalOut io.Writer
stdinTTYOverride bool
stdinIsTTY bool
stdoutTTYOverride bool
stdoutIsTTY bool
stderrTTYOverride bool
stderrIsTTY bool
// indicate whether interactive input should be disabled
neverPrompt bool
}
func (s *IOStreams) SetStdinTTY(isTTY bool) {
s.stdinTTYOverride = true
s.stdinIsTTY = isTTY
}
func (s *IOStreams) IsStdinTTY() bool {
if s.stdinTTYOverride {
return s.stdinIsTTY
}
if stdin, ok := s.In.(*os.File); ok {
return isTerminal(stdin)
}
return false
}
func (s *IOStreams) SetStdoutTTY(isTTY bool) {
s.stdoutTTYOverride = true
s.stdoutIsTTY = isTTY
}
func (s *IOStreams) IsStdoutTTY() bool {
if s.stdoutTTYOverride {
return s.stdoutIsTTY
}
if stdout, ok := s.Out.(*os.File); ok {
return isTerminal(stdout)
}
return false
}
func (s *IOStreams) SetStderrTTY(isTTY bool) {
s.stderrTTYOverride = true
s.stderrIsTTY = isTTY
}
func (s *IOStreams) IsStderrTTY() bool {
if s.stderrTTYOverride {
return s.stderrIsTTY
}
if stderr, ok := s.ErrOut.(*os.File); ok {
return isTerminal(stderr)
}
return false
}
// CanPrompt detects if the input is a TTY
func (s *IOStreams) CanPrompt() bool {
if s.neverPrompt {
return false
}
return s.IsStdinTTY() && s.IsStdoutTTY()
}
func (s *IOStreams) IsSSHSession() bool {
_, hasClient := os.LookupEnv("SSH_CLIENT")
_, hasTTY := os.LookupEnv("SSH_TTY")
return hasClient || hasTTY
}
func isTerminal(f *os.File) bool {
return isatty.IsTerminal(f.Fd()) || isatty.IsCygwinTerminal(f.Fd())
}
// System creates an IOStreams using the standard system streams
func System() *IOStreams {
stdoutIsTTY := isTerminal(os.Stdout)
stderrIsTTY := isTerminal(os.Stderr)
ioStreams := &IOStreams{
In: os.Stdin,
originalOut: os.Stdout,
Out: color.Output,
ErrOut: color.Error,
}
// prevent duplicate isTerminal queries now that we know the answer
ioStreams.SetStdoutTTY(stdoutIsTTY)
ioStreams.SetStderrTTY(stderrIsTTY)
return ioStreams
}