Procházet zdrojové kódy

Move file-type detection to its own module

I'd much rather have this separate, as it has the definite potential to
balloon up to a huge size and end up making the other parts of the file
module hard to read. But on the other hand, it meant making a few more
methods public on file... readability over cleanliness, I guess.
Ben S před 11 roky
rodič
revize
03ec414dfb
3 změnil soubory, kde provedl 123 přidání a 89 odebrání
  1. 1 0
      exa.rs
  2. 6 89
      file.rs
  3. 116 0
      filetype.rs

+ 1 - 0
exa.rs

@@ -13,6 +13,7 @@ pub mod column;
 pub mod dir;
 pub mod format;
 pub mod file;
+pub mod filetype;
 pub mod unix;
 pub mod options;
 pub mod sort;

+ 6 - 89
file.rs

@@ -1,43 +1,13 @@
+use colours::{Plain, Style, Black, Red, Green, Yellow, Blue, Purple, Cyan, Fixed};
 use std::io::fs;
 use std::io;
 
-use colours::{Plain, Style, Black, Red, Green, Yellow, Blue, Purple, Cyan, Fixed};
 use column::{Column, Permissions, FileName, FileSize, User, Group};
 use format::{format_metric_bytes, format_IEC_bytes};
 use unix::{get_user_name, get_group_name};
 use sort::SortPart;
 use dir::Dir;
-
-static IMAGE_TYPES: &'static [&'static str] = &[
-    "png", "jpeg", "jpg", "gif", "bmp", "tiff", "tif",
-    "ppm", "pgm", "pbm", "pnm", "webp", "raw", "arw",
-    "svg", "pdf", "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" ];
-
-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", "eml", "eps", "odp", "ods",
-    "odt", "pdf", "ppt", "pptx", "xls", "xlsx" ];
-
-static TEMP_TYPES: &'static [&'static str] = &[
-    "tmp", "swp", "swo", "swn", "bak" ];
-
-static CRYPTO_TYPES: &'static [&'static str] = &[
-    "asc", "gpg", "sig", "signature", "pgp" ];
-
+use filetype::FileType;
 
 // Instead of working with Rust's Paths, we have our own File object
 // that holds the Path and various cached information. Each file is
@@ -91,7 +61,7 @@ impl<'a> File<'a> {
         self.name.starts_with(".")
     }
 
