aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrooks J Rady <b.j.rady@gmail.com>2021-02-09 17:48:09 +0000
committerBrooks J Rady <b.j.rady@gmail.com>2021-02-09 17:48:09 +0000
commit012cce23898a78d8f8def64155b232abb88f00ad (patch)
tree3cb8e1cffe34295e2a6e87edc642080cf3574de9
parentMoved the status-bar into its own folder (diff)
parentBump dependency version (diff)
downloadsl0ppij-012cce23898a78d8f8def64155b232abb88f00ad.tar.gz
sl0ppij-012cce23898a78d8f8def64155b232abb88f00ad.tar.xz
sl0ppij-012cce23898a78d8f8def64155b232abb88f00ad.zip
Merged in strider
-rw-r--r--Cargo.toml16
-rw-r--r--LICENSE.md21
-rwxr-xr-xbuild-optimised.sh6
-rw-r--r--src/main.rs85
-rw-r--r--src/state.rs55
5 files changed, 183 insertions, 0 deletions
diff --git a/Cargo.toml b/Cargo.toml
new file mode 100644
index 00000000..405ae4d3
--- /dev/null
+++ b/Cargo.toml
@@ -0,0 +1,16 @@
+[package]
+name = "module"
+version = "0.2.0"
+authors = ["Brooks J Rady <b.j.rady@gmail.com>"]
+edition = "2018"
+description = "A simplified ranger clone written as a mosaic tile"
+repository = "https://github.com/mosaic-org/strider"
+license = "MIT"
+
+[dependencies]
+colored = "2"
+mosaic-tile = "0.4"
+pretty-bytes = "0.2"
+
+[profile.release]
+lto = true \ No newline at end of file
diff --git a/LICENSE.md b/LICENSE.md
new file mode 100644
index 00000000..0b264c31
--- /dev/null
+++ b/LICENSE.md
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2020 Mosaic contributors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/build-optimised.sh b/build-optimised.sh
new file mode 100755
index 00000000..e0654d89
--- /dev/null
+++ b/build-optimised.sh
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+# Build a release WASM from Rust with lto on
+cargo build --release
+# Further optimise for speed (and size)
+wasm-opt -O target/wasm32-wasi/release/module.wasm -o target/strider.wasm \ No newline at end of file
diff --git a/src/main.rs b/src/main.rs
new file mode 100644
index 00000000..e63cd822
--- /dev/null
+++ b/src/main.rs
@@ -0,0 +1,85 @@
+mod state;
+
+use colored::*;
+use mosaic_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 {
+ 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: Key) {
+ match key {
+ Key::Up => {
+ *self.selected_mut() = self.selected().saturating_sub(1);
+ }
+ Key::Down => {
+ let next = self.selected().saturating_add(1);
+ *self.selected_mut() = min(self.files.len() - 1, next);
+ }
+ Key::Right | Key::Char('\n') => match self.files[self.selected()].clone() {
+ FsEntry::Dir(p, _) => {
+ self.path = p;
+ refresh_directory(self);
+ }
+ FsEntry::File(p, _) => open_file(&p),
+ },
+ Key::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()
+ }
+ }
+}