mirror of
https://github.com/openai/codex.git
synced 2026-11-13 14:46:14 +00:00
Fix multiline paste in /goal edit (#26047)
Fixes #26025. ## Why `/goal edit` opens `CustomPromptView`, which did not use the paste-burst handling that protects the main composer when terminals deliver paste as rapid key events. On Windows terminals, the first pasted newline could be treated as Enter-to-submit, truncating the goal edit and leaving the rest of the paste behind. ## What This reuses `PasteBurst` in `CustomPromptView` as a lightweight Enter-suppression detector for paste-like key streams. Characters still insert directly, explicit paste still goes through the view paste path, and ordinary text entry still submits on Enter.
This commit is contained in:
1 parent
8030c36970
commit
a2a9e767f7
4 files changed
+160
-24
No files matched your search
@@ -10,7 +10,7 @@
|
||||
//! paste once enough chars have arrived.
|
||||
//!
|
||||
//! This module provides the `PasteBurst` state machine. `ChatComposer` feeds it only "plain"
|
||||
//! character events (no Ctrl/Alt) and uses its decisions to either:
|
||||
//! character events (no Ctrl/Alt) and uses the full buffering decisions to either:
|
||||
//!
|
||||
//! - briefly hold a first ASCII char (flicker suppression),
|
||||
//! - buffer a burst as a single pasted string, or
|
||||
@@ -32,6 +32,10 @@
|
||||
//! [`PasteBurst::flush_before_modified_input`] to avoid leaving buffered text "stuck", and then
|
||||
//! [`PasteBurst::clear_window_after_non_char`] so subsequent typing does not get grouped into a
|
||||
//! previous burst.
|
||||
//! - Direct-insert callers can skip buffering, use
|
||||
//! [`PasteBurst::direct_insert_newline_should_insert`] in their Enter handler, and call
|
||||
//! [`PasteBurst::extend_window`] when Enter or [`PasteBurst::on_plain_char_no_hold`] reports a
|
||||
//! burst-like stream.
|
||||
//!
|
||||
//! # State Variables
|
||||
//!
|
||||
@@ -106,10 +110,10 @@
|
||||
//! - [`PasteBurst::on_plain_char_no_hold`] never holds (used for IME/non-ASCII paths), since
|
||||
//! holding a non-ASCII character can feel like dropped input.
|
||||
//!
|
||||
//! # Contract With `ChatComposer`
|
||||
//! # Contract With Callers
|
||||
//!
|
||||
//! `PasteBurst` does not mutate the UI text buffer on its own. The caller (`ChatComposer`) must
|
||||
//! interpret decisions and apply the corresponding UI edits:
|
||||
//! `PasteBurst` does not mutate the UI text buffer on its own. Callers must interpret decisions
|
||||
//! and apply the corresponding UI edits. `ChatComposer` uses the full buffering contract:
|
||||
//!
|
||||
//! - For each plain ASCII `KeyCode::Char`, call [`PasteBurst::on_plain_char`].
|
||||
//! - [`CharDecision::RetainFirstChar`]: do **not** insert the char into the textarea yet.
|
||||
@@ -333,6 +337,14 @@ impl PasteBurst {
|
||||
self.is_active() || in_burst_window
|
||||
}
|
||||
|
||||
/// Decide if Enter should insert a newline for callers that insert chars immediately.
|
||||
pub fn direct_insert_newline_should_insert(&self, now: Instant) -> bool {
|
||||
self.newline_should_insert_instead_of_submit(now)
|
||||
|| self
|
||||
.last_plain_char_time
|
||||
.is_some_and(|t| now.duration_since(t) <= PASTE_BURST_CHAR_INTERVAL)
|
||||
}
|
||||
|
||||
/// Keep the burst window alive.
|
||||
pub fn extend_window(&mut self, now: Instant) {
|
||||
self.burst_window_until = Some(now + PASTE_ENTER_SUPPRESS_WINDOW);
|
||||
|
||||
Reference in new issue
Block a user