From d5796dc5eb364b17f028188f844d150604258832 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Tue, 12 Mar 2024 14:33:12 +0100 Subject: [PATCH] Show only prefix/suffix if there are more than 12 breadcrumbs (#9220) Fixes https://github.com/zed-industries/zed/issues/9079 This should fix the arena panic we were observing. I saw that breadcrumb rendering was on the stack trace for some of the panics, so my suspicion is that it's being caused by some people navigating into deeply nested files. Release Notes: - Fixed a panic that could occur when displaying too many breadcrumbs. ([#9079](https://github.com/zed-industries/zed/issues/9079)) --- crates/breadcrumbs/src/breadcrumbs.rs | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/crates/breadcrumbs/src/breadcrumbs.rs b/crates/breadcrumbs/src/breadcrumbs.rs index ca07a205ac..25e1d0346c 100644 --- a/crates/breadcrumbs/src/breadcrumbs.rs +++ b/crates/breadcrumbs/src/breadcrumbs.rs @@ -4,10 +4,11 @@ use gpui::{ ViewContext, }; use itertools::Itertools; +use std::cmp; use theme::ActiveTheme; use ui::{prelude::*, ButtonLike, ButtonStyle, Label, Tooltip}; use workspace::{ - item::{ItemEvent, ItemHandle}, + item::{BreadcrumbText, ItemEvent, ItemHandle}, ToolbarItemEvent, ToolbarItemLocation, ToolbarItemView, }; @@ -31,14 +32,30 @@ impl EventEmitter for Breadcrumbs {} impl Render for Breadcrumbs { fn render(&mut self, cx: &mut ViewContext) -> impl IntoElement { + const MAX_SEGMENTS: usize = 12; let element = h_flex().text_ui(); let Some(active_item) = self.active_item.as_ref() else { return element; }; - let Some(segments) = active_item.breadcrumbs(cx.theme(), cx) else { + let Some(mut segments) = active_item.breadcrumbs(cx.theme(), cx) else { return element; }; + let prefix_end_ix = cmp::min(segments.len(), MAX_SEGMENTS / 2); + let suffix_start_ix = cmp::max( + prefix_end_ix, + segments.len().saturating_sub(MAX_SEGMENTS / 2), + ); + if suffix_start_ix > prefix_end_ix { + segments.splice( + prefix_end_ix..suffix_start_ix, + Some(BreadcrumbText { + text: "⋯".into(), + highlights: None, + }), + ); + } + let highlighted_segments = segments.into_iter().map(|segment| { let mut text_style = cx.text_style(); text_style.color = Color::Muted.color(cx);