Repository: sharkdp/bat (language: rust)

Issue:
File extensions should be matched without case sensitivity
Perhaps there are some example use cases to the contrary, but in general it seems like it would preferable if file extensions were matched ignoring case. I recently experienced this with a file name that had the extension `SQL` instead of `sql` and `bat` did not automatically apply the desired highlighting.


Discussion / hints:
Thanks for reporting. We have fixed this upstream, and are waiting for a new release of the `syntect` dependency which will contain this fix. (See https://github.com/sharkdp/bat/issues/1807 where it was first discovered.)
Great! Thanks. Feel free to close this as it probably doesn't need a separate issue to be tracked.

Fix patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 286045facf..5626691aab 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,15 +5,21 @@
 - Correctly render tab stops in --show-all, see #2038 (@Synthetica9)
 - Add a `--style=default` option, less verbose than `full`, see #2061 (@IsaacHorvath)
 - Enable BusyBox less as pager, see #2162 (@nfisher1226)
+- File extensions are now matched without taking case into account. See #1854, #2181 (@Enselic)
 
 ## Bugfixes
 
 - 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)
+- `bat` no longer crashes when encountering files that references missing syntaxes. See #915, #2181 (@Enselic)
+
+## Performance
+
+- Skip syntax highlighting on long lines (> 16384 chars) to help improve performance. See #2165 (@keith-hall)
+- 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)
 
 ## Other
 
 - Include info about custom assets in `--diagnostics` if used. See #2107, #2144 (@Enselic)
-- Skip syntax highlighting on long lines (> 16384 chars) to help improve performance. See #2165 (@keith-hall)
 
 ## Syntaxes
 
@@ -28,6 +34,10 @@
 ## `bat` as a library
 
 - Allow configuration of `show_nonprintable` with `PrettyPrinter`, see #2142
+- The binary format of syntaxes.bin has been changed due to syntaxes now being lazy-loaded via syntect 5.0.0. See #2181 (@Enselic)
+- Mark `bat::error::Error` enum as `#[non_exhaustive]` to allow adding new variants without future semver breakage. See #2181 (@Enselic)
+- Change `Error::SyntectError(syntect::LoadingError)` to `Error::SyntectError(syntect::Error)`. See #2181 (@Enselic)
+- Add `Error::SyntectLoadingError(syntect::LoadingError)` enum variant. See #2181 (@Enselic)
 
 # v0.20.0
 
diff --git a/Cargo.lock b/Cargo.lock
index 3345565c48..da5ab17a36 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -580,12 +580,6 @@ version = "1.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
 
-[[package]]
-name = "lazycell"
-version = "1.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
-
 [[package]]
 name = "libc"
 version = "0.2.125"
@@ -1071,9 +1065,9 @@ dependencies = [
 
 [[package]]
 name = "syntect"
-version = "4.6.0"
+version = "5.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8b20815bbe80ee0be06e6957450a841185fcf690fe0178f14d77a05ce2caa031"
+checksum = "c6c454c27d9d7d9a84c7803aaa3c50cd088d2906fe3c6e42da3209aa623576a8"
 dependencies = [
  "bincode",
  "bitflags",
@@ -1081,13 +1075,14 @@ dependencies = [
  "flate2",
  "fnv",
  "lazy_static",
- "lazycell",
+ "once_cell",
  "onig",
  "plist",
  "regex-syntax",
  "serde",
  "serde_derive",
  "serde_json",
+ "thiserror",
  "walkdir",
  "yaml-rust",
 ]
diff --git a/Cargo.toml b/Cargo.toml
index 7a48b3cf83..0e015e6607 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -33,8 +33,7 @@ minimal-application = [
 ]
 git = ["git2"] # Support indicating git modifications
 paging = ["shell-words", "grep-cli"] # Support applying a pager on the output
-# Add "syntect/plist-load" when https://github.com/trishume/syntect/pull/345 reaches us
-build-assets = ["syntect/yaml-load", "syntect/dump-create", "regex", "walkdir"]
+build-assets = ["syntect/yaml-load", "syntect/plist-load", "regex", "walkdir"]
 
 # You need to use one of these if you depend on bat as a library:
 regex-onig = ["syntect/regex-onig"] # Use the "oniguruma" regex engine
@@ -73,7 +72,7 @@ optional = true
 default-features = false
 
 [dependencies.syntect]
-version = "4.6.0"
+version = "5.0.0"
 default-features = false
 features = ["parsing"]
 
diff --git a/assets/acknowledgements.bin b/assets/acknowledgements.bin
index b3d31ea714..748d1e32be 100644
Binary files a/assets/acknowledgements.bin and b/assets/acknowledgements.bin differ
diff --git a/assets/syntaxes.bin b/assets/syntaxes.bin
index c5cb3bbb4e..92ad6e7ec4 100644
Binary files a/assets/syntaxes.bin and b/assets/syntaxes.bin differ
diff --git a/assets/themes.bin b/assets/themes.bin
index 5d30912786..1163d1d243 100644
Binary files a/assets/themes.bin and b/assets/themes.bin differ
diff --git a/src/assets.rs b/src/assets.rs
index e25c233ffe..8126843373 100644
--- a/src/assets.rs
+++ b/src/assets.rs
@@ -43,8 +43,9 @@ pub struct SyntaxReferenceInSet<'a> {
     pub syntax_set: &'a SyntaxSet,
 }
 
-/// Compress for size of ~700 kB instead of ~4600 kB at the cost of ~30% longer deserialization time
-pub(crate) const COMPRESS_SYNTAXES: bool = true;
+/// Lazy-loaded syntaxes are already compressed, and we don't want to compress
+/// already compressed data.
+pub(crate) const COMPRESS_SYNTAXES: bool = false;
 
 /// We don't want to compress our [LazyThemeSet] since the lazy-loaded themes
 /// within it are already compressed, and compressing another time just makes
@@ -581,13 +582,22 @@ mod tests {
     }
 
     #[test]
-    fn syntax_detection_is_case_sensitive() {
+    fn syntax_detection_is_case_insensitive() {
         let mut test = SyntaxDetectionTest::new();
 
-        assert_ne!(test.syntax_for_file("README.MD"), "Markdown");
+        assert_eq!(test.syntax_for_file("README.md"), "Markdown");
+        assert_eq!(test.syntax_for_file("README.mD"), "Markdown");
+        assert_eq!(test.syntax_for_file("README.Md"), "Markdown");
+        assert_eq!(test.syntax_for_file("README.MD"), "Markdown");
+
+        // Adding a mapping for "MD" in addition to "md" should not break the mapping
         test.syntax_mapping
             .insert("*.MD", MappingTarget::MapTo("Markdown"))
             .ok();
+
+        assert_eq!(test.syntax_for_file("README.md"), "Markdown");
+        assert_eq!(test.syntax_for_file("README.mD"), "Markdown");
+        assert_eq!(test.syntax_for_file("README.Md"), "Markdown");
         assert_eq!(test.syntax_for_file("README.MD"), "Markdown");
     }
 
diff --git a/src/error.rs b/src/error.rs
index 54f460e73e..f9845138f1 100644
--- a/src/error.rs
+++ b/src/error.rs
@@ -2,11 +2,14 @@ use std::io::Write;
 use thiserror::Error;
 
 #[derive(Error, Debug)]
+#[non_exhaustive]
 pub enum Error {
     #[error(transparent)]
     Io(#[from] ::std::io::Error),
     #[error(transparent)]
-    SyntectError(#[from] ::syntect::LoadingError),
+    SyntectError(#[from] ::syntect::Error),
+    #[error(transparent)]
+    SyntectLoadingError(#[from] ::syntect::LoadingError),
     #[error(transparent)]
     ParseIntError(#[from] ::std::num::ParseIntError),
     #[error(transparent)]
diff --git a/src/printer.rs b/src/printer.rs
index d85120bd09..00e7da96a9 100644
--- a/src/printer.rs
+++ b/src/printer.rs
@@ -453,7 +453,7 @@ impl<'a> Printer for InteractivePrinter<'a> {
 
             let mut highlighted_line = highlighter_from_set
                 .highlighter
-                .highlight(for_highlighting, highlighter_from_set.syntax_set);
+                .highlight_line(for_highlighting, highlighter_from_set.syntax_set)?;
 
             if too_long {
                 highlighted_line[0].1 = &line;


Test patch:
diff --git a/tests/syntax-tests/highlighted/Svelte/App.svelte b/tests/syntax-tests/highlighted/Svelte/App.svelte
index 7a09649a1c..d1ec994835 100644
--- a/tests/syntax-tests/highlighted/Svelte/App.svelte
+++ b/tests/syntax-tests/highlighted/Svelte/App.svelte
@@ -27,9 +27,13 @@
 [38;2;255;255;255m</[0m[3;38;2;249;38;114mscript[0m[38;2;255;255;255m>[0m
 
 [38;2;255;255;255m<[0m[3;38;2;249;38;114mscript[0m[38;2;248;248;242m [0m[38;2;166;226;46mtype[0m[38;2;166;226;46m=[0m[38;2;255;255;255m"[0m[38;2;230;219;116mtext/livescript[0m[38;2;255;255;255m"[0m[38;2;255;255;255m>[0m
-[38;2;248;248;242m    [0m[38;2;246;170;17m// This block is a regression test for a bat panic when a LiveScript syntax definition is missing[0m
+[38;2;248;248;242m	[0m[38;2;246;170;17m// This block is a regression test for a bat panic when a LiveScript syntax definition is missing[0m
 [38;2;255;255;255m</[0m[3;38;2;249;38;114mscript[0m[38;2;255;255;255m>[0m
 
+[38;2;255;255;255m<[0m[38;2;249;38;114mstyle[0m[38;2;248;248;242m [0m[38;2;166;226;46mlang[0m[38;2;166;226;46m=[0m[38;2;255;255;255m"[0m[38;2;230;219;116mtext/postcss[0m[38;2;255;255;255m"[0m[38;2;255;255;255m>[0m
+[38;2;248;248;242m	[0m[38;2;117;113;94m/*[0m[38;2;117;113;94m This block is a regression test for a bat panic when a PostCSS syntax definition is missing [0m[38;2;117;113;94m*/[0m
+[38;2;255;255;255m</[0m[38;2;249;38;114mstyle[0m[38;2;255;255;255m>[0m
+
 [38;2;255;255;255m<[0m[38;2;249;38;114mstyle[0m[38;2;255;255;255m>[0m
 [38;2;248;248;242m	[0m[38;2;249;38;114mmain[0m[38;2;248;248;242m [0m[38;2;255;255;255m{[0m
 [38;2;248;248;242m		[0m[3;38;2;102;217;239mposition[0m[38;2;255;255;255m:[0m[38;2;248;248;242m [0m[38;2;102;217;239mrelative[0m[38;2;255;255;255m;[0m
diff --git a/tests/syntax-tests/highlighted/Vue/example.vue b/tests/syntax-tests/highlighted/Vue/example.vue
index d8da085220..07c2798671 100644
--- a/tests/syntax-tests/highlighted/Vue/example.vue
+++ b/tests/syntax-tests/highlighted/Vue/example.vue
@@ -8,6 +8,11 @@
 [38;2;248;248;242m  [0m[38;2;255;255;255m</[0m[38;2;249;38;114mdiv[0m[38;2;255;255;255m>[0m
 [38;2;255;255;255m</[0m[38;2;249;38;114mtemplate[0m[38;2;255;255;255m>[0m
 
+[38;2;255;255;255m<[0m[38;2;249;38;114mtemplate [0m[38;2;166;226;46mlang[0m[38;2;166;226;46m=[0m[38;2;255;255;255m'[0m[38;2;230;219;116mpug[0m[38;2;255;255;255m'[0m[38;2;255;255;255m>[0m
+[38;2;248;248;242m  #container.col[0m
+[38;2;248;248;242m    p This shall be formatted as Plain Text as long as a Pug syntax definition is missing[0m
+[38;2;255;255;255m</[0m[38;2;249;38;114mtemplate[0m[38;2;255;255;255m>[0m
+
 [38;2;255;255;255m<[0m[3;38;2;249;38;114mscript[0m[38;2;255;255;255m>[0m
 [38;2;249;38;114mimport[0m[38;2;248;248;242m [0m[38;2;255;255;255mAppHeader[0m[38;2;248;248;242m [0m[38;2;249;38;114mfrom[0m[38;2;248;248;242m [0m[38;2;230;219;116m"[0m[38;2;230;219;116m@/components/AppHeader[0m[38;2;230;219;116m"[0m[38;2;248;248;242m;[0m
 [38;2;249;38;114mimport[0m[38;2;248;248;242m [0m[38;2;255;255;255mAppLoadingIndicator[0m[38;2;248;248;242m [0m[38;2;249;38;114mfrom[0m[38;2;248;248;242m [0m[38;2;230;219;116m"[0m[38;2;230;219;116m@/components/AppLoadingIndicator[0m[38;2;230;219;116m"[0m[38;2;248;248;242m;[0m
diff --git a/tests/syntax-tests/source/Svelte/App.svelte b/tests/syntax-tests/source/Svelte/App.svelte
index 089172c41c..e1ae02c3eb 100644
--- a/tests/syntax-tests/source/Svelte/App.svelte
+++ b/tests/syntax-tests/source/Svelte/App.svelte
@@ -27,9 +27,13 @@
 </script>
 
 <script type="text/livescript">
-    // This block is a regression test for a bat panic when a LiveScript syntax definition is missing
+	// This block is a regression test for a bat panic when a LiveScript syntax definition is missing
 </script>
 
+<style lang="text/postcss">
+	/* This block is a regression test for a bat panic when a PostCSS syntax definition is missing */
+</style>
+
 <style>
 	main {
 		position: relative;
diff --git a/tests/syntax-tests/source/Vue/example.vue b/tests/syntax-tests/source/Vue/example.vue
index 5e0467f1bc..25506910ff 100644
--- a/tests/syntax-tests/source/Vue/example.vue
+++ b/tests/syntax-tests/source/Vue/example.vue
@@ -8,6 +8,11 @@
   </div>
 </template>
 
+<template lang='pug'>
+  #container.col
+    p This shall be formatted as Plain Text as long as a Pug syntax definition is missing
+</template>
+
 <script>
 import AppHeader from "@/components/AppHeader";
 import AppLoadingIndicator from "@/components/AppLoadingIndicator";