mirror of
https://github.com/zed-industries/zed.git
synced 2024-11-07 20:39:04 +03:00
Make WrapMap
and DisplayMap
models
This removes the need for a lock around in `WrapMap` and also removes `WrapMap::notifications` because gpui already has a standard way of notifying when a model updates.
This commit is contained in:
parent
b04c5741aa
commit
b647e3ee71
@ -1850,6 +1850,20 @@ impl<M> UpdateModel for ModelContext<'_, M> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<M> Deref for ModelContext<'_, M> {
|
||||
type Target = MutableAppContext;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.app
|
||||
}
|
||||
}
|
||||
|
||||
impl<M> DerefMut for ModelContext<'_, M> {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.app
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ViewContext<'a, T: ?Sized> {
|
||||
app: &'a mut MutableAppContext,
|
||||
window_id: usize,
|
||||
|
@ -21,7 +21,7 @@ use gpui::{
|
||||
ViewContext, WeakViewHandle,
|
||||
};
|
||||
use parking_lot::Mutex;
|
||||
use postage::{prelude::Stream, watch};
|
||||
use postage::watch;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use smallvec::SmallVec;
|
||||
use smol::Timer;
|
||||
@ -368,7 +368,7 @@ pub enum SelectAction {
|
||||
pub struct Editor {
|
||||
handle: WeakViewHandle<Self>,
|
||||
buffer: ModelHandle<Buffer>,
|
||||
display_map: DisplayMap,
|
||||
display_map: ModelHandle<DisplayMap>,
|
||||
selection_set_id: SelectionSetId,
|
||||
pending_selection: Option<Selection>,
|
||||
next_selection_id: usize,
|
||||
@ -417,17 +417,11 @@ impl Editor {
|
||||
settings: watch::Receiver<Settings>,
|
||||
cx: &mut ViewContext<Self>,
|
||||
) -> Self {
|
||||
let display_map =
|
||||
cx.add_model(|cx| DisplayMap::new(buffer.clone(), settings.borrow().clone(), None, cx));
|
||||
cx.observe_model(&buffer, Self::on_buffer_changed);
|
||||
cx.subscribe_to_model(&buffer, Self::on_buffer_event);
|
||||
let display_map = DisplayMap::new(buffer.clone(), settings.borrow().clone(), None, cx);
|
||||
|
||||
let mut notifications = display_map.notifications();
|
||||
cx.spawn(|this, mut cx| async move {
|
||||
while notifications.recv().await.is_some() {
|
||||
this.update(&mut cx, |_, cx| cx.notify());
|
||||
}
|
||||
})
|
||||
.detach();
|
||||
cx.observe_model(&display_map, Self::on_display_map_changed);
|
||||
|
||||
let mut next_selection_id = 0;
|
||||
let selection_set_id = buffer.update(cx, |buffer, cx| {
|
||||
@ -470,7 +464,7 @@ impl Editor {
|
||||
let settings = self.settings.borrow();
|
||||
|
||||
Snapshot {
|
||||
display_snapshot: self.display_map.snapshot(cx),
|
||||
display_snapshot: self.display_map.update(cx, |map, cx| map.snapshot(cx)),
|
||||
gutter_visible: !self.single_line,
|
||||
scroll_position: *self.scroll_position.lock(),
|
||||
theme: settings.theme.clone(),
|
||||
@ -504,7 +498,7 @@ impl Editor {
|
||||
line_height: f32,
|
||||
cx: &mut MutableAppContext,
|
||||
) -> bool {
|
||||
let display_map = self.display_map.snapshot(cx);
|
||||
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
|
||||
let mut scroll_position = self.scroll_position.lock();
|
||||
let scroll_top = scroll_position.y();
|
||||
scroll_position
|
||||
@ -564,7 +558,7 @@ impl Editor {
|
||||
layouts: &[text_layout::Line],
|
||||
cx: &mut MutableAppContext,
|
||||
) -> bool {
|
||||
let display_map = self.display_map.snapshot(cx);
|
||||
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
|
||||
let mut target_left = std::f32::INFINITY;
|
||||
let mut target_right = 0.0_f32;
|
||||
for selection in self.selections(cx) {
|
||||
@ -616,7 +610,7 @@ impl Editor {
|
||||
cx.emit(Event::Activate);
|
||||
}
|
||||
|
||||
let display_map = self.display_map.snapshot(cx);
|
||||
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
|
||||
let cursor = display_map.anchor_before(position, Bias::Left);
|
||||
let selection = Selection {
|
||||
id: post_inc(&mut self.next_selection_id),
|
||||
@ -640,7 +634,7 @@ impl Editor {
|
||||
scroll_position: Vector2F,
|
||||
cx: &mut ViewContext<Self>,
|
||||
) {
|
||||
let display_map = self.display_map.snapshot(cx);
|
||||
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
|
||||
let buffer = self.buffer.read(cx);
|
||||
let cursor = display_map.anchor_before(position, Bias::Left);
|
||||
if let Some(selection) = self.pending_selection.as_mut() {
|
||||
@ -719,7 +713,7 @@ impl Editor {
|
||||
T: IntoIterator<Item = &'a Range<DisplayPoint>>,
|
||||
{
|
||||
let mut selections = Vec::new();
|
||||
let display_map = self.display_map.snapshot(cx);
|
||||
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
|
||||
for range in ranges {
|
||||
let mut start = range.start;
|
||||
let mut end = range.end;
|
||||
@ -794,7 +788,7 @@ impl Editor {
|
||||
pub fn backspace(&mut self, _: &(), cx: &mut ViewContext<Self>) {
|
||||
self.start_transaction(cx);
|
||||
let mut selections = self.selections(cx.as_ref()).to_vec();
|
||||
let display_map = self.display_map.snapshot(cx);
|
||||
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
|
||||
{
|
||||
let buffer = self.buffer.read(cx);
|
||||
for selection in &mut selections {
|
||||
@ -816,7 +810,7 @@ impl Editor {
|
||||
|
||||
pub fn delete(&mut self, _: &(), cx: &mut ViewContext<Self>) {
|
||||
self.start_transaction(cx);
|
||||
let display_map = self.display_map.snapshot(cx);
|
||||
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
|
||||
let mut selections = self.selections(cx.as_ref()).to_vec();
|
||||
{
|
||||
let buffer = self.buffer.read(cx);
|
||||
@ -840,7 +834,7 @@ impl Editor {
|
||||
pub fn delete_line(&mut self, _: &(), cx: &mut ViewContext<Self>) {
|
||||
self.start_transaction(cx);
|
||||
|
||||
let display_map = self.display_map.snapshot(cx);
|
||||
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
|
||||
let app = cx.as_ref();
|
||||
let buffer = self.buffer.read(app);
|
||||
|
||||
@ -926,7 +920,7 @@ impl Editor {
|
||||
}
|
||||
self.update_selections(selections.clone(), false, cx);
|
||||
|
||||
let display_map = self.display_map.snapshot(cx);
|
||||
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
|
||||
let buffer = self.buffer.read(cx);
|
||||
|
||||
let mut edits = Vec::new();
|
||||
@ -975,7 +969,7 @@ impl Editor {
|
||||
pub fn move_line_up(&mut self, _: &(), cx: &mut ViewContext<Self>) {
|
||||
self.start_transaction(cx);
|
||||
|
||||
let display_map = self.display_map.snapshot(cx);
|
||||
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
|
||||
let app = cx.as_ref();
|
||||
let buffer = self.buffer.read(cx);
|
||||
|
||||
@ -1060,7 +1054,7 @@ impl Editor {
|
||||
pub fn move_line_down(&mut self, _: &(), cx: &mut ViewContext<Self>) {
|
||||
self.start_transaction(cx);
|
||||
|
||||
let display_map = self.display_map.snapshot(cx);
|
||||
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
|
||||
let app = cx.as_ref();
|
||||
let buffer = self.buffer.read(cx);
|
||||
|
||||
@ -1275,7 +1269,7 @@ impl Editor {
|
||||
}
|
||||
|
||||
pub fn move_left(&mut self, _: &(), cx: &mut ViewContext<Self>) {
|
||||
let display_map = self.display_map.snapshot(cx);
|
||||
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
|
||||
let app = cx.as_ref();
|
||||
let mut selections = self.selections(app).to_vec();
|
||||
{
|
||||
@ -1299,7 +1293,7 @@ impl Editor {
|
||||
}
|
||||
|
||||
pub fn select_left(&mut self, _: &(), cx: &mut ViewContext<Self>) {
|
||||
let display_map = self.display_map.snapshot(cx);
|
||||
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
|
||||
let mut selections = self.selections(cx.as_ref()).to_vec();
|
||||
{
|
||||
let buffer = self.buffer.read(cx);
|
||||
@ -1315,7 +1309,7 @@ impl Editor {
|
||||
}
|
||||
|
||||
pub fn move_right(&mut self, _: &(), cx: &mut ViewContext<Self>) {
|
||||
let display_map = self.display_map.snapshot(cx);
|
||||
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
|
||||
let mut selections = self.selections(cx.as_ref()).to_vec();
|
||||
{
|
||||
for selection in &mut selections {
|
||||
@ -1338,7 +1332,7 @@ impl Editor {
|
||||
}
|
||||
|
||||
pub fn select_right(&mut self, _: &(), cx: &mut ViewContext<Self>) {
|
||||
let display_map = self.display_map.snapshot(cx);
|
||||
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
|
||||
let mut selections = self.selections(cx.as_ref()).to_vec();
|
||||
{
|
||||
let app = cx.as_ref();
|
||||
@ -1355,7 +1349,7 @@ impl Editor {
|
||||
}
|
||||
|
||||
pub fn move_up(&mut self, _: &(), cx: &mut ViewContext<Self>) {
|
||||
let display_map = self.display_map.snapshot(cx);
|
||||
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
|
||||
if self.single_line {
|
||||
cx.propagate_action();
|
||||
} else {
|
||||
@ -1381,7 +1375,7 @@ impl Editor {
|
||||
}
|
||||
|
||||
pub fn select_up(&mut self, _: &(), cx: &mut ViewContext<Self>) {
|
||||
let display_map = self.display_map.snapshot(cx);
|
||||
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
|
||||
let mut selections = self.selections(cx.as_ref()).to_vec();
|
||||
{
|
||||
let app = cx.as_ref();
|
||||
@ -1400,7 +1394,7 @@ impl Editor {
|
||||
if self.single_line {
|
||||
cx.propagate_action();
|
||||
} else {
|
||||
let display_map = self.display_map.snapshot(cx);
|
||||
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
|
||||
let mut selections = self.selections(cx.as_ref()).to_vec();
|
||||
{
|
||||
for selection in &mut selections {
|
||||
@ -1423,7 +1417,7 @@ impl Editor {
|
||||
}
|
||||
|
||||
pub fn select_down(&mut self, _: &(), cx: &mut ViewContext<Self>) {
|
||||
let display_map = self.display_map.snapshot(cx);
|
||||
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
|
||||
let mut selections = self.selections(cx).to_vec();
|
||||
{
|
||||
let app = cx.as_ref();
|
||||
@ -1439,7 +1433,7 @@ impl Editor {
|
||||
}
|
||||
|
||||
pub fn move_to_previous_word_boundary(&mut self, _: &(), cx: &mut ViewContext<Self>) {
|
||||
let display_map = self.display_map.snapshot(cx);
|
||||
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
|
||||
let mut selections = self.selections(cx).to_vec();
|
||||
{
|
||||
for selection in &mut selections {
|
||||
@ -1456,7 +1450,7 @@ impl Editor {
|
||||
}
|
||||
|
||||
pub fn select_to_previous_word_boundary(&mut self, _: &(), cx: &mut ViewContext<Self>) {
|
||||
let display_map = self.display_map.snapshot(cx);
|
||||
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
|
||||
let mut selections = self.selections(cx).to_vec();
|
||||
{
|
||||
let buffer = self.buffer.read(cx);
|
||||
@ -1479,7 +1473,7 @@ impl Editor {
|
||||
}
|
||||
|
||||
pub fn move_to_next_word_boundary(&mut self, _: &(), cx: &mut ViewContext<Self>) {
|
||||
let display_map = self.display_map.snapshot(cx);
|
||||
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
|
||||
let mut selections = self.selections(cx).to_vec();
|
||||
{
|
||||
for selection in &mut selections {
|
||||
@ -1496,7 +1490,7 @@ impl Editor {
|
||||
}
|
||||
|
||||
pub fn select_to_next_word_boundary(&mut self, _: &(), cx: &mut ViewContext<Self>) {
|
||||
let display_map = self.display_map.snapshot(cx);
|
||||
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
|
||||
let mut selections = self.selections(cx).to_vec();
|
||||
{
|
||||
let buffer = self.buffer.read(cx);
|
||||
@ -1519,7 +1513,7 @@ impl Editor {
|
||||
}
|
||||
|
||||
pub fn move_to_beginning_of_line(&mut self, _: &(), cx: &mut ViewContext<Self>) {
|
||||
let display_map = self.display_map.snapshot(cx);
|
||||
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
|
||||
let mut selections = self.selections(cx).to_vec();
|
||||
{
|
||||
for selection in &mut selections {
|
||||
@ -1540,7 +1534,7 @@ impl Editor {
|
||||
toggle_indent: &bool,
|
||||
cx: &mut ViewContext<Self>,
|
||||
) {
|
||||
let display_map = self.display_map.snapshot(cx);
|
||||
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
|
||||
let mut selections = self.selections(cx).to_vec();
|
||||
{
|
||||
let buffer = self.buffer.read(cx);
|
||||
@ -1564,7 +1558,7 @@ impl Editor {
|
||||
}
|
||||
|
||||
pub fn move_to_end_of_line(&mut self, _: &(), cx: &mut ViewContext<Self>) {
|
||||
let display_map = self.display_map.snapshot(cx);
|
||||
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
|
||||
let mut selections = self.selections(cx).to_vec();
|
||||
{
|
||||
for selection in &mut selections {
|
||||
@ -1581,7 +1575,7 @@ impl Editor {
|
||||
}
|
||||
|
||||
pub fn select_to_end_of_line(&mut self, _: &(), cx: &mut ViewContext<Self>) {
|
||||
let display_map = self.display_map.snapshot(cx);
|
||||
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
|
||||
let mut selections = self.selections(cx).to_vec();
|
||||
{
|
||||
let buffer = self.buffer.read(cx);
|
||||
@ -1660,7 +1654,7 @@ impl Editor {
|
||||
}
|
||||
|
||||
pub fn select_line(&mut self, _: &(), cx: &mut ViewContext<Self>) {
|
||||
let display_map = self.display_map.snapshot(cx);
|
||||
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
|
||||
let buffer = self.buffer.read(cx);
|
||||
let mut selections = self.selections(cx).to_vec();
|
||||
let max_point = buffer.max_point();
|
||||
@ -1722,7 +1716,7 @@ impl Editor {
|
||||
}
|
||||
|
||||
fn add_selection(&mut self, above: bool, cx: &mut ViewContext<Self>) {
|
||||
let display_map = self.display_map.snapshot(cx);
|
||||
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
|
||||
let mut selections = self.selections(cx).to_vec();
|
||||
let mut state = self.add_selections_state.take().unwrap_or_else(|| {
|
||||
let oldest_selection = selections.iter().min_by_key(|s| s.id).unwrap().clone();
|
||||
@ -1815,7 +1809,7 @@ impl Editor {
|
||||
}
|
||||
|
||||
pub fn select_larger_syntax_node(&mut self, _: &(), cx: &mut ViewContext<Self>) {
|
||||
let display_map = self.display_map.snapshot(cx);
|
||||
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
|
||||
let buffer = self.buffer.read(cx);
|
||||
|
||||
let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
|
||||
@ -1932,7 +1926,7 @@ impl Editor {
|
||||
range: Range<DisplayPoint>,
|
||||
cx: &'a mut MutableAppContext,
|
||||
) -> impl 'a + Iterator<Item = Range<DisplayPoint>> {
|
||||
let display_map = self.display_map.snapshot(cx);
|
||||
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
|
||||
let buffer = self.buffer.read(cx);
|
||||
let selections = &buffer.selection_set(set_id).unwrap().selections;
|
||||
let start = display_map.anchor_before(range.start, Bias::Left);
|
||||
@ -2056,7 +2050,7 @@ impl Editor {
|
||||
pub fn fold(&mut self, _: &(), cx: &mut ViewContext<Self>) {
|
||||
let mut fold_ranges = Vec::new();
|
||||
|
||||
let display_map = self.display_map.snapshot(cx);
|
||||
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
|
||||
for selection in self.selections(cx) {
|
||||
let range = selection.display_range(&display_map).sorted();
|
||||
let buffer_start_row = range.start.to_buffer_point(&display_map, Bias::Left).row;
|
||||
@ -2078,7 +2072,7 @@ impl Editor {
|
||||
}
|
||||
|
||||
pub fn unfold(&mut self, _: &(), cx: &mut ViewContext<Self>) {
|
||||
let display_map = self.display_map.snapshot(cx);
|
||||
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
|
||||
let buffer = self.buffer.read(cx);
|
||||
let ranges = self
|
||||
.selections(cx)
|
||||
@ -2150,7 +2144,7 @@ impl Editor {
|
||||
|
||||
fn fold_ranges<T: ToOffset>(&mut self, ranges: Vec<Range<T>>, cx: &mut ViewContext<Self>) {
|
||||
if !ranges.is_empty() {
|
||||
self.display_map.fold(ranges, cx);
|
||||
self.display_map.update(cx, |map, cx| map.fold(ranges, cx));
|
||||
*self.autoscroll_requested.lock() = true;
|
||||
cx.notify();
|
||||
}
|
||||
@ -2158,26 +2152,35 @@ impl Editor {
|
||||
|
||||
fn unfold_ranges<T: ToOffset>(&mut self, ranges: Vec<Range<T>>, cx: &mut ViewContext<Self>) {
|
||||
if !ranges.is_empty() {
|
||||
self.display_map.unfold(ranges, cx);
|
||||
self.display_map
|
||||
.update(cx, |map, cx| map.unfold(ranges, cx));
|
||||
*self.autoscroll_requested.lock() = true;
|
||||
cx.notify();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn line_len(&self, display_row: u32, cx: &mut MutableAppContext) -> u32 {
|
||||
self.display_map.snapshot(cx).line_len(display_row)
|
||||
self.display_map
|
||||
.update(cx, |map, cx| map.snapshot(cx))
|
||||
.line_len(display_row)
|
||||
}
|
||||
|
||||
pub fn longest_row(&self, cx: &mut MutableAppContext) -> u32 {
|
||||
self.display_map.snapshot(cx).longest_row()
|
||||
self.display_map
|
||||
.update(cx, |map, cx| map.snapshot(cx))
|
||||
.longest_row()
|
||||
}
|
||||
|
||||
pub fn max_point(&self, cx: &mut MutableAppContext) -> DisplayPoint {
|
||||
self.display_map.snapshot(cx).max_point()
|
||||
self.display_map
|
||||
.update(cx, |map, cx| map.snapshot(cx))
|
||||
.max_point()
|
||||
}
|
||||
|
||||
pub fn text(&self, cx: &mut MutableAppContext) -> String {
|
||||
self.display_map.snapshot(cx).text()
|
||||
self.display_map
|
||||
.update(cx, |map, cx| map.snapshot(cx))
|
||||
.text()
|
||||
}
|
||||
|
||||
pub fn font_size(&self) -> f32 {
|
||||
@ -2185,7 +2188,8 @@ impl Editor {
|
||||
}
|
||||
|
||||
pub fn set_wrap_width(&self, width: f32, cx: &mut MutableAppContext) -> bool {
|
||||
self.display_map.set_wrap_width(Some(width), cx)
|
||||
self.display_map
|
||||
.update(cx, |map, cx| map.set_wrap_width(Some(width), cx))
|
||||
}
|
||||
|
||||
fn next_blink_epoch(&mut self) -> usize {
|
||||
@ -2259,6 +2263,10 @@ impl Editor {
|
||||
buffer::Event::Reparsed => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn on_display_map_changed(&mut self, _: ModelHandle<DisplayMap>, cx: &mut ViewContext<Self>) {
|
||||
cx.notify();
|
||||
}
|
||||
}
|
||||
|
||||
impl Snapshot {
|
||||
|
@ -5,8 +5,7 @@ mod wrap_map;
|
||||
|
||||
use super::{buffer, Anchor, Bias, Buffer, Point, Settings, ToOffset, ToPoint};
|
||||
use fold_map::FoldMap;
|
||||
use gpui::{ModelHandle, MutableAppContext};
|
||||
use postage::prelude::Stream;
|
||||
use gpui::{Entity, ModelContext, ModelHandle};
|
||||
use std::ops::Range;
|
||||
use tab_map::TabMap;
|
||||
pub use wrap_map::BufferRows;
|
||||
@ -16,7 +15,11 @@ pub struct DisplayMap {
|
||||
buffer: ModelHandle<Buffer>,
|
||||
fold_map: FoldMap,
|
||||
tab_map: TabMap,
|
||||
wrap_map: WrapMap,
|
||||
wrap_map: ModelHandle<WrapMap>,
|
||||
}
|
||||
|
||||
impl Entity for DisplayMap {
|
||||
type Event = ();
|
||||
}
|
||||
|
||||
impl DisplayMap {
|
||||
@ -24,11 +27,12 @@ impl DisplayMap {
|
||||
buffer: ModelHandle<Buffer>,
|
||||
settings: Settings,
|
||||
wrap_width: Option<f32>,
|
||||
cx: &mut MutableAppContext,
|
||||
cx: &mut ModelContext<Self>,
|
||||
) -> Self {
|
||||
let (fold_map, snapshot) = FoldMap::new(buffer.clone(), cx);
|
||||
let (tab_map, snapshot) = TabMap::new(snapshot, settings.tab_size);
|
||||
let wrap_map = WrapMap::new(snapshot, settings, wrap_width, cx);
|
||||
let wrap_map = cx.add_model(|cx| WrapMap::new(snapshot, settings, wrap_width, cx));
|
||||
cx.observe(&wrap_map, |_, _, cx| cx.notify());
|
||||
DisplayMap {
|
||||
buffer,
|
||||
fold_map,
|
||||
@ -37,10 +41,12 @@ impl DisplayMap {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn snapshot(&self, cx: &mut MutableAppContext) -> DisplayMapSnapshot {
|
||||
pub fn snapshot(&self, cx: &mut ModelContext<Self>) -> 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);
|
||||
let wraps_snapshot = self
|
||||
.wrap_map
|
||||
.update(cx, |map, cx| map.sync(tabs_snapshot.clone(), edits, cx));
|
||||
DisplayMapSnapshot {
|
||||
buffer_snapshot: self.buffer.read(cx).snapshot(),
|
||||
folds_snapshot,
|
||||
@ -52,35 +58,36 @@ impl DisplayMap {
|
||||
pub fn fold<T: ToOffset>(
|
||||
&mut self,
|
||||
ranges: impl IntoIterator<Item = Range<T>>,
|
||||
cx: &mut MutableAppContext,
|
||||
cx: &mut ModelContext<Self>,
|
||||
) {
|
||||
let (mut fold_map, snapshot, edits) = self.fold_map.write(cx);
|
||||
let (snapshot, edits) = self.tab_map.sync(snapshot, edits);
|
||||
self.wrap_map.sync(snapshot, edits, cx);
|
||||
self.wrap_map
|
||||
.update(cx, |map, cx| 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);
|
||||
self.wrap_map
|
||||
.update(cx, |map, cx| map.sync(snapshot, edits, cx));
|
||||
}
|
||||
|
||||
pub fn unfold<T: ToOffset>(
|
||||
&mut self,
|
||||
ranges: impl IntoIterator<Item = Range<T>>,
|
||||
cx: &mut MutableAppContext,
|
||||
cx: &mut ModelContext<Self>,
|
||||
) {
|
||||
let (mut fold_map, snapshot, edits) = self.fold_map.write(cx);
|
||||
let (snapshot, edits) = self.tab_map.sync(snapshot, edits);
|
||||
self.wrap_map.sync(snapshot, edits, cx);
|
||||
self.wrap_map
|
||||
.update(cx, |map, cx| 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);
|
||||
self.wrap_map
|
||||
.update(cx, |map, cx| map.sync(snapshot, edits, cx));
|
||||
}
|
||||
|
||||
pub fn set_wrap_width(&self, width: Option<f32>, cx: &mut MutableAppContext) -> bool {
|
||||
self.wrap_map.set_wrap_width(width, cx)
|
||||
}
|
||||
|
||||
pub fn notifications(&self) -> impl Stream<Item = ()> {
|
||||
self.wrap_map.notifications()
|
||||
pub fn set_wrap_width(&self, width: Option<f32>, cx: &mut ModelContext<Self>) -> bool {
|
||||
self.wrap_map
|
||||
.update(cx, |map, cx| map.set_wrap_width(width, cx))
|
||||
}
|
||||
}
|
||||
|
||||
@ -282,6 +289,7 @@ mod tests {
|
||||
util::RandomCharIter,
|
||||
};
|
||||
use buffer::History;
|
||||
use gpui::MutableAppContext;
|
||||
use rand::prelude::*;
|
||||
use std::{env, sync::Arc};
|
||||
|
||||
@ -321,11 +329,11 @@ mod tests {
|
||||
Buffer::new(0, text, cx)
|
||||
});
|
||||
let wrap_width = Some(rng.gen_range(20.0..=100.0));
|
||||
let map = cx.update(|cx| DisplayMap::new(buffer.clone(), settings, wrap_width, cx));
|
||||
let map = cx.add_model(|cx| DisplayMap::new(buffer.clone(), settings, wrap_width, cx));
|
||||
|
||||
for _op_ix in 0..operations {
|
||||
buffer.update(&mut cx, |buffer, cx| buffer.randomly_mutate(&mut rng, cx));
|
||||
let snapshot = cx.update(|cx| map.snapshot(cx));
|
||||
let snapshot = map.update(&mut cx, |map, cx| map.snapshot(cx));
|
||||
let expected_buffer_rows = (0..=snapshot.max_point().row())
|
||||
.map(|display_row| {
|
||||
DisplayPoint::new(display_row, 0)
|
||||
@ -366,9 +374,9 @@ mod tests {
|
||||
|
||||
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.update(|cx| DisplayMap::new(buffer.clone(), settings, wrap_width, cx));
|
||||
let map = cx.add_model(|cx| DisplayMap::new(buffer.clone(), settings, wrap_width, cx));
|
||||
|
||||
let snapshot = cx.update(|cx| map.snapshot(cx));
|
||||
let snapshot = map.update(&mut cx, |map, cx| map.snapshot(cx));
|
||||
assert_eq!(
|
||||
snapshot
|
||||
.chunks_at(DisplayPoint::new(0, 3))
|
||||
@ -389,7 +397,7 @@ mod tests {
|
||||
buffer.edit(vec![ix..ix], "and ", cx);
|
||||
});
|
||||
|
||||
let snapshot = cx.update(|cx| map.snapshot(cx));
|
||||
let snapshot = map.update(&mut cx, |map, cx| map.snapshot(cx));
|
||||
assert_eq!(
|
||||
snapshot
|
||||
.chunks_at(DisplayPoint::new(1, 0))
|
||||
@ -402,12 +410,14 @@ mod tests {
|
||||
fn test_chunks_at(cx: &mut gpui::MutableAppContext) {
|
||||
let text = sample_text(6, 6);
|
||||
let buffer = cx.add_model(|cx| Buffer::new(0, text, cx));
|
||||
let map = DisplayMap::new(
|
||||
buffer.clone(),
|
||||
Settings::new(cx.font_cache()).unwrap().with_tab_size(4),
|
||||
None,
|
||||
cx,
|
||||
);
|
||||
let map = cx.add_model(|cx| {
|
||||
DisplayMap::new(
|
||||
buffer.clone(),
|
||||
Settings::new(cx.font_cache()).unwrap().with_tab_size(4),
|
||||
None,
|
||||
cx,
|
||||
)
|
||||
});
|
||||
buffer.update(cx, |buffer, cx| {
|
||||
buffer.edit(
|
||||
vec![
|
||||
@ -421,19 +431,19 @@ mod tests {
|
||||
});
|
||||
|
||||
assert_eq!(
|
||||
&map.snapshot(cx)
|
||||
&map.update(cx, |map, cx| map.snapshot(cx))
|
||||
.chunks_at(DisplayPoint::new(1, 0))
|
||||
.collect::<String>()[0..10],
|
||||
" b bb"
|
||||
);
|
||||
assert_eq!(
|
||||
&map.snapshot(cx)
|
||||
&map.update(cx, |map, cx| map.snapshot(cx))
|
||||
.chunks_at(DisplayPoint::new(1, 2))
|
||||
.collect::<String>()[0..10],
|
||||
" b bbbb"
|
||||
);
|
||||
assert_eq!(
|
||||
&map.snapshot(cx)
|
||||
&map.update(cx, |map, cx| map.snapshot(cx))
|
||||
.chunks_at(DisplayPoint::new(1, 6))
|
||||
.collect::<String>()[0..13],
|
||||
" bbbbb\nc c"
|
||||
@ -484,7 +494,7 @@ mod tests {
|
||||
});
|
||||
buffer.condition(&cx, |buf, _| !buf.is_parsing()).await;
|
||||
|
||||
let mut map = cx.update(|cx| {
|
||||
let map = cx.add_model(|cx| {
|
||||
DisplayMap::new(
|
||||
buffer,
|
||||
Settings::new(cx.font_cache()).unwrap().with_tab_size(2),
|
||||
@ -512,7 +522,9 @@ mod tests {
|
||||
]
|
||||
);
|
||||
|
||||
cx.update(|cx| map.fold(vec![Point::new(0, 6)..Point::new(3, 2)], cx));
|
||||
map.update(&mut cx, |map, cx| {
|
||||
map.fold(vec![Point::new(0, 6)..Point::new(3, 2)], cx)
|
||||
});
|
||||
assert_eq!(
|
||||
cx.update(|cx| highlighted_chunks(0..2, &map, &theme, cx)),
|
||||
vec![
|
||||
@ -579,7 +591,7 @@ mod tests {
|
||||
buffer_font_size: 16.0,
|
||||
..Settings::new(&font_cache).unwrap()
|
||||
};
|
||||
let mut map = cx.update(|cx| DisplayMap::new(buffer, settings, Some(40.0), cx));
|
||||
let map = cx.add_model(|cx| DisplayMap::new(buffer, settings, Some(40.0), cx));
|
||||
assert_eq!(
|
||||
cx.update(|cx| highlighted_chunks(0..5, &map, &theme, cx)),
|
||||
[
|
||||
@ -593,7 +605,9 @@ mod tests {
|
||||
[("{}\n\n".to_string(), None)]
|
||||
);
|
||||
|
||||
cx.update(|cx| map.fold(vec![Point::new(0, 6)..Point::new(3, 2)], cx));
|
||||
map.update(&mut cx, |map, cx| {
|
||||
map.fold(vec![Point::new(0, 6)..Point::new(3, 2)], cx)
|
||||
});
|
||||
assert_eq!(
|
||||
cx.update(|cx| highlighted_chunks(1..4, &map, &theme, cx)),
|
||||
[
|
||||
@ -611,13 +625,15 @@ mod tests {
|
||||
let text = "\n'a', 'α',\t'✋',\t'❎', '🍐'\n";
|
||||
let display_text = "\n'a', 'α', '✋', '❎', '🍐'\n";
|
||||
let buffer = cx.add_model(|cx| Buffer::new(0, text, cx));
|
||||
let map = DisplayMap::new(
|
||||
buffer.clone(),
|
||||
Settings::new(cx.font_cache()).unwrap().with_tab_size(4),
|
||||
None,
|
||||
cx,
|
||||
);
|
||||
let map = map.snapshot(cx);
|
||||
let map = cx.add_model(|cx| {
|
||||
DisplayMap::new(
|
||||
buffer.clone(),
|
||||
Settings::new(cx.font_cache()).unwrap().with_tab_size(4),
|
||||
None,
|
||||
cx,
|
||||
)
|
||||
});
|
||||
let map = map.update(cx, |map, cx| map.snapshot(cx));
|
||||
|
||||
assert_eq!(map.text(), display_text);
|
||||
for (input_column, bias, output_column) in vec![
|
||||
@ -650,13 +666,15 @@ mod tests {
|
||||
fn test_tabs_with_multibyte_chars(cx: &mut gpui::MutableAppContext) {
|
||||
let text = "✅\t\tα\nβ\t\n🏀β\t\tγ";
|
||||
let buffer = cx.add_model(|cx| Buffer::new(0, text, cx));
|
||||
let map = DisplayMap::new(
|
||||
buffer.clone(),
|
||||
Settings::new(cx.font_cache()).unwrap().with_tab_size(4),
|
||||
None,
|
||||
cx,
|
||||
);
|
||||
let map = map.snapshot(cx);
|
||||
let map = cx.add_model(|cx| {
|
||||
DisplayMap::new(
|
||||
buffer.clone(),
|
||||
Settings::new(cx.font_cache()).unwrap().with_tab_size(4),
|
||||
None,
|
||||
cx,
|
||||
)
|
||||
});
|
||||
let map = map.update(cx, |map, cx| map.snapshot(cx));
|
||||
assert_eq!(map.text(), "✅ α\nβ \n🏀β γ");
|
||||
|
||||
let point = Point::new(0, "✅\t\t".len() as u32);
|
||||
@ -716,23 +734,29 @@ mod tests {
|
||||
#[gpui::test]
|
||||
fn test_max_point(cx: &mut gpui::MutableAppContext) {
|
||||
let buffer = cx.add_model(|cx| Buffer::new(0, "aaa\n\t\tbbb", cx));
|
||||
let map = DisplayMap::new(
|
||||
buffer.clone(),
|
||||
Settings::new(cx.font_cache()).unwrap().with_tab_size(4),
|
||||
None,
|
||||
cx,
|
||||
);
|
||||
assert_eq!(map.snapshot(cx).max_point(), DisplayPoint::new(1, 11))
|
||||
let map = cx.add_model(|cx| {
|
||||
DisplayMap::new(
|
||||
buffer.clone(),
|
||||
Settings::new(cx.font_cache()).unwrap().with_tab_size(4),
|
||||
None,
|
||||
cx,
|
||||
)
|
||||
});
|
||||
assert_eq!(
|
||||
map.update(cx, |map, cx| map.snapshot(cx)).max_point(),
|
||||
DisplayPoint::new(1, 11)
|
||||
)
|
||||
}
|
||||
|
||||
fn highlighted_chunks<'a>(
|
||||
rows: Range<u32>,
|
||||
map: &DisplayMap,
|
||||
map: &ModelHandle<DisplayMap>,
|
||||
theme: &'a Theme,
|
||||
cx: &mut MutableAppContext,
|
||||
) -> Vec<(String, Option<&'a str>)> {
|
||||
let mut snapshot = map.update(cx, |map, cx| map.snapshot(cx));
|
||||
let mut chunks: Vec<(String, Option<&str>)> = Vec::new();
|
||||
for (chunk, style_id) in map.snapshot(cx).highlighted_chunks_for_rows(rows) {
|
||||
for (chunk, style_id) in snapshot.highlighted_chunks_for_rows(rows) {
|
||||
let style_name = theme.syntax_style_name(style_id);
|
||||
if let Some((last_chunk, last_style_name)) = chunks.last_mut() {
|
||||
if style_name == *last_style_name {
|
||||
|
@ -10,24 +10,22 @@ use crate::{
|
||||
util::Bias,
|
||||
Settings,
|
||||
};
|
||||
use gpui::{MutableAppContext, Task};
|
||||
use parking_lot::Mutex;
|
||||
use postage::{prelude::Stream, sink::Sink, watch};
|
||||
use gpui::{Entity, ModelContext, Task};
|
||||
use smol::future::yield_now;
|
||||
use std::{collections::VecDeque, ops::Range, sync::Arc, time::Duration};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct WrapMap(Arc<Mutex<WrapMapState>>);
|
||||
|
||||
struct WrapMapState {
|
||||
pub struct WrapMap {
|
||||
snapshot: Snapshot,
|
||||
pending_edits: VecDeque<(TabSnapshot, Vec<TabEdit>)>,
|
||||
wrap_width: Option<f32>,
|
||||
background_task: Option<Task<()>>,
|
||||
updates: (watch::Sender<()>, watch::Receiver<()>),
|
||||
line_wrapper: Arc<LineWrapper>,
|
||||
}
|
||||
|
||||
impl Entity for WrapMap {
|
||||
type Event = ();
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Snapshot {
|
||||
tab_snapshot: TabSnapshot,
|
||||
@ -78,12 +76,11 @@ impl WrapMap {
|
||||
tab_snapshot: TabSnapshot,
|
||||
settings: Settings,
|
||||
wrap_width: Option<f32>,
|
||||
cx: &mut MutableAppContext,
|
||||
cx: &mut ModelContext<Self>,
|
||||
) -> Self {
|
||||
let this = Self(Arc::new(Mutex::new(WrapMapState {
|
||||
let mut this = Self {
|
||||
background_task: None,
|
||||
wrap_width: None,
|
||||
updates: watch::channel(),
|
||||
pending_edits: Default::default(),
|
||||
snapshot: Snapshot::new(tab_snapshot),
|
||||
line_wrapper: Arc::new(LineWrapper::new(
|
||||
@ -91,49 +88,38 @@ impl WrapMap {
|
||||
cx.font_cache(),
|
||||
settings,
|
||||
)),
|
||||
})));
|
||||
};
|
||||
this.set_wrap_width(wrap_width, cx);
|
||||
this
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub fn is_rewrapping(&self) -> bool {
|
||||
self.0.lock().background_task.is_some()
|
||||
}
|
||||
|
||||
pub fn notifications(&self) -> impl Stream<Item = ()> {
|
||||
let state = self.0.lock();
|
||||
let mut rx = state.updates.1.clone();
|
||||
// The first item in the stream always returns what's stored on the watch, but we only want
|
||||
// to receive notifications occurring after calling this method, so we discard the first
|
||||
// item.
|
||||
let _ = rx.blocking_recv();
|
||||
rx
|
||||
self.background_task.is_some()
|
||||
}
|
||||
|
||||
pub fn sync(
|
||||
&self,
|
||||
&mut self,
|
||||
tab_snapshot: TabSnapshot,
|
||||
edits: Vec<TabEdit>,
|
||||
cx: &mut MutableAppContext,
|
||||
cx: &mut ModelContext<Self>,
|
||||
) -> Snapshot {
|
||||
self.0.lock().pending_edits.push_back((tab_snapshot, edits));
|
||||
self.pending_edits.push_back((tab_snapshot, edits));
|
||||
self.flush_edits(cx);
|
||||
self.0.lock().snapshot.clone()
|
||||
self.snapshot.clone()
|
||||
}
|
||||
|
||||
pub fn set_wrap_width(&self, wrap_width: Option<f32>, cx: &mut MutableAppContext) -> bool {
|
||||
let mut state = self.0.lock();
|
||||
if wrap_width == state.wrap_width {
|
||||
pub fn set_wrap_width(&mut self, wrap_width: Option<f32>, cx: &mut ModelContext<Self>) -> bool {
|
||||
if wrap_width == self.wrap_width {
|
||||
return false;
|
||||
}
|
||||
|
||||
state.wrap_width = wrap_width;
|
||||
state.background_task.take();
|
||||
self.wrap_width = wrap_width;
|
||||
self.background_task.take();
|
||||
|
||||
if let Some(wrap_width) = wrap_width {
|
||||
let mut new_snapshot = state.snapshot.clone();
|
||||
let line_wrapper = state.line_wrapper.clone();
|
||||
let mut new_snapshot = self.snapshot.clone();
|
||||
let line_wrapper = self.line_wrapper.clone();
|
||||
let task = cx.background().spawn(async move {
|
||||
let tab_snapshot = new_snapshot.tab_snapshot.clone();
|
||||
let range = TabPoint::zero()..tab_snapshot.max_point();
|
||||
@ -156,19 +142,17 @@ impl WrapMap {
|
||||
.block_with_timeout(Duration::from_millis(5), task)
|
||||
{
|
||||
Ok(snapshot) => {
|
||||
state.snapshot = snapshot;
|
||||
self.snapshot = snapshot;
|
||||
}
|
||||
Err(wrap_task) => {
|
||||
let this = self.clone();
|
||||
state.background_task = Some(cx.spawn(|mut cx| async move {
|
||||
self.background_task = Some(cx.spawn(|this, mut cx| async move {
|
||||
let snapshot = wrap_task.await;
|
||||
{
|
||||
let mut state = this.0.lock();
|
||||
state.snapshot = snapshot;
|
||||
state.background_task = None;
|
||||
}
|
||||
cx.update(|cx| this.flush_edits(cx));
|
||||
this.0.lock().updates.0.blocking_send(()).ok();
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.snapshot = snapshot;
|
||||
this.background_task = None;
|
||||
this.flush_edits(cx);
|
||||
cx.notify();
|
||||
});
|
||||
}));
|
||||
}
|
||||
}
|
||||
@ -177,26 +161,24 @@ impl WrapMap {
|
||||
true
|
||||
}
|
||||
|
||||
fn flush_edits(&self, cx: &mut MutableAppContext) {
|
||||
let mut state = self.0.lock();
|
||||
|
||||
while let Some((tab_snapshot, _)) = state.pending_edits.front() {
|
||||
if tab_snapshot.version() <= state.snapshot.tab_snapshot.version() {
|
||||
state.pending_edits.pop_front();
|
||||
fn flush_edits(&mut self, cx: &mut ModelContext<Self>) {
|
||||
while let Some((tab_snapshot, _)) = self.pending_edits.front() {
|
||||
if tab_snapshot.version() <= self.snapshot.tab_snapshot.version() {
|
||||
self.pending_edits.pop_front();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if state.pending_edits.is_empty() {
|
||||
if self.pending_edits.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
if let Some(wrap_width) = state.wrap_width {
|
||||
if state.background_task.is_none() {
|
||||
let pending_edits = state.pending_edits.clone();
|
||||
let mut snapshot = state.snapshot.clone();
|
||||
let line_wrapper = state.line_wrapper.clone();
|
||||
if let Some(wrap_width) = self.wrap_width {
|
||||
if self.background_task.is_none() {
|
||||
let pending_edits = self.pending_edits.clone();
|
||||
let mut snapshot = self.snapshot.clone();
|
||||
let line_wrapper = self.line_wrapper.clone();
|
||||
|
||||
let update_task = cx.background().spawn(async move {
|
||||
for (tab_snapshot, edits) in pending_edits {
|
||||
@ -212,35 +194,33 @@ impl WrapMap {
|
||||
.block_with_timeout(Duration::from_micros(500), update_task)
|
||||
{
|
||||
Ok(snapshot) => {
|
||||
state.snapshot = snapshot;
|
||||
self.snapshot = snapshot;
|
||||
}
|
||||
Err(update_task) => {
|
||||
let this = self.clone();
|
||||
state.background_task = Some(cx.spawn(|mut cx| async move {
|
||||
self.background_task = Some(cx.spawn(|this, mut cx| async move {
|
||||
let snapshot = update_task.await;
|
||||
{
|
||||
let mut state = this.0.lock();
|
||||
state.snapshot = snapshot;
|
||||
state.background_task = None;
|
||||
}
|
||||
cx.update(|cx| this.flush_edits(cx));
|
||||
this.0.lock().updates.0.blocking_send(()).ok();
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.snapshot = snapshot;
|
||||
this.background_task = None;
|
||||
this.flush_edits(cx);
|
||||
cx.notify();
|
||||
});
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while let Some((tab_snapshot, _)) = state.pending_edits.front() {
|
||||
if tab_snapshot.version() <= state.snapshot.tab_snapshot.version() {
|
||||
state.pending_edits.pop_front();
|
||||
while let Some((tab_snapshot, _)) = self.pending_edits.front() {
|
||||
if tab_snapshot.version() <= self.snapshot.tab_snapshot.version() {
|
||||
self.pending_edits.pop_front();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (tab_snapshot, edits) in state.pending_edits.clone() {
|
||||
state.snapshot.interpolate(tab_snapshot, &edits);
|
||||
for (tab_snapshot, edits) in self.pending_edits.clone() {
|
||||
self.snapshot.interpolate(tab_snapshot, &edits);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -769,7 +749,9 @@ mod tests {
|
||||
},
|
||||
util::RandomCharIter,
|
||||
};
|
||||
use gpui::ModelHandle;
|
||||
use rand::prelude::*;
|
||||
use smol::channel;
|
||||
use std::env;
|
||||
|
||||
#[gpui::test]
|
||||
@ -816,7 +798,7 @@ mod tests {
|
||||
folds_snapshot.text()
|
||||
);
|
||||
log::info!("Unwrapped text (expanded tabs): {:?}", tabs_snapshot.text());
|
||||
let wrap_map = cx.update(|cx| {
|
||||
let wrap_map = cx.add_model(|cx| {
|
||||
WrapMap::new(
|
||||
tabs_snapshot.clone(),
|
||||
settings.clone(),
|
||||
@ -824,17 +806,18 @@ mod tests {
|
||||
cx,
|
||||
)
|
||||
});
|
||||
let mut notifications = wrap_map.notifications();
|
||||
let (_observer, notifications) = Observer::new(&wrap_map, &mut cx);
|
||||
|
||||
let mut line_wrapper = LineWrapper::new(font_system, &font_cache, settings);
|
||||
let unwrapped_text = tabs_snapshot.text();
|
||||
let expected_text = wrap_text(&unwrapped_text, wrap_width, &mut line_wrapper);
|
||||
|
||||
if wrap_map.is_rewrapping() {
|
||||
notifications.recv().await;
|
||||
if wrap_map.read_with(&cx, |map, _| map.is_rewrapping()) {
|
||||
notifications.recv().await.unwrap();
|
||||
}
|
||||
|
||||
let snapshot = cx.update(|cx| wrap_map.sync(tabs_snapshot, Vec::new(), cx));
|
||||
let snapshot =
|
||||
wrap_map.update(&mut cx, |map, cx| map.sync(tabs_snapshot, Vec::new(), cx));
|
||||
let actual_text = snapshot.text();
|
||||
assert_eq!(
|
||||
actual_text, expected_text,
|
||||
@ -858,12 +841,15 @@ mod tests {
|
||||
|
||||
let unwrapped_text = tabs_snapshot.text();
|
||||
let expected_text = wrap_text(&unwrapped_text, wrap_width, &mut line_wrapper);
|
||||
let mut snapshot = cx.update(|cx| wrap_map.sync(tabs_snapshot.clone(), edits, cx));
|
||||
let mut snapshot = wrap_map.update(&mut cx, |map, cx| {
|
||||
map.sync(tabs_snapshot.clone(), edits, cx)
|
||||
});
|
||||
snapshot.check_invariants(&mut rng);
|
||||
|
||||
if wrap_map.is_rewrapping() {
|
||||
notifications.recv().await;
|
||||
snapshot = cx.update(|cx| wrap_map.sync(tabs_snapshot, Vec::new(), cx));
|
||||
if wrap_map.read_with(&cx, |map, _| map.is_rewrapping()) {
|
||||
notifications.recv().await.unwrap();
|
||||
snapshot =
|
||||
wrap_map.update(&mut cx, |map, cx| map.sync(tabs_snapshot, Vec::new(), cx));
|
||||
}
|
||||
|
||||
snapshot.check_invariants(&mut rng);
|
||||
@ -952,4 +938,26 @@ mod tests {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct Observer;
|
||||
|
||||
impl Entity for Observer {
|
||||
type Event = ();
|
||||
}
|
||||
|
||||
impl Observer {
|
||||
fn new(
|
||||
handle: &ModelHandle<WrapMap>,
|
||||
cx: &mut gpui::TestAppContext,
|
||||
) -> (ModelHandle<Self>, channel::Receiver<()>) {
|
||||
let (notify_tx, notify_rx) = channel::unbounded();
|
||||
let observer = cx.add_model(|cx| {
|
||||
cx.observe(handle, move |_, _, _| {
|
||||
let _ = notify_tx.try_send(());
|
||||
});
|
||||
Observer
|
||||
});
|
||||
(observer, notify_rx)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user