Improve lsp log viewer's behavior in the presence of LSP restarts

Improve settings interface to local LSP
This commit is contained in:
Mikayla 2023-09-24 04:59:55 -07:00
parent 02a85b1252
commit 052cb459a6
No known key found for this signature in database
6 changed files with 71 additions and 15 deletions

1
Cargo.lock generated
View file

@ -9868,6 +9868,7 @@ dependencies = [
"serde_derive",
"serde_json",
"settings",
"shellexpand",
"simplelog",
"smallvec",
"smol",

View file

@ -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"]
// }
// },
//

View file

@ -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(&current_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,
}
}

View file

@ -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" }

View file

@ -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(),
})],
),
}

View file

@ -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,