aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorBrooks J Rady <b.j.rady@gmail.com>2020-11-17 22:10:51 +0000
committerBrooks J Rady <b.j.rady@gmail.com>2020-11-17 22:10:51 +0000
commit2ecf8bd5db43e02f7b9b2d1e99721b9f1dd54a28 (patch)
tree2a06b170742f1375e79cbaee0a8abb84cdd640fc /src
downloadsl0ppij-2ecf8bd5db43e02f7b9b2d1e99721b9f1dd54a28.tar.gz
sl0ppij-2ecf8bd5db43e02f7b9b2d1e99721b9f1dd54a28.tar.xz
sl0ppij-2ecf8bd5db43e02f7b9b2d1e99721b9f1dd54a28.zip
Initial Commit
Diffstat (limited to 'src')
-rw-r--r--src/main.rs85
-rw-r--r--src/state.rs55
2 files changed, 140 insertions, 0 deletions
diff --git a/src/main.rs b/src/main.rs
new file mode 100644
index 00000000..f48d07fc
--- /dev/null
+++ b/src/main.rs
@@ -0,0 +1,85 @@
+mod state;
+
+use colored::*;
+use mosaic_tile::register_tile;
+use state::{FsEntry, State};
+use std::{cmp::min, fs::read_dir};
+
+register_tile!(State);
+
+impl MosaicTile for State {
+ fn init(&mut self) {
+ refresh_directory(self);
+ }
+
+ fn draw(&mut self, rows: usize, cols: usize) {
+ for i in 0..rows - 1 {
+ if self.selected() < self.scroll() {
+ *self.scroll_mut() = self.selected();
+ }
+ if self.selected() - self.scroll() + 2 > rows {
+ *self.scroll_mut() = self.selected() + 2 - rows;
+ }
+ let i = self.scroll() + i;
+ if let Some(entry) = self.files.get(i) {
+ let mut path = entry.as_line(cols).normal();
+
+ if let FsEntry::Dir(..) = entry {
+ path = path.dimmed().bold();
+ }
+
+ if i == self.selected() {
+ println!("{}", path.reversed());
+ } else {
+ println!("{}", path);
+ }
+ } else {
+ println!();
+ }
+ }
+ }
+
+ fn handle_key(&mut self, key: KeyEvent) {
+ match key.code {
+ KeyCode::Up => {
+ *self.selected_mut() = self.selected().saturating_sub(1);
+ }
+ KeyCode::Down => {
+ let next = self.selected().saturating_add(1);
+ *self.selected_mut() = min(self.files.len() - 1, next);
+ }
+ KeyCode::Right | KeyCode::Enter => match self.files[self.selected()].clone() {
+ FsEntry::Dir(p, _) => {
+ self.path = p;
+ refresh_directory(self);
+ }
+ FsEntry::File(p, _) => open_file(&p),
+ },
+ KeyCode::Left => {
+ self.path.pop();
+ refresh_directory(self);
+ }
+ _ => (),
+ };
+ }
+}
+
+fn refresh_directory(state: &mut State) {
+ state.files = read_dir(&state.path)
+ .unwrap()
+ .filter_map(|res| {
+ res.and_then(|d| {
+ if d.metadata()?.is_dir() {
+ let children = read_dir(d.path())?.count();
+ Ok(FsEntry::Dir(d.path(), children))
+ } else {
+ let size = d.metadata()?.len();
+ Ok(FsEntry::File(d.path(), size))
+ }
+ })
+ .ok()
+ })
+ .collect();
+
+ state.files.sort_unstable();
+}
diff --git a/src/state.rs b/src/state.rs
new file mode 100644
index 00000000..cbb44dcd
--- /dev/null
+++ b/src/state.rs
@@ -0,0 +1,55 @@
+use pretty_bytes::converter as pb;
+use std::{collections::HashMap, path::PathBuf};
+
+#[derive(Default)]
+pub struct State {
+ pub path: PathBuf,
+ pub files: Vec<FsEntry>,
+ pub cursor_hist: HashMap<PathBuf, (usize, usize)>,
+}
+
+impl State {
+ pub fn selected_mut(&mut self) -> &mut usize {
+ &mut self.cursor_hist.entry(self.path.clone()).or_default().0
+ }
+ pub fn selected(&self) -> usize {
+ self.cursor_hist.get(&self.path).unwrap_or(&(0, 0)).0
+ }
+ pub fn scroll_mut(&mut self) -> &mut usize {
+ &mut self.cursor_hist.entry(self.path.clone()).or_default().1
+ }
+ pub fn scroll(&self) -> usize {
+ self.cursor_hist.get(&self.path).unwrap_or(&(0, 0)).1
+ }
+}
+
+#[derive(PartialEq, Eq, PartialOrd, Ord, Clone)]
+pub enum FsEntry {
+ Dir(PathBuf, usize),
+ File(PathBuf, u64),
+}
+
+impl FsEntry {
+ pub fn name(&self) -> String {
+ let path = match self {
+ FsEntry::Dir(p, _) => p,
+ FsEntry::File(p, _) => p,
+ };
+ path.file_name().unwrap().to_string_lossy().into_owned()
+ }
+
+ pub fn as_line(&self, width: usize) -> String {
+ let info = match self {
+ FsEntry::Dir(_, s) => s.to_string(),
+ FsEntry::File(_, s) => pb::convert(*s as f64),
+ };
+ let space = width - info.len();
+ let name = self.name();
+ if space - 1 < name.len() {
+ [&name[..space - 2], &info].join("~ ")
+ } else {
+ let padding = " ".repeat(space - name.len());
+ [name, padding, info].concat()
+ }
+ }
+}