Sync viewer navigation with browser sorting
This commit is contained in:
parent
bb73c1abea
commit
f0d5cf3496
5 changed files with 375 additions and 87 deletions
|
|
@ -45,7 +45,12 @@ pub enum SortDirection {
|
|||
Descending,
|
||||
}
|
||||
|
||||
pub fn sort_entries(entries: &mut [BrowserEntry], field: SortField, direction: SortDirection) {
|
||||
pub fn sort_entries(
|
||||
entries: &mut [BrowserEntry],
|
||||
field: SortField,
|
||||
direction: SortDirection,
|
||||
case_insensitive: bool,
|
||||
) {
|
||||
entries.sort_by(|left, right| {
|
||||
let kind_order = match (
|
||||
left.kind == EntryKind::Directory,
|
||||
|
|
@ -60,11 +65,24 @@ pub fn sort_entries(entries: &mut [BrowserEntry], field: SortField, direction: S
|
|||
}
|
||||
|
||||
match field {
|
||||
SortField::Name => apply_direction(natural_cmp(&left.name, &right.name), direction),
|
||||
SortField::Name => apply_direction(
|
||||
natural_cmp_with_case(&left.name, &right.name, case_insensitive),
|
||||
direction,
|
||||
),
|
||||
SortField::Modified => compare_optional_time(left.modified, right.modified, direction)
|
||||
.then_with(|| apply_direction(natural_cmp(&left.name, &right.name), direction)),
|
||||
.then_with(|| {
|
||||
apply_direction(
|
||||
natural_cmp_with_case(&left.name, &right.name, case_insensitive),
|
||||
direction,
|
||||
)
|
||||
}),
|
||||
SortField::Created => compare_optional_time(left.created, right.created, direction)
|
||||
.then_with(|| apply_direction(natural_cmp(&left.name, &right.name), direction)),
|
||||
.then_with(|| {
|
||||
apply_direction(
|
||||
natural_cmp_with_case(&left.name, &right.name, case_insensitive),
|
||||
direction,
|
||||
)
|
||||
}),
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -104,13 +122,13 @@ pub fn classify_file(path: &Path) -> EntryKind {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn natural_cmp(left: &str, right: &str) -> Ordering {
|
||||
pub fn natural_cmp_with_case(left: &str, right: &str, case_insensitive: bool) -> Ordering {
|
||||
let mut left_chars = left.chars().peekable();
|
||||
let mut right_chars = right.chars().peekable();
|
||||
|
||||
loop {
|
||||
match (left_chars.peek(), right_chars.peek()) {
|
||||
(None, None) => return Ordering::Equal,
|
||||
(None, None) => return left.cmp(right),
|
||||
(None, Some(_)) => return Ordering::Less,
|
||||
(Some(_), None) => return Ordering::Greater,
|
||||
(Some(left_char), Some(right_char))
|
||||
|
|
@ -143,10 +161,11 @@ pub fn natural_cmp(left: &str, right: &str) -> Ordering {
|
|||
(Some(_), Some(_)) => {
|
||||
let left_char = left_chars.next().unwrap();
|
||||
let right_char = right_chars.next().unwrap();
|
||||
let order = left_char
|
||||
.to_lowercase()
|
||||
.cmp(right_char.to_lowercase())
|
||||
.then_with(|| left_char.cmp(&right_char));
|
||||
let order = if case_insensitive {
|
||||
left_char.to_lowercase().cmp(right_char.to_lowercase())
|
||||
} else {
|
||||
left_char.cmp(&right_char)
|
||||
};
|
||||
if order != Ordering::Equal {
|
||||
return order;
|
||||
}
|
||||
|
|
@ -173,18 +192,30 @@ mod tests {
|
|||
#[test]
|
||||
fn natural_order_places_two_before_ten() {
|
||||
let mut names = ["page10.jpg", "page2.jpg", "page1.jpg"];
|
||||
names.sort_by(|left, right| natural_cmp(left, right));
|
||||
names.sort_by(|left, right| natural_cmp_with_case(left, right, true));
|
||||
assert_eq!(names, ["page1.jpg", "page2.jpg", "page10.jpg"]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn natural_order_handles_numbers_larger_than_integers() {
|
||||
assert_eq!(
|
||||
natural_cmp("9.zip", "123456789012345678901234567890.zip"),
|
||||
natural_cmp_with_case("9.zip", "123456789012345678901234567890.zip", true),
|
||||
Ordering::Less
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn natural_order_can_ignore_or_respect_case() {
|
||||
assert_eq!(
|
||||
natural_cmp_with_case("a2.jpg", "A10.jpg", true),
|
||||
Ordering::Less
|
||||
);
|
||||
assert_eq!(
|
||||
natural_cmp_with_case("a2.jpg", "A10.jpg", false),
|
||||
Ordering::Greater
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn zip_extension_is_case_insensitive() {
|
||||
assert_eq!(classify_file(Path::new("comic.ZIP")), EntryKind::ZipArchive);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue