diff --git a/Cargo.lock b/Cargo.lock index 595f8f0a..4ed4bf7c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -379,26 +379,12 @@ dependencies = [ "which", ] -[[package]] -name = "linutil_core" -version = "24.10.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2990ea580e635f6700ae19bd0f5fa60c7037799908da476b0c233b9e514c1481" -dependencies = [ - "ego-tree", - "include_dir", - "serde", - "temp-dir", - "toml", - "which", -] - [[package]] name = "linutil_tui" version = "24.10.31" dependencies = [ "clap", - "linutil_core 24.10.31 (registry+https://github.com/rust-lang/crates.io-index)", + "linutil_core", "nix 0.29.0", "oneshot", "portable-pty", @@ -1280,7 +1266,7 @@ checksum = "d135d17ab770252ad95e9a872d365cf3090e3be864a34ab46f48555993efc904" name = "xtask" version = "24.10.31" dependencies = [ - "linutil_core 24.10.31", + "linutil_core", ] [[package]] diff --git a/config.toml b/config.toml new file mode 100644 index 00000000..67b67a79 --- /dev/null +++ b/config.toml @@ -0,0 +1 @@ +skip_confirmation = true diff --git a/core/src/config.rs b/core/src/config.rs index cf040758..a540d5c8 100644 --- a/core/src/config.rs +++ b/core/src/config.rs @@ -1,14 +1,29 @@ +use crate::{ListNode, TabList}; use serde::Deserialize; -use std::{path::Path, process}; +use std::{fs, path::Path, process, rc::Rc}; +// Struct that defines what values can be used in the toml file #[derive(Deserialize)] +#[serde(deny_unknown_fields)] pub struct Config { - pub auto_execute: Vec, + #[serde(default)] + auto_execute: Option>, + #[serde(default)] + skip_confirmation: Option, + #[serde(default)] + size_bypass: Option, +} + +// Struct that holds the parsed values from the toml so that it can be applied in the AppState +pub struct ConfigValues { + pub auto_execute_commands: Vec>, + pub skip_confirmation: bool, + pub size_bypass: bool, } impl Config { - pub fn from_file(path: &Path) -> Self { - let content = match std::fs::read_to_string(path) { + pub fn new(path: &Path, tabs: &TabList) -> ConfigValues { + let content = match fs::read_to_string(path) { Ok(content) => content, Err(e) => { eprintln!("Failed to read config file {}: {}", path.display(), e); @@ -16,12 +31,29 @@ impl Config { } }; - match toml::from_str(&content) { + let config: Config = match toml::from_str(&content) { Ok(config) => config, Err(e) => { eprintln!("Failed to parse config file: {}", e); process::exit(1); } + }; + + ConfigValues { + auto_execute_commands: config.auto_execute_commands(tabs), + skip_confirmation: config.skip_confirmation.unwrap_or(false), + size_bypass: config.size_bypass.unwrap_or(false), } } + + fn auto_execute_commands(&self, tabs: &TabList) -> Vec> { + self.auto_execute + .as_ref() + .map_or_else(Vec::new, |commands| { + commands + .iter() + .filter_map(|name| tabs.iter().find_map(|tab| tab.find_command_by_name(name))) + .collect() + }) + } } diff --git a/core/src/lib.rs b/core/src/lib.rs index 53fe988b..852a3ab6 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -7,7 +7,7 @@ pub use ego_tree; use ego_tree::Tree; use std::path::PathBuf; -pub use config::Config; +pub use config::{Config, ConfigValues}; pub use inner::{get_tabs, TabList}; #[derive(Clone, Hash, Eq, PartialEq)] @@ -36,3 +36,12 @@ pub struct ListNode { pub task_list: String, pub multi_select: bool, } + +impl Tab { + fn find_command_by_name(&self, name: &str) -> Option> { + self.tree.root().descendants().find_map(|node| { + let node_value = node.value(); + (node_value.name == name && !node.has_children()).then_some(node_value.clone()) + }) + } +} diff --git a/tui/Cargo.toml b/tui/Cargo.toml index f33162de..56344333 100644 --- a/tui/Cargo.toml +++ b/tui/Cargo.toml @@ -22,7 +22,7 @@ tui-term = "0.2.0" time = { version = "0.3.36", features = ["formatting", "local-offset", "macros"], default-features = false } unicode-width = { version = "0.2.0", default-features = false } rand = { version = "0.8.5", optional = true } -linutil_core = { version = "24.10.31" } +linutil_core = { version = "24.10.31", path = "../core" } tree-sitter-highlight = "0.24.4" tree-sitter-bash = "0.23.3" nix = { version = "0.29.0", features = [ "user" ] } diff --git a/tui/src/state.rs b/tui/src/state.rs index 6ce07bfd..993dfa13 100644 --- a/tui/src/state.rs +++ b/tui/src/state.rs @@ -9,7 +9,7 @@ use crate::{ theme::Theme, Args, }; -use linutil_core::{ego_tree::NodeId, Command, Config, ListNode, TabList}; +use linutil_core::{ego_tree::NodeId, Command, Config, ConfigValues, ListNode, TabList}; use ratatui::{ crossterm::event::{KeyCode, KeyEvent, KeyEventKind, KeyModifiers, MouseEvent, MouseEventKind}, layout::Flex, @@ -98,10 +98,6 @@ impl AppState { let tabs = linutil_core::get_tabs(!args.override_validation); let root_id = tabs[0].tree.root().id(); - let auto_execute_commands = args - .config - .map(|path| Config::from_file(&path).auto_execute); - let longest_tab_display_len = tabs .iter() .map(|tab| tab.name.len() + args.theme.tab_icon().len()) @@ -133,28 +129,26 @@ impl AppState { } state.update_items(); - if let Some(auto_execute_commands) = auto_execute_commands { - state.handle_initial_auto_execute(&auto_execute_commands); + + if let Some(config_path) = args.config { + let config = Config::new(&config_path, &state.tabs); + state.apply_config(config); } state } - fn find_command_by_name(&self, name: &str) -> Option> { - self.tabs.iter().find_map(|tab| { - tab.tree.root().descendants().find_map(|node| { - let node_value = node.value(); - (node_value.name == name && !node.has_children()).then_some(node_value.clone()) - }) - }) + fn apply_config(&mut self, config_values: ConfigValues) { + self.skip_confirmation = self.skip_confirmation || config_values.skip_confirmation; + self.size_bypass = self.size_bypass || config_values.size_bypass; + + if !config_values.auto_execute_commands.is_empty() { + self.selected_commands = config_values.auto_execute_commands; + self.handle_initial_auto_execute(); + } } - fn handle_initial_auto_execute(&mut self, auto_execute_commands: &[String]) { - self.selected_commands = auto_execute_commands - .iter() - .filter_map(|name| self.find_command_by_name(name)) - .collect(); - + fn handle_initial_auto_execute(&mut self) { if !self.selected_commands.is_empty() { self.spawn_confirmprompt(); }