Introduce AutoindentMode parameter to Buffer::edit

This controls whether or not we preserve the relative indentation
of inserted text blocks.

Co-authored-by: Mikayla Maki <mikayla.c.maki@gmail.com>
This commit is contained in:
Max Brunsfeld 2022-07-28 14:03:31 -07:00
parent cdf6ae25bb
commit fa5af4383d
18 changed files with 308 additions and 236 deletions

View file

@ -7,9 +7,9 @@ use collections::{Bound, HashMap, HashSet};
use gpui::{AppContext, Entity, ModelContext, ModelHandle, Task};
pub use language::Completion;
use language::{
char_kind, Buffer, BufferChunks, BufferSnapshot, CharKind, Chunk, DiagnosticEntry, Event, File,
IndentSize, Language, OffsetRangeExt, Outline, OutlineItem, Selection, ToOffset as _,
ToOffsetUtf16 as _, ToPoint as _, ToPointUtf16 as _, TransactionId,
char_kind, AutoindentMode, Buffer, BufferChunks, BufferSnapshot, CharKind, Chunk,
DiagnosticEntry, Event, File, IndentSize, Language, OffsetRangeExt, Outline, OutlineItem,
Selection, ToOffset as _, ToOffsetUtf16 as _, ToPoint as _, ToPointUtf16 as _, TransactionId,
};
use smallvec::SmallVec;
use std::{
@ -302,28 +302,10 @@ impl MultiBuffer {
self.read(cx).symbols_containing(offset, theme)
}
pub fn edit<I, S, T>(&mut self, edits: I, cx: &mut ModelContext<Self>)
where
I: IntoIterator<Item = (Range<S>, T)>,
S: ToOffset,
T: Into<Arc<str>>,
{
self.edit_internal(edits, false, cx)
}
pub fn edit_with_autoindent<I, S, T>(&mut self, edits: I, cx: &mut ModelContext<Self>)
where
I: IntoIterator<Item = (Range<S>, T)>,
S: ToOffset,
T: Into<Arc<str>>,
{
self.edit_internal(edits, true, cx)
}
pub fn edit_internal<I, S, T>(
pub fn edit<I, S, T>(
&mut self,
edits: I,
autoindent: bool,
autoindent_mode: Option<AutoindentMode>,
cx: &mut ModelContext<Self>,
) where
I: IntoIterator<Item = (Range<S>, T)>,
@ -345,11 +327,7 @@ impl MultiBuffer {
if let Some(buffer) = self.as_singleton() {
return buffer.update(cx, |buffer, cx| {
if autoindent {
buffer.edit_with_autoindent(edits, cx);
} else {
buffer.edit(edits, cx);
}
buffer.edit(edits, autoindent_mode, cx);
});
}
@ -464,13 +442,8 @@ impl MultiBuffer {
}
}
if autoindent {
buffer.edit_with_autoindent(deletions, cx);
buffer.edit_with_autoindent(insertions, cx);
} else {
buffer.edit(deletions, cx);
buffer.edit(insertions, cx);
}
buffer.edit(deletions, autoindent_mode, cx);
buffer.edit(insertions, autoindent_mode, cx);
})
}
}
@ -1386,7 +1359,7 @@ impl MultiBuffer {
log::info!("mutating multi-buffer with {:?}", edits);
drop(snapshot);
self.edit(edits, cx);
self.edit(edits, None, cx);
}
pub fn randomly_edit_excerpts(
@ -3224,7 +3197,7 @@ mod tests {
.collect::<Vec<_>>()
);
buffer.update(cx, |buffer, cx| buffer.edit([(1..3, "XXX\n")], cx));
buffer.update(cx, |buffer, cx| buffer.edit([(1..3, "XXX\n")], None, cx));
let snapshot = multibuffer.read(cx).snapshot(cx);
assert_eq!(snapshot.text(), buffer.read(cx).text());
@ -3247,11 +3220,11 @@ mod tests {
let snapshot = multibuffer.read(cx).snapshot(cx);
assert_eq!(snapshot.text(), "a");
guest_buffer.update(cx, |buffer, cx| buffer.edit([(1..1, "b")], cx));
guest_buffer.update(cx, |buffer, cx| buffer.edit([(1..1, "b")], None, cx));
let snapshot = multibuffer.read(cx).snapshot(cx);
assert_eq!(snapshot.text(), "ab");
guest_buffer.update(cx, |buffer, cx| buffer.edit([(2..2, "c")], cx));
guest_buffer.update(cx, |buffer, cx| buffer.edit([(2..2, "c")], None, cx));
let snapshot = multibuffer.read(cx).snapshot(cx);
assert_eq!(snapshot.text(), "abc");
}
@ -3392,6 +3365,7 @@ mod tests {
(Point::new(0, 0)..Point::new(0, 0), text),
(Point::new(2, 1)..Point::new(2, 3), text),
],
None,
cx,
);
});
@ -3529,8 +3503,8 @@ mod tests {
let multibuffer = cx.add_model(|cx| MultiBuffer::singleton(buffer.clone(), cx));
let old_snapshot = multibuffer.read(cx).snapshot(cx);
buffer.update(cx, |buffer, cx| {
buffer.edit([(0..0, "X")], cx);
buffer.edit([(5..5, "Y")], cx);
buffer.edit([(0..0, "X")], None, cx);
buffer.edit([(5..5, "Y")], None, cx);
});
let new_snapshot = multibuffer.read(cx).snapshot(cx);
@ -3577,12 +3551,12 @@ mod tests {
assert_eq!(Anchor::max().to_offset(&old_snapshot), 10);
buffer_1.update(cx, |buffer, cx| {
buffer.edit([(0..0, "W")], cx);
buffer.edit([(5..5, "X")], cx);
buffer.edit([(0..0, "W")], None, cx);
buffer.edit([(5..5, "X")], None, cx);
});
buffer_2.update(cx, |buffer, cx| {
buffer.edit([(0..0, "Y")], cx);
buffer.edit([(6..6, "Z")], cx);
buffer.edit([(0..0, "Y")], None, cx);
buffer.edit([(6..6, "Z")], None, cx);
});
let new_snapshot = multibuffer.read(cx).snapshot(cx);
@ -3611,7 +3585,7 @@ mod tests {
// Create an insertion id in buffer 1 that doesn't exist in buffer 2.
// Add an excerpt from buffer 1 that spans this new insertion.
buffer_1.update(cx, |buffer, cx| buffer.edit([(4..4, "123")], cx));
buffer_1.update(cx, |buffer, cx| buffer.edit([(4..4, "123")], None, cx));
let excerpt_id_1 = multibuffer.update(cx, |multibuffer, cx| {
multibuffer
.push_excerpts(
@ -4184,6 +4158,7 @@ mod tests {
(Point::new(0, 0)..Point::new(0, 0), "A"),
(Point::new(1, 0)..Point::new(1, 0), "A"),
],
None,
cx,
);
multibuffer.edit(
@ -4191,6 +4166,7 @@ mod tests {
(Point::new(0, 1)..Point::new(0, 1), "B"),
(Point::new(1, 1)..Point::new(1, 1), "B"),
],
None,
cx,
);
multibuffer.end_transaction_at(now, cx);
@ -4199,19 +4175,19 @@ mod tests {
// Edit buffer 1 through the multibuffer
now += 2 * group_interval;
multibuffer.start_transaction_at(now, cx);
multibuffer.edit([(2..2, "C")], cx);
multibuffer.edit([(2..2, "C")], None, cx);
multibuffer.end_transaction_at(now, cx);
assert_eq!(multibuffer.read(cx).text(), "ABC1234\nAB5678");
// Edit buffer 1 independently
buffer_1.update(cx, |buffer_1, cx| {
buffer_1.start_transaction_at(now);
buffer_1.edit([(3..3, "D")], cx);
buffer_1.edit([(3..3, "D")], None, cx);
buffer_1.end_transaction_at(now, cx);
now += 2 * group_interval;
buffer_1.start_transaction_at(now);
buffer_1.edit([(4..4, "E")], cx);
buffer_1.edit([(4..4, "E")], None, cx);
buffer_1.end_transaction_at(now, cx);
});
assert_eq!(multibuffer.read(cx).text(), "ABCDE1234\nAB5678");
@ -4252,7 +4228,7 @@ mod tests {
// Redo stack gets cleared after an edit.
now += 2 * group_interval;
multibuffer.start_transaction_at(now, cx);
multibuffer.edit([(0..0, "X")], cx);
multibuffer.edit([(0..0, "X")], None, cx);
multibuffer.end_transaction_at(now, cx);
assert_eq!(multibuffer.read(cx).text(), "XABCD1234\nAB5678");
multibuffer.redo(cx);