language_tools: Split LSP log view selector into two (#21742)
This should make it easier to interact with LSP log view when there are multiple language servers. I often find the current UI clunky when I have over 5 servers running (which isn't uncommon with multiple projects open) https://github.com/user-attachments/assets/2ecaf17f-4b40-4c8f-aa6f-03b437a3d979 Closes #ISSUE Release Notes: - N/A
This commit is contained in:
parent
a7d12eea39
commit
39e8944dcc
1 changed files with 215 additions and 173 deletions
|
@ -1145,19 +1145,28 @@ impl Render for LspLogToolbarItemView {
|
|||
None
|
||||
}
|
||||
});
|
||||
|
||||
let available_language_servers: Vec<_> = menu_rows
|
||||
.iter()
|
||||
.map(|row| {
|
||||
(
|
||||
row.server_id,
|
||||
row.server_name.clone(),
|
||||
row.worktree_root_name.clone(),
|
||||
row.selected_entry,
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
let log_toolbar_view = cx.view().clone();
|
||||
let lsp_menu = PopoverMenu::new("LspLogView")
|
||||
.anchor(AnchorCorner::TopLeft)
|
||||
.trigger(Button::new(
|
||||
"language_server_menu_header",
|
||||
current_server
|
||||
.as_ref()
|
||||
.map(|row| {
|
||||
Cow::Owned(format!(
|
||||
"{} ({}) - {}",
|
||||
row.server_name.0,
|
||||
row.worktree_root_name,
|
||||
row.selected_entry.label()
|
||||
"{} ({})",
|
||||
row.server_name.0, row.worktree_root_name,
|
||||
))
|
||||
})
|
||||
.unwrap_or_else(|| "No server selected".into()),
|
||||
|
@ -1165,36 +1174,71 @@ impl Render for LspLogToolbarItemView {
|
|||
.menu({
|
||||
let log_view = log_view.clone();
|
||||
move |cx| {
|
||||
let menu_rows = menu_rows.clone();
|
||||
let log_view = log_view.clone();
|
||||
let log_toolbar_view = log_toolbar_view.clone();
|
||||
ContextMenu::build(cx, move |mut menu, cx| {
|
||||
for (ix, row) in menu_rows.into_iter().enumerate() {
|
||||
let server_selected = Some(row.server_id) == current_server_id;
|
||||
menu = menu
|
||||
.header(format!(
|
||||
"{} ({})",
|
||||
row.server_name.0, row.worktree_root_name
|
||||
))
|
||||
.entry(
|
||||
SERVER_LOGS,
|
||||
None,
|
||||
cx.handler_for(&log_view, move |view, cx| {
|
||||
view.show_logs_for_server(row.server_id, cx);
|
||||
}),
|
||||
);
|
||||
// We do not support tracing for remote language servers right now
|
||||
if row.server_kind.is_remote() {
|
||||
continue;
|
||||
}
|
||||
ContextMenu::build(cx, |mut menu, cx| {
|
||||
for (server_id, name, worktree_root, active_entry_kind) in
|
||||
available_language_servers.iter()
|
||||
{
|
||||
let label = format!("{} ({})", name, worktree_root);
|
||||
let server_id = *server_id;
|
||||
let active_entry_kind = *active_entry_kind;
|
||||
menu = menu.entry(
|
||||
label,
|
||||
None,
|
||||
cx.handler_for(&log_view, move |view, cx| {
|
||||
view.current_server_id = Some(server_id);
|
||||
view.active_entry_kind = active_entry_kind;
|
||||
match view.active_entry_kind {
|
||||
LogKind::Rpc => {
|
||||
view.toggle_rpc_trace_for_server(server_id, true, cx);
|
||||
view.show_rpc_trace_for_server(server_id, cx);
|
||||
}
|
||||
LogKind::Trace => view.show_trace_for_server(server_id, cx),
|
||||
LogKind::Logs => view.show_logs_for_server(server_id, cx),
|
||||
LogKind::Capabilities => {
|
||||
view.show_capabilities_for_server(server_id, cx)
|
||||
}
|
||||
}
|
||||
cx.notify();
|
||||
}),
|
||||
);
|
||||
}
|
||||
menu
|
||||
})
|
||||
.into()
|
||||
}
|
||||
});
|
||||
let view_selector = current_server.map(|server| {
|
||||
let server_id = server.server_id;
|
||||
let is_remote = server.server_kind.is_remote();
|
||||
let rpc_trace_enabled = server.rpc_trace_enabled;
|
||||
let log_view = log_view.clone();
|
||||
PopoverMenu::new("LspViewSelector")
|
||||
.anchor(AnchorCorner::TopLeft)
|
||||
.trigger(Button::new(
|
||||
"language_server_menu_header",
|
||||
server.selected_entry.label(),
|
||||
))
|
||||
.menu(move |cx| {
|
||||
let log_toolbar_view = log_toolbar_view.clone();
|
||||
let log_view = log_view.clone();
|
||||
Some(ContextMenu::build(cx, move |this, cx| {
|
||||
this.entry(
|
||||
SERVER_LOGS,
|
||||
None,
|
||||
cx.handler_for(&log_view, move |view, cx| {
|
||||
view.show_logs_for_server(server_id, cx);
|
||||
}),
|
||||
)
|
||||
.when(!is_remote, |this| {
|
||||
this.entry(
|
||||
SERVER_TRACE,
|
||||
None,
|
||||
cx.handler_for(&log_view, move |view, cx| {
|
||||
view.show_trace_for_server(row.server_id, cx);
|
||||
view.show_trace_for_server(server_id, cx);
|
||||
}),
|
||||
);
|
||||
menu = menu.custom_entry(
|
||||
)
|
||||
.custom_entry(
|
||||
{
|
||||
let log_toolbar_view = log_toolbar_view.clone();
|
||||
move |cx| {
|
||||
|
@ -1205,8 +1249,8 @@ impl Render for LspLogToolbarItemView {
|
|||
.child(
|
||||
div().child(
|
||||
Checkbox::new(
|
||||
ix,
|
||||
if row.rpc_trace_enabled {
|
||||
"LspLogEnableRpcTrace",
|
||||
if rpc_trace_enabled {
|
||||
Selection::Selected
|
||||
} else {
|
||||
Selection::Unselected
|
||||
|
@ -1220,9 +1264,7 @@ impl Render for LspLogToolbarItemView {
|
|||
Selection::Selected
|
||||
);
|
||||
view.toggle_rpc_logging_for_server(
|
||||
row.server_id,
|
||||
enabled,
|
||||
cx,
|
||||
server_id, enabled, cx,
|
||||
);
|
||||
cx.stop_propagation();
|
||||
},
|
||||
|
@ -1233,42 +1275,148 @@ impl Render for LspLogToolbarItemView {
|
|||
}
|
||||
},
|
||||
cx.handler_for(&log_view, move |view, cx| {
|
||||
view.show_rpc_trace_for_server(row.server_id, cx);
|
||||
view.show_rpc_trace_for_server(server_id, cx);
|
||||
}),
|
||||
);
|
||||
if server_selected && row.selected_entry == LogKind::Rpc {
|
||||
let selected_ix = menu.select_last();
|
||||
// Each language server has:
|
||||
// 1. A title.
|
||||
// 2. Server logs.
|
||||
// 3. Server trace.
|
||||
// 4. RPC messages.
|
||||
// 5. Server capabilities
|
||||
// Thus, if nth server's RPC is selected, the index of selected entry should match this formula
|
||||
let _expected_index = ix * 5 + 3;
|
||||
debug_assert_eq!(
|
||||
Some(_expected_index),
|
||||
selected_ix,
|
||||
"Could not scroll to a just added LSP menu item"
|
||||
);
|
||||
}
|
||||
menu = menu.entry(
|
||||
SERVER_CAPABILITIES,
|
||||
None,
|
||||
cx.handler_for(&log_view, move |view, cx| {
|
||||
view.show_capabilities_for_server(row.server_id, cx);
|
||||
}),
|
||||
);
|
||||
}
|
||||
menu
|
||||
})
|
||||
.into()
|
||||
}
|
||||
});
|
||||
|
||||
)
|
||||
})
|
||||
.entry(
|
||||
SERVER_CAPABILITIES,
|
||||
None,
|
||||
cx.handler_for(&log_view, move |view, cx| {
|
||||
view.show_capabilities_for_server(server_id, cx);
|
||||
}),
|
||||
)
|
||||
}))
|
||||
})
|
||||
});
|
||||
h_flex()
|
||||
.size_full()
|
||||
.child(lsp_menu)
|
||||
.justify_between()
|
||||
.child(
|
||||
h_flex()
|
||||
.child(lsp_menu)
|
||||
.children(view_selector)
|
||||
.child(log_view.update(cx, |this, _| match this.active_entry_kind {
|
||||
LogKind::Trace => {
|
||||
let log_view = log_view.clone();
|
||||
div().child(
|
||||
PopoverMenu::new("lsp-trace-level-menu")
|
||||
.anchor(AnchorCorner::TopLeft)
|
||||
.trigger(Button::new(
|
||||
"language_server_trace_level_selector",
|
||||
"Trace level",
|
||||
))
|
||||
.menu({
|
||||
let log_view = log_view.clone();
|
||||
|
||||
move |cx| {
|
||||
let id = log_view.read(cx).current_server_id?;
|
||||
|
||||
let trace_level = log_view.update(cx, |this, cx| {
|
||||
this.log_store.update(cx, |this, _| {
|
||||
Some(
|
||||
this.get_language_server_state(id)?
|
||||
.trace_level,
|
||||
)
|
||||
})
|
||||
})?;
|
||||
|
||||
ContextMenu::build(cx, |mut menu, _| {
|
||||
let log_view = log_view.clone();
|
||||
|
||||
for (option, label) in [
|
||||
(TraceValue::Off, "Off"),
|
||||
(TraceValue::Messages, "Messages"),
|
||||
(TraceValue::Verbose, "Verbose"),
|
||||
] {
|
||||
menu = menu.entry(label, None, {
|
||||
let log_view = log_view.clone();
|
||||
move |cx| {
|
||||
log_view.update(cx, |this, cx| {
|
||||
if let Some(id) =
|
||||
this.current_server_id
|
||||
{
|
||||
this.update_trace_level(
|
||||
id, option, cx,
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
if option == trace_level {
|
||||
menu.select_last();
|
||||
}
|
||||
}
|
||||
|
||||
menu
|
||||
})
|
||||
.into()
|
||||
}
|
||||
}),
|
||||
)
|
||||
}
|
||||
LogKind::Logs => {
|
||||
let log_view = log_view.clone();
|
||||
div().child(
|
||||
PopoverMenu::new("lsp-log-level-menu")
|
||||
.anchor(AnchorCorner::TopLeft)
|
||||
.trigger(Button::new(
|
||||
"language_server_log_level_selector",
|
||||
"Log level",
|
||||
))
|
||||
.menu({
|
||||
let log_view = log_view.clone();
|
||||
|
||||
move |cx| {
|
||||
let id = log_view.read(cx).current_server_id?;
|
||||
|
||||
let log_level = log_view.update(cx, |this, cx| {
|
||||
this.log_store.update(cx, |this, _| {
|
||||
Some(
|
||||
this.get_language_server_state(id)?
|
||||
.log_level,
|
||||
)
|
||||
})
|
||||
})?;
|
||||
|
||||
ContextMenu::build(cx, |mut menu, _| {
|
||||
let log_view = log_view.clone();
|
||||
|
||||
for (option, label) in [
|
||||
(MessageType::LOG, "Log"),
|
||||
(MessageType::INFO, "Info"),
|
||||
(MessageType::WARNING, "Warning"),
|
||||
(MessageType::ERROR, "Error"),
|
||||
] {
|
||||
menu = menu.entry(label, None, {
|
||||
let log_view = log_view.clone();
|
||||
move |cx| {
|
||||
log_view.update(cx, |this, cx| {
|
||||
if let Some(id) =
|
||||
this.current_server_id
|
||||
{
|
||||
this.update_log_level(
|
||||
id, option, cx,
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
if option == log_level {
|
||||
menu.select_last();
|
||||
}
|
||||
}
|
||||
|
||||
menu
|
||||
})
|
||||
.into()
|
||||
}
|
||||
}),
|
||||
)
|
||||
}
|
||||
_ => div(),
|
||||
})),
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
.child(
|
||||
|
@ -1288,112 +1436,6 @@ impl Render for LspLogToolbarItemView {
|
|||
)
|
||||
.ml_2(),
|
||||
)
|
||||
.child(log_view.update(cx, |this, _| match this.active_entry_kind {
|
||||
LogKind::Trace => {
|
||||
let log_view = log_view.clone();
|
||||
div().child(
|
||||
PopoverMenu::new("lsp-trace-level-menu")
|
||||
.anchor(AnchorCorner::TopLeft)
|
||||
.trigger(Button::new(
|
||||
"language_server_trace_level_selector",
|
||||
"Trace level",
|
||||
))
|
||||
.menu({
|
||||
let log_view = log_view.clone();
|
||||
|
||||
move |cx| {
|
||||
let id = log_view.read(cx).current_server_id?;
|
||||
|
||||
let trace_level = log_view.update(cx, |this, cx| {
|
||||
this.log_store.update(cx, |this, _| {
|
||||
Some(this.get_language_server_state(id)?.trace_level)
|
||||
})
|
||||
})?;
|
||||
|
||||
ContextMenu::build(cx, |mut menu, _| {
|
||||
let log_view = log_view.clone();
|
||||
|
||||
for (option, label) in [
|
||||
(TraceValue::Off, "Off"),
|
||||
(TraceValue::Messages, "Messages"),
|
||||
(TraceValue::Verbose, "Verbose"),
|
||||
] {
|
||||
menu = menu.entry(label, None, {
|
||||
let log_view = log_view.clone();
|
||||
move |cx| {
|
||||
log_view.update(cx, |this, cx| {
|
||||
if let Some(id) = this.current_server_id {
|
||||
this.update_trace_level(id, option, cx);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
if option == trace_level {
|
||||
menu.select_last();
|
||||
}
|
||||
}
|
||||
|
||||
menu
|
||||
})
|
||||
.into()
|
||||
}
|
||||
}),
|
||||
)
|
||||
}
|
||||
LogKind::Logs => {
|
||||
let log_view = log_view.clone();
|
||||
div().child(
|
||||
PopoverMenu::new("lsp-log-level-menu")
|
||||
.anchor(AnchorCorner::TopLeft)
|
||||
.trigger(Button::new(
|
||||
"language_server_log_level_selector",
|
||||
"Log level",
|
||||
))
|
||||
.menu({
|
||||
let log_view = log_view.clone();
|
||||
|
||||
move |cx| {
|
||||
let id = log_view.read(cx).current_server_id?;
|
||||
|
||||
let log_level = log_view.update(cx, |this, cx| {
|
||||
this.log_store.update(cx, |this, _| {
|
||||
Some(this.get_language_server_state(id)?.log_level)
|
||||
})
|
||||
})?;
|
||||
|
||||
ContextMenu::build(cx, |mut menu, _| {
|
||||
let log_view = log_view.clone();
|
||||
|
||||
for (option, label) in [
|
||||
(MessageType::LOG, "Log"),
|
||||
(MessageType::INFO, "Info"),
|
||||
(MessageType::WARNING, "Warning"),
|
||||
(MessageType::ERROR, "Error"),
|
||||
] {
|
||||
menu = menu.entry(label, None, {
|
||||
let log_view = log_view.clone();
|
||||
move |cx| {
|
||||
log_view.update(cx, |this, cx| {
|
||||
if let Some(id) = this.current_server_id {
|
||||
this.update_log_level(id, option, cx);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
if option == log_level {
|
||||
menu.select_last();
|
||||
}
|
||||
}
|
||||
|
||||
menu
|
||||
})
|
||||
.into()
|
||||
}
|
||||
}),
|
||||
)
|
||||
}
|
||||
_ => div(),
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue