mirror of
https://github.com/imgurbot12/rmenu.git
synced 2025-01-27 05:18:33 +01:00
feat: improved cli and implemented options entry override
This commit is contained in:
parent
7e3c6c45d8
commit
1501e748d0
6 changed files with 322 additions and 115 deletions
|
@ -12,13 +12,8 @@ path = "src/lib.rs"
|
|||
[[bin]]
|
||||
name = "rmenu-build"
|
||||
path = "src/bin/main.rs"
|
||||
required-features = ["cli"]
|
||||
|
||||
[features]
|
||||
default = []
|
||||
cli = ["clap", "serde_json"]
|
||||
|
||||
[dependencies]
|
||||
clap = { version = "4.3.22", features = ["derive"], optional = true }
|
||||
clap = { version = "4.3.22", features = ["derive"] }
|
||||
serde = { version = "1.0.171", features = ["derive"] }
|
||||
serde_json = { version = "1.0.105", optional = true }
|
||||
serde_json = "1.0.105"
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
use std::{fmt::Display, str::FromStr};
|
||||
|
||||
use rmenu_plugin::*;
|
||||
|
||||
use clap::{Parser, Subcommand};
|
||||
use clap::{Args, Parser, Subcommand};
|
||||
|
||||
/// Parse Action from JSON
|
||||
fn parse_action(action: &str) -> Result<Action, serde_json::Error> {
|
||||
|
@ -17,42 +19,192 @@ fn parse_action(action: &str) -> Result<Action, serde_json::Error> {
|
|||
// 2. plugin/source latest merged options
|
||||
// 3. configuration settings
|
||||
|
||||
//TODO: add python library to build entries as well
|
||||
|
||||
/// Valid Action Modes
|
||||
#[derive(Debug, Clone)]
|
||||
enum ActionMode {
|
||||
Run,
|
||||
Terminal,
|
||||
Echo,
|
||||
}
|
||||
|
||||
impl Display for ActionMode {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Self::Run => write!(f, "run"),
|
||||
Self::Terminal => write!(f, "terminal"),
|
||||
Self::Echo => write!(f, "echo"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for ActionMode {
|
||||
type Err = String;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
match s {
|
||||
"run" => Ok(Self::Run),
|
||||
"terminal" => Ok(Self::Terminal),
|
||||
"echo" => Ok(Self::Echo),
|
||||
_ => Err(format!("Invalid Method: {s:?}")),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Arguents for Action CLI Command
|
||||
#[derive(Debug, Args)]
|
||||
struct ActionArgs {
|
||||
/// Set Name of Action
|
||||
#[arg(short, long, default_value_t=String::from("main"))]
|
||||
name: String,
|
||||
/// Set Comment of Action
|
||||
#[arg(short, long)]
|
||||
comment: Option<String>,
|
||||
/// Arguments to run As Action Command
|
||||
#[clap(required = true, value_delimiter = ' ')]
|
||||
args: Vec<String>,
|
||||
/// Action Mode
|
||||
#[arg(short, long, default_value_t=ActionMode::Run)]
|
||||
mode: ActionMode,
|
||||
}
|
||||
|
||||
impl Into<Action> for ActionArgs {
|
||||
fn into(self) -> Action {
|
||||
let exec = self.args.join(" ");
|
||||
Action {
|
||||
name: self.name,
|
||||
comment: self.comment,
|
||||
exec: match self.mode {
|
||||
ActionMode::Run => Method::Run(exec),
|
||||
ActionMode::Terminal => Method::Terminal(exec),
|
||||
ActionMode::Echo => Method::Echo(exec),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Arguments for Entry CLI Command
|
||||
#[derive(Debug, Args)]
|
||||
struct EntryArgs {
|
||||
/// Set Name of Entry
|
||||
#[arg(short, long, default_value_t=String::from("main"))]
|
||||
name: String,
|
||||
/// Set Comment of Entry
|
||||
#[arg(short, long)]
|
||||
comment: Option<String>,
|
||||
/// Precomposed Action JSON Objects
|
||||
#[arg(short, long, value_parser=parse_action)]
|
||||
#[clap(required = true)]
|
||||
actions: Vec<Action>,
|
||||
/// Icon Image Path
|
||||
#[arg(short, long)]
|
||||
icon: Option<String>,
|
||||
/// Alternative Image Text/HTML
|
||||
#[arg(short = 'o', long)]
|
||||
icon_alt: Option<String>,
|
||||
}
|
||||
|
||||
impl Into<Entry> for EntryArgs {
|
||||
fn into(self) -> Entry {
|
||||
Entry {
|
||||
name: self.name,
|
||||
comment: self.comment,
|
||||
actions: self.actions,
|
||||
icon: self.icon,
|
||||
icon_alt: self.icon_alt,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Arguments for Options CLI Command
|
||||
#[derive(Debug, Args)]
|
||||
struct OptionArgs {
|
||||
/// Override Applicaiton Theme
|
||||
#[arg(short, long)]
|
||||
pub theme: Option<String>,
|
||||
// search settings
|
||||
/// Override Default Placeholder
|
||||
#[arg(short, long)]
|
||||
pub placeholder: Option<String>,
|
||||
/// Override Search Restriction
|
||||
#[arg(short = 'r', long)]
|
||||
pub search_restrict: Option<String>,
|
||||
/// Override Minimum Search Length
|
||||
#[arg(short = 'm', long)]
|
||||
pub search_min_length: Option<usize>,
|
||||
/// Override Maximum Search Length
|
||||
#[arg(short = 'M', long)]
|
||||
pub search_max_length: Option<usize>,
|
||||
// key settings
|
||||
/// Override Execution Keybinds
|
||||
#[arg(short = 'e', long)]
|
||||
pub key_exec: Option<Vec<String>>,
|
||||
/// Override Program-Exit Keybinds
|
||||
#[arg(short = 'E', long)]
|
||||
pub key_exit: Option<Vec<String>>,
|
||||
/// Override Move-Next Keybinds
|
||||
#[arg(short = 'n', long)]
|
||||
pub key_move_next: Option<Vec<String>>,
|
||||
/// Override Move-Previous Keybinds
|
||||
#[arg(short = 'p', long)]
|
||||
pub key_move_prev: Option<Vec<String>>,
|
||||
/// Override Open-Menu Keybinds
|
||||
#[arg(short = 'o', long)]
|
||||
pub key_open_menu: Option<Vec<String>>,
|
||||
/// Override Close-Menu Keybinds
|
||||
#[arg(short = 'c', long)]
|
||||
pub key_close_menu: Option<Vec<String>>,
|
||||
// window settings
|
||||
/// Override Window Title
|
||||
#[arg(short, long)]
|
||||
pub title: Option<String>,
|
||||
/// Override Window Deocration Settings
|
||||
#[arg(short, long)]
|
||||
pub deocorate: Option<bool>,
|
||||
/// Override Window Fullscreen Settings
|
||||
#[arg(short, long)]
|
||||
pub fullscreen: Option<bool>,
|
||||
/// Override Window Width
|
||||
#[arg(short = 'w', long)]
|
||||
pub window_width: Option<f64>,
|
||||
/// Override Window Height
|
||||
#[arg(short = 'h', long)]
|
||||
pub window_height: Option<f64>,
|
||||
}
|
||||
|
||||
impl Into<Options> for OptionArgs {
|
||||
fn into(self) -> Options {
|
||||
Options {
|
||||
theme: self.theme,
|
||||
placeholder: self.placeholder,
|
||||
search_restrict: self.search_restrict,
|
||||
search_min_length: self.search_min_length,
|
||||
search_max_length: self.search_max_length,
|
||||
key_exec: self.key_exec,
|
||||
key_exit: self.key_exit,
|
||||
key_move_next: self.key_move_next,
|
||||
key_move_prev: self.key_move_prev,
|
||||
key_open_menu: self.key_open_menu,
|
||||
key_close_menu: self.key_close_menu,
|
||||
title: self.title,
|
||||
decorate: self.deocorate,
|
||||
fullscreen: self.fullscreen,
|
||||
window_width: self.window_width,
|
||||
window_height: self.window_height,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Valid CLI Commands and their Arguments
|
||||
#[derive(Debug, Subcommand)]
|
||||
enum Command {
|
||||
/// Generate Complete RMenu Entry
|
||||
Entry {
|
||||
/// Set Name of Entry
|
||||
#[arg(short, long, default_value_t=String::from("main"))]
|
||||
name: String,
|
||||
/// Set Comment of Entry
|
||||
#[arg(short, long)]
|
||||
comment: Option<String>,
|
||||
/// Precomposed Action JSON Objects
|
||||
#[arg(short, long, value_parser=parse_action)]
|
||||
#[clap(required = true)]
|
||||
actions: Vec<Action>,
|
||||
/// Icon Image Path
|
||||
#[arg(short, long)]
|
||||
icon: Option<String>,
|
||||
/// Alternative Image Text/HTML
|
||||
#[arg(short = 'o', long)]
|
||||
icon_alt: Option<String>,
|
||||
},
|
||||
Entry(EntryArgs),
|
||||
/// Generate RMenu Entry Action Object
|
||||
Action {
|
||||
/// Set Name of Action
|
||||
#[arg(short, long, default_value_t=String::from("main"))]
|
||||
name: String,
|
||||
/// Set Comment of Action
|
||||
#[arg(short, long)]
|
||||
comment: Option<String>,
|
||||
/// Arguments to run As Action Command
|
||||
#[clap(required = true, value_delimiter = ' ')]
|
||||
args: Vec<String>,
|
||||
/// Run in New Terminal Session if Active
|
||||
#[arg(short, long)]
|
||||
terminal: bool,
|
||||
},
|
||||
Action(ActionArgs),
|
||||
/// Generate RMenu Options Settings
|
||||
Options(OptionArgs),
|
||||
}
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
|
@ -67,29 +219,18 @@ struct Cli {
|
|||
fn main() {
|
||||
let cli = Cli::parse();
|
||||
let result = match cli.command {
|
||||
Command::Entry {
|
||||
name,
|
||||
comment,
|
||||
actions,
|
||||
icon,
|
||||
icon_alt,
|
||||
} => serde_json::to_string(&Entry {
|
||||
name,
|
||||
comment,
|
||||
actions,
|
||||
icon,
|
||||
icon_alt,
|
||||
}),
|
||||
Command::Action {
|
||||
name,
|
||||
comment,
|
||||
args,
|
||||
terminal,
|
||||
} => serde_json::to_string(&Action {
|
||||
name,
|
||||
exec: Method::new(args.join(" "), terminal),
|
||||
comment,
|
||||
}),
|
||||
Command::Entry(args) => {
|
||||
let entry: Entry = args.into();
|
||||
serde_json::to_string(&entry)
|
||||
}
|
||||
Command::Action(args) => {
|
||||
let action: Action = args.into();
|
||||
serde_json::to_string(&action)
|
||||
}
|
||||
Command::Options(args) => {
|
||||
let options: Options = args.into();
|
||||
serde_json::to_string(&options)
|
||||
}
|
||||
};
|
||||
println!("{}", result.expect("Serialization Failed"));
|
||||
}
|
||||
|
|
|
@ -83,29 +83,52 @@ impl Entry {
|
|||
|
||||
/// Additional Plugin Option Overrides
|
||||
#[derive(Debug, Default, PartialEq, Clone, Serialize, Deserialize)]
|
||||
#[serde(tag = "type", rename = "options")]
|
||||
#[serde(default)]
|
||||
#[serde(default, tag = "type", rename = "options")]
|
||||
pub struct Options {
|
||||
// base settings
|
||||
theme: Option<String>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub theme: Option<String>,
|
||||
// search settings
|
||||
placeholder: Option<String>,
|
||||
search_restrict: Option<String>,
|
||||
search_min_length: Option<usize>,
|
||||
search_max_length: Option<usize>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub placeholder: Option<String>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub search_restrict: Option<String>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub search_min_length: Option<usize>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub search_max_length: Option<usize>,
|
||||
// key settings
|
||||
key_exec: Option<Vec<String>>,
|
||||
key_exit: Option<Vec<String>>,
|
||||
key_move_next: Option<Vec<String>>,
|
||||
key_move_prev: Option<Vec<String>>,
|
||||
key_open_menu: Option<Vec<String>>,
|
||||
key_close_menu: Option<Vec<String>>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub key_exec: Option<Vec<String>>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub key_exit: Option<Vec<String>>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub key_move_next: Option<Vec<String>>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub key_move_prev: Option<Vec<String>>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub key_open_menu: Option<Vec<String>>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub key_close_menu: Option<Vec<String>>,
|
||||
// window settings
|
||||
title: Option<String>,
|
||||
deocorate: Option<bool>,
|
||||
fullscreen: Option<bool>,
|
||||
window_width: Option<usize>,
|
||||
window_height: Option<usize>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub title: Option<String>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub decorate: Option<bool>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub fullscreen: Option<bool>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub window_width: Option<f64>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub window_height: Option<f64>,
|
||||
}
|
||||
|
||||
/// Valid RMenu Plugin Messages
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[serde(tag = "type", rename_all = "lowercase")]
|
||||
pub enum Message {
|
||||
Entry(Entry),
|
||||
Options(Options),
|
||||
}
|
||||
|
||||
/// Retrieve EXE of Self
|
||||
|
|
105
rmenu/src/cli.rs
105
rmenu/src/cli.rs
|
@ -5,7 +5,7 @@ use std::str::FromStr;
|
|||
use std::{fmt::Display, fs::read_to_string};
|
||||
|
||||
use clap::Parser;
|
||||
use rmenu_plugin::Entry;
|
||||
use rmenu_plugin::{Entry, Message};
|
||||
use thiserror::Error;
|
||||
|
||||
use crate::config::{Config, Keybind};
|
||||
|
@ -161,6 +161,8 @@ pub enum RMenuError {
|
|||
NoSuchPlugin(String),
|
||||
#[error("Invalid Plugin Specified")]
|
||||
InvalidPlugin(String),
|
||||
#[error("Invalid Keybind Definition")]
|
||||
InvalidKeybind(String),
|
||||
#[error("Command Runtime Exception")]
|
||||
CommandError(Option<ExitStatus>),
|
||||
#[error("Invalid JSON Entry Object")]
|
||||
|
@ -168,7 +170,6 @@ pub enum RMenuError {
|
|||
}
|
||||
|
||||
pub type Result<T> = std::result::Result<T, RMenuError>;
|
||||
type MaybeEntry = Result<Entry>;
|
||||
|
||||
macro_rules! cli_replace {
|
||||
($key:expr, $repl:expr) => {
|
||||
|
@ -183,8 +184,22 @@ macro_rules! cli_replace {
|
|||
};
|
||||
}
|
||||
|
||||
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 and Update w/ Argument Overrides
|
||||
/// Load Configuration File
|
||||
pub fn get_config(&self) -> Result<Config> {
|
||||
// read configuration
|
||||
let path = self
|
||||
|
@ -193,13 +208,18 @@ impl Args {
|
|||
.map(|v| v.as_str())
|
||||
.unwrap_or(DEFAULT_CONFIG);
|
||||
let path = shellexpand::tilde(path).to_string();
|
||||
let mut config: Config = match read_to_string(path) {
|
||||
let config: Config = match read_to_string(path) {
|
||||
Ok(content) => serde_yaml::from_str(&content),
|
||||
Err(err) => {
|
||||
log::error!("Failed to Load Config: {err:?}");
|
||||
Ok(Config::default())
|
||||
}
|
||||
}?;
|
||||
Ok(config)
|
||||
}
|
||||
|
||||
/// Update Configuration w/ CLI Specified Settings
|
||||
pub fn update_config(&self, mut config: Config) -> Config {
|
||||
// override basic settings
|
||||
config.terminal = self.terminal.clone().or_else(|| config.terminal);
|
||||
config.page_size = self.page_size.unwrap_or(config.page_size);
|
||||
|
@ -231,7 +251,7 @@ impl Args {
|
|||
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);
|
||||
Ok(config)
|
||||
config
|
||||
}
|
||||
|
||||
/// Load CSS or Default
|
||||
|
@ -258,20 +278,50 @@ impl Args {
|
|||
String::new()
|
||||
}
|
||||
|
||||
/// Read Entries Contained within the Given Reader
|
||||
fn read_entries<T: Read>(&self, reader: BufReader<T>) -> impl Iterator<Item = MaybeEntry> {
|
||||
let format = self.format.clone();
|
||||
reader
|
||||
.lines()
|
||||
.filter_map(|l| l.ok())
|
||||
.map(move |l| match format {
|
||||
Format::Json => serde_json::from_str(&l).map_err(|e| RMenuError::InvalidJson(e)),
|
||||
Format::DMenu => Ok(Entry::echo(l.trim(), None)),
|
||||
})
|
||||
fn read_entries<T: Read>(
|
||||
&mut self,
|
||||
r: BufReader<T>,
|
||||
v: &mut Vec<Entry>,
|
||||
c: &mut Config,
|
||||
) -> Result<()> {
|
||||
for line in r.lines().filter_map(|l| l.ok()) {
|
||||
match &self.format {
|
||||
Format::DMenu => v.push(Entry::echo(line.trim(), None)),
|
||||
Format::Json => {
|
||||
let msg: Message = serde_json::from_str(&line)?;
|
||||
match msg {
|
||||
Message::Entry(entry) => v.push(entry),
|
||||
Message::Options(options) => {
|
||||
// base settings
|
||||
self.theme = self.theme.clone().or(options.theme);
|
||||
// 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);
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Read Entries from a Configured Input
|
||||
fn load_input(&self, input: &str) -> Result<Vec<Entry>> {
|
||||
fn load_input(&mut self, input: &str, config: &mut Config) -> Result<Vec<Entry>> {
|
||||
// retrieve input file
|
||||
let input = if input == "-" { "/dev/stdin" } else { input };
|
||||
let fpath = shellexpand::tilde(input).to_string();
|
||||
|
@ -280,24 +330,23 @@ impl Args {
|
|||
let file = File::open(fpath)?;
|
||||
let reader = BufReader::new(file);
|
||||
let mut entries = vec![];
|
||||
for entry in self.read_entries(reader) {
|
||||
entries.push(entry?);
|
||||
}
|
||||
self.read_entries(reader, &mut entries, config)?;
|
||||
Ok(entries)
|
||||
}
|
||||
|
||||
/// Read Entries from a Plugin Source
|
||||
fn load_plugins(&self, config: &mut Config) -> Result<Vec<Entry>> {
|
||||
fn load_plugins(&mut self, config: &mut Config) -> Result<Vec<Entry>> {
|
||||
let mut entries = vec![];
|
||||
for name in self.run.iter() {
|
||||
for name in self.run.clone().into_iter() {
|
||||
// retrieve plugin configuration
|
||||
log::info!("running plugin: {name:?}");
|
||||
let plugin = config
|
||||
.plugins
|
||||
.get(name)
|
||||
.get(&name)
|
||||
.cloned()
|
||||
.ok_or_else(|| RMenuError::NoSuchPlugin(name.to_owned()))?;
|
||||
// read cache when available
|
||||
match crate::cache::read_cache(name, plugin) {
|
||||
match crate::cache::read_cache(&name, &plugin) {
|
||||
Err(err) => log::error!("cache read failed: {err:?}"),
|
||||
Ok(cached) => {
|
||||
entries.extend(cached);
|
||||
|
@ -323,9 +372,7 @@ impl Args {
|
|||
.as_mut()
|
||||
.ok_or_else(|| RMenuError::CommandError(None))?;
|
||||
let reader = BufReader::new(stdout);
|
||||
for entry in self.read_entries(reader) {
|
||||
entries.push(entry?);
|
||||
}
|
||||
self.read_entries(reader, &mut entries, config)?;
|
||||
let status = command.wait()?;
|
||||
if !status.success() {
|
||||
return Err(RMenuError::CommandError(Some(status)));
|
||||
|
@ -334,7 +381,7 @@ 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, &entries) {
|
||||
Ok(_) => {}
|
||||
Err(err) => log::error!("cache write error: {err:?}"),
|
||||
}
|
||||
|
@ -343,7 +390,7 @@ impl Args {
|
|||
}
|
||||
|
||||
/// Load Entries from Enabled/Configured Entry-Sources
|
||||
pub fn get_entries(&self, config: &mut Config) -> Result<Vec<Entry>> {
|
||||
pub fn get_entries(&mut self, config: &mut Config) -> Result<Vec<Entry>> {
|
||||
// configure default source if none are given
|
||||
let mut input = self.input.clone();
|
||||
let mut entries = vec![];
|
||||
|
@ -352,7 +399,7 @@ impl Args {
|
|||
}
|
||||
// load entries
|
||||
if let Some(input) = input {
|
||||
entries.extend(self.load_input(&input)?);
|
||||
entries.extend(self.load_input(&input, config)?);
|
||||
}
|
||||
entries.extend(self.load_plugins(config)?);
|
||||
Ok(entries)
|
||||
|
|
|
@ -148,7 +148,7 @@ impl Default for WindowConfig {
|
|||
}
|
||||
|
||||
/// Cache Settings for Configured RMenu Plugins
|
||||
#[derive(Debug, PartialEq)]
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum CacheSetting {
|
||||
NoCache,
|
||||
Never,
|
||||
|
@ -190,7 +190,7 @@ impl Default for CacheSetting {
|
|||
}
|
||||
|
||||
/// RMenu Data-Source Plugin Configuration
|
||||
#[derive(Debug, PartialEq, Deserialize)]
|
||||
#[derive(Debug, Clone, PartialEq, Deserialize)]
|
||||
pub struct PluginConfig {
|
||||
pub exec: Vec<String>,
|
||||
#[serde(default)]
|
||||
|
|
|
@ -42,13 +42,14 @@ fn main() -> cli::Result<()> {
|
|||
env_logger::init();
|
||||
|
||||
// parse cli and retrieve values for app
|
||||
let cli = cli::Args::parse();
|
||||
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 theme = cli.get_theme();
|
||||
let entries = cli.get_entries(&mut config)?;
|
||||
|
||||
// update config based on entries
|
||||
// update config based on cli-settings and entries
|
||||
config = cli.update_config(config);
|
||||
config.use_icons = config.use_icons
|
||||
&& entries
|
||||
.iter()
|
||||
|
|
Loading…
Reference in a new issue