mirror of
https://github.com/BurntSushi/ripgrep.git
synced 2025-08-05 14:42:07 -07:00
printer: move PathPrinter into grep-printer
I originally did not put PathPrinter into grep-printer because I considered it somewhat extraneous to what a "grep" program does, and also that its implementation was rather simple. But now with hyperlink support, its implementation has grown a smidge more complicated. And more importantly, its existence required exposing a lot more of the hyperlink guts. Without it, we can keep things like HyperlinkPath and HyperlinkSpan completely private. We can now also keep `PrinterPath` completely private as well. And this is a breaking change.
This commit is contained in:
179
crates/printer/src/path.rs
Normal file
179
crates/printer/src/path.rs
Normal file
@@ -0,0 +1,179 @@
|
||||
use std::{io, path::Path};
|
||||
|
||||
use termcolor::WriteColor;
|
||||
|
||||
use crate::{
|
||||
color::ColorSpecs,
|
||||
hyperlink::{HyperlinkPattern, HyperlinkSpan},
|
||||
util::PrinterPath,
|
||||
};
|
||||
|
||||
/// A configuration for describing how paths should be written.
|
||||
#[derive(Clone, Debug)]
|
||||
struct Config {
|
||||
colors: ColorSpecs,
|
||||
hyperlink_pattern: HyperlinkPattern,
|
||||
separator: Option<u8>,
|
||||
terminator: u8,
|
||||
}
|
||||
|
||||
impl Default for Config {
|
||||
fn default() -> Config {
|
||||
Config {
|
||||
colors: ColorSpecs::default(),
|
||||
hyperlink_pattern: HyperlinkPattern::default(),
|
||||
separator: None,
|
||||
terminator: b'\n',
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A builder for a printer that emits file paths.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct PathPrinterBuilder {
|
||||
config: Config,
|
||||
}
|
||||
|
||||
impl PathPrinterBuilder {
|
||||
/// Return a new path printer builder with a default configuration.
|
||||
pub fn new() -> PathPrinterBuilder {
|
||||
PathPrinterBuilder { config: Config::default() }
|
||||
}
|
||||
|
||||
/// Create a new path printer with the current configuration that writes
|
||||
/// paths to the given writer.
|
||||
pub fn build<W: WriteColor>(&self, wtr: W) -> PathPrinter<W> {
|
||||
PathPrinter { config: self.config.clone(), wtr, buf: vec![] }
|
||||
}
|
||||
|
||||
/// Set the user color specifications to use for coloring in this printer.
|
||||
///
|
||||
/// A [`UserColorSpec`](crate::UserColorSpec) can be constructed from
|
||||
/// a string in accordance with the color specification format. See
|
||||
/// the `UserColorSpec` type documentation for more details on the
|
||||
/// format. A [`ColorSpecs`] can then be generated from zero or more
|
||||
/// `UserColorSpec`s.
|
||||
///
|
||||
/// Regardless of the color specifications provided here, whether color
|
||||
/// is actually used or not is determined by the implementation of
|
||||
/// `WriteColor` provided to `build`. For example, if `termcolor::NoColor`
|
||||
/// is provided to `build`, then no color will ever be printed regardless
|
||||
/// of the color specifications provided here.
|
||||
///
|
||||
/// This completely overrides any previous color specifications. This does
|
||||
/// not add to any previously provided color specifications on this
|
||||
/// builder.
|
||||
///
|
||||
/// The default color specifications provide no styling.
|
||||
pub fn color_specs(
|
||||
&mut self,
|
||||
specs: ColorSpecs,
|
||||
) -> &mut PathPrinterBuilder {
|
||||
self.config.colors = specs;
|
||||
self
|
||||
}
|
||||
|
||||
/// Set the hyperlink pattern to use for hyperlinks output by this printer.
|
||||
///
|
||||
/// Regardless of the hyperlink format provided here, whether hyperlinks
|
||||
/// are actually used or not is determined by the implementation of
|
||||
/// `WriteColor` provided to `build`. For example, if `termcolor::NoColor`
|
||||
/// is provided to `build`, then no hyperlinks will ever be printed
|
||||
/// regardless of the format provided here.
|
||||
///
|
||||
/// This completely overrides any previous hyperlink format.
|
||||
///
|
||||
/// The default pattern format results in not emitting any hyperlinks.
|
||||
pub fn hyperlink_pattern(
|
||||
&mut self,
|
||||
pattern: HyperlinkPattern,
|
||||
) -> &mut PathPrinterBuilder {
|
||||
self.config.hyperlink_pattern = pattern;
|
||||
self
|
||||
}
|
||||
|
||||
/// Set the path separator used when printing file paths.
|
||||
///
|
||||
/// Typically, printing is done by emitting the file path as is. However,
|
||||
/// this setting provides the ability to use a different path separator
|
||||
/// from what the current environment has configured.
|
||||
///
|
||||
/// A typical use for this option is to permit cygwin users on Windows to
|
||||
/// set the path separator to `/` instead of using the system default of
|
||||
/// `\`.
|
||||
///
|
||||
/// This is disabled by default.
|
||||
pub fn separator(&mut self, sep: Option<u8>) -> &mut PathPrinterBuilder {
|
||||
self.config.separator = sep;
|
||||
self
|
||||
}
|
||||
|
||||
/// Set the path terminator used.
|
||||
///
|
||||
/// The path terminator is a byte that is printed after every file path
|
||||
/// emitted by this printer.
|
||||
///
|
||||
/// The default path terminator is `\n`.
|
||||
pub fn terminator(&mut self, terminator: u8) -> &mut PathPrinterBuilder {
|
||||
self.config.terminator = terminator;
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
/// A printer file paths, with optional color and hyperlink support.
|
||||
///
|
||||
/// This printer is very similar to [`Summary`](crate::Summary) in that it
|
||||
/// principally only emits file paths. The main difference is that this printer
|
||||
/// doesn't actually execute any search via a `Sink` implementation, and instead
|
||||
/// just provides a way for the caller to print paths.
|
||||
///
|
||||
/// A caller could just print the paths themselves, but this printer handles
|
||||
/// a few details:
|
||||
///
|
||||
/// * It can normalize path separators.
|
||||
/// * It permits configuring the terminator.
|
||||
/// * It allows setting the color configuration in a way that is consistent
|
||||
/// with the other printers in this crate.
|
||||
/// * It allows setting the hyperlink format in a way that is consistent
|
||||
/// with the other printers in this crate.
|
||||
#[derive(Debug)]
|
||||
pub struct PathPrinter<W> {
|
||||
config: Config,
|
||||
wtr: W,
|
||||
buf: Vec<u8>,
|
||||
}
|
||||
|
||||
impl<W: WriteColor> PathPrinter<W> {
|
||||
/// Write the given path to the underlying writer.
|
||||
pub fn write(&mut self, path: &Path) -> io::Result<()> {
|
||||
let ppath = PrinterPath::with_separator(path, self.config.separator);
|
||||
if !self.wtr.supports_color() {
|
||||
self.wtr.write_all(ppath.as_bytes())?;
|
||||
} else {
|
||||
let mut hyperlink = self.start_hyperlink_span(&ppath)?;
|
||||
self.wtr.set_color(self.config.colors.path())?;
|
||||
self.wtr.write_all(ppath.as_bytes())?;
|
||||
self.wtr.reset()?;
|
||||
hyperlink.end(&mut self.wtr)?;
|
||||
}
|
||||
self.wtr.write_all(&[self.config.terminator])
|
||||
}
|
||||
|
||||
/// Starts a hyperlink span when applicable.
|
||||
fn start_hyperlink_span(
|
||||
&mut self,
|
||||
path: &PrinterPath,
|
||||
) -> io::Result<HyperlinkSpan> {
|
||||
if self.wtr.supports_hyperlinks() {
|
||||
if let Some(spec) = path.create_hyperlink_spec(
|
||||
&self.config.hyperlink_pattern,
|
||||
None,
|
||||
None,
|
||||
&mut self.buf,
|
||||
) {
|
||||
return Ok(HyperlinkSpan::start(&mut self.wtr, &spec)?);
|
||||
}
|
||||
}
|
||||
Ok(HyperlinkSpan::default())
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user