diff options
author | Benjamin Sago <ogham@bsago.me> | 2016-03-18 10:11:43 -0400 |
---|---|---|
committer | Benjamin Sago <ogham@bsago.me> | 2016-03-18 10:20:44 -0400 |
commit | 3e9616cffababc491b1fa587e008a0bdb385901c (patch) | |
tree | 82fc7f858cf817cd148c93b612e0eb32f48f1eed | |
parent | d3846468a3c7089bffac559af2cae6b685ab1ed5 (diff) |
Add --sort=Name case-insensitive sorting
This uses the case-insensitive sort function in the `natord` crate to
convert both strings to lowercase lazily, sorting them as it goes. It
also adds tests for `--sort` in general.
The case sensitivity has been made an enum so it can be reused for other
fields (say, the file extension).
See #102.
-rw-r--r-- | src/options.rs | 56 |
1 files changed, 43 insertions, 13 deletions
diff --git a/src/options.rs b/src/options.rs index c9baa2e..9ff9e86 100644 --- a/src/options.rs +++ b/src/options.rs @@ -363,15 +363,18 @@ impl FileFilter { } pub fn compare_files(&self, a: &File, b: &File) -> cmp::Ordering { + use self::SortCase::{Sensitive, Insensitive}; + match self.sort_field { - SortField::Unsorted => cmp::Ordering::Equal, - SortField::Name => natord::compare(&*a.name, &*b.name), - SortField::Size => a.metadata.len().cmp(&b.metadata.len()), - SortField::FileInode => a.metadata.ino().cmp(&b.metadata.ino()), - SortField::ModifiedDate => a.metadata.mtime().cmp(&b.metadata.mtime()), - SortField::AccessedDate => a.metadata.atime().cmp(&b.metadata.atime()), - SortField::CreatedDate => a.metadata.ctime().cmp(&b.metadata.ctime()), - SortField::Extension => match a.ext.cmp(&b.ext) { + SortField::Unsorted => cmp::Ordering::Equal, + SortField::Name(Sensitive) => natord::compare(&a.name, &b.name), + SortField::Name(Insensitive) => natord::compare_ignore_case(&a.name, &b.name), + SortField::Size => a.metadata.len().cmp(&b.metadata.len()), + SortField::FileInode => a.metadata.ino().cmp(&b.metadata.ino()), + SortField::ModifiedDate => a.metadata.mtime().cmp(&b.metadata.mtime()), + SortField::AccessedDate => a.metadata.atime().cmp(&b.metadata.atime()), + SortField::CreatedDate => a.metadata.ctime().cmp(&b.metadata.ctime()), + SortField::Extension => match a.ext.cmp(&b.ext) { cmp::Ordering::Equal => natord::compare(&*a.name, &*b.name), order => order, }, @@ -459,13 +462,22 @@ impl RecurseOptions { /// User-supplied field to sort by. #[derive(PartialEq, Debug, Copy, Clone)] pub enum SortField { - Unsorted, Name, Extension, Size, FileInode, + Unsorted, Name(SortCase), Extension, Size, FileInode, ModifiedDate, AccessedDate, CreatedDate, } +/// Whether a field should be sorted case-sensitively or case-insensitively. +/// +/// This determines which of the `natord` functions to use. +#[derive(PartialEq, Debug, Copy, Clone)] +pub enum SortCase { + Sensitive, + Insensitive, +} + impl Default for SortField { fn default() -> SortField { - SortField::Name + SortField::Name(SortCase::Sensitive) } } @@ -473,7 +485,8 @@ impl OptionSet for SortField { fn deduce(matches: &getopts::Matches) -> Result<SortField, Misfire> { if let Some(word) = matches.opt_str("sort") { match &*word { - "name" | "filename" => Ok(SortField::Name), + "name" | "filename" => Ok(SortField::Name(SortCase::Sensitive)), + "Name" | "Filename" => Ok(SortField::Name(SortCase::Insensitive)), "size" | "filesize" => Ok(SortField::Size), "ext" | "extension" => Ok(SortField::Extension), "mod" | "modified" => Ok(SortField::ModifiedDate), @@ -732,8 +745,7 @@ static EXTENDED_HELP: &'static str = r##" -@, --extended display extended a #[cfg(test)] mod test { - use super::Options; - use super::Misfire; + use super::{Options, Misfire, SortField, SortCase}; use feature::xattr; fn is_helpful<T>(misfire: Result<T, Misfire>) -> bool { @@ -828,6 +840,24 @@ mod test { } #[test] + fn test_sort_size() { + let opts = Options::getopts(&[ "--sort=size".to_string() ]); + assert_eq!(opts.unwrap().0.filter.sort_field, SortField::Size); + } + + #[test] + fn test_sort_name() { + let opts = Options::getopts(&[ "--sort=name".to_string() ]); + assert_eq!(opts.unwrap().0.filter.sort_field, SortField::Name(SortCase::Sensitive)); + } + + #[test] + fn test_sort_name_lowercase() { + let opts = Options::getopts(&[ "--sort=Name".to_string() ]); + assert_eq!(opts.unwrap().0.filter.sort_field, SortField::Name(SortCase::Insensitive)); + } + + #[test] #[cfg(feature="git")] fn just_git() { let opts = Options::getopts(&[ "--git".to_string() ]); |