## Summary - add the `/exit` slash command alongside `/quit` and reuse shared exit handling - refactor the chat widget to funnel quit, exit, logout, and shutdown flows through a common `request_exit` helper - add focused unit tests that confirm both `/quit` and `/exit` send an `ExitRequest` ## Testing - `just fmt` - `just fix -p codex-tui` - `cargo test -p codex-tui` ------ https://chatgpt.com/codex/tasks/task_i_6903d5a8f47c8321bf180f031f2fa330
101 lines
3.5 KiB
Rust
101 lines
3.5 KiB
Rust
use strum::IntoEnumIterator;
|
|
use strum_macros::AsRefStr;
|
|
use strum_macros::EnumIter;
|
|
use strum_macros::EnumString;
|
|
use strum_macros::IntoStaticStr;
|
|
|
|
/// Commands that can be invoked by starting a message with a leading slash.
|
|
#[derive(
|
|
Debug, Clone, Copy, PartialEq, Eq, Hash, EnumString, EnumIter, AsRefStr, IntoStaticStr,
|
|
)]
|
|
#[strum(serialize_all = "kebab-case")]
|
|
pub enum SlashCommand {
|
|
// DO NOT ALPHA-SORT! Enum order is presentation order in the popup, so
|
|
// more frequently used commands should be listed first.
|
|
Model,
|
|
Approvals,
|
|
Review,
|
|
New,
|
|
Init,
|
|
Compact,
|
|
Undo,
|
|
Diff,
|
|
Mention,
|
|
Status,
|
|
Mcp,
|
|
Logout,
|
|
Quit,
|
|
Exit,
|
|
Feedback,
|
|
Rollout,
|
|
TestApproval,
|
|
}
|
|
|
|
impl SlashCommand {
|
|
/// User-visible description shown in the popup.
|
|
pub fn description(self) -> &'static str {
|
|
match self {
|
|
SlashCommand::Feedback => "send logs to maintainers",
|
|
SlashCommand::New => "start a new chat during a conversation",
|
|
SlashCommand::Init => "create an AGENTS.md file with instructions for Codex",
|
|
SlashCommand::Compact => "summarize conversation to prevent hitting the context limit",
|
|
SlashCommand::Review => "review my current changes and find issues",
|
|
SlashCommand::Undo => "ask Codex to undo a turn",
|
|
SlashCommand::Quit | SlashCommand::Exit => "exit Codex",
|
|
SlashCommand::Diff => "show git diff (including untracked files)",
|
|
SlashCommand::Mention => "mention a file",
|
|
SlashCommand::Status => "show current session configuration and token usage",
|
|
SlashCommand::Model => "choose what model and reasoning effort to use",
|
|
SlashCommand::Approvals => "choose what Codex can do without approval",
|
|
SlashCommand::Mcp => "list configured MCP tools",
|
|
SlashCommand::Logout => "log out of Codex",
|
|
SlashCommand::Rollout => "print the rollout file path",
|
|
SlashCommand::TestApproval => "test approval request",
|
|
}
|
|
}
|
|
|
|
/// Command string without the leading '/'. Provided for compatibility with
|
|
/// existing code that expects a method named `command()`.
|
|
pub fn command(self) -> &'static str {
|
|
self.into()
|
|
}
|
|
|
|
/// Whether this command can be run while a task is in progress.
|
|
pub fn available_during_task(self) -> bool {
|
|
match self {
|
|
SlashCommand::New
|
|
| SlashCommand::Init
|
|
| SlashCommand::Compact
|
|
| SlashCommand::Undo
|
|
| SlashCommand::Model
|
|
| SlashCommand::Approvals
|
|
| SlashCommand::Review
|
|
| SlashCommand::Logout => false,
|
|
SlashCommand::Diff
|
|
| SlashCommand::Mention
|
|
| SlashCommand::Status
|
|
| SlashCommand::Mcp
|
|
| SlashCommand::Feedback
|
|
| SlashCommand::Quit
|
|
| SlashCommand::Exit => true,
|
|
SlashCommand::Rollout => true,
|
|
SlashCommand::TestApproval => true,
|
|
}
|
|
}
|
|
|
|
fn is_visible(self) -> bool {
|
|
match self {
|
|
SlashCommand::Rollout | SlashCommand::TestApproval => cfg!(debug_assertions),
|
|
_ => true,
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Return all built-in commands in a Vec paired with their command string.
|
|
pub fn built_in_slash_commands() -> Vec<(&'static str, SlashCommand)> {
|
|
SlashCommand::iter()
|
|
.filter(|command| command.is_visible())
|
|
.map(|c| (c.command(), c))
|
|
.collect()
|
|
}
|