Skip to content

Commit

Permalink
Fix panic when using set-language on a scratch buffer
Browse files Browse the repository at this point in the history
This commit adds a dummy URL for scratch buffers.

* Add Document::scratch_url() to generate a dummy URL for the scratch buffer.
  The format of the URL is `file://<current working dir>/scratch<document id>`.
  The scheme is `file://` in order to confrom to LSP DocumentUri format and
  the DocumentUri on the LSP side is made unique using the document id.
* Send textDocument/didClose notification to LSP server when a scratch buffer
  is written as from that point on it will have a valid URL and the dummy
  connection is no longer needed.
  • Loading branch information
zen3ger committed Apr 7, 2022
1 parent b03421a commit b615c88
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 1 deletion.
4 changes: 4 additions & 0 deletions helix-term/src/commands/typed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,7 @@ fn buffer_previous(
fn write_impl(cx: &mut compositor::Context, path: Option<&Cow<str>>) -> anyhow::Result<()> {
let jobs = &mut cx.jobs;
let doc = doc_mut!(cx.editor);
let doc_was_scratch = doc.path().is_none();

if let Some(ref path) = path {
doc.set_path(Some(path.as_ref().as_ref()))
Expand All @@ -217,6 +218,9 @@ fn write_impl(cx: &mut compositor::Context, path: Option<&Cow<str>>) -> anyhow::

if path.is_some() {
let id = doc.id();
if doc_was_scratch {
let _ = doc.no_longer_scratch();
}
doc.detect_language(cx.editor.syn_loader.clone());
let _ = cx.editor.refresh_language_server(id);
}
Expand Down
23 changes: 22 additions & 1 deletion helix-view/src/document.rs
Original file line number Diff line number Diff line change
Expand Up @@ -506,6 +506,17 @@ impl Document {
}
}

// TODO: better name
pub fn no_longer_scratch(&mut self) -> Option<()> {
if let Some(language_server) = self.language_server() {
let scratch_url = Document::scratch_url(self.id()).ok()?;
let identifier = lsp::TextDocumentIdentifier::new(scratch_url);
tokio::spawn(language_server.text_document_did_close(identifier));
self.language_server = None;
}
Some(())
}

/// Detect the programming language based on the file type.
pub fn detect_language(&mut self, config_loader: Arc<syntax::Loader>) {
if let Some(path) = &self.path {
Expand Down Expand Up @@ -902,7 +913,17 @@ impl Document {

/// File path as a URL.
pub fn url(&self) -> Option<Url> {
Url::from_file_path(self.path()?).ok()
if let Some(ref path) = self.path {
Url::from_file_path(path).ok()
} else {
Document::scratch_url(self.id()).ok()
}
}

fn scratch_url(doc_id: DocumentId) -> Result<Url, ()> {
let cwd = std::env::current_dir().map_err(|_| ())?;
let path = cwd.join(format!("scratch{}", doc_id));
Url::from_file_path(path)
}

#[inline]
Expand Down

0 comments on commit b615c88

Please sign in to comment.