diff options
author | Oliver Looney <88001922+Oliver-Looney@users.noreply.github.com> | 2024-02-11 22:53:48 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-02-11 22:53:48 +0000 |
commit | c3f2ddf5092e9f81052e3183fdbf5ae68147a8af (patch) | |
tree | 5db103ecca22c96828cfed69dff304be35c4631f | |
parent | 8a51172b119d95fd5984ad46639307140b675c1b (diff) | |
parent | 5a2a20af42e7a426943122524287844acc5ee975 (diff) |
Merge branch 'master' into 2783-setting-terminal-title
58 files changed, 1935 insertions, 357 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index e3399922..b41d8d10 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,9 @@ ## Bugfixes +- Fix long file name wrapping in header, see #2835 (@FilipRazek) - Fix `NO_COLOR` support, see #2767 (@acuteenvy) +- Fix handling of inputs with OSC ANSI escape sequences, see #2541 and #2544 (@eth-p) ## Other @@ -17,18 +19,27 @@ - Minor benchmark script improvements #2768 (@cyqsimon) - Update Arch Linux package URL in README files #2779 (@brunobell) - Update and improve `zsh` completion, see #2772 (@okapia) +- More extensible syntax mapping mechanism #2755 (@cyqsimon) - Use proper Architecture for Debian packages built for musl, see #2811 (@Enselic) - Pull in fix for unsafe-libyaml security advisory, see #2812 (@dtolnay) - Update git-version dependency to use Syn v2, see #2816 (@dtolnay) +- Update git2 dependency to v0.18.2, see #2852 (@eth-p) ## Syntaxes - `cmd-help`: scope subcommands followed by other terms, and other misc improvements, see #2819 (@victor-gp) +- Upgrade JQ syntax, see #2820 (@dependabot[bot]) ## Themes ## `bat` as a library +- Changes to `syntax_mapping::SyntaxMapping` #2755 (@cyqsimon) + - `SyntaxMapping::get_syntax_for` is now correctly public + - [BREAKING] `SyntaxMapping::{empty,builtin}` are removed; use `SyntaxMapping::new` instead + - [BREAKING] `SyntaxMapping::mappings` is replaced by `SyntaxMapping::{builtin,custom,all}_mappings` +- Make `Controller::run_with_error_handler`'s error handler `FnMut`, see #2831 (@rhysd) +- Improve compile time by 20%, see #2815 (@dtolnay) # v0.24.0 @@ -129,6 +129,8 @@ dependencies = [ "globset", "grep-cli", "home", + "indexmap 2.2.2", + "itertools", "nix", "nu-ansi-term", "once_cell", @@ -140,12 +142,15 @@ dependencies = [ "run_script", "semver", "serde", + "serde_derive", + "serde_with", "serde_yaml", "serial_test", "shell-words", "syntect", "tempfile", "thiserror", + "toml", "unicode-width", "wait-timeout", "walkdir", @@ -224,11 +229,12 @@ checksum = "a3e368af43e418a04d52505cf3dbc23dda4e3407ae2fa99fd0e4f308ce546acc" [[package]] name = "cc" -version = "1.0.73" +version = "1.0.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" +checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" dependencies = [ "jobserver", + "libc", ] [[package]] @@ -267,13 +273,14 @@ checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" [[package]] name = "clircle" -version = "0.4.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8e87cbed5354f17bd8ca8821a097fb62599787fe8f611743fad7ee156a0a600" +checksum = "ec0b92245ea62a7a751db4b0e4a583f8978e508077ef6de24fcc0d0dc5311a8d" dependencies = [ "cfg-if", "libc", "serde", + "serde_derive", "winapi", ] @@ -315,6 +322,41 @@ dependencies = [ ] [[package]] +name = "darling" +version = "0.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0209d94da627ab5605dcccf08bb18afa5009cfbef48d8a8b7d7bdbc79be25c5e" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "177e3443818124b357d8e76f53be906d60937f0d3a90773a664fa63fa253e621" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn", +] + +[[package]] +name = "darling_macro" +version = "0.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5" +dependencies = [ + "darling_core", + "quote", + "syn", +] + +[[package]] name = "dashmap" version = "5.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -540,7 +582,7 @@ dependencies = [ "bstr", "log", "regex-automata", - "regex-syntax 0.8.2", + "regex-syntax", ] [[package]] @@ -579,6 +621,12 @@ dependencies = [ ] [[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] name = "idna" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -600,12 +648,13 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.0.2" +version = "2.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8adf3ddd720272c6ea8bf59463c04e0f93d0bbf7c5439b691bca2987e0270897" +checksum = "824b2ae422412366ba479e8111fd301f7b5faece8149317bb81925979a53f520" dependencies = [ "equivalent", "hashbrown 0.14.1", + "serde", ] [[package]] @@ -646,9 +695,9 @@ checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b" [[package]] name = "libgit2-sys" -version = "0.16.1+1.7.1" +version = "0.16.2+1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2a2bb3680b094add03bb3732ec520ece34da31a8cd2d633d1389d0f0fb60d0c" +checksum = "ee4126d8b4ee5c9d9ea891dd875cfdc1e9d0950437179104b183d7d8a74d24e8" dependencies = [ "cc", "libc", @@ -980,7 +1029,7 @@ dependencies = [ "aho-corasick", "memchr", "regex-automata", - "regex-syntax 0.8.2", + "regex-syntax", ] [[package]] @@ -991,17 +1040,11 @@ checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.8.2", + "regex-syntax", ] [[package]] name = "regex-syntax" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" - -[[package]] -name = "regex-syntax" version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" @@ -1066,9 +1109,9 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" [[package]] name = "semver" -version = "1.0.20" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090" +checksum = "b97ed7a9823b74f99c7742f5336af7be5ecd3eeafcb1507d1fa93347b1d589b0" [[package]] name = "serde" @@ -1102,12 +1145,44 @@ dependencies = [ ] [[package]] +name = "serde_spanned" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb3622f419d1296904700073ea6cc23ad690adbd66f13ea683df73298736f0c1" +dependencies = [ + "serde", +] + +[[package]] +name = "serde_with" +version = "3.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15d167997bd841ec232f5b2b8e0e26606df2e7caa4c31b95ea9ca52b200bd270" +dependencies = [ + "serde", + "serde_derive", + "serde_with_macros", +] + +[[package]] +name = "serde_with_macros" +version = "3.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "865f9743393e638991566a8b7a479043c2c8da94a33e0a31f18214c9cae0a64d" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn", +] + +[[package]] name = "serde_yaml" version = "0.9.29" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a15e0ef66bf939a7c890a0bf6d5a733c70202225f9888a89ed5c62298b019129" dependencies = [ - "indexmap 2.0.2", + "indexmap 2.2.2", "itoa", "ryu", "serde", @@ -1180,9 +1255,9 @@ dependencies = [ [[package]] name = "syntect" -version = "5.1.0" +version = "5.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e02b4b303bf8d08bfeb0445cba5068a3d306b6baece1d5582171a9bf49188f91" +checksum = "874dcfa363995604333cf947ae9f751ca3af4522c60886774c4963943b4746b1" dependencies = [ "bincode", "bitflags 1.3.2", @@ -1192,8 +1267,9 @@ dependencies = [ "once_cell", "onig", "plist", - "regex-syntax 0.7.5", + "regex-syntax", "serde", + "serde_derive", "serde_json", "thiserror", "walkdir", @@ -1295,6 +1371,41 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] +name = "toml" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6a4b9e8023eb94392d3dca65d717c53abc5dad49c07cb65bb8fcd87115fa325" +dependencies = [ + "indexmap 2.2.2", + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit", +] + +[[package]] +name = "toml_datetime" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_edit" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" +dependencies = [ + "indexmap 2.2.2", + "serde", + "serde_spanned", + "toml_datetime", + "winnow", +] + +[[package]] name = "unicode-bidi" version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1614,6 +1725,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" [[package]] +name = "winnow" +version = "0.5.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "176b6138793677221d420fd2f0aeeced263f197688b36484660da767bca2fa32" +dependencies = [ + "memchr", +] + +[[package]] name = "yaml-rust" version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -53,11 +53,12 @@ content_inspector = "0.2.4" shell-words = { version = "1.1.0", optional = true } unicode-width = "0.1.11" globset = "0.4" -serde = { version = "1.0", features = ["derive"] } +serde = "1.0" +serde_derive = "1.0" serde_yaml = "0.9.28" semver = "1.0" path_abs = { version = "0.5", default-features = false } -clircle = "0.4" +clircle = "0.5" bugreport = { version = "0.5.0", optional = true } etcetera = { version = "0.8.0", optional = true } grep-cli = { version = "0.1.10", optional = true } @@ -74,7 +75,7 @@ optional = true default-features = false [dependencies.syntect] -version = "5.1.0" +version = "5.2.0" default-features = false features = ["parsing"] @@ -94,12 +95,22 @@ serial_test = { version = "2.0.0", default-features = false } predicates = "3.0.4" wait-timeout = "0.2.0" tempfile = "3.8.1" +serde = { version = "1.0", features = ["derive"] } [target.'cfg(unix)'.dev-dependencies] nix = { version = "0.26.4", default-features = false, features = ["term"] } [build-dependencies] anyhow = "1.0.78" +indexmap = { version = "2.2.2", features = ["serde"] } +itertools = "0.11.0" +once_cell = "1.18" +regex = "1.10.2" +serde = "1.0" +serde_derive = "1.0" +serde_with = { version = "3.6.1", default-features = false, features = ["macros"] } +toml = { version = "0.8.9", features = ["preserve_order"] } +walkdir = "2.4" [build-dependencies.clap] version = "4.4.12" @@ -602,7 +602,8 @@ set, `less` is used by default. If you want to use a different pager, you can ei `PAGER` variable or set the `BAT_PAGER` environment variable to override what is specified in `PAGER`. -**Note**: If `PAGER` is `more` or `most`, `bat` will silently use `less` instead to ensure support for colors. +>[!NOTE] +> If `PAGER` is `more` or `most`, `bat` will silently use `less` instead to ensure support for colors. If you want to pass command-line arguments to the pager, you can also set them via the `PAGER`/`BAT_PAGER` variables: @@ -613,20 +614,37 @@ export BAT_PAGER="less -RF" Instead of using environment variables, you can also use `bat`s [configuration file](https://github.com/sharkdp/bat#configuration-file) to configure the pager (`--pager` option). -**Note**: By default, if the pager is set to `less` (and no command-line options are specified), -`bat` will pass the following command line options to the pager: `-R`/`--RAW-CONTROL-CHARS`, -`-F`/`--quit-if-one-screen` and `-X`/`--no-init`. The last option (`-X`) is only used for `less` -versions older than 530. -The `-R` option is needed to interpret ANSI colors correctly. The second option (`-F`) instructs -less to exit immediately if the output size is smaller than the vertical size of the terminal. -This is convenient for small files because you do not have to press `q` to quit the pager. The -third option (`-X`) is needed to fix a bug with the `--quit-if-one-screen` feature in old versions -of `less`. Unfortunately, it also breaks mouse-wheel support in `less`. +### Using `less` as a pager -If you want to enable mouse-wheel scrolling on older versions of `less`, you can pass just `-R` (as -in the example above, this will disable the quit-if-one-screen feature). For less 530 or newer, -it should work out of the box. +When using `less` as a pager, `bat` will automatically pass extra options along to `less` +to improve the experience. Specifically, `-R`/`--RAW-CONTROL-CHARS`, `-F`/`--quit-if-one-screen`, +and under certain conditions, `-X`/`--no-init` and/or `-S`/`--chop-long-lines`. + +>[!IMPORTANT] +> These options will not be added if: +> - The pager is not named `less`. +> - The `--pager` argument contains any command-line arguments (e.g. `--pager="less -R"`). +> - The `BAT_PAGER` environment variable contains any command-line arguments (e.g. `export BAT_PAGER="less -R"`) +> +> The `--quit-if-one-screen` option will not be added when: +> - The `--paging=always` argument is used. +> - The `BAT_PAGING` environment is set to `always`. + +The `-R` option is needed to interpret ANSI colors correctly. + +The `-F` option instructs `less` to exit immediately if the output size is smaller than +the vertical size of the terminal. This is convenient for small files because you do not +have to press `q` to quit the pager. + +The `-X` option is needed to fix a bug with the `--quit-if-one-screen` feature in versions +of `less` older than version 530. Unfortunately, it also breaks mouse-wheel support in `less`. +If you want to enable mouse-wheel scrolling on older versions of `less` and do not mind losing +the quit-if-one-screen feature, you can set the pager (via `--pager` or `BAT_PAGER`) to `less -R`. +For `less` 530 or newer, it should work out of the box. + +The `-S` option is added when `bat`'s `-S`/`--chop-long-lines` option is used. This tells `less` +to truncate any lines larger than the terminal width. ### Indentation diff --git a/assets/syntaxes/02_Extra/SublimeJQ b/assets/syntaxes/02_Extra/SublimeJQ -Subproject 687058289c1a888e0895378432d66b41609a84d +Subproject b7e53e5d86814f04a48d2e441bcf5f9fdf07e9c diff --git a/assets/syntaxes/02_Extra/cmd-help b/assets/syntaxes/02_Extra/cmd-help -Subproject b150d84534dd060afdcaf3f58977faeaf5917e5 +Subproject 209559b72f7e8848c988828088231b3a4d8b683 diff --git a/assets/themes/zenburn b/assets/themes/zenburn -Subproject e627f1cb223c1171ab0a6a48d166c87aeae2a1d +Subproject 86d4ee7a1f884851a1d21d66249687f527fced3 diff --git a/build/main.rs b/build/main.rs index 416d90d5..8966ee52 100644 --- a/build/main.rs +++ b/build/main.rs @@ -1,5 +1,6 @@ #[cfg(feature = "application")] mod application; +mod syntax_mapping; mod util; fn main() -> anyhow::Result<()> { @@ -7,6 +8,8 @@ fn main() -> anyhow::Result<()> { // see: https://doc.rust-lang.org/cargo/reference/build-scripts.html#rerun-if-changed println!("cargo:rerun-if-changed=build/"); + syntax_mapping::build_static_mappings()?; + #[cfg(feature = "application")] application::gen_man_and_comp()?; diff --git a/build/syntax_mapping.rs b/build/syntax_mapping.rs new file mode 100644 index 00000000..959caea8 --- /dev/null +++ b/build/syntax_mapping.rs @@ -0,0 +1,292 @@ +use std::{ + convert::Infallible, + env, fs, + path::{Path, PathBuf}, + str::FromStr, +}; + +use anyhow::{anyhow, bail}; +use indexmap::IndexMap; +use itertools::Itertools; +use once_cell::sync::Lazy; +use regex::Regex; +use serde_derive::Deserialize; +use serde_with::DeserializeFromStr; +use walkdir::WalkDir; + +/// Known mapping targets. +/// +/// Corresponds to `syntax_mapping::MappingTarget`. +#[allow(clippy::enum_variant_names)] +#[derive(Clone, Debug, Eq, PartialEq, Hash, DeserializeFromStr)] +pub enum MappingTarget { + MapTo(String), + MapToUnknown, + MapExtensionToUnknown, +} +impl FromStr for MappingTarget { + type Err = Infallible; + fn from_str(s: &str) -> Result<Self, Self::Err> { + match s { + "MappingTarget::MapToUnknown" => Ok(Self::MapToUnknown), + "MappingTarget::MapExtensionToUnknown" => Ok(Self::MapExtensionToUnknown), + syntax => Ok(Self::MapTo(syntax.into())), + } + } +} +impl MappingTarget { + fn codegen(&self) -> String { + match self { + Self::MapTo(syntax) => format!(r###"MappingTarget::MapTo(r#"{syntax}"#)"###), + Self::MapToUnknown => "MappingTarget::MapToUnknown".into(), + Self::MapExtensionToUnknown => "MappingTarget::MapExtensionToUnknown".into(), + } + } +} + +#[derive(Clone, Debug, PartialEq, Eq, Hash, DeserializeFromStr)] +/// A single matcher. +/// +/// Codegen converts this into a `Lazy<Option<GlobMatcher>>`. +struct Matcher(Vec<MatcherSegment>); +/// Parse a matcher. +/// +/// Note that this implementation is rather strict: it will greedily interpret +/// every valid environment variable replacement as such, then immediately +/// hard-error if it finds a '$', '{', or '}' anywhere in the remaining text +/// segments. +/// +/// The reason for this strictness is I currently cannot think of a valid reason +/// why you would ever need '$', '{', or '}' as plaintext in a glob pattern. +/// Therefore any such occurrences are likely human errors. +/// +/// If we later discover some edge cases, it's okay to make it more permissive. +impl FromStr for Matcher { + type Err = anyhow::Error; + fn from_str(s: &str) -> Result<Self, Self::Err> { + use MatcherSegment as Seg; + static VAR_REGEX: Lazy<Regex> = Lazy::new(|| Regex::new(r"\$\{([\w\d_]+)\}").unwrap()); + + let mut segments = vec![]; + let mut text_start = 0; + for capture in VAR_REGEX.captures_iter(s) { + let match_0 = capture.get(0).unwrap(); + + // text before this var + let text_end = match_0.start(); + segments.push(Seg::Text(s[text_start..text_end].into())); + text_start = match_0.end(); + + // this var + segments.push(Seg::Env(capture.get(1).unwrap().as_str().into())); + } + // possible trailing text + segments.push(Seg::Text(s[text_start..].into())); + + // cleanup empty text segments + let non_empty_segments = segments + .into_iter() + .filter(|seg| seg.text().map(|t| !t.is_empty()).unwrap_or(true)) + .collect_vec(); + + // sanity check + if non_empty_segments + .windows(2) + .any(|segs| segs[0].is_text() && segs[1].is_text()) + { + unreachable!("Parsed into consecutive text segments: {non_empty_segments:?}"); + } + + |