use super::*;
pub(super) fn classify_keybinding_action(
action: KeyCommand,
state: &MissionControlState,
prompt_viewport: PromptViewport,
transcript_viewport: TranscriptViewport,
activity_tree_viewport: ActivityTreeViewport,
detail_viewport: DetailViewport,
) -> InputCommand {
let display = |command: DisplayCommand, refresh_autocomplete: bool| {
if refresh_autocomplete {
DisplayCommand::batch([command, DisplayCommand::RefreshAutocomplete])
} else {
command
}
};
let has_activity = state.visible_node_count() != 0;
match action {
KeyCommand::ToggleHeaderModalsPinned => {
InputCommand::display(DisplayCommand::ToggleHeaderModalsPinned)
}
KeyCommand::OpenActivityDetail => InputCommand::display(DisplayCommand::OpenActivityDetail),
KeyCommand::ToggleSummaryModal => InputCommand::display(DisplayCommand::ToggleSummaryModal),
KeyCommand::ToggleActivityTreeModal => {
InputCommand::display(DisplayCommand::ToggleActivityTreeModal)
}
KeyCommand::ToggleSessionFilesModal => {
InputCommand::display(DisplayCommand::ToggleSessionFilesModal)
}
KeyCommand::ToggleSummary
| KeyCommand::ScrollSummaryUp
| KeyCommand::ScrollSummaryDown
| KeyCommand::PageSummaryUp
| KeyCommand::PageSummaryDown => InputCommand::None,
KeyCommand::SubmitPrompt => {
let prompt = state.prompt_plain_text();
let action = if is_quit_prompt(&prompt) {
InputAction::Exit
} else {
InputAction::Submit(prompt)
};
InputCommand::action_with_display(
action,
display(DisplayCommand::Prompt(PromptCommand::TakeForSubmit), true),
)
}
KeyCommand::InsertPromptNewline => {
InputCommand::display(DisplayCommand::Prompt(PromptCommand::Edit {
operation: PromptEditCommand::InsertNewline,
viewport: prompt_viewport,
refresh_autocomplete: true,
}))
}
KeyCommand::Exit => InputCommand::action(InputAction::Exit),
KeyCommand::ClearInputOrExit => {
if state.prompt_is_empty() {
InputCommand::action(InputAction::Exit)
} else {
InputCommand::display(display(
DisplayCommand::Prompt(PromptCommand::Edit {
operation: PromptEditCommand::Clear,
viewport: prompt_viewport,
refresh_autocomplete: true,
}),
true,
))
}
}
KeyCommand::FocusPrompt => InputCommand::display(display(
DisplayCommand::Focus(FocusCommand::Prompt { close_help: true }),
true,
)),
KeyCommand::FocusActivityTree => InputCommand::display(display(
DisplayCommand::Focus(FocusCommand::ActivityTree),
true,
)),
KeyCommand::CyclePrimaryAgent => {
let before = state.selected_primary_agent_id().map(str::to_owned);
let after = next_primary_agent_id(state);
let command = DisplayCommand::batch([
DisplayCommand::SetPrimaryAgent(after.clone()),
DisplayCommand::RefreshAutocomplete,
]);
if after != before {
InputCommand::action_with_display(
InputAction::PrimaryAgentSelectionChanged(after),
command,
)
} else {
InputCommand::display(command)
}
}
KeyCommand::CycleThinkingLevel => {
if let Some(next) = state.next_thinking_level() {
InputCommand::action_with_display(
InputAction::ThinkingLevelSelectionChanged(next),
DisplayCommand::batch([
DisplayCommand::SetThinkingLevel(next),
DisplayCommand::RefreshAutocomplete,
]),
)
} else {
InputCommand::display(display(
DisplayCommand::SetStatus(
"thinking level is not configurable for this model".to_string(),
),
true,
))
}
}
KeyCommand::ToggleHelp => InputCommand::display(display(
DisplayCommand::Focus(FocusCommand::ToggleHelp),
true,
)),
KeyCommand::OpenModel => InputCommand::action(InputAction::OpenModel),
KeyCommand::MoveSelectionUp if has_activity => InputCommand::display(display(
DisplayCommand::Activity(ActivityCommand::MoveUp {
visible_rows: activity_tree_viewport.visible_rows,
}),
true,
)),
KeyCommand::MoveSelectionDown if has_activity => InputCommand::display(display(
DisplayCommand::Activity(ActivityCommand::MoveDown {
visible_rows: activity_tree_viewport.visible_rows,
}),
true,
)),
KeyCommand::CollapseSelected if has_activity => InputCommand::display(display(
DisplayCommand::Activity(ActivityCommand::CollapseSelected {
visible_rows: activity_tree_viewport.visible_rows,
}),
true,
)),
KeyCommand::ExpandSelected if has_activity => InputCommand::display(display(
DisplayCommand::Activity(ActivityCommand::ExpandSelected {
visible_rows: activity_tree_viewport.visible_rows,
}),
true,
)),
KeyCommand::ExpandAll if has_activity => InputCommand::display(display(
DisplayCommand::Activity(ActivityCommand::ExpandAll {
visible_rows: activity_tree_viewport.visible_rows,
}),
true,
)),
KeyCommand::CollapseAll if has_activity => InputCommand::display(display(
DisplayCommand::Activity(ActivityCommand::CollapseAll {
visible_rows: activity_tree_viewport.visible_rows,
}),
true,
)),
KeyCommand::SelectFailed if has_activity => InputCommand::display(display(
DisplayCommand::Activity(ActivityCommand::SelectStatus {
status: crate::output::ActivityStatus::Failed,
visible_rows: activity_tree_viewport.visible_rows,
}),
true,
)),
KeyCommand::SelectRunning if has_activity => InputCommand::display(display(
DisplayCommand::Activity(ActivityCommand::SelectStatus {
status: crate::output::ActivityStatus::Running,
visible_rows: activity_tree_viewport.visible_rows,
}),
true,
)),
KeyCommand::ScrollDetailUp
| KeyCommand::ScrollDetailDown
| KeyCommand::PageDetailUp
| KeyCommand::PageDetailDown => InputCommand::display(display(
DisplayCommand::Scroll(ScrollCommand {
target: ScrollTarget::Detail,
down: matches!(
action,
KeyCommand::ScrollDetailDown | KeyCommand::PageDetailDown
),
rows: if matches!(
action,
KeyCommand::PageDetailUp | KeyCommand::PageDetailDown
) {
detail_viewport.visible_rows
} else {
1
},
visible_rows: detail_viewport.visible_rows,
wrap_width: detail_viewport.wrap_width,
}),
true,
)),
KeyCommand::ScrollTranscriptUp => {
InputCommand::display(DisplayCommand::Scroll(ScrollCommand {
target: ScrollTarget::Transcript,
down: false,
rows: 1,
visible_rows: transcript_viewport.visible_rows,
wrap_width: transcript_viewport.wrap_width,
}))
}
KeyCommand::ScrollTranscriptDown => {
InputCommand::display(DisplayCommand::Scroll(ScrollCommand {
target: ScrollTarget::Transcript,
down: true,
rows: 1,
visible_rows: transcript_viewport.visible_rows,
wrap_width: transcript_viewport.wrap_width,
}))
}
KeyCommand::MovePromptCursorLeft => InputCommand::display(display(
DisplayCommand::Prompt(PromptCommand::Edit {
operation: PromptEditCommand::MoveCursorLeft,
viewport: prompt_viewport,
refresh_autocomplete: true,
}),
true,
)),
KeyCommand::MovePromptCursorRight => InputCommand::display(display(
DisplayCommand::Prompt(PromptCommand::Edit {
operation: PromptEditCommand::MoveCursorRight,
viewport: prompt_viewport,
refresh_autocomplete: true,
}),
true,
)),
KeyCommand::MovePromptCursorUp => InputCommand::display(display(
DisplayCommand::Prompt(PromptCommand::Edit {
operation: PromptEditCommand::MoveCursorUp,
viewport: prompt_viewport,
refresh_autocomplete: true,
}),
true,
)),
KeyCommand::MovePromptCursorDown => InputCommand::display(display(
DisplayCommand::Prompt(PromptCommand::Edit {
operation: PromptEditCommand::MoveCursorDown,
viewport: prompt_viewport,
refresh_autocomplete: true,
}),
true,
)),
KeyCommand::UndoPrompt => prompt_edit_command(PromptEditCommand::Undo, prompt_viewport),
KeyCommand::RedoPrompt => prompt_edit_command(PromptEditCommand::Redo, prompt_viewport),
KeyCommand::MovePromptWordLeft => {
prompt_edit_command(PromptEditCommand::MoveWordLeft, prompt_viewport)
}
KeyCommand::MovePromptWordRight => {
prompt_edit_command(PromptEditCommand::MoveWordRight, prompt_viewport)
}
KeyCommand::DeletePromptWord => {
prompt_edit_command(PromptEditCommand::DeleteWord, prompt_viewport)
}
KeyCommand::DeletePromptNextWord => {
prompt_edit_command(PromptEditCommand::DeleteNextWord, prompt_viewport)
}
KeyCommand::ExtendPromptSelectionLeft => {
prompt_edit_command(PromptEditCommand::ExtendSelectionLeft, prompt_viewport)
}
KeyCommand::ExtendPromptSelectionRight => {
prompt_edit_command(PromptEditCommand::ExtendSelectionRight, prompt_viewport)
}
KeyCommand::ExtendPromptSelectionUp => {
prompt_edit_command(PromptEditCommand::ExtendSelectionUp, prompt_viewport)
}
KeyCommand::ExtendPromptSelectionDown => {
prompt_edit_command(PromptEditCommand::ExtendSelectionDown, prompt_viewport)
}
KeyCommand::SelectAllPrompt => {
prompt_edit_command(PromptEditCommand::SelectAll, prompt_viewport)
}
KeyCommand::MoveSelectionUp
| KeyCommand::MoveSelectionDown
| KeyCommand::CollapseSelected
| KeyCommand::ExpandSelected
| KeyCommand::ExpandAll
| KeyCommand::CollapseAll
| KeyCommand::SelectFailed
| KeyCommand::SelectRunning => InputCommand::display(DisplayCommand::RefreshAutocomplete),
}
}
fn prompt_edit_command(operation: PromptEditCommand, viewport: PromptViewport) -> InputCommand {
InputCommand::display(DisplayCommand::Prompt(PromptCommand::Edit {
operation,
viewport,
refresh_autocomplete: true,
}))
}