on master help sign in
Implemented --file-name for multiple files + tests
commit59f2e2d58d3dc8ca31b74b9bad5899c4521baf0c authorKyle Criddle <criddle.kyle@gmail.com> dateTue 24 Mar 2020, 18:26 (7 years ago) parentcfa2cb6
5 files changed+80−21
src/bin/bat/app.rs+10−1 src/controller.rs+18−4 src/lib.rs+1−1 src/printer.rs+22−15 tests/integration_tests.rs+29
src/bin/bat/app.rs+10−1
@@ -137,6 +137,12 @@ impl App {
137137 }
138138 });
139139
140+ if self.matches.value_of("file-name").is_some()
141+ && self.matches.values_of("file-name").unwrap().len() != files.len()
142+ {
143+ return Err("When using --file-name, each input file must have a corresponding --file-name specified.".into());
144+ }
145+
140146 Ok(Config {
141147 true_color: is_truecolor_terminal(),
142148 language: self.matches.value_of("language").or_else(|| {
@@ -222,7 +228,10 @@ impl App {
222228 .transpose()?
223229 .unwrap_or_else(|| vec![LineRange { lower: 0, upper: 0 }]),
224230 ),
225− filename: self.matches.value_of("file-name").or_else(|| None),
231+ filenames: self
232+ .matches
233+ .values_of("file-name")
234+ .map(|values| values.collect()),
226235 })
227236 }
228237
src/controller.rs+18−4
@@ -41,7 +41,20 @@ impl<'b> Controller<'b> {
4141
4242 let stdin = io::stdin();
4343
44− for input_file in &self.config.files {
44+ let filenames = if self.config.filenames.is_none() {
45+ vec![None; self.config.files.len()]
46+ } else {
47+ self.config
48+ .filenames
49+ .as_ref()
50+ .unwrap()
51+ .into_iter()
52+ .map(|name| Some(*name))
53+ .collect()
54+ };
55+
56+ for it in self.config.files.iter().zip(filenames) {
57+ let (input_file, file_name) = it;
4558 match input_file.get_reader(&stdin) {
4659 Err(error) => {
4760 handle_error(&error);
@@ -50,7 +63,7 @@ impl<'b> Controller<'b> {
5063 Ok(mut reader) => {
5164 let result = if self.config.loop_through {
5265 let mut printer = SimplePrinter::new();
53− self.print_file(reader, &mut printer, writer, *input_file)
66+ self.print_file(reader, &mut printer, writer, *input_file, file_name)
5467 } else {
5568 let mut printer = InteractivePrinter::new(
5669 &self.config,
@@ -58,7 +71,7 @@ impl<'b> Controller<'b> {
5871 *input_file,
5972 &mut reader,
6073 );
61− self.print_file(reader, &mut printer, writer, *input_file)
74+ self.print_file(reader, &mut printer, writer, *input_file, file_name)
6275 };
6376
6477 if let Err(error) = result {
@@ -78,9 +91,10 @@ impl<'b> Controller<'b> {
7891 printer: &mut P,
7992 writer: &mut dyn Write,
8093 input_file: InputFile<'a>,
94+ file_name: Option<&str>,
8195 ) -> Result<()> {
8296 if !reader.first_line.is_empty() || self.config.output_components.header() {
83− printer.print_header(writer, input_file)?;
97+ printer.print_header(writer, input_file, file_name)?;
8498 }
8599
86100 if !reader.first_line.is_empty() {
src/lib.rs+1−1
@@ -131,5 +131,5 @@ pub struct Config<'a> {
131131 pub highlight_lines: LineRanges,
132132
133133 /// Name of file to display when printing
134− pub filename: Option<&'a str>,
134+ pub filenames: Option<Vec<&'a str>>,
135135}
src/printer.rs+22−15
@@ -34,7 +34,12 @@ use crate::terminal::{as_terminal_escaped, to_ansi_color};
3434use crate::Config;
3535
3636pub trait Printer {
37− fn print_header(&mut self, handle: &mut dyn Write, file: InputFile) -> Result<()>;
37+ fn print_header(
38+ &mut self,
39+ handle: &mut dyn Write,
40+ file: InputFile,
41+ file_name: Option<&str>,
42+ ) -> Result<()>;
3843 fn print_footer(&mut self, handle: &mut dyn Write) -> Result<()>;
3944
4045 fn print_snip(&mut self, handle: &mut dyn Write) -> Result<()>;
@@ -57,7 +62,12 @@ impl SimplePrinter {
5762}
5863
5964impl Printer for SimplePrinter {
60− fn print_header(&mut self, _handle: &mut dyn Write, _file: InputFile) -> Result<()> {
65+ fn print_header(
66+ &mut self,
67+ _handle: &mut dyn Write,
68+ _file: InputFile,
69+ _file_name: Option<&str>,
70+ ) -> Result<()> {
6171 Ok(())
6272 }
6373
@@ -224,15 +234,20 @@ impl<'a> InteractivePrinter<'a> {
224234}
225235
226236impl<'a> Printer for InteractivePrinter<'a> {
227− fn print_header(&mut self, handle: &mut dyn Write, file: InputFile) -> Result<()> {
237+ fn print_header(
238+ &mut self,
239+ handle: &mut dyn Write,
240+ file: InputFile,
241+ file_name: Option<&str>,
242+ ) -> Result<()> {
228243 if !self.config.output_components.header() {
229244 if Some(ContentType::BINARY) == self.content_type && !self.config.show_nonprintable {
230245 let input = match file {
231246 InputFile::Ordinary(filename) => format!(
232247 "file '{}'",
233− self.config.filename.unwrap_or(&filename.to_string_lossy())
248+ file_name.unwrap_or(&filename.to_string_lossy())
234249 ),
235− _ => self.config.filename.unwrap_or("STDIN").to_owned(),
250+ _ => file_name.unwrap_or("STDIN").to_owned(),
236251 };
237252
238253 writeln!(
@@ -269,17 +284,9 @@ impl<'a> Printer for InteractivePrinter<'a> {
269284 let (prefix, name) = match file {
270285 InputFile::Ordinary(filename) => (
271286 "File: ",
272− Cow::from(
273− self.config
274− .filename
275− .unwrap_or(&filename.to_string_lossy())
276− .to_owned(),
277− ),
278− ),
279− _ => (
280− "File: ",
281− Cow::from(self.config.filename.unwrap_or("STDIN").to_owned()),
287+ Cow::from(file_name.unwrap_or(&filename.to_string_lossy()).to_owned()),
282288 ),
289+ _ => ("File: ", Cow::from(file_name.unwrap_or("STDIN").to_owned())),
283290 };
284291
285292 let mode = match self.content_type {
tests/integration_tests.rs+29
@@ -598,3 +598,32 @@ fn filename_stdin_binary() {
598598 .stdout("File: foo <BINARY>\n")
599599 .stderr("");
600600}
601+
602+#[test]
603+fn filename_multiple_ok() {
604+ bat()
605+ .arg("--decorations=always")
606+ .arg("--style=header")
607+ .arg("-r=0:0")
608+ .arg("test.txt")
609+ .arg("--file-name=foo")
610+ .arg("single-line.txt")
611+ .arg("--file-name=bar")
612+ .assert()
613+ .success()
614+ .stdout("File: foo\nFile: bar\n")
615+ .stderr("");
616+}
617+
618+#[test]
619+fn filename_multiple_err() {
620+ bat()
621+ .arg("--decorations=always")
622+ .arg("--style=header")
623+ .arg("-r=0:0")
624+ .arg("test.txt")
625+ .arg("--file-name=foo")
626+ .arg("single-line.txt")
627+ .assert()
628+ .failure();
629+}