mirror of
https://github.com/sharkdp/bat.git
synced 2025-01-18 20:11:03 +00:00
Merge pull request #2665 from einfachIrgendwer0815/feature_squeeze
Add `-s`/`--squeeze` and `--squeeze-limit` (based on #1441).
This commit is contained in:
commit
6f69682552
@ -3,6 +3,9 @@
|
|||||||
## Features
|
## Features
|
||||||
|
|
||||||
- Set terminal title to file names when Paging is not Paging::Never #2807 (@Oliver-Looney)
|
- Set terminal title to file names when Paging is not Paging::Never #2807 (@Oliver-Looney)
|
||||||
|
- `bat --squeeze-blank`/`bat -s` will now squeeze consecutive empty lines, see #1441 (@eth-p) and #2665 (@einfachIrgendwer0815)
|
||||||
|
- `bat --squeeze-limit` to set the maximum number of empty consecutive when using `--squeeze-blank`, see #1441 (@eth-p) and #2665 (@einfachIrgendwer0815)
|
||||||
|
- `PrettyPrinter::squeeze_empty_lines` to support line squeezing for bat as a library, see #1441 (@eth-p) and #2665 (@einfachIrgendwer0815)
|
||||||
|
|
||||||
## Bugfixes
|
## Bugfixes
|
||||||
|
|
||||||
|
@ -116,6 +116,12 @@ Options:
|
|||||||
--list-themes
|
--list-themes
|
||||||
Display a list of supported themes for syntax highlighting.
|
Display a list of supported themes for syntax highlighting.
|
||||||
|
|
||||||
|
-s, --squeeze-blank
|
||||||
|
Squeeze consecutive empty lines into a single empty line.
|
||||||
|
|
||||||
|
--squeeze-limit <squeeze-limit>
|
||||||
|
Set the maximum number of consecutive empty lines to be printed.
|
||||||
|
|
||||||
--style <components>
|
--style <components>
|
||||||
Configure which elements (line numbers, file headers, grid borders, Git modifications, ..)
|
Configure which elements (line numbers, file headers, grid borders, Git modifications, ..)
|
||||||
to display in addition to the file contents. The argument is a comma-separated list of
|
to display in addition to the file contents. The argument is a comma-separated list of
|
||||||
|
@ -43,6 +43,8 @@ Options:
|
|||||||
Set the color theme for syntax highlighting.
|
Set the color theme for syntax highlighting.
|
||||||
--list-themes
|
--list-themes
|
||||||
Display all supported highlighting themes.
|
Display all supported highlighting themes.
|
||||||
|
-s, --squeeze-blank
|
||||||
|
Squeeze consecutive empty lines.
|
||||||
--style <components>
|
--style <components>
|
||||||
Comma-separated list of style elements to display (*default*, auto, full, plain, changes,
|
Comma-separated list of style elements to display (*default*, auto, full, plain, changes,
|
||||||
header, header-filename, header-filesize, grid, rule, numbers, snip).
|
header, header-filename, header-filesize, grid, rule, numbers, snip).
|
||||||
|
@ -290,6 +290,16 @@ impl App {
|
|||||||
#[cfg(feature = "lessopen")]
|
#[cfg(feature = "lessopen")]
|
||||||
use_lessopen: self.matches.get_flag("lessopen"),
|
use_lessopen: self.matches.get_flag("lessopen"),
|
||||||
set_terminal_title: self.matches.get_flag("set-terminal-title"),
|
set_terminal_title: self.matches.get_flag("set-terminal-title"),
|
||||||
|
squeeze_lines: if self.matches.get_flag("squeeze-blank") {
|
||||||
|
Some(
|
||||||
|
self.matches
|
||||||
|
.get_one::<usize>("squeeze-limit")
|
||||||
|
.map(|limit| limit.to_owned())
|
||||||
|
.unwrap_or(1),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -387,6 +387,21 @@ pub fn build_app(interactive_output: bool) -> Command {
|
|||||||
.help("Display all supported highlighting themes.")
|
.help("Display all supported highlighting themes.")
|
||||||
.long_help("Display a list of supported themes for syntax highlighting."),
|
.long_help("Display a list of supported themes for syntax highlighting."),
|
||||||
)
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::new("squeeze-blank")
|
||||||
|
.long("squeeze-blank")
|
||||||
|
.short('s')
|
||||||
|
.action(ArgAction::SetTrue)
|
||||||
|
.help("Squeeze consecutive empty lines.")
|
||||||
|
.long_help("Squeeze consecutive empty lines into a single empty line.")
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::new("squeeze-limit")
|
||||||
|
.long("squeeze-limit")
|
||||||
|
.value_parser(|s: &str| s.parse::<usize>().map_err(|_| "Requires a non-negative number".to_owned()))
|
||||||
|
.long_help("Set the maximum number of consecutive empty lines to be printed.")
|
||||||
|
.hide_short_help(true)
|
||||||
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::new("style")
|
Arg::new("style")
|
||||||
.long("style")
|
.long("style")
|
||||||
|
@ -97,6 +97,9 @@ pub struct Config<'a> {
|
|||||||
|
|
||||||
// Weather or not to set terminal title when using a pager
|
// Weather or not to set terminal title when using a pager
|
||||||
pub set_terminal_title: bool,
|
pub set_terminal_title: bool,
|
||||||
|
|
||||||
|
/// The maximum number of consecutive empty lines to display
|
||||||
|
pub squeeze_lines: Option<usize>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(all(feature = "minimal-application", feature = "paging"))]
|
#[cfg(all(feature = "minimal-application", feature = "paging"))]
|
||||||
|
@ -230,6 +230,12 @@ impl<'a> PrettyPrinter<'a> {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Specify the maximum number of consecutive empty lines to print.
|
||||||
|
pub fn squeeze_empty_lines(&mut self, maximum: Option<usize>) -> &mut Self {
|
||||||
|
self.config.squeeze_lines = maximum;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
/// Specify the highlighting theme
|
/// Specify the highlighting theme
|
||||||
pub fn theme(&mut self, theme: impl AsRef<str>) -> &mut Self {
|
pub fn theme(&mut self, theme: impl AsRef<str>) -> &mut Self {
|
||||||
self.config.theme = theme.as_ref().to_owned();
|
self.config.theme = theme.as_ref().to_owned();
|
||||||
|
@ -101,11 +101,15 @@ pub(crate) trait Printer {
|
|||||||
|
|
||||||
pub struct SimplePrinter<'a> {
|
pub struct SimplePrinter<'a> {
|
||||||
config: &'a Config<'a>,
|
config: &'a Config<'a>,
|
||||||
|
consecutive_empty_lines: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> SimplePrinter<'a> {
|
impl<'a> SimplePrinter<'a> {
|
||||||
pub fn new(config: &'a Config) -> Self {
|
pub fn new(config: &'a Config) -> Self {
|
||||||
SimplePrinter { config }
|
SimplePrinter {
|
||||||
|
config,
|
||||||
|
consecutive_empty_lines: 0,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -134,6 +138,21 @@ impl<'a> Printer for SimplePrinter<'a> {
|
|||||||
_line_number: usize,
|
_line_number: usize,
|
||||||
line_buffer: &[u8],
|
line_buffer: &[u8],
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
|
// Skip squeezed lines.
|
||||||
|
if let Some(squeeze_limit) = self.config.squeeze_lines {
|
||||||
|
if String::from_utf8_lossy(line_buffer)
|
||||||
|
.trim_end_matches(|c| c == '\r' || c == '\n')
|
||||||
|
.is_empty()
|
||||||
|
{
|
||||||
|
self.consecutive_empty_lines += 1;
|
||||||
|
if self.consecutive_empty_lines > squeeze_limit {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
self.consecutive_empty_lines = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if !out_of_range {
|
if !out_of_range {
|
||||||
if self.config.show_nonprintable {
|
if self.config.show_nonprintable {
|
||||||
let line = replace_nonprintable(
|
let line = replace_nonprintable(
|
||||||
@ -187,6 +206,7 @@ pub(crate) struct InteractivePrinter<'a> {
|
|||||||
pub line_changes: &'a Option<LineChanges>,
|
pub line_changes: &'a Option<LineChanges>,
|
||||||
highlighter_from_set: Option<HighlighterFromSet<'a>>,
|
highlighter_from_set: Option<HighlighterFromSet<'a>>,
|
||||||
background_color_highlight: Option<Color>,
|
background_color_highlight: Option<Color>,
|
||||||
|
consecutive_empty_lines: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> InteractivePrinter<'a> {
|
impl<'a> InteractivePrinter<'a> {
|
||||||
@ -272,6 +292,7 @@ impl<'a> InteractivePrinter<'a> {
|
|||||||
line_changes,
|
line_changes,
|
||||||
highlighter_from_set,
|
highlighter_from_set,
|
||||||
background_color_highlight,
|
background_color_highlight,
|
||||||
|
consecutive_empty_lines: 0,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -577,6 +598,18 @@ impl<'a> Printer for InteractivePrinter<'a> {
|
|||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Skip squeezed lines.
|
||||||
|
if let Some(squeeze_limit) = self.config.squeeze_lines {
|
||||||
|
if line.trim_end_matches(|c| c == '\r' || c == '\n').is_empty() {
|
||||||
|
self.consecutive_empty_lines += 1;
|
||||||
|
if self.consecutive_empty_lines > squeeze_limit {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
self.consecutive_empty_lines = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let mut cursor: usize = 0;
|
let mut cursor: usize = 0;
|
||||||
let mut cursor_max: usize = self.config.term_width;
|
let mut cursor_max: usize = self.config.term_width;
|
||||||
let mut cursor_total: usize = 0;
|
let mut cursor_total: usize = 0;
|
||||||
|
30
tests/examples/empty_lines.txt
vendored
Normal file
30
tests/examples/empty_lines.txt
vendored
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
line 1
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
line 5
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
line 20
|
||||||
|
line 21
|
||||||
|
|
||||||
|
|
||||||
|
line 24
|
||||||
|
|
||||||
|
line 26
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
line 30
|
@ -208,6 +208,70 @@ fn line_range_multiple() {
|
|||||||
.stdout("line 1\nline 2\nline 4\n");
|
.stdout("line 1\nline 2\nline 4\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn squeeze_blank() {
|
||||||
|
bat()
|
||||||
|
.arg("empty_lines.txt")
|
||||||
|
.arg("--squeeze-blank")
|
||||||
|
.assert()
|
||||||
|
.success()
|
||||||
|
.stdout("line 1\n\nline 5\n\nline 20\nline 21\n\nline 24\n\nline 26\n\nline 30\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn squeeze_blank_line_numbers() {
|
||||||
|
bat()
|
||||||
|
.arg("empty_lines.txt")
|
||||||
|
.arg("--squeeze-blank")
|
||||||
|
.arg("--decorations=always")
|
||||||
|
.arg("--number")
|
||||||
|
.assert()
|
||||||
|
.success()
|
||||||
|
.stdout(" 1 line 1\n 2 \n 5 line 5\n 6 \n 20 line 20\n 21 line 21\n 22 \n 24 line 24\n 25 \n 26 line 26\n 27 \n 30 line 30\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn squeeze_limit() {
|
||||||
|
bat()
|
||||||
|
.arg("empty_lines.txt")
|
||||||
|
.arg("--squeeze-blank")
|
||||||
|
.arg("--squeeze-limit=2")
|
||||||
|
.assert()
|
||||||
|
.success()
|
||||||
|
.stdout("line 1\n\n\nline 5\n\n\nline 20\nline 21\n\n\nline 24\n\nline 26\n\n\nline 30\n");
|
||||||
|
|
||||||
|
bat()
|
||||||
|
.arg("empty_lines.txt")
|
||||||
|
.arg("--squeeze-blank")
|
||||||
|
.arg("--squeeze-limit=5")
|
||||||
|
.assert()
|
||||||
|
.success()
|
||||||
|
.stdout("line 1\n\n\n\nline 5\n\n\n\n\n\nline 20\nline 21\n\n\nline 24\n\nline 26\n\n\n\nline 30\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn squeeze_limit_line_numbers() {
|
||||||
|
bat()
|
||||||
|
.arg("empty_lines.txt")
|
||||||
|
.arg("--squeeze-blank")
|
||||||
|
.arg("--squeeze-limit=2")
|
||||||
|
.arg("--decorations=always")
|
||||||
|
.arg("--number")
|
||||||
|
.assert()
|
||||||
|
.success()
|
||||||
|
.stdout(" 1 line 1\n 2 \n 3 \n 5 line 5\n 6 \n 7 \n 20 line 20\n 21 line 21\n 22 \n 23 \n 24 line 24\n 25 \n 26 line 26\n 27 \n 28 \n 30 line 30\n");
|
||||||
|
|
||||||
|
bat()
|
||||||
|
.arg("empty_lines.txt")
|
||||||
|
.arg("--squeeze-blank")
|
||||||
|
.arg("--squeeze-limit=5")
|
||||||
|
.arg("--decorations=always")
|
||||||
|
.arg("--number")
|
||||||
|
.assert()
|
||||||
|
.success()
|
||||||
|
.stdout(" 1 line 1\n 2 \n 3 \n 4 \n 5 line 5\n 6 \n 7 \n 8 \n 9 \n 10 \n 20 line 20\n 21 line 21\n 22 \n 23 \n 24 line 24\n 25 \n 26 line 26\n 27 \n 28 \n 29 \n 30 line 30\n");
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg_attr(any(not(feature = "git"), target_os = "windows"), ignore)]
|
#[cfg_attr(any(not(feature = "git"), target_os = "windows"), ignore)]
|
||||||
fn short_help() {
|
fn short_help() {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user