diff --git a/.cargo/audit.toml b/.cargo/audit.toml new file mode 100644 index 00000000..90a57848 --- /dev/null +++ b/.cargo/audit.toml @@ -0,0 +1,2 @@ +[advisories] +ignore = ["RUSTSEC-2024-0320", "RUSTSEC-2024-0421"] diff --git a/.github/workflows/CICD.yml b/.github/workflows/CICD.yml index 68515f3d..5d2d27ae 100644 --- a/.github/workflows/CICD.yml +++ b/.github/workflows/CICD.yml @@ -152,6 +152,7 @@ jobs: name: cargo audit runs-on: ubuntu-latest steps: + - run: cargo install cargo-audit --locked - uses: actions/checkout@v4 - run: cargo audit @@ -170,9 +171,8 @@ jobs: - { target: i686-pc-windows-msvc , os: windows-2019, } - { target: i686-unknown-linux-gnu , os: ubuntu-20.04, dpkg_arch: i686, use-cross: true } - { target: i686-unknown-linux-musl , os: ubuntu-20.04, dpkg_arch: musl-linux-i686, use-cross: true } - - { target: x86_64-apple-darwin , os: macos-12, } + - { target: x86_64-apple-darwin , os: macos-13, } - { target: aarch64-apple-darwin , os: macos-14, } - - { target: x86_64-pc-windows-gnu , os: windows-2019, } - { target: x86_64-pc-windows-msvc , os: windows-2019, } - { target: x86_64-unknown-linux-gnu , os: ubuntu-20.04, dpkg_arch: amd64, use-cross: true } - { target: x86_64-unknown-linux-musl , os: ubuntu-20.04, dpkg_arch: musl-linux-amd64, use-cross: true } diff --git a/.github/workflows/require-changelog-for-PRs.yml b/.github/workflows/require-changelog-for-PRs.yml index 9b9d7cde..346ed385 100644 --- a/.github/workflows/require-changelog-for-PRs.yml +++ b/.github/workflows/require-changelog-for-PRs.yml @@ -30,4 +30,4 @@ jobs: echo "Added lines in CHANGELOG.md:" echo "$ADDED" echo "Grepping for PR info (see CONTRIBUTING.md):" - grep "#${PR_NUMBER}\\b.*@${PR_SUBMITTER}\\b" <<< "$ADDED" + grep "#${PR_NUMBER}\\b.*${PR_SUBMITTER}\\b" <<< "$ADDED" diff --git a/.gitignore b/.gitignore index a3ea8cff..fbfe6ac6 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ **/*.rs.bk # Generated files +/assets/completions/_bat.ps1 /assets/completions/bat.bash /assets/completions/bat.fish /assets/completions/bat.zsh diff --git a/.gitmodules b/.gitmodules index fe159da8..2c096761 100644 --- a/.gitmodules +++ b/.gitmodules @@ -65,7 +65,7 @@ path = assets/themes/onehalf url = https://github.com/sonph/onehalf [submodule "assets/syntaxes/JavaScript (Babel)"] - path = assets/syntaxes/02_Extra/JavaScript (Babel) + path = assets/syntaxes/02_Extra/JavaScript_(Babel) url = https://github.com/babel/babel-sublime [submodule "assets/syntaxes/FSharp"] path = assets/syntaxes/02_Extra/FSharp @@ -89,7 +89,7 @@ path = assets/themes/sublime-snazzy url = https://github.com/greggb/sublime-snazzy [submodule "assets/syntaxes/Assembly (ARM)"] - path = assets/syntaxes/02_Extra/Assembly (ARM) + path = assets/syntaxes/02_Extra/Assembly_(ARM) url = https://github.com/tvi/Sublime-ARM-Assembly [submodule "assets/syntaxes/protobuf-syntax-highlighting"] path = assets/syntaxes/02_Extra/Protobuf @@ -108,7 +108,7 @@ path = assets/syntaxes/02_Extra/Fish url = https://github.com/Phidica/sublime-fish.git [submodule "assets/syntaxes/Org mode"] - path = assets/syntaxes/02_Extra/Org mode + path = assets/syntaxes/02_Extra/Org_mode url = https://github.com/jezcope/Org.tmbundle.git [submodule "assets/syntaxes/DotENV"] path = assets/syntaxes/02_Extra/DotENV @@ -142,7 +142,7 @@ path = assets/themes/dracula-sublime url = https://github.com/dracula/sublime.git [submodule "assets/syntaxes/HTML (Twig)"] - path = assets/syntaxes/02_Extra/HTML (Twig) + path = assets/syntaxes/02_Extra/HTML_(Twig) url = https://github.com/Anomareh/PHP-Twig.tmbundle.git [submodule "assets/themes/Nord-sublime"] path = assets/themes/Nord-sublime @@ -263,3 +263,12 @@ [submodule "assets/syntaxes/02_Extra/CFML"] path = assets/syntaxes/02_Extra/CFML url = https://github.com/jcberquist/sublimetext-cfml.git +[submodule "assets/syntaxes/02_Extra/Idris2"] + path = assets/syntaxes/02_Extra/Idris2 + url = https://github.com/buzden/sublime-syntax-idris2 +[submodule "assets/syntaxes/02_Extra/GDScript-sublime"] + path = assets/syntaxes/02_Extra/GDScript-sublime + url = https://github.com/beefsack/GDScript-sublime +[submodule "assets/syntaxes/02_Extra/sublime-odin"] + path = assets/syntaxes/02_Extra/sublime-odin + url = https://github.com/odin-lang/sublime-odin diff --git a/CHANGELOG.md b/CHANGELOG.md index 09a46b22..ccfee8fa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,44 @@ ## Features +- Add paging to `--list-themes`, see PR #3239 (@einfachIrgendwer0815) +- Support negative relative line ranges, e.g. `bat -r :-10` / `bat -r='-10:'`, see #3068 (@ajesipow) + +## Bugfixes + +- Fix `BAT_THEME_DARK` and `BAT_THEME_LIGHT` being ignored, see issue #3171 and PR #3168 (@bash) +- Prevent `--list-themes` from outputting default theme info to stdout when it is piped, see #3189 (@einfachIrgendwer0815) +- Rename some submodules to fix Dependabot submodule updates, see issue #3198 and PR #3201 (@victor-gp) +- Make highlight tests fail when new syntaxes don't have fixtures PR #3255 (@dan-hipschman) +- Fix crash for multibyte characters in file path, see issue #3230 and PR #3245 (@HSM95) +- Add missing mappings for various bash/zsh files, see PR #3262 (@AdamGaskins) + +## Other + +- Work around build failures when building `bat` from vendored sources #3179 (@dtolnay) +- CICD: Stop building for x86_64-pc-windows-gnu which fails #3261 (Enselic) + +## Syntaxes + +- Add syntax mapping for `paru` configuration files #3182 (@cyqsimon) +- Add support for [Idris 2 programming language](https://www.idris-lang.org/) #3150 (@buzden) +- Add syntax mapping for `nix`'s '`flake.lock` lockfiles #3196 (@odilf) +- Improvements to CSV/TSV highlighting, with autodetection of delimiter and support for TSV files, see #3186 (@keith- +- Improve (Sys)log error highlighting, see #3205 (@keith-hall) +- Map `ndjson` extension to JSON syntax, see #3209 (@keith-hall) +- Map files with `csproj`, `vbproj`, `props` and `targets` extensions to XML syntax, see #3213 (@keith-hall) +- Add debsources syntax to highlight `/etc/apt/sources.list` files, see #3215 (@keith-hall) +- Add syntax definition and test file for GDScript highlighting, see #3236 (@chetanjangir0) +- Add syntax test file for Odin highlighting, see #3241 (@chetanjangir0) + +## Themes + +## `bat` as a library + +# v0.25.0 + +## 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) @@ -9,7 +47,10 @@ - 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) -- Support negative relative line ranges, e.g. `bat -r :-10` / `bat -r='-10:'`, see #3068 (@ajesipow) +- Automatically choose theme based on the terminal's color scheme, see #2896 (@bash) +- Add option `--binary=as-text` for printing binary content, see issue #2974 and PR #2976 (@einfachIrgendwer0815) +- Make shell completions available via `--completion `, see issue #2057 and PR #3126 (@einfachIrgendwer0815) +- Syntax highlighting for puppet code blocks within Markdown files, see #3152 (@liliwilson) ## Bugfixes @@ -19,6 +60,8 @@ - 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) +- Fix bugs in `$LESSOPEN` support, see #2805 (@Anomalocaridid) ## Other @@ -45,6 +88,9 @@ - Use bat's ANSI iterator during tab expansion, see #2998 (@eth-p) - Support 'statically linked binary' for aarch64 in 'Release' page, see #2992 (@tzq0301) - Update options in shell completions and the man page of `bat`, see #2995 (@akinomyoga) +- Update nix dev-dependency to v0.29.0, see #3112 (@decathorpe) +- Bump MSRV to [1.74](https://blog.rust-lang.org/2023/11/16/Rust-1.74.0.html), see #3154 (@keith-hall) +- Update clircle dependency to remove winapi transitive dependency, see #3113 (@niklasmohrin) ## Syntaxes @@ -56,12 +102,21 @@ - Associate JSON with Comments `.jsonc` with `json` syntax, see #2795 (@mxaddict) - Associate JSON-LD `.jsonld` files with `json` syntax, see #3037 (@vorburger) - Associate `.textproto` files with `ProtoBuf` syntax, see #3038 (@vorburger) +- Associate GeoJSON `.geojson` files with `json` syntax, see #3084 (@mvaaltola) - Associate `.aws/{config,credentials}`, see #2795 (@mxaddict) - Associate Wireguard config `/etc/wireguard/*.conf`, see #2874 (@cyqsimon) - Add support for [CFML](https://www.adobe.com/products/coldfusion-family.html), see #3031 (@brenton-at-pieces) +- Map `*.mkd` files to `Markdown` syntax, see issue #3060 and PR #3061 (@einfachIrgendwer0815) +- Add syntax mapping for CITATION.cff, see #3103 (@Ugzuzg) +- 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) +- Associate `uv.lock` with `TOML` syntax, see #3132 (@fepegar) ## Themes +- Patched/improved themes for better Manpage syntax highlighting support, see #2994 (@keith-hall). + ## `bat` as a library - Changes to `syntax_mapping::SyntaxMapping` #2755 (@cyqsimon) @@ -70,6 +125,10 @@ - [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) +- Add `theme::theme` for choosing an appropriate theme based on the + terminal's color scheme, see #2896 (@bash) + - [BREAKING] Remove `HighlightingAssets::default_theme`. Use `theme::default_theme` instead. +- Add `PrettyPrinter::print_with_writer` for custom output destinations, see #3070 (@kojix2) # v0.24.0 @@ -108,6 +167,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 diff --git a/Cargo.lock b/Cargo.lock index 1168501a..f836e3eb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3,16 +3,16 @@ version = 3 [[package]] -name = "adler" -version = "1.0.2" +name = "adler2" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" [[package]] name = "aho-corasick" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" dependencies = [ "memchr", ] @@ -28,67 +28,69 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.4" +version = "0.6.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ab91ebe16eb252986481c5b62f6098f3b698a45e34b5b98200cf20dd2484a44" +checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" dependencies = [ "anstyle", "anstyle-parse", "anstyle-query", "anstyle-wincon", "colorchoice", + "is_terminal_polyfill", "utf8parse", ] [[package]] name = "anstyle" -version = "1.0.0" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41ed9a86bf92ae6580e0a31281f65a1b1d867c0cc68d5346e2ae128dddfa6a7d" +checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" [[package]] name = "anstyle-parse" -version = "0.2.0" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e765fd216e48e067936442276d1d57399e37bce53c264d6fefbe298080cb57ee" +checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.0.0" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" +checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" dependencies = [ - "windows-sys 0.48.0", + "windows-sys 0.59.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.1" +version = "3.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0699d10d2f4d628a98ee7b57b289abbc98ff3bad977cb3152709d4bf2330628" +checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125" dependencies = [ "anstyle", - "windows-sys 0.48.0", + "windows-sys 0.59.0", ] [[package]] name = "anyhow" -version = "1.0.86" +version = "1.0.97" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" +checksum = "dcfed56ad506cb2c684a14971b8861fdc3baaaae314b9e5f9bb532cbe3ba7a4f" [[package]] name = "assert_cmd" -version = "2.0.12" +version = "2.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88903cb14723e4d4003335bb7f8a14f27691649105346a0f0957466c096adfe6" +checksum = "dc1835b7f27878de8525dc71410b5a31cdcc5f230aed5ba5df968e09c201b23d" dependencies = [ "anstyle", "bstr", "doc-comment", + "libc", "predicates", "predicates-core", "predicates-tree", @@ -97,19 +99,19 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.1.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "base64" -version = "0.21.0" +version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a4ddaa51a5bc52a6948f74c06d20aaaddb71924eab79b8c97a8c556e942d6a" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "bat" -version = "0.24.0" +version = "0.25.0" dependencies = [ "ansi_colours", "anyhow", @@ -123,6 +125,7 @@ dependencies = [ "content_inspector", "encoding_rs", "etcetera", + "execute", "expect-test", "flate2", "git2", @@ -130,16 +133,15 @@ dependencies = [ "grep-cli", "home", "indexmap", - "itertools", + "itertools 0.13.0", + "itertools 0.14.0", "nix", "nu-ansi-term", "once_cell", - "os_str_bytes", "path_abs", "plist", "predicates", "regex", - "run_script", "semver", "serde", "serde_derive", @@ -149,9 +151,11 @@ dependencies = [ "shell-words", "syntect", "tempfile", - "thiserror", + "terminal-colorsaurus", + "thiserror 2.0.11", "toml", - "unicode-width", + "unicode-segmentation", + "unicode-width 0.1.14", "wait-timeout", "walkdir", "wild", @@ -189,15 +193,15 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.4.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" [[package]] name = "bstr" -version = "1.8.0" +version = "1.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "542f33a8835a0884b006a0c3df3dadd99c0c3f296ed26c2fdc8028e01ad6230c" +checksum = "531a9155a481e2ee699d4f98f43c0ca4ff8ee1bfd55c31e9e98fb29d2b176fe0" dependencies = [ "memchr", "regex-automata", @@ -206,20 +210,20 @@ dependencies = [ [[package]] name = "bugreport" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "535120b8182547808081a66f1f77a64533c780b23da26763e0ee34dfb94f98c9" +checksum = "f280f65ce85b880919349bbfcb204930291251eedcb2e5f84ce2f51df969c162" dependencies = [ "git-version", "shell-escape", - "sys-info", + "sysinfo", ] [[package]] name = "bytemuck" -version = "1.12.1" +version = "1.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f5715e491b5a1598fc2bef5a606847b5dc1d48ea625bd3c02c00de8285591da" +checksum = "ef657dfab802224e671f5818e9a4935f9b1957ed18e58292690cc39e7a4092a3" [[package]] name = "bytesize" @@ -229,12 +233,13 @@ checksum = "a3e368af43e418a04d52505cf3dbc23dda4e3407ae2fa99fd0e4f308ce546acc" [[package]] name = "cc" -version = "1.0.83" +version = "1.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +checksum = "a012a0df96dd6d06ba9a1b29d6402d1a5d77c6befd2566afdc26e10603dc93d7" dependencies = [ "jobserver", "libc", + "shlex", ] [[package]] @@ -244,19 +249,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] -name = "clap" -version = "4.4.12" +name = "cfg_aliases" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcfab8ba68f3668e89f6ff60f5b205cea56aa7b769451a59f34b8682f51c056d" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + +[[package]] +name = "clap" +version = "4.5.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9560b07a799281c7e0958b9296854d6fafd4c5f31444a7e5bb1ad6dde5ccf1bd" dependencies = [ "clap_builder", ] [[package]] name = "clap_builder" -version = "4.4.12" +version = "4.5.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb7fb5e4e979aec3be7791562fcba452f94ad85e954da024396433e0e25a79e9" +checksum = "874e0dd3eb68bf99058751ac9712f622e61e6f393a94f7128fa26e3f02f5c7cd" dependencies = [ "anstream", "anstyle", @@ -267,40 +278,37 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.6.0" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" +checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" [[package]] name = "clircle" -version = "0.5.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0b92245ea62a7a751db4b0e4a583f8978e508077ef6de24fcc0d0dc5311a8d" +checksum = "7d9334f725b46fb9bed8580b9b47a932587e044fadb344ed7fa98774b067ac1a" dependencies = [ "cfg-if", - "libc", - "serde", - "serde_derive", - "winapi", + "windows 0.56.0", ] [[package]] name = "colorchoice" -version = "1.0.0" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" +checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" [[package]] name = "console" -version = "0.15.8" +version = "0.15.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e1f83fc076bd6dd27517eacdf25fef6c4dfe5f1d7448bafaaf3a26f13b5e4eb" +checksum = "ea3c6ecd8059b57859df5c69830340ed3c41d30e3da0c1cbed90a96ac853041b" dependencies = [ "encode_unicode", - "lazy_static", "libc", - "unicode-width", - "windows-sys 0.52.0", + "once_cell", + "unicode-width 0.2.0", + "windows-sys 0.59.0", ] [[package]] @@ -313,19 +321,50 @@ dependencies = [ ] [[package]] -name = "crc32fast" -version = "1.3.2" +name = "core-foundation-sys" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "crc32fast" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" dependencies = [ "cfg-if", ] [[package]] -name = "darling" -version = "0.20.3" +name = "crossbeam-deque" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0209d94da627ab5605dcccf08bb18afa5009cfbef48d8a8b7d7bdbc79be25c5e" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" + +[[package]] +name = "darling" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" dependencies = [ "darling_core", "darling_macro", @@ -333,9 +372,9 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.20.3" +version = "0.20.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "177e3443818124b357d8e76f53be906d60937f0d3a90773a664fa63fa253e621" +checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5" dependencies = [ "fnv", "ident_case", @@ -347,9 +386,9 @@ dependencies = [ [[package]] name = "darling_macro" -version = "0.20.3" +version = "0.20.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5" +checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ "darling_core", "quote", @@ -358,12 +397,12 @@ dependencies = [ [[package]] name = "dashmap" -version = "5.4.0" +version = "5.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "907076dfda823b0b36d2a1bb5f90c96660a5bbcd7729e10727f07858f22c4edc" +checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" dependencies = [ "cfg-if", - "hashbrown 0.12.3", + "hashbrown 0.14.5", "lock_api", "once_cell", "parking_lot_core", @@ -385,10 +424,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6184e33543162437515c2e2b48714794e37845ec9851711914eec9d308f6ebe8" [[package]] -name = "dissimilar" -version = "1.0.5" +name = "displaydoc" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd5f0c7e4bd266b8ab2550e6238d2e74977c23c15536ac7be45e9c95e2e3fbbb" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "dissimilar" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59f8e79d1fbf76bdfbde321e902714bf6c49df88a7dda6fc682fc2979226962d" [[package]] name = "doc-comment" @@ -396,29 +446,23 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" -[[package]] -name = "dunce" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bd4b30a6560bbd9b4620f4de34c3f14f60848e58a9b7216801afcb4c7b31c3c" - [[package]] name = "either" -version = "1.8.0" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" [[package]] name = "encode_unicode" -version = "0.3.6" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" +checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0" [[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", ] @@ -431,41 +475,67 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.3" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "136526188508e25c6fef639d7927dfb3e0e3084488bf202267829cf7fc23dbdd" +checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" dependencies = [ - "errno-dragonfly", - "libc", - "windows-sys 0.48.0", -] - -[[package]] -name = "errno-dragonfly" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" -dependencies = [ - "cc", "libc", + "windows-sys 0.59.0", ] [[package]] name = "etcetera" -version = "0.8.0" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "136d1b5283a1ab77bd9257427ffd09d8667ced0570b6f938942bc7568ed5b943" +checksum = "26c7b13d0780cb82722fd59f6f57f925e143427e4a75313a6c77243bf5326ae6" dependencies = [ "cfg-if", "home", - "windows-sys 0.48.0", + "windows-sys 0.59.0", ] [[package]] -name = "expect-test" -version = "1.5.0" +name = "execute" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e0be0a561335815e06dab7c62e50353134c796e7a6155402a64bcff66b6a5e0" +checksum = "3a82608ee96ce76aeab659e9b8d3c2b787bffd223199af88c674923d861ada10" +dependencies = [ + "execute-command-macro", + "execute-command-tokens", + "generic-array", +] + +[[package]] +name = "execute-command-macro" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90dec53d547564e911dc4ff3ecb726a64cf41a6fa01a2370ebc0d95175dd08bd" +dependencies = [ + "execute-command-macro-impl", +] + +[[package]] +name = "execute-command-macro-impl" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce8cd46a041ad005ab9c71263f9a0ff5b529eac0fe4cc9b4a20f4f0765d8cf4b" +dependencies = [ + "execute-command-tokens", + "quote", + "syn", +] + +[[package]] +name = "execute-command-tokens" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69dc321eb6be977f44674620ca3aa21703cb20ffbe560e1ae97da08401ffbcad" + +[[package]] +name = "expect-test" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63af43ff4431e848fb47472a920f14fa71c24de13255a5692e93d4e90302acb0" dependencies = [ "dissimilar", "once_cell", @@ -483,15 +553,15 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.0.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6999dc1837253364c2ebb0704ba97994bd874e8f195d665c50b7548f6ea92764" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" [[package]] name = "flate2" -version = "1.0.30" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f54427cfd1c7829e2a139fcefea601bf088ebca651d2bf53ebc600eac295dae" +checksum = "c936bfdafb507ebbf50b8074c54fa31c5be9a1e7e5f467dd659697041407d07c" dependencies = [ "crc32fast", "miniz_oxide", @@ -499,9 +569,9 @@ dependencies = [ [[package]] name = "float-cmp" -version = "0.9.0" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98de4bbd547a563b716d8dfa9aad1cb19bfab00f4fa09a6a4ed21dbcf44ce9c4" +checksum = "b09cf3155332e944990140d967ff5eceb70df778b34f77d8075db46e4704e6d8" dependencies = [ "num-traits", ] @@ -514,32 +584,32 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "form_urlencoded" -version = "1.1.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" dependencies = [ "percent-encoding", ] [[package]] -name = "fsio" -version = "0.4.0" +name = "generic-array" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dad0ce30be0cc441b325c5d705c8b613a0ca0d92b6a8953d41bd236dc09a36d0" +checksum = "2cb8bc4c28d15ade99c7e90b219f30da4be5c88e586277e8cbe886beeb868ab2" dependencies = [ - "dunce", - "rand", + "typenum", ] [[package]] name = "getrandom" -version = "0.2.7" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6" +checksum = "43a49c392881ce6d5c3b8cb70f98717b7c07aabbdff06687b9030dbfbe2725f8" dependencies = [ "cfg-if", "libc", - "wasi", + "wasi 0.13.3+wasi-0.2.2", + "windows-targets", ] [[package]] @@ -564,11 +634,11 @@ dependencies = [ [[package]] name = "git2" -version = "0.18.3" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "232e6a7bfe35766bf715e55a88b39a700596c0ccfd88cd3680b4cdb40d66ef70" +checksum = "3fda788993cc341f69012feba8bf45c0ba4f3291fcc08e214b4d5a7332d88aff" dependencies = [ - "bitflags 2.4.0", + "bitflags 2.6.0", "libc", "libgit2-sys", "log", @@ -577,15 +647,15 @@ dependencies = [ [[package]] name = "glob" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" +checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2" [[package]] name = "globset" -version = "0.4.14" +version = "0.4.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57da3b9b5b85bd66f31093f8c408b90a74431672542466497dcbdfdc02034be1" +checksum = "15f1ce686646e7f1e19bf7d5533fe443a45dbfb990e00629110797578b42fb19" dependencies = [ "aho-corasick", "bstr", @@ -596,9 +666,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", @@ -610,15 +680,15 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.12.3" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" [[package]] name = "hashbrown" -version = "0.14.1" +version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dfda62a12f55daeae5015f81b0baea145391cb4520f86c248fc615d72640d12" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" [[package]] name = "home" @@ -629,6 +699,124 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "icu_collections" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locid" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_locid_transform" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_locid_transform_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_locid_transform_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" + +[[package]] +name = "icu_normalizer" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "utf16_iter", + "utf8_iter", + "write16", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" + +[[package]] +name = "icu_properties" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_locid_transform", + "icu_properties_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" + +[[package]] +name = "icu_provider" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_provider_macros", + "stable_deref_trait", + "tinystr", + "writeable", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_provider_macros" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "ident_case" version = "1.0.1" @@ -637,25 +825,42 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "idna" -version = "0.3.0" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6" +checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" dependencies = [ - "unicode-bidi", - "unicode-normalization", + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" +dependencies = [ + "icu_normalizer", + "icu_properties", ] [[package]] name = "indexmap" -version = "2.3.0" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de3fc2e30ba82dd1b3911c8de1ffc143c74a914a14e99514d7637e3099df5ea0" +checksum = "3954d50fe15b02142bf25d3b8bdadb634ec3948f103d04ffe3031bc8fe9d7058" dependencies = [ "equivalent", - "hashbrown 0.14.1", + "hashbrown 0.15.2", "serde", ] +[[package]] +name = "is_terminal_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" + [[package]] name = "itertools" version = "0.13.0" @@ -666,37 +871,46 @@ dependencies = [ ] [[package]] -name = "itoa" -version = "1.0.3" +name = "itertools" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8af84674fe1f223a982c933a0ee1086ac4d4052aa0fb8060c12c6ad838e754" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" [[package]] name = "jobserver" -version = "0.1.25" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "068b1ee6743e4d11fb9c6a1e6064b3693a1b600e7f5f5988047d98b3dc9fb90b" +checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" dependencies = [ "libc", ] [[package]] name = "lazy_static" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.149" +version = "0.2.169" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b" +checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" [[package]] name = "libgit2-sys" -version = "0.16.2+1.7.2" +version = "0.18.0+1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee4126d8b4ee5c9d9ea891dd875cfdc1e9d0950437179104b183d7d8a74d24e8" +checksum = "e1a117465e7e1597e8febea8bb0c410f1c7fb93b1e1cddf34363f8390367ffec" dependencies = [ "cc", "libc", @@ -706,9 +920,9 @@ dependencies = [ [[package]] name = "libz-sys" -version = "1.1.8" +version = "1.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9702761c3935f8cc2f101793272e202c72b99da8f4224a19ddcf1279a6450bbf" +checksum = "df9b68e50e6e0b26f672573834882eb57759f6db9b3be2ea3c35c91188bb4eaa" dependencies = [ "cc", "libc", @@ -716,15 +930,6 @@ dependencies = [ "vcpkg", ] -[[package]] -name = "line-wrap" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f30344350a2a51da54c1d53be93fade8a237e545dbcc4bdbe635413f2117cab9" -dependencies = [ - "safemem", -] - [[package]] name = "linked-hash-map" version = "0.5.6" @@ -733,15 +938,21 @@ checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" [[package]] name = "linux-raw-sys" -version = "0.4.10" +version = "0.4.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da2479e8c062e40bf0066ffa0bc823de0a9368974af99c9f6df941d2c231e03f" +checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" + +[[package]] +name = "litemap" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104" [[package]] name = "lock_api" -version = "0.4.9" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" dependencies = [ "autocfg", "scopeguard", @@ -749,33 +960,45 @@ dependencies = [ [[package]] name = "log" -version = "0.4.20" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" [[package]] name = "memchr" -version = "2.6.4" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "miniz_oxide" -version = "0.7.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +checksum = "4ffbe83022cedc1d264172192511ae958937694cd57ce297164951b8b3568394" dependencies = [ - "adler", + "adler2", +] + +[[package]] +name = "mio" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" +dependencies = [ + "libc", + "wasi 0.11.0+wasi-snapshot-preview1", + "windows-sys 0.52.0", ] [[package]] name = "nix" -version = "0.26.4" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b" +checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.6.0", "cfg-if", + "cfg_aliases", "libc", ] @@ -786,12 +1009,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "61807f77802ff30975e01f4f071c8ba10c022052f98b3294119f3e615d13e5be" [[package]] -name = "nu-ansi-term" -version = "0.50.0" +name = "ntapi" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd2800e1520bdc966782168a627aa5d1ad92e33b984bf7c7615d31280c83ff14" +checksum = "e8a3895c6391c39d7fe7ebc444a87eb2991b2a0bc718fdabd071eec617fc68e4" dependencies = [ - "windows-sys 0.48.0", + "winapi", +] + +[[package]] +name = "nu-ansi-term" +version = "0.50.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4a28e057d01f97e61255210fcff094d74ed0466038633e95017f5beb68e4399" +dependencies = [ + "windows-sys 0.52.0", ] [[package]] @@ -802,18 +1034,18 @@ checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" [[package]] name = "num-traits" -version = "0.2.15" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", ] [[package]] name = "once_cell" -version = "1.19.0" +version = "1.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" [[package]] name = "onig" @@ -837,20 +1069,11 @@ dependencies = [ "pkg-config", ] -[[package]] -name = "os_str_bytes" -version = "7.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ac44c994af577c799b1b4bd80dc214701e349873ad894d6cdf96f4f7526e0b9" -dependencies = [ - "memchr", -] - [[package]] name = "parking_lot" -version = "0.12.1" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" dependencies = [ "lock_api", "parking_lot_core", @@ -858,15 +1081,15 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.7" +version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.2.16", + "redox_syscall", "smallvec", - "windows-sys 0.45.0", + "windows-targets", ] [[package]] @@ -880,25 +1103,24 @@ dependencies = [ [[package]] name = "percent-encoding" -version = "2.2.0" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pkg-config" -version = "0.3.25" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae" +checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" [[package]] name = "plist" -version = "1.6.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5699cc8a63d1aa2b1ee8e12b9ad70ac790d65788cd36101fa37f87ea46c4cef" +checksum = "42cf17e9a1800f5f396bc67d193dc9411b59012a5876445ef450d449881e1016" dependencies = [ "base64", "indexmap", - "line-wrap", "quick-xml", "serde", "time", @@ -910,17 +1132,11 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" -[[package]] -name = "ppv-lite86" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" - [[package]] name = "predicates" -version = "3.1.0" +version = "3.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68b87bfd4605926cdfefc1c3b5f8fe560e3feca9d5552cf68c466d3d8236c7e8" +checksum = "a5d19ee57562043d37e82899fade9a22ebab7be9cef5026b07fda9cdd4293573" dependencies = [ "anstyle", "difflib", @@ -932,15 +1148,15 @@ dependencies = [ [[package]] name = "predicates-core" -version = "1.0.6" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b794032607612e7abeb4db69adb4e33590fa6cf1149e95fd7cb00e634b92f174" +checksum = "727e462b119fe9c93fd0eb1429a5f7647394014cf3c04ab2c0350eeb09095ffa" [[package]] name = "predicates-tree" -version = "1.0.5" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d86de6de25020a36c6d3643a86d9a6a9f552107c0559c60ea03551b5e16c032" +checksum = "72dd2d6d381dfb73a193c7fca536518d7caee39fc8503f74e7dc0be0531b425c" dependencies = [ "predicates-core", "termtree", @@ -948,84 +1164,65 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.79" +version = "1.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e" +checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" dependencies = [ "unicode-ident", ] [[package]] name = "quick-xml" -version = "0.31.0" +version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1004a344b30a54e2ee58d66a71b32d2db2feb0a31f9a2d302bf0536f15de2a33" +checksum = "1d3a6e5838b60e0e8fa7a43f22ade549a37d61f8bdbe636d0d7816191de969c2" dependencies = [ "memchr", ] [[package]] name = "quote" -version = "1.0.35" +version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" dependencies = [ "proc-macro2", ] [[package]] -name = "rand" -version = "0.8.5" +name = "rayon" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" dependencies = [ - "libc", - "rand_chacha", - "rand_core", + "either", + "rayon-core", ] [[package]] -name = "rand_chacha" -version = "0.3.1" +name = "rayon-core" +version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" dependencies = [ - "ppv-lite86", - "rand_core", -] - -[[package]] -name = "rand_core" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" -dependencies = [ - "getrandom", + "crossbeam-deque", + "crossbeam-utils", ] [[package]] name = "redox_syscall" -version = "0.2.16" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" +checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834" dependencies = [ - "bitflags 1.3.2", -] - -[[package]] -name = "redox_syscall" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" -dependencies = [ - "bitflags 1.3.2", + "bitflags 2.6.0", ] [[package]] name = "regex" -version = "1.10.2" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" dependencies = [ "aho-corasick", "memchr", @@ -1035,9 +1232,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.3" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" dependencies = [ "aho-corasick", "memchr", @@ -1046,52 +1243,37 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.2" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "rgb" -version = "0.8.34" +version = "0.8.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3603b7d71ca82644f79b5a06d1220e9a58ede60bd32255f698cb1af8838b8db3" +checksum = "57397d16646700483b67d2dd6511d79318f9d057fdbd21a4066aeac8b41d310a" dependencies = [ "bytemuck", ] -[[package]] -name = "run_script" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "829f98fdc58d78989dd9af83be28bc15c94a7d77f9ecdb54abbbc0b1829ba9c7" -dependencies = [ - "fsio", -] - [[package]] name = "rustix" -version = "0.38.21" +version = "0.38.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b426b0506e5d50a7d8dafcf2e81471400deb602392c7dd110815afb4eaf02a3" +checksum = "a78891ee6bf2340288408954ac787aa063d8e8817e9f53abb37c695c6d834ef6" dependencies = [ - "bitflags 2.4.0", + "bitflags 2.6.0", "errno", "libc", "linux-raw-sys", - "windows-sys 0.48.0", + "windows-sys 0.59.0", ] [[package]] name = "ryu" -version = "1.0.11" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09" - -[[package]] -name = "safemem" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef703b7cb59335eae2eb93ceb664c0eb7ea6bf567079d843e09420219668e072" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "same-file" @@ -1104,30 +1286,30 @@ dependencies = [ [[package]] name = "scopeguard" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "semver" -version = "1.0.23" +version = "1.0.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" +checksum = "f79dfe2d285b0488816f30e700a7438c5a73d816b5b7d3ac72fbc48b0d185e03" [[package]] name = "serde" -version = "1.0.199" +version = "1.0.217" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c9f6e76df036c77cd94996771fb40db98187f096dd0b9af39c6c6e452ba966a" +checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.199" +version = "1.0.217" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11bd257a6541e141e42ca6d24ae26f7714887b47e89aa739099104c7e4d3b7fc" +checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" dependencies = [ "proc-macro2", "quote", @@ -1136,29 +1318,30 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.85" +version = "1.0.135" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e55a28e3aaef9d5ce0506d0a14dbba8054ddc7e499ef522dd8b26859ec9d4a44" +checksum = "2b0d7ba2887406110130a978386c4e1befb98c674b4fba677954e4db976630d9" dependencies = [ "itoa", + "memchr", "ryu", "serde", ] [[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", ] [[package]] name = "serde_with" -version = "3.8.1" +version = "3.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ad483d2ab0149d5a5ebcd9972a3852711e0153d863bf5a5d0391d28883c4a20" +checksum = "d6b6f7f2fcb69f747921f79f3926bd1e203fce4fef62c268dd3abfb6d86029aa" dependencies = [ "serde", "serde_derive", @@ -1167,9 +1350,9 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.8.1" +version = "3.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65569b702f41443e8bc8bbb1c5779bd0450bbe723b56198980e80ec45780bce2" +checksum = "8d00caa5193a3c8362ac2b73be6b9e768aa5a4b2f721d8f4b339600c3cb51f8e" dependencies = [ "darling", "proc-macro2", @@ -1179,9 +1362,9 @@ dependencies = [ [[package]] name = "serde_yaml" -version = "0.9.29" +version = "0.9.34+deprecated" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a15e0ef66bf939a7c890a0bf6d5a733c70202225f9888a89ed5c62298b019129" +checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" dependencies = [ "indexmap", "itoa", @@ -1226,10 +1409,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde" [[package]] -name = "smallvec" -version = "1.10.0" +name = "shlex" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" [[package]] name = "std_prelude" @@ -1239,21 +1434,32 @@ checksum = "8207e78455ffdf55661170876f88daf85356e4edd54e0a3dbc79586ca1e50cbe" [[package]] name = "strsim" -version = "0.10.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "syn" -version = "2.0.57" +version = "2.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11a6ae1e52eb25aab8f3fb9fca13be982a373b8f1157ca14b897a825ba4a2d35" +checksum = "46f71c0377baf4ef1cc3e3402ded576dccc315800fbc62dfc7fe04b009773b4a" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] +[[package]] +name = "synstructure" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "syntect" version = "5.2.0" @@ -1272,73 +1478,123 @@ dependencies = [ "serde", "serde_derive", "serde_json", - "thiserror", + "thiserror 1.0.69", "walkdir", "yaml-rust", ] [[package]] -name = "sys-info" -version = "0.9.1" +name = "sysinfo" +version = "0.33.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b3a0d0aba8bf96a0e1ddfdc352fc53b3df7f39318c71854910c3c4b024ae52c" +checksum = "4fc858248ea01b66f19d8e8a6d55f41deaf91e9d495246fd01368d99935c6c01" dependencies = [ - "cc", + "core-foundation-sys", "libc", + "memchr", + "ntapi", + "rayon", + "windows 0.57.0", ] [[package]] name = "tempfile" -version = "3.8.1" +version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ef1adac450ad7f4b3c28589471ade84f25f731a7a0fe30d71dfa9f60fd808e5" +checksum = "38c246215d7d24f48ae091a2902398798e05d978b24315d6efbc00ede9a8bb91" dependencies = [ "cfg-if", "fastrand", - "redox_syscall 0.4.1", + "getrandom", + "once_cell", "rustix", - "windows-sys 0.48.0", + "windows-sys 0.59.0", ] [[package]] name = "termcolor" -version = "1.4.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff1bc3d3f05aff0403e8ac0d92ced918ec05b666a43f83297ccef5bea8a3d449" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" dependencies = [ "winapi-util", ] [[package]] -name = "terminal_size" -version = "0.3.0" +name = "terminal-colorsaurus" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21bebf2b7c9e0a515f6e0f8c51dc0f8e4696391e6f1ff30379559f8365fb0df7" +checksum = "858625398bdd5da7a96e8ad33a10031a50c3a5ad50d5aaa81a2827369a9c216c" +dependencies = [ + "cfg-if", + "libc", + "memchr", + "mio", + "terminal-trx", + "windows-sys 0.59.0", +] + +[[package]] +name = "terminal-trx" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57a5b836e7f4f81afe61b5cd399eee774f25edcfd47009a76e29f53bb6487833" +dependencies = [ + "cfg-if", + "libc", + "windows-sys 0.59.0", +] + +[[package]] +name = "terminal_size" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5352447f921fda68cf61b4101566c0bdb5104eff6804d0678e5227580ab6a4e9" dependencies = [ "rustix", - "windows-sys 0.48.0", + "windows-sys 0.59.0", ] [[package]] name = "termtree" -version = "0.2.4" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "507e9898683b6c43a9aa55b64259b721b52ba226e0f3779137e50ad114a4c90b" +checksum = "8f50febec83f5ee1df3015341d8bd429f2d1cc62bcba7ea2076759d315084683" [[package]] name = "thiserror" -version = "1.0.61" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" dependencies = [ - "thiserror-impl", + "thiserror-impl 1.0.69", +] + +[[package]] +name = "thiserror" +version = "2.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d452f284b73e6d76dd36758a0c8684b1d5be31f92b89d07fd5822175732206fc" +dependencies = [ + "thiserror-impl 2.0.11", ] [[package]] name = "thiserror-impl" -version = "1.0.61" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26afc1baea8a989337eeb52b6e72a039780ce45c3edfcc9c5b9d112feeb173c2" dependencies = [ "proc-macro2", "quote", @@ -1347,9 +1603,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.36" +version = "0.3.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" +checksum = "35e7868883861bd0e56d9ac6efcaaca0d6d5d82a2a7ec8209ff492c07cf37b21" dependencies = [ "deranged", "itoa", @@ -1368,34 +1624,29 @@ checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.18" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" +checksum = "2834e6017e3e5e4b9834939793b282bc03b37a3336245fa820e35e233e2a85de" dependencies = [ "num-conv", "time-core", ] [[package]] -name = "tinyvec" -version = "1.6.0" +name = "tinystr" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" dependencies = [ - "tinyvec_macros", + "displaydoc", + "zerovec", ] -[[package]] -name = "tinyvec_macros" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -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 +1657,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", @@ -1427,43 +1678,46 @@ dependencies = [ ] [[package]] -name = "unicode-bidi" -version = "0.3.8" +name = "typenum" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] name = "unicode-ident" -version = "1.0.4" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcc811dc4066ac62f84f11307873c4850cb653bfa9b1719cee2bd2204a4bc5dd" +checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" [[package]] -name = "unicode-normalization" -version = "0.1.22" +name = "unicode-segmentation" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" -dependencies = [ - "tinyvec", -] +checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" [[package]] name = "unicode-width" -version = "0.1.13" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" + +[[package]] +name = "unicode-width" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fc81956842c57dac11422a97c3b8195a1ff727f06e85c84ed2e8aa277c9a0fd" [[package]] name = "unsafe-libyaml" -version = "0.2.10" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab4c90930b95a82d00dc9e9ac071b4991924390d46cbd0dfe566148667605e4b" +checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" [[package]] name = "url" -version = "2.3.1" +version = "2.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643" +checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" dependencies = [ "form_urlencoded", "idna", @@ -1471,10 +1725,22 @@ dependencies = [ ] [[package]] -name = "utf8parse" -version = "0.2.1" +name = "utf16_iter" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" +checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "vcpkg" @@ -1507,6 +1773,15 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "wasi" +version = "0.13.3+wasi-0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26816d2e1a4a36a2940b96c5296ce403917633dff8f3440e9b236ed6f6bacad2" +dependencies = [ + "wit-bindgen-rt", +] + [[package]] name = "wild" version = "2.2.1" @@ -1534,11 +1809,11 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.6" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "winapi", + "windows-sys 0.59.0", ] [[package]] @@ -1548,21 +1823,100 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] -name = "windows-sys" -version = "0.45.0" +name = "windows" +version = "0.56.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +checksum = "1de69df01bdf1ead2f4ac895dc77c9351aefff65b2f3db429a343f9cbf05e132" dependencies = [ - "windows-targets 0.42.1", + "windows-core 0.56.0", + "windows-targets", ] [[package]] -name = "windows-sys" -version = "0.48.0" +name = "windows" +version = "0.57.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +checksum = "12342cb4d8e3b046f3d80effd474a7a02447231330ef77d71daa6fbc40681143" dependencies = [ - "windows-targets 0.48.0", + "windows-core 0.57.0", + "windows-targets", +] + +[[package]] +name = "windows-core" +version = "0.56.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4698e52ed2d08f8658ab0c39512a7c00ee5fe2688c65f8c0a4f06750d729f2a6" +dependencies = [ + "windows-implement 0.56.0", + "windows-interface 0.56.0", + "windows-result", + "windows-targets", +] + +[[package]] +name = "windows-core" +version = "0.57.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2ed2439a290666cd67ecce2b0ffaad89c2a56b976b736e6ece670297897832d" +dependencies = [ + "windows-implement 0.57.0", + "windows-interface 0.57.0", + "windows-result", + "windows-targets", +] + +[[package]] +name = "windows-implement" +version = "0.56.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6fc35f58ecd95a9b71c4f2329b911016e6bec66b3f2e6a4aad86bd2e99e2f9b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "windows-implement" +version = "0.57.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9107ddc059d5b6fbfbffdfa7a7fe3e22a226def0b2608f72e9d552763d3e1ad7" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "windows-interface" +version = "0.56.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08990546bf4edef8f431fa6326e032865f27138718c587dc21bc0265bbcb57cc" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "windows-interface" +version = "0.57.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29bee4b38ea3cde66011baa44dba677c432a78593e202392d1e9070cf2a7fca7" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "windows-result" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e383302e8ec8515204254685643de10811af0ed97ea37210dc26fb0032647f8" +dependencies = [ + "windows-targets", ] [[package]] @@ -1571,189 +1925,112 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.0", + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", ] [[package]] name = "windows-targets" -version = "0.42.1" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e2522491fbfcd58cc84d47aeb2958948c4b8982e9a2d8a2a35bbaed431390e7" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm 0.42.1", - "windows_aarch64_msvc 0.42.1", - "windows_i686_gnu 0.42.1", - "windows_i686_msvc 0.42.1", - "windows_x86_64_gnu 0.42.1", - "windows_x86_64_gnullvm 0.42.1", - "windows_x86_64_msvc 0.42.1", -] - -[[package]] -name = "windows-targets" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" -dependencies = [ - "windows_aarch64_gnullvm 0.48.0", - "windows_aarch64_msvc 0.48.0", - "windows_i686_gnu 0.48.0", - "windows_i686_msvc 0.48.0", - "windows_x86_64_gnu 0.48.0", - "windows_x86_64_gnullvm 0.48.0", - "windows_x86_64_msvc 0.48.0", -] - -[[package]] -name = "windows-targets" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" -dependencies = [ - "windows_aarch64_gnullvm 0.52.0", - "windows_aarch64_msvc 0.52.0", - "windows_i686_gnu 0.52.0", - "windows_i686_msvc 0.52.0", - "windows_x86_64_gnu 0.52.0", - "windows_x86_64_gnullvm 0.52.0", - "windows_x86_64_msvc 0.52.0", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", ] [[package]] name = "windows_aarch64_gnullvm" -version = "0.42.1" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608" - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" -version = "0.42.1" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" -version = "0.42.1" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" [[package]] -name = "windows_i686_gnu" -version = "0.48.0" +name = "windows_i686_gnullvm" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" - -[[package]] -name = "windows_i686_gnu" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" -version = "0.42.1" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605" - -[[package]] -name = "windows_i686_msvc" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" - -[[package]] -name = "windows_i686_msvc" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" -version = "0.42.1" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" -version = "0.42.1" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" -version = "0.42.1" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" -version = "0.5.18" +version = "0.6.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "176b6138793677221d420fd2f0aeeced263f197688b36484660da767bca2fa32" +checksum = "39281189af81c07ec09db316b302a3e67bf9bd7cbf6c820b50e35fee9c2fa980" dependencies = [ "memchr", ] +[[package]] +name = "wit-bindgen-rt" +version = "0.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3268f3d866458b787f390cf61f4bbb563b922d091359f9608842999eaee3943c" +dependencies = [ + "bitflags 2.6.0", +] + +[[package]] +name = "write16" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" + +[[package]] +name = "writeable" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" + [[package]] name = "yaml-rust" version = "0.4.5" @@ -1762,3 +2039,70 @@ checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" dependencies = [ "linked-hash-map", ] + +[[package]] +name = "yoke" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" +dependencies = [ + "serde", + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + +[[package]] +name = "zerofrom" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cff3ee08c995dee1859d998dea82f7374f2826091dd9cd47def953cae446cd2e" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + +[[package]] +name = "zerovec" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] diff --git a/Cargo.toml b/Cargo.toml index 76234d5b..bd7bd912 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,11 +6,12 @@ homepage = "https://github.com/sharkdp/bat" license = "MIT OR Apache-2.0" name = "bat" repository = "https://github.com/sharkdp/bat" -version = "0.24.0" +version = "0.25.0" exclude = ["assets/syntaxes/*", "assets/themes/*"] build = "build/main.rs" edition = '2021' -rust-version = "1.70" +# You are free to bump MSRV as soon as a reason for bumping emerges. +rust-version = "1.74" [features] default = ["application"] @@ -33,7 +34,7 @@ minimal-application = [ ] git = ["git2"] # Support indicating git modifications paging = ["shell-words", "grep-cli"] # Support applying a pager on the output -lessopen = ["run_script", "os_str_bytes"] # Support $LESSOPEN preprocessor +lessopen = ["execute"] # Support $LESSOPEN preprocessor build-assets = ["syntect/yaml-load", "syntect/plist-load", "regex", "walkdir"] # You need to use one of these if you depend on bat as a library: @@ -44,10 +45,10 @@ regex-fancy = ["syntect/regex-fancy"] # Use the rust-only "fancy-regex" engine nu-ansi-term = "0.50.0" ansi_colours = "^1.2" bincode = "1.0" -console = "0.15.8" +console = "0.15.10" flate2 = "1.0" -once_cell = "1.19" -thiserror = "1.0" +once_cell = "1.20" +thiserror = "2.0" wild = { version = "2.2", optional = true } content_inspector = "0.2.4" shell-words = { version = "1.1.0", optional = true } @@ -58,20 +59,21 @@ serde_derive = "1.0" serde_yaml = "0.9.28" semver = "1.0" path_abs = { version = "0.5", default-features = false } -clircle = "0.5" +clircle = { version = "0.6.1", default-features = false } bugreport = { version = "0.5.0", optional = true } -etcetera = { version = "0.8.0", optional = true } -grep-cli = { version = "0.1.10", optional = true } -regex = { version = "1.10.2", optional = true } +etcetera = { version = "0.10.0", optional = true } +grep-cli = { version = "0.1.11", optional = true } +regex = { version = "1.10.6", optional = true } walkdir = { version = "2.5", optional = true } bytesize = { version = "1.3.0" } -encoding_rs = "0.8.34" -os_str_bytes = { version = "~7.0", optional = true } -run_script = { version = "^0.10.1", optional = true} +encoding_rs = "0.8.35" +execute = { version = "0.2.13", optional = true } +terminal-colorsaurus = "0.4" +unicode-segmentation = "1.12.0" itertools = "0.13.0" [dependencies.git2] -version = "0.18" +version = "0.20" optional = true default-features = false @@ -87,30 +89,30 @@ features = ["wrap_help", "cargo"] [target.'cfg(target_os = "macos")'.dependencies] home = "0.5.9" -plist = "1.6.0" +plist = "1.7.0" [dev-dependencies] assert_cmd = "2.0.12" expect-test = "1.5.0" serial_test = { version = "2.0.0", default-features = false } -predicates = "3.1.0" +predicates = "3.1.3" wait-timeout = "0.2.0" -tempfile = "3.8.1" +tempfile = "3.16.0" serde = { version = "1.0", features = ["derive"] } [target.'cfg(unix)'.dev-dependencies] -nix = { version = "0.26.4", default-features = false, features = ["term"] } +nix = { version = "0.29", default-features = false, features = ["term"] } [build-dependencies] -anyhow = "1.0.86" -indexmap = { version = "2.3.0", features = ["serde"] } -itertools = "0.13.0" -once_cell = "1.18" -regex = "1.10.2" +anyhow = "1.0.97" +indexmap = { version = "2.8.0", features = ["serde"] } +itertools = "0.14.0" +once_cell = "1.20" +regex = "1.10.6" 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"] } +serde_with = { version = "3.12.0", default-features = false, features = ["macros"] } +toml = { version = "0.8.19", features = ["preserve_order"] } walkdir = "2.5" [build-dependencies.clap] diff --git a/README.md b/README.md index 016fe834..3b3c8ec4 100644 --- a/README.md +++ b/README.md @@ -21,25 +21,14 @@ ### Sponsors -A special *thank you* goes to our biggest sponsors:
- - WorkOS -
- Your app, enterprise-ready. -
- Start selling to enterprise customers with just a few lines of code. -
- Add Single Sign-On (and more) in minutes instead of months. -
+A special *thank you* goes to our biggest sponsor:
- + Warp
- Warp is a modern, Rust-based terminal with AI built in
so you and your team can build great software, faster.
+ Warp, the intelligent terminal
- Feel more productive on the command line with parameterized commands, -
- autosuggestions, and an IDE-like text editor. + Available on MacOS, Linux, Windows
### Syntax highlighting @@ -204,24 +193,30 @@ bat main.cpp | xclip `MANPAGER` environment variable: ```bash -export MANPAGER="sh -c 'col -bx | bat -l man -p'" +export MANPAGER="sh -c 'sed -u -e \"s/\\x1B\[[0-9;]*m//g; s/.\\x08//g\" | bat -p -lman'" man 2 select ``` (replace `bat` with `batcat` if you are on Debian or Ubuntu) -It might also be necessary to set `MANROFFOPT="-c"` if you experience -formatting problems. - If you prefer to have this bundled in a new command, you can also use [`batman`](https://github.com/eth-p/bat-extras/blob/master/doc/batman.md). -Note that the [Manpage syntax](assets/syntaxes/02_Extra/Manpage.sublime-syntax) is developed in this repository and still needs some work. +> [!WARNING] +> This will [not work](https://github.com/sharkdp/bat/issues/1145) out of the box with Mandoc's `man` implementation. +> +> Please either use `batman`, or convert the shell script to a [shebang executable](https://en.wikipedia.org/wiki/Shebang_(Unix)) and point `MANPAGER` to that. -Also, note that this will [not work](https://github.com/sharkdp/bat/issues/1145) with Mandocs `man` implementation. +Note that the [Manpage syntax](assets/syntaxes/02_Extra/Manpage.sublime-syntax) is developed in this repository and still needs some work. #### `prettier` / `shfmt` / `rustfmt` The [`prettybat`](https://github.com/eth-p/bat-extras/blob/master/doc/prettybat.md) script is a wrapper that will format code and print it with `bat`. +#### `Warp` + + + Warp + + #### Highlighting `--help` messages You can use `bat` to colorize help text: `$ cp --help | bat -plhelp` @@ -245,6 +240,13 @@ alias -g -- -h='-h 2>&1 | bat --language=help --style=plain' alias -g -- --help='--help 2>&1 | bat --language=help --style=plain' ``` +For `fish`, you can use abbreviations: + +```fish +abbr -a --position anywhere -- --help '--help | bat -plhelp' +abbr -a --position anywhere -- -h '-h | bat -plhelp' +``` + This way, you can keep on using `cp --help`, but get colorized help pages. Be aware that in some cases, `-h` may not be a shorthand of `--help` (for example with `ls`). @@ -455,7 +457,7 @@ binaries are also available: look for archives with `musl` in the file name. ### From source -If you want to build `bat` from source, you need Rust 1.70.0 or +If you want to build `bat` from source, you need Rust 1.74.0 or higher. You can then use `cargo` to build everything: ```bash @@ -465,6 +467,12 @@ cargo install --locked bat Note that additional files like the man page or shell completion files can not be installed in this way. They will be generated by `cargo` and should be available in the cargo target folder (under `build`). +Shell completions are also available by running: +```bash +bat --completion +# see --help for supported shells +``` + ## Customization ### Highlighting theme @@ -482,8 +490,10 @@ the following command (you need [`fzf`](https://github.com/junegunn/fzf) for thi bat --list-themes | fzf --preview="bat --theme={} --color=always /path/to/file" ``` -`bat` looks good on a dark background by default. However, if your terminal uses a -light background, some themes like `GitHub` or `OneHalfLight` will work better for you. +`bat` automatically picks a fitting theme depending on your terminal's background color. +You can use the `--theme-dark` / `--theme-light` options or the `BAT_THEME_DARK` / `BAT_THEME_LIGHT` environment variables +to customize the themes used. This is especially useful if you frequently switch between dark and light mode. + You can also use a custom theme by following the ['Adding new themes' section below](https://github.com/sharkdp/bat#adding-new-themes). @@ -681,7 +691,7 @@ theme based on the OS theme. The following snippet uses the `default` theme when and the `GitHub` theme when in the _light mode_. ```bash -alias cat="bat --theme=\$(defaults read -globalDomain AppleInterfaceStyle &> /dev/null && echo default || echo GitHub)" +alias cat="bat --theme auto:system --theme-dark default --theme-light GitHub" ``` @@ -693,10 +703,11 @@ on your operating system. To get the default path for your system, call bat --config-file ``` -Alternatively, you can use the `BAT_CONFIG_PATH` environment variable to point `bat` to a -non-default location of the configuration file: +Alternatively, you can use `BAT_CONFIG_PATH` or `BAT_CONFIG_DIR` environment variables to point `bat` +to a non-default location of the configuration file or the configuration directory respectively: ```bash -export BAT_CONFIG_PATH="/path/to/bat.conf" +export BAT_CONFIG_PATH="/path/to/bat/bat.conf" +export BAT_CONFIG_DIR="/path/to/bat" ``` A default configuration file can be created with the `--generate-config-file` option. diff --git a/assets/acknowledgements.bin b/assets/acknowledgements.bin index 578a4f82..d62426dd 100644 Binary files a/assets/acknowledgements.bin and b/assets/acknowledgements.bin differ diff --git a/assets/completions/_bat.ps1.in b/assets/completions/_bat.ps1.in index c0c151e1..b6f62aae 100644 --- a/assets/completions/_bat.ps1.in +++ b/assets/completions/_bat.ps1.in @@ -37,6 +37,8 @@ Register-ArgumentCompleter -Native -CommandName '{{PROJECT_EXECUTABLE}}' -Script [CompletionResult]::new('-m', 'm', [CompletionResultType]::ParameterName, 'Use the specified syntax for files matching the glob pattern (''*.cpp:C++'').') [CompletionResult]::new('--map-syntax', 'map-syntax', [CompletionResultType]::ParameterName, 'Use the specified syntax for files matching the glob pattern (''*.cpp:C++'').') [CompletionResult]::new('--theme', 'theme', [CompletionResultType]::ParameterName, 'Set the color theme for syntax highlighting.') + [CompletionResult]::new('--theme-dark', 'theme', [CompletionResultType]::ParameterName, 'Set the color theme for syntax highlighting for dark backgrounds.') + [CompletionResult]::new('--theme-light', 'theme', [CompletionResultType]::ParameterName, 'Set the color theme for syntax highlighting for light backgrounds.') [CompletionResult]::new('--style', 'style', [CompletionResultType]::ParameterName, 'Comma-separated list of style elements to display (*default*, auto, full, plain, changes, header, header-filename, header-filesize, grid, rule, numbers, snip).') [CompletionResult]::new('-r', 'r', [CompletionResultType]::ParameterName, 'Only print the lines from N to M.') [CompletionResult]::new('--line-range', 'line-range', [CompletionResultType]::ParameterName, 'Only print the lines from N to M.') diff --git a/assets/completions/bat.bash.in b/assets/completions/bat.bash.in index f314bb25..90931f24 100644 --- a/assets/completions/bat.bash.in +++ b/assets/completions/bat.bash.in @@ -113,6 +113,13 @@ _bat() { return 0 ;; --theme) + local IFS=$'\n' + COMPREPLY=($(compgen -W "auto${IFS}auto:always${IFS}auto:system${IFS}dark${IFS}light${IFS}$("$1" --list-themes)" -- "$cur")) + __bat_escape_completions + return 0 + ;; + --theme-dark | \ + --theme-light) local IFS=$'\n' COMPREPLY=($(compgen -W "$("$1" --list-themes)" -- "$cur")) __bat_escape_completions @@ -170,6 +177,8 @@ _bat() { --map-syntax --ignored-suffix --theme + --theme-dark + --theme-light --list-themes --squeeze-blank --squeeze-limit diff --git a/assets/completions/bat.fish.in b/assets/completions/bat.fish.in index 788f71b0..e2712706 100644 --- a/assets/completions/bat.fish.in +++ b/assets/completions/bat.fish.in @@ -129,6 +129,14 @@ set -l tabs_opts ' 8\t ' +set -l special_themes ' + auto\tdefault,\ Choose\ a\ theme\ based\ on\ dark\ or\ light\ mode + auto:always\tChoose\ a\ theme\ based\ on\ dark\ or\ light\ mode + auto:system\tChoose\ a\ theme\ based\ on\ dark\ or\ light\ mode + dark\tUse\ the\ theme\ specified\ by\ --theme-dark + light\tUse\ the\ theme\ specified\ by\ --theme-light +' + # Completions: complete -c $bat -l acknowledgements -d "Print acknowledgements" -n __fish_is_first_arg @@ -203,7 +211,11 @@ complete -c $bat -l tabs -x -a "$tabs_opts" -d "Set tab width" -n __bat_no_excl_ complete -c $bat -l terminal-width -x -d "Set terminal , +, or -" -n __bat_no_excl_args -complete -c $bat -l theme -x -a "(command $bat --list-themes | command cat)" -d "Set the syntax highlighting theme" -n __bat_no_excl_args +complete -c $bat -l theme -x -a "$special_themes(command $bat --list-themes | command cat)" -d "Set the syntax highlighting theme" -n __bat_no_excl_args + +complete -c $bat -l theme-dark -x -a "(command $bat --list-themes | command cat)" -d "Set the syntax highlighting theme for dark backgrounds" -n __bat_no_excl_args + +complete -c $bat -l theme-light -x -a "(command $bat --list-themes | command cat)" -d "Set the syntax highlighting theme for light backgrounds" -n __bat_no_excl_args complete -c $bat -s V -l version -f -d "Show version information" -n __fish_is_first_arg diff --git a/assets/completions/bat.zsh.in b/assets/completions/bat.zsh.in index 7d03abb3..dfe1e1b9 100644 --- a/assets/completions/bat.zsh.in +++ b/assets/completions/bat.zsh.in @@ -26,7 +26,7 @@ _{{PROJECT_EXECUTABLE}}_main() { args=( '(-A --show-all)'{-A,--show-all}'[show non-printable characters (space, tab, newline, ..)]' --nonprintable-notation='[specify how to display non-printable characters when using --show-all]:notation:(caret unicode)' - \*{-p,--plain}'[show plain style (alias for `--style=plain`), repeat twice to disable disable automatic paging (alias for `--paging=never`)]' + \*{-p,--plain}'[show plain style (alias for `--style=plain`), repeat twice to disable automatic paging (alias for `--paging=never`)]' '(-l --language)'{-l+,--language=}'[set the language for syntax highlighting]:language:->languages' \*{-H+,--highlight-line=}'[highlight specified block of lines]:start\:end' \*--file-name='[specify the name to display for a file]:name:_files' @@ -42,7 +42,9 @@ _{{PROJECT_EXECUTABLE}}_main() { --decorations='[specify when to show the decorations]:when:(auto never always)' --paging='[specify when to use the pager]:when:(auto never always)' '(-m --map-syntax)'{-m+,--map-syntax=}'[map a glob pattern to an existing syntax name]: :->syntax-maps' - '(--theme)'--theme='[set the color theme for syntax highlighting]:theme:->themes' + '(--theme)'--theme='[set the color theme for syntax highlighting]:theme:->theme_preferences' + '(--theme-dark)'--theme-dark='[set the color theme for syntax highlighting for dark backgrounds]:theme:->themes' + '(--theme-light)'--theme-light='[set the color theme for syntax highlighting for light backgrounds]:theme:->themes' '(: --list-themes --list-languages -L)'--list-themes'[show all supported highlighting themes]' --style='[comma-separated list of style elements to display]: : _values "style [default]" default auto full plain changes header header-filename header-filesize grid rule numbers snip' @@ -82,7 +84,13 @@ _{{PROJECT_EXECUTABLE}}_main() { themes) local -a themes expl - themes=( ${(f)"$(_call_program themes {{PROJECT_EXECUTABLE}} --list-themes)"} ) + themes=(${(f)"$(_call_program themes {{PROJECT_EXECUTABLE}} --list-themes)"} ) + + _wanted themes expl 'theme' compadd -a themes && ret=0 + ;; + theme_preferences) + local -a themes expl + themes=(auto dark light auto:always auto:system ${(f)"$(_call_program themes {{PROJECT_EXECUTABLE}} --list-themes)"} ) _wanted themes expl 'theme' compadd -a themes && ret=0 ;; diff --git a/assets/manual/bat.1.in b/assets/manual/bat.1.in index 2bc0a3a5..ccc70629 100644 --- a/assets/manual/bat.1.in +++ b/assets/manual/bat.1.in @@ -152,9 +152,38 @@ will use JSON syntax, and ignore '.dev' .HP \fB\-\-theme\fR .IP -Set the theme for syntax highlighting. Use '\-\-list\-themes' to see all available themes. -To set a default theme, add the '\-\-theme="..."' option to the configuration file or -export the BAT_THEME environment variable (e.g.: export BAT_THEME="..."). +Set the theme for syntax highlighting. Use \fB\-\-list\-themes\fP to see all available themes. +To set a default theme, add the \fB\-\-theme="..."\fP option to the configuration file or +export the \fBBAT_THEME\fP environment variable (e.g.: \fBexport BAT_THEME="..."\fP). + +Special values: +.RS +.IP "auto (\fIdefault\fR)" +Picks a dark or light theme depending on the terminal's colors. +Use \fB-\-theme\-light\fR and \fB-\-theme\-dark\fR to customize the selected theme. +.IP "auto:always" +Variation of \fBauto\fR where where the terminal's colors are detected even when the output is redirected. +.IP "auto:system (macOS only)" +Variation of \fBauto\fR where the color scheme is detected from the system-wide preference instead. +.IP "dark" +Use the dark theme specified by \fB-\-theme-dark\fR. +.IP "light" +Use the light theme specified by \fB-\-theme-light\fR. +.RE +.HP +\fB\-\-theme\-dark\fR +.IP +Sets the theme name for syntax highlighting used when the terminal uses a dark background. +To set a default theme, add the \fB\-\-theme-dark="..."\fP option to the configuration file or +export the \fBBAT_THEME_DARK\fP environment variable (e.g. \fBexport BAT_THEME_DARK="..."\fP). +This option only has an effect when \fB\-\-theme\fP option is set to \fBauto\fR or \fBdark\fR. +.HP +\fB\-\-theme\-light\fR +.IP +Sets the theme name for syntax highlighting used when the terminal uses a dark background. +To set a default theme, add the \fB\-\-theme-dark="..."\fP option to the configuration file or +export the \fBBAT_THEME_LIGHT\fP environment variable (e.g. \fBexport BAT_THEME_LIGHT="..."\fP). +This option only has an effect when \fB\-\-theme\fP option is set to \fBauto\fR or \fBlight\fR. .HP \fB\-\-list\-themes\fR .IP @@ -307,7 +336,7 @@ To use the preprocessor, call: \fB{{PROJECT_EXECUTABLE}} --lessopen\fR -Alternatively, the preprocessor may be enabled by default by adding the '\-\-lessopen' option to the configuration file. +Alternatively, the preprocessor may be enabled by default by adding the '\-\-lessopen' option to the configuration file. To temporarily disable the preprocessor if it is enabled by default, call: @@ -323,7 +352,7 @@ Enable the $LESSOPEN preprocessor. .IP Disable the $LESSOPEN preprocessor if enabled (overrides --lessopen) .PP -For more information, see the "INPUT PREPROCESSOR" section of less(1). +For more information, see the "INPUT PREPROCESSOR" section of less(1). .SH "MORE INFORMATION" diff --git a/assets/patches/1337.tmTheme.patch b/assets/patches/1337.tmTheme.patch new file mode 100644 index 00000000..b927a74f --- /dev/null +++ b/assets/patches/1337.tmTheme.patch @@ -0,0 +1,22 @@ +diff --git themes/1337-Scheme/1337.tmTheme themes/1337-Scheme/1337.tmTheme +index fdff5bf..8cfc888 100644 +--- themes/1337-Scheme/1337.tmTheme ++++ themes/1337-Scheme/1337.tmTheme +@@ -280,7 +280,7 @@ SOFTWARE. + name + PHP Namespaces + scope +- support.other.namespace, entity.name.type.namespace ++ support.other.namespace, entity.name.type.namespace, entity.name + settings + + foreground +@@ -561,7 +561,7 @@ SOFTWARE. + name + diff.header + scope +- meta.diff, meta.diff.header ++ meta.diff, meta.diff.header, markup.heading + settings + + foreground diff --git a/assets/patches/Markdown.sublime-syntax.patch b/assets/patches/Markdown.sublime-syntax.patch index 600b6b11..a295334c 100644 --- a/assets/patches/Markdown.sublime-syntax.patch +++ b/assets/patches/Markdown.sublime-syntax.patch @@ -1,5 +1,5 @@ diff --git syntaxes/01_Packages/Markdown/Markdown.sublime-syntax syntaxes/01_Packages/Markdown/Markdown.sublime-syntax -index 19dc685d..44440c7f 100644 +index 19dc685d..3a45ea05 100644 --- syntaxes/01_Packages/Markdown/Markdown.sublime-syntax +++ syntaxes/01_Packages/Markdown/Markdown.sublime-syntax @@ -24,7 +24,6 @@ variables: @@ -166,7 +166,29 @@ index 19dc685d..44440c7f 100644 - match: ^\s*$\n? scope: invalid.illegal.non-terminated.bold-italic.markdown pop: true -@@ -1152,7 +1110,7 @@ contexts: +@@ -1073,6 +1031,21 @@ contexts: + escape: '{{code_fence_escape}}' + escape_captures: + 0: meta.code-fence.definition.end.python.markdown-gfm ++ 1: punctuation.definition.raw.code-fence.end.markdown ++ - match: |- ++ (?x) ++ {{fenced_code_block_start}} ++ ((?i:puppet)) ++ {{fenced_code_block_trailing_infostring_characters}} ++ captures: ++ 0: meta.code-fence.definition.begin.puppet.markdown-gfm ++ 2: punctuation.definition.raw.code-fence.begin.markdown ++ 5: constant.other.language-name.markdown ++ embed: scope:source.puppet ++ embed_scope: markup.raw.code-fence.puppet.markdown-gfm ++ escape: '{{code_fence_escape}}' ++ escape_captures: ++ 0: meta.code-fence.definition.end.puppet.markdown-gfm + 1: punctuation.definition.raw.code-fence.end.markdown + - match: |- + (?x) +@@ -1152,7 +1125,7 @@ contexts: - match: |- (?x) {{fenced_code_block_start}} diff --git a/assets/patches/Monokai-Extended.tmTheme.patch b/assets/patches/Monokai-Extended.tmTheme.patch index 106b584d..ece5d49c 100644 --- a/assets/patches/Monokai-Extended.tmTheme.patch +++ b/assets/patches/Monokai-Extended.tmTheme.patch @@ -21,11 +21,26 @@ index 9c2aa3e..180cbbf 100644 Invalid scope - invalid -+ invalid, markup.error ++ invalid, meta.annotation.error-line settings background -@@ -1042,7 +1042,7 @@ +@@ -1038,11 +1038,22 @@ + #f8f8f0 + + ++ ++ name ++ Error ++ scope ++ markup.error ++ settings ++ ++ foreground ++ #dd2020 ++ ++ + name Invalid deprecated scope diff --git a/assets/patches/OneHalfDark.tmTheme.patch b/assets/patches/OneHalfDark.tmTheme.patch new file mode 100644 index 00000000..1ac3e5e8 --- /dev/null +++ b/assets/patches/OneHalfDark.tmTheme.patch @@ -0,0 +1,47 @@ +diff --git themes/onehalf/sublimetext/OneHalfDark.tmTheme themes/onehalf/sublimetext/OneHalfDark.tmTheme +index b16050c..b021071 100644 +--- themes/onehalf/sublimetext/OneHalfDark.tmTheme ++++ themes/onehalf/sublimetext/OneHalfDark.tmTheme +@@ -28,7 +28,7 @@ + + + name +- OneHalfLight ++ OneHalfDark + semanticClass + theme.dark.one_half_dark + uuid +@@ -155,7 +155,7 @@ + name + Classes + scope +- support.class, entity.name.class, entity.name.type.class ++ support.class, entity.name.class, entity.name.type.class, entity.name + settings + + foreground +@@ -188,7 +188,7 @@ + name + Storage + scope +- storage ++ storage, meta.mapping.key string + settings + + foreground +@@ -309,7 +309,7 @@ + name + Markdown: Headings + scope +- markup.heading punctuation.definition.heading, entity.name.section ++ markup.heading punctuation.definition.heading, entity.name.section, markup.heading - text.html.markdown + settings + + fontStyle +@@ -660,4 +660,4 @@ + + + +- +\ No newline at end of file ++ diff --git a/assets/patches/TwoDark.tmTheme.patch b/assets/patches/TwoDark.tmTheme.patch index 05f1fc69..b6570fbc 100644 --- a/assets/patches/TwoDark.tmTheme.patch +++ b/assets/patches/TwoDark.tmTheme.patch @@ -2,6 +2,24 @@ diff --git themes/TwoDark/TwoDark.tmTheme themes/TwoDark/TwoDark.tmTheme index 87fd358..56376d3 100644 --- themes/TwoDark/TwoDark.tmTheme +++ themes/TwoDark/TwoDark.tmTheme +@@ -125,7 +125,7 @@ + name + Classes + scope +- support.class, entity.name.class, entity.name.type.class ++ support.class, entity.name.class, entity.name.type.class, entity.name + settings + + foreground +@@ -290,7 +290,7 @@ + name + Headings + scope +- markup.heading punctuation.definition.heading, entity.name.section ++ markup.heading punctuation.definition.heading, entity.name.section, markup.heading - text.html.markdown + settings + + fontStyle @@ -533,7 +533,7 @@ name Json key diff --git a/assets/syntaxes.bin b/assets/syntaxes.bin index 7a5cd310..21043c5e 100644 Binary files a/assets/syntaxes.bin and b/assets/syntaxes.bin differ diff --git a/assets/syntaxes/02_Extra/Apache b/assets/syntaxes/02_Extra/Apache index 163bc03a..cf6cefc5 160000 --- a/assets/syntaxes/02_Extra/Apache +++ b/assets/syntaxes/02_Extra/Apache @@ -1 +1 @@ -Subproject commit 163bc03ae8998a237dfb4be353d0aea198ea17f5 +Subproject commit cf6cefc51ebb46b1b54906433edbae0fe9c71cad diff --git a/assets/syntaxes/02_Extra/Assembly (ARM) b/assets/syntaxes/02_Extra/Assembly_(ARM) similarity index 100% rename from assets/syntaxes/02_Extra/Assembly (ARM) rename to assets/syntaxes/02_Extra/Assembly_(ARM) diff --git a/assets/syntaxes/02_Extra/CSV.sublime-syntax b/assets/syntaxes/02_Extra/CSV/CSV-comma.sublime-syntax similarity index 71% rename from assets/syntaxes/02_Extra/CSV.sublime-syntax rename to assets/syntaxes/02_Extra/CSV/CSV-comma.sublime-syntax index cca7cd2c..f23751ac 100644 --- a/assets/syntaxes/02_Extra/CSV.sublime-syntax +++ b/assets/syntaxes/02_Extra/CSV/CSV-comma.sublime-syntax @@ -2,20 +2,21 @@ --- # See http://www.sublimetext.com/docs/3/syntax.html name: Comma Separated Values -file_extensions: - - csv - - tsv -scope: text.csv +scope: text.csv.comma variables: - field_separator: (?:[,;\t]) + field_separator: (?:,) record_separator: (?:$\n?) contexts: - prototype: - - match: (?={{record_separator}}) - pop: true + main: + - match: '^' + push: fields + fields: + - include: record_separator - match: '' push: + - field_or_record_separator + - field5 - field_or_record_separator - field4 - field_or_record_separator @@ -24,16 +25,20 @@ contexts: - field2 - field_or_record_separator - field1 - main: - - meta_include_prototype: false - - match: '^' - set: fields - field_or_record_separator: + record_separator_pop: + - match: (?={{record_separator}}) + pop: true + + record_separator: - meta_include_prototype: false - match: '{{record_separator}}' scope: punctuation.terminator.record.csv pop: true + + field_or_record_separator: + - meta_include_prototype: false + - include: record_separator_pop - match: '{{field_separator}}' scope: punctuation.separator.sequence.csv pop: true @@ -41,24 +46,16 @@ contexts: field_contents: - match: '"' scope: punctuation.definition.string.begin.csv - push: double_quoted_string + push: scope:text.csv#double_quoted_string - - match: (?={{field_separator}}|{{record_separator}}) - pop: true - - double_quoted_string: - - meta_include_prototype: false - - meta_scope: string.quoted.double.csv - - match: '""' - scope: constant.character.escape.csv - - match: '"' - scope: punctuation.definition.string.end.csv + - include: record_separator_pop + - match: (?={{field_separator}}) pop: true field1: - match: '' set: - - meta_content_scope: meta.field-1.csv support.type + - meta_content_scope: meta.field-1.csv variable.parameter - include: field_contents field2: - match: '' @@ -75,4 +72,8 @@ contexts: set: - meta_content_scope: meta.field-4.csv keyword.operator - include: field_contents - + field5: + - match: '' + set: + - meta_content_scope: meta.field-5.csv string.unquoted + - include: field_contents diff --git a/assets/syntaxes/02_Extra/CSV/CSV-pipe.sublime-syntax b/assets/syntaxes/02_Extra/CSV/CSV-pipe.sublime-syntax new file mode 100644 index 00000000..52103fde --- /dev/null +++ b/assets/syntaxes/02_Extra/CSV/CSV-pipe.sublime-syntax @@ -0,0 +1,80 @@ +%YAML 1.2 +--- +# See http://www.sublimetext.com/docs/3/syntax.html +name: Pipe Separated Values +scope: text.csv.pipe +variables: + field_separator: (?:\|) + record_separator: (?:$\n?) + +contexts: + main: + - match: '^' + push: fields + + fields: + - include: record_separator + - match: '' + push: + - field_or_record_separator + - field5 + - field_or_record_separator + - field4 + - field_or_record_separator + - field3 + - field_or_record_separator + - field2 + - field_or_record_separator + - field1 + + record_separator_pop: + - match: (?={{record_separator}}) + pop: true + + record_separator: + - meta_include_prototype: false + - match: '{{record_separator}}' + scope: punctuation.terminator.record.csv + pop: true + + field_or_record_separator: + - meta_include_prototype: false + - include: record_separator_pop + - match: '{{field_separator}}' + scope: punctuation.separator.sequence.csv + pop: true + + field_contents: + - match: '"' + scope: punctuation.definition.string.begin.csv + push: scope:text.csv#double_quoted_string + + - include: record_separator_pop + - match: (?={{field_separator}}) + pop: true + + field1: + - match: '' + set: + - meta_content_scope: meta.field-1.csv variable.parameter + - include: field_contents + field2: + - match: '' + set: + - meta_content_scope: meta.field-2.csv support.function + - include: field_contents + field3: + - match: '' + set: + - meta_content_scope: meta.field-3.csv constant.numeric + - include: field_contents + field4: + - match: '' + set: + - meta_content_scope: meta.field-4.csv keyword.operator + - include: field_contents + field5: + - match: '' + set: + - meta_content_scope: meta.field-5.csv string.unquoted + - include: field_contents diff --git a/assets/syntaxes/02_Extra/CSV/CSV-semi-colon.sublime-syntax b/assets/syntaxes/02_Extra/CSV/CSV-semi-colon.sublime-syntax new file mode 100644 index 00000000..e0547ce0 --- /dev/null +++ b/assets/syntaxes/02_Extra/CSV/CSV-semi-colon.sublime-syntax @@ -0,0 +1,79 @@ +%YAML 1.2 +--- +# See http://www.sublimetext.com/docs/3/syntax.html +name: Semi-Colon Separated Values +scope: text.csv.semi-colon +variables: + field_separator: (?:;) + record_separator: (?:$\n?) +contexts: + main: + - match: '^' + push: fields + + fields: + - include: record_separator + - match: '' + push: + - field_or_record_separator + - field5 + - field_or_record_separator + - field4 + - field_or_record_separator + - field3 + - field_or_record_separator + - field2 + - field_or_record_separator + - field1 + + record_separator_pop: + - match: (?={{record_separator}}) + pop: true + + record_separator: + - meta_include_prototype: false + - match: '{{record_separator}}' + scope: punctuation.terminator.record.csv + pop: true + + field_or_record_separator: + - meta_include_prototype: false + - include: record_separator_pop + - match: '{{field_separator}}' + scope: punctuation.separator.sequence.csv + pop: true + + field_contents: + - match: '"' + scope: punctuation.definition.string.begin.csv + push: scope:text.csv#double_quoted_string + + - include: record_separator_pop + - match: (?={{field_separator}}) + pop: true + + field1: + - match: '' + set: + - meta_content_scope: meta.field-1.csv variable.parameter + - include: field_contents + field2: + - match: '' + set: + - meta_content_scope: meta.field-2.csv support.function + - include: field_contents + field3: + - match: '' + set: + - meta_content_scope: meta.field-3.csv constant.numeric + - include: field_contents + field4: + - match: '' + set: + - meta_content_scope: meta.field-4.csv keyword.operator + - include: field_contents + field5: + - match: '' + set: + - meta_content_scope: meta.field-5.csv string.unquoted + - include: field_contents diff --git a/assets/syntaxes/02_Extra/CSV/CSV.sublime-syntax b/assets/syntaxes/02_Extra/CSV/CSV.sublime-syntax new file mode 100644 index 00000000..8ce83acb --- /dev/null +++ b/assets/syntaxes/02_Extra/CSV/CSV.sublime-syntax @@ -0,0 +1,113 @@ +%YAML 1.2 +--- +# See http://www.sublimetext.com/docs/3/syntax.html +name: Separated Values +file_extensions: + - csv +scope: text.csv +variables: + field_separator_chars: ',;\t|' + field_separator: (?:[{{field_separator_chars}}]) + record_separator: (?:$\n?) +contexts: + main: + - meta_include_prototype: false + - include: three_field_separators + - include: single_separator_type_on_line + - match: '^' + push: unknown-separated-main + + three_field_separators: + - match: ^(?=(?:[^,]*,){3}) + set: scope:text.csv.comma + - match: ^(?=(?:[^;]*;){3}) + set: scope:text.csv.semi-colon + - match: ^(?=(?:[^\t]*\t){3}) + set: scope:text.csv.tab + - match: ^(?=(?:[^|]*\|){3}) + set: scope:text.csv.pipe + + single_separator_type_on_line: + - match: ^(?=[^{{field_separator_chars}}]*,[^;\t|]*$) + set: scope:text.csv.comma + - match: ^(?=[^{{field_separator_chars}}]*;[^,\t|]*$) + set: scope:text.csv.semi-colon + - match: ^(?=[^{{field_separator_chars}}]*\t[^,;|]*$) + set: scope:text.csv.tab + - match: ^(?=[^{{field_separator_chars}}]*\|[^,;\t]*$) + set: scope:text.csv.pipe + + unknown-separated-main: + - include: record_separator + - match: '' + push: + - field_or_record_separator + - field5 + - field_or_record_separator + - field4 + - field_or_record_separator + - field3 + - field_or_record_separator + - field2 + - field_or_record_separator + - field1 + + record_separator_pop: + - match: (?={{record_separator}}) + pop: true + + record_separator: + - meta_include_prototype: false + - match: '{{record_separator}}' + scope: punctuation.terminator.record.csv + + field_or_record_separator: + - meta_include_prototype: false + - include: record_separator_pop + - match: '{{field_separator}}' + scope: punctuation.separator.sequence.csv + pop: true + + field_contents: + - match: '"' + scope: punctuation.definition.string.begin.csv + push: double_quoted_string + + - include: record_separator_pop + - match: (?={{field_separator}}) + pop: true + + double_quoted_string: + - meta_include_prototype: false + - meta_scope: string.quoted.double.csv + - match: '""' + scope: constant.character.escape.csv + - match: '"' + scope: punctuation.definition.string.end.csv + pop: true + + field1: + - match: '' + set: + - meta_content_scope: meta.field-1.csv variable.parameter + - include: field_contents + field2: + - match: '' + set: + - meta_content_scope: meta.field-2.csv support.function + - include: field_contents + field3: + - match: '' + set: + - meta_content_scope: meta.field-3.csv constant.numeric + - include: field_contents + field4: + - match: '' + set: + - meta_content_scope: meta.field-4.csv keyword.operator + - include: field_contents + field5: + - match: '' + set: + - meta_content_scope: meta.field-5.csv string.unquoted + - include: field_contents diff --git a/assets/syntaxes/02_Extra/CSV/TSV.sublime-syntax b/assets/syntaxes/02_Extra/CSV/TSV.sublime-syntax new file mode 100644 index 00000000..fdca0c31 --- /dev/null +++ b/assets/syntaxes/02_Extra/CSV/TSV.sublime-syntax @@ -0,0 +1,83 @@ +%YAML 1.2 +--- +# See http://www.sublimetext.com/docs/3/syntax.html +name: Tab Separated Values +scope: text.csv.tab +file_extensions: + - tsv + +variables: + field_separator: (?:\t) + record_separator: (?:$\n?) + +contexts: + main: + - match: '^' + push: fields + + fields: + - include: record_separator + - match: '' + push: + - field_or_record_separator + - field5 + - field_or_record_separator + - field4 + - field_or_record_separator + - field3 + - field_or_record_separator + - field2 + - field_or_record_separator + - field1 + + record_separator_pop: + - match: (?={{record_separator}}) + pop: true + + record_separator: + - meta_include_prototype: false + - match: '{{record_separator}}' + scope: punctuation.terminator.record.csv + pop: true + + field_or_record_separator: + - meta_include_prototype: false + - include: record_separator_pop + - match: '{{field_separator}}' + scope: punctuation.separator.sequence.csv + pop: true + + field_contents: + - match: '"' + scope: punctuation.definition.string.begin.csv + push: scope:text.csv#double_quoted_string + + - include: record_separator_pop + - match: (?={{field_separator}}) + pop: true + + field1: + - match: '' + set: + - meta_content_scope: meta.field-1.csv variable.parameter + - include: field_contents + field2: + - match: '' + set: + - meta_content_scope: meta.field-2.csv support.function + - include: field_contents + field3: + - match: '' + set: + - meta_content_scope: meta.field-3.csv constant.numeric + - include: field_contents + field4: + - match: '' + set: + - meta_content_scope: meta.field-4.csv keyword.operator + - include: field_contents + field5: + - match: '' + set: + - meta_content_scope: meta.field-5.csv string.unquoted + - include: field_contents diff --git a/assets/syntaxes/02_Extra/Docker b/assets/syntaxes/02_Extra/Docker index 0f6b7bc8..c001fb28 160000 --- a/assets/syntaxes/02_Extra/Docker +++ b/assets/syntaxes/02_Extra/Docker @@ -1 +1 @@ -Subproject commit 0f6b7bc87acf684f7b0790fd480731ffb4615b87 +Subproject commit c001fb280561d7c16f0f2837d76af493cf6c3bf8 diff --git a/assets/syntaxes/02_Extra/GDScript-sublime b/assets/syntaxes/02_Extra/GDScript-sublime new file mode 160000 index 00000000..96f5dcf2 --- /dev/null +++ b/assets/syntaxes/02_Extra/GDScript-sublime @@ -0,0 +1 @@ +Subproject commit 96f5dcf29728aa987123321e2544330eed991a3e diff --git a/assets/syntaxes/02_Extra/HTML (Twig) b/assets/syntaxes/02_Extra/HTML_(Twig) similarity index 100% rename from assets/syntaxes/02_Extra/HTML (Twig) rename to assets/syntaxes/02_Extra/HTML_(Twig) diff --git a/assets/syntaxes/02_Extra/Idris2 b/assets/syntaxes/02_Extra/Idris2 new file mode 160000 index 00000000..7c1bf44c --- /dev/null +++ b/assets/syntaxes/02_Extra/Idris2 @@ -0,0 +1 @@ +Subproject commit 7c1bf44c4f9092b7b1e274b1332cf32a089b2b99 diff --git a/assets/syntaxes/02_Extra/JavaScript (Babel) b/assets/syntaxes/02_Extra/JavaScript_(Babel) similarity index 100% rename from assets/syntaxes/02_Extra/JavaScript (Babel) rename to assets/syntaxes/02_Extra/JavaScript_(Babel) diff --git a/assets/syntaxes/02_Extra/Manpage.sublime-syntax b/assets/syntaxes/02_Extra/Manpage.sublime-syntax index 2475da8a..0779ce04 100644 --- a/assets/syntaxes/02_Extra/Manpage.sublime-syntax +++ b/assets/syntaxes/02_Extra/Manpage.sublime-syntax @@ -85,6 +85,9 @@ contexts: options: # command-line options like --option=value, --some-flag, or -x + - match: '^[ ]{7}(-)(?=\s)' + captures: + 1: entity.name.command-line-option.man - match: '^[ ]{7}(?=-|\+)' push: expect-command-line-option - match: '(?:[^a-zA-Z0-9_-]|^|\s){{command_line_option}}' diff --git a/assets/syntaxes/02_Extra/Nix b/assets/syntaxes/02_Extra/Nix index 9032bd61..48c497c7 160000 --- a/assets/syntaxes/02_Extra/Nix +++ b/assets/syntaxes/02_Extra/Nix @@ -1 +1 @@ -Subproject commit 9032bd613746b9c135223fd6f26a5fa555f18946 +Subproject commit 48c497c709c66a2fb118c534a8de8e4e1c4c401d diff --git a/assets/syntaxes/02_Extra/Org mode b/assets/syntaxes/02_Extra/Org mode deleted file mode 160000 index 4976d8f8..00000000 --- a/assets/syntaxes/02_Extra/Org mode +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 4976d8f84eeecd94df7da872bf404c125df04c73 diff --git a/assets/syntaxes/02_Extra/Org_mode b/assets/syntaxes/02_Extra/Org_mode new file mode 160000 index 00000000..bb6e5d84 --- /dev/null +++ b/assets/syntaxes/02_Extra/Org_mode @@ -0,0 +1 @@ +Subproject commit bb6e5d848151135ab8f87bdcb997437b2308718a diff --git a/assets/syntaxes/02_Extra/PowerShell b/assets/syntaxes/02_Extra/PowerShell index c0372a1d..a08b55bf 160000 --- a/assets/syntaxes/02_Extra/PowerShell +++ b/assets/syntaxes/02_Extra/PowerShell @@ -1 +1 @@ -Subproject commit c0372a1d2df136ca6b3d1a9f7b85031dedf117f9 +Subproject commit a08b55bf1146c210f58e844be53c2aa78fd5e610 diff --git a/assets/syntaxes/02_Extra/TOML b/assets/syntaxes/02_Extra/TOML index fd0bf3e5..f5a57e8b 160000 --- a/assets/syntaxes/02_Extra/TOML +++ b/assets/syntaxes/02_Extra/TOML @@ -1 +1 @@ -Subproject commit fd0bf3e5d6c9e6397c0dc9639a0514d9bf55b800 +Subproject commit f5a57e8bff694a4e6c52a491dae579aabc7427cf diff --git a/assets/syntaxes/02_Extra/Zig b/assets/syntaxes/02_Extra/Zig index 1a4a3844..8a4a3fe4 160000 --- a/assets/syntaxes/02_Extra/Zig +++ b/assets/syntaxes/02_Extra/Zig @@ -1 +1 @@ -Subproject commit 1a4a38445fec495817625bafbeb01e79c44abcba +Subproject commit 8a4a3fe4a051f85c4752b82f586d395cab843c06 diff --git a/assets/syntaxes/02_Extra/apt-source-list.sublime-syntax b/assets/syntaxes/02_Extra/apt-source-list.sublime-syntax new file mode 100644 index 00000000..d5ede5b5 --- /dev/null +++ b/assets/syntaxes/02_Extra/apt-source-list.sublime-syntax @@ -0,0 +1,42 @@ +%YAML 1.2 +--- +# See http://www.sublimetext.com/docs/syntax.html +name: debsources +file_extensions: + - sources.list +scope: text.apt-source-list +contexts: + main: + - include: comments + - match: ^[\w-]+ + scope: constant.language.apt-source-list + - match: \w+://\S+ + scope: markup.underline.link.apt-source-list + push: distribution + - match: \bmain\b + scope: support.class.apt-source-list + - match: \buniverse\b + scope: support.constant.apt-source-list + - match: \brestricted\b + scope: storage.modifier.apt-source-list + - match: \bmultiverse\b + scope: keyword.other.apt-source-list + - match: '[\w-]+' + scope: constant.other.apt-source-list + + comments: + - match: '#' + scope: punctuation.definition.comment.apt-source-list + push: line_comment + + line_comment: + - meta_scope: comment.line.apt-source-list + - match: $ + pop: true + + distribution: + - match: \S+ + scope: support.type.apt-source-list + pop: 1 + - match: $ + pop: 1 diff --git a/assets/syntaxes/02_Extra/cmd-help b/assets/syntaxes/02_Extra/cmd-help index 209559b7..c71ba410 160000 --- a/assets/syntaxes/02_Extra/cmd-help +++ b/assets/syntaxes/02_Extra/cmd-help @@ -1 +1 @@ -Subproject commit 209559b72f7e8848c988828088231b3a4d8b6838 +Subproject commit c71ba410bdfcc8f627df3219f14e3f2be4fe68ba diff --git a/assets/syntaxes/02_Extra/log.sublime-syntax b/assets/syntaxes/02_Extra/log.sublime-syntax index a68c7e83..0ce01f10 100644 --- a/assets/syntaxes/02_Extra/log.sublime-syntax +++ b/assets/syntaxes/02_Extra/log.sublime-syntax @@ -38,21 +38,21 @@ contexts: scope: markup.underline.link.scheme.log push: url-host log_level_lines: - - match: ^(?=.*{{error}}) + - match: (?=.*{{error}}) push: - - error_line + - error_line_meta - main_pop_at_eol - - match: ^(?=.*{{warning}}) + - match: (?=.*{{warning}}) push: - - warning_line + - warning_line_meta - main_pop_at_eol - - match: ^(?=.*{{info}}) + - match: (?=.*{{info}}) push: - - info_line + - info_line_meta - main_pop_at_eol - - match: ^(?=.*{{debug}}) + - match: (?=.*{{debug}}) push: - - debug_line + - debug_line_meta - main_pop_at_eol log_levels: - match: '{{error}}' @@ -63,16 +63,16 @@ contexts: scope: markup.info.log - match: '{{debug}}' scope: markup.info.log - error_line: + error_line_meta: - meta_scope: meta.annotation.error-line.log - include: immediately_pop - warning_line: + warning_line_meta: - meta_scope: meta.annotation.warning-line.log - include: immediately_pop - info_line: + info_line_meta: - meta_scope: meta.annotation.info-line.log - include: immediately_pop - debug_line: + debug_line_meta: - meta_scope: meta.annotation.debug-line.log - include: immediately_pop immediately_pop: diff --git a/assets/syntaxes/02_Extra/sublime-odin b/assets/syntaxes/02_Extra/sublime-odin new file mode 160000 index 00000000..5d6a0ed4 --- /dev/null +++ b/assets/syntaxes/02_Extra/sublime-odin @@ -0,0 +1 @@ +Subproject commit 5d6a0ed41e41ec3709ec74f40686dc3761d6596e diff --git a/assets/syntaxes/02_Extra/syntax_test_man.man b/assets/syntaxes/02_Extra/syntax_test_man.man index 01ce1c55..5dfee5be 100644 --- a/assets/syntaxes/02_Extra/syntax_test_man.man +++ b/assets/syntaxes/02_Extra/syntax_test_man.man @@ -131,6 +131,12 @@ OPTIONS # ^^ - variable output NUM (default 3) lines of copied context + - This is not really a switch, but indicates that standard input +# ^ entity.name.command-line-option.man +# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - entity - variable + is coming from a file or a pipe and not interactively from the + command line. + EXAMPLE #include # ^^^^^^^^ source.c meta.preprocessor.include keyword.control.import.include diff --git a/assets/syntaxes/02_Extra/syslog.sublime-syntax b/assets/syntaxes/02_Extra/syslog.sublime-syntax index 1efad346..01ed58db 100644 --- a/assets/syntaxes/02_Extra/syslog.sublime-syntax +++ b/assets/syntaxes/02_Extra/syslog.sublime-syntax @@ -8,10 +8,10 @@ scope: text.log.syslog contexts: main: - match: ^(\w+\s+\d+)\s+(\d{2}:\d{2}:\d{2}) - scope: meta.datetime.syslog constant.numeric.syslog + scope: meta.datetime.syslog captures: - 1: meta.date.syslog - 2: meta.time.syslog + 1: meta.date.syslog constant.numeric.syslog + 2: meta.time.syslog constant.numeric.syslog push: loghost - match: ^ push: text @@ -31,22 +31,24 @@ contexts: structured-data: - match: '\[' scope: punctuation.section.mapping.begin.syslog - push: - - match: \] - scope: punctuation.section.mapping.end.syslog - pop: true - - match: \w+ - scope: variable.parameter.syslog - - match: = - scope: keyword.operator.assignment.syslog - push: - - match: '[^\s\]]+' - scope: constant.other.syslog - pop: true - - match: (?=\]) - pop: true + push: structured-data-contents - match: (?=\S) set: text + structured-data-contents: + - match: \] + scope: punctuation.section.mapping.end.syslog + pop: true + - match: \w+ + scope: variable.parameter.syslog + - match: = + scope: keyword.operator.assignment.syslog + push: structured-data-assignment + structured-data-assignment: + - match: '[^\s\]]+' + scope: constant.other.syslog + pop: true + - match: (?=\]) + pop: true text: - match: $ pop: true diff --git a/assets/themes.bin b/assets/themes.bin index c9dfcde1..b42fa8f3 100644 Binary files a/assets/themes.bin and b/assets/themes.bin differ diff --git a/assets/themes/Nord-sublime b/assets/themes/Nord-sublime index 0d655b23..bf92a9e4 160000 --- a/assets/themes/Nord-sublime +++ b/assets/themes/Nord-sublime @@ -1 +1 @@ -Subproject commit 0d655b23d6b300e691676d9b90a68d92b267f7ec +Subproject commit bf92a9e4457dc2f97efebc59bbeac95933ec6515 diff --git a/assets/themes/ansi.tmTheme b/assets/themes/ansi.tmTheme index 957f42bb..f103b418 100644 --- a/assets/themes/ansi.tmTheme +++ b/assets/themes/ansi.tmTheme @@ -69,7 +69,7 @@ name Labels scope - entity.name.label + entity.name.label, variable.parameter settings foreground @@ -80,7 +80,7 @@ name Classes scope - support.class, entity.name.class, entity.name.type.class + support.class, entity.name.class, entity.name.type.class, entity.name settings foreground @@ -234,7 +234,7 @@ name Headings scope - markup.heading punctuation.definition.heading, entity.name.section + markup.heading punctuation.definition.heading, entity.name.section, markup.heading - text.html.markdown settings fontStyle diff --git a/assets/themes/base16-256.tmTheme b/assets/themes/base16-256.tmTheme index a4547e56..b64b444e 100644 --- a/assets/themes/base16-256.tmTheme +++ b/assets/themes/base16-256.tmTheme @@ -257,7 +257,7 @@ name Tags scope - entity.name.tag + entity.name.tag, entity.name settings foreground @@ -312,7 +312,7 @@ name Headings scope - markup.heading punctuation.definition.heading, entity.name.section + markup.heading punctuation.definition.heading, entity.name.section, markup.heading - text.html.markdown settings fontStyle diff --git a/assets/themes/base16.tmTheme b/assets/themes/base16.tmTheme index 7b030068..b49f8117 100644 --- a/assets/themes/base16.tmTheme +++ b/assets/themes/base16.tmTheme @@ -256,7 +256,7 @@ name Tags scope - entity.name.tag + entity.name.tag, entity.name settings foreground @@ -311,7 +311,7 @@ name Headings scope - markup.heading punctuation.definition.heading, entity.name.section + markup.heading punctuation.definition.heading, entity.name.section, markup.heading - text.html.markdown settings fontStyle diff --git a/assets/themes/sublime-snazzy b/assets/themes/sublime-snazzy index 70343201..48f43a73 160000 --- a/assets/themes/sublime-snazzy +++ b/assets/themes/sublime-snazzy @@ -1 +1 @@ -Subproject commit 70343201f1d7539adbba3c79e2fe81c2559a0431 +Subproject commit 48f43a735037195021fa69d99c1180bf12f38f78 diff --git a/assets/themes/zenburn b/assets/themes/zenburn index 86d4ee7a..9c588ebc 160000 --- a/assets/themes/zenburn +++ b/assets/themes/zenburn @@ -1 +1 @@ -Subproject commit 86d4ee7a1f884851a1d21d66249687f527fced32 +Subproject commit 9c588ebc11c3e6487b081bd54528af08baa8a09a diff --git a/build/application.rs b/build/application.rs index 459aa5b1..addbae0e 100644 --- a/build/application.rs +++ b/build/application.rs @@ -63,5 +63,22 @@ pub fn gen_man_and_comp() -> anyhow::Result<()> { out_dir.join("assets/completions/bat.zsh"), )?; + println!( + "cargo:rustc-env=BAT_GENERATED_COMPLETION_BASH={}", + out_dir.join("assets/completions/bat.bash").display() + ); + println!( + "cargo:rustc-env=BAT_GENERATED_COMPLETION_FISH={}", + out_dir.join("assets/completions/bat.fish").display() + ); + println!( + "cargo:rustc-env=BAT_GENERATED_COMPLETION_PS1={}", + out_dir.join("assets/completions/_bat.ps1").display() + ); + println!( + "cargo:rustc-env=BAT_GENERATED_COMPLETION_ZSH={}", + out_dir.join("assets/completions/bat.zsh").display() + ); + Ok(()) } diff --git a/build/syntax_mapping.rs b/build/syntax_mapping.rs index 91a448f6..48468b9a 100644 --- a/build/syntax_mapping.rs +++ b/build/syntax_mapping.rs @@ -236,8 +236,14 @@ fn get_def_paths() -> anyhow::Result> { ]; let mut toml_paths = vec![]; - for subdir in source_subdirs { - let wd = WalkDir::new(Path::new("src/syntax_mapping/builtins").join(subdir)); + for subdir_name in source_subdirs { + let subdir = Path::new("src/syntax_mapping/builtins").join(subdir_name); + if !subdir.try_exists()? { + // Directory might not exist due to this `cargo vendor` bug: + // https://github.com/rust-lang/cargo/issues/15080 + continue; + } + let wd = WalkDir::new(subdir); let paths = wd .into_iter() .filter_map_ok(|entry| { diff --git a/doc/README-ja.md b/doc/README-ja.md index b0d52712..c906b3ec 100644 --- a/doc/README-ja.md +++ b/doc/README-ja.md @@ -366,7 +366,7 @@ ansible-galaxy install aeimer.install_bat ### From source -`bat` をソースからビルドしたいならば、Rust 1.70.0 以上の環境が必要です。 +`bat` をソースからビルドしたいならば、Rust 1.74.0 以上の環境が必要です。 `cargo` を使用してビルドすることができます: ```bash diff --git a/doc/README-ko.md b/doc/README-ko.md index 8a10fd68..6edb8ffe 100644 --- a/doc/README-ko.md +++ b/doc/README-ko.md @@ -416,7 +416,7 @@ scoop install bat ### 소스에서 -`bat`의 소스를 빌드하기 위해서는, Rust 1.70.0 이상이 필요합니다. +`bat`의 소스를 빌드하기 위해서는, Rust 1.74.0 이상이 필요합니다. `cargo`를 이용해 전부 빌드할 수 있습니다: ```bash diff --git a/doc/README-ru.md b/doc/README-ru.md index 4ed91cb1..06093077 100644 --- a/doc/README-ru.md +++ b/doc/README-ru.md @@ -3,11 +3,11 @@ Build Status license Version info
- Клон утилиты cat(1) с поддержкой выделения синтаксиса и Git + Клон утилиты cat(1) с поддержкой подсветки синтаксиса и Git

- Ключевые возможности • + Ключевые возможностиИспользованиеУстановкаКастомизация • @@ -19,11 +19,11 @@ [Русский]

-### Выделение синтаксиса +### Подсветка синтаксиса -`bat` поддерживает выделение синтаксиса для огромного количества языков программирования и разметки: +`bat` поддерживает подсветку синтаксиса для огромного количества языков программирования и разметки: -![Пример выделения синтаксиса](https://i.imgur.com/3FGy5tW.png) +![Пример подсветки синтаксиса](https://i.imgur.com/3FGy5tW.png) ### Интеграция с Git `bat` использует `git`, чтобы показать изменения в коде @@ -31,15 +31,17 @@ ![Пример интеграции с Git](https://i.imgur.com/azUAzdx.png) -### Показать непечатаемые символы +### Показ непечатных символов -Вы можете использовать `-A` / `--show-all` флаг, чтобы показать символы, которые невозможно напечатать: +Вы можете использовать флаг `-A` / `--show-all`, чтобы показать непечатные символы: ![Строка с неотображемыми символами](https://i.imgur.com/X0orYY9.png) -### Автоматическое разделение текста +### Автоматический пейджинг терминала -`bat` умеет перенаправлять вывод в `less`, если вывод не помещается на экране полностью. +`bat` умеет перенаправлять вывод в пейджер терминала (например, в `less`), если вывод не помещается на экране полностью. +Если вы хотите, чтобы `bat` работал как `cat` всё время, вы можете установить опцию `--paging=never` в командной строке или в конфигурационном файле. +Если вы намерены использовать `bat` в качестве алиаса для `cat`, вы можете установить `alias cat='bat --paging=never'`, чтобы сохранить изначальное поведение. ### Объединение файлов @@ -86,11 +88,23 @@ bat header.md content.md footer.md > document.md bat -n main.rs # показываем только количество строк -bat f - g # выводит 'f' в stdin, а потом 'g'. +bat f - g # выводит 'f', потом stdin, а потом 'g'. ``` ### Интеграция с другими утилитами +#### `fzf` + +Вы можете использовать `bat` как просмотрщик для [`fzf`](https://github.com/junegunn/fzf). +Чтобы это заработало, используйте опцию `--color=always`, чтобы вывод был всегда цветным. +Вы можете также использовать опцию `--line-range`, чтобы уменьшить время загрузки для больших файлов: + +```bash +fzf --preview "bat --color=always --style=numbers --line-range=:500 {}" +``` + +Больше деталей смотрите в [`README` программы `fzf`](https://github.com/junegunn/fzf#preview-window). + #### `find` или `fd` Вы можете использовать флаг `-exec` в `find`, чтобы посмотреть превью всех файлов в `bat` @@ -121,12 +135,22 @@ tail -f /var/log/pacman.log | bat --paging=never -l log #### `git` -Вы можете использовать `bat` с `git show`, чтобы просмотреть старую версию файла с выделением синтаксиса: +Вы можете использовать `bat` с `git show`, чтобы просмотреть старую версию файла с подсветкой синтаксиса: ```bash git show v0.6.0:src/main.rs | bat -l rs ``` -Обратите внимание, что выделение синтаксиса не работает в `git diff` на данный момент. Если вам это нужно, посмотрите [`delta`](https://github.com/dandavison/delta). +#### `git diff` + +Вы можете использовать `bat` с `git diff` для просмотра строк кода вокруг изменений с подсветкой синтаксиса: +```bash +batdiff() { + git diff --name-only --relative --diff-filter=d | xargs bat --diff +} +``` +Если вы хотите использовать это как отдельную программу, посмотрите `batdiff` из [`bat-extras`](https://github.com/eth-p/bat-extras). + +Если вам это нужна более полная поддержка для операций с git и diff, посмотрите [`delta`](https://github.com/dandavison/delta). #### `xclip` @@ -135,17 +159,18 @@ git show v0.6.0:src/main.rs | bat -l rs ```bash bat main.cpp | xclip ``` -`bat` обнаружит перенаправление вывода и выведет обычный текст без выделения синтаксиса. +`bat` обнаружит перенаправление вывода и выведет обычный текст без подсветки синтаксиса. #### `man` -`bat` может быть использован в виде выделения цвета для `man`, для этого установите переменную окружения +`bat` может быть использован для раскрашивания вывода `man`, для этого установите переменную окружения `MANPAGER`: ```bash export MANPAGER="sh -c 'col -bx | bat -l man -p'" man 2 select ``` +(замените `bat` на `batcat`, если у вас Debian или Ubuntu) Возможно вам понадобится также установить `MANROFFOPT="-c"`, если у вас есть проблемы с форматированием. @@ -153,10 +178,40 @@ man 2 select Обратите внимание, что [синтаксис manpage](assets/syntaxes/02_Extra/Manpage.sublime-syntax) разрабатывается в этом репозитории и все еще находится в разработке. +Также заметьте, что это [не заработает](https://github.com/sharkdp/bat/issues/1145) с реализацией `man` через Mandocs. + #### `prettier` / `shfmt` / `rustfmt` [`Prettybat`](https://github.com/eth-p/bat-extras/blob/master/doc/prettybat.md) — скрипт, который форматирует код и выводит его с помощью `bat`. +#### Подсветка сообщений `--help` + +Вы можете использовать `bat`, чтобы подсвечивать текст справки комманд: `$ cp --help | bat -plhelp` + +Вы можете сделать такую вспомогательную команду для этого: + +```bash +# in your .bashrc/.zshrc/*rc +alias bathelp='bat --plain --language=help' +help() { + "$@" --help 2>&1 | bathelp +} +``` + +В этом случае, вы можете просто писать `$ help cp` или `$ help git commit`. + +Если вы используете `zsh`, вы можете объявить глобальные алиасы для `-h` и `--help`: + +```bash +alias -g -- -h='-h 2>&1 | bat --language=help --style=plain' +alias -g -- --help='--help 2>&1 | bat --language=help --style=plain' +``` + +В этом случае, вы можете продолжать использовать `cp --help`, но при этом получать подцвеченный вывод. + +Обратите внимание, что не всегда опция `-h` является краткой формы опции `--help` (например, у `ls`). + +Пожалуйста, сообщайте о проблемах с подсветкой справки в [этот репозиторий](https://github.com/victor-gp/cmd-help-sublime-syntax). ## Установка @@ -165,8 +220,7 @@ man 2 select ### Ubuntu (с помощью `apt`) *... и другие дистрибутивы основанные на Debian.* -`bat` есть в репозиториях [Ubuntu](https://packages.ubuntu.com/eoan/bat) и -[Debian](https://packages.debian.org/sid/bat) и доступен начиная с Ubuntu Eoan 19.10. На Debian `bat` пока что доступен только с нестабильной веткой "Sid". +`bat` доступен на [Ubuntu since 20.04 ("Focal")](https://packages.ubuntu.com/search?keywords=bat&exact=1) и [Debian since August 2021 (Debian 11 - "Bullseye")](https://packages.debian.org/bullseye/bat). Если ваша версия Ubuntu/Debian достаточно новая, вы можете установить `bat` так: @@ -245,6 +299,14 @@ cd /usr/ports/textproc/bat make install ``` +### On OpenBSD + +Вы можете установить `bat` с помощью [`pkg_add(1)`](https://man.openbsd.org/pkg_add.1): + +```bash +pkg_add bat +``` + ### С помощью nix Вы можете установить `bat`, используя [nix package manager](https://nixos.org/nix): @@ -253,6 +315,14 @@ make install nix-env -i bat ``` +### Через flox + +Вы можете установить `bat` используя [Flox](https://flox.dev) + +```bash +flox install bat +``` + ### openSUSE Вы можете установить `bat` с помощью `zypper`: @@ -261,7 +331,7 @@ nix-env -i bat zypper install bat ``` -### macOS +### На macOS (или Linux) через Homebrew Вы можете установить `bat` с помощью [Homebrew](http://braumeister.org/formula/bat): @@ -269,6 +339,8 @@ zypper install bat brew install bat ``` +### На macOS через MacPorts + Или же установить его с помощью [MacPorts](https://ports.macports.org/port/bat/summary): ```bash @@ -277,7 +349,19 @@ port install bat ### Windows -Есть несколько способов установить `bat`. Как только вы установили его, посмотрите на секцию ["Использование `bat` в Windows"](#using-bat-on-windows). +Есть несколько способов установить `bat`. Как только вы установили его, посмотрите на секцию ["Использование `bat` в Windows"](#использование-bat-в-windows). + +#### Пререквитизы + +Вам нужно установить пакет [Visual C++ Redistributable](https://support.microsoft.com/en-us/help/2977003/the-latest-supported-visual-c-downloads). + +#### С помощью WinGet + +Вы можете установить `bat` через [WinGet](https://learn.microsoft.com/en-us/windows/package-manager/winget): + +```bash +winget install sharkdp.bat +``` #### С помощью Chocolatey @@ -293,50 +377,10 @@ choco install bat scoop install bat ``` -Для этого у вас должен быть установлен [Visual C++ Redistributable](https://support.microsoft.com/en-us/help/2977003/the-latest-supported-visual-c-downloads). - #### Из заранее скомпилированных файлов: Их вы можете скачать на [странице релизов](https://github.com/sharkdp/bat/releases). -Для этого у вас должен быть установлен [Visual C++ Redistributable](https://support.microsoft.com/en-us/help/2977003/the-latest-supported-visual-c-downloads). - -### С помощью Docker - -Вы можете использовать [Docker image](https://hub.docker.com/r/danlynn/bat/), чтобы запустить `bat` в контейнере: -```bash -docker pull danlynn/bat -alias bat='docker run -it --rm -e BAT_THEME -e BAT_STYLE -e BAT_TABS -v "$(pwd):/myapp" danlynn/bat' -``` - -### С помощью Ansible - -Вы можете установить `bat` с [Ansible](https://www.ansible.com/): - -```bash -# Устанавливаем роль на устройстве -ansible-galaxy install aeimer.install_bat -``` - -```yaml ---- -# Playbook для установки bat -- host: all - roles: - - aeimer.install_bat -``` - -- [Ansible Galaxy](https://galaxy.ansible.com/aeimer/install_bat) -- [GitHub](https://github.com/aeimer/ansible-install-bat) - -Этот способ должен сработать со следующими дистрибутивами: -- Debian/Ubuntu -- ARM (например Raspberry PI) -- Arch Linux -- Void Linux -- FreeBSD -- macOS - ### Из скомпилированных файлов Перейдите на [страницу релизов](https://github.com/sharkdp/bat/releases) для @@ -344,15 +388,24 @@ ansible-galaxy install aeimer.install_bat ### Из исходников -Если вы желаете установить `bat` из исходников, вам понадобится Rust 1.70.0 или выше. После этого используйте `cargo`, чтобы все скомпилировать: +Если вы желаете установить `bat` из исходников, вам понадобится Rust 1.74.0 или выше. После этого используйте `cargo`, чтобы всё скомпилировать: ```bash cargo install --locked bat ``` +Заметьте, что дополнительные файлы, такие как документация man и подсказки командной строки, не могут быть установлены таким способом. +Они будут сгенерированы командой `cargo` должны быть доступны в папке сборки (в `build`). + +Подсказки командной строки также доступны при таком запуске: +```bash +bat --completion +# see --help for supported shells +``` + ## Кастомизация -### Темы для выделения текста +### Темы для подсветки синтаксиса Используйте `bat --list-themes`, чтобы вывести список всех доступных тем. Для выбора темы `TwoDark` используйте `bat` с флагом `--theme=TwoDark` или выставьте переменную окружения `BAT_THEME` в `TwoDark`. Используйте `export BAT_THEME="TwoDark"` в конфигурационном файле вашей оболочки, чтобы изменить ее навсегда. Или же используйте [конфигурационный файл](https://github.com/sharkdp/bat#configuration-file) `bat`. @@ -372,7 +425,7 @@ bat --list-themes | fzf --preview="bat --theme={} --color=always /путь/к/ф ### Добавление новых синтаксисов -`bat` использует [`syntect`](https://github.com/trishume/syntect/) для выделения синтаксиса. `syntect` может читать +`bat` использует [`syntect`](https://github.com/trishume/syntect/) для подсветки синтаксиса. `syntect` может читать [файл `.sublime-syntax`](https://www.sublimetext.com/docs/3/syntax.html) и темы. Чтобы добавить новый синтаксис, сделайте следующее: @@ -403,7 +456,7 @@ bat cache --clear ### Добавление новых тем -Это работает похожим образом, так же как и добавление новых тем выделения синтаксиса +Это работает похожим образом, так же как и добавление новых тем подсветки синтаксиса Во-первых, создайте каталог с новыми темами для синтаксиса: ```bash @@ -590,7 +643,7 @@ cargo install --locked --force Есть очень много альтернатив `bat`. Смотрите [этот документ](doc/alternatives.md) для сравнения. ## Лицензия -Copyright (c) 2018-2021 [Разработчики bat](https://github.com/sharkdp/bat). +Copyright (c) 2018-2024 [Разработчики bat](https://github.com/sharkdp/bat). `bat` распространяется под лицензиями MIT License и Apache License 2.0 (на выбор пользователя). diff --git a/doc/README-zh.md b/doc/README-zh.md index 007afb3e..b3d2f5df 100644 --- a/doc/README-zh.md +++ b/doc/README-zh.md @@ -372,7 +372,7 @@ scoop install bat ### 从源码编译 -如果你想要自己构建`bat`,那么你需要安装有高于1.70.0版本的 Rust。 +如果你想要自己构建`bat`,那么你需要安装有高于1.74.0版本的 Rust。 使用以下命令编译。 @@ -616,63 +616,59 @@ iconv -f ISO-8859-1 -t UTF-8 my-file.php | bat 注意: 当`bat`无法识别语言时你可能会需要`-l`/`--language`参数。 -## Development +## 开发 ```bash -# Recursive clone to retrieve all submodules +# 递归 clone 以获取所有子模块 git clone --recursive https://github.com/sharkdp/bat -# Build (debug version) +# 构建(调试版本) cd bat cargo build --bins -# Run unit tests and integration tests +# 运行单元测试和集成测试 cargo test -# Install (release version) +# 安装(发布版本) cargo install --path . --locked -# Build a bat binary with modified syntaxes and themes +# 使用修改后的语法和主题构建一个 bat 二进制文件 bash assets/create.sh cargo install --path . --locked --force ``` -If you want to build an application that uses `bat`s pretty-printing -features as a library, check out the [the API documentation](https://docs.rs/bat/). -Note that you have to use either `regex-onig` or `regex-fancy` as a feature -when you depend on `bat` as a library. +如果你想构建一个使用 `bat` 美化打印功能的应用程序,请查看 [API 文档](https://docs.rs/bat/)。请注意,当你依赖 `bat` 作为库时,必须使用 `regex-onig` 或 `regex-fancy` 作为特性。 -## Contributing +## 贡献指南 -Take a look at the [`CONTRIBUTING.md`](CONTRIBUTING.md) guide. +请查看 [`CONTRIBUTING.md`](CONTRIBUTING.md) 指南。 -## Maintainers +## 维护者 - [sharkdp](https://github.com/sharkdp) - [eth-p](https://github.com/eth-p) - [keith-hall](https://github.com/keith-hall) - [Enselic](https://github.com/Enselic) -## Security vulnerabilities +## 安全漏洞 -Please contact [David Peter](https://david-peter.de/) via email if you want to report a vulnerability in `bat`. +如果你想报告 `bat` 中的漏洞,请通过邮件联系 [David Peter](https://david-peter.de/)。 -## Project goals and alternatives +## 项目目标和替代方案 -`bat` tries to achieve the following goals: +`bat` 试图实现以下目标: -- Provide beautiful, advanced syntax highlighting -- Integrate with Git to show file modifications -- Be a drop-in replacement for (POSIX) `cat` -- Offer a user-friendly command-line interface +- 提供美观的高级语法高亮 +- 与 Git 集成以显示文件修改 +- 成为 (POSIX) `cat` 的替代品 +- 提供用户友好的命令行界面 -There are a lot of alternatives, if you are looking for similar programs. See -[this document](doc/alternatives.md) for a comparison. +如果你在寻找类似的程序,有很多替代方案。请参阅[本文档](doc/alternatives.md)进行比较。 -## License +## 许可证 -Copyright (c) 2018-2021 [bat-developers](https://github.com/sharkdp/bat). +版权所有 (c) 2018-2021 [bat-developers](https://github.com/sharkdp/bat)。 -`bat` is made available under the terms of either the MIT License or the Apache License 2.0, at your option. +`bat` 可根据 MIT 许可证或 Apache 许可证 2.0 的条款使用,任选其一。 -See the [LICENSE-APACHE](LICENSE-APACHE) and [LICENSE-MIT](LICENSE-MIT) files for license details. +有关许可证的详细信息,请参阅 [LICENSE-APACHE](LICENSE-APACHE) 和 [LICENSE-MIT](LICENSE-MIT) 文件。 diff --git a/doc/assets.md b/doc/assets.md index a06a1e67..032a7883 100644 --- a/doc/assets.md +++ b/doc/assets.md @@ -26,7 +26,7 @@ in the `.sublime-syntax` format. 4. Re-compile `bat`. At compilation time, the `syntaxes.bin` file will be stored inside the `bat` binary. -5. Use `bat --list-languages` to check if the new languages are available. +5. Use `bat --list-languages` to check if the new languages are available. You may want to do something like `export PATH="`pwd`/target/debug:$PATH"` to ensure the locally compiled version is the one being used. 6. Add a syntax test for the new language. See [below](#Syntax-tests) for details. diff --git a/doc/long-help.txt b/doc/long-help.txt index 2b03490f..17d3395b 100644 --- a/doc/long-help.txt +++ b/doc/long-help.txt @@ -20,6 +20,13 @@ Options: * unicode (␇, ␊, ␀, ..) * caret (^G, ^J, ^@, ..) + --binary + 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 @@ -112,6 +119,27 @@ Options: Set the theme for syntax highlighting. Use '--list-themes' to see all available themes. To set a default theme, add the '--theme="..."' option to the configuration file or export the BAT_THEME environment variable (e.g.: export BAT_THEME="..."). + + Special values: + + * auto: Picks a dark or light theme depending on the terminal's colors (default). + Use '--theme-light' and '--theme-dark' to customize the selected theme. + * auto:always: Detect the terminal's colors even when the output is redirected. + * auto:system: Detect the color scheme from the system-wide preference (macOS only). + * dark: Use the dark theme specified by '--theme-dark'. + * light: Use the light theme specified by '--theme-light'. + + --theme-light + Sets the theme name for syntax highlighting used when the terminal uses a light + background. Use '--list-themes' to see all available themes. To set a default theme, add + the '--theme-light="..." option to the configuration file or export the BAT_THEME_LIGHT + environment variable (e.g. export BAT_THEME_LIGHT="..."). + + --theme-dark + Sets the theme name for syntax highlighting used when the terminal uses a dark background. + Use '--list-themes' to see all available themes. To set a default theme, add the + '--theme-dark="..." option to the configuration file or export the BAT_THEME_DARK + environment variable (e.g. export BAT_THEME_DARK="..."). --list-themes Display a list of supported themes for syntax highlighting. @@ -174,6 +202,9 @@ Options: This option exists for POSIX-compliance reasons ('u' is for 'unbuffered'). The output is always unbuffered - this option is simply ignored. + --completion + Show shell completion for a certain shell. [possible values: bash, fish, zsh, ps1] + --diagnostic Show diagnostic information for bug reports. diff --git a/doc/short-help.txt b/doc/short-help.txt index 305bbf3d..d67a51d0 100644 --- a/doc/short-help.txt +++ b/doc/short-help.txt @@ -11,6 +11,8 @@ Options: Show non-printable characters (space, tab, newline, ..). --nonprintable-notation Set notation for non-printable characters. + --binary + How to treat binary content. (default: no-printing) -p, --plain... Show plain style (alias for '--style=plain'). -l, --language @@ -41,6 +43,10 @@ Options: Use the specified syntax for files matching the glob pattern ('*.cpp:C++'). --theme Set the color theme for syntax highlighting. + --theme-light + Sets the color theme for syntax highlighting used for light backgrounds. + --theme-dark + Sets the color theme for syntax highlighting used for dark backgrounds. --list-themes Display all supported highlighting themes. -s, --squeeze-blank @@ -52,6 +58,8 @@ Options: Only print the lines from N to M. -L, --list-languages Display all supported languages. + --completion + Show shell completion for a certain shell. [possible values: bash, fish, zsh, ps1] -h, --help Print help (see more with '--help') -V, --version diff --git a/doc/sponsors/warp-logo.png b/doc/sponsors/warp-logo.png index 4795a2b9..f99dd38c 100644 Binary files a/doc/sponsors/warp-logo.png and b/doc/sponsors/warp-logo.png differ diff --git a/doc/sponsors/warp-pack-header.png b/doc/sponsors/warp-pack-header.png new file mode 100644 index 00000000..ed7efe6a Binary files /dev/null and b/doc/sponsors/warp-pack-header.png differ diff --git a/doc/sponsors/workos-logo-white-bg.svg b/doc/sponsors/workos-logo-white-bg.svg deleted file mode 100644 index 3c9bb24c..00000000 --- a/doc/sponsors/workos-logo-white-bg.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/examples/buffer.rs b/examples/buffer.rs index 839689d4..eefdb249 100644 --- a/examples/buffer.rs +++ b/examples/buffer.rs @@ -1,4 +1,6 @@ -use bat::{assets::HighlightingAssets, config::Config, controller::Controller, Input}; +use bat::{ + assets::HighlightingAssets, config::Config, controller::Controller, output::OutputHandle, Input, +}; fn main() { let mut buffer = String::new(); @@ -10,7 +12,10 @@ fn main() { let controller = Controller::new(&config, &assets); let input = Input::from_file(file!()); controller - .run(vec![input.into()], Some(&mut buffer)) + .run( + vec![input.into()], + Some(OutputHandle::FmtWrite(&mut buffer)), + ) .unwrap(); println!("{buffer}"); diff --git a/src/assets.rs b/src/assets.rs index 9655553d..e6c50219 100644 --- a/src/assets.rs +++ b/src/assets.rs @@ -13,6 +13,7 @@ use crate::error::*; use crate::input::{InputReader, OpenedInput}; use crate::syntax_mapping::ignored_suffixes::IgnoredSuffixes; use crate::syntax_mapping::MappingTarget; +use crate::theme::{default_theme, ColorScheme}; use crate::{bat_warning, SyntaxMapping}; use lazy_theme_set::LazyThemeSet; @@ -69,57 +70,6 @@ impl HighlightingAssets { } } - /// The default theme. - /// - /// ### Windows and Linux - /// - /// Windows and most Linux distributions has a dark terminal theme by - /// default. On these platforms, this function always returns a theme that - /// looks good on a dark background. - /// - /// ### macOS - /// - /// On macOS the default terminal background is light, but it is common that - /// Dark Mode is active, which makes the terminal background dark. On this - /// platform, the default theme depends on - /// ```bash - /// defaults read -globalDomain AppleInterfaceStyle - /// ``` - /// To avoid the overhead of the check on macOS, simply specify a theme - /// explicitly via `--theme`, `BAT_THEME`, or `~/.config/bat`. - /// - /// See and - /// for more context. - pub fn default_theme() -> &'static str { - #[cfg(not(target_os = "macos"))] - { - Self::default_dark_theme() - } - #[cfg(target_os = "macos")] - { - if macos_dark_mode_active() { - Self::default_dark_theme() - } else { - Self::default_light_theme() - } - } - } - - /** - * The default theme that looks good on a dark background. - */ - fn default_dark_theme() -> &'static str { - "Monokai Extended" - } - - /** - * The default theme that looks good on a light background. - */ - #[cfg(target_os = "macos")] - fn default_light_theme() -> &'static str { - "Monokai Extended Light" - } - pub fn from_cache(cache_path: &Path) -> Result { Ok(HighlightingAssets::new( SerializedSyntaxSet::FromFile(cache_path.join("syntaxes.bin")), @@ -248,7 +198,10 @@ impl HighlightingAssets { bat_warning!("Unknown theme '{}', using default.", theme) } self.get_theme_set() - .get(self.fallback_theme.unwrap_or_else(Self::default_theme)) + .get( + self.fallback_theme + .unwrap_or_else(|| default_theme(ColorScheme::Dark)), + ) .expect("something is very wrong if the default theme is missing") } } @@ -399,26 +352,6 @@ fn asset_from_cache( .map_err(|_| format!("Could not parse cached {description}").into()) } -#[cfg(target_os = "macos")] -fn macos_dark_mode_active() -> bool { - const PREFERENCES_FILE: &str = "Library/Preferences/.GlobalPreferences.plist"; - const STYLE_KEY: &str = "AppleInterfaceStyle"; - - let preferences_file = home::home_dir() - .map(|home| home.join(PREFERENCES_FILE)) - .expect("Could not get home directory"); - - match plist::Value::from_file(preferences_file).map(|file| file.into_dictionary()) { - Ok(Some(preferences)) => match preferences.get(STYLE_KEY).and_then(|val| val.as_string()) { - Some(value) => value == "Dark", - // If the key does not exist, then light theme is currently in use. - None => false, - }, - // Unreachable, in theory. All macOS users have a home directory and preferences file setup. - Ok(None) | Err(_) => true, - } -} - #[cfg(test)] mod tests { use super::*; @@ -437,7 +370,7 @@ mod tests { pub temp_dir: TempDir, } - impl<'a> SyntaxDetectionTest<'a> { + impl SyntaxDetectionTest<'_> { fn new() -> Self { SyntaxDetectionTest { assets: HighlightingAssets::from_binary(), diff --git a/src/assets/build_assets/acknowledgements.rs b/src/assets/build_assets/acknowledgements.rs index c4fde919..db9b5c69 100644 --- a/src/assets/build_assets/acknowledgements.rs +++ b/src/assets/build_assets/acknowledgements.rs @@ -60,7 +60,7 @@ fn to_path_and_stem(source_dir: &Path, entry: DirEntry) -> Option { fn handle_file(path_and_stem: &PathAndStem) -> Result> { if path_and_stem.stem == "NOTICE" { handle_notice(&path_and_stem.path) - } else if path_and_stem.stem.to_ascii_uppercase() == "LICENSE" { + } else if path_and_stem.stem.eq_ignore_ascii_case("LICENSE") { handle_license(&path_and_stem.path) } else { Ok(None) diff --git a/src/bin/bat/app.rs b/src/bin/bat/app.rs index d6628668..946ce5b1 100644 --- a/src/bin/bat/app.rs +++ b/src/bin/bat/app.rs @@ -9,6 +9,8 @@ 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::theme::{theme, ThemeName, ThemeOptions, ThemePreference}; +use bat::BinaryBehavior; use bat::StripAnsiMode; use clap::ArgMatches; @@ -16,7 +18,6 @@ use console::Term; use crate::input::{new_file_input, new_stdin_input}; use bat::{ - assets::HighlightingAssets, bat_warning, config::{Config, VisibleLines}, error::*, @@ -97,15 +98,36 @@ impl App { pub fn config(&self, inputs: &[Input]) -> Result { 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::("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) { + } else if inputs.iter().any(Input::is_stdin) + // ignore stdin when --list-themes is used because in that case no input will be read anyways + && !self.matches.get_flag("list-themes") + { // If we are reading from stdin, only enable paging if we write to an // interactive terminal and if we do not *read* from an interactive // terminal. @@ -193,6 +215,11 @@ impl App { Some("caret") => NonprintableNotation::Caret, _ => unreachable!("other values for --nonprintable-notation are not allowed"), }, + binary: match self.matches.get_one::("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::("wrap").map(|s| s.as_str()) { @@ -254,18 +281,7 @@ impl App { Some("auto") => StripAnsiMode::Auto, _ => unreachable!("other values for --strip-ansi are not allowed"), }, - theme: self - .matches - .get_one::("theme") - .map(String::from) - .map(|s| { - if s == "default" { - String::from(HighlightingAssets::default_theme()) - } else { - s - } - }) - .unwrap_or_else(|| String::from(HighlightingAssets::default_theme())), + theme: theme(self.theme_options()).to_string(), visible_lines: match self.matches.try_contains_id("diff").unwrap_or_default() && self.matches.get_flag("diff") { @@ -412,7 +428,7 @@ impl App { None => StyleComponents(HashSet::from_iter( StyleComponent::Default .components(self.interactive_output) - .into_iter() + .iter() .cloned(), )), }; @@ -424,4 +440,25 @@ impl App { Ok(styled_components) } + + fn theme_options(&self) -> ThemeOptions { + let theme = self + .matches + .get_one::("theme") + .map(|t| ThemePreference::from_str(t).unwrap()) + .unwrap_or_default(); + let theme_dark = self + .matches + .get_one::("theme-dark") + .map(|t| ThemeName::from_str(t).unwrap()); + let theme_light = self + .matches + .get_one::("theme-light") + .map(|t| ThemeName::from_str(t).unwrap()); + ThemeOptions { + theme, + theme_dark, + theme_light, + } + } } diff --git a/src/bin/bat/clap_app.rs b/src/bin/bat/clap_app.rs index 33dde980..de2db078 100644 --- a/src/bin/bat/clap_app.rs +++ b/src/bin/bat/clap_app.rs @@ -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") @@ -379,9 +393,40 @@ pub fn build_app(interactive_output: bool) -> Command { see all available themes. To set a default theme, add the \ '--theme=\"...\"' option to the configuration file or export the \ BAT_THEME environment variable (e.g.: export \ - BAT_THEME=\"...\").", + BAT_THEME=\"...\").\n\n\ + Special values:\n\n \ + * auto: Picks a dark or light theme depending on the terminal's colors (default).\n \ + Use '--theme-light' and '--theme-dark' to customize the selected theme.\n \ + * auto:always: Detect the terminal's colors even when the output is redirected.\n \ + * auto:system: Detect the color scheme from the system-wide preference (macOS only).\n \ + * dark: Use the dark theme specified by '--theme-dark'.\n \ + * light: Use the light theme specified by '--theme-light'.", ), ) + .arg( + Arg::new("theme-light") + .long("theme-light") + .overrides_with("theme-light") + .value_name("theme") + .help("Sets the color theme for syntax highlighting used for light backgrounds.") + .long_help( + "Sets the theme name for syntax highlighting used when the terminal uses a light background. \ + Use '--list-themes' to see all available themes. To set a default theme, add the \ + '--theme-light=\"...\" option to the configuration file or export the BAT_THEME_LIGHT \ + environment variable (e.g. export BAT_THEME_LIGHT=\"...\")."), + ) + .arg( + Arg::new("theme-dark") + .long("theme-dark") + .overrides_with("theme-dark") + .value_name("theme") + .help("Sets the color theme for syntax highlighting used for dark backgrounds.") + .long_help( + "Sets the theme name for syntax highlighting used when the terminal uses a dark background. \ + Use '--list-themes' to see all available themes. To set a default theme, add the \ + '--theme-dark=\"...\" option to the configuration file or export the BAT_THEME_DARK \ + environment variable (e.g. export BAT_THEME_DARK=\"...\")."), + ) .arg( Arg::new("list-themes") .long("list-themes") @@ -519,6 +564,17 @@ pub fn build_app(interactive_output: bool) -> Command { .help("Do not load custom assets"), ); + #[cfg(feature = "application")] + { + app = app.arg( + Arg::new("completion") + .long("completion") + .value_name("SHELL") + .value_parser(["bash", "fish", "ps1", "zsh"]) + .help("Show shell completion for a certain shell. [possible values: bash, fish, zsh, ps1]"), + ); + } + #[cfg(feature = "lessopen")] { app = app diff --git a/src/bin/bat/completions.rs b/src/bin/bat/completions.rs new file mode 100644 index 00000000..9b63a3e9 --- /dev/null +++ b/src/bin/bat/completions.rs @@ -0,0 +1,6 @@ +use std::env; + +pub const BASH_COMPLETION: &str = include_str!(env!("BAT_GENERATED_COMPLETION_BASH")); +pub const FISH_COMPLETION: &str = include_str!(env!("BAT_GENERATED_COMPLETION_FISH")); +pub const PS1_COMPLETION: &str = include_str!(env!("BAT_GENERATED_COMPLETION_PS1")); +pub const ZSH_COMPLETION: &str = include_str!(env!("BAT_GENERATED_COMPLETION_ZSH")); diff --git a/src/bin/bat/config.rs b/src/bin/bat/config.rs index 6fa18f09..a0ee7ba3 100644 --- a/src/bin/bat/config.rs +++ b/src/bin/bat/config.rs @@ -140,7 +140,9 @@ fn get_args_from_str(content: &str) -> Result, shell_words::ParseE pub fn get_args_from_env_vars() -> Vec { [ ("--tabs", "BAT_TABS"), - ("--theme", "BAT_THEME"), + ("--theme", bat::theme::env::BAT_THEME), + ("--theme-dark", bat::theme::env::BAT_THEME_DARK), + ("--theme-light", bat::theme::env::BAT_THEME_LIGHT), ("--pager", "BAT_PAGER"), ("--paging", "BAT_PAGING"), ("--style", "BAT_STYLE"), diff --git a/src/bin/bat/main.rs b/src/bin/bat/main.rs index 4528a60b..4496032b 100644 --- a/src/bin/bat/main.rs +++ b/src/bin/bat/main.rs @@ -3,6 +3,8 @@ mod app; mod assets; mod clap_app; +#[cfg(feature = "application")] +mod completions; mod config; mod directories; mod input; @@ -14,6 +16,8 @@ use std::io::{BufReader, Write}; use std::path::Path; use std::process; +use bat::output::{OutputHandle, OutputType}; +use bat::theme::DetectColorScheme; use nu_ansi_term::Color::Green; use nu_ansi_term::Style; @@ -30,12 +34,12 @@ use directories::PROJECT_DIRS; use globset::GlobMatcher; use bat::{ - assets::HighlightingAssets, config::Config, controller::Controller, error::*, input::Input, style::{StyleComponent, StyleComponents}, + theme::{color_scheme, default_theme, ColorScheme}, MappingTarget, PagingMode, }; @@ -189,7 +193,12 @@ fn theme_preview_file<'a>() -> Input<'a> { Input::from_reader(Box::new(BufReader::new(THEME_PREVIEW_DATA))) } -pub fn list_themes(cfg: &Config, config_dir: &Path, cache_dir: &Path) -> Result<()> { +pub fn list_themes( + cfg: &Config, + config_dir: &Path, + cache_dir: &Path, + detect_color_scheme: DetectColorScheme, +) -> Result<()> { let assets = assets_from_cache_or_binary(cfg.use_custom_assets, cache_dir)?; let mut config = cfg.clone(); let mut style = HashSet::new(); @@ -197,36 +206,46 @@ pub fn list_themes(cfg: &Config, config_dir: &Path, cache_dir: &Path) -> Result< config.language = Some("Rust"); config.style_components = StyleComponents(style); - let stdout = io::stdout(); - let mut stdout = stdout.lock(); + let mut output_type = + OutputType::from_mode(config.paging_mode, config.wrapping_mode, config.pager)?; + let mut writer = output_type.handle()?; - let default_theme = HighlightingAssets::default_theme(); + let default_theme_name = default_theme(color_scheme(detect_color_scheme).unwrap_or_default()); for theme in assets.themes() { - let default_theme_info = if default_theme == theme { + let default_theme_info = if default_theme_name == theme { " (default)" + } else if default_theme(ColorScheme::Dark) == theme { + " (default dark)" + } else if default_theme(ColorScheme::Light) == theme { + " (default light)" } else { "" }; if config.colored_output { writeln!( - stdout, + writer, "Theme: {}{}\n", Style::new().bold().paint(theme.to_string()), default_theme_info )?; config.theme = theme.to_string(); Controller::new(&config, &assets) - .run(vec![theme_preview_file()], None) + .run( + vec![theme_preview_file()], + Some(OutputHandle::IoWrite(&mut writer)), + ) .ok(); - writeln!(stdout)?; + writeln!(writer)?; + } else if config.loop_through { + writeln!(writer, "{theme}")?; } else { - writeln!(stdout, "{theme}{default_theme_info}")?; + writeln!(writer, "{theme}{default_theme_info}")?; } } if config.colored_output { writeln!( - stdout, + writer, "Further themes can be installed to '{}', \ and are added to the cache with `bat cache --build`. \ For more information, see:\n\n \ @@ -337,6 +356,18 @@ fn run() -> Result { return Ok(true); } + #[cfg(feature = "application")] + if let Some(shell) = app.matches.get_one::("completion") { + match shell.as_str() { + "bash" => println!("{}", completions::BASH_COMPLETION), + "fish" => println!("{}", completions::FISH_COMPLETION), + "ps1" => println!("{}", completions::PS1_COMPLETION), + "zsh" => println!("{}", completions::ZSH_COMPLETION), + _ => unreachable!("No completion for shell '{}' available.", shell), + } + return Ok(true); + } + match app.matches.subcommand() { Some(("cache", cache_matches)) => { // If there is a file named 'cache' in the current working directory, @@ -371,7 +402,7 @@ fn run() -> Result { }; run_controller(inputs, &plain_config, cache_dir) } else if app.matches.get_flag("list-themes") { - list_themes(&config, config_dir, cache_dir)?; + list_themes(&config, config_dir, cache_dir, DetectColorScheme::default())?; Ok(true) } else if app.matches.get_flag("config-file") { println!("{}", config_file().to_string_lossy()); diff --git a/src/config.rs b/src/config.rs index 8ff49ec1..622a6ca6 100644 --- a/src/config.rs +++ b/src/config.rs @@ -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, diff --git a/src/controller.rs b/src/controller.rs index 25ee2995..57720ab0 100644 --- a/src/controller.rs +++ b/src/controller.rs @@ -9,10 +9,10 @@ use crate::lessopen::LessOpenPreprocessor; #[cfg(feature = "git")] use crate::line_range::LineRange; use crate::line_range::{LineRanges, MaxBufferedLineNumber, RangeCheckResult}; -use crate::output::OutputType; +use crate::output::{OutputHandle, OutputType}; #[cfg(feature = "paging")] use crate::paging::PagingMode; -use crate::printer::{InteractivePrinter, OutputHandle, Printer, SimplePrinter}; +use crate::printer::{InteractivePrinter, Printer, SimplePrinter}; use std::collections::VecDeque; use std::io::{self, BufRead, Write}; use std::mem; @@ -26,7 +26,7 @@ pub struct Controller<'a> { preprocessor: Option, } -impl<'b> Controller<'b> { +impl Controller<'_> { pub fn new<'a>(config: &'a Config, assets: &'a HighlightingAssets) -> Controller<'a> { Controller { config, @@ -36,18 +36,14 @@ impl<'b> Controller<'b> { } } - pub fn run( - &self, - inputs: Vec, - output_buffer: Option<&mut dyn std::fmt::Write>, - ) -> Result { - self.run_with_error_handler(inputs, output_buffer, default_error_handler) + pub fn run(&self, inputs: Vec, output_handle: Option>) -> Result { + self.run_with_error_handler(inputs, output_handle, default_error_handler) } pub fn run_with_error_handler( &self, inputs: Vec, - output_buffer: Option<&mut dyn std::fmt::Write>, + output_handle: Option>, mut handle_error: impl FnMut(&Error, &mut dyn Write), ) -> Result { let mut output_type; @@ -89,8 +85,9 @@ impl<'b> Controller<'b> { clircle::Identifier::stdout() }; - let mut writer = match output_buffer { - Some(buf) => OutputHandle::FmtWrite(buf), + let mut writer = match output_handle { + Some(OutputHandle::FmtWrite(w)) => OutputHandle::FmtWrite(w), + Some(OutputHandle::IoWrite(w)) => OutputHandle::IoWrite(w), None => OutputHandle::IoWrite(output_type.handle()?), }; let mut no_errors: bool = true; diff --git a/src/input.rs b/src/input.rs index 0ebaa4ce..b36204df 100644 --- a/src/input.rs +++ b/src/input.rs @@ -75,7 +75,7 @@ pub(crate) enum InputKind<'a> { CustomReader(Box), } -impl<'a> InputKind<'a> { +impl InputKind<'_> { pub fn description(&self) -> InputDescription { match self { InputKind::OrdinaryFile(ref path) => InputDescription::new(path.to_string_lossy()), diff --git a/src/lessopen.rs b/src/lessopen.rs index c8f5225d..79f977af 100644 --- a/src/lessopen.rs +++ b/src/lessopen.rs @@ -1,15 +1,12 @@ -#![cfg(feature = "lessopen")] - use std::convert::TryFrom; use std::env; use std::fs::File; -use std::io::{BufRead, BufReader, Cursor, Read, Write}; +use std::io::{BufRead, BufReader, Cursor, Read}; use std::path::PathBuf; -use std::str; +use std::process::{ExitStatus, Stdio}; use clircle::{Clircle, Identifier}; -use os_str_bytes::RawOsString; -use run_script::{IoOptions, ScriptOptions}; +use execute::{shell, Execute}; use crate::error::Result; use crate::{ @@ -21,7 +18,6 @@ use crate::{ pub(crate) struct LessOpenPreprocessor { lessopen: String, lessclose: Option, - command_options: ScriptOptions, kind: LessOpenKind, /// Whether or not data piped via stdin is to be preprocessed preprocess_stdin: bool, @@ -52,7 +48,7 @@ impl LessOpenPreprocessor { // Otherwise, if output is empty and exit code is nonzero, use original file contents let (kind, lessopen) = if lessopen.starts_with("||") { (LessOpenKind::Piped, lessopen.chars().skip(2).collect()) - // "|" means pipe, but ignore exit code, always using preprocessor output + // "|" means pipe as above, but ignore exit code and always use preprocessor output even if empty } else if lessopen.starts_with('|') { ( LessOpenKind::PipedIgnoreExitCode, @@ -70,16 +66,9 @@ impl LessOpenPreprocessor { (false, lessopen) }; - let mut command_options = ScriptOptions::new(); - command_options.runner = env::var("SHELL").ok(); - command_options.input_redirection = IoOptions::Pipe; - Ok(Self { - lessopen: lessopen.replacen("%s", "$1", 1), - lessclose: env::var("LESSCLOSE") - .ok() - .map(|str| str.replacen("%s", "$1", 1).replacen("%s", "$2", 1)), - command_options, + lessopen, + lessclose: env::var("LESSCLOSE").ok(), kind, preprocess_stdin: stdin, }) @@ -98,21 +87,21 @@ impl LessOpenPreprocessor { None => return input.open(stdin, stdout_identifier), }; - let (exit_code, lessopen_stdout, _) = match run_script::run( - &self.lessopen, - &vec![path_str.to_string()], - &self.command_options, - ) { + let mut lessopen_command = shell(self.lessopen.replacen("%s", path_str, 1)); + lessopen_command.stdout(Stdio::piped()); + + let lessopen_output = match lessopen_command.execute_output() { Ok(output) => output, Err(_) => return input.open(stdin, stdout_identifier), }; - if self.fall_back_to_original_file(&lessopen_stdout, exit_code) { + if self.fall_back_to_original_file(&lessopen_output.stdout, lessopen_output.status) + { return input.open(stdin, stdout_identifier); } ( - RawOsString::from_string(lessopen_stdout), + lessopen_output.stdout, path_str.to_string(), OpenedInputKind::OrdinaryFile(path.to_path_buf()), ) @@ -127,47 +116,31 @@ impl LessOpenPreprocessor { } } - // stdin isn't Clone, so copy it to a cloneable buffer + // stdin isn't Clone or AsRef<[u8]>, so move it into a cloneable buffer + // so the data can be used multiple times if necessary + // NOTE: stdin will be empty from this point onwards let mut stdin_buffer = Vec::new(); - stdin.read_to_end(&mut stdin_buffer).unwrap(); + stdin.read_to_end(&mut stdin_buffer)?; - let mut lessopen_handle = match run_script::spawn( - &self.lessopen, - &vec!["-".to_string()], - &self.command_options, - ) { - Ok(handle) => handle, - Err(_) => { - return input.open(stdin, stdout_identifier); - } - }; + let mut lessopen_command = shell(self.lessopen.replacen("%s", "-", 1)); + lessopen_command.stdout(Stdio::piped()); - if lessopen_handle - .stdin - .as_mut() - .unwrap() - .write_all(&stdin_buffer.clone()) - .is_err() + let lessopen_output = match lessopen_command.execute_input_output(&stdin_buffer) { - return input.open(stdin, stdout_identifier); - } - - let lessopen_output = match lessopen_handle.wait_with_output() { Ok(output) => output, Err(_) => { return input.open(Cursor::new(stdin_buffer), stdout_identifier); } }; - if lessopen_output.stdout.is_empty() - && (!lessopen_output.status.success() - || matches!(self.kind, LessOpenKind::PipedIgnoreExitCode)) + if self + .fall_back_to_original_file(&lessopen_output.stdout, lessopen_output.status) { return input.open(Cursor::new(stdin_buffer), stdout_identifier); } ( - RawOsString::assert_from_raw_vec(lessopen_output.stdout), + lessopen_output.stdout, "-".to_string(), OpenedInputKind::StdIn, ) @@ -184,13 +157,17 @@ impl LessOpenPreprocessor { kind, reader: InputReader::new(BufReader::new( if matches!(self.kind, LessOpenKind::TempFile) { - // Remove newline at end of temporary file path returned by $LESSOPEN - let stdout = match lessopen_stdout.strip_suffix("\n") { - Some(stripped) => stripped.to_owned(), - None => lessopen_stdout, + let lessopen_string = match String::from_utf8(lessopen_stdout) { + Ok(string) => string, + Err(_) => { + return input.open(stdin, stdout_identifier); + } + }; + // Remove newline at end of temporary file path returned by $LESSOPEN + let stdout = match lessopen_string.strip_suffix("\n") { + Some(stripped) => stripped.to_owned(), + None => lessopen_string, }; - - let stdout = stdout.into_os_string(); let file = match File::open(PathBuf::from(&stdout)) { Ok(file) => file, @@ -201,16 +178,18 @@ impl LessOpenPreprocessor { Preprocessed { kind: PreprocessedKind::TempFile(file), - lessclose: self.lessclose.clone(), - command_args: vec![path_str, stdout.to_str().unwrap().to_string()], - command_options: self.command_options.clone(), + lessclose: self + .lessclose + .as_ref() + .map(|s| s.replacen("%s", &path_str, 1).replacen("%s", &stdout, 1)), } } else { Preprocessed { - kind: PreprocessedKind::Piped(Cursor::new(lessopen_stdout.into_raw_vec())), - lessclose: self.lessclose.clone(), - command_args: vec![path_str, "-".to_string()], - command_options: self.command_options.clone(), + kind: PreprocessedKind::Piped(Cursor::new(lessopen_stdout)), + lessclose: self + .lessclose + .as_ref() + .map(|s| s.replacen("%s", &path_str, 1).replacen("%s", "-", 1)), } }, )), @@ -219,9 +198,9 @@ impl LessOpenPreprocessor { }) } - fn fall_back_to_original_file(&self, lessopen_output: &str, exit_code: i32) -> bool { - lessopen_output.is_empty() - && (exit_code != 0 || matches!(self.kind, LessOpenKind::PipedIgnoreExitCode)) + fn fall_back_to_original_file(&self, lessopen_stdout: &[u8], exit_code: ExitStatus) -> bool { + lessopen_stdout.is_empty() + && (!exit_code.success() || matches!(self.kind, LessOpenKind::PipedIgnoreExitCode)) } #[cfg(test)] @@ -261,8 +240,6 @@ impl Read for PreprocessedKind { pub struct Preprocessed { kind: PreprocessedKind, lessclose: Option, - command_args: Vec, - command_options: ScriptOptions, } impl Read for Preprocessed { @@ -273,11 +250,20 @@ impl Read for Preprocessed { impl Drop for Preprocessed { fn drop(&mut self) { - if let Some(ref command) = self.lessclose { - self.command_options.output_redirection = IoOptions::Inherit; + if let Some(lessclose) = self.lessclose.clone() { + let mut lessclose_command = shell(lessclose); - run_script::run(command, &self.command_args, &self.command_options) - .expect("failed to run $LESSCLOSE to clean up file"); + let lessclose_output = match lessclose_command.execute_output() { + Ok(output) => output, + Err(_) => { + bat_warning!("failed to run $LESSCLOSE to clean up temporary file"); + return; + } + }; + + if lessclose_output.status.success() { + bat_warning!("$LESSCLOSE exited with nonzero exit code",) + }; } } } @@ -301,7 +287,7 @@ mod tests { fn test_just_lessopen() -> Result<()> { let preprocessor = LessOpenPreprocessor::mock_new(Some("|batpipe %s"), None)?; - assert_eq!(preprocessor.lessopen, "batpipe $1"); + assert_eq!(preprocessor.lessopen, "batpipe %s"); assert!(preprocessor.lessclose.is_none()); reset_env_vars(); @@ -327,8 +313,8 @@ mod tests { let preprocessor = LessOpenPreprocessor::mock_new(Some("lessopen.sh %s"), Some("lessclose.sh %s %s"))?; - assert_eq!(preprocessor.lessopen, "lessopen.sh $1"); - assert_eq!(preprocessor.lessclose.unwrap(), "lessclose.sh $1 $2"); + assert_eq!(preprocessor.lessopen, "lessopen.sh %s"); + assert_eq!(preprocessor.lessclose.unwrap(), "lessclose.sh %s %s"); reset_env_vars(); @@ -340,13 +326,13 @@ mod tests { fn test_lessopen_prefixes() -> Result<()> { let preprocessor = LessOpenPreprocessor::mock_new(Some("batpipe %s"), None)?; - assert_eq!(preprocessor.lessopen, "batpipe $1"); + assert_eq!(preprocessor.lessopen, "batpipe %s"); assert!(matches!(preprocessor.kind, LessOpenKind::TempFile)); assert!(!preprocessor.preprocess_stdin); let preprocessor = LessOpenPreprocessor::mock_new(Some("|batpipe %s"), None)?; - assert_eq!(preprocessor.lessopen, "batpipe $1"); + assert_eq!(preprocessor.lessopen, "batpipe %s"); assert!(matches!( preprocessor.kind, LessOpenKind::PipedIgnoreExitCode @@ -355,19 +341,19 @@ mod tests { let preprocessor = LessOpenPreprocessor::mock_new(Some("||batpipe %s"), None)?; - assert_eq!(preprocessor.lessopen, "batpipe $1"); + assert_eq!(preprocessor.lessopen, "batpipe %s"); assert!(matches!(preprocessor.kind, LessOpenKind::Piped)); assert!(!preprocessor.preprocess_stdin); let preprocessor = LessOpenPreprocessor::mock_new(Some("-batpipe %s"), None)?; - assert_eq!(preprocessor.lessopen, "batpipe $1"); + assert_eq!(preprocessor.lessopen, "batpipe %s"); assert!(matches!(preprocessor.kind, LessOpenKind::TempFile)); assert!(preprocessor.preprocess_stdin); let preprocessor = LessOpenPreprocessor::mock_new(Some("|-batpipe %s"), None)?; - assert_eq!(preprocessor.lessopen, "batpipe $1"); + assert_eq!(preprocessor.lessopen, "batpipe %s"); assert!(matches!( preprocessor.kind, LessOpenKind::PipedIgnoreExitCode @@ -376,7 +362,7 @@ mod tests { let preprocessor = LessOpenPreprocessor::mock_new(Some("||-batpipe %s"), None)?; - assert_eq!(preprocessor.lessopen, "batpipe $1"); + assert_eq!(preprocessor.lessopen, "batpipe %s"); assert!(matches!(preprocessor.kind, LessOpenKind::Piped)); assert!(preprocessor.preprocess_stdin); @@ -391,8 +377,8 @@ mod tests { let preprocessor = LessOpenPreprocessor::mock_new(Some("|echo File:%s"), Some("echo File:%s Temp:%s"))?; - assert_eq!(preprocessor.lessopen, "echo File:$1"); - assert_eq!(preprocessor.lessclose.unwrap(), "echo File:$1 Temp:$2"); + assert_eq!(preprocessor.lessopen, "echo File:%s"); + assert_eq!(preprocessor.lessclose.unwrap(), "echo File:%s Temp:%s"); reset_env_vars(); diff --git a/src/lib.rs b/src/lib.rs index 23c4a800..4c60f10e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -38,7 +38,7 @@ mod less; mod lessopen; pub mod line_range; pub(crate) mod nonprintable_notation; -mod output; +pub mod output; #[cfg(feature = "paging")] mod pager; #[cfg(feature = "paging")] @@ -49,10 +49,11 @@ pub(crate) mod printer; pub mod style; pub(crate) mod syntax_mapping; mod terminal; +pub mod theme; 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}; diff --git a/src/nonprintable_notation.rs b/src/nonprintable_notation.rs index ff09aca6..9f8d7cb8 100644 --- a/src/nonprintable_notation.rs +++ b/src/nonprintable_notation.rs @@ -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, +} diff --git a/src/output.rs b/src/output.rs index dc75d6e7..bb9a45d5 100644 --- a/src/output.rs +++ b/src/output.rs @@ -1,3 +1,4 @@ +use std::fmt; use std::io::{self, Write}; #[cfg(feature = "paging")] use std::process::Child; @@ -162,3 +163,17 @@ impl Drop for OutputType { } } } + +pub enum OutputHandle<'a> { + IoWrite(&'a mut dyn io::Write), + FmtWrite(&'a mut dyn fmt::Write), +} + +impl OutputHandle<'_> { + pub fn write_fmt(&mut self, args: fmt::Arguments<'_>) -> Result<()> { + match self { + Self::IoWrite(handle) => handle.write_fmt(args).map_err(Into::into), + Self::FmtWrite(handle) => handle.write_fmt(args).map_err(Into::into), + } + } +} diff --git a/src/pretty_printer.rs b/src/pretty_printer.rs index eb123ea3..4979bab5 100644 --- a/src/pretty_printer.rs +++ b/src/pretty_printer.rs @@ -10,6 +10,7 @@ use crate::{ error::Result, input, line_range::{HighlightedLineRanges, LineRange, LineRanges}, + output::OutputHandle, style::StyleComponent, StripAnsiMode, SyntaxMapping, WrappingMode, }; @@ -245,7 +246,9 @@ impl<'a> PrettyPrinter<'a> { self } - /// Specify the highlighting theme + /// Specify the highlighting theme. + /// You can use [`crate::theme::theme`] to pick a theme based on user preferences + /// and the terminal's background color. pub fn theme(&mut self, theme: impl AsRef) -> &mut Self { self.config.theme = theme.as_ref().to_owned(); self @@ -279,6 +282,11 @@ impl<'a> PrettyPrinter<'a> { /// If you want to call 'print' multiple times, you have to call the appropriate /// input_* methods again. pub fn print(&mut self) -> Result { + self.print_with_writer(None::<&mut dyn std::fmt::Write>) + } + + /// Pretty-print all specified inputs to a specified writer. + pub fn print_with_writer(&mut self, writer: Option) -> Result { let highlight_lines = std::mem::take(&mut self.highlighted_lines); self.config.highlighted_lines = HighlightedLineRanges(LineRanges::from(highlight_lines)); self.config.term_width = self @@ -315,7 +323,16 @@ impl<'a> PrettyPrinter<'a> { // Run the controller let controller = Controller::new(&self.config, &self.assets); - controller.run(inputs.into_iter().map(|i| i.into()).collect(), None) + + // If writer is provided, pass it to the controller, otherwise pass None + if let Some(mut w) = writer { + controller.run( + inputs.into_iter().map(|i| i.into()).collect(), + Some(OutputHandle::FmtWrite(&mut w)), + ) + } else { + controller.run(inputs.into_iter().map(|i| i.into()).collect(), None) + } } } diff --git a/src/printer.rs b/src/printer.rs index 64e89e76..369431ef 100644 --- a/src/printer.rs +++ b/src/printer.rs @@ -1,5 +1,3 @@ -use std::fmt; -use std::io; use std::vec::Vec; use nu_ansi_term::Color::{Fixed, Green, Red, Yellow}; @@ -17,6 +15,7 @@ use content_inspector::ContentType; use encoding_rs::{UTF_16BE, UTF_16LE}; +use unicode_segmentation::UnicodeSegmentation; use unicode_width::UnicodeWidthChar; use crate::assets::{HighlightingAssets, SyntaxReferenceInSet}; @@ -29,12 +28,14 @@ use crate::diff::LineChanges; use crate::error::*; use crate::input::OpenedInput; use crate::line_range::{MaxBufferedLineNumber, RangeCheckResult}; +use crate::output::OutputHandle; use crate::preprocessor::strip_ansi; use crate::preprocessor::{expand_tabs, replace_nonprintable}; 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 { @@ -67,20 +68,6 @@ const EMPTY_SYNTECT_STYLE: syntect::highlighting::Style = syntect::highlighting: font_style: FontStyle::empty(), }; -pub enum OutputHandle<'a> { - IoWrite(&'a mut dyn io::Write), - FmtWrite(&'a mut dyn fmt::Write), -} - -impl<'a> OutputHandle<'a> { - fn write_fmt(&mut self, args: fmt::Arguments<'_>) -> Result<()> { - match self { - Self::IoWrite(handle) => handle.write_fmt(args).map_err(Into::into), - Self::FmtWrite(handle) => handle.write_fmt(args).map_err(Into::into), - } - } -} - pub(crate) trait Printer { fn print_header( &mut self, @@ -116,7 +103,7 @@ impl<'a> SimplePrinter<'a> { } } -impl<'a> Printer for SimplePrinter<'a> { +impl Printer for SimplePrinter<'_> { fn print_header( &mut self, _handle: &mut OutputHandle, @@ -145,7 +132,7 @@ impl<'a> Printer for SimplePrinter<'a> { // 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') + .trim_end_matches(['\r', '\n']) .is_empty() { self.consecutive_empty_lines += 1; @@ -268,9 +255,10 @@ impl<'a> InteractivePrinter<'a> { let is_printing_binary = input .reader .content_type - .map_or(false, |c| c.is_binary() && !config.show_nonprintable); + .is_some_and(|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 { @@ -403,14 +391,18 @@ impl<'a> InteractivePrinter<'a> { handle: &mut OutputHandle, content: &str, ) -> Result<()> { - let mut content = content; let content_width = self.config.term_width - self.get_header_component_indent_length(); - while content.len() > content_width { - let (content_line, remaining) = content.split_at(content_width); - self.print_header_component_with_indent(handle, content_line)?; - content = remaining; + if content.chars().count() <= content_width { + return self.print_header_component_with_indent(handle, content); } - self.print_header_component_with_indent(handle, content) + + let mut content_graphemes: Vec<&str> = content.graphemes(true).collect(); + while content_graphemes.len() > content_width { + let (content_line, remaining) = content_graphemes.split_at(content_width); + self.print_header_component_with_indent(handle, content_line.join("").as_str())?; + content_graphemes = remaining.iter().cloned().collect(); + } + self.print_header_component_with_indent(handle, content_graphemes.join("").as_str()) } fn highlight_regions_for_line<'b>( @@ -432,7 +424,7 @@ impl<'a> InteractivePrinter<'a> { .highlight_line(for_highlighting, highlighter_from_set.syntax_set)?; if too_long { - highlighted_line[0].1 = &line; + highlighted_line[0].1 = line; } Ok(highlighted_line) @@ -448,7 +440,7 @@ impl<'a> InteractivePrinter<'a> { } } -impl<'a> Printer for InteractivePrinter<'a> { +impl Printer for InteractivePrinter<'_> { fn print_header( &mut self, handle: &mut OutputHandle, @@ -460,7 +452,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 \ @@ -541,7 +536,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.is_some_and(|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, '┴')?; @@ -553,7 +551,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.is_some_and(|c| c.is_text()) + || self.config.show_nonprintable + || matches!(self.config.binary, BinaryBehavior::AsText)) { self.print_horizontal_line(handle, '┴') } else { @@ -602,7 +602,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, @@ -635,7 +637,7 @@ impl<'a> Printer for InteractivePrinter<'a> { // Skip squeezed lines. if let Some(squeeze_limit) = self.config.squeeze_lines { - if line.trim_end_matches(|c| c == '\r' || c == '\n').is_empty() { + if line.trim_end_matches(['\r', '\n']).is_empty() { self.consecutive_empty_lines += 1; if self.consecutive_empty_lines > squeeze_limit { return Ok(()); @@ -692,7 +694,7 @@ impl<'a> Printer for InteractivePrinter<'a> { // Regular text. EscapeSequence::Text(text) => { let text = self.preprocess(text, &mut cursor_total); - let text_trimmed = text.trim_end_matches(|c| c == '\r' || c == '\n'); + let text_trimmed = text.trim_end_matches(['\r', '\n']); write!( handle, @@ -746,10 +748,8 @@ impl<'a> Printer for InteractivePrinter<'a> { match chunk { // Regular text. EscapeSequence::Text(text) => { - let text = self.preprocess( - text.trim_end_matches(|c| c == '\r' || c == '\n'), - &mut cursor_total, - ); + let text = self + .preprocess(text.trim_end_matches(['\r', '\n']), &mut cursor_total); let mut max_width = cursor_max - cursor; diff --git a/src/style.rs b/src/style.rs index b8d8b09f..d6343c94 100644 --- a/src/style.rs +++ b/src/style.rs @@ -225,7 +225,7 @@ impl FromStr for StyleComponentList { fn from_str(s: &str) -> Result { Ok(StyleComponentList( s.split(",") - .map(|s| ComponentAction::extract_from_str(s)) // If the component starts with "-", it's meant to be removed + .map(ComponentAction::extract_from_str) // If the component starts with "-", it's meant to be removed .map(|(a, s)| Ok((a, StyleComponent::from_str(s)?))) .collect::>>()?, )) diff --git a/src/syntax_mapping.rs b/src/syntax_mapping.rs index a149f9bb..0cd2d655 100644 --- a/src/syntax_mapping.rs +++ b/src/syntax_mapping.rs @@ -61,7 +61,7 @@ pub struct SyntaxMapping<'a> { halt_glob_build: Arc, } -impl<'a> Drop for SyntaxMapping<'a> { +impl Drop for SyntaxMapping<'_> { fn drop(&mut self) { // signal the offload thread to halt early self.halt_glob_build.store(true, Ordering::Relaxed); @@ -153,7 +153,7 @@ impl<'a> SyntaxMapping<'a> { if glob.is_match_candidate(&candidate) || candidate_filename .as_ref() - .map_or(false, |filename| glob.is_match_candidate(filename)) + .is_some_and(|filename| glob.is_match_candidate(filename)) { return Some(*syntax); } diff --git a/src/syntax_mapping/builtins/common/50-citation.toml b/src/syntax_mapping/builtins/common/50-citation.toml new file mode 100644 index 00000000..aa06b5b9 --- /dev/null +++ b/src/syntax_mapping/builtins/common/50-citation.toml @@ -0,0 +1,2 @@ +[mappings] +"YAML" = ["CITATION.cff"] diff --git a/src/syntax_mapping/builtins/common/50-diff.toml b/src/syntax_mapping/builtins/common/50-diff.toml new file mode 100644 index 00000000..2998d9c5 --- /dev/null +++ b/src/syntax_mapping/builtins/common/50-diff.toml @@ -0,0 +1,3 @@ +# .debdiff is the extension used for diffs in Debian packaging +[mappings] +"Diff" = ["*.debdiff"] diff --git a/src/syntax_mapping/builtins/common/50-dotnet-xml.toml b/src/syntax_mapping/builtins/common/50-dotnet-xml.toml new file mode 100644 index 00000000..1e3a860a --- /dev/null +++ b/src/syntax_mapping/builtins/common/50-dotnet-xml.toml @@ -0,0 +1,2 @@ +[mappings] +"XML" = ["*.csproj", "*.vbproj", "*.props", "*.targets"] diff --git a/src/syntax_mapping/builtins/common/50-json.toml b/src/syntax_mapping/builtins/common/50-json.toml index 7d33b6fe..6b3252e8 100644 --- a/src/syntax_mapping/builtins/common/50-json.toml +++ b/src/syntax_mapping/builtins/common/50-json.toml @@ -1,3 +1,3 @@ # JSON Lines is a simple variation of JSON #2535 [mappings] -"JSON" = ["*.jsonl", "*.jsonc", "*.jsonld"] +"JSON" = ["*.jsonl", "*.jsonc", "*.jsonld", "*.geojson", "*.ndjson"] diff --git a/src/syntax_mapping/builtins/common/50-markdown.toml b/src/syntax_mapping/builtins/common/50-markdown.toml new file mode 100644 index 00000000..aa0531d2 --- /dev/null +++ b/src/syntax_mapping/builtins/common/50-markdown.toml @@ -0,0 +1,2 @@ +[mappings] +"Markdown" = ["*.mkd"] diff --git a/src/syntax_mapping/builtins/common/50-nix.toml b/src/syntax_mapping/builtins/common/50-nix.toml new file mode 100644 index 00000000..e2d2fcbb --- /dev/null +++ b/src/syntax_mapping/builtins/common/50-nix.toml @@ -0,0 +1,2 @@ +[mappings] +"JSON" = ["flake.lock"] diff --git a/src/syntax_mapping/builtins/linux/50-kubernetes.toml b/src/syntax_mapping/builtins/linux/50-kubernetes.toml new file mode 100644 index 00000000..6a81a35a --- /dev/null +++ b/src/syntax_mapping/builtins/linux/50-kubernetes.toml @@ -0,0 +1,2 @@ +[mappings] +"YAML" = ["/etc/kubernetes/*.conf"] diff --git a/src/syntax_mapping/builtins/linux/50-pacman.toml b/src/syntax_mapping/builtins/linux/50-pacman.toml index 655118c5..2f4ee71f 100644 --- a/src/syntax_mapping/builtins/linux/50-pacman.toml +++ b/src/syntax_mapping/builtins/linux/50-pacman.toml @@ -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", +] diff --git a/src/syntax_mapping/builtins/linux/50-paru.toml b/src/syntax_mapping/builtins/linux/50-paru.toml new file mode 100644 index 00000000..2706a36e --- /dev/null +++ b/src/syntax_mapping/builtins/linux/50-paru.toml @@ -0,0 +1,6 @@ +# See https://github.com/Morganamilo/paru/blob/master/man/paru.conf.5 +[mappings] +"INI" = [ + "${PARU_CONF}", + "paru.conf", +] diff --git a/src/syntax_mapping/builtins/unix-family/50-apache.toml b/src/syntax_mapping/builtins/unix-family/50-apache.toml index dfb920f3..7394dafc 100644 --- a/src/syntax_mapping/builtins/unix-family/50-apache.toml +++ b/src/syntax_mapping/builtins/unix-family/50-apache.toml @@ -1,2 +1,2 @@ [mappings] -"Apache Conf" = ["/etc/apache2/**/*.conf", "/etc/apache2/sites-*/**/*"] +"Apache Conf" = ["/etc/apache2/**/*.conf", "/etc/apache2/sites-*/**/*", "/etc/httpd/conf/**/*.conf"] diff --git a/src/syntax_mapping/builtins/unix-family/50-shell.toml b/src/syntax_mapping/builtins/unix-family/50-shell.toml index d015ca81..cd59a84e 100644 --- a/src/syntax_mapping/builtins/unix-family/50-shell.toml +++ b/src/syntax_mapping/builtins/unix-family/50-shell.toml @@ -2,4 +2,24 @@ "Bourne Again Shell (bash)" = [ # used by lots of shells "/etc/profile", + + "bashrc", + "*.bashrc", + "bash_profile", + "*.bash_profile", + "bash_login", + "*.bash_login", + "bash_logout", + "*.bash_logout", + + "zshrc", + "*.zshrc", + "zprofile", + "*.zprofile", + "zlogin", + "*.zlogin", + "zlogout", + "*.zlogout", + "zshenv", + "*.zshenv" ] diff --git a/src/theme.rs b/src/theme.rs new file mode 100644 index 00000000..b2903b86 --- /dev/null +++ b/src/theme.rs @@ -0,0 +1,570 @@ +//! Utilities for choosing an appropriate theme for syntax highlighting. + +use std::convert::Infallible; +use std::fmt; +use std::io::IsTerminal as _; +use std::str::FromStr; + +/// Environment variable names. +pub mod env { + /// See [`crate::theme::ThemeOptions::theme`]. + pub const BAT_THEME: &str = "BAT_THEME"; + /// See [`crate::theme::ThemeOptions::theme_dark`]. + pub const BAT_THEME_DARK: &str = "BAT_THEME_DARK"; + /// See [`crate::theme::ThemeOptions::theme_light`]. + pub const BAT_THEME_LIGHT: &str = "BAT_THEME_LIGHT"; +} + +/// Chooses an appropriate theme or falls back to a default theme +/// based on the user-provided options and the color scheme of the terminal. +/// +/// Intentionally returns a [`ThemeResult`] instead of a simple string so +/// that downstream consumers such as `delta` can easily apply their own +/// default theme and can use the detected color scheme elsewhere. +pub fn theme(options: ThemeOptions) -> ThemeResult { + theme_impl(options, &TerminalColorSchemeDetector) +} + +/// The default theme, suitable for the given color scheme. +/// Use [`theme`] if you want to automatically detect the color scheme from the terminal. +pub const fn default_theme(color_scheme: ColorScheme) -> &'static str { + match color_scheme { + ColorScheme::Dark => "Monokai Extended", + ColorScheme::Light => "Monokai Extended Light", + } +} + +/// Detects the color scheme from the terminal. +pub fn color_scheme(when: DetectColorScheme) -> Option { + color_scheme_impl(when, &TerminalColorSchemeDetector) +} + +/// Options for configuring the theme used for syntax highlighting. +/// Used together with [`theme`]. +#[derive(Debug, Clone, Default, PartialEq, Eq)] +pub struct ThemeOptions { + /// Configures how the theme is chosen. If set to a [`ThemePreference::Fixed`] value, + /// then the given theme is used regardless of the terminal's background color. + /// This corresponds with the `BAT_THEME` environment variable and the `--theme` option. + pub theme: ThemePreference, + /// The theme to use in case the terminal uses a dark background with light text. + /// This corresponds with the `BAT_THEME_DARK` environment variable and the `--theme-dark` option. + pub theme_dark: Option, + /// The theme to use in case the terminal uses a light background with dark text. + /// This corresponds with the `BAT_THEME_LIGHT` environment variable and the `--theme-light` option. + pub theme_light: Option, +} + +/// What theme should `bat` use? +/// +/// The easiest way to construct this is from a string: +/// ``` +/// # use bat::theme::{ThemePreference, DetectColorScheme}; +/// let preference = ThemePreference::new("auto:system"); +/// assert_eq!(ThemePreference::Auto(DetectColorScheme::System), preference); +/// ``` +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub enum ThemePreference { + /// Choose between [`ThemeOptions::theme_dark`] and [`ThemeOptions::theme_light`] + /// based on the terminal's color scheme. + Auto(DetectColorScheme), + /// Always use the same theme regardless of the terminal's color scheme. + Fixed(ThemeName), + /// Use a dark theme. + Dark, + /// Use a light theme. + Light, +} + +impl Default for ThemePreference { + fn default() -> Self { + ThemePreference::Auto(Default::default()) + } +} + +impl ThemePreference { + /// Creates a theme preference from a string. + pub fn new(s: impl Into) -> Self { + use ThemePreference::*; + let s = s.into(); + match s.as_str() { + "auto" => Auto(Default::default()), + "auto:always" => Auto(DetectColorScheme::Always), + "auto:system" => Auto(DetectColorScheme::System), + "dark" => Dark, + "light" => Light, + _ => Fixed(ThemeName::new(s)), + } + } +} + +impl FromStr for ThemePreference { + type Err = Infallible; + + fn from_str(s: &str) -> Result { + Ok(ThemePreference::new(s)) + } +} + +impl fmt::Display for ThemePreference { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + use ThemePreference::*; + match self { + Auto(DetectColorScheme::Auto) => f.write_str("auto"), + Auto(DetectColorScheme::Always) => f.write_str("auto:always"), + Auto(DetectColorScheme::System) => f.write_str("auto:system"), + Fixed(theme) => theme.fmt(f), + Dark => f.write_str("dark"), + Light => f.write_str("light"), + } + } +} + +/// The name of a theme or the default theme. +/// +/// ``` +/// # use bat::theme::ThemeName; +/// assert_eq!(ThemeName::Default, ThemeName::new("default")); +/// assert_eq!(ThemeName::Named("example".to_string()), ThemeName::new("example")); +/// ``` +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub enum ThemeName { + Named(String), + Default, +} + +impl ThemeName { + /// Creates a theme name from a string. + pub fn new(s: impl Into) -> Self { + let s = s.into(); + if s == "default" { + ThemeName::Default + } else { + ThemeName::Named(s) + } + } +} + +impl FromStr for ThemeName { + type Err = Infallible; + + fn from_str(s: &str) -> Result { + Ok(ThemeName::new(s)) + } +} + +impl fmt::Display for ThemeName { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + ThemeName::Named(t) => f.write_str(t), + ThemeName::Default => f.write_str("default"), + } + } +} + +#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)] +pub enum DetectColorScheme { + /// Only query the terminal for its colors when appropriate (i.e. when the output is not redirected). + #[default] + Auto, + /// Always query the terminal for its colors. + Always, + /// Detect the system-wide dark/light preference (macOS only). + System, +} + +/// The color scheme used to pick a fitting theme. Defaults to [`ColorScheme::Dark`]. +#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)] +pub enum ColorScheme { + #[default] + Dark, + Light, +} + +/// The resolved theme and the color scheme as determined from +/// the terminal, OS or fallback. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct ThemeResult { + /// The theme selected according to the [`ThemeOptions`]. + pub theme: ThemeName, + /// Either the user's chosen color scheme, the terminal's color scheme, the OS's + /// color scheme or `None` if the color scheme was not detected because the user chose a fixed theme. + pub color_scheme: Option, +} + +impl fmt::Display for ThemeResult { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match &self.theme { + ThemeName::Named(name) => f.write_str(name), + ThemeName::Default => f.write_str(default_theme(self.color_scheme.unwrap_or_default())), + } + } +} + +fn theme_impl(options: ThemeOptions, detector: &dyn ColorSchemeDetector) -> ThemeResult { + // Implementation note: This function is mostly pure (i.e. it has no side effects) for the sake of testing. + // All the side effects (e.g. querying the terminal for its colors) are performed in the detector. + match options.theme { + ThemePreference::Fixed(theme) => ThemeResult { + theme, + color_scheme: None, + }, + ThemePreference::Dark => choose_theme_opt(Some(ColorScheme::Dark), options), + ThemePreference::Light => choose_theme_opt(Some(ColorScheme::Light), options), + ThemePreference::Auto(when) => choose_theme_opt(color_scheme_impl(when, detector), options), + } +} + +fn choose_theme_opt(color_scheme: Option, options: ThemeOptions) -> ThemeResult { + ThemeResult { + color_scheme, + theme: color_scheme + .and_then(|c| choose_theme(options, c)) + .unwrap_or(ThemeName::Default), + } +} + +fn choose_theme(options: ThemeOptions, color_scheme: ColorScheme) -> Option { + match color_scheme { + ColorScheme::Dark => options.theme_dark, + ColorScheme::Light => options.theme_light, + } +} + +fn color_scheme_impl( + when: DetectColorScheme, + detector: &dyn ColorSchemeDetector, +) -> Option { + let should_detect = match when { + DetectColorScheme::Auto => detector.should_detect(), + DetectColorScheme::Always => true, + DetectColorScheme::System => return color_scheme_from_system(), + }; + should_detect.then(|| detector.detect()).flatten() +} + +trait ColorSchemeDetector { + fn should_detect(&self) -> bool; + + fn detect(&self) -> Option; +} + +struct TerminalColorSchemeDetector; + +impl ColorSchemeDetector for TerminalColorSchemeDetector { + fn should_detect(&self) -> bool { + // Querying the terminal for its colors via OSC 10 / OSC 11 requires "exclusive" access + // since we read/write from the terminal and enable/disable raw mode. + // This causes race conditions with pagers such as less when they are attached to the + // same terminal as us. + // + // This is usually only an issue when the output is manually piped to a pager. + // For example: `bat Cargo.toml | less`. + // Otherwise, if we start the pager ourselves, then there's no race condition + // since the pager is started *after* the color is detected. + std::io::stdout().is_terminal() + } + + fn detect(&self) -> Option { + use terminal_colorsaurus::{color_scheme, ColorScheme as ColorsaurusScheme, QueryOptions}; + match color_scheme(QueryOptions::default()).ok()? { + ColorsaurusScheme::Dark => Some(ColorScheme::Dark), + ColorsaurusScheme::Light => Some(ColorScheme::Light), + } + } +} + +#[cfg(not(target_os = "macos"))] +fn color_scheme_from_system() -> Option { + crate::bat_warning!( + "Theme 'auto:system' is only supported on macOS, \ + using default." + ); + None +} + +#[cfg(target_os = "macos")] +fn color_scheme_from_system() -> Option { + const PREFERENCES_FILE: &str = "Library/Preferences/.GlobalPreferences.plist"; + const STYLE_KEY: &str = "AppleInterfaceStyle"; + + let preferences_file = home::home_dir() + .map(|home| home.join(PREFERENCES_FILE)) + .expect("Could not get home directory"); + + match plist::Value::from_file(preferences_file).map(|file| file.into_dictionary()) { + Ok(Some(preferences)) => match preferences.get(STYLE_KEY).and_then(|val| val.as_string()) { + Some("Dark") => Some(ColorScheme::Dark), + // If the key does not exist, then light theme is currently in use. + Some(_) | None => Some(ColorScheme::Light), + }, + // Unreachable, in theory. All macOS users have a home directory and preferences file setup. + Ok(None) | Err(_) => None, + } +} + +#[cfg(test)] +impl ColorSchemeDetector for Option { + fn should_detect(&self) -> bool { + true + } + + fn detect(&self) -> Option { + *self + } +} + +#[cfg(test)] +mod tests { + use super::ColorScheme::*; + use super::*; + use std::cell::Cell; + use std::iter; + + mod color_scheme_detection { + use super::*; + + #[test] + fn not_called_for_dark_or_light() { + for theme in [ThemePreference::Dark, ThemePreference::Light] { + let detector = DetectorStub::should_detect(Some(Dark)); + let options = ThemeOptions { + theme, + ..Default::default() + }; + _ = theme_impl(options, &detector); + assert!(!detector.was_called.get()); + } + } + + #[test] + fn called_for_always() { + let detectors = [ + DetectorStub::should_detect(Some(Dark)), + DetectorStub::should_not_detect(), + ]; + for detector in detectors { + let options = ThemeOptions { + theme: ThemePreference::Auto(DetectColorScheme::Always), + ..Default::default() + }; + _ = theme_impl(options, &detector); + assert!(detector.was_called.get()); + } + } + + #[test] + fn called_for_auto_if_should_detect() { + let detector = DetectorStub::should_detect(Some(Dark)); + _ = theme_impl(ThemeOptions::default(), &detector); + assert!(detector.was_called.get()); + } + + #[test] + fn not_called_for_auto_if_not_should_detect() { + let detector = DetectorStub::should_not_detect(); + _ = theme_impl(ThemeOptions::default(), &detector); + assert!(!detector.was_called.get()); + } + } + + mod precedence { + use super::*; + + #[test] + fn theme_is_preferred_over_light_or_dark_themes() { + for color_scheme in optional(color_schemes()) { + for options in [ + ThemeOptions { + theme: ThemePreference::Fixed(ThemeName::Named("Theme".to_string())), + ..Default::default() + }, + ThemeOptions { + theme: ThemePreference::Fixed(ThemeName::Named("Theme".to_string())), + theme_dark: Some(ThemeName::Named("Dark Theme".to_string())), + theme_light: Some(ThemeName::Named("Light Theme".to_string())), + }, + ] { + let detector = ConstantDetector(color_scheme); + assert_eq!("Theme", theme_impl(options, &detector).to_string()); + } + } + } + + #[test] + fn detector_is_not_called_if_theme_is_present() { + let options = ThemeOptions { + theme: ThemePreference::Fixed(ThemeName::Named("Theme".to_string())), + ..Default::default() + }; + let detector = DetectorStub::should_detect(Some(Dark)); + _ = theme_impl(options, &detector); + assert!(!detector.was_called.get()); + } + } + + mod default_theme { + use super::*; + + #[test] + fn default_dark_if_unable_to_detect_color_scheme() { + let detector = ConstantDetector(None); + assert_eq!( + default_theme(ColorScheme::Dark), + theme_impl(ThemeOptions::default(), &detector).to_string() + ); + } + + // For backwards compatibility, if the default theme is requested + // explicitly through BAT_THEME, we always pick the default dark theme. + #[test] + fn default_dark_if_requested_explicitly_through_theme() { + for color_scheme in optional(color_schemes()) { + let options = ThemeOptions { + theme: ThemePreference::Fixed(ThemeName::Default), + ..Default::default() + }; + let detector = ConstantDetector(color_scheme); + assert_eq!( + default_theme(ColorScheme::Dark), + theme_impl(options, &detector).to_string() + ); + } + } + + #[test] + fn varies_depending_on_color_scheme() { + for color_scheme in color_schemes() { + for options in [ + ThemeOptions::default(), + ThemeOptions { + theme_dark: Some(ThemeName::Default), + theme_light: Some(ThemeName::Default), + ..Default::default() + }, + ] { + let detector = ConstantDetector(Some(color_scheme)); + assert_eq!( + default_theme(color_scheme), + theme_impl(options, &detector).to_string() + ); + } + } + } + } + + mod choosing { + use super::*; + + #[test] + fn chooses_default_theme_if_unknown() { + let options = ThemeOptions { + theme_dark: Some(ThemeName::Named("Dark".to_string())), + theme_light: Some(ThemeName::Named("Light".to_string())), + ..Default::default() + }; + let detector = ConstantDetector(None); + assert_eq!( + default_theme(ColorScheme::default()), + theme_impl(options, &detector).to_string() + ); + } + + #[test] + fn chooses_dark_theme_if_dark_or_unknown() { + let options = ThemeOptions { + theme_dark: Some(ThemeName::Named("Dark".to_string())), + theme_light: Some(ThemeName::Named("Light".to_string())), + ..Default::default() + }; + let detector = ConstantDetector(Some(ColorScheme::Dark)); + assert_eq!("Dark", theme_impl(options, &detector).to_string()); + } + + #[test] + fn chooses_light_theme_if_light() { + let options = ThemeOptions { + theme_dark: Some(ThemeName::Named("Dark".to_string())), + theme_light: Some(ThemeName::Named("Light".to_string())), + ..Default::default() + }; + let detector = ConstantDetector(Some(ColorScheme::Light)); + assert_eq!("Light", theme_impl(options, &detector).to_string()); + } + } + + mod theme_preference { + use super::*; + + #[test] + fn values_roundtrip_via_display() { + let prefs = [ + ThemePreference::Auto(DetectColorScheme::Auto), + ThemePreference::Auto(DetectColorScheme::Always), + ThemePreference::Auto(DetectColorScheme::System), + ThemePreference::Fixed(ThemeName::Default), + ThemePreference::Fixed(ThemeName::new("foo")), + ThemePreference::Dark, + ThemePreference::Light, + ]; + for pref in prefs { + assert_eq!(pref, ThemePreference::new(pref.to_string())); + } + } + } + + struct DetectorStub { + should_detect: bool, + color_scheme: Option, + was_called: Cell, + } + + impl DetectorStub { + fn should_detect(color_scheme: Option) -> Self { + DetectorStub { + should_detect: true, + color_scheme, + was_called: Cell::default(), + } + } + + fn should_not_detect() -> Self { + DetectorStub { + should_detect: false, + color_scheme: None, + was_called: Cell::default(), + } + } + } + + impl ColorSchemeDetector for DetectorStub { + fn should_detect(&self) -> bool { + self.should_detect + } + + fn detect(&self) -> Option { + self.was_called.set(true); + self.color_scheme + } + } + + struct ConstantDetector(Option); + + impl ColorSchemeDetector for ConstantDetector { + fn should_detect(&self) -> bool { + true + } + + fn detect(&self) -> Option { + self.0 + } + } + + fn optional(value: impl Iterator) -> impl Iterator> { + value.map(Some).chain(iter::once(None)) + } + + fn color_schemes() -> impl Iterator { + [Dark, Light].into_iter() + } +} diff --git a/src/vscreen.rs b/src/vscreen.rs index 9e29f9cc..06cc038a 100644 --- a/src/vscreen.rs +++ b/src/vscreen.rs @@ -360,10 +360,10 @@ pub struct EscapeSequenceOffsetsIterator<'a> { impl<'a> EscapeSequenceOffsetsIterator<'a> { pub fn new(text: &'a str) -> EscapeSequenceOffsetsIterator<'a> { - return EscapeSequenceOffsetsIterator { + EscapeSequenceOffsetsIterator { text, chars: text.char_indices().peekable(), - }; + } } /// Takes values from the iterator while the predicate returns true. @@ -539,7 +539,7 @@ impl<'a> EscapeSequenceOffsetsIterator<'a> { } } -impl<'a> Iterator for EscapeSequenceOffsetsIterator<'a> { +impl Iterator for EscapeSequenceOffsetsIterator<'_> { type Item = EscapeSequenceOffsets; fn next(&mut self) -> Option { match self.chars.peek() { @@ -564,10 +564,10 @@ pub struct EscapeSequenceIterator<'a> { impl<'a> EscapeSequenceIterator<'a> { pub fn new(text: &'a str) -> EscapeSequenceIterator<'a> { - return EscapeSequenceIterator { + EscapeSequenceIterator { text, offset_iter: EscapeSequenceOffsetsIterator::new(text), - }; + } } } diff --git a/tests/examples/test.A—B가 b/tests/examples/test.A—B가 new file mode 100644 index 00000000..e69de29b diff --git a/tests/github-actions.rs b/tests/github-actions.rs index c902f10b..d697ddf8 100644 --- a/tests/github-actions.rs +++ b/tests/github-actions.rs @@ -35,13 +35,7 @@ fn all_jobs_not_missing_any_jobs() { .as_mapping() .unwrap() .keys() - .filter_map(|k| { - if exceptions.contains(&k.as_str().unwrap_or_default()) { - None - } else { - Some(k) - } - }) + .filter(|k| !exceptions.contains(&k.as_str().unwrap_or_default())) .map(ToOwned::to_owned) .collect::>(); diff --git a/tests/integration_tests.rs b/tests/integration_tests.rs index 1502c7c1..5a97c517 100644 --- a/tests/integration_tests.rs +++ b/tests/integration_tests.rs @@ -9,7 +9,6 @@ use tempfile::tempdir; mod unix { pub use std::fs::File; pub use std::io::{self, Write}; - pub use std::os::unix::io::FromRawFd; pub use std::path::PathBuf; pub use std::process::Stdio; pub use std::thread; @@ -314,11 +313,8 @@ fn squeeze_limit_line_numbers() { #[test] fn list_themes_with_colors() { - #[cfg(target_os = "macos")] - let default_theme_chunk = "Monokai Extended Light\x1B[0m (default)"; - - #[cfg(not(target_os = "macos"))] let default_theme_chunk = "Monokai Extended\x1B[0m (default)"; + let default_light_theme_chunk = "Monokai Extended Light\x1B[0m (default light)"; bat() .arg("--color=always") @@ -327,34 +323,50 @@ fn list_themes_with_colors() { .success() .stdout(predicate::str::contains("DarkNeon").normalize()) .stdout(predicate::str::contains(default_theme_chunk).normalize()) + .stdout(predicate::str::contains(default_light_theme_chunk).normalize()) .stdout(predicate::str::contains("Output the square of a number.").normalize()); } #[test] fn list_themes_without_colors() { - #[cfg(target_os = "macos")] - let default_theme_chunk = "Monokai Extended Light (default)"; - - #[cfg(not(target_os = "macos"))] let default_theme_chunk = "Monokai Extended (default)"; + let default_light_theme_chunk = "Monokai Extended Light (default light)"; bat() .arg("--color=never") + .arg("--decorations=always") // trick bat into setting `Config::loop_through` to false .arg("--list-themes") .assert() .success() .stdout(predicate::str::contains("DarkNeon").normalize()) - .stdout(predicate::str::contains(default_theme_chunk).normalize()); + .stdout(predicate::str::contains(default_theme_chunk).normalize()) + .stdout(predicate::str::contains(default_light_theme_chunk).normalize()); } #[test] -#[cfg_attr(any(not(feature = "git"), target_os = "windows"), ignore)] +fn list_themes_to_piped_output() { + bat().arg("--list-themes").assert().success().stdout( + predicate::str::contains("(default)") + .not() + .and(predicate::str::contains("(default light)").not()) + .and(predicate::str::contains("(default dark)").not()), + ); +} + +#[test] +#[cfg_attr( + any(not(feature = "git"), feature = "lessopen", target_os = "windows"), + ignore +)] fn short_help() { test_help("-h", "../doc/short-help.txt"); } #[test] -#[cfg_attr(any(not(feature = "git"), target_os = "windows"), ignore)] +#[cfg_attr( + any(not(feature = "git"), feature = "lessopen", target_os = "windows"), + ignore +)] fn long_help() { test_help("--help", "../doc/long-help.txt"); } @@ -445,9 +457,10 @@ fn no_args_doesnt_break() { // as the slave end of a pseudo terminal. Although both point to the same "file", bat should // not exit, because in this case it is safe to read and write to the same fd, which is why // this test exists. + let OpenptyResult { master, slave } = openpty(None, None).expect("Couldn't open pty."); - let mut master = unsafe { File::from_raw_fd(master) }; - let stdin_file = unsafe { File::from_raw_fd(slave) }; + let mut master = File::from(master); + let stdin_file = File::from(slave); let stdout_file = stdin_file.try_clone().unwrap(); let stdin = Stdio::from(stdin_file); let stdout = Stdio::from(stdout_file); @@ -455,6 +468,7 @@ fn no_args_doesnt_break() { let mut child = bat_raw_command() .stdin(stdin) .stdout(stdout) + .env("TERM", "dumb") // Suppresses color detection .spawn() .expect("Failed to start."); @@ -1050,6 +1064,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() @@ -1601,6 +1640,17 @@ oken .stderr(""); } +#[test] +fn header_narrow_terminal_with_multibyte_chars() { + bat() + .arg("--terminal-width=30") + .arg("--decorations=always") + .arg("test.A—B가") + .assert() + .success() + .stderr(""); +} + #[test] #[cfg(feature = "git")] // Expected output assumes git is enabled fn header_default() { @@ -1833,7 +1883,7 @@ fn do_not_panic_regression_tests() { ] { bat() .arg("--color=always") - .arg(&format!("regression_tests/{filename}")) + .arg(format!("regression_tests/{filename}")) .assert() .success(); } @@ -1846,7 +1896,7 @@ fn do_not_detect_different_syntax_for_stdin_and_files() { let cmd_for_file = bat() .arg("--color=always") .arg("--map-syntax=*.js:Markdown") - .arg(&format!("--file-name={file}")) + .arg(format!("--file-name={file}")) .arg("--style=plain") .arg(file) .assert() @@ -1856,7 +1906,7 @@ fn do_not_detect_different_syntax_for_stdin_and_files() { .arg("--color=always") .arg("--map-syntax=*.js:Markdown") .arg("--style=plain") - .arg(&format!("--file-name={file}")) + .arg(format!("--file-name={file}")) .pipe_stdin(Path::new(EXAMPLES_DIR).join(file)) .unwrap() .assert() @@ -1875,7 +1925,7 @@ fn no_first_line_fallback_when_mapping_to_invalid_syntax() { bat() .arg("--color=always") .arg("--map-syntax=*.invalid-syntax:InvalidSyntax") - .arg(&format!("--file-name={file}")) + .arg(format!("--file-name={file}")) .arg("--style=plain") .arg(file) .assert() @@ -1969,6 +2019,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() @@ -2257,6 +2317,46 @@ fn theme_arg_overrides_env_withconfig() { .stderr(""); } +#[test] +fn theme_light_env_var_is_respected() { + bat() + .env("BAT_THEME_LIGHT", "Coldark-Cold") + .env("COLORTERM", "truecolor") + .arg("--theme=light") + .arg("--paging=never") + .arg("--color=never") + .arg("--terminal-width=80") + .arg("--wrap=never") + .arg("--decorations=always") + .arg("--style=plain") + .arg("--highlight-line=1") + .write_stdin("Lorem Ipsum") + .assert() + .success() + .stdout("\x1B[48;2;208;218;231mLorem Ipsum\x1B[0m") + .stderr(""); +} + +#[test] +fn theme_dark_env_var_is_respected() { + bat() + .env("BAT_THEME_DARK", "Coldark-Dark") + .env("COLORTERM", "truecolor") + .arg("--theme=dark") + .arg("--paging=never") + .arg("--color=never") + .arg("--terminal-width=80") + .arg("--wrap=never") + .arg("--decorations=always") + .arg("--style=plain") + .arg("--highlight-line=1") + .write_stdin("Lorem Ipsum") + .assert() + .success() + .stdout("\x1B[48;2;33;48;67mLorem Ipsum\x1B[0m") + .stderr(""); +} + #[test] fn theme_env_overrides_config() { bat_with_config() @@ -2435,7 +2535,6 @@ fn lessopen_stdin_piped() { #[cfg(unix)] // Expected output assumed that tests are run on a Unix-like system #[cfg(feature = "lessopen")] #[test] -#[serial] // Randomly fails otherwise fn lessopen_and_lessclose_file_temp() { // This is mainly to test that $LESSCLOSE gets passed the correct file paths // In this case, the original file and the temporary file returned by $LESSOPEN @@ -2453,7 +2552,6 @@ fn lessopen_and_lessclose_file_temp() { #[cfg(unix)] // Expected output assumed that tests are run on a Unix-like system #[cfg(feature = "lessopen")] #[test] -#[serial] // Randomly fails otherwise fn lessopen_and_lessclose_file_piped() { // This is mainly to test that $LESSCLOSE gets passed the correct file paths // In these cases, the original file and a dash @@ -2480,8 +2578,6 @@ fn lessopen_and_lessclose_file_piped() { #[cfg(unix)] // Expected output assumed that tests are run on a Unix-like system #[cfg(feature = "lessopen")] #[test] -#[serial] // Randomly fails otherwise -#[ignore = "randomly failing on some systems"] fn lessopen_and_lessclose_stdin_temp() { // This is mainly to test that $LESSCLOSE gets passed the correct file paths // In this case, a dash and the temporary file returned by $LESSOPEN @@ -2499,7 +2595,6 @@ fn lessopen_and_lessclose_stdin_temp() { #[cfg(unix)] // Expected output assumed that tests are run on a Unix-like system #[cfg(feature = "lessopen")] #[test] -#[serial] // Randomly fails otherwise fn lessopen_and_lessclose_stdin_piped() { // This is mainly to test that $LESSCLOSE gets passed the correct file paths // In these cases, two dashes diff --git a/tests/syntax-tests/compare_highlighted_versions.py b/tests/syntax-tests/compare_highlighted_versions.py index 9cf67e46..ad142e9f 100755 --- a/tests/syntax-tests/compare_highlighted_versions.py +++ b/tests/syntax-tests/compare_highlighted_versions.py @@ -12,13 +12,15 @@ def compare_highlighted_versions(root_old, root_new): print(" -", root_old) print(" -", root_new) has_changes = False + # Used to check for newly added files that don't have a test + unknown_files = {strip_root(p) for p in glob.glob(path.join(root_new, "*", "*"))} + for path_old in glob.glob(path.join(root_old, "*", "*")): - filename = path.basename(path_old) - dirname = path.basename(path.dirname(path_old)) + rel_path = strip_root(path_old) + unknown_files.discard(rel_path) + path_new = path.join(root_new, rel_path) - path_new = path.join(root_new, dirname, filename) - - print("\n========== {}/{}".format(dirname, filename)) + print("\n========== {}".format(rel_path)) with open(path_old) as file_old: lines_old = file_old.readlines() @@ -39,11 +41,21 @@ def compare_highlighted_versions(root_old, root_new): has_changes = True else: print("No changes") - print() + for f in unknown_files: + print("\n========== {}: No fixture for this language, run update.sh".format(f)) + has_changes = True + + print() return has_changes +def strip_root(p: str) -> str: + filename = path.basename(p) + dirname = path.basename(path.dirname(p)) + return path.join(dirname, filename) + + if __name__ == "__main__": parser = argparse.ArgumentParser( description="This script compares two directories that were created " diff --git a/tests/syntax-tests/highlighted/CSV/comma-delimited.csv b/tests/syntax-tests/highlighted/CSV/comma-delimited.csv new file mode 100644 index 00000000..05285a7c --- /dev/null +++ b/tests/syntax-tests/highlighted/CSV/comma-delimited.csv @@ -0,0 +1,3 @@ +foo,bar,baz,this|that,test,colors,cycle +1.2,1.7,2.5,blah;cool,test,colors,cycle + diff --git a/tests/syntax-tests/highlighted/CSV/comma_in_quotes.csv b/tests/syntax-tests/highlighted/CSV/comma_in_quotes.csv index 9bd0da1a..8f4004a0 100644 --- a/tests/syntax-tests/highlighted/CSV/comma_in_quotes.csv +++ b/tests/syntax-tests/highlighted/CSV/comma_in_quotes.csv @@ -1,7 +1,7 @@ -first,last,address,city,zip -John,Doe,120 any st.,"Anytown, WW",08123 -a,b -1,"ha  +first,last,address,city,zip +John,Doe,120 any st.,"Anytown, WW",08123 +a,b +1,"ha  ""ha""  -ha",120 any st.,"Anytown, WW",08123 -3,4,120 any st.,"Anytown, WW",08123 +ha",120 any st.,"Anytown, WW",08123 +3,4,120 any st.,"Anytown, WW",08123 diff --git a/tests/syntax-tests/highlighted/CSV/decimals_comma_decimal_point_pipe_delimited.csv b/tests/syntax-tests/highlighted/CSV/decimals_comma_decimal_point_pipe_delimited.csv new file mode 100644 index 00000000..843264e6 --- /dev/null +++ b/tests/syntax-tests/highlighted/CSV/decimals_comma_decimal_point_pipe_delimited.csv @@ -0,0 +1,3 @@ +foo|bar|baz +1,2|1,7|2,7 +1,5|8,5|-5,5 diff --git a/tests/syntax-tests/highlighted/CSV/decimals_comma_decimal_point_semicolon_delimited.csv b/tests/syntax-tests/highlighted/CSV/decimals_comma_decimal_point_semicolon_delimited.csv new file mode 100644 index 00000000..da1b0704 --- /dev/null +++ b/tests/syntax-tests/highlighted/CSV/decimals_comma_decimal_point_semicolon_delimited.csv @@ -0,0 +1,3 @@ +foo;bar;baz +1,2;1,7;2,7 +1,5;8,5;-5,5 diff --git a/tests/syntax-tests/highlighted/CSV/simple.tsv b/tests/syntax-tests/highlighted/CSV/simple.tsv new file mode 100644 index 00000000..7dd1a9de --- /dev/null +++ b/tests/syntax-tests/highlighted/CSV/simple.tsv @@ -0,0 +1,3 @@ +foo bar baz|;, test hello world tsv +1,2 1,7 2,7 a b c "hello again" tsv +";|," ;|, baz test "hello world" tsv diff --git a/tests/syntax-tests/highlighted/GDScript/test.gd b/tests/syntax-tests/highlighted/GDScript/test.gd new file mode 100644 index 00000000..4ea498cf --- /dev/null +++ b/tests/syntax-tests/highlighted/GDScript/test.gd @@ -0,0 +1,71 @@ +extends Node + +signal custom_signal(param) + +const PI = 3.14159 + +var untyped_var = "Hello, World!" +var typed_int: int = 42 +var typed_float: float = 3.14 +var typed_string: String = "GDScript Test" +var typed_array: Array = [1, 2, 3, 4] +var typed_dict: Dictionary = {"key": "value", "number": 100} + +onready var label = $Label + +func say_hello() -> void: + print("Hello from GDScript!") + +func add_numbers(a: int, b: int = 10) -> int: + return a + b + +func process_value(value: int) -> String: + if value < 0: + return "Negative" + elif value == 0: + return "Zero" + else: + return "Positive" + +func sum_array(arr: Array) -> int: + var total: int = 0 + for num in arr: + total += num + return total + +func describe_number(num: int) -> String: + match num: + 0: + return "Zero" + 1, 2, 3: + return "Small number" + _: + return "Large number" + +func long_description() -> String: + return """This is a test file for GDScript. +It covers variables, functions, control structures, loops, signals, inner classes, +multiline strings, arrays, and dictionaries.""" + +class InnerExample: + var inner_value: int = 99 + func show_value() -> void: + print("Inner value is:", inner_value) + +func test_inner_class() -> void: + var inner = InnerExample.new() + inner.show_value() + +func trigger_signal() -> void: + emit_signal("custom_signal", "TestParam") + +func _ready() -> void: + say_hello() + var result_add = add_numbers(5) + print("Add result:", result_add) + print("Process value for -5:", process_value(-5)) + print("Sum of array [10, 20, 30]:", sum_array([10, 20, 30])) + print("Description for 2:", describe_number(2)) + print("Long description:\n", long_description()) + test_inner_class() + trigger_signal() diff --git a/tests/syntax-tests/highlighted/Idris2/test.idr b/tests/syntax-tests/highlighted/Idris2/test.idr new file mode 100644 index 00000000..04691268 --- /dev/null +++ b/tests/syntax-tests/highlighted/Idris2/test.idr @@ -0,0 +1,107 @@ +-- some code in Idris +module XX.X''' + +import Data.Nat + +data X = A | B + +namespace X + ||| Documentation + record Y where + [noHints] + constructor MkY' + field1 : Nat + {auto x : Nat} + +namespace X' { + parameters (x : A (Maybe b)) + x : Nat +} + +u : () +u = () + +k, w, u : Char +k = '\NUL' +w = 'w' + +x = [1, 0, 3, "sdf\{d}", 0xFF, 0o77, 0b10_1, 100_100] + +f : Int -> Int +f = if x > 0 then x else 0 () SS `elem` S $ do + x <- a [1, 2, 3] + let ukuk = akak + rewrite $ Wow Wow Wow Wow.Wow b W (W) + pure $ f A B c D (EE) E + +(&&&) : Nat -> Nat -> Nat +z &&& y = d + ?foo +(&&&) x y = ?asfda + +public export covering +(.fun) : X a Y b => Nat -> Nat +Z .fun = haha.fun haha .N +(.fun) Z = ahah $ \case + x@(x, y) => Prelude.Types.ahahah + +(.N) : Nat -> Nat +Z .N = Z +(.N) (S n) = (.N) n + +xx : Name +xx = `{Full.Name} + +infixr 0 ^^^, &&& + +xxx : ? +xxx = case x of + Z => lalalaCamelCase + z => alalalCamelCase + +ff : Nat -> TTImp +ff 0 = let x = 0 in val +ff _ = `(let x = 0 in ~val ^~^ ~(abc)) +ff _ = f `(let x = 0 in ~val ^~^ ~(abc)) x + +%language ElabReflection +%runElab X.sf ads + +%macro %inline +fff : List Decl +fff = `[ + f : Nat -> Nat + + f Z = haha %runElab %search @{%World} +] + +private infixr 4 ^--^ + +(^--^) : Nat -> Nat -> Nat +(^--^) Z Z = Z +x ^--^ y = x + y + +x : (y : Vect n (Maybe (Maybe (&&&) Nat))) -> + {x : Nat} -> {auto _ : Monoid a} -> + {default 4 xx : Nat} -> + {default (f x Y) xx' : Nat} -> + String +x Z S = ?foo +x y _ = "a b \{show $ let x = 0 in y} y >>= z" + +multiline : String +multiline = """ + A multiline string\NUL + """ + +f' : Nat -> Nat +f' = x' 4 + +x : Char +x = '\BEL' +x = '\\' +x = '\'' +x = '\o755' +x = 'a' + +xx : Int +xx = 0o7_5_5 diff --git a/tests/syntax-tests/highlighted/JSON/example.ndjson b/tests/syntax-tests/highlighted/JSON/example.ndjson new file mode 100644 index 00000000..775a5218 --- /dev/null +++ b/tests/syntax-tests/highlighted/JSON/example.ndjson @@ -0,0 +1,3 @@ +{"some":"thing"} +{"foo":17,"bar":false,"quux":true} +{"may":{"include":"nested","objects":["and","arrays"]}} diff --git a/tests/syntax-tests/highlighted/Log/example.log b/tests/syntax-tests/highlighted/Log/example.log index f0e9754a..57e0e9a3 100644 --- a/tests/syntax-tests/highlighted/Log/example.log +++ b/tests/syntax-tests/highlighted/Log/example.log @@ -1,3 +1,3 @@ 2021-03-06 23:22:21.392 https://[2001:db8:4006:812::200e]:8080/path/the%20page.html 2021-03-06 23:22:21 https://example.com:8080/path/the%20page(with_parens).html -2022-03-16T17:41:02.519 helix_term::application [WARN] unhandled window/showMessage: ShowMessageParams { typ: Error, message: "rust-analyzer failed to load workspace: Failed to read Cargo metadata from Cargo.toml file /home/zeta/dev/raytracer/Cargo.toml, cargo 1.61.0-nightly (65c8266 2022-03-09): Failed to run `\"cargo\" \"metadata\" \"--format-version\" \"1\" \"--manifest-path\" \"/home/zeta/dev/raytracer/Cargo.toml\" \"--filter-platform\" \"wasm32-unknown-unknown\"`: `cargo metadata` exited with an error: Updating crates.io index\nerror: failed to select a version for `parking_lot`.\n ... required by package `raytracer v0.1.0 (/home/zeta/dev/raytracer)`\nversions that meet the requirements `^0.12.0` are: 0.12.0\n\nthe package `raytracer` depends on `parking_lot`, with features: `wasm-bindgen` but `parking_lot` does not have these features.\n\n\nfailed to select a version for `parking_lot` which could resolve this conflict\n" } +2022-03-16T17:41:02.519 helix_term::application [WARN] unhandled window/showMessage: ShowMessageParams { typ: Error, message: "rust-analyzer failed to load workspace: Failed to read Cargo metadata from Cargo.toml file /home/zeta/dev/raytracer/Cargo.toml, cargo 1.61.0-nightly (65c8266 2022-03-09): Failed to run `\"cargo\" \"metadata\" \"--format-version\" \"1\" \"--manifest-path\" \"/home/zeta/dev/raytracer/Cargo.toml\" \"--filter-platform\" \"wasm32-unknown-unknown\"`: `cargo metadata` exited with an error: Updating crates.io index\nerror: failed to select a version for `parking_lot`.\n ... required by package `raytracer v0.1.0 (/home/zeta/dev/raytracer)`\nversions that meet the requirements `^0.12.0` are: 0.12.0\n\nthe package `raytracer` depends on `parking_lot`, with features: `wasm-bindgen` but `parking_lot` does not have these features.\n\n\nfailed to select a version for `parking_lot` which could resolve this conflict\n" } diff --git a/tests/syntax-tests/highlighted/Odin/test.odin b/tests/syntax-tests/highlighted/Odin/test.odin new file mode 100644 index 00000000..ab13ed8c --- /dev/null +++ b/tests/syntax-tests/highlighted/Odin/test.odin @@ -0,0 +1,27 @@ +package main + +import "core:fmt" +import "core:math" + +Vector :: struct { + components: []f64, +} + +euclidean_distance :: proc(v1: Vector, v2: Vector) -> f64 { + if len(v1.components) != len(v2.components) { + panic("Vectors must be same dimension") + } + sum: f64 = 0.0; + for i, comp in v1.components { + diff := comp - v2.components[i]; + sum += diff * diff; + } + return math.sqrt(sum); +} + +main :: proc() { + v1: Vector = Vector{components = []f64{1.0, 2.0, 3.0}}; + v2: Vector = Vector{components = []f64{4.0, 6.0, 8.0}}; + dist: f64 = euclidean_distance(v1, v2); + fmt.println("Distance:", dist); +} diff --git a/tests/syntax-tests/highlighted/Syslog/example.syslog b/tests/syntax-tests/highlighted/Syslog/example.syslog index 0c200c33..78c45a12 100644 --- a/tests/syntax-tests/highlighted/Syslog/example.syslog +++ b/tests/syntax-tests/highlighted/Syslog/example.syslog @@ -1,16 +1,17 @@ -Apr 4 00:00:01 hostname-here systemd[1]: logrotate.service: Succeeded. -Apr 4 00:00:01 hostname-here systemd[1]: Finished Rotate log files. -Apr 4 00:00:01 hostname-here colord[920]: failed to get session [pid 137485]: No data available -Apr 4 00:00:21 hostname-here kernel: [55604.908232] audit: type=1400 audit(1617483621.094:28): apparmor="DENIED" operation="capable" profile="/usr/sbin/cups-browsed" pid=59311 comm="cups-browsed" capability=23 capname="sys_nice" -Apr 4 00:01:38 hostname-here systemd-resolved[721]: Server returned error NXDOMAIN, mitigating potential DNS violation DVE-2018-0001, retrying transaction with reduced feature level UDP. -Apr 4 00:04:46 hostname-here ntpd[952]: Soliciting pool server 255.76.59.37 -Apr 4 00:05:21 hostname-here ntpd[952]: ::1 local addr 0:0:0:0:0:0:0:1 ->  -Apr 4 00:06:29 hostname-here ntpd[952]: receive: Unexpected origin timestamp 0xe414a8d1.82e825f5 does not match aorg 0xe414a8d5.82c50d8c from server@127.0.0.1 xmt 0xe414a8d1.e671d7c4 -Apr 4 09:30:01 hostname-here CRON[89278]: (root) CMD ([ -x /etc/init.d/anacron ] && if [ ! -d /run/systemd/system ]; then /usr/sbin/invoke-rc.d anacron start >/dev/null; fi) -Apr 4 16:32:07 hostname-here NetworkManager[740]:  [1617629527.1101] manager: NetworkManager state is now CONNECTED_GLOBAL -Apr 4 22:00:45 hostname-here dbus-daemon[1094]: [session uid=1000 pid=1094] Successfully activated service 'io.github.celluloid_player.Celluloid' -Aug 11 13:29:06 hostname-here insomnia_insomnia.desktop[142666]: 13:29:06.316 › [updater] Updater not running platform=linux dev=false -Aug 11 13:36:34 192.168.220.5 nginx: 2021/08/11 13:36:34 [debug] 2031#2031: epoll add event: fd:6 op:1 ev:00002001 -Aug 11 21:31:08 ::1 nginx: 2021/08/11 21:31:08 [debug] 760831#760831: epoll add event: fd:6 op:1 ev:10000001 -Aug 11 21:40:31 hostname-here scop hello -Aug 16 21:38:21 hostname-here systemd[1]: Finished Cleanup of Temporary Directories. +Apr 4 00:00:01 hostname-here systemd[1]: logrotate.service: Succeeded. +Apr 4 00:00:01 hostname-here systemd[1]: Finished Rotate log files. +Apr 4 00:00:01 hostname-here colord[920]: failed to get session [pid 137485]: No data available +Apr 4 00:00:21 hostname-here kernel: [55604.908232] audit: type=1400 audit(1617483621.094:28): apparmor="DENIED" operation="capable" profile="/usr/sbin/cups-browsed" pid=59311 comm="cups-browsed" capability=23 capname="sys_nice" +Apr 4 00:01:38 hostname-here systemd-resolved[721]: Server returned error NXDOMAIN, mitigating potential DNS violation DVE-2018-0001, retrying transaction with reduced feature level UDP. +Apr 4 00:04:46 hostname-here ntpd[952]: Soliciting pool server 255.76.59.37 +Apr 4 00:05:21 hostname-here ntpd[952]: ::1 local addr 0:0:0:0:0:0:0:1 ->  +Apr 4 00:06:29 hostname-here ntpd[952]: receive: Unexpected origin timestamp 0xe414a8d1.82e825f5 does not match aorg 0xe414a8d5.82c50d8c from server@127.0.0.1 xmt 0xe414a8d1.e671d7c4 +Apr 4 09:30:01 hostname-here CRON[89278]: (root) CMD ([ -x /etc/init.d/anacron ] && if [ ! -d /run/systemd/system ]; then /usr/sbin/invoke-rc.d anacron start >/dev/null; fi) +Apr 4 16:32:07 hostname-here NetworkManager[740]:  [1617629527.1101] manager: NetworkManager state is now CONNECTED_GLOBAL +Apr 4 22:00:45 hostname-here dbus-daemon[1094]: [session uid=1000 pid=1094] Successfully activated service 'io.github.celluloid_player.Celluloid' +Aug 11 13:29:06 hostname-here insomnia_insomnia.desktop[142666]: 13:29:06.316 › [updater] Updater not running platform=linux dev=false +Aug 11 13:36:34 192.168.220.5 nginx: 2021/08/11 13:36:34 [debug] 2031#2031: epoll add event: fd:6 op:1 ev:00002001 +Aug 11 21:31:08 ::1 nginx: 2021/08/11 21:31:08 [debug] 760831#760831: epoll add event: fd:6 op:1 ev:10000001 +Aug 11 21:40:31 hostname-here scop hello +Aug 16 21:38:21 hostname-here systemd[1]: Finished Cleanup of Temporary Directories. +2025-02-08 20:52:11.039 - setfont: ERROR kdfontop.c:183 put_font_kdfontop: Unable to load such font with such kernel version diff --git a/tests/syntax-tests/highlighted/XML/Directory.Build.props b/tests/syntax-tests/highlighted/XML/Directory.Build.props new file mode 100644 index 00000000..bd4b97a0 --- /dev/null +++ b/tests/syntax-tests/highlighted/XML/Directory.Build.props @@ -0,0 +1,5 @@ +<Project> + <PropertyGroup> + <OutDir>C:\output\$(MSBuildProjectName) +  + diff --git a/tests/syntax-tests/highlighted/XML/console.csproj b/tests/syntax-tests/highlighted/XML/console.csproj new file mode 100644 index 00000000..ee49fbf0 --- /dev/null +++ b/tests/syntax-tests/highlighted/XML/console.csproj @@ -0,0 +1,11 @@ +<Project Sdk="Microsoft.NET.Sdk"> + + <PropertyGroup> + <OutputType>Exe + <TargetFramework>net9.0 + <RootNamespace>SomeNamespace + <ImplicitUsings>enable + <Nullable>enable +  + + diff --git a/tests/syntax-tests/highlighted/XML/projectname.targets b/tests/syntax-tests/highlighted/XML/projectname.targets new file mode 100644 index 00000000..0af85fbd --- /dev/null +++ b/tests/syntax-tests/highlighted/XML/projectname.targets @@ -0,0 +1,8 @@ + +<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + + <Target Name="TestTarget" AfterTargets="Build"> + <Message Importance="High" Text="-------------MHM----------------" /> +  + + diff --git a/tests/syntax-tests/highlighted/debsources/sources.list b/tests/syntax-tests/highlighted/debsources/sources.list new file mode 100644 index 00000000..ef89d137 --- /dev/null +++ b/tests/syntax-tests/highlighted/debsources/sources.list @@ -0,0 +1,15 @@ +# See http://help.ubuntu.com/community/UpgradeNotes for how to upgrade to +# newer versions of the distribution. + +deb https://deb.debian.org/debian bookworm main non-free-firmware +#deb-src https://deb.debian.org/debian bookworm main non-free-firmware + +## Major bug fix updates produced after the final release of the +## distribution. +# deb-src http://lt.archive.ubuntu.com/ubuntu/ xenial-updates main restricted + +deb https://security.debian.org/debian-security bookworm-security main non-free-firmware +deb-src https://security.debian.org/debian-security bookworm-security main non-free-firmware + +deb https://deb.debian.org/debian bookworm-updates main non-free-firmware +deb-src https://deb.debian.org/debian bookworm-updates main non-free-firmware diff --git a/tests/syntax-tests/source/CSV/comma-delimited.csv b/tests/syntax-tests/source/CSV/comma-delimited.csv new file mode 100644 index 00000000..4d7b2ec2 --- /dev/null +++ b/tests/syntax-tests/source/CSV/comma-delimited.csv @@ -0,0 +1,3 @@ +foo,bar,baz,this|that,test,colors,cycle +1.2,1.7,2.5,blah;cool,test,colors,cycle + diff --git a/tests/syntax-tests/source/CSV/decimals_comma_decimal_point_pipe_delimited.csv b/tests/syntax-tests/source/CSV/decimals_comma_decimal_point_pipe_delimited.csv new file mode 100644 index 00000000..c8a46786 --- /dev/null +++ b/tests/syntax-tests/source/CSV/decimals_comma_decimal_point_pipe_delimited.csv @@ -0,0 +1,3 @@ +foo|bar|baz +1,2|1,7|2,7 +1,5|8,5|-5,5 diff --git a/tests/syntax-tests/source/CSV/decimals_comma_decimal_point_semicolon_delimited.csv b/tests/syntax-tests/source/CSV/decimals_comma_decimal_point_semicolon_delimited.csv new file mode 100644 index 00000000..63301750 --- /dev/null +++ b/tests/syntax-tests/source/CSV/decimals_comma_decimal_point_semicolon_delimited.csv @@ -0,0 +1,3 @@ +foo;bar;baz +1,2;1,7;2,7 +1,5;8,5;-5,5 diff --git a/tests/syntax-tests/source/CSV/simple.tsv b/tests/syntax-tests/source/CSV/simple.tsv new file mode 100644 index 00000000..2cf870a5 --- /dev/null +++ b/tests/syntax-tests/source/CSV/simple.tsv @@ -0,0 +1,3 @@ +foo bar baz|;, test hello world tsv +1,2 1,7 2,7 a b c "hello again" tsv +";|," ;|, baz test "hello world" tsv diff --git a/tests/syntax-tests/source/GDScript/test.gd b/tests/syntax-tests/source/GDScript/test.gd new file mode 100644 index 00000000..7192dfec --- /dev/null +++ b/tests/syntax-tests/source/GDScript/test.gd @@ -0,0 +1,71 @@ +extends Node + +signal custom_signal(param) + +const PI = 3.14159 + +var untyped_var = "Hello, World!" +var typed_int: int = 42 +var typed_float: float = 3.14 +var typed_string: String = "GDScript Test" +var typed_array: Array = [1, 2, 3, 4] +var typed_dict: Dictionary = {"key": "value", "number": 100} + +onready var label = $Label + +func say_hello() -> void: + print("Hello from GDScript!") + +func add_numbers(a: int, b: int = 10) -> int: + return a + b + +func process_value(value: int) -> String: + if value < 0: + return "Negative" + elif value == 0: + return "Zero" + else: + return "Positive" + +func sum_array(arr: Array) -> int: + var total: int = 0 + for num in arr: + total += num + return total + +func describe_number(num: int) -> String: + match num: + 0: + return "Zero" + 1, 2, 3: + return "Small number" + _: + return "Large number" + +func long_description() -> String: + return """This is a test file for GDScript. +It covers variables, functions, control structures, loops, signals, inner classes, +multiline strings, arrays, and dictionaries.""" + +class InnerExample: + var inner_value: int = 99 + func show_value() -> void: + print("Inner value is:", inner_value) + +func test_inner_class() -> void: + var inner = InnerExample.new() + inner.show_value() + +func trigger_signal() -> void: + emit_signal("custom_signal", "TestParam") + +func _ready() -> void: + say_hello() + var result_add = add_numbers(5) + print("Add result:", result_add) + print("Process value for -5:", process_value(-5)) + print("Sum of array [10, 20, 30]:", sum_array([10, 20, 30])) + print("Description for 2:", describe_number(2)) + print("Long description:\n", long_description()) + test_inner_class() + trigger_signal() diff --git a/tests/syntax-tests/source/Idris2/LICENSE.md b/tests/syntax-tests/source/Idris2/LICENSE.md new file mode 100644 index 00000000..2d9d6206 --- /dev/null +++ b/tests/syntax-tests/source/Idris2/LICENSE.md @@ -0,0 +1,7 @@ +The `test.idr` file has been added from https://github.com/buzden/sublime-syntax-idris2 under the following license: + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 diff --git a/tests/syntax-tests/source/Idris2/test.idr b/tests/syntax-tests/source/Idris2/test.idr new file mode 100644 index 00000000..1fada03d --- /dev/null +++ b/tests/syntax-tests/source/Idris2/test.idr @@ -0,0 +1,107 @@ +-- some code in Idris +module XX.X''' + +import Data.Nat + +data X = A | B + +namespace X + ||| Documentation + record Y where + [noHints] + constructor MkY' + field1 : Nat + {auto x : Nat} + +namespace X' { + parameters (x : A (Maybe b)) + x : Nat +} + +u : () +u = () + +k, w, u : Char +k = '\NUL' +w = 'w' + +x = [1, 0, 3, "sdf\{d}", 0xFF, 0o77, 0b10_1, 100_100] + +f : Int -> Int +f = if x > 0 then x else 0 () SS `elem` S $ do + x <- a [1, 2, 3] + let ukuk = akak + rewrite $ Wow Wow Wow Wow.Wow b W (W) + pure $ f A B c D (EE) E + +(&&&) : Nat -> Nat -> Nat +z &&& y = d + ?foo +(&&&) x y = ?asfda + +public export covering +(.fun) : X a Y b => Nat -> Nat +Z .fun = haha.fun haha .N +(.fun) Z = ahah $ \case + x@(x, y) => Prelude.Types.ahahah + +(.N) : Nat -> Nat +Z .N = Z +(.N) (S n) = (.N) n + +xx : Name +xx = `{Full.Name} + +infixr 0 ^^^, &&& + +xxx : ? +xxx = case x of + Z => lalalaCamelCase + z => alalalCamelCase + +ff : Nat -> TTImp +ff 0 = let x = 0 in val +ff _ = `(let x = 0 in ~val ^~^ ~(abc)) +ff _ = f `(let x = 0 in ~val ^~^ ~(abc)) x + +%language ElabReflection +%runElab X.sf ads + +%macro %inline +fff : List Decl +fff = `[ + f : Nat -> Nat + + f Z = haha %runElab %search @{%World} +] + +private infixr 4 ^--^ + +(^--^) : Nat -> Nat -> Nat +(^--^) Z Z = Z +x ^--^ y = x + y + +x : (y : Vect n (Maybe (Maybe (&&&) Nat))) -> + {x : Nat} -> {auto _ : Monoid a} -> + {default 4 xx : Nat} -> + {default (f x Y) xx' : Nat} -> + String +x Z S = ?foo +x y _ = "a b \{show $ let x = 0 in y} y >>= z" + +multiline : String +multiline = """ + A multiline string\NUL + """ + +f' : Nat -> Nat +f' = x' 4 + +x : Char +x = '\BEL' +x = '\\' +x = '\'' +x = '\o755' +x = 'a' + +xx : Int +xx = 0o7_5_5 diff --git a/tests/syntax-tests/source/JSON/example.ndjson b/tests/syntax-tests/source/JSON/example.ndjson new file mode 100644 index 00000000..2bc459eb --- /dev/null +++ b/tests/syntax-tests/source/JSON/example.ndjson @@ -0,0 +1,3 @@ +{"some":"thing"} +{"foo":17,"bar":false,"quux":true} +{"may":{"include":"nested","objects":["and","arrays"]}} diff --git a/tests/syntax-tests/source/Odin/test.odin b/tests/syntax-tests/source/Odin/test.odin new file mode 100644 index 00000000..dafcfcfd --- /dev/null +++ b/tests/syntax-tests/source/Odin/test.odin @@ -0,0 +1,27 @@ +package main + +import "core:fmt" +import "core:math" + +Vector :: struct { + components: []f64, +} + +euclidean_distance :: proc(v1: Vector, v2: Vector) -> f64 { + if len(v1.components) != len(v2.components) { + panic("Vectors must be same dimension") + } + sum: f64 = 0.0; + for i, comp in v1.components { + diff := comp - v2.components[i]; + sum += diff * diff; + } + return math.sqrt(sum); +} + +main :: proc() { + v1: Vector = Vector{components = []f64{1.0, 2.0, 3.0}}; + v2: Vector = Vector{components = []f64{4.0, 6.0, 8.0}}; + dist: f64 = euclidean_distance(v1, v2); + fmt.println("Distance:", dist); +} diff --git a/tests/syntax-tests/source/Syslog/example.syslog b/tests/syntax-tests/source/Syslog/example.syslog index 9dc82e7c..5b7e575b 100644 --- a/tests/syntax-tests/source/Syslog/example.syslog +++ b/tests/syntax-tests/source/Syslog/example.syslog @@ -14,3 +14,4 @@ Aug 11 13:36:34 192.168.220.5 nginx: 2021/08/11 13:36:34 [debug] 2031#2031: epol Aug 11 21:31:08 ::1 nginx: 2021/08/11 21:31:08 [debug] 760831#760831: epoll add event: fd:6 op:1 ev:10000001 Aug 11 21:40:31 hostname-here scop hello Aug 16 21:38:21 hostname-here systemd[1]: Finished Cleanup of Temporary Directories. +2025-02-08 20:52:11.039 - setfont: ERROR kdfontop.c:183 put_font_kdfontop: Unable to load such font with such kernel version diff --git a/tests/syntax-tests/source/XML/Directory.Build.props b/tests/syntax-tests/source/XML/Directory.Build.props new file mode 100644 index 00000000..95da98cf --- /dev/null +++ b/tests/syntax-tests/source/XML/Directory.Build.props @@ -0,0 +1,5 @@ + + + C:\output\$(MSBuildProjectName) + + diff --git a/tests/syntax-tests/source/XML/console.csproj b/tests/syntax-tests/source/XML/console.csproj new file mode 100644 index 00000000..61dd6821 --- /dev/null +++ b/tests/syntax-tests/source/XML/console.csproj @@ -0,0 +1,11 @@ + + + + Exe + net9.0 + SomeNamespace + enable + enable + + + diff --git a/tests/syntax-tests/source/XML/projectname.targets b/tests/syntax-tests/source/XML/projectname.targets new file mode 100644 index 00000000..fc597ed2 --- /dev/null +++ b/tests/syntax-tests/source/XML/projectname.targets @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/tests/syntax-tests/source/debsources/sources.list b/tests/syntax-tests/source/debsources/sources.list new file mode 100644 index 00000000..2bdc6ef1 --- /dev/null +++ b/tests/syntax-tests/source/debsources/sources.list @@ -0,0 +1,15 @@ +# See http://help.ubuntu.com/community/UpgradeNotes for how to upgrade to +# newer versions of the distribution. + +deb https://deb.debian.org/debian bookworm main non-free-firmware +#deb-src https://deb.debian.org/debian bookworm main non-free-firmware + +## Major bug fix updates produced after the final release of the +## distribution. +# deb-src http://lt.archive.ubuntu.com/ubuntu/ xenial-updates main restricted + +deb https://security.debian.org/debian-security bookworm-security main non-free-firmware +deb-src https://security.debian.org/debian-security bookworm-security main non-free-firmware + +deb https://deb.debian.org/debian bookworm-updates main non-free-firmware +deb-src https://deb.debian.org/debian bookworm-updates main non-free-firmware