mirror of
https://github.com/openai/codex.git
synced 2026-04-28 18:32:04 +03:00
5.1 KiB
5.1 KiB
Burst Paste Edge Cases: Review Guide (PR #2683)
DOs
-
Bold the keyword, then colon + concise description below each, with a short code example.
-
Idempotent setters: perform side effects only when state changes.
fn set_disable_paste_burst(&mut self, disabled: bool) {
let was_disabled = self.disable_paste_burst;
self.disable_paste_burst = disabled;
if disabled && !was_disabled {
self.paste_burst.clear_window_after_non_char();
}
}
- Constructor wiring: pass config flags into
new()and centralize side effects via a setter.
impl ChatComposer {
pub fn new(..., disable_paste_burst: bool) -> Self {
let mut this = Self { /* fields */, paste_burst: PasteBurst::default(), disable_paste_burst: false };
this.set_disable_paste_burst(disable_paste_burst);
this
}
}
- Doc comments: use
///, describe behavior and return values succinctly.
/// Flush buffered content if the inter-key timeout elapsed.
/// Returns Some(buffered_or_saved_text) when a flush occurs, otherwise None.
pub fn flush_if_due(&mut self, now: Instant) -> Option<String> { /* ... */ }
- Clear, accurate names: use descriptive enum variants (e.g.,
RetainFirstChar).
pub(crate) enum CharDecision {
BeginBuffer { retro_chars: u16 },
BufferAppend,
RetainFirstChar,
BeginBufferFromPending,
}
- Unicode-safe heuristics: count characters, not bytes; document rationale.
/// Begin buffering if recent text likely came from a paste (whitespace or long).
let looks_pastey = grabbed.chars().any(|c| c.is_whitespace()) || grabbed.chars().count() >= 16;
- Tight, total returns: ensure boolean helpers return on all paths; prefer single expression.
pub(crate) fn handle_paste_burst_tick(&mut self, fr: FrameRequester) -> bool {
if self.bottom_pane.flush_paste_burst_if_due() {
self.request_redraw();
true
} else if self.bottom_pane.is_in_paste_burst() {
fr.schedule_frame_in(ChatComposer::recommended_paste_flush_delay());
true
} else {
false
}
}
- Friendly imports: import types once; avoid fully qualified paths where possible.
use std::time::Duration;
pub(crate) fn request_redraw_in(&self, dur: Duration) {
self.frame_requester.schedule_frame_in(dur);
}
- Smart redraw scheduling: request immediate redraw on flush; schedule a delayed tick while capturing.
if needs_redraw { self.request_redraw(); }
if self.composer.is_in_paste_burst() {
self.request_redraw_in(ChatComposer::recommended_paste_flush_delay());
}
- Simple tests: keep helpers minimal; human-like typing with a small delay; use simple literals.
fn type_chars_humanlike(c: &mut ChatComposer, chars: &[char]) {
for &ch in chars {
let _ = c.handle_key_event(KeyEvent::new(KeyCode::Char(ch), KeyModifiers::NONE));
std::thread::sleep(ChatComposer::recommended_paste_flush_delay());
let _ = c.flush_paste_burst_if_due();
}
}
let count = 32;
- Exact fixtures: keep field names and timestamp formats precise.
// Right
{"ts":"2025-08-09T15:58:15.433Z","dir":"to_tui","kind":"app_event","variant":"RequestRedraw"}
// Wrong
{"ts":"2025-08-09T15:58:15.4F33Z","fdir":"to_tui","kind":"app_event","variant":"RequestRedraw"}
DON’Ts
- Repeat side effects: don’t re-clear state when the flag was already set.
// Don’t: always clear even if already disabled.
self.disable_paste_burst = disabled;
if disabled { self.paste_burst.clear_window_after_non_char(); }
- Use
//where///is required: don’t skimp on doc comments or omit return-value notes.
// Don’t
// Timer: flush buffered burst if timeout elapsed.
- Hide config outside constructors: don’t require callers to set flags post-init without a clear reason.
// Don’t
let mut c = ChatComposer::new(...);
c.set_disable_paste_burst(true); // Wire it through new() instead.
- Fully qualify types repeatedly: don’t write long paths when an import suffices.
// Don’t
pub fn request_redraw_in(&self, dur: std::time::Duration) { /* ... */ }
- Count bytes for heuristics: don’t use
.len()onStringslices for thresholds.
// Don’t
let looks_pastey = grabbed.contains(' ') || grabbed.len() >= 16;
- Leave partial returns: don’t forget a return value in one branch.
// Don’t
if flushed { self.request_redraw(); /* missing return */ }
- Overuse
#[cfg(test)]insidemod tests: don’t gate internals unnecessarily within a test module.
// Don’t
#[cfg(test)]
fn helper_in_mod_tests_only() { /* ... */ }
- Introduce fixture typos: don’t change keys (
dir→fdir) or corrupt timestamps.
// Don’t
{"ts":"...15.4F33Z","fdir":"to_tui", ...}
- Redundant renders: don’t render and also schedule a follow-up in the same frame when a flush just happened.
// Don’t
self.draw_now();
fr.schedule_frame_in(Duration::from_millis(1));
- Aggressive retro-grab: don’t yank preceding text unless the heuristic clearly indicates paste.
// Don’t
begin_with_retro_grabbed(before.to_string(), now); // without checking whitespace/length