Skip to content

Commit

Permalink
api: add convenience sort routines
Browse files Browse the repository at this point in the history
This commit adds sort_by_key and sort_by_file_name convenience routines
for common sorting needs. The signature for sort_by_key in particular
mirrors the eponymous method on slices in the standard library.

Closes #147
  • Loading branch information
Kimundi authored and BurntSushi committed Mar 22, 2021
1 parent 3d1f2f2 commit 461f4a8
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 4 deletions.
2 changes: 1 addition & 1 deletion src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ impl Error {
///
/// # Example
///
/// ```rust,no-run
/// ```rust,no_run
/// use std::io;
/// use std::path::Path;
///
Expand Down
40 changes: 38 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -377,13 +377,14 @@ impl WalkDir {
self
}

/// Set a function for sorting directory entries.
/// Set a function for sorting directory entries with a comparator
/// function.
///
/// If a compare function is set, the resulting iterator will return all
/// paths in sorted order. The compare function will be called to compare
/// entries from the same directory.
///
/// ```rust,no-run
/// ```rust,no_run
/// use std::cmp;
/// use std::ffi::OsString;
/// use walkdir::WalkDir;
Expand All @@ -398,6 +399,41 @@ impl WalkDir {
self
}

/// Set a function for sorting directory entries with a key extraction
/// function.
///
/// If a compare function is set, the resulting iterator will return all
/// paths in sorted order. The compare function will be called to compare
/// entries from the same directory.
///
/// ```rust,no_run
/// use std::cmp;
/// use std::ffi::OsString;
/// use walkdir::WalkDir;
///
/// WalkDir::new("foo").sort_by_key(|a| a.file_name().to_owned());
/// ```
pub fn sort_by_key<K, F>(self, mut cmp: F) -> Self
where
F: FnMut(&DirEntry) -> K + Send + Sync + 'static,
K: Ord,
{
self.sort_by(move |a, b| cmp(a).cmp(&cmp(b)))
}

/// Sort directory entries by file name, to ensure a deterministic order.
///
/// This is a convenience function for calling `Self::sort_by()`.
///
/// ```rust,no_run
/// use walkdir::WalkDir;
///
/// WalkDir::new("foo").sort_by_file_name();
/// ```
pub fn sort_by_file_name(self) -> Self {
self.sort_by(|a, b| a.file_name().cmp(b.file_name()))
}

/// Yield a directory's contents before the directory itself. By default,
/// this is disabled.
///
Expand Down
45 changes: 44 additions & 1 deletion src/tests/recursive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -879,7 +879,7 @@ fn filter_entry() {
}

#[test]
fn sort() {
fn sort_by() {
let dir = Dir::tmp();
dir.mkdirp("foo/bar/baz/abc");
dir.mkdirp("quux");
Expand All @@ -900,6 +900,49 @@ fn sort() {
assert_eq!(expected, r.paths());
}

#[test]
fn sort_by_key() {
let dir = Dir::tmp();
dir.mkdirp("foo/bar/baz/abc");
dir.mkdirp("quux");

let wd =
WalkDir::new(dir.path()).sort_by_key(|a| a.file_name().to_owned());
let r = dir.run_recursive(wd);
r.assert_no_errors();

let expected = vec![
dir.path().to_path_buf(),
dir.join("foo"),
dir.join("foo").join("bar"),
dir.join("foo").join("bar").join("baz"),
dir.join("foo").join("bar").join("baz").join("abc"),
dir.join("quux"),
];
assert_eq!(expected, r.paths());
}

#[test]
fn sort_by_file_name() {
let dir = Dir::tmp();
dir.mkdirp("foo/bar/baz/abc");
dir.mkdirp("quux");

let wd = WalkDir::new(dir.path()).sort_by_file_name();
let r = dir.run_recursive(wd);
r.assert_no_errors();

let expected = vec![
dir.path().to_path_buf(),
dir.join("foo"),
dir.join("foo").join("bar"),
dir.join("foo").join("bar").join("baz"),
dir.join("foo").join("bar").join("baz").join("abc"),
dir.join("quux"),
];
assert_eq!(expected, r.paths());
}

#[test]
fn sort_max_open() {
let dir = Dir::tmp();
Expand Down

0 comments on commit 461f4a8

Please sign in to comment.