Don't insert unnecessary space below the end of an inline transformation (#15865)

We achieved this by allowing block decorations to have a height of `0`
and superimposing the border on top of the line, as opposed to carving
out space below it.

Release Notes:

- N/A

---------

Co-authored-by: Jason <jason@zed.dev>
This commit is contained in:
Antonio Scandurra 2024-08-06 19:00:23 +02:00 committed by GitHub
parent 2e27448d5f
commit 104d7adc49
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 55 additions and 11 deletions

View file

@ -334,7 +334,7 @@ impl InlineAssistant {
BlockProperties { BlockProperties {
style: BlockStyle::Sticky, style: BlockStyle::Sticky,
position: range.end, position: range.end,
height: 1, height: 0,
render: Box::new(|cx| { render: Box::new(|cx| {
v_flex() v_flex()
.h_full() .h_full()

View file

@ -972,11 +972,21 @@ impl BlockSnapshot {
pub fn blocks_in_range(&self, rows: Range<u32>) -> impl Iterator<Item = (u32, &Block)> { pub fn blocks_in_range(&self, rows: Range<u32>) -> impl Iterator<Item = (u32, &Block)> {
let mut cursor = self.transforms.cursor::<BlockRow>(); let mut cursor = self.transforms.cursor::<BlockRow>();
cursor.seek(&BlockRow(rows.start), Bias::Right, &()); cursor.seek(&BlockRow(rows.start), Bias::Left, &());
while cursor.start().0 < rows.start && cursor.end(&()).0 <= rows.start {
cursor.next(&());
}
std::iter::from_fn(move || { std::iter::from_fn(move || {
while let Some(transform) = cursor.item() { while let Some(transform) = cursor.item() {
let start_row = cursor.start().0; let start_row = cursor.start().0;
if start_row >= rows.end { if start_row > rows.end
|| (start_row == rows.end
&& transform
.block
.as_ref()
.map_or(false, |block| block.height() > 0))
{
break; break;
} }
if let Some(block) = &transform.block { if let Some(block) = &transform.block {
@ -1188,6 +1198,23 @@ impl Transform {
} }
} }
impl<'a> BlockChunks<'a> {
fn advance(&mut self) {
self.transforms.next(&());
while let Some(transform) = self.transforms.item() {
if transform
.block
.as_ref()
.map_or(false, |block| block.height() == 0)
{
self.transforms.next(&());
} else {
break;
}
}
}
}
impl<'a> Iterator for BlockChunks<'a> { impl<'a> Iterator for BlockChunks<'a> {
type Item = Chunk<'a>; type Item = Chunk<'a>;
@ -1200,7 +1227,7 @@ impl<'a> Iterator for BlockChunks<'a> {
if transform.block.is_some() { if transform.block.is_some() {
let block_start = self.transforms.start().0 .0; let block_start = self.transforms.start().0 .0;
let mut block_end = self.transforms.end(&()).0 .0; let mut block_end = self.transforms.end(&()).0 .0;
self.transforms.next(&()); self.advance();
if self.transforms.item().is_none() { if self.transforms.item().is_none() {
block_end -= 1; block_end -= 1;
} }
@ -1222,7 +1249,7 @@ impl<'a> Iterator for BlockChunks<'a> {
} else { } else {
self.output_row += 1; self.output_row += 1;
if self.output_row < self.max_output_row { if self.output_row < self.max_output_row {
self.transforms.next(&()); self.advance();
return Some(Chunk { return Some(Chunk {
text: "\n", text: "\n",
..Default::default() ..Default::default()
@ -1240,7 +1267,7 @@ impl<'a> Iterator for BlockChunks<'a> {
let (mut prefix, suffix) = self.input_chunk.text.split_at(prefix_bytes); let (mut prefix, suffix) = self.input_chunk.text.split_at(prefix_bytes);
self.input_chunk.text = suffix; self.input_chunk.text = suffix;
if self.output_row == transform_end { if self.output_row == transform_end {
self.transforms.next(&()); self.advance();
} }
if self.masked { if self.masked {
@ -1272,6 +1299,18 @@ impl<'a> Iterator for BlockBufferRows<'a> {
self.transforms.next(&()); self.transforms.next(&());
} }
while let Some(transform) = self.transforms.item() {
if transform
.block
.as_ref()
.map_or(false, |block| block.height() == 0)
{
self.transforms.next(&());
} else {
break;
}
}
let transform = self.transforms.item()?; let transform = self.transforms.item()?;
if transform.block.is_some() { if transform.block.is_some() {
Some(None) Some(None)
@ -1872,7 +1911,7 @@ mod tests {
} else { } else {
BlockDisposition::Below BlockDisposition::Below
}; };
let height = rng.gen_range(1..5); let height = rng.gen_range(0..5);
log::info!( log::info!(
"inserting block {:?} {:?} with height {}", "inserting block {:?} {:?} with height {}",
disposition, disposition,
@ -2083,7 +2122,9 @@ mod tests {
.blocks_in_range(0..(expected_row_count as u32)) .blocks_in_range(0..(expected_row_count as u32))
.map(|(row, block)| (row, block.clone().into())) .map(|(row, block)| (row, block.clone().into()))
.collect::<Vec<_>>(), .collect::<Vec<_>>(),
expected_block_positions expected_block_positions,
"invalid blocks_in_range({:?})",
0..expected_row_count
); );
for (_, expected_block) in for (_, expected_block) in

View file

@ -2379,9 +2379,12 @@ impl EditorElement {
}; };
if let BlockId::Custom(custom_block_id) = block_id { if let BlockId::Custom(custom_block_id) = block_id {
let element_height_in_lines = ((final_size.height / line_height).ceil() as u32).max(1); if block.height() > 0 {
if element_height_in_lines != block.height() { let element_height_in_lines =
resized_blocks.insert(custom_block_id, element_height_in_lines); ((final_size.height / line_height).ceil() as u32).max(1);
if element_height_in_lines != block.height() {
resized_blocks.insert(custom_block_id, element_height_in_lines);
}
} }
} }