From 30250d3de8d730d977d157f92e5671c87df855ab Mon Sep 17 00:00:00 2001 From: Corey Richardson Date: Fri, 4 Apr 2014 07:47:16 -0400 Subject: [PATCH 01/15] flate: add documentation --- src/libflate/lib.rs | 46 +++++++++++++++++++++++++-------------------- 1 file changed, 26 insertions(+), 20 deletions(-) diff --git a/src/libflate/lib.rs b/src/libflate/lib.rs index 391dd01e80812..03050794d212c 100644 --- a/src/libflate/lib.rs +++ b/src/libflate/lib.rs @@ -10,7 +10,11 @@ /*! -Simple compression +Simple [DEFLATE][def]-based compression. This is a wrapper around the +[`miniz`][mz] library, which is a one-file pure-C implementation of zlib. + +[def]: https://en.wikipedia.org/wiki/DEFLATE +[mz]: https://code.google.com/p/miniz/ */ @@ -31,23 +35,21 @@ extern crate libc; use std::c_vec::CVec; use libc::{c_void, size_t, c_int}; - -pub mod rustrt { - use libc::{c_void, size_t, c_int}; - #[link(name = "miniz", kind = "static")] - extern { - pub fn tdefl_compress_mem_to_heap(psrc_buf: *c_void, - src_buf_len: size_t, - pout_len: *mut size_t, - flags: c_int) - -> *mut c_void; - - pub fn tinfl_decompress_mem_to_heap(psrc_buf: *c_void, - src_buf_len: size_t, - pout_len: *mut size_t, - flags: c_int) - -> *mut c_void; - } +#[link(name = "miniz", kind = "static")] +extern { + /// Raw miniz compression function. + fn tdefl_compress_mem_to_heap(psrc_buf: *c_void, + src_buf_len: size_t, + pout_len: *mut size_t, + flags: c_int) + -> *mut c_void; + + /// Raw miniz decompression function. + fn tinfl_decompress_mem_to_heap(psrc_buf: *c_void, + src_buf_len: size_t, + pout_len: *mut size_t, + flags: c_int) + -> *mut c_void; } static LZ_NORM : c_int = 0x80; // LZ with 128 probes, "normal" @@ -57,7 +59,7 @@ static TDEFL_WRITE_ZLIB_HEADER : c_int = 0x01000; // write zlib header and adler fn deflate_bytes_internal(bytes: &[u8], flags: c_int) -> Option> { unsafe { let mut outsz : size_t = 0; - let res = rustrt::tdefl_compress_mem_to_heap(bytes.as_ptr() as *c_void, + let res = tdefl_compress_mem_to_heap(bytes.as_ptr() as *c_void, bytes.len() as size_t, &mut outsz, flags); @@ -69,10 +71,12 @@ fn deflate_bytes_internal(bytes: &[u8], flags: c_int) -> Option> { } } +/// Compress a buffer, without writing any sort of header on the output. pub fn deflate_bytes(bytes: &[u8]) -> Option> { deflate_bytes_internal(bytes, LZ_NORM) } +/// Compress a buffer, using a header that zlib can understand. pub fn deflate_bytes_zlib(bytes: &[u8]) -> Option> { deflate_bytes_internal(bytes, LZ_NORM | TDEFL_WRITE_ZLIB_HEADER) } @@ -80,7 +84,7 @@ pub fn deflate_bytes_zlib(bytes: &[u8]) -> Option> { fn inflate_bytes_internal(bytes: &[u8], flags: c_int) -> Option> { unsafe { let mut outsz : size_t = 0; - let res = rustrt::tinfl_decompress_mem_to_heap(bytes.as_ptr() as *c_void, + let res = tinfl_decompress_mem_to_heap(bytes.as_ptr() as *c_void, bytes.len() as size_t, &mut outsz, flags); @@ -92,10 +96,12 @@ fn inflate_bytes_internal(bytes: &[u8], flags: c_int) -> Option> { } } +/// Decompress a buffer, without parsing any sort of header on the input. pub fn inflate_bytes(bytes: &[u8]) -> Option> { inflate_bytes_internal(bytes, 0) } +/// Decompress a buffer that starts with a zlib header. pub fn inflate_bytes_zlib(bytes: &[u8]) -> Option> { inflate_bytes_internal(bytes, TINFL_FLAG_PARSE_ZLIB_HEADER) } From 91fa8e5f2aaad4620928c8669218971da747e4da Mon Sep 17 00:00:00 2001 From: Corey Richardson Date: Fri, 4 Apr 2014 07:57:39 -0400 Subject: [PATCH 02/15] arena: add docs for Arena --- src/libarena/lib.rs | 62 +++++++++++++++++++++++++-------------------- 1 file changed, 34 insertions(+), 28 deletions(-) diff --git a/src/libarena/lib.rs b/src/libarena/lib.rs index 47e9a013e1135..f49bffe06d393 100644 --- a/src/libarena/lib.rs +++ b/src/libarena/lib.rs @@ -14,6 +14,10 @@ //! once, once the arena itself is destroyed. They do not support deallocation //! of individual objects while the arena itself is still alive. The benefit //! of an arena is very fast allocation; just a pointer bump. +//! +//! This crate has two arenas implemented: TypedArena, which is a simpler +//! arena but can only hold objects of a single type, and Arena, which is a +//! more complex, slower Arena which can hold objects of any type. #![crate_id = "arena#0.11.0-pre"] #![crate_type = "rlib"] @@ -56,41 +60,42 @@ impl Chunk { } } -// Arenas are used to quickly allocate objects that share a -// lifetime. The arena uses ~[u8] vectors as a backing store to -// allocate objects from. For each allocated object, the arena stores -// a pointer to the type descriptor followed by the -// object. (Potentially with alignment padding after each of them.) -// When the arena is destroyed, it iterates through all of its chunks, -// and uses the tydesc information to trace through the objects, -// calling the destructors on them. -// One subtle point that needs to be addressed is how to handle -// failures while running the user provided initializer function. It -// is important to not run the destructor on uninitialized objects, but -// how to detect them is somewhat subtle. Since alloc() can be invoked -// recursively, it is not sufficient to simply exclude the most recent -// object. To solve this without requiring extra space, we use the low -// order bit of the tydesc pointer to encode whether the object it -// describes has been fully initialized. - -// As an optimization, objects with destructors are stored in -// different chunks than objects without destructors. This reduces -// overhead when initializing plain-old-data and means we don't need -// to waste time running the destructors of POD. +/// A slower reflection-based arena that can allocate objects of any type. +/// +/// This arena uses Vec as a backing store to allocate objects from. For +/// each allocated object, the arena stores a pointer to the type descriptor +/// followed by the object. (Potentially with alignment padding after each +/// element.) When the arena is destroyed, it iterates through all of its +/// chunks, and uses the tydesc information to trace through the objects, +/// calling the destructors on them. One subtle point that needs to be +/// addressed is how to handle failures while running the user provided +/// initializer function. It is important to not run the destructor on +/// uninitialized objects, but how to detect them is somewhat subtle. Since +/// alloc() can be invoked recursively, it is not sufficient to simply exclude +/// the most recent object. To solve this without requiring extra space, we +/// use the low order bit of the tydesc pointer to encode whether the object +/// it describes has been fully initialized. +/// +/// As an optimization, objects with destructors are stored in +/// different chunks than objects without destructors. This reduces +/// overhead when initializing plain-old-data and means we don't need +/// to waste time running the destructors of POD. pub struct Arena { // The head is separated out from the list as a unbenchmarked - // microoptimization, to avoid needing to case on the list to - // access the head. + // microoptimization, to avoid needing to case on the list to access the + // head. head: Chunk, copy_head: Chunk, chunks: RefCell>, } impl Arena { + /// Allocate a new Arena with 32 bytes preallocated. pub fn new() -> Arena { Arena::new_with_size(32u) } + /// Allocate a new Arena with `initial_size` bytes preallocated. pub fn new_with_size(initial_size: uint) -> Arena { Arena { head: chunk(initial_size, false), @@ -265,7 +270,8 @@ impl Arena { } } - // The external interface + /// Allocate a new item in the arena, using `op` to initialize the value + /// and returning a reference to it. #[inline] pub fn alloc<'a, T>(&'a self, op: || -> T) -> &'a T { unsafe { @@ -313,7 +319,7 @@ fn test_arena_destructors_fail() { }); } -/// An arena that can hold objects of only one type. +/// A faster arena that can hold objects of only one type. /// /// Safety note: Modifying objects in the arena that have already had their /// `drop` destructors run can cause leaks, because the destructor will not @@ -405,13 +411,13 @@ impl TypedArenaChunk { } impl TypedArena { - /// Creates a new arena with preallocated space for 8 objects. + /// Creates a new TypedArena with preallocated space for 8 objects. #[inline] pub fn new() -> TypedArena { TypedArena::with_capacity(8) } - /// Creates a new arena with preallocated space for the given number of + /// Creates a new TypedArena with preallocated space for the given number of /// objects. #[inline] pub fn with_capacity(capacity: uint) -> TypedArena { @@ -423,7 +429,7 @@ impl TypedArena { } } - /// Allocates an object into this arena. + /// Allocates an object in the TypedArena, returning a reference to it. #[inline] pub fn alloc<'a>(&'a self, object: T) -> &'a T { unsafe { From e30198d9d4d4d016949625062bde002bc33aa574 Mon Sep 17 00:00:00 2001 From: Corey Richardson Date: Sat, 5 Apr 2014 01:08:01 -0400 Subject: [PATCH 03/15] num: expand crate documentation + add example --- src/libnum/lib.rs | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/src/libnum/lib.rs b/src/libnum/lib.rs index 20d694d0d0939..54652c9dca33d 100644 --- a/src/libnum/lib.rs +++ b/src/libnum/lib.rs @@ -8,6 +8,40 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +//! Simple numerics. +//! +//! This crate contains arbitrary-sized integer, rational, and complex types. +//! +//! ## Example +//! +//! This example uses the BigRational type and [Newton's method][newt] to +//! approximate a square root to arbitrary precision: +//! +//! ``` +//! extern crate num; +//! +//! use num::bigint::BigInt; +//! use num::rational::{Ratio, BigRational}: +//! +//! fn approx_sqrt(number: u64, iterations: uint) -> BigRational { +//! let start: Ratio = Ratio::from_integer(FromPrimitive::from_u64(number).unwrap()); +//! let mut approx = start.clone(); +//! +//! for _ in range(0, iterations) { +//! approx = (approx + (start / approx)) / +//! Ratio::from_integer(FromPrimitive::from_u64(2).unwrap()); +//! } +//! +//! approx +//! } +//! +//! fn main() { +//! println!("{}", approx_sqrt(10, 4)); // prints 4057691201/1283082416 +//! } +//! ``` +//! +//! [newt]: https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method + #![feature(macro_rules)] #![crate_id = "num#0.11.0-pre"] From f923b93694706730dd8395dec63e949ba441e0d9 Mon Sep 17 00:00:00 2001 From: Corey Richardson Date: Tue, 8 Apr 2014 11:18:10 -0400 Subject: [PATCH 04/15] term: add docs and windows support Closes #2807 --- mk/crates.mk | 2 +- src/libterm/lib.rs | 286 ++++++++++++++---------------------- src/libterm/terminfo/mod.rs | 186 +++++++++++++++++++++++ src/libterm/win.rs | 146 ++++++++++++++++++ 4 files changed, 440 insertions(+), 180 deletions(-) create mode 100644 src/libterm/win.rs diff --git a/mk/crates.mk b/mk/crates.mk index 943cd528fcdc9..895819a5a50c0 100644 --- a/mk/crates.mk +++ b/mk/crates.mk @@ -73,7 +73,7 @@ DEPS_arena := std collections DEPS_graphviz := std DEPS_glob := std DEPS_serialize := std collections log -DEPS_term := std collections +DEPS_term := std collections log DEPS_semver := std DEPS_uuid := std serialize rand DEPS_sync := std diff --git a/src/libterm/lib.rs b/src/libterm/lib.rs index 2d1b938ec3781..8f5452c23f26b 100644 --- a/src/libterm/lib.rs +++ b/src/libterm/lib.rs @@ -8,7 +8,32 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! Simple ANSI color library +//! Terminal formatting library. +//! +//! This crate provides the `Terminal` trait, which abstracts over an [ANSI +//! Termina][ansi] to provide color printing, among other things. There are two implementations, +//! the `TerminfoTerminal`, which uses control characters from a +//! [terminfo][ti] database, and `WinConsole`, which uses the [Win32 Console +//! API][win]. +//! +//! ## Example +//! +//! ```rust +//! extern crate term; +//! +//! fn main() { +//! let mut t = term::stdout(); +//! t.fg(term::color::GREEN); +//! println!("hello, "); +//! t.fg(term::color::RED); +//! println("world!"); +//! t.reset(); +//! } +//! ``` +//! +//! [ansi]: https://en.wikipedia.org/wiki/ANSI_escape_code +//! [win]: http://msdn.microsoft.com/en-us/library/windows/desktop/ms682010%28v=vs.85%29.aspx +//! [ti]: https://en.wikipedia.org/wiki/Terminfo #![crate_id = "term#0.11.0-pre"] #![comment = "Simple ANSI color library"] @@ -19,22 +44,76 @@ html_favicon_url = "http://www.rust-lang.org/favicon.ico", html_root_url = "http://static.rust-lang.org/doc/master")] -#![feature(macro_rules)] +#![feature(macro_rules, phase)] #![deny(missing_doc)] +#[phase(syntax, link)] extern crate log; extern crate collections; -use std::io; -use std::os; -use terminfo::TermInfo; -use terminfo::searcher::open; -use terminfo::parser::compiled::{parse, msys_terminfo}; -use terminfo::parm::{expand, Number, Variables}; +pub use terminfo::TerminfoTerminal; +#[cfg(windows)] +pub use win::WinConsole; + +use std::io::IoResult; pub mod terminfo; -// FIXME (#2807): Windows support. +#[cfg(windows)] +mod win; + +#[cfg(not(windows))] +/// Return a Terminal wrapping stdout, or None if a terminal couldn't be +/// opened. +pub fn stdout() -> Option<~Terminal<~Writer:Send>:Send> { + let ti: Option> + = Terminal::new(~std::io::stdout() as ~Writer:Send); + ti.map(|t| ~t as ~Terminal<~Writer:Send>:Send) +} + +#[cfg(windows)] +/// Return a Terminal wrapping stdout, or None if a terminal couldn't be +/// opened. +pub fn stdout() -> Option<~Terminal<~Writer:Send>:Send> { + let ti: Option> + = Terminal::new(~std::io::stdout() as ~Writer:Send); + + match ti { + Some(t) => Some(~t as ~Terminal<~Writer:Send>:Send), + None => { + let wc: Option> + = Terminal::new(~std::io::stdout() as ~Writer:Send); + wc.map(|w| ~w as ~Terminal<~Writer:Send>:Send) + } + } +} + +#[cfg(not(windows))] +/// Return a Terminal wrapping stderr, or None if a terminal couldn't be +/// opened. +pub fn stderr() -> Option<~Terminal<~Writer:Send>:Send> { + let ti: Option> + = Terminal::new(~std::io::stderr() as ~Writer:Send); + ti.map(|t| ~t as ~Terminal<~Writer:Send>:Send) +} + +#[cfg(windows)] +/// Return a Terminal wrapping stderr, or None if a terminal couldn't be +/// opened. +pub fn stderr() -> Option<~Terminal<~Writer:Send>:Send> { + let ti: Option> + = Terminal::new(~std::io::stderr() as ~Writer:Send); + + match ti { + Some(t) => Some(~t as ~Terminal<~Writer:Send>:Send), + None => { + let wc: Option> + = Terminal::new(~std::io::stderr() as ~Writer:Send); + wc.map(|w| ~w as ~Terminal<~Writer:Send>:Send) + } + } +} + /// Terminal color definitions pub mod color { @@ -91,72 +170,13 @@ pub mod attr { } } -fn cap_for_attr(attr: attr::Attr) -> &'static str { - match attr { - attr::Bold => "bold", - attr::Dim => "dim", - attr::Italic(true) => "sitm", - attr::Italic(false) => "ritm", - attr::Underline(true) => "smul", - attr::Underline(false) => "rmul", - attr::Blink => "blink", - attr::Standout(true) => "smso", - attr::Standout(false) => "rmso", - attr::Reverse => "rev", - attr::Secure => "invis", - attr::ForegroundColor(_) => "setaf", - attr::BackgroundColor(_) => "setab" - } -} - -/// A Terminal that knows how many colors it supports, with a reference to its -/// parsed TermInfo database record. -pub struct Terminal { - num_colors: u16, - out: T, - ti: Box, -} - -impl Terminal { - /// Returns a wrapped output stream (`Terminal`) as a `Result`. - /// - /// Returns `Err()` if the TERM environment variable is undefined. - /// TERM should be set to something like `xterm-color` or `screen-256color`. - /// - /// Returns `Err()` on failure to open the terminfo database correctly. - /// Also, in the event that the individual terminfo database entry can not - /// be parsed. - pub fn new(out: T) -> Result, StrBuf> { - let term = match os::getenv("TERM") { - Some(t) => t, - None => { - return Err("TERM environment variable undefined".to_strbuf()) - } - }; - - let mut file = match open(term) { - Ok(file) => file, - Err(err) => { - if "cygwin" == term { // msys terminal - return Ok(Terminal { - out: out, - ti: msys_terminfo(), - num_colors: 8 - }); - } - return Err(err); - } - }; +/// A terminal with similar capabilities to an ANSI Terminal +/// (foreground/background colors etc). +pub trait Terminal: Writer { + /// Returns `None` whenever the terminal cannot be created for some + /// reason. + fn new(out: T) -> Option; - let inf = try!(parse(&mut file, false)); - - let nc = if inf.strings.find_equiv(&("setaf")).is_some() - && inf.strings.find_equiv(&("setab")).is_some() { - inf.numbers.find_equiv(&("colors")).map_or(0, |&n| n) - } else { 0 }; - - return Ok(Terminal {out: out, ti: inf, num_colors: nc}); - } /// Sets the foreground color to the given color. /// /// If the color is a bright color, but the terminal only supports 8 colors, @@ -164,22 +184,8 @@ impl Terminal { /// /// Returns `Ok(true)` if the color was set, `Ok(false)` otherwise, and `Err(e)` /// if there was an I/O error. - pub fn fg(&mut self, color: color::Color) -> io::IoResult { - let color = self.dim_if_necessary(color); - if self.num_colors > color { - let s = expand(self.ti - .strings - .find_equiv(&("setaf")) - .unwrap() - .as_slice(), - [Number(color as int)], &mut Variables::new()); - if s.is_ok() { - try!(self.out.write(s.unwrap().as_slice())); - return Ok(true) - } - } - Ok(false) - } + fn fg(&mut self, color: color::Color) -> IoResult; + /// Sets the background color to the given color. /// /// If the color is a bright color, but the terminal only supports 8 colors, @@ -187,104 +193,26 @@ impl Terminal { /// /// Returns `Ok(true)` if the color was set, `Ok(false)` otherwise, and `Err(e)` /// if there was an I/O error. - pub fn bg(&mut self, color: color::Color) -> io::IoResult { - let color = self.dim_if_necessary(color); - if self.num_colors > color { - let s = expand(self.ti - .strings - .find_equiv(&("setab")) - .unwrap() - .as_slice(), - [Number(color as int)], &mut Variables::new()); - if s.is_ok() { - try!(self.out.write(s.unwrap().as_slice())); - return Ok(true) - } - } - Ok(false) - } + fn bg(&mut self, color: color::Color) -> IoResult; - /// Sets the given terminal attribute, if supported. - /// Returns `Ok(true)` if the attribute was supported, `Ok(false)` otherwise, - /// and `Err(e)` if there was an I/O error. - pub fn attr(&mut self, attr: attr::Attr) -> io::IoResult { - match attr { - attr::ForegroundColor(c) => self.fg(c), - attr::BackgroundColor(c) => self.bg(c), - _ => { - let cap = cap_for_attr(attr); - let parm = self.ti.strings.find_equiv(&cap); - if parm.is_some() { - let s = expand(parm.unwrap().as_slice(), - [], - &mut Variables::new()); - if s.is_ok() { - try!(self.out.write(s.unwrap().as_slice())); - return Ok(true) - } - } - Ok(false) - } - } - } + /// Sets the given terminal attribute, if supported. Returns `Ok(true)` + /// if the attribute was supported, `Ok(false)` otherwise, and `Err(e)` if + /// there was an I/O error. + fn attr(&mut self, attr: attr::Attr) -> IoResult; /// Returns whether the given terminal attribute is supported. - pub fn supports_attr(&self, attr: attr::Attr) -> bool { - match attr { - attr::ForegroundColor(_) | attr::BackgroundColor(_) => { - self.num_colors > 0 - } - _ => { - let cap = cap_for_attr(attr); - self.ti.strings.find_equiv(&cap).is_some() - } - } - } + fn supports_attr(&self, attr: attr::Attr) -> bool; /// Resets all terminal attributes and color to the default. /// Returns `Ok()`. - pub fn reset(&mut self) -> io::IoResult<()> { - let mut cap = self.ti.strings.find_equiv(&("sgr0")); - if cap.is_none() { - // are there any terminals that have color/attrs and not sgr0? - // Try falling back to sgr, then op - cap = self.ti.strings.find_equiv(&("sgr")); - if cap.is_none() { - cap = self.ti.strings.find_equiv(&("op")); - } - } - let s = cap.map_or(Err("can't find terminfo capability \ - `sgr0`".to_strbuf()), |op| { - expand(op.as_slice(), [], &mut Variables::new()) - }); - if s.is_ok() { - return self.out.write(s.unwrap().as_slice()) - } - Ok(()) - } - - fn dim_if_necessary(&self, color: color::Color) -> color::Color { - if color >= self.num_colors && color >= 8 && color < 16 { - color-8 - } else { color } - } + fn reset(&mut self) -> IoResult<()>; - /// Returns the contained stream - pub fn unwrap(self) -> T { self.out } + /// Returns the contained stream, destroying the `Terminal` + fn unwrap(self) -> T; /// Gets an immutable reference to the stream inside - pub fn get_ref<'a>(&'a self) -> &'a T { &self.out } + fn get_ref<'a>(&'a self) -> &'a T; /// Gets a mutable reference to the stream inside - pub fn get_mut<'a>(&'a mut self) -> &'a mut T { &mut self.out } -} - -impl Writer for Terminal { - fn write(&mut self, buf: &[u8]) -> io::IoResult<()> { - self.out.write(buf) - } - - fn flush(&mut self) -> io::IoResult<()> { - self.out.flush() - } + fn get_mut<'a>(&'a mut self) -> &'a mut T; } diff --git a/src/libterm/terminfo/mod.rs b/src/libterm/terminfo/mod.rs index 46dd397853157..93a7657fae9e4 100644 --- a/src/libterm/terminfo/mod.rs +++ b/src/libterm/terminfo/mod.rs @@ -11,6 +11,16 @@ //! Terminfo database interface. use collections::HashMap; +use std::io::IoResult; +use std::os; + +use attr; +use color; +use Terminal; +use self::searcher::open; +use self::parser::compiled::{parse, msys_terminfo}; +use self::parm::{expand, Number, Variables}; + /// A parsed terminfo database entry. pub struct TermInfo { @@ -32,3 +42,179 @@ pub mod parser { pub mod compiled; } pub mod parm; + + +fn cap_for_attr(attr: attr::Attr) -> &'static str { + match attr { + attr::Bold => "bold", + attr::Dim => "dim", + attr::Italic(true) => "sitm", + attr::Italic(false) => "ritm", + attr::Underline(true) => "smul", + attr::Underline(false) => "rmul", + attr::Blink => "blink", + attr::Standout(true) => "smso", + attr::Standout(false) => "rmso", + attr::Reverse => "rev", + attr::Secure => "invis", + attr::ForegroundColor(_) => "setaf", + attr::BackgroundColor(_) => "setab" + } +} + +/// A Terminal that knows how many colors it supports, with a reference to its +/// parsed Terminfo database record. +pub struct TerminfoTerminal { + num_colors: u16, + out: T, + ti: ~TermInfo +} + +impl Terminal for TerminfoTerminal { + fn new(out: T) -> Option> { + let term = match os::getenv("TERM") { + Some(t) => t, + None => { + debug!("TERM environment variable not defined"); + return None; + } + }; + + let entry = open(term); + if entry.is_err() { + if os::getenv("MSYSCON").map_or(false, |s| "mintty.exe" == s) { + // msys terminal + return Some(TerminfoTerminal {out: out, ti: msys_terminfo(), num_colors: 8}); + } + debug!("error finding terminfo entry: {}", entry.unwrap_err()); + return None; + } + + let mut file = entry.unwrap(); + let ti = parse(&mut file, false); + if ti.is_err() { + debug!("error parsing terminfo entry: {}", ti.unwrap_err()); + return None; + } + + let inf = ti.unwrap(); + let nc = if inf.strings.find_equiv(&("setaf")).is_some() + && inf.strings.find_equiv(&("setab")).is_some() { + inf.numbers.find_equiv(&("colors")).map_or(0, |&n| n) + } else { 0 }; + + return Some(TerminfoTerminal {out: out, ti: inf, num_colors: nc}); + } + + fn fg(&mut self, color: color::Color) -> IoResult { + let color = self.dim_if_necessary(color); + if self.num_colors > color { + let s = expand(self.ti + .strings + .find_equiv(&("setaf")) + .unwrap() + .as_slice(), + [Number(color as int)], &mut Variables::new()); + if s.is_ok() { + try!(self.out.write(s.unwrap().as_slice())); + return Ok(true) + } + } + Ok(false) + } + + fn bg(&mut self, color: color::Color) -> IoResult { + let color = self.dim_if_necessary(color); + if self.num_colors > color { + let s = expand(self.ti + .strings + .find_equiv(&("setab")) + .unwrap() + .as_slice(), + [Number(color as int)], &mut Variables::new()); + if s.is_ok() { + try!(self.out.write(s.unwrap().as_slice())); + return Ok(true) + } + } + Ok(false) + } + + fn attr(&mut self, attr: attr::Attr) -> IoResult { + match attr { + attr::ForegroundColor(c) => self.fg(c), + attr::BackgroundColor(c) => self.bg(c), + _ => { + let cap = cap_for_attr(attr); + let parm = self.ti.strings.find_equiv(&cap); + if parm.is_some() { + let s = expand(parm.unwrap().as_slice(), + [], + &mut Variables::new()); + if s.is_ok() { + try!(self.out.write(s.unwrap().as_slice())); + return Ok(true) + } + } + Ok(false) + } + } + } + + fn supports_attr(&self, attr: attr::Attr) -> bool { + match attr { + attr::ForegroundColor(_) | attr::BackgroundColor(_) => { + self.num_colors > 0 + } + _ => { + let cap = cap_for_attr(attr); + self.ti.strings.find_equiv(&cap).is_some() + } + } + } + + fn reset(&mut self) -> IoResult<()> { + let mut cap = self.ti.strings.find_equiv(&("sgr0")); + if cap.is_none() { + // are there any terminals that have color/attrs and not sgr0? + // Try falling back to sgr, then op + cap = self.ti.strings.find_equiv(&("sgr")); + if cap.is_none() { + cap = self.ti.strings.find_equiv(&("op")); + } + } + let s = cap.map_or(Err(~"can't find terminfo capability `sgr0`"), |op| { + expand(op.as_slice(), [], &mut Variables::new()) + }); + if s.is_ok() { + return self.out.write(s.unwrap().as_slice()) + } + Ok(()) + } + + fn unwrap(self) -> T { self.out } + + fn get_ref<'a>(&'a self) -> &'a T { &self.out } + + fn get_mut<'a>(&'a mut self) -> &'a mut T { &mut self.out } +} + +impl TerminfoTerminal { + fn dim_if_necessary(&self, color: color::Color) -> color::Color { + if color >= self.num_colors && color >= 8 && color < 16 { + color-8 + } else { color } + } +} + + +impl Writer for TerminfoTerminal { + fn write(&mut self, buf: &[u8]) -> IoResult<()> { + self.out.write(buf) + } + + fn flush(&mut self) -> IoResult<()> { + self.out.flush() + } +} + diff --git a/src/libterm/win.rs b/src/libterm/win.rs new file mode 100644 index 0000000000000..063f93cebac46 --- /dev/null +++ b/src/libterm/win.rs @@ -0,0 +1,146 @@ +// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Windows console handling + +// FIXME (#13400): this is only a tiny fraction of the win32 console api + +extern crate libc; + +use std::io::IoResult; + +use attr; +use color; +use Terminal; + +pub struct WinConsole { + buf: T, + foreground: color::Color, + background: color::Color, +} + +#[link(name = "kernel32")] +extern "system" { + fn SetConsoleTextAttribute(handle: libc::HANDLE, attr: libc::WORD) -> libc::BOOL; + fn GetStdHandle(which: libc::DWORD) -> libc::HANDLE; +} + +fn color_to_bits(color: color::Color) -> u16 { + // magic numbers from mingw-w64's wincon.h + + let bits = match color % 8 { + color::BLACK => 0, + color::BLUE => 0x1, + color::GREEN => 0x2, + color::RED => 0x4, + color::YELLOW => 0x2 | 0x4, + color::MAGENTA => 0x1 | 0x4, + color::CYAN => 0x1 | 0x2, + color::WHITE => 0x1 | 0x2 | 0x4, + _ => unreachable!() + }; + + if color >= 8 { + bits | 0x8 + } else { + bits + } +} + +impl WinConsole { + fn apply(&mut self) { + let mut accum: libc::WORD = 0; + accum |= color_to_bits(self.foreground); + accum |= color_to_bits(self.background) << 4; + + unsafe { + // Magic -11 means stdout, from + // http://msdn.microsoft.com/en-us/library/windows/desktop/ms683231%28v=vs.85%29.aspx + // + // You may be wondering, "but what about stderr?", and the answer + // to that is that setting terminal attributes on the stdout + // handle also sets them for stderr, since they go to the same + // terminal! Admittedly, this is fragile, since stderr could be + // redirected to a different console. This is good enough for + // rustc though. See #13400. + let out = GetStdHandle(-11); + SetConsoleTextAttribute(out, accum); + } + } +} + +impl Writer for WinConsole { + fn write(&mut self, buf: &[u8]) -> IoResult<()> { + self.buf.write(buf) + } + + fn flush(&mut self) -> IoResult<()> { + self.buf.flush() + } +} + +impl Terminal for WinConsole { + fn new(out: T) -> Option> { + Some(WinConsole { buf: out, foreground: color::WHITE, background: color::BLACK }) + } + + fn fg(&mut self, color: color::Color) -> IoResult { + self.foreground = color; + self.apply(); + + Ok(true) + } + + fn bg(&mut self, color: color::Color) -> IoResult { + self.background = color; + self.apply(); + + Ok(true) + } + + fn attr(&mut self, attr: attr::Attr) -> IoResult { + match attr { + attr::ForegroundColor(f) => { + self.foreground = f; + self.apply(); + Ok(true) + }, + attr::BackgroundColor(b) => { + self.background = b; + self.apply(); + Ok(true) + }, + _ => Ok(false) + } + } + + fn supports_attr(&self, attr: attr::Attr) -> bool { + // it claims support for underscore and reverse video, but I can't get + // it to do anything -cmr + match attr { + attr::ForegroundColor(_) | attr::BackgroundColor(_) => true, + _ => false + } + } + + fn reset(&mut self) -> IoResult<()> { + self.foreground = color::WHITE; + self.background = color::BLACK; + self.apply(); + + Ok(()) + } + + fn unwrap(self) -> T { self.buf } + + fn get_ref<'a>(&'a self) -> &'a T { &self.buf } + + fn get_mut<'a>(&'a mut self) -> &'a mut T { &mut self.buf } +} From e3d0e5e2f29ac419382530c26c2360c1be4a071b Mon Sep 17 00:00:00 2001 From: Corey Richardson Date: Tue, 8 Apr 2014 11:54:54 -0400 Subject: [PATCH 05/15] syntax: update for libterm fallout --- src/libsyntax/diagnostic.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libsyntax/diagnostic.rs b/src/libsyntax/diagnostic.rs index 94132988d972f..4bb33f59f59ad 100644 --- a/src/libsyntax/diagnostic.rs +++ b/src/libsyntax/diagnostic.rs @@ -259,7 +259,7 @@ pub struct EmitterWriter { } enum Destination { - Terminal(term::Terminal), + Terminal(~term::Terminal<~Writer:Send>:Send), Raw(Box), } @@ -274,9 +274,9 @@ impl EmitterWriter { }; if use_color { - let dst = match term::Terminal::new(stderr.unwrap()) { - Ok(t) => Terminal(t), - Err(..) => Raw(box io::stderr()), + let dst = match term::stderr() { + Some(t) => Terminal(t), + None => Raw(box stderr), }; EmitterWriter { dst: dst } } else { From 6ef2169bac46dbf68ec952669bd2b84e2a5bdd46 Mon Sep 17 00:00:00 2001 From: Corey Richardson Date: Tue, 8 Apr 2014 12:04:09 -0400 Subject: [PATCH 06/15] time: crate description --- src/libtime/lib.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/libtime/lib.rs b/src/libtime/lib.rs index 1ffe4d3cbadc4..87a87641fc03b 100644 --- a/src/libtime/lib.rs +++ b/src/libtime/lib.rs @@ -8,7 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +//! Simple time handling. + #![crate_id = "time#0.11.0-pre"] + #![crate_type = "rlib"] #![crate_type = "dylib"] #![license = "MIT/ASL2"] From 7bf1de528396f0f2622ca391da0b03d79a27ee52 Mon Sep 17 00:00:00 2001 From: Corey Richardson Date: Tue, 8 Apr 2014 12:07:23 -0400 Subject: [PATCH 07/15] workcache: add crate doc block --- src/libworkcache/lib.rs | 134 ++++++++++++++++++++-------------------- 1 file changed, 66 insertions(+), 68 deletions(-) diff --git a/src/libworkcache/lib.rs b/src/libworkcache/lib.rs index 98fbb00f4378d..b7386a97b4516 100644 --- a/src/libworkcache/lib.rs +++ b/src/libworkcache/lib.rs @@ -8,6 +8,72 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +//! A simple function caching system. +//! +//! This is a loose clone of the [fbuild build system](https://github.com/felix-lang/fbuild), +//! made a touch more generic (not wired to special cases on files) and much +//! less metaprogram-y due to rust's comparative weakness there, relative to +//! python. +//! +//! It's based around _imperative builds_ that happen to have some function +//! calls cached. That is, it's _just_ a mechanism for describing cached +//! functions. This makes it much simpler and smaller than a "build system" +//! that produces an IR and evaluates it. The evaluation order is normal +//! function calls. Some of them just return really quickly. +//! +//! A cached function consumes and produces a set of _works_. A work has a +//! name, a kind (that determines how the value is to be checked for +//! freshness) and a value. Works must also be (de)serializable. Some +//! examples of works: +//! +//! kind name value +//! ------------------------ +//! cfg os linux +//! file foo.c +//! url foo.com +//! +//! Works are conceptually single units, but we store them most of the time +//! in maps of the form (type,name) => value. These are WorkMaps. +//! +//! A cached function divides the works it's interested in into inputs and +//! outputs, and subdivides those into declared (input) works and +//! discovered (input and output) works. +//! +//! A _declared_ input or is one that is given to the workcache before +//! any work actually happens, in the "prep" phase. Even when a function's +//! work-doing part (the "exec" phase) never gets called, it has declared +//! inputs, which can be checked for freshness (and potentially +//! used to determine that the function can be skipped). +//! +//! The workcache checks _all_ works for freshness, but uses the set of +//! discovered outputs from the _previous_ exec (which it will re-discover +//! and re-record each time the exec phase runs). +//! +//! Therefore the discovered works cached in the db might be a +//! mis-approximation of the current discoverable works, but this is ok for +//! the following reason: we assume that if an artifact A changed from +//! depending on B,C,D to depending on B,C,D,E, then A itself changed (as +//! part of the change-in-dependencies), so we will be ok. +//! +//! Each function has a single discriminated output work called its _result_. +//! This is only different from other works in that it is returned, by value, +//! from a call to the cacheable function; the other output works are used in +//! passing to invalidate dependencies elsewhere in the cache, but do not +//! otherwise escape from a function invocation. Most functions only have one +//! output work anyways. +//! +//! A database (the central store of a workcache) stores a mappings: +//! +//! (fn_name,{declared_input}) => ({discovered_input}, +//! {discovered_output},result) +//! +//! (Note: fbuild, which workcache is based on, has the concept of a declared +//! output as separate from a discovered output. This distinction exists only +//! as an artifact of how fbuild works: via annotations on function types +//! and metaprogramming, with explicit dependency declaration as a fallback. +//! Workcache is more explicit about dependencies, and as such treats all +//! outputs the same, as discovered-during-the-last-run.) + #![crate_id = "workcache#0.11.0-pre"] #![crate_type = "rlib"] #![crate_type = "dylib"] @@ -33,74 +99,6 @@ use std::str; use std::io; use std::io::{File, MemWriter}; -/** -* -* This is a loose clone of the [fbuild build system](https://github.com/felix-lang/fbuild), -* made a touch more generic (not wired to special cases on files) and much -* less metaprogram-y due to rust's comparative weakness there, relative to -* python. -* -* It's based around _imperative builds_ that happen to have some function -* calls cached. That is, it's _just_ a mechanism for describing cached -* functions. This makes it much simpler and smaller than a "build system" -* that produces an IR and evaluates it. The evaluation order is normal -* function calls. Some of them just return really quickly. -* -* A cached function consumes and produces a set of _works_. A work has a -* name, a kind (that determines how the value is to be checked for -* freshness) and a value. Works must also be (de)serializable. Some -* examples of works: -* -* kind name value -* ------------------------ -* cfg os linux -* file foo.c -* url foo.com -* -* Works are conceptually single units, but we store them most of the time -* in maps of the form (type,name) => value. These are WorkMaps. -* -* A cached function divides the works it's interested in into inputs and -* outputs, and subdivides those into declared (input) works and -* discovered (input and output) works. -* -* A _declared_ input or is one that is given to the workcache before -* any work actually happens, in the "prep" phase. Even when a function's -* work-doing part (the "exec" phase) never gets called, it has declared -* inputs, which can be checked for freshness (and potentially -* used to determine that the function can be skipped). -* -* The workcache checks _all_ works for freshness, but uses the set of -* discovered outputs from the _previous_ exec (which it will re-discover -* and re-record each time the exec phase runs). -* -* Therefore the discovered works cached in the db might be a -* mis-approximation of the current discoverable works, but this is ok for -* the following reason: we assume that if an artifact A changed from -* depending on B,C,D to depending on B,C,D,E, then A itself changed (as -* part of the change-in-dependencies), so we will be ok. -* -* Each function has a single discriminated output work called its _result_. -* This is only different from other works in that it is returned, by value, -* from a call to the cacheable function; the other output works are used in -* passing to invalidate dependencies elsewhere in the cache, but do not -* otherwise escape from a function invocation. Most functions only have one -* output work anyways. -* -* A database (the central store of a workcache) stores a mappings: -* -* (fn_name,{declared_input}) => ({discovered_input}, -* {discovered_output},result) -* -* (Note: fbuild, which workcache is based on, has the concept of a declared -* output as separate from a discovered output. This distinction exists only -* as an artifact of how fbuild works: via annotations on function types -* and metaprogramming, with explicit dependency declaration as a fallback. -* Workcache is more explicit about dependencies, and as such treats all -* outputs the same, as discovered-during-the-last-run.) -* -*/ - #[deriving(Clone, Eq, Encodable, Decodable, Ord, TotalOrd, TotalEq)] struct WorkKey { kind: StrBuf, From 3af77559096ef2df19cdc83e96674b10b27911b6 Mon Sep 17 00:00:00 2001 From: Corey Richardson Date: Tue, 8 Apr 2014 12:18:16 -0400 Subject: [PATCH 08/15] test: update for term fallout --- src/libtest/lib.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index 3273e53ed8a0b..f2ecd21488779 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -447,7 +447,7 @@ pub enum TestResult { } enum OutputLocation { - Pretty(term::Terminal), + Pretty(~term::Terminal<~Writer:Send>:Send), Raw(T), } @@ -472,10 +472,11 @@ impl ConsoleTestState { Some(ref path) => Some(try!(File::create(path))), None => None }; - let out = match term::Terminal::new(io::stdio::stdout_raw()) { - Err(_) => Raw(io::stdio::stdout_raw()), - Ok(t) => Pretty(t) + let out = match term::stdout() { + None => Raw(io::stdio::stdout_raw()), + Some(t) => Pretty(t) }; + Ok(ConsoleTestState { out: out, log_out: log_out, From 67aea1f8bd422b3e4c05c5b8bf6ea468ca0bf4e2 Mon Sep 17 00:00:00 2001 From: Corey Richardson Date: Mon, 14 Apr 2014 10:20:24 -0400 Subject: [PATCH 09/15] Add WinConsole docs --- src/libterm/win.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libterm/win.rs b/src/libterm/win.rs index 063f93cebac46..252c21ab9fa19 100644 --- a/src/libterm/win.rs +++ b/src/libterm/win.rs @@ -20,6 +20,7 @@ use attr; use color; use Terminal; +/// A Terminal implementation which uses the Win32 Console API. pub struct WinConsole { buf: T, foreground: color::Color, From c4cf6ca8addb2b22c077bfa30e8112f5a6087f4a Mon Sep 17 00:00:00 2001 From: Corey Richardson Date: Wed, 7 May 2014 09:45:53 -0400 Subject: [PATCH 10/15] Update for master --- src/libterm/terminfo/mod.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/libterm/terminfo/mod.rs b/src/libterm/terminfo/mod.rs index 93a7657fae9e4..0c07bbd1e6dd6 100644 --- a/src/libterm/terminfo/mod.rs +++ b/src/libterm/terminfo/mod.rs @@ -23,6 +23,7 @@ use self::parm::{expand, Number, Variables}; /// A parsed terminfo database entry. +#[deriving(Show)] pub struct TermInfo { /// Names for the terminal pub names: Vec , @@ -86,7 +87,7 @@ impl Terminal for TerminfoTerminal { // msys terminal return Some(TerminfoTerminal {out: out, ti: msys_terminfo(), num_colors: 8}); } - debug!("error finding terminfo entry: {}", entry.unwrap_err()); + debug!("error finding terminfo entry: {}", entry.err().unwrap()); return None; } @@ -183,7 +184,7 @@ impl Terminal for TerminfoTerminal { cap = self.ti.strings.find_equiv(&("op")); } } - let s = cap.map_or(Err(~"can't find terminfo capability `sgr0`"), |op| { + let s = cap.map_or(Err("can't find terminfo capability `sgr0`".to_owned()), |op| { expand(op.as_slice(), [], &mut Variables::new()) }); if s.is_ok() { From 2afa42a32ee4422a5f1f6b82f177ee54312f5164 Mon Sep 17 00:00:00 2001 From: Corey Richardson Date: Wed, 7 May 2014 11:12:04 -0400 Subject: [PATCH 11/15] Update for Box --- src/libsyntax/diagnostic.rs | 2 +- src/libterm/lib.rs | 44 ++++++++++++++++++------------------- src/libterm/terminfo/mod.rs | 2 +- src/libtest/lib.rs | 2 +- 4 files changed, 25 insertions(+), 25 deletions(-) diff --git a/src/libsyntax/diagnostic.rs b/src/libsyntax/diagnostic.rs index 4bb33f59f59ad..1a07393f9fc80 100644 --- a/src/libsyntax/diagnostic.rs +++ b/src/libsyntax/diagnostic.rs @@ -259,7 +259,7 @@ pub struct EmitterWriter { } enum Destination { - Terminal(~term::Terminal<~Writer:Send>:Send), + Terminal(Box>:Send>), Raw(Box), } diff --git a/src/libterm/lib.rs b/src/libterm/lib.rs index 8f5452c23f26b..6a50d62ba014f 100644 --- a/src/libterm/lib.rs +++ b/src/libterm/lib.rs @@ -65,25 +65,25 @@ mod win; #[cfg(not(windows))] /// Return a Terminal wrapping stdout, or None if a terminal couldn't be /// opened. -pub fn stdout() -> Option<~Terminal<~Writer:Send>:Send> { - let ti: Option> - = Terminal::new(~std::io::stdout() as ~Writer:Send); - ti.map(|t| ~t as ~Terminal<~Writer:Send>:Send) +pub fn stdout() -> Option>:Send>> { + let ti: Option>> + = Terminal::new(box std::io::stdout() as Box); + ti.map(|t| box t as Box:Send>:Send>) } #[cfg(windows)] /// Return a Terminal wrapping stdout, or None if a terminal couldn't be /// opened. -pub fn stdout() -> Option<~Terminal<~Writer:Send>:Send> { - let ti: Option> - = Terminal::new(~std::io::stdout() as ~Writer:Send); +pub fn stdout() -> Option:Send>:Send>> { + let ti: Option>> + = Terminal::new(box std::io::stdout() as Box); match ti { - Some(t) => Some(~t as ~Terminal<~Writer:Send>:Send), + Some(t) => Some(box t as Box:Send>:Send>), None => { - let wc: Option> - = Terminal::new(~std::io::stdout() as ~Writer:Send); - wc.map(|w| ~w as ~Terminal<~Writer:Send>:Send) + let wc: Option>> + = Terminal::new(box std::io::stdout() as Box); + wc.map(|w| box w as Box:Send>:Send>) } } } @@ -91,25 +91,25 @@ pub fn stdout() -> Option<~Terminal<~Writer:Send>:Send> { #[cfg(not(windows))] /// Return a Terminal wrapping stderr, or None if a terminal couldn't be /// opened. -pub fn stderr() -> Option<~Terminal<~Writer:Send>:Send> { - let ti: Option> - = Terminal::new(~std::io::stderr() as ~Writer:Send); - ti.map(|t| ~t as ~Terminal<~Writer:Send>:Send) +pub fn stderr() -> Option:Send>:Send>:Send> { + let ti: Option>> + = Terminal::new(box std::io::stderr() as Box); + ti.map(|t| box t as Box:Send>:Send>) } #[cfg(windows)] /// Return a Terminal wrapping stderr, or None if a terminal couldn't be /// opened. -pub fn stderr() -> Option<~Terminal<~Writer:Send>:Send> { - let ti: Option> - = Terminal::new(~std::io::stderr() as ~Writer:Send); +pub fn stderr() -> Option:Send>:Send>> { + let ti: Option>> + = Terminal::new(box std::io::stderr() as Box); match ti { - Some(t) => Some(~t as ~Terminal<~Writer:Send>:Send), + Some(t) => Some(box t as Box:Send>:Send>), None => { - let wc: Option> - = Terminal::new(~std::io::stderr() as ~Writer:Send); - wc.map(|w| ~w as ~Terminal<~Writer:Send>:Send) + let wc: Option>> + = Terminal::new(box std::io::stderr() as Box); + wc.map(|w| box w as Box:Send>:Send>) } } } diff --git a/src/libterm/terminfo/mod.rs b/src/libterm/terminfo/mod.rs index 0c07bbd1e6dd6..71ea88127a706 100644 --- a/src/libterm/terminfo/mod.rs +++ b/src/libterm/terminfo/mod.rs @@ -68,7 +68,7 @@ fn cap_for_attr(attr: attr::Attr) -> &'static str { pub struct TerminfoTerminal { num_colors: u16, out: T, - ti: ~TermInfo + ti: Box } impl Terminal for TerminfoTerminal { diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index f2ecd21488779..39eee153184d7 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -447,7 +447,7 @@ pub enum TestResult { } enum OutputLocation { - Pretty(~term::Terminal<~Writer:Send>:Send), + Pretty(Box>:Send>), Raw(T), } From 2cd32a8c88a8a1d0787dd9d75f6ff6db7641d14d Mon Sep 17 00:00:00 2001 From: Corey Richardson Date: Thu, 8 May 2014 13:13:57 -0400 Subject: [PATCH 12/15] Add a bang --- src/libterm/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libterm/lib.rs b/src/libterm/lib.rs index 6a50d62ba014f..fb7d388816738 100644 --- a/src/libterm/lib.rs +++ b/src/libterm/lib.rs @@ -26,7 +26,7 @@ //! t.fg(term::color::GREEN); //! println!("hello, "); //! t.fg(term::color::RED); -//! println("world!"); +//! println!("world!"); //! t.reset(); //! } //! ``` From 26238c9a245c32fae026a268c156352a4e56e503 Mon Sep 17 00:00:00 2001 From: Corey Richardson Date: Sun, 11 May 2014 20:08:49 -0400 Subject: [PATCH 13/15] Flush before applying console attributes --- src/libterm/win.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libterm/win.rs b/src/libterm/win.rs index 252c21ab9fa19..837ddf566ef45 100644 --- a/src/libterm/win.rs +++ b/src/libterm/win.rs @@ -57,6 +57,7 @@ fn color_to_bits(color: color::Color) -> u16 { impl WinConsole { fn apply(&mut self) { + let _unused = self.buf.flush(); let mut accum: libc::WORD = 0; accum |= color_to_bits(self.foreground); accum |= color_to_bits(self.background) << 4; From 1fe15b95cb677793cd349ec2506c93283aa65016 Mon Sep 17 00:00:00 2001 From: Corey Richardson Date: Sun, 11 May 2014 20:10:03 -0400 Subject: [PATCH 14/15] Fix example --- src/libterm/lib.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libterm/lib.rs b/src/libterm/lib.rs index fb7d388816738..e6e8a1d4dc384 100644 --- a/src/libterm/lib.rs +++ b/src/libterm/lib.rs @@ -22,12 +22,12 @@ //! extern crate term; //! //! fn main() { -//! let mut t = term::stdout(); -//! t.fg(term::color::GREEN); +//! let mut t = term::stdout().unwrap(); +//! t.fg(term::color::GREEN).unwrap(); //! println!("hello, "); -//! t.fg(term::color::RED); +//! t.fg(term::color::RED).unwrap(); //! println!("world!"); -//! t.reset(); +//! t.reset().unwrap(); //! } //! ``` //! From 3da99c5d8a44f3d79eb02e76c30df2b20d2df38c Mon Sep 17 00:00:00 2001 From: Corey Richardson Date: Fri, 16 May 2014 10:59:25 -0700 Subject: [PATCH 15/15] Some fixes --- src/libnum/lib.rs | 2 +- src/libterm/terminfo/mod.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libnum/lib.rs b/src/libnum/lib.rs index 54652c9dca33d..85967d4d942be 100644 --- a/src/libnum/lib.rs +++ b/src/libnum/lib.rs @@ -21,7 +21,7 @@ //! extern crate num; //! //! use num::bigint::BigInt; -//! use num::rational::{Ratio, BigRational}: +//! use num::rational::{Ratio, BigRational}; //! //! fn approx_sqrt(number: u64, iterations: uint) -> BigRational { //! let start: Ratio = Ratio::from_integer(FromPrimitive::from_u64(number).unwrap()); diff --git a/src/libterm/terminfo/mod.rs b/src/libterm/terminfo/mod.rs index 71ea88127a706..36e5c1cf763a6 100644 --- a/src/libterm/terminfo/mod.rs +++ b/src/libterm/terminfo/mod.rs @@ -184,7 +184,7 @@ impl Terminal for TerminfoTerminal { cap = self.ti.strings.find_equiv(&("op")); } } - let s = cap.map_or(Err("can't find terminfo capability `sgr0`".to_owned()), |op| { + let s = cap.map_or(Err("can't find terminfo capability `sgr0`".to_strbuf()), |op| { expand(op.as_slice(), [], &mut Variables::new()) }); if s.is_ok() {