mirror of
				https://github.com/BurntSushi/ripgrep.git
				synced 2025-10-30 23:17:47 +02: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:
		| @@ -59,7 +59,7 @@ pub enum HyperlinkPatternError { | ||||
|  | ||||
| /// The values to replace the pattern placeholders with. | ||||
| #[derive(Clone, Debug)] | ||||
| pub struct HyperlinkValues<'a> { | ||||
| pub(crate) struct HyperlinkValues<'a> { | ||||
|     file: &'a HyperlinkPath, | ||||
|     line: u64, | ||||
|     column: u64, | ||||
| @@ -70,7 +70,7 @@ pub struct HyperlinkValues<'a> { | ||||
| /// This is the value to use as-is in the hyperlink, converted from an OS file | ||||
| /// path. | ||||
| #[derive(Clone, Debug)] | ||||
| pub struct HyperlinkPath(Vec<u8>); | ||||
| pub(crate) struct HyperlinkPath(Vec<u8>); | ||||
|  | ||||
| impl HyperlinkPatternBuilder { | ||||
|     /// Creates a new hyperlink pattern builder. | ||||
| @@ -222,7 +222,7 @@ impl HyperlinkPattern { | ||||
|     } | ||||
|  | ||||
|     /// Renders this pattern with the given values to the given output. | ||||
|     pub fn render( | ||||
|     pub(crate) fn render( | ||||
|         &self, | ||||
|         values: &HyperlinkValues, | ||||
|         output: &mut impl Write, | ||||
| @@ -353,7 +353,7 @@ impl std::error::Error for HyperlinkPatternError {} | ||||
|  | ||||
| impl<'a> HyperlinkValues<'a> { | ||||
|     /// Creates a new set of hyperlink values. | ||||
|     pub fn new( | ||||
|     pub(crate) fn new( | ||||
|         file: &'a HyperlinkPath, | ||||
|         line: Option<u64>, | ||||
|         column: Option<u64>, | ||||
| @@ -369,7 +369,7 @@ impl<'a> HyperlinkValues<'a> { | ||||
| impl HyperlinkPath { | ||||
|     /// Returns a hyperlink path from an OS path. | ||||
|     #[cfg(unix)] | ||||
|     pub fn from_path(path: &Path) -> Option<Self> { | ||||
|     pub(crate) fn from_path(path: &Path) -> Option<Self> { | ||||
|         // On Unix, this function returns the absolute file path without the | ||||
|         // leading slash, as it makes for more natural hyperlink patterns, for | ||||
|         // instance: | ||||
| @@ -506,14 +506,14 @@ impl std::fmt::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. | ||||
| #[derive(Debug, Default)] | ||||
| pub struct HyperlinkSpan { | ||||
| pub(crate) struct HyperlinkSpan { | ||||
|     active: bool, | ||||
| } | ||||
|  | ||||
| impl HyperlinkSpan { | ||||
|     /// Starts a hyperlink and returns a span which tracks whether it is still | ||||
|     /// in effect. | ||||
|     pub fn start( | ||||
|     pub(crate) fn start( | ||||
|         wtr: &mut impl WriteColor, | ||||
|         hyperlink: &HyperlinkSpec, | ||||
|     ) -> io::Result<Self> { | ||||
| @@ -526,7 +526,7 @@ impl HyperlinkSpan { | ||||
|     } | ||||
|  | ||||
|     /// Ends the hyperlink span if it is active. | ||||
|     pub fn end(&mut self, wtr: &mut impl WriteColor) -> io::Result<()> { | ||||
|     pub(crate) fn end(&mut self, wtr: &mut impl WriteColor) -> io::Result<()> { | ||||
|         if self.is_active() { | ||||
|             wtr.set_hyperlink(&HyperlinkSpec::close())?; | ||||
|             self.active = false; | ||||
| @@ -535,7 +535,7 @@ impl HyperlinkSpan { | ||||
|     } | ||||
|  | ||||
|     /// Returns true if there is currently an active hyperlink. | ||||
|     pub fn is_active(&self) -> bool { | ||||
|     pub(crate) fn is_active(&self) -> bool { | ||||
|         self.active | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -65,13 +65,12 @@ assert_eq!(output, expected); | ||||
| pub use crate::{ | ||||
|     color::{default_color_specs, ColorError, ColorSpecs, UserColorSpec}, | ||||
|     hyperlink::{ | ||||
|         HyperlinkPath, HyperlinkPattern, HyperlinkPatternBuilder, | ||||
|         HyperlinkPatternError, HyperlinkSpan, HyperlinkValues, | ||||
|         HyperlinkPattern, HyperlinkPatternBuilder, HyperlinkPatternError, | ||||
|     }, | ||||
|     path::{PathPrinter, PathPrinterBuilder}, | ||||
|     standard::{Standard, StandardBuilder, StandardSink}, | ||||
|     stats::Stats, | ||||
|     summary::{Summary, SummaryBuilder, SummaryKind, SummarySink}, | ||||
|     util::PrinterPath, | ||||
| }; | ||||
|  | ||||
| #[cfg(feature = "serde")] | ||||
| @@ -99,6 +98,7 @@ mod hyperlink_aliases; | ||||
| mod json; | ||||
| #[cfg(feature = "serde")] | ||||
| mod jsont; | ||||
| mod path; | ||||
| mod standard; | ||||
| mod stats; | ||||
| mod summary; | ||||
|   | ||||
							
								
								
									
										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()) | ||||
|     } | ||||
| } | ||||
| @@ -172,7 +172,15 @@ impl StandardBuilder { | ||||
|  | ||||
|     /// Set the hyperlink pattern to use for hyperlinks output by this printer. | ||||
|     /// | ||||
|     /// Colors need to be enabled for hyperlinks to be output. | ||||
|     /// 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, | ||||
|   | ||||
| @@ -218,7 +218,15 @@ impl SummaryBuilder { | ||||
|  | ||||
|     /// Set the hyperlink pattern to use for hyperlinks output by this printer. | ||||
|     /// | ||||
|     /// Colors need to be enabled for hyperlinks to be output. | ||||
|     /// 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, | ||||
|   | ||||
| @@ -280,7 +280,7 @@ impl<'a> Sunk<'a> { | ||||
| /// portability with a small cost: on Windows, paths that are not valid UTF-16 | ||||
| /// will not roundtrip correctly. | ||||
| #[derive(Clone, Debug)] | ||||
| pub struct PrinterPath<'a> { | ||||
| pub(crate) struct PrinterPath<'a> { | ||||
|     path: &'a Path, | ||||
|     bytes: Cow<'a, [u8]>, | ||||
|     hyperlink_path: std::cell::OnceCell<Option<HyperlinkPath>>, | ||||
| @@ -288,7 +288,7 @@ pub struct PrinterPath<'a> { | ||||
|  | ||||
| impl<'a> PrinterPath<'a> { | ||||
|     /// Create a new path suitable for printing. | ||||
|     pub fn new(path: &'a Path) -> PrinterPath<'a> { | ||||
|     pub(crate) fn new(path: &'a Path) -> PrinterPath<'a> { | ||||
|         PrinterPath { | ||||
|             path, | ||||
|             bytes: Vec::from_path_lossy(path), | ||||
| @@ -301,7 +301,10 @@ impl<'a> PrinterPath<'a> { | ||||
|     /// | ||||
|     /// If the given separator is present, then any separators in `path` are | ||||
|     /// replaced with it. | ||||
|     pub fn with_separator(path: &'a Path, sep: Option<u8>) -> PrinterPath<'a> { | ||||
|     pub(crate) fn with_separator( | ||||
|         path: &'a Path, | ||||
|         sep: Option<u8>, | ||||
|     ) -> PrinterPath<'a> { | ||||
|         let mut ppath = PrinterPath::new(path); | ||||
|         if let Some(sep) = sep { | ||||
|             ppath.replace_separator(sep); | ||||
| @@ -329,13 +332,13 @@ impl<'a> PrinterPath<'a> { | ||||
|     } | ||||
|  | ||||
|     /// Return the raw bytes for this path. | ||||
|     pub fn as_bytes(&self) -> &[u8] { | ||||
|     pub(crate) fn as_bytes(&self) -> &[u8] { | ||||
|         &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. | ||||
|     pub fn create_hyperlink_spec<'b>( | ||||
|     pub(crate) fn create_hyperlink_spec<'b>( | ||||
|         &self, | ||||
|         pattern: &HyperlinkPattern, | ||||
|         line_number: Option<u64>, | ||||
|   | ||||
		Reference in New Issue
	
	Block a user