diff --git a/crates/settings_ui/src/page_data.rs b/crates/settings_ui/src/page_data.rs index 394e6821c85f68e08450ba18fe2e44959e0cf865..ad7c854bf204ca50b7cf83a2205cf424f5d1bf08 100644 --- a/crates/settings_ui/src/page_data.rs +++ b/crates/settings_ui/src/page_data.rs @@ -4500,7 +4500,7 @@ pub(crate) fn settings_data(cx: &App) -> Vec { title: "Program", description: "The shell program to use.", field: Box::new(SettingField { - json_path: Some("terminal.shell.program"), + json_path: Some("terminal.shell"), pick: |settings_content| { match settings_content.terminal.as_ref()?.project.shell.as_ref() { Some(settings::Shell::Program(program)) => Some(program), diff --git a/crates/settings_ui/src/settings_ui.rs b/crates/settings_ui/src/settings_ui.rs index c43b8095a435eb40c25694deda2cf247d7992ca5..9e7717926f14b81b509b23d92fa9e944afd56f61 100644 --- a/crates/settings_ui/src/settings_ui.rs +++ b/crates/settings_ui/src/settings_ui.rs @@ -6,10 +6,10 @@ use editor::{Editor, EditorEvent}; use feature_flags::FeatureFlag; use fuzzy::StringMatchCandidate; use gpui::{ - Action, App, DEFAULT_ADDITIONAL_WINDOW_SIZE, Div, Entity, FocusHandle, Focusable, Global, - ListState, ReadGlobal as _, ScrollHandle, Stateful, Subscription, Task, TitlebarOptions, - UniformListScrollHandle, Window, WindowBounds, WindowHandle, WindowOptions, actions, div, list, - point, prelude::*, px, uniform_list, + Action, AnimationExt, App, DEFAULT_ADDITIONAL_WINDOW_SIZE, Div, Entity, FocusHandle, Focusable, + Global, ListState, ReadGlobal as _, ScrollHandle, Stateful, Subscription, Task, + TitlebarOptions, UniformListScrollHandle, Window, WindowBounds, WindowHandle, WindowOptions, + actions, div, list, point, prelude::*, px, uniform_list, }; use heck::ToTitleCase as _; use project::{Project, WorktreeId}; @@ -512,43 +512,10 @@ pub fn open_settings_editor( return; } - settings_window.current_file = SettingsUiFile::User; - settings_window.build_ui(window, cx); - - let mut item_info = None; - 'search: for (nav_entry_index, entry) in settings_window.navbar_entries.iter().enumerate() { - if entry.is_root { - continue; - } - let page_index = entry.page_index; - let header_index = entry - .item_index - .expect("non-root entries should have an item index"); - for item_index in header_index + 1..settings_window.pages[page_index].items.len() { - let item = &settings_window.pages[page_index].items[item_index]; - if let SettingsPageItem::SectionHeader(_) = item { - break; - } - if let SettingsPageItem::SettingItem(item) = item { - if item.field.json_path() == Some(path) { - if !item.files.contains(USER) { - log::error!("Found item {}, but it is not a user setting", path); - return; - } - item_info = Some((item_index, nav_entry_index)); - break 'search; - } - } - } - } - let Some((item_index, navbar_entry_index)) = item_info else { - log::error!("Failed to find item for {}", path); - return; - }; - - settings_window.open_navbar_entry_page(navbar_entry_index); - window.focus(&settings_window.focus_handle_for_content_element(item_index, cx)); - settings_window.scroll_to_content_item(item_index, window, cx); + settings_window.search_bar.update(cx, |editor, cx| { + editor.set_text(format!("#{path}"), window, cx); + }); + settings_window.update_matches(cx); } let existing_window = cx @@ -673,13 +640,14 @@ pub struct SettingsWindow { struct SearchIndex { bm25_engine: bm25::SearchEngine, fuzzy_match_candidates: Vec, - key_lut: Vec, + key_lut: Vec, } -struct SearchItemKey { +struct SearchKeyLUTEntry { page_index: usize, header_index: usize, item_index: usize, + json_path: Option<&'static str>, } struct SubPage { @@ -1462,7 +1430,7 @@ impl SettingsWindow { fn update_matches(&mut self, cx: &mut Context) { self.search_task.take(); - let query = self.search_bar.read(cx).text(cx); + let mut query = self.search_bar.read(cx).text(cx); if query.is_empty() || self.search_index.is_none() { for page in &mut self.filter_table { page.fill(true); @@ -1474,6 +1442,14 @@ impl SettingsWindow { return; } + let is_json_link_query; + if query.starts_with("#") { + query.remove(0); + is_json_link_query = true; + } else { + is_json_link_query = false; + } + let search_index = self.search_index.as_ref().unwrap().clone(); fn update_matches_inner( @@ -1487,10 +1463,11 @@ impl SettingsWindow { } for match_index in match_indices { - let SearchItemKey { + let SearchKeyLUTEntry { page_index, header_index, item_index, + .. } = search_index.key_lut[match_index]; let page = &mut this.filter_table[page_index]; page[header_index] = true; @@ -1504,6 +1481,29 @@ impl SettingsWindow { } self.search_task = Some(cx.spawn(async move |this, cx| { + if is_json_link_query { + let mut indices = vec![]; + for (index, SearchKeyLUTEntry { json_path, .. }) in + search_index.key_lut.iter().enumerate() + { + let Some(json_path) = json_path else { + continue; + }; + + if let Some(post) = query.strip_prefix(json_path) + && (post.is_empty() || post.starts_with('.')) + { + indices.push(index); + } + } + if !indices.is_empty() { + this.update(cx, |this, cx| { + update_matches_inner(this, search_index.as_ref(), indices.into_iter(), cx); + }) + .ok(); + return; + } + } let bm25_task = cx.background_spawn({ let search_index = search_index.clone(); let max_results = search_index.key_lut.len(); @@ -1591,7 +1591,7 @@ impl SettingsWindow { } fn build_search_index(&mut self) { - let mut key_lut: Vec = vec![]; + let mut key_lut: Vec = vec![]; let mut documents = Vec::default(); let mut fuzzy_match_candidates = Vec::default(); @@ -1613,11 +1613,16 @@ impl SettingsWindow { let mut header_str = ""; for (item_index, item) in page.items.iter().enumerate() { let key_index = key_lut.len(); + let mut json_path = None; match item { SettingsPageItem::DynamicItem(DynamicItem { discriminant: item, .. }) | SettingsPageItem::SettingItem(item) => { + json_path = item + .field + .json_path() + .map(|path| path.trim_end_matches('$')); documents.push(bm25::Document { id: key_index, contents: [page.title, header_str, item.title, item.description] @@ -1651,10 +1656,11 @@ impl SettingsWindow { push_candidates(&mut fuzzy_match_candidates, key_index, page.title); push_candidates(&mut fuzzy_match_candidates, key_index, header_str); - key_lut.push(SearchItemKey { + key_lut.push(SearchKeyLUTEntry { page_index, header_index, item_index, + json_path, }); } }