Improve outline fonts and colors (#63325)
Closes https://github.com/zed-industries/zed/issues/58580 * Outline modal and panel now use buffer fonts for the contents: <img width="1728" height="1117" alt="modal" src="https://github.com/user-attachments/assets/5e0ef6e3-be39-4949-bc32-7087a51a02ec" /> <img width="1728" height="1092" alt="panel" src="https://github.com/user-attachments/assets/5cf9edbf-5ff3-402d-a2ca-bc915bd10e8e" /> * Gutter colors are now fall-backed to tree-sitter better, if no semantic tokens could be retrieved due to multi buffer shenanigans: <img width="1728" height="426" alt="gutter" src="https://github.com/user-attachments/assets/a175b2c8-843e-4632-b030-3edfbd350982" /> Release Notes: - Improved outline fonts and colors
This commit is contained in:
1 parent
2ada348466
commit
8a54abc4b9
8 files changed
+177
-60
No files matched your search
Generated
-1
@@ -12404,7 +12404,6 @@ dependencies = [
|
|||||||
"serde_json",
|
"serde_json",
|
||||||
"settings",
|
"settings",
|
||||||
"theme",
|
"theme",
|
||||||
"theme_settings",
|
|
||||||
"ui",
|
"ui",
|
||||||
"util",
|
"util",
|
||||||
"workspace",
|
"workspace",
|
||||||
|
|||||||
@@ -10,9 +10,9 @@ use editor::{
|
|||||||
};
|
};
|
||||||
use fuzzy::{StringMatch, StringMatchCandidate};
|
use fuzzy::{StringMatch, StringMatchCandidate};
|
||||||
use gpui::{
|
use gpui::{
|
||||||
AbsoluteLength, Action, AnyView, App, AsyncWindowContext, Context, DismissEvent, Entity,
|
Action, AnyView, App, AsyncWindowContext, Context, DismissEvent, Entity, EventEmitter,
|
||||||
EventEmitter, FocusHandle, Focusable, HighlightStyle, ParentElement, Point, Render, Styled,
|
FocusHandle, Focusable, HighlightStyle, ParentElement, Point, Render, Styled, StyledText,
|
||||||
StyledText, Subscription, Task, TextRun, TextStyle, WeakEntity, Window,
|
Subscription, Task, TextRun, WeakEntity, Window,
|
||||||
};
|
};
|
||||||
use language::{
|
use language::{
|
||||||
Buffer, CodeLabel, File as _, Language, Location, Rope, ToOffset, ToPoint, lsp_to_symbol_kind,
|
Buffer, CodeLabel, File as _, Language, Location, Rope, ToOffset, ToPoint, lsp_to_symbol_kind,
|
||||||
@@ -20,9 +20,10 @@ use language::{
|
|||||||
use picker::{Picker, PickerDelegate};
|
use picker::{Picker, PickerDelegate};
|
||||||
use project::{CallHierarchyItem, LspStoreEvent, Project};
|
use project::{CallHierarchyItem, LspStoreEvent, Project};
|
||||||
use settings::Settings;
|
use settings::Settings;
|
||||||
use theme::SyntaxTheme;
|
|
||||||
use theme_settings::ThemeSettings;
|
use theme_settings::ThemeSettings;
|
||||||
use ui::{KeyBinding, ListItem, ListItemSpacing, prelude::*, tooltip_container};
|
use ui::{
|
||||||
|
KeyBinding, ListItem, ListItemSpacing, prelude::*, tooltip_container, utils::buffer_text_style,
|
||||||
|
};
|
||||||
use util::{ResultExt, paths::PathExt};
|
use util::{ResultExt, paths::PathExt};
|
||||||
use workspace::{DismissDecision, ModalView, Workspace};
|
use workspace::{DismissDecision, ModalView, Workspace};
|
||||||
pub use zed_actions::{ShowIncomingCalls, ShowOutgoingCalls, ToggleDirection};
|
pub use zed_actions::{ShowIncomingCalls, ShowOutgoingCalls, ToggleDirection};
|
||||||
@@ -806,7 +807,7 @@ impl Render for CallSignatureTooltip {
|
|||||||
Some((label, label_text)) => StyledText::new(label_text.clone())
|
Some((label, label_text)) => StyledText::new(label_text.clone())
|
||||||
.with_default_highlights(
|
.with_default_highlights(
|
||||||
&signature_style,
|
&signature_style,
|
||||||
label_syntax_runs(label, cx.theme().syntax()),
|
cx.theme().syntax().resolve_runs(&label.runs),
|
||||||
)
|
)
|
||||||
.into_any_element(),
|
.into_any_element(),
|
||||||
None => div().child(self.full_signature.clone()).into_any_element(),
|
None => div().child(self.full_signature.clone()).into_any_element(),
|
||||||
@@ -1170,29 +1171,6 @@ fn shaped_width(
|
|||||||
.width
|
.width
|
||||||
}
|
}
|
||||||
|
|
||||||
fn buffer_text_style(cx: &App) -> TextStyle {
|
|
||||||
let settings = ThemeSettings::get_global(cx);
|
|
||||||
TextStyle {
|
|
||||||
color: cx.theme().colors().text,
|
|
||||||
font_family: settings.buffer_font.family.clone(),
|
|
||||||
font_features: settings.buffer_font.features.clone(),
|
|
||||||
font_fallbacks: settings.buffer_font.fallbacks.clone(),
|
|
||||||
font_size: AbsoluteLength::from(settings.buffer_font_size(cx)),
|
|
||||||
font_weight: settings.buffer_font.weight,
|
|
||||||
line_height: relative(1.),
|
|
||||||
..TextStyle::default()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn label_syntax_runs<'a>(
|
|
||||||
label: &'a CodeLabel,
|
|
||||||
syntax_theme: &'a SyntaxTheme,
|
|
||||||
) -> impl Iterator<Item = (Range<usize>, HighlightStyle)> + 'a {
|
|
||||||
label.runs.iter().filter_map(|(range, highlight_id)| {
|
|
||||||
Some((range.clone(), *syntax_theme.get(*highlight_id)?))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn render_item(
|
fn render_item(
|
||||||
call_item: &Call,
|
call_item: &Call,
|
||||||
match_ranges: impl IntoIterator<Item = Range<usize>>,
|
match_ranges: impl IntoIterator<Item = Range<usize>>,
|
||||||
@@ -1225,7 +1203,7 @@ fn render_item(
|
|||||||
.as_ref()
|
.as_ref()
|
||||||
.zip(call_item.display.label_text.clone())
|
.zip(call_item.display.label_text.clone())
|
||||||
{
|
{
|
||||||
let syntax_runs = label_syntax_runs(label, cx.theme().syntax());
|
let syntax_runs = cx.theme().syntax().resolve_runs(&label.runs);
|
||||||
let custom_highlights = match_ranges.into_iter().map(|range| {
|
let custom_highlights = match_ranges.into_iter().map(|range| {
|
||||||
let start = label.filter_range.start + range.start;
|
let start = label.filter_range.start + range.start;
|
||||||
let end = label.filter_range.start + range.end;
|
let end = label.filter_range.start + range.end;
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ use futures::future::join_all;
|
|||||||
use gpui::{App, Context, HighlightStyle, Task};
|
use gpui::{App, Context, HighlightStyle, Task};
|
||||||
use itertools::Itertools as _;
|
use itertools::Itertools as _;
|
||||||
use language::language_settings::LanguageSettings;
|
use language::language_settings::LanguageSettings;
|
||||||
use language::{Buffer, OutlineItem};
|
use language::{Buffer, OutlineItem, highlight_ranges_from_text};
|
||||||
use multi_buffer::{
|
use multi_buffer::{
|
||||||
Anchor, AnchorRangeExt as _, MultiBufferOffset, MultiBufferRow, MultiBufferSnapshot,
|
Anchor, AnchorRangeExt as _, MultiBufferOffset, MultiBufferRow, MultiBufferSnapshot,
|
||||||
ToOffset as _,
|
ToOffset as _,
|
||||||
@@ -219,12 +219,20 @@ impl Editor {
|
|||||||
let display_snapshot =
|
let display_snapshot =
|
||||||
editor.display_map.update(cx, |map, cx| map.snapshot(cx));
|
editor.display_map.update(cx, |map, cx| map.snapshot(cx));
|
||||||
let mut highlighted_results = results;
|
let mut highlighted_results = results;
|
||||||
for items in highlighted_results.values_mut() {
|
for (buffer_id, items) in highlighted_results.iter_mut() {
|
||||||
|
let language = editor
|
||||||
|
.buffer
|
||||||
|
.read(cx)
|
||||||
|
.buffer(*buffer_id)
|
||||||
|
.and_then(|buffer| buffer.read(cx).language().cloned());
|
||||||
for item in items {
|
for item in items {
|
||||||
if let Some(highlights) =
|
if let Some(highlights) =
|
||||||
highlights_from_buffer(&display_snapshot, &item, &syntax)
|
highlights_from_buffer(&display_snapshot, &item, &syntax)
|
||||||
{
|
{
|
||||||
item.highlight_ranges = highlights;
|
item.highlight_ranges = highlights;
|
||||||
|
} else if let Some(language) = &language {
|
||||||
|
item.highlight_ranges =
|
||||||
|
highlight_ranges_from_text(&item.text, language, &syntax);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -334,6 +342,7 @@ mod tests {
|
|||||||
|
|
||||||
use futures::StreamExt as _;
|
use futures::StreamExt as _;
|
||||||
use gpui::{App, TestAppContext};
|
use gpui::{App, TestAppContext};
|
||||||
|
use language::highlight_ranges_from_text;
|
||||||
use multi_buffer::ToPoint;
|
use multi_buffer::ToPoint;
|
||||||
use settings::{DocumentSymbols, SettingsStore};
|
use settings::{DocumentSymbols, SettingsStore};
|
||||||
use text::Point;
|
use text::Point;
|
||||||
@@ -813,6 +822,82 @@ mod tests {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[gpui::test]
|
||||||
|
async fn test_lsp_document_symbols_fall_back_to_reparsed_text_highlights(
|
||||||
|
cx: &mut TestAppContext,
|
||||||
|
) {
|
||||||
|
use ui::ActiveTheme as _;
|
||||||
|
|
||||||
|
init_test(cx, |_| {});
|
||||||
|
|
||||||
|
update_test_language_settings(cx, &|settings| {
|
||||||
|
settings.defaults.document_symbols = Some(DocumentSymbols::On);
|
||||||
|
});
|
||||||
|
|
||||||
|
let mut cx = EditorLspTestContext::new_rust(
|
||||||
|
lsp::ServerCapabilities {
|
||||||
|
document_symbol_provider: Some(lsp::OneOf::Left(true)),
|
||||||
|
..lsp::ServerCapabilities::default()
|
||||||
|
},
|
||||||
|
cx,
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
cx.update_editor(|editor, _window, cx| {
|
||||||
|
editor
|
||||||
|
.project
|
||||||
|
.as_ref()
|
||||||
|
.expect("editor should have a project")
|
||||||
|
.read(cx)
|
||||||
|
.languages()
|
||||||
|
.set_theme(cx.theme().clone());
|
||||||
|
});
|
||||||
|
let mut symbol_request = cx
|
||||||
|
.set_request_handler::<lsp::request::DocumentSymbolRequest, _, _>(
|
||||||
|
move |_, _, _| async move {
|
||||||
|
Ok(Some(lsp::DocumentSymbolResponse::Nested(vec![
|
||||||
|
nested_symbol(
|
||||||
|
"impl ZzzMissing",
|
||||||
|
lsp::SymbolKind::OBJECT,
|
||||||
|
lsp_range(0, 0, 0, 12),
|
||||||
|
lsp_range(0, 3, 0, 7),
|
||||||
|
Vec::new(),
|
||||||
|
),
|
||||||
|
])))
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
cx.set_state("fn teˇst() {}\n");
|
||||||
|
assert!(symbol_request.next().await.is_some());
|
||||||
|
cx.run_until_parked();
|
||||||
|
|
||||||
|
cx.update_editor(|editor, _window, cx| {
|
||||||
|
let (_, symbols) = editor
|
||||||
|
.outline_symbols_at_cursor
|
||||||
|
.as_ref()
|
||||||
|
.expect("Should have outline symbols");
|
||||||
|
assert_eq!(symbols.len(), 1);
|
||||||
|
let symbol = &symbols[0];
|
||||||
|
assert_eq!(symbol.text, "impl ZzzMissing");
|
||||||
|
|
||||||
|
let language = editor
|
||||||
|
.buffer
|
||||||
|
.read(cx)
|
||||||
|
.as_singleton()
|
||||||
|
.expect("singleton buffer")
|
||||||
|
.read(cx)
|
||||||
|
.language()
|
||||||
|
.cloned()
|
||||||
|
.expect("buffer language");
|
||||||
|
let expected = highlight_ranges_from_text(&symbol.text, &language, cx.theme().syntax());
|
||||||
|
assert_eq!(
|
||||||
|
expected.first().map(|(range, _)| range.clone()),
|
||||||
|
Some(0..4),
|
||||||
|
"reparsing the symbol text should highlight the `impl` keyword"
|
||||||
|
);
|
||||||
|
assert_eq!(symbol.highlight_ranges, expected);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
#[gpui::test]
|
#[gpui::test]
|
||||||
async fn test_lsp_document_symbols_empty_response(cx: &mut TestAppContext) {
|
async fn test_lsp_document_symbols_empty_response(cx: &mut TestAppContext) {
|
||||||
init_test(cx, |_| {});
|
init_test(cx, |_| {});
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
use crate::{BufferSnapshot, Point, ToPoint, ToTreeSitterPoint};
|
use crate::{BufferSnapshot, Language, Point, ToPoint, ToTreeSitterPoint};
|
||||||
use fuzzy_nucleo::{Case, LengthPenalty, StringMatch, StringMatchCandidate};
|
use fuzzy_nucleo::{Case, LengthPenalty, StringMatch, StringMatchCandidate};
|
||||||
use gpui::{BackgroundExecutor, HighlightStyle, SharedString};
|
use gpui::{BackgroundExecutor, HighlightStyle, SharedString};
|
||||||
use std::ops::Range;
|
use std::{ops::Range, sync::Arc};
|
||||||
|
use text::Rope;
|
||||||
|
use theme::SyntaxTheme;
|
||||||
|
|
||||||
/// An outline of all the symbols contained in a buffer.
|
/// An outline of all the symbols contained in a buffer.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@@ -262,6 +264,16 @@ impl<T> Outline<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn highlight_ranges_from_text(
|
||||||
|
text: &str,
|
||||||
|
language: &Arc<Language>,
|
||||||
|
syntax_theme: &SyntaxTheme,
|
||||||
|
) -> Vec<(Range<usize>, HighlightStyle)> {
|
||||||
|
let rope = Rope::from(text);
|
||||||
|
let runs = language.highlight_text(&rope, 0..text.len());
|
||||||
|
syntax_theme.resolve_runs(&runs).collect()
|
||||||
|
}
|
||||||
|
|
||||||
/// Interleaves synthetic [`OutlineSearchEntry::Ancestor`] rows before each match so callers
|
/// Interleaves synthetic [`OutlineSearchEntry::Ancestor`] rows before each match so callers
|
||||||
/// can render the parent chain as tree context above the match.
|
/// can render the parent chain as tree context above the match.
|
||||||
///
|
///
|
||||||
@@ -414,4 +426,38 @@ mod tests {
|
|||||||
assert_eq!(outline.find_most_similar("struct User"), None);
|
assert_eq!(outline.find_most_similar("struct User"), None);
|
||||||
assert_eq!(outline.find_most_similar("struct"), None);
|
assert_eq!(outline.find_most_similar("struct"), None);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_highlight_ranges_from_text() {
|
||||||
|
let language = rust_lang();
|
||||||
|
let keyword = HighlightStyle::color(gpui::Hsla::from(gpui::rgba(0x100000ff)));
|
||||||
|
let type_style = HighlightStyle::color(gpui::Hsla::from(gpui::rgba(0x200000ff)));
|
||||||
|
let theme = SyntaxTheme::new([
|
||||||
|
("keyword".to_string(), keyword),
|
||||||
|
("type".to_string(), type_style),
|
||||||
|
]);
|
||||||
|
language.set_theme(&theme);
|
||||||
|
|
||||||
|
let text = "impl LspCommand for GetIncomingCalls";
|
||||||
|
assert_eq!(
|
||||||
|
highlight_ranges_from_text(text, &language, &theme),
|
||||||
|
vec![
|
||||||
|
(0..4, keyword),
|
||||||
|
(5..15, type_style),
|
||||||
|
(16..19, keyword),
|
||||||
|
(20..36, type_style),
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
let text = "pub struct OutlineItem";
|
||||||
|
assert_eq!(
|
||||||
|
highlight_ranges_from_text(text, &language, &theme),
|
||||||
|
vec![(0..3, keyword), (4..10, keyword), (11..22, type_style)]
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
highlight_ranges_from_text("", &language, &theme),
|
||||||
|
Vec::new()
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -21,7 +21,6 @@ picker.workspace = true
|
|||||||
picker_preview.workspace = true
|
picker_preview.workspace = true
|
||||||
settings.workspace = true
|
settings.workspace = true
|
||||||
theme.workspace = true
|
theme.workspace = true
|
||||||
theme_settings.workspace = true
|
|
||||||
ui.workspace = true
|
ui.workspace = true
|
||||||
util.workspace = true
|
util.workspace = true
|
||||||
workspace.workspace = true
|
workspace.workspace = true
|
||||||
|
|||||||
@@ -7,15 +7,12 @@ use editor::{MultiBufferOffset, RowHighlightOptions, SelectionEffects};
|
|||||||
use fuzzy_nucleo::StringMatch;
|
use fuzzy_nucleo::StringMatch;
|
||||||
use gpui::{
|
use gpui::{
|
||||||
App, Context, DismissEvent, Entity, EventEmitter, FocusHandle, Focusable, HighlightStyle,
|
App, Context, DismissEvent, Entity, EventEmitter, FocusHandle, Focusable, HighlightStyle,
|
||||||
ParentElement, Point, Rems, Render, Styled, StyledText, Task, TextStyle, WeakEntity, Window,
|
ParentElement, Point, Rems, Render, Styled, StyledText, Task, WeakEntity, Window, div, rems,
|
||||||
div, rems,
|
|
||||||
};
|
};
|
||||||
use language::{OffsetRangeExt, Outline, OutlineItem, OutlineSearchEntry};
|
use language::{OffsetRangeExt, Outline, OutlineItem, OutlineSearchEntry};
|
||||||
use picker::{MatchLocation, Picker, PickerDelegate, PreviewUpdate};
|
use picker::{MatchLocation, Picker, PickerDelegate, PreviewUpdate};
|
||||||
use settings::Settings;
|
|
||||||
use theme::ActiveTheme;
|
use theme::ActiveTheme;
|
||||||
use theme_settings::ThemeSettings;
|
use ui::{ListItem, ListItemSpacing, prelude::*, utils::buffer_text_style};
|
||||||
use ui::{ListItem, ListItemSpacing, prelude::*};
|
|
||||||
use workspace::{DismissDecision, ModalView};
|
use workspace::{DismissDecision, ModalView};
|
||||||
|
|
||||||
pub fn init(cx: &mut App) {
|
pub fn init(cx: &mut App) {
|
||||||
@@ -463,11 +460,11 @@ impl PickerDelegate for OutlineViewDelegate {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn render_item<T>(
|
pub fn render_item<T, M: IntoIterator<Item = Range<usize>>>(
|
||||||
outline_item: &OutlineItem<T>,
|
outline_item: &OutlineItem<T>,
|
||||||
match_ranges: impl IntoIterator<Item = Range<usize>>,
|
match_ranges: M,
|
||||||
cx: &App,
|
cx: &App,
|
||||||
) -> StyledText {
|
) -> impl IntoElement + use<T, M> {
|
||||||
let highlight_style = HighlightStyle {
|
let highlight_style = HighlightStyle {
|
||||||
background_color: Some(cx.theme().colors().text_accent.alpha(0.3)),
|
background_color: Some(cx.theme().colors().text_accent.alpha(0.3)),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@@ -476,27 +473,16 @@ pub fn render_item<T>(
|
|||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|range| (range, highlight_style));
|
.map(|range| (range, highlight_style));
|
||||||
|
|
||||||
let settings = ThemeSettings::get_global(cx);
|
let text_style = buffer_text_style(cx);
|
||||||
|
let buffer_font_size = text_style.font_size;
|
||||||
// TODO: We probably shouldn't need to build a whole new text style here
|
|
||||||
// but I'm not sure how to get the current one and modify it.
|
|
||||||
// Before this change TextStyle::default() was used here, which was giving us the wrong font and text color.
|
|
||||||
let text_style = TextStyle {
|
|
||||||
color: cx.theme().colors().text,
|
|
||||||
font_family: settings.buffer_font.family.clone(),
|
|
||||||
font_features: settings.buffer_font.features.clone(),
|
|
||||||
font_fallbacks: settings.buffer_font.fallbacks.clone(),
|
|
||||||
font_size: settings.buffer_font_size(cx).into(),
|
|
||||||
font_weight: settings.buffer_font.weight,
|
|
||||||
line_height: relative(1.),
|
|
||||||
..Default::default()
|
|
||||||
};
|
|
||||||
let highlights = gpui::combine_highlights(
|
let highlights = gpui::combine_highlights(
|
||||||
custom_highlights,
|
custom_highlights,
|
||||||
outline_item.highlight_ranges.iter().cloned(),
|
outline_item.highlight_ranges.iter().cloned(),
|
||||||
);
|
);
|
||||||
|
|
||||||
StyledText::new(outline_item.text.clone()).with_default_highlights(&text_style, highlights)
|
div().text_size(buffer_font_size).child(
|
||||||
|
StyledText::new(outline_item.text.clone()).with_default_highlights(&text_style, highlights),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
collections::{BTreeMap, btree_map::Entry},
|
collections::{BTreeMap, btree_map::Entry},
|
||||||
|
ops::Range,
|
||||||
sync::Arc,
|
sync::Arc,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -61,6 +62,14 @@ impl SyntaxTheme {
|
|||||||
self.highlights.get(highlight_index.into())
|
self.highlights.get(highlight_index.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn resolve_runs<'a, Id: Into<usize> + Copy + 'a>(
|
||||||
|
&'a self,
|
||||||
|
runs: impl IntoIterator<Item = &'a (Range<usize>, Id)> + 'a,
|
||||||
|
) -> impl Iterator<Item = (Range<usize>, HighlightStyle)> + 'a {
|
||||||
|
runs.into_iter()
|
||||||
|
.filter_map(|(range, highlight_id)| Some((range.clone(), *self.get(*highlight_id)?)))
|
||||||
|
}
|
||||||
|
|
||||||
pub fn style_for_name(&self, name: &str) -> Option<HighlightStyle> {
|
pub fn style_for_name(&self, name: &str) -> Option<HighlightStyle> {
|
||||||
self.capture_name_map
|
self.capture_name_map
|
||||||
.get(name)
|
.get(name)
|
||||||
|
|||||||
@@ -26,6 +26,21 @@ pub fn is_light(cx: &mut App) -> bool {
|
|||||||
cx.theme().appearance.is_light()
|
cx.theme().appearance.is_light()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn buffer_text_style(cx: &App) -> gpui::TextStyle {
|
||||||
|
let settings = theme::theme_settings(cx);
|
||||||
|
let buffer_font = settings.buffer_font(cx);
|
||||||
|
gpui::TextStyle {
|
||||||
|
color: cx.theme().colors().text,
|
||||||
|
font_family: buffer_font.family.clone(),
|
||||||
|
font_features: buffer_font.features.clone(),
|
||||||
|
font_fallbacks: buffer_font.fallbacks.clone(),
|
||||||
|
font_size: gpui::AbsoluteLength::from(settings.buffer_font_size(cx)),
|
||||||
|
font_weight: buffer_font.weight,
|
||||||
|
line_height: gpui::relative(1.),
|
||||||
|
..gpui::TextStyle::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the platform-appropriate label for the "reveal in file manager" action.
|
/// Returns the platform-appropriate label for the "reveal in file manager" action.
|
||||||
pub fn reveal_in_file_manager_label(is_remote: bool) -> &'static str {
|
pub fn reveal_in_file_manager_label(is_remote: bool) -> &'static str {
|
||||||
if cfg!(target_os = "macos") && !is_remote {
|
if cfg!(target_os = "macos") && !is_remote {
|
||||||
|
|||||||
Reference in new issue
Block a user