on master help sign in
Add new `--style` called `header-filesize` and display it by default (#1988)

Also rename `header` to `header-filename`. Related to #1701

commit312c8ef01f1a80f4a806629a7dacd32508b267a5 authorMahdi Dibaiee <mdibaiee@pm.me> dateMon 7 Feb 2022, 19:48 (5 years ago) parentf3f8194
111 files changed+302−42
CHANGELOG.md+2 Cargo.lock+7 Cargo.toml+1 src/bin/bat/clap_app.rs+15−5 src/input.rs+8−1 src/printer.rs+73−31 src/style.rs+19−3 tests/benchmarks/many-small-files/small-file-0.txt+1 tests/benchmarks/many-small-files/small-file-1.txt+1 tests/benchmarks/many-small-files/small-file-10.txt+1 tests/benchmarks/many-small-files/small-file-100.txt+1 tests/benchmarks/many-small-files/small-file-11.txt+1 tests/benchmarks/many-small-files/small-file-12.txt+1 tests/benchmarks/many-small-files/small-file-13.txt+1 tests/benchmarks/many-small-files/small-file-14.txt+1 tests/benchmarks/many-small-files/small-file-15.txt+1 tests/benchmarks/many-small-files/small-file-16.txt+1 tests/benchmarks/many-small-files/small-file-17.txt+1 tests/benchmarks/many-small-files/small-file-18.txt+1 tests/benchmarks/many-small-files/small-file-19.txt+1 tests/benchmarks/many-small-files/small-file-2.txt+1 tests/benchmarks/many-small-files/small-file-20.txt+1 tests/benchmarks/many-small-files/small-file-21.txt+1 tests/benchmarks/many-small-files/small-file-22.txt+1 tests/benchmarks/many-small-files/small-file-23.txt+1 tests/benchmarks/many-small-files/small-file-24.txt+1 tests/benchmarks/many-small-files/small-file-25.txt+1 tests/benchmarks/many-small-files/small-file-26.txt+1 tests/benchmarks/many-small-files/small-file-27.txt+1 tests/benchmarks/many-small-files/small-file-28.txt+1 tests/benchmarks/many-small-files/small-file-29.txt+1 tests/benchmarks/many-small-files/small-file-3.txt+1 tests/benchmarks/many-small-files/small-file-30.txt+1 tests/benchmarks/many-small-files/small-file-31.txt+1 tests/benchmarks/many-small-files/small-file-32.txt+1 tests/benchmarks/many-small-files/small-file-33.txt+1 tests/benchmarks/many-small-files/small-file-34.txt+1 tests/benchmarks/many-small-files/small-file-35.txt+1 tests/benchmarks/many-small-files/small-file-36.txt+1 tests/benchmarks/many-small-files/small-file-37.txt+1 tests/benchmarks/many-small-files/small-file-38.txt+1 tests/benchmarks/many-small-files/small-file-39.txt+1 tests/benchmarks/many-small-files/small-file-4.txt+1 tests/benchmarks/many-small-files/small-file-40.txt+1 tests/benchmarks/many-small-files/small-file-41.txt+1 tests/benchmarks/many-small-files/small-file-42.txt+1 tests/benchmarks/many-small-files/small-file-43.txt+1 tests/benchmarks/many-small-files/small-file-44.txt+1 tests/benchmarks/many-small-files/small-file-45.txt+1 tests/benchmarks/many-small-files/small-file-46.txt+1 tests/benchmarks/many-small-files/small-file-47.txt+1 tests/benchmarks/many-small-files/small-file-48.txt+1 tests/benchmarks/many-small-files/small-file-49.txt+1 tests/benchmarks/many-small-files/small-file-5.txt+1 tests/benchmarks/many-small-files/small-file-50.txt+1 tests/benchmarks/many-small-files/small-file-51.txt+1 tests/benchmarks/many-small-files/small-file-52.txt+1 tests/benchmarks/many-small-files/small-file-53.txt+1 tests/benchmarks/many-small-files/small-file-54.txt+1 tests/benchmarks/many-small-files/small-file-55.txt+1 tests/benchmarks/many-small-files/small-file-56.txt+1 tests/benchmarks/many-small-files/small-file-57.txt+1 tests/benchmarks/many-small-files/small-file-58.txt+1 tests/benchmarks/many-small-files/small-file-59.txt+1 tests/benchmarks/many-small-files/small-file-6.txt+1 tests/benchmarks/many-small-files/small-file-60.txt+1 tests/benchmarks/many-small-files/small-file-61.txt+1 tests/benchmarks/many-small-files/small-file-62.txt+1 tests/benchmarks/many-small-files/small-file-63.txt+1 tests/benchmarks/many-small-files/small-file-64.txt+1 tests/benchmarks/many-small-files/small-file-65.txt+1 tests/benchmarks/many-small-files/small-file-66.txt+1 tests/benchmarks/many-small-files/small-file-67.txt+1 tests/benchmarks/many-small-files/small-file-68.txt+1 tests/benchmarks/many-small-files/small-file-69.txt+1 tests/benchmarks/many-small-files/small-file-7.txt+1 tests/benchmarks/many-small-files/small-file-70.txt+1 tests/benchmarks/many-small-files/small-file-71.txt+1 tests/benchmarks/many-small-files/small-file-72.txt+1 tests/benchmarks/many-small-files/small-file-73.txt+1 tests/benchmarks/many-small-files/small-file-74.txt+1 tests/benchmarks/many-small-files/small-file-75.txt+1 tests/benchmarks/many-small-files/small-file-76.txt+1 tests/benchmarks/many-small-files/small-file-77.txt+1 tests/benchmarks/many-small-files/small-file-78.txt+1 tests/benchmarks/many-small-files/small-file-79.txt+1 tests/benchmarks/many-small-files/small-file-8.txt+1 tests/benchmarks/many-small-files/small-file-80.txt+1 tests/benchmarks/many-small-files/small-file-81.txt+1 tests/benchmarks/many-small-files/small-file-82.txt+1 tests/benchmarks/many-small-files/small-file-83.txt+1 tests/benchmarks/many-small-files/small-file-84.txt+1 tests/benchmarks/many-small-files/small-file-85.txt+1 tests/benchmarks/many-small-files/small-file-86.txt+1 tests/benchmarks/many-small-files/small-file-87.txt+1 tests/benchmarks/many-small-files/small-file-88.txt+1 tests/benchmarks/many-small-files/small-file-89.txt+1 tests/benchmarks/many-small-files/small-file-9.txt+1 tests/benchmarks/many-small-files/small-file-90.txt+1 tests/benchmarks/many-small-files/small-file-91.txt+1 tests/benchmarks/many-small-files/small-file-92.txt+1 tests/benchmarks/many-small-files/small-file-93.txt+1 tests/benchmarks/many-small-files/small-file-94.txt+1 tests/benchmarks/many-small-files/small-file-95.txt+1 tests/benchmarks/many-small-files/small-file-96.txt+1 tests/benchmarks/many-small-files/small-file-97.txt+1 tests/benchmarks/many-small-files/small-file-98.txt+1 tests/benchmarks/many-small-files/small-file-99.txt+1 tests/benchmarks/run-benchmarks.sh+10 tests/integration_tests.rs+65−2 tests/snapshots/output/full.snapshot.txt+1
CHANGELOG.md+2
@@ -2,6 +2,8 @@
22
33## Features
44
5+- New style component `header-filesize` to show size of the displayed file in the header. See #1988 (@mdibaiee)
6+
57## Bugfixes
68
79## Other
Cargo.lock+7
@@ -82,6 +82,7 @@ dependencies = [
8282 "atty",
8383 "bincode",
8484 "bugreport",
85+ "bytesize",
8586 "clap",
8687 "clircle",
8788 "console",
@@ -169,6 +170,12 @@ version = "1.7.3"
169170source = "registry+https://github.com/rust-lang/crates.io-index"
170171checksum = "439989e6b8c38d1b6570a384ef1e49c8848128f5a97f3914baef02920842712f"
171172
173+[[package]]
174+name = "bytesize"
175+version = "1.1.0"
176+source = "registry+https://github.com/rust-lang/crates.io-index"
177+checksum = "6c58ec36aac5066d5ca17df51b3e70279f5670a72102f5752cb7e7c856adfc70"
178+
172179[[package]]
173180name = "cc"
174181version = "1.0.72"
Cargo.toml+1
@@ -65,6 +65,7 @@ dirs-next = { version = "2.0.0", optional = true }
6565grep-cli = { version = "0.1.6", optional = true }
6666regex = { version = "1.0", optional = true }
6767walkdir = { version = "2.0", optional = true }
68+bytesize = { version = "1.1.0" }
6869
6970[dependencies.git2]
7071version = "0.13"
src/bin/bat/clap_app.rs+15−5
@@ -396,11 +396,19 @@ pub fn build_app(interactive_output: bool) -> ClapApp<'static, 'static> {
396396 .validator(|val| {
397397 let mut invalid_vals = val.split(',').filter(|style| {
398398 !&[
399− "auto", "full", "plain", "header", "grid", "rule", "numbers", "snip",
399+ "auto",
400+ "full",
401+ "plain",
402+ "header",
403+ "header-filename",
404+ "header-filesize",
405+ "grid",
406+ "rule",
407+ "numbers",
408+ "snip",
400409 #[cfg(feature = "git")]
401− "changes",
402− ]
403− .contains(style)
410+ "changes",
411+ ].contains(style)
404412 });
405413
406414 if let Some(invalid) = invalid_vals.next() {
@@ -426,7 +434,9 @@ pub fn build_app(interactive_output: bool) -> ClapApp<'static, 'static> {
426434 * auto: same as 'full', unless the output is piped.\n \
427435 * plain: disables all available components.\n \
428436 * changes: show Git modification markers.\n \
429− * header: show filenames before the content.\n \
437+ * header: alias for 'header-filename'.\n \
438+ * header-filename: show filenames before the content.\n \
439+ * header-filesize: show file sizes before the content.\n \
430440 * grid: vertical/horizontal lines to separate side bar\n \
431441 and the header from the content.\n \
432442 * rule: horizontal lines to delimit files.\n \
src/input.rs+8−1
@@ -1,4 +1,5 @@
11use std::convert::TryFrom;
2+use std::fs;
23use std::fs::File;
34use std::io::{self, BufRead, BufReader, Read};
45use std::path::{Path, PathBuf};
@@ -87,6 +88,7 @@ impl<'a> InputKind<'a> {
8788#[derive(Clone, Default)]
8889pub(crate) struct InputMetadata {
8990 pub(crate) user_provided_name: Option<PathBuf>,
91+ pub(crate) size: Option<u64>,
9092}
9193
9294pub struct Input<'a> {
@@ -130,9 +132,14 @@ impl<'a> Input<'a> {
130132
131133 fn _ordinary_file(path: &Path) -> Self {
132134 let kind = InputKind::OrdinaryFile(path.to_path_buf());
135+ let metadata = InputMetadata {
136+ size: fs::metadata(path).map(|m| m.len()).ok(),
137+ ..InputMetadata::default()
138+ };
139+
133140 Input {
134141 description: kind.description(),
135− metadata: InputMetadata::default(),
142+ metadata,
136143 kind,
137144 }
138145 }
src/printer.rs+73−31
@@ -4,6 +4,8 @@ use std::vec::Vec;
44use ansi_term::Colour::{Fixed, Green, Red, Yellow};
55use ansi_term::Style;
66
7+use bytesize::ByteSize;
8+
79use console::AnsiCodeIterator;
810
911use syntect::easy::HighlightLines;
@@ -29,6 +31,7 @@ use crate::error::*;
2931use crate::input::OpenedInput;
3032use crate::line_range::RangeCheckResult;
3133use crate::preprocessor::{expand_tabs, replace_nonprintable};
34+use crate::style::StyleComponent;
3235use crate::terminal::{as_terminal_escaped, to_ansi_color};
3336use crate::vscreen::AnsiStyle;
3437use crate::wrapping::WrappingMode;
@@ -250,6 +253,21 @@ impl<'a> InteractivePrinter<'a> {
250253 }
251254 }
252255
256+ fn print_header_component_indent(&mut self, handle: &mut dyn Write) -> std::io::Result<()> {
257+ if self.config.style_components.grid() {
258+ write!(
259+ handle,
260+ "{}{}",
261+ " ".repeat(self.panel_width),
262+ self.colors
263+ .grid
264+ .paint(if self.panel_width > 0 { "│ " } else { "" }),
265+ )
266+ } else {
267+ write!(handle, "{}", " ".repeat(self.panel_width))
268+ }
269+ }
270+
253271 fn preprocess(&self, text: &str, cursor: &mut usize) -> String {
254272 if self.config.tab_width > 0 {
255273 return expand_tabs(text, self.config.tab_width, cursor);
@@ -287,25 +305,6 @@ impl<'a> Printer for InteractivePrinter<'a> {
287305 return Ok(());
288306 }
289307
290− if self.config.style_components.grid() {
291− self.print_horizontal_line(handle, '┬')?;
292−
293− write!(
294− handle,
295− "{}{}",
296− " ".repeat(self.panel_width),
297− self.colors
298− .grid
299− .paint(if self.panel_width > 0 { "│ " } else { "" }),
300− )?;
301− } else {
302− // Only pad space between files, if we haven't already drawn a horizontal rule
303− if add_header_padding && !self.config.style_components.rule() {
304− writeln!(handle)?;
305− }
306− write!(handle, "{}", " ".repeat(self.panel_width))?;
307− }
308−
309308 let mode = match self.content_type {
310309 Some(ContentType::BINARY) => " <BINARY>",
311310 Some(ContentType::UTF_16LE) => " <UTF-16LE>",
@@ -315,17 +314,60 @@ impl<'a> Printer for InteractivePrinter<'a> {
315314 };
316315
317316 let description = &input.description;
317+ let metadata = &input.metadata;
318+
319+ // We use this iterator to have a deterministic order for
320+ // header components. HashSet has arbitrary order, but Vec is ordered.
321+ let header_components: Vec<StyleComponent> = [
322+ (
323+ StyleComponent::HeaderFilename,
324+ self.config.style_components.header_filename(),
325+ ),
326+ (
327+ StyleComponent::HeaderFilesize,
328+ self.config.style_components.header_filesize(),
329+ ),
330+ ]
331+ .iter()
332+ .filter(|(_, is_enabled)| *is_enabled)
333+ .map(|(component, _)| *component)
334+ .collect();
335+
336+ // Print the cornering grid before the first header component
337+ if self.config.style_components.grid() {
338+ self.print_horizontal_line(handle, '┬')?;
339+ } else {
340+ // Only pad space between files, if we haven't already drawn a horizontal rule
341+ if add_header_padding && !self.config.style_components.rule() {
342+ writeln!(handle)?;
343+ }
344+ }
318345
319− writeln!(
320− handle,
321− "{}{}{}",
322− description
323− .kind()
324− .map(|kind| format!("{}: ", kind))
325− .unwrap_or_else(|| "".into()),
326− self.colors.filename.paint(description.title()),
327− mode
328− )?;
346+ header_components.iter().try_for_each(|component| {
347+ self.print_header_component_indent(handle)?;
348+
349+ match component {
350+ StyleComponent::HeaderFilename => writeln!(
351+ handle,
352+ "{}{}{}",
353+ description
354+ .kind()
355+ .map(|kind| format!("{}: ", kind))
356+ .unwrap_or_else(|| "".into()),
357+ self.colors.header_value.paint(description.title()),
358+ mode
359+ ),
360+
361+ StyleComponent::HeaderFilesize => {
362+ let bsize = metadata
363+ .size
364+ .map(|s| format!("{}", ByteSize(s)))
365+ .unwrap_or_else(|| "-".into());
366+ writeln!(handle, "Size: {}", self.colors.header_value.paint(bsize))
367+ }
368+ _ => Ok(()),
369+ }
370+ })?;
329371
330372 if self.config.style_components.grid() {
331373 if self.content_type.map_or(false, |c| c.is_text()) || self.config.show_nonprintable {
@@ -617,7 +659,7 @@ const DEFAULT_GUTTER_COLOR: u8 = 238;
617659pub struct Colors {
618660 pub grid: Style,
619661 pub rule: Style,
620− pub filename: Style,
662+ pub header_value: Style,
621663 pub git_added: Style,
622664 pub git_removed: Style,
623665 pub git_modified: Style,
@@ -646,7 +688,7 @@ impl Colors {
646688 Colors {
647689 grid: gutter_style,
648690 rule: gutter_style,
649− filename: Style::new().bold(),
691+ header_value: Style::new().bold(),
650692 git_added: Green.normal(),
651693 git_removed: Red.normal(),
652694 git_modified: Yellow.normal(),
src/style.rs+19−3
@@ -3,6 +3,7 @@ use std::str::FromStr;
33
44use crate::error::*;
55
6+#[non_exhaustive]
67#[derive(Debug, Eq, PartialEq, Copy, Clone, Hash)]
78pub enum StyleComponent {
89 Auto,
@@ -11,6 +12,8 @@ pub enum StyleComponent {
1112 Grid,
1213 Rule,
1314 Header,
15+ HeaderFilename,
16+ HeaderFilesize,
1417 LineNumbers,
1518 Snip,
1619 Full,
@@ -31,14 +34,17 @@ impl StyleComponent {
3134 StyleComponent::Changes => &[StyleComponent::Changes],
3235 StyleComponent::Grid => &[StyleComponent::Grid],
3336 StyleComponent::Rule => &[StyleComponent::Rule],
34− StyleComponent::Header => &[StyleComponent::Header],
37+ StyleComponent::Header => &[StyleComponent::HeaderFilename],
38+ StyleComponent::HeaderFilename => &[StyleComponent::HeaderFilename],
39+ StyleComponent::HeaderFilesize => &[StyleComponent::HeaderFilesize],
3540 StyleComponent::LineNumbers => &[StyleComponent::LineNumbers],
3641 StyleComponent::Snip => &[StyleComponent::Snip],
3742 StyleComponent::Full => &[
3843 #[cfg(feature = "git")]
3944 StyleComponent::Changes,
4045 StyleComponent::Grid,
41− StyleComponent::Header,
46+ StyleComponent::HeaderFilename,
47+ StyleComponent::HeaderFilesize,
4248 StyleComponent::LineNumbers,
4349 StyleComponent::Snip,
4450 ],
@@ -58,6 +64,8 @@ impl FromStr for StyleComponent {
5864 "grid" => Ok(StyleComponent::Grid),
5965 "rule" => Ok(StyleComponent::Rule),
6066 "header" => Ok(StyleComponent::Header),
67+ "header-filename" => Ok(StyleComponent::HeaderFilename),
68+ "header-filesize" => Ok(StyleComponent::HeaderFilesize),
6169 "numbers" => Ok(StyleComponent::LineNumbers),
6270 "snip" => Ok(StyleComponent::Snip),
6371 "full" => Ok(StyleComponent::Full),
@@ -89,7 +97,15 @@ impl StyleComponents {
8997 }
9098
9199 pub fn header(&self) -> bool {
92− self.0.contains(&StyleComponent::Header)
100+ self.header_filename() || self.header_filesize()
101+ }
102+
103+ pub fn header_filename(&self) -> bool {
104+ self.0.contains(&StyleComponent::HeaderFilename)
105+ }
106+
107+ pub fn header_filesize(&self) -> bool {
108+ self.0.contains(&StyleComponent::HeaderFilesize)
93109 }
94110
95111 pub fn numbers(&self) -> bool {
tests/benchmarks/many-small-files/small-file-0.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 0
tests/benchmarks/many-small-files/small-file-1.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 1
tests/benchmarks/many-small-files/small-file-10.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 10
tests/benchmarks/many-small-files/small-file-100.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 100
tests/benchmarks/many-small-files/small-file-11.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 11
tests/benchmarks/many-small-files/small-file-12.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 12
tests/benchmarks/many-small-files/small-file-13.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 13
tests/benchmarks/many-small-files/small-file-14.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 14
tests/benchmarks/many-small-files/small-file-15.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 15
tests/benchmarks/many-small-files/small-file-16.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 16
tests/benchmarks/many-small-files/small-file-17.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 17
tests/benchmarks/many-small-files/small-file-18.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 18
tests/benchmarks/many-small-files/small-file-19.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 19
tests/benchmarks/many-small-files/small-file-2.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 2
tests/benchmarks/many-small-files/small-file-20.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 20
tests/benchmarks/many-small-files/small-file-21.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 21
tests/benchmarks/many-small-files/small-file-22.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 22
tests/benchmarks/many-small-files/small-file-23.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 23
tests/benchmarks/many-small-files/small-file-24.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 24
tests/benchmarks/many-small-files/small-file-25.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 25
tests/benchmarks/many-small-files/small-file-26.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 26
tests/benchmarks/many-small-files/small-file-27.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 27
tests/benchmarks/many-small-files/small-file-28.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 28
tests/benchmarks/many-small-files/small-file-29.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 29
tests/benchmarks/many-small-files/small-file-3.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 3
tests/benchmarks/many-small-files/small-file-30.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 30
tests/benchmarks/many-small-files/small-file-31.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 31
tests/benchmarks/many-small-files/small-file-32.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 32
tests/benchmarks/many-small-files/small-file-33.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 33
tests/benchmarks/many-small-files/small-file-34.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 34
tests/benchmarks/many-small-files/small-file-35.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 35
tests/benchmarks/many-small-files/small-file-36.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 36
tests/benchmarks/many-small-files/small-file-37.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 37
tests/benchmarks/many-small-files/small-file-38.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 38
tests/benchmarks/many-small-files/small-file-39.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 39
tests/benchmarks/many-small-files/small-file-4.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 4
tests/benchmarks/many-small-files/small-file-40.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 40
tests/benchmarks/many-small-files/small-file-41.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 41
tests/benchmarks/many-small-files/small-file-42.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 42
tests/benchmarks/many-small-files/small-file-43.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 43
tests/benchmarks/many-small-files/small-file-44.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 44
tests/benchmarks/many-small-files/small-file-45.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 45
tests/benchmarks/many-small-files/small-file-46.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 46
tests/benchmarks/many-small-files/small-file-47.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 47
tests/benchmarks/many-small-files/small-file-48.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 48
tests/benchmarks/many-small-files/small-file-49.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 49
tests/benchmarks/many-small-files/small-file-5.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 5
tests/benchmarks/many-small-files/small-file-50.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 50
tests/benchmarks/many-small-files/small-file-51.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 51
tests/benchmarks/many-small-files/small-file-52.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 52
tests/benchmarks/many-small-files/small-file-53.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 53
tests/benchmarks/many-small-files/small-file-54.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 54
tests/benchmarks/many-small-files/small-file-55.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 55
tests/benchmarks/many-small-files/small-file-56.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 56
tests/benchmarks/many-small-files/small-file-57.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 57
tests/benchmarks/many-small-files/small-file-58.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 58
tests/benchmarks/many-small-files/small-file-59.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 59
tests/benchmarks/many-small-files/small-file-6.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 6
tests/benchmarks/many-small-files/small-file-60.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 60
tests/benchmarks/many-small-files/small-file-61.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 61
tests/benchmarks/many-small-files/small-file-62.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 62
tests/benchmarks/many-small-files/small-file-63.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 63
tests/benchmarks/many-small-files/small-file-64.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 64
tests/benchmarks/many-small-files/small-file-65.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 65
tests/benchmarks/many-small-files/small-file-66.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 66
tests/benchmarks/many-small-files/small-file-67.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 67
tests/benchmarks/many-small-files/small-file-68.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 68
tests/benchmarks/many-small-files/small-file-69.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 69
tests/benchmarks/many-small-files/small-file-7.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 7
tests/benchmarks/many-small-files/small-file-70.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 70
tests/benchmarks/many-small-files/small-file-71.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 71
tests/benchmarks/many-small-files/small-file-72.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 72
tests/benchmarks/many-small-files/small-file-73.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 73
tests/benchmarks/many-small-files/small-file-74.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 74
tests/benchmarks/many-small-files/small-file-75.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 75
tests/benchmarks/many-small-files/small-file-76.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 76
tests/benchmarks/many-small-files/small-file-77.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 77
tests/benchmarks/many-small-files/small-file-78.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 78
tests/benchmarks/many-small-files/small-file-79.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 79
tests/benchmarks/many-small-files/small-file-8.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 8
tests/benchmarks/many-small-files/small-file-80.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 80
tests/benchmarks/many-small-files/small-file-81.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 81
tests/benchmarks/many-small-files/small-file-82.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 82
tests/benchmarks/many-small-files/small-file-83.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 83
tests/benchmarks/many-small-files/small-file-84.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 84
tests/benchmarks/many-small-files/small-file-85.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 85
tests/benchmarks/many-small-files/small-file-86.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 86
tests/benchmarks/many-small-files/small-file-87.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 87
tests/benchmarks/many-small-files/small-file-88.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 88
tests/benchmarks/many-small-files/small-file-89.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 89
tests/benchmarks/many-small-files/small-file-9.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 9
tests/benchmarks/many-small-files/small-file-90.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 90
tests/benchmarks/many-small-files/small-file-91.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 91
tests/benchmarks/many-small-files/small-file-92.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 92
tests/benchmarks/many-small-files/small-file-93.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 93
tests/benchmarks/many-small-files/small-file-94.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 94
tests/benchmarks/many-small-files/small-file-95.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 95
tests/benchmarks/many-small-files/small-file-96.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 96
tests/benchmarks/many-small-files/small-file-97.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 97
tests/benchmarks/many-small-files/small-file-98.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 98
tests/benchmarks/many-small-files/small-file-99.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 99
tests/benchmarks/run-benchmarks.sh+10
@@ -136,3 +136,13 @@ for wrap in character never; do
136136 cat "$RESULT_DIR/syntax-highlighting-speed-${filename}.md" >> "$REPORT"
137137 done
138138done
139+
140+
141+heading "Many small files speed (overhead of metadata)"
142+hyperfine \
143+ "$(printf "%q" "$BAT") --no-config --language=txt --style=plain many-small-files/*.txt" \
144+ --command-name 'bat … --language=txt *.txt' \
145+ --warmup "$WARMUP_COUNT" \
146+ --export-markdown "$RESULT_DIR/many-small-files-speed.md" \
147+ --export-json "$RESULT_DIR/many-small-files-speed.json"
148+cat "$RESULT_DIR/many-small-files-speed.md" >> "$REPORT"
tests/integration_tests.rs+65−2
@@ -919,7 +919,7 @@ fn empty_file_leads_to_empty_output_with_rule_enabled() {
919919}
920920
921921#[test]
922−fn filename_basic() {
922+fn header_basic() {
923923 bat()
924924 .arg("test.txt")
925925 .arg("--decorations=always")
@@ -933,7 +933,21 @@ fn filename_basic() {
933933}
934934
935935#[test]
936−fn filename_binary() {
936+fn header_full_basic() {
937+ bat()
938+ .arg("test.txt")
939+ .arg("--decorations=always")
940+ .arg("--style=header-filename,header-filesize")
941+ .arg("-r=0:0")
942+ .arg("--file-name=foo")
943+ .assert()
944+ .success()
945+ .stdout("File: foo\nSize: 12 B\n")
946+ .stderr("");
947+}
948+
949+#[test]
950+fn header_binary() {
937951 bat()
938952 .arg("test.binary")
939953 .arg("--decorations=always")
@@ -946,6 +960,20 @@ fn filename_binary() {
946960 .stderr("");
947961}
948962
963+#[test]
964+fn header_full_binary() {
965+ bat()
966+ .arg("test.binary")
967+ .arg("--decorations=always")
968+ .arg("--style=header-filename,header-filesize")
969+ .arg("-r=0:0")
970+ .arg("--file-name=foo")
971+ .assert()
972+ .success()
973+ .stdout("File: foo <BINARY>\nSize: 4 B\n")
974+ .stderr("");
975+}
976+
949977#[test]
950978fn filename_stdin() {
951979 bat()
@@ -1016,6 +1044,18 @@ fn header_padding() {
10161044 .stderr("");
10171045}
10181046
1047+#[test]
1048+fn header_full_padding() {
1049+ bat()
1050+ .arg("--decorations=always")
1051+ .arg("--style=header-filename,header-filesize")
1052+ .arg("test.txt")
1053+ .arg("single-line.txt")
1054+ .assert()
1055+ .stdout("File: test.txt\nSize: 12 B\nhello world\n\nFile: single-line.txt\nSize: 11 B\nSingle Line\n")
1056+ .stderr("");
1057+}
1058+
10191059#[test]
10201060fn header_padding_rule() {
10211061 bat()
@@ -1036,6 +1076,28 @@ Single Line
10361076 .stderr("");
10371077}
10381078
1079+#[test]
1080+fn header_full_padding_rule() {
1081+ bat()
1082+ .arg("--decorations=always")
1083+ .arg("--style=header-filename,header-filesize,rule")
1084+ .arg("--terminal-width=80")
1085+ .arg("test.txt")
1086+ .arg("single-line.txt")
1087+ .assert()
1088+ .stdout(
1089+ "File: test.txt
1090+Size: 12 B
1091+hello world
1092+────────────────────────────────────────────────────────────────────────────────
1093+File: single-line.txt
1094+Size: 11 B
1095+Single Line
1096+",
1097+ )
1098+ .stderr("");
1099+}
1100+
10391101#[test]
10401102fn grid_overrides_rule() {
10411103 bat()
@@ -1219,6 +1281,7 @@ fn grid_for_file_without_newline() {
12191281 "\
12201282───────┬────────────────────────────────────────────────────────────────────────
12211283 │ File: single-line.txt
1284+ │ Size: 11 B
12221285───────┼────────────────────────────────────────────────────────────────────────
12231286 1 │ Single Line
12241287───────┴────────────────────────────────────────────────────────────────────────
tests/snapshots/output/full.snapshot.txt+1
@@ -1,5 +1,6 @@
11───────┬────────────────────────────────────────────────────────────────────────
22 │ File: sample.rs
3+ │ Size: 533 B
34───────┼────────────────────────────────────────────────────────────────────────
45 1 + │ /// A rectangle. First line is changed to prevent a regression of #1869
56 2 │ struct Rectangle {