Compare commits
7 Commits
logging
...
cursor-fas
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c48cdcf315 | ||
|
|
e3f13c0aee | ||
|
|
26eabe94b5 | ||
|
|
3f70461585 | ||
|
|
4d56a6294e | ||
|
|
f31880931d | ||
|
|
253229464b |
@@ -94,6 +94,7 @@ uuid.workspace = true
|
|||||||
vim_mode_setting.workspace = true
|
vim_mode_setting.workspace = true
|
||||||
workspace.workspace = true
|
workspace.workspace = true
|
||||||
zed_actions.workspace = true
|
zed_actions.workspace = true
|
||||||
|
zlog.workspace = true
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
criterion.workspace = true
|
criterion.workspace = true
|
||||||
|
|||||||
@@ -5,7 +5,10 @@ use super::{
|
|||||||
};
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
EditorStyle, GutterDimensions,
|
EditorStyle, GutterDimensions,
|
||||||
display_map::{dimensions::RowDelta, wrap_map::WrapRow},
|
display_map::{
|
||||||
|
dimensions::RowDelta,
|
||||||
|
wrap_map::{WrapPointCursor, WrapRow},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
use collections::{Bound, HashMap, HashSet};
|
use collections::{Bound, HashMap, HashSet};
|
||||||
use gpui::{AnyElement, App, EntityId, Pixels, Window};
|
use gpui::{AnyElement, App, EntityId, Pixels, Window};
|
||||||
@@ -525,6 +528,7 @@ impl BlockMap {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn sync(&self, wrap_snapshot: &WrapSnapshot, mut edits: WrapPatch) {
|
fn sync(&self, wrap_snapshot: &WrapSnapshot, mut edits: WrapPatch) {
|
||||||
|
let _timer = zlog::time!("BlockMap::sync").warn_if_gt(std::time::Duration::from_millis(50));
|
||||||
let buffer = wrap_snapshot.buffer_snapshot();
|
let buffer = wrap_snapshot.buffer_snapshot();
|
||||||
|
|
||||||
// Handle changing the last excerpt if it is empty.
|
// Handle changing the last excerpt if it is empty.
|
||||||
@@ -561,6 +565,15 @@ impl BlockMap {
|
|||||||
let mut fold_point_cursor = wrap_snapshot.fold_point_cursor();
|
let mut fold_point_cursor = wrap_snapshot.fold_point_cursor();
|
||||||
let mut wrap_point_cursor = wrap_snapshot.wrap_point_cursor();
|
let mut wrap_point_cursor = wrap_snapshot.wrap_point_cursor();
|
||||||
|
|
||||||
|
let mut inlay_cursor = wrap_snapshot.inlay_cursor();
|
||||||
|
let mut tab_cursor = wrap_snapshot.tab_cursor();
|
||||||
|
let mut fold_cursor = wrap_snapshot.fold_cursor();
|
||||||
|
let mut wrap_cursor = wrap_snapshot.wrap_cursor();
|
||||||
|
let mut multi_buffer_cursor2 = wrap_snapshot
|
||||||
|
.buffer
|
||||||
|
.diff_transforms
|
||||||
|
.cursor::<multi_buffer::CursorType>(());
|
||||||
|
|
||||||
while let Some(edit) = edits.next() {
|
while let Some(edit) = edits.next() {
|
||||||
let mut old_start = edit.old.start;
|
let mut old_start = edit.old.start;
|
||||||
let mut new_start = edit.new.start;
|
let mut new_start = edit.new.start;
|
||||||
@@ -599,10 +612,15 @@ impl BlockMap {
|
|||||||
if transform_rows_before_edit > RowDelta(0) {
|
if transform_rows_before_edit > RowDelta(0) {
|
||||||
if transform.block.is_none() {
|
if transform.block.is_none() {
|
||||||
// Preserve any portion of the old isomorphic transform that precedes this edit.
|
// Preserve any portion of the old isomorphic transform that precedes this edit.
|
||||||
push_isomorphic(
|
push_isomorphic_(
|
||||||
&mut new_transforms,
|
&mut new_transforms,
|
||||||
transform_rows_before_edit,
|
transform_rows_before_edit,
|
||||||
wrap_snapshot,
|
wrap_snapshot,
|
||||||
|
&mut wrap_point_cursor2,
|
||||||
|
&mut multi_buffer_cursor2,
|
||||||
|
&mut inlay_point_cursor2,
|
||||||
|
&mut fold_point_cursor2,
|
||||||
|
&mut tab_point_cursor2,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
// We landed within a block that replaces some lines, so we
|
// We landed within a block that replaces some lines, so we
|
||||||
@@ -758,7 +776,12 @@ impl BlockMap {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
push_isomorphic(&mut new_transforms, rows_before_block, wrap_snapshot);
|
push_isomorphic_(
|
||||||
|
&mut new_transforms,
|
||||||
|
rows_before_block,
|
||||||
|
wrap_snapshot,
|
||||||
|
&mut wrap_cursor,
|
||||||
|
);
|
||||||
new_transforms.push(
|
new_transforms.push(
|
||||||
Transform {
|
Transform {
|
||||||
summary,
|
summary,
|
||||||
@@ -771,7 +794,12 @@ impl BlockMap {
|
|||||||
// Insert an isomorphic transform after the final block.
|
// Insert an isomorphic transform after the final block.
|
||||||
let rows_after_last_block =
|
let rows_after_last_block =
|
||||||
RowDelta(new_end.0).saturating_sub(RowDelta(new_transforms.summary().input_rows.0));
|
RowDelta(new_end.0).saturating_sub(RowDelta(new_transforms.summary().input_rows.0));
|
||||||
push_isomorphic(&mut new_transforms, rows_after_last_block, wrap_snapshot);
|
push_isomorphic_(
|
||||||
|
&mut new_transforms,
|
||||||
|
rows_after_last_block,
|
||||||
|
wrap_snapshot,
|
||||||
|
&mut wrap_cursor,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
new_transforms.append(cursor.suffix(), ());
|
new_transforms.append(cursor.suffix(), ());
|
||||||
@@ -947,13 +975,60 @@ impl BlockMap {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn push_isomorphic(tree: &mut SumTree<Transform>, rows: RowDelta, wrap_snapshot: &WrapSnapshot) {
|
fn push_isomorphic(tree: &mut SumTree<Transform>, rows: RowDelta, wrap_snapshot: &WrapSnapshot) {
|
||||||
|
let mut wrap_cursor = wrap_snapshot
|
||||||
|
.transforms
|
||||||
|
.cursor::<Dimensions<WrapPoint, super::tab_map::TabPoint>>(());
|
||||||
|
let mut mb_cursor = wrap_snapshot
|
||||||
|
.buffer
|
||||||
|
.diff_transforms
|
||||||
|
.cursor::<multi_buffer::CursorType>(());
|
||||||
|
let mut inlay_cursor = wrap_snapshot
|
||||||
|
.inlay_snapshot
|
||||||
|
.transforms
|
||||||
|
.cursor::<Dimensions<super::InlayOffset, MultiBufferOffset>>(());
|
||||||
|
let mut fold_cursor = wrap_snapshot
|
||||||
|
.fold_snapshot
|
||||||
|
.transforms
|
||||||
|
.cursor::<Dimensions<super::FoldPoint, super::InlayPoint>>(());
|
||||||
|
let mut tab_cursor = wrap_snapshot.tab_point_cursor();
|
||||||
|
|
||||||
|
push_isomorphic_(
|
||||||
|
tree,
|
||||||
|
rows,
|
||||||
|
wrap_snapshot,
|
||||||
|
&mut wrap_cursor,
|
||||||
|
&mut mb_cursor,
|
||||||
|
&mut inlay_cursor,
|
||||||
|
&mut fold_cursor,
|
||||||
|
&mut tab_cursor,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is called whenever we push actual text (nonisomorphic is inlay hints and blocks)
|
||||||
|
fn push_isomorphic_(
|
||||||
|
tree: &mut SumTree<Transform>,
|
||||||
|
rows: RowDelta,
|
||||||
|
wrap_snapshot: &WrapSnapshot,
|
||||||
|
wrap_cursor: &mut wrap_map::WrapCursor<'_>,
|
||||||
|
mb_cursor: &mut multi_buffer::MBDiffCursor<'_>,
|
||||||
|
inlay_cursor: &mut super::inlay_map::InlayOffsetCursor<'_>,
|
||||||
|
fold_cursor: &mut super::fold_map::FoldCursor<'_>,
|
||||||
|
tab_cursor: &mut super::tab_map::TabPointCursor<'_>,
|
||||||
|
) {
|
||||||
if rows == RowDelta(0) {
|
if rows == RowDelta(0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let wrap_row_start = tree.summary().input_rows;
|
let wrap_row_start = tree.summary().input_rows;
|
||||||
let wrap_row_end = wrap_row_start + rows;
|
let wrap_row_end = wrap_row_start + rows;
|
||||||
let wrap_summary = wrap_snapshot.text_summary_for_range(wrap_row_start..wrap_row_end);
|
let wrap_summary = wrap_snapshot.text_summary_for_range_(
|
||||||
|
wrap_row_start..wrap_row_end,
|
||||||
|
wrap_cursor,
|
||||||
|
mb_cursor,
|
||||||
|
inlay_cursor,
|
||||||
|
fold_cursor,
|
||||||
|
tab_cursor,
|
||||||
|
);
|
||||||
let summary = TransformSummary {
|
let summary = TransformSummary {
|
||||||
input_rows: WrapRow(rows.0),
|
input_rows: WrapRow(rows.0),
|
||||||
output_rows: BlockRow(rows.0),
|
output_rows: BlockRow(rows.0),
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use crate::display_map::inlay_map::InlayChunk;
|
use crate::display_map::inlay_map::{self, InlayChunk};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
Highlights,
|
Highlights,
|
||||||
@@ -23,6 +23,8 @@ use sum_tree::{Bias, Cursor, Dimensions, FilterCursor, SumTree, Summary, TreeMap
|
|||||||
use ui::IntoElement as _;
|
use ui::IntoElement as _;
|
||||||
use util::post_inc;
|
use util::post_inc;
|
||||||
|
|
||||||
|
pub type FoldCursor<'a> = Cursor<'a, 'static, Transform, Dimensions<FoldPoint, InlayPoint>>;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct FoldPlaceholder {
|
pub struct FoldPlaceholder {
|
||||||
/// Creates an element to represent this fold's placeholder.
|
/// Creates an element to represent this fold's placeholder.
|
||||||
@@ -626,7 +628,7 @@ impl FoldMap {
|
|||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct FoldSnapshot {
|
pub struct FoldSnapshot {
|
||||||
pub inlay_snapshot: InlaySnapshot,
|
pub inlay_snapshot: InlaySnapshot,
|
||||||
transforms: SumTree<Transform>,
|
pub transforms: SumTree<Transform>,
|
||||||
folds: SumTree<Fold>,
|
folds: SumTree<Fold>,
|
||||||
fold_metadata_by_id: TreeMap<FoldId, FoldMetadata>,
|
fold_metadata_by_id: TreeMap<FoldId, FoldMetadata>,
|
||||||
pub version: usize,
|
pub version: usize,
|
||||||
@@ -666,12 +668,34 @@ impl FoldSnapshot {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn text_summary_for_range(&self, range: Range<FoldPoint>) -> MBTextSummary {
|
pub fn text_summary_for_range(&self, range: Range<FoldPoint>) -> MBTextSummary {
|
||||||
let mut summary = MBTextSummary::default();
|
let mut fold_cursor = self
|
||||||
|
|
||||||
let mut cursor = self
|
|
||||||
.transforms
|
.transforms
|
||||||
.cursor::<Dimensions<FoldPoint, InlayPoint>>(());
|
.cursor::<Dimensions<FoldPoint, InlayPoint>>(());
|
||||||
cursor.seek(&range.start, Bias::Right);
|
let mut inlay_cursor = self
|
||||||
|
.inlay_snapshot
|
||||||
|
.transforms
|
||||||
|
.cursor::<Dimensions<InlayOffset, MultiBufferOffset>>(());
|
||||||
|
let mut mbcursor = self
|
||||||
|
.buffer
|
||||||
|
.diff_transforms
|
||||||
|
.cursor::<multi_buffer::CursorType>(());
|
||||||
|
self.text_summary_for_range_(&mut mbcursor, &mut inlay_cursor, &mut fold_cursor, range)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn text_summary_for_range_(
|
||||||
|
&self,
|
||||||
|
mbcursor: &mut multi_buffer::MBDiffCursor<'_>,
|
||||||
|
inlay_cursor: &mut inlay_map::InlayOffsetCursor<'_>,
|
||||||
|
cursor: &mut FoldCursor<'_>,
|
||||||
|
range: Range<FoldPoint>,
|
||||||
|
) -> MBTextSummary {
|
||||||
|
let mut summary = MBTextSummary::default();
|
||||||
|
|
||||||
|
if cursor.did_seek() {
|
||||||
|
cursor.seek_forward(&range.start, Bias::Right);
|
||||||
|
} else {
|
||||||
|
cursor.seek(&range.start, Bias::Right);
|
||||||
|
}
|
||||||
if let Some(transform) = cursor.item() {
|
if let Some(transform) = cursor.item() {
|
||||||
let start_in_transform = range.start.0 - cursor.start().0.0;
|
let start_in_transform = range.start.0 - cursor.start().0.0;
|
||||||
let end_in_transform = cmp::min(range.end, cursor.end().0).0 - cursor.start().0.0;
|
let end_in_transform = cmp::min(range.end, cursor.end().0).0 - cursor.start().0.0;
|
||||||
@@ -687,9 +711,11 @@ impl FoldSnapshot {
|
|||||||
let inlay_end = self
|
let inlay_end = self
|
||||||
.inlay_snapshot
|
.inlay_snapshot
|
||||||
.to_offset(InlayPoint(cursor.start().1.0 + end_in_transform));
|
.to_offset(InlayPoint(cursor.start().1.0 + end_in_transform));
|
||||||
summary = self
|
summary = self.inlay_snapshot.text_summary_for_range_(
|
||||||
.inlay_snapshot
|
mbcursor,
|
||||||
.text_summary_for_range(inlay_start..inlay_end);
|
inlay_cursor,
|
||||||
|
inlay_start..inlay_end,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -935,7 +961,7 @@ impl FoldSnapshot {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct FoldPointCursor<'transforms> {
|
pub struct FoldPointCursor<'transforms> {
|
||||||
cursor: Cursor<'transforms, 'static, Transform, Dimensions<InlayPoint, FoldPoint>>,
|
pub(crate) cursor: Cursor<'transforms, 'static, Transform, Dimensions<InlayPoint, FoldPoint>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FoldPointCursor<'_> {
|
impl FoldPointCursor<'_> {
|
||||||
@@ -1079,7 +1105,7 @@ fn consolidate_fold_edits(mut edits: Vec<FoldEdit>) -> Vec<FoldEdit> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default)]
|
#[derive(Clone, Debug, Default)]
|
||||||
struct Transform {
|
pub struct Transform {
|
||||||
summary: TransformSummary,
|
summary: TransformSummary,
|
||||||
placeholder: Option<TransformPlaceholder>,
|
placeholder: Option<TransformPlaceholder>,
|
||||||
}
|
}
|
||||||
@@ -1098,7 +1124,7 @@ impl Transform {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default, Eq, PartialEq)]
|
#[derive(Clone, Debug, Default, Eq, PartialEq)]
|
||||||
struct TransformSummary {
|
pub struct TransformSummary {
|
||||||
output: MBTextSummary,
|
output: MBTextSummary,
|
||||||
input: MBTextSummary,
|
input: MBTextSummary,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ pub struct InlayMap {
|
|||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct InlaySnapshot {
|
pub struct InlaySnapshot {
|
||||||
pub buffer: MultiBufferSnapshot,
|
pub buffer: MultiBufferSnapshot,
|
||||||
transforms: SumTree<Transform>,
|
pub transforms: SumTree<Transform>,
|
||||||
pub version: usize,
|
pub version: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -43,8 +43,11 @@ impl std::ops::Deref for InlaySnapshot {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub type InlayOffsetCursor<'a> =
|
||||||
|
Cursor<'a, 'static, Transform, Dimensions<InlayOffset, MultiBufferOffset>>;
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
enum Transform {
|
pub enum Transform {
|
||||||
Isomorphic(MBTextSummary),
|
Isomorphic(MBTextSummary),
|
||||||
Inlay(Inlay),
|
Inlay(Inlay),
|
||||||
}
|
}
|
||||||
@@ -67,7 +70,7 @@ impl sum_tree::Item for Transform {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default)]
|
#[derive(Clone, Debug, Default)]
|
||||||
struct TransformSummary {
|
pub struct TransformSummary {
|
||||||
input: MBTextSummary,
|
input: MBTextSummary,
|
||||||
output: MBTextSummary,
|
output: MBTextSummary,
|
||||||
}
|
}
|
||||||
@@ -207,7 +210,7 @@ pub struct InlayBufferRows<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct InlayChunks<'a> {
|
pub struct InlayChunks<'a> {
|
||||||
transforms: Cursor<'a, 'static, Transform, Dimensions<InlayOffset, MultiBufferOffset>>,
|
transforms: InlayOffsetCursor<'a>,
|
||||||
buffer_chunks: CustomHighlightsChunks<'a>,
|
buffer_chunks: CustomHighlightsChunks<'a>,
|
||||||
buffer_chunk: Option<Chunk<'a>>,
|
buffer_chunk: Option<Chunk<'a>>,
|
||||||
inlay_chunks: Option<text::ChunkWithBitmaps<'a>>,
|
inlay_chunks: Option<text::ChunkWithBitmaps<'a>>,
|
||||||
@@ -988,13 +991,28 @@ impl InlaySnapshot {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn text_summary_for_range(&self, range: Range<InlayOffset>) -> MBTextSummary {
|
pub fn text_summary_for_range(&self, range: Range<InlayOffset>) -> MBTextSummary {
|
||||||
let mut summary = MBTextSummary::default();
|
|
||||||
|
|
||||||
let mut cursor = self
|
let mut cursor = self
|
||||||
.transforms
|
.transforms
|
||||||
.cursor::<Dimensions<InlayOffset, MultiBufferOffset>>(());
|
.cursor::<Dimensions<InlayOffset, MultiBufferOffset>>(());
|
||||||
cursor.seek(&range.start, Bias::Right);
|
let mut mbcursor = self
|
||||||
|
.buffer
|
||||||
|
.diff_transforms
|
||||||
|
.cursor::<multi_buffer::CursorType>(());
|
||||||
|
self.text_summary_for_range_(&mut mbcursor, &mut cursor, range)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn text_summary_for_range_(
|
||||||
|
&self,
|
||||||
|
mbcursor: &mut multi_buffer::MBDiffCursor<'_>,
|
||||||
|
cursor: &mut InlayOffsetCursor,
|
||||||
|
range: Range<InlayOffset>,
|
||||||
|
) -> MBTextSummary {
|
||||||
|
if cursor.did_seek() {
|
||||||
|
cursor.seek_forward(&range.start, Bias::Right);
|
||||||
|
} else {
|
||||||
|
cursor.seek(&range.start, Bias::Right);
|
||||||
|
}
|
||||||
|
let mut summary = MBTextSummary::default();
|
||||||
let overshoot = range.start.0 - cursor.start().0.0;
|
let overshoot = range.start.0 - cursor.start().0.0;
|
||||||
match cursor.item() {
|
match cursor.item() {
|
||||||
Some(Transform::Isomorphic(_)) => {
|
Some(Transform::Isomorphic(_)) => {
|
||||||
@@ -1002,7 +1020,9 @@ impl InlaySnapshot {
|
|||||||
let suffix_start = buffer_start + overshoot;
|
let suffix_start = buffer_start + overshoot;
|
||||||
let suffix_end =
|
let suffix_end =
|
||||||
buffer_start + (cmp::min(cursor.end().0, range.end).0 - cursor.start().0.0);
|
buffer_start + (cmp::min(cursor.end().0, range.end).0 - cursor.start().0.0);
|
||||||
summary = self.buffer.text_summary_for_range(suffix_start..suffix_end);
|
summary = self
|
||||||
|
.buffer
|
||||||
|
.text_summary_for_range_(mbcursor, suffix_start..suffix_end);
|
||||||
cursor.next();
|
cursor.next();
|
||||||
}
|
}
|
||||||
Some(Transform::Inlay(inlay)) => {
|
Some(Transform::Inlay(inlay)) => {
|
||||||
@@ -1029,9 +1049,10 @@ impl InlaySnapshot {
|
|||||||
Some(Transform::Isomorphic(_)) => {
|
Some(Transform::Isomorphic(_)) => {
|
||||||
let prefix_start = cursor.start().1;
|
let prefix_start = cursor.start().1;
|
||||||
let prefix_end = prefix_start + overshoot;
|
let prefix_end = prefix_start + overshoot;
|
||||||
summary += self
|
summary += self.buffer.text_summary_for_range_::<MBTextSummary, _>(
|
||||||
.buffer
|
mbcursor,
|
||||||
.text_summary_for_range::<MBTextSummary, _>(prefix_start..prefix_end);
|
prefix_start..prefix_end,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
Some(Transform::Inlay(inlay)) => {
|
Some(Transform::Inlay(inlay)) => {
|
||||||
let prefix_end = overshoot;
|
let prefix_end = overshoot;
|
||||||
@@ -1142,7 +1163,7 @@ impl InlaySnapshot {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct InlayPointCursor<'transforms> {
|
pub struct InlayPointCursor<'transforms> {
|
||||||
cursor: Cursor<'transforms, 'static, Transform, Dimensions<Point, InlayPoint>>,
|
pub(crate) cursor: Cursor<'transforms, 'static, Transform, Dimensions<Point, InlayPoint>>,
|
||||||
transforms: &'transforms SumTree<Transform>,
|
transforms: &'transforms SumTree<Transform>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,14 @@
|
|||||||
|
use crate::display_map::{InlayOffset, InlayPoint, inlay_map};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
Highlights,
|
Highlights,
|
||||||
fold_map::{self, Chunk, FoldChunks, FoldEdit, FoldPoint, FoldSnapshot},
|
fold_map::{self, Chunk, FoldChunks, FoldEdit, FoldPoint, FoldSnapshot},
|
||||||
};
|
};
|
||||||
|
|
||||||
use language::Point;
|
use language::Point;
|
||||||
use multi_buffer::MultiBufferSnapshot;
|
use multi_buffer::{MBDiffCursor, MultiBufferOffset, MultiBufferSnapshot};
|
||||||
use std::{cmp, mem, num::NonZeroU32, ops::Range};
|
use std::{cmp, mem, num::NonZeroU32, ops::Range};
|
||||||
use sum_tree::Bias;
|
use sum_tree::{Bias, Dimensions};
|
||||||
|
|
||||||
const MAX_EXPANSION_COLUMN: u32 = 256;
|
const MAX_EXPANSION_COLUMN: u32 = 256;
|
||||||
|
|
||||||
@@ -196,8 +198,41 @@ impl TabSnapshot {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn text_summary_for_range(&self, range: Range<TabPoint>) -> TextSummary {
|
pub fn text_summary_for_range(&self, range: Range<TabPoint>) -> TextSummary {
|
||||||
|
let mut mbcursor = self
|
||||||
|
.buffer
|
||||||
|
.diff_transforms
|
||||||
|
.cursor::<multi_buffer::CursorType>(());
|
||||||
|
let mut inlay_cursor = self
|
||||||
|
.inlay_snapshot
|
||||||
|
.transforms
|
||||||
|
.cursor::<Dimensions<InlayOffset, MultiBufferOffset>>(());
|
||||||
|
let mut fold_cursor = self
|
||||||
|
.fold_snapshot
|
||||||
|
.transforms
|
||||||
|
.cursor::<Dimensions<FoldPoint, InlayPoint>>(());
|
||||||
|
let mut cursor = self.tab_point_cursor();
|
||||||
|
self.text_summary_for_range_(
|
||||||
|
&mut mbcursor,
|
||||||
|
&mut inlay_cursor,
|
||||||
|
&mut fold_cursor,
|
||||||
|
&mut cursor,
|
||||||
|
range,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn text_summary_for_range_(
|
||||||
|
&self,
|
||||||
|
mbcursor: &mut multi_buffer::MBDiffCursor<'_>,
|
||||||
|
inlay_cursor: &mut inlay_map::InlayOffsetCursor<'_>,
|
||||||
|
fold_cursor: &mut fold_map::FoldCursor<'_>,
|
||||||
|
cursor: &mut TabPointCursor<'_>,
|
||||||
|
range: Range<TabPoint>,
|
||||||
|
) -> TextSummary {
|
||||||
|
// TODO we can use cursor here
|
||||||
let input_start = self.tab_point_to_fold_point(range.start, Bias::Left).0;
|
let input_start = self.tab_point_to_fold_point(range.start, Bias::Left).0;
|
||||||
|
// TODO we can use cursor here
|
||||||
let input_end = self.tab_point_to_fold_point(range.end, Bias::Right).0;
|
let input_end = self.tab_point_to_fold_point(range.end, Bias::Right).0;
|
||||||
|
// TODO we can use cursor here
|
||||||
let input_summary = self
|
let input_summary = self
|
||||||
.fold_snapshot
|
.fold_snapshot
|
||||||
.text_summary_for_range(input_start..input_end);
|
.text_summary_for_range(input_start..input_end);
|
||||||
@@ -313,12 +348,12 @@ impl TabSnapshot {
|
|||||||
TabPointCursor { this: self }
|
TabPointCursor { this: self }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn tab_point_to_fold_point(&self, output: TabPoint, bias: Bias) -> (FoldPoint, u32, u32) {
|
pub fn tab_point_to_fold_point_<'a, I: Iterator<Item = Chunk<'a>>>(
|
||||||
let chunks = self
|
&self,
|
||||||
.fold_snapshot
|
tab_cursor: &mut TabStopCursor<'a, I>,
|
||||||
.chunks_at(FoldPoint::new(output.row(), 0));
|
output: TabPoint,
|
||||||
|
bias: Bias,
|
||||||
let tab_cursor = TabStopCursor::new(chunks);
|
) -> (FoldPoint, u32, u32) {
|
||||||
let expanded = output.column();
|
let expanded = output.column();
|
||||||
let (collapsed, expanded_char_column, to_next_stop) =
|
let (collapsed, expanded_char_column, to_next_stop) =
|
||||||
self.collapse_tabs(tab_cursor, expanded, bias);
|
self.collapse_tabs(tab_cursor, expanded, bias);
|
||||||
@@ -330,6 +365,14 @@ impl TabSnapshot {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn tab_point_to_fold_point(&self, output: TabPoint, bias: Bias) -> (FoldPoint, u32, u32) {
|
||||||
|
let chunks = self
|
||||||
|
.fold_snapshot
|
||||||
|
.chunks_at(FoldPoint::new(output.row(), 0));
|
||||||
|
let mut tab_cursor = TabStopCursor::new(chunks);
|
||||||
|
self.tab_point_to_fold_point_(&mut tab_cursor, output, bias)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn point_to_tab_point(&self, point: Point, bias: Bias) -> TabPoint {
|
pub fn point_to_tab_point(&self, point: Point, bias: Bias) -> TabPoint {
|
||||||
let inlay_point = self.fold_snapshot.inlay_snapshot.to_inlay_point(point);
|
let inlay_point = self.fold_snapshot.inlay_snapshot.to_inlay_point(point);
|
||||||
let fold_point = self.fold_snapshot.to_fold_point(inlay_point, bias);
|
let fold_point = self.fold_snapshot.to_fold_point(inlay_point, bias);
|
||||||
@@ -379,7 +422,7 @@ impl TabSnapshot {
|
|||||||
|
|
||||||
fn collapse_tabs<'a, I>(
|
fn collapse_tabs<'a, I>(
|
||||||
&self,
|
&self,
|
||||||
mut cursor: TabStopCursor<'a, I>,
|
cursor: &mut TabStopCursor<'a, I>,
|
||||||
column: u32,
|
column: u32,
|
||||||
bias: Bias,
|
bias: Bias,
|
||||||
) -> (u32, u32, u32)
|
) -> (u32, u32, u32)
|
||||||
@@ -1436,7 +1479,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct TabStopCursor<'a, I>
|
pub struct TabStopCursor<'a, I>
|
||||||
where
|
where
|
||||||
I: Iterator<Item = Chunk<'a>>,
|
I: Iterator<Item = Chunk<'a>>,
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
|
use crate::display_map::{
|
||||||
|
fold_map::FoldCursor, inlay_map::InlayOffsetCursor, tab_map::TabPointCursor,
|
||||||
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
Highlights,
|
Highlights,
|
||||||
dimensions::RowDelta,
|
dimensions::RowDelta,
|
||||||
@@ -6,7 +10,7 @@ use super::{
|
|||||||
};
|
};
|
||||||
use gpui::{App, AppContext as _, Context, Entity, Font, LineWrapper, Pixels, Task};
|
use gpui::{App, AppContext as _, Context, Entity, Font, LineWrapper, Pixels, Task};
|
||||||
use language::Point;
|
use language::Point;
|
||||||
use multi_buffer::{MultiBufferSnapshot, RowInfo};
|
use multi_buffer::{MBDiffCursor, MultiBufferSnapshot, RowInfo};
|
||||||
use smol::future::yield_now;
|
use smol::future::yield_now;
|
||||||
use std::{cmp, collections::VecDeque, mem, ops::Range, sync::LazyLock, time::Duration};
|
use std::{cmp, collections::VecDeque, mem, ops::Range, sync::LazyLock, time::Duration};
|
||||||
use sum_tree::{Bias, Cursor, Dimensions, SumTree};
|
use sum_tree::{Bias, Cursor, Dimensions, SumTree};
|
||||||
@@ -36,10 +40,12 @@ pub struct WrapMap {
|
|||||||
font_with_size: (Font, Pixels),
|
font_with_size: (Font, Pixels),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub type WrapCursor<'a> = Cursor<'a, 'static, Transform, Dimensions<WrapPoint, TabPoint>>;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct WrapSnapshot {
|
pub struct WrapSnapshot {
|
||||||
pub(super) tab_snapshot: TabSnapshot,
|
pub(super) tab_snapshot: TabSnapshot,
|
||||||
transforms: SumTree<Transform>,
|
pub transforms: SumTree<Transform>,
|
||||||
interpolated: bool,
|
interpolated: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -52,13 +58,13 @@ impl std::ops::Deref for WrapSnapshot {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default, Eq, PartialEq)]
|
#[derive(Clone, Debug, Default, Eq, PartialEq)]
|
||||||
struct Transform {
|
pub struct Transform {
|
||||||
summary: TransformSummary,
|
summary: TransformSummary,
|
||||||
display_text: Option<&'static str>,
|
display_text: Option<&'static str>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default, Eq, PartialEq)]
|
#[derive(Clone, Debug, Default, Eq, PartialEq)]
|
||||||
struct TransformSummary {
|
pub struct TransformSummary {
|
||||||
input: TextSummary,
|
input: TextSummary,
|
||||||
output: TextSummary,
|
output: TextSummary,
|
||||||
}
|
}
|
||||||
@@ -665,22 +671,59 @@ impl WrapSnapshot {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn text_summary_for_range(&self, rows: Range<WrapRow>) -> TextSummary {
|
pub fn text_summary_for_range(&self, rows: Range<WrapRow>) -> TextSummary {
|
||||||
|
let mut wrap_cursor = self.wrap_cursor();
|
||||||
|
let mut mb_cursor = self
|
||||||
|
.buffer
|
||||||
|
.diff_transforms
|
||||||
|
.cursor::<multi_buffer::CursorType>(());
|
||||||
|
let mut inlay_cursor = self
|
||||||
|
.inlay_snapshot
|
||||||
|
.transforms
|
||||||
|
.cursor::<Dimensions<super::InlayOffset, multi_buffer::MultiBufferOffset>>(());
|
||||||
|
let mut fold_cursor = self
|
||||||
|
.fold_snapshot
|
||||||
|
.transforms
|
||||||
|
.cursor::<Dimensions<super::FoldPoint, super::InlayPoint>>(());
|
||||||
|
let mut tab_cursor = self.tab_point_cursor();
|
||||||
|
self.text_summary_for_range_(
|
||||||
|
rows,
|
||||||
|
&mut wrap_cursor,
|
||||||
|
&mut mb_cursor,
|
||||||
|
&mut inlay_cursor,
|
||||||
|
&mut fold_cursor,
|
||||||
|
&mut tab_cursor,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn text_summary_for_range_(
|
||||||
|
&self,
|
||||||
|
rows: Range<WrapRow>,
|
||||||
|
wrap_cursor: &mut WrapCursor<'_>,
|
||||||
|
mb_cursor: &mut MBDiffCursor<'_>,
|
||||||
|
inlay_cursor: &mut super::inlay_map::InlayOffsetCursor<'_>,
|
||||||
|
fold_cursor: &mut super::fold_map::FoldCursor<'_>,
|
||||||
|
tab_cursor: &mut tab_map::TabPointCursor<'_>,
|
||||||
|
) -> TextSummary {
|
||||||
let mut summary = TextSummary::default();
|
let mut summary = TextSummary::default();
|
||||||
|
|
||||||
let start = WrapPoint::new(rows.start, 0);
|
let start = WrapPoint::new(rows.start, 0);
|
||||||
let end = WrapPoint::new(rows.end, 0);
|
let end = WrapPoint::new(rows.end, 0);
|
||||||
|
|
||||||
let mut cursor = self
|
// Retain this wrap cursor
|
||||||
.transforms
|
wrap_cursor.seek(&start, Bias::Right);
|
||||||
.cursor::<Dimensions<WrapPoint, TabPoint>>(());
|
if let Some(transform) = wrap_cursor.item() {
|
||||||
cursor.seek(&start, Bias::Right);
|
let start_in_transform = start.0 - wrap_cursor.start().0.0;
|
||||||
if let Some(transform) = cursor.item() {
|
let end_in_transform = cmp::min(end, wrap_cursor.end().0).0 - wrap_cursor.start().0.0;
|
||||||
let start_in_transform = start.0 - cursor.start().0.0;
|
|
||||||
let end_in_transform = cmp::min(end, cursor.end().0).0 - cursor.start().0.0;
|
|
||||||
if transform.is_isomorphic() {
|
if transform.is_isomorphic() {
|
||||||
let tab_start = TabPoint(cursor.start().1.0 + start_in_transform);
|
let tab_start = TabPoint(wrap_cursor.start().1.0 + start_in_transform);
|
||||||
let tab_end = TabPoint(cursor.start().1.0 + end_in_transform);
|
let tab_end = TabPoint(wrap_cursor.start().1.0 + end_in_transform);
|
||||||
summary += &self.tab_snapshot.text_summary_for_range(tab_start..tab_end);
|
summary += &self.tab_snapshot.text_summary_for_range_(
|
||||||
|
mb_cursor,
|
||||||
|
inlay_cursor,
|
||||||
|
fold_cursor,
|
||||||
|
tab_cursor,
|
||||||
|
tab_start..tab_end,
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
debug_assert_eq!(start_in_transform.row, end_in_transform.row);
|
debug_assert_eq!(start_in_transform.row, end_in_transform.row);
|
||||||
let indent_len = end_in_transform.column - start_in_transform.column;
|
let indent_len = end_in_transform.column - start_in_transform.column;
|
||||||
@@ -693,18 +736,18 @@ impl WrapSnapshot {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
cursor.next();
|
wrap_cursor.next();
|
||||||
}
|
}
|
||||||
|
|
||||||
if rows.end > cursor.start().0.row() {
|
if rows.end > wrap_cursor.start().0.row() {
|
||||||
summary += &cursor
|
summary += &wrap_cursor
|
||||||
.summary::<_, TransformSummary>(&WrapPoint::new(rows.end, 0), Bias::Right)
|
.summary::<_, TransformSummary>(&WrapPoint::new(rows.end, 0), Bias::Right)
|
||||||
.output;
|
.output;
|
||||||
|
|
||||||
if let Some(transform) = cursor.item() {
|
if let Some(transform) = wrap_cursor.item() {
|
||||||
let end_in_transform = end.0 - cursor.start().0.0;
|
let end_in_transform = end.0 - wrap_cursor.start().0.0;
|
||||||
if transform.is_isomorphic() {
|
if transform.is_isomorphic() {
|
||||||
let char_start = cursor.start().1;
|
let char_start = wrap_cursor.start().1;
|
||||||
let char_end = TabPoint(char_start.0 + end_in_transform);
|
let char_end = TabPoint(char_start.0 + end_in_transform);
|
||||||
summary += &self
|
summary += &self
|
||||||
.tab_snapshot
|
.tab_snapshot
|
||||||
@@ -801,6 +844,11 @@ impl WrapSnapshot {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn wrap_cursor(&self) -> WrapCursor<'_> {
|
||||||
|
self.transforms
|
||||||
|
.cursor::<Dimensions<WrapPoint, TabPoint>>(())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn clip_point(&self, mut point: WrapPoint, bias: Bias) -> WrapPoint {
|
pub fn clip_point(&self, mut point: WrapPoint, bias: Bias) -> WrapPoint {
|
||||||
if bias == Bias::Left {
|
if bias == Bias::Left {
|
||||||
let (start, _, item) = self
|
let (start, _, item) = self
|
||||||
@@ -920,10 +968,30 @@ impl WrapSnapshot {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn fold_cursor(&self) -> FoldCursor {
|
||||||
|
self.fold_snapshot
|
||||||
|
.transforms
|
||||||
|
.cursor::<Dimensions<super::FoldPoint, super::InlayPoint>>(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn tab_cursor(&self) -> TabPointCursor {
|
||||||
|
self.tab_point_cursor()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// TODO redo all cursor names, make them make sense
|
||||||
|
///
|
||||||
|
/// maybe CursorInlayToOffset (pattern: Cursor<From>To<To>)
|
||||||
|
/// that makes searching easier
|
||||||
|
pub(crate) fn inlay_cursor(&self) -> InlayOffsetCursor {
|
||||||
|
self.inlay_snapshot
|
||||||
|
.transforms
|
||||||
|
.cursor::<Dimensions<super::InlayOffset, multi_buffer::MultiBufferOffset>>(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct WrapPointCursor<'transforms> {
|
pub struct WrapPointCursor<'transforms> {
|
||||||
cursor: Cursor<'transforms, 'static, Transform, Dimensions<TabPoint, WrapPoint>>,
|
pub(crate) cursor: Cursor<'transforms, 'static, Transform, Dimensions<TabPoint, WrapPoint>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WrapPointCursor<'_> {
|
impl WrapPointCursor<'_> {
|
||||||
|
|||||||
@@ -822,12 +822,25 @@ impl WindowsPlatformInner {
|
|||||||
// we spent our budget on gpui tasks, we likely have a lot of work queued so drain system events first
|
// we spent our budget on gpui tasks, we likely have a lot of work queued so drain system events first
|
||||||
// before returning to main thread task work
|
// before returning to main thread task work
|
||||||
let mut msg = MSG::default();
|
let mut msg = MSG::default();
|
||||||
let peek_msg_type = PM_REMOVE | PM_QS_INPUT | PM_QS_PAINT;
|
let process_message = |msg: &_| {
|
||||||
while unsafe { PeekMessageW(&mut msg, None, 0, 0, peek_msg_type) }.as_bool() {
|
if translate_accelerator(msg).is_none() {
|
||||||
if translate_accelerator(&msg).is_none() {
|
_ = unsafe { TranslateMessage(msg) };
|
||||||
_ = unsafe { TranslateMessage(&msg) };
|
unsafe { DispatchMessageW(msg) };
|
||||||
unsafe { DispatchMessageW(&msg) };
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
let peek_msg = |msg: &mut _, msg_kind| unsafe {
|
||||||
|
PeekMessageW(msg, None, 0, 0, PM_REMOVE | msg_kind).as_bool()
|
||||||
|
};
|
||||||
|
// We process a paint at the start and end only to prevent getting stuck in a paint loop
|
||||||
|
// due to on going gpui animations
|
||||||
|
if peek_msg(&mut msg, PM_QS_PAINT) {
|
||||||
|
process_message(&msg);
|
||||||
|
}
|
||||||
|
while peek_msg(&mut msg, PM_QS_INPUT) {
|
||||||
|
process_message(&msg);
|
||||||
|
}
|
||||||
|
if peek_msg(&mut msg, PM_QS_PAINT) {
|
||||||
|
process_message(&msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
match self.main_receiver.try_recv() {
|
match self.main_receiver.try_recv() {
|
||||||
|
|||||||
@@ -1210,7 +1210,7 @@ impl Buffer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Reparse the branch buffer so that we get syntax highlighting immediately.
|
// Reparse the branch buffer so that we get syntax highlighting immediately.
|
||||||
branch.reparse(cx);
|
branch.reparse(cx, true);
|
||||||
|
|
||||||
branch
|
branch
|
||||||
})
|
})
|
||||||
@@ -1367,7 +1367,7 @@ impl Buffer {
|
|||||||
self.syntax_map.lock().clear(&self.text);
|
self.syntax_map.lock().clear(&self.text);
|
||||||
self.language = language;
|
self.language = language;
|
||||||
self.was_changed();
|
self.was_changed();
|
||||||
self.reparse(cx);
|
self.reparse(cx, false);
|
||||||
cx.emit(BufferEvent::LanguageChanged);
|
cx.emit(BufferEvent::LanguageChanged);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1623,7 +1623,7 @@ impl Buffer {
|
|||||||
/// initiate an additional reparse recursively. To avoid concurrent parses
|
/// initiate an additional reparse recursively. To avoid concurrent parses
|
||||||
/// for the same buffer, we only initiate a new parse if we are not already
|
/// for the same buffer, we only initiate a new parse if we are not already
|
||||||
/// parsing in the background.
|
/// parsing in the background.
|
||||||
pub fn reparse(&mut self, cx: &mut Context<Self>) {
|
pub fn reparse(&mut self, cx: &mut Context<Self>, may_block: bool) {
|
||||||
if self.reparse.is_some() {
|
if self.reparse.is_some() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1652,43 +1652,31 @@ impl Buffer {
|
|||||||
});
|
});
|
||||||
|
|
||||||
self.parse_status.0.send(ParseStatus::Parsing).unwrap();
|
self.parse_status.0.send(ParseStatus::Parsing).unwrap();
|
||||||
match cx
|
self.reparse = Some(cx.spawn(async move |this, cx| {
|
||||||
.background_executor()
|
let new_syntax_map = cx.background_spawn(parse_task).await;
|
||||||
.block_with_timeout(self.sync_parse_timeout, parse_task)
|
this.update(cx, move |this, cx| {
|
||||||
{
|
let grammar_changed = || {
|
||||||
Ok(new_syntax_snapshot) => {
|
this.language
|
||||||
self.did_finish_parsing(new_syntax_snapshot, cx);
|
.as_ref()
|
||||||
self.reparse = None;
|
.is_none_or(|current_language| !Arc::ptr_eq(&language, current_language))
|
||||||
}
|
};
|
||||||
Err(parse_task) => {
|
let language_registry_changed = || {
|
||||||
// todo(lw): hot foreground spawn
|
new_syntax_map.contains_unknown_injections()
|
||||||
self.reparse = Some(cx.spawn(async move |this, cx| {
|
&& language_registry.is_some_and(|registry| {
|
||||||
let new_syntax_map = cx.background_spawn(parse_task).await;
|
registry.version() != new_syntax_map.language_registry_version()
|
||||||
this.update(cx, move |this, cx| {
|
})
|
||||||
let grammar_changed = || {
|
};
|
||||||
this.language.as_ref().is_none_or(|current_language| {
|
let parse_again = this.version.changed_since(&parsed_version)
|
||||||
!Arc::ptr_eq(&language, current_language)
|
|| language_registry_changed()
|
||||||
})
|
|| grammar_changed();
|
||||||
};
|
this.did_finish_parsing(new_syntax_map, cx);
|
||||||
let language_registry_changed = || {
|
this.reparse = None;
|
||||||
new_syntax_map.contains_unknown_injections()
|
if parse_again {
|
||||||
&& language_registry.is_some_and(|registry| {
|
this.reparse(cx, may_block);
|
||||||
registry.version() != new_syntax_map.language_registry_version()
|
}
|
||||||
})
|
})
|
||||||
};
|
.ok();
|
||||||
let parse_again = this.version.changed_since(&parsed_version)
|
}));
|
||||||
|| language_registry_changed()
|
|
||||||
|| grammar_changed();
|
|
||||||
this.did_finish_parsing(new_syntax_map, cx);
|
|
||||||
this.reparse = None;
|
|
||||||
if parse_again {
|
|
||||||
this.reparse(cx);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.ok();
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn did_finish_parsing(&mut self, syntax_snapshot: SyntaxSnapshot, cx: &mut Context<Self>) {
|
fn did_finish_parsing(&mut self, syntax_snapshot: SyntaxSnapshot, cx: &mut Context<Self>) {
|
||||||
@@ -2588,7 +2576,7 @@ impl Buffer {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.reparse(cx);
|
self.reparse(cx, true);
|
||||||
cx.emit(BufferEvent::Edited);
|
cx.emit(BufferEvent::Edited);
|
||||||
if was_dirty != self.is_dirty() {
|
if was_dirty != self.is_dirty() {
|
||||||
cx.emit(BufferEvent::DirtyChanged);
|
cx.emit(BufferEvent::DirtyChanged);
|
||||||
|
|||||||
@@ -66,6 +66,14 @@ pub struct ExcerptId(u32);
|
|||||||
#[derive(Debug, Default, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
|
#[derive(Debug, Default, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
pub struct BaseTextRow(pub u32);
|
pub struct BaseTextRow(pub u32);
|
||||||
|
|
||||||
|
pub type MBDiffCursor<'a> = Cursor<
|
||||||
|
'a,
|
||||||
|
'static,
|
||||||
|
DiffTransform,
|
||||||
|
Dimensions<MultiBufferOffset, ExcerptDimension<MultiBufferOffset>>,
|
||||||
|
>;
|
||||||
|
pub type CursorType = Dimensions<MultiBufferOffset, ExcerptDimension<MultiBufferOffset>>;
|
||||||
|
|
||||||
/// One or more [`Buffers`](Buffer) being edited in a single view.
|
/// One or more [`Buffers`](Buffer) being edited in a single view.
|
||||||
///
|
///
|
||||||
/// See <https://zed.dev/features#multi-buffers>
|
/// See <https://zed.dev/features#multi-buffers>
|
||||||
@@ -545,7 +553,7 @@ impl DiffState {
|
|||||||
pub struct MultiBufferSnapshot {
|
pub struct MultiBufferSnapshot {
|
||||||
excerpts: SumTree<Excerpt>,
|
excerpts: SumTree<Excerpt>,
|
||||||
diffs: TreeMap<BufferId, BufferDiffSnapshot>,
|
diffs: TreeMap<BufferId, BufferDiffSnapshot>,
|
||||||
diff_transforms: SumTree<DiffTransform>,
|
pub diff_transforms: SumTree<DiffTransform>,
|
||||||
non_text_state_update_count: usize,
|
non_text_state_update_count: usize,
|
||||||
edit_count: usize,
|
edit_count: usize,
|
||||||
is_dirty: bool,
|
is_dirty: bool,
|
||||||
@@ -561,7 +569,7 @@ pub struct MultiBufferSnapshot {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
enum DiffTransform {
|
pub enum DiffTransform {
|
||||||
Unmodified {
|
Unmodified {
|
||||||
summary: MBTextSummary,
|
summary: MBTextSummary,
|
||||||
},
|
},
|
||||||
@@ -4762,11 +4770,23 @@ impl MultiBufferSnapshot {
|
|||||||
MBD: MultiBufferDimension + AddAssign,
|
MBD: MultiBufferDimension + AddAssign,
|
||||||
O: ToOffset,
|
O: ToOffset,
|
||||||
{
|
{
|
||||||
let range = range.start.to_offset(self)..range.end.to_offset(self);
|
|
||||||
let mut cursor = self
|
let mut cursor = self
|
||||||
.diff_transforms
|
.diff_transforms
|
||||||
.cursor::<Dimensions<MultiBufferOffset, ExcerptOffset>>(());
|
.cursor::<Dimensions<MultiBufferOffset, ExcerptOffset>>(());
|
||||||
cursor.seek(&range.start, Bias::Right);
|
self.text_summary_for_range_(&mut cursor, range)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn text_summary_for_range_<MBD, O>(&self, cursor: &mut MBDiffCursor, range: Range<O>) -> MBD
|
||||||
|
where
|
||||||
|
MBD: MultiBufferDimension + AddAssign,
|
||||||
|
O: ToOffset,
|
||||||
|
{
|
||||||
|
let range = range.start.to_offset(self)..range.end.to_offset(self);
|
||||||
|
if cursor.did_seek() {
|
||||||
|
cursor.seek_forward(&range.start, Bias::Right);
|
||||||
|
} else {
|
||||||
|
cursor.seek(&range.start, Bias::Right);
|
||||||
|
}
|
||||||
|
|
||||||
let Some(first_transform) = cursor.item() else {
|
let Some(first_transform) = cursor.item() else {
|
||||||
return MBD::from_summary(&MBTextSummary::default());
|
return MBD::from_summary(&MBTextSummary::default());
|
||||||
@@ -7399,7 +7419,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialOrd, Ord, Eq, PartialEq, Debug)]
|
#[derive(Copy, Clone, PartialOrd, Ord, Eq, PartialEq, Debug)]
|
||||||
struct ExcerptDimension<T>(T);
|
pub struct ExcerptDimension<T>(T);
|
||||||
|
|
||||||
impl<T: PartialEq> PartialEq<T> for ExcerptDimension<T> {
|
impl<T: PartialEq> PartialEq<T> for ExcerptDimension<T> {
|
||||||
fn eq(&self, other: &T) -> bool {
|
fn eq(&self, other: &T) -> bool {
|
||||||
|
|||||||
@@ -4353,7 +4353,7 @@ impl LspStore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for buffer in buffers_with_unknown_injections {
|
for buffer in buffers_with_unknown_injections {
|
||||||
buffer.update(cx, |buffer, cx| buffer.reparse(cx));
|
buffer.update(cx, |buffer, cx| buffer.reparse(cx, false));
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.ok();
|
.ok();
|
||||||
|
|||||||
@@ -377,6 +377,7 @@ impl ProjectSearch {
|
|||||||
})
|
})
|
||||||
.ok()?;
|
.ok()?;
|
||||||
while let Some(new_ranges) = new_ranges.next().await {
|
while let Some(new_ranges) = new_ranges.next().await {
|
||||||
|
smol::future::yield_now().await;
|
||||||
project_search
|
project_search
|
||||||
.update(cx, |project_search, cx| {
|
.update(cx, |project_search, cx| {
|
||||||
project_search.match_ranges.extend(new_ranges);
|
project_search.match_ranges.extend(new_ranges);
|
||||||
|
|||||||
@@ -403,6 +403,9 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Returns whether we found the item you were seeking for.
|
/// Returns whether we found the item you were seeking for.
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
/// If we did not seek before, use seek instead in that case
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
pub fn seek_forward<Target>(&mut self, pos: &Target, bias: Bias) -> bool
|
pub fn seek_forward<Target>(&mut self, pos: &Target, bias: Bias) -> bool
|
||||||
where
|
where
|
||||||
|
|||||||
@@ -1275,7 +1275,7 @@ impl Element for TerminalElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (relative_highlighted_range, color) in
|
for (relative_highlighted_range, color) in
|
||||||
layout.relative_highlighted_ranges.iter()
|
& layout.relative_highlighted_ranges
|
||||||
{
|
{
|
||||||
if let Some((start_y, highlighted_range_lines)) =
|
if let Some((start_y, highlighted_range_lines)) =
|
||||||
to_highlighted_range_lines(relative_highlighted_range, layout, origin)
|
to_highlighted_range_lines(relative_highlighted_range, layout, origin)
|
||||||
@@ -1542,11 +1542,13 @@ fn to_highlighted_range_lines(
|
|||||||
}
|
}
|
||||||
|
|
||||||
let clamped_start_line = unclamped_start.line.0.max(0) as usize;
|
let clamped_start_line = unclamped_start.line.0.max(0) as usize;
|
||||||
|
|
||||||
let clamped_end_line = unclamped_end
|
let clamped_end_line = unclamped_end
|
||||||
.line
|
.line
|
||||||
.0
|
.0
|
||||||
.min(layout.dimensions.num_lines() as i32) as usize;
|
.min(layout.dimensions.num_lines() as i32) as usize;
|
||||||
//Convert the start of the range to pixels
|
|
||||||
|
// Convert the start of the range to pixels
|
||||||
let start_y = origin.y + clamped_start_line as f32 * layout.dimensions.line_height;
|
let start_y = origin.y + clamped_start_line as f32 * layout.dimensions.line_height;
|
||||||
|
|
||||||
// Step 3. Expand ranges that cross lines into a collection of single-line ranges.
|
// Step 3. Expand ranges that cross lines into a collection of single-line ranges.
|
||||||
@@ -1556,10 +1558,11 @@ fn to_highlighted_range_lines(
|
|||||||
let mut line_start = 0;
|
let mut line_start = 0;
|
||||||
let mut line_end = layout.dimensions.columns();
|
let mut line_end = layout.dimensions.columns();
|
||||||
|
|
||||||
if line == clamped_start_line {
|
if line == clamped_start_line && unclamped_start.line.0 >= 0 {
|
||||||
line_start = unclamped_start.column.0;
|
line_start = unclamped_start.column.0;
|
||||||
}
|
}
|
||||||
if line == clamped_end_line {
|
if line == clamped_end_line && unclamped_end.line.0 <= layout.dimensions.num_lines() as i32
|
||||||
|
{
|
||||||
line_end = unclamped_end.column.0 + 1; // +1 for inclusive
|
line_end = unclamped_end.column.0 + 1; // +1 for inclusive
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2223,9 +2223,19 @@ impl BufferSnapshot {
|
|||||||
where
|
where
|
||||||
D: TextDimension,
|
D: TextDimension,
|
||||||
{
|
{
|
||||||
self.visible_text
|
let cursor = self.visible_text.cursor(range.start.to_offset(self));
|
||||||
.cursor(range.start.to_offset(self))
|
self.text_summary_for_range_(cursor, range)
|
||||||
.summary(range.end.to_offset(self))
|
}
|
||||||
|
|
||||||
|
pub fn text_summary_for_range_<D, O: ToOffset>(
|
||||||
|
&self,
|
||||||
|
mut cursor: Cursor<'_>,
|
||||||
|
range: Range<O>,
|
||||||
|
) -> D
|
||||||
|
where
|
||||||
|
D: TextDimension,
|
||||||
|
{
|
||||||
|
cursor.summary(range.end.to_offset(self))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn summaries_for_anchors<'a, D, A>(&'a self, anchors: A) -> impl 'a + Iterator<Item = D>
|
pub fn summaries_for_anchors<'a, D, A>(&'a self, anchors: A) -> impl 'a + Iterator<Item = D>
|
||||||
|
|||||||
@@ -183,7 +183,7 @@ macro_rules! time {
|
|||||||
$crate::Timer::new($logger, $name)
|
$crate::Timer::new($logger, $name)
|
||||||
};
|
};
|
||||||
($name:expr) => {
|
($name:expr) => {
|
||||||
time!($crate::default_logger!() => $name)
|
$crate::time!($crate::default_logger!() => $name)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user