editor: Put more syntax walking features on the background (#48450)
Currently we always compute breadcrumbs and sticky headers on every editor paint which is not cheap to do especially in bigger files, moving this off to be computed on event handling where they change and then caching them can save serveral milliseconds per render in bigger files. This also puts matching brackets refreshing and document highlights on a background task, as this tends to block the main task for prolonged time as well. Release Notes: - N/A *or* Added/Fixed/Improved ...
This commit is contained in:
1 parent
0357a4a95d
commit
5ccd64f89f
16 files changed
+157
-109
No files matched your search
Generated
-1
@@ -2348,7 +2348,6 @@ version = "0.1.0"
|
||||
dependencies = [
|
||||
"editor",
|
||||
"gpui",
|
||||
"theme",
|
||||
"ui",
|
||||
"workspace",
|
||||
]
|
||||
|
||||
@@ -15,7 +15,6 @@ doctest = false
|
||||
[dependencies]
|
||||
editor.workspace = true
|
||||
gpui.workspace = true
|
||||
theme.workspace = true
|
||||
ui.workspace = true
|
||||
workspace.workspace = true
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
use editor::render_breadcrumb_text;
|
||||
use gpui::{Context, EventEmitter, IntoElement, Render, Subscription, Window};
|
||||
use theme::ActiveTheme;
|
||||
use ui::prelude::*;
|
||||
use workspace::{
|
||||
ToolbarItemEvent, ToolbarItemLocation, ToolbarItemView,
|
||||
@@ -44,7 +43,7 @@ impl Render for Breadcrumbs {
|
||||
return element.into_any_element();
|
||||
};
|
||||
|
||||
let Some(segments) = active_item.breadcrumbs(cx.theme(), cx) else {
|
||||
let Some(segments) = active_item.breadcrumbs(cx) else {
|
||||
return element.into_any_element();
|
||||
};
|
||||
|
||||
|
||||
@@ -439,8 +439,8 @@ impl Item for StackTraceView {
|
||||
ToolbarItemLocation::PrimaryLeft
|
||||
}
|
||||
|
||||
fn breadcrumbs(&self, theme: &theme::Theme, cx: &App) -> Option<Vec<BreadcrumbText>> {
|
||||
self.editor.breadcrumbs(theme, cx)
|
||||
fn breadcrumbs(&self, cx: &App) -> Option<Vec<BreadcrumbText>> {
|
||||
self.editor.breadcrumbs(cx)
|
||||
}
|
||||
|
||||
fn added_to_workspace(
|
||||
|
||||
+92
-39
@@ -1340,6 +1340,11 @@ pub struct Editor {
|
||||
semantic_tokens_enabled: bool,
|
||||
update_semantic_tokens_task: Task<()>,
|
||||
semantic_tokens_fetched_for_buffers: HashMap<BufferId, clock::Global>,
|
||||
pub(crate) refresh_matching_bracket_highlights_task: Task<()>,
|
||||
refresh_outline_symbols_task: Task<()>,
|
||||
outline_symbols: Option<(BufferId, Vec<OutlineItem<Anchor>>)>,
|
||||
sticky_headers_task: Task<()>,
|
||||
sticky_headers: Option<Vec<OutlineItem<Anchor>>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
@@ -1969,37 +1974,43 @@ impl Editor {
|
||||
Editor::new_internal(mode, buffer, project, None, window, cx)
|
||||
}
|
||||
|
||||
pub fn sticky_headers(
|
||||
&self,
|
||||
pub fn refresh_sticky_headers(
|
||||
&mut self,
|
||||
display_snapshot: &DisplaySnapshot,
|
||||
style: &EditorStyle,
|
||||
cx: &App,
|
||||
) -> Option<Vec<OutlineItem<Anchor>>> {
|
||||
let multi_buffer = self.buffer().read(cx);
|
||||
let multi_buffer_snapshot = multi_buffer.snapshot(cx);
|
||||
cx: &mut Context<Editor>,
|
||||
) {
|
||||
if !self.mode.is_full() {
|
||||
return;
|
||||
}
|
||||
let multi_buffer = display_snapshot.buffer_snapshot();
|
||||
let multi_buffer_visible_start = self
|
||||
.scroll_manager
|
||||
.native_anchor(display_snapshot, cx)
|
||||
.anchor
|
||||
.to_point(&multi_buffer_snapshot);
|
||||
let max_row = multi_buffer_snapshot.max_point().row;
|
||||
.to_point(&multi_buffer);
|
||||
let max_row = multi_buffer.max_point().row;
|
||||
|
||||
let start_row = (multi_buffer_visible_start.row).min(max_row);
|
||||
let end_row = (multi_buffer_visible_start.row + 10).min(max_row);
|
||||
|
||||
if let Some((excerpt_id, _, buffer)) = multi_buffer.read(cx).as_singleton() {
|
||||
let outline_items = buffer
|
||||
let Some((excerpt_id, _, buffer)) = multi_buffer.as_singleton() else {
|
||||
return;
|
||||
};
|
||||
let buffer = buffer.clone();
|
||||
let &excerpt_id = excerpt_id;
|
||||
let syntax = self.style(cx).syntax.clone();
|
||||
let background_task = cx.background_spawn(async move {
|
||||
buffer
|
||||
.outline_items_containing(
|
||||
Point::new(start_row, 0)..Point::new(end_row, 0),
|
||||
true,
|
||||
Some(style.syntax.as_ref()),
|
||||
Some(syntax.as_ref()),
|
||||
)
|
||||
.into_iter()
|
||||
.map(|outline_item| OutlineItem {
|
||||
depth: outline_item.depth,
|
||||
range: Anchor::range_in_buffer(*excerpt_id, outline_item.range),
|
||||
range: Anchor::range_in_buffer(excerpt_id, outline_item.range),
|
||||
source_range_for_text: Anchor::range_in_buffer(
|
||||
*excerpt_id,
|
||||
excerpt_id,
|
||||
outline_item.source_range_for_text,
|
||||
),
|
||||
text: outline_item.text,
|
||||
@@ -2007,15 +2018,21 @@ impl Editor {
|
||||
name_ranges: outline_item.name_ranges,
|
||||
body_range: outline_item
|
||||
.body_range
|
||||
.map(|range| Anchor::range_in_buffer(*excerpt_id, range)),
|
||||
.map(|range| Anchor::range_in_buffer(excerpt_id, range)),
|
||||
annotation_range: outline_item
|
||||
.annotation_range
|
||||
.map(|range| Anchor::range_in_buffer(*excerpt_id, range)),
|
||||
});
|
||||
return Some(outline_items.collect());
|
||||
}
|
||||
|
||||
None
|
||||
.map(|range| Anchor::range_in_buffer(excerpt_id, range)),
|
||||
})
|
||||
.collect()
|
||||
});
|
||||
self.sticky_headers_task = cx.spawn(async move |this, cx| {
|
||||
let sticky_headers = background_task.await;
|
||||
this.update(cx, |this, cx| {
|
||||
this.sticky_headers = Some(sticky_headers);
|
||||
cx.notify();
|
||||
})
|
||||
.ok();
|
||||
});
|
||||
}
|
||||
|
||||
fn new_internal(
|
||||
@@ -2578,6 +2595,11 @@ impl Editor {
|
||||
update_semantic_tokens_task: Task::ready(()),
|
||||
semantic_tokens_fetched_for_buffers: HashMap::default(),
|
||||
number_deleted_lines: false,
|
||||
refresh_matching_bracket_highlights_task: Task::ready(()),
|
||||
refresh_outline_symbols_task: Task::ready(()),
|
||||
outline_symbols: None,
|
||||
sticky_headers_task: Task::ready(()),
|
||||
sticky_headers: None,
|
||||
};
|
||||
|
||||
if is_minimap {
|
||||
@@ -2633,6 +2655,7 @@ impl Editor {
|
||||
.ok();
|
||||
});
|
||||
}
|
||||
editor.refresh_sticky_headers(&editor.snapshot(window, cx), cx);
|
||||
}
|
||||
EditorEvent::Edited { .. } => {
|
||||
let vim_mode = vim_mode_setting::VimModeSetting::try_get(cx)
|
||||
@@ -3577,6 +3600,7 @@ impl Editor {
|
||||
|
||||
self.refresh_selected_text_highlights(false, window, cx);
|
||||
self.refresh_matching_bracket_highlights(window, cx);
|
||||
self.refresh_outline_symbols(cx);
|
||||
self.update_visible_edit_prediction(window, cx);
|
||||
self.edit_prediction_requires_modifier_in_indent_conflict = true;
|
||||
self.inline_blame_popover.take();
|
||||
@@ -7291,17 +7315,27 @@ impl Editor {
|
||||
}
|
||||
|
||||
let snapshot = cursor_buffer.read(cx).snapshot();
|
||||
let (start_word_range, _) = snapshot.surrounding_word(cursor_buffer_position, None);
|
||||
let (end_word_range, _) = snapshot.surrounding_word(tail_buffer_position, None);
|
||||
if start_word_range != end_word_range {
|
||||
self.document_highlights_task.take();
|
||||
self.clear_background_highlights(HighlightKey::DocumentHighlightRead, cx);
|
||||
self.clear_background_highlights(HighlightKey::DocumentHighlightWrite, cx);
|
||||
return None;
|
||||
}
|
||||
let word_ranges = cx.background_spawn(async move {
|
||||
// this might look odd to put on the background thread, but
|
||||
// `surrounding_word` can be quite expensive as it calls into
|
||||
// tree-sitter language scopes
|
||||
let (start_word_range, _) = snapshot.surrounding_word(cursor_buffer_position, None);
|
||||
let (end_word_range, _) = snapshot.surrounding_word(tail_buffer_position, None);
|
||||
(start_word_range, end_word_range)
|
||||
});
|
||||
|
||||
let debounce = EditorSettings::get_global(cx).lsp_highlight_debounce.0;
|
||||
self.document_highlights_task = Some(cx.spawn(async move |this, cx| {
|
||||
let (start_word_range, end_word_range) = word_ranges.await;
|
||||
if start_word_range != end_word_range {
|
||||
this.update(cx, |this, cx| {
|
||||
this.document_highlights_task.take();
|
||||
this.clear_background_highlights(HighlightKey::DocumentHighlightRead, cx);
|
||||
this.clear_background_highlights(HighlightKey::DocumentHighlightWrite, cx);
|
||||
})
|
||||
.ok();
|
||||
return;
|
||||
}
|
||||
cx.background_executor()
|
||||
.timer(Duration::from_millis(debounce))
|
||||
.await;
|
||||
@@ -7562,6 +7596,26 @@ impl Editor {
|
||||
});
|
||||
}
|
||||
|
||||
#[ztracing::instrument(skip_all)]
|
||||
fn refresh_outline_symbols(&mut self, cx: &mut Context<Editor>) {
|
||||
if !self.mode.is_full() {
|
||||
return;
|
||||
}
|
||||
let cursor = self.selections.newest_anchor().head();
|
||||
let multibuffer = self.buffer().read(cx).snapshot(cx);
|
||||
let syntax = cx.theme().syntax().clone();
|
||||
let background_task = cx
|
||||
.background_spawn(async move { multibuffer.symbols_containing(cursor, Some(&syntax)) });
|
||||
self.refresh_outline_symbols_task = cx.spawn(async move |this, cx| {
|
||||
let symbols = background_task.await;
|
||||
this.update(cx, |this, cx| {
|
||||
this.outline_symbols = symbols;
|
||||
cx.notify();
|
||||
})
|
||||
.ok();
|
||||
});
|
||||
}
|
||||
|
||||
#[ztracing::instrument(skip_all)]
|
||||
fn refresh_selected_text_highlights(
|
||||
&mut self,
|
||||
@@ -23773,6 +23827,8 @@ impl Editor {
|
||||
self.refresh_code_actions(window, cx);
|
||||
self.refresh_single_line_folds(window, cx);
|
||||
self.refresh_matching_bracket_highlights(window, cx);
|
||||
self.refresh_outline_symbols(cx);
|
||||
self.refresh_sticky_headers(&self.snapshot(window, cx), cx);
|
||||
if self.has_active_edit_prediction() {
|
||||
self.update_visible_edit_prediction(window, cx);
|
||||
}
|
||||
@@ -25180,14 +25236,11 @@ impl Editor {
|
||||
show_underlines: self.diagnostics_enabled(),
|
||||
}
|
||||
}
|
||||
fn breadcrumbs_inner(&self, variant: &Theme, cx: &App) -> Option<Vec<BreadcrumbText>> {
|
||||
let cursor = self.selections.newest_anchor().head();
|
||||
fn breadcrumbs_inner(&self, cx: &App) -> Option<Vec<BreadcrumbText>> {
|
||||
let multibuffer = self.buffer().read(cx);
|
||||
let is_singleton = multibuffer.is_singleton();
|
||||
let (buffer_id, symbols) = multibuffer
|
||||
.read(cx)
|
||||
.symbols_containing(cursor, Some(variant.syntax()))?;
|
||||
let buffer = multibuffer.buffer(buffer_id)?;
|
||||
let (buffer_id, symbols) = self.outline_symbols.as_ref()?;
|
||||
let buffer = multibuffer.buffer(*buffer_id)?;
|
||||
|
||||
let buffer = buffer.read(cx);
|
||||
let settings = ThemeSettings::get_global(cx);
|
||||
@@ -25220,9 +25273,9 @@ impl Editor {
|
||||
vec![]
|
||||
};
|
||||
|
||||
breadcrumbs.extend(symbols.into_iter().map(|symbol| BreadcrumbText {
|
||||
text: symbol.text,
|
||||
highlights: Some(symbol.highlight_ranges),
|
||||
breadcrumbs.extend(symbols.iter().map(|symbol| BreadcrumbText {
|
||||
text: symbol.text.clone(),
|
||||
highlights: Some(symbol.highlight_ranges.clone()),
|
||||
font: Some(settings.buffer_font.clone()),
|
||||
}));
|
||||
Some(breadcrumbs)
|
||||
|
||||
@@ -29063,8 +29063,10 @@ async fn test_sticky_scroll(cx: &mut TestAppContext) {
|
||||
let mut sticky_headers = |offset: ScrollOffset| {
|
||||
cx.update_editor(|e, window, cx| {
|
||||
e.scroll(gpui::Point { x: 0., y: offset }, None, window, cx);
|
||||
let style = e.style(cx).clone();
|
||||
EditorElement::sticky_headers(&e, &e.snapshot(window, cx), &style, cx)
|
||||
});
|
||||
cx.run_until_parked();
|
||||
cx.update_editor(|e, window, cx| {
|
||||
EditorElement::sticky_headers(&e, &e.snapshot(window, cx))
|
||||
.into_iter()
|
||||
.map(
|
||||
|StickyHeader {
|
||||
@@ -29291,6 +29293,7 @@ async fn test_scroll_by_clicking_sticky_header(cx: &mut TestAppContext) {
|
||||
cx,
|
||||
);
|
||||
});
|
||||
cx.run_until_parked();
|
||||
cx.simulate_click(
|
||||
gpui::Point {
|
||||
x: px(0.),
|
||||
@@ -29298,9 +29301,9 @@ async fn test_scroll_by_clicking_sticky_header(cx: &mut TestAppContext) {
|
||||
},
|
||||
Modifiers::none(),
|
||||
);
|
||||
cx.run_until_parked();
|
||||
cx.update_editor(|e, _, cx| (e.scroll_position(cx), display_ranges(e, cx)))
|
||||
};
|
||||
|
||||
assert_eq!(
|
||||
scroll_and_click(
|
||||
4.5, // impl Bar is halfway off the screen
|
||||
|
||||
@@ -4457,7 +4457,6 @@ impl EditorElement {
|
||||
gutter_dimensions: &GutterDimensions,
|
||||
gutter_hitbox: &Hitbox,
|
||||
text_hitbox: &Hitbox,
|
||||
style: &EditorStyle,
|
||||
relative_line_numbers: RelativeLineNumbers,
|
||||
relative_to: Option<DisplayRow>,
|
||||
window: &mut Window,
|
||||
@@ -4467,7 +4466,7 @@ impl EditorElement {
|
||||
.show_line_numbers
|
||||
.unwrap_or_else(|| EditorSettings::get_global(cx).gutter.line_numbers);
|
||||
|
||||
let rows = Self::sticky_headers(self.editor.read(cx), snapshot, style, cx);
|
||||
let rows = Self::sticky_headers(self.editor.read(cx), snapshot);
|
||||
|
||||
let mut lines = Vec::<StickyHeaderLine>::new();
|
||||
|
||||
@@ -4536,22 +4535,13 @@ impl EditorElement {
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn sticky_headers(
|
||||
editor: &Editor,
|
||||
snapshot: &EditorSnapshot,
|
||||
style: &EditorStyle,
|
||||
cx: &App,
|
||||
) -> Vec<StickyHeader> {
|
||||
pub(crate) fn sticky_headers(editor: &Editor, snapshot: &EditorSnapshot) -> Vec<StickyHeader> {
|
||||
let scroll_top = snapshot.scroll_position().y;
|
||||
|
||||
let mut end_rows = Vec::<DisplayRow>::new();
|
||||
let mut rows = Vec::<StickyHeader>::new();
|
||||
|
||||
let items = editor
|
||||
.sticky_headers(&snapshot.display_snapshot, style, cx)
|
||||
.unwrap_or_default();
|
||||
|
||||
for item in items {
|
||||
for item in editor.sticky_headers.iter().flatten() {
|
||||
let start_point = item.range.start.to_point(snapshot.buffer_snapshot());
|
||||
let end_point = item.range.end.to_point(snapshot.buffer_snapshot());
|
||||
|
||||
@@ -4587,7 +4577,7 @@ impl EditorElement {
|
||||
|
||||
end_rows.push(end_row);
|
||||
rows.push(StickyHeader {
|
||||
item,
|
||||
item: item.clone(),
|
||||
sticky_row,
|
||||
start_point,
|
||||
offset,
|
||||
@@ -8060,7 +8050,7 @@ pub(crate) fn render_buffer_header(
|
||||
let editor_handle: &dyn ItemHandle = editor;
|
||||
|
||||
let breadcrumbs = if is_selected {
|
||||
editor_read.breadcrumbs_inner(cx.theme(), cx)
|
||||
editor_read.breadcrumbs_inner(cx)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
@@ -10278,7 +10268,6 @@ impl Element for EditorElement {
|
||||
&gutter_dimensions,
|
||||
&gutter_hitbox,
|
||||
&text_hitbox,
|
||||
&style,
|
||||
relative,
|
||||
current_selection_head,
|
||||
window,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use crate::{Editor, HighlightKey, RangeToAnchorExt};
|
||||
use gpui::{Context, HighlightStyle, Window};
|
||||
use gpui::{AppContext, Context, HighlightStyle, Window};
|
||||
use language::CursorShape;
|
||||
use multi_buffer::MultiBufferOffset;
|
||||
use theme::ActiveTheme;
|
||||
@@ -14,13 +14,13 @@ impl Editor {
|
||||
self.clear_highlights(HighlightKey::MatchingBracket, cx);
|
||||
|
||||
let snapshot = self.snapshot(window, cx);
|
||||
let buffer_snapshot = snapshot.buffer_snapshot();
|
||||
let newest_selection = self.selections.newest::<MultiBufferOffset>(&snapshot);
|
||||
// Don't highlight brackets if the selection isn't empty
|
||||
if !newest_selection.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
let buffer_snapshot = snapshot.buffer_snapshot();
|
||||
let head = newest_selection.head();
|
||||
if head > buffer_snapshot.len() {
|
||||
log::error!("bug: cursor offset is out of range while refreshing bracket highlights");
|
||||
@@ -35,27 +35,35 @@ impl Editor {
|
||||
tail += tail_ch.len_utf8();
|
||||
}
|
||||
}
|
||||
|
||||
if let Some((opening_range, closing_range)) =
|
||||
buffer_snapshot.innermost_enclosing_bracket_ranges(head..tail, None)
|
||||
{
|
||||
self.highlight_text(
|
||||
HighlightKey::MatchingBracket,
|
||||
vec![
|
||||
opening_range.to_anchors(&buffer_snapshot),
|
||||
closing_range.to_anchors(&buffer_snapshot),
|
||||
],
|
||||
HighlightStyle {
|
||||
background_color: Some(
|
||||
cx.theme()
|
||||
.colors()
|
||||
.editor_document_highlight_bracket_background,
|
||||
),
|
||||
..Default::default()
|
||||
},
|
||||
cx,
|
||||
)
|
||||
}
|
||||
let task = cx.background_spawn({
|
||||
let buffer_snapshot = buffer_snapshot.clone();
|
||||
async move { buffer_snapshot.innermost_enclosing_bracket_ranges(head..tail, None) }
|
||||
});
|
||||
self.refresh_matching_bracket_highlights_task = cx.spawn(async move |editor, cx| {
|
||||
if let Some((opening_range, closing_range)) = task.await {
|
||||
let buffer_snapshot = snapshot.buffer_snapshot();
|
||||
editor
|
||||
.update(cx, |editor, cx| {
|
||||
editor.highlight_text(
|
||||
HighlightKey::MatchingBracket,
|
||||
vec![
|
||||
opening_range.to_anchors(&buffer_snapshot),
|
||||
closing_range.to_anchors(&buffer_snapshot),
|
||||
],
|
||||
HighlightStyle {
|
||||
background_color: Some(
|
||||
cx.theme()
|
||||
.colors()
|
||||
.editor_document_highlight_bracket_background,
|
||||
),
|
||||
..Default::default()
|
||||
},
|
||||
cx,
|
||||
)
|
||||
})
|
||||
.ok();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -117,6 +125,7 @@ mod tests {
|
||||
another_test(1, 2, 3);
|
||||
}
|
||||
"#});
|
||||
cx.run_until_parked();
|
||||
cx.assert_editor_text_highlights(
|
||||
HighlightKey::MatchingBracket,
|
||||
indoc! {r#"
|
||||
@@ -131,6 +140,7 @@ mod tests {
|
||||
another_test(1, ˇ2, 3);
|
||||
}
|
||||
"#});
|
||||
cx.run_until_parked();
|
||||
cx.assert_editor_text_highlights(
|
||||
HighlightKey::MatchingBracket,
|
||||
indoc! {r#"
|
||||
@@ -145,6 +155,7 @@ mod tests {
|
||||
anotherˇ_test(1, 2, 3);
|
||||
}
|
||||
"#});
|
||||
cx.run_until_parked();
|
||||
cx.assert_editor_text_highlights(
|
||||
HighlightKey::MatchingBracket,
|
||||
indoc! {r#"
|
||||
@@ -160,6 +171,7 @@ mod tests {
|
||||
another_test(1, 2, 3);
|
||||
}
|
||||
"#});
|
||||
cx.run_until_parked();
|
||||
cx.assert_editor_text_highlights(
|
||||
HighlightKey::MatchingBracket,
|
||||
indoc! {r#"
|
||||
@@ -175,6 +187,7 @@ mod tests {
|
||||
another_test(1, 2, 3);
|
||||
}
|
||||
"#});
|
||||
cx.run_until_parked();
|
||||
cx.assert_editor_text_highlights(
|
||||
HighlightKey::MatchingBracket,
|
||||
indoc! {r#"
|
||||
|
||||
@@ -39,7 +39,6 @@ use std::{
|
||||
sync::Arc,
|
||||
};
|
||||
use text::{BufferId, BufferSnapshot, Selection};
|
||||
use theme::Theme;
|
||||
use ui::{IconDecorationKind, prelude::*};
|
||||
use util::{ResultExt, TryFutureExt, paths::PathExt};
|
||||
use workspace::{
|
||||
@@ -978,9 +977,9 @@ impl Item for Editor {
|
||||
}
|
||||
|
||||
// In a non-singleton case, the breadcrumbs are actually shown on sticky file headers of the multibuffer.
|
||||
fn breadcrumbs(&self, variant: &Theme, cx: &App) -> Option<Vec<BreadcrumbText>> {
|
||||
fn breadcrumbs(&self, cx: &App) -> Option<Vec<BreadcrumbText>> {
|
||||
if self.buffer.read(cx).is_singleton() {
|
||||
self.breadcrumbs_inner(variant, cx)
|
||||
self.breadcrumbs_inner(cx)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
||||
@@ -323,8 +323,8 @@ impl Item for FileDiffView {
|
||||
ToolbarItemLocation::PrimaryLeft
|
||||
}
|
||||
|
||||
fn breadcrumbs(&self, theme: &theme::Theme, cx: &App) -> Option<Vec<BreadcrumbText>> {
|
||||
self.editor.breadcrumbs(theme, cx)
|
||||
fn breadcrumbs(&self, cx: &App) -> Option<Vec<BreadcrumbText>> {
|
||||
self.editor.breadcrumbs(cx)
|
||||
}
|
||||
|
||||
fn added_to_workspace(
|
||||
|
||||
@@ -639,11 +639,7 @@ impl Item for FileHistoryView {
|
||||
false
|
||||
}
|
||||
|
||||
fn breadcrumbs(
|
||||
&self,
|
||||
_theme: &theme::Theme,
|
||||
_cx: &App,
|
||||
) -> Option<Vec<workspace::item::BreadcrumbText>> {
|
||||
fn breadcrumbs(&self, _cx: &App) -> Option<Vec<workspace::item::BreadcrumbText>> {
|
||||
None
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,6 @@ use std::{
|
||||
path::{Path, PathBuf},
|
||||
sync::Arc,
|
||||
};
|
||||
use theme;
|
||||
use ui::{Color, Icon, IconName, Label, LabelCommon as _};
|
||||
use util::paths::PathStyle;
|
||||
use util::rel_path::RelPath;
|
||||
@@ -339,8 +338,8 @@ impl Item for MultiDiffView {
|
||||
ToolbarItemLocation::PrimaryLeft
|
||||
}
|
||||
|
||||
fn breadcrumbs(&self, theme: &theme::Theme, cx: &App) -> Option<Vec<BreadcrumbText>> {
|
||||
self.editor.breadcrumbs(theme, cx)
|
||||
fn breadcrumbs(&self, cx: &App) -> Option<Vec<BreadcrumbText>> {
|
||||
self.editor.breadcrumbs(cx)
|
||||
}
|
||||
|
||||
fn added_to_workspace(
|
||||
|
||||
@@ -17,7 +17,7 @@ use language::File as _;
|
||||
use persistence::IMAGE_VIEWER;
|
||||
use project::{ImageItem, Project, ProjectPath, image_store::ImageItemEvent};
|
||||
use settings::Settings;
|
||||
use theme::{Theme, ThemeSettings};
|
||||
use theme::ThemeSettings;
|
||||
use ui::{Tooltip, prelude::*};
|
||||
use util::paths::PathExt;
|
||||
use workspace::{
|
||||
@@ -558,7 +558,7 @@ impl Item for ImageView {
|
||||
}
|
||||
}
|
||||
|
||||
fn breadcrumbs(&self, _theme: &Theme, cx: &App) -> Option<Vec<BreadcrumbText>> {
|
||||
fn breadcrumbs(&self, cx: &App) -> Option<Vec<BreadcrumbText>> {
|
||||
let text = breadcrumbs_text_for_image(self.project.read(cx), self.image_item.read(cx), cx);
|
||||
let settings = ThemeSettings::get_global(cx);
|
||||
|
||||
|
||||
@@ -80,7 +80,7 @@ impl MultibufferHint {
|
||||
};
|
||||
|
||||
if active_pane_item.buffer_kind(cx) == ItemBufferKind::Singleton
|
||||
|| active_pane_item.breadcrumbs(cx.theme(), cx).is_none()
|
||||
|| active_pane_item.breadcrumbs(cx).is_none()
|
||||
|| !active_pane_item.can_save(cx)
|
||||
{
|
||||
return ToolbarItemLocation::Hidden;
|
||||
|
||||
@@ -1494,7 +1494,7 @@ impl Item for TerminalView {
|
||||
}
|
||||
}
|
||||
|
||||
fn breadcrumbs(&self, _: &theme::Theme, cx: &App) -> Option<Vec<BreadcrumbText>> {
|
||||
fn breadcrumbs(&self, cx: &App) -> Option<Vec<BreadcrumbText>> {
|
||||
Some(vec![BreadcrumbText {
|
||||
text: self.terminal().read(cx).breadcrumb_text.clone(),
|
||||
highlights: None,
|
||||
|
||||
@@ -31,7 +31,6 @@ use std::{
|
||||
sync::Arc,
|
||||
time::Duration,
|
||||
};
|
||||
use theme::Theme;
|
||||
use ui::{Color, Icon, IntoElement, Label, LabelCommon};
|
||||
use util::ResultExt;
|
||||
|
||||
@@ -328,7 +327,7 @@ pub trait Item: Focusable + EventEmitter<Self::Event> + Render + Sized {
|
||||
ToolbarItemLocation::Hidden
|
||||
}
|
||||
|
||||
fn breadcrumbs(&self, _theme: &Theme, _cx: &App) -> Option<Vec<BreadcrumbText>> {
|
||||
fn breadcrumbs(&self, _cx: &App) -> Option<Vec<BreadcrumbText>> {
|
||||
None
|
||||
}
|
||||
|
||||
@@ -535,7 +534,7 @@ pub trait ItemHandle: 'static + Send {
|
||||
) -> gpui::Subscription;
|
||||
fn to_searchable_item_handle(&self, cx: &App) -> Option<Box<dyn SearchableItemHandle>>;
|
||||
fn breadcrumb_location(&self, cx: &App) -> ToolbarItemLocation;
|
||||
fn breadcrumbs(&self, theme: &Theme, cx: &App) -> Option<Vec<BreadcrumbText>>;
|
||||
fn breadcrumbs(&self, cx: &App) -> Option<Vec<BreadcrumbText>>;
|
||||
fn breadcrumb_prefix(&self, window: &mut Window, cx: &mut App) -> Option<gpui::AnyElement>;
|
||||
fn show_toolbar(&self, cx: &App) -> bool;
|
||||
fn pixel_position_of_cursor(&self, cx: &App) -> Option<Point<Pixels>>;
|
||||
@@ -1059,8 +1058,8 @@ impl<T: Item> ItemHandle for Entity<T> {
|
||||
self.read(cx).breadcrumb_location(cx)
|
||||
}
|
||||
|
||||
fn breadcrumbs(&self, theme: &Theme, cx: &App) -> Option<Vec<BreadcrumbText>> {
|
||||
self.read(cx).breadcrumbs(theme, cx)
|
||||
fn breadcrumbs(&self, cx: &App) -> Option<Vec<BreadcrumbText>> {
|
||||
self.read(cx).breadcrumbs(cx)
|
||||
}
|
||||
|
||||
fn breadcrumb_prefix(&self, window: &mut Window, cx: &mut App) -> Option<gpui::AnyElement> {
|
||||
|
||||
Reference in new issue
Block a user