diff --git a/Cargo.lock b/Cargo.lock index c376a20..f9586a1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -16,42 +16,11 @@ dependencies = [ "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "backtrace" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "backtrace-sys 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "backtrace-sys" -version = "0.1.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "bitflags" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "cc" -version = "1.0.25" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "cfg-if" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "clap" version = "2.32.0" @@ -66,26 +35,6 @@ dependencies = [ "vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "failure" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "failure_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "failure_derive" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)", - "synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "lazy_static" version = "1.2.0" @@ -102,7 +51,6 @@ version = "0.3.2-pre" dependencies = [ "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", - "failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", "term_grid 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -111,22 +59,6 @@ dependencies = [ "users 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "proc-macro2" -version = "0.4.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "quote" -version = "0.6.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "redox_syscall" version = "0.1.43" @@ -140,37 +72,11 @@ dependencies = [ "redox_syscall 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "rustc-demangle" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "strsim" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "syn" -version = "0.15.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "synstructure" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "term_grid" version = "0.1.7" @@ -221,11 +127,6 @@ name = "unicode-width" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "unicode-xid" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "users" version = "0.8.1" @@ -261,31 +162,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [metadata] "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" "checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652" -"checksum backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "89a47830402e9981c5c41223151efcced65a0510c13097c769cede7efb34782a" -"checksum backtrace-sys 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)" = "c66d56ac8dabd07f6aacdaf633f4b8262f5b3601a810a0dcddffd5c22c69daa0" "checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" -"checksum cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)" = "f159dfd43363c4d08055a07703eb7a3406b0dac4d0584d96965a3262db3c9d16" -"checksum cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4" "checksum clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b957d88f4b6a63b9d70d5f454ac8011819c6efa7727858f458ab71c756ce2d3e" -"checksum failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6dd377bcc1b1b7ce911967e3ec24fa19c3224394ec05b54aa7b083d498341ac7" -"checksum failure_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "64c2d913fe8ed3b6c6518eedf4538255b989945c14c2a7d5cbff62a5e2120596" "checksum lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a374c89b9db55895453a74c1e38861d9deec0b01b405a82516e9d5de4820dea1" "checksum libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)" = "10923947f84a519a45c8fefb7dd1b3e8c08747993381adee176d7a82b4195311" -"checksum proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)" = "77619697826f31a02ae974457af0b29b723e5619e113e9397b8b82c6bd253f09" -"checksum quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "53fa22a1994bd0f9372d7a816207d8a2677ad0325b073f5c5332760f0fb62b5c" "checksum redox_syscall 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)" = "679da7508e9a6390aeaf7fbd02a800fdc64b73fe2204dd2c8ae66d22d9d5ad5d" "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" -"checksum rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "bcfe5b13211b4d78e5c2cadfebd7769197d95c639c35a50057eb4c05de811395" "checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550" -"checksum syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)" = "ae8b29eb5210bc5cf63ed6149cbf9adfc82ac0be023d8735c176ee74a2db4da7" -"checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015" "checksum term_grid 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "230d3e804faaed5a39b08319efb797783df2fd9671b39b7596490cb486d702cf" "checksum terminal_size 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "023345d35850b69849741bd9a5432aa35290e3d8eb76af8717026f270d1cf133" "checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" "checksum textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "307686869c93e71f94da64286f9a9524c0f308a9e1c87a583de8e9c9039ad3f6" "checksum time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "d825be0eb33fda1a7e68012d51e9c7f451dc1a69391e7fdc197060bb8c56667b" "checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526" -"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" "checksum users 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7fed7d0912567d35f88010c23dbaf865e9da8b5227295e8dc0f2fdd109155ab7" "checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" "checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0" diff --git a/Cargo.toml b/Cargo.toml index 50f562a..76bbaf4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,7 +13,6 @@ version = "0.3.2-pre" [dependencies] ansi_term = "0.11.0" clap = "2.32.0" -failure = "0.1.3" lazy_static = "1.2.0" libc = "0.2.44" term_grid = "0.1.7" diff --git a/src/core.rs b/src/core.rs index c82fde0..bf21dbe 100644 --- a/src/core.rs +++ b/src/core.rs @@ -1,4 +1,3 @@ -use formatter::*; use meta::{FileType, Meta}; use std::cmp::Ordering; use std::path::Path; @@ -7,16 +6,12 @@ use terminal_size::terminal_size; use Options; pub struct Core<'a> { - formatter: Formatter, options: &'a Options, } impl<'a> Core<'a> { pub fn new(options: &'a Options) -> Core<'a> { - Core { - options, - formatter: Formatter::new(), - } + Core { options } } pub fn run(&self, inputs: Vec<&str>) { @@ -31,10 +26,7 @@ impl<'a> Core<'a> { if path.is_dir() { dirs.push(path); } else if path.is_file() { - match Meta::from_path(path) { - Ok(meta) => files.push(meta), - Err(err) => println!("err : {}", err), - }; + files.push(Meta::from(path)); } else { match path.metadata() { Ok(_) => panic!("shouldn't failed"), @@ -84,7 +76,7 @@ impl<'a> Core<'a> { for meta in metas { let mut content = String::from(" "); - content = content + &self.formatter.format_name(&meta); + content += &meta.name.render(); grid.add(Cell { width: content.len(), contents: content, @@ -117,7 +109,7 @@ impl<'a> Core<'a> { meta.size .render(max_size_value_length, max_size_unit_length), meta.date.render(), - self.formatter.format_name(&meta), + meta.name.render(), link_str, ); } @@ -136,13 +128,9 @@ impl<'a> Core<'a> { for entry in dir { if let Ok(entry) = entry { - match Meta::from_path(entry.path().as_path()) { - Ok(meta) => { - if !meta.name.starts_with('.') || self.options.display_all { - content.push(meta); - } - } - Err(err) => println!("err 2: {}", err), + let meta = Meta::from(entry.path().as_path()); + if !meta.name.is_hidden() || self.options.display_all { + content.push(meta); } } } @@ -202,6 +190,6 @@ fn sort_by_meta(a: &Meta, b: &Meta) -> Ordering { } else if b.file_type == FileType::Directory && a.file_type != FileType::Directory { Ordering::Greater } else { - a.path.cmp(&b.path) + a.name.cmp(&b.name) } } diff --git a/src/formatter.rs b/src/formatter.rs deleted file mode 100644 index d5d479d..0000000 --- a/src/formatter.rs +++ /dev/null @@ -1,31 +0,0 @@ -use color::{Colors, Elem}; -use icon; -use meta::Meta; - -pub struct Formatter {} - -impl Formatter { - pub fn new() -> Formatter { - Formatter {} - } - - pub fn format_name(&self, meta: &Meta) -> String { - let mut content = String::new(); - - let color = if meta.metadata.is_dir() { - Colors[&Elem::Dir] - } else { - Colors[&Elem::File] - }; - - let mut name = meta.name.clone(); - if meta.metadata.is_dir() { - name.push('/'); - } - - content = content + icon::from_meta(&meta) + " " + &name; - content = color.paint(content).to_string(); - - content - } -} diff --git a/src/icon.rs b/src/icon.rs index bfcde97..9db32fd 100644 --- a/src/icon.rs +++ b/src/icon.rs @@ -1,4 +1,4 @@ -use meta::Meta; +use meta::Name; use std::collections::HashMap; // In order to add a new icon, write the unicode value like "\ue5fb" then @@ -228,20 +228,21 @@ lazy_static! { }; } -pub fn from_meta(meta: &Meta) -> &'static str { +pub fn from_name(name: &Name) -> &'static str { // Check the known names. - if let Some(res) = IconsByName.get(&meta.name.as_str()) { + if let Some(res) = IconsByName.get(name.name().as_str()) { return res.to_owned(); } // Check the known extensions. - let extension = meta.path.extension().unwrap_or_default().to_str().unwrap(); - if let Some(res) = IconsByExtension.get(extension) { - return res.to_owned(); + if let Some(extension) = name.extension() { + if let Some(res) = IconsByExtension.get(extension.as_str()) { + return res.to_owned(); + } } // Use the default icons. - if meta.metadata.is_dir() { + if name.is_dir() { "" } else { "" diff --git a/src/main.rs b/src/main.rs index e330a54..0a65cb7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,7 +2,6 @@ extern crate clap; #[macro_use] extern crate lazy_static; extern crate ansi_term; -extern crate failure; extern crate libc; extern crate term_grid; extern crate terminal_size; @@ -11,7 +10,6 @@ extern crate users; mod color; mod core; -mod formatter; mod icon; mod meta; diff --git a/src/meta/filetype.rs b/src/meta/filetype.rs index 578214e..7d22a3b 100644 --- a/src/meta/filetype.rs +++ b/src/meta/filetype.rs @@ -2,7 +2,7 @@ use color::{Colors, Elem}; use std::fs::Metadata; use std::os::unix::fs::FileTypeExt; -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Eq, Copy, Clone)] pub enum FileType { BlockDevice, CharDevice, @@ -39,8 +39,8 @@ impl<'a> From<&'a Metadata> for FileType { } impl FileType { - pub fn render(&self) -> String { - match *self { + pub fn render(self) -> String { + match self { FileType::File => Colors[&Elem::File].paint(".").to_string(), FileType::Directory => Colors[&Elem::Dir].paint("d").to_string(), FileType::Pipe => Colors[&Elem::Pipe].paint("|").to_string(), diff --git a/src/meta/mod.rs b/src/meta/mod.rs index e93af85..f9645f6 100644 --- a/src/meta/mod.rs +++ b/src/meta/mod.rs @@ -1,5 +1,6 @@ mod date; mod filetype; +mod name; mod owner; mod permissions; mod size; @@ -7,30 +8,19 @@ mod symlink; pub use self::date::Date; pub use self::filetype::FileType; +pub use self::name::Name; pub use self::owner::Owner; pub use self::permissions::Permissions; pub use self::size::Size; pub use self::symlink::SymLink; -use failure::*; use std::fs::read_link; -use std::fs::Metadata; -use std::path::{Path, PathBuf}; - -#[derive(Debug, Fail)] -pub enum MetaError { - #[fail(display = "file name not readable for {}", path)] - UnreadableName { path: String }, - #[fail(display = "invalid file name encoding for {}", path)] - Encoding { path: String }, -} +use std::path::Path; #[derive(Debug)] pub struct Meta { - pub path: PathBuf, - pub name: String, + pub name: Name, pub permissions: Permissions, - pub metadata: Metadata, pub date: Date, pub owner: Owner, pub file_type: FileType, @@ -38,25 +28,8 @@ pub struct Meta { pub symlink: Option, } -impl Meta { - pub fn from_path(path: &Path) -> Result { - // Retrieve and convert the name into an utf-8 String. - let name = match path.file_name() { - Some(os_str_name) => match os_str_name.to_str() { - Some(name) => name, - None => { - return Err(MetaError::Encoding { - path: path.display().to_string(), - }) - } - }, - None => { - return Err(MetaError::UnreadableName { - path: path.display().to_string(), - }) - } - }; - +impl<'a> From<&'a Path> for Meta { + fn from(path: &Path) -> Self { let mut metadata = path.metadata().expect("failed to retrieve metadata"); let mut symlink = None; if let Ok(target) = read_link(path) { @@ -71,16 +44,14 @@ impl Meta { let file_type = FileType::from(&metadata); let owner = Owner::from(&metadata); - Ok(Meta { + Meta { symlink, size: Size::from(&metadata), permissions: Permissions::from(&metadata), date: Date::from(&metadata), - path: path.to_path_buf(), - metadata, - name: String::from(name), + name: Name::new(&path, file_type), owner, file_type, - }) + } } } diff --git a/src/meta/name.rs b/src/meta/name.rs new file mode 100644 index 0000000..83f048a --- /dev/null +++ b/src/meta/name.rs @@ -0,0 +1,108 @@ +use color::{Colors, Elem}; +use icon; +use meta::filetype::FileType; +use std::cmp::{Ordering, PartialOrd}; +use std::path::Path; + +#[derive(Debug, Eq)] +pub struct Name { + name: String, + extension: Option, + file_type: FileType, +} + +impl Name { + pub fn new(path: &Path, file_type: FileType) -> Self { + let mut name = path + .file_name() + .expect("failed to retrieve file name") + .to_str() + .expect("failed to encode file name") + .to_string(); + + if file_type == FileType::Directory { + name.push('/') + } + + let mut extension = None; + if let Some(res) = path.extension() { + extension = Some( + res.to_str() + .expect("failed to encode file name") + .to_string(), + ); + } + + Name { + name, + extension, + file_type, + } + } + + pub fn render(&self) -> String { + let mut content = String::with_capacity(self.name.len() + 3 /* spaces */); + + let color = if self.file_type == FileType::Directory { + Colors[&Elem::Dir] + } else { + Colors[&Elem::File] + }; + + content += icon::from_name(&self); + content += " "; + content += &self.name; + + color.paint(content).to_string() + } + + pub fn name(&self) -> String { + self.name.clone() + } + + pub fn extension(&self) -> Option { + self.extension.clone() + } + + pub fn is_dir(&self) -> bool { + self.file_type == FileType::Directory + } + + pub fn is_hidden(&self) -> bool { + self.name.starts_with('.') + } +} + +impl Ord for Name { + fn cmp(&self, other: &Name) -> Ordering { + self.name.cmp(&other.name) + } +} + +impl PartialOrd for Name { + fn partial_cmp(&self, other: &Name) -> Option { + Some(self.name.cmp(&other.name)) + } +} + +impl PartialEq for Name { + fn eq(&self, other: &Name) -> bool { + let mut other_name = other.name.chars(); + + if self.name.len() != other.name.len() { + return false; + } + + for c in self.name.chars() { + if let Some(c2) = other_name.next() { + if c != c2 { + return false; + } + } else { + return false; + } + } + + true + } +}