summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorqkzk <qkzk@users.noreply.github.com>2022-09-30 21:34:03 +0200
committerGitHub <noreply@github.com>2022-09-30 21:34:03 +0200
commit777cfbd6fe1992e40b5c9c5592c39f2df56ac77f (patch)
treee98e1a96a8f459c013c76758a38d8648fa947045
parent9229c2038d1898a1fca2a74abf85d77760548acc (diff)
parent4d9cecf3f68cb932a2f037a8989f862808da6c93 (diff)
Merge pull request #15 from qkzk/sortingsorting
Sorting
-rw-r--r--config.yaml1
-rw-r--r--readme.md6
-rw-r--r--src/config.rs5
-rw-r--r--src/fileinfo.rs37
-rw-r--r--src/main.rs49
5 files changed, 77 insertions, 21 deletions
diff --git a/config.yaml b/config.yaml
index 593647d..a8d8ccf 100644
--- a/config.yaml
+++ b/config.yaml
@@ -38,3 +38,4 @@ keybindings:
regex_match: w
jump: j
nvim: i
+ sort_by: O
diff --git a/readme.md b/readme.md
index e18274d..d510cc8 100644
--- a/readme.md
+++ b/readme.md
@@ -56,6 +56,7 @@
- [x] confirmation for cut/paste, copy/paste, delete
- [x] bugfix: strange behavior after leaving a mode, wrong files are flagged - not in the right index or something
- [x] bugfix: can navigate outside file list
+- [ ] sorting : filename, size, date, type
## TODO
@@ -69,9 +70,6 @@
- https://github.com/KillTheMule/nvim-rs/blob/master/examples/basic.rs
- https://neovim.io/doc/user/api.html
- [ ] display / event separation. use async and message passing between coroutines
-- [ ] sorting
- - [ ] kind of sorts : filename, size, date, type
- - [ ] key for alterning sorting
## BUGS
@@ -86,3 +84,5 @@
### filepicker in vim
- [fff](https://github.com/dylanaraps/fff)
+
+
diff --git a/src/config.rs b/src/config.rs
index 5a0cbbe..aba352b 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -118,6 +118,7 @@ pub struct Keybindings {
pub regex_match: char,
pub jump: char,
pub nvim: char,
+ pub sort_by: char,
}
impl Keybindings {
@@ -188,6 +189,9 @@ impl Keybindings {
if let Some(nvim) = yaml["nvim"].as_str().map(|s| s.to_string()) {
self.nvim = nvim.chars().next().unwrap_or('i');
}
+ if let Some(nvim) = yaml["sort_by"].as_str().map(|s| s.to_string()) {
+ self.nvim = nvim.chars().next().unwrap_or('O');
+ }
}
pub fn new() -> Self {
@@ -214,6 +218,7 @@ impl Keybindings {
regex_match: 'w',
jump: 'j',
nvim: 'i',
+ sort_by: 'O',
}
}
}
diff --git a/src/fileinfo.rs b/src/fileinfo.rs
index 0a713db..d6cc1dd 100644
--- a/src/fileinfo.rs
+++ b/src/fileinfo.rs
@@ -6,6 +6,25 @@ use std::path;
use users::get_user_by_uid;
+#[derive(Debug, Clone)]
+pub enum SortBy {
+ Filename,
+ Date,
+ Size,
+ Extension,
+}
+
+impl SortBy {
+ pub fn by_key(&self, file: &FileInfo) -> String {
+ match *self {
+ Self::Filename => file.filename.clone(),
+ Self::Date => file.system_time.clone(),
+ Self::Size => file.file_size.clone(),
+ Self::Extension => file.extension.clone(),
+ }
+ }
+}
+
#[derive(Debug, Clone, Copy)]
pub enum FileKind {
NormalFile,
@@ -63,6 +82,7 @@ pub struct FileInfo {
pub system_time: String,
pub is_selected: bool,
pub file_kind: FileKind,
+ pub extension: String,
}
impl FileInfo {
@@ -77,6 +97,7 @@ impl FileInfo {
let file_kind = FileKind::new(direntry);
let dir_symbol = file_kind.extract_dir_symbol();
+ let extension = get_extension_from_filename(&filename).unwrap_or("").into();
Ok(FileInfo {
path,
@@ -88,6 +109,7 @@ impl FileInfo {
system_time,
is_selected,
file_kind,
+ extension,
})
}
@@ -121,6 +143,7 @@ pub struct PathContent {
pub files: Vec<FileInfo>,
pub selected: usize,
pub show_hidden: bool,
+ pub sort_by: SortBy,
}
impl PathContent {
@@ -142,7 +165,8 @@ impl PathContent {
})
.map(|direntry| FileInfo::new(&direntry.unwrap()).unwrap())
.collect();
- files.sort_by_key(|file| file.filename.clone());
+ let sort_by = SortBy::Filename;
+ files.sort_by_key(|file| sort_by.by_key(file));
let selected: usize = 0;
if !files.is_empty() {
files[selected].select();
@@ -153,9 +177,14 @@ impl PathContent {
files,
selected,
show_hidden,
+ sort_by,
}
}
+ pub fn sort(&mut self) {
+ self.files.sort_by_key(|file| self.sort_by.by_key(file));
+ }
+
fn owner_column_width(&self) -> usize {
let mut owner_size_btreeset = std::collections::BTreeSet::new();
for file in self.files.iter() {
@@ -280,3 +309,9 @@ fn human_size(bytes: u64) -> String {
);
human_size
}
+
+fn get_extension_from_filename(filename: &str) -> Option<&str> {
+ path::Path::new(filename)
+ .extension()
+ .and_then(std::ffi::OsStr::to_str)
+}
diff --git a/src/main.rs b/src/main.rs
index dfd1044..06c0fc1 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -17,7 +17,7 @@ use tuikit::term::{Term, TermHeight};
// use fm::args::Args;
use fm::config::{load_config, str_to_tuikit, Colors, Config};
-use fm::fileinfo::{FileInfo, FileKind, PathContent};
+use fm::fileinfo::{FileInfo, FileKind, PathContent, SortBy};
pub mod fileinfo;
@@ -64,6 +64,7 @@ use clap::Parser;
/// g: GOTO{n}
/// w: REGEXMATCH{n}
/// j: JUMP{n}
+/// O: SORT{n}
/// Enter: Execute mode then NORMAL{n}
/// Esc: NORMAL{n}
struct Args {
@@ -83,17 +84,10 @@ struct Args {
const WINDOW_PADDING: usize = 4;
const WINDOW_MARGIN_TOP: usize = 1;
const EDIT_BOX_OFFSET: usize = 10;
+const SORT_CURSOR_OFFSET: usize = 29;
const MAX_PERMISSIONS: u32 = 0o777;
static CONFIG_PATH: &str = "~/.config/fm/config.yaml";
-// static USAGE: &str = "
-// FM: dired inspired File Manager
-//
-// dired [flags] [path]
-// flags:
-// -a display hidden files
-// -h show help and exit
-// ";
static HELP_LINES: &str = "
Default key bindings:
@@ -132,6 +126,7 @@ o: xdg-open this file
g: GOTO
w: REGEXMATCH
j: JUMP
+ O: SORT
Enter: Execute mode then NORMAL
Esc: NORMAL
";
@@ -222,6 +217,7 @@ enum Mode {
RegexMatch,
Jump,
NeedConfirmation,
+ Sort,
}
impl fmt::Debug for Mode {
@@ -239,6 +235,7 @@ impl fmt::Debug for Mode {
Mode::RegexMatch => write!(f, "Regex : "),
Mode::Jump => write!(f, "Jump : "),
Mode::NeedConfirmation => write!(f, "Y/N :"),
+ Mode::Sort => write!(f, "(N)ame (D)ate (S)ize (E)xt : "),
}
}
}
@@ -603,6 +600,8 @@ impl Status {
self.event_jump();
} else if c == self.config.keybindings.nvim {
self.event_nvim_filepicker();
+ } else if c == self.config.keybindings.sort_by {
+ self.mode = Mode::Sort;
}
}
Mode::Help => {
@@ -620,6 +619,24 @@ impl Status {
self.last_edition = LastEdition::Nothing;
self.mode = Mode::Normal;
}
+ Mode::Sort => {
+ self.mode = Mode::Normal;
+ match c {
+ 'n' => self.path_content.sort_by = SortBy::Filename,
+ 'd' => self.path_content.sort_by = SortBy::Date,
+ 's' => self.path_content.sort_by = SortBy::Size,
+ 'e' => self.path_content.sort_by = SortBy::Extension,
+ _ => {
+ return;
+ }
+ }
+ if !self.path_content.files.is_empty() {
+ self.path_content.files[self.file_index].unselect();
+ self.path_content.sort();
+ self.event_home();
+ self.path_content.select_index(0);
+ }
+ }
}
}
@@ -837,7 +854,7 @@ impl Status {
Mode::Goto => self.exec_goto(),
Mode::RegexMatch => self.exec_regex(),
Mode::Jump => self.exec_jump(),
- Mode::Normal | Mode::NeedConfirmation | Mode::Help => (),
+ Mode::Normal | Mode::NeedConfirmation | Mode::Help | Mode::Sort => (),
}
self.input_string_cursor_index = 0;
@@ -1108,14 +1125,9 @@ impl Display {
let first_row: String = match status.mode {
Mode::Normal => {
format!(
- "h: {}, s: {} wt: {} wb: {} m: {:?} - c: {:?} - {}",
- status.height,
+ "Path: {} -- {} files",
+ status.path_content.path.to_str().unwrap(),
status.path_content.files.len(),
- status.window.top,
- status.window.bottom,
- status.mode,
- status.args,
- status.path_content.path.to_str().unwrap()
)
}
Mode::NeedConfirmation => {
@@ -1159,6 +1171,9 @@ impl Display {
Mode::NeedConfirmation => {
let _ = self.term.set_cursor(0, status.last_edition.offset());
}
+ Mode::Sort => {
+ let _ = self.term.set_cursor(0, SORT_CURSOR_OFFSET);
+ }
_ => {
let _ = self
.term