diff --git a/src/colours.rs b/src/colours.rs index 5085290..97ccd87 100644 --- a/src/colours.rs +++ b/src/colours.rs @@ -1,7 +1,6 @@ use ansi_term::Style; use ansi_term::Colour::{Red, Green, Yellow, Blue, Cyan, Purple, Fixed}; -use std::default::Default; #[derive(Clone, Copy, Debug, Default, PartialEq)] pub struct Colours { diff --git a/src/column.rs b/src/column.rs index 4bacba1..23e2a4b 100644 --- a/src/column.rs +++ b/src/column.rs @@ -1,10 +1,9 @@ use std::iter::repeat; -use options::{SizeFormat, TimeType}; - use ansi_term::Style; use unicode_width::UnicodeWidthStr; +use options::{SizeFormat, TimeType}; #[derive(PartialEq, Debug, Copy, Clone)] diff --git a/src/dir.rs b/src/dir.rs index 7bbeda7..932b04d 100644 --- a/src/dir.rs +++ b/src/dir.rs @@ -1,10 +1,11 @@ -use feature::Git; -use file::{File, fields}; - use std::io; use std::fs; use std::path::{Path, PathBuf}; +use feature::Git; +use file::{File, fields}; + + /// A **Dir** provides a cached list of the file paths in a directory that's /// being listed. /// diff --git a/src/feature/git.rs b/src/feature/git.rs index 59c3a8b..faa3d51 100644 --- a/src/feature/git.rs +++ b/src/feature/git.rs @@ -4,6 +4,7 @@ use git2; use file::fields; + /// Container of Git statuses for all the files in this folder's Git repository. pub struct Git { statuses: Vec<(PathBuf, git2::Status)>, diff --git a/src/feature/mod.rs b/src/feature/mod.rs index a6993b4..24ebbe9 100644 --- a/src/feature/mod.rs +++ b/src/feature/mod.rs @@ -8,6 +8,8 @@ #[cfg(not(any(target_os = "macos", target_os = "linux")))] use std::old_io as io; #[cfg(not(any(target_os = "macos", target_os = "linux")))] + + #[derive(Clone)] pub struct Attribute; @@ -38,7 +40,6 @@ impl Attribute { } - // Git support #[cfg(feature="git")] mod git; @@ -47,6 +48,7 @@ impl Attribute { #[cfg(not(feature="git"))] pub struct Git; #[cfg(not(feature="git"))] use std::path::Path; #[cfg(not(feature="git"))] use file::fields; + #[cfg(not(feature="git"))] impl Git { pub fn scan(_: &Path) -> Result { diff --git a/src/feature/xattr_darwin.rs b/src/feature/xattr_darwin.rs index 4d0abd8..c281d5c 100644 --- a/src/feature/xattr_darwin.rs +++ b/src/feature/xattr_darwin.rs @@ -2,17 +2,20 @@ extern crate libc; use std::io; +use std::mem; use std::path::Path; use std::ptr; -use std::mem; + use self::libc::{c_int, size_t, ssize_t, c_char, c_void, uint32_t}; /// Don't follow symbolic links const XATTR_NOFOLLOW: c_int = 0x0001; + /// Expose HFS Compression extended attributes const XATTR_SHOWCOMPRESSION: c_int = 0x0020; + extern "C" { fn listxattr(path: *const c_char, namebuf: *mut c_char, size: size_t, options: c_int) -> ssize_t; @@ -21,6 +24,7 @@ extern "C" { options: c_int) -> ssize_t; } + /// Attributes which can be passed to `Attribute::list_with_flags` #[derive(Copy, Clone)] pub enum ListFlags { @@ -30,6 +34,7 @@ pub enum ListFlags { ShowCompression = XATTR_SHOWCOMPRESSION as isize } + /// Extended attribute #[derive(Debug, Clone)] pub struct Attribute { diff --git a/src/feature/xattr_linux.rs b/src/feature/xattr_linux.rs index 9e7fd23..9d8f6fd 100644 --- a/src/feature/xattr_linux.rs +++ b/src/feature/xattr_linux.rs @@ -5,8 +5,10 @@ use std::ffi::CString; use std::io; use std::path::Path; use std::ptr; + use self::libc::{size_t, ssize_t, c_char, c_void}; + extern "C" { fn listxattr(path: *const c_char, list: *mut c_char, size: size_t) -> ssize_t; fn llistxattr(path: *const c_char, list: *mut c_char, size: size_t) -> ssize_t; @@ -18,6 +20,7 @@ extern "C" { ) -> ssize_t; } + /// Attributes which can be passed to `Attribute::list_with_flags` #[derive(Copy, Clone)] pub enum FollowSymlinks { @@ -25,6 +28,7 @@ pub enum FollowSymlinks { No } + /// Extended attribute #[derive(Debug, Clone)] pub struct Attribute { diff --git a/src/file.rs b/src/file.rs index c3798aa..3d432cb 100644 --- a/src/file.rs +++ b/src/file.rs @@ -423,6 +423,7 @@ fn ext(name: &str) -> Option { name.rfind('.').map(|p| name[p+1..].to_ascii_lowercase()) } + /// Wrapper types for the values returned from `File` objects. /// /// The methods of `File` don't return formatted strings; neither do they diff --git a/src/filetype.rs b/src/filetype.rs index d9ea071..ed2f369 100644 --- a/src/filetype.rs +++ b/src/filetype.rs @@ -3,6 +3,7 @@ use ansi_term::Style; use file::File; use colours::Colours; + pub fn file_colour(colours: &Colours, file: &File) -> Style { match file { f if f.is_directory() => colours.filetypes.directory, @@ -23,6 +24,7 @@ pub fn file_colour(colours: &Colours, file: &File) -> Style { } } + trait FileTypes { fn is_immediate(&self) -> bool; fn is_image(&self) -> bool; @@ -114,6 +116,7 @@ impl<'_> FileTypes for File<'_> { } } + #[cfg(broken_test)] mod test { use super::*; diff --git a/src/main.rs b/src/main.rs index cc4cb85..1e64a67 100644 --- a/src/main.rs +++ b/src/main.rs @@ -11,18 +11,19 @@ extern crate num_cpus; extern crate number_prefix; extern crate pad; extern crate threadpool; -extern crate users; extern crate unicode_width; +extern crate users; #[cfg(feature="git")] extern crate git2; + use std::env; use std::fs; use std::path::{Component, Path, PathBuf}; +use std::sync::mpsc::channel; use threadpool::ThreadPool; -use std::sync::mpsc::channel; use dir::Dir; use file::File; @@ -183,6 +184,7 @@ impl<'dir> Exa<'dir> { } } + #[cfg(not(test))] fn main() { let args: Vec = env::args().collect(); diff --git a/src/options.rs b/src/options.rs index d1619a9..542ac3c 100644 --- a/src/options.rs +++ b/src/options.rs @@ -1,13 +1,5 @@ -use colours::Colours; -use dir::Dir; -use file::File; -use column::Column; -use column::Column::*; -use feature::Attribute; -use output::{Grid, Details, Lines}; -use term::dimensions; - -use std::cmp::Ordering; +use std::cmp; +use std::default; use std::fmt; use std::num::ParseIntError; use std::os::unix::fs::MetadataExt; @@ -15,7 +7,15 @@ use std::os::unix::fs::MetadataExt; use getopts; use natord; -use self::Misfire::*; +use colours::Colours; +use column::Column; +use column::Column::*; +use dir::Dir; +use feature::Attribute; +use file::File; +use output::{Grid, Details, Lines}; +use term::dimensions; + /// The *Options* struct represents a parsed version of the user's /// command-line options. @@ -26,21 +26,6 @@ pub struct Options { pub view: View, } -#[derive(PartialEq, Debug, Copy, Clone)] -pub struct FileFilter { - list_dirs_first: bool, - reverse: bool, - show_invisibles: bool, - sort_field: SortField, -} - -#[derive(PartialEq, Debug, Copy, Clone)] -pub enum View { - Details(Details), - Lines(Lines), - Grid(Grid), -} - impl Options { /// Call getopts on the given slice of command-line strings. @@ -126,6 +111,15 @@ impl Options { } } + +#[derive(PartialEq, Debug, Copy, Clone)] +pub struct FileFilter { + list_dirs_first: bool, + reverse: bool, + show_invisibles: bool, + sort_field: SortField, +} + impl FileFilter { /// Transform the files (sorting, reversing, filtering) before listing them. pub fn transform_files(&self, files: &mut Vec) { @@ -143,8 +137,8 @@ impl FileFilter { SortField::AccessedDate => files.sort_by(|a, b| a.metadata.as_raw().atime().cmp(&b.metadata.as_raw().atime())), SortField::CreatedDate => files.sort_by(|a, b| a.metadata.as_raw().ctime().cmp(&b.metadata.as_raw().ctime())), SortField::Extension => files.sort_by(|a, b| match a.ext.cmp(&b.ext) { - Ordering::Equal => natord::compare(&*a.name, &*b.name), - order => order, + cmp::Ordering::Equal => natord::compare(&*a.name, &*b.name), + order => order, }), } @@ -166,7 +160,7 @@ pub enum SortField { ModifiedDate, AccessedDate, CreatedDate, } -impl Default for SortField { +impl default::Default for SortField { fn default() -> SortField { SortField::Name } @@ -195,6 +189,7 @@ impl SortField { } } + /// One of these things could happen instead of listing files. #[derive(PartialEq, Debug)] pub enum Misfire { @@ -227,13 +222,15 @@ pub enum Misfire { impl Misfire { /// The OS return code this misfire should signify. pub fn error_code(&self) -> i32 { - if let Help(_) = *self { 2 } - else { 3 } + if let Misfire::Help(_) = *self { 2 } + else { 3 } } } impl fmt::Display for Misfire { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + use self::Misfire::*; + match *self { InvalidOptions(ref e) => write!(f, "{}", e), Help(ref text) => write!(f, "{}", text), @@ -247,14 +244,24 @@ impl fmt::Display for Misfire { } } + +#[derive(PartialEq, Debug, Copy, Clone)] +pub enum View { + Details(Details), + Lines(Lines), + Grid(Grid), +} + impl View { pub fn deduce(matches: &getopts::Matches, filter: FileFilter, dir_action: DirAction) -> Result { + use self::Misfire::*; + if matches.opt_present("long") { if matches.opt_present("across") { - Err(Misfire::Useless("across", true, "long")) + Err(Useless("across", true, "long")) } else if matches.opt_present("oneline") { - Err(Misfire::Useless("oneline", true, "long")) + Err(Useless("oneline", true, "long")) } else { let details = Details { @@ -269,45 +276,45 @@ impl View { } } else if matches.opt_present("binary") { - Err(Misfire::Useless("binary", false, "long")) + Err(Useless("binary", false, "long")) } else if matches.opt_present("bytes") { - Err(Misfire::Useless("bytes", false, "long")) + Err(Useless("bytes", false, "long")) } else if matches.opt_present("inode") { - Err(Misfire::Useless("inode", false, "long")) + Err(Useless("inode", false, "long")) } else if matches.opt_present("links") { - Err(Misfire::Useless("links", false, "long")) + Err(Useless("links", false, "long")) } else if matches.opt_present("header") { - Err(Misfire::Useless("header", false, "long")) + Err(Useless("header", false, "long")) } else if matches.opt_present("blocks") { - Err(Misfire::Useless("blocks", false, "long")) + Err(Useless("blocks", false, "long")) } else if cfg!(feature="git") && matches.opt_present("git") { - Err(Misfire::Useless("git", false, "long")) + Err(Useless("git", false, "long")) } else if matches.opt_present("time") { - Err(Misfire::Useless("time", false, "long")) + Err(Useless("time", false, "long")) } else if matches.opt_present("tree") { - Err(Misfire::Useless("tree", false, "long")) + Err(Useless("tree", false, "long")) } else if matches.opt_present("group") { - Err(Misfire::Useless("group", false, "long")) + Err(Useless("group", false, "long")) } else if matches.opt_present("level") && !matches.opt_present("recurse") { - Err(Misfire::Useless2("level", "recurse", "tree")) + Err(Useless2("level", "recurse", "tree")) } else if Attribute::feature_implemented() && matches.opt_present("extended") { - Err(Misfire::Useless("extended", false, "long")) + Err(Useless("extended", false, "long")) } else if let Some((width, _)) = dimensions() { if matches.opt_present("oneline") { if matches.opt_present("across") { - Err(Misfire::Useless("across", true, "oneline")) + Err(Useless("across", true, "oneline")) } else { let lines = Lines { @@ -341,7 +348,6 @@ impl View { } - #[derive(PartialEq, Debug, Copy, Clone)] pub enum SizeFormat { DecimalBytes, @@ -349,7 +355,7 @@ pub enum SizeFormat { JustBytes, } -impl Default for SizeFormat { +impl default::Default for SizeFormat { fn default() -> SizeFormat { SizeFormat::DecimalBytes } @@ -393,7 +399,7 @@ pub struct TimeTypes { created: bool, } -impl Default for TimeTypes { +impl default::Default for TimeTypes { fn default() -> TimeTypes { TimeTypes { accessed: false, modified: true, created: false } } @@ -599,12 +605,11 @@ impl Columns { mod test { use super::Options; use super::Misfire; - use super::Misfire::*; use feature::Attribute; fn is_helpful(misfire: Result) -> bool { match misfire { - Err(Help(_)) => true, + Misfire::Err(Help(_)) => true, _ => false, } } diff --git a/src/output/details.rs b/src/output/details.rs index 44b5f96..84da4de 100644 --- a/src/output/details.rs +++ b/src/output/details.rs @@ -1,25 +1,25 @@ use colours::Colours; use column::{Alignment, Column, Cell}; -use feature::Attribute; use dir::Dir; -use file::File; +use feature::Attribute; use file::fields as f; +use file::File; use options::{Columns, FileFilter, RecurseOptions, SizeFormat}; -use users::{OSUsers, Users}; -use users::mock::MockUsers; - -use super::filename; - use ansi_term::{ANSIString, ANSIStrings, Style}; +use datetime::local::{LocalDateTime, DatePiece}; +use datetime::format::{DateFormat}; +use datetime::zoned::{VariableOffset, TimeZone}; + use locale; use number_prefix::{binary_prefix, decimal_prefix, Prefixed, Standalone, PrefixNames}; -use datetime::local::{LocalDateTime, DatePiece}; -use datetime::format::{DateFormat}; -use datetime::zoned::{VariableOffset, TimeZone}; +use users::{OSUsers, Users}; +use users::mock::MockUsers; + +use super::filename; /// With the **Details** view, the output gets formatted into columns, with @@ -97,6 +97,7 @@ impl Details { } } + struct Row { /// Vector of cells to display. @@ -122,6 +123,7 @@ struct Row { children: bool, } + /// A **Table** object gets built up by the view as it lists files and /// directories. pub struct Table { @@ -427,6 +429,7 @@ impl Table where U: Users { } } + #[derive(PartialEq, Debug, Clone)] enum TreePart { diff --git a/src/output/grid.rs b/src/output/grid.rs index 0c2e950..0782ea3 100644 --- a/src/output/grid.rs +++ b/src/output/grid.rs @@ -1,11 +1,13 @@ +use std::cmp::max; +use std::iter::repeat; + use colours::Colours; use column::Alignment::Left; use file::File; use filetype::file_colour; + use super::lines::Lines; -use std::cmp::max; -use std::iter::repeat; #[derive(PartialEq, Debug, Copy, Clone)] pub struct Grid { diff --git a/src/output/lines.rs b/src/output/lines.rs index bd1fcdc..1d6dade 100644 --- a/src/output/lines.rs +++ b/src/output/lines.rs @@ -1,7 +1,9 @@ use colours::Colours; use file::File; + use super::filename; + #[derive(Clone, Copy, Debug, PartialEq)] pub struct Lines { pub colours: Colours, diff --git a/src/output/mod.rs b/src/output/mod.rs index ebb11ce..ea48507 100644 --- a/src/output/mod.rs +++ b/src/output/mod.rs @@ -1,16 +1,18 @@ -mod grid; -pub mod details; -mod lines; +use ansi_term::ANSIStrings; use colours::Colours; use file::File; use filetype::file_colour; -use ansi_term::ANSIStrings; -pub use self::grid::Grid; pub use self::details::Details; +pub use self::grid::Grid; pub use self::lines::Lines; +mod grid; +pub mod details; +mod lines; + + pub fn filename(file: &File, colours: &Colours) -> String { if file.is_link() { symlink_filename(file, colours) diff --git a/src/term.rs b/src/term.rs index a3ba130..7f69b54 100644 --- a/src/term.rs +++ b/src/term.rs @@ -1,6 +1,6 @@ mod c { - pub use libc::{c_int, c_ushort, c_ulong, STDOUT_FILENO}; use std::mem::zeroed; + use libc::{c_int, c_ushort, c_ulong, STDOUT_FILENO}; // Getting the terminal size is done using an ioctl command that // takes the file handle to the terminal (which in our case is