use crossterm::event::{KeyCode, KeyEvent, KeyModifiers};
use super::state::CoordinatorState;
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum SlashCommand {
Help,
New,
Sessions,
Attach,
Stop,
Resume,
Kill,
Send,
Answer,
Activity,
Get,
Health,
Unknown(String),
}
impl SlashCommand {
pub fn is_mutating(&self) -> bool {
matches!(
self,
SlashCommand::New | SlashCommand::Kill | SlashCommand::Stop | SlashCommand::Resume
)
}
}
pub fn parse_slash(input: &str) -> Option<SlashCommand> {
let rest = input.strip_prefix('/')?;
let word = rest.split_whitespace().next()?.to_lowercase();
let cmd = match word.as_str() {
"help" => SlashCommand::Help,
"new" | "spawn" => SlashCommand::New,
"sessions" | "list" | "managed-list" => SlashCommand::Sessions,
"attach" | "managed-attach" => SlashCommand::Attach,
"stop" | "managed-stop" => SlashCommand::Stop,
"resume" | "managed-resume" => SlashCommand::Resume,
"kill" | "decommission" | "managed-decommission" => SlashCommand::Kill,
"send" | "managed-send" => SlashCommand::Send,
"answer" | "approve" | "managed-answer" => SlashCommand::Answer,
"activity" | "managed-activity" => SlashCommand::Activity,
"get" | "status" | "managed-get" => SlashCommand::Get,
"health" | "healthcheck" | "ping" => SlashCommand::Health,
other => SlashCommand::Unknown(other.to_string()),
};
Some(cmd)
}
pub fn is_quit(key: &KeyEvent, input_empty: bool) -> bool {
let ctrl_c = key.code == KeyCode::Char('c') && key.modifiers.contains(KeyModifiers::CONTROL);
let bare_q = key.code == KeyCode::Char('q') && input_empty;
ctrl_c || bare_q
}
pub fn handle_key(state: &mut CoordinatorState, key: KeyEvent) -> Option<String> {
let input_empty = state.input.is_empty();
if is_quit(&key, input_empty) {
state.should_exit = true;
return None;
}
match key.code {
KeyCode::PageUp => {
state.page_up();
None
}
KeyCode::PageDown => {
state.page_down();
None
}
KeyCode::Up | KeyCode::Char('k') if input_empty => {
state.select_up();
None
}
KeyCode::Down | KeyCode::Char('j') if input_empty => {
state.select_down();
None
}
KeyCode::Up => {
state.history_prev();
None
}
KeyCode::Down => {
state.history_next();
None
}
KeyCode::Backspace => {
state.backspace();
None
}
KeyCode::Esc => {
state.clear_input();
None
}
KeyCode::Enter => {
let submitted = state.submit_input();
if let Some(line) = submitted.as_deref()
&& parse_slash(line).is_some_and(|cmd| cmd.is_mutating())
{
state.request_repoll();
}
submitted
}
KeyCode::Char(c) => {
state.push_char(c);
None
}
_ => None,
}
}