]> git.lizzy.rs Git - rust.git/commitdiff
libextra: Remove @mut from term.
authorLuqman Aden <laden@csclub.uwaterloo.ca>
Sun, 24 Nov 2013 11:53:08 +0000 (06:53 -0500)
committerLuqman Aden <laden@csclub.uwaterloo.ca>
Sun, 24 Nov 2013 23:22:50 +0000 (18:22 -0500)
src/libextra/term.rs
src/libextra/test.rs
src/librustpkg/messages.rs
src/libsyntax/diagnostic.rs

index 05c6a366807369bdfd5a0969476ab21134ca4459..4eac6eada22c5dc0557ead52142a74af5d92fcf1 100644 (file)
@@ -13,7 +13,7 @@
 #[allow(missing_doc)];
 
 
-use std::io;
+use std::io::{Decorator, Writer};
 
 #[cfg(not(target_os = "win32"))] use std::os;
 #[cfg(not(target_os = "win32"))] use terminfo::*;
@@ -94,21 +94,21 @@ fn cap_for_attr(attr: attr::Attr) -> &'static str {
 }
 
 #[cfg(not(target_os = "win32"))]
-pub struct Terminal {
+pub struct Terminal<T> {
     priv num_colors: u16,
-    priv out: @mut io::Writer,
+    priv out: T,
     priv ti: ~TermInfo
 }
 
 #[cfg(target_os = "win32")]
-pub struct Terminal {
+pub struct Terminal<T> {
     priv num_colors: u16,
-    priv out: @mut io::Writer,
+    priv out: T,
 }
 
 #[cfg(not(target_os = "win32"))]
-impl Terminal {
-    pub fn new(out: @mut io::Writer) -> Result<Terminal, ~str> {
+impl<T: Writer> Terminal<T> {
+    pub fn new(out: T) -> Result<Terminal<T>, ~str> {
         let term = os::getenv("TERM");
         if term.is_none() {
             return Err(~"TERM environment variable undefined");
@@ -138,7 +138,7 @@ pub fn new(out: @mut io::Writer) -> Result<Terminal, ~str> {
     /// the corresponding normal color will be used instead.
     ///
     /// Returns true if the color was set, false otherwise.
-    pub fn fg(&self, color: color::Color) -> bool {
+    pub fn fg(&mut self, color: color::Color) -> bool {
         let color = self.dim_if_necessary(color);
         if self.num_colors > color {
             let s = expand(*self.ti.strings.find_equiv(&("setaf")).unwrap(),
@@ -158,7 +158,7 @@ pub fn fg(&self, color: color::Color) -> bool {
     /// the corresponding normal color will be used instead.
     ///
     /// Returns true if the color was set, false otherwise.
-    pub fn bg(&self, color: color::Color) -> bool {
+    pub fn bg(&mut self, color: color::Color) -> bool {
         let color = self.dim_if_necessary(color);
         if self.num_colors > color {
             let s = expand(*self.ti.strings.find_equiv(&("setab")).unwrap(),
@@ -175,7 +175,7 @@ pub fn bg(&self, color: color::Color) -> bool {
 
     /// Sets the given terminal attribute, if supported.
     /// Returns true if the attribute was supported, false otherwise.
-    pub fn attr(&self, attr: attr::Attr) -> bool {
+    pub fn attr(&mut self, attr: attr::Attr) -> bool {
         match attr {
             attr::ForegroundColor(c) => self.fg(c),
             attr::BackgroundColor(c) => self.bg(c),
@@ -210,7 +210,7 @@ pub fn supports_attr(&self, attr: attr::Attr) -> bool {
     }
 
     /// Resets all terminal attributes and color to the default.
-    pub fn reset(&self) {
+    pub fn reset(&mut self) {
         let mut cap = self.ti.strings.find_equiv(&("sgr0"));
         if cap.is_none() {
             // are there any terminals that have color/attrs and not sgr0?
@@ -242,20 +242,20 @@ fn dim_if_necessary(&self, color: color::Color) -> color::Color {
 }
 
 #[cfg(target_os = "win32")]
-impl Terminal {
-    pub fn new(out: @mut io::Writer) -> Result<Terminal, ~str> {
+impl<T: Writer> Terminal<T> {
+    pub fn new(out: T) -> Result<Terminal<T>, ~str> {
         return Ok(Terminal {out: out, num_colors: 0});
     }
 
-    pub fn fg(&self, _color: color::Color) -> bool {
+    pub fn fg(&mut self, _color: color::Color) -> bool {
         false
     }
 
-    pub fn bg(&self, _color: color::Color) -> bool {
+    pub fn bg(&mut self, _color: color::Color) -> bool {
         false
     }
 
-    pub fn attr(&self, _attr: attr::Attr) -> bool {
+    pub fn attr(&mut self, _attr: attr::Attr) -> bool {
         false
     }
 
@@ -266,3 +266,27 @@ pub fn supports_attr(&self, _attr: attr::Attr) -> bool {
     pub fn reset(&self) {
     }
 }
+
+impl<T: Writer> Decorator<T> for Terminal<T> {
+    fn inner(self) -> T {
+        self.out
+    }
+
+    fn inner_ref<'a>(&'a self) -> &'a T {
+        &self.out
+    }
+
+    fn inner_mut_ref<'a>(&'a mut self) -> &'a mut T {
+        &mut self.out
+    }
+}
+
+impl<T: Writer> Writer for Terminal<T> {
+    fn write(&mut self, buf: &[u8]) {
+        self.out.write(buf);
+    }
+
+    fn flush(&mut self) {
+        self.out.flush();
+    }
+}
index e9f38471d48629db0d0a632e47816e626cb21da9..b346129d7592f4a392f835d3376e88f9e535a3a9 100644 (file)
@@ -32,6 +32,8 @@
 use std::comm::{stream, SharedChan, GenericPort, GenericChan};
 use std::io;
 use std::io::File;
+use std::io::Writer;
+use std::io::stdio::StdWriter;
 use std::task;
 use std::to_str::ToStr;
 use std::f64;
@@ -338,10 +340,9 @@ pub enum TestResult {
     TrBench(BenchSamples),
 }
 
-struct ConsoleTestState {
-    out: @mut io::Writer,
-    log_out: Option<@mut io::Writer>,
-    term: Option<term::Terminal>,
+struct ConsoleTestState<T> {
+    log_out: Option<File>,
+    out: Either<term::Terminal<T>, T>,
     use_color: bool,
     total: uint,
     passed: uint,
@@ -353,22 +354,20 @@ struct ConsoleTestState {
     max_name_len: uint, // number of columns to fill when aligning names
 }
 
-impl ConsoleTestState {
-    pub fn new(opts: &TestOpts) -> ConsoleTestState {
+impl<T: Writer> ConsoleTestState<T> {
+    pub fn new(opts: &TestOpts, _: Option<T>) -> ConsoleTestState<StdWriter> {
         let log_out = match opts.logfile {
-            Some(ref path) => Some(@mut File::create(path) as @mut io::Writer),
+            Some(ref path) => File::create(path),
             None => None
         };
-        let out = @mut io::stdio::stdout() as @mut io::Writer;
-        let term = match term::Terminal::new(out) {
-            Err(_) => None,
-            Ok(t) => Some(t)
+        let out = match term::Terminal::new(io::stdout()) {
+            Err(_) => Right(io::stdout()),
+            Ok(t) => Left(t)
         };
         ConsoleTestState {
             out: out,
             log_out: log_out,
             use_color: use_color(),
-            term: term,
             total: 0u,
             passed: 0u,
             failed: 0u,
@@ -380,115 +379,123 @@ pub fn new(opts: &TestOpts) -> ConsoleTestState {
         }
     }
 
-    pub fn write_ok(&self) {
+    pub fn write_ok(&mut self) {
         self.write_pretty("ok", term::color::GREEN);
     }
 
-    pub fn write_failed(&self) {
+    pub fn write_failed(&mut self) {
         self.write_pretty("FAILED", term::color::RED);
     }
 
-    pub fn write_ignored(&self) {
+    pub fn write_ignored(&mut self) {
         self.write_pretty("ignored", term::color::YELLOW);
     }
 
-    pub fn write_metric(&self) {
+    pub fn write_metric(&mut self) {
         self.write_pretty("metric", term::color::CYAN);
     }
 
-    pub fn write_bench(&self) {
+    pub fn write_bench(&mut self) {
         self.write_pretty("bench", term::color::CYAN);
     }
 
-    pub fn write_added(&self) {
+    pub fn write_added(&mut self) {
         self.write_pretty("added", term::color::GREEN);
     }
 
-    pub fn write_improved(&self) {
+    pub fn write_improved(&mut self) {
         self.write_pretty("improved", term::color::GREEN);
     }
 
-    pub fn write_removed(&self) {
+    pub fn write_removed(&mut self) {
         self.write_pretty("removed", term::color::YELLOW);
     }
 
-    pub fn write_regressed(&self) {
+    pub fn write_regressed(&mut self) {
         self.write_pretty("regressed", term::color::RED);
     }
 
-    pub fn write_pretty(&self,
+    pub fn write_pretty(&mut self,
                         word: &str,
                         color: term::color::Color) {
-        match self.term {
-            None => self.out.write(word.as_bytes()),
-            Some(ref t) => {
+        match self.out {
+            Left(ref mut term) => {
                 if self.use_color {
-                    t.fg(color);
+                    term.fg(color);
                 }
-                self.out.write(word.as_bytes());
+                term.write(word.as_bytes());
                 if self.use_color {
-                    t.reset();
+                    term.reset();
                 }
             }
+            Right(ref mut stdout) => stdout.write(word.as_bytes())
+        }
+    }
+
+    pub fn write_plain(&mut self, s: &str) {
+        match self.out {
+            Left(ref mut term) => term.write(s.as_bytes()),
+            Right(ref mut stdout) => stdout.write(s.as_bytes())
         }
     }
 
     pub fn write_run_start(&mut self, len: uint) {
         self.total = len;
         let noun = if len != 1 { &"tests" } else { &"test" };
-        write!(self.out, "\nrunning {} {}\n", len, noun);
+        self.write_plain(format!("\nrunning {} {}\n", len, noun));
     }
 
-    pub fn write_test_start(&self, test: &TestDesc, align: NamePadding) {
+    pub fn write_test_start(&mut self, test: &TestDesc, align: NamePadding) {
         let name = test.padded_name(self.max_name_len, align);
-        write!(self.out, "test {} ... ", name);
+        self.write_plain(format!("test {} ... ", name));
     }
 
-    pub fn write_result(&self, result: &TestResult) {
+    pub fn write_result(&mut self, result: &TestResult) {
         match *result {
             TrOk => self.write_ok(),
             TrFailed => self.write_failed(),
             TrIgnored => self.write_ignored(),
             TrMetrics(ref mm) => {
                 self.write_metric();
-                write!(self.out, ": {}", fmt_metrics(mm));
+                self.write_plain(format!(": {}", fmt_metrics(mm)));
             }
             TrBench(ref bs) => {
                 self.write_bench();
-                write!(self.out, ": {}", fmt_bench_samples(bs));
+                self.write_plain(format!(": {}", fmt_bench_samples(bs)));
             }
         }
-        write!(self.out, "\n");
+        self.write_plain("\n");
     }
 
-    pub fn write_log(&self, test: &TestDesc, result: &TestResult) {
+    pub fn write_log(&mut self, test: &TestDesc, result: &TestResult) {
         match self.log_out {
             None => (),
-            Some(out) => {
-                write!(out, "{} {}",match *result {
-                                        TrOk => ~"ok",
-                                        TrFailed => ~"failed",
-                                        TrIgnored => ~"ignored",
-                                        TrMetrics(ref mm) => fmt_metrics(mm),
-                                        TrBench(ref bs) => fmt_bench_samples(bs)
-                                    }, test.name.to_str());
+            Some(ref mut o) => {
+                let s = format!("{} {}", match *result {
+                        TrOk => ~"ok",
+                        TrFailed => ~"failed",
+                        TrIgnored => ~"ignored",
+                        TrMetrics(ref mm) => fmt_metrics(mm),
+                        TrBench(ref bs) => fmt_bench_samples(bs)
+                    }, test.name.to_str());
+                o.write(s.as_bytes());
             }
         }
     }
 
-    pub fn write_failures(&self) {
-        write!(self.out, "\nfailures:\n");
+    pub fn write_failures(&mut self) {
+        self.write_plain("\nfailures:\n");
         let mut failures = ~[];
         for f in self.failures.iter() {
             failures.push(f.name.to_str());
         }
         sort::tim_sort(failures);
         for name in failures.iter() {
-            writeln!(self.out, "    {}", name.to_str());
+            self.write_plain(format!("    {}\n", name.to_str()));
         }
     }
 
-    pub fn write_metric_diff(&self, diff: &MetricDiff) {
+    pub fn write_metric_diff(&mut self, diff: &MetricDiff) {
         let mut noise = 0;
         let mut improved = 0;
         let mut regressed = 0;
@@ -501,38 +508,38 @@ pub fn write_metric_diff(&self, diff: &MetricDiff) {
                 MetricAdded => {
                     added += 1;
                     self.write_added();
-                    writeln!(self.out, ": {}", *k);
+                    self.write_plain(format!(": {}\n", *k));
                 }
                 MetricRemoved => {
                     removed += 1;
                     self.write_removed();
-                    writeln!(self.out, ": {}", *k);
+                    self.write_plain(format!(": {}\n", *k));
                 }
                 Improvement(pct) => {
                     improved += 1;
-                    write!(self.out, "{}: ", *k);
+                    self.write_plain(format!(": {}", *k));
                     self.write_improved();
-                    writeln!(self.out, " by {:.2f}%", pct as f64);
+                    self.write_plain(format!(" by {:.2f}%\n", pct as f64));
                 }
                 Regression(pct) => {
                     regressed += 1;
-                    write!(self.out, "{}: ", *k);
+                    self.write_plain(format!(": {}", *k));
                     self.write_regressed();
-                    writeln!(self.out, " by {:.2f}%", pct as f64);
+                    self.write_plain(format!(" by {:.2f}%\n", pct as f64));
                 }
             }
         }
-        writeln!(self.out, "result of ratchet: {} matrics added, {} removed, \
-                            {} improved, {} regressed, {} noise",
-                            added, removed, improved, regressed, noise);
+        self.write_plain(format!("result of ratchet: {} matrics added, {} removed, \
+                                  {} improved, {} regressed, {} noise\n",
+                                 added, removed, improved, regressed, noise));
         if regressed == 0 {
-            writeln!(self.out, "updated ratchet file");
+            self.write_plain("updated ratchet file\n");
         } else {
-            writeln!(self.out, "left ratchet file untouched");
+            self.write_plain("left ratchet file untouched\n");
         }
     }
 
-    pub fn write_run_finish(&self,
+    pub fn write_run_finish(&mut self,
                             ratchet_metrics: &Option<Path>,
                             ratchet_pct: Option<f64>) -> bool {
         assert!(self.passed + self.failed + self.ignored + self.measured == self.total);
@@ -540,12 +547,12 @@ pub fn write_run_finish(&self,
         let ratchet_success = match *ratchet_metrics {
             None => true,
             Some(ref pth) => {
-                write!(self.out, "\nusing metrics ratcher: {}\n", pth.display());
+                self.write_plain(format!("\nusing metrics ratcher: {}\n", pth.display()));
                 match ratchet_pct {
                     None => (),
                     Some(pct) =>
-                        writeln!(self.out, "with noise-tolerance forced to: {}%",
-                                 pct)
+                        self.write_plain(format!("with noise-tolerance forced to: {}%\n",
+                                                 pct))
                 }
                 let (diff, ok) = self.metrics.ratchet(pth, ratchet_pct);
                 self.write_metric_diff(&diff);
@@ -560,15 +567,16 @@ pub fn write_run_finish(&self,
 
         let success = ratchet_success && test_success;
 
-        write!(self.out, "\ntest result: ");
+        self.write_plain("\ntest result: ");
         if success {
             // There's no parallelism at this point so it's safe to use color
             self.write_ok();
         } else {
             self.write_failed();
         }
-        write!(self.out, ". {} passed; {} failed; {} ignored; {} measured\n\n",
-               self.passed, self.failed, self.ignored, self.measured);
+        let s = format!(". {} passed; {} failed; {} ignored; {} measured\n\n",
+                        self.passed, self.failed, self.ignored, self.measured);
+        self.write_plain(s);
         return success;
     }
 }
@@ -599,7 +607,7 @@ pub fn fmt_bench_samples(bs: &BenchSamples) -> ~str {
 // A simple console test runner
 pub fn run_tests_console(opts: &TestOpts,
                          tests: ~[TestDescAndFn]) -> bool {
-    fn callback(event: &TestEvent, st: &mut ConsoleTestState) {
+    fn callback<T: Writer>(event: &TestEvent, st: &mut ConsoleTestState<T>) {
         debug!("callback(event={:?})", event);
         match (*event).clone() {
             TeFiltered(ref filtered_tests) => st.write_run_start(filtered_tests.len()),
@@ -632,7 +640,7 @@ fn callback(event: &TestEvent, st: &mut ConsoleTestState) {
             }
         }
     }
-    let st = @mut ConsoleTestState::new(opts);
+    let mut st = ConsoleTestState::new(opts, None::<StdWriter>);
     fn len_if_padded(t: &TestDescAndFn) -> uint {
         match t.testfn.padding() {
             PadNone => 0u,
@@ -647,12 +655,12 @@ fn len_if_padded(t: &TestDescAndFn) -> uint {
         },
         None => {}
     }
-    run_tests(opts, tests, |x| callback(&x, st));
+    run_tests(opts, tests, |x| callback(&x, &mut st));
     match opts.save_metrics {
         None => (),
         Some(ref pth) => {
             st.metrics.save(pth);
-            write!(st.out, "\nmetrics saved to: {}", pth.display());
+            st.write_plain(format!("\nmetrics saved to: {}", pth.display()));
         }
     }
     return st.write_run_finish(&opts.ratchet_metrics, opts.ratchet_noise_percent);
@@ -660,13 +668,11 @@ fn len_if_padded(t: &TestDescAndFn) -> uint {
 
 #[test]
 fn should_sort_failures_before_printing_them() {
-    use std::io;
     use std::io::Decorator;
     use std::io::mem::MemWriter;
     use std::str;
     fn dummy() {}
 
-    let m = @mut MemWriter::new();
     let test_a = TestDesc {
         name: StaticTestName("a"),
         ignore: false,
@@ -679,10 +685,9 @@ fn dummy() {}
         should_fail: false
     };
 
-    let st = @ConsoleTestState {
-        out: m as @mut io::Writer,
+    let mut st = ConsoleTestState {
         log_out: None,
-        term: None,
+        out: Right(MemWriter::new()),
         use_color: false,
         total: 0u,
         passed: 0u,
@@ -695,7 +700,10 @@ fn dummy() {}
     };
 
     st.write_failures();
-    let s = str::from_utf8(*m.inner_ref());
+    let s = match st.out {
+        Right(ref m) => str::from_utf8(*m.inner_ref()),
+        Left(_) => unreachable!()
+    };
 
     let apos = s.find_str("a").unwrap();
     let bpos = s.find_str("b").unwrap();
index ae9e0e62661f88bb812271fb96f529b796757cc6..dbd0ee80f2875bf257fc8610aaeef973ebfc0afe 100644 (file)
 use std::io;
 
 pub fn note(msg: &str) {
-    pretty_message(msg, "note: ", term::color::GREEN,
-                   @mut io::stdout() as @mut io::Writer)
+    pretty_message(msg, "note: ", term::color::GREEN);
 }
 
 pub fn warn(msg: &str) {
-    pretty_message(msg, "warning: ", term::color::YELLOW,
-                   @mut io::stdout() as @mut io::Writer)
+    pretty_message(msg, "warning: ", term::color::YELLOW);
 }
 
 pub fn error(msg: &str) {
-    pretty_message(msg, "error: ", term::color::RED,
-                   @mut io::stdout() as @mut io::Writer)
+    pretty_message(msg, "error: ", term::color::RED);
 }
 
 fn pretty_message<'a>(msg: &'a str,
                       prefix: &'a str,
-                      color: term::color::Color,
-                      out: @mut io::Writer) {
-    let term = term::Terminal::new(out);
+                      color: term::color::Color) {
+    let mut term = term::Terminal::new(io::stdout());
+    let mut stdout = io::stdout();
     match term {
-        Ok(ref t) => {
+        Ok(ref mut t) => {
             t.fg(color);
-            out.write(prefix.as_bytes());
+            t.write(prefix.as_bytes());
             t.reset();
         },
         _ => {
-            out.write(prefix.as_bytes());
+            stdout.write(prefix.as_bytes());
         }
     }
-    out.write(msg.as_bytes());
-    out.write(['\n' as u8]);
+    stdout.write(msg.as_bytes());
+    stdout.write(['\n' as u8]);
 }
index 15b827306294980ea1d60cb63ae2416cadad4524..bb908919678b8f110dacf471af80af79463190dd 100644 (file)
@@ -12,6 +12,7 @@
 use codemap;
 
 use std::io;
+use std::io::stdio::StdWriter;
 use std::local_data;
 use extra::term;
 
@@ -197,38 +198,44 @@ fn diagnosticcolor(lvl: level) -> term::color::Color {
 }
 
 fn print_maybe_styled(msg: &str, color: term::attr::Attr) {
-    local_data_key!(tls_terminal: @Option<term::Terminal>)
+    local_data_key!(tls_terminal: ~Option<term::Terminal<StdWriter>>)
 
-    let stderr = @mut io::stderr() as @mut io::Writer;
     fn is_stderr_screen() -> bool {
         use std::libc;
         unsafe { libc::isatty(libc::STDERR_FILENO) != 0 }
     }
+    fn write_pretty<T: Writer>(term: &mut term::Terminal<T>, s: &str, c: term::attr::Attr) {
+        term.attr(c);
+        term.write(s.as_bytes());
+        term.reset();
+    }
 
     if is_stderr_screen() {
-        let t = match local_data::get(tls_terminal, |v| v.map(|k| *k)) {
-            None => {
-                let t = term::Terminal::new(stderr);
-                let tls = @match t {
-                    Ok(t) => Some(t),
-                    Err(_) => None
-                };
-                local_data::set(tls_terminal, tls);
-                &*tls
+        local_data::get_mut(tls_terminal, |term| {
+            match term {
+                Some(term) => {
+                    match **term {
+                        Some(ref mut term) => write_pretty(term, msg, color),
+                        None => io::stderr().write(msg.as_bytes())
+                    }
+                }
+                None => {
+                    let t = ~match term::Terminal::new(io::stderr()) {
+                        Ok(mut term) => {
+                            write_pretty(&mut term, msg, color);
+                            Some(term)
+                        }
+                        Err(_) => {
+                            io::stderr().write(msg.as_bytes());
+                            None
+                        }
+                    };
+                    local_data::set(tls_terminal, t);
+                }
             }
-            Some(tls) => &*tls
-        };
-
-        match t {
-            &Some(ref term) => {
-                term.attr(color);
-                write!(stderr, "{}", msg);
-                term.reset();
-            },
-            _ => write!(stderr, "{}", msg)
-        }
+        });
     } else {
-        write!(stderr, "{}", msg);
+        io::stderr().write(msg.as_bytes());
     }
 }