From 2bda77c414d113b3640b372afffc781a2fe56e6d Mon Sep 17 00:00:00 2001 From: Andrew Gallant Date: Mon, 5 Sep 2016 18:22:12 -0400 Subject: [PATCH] Fix deps so that others can build it. --- Cargo.toml | 6 +- grep/Cargo.toml | 4 +- src/main.rs | 1 + src/printer.rs | 15 ++-- src/search.rs | 2 +- src/terminal.rs | 202 ++++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 214 insertions(+), 16 deletions(-) create mode 100644 src/terminal.rs diff --git a/Cargo.toml b/Cargo.toml index f20847ab..d7a34fdd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -30,10 +30,10 @@ memchr = "0.1" memmap = "0.2" num_cpus = "1" parking_lot = "0.3" -regex = { version = "0.1", path = "/home/andrew/rust/regex" } -regex-syntax = { version = "0.3.1", path = "/home/andrew/rust/regex/regex-syntax" } +regex = "0.1.75" +regex-syntax = "0.3.5" rustc-serialize = "0.3" -term = { version = "0.4", path = "/home/andrew/clones/term" } +term = "0.4" thread_local = "0.2" walkdir = "0.1" diff --git a/grep/Cargo.toml b/grep/Cargo.toml index 5da201e9..18371c94 100644 --- a/grep/Cargo.toml +++ b/grep/Cargo.toml @@ -16,5 +16,5 @@ license = "Unlicense/MIT" [dependencies] memchr = "0.1" memmap = "0.2" -regex = { version = "0.1", path = "/home/andrew/rust/regex" } -regex-syntax = { version = "0.3.1", path = "/home/andrew/rust/regex/regex-syntax" } +regex = "0.1.75" +regex-syntax = "0.3.5" diff --git a/src/main.rs b/src/main.rs index 164918a4..b01633b5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -64,6 +64,7 @@ mod out; mod printer; mod search; mod sys; +mod terminal; mod types; mod walk; diff --git a/src/printer.rs b/src/printer.rs index bcb1f468..e5da39e9 100644 --- a/src/printer.rs +++ b/src/printer.rs @@ -7,6 +7,7 @@ use term::{self, Terminal}; use term::color::*; use term::terminfo::TermInfo; +use terminal::TerminfoTerminal; use types::FileTypeDef; use self::Writer::*; @@ -265,7 +266,7 @@ impl Printer { } enum Writer { - Colored(term::TerminfoTerminal), + Colored(TerminfoTerminal), NoColor(W), } @@ -289,14 +290,8 @@ impl Writer { if !color || TERMINFO.is_none() { return NoColor(wtr); } - // Why doesn't TERMINFO.as_ref().unwrap().clone() work? let info = TERMINFO.clone().unwrap(); - // names: TERMINFO.as_ref().unwrap().names.clone(), - // bools: TERMINFO.as_ref().unwrap().bools.clone(), - // numbers: TERMINFO.as_ref().unwrap().numbers.clone(), - // strings: TERMINFO.as_ref().unwrap().strings.clone(), - // }; - let tt = term::TerminfoTerminal::new_with_terminfo(wtr, info); + let tt = TerminfoTerminal::new_with_terminfo(wtr, info); if !tt.supports_color() { debug!("environment doesn't support coloring"); return NoColor(tt.into_inner()); @@ -315,7 +310,7 @@ impl Writer { &mut self, mut f: F, ) -> term::Result<()> - where F: FnMut(&mut term::TerminfoTerminal) -> term::Result<()> { + where F: FnMut(&mut TerminfoTerminal) -> term::Result<()> { match *self { Colored(ref mut w) => f(w), NoColor(_) => Err(term::Error::NotSupported), @@ -326,7 +321,7 @@ impl Writer { &self, mut f: F, ) -> bool - where F: FnMut(&term::TerminfoTerminal) -> bool { + where F: FnMut(&TerminfoTerminal) -> bool { match *self { Colored(ref w) => f(w), NoColor(_) => false, diff --git a/src/search.rs b/src/search.rs index 66706225..9739d51f 100644 --- a/src/search.rs +++ b/src/search.rs @@ -329,7 +329,7 @@ impl<'a, R: io::Read, W: Send + io::Write> Searcher<'a, R, W> { self.count_lines(start); self.add_line(end); self.printer.matched( - &self.grep.regex(), &self.path, + self.grep.regex(), &self.path, &self.inp.buf, start, end, self.line_count); self.last_printed = end; self.after_context_remaining = self.opts.after_context; diff --git a/src/terminal.rs b/src/terminal.rs new file mode 100644 index 00000000..50461e74 --- /dev/null +++ b/src/terminal.rs @@ -0,0 +1,202 @@ +/*! +This module contains an implementation of the `term::Terminal` trait. + +The actual implementation is copied almost verbatim from the `term` crate, so +this code is under the same license (MIT/Apache). + +The specific reason why this is copied here is to wrap an Arc instead +of a TermInfo. This makes multithreaded sharing much more performant. + +N.B. This is temporary until this issue is fixed: +https://github.com/Stebalien/term/issues/64 +*/ + +use std::io::{self, Write}; +use std::sync::Arc; + +use term::{Attr, Error, Result, Terminal, color}; +use term::terminfo::TermInfo; +use term::terminfo::parm::{Param, Variables, expand}; + +/// A Terminal that knows how many colors it supports, with a reference to its +/// parsed Terminfo database record. +#[derive(Clone, Debug)] +pub struct TerminfoTerminal { + num_colors: u16, + out: T, + ti: Arc, +} + +impl Terminal for TerminfoTerminal { + type Output = T; + fn fg(&mut self, color: color::Color) -> Result<()> { + let color = self.dim_if_necessary(color); + if self.num_colors > color { + return apply_cap(&self.ti, "setaf", &[Param::Number(color as i32)], &mut self.out); + } + Err(Error::ColorOutOfRange) + } + + fn bg(&mut self, color: color::Color) -> Result<()> { + let color = self.dim_if_necessary(color); + if self.num_colors > color { + return apply_cap(&self.ti, "setab", &[Param::Number(color as i32)], &mut self.out); + } + Err(Error::ColorOutOfRange) + } + + fn attr(&mut self, attr: Attr) -> Result<()> { + match attr { + Attr::ForegroundColor(c) => self.fg(c), + Attr::BackgroundColor(c) => self.bg(c), + _ => apply_cap(&self.ti, cap_for_attr(attr), &[], &mut self.out), + } + } + + fn supports_attr(&self, attr: Attr) -> bool { + match attr { + Attr::ForegroundColor(_) | Attr::BackgroundColor(_) => self.num_colors > 0, + _ => { + let cap = cap_for_attr(attr); + self.ti.strings.get(cap).is_some() + } + } + } + + fn reset(&mut self) -> Result<()> { + reset(&self.ti, &mut self.out) + } + + fn supports_reset(&self) -> bool { + ["sgr0", "sgr", "op"].iter().any(|&cap| self.ti.strings.get(cap).is_some()) + } + + fn supports_color(&self) -> bool { + self.num_colors > 0 && self.supports_reset() + } + + fn cursor_up(&mut self) -> Result<()> { + apply_cap(&self.ti, "cuu1", &[], &mut self.out) + } + + fn delete_line(&mut self) -> Result<()> { + apply_cap(&self.ti, "dl", &[], &mut self.out) + } + + fn carriage_return(&mut self) -> Result<()> { + apply_cap(&self.ti, "cr", &[], &mut self.out) + } + + fn get_ref(&self) -> &T { + &self.out + } + + fn get_mut(&mut self) -> &mut T { + &mut self.out + } + + fn into_inner(self) -> T + where Self: Sized + { + self.out + } +} + +impl TerminfoTerminal { + /// Create a new TerminfoTerminal with the given TermInfo and Write. + pub fn new_with_terminfo(out: T, terminfo: Arc) -> TerminfoTerminal { + let nc = if terminfo.strings.contains_key("setaf") && + terminfo.strings.contains_key("setab") { + terminfo.numbers.get("colors").map_or(0, |&n| n) + } else { + 0 + }; + + TerminfoTerminal { + out: out, + ti: terminfo, + num_colors: nc, + } + } + + /// Create a new TerminfoTerminal for the current environment with the given Write. + /// + /// Returns `None` when the terminfo cannot be found or parsed. + pub fn new(out: T) -> Option> { + TermInfo::from_env().map(move |ti| { + TerminfoTerminal::new_with_terminfo(out, Arc::new(ti)) + }).ok() + } + + fn dim_if_necessary(&self, color: color::Color) -> color::Color { + if color >= self.num_colors && color >= 8 && color < 16 { + color - 8 + } else { + color + } + } +} + +impl Write for TerminfoTerminal { + fn write(&mut self, buf: &[u8]) -> io::Result { + self.out.write(buf) + } + + fn flush(&mut self) -> io::Result<()> { + self.out.flush() + } +} + +fn cap_for_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", + } +} + +fn apply_cap(ti: &TermInfo, cmd: &str, params: &[Param], out: &mut io::Write) -> Result<()> { + match ti.strings.get(cmd) { + Some(cmd) => { + match expand(cmd, params, &mut Variables::new()) { + Ok(s) => { + try!(out.write_all(&s)); + Ok(()) + } + Err(e) => Err(e.into()), + } + } + None => Err(Error::NotSupported), + } +} + +fn reset(ti: &TermInfo, out: &mut io::Write) -> Result<()> { + // are there any terminals that have color/attrs and not sgr0? + // Try falling back to sgr, then op + let cmd = match [("sgr0", &[] as &[Param]), ("sgr", &[Param::Number(0)]), ("op", &[])] + .iter() + .filter_map(|&(cap, params)| { + ti.strings.get(cap).map(|c| (c, params)) + }) + .next() { + Some((op, params)) => { + match expand(op, params, &mut Variables::new()) { + Ok(cmd) => cmd, + Err(e) => return Err(e.into()), + } + } + None => return Err(Error::NotSupported), + }; + try!(out.write_all(&cmd)); + Ok(()) +}