use crossterm::event::{KeyCode, KeyEvent};
use super::ctx::{Nav, Notify};
use crate::app::{App, ContainerExecRequest, ContainerState, HostState, Screen, StatusCenter};
struct ExecPromptCtx<'a> {
screen: &'a mut Screen,
container_state: &'a mut ContainerState,
hosts: &'a HostState,
status: &'a mut StatusCenter,
}
impl Nav for ExecPromptCtx<'_> {
fn screen_mut(&mut self) -> &mut Screen {
self.screen
}
}
impl Notify for ExecPromptCtx<'_> {
fn status_mut(&mut self) -> &mut StatusCenter {
self.status
}
}
pub(super) fn handle_key(app: &mut App, key: KeyEvent) {
let mut ctx = ExecPromptCtx {
screen: &mut app.screen,
container_state: &mut app.container_state,
hosts: &app.hosts_state,
status: &mut app.status_center,
};
exec_prompt_key(&mut ctx, key);
}
fn exec_prompt_key(ctx: &mut ExecPromptCtx, key: KeyEvent) {
let Screen::ContainerExecPrompt {
alias,
container_id,
container_name,
query,
} = &mut *ctx.screen
else {
return;
};
match key.code {
KeyCode::Esc => {
log::debug!("[purple] container_exec_prompt: cancelled");
ctx.set_screen(Screen::HostList);
}
KeyCode::Enter => {
let cmd = query.trim().to_string();
if cmd.is_empty() {
return;
}
if cmd.chars().any(|c| c.is_control()) {
ctx.notify_error(crate::messages::CONTAINER_EXEC_INVALID_COMMAND.to_string());
return;
}
let alias = alias.clone();
let container_id = container_id.clone();
let container_name = container_name.clone();
queue_exec_with_command(ctx, alias, container_id, container_name, cmd);
}
KeyCode::Backspace => {
query.pop();
}
KeyCode::Char(c) if query.chars().count() < 512 => {
query.push(c);
}
_ => {}
}
}
fn queue_exec_with_command(
ctx: &mut ExecPromptCtx,
alias: String,
container_id: String,
container_name: String,
command: String,
) {
let Some(entry) = ctx.container_state.cache_entry(&alias) else {
log::debug!(
"[purple] container_exec_prompt: submit aborted, no cache for alias={}",
alias
);
ctx.set_screen(Screen::HostList);
return;
};
let runtime = entry.runtime;
let askpass = ctx
.hosts
.list()
.iter()
.find(|h| h.alias == alias)
.and_then(|h| h.askpass.clone());
log::info!(
"[purple] container_exec_prompt: queue exec alias={} id={} cmd_len={}",
alias,
container_id,
command.len()
);
ctx.container_state.queue_exec(ContainerExecRequest {
alias,
askpass,
runtime,
container_id,
container_name,
command: Some(command),
});
ctx.set_screen(Screen::HostList);
}