Skip to content

Commit

Permalink
Add sorting by type
Browse files Browse the repository at this point in the history
This isn’t perfect, as a file’s type isn’t cached, so it gets recomputed for every comparison in the sort! We can’t go off the file’s `st_mode` flag because it’s not guaranteed to be in any order between systems.
  • Loading branch information
ogham committed Jun 29, 2017
1 parent 7d1448d commit f750536
Show file tree
Hide file tree
Showing 5 changed files with 38 additions and 5 deletions.
5 changes: 4 additions & 1 deletion src/fs/fields.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
16 changes: 14 additions & 2 deletions src/options/filter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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 {
Expand All @@ -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))
}
}
Expand Down
9 changes: 7 additions & 2 deletions xtests/run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
10 changes: 10 additions & 0 deletions xtests/sort-by-type
Original file line number Diff line number Diff line change
@@ -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
3 changes: 3 additions & 0 deletions xtests/specials_sort
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
named-pipe
char-device
block-device

0 comments on commit f750536

Please sign in to comment.