mirror of
https://github.com/bobwen-dev/hunter
synced 2025-04-12 00:55:41 +02:00
sorting by name and size
This commit is contained in:
parent
f3f783a3a0
commit
c381203bb2
102
src/files.rs
102
src/files.rs
@ -4,27 +4,22 @@ use std::path::PathBuf;
|
||||
use std::ffi::OsStr;
|
||||
use std::cmp::{Ord, Ordering};
|
||||
|
||||
pub struct Files(Vec<File>);
|
||||
use lscolors::{LsColors, Style};
|
||||
|
||||
impl Index<usize> for Files {
|
||||
type Output = File;
|
||||
fn index(&self, pos: usize) -> &Self::Output {
|
||||
&self.0[pos]
|
||||
}
|
||||
lazy_static! {
|
||||
static ref COLORS: LsColors = LsColors::from_env().unwrap();
|
||||
}
|
||||
|
||||
impl PartialOrd for File {
|
||||
fn partial_cmp(&self, other: &File) -> Option<Ordering> {
|
||||
Some(alphanumeric_sort::compare_str(&self.name, &other.name))
|
||||
}
|
||||
#[derive(PartialEq)]
|
||||
pub struct Files {
|
||||
pub files: Vec<File>,
|
||||
pub sort: SortBy,
|
||||
}
|
||||
|
||||
impl Ord for File {
|
||||
fn cmp(&self, other: &File) -> Ordering {
|
||||
alphanumeric_sort::compare_str(&self.name, &other.name)
|
||||
impl Index<usize> for Files {
|
||||
type Output = File;
|
||||
fn index(&self, pos: usize) -> &Self::Output {
|
||||
&self.files[pos]
|
||||
}
|
||||
}
|
||||
|
||||
@ -41,7 +36,7 @@ impl Files {
|
||||
-> Result<Files, Box<dyn Error>>
|
||||
where S: std::convert::AsRef<std::path::Path> {
|
||||
let mut files = Vec::new();
|
||||
let mut dirs = Vec::new();
|
||||
|
||||
for file in std::fs::read_dir(path)? {
|
||||
let file = file?;
|
||||
let name = file.file_name();
|
||||
@ -56,26 +51,58 @@ impl Files {
|
||||
None => None
|
||||
};
|
||||
let file = File::new(&name, path, kind, size as usize, style);
|
||||
match kind {
|
||||
Kind::Directory => dirs.push(file),
|
||||
_ => files.push(file),
|
||||
}
|
||||
files.push(file)
|
||||
}
|
||||
|
||||
let mut files = Files { files: files,
|
||||
sort: SortBy::Name };
|
||||
|
||||
files.sort();
|
||||
dirs.sort();
|
||||
dirs.append(&mut files);
|
||||
Ok(files)
|
||||
}
|
||||
|
||||
let files = dirs;
|
||||
pub fn sort(&mut self) {
|
||||
match self.sort {
|
||||
SortBy::Name => {
|
||||
self.files.sort_by(|a,b| {
|
||||
alphanumeric_sort::compare_str(&a.name, &b.name)
|
||||
})
|
||||
},
|
||||
SortBy::Size => {
|
||||
self.files.sort_by(|a,b| {
|
||||
if a.size == b.size {
|
||||
return alphanumeric_sort::compare_str(&b.name, &a.name)
|
||||
}
|
||||
a.size.cmp(&b.size).reverse()
|
||||
});
|
||||
},
|
||||
_ => {}
|
||||
};
|
||||
|
||||
Ok(Files(files))
|
||||
// Direcories first
|
||||
self.files.sort_by(|a,b| {
|
||||
if a.is_dir() && !b.is_dir() {
|
||||
Ordering::Less
|
||||
} else { Ordering::Equal }
|
||||
});
|
||||
}
|
||||
|
||||
pub fn cycle_sort(&mut self) -> SortBy {
|
||||
self.sort = match self.sort {
|
||||
SortBy::Name => SortBy::Size,
|
||||
SortBy::Size => SortBy::Name,
|
||||
_ => { SortBy::Name }
|
||||
};
|
||||
self.sort();
|
||||
self.sort
|
||||
}
|
||||
|
||||
pub fn iter(&self) -> std::slice::Iter<File> {
|
||||
self.0.iter()
|
||||
self.files.iter()
|
||||
}
|
||||
|
||||
pub fn len(&self) -> usize {
|
||||
self.0.len()
|
||||
self.files.len()
|
||||
}
|
||||
}
|
||||
|
||||
@ -87,7 +114,28 @@ pub enum Kind {
|
||||
Pipe
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
impl std::fmt::Display for SortBy {
|
||||
fn fmt(&self, formatter: &mut std::fmt::Formatter<'_> )
|
||||
-> Result<(), std::fmt::Error> {
|
||||
let text = match self {
|
||||
SortBy::Name => "name",
|
||||
SortBy::Size => "size",
|
||||
SortBy::MDate => "mdate",
|
||||
SortBy::CDate => "cdate"
|
||||
};
|
||||
write!(formatter, "{}", text)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug,Copy,Clone,PartialEq)]
|
||||
pub enum SortBy {
|
||||
Name,
|
||||
Size,
|
||||
MDate,
|
||||
CDate
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub struct File {
|
||||
pub name: String,
|
||||
pub path: PathBuf,
|
||||
@ -143,6 +191,10 @@ impl File {
|
||||
Some(self.path.parent()?.parent()?.to_path_buf())
|
||||
}
|
||||
|
||||
pub fn is_dir(&self) -> bool {
|
||||
self.kind == Kind::Directory
|
||||
}
|
||||
|
||||
pub fn path(&self) -> PathBuf {
|
||||
self.path.clone()
|
||||
}
|
||||
|
@ -61,6 +61,16 @@ impl<T: 'static> ListView<T> where ListView<T>: Widget {
|
||||
self.selection += 1;
|
||||
}
|
||||
|
||||
fn set_selection(&mut self, position: usize) {
|
||||
let ysize = self.dimensions.1 as usize;
|
||||
let mut offset = 0;
|
||||
|
||||
while position + 1 > ysize + offset { offset += 1 }
|
||||
|
||||
self.offset = offset;
|
||||
self.selection = position;
|
||||
}
|
||||
|
||||
fn render_line(&self, file: &File) -> String {
|
||||
let name = &file.name;
|
||||
let (size, unit) = file.calculate_size();
|
||||
@ -100,6 +110,12 @@ impl ListView<Files> where
|
||||
file
|
||||
}
|
||||
|
||||
fn clone_selected_file(&self) -> File {
|
||||
let selection = self.selection;
|
||||
let file = self.content[selection].clone();
|
||||
file
|
||||
}
|
||||
|
||||
fn grand_parent(&self) -> Option<PathBuf> {
|
||||
self.selected_file().grand_parent()
|
||||
}
|
||||
@ -131,6 +147,19 @@ impl ListView<Files> where
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn select_file(&mut self, file: &File) {
|
||||
let pos = self.content.files.iter().position(|item| item == file).unwrap();
|
||||
self.set_selection(pos);
|
||||
}
|
||||
|
||||
fn cycle_sort(&mut self) {
|
||||
let file = self.clone_selected_file();
|
||||
self.content.cycle_sort();
|
||||
self.select_file(&file);
|
||||
self.refresh();
|
||||
self.show_status(&format!("Sorting by: {}", self.content.sort));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -207,6 +236,7 @@ impl Widget for ListView<Files> {
|
||||
Key::Right => {
|
||||
self.goto_selected()
|
||||
},
|
||||
Key::Char('s') => { self.cycle_sort() } ,
|
||||
_ => { self.bad(Event::Key(key)); }
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user