Compare commits

...

1 Commits

Author SHA1 Message Date
Richard Feldman
3ee1c903e2 WIP
Co-authored-by: Antonio <antonio@zed.dev>
2024-10-19 22:49:43 -04:00
8 changed files with 253 additions and 158 deletions

View File

@@ -2007,13 +2007,14 @@ impl ContextEditor {
}) })
.map(|(command, error_message)| BlockProperties { .map(|(command, error_message)| BlockProperties {
style: BlockStyle::Fixed, style: BlockStyle::Fixed,
position: Anchor { placement: BlockPlacement::Below {
buffer_id: Some(buffer_id), position: Anchor {
excerpt_id, buffer_id: Some(buffer_id),
text_anchor: command.source_range.start, excerpt_id,
text_anchor: command.source_range.start,
},
}, },
height: 1, height: 1,
disposition: BlockDisposition::Below,
render: slash_command_error_block_renderer(error_message), render: slash_command_error_block_renderer(error_message),
priority: 0, priority: 0,
}), }),
@@ -2240,11 +2241,12 @@ impl ContextEditor {
} else { } else {
let block_ids = editor.insert_blocks( let block_ids = editor.insert_blocks(
[BlockProperties { [BlockProperties {
position: patch_start, placement: BlockLinePlacement::Below {
position: patch_start,
},
height: path_count as u32 + 1, height: path_count as u32 + 1,
style: BlockStyle::Flex, style: BlockStyle::Flex,
render: render_block, render: render_block,
disposition: BlockDisposition::Below,
priority: 0, priority: 0,
}], }],
None, None,
@@ -2729,12 +2731,13 @@ impl ContextEditor {
}) })
}; };
let create_block_properties = |message: &Message| BlockProperties { let create_block_properties = |message: &Message| BlockProperties {
position: buffer placement: BlockLinePlacement::Above {
.anchor_in_excerpt(excerpt_id, message.anchor_range.start) position: buffer
.unwrap(), .anchor_in_excerpt(excerpt_id, message.anchor_range.start)
.unwrap(),
},
height: 2, height: 2,
style: BlockStyle::Sticky, style: BlockStyle::Sticky,
disposition: BlockDisposition::Above,
priority: usize::MAX, priority: usize::MAX,
render: render_block(MessageMetadata::from(message)), render: render_block(MessageMetadata::from(message)),
}; };
@@ -3370,7 +3373,7 @@ impl ContextEditor {
let anchor = buffer.anchor_in_excerpt(excerpt_id, anchor).unwrap(); let anchor = buffer.anchor_in_excerpt(excerpt_id, anchor).unwrap();
let image = render_image.clone(); let image = render_image.clone();
anchor.is_valid(&buffer).then(|| BlockProperties { anchor.is_valid(&buffer).then(|| BlockProperties {
position: anchor, placement: BlockLinePlacement::Above { position: anchor },
height: MAX_HEIGHT_IN_LINES, height: MAX_HEIGHT_IN_LINES,
style: BlockStyle::Sticky, style: BlockStyle::Sticky,
render: Box::new(move |cx| { render: Box::new(move |cx| {
@@ -3391,8 +3394,6 @@ impl ContextEditor {
) )
.into_any_element() .into_any_element()
}), }),
disposition: BlockDisposition::Above,
priority: 0, priority: 0,
}) })
}) })

View File

@@ -29,7 +29,8 @@ use crate::{
}; };
pub use block_map::{ pub use block_map::{
Block, BlockBufferRows, BlockChunks as DisplayChunks, BlockContext, BlockDisposition, BlockId, Block, BlockBufferRows, BlockChunks as DisplayChunks, BlockContext, BlockDisposition, BlockId,
BlockMap, BlockPoint, BlockProperties, BlockStyle, CustomBlockId, RenderBlock, BlockLinePlacement, BlockMap, BlockPoint, BlockProperties, BlockStyle, CustomBlockId,
RenderBlock,
}; };
use block_map::{BlockRow, BlockSnapshot}; use block_map::{BlockRow, BlockSnapshot};
use collections::{HashMap, HashSet}; use collections::{HashMap, HashSet};

View File

