runtime object indexing

This commit is contained in:
Carlos Zamora 2025-11-03 16:27:12 -08:00
parent 2a41f8a57c
commit 532343f1ce
9 changed files with 118 additions and 129 deletions

View File

@ -30,7 +30,6 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
const auto args = e.Parameter().as<Editor::NavigateToActionsArgs>();
_ViewModel = args.ViewModel();
// TODO CARLOS: runtime indexing and retrieval support
BringIntoViewWhenLoaded(args.ElementToFocus());
// Subscribe to the view model's FocusContainer event.

View File

@ -39,7 +39,6 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
_ViewModel = args.ViewModel();
_ViewModel.CurrentPage(ColorSchemesSubPage::Base);
// TODO CARLOS: runtime indexing and retrieval support
BringIntoViewWhenLoaded(args.ElementToFocus());
_layoutUpdatedRevoker = LayoutUpdated(winrt::auto_revoke, [this](auto /*s*/, auto /*e*/) {

View File

@ -41,7 +41,6 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
vmImpl->LazyLoadExtensions();
vmImpl->MarkAsVisited();
// TODO CARLOS: runtime indexing and retrieval support
BringIntoViewWhenLoaded(args.ElementToFocus());
if (vmImpl->IsExtensionView())

View File

@ -1081,7 +1081,47 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
// must be IInspectable to be used as ItemsSource
std::vector<IInspectable> results;
if (_filteredSearchIndex->empty())
// Package filtered search index objects into WinRT FilteredSearchResults for UI
for (const auto* indexEntry : _filteredSearchIndex->mainIndex)
{
results.push_back(winrt::make<FilteredSearchResult>(indexEntry));
}
#define APPEND_RUNTIME_OBJECT_RESULTS(runtimeObjectList, nameAccessor, filteredSearchIndex, partialSearchIndexEntry, navigationArgTransform) \
for (const auto& runtimeObj : runtimeObjectList) \
{ \
const auto& objName = nameAccessor; \
const bool nameMatches = til::contains_linguistic_insensitive(objName, sanitizedQuery); \
\
if (nameMatches) \
{ \
results.push_back(winrt::make<FilteredSearchResult>(&partialSearchIndexEntry, runtimeObj, std::optional<hstring>{ objName })); \
} \
\
for (const auto* indexEntry : filteredSearchIndex) \
{ \
results.push_back(winrt::make<FilteredSearchResult>(indexEntry, navigationArgTransform)); \
} \
}
// Profiles
APPEND_RUNTIME_OBJECT_RESULTS(_profileVMs, runtimeObj.Name(), _filteredSearchIndex->profileIndex, _searchIndex->profileIndexEntry, runtimeObj)
// New Tab Menu (Folder View)
APPEND_RUNTIME_OBJECT_RESULTS(get_self<implementation::NewTabMenuViewModel>(_newTabMenuPageVM)->FolderTreeFlatList(), runtimeObj.Name(), _filteredSearchIndex->ntmFolderIndex, _searchIndex->ntmFolderIndexEntry, runtimeObj)
// Color schemes
APPEND_RUNTIME_OBJECT_RESULTS(_colorSchemesPageVM.AllColorSchemes(), runtimeObj.Name(), _filteredSearchIndex->colorSchemeIndex, _searchIndex->colorSchemeIndexEntry, winrt::box_value(runtimeObj.Name()))
for (const auto& extension : _extensionsVM.ExtensionPackages())
{
if (til::contains_linguistic_insensitive(extension.Package().DisplayName(), sanitizedQuery))
{
results.push_back(winrt::make<FilteredSearchResult>(&_searchIndex->extensionIndexEntry, extension, std::optional<hstring>{ extension.Package().DisplayName() }));
}
}
if (results.empty())
{
// Explicitly show "no results"
@ -1091,94 +1131,6 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
results.reserve(1);
results.push_back(winrt::make<FilteredSearchResult>(noResultsText));
}
else
{
// Package filtered search index objects into WinRT FilteredSearchResults for UI
for (const auto* indexEntry : *_filteredSearchIndex)
{
results.push_back(winrt::make<FilteredSearchResult>(indexEntry));
}
// TODO CARLOS: use the macro below for runtime objects once everything is verified to be working right
#define APPEND_RUNTIME_OBJECT_RESULTS(runtimeObjectList, runtimeObjectIdentifier, filteredSearchIndex, navigationArgOverride) \
for (const auto& runtimeObj : runtimeObjectList) \
{ \
if (til::contains_linguistic_insensitive(runtimeObjectIdentifier, sanitizedQuery)) \
{ \
/*results.push_back(winrt::make<FilteredSearchResult>(<NEED ANOTHER PARAM>, runtimeObj, runtimeObjectIdentifier));*/ \
} \
\
for (const auto* indexEntry : filteredSearchIndex) \
{ \
results.push_back(winrt::make<FilteredSearchResult>(indexEntry, navigationArgOverride)); \
} \
}
// Profiles
//APPEND_RUNTIME_OBJECT_RESULTS(_profileVMs, runtimeObj.Name(), _filteredSearchProfileIndex, runtimeObj)
for (const auto& profile : _profileVMs)
{
// TODO CARLOS: replace with fuzzy search
if (til::contains_linguistic_insensitive(profile.Name(), sanitizedQuery))
{
// TODO CARLOS: if name matches, link the top-level page
// can't do that rn because I need a LocalizedIndexEntry stored somewhere for that
// SPECIFICALLY, I NEED TO CONVERT PartialProfileIndexEntry into a LocalizedIndexEntry (which is dumb, because there's nothing to localize)
//results.push_back(winrt::make<FilteredSearchResult>(&PartialProfileIndexEntry(), profile));//, std::optional<hstring>{ profile.Name() }));
}
for (const auto* indexEntry : _filteredSearchProfileIndex)
{
results.push_back(winrt::make<FilteredSearchResult>(indexEntry, profile));
}
}
// New Tab Menu (Folder View)
//APPEND_RUNTIME_OBJECT_RESULTS(get_self<implementation::NewTabMenuViewModel>(_newTabMenuPageVM)->FolderTreeFlatList(), runtimeObj.Name(), _filteredSearchNTMFolderIndex, runtimeObj)
for (const auto& ntmFolder : get_self<implementation::NewTabMenuViewModel>(_newTabMenuPageVM)->FolderTreeFlatList())
{
if (til::contains_linguistic_insensitive(ntmFolder.Name(), sanitizedQuery))
{
// TODO CARLOS: if name matches, link the top-level page
// can't do that rn because I need a LocalizedIndexEntry stored somewhere for that
//results.push_back(winrt::make<FilteredSearchResult>(, ntmFolder));
}
for (const auto* indexEntry : _filteredSearchNTMFolderIndex)
{
results.push_back(winrt::make<FilteredSearchResult>(indexEntry, ntmFolder));
}
}
// Color schemes
//APPEND_RUNTIME_OBJECT_RESULTS(_colorSchemesPageVM.AllColorSchemes(), runtimeObj.Name(), _filteredSearchColorSchemeIndex, winrt::box_value(runtimeObj.Name()))
for (const auto& scheme : _colorSchemesPageVM.AllColorSchemes())
{
if (til::contains_linguistic_insensitive(scheme.Name(), sanitizedQuery))
{
// TODO CARLOS: if name matches, link the top-level page
// can't do that rn because I need a LocalizedIndexEntry stored somewhere for that
//results.push_back(winrt::make<FilteredSearchResult>(, scheme));
}
for (const auto* indexEntry : _filteredSearchColorSchemeIndex)
{
results.push_back(winrt::make<FilteredSearchResult>(indexEntry, winrt::box_value(scheme.Name())));
}
}
// TODO CARLOS:
// - if match with extension name, go to extension page
for (const auto& extension : _extensionsVM.ExtensionPackages())
{
if (til::contains_linguistic_insensitive(extension.Package().DisplayName(), sanitizedQuery))
{
// TODO CARLOS: if name matches, link the top-level page
// can't do that rn because I need a LocalizedIndexEntry stored somewhere for that
//results.push_back(winrt::make<FilteredSearchResult>(, ntmFolder));
}
}
}
#undef APPEND_RUNTIME_OBJECT_RESULTS
// Update the UI with the results
@ -1190,7 +1142,9 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
// Update _filteredSearchIndex with results matching queryText
til::generation_t MainPage::_QuerySearchIndex(const hstring& queryText)
{
auto filteredResults{ _filteredSearchIndex.write() };
auto filteredSearchIndex{ _filteredSearchIndex.write() };
const auto generation = _filteredSearchIndex.generation();
wil::hide_name _filteredSearchIndex;
auto findMatchingResults = [&queryText](const std::vector<LocalizedIndexEntry>& searchIndex, std::vector<const LocalizedIndexEntry*>& filteredIndex) {
filteredIndex.clear();
@ -1210,18 +1164,18 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
};
// build-time search index can be filtered and returned pretty much as-is
findMatchingResults(_searchIndex, *filteredResults);
findMatchingResults(_searchIndex->mainIndex, filteredSearchIndex->mainIndex);
// Profiles
findMatchingResults(_searchProfileIndex, _filteredSearchProfileIndex);
findMatchingResults(_searchIndex->profileIndex, filteredSearchIndex->profileIndex);
// New Tab Menu (Folder View)
findMatchingResults(_searchNTMFolderIndex, _filteredSearchNTMFolderIndex);
findMatchingResults(_searchIndex->ntmFolderIndex, filteredSearchIndex->ntmFolderIndex);
// Color schemes
findMatchingResults(_searchColorSchemeIndex, _filteredSearchColorSchemeIndex);
findMatchingResults(_searchIndex->colorSchemeIndex, filteredSearchIndex->colorSchemeIndex);
return _filteredSearchIndex.generation();
return generation;
}
void MainPage::SettingsSearchBox_QuerySubmitted(const AutoSuggestBox& /*sender*/, const AutoSuggestBoxQuerySubmittedEventArgs& args)
@ -1272,10 +1226,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
// These are the new index entries we are building.
// Don't actually modify the members until we're completely done here.
std::vector<LocalizedIndexEntry> localizedIndex;
std::vector<LocalizedIndexEntry> localizedProfileIndex;
std::vector<LocalizedIndexEntry> localizedNTMFolderIndex;
std::vector<LocalizedIndexEntry> localizedColorSchemeIndex;
SearchIndex searchIndex;
// TODO CARLOS: actually use this
// copied from CommandPaletteItems.h
@ -1297,58 +1248,60 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
}();
const auto& buildIndex = LoadBuildTimeIndex();
localizedIndex.reserve(buildIndex.size());
searchIndex.mainIndex.reserve(buildIndex.size());
for (const auto& entry : buildIndex)
{
// TODO CARLOS: properly populate LocalizedIndexEntry
LocalizedIndexEntry localizedEntry;
localizedEntry.Entry = &entry;
localizedIndex.push_back(localizedEntry);
searchIndex.mainIndex.push_back(localizedEntry);
}
// Load profiles
const auto& profileIndex = LoadProfileIndex();
localizedProfileIndex.reserve(profileIndex.size());
searchIndex.profileIndex.reserve(profileIndex.size());
for (const auto& entry : profileIndex)
{
// TODO CARLOS: properly populate LocalizedIndexEntry
LocalizedIndexEntry localizedEntry;
localizedEntry.Entry = &entry;
localizedProfileIndex.push_back(localizedEntry);
searchIndex.profileIndex.push_back(localizedEntry);
}
searchIndex.profileIndexEntry.Entry = &PartialProfileIndexEntry();
// Load new tab menu
const auto& ntmFolderIndex = LoadNTMFolderIndex();
localizedNTMFolderIndex.reserve(ntmFolderIndex.size());
searchIndex.ntmFolderIndex.reserve(ntmFolderIndex.size());
for (const auto& entry : ntmFolderIndex)
{
// TODO CARLOS: properly populate LocalizedIndexEntry
LocalizedIndexEntry localizedEntry;
localizedEntry.Entry = &entry;
localizedNTMFolderIndex.push_back(localizedEntry);
searchIndex.ntmFolderIndex.push_back(localizedEntry);
}
searchIndex.ntmFolderIndexEntry.Entry = &PartialNTMFolderIndexEntry();
// Nothing to load for extensions.
// At query time, we'll search for matching extension names.
// Load extensions
// Nothing to load at build time.
// At query time, we'll search for matching extension names and use this entry below
searchIndex.extensionIndexEntry.Entry = &PartialExtensionIndexEntry();
// Load color schemes
const auto& colorSchemesIndex = LoadColorSchemeIndex();
localizedColorSchemeIndex.reserve(colorSchemesIndex.size());
searchIndex.colorSchemeIndex.reserve(colorSchemesIndex.size());
for (const auto& entry : colorSchemesIndex)
{
// TODO CARLOS: properly populate LocalizedIndexEntry
LocalizedIndexEntry localizedEntry;
localizedEntry.Entry = &entry;
localizedColorSchemeIndex.push_back(localizedEntry);
searchIndex.colorSchemeIndex.push_back(localizedEntry);
}
searchIndex.colorSchemeIndexEntry.Entry = &PartialColorSchemeIndexEntry();
// Load actions
// TODO CARLOS: postpone until actions page is updated
_searchIndex = std::move(localizedIndex);
_searchProfileIndex = std::move(localizedProfileIndex);
_searchNTMFolderIndex = std::move(localizedNTMFolderIndex);
_searchColorSchemeIndex = std::move(localizedColorSchemeIndex);
*_searchIndex.write() = std::move(searchIndex);
}
const ScopedResourceLoader& EnglishOnlyResourceLoader() noexcept

