Merge branch 'main' into tab-map-bitmask

This commit is contained in:
Anthony 2025-07-11 12:11:01 -04:00
commit 63d01c299d
293 changed files with 18374 additions and 4036 deletions

View file

@ -1331,6 +1331,7 @@ impl Render for LspLogToolbarItemView {
let Some(log_view) = self.log_view.clone() else {
return div();
};
let (menu_rows, current_server_id) = log_view.update(cx, |log_view, cx| {
let menu_rows = log_view.menu_items(cx).unwrap_or_default();
let current_server_id = log_view.current_server_id;
@ -1344,6 +1345,7 @@ impl Render for LspLogToolbarItemView {
None
}
});
let available_language_servers: Vec<_> = menu_rows
.into_iter()
.map(|row| {
@ -1355,21 +1357,28 @@ impl Render for LspLogToolbarItemView {
)
})
.collect();
let log_toolbar_view = cx.entity().clone();
let lsp_menu = PopoverMenu::new("LspLogView")
.anchor(Corner::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,
))
})
.unwrap_or_else(|| "No server selected".into()),
))
.trigger(
Button::new(
"language_server_menu_header",
current_server
.as_ref()
.map(|row| {
Cow::Owned(format!(
"{} ({})",
row.server_name.0, row.worktree_root_name,
))
})
.unwrap_or_else(|| "No server selected".into()),
)
.icon(IconName::ChevronDown)
.icon_size(IconSize::Small)
.icon_color(Color::Muted),
)
.menu({
let log_view = log_view.clone();
move |window, cx| {
@ -1413,6 +1422,7 @@ impl Render for LspLogToolbarItemView {
.into()
}
});
let view_selector = current_server.map(|server| {
let server_id = server.server_id;
let is_remote = server.server_kind.is_remote();
@ -1420,10 +1430,12 @@ impl Render for LspLogToolbarItemView {
let log_view = log_view.clone();
PopoverMenu::new("LspViewSelector")
.anchor(Corner::TopLeft)
.trigger(Button::new(
"language_server_menu_header",
server.selected_entry.label(),
))
.trigger(
Button::new("language_server_menu_header", server.selected_entry.label())
.icon(IconName::ChevronDown)
.icon_size(IconSize::Small)
.icon_color(Color::Muted),
)
.menu(move |window, cx| {
let log_toolbar_view = log_toolbar_view.clone();
let log_view = log_view.clone();
@ -1494,11 +1506,14 @@ impl Render for LspLogToolbarItemView {
}))
})
});
h_flex()
.size_full()
.gap_1()
.justify_between()
.child(
h_flex()
.gap_0p5()
.child(lsp_menu)
.children(view_selector)
.child(
@ -1508,10 +1523,15 @@ impl Render for LspLogToolbarItemView {
div().child(
PopoverMenu::new("lsp-trace-level-menu")
.anchor(Corner::TopLeft)
.trigger(Button::new(
"language_server_trace_level_selector",
"Trace level",
))
.trigger(
Button::new(
"language_server_trace_level_selector",
"Trace level",
)
.icon(IconName::ChevronDown)
.icon_size(IconSize::Small)
.icon_color(Color::Muted),
)
.menu({
let log_view = log_view.clone();
@ -1571,10 +1591,15 @@ impl Render for LspLogToolbarItemView {
div().child(
PopoverMenu::new("lsp-log-level-menu")
.anchor(Corner::TopLeft)
.trigger(Button::new(
"language_server_log_level_selector",
"Log level",
))
.trigger(
Button::new(
"language_server_log_level_selector",
"Log level",
)
.icon(IconName::ChevronDown)
.icon_size(IconSize::Small)
.icon_color(Color::Muted),
)
.menu({
let log_view = log_view.clone();
@ -1635,23 +1660,19 @@ impl Render for LspLogToolbarItemView {
),
)
.child(
div()
.child(
Button::new("clear_log_button", "Clear").on_click(cx.listener(
|this, _, window, cx| {
if let Some(log_view) = this.log_view.as_ref() {
log_view.update(cx, |log_view, cx| {
log_view.editor.update(cx, |editor, cx| {
editor.set_read_only(false);
editor.clear(window, cx);
editor.set_read_only(true);
});
})
}
},
)),
)
.ml_2(),
Button::new("clear_log_button", "Clear").on_click(cx.listener(
|this, _, window, cx| {
if let Some(log_view) = this.log_view.as_ref() {
log_view.update(cx, |log_view, cx| {
log_view.editor.update(cx, |editor, cx| {
editor.set_read_only(false);
editor.clear(window, cx);
editor.set_read_only(true);
});
})
}
},
)),
)
}
}

View file

@ -110,6 +110,7 @@ impl LanguageServerHealthStatus {
impl LanguageServerState {
fn fill_menu(&self, mut menu: ContextMenu, cx: &mut Context<Self>) -> ContextMenu {
menu = menu.align_popover_bottom();
let lsp_logs = cx
.try_global::<GlobalLogStore>()
.and_then(|lsp_logs| lsp_logs.0.upgrade());
@ -118,6 +119,7 @@ impl LanguageServerState {
return menu;
};
let mut first_button_encountered = false;
for (i, item) in self.items.iter().enumerate() {
if let LspItem::ToggleServersButton { restart } = item {
let label = if *restart {
@ -182,18 +184,25 @@ impl LanguageServerState {
.ok();
}
});
menu = menu.separator().item(button);
if !first_button_encountered {
menu = menu.separator();
first_button_encountered = true;
}
menu = menu.item(button);
continue;
};
let Some(server_info) = item.server_info() else {
continue;
};
let workspace = self.workspace.clone();
let server_selector = server_info.server_selector();
// TODO currently, Zed remote does not work well with the LSP logs
// https://github.com/zed-industries/zed/issues/28557
let has_logs = lsp_store.read(cx).as_local().is_some()
&& lsp_logs.read(cx).has_server_logs(&server_selector);
let status_color = server_info
.binary_status
.and_then(|binary_status| match binary_status.status {
@ -218,16 +227,40 @@ impl LanguageServerState {
.other_servers_start_index
.is_some_and(|index| index == i)
{
menu = menu.separator();
menu = menu.separator().header("Other Buffers");
}
if i == 0 && self.other_servers_start_index.is_some() {
menu = menu.header("Current Buffer");
}
menu = menu.item(ContextMenuItem::custom_entry(
move |_, _| {
h_flex()
.gap_1()
.group("menu_item")
.w_full()
.child(Indicator::dot().color(status_color))
.child(Label::new(server_info.name.0.clone()))
.when(!has_logs, |div| div.cursor_default())
.gap_2()
.justify_between()
.child(
h_flex()
.gap_2()
.child(Indicator::dot().color(status_color))
.child(Label::new(server_info.name.0.clone())),
)
.child(
h_flex()
.visible_on_hover("menu_item")
.child(
Label::new("View Logs")
.size(LabelSize::Small)
.color(Color::Muted),
)
.child(
Icon::new(IconName::ChevronRight)
.size(IconSize::Small)
.color(Color::Muted),
),
)
.into_any_element()
},
{
@ -678,6 +711,7 @@ impl LspTool {
new_lsp_items.extend(other_servers.into_iter().map(ServerData::into_lsp_item));
if !new_lsp_items.is_empty() {
if can_stop_all {
new_lsp_items.push(LspItem::ToggleServersButton { restart: true });
new_lsp_items.push(LspItem::ToggleServersButton { restart: false });
} else if can_restart_all {
new_lsp_items.push(LspItem::ToggleServersButton { restart: true });
@ -708,8 +742,6 @@ impl LspTool {
state.update(cx, |state, cx| state.fill_menu(menu, cx))
});
lsp_tool.lsp_menu = Some(menu.clone());
// TODO kb will this work?
// what about the selections?
lsp_tool.popover_menu_handle.refresh_menu(
window,
cx,
@ -836,17 +868,27 @@ impl Render for LspTool {
}
}
let indicator = if has_errors {
Some(Indicator::dot().color(Color::Error))
let (indicator, description) = if has_errors {
(
Some(Indicator::dot().color(Color::Error)),
"Server with errors",
)
} else if has_warnings {
Some(Indicator::dot().color(Color::Warning))
(
Some(Indicator::dot().color(Color::Warning)),
"Server with warnings",
)
} else if has_other_notifications {
Some(Indicator::dot().color(Color::Modified))
(
Some(Indicator::dot().color(Color::Modified)),
"Server with notifications",
)
} else {
None
(None, "All Servers Operational")
};
let lsp_tool = cx.entity().clone();
div().child(
PopoverMenu::new("lsp-tool")
.menu(move |_, cx| lsp_tool.read(cx).lsp_menu.clone())
@ -858,7 +900,13 @@ impl Render for LspTool {
.icon_size(IconSize::Small)
.indicator_border_color(Some(cx.theme().colors().status_bar_background)),
move |window, cx| {
Tooltip::for_action("Language Servers", &ToggleMenu, window, cx)
Tooltip::with_meta(
"Language Servers",
Some(&ToggleMenu),
description,
window,
cx,
)
},
),
)