aboutsummaryrefslogtreecommitdiffstats
path: root/default-plugins/strider/src
diff options
context:
space:
mode:
authorqepasa <pawelpalenica11@gmail.com>2021-10-12 14:37:54 -0700
committerGitHub <noreply@github.com>2021-10-12 22:37:54 +0100
commit0710594588aa768b934f925704dc57486dc0a157 (patch)
tree5b2cd4c9e94ecbda277454b77698ebaa837fab6c /default-plugins/strider/src
parentdocs(changelog): preserve umask/keep default file permissions (diff)
downloadsl0ppij-0710594588aa768b934f925704dc57486dc0a157.tar.gz
sl0ppij-0710594588aa768b934f925704dc57486dc0a157.tar.xz
sl0ppij-0710594588aa768b934f925704dc57486dc0a157.zip
feat(plugin): Add mouse events for plugins (#629)
* feat(plugin): Add mouse events for plugins * Add double click support in strider * Add support for mouse clicks in tab-bar and fix bug in strider with selecting past the list of files and random double click action * continue working on mouse support for tab bar * finish tab change * fix fmt and fix bug in strider double-click * fix clippy * cleanup dbgs and logs * fix clippy * noop change to rerun e2e tests * Rebase and fix mouse click behavior in tab-bar and strider after rebase * fix fmt * remove dbgs and and comment in tab-line/main.rs * cargo fmt * Code review suggestions * rebase fix * fix clippy * fix mouse selection for tabs in tab-bar
Diffstat (limited to 'default-plugins/strider/src')
-rw-r--r--default-plugins/strider/src/main.rs86
-rw-r--r--default-plugins/strider/src/state.rs40
2 files changed, 88 insertions, 38 deletions
diff --git a/default-plugins/strider/src/main.rs b/default-plugins/strider/src/main.rs
index f0b5cebf..3bdceefd 100644
--- a/default-plugins/strider/src/main.rs
+++ b/default-plugins/strider/src/main.rs
@@ -1,23 +1,27 @@
mod state;
use colored::*;
-use state::{FsEntry, State};
-use std::{cmp::min, fs::read_dir, path::Path};
+use state::{refresh_directory, FsEntry, State};
+use std::{cmp::min, time::Instant};
use zellij_tile::prelude::*;
-const ROOT: &str = "/host";
-
register_plugin!(State);
impl ZellijPlugin for State {
fn load(&mut self) {
refresh_directory(self);
- subscribe(&[EventType::KeyPress]);
+ subscribe(&[EventType::KeyPress, EventType::Mouse]);
}
fn update(&mut self, event: Event) {
- if let Event::KeyPress(key) = event {
- match key {
+ let prev_event = if self.ev_history.len() == 2 {
+ self.ev_history.pop_front()
+ } else {
+ None
+ };
+ self.ev_history.push_back((event.clone(), Instant::now()));
+ match event {
+ Event::KeyPress(key) => match key {
Key::Up | Key::Char('k') => {
*self.selected_mut() = self.selected().saturating_sub(1);
}
@@ -26,13 +30,8 @@ impl ZellijPlugin for State {
*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.strip_prefix(ROOT).unwrap()),
- }
+ self.traverse_dir_or_open_file();
+ self.ev_history.clear();
}
Key::Left | Key::Char('h') => {
if self.path.components().count() > 2 {
@@ -44,25 +43,59 @@ impl ZellijPlugin for State {
refresh_directory(self);
}
}
-
Key::Char('.') => {
self.toggle_hidden_files();
refresh_directory(self);
}
_ => (),
- };
+ },
+ Event::Mouse(mouse_event) => match mouse_event {
+ Mouse::ScrollDown(_) => {
+ let next = self.selected().saturating_add(1);
+ *self.selected_mut() = min(self.files.len().saturating_sub(1), next);
+ }
+ Mouse::ScrollUp(_) => {
+ *self.selected_mut() = self.selected().saturating_sub(1);
+ }
+ Mouse::MouseRelease(Some((line, _))) => {
+ if line < 0 {
+ return;
+ }
+ let mut should_select = true;
+ if let Some((Event::Mouse(Mouse::MouseRelease(Some((prev_line, _)))), t)) =
+ prev_event
+ {
+ if prev_line == line
+ && Instant::now().saturating_duration_since(t).as_millis() < 400
+ {
+ self.traverse_dir_or_open_file();
+ self.ev_history.clear();
+ should_select = false;
+ }
+ }
+ if should_select && self.scroll() + (line as usize) < self.files.len() {
+ *self.selected_mut() = self.scroll() + (line as usize);
+ }
+ }
+ _ => {}
+ },
+ _ => {
+ dbg!("Unknown event {:?}", event);
+ }
}
}
fn render(&mut self, rows: usize, cols: usize) {
for i in 0..rows {
+ // If the key was pressed, set selected so that we can see the cursor
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();
@@ -82,24 +115,3 @@ impl ZellijPlugin for State {
}
}
}
-
-fn refresh_directory(state: &mut State) {
- state.files = read_dir(Path::new(ROOT).join(&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
index 0ae84ab2..7c19cb69 100644
--- a/default-plugins/strider/src/state.rs
+++ b/default-plugins/strider/src/state.rs
@@ -1,12 +1,20 @@
use pretty_bytes::converter as pb;
-use std::{collections::HashMap, path::PathBuf};
+use std::{
+ collections::{HashMap, VecDeque},
+ fs::read_dir,
+ path::{Path, PathBuf},
+ time::Instant,
+};
+use zellij_tile::prelude::*;
+const ROOT: &str = "/host";
#[derive(Default)]
pub struct State {
pub path: PathBuf,
pub files: Vec<FsEntry>,
pub cursor_hist: HashMap<PathBuf, (usize, usize)>,
pub hide_hidden_files: bool,
+ pub ev_history: VecDeque<(Event, Instant)>, // stores last event, can be expanded in future
}
impl State {
@@ -25,6 +33,15 @@ impl State {
pub fn toggle_hidden_files(&mut self) {
self.hide_hidden_files = !self.hide_hidden_files;
}
+ pub fn traverse_dir_or_open_file(&mut self) {
+ match self.files[self.selected()].clone() {
+ FsEntry::Dir(p, _) => {
+ self.path = p;
+ refresh_directory(self);
+ }
+ FsEntry::File(p, _) => open_file(p.strip_prefix(ROOT).unwrap()),
+ }
+ }
}
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone)]
@@ -61,3 +78,24 @@ impl FsEntry {
self.name().starts_with('.')
}
}
+
+pub(crate) fn refresh_directory(state: &mut State) {
+ state.files = read_dir(Path::new(ROOT).join(&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();
+}