@@ -1,13 +1,14 @@
+use gpui::App;
use settings::{LanguageSettingsContent, SettingsContent};
use std::sync::Arc;
use ui::{IntoElement, SharedString};
use crate::{
LOCAL, SettingField, SettingItem, SettingsFieldMetadata, SettingsPage, SettingsPageItem,
- SubPageLink, USER, sub_page_stack,
+ SubPageLink, USER, all_language_names, sub_page_stack,
};
-pub(crate) fn settings_data() -> Vec<SettingsPage> {
+pub(crate) fn settings_data(cx: &App) -> Vec<SettingsPage> {
vec![
SettingsPage {
title: "General",
@@ -1405,74 +1406,27 @@ pub(crate) fn settings_data() -> Vec<SettingsPage> {
},
SettingsPage {
title: "Languages",
- items: vec![
- SettingsPageItem::SectionHeader(LANGUAGES_SECTION_HEADER),
- SettingsPageItem::SubPageLink(SubPageLink {
- title: "JSON",
- files: USER | LOCAL,
- render: Arc::new(|this, window, cx| {
- this.render_page_items(
- language_settings_data().iter().enumerate(),
- None,
- window,
- cx,
- )
- .into_any_element()
- }),
- }),
- SettingsPageItem::SubPageLink(SubPageLink {
- title: "JSONC",
- files: USER | LOCAL,
- render: Arc::new(|this, window, cx| {
- this.render_page_items(
- language_settings_data().iter().enumerate(),
- None,
- window,
- cx,
- )
- .into_any_element()
- }),
- }),
- SettingsPageItem::SubPageLink(SubPageLink {
- title: "Rust",
- files: USER | LOCAL,
- render: Arc::new(|this, window, cx| {
- this.render_page_items(
- language_settings_data().iter().enumerate(),
- None,
- window,
- cx,
- )
- .into_any_element()
- }),
- }),
- SettingsPageItem::SubPageLink(SubPageLink {
- title: "Python",
- files: USER | LOCAL,
- render: Arc::new(|this, window, cx| {
- this.render_page_items(
- language_settings_data().iter().enumerate(),
- None,
- window,
- cx,
- )
- .into_any_element()
- }),
- }),
- SettingsPageItem::SubPageLink(SubPageLink {
- title: "TSX",
- files: USER | LOCAL,
- render: Arc::new(|this, window, cx| {
- this.render_page_items(
- language_settings_data().iter().enumerate(),
- None,
- window,
- cx,
- )
- .into_any_element()
- }),
- }),
- ],
+ items: {
+ let mut items = vec![SettingsPageItem::SectionHeader(LANGUAGES_SECTION_HEADER)];
+ // todo(settings_ui): Refresh on extension (un)/installed
+ // Note that `crates/json_schema_store` solves the same problem, there is probably a way to unify the two
+ items.extend(all_language_names(cx).into_iter().map(|language_name| {
+ SettingsPageItem::SubPageLink(SubPageLink {
+ title: language_name,
+ files: USER | LOCAL,
+ render: Arc::new(|this, window, cx| {
+ this.render_page_items(
+ language_settings_data().iter().enumerate(),
+ None,
+ window,
+ cx,
+ )
+ .into_any_element()
+ }),
+ })
+ }));
+ items
+ },
},
SettingsPage {
title: "Search & Files",
@@ -4678,8 +4632,7 @@ const LANGUAGES_SECTION_HEADER: &'static str = "Languages";
fn language_settings_data() -> Vec<SettingsPageItem> {
fn current_language() -> Option<SharedString> {
sub_page_stack().iter().find_map(|page| {
- (page.section_header == LANGUAGES_SECTION_HEADER)
- .then(|| SharedString::new_static(page.link.title))
+ (page.section_header == LANGUAGES_SECTION_HEADER).then(|| page.link.title.clone())
})
}
@@ -608,7 +608,7 @@ impl SettingsPageItem {
.into_any_element()
}
SettingsPageItem::SubPageLink(sub_page_link) => h_flex()
- .id(sub_page_link.title)
+ .id(sub_page_link.title.clone())
.w_full()
.min_w_0()
.gap_2()
@@ -623,24 +623,27 @@ impl SettingsPageItem {
v_flex()
.w_full()
.max_w_1_2()
- .child(Label::new(SharedString::new_static(sub_page_link.title))),
+ .child(Label::new(sub_page_link.title.clone())),
)
.child(
- Button::new(("sub-page".into(), sub_page_link.title), "Configure")
- .icon(IconName::ChevronRight)
- .tab_index(0_isize)
- .icon_position(IconPosition::End)
- .icon_color(Color::Muted)
- .icon_size(IconSize::Small)
- .style(ButtonStyle::Outlined)
- .size(ButtonSize::Medium),
+ Button::new(
+ ("sub-page".into(), sub_page_link.title.clone()),
+ "Configure",
+ )
+ .icon(IconName::ChevronRight)
+ .tab_index(0_isize)
+ .icon_position(IconPosition::End)
+ .icon_color(Color::Muted)
+ .icon_size(IconSize::Small)
+ .style(ButtonStyle::Outlined)
+ .size(ButtonSize::Medium)
+ .on_click({
+ let sub_page_link = sub_page_link.clone();
+ cx.listener(move |this, _, _, cx| {
+ this.push_sub_page(sub_page_link.clone(), section_header, cx)
+ })
+ }),
)
- .on_click({
- let sub_page_link = sub_page_link.clone();
- cx.listener(move |this, _, _, cx| {
- this.push_sub_page(sub_page_link.clone(), section_header, cx)
- })
- })
.into_any_element(),
}
}
@@ -765,7 +768,7 @@ impl PartialEq for SettingItem {
#[derive(Clone)]
struct SubPageLink {
- title: &'static str,
+ title: SharedString,
files: FileMask,
render: Arc<
dyn Fn(&mut SettingsWindow, &mut Window, &mut Context<SettingsWindow>) -> AnyElement
@@ -781,6 +784,20 @@ impl PartialEq for SubPageLink {
}
}
+fn all_language_names(cx: &App) -> Vec<SharedString> {
+ workspace::AppState::global(cx)
+ .upgrade()
+ .map_or(vec![], |state| {
+ state
+ .languages
+ .language_names()
+ .into_iter()
+ .filter(|name| name.as_ref() != "Zed Keybind Context")
+ .map(Into::into)
+ .collect()
+ })
+}
+
#[allow(unused)]
#[derive(Clone, PartialEq)]
enum SettingsUiFile {
@@ -1049,15 +1066,9 @@ impl SettingsWindow {
header_index = index;
any_found_since_last_header = false;
}
- SettingsPageItem::SettingItem(setting_item) => {
- if !setting_item.files.contains(current_file) {
- page_filter[index] = false;
- } else {
- any_found_since_last_header = true;
- }
- }
- SettingsPageItem::SubPageLink(sub_page_link) => {
- if !sub_page_link.files.contains(current_file) {
+ SettingsPageItem::SettingItem(SettingItem { files, .. })
+ | SettingsPageItem::SubPageLink(SubPageLink { files, .. }) => {
+ if !files.contains(current_file) {
page_filter[index] = false;
} else {
any_found_since_last_header = true;
@@ -1246,12 +1257,13 @@ impl SettingsWindow {
SettingsPageItem::SubPageLink(sub_page_link) => {
documents.push(bm25::Document {
id: key_index,
- contents: [page.title, header_str, sub_page_link.title].join("\n"),
+ contents: [page.title, header_str, sub_page_link.title.as_ref()]
+ .join("\n"),
});
push_candidates(
&mut fuzzy_match_candidates,
key_index,
- sub_page_link.title,
+ sub_page_link.title.as_ref(),
);
}
}
@@ -1288,7 +1300,7 @@ impl SettingsWindow {
fn build_ui(&mut self, window: &mut Window, cx: &mut Context<SettingsWindow>) {
if self.pages.is_empty() {
- self.pages = page_data::settings_data();
+ self.pages = page_data::settings_data(cx);
self.build_navbar(cx);
self.setup_navbar_focus_subscriptions(window, cx);
self.build_content_handles(window, cx);
@@ -1809,11 +1821,11 @@ impl SettingsWindow {
fn render_sub_page_breadcrumbs(&self) -> impl IntoElement {
let mut items = vec![];
- items.push(self.current_page().title);
+ items.push(self.current_page().title.into());
items.extend(
sub_page_stack()
.iter()
- .flat_map(|page| [page.section_header, page.link.title]),
+ .flat_map(|page| [page.section_header.into(), page.link.title.clone()]),
);
let last = items.pop().unwrap();
@@ -1822,7 +1834,7 @@ impl SettingsWindow {
.children(
items
.into_iter()
- .flat_map(|item| [item, "/"])
+ .flat_map(|item| [item, "/".into()])
.map(|item| Label::new(item).color(Color::Muted)),
)
.child(Label::new(last))