From 4914e888e72bc97f6fcf2a1d5c8d342de7e630d7 Mon Sep 17 00:00:00 2001 From: Jeevitha Kannan K S Date: Tue, 15 Oct 2024 22:08:46 +0530 Subject: [PATCH] feat: Add automation based on config file --- core/src/config.rs | 28 ++++++++++++++++++++++++++++ core/src/lib.rs | 15 +++++++++++++++ tui/src/main.rs | 8 +++++++- tui/src/state.rs | 29 +++++++++++++++++++++++++++-- 4 files changed, 77 insertions(+), 3 deletions(-) create mode 100644 core/src/config.rs diff --git a/core/src/config.rs b/core/src/config.rs new file mode 100644 index 000000000..d4f5e5c57 --- /dev/null +++ b/core/src/config.rs @@ -0,0 +1,28 @@ +use serde::Deserialize; +use std::path::Path; +use std::process; + +#[derive(Deserialize)] +pub struct Config { + pub auto_execute: Vec, +} + +impl Config { + pub fn from_file(path: &Path) -> Self { + let content = match std::fs::read_to_string(path) { + Ok(content) => content, + Err(e) => { + eprintln!("Failed to read config file {}: {}", path.display(), e); + process::exit(1); + } + }; + + match toml::from_str(&content) { + Ok(config) => config, + Err(e) => { + eprintln!("Failed to parse config file: {}", e); + process::exit(1); + } + } + } +} diff --git a/core/src/lib.rs b/core/src/lib.rs index b7cd631e7..b5488135b 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -1,3 +1,4 @@ +mod config; mod inner; use std::rc::Rc; @@ -5,6 +6,7 @@ use std::rc::Rc; use ego_tree::Tree; use std::path::PathBuf; +pub use config::Config; pub use inner::get_tabs; #[derive(Clone, Hash, Eq, PartialEq)] @@ -33,3 +35,16 @@ pub struct ListNode { pub command: Command, pub task_list: String, } + +impl Tab { + pub fn find_command(&self, name: &str) -> Option> { + self.tree.root().descendants().find_map(|node| { + let value = node.value(); + if value.name == name && !node.has_children() { + Some(value.clone()) + } else { + None + } + }) + } +} diff --git a/tui/src/main.rs b/tui/src/main.rs index 801e3b1d2..ff8a1d7af 100644 --- a/tui/src/main.rs +++ b/tui/src/main.rs @@ -9,6 +9,7 @@ mod theme; use std::{ io::{self, stdout}, + path::PathBuf, time::Duration, }; @@ -26,6 +27,11 @@ use state::AppState; // Linux utility toolbox #[derive(Debug, Parser)] struct Args { + #[arg( + long, + help = "Path to the configuration file", + )] + config: Option, #[arg(short, long, value_enum)] #[arg(default_value_t = Theme::Default)] #[arg(help = "Set the theme to use in the application")] @@ -38,7 +44,7 @@ struct Args { fn main() -> io::Result<()> { let args = Args::parse(); - let mut state = AppState::new(args.theme, args.override_validation); + let mut state = AppState::new(args.theme, args.override_validation, args.config); stdout().execute(EnterAlternateScreen)?; enable_raw_mode()?; diff --git a/tui/src/state.rs b/tui/src/state.rs index 9ed61771d..380661054 100644 --- a/tui/src/state.rs +++ b/tui/src/state.rs @@ -9,7 +9,7 @@ use crate::{ }; use crossterm::event::{KeyCode, KeyEvent, KeyEventKind, KeyModifiers}; use ego_tree::NodeId; -use linutil_core::{ListNode, Tab}; +use linutil_core::{Config, ListNode, Tab}; #[cfg(feature = "tips")] use rand::Rng; use ratatui::{ @@ -19,6 +19,7 @@ use ratatui::{ widgets::{Block, Borders, List, ListState, Paragraph}, Frame, }; +use std::path::PathBuf; use std::rc::Rc; use temp_dir::TempDir; @@ -79,10 +80,12 @@ pub struct ListEntry { } impl AppState { - pub fn new(theme: Theme, override_validation: bool) -> Self { + pub fn new(theme: Theme, override_validation: bool, config_path: Option) -> Self { let (temp_dir, tabs) = linutil_core::get_tabs(!override_validation); let root_id = tabs[0].tree.root().id(); + let auto_execute_commands = config_path.map(|path| Config::from_file(&path).auto_execute); + let mut state = Self { _temp_dir: temp_dir, theme, @@ -100,9 +103,31 @@ impl AppState { }; state.update_items(); + if let Some(auto_execute_commands) = auto_execute_commands { + state.handle_initial_auto_execute(&auto_execute_commands); + } + state } + fn handle_initial_auto_execute(&mut self, auto_execute_commands: &[String]) { + self.selected_commands = auto_execute_commands + .iter() + .filter_map(|name| self.tabs.iter().find_map(|tab| tab.find_command(name))) + .collect(); + + if !self.selected_commands.is_empty() { + let cmd_names: Vec<_> = self + .selected_commands + .iter() + .map(|node| node.name.as_str()) + .collect(); + + let prompt = ConfirmPrompt::new(&cmd_names); + self.focus = Focus::ConfirmationPrompt(Float::new(Box::new(prompt), 40, 40)); + } + } + fn get_list_item_shortcut(&self) -> Box<[Shortcut]> { if self.selected_item_is_dir() { Box::new([Shortcut::new("Go to selected dir", ["l", "Right", "Enter"])])