Cargo.lock 🔗
@@ -3711,7 +3711,6 @@ dependencies = [
"tree-sitter-rust",
"tree-sitter-typescript",
"ui",
- "unicode-segmentation",
"unindent",
"url",
"util",
Conrad Irwin created
Closes: #19714
This reverts commit 6dcec47235fa85f0e416b9230e2fedc61de510ee.
Release Notes:
- (preview only) Fixes a crash when rendering invisibles
Cargo.lock | 1
Cargo.toml | 2
crates/editor/Cargo.toml | 1
crates/editor/src/display_map.rs | 118 +++++-------
crates/editor/src/display_map/block_map.rs | 55 ++---
crates/editor/src/display_map/invisibles.rs | 157 -----------------
crates/editor/src/display_map/tab_map.rs | 162 ++++++----------
crates/editor/src/display_map/wrap_map.rs | 211 +++++++++++-----------
crates/editor/src/element.rs | 17
crates/editor/src/hover_popover.rs | 45 ----
crates/gpui/src/text_system/line.rs | 51 ----
crates/language/src/buffer.rs | 3
12 files changed, 260 insertions(+), 563 deletions(-)
@@ -3711,7 +3711,6 @@ dependencies = [
"tree-sitter-rust",
"tree-sitter-typescript",
"ui",
- "unicode-segmentation",
"unindent",
"url",
"util",
@@ -464,7 +464,7 @@ tree-sitter-typescript = "0.23"
tree-sitter-yaml = { git = "https://github.com/zed-industries/tree-sitter-yaml", rev = "baff0b51c64ef6a1fb1f8390f3ad6015b83ec13a" }
unicase = "2.6"
unindent = "0.1.7"
-unicode-segmentation = "1.11"
+unicode-segmentation = "1.10"
url = "2.2"
uuid = { version = "1.1.2", features = ["v4", "v5", "serde"] }
wasmparser = "0.215"
@@ -81,7 +81,6 @@ ui.workspace = true
url.workspace = true
util.workspace = true
workspace.workspace = true
-unicode-segmentation.workspace = true
[dev-dependencies]
ctor.workspace = true
@@ -8,7 +8,7 @@
//! of several smaller structures that form a hierarchy (starting at the bottom):
//! - [`InlayMap`] that decides where the [`Inlay`]s should be displayed.
//! - [`FoldMap`] that decides where the fold indicators should be; it also tracks parts of a source file that are currently folded.
-//! - [`CharMap`] that replaces tabs and non-printable characters
+//! - [`TabMap`] that keeps track of hard tabs in a buffer.
//! - [`WrapMap`] that handles soft wrapping.
//! - [`BlockMap`] that tracks custom blocks such as diagnostics that should be displayed within buffer.
//! - [`DisplayMap`] that adds background highlights to the regions of text.
@@ -18,11 +18,10 @@
//! [EditorElement]: crate::element::EditorElement
mod block_map;
-mod char_map;
mod crease_map;
mod fold_map;
mod inlay_map;
-mod invisibles;
+mod tab_map;
mod wrap_map;
use crate::{
@@ -33,7 +32,6 @@ pub use block_map::{
BlockPlacement, BlockPoint, BlockProperties, BlockStyle, CustomBlockId, RenderBlock,
};
use block_map::{BlockRow, BlockSnapshot};
-use char_map::{CharMap, CharSnapshot};
use collections::{HashMap, HashSet};
pub use crease_map::*;
pub use fold_map::{Fold, FoldId, FoldPlaceholder, FoldPoint};
@@ -44,7 +42,6 @@ use gpui::{
pub(crate) use inlay_map::Inlay;
use inlay_map::{InlayMap, InlaySnapshot};
pub use inlay_map::{InlayOffset, InlayPoint};
-pub use invisibles::is_invisible;
use language::{
language_settings::language_settings, ChunkRenderer, OffsetUtf16, Point,
Subscription as BufferSubscription,
@@ -64,9 +61,9 @@ use std::{
sync::Arc,
};
use sum_tree::{Bias, TreeMap};
+use tab_map::{TabMap, TabSnapshot};
use text::LineIndent;
-use ui::{px, WindowContext};
-use unicode_segmentation::UnicodeSegmentation;
+use ui::WindowContext;
use wrap_map::{WrapMap, WrapSnapshot};
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
@@ -97,7 +94,7 @@ pub struct DisplayMap {
/// Decides where the fold indicators should be and tracks parts of a source file that are currently folded.
fold_map: FoldMap,
/// Keeps track of hard tabs in a buffer.
- char_map: CharMap,
+ tab_map: TabMap,
/// Handles soft wrapping.
wrap_map: Model<WrapMap>,
/// Tracks custom blocks such as diagnostics that should be displayed within buffer.
@@ -134,7 +131,7 @@ impl DisplayMap {
let crease_map = CreaseMap::new(&buffer_snapshot);
let (inlay_map, snapshot) = InlayMap::new(buffer_snapshot);
let (fold_map, snapshot) = FoldMap::new(snapshot);
- let (char_map, snapshot) = CharMap::new(snapshot, tab_size);
+ let (tab_map, snapshot) = TabMap::new(snapshot, tab_size);
let (wrap_map, snapshot) = WrapMap::new(snapshot, font, font_size, wrap_width, cx);
let block_map = BlockMap::new(
snapshot,
@@ -151,7 +148,7 @@ impl DisplayMap {
buffer_subscription,
fold_map,
inlay_map,
- char_map,
+ tab_map,
wrap_map,
block_map,
crease_map,
@@ -169,17 +166,17 @@ impl DisplayMap {
let (inlay_snapshot, edits) = self.inlay_map.sync(buffer_snapshot, edits);
let (fold_snapshot, edits) = self.fold_map.read(inlay_snapshot.clone(), edits);
let tab_size = Self::tab_size(&self.buffer, cx);
- let (char_snapshot, edits) = self.char_map.sync(fold_snapshot.clone(), edits, tab_size);
+ let (tab_snapshot, edits) = self.tab_map.sync(fold_snapshot.clone(), edits, tab_size);
let (wrap_snapshot, edits) = self
.wrap_map
- .update(cx, |map, cx| map.sync(char_snapshot.clone(), edits, cx));
+ .update(cx, |map, cx| map.sync(tab_snapshot.clone(), edits, cx));
let block_snapshot = self.block_map.read(wrap_snapshot.clone(), edits).snapshot;
DisplaySnapshot {
buffer_snapshot: self.buffer.read(cx).snapshot(cx),
fold_snapshot,
inlay_snapshot,
- char_snapshot,
+ tab_snapshot,
wrap_snapshot,
block_snapshot,
crease_snapshot: self.crease_map.snapshot(),
@@ -215,13 +212,13 @@ impl DisplayMap {
let tab_size = Self::tab_size(&self.buffer, cx);
let (snapshot, edits) = self.inlay_map.sync(snapshot, edits);
let (mut fold_map, snapshot, edits) = self.fold_map.write(snapshot, edits);
- let (snapshot, edits) = self.char_map.sync(snapshot, edits, tab_size);
+ let (snapshot, edits) = self.tab_map.sync(snapshot, edits, tab_size);
let (snapshot, edits) = self
.wrap_map
.update(cx, |map, cx| map.sync(snapshot, edits, cx));
self.block_map.read(snapshot, edits);
let (snapshot, edits) = fold_map.fold(ranges);
- let (snapshot, edits) = self.char_map.sync(snapshot, edits, tab_size);
+ let (snapshot, edits) = self.tab_map.sync(snapshot, edits, tab_size);
let (snapshot, edits) = self
.wrap_map
.update(cx, |map, cx| map.sync(snapshot, edits, cx));
@@ -239,13 +236,13 @@ impl DisplayMap {
let tab_size = Self::tab_size(&self.buffer, cx);
let (snapshot, edits) = self.inlay_map.sync(snapshot, edits);
let (mut fold_map, snapshot, edits) = self.fold_map.write(snapshot, edits);
- let (snapshot, edits) = self.char_map.sync(snapshot, edits, tab_size);
+ let (snapshot, edits) = self.tab_map.sync(snapshot, edits, tab_size);
let (snapshot, edits) = self
.wrap_map
.update(cx, |map, cx| map.sync(snapshot, edits, cx));
self.block_map.read(snapshot, edits);
let (snapshot, edits) = fold_map.unfold(ranges, inclusive);
- let (snapshot, edits) = self.char_map.sync(snapshot, edits, tab_size);
+ let (snapshot, edits) = self.tab_map.sync(snapshot, edits, tab_size);
let (snapshot, edits) = self
.wrap_map
.update(cx, |map, cx| map.sync(snapshot, edits, cx));
@@ -280,7 +277,7 @@ impl DisplayMap {
let tab_size = Self::tab_size(&self.buffer, cx);
let (snapshot, edits) = self.inlay_map.sync(snapshot, edits);
let (snapshot, edits) = self.fold_map.read(snapshot, edits);
- let (snapshot, edits) = self.char_map.sync(snapshot, edits, tab_size);
+ let (snapshot, edits) = self.tab_map.sync(snapshot, edits, tab_size);
let (snapshot, edits) = self
.wrap_map
.update(cx, |map, cx| map.sync(snapshot, edits, cx));
@@ -298,7 +295,7 @@ impl DisplayMap {
let tab_size = Self::tab_size(&self.buffer, cx);
let (snapshot, edits) = self.inlay_map.sync(snapshot, edits);
let (snapshot, edits) = self.fold_map.read(snapshot, edits);
- let (snapshot, edits) = self.char_map.sync(snapshot, edits, tab_size);
+ let (snapshot, edits) = self.tab_map.sync(snapshot, edits, tab_size);
let (snapshot, edits) = self
.wrap_map
.update(cx, |map, cx| map.sync(snapshot, edits, cx));
@@ -316,7 +313,7 @@ impl DisplayMap {
let tab_size = Self::tab_size(&self.buffer, cx);
let (snapshot, edits) = self.inlay_map.sync(snapshot, edits);
let (snapshot, edits) = self.fold_map.read(snapshot, edits);
- let (snapshot, edits) = self.char_map.sync(snapshot, edits, tab_size);
+ let (snapshot, edits) = self.tab_map.sync(snapshot, edits, tab_size);
let (snapshot, edits) = self
.wrap_map
.update(cx, |map, cx| map.sync(snapshot, edits, cx));
@@ -334,7 +331,7 @@ impl DisplayMap {
let tab_size = Self::tab_size(&self.buffer, cx);
let (snapshot, edits) = self.inlay_map.sync(snapshot, edits);
let (snapshot, edits) = self.fold_map.read(snapshot, edits);
- let (snapshot, edits) = self.char_map.sync(snapshot, edits, tab_size);
+ let (snapshot, edits) = self.tab_map.sync(snapshot, edits, tab_size);
let (snapshot, edits) = self
.wrap_map
.update(cx, |map, cx| map.sync(snapshot, edits, cx));
@@ -410,7 +407,7 @@ impl DisplayMap {
let (snapshot, edits) = self.inlay_map.sync(buffer_snapshot, edits);
let (snapshot, edits) = self.fold_map.read(snapshot, edits);
let tab_size = Self::tab_size(&self.buffer, cx);
- let (snapshot, edits) = self.char_map.sync(snapshot, edits, tab_size);
+ let (snapshot, edits) = self.tab_map.sync(snapshot, edits, tab_size);
let (snapshot, edits) = self
.wrap_map
.update(cx, |map, cx| map.sync(snapshot, edits, cx));
@@ -418,7 +415,7 @@ impl DisplayMap {
let (snapshot, edits) = self.inlay_map.splice(to_remove, to_insert);
let (snapshot, edits) = self.fold_map.read(snapshot, edits);
- let (snapshot, edits) = self.char_map.sync(snapshot, edits, tab_size);
+ let (snapshot, edits) = self.tab_map.sync(snapshot, edits, tab_size);
let (snapshot, edits) = self
.wrap_map
.update(cx, |map, cx| map.sync(snapshot, edits, cx));
@@ -470,7 +467,7 @@ pub struct DisplaySnapshot {
pub fold_snapshot: FoldSnapshot,
pub crease_snapshot: CreaseSnapshot,
inlay_snapshot: InlaySnapshot,
- char_snapshot: CharSnapshot,
+ tab_snapshot: TabSnapshot,
wrap_snapshot: WrapSnapshot,
block_snapshot: BlockSnapshot,
text_highlights: TextHighlights,
@@ -570,8 +567,8 @@ impl DisplaySnapshot {
fn point_to_display_point(&self, point: MultiBufferPoint, bias: Bias) -> DisplayPoint {
let inlay_point = self.inlay_snapshot.to_inlay_point(point);
let fold_point = self.fold_snapshot.to_fold_point(inlay_point, bias);
- let char_point = self.char_snapshot.to_char_point(fold_point);
- let wrap_point = self.wrap_snapshot.char_point_to_wrap_point(char_point);
+ let tab_point = self.tab_snapshot.to_tab_point(fold_point);
+ let wrap_point = self.wrap_snapshot.tab_point_to_wrap_point(tab_point);
let block_point = self.block_snapshot.to_block_point(wrap_point);
DisplayPoint(block_point)
}
@@ -599,21 +596,21 @@ impl DisplaySnapshot {
fn display_point_to_inlay_point(&self, point: DisplayPoint, bias: Bias) -> InlayPoint {
let block_point = point.0;
let wrap_point = self.block_snapshot.to_wrap_point(block_point);
- let char_point = self.wrap_snapshot.to_char_point(wrap_point);
- let fold_point = self.char_snapshot.to_fold_point(char_point, bias).0;
+ let tab_point = self.wrap_snapshot.to_tab_point(wrap_point);
+ let fold_point = self.tab_snapshot.to_fold_point(tab_point, bias).0;
fold_point.to_inlay_point(&self.fold_snapshot)
}
pub fn display_point_to_fold_point(&self, point: DisplayPoint, bias: Bias) -> FoldPoint {
let block_point = point.0;
let wrap_point = self.block_snapshot.to_wrap_point(block_point);
- let char_point = self.wrap_snapshot.to_char_point(wrap_point);
- self.char_snapshot.to_fold_point(char_point, bias).0
+ let tab_point = self.wrap_snapshot.to_tab_point(wrap_point);
+ self.tab_snapshot.to_fold_point(tab_point, bias).0
}
pub fn fold_point_to_display_point(&self, fold_point: FoldPoint) -> DisplayPoint {
- let char_point = self.char_snapshot.to_char_point(fold_point);
- let wrap_point = self.wrap_snapshot.char_point_to_wrap_point(char_point);
+ let tab_point = self.tab_snapshot.to_tab_point(fold_point);
+ let wrap_point = self.wrap_snapshot.tab_point_to_wrap_point(tab_point);
let block_point = self.block_snapshot.to_block_point(wrap_point);
DisplayPoint(block_point)
}
@@ -691,23 +688,6 @@ impl DisplaySnapshot {
}
}
- if chunk.is_invisible {
- let invisible_highlight = HighlightStyle {
- background_color: Some(editor_style.status.hint_background),
- underline: Some(UnderlineStyle {
- color: Some(editor_style.status.hint),
- thickness: px(1.),
- wavy: false,
- }),
- ..Default::default()
- };
- if let Some(highlight_style) = highlight_style.as_mut() {
- highlight_style.highlight(invisible_highlight);
- } else {
- highlight_style = Some(invisible_highlight);
- }
- }
-
let mut diagnostic_highlight = HighlightStyle::default();
if chunk.is_unnecessary {
@@ -804,11 +784,12 @@ impl DisplaySnapshot {
layout_line.closest_index_for_x(x) as u32
}
- pub fn grapheme_at(&self, mut point: DisplayPoint) -> Option<String> {
+ pub fn display_chars_at(
+ &self,
+ mut point: DisplayPoint,
+ ) -> impl Iterator<Item = (char, DisplayPoint)> + '_ {
point = DisplayPoint(self.block_snapshot.clip_point(point.0, Bias::Left));
-
- let chars = self
- .text_chunks(point.row())
+ self.text_chunks(point.row())
.flat_map(str::chars)
.skip_while({
let mut column = 0;
@@ -818,21 +799,16 @@ impl DisplaySnapshot {
!at_point
}
})
- .take_while({
- let mut prev = false;
- move |char| {
- let now = char.is_ascii();
- let end = char.is_ascii() && (char.is_ascii_whitespace() || prev);
- prev = now;
- !end
+ .map(move |ch| {
+ let result = (ch, point);
+ if ch == '\n' {
+ *point.row_mut() += 1;
+ *point.column_mut() = 0;
+ } else {
+ *point.column_mut() += ch.len_utf8() as u32;
}
- });
-
- chars
- .collect::<String>()
- .graphemes(true)
- .next()
- .map(|s| s.to_owned())
+ result
+ })
}
pub fn buffer_chars_at(&self, mut offset: usize) -> impl Iterator<Item = (char, usize)> + '_ {
@@ -1144,8 +1120,8 @@ impl DisplayPoint {
pub fn to_offset(self, map: &DisplaySnapshot, bias: Bias) -> usize {
let wrap_point = map.block_snapshot.to_wrap_point(self.0);
- let char_point = map.wrap_snapshot.to_char_point(wrap_point);
- let fold_point = map.char_snapshot.to_fold_point(char_point, bias).0;
+ let tab_point = map.wrap_snapshot.to_tab_point(wrap_point);
+ let fold_point = map.tab_snapshot.to_fold_point(tab_point, bias).0;
let inlay_point = fold_point.to_inlay_point(&map.fold_snapshot);
map.inlay_snapshot
.to_buffer_offset(map.inlay_snapshot.to_offset(inlay_point))
@@ -1253,7 +1229,7 @@ pub mod tests {
let snapshot = map.update(cx, |map, cx| map.snapshot(cx));
log::info!("buffer text: {:?}", snapshot.buffer_snapshot.text());
log::info!("fold text: {:?}", snapshot.fold_snapshot.text());
- log::info!("char text: {:?}", snapshot.char_snapshot.text());
+ log::info!("tab text: {:?}", snapshot.tab_snapshot.text());
log::info!("wrap text: {:?}", snapshot.wrap_snapshot.text());
log::info!("block text: {:?}", snapshot.block_snapshot.text());
log::info!("display text: {:?}", snapshot.text());
@@ -1368,7 +1344,7 @@ pub mod tests {
fold_count = snapshot.fold_count();
log::info!("buffer text: {:?}", snapshot.buffer_snapshot.text());
log::info!("fold text: {:?}", snapshot.fold_snapshot.text());
- log::info!("char text: {:?}", snapshot.char_snapshot.text());
+ log::info!("tab text: {:?}", snapshot.tab_snapshot.text());
log::info!("wrap text: {:?}", snapshot.wrap_snapshot.text());
log::info!("block text: {:?}", snapshot.block_snapshot.text());
log::info!("display text: {:?}", snapshot.text());
@@ -1666,7 +1666,7 @@ fn offset_for_row(s: &str, target: u32) -> (u32, usize) {
mod tests {
use super::*;
use crate::display_map::{
- char_map::CharMap, fold_map::FoldMap, inlay_map::InlayMap, wrap_map::WrapMap,
+ fold_map::FoldMap, inlay_map::InlayMap, tab_map::TabMap, wrap_map::WrapMap,
};
use gpui::{div, font, px, AppContext, Context as _, Element};
use language::{Buffer, Capability};
@@ -1701,9 +1701,9 @@ mod tests {
let subscription = buffer.update(cx, |buffer, _| buffer.subscribe());
let (mut inlay_map, inlay_snapshot) = InlayMap::new(buffer_snapshot.clone());
let (mut fold_map, fold_snapshot) = FoldMap::new(inlay_snapshot);
- let (mut char_map, char_snapshot) = CharMap::new(fold_snapshot, 1.try_into().unwrap());
+ let (mut tab_map, tab_snapshot) = TabMap::new(fold_snapshot, 1.try_into().unwrap());
let (wrap_map, wraps_snapshot) =
- cx.update(|cx| WrapMap::new(char_snapshot, font("Helvetica"), px(14.0), None, cx));
+ cx.update(|cx| WrapMap::new(tab_snapshot, font("Helvetica"), px(14.0), None, cx));
let mut block_map = BlockMap::new(wraps_snapshot.clone(), true, 1, 1, 1);
let mut writer = block_map.write(wraps_snapshot.clone(), Default::default());
@@ -1851,10 +1851,10 @@ mod tests {
let (inlay_snapshot, inlay_edits) =
inlay_map.sync(buffer_snapshot, subscription.consume().into_inner());
let (fold_snapshot, fold_edits) = fold_map.read(inlay_snapshot, inlay_edits);
- let (char_snapshot, tab_edits) =
- char_map.sync(fold_snapshot, fold_edits, 4.try_into().unwrap());
+ let (tab_snapshot, tab_edits) =
+ tab_map.sync(fold_snapshot, fold_edits, 4.try_into().unwrap());
let (wraps_snapshot, wrap_edits) = wrap_map.update(cx, |wrap_map, cx| {
- wrap_map.sync(char_snapshot, tab_edits, cx)
+ wrap_map.sync(tab_snapshot, tab_edits, cx)
});
let snapshot = block_map.read(wraps_snapshot, wrap_edits);
assert_eq!(snapshot.text(), "aaa\n\nb!!!\n\n\nbb\nccc\nddd\n\n\n");
@@ -1914,9 +1914,8 @@ mod tests {
let multi_buffer_snapshot = multi_buffer.read(cx).snapshot(cx);
let (_, inlay_snapshot) = InlayMap::new(multi_buffer_snapshot.clone());
let (_, fold_snapshot) = FoldMap::new(inlay_snapshot);
- let (_, char_snapshot) = CharMap::new(fold_snapshot, 4.try_into().unwrap());
- let (_, wraps_snapshot) =
- WrapMap::new(char_snapshot, font, font_size, Some(wrap_width), cx);
+ let (_, tab_snapshot) = TabMap::new(fold_snapshot, 4.try_into().unwrap());
+ let (_, wraps_snapshot) = WrapMap::new(tab_snapshot, font, font_size, Some(wrap_width), cx);
let block_map = BlockMap::new(wraps_snapshot.clone(), true, 1, 1, 1);
let snapshot = block_map.read(wraps_snapshot, Default::default());
@@ -1953,9 +1952,9 @@ mod tests {
let _subscription = buffer.update(cx, |buffer, _| buffer.subscribe());
let (_inlay_map, inlay_snapshot) = InlayMap::new(buffer_snapshot.clone());
let (_fold_map, fold_snapshot) = FoldMap::new(inlay_snapshot);
- let (_char_map, char_snapshot) = CharMap::new(fold_snapshot, 1.try_into().unwrap());
+ let (_tab_map, tab_snapshot) = TabMap::new(fold_snapshot, 1.try_into().unwrap());
let (_wrap_map, wraps_snapshot) =
- cx.update(|cx| WrapMap::new(char_snapshot, font("Helvetica"), px(14.0), None, cx));
+ cx.update(|cx| WrapMap::new(tab_snapshot, font("Helvetica"), px(14.0), None, cx));
let mut block_map = BlockMap::new(wraps_snapshot.clone(), false, 1, 1, 0);
let mut writer = block_map.write(wraps_snapshot.clone(), Default::default());
@@ -2055,15 +2054,9 @@ mod tests {
let buffer_snapshot = cx.update(|cx| buffer.read(cx).snapshot(cx));
let (_, inlay_snapshot) = InlayMap::new(buffer_snapshot.clone());
let (_, fold_snapshot) = FoldMap::new(inlay_snapshot);
- let (_, char_snapshot) = CharMap::new(fold_snapshot, 4.try_into().unwrap());
+ let (_, tab_snapshot) = TabMap::new(fold_snapshot, 4.try_into().unwrap());
let (_, wraps_snapshot) = cx.update(|cx| {
- WrapMap::new(
- char_snapshot,
- font("Helvetica"),
- px(14.0),
- Some(px(60.)),
- cx,
- )
+ WrapMap::new(tab_snapshot, font("Helvetica"), px(14.0), Some(px(60.)), cx)
});
let mut block_map = BlockMap::new(wraps_snapshot.clone(), true, 1, 1, 0);
@@ -2106,7 +2099,7 @@ mod tests {
let (mut inlay_map, inlay_snapshot) = InlayMap::new(buffer_snapshot.clone());
let (mut fold_map, fold_snapshot) = FoldMap::new(inlay_snapshot);
let tab_size = 1.try_into().unwrap();
- let (mut tab_map, tab_snapshot) = CharMap::new(fold_snapshot, tab_size);
+ let (mut tab_map, tab_snapshot) = TabMap::new(fold_snapshot, tab_size);
let (wrap_map, wraps_snapshot) =
cx.update(|cx| WrapMap::new(tab_snapshot, font("Helvetica"), px(14.0), None, cx));
let mut block_map = BlockMap::new(wraps_snapshot.clone(), false, 1, 1, 0);
@@ -2257,9 +2250,9 @@ mod tests {
let mut buffer_snapshot = cx.update(|cx| buffer.read(cx).snapshot(cx));
let (mut inlay_map, inlay_snapshot) = InlayMap::new(buffer_snapshot.clone());
let (mut fold_map, fold_snapshot) = FoldMap::new(inlay_snapshot);
- let (mut char_map, char_snapshot) = CharMap::new(fold_snapshot, 4.try_into().unwrap());
+ let (mut tab_map, tab_snapshot) = TabMap::new(fold_snapshot, 4.try_into().unwrap());
let (wrap_map, wraps_snapshot) = cx
- .update(|cx| WrapMap::new(char_snapshot, font("Helvetica"), font_size, wrap_width, cx));
+ .update(|cx| WrapMap::new(tab_snapshot, font("Helvetica"), font_size, wrap_width, cx));
let mut block_map = BlockMap::new(
wraps_snapshot,
true,
@@ -2321,10 +2314,10 @@ mod tests {
let (inlay_snapshot, inlay_edits) =
inlay_map.sync(buffer_snapshot.clone(), vec![]);
let (fold_snapshot, fold_edits) = fold_map.read(inlay_snapshot, inlay_edits);
- let (char_snapshot, tab_edits) =
- char_map.sync(fold_snapshot, fold_edits, tab_size);
+ let (tab_snapshot, tab_edits) =
+ tab_map.sync(fold_snapshot, fold_edits, tab_size);
let (wraps_snapshot, wrap_edits) = wrap_map.update(cx, |wrap_map, cx| {
- wrap_map.sync(char_snapshot, tab_edits, cx)
+ wrap_map.sync(tab_snapshot, tab_edits, cx)
});
let mut block_map = block_map.write(wraps_snapshot, wrap_edits);
block_map.insert(block_properties.iter().map(|props| BlockProperties {
@@ -2346,10 +2339,10 @@ mod tests {
let (inlay_snapshot, inlay_edits) =
inlay_map.sync(buffer_snapshot.clone(), vec![]);
let (fold_snapshot, fold_edits) = fold_map.read(inlay_snapshot, inlay_edits);
- let (char_snapshot, tab_edits) =
- char_map.sync(fold_snapshot, fold_edits, tab_size);
+ let (tab_snapshot, tab_edits) =
+ tab_map.sync(fold_snapshot, fold_edits, tab_size);
let (wraps_snapshot, wrap_edits) = wrap_map.update(cx, |wrap_map, cx| {
- wrap_map.sync(char_snapshot, tab_edits, cx)
+ wrap_map.sync(tab_snapshot, tab_edits, cx)
});
let mut block_map = block_map.write(wraps_snapshot, wrap_edits);
block_map.remove(block_ids_to_remove);
@@ -2369,9 +2362,9 @@ mod tests {
let (inlay_snapshot, inlay_edits) =
inlay_map.sync(buffer_snapshot.clone(), buffer_edits);
let (fold_snapshot, fold_edits) = fold_map.read(inlay_snapshot, inlay_edits);
- let (char_snapshot, tab_edits) = char_map.sync(fold_snapshot, fold_edits, tab_size);
+ let (tab_snapshot, tab_edits) = tab_map.sync(fold_snapshot, fold_edits, tab_size);
let (wraps_snapshot, wrap_edits) = wrap_map.update(cx, |wrap_map, cx| {
- wrap_map.sync(char_snapshot, tab_edits, cx)
+ wrap_map.sync(tab_snapshot, tab_edits, cx)
});
let blocks_snapshot = block_map.read(wraps_snapshot.clone(), wrap_edits);
assert_eq!(
@@ -2486,7 +2479,7 @@ mod tests {
.row as usize];
let soft_wrapped = wraps_snapshot
- .to_char_point(WrapPoint::new(wrap_row, 0))
+ .to_tab_point(WrapPoint::new(wrap_row, 0))
.column()
> 0;
expected_buffer_rows.push(if soft_wrapped { None } else { buffer_row });
@@ -1,157 +0,0 @@
-use std::sync::LazyLock;
-
-use collections::HashMap;
-
-// Invisibility in a Unicode context is not well defined, so we have to guess.
-//
-// We highlight all ASCII control codes, and unicode whitespace because they are likely
-// confused with a normal space (U+0020).
-//
-// We also highlight the handful of blank non-space characters:
-// U+2800 BRAILLE PATTERN BLANK - Category: So
-// U+115F HANGUL CHOSEONG FILLER - Category: Lo
-// U+1160 HANGUL CHOSEONG FILLER - Category: Lo
-// U+3164 HANGUL FILLER - Category: Lo
-// U+FFA0 HALFWIDTH HANGUL FILLER - Category: Lo
-// U+FFFC OBJECT REPLACEMENT CHARACTER - Category: So
-//
-// For the rest of Unicode, invisibility happens for two reasons:
-// * A Format character (like a byte order mark or right-to-left override)
-// * An invisible Nonspacing Mark character (like U+034F, or variation selectors)
-//
-// We don't consider unassigned codepoints invisible as the font renderer already shows
-// a replacement character in that case (and there are a *lot* of them)
-//
-// Control characters are mostly fine to highlight; except:
-// * U+E0020..=U+E007F are used in emoji flags. We don't highlight them right now, but we could if we tightened our heuristics.
-// * U+200D is used to join characters. We highlight this but don't replace it. As our font system ignores mid-glyph highlights this mostly works to highlight unexpected uses.
-//
-// Nonspacing marks are handled like U+200D. This means that mid-glyph we ignore them, but
-// probably causes issues with end-of-glyph usage.
-//
-// ref: https://invisible-characters.com
-// ref: https://www.compart.com/en/unicode/category/Cf
-// ref: https://gist.github.com/ConradIrwin/f759e1fc29267143c4c7895aa495dca5?h=1
-// ref: https://unicode.org/Public/emoji/13.0/emoji-test.txt
-// https://github.com/bits/UTF-8-Unicode-Test-Documents/blob/master/UTF-8_sequence_separated/utf8_sequence_0-0x10ffff_assigned_including-unprintable-asis.txt
-pub fn is_invisible(c: char) -> bool {
- if c <= '\u{1f}' {
- c != '\t' && c != '\n' && c != '\r'
- } else if c >= '\u{7f}' {
- c <= '\u{9f}' || c.is_whitespace() || contains(c, &FORMAT) || contains(c, &OTHER)
- } else {
- false
- }
-}
-
-pub(crate) fn replacement(c: char) -> Option<&'static str> {
- if !is_invisible(c) {
- return None;
- }
- if c <= '\x7f' {
- REPLACEMENTS.get(&c).copied()
- } else if contains(c, &PRESERVE) {
- None
- } else {
- Some(" ")
- }
-}
-
-const REPLACEMENTS: LazyLock<HashMap<char, &'static str>> = LazyLock::new(|| {
- [
- ('\x00', "␀"),
- ('\x01', "␁"),
- ('\x02', "␂"),
- ('\x03', "␃"),
- ('\x04', "␄"),
- ('\x05', "␅"),
- ('\x06', "␆"),
- ('\x07', "␇"),
- ('\x08', "␈"),
- ('\x0B', "␋"),
- ('\x0C', "␌"),
- ('\x0D', "␍"),
- ('\x0E', "␎"),
- ('\x0F', "␏"),
- ('\x10', "␐"),
- ('\x11', "␑"),
- ('\x12', "␒"),
- ('\x13', "␓"),
- ('\x14', "␔"),
- ('\x15', "␕"),
- ('\x16', "␖"),
- ('\x17', "␗"),
- ('\x18', "␘"),
- ('\x19', "␙"),
- ('\x1A', "␚"),
- ('\x1B', "␛"),
- ('\x1C', "␜"),
- ('\x1D', "␝"),
- ('\x1E', "␞"),
- ('\x1F', "␟"),
- ('\u{007F}', "␡"),
- ]
- .into_iter()
- .collect()
-});
-
-// generated using ucd-generate: ucd-generate general-category --include Format --chars ucd-16.0.0
-pub const FORMAT: &'static [(char, char)] = &[
- ('\u{ad}', '\u{ad}'),
- ('\u{600}', '\u{605}'),
- ('\u{61c}', '\u{61c}'),
- ('\u{6dd}', '\u{6dd}'),
- ('\u{70f}', '\u{70f}'),
- ('\u{890}', '\u{891}'),
- ('\u{8e2}', '\u{8e2}'),
- ('\u{180e}', '\u{180e}'),
- ('\u{200b}', '\u{200f}'),
- ('\u{202a}', '\u{202e}'),
- ('\u{2060}', '\u{2064}'),
- ('\u{2066}', '\u{206f}'),
- ('\u{feff}', '\u{feff}'),
- ('\u{fff9}', '\u{fffb}'),
- ('\u{110bd}', '\u{110bd}'),
- ('\u{110cd}', '\u{110cd}'),
- ('\u{13430}', '\u{1343f}'),
- ('\u{1bca0}', '\u{1bca3}'),
- ('\u{1d173}', '\u{1d17a}'),
- ('\u{e0001}', '\u{e0001}'),
- ('\u{e0020}', '\u{e007f}'),
-];
-
-// hand-made base on https://invisible-characters.com (Excluding Cf)
-pub const OTHER: &'static [(char, char)] = &[
- ('\u{034f}', '\u{034f}'),
- ('\u{115F}', '\u{1160}'),
- ('\u{17b4}', '\u{17b5}'),
- ('\u{180b}', '\u{180d}'),
- ('\u{2800}', '\u{2800}'),
- ('\u{3164}', '\u{3164}'),
- ('\u{fe00}', '\u{fe0d}'),
- ('\u{ffa0}', '\u{ffa0}'),
- ('\u{fffc}', '\u{fffc}'),
- ('\u{e0100}', '\u{e01ef}'),
-];
-
-// a subset of FORMAT/OTHER that may appear within glyphs
-const PRESERVE: &'static [(char, char)] = &[
- ('\u{034f}', '\u{034f}'),
- ('\u{200d}', '\u{200d}'),
- ('\u{17b4}', '\u{17b5}'),
- ('\u{180b}', '\u{180d}'),
- ('\u{e0061}', '\u{e007a}'),
- ('\u{e007f}', '\u{e007f}'),
-];
-
-fn contains(c: char, list: &[(char, char)]) -> bool {
- for (start, end) in list {
- if c < *start {
- return false;
- }
- if c <= *end {
- return true;
- }
- }
- false
-}
@@ -1,6 +1,5 @@
use super::{
fold_map::{self, FoldChunks, FoldEdit, FoldPoint, FoldSnapshot},
- invisibles::{is_invisible, replacement},
Highlights,
};
use language::{Chunk, Point};
@@ -10,14 +9,14 @@ use sum_tree::Bias;
const MAX_EXPANSION_COLUMN: u32 = 256;
-/// Keeps track of hard tabs and non-printable characters in a text buffer.
+/// Keeps track of hard tabs in a text buffer.
///
/// See the [`display_map` module documentation](crate::display_map) for more information.
-pub struct CharMap(CharSnapshot);
+pub struct TabMap(TabSnapshot);
-impl CharMap {
- pub fn new(fold_snapshot: FoldSnapshot, tab_size: NonZeroU32) -> (Self, CharSnapshot) {
- let snapshot = CharSnapshot {
+impl TabMap {
+ pub fn new(fold_snapshot: FoldSnapshot, tab_size: NonZeroU32) -> (Self, TabSnapshot) {
+ let snapshot = TabSnapshot {
fold_snapshot,
tab_size,
max_expansion_column: MAX_EXPANSION_COLUMN,
@@ -27,7 +26,7 @@ impl CharMap {
}
#[cfg(test)]
- pub fn set_max_expansion_column(&mut self, column: u32) -> CharSnapshot {
+ pub fn set_max_expansion_column(&mut self, column: u32) -> TabSnapshot {
self.0.max_expansion_column = column;
self.0.clone()
}
@@ -37,9 +36,9 @@ impl CharMap {
fold_snapshot: FoldSnapshot,
mut fold_edits: Vec<FoldEdit>,
tab_size: NonZeroU32,
- ) -> (CharSnapshot, Vec<TabEdit>) {
+ ) -> (TabSnapshot, Vec<TabEdit>) {
let old_snapshot = &mut self.0;
- let mut new_snapshot = CharSnapshot {
+ let mut new_snapshot = TabSnapshot {
fold_snapshot,
tab_size,
max_expansion_column: old_snapshot.max_expansion_column,
@@ -138,15 +137,15 @@ impl CharMap {
let new_start = fold_edit.new.start.to_point(&new_snapshot.fold_snapshot);
let new_end = fold_edit.new.end.to_point(&new_snapshot.fold_snapshot);
tab_edits.push(TabEdit {
- old: old_snapshot.to_char_point(old_start)..old_snapshot.to_char_point(old_end),
- new: new_snapshot.to_char_point(new_start)..new_snapshot.to_char_point(new_end),
+ old: old_snapshot.to_tab_point(old_start)..old_snapshot.to_tab_point(old_end),
+ new: new_snapshot.to_tab_point(new_start)..new_snapshot.to_tab_point(new_end),
});
}
} else {
new_snapshot.version += 1;
tab_edits.push(TabEdit {
- old: CharPoint::zero()..old_snapshot.max_point(),
- new: CharPoint::zero()..new_snapshot.max_point(),
+ old: TabPoint::zero()..old_snapshot.max_point(),
+ new: TabPoint::zero()..new_snapshot.max_point(),
});
}
@@ -156,14 +155,14 @@ impl CharMap {
}
#[derive(Clone)]
-pub struct CharSnapshot {
+pub struct TabSnapshot {
pub fold_snapshot: FoldSnapshot,
pub tab_size: NonZeroU32,
pub max_expansion_column: u32,
pub version: usize,
}
-impl CharSnapshot {
+impl TabSnapshot {
pub fn buffer_snapshot(&self) -> &MultiBufferSnapshot {
&self.fold_snapshot.inlay_snapshot.buffer
}
@@ -171,7 +170,7 @@ impl CharSnapshot {
pub fn line_len(&self, row: u32) -> u32 {
let max_point = self.max_point();
if row < max_point.row() {
- self.to_char_point(FoldPoint::new(row, self.fold_snapshot.line_len(row)))
+ self.to_tab_point(FoldPoint::new(row, self.fold_snapshot.line_len(row)))
.0
.column
} else {
@@ -180,10 +179,10 @@ impl CharSnapshot {
}
pub fn text_summary(&self) -> TextSummary {
- self.text_summary_for_range(CharPoint::zero()..self.max_point())
+ self.text_summary_for_range(TabPoint::zero()..self.max_point())
}
- pub fn text_summary_for_range(&self, range: Range<CharPoint>) -> TextSummary {
+ pub fn text_summary_for_range(&self, range: Range<TabPoint>) -> TextSummary {
let input_start = self.to_fold_point(range.start, Bias::Left).0;
let input_end = self.to_fold_point(range.end, Bias::Right).0;
let input_summary = self
@@ -212,7 +211,7 @@ impl CharSnapshot {
} else {
for _ in self
.chunks(
- CharPoint::new(range.end.row(), 0)..range.end,
+ TabPoint::new(range.end.row(), 0)..range.end,
false,
Highlights::default(),
)
@@ -233,7 +232,7 @@ impl CharSnapshot {
pub fn chunks<'a>(
&'a self,
- range: Range<CharPoint>,
+ range: Range<TabPoint>,
language_aware: bool,
highlights: Highlights<'a>,
) -> TabChunks<'a> {
@@ -280,7 +279,7 @@ impl CharSnapshot {
#[cfg(test)]
pub fn text(&self) -> String {
self.chunks(
- CharPoint::zero()..self.max_point(),
+ TabPoint::zero()..self.max_point(),
false,
Highlights::default(),
)
@@ -288,24 +287,24 @@ impl CharSnapshot {
.collect()
}
- pub fn max_point(&self) -> CharPoint {
- self.to_char_point(self.fold_snapshot.max_point())
+ pub fn max_point(&self) -> TabPoint {
+ self.to_tab_point(self.fold_snapshot.max_point())
}
- pub fn clip_point(&self, point: CharPoint, bias: Bias) -> CharPoint {
- self.to_char_point(
+ pub fn clip_point(&self, point: TabPoint, bias: Bias) -> TabPoint {
+ self.to_tab_point(
self.fold_snapshot
.clip_point(self.to_fold_point(point, bias).0, bias),
)
}
- pub fn to_char_point(&self, input: FoldPoint) -> CharPoint {
+ pub fn to_tab_point(&self, input: FoldPoint) -> TabPoint {
let chars = self.fold_snapshot.chars_at(FoldPoint::new(input.row(), 0));
let expanded = self.expand_tabs(chars, input.column());
- CharPoint::new(input.row(), expanded)
+ TabPoint::new(input.row(), expanded)
}
- pub fn to_fold_point(&self, output: CharPoint, bias: Bias) -> (FoldPoint, u32, u32) {
+ pub fn to_fold_point(&self, output: TabPoint, bias: Bias) -> (FoldPoint, u32, u32) {
let chars = self.fold_snapshot.chars_at(FoldPoint::new(output.row(), 0));
let expanded = output.column();
let (collapsed, expanded_char_column, to_next_stop) =
@@ -317,13 +316,13 @@ impl CharSnapshot {
)
}
- pub fn make_char_point(&self, point: Point, bias: Bias) -> CharPoint {
+ pub fn make_tab_point(&self, point: Point, bias: Bias) -> TabPoint {
let inlay_point = self.fold_snapshot.inlay_snapshot.to_inlay_point(point);
let fold_point = self.fold_snapshot.to_fold_point(inlay_point, bias);
- self.to_char_point(fold_point)
+ self.to_tab_point(fold_point)
}
- pub fn to_point(&self, point: CharPoint, bias: Bias) -> Point {
+ pub fn to_point(&self, point: TabPoint, bias: Bias) -> Point {
let fold_point = self.to_fold_point(point, bias).0;
let inlay_point = fold_point.to_inlay_point(&self.fold_snapshot);
self.fold_snapshot
@@ -346,9 +345,6 @@ impl CharSnapshot {
let tab_len = tab_size - expanded_chars % tab_size;
expanded_bytes += tab_len;
expanded_chars += tab_len;
- } else if let Some(replacement) = replacement(c) {
- expanded_chars += replacement.chars().count() as u32;
- expanded_bytes += replacement.len() as u32;
} else {
expanded_bytes += c.len_utf8() as u32;
expanded_chars += 1;
@@ -388,9 +384,6 @@ impl CharSnapshot {
Bias::Right => (collapsed_bytes + 1, expanded_chars, 0),
};
}
- } else if let Some(replacement) = replacement(c) {
- expanded_chars += replacement.chars().count() as u32;
- expanded_bytes += replacement.len() as u32;
} else {
expanded_chars += 1;
expanded_bytes += c.len_utf8() as u32;
@@ -412,9 +405,9 @@ impl CharSnapshot {
}
#[derive(Copy, Clone, Debug, Default, Eq, Ord, PartialOrd, PartialEq)]
-pub struct CharPoint(pub Point);
+pub struct TabPoint(pub Point);
-impl CharPoint {
+impl TabPoint {
pub fn new(row: u32, column: u32) -> Self {
Self(Point::new(row, column))
}
@@ -432,13 +425,13 @@ impl CharPoint {
}
}
-impl From<Point> for CharPoint {
+impl From<Point> for TabPoint {
fn from(point: Point) -> Self {
Self(point)
}
}
-pub type TabEdit = text::Edit<CharPoint>;
+pub type TabEdit = text::Edit<TabPoint>;
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct TextSummary {
@@ -493,7 +486,7 @@ impl<'a> std::ops::AddAssign<&'a Self> for TextSummary {
const SPACES: &str = " ";
pub struct TabChunks<'a> {
- snapshot: &'a CharSnapshot,
+ snapshot: &'a TabSnapshot,
fold_chunks: FoldChunks<'a>,
chunk: Chunk<'a>,
column: u32,
@@ -506,7 +499,7 @@ pub struct TabChunks<'a> {
}
impl<'a> TabChunks<'a> {
- pub(crate) fn seek(&mut self, range: Range<CharPoint>) {
+ pub(crate) fn seek(&mut self, range: Range<TabPoint>) {
let (input_start, expanded_char_column, to_next_stop) =
self.snapshot.to_fold_point(range.start, Bias::Left);
let input_column = input_start.column();
@@ -591,37 +584,6 @@ impl<'a> Iterator for TabChunks<'a> {
self.input_column = 0;
self.output_position += Point::new(1, 0);
}
- _ if is_invisible(c) => {
- if ix > 0 {
- let (prefix, suffix) = self.chunk.text.split_at(ix);
- self.chunk.text = suffix;
- return Some(Chunk {
- text: prefix,
- is_invisible: false,
- ..self.chunk.clone()
- });
- }
- let c_len = c.len_utf8();
- let replacement = replacement(c).unwrap_or(&self.chunk.text[..c_len]);
- if self.chunk.text.len() >= c_len {
- self.chunk.text = &self.chunk.text[c_len..];
- } else {
- self.chunk.text = "";
- }
- let len = replacement.chars().count() as u32;
- let next_output_position = cmp::min(
- self.output_position + Point::new(0, len),
- self.max_output_position,
- );
- self.column += len;
- self.input_column += 1;
- self.output_position = next_output_position;
- return Some(Chunk {
- text: replacement,
- is_invisible: true,
- ..self.chunk.clone()
- });
- }
_ => {
self.column += 1;
if !self.inside_leading_tab {
@@ -651,11 +613,11 @@ mod tests {
let buffer_snapshot = buffer.read(cx).snapshot(cx);
let (_, inlay_snapshot) = InlayMap::new(buffer_snapshot.clone());
let (_, fold_snapshot) = FoldMap::new(inlay_snapshot);
- let (_, char_snapshot) = CharMap::new(fold_snapshot, 4.try_into().unwrap());
+ let (_, tab_snapshot) = TabMap::new(fold_snapshot, 4.try_into().unwrap());
- assert_eq!(char_snapshot.expand_tabs("\t".chars(), 0), 0);
- assert_eq!(char_snapshot.expand_tabs("\t".chars(), 1), 4);
- assert_eq!(char_snapshot.expand_tabs("\ta".chars(), 2), 5);
+ assert_eq!(tab_snapshot.expand_tabs("\t".chars(), 0), 0);
+ assert_eq!(tab_snapshot.expand_tabs("\t".chars(), 1), 4);
+ assert_eq!(tab_snapshot.expand_tabs("\ta".chars(), 2), 5);
}
#[gpui::test]
@@ -668,16 +630,16 @@ mod tests {
let buffer_snapshot = buffer.read(cx).snapshot(cx);
let (_, inlay_snapshot) = InlayMap::new(buffer_snapshot.clone());
let (_, fold_snapshot) = FoldMap::new(inlay_snapshot);
- let (_, mut char_snapshot) = CharMap::new(fold_snapshot, 4.try_into().unwrap());
+ let (_, mut tab_snapshot) = TabMap::new(fold_snapshot, 4.try_into().unwrap());
- char_snapshot.max_expansion_column = max_expansion_column;
- assert_eq!(char_snapshot.text(), output);
+ tab_snapshot.max_expansion_column = max_expansion_column;
+ assert_eq!(tab_snapshot.text(), output);
for (ix, c) in input.char_indices() {
assert_eq!(
- char_snapshot
+ tab_snapshot
.chunks(
- CharPoint::new(0, ix as u32)..char_snapshot.max_point(),
+ TabPoint::new(0, ix as u32)..tab_snapshot.max_point(),
false,
Highlights::default(),
)
@@ -691,13 +653,13 @@ mod tests {
let input_point = Point::new(0, ix as u32);
let output_point = Point::new(0, output.find(c).unwrap() as u32);
assert_eq!(
- char_snapshot.to_char_point(FoldPoint(input_point)),
- CharPoint(output_point),
- "to_char_point({input_point:?})"
+ tab_snapshot.to_tab_point(FoldPoint(input_point)),
+ TabPoint(output_point),
+ "to_tab_point({input_point:?})"
);
assert_eq!(
- char_snapshot
- .to_fold_point(CharPoint(output_point), Bias::Left)
+ tab_snapshot
+ .to_fold_point(TabPoint(output_point), Bias::Left)
.0,
FoldPoint(input_point),
"to_fold_point({output_point:?})"
@@ -715,10 +677,10 @@ mod tests {
let buffer_snapshot = buffer.read(cx).snapshot(cx);
let (_, inlay_snapshot) = InlayMap::new(buffer_snapshot.clone());
let (_, fold_snapshot) = FoldMap::new(inlay_snapshot);
- let (_, mut char_snapshot) = CharMap::new(fold_snapshot, 4.try_into().unwrap());
+ let (_, mut tab_snapshot) = TabMap::new(fold_snapshot, 4.try_into().unwrap());
- char_snapshot.max_expansion_column = max_expansion_column;
- assert_eq!(char_snapshot.text(), input);
+ tab_snapshot.max_expansion_column = max_expansion_column;
+ assert_eq!(tab_snapshot.text(), input);
}
#[gpui::test]
@@ -729,10 +691,10 @@ mod tests {
let buffer_snapshot = buffer.read(cx).snapshot(cx);
let (_, inlay_snapshot) = InlayMap::new(buffer_snapshot.clone());
let (_, fold_snapshot) = FoldMap::new(inlay_snapshot);
- let (_, char_snapshot) = CharMap::new(fold_snapshot, 4.try_into().unwrap());
+ let (_, tab_snapshot) = TabMap::new(fold_snapshot, 4.try_into().unwrap());
assert_eq!(
- chunks(&char_snapshot, CharPoint::zero()),
+ chunks(&tab_snapshot, TabPoint::zero()),
vec![
(" ".to_string(), true),
(" ".to_string(), false),
@@ -741,7 +703,7 @@ mod tests {
]
);
assert_eq!(
- chunks(&char_snapshot, CharPoint::new(0, 2)),
+ chunks(&tab_snapshot, TabPoint::new(0, 2)),
vec![
(" ".to_string(), true),
(" ".to_string(), false),
@@ -750,7 +712,7 @@ mod tests {
]
);
- fn chunks(snapshot: &CharSnapshot, start: CharPoint) -> Vec<(String, bool)> {
+ fn chunks(snapshot: &TabSnapshot, start: TabPoint) -> Vec<(String, bool)> {
let mut chunks = Vec::new();
let mut was_tab = false;
let mut text = String::new();
@@ -796,12 +758,12 @@ mod tests {
let (inlay_snapshot, _) = inlay_map.randomly_mutate(&mut 0, &mut rng);
log::info!("InlayMap text: {:?}", inlay_snapshot.text());
- let (mut char_map, _) = CharMap::new(fold_snapshot.clone(), tab_size);
- let tabs_snapshot = char_map.set_max_expansion_column(32);
+ let (mut tab_map, _) = TabMap::new(fold_snapshot.clone(), tab_size);
+ let tabs_snapshot = tab_map.set_max_expansion_column(32);
let text = text::Rope::from(tabs_snapshot.text().as_str());
log::info!(
- "CharMap text (tab size: {}): {:?}",
+ "TabMap text (tab size: {}): {:?}",
tab_size,
tabs_snapshot.text(),
);
@@ -809,11 +771,11 @@ mod tests {
for _ in 0..5 {
let end_row = rng.gen_range(0..=text.max_point().row);
let end_column = rng.gen_range(0..=text.line_len(end_row));
- let mut end = CharPoint(text.clip_point(Point::new(end_row, end_column), Bias::Right));
+ let mut end = TabPoint(text.clip_point(Point::new(end_row, end_column), Bias::Right));
let start_row = rng.gen_range(0..=text.max_point().row);
let start_column = rng.gen_range(0..=text.line_len(start_row));
let mut start =
- CharPoint(text.clip_point(Point::new(start_row, start_column), Bias::Left));
+ TabPoint(text.clip_point(Point::new(start_row, start_column), Bias::Left));
if start > end {
mem::swap(&mut start, &mut end);
}
@@ -1,6 +1,6 @@
use super::{
- char_map::{self, CharPoint, CharSnapshot, TabEdit},
fold_map::FoldBufferRows,
+ tab_map::{self, TabEdit, TabPoint, TabSnapshot},
Highlights,
};
use gpui::{AppContext, Context, Font, LineWrapper, Model, ModelContext, Pixels, Task};
@@ -12,7 +12,7 @@ use std::{cmp, collections::VecDeque, mem, ops::Range, time::Duration};
use sum_tree::{Bias, Cursor, SumTree};
use text::Patch;
-pub use super::char_map::TextSummary;
+pub use super::tab_map::TextSummary;
pub type WrapEdit = text::Edit<u32>;
/// Handles soft wrapping of text.
@@ -20,7 +20,7 @@ pub type WrapEdit = text::Edit<u32>;
/// See the [`display_map` module documentation](crate::display_map) for more information.
pub struct WrapMap {
snapshot: WrapSnapshot,
- pending_edits: VecDeque<(CharSnapshot, Vec<TabEdit>)>,
+ pending_edits: VecDeque<(TabSnapshot, Vec<TabEdit>)>,
interpolated_edits: Patch<u32>,
edits_since_sync: Patch<u32>,
wrap_width: Option<Pixels>,
@@ -30,7 +30,7 @@ pub struct WrapMap {
#[derive(Clone)]
pub struct WrapSnapshot {
- char_snapshot: CharSnapshot,
+ tab_snapshot: TabSnapshot,
transforms: SumTree<Transform>,
interpolated: bool,
}
@@ -51,11 +51,11 @@ struct TransformSummary {
pub struct WrapPoint(pub Point);
pub struct WrapChunks<'a> {
- input_chunks: char_map::TabChunks<'a>,
+ input_chunks: tab_map::TabChunks<'a>,
input_chunk: Chunk<'a>,
output_position: WrapPoint,
max_output_row: u32,
- transforms: Cursor<'a, Transform, (WrapPoint, CharPoint)>,
+ transforms: Cursor<'a, Transform, (WrapPoint, TabPoint)>,
snapshot: &'a WrapSnapshot,
}
@@ -66,7 +66,7 @@ pub struct WrapBufferRows<'a> {
output_row: u32,
soft_wrapped: bool,
max_output_row: u32,
- transforms: Cursor<'a, Transform, (WrapPoint, CharPoint)>,
+ transforms: Cursor<'a, Transform, (WrapPoint, TabPoint)>,
}
impl<'a> WrapBufferRows<'a> {
@@ -86,7 +86,7 @@ impl<'a> WrapBufferRows<'a> {
impl WrapMap {
pub fn new(
- char_snapshot: CharSnapshot,
+ tab_snapshot: TabSnapshot,
font: Font,
font_size: Pixels,
wrap_width: Option<Pixels>,
@@ -99,7 +99,7 @@ impl WrapMap {
pending_edits: Default::default(),
interpolated_edits: Default::default(),
edits_since_sync: Default::default(),
- snapshot: WrapSnapshot::new(char_snapshot),
+ snapshot: WrapSnapshot::new(tab_snapshot),
background_task: None,
};
this.set_wrap_width(wrap_width, cx);
@@ -117,17 +117,17 @@ impl WrapMap {
pub fn sync(
&mut self,
- char_snapshot: CharSnapshot,
+ tab_snapshot: TabSnapshot,
edits: Vec<TabEdit>,
cx: &mut ModelContext<Self>,
) -> (WrapSnapshot, Patch<u32>) {
if self.wrap_width.is_some() {
- self.pending_edits.push_back((char_snapshot, edits));
+ self.pending_edits.push_back((tab_snapshot, edits));
self.flush_edits(cx);
} else {
self.edits_since_sync = self
.edits_since_sync
- .compose(self.snapshot.interpolate(char_snapshot, &edits));
+ .compose(self.snapshot.interpolate(tab_snapshot, &edits));
self.snapshot.interpolated = false;
}
@@ -177,11 +177,11 @@ impl WrapMap {
let (font, font_size) = self.font_with_size.clone();
let task = cx.background_executor().spawn(async move {
let mut line_wrapper = text_system.line_wrapper(font, font_size);
- let char_snapshot = new_snapshot.char_snapshot.clone();
- let range = CharPoint::zero()..char_snapshot.max_point();
+ let tab_snapshot = new_snapshot.tab_snapshot.clone();
+ let range = TabPoint::zero()..tab_snapshot.max_point();
let edits = new_snapshot
.update(
- char_snapshot,
+ tab_snapshot,
&[TabEdit {
old: range.clone(),
new: range.clone(),
@@ -221,7 +221,7 @@ impl WrapMap {
} else {
let old_rows = self.snapshot.transforms.summary().output.lines.row + 1;
self.snapshot.transforms = SumTree::default();
- let summary = self.snapshot.char_snapshot.text_summary();
+ let summary = self.snapshot.tab_snapshot.text_summary();
if !summary.lines.is_zero() {
self.snapshot
.transforms
@@ -239,8 +239,8 @@ impl WrapMap {
fn flush_edits(&mut self, cx: &mut ModelContext<Self>) {
if !self.snapshot.interpolated {
let mut to_remove_len = 0;
- for (char_snapshot, _) in &self.pending_edits {
- if char_snapshot.version <= self.snapshot.char_snapshot.version {
+ for (tab_snapshot, _) in &self.pending_edits {
+ if tab_snapshot.version <= self.snapshot.tab_snapshot.version {
to_remove_len += 1;
} else {
break;
@@ -262,9 +262,9 @@ impl WrapMap {
let update_task = cx.background_executor().spawn(async move {
let mut edits = Patch::default();
let mut line_wrapper = text_system.line_wrapper(font, font_size);
- for (char_snapshot, tab_edits) in pending_edits {
+ for (tab_snapshot, tab_edits) in pending_edits {
let wrap_edits = snapshot
- .update(char_snapshot, &tab_edits, wrap_width, &mut line_wrapper)
+ .update(tab_snapshot, &tab_edits, wrap_width, &mut line_wrapper)
.await;
edits = edits.compose(&wrap_edits);
}
@@ -301,11 +301,11 @@ impl WrapMap {
let was_interpolated = self.snapshot.interpolated;
let mut to_remove_len = 0;
- for (char_snapshot, edits) in &self.pending_edits {
- if char_snapshot.version <= self.snapshot.char_snapshot.version {
+ for (tab_snapshot, edits) in &self.pending_edits {
+ if tab_snapshot.version <= self.snapshot.tab_snapshot.version {
to_remove_len += 1;
} else {
- let interpolated_edits = self.snapshot.interpolate(char_snapshot.clone(), edits);
+ let interpolated_edits = self.snapshot.interpolate(tab_snapshot.clone(), edits);
self.edits_since_sync = self.edits_since_sync.compose(&interpolated_edits);
self.interpolated_edits = self.interpolated_edits.compose(&interpolated_edits);
}
@@ -318,49 +318,45 @@ impl WrapMap {
}
impl WrapSnapshot {
- fn new(char_snapshot: CharSnapshot) -> Self {
+ fn new(tab_snapshot: TabSnapshot) -> Self {
let mut transforms = SumTree::default();
- let extent = char_snapshot.text_summary();
+ let extent = tab_snapshot.text_summary();
if !extent.lines.is_zero() {
transforms.push(Transform::isomorphic(extent), &());
}
Self {
transforms,
- char_snapshot,
+ tab_snapshot,
interpolated: true,
}
}
pub fn buffer_snapshot(&self) -> &MultiBufferSnapshot {
- self.char_snapshot.buffer_snapshot()
+ self.tab_snapshot.buffer_snapshot()
}
- fn interpolate(
- &mut self,
- new_char_snapshot: CharSnapshot,
- tab_edits: &[TabEdit],
- ) -> Patch<u32> {
+ fn interpolate(&mut self, new_tab_snapshot: TabSnapshot, tab_edits: &[TabEdit]) -> Patch<u32> {
let mut new_transforms;
if tab_edits.is_empty() {
new_transforms = self.transforms.clone();
} else {
- let mut old_cursor = self.transforms.cursor::<CharPoint>(&());
+ let mut old_cursor = self.transforms.cursor::<TabPoint>(&());
let mut tab_edits_iter = tab_edits.iter().peekable();
new_transforms =
old_cursor.slice(&tab_edits_iter.peek().unwrap().old.start, Bias::Right, &());
while let Some(edit) = tab_edits_iter.next() {
- if edit.new.start > CharPoint::from(new_transforms.summary().input.lines) {
- let summary = new_char_snapshot.text_summary_for_range(
- CharPoint::from(new_transforms.summary().input.lines)..edit.new.start,
+ if edit.new.start > TabPoint::from(new_transforms.summary().input.lines) {
+ let summary = new_tab_snapshot.text_summary_for_range(
+ TabPoint::from(new_transforms.summary().input.lines)..edit.new.start,
);
new_transforms.push_or_extend(Transform::isomorphic(summary));
}
if !edit.new.is_empty() {
new_transforms.push_or_extend(Transform::isomorphic(
- new_char_snapshot.text_summary_for_range(edit.new.clone()),
+ new_tab_snapshot.text_summary_for_range(edit.new.clone()),
));
}
@@ -369,7 +365,7 @@ impl WrapSnapshot {
if next_edit.old.start > old_cursor.end(&()) {
if old_cursor.end(&()) > edit.old.end {
let summary = self
- .char_snapshot
+ .tab_snapshot
.text_summary_for_range(edit.old.end..old_cursor.end(&()));
new_transforms.push_or_extend(Transform::isomorphic(summary));
}
@@ -383,7 +379,7 @@ impl WrapSnapshot {
} else {
if old_cursor.end(&()) > edit.old.end {
let summary = self
- .char_snapshot
+ .tab_snapshot
.text_summary_for_range(edit.old.end..old_cursor.end(&()));
new_transforms.push_or_extend(Transform::isomorphic(summary));
}
@@ -396,7 +392,7 @@ impl WrapSnapshot {
let old_snapshot = mem::replace(
self,
WrapSnapshot {
- char_snapshot: new_char_snapshot,
+ tab_snapshot: new_tab_snapshot,
transforms: new_transforms,
interpolated: true,
},
@@ -407,7 +403,7 @@ impl WrapSnapshot {
async fn update(
&mut self,
- new_char_snapshot: CharSnapshot,
+ new_tab_snapshot: TabSnapshot,
tab_edits: &[TabEdit],
wrap_width: Pixels,
line_wrapper: &mut LineWrapper,
@@ -444,27 +440,27 @@ impl WrapSnapshot {
new_transforms = self.transforms.clone();
} else {
let mut row_edits = row_edits.into_iter().peekable();
- let mut old_cursor = self.transforms.cursor::<CharPoint>(&());
+ let mut old_cursor = self.transforms.cursor::<TabPoint>(&());
new_transforms = old_cursor.slice(
- &CharPoint::new(row_edits.peek().unwrap().old_rows.start, 0),
+ &TabPoint::new(row_edits.peek().unwrap().old_rows.start, 0),
Bias::Right,
&(),
);
while let Some(edit) = row_edits.next() {
if edit.new_rows.start > new_transforms.summary().input.lines.row {
- let summary = new_char_snapshot.text_summary_for_range(
- CharPoint(new_transforms.summary().input.lines)
- ..CharPoint::new(edit.new_rows.start, 0),
+ let summary = new_tab_snapshot.text_summary_for_range(
+ TabPoint(new_transforms.summary().input.lines)
+ ..TabPoint::new(edit.new_rows.start, 0),
);
new_transforms.push_or_extend(Transform::isomorphic(summary));
}
let mut line = String::new();
let mut remaining = None;
- let mut chunks = new_char_snapshot.chunks(
- CharPoint::new(edit.new_rows.start, 0)..new_char_snapshot.max_point(),
+ let mut chunks = new_tab_snapshot.chunks(
+ TabPoint::new(edit.new_rows.start, 0)..new_tab_snapshot.max_point(),
false,
Highlights::default(),
);
@@ -511,19 +507,19 @@ impl WrapSnapshot {
}
new_transforms.extend(edit_transforms, &());
- old_cursor.seek_forward(&CharPoint::new(edit.old_rows.end, 0), Bias::Right, &());
+ old_cursor.seek_forward(&TabPoint::new(edit.old_rows.end, 0), Bias::Right, &());
if let Some(next_edit) = row_edits.peek() {
if next_edit.old_rows.start > old_cursor.end(&()).row() {
- if old_cursor.end(&()) > CharPoint::new(edit.old_rows.end, 0) {
- let summary = self.char_snapshot.text_summary_for_range(
- CharPoint::new(edit.old_rows.end, 0)..old_cursor.end(&()),
+ if old_cursor.end(&()) > TabPoint::new(edit.old_rows.end, 0) {
+ let summary = self.tab_snapshot.text_summary_for_range(
+ TabPoint::new(edit.old_rows.end, 0)..old_cursor.end(&()),
);
new_transforms.push_or_extend(Transform::isomorphic(summary));
}
old_cursor.next(&());
new_transforms.append(
old_cursor.slice(
- &CharPoint::new(next_edit.old_rows.start, 0),
+ &TabPoint::new(next_edit.old_rows.start, 0),
Bias::Right,
&(),
),
@@ -531,9 +527,9 @@ impl WrapSnapshot {
);
}
} else {
- if old_cursor.end(&()) > CharPoint::new(edit.old_rows.end, 0) {
- let summary = self.char_snapshot.text_summary_for_range(
- CharPoint::new(edit.old_rows.end, 0)..old_cursor.end(&()),
+ if old_cursor.end(&()) > TabPoint::new(edit.old_rows.end, 0) {
+ let summary = self.tab_snapshot.text_summary_for_range(
+ TabPoint::new(edit.old_rows.end, 0)..old_cursor.end(&()),
);
new_transforms.push_or_extend(Transform::isomorphic(summary));
}
@@ -546,7 +542,7 @@ impl WrapSnapshot {
let old_snapshot = mem::replace(
self,
WrapSnapshot {
- char_snapshot: new_char_snapshot,
+ tab_snapshot: new_tab_snapshot,
transforms: new_transforms,
interpolated: false,
},
@@ -599,17 +595,17 @@ impl WrapSnapshot {
) -> 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, CharPoint)>(&());
+ let mut transforms = self.transforms.cursor::<(WrapPoint, TabPoint)>(&());
transforms.seek(&output_start, Bias::Right, &());
- let mut input_start = CharPoint(transforms.start().1 .0);
+ let mut input_start = TabPoint(transforms.start().1 .0);
if transforms.item().map_or(false, |t| t.is_isomorphic()) {
input_start.0 += output_start.0 - transforms.start().0 .0;
}
let input_end = self
- .to_char_point(output_end)
- .min(self.char_snapshot.max_point());
+ .to_tab_point(output_end)
+ .min(self.tab_snapshot.max_point());
WrapChunks {
- input_chunks: self.char_snapshot.chunks(
+ input_chunks: self.tab_snapshot.chunks(
input_start..input_end,
language_aware,
highlights,
@@ -627,7 +623,7 @@ impl WrapSnapshot {
}
pub fn line_len(&self, row: u32) -> u32 {
- let mut cursor = self.transforms.cursor::<(WrapPoint, CharPoint)>(&());
+ let mut cursor = self.transforms.cursor::<(WrapPoint, TabPoint)>(&());
cursor.seek(&WrapPoint::new(row + 1, 0), Bias::Left, &());
if cursor
.item()
@@ -635,7 +631,7 @@ impl WrapSnapshot {
{
let overshoot = row - cursor.start().0.row();
let tab_row = cursor.start().1.row() + overshoot;
- let tab_line_len = self.char_snapshot.line_len(tab_row);
+ let tab_line_len = self.tab_snapshot.line_len(tab_row);
if overshoot == 0 {
cursor.start().0.column() + (tab_line_len - cursor.start().1.column())
} else {
@@ -652,17 +648,15 @@ impl WrapSnapshot {
let start = WrapPoint::new(rows.start, 0);
let end = WrapPoint::new(rows.end, 0);
- let mut cursor = self.transforms.cursor::<(WrapPoint, CharPoint)>(&());
+ let mut cursor = self.transforms.cursor::<(WrapPoint, TabPoint)>(&());
cursor.seek(&start, Bias::Right, &());
if let Some(transform) = cursor.item() {
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() {
- let char_start = CharPoint(cursor.start().1 .0 + start_in_transform);
- let char_end = CharPoint(cursor.start().1 .0 + end_in_transform);
- summary += &self
- .char_snapshot
- .text_summary_for_range(char_start..char_end);
+ let tab_start = TabPoint(cursor.start().1 .0 + start_in_transform);
+ let tab_end = TabPoint(cursor.start().1 .0 + end_in_transform);
+ summary += &self.tab_snapshot.text_summary_for_range(tab_start..tab_end);
} else {
debug_assert_eq!(start_in_transform.row, end_in_transform.row);
let indent_len = end_in_transform.column - start_in_transform.column;
@@ -687,9 +681,9 @@ impl WrapSnapshot {
let end_in_transform = end.0 - cursor.start().0 .0;
if transform.is_isomorphic() {
let char_start = cursor.start().1;
- let char_end = CharPoint(char_start.0 + end_in_transform);
+ let char_end = TabPoint(char_start.0 + end_in_transform);
summary += &self
- .char_snapshot
+ .tab_snapshot
.text_summary_for_range(char_start..char_end);
} else {
debug_assert_eq!(end_in_transform, Point::new(1, 0));
@@ -724,14 +718,14 @@ impl WrapSnapshot {
}
pub fn buffer_rows(&self, start_row: u32) -> WrapBufferRows {
- let mut transforms = self.transforms.cursor::<(WrapPoint, CharPoint)>(&());
+ let mut transforms = self.transforms.cursor::<(WrapPoint, TabPoint)>(&());
transforms.seek(&WrapPoint::new(start_row, 0), Bias::Left, &());
let mut input_row = transforms.start().1.row();
if transforms.item().map_or(false, |t| t.is_isomorphic()) {
input_row += start_row - transforms.start().0.row();
}
let soft_wrapped = transforms.item().map_or(false, |t| !t.is_isomorphic());
- let mut input_buffer_rows = self.char_snapshot.buffer_rows(input_row);
+ let mut input_buffer_rows = self.tab_snapshot.buffer_rows(input_row);
let input_buffer_row = input_buffer_rows.next().unwrap();
WrapBufferRows {
transforms,
@@ -743,26 +737,26 @@ impl WrapSnapshot {
}
}
- pub fn to_char_point(&self, point: WrapPoint) -> CharPoint {
- let mut cursor = self.transforms.cursor::<(WrapPoint, CharPoint)>(&());
+ pub fn to_tab_point(&self, point: WrapPoint) -> TabPoint {
+ let mut cursor = self.transforms.cursor::<(WrapPoint, TabPoint)>(&());
cursor.seek(&point, Bias::Right, &());
- let mut char_point = cursor.start().1 .0;
+ let mut tab_point = cursor.start().1 .0;
if cursor.item().map_or(false, |t| t.is_isomorphic()) {
- char_point += point.0 - cursor.start().0 .0;
+ tab_point += point.0 - cursor.start().0 .0;
}
- CharPoint(char_point)
+ TabPoint(tab_point)
}
pub fn to_point(&self, point: WrapPoint, bias: Bias) -> Point {
- self.char_snapshot.to_point(self.to_char_point(point), bias)
+ self.tab_snapshot.to_point(self.to_tab_point(point), bias)
}
pub fn make_wrap_point(&self, point: Point, bias: Bias) -> WrapPoint {
- self.char_point_to_wrap_point(self.char_snapshot.make_char_point(point, bias))
+ self.tab_point_to_wrap_point(self.tab_snapshot.make_tab_point(point, bias))
}
- pub fn char_point_to_wrap_point(&self, point: CharPoint) -> WrapPoint {
- let mut cursor = self.transforms.cursor::<(CharPoint, WrapPoint)>(&());
+ pub fn tab_point_to_wrap_point(&self, point: TabPoint) -> WrapPoint {
+ let mut cursor = self.transforms.cursor::<(TabPoint, WrapPoint)>(&());
cursor.seek(&point, Bias::Right, &());
WrapPoint(cursor.start().1 .0 + (point.0 - cursor.start().0 .0))
}
@@ -777,10 +771,7 @@ impl WrapSnapshot {
}
}
- self.char_point_to_wrap_point(
- self.char_snapshot
- .clip_point(self.to_char_point(point), bias),
- )
+ self.tab_point_to_wrap_point(self.tab_snapshot.clip_point(self.to_tab_point(point), bias))
}
pub fn prev_row_boundary(&self, mut point: WrapPoint) -> u32 {
@@ -790,7 +781,7 @@ impl WrapSnapshot {
*point.column_mut() = 0;
- let mut cursor = self.transforms.cursor::<(WrapPoint, CharPoint)>(&());
+ let mut cursor = self.transforms.cursor::<(WrapPoint, TabPoint)>(&());
cursor.seek(&point, Bias::Right, &());
if cursor.item().is_none() {
cursor.prev(&());
@@ -810,7 +801,7 @@ impl WrapSnapshot {
pub fn next_row_boundary(&self, mut point: WrapPoint) -> Option<u32> {
point.0 += Point::new(1, 0);
- let mut cursor = self.transforms.cursor::<(WrapPoint, CharPoint)>(&());
+ let mut cursor = self.transforms.cursor::<(WrapPoint, TabPoint)>(&());
cursor.seek(&point, Bias::Right, &());
while let Some(transform) = cursor.item() {
if transform.is_isomorphic() && cursor.start().1.column() == 0 {
@@ -842,8 +833,8 @@ impl WrapSnapshot {
#[cfg(test)]
{
assert_eq!(
- CharPoint::from(self.transforms.summary().input.lines),
- self.char_snapshot.max_point()
+ TabPoint::from(self.transforms.summary().input.lines),
+ self.tab_snapshot.max_point()
);
{
@@ -856,18 +847,18 @@ impl WrapSnapshot {
}
let text = language::Rope::from(self.text().as_str());
- let mut input_buffer_rows = self.char_snapshot.buffer_rows(0);
+ let mut input_buffer_rows = self.tab_snapshot.buffer_rows(0);
let mut expected_buffer_rows = Vec::new();
let mut prev_tab_row = 0;
for display_row in 0..=self.max_point().row() {
- let char_point = self.to_char_point(WrapPoint::new(display_row, 0));
- if char_point.row() == prev_tab_row && display_row != 0 {
+ let tab_point = self.to_tab_point(WrapPoint::new(display_row, 0));
+ if tab_point.row() == prev_tab_row && display_row != 0 {
expected_buffer_rows.push(None);
} else {
expected_buffer_rows.push(input_buffer_rows.next().unwrap());
}
- prev_tab_row = char_point.row();
+ prev_tab_row = tab_point.row();
assert_eq!(self.line_len(display_row), text.line_len(display_row));
}
@@ -889,14 +880,14 @@ impl<'a> WrapChunks<'a> {
let output_start = WrapPoint::new(rows.start, 0);
let output_end = WrapPoint::new(rows.end, 0);
self.transforms.seek(&output_start, Bias::Right, &());
- let mut input_start = CharPoint(self.transforms.start().1 .0);
+ let mut input_start = TabPoint(self.transforms.start().1 .0);
if self.transforms.item().map_or(false, |t| t.is_isomorphic()) {
input_start.0 += output_start.0 - self.transforms.start().0 .0;
}
let input_end = self
.snapshot
- .to_char_point(output_end)
- .min(self.snapshot.char_snapshot.max_point());
+ .to_tab_point(output_end)
+ .min(self.snapshot.tab_snapshot.max_point());
self.input_chunks.seek(input_start..input_end);
self.input_chunk = Chunk::default();
self.output_position = output_start;
@@ -951,11 +942,13 @@ impl<'a> Iterator for WrapChunks<'a> {
} else {
*self.output_position.column_mut() += char_len as u32;
}
+
if self.output_position >= transform_end {
self.transforms.next(&());
break;
}
}
+
let (prefix, suffix) = self.input_chunk.text.split_at(input_len);
self.input_chunk.text = suffix;
Some(Chunk {
@@ -1110,7 +1103,7 @@ impl sum_tree::Summary for TransformSummary {
}
}
-impl<'a> sum_tree::Dimension<'a, TransformSummary> for CharPoint {
+impl<'a> sum_tree::Dimension<'a, TransformSummary> for TabPoint {
fn zero(_cx: &()) -> Self {
Default::default()
}
@@ -1120,7 +1113,7 @@ impl<'a> sum_tree::Dimension<'a, TransformSummary> for CharPoint {
}
}
-impl<'a> sum_tree::SeekTarget<'a, TransformSummary, TransformSummary> for CharPoint {
+impl<'a> sum_tree::SeekTarget<'a, TransformSummary, TransformSummary> for TabPoint {
fn cmp(&self, cursor_location: &TransformSummary, _: &()) -> std::cmp::Ordering {
Ord::cmp(&self.0, &cursor_location.input.lines)
}
@@ -1168,7 +1161,7 @@ fn consolidate_wrap_edits(edits: Vec<WrapEdit>) -> Vec<WrapEdit> {
mod tests {
use super::*;
use crate::{
- display_map::{char_map::CharMap, fold_map::FoldMap, inlay_map::InlayMap},
+ display_map::{fold_map::FoldMap, inlay_map::InlayMap, tab_map::TabMap},
MultiBuffer,
};
use gpui::{font, px, test::observe};
@@ -1220,9 +1213,9 @@ mod tests {
log::info!("InlayMap text: {:?}", inlay_snapshot.text());
let (mut fold_map, fold_snapshot) = FoldMap::new(inlay_snapshot.clone());
log::info!("FoldMap text: {:?}", fold_snapshot.text());
- let (mut char_map, _) = CharMap::new(fold_snapshot.clone(), tab_size);
- let tabs_snapshot = char_map.set_max_expansion_column(32);
- log::info!("CharMap text: {:?}", tabs_snapshot.text());
+ let (mut tab_map, _) = TabMap::new(fold_snapshot.clone(), tab_size);
+ let tabs_snapshot = tab_map.set_max_expansion_column(32);
+ log::info!("TabMap text: {:?}", tabs_snapshot.text());
let mut line_wrapper = text_system.line_wrapper(font.clone(), font_size);
let unwrapped_text = tabs_snapshot.text();
@@ -1268,7 +1261,7 @@ mod tests {
20..=39 => {
for (fold_snapshot, fold_edits) in fold_map.randomly_mutate(&mut rng) {
let (tabs_snapshot, tab_edits) =
- char_map.sync(fold_snapshot, fold_edits, tab_size);
+ tab_map.sync(fold_snapshot, fold_edits, tab_size);
let (mut snapshot, wrap_edits) =
wrap_map.update(cx, |map, cx| map.sync(tabs_snapshot, tab_edits, cx));
snapshot.check_invariants();
@@ -1281,7 +1274,7 @@ mod tests {
inlay_map.randomly_mutate(&mut next_inlay_id, &mut rng);
let (fold_snapshot, fold_edits) = fold_map.read(inlay_snapshot, inlay_edits);
let (tabs_snapshot, tab_edits) =
- char_map.sync(fold_snapshot, fold_edits, tab_size);
+ tab_map.sync(fold_snapshot, fold_edits, tab_size);
let (mut snapshot, wrap_edits) =
wrap_map.update(cx, |map, cx| map.sync(tabs_snapshot, tab_edits, cx));
snapshot.check_invariants();
@@ -1305,8 +1298,8 @@ mod tests {
log::info!("InlayMap text: {:?}", inlay_snapshot.text());
let (fold_snapshot, fold_edits) = fold_map.read(inlay_snapshot, inlay_edits);
log::info!("FoldMap text: {:?}", fold_snapshot.text());
- let (tabs_snapshot, tab_edits) = char_map.sync(fold_snapshot, fold_edits, tab_size);
- log::info!("CharMap text: {:?}", tabs_snapshot.text());
+ let (tabs_snapshot, tab_edits) = tab_map.sync(fold_snapshot, fold_edits, tab_size);
+ log::info!("TabMap text: {:?}", tabs_snapshot.text());
let unwrapped_text = tabs_snapshot.text();
let expected_text = wrap_text(&unwrapped_text, wrap_width, &mut line_wrapper);
@@ -1352,7 +1345,7 @@ mod tests {
if tab_size.get() == 1
|| !wrapped_snapshot
- .char_snapshot
+ .tab_snapshot
.fold_snapshot
.text()
.contains('\t')
@@ -68,7 +68,6 @@ use sum_tree::Bias;
use theme::{ActiveTheme, Appearance, PlayerColor};
use ui::prelude::*;
use ui::{h_flex, ButtonLike, ButtonStyle, ContextMenu, Tooltip};
-use unicode_segmentation::UnicodeSegmentation;
use util::RangeExt;
use util::ResultExt;
use workspace::{item::Item, Workspace};
@@ -1026,21 +1025,23 @@ impl EditorElement {
}
let block_text = if let CursorShape::Block = selection.cursor_shape {
snapshot
- .grapheme_at(cursor_position)
+ .display_chars_at(cursor_position)
+ .next()
.or_else(|| {
if cursor_column == 0 {
- snapshot.placeholder_text().and_then(|s| {
- s.graphemes(true).next().map(|s| s.to_owned())
- })
+ snapshot
+ .placeholder_text()
+ .and_then(|s| s.chars().next())
+ .map(|c| (c, cursor_position))
} else {
None
}
})
- .and_then(|grapheme| {
- let text = if grapheme == "\n" {
+ .and_then(|(character, _)| {
+ let text = if character == '\n' {
SharedString::from(" ")
} else {
- SharedString::from(grapheme)
+ SharedString::from(character.to_string())
};
let len = text.len();
@@ -1,7 +1,6 @@
use crate::{
display_map::{InlayOffset, ToDisplayPoint},
hover_links::{InlayHighlight, RangeInEditor},
- is_invisible,
scroll::ScrollAmount,
Anchor, AnchorRangeExt, DisplayPoint, DisplayRow, Editor, EditorSettings, EditorSnapshot,
Hover, RangeToAnchorExt,
@@ -12,7 +11,7 @@ use gpui::{
StyleRefinement, Styled, Task, TextStyleRefinement, View, ViewContext,
};
use itertools::Itertools;
-use language::{Diagnostic, DiagnosticEntry, Language, LanguageRegistry};
+use language::{DiagnosticEntry, Language, LanguageRegistry};
use lsp::DiagnosticSeverity;
use markdown::{Markdown, MarkdownStyle};
use multi_buffer::ToOffset;
@@ -200,6 +199,7 @@ fn show_hover(
if editor.pending_rename.is_some() {
return None;
}
+
let snapshot = editor.snapshot(cx);
let (buffer, buffer_position) = editor
@@ -259,7 +259,7 @@ fn show_hover(
}
// If there's a diagnostic, assign it on the hover state and notify
- let mut local_diagnostic = snapshot
+ let local_diagnostic = snapshot
.buffer_snapshot
.diagnostics_in_range::<_, usize>(anchor..anchor, false)
// Find the entry with the most specific range
@@ -281,42 +281,6 @@ fn show_hover(
})
});
- if let Some(invisible) = snapshot
- .buffer_snapshot
- .chars_at(anchor)
- .next()
- .filter(|&c| is_invisible(c))
- {
- let after = snapshot.buffer_snapshot.anchor_after(
- anchor.to_offset(&snapshot.buffer_snapshot) + invisible.len_utf8(),
- );
- local_diagnostic = Some(DiagnosticEntry {
- diagnostic: Diagnostic {
- severity: DiagnosticSeverity::HINT,
- message: format!("Unicode character U+{:02X}", invisible as u32),
- ..Default::default()
- },
- range: anchor..after,
- })
- } else if let Some(invisible) = snapshot
- .buffer_snapshot
- .reversed_chars_at(anchor)
- .next()
- .filter(|&c| is_invisible(c))
- {
- let before = snapshot.buffer_snapshot.anchor_before(
- anchor.to_offset(&snapshot.buffer_snapshot) - invisible.len_utf8(),
- );
- local_diagnostic = Some(DiagnosticEntry {
- diagnostic: Diagnostic {
- severity: DiagnosticSeverity::HINT,
- message: format!("Unicode character U+{:02X}", invisible as u32),
- ..Default::default()
- },
- range: before..anchor,
- })
- }
-
let diagnostic_popover = if let Some(local_diagnostic) = local_diagnostic {
let text = match local_diagnostic.diagnostic.source {
Some(ref source) => {
@@ -324,6 +288,7 @@ fn show_hover(
}
None => local_diagnostic.diagnostic.message.clone(),
};
+
let mut border_color: Option<Hsla> = None;
let mut background_color: Option<Hsla> = None;
@@ -379,6 +344,7 @@ fn show_hover(
Markdown::new_text(text, markdown_style.clone(), None, cx, None)
})
.ok();
+
Some(DiagnosticPopover {
local_diagnostic,
primary_diagnostic,
@@ -466,6 +432,7 @@ fn show_hover(
cx.notify();
cx.refresh();
})?;
+
anyhow::Ok(())
}
.log_err()
@@ -1,7 +1,6 @@
use crate::{
- black, fill, point, px, size, Bounds, Half, Hsla, LineLayout, Pixels, Point, Result,
- SharedString, StrikethroughStyle, UnderlineStyle, WindowContext, WrapBoundary,
- WrappedLineLayout,
+ black, fill, point, px, size, Bounds, Hsla, LineLayout, Pixels, Point, Result, SharedString,
+ StrikethroughStyle, UnderlineStyle, WindowContext, WrapBoundary, WrappedLineLayout,
};
use derive_more::{Deref, DerefMut};
use smallvec::SmallVec;
@@ -130,9 +129,8 @@ fn paint_line(
let text_system = cx.text_system().clone();
let mut glyph_origin = origin;
let mut prev_glyph_position = Point::default();
- let mut max_glyph_size = size(px(0.), px(0.));
for (run_ix, run) in layout.runs.iter().enumerate() {
- max_glyph_size = text_system.bounding_box(run.font_id, layout.font_size).size;
+ let max_glyph_size = text_system.bounding_box(run.font_id, layout.font_size).size;
for (glyph_ix, glyph) in run.glyphs.iter().enumerate() {
glyph_origin.x += glyph.position.x - prev_glyph_position.x;
@@ -141,9 +139,6 @@ fn paint_line(
wraps.next();
if let Some((background_origin, background_color)) = current_background.as_mut()
{
- if glyph_origin.x == background_origin.x {
- background_origin.x -= max_glyph_size.width.half()
- }
cx.paint_quad(fill(
Bounds {
origin: *background_origin,
@@ -155,9 +150,6 @@ fn paint_line(
background_origin.y += line_height;
}
if let Some((underline_origin, underline_style)) = current_underline.as_mut() {
- if glyph_origin.x == underline_origin.x {
- underline_origin.x -= max_glyph_size.width.half();
- };
cx.paint_underline(
*underline_origin,
glyph_origin.x - underline_origin.x,
@@ -169,9 +161,6 @@ fn paint_line(
if let Some((strikethrough_origin, strikethrough_style)) =
current_strikethrough.as_mut()
{
- if glyph_origin.x == strikethrough_origin.x {
- strikethrough_origin.x -= max_glyph_size.width.half();
- };
cx.paint_strikethrough(
*strikethrough_origin,
glyph_origin.x - strikethrough_origin.x,
@@ -190,18 +179,7 @@ fn paint_line(
let mut finished_underline: Option<(Point<Pixels>, UnderlineStyle)> = None;
let mut finished_strikethrough: Option<(Point<Pixels>, StrikethroughStyle)> = None;
if glyph.index >= run_end {
- let mut style_run = decoration_runs.next();
-
- // ignore style runs that apply to a partial glyph
- while let Some(run) = style_run {
- if glyph.index < run_end + (run.len as usize) {
- break;
- }
- run_end += run.len as usize;
- style_run = decoration_runs.next();
- }
-
- if let Some(style_run) = style_run {
+ if let Some(style_run) = decoration_runs.next() {
if let Some((_, background_color)) = &mut current_background {
if style_run.background_color.as_ref() != Some(background_color) {
finished_background = current_background.take();
@@ -262,14 +240,10 @@ fn paint_line(
}
if let Some((background_origin, background_color)) = finished_background {
- let mut width = glyph_origin.x - background_origin.x;
- if width == px(0.) {
- width = px(5.)
- };
cx.paint_quad(fill(
Bounds {
origin: background_origin,
- size: size(width, line_height),
+ size: size(glyph_origin.x - background_origin.x, line_height),
},
background_color,
));
@@ -325,10 +299,7 @@ fn paint_line(
last_line_end_x -= glyph.position.x;
}
- if let Some((mut background_origin, background_color)) = current_background.take() {
- if last_line_end_x == background_origin.x {
- background_origin.x -= max_glyph_size.width.half()
- };
+ if let Some((background_origin, background_color)) = current_background.take() {
cx.paint_quad(fill(
Bounds {
origin: background_origin,
@@ -338,10 +309,7 @@ fn paint_line(
));
}
- if let Some((mut underline_start, underline_style)) = current_underline.take() {
- if last_line_end_x == underline_start.x {
- underline_start.x -= max_glyph_size.width.half()
- };
+ if let Some((underline_start, underline_style)) = current_underline.take() {
cx.paint_underline(
underline_start,
last_line_end_x - underline_start.x,
@@ -349,10 +317,7 @@ fn paint_line(
);
}
- if let Some((mut strikethrough_start, strikethrough_style)) = current_strikethrough.take() {
- if last_line_end_x == strikethrough_start.x {
- strikethrough_start.x -= max_glyph_size.width.half()
- };
+ if let Some((strikethrough_start, strikethrough_style)) = current_strikethrough.take() {
cx.paint_strikethrough(
strikethrough_start,
last_line_end_x - strikethrough_start.x,
@@ -501,8 +501,6 @@ pub struct Chunk<'a> {
pub is_unnecessary: bool,
/// Whether this chunk of text was originally a tab character.
pub is_tab: bool,
- /// Whether this chunk of text is an invisible character.
- pub is_invisible: bool,
/// An optional recipe for how the chunk should be presented.
pub renderer: Option<ChunkRenderer>,
}
@@ -4213,6 +4211,7 @@ impl<'a> Iterator for BufferChunks<'a> {
if self.range.start == self.chunks.offset() + chunk.len() {
self.chunks.next().unwrap();
}
+
Some(Chunk {
text: slice,
syntax_highlight_id: highlight_id,