From afd0da97b930c1cf07698c6fdd970dacf649c5a4 Mon Sep 17 00:00:00 2001 From: Finn Evers Date: Fri, 14 Mar 2025 21:13:59 +0100 Subject: [PATCH] language_selector: Improve lookup for language icons (#26376) This PR fixes a rare case where icons could be missing in the language selector. Currently, whilst looking up an icon, all file suffixes starting with a dot are filtered out. While this works fine for some languages, there are some languages having only file suffixes starting with a dot, e.g. the "Git Attributes" language provided from the "Git Firefly" extension. This results in no icon being displayed in the list, as shown in the screenshots below. To solve this, we can just simply remove the check for this special case as well as the construction of an artificial file name in the code, as both are not needed. A simple path just consisting of the extension is sufficient, as we currently do not differentiate between file names and file suffixes during an icon lookup. see the relevant code below: https://github.com/zed-industries/zed/blob/013a64679947fca3c940d319841069000d5ddf2b/crates/file_icons/src/file_icons.rs#L23-L52 As the first lookup is directly done using the entire file name and then checked against all suffixes, we actually do not have to construct an artificial file name at all. Should that produce no match, we check for a hidden file right after, so we do not have to filter hidden file names out. With this fix, nothing changes for "normal" file suffixes, for some cases where languges provide entire file names as a path suffix, the matching might improve, and for languages with only hidden associated file names, the initially described issue is resolved. I do believe the behavior of matching icons to languages could be improved in general. Fowever, I do think this is beyond the scope of this change. | Current main | main | | --- | --- | | This PR |PR| Aditionally, in 4395f78fb2c49f74c4bfa6b4146aee8b55435838 I refactored the code which acquires the label and icon for a match, since I found it a bit hard to read initially. The majority of this diff comes from this change. Should that not be wanted, I can revert that change. Release Notes: - Fixed a rare case where languages had no associated icon in the language selector. --- .../src/language_selector.rs | 50 ++++++++----------- 1 file changed, 20 insertions(+), 30 deletions(-) diff --git a/crates/language_selector/src/language_selector.rs b/crates/language_selector/src/language_selector.rs index 10af10b4d2848e97bae936ae955cf41c46613427..d4b661ed9dd1f8c0919ad7833e4c2e0c741d415d 100644 --- a/crates/language_selector/src/language_selector.rs +++ b/crates/language_selector/src/language_selector.rs @@ -139,31 +139,27 @@ impl LanguageSelectorDelegate { let mut label = mat.string.clone(); let buffer_language = self.buffer.read(cx).language(); let need_icon = FileFinderSettings::get_global(cx).file_icons; - if let Some(buffer_language) = buffer_language { - let buffer_language_name = buffer_language.name(); - if buffer_language_name.as_ref() == mat.string.as_str() { - label.push_str(" (current)"); - let icon = need_icon - .then(|| self.language_icon(&buffer_language.config().matcher, cx)) - .flatten(); - return (label, icon); - } - } - if need_icon { - let language_name = LanguageName::new(mat.string.as_str()); - match self - .language_registry - .available_language_for_name(language_name.as_ref()) - { - Some(available_language) => { - let icon = self.language_icon(available_language.matcher(), cx); - (label, icon) - } - None => (label, None), - } + if let Some(buffer_language) = buffer_language + .filter(|buffer_language| buffer_language.name().as_ref() == mat.string.as_str()) + { + label.push_str(" (current)"); + let icon = need_icon + .then(|| self.language_icon(&buffer_language.config().matcher, cx)) + .flatten(); + (label, icon) } else { - (label, None) + let icon = need_icon + .then(|| { + let language_name = LanguageName::new(mat.string.as_str()); + self.language_registry + .available_language_for_name(language_name.as_ref()) + .and_then(|available_language| { + self.language_icon(available_language.matcher(), cx) + }) + }) + .flatten(); + (label, icon) } } @@ -171,13 +167,7 @@ impl LanguageSelectorDelegate { matcher .path_suffixes .iter() - .find_map(|extension| { - if extension.contains('.') { - None - } else { - FileIcons::get_icon(Path::new(&format!("file.{extension}")), cx) - } - }) + .find_map(|extension| FileIcons::get_icon(Path::new(extension), cx)) .map(Icon::from_path) .map(|icon| icon.color(Color::Muted)) }