Merge branch 'master' into kubernetes

This commit is contained in:
Keith Hall 2024-10-21 23:01:30 +03:00
commit c11a7d9e41
22 changed files with 658 additions and 141 deletions

3
.gitmodules vendored
View File

@ -260,3 +260,6 @@
[submodule "assets/syntaxes/02_Extra/vscode-wgsl"]
path = assets/syntaxes/02_Extra/vscode-wgsl
url = https://github.com/PolyMeilex/vscode-wgsl.git
[submodule "assets/syntaxes/02_Extra/CFML"]
path = assets/syntaxes/02_Extra/CFML
url = https://github.com/jcberquist/sublimetext-cfml.git

View File

@ -8,6 +8,7 @@
- `PrettyPrinter::squeeze_empty_lines` to support line squeezing for bat as a library, see #1441 (@eth-p) and #2665 (@einfachIrgendwer0815)
- 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)
## Bugfixes
@ -42,6 +43,7 @@
- Update the Lisp syntax, see #2970 (@ccqpein)
- 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)
## Syntaxes
@ -49,11 +51,15 @@
- Upgrade JQ syntax, see #2820 (@dependabot[bot])
- Add syntax mapping for quadman quadlets #2866 (@cyqsimon)
- Map containers .conf files to TOML syntax #2867 (@cyqsimon)
- Associate `xsh` files with `xonsh` syntax that is Python, see #2840 (@anki-code).
- Added auto detect syntax for `.jsonc` #2795 (@mxaddict)
- Added auto detect syntax for `.aws/{config,credentials}` #2795 (@mxaddict)
- Add syntax mapping for Wireguard config #2874 (@cyqsimon)
- Associate `.textproto` files with `ProtoBuf` syntax, see #3038 (@vorburger).
- Associate `.xsh` files with `xonsh` syntax that is Python, see #2840 (@anki-code)
- 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 kubernetes config files #3049 (@cyqsimon)
## Themes

89
Cargo.lock generated
View File

