diff --git a/src/fs/fields.rs b/src/fs/fields.rs index 65e52897..07b41dc8 100644 --- a/src/fs/fields.rs +++ b/src/fs/fields.rs @@ -40,8 +40,11 @@ pub type uid_t = u32; /// This type is set entirely by the filesystem, rather than relying on a /// file’s contents. So “link” is a type, but “image” is just a type of /// regular file. (See the `filetype` module for those checks.) +/// +/// Its ordering is used when sorting by type. +#[derive(PartialEq, Eq, PartialOrd, Ord)] pub enum Type { - File, Directory, Pipe, Link, Socket, CharDevice, BlockDevice, Special, + Directory, File, Link, Pipe, Socket, CharDevice, BlockDevice, Special, } impl Type { diff --git a/src/options/filter.rs b/src/options/filter.rs index c608cfc1..8493b245 100644 --- a/src/options/filter.rs +++ b/src/options/filter.rs @@ -135,6 +135,11 @@ impl FileFilter { SortField::AccessedDate => a.metadata.atime().cmp(&b.metadata.atime()), SortField::CreatedDate => a.metadata.ctime().cmp(&b.metadata.ctime()), + SortField::FileType => match a.type_char().cmp(&b.type_char()) { // todo: this recomputes + Ordering::Equal => natord::compare(&*a.name, &*b.name), + order => order, + }, + SortField::Extension(Sensitive) => match a.ext.cmp(&b.ext) { Ordering::Equal => natord::compare(&*a.name, &*b.name), order => order, @@ -195,6 +200,12 @@ pub enum SortField { /// In original Unix, this was, however, meant as creation time. /// https://www.bell-labs.com/usr/dmr/www/cacm.html CreatedDate, + + /// The type of the file: directories, links, pipes, regular, files, etc. + /// + /// Files are ordered according to the `PartialOrd` implementation of + /// `fs::fields::Type`, so changing that will change this. + FileType, } /// Whether a field should be sorted case-sensitively or case-insensitively. @@ -226,7 +237,7 @@ impl SortField { const SORTS: &[&str] = &[ "name", "Name", "size", "extension", "Extension", "modified", "accessed", - "created", "inode", "none" ]; + "created", "inode", "type", "none" ]; if let Some(word) = matches.opt_str("sort") { match &*word { @@ -238,8 +249,9 @@ impl SortField { "mod" | "modified" => Ok(SortField::ModifiedDate), "acc" | "accessed" => Ok(SortField::AccessedDate), "cr" | "created" => Ok(SortField::CreatedDate), - "none" => Ok(SortField::Unsorted), "inode" => Ok(SortField::FileInode), + "type" => Ok(SortField::FileType), + "none" => Ok(SortField::Unsorted), field => Err(Misfire::bad_argument("sort", field, SORTS)) } } diff --git a/xtests/run.sh b/xtests/run.sh index df1e3ffa..2d6c7e03 100755 --- a/xtests/run.sh +++ b/xtests/run.sh @@ -85,14 +85,19 @@ $exa $testcases/file-names-exts -1 2>&1 --sort=name | diff -q - $results/file-na $exa $testcases/file-names-exts -1 2>&1 --sort=Ext | diff -q - $results/file-names-exts-ext || exit 1 $exa $testcases/file-names-exts -1 2>&1 --sort=ext | diff -q - $results/file-names-exts-ext-case || exit 1 +# Pass multiple input arguments because there aren’t enough of different types +# in one directory already +$exa $testcases/links -1 --sort=type 2>&1 | diff -q - $results/sort-by-type || exit 1 + # We can’t guarantee inode numbers, but we can at least check that they’re in # order. The inode column is the leftmost one, so sort works for this. $exa $testcases/file-names-exts --long --inode --sort=inode | sort --check || exit 1 # Other file types -$exa $testcases/specials -l 2>&1 | diff -q - $results/specials || exit 1 -$exa $testcases/specials -F -l 2>&1 | diff -q - $results/specials_F || exit 1 +$exa $testcases/specials -l 2>&1 | diff -q - $results/specials || exit 1 +$exa $testcases/specials -F -l 2>&1 | diff -q - $results/specials_F || exit 1 +$exa $testcases/specials --sort=type -1 2>&1 | diff -q - $results/specials_sort || exit 1 # Ignores diff --git a/xtests/sort-by-type b/xtests/sort-by-type new file mode 100644 index 00000000..3bbecbeb --- /dev/null +++ b/xtests/sort-by-type @@ -0,0 +1,10 @@ +some_file +broken -> nowhere +current_dir -> . +forbidden -> /proc/1/root +itself -> itself +parent_dir -> .. +root -> / +some_file_absolute -> /testcases/links/some_file +some_file_relative -> some_file +usr -> /usr diff --git a/xtests/specials_sort b/xtests/specials_sort new file mode 100644 index 00000000..dbf551e4 --- /dev/null +++ b/xtests/specials_sort @@ -0,0 +1,3 @@ +named-pipe +char-device +block-device