feat: added jump next/prev keybinds, bincode does not support tagged items

This commit is contained in:
imgurbot12 2023-08-20 12:04:47 -07:00
parent 59e8cf6c22
commit 3f7baff1fb
9 changed files with 99 additions and 27 deletions

View File

@ -14,6 +14,7 @@ name = "rmenu-build"
path = "src/bin/main.rs"
[dependencies]
bincode = "1.3.3"
clap = { version = "4.3.22", features = ["derive"] }
serde = { version = "1.0.171", features = ["derive"] }
serde_json = "1.0.105"

View File

@ -155,6 +155,12 @@ struct OptionArgs {
/// Override Close-Menu Keybinds
#[arg(short = 'c', long)]
pub key_close_menu: Option<Vec<String>>,
/// Override Jump-Next Keybinds
#[arg(short = 'j', long)]
pub key_jump_next: Option<Vec<String>>,
/// Override Jump-Previous Keybinds
#[arg(short = 'J', long)]
pub key_jump_prev: Option<Vec<String>>,
// window settings
/// Override Window Title
#[arg(short, long)]
@ -187,6 +193,8 @@ impl Into<Options> for OptionArgs {
key_move_prev: self.key_move_prev,
key_open_menu: self.key_open_menu,
key_close_menu: self.key_close_menu,
key_jump_next: self.key_jump_next,
key_jump_prev: self.key_jump_prev,
title: self.title,
decorate: self.deocorate,
fullscreen: self.fullscreen,

View File

@ -110,6 +110,10 @@ pub struct Options {
pub key_open_menu: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub key_close_menu: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub key_jump_next: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub key_jump_prev: Option<Vec<String>>,
// window settings
#[serde(skip_serializing_if = "Option::is_none")]
pub title: Option<String>,

View File

@ -6,7 +6,6 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
bincode = "1.3.3"
cached = "0.44.0"
clap = { version = "4.3.15", features = ["derive"] }
dioxus = "0.4.0"

View File

@ -1,6 +1,5 @@
//! RMenu Plugin Result Cache
use std::fs;
use std::io::Write;
use std::path::PathBuf;
use std::time::{Duration, SystemTime};
@ -25,7 +24,7 @@ pub enum CacheError {
#[error("Cache File Error")]
FileError(#[from] std::io::Error),
#[error("Encoding Error")]
EncodingError(#[from] bincode::Error),
EncodingError(#[from] serde_json::Error),
}
#[inline]
@ -69,7 +68,7 @@ pub fn read_cache(name: &str, cfg: &PluginConfig) -> Result<Vec<Entry>, CacheErr
}
// attempt to read content
let data = fs::read(path)?;
let results: Vec<Entry> = bincode::deserialize(&data)?;
let results: Vec<Entry> = serde_json::from_slice(&data)?;
Ok(results)
}
@ -79,10 +78,10 @@ pub fn write_cache(name: &str, cfg: &PluginConfig, entries: &Vec<Entry>) -> Resu
match cfg.cache {
CacheSetting::NoCache => {}
_ => {
println!("writing {} entries", entries.len());
let path = cache_file(name);
let data = bincode::serialize(entries)?;
let mut f = fs::File::create(path)?;
f.write_all(&data)?;
let f = fs::File::create(path)?;
serde_json::to_writer(f, entries)?;
}
}
Ok(())

View File

@ -117,6 +117,12 @@ pub struct Args {
/// Override close-menu keybind
#[arg(long)]
key_close_menu: Option<Vec<Keybind>>,
/// Override jump-next keybind
#[arg(long)]
key_jump_next: Option<Vec<Keybind>>,
/// Override jump-previous keybind
#[arg(long)]
key_jump_prev: Option<Vec<Keybind>>,
//window settings
/// Override Window Title
@ -240,6 +246,8 @@ impl Args {
cli_replace!(config.keybinds.move_prev, self.key_move_prev, true);
cli_replace!(config.keybinds.open_menu, self.key_open_menu, true);
cli_replace!(config.keybinds.close_menu, self.key_close_menu, true);
cli_replace!(config.keybinds.jump_next, self.key_jump_next, true);
cli_replace!(config.keybinds.jump_prev, self.key_jump_prev, true);
// override window settings
cli_replace!(config.window.title, self.title, true);
cli_replace!(config.window.size.width, self.width, true);
@ -307,6 +315,8 @@ impl Args {
cli_keybind!(c.keybinds.move_prev, options.key_move_prev);
cli_keybind!(c.keybinds.open_menu, options.key_open_menu);
cli_keybind!(c.keybinds.close_menu, options.key_close_menu);
cli_keybind!(c.keybinds.jump_next, options.key_jump_next);
cli_keybind!(c.keybinds.jump_prev, options.key_jump_prev);
// window settings
cli_replace!(c.window.title, options.title, true);
cli_replace!(c.window.decorate, options.decorate, true);
@ -362,7 +372,7 @@ impl Args {
let main = args
.get(0)
.ok_or_else(|| RMenuError::InvalidPlugin(name.to_owned()))?;
// spawn command and handle command entries
// spawn command
let mut command = Command::new(main)
.args(&args[1..])
.stdout(Stdio::piped())
@ -371,8 +381,10 @@ impl Args {
.stdout
.as_mut()
.ok_or_else(|| RMenuError::CommandError(None))?;
// parse and read entries into vector of results
let reader = BufReader::new(stdout);
self.read_entries(reader, &mut entries, config)?;
let mut entry = vec![];
self.read_entries(reader, &mut entry, config)?;
let status = command.wait()?;
if !status.success() {
return Err(RMenuError::CommandError(Some(status)));
@ -381,10 +393,12 @@ impl Args {
if config.search.placeholder.is_none() {
config.search.placeholder = plugin.placeholder.clone();
}
match crate::cache::write_cache(&name, &plugin, &entries) {
match crate::cache::write_cache(&name, &plugin, &entry) {
Ok(_) => {}
Err(err) => log::error!("cache write error: {err:?}"),
}
// write collected entries to main output
entries.append(&mut entry);
}
Ok(entries)
}

View File

@ -87,6 +87,8 @@ pub struct KeyConfig {
pub move_prev: Vec<Keybind>,
pub open_menu: Vec<Keybind>,
pub close_menu: Vec<Keybind>,
pub jump_next: Vec<Keybind>,
pub jump_prev: Vec<Keybind>,
}
impl Default for KeyConfig {
@ -98,6 +100,8 @@ impl Default for KeyConfig {
move_prev: vec![Keybind::new(Code::ArrowDown)],
open_menu: vec![],
close_menu: vec![],
jump_next: vec![Keybind::new(Code::PageDown)],
jump_prev: vec![Keybind::new(Code::PageUp)],
};
}
}
@ -236,6 +240,7 @@ impl Default for SearchConfig {
pub struct Config {
pub page_size: usize,
pub page_load: f64,
pub jump_dist: usize,
#[serde(default = "_true")]
pub use_icons: bool,
#[serde(default = "_true")]
@ -252,6 +257,7 @@ impl Default for Config {
Self {
page_size: 50,
page_load: 0.8,
jump_dist: 5,
use_icons: true,
use_comments: true,
search: Default::default(),

View File

@ -205,14 +205,18 @@ fn App<'a>(cx: Scope<App>) -> Element {
k_updater.set_event(KeyEvent::Exec);
} else if matches(&keybinds.exit, &mods, &code) {
k_updater.set_event(KeyEvent::Exit);
} else if matches(&keybinds.move_prev, &mods, &code) {
k_updater.set_event(KeyEvent::ShiftUp);
} else if matches(&keybinds.move_next, &mods, &code) {
k_updater.set_event(KeyEvent::ShiftDown);
k_updater.set_event(KeyEvent::MoveNext);
} else if matches(&keybinds.move_prev, &mods, &code) {
k_updater.set_event(KeyEvent::MovePrev);
} else if matches(&keybinds.open_menu, &mods, &code) {
k_updater.set_event(KeyEvent::OpenMenu);
} else if matches(&keybinds.close_menu, &mods, &code) {
k_updater.set_event(KeyEvent::CloseMenu);
} else if matches(&keybinds.jump_next, &mods, &code) {
k_updater.set_event(KeyEvent::JumpNext)
} else if matches(&keybinds.jump_prev, &mods, &code) {
k_updater.set_event(KeyEvent::JumpPrev)
}
};

View File

@ -18,10 +18,12 @@ fn scroll<T>(cx: Scope<T>, pos: usize) {
pub enum KeyEvent {
Exec,
Exit,
ShiftUp,
ShiftDown,
MovePrev,
MoveNext,
OpenMenu,
CloseMenu,
JumpNext,
JumpPrev,
}
pub struct InnerState {
@ -46,8 +48,20 @@ impl InnerState {
self.pos = std::cmp::min(self.pos + x, max - 1)
}
/// Jump a spefified number of results upwards
#[inline]
pub fn jump_up(&mut self, jump: usize) {
self.move_up(jump)
}
/// Jump a specified number of results downwards
pub fn jump_down(&mut self, jump: usize, results: &Vec<&Entry>) {
let max = std::cmp::max(results.len(), 1);
self.move_down(jump, max);
}
/// Move Up Once With Context of SubMenu
pub fn shift_up(&mut self) {
pub fn move_prev(&mut self) {
if self.subpos > 0 {
self.subpos -= 1;
return;
@ -56,15 +70,14 @@ impl InnerState {
}
/// Move Down Once With Context of SubMenu
pub fn shift_down(&mut self, results: &Vec<&Entry>) {
pub fn move_next(&mut self, results: &Vec<&Entry>) {
if let Some(result) = results.get(self.pos) {
if self.subpos > 0 && self.subpos < result.actions.len() - 1 {
self.subpos += 1;
return;
}
}
let max = std::cmp::max(results.len(), 1);
self.move_down(1, max);
self.jump_down(1, results)
}
}
@ -164,13 +177,22 @@ impl<'a> AppState<'a> {
KeyEvent::Exec => self.execute(),
KeyEvent::OpenMenu => self.open_menu(),
KeyEvent::CloseMenu => self.close_menu(),
KeyEvent::ShiftUp => {
self.shift_up();
KeyEvent::MovePrev => {
self.move_prev();
let pos = self.position().0;
scroll(cx, if pos <= 3 { pos } else { pos + 3 })
}
KeyEvent::ShiftDown => {
self.shift_down();
KeyEvent::MoveNext => {
self.move_next();
scroll(cx, self.position().0 + 3)
}
KeyEvent::JumpPrev => {
self.jump_prev();
let pos = self.position().0;
scroll(cx, if pos <= 3 { pos } else { pos + 3 })
}
KeyEvent::JumpNext => {
self.jump_next();
scroll(cx, self.position().0 + 3)
}
};
@ -265,13 +287,28 @@ impl<'a> AppState<'a> {
/// Move Up Once With Context of SubMenu
#[inline]
pub fn shift_up(&self) {
self.state.with_mut(|s| s.shift_up());
pub fn move_prev(&self) {
self.state.with_mut(|s| s.move_prev());
}
/// Move Down Once With Context of SubMenu
#[inline]
pub fn shift_down(&self) {
self.state.with_mut(|s| s.shift_down(&self.results))
pub fn move_next(&self) {
self.state.with_mut(|s| s.move_next(&self.results))
}
/// Jump a Configured Distance Up the Results
#[inline]
pub fn jump_prev(&self) {
let distance = self.app.config.jump_dist;
self.state.with_mut(|s| s.jump_up(distance))
}
/// Jump a Configured Distance Down the Results
#[inline]
pub fn jump_next(&self) {
let distance = self.app.config.jump_dist;
self.state
.with_mut(|s| s.jump_down(distance, &self.results))
}
}