1use super::{config, executor};
2use crate::utils;
3use anyhow::{Result, anyhow};
4use colored::*;
5use dialoguer::{Select, theme::ColorfulTheme};
6
7pub fn run(cmd_alias: Option<&str>, args: &[String], config: &config::ProjectConfig) -> Result<()> {
8 if config.commands.is_empty() {
9 return Err(anyhow!("No commands defined in zoi.yaml"));
10 }
11
12 let command_to_run = match cmd_alias {
13 Some(alias) => config
14 .commands
15 .iter()
16 .find(|c| c.cmd == alias)
17 .ok_or_else(|| anyhow!("Command alias '{}' not found in zoi.yaml", alias))?
18 .clone(),
19 None => {
20 if !args.is_empty() {
21 return Err(anyhow!("Cannot pass arguments when in interactive mode."));
22 }
23 let selections: Vec<&str> = config.commands.iter().map(|c| c.cmd.as_str()).collect();
24 let selection = Select::with_theme(&ColorfulTheme::default())
25 .with_prompt("Choose a command to run")
26 .items(&selections)
27 .default(0)
28 .interact_opt()?
29 .ok_or(anyhow!("No command chosen."))?;
30
31 config.commands[selection].clone()
32 }
33 };
34
35 let platform = utils::get_platform()?;
36
37 let run_cmd = match &command_to_run.run {
38 config::PlatformOrString::String(s) => s.clone(),
39 config::PlatformOrString::Platform(p) => p
40 .get(&platform)
41 .or_else(|| p.get("default"))
42 .cloned()
43 .ok_or_else(|| {
44 anyhow!(
45 "No command found for platform '{}' and no default specified",
46 platform
47 )
48 })?,
49 };
50
51 let env_vars = match &command_to_run.env {
52 config::PlatformOrEnvMap::EnvMap(m) => m.clone(),
53 config::PlatformOrEnvMap::Platform(p) => p
54 .get(&platform)
55 .or_else(|| p.get("default"))
56 .cloned()
57 .unwrap_or_default(),
58 };
59
60 println!("--- Running command: {} ---", command_to_run.cmd.bold());
61 let mut full_command = run_cmd;
62 if !args.is_empty() {
63 full_command.push(' ');
64 full_command.push_str(&args.join(" "));
65 }
66 executor::run_shell_command(&full_command, &env_vars)
67}