From 09905560ffc32206988c92c6a37c1c927c86e3cb Mon Sep 17 00:00:00 2001 From: Andrew Gallant Date: Thu, 21 Sep 2023 16:57:02 -0400 Subject: [PATCH] printer: clean-up Like a previous commit did for the grep-cli crate, this does some polishing to the grep-printer crate. We aren't able to achieve as much as we did with grep-cli, but we at least eliminate all rust-analyzer lints and group imports in the way I've been doing recently. Next we'll start doing some more invasive changes. --- Cargo.lock | 5 +- crates/printer/Cargo.toml | 29 +++++--- crates/printer/src/color.rs | 38 ++++------ crates/printer/src/counter.rs | 20 +++--- crates/printer/src/hyperlink.rs | 85 +++++++++++++--------- crates/printer/src/hyperlink_aliases.rs | 2 +- crates/printer/src/json.rs | 31 ++++---- crates/printer/src/jsont.rs | 61 ++++++++-------- crates/printer/src/lib.rs | 61 ++++++++-------- crates/printer/src/standard.rs | 73 ++++++++++--------- crates/printer/src/stats.rs | 8 ++- crates/printer/src/summary.rs | 40 ++++++----- crates/printer/src/util.rs | 96 +++++++++++++------------ 13 files changed, 291 insertions(+), 258 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f2019025..885e73d3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -19,9 +19,9 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "base64" -version = "0.20.0" +version = "0.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ea22880d78093b0cbe17c89f64a7d457941e65759157ec6cb31a31d652b05e5" +checksum = "9ba43ea6f343b788c8764558649e08df62f86c6ef251fdaeb1ffd010a9ae50a2" [[package]] name = "bitflags" @@ -220,7 +220,6 @@ dependencies = [ "grep-matcher", "grep-regex", "grep-searcher", - "lazy_static", "serde", "serde_json", "termcolor", diff --git a/crates/printer/Cargo.toml b/crates/printer/Cargo.toml index 2536a235..69e03d65 100644 --- a/crates/printer/Cargo.toml +++ b/crates/printer/Cargo.toml @@ -12,22 +12,33 @@ repository = "https://github.com/BurntSushi/ripgrep/tree/master/crates/printer" readme = "README.md" keywords = ["grep", "pattern", "print", "printer", "sink"] license = "Unlicense OR MIT" -edition = "2018" +edition = "2021" [features] -default = ["serde1"] -serde1 = ["base64", "serde", "serde_json"] +default = ["serde"] +serde = ["dep:base64", "dep:serde", "dep:serde_json"] [dependencies] -base64 = { version = "0.20.0", optional = true } -bstr = "1.6.0" +base64 = { version = "0.21.4", optional = true } +bstr = "1.6.2" gethostname = "0.4.3" grep-matcher = { version = "0.1.6", path = "../matcher" } grep-searcher = { version = "0.1.11", path = "../searcher" } -lazy_static = "1.1.0" -termcolor = "1.0.4" -serde = { version = "1.0.77", optional = true, features = ["derive"] } -serde_json = { version = "1.0.27", optional = true } +termcolor = "1.3.0" +serde = { version = "1.0.188", optional = true, features = ["derive"] } +serde_json = { version = "1.0.107", optional = true } [dev-dependencies] grep-regex = { version = "0.1.11", path = "../regex" } + +[package.metadata.docs.rs] +# We want to document all features. +all-features = true +# This opts into a nightly unstable option to show the features that need to be +# enabled for public API items. To do that, we set 'docsrs', and when that's +# enabled, we enable the 'doc_auto_cfg' feature. +# +# To test this locally, run: +# +# RUSTDOCFLAGS="--cfg docsrs" cargo +nightly doc --all-features +rustdoc-args = ["--cfg", "docsrs"] diff --git a/crates/printer/src/color.rs b/crates/printer/src/color.rs index 11d2c3e6..d17674e9 100644 --- a/crates/printer/src/color.rs +++ b/crates/printer/src/color.rs @@ -1,7 +1,3 @@ -use std::error; -use std::fmt; -use std::str::FromStr; - use termcolor::{Color, ColorSpec, ParseColorError}; /// Returns a default set of color specifications. @@ -38,17 +34,7 @@ pub enum ColorError { InvalidFormat(String), } -impl error::Error for ColorError { - fn description(&self) -> &str { - match *self { - ColorError::UnrecognizedOutType(_) => "unrecognized output type", - ColorError::UnrecognizedSpecType(_) => "unrecognized spec type", - ColorError::UnrecognizedColor(_, _) => "unrecognized color name", - ColorError::UnrecognizedStyle(_) => "unrecognized style attribute", - ColorError::InvalidFormat(_) => "invalid color spec", - } - } -} +impl std::error::Error for ColorError {} impl ColorError { fn from_parse_error(err: ParseColorError) -> ColorError { @@ -59,33 +45,33 @@ impl ColorError { } } -impl fmt::Display for ColorError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { +impl std::fmt::Display for ColorError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match *self { ColorError::UnrecognizedOutType(ref name) => write!( f, "unrecognized output type '{}'. Choose from: \ - path, line, column, match.", + path, line, column, match.", name, ), ColorError::UnrecognizedSpecType(ref name) => write!( f, "unrecognized spec type '{}'. Choose from: \ - fg, bg, style, none.", + fg, bg, style, none.", name, ), ColorError::UnrecognizedColor(_, ref msg) => write!(f, "{}", msg), ColorError::UnrecognizedStyle(ref name) => write!( f, "unrecognized style attribute '{}'. Choose from: \ - nobold, bold, nointense, intense, nounderline, \ - underline.", + nobold, bold, nointense, intense, nounderline, \ + underline.", name, ), ColorError::InvalidFormat(ref original) => write!( f, "invalid color spec format: '{}'. Valid format \ - is '(path|line|column|match):(fg|bg|style):(value)'.", + is '(path|line|column|match):(fg|bg|style):(value)'.", original, ), } @@ -305,7 +291,7 @@ impl SpecValue { } } -impl FromStr for UserColorSpec { +impl std::str::FromStr for UserColorSpec { type Err = ColorError; fn from_str(s: &str) -> Result { @@ -345,7 +331,7 @@ impl FromStr for UserColorSpec { } } -impl FromStr for OutType { +impl std::str::FromStr for OutType { type Err = ColorError; fn from_str(s: &str) -> Result { @@ -359,7 +345,7 @@ impl FromStr for OutType { } } -impl FromStr for SpecType { +impl std::str::FromStr for SpecType { type Err = ColorError; fn from_str(s: &str) -> Result { @@ -373,7 +359,7 @@ impl FromStr for SpecType { } } -impl FromStr for Style { +impl std::str::FromStr for Style { type Err = ColorError; fn from_str(s: &str) -> Result { diff --git a/crates/printer/src/counter.rs b/crates/printer/src/counter.rs index 9df9c3df..a9f5af16 100644 --- a/crates/printer/src/counter.rs +++ b/crates/printer/src/counter.rs @@ -5,32 +5,32 @@ use termcolor::{ColorSpec, HyperlinkSpec, WriteColor}; /// A writer that counts the number of bytes that have been successfully /// written. #[derive(Clone, Debug)] -pub struct CounterWriter { +pub(crate) struct CounterWriter { wtr: W, count: u64, total_count: u64, } impl CounterWriter { - pub fn new(wtr: W) -> CounterWriter { - CounterWriter { wtr: wtr, count: 0, total_count: 0 } + pub(crate) fn new(wtr: W) -> CounterWriter { + CounterWriter { wtr, count: 0, total_count: 0 } } } impl CounterWriter { /// Returns the total number of bytes written since construction or the /// last time `reset` was called. - pub fn count(&self) -> u64 { + pub(crate) fn count(&self) -> u64 { self.count } /// Returns the total number of bytes written since construction. - pub fn total_count(&self) -> u64 { + pub(crate) fn total_count(&self) -> u64 { self.total_count + self.count } /// Resets the number of bytes written to `0`. - pub fn reset_count(&mut self) { + pub(crate) fn reset_count(&mut self) { self.total_count += self.count; self.count = 0; } @@ -40,21 +40,21 @@ impl CounterWriter { /// After this call, the total count of bytes written to the underlying /// writer is erased and reset. #[allow(dead_code)] - pub fn clear(&mut self) { + pub(crate) fn clear(&mut self) { self.count = 0; self.total_count = 0; } #[allow(dead_code)] - pub fn get_ref(&self) -> &W { + pub(crate) fn get_ref(&self) -> &W { &self.wtr } - pub fn get_mut(&mut self) -> &mut W { + pub(crate) fn get_mut(&mut self) -> &mut W { &mut self.wtr } - pub fn into_inner(self) -> W { + pub(crate) fn into_inner(self) -> W { self.wtr } } diff --git a/crates/printer/src/hyperlink.rs b/crates/printer/src/hyperlink.rs index eebdba4a..136ec64e 100644 --- a/crates/printer/src/hyperlink.rs +++ b/crates/printer/src/hyperlink.rs @@ -1,12 +1,14 @@ +use std::{ + io::{self, Write}, + path::Path, +}; + +use { + bstr::ByteSlice, + termcolor::{HyperlinkSpec, WriteColor}, +}; + use crate::hyperlink_aliases::HYPERLINK_PATTERN_ALIASES; -use bstr::ByteSlice; -use std::error::Error; -use std::fmt::Display; -use std::io; -use std::io::Write; -use std::path::Path; -use std::str::FromStr; -use termcolor::{HyperlinkSpec, WriteColor}; /// A builder for `HyperlinkPattern`. /// @@ -65,7 +67,8 @@ pub struct HyperlinkValues<'a> { /// Represents the {file} part of a hyperlink. /// -/// This is the value to use as-is in the hyperlink, converted from an OS file path. +/// This is the value to use as-is in the hyperlink, converted from an OS file +/// path. #[derive(Clone, Debug)] pub struct HyperlinkPath(Vec); @@ -231,7 +234,7 @@ impl HyperlinkPattern { } } -impl FromStr for HyperlinkPattern { +impl std::str::FromStr for HyperlinkPattern { type Err = HyperlinkPatternError; fn from_str(s: &str) -> Result { @@ -308,24 +311,31 @@ impl ToString for Part { } } -impl Display for HyperlinkPatternError { +impl std::fmt::Display for HyperlinkPatternError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { HyperlinkPatternError::InvalidSyntax => { write!(f, "invalid hyperlink pattern syntax") } HyperlinkPatternError::NoFilePlaceholder => { - write!(f, "the {{file}} placeholder is required in hyperlink patterns") + write!( + f, + "the {{file}} placeholder is required in hyperlink \ + patterns", + ) } HyperlinkPatternError::NoLinePlaceholder => { - write!(f, "the hyperlink pattern contains a {{column}} placeholder, \ - but no {{line}} placeholder is present") + write!( + f, + "the hyperlink pattern contains a {{column}} placeholder, \ + but no {{line}} placeholder is present", + ) } HyperlinkPatternError::InvalidPlaceholder(name) => { write!( f, - "invalid hyperlink pattern placeholder: '{}', choose from: \ - file, line, column, host", + "invalid hyperlink pattern placeholder: '{}', choose \ + from: file, line, column, host", name ) } @@ -339,7 +349,7 @@ impl Display for HyperlinkPatternError { } } -impl Error for HyperlinkPatternError {} +impl std::error::Error for HyperlinkPatternError {} impl<'a> HyperlinkValues<'a> { /// Creates a new set of hyperlink values. @@ -360,8 +370,9 @@ impl HyperlinkPath { /// Returns a hyperlink path from an OS path. #[cfg(unix)] pub fn from_path(path: &Path) -> Option { - // On Unix, this function returns the absolute file path without the leading slash, - // as it makes for more natural hyperlink patterns, for instance: + // On Unix, this function returns the absolute file path without the + // leading slash, as it makes for more natural hyperlink patterns, for + // instance: // file://{host}/{file} instead of file://{host}{file} // vscode://file/{file} instead of vscode://file{file} // It also allows for patterns to be multi-platform. @@ -410,11 +421,12 @@ impl HyperlinkPath { // Also note that the file://C:/dir/file.txt syntax is not correct, // even though it often works in practice. // - // In the end, this choice was confirmed by VSCode, whose pattern - // is vscode://file/{file}:{line}:{column} and which correctly understands + // In the end, this choice was confirmed by VSCode, whose pattern is + // vscode://file/{file}:{line}:{column} and which correctly understands // the following URL format for network drives: // vscode://file//server/dir/file.txt:1:1 - // It doesn't parse any other number of slashes in "file//server" as a network path. + // It doesn't parse any other number of slashes in "file//server" as a + // network path. const WIN32_NAMESPACE_PREFIX: &[u8] = br"\\?\"; const UNC_PREFIX: &[u8] = br"UNC\"; @@ -438,14 +450,15 @@ impl HyperlinkPath { /// Percent-encodes a path. /// /// The alphanumeric ASCII characters and "-", ".", "_", "~" are unreserved - /// as per section 2.3 of RFC 3986 (Uniform Resource Identifier (URI): Generic Syntax), - /// and are not encoded. The other ASCII characters except "/" and ":" are percent-encoded, - /// and "\" is replaced by "/" on Windows. + /// as per section 2.3 of RFC 3986 (Uniform Resource Identifier (URI): + /// Generic Syntax), and are not encoded. The other ASCII characters except + /// "/" and ":" are percent-encoded, and "\" is replaced by "/" on Windows. /// - /// Section 4 of RFC 8089 (The "file" URI Scheme) does not mandate precise encoding - /// requirements for non-ASCII characters, and this implementation leaves them unencoded. - /// On Windows, the UrlCreateFromPathW function does not encode non-ASCII characters. - /// Doing so with UTF-8 encoded paths creates invalid file:// URLs on that platform. + /// Section 4 of RFC 8089 (The "file" URI Scheme) does not mandate precise + /// encoding requirements for non-ASCII characters, and this implementation + /// leaves them unencoded. On Windows, the UrlCreateFromPathW function does + /// not encode non-ASCII characters. Doing so with UTF-8 encoded paths + /// creates invalid file:// URLs on that platform. fn encode(input: &[u8]) -> HyperlinkPath { let mut result = Vec::with_capacity(input.len()); @@ -480,7 +493,7 @@ impl HyperlinkPath { } } -impl Display for HyperlinkPath { +impl std::fmt::Display for HyperlinkPath { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!( f, @@ -490,15 +503,16 @@ impl Display for HyperlinkPath { } } -/// A simple abstraction over a hyperlink span written to the terminal. -/// This helps tracking whether a hyperlink has been started, and should be ended. +/// A simple abstraction over a hyperlink span written to the terminal. This +/// helps tracking whether a hyperlink has been started, and should be ended. #[derive(Debug, Default)] pub struct HyperlinkSpan { active: bool, } impl HyperlinkSpan { - /// Starts a hyperlink and returns a span which tracks whether it is still in effect. + /// Starts a hyperlink and returns a span which tracks whether it is still + /// in effect. pub fn start( wtr: &mut impl WriteColor, hyperlink: &HyperlinkSpec, @@ -528,6 +542,8 @@ impl HyperlinkSpan { #[cfg(test)] mod tests { + use std::str::FromStr; + use super::*; #[test] @@ -653,7 +669,8 @@ mod tests { for name in names { assert!( name > previous_name, - r#""{}" should be sorted before "{}" in `HYPERLINK_PATTERN_ALIASES`"#, + "'{}' should be sorted before '{}' \ + in HYPERLINK_PATTERN_ALIASES", name, previous_name ); diff --git a/crates/printer/src/hyperlink_aliases.rs b/crates/printer/src/hyperlink_aliases.rs index 139e982b..6d429bf8 100644 --- a/crates/printer/src/hyperlink_aliases.rs +++ b/crates/printer/src/hyperlink_aliases.rs @@ -1,7 +1,7 @@ /// Aliases to well-known hyperlink schemes. /// /// These need to be sorted by name. -pub const HYPERLINK_PATTERN_ALIASES: &[(&str, &str)] = &[ +pub(crate) const HYPERLINK_PATTERN_ALIASES: &[(&str, &str)] = &[ #[cfg(unix)] ("file", "file://{host}/{file}"), #[cfg(windows)] diff --git a/crates/printer/src/json.rs b/crates/printer/src/json.rs index d952f1f9..3f5bd48a 100644 --- a/crates/printer/src/json.rs +++ b/crates/printer/src/json.rs @@ -1,17 +1,20 @@ -use std::io::{self, Write}; -use std::path::Path; -use std::time::Instant; - -use grep_matcher::{Match, Matcher}; -use grep_searcher::{ - Searcher, Sink, SinkContext, SinkContextKind, SinkFinish, SinkMatch, +use std::{ + io::{self, Write}, + path::Path, + time::Instant, }; -use serde_json as json; -use crate::counter::CounterWriter; -use crate::jsont; -use crate::stats::Stats; -use crate::util::find_iter_at_in_context; +use { + grep_matcher::{Match, Matcher}, + grep_searcher::{ + Searcher, Sink, SinkContext, SinkContextKind, SinkFinish, SinkMatch, + }, + serde_json as json, +}; + +use crate::{ + counter::CounterWriter, jsont, stats::Stats, util::find_iter_at_in_context, +}; /// The configuration for the JSON printer. /// @@ -467,7 +470,7 @@ impl JSON { matcher: M, ) -> JSONSink<'static, 's, M, W> { JSONSink { - matcher: matcher, + matcher, json: self, path: None, start_time: Instant::now(), @@ -493,7 +496,7 @@ impl JSON { P: ?Sized + AsRef, { JSONSink { - matcher: matcher, + matcher, json: self, path: Some(path.as_ref()), start_time: Instant::now(), diff --git a/crates/printer/src/jsont.rs b/crates/printer/src/jsont.rs index 47a99f3b..5f67f115 100644 --- a/crates/printer/src/jsont.rs +++ b/crates/printer/src/jsont.rs @@ -6,19 +6,19 @@ // convenient for deserialization however, so these types would become a bit // more complex. -use std::borrow::Cow; -use std::path::Path; -use std::str; +use std::{borrow::Cow, path::Path}; -use base64; -use serde::{Serialize, Serializer}; +use { + base64, + serde::{Serialize, Serializer}, +}; use crate::stats::Stats; #[derive(Serialize)] #[serde(tag = "type", content = "data")] #[serde(rename_all = "snake_case")] -pub enum Message<'a> { +pub(crate) enum Message<'a> { Begin(Begin<'a>), End(End<'a>), Match(Match<'a>), @@ -26,48 +26,48 @@ pub enum Message<'a> { } #[derive(Serialize)] -pub struct Begin<'a> { +pub(crate) struct Begin<'a> { #[serde(serialize_with = "ser_path")] - pub path: Option<&'a Path>, + pub(crate) path: Option<&'a Path>, } #[derive(Serialize)] -pub struct End<'a> { +pub(crate) struct End<'a> { #[serde(serialize_with = "ser_path")] - pub path: Option<&'a Path>, - pub binary_offset: Option, - pub stats: Stats, + pub(crate) path: Option<&'a Path>, + pub(crate) binary_offset: Option, + pub(crate) stats: Stats, } #[derive(Serialize)] -pub struct Match<'a> { +pub(crate) struct Match<'a> { #[serde(serialize_with = "ser_path")] - pub path: Option<&'a Path>, + pub(crate) path: Option<&'a Path>, #[serde(serialize_with = "ser_bytes")] - pub lines: &'a [u8], - pub line_number: Option, - pub absolute_offset: u64, - pub submatches: &'a [SubMatch<'a>], + pub(crate) lines: &'a [u8], + pub(crate) line_number: Option, + pub(crate) absolute_offset: u64, + pub(crate) submatches: &'a [SubMatch<'a>], } #[derive(Serialize)] -pub struct Context<'a> { +pub(crate) struct Context<'a> { #[serde(serialize_with = "ser_path")] - pub path: Option<&'a Path>, + pub(crate) path: Option<&'a Path>, #[serde(serialize_with = "ser_bytes")] - pub lines: &'a [u8], - pub line_number: Option, - pub absolute_offset: u64, - pub submatches: &'a [SubMatch<'a>], + pub(crate) lines: &'a [u8], + pub(crate) line_number: Option, + pub(crate) absolute_offset: u64, + pub(crate) submatches: &'a [SubMatch<'a>], } #[derive(Serialize)] -pub struct SubMatch<'a> { +pub(crate) struct SubMatch<'a> { #[serde(rename = "match")] #[serde(serialize_with = "ser_bytes")] - pub m: &'a [u8], - pub start: usize, - pub end: usize, + pub(crate) m: &'a [u8], + pub(crate) start: usize, + pub(crate) end: usize, } /// Data represents things that look like strings, but may actually not be @@ -91,7 +91,7 @@ enum Data<'a> { impl<'a> Data<'a> { fn from_bytes(bytes: &[u8]) -> Data<'_> { - match str::from_utf8(bytes) { + match std::str::from_utf8(bytes) { Ok(text) => Data::Text { text: Cow::Borrowed(text) }, Err(_) => Data::Bytes { bytes }, } @@ -123,7 +123,8 @@ where T: AsRef<[u8]>, S: Serializer, { - ser.serialize_str(&base64::encode(&bytes)) + use base64::engine::{general_purpose::STANDARD, Engine}; + ser.serialize_str(&STANDARD.encode(&bytes)) } fn ser_bytes(bytes: T, ser: S) -> Result diff --git a/crates/printer/src/lib.rs b/crates/printer/src/lib.rs index e0093fe9..6a2ac727 100644 --- a/crates/printer/src/lib.rs +++ b/crates/printer/src/lib.rs @@ -27,11 +27,11 @@ contain matches. This example shows how to create a "standard" printer and execute a search. ``` -use std::error::Error; - -use grep_regex::RegexMatcher; -use grep_printer::Standard; -use grep_searcher::Searcher; +use { + grep_regex::RegexMatcher, + grep_printer::Standard, + grep_searcher::Searcher, +}; const SHERLOCK: &'static [u8] = b"\ For the Doctor Watsons of this world, as opposed to the Sherlock @@ -42,41 +42,40 @@ but Doctor Watson has to have it taken out for him and dusted, and exhibited clearly, with a label attached. "; -# fn main() { example().unwrap(); } -fn example() -> Result<(), Box> { - let matcher = RegexMatcher::new(r"Sherlock")?; - let mut printer = Standard::new_no_color(vec![]); - Searcher::new().search_slice(&matcher, SHERLOCK, printer.sink(&matcher))?; +let matcher = RegexMatcher::new(r"Sherlock")?; +let mut printer = Standard::new_no_color(vec![]); +Searcher::new().search_slice(&matcher, SHERLOCK, printer.sink(&matcher))?; - // into_inner gives us back the underlying writer we provided to - // new_no_color, which is wrapped in a termcolor::NoColor. Thus, a second - // into_inner gives us back the actual buffer. - let output = String::from_utf8(printer.into_inner().into_inner())?; - let expected = "\ +// into_inner gives us back the underlying writer we provided to +// new_no_color, which is wrapped in a termcolor::NoColor. Thus, a second +// into_inner gives us back the actual buffer. +let output = String::from_utf8(printer.into_inner().into_inner())?; +let expected = "\ 1:For the Doctor Watsons of this world, as opposed to the Sherlock 3:be, to a very large extent, the result of luck. Sherlock Holmes "; - assert_eq!(output, expected); - Ok(()) -} +assert_eq!(output, expected); +# Ok::<(), Box>(()) ``` */ #![deny(missing_docs)] +#![cfg_attr(feature = "pattern", feature(pattern))] -pub use crate::color::{ - default_color_specs, ColorError, ColorSpecs, UserColorSpec, +pub use crate::{ + color::{default_color_specs, ColorError, ColorSpecs, UserColorSpec}, + hyperlink::{ + HyperlinkPath, HyperlinkPattern, HyperlinkPatternBuilder, + HyperlinkPatternError, HyperlinkSpan, HyperlinkValues, + }, + standard::{Standard, StandardBuilder, StandardSink}, + stats::Stats, + summary::{Summary, SummaryBuilder, SummaryKind, SummarySink}, + util::PrinterPath, }; -pub use crate::hyperlink::{ - HyperlinkPath, HyperlinkPattern, HyperlinkPatternError, HyperlinkSpan, - HyperlinkValues, -}; -#[cfg(feature = "serde1")] + +#[cfg(feature = "serde")] pub use crate::json::{JSONBuilder, JSONSink, JSON}; -pub use crate::standard::{Standard, StandardBuilder, StandardSink}; -pub use crate::stats::Stats; -pub use crate::summary::{Summary, SummaryBuilder, SummaryKind, SummarySink}; -pub use crate::util::PrinterPath; // The maximum number of bytes to execute a search to account for look-ahead. // @@ -96,9 +95,9 @@ mod color; mod counter; mod hyperlink; mod hyperlink_aliases; -#[cfg(feature = "serde1")] +#[cfg(feature = "serde")] mod json; -#[cfg(feature = "serde1")] +#[cfg(feature = "serde")] mod jsont; mod standard; mod stats; diff --git a/crates/printer/src/standard.rs b/crates/printer/src/standard.rs index ac4338a9..4dd55ac9 100644 --- a/crates/printer/src/standard.rs +++ b/crates/printer/src/standard.rs @@ -1,25 +1,31 @@ -use std::cell::{Cell, RefCell}; -use std::cmp; -use std::io::{self, Write}; -use std::path::Path; -use std::sync::Arc; -use std::time::Instant; - -use bstr::ByteSlice; -use grep_matcher::{Match, Matcher}; -use grep_searcher::{ - LineStep, Searcher, Sink, SinkContext, SinkContextKind, SinkFinish, - SinkMatch, +use std::{ + cell::{Cell, RefCell}, + cmp, + io::{self, Write}, + path::Path, + sync::Arc, + time::Instant, }; -use termcolor::{ColorSpec, NoColor, WriteColor}; -use crate::color::ColorSpecs; -use crate::counter::CounterWriter; -use crate::hyperlink::{HyperlinkPattern, HyperlinkSpan}; -use crate::stats::Stats; -use crate::util::{ - find_iter_at_in_context, trim_ascii_prefix, trim_line_terminator, - PrinterPath, Replacer, Sunk, +use { + bstr::ByteSlice, + grep_matcher::{Match, Matcher}, + grep_searcher::{ + LineStep, Searcher, Sink, SinkContext, SinkContextKind, SinkFinish, + SinkMatch, + }, + termcolor::{ColorSpec, NoColor, WriteColor}, +}; + +use crate::{ + color::ColorSpecs, + counter::CounterWriter, + hyperlink::{HyperlinkPattern, HyperlinkSpan}, + stats::Stats, + util::{ + find_iter_at_in_context, trim_ascii_prefix, trim_line_terminator, + PrinterPath, Replacer, Sunk, + }, }; /// The configuration for the standard printer. @@ -522,7 +528,7 @@ impl Standard { let stats = if self.config.stats { Some(Stats::new()) } else { None }; let needs_match_granularity = self.needs_match_granularity(); StandardSink { - matcher: matcher, + matcher, standard: self, replacer: Replacer::new(), path: None, @@ -530,8 +536,8 @@ impl Standard { match_count: 0, after_context_remaining: 0, binary_byte_offset: None, - stats: stats, - needs_match_granularity: needs_match_granularity, + stats, + needs_match_granularity, } } @@ -558,7 +564,7 @@ impl Standard { ); let needs_match_granularity = self.needs_match_granularity(); StandardSink { - matcher: matcher, + matcher, standard: self, replacer: Replacer::new(), path: Some(ppath), @@ -566,8 +572,8 @@ impl Standard { match_count: 0, after_context_remaining: 0, binary_byte_offset: None, - stats: stats, - needs_match_granularity: needs_match_granularity, + stats, + needs_match_granularity, } } @@ -935,8 +941,8 @@ impl<'a, M: Matcher, W: WriteColor> StandardImpl<'a, M, W> { sink: &'a StandardSink<'_, '_, M, W>, ) -> StandardImpl<'a, M, W> { StandardImpl { - searcher: searcher, - sink: sink, + searcher, + sink, sunk: Sunk::empty(), in_color_match: Cell::new(false), } @@ -954,7 +960,7 @@ impl<'a, M: Matcher, W: WriteColor> StandardImpl<'a, M, W> { &sink.standard.matches, sink.replacer.replacement(), ); - StandardImpl { sunk: sunk, ..StandardImpl::new(searcher, sink) } + StandardImpl { sunk, ..StandardImpl::new(searcher, sink) } } /// Bundle self with a searcher and return the core implementation of Sink @@ -969,7 +975,7 @@ impl<'a, M: Matcher, W: WriteColor> StandardImpl<'a, M, W> { &sink.standard.matches, sink.replacer.replacement(), ); - StandardImpl { sunk: sunk, ..StandardImpl::new(searcher, sink) } + StandardImpl { sunk, ..StandardImpl::new(searcher, sink) } } fn sink(&self) -> io::Result<()> { @@ -1657,9 +1663,10 @@ impl<'a, M: Matcher, W: WriteColor> PreludeWriter<'a, M, W> { /// Starts the prelude with a hyperlink when applicable. /// - /// If a heading was written, and the hyperlink pattern is invariant on the line number, - /// then this doesn't hyperlink each line prelude, as it wouldn't point to the line anyway. - /// The hyperlink on the heading should be sufficient and less confusing. + /// If a heading was written, and the hyperlink pattern is invariant on + /// the line number, then this doesn't hyperlink each line prelude, as it + /// wouldn't point to the line anyway. The hyperlink on the heading should + /// be sufficient and less confusing. fn start( &mut self, line_number: Option, diff --git a/crates/printer/src/stats.rs b/crates/printer/src/stats.rs index 357b9a77..9aa14d46 100644 --- a/crates/printer/src/stats.rs +++ b/crates/printer/src/stats.rs @@ -1,5 +1,7 @@ -use std::ops::{Add, AddAssign}; -use std::time::Duration; +use std::{ + ops::{Add, AddAssign}, + time::Duration, +}; use crate::util::NiceDuration; @@ -8,7 +10,7 @@ use crate::util::NiceDuration; /// When statistics are reported by a printer, they correspond to all searches /// executed with that printer. #[derive(Clone, Debug, Default, PartialEq, Eq)] -#[cfg_attr(feature = "serde1", derive(serde::Serialize))] +#[cfg_attr(feature = "serde", derive(serde::Serialize))] pub struct Stats { elapsed: NiceDuration, searches: u64, diff --git a/crates/printer/src/summary.rs b/crates/printer/src/summary.rs index 99e3a1dc..f62eba90 100644 --- a/crates/printer/src/summary.rs +++ b/crates/printer/src/summary.rs @@ -1,18 +1,24 @@ -use std::cell::RefCell; -use std::io::{self, Write}; -use std::path::Path; -use std::sync::Arc; -use std::time::Instant; +use std::{ + cell::RefCell, + io::{self, Write}, + path::Path, + sync::Arc, + time::Instant, +}; -use grep_matcher::Matcher; -use grep_searcher::{Searcher, Sink, SinkError, SinkFinish, SinkMatch}; -use termcolor::{ColorSpec, NoColor, WriteColor}; +use { + grep_matcher::Matcher, + grep_searcher::{Searcher, Sink, SinkError, SinkFinish, SinkMatch}, + termcolor::{ColorSpec, NoColor, WriteColor}, +}; -use crate::color::ColorSpecs; -use crate::counter::CounterWriter; -use crate::hyperlink::{HyperlinkPattern, HyperlinkSpan}; -use crate::stats::Stats; -use crate::util::{find_iter_at_in_context, PrinterPath}; +use crate::{ + color::ColorSpecs, + counter::CounterWriter, + hyperlink::{HyperlinkPattern, HyperlinkSpan}, + stats::Stats, + util::{find_iter_at_in_context, PrinterPath}, +}; /// The configuration for the summary printer. /// @@ -392,13 +398,13 @@ impl Summary { None }; SummarySink { - matcher: matcher, + matcher, summary: self, path: None, start_time: Instant::now(), match_count: 0, binary_byte_offset: None, - stats: stats, + stats, } } @@ -428,13 +434,13 @@ impl Summary { self.config.separator_path, ); SummarySink { - matcher: matcher, + matcher, summary: self, path: Some(ppath), start_time: Instant::now(), match_count: 0, binary_byte_offset: None, - stats: stats, + stats, } } } diff --git a/crates/printer/src/util.rs b/crates/printer/src/util.rs index d987421d..bfa8551b 100644 --- a/crates/printer/src/util.rs +++ b/crates/printer/src/util.rs @@ -1,23 +1,24 @@ -use std::borrow::Cow; -use std::cell::OnceCell; -use std::path::Path; -use std::time; -use std::{fmt, io}; +use std::{borrow::Cow, fmt, io, path::Path, time}; -use bstr::{ByteSlice, ByteVec}; -use grep_matcher::{Captures, LineTerminator, Match, Matcher}; -use grep_searcher::{ - LineIter, Searcher, SinkContext, SinkContextKind, SinkError, SinkMatch, +use { + bstr::{ByteSlice, ByteVec}, + grep_matcher::{Captures, LineTerminator, Match, Matcher}, + grep_searcher::{ + LineIter, Searcher, SinkContext, SinkContextKind, SinkError, SinkMatch, + }, + termcolor::HyperlinkSpec, }; -#[cfg(feature = "serde1")] -use serde::{Serialize, Serializer}; -use termcolor::HyperlinkSpec; -use crate::hyperlink::{HyperlinkPath, HyperlinkPattern, HyperlinkValues}; -use crate::MAX_LOOK_AHEAD; +#[cfg(feature = "serde")] +use serde::{Serialize, Serializer}; + +use crate::{ + hyperlink::{HyperlinkPath, HyperlinkPattern, HyperlinkValues}, + MAX_LOOK_AHEAD, +}; /// A type for handling replacements while amortizing allocation. -pub struct Replacer { +pub(crate) struct Replacer { space: Option>, } @@ -45,7 +46,7 @@ impl Replacer { /// /// This constructor does not allocate. Instead, space for dealing with /// replacements is allocated lazily only when needed. - pub fn new() -> Replacer { + pub(crate) fn new() -> Replacer { Replacer { space: None } } @@ -54,7 +55,7 @@ impl Replacer { /// replacement, use the `replacement` method. /// /// This can fail if the underlying matcher reports an error. - pub fn replace_all<'a>( + pub(crate) fn replace_all<'a>( &'a mut self, searcher: &Searcher, matcher: &M, @@ -112,7 +113,9 @@ impl Replacer { /// all replacement occurrences within the returned replacement buffer. /// /// If no replacement has occurred then `None` is returned. - pub fn replacement<'a>(&'a self) -> Option<(&'a [u8], &'a [Match])> { + pub(crate) fn replacement<'a>( + &'a self, + ) -> Option<(&'a [u8], &'a [Match])> { match self.space { None => None, Some(ref space) => { @@ -129,7 +132,7 @@ impl Replacer { /// /// Subsequent calls to `replacement` after calling `clear` (but before /// executing another replacement) will always return `None`. - pub fn clear(&mut self) { + pub(crate) fn clear(&mut self) { if let Some(ref mut space) = self.space { space.dst.clear(); space.matches.clear(); @@ -145,8 +148,7 @@ impl Replacer { if self.space.is_none() { let caps = matcher.new_captures().map_err(io::Error::error_message)?; - self.space = - Some(Space { caps: caps, dst: vec![], matches: vec![] }); + self.space = Some(Space { caps, dst: vec![], matches: vec![] }); } Ok(self.space.as_mut().unwrap()) } @@ -165,7 +167,7 @@ impl Replacer { /// results of the replacement instead of the bytes reported directly by the /// searcher. #[derive(Debug)] -pub struct Sunk<'a> { +pub(crate) struct Sunk<'a> { bytes: &'a [u8], absolute_byte_offset: u64, line_number: Option, @@ -176,7 +178,7 @@ pub struct Sunk<'a> { impl<'a> Sunk<'a> { #[inline] - pub fn empty() -> Sunk<'static> { + pub(crate) fn empty() -> Sunk<'static> { Sunk { bytes: &[], absolute_byte_offset: 0, @@ -188,7 +190,7 @@ impl<'a> Sunk<'a> { } #[inline] - pub fn from_sink_match( + pub(crate) fn from_sink_match( sunk: &'a SinkMatch<'a>, original_matches: &'a [Match], replacement: Option<(&'a [u8], &'a [Match])>, @@ -196,17 +198,17 @@ impl<'a> Sunk<'a> { let (bytes, matches) = replacement.unwrap_or_else(|| (sunk.bytes(), original_matches)); Sunk { - bytes: bytes, + bytes, absolute_byte_offset: sunk.absolute_byte_offset(), line_number: sunk.line_number(), context_kind: None, - matches: matches, - original_matches: original_matches, + matches, + original_matches, } } #[inline] - pub fn from_sink_context( + pub(crate) fn from_sink_context( sunk: &'a SinkContext<'a>, original_matches: &'a [Match], replacement: Option<(&'a [u8], &'a [Match])>, @@ -214,47 +216,47 @@ impl<'a> Sunk<'a> { let (bytes, matches) = replacement.unwrap_or_else(|| (sunk.bytes(), original_matches)); Sunk { - bytes: bytes, + bytes, absolute_byte_offset: sunk.absolute_byte_offset(), line_number: sunk.line_number(), context_kind: Some(sunk.kind()), - matches: matches, - original_matches: original_matches, + matches, + original_matches, } } #[inline] - pub fn context_kind(&self) -> Option<&'a SinkContextKind> { + pub(crate) fn context_kind(&self) -> Option<&'a SinkContextKind> { self.context_kind } #[inline] - pub fn bytes(&self) -> &'a [u8] { + pub(crate) fn bytes(&self) -> &'a [u8] { self.bytes } #[inline] - pub fn matches(&self) -> &'a [Match] { + pub(crate) fn matches(&self) -> &'a [Match] { self.matches } #[inline] - pub fn original_matches(&self) -> &'a [Match] { + pub(crate) fn original_matches(&self) -> &'a [Match] { self.original_matches } #[inline] - pub fn lines(&self, line_term: u8) -> LineIter<'a> { + pub(crate) fn lines(&self, line_term: u8) -> LineIter<'a> { LineIter::new(line_term, self.bytes()) } #[inline] - pub fn absolute_byte_offset(&self) -> u64 { + pub(crate) fn absolute_byte_offset(&self) -> u64 { self.absolute_byte_offset } #[inline] - pub fn line_number(&self) -> Option { + pub(crate) fn line_number(&self) -> Option { self.line_number } } @@ -281,7 +283,7 @@ impl<'a> Sunk<'a> { pub struct PrinterPath<'a> { path: &'a Path, bytes: Cow<'a, [u8]>, - hyperlink_path: OnceCell>, + hyperlink_path: std::cell::OnceCell>, } impl<'a> PrinterPath<'a> { @@ -290,7 +292,7 @@ impl<'a> PrinterPath<'a> { PrinterPath { path, bytes: Vec::from_path_lossy(path), - hyperlink_path: OnceCell::new(), + hyperlink_path: std::cell::OnceCell::new(), } } @@ -331,8 +333,8 @@ impl<'a> PrinterPath<'a> { &self.bytes } - /// Creates a hyperlink for this path and the given line and column, using the specified - /// pattern. Uses the given buffer to store the hyperlink. + /// Creates a hyperlink for this path and the given line and column, using + /// the specified pattern. Uses the given buffer to store the hyperlink. pub fn create_hyperlink_spec<'b>( &self, pattern: &HyperlinkPattern, @@ -365,7 +367,7 @@ impl<'a> PrinterPath<'a> { /// with the Deserialize impl for std::time::Duration, since this type only /// adds new fields. #[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] -pub struct NiceDuration(pub time::Duration); +pub(crate) struct NiceDuration(pub time::Duration); impl fmt::Display for NiceDuration { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { @@ -383,7 +385,7 @@ impl NiceDuration { } } -#[cfg(feature = "serde1")] +#[cfg(feature = "serde")] impl Serialize for NiceDuration { fn serialize(&self, ser: S) -> Result { use serde::ser::SerializeStruct; @@ -401,7 +403,7 @@ impl Serialize for NiceDuration { /// /// This stops trimming a prefix as soon as it sees non-whitespace or a line /// terminator. -pub fn trim_ascii_prefix( +pub(crate) fn trim_ascii_prefix( line_term: LineTerminator, slice: &[u8], range: Match, @@ -422,7 +424,7 @@ pub fn trim_ascii_prefix( range.with_start(range.start() + count) } -pub fn find_iter_at_in_context( +pub(crate) fn find_iter_at_in_context( searcher: &Searcher, matcher: M, mut bytes: &[u8], @@ -482,7 +484,7 @@ where /// Given a buf and some bounds, if there is a line terminator at the end of /// the given bounds in buf, then the bounds are trimmed to remove the line /// terminator. -pub fn trim_line_terminator( +pub(crate) fn trim_line_terminator( searcher: &Searcher, buf: &[u8], line: &mut Match,