feat: reserve user input order

This commit is contained in:
Yongwoo Lee 2024-10-22 21:21:32 +09:00
parent 212829370f
commit bbeeacfe71

View file

@ -1,12 +1,24 @@
use std::{borrow::Cow, collections::HashMap, ffi::{OsStr, OsString}, io::{BufWriter, Write, stderr}, path::PathBuf}; use std::{
borrow::Cow,
collections::HashMap,
ffi::{OsStr, OsString},
io::{stderr, BufWriter, Write},
path::PathBuf,
};
use anyhow::{Result, anyhow}; use anyhow::{anyhow, Result};
use scopeguard::defer; use scopeguard::defer;
use tokio::{fs::{self, OpenOptions}, io::{AsyncReadExt, AsyncWriteExt, stdin}}; use tokio::{
fs::{self, OpenOptions},
io::{stdin, AsyncReadExt, AsyncWriteExt},
};
use yazi_config::{OPEN, PREVIEW}; use yazi_config::{OPEN, PREVIEW};
use yazi_dds::Pubsub; use yazi_dds::Pubsub;
use yazi_proxy::{AppProxy, HIDER, TasksProxy, WATCHER}; use yazi_proxy::{AppProxy, TasksProxy, HIDER, WATCHER};
use yazi_shared::{fs::{File, FilesOp, Url, max_common_root, maybe_exists, paths_to_same_file}, terminal_clear}; use yazi_shared::{
fs::{max_common_root, maybe_exists, paths_to_same_file, File, FilesOp, Url},
terminal_clear,
};
use crate::manager::Manager; use crate::manager::Manager;
@ -119,16 +131,16 @@ impl Manager {
} }
fn sort(old: Vec<PathBuf>, new: Vec<PathBuf>) -> Vec<(PathBuf, PathBuf)> { fn sort(old: Vec<PathBuf>, new: Vec<PathBuf>) -> Vec<(PathBuf, PathBuf)> {
let mut income_map: HashMap<PathBuf, bool> = let user_order: HashMap<_, _> = old.iter().enumerate().map(|(idx, path)| (path, idx)).collect();
old.iter().map(|path| (path.clone(), false)).collect(); let mut income_map: HashMap<_, _> = old.iter().map(|path| (path.clone(), false)).collect();
let mut todos: HashMap<PathBuf, PathBuf> = old let mut todos: HashMap<_, _> = old
.into_iter() .iter()
.zip(new) .zip(new)
.map(|(old, new)| { .map(|(old, new)| {
if let Some(has_income) = income_map.get_mut(&new) { if let Some(has_income) = income_map.get_mut(&new) {
*has_income = true; *has_income = true;
} }
(old, new) (old.clone(), new)
}) })
.collect(); .collect();
@ -144,13 +156,13 @@ impl Manager {
if has_no_incomes.is_empty() { if has_no_incomes.is_empty() {
// Remaining rename set has cycle, so we cannot sort, just return them all // Remaining rename set has cycle, so we cannot sort, just return them all
let mut remain = todos.drain().collect::<Vec<_>>(); let mut remain = todos.drain().collect::<Vec<_>>();
remain.sort(); remain.sort_by(|(a, _), (b, _)| user_order[a].cmp(&user_order[b]));
sorted.reverse(); sorted.reverse();
sorted.extend(remain); sorted.extend(remain);
return sorted; return sorted;
} }
has_no_incomes.sort(); has_no_incomes.sort_by(|a, b| user_order[b].cmp(&user_order[a]));
for old in has_no_incomes { for old in has_no_incomes {
income_map.remove(&old); income_map.remove(&old);
let Some(new) = todos.remove(&old) else { unreachable!("") }; let Some(new) = todos.remove(&old) else { unreachable!("") };
@ -190,19 +202,25 @@ mod tests {
#[rustfmt::skip] #[rustfmt::skip]
cmp( cmp(
&[("1", "3"), ("2", "3"), ("3", "4")], &[("1", "3"), ("2", "3"), ("3", "4")],
&[("3", "4"), ("2", "3"), ("1", "3")] &[("3", "4"), ("1", "3"), ("2", "3")]
); );
#[rustfmt::skip] #[rustfmt::skip]
cmp( cmp(
&[("2", "1"), ("1", "2")], &[("2", "1"), ("1", "2")],
&[("1", "2"), ("2", "1")] &[("2", "1"), ("1", "2")]
); );
#[rustfmt::skip] #[rustfmt::skip]
cmp( cmp(
&[("3", "2"), ("2", "1"), ("1", "3"), ("a", "b"), ("b", "c")], &[("3", "2"), ("2", "1"), ("1", "3"), ("a", "b"), ("b", "c")],
&[("b", "c"), ("a", "b"), ("1", "3"), ("2", "1"), ("3", "2")] &[("b", "c"), ("a", "b"), ("3", "2"), ("2", "1"), ("1", "3")]
);
#[rustfmt::skip]
cmp(
&[("b", "b_"), ("a", "a_"), ("c", "c_")],
&[("b", "b_"), ("a", "a_"), ("c", "c_")],
); );
} }
} }