Nicer highlighting of slash commands, /plan accepts prompt args and pasted images (#10269)

## Summary
- Make typed slash commands become text elements when the user hits
space, including paste‑burst spaces.
- Enable `/plan` to accept inline args and submit them in plan mode,
mirroring `/review` behavior and blocking submission while a task is
running.
- Preserve text elements/attachments for slash commands that take args.

<img width="1510" height="500" alt="image"
src="https://github.com/user-attachments/assets/446024df-b69a-4249-85db-1a85110e07f1"
/>

## Changes
- Add safe helper to insert element ranges in the textarea.
- Extend command‑with‑args pipeline to carry text elements and reuse
submission prep.
- Update `/plan` dispatch to switch to plan mode then submit prompt +
elements.
- Document new composer behavior and add tests.

## Notes
- `/plan` is blocked during active tasks (same as `/review`).
- Slash‑command elementization recognizes built‑ins and `/prompts:`
custom commands only.

## Codex author
`codex fork 019c16d3-4520-7bb0-9b9d-48720d40a8ab`
This commit is contained in:
Charley Cunningham
2026-02-02 09:53:29 -08:00
committed by GitHub
parent d1e71cd202
commit 3392c5af24
7 changed files with 517 additions and 36 deletions

View File

@@ -218,6 +218,12 @@ impl BottomPane {
self.composer.take_mention_paths()
}
/// Clear pending attachments and mention paths e.g. when a slash command doesn't submit text.
pub(crate) fn drain_pending_submission_state(&mut self) {
let _ = self.take_recent_submission_images_with_placeholders();
let _ = self.take_mention_paths();
}
pub fn set_steer_enabled(&mut self, enabled: bool) {
self.composer.set_steer_enabled(enabled);
}
@@ -404,6 +410,7 @@ impl BottomPane {
) {
self.composer
.set_text_content(text, text_elements, local_image_paths);
self.composer.move_cursor_to_end();
self.request_redraw();
}
@@ -787,6 +794,13 @@ impl BottomPane {
.take_recent_submission_images_with_placeholders()
}
pub(crate) fn prepare_inline_args_submission(
&mut self,
record_history: bool,
) -> Option<(String, Vec<TextElement>)> {
self.composer.prepare_inline_args_submission(record_history)
}
fn as_renderable(&'_ self) -> RenderableItem<'_> {
if let Some(view) = self.active_view() {
RenderableItem::Borrowed(view)