mirror of
https://github.com/zed-industries/zed.git
synced 2025-02-05 02:20:10 +00:00
Introduce buffer::Content<'a> struct to share logic with buffer::Snapshot
We want to move a bunch of methods on FoldMap to fold_map::Snapshot. This captures a buffer snapshot, and we'll need a bunch of methods that currently are on Buffer to also be implemented on buffer::Snapshot. This Content reference struct will be a good zero-cost place to store that logic.
This commit is contained in:
parent
be954872d0
commit
09afba9251
2 changed files with 78 additions and 34 deletions
|
@ -1215,8 +1215,8 @@ impl Editor {
|
||||||
String::from_iter(clipboard_chars.by_ref().take(clipboard_selection.len));
|
String::from_iter(clipboard_chars.by_ref().take(clipboard_selection.len));
|
||||||
|
|
||||||
self.buffer.update(cx, |buffer, cx| {
|
self.buffer.update(cx, |buffer, cx| {
|
||||||
let selection_start = selection.start.to_point(buffer);
|
let selection_start = selection.start.to_point(&*buffer);
|
||||||
let selection_end = selection.end.to_point(buffer);
|
let selection_end = selection.end.to_point(&*buffer);
|
||||||
|
|
||||||
// If the corresponding selection was empty when this slice of the
|
// If the corresponding selection was empty when this slice of the
|
||||||
// clipboard text was written, then the entire line containing the
|
// clipboard text was written, then the entire line containing the
|
||||||
|
|
|
@ -601,6 +601,7 @@ impl Buffer {
|
||||||
pub fn snapshot(&self) -> Snapshot {
|
pub fn snapshot(&self) -> Snapshot {
|
||||||
Snapshot {
|
Snapshot {
|
||||||
text: self.visible_text.clone(),
|
text: self.visible_text.clone(),
|
||||||
|
fragments: self.fragments.clone(),
|
||||||
tree: self.syntax_tree(),
|
tree: self.syntax_tree(),
|
||||||
language: self.language.clone(),
|
language: self.language.clone(),
|
||||||
query_cursor: QueryCursorHandle::new(),
|
query_cursor: QueryCursorHandle::new(),
|
||||||
|
@ -1005,10 +1006,6 @@ impl Buffer {
|
||||||
self.visible_text.summary()
|
self.visible_text.summary()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn text_summary_for_range(&self, range: Range<usize>) -> TextSummary {
|
|
||||||
self.visible_text.cursor(range.start).summary(range.end)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn len(&self) -> usize {
|
pub fn len(&self) -> usize {
|
||||||
self.fragments.extent::<usize>(&None)
|
self.fragments.extent::<usize>(&None)
|
||||||
}
|
}
|
||||||
|
@ -1149,7 +1146,7 @@ impl Buffer {
|
||||||
// Skip invalid ranges and coalesce contiguous ones.
|
// Skip invalid ranges and coalesce contiguous ones.
|
||||||
let mut ranges: Vec<Range<usize>> = Vec::new();
|
let mut ranges: Vec<Range<usize>> = Vec::new();
|
||||||
for range in ranges_iter {
|
for range in ranges_iter {
|
||||||
let range = range.start.to_offset(self)..range.end.to_offset(self);
|
let range = range.start.to_offset(&*self)..range.end.to_offset(&*self);
|
||||||
if has_new_text || !range.is_empty() {
|
if has_new_text || !range.is_empty() {
|
||||||
if let Some(prev_range) = ranges.last_mut() {
|
if let Some(prev_range) = ranges.last_mut() {
|
||||||
if prev_range.end >= range.start {
|
if prev_range.end >= range.start {
|
||||||
|
@ -1860,6 +1857,14 @@ impl Buffer {
|
||||||
edit
|
edit
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn content<'a>(&'a self) -> Content<'a> {
|
||||||
|
self.into()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn text_summary_for_range(&self, range: Range<usize>) -> TextSummary {
|
||||||
|
self.content().text_summary_for_range(range)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn anchor_before<T: ToOffset>(&self, position: T) -> Anchor {
|
pub fn anchor_before<T: ToOffset>(&self, position: T) -> Anchor {
|
||||||
self.anchor_at(position, Bias::Left)
|
self.anchor_at(position, Bias::Left)
|
||||||
}
|
}
|
||||||
|
@ -1881,18 +1886,6 @@ impl Buffer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn summary_for_anchor(&self, anchor: &Anchor) -> TextSummary {
|
|
||||||
let cx = Some(anchor.version.clone());
|
|
||||||
let mut cursor = self.fragments.cursor::<VersionedOffset, usize>();
|
|
||||||
cursor.seek(&VersionedOffset::Offset(anchor.offset), anchor.bias, &cx);
|
|
||||||
let overshoot = if cursor.item().map_or(false, |fragment| fragment.visible) {
|
|
||||||
anchor.offset - cursor.seek_start().offset()
|
|
||||||
} else {
|
|
||||||
0
|
|
||||||
};
|
|
||||||
self.text_summary_for_range(0..*cursor.sum_start() + overshoot)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn full_offset_for_anchor(&self, anchor: &Anchor) -> usize {
|
fn full_offset_for_anchor(&self, anchor: &Anchor) -> usize {
|
||||||
let cx = Some(anchor.version.clone());
|
let cx = Some(anchor.version.clone());
|
||||||
let mut cursor = self
|
let mut cursor = self
|
||||||
|
@ -1910,7 +1903,7 @@ impl Buffer {
|
||||||
|
|
||||||
pub fn point_for_offset(&self, offset: usize) -> Result<Point> {
|
pub fn point_for_offset(&self, offset: usize) -> Result<Point> {
|
||||||
if offset <= self.len() {
|
if offset <= self.len() {
|
||||||
Ok(self.text_summary_for_range(0..offset).lines)
|
Ok(self.content().text_summary_for_range(0..offset).lines)
|
||||||
} else {
|
} else {
|
||||||
Err(anyhow!("offset out of bounds"))
|
Err(anyhow!("offset out of bounds"))
|
||||||
}
|
}
|
||||||
|
@ -1957,6 +1950,7 @@ impl Clone for Buffer {
|
||||||
|
|
||||||
pub struct Snapshot {
|
pub struct Snapshot {
|
||||||
text: Rope,
|
text: Rope,
|
||||||
|
fragments: SumTree<Fragment>,
|
||||||
tree: Option<Tree>,
|
tree: Option<Tree>,
|
||||||
language: Option<Arc<Language>>,
|
language: Option<Arc<Language>>,
|
||||||
query_cursor: QueryCursorHandle,
|
query_cursor: QueryCursorHandle,
|
||||||
|
@ -2020,6 +2014,56 @@ impl Snapshot {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct Content<'a> {
|
||||||
|
visible_text: &'a Rope,
|
||||||
|
fragments: &'a SumTree<Fragment>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> From<&'a Snapshot> for Content<'a> {
|
||||||
|
fn from(snapshot: &'a Snapshot) -> Self {
|
||||||
|
Self {
|
||||||
|
visible_text: &snapshot.text,
|
||||||
|
fragments: &snapshot.fragments,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> From<&'a Buffer> for Content<'a> {
|
||||||
|
fn from(buffer: &'a Buffer) -> Self {
|
||||||
|
Self {
|
||||||
|
visible_text: &buffer.visible_text,
|
||||||
|
fragments: &buffer.fragments,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> From<&'a mut Buffer> for Content<'a> {
|
||||||
|
fn from(buffer: &'a mut Buffer) -> Self {
|
||||||
|
Self {
|
||||||
|
visible_text: &buffer.visible_text,
|
||||||
|
fragments: &buffer.fragments,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Content<'a> {
|
||||||
|
fn summary_for_anchor(&self, anchor: &Anchor) -> TextSummary {
|
||||||
|
let cx = Some(anchor.version.clone());
|
||||||
|
let mut cursor = self.fragments.cursor::<VersionedOffset, usize>();
|
||||||
|
cursor.seek(&VersionedOffset::Offset(anchor.offset), anchor.bias, &cx);
|
||||||
|
let overshoot = if cursor.item().map_or(false, |fragment| fragment.visible) {
|
||||||
|
anchor.offset - cursor.seek_start().offset()
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
};
|
||||||
|
self.text_summary_for_range(0..*cursor.sum_start() + overshoot)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn text_summary_for_range(&self, range: Range<usize>) -> TextSummary {
|
||||||
|
self.visible_text.cursor(range.start).summary(range.end)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct RopeBuilder<'a> {
|
struct RopeBuilder<'a> {
|
||||||
old_visible_cursor: rope::Cursor<'a>,
|
old_visible_cursor: rope::Cursor<'a>,
|
||||||
old_deleted_cursor: rope::Cursor<'a>,
|
old_deleted_cursor: rope::Cursor<'a>,
|
||||||
|
@ -2704,46 +2748,46 @@ impl operation_queue::Operation for Operation {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait ToOffset {
|
pub trait ToOffset {
|
||||||
fn to_offset(&self, buffer: &Buffer) -> usize;
|
fn to_offset<'a>(&self, content: impl Into<Content<'a>>) -> usize;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToOffset for Point {
|
impl ToOffset for Point {
|
||||||
fn to_offset(&self, buffer: &Buffer) -> usize {
|
fn to_offset<'a>(&self, content: impl Into<Content<'a>>) -> usize {
|
||||||
buffer.visible_text.to_offset(*self)
|
content.into().visible_text.to_offset(*self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToOffset for usize {
|
impl ToOffset for usize {
|
||||||
fn to_offset(&self, _: &Buffer) -> usize {
|
fn to_offset<'a>(&self, _: impl Into<Content<'a>>) -> usize {
|
||||||
*self
|
*self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToOffset for Anchor {
|
impl ToOffset for Anchor {
|
||||||
fn to_offset(&self, buffer: &Buffer) -> usize {
|
fn to_offset<'a>(&self, content: impl Into<Content<'a>>) -> usize {
|
||||||
buffer.summary_for_anchor(self).bytes
|
content.into().summary_for_anchor(self).bytes
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> ToOffset for &'a Anchor {
|
impl<'a> ToOffset for &'a Anchor {
|
||||||
fn to_offset(&self, buffer: &Buffer) -> usize {
|
fn to_offset<'b>(&self, content: impl Into<Content<'b>>) -> usize {
|
||||||
buffer.summary_for_anchor(self).bytes
|
content.into().summary_for_anchor(self).bytes
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait ToPoint {
|
pub trait ToPoint {
|
||||||
fn to_point(&self, buffer: &Buffer) -> Point;
|
fn to_point<'a>(&self, content: impl Into<Content<'a>>) -> Point;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToPoint for Anchor {
|
impl ToPoint for Anchor {
|
||||||
fn to_point(&self, buffer: &Buffer) -> Point {
|
fn to_point<'a>(&self, content: impl Into<Content<'a>>) -> Point {
|
||||||
buffer.summary_for_anchor(self).lines
|
content.into().summary_for_anchor(self).lines
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToPoint for usize {
|
impl ToPoint for usize {
|
||||||
fn to_point(&self, buffer: &Buffer) -> Point {
|
fn to_point<'a>(&self, content: impl Into<Content<'a>>) -> Point {
|
||||||
buffer.visible_text.to_point(*self)
|
content.into().visible_text.to_point(*self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3411,7 +3455,7 @@ mod tests {
|
||||||
.iter()
|
.iter()
|
||||||
.map(|selection| {
|
.map(|selection| {
|
||||||
assert_eq!(selection.start, selection.end);
|
assert_eq!(selection.start, selection.end);
|
||||||
selection.start.to_point(&buffer)
|
selection.start.to_point(&*buffer)
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
|
Loading…
Reference in a new issue