1use std::io::{Read, Write};
2
3pub mod cmds; pub mod conventions; pub mod runtime; pub mod runtime_helper; pub mod prelude; pub use clap_noun_verb::{run, CommandRouter, Result as ClapNounVerbResult};
13
14pub async fn cli_match() -> ggen_utils::error::Result<()> {
19 clap_noun_verb::run()
21 .map_err(|e| anyhow::anyhow!("CLI execution failed: {}", e))?;
22 Ok(())
23}
24
25#[derive(Debug, Clone)]
27pub struct RunResult {
28 pub code: i32,
29 pub stdout: String,
30 pub stderr: String,
31}
32
33pub async fn run_for_node(args: Vec<String>) -> ggen_utils::error::Result<RunResult> {
36 use std::sync::Arc;
37 use std::sync::Mutex;
38
39 let _argv: Vec<String> = std::iter::once("ggen".to_string()).chain(args.into_iter()).collect();
41
42 let stdout_buffer = Arc::new(Mutex::new(Vec::new()));
44 let stderr_buffer = Arc::new(Mutex::new(Vec::new()));
45
46 let stdout_clone = Arc::clone(&stdout_buffer);
47 let stderr_clone = Arc::clone(&stderr_buffer);
48
49 let result = tokio::task::spawn_blocking(move || {
51 let mut captured_stdout = Vec::new();
53 let mut captured_stderr = Vec::new();
54
55 let code = match (gag::BufferRedirect::stdout(), gag::BufferRedirect::stderr()) {
56 (Ok(mut so), Ok(mut se)) => {
57 let code_val = match cmds::run_cli() {
59 Ok(()) => 0,
60 Err(err) => {
61 let _ = writeln!(std::io::stderr(), "{}", err);
62 1
63 }
64 };
65
66 let _ = so.read_to_end(&mut captured_stdout);
67 let _ = se.read_to_end(&mut captured_stderr);
68
69 *stdout_clone.lock().unwrap() = captured_stdout;
70 *stderr_clone.lock().unwrap() = captured_stderr;
71
72 code_val
73 }
74 _ => {
75 match cmds::run_cli() {
77 Ok(()) => 0,
78 Err(err) => {
79 eprintln!("{}", err);
80 1
81 }
82 }
83 }
84 };
85
86 code
87 })
88 .await
89 .map_err(|e| anyhow::anyhow!("Failed to execute CLI: {}", e))?;
90
91 let stdout = String::from_utf8_lossy(&stdout_buffer.lock().unwrap()).to_string();
92 let stderr = String::from_utf8_lossy(&stderr_buffer.lock().unwrap()).to_string();
93
94 Ok(RunResult {
95 code: result,
96 stdout,
97 stderr,
98 })
99}