Filter Command Palette in English in addition to local language (#19166)

The bulk of this work is changing `Command::Name` (and its descendants
like `GenerateName`) to support looking up names in English and in the
local language.

When matching a "palette item" with a "subtitle" (a new field introduced
to store the English command name when the current language is not
English), the weight of the subtitle is used only if it is greater than
the weight of the name. This ensures that we do not penalize or
over-promote results that contain similar Latin letters in both fields.

Refs #19130, #19131, #19132, #19165
Closes #7039
This commit is contained in:
Dustin L. Howett
2025-07-28 14:08:48 -05:00
committed by GitHub
parent 671440206c
commit 65788d9099
18 changed files with 497 additions and 303 deletions

View File

@@ -21,6 +21,7 @@ namespace TerminalAppLocalTests
_value{ value } {}
winrt::hstring Name() { return _value; }
winrt::hstring Subtitle() { return {}; }
winrt::hstring KeyChordText() { return {}; }
winrt::hstring Icon() { return {}; }

View File

@@ -44,6 +44,12 @@
<Setter Property="BorderBrush" Value="{ThemeResource CardStrokeColorDefaultBrush}" />
</Style>
<Style x:Key="SubtitleTextStyle"
TargetType="TextBlock">
<Setter Property="FontSize" Value="10" />
<Setter Property="Foreground" Value="{ThemeResource SystemBaseMediumColor}" />
</Style>
<DataTemplate x:Key="ListItemTemplate"
x:DataType="local:FilteredCommand">
<ListViewItem HorizontalContentAlignment="Stretch"
@@ -71,11 +77,19 @@
Height="16"
Content="{x:Bind Item.ResolvedIcon, Mode=OneWay}" />
<local:HighlightedTextControl Grid.Column="1"
HorizontalAlignment="Left"
HighlightedRuns="{x:Bind NameHighlights, Mode=OneWay}"
Text="{x:Bind Item.Name, Mode=OneWay}" />
<StackPanel Grid.Column="1"
HorizontalAlignment="Left"
Orientation="Vertical">
<local:HighlightedTextControl HorizontalAlignment="Left"
HighlightedRuns="{x:Bind NameHighlights, Mode=OneWay}"
Text="{x:Bind Item.Name, Mode=OneWay}" />
<local:HighlightedTextControl HorizontalAlignment="Left"
HighlightedRuns="{x:Bind SubtitleHighlights, Mode=OneWay}"
Text="{x:Bind Item.Subtitle, Mode=OneWay}"
TextBlockStyle="{StaticResource SubtitleTextStyle}"
Visibility="{x:Bind HasSubtitle, Mode=OneWay}" />
</StackPanel>
<!--
The block for the key chord is only visible
when there's actual text set as the label.
@@ -122,10 +136,19 @@
Height="16"
Content="{x:Bind Item.ResolvedIcon, Mode=OneWay}" />
<local:HighlightedTextControl Grid.Column="1"
HorizontalAlignment="Left"
HighlightedRuns="{x:Bind NameHighlights, Mode=OneWay}"
Text="{x:Bind Item.Name, Mode=OneWay}" />
<StackPanel Grid.Column="1"
HorizontalAlignment="Left"
Orientation="Vertical">
<local:HighlightedTextControl HorizontalAlignment="Left"
HighlightedRuns="{x:Bind NameHighlights, Mode=OneWay}"
Text="{x:Bind Item.Name, Mode=OneWay}" />
<local:HighlightedTextControl HorizontalAlignment="Left"
HighlightedRuns="{x:Bind SubtitleHighlights, Mode=OneWay}"
Text="{x:Bind Item.Subtitle, Mode=OneWay}"
TextBlockStyle="{StaticResource SubtitleTextStyle}"
Visibility="{x:Bind HasSubtitle, Mode=OneWay}" />
</StackPanel>
<!--
The block for the key chord is only visible

View File

@@ -17,6 +17,31 @@ namespace winrt::TerminalApp::implementation
ActionPaletteItem(const Microsoft::Terminal::Settings::Model::Command& command, const winrt::hstring keyChordText) :
_Command{ command }, _name{ command.Name() }, _keyChordText{ keyChordText }
{
static bool shouldShowSubtitles = [] {
try
{
const auto context{ winrt::Windows::ApplicationModel::Resources::Core::ResourceContext::GetForViewIndependentUse() };
const auto qualifiers{ context.QualifierValues() };
if (const auto language{ qualifiers.TryLookup(L"language") })
{
return !til::starts_with_insensitive_ascii(*language, L"en-");
}
}
catch (...)
{
LOG_CAUGHT_EXCEPTION();
}
return false;
}();
if (shouldShowSubtitles)
{
const auto subtitle = _Command.LanguageNeutralName();
if (subtitle != _name)
{
_subtitle = std::move(subtitle);
}
}
}
winrt::hstring Name()
@@ -24,6 +49,11 @@ namespace winrt::TerminalApp::implementation
return _name;
}
winrt::hstring Subtitle()
{
return _subtitle;
}
winrt::hstring KeyChordText()
{
return _keyChordText;
@@ -39,6 +69,7 @@ namespace winrt::TerminalApp::implementation
private:
Windows::UI::Xaml::Data::INotifyPropertyChanged::PropertyChanged_revoker _commandChangedRevoker;
winrt::hstring _name;
winrt::hstring _subtitle;
winrt::hstring _keyChordText;
};
@@ -54,6 +85,11 @@ namespace winrt::TerminalApp::implementation
return _CommandLine;
}
winrt::hstring Subtitle()
{
return {};
}
winrt::hstring KeyChordText()
{
return {};
@@ -87,6 +123,11 @@ namespace winrt::TerminalApp::implementation
return {};
}
winrt::hstring Subtitle()
{
return {};
}
winrt::hstring KeyChordText()
{
return {};

View File

@@ -26,11 +26,16 @@ namespace winrt::TerminalApp::implementation
{
// Recompute the highlighted name if the item name changes
// Our Item will not change, so we don't need to update the revoker if it does.
_itemChangedRevoker = _Item.as<winrt::Windows::UI::Xaml::Data::INotifyPropertyChanged>().PropertyChanged(winrt::auto_revoke, [weakThis{ get_weak() }](auto& /*sender*/, auto& e) {
auto filteredCommand{ weakThis.get() };
if (filteredCommand && e.PropertyName() == L"Name")
_itemChangedRevoker = _Item.as<winrt::Windows::UI::Xaml::Data::INotifyPropertyChanged>().PropertyChanged(winrt::auto_revoke, [=](auto& /*sender*/, auto& e) {
const auto property{ e.PropertyName() };
if (property == L"Name")
{
filteredCommand->_update();
_update();
}
else if (property == L"Subtitle")
{
_update();
PropertyChanged.raise(*this, winrt::Windows::UI::Xaml::Data::PropertyChangedEventArgs{ L"HasSubtitle" });
}
});
}
@@ -46,6 +51,11 @@ namespace winrt::TerminalApp::implementation
}
}
bool FilteredCommand::HasSubtitle()
{
return !_Item.Subtitle().empty();
}
static std::tuple<std::vector<winrt::TerminalApp::HighlightedRun>, int32_t> _matchedSegmentsAndWeight(const std::shared_ptr<fzf::matcher::Pattern>& pattern, const winrt::hstring& haystack)
{
std::vector<winrt::TerminalApp::HighlightedRun> segments;
@@ -68,7 +78,17 @@ namespace winrt::TerminalApp::implementation
void FilteredCommand::_update()
{
auto [segments, weight] = _matchedSegmentsAndWeight(_pattern, _Item.Name());
auto itemName = _Item.Name();
auto [segments, weight] = _matchedSegmentsAndWeight(_pattern, itemName);
decltype(segments) subtitleSegments;
if (HasSubtitle())
{
auto itemSubtitle = _Item.Subtitle();
int32_t subtitleWeight = 0;
std::tie(subtitleSegments, subtitleWeight) = _matchedSegmentsAndWeight(_pattern, itemSubtitle);
weight = std::max(weight, subtitleWeight);
}
if (segments.empty())
{
@@ -79,6 +99,15 @@ namespace winrt::TerminalApp::implementation
NameHighlights(winrt::single_threaded_vector(std::move(segments)));
}
if (subtitleSegments.empty())
{
SubtitleHighlights(nullptr);
}
else
{
SubtitleHighlights(winrt::single_threaded_vector(std::move(subtitleSegments)));
}
Weight(weight);
}

View File

@@ -24,9 +24,12 @@ namespace winrt::TerminalApp::implementation
static int Compare(const winrt::TerminalApp::FilteredCommand& first, const winrt::TerminalApp::FilteredCommand& second);
bool HasSubtitle();
til::property_changed_event PropertyChanged;
WINRT_OBSERVABLE_PROPERTY(winrt::TerminalApp::IPaletteItem, Item, PropertyChanged.raise, nullptr);
WINRT_OBSERVABLE_PROPERTY(winrt::Windows::Foundation::Collections::IVector<winrt::TerminalApp::HighlightedRun>, NameHighlights, PropertyChanged.raise);
WINRT_OBSERVABLE_PROPERTY(winrt::Windows::Foundation::Collections::IVector<winrt::TerminalApp::HighlightedRun>, SubtitleHighlights, PropertyChanged.raise);
WINRT_OBSERVABLE_PROPERTY(int, Weight, PropertyChanged.raise);
private:

View File

@@ -13,6 +13,8 @@ namespace TerminalApp
IPaletteItem Item { get; };
IVector<HighlightedRun> NameHighlights { get; };
IVector<HighlightedRun> SubtitleHighlights { get; };
Boolean HasSubtitle { get; };
Int32 Weight;
}
}

