## Summary of the Pull Request Adds search functionality to the settings UI. This is added to an `AutoSuggestBox` in the main `NavigationView`. Invoking a result navigates to the proper location in the settings UI and focuses the setting, when possible. ## References and Relevant Issues Based on https://github.com/microsoft/PowerToys/pull/41285 ## Detailed Description of the Pull Request / Additional comments - tools/GenerateSettingsIndex.ps1: parses all the XAML files in the settings UI for SettingsContainers and builds a search index from them - XAML changes: ensures all SettingContainer objects have an `x:Name` so that we can navigate to them and bring them into view. - TerminalSettingsEditor/Utils.h: implements `BringIntoViewWhenLoaded()` which navigates to the relevant part of the UI. This is called in `OnNavigatedTo()` for each page. - fzf was moved out of TerminalApp so that TerminalSettingsEditor can access it - There's a few main components to searching, all of it is in `MainPage`: - `MainPage::_UpdateSearchIndex()`|`SearchIndex::Reset()`: loads the search index generated by `GenerateSettingsIndex.ps1`; provides additional localization, if needed - `MainPage::SettingsSearchBox_TextChanged`: - detect that text changed in the search box - perform the actual search in `SearchIndex::SearchAsync()`. This is a HEFTY async function that can be cancelled. It needs a lot of context passed in to expand the search index appropriately (i.e. build awareness of "PowerShell" profile and generate results appropriately). This is also where fzf is used to perform weighted matching. - the weighted matching itself is pretty complicated, but all the associated bonus weights are at the top of SearchIndex.cpp. - `SettingsSearchBox_QuerySubmitted`: extract the search index metadata and call the correct `_Navigate()` function ## Validation Steps Performed Search for... - settings that don't change at runtime: - [x] global settings - [x] settings in profile.defaults - [x] "add new profile" page - settings that may change at runtime: - [x] settings in a profile - [x] individual color schemes - [x] actions (main actions page + edit action subpage) - [x] new tab menu folders - [x] extensions - misc. corner cases: - [x] terminal chat (blocked in indexing script; requires minor changes in feature branch) - [x] settings in appearance objects To test fzf matching and weighted results, I specifically tested these scenarios: - "PowerShell" --> prioritize the PowerShell profile page(s) - "font size" --> prioritize profile defaults entry - "font size powershell" --> prioritize PowerShell > font size ## PR Checklist Closes #12949 ## Follow-ups - search by JSON key: need a way to add JSON keys to index entries. `GetSearchableFields()` should make the rest pretty easy. - search by keywords: need to define keywords. `GetSearchableFields()` should make the rest pretty easy.
OpenConsole Tools
These are a collection of tools and scripts to make your life building the OpenConsole project easier. Many of them are designed to be functional clones of tools that we used to use when developing inside the Windows build system.
Razzle
This is a script that quickly sets up your environment variables so that these tools can run easily. It's named after another script used by Windows developers to similar effect.
- It adds msbuild to your path.
- It adds the tools directory to your path as well, so all these scripts are easily available.
- It executes
\tools\.razzlerc.cmdto add any other personal configuration to your environment as well, or creates one if it doesn't exist. - It sets up the default build configuration to be 'Debug'. If you'd like to
manually specify a build configuration, pass the parameter
dbgfor Debug, andrelfor Release.
bcz
bcz can quick be used to clean and build the project. By default, it builds
the %DEFAULT_CONFIGURATION% configuration, which is Debug if you use razzle.cmd.
bcz dbgcan be used to manually build the Debug configuration.bcz relcan be used to manually build the Release configuration.
opencon (and openbash, openps)
opencon can be used to launch the last built OpenConsole binary. If given an
argument, it will try and run that program in the launched window. Otherwise, it
will default to cmd.exe.
openbash is similar, it immediately launches bash.exe (the Windows Subsystem
for Linux entrypoint) in your ~ directory.
Likewise, openps launches powershell.
runformat & runxamlformat
runxamlformat will format .xaml files to match our coding style. runformat
will format the c++ code (and will also call runxamlformat). runformat
should be called before making a new PR, to ensure that code is formatted
correctly. If it isn't, the CI will prevent your PR from merging.
The C++ code is formatted with clang-format. Many editors have built-in
support for automatically running clang-format on save.
Our XAML code is formatted with
XamlStyler. I don't have a good way of
running this on save, but you can add a git hook to format before committing
.xaml files. To do so, add the following to your .git/hooks/pre-commit file:
# XAML Styler - xstyler.exe pre-commit Git Hook
# Documentation: https://github.com/Xavalon/XamlStyler/wiki
# Originally from https://github.com/Xavalon/XamlStyler/wiki/Git-Hook
# Define path to xstyler.exe
XSTYLER_PATH="dotnet tool run xstyler --"
# Define path to XAML Styler configuration
XSTYLER_CONFIG="XamlStyler.json"
echo "Running XAML Styler on committed XAML files"
git diff --cached --name-only --diff-filter=ACM | grep -e '\.xaml$' | \
# Wrap in brackets to preserve variable through loop
{
files=""
# Build list of files to pass to xstyler.exe
while read FILE; do
if [ "$files" == "" ]; then
files="$FILE";
else
files="$files,$FILE";
fi
done
if [ "$files" != "" ]; then
# Check if external configuration is specified
[ -z "$XSTYLER_CONFIG" ] && configParam="" || configParam="-c $XSTYLER_CONFIG"
# Format XAML files
$XSTYLER_PATH -f "$files" $configParam
for i in $(echo $files | sed "s/,/ /g")
do
#strip BOM
sed -i '1s/^\xEF\xBB\xBF//' $i
unix2dos $i
# stage updated file
git add -u $i
done
else
echo "No XAML files detected in commit"
fi
exit 0
}
testcon, runut, runft
runut will automatically run all of the unit tests through TAEF. runft will
run the feature tests, and testcon runs all of them. They'll pass any
arguments through to TAEF, so you can more finely control the testing.
A recommended workflow is the following command:
bcz dbg && runut /name:*<name of test>*
Where <name of test> is the name of the test testing the relevant feature area
you're working on. For example, if I was working on the VT Mouse input support,
I would use MouseInputTest as that string, to isolate the mouse input tests.
If you'd like to run all the tests, just ignore the /name param:
bcz dbg && runut
To make sure your code is ready for a pull request, run the build, then launch the built console, then run the tests in it. The built console will inherit all of the razzle environment, so you can immediately start using the macros:
bczopencontestcon(in the new console window)runformat
If they all come out green, then you're ready for a pull request!