@ -3,10 +3,10 @@
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"
@ -19,9 +19,9 @@ dependencies = [
[[package]]
name = "ansi_colours"
version = "1.2.2"
version = "1.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a1558bd2075d341b9ca698ec8eb6fcc55a746b1fc4255585aad5b141d918a80"
checksum = "14eec43e0298190790f41679fe69ef7a829d2a2ddd78c8c00339e84710e435fe"
dependencies = [
"rgb",
]
@ -103,9 +103,9 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[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"
@ -463,9 +463,9 @@ dependencies = [
[[package]]
name = "expect-test"
version = "1.4.1"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "30d9eafeadd538e68fb28016364c9732d78e420b9ff8853fa5e4058861e9f8d3"
checksum = "9e0be0a561335815e06dab7c62e50353134c796e7a6155402a64bcff66b6a5e0"
dependencies = [
"dissimilar",
"once_cell",
@ -489,9 +489,9 @@ checksum = "6999dc1837253364c2ebb0704ba97994bd874e8f195d665c50b7548f6ea92764"
[[package]]
name = "flate2"
version = "1.0.30"
version = "1.0.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5f54427cfd1c7829e2a139fcefea601bf088ebca651d2bf53ebc600eac295dae"
checksum = "a1b589b4dc103969ad3cf85c950899926ec64300a1a46d76c03a6072957036f0"
dependencies = [
"crc32fast",
"miniz_oxide",
@ -564,9 +564,9 @@ dependencies = [
[[package]]
name = "git2"
version = "0.18.3"
version = "0.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "232e6a7bfe35766bf715e55a88b39a700596c0ccfd88cd3680b4cdb40d66ef70"
checksum = "b903b73e45dc0c6c596f2d37eccece7c1c8bb6e4407b001096387c63d0d93724"
dependencies = [
"bitflags 2.4.0",
"libc",
@ -583,9 +583,9 @@ checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
[[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",
@ -647,9 +647,9 @@ dependencies = [
[[package]]
name = "indexmap"
version = "2.2.6"
version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26"
checksum = "de3fc2e30ba82dd1b3911c8de1ffc143c74a914a14e99514d7637e3099df5ea0"
dependencies = [
"equivalent",
"hashbrown 0.14.1",
@ -694,9 +694,9 @@ checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b"
[[package]]
name = "libgit2-sys"
version = "0.16.2+1.7.2"
version = "0.17.0+1.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee4126d8b4ee5c9d9ea891dd875cfdc1e9d0950437179104b183d7d8a74d24e8"
checksum = "10472326a8a6477c3c20a64547b0059e4b0d086869eee31e6d7da728a8eb7224"
dependencies = [
"cc",
"libc",
@ -716,15 +716,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"
@ -761,11 +752,11 @@ checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167"
[[package]]
name = "miniz_oxide"
version = "0.7.1"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7"
checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1"
dependencies = [
"adler",
"adler2",
]
[[package]]
@ -811,9 +802,12 @@ dependencies = [
[[package]]
name = "once_cell"
version = "1.19.0"
version = "1.20.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
checksum = "82881c4be219ab5faaf2ad5e5e5ecdff8c66bd7402ca3160975c93b24961afd1"
dependencies = [
"portable-atomic",
]
[[package]]
name = "onig"
@ -892,18 +886,23 @@ checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae"
[[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",
]
[[package]]
name = "portable-atomic"
version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cc9c68a3f6da06753e9335d63e27f6b9754dd1920d941135b7ea8224f141adb2"
[[package]]
name = "powerfmt"
version = "0.2.0"
@ -957,9 +956,9 @@ dependencies = [
[[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",
]
@ -1087,12 +1086,6 @@ version = "1.0.11"
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"
[[package]]
name = "same-file"
version = "1.0.6"
@ -1116,18 +1109,18 @@ checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b"
[[package]]
name = "serde"
version = "1.0.199"
version = "1.0.209"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c9f6e76df036c77cd94996771fb40db98187f096dd0b9af39c6c6e452ba966a"
checksum = "99fce0ffe7310761ca6bf9faf5115afbc19688edd00171d81b1bb1b116c63e09"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.199"
version = "1.0.209"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "11bd257a6541e141e42ca6d24ae26f7714887b47e89aa739099104c7e4d3b7fc"
checksum = "a5831b979fd7b5439637af1752d535ff49f4860c0f341d1baeb6faf0f4242170"
dependencies = [
"proc-macro2",
"quote",

View File

@ -46,7 +46,7 @@ ansi_colours = "^1.2"
bincode = "1.0"
console = "0.15.8"
flate2 = "1.0"
once_cell = "1.19"
once_cell = "1.20"
thiserror = "1.0"
wild = { version = "2.2", optional = true }
content_inspector = "0.2.4"
@ -70,7 +70,7 @@ os_str_bytes = { version = "~7.0", optional = true }
run_script = { version = "^0.10.1", optional = true}
[dependencies.git2]
version = "0.18"
version = "0.19"
optional = true
default-features = false
@ -86,11 +86,11 @@ 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.4.1"
expect-test = "1.5.0"
serial_test = { version = "2.0.0", default-features = false }
predicates = "3.1.0"
wait-timeout = "0.2.0"
@ -102,9 +102,9 @@ nix = { version = "0.26.4", default-features = false, features = ["term"] }
[build-dependencies]
anyhow = "1.0.86"
indexmap = { version = "2.2.6", features = ["serde"] }
indexmap = { version = "2.3.0", features = ["serde"] }
itertools = "0.13.0"
once_cell = "1.18"
once_cell = "1.20"
regex = "1.10.2"
serde = "1.0"
serde_derive = "1.0"

View File

@ -515,6 +515,16 @@ and line numbers but no grid and no file header. Set the `BAT_STYLE` environment
variable to make these changes permanent or use `bat`s
[configuration file](https://github.com/sharkdp/bat#configuration-file).
>[!tip]
> If you specify a default style in `bat`'s config file, you can change which components
> are displayed during a single run of `bat` using the `--style` command-line argument.
> By prefixing a component with `+` or `-`, it can be added or removed from the current style.
>
> For example, if your config contains `--style=full,-snip`, you can run bat with
> `--style=-grid,+snip` to remove the grid and add back the `snip` component.
> Or, if you want to override the styles completely, you use `--style=numbers` to
> only show the line numbers.
### Adding new syntaxes / language definitions
Should you find that a particular syntax is not available within `bat`, you can follow these

View File

@ -76,6 +76,7 @@ _bat() {
-m | --map-syntax | \
--ignored-suffix | \
--list-themes | \
--squeeze-limit | \
--line-range | \
-L | --list-languages | \
--lessopen | \
@ -157,6 +158,7 @@ _bat() {
--diff-context
--tabs
--wrap
--chop-long-lines
--terminal-width
--number
--color
@ -169,18 +171,24 @@ _bat() {
--ignored-suffix
--theme
--list-themes
--squeeze-blank
--squeeze-limit
--style
--line-range
--list-languages
--lessopen
--diagnostic
--acknowledgements
--set-terminal-title
--help
--version
--cache-dir
--config-dir
--config-file
--generate-config-file
--no-config
--no-custom-assets
--no-lessopen
" -- "$cur"))
return 0
fi

View File

@ -133,6 +133,8 @@ set -l tabs_opts '
complete -c $bat -l acknowledgements -d "Print acknowledgements" -n __fish_is_first_arg
complete -c $bat -l cache-dir -f -d "Show bat's cache directory" -n __fish_is_first_arg
complete -c $bat -l color -x -a "$color_opts" -d "When to use colored output" -n __bat_no_excl_args
complete -c $bat -l config-dir -f -d "Display location of configuration directory" -n __fish_is_first_arg

View File

@ -48,6 +48,7 @@ _{{PROJECT_EXECUTABLE}}_main() {
default auto full plain changes header header-filename header-filesize grid rule numbers snip'
\*{-r+,--line-range=}'[only print the specified line range]:start\:end'
'(* -)'{-L,--list-languages}'[display all supported languages]'
-P'[disable paging]'
"--no-config[don't use the configuration file]"
"--no-custom-assets[don't load custom assets]"
'(--no-lessopen)'--lessopen'[enable the $LESSOPEN preprocessor]'

View File

@ -87,6 +87,10 @@ Set the tab width to T spaces. Use a width of 0 to pass tabs through directly
Specify the text\-wrapping mode (*auto*, never, character). The '\-\-terminal\-width' option
can be used in addition to control the output width.
.HP
\fB\-S\fR, \fB\-\-chop\-long\-lines\fR
.IP
Truncate all lines longer than screen width. Alias for '\-\-wrap=never'.
.HP
\fB\-\-terminal\-width\fR <width>
.IP
Explicitly set the width of the terminal instead of determining it automatically. If
@ -141,6 +145,11 @@ use -m '*.build:Python'. To highlight files named '.myignore' with the Git Ignor
syntax, use -m '.myignore:Git Ignore'.
Note that the right-hand side is the *name* of the syntax, not a file extension.
.HP
\fB\-\-ignored\-suffix\fR <ignored-suffix>
.IP
Ignore extension. For example: 'bat \-\-ignored-suffix ".dev" my_file.json.dev'
will use JSON syntax, and ignore '.dev'
.HP
\fB\-\-theme\fR <theme>
.IP
Set the theme for syntax highlighting. Use '\-\-list\-themes' to see all available themes.
@ -151,6 +160,14 @@ export the BAT_THEME environment variable (e.g.: export BAT_THEME="...").
.IP
Display a list of supported themes for syntax highlighting.
.HP
\fB\-s\fR, \fB\-\-squeeze\-blank\fR
.IP
Squeeze consecutive empty lines into a single empty line.
.HP
\fB\-\-squeeze\-limit\fR <squeeze-limit>
.IP
Set the maximum number of consecutive empty lines to be printed.
.HP
\fB\-\-style\fR <style\-components>
.IP
Configure which elements (line numbers, file headers, grid borders, Git modifications,
@ -184,6 +201,30 @@ Display a list of supported languages for syntax highlighting.
This option exists for POSIX\-compliance reasons ('u' is for 'unbuffered'). The output is
always unbuffered \- this option is simply ignored.
.HP
\fB\-\-no\-custom\-assets\fR
.IP
Do not load custom assets.
.HP
\fB\-\-config\-dir\fR
.IP
Show bat's configuration directory.
.HP
\fB\-\-cache\-dir\fR
.IP
Show bat's cache directory.
.HP
\fB\-\-diagnostic\fR
.IP
Show diagnostic information for bug reports.
.HP
\fB\-\-acknowledgements\fR
.IP
Show acknowledgements.
.HP
\fB\-\-set\-terminal\-title\fR
.IP
Sets terminal title to filenames when using a pager.
.HP
\fB\-h\fR, \fB\-\-help\fR
.IP
Print this help message.
@ -212,6 +253,20 @@ location of the configuration file.
To generate a default configuration file, call:
\fB{{PROJECT_EXECUTABLE}} --generate-config-file\fR
These are related options:
.HP
\fB\-\-config\-file\fR
.IP
Show path to the configuration file.
.HP
\fB\-\-generate-config\-file\fR
.IP
Generates a default configuration file.
.HP
\fB\-\-no\-config\fR
.IP
Do not use the configuration file.
.SH "ADDING CUSTOM LANGUAGES"
{{PROJECT_EXECUTABLE}} supports Sublime Text \fB.sublime-syntax\fR language files, and can be
customized to add additional languages to your local installation. To do this, add the \fB.sublime-syntax\fR language
@ -258,6 +313,16 @@ To temporarily disable the preprocessor if it is enabled by default, call:
\fB{{PROJECT_EXECUTABLE}} --no-lessopen\fR
These are related options:
.HP
\fB\-\-lessopen\fR
.IP
Enable the $LESSOPEN preprocessor.
.HP
\fB\-\-no\-lessopen\fR
.IP
Disable the $LESSOPEN preprocessor if enabled (overrides --lessopen)
.PP
For more information, see the "INPUT PREPROCESSOR" section of less(1).
.SH "MORE INFORMATION"

1
assets/syntaxes/02_Extra/CFML vendored Submodule

@ -0,0 +1 @@
Subproject commit b91c44a32e251c20c6359a8d9232287e1b408e6c

View File

@ -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) 文件。

View File

@ -134,6 +134,12 @@ Options:
set a default style, add the '--style=".."' option to the configuration file or export the
BAT_STYLE environment variable (e.g.: export BAT_STYLE="..").
When styles are specified in multiple places, the "nearest" set of styles take precedence.
The command-line arguments are the highest priority, followed by the BAT_STYLE environment
variable, and then the configuration file. If any set of styles consists entirely of
components prefixed with "+" or "-", it will modify the previous set of styles instead of
replacing them.
By default, the following components are enabled:
changes, grid, header-filename, numbers, snip

View File

@ -2,11 +2,13 @@ use std::collections::HashSet;
use std::env;
use std::io::IsTerminal;
use std::path::{Path, PathBuf};
use std::str::FromStr;
use crate::{
clap_app,
config::{get_args_from_config_file, get_args_from_env_opts_var, get_args_from_env_vars},
};
use bat::style::StyleComponentList;
use bat::StripAnsiMode;
use clap::ArgMatches;
@ -86,7 +88,6 @@ impl App {
// .. and the rest at the end
cli_args.for_each(|a| args.push(a));
args
};
@ -364,34 +365,57 @@ impl App {
Ok(file_input)
}
fn forced_style_components(&self) -> Option<StyleComponents> {
// No components if `--decorations=never``.
if self
.matches
.get_one::<String>("decorations")
.map(|s| s.as_str())
== Some("never")
{
return Some(StyleComponents(HashSet::new()));
}
// Only line numbers if `--number`.
if self.matches.get_flag("number") {
return Some(StyleComponents(HashSet::from([
StyleComponent::LineNumbers,
])));
}
// Plain if `--plain` is specified at least once.
if self.matches.get_count("plain") > 0 {
return Some(StyleComponents(HashSet::from([StyleComponent::Plain])));
}
// Default behavior.
None
}
fn style_components(&self) -> Result<StyleComponents> {
let matches = &self.matches;
let mut styled_components = StyleComponents(
if matches.get_one::<String>("decorations").map(|s| s.as_str()) == Some("never") {
HashSet::new()
} else if matches.get_flag("number") {
[StyleComponent::LineNumbers].iter().cloned().collect()
} else if 0 < matches.get_count("plain") {
[StyleComponent::Plain].iter().cloned().collect()
} else {
matches
.get_one::<String>("style")
.map(|styles| {
styles
.split(',')
.map(|style| style.parse::<StyleComponent>())
.filter_map(|style| style.ok())
.collect::<Vec<_>>()
})
.unwrap_or_else(|| vec![StyleComponent::Default])
let mut styled_components = match self.forced_style_components() {
Some(forced_components) => forced_components,
// Parse the `--style` arguments and merge them.
None if matches.contains_id("style") => {
let lists = matches
.get_many::<String>("style")
.expect("styles present")
.map(|v| StyleComponentList::from_str(v))
.collect::<Result<Vec<StyleComponentList>>>()?;
StyleComponentList::to_components(lists, self.interactive_output, true)
}
// Use the default.
None => StyleComponents(HashSet::from_iter(
StyleComponent::Default
.components(self.interactive_output)
.into_iter()
.map(|style| style.components(self.interactive_output))
.fold(HashSet::new(), |mut acc, components| {
acc.extend(components.iter().cloned());
acc
})
},
);
.cloned(),
)),
};
// If `grid` is set, remove `rule` as it is a subset of `grid`, and print a warning.
if styled_components.grid() && styled_components.0.remove(&StyleComponent::Rule) {

View File

@ -1,9 +1,11 @@
use bat::style::StyleComponentList;
use clap::{
crate_name, crate_version, value_parser, Arg, ArgAction, ArgGroup, ColorChoice, Command,
};
use once_cell::sync::Lazy;
use std::env;
use std::path::{Path, PathBuf};
use std::str::FromStr;
static VERSION: Lazy<String> = Lazy::new(|| {
#[cfg(feature = "bugreport")]
@ -419,34 +421,13 @@ pub fn build_app(interactive_output: bool) -> Command {
.arg(
Arg::new("style")
.long("style")
.action(ArgAction::Append)
.value_name("components")
.overrides_with("style")
.overrides_with("plain")
.overrides_with("number")
// Cannot use claps built in validation because we have to turn off clap's delimiters
.value_parser(|val: &str| {
let mut invalid_vals = val.split(',').filter(|style| {
!&[
"auto",
"full",
"default",
"plain",
"header",
"header-filename",
"header-filesize",
"grid",
"rule",
"numbers",
"snip",
#[cfg(feature = "git")]
"changes",
].contains(style)
});
if let Some(invalid) = invalid_vals.next() {
Err(format!("Unknown style, '{invalid}'"))
} else {
Ok(val.to_owned())
match StyleComponentList::from_str(val) {
Err(err) => Err(err),
Ok(_) => Ok(val.to_owned()),
}
})
.help(
@ -461,6 +442,12 @@ pub fn build_app(interactive_output: bool) -> Command {
pre-defined style ('full'). To set a default style, add the \
'--style=\"..\"' option to the configuration file or export the \
BAT_STYLE environment variable (e.g.: export BAT_STYLE=\"..\").\n\n\
When styles are specified in multiple places, the \"nearest\" set \
of styles take precedence. The command-line arguments are the highest \
priority, followed by the BAT_STYLE environment variable, and then \
the configuration file. If any set of styles consists entirely of \
components prefixed with \"+\" or \"-\", it will modify the \
previous set of styles instead of replacing them.\n\n\
By default, the following components are enabled:\n \
changes, grid, header-filename, numbers, snip\n\n\
Possible values:\n\n \

View File

@ -146,8 +146,11 @@ pub fn get_args_from_env_vars() -> Vec<OsString> {
("--style", "BAT_STYLE"),
]
.iter()
.filter_map(|(flag, key)| env::var(key).ok().map(|var| [flag.to_string(), var]))
.flatten()
.filter_map(|(flag, key)| {
env::var(key)
.ok()
.map(|var| [flag.to_string(), var].join("="))
})
.map(|a| a.into())
.collect()
}

View File

@ -202,7 +202,7 @@ pub fn list_themes(cfg: &Config, config_dir: &Path, cache_dir: &Path) -> Result<
let default_theme = HighlightingAssets::default_theme();
for theme in assets.themes() {
let default_theme_info = if default_theme == theme {
let default_theme_info = if !config.loop_through && default_theme == theme {
" (default)"
} else {
""

View File

@ -138,3 +138,227 @@ impl StyleComponents {
self.0.clear();
}
}
#[derive(Debug, PartialEq)]
enum ComponentAction {
Override,
Add,
Remove,
}
impl ComponentAction {
fn extract_from_str(string: &str) -> (ComponentAction, &str) {
match string.chars().next() {
Some('-') => (ComponentAction::Remove, string.strip_prefix('-').unwrap()),
Some('+') => (ComponentAction::Add, string.strip_prefix('+').unwrap()),
_ => (ComponentAction::Override, string),
}
}
}
/// A list of [StyleComponent] that can be parsed from a string.
pub struct StyleComponentList(Vec<(ComponentAction, StyleComponent)>);
impl StyleComponentList {
fn expand_into(&self, components: &mut HashSet<StyleComponent>, interactive_terminal: bool) {
for (action, component) in self.0.iter() {
let subcomponents = component.components(interactive_terminal);
use ComponentAction::*;
match action {
Override | Add => components.extend(subcomponents),
Remove => components.retain(|c| !subcomponents.contains(c)),
}
}
}
/// Returns `true` if any component in the list was not prefixed with `+` or `-`.
fn contains_override(&self) -> bool {
self.0.iter().any(|(a, _)| *a == ComponentAction::Override)
}
/// Combines multiple [StyleComponentList]s into a single [StyleComponents] set.
///
/// ## Precedence
/// The most recent list will take precedence and override all previous lists
/// unless it only contains components prefixed with `-` or `+`. When this
/// happens, the list's components will be merged into the previous list.
///
/// ## Example
/// ```text
/// [numbers,grid] + [header,changes] -> [header,changes]
/// [numbers,grid] + [+header,-grid] -> [numbers,header]
/// ```
///
/// ## Parameters
/// - `with_default`: If true, the styles lists will build upon the StyleComponent::Auto style.
pub fn to_components(
lists: impl IntoIterator<Item = StyleComponentList>,
interactive_terminal: bool,
with_default: bool,
) -> StyleComponents {
let mut components: HashSet<StyleComponent> = HashSet::new();
if with_default {
components.extend(StyleComponent::Auto.components(interactive_terminal))
}
StyleComponents(lists.into_iter().fold(components, |mut components, list| {
if list.contains_override() {
components.clear();
}
list.expand_into(&mut components, interactive_terminal);
components
}))
}
}
impl Default for StyleComponentList {
fn default() -> Self {
StyleComponentList(vec![(ComponentAction::Override, StyleComponent::Default)])
}
}
impl FromStr for StyleComponentList {
type Err = Error;
fn from_str(s: &str) -> Result<Self> {
Ok(StyleComponentList(
s.split(",")
.map(|s| ComponentAction::extract_from_str(s)) // If the component starts with "-", it's meant to be removed
.map(|(a, s)| Ok((a, StyleComponent::from_str(s)?)))
.collect::<Result<Vec<(ComponentAction, StyleComponent)>>>()?,
))
}
}
#[cfg(test)]
mod test {
use std::collections::HashSet;
use std::str::FromStr;
use super::ComponentAction::*;
use super::StyleComponent;
use super::StyleComponent::*;
use super::StyleComponentList;
#[test]
pub fn style_component_list_parse() {
assert_eq!(
StyleComponentList::from_str("grid,+numbers,snip,-snip,header")
.expect("no error")
.0,
vec![
(Override, Grid),
(Add, LineNumbers),
(Override, Snip),
(Remove, Snip),
(Override, Header),
]
);
assert!(StyleComponentList::from_str("not-a-component").is_err());
assert!(StyleComponentList::from_str("grid,not-a-component").is_err());
assert!(StyleComponentList::from_str("numbers,-not-a-component").is_err());
}
#[test]
pub fn style_component_list_to_components() {
assert_eq!(
StyleComponentList::to_components(
vec![StyleComponentList::from_str("grid,numbers").expect("no error")],
false,
false
)
.0,
HashSet::from([Grid, LineNumbers])
);
}
#[test]
pub fn style_component_list_to_components_removes_negated() {
assert_eq!(
StyleComponentList::to_components(
vec![StyleComponentList::from_str("grid,numbers,-grid").expect("no error")],
false,
false
)
.0,
HashSet::from([LineNumbers])
);
}
#[test]
pub fn style_component_list_to_components_expands_subcomponents() {
assert_eq!(
StyleComponentList::to_components(
vec![StyleComponentList::from_str("full").expect("no error")],
false,
false
)
.0,
HashSet::from_iter(Full.components(true).to_owned())
);
}
#[test]
pub fn style_component_list_expand_negates_subcomponents() {
assert!(!StyleComponentList::to_components(
vec![StyleComponentList::from_str("full,-numbers").expect("no error")],
true,
false
)
.numbers());
}
#[test]
pub fn style_component_list_to_components_precedence_overrides_previous_lists() {
assert_eq!(
StyleComponentList::to_components(
vec![
StyleComponentList::from_str("grid").expect("no error"),
StyleComponentList::from_str("numbers").expect("no error"),
],
false,
false
)
.0,
HashSet::from([LineNumbers])
);
}
#[test]
pub fn style_component_list_to_components_precedence_merges_previous_lists() {
assert_eq!(
StyleComponentList::to_components(
vec![
StyleComponentList::from_str("grid,header").expect("no error"),
StyleComponentList::from_str("-grid").expect("no error"),
StyleComponentList::from_str("+numbers").expect("no error"),
],
false,
false
)
.0,
HashSet::from([HeaderFilename, LineNumbers])
);
}
#[test]
pub fn style_component_list_default_builds_on_auto() {
assert_eq!(
StyleComponentList::to_components(
vec![StyleComponentList::from_str("-numbers").expect("no error"),],
true,
true
)
.0,
{
let mut expected: HashSet<StyleComponent> = HashSet::new();
expected.extend(Auto.components(true));
expected.remove(&LineNumbers);
expected
}
);
}
}

View File

@ -1,3 +1,3 @@
# JSON Lines is a simple variation of JSON #2535
[mappings]
"JSON" = ["*.jsonl", "*.jsonc"]
"JSON" = ["*.jsonl", "*.jsonc", "*.jsonld", "*.geojson"]

View File

@ -0,0 +1,2 @@
[mappings]
"Markdown" = ["*.mkd"]

View File

@ -300,6 +300,7 @@ fn list_themes_without_colors() {
bat()
.arg("--color=never")
.arg("--decorations=always") // trick bat into setting `Config::loop_through` to false
.arg("--list-themes")
.assert()
.success()
@ -307,6 +308,15 @@ fn list_themes_without_colors() {
.stdout(predicate::str::contains(default_theme_chunk).normalize());
}
#[test]
fn list_themes_to_piped_output() {
bat()
.arg("--list-themes")
.assert()
.success()
.stdout(predicate::str::contains("(default)").not());
}
#[test]
#[cfg_attr(any(not(feature = "git"), target_os = "windows"), ignore)]
fn short_help() {
@ -2810,3 +2820,71 @@ fn strip_ansi_auto_does_not_strip_ansi_when_plain_text_by_option() {
assert!(output.contains("\x1B[33mYellow"))
}
// Tests that style components can be removed with `-component`.
#[test]
fn style_components_can_be_removed() {
bat()
.arg({
#[cfg(not(feature = "git"))]
{
"--style=full,-grid"
}
#[cfg(feature = "git")]
{
"--style=full,-grid,-changes"
}
})
.arg("--decorations=always")
.arg("--color=never")
.write_stdin("test")
.assert()
.success()
.stdout(" STDIN\n Size: -\n 1 test\n")
.stderr("");
}
// Tests that style components are chosen based on the rightmost `--style` argument.
#[test]
fn style_components_can_be_overidden() {
bat()
.arg("--style=full")
.arg("--style=header,numbers")
.arg("--decorations=always")
.arg("--color=never")
.write_stdin("test")
.assert()
.success()
.stdout(" STDIN\n 1 test\n")
.stderr("");
}
// Tests that style components can be merged across multiple `--style` arguments.
#[test]
fn style_components_will_merge() {
bat()
.arg("--style=header,grid")
.arg("--style=-grid,+numbers")
.arg("--decorations=always")
.arg("--color=never")
.write_stdin("test")
.assert()
.success()
.stdout(" STDIN\n 1 test\n")
.stderr("");
}
// Tests that style components can be merged with the `BAT_STYLE` environment variable.
#[test]
fn style_components_will_merge_with_env_var() {
bat()
.env("BAT_STYLE", "header,grid")
.arg("--style=-grid,+numbers")
.arg("--decorations=always")
.arg("--color=never")
.write_stdin("test")
.assert()
.success()
.stdout(" STDIN\n 1 test\n")
.stderr("");
}

View File

@ -0,0 +1,54 @@
<head> 
<title>Add New Employees</title> 
</head> 
<body> 
<h1>Add New Employees</h1> 
<!--- Action page code for the form at the bottom of this page. ---> 
<!--- Establish parameters for first time through ---> 
<cfparam name="Form.firstname" default=""> 
<cfparam name="Form.lastname" default=""> 
<cfparam name="Form.email" default=""> 
<cfparam name="Form.phone" default=""> 
<cfparam name="Form.department" default=""> 
<!--- If at least the firstname form field is passed, create 
a structure named employee and add values. ---> 
<cfif #Form.firstname# eq ""> 
<p>Please fill out the form.</p> 
<cfelse> 
<cfoutput> 
<cfscript> 
employee=StructNew(); 
employee.firstname = Form.firstname; 
employee.lastname = Form.lastname; 
employee.email = Form.email; 
employee.phone = Form.phone; 
employee.department = Form.department; 
</cfscript> 
<!--- Display results of creating the structure. ---> 
First name is #StructFind(employee, "firstname")#<br> 
Last name is #StructFind(employee, "lastname")#<br> 
EMail is #StructFind(employee, "email")#<br> 
Phone is #StructFind(employee, "phone")#<br> 
Department is #StructFind(employee, "department")#<br> 
</cfoutput> 
<!--- Call the custom tag that adds employees. ---> 
<cf_addemployee empinfo="#employee#"> 
</cfif> 
<!--- The form for adding the new employee information ---> 
<hr> 
<form action="newemployee.cfm" method="Post"> 
First Name:&nbsp; 
<input name="firstname" type="text" hspace="30" maxlength="30"><br> 
Last Name:&nbsp; 
<input name="lastname" type="text" hspace="30" maxlength="30"><br> 
EMail:&nbsp; 
<input name="email" type="text" hspace="30" maxlength="30"><br> 
Phone:&nbsp; 
<input name="phone" type="text" hspace="20" maxlength="20"><br> 
Department:&nbsp; 
<input name="department" type="text" hspace="30" maxlength="30"><br> 
<input type="Submit" value="OK"> 
</form> 
<br> 
</body> 
</html>

View File

@ -0,0 +1,54 @@
<head>
<title>Add New Employees</title>
</head>
<body>
<h1>Add New Employees</h1>
<!--- Action page code for the form at the bottom of this page. --->
<!--- Establish parameters for first time through --->
<cfparam name="Form.firstname" default="">
<cfparam name="Form.lastname" default="">
<cfparam name="Form.email" default="">
<cfparam name="Form.phone" default="">
<cfparam name="Form.department" default="">
<!--- If at least the firstname form field is passed, create
a structure named employee and add values. --->
<cfif #Form.firstname# eq "">
<p>Please fill out the form.</p>
<cfelse>
<cfoutput>
<cfscript>
employee=StructNew();
employee.firstname = Form.firstname;
employee.lastname = Form.lastname;
employee.email = Form.email;
employee.phone = Form.phone;
employee.department = Form.department;
</cfscript>
<!--- Display results of creating the structure. --->
First name is #StructFind(employee, "firstname")#<br>
Last name is #StructFind(employee, "lastname")#<br>
EMail is #StructFind(employee, "email")#<br>
Phone is #StructFind(employee, "phone")#<br>
Department is #StructFind(employee, "department")#<br>
</cfoutput>
<!--- Call the custom tag that adds employees. --->
<cf_addemployee empinfo="#employee#">
</cfif>
<!--- The form for adding the new employee information --->
<hr>
<form action="newemployee.cfm" method="Post">
First Name:&nbsp;
<input name="firstname" type="text" hspace="30" maxlength="30"><br>
Last Name:&nbsp;
<input name="lastname" type="text" hspace="30" maxlength="30"><br>
EMail:&nbsp;
<input name="email" type="text" hspace="30" maxlength="30"><br>
Phone:&nbsp;
<input name="phone" type="text" hspace="20" maxlength="20"><br>
Department:&nbsp;
<input name="department" type="text" hspace="30" maxlength="30"><br>
<input type="Submit" value="OK">
</form>
<br>
</body>
</html>