summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Peter <sharkdp@users.noreply.github.com>2024-02-24 20:36:17 +0100
committerGitHub <noreply@github.com>2024-02-24 20:36:17 +0100
commit6f69682552a46314b5cfbe229ce6da52f14b229a (patch)
tree7c0904370f412dbc0405b75a7fedae3385fd2292
parente1a3fc5529d55abc73aa5fb18368d22f9b9bb71c (diff)
parentbc5beaec5da357f5cf44e468079d11ec3174b828 (diff)
Merge pull request #2665 from einfachIrgendwer0815/feature_squeeze
Add `-s`/`--squeeze` and `--squeeze-limit` (based on #1441).
-rw-r--r--CHANGELOG.md3
-rw-r--r--doc/long-help.txt6
-rw-r--r--doc/short-help.txt2
-rw-r--r--src/bin/bat/app.rs10
-rw-r--r--src/bin/bat/clap_app.rs15
-rw-r--r--src/config.rs3
-rw-r--r--src/pretty_printer.rs6
-rw-r--r--src/printer.rs35
-rw-r--r--tests/examples/empty_lines.txt30
-rw-r--r--tests/integration_tests.rs64
10 files changed, 173 insertions, 1 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3c95cf9f..613fb8b9 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,6 +3,9 @@
## Features
- 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
diff --git a/doc/long-help.txt b/doc/long-help.txt
index 1aae60d8..a6ffe962 100644
--- a/doc/long-help.txt
+++ b/doc/long-help.txt
@@ -116,6 +116,12 @@ Options:
--list-themes
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>
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
diff --git a/doc/short-help.txt b/doc/short-help.txt
index 118dbce2..305bbf3d 100644
--- a/doc/short-help.txt
+++ b/doc/short-help.txt
@@ -43,6 +43,8 @@ Options:
Set the color theme for syntax highlighting.
--list-themes
Display all supported highlighting themes.
+ -s, --squeeze-blank
+ Squeeze consecutive empty lines.
--style <components>
Comma-separated list of style elements to display (*default*, auto, full, plain, changes,
header, header-filename, header-filesize, grid, rule, numbers, snip).
diff --git a/src/bin/bat/app.rs b/src/bin/bat/app.rs
index 8843d53b..c382975e 100644
--- a/src/bin/bat/app.rs
+++ b/src/bin/bat/app.rs
@@ -290,6 +290,16 @@ impl App {
#[cfg(feature = "lessopen")]
use_lessopen: self.matches.get_flag("lessopen"),
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
+ },
})
}
diff --git a/src/bin/bat/clap_app.rs b/src/bin/bat/clap_app.rs
index d3cb9276..ac7f5c18 100644
--- a/src/bin/bat/clap_app.rs
+++ b/src/bin/bat/clap_app.rs
@@ -388,6 +388,21 @@ pub fn build_app(interactive_output: bool) -> Command {
.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::new("style")
.long("style")
.value_name("components")
diff --git a/src/config.rs b/src/config.rs
index c5cc2abd..0298bb2a 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -97,6 +97,9 @@ pub struct Config<'a> {
// Weather or not to set terminal title when using a pager
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"))]
diff --git a/src/pretty_printer.rs b/src/pretty_printer.rs
index 121637f1..c6203aa9 100644
--- a/src/pretty_printer.rs
+++ b/src/pretty_printer.rs
@@ -230,6 +230,12 @@ impl<'a> PrettyPrinter<'a> {
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
pub fn theme(&mut self, theme: impl AsRef<str>) -> &mut Self {
self.config.theme = theme.as_ref().to_owned();
diff --git a/src/printer.rs b/src/printer.rs
index 8fd6bc8e..fc6c16f0 100644
--- a/src/printer.rs
+++ b/src/printer.rs
@@ -101,11 +101,15 @@ pub(crate) trait Printer {
pub struct SimplePrinter<'a> {
config: &'a Config<'a>,
+ consecutive_empty_lines: usize,
}
impl<'a> SimplePrinter<'a> {
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_buffer: &[u8],
) -> 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 self.config.show_nonprintable {
let line = replace_nonprintable(
@@ -187,6 +206,7 @@ pub(crate) struct InteractivePrinter<'a> {
pub line_changes: &'a Option<LineChanges>,
highlighter_from_set: Option<HighlighterFromSet<'a>>,
background_color_highlight: Option<Color>,
+ consecutive_empty_lines: usize,
}
impl<'a> InteractivePrinter<'a> {
@@ -272,6 +292,7 @@ impl<'a> InteractivePrinter<'a> {
line_changes,
highlighter_from_set,
background_color_highlight,
+ consecutive_empty_lines: 0,
})
}
@@ -577,6 +598,18 @@ impl<'a> Printer for InteractivePrinter<'a> {
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_max: usize = self.config.term_width;
let mut cursor_total: usize = 0;
diff --git a/tests/examples/empty_lines.txt b/tests/examples/empty_lines.txt
new file mode 100644
index 00000000..8ec1fae8
--- /dev/null
+++ b/tests/examples/empty_lines.txt
@@ -0,0 +1,30 @@
+line 1
+
+
+
+line 5
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+line 20
+line 21
+
+
+line 24
+
+line 26
+
+
+
+line 30
diff --git a/tests/integration_tests.rs b/tests/integration_tests.rs
index 3612654b..61537bee 100644
--- a/tests/integration_tests.rs
+++ b/tests/integration_tests.rs
@@ -209,6 +209,70 @@ fn line_range_multiple() {
}
#[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]
#[cfg_attr(any(not(feature = "git"), target_os = "windows"), ignore)]
fn short_help() {
test_help("-h", "../doc/short-help.txt");