Skip to content

Commit

Permalink
Check stdout is a tty before using terminal features
Browse files Browse the repository at this point in the history
The implementation only checked if stderr was a tty. This lead to escape
codes in output when piped from stdout. For example, this had ANSI
codes show up in `less`:

    $ rustup component list | less

while this did not:

    $ rustup component list 2>&1 | less

even though no output went to stderr.
  • Loading branch information
kamalmarhubi committed Oct 24, 2016
1 parent d4d4922 commit 6c2203d
Showing 1 changed file with 25 additions and 8 deletions.
33 changes: 25 additions & 8 deletions src/rustup-cli/term2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,24 @@ impl Instantiable for io::Stderr {
fn instance() -> Self { io::stderr() }
}

pub struct Terminal<T: Instantiable + io::Write>(Option<Box<term::Terminal<Output = T> + Send>>);
pub trait Isatty {
fn isatty() -> bool;
}

impl Isatty for io::Stdout {
fn isatty() -> bool {
tty::stdout_isatty()
}
}

impl Isatty for io::Stderr {
fn isatty() -> bool {
tty::stderr_isatty()
}
}

pub struct Terminal<T>(Option<Box<term::Terminal<Output = T> + Send>>)
where T: Instantiable + Isatty + io::Write;
pub type StdoutTerminal = Terminal<io::Stdout>;
pub type StderrTerminal = Terminal<io::Stderr>;

Expand Down Expand Up @@ -114,12 +131,12 @@ impl<'a, T: io::Write + 'a> LineWrapper<'a, T> {
}

// Handles the formatting of text
struct LineFormatter<'a, T: Instantiable + io::Write + 'a> {
struct LineFormatter<'a, T: Instantiable + Isatty + io::Write + 'a> {
wrapper: LineWrapper<'a, Terminal<T>>,
attrs: Vec<Attr>
}

impl<'a, T: Instantiable + io::Write + 'a> LineFormatter<'a, T> {
impl<'a, T: Instantiable + Isatty + io::Write + 'a> LineFormatter<'a, T> {
fn new(w: &'a mut Terminal<T>, indent: u32, margin: u32) -> Self {
LineFormatter {
wrapper: LineWrapper::new(w, indent, margin),
Expand Down Expand Up @@ -205,7 +222,7 @@ impl<'a, T: Instantiable + io::Write + 'a> LineFormatter<'a, T> {
}
}

impl<T: Instantiable + io::Write> io::Write for Terminal<T> {
impl<T: Instantiable + Isatty + io::Write> io::Write for Terminal<T> {
fn write(&mut self, buf: &[u8]) -> Result<usize, io::Error> {
if let Some(ref mut t) = self.0 {
t.write(buf)
Expand All @@ -225,9 +242,9 @@ impl<T: Instantiable + io::Write> io::Write for Terminal<T> {
}
}

impl<T: Instantiable + io::Write> Terminal<T> {
impl<T: Instantiable + Isatty + io::Write> Terminal<T> {
pub fn fg(&mut self, color: color::Color) -> Result<(), term::Error> {
if !tty::stderr_isatty() { return Ok(()) }
if !T::isatty() { return Ok(()) }

if let Some(ref mut t) = self.0 {
t.fg(color)
Expand All @@ -237,7 +254,7 @@ impl<T: Instantiable + io::Write> Terminal<T> {
}

pub fn attr(&mut self, attr: Attr) -> Result<(), term::Error> {
if !tty::stderr_isatty() { return Ok(()) }
if !T::isatty() { return Ok(()) }

if let Some(ref mut t) = self.0 {
if let Err(e) = t.attr(attr) {
Expand All @@ -255,7 +272,7 @@ impl<T: Instantiable + io::Write> Terminal<T> {
}

pub fn reset(&mut self) -> Result<(), term::Error> {
if !tty::stderr_isatty() { return Ok(()) }
if !T::isatty() { return Ok(()) }

if let Some(ref mut t) = self.0 {
t.reset()
Expand Down

0 comments on commit 6c2203d

Please sign in to comment.