on master help sign in
.github/ISSUE_TEMPLATE/bug_report.md+19−2
since splitsnapshots
unifiedsplit
@@ -7,9 +7,26 @@ assignees: ''
7
7
8---
8---
9
9
10+<!--
11+
10−<!-- Hey there, thank you for creating an issue! -->
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. ...
11
28
12−**Describe the bug you encountered:**
29+**What happens?**
13
30
14...
31...
15
32
.github/ISSUE_TEMPLATE/question.md+2
@@ -7,3 +7,5 @@ assignees: ''
7
7
8---
8---
9
9
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:
118 toolchain: stable
118 toolchain: stable
119 default: true
119 default: true
120 profile: minimal
120 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)
121 - name: Check documentation
133 - name: Check documentation
122 env:
134 env:
123 RUSTDOCFLAGS: -D warnings
135 RUSTDOCFLAGS: -D warnings
@@ -142,7 +154,7 @@ jobs:
142 - { target: x86_64-apple-darwin , os: macos-10.15 }
154 - { target: x86_64-apple-darwin , os: macos-10.15 }
143 - { target: x86_64-pc-windows-gnu , os: windows-2019 }
155 - { target: x86_64-pc-windows-gnu , os: windows-2019 }
144 - { target: x86_64-pc-windows-msvc , os: windows-2019 }
156 - { 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 }
146 - { target: x86_64-unknown-linux-musl , os: ubuntu-20.04, use-cross: true }
158 - { target: x86_64-unknown-linux-musl , os: ubuntu-20.04, use-cross: true }
147 steps:
159 steps:
148 - name: Checkout source code
160 - name: Checkout source code
.gitmodules+5
@@ -239,3 +239,8 @@
239[submodule "assets/syntaxes/02_Extra/SublimeJQ"]
239[submodule "assets/syntaxes/02_Extra/SublimeJQ"]
240 path = assets/syntaxes/02_Extra/SublimeJQ
240 path = assets/syntaxes/02_Extra/SublimeJQ
241 url = https://github.com/zogwarg/SublimeJQ.git
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+45
@@ -2,10 +2,14 @@
2
2
3## Features
3## Features
4
4
5+- Make the default macOS theme depend on Dark Mode. See #2197, #1746 (@Enselic)
6+
5## Bugfixes
7## Bugfixes
6
8
7## Other
9## Other
8
10
11+- Relaxed glibc requirements on amd64, see #2106 and #2194 (@sharkdp)
12+
9## Syntaxes
13## Syntaxes
10
14
11## Themes
15## Themes
@@ -13,6 +17,47 @@
13## `bat` as a library
17## `bat` as a library
14
18
15
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)
28+
29+## Bugfixes
30+
31+- Bump `regex` dependency from 1.5.4 to 1.5.5 to fix [CVE-2022-24713](https://blog.rust-lang.org/2022/03/08/cve-2022-24713.html), see #2145, #2139 (@Enselic)
32+- `bat` no longer crashes when encountering files that references missing syntaxes. See #915, #2181 (@Enselic)
33+
34+## Performance
35+
36+- Skip syntax highlighting on long lines (> 16384 chars) to help improve performance. See #2165 (@keith-hall)
37+- Vastly improve startup time by lazy-loading syntaxes via syntect 5.0.0. This makes bat display small files ~75% faster than before. See #951, #2181 (@Enselic)
38+
39+## Other
40+
41+- Include info about custom assets in `--diagnostics` if used. See #2107, #2144 (@Enselic)
42+
43+## Syntaxes
44+
45+- Mapped clang-format config file (.clang-format) to YAML syntax (@TruncatedDinosour)
46+- log syntax: improved handling of escape characters in double quoted strings. See #2123 (@keith-hall)
47+- Associate `/var/spool/mail/*` and `/var/mail/*` with the `Email` syntax. See #2156 (@cyqsimon)
48+- Added cmd-help syntax to scope --help messages. See #2148 (@victor-gp)
49+- Slightly adjust Zig syntax. See #2136 (@Enselic)
50+- Associate `.inf` files with the `INI` syntax. See #2190 (@Enselic)
51+
52+## `bat` as a library
53+
54+- Allow configuration of `show_nonprintable` with `PrettyPrinter`, see #2142
55+- The binary format of syntaxes.bin has been changed due to syntaxes now being lazy-loaded via syntect 5.0.0. See #2181 (@Enselic)
56+- Mark `bat::error::Error` enum as `#[non_exhaustive]` to allow adding new variants without future semver breakage. See #2181 (@Enselic)
57+- Change `Error::SyntectError(syntect::LoadingError)` to `Error::SyntectError(syntect::Error)`. See #2181 (@Enselic)
58+- Add `Error::SyntectLoadingError(syntect::LoadingError)` enum variant. See #2181 (@Enselic)
59+
60+
16# v0.20.0
61# v0.20.0
17
62
18## Features
63## Features
Cargo.lock+75−54
@@ -74,7 +74,7 @@ checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd"
74
74
75[[package]]
75[[package]]
76name = "bat"
76name = "bat"
77−version = "0.20.0"
77+version = "0.21.0"
78dependencies = [
78dependencies = [
79 "ansi_colours",
79 "ansi_colours",
80 "ansi_term",
80 "ansi_term",
@@ -155,9 +155,9 @@ dependencies = [
155
155
156[[package]]
156[[package]]
157name = "bugreport"
157name = "bugreport"
158−version = "0.4.1"
158+version = "0.5.0"
159source = "registry+https://github.com/rust-lang/crates.io-index"
159source = "registry+https://github.com/rust-lang/crates.io-index"
160−checksum = "0014b4b2b4f63bfe69c3838470121290cc437fdc79785d408a761a21e8b2404c"
160+checksum = "535120b8182547808081a66f1f77a64533c780b23da26763e0ee34dfb94f98c9"
161dependencies = [
161dependencies = [
162 "git-version",
162 "git-version",
163 "shell-escape",
163 "shell-escape",
@@ -382,9 +382,9 @@ dependencies = [
382
382
383[[package]]
383[[package]]
384name = "flate2"
384name = "flate2"
385−version = "1.0.22"
385+version = "1.0.23"
386source = "registry+https://github.com/rust-lang/crates.io-index"
386source = "registry+https://github.com/rust-lang/crates.io-index"
387−checksum = "1e6988e897c1c9c485f43b47a529cef42fde0547f9d8d41a7062518f1d8fc53f"
387+checksum = "b39522e96686d38f4bc984b9198e3a0613264abaebaff2c5c918bfa6b6da09af"
388dependencies = [
388dependencies = [
389 "cfg-if",
389 "cfg-if",
390 "crc32fast",
390 "crc32fast",
@@ -452,9 +452,9 @@ dependencies = [
452
452
453[[package]]
453[[package]]
454name = "git2"
454name = "git2"
455−version = "0.13.25"
455+version = "0.14.2"
456source = "registry+https://github.com/rust-lang/crates.io-index"
456source = "registry+https://github.com/rust-lang/crates.io-index"
457−checksum = "f29229cc1b24c0e6062f6e742aa3e256492a5323365e5ed3413599f8a5eff7d6"
457+checksum = "3826a6e0e2215d7a41c2bfc7c9244123969273f3476b939a226aac0ab56e9e3c"
458dependencies = [
458dependencies = [
459 "bitflags",
459 "bitflags",
460 "libc",
460 "libc",
@@ -580,23 +580,17 @@ version = "1.4.0"
580source = "registry+https://github.com/rust-lang/crates.io-index"
580source = "registry+https://github.com/rust-lang/crates.io-index"
581checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
581checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
582
582
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−
589[[package]]
583[[package]]
590name = "libc"
584name = "libc"
591−version = "0.2.112"
585+version = "0.2.125"
592source = "registry+https://github.com/rust-lang/crates.io-index"
586source = "registry+https://github.com/rust-lang/crates.io-index"
593−checksum = "1b03d17f364a3a042d5e5d46b053bbbf82c92c9430c592dd4c064dc6ee997125"
587+checksum = "5916d2ae698f6de9bfb891ad7a8d65c09d232dc58cc4ac433c7da3b2fd84bc2b"
594
588
595[[package]]
589[[package]]
596name = "libgit2-sys"
590name = "libgit2-sys"
597−version = "0.12.26+1.3.0"
591+version = "0.13.2+1.4.2"
598source = "registry+https://github.com/rust-lang/crates.io-index"
592source = "registry+https://github.com/rust-lang/crates.io-index"
599−checksum = "19e1c899248e606fbfe68dcb31d8b0176ebab833b103824af31bddf4b7457494"
593+checksum = "3a42de9a51a5c12e00fc0e4ca6bc2ea43582fc6418488e8f615e905d886f258b"
600dependencies = [
594dependencies = [
601 "cc",
595 "cc",
602 "libc",
596 "libc",
@@ -661,36 +655,24 @@ version = "2.4.1"
661source = "registry+https://github.com/rust-lang/crates.io-index"
655source = "registry+https://github.com/rust-lang/crates.io-index"
662checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a"
656checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a"
663
657
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−
673[[package]]
658[[package]]
674name = "miniz_oxide"
659name = "miniz_oxide"
675−version = "0.4.4"
660+version = "0.5.1"
676source = "registry+https://github.com/rust-lang/crates.io-index"
661source = "registry+https://github.com/rust-lang/crates.io-index"
677−checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b"
662+checksum = "d2b29bd4bc3f33391105ebee3589c19197c4271e3e5a9ec9bfe8127eeff8f082"
678dependencies = [
663dependencies = [
679 "adler",
664 "adler",
680− "autocfg",
681]
665]
682
666
683[[package]]
667[[package]]
684name = "nix"
668name = "nix"
685−version = "0.23.1"
669+version = "0.24.1"
686source = "registry+https://github.com/rust-lang/crates.io-index"
670source = "registry+https://github.com/rust-lang/crates.io-index"
687−checksum = "9f866317acbd3a240710c63f065ffb1e4fd466259045ccb504130b7f668f35c6"
671+checksum = "8f17df307904acd05aa8e32e97bb20f2a0df1728bbc2d771ae8f9a90463441e9"
688dependencies = [
672dependencies = [
689 "bitflags",
673 "bitflags",
690− "cc",
691 "cfg-if",
674 "cfg-if",
692 "libc",
675 "libc",
693− "memoffset",
694]
676]
695
677
696[[package]]
678[[package]]
@@ -710,9 +692,9 @@ dependencies = [
710
692
711[[package]]
693[[package]]
712name = "once_cell"
694name = "once_cell"
713−version = "1.9.0"
695+version = "1.10.0"
714source = "registry+https://github.com/rust-lang/crates.io-index"
696source = "registry+https://github.com/rust-lang/crates.io-index"
715−checksum = "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5"
697+checksum = "87f3e037eac156d1775da914196f0f37741a274155e34a0b7e427c35d2a2ecb9"
716
698
717[[package]]
699[[package]]
718name = "onig"
700name = "onig"
@@ -798,9 +780,9 @@ dependencies = [
798
780
799[[package]]
781[[package]]
800name = "predicates"
782name = "predicates"
801−version = "2.1.0"
783+version = "2.1.1"
802source = "registry+https://github.com/rust-lang/crates.io-index"
784source = "registry+https://github.com/rust-lang/crates.io-index"
803−checksum = "95e5a7689e456ab905c22c2b48225bb921aba7c8dfa58440d68ba13f6222a715"
785+checksum = "a5aab5be6e4732b473071984b3164dbbfb7a3674d30ea5ff44410b6bcd960c3c"
804dependencies = [
786dependencies = [
805 "difflib",
787 "difflib",
806 "float-cmp",
788 "float-cmp",
@@ -826,6 +808,30 @@ dependencies = [
826 "termtree",
808 "termtree",
827]
809]
828
810
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+
829[[package]]
835[[package]]
830name = "proc-macro-hack"
836name = "proc-macro-hack"
831version = "0.5.19"
837version = "0.5.19"
@@ -871,9 +877,9 @@ dependencies = [
871
877
872[[package]]
878[[package]]
873name = "regex"
879name = "regex"
874−version = "1.5.4"
880+version = "1.5.5"
875source = "registry+https://github.com/rust-lang/crates.io-index"
881source = "registry+https://github.com/rust-lang/crates.io-index"
876−checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461"
882+checksum = "1a11647b6b25ff05a515cb92c365cec08801e83423a235b51e231e1808747286"
877dependencies = [
883dependencies = [
878 "aho-corasick",
884 "aho-corasick",
879 "memchr",
885 "memchr",
@@ -910,6 +916,12 @@ dependencies = [
910 "bytemuck",
916 "bytemuck",
911]
917]
912
918
919+[[package]]
920+name = "rustversion"
921+version = "1.0.6"
922+source = "registry+https://github.com/rust-lang/crates.io-index"
923+checksum = "f2cc38e8fa666e2de3c4aba7edeb5ffc5246c1c2ed0e3d17e560aeeba736b23f"
924+
913[[package]]
925[[package]]
914name = "ryu"
926name = "ryu"
915version = "1.0.9"
927version = "1.0.9"
@@ -939,9 +951,9 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
939
951
940[[package]]
952[[package]]
941name = "semver"
953name = "semver"
942−version = "1.0.4"
954+version = "1.0.7"
943source = "registry+https://github.com/rust-lang/crates.io-index"
955source = "registry+https://github.com/rust-lang/crates.io-index"
944−checksum = "568a8e6258aa33c13358f81fd834adb854c6f7c9468520910a9b1e8fac068012"
956+checksum = "d65bd28f48be7196d222d95b9243287f48d27aca604e08497513019ff0502cc4"
945
957
946[[package]]
958[[package]]
947name = "serde"
959name = "serde"
@@ -988,9 +1000,9 @@ dependencies = [
988
1000
989[[package]]
1001[[package]]
990name = "serial_test"
1002name = "serial_test"
991−version = "0.5.1"
1003+version = "0.6.0"
992source = "registry+https://github.com/rust-lang/crates.io-index"
1004source = "registry+https://github.com/rust-lang/crates.io-index"
993−checksum = "e0bccbcf40c8938196944a3da0e133e031a33f4d6b72db3bda3cc556e361905d"
1005+checksum = "e5bcc41d18f7a1d50525d080fd3e953be87c4f9f1a974f3c21798ca00d54ec15"
994dependencies = [
1006dependencies = [
995 "lazy_static",
1007 "lazy_static",
996 "parking_lot",
1008 "parking_lot",
@@ -999,12 +1011,14 @@ dependencies = [
999
1011
1000[[package]]
1012[[package]]
1001name = "serial_test_derive"
1013name = "serial_test_derive"
1002−version = "0.5.1"
1014+version = "0.6.0"
1003source = "registry+https://github.com/rust-lang/crates.io-index"
1015source = "registry+https://github.com/rust-lang/crates.io-index"
1004−checksum = "b2acd6defeddb41eb60bb468f8825d0cfd0c2a76bc03bfd235b6a1dc4f6a1ad5"
1016+checksum = "2881bccd7d60fb32dfa3d7b3136385312f8ad75e2674aab2852867a09790cae8"
1005dependencies = [
1017dependencies = [
1018+ "proc-macro-error",
1006 "proc-macro2",
1019 "proc-macro2",
1007 "quote",
1020 "quote",
1021+ "rustversion",
1008 "syn",
1022 "syn",
1009]
1023]
1010
1024
@@ -1016,9 +1030,9 @@ checksum = "45bb67a18fa91266cc7807181f62f9178a6873bfad7dc788c42e6430db40184f"
1016
1030
1017[[package]]
1031[[package]]
1018name = "shell-words"
1032name = "shell-words"
1019−version = "1.0.0"
1033+version = "1.1.0"
1020source = "registry+https://github.com/rust-lang/crates.io-index"
1034source = "registry+https://github.com/rust-lang/crates.io-index"
1021−checksum = "b6fa3938c99da4914afedd13bf3d79bcb6c277d1b2c398d23257a304d9e1b074"
1035+checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde"
1022
1036
1023[[package]]
1037[[package]]
1024name = "smallvec"
1038name = "smallvec"
@@ -1051,9 +1065,9 @@ dependencies = [
1051
1065
1052[[package]]
1066[[package]]
1053name = "syntect"
1067name = "syntect"
1054−version = "4.6.0"
1068+version = "5.0.0"
1055source = "registry+https://github.com/rust-lang/crates.io-index"
1069source = "registry+https://github.com/rust-lang/crates.io-index"
1056−checksum = "8b20815bbe80ee0be06e6957450a841185fcf690fe0178f14d77a05ce2caa031"
1070+checksum = "c6c454c27d9d7d9a84c7803aaa3c50cd088d2906fe3c6e42da3209aa623576a8"
1057dependencies = [
1071dependencies = [
1058 "bincode",
1072 "bincode",
1059 "bitflags",
1073 "bitflags",
@@ -1061,13 +1075,14 @@ dependencies = [
1061 "flate2",
1075 "flate2",
1062 "fnv",
1076 "fnv",
1063 "lazy_static",
1077 "lazy_static",
1064− "lazycell",
1078+ "once_cell",
1065 "onig",
1079 "onig",
1066 "plist",
1080 "plist",
1067 "regex-syntax",
1081 "regex-syntax",
1068 "serde",
1082 "serde",
1069 "serde_derive",
1083 "serde_derive",
1070 "serde_json",
1084 "serde_json",
1085+ "thiserror",
1071 "walkdir",
1086 "walkdir",
1072 "yaml-rust",
1087 "yaml-rust",
1073]
1088]
@@ -1143,18 +1158,18 @@ dependencies = [
1143
1158
1144[[package]]
1159[[package]]
1145name = "thiserror"
1160name = "thiserror"
1146−version = "1.0.30"
1161+version = "1.0.31"
1147source = "registry+https://github.com/rust-lang/crates.io-index"
1162source = "registry+https://github.com/rust-lang/crates.io-index"
1148−checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417"
1163+checksum = "bd829fe32373d27f76265620b5309d0340cb8550f523c1dda251d6298069069a"
1149dependencies = [
1164dependencies = [
1150 "thiserror-impl",
1165 "thiserror-impl",
1151]
1166]
1152
1167
1153[[package]]
1168[[package]]
1154name = "thiserror-impl"
1169name = "thiserror-impl"
1155−version = "1.0.30"
1170+version = "1.0.31"
1156source = "registry+https://github.com/rust-lang/crates.io-index"
1171source = "registry+https://github.com/rust-lang/crates.io-index"
1157−checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b"
1172+checksum = "0396bc89e626244658bef819e22d0cc459e795a5ebe878e6ec336d1674a8d79a"
1158dependencies = [
1173dependencies = [
1159 "proc-macro2",
1174 "proc-macro2",
1160 "quote",
1175 "quote",
@@ -1237,6 +1252,12 @@ version = "0.8.2"
1237source = "registry+https://github.com/rust-lang/crates.io-index"
1252source = "registry+https://github.com/rust-lang/crates.io-index"
1238checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
1253checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
1239
1254
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+
1240[[package]]
1261[[package]]
1241name = "wait-timeout"
1262name = "wait-timeout"
1242version = "0.2.0"
1263version = "0.2.0"
Cargo.toml+11−12
@@ -6,7 +6,7 @@ homepage = "https://github.com/sharkdp/bat"
6license = "MIT/Apache-2.0"
6license = "MIT/Apache-2.0"
7name = "bat"
7name = "bat"
8repository = "https://github.com/sharkdp/bat"
8repository = "https://github.com/sharkdp/bat"
9−version = "0.20.0"
9+version = "0.21.0"
10exclude = ["assets/syntaxes/*", "assets/themes/*"]
10exclude = ["assets/syntaxes/*", "assets/themes/*"]
11build = "build.rs"
11build = "build.rs"
12edition = '2018'
12edition = '2018'
@@ -33,8 +33,7 @@ minimal-application = [
33]
33]
34git = ["git2"] # Support indicating git modifications
34git = ["git2"] # Support indicating git modifications
35paging = ["shell-words", "grep-cli"] # Support applying a pager on the output
35paging = ["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"]
38
37
39# You need to use one of these if you depend on bat as a library:
38# You need to use one of these if you depend on bat as a library:
40regex-onig = ["syntect/regex-onig"] # Use the "oniguruma" regex engine
39regex-onig = ["syntect/regex-onig"] # Use the "oniguruma" regex engine
@@ -47,12 +46,12 @@ ansi_colours = "^1.1"
47bincode = "1.0"
46bincode = "1.0"
48console = "0.15.0"
47console = "0.15.0"
49flate2 = "1.0"
48flate2 = "1.0"
50−once_cell = "1.9"
49+once_cell = "1.10"
51thiserror = "1.0"
50thiserror = "1.0"
52wild = { version = "2.0", optional = true }
51wild = { version = "2.0", optional = true }
53content_inspector = "0.2.4"
52content_inspector = "0.2.4"
54encoding = "0.2"
53encoding = "0.2"
55−shell-words = { version = "1.0.0", optional = true }
54+shell-words = { version = "1.1.0", optional = true }
56unicode-width = "0.1.9"
55unicode-width = "0.1.9"
57globset = "0.4"
56globset = "0.4"
58serde = { version = "1.0", features = ["derive"] }
57serde = { version = "1.0", features = ["derive"] }
@@ -60,20 +59,20 @@ serde_yaml = "0.8"
60semver = "1.0"
59semver = "1.0"
61path_abs = { version = "0.5", default-features = false }
60path_abs = { version = "0.5", default-features = false }
62clircle = "0.3"
61clircle = "0.3"
63−bugreport = { version = "0.4", optional = true }
62+bugreport = { version = "0.5.0", optional = true }
64dirs-next = { version = "2.0.0", optional = true }
63dirs-next = { version = "2.0.0", optional = true }
65grep-cli = { version = "0.1.6", optional = true }
64grep-cli = { version = "0.1.6", optional = true }
66−regex = { version = "1.0", optional = true }
65+regex = { version = "1.5.5", optional = true }
67walkdir = { version = "2.0", optional = true }
66walkdir = { version = "2.0", optional = true }
68bytesize = { version = "1.1.0" }
67bytesize = { version = "1.1.0" }
69
68
70[dependencies.git2]
69[dependencies.git2]
71−version = "0.13"
70+version = "0.14"
72optional = true
71optional = true
73default-features = false
72default-features = false
74
73
75[dependencies.syntect]
74[dependencies.syntect]
76−version = "4.6.0"
75+version = "5.0.0"
77default-features = false
76default-features = false
78features = ["parsing"]
77features = ["parsing"]
79
78
@@ -85,13 +84,13 @@ features = ["suggestions", "color", "wrap_help"]
85
84
86[dev-dependencies]
85[dev-dependencies]
87assert_cmd = "2.0.4"
86assert_cmd = "2.0.4"
88−serial_test = "0.5.1"
87+serial_test = "0.6.0"
89−predicates = "2.1.0"
88+predicates = "2.1.1"
90wait-timeout = "0.2.0"
89wait-timeout = "0.2.0"
91tempfile = "3.3.0"
90tempfile = "3.3.0"
92
91
93[target.'cfg(unix)'.dev-dependencies]
92[target.'cfg(unix)'.dev-dependencies]
94−nix = "0.23.1"
93+nix = { version = "0.24.1", default-features = false, features = ["term"] }
95
94
96[build-dependencies]
95[build-dependencies]
97clap = { version = "2.34", optional = true }
96clap = { 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
171highlighting:
171highlighting:
172```bash
172```bash
173batdiff() {
173batdiff() {
174− git diff --name-only --diff-filter=d | xargs bat --diff
174+ git diff --name-only --relative --diff-filter=d | xargs bat --diff
175}
175}
176```
176```
177If you prefer to use this as a separate tool, check out `batdiff` in [`bat-extras`](https://github.com/eth-p/bat-extras).
177If 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)
212
212
213The [`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`.
213The [`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`.
214
214
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+
215
233
216## Installation
234## Installation
217
235
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
37 [CompletionResult]::new('-m', 'm', [CompletionResultType]::ParameterName, 'Use the specified syntax for files matching the glob pattern (''*.cpp:C++'').')
37 [CompletionResult]::new('-m', 'm', [CompletionResultType]::ParameterName, 'Use the specified syntax for files matching the glob pattern (''*.cpp:C++'').')
38 [CompletionResult]::new('--map-syntax', 'map-syntax', [CompletionResultType]::ParameterName, 'Use the specified syntax for files matching the glob pattern (''*.cpp:C++'').')
38 [CompletionResult]::new('--map-syntax', 'map-syntax', [CompletionResultType]::ParameterName, 'Use the specified syntax for files matching the glob pattern (''*.cpp:C++'').')
39 [CompletionResult]::new('--theme', 'theme', [CompletionResultType]::ParameterName, 'Set the color theme for syntax highlighting.')
39 [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, header-filename, header-filesize, 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).')
41 [CompletionResult]::new('-r', 'r', [CompletionResultType]::ParameterName, 'Only print the lines from N to M.')
41 [CompletionResult]::new('-r', 'r', [CompletionResultType]::ParameterName, 'Only print the lines from N to M.')
42 [CompletionResult]::new('--line-range', 'line-range', [CompletionResultType]::ParameterName, 'Only print the lines from N to M.')
42 [CompletionResult]::new('--line-range', 'line-range', [CompletionResultType]::ParameterName, 'Only print the lines from N to M.')
43 [CompletionResult]::new('-A', 'A', [CompletionResultType]::ParameterName, 'Show non-printable characters (space, tab, newline, ..).')
43 [CompletionResult]::new('-A', 'A', [CompletionResultType]::ParameterName, 'Show non-printable characters (space, tab, newline, ..).')
assets/completions/bat.fish.in+1−1
@@ -56,7 +56,7 @@ complete -c {{PROJECT_EXECUTABLE}} -s P -d "Disable paging. Alias for '--paging=
56
56
57complete -c {{PROJECT_EXECUTABLE}} -s A -l show-all -d "Show non-printable characters like space/tab/newline" -n "not __fish_seen_subcommand_from cache"
57complete -c {{PROJECT_EXECUTABLE}} -s A -l show-all -d "Show non-printable characters like space/tab/newline" -n "not __fish_seen_subcommand_from cache"
58
58
59−complete -c {{PROJECT_EXECUTABLE}} -l style -xka "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"
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"
60
60
61complete -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"
61complete -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"
62
62
assets/completions/bat.zsh.in+1−1
@@ -75,7 +75,7 @@ _{{PROJECT_EXECUTABLE}}_main() {
75 ;;
75 ;;
76
76
77 style)
77 style)
78− _values -s , 'style' auto full plain changes header header-filename header-filesize grid rule numbers snip
78+ _values -s , 'style' default auto full plain changes header header-filename header-filesize grid rule numbers snip
79 ;;
79 ;;
80 esac
80 esac
81}
81}
assets/manual/bat.1.in+1−1
@@ -146,7 +146,7 @@ Configure which elements (line numbers, file headers, grid borders, Git modifica
146of components to display (e.g. 'numbers,changes,grid') or a pre\-defined style ('full').
146of components to display (e.g. 'numbers,changes,grid') or a pre\-defined style ('full').
147To set a default style, add the '\-\-style=".."' option to the configuration file or
147To set a default style, add the '\-\-style=".."' option to the configuration file or
148export the BAT_STYLE environment variable (e.g.: export BAT_STYLE=".."). Possible
148export the BAT_STYLE environment variable (e.g.: export BAT_STYLE=".."). Possible
149−values: *full*, auto, plain, changes, header, header-filename, header-filesize, grid,
149+values: *default*, full, auto, plain, changes, header, header-filename, header-filesize, grid,
150rule, numbers, snip.
150rule, numbers, snip.
151.HP
151.HP
152\fB\-r\fR, \fB\-\-line\-range\fR <N:M>...
152\fB\-r\fR, \fB\-\-line\-range\fR <N:M>...
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
5file_extensions:
5file_extensions:
6 - ini
6 - ini
7 - INI
7 - INI
8− - inf
8+ - "inf"
9− - INF
9+ - "INF"
10 - reg
10 - reg
11 - REG
11 - REG
12 - lng
12 - lng
assets/syntaxes/02_Extra/Nginx+1−1

Submodule changed.

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

Submodule changed.

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

Submodule changed.

assets/syntaxes/02_Extra/log.sublime-syntax+30−6
@@ -6,6 +6,7 @@ file_extensions:
6scope: text.log
6scope: text.log
7variables:
7variables:
8 ipv4_part: (?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)
8 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)
9contexts:
10contexts:
10 main:
11 main:
11 - match: (\w+)(=)
12 - match: (\w+)(=)
@@ -17,11 +18,10 @@ contexts:
17 captures:
18 captures:
18 1: punctuation.definition.string.begin.log
19 1: punctuation.definition.string.begin.log
19 3: punctuation.definition.string.end.log
20 3: punctuation.definition.string.end.log
20− - match: (")([^"]*)(")
21+ - match: \"
21− scope: string.quoted.double.log
22 captures:
22 captures:
23 1: punctuation.definition.string.begin.log
23 1: punctuation.definition.string.begin.log
24− 3: punctuation.definition.string.end.log
24+ push: double_quoted_string
25 - include: dates
25 - include: dates
26 - include: ip_addresses
26 - include: ip_addresses
27 - include: numbers
27 - include: numbers
@@ -29,19 +29,34 @@ contexts:
29 scope: markup.error.log
29 scope: markup.error.log
30 - match: \b(?i:warn(?:ing)?)\b
30 - match: \b(?i:warn(?:ing)?)\b
31 scope: markup.warning.log
31 scope: markup.warning.log
32+ - match: \b(?i:debug)\b
33+ scope: markup.info.log
32 #- include: scope:text.html.markdown#autolink-inet
34 #- include: scope:text.html.markdown#autolink-inet
33 - match: \b\w+:/{2,3}
35 - match: \b\w+:/{2,3}
34 scope: markup.underline.link.scheme.log
36 scope: markup.underline.link.scheme.log
35 push: url-host
37 push: url-host
36 dates:
38 dates:
37− - match: \b\d{4}-\d{2}-\d{2}\b
39+ - match: \b\d{4}-\d{2}-\d{2}(?=\b|T)
38 scope: meta.date.log meta.number.integer.decimal.log constant.numeric.value.log
40 scope: meta.date.log meta.number.integer.decimal.log constant.numeric.value.log
41+ push: maybe_date_time_separator
39− - match: \b\d{4}/\d{2}/\d{2}\b
42+ - match: \b\d{4}/\d{2}/\d{2}(?=\b|T)
40 scope: meta.date.log meta.number.integer.decimal.log constant.numeric.value.log
43 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
42 scope: meta.time.log meta.number.integer.decimal.log constant.numeric.value.log
49 scope: meta.time.log meta.number.integer.decimal.log constant.numeric.value.log
43 captures:
50 captures:
44 1: punctuation.separator.decimal.log
51 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
45 ip_addresses:
60 ip_addresses:
46 - match: \b(?=(?:{{ipv4_part}}\.){3}{{ipv4_part}}\b)
61 - match: \b(?=(?:{{ipv4_part}}\.){3}{{ipv4_part}}\b)
47 push:
62 push:
@@ -114,3 +129,12 @@ contexts:
114 scope: markup.underline.link.path.log
129 scope: markup.underline.link.path.log
115 - match: ''
130 - match: ''
116 pop: true
131 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/release-checklist.md+8−6
@@ -7,21 +7,22 @@
7- [ ] Find the current min. supported Rust version by running
7- [ ] Find the current min. supported Rust version by running
8 `grep '^\s*MIN_SUPPORTED_RUST_VERSION' .github/workflows/CICD.yml`.
8 `grep '^\s*MIN_SUPPORTED_RUST_VERSION' .github/workflows/CICD.yml`.
9- [ ] Update the version and the min. supported Rust version in `README.md` and
9- [ ] Update the version and the min. supported Rust version in `README.md` and
10− `doc/README-*.md`. Check with `git grep -i 'rust.*1\.'` and
10+ `doc/README-*.md`. Check with
11− `git grep -i '1\..*rust'`.
11+ `git grep -i -e 'rust.*1\.' -e '1\..*rust' | grep README | grep -v tests/`.
12- [ ] Update `CHANGELOG.md`. Introduce a section for the new release.
12- [ ] Update `CHANGELOG.md`. Introduce a section for the new release.
13
13
14## Update syntaxes and themes (build assets)
14## Update syntaxes and themes (build assets)
15
15
16−- [ ] Install the latest master version (`cargo clean && cargo install -f --path .`) and make
16+- [ ] Install the latest master version (`cargo clean && cargo install --locked -f --path .`) and make
17 sure that it is available on the `PATH` (`bat --version` should show the
17 sure that it is available on the `PATH` (`bat --version` should show the
18 new version).
18 new version).
19- [ ] Run `assets/create.sh` and check in the binary asset files.
19- [ ] Run `assets/create.sh` and check in the binary asset files.
20
20
21## Documentation
21## Documentation
22
22
23−- [ ] Review the `-h` and `--help` texts
23+- [ ] Review `-h`, `--help`, and the `man` page. All of these are shown in
24−- [ ] Review the `man` page (`man $(fd -HIp target/release/build.*out/assets/manual/bat.1) | tee`)
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.
25
26
26## Pre-release checks
27## Pre-release checks
27
28
@@ -30,13 +31,14 @@
30- [ ] Optional: manually test the new features and command-line options. To do
31- [ ] Optional: manually test the new features and command-line options. To do
31 this, install the latest `bat` version again (to include the new syntaxes
32 this, install the latest `bat` version again (to include the new syntaxes
32 and themes).
33 and themes).
33−- [ ] 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
34 succeed later (after creating the GitHub release).
35 succeed later (after creating the GitHub release).
35
36
36## Release
37## Release
37
38
38- [ ] Create a tag and push it: `git tag vX.Y.Z; git push origin tag vX.Y.Z`.
39- [ ] Create a tag and push it: `git tag vX.Y.Z; git push origin tag vX.Y.Z`.
39 This will trigger the deployment via GitHub Actions.
40 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!
40- [ ] Go to https://github.com/sharkdp/bat/releases/new to create the new
42- [ ] Go to https://github.com/sharkdp/bat/releases/new to create the new
41 release. Select the new tag and also use it as the release title. For the
43 release. Select the new tag and also use it as the release title. For the
42 release notes, copy the corresponding section from `CHANGELOG.md` and
44 release notes, copy the corresponding section from `CHANGELOG.md` and
src/assets.rs+71−4
@@ -43,8 +43,9 @@ pub struct SyntaxReferenceInSet<'a> {
43 pub syntax_set: &'a SyntaxSet,
43 pub syntax_set: &'a SyntaxSet,
44}
44}
45
45
46−/// Compress for size of ~700 kB instead of ~4600 kB at the cost of ~30% longer deserialization time
46+/// Lazy-loaded syntaxes are already compressed, and we don't want to compress
47+/// already compressed data.
47−pub(crate) const COMPRESS_SYNTAXES: bool = true;
48+pub(crate) const COMPRESS_SYNTAXES: bool = false;
48
49
49/// We don't want to compress our [LazyThemeSet] since the lazy-loaded themes
50/// We don't want to compress our [LazyThemeSet] since the lazy-loaded themes
50/// within it are already compressed, and compressing another time just makes
51/// within it are already compressed, and compressing another time just makes
@@ -68,10 +69,57 @@ impl HighlightingAssets {
68 }
69 }
69 }
70 }
70
71
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.
71 pub fn default_theme() -> &'static str {
93 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 {
72 "Monokai Extended"
112 "Monokai Extended"
73 }
113 }
74
114
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+
75 pub fn from_cache(cache_path: &Path) -> Result<Self> {
123 pub fn from_cache(cache_path: &Path) -> Result<Self> {
76 Ok(HighlightingAssets::new(
124 Ok(HighlightingAssets::new(
77 SerializedSyntaxSet::FromFile(cache_path.join("syntaxes.bin")),
125 SerializedSyntaxSet::FromFile(cache_path.join("syntaxes.bin")),
@@ -351,6 +399,16 @@ fn asset_from_cache<T: serde::de::DeserializeOwned>(
351 .map_err(|_| format!("Could not parse cached {}", description).into())
399 .map_err(|_| format!("Could not parse cached {}", description).into())
352}
400}
353
401
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+
354#[cfg(test)]
412#[cfg(test)]
355mod tests {
413mod tests {
356 use super::*;
414 use super::*;
@@ -581,13 +639,22 @@ mod tests {
581 }
639 }
582
640
583 #[test]
641 #[test]
584− fn syntax_detection_is_case_sensitive() {
642+ fn syntax_detection_is_case_insensitive() {
585 let mut test = SyntaxDetectionTest::new();
643 let mut test = SyntaxDetectionTest::new();
586
644
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");
587− assert_ne!(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
588 test.syntax_mapping
651 test.syntax_mapping
589 .insert("*.MD", MappingTarget::MapTo("Markdown"))
652 .insert("*.MD", MappingTarget::MapTo("Markdown"))
590 .ok();
653 .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");
591 assert_eq!(test.syntax_for_file("README.MD"), "Markdown");
658 assert_eq!(test.syntax_for_file("README.MD"), "Markdown");
592 }
659 }
593
660
src/bin/bat/app.rs+1−1
@@ -322,7 +322,7 @@ impl App {
322 .collect::<Vec<_>>()
322 .collect::<Vec<_>>()
323 })
323 })
324 .or(env_style_components)
324 .or(env_style_components)
325− .unwrap_or_else(|| vec![StyleComponent::Full])
325+ .unwrap_or_else(|| vec![StyleComponent::Default])
326 .into_iter()
326 .into_iter()
327 .map(|style| style.components(self.interactive_output))
327 .map(|style| style.components(self.interactive_output))
328 .fold(HashSet::new(), |mut acc, components| {
328 .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> {
398 !&[
398 !&[
399 "auto",
399 "auto",
400 "full",
400 "full",
401+ "default",
401 "plain",
402 "plain",
402 "header",
403 "header",
403 "header-filename",
404 "header-filename",
@@ -419,7 +420,7 @@ pub fn build_app(interactive_output: bool) -> ClapApp<'static, 'static> {
419 })
420 })
420 .help(
421 .help(
421 "Comma-separated list of style elements to display \
422 "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).",
423 )
424 )
424 .long_help(
425 .long_help(
425 "Configure which elements (line numbers, file headers, grid \
426 "Configure which elements (line numbers, file headers, grid \
@@ -430,8 +431,9 @@ pub fn build_app(interactive_output: bool) -> ClapApp<'static, 'static> {
430 '--style=\"..\"' option to the configuration file or export the \
431 '--style=\"..\"' option to the configuration file or export the \
431 BAT_STYLE environment variable (e.g.: export BAT_STYLE=\"..\").\n\n\
432 BAT_STYLE environment variable (e.g.: export BAT_STYLE=\"..\").\n\n\
432 Possible values:\n\n \
433 Possible values:\n\n \
433− * full: enables all available components (default).\n \
434+ * default: enables recommended style components (default).\n \
435+ * full: enables all available components.\n \
434− * auto: same as 'full', unless the output is piped.\n \
436+ * auto: same as 'default', unless the output is piped.\n \
435 * plain: disables all available components.\n \
437 * plain: disables all available components.\n \
436 * changes: show Git modification markers.\n \
438 * changes: show Git modification markers.\n \
437 * header: alias for 'header-filename'.\n \
439 * 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
91 .ok()
91 .ok()
92 .map(|content| get_args_from_str(&content))
92 .map(|content| get_args_from_str(&content))
93 .transpose()?
93 .transpose()?
94− .unwrap_or_else(Vec::new))
94+ .unwrap_or_default())
95}
95}
96
96
97pub fn get_args_from_env_var() -> Option<Result<Vec<OsString>, shell_words::ParseError>> {
97pub 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) {
230 let pager = bat::config::get_pager_executable(app.matches.value_of("pager"))
230 let pager = bat::config::get_pager_executable(app.matches.value_of("pager"))
231 .unwrap_or_else(|| "less".to_owned()); // FIXME: Avoid non-canonical path to "less".
231 .unwrap_or_else(|| "less".to_owned()); // FIXME: Avoid non-canonical path to "less".
232
232
233+ let mut custom_assets_metadata = PROJECT_DIRS.cache_dir().to_path_buf();
234+ custom_assets_metadata.push("metadata.yaml");
235+
233 let mut report = bugreport!()
236 let mut report = bugreport!()
234 .info(SoftwareVersion::default())
237 .info(SoftwareVersion::default())
235 .info(OperatingSystem::default())
238 .info(OperatingSystem::default())
@@ -254,6 +257,14 @@ fn invoke_bugreport(app: &App) {
254 "MANPAGER",
257 "MANPAGER",
255 ]))
258 ]))
256 .info(FileContent::new("Config file", config_file()))
259 .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+ ))
257 .info(CompileTimeInformation::default());
268 .info(CompileTimeInformation::default());
258
269
259 #[cfg(feature = "paging")]
270 #[cfg(feature = "paging")]
src/error.rs+4−1
@@ -2,11 +2,14 @@ use std::io::Write;
2use thiserror::Error;
2use thiserror::Error;
3
3
4#[derive(Error, Debug)]
4#[derive(Error, Debug)]
5+#[non_exhaustive]
5pub enum Error {
6pub enum Error {
6 #[error(transparent)]
7 #[error(transparent)]
7 Io(#[from] ::std::io::Error),
8 Io(#[from] ::std::io::Error),
8 #[error(transparent)]
9 #[error(transparent)]
9− SyntectError(#[from] ::syntect::LoadingError),
10+ SyntectError(#[from] ::syntect::Error),
11+ #[error(transparent)]
12+ SyntectLoadingError(#[from] ::syntect::LoadingError),
10 #[error(transparent)]
13 #[error(transparent)]
11 ParseIntError(#[from] ::std::num::ParseIntError),
14 ParseIntError(#[from] ::std::num::ParseIntError),
12 #[error(transparent)]
15 #[error(transparent)]
src/input.rs+1−1
@@ -118,7 +118,7 @@ impl OpenedInput<'_> {
118 self.metadata
118 self.metadata
119 .user_provided_name
119 .user_provided_name
120 .as_ref()
120 .as_ref()
121− .or_else(|| match self.kind {
121+ .or(match self.kind {
122 OpenedInputKind::OrdinaryFile(ref path) => Some(path),
122 OpenedInputKind::OrdinaryFile(ref path) => Some(path),
123 _ => None,
123 _ => None,
124 })
124 })
src/less.rs+59−8
@@ -3,21 +3,38 @@
3use std::ffi::OsStr;
3use std::ffi::OsStr;
4use std::process::Command;
4use std::process::Command;
5
5
6+#[derive(Debug, PartialEq)]
7+pub enum LessVersion {
8+ Less(usize),
9+ BusyBox,
10+}
11+
6−pub fn retrieve_less_version(less_path: &dyn AsRef<OsStr>) -> Option<usize> {
12+pub fn retrieve_less_version(less_path: &dyn AsRef<OsStr>) -> Option<LessVersion> {
7 let resolved_path = grep_cli::resolve_binary(less_path.as_ref()).ok()?;
13 let resolved_path = grep_cli::resolve_binary(less_path.as_ref()).ok()?;
8
14
9 let cmd = Command::new(resolved_path).arg("--version").output().ok()?;
15 let cmd = Command::new(resolved_path).arg("--version").output().ok()?;
16+ if cmd.status.success() {
10− parse_less_version(&cmd.stdout)
17+ parse_less_version(&cmd.stdout)
18+ } else {
19+ parse_less_version_busybox(&cmd.stderr)
20+ }
11}
21}
12
22
13−fn parse_less_version(output: &[u8]) -> Option<usize> {
23+fn parse_less_version(output: &[u8]) -> Option<LessVersion> {
14 if !output.starts_with(b"less ") {
24 if !output.starts_with(b"less ") {
15 return None;
25 return None;
16 }
26 }
17
27
18 let version = std::str::from_utf8(&output[5..]).ok()?;
28 let version = std::str::from_utf8(&output[5..]).ok()?;
19 let end = version.find(|c: char| !c.is_ascii_digit())?;
29 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+ }
21}
38}
22
39
23#[test]
40#[test]
@@ -30,7 +47,7 @@ For information about the terms of redistribution,
30see the file named README in the less distribution.
47see the file named README in the less distribution.
31Homepage: http://www.greenwoodsoftware.com/less";
48Homepage: http://www.greenwoodsoftware.com/less";
32
49
33− assert_eq!(Some(487), parse_less_version(output));
50+ assert_eq!(Some(LessVersion::Less(487)), parse_less_version(output));
34}
51}
35
52
36#[test]
53#[test]
@@ -43,7 +60,7 @@ For information about the terms of redistribution,
43see the file named README in the less distribution.
60see the file named README in the less distribution.
44Homepage: http://www.greenwoodsoftware.com/less";
61Homepage: http://www.greenwoodsoftware.com/less";
45
62
46− assert_eq!(Some(529), parse_less_version(output));
63+ assert_eq!(Some(LessVersion::Less(529)), parse_less_version(output));
47}
64}
48
65
49#[test]
66#[test]
@@ -56,7 +73,7 @@ For information about the terms of redistribution,
56see the file named README in the less distribution.
73see the file named README in the less distribution.
57Home page: http://www.greenwoodsoftware.com/less";
74Home page: http://www.greenwoodsoftware.com/less";
58
75
59− assert_eq!(Some(551), parse_less_version(output));
76+ assert_eq!(Some(LessVersion::Less(551)), parse_less_version(output));
60}
77}
61
78
62#[test]
79#[test]
@@ -69,7 +86,7 @@ For information about the terms of redistribution,
69see the file named README in the less distribution.
86see the file named README in the less distribution.
70Home page: https://greenwoodsoftware.com/less";
87Home page: https://greenwoodsoftware.com/less";
71
88
72− assert_eq!(Some(581), parse_less_version(output));
89+ assert_eq!(Some(LessVersion::Less(581)), parse_less_version(output));
73}
90}
74
91
75#[test]
92#[test]
@@ -77,4 +94,38 @@ fn test_parse_less_version_wrong_program() {
77 let output = b"more from util-linux 2.34";
94 let output = b"more from util-linux 2.34";
78
95
79 assert_eq!(None, parse_less_version(output));
96 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));
80}
131}
src/output.rs+7−5
@@ -4,7 +4,7 @@ use std::process::Child;
4
4
5use crate::error::*;
5use crate::error::*;
6#[cfg(feature = "paging")]
6#[cfg(feature = "paging")]
7−use crate::less::retrieve_less_version;
7+use crate::less::{retrieve_less_version, LessVersion};
8#[cfg(feature = "paging")]
8#[cfg(feature = "paging")]
9use crate::paging::PagingMode;
9use crate::paging::PagingMode;
10#[cfg(feature = "paging")]
10#[cfg(feature = "paging")]
@@ -83,13 +83,13 @@ impl OutputType {
83 let replace_arguments_to_less = pager.source == PagerSource::EnvVarPager;
83 let replace_arguments_to_less = pager.source == PagerSource::EnvVarPager;
84
84
85 if args.is_empty() || replace_arguments_to_less {
85 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
87 if single_screen_action == SingleScreenAction::Quit {
87 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
89 }
89 }
90
90
91 if wrapping_mode == WrappingMode::NoWrapping(true) {
91 if wrapping_mode == WrappingMode::NoWrapping(true) {
92− p.arg("--chop-long-lines");
92+ p.arg("-S"); // Short version of --chop-long-lines for compatibility
93 }
93 }
94
94
95 // Passing '--no-init' fixes a bug with '--quit-if-one-screen' in older
95 // Passing '--no-init' fixes a bug with '--quit-if-one-screen' in older
@@ -103,7 +103,9 @@ impl OutputType {
103 None => {
103 None => {
104 p.arg("--no-init");
104 p.arg("--no-init");
105 }
105 }
106+ Some(LessVersion::Less(version))
106− Some(version) if (version < 530 || (cfg!(windows) && version < 558)) => {
107+ if (version < 530 || (cfg!(windows) && version < 558)) =>
108+ {
107 p.arg("--no-init");
109 p.arg("--no-init");
108 }
110 }
109 _ => {}
111 _ => {}
src/preprocessor.rs+10−3
@@ -53,26 +53,33 @@ pub fn replace_nonprintable(input: &[u8], tab_width: usize) -> String {
53 let tab_width = if tab_width == 0 { 4 } else { tab_width };
53 let tab_width = if tab_width == 0 { 4 } else { tab_width };
54
54
55 let mut idx = 0;
55 let mut idx = 0;
56+ let mut line_idx = 0;
56 let len = input.len();
57 let len = input.len();
57 while idx < len {
58 while idx < len {
58 if let Some((chr, skip_ahead)) = try_parse_utf8_char(&input[idx..]) {
59 if let Some((chr, skip_ahead)) = try_parse_utf8_char(&input[idx..]) {
59 idx += skip_ahead;
60 idx += skip_ahead;
61+ line_idx += 1;
60
62
61 match chr {
63 match chr {
62 // space
64 // space
63 ' ' => output.push('·'),
65 ' ' => output.push('·'),
64 // tab
66 // tab
65 '\t' => {
67 '\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 {
67 output.push('↹');
71 output.push('↹');
68 } else {
72 } else {
69 output.push('├');
73 output.push('├');
70− output.push_str(&"─".repeat(tab_width - 2));
74+ output.push_str(&"─".repeat(tab_stop - 2));
71 output.push('┤');
75 output.push('┤');
72 }
76 }
73 }
77 }
74 // line feed
78 // line feed
79+ '\x0A' => {
75− '\x0A' => output.push_str("␊\x0A"),
80+ output.push_str("␊\x0A");
81+ line_idx = 0;
82+ }
76 // carriage return
83 // carriage return
77 '\x0D' => output.push('␍'),
84 '\x0D' => output.push('␍'),
78 // null
85 // null
src/pretty_printer.rs+6
@@ -164,6 +164,12 @@ impl<'a> PrettyPrinter<'a> {
164 self
164 self
165 }
165 }
166
166
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+
167 /// Whether to show "snip" markers between visible line ranges (default: no)
173 /// Whether to show "snip" markers between visible line ranges (default: no)
168 pub fn snip(&mut self, yes: bool) -> &mut Self {
174 pub fn snip(&mut self, yes: bool) -> &mut Self {
169 self.active_style_components.snip = yes;
175 self.active_style_components.snip = yes;
src/printer.rs+14−2
@@ -445,9 +445,21 @@ impl<'a> Printer for InteractivePrinter<'a> {
445 return Ok(());
445 return Ok(());
446 }
446 }
447 };
447 };
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+
448− highlighter_from_set
454+ let mut highlighted_line = highlighter_from_set
449 .highlighter
455 .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
451 };
463 };
452
464
453 if out_of_range {
465 if out_of_range {
src/style.rs+11−1
@@ -17,6 +17,7 @@ pub enum StyleComponent {
17 LineNumbers,
17 LineNumbers,
18 Snip,
18 Snip,
19 Full,
19 Full,
20+ Default,
20 Plain,
21 Plain,
21}
22}
22
23
@@ -25,7 +26,7 @@ impl StyleComponent {
25 match self {
26 match self {
26 StyleComponent::Auto => {
27 StyleComponent::Auto => {
27 if interactive_terminal {
28 if interactive_terminal {
28− StyleComponent::Full.components(interactive_terminal)
29+ StyleComponent::Default.components(interactive_terminal)
29 } else {
30 } else {
30 StyleComponent::Plain.components(interactive_terminal)
31 StyleComponent::Plain.components(interactive_terminal)
31 }
32 }
@@ -48,6 +49,14 @@ impl StyleComponent {
48 StyleComponent::LineNumbers,
49 StyleComponent::LineNumbers,
49 StyleComponent::Snip,
50 StyleComponent::Snip,
50 ],
51 ],
52+ StyleComponent::Default => &[
53+ #[cfg(feature = "git")]
54+ StyleComponent::Changes,
55+ StyleComponent::Grid,
56+ StyleComponent::HeaderFilename,
57+ StyleComponent::LineNumbers,
58+ StyleComponent::Snip,
59+ ],
51 StyleComponent::Plain => &[],
60 StyleComponent::Plain => &[],
52 }
61 }
53 }
62 }
@@ -69,6 +78,7 @@ impl FromStr for StyleComponent {
69 "numbers" => Ok(StyleComponent::LineNumbers),
78 "numbers" => Ok(StyleComponent::LineNumbers),
70 "snip" => Ok(StyleComponent::Snip),
79 "snip" => Ok(StyleComponent::Snip),
71 "full" => Ok(StyleComponent::Full),
80 "full" => Ok(StyleComponent::Full),
81+ "default" => Ok(StyleComponent::Default),
72 "plain" => Ok(StyleComponent::Plain),
82 "plain" => Ok(StyleComponent::Plain),
73 _ => Err(format!("Unknown style '{}'", s).into()),
83 _ => Err(format!("Unknown style '{}'", s).into()),
74 }
84 }
src/syntax_mapping.rs+8
@@ -41,6 +41,9 @@ impl<'a> SyntaxMapping<'a> {
41 pub fn builtin() -> SyntaxMapping<'a> {
41 pub fn builtin() -> SyntaxMapping<'a> {
42 let mut mapping = Self::empty();
42 let mut mapping = Self::empty();
43 mapping.insert("*.h", MappingTarget::MapTo("C++")).unwrap();
43 mapping.insert("*.h", MappingTarget::MapTo("C++")).unwrap();
44+ mapping
45+ .insert(".clang-format", MappingTarget::MapTo("YAML"))
46+ .unwrap();
44 mapping.insert("*.fs", MappingTarget::MapTo("F#")).unwrap();
47 mapping.insert("*.fs", MappingTarget::MapTo("F#")).unwrap();
45 mapping
48 mapping
46 .insert("build", MappingTarget::MapToUnknown)
49 .insert("build", MappingTarget::MapToUnknown)
@@ -117,6 +120,11 @@ impl<'a> SyntaxMapping<'a> {
117 mapping.insert(glob, MappingTarget::MapTo("INI")).unwrap();
120 mapping.insert(glob, MappingTarget::MapTo("INI")).unwrap();
118 }
121 }
119
122
123+ // unix mail spool
124+ for glob in &["/var/spool/mail/*", "/var/mail/*"] {
125+ mapping.insert(glob, MappingTarget::MapTo("Email")).unwrap()
126+ }
127+
120 // pacman hooks
128 // pacman hooks
121 mapping
129 mapping
122 .insert("*.hook", MappingTarget::MapTo("INI"))
130 .insert("*.hook", MappingTarget::MapTo("INI"))
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+124
@@ -974,6 +974,53 @@ fn header_full_binary() {
974 .stderr("");
974 .stderr("");
975}
975}
976
976
977+#[test]
978+fn header_default() {
979+ bat()
980+ .arg("--paging=never")
981+ .arg("--color=never")
982+ .arg("--terminal-width=80")
983+ .arg("--wrap=never")
984+ .arg("--decorations=always")
985+ .arg("--style=default")
986+ .arg("single-line.txt")
987+ .assert()
988+ .success()
989+ .stdout(
990+ "\
991+───────┬────────────────────────────────────────────────────────────────────────
992+ │ File: single-line.txt
993+───────┼────────────────────────────────────────────────────────────────────────
994+ 1 │ Single Line
995+───────┴────────────────────────────────────────────────────────────────────────
996+",
997+ )
998+ .stderr("");
999+}
1000+
1001+#[test]
1002+fn header_default_is_default() {
1003+ bat()
1004+ .arg("--paging=never")
1005+ .arg("--color=never")
1006+ .arg("--terminal-width=80")
1007+ .arg("--wrap=never")
1008+ .arg("--decorations=always")
1009+ .arg("single-line.txt")
1010+ .assert()
1011+ .success()
1012+ .stdout(
1013+ "\
1014+───────┬────────────────────────────────────────────────────────────────────────
1015+ │ File: single-line.txt
1016+───────┼────────────────────────────────────────────────────────────────────────
1017+ 1 │ Single Line
1018+───────┴────────────────────────────────────────────────────────────────────────
1019+",
1020+ )
1021+ .stderr("");
1022+}
1023+
977#[test]
1024#[test]
978fn filename_stdin() {
1025fn filename_stdin() {
979 bat()
1026 bat()
@@ -1217,6 +1264,52 @@ fn show_all_mode() {
1217 .stderr("");
1264 .stderr("");
1218}
1265}
1219
1266
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+
1220#[test]
1313#[test]
1221fn no_paging_arg() {
1314fn no_paging_arg() {
1222 bat()
1315 bat()
@@ -1334,6 +1427,8 @@ fn ansi_passthrough_emit() {
1334fn ignored_suffix_arg() {
1427fn ignored_suffix_arg() {
1335 bat()
1428 bat()
1336 .arg("-f")
1429 .arg("-f")
1430+ .arg("--theme")
1431+ .arg("Monokai Extended")
1337 .arg("-p")
1432 .arg("-p")
1338 .arg("test.json~")
1433 .arg("test.json~")
1339 .assert()
1434 .assert()
@@ -1343,6 +1438,8 @@ fn ignored_suffix_arg() {
1343
1438
1344 bat()
1439 bat()
1345 .arg("-f")
1440 .arg("-f")
1441+ .arg("--theme")
1442+ .arg("Monokai Extended")
1346 .arg("-p")
1443 .arg("-p")
1347 .arg("--ignored-suffix=.suffix")
1444 .arg("--ignored-suffix=.suffix")
1348 .arg("test.json.suffix")
1445 .arg("test.json.suffix")
@@ -1353,6 +1450,8 @@ fn ignored_suffix_arg() {
1353
1450
1354 bat()
1451 bat()
1355 .arg("-f")
1452 .arg("-f")
1453+ .arg("--theme")
1454+ .arg("Monokai Extended")
1356 .arg("-p")
1455 .arg("-p")
1357 .arg("test.json.suffix")
1456 .arg("test.json.suffix")
1358 .assert()
1457 .assert()
@@ -1361,6 +1460,25 @@ fn ignored_suffix_arg() {
1361 .stderr("");
1460 .stderr("");
1362}
1461}
1363
1462
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+
1364#[test]
1482#[test]
1365fn all_global_git_config_locations_syntax_mapping_work() {
1483fn all_global_git_config_locations_syntax_mapping_work() {
1366 let fake_home = Path::new(EXAMPLES_DIR).join("git").canonicalize().unwrap();
1484 let fake_home = Path::new(EXAMPLES_DIR).join("git").canonicalize().unwrap();
@@ -1372,6 +1490,8 @@ fn all_global_git_config_locations_syntax_mapping_work() {
1372 bat()
1490 bat()
1373 .env("XDG_CONFIG_HOME", fake_home.join(".config").as_os_str())
1491 .env("XDG_CONFIG_HOME", fake_home.join(".config").as_os_str())
1374 .arg("-f")
1492 .arg("-f")
1493+ .arg("--theme")
1494+ .arg("Monokai Extended")
1375 .arg("-p")
1495 .arg("-p")
1376 .arg("git/.config/git/config")
1496 .arg("git/.config/git/config")
1377 .assert()
1497 .assert()
@@ -1382,6 +1502,8 @@ fn all_global_git_config_locations_syntax_mapping_work() {
1382 bat()
1502 bat()
1383 .env("HOME", fake_home.as_os_str())
1503 .env("HOME", fake_home.as_os_str())
1384 .arg("-f")
1504 .arg("-f")
1505+ .arg("--theme")
1506+ .arg("Monokai Extended")
1385 .arg("-p")
1507 .arg("-p")
1386 .arg("git/.config/git/config")
1508 .arg("git/.config/git/config")
1387 .assert()
1509 .assert()
@@ -1392,6 +1514,8 @@ fn all_global_git_config_locations_syntax_mapping_work() {
1392 bat()
1514 bat()
1393 .env("HOME", fake_home.as_os_str())
1515 .env("HOME", fake_home.as_os_str())
1394 .arg("-f")
1516 .arg("-f")
1517+ .arg("--theme")
1518+ .arg("Monokai Extended")
1395 .arg("-p")
1519 .arg("-p")
1396 .arg("git/.gitconfig")
1520 .arg("git/.gitconfig")
1397 .assert()
1521 .assert()
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/Log/example.log+1
@@ -1,2 +1,3 @@
12021-03-06 23:22:21.392 https://[2001:db8:4006:812::200e]:8080/path/the%20page.html
12021-03-06 23:22:21.392 https://[2001:db8:4006:812::200e]:8080/path/the%20page.html
22021-03-06 23:22:21 https://example.com:8080/path/the%20page(with_parens).html
22021-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 @@
27</script>
27</script>
28
28
29<script type="text/livescript">
29<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
31</script>
31</script>
32
32
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+
33<style>
37<style>
34 main {
38 main {
35 position: relative;
39 position: relative;
tests/syntax-tests/highlighted/Syslog/example.syslog+3−3
@@ -1,7 +1,7 @@
1Apr 4 00:00:01 hostname-here systemd[1]: logrotate.service: Succeeded.
1Apr 4 00:00:01 hostname-here systemd[1]: logrotate.service: Succeeded.
2Apr 4 00:00:01 hostname-here systemd[1]: Finished Rotate log files.
2Apr 4 00:00:01 hostname-here systemd[1]: Finished Rotate log files.
3Apr 4 00:00:01 hostname-here colord[920]: failed to get session [pid 137485]: No data available
3Apr 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"
5Apr 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.
5Apr 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.
6Apr 4 00:04:46 hostname-here ntpd[952]: Soliciting pool server 255.76.59.37
6Apr 4 00:04:46 hostname-here ntpd[952]: Soliciting pool server 255.76.59.37
7Apr 4 00:05:21 hostname-here ntpd[952]: ::1 local addr 0:0:0:0:0:0:0:1 -> <null>
7Apr 4 00:05:21 hostname-here ntpd[952]: ::1 local addr 0:0:0:0:0:0:0:1 -> <null>
@@ -10,7 +10,7 @@
10Apr 4 16:32:07 hostname-here NetworkManager[740]: <info> [1617629527.1101] manager: NetworkManager state is now CONNECTED_GLOBAL
10Apr 4 16:32:07 hostname-here NetworkManager[740]: <info> [1617629527.1101] manager: NetworkManager state is now CONNECTED_GLOBAL
11Apr 4 22:00:45 hostname-here dbus-daemon[1094]: [session uid=1000 pid=1094] Successfully activated service 'io.github.celluloid_player.Celluloid'
11Apr 4 22:00:45 hostname-here dbus-daemon[1094]: [session uid=1000 pid=1094] Successfully activated service 'io.github.celluloid_player.Celluloid'
12Aug 11 13:29:06 hostname-here insomnia_insomnia.desktop[142666]: 13:29:06.316 › [updater] Updater not running platform=linux dev=false
12Aug 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
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
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
15Aug 11 21:40:31 hostname-here scop hello
15Aug 11 21:40:31 hostname-here scop hello
16Aug 16 21:38:21 hostname-here systemd[1]: Finished Cleanup of Temporary Directories.
16Aug 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 @@
8 </div>
8 </div>
9</template>
9</template>
10
10
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+
11<script>
16<script>
12import AppHeader from "@/components/AppHeader";
17import AppHeader from "@/components/AppHeader";
13import AppLoadingIndicator from "@/components/AppLoadingIndicator";
18import AppLoadingIndicator from "@/components/AppLoadingIndicator";
tests/syntax-tests/highlighted/Zig/example.zig+39−39
@@ -1,18 +1,18 @@
1//! this is a top level doc, starts with "//!"
1//! this is a top level doc, starts with "//!"
2
2
3−const std = @import("std");
3+const std = @import("std");
4
4
5pub fn main() anyerror!void {
5pub fn main() anyerror!void {
6− const stdout = std.io.getStdOut().writer();
6+ const stdout = std.io.getStdOut().writer();
7− try stdout.print("Hello, {}!\n", .{"world"});
7+ try stdout.print("Hello, {}!\n", .{"world"});
8}
8}
9
9
10−const expect = std.testing.expect;
10+const expect = std.testing.expect;
11
11
12test "comments" {
12test "comments" {
13 // comments start with "//" until newline
13 // comments start with "//" until newline
14 // foo bar baz
14 // foo bar baz
15− const x = true; // another comment
15+ const x = true; // another comment
16 expect(x);
16 expect(x);
17}
17}
18
18
@@ -25,26 +25,26 @@
25 /// number of nanoseconds past the second
25 /// number of nanoseconds past the second
26 nano: u32,
26 nano: u32,
27
27
28− const Self = @This();
28+ const Self = @This();
29
29
30 pub fn unixEpoch() Self {
30 pub fn unixEpoch() Self {
31 return Self{
31 return Self{
32− .seconds = 0,
32+ .seconds = 0,
33− .nanos = 0,
33+ .nanos = 0,
34 };
34 };
35 }
35 }
36};
36};
37
37
38−const my_val = switch (std.Target.current.os.tag) {
38+const my_val = switch (std.Target.current.os.tag) {
39− .linux => "Linux",
39+ .linux => "Linux",
40 else => "not Linux",
40 else => "not Linux",
41};
41};
42
42
43const Book = enum {
43const Book = enum {
44− paperback,
44+ paperback,
45− hardcover,
45+ hardcover,
46− ebook,
46+ ebook,
47− pdf,
47+ pdf,
48};
48};
49
49
50const TokenType = union(enum) {
50const TokenType = union(enum) {
@@ -54,54 +54,54 @@
54};
54};
55
55
56const array_lit: [4]u8 = .{ 11, 22, 33, 44 };
56const 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 };
58
58
59test "address of syntax" {
59test "address of syntax" {
60 // Get the address of a variable:
60 // Get the address of a variable:
61 const x: i32 = 1234;
61 const x: i32 = 1234;
62− const x_ptr = &x;
62+ const x_ptr = &x;
63
63
64 // Dereference a pointer:
64 // Dereference a pointer:
65 expect(x_ptr.* == 1234);
65 expect(x_ptr.* == 1234);
66
66
67 // When you get the address of a const variable, you get a const pointer to a single item.
67 // 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);
69
69
70 // If you want to mutate the value, you'd need an address of a mutable variable:
70 // If you want to mutate the value, you'd need an address of a mutable variable:
71 var y: i32 = 5678;
71 var y: i32 = 5678;
72− const y_ptr = &y;
72+ const y_ptr = &y;
73− expect(@TypeOf(y_ptr) == *i32);
73+ expect(@TypeOf(y_ptr) == *i32);
74− y_ptr.* += 1;
74+ y_ptr.* += 1;
75 expect(y_ptr.* == 5679);
75 expect(y_ptr.* == 5679);
76}
76}
77
77
78// integer literals
78// integer literals
79−const decimal_int = 98222;
79+const decimal_int = 98222;
80−const hex_int = 0xff;
80+const hex_int = 0xff;
81−const another_hex_int = 0xFF;
81+const another_hex_int = 0xFF;
82−const octal_int = 0o755;
82+const octal_int = 0o755;
83−const binary_int = 0b11110000;
83+const binary_int = 0b11110000;
84
84
85// underscores may be placed between two digits as a visual separator
85// underscores may be placed between two digits as a visual separator
86−const one_billion = 1_000_000_000;
86+const one_billion = 1_000_000_000;
87−const binary_mask = 0b1_1111_1111;
87+const binary_mask = 0b1_1111_1111;
88−const permissions = 0o7_5_5;
88+const permissions = 0o7_5_5;
89−const big_address = 0xFF80_0000_0000_0000;
89+const big_address = 0xFF80_0000_0000_0000;
90
90
91// float literals
91// float literals
92−const floating_point = 123.0E+77;
92+const floating_point = 123.0E+77;
93−const another_float = 123.0;
93+const another_float = 123.0;
94−const yet_another = 123.0e+77;
94+const yet_another = 123.0e+77;
95
95
96−const hex_floating_point = 0x103.70p-5;
96+const hex_floating_point = 0x103.70p-5;
97−const another_hex_float = 0x103.70;
97+const another_hex_float = 0x103.70;
98−const yet_another_hex_float = 0x103.70P-5;
98+const yet_another_hex_float = 0x103.70P-5;
99
99
100// underscores may be placed between two digits as a visual separator
100// underscores may be placed between two digits as a visual separator
101−const lightspeed = 299_792_458.000_000;
101+const lightspeed = 299_792_458.000_000;
102−const nanosecond = 0.000_000_001;
102+const nanosecond = 0.000_000_001;
103−const more_hex = 0x1234_5678.9ABC_CDEFp-10;
103+const more_hex = 0x1234_5678.9ABC_CDEFp-10;
104
104
105fn max(comptime T: type, a: T, b: T) T {
105fn 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;
107}
107}
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/Log/example.log+1
@@ -1,2 +1,3 @@
12021-03-06 23:22:21.392 https://[2001:db8:4006:812::200e]:8080/path/the%20page.html
12021-03-06 23:22:21.392 https://[2001:db8:4006:812::200e]:8080/path/the%20page.html
22021-03-06 23:22:21 https://example.com:8080/path/the%20page(with_parens).html
22021-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 @@
27</script>
27</script>
28
28
29<script type="text/livescript">
29<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
31</script>
31</script>
32
32
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+
33<style>
37<style>
34 main {
38 main {
35 position: relative;
39 position: relative;
tests/syntax-tests/source/Vue/example.vue+5
@@ -8,6 +8,11 @@
8 </div>
8 </div>
9</template>
9</template>
10
10
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+
11<script>
16<script>
12import AppHeader from "@/components/AppHeader";
17import AppHeader from "@/components/AppHeader";
13import AppLoadingIndicator from "@/components/AppLoadingIndicator";
18import 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.