View File

@ -71,7 +71,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
bool IsNoResultsPlaceholder() const
{
return _overrideLabel.has_value();
return _overrideLabel.has_value() && !_NavigationArgOverride;
}
const LocalizedIndexEntry& SearchIndexEntry() const noexcept
@ -94,7 +94,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
private:
const std::optional<winrt::hstring> _overrideLabel{ std::nullopt };
const Windows::Foundation::IInspectable& _NavigationArgOverride{ nullptr };
const Windows::Foundation::IInspectable _NavigationArgOverride{ nullptr };
const LocalizedIndexEntry* _SearchIndexEntry{ nullptr };
};
@ -164,14 +164,31 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
winrt::Microsoft::Terminal::Settings::Editor::NewTabMenuViewModel _newTabMenuPageVM{ nullptr };
winrt::Microsoft::Terminal::Settings::Editor::ExtensionsViewModel _extensionsVM{ nullptr };
std::vector<LocalizedIndexEntry> _searchIndex;
std::vector<LocalizedIndexEntry> _searchProfileIndex;
std::vector<LocalizedIndexEntry> _searchNTMFolderIndex;
std::vector<LocalizedIndexEntry> _searchColorSchemeIndex;
til::generational<std::vector<const LocalizedIndexEntry*>> _filteredSearchIndex;
std::vector<const LocalizedIndexEntry*> _filteredSearchProfileIndex;
std::vector<const LocalizedIndexEntry*> _filteredSearchNTMFolderIndex;
std::vector<const LocalizedIndexEntry*> _filteredSearchColorSchemeIndex;
struct SearchIndex
{
SearchIndex& operator=(const SearchIndex& other) = default;
std::vector<LocalizedIndexEntry> mainIndex;
std::vector<LocalizedIndexEntry> profileIndex;
std::vector<LocalizedIndexEntry> ntmFolderIndex;
std::vector<LocalizedIndexEntry> colorSchemeIndex;
// Links to main page; used when searching runtime objects (i.e. profile/extension name --> Profile_Base/Extension View)
LocalizedIndexEntry profileIndexEntry;
LocalizedIndexEntry ntmFolderIndexEntry;
LocalizedIndexEntry colorSchemeIndexEntry;
LocalizedIndexEntry extensionIndexEntry;
};
til::generational<SearchIndex> _searchIndex;
struct FilteredSearchIndex
{
std::vector<const LocalizedIndexEntry*> mainIndex;
std::vector<const LocalizedIndexEntry*> profileIndex;
std::vector<const LocalizedIndexEntry*> ntmFolderIndex;
std::vector<const LocalizedIndexEntry*> colorSchemeIndex;
};
til::generational<FilteredSearchIndex> _filteredSearchIndex;
Windows::UI::Xaml::Data::INotifyPropertyChanged::PropertyChanged_revoker _profileViewModelChangedRevoker;
Windows::UI::Xaml::Data::INotifyPropertyChanged::PropertyChanged_revoker _colorSchemesPageViewModelChangedRevoker;

