1
0
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:
rabite 2019-01-25 20:20:34 +01:00
parent f3f783a3a0
commit c381203bb2
2 changed files with 109 additions and 27 deletions

View File

@ -4,27 +4,22 @@ use std::path::PathBuf;
use std::ffi::OsStr; use std::ffi::OsStr;
use std::cmp::{Ord, Ordering}; use std::cmp::{Ord, Ordering};
pub struct Files(Vec<File>);
use lscolors::{LsColors, Style}; use lscolors::{LsColors, Style};
impl Index<usize> for Files {
type Output = File;
fn index(&self, pos: usize) -> &Self::Output {
&self.0[pos]
}
lazy_static! { lazy_static! {
static ref COLORS: LsColors = LsColors::from_env().unwrap(); static ref COLORS: LsColors = LsColors::from_env().unwrap();
} }
impl PartialOrd for File { #[derive(PartialEq)]
fn partial_cmp(&self, other: &File) -> Option<Ordering> { pub struct Files {
Some(alphanumeric_sort::compare_str(&self.name, &other.name)) pub files: Vec<File>,
} pub sort: SortBy,
} }
impl Ord for File { impl Index<usize> for Files {
fn cmp(&self, other: &File) -> Ordering { type Output = File;
alphanumeric_sort::compare_str(&self.name, &other.name) fn index(&self, pos: usize) -> &Self::Output {
&self.files[pos]
} }
} }
@ -41,7 +36,7 @@ impl Files {
-> Result<Files, Box<dyn Error>> -> Result<Files, Box<dyn Error>>
where S: std::convert::AsRef<std::path::Path> { where S: std::convert::AsRef<std::path::Path> {
let mut files = Vec::new(); let mut files = Vec::new();
let mut dirs = Vec::new();
for file in std::fs::read_dir(path)? { for file in std::fs::read_dir(path)? {
let file = file?; let file = file?;
let name = file.file_name(); let name = file.file_name();
@ -56,26 +51,58 @@ impl Files {
None => None None => None
}; };
let file = File::new(&name, path, kind, size as usize, style); let file = File::new(&name, path, kind, size as usize, style);
match kind { files.push(file)
Kind::Directory => dirs.push(file),
_ => files.push(file),
}
} }
let mut files = Files { files: files,
sort: SortBy::Name };
files.sort(); files.sort();
dirs.sort(); Ok(files)
dirs.append(&mut files); }
let files = dirs; pub fn sort(&mut self) {
match self.sort {
Ok(Files(files)) 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()
});
},
_ => {}
};
// 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> { pub fn iter(&self) -> std::slice::Iter<File> {
self.0.iter() self.files.iter()
} }
pub fn len(&self) -> usize { pub fn len(&self) -> usize {
self.0.len() self.files.len()
} }
} }
@ -87,7 +114,28 @@ pub enum Kind {
Pipe 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 struct File {
pub name: String, pub name: String,
pub path: PathBuf, pub path: PathBuf,
@ -143,6 +191,10 @@ impl File {
Some(self.path.parent()?.parent()?.to_path_buf()) Some(self.path.parent()?.parent()?.to_path_buf())
} }
pub fn is_dir(&self) -> bool {
self.kind == Kind::Directory
}
pub fn path(&self) -> PathBuf { pub fn path(&self) -> PathBuf {
self.path.clone() self.path.clone()
} }

View File

@ -61,6 +61,16 @@ impl<T: 'static> ListView<T> where ListView<T>: Widget {
self.selection += 1; 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 { fn render_line(&self, file: &File) -> String {
let name = &file.name; let name = &file.name;
let (size, unit) = file.calculate_size(); let (size, unit) = file.calculate_size();
@ -100,6 +110,12 @@ impl ListView<Files> where
file file
} }
fn clone_selected_file(&self) -> File {
let selection = self.selection;
let file = self.content[selection].clone();
file
}
fn grand_parent(&self) -> Option<PathBuf> { fn grand_parent(&self) -> Option<PathBuf> {
self.selected_file().grand_parent() 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 => { Key::Right => {
self.goto_selected() self.goto_selected()
}, },
Key::Char('s') => { self.cycle_sort() } ,
_ => { self.bad(Event::Key(key)); } _ => { self.bad(Event::Key(key)); }
} }
} }