Clean up filetype-detecting code

This commit is contained in:
Ben S 2015-05-09 16:10:26 +01:00
parent 662aed302a
commit da49b80c35
2 changed files with 117 additions and 111 deletions

View File

@ -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(),

View File

@ -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;
}
else if !self.is_file() {
return Special;
}
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",
])
}
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;
}
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",
])
}
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;
}
}
fn is_video(&self) -> bool {
self.extension_is_one_of( &[
"avi", "flv", "m2v", "mkv", "mov", "mp4", "mpeg",
"mpg", "ogm", "ogv", "vob", "wmv",
])
}
return Normal; // no filetype
}
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 let Some(dir) = self.dir {
self.get_source_files().iter().any(|path| dir.contains(path))
}
else {
false
}
}
}
#[cfg(broken_test)]
@ -170,5 +172,4 @@ mod test {
let file = new_file(dummy_stat(), "/cargo.toml");
assert_eq!(FileType::Normal, file.get_type())
}
}