use crate::error::Result;
use crossterm::{
event::DisableMouseCapture,
execute,
terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen},
};
use ratatui::DefaultTerminal;
use std::path::Path;
use tracing::info;
use super::events::LogEntry;
use super::state::AppState;
use super::utils::clear_screen;
pub fn restore_terminal() {
let _ = execute!(std::io::stdout(), DisableMouseCapture);
let _ = clear_screen();
ratatui::restore();
}
pub async fn execute_worktree_command(
terminal: &mut DefaultTerminal,
command: &str,
worktree_path: &Path,
ai_runner: &crate::ai_command_runner::AiCommandRunner,
app: &mut AppState,
) -> Result<()> {
let command_clone = command.to_string();
let worktree_path_clone = worktree_path.to_path_buf();
let ai_runner_clone = ai_runner.clone();
let status_result = suspend_terminal_and_execute(terminal, || async move {
info!(
module = module_path!(),
"Running worktree command via AiCommandRunner: sh -c {}", command_clone
);
let exec_result = ai_runner_clone
.execute_streaming_with_retry(&command_clone, Some(&worktree_path_clone), None, None)
.await;
match exec_result {
Ok((mut child, mut rx)) => {
use crate::ai_command_runner::OutputLine;
while let Some(line) = rx.recv().await {
match line {
OutputLine::Stdout(s) => {
println!("{}", s);
}
OutputLine::Stderr(s) => {
eprintln!("{}", s);
}
}
}
child
.wait()
.await
.map_err(crate::error::OrchestratorError::Io)
}
Err(e) => {
eprintln!("Failed to execute worktree command: {}", e);
Err(e)
}
}
})
.await?;
match status_result {
exit_status if exit_status.success() => {
app.add_log(LogEntry::success("Worktree command completed successfully"));
}
exit_status => {
app.add_log(LogEntry::error(format!(
"Worktree command failed with exit code: {:?}",
exit_status.code()
)));
}
}
Ok(())
}
async fn suspend_terminal_and_execute<F, Fut, T>(terminal: &mut DefaultTerminal, f: F) -> Result<T>
where
F: FnOnce() -> Fut,
Fut: std::future::Future<Output = Result<T>>,
{
disable_raw_mode()?;
execute!(std::io::stdout(), LeaveAlternateScreen, DisableMouseCapture)?;
let result = f().await;
enable_raw_mode()?;
execute!(
std::io::stdout(),
EnterAlternateScreen,
crossterm::event::EnableMouseCapture
)?;
terminal.clear()?;
result
}
pub fn suspend_terminal_and_execute_sync<F, T>(terminal: &mut DefaultTerminal, f: F) -> Result<T>
where
F: FnOnce() -> Result<T>,
{
disable_raw_mode()?;
execute!(std::io::stdout(), LeaveAlternateScreen, DisableMouseCapture)?;
let result = f();
enable_raw_mode()?;
execute!(
std::io::stdout(),
EnterAlternateScreen,
crossterm::event::EnableMouseCapture
)?;
terminal.clear()?;
result
}