@@ -6,7 +6,7 @@ use crate::{EditorStyle, GutterDimensions};
use collections::{Bound, HashMap, HashSet}; use collections::{Bound, HashMap, HashSet};
use gpui::{AnyElement, EntityId, Pixels, WindowContext}; use gpui::{AnyElement, EntityId, Pixels, WindowContext};
use language::{Chunk, Patch, Point}; use language::{Chunk, Patch, Point};
use multi_buffer::{Anchor, ExcerptId, ExcerptInfo, MultiBufferRow, ToPoint as _}; use multi_buffer::{Anchor, AnchorRangeExt, ExcerptId, MultiBufferRow, MultiBufferSnapshot};
use parking_lot::Mutex; use parking_lot::Mutex;
use std::{ use std::{
cell::RefCell, cell::RefCell,
@@ -79,30 +79,101 @@ pub type RenderBlock = Box<dyn Send + FnMut(&mut BlockContext) -> AnyElement>;
pub struct CustomBlock { pub struct CustomBlock {
id: CustomBlockId, id: CustomBlockId,
position: Anchor, placement: BlockLinePlacement<Anchor>,
height: u32, height: u32,
style: BlockStyle, style: BlockStyle,
render: Arc<Mutex<RenderBlock>>, render: Arc<Mutex<RenderBlock>>,
disposition: BlockDisposition,
priority: usize, priority: usize,
} }
#[derive(Clone, Debug)]
pub enum BlockLinePlacement<T> {
Above { position: T },
Below { position: T },
Replace { range: Range<T> },
}
impl BlockLinePlacement<Anchor> {
fn cmp(&self, other: &Self, buffer: &MultiBufferSnapshot) -> Ordering {
fn cmp_between_replace(
(position, disposition): (&Anchor, &BlockDisposition),
range: &Range<Anchor>,
buffer: &MultiBufferSnapshot,
) -> Ordering {
let start_cmp = position.cmp(&range.start, buffer);
if start_cmp.is_lt() {
Ordering::Less
} else if start_cmp.is_eq() {
if disposition.is_below() {
Ordering::Greater
} else {
Ordering::Less
}
} else {
let end_cmp = position.cmp(&range.end, buffer);
if end_cmp.is_gt() {
Ordering::Greater
} else if end_cmp.is_eq() {
if disposition.is_below() {
Ordering::Greater
} else {
Ordering::Less
}
} else {
Ordering::Greater
}
}
}
match (self, other) {
(
BlockLinePlacement::Between {
position: position_a,
disposition: disposition_a,
},
BlockLinePlacement::Between {
position: position_b,
disposition: disposition_b,
},
) => position_a
.cmp(position_b, buffer)
.then_with(|| disposition_a.cmp(disposition_b)),
(
BlockLinePlacement::Between {
position,
disposition,
},
BlockLinePlacement::Replace { range },
) => cmp_between_replace((position, disposition), range, buffer),
(
BlockLinePlacement::Replace { range },
BlockLinePlacement::Between {
position,
disposition,
},
) => cmp_between_replace((position, disposition), range, buffer).reverse(),
(
BlockLinePlacement::Replace { range: range_a },
BlockLinePlacement::Replace { range: range_b },
) => range_a.cmp(range_b, buffer),
}
}
}
pub struct BlockProperties<P> { pub struct BlockProperties<P> {
pub position: P, pub placement: BlockLinePlacement<P>,
pub height: u32, pub height: u32,
pub style: BlockStyle, pub style: BlockStyle,
pub render: RenderBlock, pub render: RenderBlock,
pub disposition: BlockDisposition,
pub priority: usize, pub priority: usize,
} }
impl<P: Debug> Debug for BlockProperties<P> { impl<P: Debug> Debug for BlockProperties<P> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("BlockProperties") f.debug_struct("BlockProperties")
.field("position", &self.position) .field("placement", &self.placement)
.field("height", &self.height) .field("height", &self.height)
.field("style", &self.style) .field("style", &self.style)
.field("disposition", &self.disposition)
.finish() .finish()
} }
} }
@@ -172,7 +243,7 @@ pub(crate) enum BlockType {
pub(crate) trait BlockLike { pub(crate) trait BlockLike {
fn block_type(&self) -> BlockType; fn block_type(&self) -> BlockType;
fn disposition(&self) -> BlockDisposition; fn placement(&self) -> &BlockLinePlacement<Anchor>;
fn priority(&self) -> usize; fn priority(&self) -> usize;
} }
@@ -197,10 +268,6 @@ impl BlockLike for Block {
} }
} }
fn disposition(&self) -> BlockDisposition {
self.disposition()
}
fn priority(&self) -> usize { fn priority(&self) -> usize {
match self { match self {
Block::Custom(block) => block.priority, Block::Custom(block) => block.priority,
@@ -219,19 +286,6 @@ impl Block {
} }
} }
fn disposition(&self) -> BlockDisposition {
match self {
Block::Custom(block) => block.disposition,
Block::ExcerptBoundary { next_excerpt, .. } => {
if next_excerpt.is_some() {
BlockDisposition::Above
} else {
BlockDisposition::Below
}
}
}
}
pub fn height(&self) -> u32 { pub fn height(&self) -> u32 {
match self { match self {
Block::Custom(block) => block.height, Block::Custom(block) => block.height,
@@ -245,6 +299,17 @@ impl Block {
Block::ExcerptBoundary { .. } => BlockStyle::Sticky, Block::ExcerptBoundary { .. } => BlockStyle::Sticky,
} }
} }
fn place_below_line(&self) -> bool {
match self {
Block::Custom(block) => match &block.placement {
BlockLinePlacement::Between { disposition, .. } => disposition.is_below(),
BlockLinePlacement::Replace { .. } => false,
},
Block::ExcerptHeader { .. } => false,
Block::ExcerptFooter { disposition, .. } => disposition.is_below(),
}
}
} }
impl Debug for Block { impl Debug for Block {
@@ -377,18 +442,18 @@ impl BlockMap {
while let Some(edit) = edits.next() { while let Some(edit) = edits.next() {
// Preserve any old transforms that precede this edit. // Preserve any old transforms that precede this edit.
let old_start = WrapRow(edit.old.start); let mut old_start = WrapRow(edit.old.start);
let new_start = WrapRow(edit.new.start); let mut new_start = WrapRow(edit.new.start);
new_transforms.append(cursor.slice(&old_start, Bias::Left, &()), &()); new_transforms.append(cursor.slice(&old_start, Bias::Left, &()), &());
if let Some(transform) = cursor.item() { if let Some(transform) = cursor.item() {
if transform.is_isomorphic() && old_start == cursor.end(&()) { if transform.summary.input_rows > 0 && old_start == cursor.end(&()) {
new_transforms.push(transform.clone(), &()); new_transforms.push(transform.clone(), &());
cursor.next(&()); cursor.next(&());
while let Some(transform) = cursor.item() { while let Some(transform) = cursor.item() {
if transform if transform
.block .block
.as_ref() .as_ref()
.map_or(false, |b| b.disposition().is_below()) .map_or(false, |b| b.place_below_line())
{ {
new_transforms.push(transform.clone(), &()); new_transforms.push(transform.clone(), &());
cursor.next(&()); cursor.next(&());
@@ -399,9 +464,25 @@ impl BlockMap {
} }
} }
// Preserve any portion of an old transform that precedes this edit. let mut skip_blocks_above_start = false;
let extent_before_edit = old_start.0 - cursor.start().0; let transform = cursor.item().unwrap();
push_isomorphic(&mut new_transforms, extent_before_edit); let rows_before_edits = old_start.0 - cursor.start().0;
if rows_before_edits > 0 {
if transform.block.is_none() {
// Preserve any portion of the old isomorphic transform that precedes this edit.
push_isomorphic(&mut new_transforms, rows_before_edits);
} else {
// We landed within a block that replaces some lines, so we
// extend the edit to start at the beginning of the
// replacement.
debug_assert!(transform.summary.input_rows > 0);
old_start.0 -= rows_before_edits;
new_start.0 -= rows_before_edits;
// The blocks *above* it are already in the new transforms, so
// we don't need to re-insert them when querying blocks.
skip_blocks_above_start = true;
}
}
// Skip over any old transforms that intersect this edit. // Skip over any old transforms that intersect this edit.
let mut old_end = WrapRow(edit.old.end); let mut old_end = WrapRow(edit.old.end);
@@ -413,7 +494,7 @@ impl BlockMap {
if transform if transform
.block .block
.as_ref() .as_ref()
.map_or(false, |b| b.disposition().is_below()) .map_or(false, |b| b.place_below_line())
{ {
cursor.next(&()); cursor.next(&());
} else { } else {
@@ -434,7 +515,7 @@ impl BlockMap {
if transform if transform
.block .block
.as_ref() .as_ref()
.map_or(false, |b| b.disposition().is_below()) .map_or(false, |b| b.place_below_line())
{ {
cursor.next(&()); cursor.next(&());
} else { } else {
@@ -631,14 +712,12 @@ impl BlockMap {
}) })
} }
pub(crate) fn sort_blocks<B: BlockLike>(blocks: &mut [(u32, B)]) { pub(crate) fn sort_blocks<T, B: BlockLike>(blocks: &mut [(u32, B)]) {
// Place excerpt headers and footers above custom blocks on the same row // Place excerpt headers and footers above custom blocks on the same row
blocks.sort_unstable_by(|(row_a, block_a), (row_b, block_b)| { blocks.sort_unstable_by(|(row_a, block_a), (row_b, block_b)| {
row_a.cmp(row_b).then_with(|| { row_a.cmp(row_b).then_with(|| {
block_a block_a.placement().cmp(&block_b.placement()).then_with(|| {
.disposition() match ((block_a.block_type()), (block_b.block_type())) {
.cmp(&block_b.disposition())
.then_with(|| match ((block_a.block_type()), (block_b.block_type())) {
(BlockType::ExcerptBoundary, BlockType::ExcerptBoundary) => Ordering::Equal, (BlockType::ExcerptBoundary, BlockType::ExcerptBoundary) => Ordering::Equal,
(BlockType::ExcerptBoundary, _) => Ordering::Less, (BlockType::ExcerptBoundary, _) => Ordering::Less,
(_, BlockType::ExcerptBoundary) => Ordering::Greater, (_, BlockType::ExcerptBoundary) => Ordering::Greater,
@@ -646,7 +725,8 @@ impl BlockMap {
.priority() .priority()
.cmp(&block_a.priority()) .cmp(&block_a.priority())
.then_with(|| a_id.cmp(&b_id)), .then_with(|| a_id.cmp(&b_id)),
}) }
})
}) })
}); });
} }
@@ -710,10 +790,11 @@ impl<'a> DerefMut for BlockMapReader<'a> {
impl<'a> BlockMapReader<'a> { impl<'a> BlockMapReader<'a> {
pub fn row_for_block(&self, block_id: CustomBlockId) -> Option<BlockRow> { pub fn row_for_block(&self, block_id: CustomBlockId) -> Option<BlockRow> {
let block = self.blocks.iter().find(|block| block.id == block_id)?; let block = self.blocks.iter().find(|block| block.id == block_id)?;
let buffer_row = block let position = match &block.placement {
.position BlockLinePlacement::Between { position, .. } => *position,
.to_point(self.wrap_snapshot.buffer_snapshot()) BlockLinePlacement::Replace { range } => range.start,
.row; };
let buffer_row = position.to_point(self.wrap_snapshot.buffer_snapshot()).row;
let wrap_row = self let wrap_row = self
.wrap_snapshot .wrap_snapshot
.make_wrap_point(Point::new(buffer_row, 0), Bias::Left) .make_wrap_point(Point::new(buffer_row, 0), Bias::Left)
@@ -765,36 +846,41 @@ impl<'a> BlockMapWriter<'a> {
let id = CustomBlockId(self.0.next_block_id.fetch_add(1, SeqCst)); let id = CustomBlockId(self.0.next_block_id.fetch_add(1, SeqCst));
ids.push(id); ids.push(id);
let position = block.position; let range = match &block.placement {
let point = position.to_point(buffer); BlockLinePlacement::Between { position, .. } => *position..*position,
let wrap_row = wrap_snapshot BlockLinePlacement::Replace { range } => range.clone(),
.make_wrap_point(Point::new(point.row, 0), Bias::Left)
.row();
let (start_row, end_row) = {
previous_wrap_row_range.take_if(|range| !range.contains(&wrap_row));
let range = previous_wrap_row_range.get_or_insert_with(|| {
let start_row = wrap_snapshot.prev_row_boundary(WrapPoint::new(wrap_row, 0));
let end_row = wrap_snapshot
.next_row_boundary(WrapPoint::new(wrap_row, 0))
.unwrap_or(wrap_snapshot.max_point().row() + 1);
start_row..end_row
});
(range.start, range.end)
}; };
let start_point = range.start.to_point(buffer);
let start_wrap_row = wrap_snapshot
.make_wrap_point(Point::new(start_point.row, 0), Bias::Left)
.row();
let end_point = range.end.to_point(buffer);
let end_wrap_row = wrap_snapshot
.make_wrap_point(Point::new(end_point.row, 0), Bias::Right)
.row();
previous_wrap_row_range.take_if(|range| {
!range.contains(&start_wrap_row) || !range.contains(&end_wrap_row)
});
let wrap_row_range = previous_wrap_row_range.get_or_insert_with(|| {
let start_row = wrap_snapshot.prev_row_boundary(WrapPoint::new(start_wrap_row, 0));
let end_row = wrap_snapshot
.next_row_boundary(WrapPoint::new(end_wrap_row, 0))
.unwrap_or(wrap_snapshot.max_point().row() + 1);
start_row..end_row
});
let block_ix = match self let block_ix = match self
.0 .0
.custom_blocks .custom_blocks
.binary_search_by(|probe| probe.position.cmp(&position, buffer)) .binary_search_by(|probe| probe.placement.cmp(&block.placement, buffer))
{ {
Ok(ix) | Err(ix) => ix, Ok(ix) | Err(ix) => ix,
}; };
let new_block = Arc::new(CustomBlock { let new_block = Arc::new(CustomBlock {
id, id,
position, placement: block.placement,
height: block.height, height: block.height,
render: Arc::new(Mutex::new(block.render)), render: Arc::new(Mutex::new(block.render)),
disposition: block.disposition,
style: block.style, style: block.style,
priority: block.priority, priority: block.priority,
}); });
@@ -802,8 +888,8 @@ impl<'a> BlockMapWriter<'a> {
self.0.custom_blocks_by_id.insert(id, new_block); self.0.custom_blocks_by_id.insert(id, new_block);
edits = edits.compose([Edit { edits = edits.compose([Edit {
old: start_row..end_row, old: wrap_row_range.clone(),
new: start_row..end_row, new: wrap_row_range.clone(),
}]); }]);
} }
@@ -815,38 +901,47 @@ impl<'a> BlockMapWriter<'a> {
let wrap_snapshot = &*self.0.wrap_snapshot.borrow(); let wrap_snapshot = &*self.0.wrap_snapshot.borrow();
let buffer = wrap_snapshot.buffer_snapshot(); let buffer = wrap_snapshot.buffer_snapshot();
let mut edits = Patch::default(); let mut edits = Patch::default();
let mut last_block_buffer_row = None; let mut last_block_end_buffer_row = None;
for block in &mut self.0.custom_blocks { for block in &mut self.0.custom_blocks {
if let Some(new_height) = heights.remove(&block.id) { if let Some(new_height) = heights.remove(&block.id) {
if block.height != new_height { if block.height != new_height {
let new_block = CustomBlock { let new_block = CustomBlock {
id: block.id, id: block.id,
position: block.position, placement: block.placement,
height: new_height, height: new_height,
style: block.style, style: block.style,
render: block.render.clone(), render: block.render.clone(),
disposition: block.disposition,
priority: block.priority, priority: block.priority,
}; };
let new_block = Arc::new(new_block); let new_block = Arc::new(new_block);
*block = new_block.clone(); *block = new_block.clone();
self.0.custom_blocks_by_id.insert(block.id, new_block); self.0.custom_blocks_by_id.insert(block.id, new_block);
let buffer_row = block.position.to_point(buffer).row; let range = match &block.placement {
if last_block_buffer_row != Some(buffer_row) { BlockLinePlacement::Between { position, .. } => *position..*position,
last_block_buffer_row = Some(buffer_row); BlockLinePlacement::Replace { range } => range.clone(),
let wrap_row = wrap_snapshot };
.make_wrap_point(Point::new(buffer_row, 0), Bias::Left)
let end_buffer_row = range.end.to_point(buffer).row;
if last_block_end_buffer_row != Some(end_buffer_row) {
last_block_end_buffer_row = Some(end_buffer_row);
let start_buffer_row = range.start.to_point(buffer).row;
let mut start_wrap_row = wrap_snapshot
.make_wrap_point(Point::new(start_buffer_row, 0), Bias::Left)
.row(); .row();
let start_row = start_wrap_row =
wrap_snapshot.prev_row_boundary(WrapPoint::new(wrap_row, 0)); wrap_snapshot.prev_row_boundary(WrapPoint::new(start_wrap_row, 0));
let end_row = wrap_snapshot
.next_row_boundary(WrapPoint::new(wrap_row, 0)) let mut end_wrap_row = wrap_snapshot
.make_wrap_point(Point::new(end_buffer_row, 0), Bias::Right)
.row();
end_wrap_row = wrap_snapshot
.next_row_boundary(WrapPoint::new(end_wrap_row, 0))
.unwrap_or(wrap_snapshot.max_point().row() + 1); .unwrap_or(wrap_snapshot.max_point().row() + 1);
edits.push(Edit { edits.push(Edit {
old: start_row..end_row, old: start_wrap_row..end_wrap_row,
new: start_row..end_row, new: start_wrap_row..end_wrap_row,
}) })
} }
} }
@@ -1186,10 +1281,6 @@ impl Transform {
block: Some(block), block: Some(block),
} }
} }
fn is_isomorphic(&self) -> bool {
self.block.is_none()
}
} }
impl<'a> BlockChunks<'a> { impl<'a> BlockChunks<'a> {
@@ -1380,10 +1471,6 @@ impl CustomBlock {
self.render.lock()(cx) self.render.lock()(cx)
} }
pub fn position(&self) -> &Anchor {
&self.position
}
pub fn style(&self) -> BlockStyle { pub fn style(&self) -> BlockStyle {
self.style self.style
} }
@@ -1393,8 +1480,7 @@ impl Debug for CustomBlock {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Block") f.debug_struct("Block")
.field("id", &self.id) .field("id", &self.id)
.field("position", &self.position) .field("placement", &self.placement)
.field("disposition", &self.disposition)
.finish() .finish()
} }
} }
@@ -1465,25 +1551,31 @@ mod tests {
let block_ids = writer.insert(vec![ let block_ids = writer.insert(vec![
BlockProperties { BlockProperties {
style: BlockStyle::Fixed, style: BlockStyle::Fixed,
position: buffer_snapshot.anchor_after(Point::new(1, 0)), placement: BlockLinePlacement::Between {
position: buffer_snapshot.anchor_after(Point::new(1, 0)),
disposition: BlockDisposition::Above,
},
height: 1, height: 1,
disposition: BlockDisposition::Above,
render: Box::new(|_| div().into_any()), render: Box::new(|_| div().into_any()),
priority: 0, priority: 0,
}, },
BlockProperties { BlockProperties {
style: BlockStyle::Fixed, style: BlockStyle::Fixed,
position: buffer_snapshot.anchor_after(Point::new(1, 2)), placement: BlockLinePlacement::Between {
position: buffer_snapshot.anchor_after(Point::new(1, 2)),
disposition: BlockDisposition::Above,
},
height: 2, height: 2,
disposition: BlockDisposition::Above,
render: Box::new(|_| div().into_any()), render: Box::new(|_| div().into_any()),
priority: 0, priority: 0,
}, },
BlockProperties { BlockProperties {
style: BlockStyle::Fixed, style: BlockStyle::Fixed,
position: buffer_snapshot.anchor_after(Point::new(3, 3)), placement: BlockLinePlacement::Between {
position: buffer_snapshot.anchor_after(Point::new(3, 3)),
disposition: BlockDisposition::Below,
},
height: 3, height: 3,
disposition: BlockDisposition::Below,
render: Box::new(|_| div().into_any()), render: Box::new(|_| div().into_any()),
priority: 0, priority: 0,
}, },
@@ -1719,25 +1811,31 @@ mod tests {
let block_ids = writer.insert(vec![ let block_ids = writer.insert(vec![
BlockProperties { BlockProperties {
style: BlockStyle::Fixed, style: BlockStyle::Fixed,
position: buffer_snapshot.anchor_after(Point::new(1, 0)), placement: BlockLinePlacement::Between {
position: buffer_snapshot.anchor_after(Point::new(1, 0)),
disposition: BlockDisposition::Above,
},
height: 1, height: 1,
disposition: BlockDisposition::Above,
render: Box::new(|_| div().into_any()), render: Box::new(|_| div().into_any()),
priority: 0, priority: 0,
}, },
BlockProperties { BlockProperties {
style: BlockStyle::Fixed, style: BlockStyle::Fixed,
position: buffer_snapshot.anchor_after(Point::new(1, 2)), placement: BlockLinePlacement::Between {
position: buffer_snapshot.anchor_after(Point::new(1, 2)),
disposition: BlockDisposition::Above,
},
height: 2, height: 2,
disposition: BlockDisposition::Above,
render: Box::new(|_| div().into_any()), render: Box::new(|_| div().into_any()),
priority: 0, priority: 0,
}, },
BlockProperties { BlockProperties {
style: BlockStyle::Fixed, style: BlockStyle::Fixed,
position: buffer_snapshot.anchor_after(Point::new(3, 3)), placement: BlockLinePlacement::Between {
position: buffer_snapshot.anchor_after(Point::new(3, 3)),
disposition: BlockDisposition::Below,
},
height: 3, height: 3,
disposition: BlockDisposition::Below,
render: Box::new(|_| div().into_any()), render: Box::new(|_| div().into_any()),
priority: 0, priority: 0,
}, },
@@ -1825,16 +1923,20 @@ mod tests {
writer.insert(vec![ writer.insert(vec![
BlockProperties { BlockProperties {
style: BlockStyle::Fixed, style: BlockStyle::Fixed,
position: buffer_snapshot.anchor_after(Point::new(1, 12)), placement: BlockLinePlacement::Between {
disposition: BlockDisposition::Above, position: buffer_snapshot.anchor_after(Point::new(1, 12)),
disposition: BlockDisposition::Above,
},
render: Box::new(|_| div().into_any()), render: Box::new(|_| div().into_any()),
height: 1, height: 1,
priority: 0, priority: 0,
}, },
BlockProperties { BlockProperties {
style: BlockStyle::Fixed, style: BlockStyle::Fixed,
position: buffer_snapshot.anchor_after(Point::new(1, 1)), placement: BlockLinePlacement::Between {
disposition: BlockDisposition::Below, position: buffer_snapshot.anchor_after(Point::new(1, 1)),
disposition: BlockDisposition::Below,
},
render: Box::new(|_| div().into_any()), render: Box::new(|_| div().into_any()),
height: 1, height: 1,
priority: 0, priority: 0,
@@ -1931,10 +2033,12 @@ mod tests {
height height
); );
BlockProperties { BlockProperties {
placement: BlockLinePlacement::Between {
position,
disposition,
},
style: BlockStyle::Fixed, style: BlockStyle::Fixed,
position,
height, height,
disposition,
render: Box::new(|_| div().into_any()), render: Box::new(|_| div().into_any()),
priority: 0, priority: 0,
} }
@@ -1952,11 +2056,10 @@ mod tests {
let mut block_map = block_map.write(wraps_snapshot, wrap_edits); let mut block_map = block_map.write(wraps_snapshot, wrap_edits);
let block_ids = let block_ids =
block_map.insert(block_properties.iter().map(|props| BlockProperties { block_map.insert(block_properties.iter().map(|props| BlockProperties {
position: props.position, placement: props.placement,
height: props.height, height: props.height,
style: props.style, style: props.style,
render: Box::new(|_| div().into_any()), render: Box::new(|_| div().into_any()),
disposition: props.disposition,
priority: 0, priority: 0,
})); }));
for (block_id, props) in block_ids.into_iter().zip(block_properties) { for (block_id, props) in block_ids.into_iter().zip(block_properties) {
@@ -2259,10 +2362,6 @@ mod tests {
} }
} }
fn disposition(&self) -> BlockDisposition {
self.disposition()
}
fn priority(&self) -> usize { fn priority(&self) -> usize {
match self { match self {
ExpectedBlock::Custom { priority, .. } => *priority, ExpectedBlock::Custom { priority, .. } => *priority,
@@ -2278,19 +2377,6 @@ mod tests {
ExpectedBlock::Custom { height, .. } => *height, ExpectedBlock::Custom { height, .. } => *height,
} }
} }
fn disposition(&self) -> BlockDisposition {
match self {
ExpectedBlock::ExcerptBoundary { is_last, .. } => {
if *is_last {
BlockDisposition::Below
} else {
BlockDisposition::Above
}
}
ExpectedBlock::Custom { disposition, .. } => *disposition,
}
}
} }
impl From<Block> for ExpectedBlock { impl From<Block> for ExpectedBlock {

View File

@@ -10227,7 +10227,9 @@ impl Editor {
let block_id = this.insert_blocks( let block_id = this.insert_blocks(
[BlockProperties { [BlockProperties {
style: BlockStyle::Flex, style: BlockStyle::Flex,
position: range.start, placement: BlockLinePlacement::Below {
position: range.start,
},
height: 1, height: 1,
render: Box::new({ render: Box::new({
let rename_editor = rename_editor.clone(); let rename_editor = rename_editor.clone();
@@ -10263,7 +10265,6 @@ impl Editor {
.into_any_element() .into_any_element()
} }
}), }),
disposition: BlockDisposition::Below,
priority: 0, priority: 0,
}], }],
Some(Autoscroll::fit()), Some(Autoscroll::fit()),
@@ -10548,10 +10549,11 @@ impl Editor {
let message_height = diagnostic.message.matches('\n').count() as u32 + 1; let message_height = diagnostic.message.matches('\n').count() as u32 + 1;
BlockProperties { BlockProperties {
style: BlockStyle::Fixed, style: BlockStyle::Fixed,
position: buffer.anchor_after(entry.range.start), placement: BlockLinePlacement::Below {
position: buffer.anchor_after(entry.range.start),
},
height: message_height, height: message_height,
render: diagnostic_block_renderer(diagnostic, None, true, true), render: diagnostic_block_renderer(diagnostic, None, true, true),
disposition: BlockDisposition::Below,
priority: 0, priority: 0,
} }
}), }),

View File

@@ -3868,8 +3868,9 @@ fn test_move_line_up_down_with_blocks(cx: &mut TestAppContext) {
editor.insert_blocks( editor.insert_blocks(
[BlockProperties { [BlockProperties {
style: BlockStyle::Fixed, style: BlockStyle::Fixed,
position: snapshot.anchor_after(Point::new(2, 0)), placement: BlockLinePlacement::Below {
disposition: BlockDisposition::Below, position: snapshot.anchor_after(Point::new(2, 0)),
},
height: 1, height: 1,
render: Box::new(|_| div().into_any()), render: Box::new(|_| div().into_any()),
priority: 0, priority: 0,

View File

@@ -6295,9 +6295,9 @@ fn compute_auto_height_layout(
mod tests { mod tests {
use super::*; use super::*;
use crate::{ use crate::{
display_map::{BlockDisposition, BlockProperties}, display_map::BlockProperties,
editor_tests::{init_test, update_test_language_settings}, editor_tests::{init_test, update_test_language_settings},
Editor, MultiBuffer, BlockLinePlacement, Editor, MultiBuffer,
}; };
use gpui::{TestAppContext, VisualTestContext}; use gpui::{TestAppContext, VisualTestContext};
use language::language_settings; use language::language_settings;
@@ -6551,9 +6551,10 @@ mod tests {
editor.insert_blocks( editor.insert_blocks(
[BlockProperties { [BlockProperties {
style: BlockStyle::Fixed, style: BlockStyle::Fixed,
disposition: BlockDisposition::Above, placement: BlockLinePlacement::Above {
position: Anchor::min(),
},
height: 3, height: 3,
position: Anchor::min(),
render: Box::new(|cx| div().h(3. * cx.line_height()).into_any()), render: Box::new(|cx| div().h(3. * cx.line_height()).into_any()),
priority: 0, priority: 0,
}], }],

View File

@@ -15,7 +15,7 @@ use util::RangeExt;
use crate::{ use crate::{
editor_settings::CurrentLineHighlight, hunk_status, hunks_for_selections, ApplyDiffHunk, editor_settings::CurrentLineHighlight, hunk_status, hunks_for_selections, ApplyDiffHunk,
BlockDisposition, BlockProperties, BlockStyle, CustomBlockId, DiffRowHighlight, DisplayRow, BlockLinePlacement, BlockProperties, BlockStyle, CustomBlockId, DiffRowHighlight, DisplayRow,
DisplaySnapshot, Editor, EditorElement, ExpandAllHunkDiffs, GoToHunk, GoToPrevHunk, RevertFile, DisplaySnapshot, Editor, EditorElement, ExpandAllHunkDiffs, GoToHunk, GoToPrevHunk, RevertFile,
RevertSelectedHunks, ToDisplayPoint, ToggleHunkDiff, RevertSelectedHunks, ToDisplayPoint, ToggleHunkDiff,
}; };
@@ -377,10 +377,11 @@ impl Editor {
}; };
BlockProperties { BlockProperties {
position: hunk.multi_buffer_range.start, placement: BlockLinePlacement::Above {
position: hunk.multi_buffer_range.start,
},
height: 1, height: 1,
style: BlockStyle::Sticky, style: BlockStyle::Sticky,
disposition: BlockDisposition::Above,
priority: 0, priority: 0,
render: Box::new({ render: Box::new({
let editor = cx.view().clone(); let editor = cx.view().clone();
@@ -659,10 +660,11 @@ impl Editor {
let hunk = hunk.clone(); let hunk = hunk.clone();
let height = editor_height.max(deleted_text_height); let height = editor_height.max(deleted_text_height);
BlockProperties { BlockProperties {
position: hunk.multi_buffer_range.start, placement: BlockLinePlacement::Above {
position: hunk.multi_buffer_range.start,
},
height, height,
style: BlockStyle::Flex, style: BlockStyle::Flex,
disposition: BlockDisposition::Above,
priority: 0, priority: 0,
render: Box::new(move |cx| { render: Box::new(move |cx| {
let width = EditorElement::diff_hunk_strip_width(cx.line_height()); let width = EditorElement::diff_hunk_strip_width(cx.line_height());

View File

@@ -90,12 +90,13 @@ impl EditorBlock {
let invalidation_anchor = buffer.read(cx).read(cx).anchor_before(next_row_start); let invalidation_anchor = buffer.read(cx).read(cx).anchor_before(next_row_start);
let block = BlockProperties { let block = BlockProperties {
position: code_range.end, placement: BlockLinePlacement::Below {
position: code_range.end,
},
// Take up at least one height for status, allow the editor to determine the real height based on the content from render // Take up at least one height for status, allow the editor to determine the real height based on the content from render
height: 1, height: 1,
style: BlockStyle::Sticky, style: BlockStyle::Sticky,
render: Self::create_output_area_renderer(execution_view.clone(), on_close.clone()), render: Self::create_output_area_renderer(execution_view.clone(), on_close.clone()),
disposition: BlockDisposition::Below,
priority: 0, priority: 0,
}; };