use std::cell::RefCell;
use std::io::{self, Write};
use std::path::Path;
use std::sync::Arc;
use std::time::Instant;
use grep_matcher::Matcher;
use grep_searcher::{Searcher, Sink, SinkError, SinkFinish, SinkMatch};
use termcolor::{ColorSpec, NoColor, WriteColor};
use color::ColorSpecs;
use counter::CounterWriter;
use stats::Stats;
use util::PrinterPath;
/// The configuration for the summary printer.
///
/// This is manipulated by the SummaryBuilder and then referenced by the actual
/// implementation. Once a printer is build, the configuration is frozen and
/// cannot changed.
#[derive(Debug, Clone)]
struct Config {
kind: SummaryKind,
colors: ColorSpecs,
stats: bool,
path: bool,
max_matches: Option<u64>,
exclude_zero: bool,
separator_field: Arc<Vec<u8>>,
separator_path: Option<u8>,
path_terminator: Option<u8>,
}
impl Default for Config {
fn default() -> Config {
Config {
kind: SummaryKind::Count,
colors: ColorSpecs::default(),
stats: false,
path: true,
max_matches: None,
exclude_zero: true,
separator_field: Arc::new(b":".to_vec()),
separator_path: None,
path_terminator: None,
}
}
}
/// The type of summary output (if any) to print.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum SummaryKind {
/// Show only a count of the total number of matches (counting each line
/// at most once) found.
///
/// If the `path` setting is enabled, then the count is prefixed by the
/// corresponding file path.
Count,
/// Show only a count of the total number of matches (counting possibly
/// many matches on each line) found.
///
/// If the `path` setting is enabled, then the count is prefixed by the
/// corresponding file path.
CountMatches,
/// Show only the file path if and only if a match was found.
///
/// This ignores the `path` setting and always shows the file path. If no
/// file path is provided, then searching will immediately stop and return
/// an error.
PathWithMatch,
/// Show only the file path if and only if a match was found.
///
/// This ignores the `path` setting and always shows the file path. If no
/// file path is provided, then searching will immediately stop and return
/// an error.
PathWithoutMatch,
/// Don't show any output and the stop the search once a match is found.
///
/// Note that if `stats` is enabled, then searching continues in order to
/// compute statistics.
Quiet,
}
impl SummaryKind {
/// Returns true if and only if this output mode requires a file path.
///
/// When an output mode requires a file path, then the summary printer
/// will report an error at the start of every search that lacks a file
/// path.
fn requires_path(&self) -> bool {
use self::SummaryKind::*;
match *self {
PathWithMatch | PathWithoutMatch => true,
Count | CountMatches | Quiet => false,
}
}
/// Returns true if and only if this output mode requires computing
/// statistics, regardless of whether they have been enabled or not.
fn requires_stats(&self) -> bool {
use self::SummaryKind::*;
match *self {
CountMatches => true,
Count | PathWithMatch | PathWithoutMatch | Quiet => false,
}
}
/// Returns true if and only if a printer using this output mode can
/// quit after seeing the first match.
fn quit_early(&self) -> bool {
use self::SummaryKind::*;
match *self {
PathWithMatch | Quiet => true,
Count | CountMatches | PathWithoutMatch => false,
}
}
}
/// A builder for summary printer.
///
/// The builder permits configuring how the printer behaves. The summary
/// printer has fewer configuration options than the standard printer because
/// it aims to produce aggregate output about a single search (typically just
/// one line) instead of output for each match.
///
/// Once a `Summary` printer is built, its configuration cannot be changed.
#[derive(Clone, Debug)]
pub struct SummaryBuilder {
config: Config,
}
impl SummaryBuilder {
/// Return a new builder for configuring the summary printer.
pub fn new() -> SummaryBuilder {
SummaryBuilder { config: Config::default() }
}
/// Build a printer using any implementation of `termcolor::WriteColor`.
///
/// The implementation of `WriteColor` used here controls whether colors
/// are used or not when colors have been configured using the
/// `color_specs` method.
///
/// For maximum portability, callers should generally use either
/// `termcolor::StandardStream` or `termcolor::BufferedStandardStream`
/// where appropriate, which will automatically enable colors on Windows
/// when possible.
///
/// However, callers may also provide an arbitrary writer using the
/// `termcolor::Ansi` or `termcolor::NoColor` wrappers, which always enable
/// colors via ANSI escapes or always disable colors, respectively.