Просмотр исходного кода

Clean up filetype-detecting code

Ben S 10 лет назад
Родитель
Сommit
da49b80c35
2 измененных файлов с 117 добавлено и 111 удалено
  1. 13 8
      src/file.rs
  2. 104 103
      src/filetype.rs

+ 13 - 8
src/file.rs

@@ -25,7 +25,7 @@ use datetime::format::{DateFormat};
 use column::{Column, Cell};
 use column::Column::*;
 use dir::Dir;
-use filetype::HasType;
+use filetype::file_type;
 use options::{SizeFormat, TimeType};
 use output::details::UserLocale;
 use feature::Attribute;
@@ -112,12 +112,6 @@ impl<'a> File<'a> {
         self.name.starts_with(".")
     }
 
-    /// Whether this file is a temporary file or not.
-    pub fn is_tmpfile(&self) -> bool {
-        let name = &self.name;
-        name.ends_with("~") || (name.starts_with("#") && name.ends_with("#"))
-    }
-
     /// Get the data for a column, formatted as a coloured string.
     pub fn display<U: Users>(&self, column: &Column, users_cache: &mut U, locale: &UserLocale) -> Cell {
         match *column {
@@ -207,7 +201,7 @@ impl<'a> File<'a> {
 
     /// The `ansi_term::Style` that this file's name should be painted.
     pub fn file_colour(&self) -> Style {
-        self.get_type().style()
+        file_type(&self).style()
     }
 
     /// The Unicode 'display width' of the filename.
@@ -472,6 +466,17 @@ impl<'a> File<'a> {
         }
     }
 
+    pub fn extension_is_one_of(&self, choices: &[&str]) -> bool {
+        match self.ext {
+            Some(ref ext)  => choices.contains(&&ext[..]),
+            None           => false,
+        }
+    }
+
+    pub fn name_is_one_of(&self, choices: &[&str]) -> bool {
+        choices.contains(&&self.name[..])
+    }
+
     fn git_status(&self) -> Cell {
         let status = match self.dir {
             None    => GREY.paint("--").to_string(),

+ 104 - 103
src/filetype.rs

@@ -5,54 +5,13 @@ use ansi_term::Style;
 use ansi_term::Style::Plain;
 use ansi_term::Colour::{Red, Green, Yellow, Blue, Cyan, Fixed};
 
-#[derive(PartialEq, Debug)]
+#[derive(Debug)]
 pub enum FileType {
     Normal, Directory, Executable, Immediate, Compiled, Symlink, Special,
     Image, Video, Music, Lossless, Compressed, Document, Temp, Crypto,
 }
 
-static IMAGE_TYPES: &'static [&'static str] = &[
-    "png", "jpeg", "jpg", "gif", "bmp", "tiff", "tif",
-    "ppm", "pgm", "pbm", "pnm", "webp", "raw", "arw",
-    "svg", "stl", "eps", "dvi", "ps", "cbr",
-    "cbz", "xpm", "ico" ];
-
-static VIDEO_TYPES: &'static [&'static str] = &[
-    "avi", "flv", "m2v", "mkv", "mov", "mp4", "mpeg",
-    "mpg", "ogm", "ogv", "vob", "wmv" ];
-
-static MUSIC_TYPES: &'static [&'static str] = &[
-    "aac", "m4a", "mp3", "ogg", "wma" ];
-
-static MUSIC_LOSSLESS: &'static [&'static str] = &[
-    "alac", "ape", "flac", "wav" ];
-
-static COMPRESSED_TYPES: &'static [&'static str] = &[
-    "zip", "tar", "Z", "gz", "bz2", "a", "ar", "7z",
-    "iso", "dmg", "tc", "rar", "par" ];
-
-static DOCUMENT_TYPES: &'static [&'static str] = &[
-    "djvu", "doc", "docx", "dvi", "eml", "eps", "fotd",
-    "odp", "odt", "pdf", "ppt", "pptx", "rtf",
-    "xls", "xlsx" ];
-
-static TEMP_TYPES: &'static [&'static str] = &[
-    "tmp", "swp", "swo", "swn", "bak" ];
-
-static CRYPTO_TYPES: &'static [&'static str] = &[
-    "asc", "gpg", "sig", "signature", "pgp" ];
-
-static COMPILED_TYPES: &'static [&'static str] = &[
-    "class", "elc", "hi", "o", "pyc" ];
-
-static BUILD_TYPES: &'static [&'static str] = &[
-    "Makefile", "Cargo.toml", "SConstruct", "CMakeLists.txt",
-    "build.gradle", "Rakefile", "Gruntfile.js",
-    "Gruntfile.coffee" ];
-
 impl FileType {
-
-    /// Get the `ansi_term::Style` that a file of this type should use.
     pub fn style(&self) -> Style {
         match *self {
             Normal     => Plain,
@@ -74,72 +33,115 @@ impl FileType {
     }
 }
 
-pub trait HasType {
-    /// For a given file, find out what type it has.
-    fn get_type(&self) -> FileType;
+pub fn file_type(file: &File) -> FileType {
+    match file {
+        f if f.is_directory()        => Directory,
+        f if f.is_executable_file()  => Executable,
+        f if f.is_link()             => Symlink,
+        f if !f.is_file()            => Special,
+        f if f.is_immediate()        => Immediate,
+        f if f.is_image()            => Image,
+        f if f.is_video()            => Video,
+        f if f.is_music()            => Music,
+        f if f.is_lossless()         => Lossless,
+        f if f.is_crypto()           => Crypto,
+        f if f.is_document()         => Document,
+        f if f.is_compressed()       => Compressed,
+        f if f.is_temp()             => Temp,
+        f if f.is_compiled()         => Compiled,
+        _                            => Normal,
+    }
 }
 
-impl<'a> HasType for File<'a> {
-    fn get_type(&self) -> FileType {
+trait FileTypes {
+    fn is_immediate(&self) -> bool;
+    fn is_image(&self) -> bool;
+    fn is_video(&self) -> bool;
+    fn is_music(&self) -> bool;
+    fn is_lossless(&self) -> bool;
+    fn is_crypto(&self) -> bool;
+    fn is_document(&self) -> bool;
+    fn is_compressed(&self) -> bool;
+    fn is_temp(&self) -> bool;
+    fn is_compiled(&self) -> bool;
+}
 
-        if self.is_directory() {
-            return Directory;
-        }
-        else if self.is_executable_file() {
-            return Executable;
-        }
-        else if self.is_link() {
-            return Symlink;
+impl<'_> FileTypes for File<'_> {
+    fn is_immediate(&self) -> bool {
+        self.name.starts_with("README") || self.name_is_one_of( &[
+            "Makefile", "Cargo.toml", "SConstruct", "CMakeLists.txt",
+            "build.gradle", "Rakefile", "Gruntfile.js",
+            "Gruntfile.coffee",
+        ])
+	}
+
+    fn is_image(&self) -> bool {
+        self.extension_is_one_of( &[
+            "png", "jpeg", "jpg", "gif", "bmp", "tiff", "tif",
+            "ppm", "pgm", "pbm", "pnm", "webp", "raw", "arw",
+            "svg", "stl", "eps", "dvi", "ps", "cbr",
+            "cbz", "xpm", "ico",
+        ])
+	}
+
+    fn is_video(&self) -> bool {
+        self.extension_is_one_of( &[
+            "avi", "flv", "m2v", "mkv", "mov", "mp4", "mpeg",
+            "mpg", "ogm", "ogv", "vob", "wmv",
+        ])
+	}
+
+    fn is_music(&self) -> bool {
+        self.extension_is_one_of( &[
+            "aac", "m4a", "mp3", "ogg", "wma",
+        ])
+	}
+
+    fn is_lossless(&self) -> bool {
+        self.extension_is_one_of( &[
+            "alac", "ape", "flac", "wav",
+        ])
+	}
+
+    fn is_crypto(&self) -> bool {
+        self.extension_is_one_of( &[
+            "zip", "tar", "Z", "gz", "bz2", "a", "ar", "7z",
+            "iso", "dmg", "tc", "rar", "par",
+        ])
+	}
+
+    fn is_document(&self) -> bool {
+        self.extension_is_one_of( &[
+            "djvu", "doc", "docx", "dvi", "eml", "eps", "fotd",
+            "odp", "odt", "pdf", "ppt", "pptx", "rtf",
+            "xls", "xlsx",
+        ])
+	}
+
+    fn is_compressed(&self) -> bool {
+        self.extension_is_one_of( &[
+            "zip", "tar", "Z", "gz", "bz2", "a", "ar", "7z",
+            "iso", "dmg", "tc", "rar", "par"
+        ])
+	}
+
+    fn is_temp(&self) -> bool {
+        self.name.ends_with("~")
+            || (self.name.starts_with("#") && self.name.ends_with("#"))
+            || self.extension_is_one_of( &[ "tmp", "swp", "swo", "swn", "bak" ])
+	}
+
+    fn is_compiled(&self) -> bool {
+        if self.extension_is_one_of( &[ "class", "elc", "hi", "o", "pyc" ]) {
+            true
         }
-        else if !self.is_file() {
-            return Special;
+        else if let Some(dir) = self.dir {
+            self.get_source_files().iter().any(|path| dir.contains(path))
         }
-
-        if self.name.starts_with("README") || BUILD_TYPES.contains(&&self.name[..]) {
-            return Immediate;
-        }
-        else if let Some(ref ext) = self.ext {
-            if IMAGE_TYPES.contains(&&ext[..]) {
-                return Image;
-            }
-            else if VIDEO_TYPES.contains(&&ext[..]) {
-                return Video;
-            }
-            else if MUSIC_TYPES.contains(&&ext[..]) {
-                return Music;
-            }
-            else if MUSIC_LOSSLESS.contains(&&ext[..]) {
-                return Lossless;
-            }
-            else if CRYPTO_TYPES.contains(&&ext[..]) {
-                return Crypto;
-            }
-            else if DOCUMENT_TYPES.contains(&&ext[..]) {
-                return Document;
-            }
-            else if COMPRESSED_TYPES.contains(&&ext[..]) {
-                return Compressed;
-            }
-            else if self.is_tmpfile() || TEMP_TYPES.contains(&&ext[..]) {
-                return Temp;
-            }
-
-            let source_files = self.get_source_files();
-            if source_files.is_empty() {
-                return Normal;
-            }
-            else if let Some(dir) = self.dir {
-                if source_files.iter().any(|path| dir.contains(path)) {
-                    return Temp;
-                }
-            }
-            else if COMPILED_TYPES.contains(&&ext[..]) {
-                return Compiled;
-            }
+        else {
+            false
         }
-
-        return Normal;  // no filetype
-    }
+	}
 }
 
 #[cfg(broken_test)]
@@ -170,5 +172,4 @@ mod test {
         let file = new_file(dummy_stat(), "/cargo.toml");
         assert_eq!(FileType::Normal, file.get_type())
     }
-
 }