use std::io::{self, stdout, Write};
use std::process::Command;
use anyhow::Result;
use ratatui::crossterm::{
execute,
terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen},
};
use ratatui::DefaultTerminal;
use super::discover::{format_script_label, PackageManager, ScriptEntry};
pub struct RunOutcome {
pub label: String,
pub exit_code: i32,
}
fn suspend() -> io::Result<()> {
disable_raw_mode()?;
execute!(stdout(), LeaveAlternateScreen)?;
Ok(())
}
fn resume(terminal: &mut DefaultTerminal) -> io::Result<()> {
enable_raw_mode()?;
execute!(stdout(), EnterAlternateScreen)?;
terminal.clear()?;
Ok(())
}
pub fn run_scripts(
terminal: &mut DefaultTerminal,
entries: &[ScriptEntry],
pm: PackageManager,
) -> Result<Vec<RunOutcome>> {
if entries.is_empty() {
return Ok(Vec::new());
}
suspend()?;
let outcomes = run_all(entries, pm);
resume(terminal)?;
Ok(outcomes)
}
fn run_all(entries: &[ScriptEntry], pm: PackageManager) -> Vec<RunOutcome> {
let mut outcomes = Vec::with_capacity(entries.len());
for (index, entry) in entries.iter().enumerate() {
let label = format_script_label(entry, 28);
print_banner(index, &label, pm, &entry.script);
let exit_code = Command::new(pm.bin())
.args(["run", &entry.script])
.current_dir(&entry.package_path)
.status()
.map(|status| status.code().unwrap_or(1))
.unwrap_or(1);
outcomes.push(RunOutcome { label, exit_code });
}
outcomes
}
fn print_banner(index: usize, label: &str, pm: PackageManager, script: &str) {
let mut out = stdout();
if index > 0 {
let _ = writeln!(out);
}
let _ = writeln!(out, "\n▶ {label} ({} run {script})\n", pm.label());
let _ = out.flush();
}