summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsharkdp <davidpeter@web.de>2020-04-21 22:24:47 +0200
committerDavid Peter <sharkdp@users.noreply.github.com>2020-04-22 23:55:28 +0200
commitf3b90ddb383cfcbd575f24785a5a9400870d162e (patch)
tree9c81e6f1d1fa50b0e9df37d9c2a9a3c6a7feb150
parent3bacfc5184184c4a845d56f9e7226e87eae6d172 (diff)
Add InputDescription
-rw-r--r--src/assets.rs15
-rw-r--r--src/controller.rs12
-rw-r--r--src/input.rs134
-rw-r--r--src/pretty_printer.rs13
-rw-r--r--src/printer.rs54
5 files changed, 130 insertions, 98 deletions
diff --git a/src/assets.rs b/src/assets.rs
index 55bf3ef0..f6b10b3a 100644
--- a/src/assets.rs
+++ b/src/assets.rs
@@ -188,11 +188,11 @@ impl HighlightingAssets {
pub(crate) fn get_syntax(
&self,
language: Option<&str>,
- file: &Input,
+ input: &Input,
reader: &mut InputReader,
mapping: &SyntaxMapping,
) -> &SyntaxReference {
- let syntax = match (language, file) {
+ 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());
@@ -282,12 +282,11 @@ mod tests {
}
let input = Input::Ordinary(OrdinaryFile::from_path(file_path.as_os_str()));
- let syntax = self.assets.get_syntax(
- None,
- &input,
- &mut input.get_reader(io::stdin().lock()).unwrap(),
- &self.syntax_mapping,
- );
+ let stdin = io::stdin();
+ let mut reader = input.get_reader(stdin.lock()).unwrap();
+ let syntax = self
+ .assets
+ .get_syntax(None, &input, &mut reader, &self.syntax_mapping);
syntax.name.clone()
}
diff --git a/src/controller.rs b/src/controller.rs
index f9cf78ac..8d6b7fe0 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, InputReader};
+use crate::input::{Input, InputDescription, InputReader};
use crate::line_range::{LineRanges, RangeCheckResult};
use crate::output::OutputType;
use crate::printer::{InteractivePrinter, Printer, SimplePrinter};
@@ -61,6 +61,8 @@ 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()) {
Err(error) => {
handle_error(&error);
@@ -69,7 +71,7 @@ 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)
+ self.print_file(reader, &mut printer, writer, &description)
} else {
let mut printer = InteractivePrinter::new(
&self.config,
@@ -77,7 +79,7 @@ impl<'b> Controller<'b> {
&input,
&mut reader,
);
- self.print_file(reader, &mut printer, writer, &input)
+ self.print_file(reader, &mut printer, writer, &description)
};
if let Err(error) = result {
@@ -96,10 +98,10 @@ impl<'b> Controller<'b> {
reader: InputReader,
printer: &mut P,
writer: &mut dyn Write,
- input: &Input,
+ input_description: &InputDescription,
) -> Result<()> {
if !reader.first_line.is_empty() || self.config.style_components.header() {
- printer.print_header(writer, input)?;
+ printer.print_header(writer, input_description)?;
}
if !reader.first_line.is_empty() {
diff --git a/src/input.rs b/src/input.rs
index 7b2c371f..7b464824 100644
--- a/src/input.rs
+++ b/src/input.rs
@@ -7,51 +7,6 @@ use content_inspector::{self, ContentType};
use crate::errors::*;
const THEME_PREVIEW_FILE: &[u8] = include_bytes!("../assets/theme_preview.rs");
-
-pub struct InputReader<'a> {
- inner: Box<dyn BufRead + 'a>,
- pub(crate) first_line: Vec<u8>,
- pub(crate) content_type: Option<ContentType>,
-}
-
-impl<'a> InputReader<'a> {
- fn new<R: BufRead + 'a>(mut reader: R) -> InputReader<'a> {
- let mut first_line = vec![];
- reader.read_until(b'\n', &mut first_line).ok();
-
- let content_type = if first_line.is_empty() {
- None
- } else {
- Some(content_inspector::inspect(&first_line[..]))
- };
-
- if content_type == Some(ContentType::UTF_16LE) {
- reader.read_until(0x00, &mut first_line).ok();
- }
-
- InputReader {
- inner: Box::new(reader),
- first_line,
- content_type,
- }
- }
-
- pub(crate) fn read_line(&mut self, buf: &mut Vec<u8>) -> io::Result<bool> {
- if self.first_line.is_empty() {
- let res = self.inner.read_until(b'\n', buf).map(|size| size > 0)?;
-
- if self.content_type == Some(ContentType::UTF_16LE) {
- self.inner.read_until(0x00, buf).ok();
- }
-
- Ok(res)
- } else {
- buf.append(&mut self.first_line);
- Ok(true)
- }
- }
-}
-
#[derive(Debug, Clone, PartialEq)]
pub struct OrdinaryFile {
path: OsString,
@@ -77,6 +32,13 @@ impl OrdinaryFile {
}
}
+#[derive(Debug, Clone)]
+pub struct InputDescription {
+ pub full: String,
+ pub prefix: String,
+ pub name: String,
+}
+
pub enum Input {
StdIn(Option<OsString>),
Ordinary(OrdinaryFile),
@@ -104,6 +66,88 @@ impl Input {
Input::FromReader(_, _) => unimplemented!(), //Ok(InputReader::new(BufReader::new(reader))),
}
}
+
+ 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 {
+ 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(),
+ },
+ }
+ }
+}
+
+pub struct InputReader<'a> {
+ inner: Box<dyn BufRead + 'a>,
+ pub(crate) first_line: Vec<u8>,
+ pub(crate) content_type: Option<ContentType>,
+}
+
+impl<'a> InputReader<'a> {
+ fn new<R: BufRead + 'a>(mut reader: R) -> InputReader<'a> {
+ let mut first_line = vec![];
+ reader.read_until(b'\n', &mut first_line).ok();
+
+ let content_type = if first_line.is_empty() {
+ None
+ } else {
+ Some(content_inspector::inspect(&first_line[..]))
+ };
+
+ if content_type == Some(ContentType::UTF_16LE) {
+ reader.read_until(0x00, &mut first_line).ok();
+ }
+
+ InputReader {
+ inner: Box::new(reader),
+ first_line,
+ content_type,
+ }
+ }
+
+ pub(crate) fn read_line(&mut self, buf: &mut Vec<u8>) -> io::Result<bool> {
+ if self.first_line.is_empty() {
+ let res = self.inner.read_until(b'\n', buf).map(|size| size > 0)?;
+
+ if self.content_type == Some(ContentType::UTF_16LE) {
+ self.inner.read_until(0x00, buf).ok();
+ }
+
+ Ok(res)
+ } else {
+ buf.append(&mut self.first_line);
+ Ok(true)
+ }
+ }
}
#[test]
diff --git a/src/pretty_printer.rs b/src/pretty_printer.rs
index a03b0e3b..5b58526f 100644
--- a/src/pretty_printer.rs
+++ b/src/pretty_printer.rs
@@ -1,4 +1,5 @@
use std::ffi::OsStr;
+use std::io::Read;
use crate::{
config::{
@@ -52,6 +53,18 @@ impl<'a> PrettyPrinter<'a> {
self
}
+ /// Add STDIN as an input
+ pub fn input_stdin(&mut self) -> &mut Self {
+ self.inputs.push(Input::StdIn(None));
+ self
+ }
+
+ /// Add STDIN as an input
+ pub fn input_reader(&mut self, reader: impl Read) -> &mut Self {
+ //self.inputs.push(Input::FromReader(Box::new(reader), None));
+ self
+ }
+
/// Specify the syntax file which should be used (default: auto-detect)
pub fn language(&mut self, language: &'a str) -> &mut Self {
self.config.language = Some(language);
diff --git a/src/printer.rs b/src/printer.rs
index b61c8063..0fc914f2 100644
--- a/src/printer.rs
+++ b/src/printer.rs
@@ -27,14 +27,14 @@ use crate::decorations::{Decoration, GridBorderDecoration, LineNumberDecoration}
#[cfg(feature = "git")]
use crate::diff::{get_git_diff, LineChanges};
use crate::errors::*;
-use crate::input::{Input, InputReader};
+use crate::input::{Input, InputDescription, InputReader};
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, file: &Input) -> Result<()>;
+ fn print_header(&mut self, handle: &mut dyn Write, input: &InputDescription) -> Result<()>;
fn print_footer(&mut self, handle: &mut dyn Write) -> Result<()>;
fn print_snip(&mut self, handle: &mut dyn Write) -> Result<()>;
@@ -57,7 +57,7 @@ impl SimplePrinter {
}
impl Printer for SimplePrinter {
- fn print_header(&mut self, _handle: &mut dyn Write, _file: &Input) -> Result<()> {
+ fn print_header(&mut self, _handle: &mut dyn Write, input: &InputDescription) -> Result<()> {
Ok(())
}
@@ -101,7 +101,7 @@ impl<'a> InteractivePrinter<'a> {
pub fn new(
config: &'a Config,
assets: &'a HighlightingAssets,
- file: &Input,
+ input: &Input,
reader: &mut InputReader,
) -> Self {
let theme = assets.get_theme(&config.theme);
@@ -160,14 +160,14 @@ impl<'a> InteractivePrinter<'a> {
#[cfg(feature = "git")]
{
if config.style_components.changes() {
- if let Input::Ordinary(ofile) = file {
+ if let Input::Ordinary(ofile) = input {
line_changes = get_git_diff(ofile.provided_path());
}
}
}
// Determine the type of syntax for highlighting
- let syntax = assets.get_syntax(config.language, file, reader, &config.syntax_mapping);
+ let syntax = assets.get_syntax(config.language, input, reader, &config.syntax_mapping);
Some(HighlightLines::new(syntax, theme))
};
@@ -230,32 +230,20 @@ impl<'a> InteractivePrinter<'a> {
}
impl<'a> Printer for InteractivePrinter<'a> {
- fn print_header(&mut self, handle: &mut dyn Write, file: &Input) -> Result<()> {
+ fn print_header(
+ &mut self,
+ handle: &mut dyn Write,
+ description: &InputDescription,
+ ) -> Result<()> {
if !self.config.style_components.header() {
if Some(ContentType::BINARY) == self.content_type && !self.config.show_nonprintable {
- let input = match file {
- Input::Ordinary(ofile) => {
- format!("file '{}'", &ofile.provided_path().to_string_lossy())
- }
- Input::StdIn(Some(name)) => format!(
- "STDIN (with name '{}')",
- name.to_string_lossy().into_owned()
- ),
- Input::StdIn(None) => "STDIN".to_owned(),
- Input::ThemePreviewFile => "".to_owned(),
- Input::FromReader(_, Some(name)) => {
- format!("file '{}'", name.to_string_lossy())
- }
- Input::FromReader(_, None) => "READER".to_owned(),
- };
-
writeln!(
handle,
"{}: Binary content from {} will not be printed to the terminal \
(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]"),
- input
+ description.full,
)?;
} else {
if self.config.style_components.grid() {
@@ -280,20 +268,6 @@ impl<'a> Printer for InteractivePrinter<'a> {
write!(handle, "{}", " ".repeat(self.panel_width))?;
}
- let (prefix, name) = match file {
- Input::Ordinary(ofile) => (
- "File: ",
- Cow::from(ofile.provided_path().to_string_lossy().to_owned()),
- ),
- Input::StdIn(Some(name)) => ("File: ", Cow::from(name.to_string_lossy().to_owned())),
- Input::StdIn(None) => ("File: ", Cow::from("STDIN".to_owned())),
- Input::ThemePreviewFile => ("", Cow::from("")),
- Input::FromReader(_, Some(name)) => {
- ("File: ", Cow::from(name.to_string_lossy().to_owned()))
- }
- Input::FromReader(_, None) => ("File: ", Cow::from("READER".to_owned())),
- };
-
let mode = match self.content_type {
Some(ContentType::BINARY) => " <BINARY>",
Some(ContentType::UTF_16LE) => " <UTF-16LE>",
@@ -305,8 +279,8 @@ impl<'a> Printer for InteractivePrinter<'a> {
writeln!(
handle,
"{}{}{}",
- prefix,
- self.colors.filename.paint(name),
+ description.prefix,
+ self.colors.filename.paint(&description.name),
mode
)?;