4496 lines · 170.3 KB · Rust
RawDownload
use super::{    Highlights,    fold_map::Chunk,    wrap_map::{self, WrapEdit, WrapPatch, WrapPoint, WrapSnapshot},};use crate::{    EditorStyle, GutterDimensions,    display_map::{Companion, dimensions::RowDelta, wrap_map::WrapRow},};use collections::{Bound, HashMap, HashSet};use gpui::{AnyElement, App, EntityId, Pixels, Window};use language::{Patch, Point};use multi_buffer::{    Anchor, ExcerptId, ExcerptInfo, MultiBuffer, MultiBufferOffset, MultiBufferPoint,    MultiBufferRow, MultiBufferSnapshot, RowInfo, ToOffset, ToPoint as _,};use parking_lot::Mutex;use std::{    cell::RefCell,    cmp::{self, Ordering},    fmt::Debug,    ops::{Deref, DerefMut, Not, Range, RangeBounds, RangeInclusive},    sync::{        Arc,        atomic::{AtomicUsize, Ordering::SeqCst},    },};use sum_tree::{Bias, ContextLessSummary, Dimensions, SumTree, TreeMap};use text::{BufferId, Edit};use ui::ElementId; const NEWLINES: &[u8; rope::Chunk::MASK_BITS] = &[b'\n'; _];const BULLETS: &[u8; rope::Chunk::MASK_BITS] = &[b'*'; _]; /// Tracks custom blocks such as diagnostics that should be displayed within buffer.////// See the [`display_map` module documentation](crate::display_map) for more information.pub struct BlockMap {    pub(super) wrap_snapshot: RefCell<WrapSnapshot>,    next_block_id: AtomicUsize,    custom_blocks: Vec<Arc<CustomBlock>>,    custom_blocks_by_id: TreeMap<CustomBlockId, Arc<CustomBlock>>,    transforms: RefCell<SumTree<Transform>>,    buffer_header_height: u32,    excerpt_header_height: u32,    pub(super) folded_buffers: HashSet<BufferId>,    buffers_with_disabled_headers: HashSet<BufferId>,} pub struct BlockMapReader<'a> {    blocks: &'a Vec<Arc<CustomBlock>>,    pub snapshot: BlockSnapshot,} pub struct BlockMapWriter<'a> {    block_map: &'a mut BlockMap,    companion: Option<BlockMapWriterCompanion<'a>>,} struct BlockMapWriterCompanion<'a>(CompanionView<'a>); impl<'a> Deref for BlockMapWriterCompanion<'a> {    type Target = CompanionView<'a>;     fn deref(&self) -> &Self::Target {        &self.0    }} #[derive(Clone)]pub struct BlockSnapshot {    pub(super) wrap_snapshot: WrapSnapshot,    transforms: SumTree<Transform>,    custom_blocks_by_id: TreeMap<CustomBlockId, Arc<CustomBlock>>,    pub(super) buffer_header_height: u32,    pub(super) excerpt_header_height: u32,} impl Deref for BlockSnapshot {    type Target = WrapSnapshot;     fn deref(&self) -> &Self::Target {        &self.wrap_snapshot    }} #[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]pub struct CustomBlockId(pub usize); impl From<CustomBlockId> for ElementId {    fn from(val: CustomBlockId) -> Self {        val.0.into()    }} #[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]pub struct SpacerId(pub usize); /// A zero-indexed point in a text buffer consisting of a row and column/// adjusted for inserted blocks, wrapped rows, tabs, folds and inlays.#[derive(Copy, Clone, Debug, Default, Eq, Ord, PartialOrd, PartialEq)]pub struct BlockPoint(pub Point); #[derive(Copy, Clone, Debug, Default, Eq, Ord, PartialOrd, PartialEq)]pub struct BlockRow(pub u32); impl_for_row_types! {    BlockRow => RowDelta} impl BlockPoint {    pub fn row(&self) -> BlockRow {        BlockRow(self.0.row)    }} pub type RenderBlock = Arc<dyn Send + Sync + Fn(&mut BlockContext) -> AnyElement>; /// Where to place a block.#[derive(Clone, Debug, Eq, PartialEq)]pub enum BlockPlacement<T> {    /// Place the block above the given position.    Above(T),    /// Place the block below the given position.    Below(T),    /// Place the block next the given position.    Near(T),    /// Replace the given range of positions with the block.    Replace(RangeInclusive<T>),} impl<T> BlockPlacement<T> {    pub fn start(&self) -> &T {        match self {            BlockPlacement::Above(position) => position,            BlockPlacement::Below(position) => position,            BlockPlacement::Near(position) => position,            BlockPlacement::Replace(range) => range.start(),        }    }     fn end(&self) -> &T {        match self {            BlockPlacement::Above(position) => position,            BlockPlacement::Below(position) => position,            BlockPlacement::Near(position) => position,            BlockPlacement::Replace(range) => range.end(),        }    }     pub fn as_ref(&self) -> BlockPlacement<&T> {        match self {            BlockPlacement::Above(position) => BlockPlacement::Above(position),            BlockPlacement::Below(position) => BlockPlacement::Below(position),            BlockPlacement::Near(position) => BlockPlacement::Near(position),            BlockPlacement::Replace(range) => BlockPlacement::Replace(range.start()..=range.end()),        }    }     pub fn map<R>(self, mut f: impl FnMut(T) -> R) -> BlockPlacement<R> {        match self {            BlockPlacement::Above(position) => BlockPlacement::Above(f(position)),            BlockPlacement::Below(position) => BlockPlacement::Below(f(position)),            BlockPlacement::Near(position) => BlockPlacement::Near(f(position)),            BlockPlacement::Replace(range) => {                let (start, end) = range.into_inner();                BlockPlacement::Replace(f(start)..=f(end))            }        }    }     fn tie_break(&self) -> u8 {        match self {            BlockPlacement::Replace(_) => 0,            BlockPlacement::Above(_) => 1,            BlockPlacement::Near(_) => 2,            BlockPlacement::Below(_) => 3,        }    }} impl BlockPlacement<Anchor> {    #[ztracing::instrument(skip_all)]    fn cmp(&self, other: &Self, buffer: &MultiBufferSnapshot) -> Ordering {        self.start()            .cmp(other.start(), buffer)            .then_with(|| other.end().cmp(self.end(), buffer))            .then_with(|| self.tie_break().cmp(&other.tie_break()))    }     #[ztracing::instrument(skip_all)]    fn to_wrap_row(&self, wrap_snapshot: &WrapSnapshot) -> Option<BlockPlacement<WrapRow>> {        let buffer_snapshot = wrap_snapshot.buffer_snapshot();        match self {            BlockPlacement::Above(position) => {                let mut position = position.to_point(buffer_snapshot);                position.column = 0;                let wrap_row = wrap_snapshot.make_wrap_point(position, Bias::Left).row();                Some(BlockPlacement::Above(wrap_row))            }            BlockPlacement::Near(position) => {                let mut position = position.to_point(buffer_snapshot);                position.column = buffer_snapshot.line_len(MultiBufferRow(position.row));                let wrap_row = wrap_snapshot.make_wrap_point(position, Bias::Left).row();                Some(BlockPlacement::Near(wrap_row))            }            BlockPlacement::Below(position) => {                let mut position = position.to_point(buffer_snapshot);                position.column = buffer_snapshot.line_len(MultiBufferRow(position.row));                let wrap_row = wrap_snapshot.make_wrap_point(position, Bias::Left).row();                Some(BlockPlacement::Below(wrap_row))            }            BlockPlacement::Replace(range) => {                let mut start = range.start().to_point(buffer_snapshot);                let mut end = range.end().to_point(buffer_snapshot);                if start == end {                    None                } else {                    start.column = 0;                    let start_wrap_row = wrap_snapshot.make_wrap_point(start, Bias::Left).row();                    end.column = buffer_snapshot.line_len(MultiBufferRow(end.row));                    let end_wrap_row = wrap_snapshot.make_wrap_point(end, Bias::Left).row();                    Some(BlockPlacement::Replace(start_wrap_row..=end_wrap_row))                }            }        }    }} pub struct CustomBlock {    pub id: CustomBlockId,    pub placement: BlockPlacement<Anchor>,    pub height: Option<u32>,    style: BlockStyle,    render: Arc<Mutex<RenderBlock>>,    priority: usize,} #[derive(Clone)]pub struct BlockProperties<P> {    pub placement: BlockPlacement<P>,    // None if the block takes up no space    // (e.g. a horizontal line)    pub height: Option<u32>,    pub style: BlockStyle,    pub render: RenderBlock,    pub priority: usize,} impl<P: Debug> Debug for BlockProperties<P> {    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {        f.debug_struct("BlockProperties")            .field("placement", &self.placement)            .field("height", &self.height)            .field("style", &self.style)            .finish()    }} #[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]pub enum BlockStyle {    Fixed,    Flex,    Sticky,} #[derive(Debug, Default, Copy, Clone)]pub struct EditorMargins {    pub gutter: GutterDimensions,    pub right: Pixels,} #[derive(gpui::AppContext, gpui::VisualContext)]pub struct BlockContext<'a, 'b> {    #[window]    pub window: &'a mut Window,    #[app]    pub app: &'b mut App,    pub anchor_x: Pixels,    pub max_width: Pixels,    pub margins: &'b EditorMargins,    pub em_width: Pixels,    pub line_height: Pixels,    pub block_id: BlockId,    pub selected: bool,    pub editor_style: &'b EditorStyle,} #[derive(Debug, Clone, Copy, PartialEq, Eq, Ord, PartialOrd, Hash)]pub enum BlockId {    ExcerptBoundary(ExcerptId),    FoldedBuffer(ExcerptId),    Custom(CustomBlockId),    Spacer(SpacerId),} impl From<BlockId> for ElementId {    fn from(value: BlockId) -> Self {        match value {            BlockId::Custom(CustomBlockId(id)) => ("Block", id).into(),            BlockId::ExcerptBoundary(excerpt_id) => {                ("ExcerptBoundary", EntityId::from(excerpt_id)).into()            }            BlockId::FoldedBuffer(id) => ("FoldedBuffer", EntityId::from(id)).into(),            BlockId::Spacer(SpacerId(id)) => ("Spacer", id).into(),        }    }} impl std::fmt::Display for BlockId {    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {        match self {            Self::Custom(id) => write!(f, "Block({id:?})"),            Self::ExcerptBoundary(id) => write!(f, "ExcerptHeader({id:?})"),            Self::FoldedBuffer(id) => write!(f, "FoldedBuffer({id:?})"),            Self::Spacer(id) => write!(f, "Spacer({id:?})"),        }    }} #[derive(Clone, Debug)]struct Transform {    summary: TransformSummary,    block: Option<Block>,} #[derive(Clone)]pub enum Block {    Custom(Arc<CustomBlock>),    FoldedBuffer {        first_excerpt: ExcerptInfo,        height: u32,    },    ExcerptBoundary {        excerpt: ExcerptInfo,        height: u32,    },    BufferHeader {        excerpt: ExcerptInfo,        height: u32,    },    Spacer {        id: SpacerId,        height: u32,        is_below: bool,    },} impl Block {    pub fn id(&self) -> BlockId {        match self {            Block::Custom(block) => BlockId::Custom(block.id),            Block::ExcerptBoundary {                excerpt: next_excerpt,                ..            } => BlockId::ExcerptBoundary(next_excerpt.id),            Block::FoldedBuffer { first_excerpt, .. } => BlockId::FoldedBuffer(first_excerpt.id),            Block::BufferHeader {                excerpt: next_excerpt,                ..            } => BlockId::ExcerptBoundary(next_excerpt.id),            Block::Spacer { id, .. } => BlockId::Spacer(*id),        }    }     pub fn has_height(&self) -> bool {        match self {            Block::Custom(block) => block.height.is_some(),            Block::ExcerptBoundary { .. }            | Block::FoldedBuffer { .. }            | Block::BufferHeader { .. }            | Block::Spacer { .. } => true,        }    }     pub fn height(&self) -> u32 {        match self {            Block::Custom(block) => block.height.unwrap_or(0),            Block::ExcerptBoundary { height, .. }            | Block::FoldedBuffer { height, .. }            | Block::BufferHeader { height, .. }            | Block::Spacer { height, .. } => *height,        }    }     pub fn style(&self) -> BlockStyle {        match self {            Block::Custom(block) => block.style,            Block::ExcerptBoundary { .. }            | Block::FoldedBuffer { .. }            | Block::BufferHeader { .. }            | Block::Spacer { .. } => BlockStyle::Sticky,        }    }     fn place_above(&self) -> bool {        match self {            Block::Custom(block) => matches!(block.placement, BlockPlacement::Above(_)),            Block::FoldedBuffer { .. } => false,            Block::ExcerptBoundary { .. } => true,            Block::BufferHeader { .. } => true,            Block::Spacer { is_below, .. } => !*is_below,        }    }     pub fn place_near(&self) -> bool {        match self {            Block::Custom(block) => matches!(block.placement, BlockPlacement::Near(_)),            Block::FoldedBuffer { .. } => false,            Block::ExcerptBoundary { .. } => false,            Block::BufferHeader { .. } => false,            Block::Spacer { .. } => false,        }    }     fn place_below(&self) -> bool {        match self {            Block::Custom(block) => matches!(                block.placement,                BlockPlacement::Below(_) | BlockPlacement::Near(_)            ),            Block::FoldedBuffer { .. } => false,            Block::ExcerptBoundary { .. } => false,            Block::BufferHeader { .. } => false,            Block::Spacer { is_below, .. } => *is_below,        }    }     fn is_replacement(&self) -> bool {        match self {            Block::Custom(block) => matches!(block.placement, BlockPlacement::Replace(_)),            Block::FoldedBuffer { .. } => true,            Block::ExcerptBoundary { .. } => false,            Block::BufferHeader { .. } => false,            Block::Spacer { .. } => false,        }    }     fn is_header(&self) -> bool {        match self {            Block::Custom(_) => false,            Block::FoldedBuffer { .. } => true,            Block::ExcerptBoundary { .. } => true,            Block::BufferHeader { .. } => true,            Block::Spacer { .. } => false,        }    }     pub fn is_buffer_header(&self) -> bool {        match self {            Block::Custom(_) => false,            Block::FoldedBuffer { .. } => true,            Block::ExcerptBoundary { .. } => false,            Block::BufferHeader { .. } => true,            Block::Spacer { .. } => false,        }    }} impl Debug for Block {    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {        match self {            Self::Custom(block) => f.debug_struct("Custom").field("block", block).finish(),            Self::FoldedBuffer {                first_excerpt,                height,            } => f                .debug_struct("FoldedBuffer")                .field("first_excerpt", &first_excerpt)                .field("height", height)                .finish(),            Self::ExcerptBoundary { excerpt, height } => f                .debug_struct("ExcerptBoundary")                .field("excerpt", excerpt)                .field("height", height)                .finish(),            Self::BufferHeader { excerpt, height } => f                .debug_struct("BufferHeader")                .field("excerpt", excerpt)                .field("height", height)                .finish(),            Self::Spacer {                id,                height,                is_below: _,            } => f                .debug_struct("Spacer")                .field("id", id)                .field("height", height)                .finish(),        }    }} #[derive(Clone, Debug, Default)]struct TransformSummary {    input_rows: WrapRow,    output_rows: BlockRow,    longest_row: BlockRow,    longest_row_chars: u32,

Lines 1–500 of 4496.