From 1dc328ad495edbd98bff9e89a059d1e66f9780ef Mon Sep 17 00:00:00 2001 From: sharkdp Date: Tue, 21 Apr 2020 21:14:44 +0200 Subject: [PATCH] Separate inputs from config --- examples/cat.rs | 10 ++++++---- examples/simple.rs | 9 +++++---- src/assets.rs | 1 + src/bin/bat/app.rs | 14 +++++++++----- src/bin/bat/main.rs | 20 +++++++++++--------- src/config.rs | 3 --- src/controller.rs | 20 ++++++++++++-------- src/inputfile.rs | 5 +++-- src/pretty_printer.rs | 12 ++++++------ src/printer.rs | 8 ++++++++ 10 files changed, 61 insertions(+), 41 deletions(-) diff --git a/examples/cat.rs b/examples/cat.rs index 4575add0..c529bd6a 100644 --- a/examples/cat.rs +++ b/examples/cat.rs @@ -4,14 +4,16 @@ use bat::{PrettyPrinter, StyleComponent, StyleComponents}; use console::Term; fn main() { - PrettyPrinter::new() + let mut printer = PrettyPrinter::new(); + + printer .term_width(Term::stdout().size().1 as usize) .style_components(StyleComponents::new(&[ StyleComponent::Header, StyleComponent::Grid, StyleComponent::Numbers, ])) - .files(std::env::args_os().skip(1)) - .run() - .expect("no errors"); + .files(std::env::args_os().skip(1)); + + printer.run().expect("no errors"); } diff --git a/examples/simple.rs b/examples/simple.rs index 0a6b3d0d..a035b6c5 100644 --- a/examples/simple.rs +++ b/examples/simple.rs @@ -5,8 +5,9 @@ use std::ffi::OsStr; fn main() { let path_to_this_file = OsStr::new(file!()); - PrettyPrinter::new() - .file(path_to_this_file) - .run() - .expect("no errors"); + let mut printer = PrettyPrinter::new(); + + printer.file(path_to_this_file); + + printer.run().expect("no errors"); } diff --git a/src/assets.rs b/src/assets.rs index 916d03b3..e4e93363 100644 --- a/src/assets.rs +++ b/src/assets.rs @@ -219,6 +219,7 @@ impl HighlightingAssets { .get_extension_syntax(&file_name) .or(self.get_first_line_syntax(reader)), (_, InputFile::ThemePreviewFile) => self.syntax_set.find_syntax_by_name("Rust"), + (None, InputFile::FromReader(s, _)) => None, }; syntax.unwrap_or_else(|| self.syntax_set.find_syntax_plain_text()) diff --git a/src/bin/bat/app.rs b/src/bin/bat/app.rs index 5c2031d1..2fc1d8c4 100644 --- a/src/bin/bat/app.rs +++ b/src/bin/bat/app.rs @@ -73,8 +73,7 @@ impl App { Ok(clap_app::build_app(interactive_output).get_matches_from(args)) } - pub fn config(&self) -> Result { - let files = self.files()?; + pub fn config(&self, inputs: &[InputFile]) -> Result { let style_components = self.style_components()?; let paging_mode = match self.matches.value_of("paging") { @@ -84,7 +83,13 @@ impl App { if self.matches.occurrences_of("plain") > 1 { // If we have -pp as an option when in auto mode, the pager should be disabled. PagingMode::Never - } else if files.contains(&InputFile::StdIn(None)) { + } else if inputs.iter().any(|f| { + if let InputFile::StdIn(None) = f { + true + } else { + false + } + }) { // If we are reading from stdin, only enable paging if we write to an // interactive terminal and if we do not *read* from an interactive // terminal. @@ -170,7 +175,6 @@ impl App { loop_through: !(self.interactive_output || self.matches.value_of("color") == Some("always") || self.matches.value_of("decorations") == Some("always")), - files, tab_width: self .matches .value_of("tabs") @@ -222,7 +226,7 @@ impl App { }) } - fn files(&self) -> Result> { + pub fn inputs(&self) -> Result> { // verify equal length of file-names and input FILEs match self.matches.values_of("file-name") { Some(ref filenames) diff --git a/src/bin/bat/main.rs b/src/bin/bat/main.rs index 3b59b896..88ad2c7c 100644 --- a/src/bin/bat/main.rs +++ b/src/bin/bat/main.rs @@ -120,7 +120,6 @@ pub fn list_themes(cfg: &Config) -> Result<()> { let mut config = cfg.clone(); let mut style = HashSet::new(); style.insert(StyleComponent::Plain); - config.files = vec![InputFile::ThemePreviewFile]; config.style_components = StyleComponents(style); let stdout = io::stdout(); @@ -134,7 +133,9 @@ pub fn list_themes(cfg: &Config) -> Result<()> { Style::new().bold().paint(theme.to_string()) )?; config.theme = theme.to_string(); - let _controller = Controller::new(&config, &assets).run(); + Controller::new(&config, &assets) + .run(vec![InputFile::ThemePreviewFile]) + .ok(); writeln!(stdout)?; } } else { @@ -146,10 +147,10 @@ pub fn list_themes(cfg: &Config) -> Result<()> { Ok(()) } -fn run_controller(config: &Config) -> Result { +fn run_controller(inputs: Vec, config: &Config) -> Result { let assets = assets_from_cache_or_binary()?; let controller = Controller::new(&config, &assets); - controller.run() + controller.run(inputs) } /// Returns `Err(..)` upon fatal errors. Otherwise, returns `Ok(true)` on full success and @@ -166,16 +167,17 @@ fn run() -> Result { run_cache_subcommand(cache_matches)?; Ok(true) } else { - let mut config = app.config()?; - config.files = vec![InputFile::Ordinary(OrdinaryFile::from_path(OsStr::new( + let inputs = vec![InputFile::Ordinary(OrdinaryFile::from_path(OsStr::new( "cache", )))]; + let mut config = app.config(&inputs)?; - run_controller(&config) + run_controller(inputs, &config) } } _ => { - let config = app.config()?; + let inputs = app.inputs()?; + let config = app.config(&inputs)?; if app.matches.is_present("list-languages") { list_languages(&config)?; @@ -196,7 +198,7 @@ fn run() -> Result { writeln!(io::stdout(), "{}", cache_dir())?; Ok(true) } else { - run_controller(&config) + run_controller(inputs, &config) } } } diff --git a/src/config.rs b/src/config.rs index b200af57..42ff6bdc 100644 --- a/src/config.rs +++ b/src/config.rs @@ -22,9 +22,6 @@ impl Default for PagingMode { #[derive(Debug, Clone, Default)] pub struct Config<'a> { - /// List of files to print - pub files: Vec, - /// The explicitly configured language, if any pub language: Option<&'a str>, diff --git a/src/controller.rs b/src/controller.rs index f4fc646b..f227446e 100644 --- a/src/controller.rs +++ b/src/controller.rs @@ -20,11 +20,15 @@ impl<'b> Controller<'b> { Controller { config, assets } } - pub fn run(&self) -> Result { - self.run_with_error_handler(default_error_handler) + pub fn run(&self, inputs: Vec) -> Result { + self.run_with_error_handler(inputs, default_error_handler) } - pub fn run_with_error_handler(&self, handle_error: impl Fn(&Error)) -> Result { + pub fn run_with_error_handler( + &self, + inputs: Vec, + handle_error: impl Fn(&Error), + ) -> Result { let mut output_type; #[cfg(feature = "paging")] @@ -34,7 +38,7 @@ impl<'b> Controller<'b> { // Do not launch the pager if NONE of the input files exist let mut paging_mode = self.config.paging_mode; if self.config.paging_mode != PagingMode::Never { - let call_pager = self.config.files.iter().any(|file| { + let call_pager = inputs.iter().any(|file| { if let InputFile::Ordinary(ofile) = file { return Path::new(ofile.provided_path()).exists(); } else { @@ -56,7 +60,7 @@ impl<'b> Controller<'b> { let writer = output_type.handle()?; let mut no_errors: bool = true; - for input_file in self.config.files.iter() { + for input_file in inputs.into_iter() { match input_file.get_reader(io::stdin().lock()) { Err(error) => { handle_error(&error); @@ -65,15 +69,15 @@ impl<'b> Controller<'b> { Ok(mut reader) => { let result = if self.config.loop_through { let mut printer = SimplePrinter::new(); - self.print_file(reader, &mut printer, writer, input_file) + self.print_file(reader, &mut printer, writer, &input_file) } else { let mut printer = InteractivePrinter::new( &self.config, &self.assets, - input_file, + &input_file, &mut reader, ); - self.print_file(reader, &mut printer, writer, input_file) + self.print_file(reader, &mut printer, writer, &input_file) }; if let Err(error) = result { diff --git a/src/inputfile.rs b/src/inputfile.rs index 8e29ce57..1a9a3a4e 100644 --- a/src/inputfile.rs +++ b/src/inputfile.rs @@ -1,6 +1,6 @@ use std::ffi::{OsStr, OsString}; use std::fs::File; -use std::io::{self, BufRead, BufReader}; +use std::io::{self, BufRead, BufReader, Read}; use content_inspector::{self, ContentType}; @@ -77,10 +77,10 @@ impl OrdinaryFile { } } -#[derive(Debug, Clone, PartialEq)] pub enum InputFile { StdIn(Option), Ordinary(OrdinaryFile), + FromReader(Box, Option), ThemePreviewFile, } @@ -101,6 +101,7 @@ impl InputFile { Ok(InputFileReader::new(BufReader::new(file))) } InputFile::ThemePreviewFile => Ok(InputFileReader::new(THEME_PREVIEW_FILE)), + InputFile::FromReader(reader, _) => unimplemented!(), //Ok(InputFileReader::new(BufReader::new(reader))), } } } diff --git a/src/pretty_printer.rs b/src/pretty_printer.rs index 4c9850ea..03774397 100644 --- a/src/pretty_printer.rs +++ b/src/pretty_printer.rs @@ -13,6 +13,7 @@ use crate::{ use crate::config::PagingMode; pub struct PrettyPrinter<'a> { + inputs: Vec, config: Config<'a>, assets: HighlightingAssets, } @@ -25,6 +26,7 @@ impl<'a> PrettyPrinter<'a> { config.true_color = true; PrettyPrinter { + inputs: vec![], config, assets: HighlightingAssets::from_binary(), } @@ -32,8 +34,7 @@ impl<'a> PrettyPrinter<'a> { /// Add a file which should be pretty-printed pub fn file(&mut self, path: &OsStr) -> &mut Self { - self.config - .files + self.inputs .push(InputFile::Ordinary(OrdinaryFile::from_path(path))); self } @@ -45,8 +46,7 @@ impl<'a> PrettyPrinter<'a> { P: AsRef, { for path in paths { - self.config - .files + self.inputs .push(InputFile::Ordinary(OrdinaryFile::from_path(path.as_ref()))); } self @@ -137,8 +137,8 @@ impl<'a> PrettyPrinter<'a> { self } - pub fn run(&'a self) -> Result { + pub fn run(self) -> Result { let controller = Controller::new(&self.config, &self.assets); - controller.run() + controller.run(self.inputs) } } diff --git a/src/printer.rs b/src/printer.rs index d7d5405d..8e582f80 100644 --- a/src/printer.rs +++ b/src/printer.rs @@ -243,6 +243,10 @@ impl<'a> Printer for InteractivePrinter<'a> { ), InputFile::StdIn(None) => "STDIN".to_owned(), InputFile::ThemePreviewFile => "".to_owned(), + InputFile::FromReader(_, Some(name)) => { + format!("file '{}'", name.to_string_lossy()) + } + InputFile::FromReader(_, None) => "READER".to_owned(), }; writeln!( @@ -286,6 +290,10 @@ impl<'a> Printer for InteractivePrinter<'a> { } InputFile::StdIn(None) => ("File: ", Cow::from("STDIN".to_owned())), InputFile::ThemePreviewFile => ("", Cow::from("")), + InputFile::FromReader(_, Some(name)) => { + ("File: ", Cow::from(name.to_string_lossy().to_owned())) + } + InputFile::FromReader(_, None) => ("File: ", Cow::from("READER".to_owned())), }; let mode = match self.content_type {