settings_ui: Dynamic languages list (#40123)
Closes #ISSUE Release Notes: - N/A *or* Added/Fixed/Improved ...
This commit is contained in:
@@ -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))
|
||||
|
||||
Reference in New Issue
Block a user