Skip to content

Commit

Permalink
feat: add lsp support when moving files
Browse files Browse the repository at this point in the history
  • Loading branch information
yo-main committed Oct 22, 2023
1 parent 8cc879a commit 7ffa81e
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 7 deletions.
50 changes: 50 additions & 0 deletions helix-lsp/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1341,6 +1341,56 @@ impl Client {
Some(self.call::<lsp::request::DocumentSymbolRequest>(params))
}

pub fn prepare_file_rename(
&self,
old_uri: String,
new_uri: String,
) -> Option<impl Future<Output = Result<lsp::WorkspaceEdit>>> {
let capabilities = self.capabilities.get().unwrap();

// Return early if the server does not support willRename feature
match &capabilities.workspace {
Some(workspace) => match &workspace.file_operations {
Some(op) => {
op.will_rename.as_ref()?;
}
_ => return None,
},
_ => return None,
}

let files = vec![lsp::FileRename { old_uri, new_uri }];
let request = self.call::<lsp::request::WillRenameFiles>(lsp::RenameFilesParams { files });

Some(async move {
let json = request.await?;
let response: Option<lsp::WorkspaceEdit> = serde_json::from_value(json)?;
Ok(response.unwrap_or_default())
})
}

pub fn did_file_rename(
&self,
old_uri: String,
new_uri: String,
) -> Option<impl Future<Output = std::result::Result<(), Error>>> {
let capabilities = self.capabilities.get().unwrap();

// Return early if the server does not support DidRename feature
match &capabilities.workspace {
Some(workspace) => match &workspace.file_operations {
Some(op) => {
op.did_rename.as_ref()?;
}
_ => return None,
},
_ => return None,
}

let files = vec![lsp::FileRename { old_uri, new_uri }];
Some(self.notify::<lsp::notification::DidRenameFiles>(lsp::RenameFilesParams { files }))
}

pub fn prepare_rename(
&self,
text_document: lsp::TextDocumentIdentifier,
Expand Down
37 changes: 30 additions & 7 deletions helix-term/src/commands/typed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2419,22 +2419,45 @@ fn move_buffer(

ensure!(args.len() == 1, format!(":move takes one argument"));

let new_path =
helix_core::path::get_normalized_path(&PathBuf::from(args.first().unwrap().as_ref()));
let (_, doc) = current!(cx.editor);

let new_path = args.first().unwrap().to_string();
let doc = doc!(cx.editor);
let old_path = doc
.path()
.ok_or_else(|| anyhow!("Scratch buffer cannot be moved. Use :write instead"))?
.clone();
.to_string_lossy()
.to_string();

let edit = doc.language_servers().find_map(|lsp| {
if let Some(future) = lsp.prepare_file_rename(old_path.clone(), new_path.clone()) {
match helix_lsp::block_on(future) {
Ok(edit) => return Some(edit),
Err(e) => {
log::error!("LSP willRename request failed: {:?}", e);
}
}
};
None
});

doc.set_path(Some(new_path.as_path()));
if edit.is_some() {
if let Err(e) =
apply_workspace_edit(cx.editor, helix_lsp::OffsetEncoding::Utf8, &edit.unwrap())
{
log::error!(":move command failed to apply edits: {:?}", e);
};
}

let doc = doc_mut!(cx.editor);
doc.set_path(Some(&PathBuf::from(&new_path)));
if let Err(e) = std::fs::rename(&old_path, doc.path().unwrap()) {
doc.set_path(Some(old_path.as_path()));
doc.set_path(Some(&PathBuf::from(old_path)));
bail!("Could not move file: {}", e);
};

doc.language_servers().for_each(|lsp| {
lsp.did_file_rename(old_path.clone(), new_path.clone());
});

Ok(())
}

Expand Down

0 comments on commit 7ffa81e

Please sign in to comment.