Detailed changes
@@ -9,6 +9,7 @@ use std::{
fmt::{self, Debug},
marker::PhantomData,
mem,
+ ops::RangeInclusive,
pin::Pin,
rc::Rc,
sync::{
@@ -46,6 +47,7 @@ struct DeterministicState {
scheduled: Vec<(Runnable, Backtrace)>,
spawned_from_foreground: Vec<(Runnable, Backtrace)>,
forbid_parking: bool,
+ block_on_ticks: RangeInclusive<usize>,
}
pub struct Deterministic {
@@ -62,6 +64,7 @@ impl Deterministic {
scheduled: Default::default(),
spawned_from_foreground: Default::default(),
forbid_parking: false,
+ block_on_ticks: 0..=1000,
})),
parker: Default::default(),
}
@@ -330,13 +333,19 @@ impl Foreground {
pub fn forbid_parking(&self) {
match self {
- Self::Platform { .. } => panic!("can't call this method on a platform executor"),
- Self::Test(_) => panic!("can't call this method on a test executor"),
Self::Deterministic(executor) => {
let mut state = executor.state.lock();
state.forbid_parking = true;
state.rng = StdRng::seed_from_u64(state.seed);
}
+ _ => panic!("this method can only be called on a deterministic executor"),
+ }
+ }
+
+ pub fn set_block_on_ticks(&self, range: RangeInclusive<usize>) {
+ match self {
+ Self::Deterministic(executor) => executor.state.lock().block_on_ticks = range,
+ _ => panic!("this method can only be called on a deterministic executor"),
}
}
}
@@ -386,7 +395,11 @@ impl Background {
smol::block_on(async move { util::timeout(timeout, future).await.ok() })
}
Self::Deterministic(executor) => {
- let max_ticks = executor.state.lock().rng.gen_range(1..=1000);
+ let max_ticks = {
+ let mut state = executor.state.lock();
+ let range = state.block_on_ticks.clone();
+ state.rng.gen_range(range)
+ };
executor.block_on(max_ticks, future)
}
}
@@ -38,10 +38,12 @@ impl DisplayMap {
pub fn snapshot(&self, cx: &AppContext) -> DisplayMapSnapshot {
let (folds_snapshot, edits) = self.fold_map.read(cx);
let (tabs_snapshot, edits) = self.tab_map.sync(folds_snapshot.clone(), edits);
+ let wraps_snapshot = self.wrap_map.sync(tabs_snapshot.clone(), edits, cx);
DisplayMapSnapshot {
buffer_snapshot: self.buffer.read(cx).snapshot(),
folds_snapshot,
tabs_snapshot,
+ wraps_snapshot,
}
}
@@ -51,7 +53,11 @@ impl DisplayMap {
cx: &AppContext,
) {
let (mut fold_map, snapshot, edits) = self.fold_map.write(cx);
- let edits = fold_map.fold(ranges, cx);
+ let (snapshot, edits) = self.tab_map.sync(snapshot, edits);
+ self.wrap_map.sync(snapshot, edits, cx);
+ let (snapshot, edits) = fold_map.fold(ranges, cx);
+ let (snapshot, edits) = self.tab_map.sync(snapshot, edits);
+ self.wrap_map.sync(snapshot, edits, cx);
}
pub fn unfold<T: ToOffset>(
@@ -60,7 +66,11 @@ impl DisplayMap {
cx: &AppContext,
) {
let (mut fold_map, snapshot, edits) = self.fold_map.write(cx);
- let edits = fold_map.unfold(ranges, cx);
+ let (snapshot, edits) = self.tab_map.sync(snapshot, edits);
+ self.wrap_map.sync(snapshot, edits, cx);
+ let (snapshot, edits) = fold_map.unfold(ranges, cx);
+ let (snapshot, edits) = self.tab_map.sync(snapshot, edits);
+ self.wrap_map.sync(snapshot, edits, cx);
}
pub fn set_wrap_width(&self, width: Option<f32>) {
@@ -72,6 +82,7 @@ pub struct DisplayMapSnapshot {
buffer_snapshot: buffer::Snapshot,
folds_snapshot: fold_map::Snapshot,
tabs_snapshot: tab_map::Snapshot,
+ wraps_snapshot: wrap_map::Snapshot,
}
impl DisplayMapSnapshot {
@@ -80,11 +91,11 @@ impl DisplayMapSnapshot {
}
pub fn max_point(&self) -> DisplayPoint {
- DisplayPoint(self.tabs_snapshot.max_point())
+ DisplayPoint(self.wraps_snapshot.max_point())
}
- pub fn chunks_at(&self, point: DisplayPoint) -> tab_map::Chunks {
- self.tabs_snapshot.chunks_at(point.0)
+ pub fn chunks_at(&self, point: DisplayPoint) -> wrap_map::Chunks {
+ self.wraps_snapshot.chunks_at(point.0)
}
pub fn highlighted_chunks_for_rows(&mut self, rows: Range<u32>) -> tab_map::HighlightedChunks {
@@ -122,7 +133,7 @@ impl DisplayMapSnapshot {
}
pub fn clip_point(&self, point: DisplayPoint, bias: Bias) -> DisplayPoint {
- DisplayPoint(self.tabs_snapshot.clip_point(point.0, bias))
+ DisplayPoint(self.wraps_snapshot.clip_point(point.0, bias))
}
pub fn folds_in_range<'a, T>(
@@ -194,11 +205,11 @@ impl DisplayMapSnapshot {
}
#[derive(Copy, Clone, Debug, Default, Eq, Ord, PartialOrd, PartialEq)]
-pub struct DisplayPoint(tab_map::OutputPoint);
+pub struct DisplayPoint(wrap_map::OutputPoint);
impl DisplayPoint {
pub fn new(row: u32, column: u32) -> Self {
- Self(tab_map::OutputPoint::new(row, column))
+ Self(wrap_map::OutputPoint::new(row, column))
}
pub fn zero() -> Self {
@@ -222,22 +233,24 @@ impl DisplayPoint {
}
pub fn to_buffer_point(self, map: &DisplayMapSnapshot, bias: Bias) -> Point {
- map.folds_snapshot
- .to_input_point(map.tabs_snapshot.to_input_point(self.0, bias).0)
+ let unwrapped_point = map.wraps_snapshot.to_input_point(self.0);
+ let unexpanded_point = map.tabs_snapshot.to_input_point(unwrapped_point, bias).0;
+ map.folds_snapshot.to_input_point(unexpanded_point)
}
pub fn to_buffer_offset(self, map: &DisplayMapSnapshot, bias: Bias) -> usize {
- map.folds_snapshot
- .to_input_offset(map.tabs_snapshot.to_input_point(self.0, bias).0)
+ let unwrapped_point = map.wraps_snapshot.to_input_point(self.0);
+ let unexpanded_point = map.tabs_snapshot.to_input_point(unwrapped_point, bias).0;
+ map.folds_snapshot.to_input_offset(unexpanded_point)
}
}
impl Point {
pub fn to_display_point(self, map: &DisplayMapSnapshot) -> DisplayPoint {
- DisplayPoint(
- map.tabs_snapshot
- .to_output_point(map.folds_snapshot.to_output_point(self)),
- )
+ let folded_point = map.folds_snapshot.to_output_point(self);
+ let expanded_point = map.tabs_snapshot.to_output_point(folded_point);
+ let wrapped_point = map.wraps_snapshot.to_output_point(expanded_point);
+ DisplayPoint(wrapped_point)
}
}
@@ -258,6 +271,48 @@ mod tests {
use buffer::History;
use std::sync::Arc;
+ #[gpui::test]
+ async fn test_soft_wraps(mut cx: gpui::TestAppContext) {
+ cx.foreground().set_block_on_ticks(usize::MAX..=usize::MAX);
+
+ let font_cache = cx.font_cache();
+
+ let settings = Settings {
+ buffer_font_family: font_cache.load_family(&["Helvetica"]).unwrap(),
+ ui_font_family: font_cache.load_family(&["Helvetica"]).unwrap(),
+ buffer_font_size: 12.0,
+ ui_font_size: 12.0,
+ tab_size: 4,
+ theme: Arc::new(Theme::default()),
+ };
+ let wrap_width = Some(64.);
+
+ let text = "one two three four five\nsix seven eight";
+ let buffer = cx.add_model(|cx| Buffer::new(0, text.to_string(), cx));
+ let map = cx.read(|cx| DisplayMap::new(buffer.clone(), settings, wrap_width, cx));
+
+ let snapshot = cx.read(|cx| map.snapshot(cx));
+ assert_eq!(
+ snapshot
+ .chunks_at(DisplayPoint::new(0, 3))
+ .collect::<String>(),
+ " two \nthree four \nfive\nsix seven \neight"
+ );
+
+ buffer.update(&mut cx, |buffer, cx| {
+ let ix = buffer.text().find("seven").unwrap();
+ buffer.edit(vec![ix..ix], "and ", cx);
+ });
+
+ let snapshot = cx.read(|cx| map.snapshot(cx));
+ assert_eq!(
+ snapshot
+ .chunks_at(DisplayPoint::new(1, 0))
+ .collect::<String>(),
+ "three four \nfive\nsix and \nseven eight"
+ );
+ }
+
#[gpui::test]
fn test_chunks_at(cx: &mut gpui::MutableAppContext) {
let text = sample_text(6, 6);
@@ -14,7 +14,7 @@ use parking_lot::Mutex;
use std::{
cmp::{self, Ordering},
iter,
- ops::{Range, Sub},
+ ops::Range,
sync::atomic::{AtomicUsize, Ordering::SeqCst},
};
@@ -47,14 +47,6 @@ impl OutputPoint {
}
}
-impl Sub<Self> for OutputPoint {
- type Output = OutputPoint;
-
- fn sub(self, other: Self) -> Self::Output {
- Self(self.0 - other.0)
- }
-}
-
pub struct FoldMapWriter<'a>(&'a mut FoldMap);
impl<'a> FoldMapWriter<'a> {
@@ -906,8 +898,8 @@ impl<'a> Iterator for InputRows<'a> {
}
if self.cursor.item().is_some() {
- let overshoot = self.output_point - *self.cursor.seek_start();
- let input_point = *self.cursor.sum_start() + overshoot.0;
+ let overshoot = self.output_point.0 - self.cursor.seek_start().0;
+ let input_point = *self.cursor.sum_start() + overshoot;
*self.output_point.row_mut() += 1;
Some(input_point.row)
} else {
@@ -5,10 +5,7 @@ use super::fold_map::{
OutputOffset as InputOffset, OutputPoint as InputPoint, Snapshot as InputSnapshot,
};
use crate::{editor::rope, settings::StyleId, util::Bias};
-use std::{
- mem,
- ops::{Add, AddAssign, Range},
-};
+use std::{mem, ops::Range};
pub struct TabMap(Mutex<Snapshot>);
@@ -268,20 +265,6 @@ impl From<super::Point> for OutputPoint {
}
}
-impl AddAssign<Self> for OutputPoint {
- fn add_assign(&mut self, rhs: Self) {
- self.0 += &rhs.0;
- }
-}
-
-impl Add<Self> for OutputPoint {
- type Output = OutputPoint;
-
- fn add(self, other: Self) -> Self::Output {
- Self(self.0 + other.0)
- }
-}
-
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Edit {
pub old_lines: Range<OutputPoint>,
@@ -14,12 +14,7 @@ use postage::{
watch,
};
use smol::channel;
-use std::{
- collections::VecDeque,
- ops::{AddAssign, Range, Sub},
- sync::Arc,
- time::Duration,
-};
+use std::{collections::VecDeque, ops::Range, sync::Arc, time::Duration};
#[derive(Copy, Clone, Debug, Default, Eq, Ord, PartialOrd, PartialEq)]
pub struct OutputPoint(super::Point);
@@ -50,20 +45,6 @@ impl OutputPoint {
}
}
-impl AddAssign<Self> for OutputPoint {
- fn add_assign(&mut self, rhs: Self) {
- self.0 += &rhs.0;
- }
-}
-
-impl Sub<Self> for OutputPoint {
- type Output = OutputPoint;
-
- fn sub(self, other: Self) -> Self::Output {
- Self(self.0 - other.0)
- }
-}
-
#[derive(Clone)]
pub struct Snapshot {
transforms: SumTree<Transform>,
@@ -145,10 +126,10 @@ impl Snapshot {
}
pub fn chunks_at(&self, point: OutputPoint) -> Chunks {
- let mut transforms = self.transforms.cursor();
+ let mut transforms = self.transforms.cursor::<OutputPoint, InputPoint>();
transforms.seek(&point, Bias::Right, &());
let input_position =
- *transforms.sum_start() + InputPoint((point - *transforms.seek_start()).0);
+ InputPoint(transforms.sum_start().0 + (point.0 - transforms.seek_start().0));
let input_chunks = self.input.chunks_at(input_position);
Chunks {
input_chunks,
@@ -157,6 +138,26 @@ impl Snapshot {
input_chunk: "",
}
}
+
+ pub fn max_point(&self) -> OutputPoint {
+ self.to_output_point(self.input.max_point())
+ }
+
+ pub fn to_input_point(&self, point: OutputPoint) -> InputPoint {
+ let mut cursor = self.transforms.cursor::<OutputPoint, InputPoint>();
+ cursor.seek(&point, Bias::Right, &());
+ InputPoint(cursor.sum_start().0 + (point.0 - cursor.seek_start().0))
+ }
+
+ pub fn to_output_point(&self, point: InputPoint) -> OutputPoint {
+ let mut cursor = self.transforms.cursor::<InputPoint, OutputPoint>();
+ cursor.seek(&point, Bias::Right, &());
+ OutputPoint(cursor.sum_start().0 + (point.0 - cursor.seek_start().0))
+ }
+
+ pub fn clip_point(&self, point: OutputPoint, bias: Bias) -> OutputPoint {
+ self.to_output_point(self.input.clip_point(self.to_input_point(point), bias))
+ }
}
pub struct Chunks<'a> {
@@ -558,13 +559,13 @@ impl sum_tree::Summary for TransformSummary {
impl<'a> sum_tree::Dimension<'a, TransformSummary> for InputPoint {
fn add_summary(&mut self, summary: &'a TransformSummary, _: &()) {
- *self += InputPoint(summary.input.lines);
+ self.0 += summary.input.lines;
}
}
impl<'a> sum_tree::Dimension<'a, TransformSummary> for OutputPoint {
fn add_summary(&mut self, summary: &'a TransformSummary, _: &()) {
- *self += OutputPoint(summary.output.lines);
+ self.0 += summary.output.lines;
}
}
@@ -578,7 +579,6 @@ mod tests {
},
util::RandomCharIter,
};
- use futures::StreamExt;
use gpui::fonts::FontId;
use rand::prelude::*;
use std::env;