-    fn is_tmpfile(&self) -> bool {
+    pub fn is_tmpfile(&self) -> bool {
         self.name.ends_with("~") || (self.name.starts_with("#") && self.name.ends_with("#"))
     }
         
@@ -101,7 +71,7 @@ impl<'a> File<'a> {
     // content without their source files, such as how .js is valid
     // without a .coffee.
     
-    fn get_source_files(&self) -> Vec<Path> {
+    pub fn get_source_files(&self) -> Vec<Path> {
         match self.ext {
             Some("class") => vec![self.path.with_extension("java")],  // Java
             Some("elc") => vec![self.path.with_extension("el")],  // Emacs Lisp
@@ -112,7 +82,7 @@ impl<'a> File<'a> {
         }
     }
     
-    fn get_source_files_usual(&self) -> Vec<Path> {
+    pub fn get_source_files_usual(&self) -> Vec<Path> {
         match self.ext {
             Some("js") => vec![self.path.with_extension("coffee"), self.path.with_extension("ts")],  // CoffeeScript, TypeScript
             Some("css") => vec![self.path.with_extension("sass"), self.path.with_extension("less")],  // SASS, Less
@@ -173,60 +143,7 @@ impl<'a> File<'a> {
     }
 
     fn file_colour(&self) -> Style {
-        if self.stat.kind == io::TypeDirectory {
-            Blue.bold()
-        }
-        else if self.stat.perm.contains(io::UserExecute) {
-            Green.bold()
-        }
-        else if self.is_tmpfile() {
-            Fixed(244).normal()  // midway between white and black - should show up as grey on all terminals
-        }
-        else if self.name.starts_with("README") {
-            Yellow.bold().underline()
-        }
-        else if self.ext.is_some() && IMAGE_TYPES.iter().any(|&s| s == self.ext.unwrap()) {
-            Fixed(133).normal()
-        }
-        else if self.ext.is_some() && VIDEO_TYPES.iter().any(|&s| s == self.ext.unwrap()) {
-            Fixed(135).normal()
-        }
-        else if self.ext.is_some() && MUSIC_TYPES.iter().any(|&s| s == self.ext.unwrap()) {
-            Fixed(92).normal()
-        }
-        else if self.ext.is_some() && MUSIC_LOSSLESS.iter().any(|&s| s == self.ext.unwrap()) {
-            Fixed(93).normal()
-        }
-        else if self.ext.is_some() && CRYPTO_TYPES.iter().any(|&s| s == self.ext.unwrap()) {
-            Fixed(109).normal()
-        }
-        else if self.ext.is_some() && DOCUMENT_TYPES.iter().any(|&s| s == self.ext.unwrap()) {
-            Fixed(105).normal()
-        }
-        else if self.ext.is_some() && COMPRESSED_TYPES.iter().any(|&s| s == self.ext.unwrap()) {
-            Red.normal()
-        }
-        else if self.ext.is_some() && TEMP_TYPES.iter().any(|&s| s == self.ext.unwrap()) {
-            Fixed(244).normal()
-        }
-        else {
-            let source_files = self.get_source_files();
-            if source_files.len() == 0 {
-                let source_files_usual = self.get_source_files_usual();
-                if source_files_usual.iter().any(|path| self.dir.contains(path)) {
-                    Fixed(244).normal()
-                }
-                else {
-                    Plain
-                }
-            }
-            else if source_files.iter().any(|path| self.dir.contains(path)) {
-                Fixed(244).normal()
-            }
-            else {
-                Fixed(137).normal()
-            }
-        }
+        FileType::from_file(self).style()
     }
 
     fn permissions_string(&self) -> String {

+ 116 - 0
filetype.rs

@@ -0,0 +1,116 @@
+use colours::{Plain, Style, Black, Red, Green, Yellow, Blue, Purple, Cyan, Fixed};
+use file::File;
+use std::io;
+
+pub enum FileType {
+    Normal, Directory, Executable, Immediate, Compiled,
+    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" ];
+
+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", "eml", "eps", "odp", "ods",
+    "odt", "pdf", "ppt", "pptx", "xls", "xlsx" ];
+
+static TEMP_TYPES: &'static [&'static str] = &[
+    "tmp", "swp", "swo", "swn", "bak" ];
+
+static CRYPTO_TYPES: &'static [&'static str] = &[
+    "asc", "gpg", "sig", "signature", "pgp" ];
+
+impl FileType {
+    pub fn style(&self) -> Style {
+        match *self {
+            Normal => Plain,
+            Directory => Blue.bold(),
+            Executable => Green.bold(),
+            Image => Fixed(133).normal(),
+            Video => Fixed(135).normal(),
+            Music => Fixed(92).normal(),
+            Lossless => Fixed(93).normal(),
+            Crypto => Fixed(109).normal(),
+            Document => Fixed(105).normal(),
+            Compressed => Red.normal(),
+            Temp => Fixed(244).normal(),
+            Immediate => Yellow.bold().underline(),
+            Compiled => Fixed(137).normal(),
+        }
+    }
+
+    pub fn from_file(file: &File) -> FileType {
+        if file.stat.kind == io::TypeDirectory {
+            return Directory;
+        }
+        else if file.stat.perm.contains(io::UserExecute) {
+            return Executable;
+        }
+        else if file.ext.is_some() {
+            let ext = file.ext.unwrap();
+            if IMAGE_TYPES.iter().any(|&s| s == ext) {
+                return Image;
+            }
+            else if VIDEO_TYPES.iter().any(|&s| s == ext) {
+                return Video;
+            }
+            else if MUSIC_TYPES.iter().any(|&s| s == ext) {
+                return Music;
+            }
+            else if MUSIC_LOSSLESS.iter().any(|&s| s == ext) {
+                return Lossless;
+            }
+            else if CRYPTO_TYPES.iter().any(|&s| s == ext) {
+                return Crypto;
+            }
+            else if DOCUMENT_TYPES.iter().any(|&s| s == ext) {
+                return Document;
+            }
+            else if COMPRESSED_TYPES.iter().any(|&s| s == ext) {
+                return Compressed;
+            }
+            else if file.is_tmpfile() || TEMP_TYPES.iter().any(|&s| s == ext) {
+                return Temp;
+            }
+        }
+
+        if file.name.starts_with("README") {
+            return Immediate;
+        }
+
+        let source_files = file.get_source_files();
+        if source_files.len() == 0 {
+            let source_files_usual = file.get_source_files_usual();
+            if source_files_usual.iter().any(|path| file.dir.contains(path)) {
+                Temp
+            }
+            else {
+                Normal
+            }
+        }
+        else if source_files.iter().any(|path| file.dir.contains(path)) {
+            Temp
+        }
+        else {
+            Compiled
+        }
+    }
+}
+