1use std::io::{self, IsTerminal};
2
3use termcolor::HyperlinkSpec;
4
5#[derive(Debug)]
7pub struct StandardStream(StandardStreamKind);
8
9pub fn stdout(color_choice: termcolor::ColorChoice) -> StandardStream {
24    if std::io::stdout().is_terminal() {
25        stdout_buffered_line(color_choice)
26    } else {
27        stdout_buffered_block(color_choice)
28    }
29}
30
31pub fn stdout_buffered_line(
40    color_choice: termcolor::ColorChoice,
41) -> StandardStream {
42    let out = termcolor::StandardStream::stdout(color_choice);
43    StandardStream(StandardStreamKind::LineBuffered(out))
44}
45
46pub fn stdout_buffered_block(
55    color_choice: termcolor::ColorChoice,
56) -> StandardStream {
57    let out = termcolor::BufferedStandardStream::stdout(color_choice);
58    StandardStream(StandardStreamKind::BlockBuffered(out))
59}
60
61#[derive(Debug)]
62enum StandardStreamKind {
63    LineBuffered(termcolor::StandardStream),
64    BlockBuffered(termcolor::BufferedStandardStream),
65}
66
67impl io::Write for StandardStream {
68    #[inline]
69    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
70        use self::StandardStreamKind::*;
71
72        match self.0 {
73            LineBuffered(ref mut w) => w.write(buf),
74            BlockBuffered(ref mut w) => w.write(buf),
75        }
76    }
77
78    #[inline]
79    fn flush(&mut self) -> io::Result<()> {
80        use self::StandardStreamKind::*;
81
82        match self.0 {
83            LineBuffered(ref mut w) => w.flush(),
84            BlockBuffered(ref mut w) => w.flush(),
85        }
86    }
87}
88
89impl termcolor::WriteColor for StandardStream {
90    #[inline]
91    fn supports_color(&self) -> bool {
92        use self::StandardStreamKind::*;
93
94        match self.0 {
95            LineBuffered(ref w) => w.supports_color(),
96            BlockBuffered(ref w) => w.supports_color(),
97        }
98    }
99
100    #[inline]
101    fn supports_hyperlinks(&self) -> bool {
102        use self::StandardStreamKind::*;
103
104        match self.0 {
105            LineBuffered(ref w) => w.supports_hyperlinks(),
106            BlockBuffered(ref w) => w.supports_hyperlinks(),
107        }
108    }
109
110    #[inline]
111    fn set_color(&mut self, spec: &termcolor::ColorSpec) -> io::Result<()> {
112        use self::StandardStreamKind::*;
113
114        match self.0 {
115            LineBuffered(ref mut w) => w.set_color(spec),
116            BlockBuffered(ref mut w) => w.set_color(spec),
117        }
118    }
119
120    #[inline]
121    fn set_hyperlink(&mut self, link: &HyperlinkSpec) -> io::Result<()> {
122        use self::StandardStreamKind::*;
123
124        match self.0 {
125            LineBuffered(ref mut w) => w.set_hyperlink(link),
126            BlockBuffered(ref mut w) => w.set_hyperlink(link),
127        }
128    }
129
130    #[inline]
131    fn reset(&mut self) -> io::Result<()> {
132        use self::StandardStreamKind::*;
133
134        match self.0 {
135            LineBuffered(ref mut w) => w.reset(),
136            BlockBuffered(ref mut w) => w.reset(),
137        }
138    }
139
140    #[inline]
141    fn is_synchronous(&self) -> bool {
142        use self::StandardStreamKind::*;
143
144        match self.0 {
145            LineBuffered(ref w) => w.is_synchronous(),
146            BlockBuffered(ref w) => w.is_synchronous(),
147        }
148    }
149}