View File

@@ -16,6 +16,7 @@ namespace TerminalApp
{
PaletteItemType Type { get; };
String Name { get; };
String Subtitle { get; };
String KeyChordText { get; };
String Icon { get; };
Windows.UI.Xaml.Controls.IconElement ResolvedIcon { get; };

View File

@@ -9,6 +9,7 @@
#include <LibraryResources.h>
#include <til/static_map.h>
#include <ScopedResourceLoader.h>
static constexpr std::string_view AdjustFontSizeKey{ "adjustFontSize" };
static constexpr std::string_view CloseOtherPanesKey{ "closeOtherPanes" };
@@ -339,112 +340,112 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
return copy;
}
winrt::hstring ActionAndArgs::GenerateName() const
winrt::hstring ActionAndArgs::GenerateName(const winrt::Windows::ApplicationModel::Resources::Core::ResourceContext& context) const
{
// Sentinel used to indicate this command must ALWAYS be generated by GenerateName
static const winrt::hstring MustGenerate;
static constexpr wil::zwstring_view MustGenerate{};
// Use a magic static to initialize this map, because we won't be able
// to load the resources at _init_, only at runtime.
static const auto GeneratedActionNames = []() {
return std::unordered_map<ShortcutAction, winrt::hstring>{
{ ShortcutAction::AdjustFontSize, RS_(L"AdjustFontSizeCommandKey") },
{ ShortcutAction::CloseOtherPanes, RS_(L"CloseOtherPanesCommandKey") },
return std::unordered_map<ShortcutAction, wil::zwstring_view>{
{ ShortcutAction::AdjustFontSize, USES_RESOURCE(L"AdjustFontSizeCommandKey") },
{ ShortcutAction::CloseOtherPanes, USES_RESOURCE(L"CloseOtherPanesCommandKey") },
{ ShortcutAction::CloseOtherTabs, MustGenerate },
{ ShortcutAction::ClosePane, RS_(L"ClosePaneCommandKey") },
{ ShortcutAction::ClosePane, USES_RESOURCE(L"ClosePaneCommandKey") },
{ ShortcutAction::CloseTab, MustGenerate },
{ ShortcutAction::CloseTabsAfter, MustGenerate },
{ ShortcutAction::CloseWindow, RS_(L"CloseWindowCommandKey") },
{ ShortcutAction::CopyText, RS_(L"CopyTextCommandKey") },
{ ShortcutAction::DuplicateTab, RS_(L"DuplicateTabCommandKey") },
{ ShortcutAction::ExecuteCommandline, RS_(L"ExecuteCommandlineCommandKey") },
{ ShortcutAction::Find, RS_(L"FindCommandKey") },
{ ShortcutAction::CloseWindow, USES_RESOURCE(L"CloseWindowCommandKey") },
{ ShortcutAction::CopyText, USES_RESOURCE(L"CopyTextCommandKey") },
{ ShortcutAction::DuplicateTab, USES_RESOURCE(L"DuplicateTabCommandKey") },
{ ShortcutAction::ExecuteCommandline, USES_RESOURCE(L"ExecuteCommandlineCommandKey") },
{ ShortcutAction::Find, USES_RESOURCE(L"FindCommandKey") },
{ ShortcutAction::Invalid, MustGenerate },
{ ShortcutAction::MoveFocus, RS_(L"MoveFocusCommandKey") },
{ ShortcutAction::MovePane, RS_(L"MovePaneCommandKey") },
{ ShortcutAction::SwapPane, RS_(L"SwapPaneCommandKey") },
{ ShortcutAction::NewTab, RS_(L"NewTabCommandKey") },
{ ShortcutAction::NextTab, RS_(L"NextTabCommandKey") },
{ ShortcutAction::OpenNewTabDropdown, RS_(L"OpenNewTabDropdownCommandKey") },
{ ShortcutAction::OpenSettings, RS_(L"OpenSettingsUICommandKey") },
{ ShortcutAction::OpenTabColorPicker, RS_(L"OpenTabColorPickerCommandKey") },
{ ShortcutAction::PasteText, RS_(L"PasteTextCommandKey") },
{ ShortcutAction::PrevTab, RS_(L"PrevTabCommandKey") },
{ ShortcutAction::RenameTab, RS_(L"ResetTabNameCommandKey") },
{ ShortcutAction::OpenTabRenamer, RS_(L"OpenTabRenamerCommandKey") },
{ ShortcutAction::ResetFontSize, RS_(L"ResetFontSizeCommandKey") },
{ ShortcutAction::ResizePane, RS_(L"ResizePaneCommandKey") },
{ ShortcutAction::ScrollDown, RS_(L"ScrollDownCommandKey") },
{ ShortcutAction::ScrollDownPage, RS_(L"ScrollDownPageCommandKey") },
{ ShortcutAction::ScrollUp, RS_(L"ScrollUpCommandKey") },
{ ShortcutAction::ScrollUpPage, RS_(L"ScrollUpPageCommandKey") },
{ ShortcutAction::ScrollToTop, RS_(L"ScrollToTopCommandKey") },
{ ShortcutAction::ScrollToBottom, RS_(L"ScrollToBottomCommandKey") },
{ ShortcutAction::ScrollToMark, RS_(L"ScrollToPreviousMarkCommandKey") },
{ ShortcutAction::AddMark, RS_(L"AddMarkCommandKey") },
{ ShortcutAction::ClearMark, RS_(L"ClearMarkCommandKey") },
{ ShortcutAction::ClearAllMarks, RS_(L"ClearAllMarksCommandKey") },
{ ShortcutAction::MoveFocus, USES_RESOURCE(L"MoveFocusCommandKey") },
{ ShortcutAction::MovePane, USES_RESOURCE(L"MovePaneCommandKey") },
{ ShortcutAction::SwapPane, USES_RESOURCE(L"SwapPaneCommandKey") },
{ ShortcutAction::NewTab, USES_RESOURCE(L"NewTabCommandKey") },
{ ShortcutAction::NextTab, USES_RESOURCE(L"NextTabCommandKey") },
{ ShortcutAction::OpenNewTabDropdown, USES_RESOURCE(L"OpenNewTabDropdownCommandKey") },
{ ShortcutAction::OpenSettings, USES_RESOURCE(L"OpenSettingsUICommandKey") },
{ ShortcutAction::OpenTabColorPicker, USES_RESOURCE(L"OpenTabColorPickerCommandKey") },
{ ShortcutAction::PasteText, USES_RESOURCE(L"PasteTextCommandKey") },
{ ShortcutAction::PrevTab, USES_RESOURCE(L"PrevTabCommandKey") },
{ ShortcutAction::RenameTab, USES_RESOURCE(L"ResetTabNameCommandKey") },
{ ShortcutAction::OpenTabRenamer, USES_RESOURCE(L"OpenTabRenamerCommandKey") },
{ ShortcutAction::ResetFontSize, USES_RESOURCE(L"ResetFontSizeCommandKey") },
{ ShortcutAction::ResizePane, USES_RESOURCE(L"ResizePaneCommandKey") },
{ ShortcutAction::ScrollDown, USES_RESOURCE(L"ScrollDownCommandKey") },
{ ShortcutAction::ScrollDownPage, USES_RESOURCE(L"ScrollDownPageCommandKey") },
{ ShortcutAction::ScrollUp, USES_RESOURCE(L"ScrollUpCommandKey") },
{ ShortcutAction::ScrollUpPage, USES_RESOURCE(L"ScrollUpPageCommandKey") },
{ ShortcutAction::ScrollToTop, USES_RESOURCE(L"ScrollToTopCommandKey") },
{ ShortcutAction::ScrollToBottom, USES_RESOURCE(L"ScrollToBottomCommandKey") },
{ ShortcutAction::ScrollToMark, USES_RESOURCE(L"ScrollToPreviousMarkCommandKey") },
{ ShortcutAction::AddMark, USES_RESOURCE(L"AddMarkCommandKey") },
{ ShortcutAction::ClearMark, USES_RESOURCE(L"ClearMarkCommandKey") },
{ ShortcutAction::ClearAllMarks, USES_RESOURCE(L"ClearAllMarksCommandKey") },
{ ShortcutAction::SendInput, MustGenerate },
{ ShortcutAction::SetColorScheme, MustGenerate },
{ ShortcutAction::SetTabColor, RS_(L"ResetTabColorCommandKey") },
{ ShortcutAction::SplitPane, RS_(L"SplitPaneCommandKey") },
{ ShortcutAction::SwitchToTab, RS_(L"SwitchToTabCommandKey") },
{ ShortcutAction::TabSearch, RS_(L"TabSearchCommandKey") },
{ ShortcutAction::ToggleAlwaysOnTop, RS_(L"ToggleAlwaysOnTopCommandKey") },
{ ShortcutAction::SetTabColor, USES_RESOURCE(L"ResetTabColorCommandKey") },
{ ShortcutAction::SplitPane, USES_RESOURCE(L"SplitPaneCommandKey") },
{ ShortcutAction::SwitchToTab, USES_RESOURCE(L"SwitchToTabCommandKey") },
{ ShortcutAction::TabSearch, USES_RESOURCE(L"TabSearchCommandKey") },
{ ShortcutAction::ToggleAlwaysOnTop, USES_RESOURCE(L"ToggleAlwaysOnTopCommandKey") },
{ ShortcutAction::ToggleCommandPalette, MustGenerate },
{ ShortcutAction::SaveSnippet, MustGenerate },
{ ShortcutAction::Suggestions, MustGenerate },
{ ShortcutAction::ToggleFocusMode, RS_(L"ToggleFocusModeCommandKey") },
{ ShortcutAction::ToggleFocusMode, USES_RESOURCE(L"ToggleFocusModeCommandKey") },
{ ShortcutAction::SetFocusMode, MustGenerate },
{ ShortcutAction::ToggleFullscreen, RS_(L"ToggleFullscreenCommandKey") },
{ ShortcutAction::ToggleFullscreen, USES_RESOURCE(L"ToggleFullscreenCommandKey") },
{ ShortcutAction::SetFullScreen, MustGenerate },
{ ShortcutAction::SetMaximized, MustGenerate },
{ ShortcutAction::TogglePaneZoom, RS_(L"TogglePaneZoomCommandKey") },
{ ShortcutAction::ToggleSplitOrientation, RS_(L"ToggleSplitOrientationCommandKey") },
{ ShortcutAction::ToggleShaderEffects, RS_(L"ToggleShaderEffectsCommandKey") },
{ ShortcutAction::TogglePaneZoom, USES_RESOURCE(L"TogglePaneZoomCommandKey") },
{ ShortcutAction::ToggleSplitOrientation, USES_RESOURCE(L"ToggleSplitOrientationCommandKey") },
{ ShortcutAction::ToggleShaderEffects, USES_RESOURCE(L"ToggleShaderEffectsCommandKey") },
{ ShortcutAction::MoveTab, MustGenerate },
{ ShortcutAction::BreakIntoDebugger, RS_(L"BreakIntoDebuggerCommandKey") },
{ ShortcutAction::BreakIntoDebugger, USES_RESOURCE(L"BreakIntoDebuggerCommandKey") },
{ ShortcutAction::FindMatch, MustGenerate },
{ ShortcutAction::TogglePaneReadOnly, RS_(L"TogglePaneReadOnlyCommandKey") },
{ ShortcutAction::EnablePaneReadOnly, RS_(L"EnablePaneReadOnlyCommandKey") },
{ ShortcutAction::DisablePaneReadOnly, RS_(L"DisablePaneReadOnlyCommandKey") },
{ ShortcutAction::NewWindow, RS_(L"NewWindowCommandKey") },
{ ShortcutAction::IdentifyWindow, RS_(L"IdentifyWindowCommandKey") },
{ ShortcutAction::IdentifyWindows, RS_(L"IdentifyWindowsCommandKey") },
{ ShortcutAction::RenameWindow, RS_(L"ResetWindowNameCommandKey") },
{ ShortcutAction::OpenWindowRenamer, RS_(L"OpenWindowRenamerCommandKey") },
{ ShortcutAction::DisplayWorkingDirectory, RS_(L"DisplayWorkingDirectoryCommandKey") },
{ ShortcutAction::TogglePaneReadOnly, USES_RESOURCE(L"TogglePaneReadOnlyCommandKey") },
{ ShortcutAction::EnablePaneReadOnly, USES_RESOURCE(L"EnablePaneReadOnlyCommandKey") },
{ ShortcutAction::DisablePaneReadOnly, USES_RESOURCE(L"DisablePaneReadOnlyCommandKey") },
{ ShortcutAction::NewWindow, USES_RESOURCE(L"NewWindowCommandKey") },
{ ShortcutAction::IdentifyWindow, USES_RESOURCE(L"IdentifyWindowCommandKey") },
{ ShortcutAction::IdentifyWindows, USES_RESOURCE(L"IdentifyWindowsCommandKey") },
{ ShortcutAction::RenameWindow, USES_RESOURCE(L"ResetWindowNameCommandKey") },
{ ShortcutAction::OpenWindowRenamer, USES_RESOURCE(L"OpenWindowRenamerCommandKey") },
{ ShortcutAction::DisplayWorkingDirectory, USES_RESOURCE(L"DisplayWorkingDirectoryCommandKey") },
{ ShortcutAction::GlobalSummon, MustGenerate },
{ ShortcutAction::SearchForText, MustGenerate },
{ ShortcutAction::QuakeMode, RS_(L"QuakeModeCommandKey") },
{ ShortcutAction::QuakeMode, USES_RESOURCE(L"QuakeModeCommandKey") },
{ ShortcutAction::FocusPane, MustGenerate },
{ ShortcutAction::OpenSystemMenu, RS_(L"OpenSystemMenuCommandKey") },
{ ShortcutAction::OpenSystemMenu, USES_RESOURCE(L"OpenSystemMenuCommandKey") },
{ ShortcutAction::ExportBuffer, MustGenerate },
{ ShortcutAction::ClearBuffer, MustGenerate },
{ ShortcutAction::MultipleActions, MustGenerate },
{ ShortcutAction::Quit, RS_(L"QuitCommandKey") },
{ ShortcutAction::Quit, USES_RESOURCE(L"QuitCommandKey") },
{ ShortcutAction::AdjustOpacity, MustGenerate },
{ ShortcutAction::RestoreLastClosed, RS_(L"RestoreLastClosedCommandKey") },
{ ShortcutAction::RestoreLastClosed, USES_RESOURCE(L"RestoreLastClosedCommandKey") },
{ ShortcutAction::SelectCommand, MustGenerate },
{ ShortcutAction::SelectOutput, MustGenerate },
{ ShortcutAction::SelectAll, RS_(L"SelectAllCommandKey") },
{ ShortcutAction::MarkMode, RS_(L"MarkModeCommandKey") },
{ ShortcutAction::ToggleBlockSelection, RS_(L"ToggleBlockSelectionCommandKey") },
{ ShortcutAction::SwitchSelectionEndpoint, RS_(L"SwitchSelectionEndpointCommandKey") },
{ ShortcutAction::SelectAll, USES_RESOURCE(L"SelectAllCommandKey") },
{ ShortcutAction::MarkMode, USES_RESOURCE(L"MarkModeCommandKey") },
{ ShortcutAction::ToggleBlockSelection, USES_RESOURCE(L"ToggleBlockSelectionCommandKey") },
{ ShortcutAction::SwitchSelectionEndpoint, USES_RESOURCE(L"SwitchSelectionEndpointCommandKey") },
{ ShortcutAction::ColorSelection, MustGenerate },
{ ShortcutAction::ShowContextMenu, RS_(L"ShowContextMenuCommandKey") },
{ ShortcutAction::ExpandSelectionToWord, RS_(L"ExpandSelectionToWordCommandKey") },
{ ShortcutAction::RestartConnection, RS_(L"RestartConnectionKey") },
{ ShortcutAction::ToggleBroadcastInput, RS_(L"ToggleBroadcastInputCommandKey") },
{ ShortcutAction::OpenScratchpad, RS_(L"OpenScratchpadKey") },
{ ShortcutAction::OpenAbout, RS_(L"OpenAboutCommandKey") },
{ ShortcutAction::QuickFix, RS_(L"QuickFixCommandKey") },
{ ShortcutAction::OpenCWD, RS_(L"OpenCWDCommandKey") },
{ ShortcutAction::ShowContextMenu, USES_RESOURCE(L"ShowContextMenuCommandKey") },
{ ShortcutAction::ExpandSelectionToWord, USES_RESOURCE(L"ExpandSelectionToWordCommandKey") },
{ ShortcutAction::RestartConnection, USES_RESOURCE(L"RestartConnectionKey") },
{ ShortcutAction::ToggleBroadcastInput, USES_RESOURCE(L"ToggleBroadcastInputCommandKey") },
{ ShortcutAction::OpenScratchpad, USES_RESOURCE(L"OpenScratchpadKey") },
{ ShortcutAction::OpenAbout, USES_RESOURCE(L"OpenAboutCommandKey") },
{ ShortcutAction::QuickFix, USES_RESOURCE(L"QuickFixCommandKey") },
{ ShortcutAction::OpenCWD, USES_RESOURCE(L"OpenCWDCommandKey") },
};
}();
if (_Args)
{
auto nameFromArgs = _Args.GenerateName();
auto nameFromArgs = _Args.GenerateName(context);
if (!nameFromArgs.empty())
{
return nameFromArgs;
@@ -452,7 +453,16 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
}
const auto found = GeneratedActionNames.find(_Action);
return found != GeneratedActionNames.end() ? found->second : winrt::hstring{};
if (found != GeneratedActionNames.end() && !found->second.empty())
{
return GetLibraryResourceLoader().ResourceMap().GetValue(found->second, context).ValueAsString();
}
return winrt::hstring{};
}
winrt::hstring ActionAndArgs::GenerateName() const
{
return GenerateName(GetLibraryResourceLoader().ResourceContext());
}
// Function Description:

View File

@@ -25,6 +25,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
_Args{ args } {};
com_ptr<ActionAndArgs> Copy() const;
hstring GenerateName(const winrt::Windows::ApplicationModel::Resources::Core::ResourceContext& context) const;
hstring GenerateName() const;
hstring GenerateID() const;

View File

@@ -53,12 +53,42 @@
#include <LibraryResources.h>
#include <WtExeUtils.h>
#include <ScopedResourceLoader.h>
namespace winrt
{
namespace WARC = ::winrt::Windows::ApplicationModel::Resources::Core;
}
// Like RS_ and RS_fmt, but they use an ambient boolean named "localized" to
// determine whether to load the English version of a resource or the localized
// one.
#define RS_switchable_(x) RS_switchable_impl(context, USES_RESOURCE(x))
#define RS_switchable_fmt(x, ...) RS_switchable_fmt_impl(context, USES_RESOURCE(x), __VA_ARGS__)
static winrt::hstring RS_switchable_impl(const winrt::WARC::ResourceContext& context, std::wstring_view key)
{
return GetLibraryResourceLoader().ResourceMap().GetValue(key, context).ValueAsString();
}
template<typename... Args>
static std::wstring RS_switchable_fmt_impl(const winrt::WARC::ResourceContext& context, std::wstring_view key, Args&&... args)
{
const auto format = RS_switchable_impl(context, key);
return fmt::format(fmt::runtime(std::wstring_view{ format }), std::forward<Args>(args)...);
}
using namespace winrt::Microsoft::Terminal::Control;
namespace winrt::Microsoft::Terminal::Settings::Model::implementation
{
winrt::hstring NewTerminalArgs::GenerateName() const
const ScopedResourceLoader& EnglishOnlyResourceLoader() noexcept
{
static ScopedResourceLoader loader{ GetLibraryResourceLoader().WithQualifier(L"language", L"en-US") };
return loader;
}
winrt::hstring NewTerminalArgs::GenerateName(const winrt::WARC::ResourceContext&) const
{
std::wstring str;
@@ -194,17 +224,17 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
return winrt::hstring{ str };
}
winrt::hstring CopyTextArgs::GenerateName() const
winrt::hstring CopyTextArgs::GenerateName(const winrt::WARC::ResourceContext& context) const
{
std::wstring str;
if (SingleLine())
{
str.append(RS_(L"CopyTextAsSingleLineCommandKey"));
str.append(RS_switchable_(L"CopyTextAsSingleLineCommandKey"));
}
else
{
str.append(RS_(L"CopyTextCommandKey"));
str.append(RS_switchable_(L"CopyTextCommandKey"));
}
if (WithControlSequences())
@@ -248,24 +278,24 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
return winrt::hstring{ str };
}
winrt::hstring NewTabArgs::GenerateName() const
winrt::hstring NewTabArgs::GenerateName(const winrt::WARC::ResourceContext& context) const
{
winrt::hstring newTerminalArgsStr;
if (ContentArgs())
{
newTerminalArgsStr = ContentArgs().GenerateName();
newTerminalArgsStr = ContentArgs().GenerateName(context);
}
if (newTerminalArgsStr.empty())
{
return RS_(L"NewTabCommandKey");
return RS_switchable_(L"NewTabCommandKey");
}
return winrt::hstring{
fmt::format(FMT_COMPILE(L"{}, {}"), RS_(L"NewTabCommandKey"), newTerminalArgsStr)
fmt::format(FMT_COMPILE(L"{}, {}"), RS_switchable_(L"NewTabCommandKey"), newTerminalArgsStr)
};
}
winrt::hstring MovePaneArgs::GenerateName() const
winrt::hstring MovePaneArgs::GenerateName(const winrt::WARC::ResourceContext& context) const
{
if (!Window().empty())
{
@@ -274,115 +304,115 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
// in the new window, till we get there.
if (Window() == L"new")
{
return RS_(L"MovePaneToNewWindowCommandKey");
return RS_switchable_(L"MovePaneToNewWindowCommandKey");
}
return winrt::hstring{
fmt::format(FMT_COMPILE(L"{}, window:{}, tab index:{}"), RS_(L"MovePaneCommandKey"), Window(), TabIndex())
fmt::format(FMT_COMPILE(L"{}, window:{}, tab index:{}"), RS_switchable_(L"MovePaneCommandKey"), Window(), TabIndex())
};
}
return winrt::hstring{
fmt::format(FMT_COMPILE(L"{}, tab index:{}"), RS_(L"MovePaneCommandKey"), TabIndex())
fmt::format(FMT_COMPILE(L"{}, tab index:{}"), RS_switchable_(L"MovePaneCommandKey"), TabIndex())
};
}
winrt::hstring SwitchToTabArgs::GenerateName() const
winrt::hstring SwitchToTabArgs::GenerateName(const winrt::WARC::ResourceContext& context) const
{
if (TabIndex() == UINT32_MAX)
{
return RS_(L"SwitchToLastTabCommandKey");
return RS_switchable_(L"SwitchToLastTabCommandKey");
}
return winrt::hstring{
fmt::format(FMT_COMPILE(L"{}, index:{}"), RS_(L"SwitchToTabCommandKey"), TabIndex())
fmt::format(FMT_COMPILE(L"{}, index:{}"), RS_switchable_(L"SwitchToTabCommandKey"), TabIndex())
};
}
winrt::hstring ResizePaneArgs::GenerateName() const
winrt::hstring ResizePaneArgs::GenerateName(const winrt::WARC::ResourceContext& context) const
{
winrt::hstring directionString;
switch (ResizeDirection())
{
case ResizeDirection::Left:
directionString = RS_(L"DirectionLeft");
directionString = RS_switchable_(L"DirectionLeft");
break;
case ResizeDirection::Right:
directionString = RS_(L"DirectionRight");
directionString = RS_switchable_(L"DirectionRight");
break;
case ResizeDirection::Up:
directionString = RS_(L"DirectionUp");
directionString = RS_switchable_(L"DirectionUp");
break;
case ResizeDirection::Down:
directionString = RS_(L"DirectionDown");
directionString = RS_switchable_(L"DirectionDown");
break;
}
return winrt::hstring{ RS_fmt(L"ResizePaneWithArgCommandKey", directionString) };
return winrt::hstring{ RS_switchable_fmt(L"ResizePaneWithArgCommandKey", directionString) };
}
winrt::hstring MoveFocusArgs::GenerateName() const
winrt::hstring MoveFocusArgs::GenerateName(const winrt::WARC::ResourceContext& context) const
{
winrt::hstring directionString;
switch (FocusDirection())
{
case FocusDirection::Left:
directionString = RS_(L"DirectionLeft");
directionString = RS_switchable_(L"DirectionLeft");
break;
case FocusDirection::Right:
directionString = RS_(L"DirectionRight");
directionString = RS_switchable_(L"DirectionRight");
break;
case FocusDirection::Up:
directionString = RS_(L"DirectionUp");
directionString = RS_switchable_(L"DirectionUp");
break;
case FocusDirection::Down:
directionString = RS_(L"DirectionDown");
directionString = RS_switchable_(L"DirectionDown");
break;
case FocusDirection::Previous:
return RS_(L"MoveFocusToLastUsedPane");
return RS_switchable_(L"MoveFocusToLastUsedPane");
case FocusDirection::NextInOrder:
return RS_(L"MoveFocusNextInOrder");
return RS_switchable_(L"MoveFocusNextInOrder");
case FocusDirection::PreviousInOrder:
return RS_(L"MoveFocusPreviousInOrder");
return RS_switchable_(L"MoveFocusPreviousInOrder");
case FocusDirection::First:
return RS_(L"MoveFocusFirstPane");
return RS_switchable_(L"MoveFocusFirstPane");
case FocusDirection::Parent:
return RS_(L"MoveFocusParentPane");
return RS_switchable_(L"MoveFocusParentPane");
case FocusDirection::Child:
return RS_(L"MoveFocusChildPane");
return RS_switchable_(L"MoveFocusChildPane");
}
return winrt::hstring{ RS_fmt(L"MoveFocusWithArgCommandKey", directionString) };
return winrt::hstring{ RS_switchable_fmt(L"MoveFocusWithArgCommandKey", directionString) };
}
winrt::hstring SwapPaneArgs::GenerateName() const
winrt::hstring SwapPaneArgs::GenerateName(const winrt::WARC::ResourceContext& context) const
{
winrt::hstring directionString;
switch (Direction())
{
case FocusDirection::Left:
directionString = RS_(L"DirectionLeft");
directionString = RS_switchable_(L"DirectionLeft");
break;
case FocusDirection::Right:
directionString = RS_(L"DirectionRight");
directionString = RS_switchable_(L"DirectionRight");
break;
case FocusDirection::Up:
directionString = RS_(L"DirectionUp");
directionString = RS_switchable_(L"DirectionUp");
break;
case FocusDirection::Down:
directionString = RS_(L"DirectionDown");
directionString = RS_switchable_(L"DirectionDown");
break;
case FocusDirection::Previous:
return RS_(L"SwapPaneToLastUsedPane");
return RS_switchable_(L"SwapPaneToLastUsedPane");
case FocusDirection::NextInOrder:
return RS_(L"SwapPaneNextInOrder");
return RS_switchable_(L"SwapPaneNextInOrder");
case FocusDirection::PreviousInOrder:
return RS_(L"SwapPanePreviousInOrder");
return RS_switchable_(L"SwapPanePreviousInOrder");
case FocusDirection::First:
return RS_(L"SwapPaneFirstPane");
return RS_switchable_(L"SwapPaneFirstPane");
}
return winrt::hstring{ RS_fmt(L"SwapPaneWithArgCommandKey", directionString) };
return winrt::hstring{ RS_switchable_fmt(L"SwapPaneWithArgCommandKey", directionString) };
}
winrt::hstring AdjustFontSizeArgs::GenerateName() const
winrt::hstring AdjustFontSizeArgs::GenerateName(const winrt::WARC::ResourceContext& context) const
{
// If the amount is just 1 (or -1), we'll just return "Increase font
// size" (or "Decrease font size"). If the amount delta has a greater
@@ -390,25 +420,25 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
// * Decrease font size, amount: {delta}"
if (Delta() < 0)
{
return Delta() == -1 ? RS_(L"DecreaseFontSizeCommandKey") : winrt::hstring{ RS_fmt(L"DecreaseFontSizeWithAmountCommandKey", -Delta()) };
return Delta() == -1 ? RS_switchable_(L"DecreaseFontSizeCommandKey") : winrt::hstring{ RS_switchable_fmt(L"DecreaseFontSizeWithAmountCommandKey", -Delta()) };
}
else
{
return Delta() == 1 ? RS_(L"IncreaseFontSizeCommandKey") : winrt::hstring{ RS_fmt(L"IncreaseFontSizeWithAmountCommandKey", Delta()) };
return Delta() == 1 ? RS_switchable_(L"IncreaseFontSizeCommandKey") : winrt::hstring{ RS_switchable_fmt(L"IncreaseFontSizeWithAmountCommandKey", Delta()) };
}
}
winrt::hstring SendInputArgs::GenerateName() const
winrt::hstring SendInputArgs::GenerateName(const winrt::WARC::ResourceContext& context) const
{
// The string will be similar to the following:
// * "Send Input: ...input..."
const auto escapedInput = til::visualize_control_codes(Input());
const auto name = RS_fmt(L"SendInputCommandKey", escapedInput);
const auto name = RS_switchable_fmt(L"SendInputCommandKey", escapedInput);
return winrt::hstring{ name };
}
winrt::hstring SplitPaneArgs::GenerateName() const
winrt::hstring SplitPaneArgs::GenerateName(const winrt::WARC::ResourceContext& context) const
{
// The string will be similar to the following:
// * "Duplicate pane[, split: <direction>][, size: <size>%][, new terminal arguments...]"
@@ -422,11 +452,11 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
std::wstring str;
if (SplitMode() == SplitType::Duplicate)
{
str.append(RS_(L"DuplicatePaneCommandKey"));
str.append(RS_switchable_(L"DuplicatePaneCommandKey"));
}
else
{
str.append(RS_(L"SplitPaneCommandKey"));
str.append(RS_switchable_(L"SplitPaneCommandKey"));
}
str.append(L", ");
@@ -456,7 +486,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
winrt::hstring newTerminalArgsStr;
if (ContentArgs())
{
newTerminalArgsStr = ContentArgs().GenerateName();
newTerminalArgsStr = ContentArgs().GenerateName(context);
}
if (SplitMode() != SplitType::Duplicate && !newTerminalArgsStr.empty())
@@ -470,209 +500,209 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
return winrt::hstring{ str };
}
winrt::hstring OpenSettingsArgs::GenerateName() const
winrt::hstring OpenSettingsArgs::GenerateName(const winrt::WARC::ResourceContext& context) const
{
switch (Target())
{
case SettingsTarget::DefaultsFile:
return RS_(L"OpenDefaultSettingsCommandKey");
return RS_switchable_(L"OpenDefaultSettingsCommandKey");
case SettingsTarget::AllFiles:
return RS_(L"OpenBothSettingsFilesCommandKey");
return RS_switchable_(L"OpenBothSettingsFilesCommandKey");
case SettingsTarget::SettingsFile:
return RS_(L"OpenSettingsCommandKey");
return RS_switchable_(L"OpenSettingsCommandKey");
case SettingsTarget::Directory:
return RS_(L"SettingsFileOpenInExplorerCommandKey");
return RS_switchable_(L"SettingsFileOpenInExplorerCommandKey");
case SettingsTarget::SettingsUI:
default:
return RS_(L"OpenSettingsUICommandKey");
return RS_switchable_(L"OpenSettingsUICommandKey");
}
}
winrt::hstring SetFocusModeArgs::GenerateName() const
winrt::hstring SetFocusModeArgs::GenerateName(const winrt::WARC::ResourceContext& context) const
{
if (IsFocusMode())
{
return RS_(L"EnableFocusModeCommandKey");
return RS_switchable_(L"EnableFocusModeCommandKey");
}
return RS_(L"DisableFocusModeCommandKey");
return RS_switchable_(L"DisableFocusModeCommandKey");
}
winrt::hstring SetFullScreenArgs::GenerateName() const
winrt::hstring SetFullScreenArgs::GenerateName(const winrt::WARC::ResourceContext& context) const
{
if (IsFullScreen())
{
return RS_(L"EnableFullScreenCommandKey");
return RS_switchable_(L"EnableFullScreenCommandKey");
}
return RS_(L"DisableFullScreenCommandKey");
return RS_switchable_(L"DisableFullScreenCommandKey");
}
winrt::hstring SetMaximizedArgs::GenerateName() const
winrt::hstring SetMaximizedArgs::GenerateName(const winrt::WARC::ResourceContext& context) const
{
if (IsMaximized())
{
return RS_(L"EnableMaximizedCommandKey");
return RS_switchable_(L"EnableMaximizedCommandKey");
}
return RS_(L"DisableMaximizedCommandKey");
return RS_switchable_(L"DisableMaximizedCommandKey");
}
winrt::hstring SetColorSchemeArgs::GenerateName() const
winrt::hstring SetColorSchemeArgs::GenerateName(const winrt::WARC::ResourceContext& context) const
{
// "Set color scheme to "{_SchemeName}""
if (!SchemeName().empty())
{
return winrt::hstring{ RS_fmt(L"SetColorSchemeCommandKey", SchemeName()) };
return winrt::hstring{ RS_switchable_fmt(L"SetColorSchemeCommandKey", SchemeName()) };
}
return {};
}
winrt::hstring SetTabColorArgs::GenerateName() const
winrt::hstring SetTabColorArgs::GenerateName(const winrt::WARC::ResourceContext& context) const
{
// "Set tab color to #RRGGBB"
// "Reset tab color"
if (TabColor())
{
til::color tabColor{ TabColor().Value() };
return winrt::hstring{ RS_fmt(L"SetTabColorCommandKey", tabColor.ToHexString(true)) };
return winrt::hstring{ RS_switchable_fmt(L"SetTabColorCommandKey", tabColor.ToHexString(true)) };
}
return RS_(L"ResetTabColorCommandKey");
return RS_switchable_(L"ResetTabColorCommandKey");
}
winrt::hstring RenameTabArgs::GenerateName() const
winrt::hstring RenameTabArgs::GenerateName(const winrt::WARC::ResourceContext& context) const
{
// "Rename tab to \"{_Title}\""
// "Reset tab title"
if (!Title().empty())
{
return winrt::hstring{ RS_fmt(L"RenameTabCommandKey", Title()) };
return winrt::hstring{ RS_switchable_fmt(L"RenameTabCommandKey", Title()) };
}
return RS_(L"ResetTabNameCommandKey");
return RS_switchable_(L"ResetTabNameCommandKey");
}
winrt::hstring ExecuteCommandlineArgs::GenerateName() const
winrt::hstring ExecuteCommandlineArgs::GenerateName(const winrt::WARC::ResourceContext& context) const
{
// "Run commandline "{_Commandline}" in this window"
if (!Commandline().empty())
{
return winrt::hstring{ RS_fmt(L"ExecuteCommandlineCommandKey", Commandline()) };
return winrt::hstring{ RS_switchable_fmt(L"ExecuteCommandlineCommandKey", Commandline()) };
}
return {};
}
winrt::hstring CloseOtherTabsArgs::GenerateName() const
winrt::hstring CloseOtherTabsArgs::GenerateName(const winrt::WARC::ResourceContext& context) const
{
if (Index())
{
// "Close tabs other than index {0}"
return winrt::hstring{ RS_fmt(L"CloseOtherTabsCommandKey", Index().Value()) };
return winrt::hstring{ RS_switchable_fmt(L"CloseOtherTabsCommandKey", Index().Value()) };
}
return RS_(L"CloseOtherTabsDefaultCommandKey");
return RS_switchable_(L"CloseOtherTabsDefaultCommandKey");
}
winrt::hstring CloseTabsAfterArgs::GenerateName() const
winrt::hstring CloseTabsAfterArgs::GenerateName(const winrt::WARC::ResourceContext& context) const
{
if (Index())
{
// "Close tabs after index {0}"
return winrt::hstring{ RS_fmt(L"CloseTabsAfterCommandKey", Index().Value()) };
return winrt::hstring{ RS_switchable_fmt(L"CloseTabsAfterCommandKey", Index().Value()) };
}
return RS_(L"CloseTabsAfterDefaultCommandKey");
return RS_switchable_(L"CloseTabsAfterDefaultCommandKey");
}
winrt::hstring CloseTabArgs::GenerateName() const
winrt::hstring CloseTabArgs::GenerateName(const winrt::WARC::ResourceContext& context) const
{
if (Index())
{
// "Close tab at index {0}"
return winrt::hstring{ RS_fmt(L"CloseTabAtIndexCommandKey", Index().Value()) };
return winrt::hstring{ RS_switchable_fmt(L"CloseTabAtIndexCommandKey", Index().Value()) };
}
return RS_(L"CloseTabCommandKey");
return RS_switchable_(L"CloseTabCommandKey");
}
winrt::hstring ScrollUpArgs::GenerateName() const
winrt::hstring ScrollUpArgs::GenerateName(const winrt::WARC::ResourceContext& context) const
{
if (RowsToScroll())
{
return winrt::hstring{ RS_fmt(L"ScrollUpSeveralRowsCommandKey", RowsToScroll().Value()) };
return winrt::hstring{ RS_switchable_fmt(L"ScrollUpSeveralRowsCommandKey", RowsToScroll().Value()) };
}
return RS_(L"ScrollUpCommandKey");
return RS_switchable_(L"ScrollUpCommandKey");
}
winrt::hstring ScrollDownArgs::GenerateName() const
winrt::hstring ScrollDownArgs::GenerateName(const winrt::WARC::ResourceContext& context) const
{
if (RowsToScroll())
{
return winrt::hstring{ RS_fmt(L"ScrollDownSeveralRowsCommandKey", RowsToScroll().Value()) };
return winrt::hstring{ RS_switchable_fmt(L"ScrollDownSeveralRowsCommandKey", RowsToScroll().Value()) };
}
return RS_(L"ScrollDownCommandKey");
return RS_switchable_(L"ScrollDownCommandKey");
}
winrt::hstring ScrollToMarkArgs::GenerateName() const
winrt::hstring ScrollToMarkArgs::GenerateName(const winrt::WARC::ResourceContext& context) const
{
switch (Direction())
{
case Microsoft::Terminal::Control::ScrollToMarkDirection::Last:
return winrt::hstring{ RS_(L"ScrollToLastMarkCommandKey") };
return winrt::hstring{ RS_switchable_(L"ScrollToLastMarkCommandKey") };
case Microsoft::Terminal::Control::ScrollToMarkDirection::First:
return winrt::hstring{ RS_(L"ScrollToFirstMarkCommandKey") };
return winrt::hstring{ RS_switchable_(L"ScrollToFirstMarkCommandKey") };
case Microsoft::Terminal::Control::ScrollToMarkDirection::Next:
return winrt::hstring{ RS_(L"ScrollToNextMarkCommandKey") };
return winrt::hstring{ RS_switchable_(L"ScrollToNextMarkCommandKey") };
case Microsoft::Terminal::Control::ScrollToMarkDirection::Previous:
default:
return winrt::hstring{ RS_(L"ScrollToPreviousMarkCommandKey") };
return winrt::hstring{ RS_switchable_(L"ScrollToPreviousMarkCommandKey") };
}
return winrt::hstring{ RS_(L"ScrollToPreviousMarkCommandKey") };
return winrt::hstring{ RS_switchable_(L"ScrollToPreviousMarkCommandKey") };
}
winrt::hstring AddMarkArgs::GenerateName() const
winrt::hstring AddMarkArgs::GenerateName(const winrt::WARC::ResourceContext& context) const
{
if (Color())
{
return winrt::hstring{ RS_fmt(L"AddMarkWithColorCommandKey", til::color{ Color().Value() }.ToHexString(true)) };
return winrt::hstring{ RS_switchable_fmt(L"AddMarkWithColorCommandKey", til::color{ Color().Value() }.ToHexString(true)) };
}
else
{
return RS_(L"AddMarkCommandKey");
return RS_switchable_(L"AddMarkCommandKey");
}
}
winrt::hstring MoveTabArgs::GenerateName() const
winrt::hstring MoveTabArgs::GenerateName(const winrt::WARC::ResourceContext& context) const
{
if (!Window().empty())
{
if (Window() == L"new")
{
return RS_(L"MoveTabToNewWindowCommandKey");
return RS_switchable_(L"MoveTabToNewWindowCommandKey");
}
return winrt::hstring{ RS_fmt(L"MoveTabToWindowCommandKey", Window()) };
return winrt::hstring{ RS_switchable_fmt(L"MoveTabToWindowCommandKey", Window()) };
}
winrt::hstring directionString;
switch (Direction())
{
case MoveTabDirection::Forward:
directionString = RS_(L"MoveTabDirectionForward");
directionString = RS_switchable_(L"MoveTabDirectionForward");
break;
case MoveTabDirection::Backward:
directionString = RS_(L"MoveTabDirectionBackward");
directionString = RS_switchable_(L"MoveTabDirectionBackward");
break;
}
return winrt::hstring{ RS_fmt(L"MoveTabCommandKey", directionString) };
return winrt::hstring{ RS_switchable_fmt(L"MoveTabCommandKey", directionString) };
}
winrt::hstring ToggleCommandPaletteArgs::GenerateName() const
winrt::hstring ToggleCommandPaletteArgs::GenerateName(const winrt::WARC::ResourceContext& context) const
{
if (LaunchMode() == CommandPaletteLaunchMode::CommandLine)
{
return RS_(L"ToggleCommandPaletteCommandLineModeCommandKey");
return RS_switchable_(L"ToggleCommandPaletteCommandLineModeCommandKey");
}
return RS_(L"ToggleCommandPaletteCommandKey");
return RS_switchable_(L"ToggleCommandPaletteCommandKey");
}
winrt::hstring SuggestionsArgs::GenerateName() const
winrt::hstring SuggestionsArgs::GenerateName(const winrt::WARC::ResourceContext& context) const
{
std::wstring str;
str.append(RS_(L"SuggestionsCommandKey"));
str.append(RS_switchable_(L"SuggestionsCommandKey"));
if (UseCommandline())
{
@@ -707,78 +737,78 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
return winrt::hstring{ str };
}
winrt::hstring FindMatchArgs::GenerateName() const
winrt::hstring FindMatchArgs::GenerateName(const winrt::WARC::ResourceContext& context) const
{
switch (Direction())
{
case FindMatchDirection::Next:
return winrt::hstring{ RS_(L"FindNextCommandKey") };
return winrt::hstring{ RS_switchable_(L"FindNextCommandKey") };
case FindMatchDirection::Previous:
return winrt::hstring{ RS_(L"FindPrevCommandKey") };
return winrt::hstring{ RS_switchable_(L"FindPrevCommandKey") };
}
return {};
}
winrt::hstring NewWindowArgs::GenerateName() const
winrt::hstring NewWindowArgs::GenerateName(const winrt::WARC::ResourceContext& context) const
{
winrt::hstring newTerminalArgsStr;
if (ContentArgs())
{
newTerminalArgsStr = ContentArgs().GenerateName();
newTerminalArgsStr = ContentArgs().GenerateName(context);
}
if (newTerminalArgsStr.empty())
{
return RS_(L"NewWindowCommandKey");
return RS_switchable_(L"NewWindowCommandKey");
}
return winrt::hstring{ fmt::format(FMT_COMPILE(L"{}, {}"), RS_(L"NewWindowCommandKey"), newTerminalArgsStr) };
return winrt::hstring{ fmt::format(FMT_COMPILE(L"{}, {}"), RS_switchable_(L"NewWindowCommandKey"), newTerminalArgsStr) };
}
winrt::hstring PrevTabArgs::GenerateName() const
winrt::hstring PrevTabArgs::GenerateName(const winrt::WARC::ResourceContext& context) const
{
if (!SwitcherMode())
{
return RS_(L"PrevTabCommandKey");
return RS_switchable_(L"PrevTabCommandKey");
}
const auto mode = SwitcherMode().Value() == TabSwitcherMode::MostRecentlyUsed ? L"most recently used" : L"in order";
return winrt::hstring(fmt::format(FMT_COMPILE(L"{}, {}"), RS_(L"PrevTabCommandKey"), mode));
return winrt::hstring(fmt::format(FMT_COMPILE(L"{}, {}"), RS_switchable_(L"PrevTabCommandKey"), mode));
}
winrt::hstring NextTabArgs::GenerateName() const
winrt::hstring NextTabArgs::GenerateName(const winrt::WARC::ResourceContext& context) const
{
if (!SwitcherMode())
{
return RS_(L"NextTabCommandKey");
return RS_switchable_(L"NextTabCommandKey");
}
const auto mode = SwitcherMode().Value() == TabSwitcherMode::MostRecentlyUsed ? L"most recently used" : L"in order";
return winrt::hstring(fmt::format(FMT_COMPILE(L"{}, {}"), RS_(L"NextTabCommandKey"), mode));
return winrt::hstring(fmt::format(FMT_COMPILE(L"{}, {}"), RS_switchable_(L"NextTabCommandKey"), mode));
}
winrt::hstring RenameWindowArgs::GenerateName() const
winrt::hstring RenameWindowArgs::GenerateName(const winrt::WARC::ResourceContext& context) const
{
// "Rename window to \"{_Name}\""
// "Clear window name"
if (!Name().empty())
{
return winrt::hstring{ RS_fmt(L"RenameWindowCommandKey", Name()) };
return winrt::hstring{ RS_switchable_fmt(L"RenameWindowCommandKey", Name()) };
}
return RS_(L"ResetWindowNameCommandKey");
return RS_switchable_(L"ResetWindowNameCommandKey");
}
winrt::hstring SearchForTextArgs::GenerateName() const
winrt::hstring SearchForTextArgs::GenerateName(const winrt::WARC::ResourceContext& context) const
{
if (QueryUrl().empty())
{
// Return the default command name, because we'll just use the
// default search engine for this.
return RS_(L"SearchWebCommandKey");
return RS_switchable_(L"SearchWebCommandKey");
}
try
{
return winrt::hstring{ RS_fmt(L"SearchForTextCommandKey", Windows::Foundation::Uri(QueryUrl()).Domain()) };
return winrt::hstring{ RS_switchable_fmt(L"SearchForTextCommandKey", Windows::Foundation::Uri(QueryUrl()).Domain()) };
}
CATCH_LOG();
@@ -787,17 +817,17 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
return {};
}
winrt::hstring GlobalSummonArgs::GenerateName() const
winrt::hstring GlobalSummonArgs::GenerateName(const winrt::WARC::ResourceContext& context) const
{
// GH#10210 - Is this action literally the same thing as the `quakeMode`
// action? That has a special name.
static const auto quakeModeArgs{ std::get<0>(GlobalSummonArgs::QuakeModeFromJson(Json::Value::null)) };
if (quakeModeArgs.Equals(*this))
{
return RS_(L"QuakeModeCommandKey");
return RS_switchable_(L"QuakeModeCommandKey");
}
std::wstring str{ RS_(L"GlobalSummonCommandKey") };
std::wstring str{ RS_switchable_(L"GlobalSummonCommandKey") };
// "Summon the Terminal window"
// "Summon the Terminal window, name:\"{_Name}\""
@@ -809,27 +839,27 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
return winrt::hstring{ str };
}
winrt::hstring FocusPaneArgs::GenerateName() const
winrt::hstring FocusPaneArgs::GenerateName(const winrt::WARC::ResourceContext& context) const
{
// "Focus pane {Id}"
return winrt::hstring{ RS_fmt(L"FocusPaneCommandKey", Id()) };
return winrt::hstring{ RS_switchable_fmt(L"FocusPaneCommandKey", Id()) };
}
winrt::hstring ExportBufferArgs::GenerateName() const
winrt::hstring ExportBufferArgs::GenerateName(const winrt::WARC::ResourceContext& context) const
{
if (!Path().empty())
{
// "Export text to {path}"
return winrt::hstring{ RS_fmt(L"ExportBufferToPathCommandKey", Path()) };
return winrt::hstring{ RS_switchable_fmt(L"ExportBufferToPathCommandKey", Path()) };
}
else
{
// "Export text"
return RS_(L"ExportBufferCommandKey");
return RS_switchable_(L"ExportBufferCommandKey");
}
}
winrt::hstring ClearBufferArgs::GenerateName() const
winrt::hstring ClearBufferArgs::GenerateName(const winrt::WARC::ResourceContext& context) const
{
// "Clear Buffer"
// "Clear Viewport"
@@ -837,49 +867,49 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
switch (Clear())
{
case Control::ClearBufferType::All:
return RS_(L"ClearAllCommandKey");
return RS_switchable_(L"ClearAllCommandKey");
case Control::ClearBufferType::Screen:
return RS_(L"ClearViewportCommandKey");
return RS_switchable_(L"ClearViewportCommandKey");
case Control::ClearBufferType::Scrollback:
return RS_(L"ClearScrollbackCommandKey");
return RS_switchable_(L"ClearScrollbackCommandKey");
}
// Return the empty string - the Clear() should be one of these values
return {};
}
winrt::hstring MultipleActionsArgs::GenerateName() const
winrt::hstring MultipleActionsArgs::GenerateName(const winrt::WARC::ResourceContext&) const
{
return {};
}
winrt::hstring AdjustOpacityArgs::GenerateName() const
winrt::hstring AdjustOpacityArgs::GenerateName(const winrt::WARC::ResourceContext& context) const
{
if (Relative())
{
if (Opacity() >= 0)
{
// "Increase background opacity by {Opacity}%"
return winrt::hstring{ RS_fmt(L"IncreaseOpacityCommandKey", Opacity()) };
return winrt::hstring{ RS_switchable_fmt(L"IncreaseOpacityCommandKey", Opacity()) };
}
else
{
// "Decrease background opacity by {Opacity}%"
return winrt::hstring{ RS_fmt(L"DecreaseOpacityCommandKey", Opacity()) };
return winrt::hstring{ RS_switchable_fmt(L"DecreaseOpacityCommandKey", Opacity()) };
}
}
else
{
// "Set background opacity to {Opacity}%"
return winrt::hstring{ RS_fmt(L"AdjustOpacityCommandKey", Opacity()) };
return winrt::hstring{ RS_switchable_fmt(L"AdjustOpacityCommandKey", Opacity()) };
}
}
winrt::hstring SaveSnippetArgs::GenerateName() const
winrt::hstring SaveSnippetArgs::GenerateName(const winrt::WARC::ResourceContext& context) const
{
if (Feature_SaveSnippet::IsEnabled())
{
auto str = fmt::format(FMT_COMPILE(L"{} commandline: {}"), RS_(L"SaveSnippetNamePrefix"), Commandline());
auto str = fmt::format(FMT_COMPILE(L"{} commandline: {}"), RS_switchable_(L"SaveSnippetNamePrefix"), Commandline());
if (!Name().empty())
{
@@ -959,12 +989,12 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
return color.with_alpha(0) == til::color{};
}
winrt::hstring ColorSelectionArgs::GenerateName() const
winrt::hstring ColorSelectionArgs::GenerateName(const winrt::WARC::ResourceContext& context) const
{
auto matchModeStr = winrt::hstring{};
if (MatchMode() == Core::MatchMode::All)
{
matchModeStr = fmt::format(FMT_COMPILE(L", {}"), RS_(L"ColorSelection_allMatches")); // ", all matches"
matchModeStr = fmt::format(FMT_COMPILE(L", {}"), RS_switchable_(L"ColorSelection_allMatches")); // ", all matches"
}
const auto foreground = Foreground();
@@ -984,44 +1014,44 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
if (foreground && backgroundIsBoring)
{
// "Color selection, foreground: {0}{1}"
return winrt::hstring{ RS_fmt(L"ColorSelection_fg_action", fgStr, matchModeStr) };
return winrt::hstring{ RS_switchable_fmt(L"ColorSelection_fg_action", fgStr, matchModeStr) };
}
else if (background && foregroundIsBoring)
{
// "Color selection, background: {0}{1}"
return winrt::hstring{ RS_fmt(L"ColorSelection_bg_action", bgStr, matchModeStr) };
return winrt::hstring{ RS_switchable_fmt(L"ColorSelection_bg_action", bgStr, matchModeStr) };
}
else if (foreground && background)
{
// "Color selection, foreground: {0}, background: {1}{2}"
return winrt::hstring{ RS_fmt(L"ColorSelection_fg_bg_action", fgStr, bgStr, matchModeStr) };
return winrt::hstring{ RS_switchable_fmt(L"ColorSelection_fg_bg_action", fgStr, bgStr, matchModeStr) };
}
else
{
// "Color selection, (default foreground/background){0}"
return winrt::hstring{ RS_fmt(L"ColorSelection_default_action", matchModeStr) };
return winrt::hstring{ RS_switchable_fmt(L"ColorSelection_default_action", matchModeStr) };
}
}
winrt::hstring SelectOutputArgs::GenerateName() const
winrt::hstring SelectOutputArgs::GenerateName(const winrt::WARC::ResourceContext& context) const
{
switch (Direction())
{
case SelectOutputDirection::Next:
return RS_(L"SelectOutputNextCommandKey");
return RS_switchable_(L"SelectOutputNextCommandKey");
case SelectOutputDirection::Previous:
return RS_(L"SelectOutputPreviousCommandKey");
return RS_switchable_(L"SelectOutputPreviousCommandKey");
}
return {};
}
winrt::hstring SelectCommandArgs::GenerateName() const
winrt::hstring SelectCommandArgs::GenerateName(const winrt::WARC::ResourceContext& context) const
{
switch (Direction())
{
case SelectOutputDirection::Next:
return RS_(L"SelectCommandNextCommandKey");
return RS_switchable_(L"SelectCommandNextCommandKey");
case SelectOutputDirection::Previous:
return RS_(L"SelectCommandPreviousCommandKey");
return RS_switchable_(L"SelectCommandPreviousCommandKey");
}
return {};
}

View File

@@ -59,6 +59,9 @@
#include "TerminalSettingsSerializationHelpers.h"
#include <LibraryResources.h>
#include <ScopedResourceLoader.h>
#include "ActionArgsMagic.h"
#define ACTION_ARG(type, name, ...) \
@@ -336,7 +339,8 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
copy->_Type = _Type;
return *copy;
}
winrt::hstring GenerateName() const
winrt::hstring GenerateName() const { return GenerateName(GetLibraryResourceLoader().ResourceContext()); }
winrt::hstring GenerateName(const winrt::Windows::ApplicationModel::Resources::Core::ResourceContext&) const
{
return winrt::hstring{ L"type: " } + Type();
}
@@ -393,7 +397,8 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
static constexpr std::string_view ContentKey{ "__content" };
public:
hstring GenerateName() const;
hstring GenerateName() const { return GenerateName(GetLibraryResourceLoader().ResourceContext()); }
hstring GenerateName(const winrt::Windows::ApplicationModel::Resources::Core::ResourceContext&) const;
hstring ToCommandline() const;
bool Equals(const Model::INewContentArgs& other)
@@ -592,7 +597,8 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
WINRT_PROPERTY(Model::INewContentArgs, ContentArgs, nullptr);
public:
hstring GenerateName() const;
hstring GenerateName() const { return GenerateName(GetLibraryResourceLoader().ResourceContext()); }
hstring GenerateName(const winrt::Windows::ApplicationModel::Resources::Core::ResourceContext&) const;
bool Equals(const IActionArgs& other)
{
@@ -662,7 +668,8 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
static constexpr std::string_view SplitSizeKey{ "size" };
public:
hstring GenerateName() const;
hstring GenerateName() const { return GenerateName(GetLibraryResourceLoader().ResourceContext()); }
hstring GenerateName(const winrt::Windows::ApplicationModel::Resources::Core::ResourceContext&) const;
bool Equals(const IActionArgs& other)
{
@@ -734,7 +741,8 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
WINRT_PROPERTY(Model::INewContentArgs, ContentArgs, nullptr);
public:
hstring GenerateName() const;
hstring GenerateName() const { return GenerateName(GetLibraryResourceLoader().ResourceContext()); }
hstring GenerateName(const winrt::Windows::ApplicationModel::Resources::Core::ResourceContext&) const;
bool Equals(const IActionArgs& other)
{
@@ -871,7 +879,8 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
static constexpr std::string_view ActionsKey{ "actions" };
public:
hstring GenerateName() const;
hstring GenerateName() const { return GenerateName(GetLibraryResourceLoader().ResourceContext()); }
hstring GenerateName(const winrt::Windows::ApplicationModel::Resources::Core::ResourceContext&) const;
bool Equals(const IActionArgs& other)
{
@@ -964,3 +973,10 @@ namespace winrt::Microsoft::Terminal::Settings::Model::factory_implementation
BASIC_FACTORY(SelectCommandArgs);
BASIC_FACTORY(SelectOutputArgs);
}
class ScopedResourceLoader;
namespace winrt::Microsoft::Terminal::Settings::Model::implementation
{
const ScopedResourceLoader& EnglishOnlyResourceLoader() noexcept;
}

View File

@@ -9,6 +9,7 @@ namespace Microsoft.Terminal.Settings.Model
{
Boolean Equals(IActionArgs other);
String GenerateName();
String GenerateName(Windows.ApplicationModel.Resources.Core.ResourceContext context);
IActionArgs Copy();
UInt64 Hash();
};
@@ -130,6 +131,7 @@ namespace Microsoft.Terminal.Settings.Model
UInt64 Hash();
INewContentArgs Copy();
String GenerateName();
String GenerateName(Windows.ApplicationModel.Resources.Core.ResourceContext context);
};
runtimeclass BaseContentArgs : [default] INewContentArgs {

View File

@@ -111,53 +111,59 @@ struct InitListPlaceholder
// * NewTerminalArgs has a ToCommandline method it needs to additionally declare.
// * GlobalSummonArgs has the QuakeModeFromJson helper
#define ACTION_ARG_BODY(className, argsMacro) \
className() = default; \
className( \
argsMacro(CTOR_PARAMS) InitListPlaceholder = {}) : \
argsMacro(CTOR_INIT) _placeholder{} {}; \
argsMacro(DECLARE_ARGS); \
\
private: \
InitListPlaceholder _placeholder; \
\
public: \
hstring GenerateName() const; \
bool Equals(const IActionArgs& other) \
{ \
auto otherAsUs = other.try_as<className>(); \
if (otherAsUs) \
{ \
return true argsMacro(EQUALS_ARGS); \
} \
return false; \
}; \
static FromJsonResult FromJson(const Json::Value& json) \
{ \
auto args = winrt::make_self<className>(); \
argsMacro(FROM_JSON_ARGS); \
return { *args, {} }; \
} \
static Json::Value ToJson(const IActionArgs& val) \
{ \
if (!val) \
{ \
return {}; \
} \
Json::Value json{ Json::ValueType::objectValue }; \
const auto args{ get_self<className>(val) }; \
argsMacro(TO_JSON_ARGS); \
return json; \
} \
IActionArgs Copy() const \
{ \
auto copy{ winrt::make_self<className>() }; \
argsMacro(COPY_ARGS); \
return *copy; \
} \
size_t Hash() const \
{ \
til::hasher h; \
argsMacro(HASH_ARGS); \
return h.finalize(); \
#define ACTION_ARG_BODY(className, argsMacro) \
className() = default; \
className( \
argsMacro(CTOR_PARAMS) InitListPlaceholder = {}) : \
argsMacro(CTOR_INIT) _placeholder{} {}; \
argsMacro(DECLARE_ARGS); \
\
private: \
InitListPlaceholder _placeholder; \
\
public: \
hstring GenerateName() const \
{ \
return GenerateName( \
GetLibraryResourceLoader().ResourceContext()); \
} \
hstring GenerateName( \
const winrt::Windows::ApplicationModel::Resources::Core::ResourceContext& context) const; \
bool Equals(const IActionArgs& other) \
{ \
auto otherAsUs = other.try_as<className>(); \
if (otherAsUs) \
{ \
return true argsMacro(EQUALS_ARGS); \
} \
return false; \
}; \
static FromJsonResult FromJson(const Json::Value& json) \
{ \
auto args = winrt::make_self<className>(); \
argsMacro(FROM_JSON_ARGS); \
return { *args, {} }; \
} \
static Json::Value ToJson(const IActionArgs& val) \
{ \
if (!val) \
{ \
return {}; \
} \
Json::Value json{ Json::ValueType::objectValue }; \
const auto args{ get_self<className>(val) }; \
argsMacro(TO_JSON_ARGS); \
return json; \
} \
IActionArgs Copy() const \
{ \
auto copy{ winrt::make_self<className>() }; \
argsMacro(COPY_ARGS); \
return *copy; \
} \
size_t Hash() const \
{ \
til::hasher h; \
argsMacro(HASH_ARGS); \
return h.finalize(); \
}

View File

@@ -7,6 +7,7 @@
#include <LibraryResources.h>
#include <til/replace.h>
#include <ScopedResourceLoader.h>
#include "KeyChordSerialization.h"
@@ -169,6 +170,28 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
}
}
hstring Command::LanguageNeutralName() const noexcept
{
if (_name.has_value())
{
// User-specified names **only matter** if they are resource keys (and therefore have a language-neutral version)
if (!_name->resource.empty())
{
// Resource key overrides name
return EnglishOnlyResourceLoader().GetLocalizedString(_name->resource);
}
// ...if there was no resource, then, return nothing.
}
else if (_ActionAndArgs)
{
// generate a name from our action
return get_self<implementation::ActionAndArgs>(_ActionAndArgs)->GenerateName(EnglishOnlyResourceLoader().ResourceContext());
}
// we have no neutral name
return {};
}
hstring Command::ID() const noexcept
{
return hstring{ _ID };

View File

@@ -77,6 +77,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
bool HasName() const noexcept;
hstring Name() const noexcept;
void Name(const hstring& name);
hstring LanguageNeutralName() const noexcept;
hstring ID() const noexcept;
void GenerateID();

View File

@@ -37,6 +37,7 @@ namespace Microsoft.Terminal.Settings.Model
Command();
String Name { get; };
String LanguageNeutralName { get; };
String ID { get; };
String Description { get; };

View File

@@ -27,6 +27,7 @@
#include <wil/registry.h>
#include <winrt/Windows.ApplicationModel.AppExtensions.h>
#include <winrt/Windows.ApplicationModel.Resources.Core.h>
#include <winrt/Windows.ApplicationModel.h>
#include <winrt/Windows.Foundation.Collections.h>
#include <winrt/Windows.Foundation.h>

View File

@@ -13,6 +13,9 @@ public:
ScopedResourceLoader WithQualifier(const wil::zwstring_view qualifierName, const wil::zwstring_view qualifierValue) const;
const winrt::Windows::ApplicationModel::Resources::Core::ResourceMap& ResourceMap() const noexcept { return _resourceMap; }
const winrt::Windows::ApplicationModel::Resources::Core::ResourceContext& ResourceContext() const noexcept { return _resourceContext; }
private:
ScopedResourceLoader(winrt::Windows::ApplicationModel::Resources::Core::ResourceMap map, winrt::Windows::ApplicationModel::Resources::Core::ResourceContext context) noexcept;
winrt::Windows::ApplicationModel::Resources::Core::ResourceMap _resourceMap;