Compare commits

..

6 Commits

Author SHA1 Message Date
Andrew Gallant
12a78a992c termcolor-0.3.3 2017-08-27 11:05:55 -04:00
Andrew Gallant
d97c80be63 termcolor: make StandardStream be Send
This commit fixes a bug where the `StandardStream` type isn't `Send` on
Windows. This can cause some surprising compile breakage, and the only
motivation for it being non-Send was dubious. Namely, it was a result of
trying to eliminate code duplication.

This refactoring also eliminates at least one "unreachable" panic case
that was a result of trying to eliminate code reuse, so that's a nice
benefit as well.

Fixes #503
2017-08-27 11:05:02 -04:00
Andrew Gallant
5213bd30ea termcolor: 80 cols 2017-08-27 11:05:02 -04:00
Alex Burka
82d101907a ignore: document git_global enabled by default 2017-08-26 14:49:40 -04:00
Andrew Gallant
30608f2444 readme: update minimum version 2017-08-23 23:08:21 -04:00
Andrew Gallant
3d323928a0 update brew tap 2017-08-23 22:04:16 -04:00
5 changed files with 120 additions and 51 deletions

View File

@@ -210,7 +210,8 @@ $ # (Or using the attribute name, which is also `ripgrep`.)
``` ```
If you're a **Rust programmer**, `ripgrep` can be installed with `cargo`. Note If you're a **Rust programmer**, `ripgrep` can be installed with `cargo`. Note
that this requires you to have **Rust 1.12 or newer** installed. that the minimum supported version of Rust for ripgrep is **1.17**, although
ripgrep may work with older versions.
``` ```
$ cargo install ripgrep $ cargo install ripgrep
@@ -354,7 +355,7 @@ For **zsh**, move `complete/_rg` to one of your `$fpath` directories.
`ripgrep` is written in Rust, so you'll need to grab a `ripgrep` is written in Rust, so you'll need to grab a
[Rust installation](https://www.rust-lang.org/) in order to compile it. [Rust installation](https://www.rust-lang.org/) in order to compile it.
`ripgrep` compiles with Rust 1.12 (stable) or newer. Building is easy: `ripgrep` compiles with Rust 1.17 (stable) or newer. Building is easy:
``` ```
$ git clone https://github.com/BurntSushi/ripgrep $ git clone https://github.com/BurntSushi/ripgrep

View File

@@ -610,6 +610,8 @@ impl WalkBuilder {
/// does not exist or does not specify `core.excludesFile`, then /// does not exist or does not specify `core.excludesFile`, then
/// `$XDG_CONFIG_HOME/git/ignore` is read. If `$XDG_CONFIG_HOME` is not /// `$XDG_CONFIG_HOME/git/ignore` is read. If `$XDG_CONFIG_HOME` is not
/// set or is empty, then `$HOME/.config/git/ignore` is used instead. /// set or is empty, then `$HOME/.config/git/ignore` is used instead.
///
/// This is enabled by default.
pub fn git_global(&mut self, yes: bool) -> &mut WalkBuilder { pub fn git_global(&mut self, yes: bool) -> &mut WalkBuilder {
self.ig_builder.git_global(yes); self.ig_builder.git_global(yes);
self self

View File

@@ -1,9 +1,9 @@
class RipgrepBin < Formula class RipgrepBin < Formula
version '0.5.2' version '0.6.0'
desc "Search tool like grep and The Silver Searcher." desc "Search tool like grep and The Silver Searcher."
homepage "https://github.com/BurntSushi/ripgrep" homepage "https://github.com/BurntSushi/ripgrep"
url "https://github.com/BurntSushi/ripgrep/releases/download/#{version}/ripgrep-#{version}-x86_64-apple-darwin.tar.gz" url "https://github.com/BurntSushi/ripgrep/releases/download/#{version}/ripgrep-#{version}-x86_64-apple-darwin.tar.gz"
sha256 "a0326a84af8517ad707d8c7cccba6e112de27822c391cc0937e4727fbb6c48f4" sha256 "2aeffe25322f886bcd846ac15b6574dc769865fb44b28a9b0c356f3004019685"
conflicts_with "ripgrep" conflicts_with "ripgrep"

View File

@@ -1,6 +1,6 @@
[package] [package]
name = "termcolor" name = "termcolor"
version = "0.3.2" #:version version = "0.3.3" #:version
authors = ["Andrew Gallant <jamslam@gmail.com>"] authors = ["Andrew Gallant <jamslam@gmail.com>"]
description = """ description = """
A simple cross platform library for writing colored text to a terminal. A simple cross platform library for writing colored text to a terminal.

View File

@@ -202,15 +202,23 @@ enum IoStandardStream {
impl IoStandardStream { impl IoStandardStream {
fn new(sty: StandardStreamType) -> IoStandardStream { fn new(sty: StandardStreamType) -> IoStandardStream {
match sty { match sty {
StandardStreamType::Stdout => IoStandardStream::Stdout(io::stdout()), StandardStreamType::Stdout => {
StandardStreamType::Stderr => IoStandardStream::Stderr(io::stderr()), IoStandardStream::Stdout(io::stdout())
}
StandardStreamType::Stderr => {
IoStandardStream::Stderr(io::stderr())
}
} }
} }
fn lock(&self) -> IoStandardStreamLock { fn lock(&self) -> IoStandardStreamLock {
match *self { match *self {
IoStandardStream::Stdout(ref s) => IoStandardStreamLock::StdoutLock(s.lock()), IoStandardStream::Stdout(ref s) => {
IoStandardStream::Stderr(ref s) => IoStandardStreamLock::StderrLock(s.lock()), IoStandardStreamLock::StdoutLock(s.lock())
}
IoStandardStream::Stderr(ref s) => {
IoStandardStreamLock::StderrLock(s.lock())
}
} }
} }
} }
@@ -257,7 +265,7 @@ impl<'a> io::Write for IoStandardStreamLock<'a> {
/// Satisfies `io::Write` and `WriteColor`, and supports optional coloring /// Satisfies `io::Write` and `WriteColor`, and supports optional coloring
/// to either of the standard output streams, stdout and stderr. /// to either of the standard output streams, stdout and stderr.
pub struct StandardStream { pub struct StandardStream {
wtr: LossyStandardStream<WriterInner<'static, IoStandardStream>>, wtr: LossyStandardStream<WriterInner<IoStandardStream>>,
} }
/// `StandardStreamLock` is a locked reference to a `StandardStream`. /// `StandardStreamLock` is a locked reference to a `StandardStream`.
@@ -265,14 +273,24 @@ pub struct StandardStream {
/// This implements the `io::Write` and `WriteColor` traits, and is constructed /// This implements the `io::Write` and `WriteColor` traits, and is constructed
/// via the `Write::lock` method. /// via the `Write::lock` method.
/// ///
/// The lifetime `'a` refers to the lifetime of the corresponding `StandardStream`. /// The lifetime `'a` refers to the lifetime of the corresponding
/// `StandardStream`.
pub struct StandardStreamLock<'a> { pub struct StandardStreamLock<'a> {
wtr: LossyStandardStream<WriterInner<'a, IoStandardStreamLock<'a>>>, wtr: LossyStandardStream<WriterInnerLock<'a, IoStandardStreamLock<'a>>>,
} }
/// WriterInner is a (limited) generic representation of a writer. It is /// WriterInner is a (limited) generic representation of a writer. It is
/// limited because W should only ever be stdout/stderr on Windows. /// limited because W should only ever be stdout/stderr on Windows.
enum WriterInner<'a, W> { enum WriterInner<W> {
NoColor(NoColor<W>),
Ansi(Ansi<W>),
#[cfg(windows)]
Windows { wtr: W, console: Mutex<wincolor::Console> },
}
/// WriterInnerLock is a (limited) generic representation of a writer. It is
/// limited because W should only ever be stdout/stderr on Windows.
enum WriterInnerLock<'a, W> {
NoColor(NoColor<W>), NoColor(NoColor<W>),
Ansi(Ansi<W>), Ansi(Ansi<W>),
/// What a gross hack. On Windows, we need to specify a lifetime for the /// What a gross hack. On Windows, we need to specify a lifetime for the
@@ -282,9 +300,7 @@ enum WriterInner<'a, W> {
#[allow(dead_code)] #[allow(dead_code)]
Unreachable(::std::marker::PhantomData<&'a ()>), Unreachable(::std::marker::PhantomData<&'a ()>),
#[cfg(windows)] #[cfg(windows)]
Windows { wtr: W, console: Mutex<wincolor::Console> }, Windows { wtr: W, console: MutexGuard<'a, wincolor::Console> },
#[cfg(windows)]
WindowsLocked { wtr: W, console: MutexGuard<'a, wincolor::Console> },
} }
impl StandardStream { impl StandardStream {
@@ -332,7 +348,9 @@ impl StandardStream {
} else { } else {
WriterInner::NoColor(NoColor(IoStandardStream::new(sty))) WriterInner::NoColor(NoColor(IoStandardStream::new(sty)))
}; };
StandardStream { wtr: LossyStandardStream::new(wtr).is_console(is_win_console) } StandardStream {
wtr: LossyStandardStream::new(wtr).is_console(is_win_console),
}
} }
/// Create a new `StandardStream` with the given color preferences that /// Create a new `StandardStream` with the given color preferences that
@@ -375,12 +393,11 @@ impl<'a> StandardStreamLock<'a> {
#[cfg(not(windows))] #[cfg(not(windows))]
fn from_stream(stream: &StandardStream) -> StandardStreamLock { fn from_stream(stream: &StandardStream) -> StandardStreamLock {
let locked = match *stream.wtr.get_ref() { let locked = match *stream.wtr.get_ref() {
WriterInner::Unreachable(_) => unreachable!(),
WriterInner::NoColor(ref w) => { WriterInner::NoColor(ref w) => {
WriterInner::NoColor(NoColor(w.0.lock())) WriterInnerLock::NoColor(NoColor(w.0.lock()))
} }
WriterInner::Ansi(ref w) => { WriterInner::Ansi(ref w) => {
WriterInner::Ansi(Ansi(w.0.lock())) WriterInnerLock::Ansi(Ansi(w.0.lock()))
} }
}; };
StandardStreamLock { wtr: stream.wtr.wrap(locked) } StandardStreamLock { wtr: stream.wtr.wrap(locked) }
@@ -389,24 +406,19 @@ impl<'a> StandardStreamLock<'a> {
#[cfg(windows)] #[cfg(windows)]
fn from_stream(stream: &StandardStream) -> StandardStreamLock { fn from_stream(stream: &StandardStream) -> StandardStreamLock {
let locked = match *stream.wtr.get_ref() { let locked = match *stream.wtr.get_ref() {
WriterInner::Unreachable(_) => unreachable!(),
WriterInner::NoColor(ref w) => { WriterInner::NoColor(ref w) => {
WriterInner::NoColor(NoColor(w.0.lock())) WriterInnerLock::NoColor(NoColor(w.0.lock()))
} }
WriterInner::Ansi(ref w) => { WriterInner::Ansi(ref w) => {
WriterInner::Ansi(Ansi(w.0.lock())) WriterInnerLock::Ansi(Ansi(w.0.lock()))
} }
#[cfg(windows)] #[cfg(windows)]
WriterInner::Windows { ref wtr, ref console } => { WriterInner::Windows { ref wtr, ref console } => {
WriterInner::WindowsLocked { WriterInnerLock::Windows {
wtr: wtr.lock(), wtr: wtr.lock(),
console: console.lock().unwrap(), console: console.lock().unwrap(),
} }
} }
#[cfg(windows)]
WriterInner::WindowsLocked{..} => {
panic!("cannot call StandardStream.lock while a StandardStreamLock is alive");
}
}; };
StandardStreamLock { wtr: stream.wtr.wrap(locked) } StandardStreamLock { wtr: stream.wtr.wrap(locked) }
} }
@@ -438,48 +450,38 @@ impl<'a> WriteColor for StandardStreamLock<'a> {
fn reset(&mut self) -> io::Result<()> { self.wtr.reset() } fn reset(&mut self) -> io::Result<()> { self.wtr.reset() }
} }
impl<'a, W: io::Write> io::Write for WriterInner<'a, W> { impl<W: io::Write> io::Write for WriterInner<W> {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> { fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
match *self { match *self {
WriterInner::Unreachable(_) => unreachable!(),
WriterInner::NoColor(ref mut wtr) => wtr.write(buf), WriterInner::NoColor(ref mut wtr) => wtr.write(buf),
WriterInner::Ansi(ref mut wtr) => wtr.write(buf), WriterInner::Ansi(ref mut wtr) => wtr.write(buf),
#[cfg(windows)] #[cfg(windows)]
WriterInner::Windows { ref mut wtr, .. } => wtr.write(buf), WriterInner::Windows { ref mut wtr, .. } => wtr.write(buf),
#[cfg(windows)]
WriterInner::WindowsLocked { ref mut wtr, .. } => wtr.write(buf),
} }
} }
fn flush(&mut self) -> io::Result<()> { fn flush(&mut self) -> io::Result<()> {
match *self { match *self {
WriterInner::Unreachable(_) => unreachable!(),
WriterInner::NoColor(ref mut wtr) => wtr.flush(), WriterInner::NoColor(ref mut wtr) => wtr.flush(),
WriterInner::Ansi(ref mut wtr) => wtr.flush(), WriterInner::Ansi(ref mut wtr) => wtr.flush(),
#[cfg(windows)] #[cfg(windows)]
WriterInner::Windows { ref mut wtr, .. } => wtr.flush(), WriterInner::Windows { ref mut wtr, .. } => wtr.flush(),
#[cfg(windows)]
WriterInner::WindowsLocked { ref mut wtr, .. } => wtr.flush(),
} }
} }
} }
impl<'a, W: io::Write> WriteColor for WriterInner<'a, W> { impl<W: io::Write> WriteColor for WriterInner<W> {
fn supports_color(&self) -> bool { fn supports_color(&self) -> bool {
match *self { match *self {
WriterInner::Unreachable(_) => unreachable!(),
WriterInner::NoColor(_) => false, WriterInner::NoColor(_) => false,
WriterInner::Ansi(_) => true, WriterInner::Ansi(_) => true,
#[cfg(windows)] #[cfg(windows)]
WriterInner::Windows { .. } => true, WriterInner::Windows { .. } => true,
#[cfg(windows)]
WriterInner::WindowsLocked { .. } => true,
} }
} }
fn set_color(&mut self, spec: &ColorSpec) -> io::Result<()> { fn set_color(&mut self, spec: &ColorSpec) -> io::Result<()> {
match *self { match *self {
WriterInner::Unreachable(_) => unreachable!(),
WriterInner::NoColor(ref mut wtr) => wtr.set_color(spec), WriterInner::NoColor(ref mut wtr) => wtr.set_color(spec),
WriterInner::Ansi(ref mut wtr) => wtr.set_color(spec), WriterInner::Ansi(ref mut wtr) => wtr.set_color(spec),
#[cfg(windows)] #[cfg(windows)]
@@ -488,17 +490,11 @@ impl<'a, W: io::Write> WriteColor for WriterInner<'a, W> {
let mut console = console.lock().unwrap(); let mut console = console.lock().unwrap();
spec.write_console(&mut *console) spec.write_console(&mut *console)
} }
#[cfg(windows)]
WriterInner::WindowsLocked { ref mut wtr, ref mut console } => {
try!(wtr.flush());
spec.write_console(console)
}
} }
} }
fn reset(&mut self) -> io::Result<()> { fn reset(&mut self) -> io::Result<()> {
match *self { match *self {
WriterInner::Unreachable(_) => unreachable!(),
WriterInner::NoColor(ref mut wtr) => wtr.reset(), WriterInner::NoColor(ref mut wtr) => wtr.reset(),
WriterInner::Ansi(ref mut wtr) => wtr.reset(), WriterInner::Ansi(ref mut wtr) => wtr.reset(),
#[cfg(windows)] #[cfg(windows)]
@@ -507,8 +503,63 @@ impl<'a, W: io::Write> WriteColor for WriterInner<'a, W> {
try!(console.lock().unwrap().reset()); try!(console.lock().unwrap().reset());
Ok(()) Ok(())
} }
}
}
}
impl<'a, W: io::Write> io::Write for WriterInnerLock<'a, W> {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
match *self {
WriterInnerLock::Unreachable(_) => unreachable!(),
WriterInnerLock::NoColor(ref mut wtr) => wtr.write(buf),
WriterInnerLock::Ansi(ref mut wtr) => wtr.write(buf),
#[cfg(windows)] #[cfg(windows)]
WriterInner::WindowsLocked { ref mut wtr, ref mut console } => { WriterInnerLock::Windows { ref mut wtr, .. } => wtr.write(buf),
}
}
fn flush(&mut self) -> io::Result<()> {
match *self {
WriterInnerLock::Unreachable(_) => unreachable!(),
WriterInnerLock::NoColor(ref mut wtr) => wtr.flush(),
WriterInnerLock::Ansi(ref mut wtr) => wtr.flush(),
#[cfg(windows)]
WriterInnerLock::Windows { ref mut wtr, .. } => wtr.flush(),
}
}
}
impl<'a, W: io::Write> WriteColor for WriterInnerLock<'a, W> {
fn supports_color(&self) -> bool {
match *self {
WriterInnerLock::Unreachable(_) => unreachable!(),
WriterInnerLock::NoColor(_) => false,
WriterInnerLock::Ansi(_) => true,
#[cfg(windows)]
WriterInnerLock::Windows { .. } => true,
}
}
fn set_color(&mut self, spec: &ColorSpec) -> io::Result<()> {
match *self {
WriterInnerLock::Unreachable(_) => unreachable!(),
WriterInnerLock::NoColor(ref mut wtr) => wtr.set_color(spec),
WriterInnerLock::Ansi(ref mut wtr) => wtr.set_color(spec),
#[cfg(windows)]
WriterInnerLock::Windows { ref mut wtr, ref mut console } => {
try!(wtr.flush());
spec.write_console(console)
}
}
}
fn reset(&mut self) -> io::Result<()> {
match *self {
WriterInnerLock::Unreachable(_) => unreachable!(),
WriterInnerLock::NoColor(ref mut wtr) => wtr.reset(),
WriterInnerLock::Ansi(ref mut wtr) => wtr.reset(),
#[cfg(windows)]
WriterInnerLock::Windows { ref mut wtr, ref mut console } => {
try!(wtr.flush()); try!(wtr.flush());
try!(console.reset()); try!(console.reset());
Ok(()) Ok(())
@@ -565,7 +616,8 @@ impl BufferWriter {
StandardStreamType::Stdout => wincolor::Console::stdout(), StandardStreamType::Stdout => wincolor::Console::stdout(),
StandardStreamType::Stderr => wincolor::Console::stderr(), StandardStreamType::Stderr => wincolor::Console::stderr(),
}.ok().map(Mutex::new); }.ok().map(Mutex::new);
let stream = LossyStandardStream::new(IoStandardStream::new(sty)).is_console(con.is_some()); let stream = LossyStandardStream::new(IoStandardStream::new(sty))
.is_console(con.is_some());
BufferWriter { BufferWriter {
stream: stream, stream: stream,
printed: AtomicBool::new(false), printed: AtomicBool::new(false),
@@ -1253,7 +1305,9 @@ struct LossyStandardStream<W> {
impl<W: io::Write> LossyStandardStream<W> { impl<W: io::Write> LossyStandardStream<W> {
#[cfg(not(windows))] #[cfg(not(windows))]
fn new(wtr: W) -> LossyStandardStream<W> { LossyStandardStream { wtr: wtr } } fn new(wtr: W) -> LossyStandardStream<W> {
LossyStandardStream { wtr: wtr }
}
#[cfg(windows)] #[cfg(windows)]
fn new(wtr: W) -> LossyStandardStream<W> { fn new(wtr: W) -> LossyStandardStream<W> {
@@ -1320,3 +1374,15 @@ fn write_lossy_utf8<W: io::Write>(mut w: W, buf: &[u8]) -> io::Result<usize> {
Err(e) => w.write(&buf[..e.valid_up_to()]), Err(e) => w.write(&buf[..e.valid_up_to()]),
} }
} }
#[cfg(test)]
mod tests {
use super::StandardStream;
fn assert_is_send<T: Send>() {}
#[test]
fn standard_stream_is_send() {
assert_is_send::<StandardStream>();
}
}