diff --git a/rmenu-plugin/src/bin/main.rs b/rmenu-plugin/src/bin/main.rs index ace6d87..b026d42 100644 --- a/rmenu-plugin/src/bin/main.rs +++ b/rmenu-plugin/src/bin/main.rs @@ -171,6 +171,9 @@ struct OptionArgs { /// Override Window Fullscreen Settings #[arg(short, long)] pub fullscreen: Option, + /// Override Window Tranparent Settings + #[arg(short, long)] + pub transparent: Option, /// Override Window Width #[arg(short = 'w', long)] pub window_width: Option, @@ -198,6 +201,7 @@ impl Into for OptionArgs { title: self.title, decorate: self.deocorate, fullscreen: self.fullscreen, + transparent: self.transparent, window_width: self.window_width, window_height: self.window_height, } diff --git a/rmenu-plugin/src/lib.rs b/rmenu-plugin/src/lib.rs index 17cd7e0..44e7324 100644 --- a/rmenu-plugin/src/lib.rs +++ b/rmenu-plugin/src/lib.rs @@ -120,6 +120,8 @@ pub struct Options { #[serde(skip_serializing_if = "Option::is_none")] pub decorate: Option, #[serde(skip_serializing_if = "Option::is_none")] + pub transparent: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub fullscreen: Option, #[serde(skip_serializing_if = "Option::is_none")] pub window_width: Option, diff --git a/rmenu/public/config.yaml b/rmenu/public/config.yaml index 54d931b..3e951fb 100644 --- a/rmenu/public/config.yaml +++ b/rmenu/public/config.yaml @@ -25,6 +25,15 @@ plugins: drun: exec: ["~/.config/rmenu/rmenu-desktop"] cache: onlogin + options: + css: ~/Code/rust/rmenu2/themes/fullscreen.css + transparent: true + window_width: 1200 + window_height: 800 + key_move_prev: ["Arrow-Left"] + key_move_next: ["Arrow-Right"] + key_jump_prev: ["Arrow-Up"] + key_jump_next: ["Arrow-Down"] network: exec: ["~/.config/rmenu/rmenu-network"] cache: false diff --git a/rmenu/src/cache.rs b/rmenu/src/cache.rs index 396fed3..b33707a 100644 --- a/rmenu/src/cache.rs +++ b/rmenu/src/cache.rs @@ -78,7 +78,7 @@ pub fn write_cache(name: &str, cfg: &PluginConfig, entries: &Vec) -> Resu match cfg.cache { CacheSetting::NoCache => {} _ => { - println!("writing {} entries", entries.len()); + log::debug!("{name:?} writing {} entries", entries.len()); let path = cache_file(name); let f = fs::File::create(path)?; serde_json::to_writer(f, entries)?; diff --git a/rmenu/src/cli.rs b/rmenu/src/cli.rs index 3916e83..8318adf 100644 --- a/rmenu/src/cli.rs +++ b/rmenu/src/cli.rs @@ -8,7 +8,7 @@ use clap::Parser; use rmenu_plugin::{Entry, Message}; use thiserror::Error; -use crate::config::{Config, Keybind}; +use crate::config::{cfg_replace, Config, Keybind}; use crate::{DEFAULT_CONFIG, DEFAULT_CSS}; /// Allowed Formats for Entry Ingestion @@ -177,33 +177,6 @@ pub enum RMenuError { pub type Result = std::result::Result; -macro_rules! cli_replace { - ($key:expr, $repl:expr) => { - if $repl.is_some() { - $key = $repl.clone(); - } - }; - ($key:expr, $repl:expr, true) => { - if let Some(value) = $repl.as_ref() { - $key = value.to_owned(); - } - }; -} - -macro_rules! cli_keybind { - ($key:expr, $repl:expr) => { - if let Some(bind_strings) = $repl.as_ref() { - let mut keybinds = vec![]; - for bind_str in bind_strings.iter() { - let bind = - Keybind::from_str(bind_str).map_err(|e| RMenuError::InvalidKeybind(e))?; - keybinds.push(bind); - } - $key = keybinds; - } - }; -} - impl Args { /// Load Configuration File pub fn get_config(&self) -> Result { @@ -233,32 +206,32 @@ impl Args { config.use_icons = self.use_icons.unwrap_or(config.use_icons); config.use_comments = self.use_icons.unwrap_or(config.use_comments); // override search settings - cli_replace!(config.search.restrict, self.search_restrict); - cli_replace!(config.search.min_length, self.search_min_length); - cli_replace!(config.search.max_length, self.search_max_length); - cli_replace!(config.search.use_regex, self.search_regex, true); - cli_replace!(config.search.ignore_case, self.ignore_case, true); - cli_replace!(config.search.placeholder, self.placeholder); + cfg_replace!(config.search.restrict, self.search_restrict); + cfg_replace!(config.search.min_length, self.search_min_length); + cfg_replace!(config.search.max_length, self.search_max_length); + cfg_replace!(config.search.use_regex, self.search_regex, true); + cfg_replace!(config.search.ignore_case, self.ignore_case, true); + cfg_replace!(config.search.placeholder, self.placeholder); // override keybind settings - cli_replace!(config.keybinds.exec, self.key_exec, true); - cli_replace!(config.keybinds.exit, self.key_exit, true); - cli_replace!(config.keybinds.move_next, self.key_move_next, true); - 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); + cfg_replace!(config.keybinds.exec, self.key_exec, true); + cfg_replace!(config.keybinds.exit, self.key_exit, true); + cfg_replace!(config.keybinds.move_next, self.key_move_next, true); + cfg_replace!(config.keybinds.move_prev, self.key_move_prev, true); + cfg_replace!(config.keybinds.open_menu, self.key_open_menu, true); + cfg_replace!(config.keybinds.close_menu, self.key_close_menu, true); + cfg_replace!(config.keybinds.jump_next, self.key_jump_next, true); + cfg_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); - cli_replace!(config.window.size.height, self.height, true); - cli_replace!(config.window.position.x, self.xpos, true); - cli_replace!(config.window.position.y, self.ypos, true); - cli_replace!(config.window.focus, self.focus, true); - cli_replace!(config.window.decorate, self.decorate, true); - cli_replace!(config.window.transparent, self.transparent, true); - cli_replace!(config.window.always_top, self.always_top, true); - cli_replace!(config.window.fullscreen, self.fullscreen); + cfg_replace!(config.window.title, self.title, true); + cfg_replace!(config.window.size.width, self.width, true); + cfg_replace!(config.window.size.height, self.height, true); + cfg_replace!(config.window.position.x, self.xpos, true); + cfg_replace!(config.window.position.y, self.ypos, true); + cfg_replace!(config.window.focus, self.focus, true); + cfg_replace!(config.window.decorate, self.decorate, true); + cfg_replace!(config.window.transparent, self.transparent, true); + cfg_replace!(config.window.always_top, self.always_top, true); + cfg_replace!(config.window.fullscreen, self.fullscreen); config } @@ -275,8 +248,8 @@ impl Args { } /// Load Additional CSS or Default - pub fn get_css(&self) -> String { - if let Some(css) = self.css.as_ref() { + pub fn get_css(&self, c: &Config) -> String { + if let Some(css) = self.css.as_ref().or(c.css.as_ref()) { let path = shellexpand::tilde(&css).to_string(); match read_to_string(&path) { Ok(theme) => return theme, @@ -299,30 +272,9 @@ impl Args { let msg: Message = serde_json::from_str(&line)?; match msg { Message::Entry(entry) => v.push(entry), - Message::Options(options) => { - // base settings - self.css = self.css.clone().or(options.css); - // search settings - cli_replace!(c.search.placeholder, options.placeholder); - cli_replace!(c.search.restrict, options.search_restrict); - cli_replace!(c.search.min_length, options.search_min_length); - cli_replace!(c.search.max_length, options.search_max_length); - // keybind settings - cli_keybind!(c.keybinds.exec, options.key_exec); - cli_keybind!(c.keybinds.exec, options.key_exec); - cli_keybind!(c.keybinds.exit, options.key_exit); - cli_keybind!(c.keybinds.move_next, options.key_move_next); - 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); - cli_replace!(c.window.size.width, options.window_width, true); - cli_replace!(c.window.size.height, options.window_height, true); - } + Message::Options(options) => c + .update(&options) + .map_err(|s| RMenuError::InvalidKeybind(s))?, } } } @@ -355,6 +307,12 @@ impl Args { .get(&name) .cloned() .ok_or_else(|| RMenuError::NoSuchPlugin(name.to_owned()))?; + // update config w/ plugin options when available + if let Some(options) = plugin.options.as_ref() { + config + .update(options) + .map_err(|e| RMenuError::InvalidKeybind(e))?; + } // read cache when available match crate::cache::read_cache(&name, &plugin) { Err(err) => log::error!("cache read failed: {err:?}"), diff --git a/rmenu/src/config.rs b/rmenu/src/config.rs index b1b197a..13ada9b 100644 --- a/rmenu/src/config.rs +++ b/rmenu/src/config.rs @@ -1,6 +1,7 @@ //! RMENU Configuration Implementations use heck::AsPascalCase; use keyboard_types::{Code, Modifiers}; +use rmenu_plugin::Options; use serde::{de::Error, Deserialize}; use std::collections::BTreeMap; use std::str::FromStr; @@ -201,6 +202,8 @@ pub struct PluginConfig { pub cache: CacheSetting, #[serde(default)] pub placeholder: Option, + #[serde(default)] + pub options: Option, } #[inline] @@ -249,6 +252,7 @@ pub struct Config { pub plugins: BTreeMap, pub keybinds: KeyConfig, pub window: WindowConfig, + pub css: Option, pub terminal: Option, } @@ -264,7 +268,67 @@ impl Default for Config { plugins: Default::default(), keybinds: Default::default(), window: Default::default(), - terminal: Default::default(), + css: None, + terminal: None, } } } + +macro_rules! cfg_replace { + ($key:expr, $repl:expr) => { + if $repl.is_some() { + $key = $repl.clone(); + } + }; + ($key:expr, $repl:expr, true) => { + if let Some(value) = $repl.as_ref() { + $key = value.to_owned(); + } + }; +} + +macro_rules! cfg_keybind { + ($key:expr, $repl:expr) => { + if let Some(bind_strings) = $repl.as_ref() { + let mut keybinds = vec![]; + for bind_str in bind_strings.iter() { + let bind = Keybind::from_str(bind_str)?; + keybinds.push(bind); + } + $key = keybinds; + } + }; +} + +pub(crate) use cfg_keybind; +pub(crate) use cfg_replace; + +impl Config { + /// Update Configuration from Options Object + pub fn update(&mut self, options: &Options) -> Result<(), String> { + cfg_replace!(self.css, options.css); + // search settings + cfg_replace!(self.search.placeholder, options.placeholder); + cfg_replace!(self.search.restrict, options.search_restrict); + cfg_replace!(self.search.min_length, options.search_min_length); + cfg_replace!(self.search.max_length, options.search_max_length); + // keybind settings + cfg_keybind!(self.keybinds.exec, options.key_exec); + cfg_keybind!(self.keybinds.exec, options.key_exec); + cfg_keybind!(self.keybinds.exit, options.key_exit); + cfg_keybind!(self.keybinds.move_next, options.key_move_next); + cfg_keybind!(self.keybinds.move_prev, options.key_move_prev); + cfg_keybind!(self.keybinds.open_menu, options.key_open_menu); + cfg_keybind!(self.keybinds.close_menu, options.key_close_menu); + cfg_keybind!(self.keybinds.jump_next, options.key_jump_next); + cfg_keybind!(self.keybinds.jump_prev, options.key_jump_prev); + // window settings + cfg_replace!(self.window.title, options.title, true); + cfg_replace!(self.window.decorate, options.decorate, true); + cfg_replace!(self.window.fullscreen, options.fullscreen); + cfg_replace!(self.window.transparent, options.transparent, true); + cfg_replace!(self.window.size.width, options.window_width, true); + cfg_replace!(self.window.size.height, options.window_height, true); + Ok(()) + } +} diff --git a/rmenu/src/image.rs b/rmenu/src/image.rs index a2388ca..b77f0a6 100644 --- a/rmenu/src/image.rs +++ b/rmenu/src/image.rs @@ -1,5 +1,5 @@ //! GUI Image Processing -use std::fs::{create_dir_all, read_to_string, write}; +use std::fs::{create_dir_all, write}; use std::io; use std::path::PathBuf; use std::sync::Mutex; @@ -37,9 +37,9 @@ fn make_temp() -> Result<(), io::Error> { /// Convert SVG to PNG Image fn svg_to_png(path: &str, dest: &PathBuf, pixels: u32) -> Result<(), SvgError> { // read and convert to resvg document tree - let xml = read_to_string(path)?; + let xml = std::fs::read(path)?; let opt = resvg::usvg::Options::default(); - let tree = resvg::usvg::Tree::from_str(&xml, &opt)?; + let tree = resvg::usvg::Tree::from_data(&xml, &opt)?; let rtree = resvg::Tree::from_usvg(&tree); // generate pixel-buffer and scale according to size preference let size = rtree.size.to_int_size(); diff --git a/rmenu/src/main.rs b/rmenu/src/main.rs index c194ecf..2b1d962 100644 --- a/rmenu/src/main.rs +++ b/rmenu/src/main.rs @@ -45,7 +45,7 @@ fn main() -> cli::Result<()> { let mut cli = cli::Args::parse(); let mut config = cli.get_config()?; let entries = cli.get_entries(&mut config)?; - let css = cli.get_css(); + let css = cli.get_css(&config); let theme = cli.get_theme(); // update config based on cli-settings and entries