actr_cli/commands/
run.rs

1//! Run command implementation
2
3use crate::commands::Command;
4use crate::error::{ActrCliError, Result};
5use crate::utils::{execute_command_streaming, is_actr_project, warn_if_not_actr_project};
6use actr_config::ConfigParser;
7use async_trait::async_trait;
8use clap::Args;
9use tracing::info;
10
11#[derive(Args)]
12pub struct RunCommand {
13    /// Script name to run (defaults to "run")
14    pub script_name: Option<String>,
15}
16
17#[async_trait]
18impl Command for RunCommand {
19    async fn execute(&self) -> Result<()> {
20        info!("🚀 Running Actor-RTC project");
21
22        // Check that we're in an Actor-RTC project
23        warn_if_not_actr_project();
24
25        let _project_root = std::env::current_dir()?;
26
27        // Load configuration if available
28        let config = if is_actr_project() {
29            Some(ConfigParser::from_file("Actr.toml")?)
30        } else {
31            None
32        };
33
34        // Get script command from configuration
35        let script_name = self.script_name.as_deref().unwrap_or("run");
36        let script_command = if let Some(ref config) = config {
37            config.get_script(script_name).map(|s| s.to_string())
38        } else {
39            None
40        };
41
42        // Use script command or fall back to default
43        let command = script_command.unwrap_or_else(|| "cargo run".to_string());
44
45        info!("📜 Executing script '{}': {}", script_name, command);
46
47        // Execute the script command
48        self.run_script_command(&command).await?;
49
50        Ok(())
51    }
52}
53
54impl RunCommand {
55    async fn run_script_command(&self, command: &str) -> Result<()> {
56        // Parse command into program and args
57        let parts: Vec<&str> = command.split_whitespace().collect();
58        if parts.is_empty() {
59            return Err(ActrCliError::command_error("Empty command".to_string()));
60        }
61
62        let program = parts[0];
63        let args = parts[1..].to_vec();
64
65        info!("▶️  Executing: {} {}", program, args.join(" "));
66
67        // Execute the command
68        execute_command_streaming(program, &args, None).await
69    }
70}
71
72#[cfg(test)]
73mod tests {
74    use super::*;
75
76    #[test]
77    fn test_script_name_default() {
78        let cmd = RunCommand { script_name: None };
79
80        let script_name = cmd.script_name.as_deref().unwrap_or("run");
81        assert_eq!(script_name, "run");
82    }
83
84    #[test]
85    fn test_script_name_custom() {
86        let cmd = RunCommand {
87            script_name: Some("test".to_string()),
88        };
89
90        let script_name = cmd.script_name.as_deref().unwrap_or("run");
91        assert_eq!(script_name, "test");
92    }
93}