on master help sign in
Add InputDescription
commitf3b90ddb383cfcbd575f24785a5a9400870d162e authorsharkdp <davidpeter@web.de> dateTue 21 Apr 2020, 22:24 (7 years ago) parent3bacfc5
5 files changed+130−98
src/assets.rs+7−8 src/controller.rs+7−5 src/input.rs+89−45 src/pretty_printer.rs+13 src/printer.rs+14−40
src/assets.rs+7−8
@@ -188,11 +188,11 @@ impl HighlightingAssets {
188188 pub(crate) fn get_syntax(
189189 &self,
190190 language: Option<&str>,
191− file: &Input,
191+ input: &Input,
192192 reader: &mut InputReader,
193193 mapping: &SyntaxMapping,
194194 ) -> &SyntaxReference {
195− let syntax = match (language, file) {
195+ let syntax = match (language, input) {
196196 (Some(language), _) => self.syntax_set.find_syntax_by_token(language),
197197 (None, Input::Ordinary(ofile)) => {
198198 let path = Path::new(ofile.provided_path());
@@ -282,12 +282,11 @@ mod tests {
282282 }
283283
284284 let input = Input::Ordinary(OrdinaryFile::from_path(file_path.as_os_str()));
285− let syntax = self.assets.get_syntax(
286− None,
287− &input,
288− &mut input.get_reader(io::stdin().lock()).unwrap(),
289− &self.syntax_mapping,
290− );
285+ let stdin = io::stdin();
286+ let mut reader = input.get_reader(stdin.lock()).unwrap();
287+ let syntax = self
288+ .assets
289+ .get_syntax(None, &input, &mut reader, &self.syntax_mapping);
291290
292291 syntax.name.clone()
293292 }
src/controller.rs+7−5
@@ -5,7 +5,7 @@ use crate::config::Config;
55#[cfg(feature = "paging")]
66use crate::config::PagingMode;
77use crate::errors::*;
8−use crate::input::{Input, InputReader};
8+use crate::input::{Input, InputDescription, InputReader};
99use crate::line_range::{LineRanges, RangeCheckResult};
1010use crate::output::OutputType;
1111use crate::printer::{InteractivePrinter, Printer, SimplePrinter};
@@ -61,6 +61,8 @@ impl<'b> Controller<'b> {
6161 let mut no_errors: bool = true;
6262
6363 for input in inputs.into_iter() {
64+ let description = input.description();
65+
6466 match input.get_reader(io::stdin().lock()) {
6567 Err(error) => {
6668 handle_error(&error);
@@ -69,7 +71,7 @@ impl<'b> Controller<'b> {
6971 Ok(mut reader) => {
7072 let result = if self.config.loop_through {
7173 let mut printer = SimplePrinter::new();
72− self.print_file(reader, &mut printer, writer, &input)
74+ self.print_file(reader, &mut printer, writer, &description)
7375 } else {
7476 let mut printer = InteractivePrinter::new(
7577 &self.config,
@@ -77,7 +79,7 @@ impl<'b> Controller<'b> {
7779 &input,
7880 &mut reader,
7981 );
80− self.print_file(reader, &mut printer, writer, &input)
82+ self.print_file(reader, &mut printer, writer, &description)
8183 };
8284
8385 if let Err(error) = result {
@@ -96,10 +98,10 @@ impl<'b> Controller<'b> {
9698 reader: InputReader,
9799 printer: &mut P,
98100 writer: &mut dyn Write,
99− input: &Input,
101+ input_description: &InputDescription,
100102 ) -> Result<()> {
101103 if !reader.first_line.is_empty() || self.config.style_components.header() {
102− printer.print_header(writer, input)?;
104+ printer.print_header(writer, input_description)?;
103105 }
104106
105107 if !reader.first_line.is_empty() {
src/input.rs+89−45
@@ -7,51 +7,6 @@ use content_inspector::{self, ContentType};
77use crate::errors::*;
88
99const THEME_PREVIEW_FILE: &[u8] = include_bytes!("../assets/theme_preview.rs");
10−
11−pub struct InputReader<'a> {
12− inner: Box<dyn BufRead + 'a>,
13− pub(crate) first_line: Vec<u8>,
14− pub(crate) content_type: Option<ContentType>,
15−}
16−
17−impl<'a> InputReader<'a> {
18− fn new<R: BufRead + 'a>(mut reader: R) -> InputReader<'a> {
19− let mut first_line = vec![];
20− reader.read_until(b'\n', &mut first_line).ok();
21−
22− let content_type = if first_line.is_empty() {
23− None
24− } else {
25− Some(content_inspector::inspect(&first_line[..]))
26− };
27−
28− if content_type == Some(ContentType::UTF_16LE) {
29− reader.read_until(0x00, &mut first_line).ok();
30− }
31−
32− InputReader {
33− inner: Box::new(reader),
34− first_line,
35− content_type,
36− }
37− }
38−
39− pub(crate) fn read_line(&mut self, buf: &mut Vec<u8>) -> io::Result<bool> {
40− if self.first_line.is_empty() {
41− let res = self.inner.read_until(b'\n', buf).map(|size| size > 0)?;
42−
43− if self.content_type == Some(ContentType::UTF_16LE) {
44− self.inner.read_until(0x00, buf).ok();
45− }
46−
47− Ok(res)
48− } else {
49− buf.append(&mut self.first_line);
50− Ok(true)
51− }
52− }
53−}
54−
5510#[derive(Debug, Clone, PartialEq)]
5611pub struct OrdinaryFile {
5712 path: OsString,
@@ -77,6 +32,13 @@ impl OrdinaryFile {
7732 }
7833}
7934
35+#[derive(Debug, Clone)]
36+pub struct InputDescription {
37+ pub full: String,
38+ pub prefix: String,
39+ pub name: String,
40+}
41+
8042pub enum Input {
8143 StdIn(Option<OsString>),
8244 Ordinary(OrdinaryFile),
@@ -104,6 +66,88 @@ impl Input {
10466 Input::FromReader(_, _) => unimplemented!(), //Ok(InputReader::new(BufReader::new(reader))),
10567 }
10668 }
69+
70+ pub(crate) fn description(&self) -> InputDescription {
71+ match self {
72+ Input::Ordinary(ofile) => InputDescription {
73+ full: format!("file '{}'", &ofile.provided_path().to_string_lossy()),
74+ prefix: "File: ".to_owned(),
75+ name: ofile.provided_path().to_string_lossy().into_owned(),
76+ },
77+ Input::StdIn(Some(name)) => InputDescription {
78+ full: format!(
79+ "STDIN (with name '{}')",
80+ name.to_string_lossy().into_owned()
81+ ),
82+ prefix: "File: ".to_owned(),
83+ name: name.to_string_lossy().into_owned(),
84+ },
85+ Input::StdIn(None) => InputDescription {
86+ full: "STDIN".to_owned(),
87+ prefix: "".to_owned(),
88+ name: "STDIN".to_owned(),
89+ },
90+ Input::ThemePreviewFile => InputDescription {
91+ full: "".to_owned(),
92+ prefix: "".to_owned(),
93+ name: "".to_owned(),
94+ },
95+ Input::FromReader(_, Some(name)) => InputDescription {
96+ full: format!("file '{}'", name.to_string_lossy()),
97+ prefix: "File: ".to_owned(),
98+ name: name.to_string_lossy().into_owned(),
99+ },
100+ Input::FromReader(_, None) => InputDescription {
101+ full: "reader".to_owned(),
102+ prefix: "".to_owned(),
103+ name: "READER".into(),
104+ },
105+ }
106+ }
107+}
108+
109+pub struct InputReader<'a> {
110+ inner: Box<dyn BufRead + 'a>,
111+ pub(crate) first_line: Vec<u8>,
112+ pub(crate) content_type: Option<ContentType>,
113+}
114+
115+impl<'a> InputReader<'a> {
116+ fn new<R: BufRead + 'a>(mut reader: R) -> InputReader<'a> {
117+ let mut first_line = vec![];
118+ reader.read_until(b'\n', &mut first_line).ok();
119+
120+ let content_type = if first_line.is_empty() {
121+ None
122+ } else {
123+ Some(content_inspector::inspect(&first_line[..]))
124+ };
125+
126+ if content_type == Some(ContentType::UTF_16LE) {
127+ reader.read_until(0x00, &mut first_line).ok();
128+ }
129+
130+ InputReader {
131+ inner: Box::new(reader),
132+ first_line,
133+ content_type,
134+ }
135+ }
136+
137+ pub(crate) fn read_line(&mut self, buf: &mut Vec<u8>) -> io::Result<bool> {
138+ if self.first_line.is_empty() {
139+ let res = self.inner.read_until(b'\n', buf).map(|size| size > 0)?;
140+
141+ if self.content_type == Some(ContentType::UTF_16LE) {
142+ self.inner.read_until(0x00, buf).ok();
143+ }
144+
145+ Ok(res)
146+ } else {
147+ buf.append(&mut self.first_line);
148+ Ok(true)
149+ }
150+ }
107151}
108152
109153#[test]
src/pretty_printer.rs+13
@@ -1,4 +1,5 @@
11use std::ffi::OsStr;
2+use std::io::Read;
23
34use crate::{
45 config::{
@@ -52,6 +53,18 @@ impl<'a> PrettyPrinter<'a> {
5253 self
5354 }
5455
56+ /// Add STDIN as an input
57+ pub fn input_stdin(&mut self) -> &mut Self {
58+ self.inputs.push(Input::StdIn(None));
59+ self
60+ }
61+
62+ /// Add STDIN as an input
63+ pub fn input_reader(&mut self, reader: impl Read) -> &mut Self {
64+ //self.inputs.push(Input::FromReader(Box::new(reader), None));
65+ self
66+ }
67+
5568 /// Specify the syntax file which should be used (default: auto-detect)
5669 pub fn language(&mut self, language: &'a str) -> &mut Self {
5770 self.config.language = Some(language);
src/printer.rs+14−40
@@ -27,14 +27,14 @@ use crate::decorations::{Decoration, GridBorderDecoration, LineNumberDecoration}
2727#[cfg(feature = "git")]
2828use crate::diff::{get_git_diff, LineChanges};
2929use crate::errors::*;
30−use crate::input::{Input, InputReader};
30+use crate::input::{Input, InputDescription, InputReader};
3131use crate::line_range::RangeCheckResult;
3232use crate::preprocessor::{expand_tabs, replace_nonprintable};
3333use crate::terminal::{as_terminal_escaped, to_ansi_color};
3434use crate::wrap::WrappingMode;
3535
3636pub trait Printer {
37− fn print_header(&mut self, handle: &mut dyn Write, file: &Input) -> Result<()>;
37+ fn print_header(&mut self, handle: &mut dyn Write, input: &InputDescription) -> Result<()>;
3838 fn print_footer(&mut self, handle: &mut dyn Write) -> Result<()>;
3939
4040 fn print_snip(&mut self, handle: &mut dyn Write) -> Result<()>;
@@ -57,7 +57,7 @@ impl SimplePrinter {
5757}
5858
5959impl Printer for SimplePrinter {
60− fn print_header(&mut self, _handle: &mut dyn Write, _file: &Input) -> Result<()> {
60+ fn print_header(&mut self, _handle: &mut dyn Write, input: &InputDescription) -> Result<()> {
6161 Ok(())
6262 }
6363
@@ -101,7 +101,7 @@ impl<'a> InteractivePrinter<'a> {
101101 pub fn new(
102102 config: &'a Config,
103103 assets: &'a HighlightingAssets,
104− file: &Input,
104+ input: &Input,
105105 reader: &mut InputReader,
106106 ) -> Self {
107107 let theme = assets.get_theme(&config.theme);
@@ -160,14 +160,14 @@ impl<'a> InteractivePrinter<'a> {
160160 #[cfg(feature = "git")]
161161 {
162162 if config.style_components.changes() {
163− if let Input::Ordinary(ofile) = file {
163+ if let Input::Ordinary(ofile) = input {
164164 line_changes = get_git_diff(ofile.provided_path());
165165 }
166166 }
167167 }
168168
169169 // Determine the type of syntax for highlighting
170− let syntax = assets.get_syntax(config.language, file, reader, &config.syntax_mapping);
170+ let syntax = assets.get_syntax(config.language, input, reader, &config.syntax_mapping);
171171 Some(HighlightLines::new(syntax, theme))
172172 };
173173
@@ -230,32 +230,20 @@ impl<'a> InteractivePrinter<'a> {
230230}
231231
232232impl<'a> Printer for InteractivePrinter<'a> {
233− fn print_header(&mut self, handle: &mut dyn Write, file: &Input) -> Result<()> {
233+ fn print_header(
234+ &mut self,
235+ handle: &mut dyn Write,
236+ description: &InputDescription,
237+ ) -> Result<()> {
234238 if !self.config.style_components.header() {
235239 if Some(ContentType::BINARY) == self.content_type && !self.config.show_nonprintable {
236− let input = match file {
237− Input::Ordinary(ofile) => {
238− format!("file '{}'", &ofile.provided_path().to_string_lossy())
239− }
240− Input::StdIn(Some(name)) => format!(
241− "STDIN (with name '{}')",
242− name.to_string_lossy().into_owned()
243− ),
244− Input::StdIn(None) => "STDIN".to_owned(),
245− Input::ThemePreviewFile => "".to_owned(),
246− Input::FromReader(_, Some(name)) => {
247− format!("file '{}'", name.to_string_lossy())
248− }
249− Input::FromReader(_, None) => "READER".to_owned(),
250− };
251−
252240 writeln!(
253241 handle,
254242 "{}: Binary content from {} will not be printed to the terminal \
255243 (but will be present if the output of 'bat' is piped). You can use 'bat -A' \
256244 to show the binary file contents.",
257245 Yellow.paint("[bat warning]"),
258− input
246+ description.full,
259247 )?;
260248 } else {
261249 if self.config.style_components.grid() {
@@ -280,20 +268,6 @@ impl<'a> Printer for InteractivePrinter<'a> {
280268 write!(handle, "{}", " ".repeat(self.panel_width))?;
281269 }
282270
283− let (prefix, name) = match file {
284− Input::Ordinary(ofile) => (
285− "File: ",
286− Cow::from(ofile.provided_path().to_string_lossy().to_owned()),
287− ),
288− Input::StdIn(Some(name)) => ("File: ", Cow::from(name.to_string_lossy().to_owned())),
289− Input::StdIn(None) => ("File: ", Cow::from("STDIN".to_owned())),
290− Input::ThemePreviewFile => ("", Cow::from("")),
291− Input::FromReader(_, Some(name)) => {
292− ("File: ", Cow::from(name.to_string_lossy().to_owned()))
293− }
294− Input::FromReader(_, None) => ("File: ", Cow::from("READER".to_owned())),
295− };
296−
297271 let mode = match self.content_type {
298272 Some(ContentType::BINARY) => " <BINARY>",
299273 Some(ContentType::UTF_16LE) => " <UTF-16LE>",
@@ -305,8 +279,8 @@ impl<'a> Printer for InteractivePrinter<'a> {
305279 writeln!(
306280 handle,
307281 "{}{}{}",
308− prefix,
309− self.colors.filename.paint(name),
282+ description.prefix,
283+ self.colors.filename.paint(&description.name),
310284 mode
311285 )?;
312286