mirror of
https://github.com/openai/codex.git
synced 2026-11-13 22:47:20 +00:00
feat: open prompt in configured external editor (#7606)
Add `ctrl+g` shortcut to enable opening current prompt in configured editor (`$VISUAL` or `$EDITOR`). - Prompt is updated with editor's content upon editor close. - Paste placeholders are automatically expanded when opening the external editor, and are not "recompressed" on close - They could be preserved in the editor, but it would be hard to prevent the user from modifying the placeholder text directly, which would drop the mapping to the `pending_paste` value - Image placeholders stay as-is - `ctrl+g` explanation added to shortcuts menu, snapshot tests updated https://github.com/user-attachments/assets/4ee05c81-fa49-4e99-8b07-fc9eef0bbfce
This commit is contained in:
1 parent
8e900c210c
commit
4673090f73
14 files changed
+723
-18
No files matched your search
@@ -302,6 +302,14 @@ enum RateLimitSwitchPromptState {
|
||||
Shown,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
|
||||
pub(crate) enum ExternalEditorState {
|
||||
#[default]
|
||||
Closed,
|
||||
Requested,
|
||||
Active,
|
||||
}
|
||||
|
||||
pub(crate) struct ChatWidget {
|
||||
app_event_tx: AppEventSender,
|
||||
codex_op_tx: UnboundedSender<Op>,
|
||||
@@ -360,6 +368,7 @@ pub(crate) struct ChatWidget {
|
||||
feedback: codex_feedback::CodexFeedback,
|
||||
// Current session rollout path (if known)
|
||||
current_rollout_path: Option<PathBuf>,
|
||||
external_editor_state: ExternalEditorState,
|
||||
}
|
||||
|
||||
struct UserMessage {
|
||||
@@ -1469,6 +1478,7 @@ impl ChatWidget {
|
||||
last_rendered_width: std::cell::Cell::new(None),
|
||||
feedback,
|
||||
current_rollout_path: None,
|
||||
external_editor_state: ExternalEditorState::Closed,
|
||||
};
|
||||
|
||||
widget.prefetch_rate_limits();
|
||||
@@ -1555,6 +1565,7 @@ impl ChatWidget {
|
||||
last_rendered_width: std::cell::Cell::new(None),
|
||||
feedback,
|
||||
current_rollout_path: None,
|
||||
external_editor_state: ExternalEditorState::Closed,
|
||||
};
|
||||
|
||||
widget.prefetch_rate_limits();
|
||||
@@ -1653,6 +1664,31 @@ impl ChatWidget {
|
||||
self.request_redraw();
|
||||
}
|
||||
|
||||
pub(crate) fn composer_text_with_pending(&self) -> String {
|
||||
self.bottom_pane.composer_text_with_pending()
|
||||
}
|
||||
|
||||
pub(crate) fn apply_external_edit(&mut self, text: String) {
|
||||
self.bottom_pane.apply_external_edit(text);
|
||||
self.request_redraw();
|
||||
}
|
||||
|
||||
pub(crate) fn external_editor_state(&self) -> ExternalEditorState {
|
||||
self.external_editor_state
|
||||
}
|
||||
|
||||
pub(crate) fn set_external_editor_state(&mut self, state: ExternalEditorState) {
|
||||
self.external_editor_state = state;
|
||||
}
|
||||
|
||||
pub(crate) fn set_footer_hint_override(&mut self, items: Option<Vec<(String, String)>>) {
|
||||
self.bottom_pane.set_footer_hint_override(items);
|
||||
}
|
||||
|
||||
pub(crate) fn can_launch_external_editor(&self) -> bool {
|
||||
self.bottom_pane.can_launch_external_editor()
|
||||
}
|
||||
|
||||
fn dispatch_command(&mut self, cmd: SlashCommand) {
|
||||
if !cmd.available_during_task() && self.bottom_pane.is_task_running() {
|
||||
let message = format!(
|
||||
@@ -1854,7 +1890,7 @@ impl ChatWidget {
|
||||
.send(AppEvent::InsertHistoryCell(Box::new(cell)));
|
||||
}
|
||||
|
||||
fn add_to_history(&mut self, cell: impl HistoryCell + 'static) {
|
||||
pub(crate) fn add_to_history(&mut self, cell: impl HistoryCell + 'static) {
|
||||
self.add_boxed_history(Box::new(cell));
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user