on master help sign in
61 files changed+1078−187
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+66−3 CONTRIBUTING.md+22 Cargo.lock+75−54 Cargo.toml+11−12 README.md+19−1 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/INI.sublime-syntax+2−2 assets/syntaxes/02_Extra/Nginx+1−1 assets/syntaxes/02_Extra/SublimeJQ+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 rustfmt.toml+1 src/assets.rs+71−4 src/bin/bat/app.rs+1−1 src/bin/bat/clap_app.rs+5−3 src/bin/bat/config.rs+1−1 src/bin/bat/main.rs+11 src/error.rs+4−1 src/input.rs+1−1 src/less.rs+59−8 src/output.rs+7−5 src/preprocessor.rs+10−3 src/pretty_printer.rs+6 src/printer.rs+23−2 src/style.rs+11−1 src/syntax_mapping.rs+24−2 tests/examples/git/.config/git/config+3 tests/examples/git/.gitconfig+3 tests/examples/longline.json+3 tests/integration_tests.rs+185−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+66−3
@@ -2,24 +2,87 @@
22
33## Features
44
5−- New style component `header-filesize` to show size of the displayed file in the header. See #1988 (@mdibaiee)
5+- Make the default macOS theme depend on Dark Mode. See #2197, #1746 (@Enselic)
6+
7+## Bugfixes
8+
9+## Other
10+
11+- Relaxed glibc requirements on amd64, see #2106 and #2194 (@sharkdp)
12+
13+## Syntaxes
14+
15+## Themes
16+
17+## `bat` as a library
18+
19+
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)
628
729## Bugfixes
830
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+
939## Other
1040
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+
1172## Syntaxes
1273
1374- `GraphQL`: Add support for interfaces implementing interfaces and consider ampersand an operator. See #2000
1475- Associate `_vimrc` and `_gvimrc` files with the `VimL` syntax. See #2002
1576- Associate `poetry.lock` files with the `TOML` syntax. See #2049
1677- Associate `.mesh`, `.task`, `.rgen`, `.rint`, `.rahit`, `.rchit`, `.rmiss`, and `.rcall` with the `GLSL` syntax. See #2050
17−
18−## Themes
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)
1980
2081## `bat` as a library
2182
2283- 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+
2386
2487# v0.19.0
2588
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+75−54
@@ -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",
@@ -155,9 +155,9 @@ dependencies = [
155155
156156[[package]]
157157name = "bugreport"
158−version = "0.4.1"
158+version = "0.5.0"
159159source = "registry+https://github.com/rust-lang/crates.io-index"
160−checksum = "0014b4b2b4f63bfe69c3838470121290cc437fdc79785d408a761a21e8b2404c"
160+checksum = "535120b8182547808081a66f1f77a64533c780b23da26763e0ee34dfb94f98c9"
161161dependencies = [
162162 "git-version",
163163 "shell-escape",
@@ -382,9 +382,9 @@ dependencies = [
382382
383383[[package]]
384384name = "flate2"
385−version = "1.0.22"
385+version = "1.0.23"
386386source = "registry+https://github.com/rust-lang/crates.io-index"
387−checksum = "1e6988e897c1c9c485f43b47a529cef42fde0547f9d8d41a7062518f1d8fc53f"
387+checksum = "b39522e96686d38f4bc984b9198e3a0613264abaebaff2c5c918bfa6b6da09af"
388388dependencies = [
389389 "cfg-if",
390390 "crc32fast",
@@ -452,9 +452,9 @@ dependencies = [
452452
453453[[package]]
454454name = "git2"
455−version = "0.13.25"
455+version = "0.14.2"
456456source = "registry+https://github.com/rust-lang/crates.io-index"
457−checksum = "f29229cc1b24c0e6062f6e742aa3e256492a5323365e5ed3413599f8a5eff7d6"
457+checksum = "3826a6e0e2215d7a41c2bfc7c9244123969273f3476b939a226aac0ab56e9e3c"
458458dependencies = [
459459 "bitflags",
460460 "libc",
@@ -580,23 +580,17 @@ version = "1.4.0"
580580source = "registry+https://github.com/rust-lang/crates.io-index"
581581checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
582582
583−[[package]]
584−name = "lazycell"
585−version = "1.3.0"
586−source = "registry+https://github.com/rust-lang/crates.io-index"
587−checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
588−
589583[[package]]
590584name = "libc"
591−version = "0.2.112"
585+version = "0.2.125"
592586source = "registry+https://github.com/rust-lang/crates.io-index"
593−checksum = "1b03d17f364a3a042d5e5d46b053bbbf82c92c9430c592dd4c064dc6ee997125"
587+checksum = "5916d2ae698f6de9bfb891ad7a8d65c09d232dc58cc4ac433c7da3b2fd84bc2b"
594588
595589[[package]]
596590name = "libgit2-sys"
597−version = "0.12.26+1.3.0"
591+version = "0.13.2+1.4.2"
598592source = "registry+https://github.com/rust-lang/crates.io-index"
599−checksum = "19e1c899248e606fbfe68dcb31d8b0176ebab833b103824af31bddf4b7457494"
593+checksum = "3a42de9a51a5c12e00fc0e4ca6bc2ea43582fc6418488e8f615e905d886f258b"
600594dependencies = [
601595 "cc",
602596 "libc",
@@ -661,36 +655,24 @@ version = "2.4.1"
661655source = "registry+https://github.com/rust-lang/crates.io-index"
662656checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a"
663657
664−[[package]]
665−name = "memoffset"
666−version = "0.6.5"
667−source = "registry+https://github.com/rust-lang/crates.io-index"
668−checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce"
669−dependencies = [
670− "autocfg",
671−]
672−
673658[[package]]
674659name = "miniz_oxide"
675−version = "0.4.4"
660+version = "0.5.1"
676661source = "registry+https://github.com/rust-lang/crates.io-index"
677−checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b"
662+checksum = "d2b29bd4bc3f33391105ebee3589c19197c4271e3e5a9ec9bfe8127eeff8f082"
678663dependencies = [
679664 "adler",
680− "autocfg",
681665]
682666
683667[[package]]
684668name = "nix"
685−version = "0.23.1"
669+version = "0.24.1"
686670source = "registry+https://github.com/rust-lang/crates.io-index"
687−checksum = "9f866317acbd3a240710c63f065ffb1e4fd466259045ccb504130b7f668f35c6"
671+checksum = "8f17df307904acd05aa8e32e97bb20f2a0df1728bbc2d771ae8f9a90463441e9"
688672dependencies = [
689673 "bitflags",
690− "cc",
691674 "cfg-if",
692675 "libc",
693− "memoffset",
694676]
695677
696678[[package]]
@@ -710,9 +692,9 @@ dependencies = [
710692
711693[[package]]
712694name = "once_cell"
713−version = "1.9.0"
695+version = "1.10.0"
714696source = "registry+https://github.com/rust-lang/crates.io-index"
715−checksum = "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5"
697+checksum = "87f3e037eac156d1775da914196f0f37741a274155e34a0b7e427c35d2a2ecb9"
716698
717699[[package]]
718700name = "onig"
@@ -798,9 +780,9 @@ dependencies = [
798780
799781[[package]]
800782name = "predicates"
801−version = "2.1.0"
783+version = "2.1.1"
802784source = "registry+https://github.com/rust-lang/crates.io-index"
803−checksum = "95e5a7689e456ab905c22c2b48225bb921aba7c8dfa58440d68ba13f6222a715"
785+checksum = "a5aab5be6e4732b473071984b3164dbbfb7a3674d30ea5ff44410b6bcd960c3c"
804786dependencies = [
805787 "difflib",
806788 "float-cmp",
@@ -826,6 +808,30 @@ dependencies = [
826808 "termtree",
827809]
828810
811+[[package]]
812+name = "proc-macro-error"
813+version = "1.0.4"
814+source = "registry+https://github.com/rust-lang/crates.io-index"
815+checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
816+dependencies = [
817+ "proc-macro-error-attr",
818+ "proc-macro2",
819+ "quote",
820+ "syn",
821+ "version_check",
822+]
823+
824+[[package]]
825+name = "proc-macro-error-attr"
826+version = "1.0.4"
827+source = "registry+https://github.com/rust-lang/crates.io-index"
828+checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
829+dependencies = [
830+ "proc-macro2",
831+ "quote",
832+ "version_check",
833+]
834+
829835[[package]]
830836name = "proc-macro-hack"
831837version = "0.5.19"
@@ -871,9 +877,9 @@ dependencies = [
871877
872878[[package]]
873879name = "regex"
874−version = "1.5.4"
880+version = "1.5.5"
875881source = "registry+https://github.com/rust-lang/crates.io-index"
876−checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461"
882+checksum = "1a11647b6b25ff05a515cb92c365cec08801e83423a235b51e231e1808747286"
877883dependencies = [
878884 "aho-corasick",
879885 "memchr",
@@ -910,6 +916,12 @@ dependencies = [
910916 "bytemuck",
911917]
912918
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+
913925[[package]]
914926name = "ryu"
915927version = "1.0.9"
@@ -939,9 +951,9 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
939951
940952[[package]]
941953name = "semver"
942−version = "1.0.4"
954+version = "1.0.7"
943955source = "registry+https://github.com/rust-lang/crates.io-index"
944−checksum = "568a8e6258aa33c13358f81fd834adb854c6f7c9468520910a9b1e8fac068012"
956+checksum = "d65bd28f48be7196d222d95b9243287f48d27aca604e08497513019ff0502cc4"
945957
946958[[package]]
947959name = "serde"
@@ -988,9 +1000,9 @@ dependencies = [
9881000
9891001[[package]]
9901002name = "serial_test"
991−version = "0.5.1"
1003+version = "0.6.0"
9921004source = "registry+https://github.com/rust-lang/crates.io-index"
993−checksum = "e0bccbcf40c8938196944a3da0e133e031a33f4d6b72db3bda3cc556e361905d"
1005+checksum = "e5bcc41d18f7a1d50525d080fd3e953be87c4f9f1a974f3c21798ca00d54ec15"
9941006dependencies = [
9951007 "lazy_static",
9961008 "parking_lot",
@@ -999,12 +1011,14 @@ dependencies = [
9991011
10001012[[package]]
10011013name = "serial_test_derive"
1002−version = "0.5.1"
1014+version = "0.6.0"
10031015source = "registry+https://github.com/rust-lang/crates.io-index"
1004−checksum = "b2acd6defeddb41eb60bb468f8825d0cfd0c2a76bc03bfd235b6a1dc4f6a1ad5"
1016+checksum = "2881bccd7d60fb32dfa3d7b3136385312f8ad75e2674aab2852867a09790cae8"
10051017dependencies = [
1018+ "proc-macro-error",
10061019 "proc-macro2",
10071020 "quote",
1021+ "rustversion",
10081022 "syn",
10091023]
10101024
@@ -1016,9 +1030,9 @@ checksum = "45bb67a18fa91266cc7807181f62f9178a6873bfad7dc788c42e6430db40184f"
10161030
10171031[[package]]
10181032name = "shell-words"
1019−version = "1.0.0"
1033+version = "1.1.0"
10201034source = "registry+https://github.com/rust-lang/crates.io-index"
1021−checksum = "b6fa3938c99da4914afedd13bf3d79bcb6c277d1b2c398d23257a304d9e1b074"
1035+checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde"
10221036
10231037[[package]]
10241038name = "smallvec"
@@ -1051,9 +1065,9 @@ dependencies = [
10511065
10521066[[package]]
10531067name = "syntect"
1054−version = "4.6.0"
1068+version = "5.0.0"
10551069source = "registry+https://github.com/rust-lang/crates.io-index"
1056−checksum = "8b20815bbe80ee0be06e6957450a841185fcf690fe0178f14d77a05ce2caa031"
1070+checksum = "c6c454c27d9d7d9a84c7803aaa3c50cd088d2906fe3c6e42da3209aa623576a8"
10571071dependencies = [
10581072 "bincode",
10591073 "bitflags",
@@ -1061,13 +1075,14 @@ dependencies = [
10611075 "flate2",
10621076 "fnv",
10631077 "lazy_static",
1064− "lazycell",
1078+ "once_cell",
10651079 "onig",
10661080 "plist",
10671081 "regex-syntax",
10681082 "serde",
10691083 "serde_derive",
10701084 "serde_json",
1085+ "thiserror",
10711086 "walkdir",
10721087 "yaml-rust",
10731088]
@@ -1143,18 +1158,18 @@ dependencies = [
11431158
11441159[[package]]
11451160name = "thiserror"
1146−version = "1.0.30"
1161+version = "1.0.31"
11471162source = "registry+https://github.com/rust-lang/crates.io-index"
1148−checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417"
1163+checksum = "bd829fe32373d27f76265620b5309d0340cb8550f523c1dda251d6298069069a"
11491164dependencies = [
11501165 "thiserror-impl",
11511166]
11521167
11531168[[package]]
11541169name = "thiserror-impl"
1155−version = "1.0.30"
1170+version = "1.0.31"
11561171source = "registry+https://github.com/rust-lang/crates.io-index"
1157−checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b"
1172+checksum = "0396bc89e626244658bef819e22d0cc459e795a5ebe878e6ec336d1674a8d79a"
11581173dependencies = [
11591174 "proc-macro2",
11601175 "quote",
@@ -1237,6 +1252,12 @@ version = "0.8.2"
12371252source = "registry+https://github.com/rust-lang/crates.io-index"
12381253checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
12391254
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+
12401261[[package]]
12411262name = "wait-timeout"
12421263version = "0.2.0"
Cargo.toml+11−12
@@ -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
@@ -47,12 +46,12 @@ 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,20 +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 }
6867bytesize = { version = "1.1.0" }
6968
7069[dependencies.git2]
71−version = "0.13"
70+version = "0.14"
7271optional = true
7372default-features = false
7473
7574[dependencies.syntect]
76−version = "4.6.0"
75+version = "5.0.0"
7776default-features = false
7877features = ["parsing"]
7978
@@ -85,13 +84,13 @@ features = ["suggestions", "color", "wrap_help"]
8584
8685[dev-dependencies]
8786assert_cmd = "2.0.4"
88−serial_test = "0.5.1"
89−predicates = "2.1.0"
87+serial_test = "0.6.0"
88+predicates = "2.1.1"
9089wait-timeout = "0.2.0"
9190tempfile = "3.3.0"
9291
9392[target.'cfg(unix)'.dev-dependencies]
94−nix = "0.23.1"
93+nix = { version = "0.24.1", default-features = false, features = ["term"] }
9594
9695[build-dependencies]
9796clap = { version = "2.34", optional = true }
README.md+19−1
@@ -171,7 +171,7 @@ You can combine `bat` with `git diff` to view lines around code changes with pro
171171highlighting:
172172```bash
173173batdiff() {
174− git diff --name-only --diff-filter=d | xargs bat --diff
174+ git diff --name-only --relative --diff-filter=d | xargs bat --diff
175175}
176176```
177177If you prefer to use this as a separate tool, check out `batdiff` in [`bat-extras`](https://github.com/eth-p/bat-extras).
@@ -212,6 +212,24 @@ Also, note that this will [not work](https://github.com/sharkdp/bat/issues/1145)
212212
213213The [`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`.
214214
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+
215233
216234## Installation
217235
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/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/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+```
rustfmt.toml+1
@@ -0,0 +1 @@
1+# Defaults are used
src/assets.rs+71−4
@@ -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")),
@@ -351,6 +399,16 @@ fn asset_from_cache<T: serde::de::DeserializeOwned>(
351399 .map_err(|_| format!("Could not parse cached {}", description).into())
352400}
353401
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+
354412#[cfg(test)]
355413mod tests {
356414 use super::*;
@@ -581,13 +639,22 @@ mod tests {
581639 }
582640
583641 #[test]
584− fn syntax_detection_is_case_sensitive() {
642+ fn syntax_detection_is_case_insensitive() {
585643 let mut test = SyntaxDetectionTest::new();
586644
587− 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
588651 test.syntax_mapping
589652 .insert("*.MD", MappingTarget::MapTo("Markdown"))
590653 .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");
591658 assert_eq!(test.syntax_for_file("README.MD"), "Markdown");
592659 }
593660
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+5−3
@@ -398,6 +398,7 @@ pub fn build_app(interactive_output: bool) -> ClapApp<'static, 'static> {
398398 !&[
399399 "auto",
400400 "full",
401+ "default",
401402 "plain",
402403 "header",
403404 "header-filename",
@@ -419,7 +420,7 @@ pub fn build_app(interactive_output: bool) -> ClapApp<'static, 'static> {
419420 })
420421 .help(
421422 "Comma-separated list of style elements to display \
422− (*auto*, full, plain, changes, header, grid, rule, numbers, snip).",
423+ (*default*, auto, full, plain, changes, header, header-filename, header-filesize, grid, rule, numbers, snip).",
423424 )
424425 .long_help(
425426 "Configure which elements (line numbers, file headers, grid \
@@ -430,8 +431,9 @@ pub fn build_app(interactive_output: bool) -> ClapApp<'static, 'static> {
430431 '--style=\"..\"' option to the configuration file or export the \
431432 BAT_STYLE environment variable (e.g.: export BAT_STYLE=\"..\").\n\n\
432433 Possible values:\n\n \
433− * full: enables all available components (default).\n \
434− * 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 \
435437 * plain: disables all available components.\n \
436438 * changes: show Git modification markers.\n \
437439 * header: alias for 'header-filename'.\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+1−1
@@ -118,7 +118,7 @@ impl OpenedInput<'_> {
118118 self.metadata
119119 .user_provided_name
120120 .as_ref()
121− .or_else(|| match self.kind {
121+ .or(match self.kind {
122122 OpenedInputKind::OrdinaryFile(ref path) => Some(path),
123123 _ => None,
124124 })
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+23−2
@@ -445,9 +445,21 @@ impl<'a> Printer for InteractivePrinter<'a> {
445445 return Ok(());
446446 }
447447 };
448− 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
449455 .highlighter
450− .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
451463 };
452464
453465 if out_of_range {
@@ -463,6 +475,10 @@ impl<'a> Printer for InteractivePrinter<'a> {
463475 let highlight_this_line =
464476 self.config.highlighted_lines.0.check(line_number) == RangeCheckResult::InRange;
465477
478+ if highlight_this_line && self.config.theme == "ansi" {
479+ self.ansi_style.update("^[4m");
480+ }
481+
466482 let background_color = self
467483 .background_color_highlight
468484 .filter(|_| highlight_this_line);
@@ -649,6 +665,11 @@ impl<'a> Printer for InteractivePrinter<'a> {
649665 writeln!(handle)?;
650666 }
651667
668+ if highlight_this_line && self.config.theme == "ansi" {
669+ self.ansi_style.update("^[24m");
670+ write!(handle, "\x1B[24m")?;
671+ }
672+
652673 Ok(())
653674 }
654675}
src/style.rs+11−1
@@ -17,6 +17,7 @@ pub enum StyleComponent {
1717 LineNumbers,
1818 Snip,
1919 Full,
20+ Default,
2021 Plain,
2122}
2223
@@ -25,7 +26,7 @@ impl StyleComponent {
2526 match self {
2627 StyleComponent::Auto => {
2728 if interactive_terminal {
28− StyleComponent::Full.components(interactive_terminal)
29+ StyleComponent::Default.components(interactive_terminal)
2930 } else {
3031 StyleComponent::Plain.components(interactive_terminal)
3132 }
@@ -48,6 +49,14 @@ impl StyleComponent {
4849 StyleComponent::LineNumbers,
4950 StyleComponent::Snip,
5051 ],
52+ StyleComponent::Default => &[
53+ #[cfg(feature = "git")]
54+ StyleComponent::Changes,
55+ StyleComponent::Grid,
56+ StyleComponent::HeaderFilename,
57+ StyleComponent::LineNumbers,
58+ StyleComponent::Snip,
59+ ],
5160 StyleComponent::Plain => &[],
5261 }
5362 }
@@ -69,6 +78,7 @@ impl FromStr for StyleComponent {
6978 "numbers" => Ok(StyleComponent::LineNumbers),
7079 "snip" => Ok(StyleComponent::Snip),
7180 "full" => Ok(StyleComponent::Full),
81+ "default" => Ok(StyleComponent::Default),
7282 "plain" => Ok(StyleComponent::Plain),
7383 _ => Err(format!("Unknown style '{}'", s).into()),
7484 }
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/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+185−1
@@ -974,6 +974,53 @@ fn header_full_binary() {
974974 .stderr("");
975975}
976976
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+
9771024#[test]
9781025fn filename_stdin() {
9791026 bat()
@@ -1117,7 +1164,9 @@ Single Line
11171164────────────────────────────────────────────────────────────────────────────────
11181165",
11191166 )
1120− .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+ );
11211170}
11221171
11231172#[cfg(target_os = "linux")]
@@ -1215,6 +1264,52 @@ fn show_all_mode() {
12151264 .stderr("");
12161265}
12171266
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+
12181313#[test]
12191314fn no_paging_arg() {
12201315 bat()
@@ -1290,6 +1385,25 @@ fn grid_for_file_without_newline() {
12901385 .stderr("");
12911386}
12921387
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+
12931407// Ensure that ANSI passthrough is emitted properly for both wrapping and non-wrapping printer.
12941408#[test]
12951409fn ansi_passthrough_emit() {
@@ -1313,6 +1427,8 @@ fn ansi_passthrough_emit() {
13131427fn ignored_suffix_arg() {
13141428 bat()
13151429 .arg("-f")
1430+ .arg("--theme")
1431+ .arg("Monokai Extended")
13161432 .arg("-p")
13171433 .arg("test.json~")
13181434 .assert()
@@ -1322,6 +1438,8 @@ fn ignored_suffix_arg() {
13221438
13231439 bat()
13241440 .arg("-f")
1441+ .arg("--theme")
1442+ .arg("Monokai Extended")
13251443 .arg("-p")
13261444 .arg("--ignored-suffix=.suffix")
13271445 .arg("test.json.suffix")
@@ -1332,6 +1450,8 @@ fn ignored_suffix_arg() {
13321450
13331451 bat()
13341452 .arg("-f")
1453+ .arg("--theme")
1454+ .arg("Monokai Extended")
13351455 .arg("-p")
13361456 .arg("test.json.suffix")
13371457 .assert()
@@ -1340,6 +1460,70 @@ fn ignored_suffix_arg() {
13401460 .stderr("");
13411461}
13421462
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+
13431527#[test]
13441528fn acknowledgements() {
13451529 bat()
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.