summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBenjamin Sago <ogham@bsago.me>2016-03-18 10:11:43 -0400
committerBenjamin Sago <ogham@bsago.me>2016-03-18 10:20:44 -0400
commit3e9616cffababc491b1fa587e008a0bdb385901c (patch)
tree82fc7f858cf817cd148c93b612e0eb32f48f1eed
parentd3846468a3c7089bffac559af2cae6b685ab1ed5 (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.rs56
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() ]);