feat: better config defaults, added dmenu format, no-comments mode, placeholder opt

This commit is contained in:
imgurbot12 2023-08-11 16:24:30 -07:00
parent ad460bd8c2
commit 8bd0a91eb1
5 changed files with 80 additions and 17 deletions

View File

@ -5,6 +5,7 @@ use serde::{Deserialize, Serialize};
pub enum Method {
Terminal(String),
Run(String),
Echo(String),
}
impl Method {
@ -31,6 +32,13 @@ impl Action {
comment: None,
}
}
pub fn echo(echo: &str) -> Self {
Self {
name: "main".to_string(),
exec: Method::Echo(echo.to_string()),
comment: None,
}
}
}
#[derive(Debug, PartialEq, Serialize, Deserialize)]
@ -50,4 +58,13 @@ impl Entry {
icon: Default::default(),
}
}
pub fn echo(echo: &str, comment: Option<&str>) -> Self {
Self {
name: echo.to_owned(),
actions: vec![Action::echo(echo)],
comment: comment.map(|c| c.to_owned()),
icon: Default::default(),
}
}
}

View File

@ -116,12 +116,8 @@ impl Default for WindowConfig {
fn default() -> Self {
Self {
title: "RMenu - App Launcher".to_owned(),
// size: LogicalSize {
// width: 700.0,
// height: 400.0,
// },
size: LogicalSize {
width: 1000.0,
width: 700.0,
height: 400.0,
},
position: LogicalPosition { x: 100.0, y: 100.0 },
@ -182,6 +178,13 @@ pub struct PluginConfig {
pub exec: Vec<String>,
#[serde(default)]
pub cache: CacheSetting,
#[serde(default)]
pub placeholder: Option<String>,
}
#[inline]
fn _true() -> bool {
true
}
/// Global RMenu Complete Configuration
@ -190,9 +193,15 @@ pub struct PluginConfig {
pub struct Config {
pub page_size: usize,
pub page_load: f64,
#[serde(default = "_true")]
pub use_icons: bool,
#[serde(default = "_true")]
pub use_comments: bool,
#[serde(default = "_true")]
pub search_regex: bool,
#[serde(default = "_true")]
pub ignore_case: bool,
pub placeholder: Option<String>,
pub plugins: BTreeMap<String, PluginConfig>,
pub keybinds: KeyConfig,
pub window: WindowConfig,
@ -205,8 +214,10 @@ impl Default for Config {
page_size: 50,
page_load: 0.8,
use_icons: true,
use_comments: true,
search_regex: false,
ignore_case: true,
placeholder: Default::default(),
plugins: Default::default(),
keybinds: Default::default(),
window: Default::default(),

View File

@ -51,6 +51,10 @@ pub fn execute(action: &Action, term: Option<String>) {
let command = strfmt(&terminal, &args).expect("Failed String Format");
parse_args(&command)
}
Method::Echo(echo) => {
println!("{echo}");
std::process::exit(0);
}
};
let err = Command::new(&args[0]).args(&args[1..]).exec();
panic!("Command Error: {err:?}");

View File

@ -121,6 +121,8 @@ fn TableEntry<'a>(cx: Scope<'a, GEntry<'a>>) -> Element<'a> {
}
})
}
match cx.props.state.config().use_comments {
true => cx.render(rsx! {
div {
class: "name",
"{cx.props.entry.name}"
@ -129,6 +131,14 @@ fn TableEntry<'a>(cx: Scope<'a, GEntry<'a>>) -> Element<'a> {
class: "comment",
render_comment(cx.props.entry.comment.as_ref())
}
}),
false => cx.render(rsx! {
div {
class: "entry",
"{cx.props.entry.name}"
}
})
}
}
div {
id: "result-{cx.props.index}-actions",
@ -209,6 +219,16 @@ fn App<'a>(cx: Scope<App>) -> Element {
})
});
// retreive placeholder
let placeholder = cx
.props
.config
.placeholder
.as_ref()
.map(|s| s.to_string())
.unwrap_or_else(|| "".to_owned());
// complete final rendering
cx.render(rsx! {
style { DEFAULT_CSS_CONTENT }
style { "{cx.props.css}" }
@ -220,6 +240,7 @@ fn App<'a>(cx: Scope<App>) -> Element {
input {
id: "search",
value: "{search}",
placeholder: "{placeholder}",
oninput: move |evt| s_updater.set_search(cx, evt.value.clone()),
}
}

View File

@ -25,7 +25,7 @@ static DEFAULT_CSS_CONTENT: &'static str = include_str!("../public/default.css")
#[derive(Debug, Clone)]
pub enum Format {
Json,
MsgPack,
DMenu,
}
impl Display for Format {
@ -40,7 +40,7 @@ impl FromStr for Format {
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.to_ascii_lowercase().as_str() {
"json" => Ok(Format::Json),
"msgpack" => Ok(Format::MsgPack),
"dmenu" => Ok(Format::DMenu),
_ => Err("No Such Format".to_owned()),
}
}
@ -90,6 +90,8 @@ pub struct Args {
config: Option<String>,
#[arg(long)]
css: Option<String>,
#[arg(short, long)]
placehold: Option<String>,
}
impl Args {
@ -114,7 +116,7 @@ impl Args {
fn readentry(&self, cfg: &config::Config, line: &str) -> Result<Entry, RMenuError> {
let mut entry = match self.format {
Format::Json => serde_json::from_str::<Entry>(line)?,
Format::MsgPack => todo!(),
Format::DMenu => Entry::echo(line.trim(), None),
};
if !cfg.use_icons {
entry.icon = None;
@ -140,7 +142,7 @@ impl Args {
}
/// Load Entries From Specified Sources
fn load_sources(&self, cfg: &config::Config) -> Result<Vec<Entry>, RMenuError> {
fn load_sources(&self, cfg: &mut config::Config) -> Result<Vec<Entry>, RMenuError> {
log::debug!("config: {cfg:?}");
// execute commands to get a list of entries
let mut entries = vec![];
@ -192,6 +194,10 @@ impl Args {
Some(status.clone()),
));
}
// update placeholder if empty
if cfg.placeholder.is_none() {
cfg.placeholder = plugin.placeholder.clone();
}
// write cache for entries collected
match cache::write_cache(name, plugin, &entries) {
Ok(_) => {}
@ -217,12 +223,16 @@ impl Args {
};
// load entries from configured sources
let entries = match args.run.len() > 0 {
true => args.load_sources(&config)?,
true => args.load_sources(&mut config)?,
false => args.load_default(&config)?,
};
// update configuration based on cli
config.use_icons = config.use_icons && entries.iter().any(|e| e.icon.is_some());
config.use_comments = config.use_icons && entries.iter().any(|e| e.comment.is_some());
config.search_regex = args.regex.unwrap_or(config.search_regex);
if args.placehold.is_some() {
config.placeholder = args.placehold.clone();
};
// generate app object
return Ok(App {
css,