Get app running and test passing after gpui App+Platform restructure
This commit is contained in:
@@ -2193,13 +2193,13 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_edit_events() {
|
||||
App::test((), |mut app| async move {
|
||||
App::test((), |app| {
|
||||
let buffer_1_events = Rc::new(RefCell::new(Vec::new()));
|
||||
let buffer_2_events = Rc::new(RefCell::new(Vec::new()));
|
||||
|
||||
let buffer1 = app.add_model(|_| Buffer::new(0, "abcdef"));
|
||||
let buffer2 = app.add_model(|_| Buffer::new(1, "abcdef"));
|
||||
let ops = buffer1.update(&mut app, |buffer, ctx| {
|
||||
let ops = buffer1.update(app, |buffer, ctx| {
|
||||
let buffer_1_events = buffer_1_events.clone();
|
||||
ctx.subscribe(&buffer1, move |_, event, _| {
|
||||
buffer_1_events.borrow_mut().push(event.clone())
|
||||
@@ -2211,7 +2211,7 @@ mod tests {
|
||||
|
||||
buffer.edit(Some(2..4), "XYZ", Some(ctx)).unwrap()
|
||||
});
|
||||
buffer2.update(&mut app, |buffer, ctx| {
|
||||
buffer2.update(app, |buffer, ctx| {
|
||||
buffer.apply_ops(ops, Some(ctx)).unwrap();
|
||||
});
|
||||
|
||||
@@ -2715,12 +2715,12 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_is_modified() -> Result<()> {
|
||||
App::test((), |mut app| async move {
|
||||
App::test((), |app| {
|
||||
let model = app.add_model(|_| Buffer::new(0, "abc"));
|
||||
let events = Rc::new(RefCell::new(Vec::new()));
|
||||
|
||||
// initially, the buffer isn't dirty.
|
||||
model.update(&mut app, |buffer, ctx| {
|
||||
model.update(app, |buffer, ctx| {
|
||||
ctx.subscribe(&model, {
|
||||
let events = events.clone();
|
||||
move |_, event, _| events.borrow_mut().push(event.clone())
|
||||
@@ -2733,7 +2733,7 @@ mod tests {
|
||||
});
|
||||
|
||||
// after the first edit, the buffer is dirty, and emits a dirtied event.
|
||||
model.update(&mut app, |buffer, ctx| {
|
||||
model.update(app, |buffer, ctx| {
|
||||
assert!(buffer.text() == "ac");
|
||||
assert!(buffer.is_dirty());
|
||||
assert_eq!(
|
||||
@@ -2752,7 +2752,7 @@ mod tests {
|
||||
});
|
||||
|
||||
// after saving, the buffer is not dirty, and emits a saved event.
|
||||
model.update(&mut app, |buffer, ctx| {
|
||||
model.update(app, |buffer, ctx| {
|
||||
assert!(!buffer.is_dirty());
|
||||
assert_eq!(*events.borrow(), &[Event::Saved]);
|
||||
events.borrow_mut().clear();
|
||||
@@ -2762,7 +2762,7 @@ mod tests {
|
||||
});
|
||||
|
||||
// after editing again, the buffer is dirty, and emits another dirty event.
|
||||
model.update(&mut app, |buffer, ctx| {
|
||||
model.update(app, |buffer, ctx| {
|
||||
assert!(buffer.text() == "aBDc");
|
||||
assert!(buffer.is_dirty());
|
||||
assert_eq!(
|
||||
@@ -2788,7 +2788,7 @@ mod tests {
|
||||
assert!(buffer.is_dirty());
|
||||
});
|
||||
|
||||
model.update(&mut app, |_, _| {
|
||||
model.update(app, |_, _| {
|
||||
assert_eq!(
|
||||
*events.borrow(),
|
||||
&[Event::Edited(vec![Edit {
|
||||
|
||||
+106
-100
@@ -6,7 +6,7 @@ use crate::{settings::Settings, watch, workspace};
|
||||
use anyhow::Result;
|
||||
use futures_core::future::LocalBoxFuture;
|
||||
use gpui::{
|
||||
fonts::Properties as FontProperties, keymap::Binding, text_layout, App, AppContext, Element,
|
||||
fonts::Properties as FontProperties, keymap::Binding, text_layout, AppContext, Element,
|
||||
ElementBox, Entity, FontCache, ModelHandle, MutableAppContext, View, ViewContext,
|
||||
WeakViewHandle,
|
||||
};
|
||||
@@ -1240,112 +1240,125 @@ mod tests {
|
||||
use super::*;
|
||||
use crate::{editor::Point, settings, test::sample_text};
|
||||
use anyhow::Error;
|
||||
use gpui::App;
|
||||
use unindent::Unindent;
|
||||
|
||||
#[test]
|
||||
fn test_selection_with_mouse() {
|
||||
App::test((), |mut app| async move {
|
||||
App::test((), |app| {
|
||||
let buffer = app.add_model(|_| Buffer::new(0, "aaaaaa\nbbbbbb\ncccccc\ndddddd\n"));
|
||||
let settings = settings::channel(&app.font_cache()).unwrap().1;
|
||||
let (_, buffer_view) =
|
||||
app.add_window(|ctx| BufferView::for_buffer(buffer, settings, ctx));
|
||||
|
||||
buffer_view.update(&mut app, |view, ctx| {
|
||||
buffer_view.update(app, |view, ctx| {
|
||||
view.begin_selection(DisplayPoint::new(2, 2), false, ctx);
|
||||
});
|
||||
|
||||
buffer_view.read(&app, |view, app| {
|
||||
let selections = view
|
||||
.selections_in_range(DisplayPoint::zero()..view.max_point(app), app)
|
||||
.collect::<Vec<_>>();
|
||||
assert_eq!(
|
||||
selections,
|
||||
[DisplayPoint::new(2, 2)..DisplayPoint::new(2, 2)]
|
||||
);
|
||||
});
|
||||
let view = buffer_view.as_ref(app);
|
||||
let selections = view
|
||||
.selections_in_range(
|
||||
DisplayPoint::zero()..view.max_point(app.as_ref()),
|
||||
app.as_ref(),
|
||||
)
|
||||
.collect::<Vec<_>>();
|
||||
assert_eq!(
|
||||
selections,
|
||||
[DisplayPoint::new(2, 2)..DisplayPoint::new(2, 2)]
|
||||
);
|
||||
|
||||
buffer_view.update(&mut app, |view, ctx| {
|
||||
buffer_view.update(app, |view, ctx| {
|
||||
view.update_selection(DisplayPoint::new(3, 3), Vector2F::zero(), ctx);
|
||||
});
|
||||
|
||||
buffer_view.read(&app, |view, app| {
|
||||
let selections = view
|
||||
.selections_in_range(DisplayPoint::zero()..view.max_point(app), app)
|
||||
.collect::<Vec<_>>();
|
||||
assert_eq!(
|
||||
selections,
|
||||
[DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3)]
|
||||
);
|
||||
});
|
||||
let view = buffer_view.as_ref(app);
|
||||
let selections = view
|
||||
.selections_in_range(
|
||||
DisplayPoint::zero()..view.max_point(app.as_ref()),
|
||||
app.as_ref(),
|
||||
)
|
||||
.collect::<Vec<_>>();
|
||||
assert_eq!(
|
||||
selections,
|
||||
[DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3)]
|
||||
);
|
||||
|
||||
buffer_view.update(&mut app, |view, ctx| {
|
||||
buffer_view.update(app, |view, ctx| {
|
||||
view.update_selection(DisplayPoint::new(1, 1), Vector2F::zero(), ctx);
|
||||
});
|
||||
|
||||
buffer_view.read(&app, |view, app| {
|
||||
let selections = view
|
||||
.selections_in_range(DisplayPoint::zero()..view.max_point(app), app)
|
||||
.collect::<Vec<_>>();
|
||||
assert_eq!(
|
||||
selections,
|
||||
[DisplayPoint::new(2, 2)..DisplayPoint::new(1, 1)]
|
||||
);
|
||||
});
|
||||
let view = buffer_view.as_ref(app);
|
||||
let selections = view
|
||||
.selections_in_range(
|
||||
DisplayPoint::zero()..view.max_point(app.as_ref()),
|
||||
app.as_ref(),
|
||||
)
|
||||
.collect::<Vec<_>>();
|
||||
assert_eq!(
|
||||
selections,
|
||||
[DisplayPoint::new(2, 2)..DisplayPoint::new(1, 1)]
|
||||
);
|
||||
|
||||
buffer_view.update(&mut app, |view, ctx| {
|
||||
buffer_view.update(app, |view, ctx| {
|
||||
view.end_selection(ctx);
|
||||
view.update_selection(DisplayPoint::new(3, 3), Vector2F::zero(), ctx);
|
||||
});
|
||||
|
||||
buffer_view.read(&app, |view, app| {
|
||||
let selections = view
|
||||
.selections_in_range(DisplayPoint::zero()..view.max_point(app), app)
|
||||
.collect::<Vec<_>>();
|
||||
assert_eq!(
|
||||
selections,
|
||||
[DisplayPoint::new(2, 2)..DisplayPoint::new(1, 1)]
|
||||
);
|
||||
});
|
||||
let view = buffer_view.as_ref(app);
|
||||
let selections = view
|
||||
.selections_in_range(
|
||||
DisplayPoint::zero()..view.max_point(app.as_ref()),
|
||||
app.as_ref(),
|
||||
)
|
||||
.collect::<Vec<_>>();
|
||||
assert_eq!(
|
||||
selections,
|
||||
[DisplayPoint::new(2, 2)..DisplayPoint::new(1, 1)]
|
||||
);
|
||||
|
||||
buffer_view.update(&mut app, |view, ctx| {
|
||||
buffer_view.update(app, |view, ctx| {
|
||||
view.begin_selection(DisplayPoint::new(3, 3), true, ctx);
|
||||
view.update_selection(DisplayPoint::new(0, 0), Vector2F::zero(), ctx);
|
||||
});
|
||||
|
||||
buffer_view.read(&app, |view, app| {
|
||||
let selections = view
|
||||
.selections_in_range(DisplayPoint::zero()..view.max_point(app), app)
|
||||
.collect::<Vec<_>>();
|
||||
assert_eq!(
|
||||
selections,
|
||||
[
|
||||
DisplayPoint::new(2, 2)..DisplayPoint::new(1, 1),
|
||||
DisplayPoint::new(3, 3)..DisplayPoint::new(0, 0)
|
||||
]
|
||||
);
|
||||
});
|
||||
let view = buffer_view.as_ref(app);
|
||||
let selections = view
|
||||
.selections_in_range(
|
||||
DisplayPoint::zero()..view.max_point(app.as_ref()),
|
||||
app.as_ref(),
|
||||
)
|
||||
.collect::<Vec<_>>();
|
||||
assert_eq!(
|
||||
selections,
|
||||
[
|
||||
DisplayPoint::new(2, 2)..DisplayPoint::new(1, 1),
|
||||
DisplayPoint::new(3, 3)..DisplayPoint::new(0, 0)
|
||||
]
|
||||
);
|
||||
|
||||
buffer_view.update(&mut app, |view, ctx| {
|
||||
buffer_view.update(app, |view, ctx| {
|
||||
view.end_selection(ctx);
|
||||
});
|
||||
|
||||
buffer_view.read(&app, |view, app| {
|
||||
let selections = view
|
||||
.selections_in_range(DisplayPoint::zero()..view.max_point(app), app)
|
||||
.collect::<Vec<_>>();
|
||||
assert_eq!(
|
||||
selections,
|
||||
[DisplayPoint::new(3, 3)..DisplayPoint::new(0, 0)]
|
||||
);
|
||||
});
|
||||
let view = buffer_view.as_ref(app);
|
||||
let selections = view
|
||||
.selections_in_range(
|
||||
DisplayPoint::zero()..view.max_point(app.as_ref()),
|
||||
app.as_ref(),
|
||||
)
|
||||
.collect::<Vec<_>>();
|
||||
assert_eq!(
|
||||
selections,
|
||||
[DisplayPoint::new(3, 3)..DisplayPoint::new(0, 0)]
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_layout_line_numbers() -> Result<()> {
|
||||
App::test((), |mut app| async move {
|
||||
fn test_layout_line_numbers() {
|
||||
App::test((), |app| {
|
||||
let layout_cache = TextLayoutCache::new(app.platform().fonts());
|
||||
let font_cache = app.font_cache();
|
||||
let font_cache = app.font_cache().clone();
|
||||
|
||||
let buffer = app.add_model(|_| Buffer::new(0, sample_text(6, 6)));
|
||||
|
||||
@@ -1353,19 +1366,17 @@ mod tests {
|
||||
let (_, view) =
|
||||
app.add_window(|ctx| BufferView::for_buffer(buffer.clone(), settings, ctx));
|
||||
|
||||
view.read(&app, |view, app| {
|
||||
let layouts = view.layout_line_numbers(1000.0, &font_cache, &layout_cache, app)?;
|
||||
assert_eq!(layouts.len(), 6);
|
||||
Result::<()>::Ok(())
|
||||
})?;
|
||||
|
||||
Ok(())
|
||||
let layouts = view
|
||||
.as_ref(app)
|
||||
.layout_line_numbers(1000.0, &font_cache, &layout_cache, app.as_ref())
|
||||
.unwrap();
|
||||
assert_eq!(layouts.len(), 6);
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fold() -> Result<()> {
|
||||
App::test((), |mut app| async move {
|
||||
fn test_fold() {
|
||||
App::test((), |app| {
|
||||
let buffer = app.add_model(|_| {
|
||||
Buffer::new(
|
||||
0,
|
||||
@@ -1393,8 +1404,9 @@ mod tests {
|
||||
let (_, view) =
|
||||
app.add_window(|ctx| BufferView::for_buffer(buffer.clone(), settings, ctx));
|
||||
|
||||
view.update(&mut app, |view, ctx| {
|
||||
view.select_ranges(&[DisplayPoint::new(8, 0)..DisplayPoint::new(12, 0)], ctx)?;
|
||||
view.update(app, |view, ctx| {
|
||||
view.select_ranges(&[DisplayPoint::new(8, 0)..DisplayPoint::new(12, 0)], ctx)
|
||||
.unwrap();
|
||||
view.fold(&(), ctx);
|
||||
assert_eq!(
|
||||
view.text(ctx.app()),
|
||||
@@ -1449,23 +1461,19 @@ mod tests {
|
||||
|
||||
view.unfold(&(), ctx);
|
||||
assert_eq!(view.text(ctx.app()), buffer.as_ref(ctx).text());
|
||||
|
||||
Ok::<(), Error>(())
|
||||
})?;
|
||||
|
||||
Ok(())
|
||||
})
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_move_cursor() -> Result<()> {
|
||||
App::test((), |mut app| async move {
|
||||
App::test((), |app| {
|
||||
let buffer = app.add_model(|_| Buffer::new(0, sample_text(6, 6)));
|
||||
let settings = settings::channel(&app.font_cache()).unwrap().1;
|
||||
let (_, view) =
|
||||
app.add_window(|ctx| BufferView::for_buffer(buffer.clone(), settings, ctx));
|
||||
|
||||
buffer.update(&mut app, |buffer, ctx| {
|
||||
buffer.update(app, |buffer, ctx| {
|
||||
buffer.edit(
|
||||
vec![
|
||||
Point::new(1, 0)..Point::new(1, 0),
|
||||
@@ -1476,7 +1484,7 @@ mod tests {
|
||||
)
|
||||
})?;
|
||||
|
||||
view.update(&mut app, |view, ctx| {
|
||||
view.update(app, |view, ctx| {
|
||||
view.move_down(&(), ctx);
|
||||
assert_eq!(
|
||||
view.selections(ctx.app()),
|
||||
@@ -1495,8 +1503,8 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_backspace() -> Result<()> {
|
||||
App::test((), |mut app| async move {
|
||||
fn test_backspace() {
|
||||
App::test((), |app| {
|
||||
let buffer = app.add_model(|_| {
|
||||
Buffer::new(0, "one two three\nfour five six\nseven eight nine\nten\n")
|
||||
});
|
||||
@@ -1504,7 +1512,7 @@ mod tests {
|
||||
let (_, view) =
|
||||
app.add_window(|ctx| BufferView::for_buffer(buffer.clone(), settings, ctx));
|
||||
|
||||
view.update(&mut app, |view, ctx| -> Result<()> {
|
||||
view.update(app, |view, ctx| {
|
||||
view.select_ranges(
|
||||
&[
|
||||
// an empty selection - the preceding character is deleted
|
||||
@@ -1515,17 +1523,15 @@ mod tests {
|
||||
DisplayPoint::new(2, 6)..DisplayPoint::new(3, 0),
|
||||
],
|
||||
ctx,
|
||||
)?;
|
||||
)
|
||||
.unwrap();
|
||||
view.backspace(&(), ctx);
|
||||
Ok(())
|
||||
})?;
|
||||
});
|
||||
|
||||
buffer.read(&mut app, |buffer, _| -> Result<()> {
|
||||
assert_eq!(buffer.text(), "oe two three\nfou five six\nseven ten\n");
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
Ok(())
|
||||
assert_eq!(
|
||||
buffer.as_ref(app).text(),
|
||||
"oe two three\nfou five six\nseven ten\n"
|
||||
);
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -469,115 +469,106 @@ mod tests {
|
||||
use gpui::App;
|
||||
|
||||
#[test]
|
||||
fn test_basic_folds() -> Result<()> {
|
||||
App::test((), |mut app| async move {
|
||||
fn test_basic_folds() {
|
||||
App::test((), |app| {
|
||||
let buffer = app.add_model(|_| Buffer::new(0, sample_text(5, 6)));
|
||||
let mut map = app.read(|app| FoldMap::new(buffer.clone(), app));
|
||||
let mut map = FoldMap::new(buffer.clone(), app.as_ref());
|
||||
|
||||
app.read(|app| {
|
||||
map.fold(
|
||||
vec![
|
||||
Point::new(0, 2)..Point::new(2, 2),
|
||||
Point::new(2, 4)..Point::new(4, 1),
|
||||
],
|
||||
app,
|
||||
)?;
|
||||
assert_eq!(map.text(app), "aa…cc…eeeee");
|
||||
Ok::<(), anyhow::Error>(())
|
||||
})?;
|
||||
map.fold(
|
||||
vec![
|
||||
Point::new(0, 2)..Point::new(2, 2),
|
||||
Point::new(2, 4)..Point::new(4, 1),
|
||||
],
|
||||
app.as_ref(),
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(map.text(app.as_ref()), "aa…cc…eeeee");
|
||||
|
||||
let edits = buffer.update(&mut app, |buffer, ctx| {
|
||||
let edits = buffer.update(app, |buffer, ctx| {
|
||||
let start_version = buffer.version.clone();
|
||||
buffer.edit(
|
||||
vec![
|
||||
Point::new(0, 0)..Point::new(0, 1),
|
||||
Point::new(2, 3)..Point::new(2, 3),
|
||||
],
|
||||
"123",
|
||||
Some(ctx),
|
||||
)?;
|
||||
Ok::<_, anyhow::Error>(buffer.edits_since(start_version).collect::<Vec<_>>())
|
||||
})?;
|
||||
buffer
|
||||
.edit(
|
||||
vec![
|
||||
Point::new(0, 0)..Point::new(0, 1),
|
||||
Point::new(2, 3)..Point::new(2, 3),
|
||||
],
|
||||
"123",
|
||||
Some(ctx),
|
||||
)
|
||||
.unwrap();
|
||||
buffer.edits_since(start_version).collect::<Vec<_>>()
|
||||
});
|
||||
|
||||
app.read(|app| {
|
||||
map.apply_edits(&edits, app)?;
|
||||
assert_eq!(map.text(app), "123a…c123c…eeeee");
|
||||
Ok::<(), anyhow::Error>(())
|
||||
})?;
|
||||
map.apply_edits(&edits, app.as_ref()).unwrap();
|
||||
assert_eq!(map.text(app.as_ref()), "123a…c123c…eeeee");
|
||||
|
||||
let edits = buffer.update(&mut app, |buffer, ctx| {
|
||||
let edits = buffer.update(app, |buffer, ctx| {
|
||||
let start_version = buffer.version.clone();
|
||||
buffer.edit(Some(Point::new(2, 6)..Point::new(4, 3)), "456", Some(ctx))?;
|
||||
Ok::<_, anyhow::Error>(buffer.edits_since(start_version).collect::<Vec<_>>())
|
||||
})?;
|
||||
buffer
|
||||
.edit(Some(Point::new(2, 6)..Point::new(4, 3)), "456", Some(ctx))
|
||||
.unwrap();
|
||||
buffer.edits_since(start_version).collect::<Vec<_>>()
|
||||
});
|
||||
|
||||
app.read(|app| {
|
||||
map.apply_edits(&edits, app)?;
|
||||
assert_eq!(map.text(app), "123a…c123456eee");
|
||||
map.apply_edits(&edits, app.as_ref()).unwrap();
|
||||
assert_eq!(map.text(app.as_ref()), "123a…c123456eee");
|
||||
|
||||
map.unfold(Some(Point::new(0, 4)..Point::new(0, 4)), app)?;
|
||||
assert_eq!(map.text(app), "123aaaaa\nbbbbbb\nccc123456eee");
|
||||
map.unfold(Some(Point::new(0, 4)..Point::new(0, 4)), app.as_ref())
|
||||
.unwrap();
|
||||
assert_eq!(map.text(app.as_ref()), "123aaaaa\nbbbbbb\nccc123456eee");
|
||||
});
|
||||
}
|
||||
|
||||
Ok(())
|
||||
})
|
||||
#[test]
|
||||
fn test_overlapping_folds() {
|
||||
App::test((), |app| {
|
||||
let buffer = app.add_model(|_| Buffer::new(0, sample_text(5, 6)));
|
||||
let mut map = FoldMap::new(buffer.clone(), app.as_ref());
|
||||
map.fold(
|
||||
vec![
|
||||
Point::new(0, 2)..Point::new(2, 2),
|
||||
Point::new(0, 4)..Point::new(1, 0),
|
||||
Point::new(1, 2)..Point::new(3, 2),
|
||||
Point::new(3, 1)..Point::new(4, 1),
|
||||
],
|
||||
app.as_ref(),
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(map.text(app.as_ref()), "aa…eeeee");
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_overlapping_folds() -> Result<()> {
|
||||
App::test((), |mut app| async move {
|
||||
fn test_merging_folds_via_edit() {
|
||||
App::test((), |app| {
|
||||
let buffer = app.add_model(|_| Buffer::new(0, sample_text(5, 6)));
|
||||
app.read(|app| {
|
||||
let mut map = FoldMap::new(buffer.clone(), app);
|
||||
map.fold(
|
||||
vec![
|
||||
Point::new(0, 2)..Point::new(2, 2),
|
||||
Point::new(0, 4)..Point::new(1, 0),
|
||||
Point::new(1, 2)..Point::new(3, 2),
|
||||
Point::new(3, 1)..Point::new(4, 1),
|
||||
],
|
||||
app,
|
||||
)?;
|
||||
assert_eq!(map.text(app), "aa…eeeee");
|
||||
Ok(())
|
||||
})
|
||||
})
|
||||
}
|
||||
let mut map = FoldMap::new(buffer.clone(), app.as_ref());
|
||||
|
||||
#[test]
|
||||
fn test_merging_folds_via_edit() -> Result<()> {
|
||||
App::test((), |mut app| async move {
|
||||
let buffer = app.add_model(|_| Buffer::new(0, sample_text(5, 6)));
|
||||
let mut map = app.read(|app| FoldMap::new(buffer.clone(), app));
|
||||
map.fold(
|
||||
vec![
|
||||
Point::new(0, 2)..Point::new(2, 2),
|
||||
Point::new(3, 1)..Point::new(4, 1),
|
||||
],
|
||||
app.as_ref(),
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(map.text(app.as_ref()), "aa…cccc\nd…eeeee");
|
||||
|
||||
app.read(|app| {
|
||||
map.fold(
|
||||
vec![
|
||||
Point::new(0, 2)..Point::new(2, 2),
|
||||
Point::new(3, 1)..Point::new(4, 1),
|
||||
],
|
||||
app,
|
||||
)?;
|
||||
assert_eq!(map.text(app), "aa…cccc\nd…eeeee");
|
||||
Ok::<(), anyhow::Error>(())
|
||||
})?;
|
||||
|
||||
let edits = buffer.update(&mut app, |buffer, ctx| {
|
||||
let edits = buffer.update(app, |buffer, ctx| {
|
||||
let start_version = buffer.version.clone();
|
||||
buffer.edit(Some(Point::new(2, 2)..Point::new(3, 1)), "", Some(ctx))?;
|
||||
Ok::<_, anyhow::Error>(buffer.edits_since(start_version).collect::<Vec<_>>())
|
||||
})?;
|
||||
buffer
|
||||
.edit(Some(Point::new(2, 2)..Point::new(3, 1)), "", Some(ctx))
|
||||
.unwrap();
|
||||
buffer.edits_since(start_version).collect::<Vec<_>>()
|
||||
});
|
||||
|
||||
app.read(|app| {
|
||||
map.apply_edits(&edits, app)?;
|
||||
assert_eq!(map.text(app), "aa…eeeee");
|
||||
Ok(())
|
||||
})
|
||||
})
|
||||
map.apply_edits(&edits, app.as_ref()).unwrap();
|
||||
assert_eq!(map.text(app.as_ref()), "aa…eeeee");
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_random_folds() -> Result<()> {
|
||||
fn test_random_folds() {
|
||||
use crate::editor::ToPoint;
|
||||
use crate::util::RandomCharIter;
|
||||
use rand::prelude::*;
|
||||
@@ -597,15 +588,15 @@ mod tests {
|
||||
println!("{:?}", seed);
|
||||
let mut rng = StdRng::seed_from_u64(seed);
|
||||
|
||||
App::test((), |mut app| async move {
|
||||
App::test((), |app| {
|
||||
let buffer = app.add_model(|_| {
|
||||
let len = rng.gen_range(0..10);
|
||||
let text = RandomCharIter::new(&mut rng).take(len).collect::<String>();
|
||||
Buffer::new(0, text)
|
||||
});
|
||||
let mut map = app.read(|app| FoldMap::new(buffer.clone(), app));
|
||||
let mut map = FoldMap::new(buffer.clone(), app.as_ref());
|
||||
|
||||
app.read(|app| {
|
||||
{
|
||||
let buffer = buffer.as_ref(app);
|
||||
|
||||
let fold_count = rng.gen_range(0..10);
|
||||
@@ -616,93 +607,83 @@ mod tests {
|
||||
fold_ranges.push(start..end);
|
||||
}
|
||||
|
||||
map.fold(fold_ranges, app)?;
|
||||
map.fold(fold_ranges, app.as_ref()).unwrap();
|
||||
|
||||
let mut expected_text = buffer.text();
|
||||
for fold_range in map.merged_fold_ranges(app).into_iter().rev() {
|
||||
for fold_range in map.merged_fold_ranges(app.as_ref()).into_iter().rev() {
|
||||
expected_text.replace_range(fold_range.start..fold_range.end, "…");
|
||||
}
|
||||
|
||||
assert_eq!(map.text(app), expected_text);
|
||||
assert_eq!(map.text(app.as_ref()), expected_text);
|
||||
|
||||
for fold_range in map.merged_fold_ranges(app) {
|
||||
for fold_range in map.merged_fold_ranges(app.as_ref()) {
|
||||
let display_point =
|
||||
map.to_display_point(fold_range.start.to_point(buffer).unwrap());
|
||||
assert!(map.is_line_folded(display_point.row()));
|
||||
}
|
||||
}
|
||||
|
||||
Ok::<(), anyhow::Error>(())
|
||||
})?;
|
||||
|
||||
let edits = buffer.update(&mut app, |buffer, ctx| {
|
||||
let edits = buffer.update(app, |buffer, ctx| {
|
||||
let start_version = buffer.version.clone();
|
||||
let edit_count = rng.gen_range(1..10);
|
||||
buffer.randomly_edit(&mut rng, edit_count, Some(ctx));
|
||||
Ok::<_, anyhow::Error>(buffer.edits_since(start_version).collect::<Vec<_>>())
|
||||
})?;
|
||||
buffer.edits_since(start_version).collect::<Vec<_>>()
|
||||
});
|
||||
|
||||
app.read(|app| {
|
||||
map.apply_edits(&edits, app)?;
|
||||
map.apply_edits(&edits, app.as_ref()).unwrap();
|
||||
|
||||
let buffer = map.buffer.as_ref(app);
|
||||
let mut expected_text = buffer.text();
|
||||
let mut expected_buffer_rows = Vec::new();
|
||||
let mut next_row = buffer.max_point().row;
|
||||
for fold_range in map.merged_fold_ranges(app).into_iter().rev() {
|
||||
let fold_start = buffer.point_for_offset(fold_range.start).unwrap();
|
||||
let fold_end = buffer.point_for_offset(fold_range.end).unwrap();
|
||||
expected_buffer_rows.extend((fold_end.row + 1..=next_row).rev());
|
||||
next_row = fold_start.row;
|
||||
let buffer = map.buffer.as_ref(app);
|
||||
let mut expected_text = buffer.text();
|
||||
let mut expected_buffer_rows = Vec::new();
|
||||
let mut next_row = buffer.max_point().row;
|
||||
for fold_range in map.merged_fold_ranges(app.as_ref()).into_iter().rev() {
|
||||
let fold_start = buffer.point_for_offset(fold_range.start).unwrap();
|
||||
let fold_end = buffer.point_for_offset(fold_range.end).unwrap();
|
||||
expected_buffer_rows.extend((fold_end.row + 1..=next_row).rev());
|
||||
next_row = fold_start.row;
|
||||
|
||||
expected_text.replace_range(fold_range.start..fold_range.end, "…");
|
||||
}
|
||||
expected_buffer_rows.extend((0..=next_row).rev());
|
||||
expected_buffer_rows.reverse();
|
||||
expected_text.replace_range(fold_range.start..fold_range.end, "…");
|
||||
}
|
||||
expected_buffer_rows.extend((0..=next_row).rev());
|
||||
expected_buffer_rows.reverse();
|
||||
|
||||
assert_eq!(map.text(app), expected_text);
|
||||
assert_eq!(map.text(app.as_ref()), expected_text);
|
||||
|
||||
for (idx, buffer_row) in expected_buffer_rows.iter().enumerate() {
|
||||
let display_row = map.to_display_point(Point::new(*buffer_row, 0)).row();
|
||||
assert_eq!(
|
||||
map.buffer_rows(display_row).unwrap().collect::<Vec<_>>(),
|
||||
expected_buffer_rows[idx..],
|
||||
);
|
||||
}
|
||||
|
||||
Ok::<(), anyhow::Error>(())
|
||||
})?;
|
||||
|
||||
Ok::<(), anyhow::Error>(())
|
||||
})?;
|
||||
for (idx, buffer_row) in expected_buffer_rows.iter().enumerate() {
|
||||
let display_row = map.to_display_point(Point::new(*buffer_row, 0)).row();
|
||||
assert_eq!(
|
||||
map.buffer_rows(display_row).unwrap().collect::<Vec<_>>(),
|
||||
expected_buffer_rows[idx..],
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_buffer_rows() -> Result<()> {
|
||||
App::test((), |mut app| async move {
|
||||
fn test_buffer_rows() {
|
||||
App::test((), |app| {
|
||||
let text = sample_text(6, 6) + "\n";
|
||||
let buffer = app.add_model(|_| Buffer::new(0, text));
|
||||
|
||||
app.read(|app| {
|
||||
let mut map = FoldMap::new(buffer.clone(), app);
|
||||
let mut map = FoldMap::new(buffer.clone(), app.as_ref());
|
||||
|
||||
map.fold(
|
||||
vec![
|
||||
Point::new(0, 2)..Point::new(2, 2),
|
||||
Point::new(3, 1)..Point::new(4, 1),
|
||||
],
|
||||
app,
|
||||
)?;
|
||||
map.fold(
|
||||
vec![
|
||||
Point::new(0, 2)..Point::new(2, 2),
|
||||
Point::new(3, 1)..Point::new(4, 1),
|
||||
],
|
||||
app.as_ref(),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(map.text(app), "aa…cccc\nd…eeeee\nffffff\n");
|
||||
assert_eq!(map.buffer_rows(0)?.collect::<Vec<_>>(), vec![0, 3, 5, 6]);
|
||||
assert_eq!(map.buffer_rows(3)?.collect::<Vec<_>>(), vec![6]);
|
||||
|
||||
Ok(())
|
||||
})
|
||||
})
|
||||
assert_eq!(map.text(app.as_ref()), "aa…cccc\nd…eeeee\nffffff\n");
|
||||
assert_eq!(
|
||||
map.buffer_rows(0).unwrap().collect::<Vec<_>>(),
|
||||
vec![0, 3, 5, 6]
|
||||
);
|
||||
assert_eq!(map.buffer_rows(3).unwrap().collect::<Vec<_>>(), vec![6]);
|
||||
});
|
||||
}
|
||||
|
||||
impl FoldMap {
|
||||
|
||||
@@ -292,52 +292,51 @@ pub fn collapse_tabs(
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::test::*;
|
||||
use anyhow::Error;
|
||||
use gpui::App;
|
||||
|
||||
#[test]
|
||||
fn test_chars_at() -> Result<()> {
|
||||
App::test((), |mut app| async move {
|
||||
fn test_chars_at() {
|
||||
App::test((), |app| {
|
||||
let text = sample_text(6, 6);
|
||||
let buffer = app.add_model(|_| Buffer::new(0, text));
|
||||
let map = app.add_model(|ctx| DisplayMap::new(buffer.clone(), 4, ctx));
|
||||
buffer.update(&mut app, |buffer, ctx| {
|
||||
buffer.edit(
|
||||
vec![
|
||||
Point::new(1, 0)..Point::new(1, 0),
|
||||
Point::new(1, 1)..Point::new(1, 1),
|
||||
Point::new(2, 1)..Point::new(2, 1),
|
||||
],
|
||||
"\t",
|
||||
Some(ctx),
|
||||
)
|
||||
})?;
|
||||
buffer
|
||||
.update(app, |buffer, ctx| {
|
||||
buffer.edit(
|
||||
vec![
|
||||
Point::new(1, 0)..Point::new(1, 0),
|
||||
Point::new(1, 1)..Point::new(1, 1),
|
||||
Point::new(2, 1)..Point::new(2, 1),
|
||||
],
|
||||
"\t",
|
||||
Some(ctx),
|
||||
)
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
map.read(&app, |map, ctx| {
|
||||
assert_eq!(
|
||||
map.chars_at(DisplayPoint::new(1, 0), ctx)?
|
||||
.take(10)
|
||||
.collect::<String>(),
|
||||
" b bb"
|
||||
);
|
||||
assert_eq!(
|
||||
map.chars_at(DisplayPoint::new(1, 2), ctx)?
|
||||
.take(10)
|
||||
.collect::<String>(),
|
||||
" b bbbb"
|
||||
);
|
||||
assert_eq!(
|
||||
map.chars_at(DisplayPoint::new(1, 6), ctx)?
|
||||
.take(13)
|
||||
.collect::<String>(),
|
||||
" bbbbb\nc c"
|
||||
);
|
||||
|
||||
Ok::<(), Error>(())
|
||||
})?;
|
||||
|
||||
Ok(())
|
||||
})
|
||||
let map = map.as_ref(app);
|
||||
assert_eq!(
|
||||
map.chars_at(DisplayPoint::new(1, 0), app.as_ref())
|
||||
.unwrap()
|
||||
.take(10)
|
||||
.collect::<String>(),
|
||||
" b bb"
|
||||
);
|
||||
assert_eq!(
|
||||
map.chars_at(DisplayPoint::new(1, 2), app.as_ref())
|
||||
.unwrap()
|
||||
.take(10)
|
||||
.collect::<String>(),
|
||||
" b bbbb"
|
||||
);
|
||||
assert_eq!(
|
||||
map.chars_at(DisplayPoint::new(1, 6), app.as_ref())
|
||||
.unwrap()
|
||||
.take(13)
|
||||
.collect::<String>(),
|
||||
" bbbbb\nc c"
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -364,14 +363,14 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_max_point() -> Result<()> {
|
||||
App::test((), |mut app| async move {
|
||||
fn test_max_point() {
|
||||
App::test((), |app| {
|
||||
let buffer = app.add_model(|_| Buffer::new(0, "aaa\n\t\tbbb"));
|
||||
let map = app.add_model(|ctx| DisplayMap::new(buffer.clone(), 4, ctx));
|
||||
map.read(&app, |map, app| {
|
||||
assert_eq!(map.max_point(app), DisplayPoint::new(1, 11))
|
||||
});
|
||||
Ok(())
|
||||
})
|
||||
assert_eq!(
|
||||
map.as_ref(app).max_point(app.as_ref()),
|
||||
DisplayPoint::new(1, 11)
|
||||
)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
+24
-23
@@ -11,7 +11,7 @@ use gpui::{
|
||||
fonts::{Properties, Weight},
|
||||
geometry::vector::vec2f,
|
||||
keymap::{self, Binding},
|
||||
App, AppContext, Axis, Border, Entity, ModelHandle, MutableAppContext, View, ViewContext,
|
||||
AppContext, Axis, Border, Entity, ModelHandle, MutableAppContext, View, ViewContext,
|
||||
ViewHandle, WeakViewHandle,
|
||||
};
|
||||
use std::cmp;
|
||||
@@ -394,20 +394,23 @@ mod tests {
|
||||
editor, settings,
|
||||
workspace::{Workspace, WorkspaceView},
|
||||
};
|
||||
use anyhow::Result;
|
||||
use gpui::App;
|
||||
use smol::fs;
|
||||
use tempdir::TempDir;
|
||||
|
||||
#[test]
|
||||
fn test_matching_paths() -> Result<()> {
|
||||
App::test((), |mut app| async move {
|
||||
let tmp_dir = TempDir::new("example")?;
|
||||
fs::create_dir(tmp_dir.path().join("a")).await?;
|
||||
fs::write(tmp_dir.path().join("a/banana"), "banana").await?;
|
||||
fs::write(tmp_dir.path().join("a/bandana"), "bandana").await?;
|
||||
super::init(&mut app);
|
||||
editor::init(&mut app);
|
||||
fn test_matching_paths() {
|
||||
App::test_async((), |app| async move {
|
||||
let tmp_dir = TempDir::new("example").unwrap();
|
||||
fs::create_dir(tmp_dir.path().join("a")).await.unwrap();
|
||||
fs::write(tmp_dir.path().join("a/banana"), "banana")
|
||||
.await
|
||||
.unwrap();
|
||||
fs::write(tmp_dir.path().join("a/bandana"), "bandana")
|
||||
.await
|
||||
.unwrap();
|
||||
super::init(app);
|
||||
editor::init(app);
|
||||
|
||||
let settings = settings::channel(&app.font_cache()).unwrap().1;
|
||||
let workspace = app.add_model(|ctx| Workspace::new(vec![tmp_dir.path().into()], ctx));
|
||||
@@ -420,16 +423,15 @@ mod tests {
|
||||
"file_finder:toggle".into(),
|
||||
(),
|
||||
);
|
||||
let (finder, query_buffer) = workspace_view.read(&app, |view, ctx| {
|
||||
let finder = view
|
||||
.modal()
|
||||
.cloned()
|
||||
.unwrap()
|
||||
.downcast::<FileFinder>()
|
||||
.unwrap();
|
||||
let query_buffer = finder.as_ref(ctx).query_buffer.clone();
|
||||
(finder, query_buffer)
|
||||
});
|
||||
|
||||
let finder = workspace_view
|
||||
.as_ref(app)
|
||||
.modal()
|
||||
.cloned()
|
||||
.unwrap()
|
||||
.downcast::<FileFinder>()
|
||||
.unwrap();
|
||||
let query_buffer = finder.as_ref(app).query_buffer.clone();
|
||||
|
||||
let chain = vec![finder.id(), query_buffer.id()];
|
||||
app.dispatch_action(window_id, chain.clone(), "buffer:insert", "b".to_string());
|
||||
@@ -452,7 +454,7 @@ mod tests {
|
||||
// (),
|
||||
// );
|
||||
// app.finish_pending_tasks().await; // Load Buffer and open BufferView.
|
||||
// let active_pane = workspace_view.read(&app, |view, _| view.active_pane().clone());
|
||||
// let active_pane = workspace_view.as_ref(app).active_pane().clone();
|
||||
// assert_eq!(
|
||||
// active_pane.state(&app),
|
||||
// pane::State {
|
||||
@@ -462,7 +464,6 @@ mod tests {
|
||||
// }]
|
||||
// }
|
||||
// );
|
||||
Ok(())
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
+5
-3
@@ -1,5 +1,5 @@
|
||||
use fs::OpenOptions;
|
||||
use gpui::platform::{current as platform, PathPromptOptions, Runner as _};
|
||||
use gpui::platform::PathPromptOptions;
|
||||
use log::LevelFilter;
|
||||
use simplelog::SimpleLogger;
|
||||
use std::{fs, path::PathBuf};
|
||||
@@ -13,6 +13,7 @@ fn main() {
|
||||
|
||||
let app = gpui::App::new(assets::Assets).unwrap();
|
||||
let (_, settings_rx) = settings::channel(&app.font_cache()).unwrap();
|
||||
app.set_menus(menus::MENUS);
|
||||
app.on_menu_command({
|
||||
let settings_rx = settings_rx.clone();
|
||||
move |command, ctx| match command {
|
||||
@@ -34,7 +35,7 @@ fn main() {
|
||||
_ => ctx.dispatch_global_action(command, ()),
|
||||
}
|
||||
})
|
||||
.run(move |ctx| {
|
||||
.on_finish_launching(move |ctx| {
|
||||
workspace::init(ctx);
|
||||
editor::init(ctx);
|
||||
file_finder::init(ctx);
|
||||
@@ -53,7 +54,8 @@ fn main() {
|
||||
},
|
||||
);
|
||||
}
|
||||
});
|
||||
})
|
||||
.run();
|
||||
}
|
||||
|
||||
fn init_logger() {
|
||||
|
||||
+18
-10
@@ -9,7 +9,7 @@ pub use workspace::*;
|
||||
pub use workspace_view::*;
|
||||
|
||||
use crate::{settings::Settings, watch};
|
||||
use gpui::{App, MutableAppContext};
|
||||
use gpui::MutableAppContext;
|
||||
use std::path::PathBuf;
|
||||
|
||||
pub fn init(app: &mut MutableAppContext) {
|
||||
@@ -64,10 +64,10 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_open_paths_action() {
|
||||
App::test((), |mut app| async move {
|
||||
App::test((), |app| {
|
||||
let settings = settings::channel(&app.font_cache()).unwrap().1;
|
||||
|
||||
init(&mut app);
|
||||
init(app);
|
||||
|
||||
let dir = temp_tree(json!({
|
||||
"a": {
|
||||
@@ -94,7 +94,7 @@ mod tests {
|
||||
settings: settings.clone(),
|
||||
},
|
||||
);
|
||||
assert_eq!(app.window_ids().len(), 1);
|
||||
assert_eq!(app.window_ids().count(), 1);
|
||||
|
||||
app.dispatch_global_action(
|
||||
"workspace:open_paths",
|
||||
@@ -103,11 +103,19 @@ mod tests {
|
||||
settings: settings.clone(),
|
||||
},
|
||||
);
|
||||
assert_eq!(app.window_ids().len(), 1);
|
||||
let workspace_view_1 = app.root_view::<WorkspaceView>(app.window_ids()[0]).unwrap();
|
||||
workspace_view_1.read(&app, |view, app| {
|
||||
assert_eq!(view.workspace.as_ref(app).worktrees().len(), 2);
|
||||
});
|
||||
assert_eq!(app.window_ids().count(), 1);
|
||||
let workspace_view_1 = app
|
||||
.root_view::<WorkspaceView>(app.window_ids().next().unwrap())
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
workspace_view_1
|
||||
.as_ref(app)
|
||||
.workspace
|
||||
.as_ref(app)
|
||||
.worktrees()
|
||||
.len(),
|
||||
2
|
||||
);
|
||||
|
||||
app.dispatch_global_action(
|
||||
"workspace:open_paths",
|
||||
@@ -119,7 +127,7 @@ mod tests {
|
||||
settings: settings.clone(),
|
||||
},
|
||||
);
|
||||
assert_eq!(app.window_ids().len(), 2);
|
||||
assert_eq!(app.window_ids().count(), 2);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ use gpui::{
|
||||
elements::*,
|
||||
geometry::{rect::RectF, vector::vec2f},
|
||||
keymap::Binding,
|
||||
App, AppContext, Border, Entity, MutableAppContext, Quad, View, ViewContext,
|
||||
AppContext, Border, Entity, MutableAppContext, Quad, View, ViewContext,
|
||||
};
|
||||
use std::cmp;
|
||||
|
||||
|
||||
@@ -200,23 +200,22 @@ impl Entity for Workspace {
|
||||
|
||||
#[cfg(test)]
|
||||
pub trait WorkspaceHandle {
|
||||
fn file_entries(&self, app: &gpui::App) -> Vec<(usize, usize)>;
|
||||
fn file_entries(&self, app: &mut MutableAppContext) -> Vec<(usize, usize)>;
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
impl WorkspaceHandle for ModelHandle<Workspace> {
|
||||
fn file_entries(&self, app: &gpui::App) -> Vec<(usize, usize)> {
|
||||
self.read(&app, |w, app| {
|
||||
w.worktrees()
|
||||
.iter()
|
||||
.flat_map(|tree| {
|
||||
let tree_id = tree.id();
|
||||
tree.as_ref(app)
|
||||
.files()
|
||||
.map(move |file| (tree_id, file.entry_id))
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
})
|
||||
fn file_entries(&self, app: &mut MutableAppContext) -> Vec<(usize, usize)> {
|
||||
self.as_ref(app)
|
||||
.worktrees()
|
||||
.iter()
|
||||
.flat_map(|tree| {
|
||||
let tree_id = tree.id();
|
||||
tree.as_ref(app)
|
||||
.files()
|
||||
.map(move |file| (tree_id, file.entry_id))
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -228,8 +227,8 @@ mod tests {
|
||||
use serde_json::json;
|
||||
|
||||
#[test]
|
||||
fn test_open_entry() -> Result<(), Arc<anyhow::Error>> {
|
||||
App::test((), |mut app| async move {
|
||||
fn test_open_entry() {
|
||||
App::test_async((), |app| async move {
|
||||
let dir = temp_tree(json!({
|
||||
"a": {
|
||||
"aa": "aa contents",
|
||||
@@ -241,32 +240,29 @@ mod tests {
|
||||
app.finish_pending_tasks().await; // Open and populate worktree.
|
||||
|
||||
// Get the first file entry.
|
||||
let entry = workspace.read(&app, |w, app| {
|
||||
let tree = w.worktrees.iter().next().unwrap();
|
||||
let entry_id = tree.as_ref(app).files().next().unwrap().entry_id;
|
||||
(tree.id(), entry_id)
|
||||
});
|
||||
let tree = workspace.as_ref(app).worktrees.iter().next().unwrap();
|
||||
let entry_id = tree.as_ref(app).files().next().unwrap().entry_id;
|
||||
let entry = (tree.id(), entry_id);
|
||||
|
||||
// Open the same entry twice before it finishes loading.
|
||||
let (future_1, future_2) = workspace.update(&mut app, |w, app| {
|
||||
let (future_1, future_2) = workspace.update(app, |w, app| {
|
||||
(
|
||||
w.open_entry(entry, app).unwrap(),
|
||||
w.open_entry(entry, app).unwrap(),
|
||||
)
|
||||
});
|
||||
|
||||
let handle_1 = future_1.await?;
|
||||
let handle_2 = future_2.await?;
|
||||
let handle_1 = future_1.await.unwrap();
|
||||
let handle_2 = future_2.await.unwrap();
|
||||
assert_eq!(handle_1.id(), handle_2.id());
|
||||
|
||||
// Open the same entry again now that it has loaded
|
||||
let handle_3 = workspace
|
||||
.update(&mut app, |w, app| w.open_entry(entry, app).unwrap())
|
||||
.await?;
|
||||
.update(app, |w, app| w.open_entry(entry, app).unwrap())
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(handle_3.id(), handle_1.id());
|
||||
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,8 @@ use super::{pane, Pane, PaneGroup, SplitDirection, Workspace};
|
||||
use crate::{settings::Settings, watch};
|
||||
use futures_core::future::LocalBoxFuture;
|
||||
use gpui::{
|
||||
color::rgbu, elements::*, json::to_string_pretty, keymap::Binding, AnyViewHandle, App,
|
||||
AppContext, Entity, ModelHandle, MutableAppContext, View, ViewContext, ViewHandle,
|
||||
color::rgbu, elements::*, json::to_string_pretty, keymap::Binding, AnyViewHandle, AppContext,
|
||||
Entity, ModelHandle, MutableAppContext, View, ViewContext, ViewHandle,
|
||||
};
|
||||
use log::{error, info};
|
||||
use std::{collections::HashSet, path::PathBuf};
|
||||
@@ -389,13 +389,12 @@ impl View for WorkspaceView {
|
||||
mod tests {
|
||||
use super::{pane, Workspace, WorkspaceView};
|
||||
use crate::{settings, test::temp_tree, workspace::WorkspaceHandle as _};
|
||||
use anyhow::Result;
|
||||
use gpui::App;
|
||||
use serde_json::json;
|
||||
|
||||
#[test]
|
||||
fn test_open_entry() -> Result<()> {
|
||||
App::test((), |mut app| async move {
|
||||
fn test_open_entry() {
|
||||
App::test_async((), |app| async move {
|
||||
let dir = temp_tree(json!({
|
||||
"a": {
|
||||
"aa": "aa contents",
|
||||
@@ -407,64 +406,70 @@ mod tests {
|
||||
let settings = settings::channel(&app.font_cache()).unwrap().1;
|
||||
let workspace = app.add_model(|ctx| Workspace::new(vec![dir.path().into()], ctx));
|
||||
app.finish_pending_tasks().await; // Open and populate worktree.
|
||||
let entries = workspace.file_entries(&app);
|
||||
let entries = workspace.file_entries(app);
|
||||
|
||||
let (_, workspace_view) =
|
||||
app.add_window(|ctx| WorkspaceView::new(workspace.clone(), settings, ctx));
|
||||
|
||||
// Open the first entry
|
||||
workspace_view.update(&mut app, |w, ctx| w.open_entry(entries[0], ctx));
|
||||
workspace_view.update(app, |w, ctx| w.open_entry(entries[0], ctx));
|
||||
app.finish_pending_tasks().await;
|
||||
|
||||
workspace_view.read(&app, |w, app| {
|
||||
assert_eq!(w.active_pane().as_ref(app).items().len(), 1);
|
||||
});
|
||||
assert_eq!(
|
||||
workspace_view
|
||||
.as_ref(app)
|
||||
.active_pane()
|
||||
.as_ref(app)
|
||||
.items()
|
||||
.len(),
|
||||
1
|
||||
);
|
||||
|
||||
// Open the second entry
|
||||
workspace_view.update(&mut app, |w, ctx| w.open_entry(entries[1], ctx));
|
||||
workspace_view.update(app, |w, ctx| w.open_entry(entries[1], ctx));
|
||||
app.finish_pending_tasks().await;
|
||||
|
||||
workspace_view.read(&app, |w, app| {
|
||||
let active_pane = w.active_pane().as_ref(app);
|
||||
assert_eq!(active_pane.items().len(), 2);
|
||||
assert_eq!(
|
||||
active_pane.active_item().unwrap().entry_id(app),
|
||||
Some(entries[1])
|
||||
);
|
||||
});
|
||||
let active_pane = workspace_view.as_ref(app).active_pane().as_ref(app);
|
||||
assert_eq!(active_pane.items().len(), 2);
|
||||
assert_eq!(
|
||||
active_pane.active_item().unwrap().entry_id(app.as_ref()),
|
||||
Some(entries[1])
|
||||
);
|
||||
|
||||
// Open the first entry again
|
||||
workspace_view.update(&mut app, |w, ctx| w.open_entry(entries[0], ctx));
|
||||
workspace_view.update(app, |w, ctx| w.open_entry(entries[0], ctx));
|
||||
app.finish_pending_tasks().await;
|
||||
|
||||
workspace_view.read(&app, |w, app| {
|
||||
let active_pane = w.active_pane().as_ref(app);
|
||||
assert_eq!(active_pane.items().len(), 2);
|
||||
assert_eq!(
|
||||
active_pane.active_item().unwrap().entry_id(app),
|
||||
Some(entries[0])
|
||||
);
|
||||
});
|
||||
let active_pane = workspace_view.as_ref(app).active_pane().as_ref(app);
|
||||
assert_eq!(active_pane.items().len(), 2);
|
||||
assert_eq!(
|
||||
active_pane.active_item().unwrap().entry_id(app.as_ref()),
|
||||
Some(entries[0])
|
||||
);
|
||||
|
||||
// Open the third entry twice concurrently
|
||||
workspace_view.update(&mut app, |w, ctx| {
|
||||
workspace_view.update(app, |w, ctx| {
|
||||
w.open_entry(entries[2], ctx);
|
||||
w.open_entry(entries[2], ctx);
|
||||
});
|
||||
app.finish_pending_tasks().await;
|
||||
|
||||
workspace_view.read(&app, |w, app| {
|
||||
assert_eq!(w.active_pane().as_ref(app).items().len(), 3);
|
||||
});
|
||||
|
||||
Ok(())
|
||||
})
|
||||
assert_eq!(
|
||||
workspace_view
|
||||
.as_ref(app)
|
||||
.active_pane()
|
||||
.as_ref(app)
|
||||
.items()
|
||||
.len(),
|
||||
3
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_pane_actions() -> Result<()> {
|
||||
App::test((), |mut app| async move {
|
||||
pane::init(&mut app);
|
||||
fn test_pane_actions() {
|
||||
App::test_async((), |app| async move {
|
||||
pane::init(app);
|
||||
|
||||
let dir = temp_tree(json!({
|
||||
"a": {
|
||||
@@ -474,35 +479,37 @@ mod tests {
|
||||
},
|
||||
}));
|
||||
|
||||
let settings = settings::channel(&app.font_cache()).unwrap().1;
|
||||
let settings = settings::channel(app.font_cache()).unwrap().1;
|
||||
let workspace = app.add_model(|ctx| Workspace::new(vec![dir.path().into()], ctx));
|
||||
app.finish_pending_tasks().await; // Open and populate worktree.
|
||||
let entries = workspace.file_entries(&app);
|
||||
let entries = workspace.file_entries(app);
|
||||
|
||||
let (window_id, workspace_view) =
|
||||
app.add_window(|ctx| WorkspaceView::new(workspace.clone(), settings, ctx));
|
||||
|
||||
workspace_view.update(&mut app, |w, ctx| w.open_entry(entries[0], ctx));
|
||||
workspace_view.update(app, |w, ctx| w.open_entry(entries[0], ctx));
|
||||
app.finish_pending_tasks().await;
|
||||
|
||||
let pane_1 = workspace_view.read(&app, |w, _| w.active_pane().clone());
|
||||
let pane_1 = workspace_view.as_ref(app).active_pane().clone();
|
||||
|
||||
app.dispatch_action(window_id, vec![pane_1.id()], "pane:split_right", ());
|
||||
let pane_2 = workspace_view.read(&app, |w, _| w.active_pane().clone());
|
||||
let pane_2 = workspace_view.as_ref(app).active_pane().clone();
|
||||
assert_ne!(pane_1, pane_2);
|
||||
|
||||
pane_2.read(&app, |p, app| {
|
||||
assert_eq!(p.active_item().unwrap().entry_id(app), Some(entries[0]));
|
||||
});
|
||||
assert_eq!(
|
||||
pane_2
|
||||
.as_ref(app)
|
||||
.active_item()
|
||||
.unwrap()
|
||||
.entry_id(app.downgrade()),
|
||||
Some(entries[0])
|
||||
);
|
||||
|
||||
app.dispatch_action(window_id, vec![pane_2.id()], "pane:close_active_item", ());
|
||||
|
||||
workspace_view.read(&app, |w, _| {
|
||||
assert_eq!(w.panes.len(), 1);
|
||||
assert_eq!(w.active_pane(), &pane_1)
|
||||
});
|
||||
|
||||
Ok(())
|
||||
})
|
||||
let w = workspace_view.as_ref(app);
|
||||
assert_eq!(w.panes.len(), 1);
|
||||
assert_eq!(w.active_pane(), &pane_1);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -648,8 +648,8 @@ mod test {
|
||||
use std::os::unix;
|
||||
|
||||
#[test]
|
||||
fn test_populate_and_search() -> Result<()> {
|
||||
App::test((), |mut app| async move {
|
||||
fn test_populate_and_search() {
|
||||
App::test_async((), |app| async move {
|
||||
let dir = temp_tree(json!({
|
||||
"root": {
|
||||
"apple": "",
|
||||
@@ -666,33 +666,31 @@ mod test {
|
||||
}));
|
||||
|
||||
let root_link_path = dir.path().join("root_link");
|
||||
unix::fs::symlink(&dir.path().join("root"), &root_link_path)?;
|
||||
unix::fs::symlink(&dir.path().join("root"), &root_link_path).unwrap();
|
||||
|
||||
let tree = app.add_model(|ctx| Worktree::new(1, root_link_path, Some(ctx)));
|
||||
app.finish_pending_tasks().await;
|
||||
|
||||
tree.read(&app, |tree, _| {
|
||||
assert_eq!(tree.file_count(), 4);
|
||||
let results = match_paths(&[tree.clone()], "bna", false, false, 10)
|
||||
.iter()
|
||||
.map(|result| tree.entry_path(result.entry_id))
|
||||
.collect::<Result<Vec<PathBuf>, _>>()
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
results,
|
||||
vec![
|
||||
PathBuf::from("root_link/banana/carrot/date"),
|
||||
PathBuf::from("root_link/banana/carrot/endive"),
|
||||
]
|
||||
);
|
||||
});
|
||||
Ok(())
|
||||
})
|
||||
let tree = tree.as_ref(app);
|
||||
assert_eq!(tree.file_count(), 4);
|
||||
let results = match_paths(&[tree.clone()], "bna", false, false, 10)
|
||||
.iter()
|
||||
.map(|result| tree.entry_path(result.entry_id))
|
||||
.collect::<Result<Vec<PathBuf>, _>>()
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
results,
|
||||
vec![
|
||||
PathBuf::from("root_link/banana/carrot/date"),
|
||||
PathBuf::from("root_link/banana/carrot/endive"),
|
||||
]
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_save_file() {
|
||||
App::test((), |mut app| async move {
|
||||
App::test_async((), |app| async move {
|
||||
let dir = temp_tree(json!({
|
||||
"file1": "the old contents",
|
||||
}));
|
||||
@@ -700,24 +698,18 @@ mod test {
|
||||
let tree = app.add_model(|ctx| Worktree::new(1, dir.path(), Some(ctx)));
|
||||
app.finish_pending_tasks().await;
|
||||
|
||||
let file_id = tree.read(&app, |tree, _| {
|
||||
let entry = tree.files().next().unwrap();
|
||||
assert_eq!(entry.path.file_name().unwrap(), "file1");
|
||||
entry.entry_id
|
||||
});
|
||||
let entry = tree.as_ref(app).files().next().unwrap();
|
||||
assert_eq!(entry.path.file_name().unwrap(), "file1");
|
||||
let file_id = entry.entry_id;
|
||||
|
||||
let buffer = Buffer::new(1, "a line of text.\n".repeat(10 * 1024));
|
||||
|
||||
tree.update(&mut app, |tree, ctx| {
|
||||
tree.update(app, |tree, ctx| {
|
||||
smol::block_on(tree.save(file_id, buffer.snapshot(), ctx.app())).unwrap()
|
||||
});
|
||||
|
||||
let history = tree
|
||||
.read(&app, |tree, _| tree.load_history(file_id))
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let history = tree.as_ref(app).load_history(file_id).await.unwrap();
|
||||
assert_eq!(history.base_text, buffer.text());
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user