@@ -940,9 +940,15 @@ impl Editor {
_: &workspace::OpenNew,
cx: &mut ViewContext<Workspace>,
) {
- 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 {
@@ -715,6 +715,18 @@ impl Project {
!self.is_local()
}
+ pub fn create_buffer(&mut self, cx: &mut ModelContext<Self>) -> Result<ModelHandle<Buffer>> {
+ 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<ProjectPath>,
@@ -1342,15 +1354,47 @@ impl Project {
}
for (buffer, buffer_abs_path, lang_server) in local_buffers {
- let lsp_edits = lang_server
- .request::<lsp::request::Formatting>(lsp::DocumentFormattingParams {
- text_document: lsp::TextDocumentIdentifier::new(
- lsp::Url::from_file_path(&buffer_abs_path).unwrap(),
- ),
- options: Default::default(),
- work_done_progress_params: Default::default(),
- })
- .await?;
+ let capabilities = if let Some(capabilities) = lang_server.capabilities().await {
+ capabilities
+ } else {
+ continue;
+ };
+
+ let text_document = lsp::TextDocumentIdentifier::new(
+ lsp::Url::from_file_path(&buffer_abs_path).unwrap(),
+ );
+ let lsp_edits = if capabilities
+ .document_formatting_provider
+ .map_or(false, |provider| provider != lsp::OneOf::Left(false))
+ {
+ lang_server
+ .request::<lsp::request::Formatting>(lsp::DocumentFormattingParams {
+ text_document,
+ options: Default::default(),
+ work_done_progress_params: Default::default(),
+ })
+ .await?
+ } else if capabilities
+ .document_range_formatting_provider
+ .map_or(false, |provider| provider != lsp::OneOf::Left(false))
+ {
+ let buffer_start = lsp::Position::new(0, 0);
+ let buffer_end = buffer
+ .read_with(&cx, |buffer, _| buffer.max_point_utf16())
+ .to_lsp_position();
+ lang_server
+ .request::<lsp::request::RangeFormatting>(
+ lsp::DocumentRangeFormattingParams {
+ text_document,
+ range: lsp::Range::new(buffer_start, buffer_end),
+ options: Default::default(),
+ work_done_progress_params: Default::default(),
+ },
+ )
+ .await?
+ } else {
+ continue;
+ };
if let Some(lsp_edits) = lsp_edits {
let edits = buffer
@@ -4128,6 +4172,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!({