mirror of
https://github.com/helix-editor/helix.git
synced 2025-04-02 02:17:44 +03:00
Add document and LSP lifecycle events, move some callbacks into hooks
This adds events for: * a document being opened * a document being closed * a language server sending the initialized notification * a language server exiting and also moves some handling done for these scenarios into hooks, generally moving more into helix-view. A hook is also added on `DocumentDidChange` which sends the `text_document_did_change` notification - this resolves a TODO in `document`.
This commit is contained in:
parent
2cc33b5c47
commit
6da1a79d80
8 changed files with 101 additions and 45 deletions
|
@ -704,28 +704,10 @@ impl Application {
|
|||
language_server.did_change_configuration(config.clone());
|
||||
}
|
||||
|
||||
let docs = self
|
||||
.editor
|
||||
.documents()
|
||||
.filter(|doc| doc.supports_language_server(server_id));
|
||||
|
||||
// trigger textDocument/didOpen for docs that are already open
|
||||
for doc in docs {
|
||||
let url = match doc.url() {
|
||||
Some(url) => url,
|
||||
None => continue, // skip documents with no path
|
||||
};
|
||||
|
||||
let language_id =
|
||||
doc.language_id().map(ToOwned::to_owned).unwrap_or_default();
|
||||
|
||||
language_server.text_document_did_open(
|
||||
url,
|
||||
doc.version(),
|
||||
doc.text(),
|
||||
language_id,
|
||||
);
|
||||
}
|
||||
helix_event::dispatch(helix_view::events::LanguageServerInitialized {
|
||||
editor: &mut self.editor,
|
||||
server_id,
|
||||
});
|
||||
}
|
||||
Notification::PublishDiagnostics(params) => {
|
||||
let uri = match helix_core::Uri::try_from(params.uri) {
|
||||
|
@ -870,6 +852,11 @@ impl Application {
|
|||
doc.clear_diagnostics_for_language_server(server_id);
|
||||
}
|
||||
|
||||
helix_event::dispatch(helix_view::events::LanguageServerExited {
|
||||
editor: &mut self.editor,
|
||||
server_id,
|
||||
});
|
||||
|
||||
// Remove the language server from the registry.
|
||||
self.editor.language_servers.remove_by_id(server_id);
|
||||
}
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
use helix_event::{events, register_event};
|
||||
use helix_view::document::Mode;
|
||||
use helix_view::events::{
|
||||
DiagnosticsDidChange, DocumentDidChange, DocumentFocusLost, SelectionDidChange,
|
||||
DiagnosticsDidChange, DocumentDidChange, DocumentDidClose, DocumentDidOpen, DocumentFocusLost,
|
||||
LanguageServerExited, LanguageServerInitialized, SelectionDidChange,
|
||||
};
|
||||
|
||||
use crate::commands;
|
||||
|
@ -17,8 +18,12 @@ pub fn register() {
|
|||
register_event::<OnModeSwitch>();
|
||||
register_event::<PostInsertChar>();
|
||||
register_event::<PostCommand>();
|
||||
register_event::<DocumentDidOpen>();
|
||||
register_event::<DocumentDidChange>();
|
||||
register_event::<DocumentDidClose>();
|
||||
register_event::<DocumentFocusLost>();
|
||||
register_event::<SelectionDidChange>();
|
||||
register_event::<DiagnosticsDidChange>();
|
||||
register_event::<LanguageServerInitialized>();
|
||||
register_event::<LanguageServerExited>();
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@ pub fn setup(config: Arc<ArcSwap<Config>>) -> Handlers {
|
|||
auto_save,
|
||||
};
|
||||
|
||||
helix_view::handlers::register_hooks(&handlers);
|
||||
completion::register_hooks(&handlers);
|
||||
signature_help::register_hooks(&handlers);
|
||||
auto_save::register_hooks(&handlers);
|
||||
|
|
|
@ -1489,19 +1489,6 @@ impl Document {
|
|||
});
|
||||
}
|
||||
|
||||
if emit_lsp_notification {
|
||||
// TODO: move to hook
|
||||
// emit lsp notification
|
||||
for language_server in self.language_servers() {
|
||||
let _ = language_server.text_document_did_change(
|
||||
self.versioned_identifier(),
|
||||
&old_doc,
|
||||
self.text(),
|
||||
changes,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ use crate::{
|
|||
document::{
|
||||
DocumentOpenError, DocumentSavedEventFuture, DocumentSavedEventResult, Mode, SavePoint,
|
||||
},
|
||||
events::DocumentFocusLost,
|
||||
events::{DocumentDidClose, DocumentDidOpen, DocumentFocusLost},
|
||||
graphics::{CursorKind, Rect},
|
||||
handlers::Handlers,
|
||||
info::Info,
|
||||
|
@ -1783,10 +1783,16 @@ impl Editor {
|
|||
let id = self.new_document(doc);
|
||||
self.launch_language_servers(id);
|
||||
|
||||
helix_event::dispatch(DocumentDidOpen {
|
||||
editor: self,
|
||||
doc: id,
|
||||
});
|
||||
|
||||
id
|
||||
};
|
||||
|
||||
self.switch(id, action);
|
||||
|
||||
Ok(id)
|
||||
}
|
||||
|
||||
|
@ -1800,7 +1806,7 @@ impl Editor {
|
|||
}
|
||||
|
||||
pub fn close_document(&mut self, doc_id: DocumentId, force: bool) -> Result<(), CloseError> {
|
||||
let doc = match self.documents.get_mut(&doc_id) {
|
||||
let doc = match self.documents.remove(&doc_id) {
|
||||
Some(doc) => doc,
|
||||
None => return Err(CloseError::DoesNotExist),
|
||||
};
|
||||
|
@ -1811,10 +1817,6 @@ impl Editor {
|
|||
// This will also disallow any follow-up writes
|
||||
self.saves.remove(&doc_id);
|
||||
|
||||
for language_server in doc.language_servers() {
|
||||
language_server.text_document_did_close(doc.identifier());
|
||||
}
|
||||
|
||||
enum Action {
|
||||
Close(ViewId),
|
||||
ReplaceDoc(ViewId, DocumentId),
|
||||
|
@ -1851,8 +1853,6 @@ impl Editor {
|
|||
}
|
||||
}
|
||||
|
||||
self.documents.remove(&doc_id);
|
||||
|
||||
// If the document we removed was visible in all views, we will have no more views. We don't
|
||||
// want to close the editor just for a simple buffer close, so we need to create a new view
|
||||
// containing either an existing document, or a brand new document.
|
||||
|
@ -1872,6 +1872,8 @@ impl Editor {
|
|||
|
||||
self._refresh();
|
||||
|
||||
helix_event::dispatch(DocumentDidClose { editor: self, doc });
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
|
@ -1,9 +1,14 @@
|
|||
use helix_core::{ChangeSet, Rope};
|
||||
use helix_event::events;
|
||||
use helix_lsp::LanguageServerId;
|
||||
|
||||
use crate::{Document, DocumentId, Editor, ViewId};
|
||||
|
||||
events! {
|
||||
DocumentDidOpen<'a> {
|
||||
editor: &'a mut Editor,
|
||||
doc: DocumentId
|
||||
}
|
||||
DocumentDidChange<'a> {
|
||||
doc: &'a mut Document,
|
||||
view: ViewId,
|
||||
|
@ -11,8 +16,21 @@ events! {
|
|||
changes: &'a ChangeSet,
|
||||
ghost_transaction: bool
|
||||
}
|
||||
DocumentDidClose<'a> {
|
||||
editor: &'a mut Editor,
|
||||
doc: Document
|
||||
}
|
||||
SelectionDidChange<'a> { doc: &'a mut Document, view: ViewId }
|
||||
DiagnosticsDidChange<'a> { editor: &'a mut Editor, doc: DocumentId }
|
||||
// called **after** a document loses focus (but not when its closed)
|
||||
DocumentFocusLost<'a> { editor: &'a mut Editor, doc: DocumentId }
|
||||
|
||||
LanguageServerInitialized<'a> {
|
||||
editor: &'a mut Editor,
|
||||
server_id: LanguageServerId
|
||||
}
|
||||
LanguageServerExited<'a> {
|
||||
editor: &'a mut Editor,
|
||||
server_id: LanguageServerId
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,3 +46,7 @@ impl Handlers {
|
|||
send_blocking(&self.signature_hints, event)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn register_hooks(handlers: &Handlers) {
|
||||
lsp::register_hooks(handlers);
|
||||
}
|
||||
|
|
|
@ -2,13 +2,18 @@ use std::collections::btree_map::Entry;
|
|||
use std::fmt::Display;
|
||||
|
||||
use crate::editor::Action;
|
||||
use crate::events::DiagnosticsDidChange;
|
||||
use crate::events::{
|
||||
DiagnosticsDidChange, DocumentDidChange, DocumentDidClose, LanguageServerInitialized,
|
||||
};
|
||||
use crate::Editor;
|
||||
use helix_core::diagnostic::DiagnosticProvider;
|
||||
use helix_core::Uri;
|
||||
use helix_event::register_hook;
|
||||
use helix_lsp::util::generate_transaction_from_edits;
|
||||
use helix_lsp::{lsp, LanguageServerId, OffsetEncoding};
|
||||
|
||||
use super::Handlers;
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||
pub enum SignatureHelpInvoked {
|
||||
Automatic,
|
||||
|
@ -381,3 +386,50 @@ impl Editor {
|
|||
});
|
||||
}
|
||||
}
|
||||
|
||||
pub fn register_hooks(_handlers: &Handlers) {
|
||||
register_hook!(move |event: &mut LanguageServerInitialized<'_>| {
|
||||
let language_server = event.editor.language_server_by_id(event.server_id).unwrap();
|
||||
|
||||
for doc in event
|
||||
.editor
|
||||
.documents()
|
||||
.filter(|doc| doc.supports_language_server(event.server_id))
|
||||
{
|
||||
let Some(url) = doc.url() else {
|
||||
continue;
|
||||
};
|
||||
|
||||
let language_id = doc.language_id().map(ToOwned::to_owned).unwrap_or_default();
|
||||
|
||||
language_server.text_document_did_open(url, doc.version(), doc.text(), language_id);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
});
|
||||
|
||||
register_hook!(move |event: &mut DocumentDidChange<'_>| {
|
||||
// Send textDocument/didChange notifications.
|
||||
if !event.ghost_transaction {
|
||||
for language_server in event.doc.language_servers() {
|
||||
language_server.text_document_did_change(
|
||||
event.doc.versioned_identifier(),
|
||||
event.old_text,
|
||||
event.doc.text(),
|
||||
event.changes,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
});
|
||||
|
||||
register_hook!(move |event: &mut DocumentDidClose<'_>| {
|
||||
// Send textDocument/didClose notifications.
|
||||
for language_server in event.doc.language_servers() {
|
||||
language_server.text_document_did_close(event.doc.identifier());
|
||||
}
|
||||
|
||||
Ok(())
|
||||
});
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue