1
0
mirror of https://github.com/sharkdp/bat.git synced 2025-05-30 04:56:27 +01:00

Add new --style called header-filesize and display it by default ()

Also rename `header` to `header-filename`.

Related to 
This commit is contained in:
Mahdi Dibaiee 2022-02-07 19:48:57 +00:00 committed by GitHub
parent f3f8194932
commit 312c8ef01f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
111 changed files with 302 additions and 42 deletions
CHANGELOG.mdCargo.lockCargo.toml
src
tests/benchmarks/many-small-files
small-file-0.txtsmall-file-1.txtsmall-file-10.txtsmall-file-100.txtsmall-file-11.txtsmall-file-12.txtsmall-file-13.txtsmall-file-14.txtsmall-file-15.txtsmall-file-16.txtsmall-file-17.txtsmall-file-18.txtsmall-file-19.txtsmall-file-2.txtsmall-file-20.txtsmall-file-21.txtsmall-file-22.txtsmall-file-23.txtsmall-file-24.txtsmall-file-25.txtsmall-file-26.txtsmall-file-27.txtsmall-file-28.txtsmall-file-29.txtsmall-file-3.txtsmall-file-30.txtsmall-file-31.txtsmall-file-32.txtsmall-file-33.txtsmall-file-34.txtsmall-file-35.txtsmall-file-36.txtsmall-file-37.txtsmall-file-38.txtsmall-file-39.txtsmall-file-4.txtsmall-file-40.txtsmall-file-41.txtsmall-file-42.txtsmall-file-43.txtsmall-file-44.txtsmall-file-45.txtsmall-file-46.txtsmall-file-47.txtsmall-file-48.txtsmall-file-49.txtsmall-file-5.txtsmall-file-50.txtsmall-file-51.txtsmall-file-52.txtsmall-file-53.txtsmall-file-54.txtsmall-file-55.txtsmall-file-56.txtsmall-file-57.txtsmall-file-58.txtsmall-file-59.txtsmall-file-6.txtsmall-file-60.txtsmall-file-61.txtsmall-file-62.txtsmall-file-63.txtsmall-file-64.txtsmall-file-65.txtsmall-file-66.txtsmall-file-67.txtsmall-file-68.txtsmall-file-69.txtsmall-file-7.txtsmall-file-70.txtsmall-file-71.txtsmall-file-72.txtsmall-file-73.txtsmall-file-74.txtsmall-file-75.txtsmall-file-76.txtsmall-file-77.txtsmall-file-78.txtsmall-file-79.txtsmall-file-8.txtsmall-file-80.txtsmall-file-81.txtsmall-file-82.txtsmall-file-83.txtsmall-file-84.txtsmall-file-85.txtsmall-file-86.txtsmall-file-87.txtsmall-file-88.txtsmall-file-89.txtsmall-file-9.txtsmall-file-90.txtsmall-file-91.txt

@ -2,6 +2,8 @@
## Features
- New style component `header-filesize` to show size of the displayed file in the header. See #1988 (@mdibaiee)
## Bugfixes
## Other

7
Cargo.lock generated

