mirror of
https://github.com/imgurbot12/rmenu.git
synced 2025-01-12 23:36:29 +01:00
feat: better cfg defaults, navigation fixes, css uses one file w/ builtin backup.
This commit is contained in:
parent
25ee2f32c4
commit
82897da0e2
6 changed files with 42 additions and 49 deletions
|
@ -9,7 +9,7 @@ edition = "2021"
|
|||
clap = { version = "4.3.15", features = ["derive"] }
|
||||
dioxus = "0.3.2"
|
||||
dioxus-desktop = "0.3.0"
|
||||
dirs = "5.0.1"
|
||||
env_logger = "0.10.0"
|
||||
heck = "0.4.1"
|
||||
keyboard-types = "0.6.2"
|
||||
log = "0.4.19"
|
||||
|
|
|
@ -74,14 +74,13 @@ impl<'de> Deserialize<'de> for Keybind {
|
|||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Deserialize)]
|
||||
#[serde(default)]
|
||||
pub struct KeyConfig {
|
||||
pub exec: Vec<Keybind>,
|
||||
pub exit: Vec<Keybind>,
|
||||
pub move_up: Vec<Keybind>,
|
||||
pub move_down: Vec<Keybind>,
|
||||
#[serde(default)]
|
||||
pub open_menu: Vec<Keybind>,
|
||||
#[serde(default)]
|
||||
pub close_menu: Vec<Keybind>,
|
||||
}
|
||||
|
||||
|
@ -129,23 +128,19 @@ impl Default for WindowConfig {
|
|||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Deserialize)]
|
||||
#[serde(default)]
|
||||
pub struct Config {
|
||||
pub css: Vec<String>,
|
||||
pub use_icons: bool,
|
||||
pub search_regex: bool,
|
||||
pub ignore_case: bool,
|
||||
#[serde(default)]
|
||||
pub plugins: BTreeMap<String, Vec<String>>,
|
||||
#[serde(default)]
|
||||
pub keybinds: KeyConfig,
|
||||
#[serde(default)]
|
||||
pub window: WindowConfig,
|
||||
}
|
||||
|
||||
impl Default for Config {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
css: vec![],
|
||||
use_icons: true,
|
||||
search_regex: false,
|
||||
ignore_case: true,
|
||||
|
|
|
@ -5,6 +5,7 @@ use std::process::Command;
|
|||
use rmenu_plugin::Action;
|
||||
|
||||
pub fn execute(action: &Action) {
|
||||
log::info!("executing: {} {:?}", action.name, action.exec);
|
||||
let args = match shell_words::split(&action.exec) {
|
||||
Ok(args) => args,
|
||||
Err(err) => panic!("{:?} invalid command {err}", action.exec),
|
||||
|
|
|
@ -95,13 +95,8 @@ fn TableEntry<'a>(cx: Scope<'a, GEntry<'a>>) -> Element<'a> {
|
|||
ondblclick: |_| {
|
||||
let action = match cx.props.entry.actions.get(0) {
|
||||
Some(action) => action,
|
||||
None => {
|
||||
let name = &cx.props.entry.name;
|
||||
log::warn!("no action to execute on {:?}", name);
|
||||
return;
|
||||
}
|
||||
None => panic!("No Action Configured"),
|
||||
};
|
||||
log::info!("executing: {:?}", action.exec);
|
||||
execute(action);
|
||||
},
|
||||
if cx.props.config.use_icons {
|
||||
|
@ -168,7 +163,7 @@ fn App(cx: Scope<App>) -> Element {
|
|||
// retrieve results build and build position-tracker
|
||||
let tracker = PosTracker::new(cx, results.clone());
|
||||
let (pos, subpos) = tracker.position();
|
||||
log::debug!("pos: {pos}, {subpos}");
|
||||
log::debug!("search: {search:?}, pos: {pos}, {subpos}");
|
||||
|
||||
// keyboard events
|
||||
let keybinds = &cx.props.config.keybinds;
|
||||
|
|
|
@ -15,6 +15,11 @@ use clap::Parser;
|
|||
use rmenu_plugin::Entry;
|
||||
use thiserror::Error;
|
||||
|
||||
static CONFIG_DIR: &'static str = "~/.config/rmenu/";
|
||||
static DEFAULT_CSS: &'static str = "~/.config/rmenu/style.css";
|
||||
static DEFAULT_CONFIG: &'static str = "~/.config/rmenu/config.yaml";
|
||||
static DEFAULT_CSS_CONTENT: &'static str = include_str!("../public/default.css");
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Format {
|
||||
Json,
|
||||
|
@ -80,7 +85,7 @@ pub struct Args {
|
|||
#[arg(short, long)]
|
||||
config: Option<String>,
|
||||
#[arg(long)]
|
||||
css: Vec<String>,
|
||||
css: Option<String>,
|
||||
}
|
||||
|
||||
impl Args {
|
||||
|
@ -88,16 +93,7 @@ impl Args {
|
|||
fn config(&self) -> Result<config::Config, RMenuError> {
|
||||
let path = match &self.config {
|
||||
Some(path) => path.to_owned(),
|
||||
None => match dirs::config_dir() {
|
||||
Some(mut dir) => {
|
||||
dir.push("rmenu");
|
||||
dir.push("config.yaml");
|
||||
dir.to_string_lossy().to_string()
|
||||
}
|
||||
None => {
|
||||
return Err(RMenuError::HomeNotFound);
|
||||
}
|
||||
},
|
||||
None => shellexpand::tilde(DEFAULT_CONFIG).to_string(),
|
||||
};
|
||||
log::debug!("loading config from {path:?}");
|
||||
let cfg = match read_to_string(path) {
|
||||
|
@ -140,7 +136,7 @@ impl Args {
|
|||
|
||||
/// Load Entries From Specified Sources
|
||||
fn load_sources(&self, cfg: &config::Config) -> Result<Vec<Entry>, RMenuError> {
|
||||
println!("{cfg:?}");
|
||||
log::debug!("config: {cfg:?}");
|
||||
// execute commands to get a list of entries
|
||||
let mut entries = vec![];
|
||||
for plugin in self.run.iter() {
|
||||
|
@ -188,15 +184,17 @@ impl Args {
|
|||
/// Load Application
|
||||
pub fn parse_app() -> Result<App, RMenuError> {
|
||||
let args = Self::parse();
|
||||
let mut config = args.config()?;
|
||||
let config = args.config()?;
|
||||
// load css files from settings
|
||||
config.css.extend(args.css.clone());
|
||||
let mut css = vec![];
|
||||
for path in config.css.iter() {
|
||||
let path = shellexpand::tilde(path).to_string();
|
||||
let src = read_to_string(path)?;
|
||||
css.push(src);
|
||||
}
|
||||
let csspath = args.css.clone().unwrap_or_else(|| DEFAULT_CSS.to_owned());
|
||||
let csspath = shellexpand::tilde(&csspath).to_string();
|
||||
let css = match read_to_string(csspath) {
|
||||
Ok(css) => css,
|
||||
Err(err) => {
|
||||
log::error!("failed to load css: {err:?}");
|
||||
DEFAULT_CSS_CONTENT.to_owned()
|
||||
}
|
||||
};
|
||||
// load entries from configured sources
|
||||
let entries = match args.run.len() > 0 {
|
||||
true => args.load_sources(&config)?,
|
||||
|
@ -204,7 +202,7 @@ impl Args {
|
|||
};
|
||||
// generate app object
|
||||
return Ok(App {
|
||||
css: css.join("\n"),
|
||||
css,
|
||||
name: "rmenu".to_owned(),
|
||||
entries,
|
||||
config,
|
||||
|
@ -215,13 +213,16 @@ impl Args {
|
|||
//TODO: improve search w/ modes?
|
||||
//TODO: improve looks and css
|
||||
|
||||
//TODO: config
|
||||
// - default and cli accessable modules (instead of piped in)
|
||||
// - should resolve arguments/paths with home expansion
|
||||
|
||||
//TODO: add exit key (Esc by default?) - part of keybindings
|
||||
|
||||
fn main() -> Result<(), RMenuError> {
|
||||
// enable log if env-var is present
|
||||
if std::env::var("RUST_LOG").is_ok() {
|
||||
env_logger::init();
|
||||
}
|
||||
// change directory to configuration dir
|
||||
let cfgdir = shellexpand::tilde(CONFIG_DIR).to_string();
|
||||
if let Err(err) = std::env::set_current_dir(&cfgdir) {
|
||||
log::error!("failed to change directory: {err:?}");
|
||||
}
|
||||
// parse cli / config / application-settings
|
||||
let app = Args::parse_app()?;
|
||||
gui::run(app);
|
||||
|
|
|
@ -28,9 +28,9 @@ impl<'a> PosTracker<'a> {
|
|||
}
|
||||
/// Move X Primary Results Downwards
|
||||
pub fn move_down(&self, x: usize) {
|
||||
let max = std::cmp::max(self.results.len(), 1);
|
||||
self.subpos.set(0);
|
||||
self.pos
|
||||
.modify(|v| std::cmp::min(v + x, self.results.len() - 1))
|
||||
self.pos.modify(|v| std::cmp::min(v + x, max - 1))
|
||||
}
|
||||
/// Get Current Position/SubPosition
|
||||
pub fn position(&self) -> (usize, usize) {
|
||||
|
@ -64,11 +64,12 @@ impl<'a> PosTracker<'a> {
|
|||
/// Move Down Once With Context of SubMenu
|
||||
pub fn shift_down(&self) {
|
||||
let index = *self.pos.get();
|
||||
let result = &self.results[index];
|
||||
let subpos = *self.subpos.get();
|
||||
if subpos > 0 && subpos < result.actions.len() - 1 {
|
||||
self.subpos.modify(|v| v + 1);
|
||||
return;
|
||||
if let Some(result) = &self.results.get(index) {
|
||||
let subpos = *self.subpos.get();
|
||||
if subpos > 0 && subpos < result.actions.len() - 1 {
|
||||
self.subpos.modify(|v| v + 1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
self.move_down(1)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue