feat: remove ModePicker overlay and related commands; update mode handling and documentation
This commit is contained in:
@@ -30,7 +30,6 @@ pub enum Action {
|
||||
OpenOverlay(Overlay),
|
||||
CloseOverlay,
|
||||
ToggleYoloArm,
|
||||
CycleAgentMode,
|
||||
SystemNote {
|
||||
kind: String,
|
||||
message: String,
|
||||
@@ -242,13 +241,6 @@ pub fn apply_action(state: &mut AppStateRest, action: Action) {
|
||||
state.misc.yolo_armed = !state.misc.yolo_armed;
|
||||
state.dirty = true;
|
||||
}
|
||||
Action::CycleAgentMode => {
|
||||
let next = state.mode.cycle();
|
||||
state.set_mode(next);
|
||||
let toast = Toast::new(ToastKind::Info, format!("Mode: {}", state.mode.name()));
|
||||
state.push_toast(toast);
|
||||
state.dirty = true;
|
||||
}
|
||||
Action::SystemNote { kind: _kind, message } => {
|
||||
let toast = crate::app::state::types::Toast::new(
|
||||
crate::app::state::types::ToastKind::Info,
|
||||
|
||||
@@ -75,14 +75,6 @@ const COMMANDS: &[&str] = &[
|
||||
"/lesson import",
|
||||
"/lesson accept",
|
||||
"/lesson reject",
|
||||
"/mode chat",
|
||||
"/mode bash",
|
||||
"/mode help",
|
||||
"/mode settings",
|
||||
"/mode effort",
|
||||
"/mode mcp",
|
||||
"/mode rewind",
|
||||
"/mode editor",
|
||||
"/login",
|
||||
"/login zen",
|
||||
"/login openai",
|
||||
|
||||
@@ -68,7 +68,7 @@ impl AppStateRest {
|
||||
.map(|n| n.to_string_lossy().to_string())
|
||||
.unwrap_or_default();
|
||||
AppStateRest {
|
||||
mode: AgentMode::Normal,
|
||||
mode: AgentMode::Auto,
|
||||
settings,
|
||||
app_config,
|
||||
workspace_roots,
|
||||
|
||||
@@ -87,7 +87,6 @@ pub enum Overlay {
|
||||
Loading,
|
||||
ModelSelector,
|
||||
ClearConfirm,
|
||||
ModePicker,
|
||||
LoginPicker,
|
||||
}
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ pub fn parse_command(text: &str) -> Command {
|
||||
"/quit" => Command::Quit,
|
||||
"/clear" if arg1.is_empty() => Command::ClearConfirm,
|
||||
"/clear" => Command::Clear,
|
||||
"/mode" if arg1.is_empty() => Command::Help, // open help to show available modes
|
||||
"/mode" if arg1.is_empty() => Command::Unknown("/mode requires a subcommand: chat, bash, help, settings".to_string()),
|
||||
"/mode" => {
|
||||
let mode = match arg1 {
|
||||
"chat" | "c" => ModeKind::Chat,
|
||||
|
||||
@@ -124,10 +124,6 @@ pub fn handle_key(key: KeyEvent, state: &mut AppStateRest) -> Vec<Action> {
|
||||
state.misc.selected_index = if state.misc.selected_index == 0 { n.saturating_sub(1) } else { state.misc.selected_index - 1 };
|
||||
state.dirty = true;
|
||||
Vec::new()
|
||||
} else if state.misc.overlay == Overlay::ModePicker {
|
||||
state.misc.selected_index = if state.misc.selected_index == 0 { 3 } else { state.misc.selected_index - 1 };
|
||||
state.dirty = true;
|
||||
Vec::new()
|
||||
} else if state.misc.overlay == Overlay::LoginPicker {
|
||||
let n = crate::app::mode::onboard_provider::PROVIDERS.len();
|
||||
state.misc.selected_index = if state.misc.selected_index == 0 { n.saturating_sub(1) } else { state.misc.selected_index - 1 };
|
||||
@@ -162,10 +158,6 @@ pub fn handle_key(key: KeyEvent, state: &mut AppStateRest) -> Vec<Action> {
|
||||
state.misc.selected_index = if n == 0 { 0 } else { (state.misc.selected_index + 1) % n };
|
||||
state.dirty = true;
|
||||
Vec::new()
|
||||
} else if state.misc.overlay == Overlay::ModePicker {
|
||||
state.misc.selected_index = (state.misc.selected_index + 1) % 4;
|
||||
state.dirty = true;
|
||||
Vec::new()
|
||||
} else if state.misc.overlay == Overlay::LoginPicker {
|
||||
let n = crate::app::mode::onboard_provider::PROVIDERS.len();
|
||||
state.misc.selected_index = (state.misc.selected_index + 1) % n;
|
||||
@@ -181,33 +173,6 @@ pub fn handle_key(key: KeyEvent, state: &mut AppStateRest) -> Vec<Action> {
|
||||
KeyCode::PageDown => {
|
||||
vec![Action::ScrollDown]
|
||||
}
|
||||
KeyCode::Char('h') if key.modifiers.contains(KeyModifiers::CONTROL) => {
|
||||
vec![Action::OpenOverlay(Overlay::Help)]
|
||||
}
|
||||
KeyCode::Char('p') if key.modifiers.contains(KeyModifiers::CONTROL) => {
|
||||
vec![Action::OpenOverlay(Overlay::Settings)]
|
||||
}
|
||||
KeyCode::Char('a') if key.modifiers.contains(KeyModifiers::CONTROL) => {
|
||||
vec![Action::ToggleYoloArm]
|
||||
}
|
||||
KeyCode::Char('m') if key.modifiers.contains(KeyModifiers::CONTROL) => {
|
||||
vec![Action::CycleAgentMode]
|
||||
}
|
||||
KeyCode::Char('b') if key.modifiers.contains(KeyModifiers::CONTROL) => {
|
||||
vec![Action::OpenOverlay(Overlay::Bash)]
|
||||
}
|
||||
KeyCode::Char('S') if key.modifiers.contains(KeyModifiers::CONTROL) => {
|
||||
vec![Action::OpenOverlay(Overlay::Security)]
|
||||
}
|
||||
KeyCode::Char('t') if key.modifiers.contains(KeyModifiers::CONTROL) => {
|
||||
vec![Action::OpenOverlay(Overlay::Todo)]
|
||||
}
|
||||
KeyCode::Char('w') if key.modifiers.contains(KeyModifiers::CONTROL) => {
|
||||
vec![Action::OpenOverlay(Overlay::Workflow)]
|
||||
}
|
||||
KeyCode::Char('k') if key.modifiers.contains(KeyModifiers::CONTROL) => {
|
||||
vec![Action::OpenOverlay(Overlay::KeyInput)]
|
||||
}
|
||||
KeyCode::Esc => {
|
||||
if state.input.autocomplete_visible {
|
||||
state.input.close_autocomplete();
|
||||
@@ -230,12 +195,6 @@ pub fn handle_key(key: KeyEvent, state: &mut AppStateRest) -> Vec<Action> {
|
||||
}
|
||||
Vec::new()
|
||||
}
|
||||
KeyCode::Char('l') if key.modifiers.contains(KeyModifiers::CONTROL) => {
|
||||
vec![Action::OpenOverlay(Overlay::Learning)]
|
||||
}
|
||||
KeyCode::Char('u') if key.modifiers.contains(KeyModifiers::CONTROL) => {
|
||||
vec![Action::OpenOverlay(Overlay::Usage)]
|
||||
}
|
||||
KeyCode::Char(c) => {
|
||||
if state.input.autocomplete_visible {
|
||||
state.input.close_autocomplete();
|
||||
@@ -341,17 +300,6 @@ fn handle_overlay_enter(state: &mut AppStateRest) -> Vec<Action> {
|
||||
state.dirty = true;
|
||||
Vec::new()
|
||||
}
|
||||
Overlay::ModePicker => {
|
||||
let mode = state.mode.cycle();
|
||||
state.mode = mode;
|
||||
state.push_toast(crate::app::state::types::Toast::new(
|
||||
crate::app::state::types::ToastKind::Info,
|
||||
format!("Mode: {}", mode.name()),
|
||||
));
|
||||
state.misc.overlay = Overlay::None;
|
||||
state.dirty = true;
|
||||
Vec::new()
|
||||
}
|
||||
Overlay::LoginPicker => {
|
||||
state.misc.overlay = Overlay::OnboardProvider;
|
||||
state.dirty = true;
|
||||
|
||||
@@ -232,7 +232,6 @@ fn apply_client_update(
|
||||
Some("Loading") => Overlay::Loading,
|
||||
Some("ModelSelector") => Overlay::ModelSelector,
|
||||
Some("ClearConfirm") => Overlay::ClearConfirm,
|
||||
Some("ModePicker") => Overlay::ModePicker,
|
||||
Some("LoginPicker") => Overlay::LoginPicker,
|
||||
_ => Overlay::None,
|
||||
};
|
||||
|
||||
+1
-1
@@ -27,7 +27,7 @@ Modes:
|
||||
Input:
|
||||
/help Show help
|
||||
/clear Clear screen
|
||||
/mode Show current mode
|
||||
/model Select AI model provider
|
||||
/exit Exit application
|
||||
/settings Open settings
|
||||
/session Session management
|
||||
|
||||
@@ -608,43 +608,6 @@ fn render_overlay(frame: &mut Frame, area: Rect, overlay: crate::app::state::typ
|
||||
let paragraph = Paragraph::new(lines).block(block);
|
||||
frame.render_widget(paragraph, overlay_area);
|
||||
}
|
||||
crate::app::state::types::Overlay::ModePicker => {
|
||||
let block = block.title(" Mode ");
|
||||
let modes = [
|
||||
("Auto", "auto-approve tools"),
|
||||
("Normal", "ask before risky tools"),
|
||||
("Plan", "plan-only mode"),
|
||||
("Yolo", "full auto"),
|
||||
];
|
||||
let current = state.mode.name();
|
||||
let mut lines: Vec<Line> = vec![
|
||||
Line::from(Span::styled(
|
||||
format!("Current: {}", current),
|
||||
Style::default().fg(Theme::INFO).add_modifier(Modifier::BOLD),
|
||||
)),
|
||||
Line::from(Span::styled("", Style::default())),
|
||||
];
|
||||
for (i, (name, desc)) in modes.iter().enumerate() {
|
||||
let is_selected = i == state.misc.selected_index;
|
||||
let prefix = if is_selected { "▸ " } else { " " };
|
||||
let label = format!("{}{} ({})", prefix, name, desc);
|
||||
let style = if *name == current {
|
||||
Style::default().fg(Theme::HIGHLIGHT).add_modifier(Modifier::BOLD).add_modifier(Modifier::ITALIC)
|
||||
} else if is_selected {
|
||||
Style::default().fg(Theme::BG).bg(Theme::HIGHLIGHT)
|
||||
} else {
|
||||
Style::default().fg(Theme::TEXT)
|
||||
};
|
||||
lines.push(Line::from(Span::styled(label, style)));
|
||||
}
|
||||
lines.push(Line::from(Span::styled("", Style::default())));
|
||||
lines.push(Line::from(Span::styled(
|
||||
"↑↓ navigate · Enter select · Esc close",
|
||||
Style::default().fg(Theme::DIM),
|
||||
)));
|
||||
let paragraph = Paragraph::new(lines).block(block);
|
||||
frame.render_widget(paragraph, overlay_area);
|
||||
}
|
||||
crate::app::state::types::Overlay::LoginPicker => {
|
||||
let block = block.title(" Login ");
|
||||
let providers = crate::app::mode::onboard_provider::PROVIDERS;
|
||||
|
||||
Reference in New Issue
Block a user