aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBlaž Hrastnik2021-03-14 08:13:55 +0000
committerBlaž Hrastnik2021-03-14 08:14:34 +0000
commitbb87b08fc9677ddf0f083a2297c23c17144470e2 (patch)
treeccbd0124469f4b50ed423af9b8ef328420bd68e7
parent1cf887dea93f7aa2184772fa2073751f031c5bf3 (diff)
Configure language servers via LanguageConfiguration.
-rw-r--r--helix-core/src/syntax.rs22
-rw-r--r--helix-lsp/src/lib.rs42
-rw-r--r--helix-view/src/document.rs30
-rw-r--r--helix-view/src/editor.rs3
4 files changed, 59 insertions, 38 deletions
diff --git a/helix-core/src/syntax.rs b/helix-core/src/syntax.rs
index 54aa78cf..499d91d1 100644
--- a/helix-core/src/syntax.rs
+++ b/helix-core/src/syntax.rs
@@ -11,20 +11,27 @@ use once_cell::sync::{Lazy, OnceCell};
// largely based on tree-sitter/cli/src/loader.rs
pub struct LanguageConfiguration {
- pub(crate) scope: String, // source.rust
- pub(crate) file_types: Vec<String>, // filename ends_with? <Gemfile, rb, etc>
+ pub scope: String, // source.rust
+ pub file_types: Vec<String>, // filename ends_with? <Gemfile, rb, etc>
+ pub roots: Vec<String>, // these indicate project roots <.git, Cargo.toml>
- pub(crate) path: PathBuf,
+ pub path: PathBuf,
+ // root_path for tree-sitter (^)
// content_regex
// injection_regex
// first_line_regex
//
- // root_path
//
pub(crate) language_id: Lang,
pub(crate) highlight_config: OnceCell<Option<Arc<HighlightConfiguration>>>,
// tags_config OnceCell<> https://github.com/tree-sitter/tree-sitter/pull/583
+ pub language_server_config: Option<LanguageServerConfiguration>,
+}
+
+pub struct LanguageServerConfiguration {
+ pub command: String,
+ pub args: Vec<String>,
}
impl LanguageConfiguration {
@@ -90,6 +97,11 @@ impl Loader {
highlight_config: OnceCell::new(),
//
path: "../helix-syntax/languages/tree-sitter-rust".into(),
+ roots: vec![],
+ language_server_config: Some(LanguageServerConfiguration {
+ command: "rust-analyzer".to_string(),
+ args: vec![],
+ }),
},
LanguageConfiguration {
scope: "source.toml".to_string(),
@@ -98,6 +110,8 @@ impl Loader {
highlight_config: OnceCell::new(),
//
path: "../helix-syntax/languages/tree-sitter-toml".into(),
+ roots: vec![],
+ language_server_config: None,
},
];
diff --git a/helix-lsp/src/lib.rs b/helix-lsp/src/lib.rs
index 93bc06b5..0d04b711 100644
--- a/helix-lsp/src/lib.rs
+++ b/helix-lsp/src/lib.rs
@@ -10,6 +10,8 @@ pub use once_cell::sync::{Lazy, OnceCell};
pub use client::Client;
pub use lsp::{Position, Url};
+use helix_core::syntax::LanguageConfiguration;
+
use thiserror::Error;
use std::{collections::HashMap, sync::Arc};
@@ -106,7 +108,7 @@ use crate::select_all::SelectAll;
use smol::channel::Receiver;
pub struct Registry {
- inner: HashMap<LanguageId, OnceCell<Arc<Client>>>,
+ inner: HashMap<LanguageId, Arc<Client>>,
pub incoming: SelectAll<Receiver<Call>>,
}
@@ -119,35 +121,43 @@ impl Default for Registry {
impl Registry {
pub fn new() -> Self {
- let mut inner = HashMap::new();
-
- inner.insert("source.rust".to_string(), OnceCell::new());
-
Self {
- inner,
+ inner: HashMap::new(),
incoming: SelectAll::new(),
}
}
- pub fn get(&self, id: &str, ex: &smol::Executor) -> Option<Arc<Client>> {
- // TODO: use get_or_try_init and propagate the error
- self.inner
- .get(id)
- .map(|cell| {
- cell.get_or_init(|| {
+ pub fn get(
+ &mut self,
+ language_config: &LanguageConfiguration,
+ ex: &smol::Executor,
+ ) -> Option<Arc<Client>> {
+ // TODO: propagate the error
+ if let Some(config) = &language_config.language_server_config {
+ // avoid borrow issues
+ let inner = &mut self.inner;
+ let s_incoming = &self.incoming;
+
+ let language_server = inner
+ .entry(language_config.scope.clone()) // can't use entry with Borrow keys: https://github.com/rust-lang/rfcs/pull/1769
+ .or_insert_with(|| {
// TODO: lookup defaults for id (name, args)
// initialize a new client
- let (mut client, incoming) = Client::start(&ex, "rust-analyzer", &[]);
+ let (mut client, incoming) = Client::start(&ex, &config.command, &config.args);
// TODO: run this async without blocking
smol::block_on(client.initialize()).unwrap();
- self.incoming.push(incoming);
+ s_incoming.push(incoming);
Arc::new(client)
})
- })
- .cloned()
+ .clone();
+
+ return Some(language_server);
+ }
+
+ None
}
}
diff --git a/helix-view/src/document.rs b/helix-view/src/document.rs
index f394f2be..033a3593 100644
--- a/helix-view/src/document.rs
+++ b/helix-view/src/document.rs
@@ -4,7 +4,8 @@ use std::path::{Path, PathBuf};
use std::sync::Arc;
use helix_core::{
- syntax::LOADER, ChangeSet, Diagnostic, History, Rope, Selection, State, Syntax, Transaction,
+ syntax::{LanguageConfiguration, LOADER},
+ ChangeSet, Diagnostic, History, Rope, Selection, State, Syntax, Transaction,
};
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
@@ -26,8 +27,8 @@ pub struct Document {
/// Tree-sitter AST tree
pub syntax: Option<Syntax>,
- /// Corresponding language scope name. Usually `source.<lang>`.
- language: Option<String>,
+ // /// Corresponding language scope name. Usually `source.<lang>`.
+ pub(crate) language: Option<Arc<LanguageConfiguration>>,
/// Pending changes since last history commit.
changes: ChangeSet,
@@ -144,20 +145,13 @@ impl Document {
scopes: &[String],
) {
if let Some(language_config) = language_config {
- // TODO: maybe just keep an Arc<> pointer to the language_config?
- self.language = Some(language_config.scope().to_string());
-
- // TODO: this ties lsp support to tree-sitter enabled languages for now. Language
- // config should use Option<HighlightConfig> to let us have non-tree-sitter configs.
-
- let highlight_config = language_config
- .highlight_config(scopes)
- .expect("No highlight_config found!");
- // TODO: config.configure(scopes) is now delayed, is that ok?
-
- let syntax = Syntax::new(&self.state.doc, highlight_config);
+ if let Some(highlight_config) = language_config.highlight_config(scopes) {
+ let syntax = Syntax::new(&self.state.doc, highlight_config);
+ self.syntax = Some(syntax);
+ // TODO: config.configure(scopes) is now delayed, is that ok?
+ }
- self.syntax = Some(syntax);
+ self.language = Some(language_config);
} else {
self.syntax = None;
self.language = None;
@@ -286,7 +280,9 @@ impl Document {
#[inline]
/// Corresponding language scope name. Usually `source.<lang>`.
pub fn language(&self) -> Option<&str> {
- self.language.as_deref()
+ self.language
+ .as_ref()
+ .map(|language| language.scope.as_str())
}
#[inline]
diff --git a/helix-view/src/editor.rs b/helix-view/src/editor.rs
index c072d76f..01a2dac5 100644
--- a/helix-view/src/editor.rs
+++ b/helix-view/src/editor.rs
@@ -39,7 +39,8 @@ impl Editor {
// try to find a language server based on the language name
let language_server = doc
- .language()
+ .language
+ .as_ref()
.and_then(|language| self.language_servers.get(language, &executor));
if let Some(language_server) = language_server {