on master help sign in
171 files changed+1478−300
since splitsnapshots
unifiedsplit
.github/ISSUE_TEMPLATE/bug_report.md+19−2 .github/ISSUE_TEMPLATE/question.md+2 .github/workflows/CICD.yml+13−1 .gitmodules+8 CHANGELOG.md+71 CONTRIBUTING.md+22 Cargo.lock+118−112 Cargo.toml+15−15 README.md+34−3 assets/acknowledgements.bin assets/completions/_bat.ps1.in+1−1 assets/completions/bat.bash.in+15−2 assets/completions/bat.fish.in+1−1 assets/completions/bat.zsh.in+1−1 assets/manual/bat.1.in+2−1 assets/syntaxes.bin assets/syntaxes/02_Extra/Fish+1−1 assets/syntaxes/02_Extra/GLSL+1−1 assets/syntaxes/02_Extra/GraphQL+1−1 assets/syntaxes/02_Extra/INI.sublime-syntax+2−2 assets/syntaxes/02_Extra/Nginx+1−1 assets/syntaxes/02_Extra/SublimeJQ+1 assets/syntaxes/02_Extra/TOML+1−1 assets/syntaxes/02_Extra/VimL+1−1 assets/syntaxes/02_Extra/Zig+1−1 assets/syntaxes/02_Extra/cmd-help+1 assets/syntaxes/02_Extra/log.sublime-syntax+30−6 assets/themes.bin doc/README-ja.md+1−1 doc/README-ru.md+1−1 doc/release-checklist.md+28−18 doc/sponsors.md+14 doc/sponsors/workos-logo-white-bg.svg+11 rustfmt.toml+1 src/assets.rs+75−6 src/assets/build_assets/acknowledgements.rs+3 src/bin/bat/app.rs+1−1 src/bin/bat/clap_app.rs+20−8 src/bin/bat/config.rs+1−1 src/bin/bat/main.rs+11 src/error.rs+4−1 src/input.rs+9−2 src/less.rs+59−8 src/output.rs+7−5 src/preprocessor.rs+10−3 src/pretty_printer.rs+6 src/printer.rs+96−33 src/style.rs+30−4 src/syntax_mapping.rs+24−2 tests/benchmarks/many-small-files/small-file-0.txt+1 tests/benchmarks/many-small-files/small-file-1.txt+1 tests/benchmarks/many-small-files/small-file-10.txt+1 tests/benchmarks/many-small-files/small-file-100.txt+1 tests/benchmarks/many-small-files/small-file-11.txt+1 tests/benchmarks/many-small-files/small-file-12.txt+1 tests/benchmarks/many-small-files/small-file-13.txt+1 tests/benchmarks/many-small-files/small-file-14.txt+1 tests/benchmarks/many-small-files/small-file-15.txt+1 tests/benchmarks/many-small-files/small-file-16.txt+1 tests/benchmarks/many-small-files/small-file-17.txt+1 tests/benchmarks/many-small-files/small-file-18.txt+1 tests/benchmarks/many-small-files/small-file-19.txt+1 tests/benchmarks/many-small-files/small-file-2.txt+1 tests/benchmarks/many-small-files/small-file-20.txt+1 tests/benchmarks/many-small-files/small-file-21.txt+1 tests/benchmarks/many-small-files/small-file-22.txt+1 tests/benchmarks/many-small-files/small-file-23.txt+1 tests/benchmarks/many-small-files/small-file-24.txt+1 tests/benchmarks/many-small-files/small-file-25.txt+1 tests/benchmarks/many-small-files/small-file-26.txt+1 tests/benchmarks/many-small-files/small-file-27.txt+1 tests/benchmarks/many-small-files/small-file-28.txt+1 tests/benchmarks/many-small-files/small-file-29.txt+1 tests/benchmarks/many-small-files/small-file-3.txt+1 tests/benchmarks/many-small-files/small-file-30.txt+1 tests/benchmarks/many-small-files/small-file-31.txt+1 tests/benchmarks/many-small-files/small-file-32.txt+1 tests/benchmarks/many-small-files/small-file-33.txt+1 tests/benchmarks/many-small-files/small-file-34.txt+1 tests/benchmarks/many-small-files/small-file-35.txt+1 tests/benchmarks/many-small-files/small-file-36.txt+1 tests/benchmarks/many-small-files/small-file-37.txt+1 tests/benchmarks/many-small-files/small-file-38.txt+1 tests/benchmarks/many-small-files/small-file-39.txt+1 tests/benchmarks/many-small-files/small-file-4.txt+1 tests/benchmarks/many-small-files/small-file-40.txt+1 tests/benchmarks/many-small-files/small-file-41.txt+1 tests/benchmarks/many-small-files/small-file-42.txt+1 tests/benchmarks/many-small-files/small-file-43.txt+1 tests/benchmarks/many-small-files/small-file-44.txt+1 tests/benchmarks/many-small-files/small-file-45.txt+1 tests/benchmarks/many-small-files/small-file-46.txt+1 tests/benchmarks/many-small-files/small-file-47.txt+1 tests/benchmarks/many-small-files/small-file-48.txt+1 tests/benchmarks/many-small-files/small-file-49.txt+1 tests/benchmarks/many-small-files/small-file-5.txt+1 tests/benchmarks/many-small-files/small-file-50.txt+1 tests/benchmarks/many-small-files/small-file-51.txt+1 tests/benchmarks/many-small-files/small-file-52.txt+1 tests/benchmarks/many-small-files/small-file-53.txt+1 tests/benchmarks/many-small-files/small-file-54.txt+1 tests/benchmarks/many-small-files/small-file-55.txt+1 tests/benchmarks/many-small-files/small-file-56.txt+1 tests/benchmarks/many-small-files/small-file-57.txt+1 tests/benchmarks/many-small-files/small-file-58.txt+1 tests/benchmarks/many-small-files/small-file-59.txt+1 tests/benchmarks/many-small-files/small-file-6.txt+1 tests/benchmarks/many-small-files/small-file-60.txt+1 tests/benchmarks/many-small-files/small-file-61.txt+1 tests/benchmarks/many-small-files/small-file-62.txt+1 tests/benchmarks/many-small-files/small-file-63.txt+1 tests/benchmarks/many-small-files/small-file-64.txt+1 tests/benchmarks/many-small-files/small-file-65.txt+1 tests/benchmarks/many-small-files/small-file-66.txt+1 tests/benchmarks/many-small-files/small-file-67.txt+1 tests/benchmarks/many-small-files/small-file-68.txt+1 tests/benchmarks/many-small-files/small-file-69.txt+1 tests/benchmarks/many-small-files/small-file-7.txt+1 tests/benchmarks/many-small-files/small-file-70.txt+1 tests/benchmarks/many-small-files/small-file-71.txt+1 tests/benchmarks/many-small-files/small-file-72.txt+1 tests/benchmarks/many-small-files/small-file-73.txt+1 tests/benchmarks/many-small-files/small-file-74.txt+1 tests/benchmarks/many-small-files/small-file-75.txt+1 tests/benchmarks/many-small-files/small-file-76.txt+1 tests/benchmarks/many-small-files/small-file-77.txt+1 tests/benchmarks/many-small-files/small-file-78.txt+1 tests/benchmarks/many-small-files/small-file-79.txt+1 tests/benchmarks/many-small-files/small-file-8.txt+1 tests/benchmarks/many-small-files/small-file-80.txt+1 tests/benchmarks/many-small-files/small-file-81.txt+1 tests/benchmarks/many-small-files/small-file-82.txt+1 tests/benchmarks/many-small-files/small-file-83.txt+1 tests/benchmarks/many-small-files/small-file-84.txt+1 tests/benchmarks/many-small-files/small-file-85.txt+1 tests/benchmarks/many-small-files/small-file-86.txt+1 tests/benchmarks/many-small-files/small-file-87.txt+1 tests/benchmarks/many-small-files/small-file-88.txt+1 tests/benchmarks/many-small-files/small-file-89.txt+1 tests/benchmarks/many-small-files/small-file-9.txt+1 tests/benchmarks/many-small-files/small-file-90.txt+1 tests/benchmarks/many-small-files/small-file-91.txt+1 tests/benchmarks/many-small-files/small-file-92.txt+1 tests/benchmarks/many-small-files/small-file-93.txt+1 tests/benchmarks/many-small-files/small-file-94.txt+1 tests/benchmarks/many-small-files/small-file-95.txt+1 tests/benchmarks/many-small-files/small-file-96.txt+1 tests/benchmarks/many-small-files/small-file-97.txt+1 tests/benchmarks/many-small-files/small-file-98.txt+1 tests/benchmarks/many-small-files/small-file-99.txt+1 tests/benchmarks/run-benchmarks.sh+15−5 tests/examples/git/.config/git/config+3 tests/examples/git/.gitconfig+3 tests/examples/longline.json+3 tests/integration_tests.rs+250−3 tests/snapshots/output/full.snapshot.txt+1 tests/syntax-tests/highlighted/INI/test.inf+5 tests/syntax-tests/highlighted/JQ/sample.jq+60 tests/syntax-tests/highlighted/Log/example.log+1 tests/syntax-tests/highlighted/Svelte/App.svelte+5−1 tests/syntax-tests/highlighted/Syslog/example.syslog+3−3 tests/syntax-tests/highlighted/Vue/example.vue+5 tests/syntax-tests/highlighted/Zig/example.zig+39−39 tests/syntax-tests/highlighted/cmd-help/test.cmd-help+54 tests/syntax-tests/source/INI/test.inf+5 tests/syntax-tests/source/JQ/LICENSE.md+25 tests/syntax-tests/source/JQ/sample.jq+60 tests/syntax-tests/source/Log/example.log+1 tests/syntax-tests/source/Svelte/App.svelte+5−1 tests/syntax-tests/source/Vue/example.vue+5 tests/syntax-tests/source/cmd-help/test.cmd-help+54
.github/ISSUE_TEMPLATE/bug_report.md+19−2
@@ -7,9 +7,26 @@ assignees: ''
77
88---
99
10−<!-- Hey there, thank you for creating an issue! -->
10+<!--
11+
12+Hey there, thank you for reporting a bug!
13+
14+Please note that the following bugs have already been reported:
15+
16+* dpkg: error processing archive /some/path/some-program.deb (--unpack):
17+ trying to overwrite '/usr/.crates2.json'
18+
19+ See https://github.com/sharkdp/bat/issues/938
20+
21+-->
22+
23+**What steps will reproduce the bug?**
24+
25+1. step 1
26+2. step 2
27+3. ...
1128
12−**Describe the bug you encountered:**
29+**What happens?**
1330
1431...
1532
.github/ISSUE_TEMPLATE/question.md+2
@@ -7,3 +7,5 @@ assignees: ''
77
88---
99
10+<!-- Using a normal ticket is still fine, but feel free to ask your
11+questions about bat on https://github.com/sharkdp/bat/discussions instead. -->
.github/workflows/CICD.yml+13−1
@@ -118,6 +118,18 @@ jobs:
118118 toolchain: stable
119119 default: true
120120 profile: minimal
121+ - name: Print -h
122+ uses: actions-rs/cargo@v1
123+ with:
124+ command: run
125+ args: --locked -- -h
126+ - name: Print --help
127+ uses: actions-rs/cargo@v1
128+ with:
129+ command: run
130+ args: --locked -- --help
131+ - name: Show man page
132+ run: man $(find . -name bat.1)
121133 - name: Check documentation
122134 env:
123135 RUSTDOCFLAGS: -D warnings
@@ -142,7 +154,7 @@ jobs:
142154 - { target: x86_64-apple-darwin , os: macos-10.15 }
143155 - { target: x86_64-pc-windows-gnu , os: windows-2019 }
144156 - { target: x86_64-pc-windows-msvc , os: windows-2019 }
145− - { target: x86_64-unknown-linux-gnu , os: ubuntu-20.04 }
157+ - { target: x86_64-unknown-linux-gnu , os: ubuntu-20.04, use-cross: true }
146158 - { target: x86_64-unknown-linux-musl , os: ubuntu-20.04, use-cross: true }
147159 steps:
148160 - name: Checkout source code
.gitmodules+8
@@ -236,3 +236,11 @@
236236[submodule "assets/syntaxes/02_Extra/Dart"]
237237 path = assets/syntaxes/02_Extra/Dart
238238 url = https://github.com/elMuso/Dartlight.git
239+[submodule "assets/syntaxes/02_Extra/SublimeJQ"]
240+ path = assets/syntaxes/02_Extra/SublimeJQ
241+ url = https://github.com/zogwarg/SublimeJQ.git
242+[submodule "assets/syntaxes/02_Extra/cmd-help"]
243+ path = assets/syntaxes/02_Extra/cmd-help
244+ url = https://github.com/victor-gp/cmd-help-sublime-syntax.git
245+ branch = main
246+ shallow = true
CHANGELOG.md+71
@@ -2,10 +2,14 @@
22
33## Features
44
5+- Make the default macOS theme depend on Dark Mode. See #2197, #1746 (@Enselic)
6+
57## Bugfixes
68
79## Other
810
11+- Relaxed glibc requirements on amd64, see #2106 and #2194 (@sharkdp)
12+
913## Syntaxes
1014
1115## Themes
@@ -13,6 +17,73 @@
1317## `bat` as a library
1418
1519
20+# v0.21.0
21+
22+## Features
23+
24+- Correctly render tab stops in `--show-all`, see #2038 (@Synthetica9)
25+- Add a `--style=default` option and make it the default. It is less verbose than `full`, see #2061 (@IsaacHorvath)
26+- Enable BusyBox `less` as pager, see #2162 (@nfisher1226)
27+- File extensions are now matched case-insensitively. See #1854, #2181 (@Enselic)
28+
29+## Bugfixes
30+
31+- Bump `regex` dependency from 1.5.4 to 1.5.5 to fix [CVE-2022-24713](https://blog.rust-lang.org/2022/03/08/cve-2022-24713.html), see #2145, #2139 (@Enselic)
32+- `bat` no longer crashes when encountering files that references missing syntaxes. See #915, #2181 (@Enselic)
33+
34+## Performance
35+
36+- Skip syntax highlighting on long lines (> 16384 chars) to help improve performance. See #2165 (@keith-hall)
37+- Vastly improve startup time by lazy-loading syntaxes via syntect 5.0.0. This makes bat display small files ~75% faster than before. See #951, #2181 (@Enselic)
38+
39+## Other
40+
41+- Include info about custom assets in `--diagnostics` if used. See #2107, #2144 (@Enselic)
42+
43+## Syntaxes
44+
45+- Mapped clang-format config file (.clang-format) to YAML syntax (@TruncatedDinosour)
46+- log syntax: improved handling of escape characters in double quoted strings. See #2123 (@keith-hall)
47+- Associate `/var/spool/mail/*` and `/var/mail/*` with the `Email` syntax. See #2156 (@cyqsimon)
48+- Added cmd-help syntax to scope --help messages. See #2148 (@victor-gp)
49+- Slightly adjust Zig syntax. See #2136 (@Enselic)
50+- Associate `.inf` files with the `INI` syntax. See #2190 (@Enselic)
51+
52+## `bat` as a library
53+
54+- Allow configuration of `show_nonprintable` with `PrettyPrinter`, see #2142
55+- The binary format of syntaxes.bin has been changed due to syntaxes now being lazy-loaded via syntect 5.0.0. See #2181 (@Enselic)
56+- Mark `bat::error::Error` enum as `#[non_exhaustive]` to allow adding new variants without future semver breakage. See #2181 (@Enselic)
57+- Change `Error::SyntectError(syntect::LoadingError)` to `Error::SyntectError(syntect::Error)`. See #2181 (@Enselic)
58+- Add `Error::SyntectLoadingError(syntect::LoadingError)` enum variant. See #2181 (@Enselic)
59+
60+
61+# v0.20.0
62+
63+## Features
64+
65+- New style component `header-filesize` to show size of the displayed file in the header. See #1988 (@mdibaiee)
66+- Use underline for line highlighting on ANSI, see #1730 (@mdibaiee)
67+
68+## Bugfixes
69+
70+- Fix bash completion on bash 3.x and bash-completion 1.x. See #2066 (@joshpencheon)
71+
72+## Syntaxes
73+
74+- `GraphQL`: Add support for interfaces implementing interfaces and consider ampersand an operator. See #2000
75+- Associate `_vimrc` and `_gvimrc` files with the `VimL` syntax. See #2002
76+- Associate `poetry.lock` files with the `TOML` syntax. See #2049
77+- Associate `.mesh`, `.task`, `.rgen`, `.rint`, `.rahit`, `.rchit`, `.rmiss`, and `.rcall` with the `GLSL` syntax. See #2050
78+- Added support for `JQ` syntax, see #2072
79+- Properly associate global git config files rooted in `$XDG_CONFIG_HOME/git/` or `$HOME/.config/git/`. See #2067 (@cyqsimon)
80+
81+## `bat` as a library
82+
83+- Exposed `get_syntax_set` and `get_theme` methods on `HighlightingAssets`. See #2030 (@dandavison)
84+- Added `HeaderFilename` and `HeaderFilesize` to `StyleComponent` enum, and mark it `#[non_exhaustive]`. See #1988 (@mdibaiee)
85+
86+
1687# v0.19.0
1788
1889## Performance
CONTRIBUTING.md+22
@@ -46,3 +46,25 @@ If you really think that a particular syntax or theme should be added for all
4646users, please read the corresponding
4747[documentation](https://github.com/sharkdp/bat/blob/master/doc/assets.md)
4848first.
49+
50+
51+## Regression tests
52+
53+You are strongly encouraged to add regression tests. Regression tests are great,
54+not least because they:
55+
56+* ensure that your contribution will never completely stop working,
57+
58+* makes code review easier, because it becomes very clear what the code is
59+ supposed to do.
60+
61+For functional changes, you most likely want to add a test to
62+[`tests/integration_tests.rs`](https://github.com/sharkdp/bat/blob/master/tests/integration_tests.rs).
63+Look at existing tests to know how to write a new test. In short, you will
64+invoke the `bat` binary with a certain set of arguments, and then assert on
65+stdout/stderr.
66+
67+To learn how to write regression tests for theme and syntax changes, read the
68+[Syntax
69+tests](https://github.com/sharkdp/bat/blob/master/doc/assets.md#syntax-tests)
70+section in `assets.md`.
Cargo.lock+118−112
@@ -19,11 +19,11 @@ dependencies = [
1919
2020[[package]]
2121name = "ansi_colours"
22−version = "1.0.4"
22+version = "1.1.1"
2323source = "registry+https://github.com/rust-lang/crates.io-index"
24−checksum = "60e2fb6138a49ad9f1cb3c6d8f8ccbdd5e62b4dab317c1b435a47ecd7da1d28f"
24+checksum = "32678233b67f9056b0c144b39d46dc3218637e8d84ad6038ded339e08b19620d"
2525dependencies = [
26− "cc",
26+ "rgb",
2727]
2828
2929[[package]]
@@ -37,9 +37,9 @@ dependencies = [
3737
3838[[package]]
3939name = "assert_cmd"
40−version = "2.0.2"
40+version = "2.0.4"
4141source = "registry+https://github.com/rust-lang/crates.io-index"
42−checksum = "e996dc7940838b7ef1096b882e29ec30a3149a3a443cdc8dba19ed382eca1fe2"
42+checksum = "93ae1ddd39efd67689deb1979d80bad3bf7f2b09c6e6117c8d1f2443b5e2f83e"
4343dependencies = [
4444 "bstr",
4545 "doc-comment",
@@ -74,7 +74,7 @@ checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd"
7474
7575[[package]]
7676name = "bat"
77−version = "0.19.0"
77+version = "0.21.0"
7878dependencies = [
7979 "ansi_colours",
8080 "ansi_term",
@@ -82,6 +82,7 @@ dependencies = [
8282 "atty",
8383 "bincode",
8484 "bugreport",
85+ "bytesize",
8586 "clap",
8687 "clircle",
8788 "console",
@@ -154,15 +155,27 @@ dependencies = [
154155
155156[[package]]
156157name = "bugreport"
157−version = "0.4.1"
158+version = "0.5.0"
158159source = "registry+https://github.com/rust-lang/crates.io-index"
159−checksum = "0014b4b2b4f63bfe69c3838470121290cc437fdc79785d408a761a21e8b2404c"
160+checksum = "535120b8182547808081a66f1f77a64533c780b23da26763e0ee34dfb94f98c9"
160161dependencies = [
161162 "git-version",
162163 "shell-escape",
163164 "sys-info",
164165]
165166
167+[[package]]
168+name = "bytemuck"
169+version = "1.7.3"
170+source = "registry+https://github.com/rust-lang/crates.io-index"
171+checksum = "439989e6b8c38d1b6570a384ef1e49c8848128f5a97f3914baef02920842712f"
172+
173+[[package]]
174+name = "bytesize"
175+version = "1.1.0"
176+source = "registry+https://github.com/rust-lang/crates.io-index"
177+checksum = "6c58ec36aac5066d5ca17df51b3e70279f5670a72102f5752cb7e7c856adfc70"
178+
166179[[package]]
167180name = "cc"
168181version = "1.0.72"
@@ -358,11 +371,20 @@ dependencies = [
358371 "regex",
359372]
360373
374+[[package]]
375+name = "fastrand"
376+version = "1.7.0"
377+source = "registry+https://github.com/rust-lang/crates.io-index"
378+checksum = "c3fcf0cee53519c866c09b5de1f6c56ff9d647101f81c1964fa632e148896cdf"
379+dependencies = [
380+ "instant",
381+]
382+
361383[[package]]
362384name = "flate2"
363−version = "1.0.22"
385+version = "1.0.23"
364386source = "registry+https://github.com/rust-lang/crates.io-index"
365−checksum = "1e6988e897c1c9c485f43b47a529cef42fde0547f9d8d41a7062518f1d8fc53f"
387+checksum = "b39522e96686d38f4bc984b9198e3a0613264abaebaff2c5c918bfa6b6da09af"
366388dependencies = [
367389 "cfg-if",
368390 "crc32fast",
@@ -430,9 +452,9 @@ dependencies = [
430452
431453[[package]]
432454name = "git2"
433−version = "0.13.25"
455+version = "0.14.2"
434456source = "registry+https://github.com/rust-lang/crates.io-index"
435−checksum = "f29229cc1b24c0e6062f6e742aa3e256492a5323365e5ed3413599f8a5eff7d6"
457+checksum = "3826a6e0e2215d7a41c2bfc7c9244123969273f3476b939a226aac0ab56e9e3c"
436458dependencies = [
437459 "bitflags",
438460 "libc",
@@ -558,23 +580,17 @@ version = "1.4.0"
558580source = "registry+https://github.com/rust-lang/crates.io-index"
559581checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
560582
561−[[package]]
562−name = "lazycell"
563−version = "1.3.0"
564−source = "registry+https://github.com/rust-lang/crates.io-index"
565−checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
566−
567583[[package]]
568584name = "libc"
569−version = "0.2.112"
585+version = "0.2.125"
570586source = "registry+https://github.com/rust-lang/crates.io-index"
571−checksum = "1b03d17f364a3a042d5e5d46b053bbbf82c92c9430c592dd4c064dc6ee997125"
587+checksum = "5916d2ae698f6de9bfb891ad7a8d65c09d232dc58cc4ac433c7da3b2fd84bc2b"
572588
573589[[package]]
574590name = "libgit2-sys"
575−version = "0.12.26+1.3.0"
591+version = "0.13.2+1.4.2"
576592source = "registry+https://github.com/rust-lang/crates.io-index"
577−checksum = "19e1c899248e606fbfe68dcb31d8b0176ebab833b103824af31bddf4b7457494"
593+checksum = "3a42de9a51a5c12e00fc0e4ca6bc2ea43582fc6418488e8f615e905d886f258b"
578594dependencies = [
579595 "cc",
580596 "libc",
@@ -639,36 +655,24 @@ version = "2.4.1"
639655source = "registry+https://github.com/rust-lang/crates.io-index"
640656checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a"
641657
642−[[package]]
643−name = "memoffset"
644−version = "0.6.5"
645−source = "registry+https://github.com/rust-lang/crates.io-index"
646−checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce"
647−dependencies = [
648− "autocfg",
649−]
650−
651658[[package]]
652659name = "miniz_oxide"
653−version = "0.4.4"
660+version = "0.5.1"
654661source = "registry+https://github.com/rust-lang/crates.io-index"
655−checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b"
662+checksum = "d2b29bd4bc3f33391105ebee3589c19197c4271e3e5a9ec9bfe8127eeff8f082"
656663dependencies = [
657664 "adler",
658− "autocfg",
659665]
660666
661667[[package]]
662668name = "nix"
663−version = "0.23.1"
669+version = "0.24.1"
664670source = "registry+https://github.com/rust-lang/crates.io-index"
665−checksum = "9f866317acbd3a240710c63f065ffb1e4fd466259045ccb504130b7f668f35c6"
671+checksum = "8f17df307904acd05aa8e32e97bb20f2a0df1728bbc2d771ae8f9a90463441e9"
666672dependencies = [
667673 "bitflags",
668− "cc",
669674 "cfg-if",
670675 "libc",
671− "memoffset",
672676]
673677
674678[[package]]
@@ -688,9 +692,9 @@ dependencies = [
688692
689693[[package]]
690694name = "once_cell"
691−version = "1.9.0"
695+version = "1.10.0"
692696source = "registry+https://github.com/rust-lang/crates.io-index"
693−checksum = "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5"
697+checksum = "87f3e037eac156d1775da914196f0f37741a274155e34a0b7e427c35d2a2ecb9"
694698
695699[[package]]
696700name = "onig"
@@ -774,17 +778,11 @@ dependencies = [
774778 "xml-rs",
775779]
776780
777−[[package]]
778−name = "ppv-lite86"
779−version = "0.2.16"
780−source = "registry+https://github.com/rust-lang/crates.io-index"
781−checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872"
782−
783781[[package]]
784782name = "predicates"
785−version = "2.1.0"
783+version = "2.1.1"
786784source = "registry+https://github.com/rust-lang/crates.io-index"
787−checksum = "95e5a7689e456ab905c22c2b48225bb921aba7c8dfa58440d68ba13f6222a715"
785+checksum = "a5aab5be6e4732b473071984b3164dbbfb7a3674d30ea5ff44410b6bcd960c3c"
788786dependencies = [
789787 "difflib",
790788 "float-cmp",
@@ -811,67 +809,51 @@ dependencies = [
811809]
812810
813811[[package]]
814−name = "proc-macro-hack"
815−version = "0.5.19"
816−source = "registry+https://github.com/rust-lang/crates.io-index"
817−checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5"
818−
819−[[package]]
820−name = "proc-macro2"
821−version = "1.0.36"
822−source = "registry+https://github.com/rust-lang/crates.io-index"
823−checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029"
824−dependencies = [
825− "unicode-xid",
826−]
827−
828−[[package]]
829−name = "quote"
830−version = "1.0.14"
812+name = "proc-macro-error"
813+version = "1.0.4"
831814source = "registry+https://github.com/rust-lang/crates.io-index"
832−checksum = "47aa80447ce4daf1717500037052af176af5d38cc3e571d9ec1c7353fc10c87d"
815+checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
833816dependencies = [
817+ "proc-macro-error-attr",
834818 "proc-macro2",
819+ "quote",
820+ "syn",
821+ "version_check",
835822]
836823
837824[[package]]
838−name = "rand"
839−version = "0.8.4"
825+name = "proc-macro-error-attr"
826+version = "1.0.4"
840827source = "registry+https://github.com/rust-lang/crates.io-index"
841−checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8"
828+checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
842829dependencies = [
843− "libc",
844− "rand_chacha",
845− "rand_core",
846− "rand_hc",
830+ "proc-macro2",
831+ "quote",
832+ "version_check",
847833]
848834
849835[[package]]
850−name = "rand_chacha"
851−version = "0.3.1"
836+name = "proc-macro-hack"
837+version = "0.5.19"
852838source = "registry+https://github.com/rust-lang/crates.io-index"
853−checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
854−dependencies = [
855− "ppv-lite86",
856− "rand_core",
857−]
839+checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5"
858840
859841[[package]]
860−name = "rand_core"
861−version = "0.6.3"
842+name = "proc-macro2"
843+version = "1.0.36"
862844source = "registry+https://github.com/rust-lang/crates.io-index"
863−checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7"
845+checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029"
864846dependencies = [
865− "getrandom",
847+ "unicode-xid",
866848]
867849
868850[[package]]
869−name = "rand_hc"
870−version = "0.3.1"
851+name = "quote"
852+version = "1.0.14"
871853source = "registry+https://github.com/rust-lang/crates.io-index"
872−checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7"
854+checksum = "47aa80447ce4daf1717500037052af176af5d38cc3e571d9ec1c7353fc10c87d"
873855dependencies = [
874− "rand_core",
856+ "proc-macro2",
875857]
876858
877859[[package]]
@@ -895,9 +877,9 @@ dependencies = [
895877
896878[[package]]
897879name = "regex"
898−version = "1.5.4"
880+version = "1.5.5"
899881source = "registry+https://github.com/rust-lang/crates.io-index"
900−checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461"
882+checksum = "1a11647b6b25ff05a515cb92c365cec08801e83423a235b51e231e1808747286"
901883dependencies = [
902884 "aho-corasick",
903885 "memchr",
@@ -925,6 +907,21 @@ dependencies = [
925907 "winapi",
926908]
927909
910+[[package]]
911+name = "rgb"
912+version = "0.8.31"
913+source = "registry+https://github.com/rust-lang/crates.io-index"
914+checksum = "9a374af9a0e5fdcdd98c1c7b64f05004f9ea2555b6c75f211daa81268a3c50f1"
915+dependencies = [
916+ "bytemuck",
917+]
918+
919+[[package]]
920+name = "rustversion"
921+version = "1.0.6"
922+source = "registry+https://github.com/rust-lang/crates.io-index"
923+checksum = "f2cc38e8fa666e2de3c4aba7edeb5ffc5246c1c2ed0e3d17e560aeeba736b23f"
924+
928925[[package]]
929926name = "ryu"
930927version = "1.0.9"
@@ -954,24 +951,24 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
954951
955952[[package]]
956953name = "semver"
957−version = "1.0.4"
954+version = "1.0.7"
958955source = "registry+https://github.com/rust-lang/crates.io-index"
959−checksum = "568a8e6258aa33c13358f81fd834adb854c6f7c9468520910a9b1e8fac068012"
956+checksum = "d65bd28f48be7196d222d95b9243287f48d27aca604e08497513019ff0502cc4"
960957
961958[[package]]
962959name = "serde"
963−version = "1.0.133"
960+version = "1.0.136"
964961source = "registry+https://github.com/rust-lang/crates.io-index"
965−checksum = "97565067517b60e2d1ea8b268e59ce036de907ac523ad83a0475da04e818989a"
962+checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789"
966963dependencies = [
967964 "serde_derive",
968965]
969966
970967[[package]]
971968name = "serde_derive"
972−version = "1.0.133"
969+version = "1.0.136"
973970source = "registry+https://github.com/rust-lang/crates.io-index"
974−checksum = "ed201699328568d8d08208fdd080e3ff594e6c422e438b6705905da01005d537"
971+checksum = "08597e7152fcd306f41838ed3e37be9eaeed2b61c42e2117266a554fab4662f9"
975972dependencies = [
976973 "proc-macro2",
977974 "quote",
@@ -1003,9 +1000,9 @@ dependencies = [
10031000
10041001[[package]]
10051002name = "serial_test"
1006−version = "0.5.1"
1003+version = "0.6.0"
10071004source = "registry+https://github.com/rust-lang/crates.io-index"
1008−checksum = "e0bccbcf40c8938196944a3da0e133e031a33f4d6b72db3bda3cc556e361905d"
1005+checksum = "e5bcc41d18f7a1d50525d080fd3e953be87c4f9f1a974f3c21798ca00d54ec15"
10091006dependencies = [
10101007 "lazy_static",
10111008 "parking_lot",
@@ -1014,12 +1011,14 @@ dependencies = [
10141011
10151012[[package]]
10161013name = "serial_test_derive"
1017−version = "0.5.1"
1014+version = "0.6.0"
10181015source = "registry+https://github.com/rust-lang/crates.io-index"
1019−checksum = "b2acd6defeddb41eb60bb468f8825d0cfd0c2a76bc03bfd235b6a1dc4f6a1ad5"
1016+checksum = "2881bccd7d60fb32dfa3d7b3136385312f8ad75e2674aab2852867a09790cae8"
10201017dependencies = [
1018+ "proc-macro-error",
10211019 "proc-macro2",
10221020 "quote",
1021+ "rustversion",
10231022 "syn",
10241023]
10251024
@@ -1031,9 +1030,9 @@ checksum = "45bb67a18fa91266cc7807181f62f9178a6873bfad7dc788c42e6430db40184f"
10311030
10321031[[package]]
10331032name = "shell-words"
1034−version = "1.0.0"
1033+version = "1.1.0"
10351034source = "registry+https://github.com/rust-lang/crates.io-index"
1036−checksum = "b6fa3938c99da4914afedd13bf3d79bcb6c277d1b2c398d23257a304d9e1b074"
1035+checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde"
10371036
10381037[[package]]
10391038name = "smallvec"
@@ -1066,9 +1065,9 @@ dependencies = [
10661065
10671066[[package]]
10681067name = "syntect"
1069−version = "4.6.0"
1068+version = "5.0.0"
10701069source = "registry+https://github.com/rust-lang/crates.io-index"
1071−checksum = "8b20815bbe80ee0be06e6957450a841185fcf690fe0178f14d77a05ce2caa031"
1070+checksum = "c6c454c27d9d7d9a84c7803aaa3c50cd088d2906fe3c6e42da3209aa623576a8"
10721071dependencies = [
10731072 "bincode",
10741073 "bitflags",
@@ -1076,13 +1075,14 @@ dependencies = [
10761075 "flate2",
10771076 "fnv",
10781077 "lazy_static",
1079− "lazycell",
1078+ "once_cell",
10801079 "onig",
10811080 "plist",
10821081 "regex-syntax",
10831082 "serde",
10841083 "serde_derive",
10851084 "serde_json",
1085+ "thiserror",
10861086 "walkdir",
10871087 "yaml-rust",
10881088]
@@ -1099,13 +1099,13 @@ dependencies = [
10991099
11001100[[package]]
11011101name = "tempfile"
1102−version = "3.2.0"
1102+version = "3.3.0"
11031103source = "registry+https://github.com/rust-lang/crates.io-index"
1104−checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22"
1104+checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4"
11051105dependencies = [
11061106 "cfg-if",
1107+ "fastrand",
11071108 "libc",
1108− "rand",
11091109 "redox_syscall",
11101110 "remove_dir_all",
11111111 "winapi",
@@ -1158,18 +1158,18 @@ dependencies = [
11581158
11591159[[package]]
11601160name = "thiserror"
1161−version = "1.0.30"
1161+version = "1.0.31"
11621162source = "registry+https://github.com/rust-lang/crates.io-index"
1163−checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417"
1163+checksum = "bd829fe32373d27f76265620b5309d0340cb8550f523c1dda251d6298069069a"
11641164dependencies = [
11651165 "thiserror-impl",
11661166]
11671167
11681168[[package]]
11691169name = "thiserror-impl"
1170−version = "1.0.30"
1170+version = "1.0.31"
11711171source = "registry+https://github.com/rust-lang/crates.io-index"
1172−checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b"
1172+checksum = "0396bc89e626244658bef819e22d0cc459e795a5ebe878e6ec336d1674a8d79a"
11731173dependencies = [
11741174 "proc-macro2",
11751175 "quote",
@@ -1252,6 +1252,12 @@ version = "0.8.2"
12521252source = "registry+https://github.com/rust-lang/crates.io-index"
12531253checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
12541254
1255+[[package]]
1256+name = "version_check"
1257+version = "0.9.4"
1258+source = "registry+https://github.com/rust-lang/crates.io-index"
1259+checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
1260+
12551261[[package]]
12561262name = "wait-timeout"
12571263version = "0.2.0"
Cargo.toml+15−15
@@ -6,7 +6,7 @@ homepage = "https://github.com/sharkdp/bat"
66license = "MIT/Apache-2.0"
77name = "bat"
88repository = "https://github.com/sharkdp/bat"
9−version = "0.19.0"
9+version = "0.21.0"
1010exclude = ["assets/syntaxes/*", "assets/themes/*"]
1111build = "build.rs"
1212edition = '2018'
@@ -33,8 +33,7 @@ minimal-application = [
3333]
3434git = ["git2"] # Support indicating git modifications
3535paging = ["shell-words", "grep-cli"] # Support applying a pager on the output
36−# Add "syntect/plist-load" when https://github.com/trishume/syntect/pull/345 reaches us
37−build-assets = ["syntect/yaml-load", "syntect/dump-create", "regex", "walkdir"]
36+build-assets = ["syntect/yaml-load", "syntect/plist-load", "regex", "walkdir"]
3837
3938# You need to use one of these if you depend on bat as a library:
4039regex-onig = ["syntect/regex-onig"] # Use the "oniguruma" regex engine
@@ -43,16 +42,16 @@ regex-fancy = ["syntect/regex-fancy"] # Use the rust-only "fancy-regex" engine
4342[dependencies]
4443atty = { version = "0.2.14", optional = true }
4544ansi_term = "^0.12.1"
46−ansi_colours = "^1.0"
45+ansi_colours = "^1.1"
4746bincode = "1.0"
4847console = "0.15.0"
4948flate2 = "1.0"
50−once_cell = "1.9"
49+once_cell = "1.10"
5150thiserror = "1.0"
5251wild = { version = "2.0", optional = true }
5352content_inspector = "0.2.4"
5453encoding = "0.2"
55−shell-words = { version = "1.0.0", optional = true }
54+shell-words = { version = "1.1.0", optional = true }
5655unicode-width = "0.1.9"
5756globset = "0.4"
5857serde = { version = "1.0", features = ["derive"] }
@@ -60,19 +59,20 @@ serde_yaml = "0.8"
6059semver = "1.0"
6160path_abs = { version = "0.5", default-features = false }
6261clircle = "0.3"
63−bugreport = { version = "0.4", optional = true }
62+bugreport = { version = "0.5.0", optional = true }
6463dirs-next = { version = "2.0.0", optional = true }
6564grep-cli = { version = "0.1.6", optional = true }
66−regex = { version = "1.0", optional = true }
65+regex = { version = "1.5.5", optional = true }
6766walkdir = { version = "2.0", optional = true }
67+bytesize = { version = "1.1.0" }
6868
6969[dependencies.git2]
70−version = "0.13"
70+version = "0.14"
7171optional = true
7272default-features = false
7373
7474[dependencies.syntect]
75−version = "4.6.0"
75+version = "5.0.0"
7676default-features = false
7777features = ["parsing"]
7878
@@ -83,14 +83,14 @@ default-features = false
8383features = ["suggestions", "color", "wrap_help"]
8484
8585[dev-dependencies]
86−assert_cmd = "2.0.2"
87−serial_test = "0.5.1"
88−predicates = "2.1.0"
86+assert_cmd = "2.0.4"
87+serial_test = "0.6.0"
88+predicates = "2.1.1"
8989wait-timeout = "0.2.0"
90−tempfile = "3.2.0"
90+tempfile = "3.3.0"
9191
9292[target.'cfg(unix)'.dev-dependencies]
93−nix = "0.23.1"
93+nix = { version = "0.24.1", default-features = false, features = ["term"] }
9494
9595[build-dependencies]
9696clap = { version = "2.34", optional = true }
README.md+34−3
@@ -19,6 +19,19 @@
1919 [<a href="doc/README-ru.md">Русский</a>]
2020</p>
2121
22+### Sponsors
23+
24+A special *thank you* goes to our biggest <a href="doc/sponsors.md">sponsors</a>:<br>
25+<a href="https://workos.com/?utm_campaign=github_repo&utm_medium=referral&utm_content=bat&utm_source=github">
26+ <img src="doc/sponsors/workos-logo-white-bg.svg" width="200" alt="WorkOS">
27+ <br>
28+ <strong>Your app, enterprise-ready.</strong>
29+ <br>
30+ <sub>Start selling to enterprise customers with just a few lines of code.</sub>
31+ <br>
32+ <sup>Add Single Sign-On (and more) in minutes instead of months.</sup>
33+</a>
34+
2235### Syntax highlighting
2336
2437`bat` supports syntax highlighting for a large number of programming and markup
@@ -158,7 +171,7 @@ You can combine `bat` with `git diff` to view lines around code changes with pro
158171highlighting:
159172```bash
160173batdiff() {
161− git diff --name-only --diff-filter=d | xargs bat --diff
174+ git diff --name-only --relative --diff-filter=d | xargs bat --diff
162175}
163176```
164177If you prefer to use this as a separate tool, check out `batdiff` in [`bat-extras`](https://github.com/eth-p/bat-extras).
@@ -199,6 +212,24 @@ Also, note that this will [not work](https://github.com/sharkdp/bat/issues/1145)
199212
200213The [`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`.
201214
215+#### Highlighting `--help` messages
216+
217+You can use `bat` to colorize help text: `$ cp --help | bat -plhelp`
218+
219+You can also use a wrapper around this:
220+
221+```bash
222+# in your .bashrc/.zshrc/*rc
223+alias bathelp='bat --plain --language=help'
224+help() {
225+ "$@" --help 2>&1 | bathelp
226+}
227+```
228+
229+Then you can do `$ help cp` or `$ help git commit`.
230+
231+Please report any issues with the help syntax in [this repository](https://github.com/victor-gp/cmd-help-sublime-syntax).
232+
202233
203234## Installation
204235
@@ -515,8 +546,8 @@ command line option. The option takes an argument of the form `pattern:syntax` w
515546the absolute file path. The `syntax` part is the full name of a supported language
516547(use `bat --list-languages` for an overview).
517548
518−*Note:* You probably want to use this option as [an entry in `bat`'s configuration file](#configuration-file)
519−for persistence, instead of passing it on the command line as a one-off, as generally
549+**Note:** You probably want to use this option as [an entry in `bat`'s configuration file](#configuration-file)
550+for persistence instead of passing it on the command line as a one-off. Generally
520551you'd just use `-l` if you want to manually specify a language for a file.
521552
522553Example: To use "INI" syntax highlighting for all files with a `.conf` file extension, use
assets/acknowledgements.bin

Binary file not shown.

assets/completions/_bat.ps1.in+1−1
@@ -37,7 +37,7 @@ Register-ArgumentCompleter -Native -CommandName '{{PROJECT_EXECUTABLE}}' -Script
3737 [CompletionResult]::new('-m', 'm', [CompletionResultType]::ParameterName, 'Use the specified syntax for files matching the glob pattern (''*.cpp:C++'').')
3838 [CompletionResult]::new('--map-syntax', 'map-syntax', [CompletionResultType]::ParameterName, 'Use the specified syntax for files matching the glob pattern (''*.cpp:C++'').')
3939 [CompletionResult]::new('--theme', 'theme', [CompletionResultType]::ParameterName, 'Set the color theme for syntax highlighting.')
40− [CompletionResult]::new('--style', 'style', [CompletionResultType]::ParameterName, 'Comma-separated list of style elements to display (*auto*, full, plain, changes, header, grid, rule, numbers, snip).')
40+ [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).')
4141 [CompletionResult]::new('-r', 'r', [CompletionResultType]::ParameterName, 'Only print the lines from N to M.')
4242 [CompletionResult]::new('--line-range', 'line-range', [CompletionResultType]::ParameterName, 'Only print the lines from N to M.')
4343 [CompletionResult]::new('-A', 'A', [CompletionResultType]::ParameterName, 'Show non-printable characters (space, tab, newline, ..).')
assets/completions/bat.bash.in+15−2
@@ -2,9 +2,22 @@
22
33# Requires https://github.com/scop/bash-completion
44
5+# Macs have bash3 for which the bash-completion package doesn't include
6+# _init_completion. This is a minimal version of that function.
7+__bat_init_completion()
8+{
9+ COMPREPLY=()
10+ _get_comp_words_by_ref "$@" cur prev words cword
11+}
12+
513_bat() {
6− local cur prev words cword split
7− _init_completion -s || return 0
14+ local cur prev words cword split=false
15+ if declare -F _init_completion >/dev/null 2>&1; then
16+ _init_completion -s || return 0
17+ else
18+ __bat_init_completion -n "=" || return 0
19+ _split_longopt && split=true
20+ fi
821
922 if [[ ${words[1]-} == cache ]]; then
1023 case $prev in
assets/completions/bat.fish.in+1−1
@@ -56,7 +56,7 @@ complete -c {{PROJECT_EXECUTABLE}} -s P -d "Disable paging. Alias for '--paging=
5656
5757complete -c {{PROJECT_EXECUTABLE}} -s A -l show-all -d "Show non-printable characters like space/tab/newline" -n "not __fish_seen_subcommand_from cache"
5858
59−complete -c {{PROJECT_EXECUTABLE}} -l style -xka "auto full plain changes header grid rule numbers snip" -d "Comma-separated list of style elements or presets to display with file contents" -n "not __fish_seen_subcommand_from cache"
59+complete -c {{PROJECT_EXECUTABLE}} -l style -xka "default auto full plain changes header header-filename header-filesize grid rule numbers snip" -d "Comma-separated list of style elements or presets to display with file contents" -n "not __fish_seen_subcommand_from cache"
6060
6161complete -c {{PROJECT_EXECUTABLE}} -l tabs -x -d "<T> Set the tab width to T spaces (width of 0 passes tabs through directly)" -n "not __fish_seen_subcommand_from cache"
6262
assets/completions/bat.zsh.in+1−1
@@ -75,7 +75,7 @@ _{{PROJECT_EXECUTABLE}}_main() {
7575 ;;
7676
7777 style)
78− _values -s , 'style' auto full plain changes header grid rule numbers snip
78+ _values -s , 'style' default auto full plain changes header header-filename header-filesize grid rule numbers snip
7979 ;;
8080 esac
8181}
assets/manual/bat.1.in+2−1
@@ -146,7 +146,8 @@ Configure which elements (line numbers, file headers, grid borders, Git modifica
146146of components to display (e.g. 'numbers,changes,grid') or a pre\-defined style ('full').
147147To set a default style, add the '\-\-style=".."' option to the configuration file or
148148export the BAT_STYLE environment variable (e.g.: export BAT_STYLE=".."). Possible
149−values: *full*, auto, plain, changes, header, grid, rule, numbers, snip.
149+values: *default*, full, auto, plain, changes, header, header-filename, header-filesize, grid,
150+rule, numbers, snip.
150151.HP
151152\fB\-r\fR, \fB\-\-line\-range\fR <N:M>...
152153.IP
assets/syntaxes.bin

Binary file not shown.

assets/syntaxes/02_Extra/Fish+1−1

Submodule changed.

assets/syntaxes/02_Extra/GLSL+1−1

Submodule changed.

assets/syntaxes/02_Extra/GraphQL+1−1

Submodule changed.

assets/syntaxes/02_Extra/INI.sublime-syntax+2−2
@@ -5,8 +5,8 @@ name: INI
55file_extensions:
66 - ini
77 - INI
8− - inf
9− - INF
8+ - "inf"
9+ - "INF"
1010 - reg
1111 - REG
1212 - lng
assets/syntaxes/02_Extra/Nginx+1−1

Submodule changed.

assets/syntaxes/02_Extra/SublimeJQnew file+1

Submodule changed.

assets/syntaxes/02_Extra/TOML+1−1

Submodule changed.

assets/syntaxes/02_Extra/VimL+1−1

Submodule changed.

assets/syntaxes/02_Extra/Zig+1−1

Submodule changed.

assets/syntaxes/02_Extra/cmd-helpnew file+1

Submodule changed.

assets/syntaxes/02_Extra/log.sublime-syntax+30−6
@@ -6,6 +6,7 @@ file_extensions:
66scope: text.log
77variables:
88 ipv4_part: (?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)
9+ hours_minutes_seconds: (?:[01]\d|2[0-3]):(?:[0-5]\d):(?:[0-5]\d)
910contexts:
1011 main:
1112 - match: (\w+)(=)
@@ -17,11 +18,10 @@ contexts:
1718 captures:
1819 1: punctuation.definition.string.begin.log
1920 3: punctuation.definition.string.end.log
20− - match: (")([^"]*)(")
21− scope: string.quoted.double.log
21+ - match: \"
2222 captures:
2323 1: punctuation.definition.string.begin.log
24− 3: punctuation.definition.string.end.log
24+ push: double_quoted_string
2525 - include: dates
2626 - include: ip_addresses
2727 - include: numbers
@@ -29,19 +29,34 @@ contexts:
2929 scope: markup.error.log
3030 - match: \b(?i:warn(?:ing)?)\b
3131 scope: markup.warning.log
32+ - match: \b(?i:debug)\b
33+ scope: markup.info.log
3234 #- include: scope:text.html.markdown#autolink-inet
3335 - match: \b\w+:/{2,3}
3436 scope: markup.underline.link.scheme.log
3537 push: url-host
3638 dates:
37− - match: \b\d{4}-\d{2}-\d{2}\b
39+ - match: \b\d{4}-\d{2}-\d{2}(?=\b|T)
3840 scope: meta.date.log meta.number.integer.decimal.log constant.numeric.value.log
39− - match: \b\d{4}/\d{2}/\d{2}\b
41+ push: maybe_date_time_separator
42+ - match: \b\d{4}/\d{2}/\d{2}(?=\b|T)
4043 scope: meta.date.log meta.number.integer.decimal.log constant.numeric.value.log
41− - match: \b(?:[01]\d|2[0-3]):(?:[0-5]\d):(?:[0-5]\d)(?:(\.)\d{3})?\b
44+ push: maybe_date_time_separator
45+ - match: \b(?={{hours_minutes_seconds}})
46+ push: time
47+ time:
48+ - match: (?:{{hours_minutes_seconds}})(?:(\.)\d{3})?\b
4249 scope: meta.time.log meta.number.integer.decimal.log constant.numeric.value.log
4350 captures:
4451 1: punctuation.separator.decimal.log
52+ - match: ''
53+ pop: true
54+ maybe_date_time_separator:
55+ - match: T(?={{hours_minutes_seconds}})
56+ scope: meta.date.log meta.time.log keyword.other.log
57+ set: time
58+ - match: ''
59+ pop: true
4560 ip_addresses:
4661 - match: \b(?=(?:{{ipv4_part}}\.){3}{{ipv4_part}}\b)
4762 push:
@@ -114,3 +129,12 @@ contexts:
114129 scope: markup.underline.link.path.log
115130 - match: ''
116131 pop: true
132+ double_quoted_string:
133+ - meta_scope: string.quoted.double.log
134+ - match: \\"
135+ scope: constant.character.escape.log
136+ - match: \\n
137+ scope: constant.character.escape.log
138+ - match: \"
139+ scope: punctuation.definition.string.end.log
140+ pop: true
assets/themes.bin

Binary file not shown.

doc/README-ja.md+1−1
@@ -181,7 +181,7 @@ man 2 select
181181
182182## インストール
183183
184−[![Packaging status](https://repology.org/badge/vertical-allrepos/bat.svg)](https://repology.org/project/bat/versions)
184+[![Packaging status](https://repology.org/badge/vertical-allrepos/bat-cat.svg)](https://repology.org/project/bat-cat/versions)
185185
186186### On Ubuntu (`apt` を使用)
187187*... や他のDebianベースのLinuxディストリビューション*
doc/README-ru.md+1−1
@@ -160,7 +160,7 @@ man 2 select
160160
161161## Установка
162162
163−[![Packaging status](https://repology.org/badge/vertical-allrepos/bat.svg)](https://repology.org/project/bat/versions)
163+[![Packaging status](https://repology.org/badge/vertical-allrepos/bat-cat.svg)](https://repology.org/project/bat-cat/versions)
164164
165165### Ubuntu (с помощью `apt`)
166166*... и другие дистрибутивы основанные на Debian.*
doc/release-checklist.md+28−18
@@ -1,16 +1,5 @@
11# Release checklist
22
3−## Dependencies
4−
5−See this page for a good overview: https://deps.rs/repo/github/sharkdp/bat
6−
7−- [ ] Optional: update dependencies with `cargo update`. This is also done by
8− dependabot, so it is not strictly necessary.
9−- [ ] Install [cargo-outdated](https://crates.io/crates/cargo-outdated). Check
10− for outdated dependencies with `cargo outdated --root-deps-only` and
11− decide for each of them whether we want to (manually) upgrade. This will
12− require changes to `Cargo.toml`.
13−
143## Version bump
154
165- [ ] Update version in `Cargo.toml`. Run `cargo build` to update `Cargo.lock`.
@@ -18,21 +7,22 @@ See this page for a good overview: https://deps.rs/repo/github/sharkdp/bat
187- [ ] Find the current min. supported Rust version by running
198 `grep '^\s*MIN_SUPPORTED_RUST_VERSION' .github/workflows/CICD.yml`.
209- [ ] Update the version and the min. supported Rust version in `README.md` and
21− `doc/README-*.md`. Check with `git grep -i 'rust.*1\.'` and
22− `git grep -i '1\..*rust'`.
10+ `doc/README-*.md`. Check with
11+ `git grep -i -e 'rust.*1\.' -e '1\..*rust' | grep README | grep -v tests/`.
2312- [ ] Update `CHANGELOG.md`. Introduce a section for the new release.
2413
2514## Update syntaxes and themes (build assets)
2615
27−- [ ] Install the latest master version (`cargo install -f --path .`) and make
16+- [ ] Install the latest master version (`cargo clean && cargo install --locked -f --path .`) and make
2817 sure that it is available on the `PATH` (`bat --version` should show the
2918 new version).
3019- [ ] Run `assets/create.sh` and check in the binary asset files.
3120
3221## Documentation
3322
34−- [ ] Review the `-h` and `--help` texts
35−- [ ] Review the `man` page
23+- [ ] Review `-h`, `--help`, and the `man` page. All of these are shown in
24+ the output of the CI job called *Documentation*, so look there.
25+ The CI workflow corresponding to the tip of the master branch is a good place to look.
3626
3727## Pre-release checks
3828
@@ -41,13 +31,14 @@ See this page for a good overview: https://deps.rs/repo/github/sharkdp/bat
4131- [ ] Optional: manually test the new features and command-line options. To do
4232 this, install the latest `bat` version again (to include the new syntaxes
4333 and themes).
44−- [ ] Run `cargo publish --dry-run --allow-dirty` to make sure that it will
34+- [ ] Run `cargo publish --dry-run` to make sure that it will
4535 succeed later (after creating the GitHub release).
4636
4737## Release
4838
4939- [ ] Create a tag and push it: `git tag vX.Y.Z; git push origin tag vX.Y.Z`.
5040 This will trigger the deployment via GitHub Actions.
41+ REMINDER: If your `origin` is a fork, don't forget to push to e.g. `upstream` instead!
5142- [ ] Go to https://github.com/sharkdp/bat/releases/new to create the new
5243 release. Select the new tag and also use it as the release title. For the
5344 release notes, copy the corresponding section from `CHANGELOG.md` and
@@ -60,4 +51,23 @@ See this page for a good overview: https://deps.rs/repo/github/sharkdp/bat
6051
6152## Post-release
6253
63−- [ ] Prepare a new (empty) "unreleased" section at the top of `CHANGELOG.md`.
54+- [ ] Prepare a new "unreleased" section at the top of `CHANGELOG.md`.
55+ Put this at the top:
56+
57+```
58+# unreleased
59+
60+## Features
61+
62+## Bugfixes
63+
64+## Other
65+
66+## Syntaxes
67+
68+## Themes
69+
70+## `bat` as a library
71+
72+
73+```
doc/sponsors.mdnew file+14
@@ -0,0 +1,14 @@
1+## Sponsors
2+
3+`bat` development is sponsored by many individuals and companies. Thank you very much!
4+
5+Please note, that being sponsored does not affect the individuality of the `bat`
6+project or affect the maintainers' actions in any way.
7+We remain impartial and continue to assess pull requests solely on merit - the
8+features added, bugs solved, and effect on the overall complexity of the code.
9+No issue will have a different priority based on sponsorship status of the
10+reporter.
11+
12+Contributions from anybody are most welcomed, please see our [`CONTRIBUTING.md`](../CONTRIBUTING.md) guide.
13+
14+If you want to see our biggest sponsors, check the top of [`README.md`](../README.md#sponsors).
doc/sponsors/workos-logo-white-bg.svgnew file+11
@@ -0,0 +1,11 @@
1+<svg width="1354" height="420" viewBox="0 0 1354 420" fill="none" xmlns="http://www.w3.org/2000/svg">
2+<rect width="1354" height="420" rx="20" fill="white"/>
3+<path d="M434.751 133.122H466.637L489.595 227.729C493.852 245.585 494.697 256.219 494.697 256.219H495.128C495.128 256.219 496.61 245.808 500.867 227.729L522.757 133.122H558.9L582.066 227.729C586.53 246.223 587.598 256.219 587.598 256.219H588.236C588.236 256.219 588.666 246.223 592.907 227.729L615.02 133.122H646.907L606.523 288.313H571.017L546.576 194.344C541.474 173.936 541.044 164.801 541.044 164.801H540.614C540.614 164.801 540.183 173.936 535.512 194.344L512.553 288.313H475.996L434.751 133.122Z" fill="black"/>
4+<path d="M641.583 231.934C641.583 196.428 664.541 173.47 699.202 173.47C733.639 173.47 756.597 196.428 756.597 231.934C756.597 267.647 733.639 290.828 699.202 290.828C664.557 290.812 641.583 267.647 641.583 231.934ZM726.832 231.934C726.832 208.976 715.783 195.998 699.202 195.998C681.346 195.998 671.349 210.458 671.349 231.934C671.349 255.323 682.398 268.284 699.202 268.284C717.058 268.284 726.832 253.824 726.832 231.934Z" fill="black"/>
5+<path d="M770.836 175.21H799.103V196.048H799.741C804.635 185.207 816.322 174.365 836.299 174.365C839.695 174.365 841.831 174.796 843.314 175.21V203.478H842.469C842.469 203.478 839.918 202.633 832.903 202.633C811.013 202.633 799.103 215.594 799.103 239.828V288.295H770.836V175.21Z" fill="black"/>
6+<path d="M856.5 133.122H884.767V182.865C884.767 212.2 884.336 217.509 884.336 217.509H884.767L926.857 175.212H962.139L912.843 224.11L970.031 288.313H936.646L895.401 241.536L884.767 251.946V288.297H856.5V133.122Z" fill="black"/>
7+<path d="M970.444 211.285C970.444 163.455 1000.21 131.569 1044.85 131.569C1089.49 131.569 1119.26 163.455 1119.26 211.285C1119.26 259.114 1089.49 291.001 1044.85 291.001C1000.21 291.001 970.444 259.114 970.444 211.285ZM1088.42 211.285C1088.42 178.761 1071 156.855 1044.84 156.855C1018.67 156.855 1001.26 178.761 1001.26 211.285C1001.26 243.809 1018.69 265.715 1044.84 265.715C1070.98 265.715 1088.42 243.809 1088.42 211.285Z" fill="black"/>
8+<path d="M1130.08 236.656H1162.4C1162.4 254.943 1174.95 265.146 1194.08 265.146C1210.23 265.146 1221.29 257.063 1221.29 245.584C1221.29 232.622 1212.79 229.21 1185.79 223.901C1161.12 219.007 1134.98 210.716 1134.98 178.399C1134.98 151.408 1157.93 131 1193.01 131C1229.57 131 1252.11 150.132 1252.11 179.037H1219.79C1219.79 165.007 1208.95 156.286 1193.01 156.286C1176.86 156.286 1166.86 164.146 1166.86 175.625C1166.86 187.742 1173.88 192.413 1195.56 196.878C1227.65 203.685 1254.02 207.288 1254.02 243.001C1254.02 271.3 1229.36 290.432 1193.01 290.432C1156.02 290.432 1130.08 268.957 1130.08 236.656Z" fill="black"/>
9+<path d="M100 210C100 214.824 101.269 219.647 103.723 223.793L148.231 300.878C152.8 308.747 159.739 315.178 168.369 318.055C185.377 323.724 202.977 316.447 211.354 301.893L222.1 283.278L179.708 210L224.47 132.408L235.216 113.792C238.431 108.208 242.747 103.638 247.824 100H243.17H178.777C166.677 100 155.508 106.431 149.5 116.923L103.723 196.208C101.269 200.354 100 205.177 100 210Z" fill="#6363F1"/>
10+<path d="M353.847 210C353.847 205.177 352.578 200.353 350.124 196.207L305.024 118.107C296.647 103.638 279.047 96.3608 262.039 101.945C253.409 104.822 246.47 111.253 241.901 119.122L231.747 136.638L274.139 210L229.378 287.592L218.632 306.208C215.416 311.708 211.101 316.362 206.024 320H210.678H275.07C287.17 320 298.34 313.569 304.347 303.077L350.124 223.792C352.578 219.646 353.847 214.823 353.847 210Z" fill="#6363F1"/>
11+</svg>
rustfmt.tomlnew file+1
@@ -0,0 +1 @@
1+# Defaults are used
src/assets.rs+75−6
@@ -43,8 +43,9 @@ pub struct SyntaxReferenceInSet<'a> {
4343 pub syntax_set: &'a SyntaxSet,
4444}
4545
46−/// Compress for size of ~700 kB instead of ~4600 kB at the cost of ~30% longer deserialization time
47−pub(crate) const COMPRESS_SYNTAXES: bool = true;
46+/// Lazy-loaded syntaxes are already compressed, and we don't want to compress
47+/// already compressed data.
48+pub(crate) const COMPRESS_SYNTAXES: bool = false;
4849
4950/// We don't want to compress our [LazyThemeSet] since the lazy-loaded themes
5051/// within it are already compressed, and compressing another time just makes
@@ -68,10 +69,57 @@ impl HighlightingAssets {
6869 }
6970 }
7071
72+ /// The default theme.
73+ ///
74+ /// ### Windows and Linux
75+ ///
76+ /// Windows and most Linux distributions has a dark terminal theme by
77+ /// default. On these platforms, this function always returns a theme that
78+ /// looks good on a dark background.
79+ ///
80+ /// ### macOS
81+ ///
82+ /// On macOS the default terminal background is light, but it is common that
83+ /// Dark Mode is active, which makes the terminal background dark. On this
84+ /// platform, the default theme depends on
85+ /// ```bash
86+ /// defaults read -globalDomain AppleInterfaceStyle
87+ /// ````
88+ /// To avoid the overhead of the check on macOS, simply specify a theme
89+ /// explicitly via `--theme`, `BAT_THEME`, or `~/.config/bat`.
90+ ///
91+ /// See <https://github.com/sharkdp/bat/issues/1746> and
92+ /// <https://github.com/sharkdp/bat/issues/1928> for more context.
7193 pub fn default_theme() -> &'static str {
94+ #[cfg(not(target_os = "macos"))]
95+ {
96+ Self::default_dark_theme()
97+ }
98+ #[cfg(target_os = "macos")]
99+ {
100+ if macos_dark_mode_active() {
101+ Self::default_dark_theme()
102+ } else {
103+ Self::default_light_theme()
104+ }
105+ }
106+ }
107+
108+ /**
109+ * The default theme that looks good on a dark background.
110+ */
111+ fn default_dark_theme() -> &'static str {
72112 "Monokai Extended"
73113 }
74114
115+ /**
116+ * The default theme that looks good on a light background.
117+ */
118+ #[cfg(target_os = "macos")]
119+ fn default_light_theme() -> &'static str {
120+ "Monokai Extended Light"
121+ }
122+
75123 pub fn from_cache(cache_path: &Path) -> Result<Self> {
76124 Ok(HighlightingAssets::new(
77125 SerializedSyntaxSet::FromFile(cache_path.join("syntaxes.bin")),
@@ -90,7 +138,8 @@ impl HighlightingAssets {
90138 self.fallback_theme = Some(theme);
91139 }
92140
93− fn get_syntax_set(&self) -> Result<&SyntaxSet> {
141+ /// Return the collection of syntect syntax definitions.
142+ pub fn get_syntax_set(&self) -> Result<&SyntaxSet> {
94143 self.syntax_set_cell
95144 .get_or_try_init(|| self.serialized_syntax_set.deserialize())
96145 }
@@ -186,7 +235,8 @@ impl HighlightingAssets {
186235 }
187236 }
188237
189− pub(crate) fn get_theme(&self, theme: &str) -> &Theme {
238+ /// Look up a syntect theme by name.
239+ pub fn get_theme(&self, theme: &str) -> &Theme {
190240 match self.get_theme_set().get(theme) {
191241 Some(theme) => theme,
192242 None => {
@@ -349,6 +399,16 @@ fn asset_from_cache<T: serde::de::DeserializeOwned>(
349399 .map_err(|_| format!("Could not parse cached {}", description).into())
350400}
351401
402+#[cfg(target_os = "macos")]
403+fn macos_dark_mode_active() -> bool {
404+ let mut defaults_cmd = std::process::Command::new("defaults");
405+ defaults_cmd.args(&["read", "-globalDomain", "AppleInterfaceStyle"]);
406+ match defaults_cmd.output() {
407+ Ok(output) => output.stdout == b"Dark\n",
408+ Err(_) => true,
409+ }
410+}
411+
352412#[cfg(test)]
353413mod tests {
354414 use super::*;
@@ -579,13 +639,22 @@ mod tests {
579639 }
580640
581641 #[test]
582− fn syntax_detection_is_case_sensitive() {
642+ fn syntax_detection_is_case_insensitive() {
583643 let mut test = SyntaxDetectionTest::new();
584644
585− assert_ne!(test.syntax_for_file("README.MD"), "Markdown");
645+ assert_eq!(test.syntax_for_file("README.md"), "Markdown");
646+ assert_eq!(test.syntax_for_file("README.mD"), "Markdown");
647+ assert_eq!(test.syntax_for_file("README.Md"), "Markdown");
648+ assert_eq!(test.syntax_for_file("README.MD"), "Markdown");
649+
650+ // Adding a mapping for "MD" in addition to "md" should not break the mapping
586651 test.syntax_mapping
587652 .insert("*.MD", MappingTarget::MapTo("Markdown"))
588653 .ok();
654+
655+ assert_eq!(test.syntax_for_file("README.md"), "Markdown");
656+ assert_eq!(test.syntax_for_file("README.mD"), "Markdown");
657+ assert_eq!(test.syntax_for_file("README.Md"), "Markdown");
589658 assert_eq!(test.syntax_for_file("README.MD"), "Markdown");
590659 }
591660
src/assets/build_assets/acknowledgements.rs+3
@@ -104,6 +104,9 @@ fn license_not_needed_in_acknowledgements(license_text: &str) -> bool {
104104 // Public domain
105105 "This is free and unencumbered software released into the public domain.",
106106
107+ // Public domain with stronger wording than above
108+ "DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE",
109+
107110 // Special license of assets/syntaxes/01_Packages/LICENSE
108111 "Permission to copy, use, modify, sell and distribute this software is granted. This software is provided \"as is\" without express or implied warranty, and with no claim as to its suitability for any purpose."
109112 ];
src/bin/bat/app.rs+1−1
@@ -322,7 +322,7 @@ impl App {
322322 .collect::<Vec<_>>()
323323 })
324324 .or(env_style_components)
325− .unwrap_or_else(|| vec![StyleComponent::Full])
325+ .unwrap_or_else(|| vec![StyleComponent::Default])
326326 .into_iter()
327327 .map(|style| style.components(self.interactive_output))
328328 .fold(HashSet::new(), |mut acc, components| {
src/bin/bat/clap_app.rs+20−8
@@ -396,11 +396,20 @@ pub fn build_app(interactive_output: bool) -> ClapApp<'static, 'static> {
396396 .validator(|val| {
397397 let mut invalid_vals = val.split(',').filter(|style| {
398398 !&[
399− "auto", "full", "plain", "header", "grid", "rule", "numbers", "snip",
399+ "auto",
400+ "full",
401+ "default",
402+ "plain",
403+ "header",
404+ "header-filename",
405+ "header-filesize",
406+ "grid",
407+ "rule",
408+ "numbers",
409+ "snip",
400410 #[cfg(feature = "git")]
401− "changes",
402− ]
403− .contains(style)
411+ "changes",
412+ ].contains(style)
404413 });
405414
406415 if let Some(invalid) = invalid_vals.next() {
@@ -411,7 +420,7 @@ pub fn build_app(interactive_output: bool) -> ClapApp<'static, 'static> {
411420 })
412421 .help(
413422 "Comma-separated list of style elements to display \
414− (*auto*, full, plain, changes, header, grid, rule, numbers, snip).",
423+ (*default*, auto, full, plain, changes, header, header-filename, header-filesize, grid, rule, numbers, snip).",
415424 )
416425 .long_help(
417426 "Configure which elements (line numbers, file headers, grid \
@@ -422,11 +431,14 @@ pub fn build_app(interactive_output: bool) -> ClapApp<'static, 'static> {
422431 '--style=\"..\"' option to the configuration file or export the \
423432 BAT_STYLE environment variable (e.g.: export BAT_STYLE=\"..\").\n\n\
424433 Possible values:\n\n \
425− * full: enables all available components (default).\n \
426− * auto: same as 'full', unless the output is piped.\n \
434+ * default: enables recommended style components (default).\n \
435+ * full: enables all available components.\n \
436+ * auto: same as 'default', unless the output is piped.\n \
427437 * plain: disables all available components.\n \
428438 * changes: show Git modification markers.\n \
429− * header: show filenames before the content.\n \
439+ * header: alias for 'header-filename'.\n \
440+ * header-filename: show filenames before the content.\n \
441+ * header-filesize: show file sizes before the content.\n \
430442 * grid: vertical/horizontal lines to separate side bar\n \
431443 and the header from the content.\n \
432444 * rule: horizontal lines to delimit files.\n \
src/bin/bat/config.rs+1−1
@@ -91,7 +91,7 @@ pub fn get_args_from_config_file() -> Result<Vec<OsString>, shell_words::ParseEr
9191 .ok()
9292 .map(|content| get_args_from_str(&content))
9393 .transpose()?
94− .unwrap_or_else(Vec::new))
94+ .unwrap_or_default())
9595}
9696
9797pub fn get_args_from_env_var() -> Option<Result<Vec<OsString>, shell_words::ParseError>> {
src/bin/bat/main.rs+11
@@ -230,6 +230,9 @@ fn invoke_bugreport(app: &App) {
230230 let pager = bat::config::get_pager_executable(app.matches.value_of("pager"))
231231 .unwrap_or_else(|| "less".to_owned()); // FIXME: Avoid non-canonical path to "less".
232232
233+ let mut custom_assets_metadata = PROJECT_DIRS.cache_dir().to_path_buf();
234+ custom_assets_metadata.push("metadata.yaml");
235+
233236 let mut report = bugreport!()
234237 .info(SoftwareVersion::default())
235238 .info(OperatingSystem::default())
@@ -254,6 +257,14 @@ fn invoke_bugreport(app: &App) {
254257 "MANPAGER",
255258 ]))
256259 .info(FileContent::new("Config file", config_file()))
260+ .info(FileContent::new(
261+ "Custom assets metadata",
262+ custom_assets_metadata,
263+ ))
264+ .info(DirectoryEntries::new(
265+ "Custom assets",
266+ PROJECT_DIRS.cache_dir(),
267+ ))
257268 .info(CompileTimeInformation::default());
258269
259270 #[cfg(feature = "paging")]
src/error.rs+4−1
@@ -2,11 +2,14 @@ use std::io::Write;
22use thiserror::Error;
33
44#[derive(Error, Debug)]
5+#[non_exhaustive]
56pub enum Error {
67 #[error(transparent)]
78 Io(#[from] ::std::io::Error),
89 #[error(transparent)]
9− SyntectError(#[from] ::syntect::LoadingError),
10+ SyntectError(#[from] ::syntect::Error),
11+ #[error(transparent)]
12+ SyntectLoadingError(#[from] ::syntect::LoadingError),
1013 #[error(transparent)]
1114 ParseIntError(#[from] ::std::num::ParseIntError),
1215 #[error(transparent)]
src/input.rs+9−2
@@ -1,4 +1,5 @@
11use std::convert::TryFrom;
2+use std::fs;
23use std::fs::File;
34use std::io::{self, BufRead, BufReader, Read};
45use std::path::{Path, PathBuf};
@@ -87,6 +88,7 @@ impl<'a> InputKind<'a> {
8788#[derive(Clone, Default)]
8889pub(crate) struct InputMetadata {
8990 pub(crate) user_provided_name: Option<PathBuf>,
91+ pub(crate) size: Option<u64>,
9092}
9193
9294pub struct Input<'a> {
@@ -116,7 +118,7 @@ impl OpenedInput<'_> {
116118 self.metadata
117119 .user_provided_name
118120 .as_ref()
119− .or_else(|| match self.kind {
121+ .or(match self.kind {
120122 OpenedInputKind::OrdinaryFile(ref path) => Some(path),
121123 _ => None,
122124 })
@@ -130,9 +132,14 @@ impl<'a> Input<'a> {
130132
131133 fn _ordinary_file(path: &Path) -> Self {
132134 let kind = InputKind::OrdinaryFile(path.to_path_buf());
135+ let metadata = InputMetadata {
136+ size: fs::metadata(path).map(|m| m.len()).ok(),
137+ ..InputMetadata::default()
138+ };
139+
133140 Input {
134141 description: kind.description(),
135− metadata: InputMetadata::default(),
142+ metadata,
136143 kind,
137144 }
138145 }
src/less.rs+59−8
@@ -3,21 +3,38 @@
33use std::ffi::OsStr;
44use std::process::Command;
55
6−pub fn retrieve_less_version(less_path: &dyn AsRef<OsStr>) -> Option<usize> {
6+#[derive(Debug, PartialEq)]
7+pub enum LessVersion {
8+ Less(usize),
9+ BusyBox,
10+}
11+
12+pub fn retrieve_less_version(less_path: &dyn AsRef<OsStr>) -> Option<LessVersion> {
713 let resolved_path = grep_cli::resolve_binary(less_path.as_ref()).ok()?;
814
915 let cmd = Command::new(resolved_path).arg("--version").output().ok()?;
10− parse_less_version(&cmd.stdout)
16+ if cmd.status.success() {
17+ parse_less_version(&cmd.stdout)
18+ } else {
19+ parse_less_version_busybox(&cmd.stderr)
20+ }
1121}
1222
13−fn parse_less_version(output: &[u8]) -> Option<usize> {
23+fn parse_less_version(output: &[u8]) -> Option<LessVersion> {
1424 if !output.starts_with(b"less ") {
1525 return None;
1626 }
1727
1828 let version = std::str::from_utf8(&output[5..]).ok()?;
1929 let end = version.find(|c: char| !c.is_ascii_digit())?;
20− version[..end].parse::<usize>().ok()
30+ Some(LessVersion::Less(version[..end].parse::<usize>().ok()?))
31+}
32+
33+fn parse_less_version_busybox(output: &[u8]) -> Option<LessVersion> {
34+ match std::str::from_utf8(output) {
35+ Ok(version) if version.contains("BusyBox ") => Some(LessVersion::BusyBox),
36+ _ => None,
37+ }
2138}
2239
2340#[test]
@@ -30,7 +47,7 @@ For information about the terms of redistribution,
3047see the file named README in the less distribution.
3148Homepage: http://www.greenwoodsoftware.com/less";
3249
33− assert_eq!(Some(487), parse_less_version(output));
50+ assert_eq!(Some(LessVersion::Less(487)), parse_less_version(output));
3451}
3552
3653#[test]
@@ -43,7 +60,7 @@ For information about the terms of redistribution,
4360see the file named README in the less distribution.
4461Homepage: http://www.greenwoodsoftware.com/less";
4562
46− assert_eq!(Some(529), parse_less_version(output));
63+ assert_eq!(Some(LessVersion::Less(529)), parse_less_version(output));
4764}
4865
4966#[test]
@@ -56,7 +73,7 @@ For information about the terms of redistribution,
5673see the file named README in the less distribution.
5774Home page: http://www.greenwoodsoftware.com/less";
5875
59− assert_eq!(Some(551), parse_less_version(output));
76+ assert_eq!(Some(LessVersion::Less(551)), parse_less_version(output));
6077}
6178
6279#[test]
@@ -69,7 +86,7 @@ For information about the terms of redistribution,
6986see the file named README in the less distribution.
7087Home page: https://greenwoodsoftware.com/less";
7188
72− assert_eq!(Some(581), parse_less_version(output));
89+ assert_eq!(Some(LessVersion::Less(581)), parse_less_version(output));
7390}
7491
7592#[test]
@@ -77,4 +94,38 @@ fn test_parse_less_version_wrong_program() {
7794 let output = b"more from util-linux 2.34";
7895
7996 assert_eq!(None, parse_less_version(output));
97+ assert_eq!(None, parse_less_version_busybox(output));
98+}
99+
100+#[test]
101+fn test_parse_less_version_busybox() {
102+ let output = b"pkg/less: unrecognized option '--version'
103+BusyBox v1.35.0 (2022-04-21 10:38:11 EDT) multi-call binary.
104+
105+Usage: less [-EFIMmNSRh~] [FILE]...
106+
107+View FILE (or stdin) one screenful at a time
108+
109+ -E Quit once the end of a file is reached
110+ -F Quit if entire file fits on first screen
111+ -I Ignore case in all searches
112+ -M,-m Display status line with line numbers
113+ and percentage through the file
114+ -N Prefix line number to each line
115+ -S Truncate long lines
116+ -R Remove color escape codes in input
117+ -~ Suppress ~s displayed past EOF";
118+
119+ assert_eq!(
120+ Some(LessVersion::BusyBox),
121+ parse_less_version_busybox(output)
122+ );
123+}
124+
125+#[test]
126+fn test_parse_less_version_invalid_utf_8() {
127+ let output = b"\xff";
128+
129+ assert_eq!(None, parse_less_version(output));
130+ assert_eq!(None, parse_less_version_busybox(output));
80131}
src/output.rs+7−5
@@ -4,7 +4,7 @@ use std::process::Child;
44
55use crate::error::*;
66#[cfg(feature = "paging")]
7−use crate::less::retrieve_less_version;
7+use crate::less::{retrieve_less_version, LessVersion};
88#[cfg(feature = "paging")]
99use crate::paging::PagingMode;
1010#[cfg(feature = "paging")]
@@ -83,13 +83,13 @@ impl OutputType {
8383 let replace_arguments_to_less = pager.source == PagerSource::EnvVarPager;
8484
8585 if args.is_empty() || replace_arguments_to_less {
86− p.arg("--RAW-CONTROL-CHARS");
86+ p.arg("-R"); // Short version of --RAW-CONTROL-CHARS for maximum compatibility
8787 if single_screen_action == SingleScreenAction::Quit {
88− p.arg("--quit-if-one-screen");
88+ p.arg("-F"); // Short version of --quit-if-one-screen for compatibility
8989 }
9090
9191 if wrapping_mode == WrappingMode::NoWrapping(true) {
92− p.arg("--chop-long-lines");
92+ p.arg("-S"); // Short version of --chop-long-lines for compatibility
9393 }
9494
9595 // Passing '--no-init' fixes a bug with '--quit-if-one-screen' in older
@@ -103,7 +103,9 @@ impl OutputType {
103103 None => {
104104 p.arg("--no-init");
105105 }
106− Some(version) if (version < 530 || (cfg!(windows) && version < 558)) => {
106+ Some(LessVersion::Less(version))
107+ if (version < 530 || (cfg!(windows) && version < 558)) =>
108+ {
107109 p.arg("--no-init");
108110 }
109111 _ => {}
src/preprocessor.rs+10−3
@@ -53,26 +53,33 @@ pub fn replace_nonprintable(input: &[u8], tab_width: usize) -> String {
5353 let tab_width = if tab_width == 0 { 4 } else { tab_width };
5454
5555 let mut idx = 0;
56+ let mut line_idx = 0;
5657 let len = input.len();
5758 while idx < len {
5859 if let Some((chr, skip_ahead)) = try_parse_utf8_char(&input[idx..]) {
5960 idx += skip_ahead;
61+ line_idx += 1;
6062
6163 match chr {
6264 // space
6365 ' ' => output.push('·'),
6466 // tab
6567 '\t' => {
66− if tab_width == 1 {
68+ let tab_stop = tab_width - ((line_idx - 1) % tab_width);
69+ line_idx = 0;
70+ if tab_stop == 1 {
6771 output.push('↹');
6872 } else {
6973 output.push('├');
70− output.push_str(&"─".repeat(tab_width - 2));
74+ output.push_str(&"─".repeat(tab_stop - 2));
7175 output.push('┤');
7276 }
7377 }
7478 // line feed
75− '\x0A' => output.push_str("␊\x0A"),
79+ '\x0A' => {
80+ output.push_str("␊\x0A");
81+ line_idx = 0;
82+ }
7683 // carriage return
7784 '\x0D' => output.push('␍'),
7885 // null
src/pretty_printer.rs+6
@@ -164,6 +164,12 @@ impl<'a> PrettyPrinter<'a> {
164164 self
165165 }
166166
167+ /// Whether to print binary content or nonprintable characters (default: no)
168+ pub fn show_nonprintable(&mut self, yes: bool) -> &mut Self {
169+ self.config.show_nonprintable = yes;
170+ self
171+ }
172+
167173 /// Whether to show "snip" markers between visible line ranges (default: no)
168174 pub fn snip(&mut self, yes: bool) -> &mut Self {
169175 self.active_style_components.snip = yes;
src/printer.rs+96−33
@@ -4,6 +4,8 @@ use std::vec::Vec;
44use ansi_term::Colour::{Fixed, Green, Red, Yellow};
55use ansi_term::Style;
66
7+use bytesize::ByteSize;
8+
79use console::AnsiCodeIterator;
810
911use syntect::easy::HighlightLines;
@@ -29,6 +31,7 @@ use crate::error::*;
2931use crate::input::OpenedInput;
3032use crate::line_range::RangeCheckResult;
3133use crate::preprocessor::{expand_tabs, replace_nonprintable};
34+use crate::style::StyleComponent;
3235use crate::terminal::{as_terminal_escaped, to_ansi_color};
3336use crate::vscreen::AnsiStyle;
3437use crate::wrapping::WrappingMode;
@@ -250,6 +253,21 @@ impl<'a> InteractivePrinter<'a> {
250253 }
251254 }
252255
256+ fn print_header_component_indent(&mut self, handle: &mut dyn Write) -> std::io::Result<()> {
257+ if self.config.style_components.grid() {
258+ write!(
259+ handle,
260+ "{}{}",
261+ " ".repeat(self.panel_width),
262+ self.colors
263+ .grid
264+ .paint(if self.panel_width > 0 { "│ " } else { "" }),
265+ )
266+ } else {
267+ write!(handle, "{}", " ".repeat(self.panel_width))
268+ }
269+ }
270+
253271 fn preprocess(&self, text: &str, cursor: &mut usize) -> String {
254272 if self.config.tab_width > 0 {
255273 return expand_tabs(text, self.config.tab_width, cursor);
@@ -287,25 +305,6 @@ impl<'a> Printer for InteractivePrinter<'a> {
287305 return Ok(());
288306 }
289307
290− if self.config.style_components.grid() {
291− self.print_horizontal_line(handle, '┬')?;
292−
293− write!(
294− handle,
295− "{}{}",
296− " ".repeat(self.panel_width),
297− self.colors
298− .grid
299− .paint(if self.panel_width > 0 { "│ " } else { "" }),
300− )?;
301− } else {
302− // Only pad space between files, if we haven't already drawn a horizontal rule
303− if add_header_padding && !self.config.style_components.rule() {
304− writeln!(handle)?;
305− }
306− write!(handle, "{}", " ".repeat(self.panel_width))?;
307− }
308−
309308 let mode = match self.content_type {
310309 Some(ContentType::BINARY) => " <BINARY>",
311310 Some(ContentType::UTF_16LE) => " <UTF-16LE>",
@@ -315,17 +314,60 @@ impl<'a> Printer for InteractivePrinter<'a> {
315314 };
316315
317316 let description = &input.description;
317+ let metadata = &input.metadata;
318+
319+ // We use this iterator to have a deterministic order for
320+ // header components. HashSet has arbitrary order, but Vec is ordered.
321+ let header_components: Vec<StyleComponent> = [
322+ (
323+ StyleComponent::HeaderFilename,
324+ self.config.style_components.header_filename(),
325+ ),
326+ (
327+ StyleComponent::HeaderFilesize,
328+ self.config.style_components.header_filesize(),
329+ ),
330+ ]
331+ .iter()
332+ .filter(|(_, is_enabled)| *is_enabled)
333+ .map(|(component, _)| *component)
334+ .collect();
335+
336+ // Print the cornering grid before the first header component
337+ if self.config.style_components.grid() {
338+ self.print_horizontal_line(handle, '┬')?;
339+ } else {
340+ // Only pad space between files, if we haven't already drawn a horizontal rule
341+ if add_header_padding && !self.config.style_components.rule() {
342+ writeln!(handle)?;
343+ }
344+ }
318345
319− writeln!(
320− handle,
321− "{}{}{}",
322− description
323− .kind()
324− .map(|kind| format!("{}: ", kind))
325− .unwrap_or_else(|| "".into()),
326− self.colors.filename.paint(description.title()),
327− mode
328− )?;
346+ header_components.iter().try_for_each(|component| {
347+ self.print_header_component_indent(handle)?;
348+
349+ match component {
350+ StyleComponent::HeaderFilename => writeln!(
351+ handle,
352+ "{}{}{}",
353+ description
354+ .kind()
355+ .map(|kind| format!("{}: ", kind))
356+ .unwrap_or_else(|| "".into()),
357+ self.colors.header_value.paint(description.title()),
358+ mode
359+ ),
360+
361+ StyleComponent::HeaderFilesize => {
362+ let bsize = metadata
363+ .size
364+ .map(|s| format!("{}", ByteSize(s)))
365+ .unwrap_or_else(|| "-".into());
366+ writeln!(handle, "Size: {}", self.colors.header_value.paint(bsize))
367+ }
368+ _ => Ok(()),
369+ }
370+ })?;
329371
330372 if self.config.style_components.grid() {
331373 if self.content_type.map_or(false, |c| c.is_text()) || self.config.show_nonprintable {
@@ -403,9 +445,21 @@ impl<'a> Printer for InteractivePrinter<'a> {
403445 return Ok(());
404446 }
405447 };
406− highlighter_from_set
448+
449+ // skip syntax highlighting on long lines
450+ let too_long = line.len() > 1024 * 16;
451+
452+ let for_highlighting: &str = if too_long { "\n" } else { &line };
453+
454+ let mut highlighted_line = highlighter_from_set
407455 .highlighter
408− .highlight(&line, highlighter_from_set.syntax_set)
456+ .highlight_line(for_highlighting, highlighter_from_set.syntax_set)?;
457+
458+ if too_long {
459+ highlighted_line[0].1 = &line;
460+ }
461+
462+ highlighted_line
409463 };
410464
411465 if out_of_range {
@@ -421,6 +475,10 @@ impl<'a> Printer for InteractivePrinter<'a> {
421475 let highlight_this_line =
422476 self.config.highlighted_lines.0.check(line_number) == RangeCheckResult::InRange;
423477
478+ if highlight_this_line && self.config.theme == "ansi" {
479+ self.ansi_style.update("^[4m");
480+ }
481+
424482 let background_color = self
425483 .background_color_highlight
426484 .filter(|_| highlight_this_line);
@@ -607,6 +665,11 @@ impl<'a> Printer for InteractivePrinter<'a> {
607665 writeln!(handle)?;
608666 }
609667
668+ if highlight_this_line && self.config.theme == "ansi" {
669+ self.ansi_style.update("^[24m");
670+ write!(handle, "\x1B[24m")?;
671+ }
672+
610673 Ok(())
611674 }
612675}
@@ -617,7 +680,7 @@ const DEFAULT_GUTTER_COLOR: u8 = 238;
617680pub struct Colors {
618681 pub grid: Style,
619682 pub rule: Style,
620− pub filename: Style,
683+ pub header_value: Style,
621684 pub git_added: Style,
622685 pub git_removed: Style,
623686 pub git_modified: Style,
@@ -646,7 +709,7 @@ impl Colors {
646709 Colors {
647710 grid: gutter_style,
648711 rule: gutter_style,
649− filename: Style::new().bold(),
712+ header_value: Style::new().bold(),
650713 git_added: Green.normal(),
651714 git_removed: Red.normal(),
652715 git_modified: Yellow.normal(),
src/style.rs+30−4
@@ -3,6 +3,7 @@ use std::str::FromStr;
33
44use crate::error::*;
55
6+#[non_exhaustive]
67#[derive(Debug, Eq, PartialEq, Copy, Clone, Hash)]
78pub enum StyleComponent {
89 Auto,
@@ -11,9 +12,12 @@ pub enum StyleComponent {
1112 Grid,
1213 Rule,
1314 Header,
15+ HeaderFilename,
16+ HeaderFilesize,
1417 LineNumbers,
1518 Snip,
1619 Full,
20+ Default,
1721 Plain,
1822}
1923
@@ -22,7 +26,7 @@ impl StyleComponent {
2226 match self {
2327 StyleComponent::Auto => {
2428 if interactive_terminal {
25− StyleComponent::Full.components(interactive_terminal)
29+ StyleComponent::Default.components(interactive_terminal)
2630 } else {
2731 StyleComponent::Plain.components(interactive_terminal)
2832 }
@@ -31,14 +35,25 @@ impl StyleComponent {
3135 StyleComponent::Changes => &[StyleComponent::Changes],
3236 StyleComponent::Grid => &[StyleComponent::Grid],
3337 StyleComponent::Rule => &[StyleComponent::Rule],
34− StyleComponent::Header => &[StyleComponent::Header],
38+ StyleComponent::Header => &[StyleComponent::HeaderFilename],
39+ StyleComponent::HeaderFilename => &[StyleComponent::HeaderFilename],
40+ StyleComponent::HeaderFilesize => &[StyleComponent::HeaderFilesize],
3541 StyleComponent::LineNumbers => &[StyleComponent::LineNumbers],
3642 StyleComponent::Snip => &[StyleComponent::Snip],
3743 StyleComponent::Full => &[
3844 #[cfg(feature = "git")]
3945 StyleComponent::Changes,
4046 StyleComponent::Grid,
41− StyleComponent::Header,
47+ StyleComponent::HeaderFilename,
48+ StyleComponent::HeaderFilesize,
49+ StyleComponent::LineNumbers,
50+ StyleComponent::Snip,
51+ ],
52+ StyleComponent::Default => &[
53+ #[cfg(feature = "git")]
54+ StyleComponent::Changes,
55+ StyleComponent::Grid,
56+ StyleComponent::HeaderFilename,
4257 StyleComponent::LineNumbers,
4358 StyleComponent::Snip,
4459 ],
@@ -58,9 +73,12 @@ impl FromStr for StyleComponent {
5873 "grid" => Ok(StyleComponent::Grid),
5974 "rule" => Ok(StyleComponent::Rule),
6075 "header" => Ok(StyleComponent::Header),
76+ "header-filename" => Ok(StyleComponent::HeaderFilename),
77+ "header-filesize" => Ok(StyleComponent::HeaderFilesize),
6178 "numbers" => Ok(StyleComponent::LineNumbers),
6279 "snip" => Ok(StyleComponent::Snip),
6380 "full" => Ok(StyleComponent::Full),
81+ "default" => Ok(StyleComponent::Default),
6482 "plain" => Ok(StyleComponent::Plain),
6583 _ => Err(format!("Unknown style '{}'", s).into()),
6684 }
@@ -89,7 +107,15 @@ impl StyleComponents {
89107 }
90108
91109 pub fn header(&self) -> bool {
92− self.0.contains(&StyleComponent::Header)
110+ self.header_filename() || self.header_filesize()
111+ }
112+
113+ pub fn header_filename(&self) -> bool {
114+ self.0.contains(&StyleComponent::HeaderFilename)
115+ }
116+
117+ pub fn header_filesize(&self) -> bool {
118+ self.0.contains(&StyleComponent::HeaderFilesize)
93119 }
94120
95121 pub fn numbers(&self) -> bool {
src/syntax_mapping.rs+24−2
@@ -41,6 +41,9 @@ impl<'a> SyntaxMapping<'a> {
4141 pub fn builtin() -> SyntaxMapping<'a> {
4242 let mut mapping = Self::empty();
4343 mapping.insert("*.h", MappingTarget::MapTo("C++")).unwrap();
44+ mapping
45+ .insert(".clang-format", MappingTarget::MapTo("YAML"))
46+ .unwrap();
4447 mapping.insert("*.fs", MappingTarget::MapTo("F#")).unwrap();
4548 mapping
4649 .insert("build", MappingTarget::MapToUnknown)
@@ -117,13 +120,32 @@ impl<'a> SyntaxMapping<'a> {
117120 mapping.insert(glob, MappingTarget::MapTo("INI")).unwrap();
118121 }
119122
123+ // unix mail spool
124+ for glob in &["/var/spool/mail/*", "/var/mail/*"] {
125+ mapping.insert(glob, MappingTarget::MapTo("Email")).unwrap()
126+ }
127+
120128 // pacman hooks
121129 mapping
122130 .insert("*.hook", MappingTarget::MapTo("INI"))
123131 .unwrap();
124132
125− if let Some(xdg_config_home) = std::env::var_os("XDG_CONFIG_HOME") {
126− let git_config_path = Path::new(&xdg_config_home).join("git");
133+ // Global git config files rooted in `$XDG_CONFIG_HOME/git/` or `$HOME/.config/git/`
134+ // See e.g. https://git-scm.com/docs/git-config#FILES
135+ if let Some(xdg_config_home) =
136+ std::env::var_os("XDG_CONFIG_HOME").filter(|val| !val.is_empty())
137+ {
138+ insert_git_config_global(&mut mapping, &xdg_config_home);
139+ }
140+ if let Some(default_config_home) = std::env::var_os("HOME")
141+ .filter(|val| !val.is_empty())
142+ .map(|home| Path::new(&home).join(".config"))
143+ {
144+ insert_git_config_global(&mut mapping, &default_config_home);
145+ }
146+
147+ fn insert_git_config_global(mapping: &mut SyntaxMapping, config_home: impl AsRef<Path>) {
148+ let git_config_path = config_home.as_ref().join("git");
127149
128150 mapping
129151 .insert(
tests/benchmarks/many-small-files/small-file-0.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 0
tests/benchmarks/many-small-files/small-file-1.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 1
tests/benchmarks/many-small-files/small-file-10.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 10
tests/benchmarks/many-small-files/small-file-100.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 100
tests/benchmarks/many-small-files/small-file-11.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 11
tests/benchmarks/many-small-files/small-file-12.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 12
tests/benchmarks/many-small-files/small-file-13.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 13
tests/benchmarks/many-small-files/small-file-14.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 14
tests/benchmarks/many-small-files/small-file-15.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 15
tests/benchmarks/many-small-files/small-file-16.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 16
tests/benchmarks/many-small-files/small-file-17.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 17
tests/benchmarks/many-small-files/small-file-18.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 18
tests/benchmarks/many-small-files/small-file-19.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 19
tests/benchmarks/many-small-files/small-file-2.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 2
tests/benchmarks/many-small-files/small-file-20.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 20
tests/benchmarks/many-small-files/small-file-21.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 21
tests/benchmarks/many-small-files/small-file-22.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 22
tests/benchmarks/many-small-files/small-file-23.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 23
tests/benchmarks/many-small-files/small-file-24.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 24
tests/benchmarks/many-small-files/small-file-25.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 25
tests/benchmarks/many-small-files/small-file-26.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 26
tests/benchmarks/many-small-files/small-file-27.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 27
tests/benchmarks/many-small-files/small-file-28.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 28
tests/benchmarks/many-small-files/small-file-29.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 29
tests/benchmarks/many-small-files/small-file-3.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 3
tests/benchmarks/many-small-files/small-file-30.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 30
tests/benchmarks/many-small-files/small-file-31.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 31
tests/benchmarks/many-small-files/small-file-32.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 32
tests/benchmarks/many-small-files/small-file-33.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 33
tests/benchmarks/many-small-files/small-file-34.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 34
tests/benchmarks/many-small-files/small-file-35.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 35
tests/benchmarks/many-small-files/small-file-36.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 36
tests/benchmarks/many-small-files/small-file-37.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 37
tests/benchmarks/many-small-files/small-file-38.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 38
tests/benchmarks/many-small-files/small-file-39.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 39
tests/benchmarks/many-small-files/small-file-4.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 4
tests/benchmarks/many-small-files/small-file-40.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 40
tests/benchmarks/many-small-files/small-file-41.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 41
tests/benchmarks/many-small-files/small-file-42.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 42
tests/benchmarks/many-small-files/small-file-43.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 43
tests/benchmarks/many-small-files/small-file-44.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 44
tests/benchmarks/many-small-files/small-file-45.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 45
tests/benchmarks/many-small-files/small-file-46.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 46
tests/benchmarks/many-small-files/small-file-47.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 47
tests/benchmarks/many-small-files/small-file-48.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 48
tests/benchmarks/many-small-files/small-file-49.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 49
tests/benchmarks/many-small-files/small-file-5.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 5
tests/benchmarks/many-small-files/small-file-50.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 50
tests/benchmarks/many-small-files/small-file-51.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 51
tests/benchmarks/many-small-files/small-file-52.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 52
tests/benchmarks/many-small-files/small-file-53.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 53
tests/benchmarks/many-small-files/small-file-54.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 54
tests/benchmarks/many-small-files/small-file-55.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 55
tests/benchmarks/many-small-files/small-file-56.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 56
tests/benchmarks/many-small-files/small-file-57.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 57
tests/benchmarks/many-small-files/small-file-58.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 58
tests/benchmarks/many-small-files/small-file-59.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 59
tests/benchmarks/many-small-files/small-file-6.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 6
tests/benchmarks/many-small-files/small-file-60.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 60
tests/benchmarks/many-small-files/small-file-61.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 61
tests/benchmarks/many-small-files/small-file-62.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 62
tests/benchmarks/many-small-files/small-file-63.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 63
tests/benchmarks/many-small-files/small-file-64.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 64
tests/benchmarks/many-small-files/small-file-65.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 65
tests/benchmarks/many-small-files/small-file-66.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 66
tests/benchmarks/many-small-files/small-file-67.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 67
tests/benchmarks/many-small-files/small-file-68.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 68
tests/benchmarks/many-small-files/small-file-69.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 69
tests/benchmarks/many-small-files/small-file-7.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 7
tests/benchmarks/many-small-files/small-file-70.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 70
tests/benchmarks/many-small-files/small-file-71.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 71
tests/benchmarks/many-small-files/small-file-72.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 72
tests/benchmarks/many-small-files/small-file-73.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 73
tests/benchmarks/many-small-files/small-file-74.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 74
tests/benchmarks/many-small-files/small-file-75.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 75
tests/benchmarks/many-small-files/small-file-76.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 76
tests/benchmarks/many-small-files/small-file-77.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 77
tests/benchmarks/many-small-files/small-file-78.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 78
tests/benchmarks/many-small-files/small-file-79.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 79
tests/benchmarks/many-small-files/small-file-8.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 8
tests/benchmarks/many-small-files/small-file-80.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 80
tests/benchmarks/many-small-files/small-file-81.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 81
tests/benchmarks/many-small-files/small-file-82.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 82
tests/benchmarks/many-small-files/small-file-83.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 83
tests/benchmarks/many-small-files/small-file-84.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 84
tests/benchmarks/many-small-files/small-file-85.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 85
tests/benchmarks/many-small-files/small-file-86.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 86
tests/benchmarks/many-small-files/small-file-87.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 87
tests/benchmarks/many-small-files/small-file-88.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 88
tests/benchmarks/many-small-files/small-file-89.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 89
tests/benchmarks/many-small-files/small-file-9.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 9
tests/benchmarks/many-small-files/small-file-90.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 90
tests/benchmarks/many-small-files/small-file-91.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 91
tests/benchmarks/many-small-files/small-file-92.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 92
tests/benchmarks/many-small-files/small-file-93.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 93
tests/benchmarks/many-small-files/small-file-94.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 94
tests/benchmarks/many-small-files/small-file-95.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 95
tests/benchmarks/many-small-files/small-file-96.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 96
tests/benchmarks/many-small-files/small-file-97.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 97
tests/benchmarks/many-small-files/small-file-98.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 98
tests/benchmarks/many-small-files/small-file-99.txtnew file+1
@@ -0,0 +1 @@
1+I am small file 99
tests/benchmarks/run-benchmarks.sh+15−5
@@ -9,15 +9,15 @@ if ! command -v hyperfine > /dev/null 2>&1; then
99 exit 1
1010fi
1111
12−# Check that jq is installed.
13−if ! command -v jq > /dev/null 2>&1; then
14− echo "'jq' does not seem to be installed."
15− echo "You can get it here: https://stedolan.github.io/jq"
12+# Check that python3 is installed.
13+if ! command -v python3 > /dev/null 2>&1; then
14+ echo "'python3' does not seem to be installed."
15+ echo "You can get it here: https://www.python.org/downloads/"
1616 exit 1
1717fi
1818
1919get_cargo_target_dir() {
20− cargo metadata --no-deps --format-version 1 | jq -r .target_directory
20+ cargo metadata --no-deps --format-version 1 | python3 -c 'import sys, json; print(json.load(sys.stdin)["target_directory"])'
2121}
2222
2323heading() {
@@ -136,3 +136,13 @@ for wrap in character never; do
136136 cat "$RESULT_DIR/syntax-highlighting-speed-${filename}.md" >> "$REPORT"
137137 done
138138done
139+
140+
141+heading "Many small files speed (overhead of metadata)"
142+hyperfine \
143+ "$(printf "%q" "$BAT") --no-config --language=txt --style=plain many-small-files/*.txt" \
144+ --command-name 'bat … --language=txt *.txt' \
145+ --warmup "$WARMUP_COUNT" \
146+ --export-markdown "$RESULT_DIR/many-small-files-speed.md" \
147+ --export-json "$RESULT_DIR/many-small-files-speed.json"
148+cat "$RESULT_DIR/many-small-files-speed.md" >> "$REPORT"
tests/examples/git/.config/git/confignew file+3
@@ -0,0 +1,3 @@
1+[user]
2+ email = foo@bar.net
3+ name = foobar
tests/examples/git/.gitconfignew file+3
@@ -0,0 +1,3 @@
1+[user]
2+ email = foo@bar.net
3+ name = foobar
tests/examples/longline.jsonnew file+3
@@ -0,0 +1,3 @@
1+{"api":
2+ {"ANGLE_instanced_arrays":{"__compat":{"mdn_url":"https://developer.mozilla.org/docs/Web/API/ANGLE_instanced_arrays","spec_url":"https://www.khronos.org/registry/webgl/extensions/ANGLE_instanced_arrays/","support":{"chrome":{"version_added":"32"},"chrome_android":{"version_added":"32"},"edge":{"version_added":"12"},"firefox":{"version_added":"47"},"firefox_android":{"version_added":true},"ie":{"version_added":"11"},"opera":{"version_added":"19"},"opera_android":{"version_added":"19"},"safari":{"version_added":"8"},"safari_ios":{"version_added":"8"},"samsunginternet_android":{"version_added":"2.0"},"webview_android":{"version_added":"4.4"}},"status":{"experimental":false,"standard_track":true,"deprecated":false}},"drawArraysInstancedANGLE":{"__compat":{"mdn_url":"https://developer.mozilla.org/docs/Web/API/ANGLE_instanced_arrays/drawArraysInstancedANGLE","spec_url":"https://www.khronos.org/registry/webgl/extensions/ANGLE_instanced_arrays/","support":{"chrome":{"version_added":"32"},"chrome_android":{"version_added":"32"},"edge":{"version_added":"12"},"firefox":{"version_added":"47"},"firefox_android":{"version_added":true},"ie":{"version_added":"11"},"opera":{"version_added":"19"},"opera_android":{"version_added":"19"},"safari":{"version_added":"8"},"safari_ios":{"version_added":"8"},"samsunginternet_android":{"version_added":"2.0"},"webview_android":{"version_added":"4.4"}},"status":{"experimental":false,"standard_track":true,"deprecated":false}}},"drawElementsInstancedANGLE":{"__compat":{"mdn_url":"https://developer.mozilla.org/docs/Web/API/ANGLE_instanced_arrays/drawElementsInstancedANGLE","spec_url":"https://www.khronos.org/registry/webgl/extensions/ANGLE_instanced_arrays/","support":{"chrome":{"version_added":"32"},"chrome_android":{"version_added":"32"},"edge":{"version_added":"12"},"firefox":{"version_added":"47"},"firefox_android":{"version_added":true},"ie":{"version_added":"11"},"opera":{"version_added":"19"},"opera_android":{"version_added":"19"},"safari":{"version_added":"8"},"safari_ios":{"version_added":"8"},"samsunginternet_android":{"version_added":"2.0"},"webview_android":{"version_added":"4.4"}},"status":{"experimental":false,"standard_track":true,"deprecated":false}}},"vertexAttribDivisorANGLE":{"__compat":{"mdn_url":"https://developer.mozilla.org/docs/Web/API/ANGLE_instanced_arrays/vertexAttribDivisorANGLE","spec_url":"https://www.khronos.org/registry/webgl/extensions/ANGLE_instanced_arrays/","support":{"chrome":{"version_added":"32"},"chrome_android":{"version_added":"32"},"edge":{"version_added":"12"},"firefox":{"version_added":"47"},"firefox_android":{"version_added":true},"ie":{"version_added":"11"},"opera":{"version_added":"19"},"opera_android":{"version_added":"19"},"safari":{"version_added":"8"},"safari_ios":{"version_added":"8"},"samsunginternet_android":{"version_added":"2.0"},"webview_android":{"version_added":"4.4"}},"status":{"experimental":false,"standard_track":true,"deprecated":false}}}},"AbortController":{"__compat":{"mdn_url":"https://developer.mozilla.org/docs/Web/API/AbortController","spec_url":"https://dom.spec.whatwg.org/#interface-abortcontroller","support":{"chrome":{"version_added":"66"},"chrome_android":{"version_added":"66"},"edge":{"version_added":"16"},"firefox":{"version_added":"57"},"firefox_android":{"version_added":"57"},"ie":{"version_added":false},"nodejs":{"version_added":"15.0.0"},"opera":{"version_added":"53"},"opera_android":{"version_added":"47"},"safari":[{"version_added":"12.1"},{"version_added":"11.1","partial_implementation":true,"notes":"Even though <code>window.AbortController</code> is defined, it doesn't really abort <code>fetch</code> requests. See <a href='https://webkit.org/b/174980'>bug 174980</a>."}],"safari_ios":[{"version_added":"12.2"},{"version_added":"11.3","partial_implementation":true,"notes":"Even though <code>window.AbortController</code> is defined, it doesn't really abort <code>fetch</code> requests. See <a href='https://webkit.org/b/174980'>bug 174980</a>."}],"samsunginternet_android":{"version_added":"9.0"},"webview_android":{"version_added":"66"}},"status":{"experimental":true,"standard_track":true,"deprecated":false}},"AbortController":{"__compat":{"mdn_url":"https://developer.mozilla.org/docs/Web/API/AbortController/AbortController","spec_url":"https://dom.spec.whatwg.org/#ref-for-dom-abortcontroller-abortcontroller①","description":"<code>AbortController()</code> constructor","support":{"chrome":{"version_added":"66"},"chrome_android":{"version_added":"66"},"edge":{"version_added":"16"},"firefox":{"version_added":"57"},"firefox_android":{"version_added":"57"},"ie":{"version_added":false},"nodejs":{"version_added":"15.0.0"},"opera":{"version_added":"53"},"opera_android":{"version_added":"47"},"safari":[{"version_added":"12.1"},{"version_added":"11.1","partial_implementation":true,"notes":"Even though <code>window.AbortController</code> is defined, it doesn't really abort <code>fetch</code> requests. See <a href='https://webkit.org/b/174980'>bug 174980</a>."}],"safari_ios":[{"version_added":"12.2"},{"version_added":"11.3","partial_implementation":true,"notes":"Even though <code>window.AbortController</code> is defined, it doesn't really abort <code>fetch</code> requests. See <a href='https://webkit.org/b/174980'>bug 174980</a>."}],"samsunginternet_android":{"version_added":"9.0"},"webview_android":{"version_added":"66"}},"status":{"experimental":true,"standard_track":true,"deprecated":false}}},"abort":{"__compat":{"mdn_url":"https://developer.mozilla.org/docs/Web/API/AbortController/abort","spec_url":"https://dom.spec.whatwg.org/#ref-for-dom-abortcontroller-abortcontroller①","support":{"chrome":{"version_added":"66"},"chrome_android":{"version_added":"66"},"edge":{"version_added":"16"},"firefox":{"version_added":"57"},"firefox_android":{"version_added":"57"},"ie":{"version_added":false},"nodejs":{"version_added":"15.0.0"},"opera":{"version_added":"53"},"opera_android":{"version_added":"47"},"safari":[{"version_added":"12.1"},{"version_added":"11.1","partial_implementation":true,"notes":"Even though <code>window.AbortController</code> is defined, it doesn't really abort <code>fetch</code> requests. See <a href='https://webkit.org/b/174980'>bug 174980</a>."}],"safari_ios":[{"version_added":"12.2"},{"version_added":"11.3","partial_implementation":true,"notes":"Even though <code>window.AbortController</code> is defined, it doesn't really abort <code>fetch</code> requests. See <a href='https://webkit.org/b/174980'>bug 174980</a>."}],"samsunginternet_android":{"version_added":"9.0"},"webview_android":{"version_added":"66"}},"status":{"experimental":true,"standard_track":true,"deprecated":false}}},"signal":{"__compat":{"mdn_url":"https://developer.mozilla.org/docs/Web/API/AbortController/signal","spec_url":"https://dom.spec.whatwg.org/#ref-for-dom-abortcontroller-signal②","support":{"chrome":{"version_added":"66"},"chrome_android":{"version_added":"66"},"edge":{"version_added":"16"},"firefox":{"version_added":"57"},"firefox_android":{"version_added":"57"},"ie":{"version_added":false},"nodejs":{"version_added":"15.0.0"},"opera":{"version_added":"53"},"opera_android":{"version_added":"47"},"safari":[{"version_added":"12.1"},{"version_added":"11.1","partial_implementation":true,"notes":"Even though <code>window.AbortController</code> is defined, it doesn't really abort <code>fetch</code> requests. See <a href='https://webkit.org/b/174980'>bug 174980</a>."}],"safari_ios":[{"version_added":"12.2"},{"version_added":"11.3","partial_implementation":true,"notes":"Even though <code>window.AbortController</code> is defined, it doesn't really abort <code>fetch</code> requests. See <a href='https://webkit.org/b/174980'>bug 174980</a>."}],"samsunginternet_android":{"version_added":"9.0"},"webview_android":{"version_added":"66"}},"status":{"experimental":true,"standard_track":true,"deprecated":false}}}},"AbortPaymentEvent":{"__compat":{"mdn_url":"https://developer.mozilla.org/docs/Web/API/AbortPaymentEvent","support":{"chrome":{"version_added":"70"},"chrome_android":{"version_added":"70"},"edge":{"version_added":"79"},"firefox":{"version_added":false},"firefox_android":{"version_added":false},"ie":{"version_added":false},"opera":{"version_added":"57"},"opera_android":{"version_added":"49"},"safari":{"version_added":false},"safari_ios":{"version_added":false},"samsunginternet_android":{"version_added":"10.0"},"webview_android":{"version_added":false}},"status":{"experimental":true,"standard_track":false,"deprecated":false}},"AbortPaymentEvent":{"__compat":{"description":"<code>AbortPaymentEvent()</code> constructor","mdn_url":"https://developer.mozilla.org/docs/Web/API/AbortPaymentEvent/AbortPaymentEvent","support":{"chrome":{"version_added":"70"},"chrome_android":{"version_added":"70"},"edge":{"version_added":"79"},"firefox":{"version_added":false},"firefox_android":{"version_added":false},"ie":{"version_added":false},"opera":{"version_added":"57"},"opera_android":{"version_added":"49"},"safari":{"version_added":false},"safari_ios":{"version_added":false},"samsunginternet_android":{"version_added":"10.0"},"webview_android":{"version_added":false}},"status":{"experimental":true,"standard_track":false,"deprecated":false}}},"respondWith":{"__compat":{"mdn_url":"https://developer.mozilla.org/docs/Web/API/AbortPaymentEvent/respondWith","support":{"chrome":{"version_added":"70"},"chrome_android":{"version_added":"70"},"edge":{"version_added":"79"},"firefox":{"version_added":false},"firefox_android":{"version_added":false},"ie":{"version_added":false},"opera":{"version_added":"57"},"opera_android":{"version_added":"49"},"safari":{"version_added":false},"safari_ios":{"version_added":false},"samsunginternet_android":{"version_added":"10.0"},"webview_android":{"version_added":false}},"status":{"experimental":true,"standard_track":false,"deprecated":false}}}},"AbortSignal":{"__compat":{"mdn_url":"https://developer.mozilla.org/docs/Web/API/AbortSignal","spec_url":"https://dom.spec.whatwg.org/#interface-AbortSignal","support":{"chrome":{"version_added":"66"},"chrome_android":{"version_added":"66"},"edge":{"version_added":"16"},"firefox":{"version_added":"57"},"firefox_android":{"version_added":"57"},"ie":{"version_added":false},"nodejs":{"version_added":"15.0.0"},"opera":{"version_added":"53"},"opera_android":{"version_added":"47"},"safari":{"version_added":"11.1"},"safari_ios":{"version_added":"11.3"},"samsunginternet_android":{"version_added":"9.0"},"webview_android":{"version_added":"66"}},"status":{"experimental":false,"standard_track":true,"deprecated":false}},"abort":{"__compat":{"mdn_url":"https://developer.mozilla.org/docs/Web/API/AbortSignal/abort","spec_url":"https://dom.spec.whatwg.org/#ref-for-dom-abortsignal-abort①","support":{"chrome":{"version_added":false},"chrome_android":{"version_added":false},"edge":{"version_added":false},"firefox":{"version_added":"88"},"firefox_android":{"version_added":"88"},"ie":{"version_added":false},"nodejs":{"version_added":false},"opera":{"version_added":false},"opera_android":{"version_added":false},"safari":{"version_added":false},"safari_ios":{"version_added":false},"samsunginternet_android":{"version_added":false},"webview_android":{"version_added":false}},"status":{"experimental":false,"standard_track":true,"deprecated":false}}},"abort_event":{"__compat":{"description":"<code>abort</code> event","mdn_url":"https://developer.mozilla.org/docs/Web/API/AbortSignal/abort_event","spec_url":"https://dom.spec.whatwg.org/#eventdef-abortsignal-abort","support":{"chrome":{"version_added":"66"},"chrome_android":{"version_added":"66"},"edge":{"version_added":"16"},"firefox":{"version_added":"57"},"firefox_android":{"version_added":"57"},"ie":{"version_added":false},"nodejs":{"version_added":"15.0.0"},"opera":{"version_added":"53"},"opera_android":{"version_added":"47"},"safari":{"version_added":"11.1"},"safari_ios":{"version_added":"11.3"},"samsunginternet_android":{"version_added":"9.0"},"webview_android":{"version_added":"66"}},"status":{"experimental":false,"standard_track":true,"deprecated":false}}},"aborted":{"__compat":{"mdn_url":"https://developer.mozilla.org/docs/Web/API/AbortSignal/aborted","spec_url":"https://dom.spec.whatwg.org/#ref-for-dom-abortsignal-aborted①","support":{"chrome":{"version_added":"66"},"chrome_android":{"version_added":"66"},"edge":{"version_added":"16"},"firefox":{"version_added":"57"},"firefox_android":{"version_added":"57"},"ie":{"version_added":false},"nodejs":{"version_added":"15.0.0"},"opera":{"version_added":"53"},"opera_android":{"version_added":"47"},"safari":{"version_added":"11.1"},"safari_ios":{"version_added":"11.3"},"samsunginternet_android":{"version_added":"9.0"},"webview_android":{"version_added":"66"}},"status":{"experimental":false,"standard_track":true,"deprecated":false}}},"onabort":{"__compat":{"mdn_url":"https://developer.mozilla.org/docs/Web/API/AbortSignal/onabort","spec_url":"https://dom.spec.whatwg.org/#abortsignal-onabort","support":{"chrome":{"version_added":"66"},"chrome_android":{"version_added":"66"},"edge":{"version_added":"16"},"firefox":{"version_added":"57"},"firefox_android":{"version_added":"57"},"ie":{"version_added":false},"nodejs":{"version_added":"15.0.0"},"opera":{"version_added":"53"},"opera_android":{"version_added":"47"},"safari":{"version_added":"11.1"},"safari_ios":{"version_added":"11.3"},"samsunginternet_android":{"version_added":"9.0"},"webview_android":{"version_added":"66"}},"status":{"experimental":false,"standard_track":true,"deprecated":false}}}},"AbsoluteOrientationSensor":{"__compat":{"mdn_url":"https://developer.mozilla.org/docs/Web/API/AbsoluteOrientationSensor","spec_url":"https://w3c.github.io/orientation-sensor/#absoluteorientationsensor-interface","support":{"chrome":{"version_added":"67"},"chrome_android":{"version_added":"67"},"edge":{"version_added":"79"},"firefox":{"version_added":false},"firefox_android":{"version_added":false},"ie":{"version_added":false},"opera":{"version_added":"54"},"opera_android":{"version_added":"48"},"safari":{"version_added":false},"safari_ios":{"version_added":false},"samsunginternet_android":{"version_added":"9.0"},"webview_android":{"version_added":"67"}},"status":{"experimental":false,"standard_track":true,"deprecated":false}},"AbsoluteOrientationSensor":{"__compat":{"mdn_url":"https://developer.mozilla.org/docs/Web/API/AbsoluteOrientationSensor/AbsoluteOrientationSensor","spec_url":"https://w3c.github.io/orientation-sensor/#dom-absoluteorientationsensor-absoluteorientationsensor","description":"<code>AbsoluteOrientationSensor()</code> constructor","support":{"chrome":{"version_added":"67"},"chrome_android":{"version_added":"67"},"edge":{"version_added":"79"},"firefox":{"version_added":false},"firefox_android":{"version_added":false},"ie":{"version_added":false},"opera":{"version_added":"54"},"opera_android":{"version_added":"48"},"safari":{"version_added":false},"safari_ios":{"version_added":false},"samsunginternet_android":{"version_added":"9.0"},"webview_android":{"version_added":"67"}},"status":{"experimental":false,"standard_track":true,"deprecated":false}}}},"AbstractRange":{"__compat":{"mdn_url":"https://developer.mozilla.org/docs/Web/API/AbstractRange","spec_url":"https://dom.spec.whatwg.org/#interface-abstractrange","support":{"chrome":{"version_added":"90"},"chrome_android":{"version_added":"90"},"edge":[{"version_added":"90"},{"version_added":"18","version_removed":"79"}],"firefox":{"version_added":"69"},"firefox_android":{"version_added":false},"ie":{"version_added":false},"opera":{"version_added":false},"opera_android":{"version_added":false},"safari":{"version_added":"14.1"},"safari_ios":{"version_added":"14.5"},"samsunginternet_android":{"version_added":false},"webview_android":{"version_added":"90"}},"status":{"experimental":false,"standard_track":true,"deprecated":false}},"collapsed":{"__compat":{"mdn_url":"https://developer.mozilla.org/docs/Web/API/AbstractRange/collapsed","spec_url":"https://dom.spec.whatwg.org/#ref-for-dom-range-collapsed①","support":{"chrome":{"version_added":"90"},"chrome_android":{"version_added":"90"},"edge":[{"version_added":"90"},{"version_added":"18","version_removed":"79"}],"firefox":{"version_added":"69"},"firefox_android":{"version_added":false},"ie":{"version_added":false},"opera":{"version_added":false},"opera_android":
3+ {"version_added":false}
tests/integration_tests.rs+250−3
@@ -919,7 +919,7 @@ fn empty_file_leads_to_empty_output_with_rule_enabled() {
919919}
920920
921921#[test]
922−fn filename_basic() {
922+fn header_basic() {
923923 bat()
924924 .arg("test.txt")
925925 .arg("--decorations=always")
@@ -933,7 +933,21 @@ fn filename_basic() {
933933}
934934
935935#[test]
936−fn filename_binary() {
936+fn header_full_basic() {
937+ bat()
938+ .arg("test.txt")
939+ .arg("--decorations=always")
940+ .arg("--style=header-filename,header-filesize")
941+ .arg("-r=0:0")
942+ .arg("--file-name=foo")
943+ .assert()
944+ .success()
945+ .stdout("File: foo\nSize: 12 B\n")
946+ .stderr("");
947+}
948+
949+#[test]
950+fn header_binary() {
937951 bat()
938952 .arg("test.binary")
939953 .arg("--decorations=always")
@@ -946,6 +960,67 @@ fn filename_binary() {
946960 .stderr("");
947961}
948962
963+#[test]
964+fn header_full_binary() {
965+ bat()
966+ .arg("test.binary")
967+ .arg("--decorations=always")
968+ .arg("--style=header-filename,header-filesize")
969+ .arg("-r=0:0")
970+ .arg("--file-name=foo")
971+ .assert()
972+ .success()
973+ .stdout("File: foo <BINARY>\nSize: 4 B\n")
974+ .stderr("");
975+}
976+
977+#[test]
978+fn header_default() {
979+ bat()
980+ .arg("--paging=never")
981+ .arg("--color=never")
982+ .arg("--terminal-width=80")
983+ .arg("--wrap=never")
984+ .arg("--decorations=always")
985+ .arg("--style=default")
986+ .arg("single-line.txt")
987+ .assert()
988+ .success()
989+ .stdout(
990+ "\
991+───────┬────────────────────────────────────────────────────────────────────────
992+ │ File: single-line.txt
993+───────┼────────────────────────────────────────────────────────────────────────
994+ 1 │ Single Line
995+───────┴────────────────────────────────────────────────────────────────────────
996+",
997+ )
998+ .stderr("");
999+}
1000+
1001+#[test]
1002+fn header_default_is_default() {
1003+ bat()
1004+ .arg("--paging=never")
1005+ .arg("--color=never")
1006+ .arg("--terminal-width=80")
1007+ .arg("--wrap=never")
1008+ .arg("--decorations=always")
1009+ .arg("single-line.txt")
1010+ .assert()
1011+ .success()
1012+ .stdout(
1013+ "\
1014+───────┬────────────────────────────────────────────────────────────────────────
1015+ │ File: single-line.txt
1016+───────┼────────────────────────────────────────────────────────────────────────
1017+ 1 │ Single Line
1018+───────┴────────────────────────────────────────────────────────────────────────
1019+",
1020+ )
1021+ .stderr("");
1022+}
1023+
9491024#[test]
9501025fn filename_stdin() {
9511026 bat()
@@ -1016,6 +1091,18 @@ fn header_padding() {
10161091 .stderr("");
10171092}
10181093
1094+#[test]
1095+fn header_full_padding() {
1096+ bat()
1097+ .arg("--decorations=always")
1098+ .arg("--style=header-filename,header-filesize")
1099+ .arg("test.txt")
1100+ .arg("single-line.txt")
1101+ .assert()
1102+ .stdout("File: test.txt\nSize: 12 B\nhello world\n\nFile: single-line.txt\nSize: 11 B\nSingle Line\n")
1103+ .stderr("");
1104+}
1105+
10191106#[test]
10201107fn header_padding_rule() {
10211108 bat()
@@ -1036,6 +1123,28 @@ Single Line
10361123 .stderr("");
10371124}
10381125
1126+#[test]
1127+fn header_full_padding_rule() {
1128+ bat()
1129+ .arg("--decorations=always")
1130+ .arg("--style=header-filename,header-filesize,rule")
1131+ .arg("--terminal-width=80")
1132+ .arg("test.txt")
1133+ .arg("single-line.txt")
1134+ .assert()
1135+ .stdout(
1136+ "File: test.txt
1137+Size: 12 B
1138+hello world
1139+────────────────────────────────────────────────────────────────────────────────
1140+File: single-line.txt
1141+Size: 11 B
1142+Single Line
1143+",
1144+ )
1145+ .stderr("");
1146+}
1147+
10391148#[test]
10401149fn grid_overrides_rule() {
10411150 bat()
@@ -1055,7 +1164,9 @@ Single Line
10551164────────────────────────────────────────────────────────────────────────────────
10561165",
10571166 )
1058− .stderr("\x1b[33m[bat warning]\x1b[0m: Style 'rule' is a subset of style 'grid', 'rule' will not be visible.\n");
1167+ .stderr(
1168+ "\x1b[33m[bat warning]\x1b[0m: Style 'rule' is a subset of style 'grid', 'rule' will not be visible.\n",
1169+ );
10591170}
10601171
10611172#[cfg(target_os = "linux")]
@@ -1153,6 +1264,52 @@ fn show_all_mode() {
11531264 .stderr("");
11541265}
11551266
1267+#[test]
1268+fn show_all_extends_tab_markers_to_next_tabstop() {
1269+ bat()
1270+ .arg("tabs.txt")
1271+ .arg("--show-all")
1272+ .arg("--tabs=4")
1273+ .arg("--style=plain")
1274+ .assert()
1275+ .success()
1276+ .stdout(
1277+ "├──┤1├─┤2├─┤3├─┤4␊
1278+1├─┤?␊
1279+22├┤?␊
1280+333↹?␊
1281+4444├──┤?␊
1282+55555├─┤?␊
1283+666666├┤?␊
1284+7777777↹?␊
1285+88888888├──┤?␊
1286+",
1287+ );
1288+}
1289+
1290+#[test]
1291+fn show_all_extends_tab_markers_to_next_tabstop_width_8() {
1292+ bat()
1293+ .arg("tabs.txt")
1294+ .arg("--show-all")
1295+ .arg("--tabs=8")
1296+ .arg("--style=plain")
1297+ .assert()
1298+ .success()
1299+ .stdout(
1300+ "├──────┤1├─────┤2├─────┤3├─────┤4␊
1301+1├─────┤?␊
1302+22├────┤?␊
1303+333├───┤?␊
1304+4444├──┤?␊
1305+55555├─┤?␊
1306+666666├┤?␊
1307+7777777↹?␊
1308+88888888├──────┤?␊
1309+",
1310+ );
1311+}
1312+
11561313#[test]
11571314fn no_paging_arg() {
11581315 bat()
@@ -1219,6 +1376,7 @@ fn grid_for_file_without_newline() {
12191376 "\
12201377───────┬────────────────────────────────────────────────────────────────────────
12211378 │ File: single-line.txt
1379+ │ Size: 11 B
12221380───────┼────────────────────────────────────────────────────────────────────────
12231381 1 │ Single Line
12241382───────┴────────────────────────────────────────────────────────────────────────
@@ -1227,6 +1385,25 @@ fn grid_for_file_without_newline() {
12271385 .stderr("");
12281386}
12291387
1388+// For ANSI theme, use underscore as a highlighter
1389+#[test]
1390+fn ansi_highlight_underline() {
1391+ bat()
1392+ .arg("--paging=never")
1393+ .arg("--color=never")
1394+ .arg("--terminal-width=80")
1395+ .arg("--wrap=never")
1396+ .arg("--decorations=always")
1397+ .arg("--theme=ansi")
1398+ .arg("--style=plain")
1399+ .arg("--highlight-line=1")
1400+ .write_stdin("Ansi Underscore Test\nAnother Line")
1401+ .assert()
1402+ .success()
1403+ .stdout("\x1B[4mAnsi Underscore Test\n\x1B[24mAnother Line")
1404+ .stderr("");
1405+}
1406+
12301407// Ensure that ANSI passthrough is emitted properly for both wrapping and non-wrapping printer.
12311408#[test]
12321409fn ansi_passthrough_emit() {
@@ -1250,6 +1427,8 @@ fn ansi_passthrough_emit() {
12501427fn ignored_suffix_arg() {
12511428 bat()
12521429 .arg("-f")
1430+ .arg("--theme")
1431+ .arg("Monokai Extended")
12531432 .arg("-p")
12541433 .arg("test.json~")
12551434 .assert()
@@ -1259,6 +1438,8 @@ fn ignored_suffix_arg() {
12591438
12601439 bat()
12611440 .arg("-f")
1441+ .arg("--theme")
1442+ .arg("Monokai Extended")
12621443 .arg("-p")
12631444 .arg("--ignored-suffix=.suffix")
12641445 .arg("test.json.suffix")
@@ -1269,6 +1450,8 @@ fn ignored_suffix_arg() {
12691450
12701451 bat()
12711452 .arg("-f")
1453+ .arg("--theme")
1454+ .arg("Monokai Extended")
12721455 .arg("-p")
12731456 .arg("test.json.suffix")
12741457 .assert()
@@ -1277,6 +1460,70 @@ fn ignored_suffix_arg() {
12771460 .stderr("");
12781461}
12791462
1463+#[test]
1464+fn highlighting_is_skipped_on_long_lines() {
1465+ let expected = "\u{1b}[38;5;231m{\u{1b}[0m\u{1b}[38;5;208m\"\u{1b}[0m\u{1b}[38;5;208mapi\u{1b}[0m\u{1b}[38;5;208m\"\u{1b}[0m\u{1b}[38;5;231m:\u{1b}[0m\n".to_owned() +
1466+ "\u{1b}" +
1467+ r#"[38;5;231m {"ANGLE_instanced_arrays":{"__compat":{"mdn_url":"https://developer.mozilla.org/docs/Web/API/ANGLE_instanced_arrays","spec_url":"https://www.khronos.org/registry/webgl/extensions/ANGLE_instanced_arrays/","support":{"chrome":{"version_added":"32"},"chrome_android":{"version_added":"32"},"edge":{"version_added":"12"},"firefox":{"version_added":"47"},"firefox_android":{"version_added":true},"ie":{"version_added":"11"},"opera":{"version_added":"19"},"opera_android":{"version_added":"19"},"safari":{"version_added":"8"},"safari_ios":{"version_added":"8"},"samsunginternet_android":{"version_added":"2.0"},"webview_android":{"version_added":"4.4"}},"status":{"experimental":false,"standard_track":true,"deprecated":false}},"drawArraysInstancedANGLE":{"__compat":{"mdn_url":"https://developer.mozilla.org/docs/Web/API/ANGLE_instanced_arrays/drawArraysInstancedANGLE","spec_url":"https://www.khronos.org/registry/webgl/extensions/ANGLE_instanced_arrays/","support":{"chrome":{"version_added":"32"},"chrome_android":{"version_added":"32"},"edge":{"version_added":"12"},"firefox":{"version_added":"47"},"firefox_android":{"version_added":true},"ie":{"version_added":"11"},"opera":{"version_added":"19"},"opera_android":{"version_added":"19"},"safari":{"version_added":"8"},"safari_ios":{"version_added":"8"},"samsunginternet_android":{"version_added":"2.0"},"webview_android":{"version_added":"4.4"}},"status":{"experimental":false,"standard_track":true,"deprecated":false}}},"drawElementsInstancedANGLE":{"__compat":{"mdn_url":"https://developer.mozilla.org/docs/Web/API/ANGLE_instanced_arrays/drawElementsInstancedANGLE","spec_url":"https://www.khronos.org/registry/webgl/extensions/ANGLE_instanced_arrays/","support":{"chrome":{"version_added":"32"},"chrome_android":{"version_added":"32"},"edge":{"version_added":"12"},"firefox":{"version_added":"47"},"firefox_android":{"version_added":true},"ie":{"version_added":"11"},"opera":{"version_added":"19"},"opera_android":{"version_added":"19"},"safari":{"version_added":"8"},"safari_ios":{"version_added":"8"},"samsunginternet_android":{"version_added":"2.0"},"webview_android":{"version_added":"4.4"}},"status":{"experimental":false,"standard_track":true,"deprecated":false}}},"vertexAttribDivisorANGLE":{"__compat":{"mdn_url":"https://developer.mozilla.org/docs/Web/API/ANGLE_instanced_arrays/vertexAttribDivisorANGLE","spec_url":"https://www.khronos.org/registry/webgl/extensions/ANGLE_instanced_arrays/","support":{"chrome":{"version_added":"32"},"chrome_android":{"version_added":"32"},"edge":{"version_added":"12"},"firefox":{"version_added":"47"},"firefox_android":{"version_added":true},"ie":{"version_added":"11"},"opera":{"version_added":"19"},"opera_android":{"version_added":"19"},"safari":{"version_added":"8"},"safari_ios":{"version_added":"8"},"samsunginternet_android":{"version_added":"2.0"},"webview_android":{"version_added":"4.4"}},"status":{"experimental":false,"standard_track":true,"deprecated":false}}}},"AbortController":{"__compat":{"mdn_url":"https://developer.mozilla.org/docs/Web/API/AbortController","spec_url":"https://dom.spec.whatwg.org/#interface-abortcontroller","support":{"chrome":{"version_added":"66"},"chrome_android":{"version_added":"66"},"edge":{"version_added":"16"},"firefox":{"version_added":"57"},"firefox_android":{"version_added":"57"},"ie":{"version_added":false},"nodejs":{"version_added":"15.0.0"},"opera":{"version_added":"53"},"opera_android":{"version_added":"47"},"safari":[{"version_added":"12.1"},{"version_added":"11.1","partial_implementation":true,"notes":"Even though <code>window.AbortController</code> is defined, it doesn't really abort <code>fetch</code> requests. See <a href='https://webkit.org/b/174980'>bug 174980</a>."}],"safari_ios":[{"version_added":"12.2"},{"version_added":"11.3","partial_implementation":true,"notes":"Even though <code>window.AbortController</code> is defined, it doesn't really abort <code>fetch</code> requests. See <a href='https://webkit.org/b/174980'>bug 174980</a>."}],"samsunginternet_android":{"version_added":"9.0"},"webview_android":{"version_added":"66"}},"status":{"experimental":true,"standard_track":true,"deprecated":false}},"AbortController":{"__compat":{"mdn_url":"https://developer.mozilla.org/docs/Web/API/AbortController/AbortController","spec_url":"https://dom.spec.whatwg.org/#ref-for-dom-abortcontroller-abortcontroller①","description":"<code>AbortController()</code> constructor","support":{"chrome":{"version_added":"66"},"chrome_android":{"version_added":"66"},"edge":{"version_added":"16"},"firefox":{"version_added":"57"},"firefox_android":{"version_added":"57"},"ie":{"version_added":false},"nodejs":{"version_added":"15.0.0"},"opera":{"version_added":"53"},"opera_android":{"version_added":"47"},"safari":[{"version_added":"12.1"},{"version_added":"11.1","partial_implementation":true,"notes":"Even though <code>window.AbortController</code> is defined, it doesn't really abort <code>fetch</code> requests. See <a href='https://webkit.org/b/174980'>bug 174980</a>."}],"safari_ios":[{"version_added":"12.2"},{"version_added":"11.3","partial_implementation":true,"notes":"Even though <code>window.AbortController</code> is defined, it doesn't really abort <code>fetch</code> requests. See <a href='https://webkit.org/b/174980'>bug 174980</a>."}],"samsunginternet_android":{"version_added":"9.0"},"webview_android":{"version_added":"66"}},"status":{"experimental":true,"standard_track":true,"deprecated":false}}},"abort":{"__compat":{"mdn_url":"https://developer.mozilla.org/docs/Web/API/AbortController/abort","spec_url":"https://dom.spec.whatwg.org/#ref-for-dom-abortcontroller-abortcontroller①","support":{"chrome":{"version_added":"66"},"chrome_android":{"version_added":"66"},"edge":{"version_added":"16"},"firefox":{"version_added":"57"},"firefox_android":{"version_added":"57"},"ie":{"version_added":false},"nodejs":{"version_added":"15.0.0"},"opera":{"version_added":"53"},"opera_android":{"version_added":"47"},"safari":[{"version_added":"12.1"},{"version_added":"11.1","partial_implementation":true,"notes":"Even though <code>window.AbortController</code> is defined, it doesn't really abort <code>fetch</code> requests. See <a href='https://webkit.org/b/174980'>bug 174980</a>."}],"safari_ios":[{"version_added":"12.2"},{"version_added":"11.3","partial_implementation":true,"notes":"Even though <code>window.AbortController</code> is defined, it doesn't really abort <code>fetch</code> requests. See <a href='https://webkit.org/b/174980'>bug 174980</a>."}],"samsunginternet_android":{"version_added":"9.0"},"webview_android":{"version_added":"66"}},"status":{"experimental":true,"standard_track":true,"deprecated":false}}},"signal":{"__compat":{"mdn_url":"https://developer.mozilla.org/docs/Web/API/AbortController/signal","spec_url":"https://dom.spec.whatwg.org/#ref-for-dom-abortcontroller-signal②","support":{"chrome":{"version_added":"66"},"chrome_android":{"version_added":"66"},"edge":{"version_added":"16"},"firefox":{"version_added":"57"},"firefox_android":{"version_added":"57"},"ie":{"version_added":false},"nodejs":{"version_added":"15.0.0"},"opera":{"version_added":"53"},"opera_android":{"version_added":"47"},"safari":[{"version_added":"12.1"},{"version_added":"11.1","partial_implementation":true,"notes":"Even though <code>window.AbortController</code> is defined, it doesn't really abort <code>fetch</code> requests. See <a href='https://webkit.org/b/174980'>bug 174980</a>."}],"safari_ios":[{"version_added":"12.2"},{"version_added":"11.3","partial_implementation":true,"notes":"Even though <code>window.AbortController</code> is defined, it doesn't really abort <code>fetch</code> requests. See <a href='https://webkit.org/b/174980'>bug 174980</a>."}],"samsunginternet_android":{"version_added":"9.0"},"webview_android":{"version_added":"66"}},"status":{"experimental":true,"standard_track":true,"deprecated":false}}}},"AbortPaymentEvent":{"__compat":{"mdn_url":"https://developer.mozilla.org/docs/Web/API/AbortPaymentEvent","support":{"chrome":{"version_added":"70"},"chrome_android":{"version_added":"70"},"edge":{"version_added":"79"},"firefox":{"version_added":false},"firefox_android":{"version_added":false},"ie":{"version_added":false},"opera":{"version_added":"57"},"opera_android":{"version_added":"49"},"safari":{"version_added":false},"safari_ios":{"version_added":false},"samsunginternet_android":{"version_added":"10.0"},"webview_android":{"version_added":false}},"status":{"experimental":true,"standard_track":false,"deprecated":false}},"AbortPaymentEvent":{"__compat":{"description":"<code>AbortPaymentEvent()</code> constructor","mdn_url":"https://developer.mozilla.org/docs/Web/API/AbortPaymentEvent/AbortPaymentEvent","support":{"chrome":{"version_added":"70"},"chrome_android":{"version_added":"70"},"edge":{"version_added":"79"},"firefox":{"version_added":false},"firefox_android":{"version_added":false},"ie":{"version_added":false},"opera":{"version_added":"57"},"opera_android":{"version_added":"49"},"safari":{"version_added":false},"safari_ios":{"version_added":false},"samsunginternet_android":{"version_added":"10.0"},"webview_android":{"version_added":false}},"status":{"experimental":true,"standard_track":false,"deprecated":false}}},"respondWith":{"__compat":{"mdn_url":"https://developer.mozilla.org/docs/Web/API/AbortPaymentEvent/respondWith","support":{"chrome":{"version_added":"70"},"chrome_android":{"version_added":"70"},"edge":{"version_added":"79"},"firefox":{"version_added":false},"firefox_android":{"version_added":false},"ie":{"version_added":false},"opera":{"version_added":"57"},"opera_android":{"version_added":"49"},"safari":{"version_added":false},"safari_ios":{"version_added":false},"samsunginternet_android":{"version_added":"10.0"},"webview_android":{"version_added":false}},"status":{"experimental":true,"standard_track":false,"deprecated":false}}}},"AbortSignal":{"__compat":{"mdn_url":"https://developer.mozilla.org/docs/Web/API/AbortSignal","spec_url":"https://dom.spec.whatwg.org/#interface-AbortSignal","support":{"chrome":{"version_added":"66"},"chrome_android":{"version_added":"66"},"edge":{"version_added":"16"},"firefox":{"version_added":"57"},"firefox_android":{"version_added":"57"},"ie":{"version_added":false},"nodejs":{"version_added":"15.0.0"},"opera":{"version_added":"53"},"opera_android":{"version_added":"47"},"safari":{"version_added":"11.1"},"safari_ios":{"version_added":"11.3"},"samsunginternet_android":{"version_added":"9.0"},"webview_android":{"version_added":"66"}},"status":{"experimental":false,"standard_track":true,"deprecated":false}},"abort":{"__compat":{"mdn_url":"https://developer.mozilla.org/docs/Web/API/AbortSignal/abort","spec_url":"https://dom.spec.whatwg.org/#ref-for-dom-abortsignal-abort①","support":{"chrome":{"version_added":false},"chrome_android":{"version_added":false},"edge":{"version_added":false},"firefox":{"version_added":"88"},"firefox_android":{"version_added":"88"},"ie":{"version_added":false},"nodejs":{"version_added":false},"opera":{"version_added":false},"opera_android":{"version_added":false},"safari":{"version_added":false},"safari_ios":{"version_added":false},"samsunginternet_android":{"version_added":false},"webview_android":{"version_added":false}},"status":{"experimental":false,"standard_track":true,"deprecated":false}}},"abort_event":{"__compat":{"description":"<code>abort</code> event","mdn_url":"https://developer.mozilla.org/docs/Web/API/AbortSignal/abort_event","spec_url":"https://dom.spec.whatwg.org/#eventdef-abortsignal-abort","support":{"chrome":{"version_added":"66"},"chrome_android":{"version_added":"66"},"edge":{"version_added":"16"},"firefox":{"version_added":"57"},"firefox_android":{"version_added":"57"},"ie":{"version_added":false},"nodejs":{"version_added":"15.0.0"},"opera":{"version_added":"53"},"opera_android":{"version_added":"47"},"safari":{"version_added":"11.1"},"safari_ios":{"version_added":"11.3"},"samsunginternet_android":{"version_added":"9.0"},"webview_android":{"version_added":"66"}},"status":{"experimental":false,"standard_track":true,"deprecated":false}}},"aborted":{"__compat":{"mdn_url":"https://developer.mozilla.org/docs/Web/API/AbortSignal/aborted","spec_url":"https://dom.spec.whatwg.org/#ref-for-dom-abortsignal-aborted①","support":{"chrome":{"version_added":"66"},"chrome_android":{"version_added":"66"},"edge":{"version_added":"16"},"firefox":{"version_added":"57"},"firefox_android":{"version_added":"57"},"ie":{"version_added":false},"nodejs":{"version_added":"15.0.0"},"opera":{"version_added":"53"},"opera_android":{"version_added":"47"},"safari":{"version_added":"11.1"},"safari_ios":{"version_added":"11.3"},"samsunginternet_android":{"version_added":"9.0"},"webview_android":{"version_added":"66"}},"status":{"experimental":false,"standard_track":true,"deprecated":false}}},"onabort":{"__compat":{"mdn_url":"https://developer.mozilla.org/docs/Web/API/AbortSignal/onabort","spec_url":"https://dom.spec.whatwg.org/#abortsignal-onabort","support":{"chrome":{"version_added":"66"},"chrome_android":{"version_added":"66"},"edge":{"version_added":"16"},"firefox":{"version_added":"57"},"firefox_android":{"version_added":"57"},"ie":{"version_added":false},"nodejs":{"version_added":"15.0.0"},"opera":{"version_added":"53"},"opera_android":{"version_added":"47"},"safari":{"version_added":"11.1"},"safari_ios":{"version_added":"11.3"},"samsunginternet_android":{"version_added":"9.0"},"webview_android":{"version_added":"66"}},"status":{"experimental":false,"standard_track":true,"deprecated":false}}}},"AbsoluteOrientationSensor":{"__compat":{"mdn_url":"https://developer.mozilla.org/docs/Web/API/AbsoluteOrientationSensor","spec_url":"https://w3c.github.io/orientation-sensor/#absoluteorientationsensor-interface","support":{"chrome":{"version_added":"67"},"chrome_android":{"version_added":"67"},"edge":{"version_added":"79"},"firefox":{"version_added":false},"firefox_android":{"version_added":false},"ie":{"version_added":false},"opera":{"version_added":"54"},"opera_android":{"version_added":"48"},"safari":{"version_added":false},"safari_ios":{"version_added":false},"samsunginternet_android":{"version_added":"9.0"},"webview_android":{"version_added":"67"}},"status":{"experimental":false,"standard_track":true,"deprecated":false}},"AbsoluteOrientationSensor":{"__compat":{"mdn_url":"https://developer.mozilla.org/docs/Web/API/AbsoluteOrientationSensor/AbsoluteOrientationSensor","spec_url":"https://w3c.github.io/orientation-sensor/#dom-absoluteorientationsensor-absoluteorientationsensor","description":"<code>AbsoluteOrientationSensor()</code> constructor","support":{"chrome":{"version_added":"67"},"chrome_android":{"version_added":"67"},"edge":{"version_added":"79"},"firefox":{"version_added":false},"firefox_android":{"version_added":false},"ie":{"version_added":false},"opera":{"version_added":"54"},"opera_android":{"version_added":"48"},"safari":{"version_added":false},"safari_ios":{"version_added":false},"samsunginternet_android":{"version_added":"9.0"},"webview_android":{"version_added":"67"}},"status":{"experimental":false,"standard_track":true,"deprecated":false}}}},"AbstractRange":{"__compat":{"mdn_url":"https://developer.mozilla.org/docs/Web/API/AbstractRange","spec_url":"https://dom.spec.whatwg.org/#interface-abstractrange","support":{"chrome":{"version_added":"90"},"chrome_android":{"version_added":"90"},"edge":[{"version_added":"90"},{"version_added":"18","version_removed":"79"}],"firefox":{"version_added":"69"},"firefox_android":{"version_added":false},"ie":{"version_added":false},"opera":{"version_added":false},"opera_android":{"version_added":false},"safari":{"version_added":"14.1"},"safari_ios":{"version_added":"14.5"},"samsunginternet_android":{"version_added":false},"webview_android":{"version_added":"90"}},"status":{"experimental":false,"standard_track":true,"deprecated":false}},"collapsed":{"__compat":{"mdn_url":"https://developer.mozilla.org/docs/Web/API/AbstractRange/collapsed","spec_url":"https://dom.spec.whatwg.org/#ref-for-dom-range-collapsed①","support":{"chrome":{"version_added":"90"},"chrome_android":{"version_added":"90"},"edge":[{"version_added":"90"},{"version_added":"18","version_removed":"79"}],"firefox":{"version_added":"69"},"firefox_android":{"version_added":false},"ie":{"version_added":false},"opera":{"version_added":false},"opera_android":"# +
1468+ "\u{1b}[0m\n\u{1b}[38;5;231m \u{1b}[0m\u{1b}[38;5;231m{\u{1b}[0m\u{1b}[38;5;208m\"\u{1b}[0m\u{1b}[38;5;208mversion_added\u{1b}[0m\u{1b}[38;5;208m\"\u{1b}[0m\u{1b}[38;5;231m:\u{1b}[0m\u{1b}[38;5;141mfalse\u{1b}[0m\u{1b}[38;5;231m}\u{1b}[0m\n";
1469+
1470+ bat()
1471+ .arg("-f")
1472+ .arg("--theme")
1473+ .arg("Monokai Extended")
1474+ .arg("-p")
1475+ .arg("longline.json")
1476+ .assert()
1477+ .success()
1478+ .stdout(expected)
1479+ .stderr("");
1480+}
1481+
1482+#[test]
1483+fn all_global_git_config_locations_syntax_mapping_work() {
1484+ let fake_home = Path::new(EXAMPLES_DIR).join("git").canonicalize().unwrap();
1485+ let expected = "\u{1b}[38;5;231m[\u{1b}[0m\u{1b}[38;5;149muser\u{1b}[0m\u{1b}[38;5;231m]\u{1b}[0m
1486+\u{1b}[38;5;231m \u{1b}[0m\u{1b}[38;5;231memail\u{1b}[0m\u{1b}[38;5;231m \u{1b}[0m\u{1b}[38;5;203m=\u{1b}[0m\u{1b}[38;5;231m \u{1b}[0m\u{1b}[38;5;186mfoo@bar.net\u{1b}[0m
1487+\u{1b}[38;5;231m \u{1b}[0m\u{1b}[38;5;231mname\u{1b}[0m\u{1b}[38;5;231m \u{1b}[0m\u{1b}[38;5;203m=\u{1b}[0m\u{1b}[38;5;231m \u{1b}[0m\u{1b}[38;5;186mfoobar\u{1b}[0m
1488+";
1489+
1490+ bat()
1491+ .env("XDG_CONFIG_HOME", fake_home.join(".config").as_os_str())
1492+ .arg("-f")
1493+ .arg("--theme")
1494+ .arg("Monokai Extended")
1495+ .arg("-p")
1496+ .arg("git/.config/git/config")
1497+ .assert()
1498+ .success()
1499+ .stdout(expected)
1500+ .stderr("");
1501+
1502+ bat()
1503+ .env("HOME", fake_home.as_os_str())
1504+ .arg("-f")
1505+ .arg("--theme")
1506+ .arg("Monokai Extended")
1507+ .arg("-p")
1508+ .arg("git/.config/git/config")
1509+ .assert()
1510+ .success()
1511+ .stdout(expected)
1512+ .stderr("");
1513+
1514+ bat()
1515+ .env("HOME", fake_home.as_os_str())
1516+ .arg("-f")
1517+ .arg("--theme")
1518+ .arg("Monokai Extended")
1519+ .arg("-p")
1520+ .arg("git/.gitconfig")
1521+ .assert()
1522+ .success()
1523+ .stdout(expected)
1524+ .stderr("");
1525+}
1526+
12801527#[test]
12811528fn acknowledgements() {
12821529 bat()
tests/snapshots/output/full.snapshot.txt+1
@@ -1,5 +1,6 @@
11───────┬────────────────────────────────────────────────────────────────────────
22 │ File: sample.rs
3+ │ Size: 533 B
34───────┼────────────────────────────────────────────────────────────────────────
45 1 + │ /// A rectangle. First line is changed to prevent a regression of #1869
56 2 │ struct Rectangle {
tests/syntax-tests/highlighted/INI/test.infnew file+5
@@ -0,0 +1,5 @@
1+[section]
2+key=value
3+# This file is just for testing that the INI syntax is registered to handle
4+# the .inf file extension, it is not testing the syntax highlighting capabilities
5+# of the INI syntax itself
tests/syntax-tests/highlighted/JQ/sample.jqnew file+60
@@ -0,0 +1,60 @@
1+import "../imported-file" ;
2+
3+# With Comments !
4+def weird($a; $b; $c):
5+ [ $a, $b, $c ] | transpose | reduce .[][] as $item (
6+ [];
7+ . + $item.property
8+ )
9+;
10+
11+. | weird (.a; .b; .c) |
12+
13+(
14+
15+if (. | contains("never") ) then
16+ "Why yes"
17+else
18+ 12.23
19+end
20+
21+) as $never |
22+
23+{
24+ hello,
25+ why: "because",
26+ hello: ( weird | ascii_upcase ),
27+ format_eg: ( . | @json "My json string \( . | this | part | just | white | ascii_upcase | transpose)" ),
28+ never: $never,
29+ "literal_key": literal_value,
30+ "this": 12.1e12,
31+ "part": "almost"
32+ "like": [
33+ 12,
34+ 2
35+ "json"
36+ {
37+ "quite": {
38+ similar: "but not quite"
39+ }
40+ }
41+ ],
42+} | (
43+ 
44+ # And with very basic brace matching
45+ 
46+ # Invalid End
47+ ] 
48+ 
49+ # Other invalid ends
50+ ( [ } ] )
51+
52+ # A "valid" sequence
53+ ( [ { key: () , other_key:( [ [] [[]] ] ), gaga } ] )
54+
55+ # A "invalid" sequence
56+ ( [ { key: () , other_key:( [ [] [[] ] ), gaga } ] )
57+
58+ "A string\n whith escaped characters \" because we can"
59+)
60+
tests/syntax-tests/highlighted/Log/example.log+1
@@ -1,2 +1,3 @@
112021-03-06 23:22:21.392 https://[2001:db8:4006:812::200e]:8080/path/the%20page.html
222021-03-06 23:22:21 https://example.com:8080/path/the%20page(with_parens).html
3+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" }
tests/syntax-tests/highlighted/Svelte/App.svelte+5−1
@@ -27,9 +27,13 @@
2727</script>
2828
2929<script type="text/livescript">
30− // This block is a regression test for a bat panic when a LiveScript syntax definition is missing
30+ // This block is a regression test for a bat panic when a LiveScript syntax definition is missing
3131</script>
3232
33+<style lang="text/postcss">
34+ /* This block is a regression test for a bat panic when a PostCSS syntax definition is missing */
35+</style>
36+
3337<style>
3438 main {
3539 position: relative;
tests/syntax-tests/highlighted/Syslog/example.syslog+3−3
@@ -1,7 +1,7 @@
11Apr 4 00:00:01 hostname-here systemd[1]: logrotate.service: Succeeded.
22Apr 4 00:00:01 hostname-here systemd[1]: Finished Rotate log files.
33Apr 4 00:00:01 hostname-here colord[920]: failed to get session [pid 137485]: No data available
4−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"
4+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"
55Apr 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.
66Apr 4 00:04:46 hostname-here ntpd[952]: Soliciting pool server 255.76.59.37
77Apr 4 00:05:21 hostname-here ntpd[952]: ::1 local addr 0:0:0:0:0:0:0:1 -> <null>
@@ -10,7 +10,7 @@
1010Apr 4 16:32:07 hostname-here NetworkManager[740]: <info> [1617629527.1101] manager: NetworkManager state is now CONNECTED_GLOBAL
1111Apr 4 22:00:45 hostname-here dbus-daemon[1094]: [session uid=1000 pid=1094] Successfully activated service 'io.github.celluloid_player.Celluloid'
1212Aug 11 13:29:06 hostname-here insomnia_insomnia.desktop[142666]: 13:29:06.316 › [updater] Updater not running platform=linux dev=false
13−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
14−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
13+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
14+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
1515Aug 11 21:40:31 hostname-here scop hello
1616Aug 16 21:38:21 hostname-here systemd[1]: Finished Cleanup of Temporary Directories.
tests/syntax-tests/highlighted/Vue/example.vue+5
@@ -8,6 +8,11 @@
88 </div>
99</template>
1010
11+<template lang='pug'>
12+ #container.col
13+ p This shall be formatted as Plain Text as long as a Pug syntax definition is missing
14+</template>
15+
1116<script>
1217import AppHeader from "@/components/AppHeader";
1318import AppLoadingIndicator from "@/components/AppLoadingIndicator";
tests/syntax-tests/highlighted/Zig/example.zig+39−39
@@ -1,18 +1,18 @@
11//! this is a top level doc, starts with "//!"
22
3−const std = @import("std");
3+const std = @import("std");
44
55pub fn main() anyerror!void {
6− const stdout = std.io.getStdOut().writer();
7− try stdout.print("Hello, {}!\n", .{"world"});
6+ const stdout = std.io.getStdOut().writer();
7+ try stdout.print("Hello, {}!\n", .{"world"});
88}
99
10−const expect = std.testing.expect;
10+const expect = std.testing.expect;
1111
1212test "comments" {
1313 // comments start with "//" until newline
1414 // foo bar baz
15− const x = true; // another comment
15+ const x = true; // another comment
1616 expect(x);
1717}
1818
@@ -25,26 +25,26 @@
2525 /// number of nanoseconds past the second
2626 nano: u32,
2727
28− const Self = @This();
28+ const Self = @This();
2929
3030 pub fn unixEpoch() Self {
3131 return Self{
32− .seconds = 0,
33− .nanos = 0,
32+ .seconds = 0,
33+ .nanos = 0,
3434 };
3535 }
3636};
3737
38−const my_val = switch (std.Target.current.os.tag) {
39− .linux => "Linux",
38+const my_val = switch (std.Target.current.os.tag) {
39+ .linux => "Linux",
4040 else => "not Linux",
4141};
4242
4343const Book = enum {
44− paperback,
45− hardcover,
46− ebook,
47− pdf,
44+ paperback,
45+ hardcover,
46+ ebook,
47+ pdf,
4848};
4949
5050const TokenType = union(enum) {
@@ -54,54 +54,54 @@
5454};
5555
5656const array_lit: [4]u8 = .{ 11, 22, 33, 44 };
57−const sentinal_lit = [_:0]u8{ 1, 2, 3, 4 };
57+const sentinal_lit = [_:0]u8{ 1, 2, 3, 4 };
5858
5959test "address of syntax" {
6060 // Get the address of a variable:
6161 const x: i32 = 1234;
62− const x_ptr = &x;
62+ const x_ptr = &x;
6363
6464 // Dereference a pointer:
6565 expect(x_ptr.* == 1234);
6666
6767 // When you get the address of a const variable, you get a const pointer to a single item.
68− expect(@TypeOf(x_ptr) == *const i32);
68+ expect(@TypeOf(x_ptr) == *const i32);
6969
7070 // If you want to mutate the value, you'd need an address of a mutable variable:
7171 var y: i32 = 5678;
72− const y_ptr = &y;
73− expect(@TypeOf(y_ptr) == *i32);
74− y_ptr.* += 1;
72+ const y_ptr = &y;
73+ expect(@TypeOf(y_ptr) == *i32);
74+ y_ptr.* += 1;
7575 expect(y_ptr.* == 5679);
7676}
7777
7878// integer literals
79−const decimal_int = 98222;
80−const hex_int = 0xff;
81−const another_hex_int = 0xFF;
82−const octal_int = 0o755;
83−const binary_int = 0b11110000;
79+const decimal_int = 98222;
80+const hex_int = 0xff;
81+const another_hex_int = 0xFF;
82+const octal_int = 0o755;
83+const binary_int = 0b11110000;
8484
8585// underscores may be placed between two digits as a visual separator
86−const one_billion = 1_000_000_000;
87−const binary_mask = 0b1_1111_1111;
88−const permissions = 0o7_5_5;
89−const big_address = 0xFF80_0000_0000_0000;
86+const one_billion = 1_000_000_000;
87+const binary_mask = 0b1_1111_1111;
88+const permissions = 0o7_5_5;
89+const big_address = 0xFF80_0000_0000_0000;
9090
9191// float literals
92−const floating_point = 123.0E+77;
93−const another_float = 123.0;
94−const yet_another = 123.0e+77;
92+const floating_point = 123.0E+77;
93+const another_float = 123.0;
94+const yet_another = 123.0e+77;
9595
96−const hex_floating_point = 0x103.70p-5;
97−const another_hex_float = 0x103.70;
98−const yet_another_hex_float = 0x103.70P-5;
96+const hex_floating_point = 0x103.70p-5;
97+const another_hex_float = 0x103.70;
98+const yet_another_hex_float = 0x103.70P-5;
9999
100100// underscores may be placed between two digits as a visual separator
101−const lightspeed = 299_792_458.000_000;
102−const nanosecond = 0.000_000_001;
103−const more_hex = 0x1234_5678.9ABC_CDEFp-10;
101+const lightspeed = 299_792_458.000_000;
102+const nanosecond = 0.000_000_001;
103+const more_hex = 0x1234_5678.9ABC_CDEFp-10;
104104
105105fn max(comptime T: type, a: T, b: T) T {
106− return if (a > b) a else b;
106+ return if (a > b) a else b;
107107}
tests/syntax-tests/highlighted/cmd-help/test.cmd-helpnew file+54
@@ -0,0 +1,54 @@
1+bat 0.20.0 (e735562-modified)
2+A cat(1) clone with syntax highlighting and Git integration.
3+
4+USAGE:
5+ bat [OPTIONS] [FILE]...
6+ bat <SUBCOMMAND>
7+
8+OPTIONS:
9+ -A, --show-all
10+ Show non-printable characters (space, tab, newline, ..).
11+
12+ -p, --plain Show plain style (alias for '--style=plain').
13+ -l, --language <language> Set the language for syntax highlighting.
14+ -H, --highlight-line <N:M>... Highlight lines N through M.
15+ --file-name <name>... Specify the name to display for a file.
16+ -d, --diff
17+ Only show lines that have been added/removed/modified.
18+
19+ --tabs <T> Set the tab width to T spaces.
20+ --wrap <mode>
21+ Specify the text-wrapping mode (*auto*, never, character).
22+
23+ -n, --number
24+ Show line numbers (alias for '--style=numbers').
25+
26+ --color <when> When to use colors (*auto*, never, always).
27+ --italic-text <when> Use italics in output (always, *never*)
28+ --decorations <when>
29+ When to show the decorations (*auto*, never, always).
30+
31+ --paging <when>
32+ Specify when to use the pager, or use `-P` to disable (*auto*, never,
33+ always).
34+ -m, --map-syntax <glob:syntax>...
35+ Use the specified syntax for files matching the glob pattern
36+ ('*.cpp:C++').
37+ --theme <theme> Set the color theme for syntax highlighting.
38+ --list-themes Display all supported highlighting themes.
39+ --style <components>
40+ Comma-separated list of style elements to display (*auto*, full, plain,
41+ changes, header, grid, rule, numbers, snip).
42+ -r, --line-range <N:M>... Only print the lines from N to M.
43+ -L, --list-languages Display all supported languages.
44+ -h, --help Print this help message.
45+ -V, --version Show version information.
46+
47+ARGS:
48+ <FILE>... File(s) to print / concatenate. Use '-' for standard input.
49+
50+SUBCOMMANDS:
51+ cache Modify the syntax-definition and theme cache
52+
53+Note: `bat -h` prints a short and concise overview while `bat --help` gives all
54+details.
tests/syntax-tests/source/INI/test.infnew file+5
@@ -0,0 +1,5 @@
1+[section]
2+key=value
3+# This file is just for testing that the INI syntax is registered to handle
4+# the .inf file extension, it is not testing the syntax highlighting capabilities
5+# of the INI syntax itself
tests/syntax-tests/source/JQ/LICENSE.mdnew file+25
@@ -0,0 +1,25 @@
1+The `sample.jq` file was taken from [SublimeJQ] under the following license:
2+
3+[SublimeJQ]: https://github.com/zogwarg/SublimeJQ
4+
5+MIT License
6+
7+Copyright (c) 2017 Thomas Buick
8+
9+Permission is hereby granted, free of charge, to any person obtaining a copy
10+of this software and associated documentation files (the "Software"), to deal
11+in the Software without restriction, including without limitation the rights
12+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13+copies of the Software, and to permit persons to whom the Software is
14+furnished to do so, subject to the following conditions:
15+
16+The above copyright notice and this permission notice shall be included in all
17+copies or substantial portions of the Software.
18+
19+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25+SOFTWARE.
tests/syntax-tests/source/JQ/sample.jqnew file+60
@@ -0,0 +1,60 @@
1+import "../imported-file" ;
2+
3+# With Comments !
4+def weird($a; $b; $c):
5+ [ $a, $b, $c ] | transpose | reduce .[][] as $item (
6+ [];
7+ . + $item.property
8+ )
9+;
10+
11+. | weird (.a; .b; .c) |
12+
13+(
14+
15+if (. | contains("never") ) then
16+ "Why yes"
17+else
18+ 12.23
19+end
20+
21+) as $never |
22+
23+{
24+ hello,
25+ why: "because",
26+ hello: ( weird | ascii_upcase ),
27+ format_eg: ( . | @json "My json string \( . | this | part | just | white | ascii_upcase | transpose)" ),
28+ never: $never,
29+ "literal_key": literal_value,
30+ "this": 12.1e12,
31+ "part": "almost"
32+ "like": [
33+ 12,
34+ 2
35+ "json"
36+ {
37+ "quite": {
38+ similar: "but not quite"
39+ }
40+ }
41+ ],
42+} | (
43+
44+ # And with very basic brace matching
45+
46+ # Invalid End
47+ ]
48+
49+ # Other invalid ends
50+ ( [ } ] )
51+
52+ # A "valid" sequence
53+ ( [ { key: () , other_key:( [ [] [[]] ] ), gaga } ] )
54+
55+ # A "invalid" sequence
56+ ( [ { key: () , other_key:( [ [] [[] ] ), gaga } ] )
57+
58+ "A string\n whith escaped characters \" because we can"
59+)
60+
tests/syntax-tests/source/Log/example.log+1
@@ -1,2 +1,3 @@
112021-03-06 23:22:21.392 https://[2001:db8:4006:812::200e]:8080/path/the%20page.html
222021-03-06 23:22:21 https://example.com:8080/path/the%20page(with_parens).html
3+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" }
tests/syntax-tests/source/Svelte/App.svelte+5−1
@@ -27,9 +27,13 @@
2727</script>
2828
2929<script type="text/livescript">
30− // This block is a regression test for a bat panic when a LiveScript syntax definition is missing
30+ // This block is a regression test for a bat panic when a LiveScript syntax definition is missing
3131</script>
3232
33+<style lang="text/postcss">
34+ /* This block is a regression test for a bat panic when a PostCSS syntax definition is missing */
35+</style>
36+
3337<style>
3438 main {
3539 position: relative;
tests/syntax-tests/source/Vue/example.vue+5
@@ -8,6 +8,11 @@
88 </div>
99</template>
1010
11+<template lang='pug'>
12+ #container.col
13+ p This shall be formatted as Plain Text as long as a Pug syntax definition is missing
14+</template>
15+
1116<script>
1217import AppHeader from "@/components/AppHeader";
1318import AppLoadingIndicator from "@/components/AppLoadingIndicator";
tests/syntax-tests/source/cmd-help/test.cmd-helpnew file+54
@@ -0,0 +1,54 @@
1+bat 0.20.0 (e735562-modified)
2+A cat(1) clone with syntax highlighting and Git integration.
3+
4+USAGE:
5+ bat [OPTIONS] [FILE]...
6+ bat <SUBCOMMAND>
7+
8+OPTIONS:
9+ -A, --show-all
10+ Show non-printable characters (space, tab, newline, ..).
11+
12+ -p, --plain Show plain style (alias for '--style=plain').
13+ -l, --language <language> Set the language for syntax highlighting.
14+ -H, --highlight-line <N:M>... Highlight lines N through M.
15+ --file-name <name>... Specify the name to display for a file.
16+ -d, --diff
17+ Only show lines that have been added/removed/modified.
18+
19+ --tabs <T> Set the tab width to T spaces.
20+ --wrap <mode>
21+ Specify the text-wrapping mode (*auto*, never, character).
22+
23+ -n, --number
24+ Show line numbers (alias for '--style=numbers').
25+
26+ --color <when> When to use colors (*auto*, never, always).
27+ --italic-text <when> Use italics in output (always, *never*)
28+ --decorations <when>
29+ When to show the decorations (*auto*, never, always).
30+
31+ --paging <when>
32+ Specify when to use the pager, or use `-P` to disable (*auto*, never,
33+ always).
34+ -m, --map-syntax <glob:syntax>...
35+ Use the specified syntax for files matching the glob pattern
36+ ('*.cpp:C++').
37+ --theme <theme> Set the color theme for syntax highlighting.
38+ --list-themes Display all supported highlighting themes.
39+ --style <components>
40+ Comma-separated list of style elements to display (*auto*, full, plain,
41+ changes, header, grid, rule, numbers, snip).
42+ -r, --line-range <N:M>... Only print the lines from N to M.
43+ -L, --list-languages Display all supported languages.
44+ -h, --help Print this help message.
45+ -V, --version Show version information.
46+
47+ARGS:
48+ <FILE>... File(s) to print / concatenate. Use '-' for standard input.
49+
50+SUBCOMMANDS:
51+ cache Modify the syntax-definition and theme cache
52+
53+Note: `bat -h` prints a short and concise overview while `bat --help` gives all
54+details.