From 590960f7f5b5454c2da8c36409a8d57a58b2980c Mon Sep 17 00:00:00 2001 From: sharkdp Date: Wed, 22 Apr 2020 16:27:34 +0200 Subject: [PATCH] Completely refactor 'input' module --- src/assets.rs | 86 ++++++++++--------- src/bin/bat/app.rs | 37 ++++---- src/bin/bat/main.rs | 9 +- src/config.rs | 2 - src/controller.rs | 52 ++++++----- src/input.rs | 195 +++++++++++++++++++++++++----------------- src/lib.rs | 2 +- src/pretty_printer.rs | 14 +-- src/printer.rs | 36 ++++---- 9 files changed, 233 insertions(+), 200 deletions(-) diff --git a/src/assets.rs b/src/assets.rs index f6b10b3a..6e3190a0 100644 --- a/src/assets.rs +++ b/src/assets.rs @@ -10,7 +10,7 @@ use syntect::parsing::{SyntaxReference, SyntaxSet, SyntaxSetBuilder}; use crate::assets_metadata::AssetsMetadata; use crate::errors::*; -use crate::input::{Input, InputReader}; +use crate::input::{Input, InputKind, InputReader, OpenedInput, OpenedInputKind}; use crate::syntax_mapping::{MappingTarget, SyntaxMapping}; #[derive(Debug)] @@ -188,38 +188,46 @@ impl HighlightingAssets { pub(crate) fn get_syntax( &self, language: Option<&str>, - input: &Input, - reader: &mut InputReader, + input: &mut OpenedInput, mapping: &SyntaxMapping, ) -> &SyntaxReference { - let syntax = match (language, input) { - (Some(language), _) => self.syntax_set.find_syntax_by_token(language), - (None, Input::Ordinary(ofile)) => { - let path = Path::new(ofile.provided_path()); - let line_syntax = self.get_first_line_syntax(reader); + let syntax = if let Some(language) = language { + self.syntax_set.find_syntax_by_token(language) + } else { + match input.kind { + OpenedInputKind::OrdinaryFile(ref actual_path) => { + let path_str = input + .metadata + .user_provided_name + .as_ref() + .unwrap_or(actual_path); + let path = Path::new(path_str); + let line_syntax = self.get_first_line_syntax(&mut input.reader); - let absolute_path = path.canonicalize().ok().unwrap_or(path.to_owned()); - match mapping.get_syntax_for(absolute_path) { - Some(MappingTarget::MapTo(syntax_name)) => { - // TODO: we should probably return an error here if this syntax can not be - // found. Currently, we just fall back to 'plain'. - self.syntax_set.find_syntax_by_name(syntax_name) - } - Some(MappingTarget::MapToUnknown) => line_syntax, - None => { - let file_name = path.file_name().unwrap_or_default(); - self.get_extension_syntax(file_name).or(line_syntax) + let absolute_path = path.canonicalize().ok().unwrap_or(path.to_owned()); + match mapping.get_syntax_for(absolute_path) { + Some(MappingTarget::MapTo(syntax_name)) => { + // TODO: we should probably return an error here if this syntax can not be + // found. Currently, we just fall back to 'plain'. + self.syntax_set.find_syntax_by_name(syntax_name) + } + Some(MappingTarget::MapToUnknown) => line_syntax, + None => { + let file_name = path.file_name().unwrap_or_default(); + self.get_extension_syntax(file_name).or(line_syntax) + } } } + OpenedInputKind::StdIn | OpenedInputKind::CustomReader => { + if let Some(ref name) = input.metadata.user_provided_name { + self.get_extension_syntax(&name) + .or(self.get_first_line_syntax(&mut input.reader)) + } else { + self.get_first_line_syntax(&mut input.reader) + } + } + OpenedInputKind::ThemePreviewFile => self.syntax_set.find_syntax_by_name("Rust"), } - (None, Input::StdIn(None)) => String::from_utf8(reader.first_line.clone()) - .ok() - .and_then(|l| self.syntax_set.find_syntax_by_first_line(&l)), - (None, Input::StdIn(Some(file_name))) => self - .get_extension_syntax(&file_name) - .or(self.get_first_line_syntax(reader)), - (_, Input::ThemePreviewFile) => self.syntax_set.find_syntax_by_name("Rust"), - (None, Input::FromReader(_, _)) => unimplemented!(), }; syntax.unwrap_or_else(|| self.syntax_set.find_syntax_plain_text()) @@ -249,8 +257,6 @@ impl HighlightingAssets { mod tests { use super::*; - use crate::input::OrdinaryFile; - use std::ffi::{OsStr, OsString}; use std::fs::File; use std::io; @@ -281,12 +287,12 @@ mod tests { writeln!(temp_file, "{}", first_line).unwrap(); } - let input = Input::Ordinary(OrdinaryFile::from_path(file_path.as_os_str())); - let stdin = io::stdin(); - let mut reader = input.get_reader(stdin.lock()).unwrap(); + let input: Input = Input::ordinary_file(file_path.as_os_str()); + let dummy_stdin: &[u8] = &[]; + let mut opened_input = input.open(dummy_stdin).unwrap(); let syntax = self .assets - .get_syntax(None, &input, &mut reader, &self.syntax_mapping); + .get_syntax(None, &mut opened_input, &self.syntax_mapping); syntax.name.clone() } @@ -304,13 +310,13 @@ mod tests { } fn syntax_for_stdin_with_content(&self, file_name: &str, content: &[u8]) -> String { - let input = Input::StdIn(Some(OsString::from(file_name))); - let syntax = self.assets.get_syntax( - None, - &input, - &mut input.get_reader(content).unwrap(), - &self.syntax_mapping, - ); + let mut input = Input::stdin(); + input.set_provided_name(Some(OsStr::new(file_name))); + let mut opened_input = input.open(content).unwrap(); + + let syntax = self + .assets + .get_syntax(None, &mut opened_input, &self.syntax_mapping); syntax.name.clone() } } diff --git a/src/bin/bat/app.rs b/src/bin/bat/app.rs index 569e7b47..b5e8f28e 100644 --- a/src/bin/bat/app.rs +++ b/src/bin/bat/app.rs @@ -15,10 +15,11 @@ use console::Term; use bat::{ config::{ - Config, HighlightedLineRanges, Input, LineRange, LineRanges, MappingTarget, OrdinaryFile, - PagingMode, StyleComponent, StyleComponents, SyntaxMapping, WrappingMode, + Config, HighlightedLineRanges, LineRange, LineRanges, MappingTarget, PagingMode, + StyleComponent, StyleComponents, SyntaxMapping, WrappingMode, }, errors::*, + input::Input, HighlightingAssets, }; @@ -83,13 +84,7 @@ 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 inputs.iter().any(|f| { - if let Input::StdIn(None) = f { - true - } else { - false - } - }) { + } else if inputs.iter().any(Input::is_stdin) { // 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. @@ -251,9 +246,9 @@ impl App { let files: Option> = self.matches.values_of_os("FILE").map(|vs| vs.collect()); if files.is_none() { - return Ok(vec![Input::StdIn( - filenames_or_none.nth(0).unwrap().map(|f| f.to_owned()), - )]); + let mut input = Input::stdin(); + input.set_provided_name(filenames_or_none.nth(0).unwrap_or(None)); + return Ok(vec![input]); } let files_or_none: Box> = match files { Some(ref files) => Box::new(files.into_iter().map(|name| Some(*name))), @@ -261,16 +256,16 @@ impl App { }; let mut file_input = Vec::new(); - for (input, name) in files_or_none.zip(filenames_or_none) { - if let Some(input) = input { - if input.to_str().unwrap_or_default() == "-" { - file_input.push(Input::StdIn(name.map(|n| n.to_owned()))); + for (filepath, provided_name) in files_or_none.zip(filenames_or_none) { + if let Some(filepath) = filepath { + if filepath.to_str().unwrap_or_default() == "-" { + let mut input = Input::stdin(); + input.set_provided_name(provided_name); + file_input.push(input); } else { - let mut ofile = OrdinaryFile::from_path(input); - if let Some(path) = name { - ofile.set_provided_path(path); - } - file_input.push(Input::Ordinary(ofile)) + let mut input = Input::ordinary_file(filepath); + input.set_provided_name(provided_name); + file_input.push(input); } } } diff --git a/src/bin/bat/main.rs b/src/bin/bat/main.rs index 924461d8..3d8b3ff7 100644 --- a/src/bin/bat/main.rs +++ b/src/bin/bat/main.rs @@ -26,8 +26,9 @@ use clap::crate_version; use directories::PROJECT_DIRS; use bat::{ - config::{Config, Input, OrdinaryFile, StyleComponent, StyleComponents}, + config::{Config, StyleComponent, StyleComponents}, errors::*, + input::Input, Controller, HighlightingAssets, }; @@ -134,7 +135,7 @@ pub fn list_themes(cfg: &Config) -> Result<()> { )?; config.theme = theme.to_string(); Controller::new(&config, &assets) - .run(vec![Input::ThemePreviewFile]) + .run(vec![Input::theme_preview_file()]) .ok(); writeln!(stdout)?; } @@ -167,9 +168,7 @@ fn run() -> Result { run_cache_subcommand(cache_matches)?; Ok(true) } else { - let inputs = vec![Input::Ordinary(OrdinaryFile::from_path(OsStr::new( - "cache", - )))]; + let inputs = vec![Input::ordinary_file(OsStr::new("cache"))]; let config = app.config(&inputs)?; run_controller(inputs, &config) diff --git a/src/config.rs b/src/config.rs index 960ac63e..d708fad4 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,5 +1,3 @@ -pub use crate::input::Input; -pub use crate::input::OrdinaryFile; pub use crate::line_range::{HighlightedLineRanges, LineRange, LineRanges}; pub use crate::style::{StyleComponent, StyleComponents}; pub use crate::syntax_mapping::{MappingTarget, SyntaxMapping}; diff --git a/src/controller.rs b/src/controller.rs index 8d6b7fe0..bc37330d 100644 --- a/src/controller.rs +++ b/src/controller.rs @@ -5,7 +5,7 @@ use crate::config::Config; #[cfg(feature = "paging")] use crate::config::PagingMode; use crate::errors::*; -use crate::input::{Input, InputDescription, InputReader}; +use crate::input::{Input, InputDescription, InputKind, InputReader, OpenedInput}; use crate::line_range::{LineRanges, RangeCheckResult}; use crate::output::OutputType; use crate::printer::{InteractivePrinter, Printer, SimplePrinter}; @@ -38,9 +38,9 @@ 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 = inputs.iter().any(|file| { - if let Input::Ordinary(ofile) = file { - return Path::new(ofile.provided_path()).exists(); + let call_pager = inputs.iter().any(|ref input| { + if let InputKind::OrdinaryFile(ref path) = input.kind { + return Path::new(path).exists(); } else { return true; } @@ -61,27 +61,24 @@ impl<'b> Controller<'b> { let mut no_errors: bool = true; for input in inputs.into_iter() { - let description = input.description(); - - match input.get_reader(io::stdin().lock()) { + match input.open(io::stdin().lock()) { Err(error) => { handle_error(&error); no_errors = false; } - Ok(mut reader) => { - let result = if self.config.loop_through { - let mut printer = SimplePrinter::new(); - self.print_file(reader, &mut printer, writer, &description) + Ok(mut opened_input) => { + let mut printer: Box = if self.config.loop_through { + Box::new(SimplePrinter::new()) } else { - let mut printer = InteractivePrinter::new( + Box::new(InteractivePrinter::new( &self.config, &self.assets, - &input, - &mut reader, - ); - self.print_file(reader, &mut printer, writer, &description) + &mut opened_input, + )) }; + let result = self.print_file(&mut *printer, writer, &mut opened_input); + if let Err(error) = result { handle_error(&error); no_errors = false; @@ -93,30 +90,29 @@ impl<'b> Controller<'b> { Ok(no_errors) } - fn print_file<'a, P: Printer>( + fn print_file<'a>( &self, - reader: InputReader, - printer: &mut P, + printer: &mut dyn Printer, writer: &mut dyn Write, - input_description: &InputDescription, + input: &mut OpenedInput, ) -> Result<()> { - if !reader.first_line.is_empty() || self.config.style_components.header() { - printer.print_header(writer, input_description)?; + if !input.reader.first_line.is_empty() || self.config.style_components.header() { + printer.print_header(writer, input)?; } - if !reader.first_line.is_empty() { - self.print_file_ranges(printer, writer, reader, &self.config.line_ranges)?; + if !input.reader.first_line.is_empty() { + self.print_file_ranges(printer, writer, &mut input.reader, &self.config.line_ranges)?; } - printer.print_footer(writer)?; + printer.print_footer(writer, input)?; Ok(()) } - fn print_file_ranges( + fn print_file_ranges( &self, - printer: &mut P, + printer: &mut dyn Printer, writer: &mut dyn Write, - mut reader: InputReader, + reader: &mut InputReader, line_ranges: &LineRanges, ) -> Result<()> { let mut line_buffer = Vec::new(); diff --git a/src/input.rs b/src/input.rs index 7b464824..dae61d49 100644 --- a/src/input.rs +++ b/src/input.rs @@ -7,30 +7,6 @@ use content_inspector::{self, ContentType}; use crate::errors::*; const THEME_PREVIEW_FILE: &[u8] = include_bytes!("../assets/theme_preview.rs"); -#[derive(Debug, Clone, PartialEq)] -pub struct OrdinaryFile { - path: OsString, - user_provided_path: Option, -} - -impl OrdinaryFile { - pub fn from_path(path: &OsStr) -> OrdinaryFile { - OrdinaryFile { - path: path.to_os_string(), - user_provided_path: None, - } - } - - pub fn set_provided_path(&mut self, user_provided_path: &OsStr) { - self.user_provided_path = Some(user_provided_path.to_os_string()); - } - - pub(crate) fn provided_path<'a>(&'a self) -> &'a OsStr { - self.user_provided_path - .as_ref() - .unwrap_or_else(|| &self.path) - } -} #[derive(Debug, Clone)] pub struct InputDescription { @@ -39,69 +15,134 @@ pub struct InputDescription { pub name: String, } -pub enum Input { - StdIn(Option), - Ordinary(OrdinaryFile), - FromReader(Box, Option), +pub enum InputKind { + OrdinaryFile(OsString), + StdIn, ThemePreviewFile, + CustomReader(Box), +} + +#[derive(Clone, Default)] +pub struct InputMetadata { + pub user_provided_name: Option, +} + +pub struct Input { + pub kind: InputKind, + pub metadata: InputMetadata, +} + +pub enum OpenedInputKind { + OrdinaryFile(OsString), + StdIn, + ThemePreviewFile, + CustomReader, +} + +pub struct OpenedInput<'a> { + pub kind: OpenedInputKind, + pub metadata: InputMetadata, + pub reader: InputReader<'a>, } impl Input { - pub(crate) fn get_reader<'a, R: BufRead + 'a>(&self, stdin: R) -> Result> { - match self { - Input::StdIn(_) => Ok(InputReader::new(stdin)), - Input::Ordinary(ofile) => { - let file = File::open(&ofile.path) - .map_err(|e| format!("'{}': {}", ofile.path.to_string_lossy(), e))?; - - if file.metadata()?.is_dir() { - return Err( - format!("'{}' is a directory.", ofile.path.to_string_lossy()).into(), - ); - } - - Ok(InputReader::new(BufReader::new(file))) - } - Input::ThemePreviewFile => Ok(InputReader::new(THEME_PREVIEW_FILE)), - Input::FromReader(_, _) => unimplemented!(), //Ok(InputReader::new(BufReader::new(reader))), + pub fn ordinary_file(path: &OsStr) -> Self { + Input { + kind: InputKind::OrdinaryFile(path.to_os_string()), + metadata: InputMetadata::default(), } } - pub(crate) fn description(&self) -> InputDescription { - match self { - Input::Ordinary(ofile) => InputDescription { - full: format!("file '{}'", &ofile.provided_path().to_string_lossy()), - prefix: "File: ".to_owned(), - name: ofile.provided_path().to_string_lossy().into_owned(), - }, - Input::StdIn(Some(name)) => InputDescription { - full: format!( - "STDIN (with name '{}')", - name.to_string_lossy().into_owned() - ), - prefix: "File: ".to_owned(), - name: name.to_string_lossy().into_owned(), - }, - Input::StdIn(None) => InputDescription { - full: "STDIN".to_owned(), - prefix: "".to_owned(), - name: "STDIN".to_owned(), - }, - Input::ThemePreviewFile => InputDescription { - full: "".to_owned(), - prefix: "".to_owned(), - name: "".to_owned(), - }, - Input::FromReader(_, Some(name)) => InputDescription { + pub fn stdin() -> Self { + Input { + kind: InputKind::StdIn, + metadata: InputMetadata::default(), + } + } + + pub fn theme_preview_file() -> Self { + Input { + kind: InputKind::ThemePreviewFile, + metadata: InputMetadata::default(), + } + } + + pub fn is_stdin(&self) -> bool { + if let InputKind::StdIn = self.kind { + true + } else { + false + } + } + + pub fn set_provided_name(&mut self, provided_name: Option<&OsStr>) { + self.metadata.user_provided_name = provided_name.map(|n| n.to_owned()); + } + + pub fn open<'a, R: BufRead + 'a>(self, stdin: R) -> Result> { + match self.kind { + InputKind::StdIn => Ok(OpenedInput { + kind: OpenedInputKind::StdIn, + metadata: self.metadata, + reader: InputReader::new(stdin), + }), + InputKind::OrdinaryFile(path) => Ok(OpenedInput { + kind: OpenedInputKind::OrdinaryFile(path.clone()), + metadata: self.metadata, + reader: { + let file = File::open(&path) + .map_err(|e| format!("'{}': {}", path.to_string_lossy(), e))?; + if file.metadata()?.is_dir() { + return Err(format!("'{}' is a directory.", path.to_string_lossy()).into()); + } + InputReader::new(BufReader::new(file)) + }, + }), + InputKind::ThemePreviewFile => Ok(OpenedInput { + kind: OpenedInputKind::ThemePreviewFile, + metadata: self.metadata, + reader: InputReader::new(THEME_PREVIEW_FILE), + }), + InputKind::CustomReader(reader) => Ok(OpenedInput { + kind: OpenedInputKind::CustomReader, + metadata: self.metadata, + reader: InputReader::new(BufReader::new(reader)), + }), + } + } +} + +impl<'a> OpenedInput<'a> { + pub fn description(&self) -> InputDescription { + if let Some(ref name) = self.metadata.user_provided_name { + InputDescription { full: format!("file '{}'", name.to_string_lossy()), prefix: "File: ".to_owned(), name: name.to_string_lossy().into_owned(), - }, - Input::FromReader(_, None) => InputDescription { - full: "reader".to_owned(), - prefix: "".to_owned(), - name: "READER".into(), - }, + } + } else { + match self.kind { + OpenedInputKind::OrdinaryFile(ref path) => InputDescription { + full: format!("file '{}'", path.to_string_lossy()), + prefix: "File: ".to_owned(), + name: path.to_string_lossy().into_owned(), + }, + OpenedInputKind::StdIn => InputDescription { + full: "STDIN".to_owned(), + prefix: "".to_owned(), + name: "STDIN".to_owned(), + }, + OpenedInputKind::ThemePreviewFile => InputDescription { + full: "".to_owned(), + prefix: "".to_owned(), + name: "".to_owned(), + }, + OpenedInputKind::CustomReader => InputDescription { + full: "reader".to_owned(), + prefix: "".to_owned(), + name: "READER".into(), + }, + } } } } diff --git a/src/lib.rs b/src/lib.rs index 1352cb2b..cdd5a416 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,7 +8,7 @@ pub(crate) mod controller; mod decorations; mod diff; pub mod errors; -pub(crate) mod input; +pub mod input; mod less; pub(crate) mod line_range; mod output; diff --git a/src/pretty_printer.rs b/src/pretty_printer.rs index 3d76c920..da46ce9b 100644 --- a/src/pretty_printer.rs +++ b/src/pretty_printer.rs @@ -3,10 +3,10 @@ use std::io::Read; use crate::{ config::{ - Config, HighlightedLineRanges, Input, LineRanges, OrdinaryFile, StyleComponents, - SyntaxMapping, WrappingMode, + Config, HighlightedLineRanges, LineRanges, StyleComponents, SyntaxMapping, WrappingMode, }, errors::Result, + input::{Input, InputKind, OpenedInput}, Controller, HighlightingAssets, }; @@ -35,8 +35,8 @@ impl<'a> PrettyPrinter<'a> { /// Add a file which should be pretty-printed pub fn input_file(&mut self, path: &OsStr) -> &mut Self { - self.inputs - .push(Input::Ordinary(OrdinaryFile::from_path(path))); + // self.inputs + // .push(Input::Ordinary(OrdinaryFile::from_path(path))); self } @@ -47,15 +47,15 @@ impl<'a> PrettyPrinter<'a> { P: AsRef, { for path in paths { - self.inputs - .push(Input::Ordinary(OrdinaryFile::from_path(path.as_ref()))); + // self.inputs + // .push(Input::Ordinary(OrdinaryFile::from_path(path.as_ref()))); } self } /// Add STDIN as an input pub fn input_stdin(&mut self) -> &mut Self { - self.inputs.push(Input::StdIn(None)); + // self.inputs.push(Input::StdIn(None)); self } diff --git a/src/printer.rs b/src/printer.rs index 0fc914f2..fc409433 100644 --- a/src/printer.rs +++ b/src/printer.rs @@ -27,15 +27,15 @@ use crate::decorations::{Decoration, GridBorderDecoration, LineNumberDecoration} #[cfg(feature = "git")] use crate::diff::{get_git_diff, LineChanges}; use crate::errors::*; -use crate::input::{Input, InputDescription, InputReader}; +use crate::input::{Input, InputDescription, InputKind, InputReader, OpenedInput, OpenedInputKind}; use crate::line_range::RangeCheckResult; use crate::preprocessor::{expand_tabs, replace_nonprintable}; use crate::terminal::{as_terminal_escaped, to_ansi_color}; use crate::wrap::WrappingMode; pub trait Printer { - fn print_header(&mut self, handle: &mut dyn Write, input: &InputDescription) -> Result<()>; - fn print_footer(&mut self, handle: &mut dyn Write) -> Result<()>; + fn print_header(&mut self, handle: &mut dyn Write, input: &OpenedInput) -> Result<()>; + fn print_footer(&mut self, handle: &mut dyn Write, input: &OpenedInput) -> Result<()>; fn print_snip(&mut self, handle: &mut dyn Write) -> Result<()>; @@ -57,11 +57,11 @@ impl SimplePrinter { } impl Printer for SimplePrinter { - fn print_header(&mut self, _handle: &mut dyn Write, input: &InputDescription) -> Result<()> { + fn print_header(&mut self, _handle: &mut dyn Write, _input: &OpenedInput) -> Result<()> { Ok(()) } - fn print_footer(&mut self, _handle: &mut dyn Write) -> Result<()> { + fn print_footer(&mut self, _handle: &mut dyn Write, _input: &OpenedInput) -> Result<()> { Ok(()) } @@ -101,8 +101,7 @@ impl<'a> InteractivePrinter<'a> { pub fn new( config: &'a Config, assets: &'a HighlightingAssets, - input: &Input, - reader: &mut InputReader, + input: &mut OpenedInput, ) -> Self { let theme = assets.get_theme(&config.theme); @@ -150,7 +149,8 @@ impl<'a> InteractivePrinter<'a> { #[cfg(feature = "git")] let mut line_changes = None; - let highlighter = if reader + let highlighter = if input + .reader .content_type .map_or(false, |c| c.is_binary() && !config.show_nonprintable) { @@ -160,14 +160,14 @@ impl<'a> InteractivePrinter<'a> { #[cfg(feature = "git")] { if config.style_components.changes() { - if let Input::Ordinary(ofile) = input { - line_changes = get_git_diff(ofile.provided_path()); + if let OpenedInputKind::OrdinaryFile(ref path) = input.kind { + line_changes = get_git_diff(path); } } } // Determine the type of syntax for highlighting - let syntax = assets.get_syntax(config.language, input, reader, &config.syntax_mapping); + let syntax = assets.get_syntax(config.language, input, &config.syntax_mapping); Some(HighlightLines::new(syntax, theme)) }; @@ -176,7 +176,7 @@ impl<'a> InteractivePrinter<'a> { colors, config, decorations, - content_type: reader.content_type, + content_type: input.reader.content_type, ansi_prefix_sgr: String::new(), #[cfg(feature = "git")] line_changes, @@ -230,11 +230,7 @@ impl<'a> InteractivePrinter<'a> { } impl<'a> Printer for InteractivePrinter<'a> { - fn print_header( - &mut self, - handle: &mut dyn Write, - description: &InputDescription, - ) -> Result<()> { + fn print_header(&mut self, handle: &mut dyn Write, input: &OpenedInput) -> Result<()> { if !self.config.style_components.header() { if Some(ContentType::BINARY) == self.content_type && !self.config.show_nonprintable { writeln!( @@ -243,7 +239,7 @@ impl<'a> Printer for InteractivePrinter<'a> { (but will be present if the output of 'bat' is piped). You can use 'bat -A' \ to show the binary file contents.", Yellow.paint("[bat warning]"), - description.full, + input.description().full, )?; } else { if self.config.style_components.grid() { @@ -276,6 +272,8 @@ impl<'a> Printer for InteractivePrinter<'a> { _ => "", }; + let description = input.description(); + writeln!( handle, "{}{}{}", @@ -295,7 +293,7 @@ impl<'a> Printer for InteractivePrinter<'a> { Ok(()) } - fn print_footer(&mut self, handle: &mut dyn Write) -> Result<()> { + fn print_footer(&mut self, handle: &mut dyn Write, _input: &OpenedInput) -> Result<()> { if self.config.style_components.grid() && (self.content_type.map_or(false, |c| c.is_text()) || self.config.show_nonprintable) {