From a732a5f4c180f6d594ad37aa0544c52a46e5db00 Mon Sep 17 00:00:00 2001 From: iff Date: Wed, 11 Jun 2025 13:59:59 +0200 Subject: [PATCH] feat: shell eval method --- config.md | 10 +++++++--- core/src/config.rs | 9 +++++++++ core/src/shell.rs | 13 +++++++++++++ core/src/suggestions.rs | 28 +++++++++++++++++++++++++++- 4 files changed, 56 insertions(+), 4 deletions(-) diff --git a/config.md b/config.md index bebebae..2dbbbad 100644 --- a/config.md +++ b/config.md @@ -11,14 +11,18 @@ All available options are listed in the following example file: ```toml # maximum time in milliseconds for getting previous output timeout = 3000 -# your preferred command for privileges -sudo = "run0" + +# how suggestions are evaluated after being confirmed +# options can be: +# - Internal: commands are evaluated inside `pay-respects` +# - Shell: current working shell is responsible for execution +eval_method = "Internal" [package_manager] # preferred package manager package_manager = "pacman" -# preferred installation method, can be limited with the package manager +# preferred installation method, can be limited by the package manager # available options are: # - System # - Shell (nix and guix only) diff --git a/core/src/config.rs b/core/src/config.rs index ed1ec8f..f9251e2 100644 --- a/core/src/config.rs +++ b/core/src/config.rs @@ -7,6 +7,8 @@ pub struct Config { #[serde(default)] pub timeout: Timeout, #[serde(default)] + pub eval_method: EvalMethod, + #[serde(default)] pub package_manager: PackageManagerConfig, } @@ -36,6 +38,13 @@ pub enum InstallMethod { Shell, } +#[derive(Deserialize, Default, PartialEq)] +pub enum EvalMethod { + #[default] + Internal, + Shell, +} + pub fn load_config() -> Config { let path = config_path(); let exists = std::path::Path::new(&path).exists(); diff --git a/core/src/shell.rs b/core/src/shell.rs index bc8ee90..b39a3b5 100644 --- a/core/src/shell.rs +++ b/core/src/shell.rs @@ -408,6 +408,19 @@ pub fn shell_syntax(shell: &str, command: &str) -> String { } } +pub fn add_privilege(shell: &str, privilege: &str, command: &str) -> String { + if command.contains("&&") || command.contains("||") || command.contains('>') { + format!( + "{} {} -c \"{}\"", + privilege, + shell, + command.replace("\"", "\\\"") + ) + } else { + format!("{} {}", privilege, command) + } +} + pub fn shell_evaluated_commands(shell: &str, command: &str, success: bool) { let lines = command .lines() diff --git a/core/src/suggestions.rs b/core/src/suggestions.rs index 2726d85..1aa5d33 100644 --- a/core/src/suggestions.rs +++ b/core/src/suggestions.rs @@ -7,9 +7,12 @@ use colored::Colorize; use inquire::*; use ui::Color; +use crate::config; use crate::data::Data; use crate::rules::match_pattern; -use crate::shell::{add_candidates_no_dup, module_output, shell_evaluated_commands, shell_syntax}; +use crate::shell::{ + add_candidates_no_dup, add_privilege, module_output, shell_evaluated_commands, shell_syntax, +}; use crate::style::highlight_difference; pub fn suggest_candidates(data: &mut Data) { @@ -143,6 +146,12 @@ pub fn confirm_suggestion(data: &Data) -> Result<(), String> { #[cfg(debug_assertions)] eprintln!("running command: {command}"); + let eval_method = &data.config.eval_method; + if eval_method == &config::EvalMethod::Shell { + shell_suggestion(data, command); + return Ok(()); + }; + let now = Instant::now(); let process = run_suggestion(data, command); @@ -185,6 +194,23 @@ pub fn run_suggestion(data: &Data, command: &str) -> std::process::ExitStatus { } } +pub fn shell_suggestion(data: &Data, command: &str) { + let shell = &data.shell; + let privilege = &data.privilege; + let command = if let Some(env) = &data.env { + format!("{env} {command}") + } else { + command.to_string() + }; + + let command = if let Some(privilege) = privilege { + add_privilege(shell, privilege, &command) + } else { + command + }; + println!("{}", command); +} + fn suggestion_err(data: &Data, command: &str) -> Result<(), String> { let shell = &data.shell; let privilege = &data.privilege;