mirror of
https://github.com/zed-industries/zed.git
synced 2025-02-04 10:12:47 +00:00
Merge pull request #980 from zed-industries/coerce-multibuffer-changes
Filter overlapping multibuffer edits
This commit is contained in:
commit
93f8f47cc0
3 changed files with 48 additions and 48 deletions
|
@ -9801,55 +9801,49 @@ mod tests {
|
|||
#[gpui::test]
|
||||
fn test_editing_overlapping_excerpts(cx: &mut gpui::MutableAppContext) {
|
||||
cx.set_global(Settings::test(cx));
|
||||
let buffer = cx.add_model(|cx| Buffer::new(0, sample_text(3, 4, 'a'), cx));
|
||||
let (initial_text, excerpt_ranges) = marked_text_ranges(indoc! {"
|
||||
[aaaa
|
||||
(bbbb]
|
||||
cccc)"});
|
||||
let buffer = cx.add_model(|cx| Buffer::new(0, initial_text, cx));
|
||||
let multibuffer = cx.add_model(|cx| {
|
||||
let mut multibuffer = MultiBuffer::new(0);
|
||||
multibuffer.push_excerpts(
|
||||
buffer,
|
||||
[
|
||||
Point::new(0, 0)..Point::new(1, 4),
|
||||
Point::new(1, 0)..Point::new(2, 4),
|
||||
],
|
||||
cx,
|
||||
);
|
||||
multibuffer.push_excerpts(buffer, excerpt_ranges, cx);
|
||||
multibuffer
|
||||
});
|
||||
|
||||
assert_eq!(
|
||||
multibuffer.read(cx).read(cx).text(),
|
||||
"aaaa\nbbbb\nbbbb\ncccc"
|
||||
);
|
||||
|
||||
let (_, view) = cx.add_window(Default::default(), |cx| build_editor(multibuffer, cx));
|
||||
view.update(cx, |view, cx| {
|
||||
view.select_ranges(
|
||||
[
|
||||
Point::new(1, 1)..Point::new(1, 1),
|
||||
Point::new(2, 3)..Point::new(2, 3),
|
||||
],
|
||||
None,
|
||||
cx,
|
||||
);
|
||||
let (expected_text, selection_ranges) = marked_text_ranges(indoc! {"
|
||||
aaaa
|
||||
b|bbb
|
||||
b|bb|b
|
||||
cccc"});
|
||||
assert_eq!(view.text(cx), expected_text);
|
||||
view.select_ranges(selection_ranges, None, cx);
|
||||
|
||||
view.handle_input(&Input("X".to_string()), cx);
|
||||
assert_eq!(view.text(cx), "aaaa\nbXbbXb\nbXbbXb\ncccc");
|
||||
assert_eq!(
|
||||
view.selected_ranges(cx),
|
||||
[
|
||||
Point::new(1, 2)..Point::new(1, 2),
|
||||
Point::new(2, 5)..Point::new(2, 5),
|
||||
]
|
||||
);
|
||||
|
||||
let (expected_text, expected_selections) = marked_text_ranges(indoc! {"
|
||||
aaaa
|
||||
bX|bbXb
|
||||
bX|bbX|b
|
||||
cccc"});
|
||||
assert_eq!(view.text(cx), expected_text);
|
||||
assert_eq!(view.selected_ranges(cx), expected_selections);
|
||||
|
||||
view.newline(&Newline, cx);
|
||||
assert_eq!(view.text(cx), "aaaa\nbX\nbbX\nb\nbX\nbbX\nb\ncccc");
|
||||
assert_eq!(
|
||||
view.selected_ranges(cx),
|
||||
[
|
||||
Point::new(2, 0)..Point::new(2, 0),
|
||||
Point::new(6, 0)..Point::new(6, 0),
|
||||
]
|
||||
);
|
||||
let (expected_text, expected_selections) = marked_text_ranges(indoc! {"
|
||||
aaaa
|
||||
bX
|
||||
|bbX
|
||||
b
|
||||
bX
|
||||
|bbX
|
||||
|b
|
||||
cccc"});
|
||||
assert_eq!(view.text(cx), expected_text);
|
||||
assert_eq!(view.selected_ranges(cx), expected_selections);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -378,13 +378,11 @@ impl MultiBuffer {
|
|||
let mut insertions = Vec::new();
|
||||
let mut deletions = Vec::new();
|
||||
let empty_str: Arc<str> = "".into();
|
||||
while let Some((mut range, mut new_text, mut is_insertion)) = edits.next() {
|
||||
while let Some((next_range, next_new_text, next_is_insertion)) =
|
||||
edits.peek()
|
||||
{
|
||||
while let Some((mut range, new_text, mut is_insertion)) = edits.next() {
|
||||
while let Some((next_range, _, next_is_insertion)) = edits.peek() {
|
||||
if range.end >= next_range.start {
|
||||
range.end = cmp::max(next_range.end, range.end);
|
||||
new_text = format!("{new_text}{next_new_text}").into();
|
||||
|
||||
is_insertion |= *next_is_insertion;
|
||||
edits.next();
|
||||
} else {
|
||||
|
@ -395,7 +393,7 @@ impl MultiBuffer {
|
|||
if is_insertion {
|
||||
insertions.push((
|
||||
buffer.anchor_before(range.start)..buffer.anchor_before(range.end),
|
||||
new_text,
|
||||
new_text.clone(),
|
||||
));
|
||||
} else if !range.is_empty() {
|
||||
deletions.push((
|
||||
|
|
|
@ -55,10 +55,18 @@ pub fn marked_text_ranges_by(
|
|||
(unmarked_text, range_lookup)
|
||||
}
|
||||
|
||||
pub fn marked_text_ranges(marked_text: &str) -> (String, Vec<Range<usize>>) {
|
||||
let (unmarked_text, mut ranges) = marked_text_ranges_by(marked_text, vec![('[', ']')]);
|
||||
// Returns ranges delimited by (), [], and <> ranges. Ranges using the same markers
|
||||
// must not be overlapping. May also include | for empty ranges
|
||||
pub fn marked_text_ranges(full_marked_text: &str) -> (String, Vec<Range<usize>>) {
|
||||
let (range_marked_text, empty_offsets) = marked_text(full_marked_text);
|
||||
let (unmarked, range_lookup) =
|
||||
marked_text_ranges_by(&range_marked_text, vec![('[', ']'), ('(', ')'), ('<', '>')]);
|
||||
(
|
||||
unmarked_text,
|
||||
ranges.remove(&('[', ']')).unwrap_or_else(Vec::new),
|
||||
unmarked,
|
||||
range_lookup
|
||||
.into_values()
|
||||
.flatten()
|
||||
.chain(empty_offsets.into_iter().map(|offset| offset..offset))
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue