Move multi_buffer to editor crate
This commit is contained in:
parent
6caf016df9
commit
c8b43e3078
16 changed files with 44 additions and 47 deletions
|
@ -3,13 +3,11 @@ mod fold_map;
|
|||
mod tab_map;
|
||||
mod wrap_map;
|
||||
|
||||
use crate::{Anchor, MultiBuffer, MultiBufferSnapshot, ToOffset, ToPoint};
|
||||
use block_map::{BlockMap, BlockPoint};
|
||||
use fold_map::{FoldMap, ToFoldPoint as _};
|
||||
use gpui::{fonts::FontId, ElementBox, Entity, ModelContext, ModelHandle};
|
||||
use language::{
|
||||
multi_buffer::{Anchor, MultiBuffer, MultiBufferSnapshot, ToOffset, ToPoint},
|
||||
Point, Subscription as BufferSubscription,
|
||||
};
|
||||
use language::{Point, Subscription as BufferSubscription};
|
||||
use std::{
|
||||
collections::{HashMap, HashSet},
|
||||
ops::Range,
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
use super::wrap_map::{self, WrapEdit, WrapPoint, WrapSnapshot};
|
||||
use crate::{Anchor, ToOffset, ToPoint as _};
|
||||
use gpui::{AppContext, ElementBox};
|
||||
use language::{
|
||||
multi_buffer::{Anchor, ToOffset, ToPoint as _},
|
||||
Chunk,
|
||||
};
|
||||
use language::Chunk;
|
||||
use parking_lot::Mutex;
|
||||
use std::{
|
||||
cmp::{self, Ordering},
|
||||
|
@ -866,8 +864,8 @@ fn offset_for_row(s: &str, target: u32) -> (u32, usize) {
|
|||
mod tests {
|
||||
use super::*;
|
||||
use crate::display_map::{fold_map::FoldMap, tab_map::TabMap, wrap_map::WrapMap};
|
||||
use crate::multi_buffer::MultiBuffer;
|
||||
use gpui::{elements::Empty, Element};
|
||||
use language::multi_buffer::MultiBuffer;
|
||||
use rand::prelude::*;
|
||||
use std::env;
|
||||
use text::RandomCharIter;
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
use language::{
|
||||
multi_buffer::{Anchor, AnchorRangeExt, MultiBufferChunks, MultiBufferSnapshot, ToOffset},
|
||||
Chunk, Edit, Point, PointUtf16, TextSummary,
|
||||
};
|
||||
use crate::{Anchor, AnchorRangeExt, MultiBufferChunks, MultiBufferSnapshot, ToOffset};
|
||||
use language::{Chunk, Edit, Point, PointUtf16, TextSummary};
|
||||
use parking_lot::Mutex;
|
||||
use std::{
|
||||
cmp::{self, Ordering},
|
||||
|
@ -1057,8 +1055,7 @@ pub type FoldEdit = Edit<FoldOffset>;
|
|||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::ToPoint;
|
||||
use language::multi_buffer::MultiBuffer;
|
||||
use crate::{MultiBuffer, ToPoint};
|
||||
use rand::prelude::*;
|
||||
use std::{env, mem};
|
||||
use text::RandomCharIter;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use super::fold_map::{self, FoldEdit, FoldPoint, FoldSnapshot, ToFoldPoint};
|
||||
use language::{multi_buffer::MultiBufferSnapshot, rope, Chunk};
|
||||
use crate::MultiBufferSnapshot;
|
||||
use language::{rope, Chunk};
|
||||
use parking_lot::Mutex;
|
||||
use std::{cmp, mem, ops::Range};
|
||||
use sum_tree::Bias;
|
||||
|
@ -438,8 +439,7 @@ impl<'a> Iterator for TabChunks<'a> {
|
|||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::display_map::fold_map::FoldMap;
|
||||
use language::multi_buffer::MultiBuffer;
|
||||
use crate::{display_map::fold_map::FoldMap, MultiBuffer};
|
||||
use rand::{prelude::StdRng, Rng};
|
||||
use text::{RandomCharIter, Rope};
|
||||
|
||||
|
|
|
@ -2,11 +2,12 @@ use super::{
|
|||
fold_map,
|
||||
tab_map::{self, TabEdit, TabPoint, TabSnapshot},
|
||||
};
|
||||
use crate::{MultiBufferSnapshot, Point};
|
||||
use gpui::{
|
||||
fonts::FontId, text_layout::LineWrapper, Entity, ModelContext, ModelHandle, MutableAppContext,
|
||||
Task,
|
||||
};
|
||||
use language::{multi_buffer::MultiBufferSnapshot, Chunk, Point};
|
||||
use language::Chunk;
|
||||
use lazy_static::lazy_static;
|
||||
use smol::future::yield_now;
|
||||
use std::{collections::VecDeque, mem, ops::Range, time::Duration};
|
||||
|
@ -977,8 +978,9 @@ mod tests {
|
|||
use crate::{
|
||||
display_map::{fold_map::FoldMap, tab_map::TabMap},
|
||||
test::Observer,
|
||||
MultiBuffer,
|
||||
};
|
||||
use language::{multi_buffer::MultiBuffer, RandomCharIter};
|
||||
use language::RandomCharIter;
|
||||
use rand::prelude::*;
|
||||
use std::{cmp, env};
|
||||
use text::Rope;
|
||||
|
|
|
@ -2,6 +2,7 @@ pub mod display_map;
|
|||
mod element;
|
||||
pub mod items;
|
||||
pub mod movement;
|
||||
mod multi_buffer;
|
||||
|
||||
#[cfg(test)]
|
||||
mod test;
|
||||
|
@ -21,12 +22,14 @@ use gpui::{
|
|||
};
|
||||
use items::BufferItemHandle;
|
||||
use language::{
|
||||
multi_buffer::{
|
||||
Anchor, AnchorRangeExt, MultiBuffer, MultiBufferSnapshot, SelectionSet, ToOffset, ToPoint,
|
||||
},
|
||||
BracketPair, Buffer, Diagnostic, DiagnosticSeverity, Language, Point, Selection, SelectionGoal,
|
||||
SelectionSetId,
|
||||
};
|
||||
use multi_buffer::{
|
||||
Anchor, AnchorRangeExt, MultiBufferChunks, MultiBufferSnapshot,
|
||||
SelectionSet, ToOffset, ToPoint,
|
||||
};
|
||||
pub use multi_buffer::MultiBuffer;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use smallvec::SmallVec;
|
||||
use smol::Timer;
|
||||
|
|
|
@ -4,6 +4,7 @@ use super::{
|
|||
DisplayPoint, Editor, EditorMode, EditorSettings, EditorSnapshot, EditorStyle, Input, Scroll,
|
||||
Select, SelectPhase, SoftWrap, MAX_LINE_LEN,
|
||||
};
|
||||
use crate::ToPoint;
|
||||
use clock::ReplicaId;
|
||||
use gpui::{
|
||||
color::Color,
|
||||
|
@ -19,7 +20,7 @@ use gpui::{
|
|||
MutableAppContext, PaintContext, Quad, Scene, SizeConstraint, ViewContext, WeakViewHandle,
|
||||
};
|
||||
use json::json;
|
||||
use language::{multi_buffer::ToPoint, Chunk};
|
||||
use language::Chunk;
|
||||
use smallvec::SmallVec;
|
||||
use std::{
|
||||
cmp::{self, Ordering},
|
||||
|
@ -1162,8 +1163,7 @@ fn scale_horizontal_mouse_autoscroll_delta(delta: f32) -> f32 {
|
|||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::{Editor, EditorSettings};
|
||||
use language::{MultiBuffer};
|
||||
use crate::{Editor, EditorSettings, MultiBuffer};
|
||||
use util::test::sample_text;
|
||||
|
||||
#[gpui::test]
|
||||
|
|
|
@ -1,14 +1,12 @@
|
|||
use crate::{Editor, EditorSettings, Event};
|
||||
use crate::{MultiBuffer, ToPoint as _};
|
||||
use anyhow::Result;
|
||||
use gpui::{
|
||||
elements::*, fonts::TextStyle, AppContext, Entity, ModelContext, ModelHandle,
|
||||
MutableAppContext, RenderContext, Subscription, Task, View, ViewContext, ViewHandle,
|
||||
WeakModelHandle,
|
||||
};
|
||||
use language::{
|
||||
multi_buffer::{MultiBuffer, ToPoint as _},
|
||||
Diagnostic, File as _,
|
||||
};
|
||||
use language::{Diagnostic, File as _};
|
||||
use postage::watch;
|
||||
use project::{ProjectPath, Worktree};
|
||||
use std::fmt::Write;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use super::{Bias, DisplayPoint, DisplaySnapshot, SelectionGoal, ToDisplayPoint};
|
||||
use crate::ToPoint;
|
||||
use anyhow::Result;
|
||||
use language::multi_buffer::ToPoint;
|
||||
use std::{cmp, ops::Range};
|
||||
|
||||
pub fn left(map: &DisplaySnapshot, mut point: DisplayPoint) -> Result<DisplayPoint> {
|
||||
|
@ -244,8 +244,7 @@ fn char_kind(c: char) -> CharKind {
|
|||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::display_map::DisplayMap;
|
||||
use language::MultiBuffer;
|
||||
use crate::{DisplayMap, MultiBuffer};
|
||||
|
||||
#[gpui::test]
|
||||
fn test_prev_next_word_boundary_multibyte(cx: &mut gpui::MutableAppContext) {
|
||||
|
|
1734
crates/editor/src/multi_buffer.rs
Normal file
1734
crates/editor/src/multi_buffer.rs
Normal file
File diff suppressed because it is too large
Load diff
113
crates/editor/src/multi_buffer/anchor.rs
Normal file
113
crates/editor/src/multi_buffer/anchor.rs
Normal file
|
@ -0,0 +1,113 @@
|
|||
use super::{ExcerptId, MultiBufferSnapshot, ToOffset, ToPoint};
|
||||
use anyhow::{anyhow, Result};
|
||||
use std::{
|
||||
cmp::Ordering,
|
||||
ops::{Range, Sub},
|
||||
};
|
||||
use sum_tree::Bias;
|
||||
use text::{rope::TextDimension, Point};
|
||||
|
||||
#[derive(Clone, Eq, PartialEq, Debug, Hash)]
|
||||
pub struct Anchor {
|
||||
pub(crate) excerpt_id: ExcerptId,
|
||||
pub(crate) text_anchor: text::Anchor,
|
||||
}
|
||||
|
||||
impl Anchor {
|
||||
pub fn min() -> Self {
|
||||
Self {
|
||||
excerpt_id: ExcerptId::min(),
|
||||
text_anchor: text::Anchor::min(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn max() -> Self {
|
||||
Self {
|
||||
excerpt_id: ExcerptId::max(),
|
||||
text_anchor: text::Anchor::max(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn cmp<'a>(&self, other: &Anchor, snapshot: &MultiBufferSnapshot) -> Result<Ordering> {
|
||||
let excerpt_id_cmp = self.excerpt_id.cmp(&other.excerpt_id);
|
||||
if excerpt_id_cmp.is_eq() {
|
||||
if self.excerpt_id == ExcerptId::max() {
|
||||
return Ok(Ordering::Equal);
|
||||
}
|
||||
self.text_anchor.cmp(
|
||||
&other.text_anchor,
|
||||
snapshot
|
||||
.buffer_snapshot_for_excerpt(&self.excerpt_id)
|
||||
.ok_or_else(|| anyhow!("excerpt {:?} not found", self.excerpt_id))?,
|
||||
)
|
||||
} else {
|
||||
return Ok(excerpt_id_cmp);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn bias_left(&self, snapshot: &MultiBufferSnapshot) -> Anchor {
|
||||
if self.text_anchor.bias != Bias::Left {
|
||||
if let Some(buffer_snapshot) = snapshot.buffer_snapshot_for_excerpt(&self.excerpt_id) {
|
||||
return Self {
|
||||
excerpt_id: self.excerpt_id.clone(),
|
||||
text_anchor: self.text_anchor.bias_left(buffer_snapshot),
|
||||
};
|
||||
}
|
||||
}
|
||||
self.clone()
|
||||
}
|
||||
|
||||
pub fn bias_right(&self, snapshot: &MultiBufferSnapshot) -> Anchor {
|
||||
if self.text_anchor.bias != Bias::Right {
|
||||
if let Some(buffer_snapshot) = snapshot.buffer_snapshot_for_excerpt(&self.excerpt_id) {
|
||||
return Self {
|
||||
excerpt_id: self.excerpt_id.clone(),
|
||||
text_anchor: self.text_anchor.bias_right(buffer_snapshot),
|
||||
};
|
||||
}
|
||||
}
|
||||
self.clone()
|
||||
}
|
||||
|
||||
pub fn summary<D>(&self, snapshot: &MultiBufferSnapshot) -> D
|
||||
where
|
||||
D: TextDimension + Ord + Sub<D, Output = D>,
|
||||
{
|
||||
snapshot.summary_for_anchor(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl ToOffset for Anchor {
|
||||
fn to_offset<'a>(&self, snapshot: &MultiBufferSnapshot) -> usize {
|
||||
self.summary(snapshot)
|
||||
}
|
||||
}
|
||||
|
||||
impl ToPoint for Anchor {
|
||||
fn to_point<'a>(&self, snapshot: &MultiBufferSnapshot) -> Point {
|
||||
self.summary(snapshot)
|
||||
}
|
||||
}
|
||||
|
||||
pub trait AnchorRangeExt {
|
||||
fn cmp(&self, b: &Range<Anchor>, buffer: &MultiBufferSnapshot) -> Result<Ordering>;
|
||||
fn to_offset(&self, content: &MultiBufferSnapshot) -> Range<usize>;
|
||||
fn to_point(&self, content: &MultiBufferSnapshot) -> Range<Point>;
|
||||
}
|
||||
|
||||
impl AnchorRangeExt for Range<Anchor> {
|
||||
fn cmp(&self, other: &Range<Anchor>, buffer: &MultiBufferSnapshot) -> Result<Ordering> {
|
||||
Ok(match self.start.cmp(&other.start, buffer)? {
|
||||
Ordering::Equal => other.end.cmp(&self.end, buffer)?,
|
||||
ord @ _ => ord,
|
||||
})
|
||||
}
|
||||
|
||||
fn to_offset(&self, content: &MultiBufferSnapshot) -> Range<usize> {
|
||||
self.start.to_offset(&content)..self.end.to_offset(&content)
|
||||
}
|
||||
|
||||
fn to_point(&self, content: &MultiBufferSnapshot) -> Range<Point> {
|
||||
self.start.to_point(&content)..self.end.to_point(&content)
|
||||
}
|
||||
}
|
121
crates/editor/src/multi_buffer/selection.rs
Normal file
121
crates/editor/src/multi_buffer/selection.rs
Normal file
|
@ -0,0 +1,121 @@
|
|||
use super::{Anchor, MultiBufferSnapshot, ToOffset};
|
||||
use std::{
|
||||
ops::{Range, Sub},
|
||||
sync::Arc,
|
||||
};
|
||||
use sum_tree::Bias;
|
||||
use text::{rope::TextDimension, Selection, SelectionSetId};
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub struct SelectionSet {
|
||||
pub id: SelectionSetId,
|
||||
pub active: bool,
|
||||
pub selections: Arc<[Selection<Anchor>]>,
|
||||
}
|
||||
|
||||
impl SelectionSet {
|
||||
pub fn len(&self) -> usize {
|
||||
self.selections.len()
|
||||
}
|
||||
|
||||
pub fn selections<'a, D>(
|
||||
&'a self,
|
||||
snapshot: &'a MultiBufferSnapshot,
|
||||
) -> impl 'a + Iterator<Item = Selection<D>>
|
||||
where
|
||||
D: TextDimension + Ord + Sub<D, Output = D>,
|
||||
{
|
||||
resolve_selections(&self.selections, snapshot)
|
||||
}
|
||||
|
||||
pub fn intersecting_selections<'a, D, I>(
|
||||
&'a self,
|
||||
range: Range<(I, Bias)>,
|
||||
snapshot: &'a MultiBufferSnapshot,
|
||||
) -> impl 'a + Iterator<Item = Selection<D>>
|
||||
where
|
||||
D: TextDimension + Ord + Sub<D, Output = D>,
|
||||
I: 'a + ToOffset,
|
||||
{
|
||||
let start = snapshot.anchor_at(range.start.0, range.start.1);
|
||||
let end = snapshot.anchor_at(range.end.0, range.end.1);
|
||||
let start_ix = match self
|
||||
.selections
|
||||
.binary_search_by(|probe| probe.end.cmp(&start, snapshot).unwrap())
|
||||
{
|
||||
Ok(ix) | Err(ix) => ix,
|
||||
};
|
||||
let end_ix = match self
|
||||
.selections
|
||||
.binary_search_by(|probe| probe.start.cmp(&end, snapshot).unwrap())
|
||||
{
|
||||
Ok(ix) | Err(ix) => ix,
|
||||
};
|
||||
resolve_selections(&self.selections[start_ix..end_ix], snapshot)
|
||||
}
|
||||
|
||||
pub fn oldest_selection<'a, D>(
|
||||
&'a self,
|
||||
snapshot: &'a MultiBufferSnapshot,
|
||||
) -> Option<Selection<D>>
|
||||
where
|
||||
D: TextDimension + Ord + Sub<D, Output = D>,
|
||||
{
|
||||
self.selections
|
||||
.iter()
|
||||
.min_by_key(|selection| selection.id)
|
||||
.map(|selection| resolve_selection(selection, snapshot))
|
||||
}
|
||||
|
||||
pub fn newest_selection<'a, D>(
|
||||
&'a self,
|
||||
snapshot: &'a MultiBufferSnapshot,
|
||||
) -> Option<Selection<D>>
|
||||
where
|
||||
D: TextDimension + Ord + Sub<D, Output = D>,
|
||||
{
|
||||
self.selections
|
||||
.iter()
|
||||
.max_by_key(|selection| selection.id)
|
||||
.map(|selection| resolve_selection(selection, snapshot))
|
||||
}
|
||||
}
|
||||
|
||||
fn resolve_selection<'a, D>(
|
||||
selection: &'a Selection<Anchor>,
|
||||
snapshot: &'a MultiBufferSnapshot,
|
||||
) -> Selection<D>
|
||||
where
|
||||
D: TextDimension + Ord + Sub<D, Output = D>,
|
||||
{
|
||||
Selection {
|
||||
id: selection.id,
|
||||
start: selection.start.summary::<D>(snapshot),
|
||||
end: selection.end.summary::<D>(snapshot),
|
||||
reversed: selection.reversed,
|
||||
goal: selection.goal,
|
||||
}
|
||||
}
|
||||
|
||||
fn resolve_selections<'a, D>(
|
||||
selections: &'a [Selection<Anchor>],
|
||||
snapshot: &'a MultiBufferSnapshot,
|
||||
) -> impl 'a + Iterator<Item = Selection<D>>
|
||||
where
|
||||
D: TextDimension + Ord + Sub<D, Output = D>,
|
||||
{
|
||||
let mut summaries = snapshot
|
||||
.summaries_for_anchors::<D, _>(
|
||||
selections
|
||||
.iter()
|
||||
.flat_map(|selection| [&selection.start, &selection.end]),
|
||||
)
|
||||
.into_iter();
|
||||
selections.iter().map(move |selection| Selection {
|
||||
id: selection.id,
|
||||
start: summaries.next().unwrap(),
|
||||
end: summaries.next().unwrap(),
|
||||
reversed: selection.reversed,
|
||||
goal: selection.goal,
|
||||
})
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue