summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorrabite <rabite@posteo.de>2019-01-25 20:20:34 +0100
committerrabite <rabite@posteo.de>2019-01-25 20:20:34 +0100
commitc381203bb2c9fd91add74154237dcc93853f73c3 (patch)
tree0a5ce0a1f6a3f8130fe4782600c444f07734b1b1 /src
parentf3f783a3a0bc3c96e4678c7fa986dc31bcb8d585 (diff)
sorting by name and size
Diffstat (limited to 'src')
-rw-r--r--src/files.rs106
-rw-r--r--src/listview.rs30
2 files changed, 109 insertions, 27 deletions
diff --git a/src/files.rs b/src/files.rs
index 1192659..ba37e04 100644
--- a/src/files.rs
+++ b/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);
-
- let files = dirs;
-
- Ok(Files(files))
+ Ok(files)
+ }
+
+ 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()
+ });
+ },
+ _ => {}
+ };
+
+ // 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()
}
diff --git a/src/listview.rs b/src/listview.rs
index 93424d7..c29351e 100644
--- a/src/listview.rs
+++ b/src/listview.rs
@@ -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)); }
}
}