mirror of
https://github.com/BurntSushi/ripgrep.git
synced 2025-05-19 09:40:22 -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:
parent
09905560ff
commit
23e21133ba
@ -18,8 +18,9 @@ use grep::pcre2::{
|
|||||||
RegexMatcherBuilder as PCRE2RegexMatcherBuilder,
|
RegexMatcherBuilder as PCRE2RegexMatcherBuilder,
|
||||||
};
|
};
|
||||||
use grep::printer::{
|
use grep::printer::{
|
||||||
default_color_specs, ColorSpecs, HyperlinkPattern, JSONBuilder, Standard,
|
default_color_specs, ColorSpecs, HyperlinkPattern, JSONBuilder,
|
||||||
StandardBuilder, Stats, Summary, SummaryBuilder, SummaryKind, JSON,
|
PathPrinter, PathPrinterBuilder, Standard, StandardBuilder, Stats,
|
||||||
|
Summary, SummaryBuilder, SummaryKind, JSON,
|
||||||
};
|
};
|
||||||
use grep::regex::{
|
use grep::regex::{
|
||||||
RegexMatcher as RustRegexMatcher,
|
RegexMatcher as RustRegexMatcher,
|
||||||
@ -38,7 +39,6 @@ use crate::app;
|
|||||||
use crate::config;
|
use crate::config;
|
||||||
use crate::logger::Logger;
|
use crate::logger::Logger;
|
||||||
use crate::messages::{set_ignore_messages, set_messages};
|
use crate::messages::{set_ignore_messages, set_messages};
|
||||||
use crate::path_printer::{PathPrinter, PathPrinterBuilder};
|
|
||||||
use crate::search::{
|
use crate::search::{
|
||||||
PatternMatcher, Printer, SearchWorker, SearchWorkerBuilder,
|
PatternMatcher, Printer, SearchWorker, SearchWorkerBuilder,
|
||||||
};
|
};
|
||||||
|
@ -16,7 +16,6 @@ mod app;
|
|||||||
mod args;
|
mod args;
|
||||||
mod config;
|
mod config;
|
||||||
mod logger;
|
mod logger;
|
||||||
mod path_printer;
|
|
||||||
mod search;
|
mod search;
|
||||||
mod subject;
|
mod subject;
|
||||||
|
|
||||||
@ -248,7 +247,7 @@ fn files(args: &Args) -> Result<bool> {
|
|||||||
if quit_after_match {
|
if quit_after_match {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if let Err(err) = path_printer.write_path(subject.path()) {
|
if let Err(err) = path_printer.write(subject.path()) {
|
||||||
// A broken pipe means graceful termination.
|
// A broken pipe means graceful termination.
|
||||||
if err.kind() == io::ErrorKind::BrokenPipe {
|
if err.kind() == io::ErrorKind::BrokenPipe {
|
||||||
break;
|
break;
|
||||||
@ -293,7 +292,7 @@ fn files_parallel(args: &Args) -> Result<bool> {
|
|||||||
|
|
||||||
let print_thread = thread::spawn(move || -> io::Result<()> {
|
let print_thread = thread::spawn(move || -> io::Result<()> {
|
||||||
for subject in rx.iter() {
|
for subject in rx.iter() {
|
||||||
path_printer.write_path(subject.path())?;
|
path_printer.write(subject.path())?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
});
|
});
|
||||||
|
@ -1,134 +0,0 @@
|
|||||||
use std::io;
|
|
||||||
use std::path::Path;
|
|
||||||
|
|
||||||
use grep::printer::{
|
|
||||||
ColorSpecs, HyperlinkPattern, HyperlinkSpan, PrinterPath,
|
|
||||||
};
|
|
||||||
use termcolor::WriteColor;
|
|
||||||
|
|
||||||
/// 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 constructing things to search over.
|
|
||||||
#[derive(Clone, Debug)]
|
|
||||||
pub struct PathPrinterBuilder {
|
|
||||||
config: Config,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PathPrinterBuilder {
|
|
||||||
/// Return a new subject 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 color specification for this printer.
|
|
||||||
///
|
|
||||||
/// Currently, only the `path` component of the given specification is
|
|
||||||
/// used.
|
|
||||||
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.
|
|
||||||
///
|
|
||||||
/// Colors need to be enabled for hyperlinks to be output.
|
|
||||||
pub fn hyperlink_pattern(
|
|
||||||
&mut self,
|
|
||||||
pattern: HyperlinkPattern,
|
|
||||||
) -> &mut PathPrinterBuilder {
|
|
||||||
self.config.hyperlink_pattern = pattern;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A path separator.
|
|
||||||
///
|
|
||||||
/// When provided, the path's default separator will be replaced with
|
|
||||||
/// the given separator.
|
|
||||||
///
|
|
||||||
/// This is not set by default, and the system's default path separator
|
|
||||||
/// will be used.
|
|
||||||
pub fn separator(&mut self, sep: Option<u8>) -> &mut PathPrinterBuilder {
|
|
||||||
self.config.separator = sep;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A path terminator.
|
|
||||||
///
|
|
||||||
/// When printing a path, it will be by terminated by the given byte.
|
|
||||||
///
|
|
||||||
/// This is set to `\n` by default.
|
|
||||||
pub fn terminator(&mut self, terminator: u8) -> &mut PathPrinterBuilder {
|
|
||||||
self.config.terminator = terminator;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A printer for emitting paths to a writer, with optional color support.
|
|
||||||
#[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_path(&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())
|
|
||||||
}
|
|
||||||
}
|
|
@ -59,7 +59,7 @@ pub enum HyperlinkPatternError {
|
|||||||
|
|
||||||
/// The values to replace the pattern placeholders with.
|
/// The values to replace the pattern placeholders with.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct HyperlinkValues<'a> {
|
pub(crate) struct HyperlinkValues<'a> {
|
||||||
file: &'a HyperlinkPath,
|
file: &'a HyperlinkPath,
|
||||||
line: u64,
|
line: u64,
|
||||||
column: 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
|
/// This is the value to use as-is in the hyperlink, converted from an OS file
|
||||||
/// path.
|
/// path.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct HyperlinkPath(Vec<u8>);
|
pub(crate) struct HyperlinkPath(Vec<u8>);
|
||||||
|
|
||||||
impl HyperlinkPatternBuilder {
|
impl HyperlinkPatternBuilder {
|
||||||
/// Creates a new hyperlink pattern builder.
|
/// Creates a new hyperlink pattern builder.
|
||||||
@ -222,7 +222,7 @@ impl HyperlinkPattern {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Renders this pattern with the given values to the given output.
|
/// Renders this pattern with the given values to the given output.
|
||||||
pub fn render(
|
pub(crate) fn render(
|
||||||
&self,
|
&self,
|
||||||
values: &HyperlinkValues,
|
values: &HyperlinkValues,
|
||||||
output: &mut impl Write,
|
output: &mut impl Write,
|
||||||
@ -353,7 +353,7 @@ impl std::error::Error for HyperlinkPatternError {}
|
|||||||
|
|
||||||
impl<'a> HyperlinkValues<'a> {
|
impl<'a> HyperlinkValues<'a> {
|
||||||
/// Creates a new set of hyperlink values.
|
/// Creates a new set of hyperlink values.
|
||||||
pub fn new(
|
pub(crate) fn new(
|
||||||
file: &'a HyperlinkPath,
|
file: &'a HyperlinkPath,
|
||||||
line: Option<u64>,
|
line: Option<u64>,
|
||||||
column: Option<u64>,
|
column: Option<u64>,
|
||||||
@ -369,7 +369,7 @@ impl<'a> HyperlinkValues<'a> {
|
|||||||
impl HyperlinkPath {
|
impl HyperlinkPath {
|
||||||
/// Returns a hyperlink path from an OS path.
|
/// Returns a hyperlink path from an OS path.
|
||||||
#[cfg(unix)]
|
#[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
|
// On Unix, this function returns the absolute file path without the
|
||||||
// leading slash, as it makes for more natural hyperlink patterns, for
|
// leading slash, as it makes for more natural hyperlink patterns, for
|
||||||
// instance:
|
// instance:
|
||||||
@ -506,14 +506,14 @@ impl std::fmt::Display for HyperlinkPath {
|
|||||||
/// A simple abstraction over a hyperlink span written to the terminal. This
|
/// A simple abstraction over a hyperlink span written to the terminal. This
|
||||||
/// helps tracking whether a hyperlink has been started, and should be ended.
|
/// helps tracking whether a hyperlink has been started, and should be ended.
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
pub struct HyperlinkSpan {
|
pub(crate) struct HyperlinkSpan {
|
||||||
active: bool,
|
active: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HyperlinkSpan {
|
impl HyperlinkSpan {
|
||||||
/// Starts a hyperlink and returns a span which tracks whether it is still
|
/// Starts a hyperlink and returns a span which tracks whether it is still
|
||||||
/// in effect.
|
/// in effect.
|
||||||
pub fn start(
|
pub(crate) fn start(
|
||||||
wtr: &mut impl WriteColor,
|
wtr: &mut impl WriteColor,
|
||||||
hyperlink: &HyperlinkSpec,
|
hyperlink: &HyperlinkSpec,
|
||||||
) -> io::Result<Self> {
|
) -> io::Result<Self> {
|
||||||
@ -526,7 +526,7 @@ impl HyperlinkSpan {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Ends the hyperlink span if it is active.
|
/// 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() {
|
if self.is_active() {
|
||||||
wtr.set_hyperlink(&HyperlinkSpec::close())?;
|
wtr.set_hyperlink(&HyperlinkSpec::close())?;
|
||||||
self.active = false;
|
self.active = false;
|
||||||
@ -535,7 +535,7 @@ impl HyperlinkSpan {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true if there is currently an active hyperlink.
|
/// Returns true if there is currently an active hyperlink.
|
||||||
pub fn is_active(&self) -> bool {
|
pub(crate) fn is_active(&self) -> bool {
|
||||||
self.active
|
self.active
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -65,13 +65,12 @@ assert_eq!(output, expected);
|
|||||||
pub use crate::{
|
pub use crate::{
|
||||||
color::{default_color_specs, ColorError, ColorSpecs, UserColorSpec},
|
color::{default_color_specs, ColorError, ColorSpecs, UserColorSpec},
|
||||||
hyperlink::{
|
hyperlink::{
|
||||||
HyperlinkPath, HyperlinkPattern, HyperlinkPatternBuilder,
|
HyperlinkPattern, HyperlinkPatternBuilder, HyperlinkPatternError,
|
||||||
HyperlinkPatternError, HyperlinkSpan, HyperlinkValues,
|
|
||||||
},
|
},
|
||||||
|
path::{PathPrinter, PathPrinterBuilder},
|
||||||
standard::{Standard, StandardBuilder, StandardSink},
|
standard::{Standard, StandardBuilder, StandardSink},
|
||||||
stats::Stats,
|
stats::Stats,
|
||||||
summary::{Summary, SummaryBuilder, SummaryKind, SummarySink},
|
summary::{Summary, SummaryBuilder, SummaryKind, SummarySink},
|
||||||
util::PrinterPath,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(feature = "serde")]
|
#[cfg(feature = "serde")]
|
||||||
@ -99,6 +98,7 @@ mod hyperlink_aliases;
|
|||||||
mod json;
|
mod json;
|
||||||
#[cfg(feature = "serde")]
|
#[cfg(feature = "serde")]
|
||||||
mod jsont;
|
mod jsont;
|
||||||
|
mod path;
|
||||||
mod standard;
|
mod standard;
|
||||||
mod stats;
|
mod stats;
|
||||||
mod summary;
|
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.
|
/// 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(
|
pub fn hyperlink_pattern(
|
||||||
&mut self,
|
&mut self,
|
||||||
pattern: HyperlinkPattern,
|
pattern: HyperlinkPattern,
|
||||||
|
@ -218,7 +218,15 @@ impl SummaryBuilder {
|
|||||||
|
|
||||||
/// Set the hyperlink pattern to use for hyperlinks output by this printer.
|
/// 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(
|
pub fn hyperlink_pattern(
|
||||||
&mut self,
|
&mut self,
|
||||||
pattern: HyperlinkPattern,
|
pattern: HyperlinkPattern,
|
||||||
|
@ -280,7 +280,7 @@ impl<'a> Sunk<'a> {
|
|||||||
/// portability with a small cost: on Windows, paths that are not valid UTF-16
|
/// portability with a small cost: on Windows, paths that are not valid UTF-16
|
||||||
/// will not roundtrip correctly.
|
/// will not roundtrip correctly.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct PrinterPath<'a> {
|
pub(crate) struct PrinterPath<'a> {
|
||||||
path: &'a Path,
|
path: &'a Path,
|
||||||
bytes: Cow<'a, [u8]>,
|
bytes: Cow<'a, [u8]>,
|
||||||
hyperlink_path: std::cell::OnceCell<Option<HyperlinkPath>>,
|
hyperlink_path: std::cell::OnceCell<Option<HyperlinkPath>>,
|
||||||
@ -288,7 +288,7 @@ pub struct PrinterPath<'a> {
|
|||||||
|
|
||||||
impl<'a> PrinterPath<'a> {
|
impl<'a> PrinterPath<'a> {
|
||||||
/// Create a new path suitable for printing.
|
/// 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 {
|
PrinterPath {
|
||||||
path,
|
path,
|
||||||
bytes: Vec::from_path_lossy(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
|
/// If the given separator is present, then any separators in `path` are
|
||||||
/// replaced with it.
|
/// 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);
|
let mut ppath = PrinterPath::new(path);
|
||||||
if let Some(sep) = sep {
|
if let Some(sep) = sep {
|
||||||
ppath.replace_separator(sep);
|
ppath.replace_separator(sep);
|
||||||
@ -329,13 +332,13 @@ impl<'a> PrinterPath<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Return the raw bytes for this path.
|
/// Return the raw bytes for this path.
|
||||||
pub fn as_bytes(&self) -> &[u8] {
|
pub(crate) fn as_bytes(&self) -> &[u8] {
|
||||||
&self.bytes
|
&self.bytes
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a hyperlink for this path and the given line and column, using
|
/// Creates a hyperlink for this path and the given line and column, using
|
||||||
/// the specified pattern. Uses the given buffer to store the hyperlink.
|
/// 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,
|
&self,
|
||||||
pattern: &HyperlinkPattern,
|
pattern: &HyperlinkPattern,
|
||||||
line_number: Option<u64>,
|
line_number: Option<u64>,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user