mirror of
				https://github.com/sharkdp/bat.git
				synced 2025-10-31 15:12:12 +00:00 
			
		
		
		
	Merge branch 'master' into add-pipe-delimter-to-csv-syntax
This commit is contained in:
		| @@ -9,6 +9,7 @@ | ||||
| - Syntax highlighting for JavaScript files that start with `#!/usr/bin/env bun` #2913 (@sharunkumar) | ||||
| - `bat --strip-ansi={never,always,auto}` to remove ANSI escape sequences from bat's input, see #2999 (@eth-p) | ||||
| - Add or remove individual style components without replacing all styles #2929 (@eth-p) | ||||
| - Add option `--binary=as-text` for printing binary content, see issue #2974 and PR #2976 (@einfachIrgendwer0815) | ||||
|  | ||||
| ## Bugfixes | ||||
|  | ||||
| @@ -18,6 +19,7 @@ | ||||
| - Fix handling of inputs with combined ANSI color and attribute sequences, see #2185 and #2856 (@eth-p) | ||||
| - Fix panel width when line 10000 wraps, see #2854 (@eth-p) | ||||
| - Fix compile issue of `time` dependency caused by standard library regression #3045 (@cyqsimon) | ||||
| - Fix override behavior of --plain and --paging, see issue #2731 and PR #3108 (@einfachIrgendwer0815) | ||||
|  | ||||
| ## Other | ||||
|  | ||||
| @@ -63,6 +65,7 @@ | ||||
| - Map `*.mkd` files to `Markdown` syntax, see issue #3060 and PR #3061 (@einfachIrgendwer0815) | ||||
| - Add syntax mapping for kubernetes config files #3049 (@cyqsimon) | ||||
| - Adds support for pipe delimiter for CSV #3115 (@pratik-m) | ||||
| - Add syntax mapping for `/etc/pacman.conf` #2961 (@cyqsimon) | ||||
|  | ||||
| ## Themes | ||||
|  | ||||
| @@ -112,6 +115,7 @@ | ||||
| - Update `Julia` syntax, see #2553 (@dependabot) | ||||
| - add `NSIS` support, see #2577 (@idleberg) | ||||
| - Update `ssh-config`, see #2697 (@mrmeszaros) | ||||
| - Add syntax mapping `*.debdiff` => `diff`, see #2947 (@jacg) | ||||
|  | ||||
| ## `bat` as a library | ||||
|  | ||||
|   | ||||
							
								
								
									
										33
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										33
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							| @@ -279,12 +279,11 @@ checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" | ||||
|  | ||||
| [[package]] | ||||
| name = "clircle" | ||||
| version = "0.5.0" | ||||
| version = "0.6.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "ec0b92245ea62a7a751db4b0e4a583f8978e508077ef6de24fcc0d0dc5311a8d" | ||||
| checksum = "e136d50bd652710f1d86259a8977263d46bef0ab782a8bfc3887e44338517015" | ||||
| dependencies = [ | ||||
|  "cfg-if", | ||||
|  "libc", | ||||
|  "serde", | ||||
|  "serde_derive", | ||||
|  "winapi", | ||||
| @@ -422,9 +421,9 @@ checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" | ||||
|  | ||||
| [[package]] | ||||
| name = "encoding_rs" | ||||
| version = "0.8.34" | ||||
| version = "0.8.35" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" | ||||
| checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" | ||||
| dependencies = [ | ||||
|  "cfg-if", | ||||
| ] | ||||
| @@ -602,9 +601,9 @@ dependencies = [ | ||||
|  | ||||
| [[package]] | ||||
| name = "grep-cli" | ||||
| version = "0.1.10" | ||||
| version = "0.1.11" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "ea40788c059ab8b622c4d074732750bfb3bd2912e2dd58eabc11798a4d5ad725" | ||||
| checksum = "47f1288f0e06f279f84926fa4c17e3fcd2a22b357927a82f2777f7be26e4cec0" | ||||
| dependencies = [ | ||||
|  "bstr", | ||||
|  "globset", | ||||
| @@ -1147,9 +1146,9 @@ dependencies = [ | ||||
|  | ||||
| [[package]] | ||||
| name = "serde_spanned" | ||||
| version = "0.6.5" | ||||
| version = "0.6.8" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "eb3622f419d1296904700073ea6cc23ad690adbd66f13ea683df73298736f0c1" | ||||
| checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" | ||||
| dependencies = [ | ||||
|  "serde", | ||||
| ] | ||||
| @@ -1393,9 +1392,9 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" | ||||
|  | ||||
| [[package]] | ||||
| name = "toml" | ||||
| version = "0.8.9" | ||||
| version = "0.8.19" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "c6a4b9e8023eb94392d3dca65d717c53abc5dad49c07cb65bb8fcd87115fa325" | ||||
| checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e" | ||||
| dependencies = [ | ||||
|  "indexmap", | ||||
|  "serde", | ||||
| @@ -1406,18 +1405,18 @@ dependencies = [ | ||||
|  | ||||
| [[package]] | ||||
| name = "toml_datetime" | ||||
| version = "0.6.5" | ||||
| version = "0.6.8" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" | ||||
| checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" | ||||
| dependencies = [ | ||||
|  "serde", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "toml_edit" | ||||
| version = "0.21.1" | ||||
| version = "0.22.22" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" | ||||
| checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" | ||||
| dependencies = [ | ||||
|  "indexmap", | ||||
|  "serde", | ||||
| @@ -1747,9 +1746,9 @@ checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" | ||||
|  | ||||
| [[package]] | ||||
| name = "winnow" | ||||
| version = "0.5.18" | ||||
| version = "0.6.20" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "176b6138793677221d420fd2f0aeeced263f197688b36484660da767bca2fa32" | ||||
| checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b" | ||||
| dependencies = [ | ||||
|  "memchr", | ||||
| ] | ||||
|   | ||||
| @@ -58,14 +58,14 @@ serde_derive = "1.0" | ||||
| serde_yaml = "0.9.28" | ||||
| semver = "1.0" | ||||
| path_abs = { version = "0.5", default-features = false } | ||||
| clircle = "0.5" | ||||
| clircle = "0.6" | ||||
| bugreport = { version = "0.5.0", optional = true } | ||||
| etcetera = { version = "0.8.0", optional = true } | ||||
| grep-cli = { version = "0.1.10", optional = true } | ||||
| grep-cli = { version = "0.1.11", optional = true } | ||||
| regex = { version = "1.10.2", optional = true } | ||||
| walkdir = { version = "2.5", optional = true } | ||||
| bytesize = { version = "1.3.0" } | ||||
| encoding_rs = "0.8.34" | ||||
| encoding_rs = "0.8.35" | ||||
| os_str_bytes = { version = "~7.0", optional = true } | ||||
| run_script = { version = "^0.10.1", optional = true} | ||||
|  | ||||
| @@ -109,7 +109,7 @@ regex = "1.10.2" | ||||
| serde = "1.0" | ||||
| serde_derive = "1.0" | ||||
| serde_with = { version = "3.8.1", default-features = false, features = ["macros"] } | ||||
| toml = { version = "0.8.9", features = ["preserve_order"] } | ||||
| toml = { version = "0.8.19", features = ["preserve_order"] } | ||||
| walkdir = "2.5" | ||||
|  | ||||
| [build-dependencies.clap] | ||||
|   | ||||
| @@ -20,6 +20,13 @@ Options: | ||||
|             * unicode (␇, ␊, ␀, ..) | ||||
|             * caret   (^G, ^J, ^@, ..) | ||||
|  | ||||
|       --binary <behavior> | ||||
|           How to treat binary content. (default: no-printing) | ||||
|            | ||||
|           Possible values: | ||||
|             * no-printing: do not print any binary content | ||||
|             * as-text: treat binary content as normal text | ||||
|  | ||||
|   -p, --plain... | ||||
|           Only show plain style, no decorations. This is an alias for '--style=plain'. When '-p' is | ||||
|           used twice ('-pp'), it also disables automatic paging (alias for '--style=plain | ||||
|   | ||||
| @@ -11,6 +11,8 @@ Options: | ||||
|           Show non-printable characters (space, tab, newline, ..). | ||||
|       --nonprintable-notation <notation> | ||||
|           Set notation for non-printable characters. | ||||
|       --binary <behavior> | ||||
|           How to treat binary content. (default: no-printing) | ||||
|   -p, --plain... | ||||
|           Show plain style (alias for '--style=plain'). | ||||
|   -l, --language <language> | ||||
|   | ||||
| @@ -9,6 +9,7 @@ use crate::{ | ||||
|     config::{get_args_from_config_file, get_args_from_env_opts_var, get_args_from_env_vars}, | ||||
| }; | ||||
| use bat::style::StyleComponentList; | ||||
| use bat::BinaryBehavior; | ||||
| use bat::StripAnsiMode; | ||||
| use clap::ArgMatches; | ||||
|  | ||||
| @@ -97,12 +98,30 @@ impl App { | ||||
|     pub fn config(&self, inputs: &[Input]) -> Result<Config> { | ||||
|         let style_components = self.style_components()?; | ||||
|  | ||||
|         let extra_plain = self.matches.get_count("plain") > 1; | ||||
|         let plain_last_index = self | ||||
|             .matches | ||||
|             .indices_of("plain") | ||||
|             .and_then(Iterator::max) | ||||
|             .unwrap_or_default(); | ||||
|         let paging_last_index = self | ||||
|             .matches | ||||
|             .indices_of("paging") | ||||
|             .and_then(Iterator::max) | ||||
|             .unwrap_or_default(); | ||||
|  | ||||
|         let paging_mode = match self.matches.get_one::<String>("paging").map(|s| s.as_str()) { | ||||
|             Some("always") => PagingMode::Always, | ||||
|             Some("always") => { | ||||
|                 // Disable paging if the second -p (or -pp) is specified after --paging=always | ||||
|                 if extra_plain && plain_last_index > paging_last_index { | ||||
|                     PagingMode::Never | ||||
|                 } else { | ||||
|                     PagingMode::Always | ||||
|                 } | ||||
|             } | ||||
|             Some("never") => PagingMode::Never, | ||||
|             Some("auto") | None => { | ||||
|                 // If we have -pp as an option when in auto mode, the pager should be disabled. | ||||
|                 let extra_plain = self.matches.get_count("plain") > 1; | ||||
|                 if extra_plain || self.matches.get_flag("no-paging") { | ||||
|                     PagingMode::Never | ||||
|                 } else if inputs.iter().any(Input::is_stdin) { | ||||
| @@ -193,6 +212,11 @@ impl App { | ||||
|                 Some("caret") => NonprintableNotation::Caret, | ||||
|                 _ => unreachable!("other values for --nonprintable-notation are not allowed"), | ||||
|             }, | ||||
|             binary: match self.matches.get_one::<String>("binary").map(|s| s.as_str()) { | ||||
|                 Some("as-text") => BinaryBehavior::AsText, | ||||
|                 Some("no-printing") => BinaryBehavior::NoPrinting, | ||||
|                 _ => unreachable!("other values for --binary are not allowed"), | ||||
|             }, | ||||
|             wrapping_mode: if self.interactive_output || maybe_term_width.is_some() { | ||||
|                 if !self.matches.get_flag("chop-long-lines") { | ||||
|                     match self.matches.get_one::<String>("wrap").map(|s| s.as_str()) { | ||||
|   | ||||
| @@ -77,11 +77,26 @@ pub fn build_app(interactive_output: bool) -> Command { | ||||
|                     * caret   (^G, ^J, ^@, ..)", | ||||
|                 ), | ||||
|         ) | ||||
|         .arg( | ||||
|             Arg::new("binary") | ||||
|                 .long("binary") | ||||
|                 .action(ArgAction::Set) | ||||
|                 .default_value("no-printing") | ||||
|                 .value_parser(["no-printing", "as-text"]) | ||||
|                 .value_name("behavior") | ||||
|                 .hide_default_value(true) | ||||
|                 .help("How to treat binary content. (default: no-printing)") | ||||
|                 .long_help( | ||||
|                     "How to treat binary content. (default: no-printing)\n\n\ | ||||
|                     Possible values:\n  \ | ||||
|                     * no-printing: do not print any binary content\n  \ | ||||
|                     * as-text: treat binary content as normal text", | ||||
|                 ), | ||||
|         ) | ||||
|         .arg( | ||||
|             Arg::new("plain") | ||||
|                 .overrides_with("plain") | ||||
|                 .overrides_with("number") | ||||
|                 .overrides_with("paging") | ||||
|                 .short('p') | ||||
|                 .long("plain") | ||||
|                 .action(ArgAction::Count) | ||||
| @@ -306,7 +321,6 @@ pub fn build_app(interactive_output: bool) -> Command { | ||||
|                 .long("paging") | ||||
|                 .overrides_with("paging") | ||||
|                 .overrides_with("no-paging") | ||||
|                 .overrides_with("plain") | ||||
|                 .value_name("when") | ||||
|                 .value_parser(["auto", "never", "always"]) | ||||
|                 .default_value("auto") | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| use crate::line_range::{HighlightedLineRanges, LineRanges}; | ||||
| use crate::nonprintable_notation::NonprintableNotation; | ||||
| use crate::nonprintable_notation::{BinaryBehavior, NonprintableNotation}; | ||||
| #[cfg(feature = "paging")] | ||||
| use crate::paging::PagingMode; | ||||
| use crate::style::StyleComponents; | ||||
| @@ -44,6 +44,9 @@ pub struct Config<'a> { | ||||
|     /// The configured notation for non-printable characters | ||||
|     pub nonprintable_notation: NonprintableNotation, | ||||
|  | ||||
|     /// How to treat binary content | ||||
|     pub binary: BinaryBehavior, | ||||
|  | ||||
|     /// The character width of the terminal | ||||
|     pub term_width: usize, | ||||
|  | ||||
|   | ||||
| @@ -52,7 +52,7 @@ mod terminal; | ||||
| mod vscreen; | ||||
| pub(crate) mod wrapping; | ||||
|  | ||||
| pub use nonprintable_notation::NonprintableNotation; | ||||
| pub use nonprintable_notation::{BinaryBehavior, NonprintableNotation}; | ||||
| pub use preprocessor::StripAnsiMode; | ||||
| pub use pretty_printer::{Input, PrettyPrinter, Syntax}; | ||||
| pub use syntax_mapping::{MappingTarget, SyntaxMapping}; | ||||
|   | ||||
| @@ -10,3 +10,15 @@ pub enum NonprintableNotation { | ||||
|     #[default] | ||||
|     Unicode, | ||||
| } | ||||
|  | ||||
| /// How to treat binary content | ||||
| #[derive(Debug, Default, Clone, Copy, PartialEq, Eq)] | ||||
| #[non_exhaustive] | ||||
| pub enum BinaryBehavior { | ||||
|     /// Do not print any binary content | ||||
|     #[default] | ||||
|     NoPrinting, | ||||
|  | ||||
|     /// Treat binary content as normal text | ||||
|     AsText, | ||||
| } | ||||
|   | ||||
| @@ -35,6 +35,7 @@ use crate::style::StyleComponent; | ||||
| use crate::terminal::{as_terminal_escaped, to_ansi_color}; | ||||
| use crate::vscreen::{AnsiStyle, EscapeSequence, EscapeSequenceIterator}; | ||||
| use crate::wrapping::WrappingMode; | ||||
| use crate::BinaryBehavior; | ||||
| use crate::StripAnsiMode; | ||||
|  | ||||
| const ANSI_UNDERLINE_ENABLE: EscapeSequence = EscapeSequence::CSI { | ||||
| @@ -268,7 +269,8 @@ impl<'a> InteractivePrinter<'a> { | ||||
|             .content_type | ||||
|             .map_or(false, |c| c.is_binary() && !config.show_nonprintable); | ||||
|  | ||||
|         let needs_to_match_syntax = !is_printing_binary | ||||
|         let needs_to_match_syntax = (!is_printing_binary | ||||
|             || matches!(config.binary, BinaryBehavior::AsText)) | ||||
|             && (config.colored_output || config.strip_ansi == StripAnsiMode::Auto); | ||||
|  | ||||
|         let (is_plain_text, highlighter_from_set) = if needs_to_match_syntax { | ||||
| @@ -458,7 +460,10 @@ impl<'a> Printer for InteractivePrinter<'a> { | ||||
|         } | ||||
|  | ||||
|         if !self.config.style_components.header() { | ||||
|             if Some(ContentType::BINARY) == self.content_type && !self.config.show_nonprintable { | ||||
|             if Some(ContentType::BINARY) == self.content_type | ||||
|                 && !self.config.show_nonprintable | ||||
|                 && !matches!(self.config.binary, BinaryBehavior::AsText) | ||||
|             { | ||||
|                 writeln!( | ||||
|                     handle, | ||||
|                     "{}: Binary content from {} will not be printed to the terminal \ | ||||
| @@ -539,7 +544,10 @@ impl<'a> Printer for InteractivePrinter<'a> { | ||||
|             })?; | ||||
|  | ||||
|         if self.config.style_components.grid() { | ||||
|             if self.content_type.map_or(false, |c| c.is_text()) || self.config.show_nonprintable { | ||||
|             if self.content_type.map_or(false, |c| c.is_text()) | ||||
|                 || self.config.show_nonprintable | ||||
|                 || matches!(self.config.binary, BinaryBehavior::AsText) | ||||
|             { | ||||
|                 self.print_horizontal_line(handle, '┼')?; | ||||
|             } else { | ||||
|                 self.print_horizontal_line(handle, '┴')?; | ||||
| @@ -551,7 +559,9 @@ impl<'a> Printer for InteractivePrinter<'a> { | ||||
|  | ||||
|     fn print_footer(&mut self, handle: &mut OutputHandle, _input: &OpenedInput) -> Result<()> { | ||||
|         if self.config.style_components.grid() | ||||
|             && (self.content_type.map_or(false, |c| c.is_text()) || self.config.show_nonprintable) | ||||
|             && (self.content_type.map_or(false, |c| c.is_text()) | ||||
|                 || self.config.show_nonprintable | ||||
|                 || matches!(self.config.binary, BinaryBehavior::AsText)) | ||||
|         { | ||||
|             self.print_horizontal_line(handle, '┴') | ||||
|         } else { | ||||
| @@ -599,7 +609,9 @@ impl<'a> Printer for InteractivePrinter<'a> { | ||||
|             .into() | ||||
|         } else { | ||||
|             let mut line = match self.content_type { | ||||
|                 Some(ContentType::BINARY) | None => { | ||||
|                 Some(ContentType::BINARY) | None | ||||
|                     if !matches!(self.config.binary, BinaryBehavior::AsText) => | ||||
|                 { | ||||
|                     return Ok(()); | ||||
|                 } | ||||
|                 Some(ContentType::UTF_16LE) => UTF_16LE.decode_with_bom_removal(line_buffer).0, | ||||
|   | ||||
							
								
								
									
										3
									
								
								src/syntax_mapping/builtins/common/50-diff.toml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								src/syntax_mapping/builtins/common/50-diff.toml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | ||||
| # .debdiff is the extension used for diffs in Debian packaging | ||||
| [mappings] | ||||
| "Diff" = ["*.debdiff"] | ||||
| @@ -1,3 +1,8 @@ | ||||
| [mappings] | ||||
| # pacman hooks | ||||
| "INI" = ["/usr/share/libalpm/hooks/*.hook", "/etc/pacman.d/hooks/*.hook"] | ||||
| "INI" = [ | ||||
|     # config | ||||
|     "/etc/pacman.conf", | ||||
|     # hooks | ||||
|     "/usr/share/libalpm/hooks/*.hook", | ||||
|     "/etc/pacman.d/hooks/*.hook", | ||||
| ] | ||||
|   | ||||
| @@ -1019,6 +1019,31 @@ fn enable_pager_if_pp_flag_comes_before_paging() { | ||||
|         .stdout(predicate::eq("pager-output\n").normalize()); | ||||
| } | ||||
|  | ||||
| #[test] | ||||
| fn paging_does_not_override_simple_plain() { | ||||
|     bat() | ||||
|         .env("PAGER", "echo pager-output") | ||||
|         .arg("--decorations=always") | ||||
|         .arg("--plain") | ||||
|         .arg("--paging=never") | ||||
|         .arg("test.txt") | ||||
|         .assert() | ||||
|         .success() | ||||
|         .stdout(predicate::eq("hello world\n")); | ||||
| } | ||||
|  | ||||
| #[test] | ||||
| fn simple_plain_does_not_override_paging() { | ||||
|     bat() | ||||
|         .env("PAGER", "echo pager-output") | ||||
|         .arg("--paging=always") | ||||
|         .arg("--plain") | ||||
|         .arg("test.txt") | ||||
|         .assert() | ||||
|         .success() | ||||
|         .stdout(predicate::eq("pager-output\n")); | ||||
| } | ||||
|  | ||||
| #[test] | ||||
| fn pager_failed_to_parse() { | ||||
|     bat() | ||||
| @@ -1938,6 +1963,16 @@ fn show_all_with_unicode() { | ||||
|         .stderr(""); | ||||
| } | ||||
|  | ||||
| #[test] | ||||
| fn binary_as_text() { | ||||
|     bat() | ||||
|         .arg("--binary=as-text") | ||||
|         .arg("control_characters.txt") | ||||
|         .assert() | ||||
|         .stdout("\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F\x7F") | ||||
|         .stderr(""); | ||||
| } | ||||
|  | ||||
| #[test] | ||||
| fn no_paging_arg() { | ||||
|     bat() | ||||
|   | ||||
		Reference in New Issue
	
	Block a user