diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index 4b75627ef3..857b33f625 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -940,9 +940,15 @@ impl Editor { _: &workspace::OpenNew, cx: &mut ViewContext, ) { - let buffer = cx - .add_model(|cx| Buffer::new(0, "", cx).with_language(language::PLAIN_TEXT.clone(), cx)); - workspace.open_item(BufferItemHandle(buffer), cx); + let project = workspace.project(); + if project.read(cx).is_remote() { + cx.propagate_action(); + } else if let Some(buffer) = project + .update(cx, |project, cx| project.create_buffer(cx)) + .log_err() + { + workspace.open_item(BufferItemHandle(buffer), cx); + } } pub fn replica_id(&self, cx: &AppContext) -> ReplicaId { diff --git a/crates/project/src/project.rs b/crates/project/src/project.rs index a89317db90..501cca2822 100644 --- a/crates/project/src/project.rs +++ b/crates/project/src/project.rs @@ -687,6 +687,18 @@ impl Project { !self.is_local() } + pub fn create_buffer(&mut self, cx: &mut ModelContext) -> Result> { + if self.is_remote() { + return Err(anyhow!("creating buffers as a guest is not supported yet")); + } + + let buffer = cx.add_model(|cx| { + Buffer::new(self.replica_id(), "", cx).with_language(language::PLAIN_TEXT.clone(), cx) + }); + self.register_buffer(&buffer, None, cx)?; + Ok(buffer) + } + pub fn open_buffer( &mut self, path: impl Into, @@ -4113,6 +4125,48 @@ mod tests { assert_eq!(new_text, buffer.read_with(cx, |buffer, _| buffer.text())); } + #[gpui::test] + async fn test_save_as(cx: &mut gpui::TestAppContext) { + let fs = FakeFs::new(cx.background()); + fs.insert_tree("/dir", json!({})).await; + + let project = Project::test(fs.clone(), cx); + let (worktree, _) = project + .update(cx, |project, cx| { + project.find_or_create_local_worktree("/dir", true, cx) + }) + .await + .unwrap(); + let worktree_id = worktree.read_with(cx, |worktree, _| worktree.id()); + + let buffer = project.update(cx, |project, cx| project.create_buffer(cx).unwrap()); + buffer.update(cx, |buffer, cx| { + buffer.edit([0..0], "abc", cx); + assert!(buffer.is_dirty()); + assert!(!buffer.has_conflict()); + }); + project + .update(cx, |project, cx| { + project.save_buffer_as(buffer.clone(), "/dir/file1".into(), cx) + }) + .await + .unwrap(); + assert_eq!(fs.load(Path::new("/dir/file1")).await.unwrap(), "abc"); + buffer.read_with(cx, |buffer, cx| { + assert_eq!(buffer.file().unwrap().full_path(cx), Path::new("dir/file1")); + assert!(!buffer.is_dirty()); + assert!(!buffer.has_conflict()); + }); + + let opened_buffer = project + .update(cx, |project, cx| { + project.open_buffer((worktree_id, "file1"), cx) + }) + .await + .unwrap(); + assert_eq!(opened_buffer, buffer); + } + #[gpui::test(retries = 5)] async fn test_rescan_and_remote_updates(cx: &mut gpui::TestAppContext) { let dir = temp_tree(json!({