Pārlūkot izejas kodu

refactor: Use phf macros instead of codegen to create icon and filetype tables

Robert Minsk 2 gadi atpakaļ
vecāks
revīzija
bf5d602dc6
5 mainītis faili ar 661 papildinājumiem un 690 dzēšanām
  1. 45 7
      Cargo.lock
  2. 1 8
      Cargo.toml
  3. 3 664
      build.rs
  4. 207 8
      src/info/filetype.rs
  5. 405 3
      src/output/icons.rs

+ 45 - 7
Cargo.lock

@@ -94,7 +94,6 @@ dependencies = [
  "num_cpus",
  "number_prefix",
  "phf",
- "phf_codegen",
  "scoped_threadpool",
  "term_grid",
  "terminal_size",
@@ -301,27 +300,31 @@ version = "0.11.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc"
 dependencies = [
+ "phf_macros",
  "phf_shared",
 ]
 
 [[package]]
-name = "phf_codegen"
+name = "phf_generator"
 version = "0.11.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e8d39688d359e6b34654d328e262234662d16cc0f60ec8dcbe5e718709342a5a"
+checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0"
 dependencies = [
- "phf_generator",
  "phf_shared",
+ "rand",
 ]
 
 [[package]]
-name = "phf_generator"
+name = "phf_macros"
 version = "0.11.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0"
+checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b"
 dependencies = [
+ "phf_generator",
  "phf_shared",
- "rand",
+ "proc-macro2",
+ "quote",
+ "syn",
 ]
 
 [[package]]
@@ -339,6 +342,24 @@ version = "0.3.19"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c"
 
+[[package]]
+name = "proc-macro2"
+version = "1.0.66"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.33"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae"
+dependencies = [
+ "proc-macro2",
+]
+
 [[package]]
 name = "rand"
 version = "0.8.5"
@@ -386,6 +407,17 @@ version = "0.3.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d"
 
+[[package]]
+name = "syn"
+version = "2.0.29"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c324c494eba9d92503e6f1ef2e6df781e78f6a7705a0202d9801b198807d518a"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
 [[package]]
 name = "term_grid"
 version = "0.1.7"
@@ -435,6 +467,12 @@ dependencies = [
  "matches",
 ]
 
+[[package]]
+name = "unicode-ident"
+version = "1.0.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c"
+
 [[package]]
 name = "unicode-normalization"
 version = "0.1.17"

+ 1 - 8
Cargo.toml

@@ -45,6 +45,7 @@ log = "0.4"
 natord = "1.0"
 num_cpus = "1.16"
 number_prefix = "0.4"
+phf = { version = "0.11.2", features = ["macros"]}
 scoped_threadpool = "0.1"
 term_grid = "0.1"
 terminal_size = "0.2.6"
@@ -62,10 +63,6 @@ version = "0.18"
 optional = true
 default-features = false
 
-[dependencies.phf]
-version = "0.11.2"
-default-features = false
-
 [target.'cfg(unix)'.dependencies]
 uzers = "0.11.2"
 
@@ -73,10 +70,6 @@ uzers = "0.11.2"
 version = "0.5.2"
 default-features = false
 
-[build-dependencies.phf_codegen]
-version = "0.11.2"
-default-features = false
-
 [features]
 default = [ "git" ]
 git = [ "git2" ]

+ 3 - 664
build.rs

@@ -20,13 +20,6 @@ use datetime::{LocalDateTime, ISO};
 
 /// The build script entry point.
 fn main() -> io::Result<()> {
-    create_version_string_file()?;
-    create_file_typing_hash_file()?;
-    create_file_icon_hash_file()
-}
-
-/// Create the version_string.txt file
-fn create_version_string_file() -> io::Result<()> {
     #![allow(clippy::write_with_newline)]
 
     let tagline = "eza - A modern, maintained replacement for ls";
@@ -49,7 +42,9 @@ fn create_version_string_file() -> io::Result<()> {
 
     // Bland version text
     let mut f = File::create(path).unwrap_or_else(|_| { panic!("{}", path.to_string_lossy().to_string()) });
-    writeln!(f, "{}", strip_codes(&ver))
+    writeln!(f, "{}", strip_codes(&ver))?;
+
+    Ok(())
 }
 
 /// Removes escape codes from a string.
@@ -126,659 +121,3 @@ fn build_date() -> String {
     let now = LocalDateTime::now();
     format!("{}", now.date().iso())
 }
-
-/// Create the perfect hashing for file typing
-fn create_file_typing_hash_file() -> io::Result<()> {
-    let path = &PathBuf::from(env::var("OUT_DIR").unwrap()).join("filetype_maps.rs");
-    let mut file = io::BufWriter::new(File::create(path).unwrap_or_else(|_| {
-        panic!("{}", path.to_string_lossy().to_string())
-    }));
-    generate_filename_type_map(file.get_mut())?;
-    generate_extension_type_map(file.get_mut())?;
-    file.flush()
-}
-
-/// Create the perfect hashing for file icons
-fn create_file_icon_hash_file() -> io::Result<()> {
-    let path = &PathBuf::from(env::var("OUT_DIR").unwrap()).join("icon_maps.rs");
-    let mut file = io::BufWriter::new(File::create(path).unwrap_or_else(|_| {
-        panic!("{}", path.to_string_lossy().to_string());
-    }));
-    generate_filename_icon_map(file.get_mut())?;
-    generate_extension_icon_map(file.get_mut())?;
-    file.flush()
-}
-
-/// Generate mapping from full filenames to file type. For file types see info/filetype.rs
-fn generate_filename_type_map(file: &mut File) -> io::Result<()> {
-    writeln!(file, "#[allow(clippy::unreadable_literal)]")?;
-    writeln!(file, "static FILENAME_TYPES: phf::Map<&'static str, FileType> = {};\n",
-             phf_codegen::Map::new()
-                 /* Immediate file - kick off the build of a project */
-                 .entry("Brewfile",          "FileType::Immediate")
-                 .entry("bsconfig.json",     "FileType::Immediate")
-                 .entry("BUILD",             "FileType::Immediate")
-                 .entry("BUILD.bazel",       "FileType::Immediate")
-                 .entry("build.gradle",      "FileType::Immediate")
-                 .entry("build.sbt",         "FileType::Immediate")
-                 .entry("build.xml",         "FileType::Immediate")
-                 .entry("Cargo.lock",        "FileType::Immediate")
-                 .entry("Cargo.toml",        "FileType::Immediate")
-                 .entry("CMakeLists.txt",    "FileType::Immediate")
-                 .entry("composer.json",     "FileType::Immediate")
-                 .entry("configure.ac",      "FileType::Immediate")
-                 .entry("Configure.ac",      "FileType::Immediate")
-                 .entry("Containerfile",     "FileType::Immediate")
-                 .entry("Dockerfile",        "FileType::Immediate")
-                 .entry("Earthfile",         "FileType::Immediate")
-                 .entry("flake.lock",        "FileType::Immediate")
-                 .entry("flake.nix",         "FileType::Immediate")
-                 .entry("Gemfile",           "FileType::Immediate")
-                 .entry("GNUmakefile",       "FileType::Immediate")
-                 .entry("Gruntfile.coffee",  "FileType::Immediate")
-                 .entry("Gruntfile.js",      "FileType::Immediate")
-                 .entry("Justfile",          "FileType::Immediate")
-                 .entry("justfile",          "FileType::Immediate")
-                 .entry("Makefile",          "FileType::Immediate")
-                 .entry("makefile",          "FileType::Immediate")
-                 .entry("Makefile.in",       "FileType::Immediate")
-                 .entry("makefile.in",       "FileType::Immediate")
-                 .entry("meson.build",       "FileType::Immediate")
-                 .entry("mix.exs",           "FileType::Immediate")
-                 .entry("package.json",      "FileType::Immediate")
-                 .entry("Pipfile",           "FileType::Immediate")
-                 .entry("PKGBUILD",          "FileType::Immediate")
-                 .entry("Podfile",           "FileType::Immediate")
-                 .entry("pom.xml",           "FileType::Immediate")
-                 .entry("Procfile",          "FileType::Immediate")
-                 .entry("Rakefile",          "FileType::Immediate")
-                 .entry("RoboFile.php",      "FileType::Immediate")
-                 .entry("SConstruct",        "FileType::Immediate")
-                 .entry("tsconfig.json",     "FileType::Immediate")
-                 .entry("Vagrantfile",       "FileType::Immediate")
-                 .entry("webpack.config.cjs","FileType::Immediate")
-                 .entry("webpack.config.js", "FileType::Immediate")
-                 .entry("WORKSPACE",         "FileType::Immediate")
-                 .build()
-    )
-}
-
-/// Generate mapping from lowercase file extension to file type.  If an image, video, music, or
-/// lossless extension is added also update the extension icon map. For file types see
-/// info/filetype.rs
-fn generate_extension_type_map(file: &mut File) -> io::Result<()> {
-    // Extension are converted to lower case for comparison
-    writeln!(file, "#[allow(clippy::unreadable_literal)]")?;
-    writeln!(file, "static EXTENSION_TYPES: phf::Map<&'static str, FileType> = {};\n",
-             phf_codegen::Map::new()
-                 /* Immediate file - kick off the build of a project */
-                 .entry("ninja",     "FileType::Immediate")
-                 /* Image files */
-                 .entry("arw",       "FileType::Image")
-                 .entry("avif",      "FileType::Image")
-                 .entry("bmp",       "FileType::Image")
-                 .entry("cbr",       "FileType::Image")
-                 .entry("cbz",       "FileType::Image")
-                 .entry("cr2",       "FileType::Image")
-                 .entry("dvi",       "FileType::Image")
-                 .entry("eps",       "FileType::Image")
-                 .entry("gif",       "FileType::Image")
-                 .entry("heif",      "FileType::Image")
-                 .entry("ico",       "FileType::Image")
-                 .entry("j2c",       "FileType::Image")
-                 .entry("j2k",       "FileType::Image")
-                 .entry("jfi",       "FileType::Image")
-                 .entry("jfif",      "FileType::Image")
-                 .entry("jif",       "FileType::Image")
-                 .entry("jp2",       "FileType::Image")
-                 .entry("jpe",       "FileType::Image")
-                 .entry("jpeg",      "FileType::Image")
-                 .entry("jpf",       "FileType::Image")
-                 .entry("jpg",       "FileType::Image")
-                 .entry("jpx",       "FileType::Image")
-                 .entry("jxl",       "FileType::Image")
-                 .entry("nef",       "FileType::Image")
-                 .entry("orf",       "FileType::Image")
-                 .entry("pbm",       "FileType::Image")
-                 .entry("pgm",       "FileType::Image")
-                 .entry("png",       "FileType::Image")
-                 .entry("pnm",       "FileType::Image")
-                 .entry("ppm",       "FileType::Image")
-                 .entry("ps",        "FileType::Image")
-                 .entry("pxm",       "FileType::Image")
-                 .entry("raw",       "FileType::Image")
-                 .entry("stl",       "FileType::Image")
-                 .entry("svg",       "FileType::Image")
-                 .entry("tif",       "FileType::Image")
-                 .entry("tiff",      "FileType::Image")
-                 .entry("webp",      "FileType::Image")
-                 .entry("xpm",       "FileType::Image")
-                 /* Video files */
-                 .entry("avi",       "FileType::Video")
-                 .entry("flv",       "FileType::Video")
-                 .entry("heic",      "FileType::Video")
-                 .entry("m2ts",      "FileType::Video")
-                 .entry("m2v",       "FileType::Video")
-                 .entry("m4v",       "FileType::Video")
-                 .entry("mkv",       "FileType::Video")
-                 .entry("mov",       "FileType::Video")
-                 .entry("mp4",       "FileType::Video")
-                 .entry("mpeg",      "FileType::Video")
-                 .entry("mpg",       "FileType::Video")
-                 .entry("ogm",       "FileType::Video")
-                 .entry("ogv",       "FileType::Video")
-                 .entry("vob",       "FileType::Video")
-                 .entry("webm",      "FileType::Video")
-                 .entry("wmv",       "FileType::Video")
-                 /* Music files */
-                 .entry("aac",       "FileType::Music")
-                 .entry("m4a",       "FileType::Music")
-                 .entry("mka",       "FileType::Music")
-                 .entry("mp2",       "FileType::Music")
-                 .entry("mp3",       "FileType::Music")
-                 .entry("ogg",       "FileType::Music")
-                 .entry("opus",      "FileType::Music")
-                 .entry("wma",       "FileType::Music")
-                 /* Lossless music, rather than any other kind of data... */
-                 .entry("alac",      "FileType::Lossless")
-                 .entry("ape",       "FileType::Lossless")
-                 .entry("flac",      "FileType::Lossless")
-                 .entry("wav",       "FileType::Lossless")
-                 /* Cryptology files */
-                 .entry("asc",       "FileType::Crypto")
-                 .entry("enc",       "FileType::Crypto")
-                 .entry("gpg",       "FileType::Crypto")
-                 .entry("p12",       "FileType::Crypto")
-                 .entry("pfx",       "FileType::Crypto")
-                 .entry("pgp",       "FileType::Crypto")
-                 .entry("sig",       "FileType::Crypto")
-                 .entry("signature", "FileType::Crypto")
-                 /* Document files */
-                 .entry("djvu",      "FileType::Document")
-                 .entry("doc",       "FileType::Document")
-                 .entry("docx",      "FileType::Document")
-                 // .entry("dvi",       "FileType::Document") // already an image format
-                 .entry("eml",       "FileType::Document")
-                 // .entry("eps",       "FileType::Document") // already an image format
-                 .entry("fotd",      "FileType::Document")
-                 .entry("key",       "FileType::Document")
-                 .entry("keynote",   "FileType::Document")
-                 .entry("numbers",   "FileType::Document")
-                 .entry("odp",       "FileType::Document")
-                 .entry("odt",       "FileType::Document")
-                 .entry("pages",     "FileType::Document")
-                 .entry("pdf",       "FileType::Document")
-                 .entry("ppt",       "FileType::Document")
-                 .entry("pptx",      "FileType::Document")
-                 .entry("rtf",       "FileType::Document")
-                 .entry("xls",       "FileType::Document")
-                 .entry("xlsx",      "FileType::Document")
-                 /* Compressed/archive files */
-                 .entry("7z",        "FileType::Compressed")
-                 .entry("a",         "FileType::Compressed")
-                 .entry("ar",        "FileType::Compressed")
-                 .entry("bz",        "FileType::Compressed")
-                 .entry("bz2",       "FileType::Compressed")
-                 .entry("cpio",      "FileType::Compressed")
-                 .entry("deb",       "FileType::Compressed")
-                 .entry("dmg",       "FileType::Compressed")
-                 .entry("gz",        "FileType::Compressed")
-                 .entry("iso",       "FileType::Compressed")
-                 .entry("lz",        "FileType::Compressed")
-                 .entry("lz4",       "FileType::Compressed")
-                 .entry("lzh",       "FileType::Compressed")
-                 .entry("lzma",      "FileType::Compressed")
-                 .entry("lzo",       "FileType::Compressed")
-                 .entry("par",       "FileType::Compressed")
-                 .entry("rar",       "FileType::Compressed")
-                 .entry("rpm",       "FileType::Compressed")
-                 .entry("tar",       "FileType::Compressed")
-                 .entry("taz",       "FileType::Compressed")
-                 .entry("tbz",       "FileType::Compressed")
-                 .entry("tbz2",      "FileType::Compressed")
-                 .entry("tc",        "FileType::Compressed")
-                 .entry("tgz",       "FileType::Compressed")
-                 .entry("tlz",       "FileType::Compressed")
-                 .entry("txz",       "FileType::Compressed")
-                 .entry("tz",        "FileType::Compressed")
-                 .entry("tzo",       "FileType::Compressed")
-                 .entry("xz",        "FileType::Compressed")
-                 .entry("z",         "FileType::Compressed")
-                 .entry("zip",       "FileType::Compressed")
-                 .entry("zst",       "FileType::Compressed")
-                 /* Temporary files */
-                 .entry("bak",       "FileType::Temp")
-                 .entry("bk",        "FileType::Temp")
-                 .entry("bkp",       "FileType::Temp")
-                 .entry("swn",       "FileType::Temp")
-                 .entry("swo",       "FileType::Temp")
-                 .entry("swp",       "FileType::Temp")
-                 .entry("tmp",       "FileType::Temp")
-                 /* Compiler output files */
-                 .entry("class",     "FileType::Compiled")
-                 .entry("elc",       "FileType::Compiled")
-                 .entry("hi",        "FileType::Compiled")
-                 .entry("ko",        "FileType::Compiled")
-                 .entry("o",         "FileType::Compiled")
-                 .entry("pyc",       "FileType::Compiled")
-                 .entry("zwc",       "FileType::Compiled")
-                 .build()
-    )
-}
-
-/// Generate mapping from full filenames to file type. This mapping should also contain all the
-/// "dot" directories that have a custom icon.  See output/render/icons.rs for a partial list of
-/// icon constants.
-fn generate_filename_icon_map(file: &mut File) -> io::Result<()> {
-    writeln!(file, "#[allow(clippy::unreadable_literal)]")?;
-    writeln!(file, "static FILENAME_ICONS: phf::Map<&'static str, char> = {};\n",
-             phf_codegen::Map::new()
-                 .entry(".atom",              "'\u{e764}'") // 
-                 .entry(".bashprofile",       "'\u{e615}'") // 
-                 .entry(".bashrc",            "'\u{f489}'") // 
-                 .entry(".emacs",             "'\u{e632}'") // 
-                 .entry(".git",               "'\u{f1d3}'") // 
-                 .entry(".gitattributes",     "'\u{f1d3}'") // 
-                 .entry(".gitconfig",         "'\u{f1d3}'") // 
-                 .entry(".github",            "'\u{f408}'") // 
-                 .entry(".gitignore",         "'\u{f1d3}'") // 
-                 .entry(".gitignore_global",  "'\u{f1d3}'") // 
-                 .entry(".gitmodules",        "'\u{f1d3}'") // 
-                 .entry(".idea",              "'\u{e7b5}'") // 
-                 .entry(".rvm",               "'\u{e21e}'") // 
-                 .entry(".Trash",             "'\u{f1f8}'") // 
-                 .entry(".vimrc",             "'\u{e7c5}'") // 
-                 .entry(".vscode",            "'\u{e70c}'") // 
-                 .entry(".zshrc",             "'\u{f489}'") // 
-                 .entry("bin",                "'\u{e5fc}'") // 
-                 .entry("Cargo.lock",         "'\u{e7a8}'") // 
-                 .entry("config",             "'\u{e5fc}'") // 
-                 .entry("docker-compose.yml", "'\u{f308}'") // 
-                 .entry("Dockerfile",         "'\u{f308}'") // 
-                 .entry("ds_store",           "'\u{f179}'") // 
-                 .entry("Earthfile",          "'\u{f0ac}'") // 
-                 .entry("gitignore_global",   "'\u{f1d3}'") // 
-                 .entry("gitlab-ci.yml",      "'\u{f296}'") // 
-                 .entry("go.mod",             "'\u{e626}'") // 
-                 .entry("go.sum",             "'\u{e626}'") // 
-                 .entry("gradle",             "'\u{e256}'") // 
-                 .entry("gruntfile.coffee",   "'\u{e611}'") // 
-                 .entry("gruntfile.js",       "'\u{e611}'") // 
-                 .entry("gruntfile.ls",       "'\u{e611}'") // 
-                 .entry("gulpfile.coffee",    "'\u{e610}'") // 
-                 .entry("gulpfile.js",        "'\u{e610}'") // 
-                 .entry("gulpfile.ls",        "'\u{e610}'") // 
-                 .entry("hidden",             "'\u{f023}'") // 
-                 .entry("include",            "'\u{e5fc}'") // 
-                 .entry("lib",                "'\u{f121}'") // 
-                 .entry("LICENSE",            "'\u{f02d}'") // 
-                 .entry("localized",          "'\u{f179}'") // 
-                 .entry("Makefile",           "'\u{f489}'") // 
-                 .entry("node_modules",       "'\u{e718}'") // 
-                 .entry("npmignore",          "'\u{e71e}'") // 
-                 .entry("PKGBUILD",           "'\u{f303}'") // 
-                 .entry("rubydoc",            "'\u{e73b}'") // 
-                 .entry("Vagrantfile",        "'\u{2371}'") // ⍱
-                 .entry("yarn.lock",          "'\u{e718}'") // 
-                 .build()
-    )
-}
-
-/// Generate mapping from lowercase file extension to icons.  If an image, video, or audio
-/// extension is add also update the extension filetype map.  See output/render/icons.rs for
-/// a partial list of icon constants.
-fn generate_extension_icon_map(file: &mut File) -> io::Result<()> {
-    writeln!(file, "#[allow(clippy::unreadable_literal)]")?;
-    writeln!(file, "static EXTENSION_ICONS: phf::Map<&'static str, char> = {};\n",
-             phf_codegen::Map::new()
-                 .entry("7z",            "'\u{f410}'")  // 
-                 .entry("a",             "'\u{f17c}'")  // 
-                 .entry("acc",           "'\u{f001}'")  // 
-                 .entry("acf",           "'\u{f1b6}'")  // 
-                 .entry("ai",            "'\u{e7b4}'")  // 
-                 .entry("alac",          "'\u{f001}'")  // 
-                 .entry("android",       "'\u{e70e}'")  // 
-                 .entry("ape",           "'\u{f001}'")  // 
-                 .entry("apk",           "'\u{e70e}'")  // 
-                 .entry("apple",         "'\u{f179}'")  // 
-                 .entry("ar",            "'\u{f410}'")  // 
-                 .entry("arw",           "'\u{f1c5}'")  // 
-                 .entry("asm",           "'\u{e637}'")  // 
-                 .entry("avi",           "'\u{f03d}'")  // 
-                 .entry("avif",          "'\u{f1c5}'")  // 
-                 .entry("avro",          "'\u{e60b}'")  // 
-                 .entry("awk",           "'\u{f489}'")  // 
-                 .entry("bash",          "'\u{f489}'")  // 
-                 .entry("bashrc",        "'\u{f489}'")  // 
-                 .entry("bash_history",  "'\u{f489}'")  // 
-                 .entry("bash_profile",  "'\u{f489}'")  // 
-                 .entry("bat",           "'\u{ebc4}'")  // 
-                 .entry("bats",          "'\u{f489}'")  // 
-                 .entry("bib",           "'\u{e69b}'")  // 
-                 .entry("bin",           "'\u{eae8}'")  // 
-                 .entry("bmp",           "'\u{f1c5}'")  // 
-                 .entry("bst",           "'\u{e69b}'")  // 
-                 .entry("bz",            "'\u{f410}'")  // 
-                 .entry("bz2",           "'\u{f410}'")  // 
-                 .entry("c",             "'\u{e61e}'")  // 
-                 .entry("c++",           "'\u{e61d}'")  // 
-                 .entry("cab",           "'\u{e70f}'")  // 
-                 .entry("cbr",           "'\u{f1c5}'")  // 
-                 .entry("cbz",           "'\u{f1c5}'")  // 
-                 .entry("cc",            "'\u{e61d}'")  // 
-                 .entry("cert",          "'\u{eafa}'")  // 
-                 .entry("cfg",           "'\u{e615}'")  // 
-                 .entry("cjs",           "'\u{e74e}'")  // 
-                 .entry("class",         "'\u{e256}'")  // 
-                 .entry("clj",           "'\u{e768}'")  // 
-                 .entry("cljs",          "'\u{e76a}'")  // 
-                 .entry("cls",           "'\u{e69b}'")  // 
-                 .entry("cmd",           "'\u{e70f}'")  // 
-                 .entry("coffee",        "'\u{f0f4}'")  // 
-                 .entry("conf",          "'\u{e615}'")  // 
-                 .entry("config",        "'\u{e615}'")  // 
-                 .entry("cp",            "'\u{e61d}'")  // 
-                 .entry("cpio",          "'\u{f410}'")  // 
-                 .entry("cpp",           "'\u{e61d}'")  // 
-                 .entry("cr2",           "'\u{f1c5}'")  // 
-                 .entry("crt",           "'\u{eafa}'")  // 
-                 .entry("cs",            "'\u{f031b}'") // 󰌛
-                 .entry("csh",           "'\u{f489}'")  // 
-                 .entry("cshtml",        "'\u{f1fa}'")  // 
-                 .entry("csproj",        "'\u{f031b}'") // 󰌛
-                 .entry("css",           "'\u{e749}'")  // 
-                 .entry("csv",           "'\u{f1c3}'")  // 
-                 .entry("csx",           "'\u{f031b}'") // 󰌛
-                 .entry("cts",           "'\u{e628}'")  // 
-                 .entry("cu",            "'\u{e64b}'")  // 
-                 .entry("cxx",           "'\u{e61d}'")  // 
-                 .entry("d",             "'\u{e7af}'")  // 
-                 .entry("dart",          "'\u{e798}'")  // 
-                 .entry("db",            "'\u{f1c0}'")  // 
-                 .entry("deb",           "'\u{e77d}'")  // 
-                 .entry("desktop",       "'\u{ebd1}'")  // 
-                 .entry("diff",          "'\u{f440}'")  // 
-                 .entry("djvu",          "'\u{f02d}'")  // 
-                 .entry("dll",           "'\u{e70f}'")  // 
-                 .entry("dmg",           "'\u{e271}'")  // 
-                 .entry("doc",           "'\u{f1c2}'")  // 
-                 .entry("docx",          "'\u{f1c2}'")  // 
-                 .entry("drawio",        "'\u{ebba}'")  // 
-                 .entry("ds_store",      "'\u{f179}'")  // 
-                 .entry("dump",          "'\u{f1c0}'")  // 
-                 .entry("dvi",           "'\u{f1c5}'")  // 
-                 .entry("ebook",         "'\u{e28b}'")  // 
-                 .entry("ebuild",        "'\u{f30d}'")  // 
-                 .entry("editorconfig",  "'\u{e615}'")  // 
-                 .entry("ejs",           "'\u{e618}'")  // 
-                 .entry("el",            "'\u{e632}'")  // 
-                 .entry("elm",           "'\u{e62c}'")  // 
-                 .entry("eml",           "'\u{f003}'")  // 
-                 .entry("env",           "'\u{f462}'")  // 
-                 .entry("eot",           "'\u{f031}'")  // 
-                 .entry("eps",           "'\u{f1c5}'")  // 
-                 .entry("epub",          "'\u{e28a}'")  // 
-                 .entry("erb",           "'\u{e73b}'")  // 
-                 .entry("erl",           "'\u{e7b1}'")  // 
-                 .entry("ex",            "'\u{e62d}'")  // 
-                 .entry("exe",           "'\u{f17a}'")  // 
-                 .entry("exs",           "'\u{e62d}'")  // 
-                 .entry("fish",          "'\u{f489}'")  // 
-                 .entry("flac",          "'\u{f001}'")  // 
-                 .entry("flv",           "'\u{f03d}'")  // 
-                 .entry("font",          "'\u{f031}'")  // 
-                 .entry("fs",            "'\u{e7a7}'")  // 
-                 .entry("fsi",           "'\u{e7a7}'")  // 
-                 .entry("fsx",           "'\u{e7a7}'")  // 
-                 .entry("gdoc",          "'\u{f1c2}'")  // 
-                 .entry("gem",           "'\u{e21e}'")  // 
-                 .entry("gemfile",       "'\u{e21e}'")  // 
-                 .entry("gemspec",       "'\u{e21e}'")  // 
-                 .entry("gform",         "'\u{f298}'")  // 
-                 .entry("gif",           "'\u{f1c5}'")  // 
-                 .entry("git",           "'\u{f1d3}'")  // 
-                 .entry("gitattributes", "'\u{f1d3}'")  // 
-                 .entry("gitignore",     "'\u{f1d3}'")  // 
-                 .entry("gitmodules",    "'\u{f1d3}'")  // 
-                 .entry("go",            "'\u{e626}'")  // 
-                 .entry("gpg",           "'\u{e60a}'")  // 
-                 .entry("gradle",        "'\u{e256}'")  // 
-                 .entry("groovy",        "'\u{e775}'")  // 
-                 .entry("gsheet",        "'\u{f1c3}'")  // 
-                 .entry("gslides",       "'\u{f1c4}'")  // 
-                 .entry("guardfile",     "'\u{e21e}'")  // 
-                 .entry("gz",            "'\u{f410}'")  // 
-                 .entry("h",             "'\u{f0fd}'")  // 
-                 .entry("hbs",           "'\u{e60f}'")  // 
-                 .entry("heic",          "'\u{f03d}'")  // 
-                 .entry("heif",          "'\u{f1c5}'")  // 
-                 .entry("hpp",           "'\u{f0fd}'")  // 
-                 .entry("hs",            "'\u{e777}'")  // 
-                 .entry("htm",           "'\u{f13b}'")  // 
-                 .entry("html",          "'\u{f13b}'")  // 
-                 .entry("hxx",           "'\u{f0fd}'")  // 
-                 .entry("ical",          "'\u{eab0}'")  // 
-                 .entry("icalendar",     "'\u{eab0}'")  // 
-                 .entry("ico",           "'\u{f1c5}'")  // 
-                 .entry("ics",           "'\u{eab0}'")  // 
-                 .entry("ifb",           "'\u{eab0}'")  // 
-                 .entry("image",         "'\u{f1c5}'")  // 
-                 .entry("img",           "'\u{e271}'")  // 
-                 .entry("iml",           "'\u{e7b5}'")  // 
-                 .entry("ini",           "'\u{f17a}'")  // 
-                 .entry("ipynb",         "'\u{e678}'")  // 
-                 .entry("iso",           "'\u{e271}'")  // 
-                 .entry("j2c",           "'\u{f1c5}'")  // 
-                 .entry("j2k",           "'\u{f1c5}'")  // 
-                 .entry("jad",           "'\u{e256}'")  // 
-                 .entry("jar",           "'\u{e256}'")  // 
-                 .entry("java",          "'\u{e256}'")  // 
-                 .entry("jfi",           "'\u{f1c5}'")  // 
-                 .entry("jfif",          "'\u{f1c5}'")  // 
-                 .entry("jif",           "'\u{f1c5}'")  // 
-                 .entry("jl",            "'\u{e624}'")  // 
-                 .entry("jmd",           "'\u{f48a}'")  // 
-                 .entry("jp2",           "'\u{f1c5}'")  // 
-                 .entry("jpe",           "'\u{f1c5}'")  // 
-                 .entry("jpeg",          "'\u{f1c5}'")  // 
-                 .entry("jpf",           "'\u{f1c5}'")  // 
-                 .entry("jpg",           "'\u{f1c5}'")  // 
-                 .entry("jpx",           "'\u{f1c5}'")  // 
-                 .entry("js",            "'\u{e74e}'")  // 
-                 .entry("json",          "'\u{e60b}'")  // 
-                 .entry("jsx",           "'\u{e7ba}'")  // 
-                 .entry("jxl",           "'\u{f1c5}'")  // 
-                 .entry("kdb",           "'\u{f23e}'")  // 
-                 .entry("kdbx",          "'\u{f23e}'")  // 
-                 .entry("key",           "'\u{eb11}'")  // 
-                 .entry("ko",            "'\u{f17c}'")  // 
-                 .entry("ksh",           "'\u{f489}'")  // 
-                 .entry("latex",         "'\u{e69b}'")  // 
-                 .entry("less",          "'\u{e758}'")  // 
-                 .entry("lhs",           "'\u{e777}'")  // 
-                 .entry("license",       "'\u{f02d}'")  // 
-                 .entry("localized",     "'\u{f179}'")  // 
-                 .entry("lock",          "'\u{f023}'")  // 
-                 .entry("log",           "'\u{f18d}'")  // 
-                 .entry("lua",           "'\u{e620}'")  // 
-                 .entry("lz",            "'\u{f410}'")  // 
-                 .entry("lz4",           "'\u{f410}'")  // 
-                 .entry("lzh",           "'\u{f410}'")  // 
-                 .entry("lzma",          "'\u{f410}'")  // 
-                 .entry("lzo",           "'\u{f410}'")  // 
-                 .entry("m",             "'\u{e61e}'")  // 
-                 .entry("m2ts",          "'\u{f03d}'")  // 
-                 .entry("m2v",           "'\u{f03d}'")  // 
-                 .entry("m4a",           "'\u{f001}'")  // 
-                 .entry("m4v",           "'\u{f03d}'")  // 
-                 .entry("magnet",        "'\u{f076}'")  // 
-                 .entry("markdown",      "'\u{f48a}'")  // 
-                 .entry("md",            "'\u{f48a}'")  // 
-                 .entry("mjs",           "'\u{e74e}'")  // 
-                 .entry("mk",            "'\u{f489}'")  // 
-                 .entry("mka",           "'\u{f001}'")  // 
-                 .entry("mkd",           "'\u{f48a}'")  // 
-                 .entry("mkv",           "'\u{f03d}'")  // 
-                 .entry("ml",            "'\u{e67a}'")  // 
-                 .entry("mli",           "'\u{e67a}'")  // 
-                 .entry("mll",           "'\u{e67a}'")  // 
-                 .entry("mly",           "'\u{e67a}'")  // 
-                 .entry("mm",            "'\u{e61d}'")  // 
-                 .entry("mobi",          "'\u{e28b}'")  // 
-                 .entry("mov",           "'\u{f03d}'")  // 
-                 .entry("mp2",           "'\u{f001}'")  // 
-                 .entry("mp3",           "'\u{f001}'")  // 
-                 .entry("mp4",           "'\u{f03d}'")  // 
-                 .entry("mpeg",          "'\u{f03d}'")  // 
-                 .entry("mpg",           "'\u{f03d}'")  // 
-                 .entry("msi",           "'\u{e70f}'")  // 
-                 .entry("mts",           "'\u{e628}'")  // 
-                 .entry("mustache",      "'\u{e60f}'")  // 
-                 .entry("nef",           "'\u{f1c5}'")  // 
-                 .entry("ninja",         "'\u{f0774}'") // 󰝴
-                 .entry("nix",           "'\u{f313}'")  // 
-                 .entry("node",          "'\u{f0399}'") // 󰎙
-                 .entry("npmignore",     "'\u{e71e}'")  // 
-                 .entry("o",             "'\u{eae8}'")  // 
-                 .entry("odp",           "'\u{f1c4}'")  // 
-                 .entry("ods",           "'\u{f1c3}'")  // 
-                 .entry("odt",           "'\u{f1c2}'")  // 
-                 .entry("ogg",           "'\u{f001}'")  // 
-                 .entry("ogm",           "'\u{f03d}'")  // 
-                 .entry("ogv",           "'\u{f03d}'")  // 
-                 .entry("opus",          "'\u{f001}'")  // 
-                 .entry("orf",           "'\u{f1c5}'")  // 
-                 .entry("org",           "'\u{e633}'")  // 
-                 .entry("otf",           "'\u{f031}'")  // 
-                 .entry("out",           "'\u{eb2c}'")  // 
-                 .entry("par",           "'\u{f410}'")  // 
-                 .entry("part",          "'\u{f43a}'")  // 
-                 .entry("patch",         "'\u{f440}'")  // 
-                 .entry("pbm",           "'\u{f1c5}'")  // 
-                 .entry("pdf",           "'\u{f1c1}'")  // 
-                 .entry("pem",           "'\u{eb11}'")  // 
-                 .entry("pgm",           "'\u{f1c5}'")  // 
-                 .entry("php",           "'\u{e73d}'")  // 
-                 .entry("pl",            "'\u{e769}'")  // 
-                 .entry("plx",           "'\u{e769}'")  // 
-                 .entry("pm",            "'\u{e769}'")  // 
-                 .entry("png",           "'\u{f1c5}'")  // 
-                 .entry("pnm",           "'\u{f1c5}'")  // 
-                 .entry("pod",           "'\u{e769}'")  // 
-                 .entry("ppm",           "'\u{f1c5}'")  // 
-                 .entry("ppt",           "'\u{f1c4}'")  // 
-                 .entry("pptx",          "'\u{f1c4}'")  // 
-                 .entry("procfile",      "'\u{e21e}'")  // 
-                 .entry("properties",    "'\u{e60b}'")  // 
-                 .entry("ps",            "'\u{f1c5}'")  // 
-                 .entry("ps1",           "'\u{ebc7}'")  // 
-                 .entry("psd",           "'\u{e7b8}'")  // 
-                 .entry("psd1",          "'\u{ebc7}'")  // 
-                 .entry("psm1",          "'\u{ebc7}'")  // 
-                 .entry("pxm",           "'\u{f1c5}'")  // 
-                 .entry("py",            "'\u{e606}'")  // 
-                 .entry("pyc",           "'\u{e606}'")  // 
-                 .entry("qcow2",         "'\u{e271}'")  // 
-                 .entry("r",             "'\u{f25d}'")  // 
-                 .entry("rakefile",      "'\u{e21e}'")  // 
-                 .entry("rar",           "'\u{f410}'")  // 
-                 .entry("raw",           "'\u{f1c5}'")  // 
-                 .entry("razor",         "'\u{f1fa}'")  // 
-                 .entry("rb",            "'\u{e21e}'")  // 
-                 .entry("rdata",         "'\u{f25d}'")  // 
-                 .entry("rdb",           "'\u{e76d}'")  // 
-                 .entry("rdoc",          "'\u{f48a}'")  // 
-                 .entry("rds",           "'\u{f25d}'")  // 
-                 .entry("readme",        "'\u{f48a}'")  // 
-                 .entry("rlib",          "'\u{e7a8}'")  // 
-                 .entry("rmd",           "'\u{f48a}'")  // 
-                 .entry("rmeta",         "'\u{e7a8}'")  // 
-                 .entry("rpm",           "'\u{e7bb}'")  // 
-                 .entry("rs",            "'\u{e7a8}'")  // 
-                 .entry("rspec",         "'\u{e21e}'")  // 
-                 .entry("rspec_parallel","'\u{e21e}'")  // 
-                 .entry("rspec_status",  "'\u{e21e}'")  // 
-                 .entry("rss",           "'\u{f09e}'")  // 
-                 .entry("rst",           "'\u{f15c}'")  // 
-                 .entry("rtf",           "'\u{f0219}'") // 󰈙
-                 .entry("ru",            "'\u{e21e}'")  // 
-                 .entry("rubydoc",       "'\u{e73b}'")  // 
-                 .entry("s",             "'\u{e637}'")  // 
-                 .entry("sass",          "'\u{e603}'")  // 
-                 .entry("scala",         "'\u{e737}'")  // 
-                 .entry("scss",          "'\u{e749}'")  // 
-                 .entry("service",       "'\u{eba2}'")  // 
-                 .entry("sh",            "'\u{f489}'")  // 
-                 .entry("shell",         "'\u{f489}'")  // 
-                 .entry("slim",          "'\u{e73b}'")  // 
-                 .entry("sln",           "'\u{e70c}'")  // 
-                 .entry("so",            "'\u{f17c}'")  // 
-                 .entry("sql",           "'\u{f1c0}'")  // 
-                 .entry("sqlite3",       "'\u{e7c4}'")  // 
-                 .entry("stl",           "'\u{f1c5}'")  // 
-                 .entry("sty",           "'\u{e69b}'")  // 
-                 .entry("styl",          "'\u{e600}'")  // 
-                 .entry("stylus",        "'\u{e600}'")  // 
-                 .entry("svelte",        "'\u{e697}'")  // 
-                 .entry("svg",           "'\u{f1c5}'")  // 
-                 .entry("swift",         "'\u{e755}'")  // 
-                 .entry("t",             "'\u{e769}'")  // 
-                 .entry("tar",           "'\u{f410}'")  // 
-                 .entry("taz",           "'\u{f410}'")  // 
-                 .entry("tbz",           "'\u{f410}'")  // 
-                 .entry("tbz2",          "'\u{f410}'")  // 
-                 .entry("tc",            "'\u{f410}'")  // 
-                 .entry("tex",           "'\u{e69b}'")  // 
-                 .entry("tgz",           "'\u{f410}'")  // 
-                 .entry("tif",           "'\u{f1c5}'")  // 
-                 .entry("tiff",          "'\u{f1c5}'")  // 
-                 .entry("tlz",           "'\u{f410}'")  // 
-                 .entry("toml",          "'\u{e615}'")  // 
-                 .entry("torrent",       "'\u{e275}'")  // 
-                 .entry("ts",            "'\u{e628}'")  // 
-                 .entry("tsv",           "'\u{f1c3}'")  // 
-                 .entry("tsx",           "'\u{e7ba}'")  // 
-                 .entry("ttf",           "'\u{f031}'")  // 
-                 .entry("twig",          "'\u{e61c}'")  // 
-                 .entry("txt",           "'\u{f15c}'")  // 
-                 .entry("txz",           "'\u{f410}'")  // 
-                 .entry("tz",            "'\u{f410}'")  // 
-                 .entry("tzo",           "'\u{f410}'")  // 
-                 .entry("unity",         "'\u{e721}'")  // 
-                 .entry("unity3d",       "'\u{e721}'")  // 
-                 .entry("vdi",           "'\u{e271}'")  // 
-                 .entry("vhd",           "'\u{e271}'")  // 
-                 .entry("video",         "'\u{f03d}'")  // 
-                 .entry("vim",           "'\u{e7c5}'")  // 
-                 .entry("vmdk",          "'\u{e271}'")  // 
-                 .entry("vob",           "'\u{f03d}'")  // 
-                 .entry("vue",           "'\u{f0844}'") // 󰡄
-                 .entry("war",           "'\u{e256}'")  // 
-                 .entry("wav",           "'\u{f001}'")  // 
-                 .entry("webm",          "'\u{f03d}'")  // 
-                 .entry("webp",          "'\u{f1c5}'")  // 
-                 .entry("windows",       "'\u{f17a}'")  // 
-                 .entry("wma",           "'\u{f001}'")  // 
-                 .entry("wmv",           "'\u{f03d}'")  // 
-                 .entry("woff",          "'\u{f031}'")  // 
-                 .entry("woff2",         "'\u{f031}'")  // 
-                 .entry("xhtml",         "'\u{f13b}'")  // 
-                 .entry("xls",           "'\u{f1c3}'")  // 
-                 .entry("xlsm",          "'\u{f1c3}'")  // 
-                 .entry("xlsx",          "'\u{f1c3}'")  // 
-                 .entry("xml",           "'\u{f05c0}'") // 󰗀
-                 .entry("xpm",           "'\u{f1c5}'")  // 
-                 .entry("xul",           "'\u{f05c0}'") // 󰗀
-                 .entry("xz",            "'\u{f410}'")  // 
-                 .entry("yaml",          "'\u{f481}'")  // 
-                 .entry("yml",           "'\u{f481}'")  // 
-                 .entry("z",             "'\u{f410}'")  // 
-                 .entry("zig",           "'\u{21af}'")  // ↯
-                 .entry("zip",           "'\u{f410}'")  // 
-                 .entry("zsh",           "'\u{f489}'")  // 
-                 .entry("zsh-theme",     "'\u{f489}'")  // 
-                 .entry("zshrc",         "'\u{f489}'")  // 
-                 .entry("zst",           "'\u{f410}'")  // 
-                 .build()
-    )
-}

+ 207 - 8
src/info/filetype.rs

@@ -8,7 +8,7 @@
 //! Please keep these lists sorted. If you're using vim, :sort i
 
 use ansi_term::Style;
-use phf;
+use phf::{phf_map, Map};
 
 use crate::fs::File;
 use crate::theme::FileColours;
@@ -24,16 +24,215 @@ enum FileType {
     Compressed,
     Temp,
     Compiled,
-    // An “immediate” file is something that can be run or activated somehow
-    // in order to kick off the build of a project. It’s usually only present
-    // in directories full of source code.
-    Immediate
+    Immediate // An “immediate” file is something that can be run or activated somehow in order to
+              // kick off the build of a project. It’s usually only present in directories full of
+              // source code.
 }
 
-// See build.rs for EXTENSION_TYPES and FILENAME_TYPES
-include!(concat!(env!("OUT_DIR"), "/filetype_maps.rs"));
+/// Mapping from full filenames to file type.
+const FILENAME_TYPES: Map<&'static str, FileType> = phf_map! {
+    /* Immediate file - kick off the build of a project */
+    "Brewfile"           => FileType::Immediate,
+    "bsconfig.json"      => FileType::Immediate,
+    "BUILD"              => FileType::Immediate,
+    "BUILD.bazel"        => FileType::Immediate,
+    "build.gradle"       => FileType::Immediate,
+    "build.sbt"          => FileType::Immediate,
+    "build.xml"          => FileType::Immediate,
+    "Cargo.lock"         => FileType::Immediate,
+    "Cargo.toml"         => FileType::Immediate,
+    "CMakeLists.txt"     => FileType::Immediate,
+    "composer.json"      => FileType::Immediate,
+    "configure.ac"       => FileType::Immediate,
+    "Configure.ac"       => FileType::Immediate,
+    "Containerfile"      => FileType::Immediate,
+    "Dockerfile"         => FileType::Immediate,
+    "Earthfile"          => FileType::Immediate,
+    "flake.lock"         => FileType::Immediate,
+    "flake.nix"          => FileType::Immediate,
+    "Gemfile"            => FileType::Immediate,
+    "GNUmakefile"        => FileType::Immediate,
+    "Gruntfile.coffee"   => FileType::Immediate,
+    "Gruntfile.js"       => FileType::Immediate,
+    "Justfile"           => FileType::Immediate,
+    "justfile"           => FileType::Immediate,
+    "Makefile"           => FileType::Immediate,
+    "makefile"           => FileType::Immediate,
+    "Makefile.in"        => FileType::Immediate,
+    "makefile.in"        => FileType::Immediate,
+    "meson.build"        => FileType::Immediate,
+    "mix.exs"            => FileType::Immediate,
+    "package.json"       => FileType::Immediate,
+    "Pipfile"            => FileType::Immediate,
+    "PKGBUILD"           => FileType::Immediate,
+    "Podfile"            => FileType::Immediate,
+    "pom.xml"            => FileType::Immediate,
+    "Procfile"           => FileType::Immediate,
+    "Rakefile"           => FileType::Immediate,
+    "RoboFile.php"       => FileType::Immediate,
+    "SConstruct"         => FileType::Immediate,
+    "tsconfig.json"      => FileType::Immediate,
+    "Vagrantfile"        => FileType::Immediate,
+    "webpack.config.cjs" => FileType::Immediate,
+    "webpack.config.js"  => FileType::Immediate,
+    "WORKSPACE"          => FileType::Immediate,
+};
 
-#[derive(Debug, Default, PartialEq, Eq)]
+/// Mapping from lowercase file extension to file type.  If an image, video, music, or lossless
+/// extension is added also update the extension icon map.
+const EXTENSION_TYPES: Map<&'static str, FileType> = phf_map! {
+    /* Immediate file - kick off the build of a project */
+    "ninja"      => FileType::Immediate,
+    /* Image files */
+    "arw"        => FileType::Image,
+    "avif"       => FileType::Image,
+    "bmp"        => FileType::Image,
+    "cbr"        => FileType::Image,
+    "cbz"        => FileType::Image,
+    "cr2"        => FileType::Image,
+    "dvi"        => FileType::Image,
+    "eps"        => FileType::Image,
+    "gif"        => FileType::Image,
+    "heif"       => FileType::Image,
+    "ico"        => FileType::Image,
+    "j2c"        => FileType::Image,
+    "j2k"        => FileType::Image,
+    "jfi"        => FileType::Image,
+    "jfif"       => FileType::Image,
+    "jif"        => FileType::Image,
+    "jp2"        => FileType::Image,
+    "jpe"        => FileType::Image,
+    "jpeg"       => FileType::Image,
+    "jpf"        => FileType::Image,
+    "jpg"        => FileType::Image,
+    "jpx"        => FileType::Image,
+    "jxl"        => FileType::Image,
+    "nef"        => FileType::Image,
+    "orf"        => FileType::Image,
+    "pbm"        => FileType::Image,
+    "pgm"        => FileType::Image,
+    "png"        => FileType::Image,
+    "pnm"        => FileType::Image,
+    "ppm"        => FileType::Image,
+    "ps"         => FileType::Image,
+    "pxm"        => FileType::Image,
+    "raw"        => FileType::Image,
+    "stl"        => FileType::Image,
+    "svg"        => FileType::Image,
+    "tif"        => FileType::Image,
+    "tiff"       => FileType::Image,
+    "webp"       => FileType::Image,
+    "xpm"        => FileType::Image,
+    /* Video files */
+    "avi"        => FileType::Video,
+    "flv"        => FileType::Video,
+    "heic"       => FileType::Video,
+    "m2ts"       => FileType::Video,
+    "m2v"        => FileType::Video,
+    "m4v"        => FileType::Video,
+    "mkv"        => FileType::Video,
+    "mov"        => FileType::Video,
+    "mp4"        => FileType::Video,
+    "mpeg"       => FileType::Video,
+    "mpg"        => FileType::Video,
+    "ogm"        => FileType::Video,
+    "ogv"        => FileType::Video,
+    "vob"        => FileType::Video,
+    "webm"       => FileType::Video,
+    "wmv"        => FileType::Video,
+    /* Music files */
+    "aac"        => FileType::Music,
+    "m4a"        => FileType::Music,
+    "mka"        => FileType::Music,
+    "mp2"        => FileType::Music,
+    "mp3"        => FileType::Music,
+    "ogg"        => FileType::Music,
+    "opus"       => FileType::Music,
+    "wma"        => FileType::Music,
+    /* Lossless music, rather than any other kind of data... */
+    "alac"       => FileType::Lossless,
+    "ape"        => FileType::Lossless,
+    "flac"       => FileType::Lossless,
+    "wav"        => FileType::Lossless,
+    /* Cryptology files */
+    "asc"        => FileType::Crypto,
+    "enc"        => FileType::Crypto,
+    "gpg"        => FileType::Crypto,
+    "p12"        => FileType::Crypto,
+    "pfx"        => FileType::Crypto,
+    "pgp"        => FileType::Crypto,
+    "sig"        => FileType::Crypto,
+    "signature"  => FileType::Crypto,
+    /* Document files */
+    "djvu"       => FileType::Document,
+    "doc"        => FileType::Document,
+    "docx"       => FileType::Document,
+    "eml"        => FileType::Document,
+    "fotd"       => FileType::Document,
+    "key"        => FileType::Document,
+    "keynote"    => FileType::Document,
+    "numbers"    => FileType::Document,
+    "odp"        => FileType::Document,
+    "odt"        => FileType::Document,
+    "pages"      => FileType::Document,
+    "pdf"        => FileType::Document,
+    "ppt"        => FileType::Document,
+    "pptx"       => FileType::Document,
+    "rtf"        => FileType::Document,
+    "xls"        => FileType::Document,
+    "xlsx"       => FileType::Document,
+    /* Compressed/archive files */
+    "7z"         => FileType::Compressed,
+    "a"          => FileType::Compressed,
+    "ar"         => FileType::Compressed,
+    "bz"         => FileType::Compressed,
+    "bz2"        => FileType::Compressed,
+    "cpio"       => FileType::Compressed,
+    "deb"        => FileType::Compressed,
+    "dmg"        => FileType::Compressed,
+    "gz"         => FileType::Compressed,
+    "iso"        => FileType::Compressed,
+    "lz"         => FileType::Compressed,
+    "lz4"        => FileType::Compressed,
+    "lzh"        => FileType::Compressed,
+    "lzma"       => FileType::Compressed,
+    "lzo"        => FileType::Compressed,
+    "par"        => FileType::Compressed,
+    "rar"        => FileType::Compressed,
+    "rpm"        => FileType::Compressed,
+    "tar"        => FileType::Compressed,
+    "taz"        => FileType::Compressed,
+    "tbz"        => FileType::Compressed,
+    "tbz2"       => FileType::Compressed,
+    "tc"         => FileType::Compressed,
+    "tgz"        => FileType::Compressed,
+    "tlz"        => FileType::Compressed,
+    "txz"        => FileType::Compressed,
+    "tz"         => FileType::Compressed,
+    "tzo"        => FileType::Compressed,
+    "xz"         => FileType::Compressed,
+    "z"          => FileType::Compressed,
+    "zip"        => FileType::Compressed,
+    "zst"        => FileType::Compressed,
+    /* Temporary files */
+    "bak"        => FileType::Temp,
+    "bk"         => FileType::Temp,
+    "bkp"        => FileType::Temp,
+    "swn"        => FileType::Temp,
+    "swo"        => FileType::Temp,
+    "swp"        => FileType::Temp,
+    "tmp"        => FileType::Temp,
+    /* Compiler output files */
+    "class"      => FileType::Compiled,
+    "elc"        => FileType::Compiled,
+    "hi"         => FileType::Compiled,
+    "ko"         => FileType::Compiled,
+    "o"          => FileType::Compiled,
+    "pyc"        => FileType::Compiled,
+    "zwc"        => FileType::Compiled,
+};
+
+#[derive(Debug)]
 pub struct FileExtensions;
 
 impl FileExtensions {

+ 405 - 3
src/output/icons.rs

@@ -1,10 +1,412 @@
 use ansi_term::Style;
-use phf;
+use phf::{phf_map, Map};
 
 use crate::fs::File;
 
-// See build.rs for FILENAME_ICONS and EXTENSION_ICONS
-include!(concat!(env!("OUT_DIR"), "/icon_maps.rs"));
+/// Mapping from full filenames to file type. This mapping should also contain all the "dot"
+/// files/directories that have a custom icon.
+const FILENAME_ICONS: Map<&'static str, char> = phf_map! {
+    ".atom"               => '\u{e764}', // 
+    ".bashprofile"        => '\u{e615}', // 
+    ".bashrc"             => '\u{f489}', // 
+    ".emacs"              => '\u{e632}', // 
+    ".git"                => '\u{f1d3}', // 
+    ".gitattributes"      => '\u{f1d3}', // 
+    ".gitconfig"          => '\u{f1d3}', // 
+    ".github"             => '\u{f408}', // 
+    ".gitignore"          => '\u{f1d3}', // 
+    ".gitignore_global"   => '\u{f1d3}', // 
+    ".gitmodules"         => '\u{f1d3}', // 
+    ".idea"               => '\u{e7b5}', // 
+    ".rvm"                => '\u{e21e}', // 
+    ".Trash"              => '\u{f1f8}', // 
+    ".vimrc"              => '\u{e7c5}', // 
+    ".vscode"             => '\u{e70c}', // 
+    ".zshrc"              => '\u{f489}', // 
+    "bin"                 => '\u{e5fc}', // 
+    "Cargo.lock"          => '\u{e7a8}', // 
+    "config"              => '\u{e5fc}', // 
+    "docker-compose.yml"  => '\u{f308}', // 
+    "Dockerfile"          => '\u{f308}', // 
+    "ds_store"            => '\u{f179}', // 
+    "Earthfile"           => '\u{f0ac}', // 
+    "gitignore_global"    => '\u{f1d3}', // 
+    "gitlab-ci.yml"       => '\u{f296}', // 
+    "go.mod"              => '\u{e626}', // 
+    "go.sum"              => '\u{e626}', // 
+    "gradle"              => '\u{e256}', // 
+    "gruntfile.coffee"    => '\u{e611}', // 
+    "gruntfile.js"        => '\u{e611}', // 
+    "gruntfile.ls"        => '\u{e611}', // 
+    "gulpfile.coffee"     => '\u{e610}', // 
+    "gulpfile.js"         => '\u{e610}', // 
+    "gulpfile.ls"         => '\u{e610}', // 
+    "hidden"              => '\u{f023}', // 
+    "include"             => '\u{e5fc}', // 
+    "lib"                 => '\u{f121}', // 
+    "LICENSE"             => '\u{f02d}', // 
+    "localized"           => '\u{f179}', // 
+    "Makefile"            => '\u{f489}', // 
+    "node_modules"        => '\u{e718}', // 
+    "npmignore"           => '\u{e71e}', // 
+    "PKGBUILD"            => '\u{f303}', // 
+    "rubydoc"             => '\u{e73b}', // 
+    "Vagrantfile"         => '\u{2371}', // ⍱
+    "yarn.lock"           => '\u{e718}', // 
+};
+
+/// Mapping from lowercase file extension to icons.  If an image, video, or audio extension is add
+/// also update the extension filetype map.
+const EXTENSION_ICONS: Map<&'static str, char> = phf_map! {
+    "7z"             => '\u{f410}',  // 
+    "a"              => '\u{f17c}',  // 
+    "acc"            => '\u{f001}',  // 
+    "acf"            => '\u{f1b6}',  // 
+    "ai"             => '\u{e7b4}',  // 
+    "alac"           => '\u{f001}',  // 
+    "android"        => '\u{e70e}',  // 
+    "ape"            => '\u{f001}',  // 
+    "apk"            => '\u{e70e}',  // 
+    "apple"          => '\u{f179}',  // 
+    "ar"             => '\u{f410}',  // 
+    "arw"            => '\u{f1c5}',  // 
+    "asm"            => '\u{e637}',  // 
+    "avi"            => '\u{f03d}',  // 
+    "avif"           => '\u{f1c5}',  // 
+    "avro"           => '\u{e60b}',  // 
+    "awk"            => '\u{f489}',  // 
+    "bash"           => '\u{f489}',  // 
+    "bashrc"         => '\u{f489}',  // 
+    "bash_history"   => '\u{f489}',  // 
+    "bash_profile"   => '\u{f489}',  // 
+    "bat"            => '\u{ebc4}',  // 
+    "bats"           => '\u{f489}',  // 
+    "bib"            => '\u{e69b}',  // 
+    "bin"            => '\u{eae8}',  // 
+    "bmp"            => '\u{f1c5}',  // 
+    "bst"            => '\u{e69b}',  // 
+    "bz"             => '\u{f410}',  // 
+    "bz2"            => '\u{f410}',  // 
+    "c"              => '\u{e61e}',  // 
+    "c++"            => '\u{e61d}',  // 
+    "cab"            => '\u{e70f}',  // 
+    "cbr"            => '\u{f1c5}',  // 
+    "cbz"            => '\u{f1c5}',  // 
+    "cc"             => '\u{e61d}',  // 
+    "cert"           => '\u{eafa}',  // 
+    "cfg"            => '\u{e615}',  // 
+    "cjs"            => '\u{e74e}',  // 
+    "class"          => '\u{e256}',  // 
+    "clj"            => '\u{e768}',  // 
+    "cljs"           => '\u{e76a}',  // 
+    "cls"            => '\u{e69b}',  // 
+    "cmd"            => '\u{e70f}',  // 
+    "coffee"         => '\u{f0f4}',  // 
+    "conf"           => '\u{e615}',  // 
+    "config"         => '\u{e615}',  // 
+    "cp"             => '\u{e61d}',  // 
+    "cpio"           => '\u{f410}',  // 
+    "cpp"            => '\u{e61d}',  // 
+    "cr2"            => '\u{f1c5}',  // 
+    "crt"            => '\u{eafa}',  // 
+    "cs"             => '\u{f031b}', // 󰌛
+    "csh"            => '\u{f489}',  // 
+    "cshtml"         => '\u{f1fa}',  // 
+    "csproj"         => '\u{f031b}', // 󰌛
+    "css"            => '\u{e749}',  // 
+    "csv"            => '\u{f1c3}',  // 
+    "csx"            => '\u{f031b}', // 󰌛
+    "cts"            => '\u{e628}',  // 
+    "cu"             => '\u{e64b}',  // 
+    "cxx"            => '\u{e61d}',  // 
+    "d"              => '\u{e7af}',  // 
+    "dart"           => '\u{e798}',  // 
+    "db"             => '\u{f1c0}',  // 
+    "deb"            => '\u{e77d}',  // 
+    "desktop"        => '\u{ebd1}',  // 
+    "diff"           => '\u{f440}',  // 
+    "djvu"           => '\u{f02d}',  // 
+    "dll"            => '\u{e70f}',  // 
+    "dmg"            => '\u{e271}',  // 
+    "doc"            => '\u{f1c2}',  // 
+    "docx"           => '\u{f1c2}',  // 
+    "drawio"         => '\u{ebba}',  // 
+    "ds_store"       => '\u{f179}',  // 
+    "dump"           => '\u{f1c0}',  // 
+    "dvi"            => '\u{f1c5}',  // 
+    "ebook"          => '\u{e28b}',  // 
+    "ebuild"         => '\u{f30d}',  // 
+    "editorconfig"   => '\u{e615}',  // 
+    "ejs"            => '\u{e618}',  // 
+    "el"             => '\u{e632}',  // 
+    "elm"            => '\u{e62c}',  // 
+    "eml"            => '\u{f003}',  // 
+    "env"            => '\u{f462}',  // 
+    "eot"            => '\u{f031}',  // 
+    "eps"            => '\u{f1c5}',  // 
+    "epub"           => '\u{e28a}',  // 
+    "erb"            => '\u{e73b}',  // 
+    "erl"            => '\u{e7b1}',  // 
+    "ex"             => '\u{e62d}',  // 
+    "exe"            => '\u{f17a}',  // 
+    "exs"            => '\u{e62d}',  // 
+    "fish"           => '\u{f489}',  // 
+    "flac"           => '\u{f001}',  // 
+    "flv"            => '\u{f03d}',  // 
+    "font"           => '\u{f031}',  // 
+    "fs"             => '\u{e7a7}',  // 
+    "fsi"            => '\u{e7a7}',  // 
+    "fsx"            => '\u{e7a7}',  // 
+    "gdoc"           => '\u{f1c2}',  // 
+    "gem"            => '\u{e21e}',  // 
+    "gemfile"        => '\u{e21e}',  // 
+    "gemspec"        => '\u{e21e}',  // 
+    "gform"          => '\u{f298}',  // 
+    "gif"            => '\u{f1c5}',  // 
+    "git"            => '\u{f1d3}',  // 
+    "gitattributes"  => '\u{f1d3}',  // 
+    "gitignore"      => '\u{f1d3}',  // 
+    "gitmodules"     => '\u{f1d3}',  // 
+    "go"             => '\u{e626}',  // 
+    "gpg"            => '\u{e60a}',  // 
+    "gradle"         => '\u{e256}',  // 
+    "groovy"         => '\u{e775}',  // 
+    "gsheet"         => '\u{f1c3}',  // 
+    "gslides"        => '\u{f1c4}',  // 
+    "guardfile"      => '\u{e21e}',  // 
+    "gz"             => '\u{f410}',  // 
+    "h"              => '\u{f0fd}',  // 
+    "hbs"            => '\u{e60f}',  // 
+    "heic"           => '\u{f03d}',  // 
+    "heif"           => '\u{f1c5}',  // 
+    "hpp"            => '\u{f0fd}',  // 
+    "hs"             => '\u{e777}',  // 
+    "htm"            => '\u{f13b}',  // 
+    "html"           => '\u{f13b}',  // 
+    "hxx"            => '\u{f0fd}',  // 
+    "ical"           => '\u{eab0}',  // 
+    "icalendar"      => '\u{eab0}',  // 
+    "ico"            => '\u{f1c5}',  // 
+    "ics"            => '\u{eab0}',  // 
+    "ifb"            => '\u{eab0}',  // 
+    "image"          => '\u{f1c5}',  // 
+    "img"            => '\u{e271}',  // 
+    "iml"            => '\u{e7b5}',  // 
+    "ini"            => '\u{f17a}',  // 
+    "ipynb"          => '\u{e678}',  // 
+    "iso"            => '\u{e271}',  // 
+    "j2c"            => '\u{f1c5}',  // 
+    "j2k"            => '\u{f1c5}',  // 
+    "jad"            => '\u{e256}',  // 
+    "jar"            => '\u{e256}',  // 
+    "java"           => '\u{e256}',  // 
+    "jfi"            => '\u{f1c5}',  // 
+    "jfif"           => '\u{f1c5}',  // 
+    "jif"            => '\u{f1c5}',  // 
+    "jl"             => '\u{e624}',  // 
+    "jmd"            => '\u{f48a}',  // 
+    "jp2"            => '\u{f1c5}',  // 
+    "jpe"            => '\u{f1c5}',  // 
+    "jpeg"           => '\u{f1c5}',  // 
+    "jpf"            => '\u{f1c5}',  // 
+    "jpg"            => '\u{f1c5}',  // 
+    "jpx"            => '\u{f1c5}',  // 
+    "js"             => '\u{e74e}',  // 
+    "json"           => '\u{e60b}',  // 
+    "jsx"            => '\u{e7ba}',  // 
+    "jxl"            => '\u{f1c5}',  // 
+    "kdb"            => '\u{f23e}',  // 
+    "kdbx"           => '\u{f23e}',  // 
+    "key"            => '\u{eb11}',  // 
+    "ko"             => '\u{f17c}',  // 
+    "ksh"            => '\u{f489}',  // 
+    "latex"          => '\u{e69b}',  // 
+    "less"           => '\u{e758}',  // 
+    "lhs"            => '\u{e777}',  // 
+    "license"        => '\u{f02d}',  // 
+    "localized"      => '\u{f179}',  // 
+    "lock"           => '\u{f023}',  // 
+    "log"            => '\u{f18d}',  // 
+    "lua"            => '\u{e620}',  // 
+    "lz"             => '\u{f410}',  // 
+    "lz4"            => '\u{f410}',  // 
+    "lzh"            => '\u{f410}',  // 
+    "lzma"           => '\u{f410}',  // 
+    "lzo"            => '\u{f410}',  // 
+    "m"              => '\u{e61e}',  // 
+    "m2ts"           => '\u{f03d}',  // 
+    "m2v"            => '\u{f03d}',  // 
+    "m4a"            => '\u{f001}',  // 
+    "m4v"            => '\u{f03d}',  // 
+    "magnet"         => '\u{f076}',  // 
+    "markdown"       => '\u{f48a}',  // 
+    "md"             => '\u{f48a}',  // 
+    "mjs"            => '\u{e74e}',  // 
+    "mk"             => '\u{f489}',  // 
+    "mka"            => '\u{f001}',  // 
+    "mkd"            => '\u{f48a}',  // 
+    "mkv"            => '\u{f03d}',  // 
+    "ml"             => '\u{e67a}',  // 
+    "mli"            => '\u{e67a}',  // 
+    "mll"            => '\u{e67a}',  // 
+    "mly"            => '\u{e67a}',  // 
+    "mm"             => '\u{e61d}',  // 
+    "mobi"           => '\u{e28b}',  // 
+    "mov"            => '\u{f03d}',  // 
+    "mp2"            => '\u{f001}',  // 
+    "mp3"            => '\u{f001}',  // 
+    "mp4"            => '\u{f03d}',  // 
+    "mpeg"           => '\u{f03d}',  // 
+    "mpg"            => '\u{f03d}',  // 
+    "msi"            => '\u{e70f}',  // 
+    "mts"            => '\u{e628}',  // 
+    "mustache"       => '\u{e60f}',  // 
+    "nef"            => '\u{f1c5}',  // 
+    "ninja"          => '\u{f0774}', // 󰝴
+    "nix"            => '\u{f313}',  // 
+    "node"           => '\u{f0399}', // 󰎙
+    "npmignore"      => '\u{e71e}',  // 
+    "o"              => '\u{eae8}',  // 
+    "odp"            => '\u{f1c4}',  // 
+    "ods"            => '\u{f1c3}',  // 
+    "odt"            => '\u{f1c2}',  // 
+    "ogg"            => '\u{f001}',  // 
+    "ogm"            => '\u{f03d}',  // 
+    "ogv"            => '\u{f03d}',  // 
+    "opus"           => '\u{f001}',  // 
+    "orf"            => '\u{f1c5}',  // 
+    "org"            => '\u{e633}',  // 
+    "otf"            => '\u{f031}',  // 
+    "out"            => '\u{eb2c}',  // 
+    "par"            => '\u{f410}',  // 
+    "part"           => '\u{f43a}',  // 
+    "patch"          => '\u{f440}',  // 
+    "pbm"            => '\u{f1c5}',  // 
+    "pdf"            => '\u{f1c1}',  // 
+    "pem"            => '\u{eb11}',  // 
+    "pgm"            => '\u{f1c5}',  // 
+    "php"            => '\u{e73d}',  // 
+    "pl"             => '\u{e769}',  // 
+    "plx"            => '\u{e769}',  // 
+    "pm"             => '\u{e769}',  // 
+    "png"            => '\u{f1c5}',  // 
+    "pnm"            => '\u{f1c5}',  // 
+    "pod"            => '\u{e769}',  // 
+    "ppm"            => '\u{f1c5}',  // 
+    "ppt"            => '\u{f1c4}',  // 
+    "pptx"           => '\u{f1c4}',  // 
+    "procfile"       => '\u{e21e}',  // 
+    "properties"     => '\u{e60b}',  // 
+    "ps"             => '\u{f1c5}',  // 
+    "ps1"            => '\u{ebc7}',  // 
+    "psd"            => '\u{e7b8}',  // 
+    "psd1"           => '\u{ebc7}',  // 
+    "psm1"           => '\u{ebc7}',  // 
+    "pxm"            => '\u{f1c5}',  // 
+    "py"             => '\u{e606}',  // 
+    "pyc"            => '\u{e606}',  // 
+    "qcow2"          => '\u{e271}',  // 
+    "r"              => '\u{f25d}',  // 
+    "rakefile"       => '\u{e21e}',  // 
+    "rar"            => '\u{f410}',  // 
+    "raw"            => '\u{f1c5}',  // 
+    "razor"          => '\u{f1fa}',  // 
+    "rb"             => '\u{e21e}',  // 
+    "rdata"          => '\u{f25d}',  // 
+    "rdb"            => '\u{e76d}',  // 
+    "rdoc"           => '\u{f48a}',  // 
+    "rds"            => '\u{f25d}',  // 
+    "readme"         => '\u{f48a}',  // 
+    "rlib"           => '\u{e7a8}',  // 
+    "rmd"            => '\u{f48a}',  // 
+    "rmeta"          => '\u{e7a8}',  // 
+    "rpm"            => '\u{e7bb}',  // 
+    "rs"             => '\u{e7a8}',  // 
+    "rspec"          => '\u{e21e}',  // 
+    "rspec_parallel" => '\u{e21e}',  // 
+    "rspec_status"   => '\u{e21e}',  // 
+    "rss"            => '\u{f09e}',  // 
+    "rst"            => '\u{f15c}',  // 
+    "rtf"            => '\u{f0219}', // 󰈙
+    "ru"             => '\u{e21e}',  // 
+    "rubydoc"        => '\u{e73b}',  // 
+    "s"              => '\u{e637}',  // 
+    "sass"           => '\u{e603}',  // 
+    "scala"          => '\u{e737}',  // 
+    "scss"           => '\u{e749}',  // 
+    "service"        => '\u{eba2}',  // 
+    "sh"             => '\u{f489}',  // 
+    "shell"          => '\u{f489}',  // 
+    "slim"           => '\u{e73b}',  // 
+    "sln"            => '\u{e70c}',  // 
+    "so"             => '\u{f17c}',  // 
+    "sql"            => '\u{f1c0}',  // 
+    "sqlite3"        => '\u{e7c4}',  // 
+    "stl"            => '\u{f1c5}',  // 
+    "sty"            => '\u{e69b}',  // 
+    "styl"           => '\u{e600}',  // 
+    "stylus"         => '\u{e600}',  // 
+    "svelte"         => '\u{e697}',  // 
+    "svg"            => '\u{f1c5}',  // 
+    "swift"          => '\u{e755}',  // 
+    "t"              => '\u{e769}',  // 
+    "tar"            => '\u{f410}',  // 
+    "taz"            => '\u{f410}',  // 
+    "tbz"            => '\u{f410}',  // 
+    "tbz2"           => '\u{f410}',  // 
+    "tc"             => '\u{f410}',  // 
+    "tex"            => '\u{e69b}',  // 
+    "tgz"            => '\u{f410}',  // 
+    "tif"            => '\u{f1c5}',  // 
+    "tiff"           => '\u{f1c5}',  // 
+    "tlz"            => '\u{f410}',  // 
+    "toml"           => '\u{e615}',  // 
+    "torrent"        => '\u{e275}',  // 
+    "ts"             => '\u{e628}',  // 
+    "tsv"            => '\u{f1c3}',  // 
+    "tsx"            => '\u{e7ba}',  // 
+    "ttf"            => '\u{f031}',  // 
+    "twig"           => '\u{e61c}',  // 
+    "txt"            => '\u{f15c}',  // 
+    "txz"            => '\u{f410}',  // 
+    "tz"             => '\u{f410}',  // 
+    "tzo"            => '\u{f410}',  // 
+    "unity"          => '\u{e721}',  // 
+    "unity3d"        => '\u{e721}',  // 
+    "vdi"            => '\u{e271}',  // 
+    "vhd"            => '\u{e271}',  // 
+    "video"          => '\u{f03d}',  // 
+    "vim"            => '\u{e7c5}',  // 
+    "vmdk"           => '\u{e271}',  // 
+    "vob"            => '\u{f03d}',  // 
+    "vue"            => '\u{f0844}', // 󰡄
+    "war"            => '\u{e256}',  // 
+    "wav"            => '\u{f001}',  // 
+    "webm"           => '\u{f03d}',  // 
+    "webp"           => '\u{f1c5}',  // 
+    "windows"        => '\u{f17a}',  // 
+    "wma"            => '\u{f001}',  // 
+    "wmv"            => '\u{f03d}',  // 
+    "woff"           => '\u{f031}',  // 
+    "woff2"          => '\u{f031}',  // 
+    "xhtml"          => '\u{f13b}',  // 
+    "xls"            => '\u{f1c3}',  // 
+    "xlsm"           => '\u{f1c3}',  // 
+    "xlsx"           => '\u{f1c3}',  // 
+    "xml"            => '\u{f05c0}', // 󰗀
+    "xpm"            => '\u{f1c5}',  // 
+    "xul"            => '\u{f05c0}', // 󰗀
+    "xz"             => '\u{f410}',  // 
+    "yaml"           => '\u{f481}',  // 
+    "yml"            => '\u{f481}',  // 
+    "z"              => '\u{f410}',  // 
+    "zig"            => '\u{21af}',  // ↯
+    "zip"            => '\u{f410}',  // 
+    "zsh"            => '\u{f489}',  // 
+    "zsh-theme"      => '\u{f489}',  // 
+    "zshrc"          => '\u{f489}',  // 
+    "zst"            => '\u{f410}',  // 
+};
 
 /// Converts the style used to paint a file name into the style that should be
 /// used to paint an icon.