mirror of
https://github.com/openai/codex.git
synced 2026-09-15 12:08:01 +00:00
Optional command
This commit is contained in:
@@ -69,7 +69,10 @@ const LARGE_PASTE_CHAR_THRESHOLD: usize = 1000;
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum InputResult {
|
||||
Submitted(String),
|
||||
Command { command: SlashCommand, args: String },
|
||||
Command {
|
||||
command: SlashCommand,
|
||||
args: Option<String>,
|
||||
},
|
||||
None,
|
||||
}
|
||||
|
||||
@@ -333,13 +336,17 @@ impl ChatComposer {
|
||||
PasteBurst::recommended_flush_delay()
|
||||
}
|
||||
|
||||
fn command_args_from_line(line: &str, command: SlashCommand) -> String {
|
||||
fn command_args_from_line(line: &str, command: SlashCommand) -> Option<String> {
|
||||
if let Some((name, rest)) = parse_slash_name(line)
|
||||
&& name == command.command()
|
||||
{
|
||||
return rest.to_string();
|
||||
let trimmed = rest.trim();
|
||||
if trimmed.is_empty() {
|
||||
return None;
|
||||
}
|
||||
return Some(trimmed.to_string());
|
||||
}
|
||||
String::new()
|
||||
None
|
||||
}
|
||||
|
||||
/// Integrate results from an asynchronous file search.
|
||||
@@ -2410,7 +2417,7 @@ mod tests {
|
||||
match result {
|
||||
InputResult::Command { command: cmd, args } => {
|
||||
assert_eq!(cmd.command(), "init");
|
||||
assert!(args.is_empty());
|
||||
assert!(args.is_none());
|
||||
}
|
||||
InputResult::Submitted(text) => {
|
||||
panic!("expected command dispatch, but composer submitted literal text: {text}")
|
||||
@@ -2486,7 +2493,7 @@ mod tests {
|
||||
match result {
|
||||
InputResult::Command { command: cmd, args } => {
|
||||
assert_eq!(cmd.command(), "diff");
|
||||
assert!(args.is_empty());
|
||||
assert!(args.is_none());
|
||||
}
|
||||
InputResult::Submitted(text) => {
|
||||
panic!("expected command dispatch after Tab completion, got literal submit: {text}")
|
||||
@@ -2520,7 +2527,7 @@ mod tests {
|
||||
match result {
|
||||
InputResult::Command { command: cmd, args } => {
|
||||
assert_eq!(cmd, SlashCommand::Save);
|
||||
assert_eq!(args, "feature-one");
|
||||
assert_eq!(args.as_deref(), Some("feature-one"));
|
||||
}
|
||||
InputResult::Submitted(text) => {
|
||||
panic!(
|
||||
@@ -2556,7 +2563,7 @@ mod tests {
|
||||
match result {
|
||||
InputResult::Command { command: cmd, args } => {
|
||||
assert_eq!(cmd.command(), "mention");
|
||||
assert!(args.is_empty());
|
||||
assert!(args.is_none());
|
||||
}
|
||||
InputResult::Submitted(text) => {
|
||||
panic!("expected command dispatch, but composer submitted literal text: {text}")
|
||||
|
||||
@@ -1323,7 +1323,7 @@ impl ChatWidget {
|
||||
self.request_redraw();
|
||||
}
|
||||
|
||||
fn dispatch_command(&mut self, cmd: SlashCommand, args: String) {
|
||||
fn dispatch_command(&mut self, cmd: SlashCommand, args: Option<String>) {
|
||||
if !cmd.available_during_task() && self.bottom_pane.is_task_running() {
|
||||
let message = format!(
|
||||
"'/{}' is disabled while a task is in progress.",
|
||||
@@ -1463,8 +1463,14 @@ impl ChatWidget {
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_save_command(&mut self, args: String) {
|
||||
let name = args.trim();
|
||||
fn handle_save_command(&mut self, args: Option<String>) {
|
||||
let Some(name_raw) = args else {
|
||||
self.add_to_history(history_cell::new_error_event(
|
||||
"Usage: /save <name>".to_string(),
|
||||
));
|
||||
return;
|
||||
};
|
||||
let name = name_raw.trim();
|
||||
if name.is_empty() {
|
||||
self.add_to_history(history_cell::new_error_event(
|
||||
"Usage: /save <name>".to_string(),
|
||||
|
||||
@@ -954,7 +954,7 @@ fn slash_init_skips_when_project_doc_exists() {
|
||||
std::fs::write(&existing_path, "existing instructions").unwrap();
|
||||
chat.config.cwd = tempdir.path().to_path_buf();
|
||||
|
||||
chat.dispatch_command(SlashCommand::Init, String::new());
|
||||
chat.dispatch_command(SlashCommand::Init, None);
|
||||
|
||||
match op_rx.try_recv() {
|
||||
Err(TryRecvError::Empty) => {}
|
||||
@@ -982,7 +982,7 @@ fn slash_init_skips_when_project_doc_exists() {
|
||||
fn slash_quit_requests_exit() {
|
||||
let (mut chat, mut rx, _op_rx) = make_chatwidget_manual();
|
||||
|
||||
chat.dispatch_command(SlashCommand::Quit, String::new());
|
||||
chat.dispatch_command(SlashCommand::Quit, None);
|
||||
|
||||
assert_matches!(rx.try_recv(), Ok(AppEvent::ExitRequest));
|
||||
}
|
||||
@@ -991,7 +991,7 @@ fn slash_quit_requests_exit() {
|
||||
fn slash_exit_requests_exit() {
|
||||
let (mut chat, mut rx, _op_rx) = make_chatwidget_manual();
|
||||
|
||||
chat.dispatch_command(SlashCommand::Exit, String::new());
|
||||
chat.dispatch_command(SlashCommand::Exit, None);
|
||||
|
||||
assert_matches!(rx.try_recv(), Ok(AppEvent::ExitRequest));
|
||||
}
|
||||
@@ -1000,7 +1000,7 @@ fn slash_exit_requests_exit() {
|
||||
fn slash_undo_sends_op() {
|
||||
let (mut chat, mut rx, _op_rx) = make_chatwidget_manual();
|
||||
|
||||
chat.dispatch_command(SlashCommand::Undo, String::new());
|
||||
chat.dispatch_command(SlashCommand::Undo, None);
|
||||
|
||||
match rx.try_recv() {
|
||||
Ok(AppEvent::CodexOp(Op::Undo)) => {}
|
||||
@@ -1014,7 +1014,7 @@ fn slash_rollout_displays_current_path() {
|
||||
let rollout_path = PathBuf::from("/tmp/codex-test-rollout.jsonl");
|
||||
chat.current_rollout_path = Some(rollout_path.clone());
|
||||
|
||||
chat.dispatch_command(SlashCommand::Rollout, String::new());
|
||||
chat.dispatch_command(SlashCommand::Rollout, None);
|
||||
|
||||
let cells = drain_insert_history(&mut rx);
|
||||
assert_eq!(cells.len(), 1, "expected info message for rollout path");
|
||||
@@ -1029,7 +1029,7 @@ fn slash_rollout_displays_current_path() {
|
||||
fn slash_rollout_handles_missing_path() {
|
||||
let (mut chat, mut rx, _op_rx) = make_chatwidget_manual();
|
||||
|
||||
chat.dispatch_command(SlashCommand::Rollout, String::new());
|
||||
chat.dispatch_command(SlashCommand::Rollout, None);
|
||||
|
||||
let cells = drain_insert_history(&mut rx);
|
||||
assert_eq!(
|
||||
@@ -1624,7 +1624,7 @@ fn feedback_selection_popup_snapshot() {
|
||||
let (mut chat, _rx, _op_rx) = make_chatwidget_manual();
|
||||
|
||||
// Open the feedback category selection popup via slash command.
|
||||
chat.dispatch_command(SlashCommand::Feedback, String::new());
|
||||
chat.dispatch_command(SlashCommand::Feedback, None);
|
||||
|
||||
let popup = render_bottom_popup(&chat, 80);
|
||||
assert_snapshot!("feedback_selection_popup", popup);
|
||||
@@ -1702,7 +1702,7 @@ fn disabled_slash_command_while_task_running_snapshot() {
|
||||
chat.bottom_pane.set_task_running(true);
|
||||
|
||||
// Dispatch a command that is unavailable while a task runs (e.g., /model)
|
||||
chat.dispatch_command(SlashCommand::Model, String::new());
|
||||
chat.dispatch_command(SlashCommand::Model, None);
|
||||
|
||||
// Drain history and snapshot the rendered error line(s)
|
||||
let cells = drain_insert_history(&mut rx);
|
||||
|
||||
Reference in New Issue
Block a user