1817 lines · 65.2 KB · Rust
RawDownload
mod block_map;mod fold_map;mod inlay_map;mod tab_map;mod wrap_map; use crate::{    link_go_to_definition::{DocumentRange, InlayRange},    Anchor, AnchorRangeExt, InlayId, MultiBuffer, MultiBufferSnapshot, ToOffset, ToPoint,};pub use block_map::{BlockMap, BlockPoint};use collections::{HashMap, HashSet};use fold_map::FoldMap;use gpui::{    color::Color,    fonts::{FontId, HighlightStyle},    Entity, ModelContext, ModelHandle,};use inlay_map::InlayMap;use language::{    language_settings::language_settings, OffsetUtf16, Point, Subscription as BufferSubscription,};use std::{any::TypeId, fmt::Debug, num::NonZeroU32, ops::Range, sync::Arc};use sum_tree::{Bias, TreeMap};use tab_map::TabMap;use wrap_map::WrapMap; pub use block_map::{    BlockBufferRows as DisplayBufferRows, BlockChunks as DisplayChunks, BlockContext,    BlockDisposition, BlockId, BlockProperties, BlockStyle, RenderBlock, TransformBlock,}; pub use self::fold_map::FoldPoint;pub use self::inlay_map::{Inlay, InlayOffset, InlayPoint}; #[derive(Copy, Clone, Debug, PartialEq, Eq)]pub enum FoldStatus {    Folded,    Foldable,} pub trait ToDisplayPoint {    fn to_display_point(&self, map: &DisplaySnapshot) -> DisplayPoint;} type TextHighlights = TreeMap<Option<TypeId>, Arc<(HighlightStyle, Vec<DocumentRange>)>>; pub struct DisplayMap {    buffer: ModelHandle<MultiBuffer>,    buffer_subscription: BufferSubscription,    fold_map: FoldMap,    inlay_map: InlayMap,    tab_map: TabMap,    wrap_map: ModelHandle<WrapMap>,    block_map: BlockMap,    text_highlights: TextHighlights,    pub clip_at_line_ends: bool,} impl Entity for DisplayMap {    type Event = ();} impl DisplayMap {    pub fn new(        buffer: ModelHandle<MultiBuffer>,        font_id: FontId,        font_size: f32,        wrap_width: Option<f32>,        buffer_header_height: u8,        excerpt_header_height: u8,        cx: &mut ModelContext<Self>,    ) -> Self {        let buffer_subscription = buffer.update(cx, |buffer, _| buffer.subscribe());         let tab_size = Self::tab_size(&buffer, cx);        let (inlay_map, snapshot) = InlayMap::new(buffer.read(cx).snapshot(cx));        let (fold_map, snapshot) = FoldMap::new(snapshot);        let (tab_map, snapshot) = TabMap::new(snapshot, tab_size);        let (wrap_map, snapshot) = WrapMap::new(snapshot, font_id, font_size, wrap_width, cx);        let block_map = BlockMap::new(snapshot, buffer_header_height, excerpt_header_height);        cx.observe(&wrap_map, |_, _, cx| cx.notify()).detach();        DisplayMap {            buffer,            buffer_subscription,            fold_map,            inlay_map,            tab_map,            wrap_map,            block_map,            text_highlights: Default::default(),            clip_at_line_ends: false,        }    }     pub fn snapshot(&mut self, cx: &mut ModelContext<Self>) -> DisplaySnapshot {        let buffer_snapshot = self.buffer.read(cx).snapshot(cx);        let edits = self.buffer_subscription.consume().into_inner();        let (inlay_snapshot, edits) = self.inlay_map.sync(buffer_snapshot, edits);        let (fold_snapshot, edits) = self.fold_map.read(inlay_snapshot.clone(), edits);        let tab_size = Self::tab_size(&self.buffer, cx);        let (tab_snapshot, edits) = self.tab_map.sync(fold_snapshot.clone(), edits, tab_size);        let (wrap_snapshot, edits) = self            .wrap_map            .update(cx, |map, cx| map.sync(tab_snapshot.clone(), edits, cx));        let block_snapshot = self.block_map.read(wrap_snapshot.clone(), edits);         DisplaySnapshot {            buffer_snapshot: self.buffer.read(cx).snapshot(cx),            fold_snapshot,            inlay_snapshot,            tab_snapshot,            wrap_snapshot,            block_snapshot,            text_highlights: self.text_highlights.clone(),            clip_at_line_ends: self.clip_at_line_ends,        }    }     pub fn set_state(&mut self, other: &DisplaySnapshot, cx: &mut ModelContext<Self>) {        self.fold(            other                .folds_in_range(0..other.buffer_snapshot.len())                .map(|fold| fold.to_offset(&other.buffer_snapshot)),            cx,        );    }     pub fn fold<T: ToOffset>(        &mut self,        ranges: impl IntoIterator<Item = Range<T>>,        cx: &mut ModelContext<Self>,    ) {        let snapshot = self.buffer.read(cx).snapshot(cx);        let edits = self.buffer_subscription.consume().into_inner();        let tab_size = Self::tab_size(&self.buffer, cx);        let (snapshot, edits) = self.inlay_map.sync(snapshot, edits);        let (mut fold_map, snapshot, edits) = self.fold_map.write(snapshot, edits);        let (snapshot, edits) = self.tab_map.sync(snapshot, edits, tab_size);        let (snapshot, edits) = self            .wrap_map            .update(cx, |map, cx| map.sync(snapshot, edits, cx));        self.block_map.read(snapshot, edits);        let (snapshot, edits) = fold_map.fold(ranges);        let (snapshot, edits) = self.tab_map.sync(snapshot, edits, tab_size);        let (snapshot, edits) = self            .wrap_map            .update(cx, |map, cx| map.sync(snapshot, edits, cx));        self.block_map.read(snapshot, edits);    }     pub fn unfold<T: ToOffset>(        &mut self,        ranges: impl IntoIterator<Item = Range<T>>,        inclusive: bool,        cx: &mut ModelContext<Self>,    ) {        let snapshot = self.buffer.read(cx).snapshot(cx);        let edits = self.buffer_subscription.consume().into_inner();        let tab_size = Self::tab_size(&self.buffer, cx);        let (snapshot, edits) = self.inlay_map.sync(snapshot, edits);        let (mut fold_map, snapshot, edits) = self.fold_map.write(snapshot, edits);        let (snapshot, edits) = self.tab_map.sync(snapshot, edits, tab_size);        let (snapshot, edits) = self            .wrap_map            .update(cx, |map, cx| map.sync(snapshot, edits, cx));        self.block_map.read(snapshot, edits);        let (snapshot, edits) = fold_map.unfold(ranges, inclusive);        let (snapshot, edits) = self.tab_map.sync(snapshot, edits, tab_size);        let (snapshot, edits) = self            .wrap_map            .update(cx, |map, cx| map.sync(snapshot, edits, cx));        self.block_map.read(snapshot, edits);    }     pub fn insert_blocks(        &mut self,        blocks: impl IntoIterator<Item = BlockProperties<Anchor>>,        cx: &mut ModelContext<Self>,    ) -> Vec<BlockId> {        let snapshot = self.buffer.read(cx).snapshot(cx);        let edits = self.buffer_subscription.consume().into_inner();        let tab_size = Self::tab_size(&self.buffer, cx);        let (snapshot, edits) = self.inlay_map.sync(snapshot, edits);        let (snapshot, edits) = self.fold_map.read(snapshot, edits);        let (snapshot, edits) = self.tab_map.sync(snapshot, edits, tab_size);        let (snapshot, edits) = self            .wrap_map            .update(cx, |map, cx| map.sync(snapshot, edits, cx));        let mut block_map = self.block_map.write(snapshot, edits);        block_map.insert(blocks)    }     pub fn replace_blocks(&mut self, styles: HashMap<BlockId, RenderBlock>) {        self.block_map.replace(styles);    }     pub fn remove_blocks(&mut self, ids: HashSet<BlockId>, cx: &mut ModelContext<Self>) {        let snapshot = self.buffer.read(cx).snapshot(cx);        let edits = self.buffer_subscription.consume().into_inner();        let tab_size = Self::tab_size(&self.buffer, cx);        let (snapshot, edits) = self.inlay_map.sync(snapshot, edits);        let (snapshot, edits) = self.fold_map.read(snapshot, edits);        let (snapshot, edits) = self.tab_map.sync(snapshot, edits, tab_size);        let (snapshot, edits) = self            .wrap_map            .update(cx, |map, cx| map.sync(snapshot, edits, cx));        let mut block_map = self.block_map.write(snapshot, edits);        block_map.remove(ids);    }     pub fn highlight_text(        &mut self,        type_id: TypeId,        ranges: Vec<Range<Anchor>>,        style: HighlightStyle,    ) {        self.text_highlights.insert(            Some(type_id),            Arc::new((style, ranges.into_iter().map(DocumentRange::Text).collect())),        );    }     pub fn highlight_inlays(        &mut self,        type_id: TypeId,        ranges: Vec<InlayRange>,        style: HighlightStyle,    ) {        self.text_highlights.insert(            Some(type_id),            Arc::new((                style,                ranges.into_iter().map(DocumentRange::Inlay).collect(),            )),        );    }     pub fn text_highlights(&self, type_id: TypeId) -> Option<(HighlightStyle, &[DocumentRange])> {        let highlights = self.text_highlights.get(&Some(type_id))?;        Some((highlights.0, &highlights.1))    }     pub fn clear_text_highlights(        &mut self,        type_id: TypeId,    ) -> Option<Arc<(HighlightStyle, Vec<DocumentRange>)>> {        self.text_highlights.remove(&Some(type_id))    }     pub fn set_font(&self, font_id: FontId, font_size: f32, cx: &mut ModelContext<Self>) -> bool {        self.wrap_map            .update(cx, |map, cx| map.set_font(font_id, font_size, cx))    }     pub fn set_fold_ellipses_color(&mut self, color: Color) -> bool {        self.fold_map.set_ellipses_color(color)    }     pub fn set_wrap_width(&self, width: Option<f32>, cx: &mut ModelContext<Self>) -> bool {        self.wrap_map            .update(cx, |map, cx| map.set_wrap_width(width, cx))    }     pub fn current_inlays(&self) -> impl Iterator<Item = &Inlay> {        self.inlay_map.current_inlays()    }     pub fn splice_inlays(        &mut self,        to_remove: Vec<InlayId>,        to_insert: Vec<Inlay>,        cx: &mut ModelContext<Self>,    ) {        if to_remove.is_empty() && to_insert.is_empty() {            return;        }        let buffer_snapshot = self.buffer.read(cx).snapshot(cx);        let edits = self.buffer_subscription.consume().into_inner();        let (snapshot, edits) = self.inlay_map.sync(buffer_snapshot, edits);        let (snapshot, edits) = self.fold_map.read(snapshot, edits);        let tab_size = Self::tab_size(&self.buffer, cx);        let (snapshot, edits) = self.tab_map.sync(snapshot, edits, tab_size);        let (snapshot, edits) = self            .wrap_map            .update(cx, |map, cx| map.sync(snapshot, edits, cx));        self.block_map.read(snapshot, edits);         let (snapshot, edits) = self.inlay_map.splice(to_remove, to_insert);        let (snapshot, edits) = self.fold_map.read(snapshot, edits);        let (snapshot, edits) = self.tab_map.sync(snapshot, edits, tab_size);        let (snapshot, edits) = self            .wrap_map            .update(cx, |map, cx| map.sync(snapshot, edits, cx));        self.block_map.read(snapshot, edits);    }     fn tab_size(buffer: &ModelHandle<MultiBuffer>, cx: &mut ModelContext<Self>) -> NonZeroU32 {        let language = buffer            .read(cx)            .as_singleton()            .and_then(|buffer| buffer.read(cx).language());        language_settings(language.as_deref(), None, cx).tab_size    }     #[cfg(test)]    pub fn is_rewrapping(&self, cx: &gpui::AppContext) -> bool {        self.wrap_map.read(cx).is_rewrapping()    }} pub struct DisplaySnapshot {    pub buffer_snapshot: MultiBufferSnapshot,    pub fold_snapshot: fold_map::FoldSnapshot,    inlay_snapshot: inlay_map::InlaySnapshot,    tab_snapshot: tab_map::TabSnapshot,    wrap_snapshot: wrap_map::WrapSnapshot,    block_snapshot: block_map::BlockSnapshot,    text_highlights: TextHighlights,    clip_at_line_ends: bool,} impl DisplaySnapshot {    #[cfg(test)]    pub fn fold_count(&self) -> usize {        self.fold_snapshot.fold_count()    }     pub fn is_empty(&self) -> bool {        self.buffer_snapshot.len() == 0    }     pub fn buffer_rows(&self, start_row: u32) -> DisplayBufferRows {        self.block_snapshot.buffer_rows(start_row)    }     pub fn max_buffer_row(&self) -> u32 {        self.buffer_snapshot.max_buffer_row()    }     pub fn prev_line_boundary(&self, mut point: Point) -> (Point, DisplayPoint) {        loop {            let mut inlay_point = self.inlay_snapshot.to_inlay_point(point);            let mut fold_point = self.fold_snapshot.to_fold_point(inlay_point, Bias::Left);            fold_point.0.column = 0;            inlay_point = fold_point.to_inlay_point(&self.fold_snapshot);            point = self.inlay_snapshot.to_buffer_point(inlay_point);             let mut display_point = self.point_to_display_point(point, Bias::Left);            *display_point.column_mut() = 0;            let next_point = self.display_point_to_point(display_point, Bias::Left);            if next_point == point {                return (point, display_point);            }            point = next_point;        }    }     pub fn next_line_boundary(&self, mut point: Point) -> (Point, DisplayPoint) {        loop {            let mut inlay_point = self.inlay_snapshot.to_inlay_point(point);            let mut fold_point = self.fold_snapshot.to_fold_point(inlay_point, Bias::Right);            fold_point.0.column = self.fold_snapshot.line_len(fold_point.row());            inlay_point = fold_point.to_inlay_point(&self.fold_snapshot);            point = self.inlay_snapshot.to_buffer_point(inlay_point);             let mut display_point = self.point_to_display_point(point, Bias::Right);            *display_point.column_mut() = self.line_len(display_point.row());            let next_point = self.display_point_to_point(display_point, Bias::Right);            if next_point == point {                return (point, display_point);            }            point = next_point;        }    }     // used by line_mode selections and tries to match vim behaviour    pub fn expand_to_line(&self, range: Range<Point>) -> Range<Point> {        let new_start = if range.start.row == 0 {            Point::new(0, 0)        } else if range.start.row == self.max_buffer_row()            || (range.end.column > 0 && range.end.row == self.max_buffer_row())        {            Point::new(range.start.row - 1, self.line_len(range.start.row - 1))        } else {            self.prev_line_boundary(range.start).0        };         let new_end = if range.end.column == 0 {            range.end        } else if range.end.row < self.max_buffer_row() {            self.buffer_snapshot                .clip_point(Point::new(range.end.row + 1, 0), Bias::Left)        } else {            self.buffer_snapshot.max_point()        };         new_start..new_end    }     fn point_to_display_point(&self, point: Point, bias: Bias) -> DisplayPoint {        let inlay_point = self.inlay_snapshot.to_inlay_point(point);        let fold_point = self.fold_snapshot.to_fold_point(inlay_point, bias);        let tab_point = self.tab_snapshot.to_tab_point(fold_point);        let wrap_point = self.wrap_snapshot.tab_point_to_wrap_point(tab_point);        let block_point = self.block_snapshot.to_block_point(wrap_point);        DisplayPoint(block_point)    }     fn display_point_to_point(&self, point: DisplayPoint, bias: Bias) -> Point {        self.inlay_snapshot            .to_buffer_point(self.display_point_to_inlay_point(point, bias))    }     pub fn display_point_to_inlay_offset(&self, point: DisplayPoint, bias: Bias) -> InlayOffset {        self.inlay_snapshot            .to_offset(self.display_point_to_inlay_point(point, bias))    }     pub fn anchor_to_inlay_offset(&self, anchor: Anchor) -> InlayOffset {        self.inlay_snapshot            .to_inlay_offset(anchor.to_offset(&self.buffer_snapshot))    }     pub fn inlay_offset_to_display_point(&self, offset: InlayOffset, bias: Bias) -> DisplayPoint {        let inlay_point = self.inlay_snapshot.to_point(offset);        let fold_point = self.fold_snapshot.to_fold_point(inlay_point, bias);        let tab_point = self.tab_snapshot.to_tab_point(fold_point);        let wrap_point = self.wrap_snapshot.tab_point_to_wrap_point(tab_point);        let block_point = self.block_snapshot.to_block_point(wrap_point);        DisplayPoint(block_point)    }     fn display_point_to_inlay_point(&self, point: DisplayPoint, bias: Bias) -> InlayPoint {        let block_point = point.0;        let wrap_point = self.block_snapshot.to_wrap_point(block_point);        let tab_point = self.wrap_snapshot.to_tab_point(wrap_point);        let fold_point = self.tab_snapshot.to_fold_point(tab_point, bias).0;        fold_point.to_inlay_point(&self.fold_snapshot)    }     pub fn display_point_to_fold_point(&self, point: DisplayPoint, bias: Bias) -> FoldPoint {        let block_point = point.0;        let wrap_point = self.block_snapshot.to_wrap_point(block_point);        let tab_point = self.wrap_snapshot.to_tab_point(wrap_point);        self.tab_snapshot.to_fold_point(tab_point, bias).0    }     pub fn fold_point_to_display_point(&self, fold_point: FoldPoint) -> DisplayPoint {        let tab_point = self.tab_snapshot.to_tab_point(fold_point);        let wrap_point = self.wrap_snapshot.tab_point_to_wrap_point(tab_point);        let block_point = self.block_snapshot.to_block_point(wrap_point);        DisplayPoint(block_point)    }     pub fn max_point(&self) -> DisplayPoint {        DisplayPoint(self.block_snapshot.max_point())    }     /// Returns text chunks starting at the given display row until the end of the file    pub fn text_chunks(&self, display_row: u32) -> impl Iterator<Item = &str> {        self.block_snapshot            .chunks(                display_row..self.max_point().row() + 1,                false,                None,                None,                None,            )            .map(|h| h.text)    }     /// Returns text chunks starting at the end of the given display row in reverse until the start of the file    pub fn reverse_text_chunks(&self, display_row: u32) -> impl Iterator<Item = &str> {        (0..=display_row).into_iter().rev().flat_map(|row| {            self.block_snapshot                .chunks(row..row + 1, false, None, None, None)                .map(|h| h.text)                .collect::<Vec<_>>()                .into_iter()                .rev()        })    }     pub fn chunks(        &self,        display_rows: Range<u32>,        language_aware: bool,        hint_highlight_style: Option<HighlightStyle>,        suggestion_highlight_style: Option<HighlightStyle>,    ) -> DisplayChunks<'_> {        self.block_snapshot.chunks(            display_rows,            language_aware,            Some(&self.text_highlights),            hint_highlight_style,            suggestion_highlight_style,        )    } 

Lines 1–500 of 1817.