Skip to content

Commit c9ca63d

Browse files
authored
burst paste edge cases (#2683)
This PR fixes two edge cases in managing burst paste (mainly on power shell). Bugs: - Needs an event key after paste to render the pasted items > ChatComposer::flush_paste_burst_if_due() flushes on timeout. Called: > - Pre-render in App on TuiEvent::Draw. > - Via a delayed frame > BottomPane::request_redraw_in(ChatComposer::recommended_paste_flush_delay()). - Parses two key events separately before starting parsing burst paste > When threshold is crossed, pull preceding burst chars out of the textarea and prepend to paste_burst_buffer, then keep buffering. - Integrates with #2567 to bring image pasting to windows.
1 parent ed06f90 commit c9ca63d

File tree

8 files changed

+632
-158
lines changed

8 files changed

+632
-158
lines changed

codex-rs/core/src/config.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,10 @@ pub struct Config {
181181

182182
/// Include the `view_image` tool that lets the agent attach a local image path to context.
183183
pub include_view_image_tool: bool,
184+
/// When true, disables burst-paste detection for typed input entirely.
185+
/// All characters are inserted as they are received, and no buffering
186+
/// or placeholder replacement will occur for fast keypress bursts.
187+
pub disable_paste_burst: bool,
184188
}
185189

186190
impl Config {
@@ -488,6 +492,11 @@ pub struct ConfigToml {
488492

489493
/// Nested tools section for feature toggles
490494
pub tools: Option<ToolsToml>,
495+
496+
/// When true, disables burst-paste detection for typed input entirely.
497+
/// All characters are inserted as they are received, and no buffering
498+
/// or placeholder replacement will occur for fast keypress bursts.
499+
pub disable_paste_burst: Option<bool>,
491500
}
492501

493502
#[derive(Deserialize, Debug, Clone, PartialEq, Eq)]
@@ -798,6 +807,7 @@ impl Config {
798807
.experimental_use_exec_command_tool
799808
.unwrap_or(false),
800809
include_view_image_tool,
810+
disable_paste_burst: cfg.disable_paste_burst.unwrap_or(false),
801811
};
802812
Ok(config)
803813
}
@@ -1167,6 +1177,7 @@ disable_response_storage = true
11671177
preferred_auth_method: AuthMode::ChatGPT,
11681178
use_experimental_streamable_shell_tool: false,
11691179
include_view_image_tool: true,
1180+
disable_paste_burst: false,
11701181
},
11711182
o3_profile_config
11721183
);
@@ -1224,6 +1235,7 @@ disable_response_storage = true
12241235
preferred_auth_method: AuthMode::ChatGPT,
12251236
use_experimental_streamable_shell_tool: false,
12261237
include_view_image_tool: true,
1238+
disable_paste_burst: false,
12271239
};
12281240

12291241
assert_eq!(expected_gpt3_profile_config, gpt3_profile_config);
@@ -1296,6 +1308,7 @@ disable_response_storage = true
12961308
preferred_auth_method: AuthMode::ChatGPT,
12971309
use_experimental_streamable_shell_tool: false,
12981310
include_view_image_tool: true,
1311+
disable_paste_burst: false,
12991312
};
13001313

13011314
assert_eq!(expected_zdr_profile_config, zdr_profile_config);

codex-rs/tui/src/app.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,12 @@ impl App {
133133
self.chat_widget.handle_paste(pasted);
134134
}
135135
TuiEvent::Draw => {
136+
if self
137+
.chat_widget
138+
.handle_paste_burst_tick(tui.frame_requester())
139+
{
140+
return Ok(true);
141+
}
136142
tui.draw(
137143
self.chat_widget.desired_height(tui.terminal.size()?.width),
138144
|frame| {

codex-rs/tui/src/bottom_pane/approval_modal_view.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ mod tests {
100100
has_input_focus: true,
101101
enhanced_keys_supported: false,
102102
placeholder_text: "Ask Codex to do anything".to_string(),
103+
disable_paste_burst: false,
103104
});
104105
assert_eq!(CancellationEvent::Handled, view.on_ctrl_c(&mut pane));
105106
assert!(view.queue.is_empty());

0 commit comments

Comments
 (0)