Skip to content

Commit

Permalink
Stream results when feasible.
Browse files Browse the repository at this point in the history
For example, when only a single file (or stdin) is being searched, then we
should be able to print directly to the terminal instead of intermediate
buffers. (The buffers are only necessary for parallelism.)

Closes BurntSushi#4.
  • Loading branch information
amsharma91 committed Sep 20, 2016
1 parent 084961c commit 733893f
Show file tree
Hide file tree
Showing 12 changed files with 488 additions and 645 deletions.
35 changes: 30 additions & 5 deletions src/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,20 @@ use grep::{Grep, GrepBuilder};
use log;
use num_cpus;
use regex;
use term::Terminal;
use term::{self, Terminal};
#[cfg(windows)]
use term::WinConsole;
use walkdir::WalkDir;

use atty;
use gitignore::{Gitignore, GitignoreBuilder};
use ignore::Ignore;
use out::{Out, OutBuffer};
use out::{Out, ColoredTerminal};
use printer::Printer;
use search_buffer::BufferSearcher;
use search_stream::{InputBuffer, Searcher};
#[cfg(windows)]
use terminal_win::WindowsBuffer;
use types::{FileTypeDef, Types, TypesBuilder};
use walk;

Expand Down Expand Up @@ -442,7 +446,7 @@ impl Args {

/// Create a new printer of individual search results that writes to the
/// writer given.
pub fn printer<W: Send + Terminal>(&self, wtr: W) -> Printer<W> {
pub fn printer<W: Terminal + Send>(&self, wtr: W) -> Printer<W> {
let mut p = Printer::new(wtr)
.column(self.column)
.context_separator(self.context_separator.clone())
Expand All @@ -469,8 +473,29 @@ impl Args {
}

/// Create a new buffer for use with searching.
pub fn outbuf(&self) -> OutBuffer {
OutBuffer::new(self.color)
#[cfg(not(windows))]
pub fn outbuf(&self) -> ColoredTerminal<term::TerminfoTerminal<Vec<u8>>> {
ColoredTerminal::new(vec![], self.color)
}

/// Create a new buffer for use with searching.
#[cfg(windows)]
pub fn outbuf(&self) -> ColoredTerminal<WindowsBuffer> {
ColoredTerminal::new_buffer(self.color)
}

/// Create a new buffer for use with searching.
#[cfg(not(windows))]
pub fn stdout(
&self,
) -> ColoredTerminal<term::TerminfoTerminal<io::BufWriter<io::Stdout>>> {
ColoredTerminal::new(io::BufWriter::new(io::stdout()), self.color)
}

/// Create a new buffer for use with searching.
#[cfg(windows)]
pub fn stdout(&self) -> ColoredTerminal<WinConsole<io::Stdout>> {
ColoredTerminal::new_stdout(self.color)
}

/// Return the paths that should be searched.
Expand Down
22 changes: 3 additions & 19 deletions src/gitignore.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ additional rules such as whitelists (prefix of `!`) or directory-only globs
// TODO(burntsushi): Implement something similar, but for Mercurial. We can't
// use this exact implementation because hgignore files are different.

use std::env;
use std::error::Error as StdError;
use std::fmt;
use std::fs::File;
Expand Down Expand Up @@ -89,21 +88,10 @@ pub struct Gitignore {
}

impl Gitignore {
/// Create a new gitignore glob matcher from the gitignore file at the
/// given path. The root of the gitignore file is the basename of path.
pub fn from_path<P: AsRef<Path>>(path: P) -> Result<Gitignore, Error> {
let root = match path.as_ref().parent() {
Some(parent) => parent.to_path_buf(),
None => env::current_dir().unwrap_or(Path::new("/").to_path_buf()),
};
let mut builder = GitignoreBuilder::new(root);
try!(builder.add_path(path));
builder.build()
}

/// Create a new gitignore glob matcher from the given root directory and
/// string containing the contents of a gitignore file.
pub fn from_str<P: AsRef<Path>>(
#[allow(dead_code)]
fn from_str<P: AsRef<Path>>(
root: P,
gitignore: &str,
) -> Result<Gitignore, Error> {
Expand Down Expand Up @@ -159,11 +147,6 @@ impl Gitignore {
pub fn num_ignores(&self) -> u64 {
self.num_ignores
}

/// Returns the total number of whitelisted patterns.
pub fn num_whitelist(&self) -> u64 {
self.num_whitelist
}
}

/// The result of a glob match.
Expand All @@ -182,6 +165,7 @@ pub enum Match<'a> {

impl<'a> Match<'a> {
/// Returns true if the match result implies the path should be ignored.
#[allow(dead_code)]
pub fn is_ignored(&self) -> bool {
match *self {
Match::Ignored(_) => true,
Expand Down
5 changes: 4 additions & 1 deletion src/glob.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ impl Set {
}

/// Returns the number of glob patterns in this set.
#[allow(dead_code)]
pub fn len(&self) -> usize {
self.set.len()
}
Expand Down Expand Up @@ -137,6 +138,7 @@ impl SetBuilder {
///
/// If the pattern could not be parsed as a glob, then an error is
/// returned.
#[allow(dead_code)]
pub fn add(&mut self, pat: &str) -> Result<(), Error> {
self.add_with(pat, &MatchOptions::default())
}
Expand Down Expand Up @@ -205,6 +207,7 @@ impl Pattern {
/// Convert this pattern to a string that is guaranteed to be a valid
/// regular expression and will represent the matching semantics of this
/// glob pattern. This uses a default set of options.
#[allow(dead_code)]
pub fn to_regex(&self) -> String {
self.to_regex_with(&MatchOptions::default())
}
Expand Down Expand Up @@ -315,7 +318,7 @@ impl<'a> Parser<'a> {
}
return Ok(());
}
let last = self.p.tokens.pop().unwrap();
self.p.tokens.pop().unwrap();
if prev != Some('/') {
return Err(Error::InvalidRecursive);
}
Expand Down
Loading

0 comments on commit 733893f

Please sign in to comment.