mirror of
https://github.com/sharkdp/bat.git
synced 2026-02-08 00:32:08 +00:00
Merge pull request #3496 from sharkdp/decorations_auto
Restore expected behavior when piping output with styles configured and auto decorations
This commit is contained in:
@@ -9,6 +9,7 @@
|
|||||||
- Fix hang when using `--list-themes` with an explicit pager, see #3457 (@abhinavcool42)
|
- Fix hang when using `--list-themes` with an explicit pager, see #3457 (@abhinavcool42)
|
||||||
- Fix negative values of N not being parsed in <N:M> line ranges without `=` flag value separator, see #3442 (@lmmx)
|
- Fix negative values of N not being parsed in <N:M> line ranges without `=` flag value separator, see #3442 (@lmmx)
|
||||||
- Fix broken Docker syntax preventing use of custom assets, see #3476 (@keith-hall)
|
- Fix broken Docker syntax preventing use of custom assets, see #3476 (@keith-hall)
|
||||||
|
- Fix decorations being applied unexpectedly when piping. Now only line numbers explicitly required on the command line should be applied in auto decorations mode for `cat` compatibility. See #3496 (@keith-hall)
|
||||||
|
|
||||||
## Other
|
## Other
|
||||||
- Improve README documentation on pager options passed to less, see #3443 (@injust)
|
- Improve README documentation on pager options passed to less, see #3443 (@injust)
|
||||||
|
|||||||
@@ -540,6 +540,12 @@ variable to make these changes permanent or use `bat`'s
|
|||||||
> Or, if you want to override the styles completely, you use `--style=numbers` to
|
> Or, if you want to override the styles completely, you use `--style=numbers` to
|
||||||
> only show the line numbers.
|
> only show the line numbers.
|
||||||
|
|
||||||
|
### Decorations
|
||||||
|
|
||||||
|
By default, `bat` only shows decorations (such as line numbers, file headers, grid borders, etc.) when outputting to an interactive terminal. You can control this behavior with the `--decorations` option. Use `--decorations=always` to show decorations even when piping output to another command, or `--decorations=never` to disable them entirely. Possible values are `auto` (default), `never`, and `always`.
|
||||||
|
|
||||||
|
There is also the `--force-colorization` option, which is an alias for `--decorations=always --color=always`. This is useful if you want to keep colorization and decorations when piping `bat`'s output to another program.
|
||||||
|
|
||||||
### Adding new syntaxes / language definitions
|
### Adding new syntaxes / language definitions
|
||||||
|
|
||||||
Should you find that a particular syntax is not available within `bat`, you can follow these
|
Should you find that a particular syntax is not available within `bat`, you can follow these
|
||||||
|
|||||||
@@ -46,6 +46,10 @@ enum HelpType {
|
|||||||
pub struct App {
|
pub struct App {
|
||||||
pub matches: ArgMatches,
|
pub matches: ArgMatches,
|
||||||
interactive_output: bool,
|
interactive_output: bool,
|
||||||
|
/// True if -n / --number was passed on the command line
|
||||||
|
/// (not from config file or environment variables).
|
||||||
|
/// This is used to honor the flag when piping output, similar to `cat -n`.
|
||||||
|
number_from_cli: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl App {
|
impl App {
|
||||||
@@ -54,6 +58,38 @@ impl App {
|
|||||||
let _ = nu_ansi_term::enable_ansi_support();
|
let _ = nu_ansi_term::enable_ansi_support();
|
||||||
|
|
||||||
let interactive_output = std::io::stdout().is_terminal();
|
let interactive_output = std::io::stdout().is_terminal();
|
||||||
|
|
||||||
|
// Check if the -n / --number option was passed on the command line
|
||||||
|
// (before merging with config file and environment variables).
|
||||||
|
// This is needed to honor the -n flag when piping output, similar to `cat -n`.
|
||||||
|
// We need to handle both standalone (-n, --number) and combined short flags (-pn, -An, etc.)
|
||||||
|
// Note: We only check if -n appears and is not overridden by -p in the same combined flag.
|
||||||
|
// For combined flags like -np, -p comes after -n and overrides it, so we don't count it.
|
||||||
|
// For combined flags like -pn, -n comes after -p and takes effect.
|
||||||
|
let number_from_cli = wild::args_os().any(|arg| {
|
||||||
|
let arg_str = arg.to_string_lossy();
|
||||||
|
if arg_str == "-n" || arg_str == "--number" {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// Handle combined short flags
|
||||||
|
// Only count -n if it's the LAST flag in the combined form (so -p doesn't override it)
|
||||||
|
// or if -p is not present in the combined form
|
||||||
|
if arg_str.starts_with('-') && !arg_str.starts_with("--") && arg_str.len() > 2 {
|
||||||
|
let chars: Vec<char> = arg_str.chars().skip(1).collect();
|
||||||
|
let n_pos = chars.iter().position(|&c| c == 'n');
|
||||||
|
let p_pos = chars.iter().position(|&c| c == 'p');
|
||||||
|
// -n is in the combined flag and either:
|
||||||
|
// - -p is not present, OR
|
||||||
|
// - -n comes after -p (so -n takes effect)
|
||||||
|
if let Some(n) = n_pos {
|
||||||
|
if p_pos.is_none() || n > p_pos.unwrap() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
false
|
||||||
|
});
|
||||||
|
|
||||||
let matches = Self::matches(interactive_output)?;
|
let matches = Self::matches(interactive_output)?;
|
||||||
|
|
||||||
if matches.get_flag("help") {
|
if matches.get_flag("help") {
|
||||||
@@ -91,6 +127,7 @@ impl App {
|
|||||||
Ok(App {
|
Ok(App {
|
||||||
matches,
|
matches,
|
||||||
interactive_output,
|
interactive_output,
|
||||||
|
number_from_cli,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -384,8 +421,7 @@ impl App {
|
|||||||
.map(|s| s.as_str())
|
.map(|s| s.as_str())
|
||||||
== Some("always")
|
== Some("always")
|
||||||
|| self.matches.get_flag("force-colorization")
|
|| self.matches.get_flag("force-colorization")
|
||||||
|| self.matches.get_flag("number")
|
|| self.number_from_cli),
|
||||||
|| self.matches.contains_id("style") && !style_components.plain()),
|
|
||||||
tab_width: self
|
tab_width: self
|
||||||
.matches
|
.matches
|
||||||
.get_one::<String>("tabs")
|
.get_one::<String>("tabs")
|
||||||
|
|||||||
@@ -166,6 +166,53 @@ fn line_numbers() {
|
|||||||
.stdout(" 1 line 1\n 2 line 2\n 3 line 3\n 4 line 4\n 5 line 5\n 6 line 6\n 7 line 7\n 8 line 8\n 9 line 9\n 10 line 10\n");
|
.stdout(" 1 line 1\n 2 line 2\n 3 line 3\n 4 line 4\n 5 line 5\n 6 line 6\n 7 line 7\n 8 line 8\n 9 line 9\n 10 line 10\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test that -n on command line shows line numbers even when piping (similar to `cat -n`)
|
||||||
|
#[test]
|
||||||
|
fn line_numbers_from_cli_in_loop_through_mode() {
|
||||||
|
bat()
|
||||||
|
.arg("multiline.txt")
|
||||||
|
.arg("-n")
|
||||||
|
.assert()
|
||||||
|
.success()
|
||||||
|
.stdout(" 1 line 1\n 2 line 2\n 3 line 3\n 4 line 4\n 5 line 5\n 6 line 6\n 7 line 7\n 8 line 8\n 9 line 9\n 10 line 10\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn style_from_env_var_ignored_and_line_numbers_from_cli_in_loop_through_mode() {
|
||||||
|
bat()
|
||||||
|
.env("BAT_STYLE", "full")
|
||||||
|
.arg("multiline.txt")
|
||||||
|
.arg("-n")
|
||||||
|
.arg("--decorations=auto")
|
||||||
|
.assert()
|
||||||
|
.success()
|
||||||
|
.stdout(" 1 line 1\n 2 line 2\n 3 line 3\n 4 line 4\n 5 line 5\n 6 line 6\n 7 line 7\n 8 line 8\n 9 line 9\n 10 line 10\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn numbers_ignored_from_cli_when_followed_by_plain_in_loop_through_mode() {
|
||||||
|
bat()
|
||||||
|
.arg("multiline.txt")
|
||||||
|
.arg("-np")
|
||||||
|
.arg("--decorations=auto")
|
||||||
|
.assert()
|
||||||
|
.success()
|
||||||
|
.stdout(
|
||||||
|
"line 1\nline 2\nline 3\nline 4\nline 5\nline 6\nline 7\nline 8\nline 9\nline 10\n",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn numbers_honored_from_cli_when_preceeded_by_plain_in_loop_through_mode() {
|
||||||
|
bat()
|
||||||
|
.arg("multiline.txt")
|
||||||
|
.arg("-pn")
|
||||||
|
.arg("--decorations=auto")
|
||||||
|
.assert()
|
||||||
|
.success()
|
||||||
|
.stdout(" 1 line 1\n 2 line 2\n 3 line 3\n 4 line 4\n 5 line 5\n 6 line 6\n 7 line 7\n 8 line 8\n 9 line 9\n 10 line 10\n");
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn line_range_2_3() {
|
fn line_range_2_3() {
|
||||||
bat()
|
bat()
|
||||||
@@ -415,26 +462,18 @@ fn piped_output_with_line_numbers_style_flag() {
|
|||||||
.write_stdin("hello\nworld\n")
|
.write_stdin("hello\nworld\n")
|
||||||
.assert()
|
.assert()
|
||||||
.success()
|
.success()
|
||||||
.stdout(" 1 hello\n 2 world\n");
|
.stdout("hello\nworld\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(not(target_os = "windows"))]
|
|
||||||
fn piped_output_with_line_numbers_with_header_grid_style_flag() {
|
fn piped_output_with_line_numbers_with_header_grid_style_flag() {
|
||||||
|
// style ignored because non-interactive
|
||||||
bat()
|
bat()
|
||||||
.arg("--style=header,grid,numbers")
|
.arg("--style=header,grid,numbers")
|
||||||
.write_stdin("hello\nworld\n")
|
.write_stdin("hello\nworld\n")
|
||||||
.assert()
|
.assert()
|
||||||
.success()
|
.success()
|
||||||
.stdout(
|
.stdout("hello\nworld\n");
|
||||||
"─────┬──────────────────────────────────────────────────────────────────────────
|
|
||||||
│ STDIN
|
|
||||||
─────┼──────────────────────────────────────────────────────────────────────────
|
|
||||||
1 │ hello
|
|
||||||
2 │ world
|
|
||||||
─────┴──────────────────────────────────────────────────────────────────────────
|
|
||||||
",
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -452,6 +491,7 @@ fn piped_output_with_auto_style() {
|
|||||||
fn piped_output_with_default_style_flag() {
|
fn piped_output_with_default_style_flag() {
|
||||||
bat()
|
bat()
|
||||||
.arg("--style=default")
|
.arg("--style=default")
|
||||||
|
.arg("--decorations=always")
|
||||||
.write_stdin("hello\nworld\n")
|
.write_stdin("hello\nworld\n")
|
||||||
.assert()
|
.assert()
|
||||||
.success()
|
.success()
|
||||||
|
|||||||
Reference in New Issue
Block a user