WIP
This commit is contained in:
@@ -275,7 +275,7 @@ impl DisplaySnapshot {
|
||||
|
||||
pub fn text_chunks(&self, display_row: u32) -> impl Iterator<Item = &str> {
|
||||
self.blocks_snapshot
|
||||
.chunks(display_row..self.max_point().row() + 1, false)
|
||||
.chunks(display_row..self.max_point().row() + 1, false, None)
|
||||
.map(|h| h.text)
|
||||
}
|
||||
|
||||
@@ -284,7 +284,8 @@ impl DisplaySnapshot {
|
||||
display_rows: Range<u32>,
|
||||
language_aware: bool,
|
||||
) -> DisplayChunks<'a> {
|
||||
self.blocks_snapshot.chunks(display_rows, language_aware)
|
||||
self.blocks_snapshot
|
||||
.chunks(display_rows, language_aware, Some(&self.text_highlights))
|
||||
}
|
||||
|
||||
pub fn chars_at<'a>(&'a self, point: DisplayPoint) -> impl Iterator<Item = char> + 'a {
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
use super::wrap_map::{self, WrapEdit, WrapPoint, WrapSnapshot};
|
||||
use super::{
|
||||
wrap_map::{self, WrapEdit, WrapPoint, WrapSnapshot},
|
||||
TextHighlights,
|
||||
};
|
||||
use crate::{Anchor, ToPoint as _};
|
||||
use collections::{Bound, HashMap, HashSet};
|
||||
use gpui::{AppContext, ElementBox};
|
||||
@@ -555,12 +558,17 @@ impl<'a> BlockMapWriter<'a> {
|
||||
impl BlockSnapshot {
|
||||
#[cfg(test)]
|
||||
pub fn text(&self) -> String {
|
||||
self.chunks(0..self.transforms.summary().output_rows, false)
|
||||
self.chunks(0..self.transforms.summary().output_rows, false, None)
|
||||
.map(|chunk| chunk.text)
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn chunks<'a>(&'a self, rows: Range<u32>, language_aware: bool) -> BlockChunks<'a> {
|
||||
pub fn chunks<'a>(
|
||||
&'a self,
|
||||
rows: Range<u32>,
|
||||
language_aware: bool,
|
||||
text_highlights: Option<&'a TextHighlights>,
|
||||
) -> BlockChunks<'a> {
|
||||
let max_output_row = cmp::min(rows.end, self.transforms.summary().output_rows);
|
||||
let mut cursor = self.transforms.cursor::<(BlockRow, WrapRow)>();
|
||||
let input_end = {
|
||||
@@ -588,9 +596,11 @@ impl BlockSnapshot {
|
||||
cursor.start().1 .0 + overshoot
|
||||
};
|
||||
BlockChunks {
|
||||
input_chunks: self
|
||||
.wrap_snapshot
|
||||
.chunks(input_start..input_end, language_aware),
|
||||
input_chunks: self.wrap_snapshot.chunks(
|
||||
input_start..input_end,
|
||||
language_aware,
|
||||
text_highlights,
|
||||
),
|
||||
input_chunk: Default::default(),
|
||||
transforms: cursor,
|
||||
output_row: rows.start,
|
||||
@@ -1436,7 +1446,11 @@ mod tests {
|
||||
for start_row in 0..expected_row_count {
|
||||
let expected_text = expected_lines[start_row..].join("\n");
|
||||
let actual_text = blocks_snapshot
|
||||
.chunks(start_row as u32..blocks_snapshot.max_point().row + 1, false)
|
||||
.chunks(
|
||||
start_row as u32..blocks_snapshot.max_point().row + 1,
|
||||
false,
|
||||
None,
|
||||
)
|
||||
.map(|chunk| chunk.text)
|
||||
.collect::<String>();
|
||||
assert_eq!(
|
||||
|
||||
@@ -2,16 +2,22 @@ use crate::{
|
||||
multi_buffer::MultiBufferRows, Anchor, AnchorRangeExt, MultiBufferChunks, MultiBufferSnapshot,
|
||||
ToOffset,
|
||||
};
|
||||
use collections::BTreeMap;
|
||||
use gpui::fonts::HighlightStyle;
|
||||
use language::{Chunk, Edit, Point, PointUtf16, TextSummary};
|
||||
use parking_lot::Mutex;
|
||||
use std::{
|
||||
any::TypeId,
|
||||
cmp::{self, Ordering},
|
||||
iter,
|
||||
iter::{self, Peekable},
|
||||
ops::{Range, Sub},
|
||||
sync::atomic::{AtomicUsize, Ordering::SeqCst},
|
||||
vec,
|
||||
};
|
||||
use sum_tree::{Bias, Cursor, FilterCursor, SumTree};
|
||||
|
||||
use super::TextHighlights;
|
||||
|
||||
pub trait ToFoldPoint {
|
||||
fn to_fold_point(&self, snapshot: &FoldSnapshot, bias: Bias) -> FoldPoint;
|
||||
}
|
||||
@@ -95,6 +101,12 @@ impl ToFoldPoint for Point {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> sum_tree::Dimension<'a, TransformSummary> for FoldPoint {
|
||||
fn add_summary(&mut self, summary: &'a TransformSummary, _: &()) {
|
||||
self.0 += &summary.output.lines;
|
||||
}
|
||||
}
|
||||
|
||||
pub struct FoldMapWriter<'a>(&'a mut FoldMap);
|
||||
|
||||
impl<'a> FoldMapWriter<'a> {
|
||||
@@ -500,7 +512,7 @@ impl FoldSnapshot {
|
||||
|
||||
#[cfg(test)]
|
||||
pub fn text(&self) -> String {
|
||||
self.chunks(FoldOffset(0)..self.len(), false)
|
||||
self.chunks(FoldOffset(0)..self.len(), false, None)
|
||||
.map(|c| c.text)
|
||||
.collect()
|
||||
}
|
||||
@@ -640,20 +652,96 @@ impl FoldSnapshot {
|
||||
|
||||
pub fn chars_at(&self, start: FoldPoint) -> impl '_ + Iterator<Item = char> {
|
||||
let start = start.to_offset(self);
|
||||
self.chunks(start..self.len(), false)
|
||||
self.chunks(start..self.len(), false, None)
|
||||
.flat_map(|chunk| chunk.text.chars())
|
||||
}
|
||||
|
||||
pub fn chunks<'a>(&'a self, range: Range<FoldOffset>, language_aware: bool) -> FoldChunks<'a> {
|
||||
pub fn chunks<'a>(
|
||||
&'a self,
|
||||
range: Range<FoldOffset>,
|
||||
language_aware: bool,
|
||||
text_highlights: Option<&'a TextHighlights>,
|
||||
) -> FoldChunks<'a> {
|
||||
let mut highlight_endpoints = Vec::new();
|
||||
let mut transform_cursor = self.transforms.cursor::<(FoldOffset, usize)>();
|
||||
|
||||
transform_cursor.seek(&range.end, Bias::Right, &());
|
||||
let overshoot = range.end.0 - transform_cursor.start().0 .0;
|
||||
let buffer_end = transform_cursor.start().1 + overshoot;
|
||||
let buffer_end = {
|
||||
transform_cursor.seek(&range.end, Bias::Right, &());
|
||||
let overshoot = range.end.0 - transform_cursor.start().0 .0;
|
||||
transform_cursor.start().1 + overshoot
|
||||
};
|
||||
|
||||
transform_cursor.seek(&range.start, Bias::Right, &());
|
||||
let overshoot = range.start.0 - transform_cursor.start().0 .0;
|
||||
let buffer_start = transform_cursor.start().1 + overshoot;
|
||||
let buffer_start = {
|
||||
transform_cursor.seek(&range.start, Bias::Right, &());
|
||||
let overshoot = range.start.0 - transform_cursor.start().0 .0;
|
||||
transform_cursor.start().1 + overshoot
|
||||
};
|
||||
|
||||
if let Some(text_highlights) = text_highlights {
|
||||
if !text_highlights.is_empty() {
|
||||
while transform_cursor.start().0 < range.end {
|
||||
if !transform_cursor.item().unwrap().is_fold() {
|
||||
let transform_start = self
|
||||
.buffer_snapshot
|
||||
.anchor_after(cmp::max(buffer_start, transform_cursor.start().1));
|
||||
|
||||
let transform_end = {
|
||||
let overshoot = range.end.0 - transform_cursor.start().0 .0;
|
||||
self.buffer_snapshot.anchor_before(cmp::min(
|
||||
transform_cursor.end(&()).1,
|
||||
transform_cursor.start().1 + overshoot,
|
||||
))
|
||||
};
|
||||
|
||||
for (tag, highlights) in text_highlights.iter() {
|
||||
let style = highlights.0;
|
||||
let ranges = &highlights.1;
|
||||
|
||||
let start_ix = match ranges.binary_search_by(|probe| {
|
||||
let cmp = probe
|
||||
.end
|
||||
.cmp(&transform_start, &self.buffer_snapshot())
|
||||
.unwrap();
|
||||
if cmp.is_gt() {
|
||||
Ordering::Greater
|
||||
} else {
|
||||
Ordering::Less
|
||||
}
|
||||
}) {
|
||||
Ok(i) | Err(i) => i,
|
||||
};
|
||||
for range in &ranges[start_ix..] {
|
||||
if range
|
||||
.start
|
||||
.cmp(&transform_end, &self.buffer_snapshot)
|
||||
.unwrap()
|
||||
.is_ge()
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
highlight_endpoints.push(HighlightEndpoint {
|
||||
offset: range.start.to_offset(&self.buffer_snapshot),
|
||||
is_start: true,
|
||||
tag: *tag,
|
||||
style,
|
||||
});
|
||||
highlight_endpoints.push(HighlightEndpoint {
|
||||
offset: range.end.to_offset(&self.buffer_snapshot),
|
||||
is_start: false,
|
||||
tag: *tag,
|
||||
style,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
transform_cursor.next(&());
|
||||
}
|
||||
highlight_endpoints.sort();
|
||||
transform_cursor.seek(&range.start, Bias::Right, &());
|
||||
}
|
||||
}
|
||||
|
||||
FoldChunks {
|
||||
transform_cursor,
|
||||
@@ -664,6 +752,8 @@ impl FoldSnapshot {
|
||||
buffer_offset: buffer_start,
|
||||
output_offset: range.start.0,
|
||||
max_output_offset: range.end.0,
|
||||
highlight_endpoints: highlight_endpoints.into_iter().peekable(),
|
||||
active_highlights: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -952,6 +1042,8 @@ pub struct FoldChunks<'a> {
|
||||
buffer_offset: usize,
|
||||
output_offset: usize,
|
||||
max_output_offset: usize,
|
||||
highlight_endpoints: Peekable<vec::IntoIter<HighlightEndpoint>>,
|
||||
active_highlights: BTreeMap<Option<TypeId>, HighlightStyle>,
|
||||
}
|
||||
|
||||
impl<'a> Iterator for FoldChunks<'a> {
|
||||
@@ -990,6 +1082,21 @@ impl<'a> Iterator for FoldChunks<'a> {
|
||||
});
|
||||
}
|
||||
|
||||
let mut next_highlight_endpoint = usize::MAX;
|
||||
while let Some(endpoint) = self.highlight_endpoints.peek().copied() {
|
||||
if endpoint.offset <= self.buffer_offset {
|
||||
if endpoint.is_start {
|
||||
self.active_highlights.insert(endpoint.tag, endpoint.style);
|
||||
} else {
|
||||
self.active_highlights.remove(&endpoint.tag);
|
||||
}
|
||||
self.highlight_endpoints.next();
|
||||
} else {
|
||||
next_highlight_endpoint = endpoint.offset;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Retrieve a chunk from the current location in the buffer.
|
||||
if self.buffer_chunk.is_none() {
|
||||
let chunk_offset = self.buffer_chunks.offset();
|
||||
@@ -997,20 +1104,31 @@ impl<'a> Iterator for FoldChunks<'a> {
|
||||
}
|
||||
|
||||
// Otherwise, take a chunk from the buffer's text.
|
||||
if let Some((chunk_offset, mut chunk)) = self.buffer_chunk {
|
||||
let offset_in_chunk = self.buffer_offset - chunk_offset;
|
||||
chunk.text = &chunk.text[offset_in_chunk..];
|
||||
if let Some((buffer_chunk_start, mut chunk)) = self.buffer_chunk {
|
||||
let buffer_chunk_end = buffer_chunk_start + chunk.text.len();
|
||||
let transform_end = self.transform_cursor.end(&()).1;
|
||||
let chunk_end = buffer_chunk_end
|
||||
.min(transform_end)
|
||||
.min(next_highlight_endpoint);
|
||||
|
||||
// Truncate the chunk so that it ends at the next fold.
|
||||
let region_end = self.transform_cursor.end(&()).1 - self.buffer_offset;
|
||||
if chunk.text.len() >= region_end {
|
||||
chunk.text = &chunk.text[0..region_end];
|
||||
chunk.text = &chunk.text
|
||||
[self.buffer_offset - buffer_chunk_start..chunk_end - buffer_chunk_start];
|
||||
|
||||
if !self.active_highlights.is_empty() {
|
||||
let mut highlight_style = HighlightStyle::default();
|
||||
for active_highlight in self.active_highlights.values() {
|
||||
highlight_style.highlight(*active_highlight);
|
||||
}
|
||||
chunk.highlight_style = Some(highlight_style);
|
||||
}
|
||||
|
||||
if chunk_end == transform_end {
|
||||
self.transform_cursor.next(&());
|
||||
} else {
|
||||
} else if chunk_end == buffer_chunk_end {
|
||||
self.buffer_chunk.take();
|
||||
}
|
||||
|
||||
self.buffer_offset += chunk.text.len();
|
||||
self.buffer_offset = chunk_end;
|
||||
self.output_offset += chunk.text.len();
|
||||
return Some(chunk);
|
||||
}
|
||||
@@ -1019,9 +1137,25 @@ impl<'a> Iterator for FoldChunks<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> sum_tree::Dimension<'a, TransformSummary> for FoldPoint {
|
||||
fn add_summary(&mut self, summary: &'a TransformSummary, _: &()) {
|
||||
self.0 += &summary.output.lines;
|
||||
#[derive(Copy, Clone, Eq, PartialEq)]
|
||||
struct HighlightEndpoint {
|
||||
offset: usize,
|
||||
is_start: bool,
|
||||
tag: Option<TypeId>,
|
||||
style: HighlightStyle,
|
||||
}
|
||||
|
||||
impl PartialOrd for HighlightEndpoint {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||
Some(self.cmp(other))
|
||||
}
|
||||
}
|
||||
|
||||
impl Ord for HighlightEndpoint {
|
||||
fn cmp(&self, other: &Self) -> Ordering {
|
||||
self.offset
|
||||
.cmp(&other.offset)
|
||||
.then_with(|| self.is_start.cmp(&other.is_start))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1078,7 +1212,8 @@ mod tests {
|
||||
use super::*;
|
||||
use crate::{MultiBuffer, ToPoint};
|
||||
use rand::prelude::*;
|
||||
use std::{env, mem};
|
||||
use std::{cmp::Reverse, env, mem, sync::Arc};
|
||||
use sum_tree::TreeMap;
|
||||
use text::RandomCharIter;
|
||||
use util::test::sample_text;
|
||||
use Bias::{Left, Right};
|
||||
@@ -1283,6 +1418,25 @@ mod tests {
|
||||
let (mut initial_snapshot, _) = map.read(buffer_snapshot.clone(), vec![]);
|
||||
let mut snapshot_edits = Vec::new();
|
||||
|
||||
let mut highlights = TreeMap::default();
|
||||
let highlight_count = rng.gen_range(0_usize..10);
|
||||
let mut highlight_ranges = (0..highlight_count)
|
||||
.map(|_| buffer_snapshot.random_byte_range(0, &mut rng))
|
||||
.collect::<Vec<_>>();
|
||||
highlight_ranges.sort_by_key(|range| (range.start, Reverse(range.end)));
|
||||
log::info!("highlighting ranges {:?}", highlight_ranges);
|
||||
let highlight_ranges = highlight_ranges
|
||||
.into_iter()
|
||||
.map(|range| {
|
||||
buffer_snapshot.anchor_before(range.start)..buffer_snapshot.anchor_after(range.end)
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
highlights.insert(
|
||||
Some(TypeId::of::<()>()),
|
||||
Arc::new((HighlightStyle::default(), highlight_ranges)),
|
||||
);
|
||||
|
||||
for _ in 0..operations {
|
||||
log::info!("text: {:?}", buffer_snapshot.text());
|
||||
let mut buffer_edits = Vec::new();
|
||||
@@ -1407,7 +1561,7 @@ mod tests {
|
||||
let text = &expected_text[start.0..end.0];
|
||||
assert_eq!(
|
||||
snapshot
|
||||
.chunks(start..end, false)
|
||||
.chunks(start..end, false, Some(&highlights))
|
||||
.map(|c| c.text)
|
||||
.collect::<String>(),
|
||||
text,
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
use super::fold_map::{self, FoldEdit, FoldPoint, FoldSnapshot, ToFoldPoint};
|
||||
use super::{
|
||||
fold_map::{self, FoldEdit, FoldPoint, FoldSnapshot, ToFoldPoint},
|
||||
TextHighlights,
|
||||
};
|
||||
use crate::MultiBufferSnapshot;
|
||||
use language::{rope, Chunk};
|
||||
use parking_lot::Mutex;
|
||||
@@ -32,9 +35,10 @@ impl TabMap {
|
||||
let mut tab_edits = Vec::with_capacity(fold_edits.len());
|
||||
for fold_edit in &mut fold_edits {
|
||||
let mut delta = 0;
|
||||
for chunk in old_snapshot
|
||||
.fold_snapshot
|
||||
.chunks(fold_edit.old.end..max_offset, false)
|
||||
for chunk in
|
||||
old_snapshot
|
||||
.fold_snapshot
|
||||
.chunks(fold_edit.old.end..max_offset, false, None)
|
||||
{
|
||||
let patterns: &[_] = &['\t', '\n'];
|
||||
if let Some(ix) = chunk.text.find(patterns) {
|
||||
@@ -109,7 +113,7 @@ impl TabSnapshot {
|
||||
self.max_point()
|
||||
};
|
||||
for c in self
|
||||
.chunks(range.start..line_end, false)
|
||||
.chunks(range.start..line_end, false, None)
|
||||
.flat_map(|chunk| chunk.text.chars())
|
||||
{
|
||||
if c == '\n' {
|
||||
@@ -123,7 +127,7 @@ impl TabSnapshot {
|
||||
last_line_chars = first_line_chars;
|
||||
} else {
|
||||
for _ in self
|
||||
.chunks(TabPoint::new(range.end.row(), 0)..range.end, false)
|
||||
.chunks(TabPoint::new(range.end.row(), 0)..range.end, false, None)
|
||||
.flat_map(|chunk| chunk.text.chars())
|
||||
{
|
||||
last_line_chars += 1;
|
||||
@@ -143,7 +147,12 @@ impl TabSnapshot {
|
||||
self.fold_snapshot.version
|
||||
}
|
||||
|
||||
pub fn chunks<'a>(&'a self, range: Range<TabPoint>, language_aware: bool) -> TabChunks<'a> {
|
||||
pub fn chunks<'a>(
|
||||
&'a self,
|
||||
range: Range<TabPoint>,
|
||||
language_aware: bool,
|
||||
text_highlights: Option<&'a TextHighlights>,
|
||||
) -> TabChunks<'a> {
|
||||
let (input_start, expanded_char_column, to_next_stop) =
|
||||
self.to_fold_point(range.start, Bias::Left);
|
||||
let input_start = input_start.to_offset(&self.fold_snapshot);
|
||||
@@ -158,9 +167,11 @@ impl TabSnapshot {
|
||||
};
|
||||
|
||||
TabChunks {
|
||||
fold_chunks: self
|
||||
.fold_snapshot
|
||||
.chunks(input_start..input_end, language_aware),
|
||||
fold_chunks: self.fold_snapshot.chunks(
|
||||
input_start..input_end,
|
||||
language_aware,
|
||||
text_highlights,
|
||||
),
|
||||
column: expanded_char_column,
|
||||
output_position: range.start.0,
|
||||
max_output_position: range.end.0,
|
||||
@@ -179,7 +190,7 @@ impl TabSnapshot {
|
||||
|
||||
#[cfg(test)]
|
||||
pub fn text(&self) -> String {
|
||||
self.chunks(TabPoint::zero()..self.max_point(), false)
|
||||
self.chunks(TabPoint::zero()..self.max_point(), false, None)
|
||||
.map(|chunk| chunk.text)
|
||||
.collect()
|
||||
}
|
||||
@@ -492,7 +503,7 @@ mod tests {
|
||||
assert_eq!(
|
||||
expected_text,
|
||||
tabs_snapshot
|
||||
.chunks(start..end, false)
|
||||
.chunks(start..end, false, None)
|
||||
.map(|c| c.text)
|
||||
.collect::<String>(),
|
||||
"chunks({:?}..{:?})",
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
use super::{
|
||||
fold_map,
|
||||
tab_map::{self, TabEdit, TabPoint, TabSnapshot},
|
||||
TextHighlights,
|
||||
};
|
||||
use crate::{MultiBufferSnapshot, Point};
|
||||
use gpui::{
|
||||
@@ -433,6 +434,7 @@ impl WrapSnapshot {
|
||||
let mut chunks = new_tab_snapshot.chunks(
|
||||
TabPoint::new(edit.new_rows.start, 0)..new_tab_snapshot.max_point(),
|
||||
false,
|
||||
None,
|
||||
);
|
||||
let mut edit_transforms = Vec::<Transform>::new();
|
||||
for _ in edit.new_rows.start..edit.new_rows.end {
|
||||
@@ -558,11 +560,16 @@ impl WrapSnapshot {
|
||||
}
|
||||
|
||||
pub fn text_chunks(&self, wrap_row: u32) -> impl Iterator<Item = &str> {
|
||||
self.chunks(wrap_row..self.max_point().row() + 1, false)
|
||||
self.chunks(wrap_row..self.max_point().row() + 1, false, None)
|
||||
.map(|h| h.text)
|
||||
}
|
||||
|
||||
pub fn chunks<'a>(&'a self, rows: Range<u32>, language_aware: bool) -> WrapChunks<'a> {
|
||||
pub fn chunks<'a>(
|
||||
&'a self,
|
||||
rows: Range<u32>,
|
||||
language_aware: bool,
|
||||
text_highlights: Option<&'a TextHighlights>,
|
||||
) -> WrapChunks<'a> {
|
||||
let output_start = WrapPoint::new(rows.start, 0);
|
||||
let output_end = WrapPoint::new(rows.end, 0);
|
||||
let mut transforms = self.transforms.cursor::<(WrapPoint, TabPoint)>();
|
||||
@@ -575,9 +582,11 @@ impl WrapSnapshot {
|
||||
.to_tab_point(output_end)
|
||||
.min(self.tab_snapshot.max_point());
|
||||
WrapChunks {
|
||||
input_chunks: self
|
||||
.tab_snapshot
|
||||
.chunks(input_start..input_end, language_aware),
|
||||
input_chunks: self.tab_snapshot.chunks(
|
||||
input_start..input_end,
|
||||
language_aware,
|
||||
text_highlights,
|
||||
),
|
||||
input_chunk: Default::default(),
|
||||
output_position: output_start,
|
||||
max_output_row: rows.end,
|
||||
@@ -1280,7 +1289,7 @@ mod tests {
|
||||
}
|
||||
|
||||
let actual_text = self
|
||||
.chunks(start_row..end_row, true)
|
||||
.chunks(start_row..end_row, true, None)
|
||||
.map(|c| c.text)
|
||||
.collect::<String>();
|
||||
assert_eq!(
|
||||
|
||||
@@ -4398,16 +4398,16 @@ impl Editor {
|
||||
None,
|
||||
cx,
|
||||
);
|
||||
editor.highlight_background::<Rename>(
|
||||
vec![Anchor::min()..Anchor::max()],
|
||||
style.diff_background_inserted,
|
||||
cx,
|
||||
);
|
||||
editor
|
||||
});
|
||||
this.highlight_background::<Rename>(
|
||||
this.highlight_text::<Rename>(
|
||||
vec![range.clone()],
|
||||
style.diff_background_deleted,
|
||||
HighlightStyle {
|
||||
color: Color::transparent_black(),
|
||||
font_properties: todo!(),
|
||||
underline: todo!(),
|
||||
fade_out: todo!(),
|
||||
},
|
||||
cx,
|
||||
);
|
||||
this.update_selections(
|
||||
|
||||
@@ -213,25 +213,6 @@ impl MultiBuffer {
|
||||
this
|
||||
}
|
||||
|
||||
#[cfg(any(test, feature = "test-support"))]
|
||||
pub fn build_simple(text: &str, cx: &mut gpui::MutableAppContext) -> ModelHandle<Self> {
|
||||
let buffer = cx.add_model(|cx| Buffer::new(0, text, cx));
|
||||
cx.add_model(|cx| Self::singleton(buffer, cx))
|
||||
}
|
||||
|
||||
#[cfg(any(test, feature = "test-support"))]
|
||||
pub fn build_random(
|
||||
rng: &mut impl rand::Rng,
|
||||
cx: &mut gpui::MutableAppContext,
|
||||
) -> ModelHandle<Self> {
|
||||
cx.add_model(|cx| {
|
||||
let mut multibuffer = MultiBuffer::new(0);
|
||||
let mutation_count = rng.gen_range(1..=5);
|
||||
multibuffer.randomly_edit_excerpts(rng, mutation_count, cx);
|
||||
multibuffer
|
||||
})
|
||||
}
|
||||
|
||||
pub fn replica_id(&self) -> ReplicaId {
|
||||
self.replica_id
|
||||
}
|
||||
@@ -1170,6 +1151,23 @@ impl MultiBuffer {
|
||||
|
||||
#[cfg(any(test, feature = "test-support"))]
|
||||
impl MultiBuffer {
|
||||
pub fn build_simple(text: &str, cx: &mut gpui::MutableAppContext) -> ModelHandle<Self> {
|
||||
let buffer = cx.add_model(|cx| Buffer::new(0, text, cx));
|
||||
cx.add_model(|cx| Self::singleton(buffer, cx))
|
||||
}
|
||||
|
||||
pub fn build_random(
|
||||
rng: &mut impl rand::Rng,
|
||||
cx: &mut gpui::MutableAppContext,
|
||||
) -> ModelHandle<Self> {
|
||||
cx.add_model(|cx| {
|
||||
let mut multibuffer = MultiBuffer::new(0);
|
||||
let mutation_count = rng.gen_range(1..=5);
|
||||
multibuffer.randomly_edit_excerpts(rng, mutation_count, cx);
|
||||
multibuffer
|
||||
})
|
||||
}
|
||||
|
||||
pub fn randomly_edit(
|
||||
&mut self,
|
||||
rng: &mut impl rand::Rng,
|
||||
@@ -2300,6 +2298,15 @@ impl MultiBufferSnapshot {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(test, feature = "test-support"))]
|
||||
impl MultiBufferSnapshot {
|
||||
pub fn random_byte_range(&self, start_offset: usize, rng: &mut impl rand::Rng) -> Range<usize> {
|
||||
let end = self.clip_offset(rng.gen_range(start_offset..=self.len()), Bias::Right);
|
||||
let start = self.clip_offset(rng.gen_range(start_offset..=end), Bias::Right);
|
||||
start..end
|
||||
}
|
||||
}
|
||||
|
||||
impl History {
|
||||
fn start_transaction(&mut self, now: Instant) -> Option<TransactionId> {
|
||||
self.transaction_depth += 1;
|
||||
|
||||
@@ -50,8 +50,9 @@ impl Color {
|
||||
}
|
||||
|
||||
pub fn blend(source: Color, dest: Color) -> Color {
|
||||
if dest.a == 255 {
|
||||
return dest;
|
||||
// If source is fully opaque, don't blend.
|
||||
if source.a == 255 {
|
||||
return source;
|
||||
}
|
||||
|
||||
let source = source.0.to_f32();
|
||||
|
||||
@@ -31,6 +31,10 @@ impl<K: Clone + Debug + Default + Ord, V: Clone + Debug> TreeMap<K, V> {
|
||||
Self(tree)
|
||||
}
|
||||
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.0.is_empty()
|
||||
}
|
||||
|
||||
pub fn get<'a>(&self, key: &'a K) -> Option<&V> {
|
||||
let mut cursor = self.0.cursor::<MapKeyRef<'_, K>>();
|
||||
cursor.seek(&MapKeyRef(Some(key)), Bias::Left, &());
|
||||
|
||||
Reference in New Issue
Block a user