diff options
author | Brooks J Rady <b.j.rady@gmail.com> | 2021-04-19 23:37:47 +0100 |
---|---|---|
committer | Brooks J Rady <b.j.rady@gmail.com> | 2021-04-19 23:37:47 +0100 |
commit | fee999ec40b469564e65c8c551f463805003ba6d (patch) | |
tree | e66c4f4bce0d22aa22de4408b4e0c9db5b71b0fa /default-plugins/strider | |
parent | 996c197fcf9fbc655e7cf7e741c62ad71970c322 (diff) |
fix(naming): made plugin terminology more consistent
Diffstat (limited to 'default-plugins/strider')
-rw-r--r-- | default-plugins/strider/.cargo/config.toml | 2 | ||||
-rw-r--r-- | default-plugins/strider/Cargo.toml | 12 | ||||
l--------- | default-plugins/strider/LICENSE.md | 1 | ||||
-rw-r--r-- | default-plugins/strider/src/main.rs | 97 | ||||
-rw-r--r-- | default-plugins/strider/src/state.rs | 63 |
5 files changed, 175 insertions, 0 deletions
diff --git a/default-plugins/strider/.cargo/config.toml b/default-plugins/strider/.cargo/config.toml new file mode 100644 index 000000000..bc255e30b --- /dev/null +++ b/default-plugins/strider/.cargo/config.toml @@ -0,0 +1,2 @@ +[build] +target = "wasm32-wasi"
\ No newline at end of file diff --git a/default-plugins/strider/Cargo.toml b/default-plugins/strider/Cargo.toml new file mode 100644 index 000000000..d10598512 --- /dev/null +++ b/default-plugins/strider/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "strider" +version = "0.2.0" +authors = ["Brooks J Rady <b.j.rady@gmail.com>"] +edition = "2018" +description = "A simplified ranger clone written as a Zellij plugin" +license = "MIT" + +[dependencies] +colored = "2" +zellij-tile = { path = "../../zellij-tile" } +pretty-bytes = "0.2"
\ No newline at end of file diff --git a/default-plugins/strider/LICENSE.md b/default-plugins/strider/LICENSE.md new file mode 120000 index 000000000..f0608a63a --- /dev/null +++ b/default-plugins/strider/LICENSE.md @@ -0,0 +1 @@ +../../LICENSE.md
\ No newline at end of file diff --git a/default-plugins/strider/src/main.rs b/default-plugins/strider/src/main.rs new file mode 100644 index 000000000..8edc1e197 --- /dev/null +++ b/default-plugins/strider/src/main.rs @@ -0,0 +1,97 @@ +mod state; + +use colored::*; +use state::{FsEntry, State}; +use std::{cmp::min, fs::read_dir}; +use zellij_tile::prelude::*; + +register_plugin!(State); + +impl ZellijPlugin for State { + fn load(&mut self) { + refresh_directory(self); + subscribe(&[EventType::KeyPress]); + } + + fn update(&mut self, event: Event) { + if let Event::KeyPress(key) = event { + match key { + Key::Up | Key::Char('k') => { + *self.selected_mut() = self.selected().saturating_sub(1); + } + Key::Down | Key::Char('j') => { + let next = self.selected().saturating_add(1); + *self.selected_mut() = min(self.files.len() - 1, next); + } + Key::Right | Key::Char('\n') | Key::Char('l') if !self.files.is_empty() => { + match self.files[self.selected()].clone() { + FsEntry::Dir(p, _) => { + self.path = p; + refresh_directory(self); + } + FsEntry::File(p, _) => open_file(&p), + } + } + Key::Left | Key::Char('h') => { + self.path.pop(); + refresh_directory(self); + } + + Key::Char('.') => { + self.toggle_hidden_files(); + refresh_directory(self); + } + + _ => (), + }; + } + } + + fn render(&mut self, rows: usize, cols: usize) { + for i in 0..rows { + 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 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() + .filter(|d| !d.is_hidden_file() || !state.hide_hidden_files) + }) + .collect(); + + state.files.sort_unstable(); +} diff --git a/default-plugins/strider/src/state.rs b/default-plugins/strider/src/state.rs new file mode 100644 index 000000000..0d96ae0b9 --- /dev/null +++ b/default-plugins/strider/src/state.rs @@ -0,0 +1,63 @@ +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)>, + pub hide_hidden_files: bool, +} + +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 + } + pub fn toggle_hidden_files(&mut self) { + self.hide_hidden_files = !self.hide_hidden_files; + } +} + +#[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() + } + } + + pub fn is_hidden_file(&self) -> bool { + self.name().starts_with('.') + } +} |