Detailed changes
@@ -719,6 +719,18 @@ dependencies = [
"once_cell",
]
+[[package]]
+name = "breadcrumbs"
+version = "0.1.0"
+dependencies = [
+ "collections",
+ "editor",
+ "gpui",
+ "language",
+ "theme",
+ "workspace",
+]
+
[[package]]
name = "brotli"
version = "3.3.0"
@@ -5963,6 +5975,7 @@ dependencies = [
"async-compression",
"async-recursion",
"async-trait",
+ "breadcrumbs",
"chat_panel",
"client",
"clock",
@@ -0,0 +1,21 @@
+[package]
+name = "breadcrumbs"
+version = "0.1.0"
+edition = "2021"
+
+[lib]
+path = "src/breadcrumbs.rs"
+doctest = false
+
+[dependencies]
+collections = { path = "../collections" }
+editor = { path = "../editor" }
+gpui = { path = "../gpui" }
+language = { path = "../language" }
+theme = { path = "../theme" }
+workspace = { path = "../workspace" }
+
+[dev-dependencies]
+editor = { path = "../editor", features = ["test-support"] }
+gpui = { path = "../gpui", features = ["test-support"] }
+workspace = { path = "../workspace", features = ["test-support"] }
@@ -0,0 +1,99 @@
+use editor::{Anchor, Editor};
+use gpui::{
+ elements::*, AppContext, Entity, RenderContext, Subscription, View, ViewContext, ViewHandle,
+};
+use language::{BufferSnapshot, OutlineItem};
+use std::borrow::Cow;
+use theme::SyntaxTheme;
+use workspace::{ItemHandle, Settings, ToolbarItemView};
+
+pub struct Breadcrumbs {
+ editor: Option<ViewHandle<Editor>>,
+ editor_subscription: Option<Subscription>,
+}
+
+impl Breadcrumbs {
+ pub fn new() -> Self {
+ Self {
+ editor: Default::default(),
+ editor_subscription: Default::default(),
+ }
+ }
+
+ fn active_symbols(
+ &self,
+ theme: &SyntaxTheme,
+ cx: &AppContext,
+ ) -> Option<(BufferSnapshot, Vec<OutlineItem<Anchor>>)> {
+ let editor = self.editor.as_ref()?.read(cx);
+ let cursor = editor.newest_anchor_selection().head();
+ let (buffer, symbols) = editor
+ .buffer()
+ .read(cx)
+ .read(cx)
+ .symbols_containing(cursor, Some(theme))?;
+ if buffer.path().is_none() && symbols.is_empty() {
+ None
+ } else {
+ Some((buffer, symbols))
+ }
+ }
+}
+
+impl Entity for Breadcrumbs {
+ type Event = ();
+}
+
+impl View for Breadcrumbs {
+ fn ui_name() -> &'static str {
+ "Breadcrumbs"
+ }
+
+ fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox {
+ let theme = cx.global::<Settings>().theme.clone();
+ let (buffer, symbols) =
+ if let Some((buffer, symbols)) = self.active_symbols(&theme.editor.syntax, cx) {
+ (buffer, symbols)
+ } else {
+ return Empty::new().boxed();
+ };
+
+ let filename = if let Some(path) = buffer.path() {
+ path.to_string_lossy()
+ } else {
+ Cow::Borrowed("untitled")
+ };
+
+ Flex::row()
+ .with_child(Label::new(filename.to_string(), theme.breadcrumbs.text.clone()).boxed())
+ .with_children(symbols.into_iter().flat_map(|symbol| {
+ [
+ Label::new(" > ".to_string(), theme.breadcrumbs.text.clone()).boxed(),
+ Text::new(symbol.text, theme.breadcrumbs.text.clone())
+ .with_highlights(symbol.highlight_ranges)
+ .boxed(),
+ ]
+ }))
+ .boxed()
+ }
+}
+
+impl ToolbarItemView for Breadcrumbs {
+ fn set_active_pane_item(
+ &mut self,
+ active_pane_item: Option<&dyn ItemHandle>,
+ cx: &mut ViewContext<Self>,
+ ) {
+ self.editor_subscription = None;
+ self.editor = None;
+ if let Some(editor) = active_pane_item.and_then(|i| i.act_as::<Editor>(cx)) {
+ self.editor_subscription = Some(cx.subscribe(&editor, |_, _, event, cx| match event {
+ editor::Event::BufferEdited => cx.notify(),
+ editor::Event::SelectionsChanged { local } if *local => cx.notify(),
+ _ => {}
+ }));
+ self.editor = Some(editor);
+ }
+ cx.notify();
+ }
+}
@@ -26,6 +26,7 @@ pub struct Theme {
pub editor: Editor,
pub search: Search,
pub project_diagnostics: ProjectDiagnostics,
+ pub breadcrumbs: Breadcrumbs,
}
#[derive(Deserialize, Default)]
@@ -271,6 +272,11 @@ pub struct ProjectDiagnostics {
pub tab_summary_spacing: f32,
}
+#[derive(Clone, Deserialize, Default)]
+pub struct Breadcrumbs {
+ pub text: TextStyle,
+}
+
#[derive(Clone, Deserialize, Default)]
pub struct Editor {
pub text_color: Color,
@@ -29,6 +29,7 @@ test-support = [
]
[dependencies]
+breadcrumbs = { path = "../breadcrumbs" }
chat_panel = { path = "../chat_panel" }
collections = { path = "../collections" }
client = { path = "../client" }
@@ -92,6 +92,9 @@ item_spacing = 8
padding.left = 8
padding.right = 8
+[breadcrumbs]
+text = "$text.1"
+
[panel]
padding = { top = 12, left = 12, bottom = 12, right = 12 }
@@ -4,6 +4,7 @@ pub mod menus;
#[cfg(any(test, feature = "test-support"))]
pub mod test;
+use breadcrumbs::Breadcrumbs;
use chat_panel::ChatPanel;
pub use client;
pub use contacts_panel;
@@ -109,6 +110,9 @@ pub fn build_workspace(
let workspace::Event::PaneAdded(pane) = event;
pane.update(cx, |pane, cx| {
pane.toolbar().update(cx, |toolbar, cx| {
+ let breadcrumbs = cx.add_view(|_| Breadcrumbs::new());
+ toolbar.add_left_item(breadcrumbs, cx);
+
let search_bar = cx.add_view(|cx| SearchBar::new(cx));
toolbar.add_right_item(search_bar, cx);
})