WIP
co-authored-by: conrad <conrad.irwin@zed.dev>
This commit is contained in:
parent
0e3fd92bd0
commit
a4e9fea133
15 changed files with 3384 additions and 383 deletions
3
Cargo.lock
generated
3
Cargo.lock
generated
|
@ -2012,7 +2012,7 @@ dependencies = [
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
"settings2",
|
"settings2",
|
||||||
"smol",
|
"smol",
|
||||||
"theme",
|
"theme2",
|
||||||
"util",
|
"util",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -2768,7 +2768,6 @@ dependencies = [
|
||||||
"copilot2",
|
"copilot2",
|
||||||
"ctor",
|
"ctor",
|
||||||
"db2",
|
"db2",
|
||||||
"drag_and_drop",
|
|
||||||
"env_logger 0.9.3",
|
"env_logger 0.9.3",
|
||||||
"futures 0.3.28",
|
"futures 0.3.28",
|
||||||
"fuzzy2",
|
"fuzzy2",
|
||||||
|
|
|
@ -1,11 +1,14 @@
|
||||||
|
use std::ops::Range;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
rpc::{CLEANUP_TIMEOUT, RECONNECT_TIMEOUT},
|
rpc::{CLEANUP_TIMEOUT, RECONNECT_TIMEOUT},
|
||||||
tests::TestServer,
|
tests::TestServer,
|
||||||
};
|
};
|
||||||
use client::{Collaborator, UserId};
|
use client::{Collaborator, ParticipantIndex, UserId};
|
||||||
use collections::HashMap;
|
use collections::HashMap;
|
||||||
|
use editor::{Anchor, Editor, ToOffset};
|
||||||
use futures::future;
|
use futures::future;
|
||||||
use gpui::{BackgroundExecutor, Model, TestAppContext};
|
use gpui::{BackgroundExecutor, Model, TestAppContext, ViewContext};
|
||||||
use rpc::{proto::PeerId, RECEIVE_TIMEOUT};
|
use rpc::{proto::PeerId, RECEIVE_TIMEOUT};
|
||||||
|
|
||||||
#[gpui::test]
|
#[gpui::test]
|
||||||
|
|
|
@ -1,10 +1,30 @@
|
||||||
use editor::{
|
use std::{
|
||||||
test::editor_test_context::EditorTestContext, ConfirmCodeAction, ConfirmCompletion,
|
path::Path,
|
||||||
ConfirmRename, Editor, Redo, Rename, ToggleCodeActions, Undo,
|
sync::{
|
||||||
|
atomic::{self, AtomicBool, AtomicUsize},
|
||||||
|
Arc,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
use gpui::{BackgroundExecutor, TestAppContext};
|
|
||||||
|
|
||||||
use crate::tests::TestServer;
|
use call::ActiveCall;
|
||||||
|
use editor::{
|
||||||
|
test::editor_test_context::{AssertionContextManager, EditorTestContext},
|
||||||
|
Anchor, ConfirmCodeAction, ConfirmCompletion, ConfirmRename, Editor, Redo, Rename,
|
||||||
|
ToggleCodeActions, Undo,
|
||||||
|
};
|
||||||
|
use gpui::{BackgroundExecutor, TestAppContext, VisualContext, VisualTestContext};
|
||||||
|
use indoc::indoc;
|
||||||
|
use language::{
|
||||||
|
language_settings::{AllLanguageSettings, InlayHintSettings},
|
||||||
|
tree_sitter_rust, FakeLspAdapter, Language, LanguageConfig,
|
||||||
|
};
|
||||||
|
use rpc::RECEIVE_TIMEOUT;
|
||||||
|
use serde_json::json;
|
||||||
|
use settings::SettingsStore;
|
||||||
|
use text::Point;
|
||||||
|
use workspace::Workspace;
|
||||||
|
|
||||||
|
use crate::{rpc::RECONNECT_TIMEOUT, tests::TestServer};
|
||||||
|
|
||||||
#[gpui::test(iterations = 10)]
|
#[gpui::test(iterations = 10)]
|
||||||
async fn test_host_disconnect(
|
async fn test_host_disconnect(
|
||||||
|
@ -13,7 +33,7 @@ async fn test_host_disconnect(
|
||||||
cx_b: &mut TestAppContext,
|
cx_b: &mut TestAppContext,
|
||||||
cx_c: &mut TestAppContext,
|
cx_c: &mut TestAppContext,
|
||||||
) {
|
) {
|
||||||
let mut server = TestServer::start(&executor).await;
|
let mut server = TestServer::start(executor).await;
|
||||||
let client_a = server.create_client(cx_a, "user_a").await;
|
let client_a = server.create_client(cx_a, "user_a").await;
|
||||||
let client_b = server.create_client(cx_b, "user_b").await;
|
let client_b = server.create_client(cx_b, "user_b").await;
|
||||||
let client_c = server.create_client(cx_c, "user_c").await;
|
let client_c = server.create_client(cx_c, "user_c").await;
|
||||||
|
@ -27,7 +47,7 @@ async fn test_host_disconnect(
|
||||||
.fs()
|
.fs()
|
||||||
.insert_tree(
|
.insert_tree(
|
||||||
"/a",
|
"/a",
|
||||||
json!({
|
serde_json::json!({
|
||||||
"a.txt": "a-contents",
|
"a.txt": "a-contents",
|
||||||
"b.txt": "b-contents",
|
"b.txt": "b-contents",
|
||||||
}),
|
}),
|
||||||
|
@ -37,7 +57,7 @@ async fn test_host_disconnect(
|
||||||
let active_call_a = cx_a.read(ActiveCall::global);
|
let active_call_a = cx_a.read(ActiveCall::global);
|
||||||
let (project_a, worktree_id) = client_a.build_local_project("/a", cx_a).await;
|
let (project_a, worktree_id) = client_a.build_local_project("/a", cx_a).await;
|
||||||
|
|
||||||
let worktree_a = project_a.read_with(cx_a, |project, cx| project.worktrees(cx).next().unwrap());
|
let worktree_a = project_a.read_with(cx_a, |project, cx| project.worktrees().next().unwrap());
|
||||||
let project_id = active_call_a
|
let project_id = active_call_a
|
||||||
.update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
|
.update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
|
||||||
.await
|
.await
|
||||||
|
@ -50,19 +70,23 @@ async fn test_host_disconnect(
|
||||||
|
|
||||||
let workspace_b =
|
let workspace_b =
|
||||||
cx_b.add_window(|cx| Workspace::new(0, project_b.clone(), client_b.app_state.clone(), cx));
|
cx_b.add_window(|cx| Workspace::new(0, project_b.clone(), client_b.app_state.clone(), cx));
|
||||||
|
let cx_b = &mut VisualTestContext::from_window(*workspace_b, cx_b);
|
||||||
|
|
||||||
let editor_b = workspace_b
|
let editor_b = workspace_b
|
||||||
.update(cx_b, |workspace, cx| {
|
.update(cx_b, |workspace, cx| {
|
||||||
workspace.open_path((worktree_id, "b.txt"), None, true, cx)
|
workspace.open_path((worktree_id, "b.txt"), None, true, cx)
|
||||||
})
|
})
|
||||||
|
.unwrap()
|
||||||
.await
|
.await
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.downcast::<Editor>()
|
.downcast::<Editor>()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
assert!(window_b.read_with(cx_b, |cx| editor_b.is_focused(cx)));
|
//TODO: focus
|
||||||
|
assert!(cx_b.update_view(&editor_b, |editor, cx| editor.is_focused(cx)));
|
||||||
editor_b.update(cx_b, |editor, cx| editor.insert("X", cx));
|
editor_b.update(cx_b, |editor, cx| editor.insert("X", cx));
|
||||||
assert!(window_b.is_edited(cx_b));
|
//todo(is_edited)
|
||||||
|
// assert!(workspace_b.is_edited(cx_b));
|
||||||
|
|
||||||
// Drop client A's connection. Collaborators should disappear and the project should not be shown as shared.
|
// Drop client A's connection. Collaborators should disappear and the project should not be shown as shared.
|
||||||
server.forbid_connections();
|
server.forbid_connections();
|
||||||
|
@ -79,10 +103,10 @@ async fn test_host_disconnect(
|
||||||
|
|
||||||
// Ensure client B's edited state is reset and that the whole window is blurred.
|
// Ensure client B's edited state is reset and that the whole window is blurred.
|
||||||
|
|
||||||
window_b.read_with(cx_b, |cx| {
|
workspace_b.update(cx_b, |_, cx| {
|
||||||
assert_eq!(cx.focused_view_id(), None);
|
assert_eq!(cx.focused_view_id(), None);
|
||||||
});
|
});
|
||||||
assert!(!window_b.is_edited(cx_b));
|
// assert!(!workspace_b.is_edited(cx_b));
|
||||||
|
|
||||||
// Ensure client B is not prompted to save edits when closing window after disconnecting.
|
// Ensure client B is not prompted to save edits when closing window after disconnecting.
|
||||||
let can_close = workspace_b
|
let can_close = workspace_b
|
||||||
|
@ -153,12 +177,14 @@ async fn test_newline_above_or_below_does_not_move_guest_cursor(
|
||||||
.update(cx_a, |p, cx| p.open_buffer((worktree_id, "a.txt"), cx))
|
.update(cx_a, |p, cx| p.open_buffer((worktree_id, "a.txt"), cx))
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let window_a = cx_a.add_window(|_| EmptyView);
|
let window_a = cx_a.add_empty_window();
|
||||||
let editor_a = window_a.add_view(cx_a, |cx| Editor::for_buffer(buffer_a, Some(project_a), cx));
|
let editor_a =
|
||||||
|
window_a.build_view(cx_a, |cx| Editor::for_buffer(buffer_a, Some(project_a), cx));
|
||||||
let mut editor_cx_a = EditorTestContext {
|
let mut editor_cx_a = EditorTestContext {
|
||||||
cx: cx_a,
|
cx: cx_a,
|
||||||
window: window_a.into(),
|
window: window_a.into(),
|
||||||
editor: editor_a,
|
editor: editor_a,
|
||||||
|
assertion_cx: AssertionContextManager::new(),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Open a buffer as client B
|
// Open a buffer as client B
|
||||||
|
@ -166,12 +192,14 @@ async fn test_newline_above_or_below_does_not_move_guest_cursor(
|
||||||
.update(cx_b, |p, cx| p.open_buffer((worktree_id, "a.txt"), cx))
|
.update(cx_b, |p, cx| p.open_buffer((worktree_id, "a.txt"), cx))
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let window_b = cx_b.add_window(|_| EmptyView);
|
let window_b = cx_b.add_empty_window();
|
||||||
let editor_b = window_b.add_view(cx_b, |cx| Editor::for_buffer(buffer_b, Some(project_b), cx));
|
let editor_b =
|
||||||
|
window_b.build_view(cx_b, |cx| Editor::for_buffer(buffer_b, Some(project_b), cx));
|
||||||
let mut editor_cx_b = EditorTestContext {
|
let mut editor_cx_b = EditorTestContext {
|
||||||
cx: cx_b,
|
cx: cx_b,
|
||||||
window: window_b.into(),
|
window: window_b.into(),
|
||||||
editor: editor_b,
|
editor: editor_b,
|
||||||
|
assertion_cx: AssertionContextManager::new(),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Test newline above
|
// Test newline above
|
||||||
|
@ -275,8 +303,8 @@ async fn test_collaborating_with_completion(
|
||||||
.update(cx_b, |p, cx| p.open_buffer((worktree_id, "main.rs"), cx))
|
.update(cx_b, |p, cx| p.open_buffer((worktree_id, "main.rs"), cx))
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let window_b = cx_b.add_window(|_| EmptyView);
|
let window_b = cx_b.add_empty_window();
|
||||||
let editor_b = window_b.add_view(cx_b, |cx| {
|
let editor_b = window_b.build_view(cx_b, |cx| {
|
||||||
Editor::for_buffer(buffer_b.clone(), Some(project_b.clone()), cx)
|
Editor::for_buffer(buffer_b.clone(), Some(project_b.clone()), cx)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -384,7 +412,7 @@ async fn test_collaborating_with_completion(
|
||||||
);
|
);
|
||||||
|
|
||||||
// The additional edit is applied.
|
// The additional edit is applied.
|
||||||
cx_a.foreground().run_until_parked();
|
cx_a.executor().run_until_parked();
|
||||||
|
|
||||||
buffer_a.read_with(cx_a, |buffer, _| {
|
buffer_a.read_with(cx_a, |buffer, _| {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
@ -935,8 +963,8 @@ async fn test_share_project(
|
||||||
cx_b: &mut TestAppContext,
|
cx_b: &mut TestAppContext,
|
||||||
cx_c: &mut TestAppContext,
|
cx_c: &mut TestAppContext,
|
||||||
) {
|
) {
|
||||||
let window_b = cx_b.add_window(|_| EmptyView);
|
let window_b = cx_b.add_empty_window();
|
||||||
let mut server = TestServer::start(&executor).await;
|
let mut server = TestServer::start(executor).await;
|
||||||
let client_a = server.create_client(cx_a, "user_a").await;
|
let client_a = server.create_client(cx_a, "user_a").await;
|
||||||
let client_b = server.create_client(cx_b, "user_b").await;
|
let client_b = server.create_client(cx_b, "user_b").await;
|
||||||
let client_c = server.create_client(cx_c, "user_c").await;
|
let client_c = server.create_client(cx_c, "user_c").await;
|
||||||
|
@ -1050,7 +1078,7 @@ async fn test_share_project(
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let editor_b = window_b.add_view(cx_b, |cx| Editor::for_buffer(buffer_b, None, cx));
|
let editor_b = window_b.build_view(cx_b, |cx| Editor::for_buffer(buffer_b, None, cx));
|
||||||
|
|
||||||
// Client A sees client B's selection
|
// Client A sees client B's selection
|
||||||
executor.run_until_parked();
|
executor.run_until_parked();
|
||||||
|
@ -1164,10 +1192,12 @@ async fn test_on_input_format_from_host_to_guest(
|
||||||
.update(cx_a, |p, cx| p.open_buffer((worktree_id, "main.rs"), cx))
|
.update(cx_a, |p, cx| p.open_buffer((worktree_id, "main.rs"), cx))
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let window_a = cx_a.add_window(|_| EmptyView);
|
let window_a = cx_a.add_empty_window();
|
||||||
let editor_a = window_a.add_view(cx_a, |cx| {
|
let editor_a = window_a
|
||||||
Editor::for_buffer(buffer_a, Some(project_a.clone()), cx)
|
.update(cx_a, |_, cx| {
|
||||||
});
|
cx.build_view(|cx| Editor::for_buffer(buffer_a, Some(project_a.clone()), cx))
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
let fake_language_server = fake_language_servers.next().await.unwrap();
|
let fake_language_server = fake_language_servers.next().await.unwrap();
|
||||||
executor.run_until_parked();
|
executor.run_until_parked();
|
||||||
|
@ -1294,8 +1324,8 @@ async fn test_on_input_format_from_guest_to_host(
|
||||||
.update(cx_b, |p, cx| p.open_buffer((worktree_id, "main.rs"), cx))
|
.update(cx_b, |p, cx| p.open_buffer((worktree_id, "main.rs"), cx))
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let window_b = cx_b.add_window(|_| EmptyView);
|
let window_b = cx_b.add_empty_window();
|
||||||
let editor_b = window_b.add_view(cx_b, |cx| {
|
let editor_b = window_b.build_view(cx_b, |cx| {
|
||||||
Editor::for_buffer(buffer_b, Some(project_b.clone()), cx)
|
Editor::for_buffer(buffer_b, Some(project_b.clone()), cx)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1459,7 +1489,7 @@ async fn test_mutual_editor_inlay_hint_cache_update(
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let workspace_a = client_a.build_workspace(&project_a, cx_a).root(cx_a);
|
let workspace_a = client_a.build_workspace(&project_a, cx_a).root_view(cx_a);
|
||||||
cx_a.foreground().start_waiting();
|
cx_a.foreground().start_waiting();
|
||||||
|
|
||||||
// The host opens a rust file.
|
// The host opens a rust file.
|
||||||
|
|
|
@ -24,7 +24,7 @@ collections = { path = "../collections" }
|
||||||
gpui = { package = "gpui2", path = "../gpui2" }
|
gpui = { package = "gpui2", path = "../gpui2" }
|
||||||
language = { package = "language2", path = "../language2" }
|
language = { package = "language2", path = "../language2" }
|
||||||
settings = { package = "settings2", path = "../settings2" }
|
settings = { package = "settings2", path = "../settings2" }
|
||||||
theme = { path = "../theme" }
|
theme = { package = "theme2", path = "../theme2" }
|
||||||
lsp = { package = "lsp2", path = "../lsp2" }
|
lsp = { package = "lsp2", path = "../lsp2" }
|
||||||
node_runtime = { path = "../node_runtime"}
|
node_runtime = { path = "../node_runtime"}
|
||||||
util = { path = "../util" }
|
util = { path = "../util" }
|
||||||
|
|
|
@ -27,7 +27,6 @@ client = { package = "client2", path = "../client2" }
|
||||||
clock = { path = "../clock" }
|
clock = { path = "../clock" }
|
||||||
copilot = { package="copilot2", path = "../copilot2" }
|
copilot = { package="copilot2", path = "../copilot2" }
|
||||||
db = { package="db2", path = "../db2" }
|
db = { package="db2", path = "../db2" }
|
||||||
drag_and_drop = { path = "../drag_and_drop" }
|
|
||||||
collections = { path = "../collections" }
|
collections = { path = "../collections" }
|
||||||
# context_menu = { path = "../context_menu" }
|
# context_menu = { path = "../context_menu" }
|
||||||
fuzzy = { package = "fuzzy2", path = "../fuzzy2" }
|
fuzzy = { package = "fuzzy2", path = "../fuzzy2" }
|
||||||
|
|
|
@ -2023,24 +2023,24 @@ impl Editor {
|
||||||
dispatch_context
|
dispatch_context
|
||||||
}
|
}
|
||||||
|
|
||||||
// pub fn new_file(
|
pub fn new_file(
|
||||||
// workspace: &mut Workspace,
|
workspace: &mut Workspace,
|
||||||
// _: &workspace::NewFile,
|
_: &workspace::NewFile,
|
||||||
// cx: &mut ViewContext<Workspace>,
|
cx: &mut ViewContext<Workspace>,
|
||||||
// ) {
|
) {
|
||||||
// let project = workspace.project().clone();
|
let project = workspace.project().clone();
|
||||||
// if project.read(cx).is_remote() {
|
if project.read(cx).is_remote() {
|
||||||
// cx.propagate();
|
cx.propagate();
|
||||||
// } else if let Some(buffer) = project
|
} else if let Some(buffer) = project
|
||||||
// .update(cx, |project, cx| project.create_buffer("", None, cx))
|
.update(cx, |project, cx| project.create_buffer("", None, cx))
|
||||||
// .log_err()
|
.log_err()
|
||||||
// {
|
{
|
||||||
// workspace.add_item(
|
workspace.add_item(
|
||||||
// Box::new(cx.add_view(|cx| Editor::for_buffer(buffer, Some(project.clone()), cx))),
|
Box::new(cx.build_view(|cx| Editor::for_buffer(buffer, Some(project.clone()), cx))),
|
||||||
// cx,
|
cx,
|
||||||
// );
|
);
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
|
|
||||||
// pub fn new_file_in_direction(
|
// pub fn new_file_in_direction(
|
||||||
// workspace: &mut Workspace,
|
// workspace: &mut Workspace,
|
||||||
|
@ -2124,17 +2124,17 @@ impl Editor {
|
||||||
// )
|
// )
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// pub fn mode(&self) -> EditorMode {
|
pub fn mode(&self) -> EditorMode {
|
||||||
// self.mode
|
self.mode
|
||||||
// }
|
}
|
||||||
|
|
||||||
// pub fn collaboration_hub(&self) -> Option<&dyn CollaborationHub> {
|
pub fn collaboration_hub(&self) -> Option<&dyn CollaborationHub> {
|
||||||
// self.collaboration_hub.as_deref()
|
self.collaboration_hub.as_deref()
|
||||||
// }
|
}
|
||||||
|
|
||||||
// pub fn set_collaboration_hub(&mut self, hub: Box<dyn CollaborationHub>) {
|
pub fn set_collaboration_hub(&mut self, hub: Box<dyn CollaborationHub>) {
|
||||||
// self.collaboration_hub = Some(hub);
|
self.collaboration_hub = Some(hub);
|
||||||
// }
|
}
|
||||||
|
|
||||||
pub fn set_placeholder_text(
|
pub fn set_placeholder_text(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
|
|
@ -7,7 +7,7 @@ use crate::{
|
||||||
},
|
},
|
||||||
JoinLines,
|
JoinLines,
|
||||||
};
|
};
|
||||||
use drag_and_drop::DragAndDrop;
|
|
||||||
use futures::StreamExt;
|
use futures::StreamExt;
|
||||||
use gpui::{
|
use gpui::{
|
||||||
div,
|
div,
|
||||||
|
@ -517,7 +517,6 @@ fn test_clone(cx: &mut TestAppContext) {
|
||||||
async fn test_navigation_history(cx: &mut TestAppContext) {
|
async fn test_navigation_history(cx: &mut TestAppContext) {
|
||||||
init_test(cx, |_| {});
|
init_test(cx, |_| {});
|
||||||
|
|
||||||
cx.set_global(DragAndDrop::<Workspace>::default());
|
|
||||||
use workspace::item::Item;
|
use workspace::item::Item;
|
||||||
|
|
||||||
let fs = FakeFs::new(cx.executor());
|
let fs = FakeFs::new(cx.executor());
|
||||||
|
@ -3483,198 +3482,256 @@ fn test_split_selection_into_lines(cx: &mut TestAppContext) {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[gpui::test]
|
#[gpui::test]
|
||||||
fn test_add_selection_above_below(cx: &mut TestAppContext) {
|
async fn test_add_selection_above_below(cx: &mut TestAppContext) {
|
||||||
init_test(cx, |_| {});
|
init_test(cx, |_| {});
|
||||||
|
|
||||||
let view = cx.add_window(|cx| {
|
let mut cx = EditorTestContext::new(cx).await;
|
||||||
let buffer = MultiBuffer::build_simple("abc\ndefghi\n\njk\nlmno\n", cx);
|
|
||||||
build_editor(buffer, cx)
|
// let buffer = MultiBuffer::build_simple("abc\ndefghi\n\njk\nlmno\n", cx);
|
||||||
|
cx.set_state(indoc!(
|
||||||
|
r#"abc
|
||||||
|
defˇghi
|
||||||
|
|
||||||
|
jk
|
||||||
|
nlmo
|
||||||
|
"#
|
||||||
|
));
|
||||||
|
|
||||||
|
cx.update_editor(|editor, cx| {
|
||||||
|
editor.add_selection_above(&Default::default(), cx);
|
||||||
});
|
});
|
||||||
|
|
||||||
view.update(cx, |view, cx| {
|
cx.assert_editor_state(indoc!(
|
||||||
view.change_selections(None, cx, |s| {
|
r#"abcˇ
|
||||||
s.select_display_ranges([DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)])
|
defˇghi
|
||||||
});
|
|
||||||
});
|
jk
|
||||||
view.update(cx, |view, cx| {
|
nlmo
|
||||||
view.add_selection_above(&AddSelectionAbove, cx);
|
"#
|
||||||
assert_eq!(
|
));
|
||||||
view.selections.display_ranges(cx),
|
|
||||||
vec![
|
cx.update_editor(|editor, cx| {
|
||||||
DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
|
editor.add_selection_above(&Default::default(), cx);
|
||||||
DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)
|
|
||||||
]
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
view.update(cx, |view, cx| {
|
cx.assert_editor_state(indoc!(
|
||||||
view.add_selection_above(&AddSelectionAbove, cx);
|
r#"abcˇ
|
||||||
assert_eq!(
|
defˇghi
|
||||||
view.selections.display_ranges(cx),
|
|
||||||
vec![
|
jk
|
||||||
DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
|
nlmo
|
||||||
DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)
|
"#
|
||||||
]
|
));
|
||||||
);
|
|
||||||
|
cx.update_editor(|view, cx| {
|
||||||
|
view.add_selection_below(&Default::default(), cx);
|
||||||
});
|
});
|
||||||
|
|
||||||
view.update(cx, |view, cx| {
|
cx.assert_editor_state(indoc!(
|
||||||
view.add_selection_below(&AddSelectionBelow, cx);
|
r#"abc
|
||||||
assert_eq!(
|
defˇghi
|
||||||
view.selections.display_ranges(cx),
|
|
||||||
vec![DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)]
|
|
||||||
);
|
|
||||||
|
|
||||||
view.undo_selection(&UndoSelection, cx);
|
jk
|
||||||
assert_eq!(
|
nlmo
|
||||||
view.selections.display_ranges(cx),
|
"#
|
||||||
vec![
|
));
|
||||||
DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
|
|
||||||
DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)
|
|
||||||
]
|
|
||||||
);
|
|
||||||
|
|
||||||
view.redo_selection(&RedoSelection, cx);
|
cx.update_editor(|view, cx| {
|
||||||
assert_eq!(
|
view.undo_selection(&Default::default(), cx);
|
||||||
view.selections.display_ranges(cx),
|
|
||||||
vec![DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)]
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
view.update(cx, |view, cx| {
|
cx.assert_editor_state(indoc!(
|
||||||
view.add_selection_below(&AddSelectionBelow, cx);
|
r#"abcˇ
|
||||||
assert_eq!(
|
defˇghi
|
||||||
view.selections.display_ranges(cx),
|
|
||||||
vec![
|
jk
|
||||||
DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3),
|
nlmo
|
||||||
DisplayPoint::new(4, 3)..DisplayPoint::new(4, 3)
|
"#
|
||||||
]
|
));
|
||||||
);
|
|
||||||
|
cx.update_editor(|view, cx| {
|
||||||
|
view.redo_selection(&Default::default(), cx);
|
||||||
});
|
});
|
||||||
|
|
||||||
view.update(cx, |view, cx| {
|
cx.assert_editor_state(indoc!(
|
||||||
view.add_selection_below(&AddSelectionBelow, cx);
|
r#"abc
|
||||||
assert_eq!(
|
defˇghi
|
||||||
view.selections.display_ranges(cx),
|
|
||||||
vec![
|
jk
|
||||||
DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3),
|
nlmo
|
||||||
DisplayPoint::new(4, 3)..DisplayPoint::new(4, 3)
|
"#
|
||||||
]
|
));
|
||||||
);
|
|
||||||
|
cx.update_editor(|view, cx| {
|
||||||
|
view.add_selection_below(&Default::default(), cx);
|
||||||
});
|
});
|
||||||
|
|
||||||
view.update(cx, |view, cx| {
|
cx.assert_editor_state(indoc!(
|
||||||
view.change_selections(None, cx, |s| {
|
r#"abc
|
||||||
s.select_display_ranges([DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3)])
|
defˇghi
|
||||||
});
|
|
||||||
});
|
jk
|
||||||
view.update(cx, |view, cx| {
|
nlmˇo
|
||||||
view.add_selection_below(&AddSelectionBelow, cx);
|
"#
|
||||||
assert_eq!(
|
));
|
||||||
view.selections.display_ranges(cx),
|
|
||||||
vec![
|
cx.update_editor(|view, cx| {
|
||||||
DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3),
|
view.add_selection_below(&Default::default(), cx);
|
||||||
DisplayPoint::new(4, 4)..DisplayPoint::new(4, 3)
|
|
||||||
]
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
view.update(cx, |view, cx| {
|
cx.assert_editor_state(indoc!(
|
||||||
view.add_selection_below(&AddSelectionBelow, cx);
|
r#"abc
|
||||||
assert_eq!(
|
defˇghi
|
||||||
view.selections.display_ranges(cx),
|
|
||||||
vec![
|
jk
|
||||||
DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3),
|
nlmˇo
|
||||||
DisplayPoint::new(4, 4)..DisplayPoint::new(4, 3)
|
"#
|
||||||
]
|
));
|
||||||
);
|
|
||||||
|
// change selections
|
||||||
|
cx.set_state(indoc!(
|
||||||
|
r#"abc
|
||||||
|
def«ˇg»hi
|
||||||
|
|
||||||
|
jk
|
||||||
|
nlmo
|
||||||
|
"#
|
||||||
|
));
|
||||||
|
|
||||||
|
cx.update_editor(|view, cx| {
|
||||||
|
view.add_selection_below(&Default::default(), cx);
|
||||||
});
|
});
|
||||||
|
|
||||||
view.update(cx, |view, cx| {
|
cx.assert_editor_state(indoc!(
|
||||||
view.add_selection_above(&AddSelectionAbove, cx);
|
r#"abc
|
||||||
assert_eq!(
|
def«ˇg»hi
|
||||||
view.selections.display_ranges(cx),
|
|
||||||
vec![DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3)]
|
jk
|
||||||
);
|
nlm«ˇo»
|
||||||
|
"#
|
||||||
|
));
|
||||||
|
|
||||||
|
cx.update_editor(|view, cx| {
|
||||||
|
view.add_selection_below(&Default::default(), cx);
|
||||||
});
|
});
|
||||||
|
|
||||||
view.update(cx, |view, cx| {
|
cx.assert_editor_state(indoc!(
|
||||||
view.add_selection_above(&AddSelectionAbove, cx);
|
r#"abc
|
||||||
assert_eq!(
|
def«ˇg»hi
|
||||||
view.selections.display_ranges(cx),
|
|
||||||
vec![DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3)]
|
jk
|
||||||
);
|
nlm«ˇo»
|
||||||
|
"#
|
||||||
|
));
|
||||||
|
|
||||||
|
cx.update_editor(|view, cx| {
|
||||||
|
view.add_selection_above(&Default::default(), cx);
|
||||||
});
|
});
|
||||||
|
|
||||||
view.update(cx, |view, cx| {
|
cx.assert_editor_state(indoc!(
|
||||||
view.change_selections(None, cx, |s| {
|
r#"abc
|
||||||
s.select_display_ranges([DisplayPoint::new(0, 1)..DisplayPoint::new(1, 4)])
|
def«ˇg»hi
|
||||||
});
|
|
||||||
view.add_selection_below(&AddSelectionBelow, cx);
|
jk
|
||||||
assert_eq!(
|
nlmo
|
||||||
view.selections.display_ranges(cx),
|
"#
|
||||||
vec![
|
));
|
||||||
DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
|
|
||||||
DisplayPoint::new(1, 1)..DisplayPoint::new(1, 4),
|
cx.update_editor(|view, cx| {
|
||||||
DisplayPoint::new(3, 1)..DisplayPoint::new(3, 2),
|
view.add_selection_above(&Default::default(), cx);
|
||||||
]
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
view.update(cx, |view, cx| {
|
cx.assert_editor_state(indoc!(
|
||||||
view.add_selection_below(&AddSelectionBelow, cx);
|
r#"abc
|
||||||
assert_eq!(
|
def«ˇg»hi
|
||||||
view.selections.display_ranges(cx),
|
|
||||||
vec![
|
jk
|
||||||
DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
|
nlmo
|
||||||
DisplayPoint::new(1, 1)..DisplayPoint::new(1, 4),
|
"#
|
||||||
DisplayPoint::new(3, 1)..DisplayPoint::new(3, 2),
|
));
|
||||||
DisplayPoint::new(4, 1)..DisplayPoint::new(4, 4),
|
|
||||||
]
|
// Change selections again
|
||||||
);
|
cx.set_state(indoc!(
|
||||||
|
r#"a«bc
|
||||||
|
defgˇ»hi
|
||||||
|
|
||||||
|
jk
|
||||||
|
nlmo
|
||||||
|
"#
|
||||||
|
));
|
||||||
|
|
||||||
|
cx.update_editor(|view, cx| {
|
||||||
|
view.add_selection_below(&Default::default(), cx);
|
||||||
});
|
});
|
||||||
|
|
||||||
view.update(cx, |view, cx| {
|
cx.assert_editor_state(indoc!(
|
||||||
view.add_selection_above(&AddSelectionAbove, cx);
|
r#"a«bcˇ»
|
||||||
assert_eq!(
|
d«efgˇ»hi
|
||||||
view.selections.display_ranges(cx),
|
|
||||||
vec![
|
j«kˇ»
|
||||||
DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
|
nlmo
|
||||||
DisplayPoint::new(1, 1)..DisplayPoint::new(1, 4),
|
"#
|
||||||
DisplayPoint::new(3, 1)..DisplayPoint::new(3, 2),
|
));
|
||||||
]
|
|
||||||
);
|
cx.update_editor(|view, cx| {
|
||||||
|
view.add_selection_below(&Default::default(), cx);
|
||||||
|
});
|
||||||
|
cx.assert_editor_state(indoc!(
|
||||||
|
r#"a«bcˇ»
|
||||||
|
d«efgˇ»hi
|
||||||
|
|
||||||
|
j«kˇ»
|
||||||
|
n«lmoˇ»
|
||||||
|
"#
|
||||||
|
));
|
||||||
|
cx.update_editor(|view, cx| {
|
||||||
|
view.add_selection_above(&Default::default(), cx);
|
||||||
});
|
});
|
||||||
|
|
||||||
view.update(cx, |view, cx| {
|
cx.assert_editor_state(indoc!(
|
||||||
view.change_selections(None, cx, |s| {
|
r#"a«bcˇ»
|
||||||
s.select_display_ranges([DisplayPoint::new(4, 3)..DisplayPoint::new(1, 1)])
|
d«efgˇ»hi
|
||||||
});
|
|
||||||
});
|
j«kˇ»
|
||||||
view.update(cx, |view, cx| {
|
nlmo
|
||||||
view.add_selection_above(&AddSelectionAbove, cx);
|
"#
|
||||||
assert_eq!(
|
));
|
||||||
view.selections.display_ranges(cx),
|
|
||||||
vec![
|
// Change selections again
|
||||||
DisplayPoint::new(0, 3)..DisplayPoint::new(0, 1),
|
cx.set_state(indoc!(
|
||||||
DisplayPoint::new(1, 3)..DisplayPoint::new(1, 1),
|
r#"abc
|
||||||
DisplayPoint::new(3, 2)..DisplayPoint::new(3, 1),
|
d«ˇefghi
|
||||||
DisplayPoint::new(4, 3)..DisplayPoint::new(4, 1),
|
|
||||||
]
|
jk
|
||||||
);
|
nlm»o
|
||||||
|
"#
|
||||||
|
));
|
||||||
|
|
||||||
|
cx.update_editor(|view, cx| {
|
||||||
|
view.add_selection_above(&Default::default(), cx);
|
||||||
});
|
});
|
||||||
|
|
||||||
view.update(cx, |view, cx| {
|
cx.assert_editor_state(indoc!(
|
||||||
view.add_selection_below(&AddSelectionBelow, cx);
|
r#"a«ˇbc»
|
||||||
assert_eq!(
|
d«ˇef»ghi
|
||||||
view.selections.display_ranges(cx),
|
|
||||||
vec![
|
j«ˇk»
|
||||||
DisplayPoint::new(1, 3)..DisplayPoint::new(1, 1),
|
n«ˇlm»o
|
||||||
DisplayPoint::new(3, 2)..DisplayPoint::new(3, 1),
|
"#
|
||||||
DisplayPoint::new(4, 3)..DisplayPoint::new(4, 1),
|
));
|
||||||
]
|
|
||||||
);
|
cx.update_editor(|view, cx| {
|
||||||
|
view.add_selection_below(&Default::default(), cx);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
cx.assert_editor_state(indoc!(
|
||||||
|
r#"abc
|
||||||
|
d«ˇef»ghi
|
||||||
|
|
||||||
|
j«ˇk»
|
||||||
|
n«ˇlm»o
|
||||||
|
"#
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[gpui::test]
|
#[gpui::test]
|
||||||
|
@ -6898,6 +6955,7 @@ async fn go_to_hunk(executor: BackgroundExecutor, cx: &mut gpui::TestAppContext)
|
||||||
&r#"
|
&r#"
|
||||||
ˇuse some::modified;
|
ˇuse some::modified;
|
||||||
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
println!("hello there");
|
println!("hello there");
|
||||||
|
|
||||||
|
@ -6919,6 +6977,7 @@ async fn go_to_hunk(executor: BackgroundExecutor, cx: &mut gpui::TestAppContext)
|
||||||
&r#"
|
&r#"
|
||||||
use some::modified;
|
use some::modified;
|
||||||
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
ˇ println!("hello there");
|
ˇ println!("hello there");
|
||||||
|
|
||||||
|
@ -6958,6 +7017,7 @@ async fn go_to_hunk(executor: BackgroundExecutor, cx: &mut gpui::TestAppContext)
|
||||||
&r#"
|
&r#"
|
||||||
use some::modified;
|
use some::modified;
|
||||||
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
ˇ println!("hello there");
|
ˇ println!("hello there");
|
||||||
|
|
||||||
|
@ -6981,6 +7041,7 @@ async fn go_to_hunk(executor: BackgroundExecutor, cx: &mut gpui::TestAppContext)
|
||||||
&r#"
|
&r#"
|
||||||
ˇuse some::modified;
|
ˇuse some::modified;
|
||||||
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
println!("hello there");
|
println!("hello there");
|
||||||
|
|
||||||
|
@ -7374,105 +7435,106 @@ async fn test_copilot_completion_invalidation(
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
#[gpui::test]
|
//todo!()
|
||||||
async fn test_copilot_multibuffer(executor: BackgroundExecutor, cx: &mut gpui::TestAppContext) {
|
// #[gpui::test]
|
||||||
init_test(cx, |_| {});
|
// async fn test_copilot_multibuffer(executor: BackgroundExecutor, cx: &mut gpui::TestAppContext) {
|
||||||
|
// init_test(cx, |_| {});
|
||||||
|
|
||||||
let (copilot, copilot_lsp) = Copilot::fake(cx);
|
// let (copilot, copilot_lsp) = Copilot::fake(cx);
|
||||||
cx.update(|cx| cx.set_global(copilot));
|
// cx.update(|cx| cx.set_global(copilot));
|
||||||
|
|
||||||
let buffer_1 = cx.build_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), "a = 1\nb = 2\n"));
|
// let buffer_1 = cx.build_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), "a = 1\nb = 2\n"));
|
||||||
let buffer_2 = cx.build_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), "c = 3\nd = 4\n"));
|
// let buffer_2 = cx.build_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), "c = 3\nd = 4\n"));
|
||||||
let multibuffer = cx.build_model(|cx| {
|
// let multibuffer = cx.build_model(|cx| {
|
||||||
let mut multibuffer = MultiBuffer::new(0);
|
// let mut multibuffer = MultiBuffer::new(0);
|
||||||
multibuffer.push_excerpts(
|
// multibuffer.push_excerpts(
|
||||||
buffer_1.clone(),
|
// buffer_1.clone(),
|
||||||
[ExcerptRange {
|
// [ExcerptRange {
|
||||||
context: Point::new(0, 0)..Point::new(2, 0),
|
// context: Point::new(0, 0)..Point::new(2, 0),
|
||||||
primary: None,
|
// primary: None,
|
||||||
}],
|
// }],
|
||||||
cx,
|
// cx,
|
||||||
);
|
// );
|
||||||
multibuffer.push_excerpts(
|
// multibuffer.push_excerpts(
|
||||||
buffer_2.clone(),
|
// buffer_2.clone(),
|
||||||
[ExcerptRange {
|
// [ExcerptRange {
|
||||||
context: Point::new(0, 0)..Point::new(2, 0),
|
// context: Point::new(0, 0)..Point::new(2, 0),
|
||||||
primary: None,
|
// primary: None,
|
||||||
}],
|
// }],
|
||||||
cx,
|
// cx,
|
||||||
);
|
// );
|
||||||
multibuffer
|
// multibuffer
|
||||||
});
|
// });
|
||||||
let editor = cx.add_window(|cx| build_editor(multibuffer, cx));
|
// let editor = cx.add_window(|cx| build_editor(multibuffer, cx));
|
||||||
|
|
||||||
handle_copilot_completion_request(
|
// handle_copilot_completion_request(
|
||||||
&copilot_lsp,
|
// &copilot_lsp,
|
||||||
vec![copilot::request::Completion {
|
// vec![copilot::request::Completion {
|
||||||
text: "b = 2 + a".into(),
|
// text: "b = 2 + a".into(),
|
||||||
range: lsp::Range::new(lsp::Position::new(1, 0), lsp::Position::new(1, 5)),
|
// range: lsp::Range::new(lsp::Position::new(1, 0), lsp::Position::new(1, 5)),
|
||||||
..Default::default()
|
// ..Default::default()
|
||||||
}],
|
// }],
|
||||||
vec![],
|
// vec![],
|
||||||
);
|
// );
|
||||||
editor.update(cx, |editor, cx| {
|
// editor.update(cx, |editor, cx| {
|
||||||
// Ensure copilot suggestions are shown for the first excerpt.
|
// // Ensure copilot suggestions are shown for the first excerpt.
|
||||||
editor.change_selections(None, cx, |s| {
|
// editor.change_selections(None, cx, |s| {
|
||||||
s.select_ranges([Point::new(1, 5)..Point::new(1, 5)])
|
// s.select_ranges([Point::new(1, 5)..Point::new(1, 5)])
|
||||||
});
|
// });
|
||||||
editor.next_copilot_suggestion(&Default::default(), cx);
|
// editor.next_copilot_suggestion(&Default::default(), cx);
|
||||||
});
|
// });
|
||||||
executor.advance_clock(COPILOT_DEBOUNCE_TIMEOUT);
|
// executor.advance_clock(COPILOT_DEBOUNCE_TIMEOUT);
|
||||||
editor.update(cx, |editor, cx| {
|
// editor.update(cx, |editor, cx| {
|
||||||
assert!(editor.has_active_copilot_suggestion(cx));
|
// assert!(editor.has_active_copilot_suggestion(cx));
|
||||||
assert_eq!(
|
// assert_eq!(
|
||||||
editor.display_text(cx),
|
// editor.display_text(cx),
|
||||||
"\n\na = 1\nb = 2 + a\n\n\n\nc = 3\nd = 4\n"
|
// "\n\na = 1\nb = 2 + a\n\n\n\nc = 3\nd = 4\n"
|
||||||
);
|
// );
|
||||||
assert_eq!(editor.text(cx), "a = 1\nb = 2\n\nc = 3\nd = 4\n");
|
// assert_eq!(editor.text(cx), "a = 1\nb = 2\n\nc = 3\nd = 4\n");
|
||||||
});
|
// });
|
||||||
|
|
||||||
handle_copilot_completion_request(
|
// handle_copilot_completion_request(
|
||||||
&copilot_lsp,
|
// &copilot_lsp,
|
||||||
vec![copilot::request::Completion {
|
// vec![copilot::request::Completion {
|
||||||
text: "d = 4 + c".into(),
|
// text: "d = 4 + c".into(),
|
||||||
range: lsp::Range::new(lsp::Position::new(1, 0), lsp::Position::new(1, 6)),
|
// range: lsp::Range::new(lsp::Position::new(1, 0), lsp::Position::new(1, 6)),
|
||||||
..Default::default()
|
// ..Default::default()
|
||||||
}],
|
// }],
|
||||||
vec![],
|
// vec![],
|
||||||
);
|
// );
|
||||||
editor.update(cx, |editor, cx| {
|
// editor.update(cx, |editor, cx| {
|
||||||
// Move to another excerpt, ensuring the suggestion gets cleared.
|
// // Move to another excerpt, ensuring the suggestion gets cleared.
|
||||||
editor.change_selections(None, cx, |s| {
|
// editor.change_selections(None, cx, |s| {
|
||||||
s.select_ranges([Point::new(4, 5)..Point::new(4, 5)])
|
// s.select_ranges([Point::new(4, 5)..Point::new(4, 5)])
|
||||||
});
|
// });
|
||||||
assert!(!editor.has_active_copilot_suggestion(cx));
|
// assert!(!editor.has_active_copilot_suggestion(cx));
|
||||||
assert_eq!(
|
// assert_eq!(
|
||||||
editor.display_text(cx),
|
// editor.display_text(cx),
|
||||||
"\n\na = 1\nb = 2\n\n\n\nc = 3\nd = 4\n"
|
// "\n\na = 1\nb = 2\n\n\n\nc = 3\nd = 4\n"
|
||||||
);
|
// );
|
||||||
assert_eq!(editor.text(cx), "a = 1\nb = 2\n\nc = 3\nd = 4\n");
|
// assert_eq!(editor.text(cx), "a = 1\nb = 2\n\nc = 3\nd = 4\n");
|
||||||
|
|
||||||
// Type a character, ensuring we don't even try to interpolate the previous suggestion.
|
// // Type a character, ensuring we don't even try to interpolate the previous suggestion.
|
||||||
editor.handle_input(" ", cx);
|
// editor.handle_input(" ", cx);
|
||||||
assert!(!editor.has_active_copilot_suggestion(cx));
|
// assert!(!editor.has_active_copilot_suggestion(cx));
|
||||||
assert_eq!(
|
// assert_eq!(
|
||||||
editor.display_text(cx),
|
// editor.display_text(cx),
|
||||||
"\n\na = 1\nb = 2\n\n\n\nc = 3\nd = 4 \n"
|
// "\n\na = 1\nb = 2\n\n\n\nc = 3\nd = 4 \n"
|
||||||
);
|
// );
|
||||||
assert_eq!(editor.text(cx), "a = 1\nb = 2\n\nc = 3\nd = 4 \n");
|
// assert_eq!(editor.text(cx), "a = 1\nb = 2\n\nc = 3\nd = 4 \n");
|
||||||
});
|
// });
|
||||||
|
|
||||||
// Ensure the new suggestion is displayed when the debounce timeout expires.
|
// // Ensure the new suggestion is displayed when the debounce timeout expires.
|
||||||
executor.advance_clock(COPILOT_DEBOUNCE_TIMEOUT);
|
// executor.advance_clock(COPILOT_DEBOUNCE_TIMEOUT);
|
||||||
editor.update(cx, |editor, cx| {
|
// editor.update(cx, |editor, cx| {
|
||||||
assert!(editor.has_active_copilot_suggestion(cx));
|
// assert!(editor.has_active_copilot_suggestion(cx));
|
||||||
assert_eq!(
|
// assert_eq!(
|
||||||
editor.display_text(cx),
|
// editor.display_text(cx),
|
||||||
"\n\na = 1\nb = 2\n\n\n\nc = 3\nd = 4 + c\n"
|
// "\n\na = 1\nb = 2\n\n\n\nc = 3\nd = 4 + c\n"
|
||||||
);
|
// );
|
||||||
assert_eq!(editor.text(cx), "a = 1\nb = 2\n\nc = 3\nd = 4 \n");
|
// assert_eq!(editor.text(cx), "a = 1\nb = 2\n\nc = 3\nd = 4 \n");
|
||||||
});
|
// });
|
||||||
}
|
// }
|
||||||
|
|
||||||
#[gpui::test]
|
#[gpui::test]
|
||||||
async fn test_copilot_disabled_globs(executor: BackgroundExecutor, cx: &mut gpui::TestAppContext) {
|
async fn test_copilot_disabled_globs(executor: BackgroundExecutor, cx: &mut gpui::TestAppContext) {
|
||||||
|
|
|
@ -1683,21 +1683,24 @@ impl EditorElement {
|
||||||
ShowScrollbar::Never => false,
|
ShowScrollbar::Never => false,
|
||||||
};
|
};
|
||||||
|
|
||||||
let fold_ranges: Vec<(BufferRow, Range<DisplayPoint>, Hsla)> = fold_ranges
|
let fold_ranges: Vec<(BufferRow, Range<DisplayPoint>, Hsla)> = Vec::new();
|
||||||
.into_iter()
|
// todo!()
|
||||||
.map(|(id, fold)| {
|
|
||||||
todo!("folds!")
|
|
||||||
// let color = self
|
|
||||||
// .style
|
|
||||||
// .folds
|
|
||||||
// .ellipses
|
|
||||||
// .background
|
|
||||||
// .style_for(&mut cx.mouse_state::<FoldMarkers>(id as usize))
|
|
||||||
// .color;
|
|
||||||
|
|
||||||
// (id, fold, color)
|
// fold_ranges
|
||||||
})
|
// .into_iter()
|
||||||
.collect();
|
// .map(|(id, fold)| {
|
||||||
|
// // todo!("folds!")
|
||||||
|
// // let color = self
|
||||||
|
// // .style
|
||||||
|
// // .folds
|
||||||
|
// // .ellipses
|
||||||
|
// // .background
|
||||||
|
// // .style_for(&mut cx.mouse_state::<FoldMarkers>(id as usize))
|
||||||
|
// // .color;
|
||||||
|
|
||||||
|
// // (id, fold, color)
|
||||||
|
// })
|
||||||
|
// .collect();
|
||||||
|
|
||||||
let head_for_relative = newest_selection_head.unwrap_or_else(|| {
|
let head_for_relative = newest_selection_head.unwrap_or_else(|| {
|
||||||
let newest = editor.selections.newest::<Point>(cx);
|
let newest = editor.selections.newest::<Point>(cx);
|
||||||
|
|
|
@ -315,11 +315,14 @@ impl SelectionsCollection {
|
||||||
|
|
||||||
let layed_out_line = display_map.lay_out_line_for_row(row, &text_layout_details);
|
let layed_out_line = display_map.lay_out_line_for_row(row, &text_layout_details);
|
||||||
|
|
||||||
|
dbg!("****START COL****");
|
||||||
let start_col = layed_out_line.closest_index_for_x(positions.start) as u32;
|
let start_col = layed_out_line.closest_index_for_x(positions.start) as u32;
|
||||||
if start_col < line_len || (is_empty && positions.start == layed_out_line.width) {
|
if start_col < line_len || (is_empty && positions.start == layed_out_line.width) {
|
||||||
let start = DisplayPoint::new(row, start_col);
|
let start = DisplayPoint::new(row, start_col);
|
||||||
|
dbg!("****END COL****");
|
||||||
let end_col = layed_out_line.closest_index_for_x(positions.end) as u32;
|
let end_col = layed_out_line.closest_index_for_x(positions.end) as u32;
|
||||||
let end = DisplayPoint::new(row, end_col);
|
let end = DisplayPoint::new(row, end_col);
|
||||||
|
dbg!(start_col, end_col);
|
||||||
|
|
||||||
Some(Selection {
|
Some(Selection {
|
||||||
id: post_inc(&mut self.next_selection_id),
|
id: post_inc(&mut self.next_selection_id),
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
AnyView, AnyWindowHandle, AppCell, AppContext, AsyncAppContext, BackgroundExecutor, Context,
|
div, AnyView, AnyWindowHandle, AppCell, AppContext, AsyncAppContext, BackgroundExecutor,
|
||||||
EventEmitter, ForegroundExecutor, InputEvent, KeyDownEvent, Keystroke, Model, ModelContext,
|
Context, Div, EventEmitter, ForegroundExecutor, InputEvent, KeyDownEvent, Keystroke, Model,
|
||||||
Render, Result, Task, TestDispatcher, TestPlatform, View, ViewContext, VisualContext,
|
ModelContext, Render, Result, Task, TestDispatcher, TestPlatform, View, ViewContext,
|
||||||
WindowContext, WindowHandle, WindowOptions,
|
VisualContext, WindowContext, WindowHandle, WindowOptions,
|
||||||
};
|
};
|
||||||
use anyhow::{anyhow, bail};
|
use anyhow::{anyhow, bail};
|
||||||
use futures::{Stream, StreamExt};
|
use futures::{Stream, StreamExt};
|
||||||
|
@ -132,6 +132,14 @@ impl TestAppContext {
|
||||||
cx.open_window(WindowOptions::default(), |cx| cx.build_view(build_window))
|
cx.open_window(WindowOptions::default(), |cx| cx.build_view(build_window))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn add_empty_window(&mut self) -> AnyWindowHandle {
|
||||||
|
let mut cx = self.app.borrow_mut();
|
||||||
|
cx.open_window(WindowOptions::default(), |cx| {
|
||||||
|
cx.build_view(|_| EmptyView {})
|
||||||
|
})
|
||||||
|
.any_handle
|
||||||
|
}
|
||||||
|
|
||||||
pub fn add_window_view<F, V>(&mut self, build_window: F) -> (View<V>, VisualTestContext)
|
pub fn add_window_view<F, V>(&mut self, build_window: F) -> (View<V>, VisualTestContext)
|
||||||
where
|
where
|
||||||
F: FnOnce(&mut ViewContext<V>) -> V,
|
F: FnOnce(&mut ViewContext<V>) -> V,
|
||||||
|
@ -456,3 +464,23 @@ impl<'a> VisualContext for VisualTestContext<'a> {
|
||||||
.unwrap()
|
.unwrap()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl AnyWindowHandle {
|
||||||
|
pub fn build_view<V: Render + 'static>(
|
||||||
|
&self,
|
||||||
|
cx: &mut TestAppContext,
|
||||||
|
build_view: impl FnOnce(&mut ViewContext<'_, V>) -> V,
|
||||||
|
) -> View<V> {
|
||||||
|
self.update(cx, |_, cx| cx.build_view(build_view)).unwrap()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct EmptyView {}
|
||||||
|
|
||||||
|
impl Render for EmptyView {
|
||||||
|
type Element = Div<Self>;
|
||||||
|
|
||||||
|
fn render(&mut self, _cx: &mut crate::ViewContext<Self>) -> Self::Element {
|
||||||
|
div()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -8,7 +8,8 @@ use parking_lot::Mutex;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
px, AtlasKey, AtlasTextureId, AtlasTile, Pixels, PlatformAtlas, PlatformDisplay,
|
px, AtlasKey, AtlasTextureId, AtlasTile, Pixels, PlatformAtlas, PlatformDisplay,
|
||||||
PlatformWindow, Point, Scene, Size, TileId, WindowAppearance, WindowBounds, WindowOptions,
|
PlatformInputHandler, PlatformWindow, Point, Scene, Size, TileId, WindowAppearance,
|
||||||
|
WindowBounds, WindowOptions,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
|
@ -23,6 +24,7 @@ pub struct TestWindow {
|
||||||
bounds: WindowBounds,
|
bounds: WindowBounds,
|
||||||
current_scene: Mutex<Option<Scene>>,
|
current_scene: Mutex<Option<Scene>>,
|
||||||
display: Rc<dyn PlatformDisplay>,
|
display: Rc<dyn PlatformDisplay>,
|
||||||
|
input_handler: Option<Box<dyn PlatformInputHandler>>,
|
||||||
|
|
||||||
handlers: Mutex<Handlers>,
|
handlers: Mutex<Handlers>,
|
||||||
sprite_atlas: Arc<dyn PlatformAtlas>,
|
sprite_atlas: Arc<dyn PlatformAtlas>,
|
||||||
|
@ -33,7 +35,7 @@ impl TestWindow {
|
||||||
bounds: options.bounds,
|
bounds: options.bounds,
|
||||||
current_scene: Default::default(),
|
current_scene: Default::default(),
|
||||||
display,
|
display,
|
||||||
|
input_handler: None,
|
||||||
sprite_atlas: Arc::new(TestAtlas::new()),
|
sprite_atlas: Arc::new(TestAtlas::new()),
|
||||||
handlers: Default::default(),
|
handlers: Default::default(),
|
||||||
}
|
}
|
||||||
|
@ -77,8 +79,8 @@ impl PlatformWindow for TestWindow {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_input_handler(&mut self, _input_handler: Box<dyn crate::PlatformInputHandler>) {
|
fn set_input_handler(&mut self, input_handler: Box<dyn crate::PlatformInputHandler>) {
|
||||||
todo!()
|
self.input_handler = Some(input_handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn prompt(
|
fn prompt(
|
||||||
|
|
|
@ -54,9 +54,9 @@ impl LineLayout {
|
||||||
pub fn closest_index_for_x(&self, x: Pixels) -> usize {
|
pub fn closest_index_for_x(&self, x: Pixels) -> usize {
|
||||||
let mut prev_index = 0;
|
let mut prev_index = 0;
|
||||||
let mut prev_x = px(0.);
|
let mut prev_x = px(0.);
|
||||||
|
|
||||||
for run in self.runs.iter() {
|
for run in self.runs.iter() {
|
||||||
for glyph in run.glyphs.iter() {
|
for glyph in run.glyphs.iter() {
|
||||||
|
glyph.index;
|
||||||
if glyph.position.x >= x {
|
if glyph.position.x >= x {
|
||||||
if glyph.position.x - x < x - prev_x {
|
if glyph.position.x - x < x - prev_x {
|
||||||
return glyph.index;
|
return glyph.index;
|
||||||
|
@ -68,7 +68,7 @@ impl LineLayout {
|
||||||
prev_x = glyph.position.x;
|
prev_x = glyph.position.x;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
prev_index
|
prev_index + 1
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn x_for_index(&self, index: usize) -> Pixels {
|
pub fn x_for_index(&self, index: usize) -> Pixels {
|
||||||
|
|
2868
crates/project_panel2/src/project_panel.rs
Normal file
2868
crates/project_panel2/src/project_panel.rs
Normal file
File diff suppressed because it is too large
Load diff
|
@ -1319,53 +1319,56 @@ impl Workspace {
|
||||||
// }))
|
// }))
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// pub fn prepare_to_close(
|
pub fn prepare_to_close(
|
||||||
// &mut self,
|
&mut self,
|
||||||
// quitting: bool,
|
quitting: bool,
|
||||||
// cx: &mut ViewContext<Self>,
|
cx: &mut ViewContext<Self>,
|
||||||
// ) -> Task<Result<bool>> {
|
) -> Task<Result<bool>> {
|
||||||
// let active_call = self.active_call().cloned();
|
//todo!(saveing)
|
||||||
// let window = cx.window();
|
// let active_call = self.active_call().cloned();
|
||||||
|
// let window = cx.window();
|
||||||
|
|
||||||
// cx.spawn(|this, mut cx| async move {
|
cx.spawn(|this, mut cx| async move {
|
||||||
// let workspace_count = cx
|
// let workspace_count = cx
|
||||||
// .windows()
|
// .windows()
|
||||||
// .into_iter()
|
// .into_iter()
|
||||||
// .filter(|window| window.root_is::<Workspace>())
|
// .filter(|window| window.root_is::<Workspace>())
|
||||||
// .count();
|
// .count();
|
||||||
|
|
||||||
// if let Some(active_call) = active_call {
|
// if let Some(active_call) = active_call {
|
||||||
// if !quitting
|
// if !quitting
|
||||||
// && workspace_count == 1
|
// && workspace_count == 1
|
||||||
// && active_call.read_with(&cx, |call, _| call.room().is_some())
|
// && active_call.read_with(&cx, |call, _| call.room().is_some())
|
||||||
// {
|
// {
|
||||||
// let answer = window.prompt(
|
// let answer = window.prompt(
|
||||||
// PromptLevel::Warning,
|
// PromptLevel::Warning,
|
||||||
// "Do you want to leave the current call?",
|
// "Do you want to leave the current call?",
|
||||||
// &["Close window and hang up", "Cancel"],
|
// &["Close window and hang up", "Cancel"],
|
||||||
// &mut cx,
|
// &mut cx,
|
||||||
// );
|
// );
|
||||||
|
|
||||||
// if let Some(mut answer) = answer {
|
// if let Some(mut answer) = answer {
|
||||||
// if answer.next().await == Some(1) {
|
// if answer.next().await == Some(1) {
|
||||||
// return anyhow::Ok(false);
|
// return anyhow::Ok(false);
|
||||||
// } else {
|
// } else {
|
||||||
// active_call
|
// active_call
|
||||||
// .update(&mut cx, |call, cx| call.hang_up(cx))
|
// .update(&mut cx, |call, cx| call.hang_up(cx))
|
||||||
// .await
|
// .await
|
||||||
// .log_err();
|
// .log_err();
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// Ok(this
|
Ok(
|
||||||
// .update(&mut cx, |this, cx| {
|
false, // this
|
||||||
// this.save_all_internal(SaveIntent::Close, cx)
|
// .update(&mut cx, |this, cx| {
|
||||||
// })?
|
// this.save_all_internal(SaveIntent::Close, cx)
|
||||||
// .await?)
|
// })?
|
||||||
// })
|
// .await?
|
||||||
// }
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// fn save_all(
|
// fn save_all(
|
||||||
// &mut self,
|
// &mut self,
|
||||||
|
|
|
@ -9,6 +9,7 @@ use backtrace::Backtrace;
|
||||||
use cli::FORCE_CLI_MODE_ENV_VAR_NAME;
|
use cli::FORCE_CLI_MODE_ENV_VAR_NAME;
|
||||||
use client::UserStore;
|
use client::UserStore;
|
||||||
use db::kvp::KEY_VALUE_STORE;
|
use db::kvp::KEY_VALUE_STORE;
|
||||||
|
use editor::Editor;
|
||||||
use fs::RealFs;
|
use fs::RealFs;
|
||||||
use futures::StreamExt;
|
use futures::StreamExt;
|
||||||
use gpui::{Action, App, AppContext, AsyncAppContext, Context, SemanticVersion, Task};
|
use gpui::{Action, App, AppContext, AsyncAppContext, Context, SemanticVersion, Task};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue