Cargo.lock 🔗
@@ -9868,6 +9868,7 @@ dependencies = [
"serde_derive",
"serde_json",
"settings",
+ "shellexpand",
"simplelog",
"smallvec",
"smol",
Mikayla created
Improve settings interface to local LSP
Cargo.lock | 1
assets/settings/default.json | 6 +-
crates/language_tools/src/lsp_log.rs | 50 +++++++++++++++++++++++++-
crates/zed/Cargo.toml | 1
crates/zed/src/languages.rs | 3 +
crates/zed/src/languages/elixir_next.rs | 25 +++++++++----
6 files changed, 71 insertions(+), 15 deletions(-)
@@ -9868,6 +9868,7 @@ dependencies = [
"serde_derive",
"serde_json",
"settings",
+ "shellexpand",
"simplelog",
"smallvec",
"smol",
@@ -384,11 +384,11 @@
// "next": "off"
// 2. Use a bundled version of the next Next LS LSP server
// "next": "on",
- // 3. Use a locally running version of the next Next LS LSP server,
- // on a specific port:
+ // 3. Use a local build of the next Next LS LSP server:
// "next": {
// "local": {
- // "port": 4000
+ // "path": "~/next-ls/bin/start",
+ // "arguments": ["--stdio"]
// }
// },
//
@@ -8,8 +8,8 @@ use gpui::{
ParentElement, Stack,
},
platform::{CursorStyle, MouseButton},
- AnyElement, AppContext, Element, Entity, ModelContext, ModelHandle, View, ViewContext,
- ViewHandle, WeakModelHandle,
+ AnyElement, AppContext, Element, Entity, ModelContext, ModelHandle, Subscription, View,
+ ViewContext, ViewHandle, WeakModelHandle,
};
use language::{Buffer, LanguageServerId, LanguageServerName};
use lsp::IoKind;
@@ -52,10 +52,12 @@ pub struct LspLogView {
current_server_id: Option<LanguageServerId>,
is_showing_rpc_trace: bool,
project: ModelHandle<Project>,
+ _log_store_subscription: Subscription,
}
pub struct LspLogToolbarItemView {
log_view: Option<ViewHandle<LspLogView>>,
+ _log_view_subscription: Option<Subscription>,
menu_open: bool,
}
@@ -346,12 +348,49 @@ impl LspLogView {
.get(&project.downgrade())
.and_then(|project| project.servers.keys().copied().next());
let buffer = cx.add_model(|cx| Buffer::new(0, cx.model_id() as u64, ""));
+ let _log_store_subscription = cx.observe(&log_store, |this, store, cx| {
+ (|| -> Option<()> {
+ let project_state = store.read(cx).projects.get(&this.project.downgrade())?;
+ if let Some(current_lsp) = this.current_server_id {
+ if !project_state.servers.contains_key(¤t_lsp) {
+ if let Some(server) = project_state.servers.iter().next() {
+ if this.is_showing_rpc_trace {
+ this.show_rpc_trace_for_server(*server.0, cx)
+ } else {
+ this.show_logs_for_server(*server.0, cx)
+ }
+ } else {
+ this.current_server_id = None;
+ this.editor.update(cx, |editor, cx| {
+ editor.set_read_only(false);
+ editor.clear(cx);
+ editor.set_read_only(true);
+ });
+ cx.notify();
+ }
+ }
+ } else {
+ if let Some(server) = project_state.servers.iter().next() {
+ if this.is_showing_rpc_trace {
+ this.show_rpc_trace_for_server(*server.0, cx)
+ } else {
+ this.show_logs_for_server(*server.0, cx)
+ }
+ }
+ }
+
+ Some(())
+ })();
+
+ cx.notify();
+ });
let mut this = Self {
editor: Self::editor_for_buffer(project.clone(), buffer, cx),
project,
log_store,
current_server_id: None,
is_showing_rpc_trace: false,
+ _log_store_subscription,
};
if let Some(server_id) = server_id {
this.show_logs_for_server(server_id, cx);
@@ -556,18 +595,22 @@ impl ToolbarItemView for LspLogToolbarItemView {
fn set_active_pane_item(
&mut self,
active_pane_item: Option<&dyn ItemHandle>,
- _: &mut ViewContext<Self>,
+ cx: &mut ViewContext<Self>,
) -> workspace::ToolbarItemLocation {
self.menu_open = false;
if let Some(item) = active_pane_item {
if let Some(log_view) = item.downcast::<LspLogView>() {
self.log_view = Some(log_view.clone());
+ self._log_view_subscription = Some(cx.observe(&log_view, |_, _, cx| {
+ cx.notify();
+ }));
return ToolbarItemLocation::PrimaryLeft {
flex: Some((1., false)),
};
}
}
self.log_view = None;
+ self._log_view_subscription = None;
ToolbarItemLocation::Hidden
}
}
@@ -697,6 +740,7 @@ impl LspLogToolbarItemView {
Self {
menu_open: false,
log_view: None,
+ _log_view_subscription: None,
}
}
@@ -62,6 +62,7 @@ rpc = { path = "../rpc" }
settings = { path = "../settings" }
feature_flags = { path = "../feature_flags" }
sum_tree = { path = "../sum_tree" }
+shellexpand = "2.1.0"
text = { path = "../text" }
terminal_view = { path = "../terminal_view" }
theme = { path = "../theme" }
@@ -79,11 +79,12 @@ pub fn init(
vec![Arc::new(elixir::ElixirLspAdapter)],
),
elixir_next::ElixirNextSetting::On => todo!(),
- elixir_next::ElixirNextSetting::Local { path } => language(
+ elixir_next::ElixirNextSetting::Local { path, arguments } => language(
"elixir",
tree_sitter_elixir::language(),
vec![Arc::new(elixir_next::LocalNextLspAdapter {
path: path.clone(),
+ arguments: arguments.clone(),
})],
),
}
@@ -5,7 +5,7 @@ use lsp::{CompletionItemKind, LanguageServerBinary, SymbolKind};
use schemars::JsonSchema;
use serde_derive::{Deserialize, Serialize};
use settings::Setting;
-use std::{any::Any, path::PathBuf, sync::Arc};
+use std::{any::Any, ops::Deref, path::PathBuf, sync::Arc};
#[derive(Clone, Serialize, Deserialize, JsonSchema)]
pub struct ElixirSettings {
@@ -17,7 +17,10 @@ pub struct ElixirSettings {
pub enum ElixirNextSetting {
Off,
On,
- Local { path: String },
+ Local {
+ path: String,
+ arguments: Vec<String>,
+ },
}
#[derive(Clone, Serialize, Default, Deserialize, JsonSchema)]
@@ -44,6 +47,7 @@ impl Setting for ElixirSettings {
pub struct LocalNextLspAdapter {
pub path: String,
+ pub arguments: Vec<String>,
}
#[async_trait]
@@ -69,9 +73,10 @@ impl LspAdapter for LocalNextLspAdapter {
_: PathBuf,
_: &dyn LspAdapterDelegate,
) -> Result<LanguageServerBinary> {
+ let path = shellexpand::full(&self.path)?;
Ok(LanguageServerBinary {
- path: self.path.clone().into(),
- arguments: vec!["--stdio".into()],
+ path: PathBuf::from(path.deref()),
+ arguments: self.arguments.iter().map(|arg| arg.into()).collect(),
})
}
@@ -80,19 +85,22 @@ impl LspAdapter for LocalNextLspAdapter {
_: PathBuf,
_: &dyn LspAdapterDelegate,
) -> Option<LanguageServerBinary> {
+ let path = shellexpand::full(&self.path).ok()?;
Some(LanguageServerBinary {
- path: self.path.clone().into(),
- arguments: vec!["--stdio".into()],
+ path: PathBuf::from(path.deref()),
+ arguments: self.arguments.iter().map(|arg| arg.into()).collect(),
})
}
async fn installation_test_binary(&self, _: PathBuf) -> Option<LanguageServerBinary> {
+ let path = shellexpand::full(&self.path).ok()?;
Some(LanguageServerBinary {
- path: self.path.clone().into(),
- arguments: vec!["--stdio".into()],
+ path: PathBuf::from(path.deref()),
+ arguments: self.arguments.iter().map(|arg| arg.into()).collect(),
})
}
+ // TODO:
async fn label_for_completion(
&self,
completion: &lsp::CompletionItem,
@@ -147,6 +155,7 @@ impl LspAdapter for LocalNextLspAdapter {
None
}
+ // TODO:
async fn label_for_symbol(
&self,
name: &str,