Skip to content

Commit 014426f

Browse files
authored
feat: custom sorting (#4363)
1 parent 9203fd2 commit 014426f

11 files changed

Lines changed: 67 additions & 13 deletions

File tree

‎CHANGELOG.md‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/):
1414

1515
### Added
1616

17+
- Custom sorting ([#4363])
1718
- Dynamic virtual filesystem Lua API ([#4338])
1819

1920
### Changed
@@ -1882,3 +1883,4 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/):
18821883
[#4346]: https://github.com/sxyazi/yazi/pull/4346
18831884
[#4352]: https://github.com/sxyazi/yazi/pull/4352
18841885
[#4359]: https://github.com/sxyazi/yazi/pull/4359
1886+
[#4363]: https://github.com/sxyazi/yazi/pull/4363

‎CLAUDE.md‎

Lines changed: 0 additions & 1 deletion
This file was deleted.

‎yazi-actor/src/mgr/update_files.rs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ impl UpdateFiles {
9393
}
9494

9595
fn update_current(cx: &mut Ctx, op: FilesOp) -> Result<Data> {
96-
let calc = !matches!(op, FilesOp::Size(..) | FilesOp::Deleting(..));
96+
let calc = !matches!(op, FilesOp::Size(..) | FilesOp::Rank(..) | FilesOp::Deleting(..));
9797

9898
let id = cx.tab().id;
9999
if !cx.current_mut().update_pub(id, op) {

‎yazi-core/src/tab/folder.rs‎

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ impl Folder {
8686
FilesOp::Part(_, files, ticket) => self.entries.update_part(files, ticket),
8787
FilesOp::Done(..) => {}
8888
FilesOp::Size(_, sizes) => self.entries.update_size(sizes),
89+
FilesOp::Rank(_, ranks) => self.entries.update_rank(ranks),
8990
FilesOp::IOErr(..) => self.entries.update_ioerr(),
9091

9192
FilesOp::Creating(_, files) => self.entries.update_creating(files),
@@ -102,11 +103,13 @@ impl Folder {
102103
}
103104

104105
pub fn update_pub(&mut self, tab: Id, op: FilesOp) -> bool {
105-
if self.update(op) {
106+
let load = !matches!(op, FilesOp::Rank(..));
107+
if !self.update(op) {
108+
return false;
109+
} else if load {
106110
log_if_err!(Pubsub::pub_after_load(tab, &self.url, &self.stage));
107-
return true;
108111
}
109-
false
112+
true
110113
}
111114

112115
pub fn arrow(&mut self, step: impl Into<Step>) -> bool {

‎yazi-fs/src/entries.rs‎

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ pub struct Entries {
1515
pub revision: u64,
1616

1717
pub sizes: HashMap<PathBufDyn, u64>,
18+
pub ranks: HashMap<PathBufDyn, i64>,
1819

1920
sorter: FilesSorter,
2021
filter: Option<Filter>,
@@ -84,6 +85,31 @@ impl Entries {
8485
}
8586
}
8687

88+
pub fn update_rank(&mut self, mut ranks: HashMap<PathBufDyn, i64>) {
89+
let mut changed = false;
90+
91+
if self.ranks.is_empty() {
92+
ranks.retain(|key, rank| *rank != 0 && !key.is_empty());
93+
(changed, self.ranks) = (!ranks.is_empty(), mem::take(&mut ranks));
94+
}
95+
96+
for (key, rank) in ranks {
97+
if key.is_empty() {
98+
continue;
99+
}
100+
101+
changed |= if rank == 0 {
102+
self.ranks.remove(&key).is_some()
103+
} else {
104+
self.ranks.insert(key, rank) != Some(rank)
105+
};
106+
}
107+
108+
if changed && self.sorter.by == SortBy::Custom {
109+
self.revision += 1;
110+
}
111+
}
112+
87113
pub fn update_ioerr(&mut self) {
88114
self.ticket = FILES_TICKET.next();
89115
self.hidden.clear();
@@ -219,7 +245,7 @@ impl Entries {
219245
}
220246

221247
self.version = self.revision;
222-
self.sorter.sort(&mut self.items, &self.sizes);
248+
self.sorter.sort(&mut self.items, &self.sizes, &self.ranks);
223249
true
224250
}
225251

@@ -277,14 +303,14 @@ impl Entries {
277303
self.hidden = hidden;
278304
if !items.is_empty() {
279305
self.items.extend(items);
280-
self.sorter.sort(&mut self.items, &self.sizes);
306+
self.sorter.sort(&mut self.items, &self.sizes, &self.ranks);
281307
}
282308
return true;
283309
}
284310

285311
let it = mem::take(&mut self.items).into_iter().chain(mem::take(&mut self.hidden));
286312
(self.hidden, self.items) = self.split_files(it);
287-
self.sorter.sort(&mut self.items, &self.sizes);
313+
self.sorter.sort(&mut self.items, &self.sizes, &self.ranks);
288314
true
289315
}
290316

‎yazi-fs/src/op.rs‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ pub enum FilesOp {
1616
Part(UrlBuf, Vec<File>, Id),
1717
Done(File, Id),
1818
Size(UrlBuf, HashMap<PathBufDyn, u64>),
19+
Rank(UrlBuf, HashMap<PathBufDyn, i64>),
1920
IOErr(UrlBuf, yazi_shim::fs::Error),
2021

2122
Creating(UrlBuf, Vec<File>),
@@ -33,6 +34,7 @@ impl FilesOp {
3334
Self::Part(u, ..) => u,
3435
Self::Done(f, ..) => &f.url,
3536
Self::Size(u, _) => u,
37+
Self::Rank(u, _) => u,
3638
Self::IOErr(u, _) => u,
3739

3840
Self::Creating(u, _) => u,
@@ -124,7 +126,8 @@ impl FilesOp {
124126
Self::Full(file, files) => Self::Full(file.chdir(wd), files!(files)),
125127
Self::Part(_, files, ticket) => Self::Part(w, files!(files), *ticket),
126128
Self::Done(file, ticket) => Self::Done(file.chdir(wd), *ticket),
127-
Self::Size(_, map) => Self::Size(w, map.iter().map(|(key, &s)| (key.clone(), s)).collect()),
129+
Self::Size(_, map) => Self::Size(w, map.clone()),
130+
Self::Rank(_, map) => Self::Rank(w, map.clone()),
128131
Self::IOErr(_, err) => Self::IOErr(w, err.clone()),
129132

130133
Self::Creating(_, files) => Self::Creating(w, files!(files)),

‎yazi-fs/src/sorter.rs‎

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,12 @@ pub struct FilesSorter {
1717
}
1818

1919
impl FilesSorter {
20-
pub(super) fn sort(&self, items: &mut [File], sizes: &HashMap<PathBufDyn, u64>) {
20+
pub(super) fn sort(
21+
&self,
22+
items: &mut [File],
23+
sizes: &HashMap<PathBufDyn, u64>,
24+
ranks: &HashMap<PathBufDyn, i64>,
25+
) {
2126
if items.is_empty() {
2227
return;
2328
}
@@ -78,6 +83,12 @@ impl FilesSorter {
7883
self.cmp(rng.next_u64(), rng.next_u64())
7984
})
8085
}
86+
SortBy::Custom => items.sort_unstable_by(|a, b| {
87+
promote!(a, b);
88+
let aa = ranks.get(&a.key()).copied().unwrap_or_default();
89+
let bb = ranks.get(&b.key()).copied().unwrap_or_default();
90+
self.fallback(a, b, self.cmp(aa, bb))
91+
}),
8192
}
8293
}
8394

‎yazi-fs/src/sorting.rs‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ pub enum SortBy {
1717
Natural,
1818
Size,
1919
Random,
20+
Custom,
2021
}
2122

2223
// --- fallback

‎yazi-fs/src/stage.rs‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ pub enum FolderStage {
99
Loaded,
1010
Failed(yazi_shim::fs::Error),
1111
}
12+
1213
impl UserData for FolderStage {
1314
fn add_methods<M: UserDataMethods<Self>>(methods: &mut M) {
1415
methods.add_meta_method(MetaMethod::Call, |lua, me, ()| {

‎yazi-plugin/src/fs/fs.rs‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@ fn op(lua: &Lua) -> mlua::Result<Function> {
146146
b"part" => super::FilesOp::part(lua, t),
147147
b"done" => super::FilesOp::done(lua, t),
148148
b"size" => super::FilesOp::size(lua, t),
149+
b"rank" => super::FilesOp::rank(lua, t),
149150
b"upsert" => super::FilesOp::upsert(lua, t),
150151
_ => Err("Unknown operation".into_lua_err())?,
151152
})

0 commit comments

Comments
 (0)