cargo_e/
e_runner.rs

1use crate::prelude::*;
2// #[cfg(not(feature = "equivalent"))]
3// use ctrlc;
4use crate::Example;
5
6/// In "equivalent" mode, behave exactly like "cargo run --example <name>"
7#[cfg(feature = "equivalent")]
8pub fn run_example(example: &Example, extra_args: &[String]) -> Result<(), Box<dyn Error>> {
9    // In "equivalent" mode, behave exactly like "cargo run --example <name>"
10    let mut cmd = Command::new("cargo");
11    cmd.args(["run", "--example", &example.name]);
12    if !extra_args.is_empty() {
13        cmd.arg("--").args(extra_args);
14    }
15    // Inherit the standard input (as well as stdout/stderr) so that input is passed through.
16    use std::process::Stdio;
17    cmd.stdin(Stdio::inherit())
18        .stdout(Stdio::inherit())
19        .stderr(Stdio::inherit());
20
21    let status = cmd.status()?;
22    std::process::exit(status.code().unwrap_or(1));
23}
24
25/// Runs the given example (or binary) target.
26#[cfg(not(feature = "equivalent"))]
27pub fn run_example(example: &Example, extra_args: &[String]) -> Result<(), Box<dyn Error>> {
28    let mut cmd = Command::new("cargo");
29
30    if example.extended {
31        println!(
32            "Running extended example in folder: examples/{}",
33            example.name
34        );
35        cmd.arg("run")
36            .current_dir(format!("examples/{}", example.name));
37    } else {
38        println!("Running: cargo run --release --example {}", example.name);
39        cmd.args(["run", "--release", "--example", &example.name]);
40    }
41
42    if !extra_args.is_empty() {
43        cmd.arg("--").args(extra_args);
44    }
45
46    let child = cmd.spawn()?;
47    use std::sync::{Arc, Mutex};
48    let child_arc = Arc::new(Mutex::new(child));
49    let child_for_handler = Arc::clone(&child_arc);
50
51    ctrlc::set_handler(move || {
52        eprintln!("Ctrl+C pressed, terminating process...");
53        let mut child = child_for_handler.lock().unwrap();
54        let _ = child.kill();
55    })?;
56
57    let status = child_arc.lock().unwrap().wait()?;
58    println!("Process exited with status: {:?}", status.code());
59    Ok(())
60}
61
62/// Helper function to spawn a cargo process.
63/// On Windows, this sets the CREATE_NEW_PROCESS_GROUP flag.
64pub fn spawn_cargo_process(args: &[&str]) -> Result<Child, Box<dyn Error>> {
65    #[cfg(windows)]
66    {
67        use std::os::windows::process::CommandExt;
68        const CREATE_NEW_PROCESS_GROUP: u32 = 0x00000200;
69        let child = Command::new("cargo")
70            .args(args)
71            .creation_flags(CREATE_NEW_PROCESS_GROUP)
72            .spawn()?;
73        Ok(child)
74    }
75    #[cfg(not(windows))]
76    {
77        let child = Command::new("cargo").args(args).spawn()?;
78        Ok(child)
79    }
80}