@ -82,6 +82,7 @@ dependencies = [
"atty",
"bincode",
"bugreport",
"bytesize",
"clap",
"clircle",
"console",
@ -169,6 +170,12 @@ version = "1.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "439989e6b8c38d1b6570a384ef1e49c8848128f5a97f3914baef02920842712f"
[[package]]
name = "bytesize"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c58ec36aac5066d5ca17df51b3e70279f5670a72102f5752cb7e7c856adfc70"
[[package]]
name = "cc"
version = "1.0.72"

@ -65,6 +65,7 @@ dirs-next = { version = "2.0.0", optional = true }
grep-cli = { version = "0.1.6", optional = true }
regex = { version = "1.0", optional = true }
walkdir = { version = "2.0", optional = true }
bytesize = { version = "1.1.0" }
[dependencies.git2]
version = "0.13"

@ -396,11 +396,19 @@ pub fn build_app(interactive_output: bool) -> ClapApp<'static, 'static> {
.validator(|val| {
let mut invalid_vals = val.split(',').filter(|style| {
!&[
"auto", "full", "plain", "header", "grid", "rule", "numbers", "snip",
"auto",
"full",
"plain",
"header",
"header-filename",
"header-filesize",
"grid",
"rule",
"numbers",
"snip",
#[cfg(feature = "git")]
"changes",
]
.contains(style)
"changes",
].contains(style)
});
if let Some(invalid) = invalid_vals.next() {
@ -426,7 +434,9 @@ pub fn build_app(interactive_output: bool) -> ClapApp<'static, 'static> {
* auto: same as 'full', unless the output is piped.\n \
* plain: disables all available components.\n \
* changes: show Git modification markers.\n \
* header: show filenames before the content.\n \
* header: alias for 'header-filename'.\n \
* header-filename: show filenames before the content.\n \
* header-filesize: show file sizes before the content.\n \
* grid: vertical/horizontal lines to separate side bar\n \
and the header from the content.\n \
* rule: horizontal lines to delimit files.\n \

@ -1,4 +1,5 @@
use std::convert::TryFrom;
use std::fs;
use std::fs::File;
use std::io::{self, BufRead, BufReader, Read};
use std::path::{Path, PathBuf};
@ -87,6 +88,7 @@ impl<'a> InputKind<'a> {
#[derive(Clone, Default)]
pub(crate) struct InputMetadata {
pub(crate) user_provided_name: Option<PathBuf>,
pub(crate) size: Option<u64>,
}
pub struct Input<'a> {
@ -130,9 +132,14 @@ impl<'a> Input<'a> {
fn _ordinary_file(path: &Path) -> Self {
let kind = InputKind::OrdinaryFile(path.to_path_buf());
let metadata = InputMetadata {
size: fs::metadata(path).map(|m| m.len()).ok(),
..InputMetadata::default()
};
Input {
description: kind.description(),
metadata: InputMetadata::default(),
metadata,
kind,
}
}

@ -4,6 +4,8 @@ use std::vec::Vec;
use ansi_term::Colour::{Fixed, Green, Red, Yellow};
use ansi_term::Style;
use bytesize::ByteSize;
use console::AnsiCodeIterator;
use syntect::easy::HighlightLines;
@ -29,6 +31,7 @@ use crate::error::*;
use crate::input::OpenedInput;
use crate::line_range::RangeCheckResult;
use crate::preprocessor::{expand_tabs, replace_nonprintable};
use crate::style::StyleComponent;
use crate::terminal::{as_terminal_escaped, to_ansi_color};
use crate::vscreen::AnsiStyle;
use crate::wrapping::WrappingMode;
@ -250,6 +253,21 @@ impl<'a> InteractivePrinter<'a> {
}
}
fn print_header_component_indent(&mut self, handle: &mut dyn Write) -> std::io::Result<()> {
if self.config.style_components.grid() {
write!(
handle,
"{}{}",
" ".repeat(self.panel_width),
self.colors
.grid
.paint(if self.panel_width > 0 { "" } else { "" }),
)
} else {
write!(handle, "{}", " ".repeat(self.panel_width))
}
}
fn preprocess(&self, text: &str, cursor: &mut usize) -> String {
if self.config.tab_width > 0 {
return expand_tabs(text, self.config.tab_width, cursor);
@ -287,25 +305,6 @@ impl<'a> Printer for InteractivePrinter<'a> {
return Ok(());
}
if self.config.style_components.grid() {
self.print_horizontal_line(handle, '┬')?;
write!(
handle,
"{}{}",
" ".repeat(self.panel_width),
self.colors
.grid
.paint(if self.panel_width > 0 { "" } else { "" }),
)?;
} else {
// Only pad space between files, if we haven't already drawn a horizontal rule
if add_header_padding && !self.config.style_components.rule() {
writeln!(handle)?;
}
write!(handle, "{}", " ".repeat(self.panel_width))?;
}
let mode = match self.content_type {
Some(ContentType::BINARY) => " <BINARY>",
Some(ContentType::UTF_16LE) => " <UTF-16LE>",
@ -315,17 +314,60 @@ impl<'a> Printer for InteractivePrinter<'a> {
};
let description = &input.description;
let metadata = &input.metadata;
writeln!(
handle,
"{}{}{}",
description
.kind()
.map(|kind| format!("{}: ", kind))
.unwrap_or_else(|| "".into()),
self.colors.filename.paint(description.title()),
mode
)?;
// We use this iterator to have a deterministic order for
// header components. HashSet has arbitrary order, but Vec is ordered.
let header_components: Vec<StyleComponent> = [
(
StyleComponent::HeaderFilename,
self.config.style_components.header_filename(),
),
(
StyleComponent::HeaderFilesize,
self.config.style_components.header_filesize(),
),
]
.iter()
.filter(|(_, is_enabled)| *is_enabled)
.map(|(component, _)| *component)
.collect();
// Print the cornering grid before the first header component
if self.config.style_components.grid() {
self.print_horizontal_line(handle, '┬')?;
} else {
// Only pad space between files, if we haven't already drawn a horizontal rule
if add_header_padding && !self.config.style_components.rule() {
writeln!(handle)?;
}
}
header_components.iter().try_for_each(|component| {
self.print_header_component_indent(handle)?;
match component {
StyleComponent::HeaderFilename => writeln!(
handle,
"{}{}{}",
description
.kind()
.map(|kind| format!("{}: ", kind))
.unwrap_or_else(|| "".into()),
self.colors.header_value.paint(description.title()),
mode
),
StyleComponent::HeaderFilesize => {
let bsize = metadata
.size
.map(|s| format!("{}", ByteSize(s)))
.unwrap_or_else(|| "-".into());
writeln!(handle, "Size: {}", self.colors.header_value.paint(bsize))
}
_ => Ok(()),
}
})?;
if self.config.style_components.grid() {
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;
pub struct Colors {
pub grid: Style,
pub rule: Style,
pub filename: Style,
pub header_value: Style,
pub git_added: Style,
pub git_removed: Style,
pub git_modified: Style,
@ -646,7 +688,7 @@ impl Colors {
Colors {
grid: gutter_style,
rule: gutter_style,
filename: Style::new().bold(),
header_value: Style::new().bold(),
git_added: Green.normal(),
git_removed: Red.normal(),
git_modified: Yellow.normal(),

@ -3,6 +3,7 @@ use std::str::FromStr;
use crate::error::*;
#[non_exhaustive]
#[derive(Debug, Eq, PartialEq, Copy, Clone, Hash)]
pub enum StyleComponent {
Auto,
@ -11,6 +12,8 @@ pub enum StyleComponent {
Grid,
Rule,
Header,
HeaderFilename,
HeaderFilesize,
LineNumbers,
Snip,
Full,
@ -31,14 +34,17 @@ impl StyleComponent {
StyleComponent::Changes => &[StyleComponent::Changes],
StyleComponent::Grid => &[StyleComponent::Grid],
StyleComponent::Rule => &[StyleComponent::Rule],
StyleComponent::Header => &[StyleComponent::Header],
StyleComponent::Header => &[StyleComponent::HeaderFilename],
StyleComponent::HeaderFilename => &[StyleComponent::HeaderFilename],
StyleComponent::HeaderFilesize => &[StyleComponent::HeaderFilesize],
StyleComponent::LineNumbers => &[StyleComponent::LineNumbers],
StyleComponent::Snip => &[StyleComponent::Snip],
StyleComponent::Full => &[
#[cfg(feature = "git")]
StyleComponent::Changes,
StyleComponent::Grid,
StyleComponent::Header,
StyleComponent::HeaderFilename,
StyleComponent::HeaderFilesize,
StyleComponent::LineNumbers,
StyleComponent::Snip,
],
@ -58,6 +64,8 @@ impl FromStr for StyleComponent {
"grid" => Ok(StyleComponent::Grid),
"rule" => Ok(StyleComponent::Rule),
"header" => Ok(StyleComponent::Header),
"header-filename" => Ok(StyleComponent::HeaderFilename),
"header-filesize" => Ok(StyleComponent::HeaderFilesize),
"numbers" => Ok(StyleComponent::LineNumbers),
"snip" => Ok(StyleComponent::Snip),
"full" => Ok(StyleComponent::Full),
@ -89,7 +97,15 @@ impl StyleComponents {
}
pub fn header(&self) -> bool {
self.0.contains(&StyleComponent::Header)
self.header_filename() || self.header_filesize()
}
pub fn header_filename(&self) -> bool {
self.0.contains(&StyleComponent::HeaderFilename)
}
pub fn header_filesize(&self) -> bool {
self.0.contains(&StyleComponent::HeaderFilesize)
}
pub fn numbers(&self) -> bool {

@ -0,0 +1 @@
I am small file 0

@ -0,0 +1 @@
I am small file 1

@ -0,0 +1 @@
I am small file 10

@ -0,0 +1 @@
I am small file 100

@ -0,0 +1 @@
I am small file 11

@ -0,0 +1 @@
I am small file 12

@ -0,0 +1 @@
I am small file 13

@ -0,0 +1 @@
I am small file 14

@ -0,0 +1 @@
I am small file 15

@ -0,0 +1 @@
I am small file 16

@ -0,0 +1 @@
I am small file 17

@ -0,0 +1 @@
I am small file 18

@ -0,0 +1 @@
I am small file 19

@ -0,0 +1 @@
I am small file 2

@ -0,0 +1 @@
I am small file 20

@ -0,0 +1 @@
I am small file 21

@ -0,0 +1 @@
I am small file 22

@ -0,0 +1 @@
I am small file 23

@ -0,0 +1 @@
I am small file 24

@ -0,0 +1 @@
I am small file 25

@ -0,0 +1 @@
I am small file 26

@ -0,0 +1 @@
I am small file 27

@ -0,0 +1 @@
I am small file 28

@ -0,0 +1 @@
I am small file 29

@ -0,0 +1 @@
I am small file 3

@ -0,0 +1 @@
I am small file 30

@ -0,0 +1 @@
I am small file 31

@ -0,0 +1 @@
I am small file 32

@ -0,0 +1 @@
I am small file 33

@ -0,0 +1 @@
I am small file 34

@ -0,0 +1 @@
I am small file 35

@ -0,0 +1 @@
I am small file 36

@ -0,0 +1 @@
I am small file 37

@ -0,0 +1 @@
I am small file 38

@ -0,0 +1 @@
I am small file 39

@ -0,0 +1 @@
I am small file 4

@ -0,0 +1 @@
I am small file 40

@ -0,0 +1 @@
I am small file 41

@ -0,0 +1 @@
I am small file 42

@ -0,0 +1 @@
I am small file 43

@ -0,0 +1 @@
I am small file 44

@ -0,0 +1 @@
I am small file 45

@ -0,0 +1 @@
I am small file 46

@ -0,0 +1 @@
I am small file 47

@ -0,0 +1 @@
I am small file 48

@ -0,0 +1 @@
I am small file 49

@ -0,0 +1 @@
I am small file 5

@ -0,0 +1 @@
I am small file 50

@ -0,0 +1 @@
I am small file 51

@ -0,0 +1 @@
I am small file 52

@ -0,0 +1 @@
I am small file 53

@ -0,0 +1 @@
I am small file 54

@ -0,0 +1 @@
I am small file 55

@ -0,0 +1 @@
I am small file 56

@ -0,0 +1 @@
I am small file 57

@ -0,0 +1 @@
I am small file 58

@ -0,0 +1 @@
I am small file 59

@ -0,0 +1 @@
I am small file 6

@ -0,0 +1 @@
I am small file 60

@ -0,0 +1 @@
I am small file 61

@ -0,0 +1 @@
I am small file 62

@ -0,0 +1 @@
I am small file 63

@ -0,0 +1 @@
I am small file 64

@ -0,0 +1 @@
I am small file 65

@ -0,0 +1 @@
I am small file 66

@ -0,0 +1 @@
I am small file 67

@ -0,0 +1 @@
I am small file 68

@ -0,0 +1 @@
I am small file 69

@ -0,0 +1 @@
I am small file 7

@ -0,0 +1 @@
I am small file 70

@ -0,0 +1 @@
I am small file 71

@ -0,0 +1 @@
I am small file 72

@ -0,0 +1 @@
I am small file 73

@ -0,0 +1 @@
I am small file 74

@ -0,0 +1 @@
I am small file 75

@ -0,0 +1 @@
I am small file 76

@ -0,0 +1 @@
I am small file 77

@ -0,0 +1 @@
I am small file 78

@ -0,0 +1 @@
I am small file 79

@ -0,0 +1 @@
I am small file 8

@ -0,0 +1 @@
I am small file 80

@ -0,0 +1 @@
I am small file 81

@ -0,0 +1 @@
I am small file 82

@ -0,0 +1 @@
I am small file 83

@ -0,0 +1 @@
I am small file 84

@ -0,0 +1 @@
I am small file 85

@ -0,0 +1 @@
I am small file 86

@ -0,0 +1 @@
I am small file 87

@ -0,0 +1 @@
I am small file 88

@ -0,0 +1 @@
I am small file 89

@ -0,0 +1 @@
I am small file 9

@ -0,0 +1 @@
I am small file 90

@ -0,0 +1 @@
I am small file 91

Some files were not shown because too many files have changed in this diff Show More