mirror of
https://github.com/openai/codex.git
synced 2026-09-16 12:13:30 +00:00
Fix large paste placeholder numbering after deletion
This commit is contained in:
@@ -256,7 +256,6 @@ pub(crate) struct ChatComposer {
|
||||
dismissed_file_popup_token: Option<String>,
|
||||
current_file_query: Option<String>,
|
||||
pending_pastes: Vec<(String, String)>,
|
||||
large_paste_counters: HashMap<usize, usize>,
|
||||
has_focus: bool,
|
||||
/// Invariant: attached images are labeled `[Image #1]..[Image #N]` in vec order.
|
||||
attached_images: Vec<AttachedImage>,
|
||||
@@ -347,7 +346,6 @@ impl ChatComposer {
|
||||
dismissed_file_popup_token: None,
|
||||
current_file_query: None,
|
||||
pending_pastes: Vec::new(),
|
||||
large_paste_counters: HashMap::new(),
|
||||
has_focus: has_input_focus,
|
||||
attached_images: Vec::new(),
|
||||
placeholder_text,
|
||||
@@ -891,14 +889,27 @@ impl ChatComposer {
|
||||
.is_some_and(|expires_at| Instant::now() < expires_at)
|
||||
}
|
||||
|
||||
fn next_large_paste_placeholder(&mut self, char_count: usize) -> String {
|
||||
fn next_large_paste_placeholder(&self, char_count: usize) -> String {
|
||||
let base = format!("[Pasted Content {char_count} chars]");
|
||||
let next_suffix = self.large_paste_counters.entry(char_count).or_insert(0);
|
||||
*next_suffix += 1;
|
||||
if *next_suffix == 1 {
|
||||
let prefix = format!("{base} #");
|
||||
let mut max_suffix = 0usize;
|
||||
|
||||
for (placeholder, _) in &self.pending_pastes {
|
||||
if placeholder == &base {
|
||||
max_suffix = max_suffix.max(1);
|
||||
continue;
|
||||
}
|
||||
if let Some(suffix) = placeholder.strip_prefix(&prefix)
|
||||
&& let Ok(value) = suffix.parse::<usize>()
|
||||
{
|
||||
max_suffix = max_suffix.max(value);
|
||||
}
|
||||
}
|
||||
|
||||
if max_suffix == 0 {
|
||||
base
|
||||
} else {
|
||||
format!("{base} #{next_suffix}")
|
||||
format!("{base} #{}", max_suffix + 1)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4662,8 +4673,8 @@ mod tests {
|
||||
assert_eq!(composer.pending_pastes[0].1, paste);
|
||||
}
|
||||
|
||||
/// Behavior: large-paste placeholder numbering does not get reused after deletion, so a new
|
||||
/// paste of the same length gets a new unique placeholder label.
|
||||
/// Behavior: large-paste placeholder numbering continues when another placeholder of the
|
||||
/// same length still exists, so a new paste gets a new unique placeholder label.
|
||||
#[test]
|
||||
fn large_paste_numbering_does_not_reuse_after_deletion() {
|
||||
use crossterm::event::KeyCode;
|
||||
@@ -4704,6 +4715,42 @@ mod tests {
|
||||
assert_eq!(composer.pending_pastes[1].0, third);
|
||||
}
|
||||
|
||||
/// Behavior: if all placeholders of a given length are removed, numbering resets to the
|
||||
/// base placeholder on the next paste.
|
||||
#[test]
|
||||
fn large_paste_numbering_reuses_after_all_deleted() {
|
||||
use crossterm::event::KeyCode;
|
||||
use crossterm::event::KeyEvent;
|
||||
use crossterm::event::KeyModifiers;
|
||||
|
||||
let (tx, _rx) = unbounded_channel::<AppEvent>();
|
||||
let sender = AppEventSender::new(tx);
|
||||
let mut composer = ChatComposer::new(
|
||||
true,
|
||||
sender,
|
||||
false,
|
||||
"Ask Codex to do anything".to_string(),
|
||||
false,
|
||||
);
|
||||
|
||||
let paste = "x".repeat(LARGE_PASTE_CHAR_THRESHOLD + 4);
|
||||
let base = format!("[Pasted Content {} chars]", paste.chars().count());
|
||||
|
||||
composer.handle_paste(paste.clone());
|
||||
assert_eq!(composer.textarea.text(), base);
|
||||
assert_eq!(composer.pending_pastes.len(), 1);
|
||||
|
||||
composer.textarea.set_cursor(composer.textarea.text().len());
|
||||
composer.handle_key_event(KeyEvent::new(KeyCode::Backspace, KeyModifiers::NONE));
|
||||
assert!(composer.textarea.text().is_empty());
|
||||
assert!(composer.pending_pastes.is_empty());
|
||||
|
||||
composer.handle_paste(paste);
|
||||
assert_eq!(composer.textarea.text(), base);
|
||||
assert_eq!(composer.pending_pastes.len(), 1);
|
||||
assert_eq!(composer.pending_pastes[0].0, base);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_partial_placeholder_deletion() {
|
||||
use crossterm::event::KeyCode;
|
||||
|
||||
Reference in New Issue
Block a user