Show breadcrumbs in the toolbar

This commit is contained in:
Antonio Scandurra 2022-03-29 14:01:15 +02:00
parent 099250c691
commit 13f42550c9
7 changed files with 147 additions and 0 deletions

View file

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

View file

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