mod anchor;#[cfg(test)]mod multi_buffer_tests;mod path_key;mod transaction; use self::transaction::History; pub use anchor::{Anchor, AnchorRangeExt}; use anyhow::{Result, anyhow};use buffer_diff::{ BufferDiff, BufferDiffEvent, BufferDiffSnapshot, DiffChanged, DiffHunkSecondaryStatus, DiffHunkStatus, DiffHunkStatusKind,};use clock::ReplicaId;use collections::{BTreeMap, Bound, HashMap, HashSet};use gpui::{App, Context, Entity, EntityId, EventEmitter};use itertools::Itertools;use language::{ AutoindentMode, BracketMatch, Buffer, BufferChunks, BufferRow, BufferSnapshot, Capability, CharClassifier, CharKind, CharScopeContext, Chunk, CursorShape, DiagnosticEntryRef, File, IndentGuideSettings, IndentSize, Language, LanguageScope, OffsetRangeExt, OffsetUtf16, Outline, OutlineItem, Point, PointUtf16, Selection, TextDimension, TextObject, ToOffset as _, ToPoint as _, TransactionId, TreeSitterOptions, Unclipped, language_settings::{LanguageSettings, language_settings},}; #[cfg(any(test, feature = "test-support"))]use gpui::AppContext as _; use rope::DimensionPair;use smallvec::SmallVec;use smol::future::yield_now;use std::{ any::type_name, borrow::Cow, cell::{Cell, OnceCell, Ref, RefCell}, cmp, fmt, future::Future, io, iter::{self, FromIterator}, mem, ops::{self, Add, AddAssign, ControlFlow, Range, RangeBounds, Sub, SubAssign}, rc::Rc, str, sync::{Arc, OnceLock}, time::Duration,};use sum_tree::{Bias, Cursor, Dimension, Dimensions, SumTree, TreeMap};use text::{ BufferId, Edit, LineIndent, TextSummary, locator::Locator, subscription::{Subscription, Topic},};use theme::SyntaxTheme;use util::post_inc;use ztracing::instrument; pub use self::path_key::{PathExcerptInsertResult, PathKey}; pub static EXCERPT_CONTEXT_LINES: OnceLock<fn(&App) -> u32> = OnceLock::new(); pub fn excerpt_context_lines(cx: &App) -> u32 { EXCERPT_CONTEXT_LINES.get().map(|f| f(cx)).unwrap_or(2)} #[derive(Debug, Default, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]pub struct ExcerptId(u32); /// One or more [`Buffers`](Buffer) being edited in a single view.////// See <https://zed.dev/features#multi-buffers>pub struct MultiBuffer { /// A snapshot of the [`Excerpt`]s in the MultiBuffer. /// Use [`MultiBuffer::snapshot`] to get a up-to-date snapshot. snapshot: RefCell<MultiBufferSnapshot>, /// Contains the state of the buffers being edited buffers: BTreeMap<BufferId, BufferState>, /// Mapping from path keys to their excerpts. excerpts_by_path: BTreeMap<PathKey, Vec<ExcerptId>>, /// Mapping from excerpt IDs to their path key. paths_by_excerpt: HashMap<ExcerptId, PathKey>, /// Mapping from buffer IDs to their diff states diffs: HashMap<BufferId, DiffState>, subscriptions: Topic<MultiBufferOffset>, /// If true, the multi-buffer only contains a single [`Buffer`] and a single [`Excerpt`] singleton: bool, /// The history of the multi-buffer. history: History, /// The explicit title of the multi-buffer. /// If `None`, it will be derived from the underlying path or content. title: Option<String>, /// The writing capability of the multi-buffer. capability: Capability, buffer_changed_since_sync: Rc<Cell<bool>>,} #[derive(Clone, Debug, PartialEq, Eq)]pub enum Event { ExcerptsAdded { buffer: Entity<Buffer>, predecessor: ExcerptId, excerpts: Vec<(ExcerptId, ExcerptRange<language::Anchor>)>, }, ExcerptsRemoved { ids: Vec<ExcerptId>, /// Contains only buffer IDs for which all excerpts have been removed. /// Buffers that still have remaining excerpts are never included. removed_buffer_ids: Vec<BufferId>, }, ExcerptsExpanded { ids: Vec<ExcerptId>, }, ExcerptsEdited { excerpt_ids: Vec<ExcerptId>, buffer_ids: Vec<BufferId>, }, DiffHunksToggled, Edited { edited_buffer: Option<Entity<Buffer>>, is_local: bool, }, TransactionUndone { transaction_id: TransactionId, }, Reloaded, LanguageChanged(BufferId, bool), Reparsed(BufferId), Saved, FileHandleChanged, DirtyChanged, DiagnosticsUpdated, BufferDiffChanged,} /// A diff hunk, representing a range of consequent lines in a multibuffer.#[derive(Debug, Clone, PartialEq, Eq)]pub struct MultiBufferDiffHunk { /// The row range in the multibuffer where this diff hunk appears. pub row_range: Range<MultiBufferRow>, /// The buffer ID that this hunk belongs to. pub buffer_id: BufferId, /// The range of the underlying buffer that this hunk corresponds to. pub buffer_range: Range<text::Anchor>, /// The excerpt that contains the diff hunk. pub excerpt_id: ExcerptId, /// The range within the buffer's diff base that this hunk corresponds to. pub diff_base_byte_range: Range<BufferOffset>, /// The status of this hunk (added/modified/deleted and secondary status). pub status: DiffHunkStatus, /// The word diffs for this hunk. pub word_diffs: Vec<Range<MultiBufferOffset>>,} impl MultiBufferDiffHunk { pub fn status(&self) -> DiffHunkStatus { self.status } pub fn is_created_file(&self) -> bool { self.diff_base_byte_range == (BufferOffset(0)..BufferOffset(0)) && self.buffer_range.start.is_min() && self.buffer_range.end.is_max() } pub fn multi_buffer_range(&self) -> Range<Anchor> { let start = Anchor::in_buffer(self.excerpt_id, self.buffer_range.start); let end = Anchor::in_buffer(self.excerpt_id, self.buffer_range.end); start..end }} pub type MultiBufferPoint = Point;type ExcerptOffset = ExcerptDimension<MultiBufferOffset>;type ExcerptPoint = ExcerptDimension<Point>; #[derive(Copy, Clone, Debug, Default, Eq, Ord, PartialOrd, PartialEq, Hash, serde::Deserialize)]#[serde(transparent)]pub struct MultiBufferRow(pub u32); impl MultiBufferRow { pub const MIN: Self = Self(0); pub const MAX: Self = Self(u32::MAX);} impl ops::Add<usize> for MultiBufferRow { type Output = Self; fn add(self, rhs: usize) -> Self::Output { MultiBufferRow(self.0 + rhs as u32) }} pub trait MultiBufferDimension: 'static + Copy + Default + std::fmt::Debug { type TextDimension: TextDimension; fn from_summary(summary: &MBTextSummary) -> Self; fn add_text_dim(&mut self, summary: &Self::TextDimension); fn add_mb_text_summary(&mut self, summary: &MBTextSummary);} // todo(lw): MultiBufferPointimpl MultiBufferDimension for Point { type TextDimension = Point; fn from_summary(summary: &MBTextSummary) -> Self { summary.lines } fn add_text_dim(&mut self, other: &Self::TextDimension) { *self += *other; } fn add_mb_text_summary(&mut self, summary: &MBTextSummary) { *self += summary.lines; }} // todo(lw): MultiBufferPointUtf16impl MultiBufferDimension for PointUtf16 { type TextDimension = PointUtf16; fn from_summary(summary: &MBTextSummary) -> Self { summary.lines_utf16() } fn add_text_dim(&mut self, other: &Self::TextDimension) { *self += *other; } fn add_mb_text_summary(&mut self, summary: &MBTextSummary) { *self += summary.lines_utf16(); }} #[derive(Copy, Clone, Debug, Default, Eq, Ord, PartialOrd, PartialEq, Hash, serde::Deserialize)]pub struct MultiBufferOffset(pub usize); impl fmt::Display for MultiBufferOffset { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{}", self.0) }} impl rand::distr::uniform::SampleUniform for MultiBufferOffset { type Sampler = MultiBufferOffsetUniformSampler;} pub struct MultiBufferOffsetUniformSampler { sampler: rand::distr::uniform::UniformUsize,} impl rand::distr::uniform::UniformSampler for MultiBufferOffsetUniformSampler { type X = MultiBufferOffset; fn new<B1, B2>(low_b: B1, high_b: B2) -> Result<Self, rand::distr::uniform::Error> where B1: rand::distr::uniform::SampleBorrow<Self::X> + Sized, B2: rand::distr::uniform::SampleBorrow<Self::X> + Sized, { let low = *low_b.borrow(); let high = *high_b.borrow(); let sampler = rand::distr::uniform::UniformUsize::new(low.0, high.0); sampler.map(|sampler| MultiBufferOffsetUniformSampler { sampler }) } #[inline] // if the range is constant, this helps LLVM to do the // calculations at compile-time. fn new_inclusive<B1, B2>(low_b: B1, high_b: B2) -> Result<Self, rand::distr::uniform::Error> where B1: rand::distr::uniform::SampleBorrow<Self::X> + Sized, B2: rand::distr::uniform::SampleBorrow<Self::X> + Sized, { let low = *low_b.borrow(); let high = *high_b.borrow(); let sampler = rand::distr::uniform::UniformUsize::new_inclusive(low.0, high.0); sampler.map(|sampler| MultiBufferOffsetUniformSampler { sampler }) } fn sample<R: rand::Rng + ?Sized>(&self, rng: &mut R) -> Self::X { MultiBufferOffset(self.sampler.sample(rng)) }}impl MultiBufferDimension for MultiBufferOffset { type TextDimension = usize; fn from_summary(summary: &MBTextSummary) -> Self { summary.len } fn add_text_dim(&mut self, other: &Self::TextDimension) { self.0 += *other; } fn add_mb_text_summary(&mut self, summary: &MBTextSummary) { *self += summary.len; }}impl MultiBufferDimension for MultiBufferOffsetUtf16 { type TextDimension = OffsetUtf16; fn from_summary(summary: &MBTextSummary) -> Self { MultiBufferOffsetUtf16(summary.len_utf16) } fn add_text_dim(&mut self, other: &Self::TextDimension) { self.0 += *other; } fn add_mb_text_summary(&mut self, summary: &MBTextSummary) { self.0 += summary.len_utf16; }} #[derive(Copy, Clone, Debug, Default, Eq, Ord, PartialOrd, PartialEq, Hash, serde::Deserialize)]pub struct BufferOffset(pub usize); impl TextDimension for BufferOffset { fn from_text_summary(summary: &TextSummary) -> Self { BufferOffset(usize::from_text_summary(summary)) } fn from_chunk(chunk: rope::ChunkSlice) -> Self { BufferOffset(usize::from_chunk(chunk)) } fn add_assign(&mut self, other: &Self) { TextDimension::add_assign(&mut self.0, &other.0); }}impl<'a> sum_tree::Dimension<'a, rope::ChunkSummary> for BufferOffset { fn zero(cx: ()) -> Self { BufferOffset(<usize as sum_tree::Dimension<'a, rope::ChunkSummary>>::zero(cx)) } fn add_summary(&mut self, summary: &'a rope::ChunkSummary, cx: ()) { usize::add_summary(&mut self.0, summary, cx); }} impl Sub for BufferOffset { type Output = usize; fn sub(self, other: BufferOffset) -> Self::Output { self.0 - other.0 }} impl AddAssign<DimensionPair<usize, Point>> for BufferOffset { fn add_assign(&mut self, other: DimensionPair<usize, Point>) { self.0 += other.key; }} impl language::ToPoint for BufferOffset { fn to_point(&self, snapshot: &text::BufferSnapshot) -> Point { self.0.to_point(snapshot) }} impl language::ToPointUtf16 for BufferOffset { fn to_point_utf16(&self, snapshot: &text::BufferSnapshot) -> PointUtf16 { self.0.to_point_utf16(snapshot) }} impl language::ToOffset for BufferOffset { fn to_offset(&self, snapshot: &text::BufferSnapshot) -> usize { self.0.to_offset(snapshot) }} impl language::ToOffsetUtf16 for BufferOffset { fn to_offset_utf16(&self, snapshot: &text::BufferSnapshot) -> OffsetUtf16 { self.0.to_offset_utf16(snapshot) }} #[derive(Copy, Clone, Debug, Default, Eq, Ord, PartialOrd, PartialEq)]pub struct MultiBufferOffsetUtf16(pub OffsetUtf16); impl ops::Add<usize> for MultiBufferOffsetUtf16 { type Output = MultiBufferOffsetUtf16; fn add(self, rhs: usize) -> Self::Output { MultiBufferOffsetUtf16(OffsetUtf16(self.0.0 + rhs)) }} impl ops::Add<OffsetUtf16> for MultiBufferOffsetUtf16 { type Output = Self; fn add(self, rhs: OffsetUtf16) -> Self::Output { MultiBufferOffsetUtf16(self.0 + rhs) }} impl AddAssign<OffsetUtf16> for MultiBufferOffsetUtf16 { fn add_assign(&mut self, rhs: OffsetUtf16) { self.0 += rhs; }} impl AddAssign<usize> for MultiBufferOffsetUtf16 { fn add_assign(&mut self, rhs: usize) { self.0.0 += rhs; }} impl Sub for MultiBufferOffsetUtf16 { type Output = OffsetUtf16; fn sub(self, other: MultiBufferOffsetUtf16) -> Self::Output { self.0 - other.0 }} impl Sub<OffsetUtf16> for MultiBufferOffsetUtf16 { type Output = MultiBufferOffsetUtf16; fn sub(self, other: OffsetUtf16) -> Self::Output { MultiBufferOffsetUtf16(self.0 - other) }} #[derive(Copy, Clone, Debug, Default, Eq, Ord, PartialOrd, PartialEq)]pub struct BufferOffsetUtf16(pub OffsetUtf16); impl MultiBufferOffset { const ZERO: Self = Self(0); pub fn saturating_sub(self, other: MultiBufferOffset) -> usize { self.0.saturating_sub(other.0) } pub fn saturating_sub_usize(self, other: usize) -> MultiBufferOffset { MultiBufferOffset(self.0.saturating_sub(other)) }} impl ops::Sub for MultiBufferOffset { type Output = usize; fn sub(self, other: MultiBufferOffset) -> Self::Output { self.0 - other.0 }} impl ops::Sub<usize> for MultiBufferOffset { type Output = Self; fn sub(self, other: usize) -> Self::Output { MultiBufferOffset(self.0 - other) }} impl ops::SubAssign<usize> for MultiBufferOffset { fn sub_assign(&mut self, other: usize) { self.0 -= other; }} impl ops::Add<usize> for BufferOffset { type Output = Self; fn add(self, rhs: usize) -> Self::Output { BufferOffset(self.0 + rhs) }} impl ops::AddAssign<usize> for BufferOffset { fn add_assign(&mut self, other: usize) { self.0 += other; }} impl ops::Add<usize> for MultiBufferOffset { type Output = Self; fn add(self, rhs: usize) -> Self::Output { MultiBufferOffset(self.0 + rhs) }} impl ops::AddAssign<usize> for MultiBufferOffset { fn add_assign(&mut self, other: usize) { self.0 += other; }} impl ops::Add<isize> for MultiBufferOffset { type Output = Self; fn add(self, rhs: isize) -> Self::Output { MultiBufferOffset((self.0 as isize + rhs) as usize) }} impl ops::Add for MultiBufferOffset { type Output = Self; fn add(self, rhs: MultiBufferOffset) -> Self::Output { MultiBufferOffset(self.0 + rhs.0) }} Lines 1–500 of 8828. Load more
mod anchor; #[cfg(test)] mod multi_buffer_tests; mod path_key; mod transaction; use self::transaction::History; pub use anchor::{Anchor, AnchorRangeExt}; use anyhow::{Result, anyhow}; use buffer_diff::{ BufferDiff, BufferDiffEvent, BufferDiffSnapshot, DiffChanged, DiffHunkSecondaryStatus, DiffHunkStatus, DiffHunkStatusKind, }; use clock::ReplicaId; use collections::{BTreeMap, Bound, HashMap, HashSet}; use gpui::{App, Context, Entity, EntityId, EventEmitter}; use itertools::Itertools; use language::{ AutoindentMode, BracketMatch, Buffer, BufferChunks, BufferRow, BufferSnapshot, Capability, CharClassifier, CharKind, CharScopeContext, Chunk, CursorShape, DiagnosticEntryRef, File, IndentGuideSettings, IndentSize, Language, LanguageScope, OffsetRangeExt, OffsetUtf16, Outline, OutlineItem, Point, PointUtf16, Selection, TextDimension, TextObject, ToOffset as _, ToPoint as _, TransactionId, TreeSitterOptions, Unclipped, language_settings::{LanguageSettings, language_settings}, }; #[cfg(any(test, feature = "test-support"))] use gpui::AppContext as _; use rope::DimensionPair; use smallvec::SmallVec; use smol::future::yield_now; use std::{ any::type_name, borrow::Cow, cell::{Cell, OnceCell, Ref, RefCell}, cmp, fmt, future::Future, io, iter::{self, FromIterator}, mem, ops::{self, Add, AddAssign, ControlFlow, Range, RangeBounds, Sub, SubAssign}, rc::Rc, str, sync::{Arc, OnceLock}, time::Duration, }; use sum_tree::{Bias, Cursor, Dimension, Dimensions, SumTree, TreeMap}; use text::{ BufferId, Edit, LineIndent, TextSummary, locator::Locator, subscription::{Subscription, Topic}, }; use theme::SyntaxTheme; use util::post_inc; use ztracing::instrument; pub use self::path_key::{PathExcerptInsertResult, PathKey}; pub static EXCERPT_CONTEXT_LINES: OnceLock<fn(&App) -> u32> = OnceLock::new(); pub fn excerpt_context_lines(cx: &App) -> u32 { EXCERPT_CONTEXT_LINES.get().map(|f| f(cx)).unwrap_or(2) } #[derive(Debug, Default, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct ExcerptId(u32); /// One or more [`Buffers`](Buffer) being edited in a single view. /// /// See <https://zed.dev/features#multi-buffers> pub struct MultiBuffer { /// A snapshot of the [`Excerpt`]s in the MultiBuffer. /// Use [`MultiBuffer::snapshot`] to get a up-to-date snapshot. snapshot: RefCell<MultiBufferSnapshot>, /// Contains the state of the buffers being edited buffers: BTreeMap<BufferId, BufferState>, /// Mapping from path keys to their excerpts. excerpts_by_path: BTreeMap<PathKey, Vec<ExcerptId>>, /// Mapping from excerpt IDs to their path key. paths_by_excerpt: HashMap<ExcerptId, PathKey>, /// Mapping from buffer IDs to their diff states diffs: HashMap<BufferId, DiffState>, subscriptions: Topic<MultiBufferOffset>, /// If true, the multi-buffer only contains a single [`Buffer`] and a single [`Excerpt`] singleton: bool, /// The history of the multi-buffer. history: History, /// The explicit title of the multi-buffer. /// If `None`, it will be derived from the underlying path or content. title: Option<String>, /// The writing capability of the multi-buffer. capability: Capability, buffer_changed_since_sync: Rc<Cell<bool>>, } #[derive(Clone, Debug, PartialEq, Eq)] pub enum Event { ExcerptsAdded { buffer: Entity<Buffer>, predecessor: ExcerptId, excerpts: Vec<(ExcerptId, ExcerptRange<language::Anchor>)>, }, ExcerptsRemoved { ids: Vec<ExcerptId>, /// Contains only buffer IDs for which all excerpts have been removed. /// Buffers that still have remaining excerpts are never included. removed_buffer_ids: Vec<BufferId>, }, ExcerptsExpanded { ids: Vec<ExcerptId>, }, ExcerptsEdited { excerpt_ids: Vec<ExcerptId>, buffer_ids: Vec<BufferId>, }, DiffHunksToggled, Edited { edited_buffer: Option<Entity<Buffer>>, is_local: bool, }, TransactionUndone { transaction_id: TransactionId, }, Reloaded, LanguageChanged(BufferId, bool), Reparsed(BufferId), Saved, FileHandleChanged, DirtyChanged, DiagnosticsUpdated, BufferDiffChanged, } /// A diff hunk, representing a range of consequent lines in a multibuffer. #[derive(Debug, Clone, PartialEq, Eq)] pub struct MultiBufferDiffHunk { /// The row range in the multibuffer where this diff hunk appears. pub row_range: Range<MultiBufferRow>, /// The buffer ID that this hunk belongs to. pub buffer_id: BufferId, /// The range of the underlying buffer that this hunk corresponds to. pub buffer_range: Range<text::Anchor>, /// The excerpt that contains the diff hunk. pub excerpt_id: ExcerptId, /// The range within the buffer's diff base that this hunk corresponds to. pub diff_base_byte_range: Range<BufferOffset>, /// The status of this hunk (added/modified/deleted and secondary status). pub status: DiffHunkStatus, /// The word diffs for this hunk. pub word_diffs: Vec<Range<MultiBufferOffset>>, } impl MultiBufferDiffHunk { pub fn status(&self) -> DiffHunkStatus { self.status } pub fn is_created_file(&self) -> bool { self.diff_base_byte_range == (BufferOffset(0)..BufferOffset(0)) && self.buffer_range.start.is_min() && self.buffer_range.end.is_max() } pub fn multi_buffer_range(&self) -> Range<Anchor> { let start = Anchor::in_buffer(self.excerpt_id, self.buffer_range.start); let end = Anchor::in_buffer(self.excerpt_id, self.buffer_range.end); start..end } } pub type MultiBufferPoint = Point; type ExcerptOffset = ExcerptDimension<MultiBufferOffset>; type ExcerptPoint = ExcerptDimension<Point>; #[derive(Copy, Clone, Debug, Default, Eq, Ord, PartialOrd, PartialEq, Hash, serde::Deserialize)] #[serde(transparent)] pub struct MultiBufferRow(pub u32); impl MultiBufferRow { pub const MIN: Self = Self(0); pub const MAX: Self = Self(u32::MAX); } impl ops::Add<usize> for MultiBufferRow { type Output = Self; fn add(self, rhs: usize) -> Self::Output { MultiBufferRow(self.0 + rhs as u32) } } pub trait MultiBufferDimension: 'static + Copy + Default + std::fmt::Debug { type TextDimension: TextDimension; fn from_summary(summary: &MBTextSummary) -> Self; fn add_text_dim(&mut self, summary: &Self::TextDimension); fn add_mb_text_summary(&mut self, summary: &MBTextSummary); } // todo(lw): MultiBufferPoint impl MultiBufferDimension for Point { type TextDimension = Point; fn from_summary(summary: &MBTextSummary) -> Self { summary.lines } fn add_text_dim(&mut self, other: &Self::TextDimension) { *self += *other; } fn add_mb_text_summary(&mut self, summary: &MBTextSummary) { *self += summary.lines; } } // todo(lw): MultiBufferPointUtf16 impl MultiBufferDimension for PointUtf16 { type TextDimension = PointUtf16; fn from_summary(summary: &MBTextSummary) -> Self { summary.lines_utf16() } fn add_text_dim(&mut self, other: &Self::TextDimension) { *self += *other; } fn add_mb_text_summary(&mut self, summary: &MBTextSummary) { *self += summary.lines_utf16(); } } #[derive(Copy, Clone, Debug, Default, Eq, Ord, PartialOrd, PartialEq, Hash, serde::Deserialize)] pub struct MultiBufferOffset(pub usize); impl fmt::Display for MultiBufferOffset { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{}", self.0) } } impl rand::distr::uniform::SampleUniform for MultiBufferOffset { type Sampler = MultiBufferOffsetUniformSampler; } pub struct MultiBufferOffsetUniformSampler { sampler: rand::distr::uniform::UniformUsize, } impl rand::distr::uniform::UniformSampler for MultiBufferOffsetUniformSampler { type X = MultiBufferOffset; fn new<B1, B2>(low_b: B1, high_b: B2) -> Result<Self, rand::distr::uniform::Error> where B1: rand::distr::uniform::SampleBorrow<Self::X> + Sized, B2: rand::distr::uniform::SampleBorrow<Self::X> + Sized, { let low = *low_b.borrow(); let high = *high_b.borrow(); let sampler = rand::distr::uniform::UniformUsize::new(low.0, high.0); sampler.map(|sampler| MultiBufferOffsetUniformSampler { sampler }) } #[inline] // if the range is constant, this helps LLVM to do the // calculations at compile-time. fn new_inclusive<B1, B2>(low_b: B1, high_b: B2) -> Result<Self, rand::distr::uniform::Error> where B1: rand::distr::uniform::SampleBorrow<Self::X> + Sized, B2: rand::distr::uniform::SampleBorrow<Self::X> + Sized, { let low = *low_b.borrow(); let high = *high_b.borrow(); let sampler = rand::distr::uniform::UniformUsize::new_inclusive(low.0, high.0); sampler.map(|sampler| MultiBufferOffsetUniformSampler { sampler }) } fn sample<R: rand::Rng + ?Sized>(&self, rng: &mut R) -> Self::X { MultiBufferOffset(self.sampler.sample(rng)) } } impl MultiBufferDimension for MultiBufferOffset { type TextDimension = usize; fn from_summary(summary: &MBTextSummary) -> Self { summary.len } fn add_text_dim(&mut self, other: &Self::TextDimension) { self.0 += *other; } fn add_mb_text_summary(&mut self, summary: &MBTextSummary) { *self += summary.len; } } impl MultiBufferDimension for MultiBufferOffsetUtf16 { type TextDimension = OffsetUtf16; fn from_summary(summary: &MBTextSummary) -> Self { MultiBufferOffsetUtf16(summary.len_utf16) } fn add_text_dim(&mut self, other: &Self::TextDimension) { self.0 += *other; } fn add_mb_text_summary(&mut self, summary: &MBTextSummary) { self.0 += summary.len_utf16; } } #[derive(Copy, Clone, Debug, Default, Eq, Ord, PartialOrd, PartialEq, Hash, serde::Deserialize)] pub struct BufferOffset(pub usize); impl TextDimension for BufferOffset { fn from_text_summary(summary: &TextSummary) -> Self { BufferOffset(usize::from_text_summary(summary)) } fn from_chunk(chunk: rope::ChunkSlice) -> Self { BufferOffset(usize::from_chunk(chunk)) } fn add_assign(&mut self, other: &Self) { TextDimension::add_assign(&mut self.0, &other.0); } } impl<'a> sum_tree::Dimension<'a, rope::ChunkSummary> for BufferOffset { fn zero(cx: ()) -> Self { BufferOffset(<usize as sum_tree::Dimension<'a, rope::ChunkSummary>>::zero(cx)) } fn add_summary(&mut self, summary: &'a rope::ChunkSummary, cx: ()) { usize::add_summary(&mut self.0, summary, cx); } } impl Sub for BufferOffset { type Output = usize; fn sub(self, other: BufferOffset) -> Self::Output { self.0 - other.0 } } impl AddAssign<DimensionPair<usize, Point>> for BufferOffset { fn add_assign(&mut self, other: DimensionPair<usize, Point>) { self.0 += other.key; } } impl language::ToPoint for BufferOffset { fn to_point(&self, snapshot: &text::BufferSnapshot) -> Point { self.0.to_point(snapshot) } } impl language::ToPointUtf16 for BufferOffset { fn to_point_utf16(&self, snapshot: &text::BufferSnapshot) -> PointUtf16 { self.0.to_point_utf16(snapshot) } } impl language::ToOffset for BufferOffset { fn to_offset(&self, snapshot: &text::BufferSnapshot) -> usize { self.0.to_offset(snapshot) } } impl language::ToOffsetUtf16 for BufferOffset { fn to_offset_utf16(&self, snapshot: &text::BufferSnapshot) -> OffsetUtf16 { self.0.to_offset_utf16(snapshot) } } #[derive(Copy, Clone, Debug, Default, Eq, Ord, PartialOrd, PartialEq)] pub struct MultiBufferOffsetUtf16(pub OffsetUtf16); impl ops::Add<usize> for MultiBufferOffsetUtf16 { type Output = MultiBufferOffsetUtf16; fn add(self, rhs: usize) -> Self::Output { MultiBufferOffsetUtf16(OffsetUtf16(self.0.0 + rhs)) } } impl ops::Add<OffsetUtf16> for MultiBufferOffsetUtf16 { type Output = Self; fn add(self, rhs: OffsetUtf16) -> Self::Output { MultiBufferOffsetUtf16(self.0 + rhs) } } impl AddAssign<OffsetUtf16> for MultiBufferOffsetUtf16 { fn add_assign(&mut self, rhs: OffsetUtf16) { self.0 += rhs; } } impl AddAssign<usize> for MultiBufferOffsetUtf16 { fn add_assign(&mut self, rhs: usize) { self.0.0 += rhs; } } impl Sub for MultiBufferOffsetUtf16 { type Output = OffsetUtf16; fn sub(self, other: MultiBufferOffsetUtf16) -> Self::Output { self.0 - other.0 } } impl Sub<OffsetUtf16> for MultiBufferOffsetUtf16 { type Output = MultiBufferOffsetUtf16; fn sub(self, other: OffsetUtf16) -> Self::Output { MultiBufferOffsetUtf16(self.0 - other) } } #[derive(Copy, Clone, Debug, Default, Eq, Ord, PartialOrd, PartialEq)] pub struct BufferOffsetUtf16(pub OffsetUtf16); impl MultiBufferOffset { const ZERO: Self = Self(0); pub fn saturating_sub(self, other: MultiBufferOffset) -> usize { self.0.saturating_sub(other.0) } pub fn saturating_sub_usize(self, other: usize) -> MultiBufferOffset { MultiBufferOffset(self.0.saturating_sub(other)) } } impl ops::Sub for MultiBufferOffset { type Output = usize; fn sub(self, other: MultiBufferOffset) -> Self::Output { self.0 - other.0 } } impl ops::Sub<usize> for MultiBufferOffset { type Output = Self; fn sub(self, other: usize) -> Self::Output { MultiBufferOffset(self.0 - other) } } impl ops::SubAssign<usize> for MultiBufferOffset { fn sub_assign(&mut self, other: usize) { self.0 -= other; } } impl ops::Add<usize> for BufferOffset { type Output = Self; fn add(self, rhs: usize) -> Self::Output { BufferOffset(self.0 + rhs) } } impl ops::AddAssign<usize> for BufferOffset { fn add_assign(&mut self, other: usize) { self.0 += other; } } impl ops::Add<usize> for MultiBufferOffset { type Output = Self; fn add(self, rhs: usize) -> Self::Output { MultiBufferOffset(self.0 + rhs) } } impl ops::AddAssign<usize> for MultiBufferOffset { fn add_assign(&mut self, other: usize) { self.0 += other; } } impl ops::Add<isize> for MultiBufferOffset { type Output = Self; fn add(self, rhs: isize) -> Self::Output { MultiBufferOffset((self.0 as isize + rhs) as usize) } } impl ops::Add for MultiBufferOffset { type Output = Self; fn add(self, rhs: MultiBufferOffset) -> Self::Output { MultiBufferOffset(self.0 + rhs.0) } }