1use crate::tree::TreeEntry;
2
3#[derive(Debug, Clone, Default)]
5pub enum SortKey {
6 #[default]
7 Name,
8 Size,
9 Time,
10 None,
11}
12
13impl SortKey {
14 pub fn from_str(s: &str) -> Self {
15 match s.to_lowercase().as_str() {
16 "name" => SortKey::Name,
17 "size" => SortKey::Size,
18 "mtime" | "time" => SortKey::Time,
19 "none" => SortKey::None,
20 _ => SortKey::Name,
21 }
22 }
23}
24
25pub struct Sorter {
27 key: SortKey,
28 reverse: bool,
29 dirs_first: bool,
30}
31
32impl Sorter {
33 pub fn new(key: SortKey, reverse: bool, dirs_first: bool) -> Self {
34 Self {
35 key,
36 reverse,
37 dirs_first,
38 }
39 }
40
41 pub fn sort(&self, entries: &mut [TreeEntry]) {
42 if matches!(self.key, SortKey::None) && !self.dirs_first {
43 return;
44 }
45
46 entries.sort_by(|a, b| {
47 if self.dirs_first {
49 match (a.is_dir, b.is_dir) {
50 (true, false) => return std::cmp::Ordering::Less,
51 (false, true) => return std::cmp::Ordering::Greater,
52 _ => {}
53 }
54 }
55
56 let ordering = match self.key {
57 SortKey::Name => a.name.to_lowercase().cmp(&b.name.to_lowercase()),
58 SortKey::Size => a.size().cmp(&b.size()),
59 SortKey::Time => {
60 let a_time = a.modified();
61 let b_time = b.modified();
62 match (a_time, b_time) {
63 (Some(at), Some(bt)) => at.cmp(&bt),
64 (Some(_), None) => std::cmp::Ordering::Less,
65 (None, Some(_)) => std::cmp::Ordering::Greater,
66 (None, None) => std::cmp::Ordering::Equal,
67 }
68 }
69 SortKey::None => std::cmp::Ordering::Equal,
70 };
71
72 if self.reverse {
73 ordering.reverse()
74 } else {
75 ordering
76 }
77 });
78 }
79}