eza/info/
filetype.rs

1// SPDX-FileCopyrightText: 2024 Christina Sørensen
2// SPDX-License-Identifier: EUPL-1.2
3//
4// SPDX-FileCopyrightText: 2023-2024 Christina Sørensen, eza contributors
5// SPDX-FileCopyrightText: 2014 Benjamin Sago
6// SPDX-License-Identifier: MIT
7//! Tests for various types of file (video, image, compressed, etc).
8//!
9//! Currently this is dependent on the file’s name and extension, because
10//! those are the only metadata that we have access to without reading the
11//! file’s contents.
12//!
13//! # Contributors
14//! Please keep these lists sorted. If you're using vim, :sort i
15
16use phf::{phf_map, Map};
17
18use crate::fs::File;
19
20#[derive(Debug, Clone)]
21pub enum FileType {
22    Image,
23    Video,
24    Music,
25    Lossless, // Lossless music, rather than any other kind of data...
26    Crypto,
27    Document,
28    Compressed,
29    Temp,
30    Compiled,
31    Build, // A “build file is something that can be run or activated somehow in order to
32    // kick off the build of a project. It’s usually only present in directories full of
33    // source code.
34    Source,
35}
36
37/// Mapping from full filenames to file type.
38const FILENAME_TYPES: Map<&'static str, FileType> = phf_map! {
39    /* Immediate file - kick off the build of a project */
40    "Brewfile"           => FileType::Build,
41    "bsconfig.json"      => FileType::Build,
42    "BUILD"              => FileType::Build,
43    "BUILD.bazel"        => FileType::Build,
44    "build.gradle"       => FileType::Build,
45    "build.sbt"          => FileType::Build,
46    "build.xml"          => FileType::Build,
47    "Cargo.toml"         => FileType::Build,
48    "CMakeLists.txt"     => FileType::Build,
49    "composer.json"      => FileType::Build,
50    "configure"          => FileType::Build,
51    "Containerfile"      => FileType::Build,
52    "Dockerfile"         => FileType::Build,
53    "Earthfile"          => FileType::Build,
54    "flake.nix"          => FileType::Build,
55    "Gemfile"            => FileType::Build,
56    "GNUmakefile"        => FileType::Build,
57    "Gruntfile.coffee"   => FileType::Build,
58    "Gruntfile.js"       => FileType::Build,
59    "jsconfig.json"      => FileType::Build,
60    "Justfile"           => FileType::Build,
61    "justfile"           => FileType::Build,
62    "Makefile"           => FileType::Build,
63    "makefile"           => FileType::Build,
64    "meson.build"        => FileType::Build,
65    "mix.exs"            => FileType::Build,
66    "package.json"       => FileType::Build,
67    "Pipfile"            => FileType::Build,
68    "PKGBUILD"           => FileType::Build,
69    "Podfile"            => FileType::Build,
70    "pom.xml"            => FileType::Build,
71    "Procfile"           => FileType::Build,
72    "pyproject.toml"     => FileType::Build,
73    "Rakefile"           => FileType::Build,
74    "RoboFile.php"       => FileType::Build,
75    "SConstruct"         => FileType::Build,
76    "tsconfig.json"      => FileType::Build,
77    "Vagrantfile"        => FileType::Build,
78    "webpack.config.cjs" => FileType::Build,
79    "webpack.config.js"  => FileType::Build,
80    "WORKSPACE"          => FileType::Build,
81    /* Cryptology files */
82    "id_dsa"             => FileType::Crypto,
83    "id_ecdsa"           => FileType::Crypto,
84    "id_ecdsa_sk"        => FileType::Crypto,
85    "id_ed25519"         => FileType::Crypto,
86    "id_ed25519_sk"      => FileType::Crypto,
87    "id_rsa"             => FileType::Crypto,
88};
89
90/// Mapping from lowercase file extension to file type.  If an image, video, music, or lossless
91/// extension is added also update the extension icon map.
92const EXTENSION_TYPES: Map<&'static str, FileType> = phf_map! {
93    /* Immediate file - kick off the build of a project */
94    "ninja"      => FileType::Build,
95    /* Image files */
96    "arw"        => FileType::Image,
97    "avif"       => FileType::Image,
98    "bmp"        => FileType::Image,
99    "cbr"        => FileType::Image,
100    "cbz"        => FileType::Image,
101    "cr2"        => FileType::Image,
102    "dvi"        => FileType::Image,
103    "eps"        => FileType::Image,
104    "fodg"       => FileType::Image,
105    "gif"        => FileType::Image,
106    "heic"       => FileType::Image,
107    "heif"       => FileType::Image,
108    "ico"        => FileType::Image,
109    "j2c"        => FileType::Image,
110    "j2k"        => FileType::Image,
111    "jfi"        => FileType::Image,
112    "jfif"       => FileType::Image,
113    "jif"        => FileType::Image,
114    "jp2"        => FileType::Image,
115    "jpe"        => FileType::Image,
116    "jpeg"       => FileType::Image,
117    "jpf"        => FileType::Image,
118    "jpg"        => FileType::Image,
119    "jpx"        => FileType::Image,
120    "jxl"        => FileType::Image,
121    "kra"        => FileType::Image,
122    "krz"        => FileType::Image,
123    "nef"        => FileType::Image,
124    "odg"        => FileType::Image,
125    "orf"        => FileType::Image,
126    "pbm"        => FileType::Image,
127    "pgm"        => FileType::Image,
128    "png"        => FileType::Image,
129    "pnm"        => FileType::Image,
130    "ppm"        => FileType::Image,
131    "ps"         => FileType::Image,
132    "psd"        => FileType::Image,
133    "pxm"        => FileType::Image,
134    "raw"        => FileType::Image,
135    "qoi"        => FileType::Image,
136    "svg"        => FileType::Image,
137    "tif"        => FileType::Image,
138    "tiff"       => FileType::Image,
139    "webp"       => FileType::Image,
140    "xcf"        => FileType::Image,
141    "xpm"        => FileType::Image,
142    /* Video files */
143    "avi"        => FileType::Video,
144    "flv"        => FileType::Video,
145    "h264"       => FileType::Video,
146    "heics"      => FileType::Video,
147    "m2ts"       => FileType::Video,
148    "m2v"        => FileType::Video,
149    "m4v"        => FileType::Video,
150    "mkv"        => FileType::Video,
151    "mov"        => FileType::Video,
152    "mp4"        => FileType::Video,
153    "mpeg"       => FileType::Video,
154    "mpg"        => FileType::Video,
155    "ogm"        => FileType::Video,
156    "ogv"        => FileType::Video,
157    "video"      => FileType::Video,
158    "vob"        => FileType::Video,
159    "webm"       => FileType::Video,
160    "wmv"        => FileType::Video,
161    /* Music files */
162    "aac"        => FileType::Music, // Advanced Audio Coding
163    "m4a"        => FileType::Music,
164    "mka"        => FileType::Music,
165    "mp2"        => FileType::Music,
166    "mp3"        => FileType::Music,
167    "ogg"        => FileType::Music,
168    "opus"       => FileType::Music,
169    "wma"        => FileType::Music,
170    /* Lossless music, rather than any other kind of data... */
171    "aif"        => FileType::Lossless,
172    "aifc"       => FileType::Lossless,
173    "aiff"       => FileType::Lossless,
174    "alac"       => FileType::Lossless,
175    "ape"        => FileType::Lossless,
176    "flac"       => FileType::Lossless,
177    "pcm"        => FileType::Lossless,
178    "wav"        => FileType::Lossless,
179    "wv"         => FileType::Lossless,
180    /* Cryptology files */
181    "age"        => FileType::Crypto, // age encrypted file
182    "asc"        => FileType::Crypto, // GnuPG ASCII armored file
183    "cer"        => FileType::Crypto,
184    "crt"        => FileType::Crypto,
185    "csr"        => FileType::Crypto, // PKCS#10 Certificate Signing Request
186    "gpg"        => FileType::Crypto, // GnuPG encrypted file
187    "kbx"        => FileType::Crypto, // GnuPG keybox
188    "md5"        => FileType::Crypto, // MD5 checksum
189    "p12"        => FileType::Crypto, // PKCS#12 certificate (Netscape)
190    "pem"        => FileType::Crypto, // Privacy-Enhanced Mail certificate
191    "pfx"        => FileType::Crypto, // PKCS#12 certificate (Microsoft)
192    "pgp"        => FileType::Crypto, // PGP security key
193    "pub"        => FileType::Crypto, // Public key
194    "sha1"       => FileType::Crypto, // SHA-1 hash
195    "sha224"     => FileType::Crypto, // SHA-224 hash
196    "sha256"     => FileType::Crypto, // SHA-256 hash
197    "sha384"     => FileType::Crypto, // SHA-384 hash
198    "sha512"     => FileType::Crypto, // SHA-512 hash
199    "sig"        => FileType::Crypto, // GnuPG signed file
200    "signature"  => FileType::Crypto, // e-Filing Digital Signature File (India)
201    /* Document files */
202    "djvu"       => FileType::Document,
203    "doc"        => FileType::Document,
204    "docx"       => FileType::Document,
205    "eml"        => FileType::Document,
206    "fodp"       => FileType::Document,
207    "fods"       => FileType::Document,
208    "fodt"       => FileType::Document,
209    "fotd"       => FileType::Document,
210    "gdoc"       => FileType::Document,
211    "key"        => FileType::Document,
212    "keynote"    => FileType::Document,
213    "numbers"    => FileType::Document,
214    "odp"        => FileType::Document,
215    "ods"        => FileType::Document,
216    "odt"        => FileType::Document,
217    "pages"      => FileType::Document,
218    "pdf"        => FileType::Document,
219    "ppt"        => FileType::Document,
220    "pptx"       => FileType::Document,
221    "rtf"        => FileType::Document, // Rich Text Format
222    "xls"        => FileType::Document,
223    "xlsm"       => FileType::Document,
224    "xlsx"       => FileType::Document,
225    /* Compressed/archive files */
226    "7z"         => FileType::Compressed, // 7-Zip
227    "ar"         => FileType::Compressed,
228    "arj"        => FileType::Compressed,
229    "br"         => FileType::Compressed, // Brotli
230    "bz"         => FileType::Compressed, // bzip
231    "bz2"        => FileType::Compressed, // bzip2
232    "bz3"        => FileType::Compressed, // bzip3
233    "cpio"       => FileType::Compressed,
234    "deb"        => FileType::Compressed, // Debian
235    "dmg"        => FileType::Compressed,
236    "gz"         => FileType::Compressed, // gzip
237    "iso"        => FileType::Compressed,
238    "lz"         => FileType::Compressed,
239    "lz4"        => FileType::Compressed,
240    "lzh"        => FileType::Compressed,
241    "lzma"       => FileType::Compressed,
242    "lzo"        => FileType::Compressed,
243    "phar"       => FileType::Compressed, // PHP PHAR
244    "qcow"       => FileType::Compressed,
245    "qcow2"      => FileType::Compressed,
246    "rar"        => FileType::Compressed,
247    "rpm"        => FileType::Compressed,
248    "tar"        => FileType::Compressed,
249    "taz"        => FileType::Compressed,
250    "tbz"        => FileType::Compressed,
251    "tbz2"       => FileType::Compressed,
252    "tc"         => FileType::Compressed,
253    "tgz"        => FileType::Compressed,
254    "tlz"        => FileType::Compressed,
255    "txz"        => FileType::Compressed,
256    "tz"         => FileType::Compressed,
257    "xz"         => FileType::Compressed,
258    "vdi"        => FileType::Compressed,
259    "vhd"        => FileType::Compressed,
260    "vhdx"       => FileType::Compressed,
261    "vmdk"       => FileType::Compressed,
262    "z"          => FileType::Compressed,
263    "zip"        => FileType::Compressed,
264    "zst"        => FileType::Compressed, // Zstandard
265    /* Temporary files */
266    "bak"        => FileType::Temp,
267    "bk"         => FileType::Temp,
268    "bkp"        => FileType::Temp,
269    "crdownload" => FileType::Temp,
270    "download"   => FileType::Temp,
271    "fcbak"      => FileType::Temp,
272    "fcstd1"     => FileType::Temp,
273    "fdmdownload"=> FileType::Temp,
274    "part"       => FileType::Temp,
275    "swn"        => FileType::Temp,
276    "swo"        => FileType::Temp,
277    "swp"        => FileType::Temp,
278    "tmp"        => FileType::Temp,
279    /* Compiler output files */
280    "a"          => FileType::Compiled, // Unix static library
281    "bundle"     => FileType::Compiled, // macOS application bundle
282    "class"      => FileType::Compiled, // Java class file
283    "cma"        => FileType::Compiled, // OCaml bytecode library
284    "cmi"        => FileType::Compiled, // OCaml interface
285    "cmo"        => FileType::Compiled, // OCaml bytecode object
286    "cmx"        => FileType::Compiled, // OCaml bytecode object for inlining
287    "dll"        => FileType::Compiled, // Windows dynamic link library
288    "dylib"      => FileType::Compiled, // Mach-O dynamic library
289    "elc"        => FileType::Compiled, // Emacs compiled lisp
290    "elf"        => FileType::Compiled, // Executable and Linkable Format
291    "ko"         => FileType::Compiled, // Linux kernel module
292    "lib"        => FileType::Compiled, // Windows static library
293    "o"          => FileType::Compiled, // Compiled object file
294    "obj"        => FileType::Compiled, // Compiled object file
295    "pyc"        => FileType::Compiled, // Python compiled code
296    "pyd"        => FileType::Compiled, // Python dynamic module
297    "pyo"        => FileType::Compiled, // Python optimized code
298    "so"         => FileType::Compiled, // Unix shared library
299    "zwc"        => FileType::Compiled, // zsh compiled file
300    /* Source code files */
301    "applescript"=> FileType::Source, // Apple script
302    "as"         => FileType::Source, // Action script
303    "asa"        => FileType::Source, // asp
304    "awk"        => FileType::Source, // awk
305    "c"          => FileType::Source, // C/C++
306    "c++"        => FileType::Source, // C/C++
307    "c++m"       => FileType::Source, // C/C++ module
308    "cabal"      => FileType::Source, // Cabal
309    "cc"         => FileType::Source, // C/C++
310    "ccm"        => FileType::Source, // C/C++ module
311    "clj"        => FileType::Source, // Clojure
312    "cp"         => FileType::Source, // C/C++ Xcode
313    "cpp"        => FileType::Source, // C/C++
314    "cppm"       => FileType::Source, // C/C++ module
315    "cr"         => FileType::Source, // Crystal
316    "cs"         => FileType::Source, // C#
317    "css"        => FileType::Source, // css
318    "csx"        => FileType::Source, // C#
319    "cu"         => FileType::Source, // CUDA
320    "cxx"        => FileType::Source, // C/C++
321    "cxxm"       => FileType::Source, // C/C++ module
322    "cypher"     => FileType::Source, // Cypher (query language)
323    "d"          => FileType::Source, // D
324    "dart"       => FileType::Source, // Dart
325    "di"         => FileType::Source, // D
326    "dpr"        => FileType::Source, // Delphi Pascal
327    "el"         => FileType::Source, // Lisp
328    "elm"        => FileType::Source, // Elm
329    "erl"        => FileType::Source, // Erlang
330    "ex"         => FileType::Source, // Elixir
331    "exs"        => FileType::Source, // Elixir
332    "f"          => FileType::Source, // Fortran
333    "f90"        => FileType::Source, // Fortran
334    "fcmacro"    => FileType::Source, // FreeCAD macro
335    "fcscript"   => FileType::Source, // FreeCAD script
336    "fnl"        => FileType::Source, // Fennel
337    "for"        => FileType::Source, // Fortran
338    "fs"         => FileType::Source, // F#
339    "fsh"        => FileType::Source, // Fragment shader
340    "fsi"        => FileType::Source, // F#
341    "fsx"        => FileType::Source, // F#
342    "gd"         => FileType::Source, // GDScript
343    "go"         => FileType::Source, // Go
344    "gradle"     => FileType::Source, // Gradle
345    "groovy"     => FileType::Source, // Groovy
346    "gvy"        => FileType::Source, // Groovy
347    "h"          => FileType::Source, // C/C++ header
348    "h++"        => FileType::Source, // C/C++ header
349    "hh"         => FileType::Source, // C/C++ header
350    "hpp"        => FileType::Source, // C/C++ header
351    "hc"         => FileType::Source, // HolyC
352    "hs"         => FileType::Source, // Haskell
353    "htc"        => FileType::Source, // JavaScript
354    "hxx"        => FileType::Source, // C/C++ header
355    "inc"        => FileType::Source,
356    "inl"        => FileType::Source, // C/C++ Microsoft
357    "ino"        => FileType::Source, // Arduino
358    "ipynb"      => FileType::Source, // Jupyter Notebook
359    "ixx"        => FileType::Source, // C/C++ module
360    "java"       => FileType::Source, // Java
361    "jl"         => FileType::Source, // Julia
362    "js"         => FileType::Source, // JavaScript
363    "jsx"        => FileType::Source, // React
364    "kt"         => FileType::Source, // Kotlin
365    "kts"        => FileType::Source, // Kotlin
366    "kusto"      => FileType::Source, // Kusto (query language)
367    "less"       => FileType::Source, // less
368    "lhs"        => FileType::Source, // Haskell
369    "lisp"       => FileType::Source, // Lisp
370    "ltx"        => FileType::Source, // LaTeX
371    "lua"        => FileType::Source, // Lua
372    "m"          => FileType::Source, // Matlab
373    "malloy"     => FileType::Source, // Malloy (query language)
374    "matlab"     => FileType::Source, // Matlab
375    "ml"         => FileType::Source, // OCaml
376    "mli"        => FileType::Source, // OCaml
377    "mn"         => FileType::Source, // Matlab
378    "nb"         => FileType::Source, // Mathematica
379    "p"          => FileType::Source, // Pascal
380    "pas"        => FileType::Source, // Pascal
381    "php"        => FileType::Source, // PHP
382    "pl"         => FileType::Source, // Perl
383    "pm"         => FileType::Source, // Perl
384    "pod"        => FileType::Source, // Perl
385    "pp"         => FileType::Source, // Puppet
386    "prql"       => FileType::Source, // PRQL
387    "ps1"        => FileType::Source, // PowerShell
388    "psd1"       => FileType::Source, // PowerShell
389    "psm1"       => FileType::Source, // PowerShell
390    "purs"       => FileType::Source, // PureScript
391    "py"         => FileType::Source, // Python
392    "r"          => FileType::Source, // R
393    "rb"         => FileType::Source, // Ruby
394    "rs"         => FileType::Source, // Rust
395    "rq"         => FileType::Source, // SPARQL (query language)
396    "sass"       => FileType::Source, // Sass
397    "scala"      => FileType::Source, // Scala
398    "scm"        => FileType::Source, // Scheme
399    "scad"       => FileType::Source, // OpenSCAD
400    "scss"       => FileType::Source, // Sass
401    "sld"        => FileType::Source, // Scheme Library Definition
402    "sql"        => FileType::Source, // SQL
403    "ss"         => FileType::Source, // Scheme Source
404    "swift"      => FileType::Source, // Swift
405    "tcl"        => FileType::Source, // TCL
406    "tex"        => FileType::Source, // LaTeX
407    "ts"         => FileType::Source, // TypeScript
408    "v"          => FileType::Source, // V
409    "vb"         => FileType::Source, // Visual Basic
410    "vsh"        => FileType::Source, // Vertex shader
411    "zig"        => FileType::Source, // Zig
412};
413
414impl FileType {
415    /// Lookup the file type based on the file's name, by the file name
416    /// lowercase extension, or if the file could be compiled from related
417    /// source code.
418    pub(crate) fn get_file_type(file: &File<'_>) -> Option<FileType> {
419        // Case-insensitive readme is checked first for backwards compatibility.
420        if file.name.to_lowercase().starts_with("readme") {
421            return Some(Self::Build);
422        }
423        if let Some(file_type) = FILENAME_TYPES.get(&file.name) {
424            return Some(file_type.clone());
425        }
426        if let Some(file_type) = file.ext.as_ref().and_then(|ext| EXTENSION_TYPES.get(ext)) {
427            return Some(file_type.clone());
428        }
429        if file.name.ends_with('~') || (file.name.starts_with('#') && file.name.ends_with('#')) {
430            return Some(Self::Temp);
431        }
432        if let Some(dir) = file.parent_dir {
433            if file
434                .get_source_files()
435                .iter()
436                .any(|path| dir.contains(path))
437            {
438                return Some(Self::Compiled);
439            }
440        }
441        None
442    }
443}