View File

@ -46,7 +46,6 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
const auto args = e.Parameter().as<Editor::NavigateToNewTabMenuArgs>();
_ViewModel = args.ViewModel();
// TODO CARLOS: runtime indexing and retrieval support
BringIntoViewWhenLoaded(args.ElementToFocus());
TraceLoggingWrite(

View File

@ -2472,7 +2472,7 @@
<comment>Placeholder text for the main search box in the settings editor.</comment>
</data>
<data name="Search_NoResults" xml:space="preserve">
<value>No results for {}</value>
<comment>{Locked="{}"} Displayed when no results were found for a given query. "{}" will be replaced with the query.</comment>
<value>No results for "{}"</value>
<comment>{Locked=""{}""} Displayed when no results were found for a given query. "{}" will be replaced with the query.</comment>
</data>
</root>

View File

@ -3,6 +3,8 @@
#pragma once
#include "SettingContainer.h"
// This macro must be used alongside GETSET_BINDABLE_ENUM_SETTING.
// Use this in your class's constructor after Initialize_Component().
// It sorts and initializes the observable list of enum entries with the enum name

View File

@ -428,6 +428,9 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
const std::array<IndexEntry, $($schemeEntries.Count)>& LoadColorSchemeIndex();
const IndexEntry& PartialProfileIndexEntry();
const IndexEntry& PartialNTMFolderIndexEntry();
const IndexEntry& PartialColorSchemeIndexEntry();
const IndexEntry& PartialExtensionIndexEntry();
}
"@
@ -483,6 +486,24 @@ $( ($schemeEntries -join "`r`n") )
static IndexEntry entry{ L"", std::nullopt, winrt::xaml_typename<Microsoft::Terminal::Settings::Editor::Profiles_Base>(), nullptr, BreadcrumbSubPage::None, L"" };
return entry;
}
const IndexEntry& PartialNTMFolderIndexEntry()
{
static IndexEntry entry{ L"", std::nullopt, winrt::xaml_typename<Microsoft::Terminal::Settings::Editor::NewTabMenu>(), nullptr, BreadcrumbSubPage::NewTabMenu_Folder, L"" };
return entry;
}
const IndexEntry& PartialColorSchemeIndexEntry()
{
static IndexEntry entry{ L"", std::nullopt, winrt::xaml_typename<Microsoft::Terminal::Settings::Editor::EditColorScheme>(), nullptr, BreadcrumbSubPage::ColorSchemes_Edit, L"" };
return entry;
}
const IndexEntry& PartialExtensionIndexEntry()
{
static IndexEntry entry{ L"", std::nullopt, winrt::xaml_typename<Microsoft::Terminal::Settings::Editor::Extensions>(), nullptr, BreadcrumbSubPage::Extensions_Extension, L"" };
return entry;
}
}
"@