Avoid inserting redundant newlines
Co-Authored-By: Piotr Osiewicz <piotr@zed.dev> Co-Authored-By: Antonio Scandurra <antonio@zed.dev>
This commit is contained in:
parent
ef6cb11d5c
commit
6c0f65cfe0
1 changed files with 155 additions and 20 deletions
|
@ -736,18 +736,33 @@ impl Assistant {
|
|||
}
|
||||
|
||||
let role = metadata.role;
|
||||
let is_newline = self.buffer.update(cx, |buffer, cx| {
|
||||
if buffer.chars_at(range.end).next() != Some('\n') {
|
||||
buffer.edit([(range.end..range.end, "\n")], None, cx);
|
||||
false
|
||||
} else {
|
||||
true
|
||||
let mut edited_buffer = false;
|
||||
|
||||
let mut suffix_start = None;
|
||||
if range.start > message_range.start && range.end < message_range.end - 1 {
|
||||
if self.buffer.read(cx).chars_at(range.end).next() == Some('\n') {
|
||||
suffix_start = Some(range.end + 1);
|
||||
} else if self.buffer.read(cx).reversed_chars_at(range.end).next() == Some('\n') {
|
||||
suffix_start = Some(range.end);
|
||||
}
|
||||
}
|
||||
|
||||
let suffix = if let Some(suffix_start) = suffix_start {
|
||||
Message {
|
||||
id: MessageId(post_inc(&mut self.next_message_id.0)),
|
||||
start: self.buffer.read(cx).anchor_before(suffix_start),
|
||||
}
|
||||
} else {
|
||||
self.buffer.update(cx, |buffer, cx| {
|
||||
buffer.edit([(range.end..range.end, "\n")], None, cx);
|
||||
});
|
||||
edited_buffer = true;
|
||||
Message {
|
||||
id: MessageId(post_inc(&mut self.next_message_id.0)),
|
||||
start: self.buffer.read(cx).anchor_before(range.end + 1),
|
||||
}
|
||||
});
|
||||
let suffix = Message {
|
||||
id: MessageId(post_inc(&mut self.next_message_id.0)),
|
||||
start: self.buffer.read(cx).anchor_before(range.end + 1),
|
||||
};
|
||||
|
||||
self.messages.insert(start_message_ix + 1, suffix.clone());
|
||||
self.messages_metadata.insert(
|
||||
suffix.id,
|
||||
|
@ -757,19 +772,38 @@ impl Assistant {
|
|||
error: None,
|
||||
},
|
||||
);
|
||||
if is_newline {
|
||||
cx.emit(AssistantEvent::MessagesEdited);
|
||||
}
|
||||
if range.start == range.end || range.start == message_range.start {
|
||||
|
||||
let new_messages = if range.start == range.end || range.start == message_range.start {
|
||||
(None, Some(suffix))
|
||||
} else {
|
||||
self.buffer.update(cx, |buffer, cx| {
|
||||
buffer.edit([(range.start..range.start, "\n")], None, cx)
|
||||
});
|
||||
let selection = Message {
|
||||
id: MessageId(post_inc(&mut self.next_message_id.0)),
|
||||
start: self.buffer.read(cx).anchor_before(range.start + 1),
|
||||
let mut prefix_end = None;
|
||||
if range.start > message_range.start && range.end < message_range.end - 1 {
|
||||
if self.buffer.read(cx).chars_at(range.start).next() == Some('\n') {
|
||||
prefix_end = Some(range.start + 1);
|
||||
} else if self.buffer.read(cx).reversed_chars_at(range.start).next()
|
||||
== Some('\n')
|
||||
{
|
||||
prefix_end = Some(range.start);
|
||||
}
|
||||
}
|
||||
|
||||
let selection = if let Some(prefix_end) = prefix_end {
|
||||
cx.emit(AssistantEvent::MessagesEdited);
|
||||
Message {
|
||||
id: MessageId(post_inc(&mut self.next_message_id.0)),
|
||||
start: self.buffer.read(cx).anchor_before(prefix_end),
|
||||
}
|
||||
} else {
|
||||
self.buffer.update(cx, |buffer, cx| {
|
||||
buffer.edit([(range.start..range.start, "\n")], None, cx)
|
||||
});
|
||||
edited_buffer = true;
|
||||
Message {
|
||||
id: MessageId(post_inc(&mut self.next_message_id.0)),
|
||||
start: self.buffer.read(cx).anchor_before(range.end + 1),
|
||||
}
|
||||
};
|
||||
|
||||
self.messages
|
||||
.insert(start_message_ix + 1, selection.clone());
|
||||
self.messages_metadata.insert(
|
||||
|
@ -781,7 +815,12 @@ impl Assistant {
|
|||
},
|
||||
);
|
||||
(Some(selection), Some(suffix))
|
||||
};
|
||||
|
||||
if !edited_buffer {
|
||||
cx.emit(AssistantEvent::MessagesEdited);
|
||||
}
|
||||
new_messages
|
||||
} else {
|
||||
(None, None)
|
||||
}
|
||||
|
@ -1594,8 +1633,11 @@ mod tests {
|
|||
(message_3.id, Role::User, 5..6)
|
||||
]
|
||||
);
|
||||
|
||||
let (message_6, message_7) =
|
||||
assistant.update(cx, |assistant, cx| assistant.split_message(2..3, cx));
|
||||
|
||||
assert_eq!(buffer.read(cx).text(), "1C\n3\n\n\nD"); // We insert a newline for the new empty message
|
||||
let (message_6, message_7) = (message_6.unwrap(), message_7.unwrap());
|
||||
assert_eq!(
|
||||
messages(&assistant, cx),
|
||||
|
@ -1626,6 +1668,99 @@ mod tests {
|
|||
);
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
fn test_message_splitting(cx: &mut AppContext) {
|
||||
let registry = Arc::new(LanguageRegistry::test());
|
||||
let assistant = cx.add_model(|cx| Assistant::new(Default::default(), registry, cx));
|
||||
let buffer = assistant.read(cx).buffer.clone();
|
||||
|
||||
let message_1 = assistant.read(cx).messages[0].clone();
|
||||
assert_eq!(
|
||||
messages(&assistant, cx),
|
||||
vec![(message_1.id, Role::User, 0..0)]
|
||||
);
|
||||
|
||||
buffer.update(cx, |buffer, cx| {
|
||||
buffer.edit([(0..0, "aaa\nbbb\nccc\nddd\n")], None, cx)
|
||||
});
|
||||
|
||||
let (_, message_2) =
|
||||
assistant.update(cx, |assistant, cx| assistant.split_message(3..3, cx));
|
||||
let message_2 = message_2.unwrap();
|
||||
|
||||
// We recycle newlines in the middle of a split message
|
||||
assert_eq!(buffer.read(cx).text(), "aaa\nbbb\nccc\nddd\n");
|
||||
assert_eq!(
|
||||
messages(&assistant, cx),
|
||||
vec![
|
||||
(message_1.id, Role::User, 0..4),
|
||||
(message_2.id, Role::User, 4..16),
|
||||
]
|
||||
);
|
||||
|
||||
let (_, message_3) =
|
||||
assistant.update(cx, |assistant, cx| assistant.split_message(3..3, cx));
|
||||
let message_3 = message_3.unwrap();
|
||||
|
||||
// We don't recycle newlines at the end of a split message
|
||||
assert_eq!(buffer.read(cx).text(), "aaa\n\nbbb\nccc\nddd\n");
|
||||
assert_eq!(
|
||||
messages(&assistant, cx),
|
||||
vec![
|
||||
(message_1.id, Role::User, 0..4),
|
||||
(message_3.id, Role::User, 4..5),
|
||||
(message_2.id, Role::User, 5..17),
|
||||
]
|
||||
);
|
||||
|
||||
let (_, message_4) =
|
||||
assistant.update(cx, |assistant, cx| assistant.split_message(9..9, cx));
|
||||
let message_4 = message_4.unwrap();
|
||||
assert_eq!(buffer.read(cx).text(), "aaa\n\nbbb\nccc\nddd\n");
|
||||
assert_eq!(
|
||||
messages(&assistant, cx),
|
||||
vec![
|
||||
(message_1.id, Role::User, 0..4),
|
||||
(message_3.id, Role::User, 4..5),
|
||||
(message_2.id, Role::User, 5..9),
|
||||
(message_4.id, Role::User, 9..17),
|
||||
]
|
||||
);
|
||||
|
||||
let (_, message_5) =
|
||||
assistant.update(cx, |assistant, cx| assistant.split_message(9..9, cx));
|
||||
let message_5 = message_5.unwrap();
|
||||
assert_eq!(buffer.read(cx).text(), "aaa\n\nbbb\n\nccc\nddd\n");
|
||||
assert_eq!(
|
||||
messages(&assistant, cx),
|
||||
vec![
|
||||
(message_1.id, Role::User, 0..4),
|
||||
(message_3.id, Role::User, 4..5),
|
||||
(message_2.id, Role::User, 5..9),
|
||||
(message_4.id, Role::User, 9..10),
|
||||
(message_5.id, Role::User, 10..18),
|
||||
]
|
||||
);
|
||||
|
||||
let (message_6, message_7) =
|
||||
assistant.update(cx, |assistant, cx| assistant.split_message(14..16, cx));
|
||||
let message_6 = message_6.unwrap();
|
||||
let message_7 = message_7.unwrap();
|
||||
assert_eq!(buffer.read(cx).text(), "aaa\n\nbbb\n\nccc\ndd\nd\n");
|
||||
assert_eq!(
|
||||
messages(&assistant, cx),
|
||||
vec![
|
||||
(message_1.id, Role::User, 0..4),
|
||||
(message_3.id, Role::User, 4..5),
|
||||
(message_2.id, Role::User, 5..9),
|
||||
(message_4.id, Role::User, 9..10),
|
||||
(message_5.id, Role::User, 10..14),
|
||||
(message_6.id, Role::User, 14..17),
|
||||
(message_7.id, Role::User, 17..19),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
fn messages(
|
||||
assistant: &ModelHandle<Assistant>,
|
||||
cx: &AppContext,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue