mirror of
https://github.com/microsoft/terminal.git
synced 2026-05-17 15:36:35 +00:00
Compare commits
75 Commits
v1.25.1322
...
dev/cazamo
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
533e48dad6 | ||
|
|
cd25b44158 | ||
|
|
deec76fef8 | ||
|
|
ce1ba031d5 | ||
|
|
21e1e15b65 | ||
|
|
4e87177ac8 | ||
|
|
c55ba1b13c | ||
|
|
4a972cca71 | ||
|
|
0cb802e8a1 | ||
|
|
0227969781 | ||
|
|
cdb9599c96 | ||
|
|
e2b2d46944 | ||
|
|
b0ba0df1d7 | ||
|
|
46b036b151 | ||
|
|
80924f264d | ||
|
|
035b3414bc | ||
|
|
18830be62d | ||
|
|
ed257207c5 | ||
|
|
d62ede4bae | ||
|
|
6557d17048 | ||
|
|
abee0c6c12 | ||
|
|
ac717dc913 | ||
|
|
ffcce7fe03 | ||
|
|
1cd660f250 | ||
|
|
a5a7aeaea3 | ||
|
|
d38cc9af76 | ||
|
|
ca32d58443 | ||
|
|
81ffd975fe | ||
|
|
190008eac6 | ||
|
|
5b617e00ea | ||
|
|
9618831ec7 | ||
|
|
eecb32d297 | ||
|
|
23a04324f8 | ||
|
|
72e9b64e2d | ||
|
|
8d0f947e94 | ||
|
|
63ec868455 | ||
|
|
acad3880d0 | ||
|
|
ce8b31b825 | ||
|
|
ed88c698b1 | ||
|
|
2f6108da6a | ||
|
|
d9738363b7 | ||
|
|
a282164c35 | ||
|
|
8db1805e17 | ||
|
|
27e1aee881 | ||
|
|
5ae13b3e42 | ||
|
|
831313c959 | ||
|
|
2d077ca892 | ||
|
|
3353323880 | ||
|
|
244550044a | ||
|
|
34c6115a59 | ||
|
|
fc0eb78f5f | ||
|
|
debaceee2f | ||
|
|
057128e661 | ||
|
|
36d28e2ba9 | ||
|
|
0fe444e07a | ||
|
|
cc1d632598 | ||
|
|
a7d6e27a48 | ||
|
|
2e7e37ae09 | ||
|
|
f25e6fe2d1 | ||
|
|
e9f83fc4eb | ||
|
|
c371c484a3 | ||
|
|
1072d69fb7 | ||
|
|
b472d9fed9 | ||
|
|
7fcdeaac40 | ||
|
|
2766f21d31 | ||
|
|
0af4eb0e21 | ||
|
|
b0a7ef1d39 | ||
|
|
7cdbb7c795 | ||
|
|
5afc9bc86a | ||
|
|
6b83fa705a | ||
|
|
e6c43c0d4c | ||
|
|
75d02c29bd | ||
|
|
f11515e692 | ||
|
|
7f0c9e5374 | ||
|
|
019bb766db |
@@ -2000,6 +2000,24 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"PaneTheme": {
|
||||
"additionalProperties": false,
|
||||
"description": "A set of properties for customizing the appearance of the panes",
|
||||
"properties": {
|
||||
"activeBorderColor": {
|
||||
"description": "The color of the pane border when the pane is active",
|
||||
"$ref": "#/$defs/ThemeColor"
|
||||
},
|
||||
"inactiveBorderColor": {
|
||||
"description": "The color of the pane border when the pane is inactive",
|
||||
"$ref": "#/$defs/ThemeColor"
|
||||
},
|
||||
"broadcastBorderColor": {
|
||||
"description": "The color of the pane border when broadcasted",
|
||||
"$ref": "#/$defs/ThemeColor"
|
||||
}
|
||||
}
|
||||
},
|
||||
"WindowTheme": {
|
||||
"additionalProperties": false,
|
||||
"description": "A set of properties for customizing the appearance of the window itself",
|
||||
@@ -2056,6 +2074,9 @@
|
||||
},
|
||||
"window": {
|
||||
"$ref": "#/$defs/WindowTheme"
|
||||
},
|
||||
"pane": {
|
||||
"$ref": "#/$defs/PaneTheme"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1292,10 +1292,10 @@ void Pane::UpdateSettings(const CascadiaSettings& settings)
|
||||
// - splitType: How the pane should be attached
|
||||
// Return Value:
|
||||
// - the new reference to the child created from the current pane.
|
||||
std::shared_ptr<Pane> Pane::AttachPane(std::shared_ptr<Pane> pane, SplitDirection splitType)
|
||||
std::shared_ptr<Pane> Pane::AttachPane(std::shared_ptr<Pane> pane, SplitDirection splitType, const float splitSize)
|
||||
{
|
||||
// Splice the new pane into the tree
|
||||
const auto [first, _] = _Split(splitType, .5, pane);
|
||||
const auto [first, _] = _Split(splitType, splitSize, pane);
|
||||
|
||||
// If the new pane has a child that was the focus, re-focus it
|
||||
// to steal focus from the currently focused pane.
|
||||
|
||||
@@ -131,7 +131,8 @@ public:
|
||||
void Close();
|
||||
|
||||
std::shared_ptr<Pane> AttachPane(std::shared_ptr<Pane> pane,
|
||||
winrt::Microsoft::Terminal::Settings::Model::SplitDirection splitType);
|
||||
winrt::Microsoft::Terminal::Settings::Model::SplitDirection splitType,
|
||||
const float splitSize = .5);
|
||||
std::shared_ptr<Pane> DetachPane(std::shared_ptr<Pane> pane);
|
||||
|
||||
int GetLeafPaneCount() const noexcept;
|
||||
|
||||
@@ -77,6 +77,16 @@ namespace winrt::TerminalApp::implementation
|
||||
}
|
||||
const auto settings{ TerminalSettings::CreateWithNewTerminalArgs(_settings, newTerminalArgs, *_bindings) };
|
||||
|
||||
if (profile.Source() == L"Windows.Terminal.InstallPowerShell")
|
||||
{
|
||||
TraceLoggingWrite(
|
||||
g_hTerminalAppProvider,
|
||||
"InstallPowerShellStubInvoked",
|
||||
TraceLoggingDescription("Event emitted when the 'Install Latest PowerShell' stub was invoked"),
|
||||
TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES),
|
||||
TelemetryPrivacyDataTag(PDT_ProductAndServiceUsage));
|
||||
}
|
||||
|
||||
// Try to handle auto-elevation
|
||||
if (_maybeElevate(newTerminalArgs, settings, profile))
|
||||
{
|
||||
|
||||
@@ -132,6 +132,38 @@
|
||||
</ResourceDictionary>
|
||||
</mux:SplitButton.Resources>
|
||||
</mux:SplitButton>
|
||||
<mux:SplitButton x:Name="NewTmuxTabButton"
|
||||
x:Uid="NewTmuxTabSplitButton"
|
||||
Height="24"
|
||||
Margin="0,4"
|
||||
Padding="0"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Stretch"
|
||||
AllowDrop="False"
|
||||
AutomationProperties.AccessibilityView="Control"
|
||||
BorderThickness="0"
|
||||
Content=""
|
||||
FontFamily="{ThemeResource SymbolThemeFontFamily}"
|
||||
FontSize="12"
|
||||
Visibility="Collapsed">
|
||||
<mux:SplitButton.Flyout>
|
||||
<MenuFlyout x:Name="SplitMenu" Placement="BottomEdgeAlignedLeft">
|
||||
<MenuFlyoutItem Text="Horizontal Split">
|
||||
<MenuFlyoutItem.Icon>
|
||||
<FontIcon Glyph="">
|
||||
</FontIcon>
|
||||
</MenuFlyoutItem.Icon>
|
||||
</MenuFlyoutItem>
|
||||
<MenuFlyoutItem Text="Vertical Split">
|
||||
<MenuFlyoutItem.Icon>
|
||||
<FontIcon Glyph="">
|
||||
</FontIcon>
|
||||
</MenuFlyoutItem.Icon>
|
||||
</MenuFlyoutItem>
|
||||
</MenuFlyout>
|
||||
</mux:SplitButton.Flyout>
|
||||
|
||||
</mux:SplitButton>
|
||||
</Grid>
|
||||
</mux:TabView.TabStripFooter>
|
||||
|
||||
|
||||
@@ -177,6 +177,9 @@
|
||||
<ClInclude Include="SettingsPaneContent.h">
|
||||
<DependentUpon>TerminalPaneContent.idl</DependentUpon>
|
||||
</ClInclude>
|
||||
<ClInclude Include="TmuxControl.h">
|
||||
<DependentUpon>TerminalPage.idl</DependentUpon>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Toast.h" />
|
||||
<ClInclude Include="TerminalSettingsCache.h">
|
||||
<DependentUpon>TerminalSettingsCache.idl</DependentUpon>
|
||||
@@ -300,6 +303,9 @@
|
||||
<ClCompile Include="SettingsPaneContent.cpp">
|
||||
<DependentUpon>TerminalPaneContent.idl</DependentUpon>
|
||||
</ClCompile>
|
||||
<ClCompile Include="TmuxControl.cpp">
|
||||
<DependentUpon>TerminalPage.xaml</DependentUpon>
|
||||
</ClCompile>
|
||||
<ClCompile Include="$(GeneratedFilesDir)module.g.cpp" />
|
||||
<ClCompile Include="Toast.cpp" />
|
||||
<ClCompile Include="TerminalSettingsCache.cpp">
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include "ScratchpadContent.h"
|
||||
#include "SnippetsPaneContent.h"
|
||||
#include "MarkdownPaneContent.h"
|
||||
#include "TmuxControl.h"
|
||||
#include "TabRowControl.h"
|
||||
#include "Remoting.h"
|
||||
|
||||
@@ -104,6 +105,8 @@ namespace winrt::TerminalApp::implementation
|
||||
}
|
||||
}
|
||||
_hostingHwnd = hwnd;
|
||||
|
||||
_tmuxControl = std::make_unique<TmuxControl>(*this);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
@@ -3354,6 +3357,9 @@ namespace winrt::TerminalApp::implementation
|
||||
resultPane->ClearActive();
|
||||
original->SetActive();
|
||||
}
|
||||
control.SetTmuxControlHandlerProducer([this, control](auto print) {
|
||||
return _tmuxControl->TmuxControlHandlerProducer(control, print);
|
||||
});
|
||||
|
||||
return resultPane;
|
||||
}
|
||||
@@ -4689,10 +4695,13 @@ namespace winrt::TerminalApp::implementation
|
||||
}
|
||||
|
||||
const auto theme = _settings.GlobalSettings().CurrentTheme();
|
||||
auto requestedTheme{ theme.RequestedTheme() };
|
||||
const auto paneActiveBorderColor = theme.Pane() ? theme.Pane().ActiveBorderColor() : nullptr;
|
||||
const auto paneInactiveBorderColor = theme.Pane() ? theme.Pane().InactiveBorderColor() : nullptr;
|
||||
const auto broadcastBorderColor = theme.Pane() ? theme.Pane().BroadcastBorderColor() : nullptr;
|
||||
const auto requestedTheme{ theme.RequestedTheme() };
|
||||
|
||||
{
|
||||
_updatePaneResources(requestedTheme);
|
||||
_updatePaneResources(requestedTheme, paneActiveBorderColor, paneInactiveBorderColor, broadcastBorderColor);
|
||||
|
||||
for (const auto& tab : _tabs)
|
||||
{
|
||||
@@ -4796,6 +4805,49 @@ namespace winrt::TerminalApp::implementation
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Color TerminalPage::_colorFromKey(const ResourceDictionary& resourceDictionary, const ElementTheme& requestedTheme, const IInspectable& colorKey)
|
||||
{
|
||||
const auto colorFromResources = ThemeLookup(resourceDictionary, requestedTheme, colorKey);
|
||||
// If SystemAccentColor is _not_ a Color for some reason, use
|
||||
// Transparent as the color, so we don't do this process again on
|
||||
// the next pane (by leaving s_focusedBorderBrush nullptr)
|
||||
return winrt::unbox_value_or<Color>(colorFromResources, Colors::Black());
|
||||
}
|
||||
|
||||
Color TerminalPage::_parseThemeColorToColor(
|
||||
const ThemeColor& colorToCopy,
|
||||
const ResourceDictionary& resourceDictionary,
|
||||
const ElementTheme& requestedTheme,
|
||||
const IInspectable& colorKey
|
||||
)
|
||||
{
|
||||
switch (colorToCopy.ColorType())
|
||||
{
|
||||
case ThemeColorType::Accent:
|
||||
return _colorFromKey(resourceDictionary, requestedTheme, colorKey);
|
||||
case ThemeColorType::Color:
|
||||
const auto rawColor = colorToCopy.Color();
|
||||
return Color{
|
||||
rawColor.A,
|
||||
rawColor.R,
|
||||
rawColor.G,
|
||||
rawColor.B
|
||||
};
|
||||
case ThemeColorType::TerminalBackground:
|
||||
const auto terminalBg = ThemeColor::FromTerminalBackground().Color();
|
||||
return Color{
|
||||
terminalBg.A,
|
||||
terminalBg.R,
|
||||
terminalBg.G,
|
||||
terminalBg.B
|
||||
};
|
||||
default:
|
||||
assert(false && "unknown type for color type in theme color"); // should never be reached
|
||||
return winrt::Windows::UI::Color{};
|
||||
}
|
||||
}
|
||||
|
||||
// Function Description:
|
||||
// - Attempts to load some XAML resources that Panes will need. This includes:
|
||||
// * The Color they'll use for active Panes's borders - SystemAccentColor
|
||||
@@ -4803,60 +4855,56 @@ namespace winrt::TerminalApp::implementation
|
||||
// color of the titlebar)
|
||||
// Arguments:
|
||||
// - requestedTheme: this should be the currently active Theme for the app
|
||||
// - activeBorderColor: the pane's border color for the application when it is active
|
||||
// - inactiveBorderColor: the pane's border color for the application when it is inactive
|
||||
// - broadcastBorderColor: the pane's border color for the application when it is broadcast
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void TerminalPage::_updatePaneResources(const winrt::Windows::UI::Xaml::ElementTheme& requestedTheme)
|
||||
void TerminalPage::_updatePaneResources(const ElementTheme& requestedTheme, const ThemeColor& activeBorderColor, const ThemeColor& inactiveBorderColor, const ThemeColor& broadcastBorderColor)
|
||||
{
|
||||
const auto res = Application::Current().Resources();
|
||||
const auto accentColorKey = winrt::box_value(L"SystemAccentColor");
|
||||
auto activeBrushColor = Colors::Black(), inactiveBrushColor = Colors::Black(), broadcastBrushColor = Colors::Black();
|
||||
if (res.HasKey(accentColorKey))
|
||||
{
|
||||
const auto colorFromResources = ThemeLookup(res, requestedTheme, accentColorKey);
|
||||
// If SystemAccentColor is _not_ a Color for some reason, use
|
||||
// Transparent as the color, so we don't do this process again on
|
||||
// the next pane (by leaving s_focusedBorderBrush nullptr)
|
||||
auto actualColor = winrt::unbox_value_or<Color>(colorFromResources, Colors::Black());
|
||||
_paneResources.focusedBorderBrush = SolidColorBrush(actualColor);
|
||||
activeBrushColor = _colorFromKey(res, requestedTheme, accentColorKey);
|
||||
}
|
||||
else
|
||||
// Overwrites the accent above (or the black default color if there was no accent color)
|
||||
if (activeBorderColor)
|
||||
{
|
||||
// DON'T use Transparent here - if it's "Transparent", then it won't
|
||||
// be able to hittest for clicks, and then clicking on the border
|
||||
// will eat focus.
|
||||
_paneResources.focusedBorderBrush = SolidColorBrush{ Colors::Black() };
|
||||
activeBrushColor = _parseThemeColorToColor(activeBorderColor, res, requestedTheme, accentColorKey);
|
||||
}
|
||||
|
||||
// DON'T use Transparent here - if it's "Transparent", then it won't
|
||||
// be able to hittest for clicks, and then clicking on the border
|
||||
// will eat focus.
|
||||
_paneResources.focusedBorderBrush = SolidColorBrush(activeBrushColor);
|
||||
const auto unfocusedBorderBrushKey = winrt::box_value(L"UnfocusedBorderBrush");
|
||||
if (res.HasKey(unfocusedBorderBrushKey))
|
||||
{
|
||||
// MAKE SURE TO USE ThemeLookup, so that we get the correct resource for
|
||||
// the requestedTheme, not just the value from the resources (which
|
||||
// might not respect the settings' requested theme)
|
||||
auto obj = ThemeLookup(res, requestedTheme, unfocusedBorderBrushKey);
|
||||
_paneResources.unfocusedBorderBrush = obj.try_as<winrt::Windows::UI::Xaml::Media::SolidColorBrush>();
|
||||
inactiveBrushColor = _colorFromKey(res, requestedTheme, unfocusedBorderBrushKey);
|
||||
}
|
||||
else
|
||||
// Overwrites the above (or the black default color if there was no unfocusedBorderBrushKey)
|
||||
if (inactiveBorderColor)
|
||||
{
|
||||
// DON'T use Transparent here - if it's "Transparent", then it won't
|
||||
// be able to hittest for clicks, and then clicking on the border
|
||||
// will eat focus.
|
||||
_paneResources.unfocusedBorderBrush = SolidColorBrush{ Colors::Black() };
|
||||
inactiveBrushColor = _parseThemeColorToColor(inactiveBorderColor, res, requestedTheme, unfocusedBorderBrushKey);
|
||||
}
|
||||
|
||||
// DON'T use Transparent here - if it's "Transparent", then it won't
|
||||
// be able to hittest for clicks, and then clicking on the border
|
||||
// will eat focus.
|
||||
_paneResources.unfocusedBorderBrush = SolidColorBrush(inactiveBrushColor);
|
||||
const auto broadcastColorKey = winrt::box_value(L"BroadcastPaneBorderColor");
|
||||
if (res.HasKey(broadcastColorKey))
|
||||
{
|
||||
// MAKE SURE TO USE ThemeLookup
|
||||
auto obj = ThemeLookup(res, requestedTheme, broadcastColorKey);
|
||||
_paneResources.broadcastBorderBrush = obj.try_as<winrt::Windows::UI::Xaml::Media::SolidColorBrush>();
|
||||
_colorFromKey(res, requestedTheme, broadcastColorKey);
|
||||
}
|
||||
else
|
||||
if (broadcastBorderColor)
|
||||
{
|
||||
// DON'T use Transparent here - if it's "Transparent", then it won't
|
||||
// be able to hittest for clicks, and then clicking on the border
|
||||
// will eat focus.
|
||||
_paneResources.broadcastBorderBrush = SolidColorBrush{ Colors::Black() };
|
||||
broadcastBrushColor = _parseThemeColorToColor(broadcastBorderColor, res, requestedTheme, broadcastColorKey);
|
||||
}
|
||||
// DON'T use Transparent here - if it's "Transparent", then it won't
|
||||
// be able to hittest for clicks, and then clicking on the border
|
||||
// will eat focus.
|
||||
_paneResources.broadcastBorderBrush = SolidColorBrush(broadcastBrushColor);
|
||||
}
|
||||
|
||||
void TerminalPage::WindowActivated(const bool activated)
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "RenameWindowRequestedArgs.g.h"
|
||||
#include "RequestMoveContentArgs.g.h"
|
||||
#include "LaunchPositionRequest.g.h"
|
||||
#include "TmuxControl.h"
|
||||
#include "Toast.h"
|
||||
|
||||
#include "WindowsPackageManagerFactory.h"
|
||||
@@ -245,6 +246,7 @@ namespace winrt::TerminalApp::implementation
|
||||
std::vector<std::vector<Microsoft::Terminal::Settings::Model::ActionAndArgs>> _previouslyClosedPanesAndTabs{};
|
||||
|
||||
uint32_t _systemRowsToScroll{ DefaultRowsToScroll };
|
||||
std::unique_ptr<TmuxControl> _tmuxControl{ nullptr };
|
||||
|
||||
// use a weak reference to prevent circular dependency with AppLogic
|
||||
winrt::weak_ref<winrt::TerminalApp::IDialogPresenter> _dialogPresenter;
|
||||
@@ -519,7 +521,9 @@ namespace winrt::TerminalApp::implementation
|
||||
|
||||
void _updateThemeColors();
|
||||
void _updateAllTabCloseButtons();
|
||||
void _updatePaneResources(const winrt::Windows::UI::Xaml::ElementTheme& requestedTheme);
|
||||
winrt::Windows::UI::Color _colorFromKey(const winrt::Windows::UI::Xaml::ResourceDictionary& resourceDictionary, const winrt::Windows::UI::Xaml::ElementTheme& requestedTheme, const winrt::Windows::Foundation::IInspectable& colorKey);
|
||||
winrt::Windows::UI::Color _parseThemeColorToColor(const winrt::Microsoft::Terminal::Settings::Model::ThemeColor& colorToCopy, const winrt::Windows::UI::Xaml::ResourceDictionary& resourceDictionary, const winrt::Windows::UI::Xaml::ElementTheme& requestedTheme, const winrt::Windows::Foundation::IInspectable& colorKey);
|
||||
void _updatePaneResources(const winrt::Windows::UI::Xaml::ElementTheme& requestedTheme, const winrt::Microsoft::Terminal::Settings::Model::ThemeColor& activeBorderColor, const winrt::Microsoft::Terminal::Settings::Model::ThemeColor& inactiveBorderColor, const winrt::Microsoft::Terminal::Settings::Model::ThemeColor& broadcastBorderColor);
|
||||
|
||||
safe_void_coroutine _ControlCompletionsChangedHandler(const winrt::Windows::Foundation::IInspectable sender, const winrt::Microsoft::Terminal::Control::CompletionsChangedEventArgs args);
|
||||
|
||||
@@ -565,6 +569,7 @@ namespace winrt::TerminalApp::implementation
|
||||
|
||||
friend class TerminalAppLocalTests::TabTests;
|
||||
friend class TerminalAppLocalTests::SettingsTests;
|
||||
friend class TmuxControl;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
1330
src/cascadia/TerminalApp/TmuxControl.cpp
Normal file
1330
src/cascadia/TerminalApp/TmuxControl.cpp
Normal file
File diff suppressed because it is too large
Load Diff
384
src/cascadia/TerminalApp/TmuxControl.h
Normal file
384
src/cascadia/TerminalApp/TmuxControl.h
Normal file
@@ -0,0 +1,384 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <regex>
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
#include <functional>
|
||||
|
||||
#include "Pane.h"
|
||||
|
||||
namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
struct TerminalPage;
|
||||
|
||||
class TmuxControl
|
||||
{
|
||||
using StringHandler = std::function<bool(const wchar_t)>;
|
||||
using PrintHandler = std::function<void(const std::wstring_view)>;
|
||||
using StringHandlerProducer = std::function<StringHandler(PrintHandler)>;
|
||||
using SplitDirection = winrt::Microsoft::Terminal::Settings::Model::SplitDirection;
|
||||
|
||||
public:
|
||||
TmuxControl(TerminalPage& page);
|
||||
StringHandler TmuxControlHandlerProducer(const winrt::Microsoft::Terminal::Control::TermControl control, const PrintHandler print);
|
||||
|
||||
private:
|
||||
static const std::wregex REG_BEGIN;
|
||||
static const std::wregex REG_END;
|
||||
static const std::wregex REG_ERROR;
|
||||
|
||||
static const std::wregex REG_CLIENT_SESSION_CHANGED;
|
||||
static const std::wregex REG_CLIENT_DETACHED;
|
||||
static const std::wregex REG_CONFIG_ERROR;
|
||||
static const std::wregex REG_CONTINUE;
|
||||
static const std::wregex REG_DETACH;
|
||||
static const std::wregex REG_EXIT;
|
||||
static const std::wregex REG_EXTENDED_OUTPUT;
|
||||
static const std::wregex REG_LAYOUT_CHANGED;
|
||||
static const std::wregex REG_MESSAGE;
|
||||
static const std::wregex REG_OUTPUT;
|
||||
static const std::wregex REG_PANE_MODE_CHANGED;
|
||||
static const std::wregex REG_PASTE_BUFFER_CHANGED;
|
||||
static const std::wregex REG_PASTE_BUFFER_DELETED;
|
||||
static const std::wregex REG_PAUSE;
|
||||
static const std::wregex REG_SESSION_CHANGED;
|
||||
static const std::wregex REG_SESSION_RENAMED;
|
||||
static const std::wregex REG_SESSION_WINDOW_CHANGED;
|
||||
static const std::wregex REG_SESSIONS_CHANGED;
|
||||
static const std::wregex REG_SUBSCRIPTION_CHANGED;
|
||||
static const std::wregex REG_UNLINKED_WINDOW_ADD;
|
||||
static const std::wregex REG_UNLINKED_WINDOW_CLOSE;
|
||||
static const std::wregex REG_UNLINKED_WINDOW_RENAMED;
|
||||
static const std::wregex REG_WINDOW_ADD;
|
||||
static const std::wregex REG_WINDOW_CLOSE;
|
||||
static const std::wregex REG_WINDOW_PANE_CHANGED;
|
||||
static const std::wregex REG_WINDOW_RENAMED;
|
||||
|
||||
enum State : int
|
||||
{
|
||||
INIT,
|
||||
ATTACHING,
|
||||
ATTACHED,
|
||||
} _state{ INIT };
|
||||
|
||||
enum CommandState : int
|
||||
{
|
||||
READY,
|
||||
WAITING,
|
||||
} _cmdState{ READY };
|
||||
|
||||
enum EventType : int
|
||||
{
|
||||
BEGIN,
|
||||
END,
|
||||
ERR,
|
||||
|
||||
ATTACH,
|
||||
DETACH,
|
||||
CLIENT_SESSION_CHANGED,
|
||||
CLIENT_DETACHED,
|
||||
CONFIG_ERROR,
|
||||
CONTINUE,
|
||||
EXIT,
|
||||
EXTENEDED_OUTPUT,
|
||||
LAYOUT_CHANGED,
|
||||
NOTHING,
|
||||
MESSAGE,
|
||||
OUTPUT,
|
||||
PANE_MODE_CHANGED,
|
||||
PASTE_BUFFER_CHANGED,
|
||||
PASTE_BUFFER_DELETED,
|
||||
PAUSE,
|
||||
RESPONSE,
|
||||
SESSION_CHANGED,
|
||||
SESSION_RENAMED,
|
||||
SESSION_WINDOW_CHANGED,
|
||||
SESSIONS_CHANGED,
|
||||
SUBSCRIPTION_CHANGED,
|
||||
UNLINKED_WINDOW_ADD,
|
||||
UNLINKED_WINDOW_CLOSE,
|
||||
UNLINKED_WINDOW_RENAMED,
|
||||
WINDOW_ADD,
|
||||
WINDOW_CLOSE,
|
||||
WINDOW_PANE_CHANGED,
|
||||
WINDOW_RENAMED,
|
||||
};
|
||||
|
||||
struct Event
|
||||
{
|
||||
EventType type{ NOTHING };
|
||||
int sessionId{ -1 };
|
||||
int windowId{ -1 };
|
||||
int paneId{ -1 };
|
||||
|
||||
std::wstring response;
|
||||
} _event;
|
||||
|
||||
// Command structs
|
||||
struct Command
|
||||
{
|
||||
public:
|
||||
virtual std::wstring GetCommand() = 0;
|
||||
virtual bool ResultHandler(const std::wstring& /*result*/, TmuxControl& /*tmux*/) { return true; };
|
||||
};
|
||||
|
||||
struct AttachDone : public Command
|
||||
{
|
||||
public:
|
||||
std::wstring GetCommand() override;
|
||||
bool ResultHandler(const std::wstring& result, TmuxControl& tmux) override;
|
||||
};
|
||||
|
||||
struct CapturePane : public Command
|
||||
{
|
||||
public:
|
||||
std::wstring GetCommand() override;
|
||||
bool ResultHandler(const std::wstring& result, TmuxControl& tmux) override;
|
||||
|
||||
int paneId{ -1 };
|
||||
int cursorX{ 0 };
|
||||
int cursorY{ 0 };
|
||||
int history{ 0 };
|
||||
};
|
||||
|
||||
struct DiscoverPanes : public Command {
|
||||
public:
|
||||
std::wstring GetCommand() override;
|
||||
bool ResultHandler(const std::wstring& result, TmuxControl& tmux) override;
|
||||
|
||||
int sessionId{ -1 };
|
||||
int windowId{ -1 };
|
||||
bool newWindow{ false };
|
||||
};
|
||||
|
||||
struct DiscoverWindows : public Command {
|
||||
public:
|
||||
std::wstring GetCommand() override;
|
||||
bool ResultHandler(const std::wstring& result, TmuxControl& tmux) override;
|
||||
|
||||
int sessionId{ -1 };
|
||||
};
|
||||
|
||||
struct ListPanes : public Command
|
||||
{
|
||||
public:
|
||||
std::wstring GetCommand() override;
|
||||
bool ResultHandler(const std::wstring& result, TmuxControl& tmux) override;
|
||||
|
||||
int windowId{ -1 };
|
||||
int history{ 2000 };
|
||||
};
|
||||
|
||||
struct ListWindow : public Command {
|
||||
public:
|
||||
std::wstring GetCommand() override;
|
||||
bool ResultHandler(const std::wstring& result, TmuxControl& tmux) override;
|
||||
|
||||
int windowId{ -1 };
|
||||
int sessionId{ -1 };
|
||||
};
|
||||
|
||||
struct NewWindow : public Command
|
||||
{
|
||||
public:
|
||||
std::wstring GetCommand() override;
|
||||
};
|
||||
|
||||
struct ResizePane : public Command
|
||||
{
|
||||
public:
|
||||
std::wstring GetCommand() override;
|
||||
|
||||
int width{ 0 };
|
||||
int height{ 0 };
|
||||
int paneId{ -1 };
|
||||
};
|
||||
|
||||
struct ResizeWindow : public Command
|
||||
{
|
||||
public:
|
||||
std::wstring GetCommand() override;
|
||||
int width{ 0 };
|
||||
int height{ 0 };
|
||||
int windowId{ -1 };
|
||||
};
|
||||
|
||||
struct SelectWindow : public Command
|
||||
{
|
||||
public:
|
||||
std::wstring GetCommand() override;
|
||||
|
||||
int windowId{ -1 };
|
||||
};
|
||||
|
||||
struct SelectPane : public Command
|
||||
{
|
||||
public:
|
||||
std::wstring GetCommand() override;
|
||||
|
||||
int paneId{ -1 };
|
||||
};
|
||||
|
||||
struct SendKey : public Command
|
||||
{
|
||||
public:
|
||||
std::wstring GetCommand() override;
|
||||
|
||||
int paneId{ -1 };
|
||||
std::wstring keys;
|
||||
wchar_t key{ '\0' };
|
||||
};
|
||||
|
||||
struct SetOption : public Command
|
||||
{
|
||||
public:
|
||||
std::wstring GetCommand() override;
|
||||
|
||||
std::wstring option;
|
||||
};
|
||||
|
||||
struct SplitPane : public Command
|
||||
{
|
||||
public:
|
||||
std::wstring GetCommand() override;
|
||||
|
||||
int paneId{ -1 };
|
||||
SplitDirection direction{ SplitDirection::Left };
|
||||
};
|
||||
|
||||
// Layout structs
|
||||
enum TmuxLayoutType : int
|
||||
{
|
||||
SIGNLE_PANE,
|
||||
SPLIT_HORIZONTAL,
|
||||
SPLIT_VERTICAL,
|
||||
};
|
||||
|
||||
struct TmuxPaneLayout
|
||||
{
|
||||
int width;
|
||||
int height;
|
||||
int left;
|
||||
int top;
|
||||
int id;
|
||||
};
|
||||
|
||||
struct TmuxWindowLayout
|
||||
{
|
||||
TmuxLayoutType type{ SIGNLE_PANE };
|
||||
std::vector<TmuxPaneLayout> panes;
|
||||
};
|
||||
|
||||
struct TmuxWindow
|
||||
{
|
||||
int sessionId{ -1 };
|
||||
int windowId{ -1 };
|
||||
int width{ 0 };
|
||||
int height{ 0 };
|
||||
int history{ 2000 };
|
||||
bool active{ false };
|
||||
std::wstring name;
|
||||
std::wstring layoutCsum;
|
||||
std::vector<TmuxWindowLayout> layout;
|
||||
};
|
||||
|
||||
struct TmuxPane
|
||||
{
|
||||
int sessionId;
|
||||
int windowId;
|
||||
int paneId;
|
||||
int cursorX;
|
||||
int cursorY;
|
||||
bool active;
|
||||
};
|
||||
|
||||
struct AttachedPane
|
||||
{
|
||||
int windowId;
|
||||
int paneId;
|
||||
winrt::Microsoft::Terminal::Control::TermControl control;
|
||||
bool initilized { false };
|
||||
};
|
||||
|
||||
// Private methods
|
||||
void _AttachSession();
|
||||
void _DetachSession();
|
||||
void _SetupProfile();
|
||||
|
||||
float _ComputeSplitSize(int newSize, int originSize, SplitDirection direction) const;
|
||||
TerminalApp::TerminalTab _GetTab(int windowId) const;
|
||||
|
||||
void _SendOutput(int paneId, const std::wstring& text);
|
||||
void _Output(int paneId, const std::wstring& result);
|
||||
void _CloseWindow(int windowId);
|
||||
void _RenameWindow(int windowId, const std::wstring& name);
|
||||
void _NewWindowFinalize(int windowId, int paneId, const std::wstring& windowName);
|
||||
void _SplitPaneFinalize(int windowId, int paneId);
|
||||
std::shared_ptr<Pane> _NewPane(int windowId, int paneId);
|
||||
|
||||
bool _SyncPaneState(std::vector<TmuxPane> panes, int history);
|
||||
bool _SyncWindowState(std::vector<TmuxWindow> windows);
|
||||
std::vector<TmuxWindowLayout> _ParseTmuxWindowLayout(std::wstring& layout);
|
||||
|
||||
void _EventHandler(const Event& e);
|
||||
void _Parse(const std::wstring& buffer);
|
||||
bool _Advance(wchar_t ch);
|
||||
|
||||
// Tmux command methods
|
||||
void _AttachDone();
|
||||
void _CapturePane(int paneId, int cursorX, int cursorY, int history);
|
||||
void _DiscoverPanes(int sessionId, int windowId, bool newWindow);
|
||||
void _DiscoverWindows(int sessionId);
|
||||
void _ListWindow(int sessionId, int windowId);
|
||||
void _ListPanes(int windowId, int history);
|
||||
void _NewWindow();
|
||||
void _ResizePane(int paneId, int width, int height);
|
||||
void _ResizeWindow(int windowId, int width, int height);
|
||||
void _SelectPane(int paneId);
|
||||
void _SelectWindow(int windowId);
|
||||
void _SendKey(int paneId, const std::wstring keys);
|
||||
void _SetOption(const std::wstring& option);
|
||||
void _SplitPane(SplitDirection direction);
|
||||
|
||||
void _CommandHandler(const std::wstring& result);
|
||||
void _SendCommand(std::unique_ptr<Command> cmd);
|
||||
void _ScheduleCommand();
|
||||
|
||||
// Private variables
|
||||
TerminalPage& _page;
|
||||
winrt::Microsoft::Terminal::Settings::Model::Profile _profile;
|
||||
winrt::Microsoft::Terminal::Control::TermControl _control { nullptr };
|
||||
winrt::Windows::System::DispatcherQueue _dispatcherQueue{ nullptr };
|
||||
|
||||
winrt::event_token _detachKeyDownRevoker;
|
||||
winrt::event_token _windowSizeChangedRevoker;
|
||||
|
||||
std::vector<wchar_t> _dcsBuffer;
|
||||
std::deque<std::unique_ptr<TmuxControl::Command>> _cmdQueue;
|
||||
std::unordered_map<int, AttachedPane> _attachedPanes;
|
||||
std::unordered_map<int, TerminalApp::TerminalTab> _attachedWindows;
|
||||
std::unordered_map<int, std::wstring> _outputBacklog;
|
||||
|
||||
int _sessionId{ -1 };
|
||||
|
||||
int _terminalWidth{ 0 };
|
||||
int _terminalHeight{ 0 };
|
||||
|
||||
float _fontWidth{ 0 };
|
||||
float _fontHeight{ 0 };
|
||||
|
||||
::winrt::Windows::UI::Xaml::Thickness _thickness{ 0,0,0,0 };
|
||||
|
||||
std::pair<int, SplitDirection> _splittingPane{-1, SplitDirection::Right};
|
||||
|
||||
int _activePaneId{ -1 };
|
||||
int _activeWindowId{ -1 };
|
||||
|
||||
std::function<void(const std::wstring_view string)> _Print;
|
||||
bool _inUse { false };
|
||||
std::mutex _inUseMutex;
|
||||
};
|
||||
}
|
||||
29
src/cascadia/TerminalConnection/DumyConnection.cpp
Normal file
29
src/cascadia/TerminalConnection/DumyConnection.cpp
Normal file
@@ -0,0 +1,29 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#include "pch.h"
|
||||
#include "DumyConnection.h"
|
||||
#include <sstream>
|
||||
|
||||
#include "DumyConnection.g.cpp"
|
||||
|
||||
namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
||||
{
|
||||
DumyConnection::DumyConnection() noexcept = default;
|
||||
|
||||
void DumyConnection::Start() noexcept
|
||||
{
|
||||
}
|
||||
|
||||
void DumyConnection::WriteInput(const winrt::array_view<const char16_t> /*buffer*/)
|
||||
{
|
||||
}
|
||||
|
||||
void DumyConnection::Resize(uint32_t /*rows*/, uint32_t /*columns*/) noexcept
|
||||
{
|
||||
}
|
||||
|
||||
void DumyConnection::Close() noexcept
|
||||
{
|
||||
}
|
||||
}
|
||||
34
src/cascadia/TerminalConnection/DumyConnection.h
Normal file
34
src/cascadia/TerminalConnection/DumyConnection.h
Normal file
@@ -0,0 +1,34 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "DumyConnection.g.h"
|
||||
|
||||
namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
||||
{
|
||||
struct DumyConnection : DumyConnectionT<DumyConnection>
|
||||
{
|
||||
DumyConnection() noexcept;
|
||||
|
||||
void Start() noexcept;
|
||||
void WriteInput(const winrt::array_view<const char16_t> buffer);
|
||||
void Resize(uint32_t rows, uint32_t columns) noexcept;
|
||||
void Close() noexcept;
|
||||
|
||||
void Initialize(const Windows::Foundation::Collections::ValueSet& /*settings*/) const noexcept {};
|
||||
|
||||
winrt::guid SessionId() const noexcept { return {}; }
|
||||
ConnectionState State() const noexcept { return ConnectionState::Connected; }
|
||||
|
||||
til::event<TerminalOutputHandler> TerminalOutput;
|
||||
til::typed_event<ITerminalConnection, IInspectable> StateChanged;
|
||||
|
||||
bool _rawMode { false };
|
||||
};
|
||||
}
|
||||
|
||||
namespace winrt::Microsoft::Terminal::TerminalConnection::factory_implementation
|
||||
{
|
||||
BASIC_FACTORY(DumyConnection);
|
||||
}
|
||||
14
src/cascadia/TerminalConnection/DumyConnection.idl
Normal file
14
src/cascadia/TerminalConnection/DumyConnection.idl
Normal file
@@ -0,0 +1,14 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import "ITerminalConnection.idl";
|
||||
|
||||
namespace Microsoft.Terminal.TerminalConnection
|
||||
{
|
||||
[default_interface]
|
||||
runtimeclass DumyConnection : ITerminalConnection
|
||||
{
|
||||
DumyConnection();
|
||||
};
|
||||
|
||||
}
|
||||
@@ -32,6 +32,9 @@
|
||||
<ClInclude Include="EchoConnection.h">
|
||||
<DependentUpon>EchoConnection.idl</DependentUpon>
|
||||
</ClInclude>
|
||||
<ClInclude Include="DumyConnection.h">
|
||||
<DependentUpon>DumyConnection.idl</DependentUpon>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="CTerminalHandoff.cpp" />
|
||||
@@ -48,6 +51,9 @@
|
||||
<ClCompile Include="EchoConnection.cpp">
|
||||
<DependentUpon>EchoConnection.idl</DependentUpon>
|
||||
</ClCompile>
|
||||
<ClCompile Include="DumyConnection.cpp">
|
||||
<DependentUpon>DumyConnection.idl</DependentUpon>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ConptyConnection.cpp">
|
||||
<DependentUpon>ConptyConnection.idl</DependentUpon>
|
||||
</ClCompile>
|
||||
@@ -58,6 +64,7 @@
|
||||
<Midl Include="ITerminalConnection.idl" />
|
||||
<Midl Include="ConptyConnection.idl" />
|
||||
<Midl Include="EchoConnection.idl" />
|
||||
<Midl Include="DumyConnection.idl" />
|
||||
<Midl Include="AzureConnection.idl" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
@@ -98,4 +105,4 @@
|
||||
<Import Project="$(SolutionDir)build\rules\CollectWildcardResources.targets" />
|
||||
<!-- This -must- go after cppwinrt.build.post.props because that includes many VS-provided props including appcontainer.common.props, which stomps on what cppwinrt.targets did. -->
|
||||
<Import Project="$(OpenConsoleDir)src\common.nugetversions.targets" />
|
||||
</Project>
|
||||
</Project>
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
<ItemGroup>
|
||||
<ClCompile Include="pch.cpp" />
|
||||
<ClCompile Include="EchoConnection.cpp" />
|
||||
<ClCompile Include="DumyConnection.cpp" />
|
||||
<ClCompile Include="$(GeneratedFilesDir)module.g.cpp" />
|
||||
<ClCompile Include="AzureConnection.cpp" />
|
||||
<ClCompile Include="init.cpp" />
|
||||
@@ -23,6 +24,7 @@
|
||||
<ItemGroup>
|
||||
<ClInclude Include="pch.h" />
|
||||
<ClInclude Include="EchoConnection.h" />
|
||||
<ClInclude Include="DumyConnection.h" />
|
||||
<ClInclude Include="AzureConnection.h" />
|
||||
<ClInclude Include="AzureClientID.h" />
|
||||
<ClInclude Include="CTerminalHandoff.h" />
|
||||
@@ -31,6 +33,7 @@
|
||||
<ItemGroup>
|
||||
<Midl Include="ITerminalConnection.idl" />
|
||||
<Midl Include="EchoConnection.idl" />
|
||||
<Midl Include="DumyConnection.idl" />
|
||||
<Midl Include="AzureConnection.idl" />
|
||||
<Midl Include="ConptyConnection.idl" />
|
||||
<Midl Include="ConnectionInformation.idl" />
|
||||
@@ -42,4 +45,4 @@
|
||||
<ItemGroup>
|
||||
<PRIResource Include="Resources\en-US\Resources.resw" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
|
||||
@@ -478,6 +478,17 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
}
|
||||
}
|
||||
|
||||
void ControlCore::SendOutput(const std::wstring_view wstr)
|
||||
{
|
||||
if (wstr.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = _terminal->LockForWriting();
|
||||
_terminal->Write(wstr);
|
||||
}
|
||||
|
||||
bool ControlCore::SendCharEvent(const wchar_t ch,
|
||||
const WORD scanCode,
|
||||
const ::Microsoft::Terminal::Core::ControlKeyStates modifiers)
|
||||
@@ -1565,6 +1576,16 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
return _terminal->GetViewport().Height();
|
||||
}
|
||||
|
||||
// Function Description:
|
||||
// - Gets the width of the terminal in lines of text. This is just the
|
||||
// widht of the viewport.
|
||||
// Return Value:
|
||||
// - The width of the terminal in lines of text
|
||||
int ControlCore::ViewWidth() const
|
||||
{
|
||||
const auto lock = _terminal->LockForReading();
|
||||
return _terminal->GetViewport().Width();
|
||||
}
|
||||
// Function Description:
|
||||
// - Gets the height of the terminal in lines of text. This includes the
|
||||
// history AND the viewport.
|
||||
@@ -2990,4 +3011,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
{
|
||||
_terminal->PreviewText(input);
|
||||
}
|
||||
|
||||
void ControlCore::SetTmuxControlHandlerProducer(ITermDispatch::StringHandlerProducer producer)
|
||||
{
|
||||
_terminal->SetTmuxControlHandlerProducer(producer);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "../../buffer/out/search.h"
|
||||
#include "../../cascadia/TerminalCore/Terminal.hpp"
|
||||
#include "../../renderer/inc/FontInfoDesired.hpp"
|
||||
#include "../../terminal/adapter/ITermDispatch.hpp"
|
||||
|
||||
namespace Microsoft::Console::Render::Atlas
|
||||
{
|
||||
@@ -41,6 +42,8 @@ namespace ControlUnitTests
|
||||
class ControlInteractivityTests;
|
||||
};
|
||||
|
||||
using Microsoft::Console::VirtualTerminal::ITermDispatch;
|
||||
|
||||
#define RUNTIME_SETTING(type, name, setting) \
|
||||
private: \
|
||||
std::optional<type> _runtime##name{ std::nullopt }; \
|
||||
@@ -122,6 +125,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
til::color BackgroundColor() const;
|
||||
|
||||
void SendInput(std::wstring_view wstr);
|
||||
void SendOutput(std::wstring_view wstr);
|
||||
void PasteText(const winrt::hstring& hstr);
|
||||
bool CopySelectionToClipboard(bool singleLine, bool withControlSequences, const Windows::Foundation::IReference<CopyFormat>& formats);
|
||||
void SelectAll();
|
||||
@@ -171,6 +175,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
|
||||
int ScrollOffset();
|
||||
int ViewHeight() const;
|
||||
int ViewWidth() const;
|
||||
int BufferHeight() const;
|
||||
|
||||
bool HasSelection() const;
|
||||
@@ -266,6 +271,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
bool ShouldShowSelectOutput();
|
||||
|
||||
void PreviewInput(std::wstring_view input);
|
||||
void SetTmuxControlHandlerProducer(ITermDispatch::StringHandlerProducer producer);
|
||||
|
||||
RUNTIME_SETTING(float, Opacity, _settings->Opacity());
|
||||
RUNTIME_SETTING(float, FocusedOpacity, FocusedAppearance().Opacity());
|
||||
@@ -451,6 +457,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
friend class ControlUnitTests::ControlInteractivityTests;
|
||||
bool _inUnitTests{ false };
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
namespace winrt::Microsoft::Terminal::Control::factory_implementation
|
||||
|
||||
@@ -67,6 +67,10 @@ namespace Microsoft.Terminal.Control
|
||||
Boolean SearchRegexInvalid;
|
||||
};
|
||||
|
||||
delegate Boolean TmuxDCSHandler(Char ch);
|
||||
delegate void PrintHandler(String str);
|
||||
delegate TmuxDCSHandler TmuxDCSHandlerProducer(PrintHandler print);
|
||||
|
||||
[default_interface] runtimeclass SelectionColor
|
||||
{
|
||||
SelectionColor();
|
||||
@@ -121,6 +125,7 @@ namespace Microsoft.Terminal.Control
|
||||
Int16 scanCode,
|
||||
Microsoft.Terminal.Core.ControlKeyStates modifiers);
|
||||
void SendInput(String text);
|
||||
void SendOutput(String text);
|
||||
void PasteText(String text);
|
||||
void SelectAll();
|
||||
void ClearSelection();
|
||||
@@ -179,6 +184,7 @@ namespace Microsoft.Terminal.Control
|
||||
Boolean ShouldShowSelectOutput();
|
||||
|
||||
void OpenCWD();
|
||||
void SetTmuxControlHandlerProducer(TmuxDCSHandlerProducer producer);
|
||||
|
||||
void ClearQuickFix();
|
||||
|
||||
|
||||
@@ -40,6 +40,7 @@ namespace Microsoft.Terminal.Control
|
||||
|
||||
Int32 ScrollOffset { get; };
|
||||
Int32 ViewHeight { get; };
|
||||
Int32 ViewWidth { get; };
|
||||
Int32 BufferHeight { get; };
|
||||
|
||||
Boolean HasSelection { get; };
|
||||
|
||||
@@ -883,6 +883,10 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
|
||||
RawWriteString(wstr);
|
||||
}
|
||||
void TermControl::SendOutput(const winrt::hstring& wstr)
|
||||
{
|
||||
_core.SendOutput(wstr);
|
||||
}
|
||||
void TermControl::ClearBuffer(Control::ClearBufferType clearType)
|
||||
{
|
||||
_core.ClearBuffer(clearType);
|
||||
@@ -1448,6 +1452,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
// Likewise, run the event handlers outside of lock (they could
|
||||
// be reentrant)
|
||||
Initialized.raise(*this, nullptr);
|
||||
_core.SetTmuxControlHandlerProducer(_tmuxDCSHandlerProducer);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -2758,6 +2763,11 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
return _core.ViewHeight();
|
||||
}
|
||||
|
||||
int TermControl::ViewWidth() const
|
||||
{
|
||||
return _core.ViewWidth();
|
||||
}
|
||||
|
||||
int TermControl::BufferHeight() const
|
||||
{
|
||||
return _core.BufferHeight();
|
||||
@@ -2957,7 +2967,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
else
|
||||
{
|
||||
// Do we ever get here (= uninitialized terminal)? If so: How?
|
||||
assert(false);
|
||||
// Yes, we can get here, when do Pane._Split, it need to call _SetupEntranceAnimation^M
|
||||
// which need the control's size, while this size can only be available when the control^M
|
||||
// is initialized.^M
|
||||
return { 10, 10 };
|
||||
}
|
||||
}
|
||||
@@ -4202,4 +4214,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
_core.CursorOn(focused);
|
||||
}
|
||||
}
|
||||
void TermControl::SetTmuxControlHandlerProducer(winrt::Microsoft::Terminal::Control::TmuxDCSHandlerProducer producer)
|
||||
{
|
||||
_tmuxDCSHandlerProducer = producer;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,6 +96,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
|
||||
int ScrollOffset() const;
|
||||
int ViewHeight() const;
|
||||
int ViewWidth() const;
|
||||
int BufferHeight() const;
|
||||
|
||||
bool HasSelection() const;
|
||||
@@ -118,6 +119,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
void SelectOutput(const bool goUp);
|
||||
|
||||
winrt::hstring CurrentWorkingDirectory() const;
|
||||
void SetTmuxControlHandlerProducer(winrt::Microsoft::Terminal::Control::TmuxDCSHandlerProducer producer);
|
||||
#pragma endregion
|
||||
|
||||
void ScrollViewport(int viewTop);
|
||||
@@ -127,6 +129,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
winrt::Windows::Foundation::Size GetFontSize() const;
|
||||
|
||||
void SendInput(const winrt::hstring& input);
|
||||
void SendOutput(const winrt::hstring& input);
|
||||
void ClearBuffer(Control::ClearBufferType clearType);
|
||||
|
||||
void ToggleShaderEffects();
|
||||
@@ -451,6 +454,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
void _SelectCommandHandler(const IInspectable& sender, const IInspectable& args);
|
||||
void _SelectOutputHandler(const IInspectable& sender, const IInspectable& args);
|
||||
bool _displayCursorWhileBlurred() const noexcept;
|
||||
winrt::Microsoft::Terminal::Control::TmuxDCSHandlerProducer _tmuxDCSHandlerProducer { nullptr };
|
||||
|
||||
struct Revokers
|
||||
{
|
||||
|
||||
@@ -117,6 +117,7 @@ namespace Microsoft.Terminal.Control
|
||||
|
||||
void ToggleShaderEffects();
|
||||
void SendInput(String input);
|
||||
void SendOutput(String input);
|
||||
Boolean RawWriteKeyEvent(UInt16 vkey, UInt16 scanCode, Microsoft.Terminal.Core.ControlKeyStates modifiers, Boolean keyDown);
|
||||
Boolean RawWriteChar(Char character, UInt16 scanCode, Microsoft.Terminal.Core.ControlKeyStates modifiers);
|
||||
void RawWriteString(String text);
|
||||
@@ -156,5 +157,6 @@ namespace Microsoft.Terminal.Control
|
||||
void ClearQuickFix();
|
||||
|
||||
void Detach();
|
||||
void SetTmuxControlHandlerProducer(TmuxDCSHandlerProducer producer);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -225,6 +225,12 @@ void Terminal::SetVtChecksumReportSupport(const bool enabled)
|
||||
engine.Dispatch().SetVtChecksumReportSupport(enabled);
|
||||
}
|
||||
|
||||
void Terminal::SetTmuxControlHandlerProducer(ITermDispatch::StringHandlerProducer producer) const noexcept
|
||||
{
|
||||
auto& engine = reinterpret_cast<OutputStateMachineEngine&>(_stateMachine->Engine());
|
||||
engine.Dispatch().SetTmuxControlHandlerProducer(producer);
|
||||
}
|
||||
|
||||
bool Terminal::IsXtermBracketedPasteModeEnabled() const noexcept
|
||||
{
|
||||
return _systemMode.test(Mode::BracketedPaste);
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include "../../types/inc/Viewport.hpp"
|
||||
#include "../../types/inc/GlyphWidth.hpp"
|
||||
#include "../../cascadia/terminalcore/ITerminalInput.hpp"
|
||||
#include "../../terminal/adapter/ITermDispatch.hpp"
|
||||
|
||||
#include <til/generational.h>
|
||||
#include <til/ticket_lock.h>
|
||||
@@ -126,6 +127,7 @@ public:
|
||||
std::wstring CurrentCommand() const;
|
||||
|
||||
void SerializeMainBuffer(const wchar_t* destination) const;
|
||||
void SetTmuxControlHandlerProducer(Microsoft::Console::VirtualTerminal::ITermDispatch::StringHandlerProducer producer) const noexcept;
|
||||
|
||||
#pragma region ITerminalApi
|
||||
// These methods are defined in TerminalApi.cpp
|
||||
|
||||
@@ -19,57 +19,14 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
Automation::AutomationProperties::SetName(AddNewButton(), RS_(L"Actions_AddNewTextBlock/Text"));
|
||||
}
|
||||
|
||||
Automation::Peers::AutomationPeer Actions::OnCreateAutomationPeer()
|
||||
{
|
||||
_ViewModel.OnAutomationPeerAttached();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void Actions::OnNavigatedTo(const NavigationEventArgs& e)
|
||||
{
|
||||
_ViewModel = e.Parameter().as<Editor::ActionsViewModel>();
|
||||
|
||||
// Subscribe to the view model's FocusContainer event.
|
||||
// Use the KeyBindingViewModel or index provided in the event to focus the corresponding container
|
||||
_ViewModel.FocusContainer([this](const auto& /*sender*/, const auto& args) {
|
||||
if (auto kbdVM{ args.try_as<KeyBindingViewModel>() })
|
||||
{
|
||||
if (const auto& container = KeyBindingsListView().ContainerFromItem(*kbdVM))
|
||||
{
|
||||
container.as<Controls::ListViewItem>().Focus(FocusState::Programmatic);
|
||||
}
|
||||
}
|
||||
else if (const auto& index = args.try_as<uint32_t>())
|
||||
{
|
||||
if (const auto& container = KeyBindingsListView().ContainerFromIndex(*index))
|
||||
{
|
||||
container.as<Controls::ListViewItem>().Focus(FocusState::Programmatic);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Subscribe to the view model's UpdateBackground event.
|
||||
// The view model does not have access to the page resources, so it asks us
|
||||
// to update the key binding's container background
|
||||
_ViewModel.UpdateBackground([this](const auto& /*sender*/, const auto& args) {
|
||||
if (auto kbdVM{ args.try_as<KeyBindingViewModel>() })
|
||||
{
|
||||
if (kbdVM->IsInEditMode())
|
||||
{
|
||||
const auto& containerBackground{ Resources().Lookup(box_value(L"ActionContainerBackgroundEditing")).as<Windows::UI::Xaml::Media::Brush>() };
|
||||
kbdVM->ContainerBackground(containerBackground);
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto& containerBackground{ Resources().Lookup(box_value(L"ActionContainerBackground")).as<Windows::UI::Xaml::Media::Brush>() };
|
||||
kbdVM->ContainerBackground(containerBackground);
|
||||
}
|
||||
}
|
||||
});
|
||||
_ViewModel.CurrentPage(ActionsSubPage::Base);
|
||||
}
|
||||
|
||||
void Actions::AddNew_Click(const IInspectable& /*sender*/, const RoutedEventArgs& /*eventArgs*/)
|
||||
{
|
||||
_ViewModel.AddNewKeybinding();
|
||||
_ViewModel.AddNewCommand();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,6 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
Actions();
|
||||
|
||||
void OnNavigatedTo(const winrt::Windows::UI::Xaml::Navigation::NavigationEventArgs& e);
|
||||
Windows::UI::Xaml::Automation::Peers::AutomationPeer OnCreateAutomationPeer();
|
||||
|
||||
void AddNew_Click(const IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& eventArgs);
|
||||
|
||||
|
||||
@@ -122,7 +122,7 @@
|
||||
<Style x:Key="KeyBindingContainerStyle"
|
||||
BasedOn="{StaticResource DefaultListViewItemStyle}"
|
||||
TargetType="ListViewItem">
|
||||
<Setter Property="Padding" Value="4" />
|
||||
<Setter Property="Padding" Value="12,4,4,4" />
|
||||
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
|
||||
<Setter Property="XYFocusKeyboardNavigation" Value="Enabled" />
|
||||
</Style>
|
||||
@@ -137,24 +137,6 @@
|
||||
<Setter Property="HorizontalAlignment" Value="Right" />
|
||||
<Setter Property="VerticalAlignment" Value="Center" />
|
||||
</Style>
|
||||
<x:Int32 x:Key="EditButtonSize">32</x:Int32>
|
||||
<x:Double x:Key="EditButtonIconSize">15</x:Double>
|
||||
<Style x:Key="EditButtonStyle"
|
||||
BasedOn="{StaticResource DefaultButtonStyle}"
|
||||
TargetType="Button">
|
||||
<Setter Property="Padding" Value="0" />
|
||||
<Setter Property="VerticalAlignment" Value="Center" />
|
||||
<Setter Property="Height" Value="{StaticResource EditButtonSize}" />
|
||||
<Setter Property="Width" Value="{StaticResource EditButtonSize}" />
|
||||
</Style>
|
||||
<Style x:Key="AccentEditButtonStyle"
|
||||
BasedOn="{StaticResource AccentButtonStyle}"
|
||||
TargetType="Button">
|
||||
<Setter Property="Padding" Value="3" />
|
||||
<Setter Property="VerticalAlignment" Value="Center" />
|
||||
<Setter Property="Height" Value="{StaticResource EditButtonSize}" />
|
||||
<Setter Property="Width" Value="{StaticResource EditButtonSize}" />
|
||||
</Style>
|
||||
|
||||
<!-- Converters & Misc. -->
|
||||
<SolidColorBrush x:Key="ActionContainerBackgroundEditing"
|
||||
@@ -163,22 +145,16 @@
|
||||
Color="Transparent" />
|
||||
|
||||
<!-- Templates -->
|
||||
<DataTemplate x:Key="KeyBindingTemplate"
|
||||
x:DataType="local:KeyBindingViewModel">
|
||||
<ListViewItem AutomationProperties.AcceleratorKey="{x:Bind KeyChordText, Mode=OneWay}"
|
||||
AutomationProperties.Name="{x:Bind Name, Mode=OneWay}"
|
||||
Background="{x:Bind ContainerBackground, Mode=OneWay}"
|
||||
GotFocus="{x:Bind ActionGotFocus}"
|
||||
LostFocus="{x:Bind ActionLostFocus}"
|
||||
PointerEntered="{x:Bind EnterHoverMode}"
|
||||
PointerExited="{x:Bind ExitHoverMode}"
|
||||
<DataTemplate x:Key="CommandTemplate"
|
||||
x:DataType="local:CommandViewModel">
|
||||
<ListViewItem AutomationProperties.Name="{x:Bind DisplayName, Mode=OneWay}"
|
||||
Style="{StaticResource KeyBindingContainerStyle}">
|
||||
<Grid ColumnSpacing="8">
|
||||
<Grid.ColumnDefinitions>
|
||||
<!-- command name -->
|
||||
<ColumnDefinition Width="*" />
|
||||
<!-- key chord -->
|
||||
<ColumnDefinition Width="auto" />
|
||||
<ColumnDefinition Width="150" />
|
||||
<!-- edit buttons -->
|
||||
<!--
|
||||
This needs to be 112 because that is the width of the row of buttons in edit mode + padding.
|
||||
@@ -192,133 +168,7 @@
|
||||
<!-- Command Name -->
|
||||
<TextBlock Grid.Column="0"
|
||||
Style="{StaticResource KeyBindingNameTextBlockStyle}"
|
||||
Text="{x:Bind Name, Mode=OneWay}"
|
||||
Visibility="{x:Bind mtu:Converters.InvertedBooleanToVisibility(IsInEditMode), Mode=OneWay}" />
|
||||
|
||||
<!-- Edit Mode: Action Combo-box -->
|
||||
<ComboBox x:Uid="Actions_ActionComboBox"
|
||||
Grid.Column="0"
|
||||
VerticalAlignment="Center"
|
||||
ItemsSource="{x:Bind AvailableActions, Mode=OneWay}"
|
||||
SelectedItem="{x:Bind ProposedAction, Mode=TwoWay}"
|
||||
Visibility="{x:Bind IsInEditMode, Mode=OneWay}" />
|
||||
|
||||
<!-- Key Chord Text -->
|
||||
<Border Grid.Column="1"
|
||||
Padding="2,0,2,0"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Center"
|
||||
Style="{ThemeResource KeyChordBorderStyle}"
|
||||
Visibility="{x:Bind mtu:Converters.InvertedBooleanToVisibility(IsInEditMode), Mode=OneWay}">
|
||||
|
||||
<TextBlock FontSize="14"
|
||||
Style="{ThemeResource KeyChordTextBlockStyle}"
|
||||
Text="{x:Bind KeyChordText, Mode=OneWay}"
|
||||
TextWrapping="WrapWholeWords" />
|
||||
</Border>
|
||||
|
||||
<!-- Edit Mode: Key Chord Listener -->
|
||||
<local:KeyChordListener Grid.Column="1"
|
||||
Keys="{x:Bind ProposedKeys, Mode=TwoWay}"
|
||||
Style="{StaticResource KeyChordEditorStyle}"
|
||||
Visibility="{x:Bind IsInEditMode, Mode=OneWay}" />
|
||||
|
||||
<!-- Edit Button -->
|
||||
<Button x:Uid="Actions_EditButton"
|
||||
Grid.Column="2"
|
||||
AutomationProperties.Name="{x:Bind EditButtonName}"
|
||||
Background="Transparent"
|
||||
Click="{x:Bind ToggleEditMode}"
|
||||
GettingFocus="{x:Bind EditButtonGettingFocus}"
|
||||
LosingFocus="{x:Bind EditButtonLosingFocus}"
|
||||
Style="{StaticResource EditButtonStyle}"
|
||||
Visibility="{x:Bind ShowEditButton, Mode=OneWay}">
|
||||
<Button.Content>
|
||||
<FontIcon FontSize="{StaticResource EditButtonIconSize}"
|
||||
Glyph="" />
|
||||
</Button.Content>
|
||||
<Button.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.ThemeDictionaries>
|
||||
<ResourceDictionary x:Key="Light">
|
||||
<SolidColorBrush x:Key="ButtonForegroundPointerOver"
|
||||
Color="{StaticResource SystemAccentColor}" />
|
||||
<SolidColorBrush x:Key="ButtonForegroundPressed"
|
||||
Color="{StaticResource SystemAccentColor}" />
|
||||
</ResourceDictionary>
|
||||
<ResourceDictionary x:Key="Dark">
|
||||
<SolidColorBrush x:Key="ButtonForegroundPointerOver"
|
||||
Color="{StaticResource SystemAccentColor}" />
|
||||
<SolidColorBrush x:Key="ButtonForegroundPressed"
|
||||
Color="{StaticResource SystemAccentColor}" />
|
||||
</ResourceDictionary>
|
||||
<ResourceDictionary x:Key="HighContrast">
|
||||
<SolidColorBrush x:Key="ButtonBackground"
|
||||
Color="{ThemeResource SystemColorButtonFaceColor}" />
|
||||
<SolidColorBrush x:Key="ButtonBackgroundPointerOver"
|
||||
Color="{ThemeResource SystemColorHighlightColor}" />
|
||||
<SolidColorBrush x:Key="ButtonBackgroundPressed"
|
||||
Color="{ThemeResource SystemColorHighlightColor}" />
|
||||
<SolidColorBrush x:Key="ButtonForeground"
|
||||
Color="{ThemeResource SystemColorButtonTextColor}" />
|
||||
<SolidColorBrush x:Key="ButtonForegroundPointerOver"
|
||||
Color="{ThemeResource SystemColorHighlightTextColor}" />
|
||||
<SolidColorBrush x:Key="ButtonForegroundPressed"
|
||||
Color="{ThemeResource SystemColorHighlightTextColor}" />
|
||||
</ResourceDictionary>
|
||||
</ResourceDictionary.ThemeDictionaries>
|
||||
</ResourceDictionary>
|
||||
</Button.Resources>
|
||||
</Button>
|
||||
|
||||
<!-- Edit Mode: Buttons -->
|
||||
<StackPanel Grid.Column="2"
|
||||
Orientation="Horizontal"
|
||||
Visibility="{x:Bind IsInEditMode, Mode=OneWay}">
|
||||
|
||||
<!-- Cancel editing the action -->
|
||||
<Button x:Uid="Actions_CancelButton"
|
||||
AutomationProperties.Name="{x:Bind CancelButtonName}"
|
||||
Click="{x:Bind CancelChanges}"
|
||||
Style="{StaticResource EditButtonStyle}">
|
||||
<FontIcon FontSize="{StaticResource EditButtonIconSize}"
|
||||
Glyph="" />
|
||||
</Button>
|
||||
|
||||
<!-- Accept changes -->
|
||||
<Button x:Uid="Actions_AcceptButton"
|
||||
Margin="8,0,0,0"
|
||||
AutomationProperties.Name="{x:Bind AcceptButtonName}"
|
||||
Click="{x:Bind AttemptAcceptChanges}"
|
||||
Flyout="{x:Bind AcceptChangesFlyout, Mode=OneWay}"
|
||||
Style="{StaticResource AccentEditButtonStyle}">
|
||||
<FontIcon FontSize="{StaticResource EditButtonIconSize}"
|
||||
Glyph="" />
|
||||
</Button>
|
||||
|
||||
<!-- Delete the current key binding -->
|
||||
<Button x:Uid="Actions_DeleteButton"
|
||||
Margin="8,0,0,0"
|
||||
AutomationProperties.Name="{x:Bind DeleteButtonName}"
|
||||
Style="{StaticResource DeleteSmallButtonStyle}"
|
||||
Visibility="{x:Bind mtu:Converters.InvertedBooleanToVisibility(IsNewlyAdded), Mode=OneWay}">
|
||||
<Button.Content>
|
||||
<FontIcon FontSize="{StaticResource EditButtonIconSize}"
|
||||
Glyph="" />
|
||||
</Button.Content>
|
||||
<Button.Flyout>
|
||||
<Flyout FlyoutPresenterStyle="{StaticResource CustomFlyoutPresenterStyle}">
|
||||
<StackPanel>
|
||||
<TextBlock x:Uid="Actions_DeleteConfirmationMessage"
|
||||
Style="{StaticResource CustomFlyoutTextStyle}" />
|
||||
<Button x:Uid="Actions_DeleteConfirmationButton"
|
||||
Click="{x:Bind DeleteKeyBinding}" />
|
||||
</StackPanel>
|
||||
</Flyout>
|
||||
</Button.Flyout>
|
||||
</Button>
|
||||
|
||||
</StackPanel>
|
||||
Text="{x:Bind DisplayName, Mode=OneWay}" />
|
||||
</Grid>
|
||||
</ListViewItem>
|
||||
</DataTemplate>
|
||||
@@ -330,6 +180,13 @@
|
||||
HorizontalAlignment="Left"
|
||||
Spacing="8"
|
||||
Style="{StaticResource SettingsStackStyle}">
|
||||
<TextBlock Style="{StaticResource DisclaimerStyle}"
|
||||
TextWrapping="WrapWholeWords">
|
||||
<Hyperlink NavigateUri="https://learn.microsoft.com/en-us/windows/terminal/customize-settings/actions"
|
||||
TextDecorations="None">
|
||||
<Run x:Uid="Actions_Disclaimer" />
|
||||
</Hyperlink>
|
||||
</TextBlock>
|
||||
<!-- Add New Button -->
|
||||
<Button x:Name="AddNewButton"
|
||||
Click="AddNew_Click">
|
||||
@@ -344,10 +201,12 @@
|
||||
</Button>
|
||||
|
||||
<!-- Keybindings -->
|
||||
<ListView x:Name="KeyBindingsListView"
|
||||
ItemTemplate="{StaticResource KeyBindingTemplate}"
|
||||
ItemsSource="{x:Bind ViewModel.KeyBindingList, Mode=OneWay}"
|
||||
SelectionMode="None" />
|
||||
<ListView x:Name="CommandsListView"
|
||||
Margin="-8,0,0,0"
|
||||
IsItemClickEnabled="True"
|
||||
ItemClick="{x:Bind ViewModel.CmdListItemClicked}"
|
||||
ItemTemplate="{StaticResource CommandTemplate}"
|
||||
ItemsSource="{x:Bind ViewModel.CommandList, Mode=OneWay}" />
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</Page>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -4,127 +4,248 @@
|
||||
#pragma once
|
||||
|
||||
#include "ActionsViewModel.g.h"
|
||||
#include "KeyBindingViewModel.g.h"
|
||||
#include "ModifyKeyBindingEventArgs.g.h"
|
||||
#include "NavigateToCommandArgs.g.h"
|
||||
#include "CommandViewModel.g.h"
|
||||
#include "ArgWrapper.g.h"
|
||||
#include "ActionArgsViewModel.g.h"
|
||||
#include "KeyChordViewModel.g.h"
|
||||
#include "ModifyKeyChordEventArgs.g.h"
|
||||
#include "Utils.h"
|
||||
#include "ViewModelHelpers.h"
|
||||
|
||||
namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
{
|
||||
struct KeyBindingViewModelComparator
|
||||
struct CommandViewModelComparator
|
||||
{
|
||||
bool operator()(const Editor::KeyBindingViewModel& lhs, const Editor::KeyBindingViewModel& rhs) const
|
||||
bool operator()(const Editor::CommandViewModel& lhs, const Editor::CommandViewModel& rhs) const
|
||||
{
|
||||
return lhs.Name() < rhs.Name();
|
||||
return lhs.DisplayName() < rhs.DisplayName();
|
||||
}
|
||||
};
|
||||
|
||||
struct ModifyKeyBindingEventArgs : ModifyKeyBindingEventArgsT<ModifyKeyBindingEventArgs>
|
||||
struct NavigateToCommandArgs : NavigateToCommandArgsT<NavigateToCommandArgs>
|
||||
{
|
||||
public:
|
||||
ModifyKeyBindingEventArgs(const Control::KeyChord& oldKeys, const Control::KeyChord& newKeys, const hstring oldActionName, const hstring newActionName) :
|
||||
NavigateToCommandArgs(CommandViewModel command, Editor::IHostedInWindow windowRoot) :
|
||||
_Command(command),
|
||||
_WindowRoot(windowRoot) {}
|
||||
|
||||
Editor::IHostedInWindow WindowRoot() const noexcept { return _WindowRoot; }
|
||||
Editor::CommandViewModel Command() const noexcept { return _Command; }
|
||||
|
||||
private:
|
||||
Editor::IHostedInWindow _WindowRoot;
|
||||
Editor::CommandViewModel _Command{ nullptr };
|
||||
};
|
||||
|
||||
struct ModifyKeyChordEventArgs : ModifyKeyChordEventArgsT<ModifyKeyChordEventArgs>
|
||||
{
|
||||
public:
|
||||
ModifyKeyChordEventArgs(const Control::KeyChord& oldKeys, const Control::KeyChord& newKeys) :
|
||||
_OldKeys{ oldKeys },
|
||||
_NewKeys{ newKeys },
|
||||
_OldActionName{ std::move(oldActionName) },
|
||||
_NewActionName{ std::move(newActionName) } {}
|
||||
_NewKeys{ newKeys } {}
|
||||
|
||||
WINRT_PROPERTY(Control::KeyChord, OldKeys, nullptr);
|
||||
WINRT_PROPERTY(Control::KeyChord, NewKeys, nullptr);
|
||||
WINRT_PROPERTY(hstring, OldActionName);
|
||||
WINRT_PROPERTY(hstring, NewActionName);
|
||||
};
|
||||
|
||||
struct KeyBindingViewModel : KeyBindingViewModelT<KeyBindingViewModel>, ViewModelHelper<KeyBindingViewModel>
|
||||
struct CommandViewModel : CommandViewModelT<CommandViewModel>, ViewModelHelper<CommandViewModel>
|
||||
{
|
||||
public:
|
||||
KeyBindingViewModel(const Windows::Foundation::Collections::IObservableVector<hstring>& availableActions);
|
||||
KeyBindingViewModel(const Control::KeyChord& keys, const hstring& name, const Windows::Foundation::Collections::IObservableVector<hstring>& availableActions);
|
||||
CommandViewModel(winrt::Microsoft::Terminal::Settings::Model::Command cmd,
|
||||
std::vector<Control::KeyChord> keyChordList,
|
||||
const Editor::ActionsViewModel actionsPageVM,
|
||||
const Windows::Foundation::Collections::IMap<Model::ShortcutAction, winrt::hstring>& availableShortcutActionsAndNames);
|
||||
void Initialize();
|
||||
|
||||
hstring Name() const { return _CurrentAction; }
|
||||
hstring KeyChordText() const { return _KeyChordText; }
|
||||
winrt::hstring DisplayName();
|
||||
winrt::hstring Name();
|
||||
void Name(const winrt::hstring& newName);
|
||||
|
||||
// UIA Text
|
||||
hstring EditButtonName() const noexcept;
|
||||
hstring CancelButtonName() const noexcept;
|
||||
hstring AcceptButtonName() const noexcept;
|
||||
hstring DeleteButtonName() const noexcept;
|
||||
winrt::hstring ID();
|
||||
void ID(const winrt::hstring& newID);
|
||||
|
||||
void EnterHoverMode() { IsHovered(true); };
|
||||
void ExitHoverMode() { IsHovered(false); };
|
||||
void ActionGotFocus() { IsContainerFocused(true); };
|
||||
void ActionLostFocus() { IsContainerFocused(false); };
|
||||
void EditButtonGettingFocus() { IsEditButtonFocused(true); };
|
||||
void EditButtonLosingFocus() { IsEditButtonFocused(false); };
|
||||
bool ShowEditButton() const noexcept;
|
||||
void ToggleEditMode();
|
||||
void DisableEditMode() { IsInEditMode(false); }
|
||||
void AttemptAcceptChanges();
|
||||
void AttemptAcceptChanges(const Control::KeyChord newKeys);
|
||||
void CancelChanges();
|
||||
void DeleteKeyBinding() { DeleteKeyBindingRequested.raise(*this, _CurrentKeys); }
|
||||
bool IsUserAction();
|
||||
|
||||
// ProposedAction: the entry selected by the combo box; may disagree with the settings model.
|
||||
// CurrentAction: the combo box item that maps to the settings model value.
|
||||
// AvailableActions: the list of options in the combo box; both actions above must be in this list.
|
||||
// NOTE: ProposedAction and CurrentAction may disagree mainly due to the "edit mode" system in place.
|
||||
// Current Action serves as...
|
||||
// 1 - a record of what to set ProposedAction to on a cancellation
|
||||
// 2 - a form of translation between ProposedAction and the settings model
|
||||
// We would also need an ActionMap reference to remove this, but this is a better separation
|
||||
// of responsibilities.
|
||||
VIEW_MODEL_OBSERVABLE_PROPERTY(IInspectable, ProposedAction);
|
||||
VIEW_MODEL_OBSERVABLE_PROPERTY(hstring, CurrentAction);
|
||||
WINRT_PROPERTY(Windows::Foundation::Collections::IObservableVector<hstring>, AvailableActions, nullptr);
|
||||
void Edit_Click();
|
||||
til::typed_event<Editor::CommandViewModel, IInspectable> EditRequested;
|
||||
|
||||
// ProposedKeys: the keys proposed by the control; may disagree with the settings model.
|
||||
// CurrentKeys: the key chord bound in the settings model.
|
||||
VIEW_MODEL_OBSERVABLE_PROPERTY(Control::KeyChord, ProposedKeys);
|
||||
VIEW_MODEL_OBSERVABLE_PROPERTY(Control::KeyChord, CurrentKeys, nullptr);
|
||||
void Delete_Click();
|
||||
til::typed_event<Editor::CommandViewModel, IInspectable> DeleteRequested;
|
||||
|
||||
VIEW_MODEL_OBSERVABLE_PROPERTY(bool, IsInEditMode, false);
|
||||
VIEW_MODEL_OBSERVABLE_PROPERTY(bool, IsNewlyAdded, false);
|
||||
VIEW_MODEL_OBSERVABLE_PROPERTY(Windows::UI::Xaml::Controls::Flyout, AcceptChangesFlyout, nullptr);
|
||||
VIEW_MODEL_OBSERVABLE_PROPERTY(bool, IsAutomationPeerAttached, false);
|
||||
VIEW_MODEL_OBSERVABLE_PROPERTY(bool, IsHovered, false);
|
||||
VIEW_MODEL_OBSERVABLE_PROPERTY(bool, IsContainerFocused, false);
|
||||
VIEW_MODEL_OBSERVABLE_PROPERTY(bool, IsEditButtonFocused, false);
|
||||
VIEW_MODEL_OBSERVABLE_PROPERTY(Windows::UI::Xaml::Media::Brush, ContainerBackground, nullptr);
|
||||
void AddKeybinding_Click();
|
||||
|
||||
public:
|
||||
til::typed_event<Editor::KeyBindingViewModel, Editor::ModifyKeyBindingEventArgs> ModifyKeyBindingRequested;
|
||||
til::typed_event<Editor::KeyBindingViewModel, Terminal::Control::KeyChord> DeleteKeyBindingRequested;
|
||||
til::typed_event<Editor::KeyBindingViewModel, IInspectable> DeleteNewlyAddedKeyBinding;
|
||||
til::typed_event<IInspectable, Editor::ArgWrapper> PropagateColorSchemeRequested;
|
||||
til::typed_event<IInspectable, Editor::ArgWrapper> PropagateColorSchemeNamesRequested;
|
||||
til::typed_event<IInspectable, Editor::ArgWrapper> PropagateWindowRootRequested;
|
||||
|
||||
VIEW_MODEL_OBSERVABLE_PROPERTY(IInspectable, ProposedShortcutAction);
|
||||
VIEW_MODEL_OBSERVABLE_PROPERTY(Editor::ActionArgsViewModel, ActionArgsVM, nullptr);
|
||||
WINRT_PROPERTY(Windows::Foundation::Collections::IObservableVector<hstring>, AvailableShortcutActions, nullptr);
|
||||
WINRT_PROPERTY(Windows::Foundation::Collections::IObservableVector<Editor::KeyChordViewModel>, KeyChordViewModelList, nullptr);
|
||||
WINRT_PROPERTY(bool, IsNewCommand, false);
|
||||
|
||||
private:
|
||||
hstring _KeyChordText{};
|
||||
winrt::Microsoft::Terminal::Settings::Model::Command _command;
|
||||
std::vector<Control::KeyChord> _keyChordList;
|
||||
weak_ref<Editor::ActionsViewModel> _actionsPageVM{ nullptr };
|
||||
void _RegisterKeyChordVMEvents(Editor::KeyChordViewModel kcVM);
|
||||
void _RegisterActionArgsVMEvents(Editor::ActionArgsViewModel actionArgsVM);
|
||||
void _ReplaceCommandWithUserCopy(bool reinitialize);
|
||||
void _CreateAndInitializeActionArgsVMHelper();
|
||||
Windows::Foundation::Collections::IMap<Model::ShortcutAction, winrt::hstring> _AvailableActionsAndNamesMap;
|
||||
std::unordered_map<winrt::hstring, Model::ShortcutAction> _NameToActionMap;
|
||||
};
|
||||
|
||||
struct ArgWrapper : ArgWrapperT<ArgWrapper>, ViewModelHelper<ArgWrapper>
|
||||
{
|
||||
public:
|
||||
ArgWrapper(const winrt::hstring& name, const winrt::hstring& type, const bool required, const Model::ArgTypeHint typeHint, const Windows::Foundation::IInspectable& value);
|
||||
void Initialize();
|
||||
|
||||
winrt::hstring Name() const noexcept { return _name; };
|
||||
winrt::hstring Type() const noexcept { return _type; };
|
||||
Model::ArgTypeHint TypeHint() const noexcept { return _typeHint; };
|
||||
bool Required() const noexcept { return _required; };
|
||||
|
||||
// We cannot use the macro here because we need to implement additional logic for the setter
|
||||
Windows::Foundation::IInspectable EnumValue() const noexcept { return _EnumValue; };
|
||||
void EnumValue(const Windows::Foundation::IInspectable& value);
|
||||
Windows::Foundation::Collections::IObservableVector<Microsoft::Terminal::Settings::Editor::EnumEntry> EnumList() const noexcept { return _EnumList; };
|
||||
Windows::Foundation::Collections::IObservableVector<Microsoft::Terminal::Settings::Editor::FlagEntry> FlagList() const noexcept { return _FlagList; };
|
||||
|
||||
// unboxing functions
|
||||
winrt::hstring UnboxString(const Windows::Foundation::IInspectable& value);
|
||||
winrt::hstring UnboxGuid(const Windows::Foundation::IInspectable& value);
|
||||
int32_t UnboxInt32(const Windows::Foundation::IInspectable& value);
|
||||
float UnboxInt32Optional(const Windows::Foundation::IInspectable& value);
|
||||
uint32_t UnboxUInt32(const Windows::Foundation::IInspectable& value);
|
||||
float UnboxUInt32Optional(const Windows::Foundation::IInspectable& value);
|
||||
float UnboxUInt64(const Windows::Foundation::IInspectable& value);
|
||||
float UnboxFloat(const Windows::Foundation::IInspectable& value);
|
||||
bool UnboxBool(const Windows::Foundation::IInspectable& value);
|
||||
winrt::Windows::Foundation::IReference<bool> UnboxBoolOptional(const Windows::Foundation::IInspectable& value);
|
||||
winrt::Windows::Foundation::IReference<Microsoft::Terminal::Core::Color> UnboxTerminalCoreColorOptional(const Windows::Foundation::IInspectable& value);
|
||||
winrt::Windows::Foundation::IReference<Microsoft::Terminal::Core::Color> UnboxWindowsUIColorOptional(const Windows::Foundation::IInspectable& value);
|
||||
|
||||
// bind back functions
|
||||
void StringBindBack(const winrt::hstring& newValue);
|
||||
void GuidBindBack(const winrt::hstring& newValue);
|
||||
void Int32BindBack(const double newValue);
|
||||
void Int32OptionalBindBack(const double newValue);
|
||||
void UInt32BindBack(const double newValue);
|
||||
void UInt32OptionalBindBack(const double newValue);
|
||||
void UInt64BindBack(const double newValue);
|
||||
void FloatBindBack(const double newValue);
|
||||
void BoolOptionalBindBack(const Windows::Foundation::IReference<bool> newValue);
|
||||
void TerminalCoreColorBindBack(const winrt::Windows::Foundation::IReference<Microsoft::Terminal::Core::Color> newValue);
|
||||
void WindowsUIColorBindBack(const winrt::Windows::Foundation::IReference<Microsoft::Terminal::Core::Color> newValue);
|
||||
|
||||
safe_void_coroutine Browse_Click(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& e);
|
||||
|
||||
// some argWrappers need to know additional information (like the default color scheme or the list of all color scheme names)
|
||||
// to avoid populating all ArgWrappers with that information, instead we emit an event when we need that information
|
||||
// (these events then get propagated up to the ActionsVM) and then the actionsVM will populate the value in us
|
||||
// since there's an actionArgsVM above us and a commandVM above that, the event does get propagated through a few times but that's
|
||||
// probably better than having every argWrapper contain the information by default
|
||||
til::typed_event<IInspectable, Editor::ArgWrapper> ColorSchemeRequested;
|
||||
til::typed_event<IInspectable, Editor::ArgWrapper> ColorSchemeNamesRequested;
|
||||
til::typed_event<IInspectable, Editor::ArgWrapper> WindowRootRequested;
|
||||
|
||||
VIEW_MODEL_OBSERVABLE_PROPERTY(Editor::ColorSchemeViewModel, DefaultColorScheme, nullptr);
|
||||
VIEW_MODEL_OBSERVABLE_PROPERTY(Windows::Foundation::IInspectable, Value, nullptr);
|
||||
WINRT_PROPERTY(Windows::Foundation::Collections::IVector<winrt::hstring>, ColorSchemeNamesList, nullptr);
|
||||
WINRT_PROPERTY(Editor::IHostedInWindow, WindowRoot, nullptr);
|
||||
|
||||
private:
|
||||
winrt::hstring _name;
|
||||
winrt::hstring _type;
|
||||
Model::ArgTypeHint _typeHint;
|
||||
bool _required;
|
||||
Windows::Foundation::IInspectable _EnumValue{ nullptr };
|
||||
Windows::Foundation::Collections::IObservableVector<Microsoft::Terminal::Settings::Editor::EnumEntry> _EnumList;
|
||||
Windows::Foundation::Collections::IObservableVector<Microsoft::Terminal::Settings::Editor::FlagEntry> _FlagList;
|
||||
};
|
||||
|
||||
struct ActionArgsViewModel : ActionArgsViewModelT<ActionArgsViewModel>, ViewModelHelper<ActionArgsViewModel>
|
||||
{
|
||||
public:
|
||||
ActionArgsViewModel(const Microsoft::Terminal::Settings::Model::ActionAndArgs actionAndArgs);
|
||||
void Initialize();
|
||||
|
||||
bool HasArgs() const noexcept;
|
||||
void ReplaceActionAndArgs(Model::ActionAndArgs newActionAndArgs);
|
||||
|
||||
til::typed_event<IInspectable, IInspectable> WrapperValueChanged;
|
||||
til::typed_event<IInspectable, Editor::ArgWrapper> PropagateColorSchemeRequested;
|
||||
til::typed_event<IInspectable, Editor::ArgWrapper> PropagateColorSchemeNamesRequested;
|
||||
til::typed_event<IInspectable, Editor::ArgWrapper> PropagateWindowRootRequested;
|
||||
|
||||
WINRT_PROPERTY(Windows::Foundation::Collections::IObservableVector<Editor::ArgWrapper>, ArgValues, nullptr);
|
||||
|
||||
private:
|
||||
Model::ActionAndArgs _actionAndArgs{ nullptr };
|
||||
};
|
||||
|
||||
struct KeyChordViewModel : KeyChordViewModelT<KeyChordViewModel>, ViewModelHelper<KeyChordViewModel>
|
||||
{
|
||||
public:
|
||||
KeyChordViewModel(Control::KeyChord CurrentKeys);
|
||||
|
||||
void CurrentKeys(const Control::KeyChord& newKeys);
|
||||
Control::KeyChord CurrentKeys() const noexcept;
|
||||
|
||||
void ToggleEditMode();
|
||||
void AttemptAcceptChanges();
|
||||
void CancelChanges();
|
||||
void DeleteKeyChord();
|
||||
|
||||
VIEW_MODEL_OBSERVABLE_PROPERTY(bool, IsInEditMode, false);
|
||||
VIEW_MODEL_OBSERVABLE_PROPERTY(Control::KeyChord, ProposedKeys);
|
||||
VIEW_MODEL_OBSERVABLE_PROPERTY(winrt::hstring, KeyChordText);
|
||||
VIEW_MODEL_OBSERVABLE_PROPERTY(Windows::UI::Xaml::Controls::Flyout, AcceptChangesFlyout, nullptr);
|
||||
|
||||
public:
|
||||
til::typed_event<Editor::KeyChordViewModel, Terminal::Control::KeyChord> AddKeyChordRequested;
|
||||
til::typed_event<Editor::KeyChordViewModel, Editor::ModifyKeyChordEventArgs> ModifyKeyChordRequested;
|
||||
til::typed_event<Editor::KeyChordViewModel, Terminal::Control::KeyChord> DeleteKeyChordRequested;
|
||||
|
||||
private:
|
||||
Control::KeyChord _currentKeys;
|
||||
};
|
||||
|
||||
struct ActionsViewModel : ActionsViewModelT<ActionsViewModel>, ViewModelHelper<ActionsViewModel>
|
||||
{
|
||||
public:
|
||||
ActionsViewModel(Model::CascadiaSettings settings);
|
||||
void UpdateSettings(const Model::CascadiaSettings& settings);
|
||||
|
||||
void OnAutomationPeerAttached();
|
||||
void AddNewKeybinding();
|
||||
void AddNewCommand();
|
||||
|
||||
til::typed_event<IInspectable, IInspectable> FocusContainer;
|
||||
til::typed_event<IInspectable, IInspectable> UpdateBackground;
|
||||
void CurrentCommand(const Editor::CommandViewModel& newCommand);
|
||||
Editor::CommandViewModel CurrentCommand();
|
||||
void CmdListItemClicked(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::UI::Xaml::Controls::ItemClickEventArgs& e);
|
||||
|
||||
WINRT_PROPERTY(Windows::Foundation::Collections::IObservableVector<Editor::KeyBindingViewModel>, KeyBindingList);
|
||||
void AttemptDeleteKeyChord(const Control::KeyChord& keys);
|
||||
void AttemptAddOrModifyKeyChord(const Editor::KeyChordViewModel& senderVM, winrt::hstring commandID, const Control::KeyChord& newKeys, const Control::KeyChord& oldKeys);
|
||||
void AttemptAddCopiedCommand(const Model::Command& newCommand);
|
||||
|
||||
WINRT_PROPERTY(Windows::Foundation::Collections::IObservableVector<Editor::CommandViewModel>, CommandList);
|
||||
WINRT_OBSERVABLE_PROPERTY(ActionsSubPage, CurrentPage, _propertyChangedHandlers, ActionsSubPage::Base);
|
||||
|
||||
private:
|
||||
bool _AutomationPeerAttached{ false };
|
||||
Editor::CommandViewModel _CurrentCommand{ nullptr };
|
||||
Model::CascadiaSettings _Settings;
|
||||
Windows::Foundation::Collections::IObservableVector<hstring> _AvailableActionAndArgs;
|
||||
Windows::Foundation::Collections::IMap<hstring, Model::ActionAndArgs> _AvailableActionMap;
|
||||
Windows::Foundation::Collections::IMap<Model::ShortcutAction, winrt::hstring> _AvailableActionsAndNamesMap;
|
||||
|
||||
std::optional<uint32_t> _GetContainerIndexByKeyChord(const Control::KeyChord& keys);
|
||||
void _RegisterEvents(com_ptr<implementation::KeyBindingViewModel>& kbdVM);
|
||||
void _MakeCommandVMsHelper();
|
||||
void _RegisterCmdVMEvents(com_ptr<implementation::CommandViewModel>& cmdVM);
|
||||
|
||||
void _KeyBindingViewModelPropertyChangedHandler(const Windows::Foundation::IInspectable& senderVM, const Windows::UI::Xaml::Data::PropertyChangedEventArgs& args);
|
||||
void _KeyBindingViewModelDeleteKeyBindingHandler(const Editor::KeyBindingViewModel& senderVM, const Control::KeyChord& args);
|
||||
void _KeyBindingViewModelModifyKeyBindingHandler(const Editor::KeyBindingViewModel& senderVM, const Editor::ModifyKeyBindingEventArgs& args);
|
||||
void _KeyBindingViewModelDeleteNewlyAddedKeyBindingHandler(const Editor::KeyBindingViewModel& senderVM, const IInspectable& args);
|
||||
void _CmdVMPropertyChangedHandler(const IInspectable& sender, const Windows::UI::Xaml::Data::PropertyChangedEventArgs& args);
|
||||
void _CmdVMEditRequestedHandler(const Editor::CommandViewModel& senderVM, const IInspectable& args);
|
||||
void _CmdVMDeleteRequestedHandler(const Editor::CommandViewModel& senderVM, const IInspectable& args);
|
||||
void _CmdVMPropagateColorSchemeRequestedHandler(const IInspectable& sender, const Editor::ArgWrapper& wrapper);
|
||||
void _CmdVMPropagateColorSchemeNamesRequestedHandler(const IInspectable& sender, const Editor::ArgWrapper& wrapper);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -1,60 +1,148 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import "EnumEntry.idl";
|
||||
import "ColorSchemeViewModel.idl";
|
||||
import "MainPage.idl";
|
||||
|
||||
namespace Microsoft.Terminal.Settings.Editor
|
||||
{
|
||||
runtimeclass ModifyKeyBindingEventArgs
|
||||
runtimeclass NavigateToCommandArgs
|
||||
{
|
||||
CommandViewModel Command { get; };
|
||||
IHostedInWindow WindowRoot { get; };
|
||||
}
|
||||
|
||||
runtimeclass ModifyKeyChordEventArgs
|
||||
{
|
||||
Microsoft.Terminal.Control.KeyChord OldKeys { get; };
|
||||
Microsoft.Terminal.Control.KeyChord NewKeys { get; };
|
||||
String OldActionName { get; };
|
||||
String NewActionName { get; };
|
||||
}
|
||||
|
||||
runtimeclass KeyBindingViewModel : Windows.UI.Xaml.Data.INotifyPropertyChanged
|
||||
runtimeclass CommandViewModel : Windows.UI.Xaml.Data.INotifyPropertyChanged
|
||||
{
|
||||
// Settings Model side
|
||||
String Name;
|
||||
String ID;
|
||||
Boolean IsUserAction { get; };
|
||||
// keybindings
|
||||
IObservableVector<KeyChordViewModel> KeyChordViewModelList { get; };
|
||||
// action args
|
||||
ActionArgsViewModel ActionArgsVM { get; };
|
||||
|
||||
// View-model specific
|
||||
String DisplayName { get; };
|
||||
|
||||
// UI side (command list page)
|
||||
void Edit_Click();
|
||||
|
||||
// UI side (edit command page)
|
||||
IObservableVector<String> AvailableShortcutActions { get; };
|
||||
Object ProposedShortcutAction;
|
||||
void Delete_Click();
|
||||
void AddKeybinding_Click();
|
||||
event Windows.Foundation.TypedEventHandler<Object, ArgWrapper> PropagateColorSchemeRequested;
|
||||
event Windows.Foundation.TypedEventHandler<Object, ArgWrapper> PropagateColorSchemeNamesRequested;
|
||||
event Windows.Foundation.TypedEventHandler<Object, ArgWrapper> PropagateWindowRootRequested;
|
||||
}
|
||||
|
||||
runtimeclass ArgWrapper : Windows.UI.Xaml.Data.INotifyPropertyChanged
|
||||
{
|
||||
String Name { get; };
|
||||
String Type { get; };
|
||||
Microsoft.Terminal.Settings.Model.ArgTypeHint TypeHint { get; };
|
||||
Boolean Required { get; };
|
||||
IInspectable Value;
|
||||
IInspectable EnumValue;
|
||||
Windows.Foundation.Collections.IObservableVector<Microsoft.Terminal.Settings.Editor.EnumEntry> EnumList { get; };
|
||||
Windows.Foundation.Collections.IObservableVector<Microsoft.Terminal.Settings.Editor.FlagEntry> FlagList { get; };
|
||||
ColorSchemeViewModel DefaultColorScheme;
|
||||
Windows.Foundation.Collections.IVector<String> ColorSchemeNamesList;
|
||||
IHostedInWindow WindowRoot;
|
||||
|
||||
// unboxing functions
|
||||
String UnboxString(Object value);
|
||||
String UnboxGuid(Object value);
|
||||
UInt32 UnboxInt32(Object value);
|
||||
Single UnboxInt32Optional(Object value);
|
||||
UInt32 UnboxUInt32(Object value);
|
||||
Single UnboxUInt32Optional(Object value);
|
||||
Single UnboxUInt64(Object value);
|
||||
Single UnboxFloat(Object value);
|
||||
Boolean UnboxBool(Object value);
|
||||
Windows.Foundation.IReference<Boolean> UnboxBoolOptional(Object value);
|
||||
Windows.Foundation.IReference<Microsoft.Terminal.Core.Color> UnboxTerminalCoreColorOptional(Object value);
|
||||
Windows.Foundation.IReference<Microsoft.Terminal.Core.Color> UnboxWindowsUIColorOptional(Object value);
|
||||
|
||||
// bind back functions
|
||||
void StringBindBack(String newValue);
|
||||
void GuidBindBack(String newValue);
|
||||
void Int32BindBack(Double newValue);
|
||||
void Int32OptionalBindBack(Double newValue);
|
||||
void UInt32BindBack(Double newValue);
|
||||
void UInt32OptionalBindBack(Double newValue);
|
||||
void UInt64BindBack(Double newValue);
|
||||
void FloatBindBack(Double newValue);
|
||||
void BoolOptionalBindBack(Windows.Foundation.IReference<Boolean> newValue);
|
||||
void TerminalCoreColorBindBack(Windows.Foundation.IReference<Microsoft.Terminal.Core.Color> newValue);
|
||||
void WindowsUIColorBindBack(Windows.Foundation.IReference<Microsoft.Terminal.Core.Color> newValue);
|
||||
|
||||
void Browse_Click(IInspectable sender, Windows.UI.Xaml.RoutedEventArgs args);
|
||||
|
||||
event Windows.Foundation.TypedEventHandler<Object, ArgWrapper> ColorSchemeRequested;
|
||||
event Windows.Foundation.TypedEventHandler<Object, ArgWrapper> ColorSchemeNamesRequested;
|
||||
event Windows.Foundation.TypedEventHandler<Object, ArgWrapper> WindowRootRequested;
|
||||
}
|
||||
|
||||
runtimeclass ActionArgsViewModel : Windows.UI.Xaml.Data.INotifyPropertyChanged
|
||||
{
|
||||
Boolean HasArgs { get; };
|
||||
IObservableVector<ArgWrapper> ArgValues;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> WrapperValueChanged;
|
||||
event Windows.Foundation.TypedEventHandler<Object, ArgWrapper> PropagateColorSchemeRequested;
|
||||
event Windows.Foundation.TypedEventHandler<Object, ArgWrapper> PropagateColorSchemeNamesRequested;
|
||||
event Windows.Foundation.TypedEventHandler<Object, ArgWrapper> PropagateWindowRootRequested;
|
||||
}
|
||||
|
||||
runtimeclass KeyChordViewModel : Windows.UI.Xaml.Data.INotifyPropertyChanged
|
||||
{
|
||||
String KeyChordText { get; };
|
||||
|
||||
// UI side
|
||||
Boolean ShowEditButton { get; };
|
||||
Boolean IsInEditMode { get; };
|
||||
Boolean IsNewlyAdded { get; };
|
||||
Microsoft.Terminal.Control.KeyChord ProposedKeys;
|
||||
Object ProposedAction;
|
||||
Windows.UI.Xaml.Controls.Flyout AcceptChangesFlyout;
|
||||
String EditButtonName { get; };
|
||||
String CancelButtonName { get; };
|
||||
String AcceptButtonName { get; };
|
||||
String DeleteButtonName { get; };
|
||||
Windows.UI.Xaml.Media.Brush ContainerBackground { get; };
|
||||
|
||||
void EnterHoverMode();
|
||||
void ExitHoverMode();
|
||||
void ActionGotFocus();
|
||||
void ActionLostFocus();
|
||||
void EditButtonGettingFocus();
|
||||
void EditButtonLosingFocus();
|
||||
IObservableVector<String> AvailableActions { get; };
|
||||
Boolean IsInEditMode { get; };
|
||||
void ToggleEditMode();
|
||||
void AttemptAcceptChanges();
|
||||
void CancelChanges();
|
||||
void DeleteKeyBinding();
|
||||
void DeleteKeyChord();
|
||||
|
||||
event Windows.Foundation.TypedEventHandler<KeyBindingViewModel, ModifyKeyBindingEventArgs> ModifyKeyBindingRequested;
|
||||
event Windows.Foundation.TypedEventHandler<KeyBindingViewModel, Microsoft.Terminal.Control.KeyChord> DeleteKeyBindingRequested;
|
||||
event Windows.Foundation.TypedEventHandler<KeyChordViewModel, Microsoft.Terminal.Control.KeyChord> AddKeyChordRequested;
|
||||
event Windows.Foundation.TypedEventHandler<KeyChordViewModel, ModifyKeyChordEventArgs> ModifyKeyChordRequested;
|
||||
event Windows.Foundation.TypedEventHandler<KeyChordViewModel, Microsoft.Terminal.Control.KeyChord> DeleteKeyChordRequested;
|
||||
}
|
||||
|
||||
enum ActionsSubPage
|
||||
{
|
||||
Base = 0,
|
||||
Edit = 1
|
||||
};
|
||||
|
||||
runtimeclass ActionsViewModel : Windows.UI.Xaml.Data.INotifyPropertyChanged
|
||||
{
|
||||
ActionsViewModel(Microsoft.Terminal.Settings.Model.CascadiaSettings settings);
|
||||
void UpdateSettings(Microsoft.Terminal.Settings.Model.CascadiaSettings settings);
|
||||
|
||||
void OnAutomationPeerAttached();
|
||||
void AddNewKeybinding();
|
||||
void AddNewCommand();
|
||||
|
||||
IObservableVector<KeyBindingViewModel> KeyBindingList { get; };
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> FocusContainer;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> UpdateBackground;
|
||||
ActionsSubPage CurrentPage;
|
||||
CommandViewModel CurrentCommand;
|
||||
|
||||
void AttemptAddOrModifyKeyChord(KeyChordViewModel senderVM, String commandID, Microsoft.Terminal.Control.KeyChord newKeys, Microsoft.Terminal.Control.KeyChord oldKeys);
|
||||
void AttemptDeleteKeyChord(Microsoft.Terminal.Control.KeyChord keys);
|
||||
void AttemptAddCopiedCommand(Microsoft.Terminal.Settings.Model.Command newCommand);
|
||||
|
||||
IObservableVector<CommandViewModel> CommandList { get; };
|
||||
void CmdListItemClicked(IInspectable sender, Windows.UI.Xaml.Controls.ItemClickEventArgs args);
|
||||
}
|
||||
}
|
||||
|
||||
117
src/cascadia/TerminalSettingsEditor/ArgsTemplateSelectors.cpp
Normal file
117
src/cascadia/TerminalSettingsEditor/ArgsTemplateSelectors.cpp
Normal file
@@ -0,0 +1,117 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#include "pch.h"
|
||||
#include "ArgsTemplateSelectors.h"
|
||||
#include "ArgsTemplateSelectors.g.cpp"
|
||||
|
||||
namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
{
|
||||
Windows::UI::Xaml::DataTemplate ArgsTemplateSelectors::SelectTemplateCore(const winrt::Windows::Foundation::IInspectable& item, const winrt::Windows::UI::Xaml::DependencyObject& /*container*/)
|
||||
{
|
||||
return SelectTemplateCore(item);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - This method is called once command palette decides how to render a filtered command.
|
||||
// Currently we support two ways to render command, that depend on its palette item type:
|
||||
// - For TabPalette item we render an icon, a title, and some tab-related indicators like progress bar (as defined by TabItemTemplate)
|
||||
// - All other items are currently rendered with icon, title and optional key-chord (as defined by GeneralItemTemplate)
|
||||
// Arguments:
|
||||
// - item - an instance of filtered command to render
|
||||
// Return Value:
|
||||
// - data template to use for rendering
|
||||
Windows::UI::Xaml::DataTemplate ArgsTemplateSelectors::SelectTemplateCore(const winrt::Windows::Foundation::IInspectable& item)
|
||||
{
|
||||
if (const auto argWrapper{ item.try_as<Microsoft::Terminal::Settings::Editor::ArgWrapper>() })
|
||||
{
|
||||
const auto argType = argWrapper.Type();
|
||||
if (argType == L"winrt::hstring")
|
||||
{
|
||||
// string has some special cases - check the tag
|
||||
const auto argTag = argWrapper.TypeHint();
|
||||
if (argTag == Model::ArgTypeHint::ColorScheme)
|
||||
{
|
||||
return ColorSchemeTemplate();
|
||||
}
|
||||
else if (argTag == Model::ArgTypeHint::FilePath)
|
||||
{
|
||||
return FilePickerTemplate();
|
||||
}
|
||||
|
||||
// no special handling required, just return the normal string template
|
||||
return StringTemplate();
|
||||
}
|
||||
else if (argType == L"winrt::guid")
|
||||
{
|
||||
return GuidTemplate();
|
||||
}
|
||||
else if (argType == L"int32_t")
|
||||
{
|
||||
return Int32Template();
|
||||
}
|
||||
else if (argType == L"uint32_t")
|
||||
{
|
||||
return UInt32Template();
|
||||
}
|
||||
else if (argType == L"uint64_t")
|
||||
{
|
||||
return UInt64Template();
|
||||
}
|
||||
else if (argType == L"float")
|
||||
{
|
||||
return FloatTemplate();
|
||||
}
|
||||
else if (argType == L"bool")
|
||||
{
|
||||
return BoolTemplate();
|
||||
}
|
||||
else if (argType == L"Windows::Foundation::IReference<bool>")
|
||||
{
|
||||
return BoolOptionalTemplate();
|
||||
}
|
||||
else if (argType == L"Windows::Foundation::IReference<int32_t>")
|
||||
{
|
||||
return Int32OptionalTemplate();
|
||||
}
|
||||
else if (argType == L"Windows::Foundation::IReference<uint32_t>")
|
||||
{
|
||||
return UInt32OptionalTemplate();
|
||||
}
|
||||
else if (argType == L"Model::ResizeDirection" ||
|
||||
argType == L"Model::FocusDirection" ||
|
||||
argType == L"SettingsTarget" ||
|
||||
argType == L"MoveTabDirection" ||
|
||||
argType == L"Microsoft::Terminal::Control::ScrollToMarkDirection" ||
|
||||
argType == L"CommandPaletteLaunchMode" ||
|
||||
argType == L"FindMatchDirection" ||
|
||||
argType == L"Model::DesktopBehavior" ||
|
||||
argType == L"Model::MonitorBehavior" ||
|
||||
argType == L"winrt::Microsoft::Terminal::Control::ClearBufferType" ||
|
||||
argType == L"SelectOutputDirection" ||
|
||||
argType == L"Windows::Foundation::IReference<TabSwitcherMode>" ||
|
||||
argType == L"Model::SplitDirection" ||
|
||||
argType == L"SplitType")
|
||||
{
|
||||
return EnumTemplate();
|
||||
}
|
||||
else if (argType == L"SuggestionsSource")
|
||||
{
|
||||
return FlagTemplate();
|
||||
}
|
||||
else if (argType == L"Windows::Foundation::IReference<Microsoft::Terminal::Core::Color>")
|
||||
{
|
||||
return TerminalCoreColorOptionalTemplate();
|
||||
}
|
||||
else if (argType == L"Windows::Foundation::IReference<Windows::UI::Color>")
|
||||
{
|
||||
return WindowsUIColorOptionalTemplate();
|
||||
}
|
||||
else if (argType == L"Windows::Foundation::IReference<Control::CopyFormat>")
|
||||
{
|
||||
return FlagTemplate();
|
||||
}
|
||||
}
|
||||
return NoArgTemplate();
|
||||
}
|
||||
}
|
||||
40
src/cascadia/TerminalSettingsEditor/ArgsTemplateSelectors.h
Normal file
40
src/cascadia/TerminalSettingsEditor/ArgsTemplateSelectors.h
Normal file
@@ -0,0 +1,40 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ArgsTemplateSelectors.g.h"
|
||||
|
||||
namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
{
|
||||
struct ArgsTemplateSelectors : ArgsTemplateSelectorsT<ArgsTemplateSelectors>
|
||||
{
|
||||
ArgsTemplateSelectors() = default;
|
||||
|
||||
Windows::UI::Xaml::DataTemplate SelectTemplateCore(const winrt::Windows::Foundation::IInspectable&, const winrt::Windows::UI::Xaml::DependencyObject&);
|
||||
Windows::UI::Xaml::DataTemplate SelectTemplateCore(const winrt::Windows::Foundation::IInspectable&);
|
||||
|
||||
WINRT_PROPERTY(winrt::Windows::UI::Xaml::DataTemplate, NoArgTemplate);
|
||||
WINRT_PROPERTY(winrt::Windows::UI::Xaml::DataTemplate, GuidTemplate);
|
||||
WINRT_PROPERTY(winrt::Windows::UI::Xaml::DataTemplate, Int32Template);
|
||||
WINRT_PROPERTY(winrt::Windows::UI::Xaml::DataTemplate, Int32OptionalTemplate);
|
||||
WINRT_PROPERTY(winrt::Windows::UI::Xaml::DataTemplate, UInt32Template);
|
||||
WINRT_PROPERTY(winrt::Windows::UI::Xaml::DataTemplate, UInt32OptionalTemplate);
|
||||
WINRT_PROPERTY(winrt::Windows::UI::Xaml::DataTemplate, UInt64Template);
|
||||
WINRT_PROPERTY(winrt::Windows::UI::Xaml::DataTemplate, FloatTemplate);
|
||||
WINRT_PROPERTY(winrt::Windows::UI::Xaml::DataTemplate, StringTemplate);
|
||||
WINRT_PROPERTY(winrt::Windows::UI::Xaml::DataTemplate, ColorSchemeTemplate);
|
||||
WINRT_PROPERTY(winrt::Windows::UI::Xaml::DataTemplate, FilePickerTemplate);
|
||||
WINRT_PROPERTY(winrt::Windows::UI::Xaml::DataTemplate, BoolTemplate);
|
||||
WINRT_PROPERTY(winrt::Windows::UI::Xaml::DataTemplate, BoolOptionalTemplate);
|
||||
WINRT_PROPERTY(winrt::Windows::UI::Xaml::DataTemplate, EnumTemplate);
|
||||
WINRT_PROPERTY(winrt::Windows::UI::Xaml::DataTemplate, FlagTemplate);
|
||||
WINRT_PROPERTY(winrt::Windows::UI::Xaml::DataTemplate, TerminalCoreColorOptionalTemplate);
|
||||
WINRT_PROPERTY(winrt::Windows::UI::Xaml::DataTemplate, WindowsUIColorOptionalTemplate);
|
||||
};
|
||||
}
|
||||
|
||||
namespace winrt::Microsoft::Terminal::Settings::Editor::factory_implementation
|
||||
{
|
||||
BASIC_FACTORY(ArgsTemplateSelectors);
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
namespace Microsoft.Terminal.Settings.Editor
|
||||
{
|
||||
[default_interface] runtimeclass ArgsTemplateSelectors : Windows.UI.Xaml.Controls.DataTemplateSelector
|
||||
{
|
||||
ArgsTemplateSelectors();
|
||||
|
||||
Windows.UI.Xaml.DataTemplate NoArgTemplate;
|
||||
Windows.UI.Xaml.DataTemplate GuidTemplate;
|
||||
Windows.UI.Xaml.DataTemplate Int32Template;
|
||||
Windows.UI.Xaml.DataTemplate Int32OptionalTemplate;
|
||||
Windows.UI.Xaml.DataTemplate UInt32Template;
|
||||
Windows.UI.Xaml.DataTemplate UInt32OptionalTemplate;
|
||||
Windows.UI.Xaml.DataTemplate UInt64Template;
|
||||
Windows.UI.Xaml.DataTemplate FloatTemplate;
|
||||
Windows.UI.Xaml.DataTemplate StringTemplate;
|
||||
Windows.UI.Xaml.DataTemplate ColorSchemeTemplate;
|
||||
Windows.UI.Xaml.DataTemplate FilePickerTemplate;
|
||||
Windows.UI.Xaml.DataTemplate BoolTemplate;
|
||||
Windows.UI.Xaml.DataTemplate BoolOptionalTemplate;
|
||||
Windows.UI.Xaml.DataTemplate EnumTemplate;
|
||||
Windows.UI.Xaml.DataTemplate FlagTemplate;
|
||||
Windows.UI.Xaml.DataTemplate TerminalCoreColorOptionalTemplate;
|
||||
Windows.UI.Xaml.DataTemplate WindowsUIColorOptionalTemplate;
|
||||
}
|
||||
}
|
||||
56
src/cascadia/TerminalSettingsEditor/EditAction.cpp
Normal file
56
src/cascadia/TerminalSettingsEditor/EditAction.cpp
Normal file
@@ -0,0 +1,56 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#include "pch.h"
|
||||
#include "EditAction.h"
|
||||
#include "EditAction.g.cpp"
|
||||
#include "LibraryResources.h"
|
||||
#include "../TerminalSettingsModel/AllShortcutActions.h"
|
||||
|
||||
using namespace winrt::Windows::UI::Xaml;
|
||||
using namespace winrt::Windows::UI::Xaml::Navigation;
|
||||
|
||||
namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
{
|
||||
EditAction::EditAction()
|
||||
{
|
||||
InitializeComponent();
|
||||
_itemTemplateSelector = Resources().Lookup(winrt::box_value(L"ArgsTemplateSelector")).try_as<ArgsTemplateSelectors>();
|
||||
_listItemTemplate = Resources().Lookup(winrt::box_value(L"ListItemTemplate")).try_as<DataTemplate>();
|
||||
}
|
||||
|
||||
void EditAction::OnNavigatedTo(const NavigationEventArgs& e)
|
||||
{
|
||||
const auto args = e.Parameter().as<Editor::NavigateToCommandArgs>();
|
||||
_ViewModel = args.Command();
|
||||
_windowRoot = args.WindowRoot();
|
||||
_ViewModel.PropagateWindowRootRequested([weakThis = get_weak()](const IInspectable& /*sender*/, const Editor::ArgWrapper& wrapper) {
|
||||
if (auto weak = weakThis.get())
|
||||
{
|
||||
if (wrapper)
|
||||
{
|
||||
wrapper.WindowRoot(weak->_windowRoot);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void EditAction::_choosingItemContainer(
|
||||
const Windows::UI::Xaml::Controls::ListViewBase& /*sender*/,
|
||||
const Windows::UI::Xaml::Controls::ChoosingItemContainerEventArgs& args)
|
||||
{
|
||||
const auto dataTemplate = _itemTemplateSelector.SelectTemplate(args.Item());
|
||||
const auto itemContainer = args.ItemContainer();
|
||||
|
||||
if (!itemContainer || itemContainer.ContentTemplate() != dataTemplate)
|
||||
{
|
||||
ElementFactoryGetArgs factoryArgs{};
|
||||
const auto listViewItem = _listItemTemplate.GetElement(factoryArgs).try_as<Controls::ListViewItem>();
|
||||
listViewItem.ContentTemplate(dataTemplate);
|
||||
|
||||
args.ItemContainer(listViewItem);
|
||||
}
|
||||
|
||||
args.IsContainerPrepared(true);
|
||||
}
|
||||
}
|
||||
35
src/cascadia/TerminalSettingsEditor/EditAction.h
Normal file
35
src/cascadia/TerminalSettingsEditor/EditAction.h
Normal file
@@ -0,0 +1,35 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "EditAction.g.h"
|
||||
#include "ActionsViewModel.h"
|
||||
#include "Utils.h"
|
||||
#include "ViewModelHelpers.h"
|
||||
|
||||
namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
{
|
||||
struct EditAction : public HasScrollViewer<EditAction>, EditActionT<EditAction>
|
||||
{
|
||||
public:
|
||||
EditAction();
|
||||
void OnNavigatedTo(const winrt::Windows::UI::Xaml::Navigation::NavigationEventArgs& e);
|
||||
|
||||
til::property_changed_event PropertyChanged;
|
||||
|
||||
WINRT_OBSERVABLE_PROPERTY(Editor::CommandViewModel, ViewModel, PropertyChanged.raise, nullptr);
|
||||
|
||||
private:
|
||||
friend struct EditActionT<EditAction>; // for Xaml to bind events
|
||||
Editor::IHostedInWindow _windowRoot;
|
||||
Windows::UI::Xaml::DataTemplate _listItemTemplate;
|
||||
winrt::Microsoft::Terminal::Settings::Editor::ArgsTemplateSelectors _itemTemplateSelector{ nullptr };
|
||||
void _choosingItemContainer(const Windows::UI::Xaml::Controls::ListViewBase& sender, const Windows::UI::Xaml::Controls::ChoosingItemContainerEventArgs& args);
|
||||
};
|
||||
}
|
||||
|
||||
namespace winrt::Microsoft::Terminal::Settings::Editor::factory_implementation
|
||||
{
|
||||
BASIC_FACTORY(EditAction);
|
||||
}
|
||||
13
src/cascadia/TerminalSettingsEditor/EditAction.idl
Normal file
13
src/cascadia/TerminalSettingsEditor/EditAction.idl
Normal file
@@ -0,0 +1,13 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import "ActionsViewModel.idl";
|
||||
|
||||
namespace Microsoft.Terminal.Settings.Editor
|
||||
{
|
||||
[default_interface] runtimeclass EditAction : Windows.UI.Xaml.Controls.Page, Windows.UI.Xaml.Data.INotifyPropertyChanged
|
||||
{
|
||||
EditAction();
|
||||
CommandViewModel ViewModel { get; };
|
||||
}
|
||||
}
|
||||
703
src/cascadia/TerminalSettingsEditor/EditAction.xaml
Normal file
703
src/cascadia/TerminalSettingsEditor/EditAction.xaml
Normal file
@@ -0,0 +1,703 @@
|
||||
<!--
|
||||
Copyright (c) Microsoft Corporation. All rights reserved. Licensed under
|
||||
the MIT License. See LICENSE in the project root for license information.
|
||||
-->
|
||||
<Page x:Class="Microsoft.Terminal.Settings.Editor.EditAction"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="using:Microsoft.Terminal.Settings.Editor"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:mtu="using:Microsoft.Terminal.UI"
|
||||
xmlns:muxc="using:Microsoft.UI.Xaml.Controls"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<Page.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceDictionary Source="CommonResources.xaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
<!-- Theme Dictionary -->
|
||||
<ResourceDictionary.ThemeDictionaries>
|
||||
<ResourceDictionary x:Key="Dark">
|
||||
<!-- KeyChordText styles -->
|
||||
<Style x:Key="KeyChordBorderStyle"
|
||||
TargetType="Button">
|
||||
<Setter Property="BorderThickness" Value="1" />
|
||||
<Setter Property="CornerRadius" Value="1" />
|
||||
<Setter Property="Background" Value="{ThemeResource SystemAltMediumLowColor}" />
|
||||
<Setter Property="BorderBrush" Value="{ThemeResource SystemControlForegroundBaseMediumBrush}" />
|
||||
<!-- Override visual states -->
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="Button">
|
||||
<Grid>
|
||||
<!-- Define the appearance of the button -->
|
||||
<Border x:Name="border"
|
||||
Background="{TemplateBinding Background}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
CornerRadius="{TemplateBinding CornerRadius}">
|
||||
<ContentPresenter HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center" />
|
||||
</Border>
|
||||
<VisualStateManager.VisualStateGroups>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
<VisualState x:Name="Normal" />
|
||||
<VisualState x:Name="PointerOver">
|
||||
<Storyboard>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="border"
|
||||
Storyboard.TargetProperty="Background">
|
||||
<DiscreteObjectKeyFrame KeyTime="0"
|
||||
Value="{ThemeResource SystemControlHighlightAccentRevealBackgroundBrush}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
</Storyboard>
|
||||
</VisualState>
|
||||
<VisualState x:Name="Pressed" />
|
||||
<VisualState x:Name="Disabled" />
|
||||
</VisualStateGroup>
|
||||
</VisualStateManager.VisualStateGroups>
|
||||
</Grid>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
<Style x:Key="KeyChordTextBlockStyle"
|
||||
TargetType="TextBlock">
|
||||
<Setter Property="Foreground" Value="{ThemeResource SystemControlForegroundBaseMediumBrush}" />
|
||||
</Style>
|
||||
</ResourceDictionary>
|
||||
<ResourceDictionary x:Key="Light">
|
||||
<!-- KeyChordText styles -->
|
||||
<Style x:Key="KeyChordBorderStyle"
|
||||
TargetType="Button">
|
||||
<Setter Property="BorderThickness" Value="1" />
|
||||
<Setter Property="CornerRadius" Value="1" />
|
||||
<Setter Property="Background" Value="{ThemeResource SystemAltMediumLowColor}" />
|
||||
<Setter Property="BorderBrush" Value="{ThemeResource SystemControlForegroundBaseMediumBrush}" />
|
||||
<!-- Override visual states -->
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="Button">
|
||||
<Grid>
|
||||
<!-- Define the appearance of the button -->
|
||||
<Border x:Name="border"
|
||||
Background="{TemplateBinding Background}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
CornerRadius="{TemplateBinding CornerRadius}">
|
||||
<ContentPresenter HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center" />
|
||||
</Border>
|
||||
<VisualStateManager.VisualStateGroups>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
<VisualState x:Name="Normal" />
|
||||
<VisualState x:Name="PointerOver">
|
||||
<Storyboard>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="border"
|
||||
Storyboard.TargetProperty="Background">
|
||||
<DiscreteObjectKeyFrame KeyTime="0"
|
||||
Value="{ThemeResource SystemControlHighlightAccentRevealBackgroundBrush}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
</Storyboard>
|
||||
</VisualState>
|
||||
<VisualState x:Name="Pressed" />
|
||||
<VisualState x:Name="Disabled" />
|
||||
</VisualStateGroup>
|
||||
</VisualStateManager.VisualStateGroups>
|
||||
</Grid>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
<Style x:Key="KeyChordTextBlockStyle"
|
||||
TargetType="TextBlock">
|
||||
<Setter Property="Foreground" Value="{ThemeResource SystemControlForegroundBaseMediumBrush}" />
|
||||
</Style>
|
||||
</ResourceDictionary>
|
||||
<ResourceDictionary x:Key="HighContrast">
|
||||
<!-- KeyChordText styles (use XAML defaults for High Contrast theme) -->
|
||||
<Style x:Key="KeyChordBorderStyle"
|
||||
TargetType="Button" />
|
||||
<Style x:Key="KeyChordTextBlockStyle"
|
||||
TargetType="TextBlock" />
|
||||
</ResourceDictionary>
|
||||
</ResourceDictionary.ThemeDictionaries>
|
||||
|
||||
<GridLength x:Key="ArgumentNameWidth">148</GridLength>
|
||||
|
||||
<!-- Styles -->
|
||||
<Style x:Key="KeyBindingContainerStyle"
|
||||
BasedOn="{StaticResource DefaultListViewItemStyle}"
|
||||
TargetType="ListViewItem">
|
||||
<Setter Property="Padding" Value="4" />
|
||||
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
|
||||
<Setter Property="XYFocusKeyboardNavigation" Value="Enabled" />
|
||||
</Style>
|
||||
<Style x:Key="KeyChordEditorStyle"
|
||||
TargetType="local:KeyChordListener">
|
||||
<Setter Property="HorizontalAlignment" Value="Left" />
|
||||
<Setter Property="VerticalAlignment" Value="Center" />
|
||||
</Style>
|
||||
<x:Int32 x:Key="EditButtonSize">32</x:Int32>
|
||||
<x:Double x:Key="EditButtonIconSize">15</x:Double>
|
||||
<Style x:Key="EditButtonStyle"
|
||||
BasedOn="{StaticResource DefaultButtonStyle}"
|
||||
TargetType="Button">
|
||||
<Setter Property="Padding" Value="0" />
|
||||
<Setter Property="VerticalAlignment" Value="Center" />
|
||||
<Setter Property="Height" Value="{StaticResource EditButtonSize}" />
|
||||
<Setter Property="Width" Value="{StaticResource EditButtonSize}" />
|
||||
</Style>
|
||||
<Style x:Key="AccentEditButtonStyle"
|
||||
BasedOn="{StaticResource AccentButtonStyle}"
|
||||
TargetType="Button">
|
||||
<Setter Property="Padding" Value="3" />
|
||||
<Setter Property="VerticalAlignment" Value="Center" />
|
||||
<Setter Property="Height" Value="{StaticResource EditButtonSize}" />
|
||||
<Setter Property="Width" Value="{StaticResource EditButtonSize}" />
|
||||
</Style>
|
||||
|
||||
<!-- Templates -->
|
||||
<DataTemplate x:Key="KeyChordTemplate"
|
||||
x:DataType="local:KeyChordViewModel">
|
||||
<ListViewItem Style="{StaticResource KeyBindingContainerStyle}">
|
||||
<Grid Padding="2,0,2,0"
|
||||
VerticalAlignment="Center">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Button Grid.Column="0"
|
||||
Click="{x:Bind ToggleEditMode}"
|
||||
Style="{ThemeResource KeyChordBorderStyle}"
|
||||
Visibility="{x:Bind mtu:Converters.InvertedBooleanToVisibility(IsInEditMode), Mode=OneWay}">
|
||||
<TextBlock FontSize="14"
|
||||
Style="{ThemeResource KeyChordTextBlockStyle}"
|
||||
Text="{x:Bind KeyChordText, Mode=OneWay}"
|
||||
TextWrapping="WrapWholeWords" />
|
||||
</Button>
|
||||
<Grid Grid.Column="0"
|
||||
ColumnSpacing="8"
|
||||
Visibility="{x:Bind IsInEditMode, Mode=OneWay}">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<!-- Edit Mode: Key Chord Listener -->
|
||||
<local:KeyChordListener Grid.Column="0"
|
||||
Keys="{x:Bind ProposedKeys, Mode=TwoWay}"
|
||||
Style="{StaticResource KeyChordEditorStyle}" />
|
||||
|
||||
<!-- Cancel editing the action -->
|
||||
<Button x:Uid="Actions_CancelButton"
|
||||
Grid.Column="1"
|
||||
Click="{x:Bind CancelChanges}"
|
||||
Style="{StaticResource EditButtonStyle}">
|
||||
<FontIcon FontSize="{StaticResource EditButtonIconSize}"
|
||||
Glyph="" />
|
||||
</Button>
|
||||
|
||||
<!-- Accept changes -->
|
||||
<Button x:Uid="Actions_AcceptButton"
|
||||
Grid.Column="2"
|
||||
Click="{x:Bind AttemptAcceptChanges}"
|
||||
Flyout="{x:Bind AcceptChangesFlyout, Mode=OneWay}"
|
||||
Style="{StaticResource AccentEditButtonStyle}">
|
||||
<FontIcon FontSize="{StaticResource EditButtonIconSize}"
|
||||
Glyph="" />
|
||||
</Button>
|
||||
</Grid>
|
||||
<Button Grid.Column="1"
|
||||
Margin="8,0,0,0"
|
||||
Style="{StaticResource DeleteSmallButtonStyle}">
|
||||
<Button.Content>
|
||||
<FontIcon FontSize="{StaticResource EditButtonIconSize}"
|
||||
Glyph="" />
|
||||
</Button.Content>
|
||||
<Button.Flyout>
|
||||
<Flyout>
|
||||
<StackPanel>
|
||||
<TextBlock x:Uid="Actions_DeleteConfirmationMessage"
|
||||
Style="{StaticResource CustomFlyoutTextStyle}" />
|
||||
<Button x:Uid="Actions_DeleteConfirmationButton"
|
||||
Click="{x:Bind DeleteKeyChord}" />
|
||||
</StackPanel>
|
||||
</Flyout>
|
||||
</Button.Flyout>
|
||||
</Button>
|
||||
</Grid>
|
||||
</ListViewItem>
|
||||
</DataTemplate>
|
||||
|
||||
<DataTemplate x:Key="ListItemTemplate"
|
||||
x:DataType="local:ArgWrapper">
|
||||
<ListViewItem HorizontalContentAlignment="Stretch" />
|
||||
</DataTemplate>
|
||||
|
||||
<DataTemplate x:Key="NoArgTemplate"
|
||||
x:DataType="local:ArgWrapper">
|
||||
<ListViewItem />
|
||||
</DataTemplate>
|
||||
|
||||
<DataTemplate x:Key="Int32Template"
|
||||
x:DataType="local:ArgWrapper">
|
||||
<ListViewItem>
|
||||
<Grid ColumnSpacing="8">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="{StaticResource ArgumentNameWidth}" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Grid.Column="0"
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Bind Name}" />
|
||||
<muxc:NumberBox Grid.Column="1"
|
||||
LargeChange="1"
|
||||
Maximum="999"
|
||||
Minimum="0"
|
||||
SmallChange="1"
|
||||
Style="{StaticResource NumberBoxSettingStyle}"
|
||||
Value="{x:Bind UnboxInt32(Value), Mode=TwoWay, BindBack=Int32BindBack}" />
|
||||
</Grid>
|
||||
</ListViewItem>
|
||||
</DataTemplate>
|
||||
|
||||
<DataTemplate x:Key="UInt32Template"
|
||||
x:DataType="local:ArgWrapper">
|
||||
<ListViewItem>
|
||||
<Grid ColumnSpacing="8">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="{StaticResource ArgumentNameWidth}" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Grid.Column="0"
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Bind Name}" />
|
||||
<muxc:NumberBox Grid.Column="1"
|
||||
LargeChange="1"
|
||||
Maximum="999"
|
||||
Minimum="0"
|
||||
SmallChange="1"
|
||||
Style="{StaticResource NumberBoxSettingStyle}"
|
||||
Value="{x:Bind UnboxUInt32(Value), Mode=TwoWay, BindBack=UInt32BindBack}" />
|
||||
</Grid>
|
||||
</ListViewItem>
|
||||
</DataTemplate>
|
||||
|
||||
<DataTemplate x:Key="UInt32OptionalTemplate"
|
||||
x:DataType="local:ArgWrapper">
|
||||
<ListViewItem>
|
||||
<Grid ColumnSpacing="8">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="{StaticResource ArgumentNameWidth}" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Grid.Column="0"
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Bind Name}" />
|
||||
<muxc:NumberBox Grid.Column="1"
|
||||
LargeChange="1"
|
||||
Maximum="999"
|
||||
Minimum="0"
|
||||
SmallChange="1"
|
||||
Style="{StaticResource NumberBoxSettingStyle}"
|
||||
Value="{x:Bind UnboxUInt32Optional(Value), Mode=TwoWay, BindBack=UInt32OptionalBindBack}" />
|
||||
</Grid>
|
||||
</ListViewItem>
|
||||
</DataTemplate>
|
||||
|
||||
<DataTemplate x:Key="UInt64Template"
|
||||
x:DataType="local:ArgWrapper">
|
||||
<ListViewItem>
|
||||
<Grid ColumnSpacing="8">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="{StaticResource ArgumentNameWidth}" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Grid.Column="0"
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Bind Name}" />
|
||||
<muxc:NumberBox Grid.Column="1"
|
||||
LargeChange="1"
|
||||
Maximum="999"
|
||||
Minimum="0"
|
||||
SmallChange="1"
|
||||
Style="{StaticResource NumberBoxSettingStyle}"
|
||||
Value="{x:Bind UnboxUInt64(Value), Mode=TwoWay, BindBack=UInt64BindBack}" />
|
||||
</Grid>
|
||||
</ListViewItem>
|
||||
</DataTemplate>
|
||||
|
||||
<DataTemplate x:Key="Int32OptionalTemplate"
|
||||
x:DataType="local:ArgWrapper">
|
||||
<ListViewItem>
|
||||
<Grid ColumnSpacing="8">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="{StaticResource ArgumentNameWidth}" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Grid.Column="0"
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Bind Name}" />
|
||||
<muxc:NumberBox Grid.Column="1"
|
||||
LargeChange="1"
|
||||
Maximum="999"
|
||||
Minimum="0"
|
||||
SmallChange="1"
|
||||
Style="{StaticResource NumberBoxSettingStyle}"
|
||||
Value="{x:Bind UnboxInt32Optional(Value), Mode=TwoWay, BindBack=Int32OptionalBindBack}" />
|
||||
</Grid>
|
||||
</ListViewItem>
|
||||
</DataTemplate>
|
||||
|
||||
<DataTemplate x:Key="FloatTemplate"
|
||||
x:DataType="local:ArgWrapper">
|
||||
<ListViewItem>
|
||||
<Grid ColumnSpacing="8">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="{StaticResource ArgumentNameWidth}" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Grid.Column="0"
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Bind Name}" />
|
||||
<muxc:NumberBox Grid.Column="1"
|
||||
LargeChange="1"
|
||||
Maximum="999"
|
||||
Minimum="0"
|
||||
SmallChange="1"
|
||||
Style="{StaticResource NumberBoxSettingStyle}"
|
||||
Value="{x:Bind UnboxFloat(Value), Mode=TwoWay, BindBack=FloatBindBack}" />
|
||||
</Grid>
|
||||
</ListViewItem>
|
||||
</DataTemplate>
|
||||
|
||||
<DataTemplate x:Key="StringTemplate"
|
||||
x:DataType="local:ArgWrapper">
|
||||
<ListViewItem>
|
||||
<Grid ColumnSpacing="8">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="{StaticResource ArgumentNameWidth}" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Grid.Column="0"
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Bind Name}" />
|
||||
<TextBox Grid.Column="1"
|
||||
Text="{x:Bind UnboxString(Value), Mode=TwoWay, BindBack=StringBindBack}" />
|
||||
</Grid>
|
||||
</ListViewItem>
|
||||
</DataTemplate>
|
||||
|
||||
<DataTemplate x:Key="ColorSchemeTemplate"
|
||||
x:DataType="local:ArgWrapper">
|
||||
<ListViewItem>
|
||||
<Grid ColumnSpacing="8">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="{StaticResource ArgumentNameWidth}" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Grid.Column="0"
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Bind Name}" />
|
||||
<ComboBox Grid.Column="1"
|
||||
ItemTemplate="{StaticResource EnumComboBoxTemplate}"
|
||||
ItemsSource="{x:Bind EnumList, Mode=OneWay}"
|
||||
SelectedItem="{x:Bind EnumValue, Mode=TwoWay}"
|
||||
Style="{StaticResource ComboBoxSettingStyle}" />
|
||||
</Grid>
|
||||
</ListViewItem>
|
||||
</DataTemplate>
|
||||
|
||||
<DataTemplate x:Key="FilePickerTemplate"
|
||||
x:DataType="local:ArgWrapper">
|
||||
<ListViewItem>
|
||||
<Grid ColumnSpacing="8">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="{StaticResource ArgumentNameWidth}" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Grid.Column="0"
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Bind Name}" />
|
||||
<TextBox Grid.Column="1"
|
||||
Text="{x:Bind UnboxString(Value), Mode=TwoWay, BindBack=StringBindBack}" />
|
||||
<Button x:Uid="Actions_Browse"
|
||||
Grid.Column="2"
|
||||
Click="{x:Bind Browse_Click}"
|
||||
Style="{StaticResource BrowseButtonStyle}" />
|
||||
</Grid>
|
||||
</ListViewItem>
|
||||
</DataTemplate>
|
||||
|
||||
<DataTemplate x:Key="GuidTemplate"
|
||||
x:DataType="local:ArgWrapper">
|
||||
<ListViewItem>
|
||||
<Grid ColumnSpacing="8">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="{StaticResource ArgumentNameWidth}" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Grid.Column="0"
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Bind Name}" />
|
||||
<TextBox Grid.Column="1"
|
||||
Text="{x:Bind UnboxGuid(Value), Mode=TwoWay, BindBack=GuidBindBack}" />
|
||||
</Grid>
|
||||
</ListViewItem>
|
||||
</DataTemplate>
|
||||
|
||||
<DataTemplate x:Key="BoolTemplate"
|
||||
x:DataType="local:ArgWrapper">
|
||||
<ListViewItem>
|
||||
<Grid ColumnSpacing="8">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="{StaticResource ArgumentNameWidth}" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Grid.Column="0"
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Bind Name}" />
|
||||
<ToggleSwitch Grid.Column="1"
|
||||
IsOn="{x:Bind UnboxBool(Value), Mode=TwoWay, BindBack=BoolOptionalBindBack}" />
|
||||
</Grid>
|
||||
</ListViewItem>
|
||||
</DataTemplate>
|
||||
|
||||
<DataTemplate x:Key="BoolOptionalTemplate"
|
||||
x:DataType="local:ArgWrapper">
|
||||
<ListViewItem>
|
||||
<Grid ColumnSpacing="8">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="{StaticResource ArgumentNameWidth}" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Grid.Column="0"
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Bind Name}" />
|
||||
<CheckBox Grid.Column="1"
|
||||
IsChecked="{x:Bind UnboxBoolOptional(Value), Mode=TwoWay, BindBack=BoolOptionalBindBack}"
|
||||
IsThreeState="True" />
|
||||
</Grid>
|
||||
</ListViewItem>
|
||||
</DataTemplate>
|
||||
|
||||
<DataTemplate x:Key="EnumComboBoxTemplate"
|
||||
x:DataType="local:EnumEntry">
|
||||
<TextBlock Text="{x:Bind EnumName, Mode=OneWay}" />
|
||||
</DataTemplate>
|
||||
|
||||
<DataTemplate x:Key="EnumTemplate"
|
||||
x:DataType="local:ArgWrapper">
|
||||
<ListViewItem>
|
||||
<Grid ColumnSpacing="8">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="{StaticResource ArgumentNameWidth}" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Grid.Column="0"
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Bind Name}" />
|
||||
<ComboBox Grid.Column="1"
|
||||
ItemTemplate="{StaticResource EnumComboBoxTemplate}"
|
||||
ItemsSource="{x:Bind EnumList, Mode=OneWay}"
|
||||
SelectedItem="{x:Bind EnumValue, Mode=TwoWay}"
|
||||
Style="{StaticResource ComboBoxSettingStyle}" />
|
||||
</Grid>
|
||||
</ListViewItem>
|
||||
</DataTemplate>
|
||||
|
||||
<DataTemplate x:Key="FlagItemTemplate"
|
||||
x:DataType="local:FlagEntry">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="40" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<CheckBox Grid.Column="0"
|
||||
IsChecked="{x:Bind IsSet, Mode=TwoWay}" />
|
||||
<TextBlock Grid.Column="1"
|
||||
Padding="0,0,0,4"
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Bind FlagName, Mode=OneWay}" />
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
|
||||
<DataTemplate x:Key="FlagTemplate"
|
||||
x:DataType="local:ArgWrapper">
|
||||
<ListViewItem>
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="{StaticResource ArgumentNameWidth}" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Grid.Column="0"
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Bind Name}" />
|
||||
<ListView Grid.Column="1"
|
||||
Margin="0"
|
||||
Padding="-8,0,0,0"
|
||||
HorizontalAlignment="Left"
|
||||
ItemTemplate="{StaticResource FlagItemTemplate}"
|
||||
ItemsSource="{x:Bind FlagList, Mode=OneWay}"
|
||||
SelectionMode="None" />
|
||||
</Grid>
|
||||
</ListViewItem>
|
||||
</DataTemplate>
|
||||
|
||||
<DataTemplate x:Key="TerminalCoreColorOptionalTemplate"
|
||||
x:DataType="local:ArgWrapper">
|
||||
<ListViewItem>
|
||||
<Grid ColumnSpacing="8">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="{StaticResource ArgumentNameWidth}" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Grid.Column="0"
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Bind Name}" />
|
||||
<local:NullableColorPicker x:Uid="Actions_NullableColorPicker"
|
||||
Grid.Column="1"
|
||||
ColorSchemeVM="{x:Bind DefaultColorScheme, Mode=OneWay}"
|
||||
CurrentColor="{x:Bind UnboxTerminalCoreColorOptional(Value), Mode=TwoWay, BindBack=TerminalCoreColorBindBack}"
|
||||
NullColorPreview="{x:Bind DefaultColorScheme.ForegroundColor.Color, Mode=OneWay}" />
|
||||
</Grid>
|
||||
</ListViewItem>
|
||||
</DataTemplate>
|
||||
|
||||
<DataTemplate x:Key="WindowsUIColorOptionalTemplate"
|
||||
x:DataType="local:ArgWrapper">
|
||||
<ListViewItem>
|
||||
<Grid ColumnSpacing="8">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="{StaticResource ArgumentNameWidth}" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Grid.Column="0"
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Bind Name}" />
|
||||
<local:NullableColorPicker x:Uid="Actions_NullableColorPicker"
|
||||
Grid.Column="1"
|
||||
ColorSchemeVM="{x:Bind DefaultColorScheme, Mode=OneWay}"
|
||||
CurrentColor="{x:Bind UnboxWindowsUIColorOptional(Value), Mode=TwoWay, BindBack=WindowsUIColorBindBack}"
|
||||
NullColorPreview="{x:Bind DefaultColorScheme.ForegroundColor.Color, Mode=OneWay}" />
|
||||
</Grid>
|
||||
</ListViewItem>
|
||||
</DataTemplate>
|
||||
|
||||
<local:ArgsTemplateSelectors x:Key="ArgsTemplateSelector"
|
||||
BoolOptionalTemplate="{StaticResource BoolOptionalTemplate}"
|
||||
BoolTemplate="{StaticResource BoolTemplate}"
|
||||
ColorSchemeTemplate="{StaticResource ColorSchemeTemplate}"
|
||||
EnumTemplate="{StaticResource EnumTemplate}"
|
||||
FilePickerTemplate="{StaticResource FilePickerTemplate}"
|
||||
FlagTemplate="{StaticResource FlagTemplate}"
|
||||
FloatTemplate="{StaticResource FloatTemplate}"
|
||||
GuidTemplate="{StaticResource GuidTemplate}"
|
||||
Int32OptionalTemplate="{StaticResource Int32OptionalTemplate}"
|
||||
Int32Template="{StaticResource Int32Template}"
|
||||
NoArgTemplate="{StaticResource NoArgTemplate}"
|
||||
StringTemplate="{StaticResource StringTemplate}"
|
||||
TerminalCoreColorOptionalTemplate="{StaticResource TerminalCoreColorOptionalTemplate}"
|
||||
UInt32OptionalTemplate="{StaticResource UInt32OptionalTemplate}"
|
||||
UInt32Template="{StaticResource UInt32Template}"
|
||||
UInt64Template="{StaticResource UInt64Template}"
|
||||
WindowsUIColorOptionalTemplate="{StaticResource WindowsUIColorOptionalTemplate}" />
|
||||
|
||||
</ResourceDictionary>
|
||||
</Page.Resources>
|
||||
|
||||
<Border MaxWidth="{StaticResource StandardControlMaxWidth}"
|
||||
Margin="{StaticResource SettingStackMargin}">
|
||||
<Grid MaxWidth="600"
|
||||
Margin="{StaticResource SettingStackMargin}"
|
||||
HorizontalAlignment="Left"
|
||||
ColumnSpacing="16"
|
||||
RowSpacing="8">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock x:Uid="Actions_Name"
|
||||
Grid.Row="0"
|
||||
Grid.Column="0"
|
||||
VerticalAlignment="Center" />
|
||||
<TextBox Grid.Row="0"
|
||||
Grid.Column="1"
|
||||
Width="300"
|
||||
HorizontalAlignment="Left"
|
||||
PlaceholderText="{x:Bind ViewModel.DisplayName, Mode=OneWay}"
|
||||
Text="{x:Bind ViewModel.Name, Mode=TwoWay}" />
|
||||
<TextBlock x:Uid="Actions_ShortcutAction"
|
||||
Grid.Row="1"
|
||||
Grid.Column="0"
|
||||
VerticalAlignment="Center" />
|
||||
<ComboBox Grid.Row="1"
|
||||
Grid.Column="1"
|
||||
VerticalAlignment="Center"
|
||||
ItemsSource="{x:Bind ViewModel.AvailableShortcutActions, Mode=OneWay}"
|
||||
SelectedItem="{x:Bind ViewModel.ProposedShortcutAction, Mode=TwoWay}" />
|
||||
<TextBlock x:Uid="Actions_Arguments"
|
||||
Grid.Row="2"
|
||||
Grid.Column="0"
|
||||
VerticalAlignment="Center"
|
||||
Visibility="{x:Bind ViewModel.ActionArgsVM.HasArgs, Mode=OneWay}" />
|
||||
<ListView Grid.Row="2"
|
||||
Grid.Column="1"
|
||||
Margin="-28,0,0,0"
|
||||
AllowDrop="False"
|
||||
CanDragItems="False"
|
||||
CanReorderItems="False"
|
||||
ChoosingItemContainer="_choosingItemContainer"
|
||||
ItemsSource="{x:Bind ViewModel.ActionArgsVM.ArgValues, Mode=OneWay}"
|
||||
SelectionMode="None" />
|
||||
<TextBlock x:Uid="Actions_Keybindings"
|
||||
Grid.Row="3"
|
||||
Grid.Column="0"
|
||||
VerticalAlignment="Center" />
|
||||
<ListView Grid.Row="3"
|
||||
Grid.Column="1"
|
||||
ItemTemplate="{StaticResource KeyChordTemplate}"
|
||||
ItemsSource="{x:Bind ViewModel.KeyChordViewModelList, Mode=OneWay}"
|
||||
SelectionMode="None">
|
||||
<ListView.Header>
|
||||
<Button Click="{x:Bind ViewModel.AddKeybinding_Click}">
|
||||
<TextBlock x:Uid="Actions_AddKeyChord" />
|
||||
</Button>
|
||||
</ListView.Header>
|
||||
</ListView>
|
||||
<Button Grid.Row="4"
|
||||
Grid.Column="0"
|
||||
IsEnabled="{x:Bind ViewModel.IsUserAction, Mode=OneWay}"
|
||||
Style="{StaticResource DeleteButtonStyle}">
|
||||
<Button.Content>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<FontIcon FontSize="{StaticResource StandardIconSize}"
|
||||
Glyph="" />
|
||||
<TextBlock x:Uid="Actions_DeleteButton2"
|
||||
Style="{StaticResource IconButtonTextBlockStyle}" />
|
||||
</StackPanel>
|
||||
</Button.Content>
|
||||
<Button.Flyout>
|
||||
<Flyout>
|
||||
<StackPanel>
|
||||
<TextBlock x:Uid="Actions_CommandDeleteConfirmationMessage"
|
||||
Style="{StaticResource CustomFlyoutTextStyle}" />
|
||||
<Button x:Uid="Actions_CommandDeleteConfirmationButton"
|
||||
Click="{x:Bind ViewModel.Delete_Click}" />
|
||||
</StackPanel>
|
||||
</Flyout>
|
||||
</Button.Flyout>
|
||||
</Button>
|
||||
</Grid>
|
||||
</Border>
|
||||
</Page>
|
||||
@@ -17,6 +17,7 @@ Author(s):
|
||||
#pragma once
|
||||
|
||||
#include "EnumEntry.g.h"
|
||||
#include "FlagEntry.g.h"
|
||||
#include "Utils.h"
|
||||
|
||||
namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
@@ -55,4 +56,41 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
WINRT_OBSERVABLE_PROPERTY(winrt::hstring, EnumName, PropertyChanged.raise);
|
||||
WINRT_OBSERVABLE_PROPERTY(winrt::Windows::Foundation::IInspectable, EnumValue, PropertyChanged.raise);
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct FlagEntryComparator
|
||||
{
|
||||
bool operator()(const Editor::FlagEntry& lhs, const Editor::FlagEntry& rhs) const
|
||||
{
|
||||
return lhs.FlagValue().as<T>() < rhs.FlagValue().as<T>();
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct FlagEntryReverseComparator
|
||||
{
|
||||
bool operator()(const Editor::FlagEntry& lhs, const Editor::FlagEntry& rhs) const
|
||||
{
|
||||
return lhs.FlagValue().as<T>() > rhs.FlagValue().as<T>();
|
||||
}
|
||||
};
|
||||
|
||||
struct FlagEntry : FlagEntryT<FlagEntry>
|
||||
{
|
||||
public:
|
||||
FlagEntry(const winrt::hstring flagName, const winrt::Windows::Foundation::IInspectable& flagValue, const bool isSet) :
|
||||
_FlagName{ flagName },
|
||||
_FlagValue{ flagValue },
|
||||
_IsSet{ isSet } {}
|
||||
|
||||
hstring ToString()
|
||||
{
|
||||
return FlagName();
|
||||
}
|
||||
|
||||
til::property_changed_event PropertyChanged;
|
||||
WINRT_OBSERVABLE_PROPERTY(winrt::hstring, FlagName, PropertyChanged.raise);
|
||||
WINRT_OBSERVABLE_PROPERTY(winrt::Windows::Foundation::IInspectable, FlagValue, PropertyChanged.raise);
|
||||
WINRT_OBSERVABLE_PROPERTY(bool, IsSet, PropertyChanged.raise);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -8,4 +8,11 @@ namespace Microsoft.Terminal.Settings.Editor
|
||||
String EnumName { get; };
|
||||
IInspectable EnumValue { get; };
|
||||
}
|
||||
|
||||
[default_interface] runtimeclass FlagEntry : Windows.UI.Xaml.Data.INotifyPropertyChanged, Windows.Foundation.IStringable
|
||||
{
|
||||
String FlagName { get; };
|
||||
IInspectable FlagValue { get; };
|
||||
Boolean IsSet;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -170,7 +170,8 @@
|
||||
x:Uid="Extensions_NavigateToProfileButton"
|
||||
Click="NavigateToProfile_Click"
|
||||
Style="{StaticResource SettingContainerResetButtonStyle}"
|
||||
Tag="{x:Bind Profile.Guid}">
|
||||
Tag="{x:Bind Profile.Guid}"
|
||||
Visibility="{x:Bind mtu:Converters.InvertedBooleanToVisibility(Profile.Deleted)}">
|
||||
<FontIcon Glyph=""
|
||||
Style="{StaticResource SettingContainerFontIconStyle}" />
|
||||
</Button>
|
||||
|
||||
@@ -114,6 +114,24 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
}
|
||||
});
|
||||
|
||||
_actionsVM = winrt::make<ActionsViewModel>(_settingsClone);
|
||||
_actionsViewModelChangedRevoker = _actionsVM.PropertyChanged(winrt::auto_revoke, [=](auto&&, const PropertyChangedEventArgs& args) {
|
||||
const auto settingName{ args.PropertyName() };
|
||||
if (settingName == L"CurrentPage")
|
||||
{
|
||||
if (_actionsVM.CurrentPage() == ActionsSubPage::Edit)
|
||||
{
|
||||
contentFrame().Navigate(xaml_typename<Editor::EditAction>(), winrt::make<implementation::NavigateToCommandArgs>(_actionsVM.CurrentCommand(), *this));
|
||||
const auto crumb = winrt::make<Breadcrumb>(box_value(actionsTag), L"Edit Action...", BreadcrumbSubPage::Actions_Edit);
|
||||
_breadcrumbs.Append(crumb);
|
||||
}
|
||||
else if (_actionsVM.CurrentPage() == ActionsSubPage::Base)
|
||||
{
|
||||
_Navigate(winrt::hstring{ actionsTag }, BreadcrumbSubPage::None);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
auto extensionsVMImpl = winrt::make_self<ExtensionsViewModel>(_settingsClone, _colorSchemesPageVM);
|
||||
extensionsVMImpl->NavigateToProfileRequested({ this, &MainPage::_NavigateToProfileHandler });
|
||||
extensionsVMImpl->NavigateToColorSchemeRequested({ this, &MainPage::_NavigateToColorSchemeHandler });
|
||||
@@ -190,6 +208,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
_InitializeProfilesList();
|
||||
// Update the Nav State with the new version of the settings
|
||||
_colorSchemesPageVM.UpdateSettings(_settingsClone);
|
||||
_actionsVM.UpdateSettings(_settingsClone);
|
||||
_newTabMenuPageVM.UpdateSettings(_settingsClone);
|
||||
_extensionsVM.UpdateSettings(_settingsClone, _colorSchemesPageVM);
|
||||
|
||||
@@ -478,9 +497,14 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
}
|
||||
else if (clickedItemTag == actionsTag)
|
||||
{
|
||||
contentFrame().Navigate(xaml_typename<Editor::Actions>(), winrt::make<ActionsViewModel>(_settingsClone));
|
||||
const auto crumb = winrt::make<Breadcrumb>(box_value(clickedItemTag), RS_(L"Nav_Actions/Content"), BreadcrumbSubPage::None);
|
||||
_breadcrumbs.Append(crumb);
|
||||
contentFrame().Navigate(xaml_typename<Editor::Actions>(), _actionsVM);
|
||||
|
||||
if (subPage == BreadcrumbSubPage::Actions_Edit && _actionsVM.CurrentCommand() != nullptr)
|
||||
{
|
||||
_actionsVM.CurrentPage(ActionsSubPage::Edit);
|
||||
}
|
||||
}
|
||||
else if (clickedItemTag == newTabMenuTag)
|
||||
{
|
||||
|
||||
@@ -77,11 +77,13 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
void _MoveXamlParsedNavItemsIntoItemSource();
|
||||
|
||||
winrt::Microsoft::Terminal::Settings::Editor::ColorSchemesPageViewModel _colorSchemesPageVM{ nullptr };
|
||||
winrt::Microsoft::Terminal::Settings::Editor::ActionsViewModel _actionsVM{ nullptr };
|
||||
winrt::Microsoft::Terminal::Settings::Editor::NewTabMenuViewModel _newTabMenuPageVM{ nullptr };
|
||||
winrt::Microsoft::Terminal::Settings::Editor::ExtensionsViewModel _extensionsVM{ nullptr };
|
||||
|
||||
Windows::UI::Xaml::Data::INotifyPropertyChanged::PropertyChanged_revoker _profileViewModelChangedRevoker;
|
||||
Windows::UI::Xaml::Data::INotifyPropertyChanged::PropertyChanged_revoker _colorSchemesPageViewModelChangedRevoker;
|
||||
Windows::UI::Xaml::Data::INotifyPropertyChanged::PropertyChanged_revoker _actionsViewModelChangedRevoker;
|
||||
Windows::UI::Xaml::Data::INotifyPropertyChanged::PropertyChanged_revoker _ntmViewModelChangedRevoker;
|
||||
Windows::UI::Xaml::Data::INotifyPropertyChanged::PropertyChanged_revoker _extensionsViewModelChangedRevoker;
|
||||
};
|
||||
|
||||
@@ -22,6 +22,7 @@ namespace Microsoft.Terminal.Settings.Editor
|
||||
Profile_Terminal,
|
||||
Profile_Advanced,
|
||||
ColorSchemes_Edit,
|
||||
Actions_Edit,
|
||||
NewTabMenu_Folder,
|
||||
Extensions_Extension
|
||||
};
|
||||
|
||||
@@ -44,6 +44,13 @@
|
||||
<ClInclude Include="Actions.h">
|
||||
<DependentUpon>Actions.xaml</DependentUpon>
|
||||
</ClInclude>
|
||||
<ClInclude Include="ArgsTemplateSelectors.h">
|
||||
<DependentUpon>ArgsTemplateSelectors.idl</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
</ClInclude>
|
||||
<ClInclude Include="EditAction.h">
|
||||
<DependentUpon>EditAction.xaml</DependentUpon>
|
||||
</ClInclude>
|
||||
<ClInclude Include="AddProfile.h">
|
||||
<DependentUpon>AddProfile.xaml</DependentUpon>
|
||||
</ClInclude>
|
||||
@@ -167,6 +174,9 @@
|
||||
<Page Include="Actions.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="EditAction.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="AddProfile.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
@@ -236,6 +246,13 @@
|
||||
<ClCompile Include="Actions.cpp">
|
||||
<DependentUpon>Actions.xaml</DependentUpon>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ArgsTemplateSelectors.cpp">
|
||||
<DependentUpon>ArgsTemplateSelectors.idl</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
</ClCompile>
|
||||
<ClCompile Include="EditAction.cpp">
|
||||
<DependentUpon>EditAction.xaml</DependentUpon>
|
||||
</ClCompile>
|
||||
<ClCompile Include="AddProfile.cpp">
|
||||
<DependentUpon>AddProfile.xaml</DependentUpon>
|
||||
</ClCompile>
|
||||
@@ -361,6 +378,13 @@
|
||||
<DependentUpon>Actions.xaml</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
</Midl>
|
||||
<Midl Include="ArgsTemplateSelectors.idl">
|
||||
<SubType>Designer</SubType>
|
||||
</Midl>
|
||||
<Midl Include="EditAction.idl">
|
||||
<DependentUpon>EditAction.xaml</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
</Midl>
|
||||
<Midl Include="AddProfile.idl">
|
||||
<DependentUpon>AddProfile.xaml</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
<Midl Include="LaunchViewModel.idl" />
|
||||
<Midl Include="EnumEntry.idl" />
|
||||
<Midl Include="SettingContainer.idl" />
|
||||
<Midl Include="ArgsTemplateSelectors.idl" />
|
||||
<Midl Include="TerminalColorConverters.idl" />
|
||||
<Midl Include="NewTabMenuViewModel.idl" />
|
||||
</ItemGroup>
|
||||
@@ -49,6 +50,7 @@
|
||||
<Page Include="Appearances.xaml" />
|
||||
<Page Include="Rendering.xaml" />
|
||||
<Page Include="Actions.xaml" />
|
||||
<Page Include="EditAction.xaml" />
|
||||
<Page Include="SettingContainerStyle.xaml" />
|
||||
<Page Include="AddProfile.xaml" />
|
||||
<Page Include="KeyChordListener.xaml" />
|
||||
|
||||
@@ -1788,6 +1788,38 @@
|
||||
<value>Delete the unfocused appearance for this profile.</value>
|
||||
<comment>A description for what the delete unfocused appearance button does.</comment>
|
||||
</data>
|
||||
<data name="Actions_Disclaimer.Text" xml:space="preserve">
|
||||
<value>Learn more about actions</value>
|
||||
<comment>Disclaimer presented at the top of the actions page to redirect the user to documentation regarding actions.</comment>
|
||||
</data>
|
||||
<data name="Actions_DeleteButton2.Text" xml:space="preserve">
|
||||
<value>Delete action</value>
|
||||
<comment>Button label that deletes the selected action.</comment>
|
||||
</data>
|
||||
<data name="Actions_Name.Text" xml:space="preserve">
|
||||
<value>Action name</value>
|
||||
<comment>Label for the text box that edits the action name.</comment>
|
||||
</data>
|
||||
<data name="Actions_NameEntryBox.PlaceholderText" xml:space="preserve">
|
||||
<value>Action name</value>
|
||||
<comment>Placeholder text for the text box where the user can edit the action name.</comment>
|
||||
</data>
|
||||
<data name="Actions_ShortcutAction.Text" xml:space="preserve">
|
||||
<value>Action type</value>
|
||||
<comment>Label for the combo box that edits the action type.</comment>
|
||||
</data>
|
||||
<data name="Actions_Arguments.Text" xml:space="preserve">
|
||||
<value>Additional arguments</value>
|
||||
<comment>Label for the list of editable arguments for the currently selected action.</comment>
|
||||
</data>
|
||||
<data name="Actions_Keybindings.Text" xml:space="preserve">
|
||||
<value>Keybindings</value>
|
||||
<comment>Label for the list of editable keybindings for the current command.</comment>
|
||||
</data>
|
||||
<data name="Actions_AddKeyChord.Text" xml:space="preserve">
|
||||
<value>Add keybinding</value>
|
||||
<comment>Button label that adds a keybinding to the current action.</comment>
|
||||
</data>
|
||||
<data name="Actions_DeleteConfirmationButton.Content" xml:space="preserve">
|
||||
<value>Yes, delete key binding</value>
|
||||
<comment>Button label that confirms deletion of a key binding entry.</comment>
|
||||
@@ -1796,6 +1828,14 @@
|
||||
<value>Are you sure you want to delete this key binding?</value>
|
||||
<comment>Confirmation message displayed when the user attempts to delete a key binding entry.</comment>
|
||||
</data>
|
||||
<data name="Actions_CommandDeleteConfirmationButton.Content" xml:space="preserve">
|
||||
<value>Yes, delete action</value>
|
||||
<comment>Button label that confirms deletion of an action.</comment>
|
||||
</data>
|
||||
<data name="Actions_CommandDeleteConfirmationMessage.Text" xml:space="preserve">
|
||||
<value>Are you sure you want to delete this action?</value>
|
||||
<comment>Confirmation message displayed when the user attempts to delete an action.</comment>
|
||||
</data>
|
||||
<data name="Actions_InvalidKeyChordMessage" xml:space="preserve">
|
||||
<value>Invalid key chord. Please enter a valid key chord.</value>
|
||||
<comment>Error message displayed when an invalid key chord is input by the user.</comment>
|
||||
@@ -1840,6 +1880,278 @@
|
||||
<value>Action</value>
|
||||
<comment>Label for a control that sets the action of a key binding.</comment>
|
||||
</data>
|
||||
<data name="Actions_NullEnumValue" xml:space="preserve">
|
||||
<value>Null (use global setting)</value>
|
||||
<comment>An option to choose from for nullable enums. Clears the enum value.</comment>
|
||||
</data>
|
||||
<data name="Actions_CopyFormatHtml.Content" xml:space="preserve">
|
||||
<value>HTML</value>
|
||||
<comment>An option to choose from for the "copy format". Copies content in HTML format.</comment>
|
||||
</data>
|
||||
<data name="Actions_CopyFormatRtf.Content" xml:space="preserve">
|
||||
<value>RTF</value>
|
||||
<comment>An option to choose from for the "copy format". Copies content in Rich Text Format (RTF).</comment>
|
||||
</data>
|
||||
<data name="Actions_SplitDirectionAuto.Content" xml:space="preserve">
|
||||
<value>Automatic</value>
|
||||
<comment>An option to choose from for the "split direction". Automatically determines the split direction.</comment>
|
||||
</data>
|
||||
<data name="Actions_SplitDirectionUp.Content" xml:space="preserve">
|
||||
<value>Up</value>
|
||||
<comment>An option to choose from for the "split direction". Splits upward.</comment>
|
||||
</data>
|
||||
<data name="Actions_SplitDirectionRight.Content" xml:space="preserve">
|
||||
<value>Right</value>
|
||||
<comment>An option to choose from for the "split direction". Splits to the right.</comment>
|
||||
</data>
|
||||
<data name="Actions_SplitDirectionDown.Content" xml:space="preserve">
|
||||
<value>Down</value>
|
||||
<comment>An option to choose from for the "split direction". Splits downward.</comment>
|
||||
</data>
|
||||
<data name="Actions_SplitDirectionLeft.Content" xml:space="preserve">
|
||||
<value>Left</value>
|
||||
<comment>An option to choose from for the "split direction". Splits to the left.</comment>
|
||||
</data>
|
||||
<data name="Actions_SplitDirectionVertical.Content" xml:space="preserve">
|
||||
<value>Vertical</value>
|
||||
<comment>An option to choose from for the "split direction". Splits to the left.</comment>
|
||||
</data>
|
||||
<data name="Actions_SplitDirectionHorizontal.Content" xml:space="preserve">
|
||||
<value>Horizontal</value>
|
||||
<comment>An option to choose from for the "split direction". Splits to the left.</comment>
|
||||
</data>
|
||||
<data name="Actions_SplitTypeManual.Content" xml:space="preserve">
|
||||
<value>Manual</value>
|
||||
<comment>An option to choose from for the "split type". Creates a manual split.</comment>
|
||||
</data>
|
||||
<data name="Actions_SplitTypeDuplicate.Content" xml:space="preserve">
|
||||
<value>Duplicate</value>
|
||||
<comment>An option to choose from for the "split type". Creates a split by duplicating the current session.</comment>
|
||||
</data>
|
||||
<data name="Actions_ResizeDirectionNone.Content" xml:space="preserve">
|
||||
<value>None</value>
|
||||
<comment>An option to choose from for the "resize direction". None option.</comment>
|
||||
</data>
|
||||
<data name="Actions_ResizeDirectionLeft.Content" xml:space="preserve">
|
||||
<value>Left</value>
|
||||
<comment>An option to choose from for the "resize direction". Left option.</comment>
|
||||
</data>
|
||||
<data name="Actions_ResizeDirectionRight.Content" xml:space="preserve">
|
||||
<value>Right</value>
|
||||
<comment>An option to choose from for the "resize direction". Right option.</comment>
|
||||
</data>
|
||||
<data name="Actions_ResizeDirectionUp.Content" xml:space="preserve">
|
||||
<value>Up</value>
|
||||
<comment>An option to choose from for the "resize direction". Up option.</comment>
|
||||
</data>
|
||||
<data name="Actions_ResizeDirectionDown.Content" xml:space="preserve">
|
||||
<value>Down</value>
|
||||
<comment>An option to choose from for the "resize direction". Down option.</comment>
|
||||
</data>
|
||||
<data name="Actions_FocusDirectionNone.Content" xml:space="preserve">
|
||||
<value>None</value>
|
||||
<comment>An option to choose from for the "focus direction". None option.</comment>
|
||||
</data>
|
||||
<data name="Actions_FocusDirectionLeft.Content" xml:space="preserve">
|
||||
<value>Left</value>
|
||||
<comment>An option to choose from for the "focus direction". Left option.</comment>
|
||||
</data>
|
||||
<data name="Actions_FocusDirectionRight.Content" xml:space="preserve">
|
||||
<value>Right</value>
|
||||
<comment>An option to choose from for the "focus direction". Right option.</comment>
|
||||
</data>
|
||||
<data name="Actions_FocusDirectionUp.Content" xml:space="preserve">
|
||||
<value>Up</value>
|
||||
<comment>An option to choose from for the "focus direction". Up option.</comment>
|
||||
</data>
|
||||
<data name="Actions_FocusDirectionDown.Content" xml:space="preserve">
|
||||
<value>Down</value>
|
||||
<comment>An option to choose from for the "focus direction". Down option.</comment>
|
||||
</data>
|
||||
<data name="Actions_FocusDirectionPrevious.Content" xml:space="preserve">
|
||||
<value>Previous</value>
|
||||
<comment>An option to choose from for the "focus direction". Previous option.</comment>
|
||||
</data>
|
||||
<data name="Actions_FocusDirectionPreviousInOrder.Content" xml:space="preserve">
|
||||
<value>Previous In Order</value>
|
||||
<comment>An option to choose from for the "focus direction". Previous in order option.</comment>
|
||||
</data>
|
||||
<data name="Actions_FocusDirectionNextInOrder.Content" xml:space="preserve">
|
||||
<value>Next In Order</value>
|
||||
<comment>An option to choose from for the "focus direction". Next in order option.</comment>
|
||||
</data>
|
||||
<data name="Actions_FocusDirectionFirst.Content" xml:space="preserve">
|
||||
<value>First</value>
|
||||
<comment>An option to choose from for the "focus direction". First option.</comment>
|
||||
</data>
|
||||
<data name="Actions_FocusDirectionParent.Content" xml:space="preserve">
|
||||
<value>Parent</value>
|
||||
<comment>An option to choose from for the "focus direction". Parent option.</comment>
|
||||
</data>
|
||||
<data name="Actions_FocusDirectionChild.Content" xml:space="preserve">
|
||||
<value>Child</value>
|
||||
<comment>An option to choose from for the "focus direction". Child option.</comment>
|
||||
</data>
|
||||
<data name="Actions_SettingsTargetSettingsFile.Content" xml:space="preserve">
|
||||
<value>Settings File</value>
|
||||
<comment>An option to choose from for the "settings target". Targets the settings file.</comment>
|
||||
</data>
|
||||
<data name="Actions_SettingsTargetDefaultsFile.Content" xml:space="preserve">
|
||||
<value>Defaults File</value>
|
||||
<comment>An option to choose from for the "settings target". Targets the defaults file.</comment>
|
||||
</data>
|
||||
<data name="Actions_SettingsTargetAllFiles.Content" xml:space="preserve">
|
||||
<value>All Files</value>
|
||||
<comment>An option to choose from for the "settings target". Targets all files.</comment>
|
||||
</data>
|
||||
<data name="Actions_SettingsTargetSettingsUI.Content" xml:space="preserve">
|
||||
<value>Settings UI</value>
|
||||
<comment>An option to choose from for the "settings target". Targets the settings UI.</comment>
|
||||
</data>
|
||||
<data name="Actions_SettingsTargetDirectory.Content" xml:space="preserve">
|
||||
<value>Directory</value>
|
||||
<comment>An option to choose from for the "settings target". Targets the directory.</comment>
|
||||
</data>
|
||||
<data name="Actions_MoveTabDirectionNone.Content" xml:space="preserve">
|
||||
<value>None</value>
|
||||
<comment>An option to choose from for the "move tab direction". No movement.</comment>
|
||||
</data>
|
||||
<data name="Actions_MoveTabDirectionForward.Content" xml:space="preserve">
|
||||
<value>Forward</value>
|
||||
<comment>An option to choose from for the "move tab direction". Moves the tab forward.</comment>
|
||||
</data>
|
||||
<data name="Actions_MoveTabDirectionBackward.Content" xml:space="preserve">
|
||||
<value>Backward</value>
|
||||
<comment>An option to choose from for the "move tab direction". Moves the tab backward.</comment>
|
||||
</data>
|
||||
<data name="Actions_ScrollToMarkDirectionPrevious.Content" xml:space="preserve">
|
||||
<value>Previous</value>
|
||||
<comment>An option to choose from for the "scroll to mark direction". Scrolls to the previous mark.</comment>
|
||||
</data>
|
||||
<data name="Actions_ScrollToMarkDirectionNext.Content" xml:space="preserve">
|
||||
<value>Next</value>
|
||||
<comment>An option to choose from for the "scroll to mark direction". Scrolls to the next mark.</comment>
|
||||
</data>
|
||||
<data name="Actions_ScrollToMarkDirectionFirst.Content" xml:space="preserve">
|
||||
<value>First</value>
|
||||
<comment>An option to choose from for the "scroll to mark direction". Scrolls to the first mark.</comment>
|
||||
</data>
|
||||
<data name="Actions_ScrollToMarkDirectionLast.Content" xml:space="preserve">
|
||||
<value>Last</value>
|
||||
<comment>An option to choose from for the "scroll to mark direction". Scrolls to the last mark.</comment>
|
||||
</data>
|
||||
<data name="Actions_CommandPaletteLaunchModeAction.Content" xml:space="preserve">
|
||||
<value>Action</value>
|
||||
<comment>An option to choose from for the "command palette launch mode". Launches in action mode.</comment>
|
||||
</data>
|
||||
<data name="Actions_CommandPaletteLaunchModeCommandLine.Content" xml:space="preserve">
|
||||
<value>Command Line</value>
|
||||
<comment>An option to choose from for the "command palette launch mode". Launches in command line mode.</comment>
|
||||
</data>
|
||||
<data name="Actions_SuggestionsSourceNone.Content" xml:space="preserve">
|
||||
<value>None</value>
|
||||
<comment>An option to choose from for the "suggestions source". No suggestions source.</comment>
|
||||
</data>
|
||||
<data name="Actions_SuggestionsSourceTasks.Content" xml:space="preserve">
|
||||
<value>Tasks</value>
|
||||
<comment>An option to choose from for the "suggestions source". Suggestions come from tasks.</comment>
|
||||
</data>
|
||||
<data name="Actions_SuggestionsSourceSnippets.Content" xml:space="preserve">
|
||||
<value>Snippets</value>
|
||||
<comment>An option to choose from for the "suggestions source". Suggestions come from snippets.</comment>
|
||||
</data>
|
||||
<data name="Actions_SuggestionsSourceCommandHistory.Content" xml:space="preserve">
|
||||
<value>Command History</value>
|
||||
<comment>An option to choose from for the "suggestions source". Suggestions come from command history.</comment>
|
||||
</data>
|
||||
<data name="Actions_SuggestionsSourceDirectoryHistory.Content" xml:space="preserve">
|
||||
<value>Directory History</value>
|
||||
<comment>An option to choose from for the "suggestions source". Suggestions come from directory history.</comment>
|
||||
</data>
|
||||
<data name="Actions_SuggestionsSourceQuickFix.Content" xml:space="preserve">
|
||||
<value>Quick Fixes</value>
|
||||
<comment>An option to choose from for the "suggestions source". Suggestions come from quick fixes.</comment>
|
||||
</data>
|
||||
<data name="Actions_SuggestionsSourceAll.Content" xml:space="preserve">
|
||||
<value>All</value>
|
||||
<comment>An option to choose from for the "suggestions source". Includes all suggestion sources.</comment>
|
||||
</data>
|
||||
<data name="Actions_FindMatchDirectionNone.Content" xml:space="preserve">
|
||||
<value>None</value>
|
||||
<comment>An option to choose from for the "find match direction". No direction selected.</comment>
|
||||
</data>
|
||||
<data name="Actions_FindMatchDirectionNext.Content" xml:space="preserve">
|
||||
<value>Next</value>
|
||||
<comment>An option to choose from for the "find match direction". Finds the next match.</comment>
|
||||
</data>
|
||||
<data name="Actions_FindMatchDirectionPrev.Content" xml:space="preserve">
|
||||
<value>Previous</value>
|
||||
<comment>An option to choose from for the "find match direction". Finds the previous match.</comment>
|
||||
</data>
|
||||
<data name="Actions_DesktopBehaviorAny.Content" xml:space="preserve">
|
||||
<value>Any</value>
|
||||
<comment>An option to choose from for the "desktop behavior". Applies to any desktop.</comment>
|
||||
</data>
|
||||
<data name="Actions_DesktopBehaviorToCurrent.Content" xml:space="preserve">
|
||||
<value>To Current</value>
|
||||
<comment>An option to choose from for the "desktop behavior". Moves to the current desktop.</comment>
|
||||
</data>
|
||||
<data name="Actions_DesktopBehaviorOnCurrent.Content" xml:space="preserve">
|
||||
<value>On Current</value>
|
||||
<comment>An option to choose from for the "desktop behavior". Stays on the current desktop.</comment>
|
||||
</data>
|
||||
<data name="Actions_MonitorBehaviorAny.Content" xml:space="preserve">
|
||||
<value>Any</value>
|
||||
<comment>An option to choose from for the "monitor behavior". Applies to any monitor.</comment>
|
||||
</data>
|
||||
<data name="Actions_MonitorBehaviorToCurrent.Content" xml:space="preserve">
|
||||
<value>To Current</value>
|
||||
<comment>An option to choose from for the "monitor behavior". Moves to the current monitor.</comment>
|
||||
</data>
|
||||
<data name="Actions_MonitorBehaviorToMouse.Content" xml:space="preserve">
|
||||
<value>To Mouse</value>
|
||||
<comment>An option to choose from for the "monitor behavior". Moves to the monitor where the mouse is located.</comment>
|
||||
</data>
|
||||
<data name="Actions_ClearBufferTypeScreen.Content" xml:space="preserve">
|
||||
<value>Screen</value>
|
||||
<comment>An option to choose from for the "clear buffer type". Clears only the screen.</comment>
|
||||
</data>
|
||||
<data name="Actions_ClearBufferTypeScrollback.Content" xml:space="preserve">
|
||||
<value>Scrollback</value>
|
||||
<comment>An option to choose from for the "clear buffer type". Clears only the scrollback buffer.</comment>
|
||||
</data>
|
||||
<data name="Actions_ClearBufferTypeAll.Content" xml:space="preserve">
|
||||
<value>All</value>
|
||||
<comment>An option to choose from for the "clear buffer type". Clears both the screen and the scrollback buffer.</comment>
|
||||
</data>
|
||||
<data name="Actions_SelectOutputDirectionPrev.Content" xml:space="preserve">
|
||||
<value>Previous</value>
|
||||
<comment>An option to choose from for the "select output direction". Selects the previous output.</comment>
|
||||
</data>
|
||||
<data name="Actions_SelectOutputDirectionNext.Content" xml:space="preserve">
|
||||
<value>Next</value>
|
||||
<comment>An option to choose from for the "select output direction". Selects the next output.</comment>
|
||||
</data>
|
||||
<data name="Actions_TabSwitcherModeMru.Content" xml:space="preserve">
|
||||
<value>Most Recently Used</value>
|
||||
<comment>An option to choose from for the "tab switcher mode". Switches tabs based on most recently used order.</comment>
|
||||
</data>
|
||||
<data name="Actions_TabSwitcherModeInOrder.Content" xml:space="preserve">
|
||||
<value>In Order</value>
|
||||
<comment>An option to choose from for the "tab switcher mode". Switches tabs in sequential order.</comment>
|
||||
</data>
|
||||
<data name="Actions_TabSwitcherModeDisabled.Content" xml:space="preserve">
|
||||
<value>Disabled</value>
|
||||
<comment>An option to choose from for the "tab switcher mode". Disables tab switching.</comment>
|
||||
</data>
|
||||
<data name="Actions_NullableColorPicker.NullColorButtonLabel" xml:space="preserve">
|
||||
<value>No color</value>
|
||||
<comment>Label for a button directing the user to opt out of choosing a color.</comment>
|
||||
</data>
|
||||
<data name="Actions_Browse.Content" xml:space="preserve">
|
||||
<value>Browse...</value>
|
||||
<comment>Button label that opens a file picker in a new window. The "..." is standard to mean it will open a new window.</comment>
|
||||
</data>
|
||||
<data name="KeyChordListener.[using:Windows.UI.Xaml.Automation]AutomationProperties.HelpText" xml:space="preserve">
|
||||
<value>Input your desired keyboard shortcut.</value>
|
||||
<comment>Help text directing users how to use the "KeyChordListener" control. Pressing a keyboard shortcut will be recorded by this control.</comment>
|
||||
|
||||
@@ -341,107 +341,6 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
|
||||
winrt::hstring ActionAndArgs::GenerateName() const
|
||||
{
|
||||
// Sentinel used to indicate this command must ALWAYS be generated by GenerateName
|
||||
static const winrt::hstring 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") },
|
||||
{ ShortcutAction::CloseOtherTabs, MustGenerate },
|
||||
{ ShortcutAction::ClosePane, RS_(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::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::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::ToggleCommandPalette, MustGenerate },
|
||||
{ ShortcutAction::SaveSnippet, MustGenerate },
|
||||
{ ShortcutAction::Suggestions, MustGenerate },
|
||||
{ ShortcutAction::ToggleFocusMode, RS_(L"ToggleFocusModeCommandKey") },
|
||||
{ ShortcutAction::SetFocusMode, MustGenerate },
|
||||
{ ShortcutAction::ToggleFullscreen, RS_(L"ToggleFullscreenCommandKey") },
|
||||
{ ShortcutAction::SetFullScreen, MustGenerate },
|
||||
{ ShortcutAction::SetMaximized, MustGenerate },
|
||||
{ ShortcutAction::TogglePaneZoom, RS_(L"TogglePaneZoomCommandKey") },
|
||||
{ ShortcutAction::ToggleSplitOrientation, RS_(L"ToggleSplitOrientationCommandKey") },
|
||||
{ ShortcutAction::ToggleShaderEffects, RS_(L"ToggleShaderEffectsCommandKey") },
|
||||
{ ShortcutAction::MoveTab, MustGenerate },
|
||||
{ ShortcutAction::BreakIntoDebugger, RS_(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::GlobalSummon, MustGenerate },
|
||||
{ ShortcutAction::SearchForText, MustGenerate },
|
||||
{ ShortcutAction::QuakeMode, RS_(L"QuakeModeCommandKey") },
|
||||
{ ShortcutAction::FocusPane, MustGenerate },
|
||||
{ ShortcutAction::OpenSystemMenu, RS_(L"OpenSystemMenuCommandKey") },
|
||||
{ ShortcutAction::ExportBuffer, MustGenerate },
|
||||
{ ShortcutAction::ClearBuffer, MustGenerate },
|
||||
{ ShortcutAction::MultipleActions, MustGenerate },
|
||||
{ ShortcutAction::Quit, RS_(L"QuitCommandKey") },
|
||||
{ ShortcutAction::AdjustOpacity, MustGenerate },
|
||||
{ ShortcutAction::RestoreLastClosed, RS_(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::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") },
|
||||
};
|
||||
}();
|
||||
|
||||
if (_Args)
|
||||
{
|
||||
auto nameFromArgs = _Args.GenerateName();
|
||||
@@ -451,8 +350,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
}
|
||||
}
|
||||
|
||||
const auto found = GeneratedActionNames.find(_Action);
|
||||
return found != GeneratedActionNames.end() ? found->second : winrt::hstring{};
|
||||
return ActionArgFactory::GetNameForAction(_Action);
|
||||
}
|
||||
|
||||
// Function Description:
|
||||
|
||||
@@ -102,189 +102,208 @@ protected: \
|
||||
// false, if we don't really care if the parameter is required or not.
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
#define COPY_TEXT_ARGS(X) \
|
||||
X(bool, DismissSelection, "dismissSelection", false, true) \
|
||||
X(bool, SingleLine, "singleLine", false, false) \
|
||||
X(bool, WithControlSequences, "withControlSequences", false, false) \
|
||||
X(Windows::Foundation::IReference<Control::CopyFormat>, CopyFormatting, "copyFormatting", false, nullptr)
|
||||
#define COPY_TEXT_ARGS(X) \
|
||||
X(bool, DismissSelection, "dismissSelection", false, ArgTypeHint::None, true) \
|
||||
X(bool, SingleLine, "singleLine", false, ArgTypeHint::None, false) \
|
||||
X(bool, WithControlSequences, "withControlSequences", false, ArgTypeHint::None, false) \
|
||||
X(Windows::Foundation::IReference<Control::CopyFormat>, CopyFormatting, "copyFormatting", false, ArgTypeHint::None, nullptr)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
#define MOVE_PANE_ARGS(X) \
|
||||
X(uint32_t, TabIndex, "index", false, 0) \
|
||||
X(winrt::hstring, Window, "window", false, L"")
|
||||
#define MOVE_PANE_ARGS(X) \
|
||||
X(uint32_t, TabIndex, "index", false, ArgTypeHint::None, 0) \
|
||||
X(winrt::hstring, Window, "window", false, ArgTypeHint::None, L"")
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
#define SWITCH_TO_TAB_ARGS(X) \
|
||||
X(uint32_t, TabIndex, "index", false, 0)
|
||||
X(uint32_t, TabIndex, "index", false, ArgTypeHint::None, 0)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
#define RESIZE_PANE_ARGS(X) \
|
||||
X(Model::ResizeDirection, ResizeDirection, "direction", args->ResizeDirection() == ResizeDirection::None, Model::ResizeDirection::None)
|
||||
X(Model::ResizeDirection, ResizeDirection, "direction", args->ResizeDirection() == ResizeDirection::None, ArgTypeHint::None, Model::ResizeDirection::None)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
#define MOVE_FOCUS_ARGS(X) \
|
||||
X(Model::FocusDirection, FocusDirection, "direction", args->FocusDirection() == Model::FocusDirection::None, Model::FocusDirection::None)
|
||||
X(Model::FocusDirection, FocusDirection, "direction", args->FocusDirection() == Model::FocusDirection::None, ArgTypeHint::None, Model::FocusDirection::None)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
#define SWAP_PANE_ARGS(X) \
|
||||
X(Model::FocusDirection, Direction, "direction", args->Direction() == Model::FocusDirection::None, Model::FocusDirection::None)
|
||||
X(Model::FocusDirection, Direction, "direction", args->Direction() == Model::FocusDirection::None, ArgTypeHint::None, Model::FocusDirection::None)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
#define ADJUST_FONT_SIZE_ARGS(X) \
|
||||
X(float, Delta, "delta", false, 0)
|
||||
X(float, Delta, "delta", false, ArgTypeHint::None, 0)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
#define SEND_INPUT_ARGS(X) \
|
||||
X(winrt::hstring, Input, "input", args->Input().empty(), L"")
|
||||
X(winrt::hstring, Input, "input", args->Input().empty(), ArgTypeHint::None, L"")
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
#define OPEN_SETTINGS_ARGS(X) \
|
||||
X(SettingsTarget, Target, "target", false, SettingsTarget::SettingsFile)
|
||||
X(SettingsTarget, Target, "target", false, ArgTypeHint::None, SettingsTarget::SettingsFile)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
#define SET_FOCUS_MODE_ARGS(X) \
|
||||
X(bool, IsFocusMode, "isFocusMode", false, false)
|
||||
X(bool, IsFocusMode, "isFocusMode", false, ArgTypeHint::None, false)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
#define SET_MAXIMIZED_ARGS(X) \
|
||||
X(bool, IsMaximized, "isMaximized", false, false)
|
||||
X(bool, IsMaximized, "isMaximized", false, ArgTypeHint::None, false)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
#define SET_FULL_SCREEN_ARGS(X) \
|
||||
X(bool, IsFullScreen, "isFullScreen", false, false)
|
||||
X(bool, IsFullScreen, "isFullScreen", false, ArgTypeHint::None, false)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
#define SET_MAXIMIZED_ARGS(X) \
|
||||
X(bool, IsMaximized, "isMaximized", false, false)
|
||||
X(bool, IsMaximized, "isMaximized", false, ArgTypeHint::None, false)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
#define SET_COLOR_SCHEME_ARGS(X) \
|
||||
X(winrt::hstring, SchemeName, "colorScheme", args->SchemeName().empty(), L"")
|
||||
X(winrt::hstring, SchemeName, "colorScheme", args->SchemeName().empty(), ArgTypeHint::ColorScheme, L"")
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
#define SET_TAB_COLOR_ARGS(X) \
|
||||
X(Windows::Foundation::IReference<Windows::UI::Color>, TabColor, "color", false, nullptr)
|
||||
X(Windows::Foundation::IReference<Windows::UI::Color>, TabColor, "color", false, ArgTypeHint::None, nullptr)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
#define RENAME_TAB_ARGS(X) \
|
||||
X(winrt::hstring, Title, "title", false, L"")
|
||||
X(winrt::hstring, Title, "title", false, ArgTypeHint::None, L"")
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
#define EXECUTE_COMMANDLINE_ARGS(X) \
|
||||
X(winrt::hstring, Commandline, "commandline", args->Commandline().empty(), L"")
|
||||
X(winrt::hstring, Commandline, "commandline", args->Commandline().empty(), ArgTypeHint::None, L"")
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
#define CLOSE_OTHER_TABS_ARGS(X) \
|
||||
X(Windows::Foundation::IReference<uint32_t>, Index, "index", false, nullptr)
|
||||
X(Windows::Foundation::IReference<uint32_t>, Index, "index", false, ArgTypeHint::None, nullptr)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
#define CLOSE_TABS_AFTER_ARGS(X) \
|
||||
X(Windows::Foundation::IReference<uint32_t>, Index, "index", false, nullptr)
|
||||
X(Windows::Foundation::IReference<uint32_t>, Index, "index", false, ArgTypeHint::None, nullptr)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
#define CLOSE_TAB_ARGS(X) \
|
||||
X(Windows::Foundation::IReference<uint32_t>, Index, "index", false, nullptr)
|
||||
X(Windows::Foundation::IReference<uint32_t>, Index, "index", false, ArgTypeHint::None, nullptr)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Interestingly, the order MATTERS here. Window has to be BEFORE Direction,
|
||||
// because otherwise we won't have parsed the Window yet when we validate the
|
||||
// Direction.
|
||||
#define MOVE_TAB_ARGS(X) \
|
||||
X(winrt::hstring, Window, "window", false, L"") \
|
||||
X(MoveTabDirection, Direction, "direction", (args->Direction() == MoveTabDirection::None) && (args->Window().empty()), MoveTabDirection::None)
|
||||
#define MOVE_TAB_ARGS(X) \
|
||||
X(winrt::hstring, Window, "window", false, ArgTypeHint::None, L"") \
|
||||
X(MoveTabDirection, Direction, "direction", (args->Direction() == MoveTabDirection::None) && (args->Window().empty()), ArgTypeHint::None, MoveTabDirection::None)
|
||||
|
||||
// Other ideas:
|
||||
// X(uint32_t, TabIndex, "index", false, 0) \ // target? source?
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
#define SCROLL_UP_ARGS(X) \
|
||||
X(Windows::Foundation::IReference<uint32_t>, RowsToScroll, "rowsToScroll", false, nullptr)
|
||||
X(Windows::Foundation::IReference<uint32_t>, RowsToScroll, "rowsToScroll", false, ArgTypeHint::None, nullptr)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
#define SCROLL_DOWN_ARGS(X) \
|
||||
X(Windows::Foundation::IReference<uint32_t>, RowsToScroll, "rowsToScroll", false, nullptr)
|
||||
X(Windows::Foundation::IReference<uint32_t>, RowsToScroll, "rowsToScroll", false, ArgTypeHint::None, nullptr)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
#define SCROLL_TO_MARK_ARGS(X) \
|
||||
X(Microsoft::Terminal::Control::ScrollToMarkDirection, Direction, "direction", false, Microsoft::Terminal::Control::ScrollToMarkDirection::Previous)
|
||||
X(Microsoft::Terminal::Control::ScrollToMarkDirection, Direction, "direction", false, ArgTypeHint::None, Microsoft::Terminal::Control::ScrollToMarkDirection::Previous)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
#define ADD_MARK_ARGS(X) \
|
||||
X(Windows::Foundation::IReference<Microsoft::Terminal::Core::Color>, Color, "color", false, nullptr)
|
||||
X(Windows::Foundation::IReference<Microsoft::Terminal::Core::Color>, Color, "color", false, ArgTypeHint::None, nullptr)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
#define TOGGLE_COMMAND_PALETTE_ARGS(X) \
|
||||
X(CommandPaletteLaunchMode, LaunchMode, "launchMode", false, CommandPaletteLaunchMode::Action)
|
||||
X(CommandPaletteLaunchMode, LaunchMode, "launchMode", false, ArgTypeHint::None, CommandPaletteLaunchMode::Action)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
#define SAVE_TASK_ARGS(X) \
|
||||
X(winrt::hstring, Name, "name", false, L"") \
|
||||
X(winrt::hstring, Commandline, "commandline", args->Commandline().empty(), L"") \
|
||||
X(winrt::hstring, KeyChord, "keyChord", false, L"")
|
||||
#define SAVE_TASK_ARGS(X) \
|
||||
X(winrt::hstring, Name, "name", false, ArgTypeHint::None, L"") \
|
||||
X(winrt::hstring, Commandline, "commandline", args->Commandline().empty(), ArgTypeHint::None, L"") \
|
||||
X(winrt::hstring, KeyChord, "keyChord", false, ArgTypeHint::None, L"")
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
#define SUGGESTIONS_ARGS(X) \
|
||||
X(SuggestionsSource, Source, "source", false, SuggestionsSource::Tasks) \
|
||||
X(bool, UseCommandline, "useCommandline", false, false)
|
||||
#define SUGGESTIONS_ARGS(X) \
|
||||
X(SuggestionsSource, Source, "source", false, ArgTypeHint::None, SuggestionsSource::Tasks) \
|
||||
X(bool, UseCommandline, "useCommandline", false, ArgTypeHint::None, false)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
#define FIND_MATCH_ARGS(X) \
|
||||
X(FindMatchDirection, Direction, "direction", args->Direction() == FindMatchDirection::None, FindMatchDirection::None)
|
||||
X(FindMatchDirection, Direction, "direction", args->Direction() == FindMatchDirection::None, ArgTypeHint::None, FindMatchDirection::None)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
#define PREV_TAB_ARGS(X) \
|
||||
X(Windows::Foundation::IReference<TabSwitcherMode>, SwitcherMode, "tabSwitcherMode", false, nullptr)
|
||||
X(Windows::Foundation::IReference<TabSwitcherMode>, SwitcherMode, "tabSwitcherMode", false, ArgTypeHint::None, nullptr)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
#define NEXT_TAB_ARGS(X) \
|
||||
X(Windows::Foundation::IReference<TabSwitcherMode>, SwitcherMode, "tabSwitcherMode", false, nullptr)
|
||||
X(Windows::Foundation::IReference<TabSwitcherMode>, SwitcherMode, "tabSwitcherMode", false, ArgTypeHint::None, nullptr)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
#define RENAME_WINDOW_ARGS(X) \
|
||||
X(winrt::hstring, Name, "name", false, L"")
|
||||
X(winrt::hstring, Name, "name", false, ArgTypeHint::None, L"")
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
#define SEARCH_FOR_TEXT_ARGS(X) \
|
||||
X(winrt::hstring, QueryUrl, "queryUrl", false, L"")
|
||||
X(winrt::hstring, QueryUrl, "queryUrl", false, ArgTypeHint::None, L"")
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
#define GLOBAL_SUMMON_ARGS(X) \
|
||||
X(winrt::hstring, Name, "name", false, L"") \
|
||||
X(Model::DesktopBehavior, Desktop, "desktop", false, Model::DesktopBehavior::ToCurrent) \
|
||||
X(Model::MonitorBehavior, Monitor, "monitor", false, Model::MonitorBehavior::ToMouse) \
|
||||
X(bool, ToggleVisibility, "toggleVisibility", false, true) \
|
||||
X(uint32_t, DropdownDuration, "dropdownDuration", false, 0)
|
||||
#define GLOBAL_SUMMON_ARGS(X) \
|
||||
X(winrt::hstring, Name, "name", false, ArgTypeHint::None, L"") \
|
||||
X(Model::DesktopBehavior, Desktop, "desktop", false, ArgTypeHint::None, Model::DesktopBehavior::ToCurrent) \
|
||||
X(Model::MonitorBehavior, Monitor, "monitor", false, ArgTypeHint::None, Model::MonitorBehavior::ToMouse) \
|
||||
X(bool, ToggleVisibility, "toggleVisibility", false, ArgTypeHint::None, true) \
|
||||
X(uint32_t, DropdownDuration, "dropdownDuration", false, ArgTypeHint::None, 0)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
#define FOCUS_PANE_ARGS(X) \
|
||||
X(uint32_t, Id, "id", false, 0u)
|
||||
X(uint32_t, Id, "id", false, ArgTypeHint::None, 0u)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
#define EXPORT_BUFFER_ARGS(X) \
|
||||
X(winrt::hstring, Path, "path", false, L"")
|
||||
X(winrt::hstring, Path, "path", false, ArgTypeHint::FilePath, L"")
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
#define CLEAR_BUFFER_ARGS(X) \
|
||||
X(winrt::Microsoft::Terminal::Control::ClearBufferType, Clear, "clear", false, winrt::Microsoft::Terminal::Control::ClearBufferType::All)
|
||||
X(winrt::Microsoft::Terminal::Control::ClearBufferType, Clear, "clear", false, ArgTypeHint::None, winrt::Microsoft::Terminal::Control::ClearBufferType::All)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
#define ADJUST_OPACITY_ARGS(X) \
|
||||
X(int32_t, Opacity, "opacity", false, 0) \
|
||||
X(bool, Relative, "relative", false, true)
|
||||
#define ADJUST_OPACITY_ARGS(X) \
|
||||
X(int32_t, Opacity, "opacity", false, ArgTypeHint::None, 0) \
|
||||
X(bool, Relative, "relative", false, ArgTypeHint::None, true)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
#define SELECT_COMMAND_ARGS(X) \
|
||||
X(SelectOutputDirection, Direction, "direction", false, SelectOutputDirection::Previous)
|
||||
X(SelectOutputDirection, Direction, "direction", false, ArgTypeHint::None, SelectOutputDirection::Previous)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
#define SELECT_OUTPUT_ARGS(X) \
|
||||
X(SelectOutputDirection, Direction, "direction", false, SelectOutputDirection::Previous)
|
||||
X(SelectOutputDirection, Direction, "direction", false, ArgTypeHint::None, SelectOutputDirection::Previous)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
#define COLOR_SELECTION_ARGS(X) \
|
||||
X(winrt::Microsoft::Terminal::Control::SelectionColor, Foreground, "foreground", false, nullptr) \
|
||||
X(winrt::Microsoft::Terminal::Control::SelectionColor, Background, "background", false, nullptr) \
|
||||
X(winrt::Microsoft::Terminal::Core::MatchMode, MatchMode, "matchMode", false, winrt::Microsoft::Terminal::Core::MatchMode::None)
|
||||
#define COLOR_SELECTION_ARGS(X) \
|
||||
X(winrt::Microsoft::Terminal::Control::SelectionColor, Foreground, "foreground", false, ArgTypeHint::None, nullptr) \
|
||||
X(winrt::Microsoft::Terminal::Control::SelectionColor, Background, "background", false, ArgTypeHint::None, nullptr) \
|
||||
X(winrt::Microsoft::Terminal::Core::MatchMode, MatchMode, "matchMode", false, ArgTypeHint::None, winrt::Microsoft::Terminal::Core::MatchMode::None)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
#define NEW_TERMINAL_ARGS(X) \
|
||||
X(winrt::hstring, Commandline, "commandline", false, ArgTypeHint::None, L"") \
|
||||
X(winrt::hstring, StartingDirectory, "startingDirectory", false, ArgTypeHint::FolderPath, L"") \
|
||||
X(winrt::hstring, TabTitle, "tabTitle", false, ArgTypeHint::None, L"") \
|
||||
X(Windows::Foundation::IReference<Windows::UI::Color>, TabColor, "tabColor", false, ArgTypeHint::None, nullptr) \
|
||||
X(Windows::Foundation::IReference<int32_t>, ProfileIndex, "index", false, ArgTypeHint::None, nullptr) \
|
||||
X(winrt::hstring, Profile, "profile", false, ArgTypeHint::None, L"") \
|
||||
X(Windows::Foundation::IReference<bool>, SuppressApplicationTitle, "suppressApplicationTitle", false, ArgTypeHint::None, nullptr) \
|
||||
X(winrt::hstring, ColorScheme, "colorScheme", args->SchemeName().empty(), ArgTypeHint::ColorScheme, L"") \
|
||||
X(Windows::Foundation::IReference<bool>, Elevate, "elevate", false, ArgTypeHint::None, nullptr) \
|
||||
X(Windows::Foundation::IReference<bool>, ReloadEnvironmentVariables, "reloadEnvironmentVariables", false, ArgTypeHint::None, nullptr)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
#define SPLIT_PANE_ARGS(X) \
|
||||
X(Model::SplitDirection, SplitDirection, "split", false, ArgTypeHint::None, SplitDirection::Automatic) \
|
||||
X(SplitType, SplitMode, "splitMode", false, ArgTypeHint::None, SplitType::Manual) \
|
||||
X(float, SplitSize, "size", false, ArgTypeHint::None, 0.5f)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -358,41 +377,22 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
// assumptions made in the macro.
|
||||
struct NewTerminalArgs : public NewTerminalArgsT<NewTerminalArgs>
|
||||
{
|
||||
NewTerminalArgs() = default;
|
||||
NewTerminalArgs(int32_t& profileIndex) :
|
||||
_ProfileIndex{ profileIndex } {};
|
||||
|
||||
PARTIAL_ACTION_ARG_BODY(NewTerminalArgs, NEW_TERMINAL_ARGS);
|
||||
ACTION_ARG(winrt::hstring, Type, L"");
|
||||
|
||||
ACTION_ARG(winrt::hstring, Commandline, L"");
|
||||
ACTION_ARG(winrt::hstring, StartingDirectory, L"");
|
||||
ACTION_ARG(winrt::hstring, TabTitle, L"");
|
||||
ACTION_ARG(Windows::Foundation::IReference<Windows::UI::Color>, TabColor, nullptr);
|
||||
ACTION_ARG(Windows::Foundation::IReference<int32_t>, ProfileIndex, nullptr);
|
||||
ACTION_ARG(winrt::hstring, Profile, L"");
|
||||
ACTION_ARG(winrt::guid, SessionId, winrt::guid{});
|
||||
ACTION_ARG(bool, AppendCommandLine, false);
|
||||
ACTION_ARG(Windows::Foundation::IReference<bool>, SuppressApplicationTitle, nullptr);
|
||||
ACTION_ARG(winrt::hstring, ColorScheme);
|
||||
ACTION_ARG(Windows::Foundation::IReference<bool>, Elevate, nullptr);
|
||||
ACTION_ARG(Windows::Foundation::IReference<bool>, ReloadEnvironmentVariables, nullptr);
|
||||
ACTION_ARG(uint64_t, ContentId);
|
||||
|
||||
static constexpr std::string_view CommandlineKey{ "commandline" };
|
||||
static constexpr std::string_view StartingDirectoryKey{ "startingDirectory" };
|
||||
static constexpr std::string_view TabTitleKey{ "tabTitle" };
|
||||
static constexpr std::string_view TabColorKey{ "tabColor" };
|
||||
static constexpr std::string_view ProfileIndexKey{ "index" };
|
||||
static constexpr std::string_view ProfileKey{ "profile" };
|
||||
static constexpr std::string_view SessionIdKey{ "sessionId" };
|
||||
static constexpr std::string_view AppendCommandLineKey{ "appendCommandLine" };
|
||||
static constexpr std::string_view SuppressApplicationTitleKey{ "suppressApplicationTitle" };
|
||||
static constexpr std::string_view ColorSchemeKey{ "colorScheme" };
|
||||
static constexpr std::string_view ElevateKey{ "elevate" };
|
||||
static constexpr std::string_view ReloadEnvironmentVariablesKey{ "reloadEnvironmentVariables" };
|
||||
static constexpr std::string_view ContentKey{ "__content" };
|
||||
|
||||
public:
|
||||
NewTerminalArgs(int32_t& profileIndex) :
|
||||
_ProfileIndex{ profileIndex }
|
||||
{
|
||||
NEW_TERMINAL_ARGS(APPEND_ARG_DESCRIPTION);
|
||||
};
|
||||
hstring GenerateName() const;
|
||||
hstring ToCommandline() const;
|
||||
|
||||
@@ -471,6 +471,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
copy->_Elevate = _Elevate;
|
||||
copy->_ReloadEnvironmentVariables = _ReloadEnvironmentVariables;
|
||||
copy->_ContentId = _ContentId;
|
||||
copy->_argDescriptors = _argDescriptors;
|
||||
return *copy;
|
||||
}
|
||||
size_t Hash() const
|
||||
@@ -589,7 +590,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
NewTabArgs() = default;
|
||||
NewTabArgs(const Model::INewContentArgs& terminalArgs) :
|
||||
_ContentArgs{ terminalArgs } {};
|
||||
WINRT_PROPERTY(Model::INewContentArgs, ContentArgs, nullptr);
|
||||
WINRT_PROPERTY(Model::INewContentArgs, ContentArgs, Model::NewTerminalArgs{});
|
||||
|
||||
public:
|
||||
hstring GenerateName() const;
|
||||
@@ -632,34 +633,61 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
h.write(ContentArgs());
|
||||
return h.finalize();
|
||||
}
|
||||
uint32_t GetArgCount() const
|
||||
{
|
||||
if (_ContentArgs)
|
||||
{
|
||||
if (const auto newTermArgs = _ContentArgs.try_as<NewTerminalArgs>())
|
||||
{
|
||||
return newTermArgs->GetArgCount();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
Model::ArgDescriptor GetArgDescriptorAt(uint32_t index) const
|
||||
{
|
||||
return _ContentArgs.as<NewTerminalArgs>()->GetArgDescriptorAt(index);
|
||||
}
|
||||
IInspectable GetArgAt(uint32_t index) const
|
||||
{
|
||||
return _ContentArgs.as<NewTerminalArgs>()->GetArgAt(index);
|
||||
}
|
||||
void SetArgAt(uint32_t index, IInspectable value)
|
||||
{
|
||||
_ContentArgs.as<NewTerminalArgs>()->SetArgAt(index, value);
|
||||
}
|
||||
};
|
||||
|
||||
struct SplitPaneArgs : public SplitPaneArgsT<SplitPaneArgs>
|
||||
{
|
||||
SplitPaneArgs() = default;
|
||||
SplitPaneArgs(){
|
||||
SPLIT_PANE_ARGS(APPEND_ARG_DESCRIPTION)
|
||||
};
|
||||
SplitPaneArgs(SplitType splitMode, SplitDirection direction, float size, const Model::INewContentArgs& terminalArgs) :
|
||||
_SplitMode{ splitMode },
|
||||
_SplitDirection{ direction },
|
||||
_SplitSize{ size },
|
||||
_ContentArgs{ terminalArgs } {};
|
||||
_ContentArgs{ terminalArgs } {
|
||||
SPLIT_PANE_ARGS(APPEND_ARG_DESCRIPTION)
|
||||
};
|
||||
SplitPaneArgs(SplitDirection direction, float size, const Model::INewContentArgs& terminalArgs) :
|
||||
_SplitDirection{ direction },
|
||||
_SplitSize{ size },
|
||||
_ContentArgs{ terminalArgs } {};
|
||||
_ContentArgs{ terminalArgs } {
|
||||
SPLIT_PANE_ARGS(APPEND_ARG_DESCRIPTION)
|
||||
};
|
||||
SplitPaneArgs(SplitDirection direction, const Model::INewContentArgs& terminalArgs) :
|
||||
_SplitDirection{ direction },
|
||||
_ContentArgs{ terminalArgs } {};
|
||||
_ContentArgs{ terminalArgs } {
|
||||
SPLIT_PANE_ARGS(APPEND_ARG_DESCRIPTION)
|
||||
};
|
||||
SplitPaneArgs(SplitType splitMode) :
|
||||
_SplitMode{ splitMode } {};
|
||||
_SplitMode{ splitMode } {
|
||||
SPLIT_PANE_ARGS(APPEND_ARG_DESCRIPTION)
|
||||
};
|
||||
|
||||
ACTION_ARG(Model::SplitDirection, SplitDirection, SplitDirection::Automatic);
|
||||
WINRT_PROPERTY(Model::INewContentArgs, ContentArgs, nullptr);
|
||||
ACTION_ARG(SplitType, SplitMode, SplitType::Manual);
|
||||
ACTION_ARG(float, SplitSize, 0.5f);
|
||||
|
||||
static constexpr std::string_view SplitKey{ "split" };
|
||||
static constexpr std::string_view SplitModeKey{ "splitMode" };
|
||||
static constexpr std::string_view SplitSizeKey{ "size" };
|
||||
SPLIT_PANE_ARGS(DECLARE_ARGS);
|
||||
WINRT_PROPERTY(Model::INewContentArgs, ContentArgs, Model::NewTerminalArgs{});
|
||||
|
||||
public:
|
||||
hstring GenerateName() const;
|
||||
@@ -681,7 +709,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
{
|
||||
// LOAD BEARING: Not using make_self here _will_ break you in the future!
|
||||
auto args = winrt::make_self<SplitPaneArgs>();
|
||||
JsonUtils::GetValueForKey(json, SplitKey, args->_SplitDirection);
|
||||
JsonUtils::GetValueForKey(json, SplitDirectionKey, args->_SplitDirection);
|
||||
JsonUtils::GetValueForKey(json, SplitModeKey, args->_SplitMode);
|
||||
JsonUtils::GetValueForKey(json, SplitSizeKey, args->_SplitSize);
|
||||
if (args->SplitSize() >= 1 || args->SplitSize() <= 0)
|
||||
@@ -701,7 +729,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
}
|
||||
const auto args{ get_self<SplitPaneArgs>(val) };
|
||||
auto json{ ContentArgsToJson(args->_ContentArgs) };
|
||||
JsonUtils::SetValueForKey(json, SplitKey, args->_SplitDirection);
|
||||
JsonUtils::SetValueForKey(json, SplitDirectionKey, args->_SplitDirection);
|
||||
JsonUtils::SetValueForKey(json, SplitModeKey, args->_SplitMode);
|
||||
JsonUtils::SetValueForKey(json, SplitSizeKey, args->_SplitSize);
|
||||
return json;
|
||||
@@ -713,6 +741,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
copy->_ContentArgs = _ContentArgs.Copy();
|
||||
copy->_SplitMode = _SplitMode;
|
||||
copy->_SplitSize = _SplitSize;
|
||||
copy->_argDescriptors = _argDescriptors;
|
||||
return *copy;
|
||||
}
|
||||
size_t Hash() const
|
||||
@@ -724,6 +753,59 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
h.write(SplitSize());
|
||||
return h.finalize();
|
||||
}
|
||||
uint32_t GetArgCount() const
|
||||
{
|
||||
if (_ContentArgs)
|
||||
{
|
||||
if (const auto newTermArgs = _ContentArgs.try_as<NewTerminalArgs>())
|
||||
{
|
||||
return newTermArgs->GetArgCount() + gsl::narrow<uint32_t>(_argDescriptors.size());
|
||||
}
|
||||
}
|
||||
return gsl::narrow<uint32_t>(_argDescriptors.size());
|
||||
}
|
||||
Model::ArgDescriptor GetArgDescriptorAt(uint32_t index) const
|
||||
{
|
||||
const auto additionalArgCount = gsl::narrow<uint32_t>(_argDescriptors.size());
|
||||
if (index < additionalArgCount)
|
||||
{
|
||||
return _argDescriptors.at(index);
|
||||
}
|
||||
else
|
||||
{
|
||||
return _ContentArgs.as<NewTerminalArgs>()->GetArgDescriptorAt(index - additionalArgCount);
|
||||
}
|
||||
}
|
||||
IInspectable GetArgAt(uint32_t index) const
|
||||
{
|
||||
const auto additionalArgCount = gsl::narrow<uint32_t>(_argDescriptors.size());
|
||||
if (index < additionalArgCount)
|
||||
{
|
||||
uint32_t curIndex{ 0 };
|
||||
SPLIT_PANE_ARGS(GET_ARG_BY_INDEX);
|
||||
}
|
||||
else
|
||||
{
|
||||
return _ContentArgs.as<NewTerminalArgs>()->GetArgAt(index - additionalArgCount);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
void SetArgAt(uint32_t index, IInspectable value)
|
||||
{
|
||||
const auto additionalArgCount = gsl::narrow<uint32_t>(_argDescriptors.size());
|
||||
if (index < additionalArgCount)
|
||||
{
|
||||
uint32_t curIndex{ 0 };
|
||||
SPLIT_PANE_ARGS(SET_ARG_BY_INDEX);
|
||||
}
|
||||
else
|
||||
{
|
||||
_ContentArgs.as<NewTerminalArgs>()->SetArgAt(index - additionalArgCount, value);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<ArgDescriptor> _argDescriptors;
|
||||
};
|
||||
|
||||
struct NewWindowArgs : public NewWindowArgsT<NewWindowArgs>
|
||||
@@ -731,7 +813,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
NewWindowArgs() = default;
|
||||
NewWindowArgs(const Model::INewContentArgs& terminalArgs) :
|
||||
_ContentArgs{ terminalArgs } {};
|
||||
WINRT_PROPERTY(Model::INewContentArgs, ContentArgs, nullptr);
|
||||
WINRT_PROPERTY(Model::INewContentArgs, ContentArgs, Model::NewTerminalArgs{});
|
||||
|
||||
public:
|
||||
hstring GenerateName() const;
|
||||
@@ -774,6 +856,29 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
h.write(ContentArgs());
|
||||
return h.finalize();
|
||||
}
|
||||
uint32_t GetArgCount() const
|
||||
{
|
||||
if (_ContentArgs)
|
||||
{
|
||||
if (const auto newTermArgs = _ContentArgs.try_as<NewTerminalArgs>())
|
||||
{
|
||||
return newTermArgs->GetArgCount();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
Model::ArgDescriptor GetArgDescriptorAt(uint32_t index) const
|
||||
{
|
||||
return _ContentArgs.as<NewTerminalArgs>()->GetArgDescriptorAt(index);
|
||||
}
|
||||
IInspectable GetArgAt(uint32_t index) const
|
||||
{
|
||||
return _ContentArgs.as<NewTerminalArgs>()->GetArgAt(index);
|
||||
}
|
||||
void SetArgAt(uint32_t index, IInspectable value)
|
||||
{
|
||||
_ContentArgs.as<NewTerminalArgs>()->SetArgAt(index, value);
|
||||
}
|
||||
};
|
||||
|
||||
ACTION_ARGS_STRUCT(CopyTextArgs, COPY_TEXT_ARGS);
|
||||
@@ -913,6 +1018,22 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
h.write(winrt::get_abi(_Actions));
|
||||
return h.finalize();
|
||||
}
|
||||
uint32_t GetArgCount() const
|
||||
{
|
||||
return _Actions.Size();
|
||||
}
|
||||
Model::ArgDescriptor GetArgDescriptorAt(uint32_t /*index*/) const
|
||||
{
|
||||
return {};
|
||||
}
|
||||
IInspectable GetArgAt(uint32_t /*index*/) const
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
void SetArgAt(uint32_t /*index*/, IInspectable /*value*/)
|
||||
{
|
||||
throw winrt::hresult_not_implemented();
|
||||
}
|
||||
};
|
||||
|
||||
ACTION_ARGS_STRUCT(AdjustOpacityArgs, ADJUST_OPACITY_ARGS);
|
||||
|
||||
@@ -5,6 +5,30 @@ import "Command.idl";
|
||||
|
||||
namespace Microsoft.Terminal.Settings.Model
|
||||
{
|
||||
enum ArgTypeHint
|
||||
{
|
||||
None = 0,
|
||||
FilePath,
|
||||
FolderPath,
|
||||
ColorScheme
|
||||
};
|
||||
|
||||
struct ArgDescriptor
|
||||
{
|
||||
String Name;
|
||||
String Type;
|
||||
Boolean Required;
|
||||
ArgTypeHint Tag;
|
||||
};
|
||||
|
||||
interface IActionArgsDescriptorAccess
|
||||
{
|
||||
UInt32 GetArgCount();
|
||||
ArgDescriptor GetArgDescriptorAt(UInt32 index);
|
||||
IInspectable GetArgAt(UInt32 index);
|
||||
void SetArgAt(UInt32 index, Object value);
|
||||
};
|
||||
|
||||
interface IActionArgs
|
||||
{
|
||||
Boolean Equals(IActionArgs other);
|
||||
@@ -137,7 +161,7 @@ namespace Microsoft.Terminal.Settings.Model
|
||||
BaseContentArgs(String type);
|
||||
};
|
||||
|
||||
runtimeclass NewTerminalArgs : INewContentArgs {
|
||||
runtimeclass NewTerminalArgs : INewContentArgs, IActionArgsDescriptorAccess {
|
||||
NewTerminalArgs();
|
||||
NewTerminalArgs(Int32 profileIndex);
|
||||
|
||||
@@ -176,7 +200,7 @@ namespace Microsoft.Terminal.Settings.Model
|
||||
ActionEventArgs(IActionArgs args);
|
||||
};
|
||||
|
||||
[default_interface] runtimeclass CopyTextArgs : IActionArgs
|
||||
[default_interface] runtimeclass CopyTextArgs : IActionArgs, IActionArgsDescriptorAccess
|
||||
{
|
||||
CopyTextArgs();
|
||||
Boolean DismissSelection { get; };
|
||||
@@ -185,55 +209,55 @@ namespace Microsoft.Terminal.Settings.Model
|
||||
Windows.Foundation.IReference<Microsoft.Terminal.Control.CopyFormat> CopyFormatting { get; };
|
||||
};
|
||||
|
||||
[default_interface] runtimeclass NewTabArgs : IActionArgs
|
||||
[default_interface] runtimeclass NewTabArgs : IActionArgs, IActionArgsDescriptorAccess
|
||||
{
|
||||
NewTabArgs(INewContentArgs contentArgs);
|
||||
INewContentArgs ContentArgs { get; };
|
||||
};
|
||||
|
||||
[default_interface] runtimeclass MovePaneArgs : IActionArgs
|
||||
[default_interface] runtimeclass MovePaneArgs : IActionArgs, IActionArgsDescriptorAccess
|
||||
{
|
||||
MovePaneArgs(UInt32 tabIndex, String Window);
|
||||
UInt32 TabIndex;
|
||||
String Window;
|
||||
};
|
||||
|
||||
[default_interface] runtimeclass SwitchToTabArgs : IActionArgs
|
||||
[default_interface] runtimeclass SwitchToTabArgs : IActionArgs, IActionArgsDescriptorAccess
|
||||
{
|
||||
SwitchToTabArgs(UInt32 tabIndex);
|
||||
UInt32 TabIndex;
|
||||
};
|
||||
|
||||
[default_interface] runtimeclass ResizePaneArgs : IActionArgs
|
||||
[default_interface] runtimeclass ResizePaneArgs : IActionArgs, IActionArgsDescriptorAccess
|
||||
{
|
||||
ResizeDirection ResizeDirection { get; };
|
||||
};
|
||||
|
||||
[default_interface] runtimeclass MoveFocusArgs : IActionArgs
|
||||
[default_interface] runtimeclass MoveFocusArgs : IActionArgs, IActionArgsDescriptorAccess
|
||||
{
|
||||
MoveFocusArgs(FocusDirection direction);
|
||||
FocusDirection FocusDirection { get; };
|
||||
};
|
||||
|
||||
[default_interface] runtimeclass SwapPaneArgs : IActionArgs
|
||||
[default_interface] runtimeclass SwapPaneArgs : IActionArgs, IActionArgsDescriptorAccess
|
||||
{
|
||||
SwapPaneArgs(FocusDirection direction);
|
||||
FocusDirection Direction { get; };
|
||||
};
|
||||
|
||||
[default_interface] runtimeclass AdjustFontSizeArgs : IActionArgs
|
||||
[default_interface] runtimeclass AdjustFontSizeArgs : IActionArgs, IActionArgsDescriptorAccess
|
||||
{
|
||||
Single Delta { get; };
|
||||
};
|
||||
|
||||
[default_interface] runtimeclass SendInputArgs : IActionArgs
|
||||
[default_interface] runtimeclass SendInputArgs : IActionArgs, IActionArgsDescriptorAccess
|
||||
{
|
||||
SendInputArgs(String input);
|
||||
|
||||
String Input { get; };
|
||||
};
|
||||
|
||||
[default_interface] runtimeclass SplitPaneArgs : IActionArgs
|
||||
[default_interface] runtimeclass SplitPaneArgs : IActionArgs, IActionArgsDescriptorAccess
|
||||
{
|
||||
SplitPaneArgs(SplitType splitMode, SplitDirection split, Single size, INewContentArgs contentArgs);
|
||||
SplitPaneArgs(SplitDirection split, Single size, INewContentArgs contentArgs);
|
||||
@@ -246,106 +270,106 @@ namespace Microsoft.Terminal.Settings.Model
|
||||
Single SplitSize { get; };
|
||||
};
|
||||
|
||||
[default_interface] runtimeclass OpenSettingsArgs : IActionArgs
|
||||
[default_interface] runtimeclass OpenSettingsArgs : IActionArgs, IActionArgsDescriptorAccess
|
||||
{
|
||||
OpenSettingsArgs(SettingsTarget target);
|
||||
SettingsTarget Target { get; };
|
||||
};
|
||||
|
||||
[default_interface] runtimeclass SetFocusModeArgs : IActionArgs
|
||||
[default_interface] runtimeclass SetFocusModeArgs : IActionArgs, IActionArgsDescriptorAccess
|
||||
{
|
||||
SetFocusModeArgs(Boolean isFocusMode);
|
||||
Boolean IsFocusMode { get; };
|
||||
};
|
||||
|
||||
[default_interface] runtimeclass SetFullScreenArgs : IActionArgs
|
||||
[default_interface] runtimeclass SetFullScreenArgs : IActionArgs, IActionArgsDescriptorAccess
|
||||
{
|
||||
SetFullScreenArgs(Boolean isFullScreen);
|
||||
Boolean IsFullScreen { get; };
|
||||
};
|
||||
|
||||
[default_interface] runtimeclass SetMaximizedArgs : IActionArgs
|
||||
[default_interface] runtimeclass SetMaximizedArgs : IActionArgs, IActionArgsDescriptorAccess
|
||||
{
|
||||
SetMaximizedArgs(Boolean isMaximized);
|
||||
Boolean IsMaximized { get; };
|
||||
};
|
||||
|
||||
[default_interface] runtimeclass SetColorSchemeArgs : IActionArgs
|
||||
[default_interface] runtimeclass SetColorSchemeArgs : IActionArgs, IActionArgsDescriptorAccess
|
||||
{
|
||||
SetColorSchemeArgs(String name);
|
||||
String SchemeName { get; };
|
||||
};
|
||||
|
||||
[default_interface] runtimeclass SetTabColorArgs : IActionArgs
|
||||
[default_interface] runtimeclass SetTabColorArgs : IActionArgs, IActionArgsDescriptorAccess
|
||||
{
|
||||
SetTabColorArgs(Windows.UI.Color tabColor);
|
||||
Windows.Foundation.IReference<Windows.UI.Color> TabColor { get; };
|
||||
};
|
||||
|
||||
[default_interface] runtimeclass RenameTabArgs : IActionArgs
|
||||
[default_interface] runtimeclass RenameTabArgs : IActionArgs, IActionArgsDescriptorAccess
|
||||
{
|
||||
RenameTabArgs(String title);
|
||||
String Title { get; };
|
||||
};
|
||||
|
||||
[default_interface] runtimeclass ExecuteCommandlineArgs : IActionArgs
|
||||
[default_interface] runtimeclass ExecuteCommandlineArgs : IActionArgs, IActionArgsDescriptorAccess
|
||||
{
|
||||
ExecuteCommandlineArgs(String commandline);
|
||||
String Commandline;
|
||||
};
|
||||
|
||||
[default_interface] runtimeclass CloseOtherTabsArgs : IActionArgs
|
||||
[default_interface] runtimeclass CloseOtherTabsArgs : IActionArgs, IActionArgsDescriptorAccess
|
||||
{
|
||||
CloseOtherTabsArgs(UInt32 tabIndex);
|
||||
Windows.Foundation.IReference<UInt32> Index { get; };
|
||||
};
|
||||
|
||||
[default_interface] runtimeclass CloseTabsAfterArgs : IActionArgs
|
||||
[default_interface] runtimeclass CloseTabsAfterArgs : IActionArgs, IActionArgsDescriptorAccess
|
||||
{
|
||||
CloseTabsAfterArgs(UInt32 tabIndex);
|
||||
Windows.Foundation.IReference<UInt32> Index { get; };
|
||||
};
|
||||
|
||||
[default_interface] runtimeclass CloseTabArgs : IActionArgs
|
||||
[default_interface] runtimeclass CloseTabArgs : IActionArgs, IActionArgsDescriptorAccess
|
||||
{
|
||||
CloseTabArgs(UInt32 tabIndex);
|
||||
Windows.Foundation.IReference<UInt32> Index { get; };
|
||||
};
|
||||
|
||||
[default_interface] runtimeclass MoveTabArgs : IActionArgs
|
||||
[default_interface] runtimeclass MoveTabArgs : IActionArgs, IActionArgsDescriptorAccess
|
||||
{
|
||||
MoveTabArgs(String window, MoveTabDirection direction);
|
||||
MoveTabDirection Direction { get; };
|
||||
String Window { get; };
|
||||
};
|
||||
|
||||
[default_interface] runtimeclass ScrollUpArgs : IActionArgs
|
||||
[default_interface] runtimeclass ScrollUpArgs : IActionArgs, IActionArgsDescriptorAccess
|
||||
{
|
||||
Windows.Foundation.IReference<UInt32> RowsToScroll { get; };
|
||||
};
|
||||
|
||||
[default_interface] runtimeclass ScrollDownArgs : IActionArgs
|
||||
[default_interface] runtimeclass ScrollDownArgs : IActionArgs, IActionArgsDescriptorAccess
|
||||
{
|
||||
Windows.Foundation.IReference<UInt32> RowsToScroll { get; };
|
||||
};
|
||||
|
||||
|
||||
[default_interface] runtimeclass ScrollToMarkArgs : IActionArgs
|
||||
[default_interface] runtimeclass ScrollToMarkArgs : IActionArgs, IActionArgsDescriptorAccess
|
||||
{
|
||||
Microsoft.Terminal.Control.ScrollToMarkDirection Direction { get; };
|
||||
};
|
||||
|
||||
[default_interface] runtimeclass AddMarkArgs : IActionArgs
|
||||
[default_interface] runtimeclass AddMarkArgs : IActionArgs, IActionArgsDescriptorAccess
|
||||
{
|
||||
Windows.Foundation.IReference<Microsoft.Terminal.Core.Color> Color { get; };
|
||||
};
|
||||
|
||||
[default_interface] runtimeclass ToggleCommandPaletteArgs : IActionArgs
|
||||
[default_interface] runtimeclass ToggleCommandPaletteArgs : IActionArgs, IActionArgsDescriptorAccess
|
||||
{
|
||||
CommandPaletteLaunchMode LaunchMode { get; };
|
||||
};
|
||||
|
||||
[default_interface] runtimeclass SuggestionsArgs : IActionArgs
|
||||
[default_interface] runtimeclass SuggestionsArgs : IActionArgs, IActionArgsDescriptorAccess
|
||||
{
|
||||
SuggestionsArgs();
|
||||
SuggestionsArgs(SuggestionsSource source, Boolean useCommandline);
|
||||
@@ -353,13 +377,13 @@ namespace Microsoft.Terminal.Settings.Model
|
||||
Boolean UseCommandline { get; };
|
||||
};
|
||||
|
||||
[default_interface] runtimeclass FindMatchArgs : IActionArgs
|
||||
[default_interface] runtimeclass FindMatchArgs : IActionArgs, IActionArgsDescriptorAccess
|
||||
{
|
||||
FindMatchArgs(FindMatchDirection direction);
|
||||
FindMatchDirection Direction { get; };
|
||||
};
|
||||
|
||||
[default_interface] runtimeclass SaveSnippetArgs : IActionArgs
|
||||
[default_interface] runtimeclass SaveSnippetArgs : IActionArgs, IActionArgsDescriptorAccess
|
||||
{
|
||||
SaveSnippetArgs();
|
||||
SaveSnippetArgs(String Name, String Commandline, String KeyChord);
|
||||
@@ -368,38 +392,38 @@ namespace Microsoft.Terminal.Settings.Model
|
||||
String KeyChord;
|
||||
};
|
||||
|
||||
[default_interface] runtimeclass NewWindowArgs : IActionArgs
|
||||
[default_interface] runtimeclass NewWindowArgs : IActionArgs, IActionArgsDescriptorAccess
|
||||
{
|
||||
NewWindowArgs(INewContentArgs contentArgs);
|
||||
INewContentArgs ContentArgs { get; };
|
||||
};
|
||||
|
||||
[default_interface] runtimeclass PrevTabArgs : IActionArgs
|
||||
[default_interface] runtimeclass PrevTabArgs : IActionArgs, IActionArgsDescriptorAccess
|
||||
{
|
||||
PrevTabArgs();
|
||||
PrevTabArgs(TabSwitcherMode SwitcherMode);
|
||||
Windows.Foundation.IReference<TabSwitcherMode> SwitcherMode;
|
||||
};
|
||||
|
||||
[default_interface] runtimeclass NextTabArgs : IActionArgs
|
||||
[default_interface] runtimeclass NextTabArgs : IActionArgs, IActionArgsDescriptorAccess
|
||||
{
|
||||
NextTabArgs();
|
||||
NextTabArgs(TabSwitcherMode SwitcherMode);
|
||||
Windows.Foundation.IReference<TabSwitcherMode> SwitcherMode;
|
||||
};
|
||||
|
||||
[default_interface] runtimeclass RenameWindowArgs : IActionArgs
|
||||
[default_interface] runtimeclass RenameWindowArgs : IActionArgs, IActionArgsDescriptorAccess
|
||||
{
|
||||
RenameWindowArgs(String name);
|
||||
String Name { get; };
|
||||
};
|
||||
|
||||
[default_interface] runtimeclass SearchForTextArgs : IActionArgs
|
||||
[default_interface] runtimeclass SearchForTextArgs : IActionArgs, IActionArgsDescriptorAccess
|
||||
{
|
||||
String QueryUrl { get; };
|
||||
};
|
||||
|
||||
[default_interface] runtimeclass GlobalSummonArgs : IActionArgs
|
||||
[default_interface] runtimeclass GlobalSummonArgs : IActionArgs, IActionArgsDescriptorAccess
|
||||
{
|
||||
String Name { get; };
|
||||
DesktopBehavior Desktop { get; };
|
||||
@@ -408,50 +432,50 @@ namespace Microsoft.Terminal.Settings.Model
|
||||
UInt32 DropdownDuration { get; };
|
||||
};
|
||||
|
||||
[default_interface] runtimeclass FocusPaneArgs : IActionArgs
|
||||
[default_interface] runtimeclass FocusPaneArgs : IActionArgs, IActionArgsDescriptorAccess
|
||||
{
|
||||
FocusPaneArgs(UInt32 Id);
|
||||
UInt32 Id { get; };
|
||||
};
|
||||
|
||||
[default_interface] runtimeclass ExportBufferArgs : IActionArgs
|
||||
[default_interface] runtimeclass ExportBufferArgs : IActionArgs, IActionArgsDescriptorAccess
|
||||
{
|
||||
ExportBufferArgs(String path);
|
||||
String Path { get; };
|
||||
};
|
||||
|
||||
[default_interface] runtimeclass ClearBufferArgs : IActionArgs
|
||||
[default_interface] runtimeclass ClearBufferArgs : IActionArgs, IActionArgsDescriptorAccess
|
||||
{
|
||||
ClearBufferArgs(Microsoft.Terminal.Control.ClearBufferType clear);
|
||||
Microsoft.Terminal.Control.ClearBufferType Clear { get; };
|
||||
};
|
||||
|
||||
[default_interface] runtimeclass MultipleActionsArgs : IActionArgs
|
||||
[default_interface] runtimeclass MultipleActionsArgs : IActionArgs, IActionArgsDescriptorAccess
|
||||
{
|
||||
MultipleActionsArgs();
|
||||
Windows.Foundation.Collections.IVector<ActionAndArgs> Actions;
|
||||
};
|
||||
|
||||
[default_interface] runtimeclass AdjustOpacityArgs : IActionArgs
|
||||
[default_interface] runtimeclass AdjustOpacityArgs : IActionArgs, IActionArgsDescriptorAccess
|
||||
{
|
||||
AdjustOpacityArgs();
|
||||
Int32 Opacity { get; };
|
||||
Boolean Relative { get; };
|
||||
};
|
||||
|
||||
[default_interface] runtimeclass ColorSelectionArgs : IActionArgs
|
||||
[default_interface] runtimeclass ColorSelectionArgs : IActionArgs, IActionArgsDescriptorAccess
|
||||
{
|
||||
Microsoft.Terminal.Control.SelectionColor Foreground;
|
||||
Microsoft.Terminal.Control.SelectionColor Background;
|
||||
Microsoft.Terminal.Core.MatchMode MatchMode { get; };
|
||||
};
|
||||
|
||||
[default_interface] runtimeclass SelectCommandArgs : IActionArgs
|
||||
[default_interface] runtimeclass SelectCommandArgs : IActionArgs, IActionArgsDescriptorAccess
|
||||
{
|
||||
SelectCommandArgs(SelectOutputDirection direction);
|
||||
SelectOutputDirection Direction { get; };
|
||||
}
|
||||
[default_interface] runtimeclass SelectOutputArgs : IActionArgs
|
||||
[default_interface] runtimeclass SelectOutputArgs : IActionArgs, IActionArgsDescriptorAccess
|
||||
{
|
||||
SelectOutputArgs(SelectOutputDirection direction);
|
||||
SelectOutputDirection Direction { get; };
|
||||
|
||||
@@ -54,24 +54,55 @@ struct InitListPlaceholder
|
||||
// expanded. Pretty critical for tracking down extraneous commas, etc.
|
||||
|
||||
// Property definitions, and JSON keys
|
||||
#define DECLARE_ARGS(type, name, jsonKey, required, ...) \
|
||||
static constexpr std::string_view name##Key{ jsonKey }; \
|
||||
#define DECLARE_ARGS(type, name, jsonKey, required, tag, ...) \
|
||||
static constexpr std::string_view name##Key{ jsonKey }; \
|
||||
ACTION_ARG(type, name, ##__VA_ARGS__);
|
||||
|
||||
// Parameters to the non-default ctor
|
||||
#define CTOR_PARAMS(type, name, jsonKey, required, ...) \
|
||||
#define CTOR_PARAMS(type, name, jsonKey, required, tag, ...) \
|
||||
const type &name##Param,
|
||||
|
||||
// initializers in the ctor
|
||||
#define CTOR_INIT(type, name, jsonKey, required, ...) \
|
||||
#define CTOR_INIT(type, name, jsonKey, required, tag, ...) \
|
||||
_##name{ name##Param },
|
||||
|
||||
// append this argument's description to the internal vector
|
||||
#define APPEND_ARG_DESCRIPTION(type, name, jsonKey, required, tag, ...) \
|
||||
_argDescriptors.push_back({ L## #name, L## #type, std::wstring_view(L## #required) != L"false", tag });
|
||||
|
||||
// check each property in the Equals() method. You'll note there's a stray
|
||||
// `true` in the definition of Equals() below, that's to deal with trailing
|
||||
// commas
|
||||
#define EQUALS_ARGS(type, name, jsonKey, required, ...) \
|
||||
#define EQUALS_ARGS(type, name, jsonKey, required, tag, ...) \
|
||||
&&(otherAsUs->_##name == _##name)
|
||||
|
||||
// getter and setter for each property by index
|
||||
#define GET_ARG_BY_INDEX(type, name, jsonKey, required, tag, ...) \
|
||||
if (index == curIndex++) \
|
||||
{ \
|
||||
if (_##name.has_value()) \
|
||||
{ \
|
||||
return winrt::box_value(_##name.value()); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
return winrt::box_value(static_cast<type>(__VA_ARGS__)); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define SET_ARG_BY_INDEX(type, name, jsonKey, required, tag, ...) \
|
||||
if (index == curIndex++) \
|
||||
{ \
|
||||
if (value) \
|
||||
{ \
|
||||
_##name = winrt::unbox_value<type>(value); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
_##name = std::nullopt; \
|
||||
} \
|
||||
}
|
||||
|
||||
// JSON deserialization. If the parameter is required to pass any validation,
|
||||
// add that as the `required` parameter here, as the body of a conditional
|
||||
// EX: For the RESIZE_PANE_ARGS
|
||||
@@ -79,7 +110,7 @@ struct InitListPlaceholder
|
||||
// the bit
|
||||
// args->ResizeDirection() == ResizeDirection::None
|
||||
// is used as the conditional for the validation here.
|
||||
#define FROM_JSON_ARGS(type, name, jsonKey, required, ...) \
|
||||
#define FROM_JSON_ARGS(type, name, jsonKey, required, tag, ...) \
|
||||
JsonUtils::GetValueForKey(json, jsonKey, args->_##name); \
|
||||
if (required) \
|
||||
{ \
|
||||
@@ -87,17 +118,17 @@ struct InitListPlaceholder
|
||||
}
|
||||
|
||||
// JSON serialization
|
||||
#define TO_JSON_ARGS(type, name, jsonKey, required, ...) \
|
||||
#define TO_JSON_ARGS(type, name, jsonKey, required, tag, ...) \
|
||||
JsonUtils::SetValueForKey(json, jsonKey, args->_##name);
|
||||
|
||||
// Copy each property in the Copy() method
|
||||
#define COPY_ARGS(type, name, jsonKey, required, ...) \
|
||||
#define COPY_ARGS(type, name, jsonKey, required, tag, ...) \
|
||||
copy->_##name = _##name;
|
||||
|
||||
// hash each property in Hash(). You'll note there's a stray `0` in the
|
||||
// definition of Hash() below, that's to deal with trailing commas (or in this
|
||||
// case, leading.)
|
||||
#define HASH_ARGS(type, name, jsonKey, required, ...) \
|
||||
#define HASH_ARGS(type, name, jsonKey, required, tag, ...) \
|
||||
h.write(name());
|
||||
|
||||
// Use ACTION_ARGS_STRUCT when you've got no other customizing to do.
|
||||
@@ -111,53 +142,108 @@ 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(){ argsMacro(APPEND_ARG_DESCRIPTION) }; \
|
||||
className( \
|
||||
argsMacro(CTOR_PARAMS) InitListPlaceholder = {}) : \
|
||||
argsMacro(CTOR_INIT) _placeholder{} { \
|
||||
argsMacro(APPEND_ARG_DESCRIPTION) \
|
||||
}; \
|
||||
argsMacro(DECLARE_ARGS); \
|
||||
\
|
||||
private: \
|
||||
InitListPlaceholder _placeholder; \
|
||||
std::vector<ArgDescriptor> _argDescriptors; \
|
||||
\
|
||||
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); \
|
||||
copy->_argDescriptors = _argDescriptors; \
|
||||
return *copy; \
|
||||
} \
|
||||
size_t Hash() const \
|
||||
{ \
|
||||
til::hasher h; \
|
||||
argsMacro(HASH_ARGS); \
|
||||
return h.finalize(); \
|
||||
} \
|
||||
uint32_t GetArgCount() const \
|
||||
{ \
|
||||
return gsl::narrow<uint32_t>(_argDescriptors.size()); \
|
||||
} \
|
||||
ArgDescriptor GetArgDescriptorAt(uint32_t index) const \
|
||||
{ \
|
||||
return _argDescriptors.at(index); \
|
||||
} \
|
||||
IInspectable GetArgAt(uint32_t index) const \
|
||||
{ \
|
||||
uint32_t curIndex{ 0 }; \
|
||||
argsMacro(GET_ARG_BY_INDEX) return nullptr; \
|
||||
} \
|
||||
void SetArgAt(uint32_t index, IInspectable value) \
|
||||
{ \
|
||||
uint32_t curIndex{ 0 }; \
|
||||
argsMacro(SET_ARG_BY_INDEX) \
|
||||
}
|
||||
|
||||
#define PARTIAL_ACTION_ARG_BODY(className, argsMacro) \
|
||||
className(){ argsMacro(APPEND_ARG_DESCRIPTION) }; \
|
||||
className( \
|
||||
argsMacro(CTOR_PARAMS) InitListPlaceholder = {}) : \
|
||||
argsMacro(CTOR_INIT) _placeholder{} { \
|
||||
argsMacro(APPEND_ARG_DESCRIPTION) \
|
||||
}; \
|
||||
argsMacro(DECLARE_ARGS); \
|
||||
\
|
||||
private: \
|
||||
InitListPlaceholder _placeholder; \
|
||||
std::vector<ArgDescriptor> _argDescriptors; \
|
||||
\
|
||||
public: \
|
||||
uint32_t GetArgCount() const \
|
||||
{ \
|
||||
return gsl::narrow<uint32_t>(_argDescriptors.size()); \
|
||||
} \
|
||||
ArgDescriptor GetArgDescriptorAt(uint32_t index) const \
|
||||
{ \
|
||||
return _argDescriptors.at(index); \
|
||||
} \
|
||||
IInspectable GetArgAt(uint32_t index) const \
|
||||
{ \
|
||||
uint32_t curIndex{ 0 }; \
|
||||
argsMacro(GET_ARG_BY_INDEX) return nullptr; \
|
||||
} \
|
||||
void SetArgAt(uint32_t index, IInspectable value) \
|
||||
{ \
|
||||
uint32_t curIndex{ 0 }; \
|
||||
argsMacro(SET_ARG_BY_INDEX) \
|
||||
}
|
||||
|
||||
@@ -380,6 +380,15 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
return _ResolvedKeyToActionMapCache.GetView();
|
||||
}
|
||||
|
||||
IVectorView<Model::Command> ActionMap::AllCommands()
|
||||
{
|
||||
if (!_ResolvedKeyToActionMapCache)
|
||||
{
|
||||
_RefreshKeyBindingCaches();
|
||||
}
|
||||
return _AllCommandsCache.GetView();
|
||||
}
|
||||
|
||||
void ActionMap::_RefreshKeyBindingCaches()
|
||||
{
|
||||
_CumulativeKeyToActionMapCache.clear();
|
||||
@@ -387,6 +396,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
_CumulativeActionToKeyMapCache.clear();
|
||||
std::unordered_map<KeyChord, Model::Command, KeyChordHash, KeyChordEquality> globalHotkeys;
|
||||
std::unordered_map<KeyChord, Model::Command, KeyChordHash, KeyChordEquality> resolvedKeyToActionMap;
|
||||
std::vector<Model::Command> allCommandsVector;
|
||||
|
||||
_PopulateCumulativeKeyMaps(_CumulativeKeyToActionMapCache, _CumulativeActionToKeyMapCache);
|
||||
_PopulateCumulativeActionMap(_CumulativeIDToActionMapCache);
|
||||
@@ -406,8 +416,14 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto& [_, cmd] : _CumulativeIDToActionMapCache)
|
||||
{
|
||||
allCommandsVector.emplace_back(cmd);
|
||||
}
|
||||
|
||||
_ResolvedKeyToActionMapCache = single_threaded_map(std::move(resolvedKeyToActionMap));
|
||||
_GlobalHotkeysCache = single_threaded_map(std::move(globalHotkeys));
|
||||
_AllCommandsCache = single_threaded_vector(std::move(allCommandsVector));
|
||||
}
|
||||
|
||||
com_ptr<ActionMap> ActionMap::Copy() const
|
||||
@@ -421,7 +437,9 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
actionMap->_ActionMap.reserve(_ActionMap.size());
|
||||
for (const auto& [actionID, cmd] : _ActionMap)
|
||||
{
|
||||
actionMap->_ActionMap.emplace(actionID, *winrt::get_self<Command>(cmd)->Copy());
|
||||
const auto copiedCmd = winrt::get_self<Command>(cmd)->Copy();
|
||||
actionMap->_ActionMap.emplace(actionID, *copiedCmd);
|
||||
copiedCmd->IDChanged({ actionMap.get(), &ActionMap::_CommandIDChangedHandler });
|
||||
}
|
||||
|
||||
// Name --> Command
|
||||
@@ -541,6 +559,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
}
|
||||
}
|
||||
}
|
||||
cmd.IDChanged({ this, &ActionMap::_CommandIDChangedHandler });
|
||||
_ActionMap.insert_or_assign(cmdID, cmd);
|
||||
}
|
||||
}
|
||||
@@ -573,6 +592,45 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
_changeLog.emplace(KeysKey);
|
||||
}
|
||||
|
||||
void ActionMap::_CommandIDChangedHandler(const Model::Command& senderCmd, const winrt::hstring& oldID)
|
||||
{
|
||||
const auto newID = senderCmd.ID();
|
||||
if (newID != oldID)
|
||||
{
|
||||
if (const auto foundCmd{ _GetActionByID(newID) })
|
||||
{
|
||||
if (foundCmd.ActionAndArgs() != senderCmd.ActionAndArgs())
|
||||
{
|
||||
// we found a command that has the same ID as this one, but that command has different ActionAndArgs
|
||||
// this means that foundCommand's action and/or args have been changed since its ID was generated,
|
||||
// generate a new one for it
|
||||
// Note: this is recursive! Found command's ID being changed lands us back in here to resolve any cascading collisions
|
||||
foundCmd.GenerateID();
|
||||
}
|
||||
}
|
||||
// update _ActionMap with the ID change
|
||||
_ActionMap.erase(oldID);
|
||||
_ActionMap.emplace(newID, senderCmd);
|
||||
|
||||
// update _KeyMap so that all keys that pointed to the old ID now point to the new ID
|
||||
std::unordered_set<KeyChord, KeyChordHash, KeyChordEquality> keysToRemap{};
|
||||
for (const auto& [keys, cmdID] : _KeyMap)
|
||||
{
|
||||
if (cmdID == oldID)
|
||||
{
|
||||
keysToRemap.insert(keys);
|
||||
}
|
||||
}
|
||||
for (const auto& keys : keysToRemap)
|
||||
{
|
||||
_KeyMap.erase(keys);
|
||||
_KeyMap.emplace(keys, newID);
|
||||
}
|
||||
PropagateCommandIDChanged.raise(senderCmd, oldID);
|
||||
}
|
||||
_RefreshKeyBindingCaches();
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Determines whether the given key chord is explicitly unbound
|
||||
// Arguments:
|
||||
@@ -686,6 +744,24 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
IVector<Control::KeyChord> ActionMap::AllKeyBindingsForAction(const winrt::hstring& cmdID)
|
||||
{
|
||||
if (!_ResolvedKeyToActionMapCache)
|
||||
{
|
||||
_RefreshKeyBindingCaches();
|
||||
}
|
||||
|
||||
std::vector<Control::KeyChord> keybindingsList;
|
||||
for (const auto& [key, ID] : _CumulativeKeyToActionMapCache)
|
||||
{
|
||||
if (ID == cmdID)
|
||||
{
|
||||
keybindingsList.emplace_back(key);
|
||||
}
|
||||
}
|
||||
return single_threaded_vector(std::move(keybindingsList));
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Rebinds a key binding to a new key chord
|
||||
// Arguments:
|
||||
@@ -741,6 +817,13 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
}
|
||||
}
|
||||
|
||||
void ActionMap::AddKeyBinding(Control::KeyChord keys, const winrt::hstring& cmdID)
|
||||
{
|
||||
_KeyMap.insert_or_assign(keys, cmdID);
|
||||
_changeLog.emplace(KeysKey);
|
||||
_RefreshKeyBindingCaches();
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Add a new key binding
|
||||
// - If the key chord is already in use, the conflicting command is overwritten.
|
||||
@@ -757,6 +840,12 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
AddAction(*cmd, keys);
|
||||
}
|
||||
|
||||
void ActionMap::DeleteUserCommand(const winrt::hstring& cmdID)
|
||||
{
|
||||
_ActionMap.erase(cmdID);
|
||||
_RefreshKeyBindingCaches();
|
||||
}
|
||||
|
||||
// This is a helper to aid in sorting commands by their `Name`s, alphabetically.
|
||||
static bool _compareSchemeNames(const ColorScheme& lhs, const ColorScheme& rhs)
|
||||
{
|
||||
|
||||
@@ -56,6 +56,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
Windows::Foundation::Collections::IMapView<hstring, Model::Command> NameMap();
|
||||
Windows::Foundation::Collections::IMapView<Control::KeyChord, Model::Command> GlobalHotkeys();
|
||||
Windows::Foundation::Collections::IMapView<Control::KeyChord, Model::Command> KeyBindings();
|
||||
Windows::Foundation::Collections::IVectorView<Model::Command> AllCommands();
|
||||
com_ptr<ActionMap> Copy() const;
|
||||
|
||||
// queries
|
||||
@@ -63,6 +64,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
Model::Command GetActionByID(const winrt::hstring& cmdID) const;
|
||||
bool IsKeyChordExplicitlyUnbound(const Control::KeyChord& keys) const;
|
||||
Control::KeyChord GetKeyBindingForAction(const winrt::hstring& cmdID);
|
||||
Windows::Foundation::Collections::IVector<Control::KeyChord> AllKeyBindingsForAction(const winrt::hstring& cmdID);
|
||||
|
||||
// population
|
||||
void AddAction(const Model::Command& cmd, const Control::KeyChord& keys);
|
||||
@@ -78,7 +80,9 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
// modification
|
||||
bool RebindKeys(const Control::KeyChord& oldKeys, const Control::KeyChord& newKeys);
|
||||
void DeleteKeyBinding(const Control::KeyChord& keys);
|
||||
void AddKeyBinding(Control::KeyChord keys, const winrt::hstring& cmdID);
|
||||
void RegisterKeyBinding(Control::KeyChord keys, Model::ActionAndArgs action);
|
||||
void DeleteUserCommand(const winrt::hstring& cmdID);
|
||||
void AddSendInputAction(winrt::hstring name, winrt::hstring input, const Control::KeyChord keys);
|
||||
|
||||
Windows::Foundation::Collections::IVector<Model::Command> ExpandedCommands();
|
||||
@@ -87,6 +91,8 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
|
||||
winrt::Windows::Foundation::IAsyncOperation<winrt::Windows::Foundation::Collections::IVector<Model::Command>> FilterToSnippets(winrt::hstring currentCommandline, winrt::hstring currentWorkingDirectory);
|
||||
|
||||
til::typed_event<Model::Command, winrt::hstring> PropagateCommandIDChanged;
|
||||
|
||||
private:
|
||||
Model::Command _GetActionByID(const winrt::hstring& actionID) const;
|
||||
std::optional<winrt::hstring> _GetActionIdByKeyChordInternal(const Control::KeyChord& keys) const;
|
||||
@@ -105,6 +111,8 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
|
||||
static std::unordered_map<hstring, Model::Command> _loadLocalSnippets(const std::filesystem::path& currentWorkingDirectory);
|
||||
|
||||
void _CommandIDChangedHandler(const Model::Command& senderCmd, const winrt::hstring& oldID);
|
||||
|
||||
Windows::Foundation::Collections::IMap<hstring, Model::ActionAndArgs> _AvailableActionsCache{ nullptr };
|
||||
Windows::Foundation::Collections::IMap<hstring, Model::Command> _NameMapCache{ nullptr };
|
||||
Windows::Foundation::Collections::IMap<Control::KeyChord, Model::Command> _GlobalHotkeysCache{ nullptr };
|
||||
@@ -136,6 +144,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
// This is effectively a combination of _CumulativeKeyMapCache and _CumulativeActionMapCache and its purpose is so that
|
||||
// we can give the SUI a view of the key chords and the commands they map to
|
||||
Windows::Foundation::Collections::IMap<Control::KeyChord, Model::Command> _ResolvedKeyToActionMapCache{ nullptr };
|
||||
Windows::Foundation::Collections::IVector<Model::Command> _AllCommandsCache{ nullptr };
|
||||
|
||||
til::shared_mutex<std::unordered_map<std::filesystem::path, std::unordered_map<hstring, Model::Command>>> _cwdLocalSnippetsCache{};
|
||||
|
||||
|
||||
@@ -13,23 +13,29 @@ namespace Microsoft.Terminal.Settings.Model
|
||||
Command GetActionByKeyChord(Microsoft.Terminal.Control.KeyChord keys);
|
||||
Command GetActionByID(String cmdID);
|
||||
Microsoft.Terminal.Control.KeyChord GetKeyBindingForAction(String cmdID);
|
||||
IVector<Microsoft.Terminal.Control.KeyChord> AllKeyBindingsForAction(String cmdID);
|
||||
|
||||
Windows.Foundation.Collections.IMapView<String, ActionAndArgs> AvailableActions { get; };
|
||||
|
||||
Windows.Foundation.Collections.IMapView<String, Command> NameMap { get; };
|
||||
Windows.Foundation.Collections.IMapView<Microsoft.Terminal.Control.KeyChord, Command> KeyBindings { get; };
|
||||
Windows.Foundation.Collections.IMapView<Microsoft.Terminal.Control.KeyChord, Command> GlobalHotkeys { get; };
|
||||
Windows.Foundation.Collections.IVectorView<Command> AllCommands { get; };
|
||||
|
||||
IVector<Command> ExpandedCommands { get; };
|
||||
|
||||
Windows.Foundation.IAsyncOperation<IVector<Command> > FilterToSnippets(String CurrentCommandline, String CurrentWorkingDirectory);
|
||||
|
||||
event Windows.Foundation.TypedEventHandler<Command, String> PropagateCommandIDChanged;
|
||||
};
|
||||
|
||||
[default_interface] runtimeclass ActionMap : IActionMapView
|
||||
{
|
||||
void AddAction(Command cmd, Microsoft.Terminal.Control.KeyChord keys);
|
||||
void RebindKeys(Microsoft.Terminal.Control.KeyChord oldKeys, Microsoft.Terminal.Control.KeyChord newKeys);
|
||||
void DeleteKeyBinding(Microsoft.Terminal.Control.KeyChord keys);
|
||||
|
||||
void DeleteUserCommand(String cmdID);
|
||||
void AddKeyBinding(Microsoft.Terminal.Control.KeyChord keys, String cmdID);
|
||||
void RegisterKeyBinding(Microsoft.Terminal.Control.KeyChord keys, ActionAndArgs action);
|
||||
void AddSendInputAction(String name, String input, Microsoft.Terminal.Control.KeyChord keys);
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ std::wstring_view AzureCloudShellGenerator::GetIcon() const noexcept
|
||||
// - <none>
|
||||
// Return Value:
|
||||
// - a vector with the Azure Cloud Shell connection profile, if available.
|
||||
void AzureCloudShellGenerator::GenerateProfiles(std::vector<winrt::com_ptr<implementation::Profile>>& profiles) const
|
||||
void AzureCloudShellGenerator::GenerateProfiles(std::vector<winrt::com_ptr<implementation::Profile>>& profiles)
|
||||
{
|
||||
if (AzureConnection::IsAzureConnectionAvailable())
|
||||
{
|
||||
|
||||
@@ -27,6 +27,6 @@ namespace winrt::Microsoft::Terminal::Settings::Model
|
||||
std::wstring_view GetNamespace() const noexcept override;
|
||||
std::wstring_view GetDisplayName() const noexcept override;
|
||||
std::wstring_view GetIcon() const noexcept override;
|
||||
void GenerateProfiles(std::vector<winrt::com_ptr<implementation::Profile>>& profiles) const override;
|
||||
void GenerateProfiles(std::vector<winrt::com_ptr<implementation::Profile>>& profiles) override;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -4,11 +4,14 @@
|
||||
#include "pch.h"
|
||||
#include "CascadiaSettings.h"
|
||||
#include "CascadiaSettings.g.cpp"
|
||||
#include "ActionArgFactory.g.cpp"
|
||||
#include "MatchProfilesEntry.h"
|
||||
|
||||
#include "DefaultTerminal.h"
|
||||
#include "FileUtils.h"
|
||||
|
||||
#include "AllShortcutActions.h"
|
||||
|
||||
#include <LibraryResources.h>
|
||||
#include <VersionHelpers.h>
|
||||
#include <WtExeUtils.h>
|
||||
@@ -54,6 +57,137 @@ std::string_view Model::implementation::LoadStringResource(int resourceID)
|
||||
return { reinterpret_cast<const char*>(ptr), sz };
|
||||
}
|
||||
|
||||
winrt::hstring ActionArgFactory::GetNameForAction(Model::ShortcutAction action)
|
||||
{
|
||||
// Use a magic static to initialize this map, because we won't be able
|
||||
// to load the resources at _init_, only at runtime.
|
||||
static auto actionNames = []() {
|
||||
return std::unordered_map<ShortcutAction, winrt::hstring>{
|
||||
{ ShortcutAction::AdjustFontSize, RS_(L"AdjustFontSizeCommandKey") },
|
||||
{ ShortcutAction::CloseOtherPanes, RS_(L"CloseOtherPanesCommandKey") },
|
||||
{ ShortcutAction::CloseOtherTabs, RS_(L"CloseOtherTabs") },
|
||||
{ ShortcutAction::ClosePane, RS_(L"ClosePaneCommandKey") },
|
||||
{ ShortcutAction::CloseTab, RS_(L"CloseTab") },
|
||||
{ ShortcutAction::CloseTabsAfter, RS_(L"CloseTabsAfter") },
|
||||
{ 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::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::SendInput, RS_(L"SendInput") },
|
||||
{ ShortcutAction::SetColorScheme, RS_(L"SetColorScheme") },
|
||||
{ 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::ToggleCommandPalette, RS_(L"ToggleCommandPaletteCommandKey") },
|
||||
{ ShortcutAction::Suggestions, RS_(L"Suggestions") },
|
||||
{ ShortcutAction::ToggleFocusMode, RS_(L"ToggleFocusModeCommandKey") },
|
||||
{ ShortcutAction::SetFocusMode, RS_(L"SetFocusMode") },
|
||||
{ ShortcutAction::ToggleFullscreen, RS_(L"ToggleFullscreenCommandKey") },
|
||||
{ ShortcutAction::SetFullScreen, RS_(L"SetFullScreen") },
|
||||
{ ShortcutAction::SetMaximized, RS_(L"SetMaximized") },
|
||||
{ ShortcutAction::TogglePaneZoom, RS_(L"TogglePaneZoomCommandKey") },
|
||||
{ ShortcutAction::ToggleSplitOrientation, RS_(L"ToggleSplitOrientationCommandKey") },
|
||||
{ ShortcutAction::ToggleShaderEffects, RS_(L"ToggleShaderEffectsCommandKey") },
|
||||
{ ShortcutAction::MoveTab, RS_(L"MoveTab") },
|
||||
{ ShortcutAction::BreakIntoDebugger, RS_(L"BreakIntoDebuggerCommandKey") },
|
||||
{ ShortcutAction::FindMatch, RS_(L"FindMatch") },
|
||||
{ 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::GlobalSummon, RS_(L"GlobalSummonCommandKey") },
|
||||
{ ShortcutAction::SearchForText, RS_(L"SearchForText") },
|
||||
{ ShortcutAction::QuakeMode, RS_(L"QuakeModeCommandKey") },
|
||||
{ ShortcutAction::FocusPane, RS_(L"FocusPane") },
|
||||
{ ShortcutAction::OpenSystemMenu, RS_(L"OpenSystemMenuCommandKey") },
|
||||
{ ShortcutAction::ExportBuffer, RS_(L"ExportBuffer") },
|
||||
{ ShortcutAction::ClearBuffer, RS_(L"ClearBuffer") },
|
||||
{ ShortcutAction::MultipleActions, RS_(L"MultipleActions") },
|
||||
{ ShortcutAction::Quit, RS_(L"QuitCommandKey") },
|
||||
{ ShortcutAction::AdjustOpacity, RS_(L"AdjustOpacity") },
|
||||
{ ShortcutAction::RestoreLastClosed, RS_(L"RestoreLastClosedCommandKey") },
|
||||
{ ShortcutAction::SelectCommand, RS_(L"SelectCommand") },
|
||||
{ ShortcutAction::SelectOutput, RS_(L"SelectOutput") },
|
||||
{ ShortcutAction::SelectAll, RS_(L"SelectAllCommandKey") },
|
||||
{ ShortcutAction::MarkMode, RS_(L"MarkModeCommandKey") },
|
||||
{ ShortcutAction::ToggleBlockSelection, RS_(L"ToggleBlockSelectionCommandKey") },
|
||||
{ ShortcutAction::SwitchSelectionEndpoint, RS_(L"SwitchSelectionEndpointCommandKey") },
|
||||
{ ShortcutAction::ColorSelection, RS_(L"ColorSelection") },
|
||||
{ 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") },
|
||||
};
|
||||
}();
|
||||
|
||||
const auto found = actionNames.find(action);
|
||||
return found != actionNames.end() ? found->second : winrt::hstring{};
|
||||
}
|
||||
|
||||
winrt::Windows::Foundation::Collections::IMap<Model::ShortcutAction, winrt::hstring> ActionArgFactory::AvailableShortcutActionsAndNames()
|
||||
{
|
||||
std::unordered_map<ShortcutAction, winrt::hstring> actionNames;
|
||||
#define ON_ALL_ACTIONS(action) actionNames.emplace(ShortcutAction::action, GetNameForAction(ShortcutAction::action));
|
||||
|
||||
ALL_SHORTCUT_ACTIONS
|
||||
|
||||
#undef ON_ALL_ACTIONS
|
||||
return winrt::single_threaded_map(std::move(actionNames));
|
||||
}
|
||||
|
||||
Model::IActionArgs ActionArgFactory::GetEmptyArgsForAction(Model::ShortcutAction shortcutAction)
|
||||
{
|
||||
switch (shortcutAction)
|
||||
{
|
||||
#define ON_ALL_ACTIONS_WITH_ARGS(name) \
|
||||
case Model::ShortcutAction::name: \
|
||||
return winrt::make<name##Args>();
|
||||
|
||||
ALL_SHORTCUT_ACTIONS_WITH_ARGS
|
||||
|
||||
#undef ON_ALL_ACTIONS_WITH_ARGS
|
||||
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
winrt::hstring CascadiaSettings::Hash() const noexcept
|
||||
{
|
||||
return _hash;
|
||||
|
||||
@@ -18,6 +18,7 @@ Author(s):
|
||||
#pragma once
|
||||
|
||||
#include "CascadiaSettings.g.h"
|
||||
#include "ActionArgFactory.g.h"
|
||||
#include "FragmentSettings.g.h"
|
||||
#include "FragmentProfileEntry.g.h"
|
||||
#include "FragmentColorSchemeEntry.g.h"
|
||||
@@ -129,7 +130,8 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
void _appendProfile(winrt::com_ptr<Profile>&& profile, const winrt::guid& guid, ParsedSettings& settings);
|
||||
void _addUserProfileParent(const winrt::com_ptr<implementation::Profile>& profile);
|
||||
bool _addOrMergeUserColorScheme(const winrt::com_ptr<implementation::ColorScheme>& colorScheme);
|
||||
static void _executeGenerator(const IDynamicProfileGenerator& generator, std::vector<winrt::com_ptr<implementation::Profile>>& profilesList);
|
||||
static void _executeGenerator(IDynamicProfileGenerator& generator, std::vector<winrt::com_ptr<implementation::Profile>>& profilesList);
|
||||
void _patchInstallPowerShellProfile(bool isPowerShellInstalled);
|
||||
winrt::com_ptr<implementation::ExtensionPackage> _registerFragment(const winrt::Microsoft::Terminal::Settings::Model::FragmentSettings& fragment, FragmentScope scope);
|
||||
Json::StreamWriterBuilder _getJsonStyledWriter();
|
||||
|
||||
@@ -139,6 +141,15 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
size_t _userProfileCount = 0;
|
||||
};
|
||||
|
||||
struct ActionArgFactory
|
||||
{
|
||||
ActionArgFactory() = default;
|
||||
|
||||
static winrt::hstring GetNameForAction(ShortcutAction action);
|
||||
static Windows::Foundation::Collections::IMap<Model::ShortcutAction, winrt::hstring> AvailableShortcutActionsAndNames();
|
||||
static Model::IActionArgs GetEmptyArgsForAction(Model::ShortcutAction shortcutAction);
|
||||
};
|
||||
|
||||
struct CascadiaSettings : CascadiaSettingsT<CascadiaSettings>
|
||||
{
|
||||
public:
|
||||
@@ -248,14 +259,13 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
public:
|
||||
FragmentProfileEntry(winrt::guid profileGuid, hstring json) :
|
||||
_profileGuid{ profileGuid },
|
||||
_json{ json } {}
|
||||
Json{ json } {}
|
||||
|
||||
winrt::guid ProfileGuid() const noexcept { return _profileGuid; }
|
||||
hstring Json() const noexcept { return _json; }
|
||||
til::property<hstring> Json;
|
||||
|
||||
private:
|
||||
winrt::guid _profileGuid;
|
||||
hstring _json;
|
||||
};
|
||||
|
||||
struct FragmentColorSchemeEntry : FragmentColorSchemeEntryT<FragmentColorSchemeEntry>
|
||||
@@ -278,11 +288,10 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
public:
|
||||
FragmentSettings(hstring source, hstring json, hstring filename) :
|
||||
_source{ source },
|
||||
_json{ json },
|
||||
_Json{ json },
|
||||
_filename{ filename } {}
|
||||
|
||||
hstring Source() const noexcept { return _source; }
|
||||
hstring Json() const noexcept { return _json; }
|
||||
hstring Filename() const noexcept { return _filename; }
|
||||
Windows::Foundation::Collections::IVector<Model::FragmentProfileEntry> ModifiedProfiles() const noexcept { return _modifiedProfiles; }
|
||||
void ModifiedProfiles(const Windows::Foundation::Collections::IVector<Model::FragmentProfileEntry>& modifiedProfiles) noexcept { _modifiedProfiles = modifiedProfiles; }
|
||||
@@ -290,7 +299,9 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
void NewProfiles(const Windows::Foundation::Collections::IVector<Model::FragmentProfileEntry>& newProfiles) noexcept { _newProfiles = newProfiles; }
|
||||
Windows::Foundation::Collections::IVector<Model::FragmentColorSchemeEntry> ColorSchemes() const noexcept { return _colorSchemes; }
|
||||
void ColorSchemes(const Windows::Foundation::Collections::IVector<Model::FragmentColorSchemeEntry>& colorSchemes) noexcept { _colorSchemes = colorSchemes; }
|
||||
WINRT_PROPERTY(hstring, Json);
|
||||
|
||||
public:
|
||||
// views
|
||||
Windows::Foundation::Collections::IVectorView<Model::FragmentProfileEntry> ModifiedProfilesView() const noexcept { return _modifiedProfiles ? _modifiedProfiles.GetView() : nullptr; }
|
||||
Windows::Foundation::Collections::IVectorView<Model::FragmentProfileEntry> NewProfilesView() const noexcept { return _newProfiles ? _newProfiles.GetView() : nullptr; }
|
||||
@@ -298,7 +309,6 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
|
||||
private:
|
||||
hstring _source;
|
||||
hstring _json;
|
||||
hstring _filename;
|
||||
Windows::Foundation::Collections::IVector<Model::FragmentProfileEntry> _modifiedProfiles;
|
||||
Windows::Foundation::Collections::IVector<Model::FragmentProfileEntry> _newProfiles;
|
||||
@@ -309,4 +319,5 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
namespace winrt::Microsoft::Terminal::Settings::Model::factory_implementation
|
||||
{
|
||||
BASIC_FACTORY(CascadiaSettings);
|
||||
BASIC_FACTORY(ActionArgFactory);
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import "GlobalAppSettings.idl";
|
||||
import "Profile.idl";
|
||||
import "TerminalWarnings.idl";
|
||||
import "DefaultTerminal.idl";
|
||||
import "ActionArgs.idl";
|
||||
|
||||
namespace Microsoft.Terminal.Settings.Model
|
||||
{
|
||||
@@ -14,6 +15,13 @@ namespace Microsoft.Terminal.Settings.Model
|
||||
Machine
|
||||
};
|
||||
|
||||
static runtimeclass ActionArgFactory
|
||||
{
|
||||
static String GetNameForAction(Microsoft.Terminal.Settings.Model.ShortcutAction action);
|
||||
static Windows.Foundation.Collections.IMap<Microsoft.Terminal.Settings.Model.ShortcutAction, String> AvailableShortcutActionsAndNames { get; };
|
||||
static IActionArgs GetEmptyArgsForAction(Microsoft.Terminal.Settings.Model.ShortcutAction shortcutAction);
|
||||
}
|
||||
|
||||
[default_interface] runtimeclass CascadiaSettings {
|
||||
static CascadiaSettings LoadDefaults();
|
||||
static CascadiaSettings LoadAll();
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#if TIL_FEATURE_DYNAMICSSHPROFILES_ENABLED
|
||||
#include "SshHostGenerator.h"
|
||||
#endif
|
||||
#include "PowershellInstallationProfileGenerator.h"
|
||||
|
||||
#include "ApplicationState.h"
|
||||
#include "DefaultTerminal.h"
|
||||
@@ -210,28 +211,58 @@ Json::StreamWriterBuilder SettingsLoader::_getJsonStyledWriter()
|
||||
// (meaning profiles specified by the application rather by the user).
|
||||
void SettingsLoader::GenerateProfiles()
|
||||
{
|
||||
auto generateProfiles = [&](const IDynamicProfileGenerator& generator) {
|
||||
auto generateProfiles = [&]<typename T>() {
|
||||
T generator{};
|
||||
if (!_ignoredNamespaces.contains(generator.GetNamespace()))
|
||||
{
|
||||
_executeGenerator(generator, inboxSettings.profiles);
|
||||
}
|
||||
return generator;
|
||||
};
|
||||
|
||||
bool isPowerShellInstalled;
|
||||
{
|
||||
auto powerShellGenerator = generateProfiles.template operator()<PowershellCoreProfileGenerator>();
|
||||
isPowerShellInstalled = !powerShellGenerator.GetPowerShellInstances().empty();
|
||||
}
|
||||
|
||||
if (Feature_PowerShellInstallerProfileGenerator::IsEnabled())
|
||||
{
|
||||
if (isPowerShellInstalled)
|
||||
{
|
||||
// PowerShell is installed, mark the installer profile for deletion (if found)
|
||||
const winrt::guid profileGuid{ L"{965a10f2-b0f2-55dc-a3c2-2ddbf639bf89}" };
|
||||
for (const auto& profile : userSettings.profiles)
|
||||
{
|
||||
if (profile->Guid() == profileGuid)
|
||||
{
|
||||
profile->Deleted(true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// PowerShell isn't installed --> generate the installer stub profile
|
||||
generateProfiles.template operator()<PowershellInstallationProfileGenerator>();
|
||||
}
|
||||
}
|
||||
|
||||
// Generate profiles for each generator and add them to the inbox settings.
|
||||
// Be sure to update the same list below.
|
||||
generateProfiles(PowershellCoreProfileGenerator{});
|
||||
generateProfiles(WslDistroGenerator{});
|
||||
generateProfiles(AzureCloudShellGenerator{});
|
||||
generateProfiles(VisualStudioGenerator{});
|
||||
generateProfiles.template operator()<WslDistroGenerator>();
|
||||
generateProfiles.template operator()<AzureCloudShellGenerator>();
|
||||
generateProfiles.template operator()<VisualStudioGenerator>();
|
||||
#if TIL_FEATURE_DYNAMICSSHPROFILES_ENABLED
|
||||
generateProfiles(SshHostGenerator{});
|
||||
generateProfiles.template operator()<SshHostGenerator>();
|
||||
#endif
|
||||
}
|
||||
|
||||
// Generate ExtensionPackage objects from the profile generators.
|
||||
void SettingsLoader::GenerateExtensionPackagesFromProfileGenerators()
|
||||
{
|
||||
auto generateExtensionPackages = [&](const IDynamicProfileGenerator& generator) {
|
||||
auto generateExtensionPackages = [&]<typename T>() {
|
||||
T generator{};
|
||||
std::vector<winrt::com_ptr<implementation::Profile>> profilesList;
|
||||
_executeGenerator(generator, profilesList);
|
||||
|
||||
@@ -256,19 +287,69 @@ void SettingsLoader::GenerateExtensionPackagesFromProfileGenerators()
|
||||
auto extPkg = _registerFragment(std::move(*generatorExtension), FragmentScope::Machine);
|
||||
extPkg->DisplayName(hstring{ generator.GetDisplayName() });
|
||||
extPkg->Icon(hstring{ generator.GetIcon() });
|
||||
return generator;
|
||||
};
|
||||
|
||||
bool isPowerShellInstalled;
|
||||
{
|
||||
auto powerShellGenerator = generateExtensionPackages.template operator()<PowershellCoreProfileGenerator>();
|
||||
isPowerShellInstalled = !powerShellGenerator.GetPowerShellInstances().empty();
|
||||
}
|
||||
if (Feature_PowerShellInstallerProfileGenerator::IsEnabled())
|
||||
{
|
||||
generateExtensionPackages.template operator()<PowershellInstallationProfileGenerator>();
|
||||
_patchInstallPowerShellProfile(isPowerShellInstalled);
|
||||
}
|
||||
|
||||
// Generate extension package objects for each generator.
|
||||
// Be sure to update the same list above.
|
||||
generateExtensionPackages(PowershellCoreProfileGenerator{});
|
||||
generateExtensionPackages(WslDistroGenerator{});
|
||||
generateExtensionPackages(AzureCloudShellGenerator{});
|
||||
generateExtensionPackages(VisualStudioGenerator{});
|
||||
generateExtensionPackages.template operator()<WslDistroGenerator>();
|
||||
generateExtensionPackages.template operator()<AzureCloudShellGenerator>();
|
||||
generateExtensionPackages.template operator()<VisualStudioGenerator>();
|
||||
#if TIL_FEATURE_DYNAMICSSHPROFILES_ENABLED
|
||||
generateExtensionPackages(SshHostGenerator{});
|
||||
generateExtensionPackages.template operator()<SshHostGenerator>();
|
||||
#endif
|
||||
}
|
||||
|
||||
// Retrieve the "Install Latest PowerShell" profile and add a comment to the JSON to indicate it's conditionally applied.
|
||||
// If PowerShell is installed, delete the profile from the extension package.
|
||||
void SettingsLoader::_patchInstallPowerShellProfile(bool isPowerShellInstalled)
|
||||
{
|
||||
const hstring pwshInstallerNamespace{ PowershellInstallationProfileGenerator::Namespace };
|
||||
if (extensionPackageMap.contains(pwshInstallerNamespace))
|
||||
{
|
||||
if (const auto& fragExtList = extensionPackageMap[pwshInstallerNamespace]->Fragments(); fragExtList.Size() > 0)
|
||||
{
|
||||
auto fragExt = get_self<FragmentSettings>(fragExtList.GetAt(0));
|
||||
|
||||
// We want the comment to be the first thing in the object,
|
||||
// "closeOnExit" is the first property, so target that.
|
||||
auto fragExtJson = _parseJSON(til::u16u8(fragExt->Json()));
|
||||
fragExtJson[JsonKey(ProfilesKey)][0]["closeOnExit"].setComment(til::u16u8(fmt::format(FMT_COMPILE(L"// {}"), RS_(L"PowerShellInstallationProfileJsonComment"))), Json::CommentPlacement::commentBefore);
|
||||
fragExt->Json(hstring{ til::u8u16(Json::writeString(_getJsonStyledWriter(), fragExtJson)) });
|
||||
|
||||
if (const auto& profileEntryList = fragExt->NewProfiles(); profileEntryList.Size() > 0)
|
||||
{
|
||||
if (isPowerShellInstalled)
|
||||
{
|
||||
// PowerShell is installed, so the installer profile was marked for deletion in GenerateProfiles().
|
||||
// Remove the profile object from the fragment so it doesn't show up in the settings UI.
|
||||
profileEntryList.RemoveAt(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
// We want the comment to be the first thing in the object,
|
||||
// "closeOnExit" is the first property, so target that.
|
||||
auto profileEntry = get_self<FragmentProfileEntry>(profileEntryList.GetAt(0));
|
||||
auto profileJson = _parseJSON(til::u16u8(profileEntry->Json()));
|
||||
profileJson["closeOnExit"].setComment(til::u16u8(fmt::format(FMT_COMPILE(L"// {}"), RS_(L"PowerShellInstallationProfileJsonComment"))), Json::CommentPlacement::commentBefore);
|
||||
profileEntry->Json(hstring{ til::u8u16(Json::writeString(_getJsonStyledWriter(), profileJson)) });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// A new settings.json gets a special treatment:
|
||||
// 1. The default profile is a PowerShell 7+ one, if one was generated,
|
||||
// and falls back to the standard PowerShell 5 profile otherwise.
|
||||
@@ -1095,7 +1176,7 @@ bool SettingsLoader::_addOrMergeUserColorScheme(const winrt::com_ptr<implementat
|
||||
|
||||
// As the name implies it executes a generator.
|
||||
// Generated profiles are added to .inboxSettings. Used by GenerateProfiles().
|
||||
void SettingsLoader::_executeGenerator(const IDynamicProfileGenerator& generator, std::vector<winrt::com_ptr<implementation::Profile>>& profilesList)
|
||||
void SettingsLoader::_executeGenerator(IDynamicProfileGenerator& generator, std::vector<winrt::com_ptr<implementation::Profile>>& profilesList)
|
||||
{
|
||||
const auto generatorNamespace = generator.GetNamespace();
|
||||
const auto previousSize = profilesList.size();
|
||||
@@ -1679,7 +1760,11 @@ void CascadiaSettings::_resolveNewTabMenuProfiles() const
|
||||
auto activeProfileCount = gsl::narrow_cast<int>(_activeProfiles.Size());
|
||||
for (auto profileIndex = 0; profileIndex < activeProfileCount; profileIndex++)
|
||||
{
|
||||
remainingProfilesMap.emplace(profileIndex, _activeProfiles.GetAt(profileIndex));
|
||||
const auto& profile = _activeProfiles.GetAt(profileIndex);
|
||||
if (!profile.Deleted())
|
||||
{
|
||||
remainingProfilesMap.emplace(profileIndex, _activeProfiles.GetAt(profileIndex));
|
||||
}
|
||||
}
|
||||
|
||||
// We keep track of the "remaining profiles" - those that have not yet been resolved
|
||||
|
||||
@@ -28,6 +28,21 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
{
|
||||
Command::Command() = default;
|
||||
|
||||
Model::Command Command::NewUserCommand()
|
||||
{
|
||||
auto newCmd{ winrt::make_self<Command>() };
|
||||
newCmd->_Origin = OriginTag::User;
|
||||
return *newCmd;
|
||||
}
|
||||
|
||||
Model::Command Command::CopyAsUserCommand(const Model::Command& originalCmd)
|
||||
{
|
||||
auto command{ winrt::get_self<Command>(originalCmd) };
|
||||
auto copy{ command->Copy() };
|
||||
copy->_Origin = OriginTag::User;
|
||||
return *copy;
|
||||
}
|
||||
|
||||
com_ptr<Command> Command::Copy() const
|
||||
{
|
||||
auto command{ winrt::make_self<Command>() };
|
||||
@@ -113,6 +128,13 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
return hstring{ _ID };
|
||||
}
|
||||
|
||||
void Command::ID(const hstring& ID) noexcept
|
||||
{
|
||||
const auto oldID = _ID;
|
||||
_ID = ID;
|
||||
IDChanged.raise(*this, oldID);
|
||||
}
|
||||
|
||||
void Command::GenerateID()
|
||||
{
|
||||
if (_ActionAndArgs)
|
||||
@@ -120,8 +142,8 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
auto actionAndArgsImpl{ winrt::get_self<implementation::ActionAndArgs>(_ActionAndArgs) };
|
||||
if (const auto generatedID = actionAndArgsImpl->GenerateID(); !generatedID.empty())
|
||||
{
|
||||
_ID = generatedID;
|
||||
_IDWasGenerated = true;
|
||||
ID(generatedID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,6 +45,8 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
struct Command : CommandT<Command>
|
||||
{
|
||||
Command();
|
||||
static Model::Command NewUserCommand();
|
||||
static Model::Command CopyAsUserCommand(const Model::Command& originalCmd);
|
||||
com_ptr<Command> Copy() const;
|
||||
|
||||
static winrt::com_ptr<Command> FromJson(const Json::Value& json,
|
||||
@@ -73,6 +75,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
void Name(const hstring& name);
|
||||
|
||||
hstring ID() const noexcept;
|
||||
void ID(const hstring& ID) noexcept;
|
||||
void GenerateID();
|
||||
bool IDWasGenerated();
|
||||
|
||||
@@ -85,11 +88,14 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
bool directories,
|
||||
hstring iconPath);
|
||||
|
||||
WINRT_PROPERTY(Model::ActionAndArgs, ActionAndArgs, Model::ActionAndArgs{});
|
||||
WINRT_PROPERTY(ExpandCommandType, IterateOn, ExpandCommandType::None);
|
||||
WINRT_PROPERTY(Model::ActionAndArgs, ActionAndArgs);
|
||||
WINRT_PROPERTY(OriginTag, Origin);
|
||||
WINRT_PROPERTY(winrt::hstring, Description, L"");
|
||||
|
||||
public:
|
||||
til::typed_event<Model::Command, winrt::hstring> IDChanged;
|
||||
|
||||
private:
|
||||
Json::Value _originalJson;
|
||||
Windows::Foundation::Collections::IMap<winrt::hstring, Model::Command> _subcommands{ nullptr };
|
||||
|
||||
@@ -35,13 +35,17 @@ namespace Microsoft.Terminal.Settings.Model
|
||||
[default_interface] runtimeclass Command : ISettingsModelObject
|
||||
{
|
||||
Command();
|
||||
static Command NewUserCommand();
|
||||
static Command CopyAsUserCommand(Command originalCmd);
|
||||
|
||||
String Name { get; };
|
||||
String ID { get; };
|
||||
String Name;
|
||||
Boolean HasName();
|
||||
String ID;
|
||||
void GenerateID();
|
||||
|
||||
String Description { get; };
|
||||
|
||||
ActionAndArgs ActionAndArgs { get; };
|
||||
ActionAndArgs ActionAndArgs;
|
||||
|
||||
String IconPath;
|
||||
|
||||
@@ -51,5 +55,6 @@ namespace Microsoft.Terminal.Settings.Model
|
||||
static IVector<Command> ParsePowerShellMenuComplete(String json, Int32 replaceLength);
|
||||
static IVector<Command> HistoryToCommands(IVector<String> commandHistory, String commandline, Boolean directories, String iconPath);
|
||||
|
||||
event Windows.Foundation.TypedEventHandler<Command, String> IDChanged;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,6 +53,22 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
DEFINE_ENUM_MAP(Microsoft::Terminal::Core::AdjustTextMode, AdjustIndistinguishableColors);
|
||||
DEFINE_ENUM_MAP(Microsoft::Terminal::Control::PathTranslationStyle, PathTranslationStyle);
|
||||
|
||||
// Actions
|
||||
DEFINE_ENUM_MAP(Microsoft::Terminal::Settings::Model::ResizeDirection, ResizeDirection);
|
||||
DEFINE_ENUM_MAP(Microsoft::Terminal::Settings::Model::FocusDirection, FocusDirection);
|
||||
DEFINE_ENUM_MAP(Microsoft::Terminal::Settings::Model::SplitDirection, SplitDirection);
|
||||
DEFINE_ENUM_MAP(Microsoft::Terminal::Settings::Model::SplitType, SplitType);
|
||||
DEFINE_ENUM_MAP(Microsoft::Terminal::Settings::Model::SettingsTarget, SettingsTarget);
|
||||
DEFINE_ENUM_MAP(Microsoft::Terminal::Settings::Model::MoveTabDirection, MoveTabDirection);
|
||||
DEFINE_ENUM_MAP(Microsoft::Terminal::Control::ScrollToMarkDirection, ScrollToMarkDirection);
|
||||
DEFINE_ENUM_MAP(Microsoft::Terminal::Settings::Model::CommandPaletteLaunchMode, CommandPaletteLaunchMode);
|
||||
DEFINE_ENUM_MAP(Microsoft::Terminal::Settings::Model::SuggestionsSource, SuggestionsSource);
|
||||
DEFINE_ENUM_MAP(Microsoft::Terminal::Settings::Model::FindMatchDirection, FindMatchDirection);
|
||||
DEFINE_ENUM_MAP(Microsoft::Terminal::Settings::Model::DesktopBehavior, DesktopBehavior);
|
||||
DEFINE_ENUM_MAP(Microsoft::Terminal::Settings::Model::MonitorBehavior, MonitorBehavior);
|
||||
DEFINE_ENUM_MAP(Microsoft::Terminal::Control::ClearBufferType, ClearBufferType);
|
||||
DEFINE_ENUM_MAP(Microsoft::Terminal::Settings::Model::SelectOutputDirection, SelectOutputDirection);
|
||||
|
||||
// FontWeight is special because the JsonUtils::ConversionTrait for it
|
||||
// creates a FontWeight object, but we need to use the uint16_t value.
|
||||
winrt::Windows::Foundation::Collections::IMap<winrt::hstring, uint16_t> EnumMappings::FontWeight()
|
||||
|
||||
@@ -49,6 +49,22 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
static winrt::Windows::Foundation::Collections::IMap<winrt::hstring, winrt::Microsoft::Terminal::Settings::Model::IntenseStyle> IntenseTextStyle();
|
||||
static winrt::Windows::Foundation::Collections::IMap<winrt::hstring, winrt::Microsoft::Terminal::Core::AdjustTextMode> AdjustIndistinguishableColors();
|
||||
static winrt::Windows::Foundation::Collections::IMap<winrt::hstring, winrt::Microsoft::Terminal::Control::PathTranslationStyle> PathTranslationStyle();
|
||||
|
||||
// Actions
|
||||
static winrt::Windows::Foundation::Collections::IMap<winrt::hstring, winrt::Microsoft::Terminal::Settings::Model::ResizeDirection> ResizeDirection();
|
||||
static winrt::Windows::Foundation::Collections::IMap<winrt::hstring, winrt::Microsoft::Terminal::Settings::Model::FocusDirection> FocusDirection();
|
||||
static winrt::Windows::Foundation::Collections::IMap<winrt::hstring, winrt::Microsoft::Terminal::Settings::Model::SplitDirection> SplitDirection();
|
||||
static winrt::Windows::Foundation::Collections::IMap<winrt::hstring, winrt::Microsoft::Terminal::Settings::Model::SplitType> SplitType();
|
||||
static winrt::Windows::Foundation::Collections::IMap<winrt::hstring, winrt::Microsoft::Terminal::Settings::Model::SettingsTarget> SettingsTarget();
|
||||
static winrt::Windows::Foundation::Collections::IMap<winrt::hstring, winrt::Microsoft::Terminal::Settings::Model::MoveTabDirection> MoveTabDirection();
|
||||
static winrt::Windows::Foundation::Collections::IMap<winrt::hstring, winrt::Microsoft::Terminal::Control::ScrollToMarkDirection> ScrollToMarkDirection();
|
||||
static winrt::Windows::Foundation::Collections::IMap<winrt::hstring, winrt::Microsoft::Terminal::Settings::Model::CommandPaletteLaunchMode> CommandPaletteLaunchMode();
|
||||
static winrt::Windows::Foundation::Collections::IMap<winrt::hstring, winrt::Microsoft::Terminal::Settings::Model::SuggestionsSource> SuggestionsSource();
|
||||
static winrt::Windows::Foundation::Collections::IMap<winrt::hstring, winrt::Microsoft::Terminal::Settings::Model::FindMatchDirection> FindMatchDirection();
|
||||
static winrt::Windows::Foundation::Collections::IMap<winrt::hstring, winrt::Microsoft::Terminal::Settings::Model::DesktopBehavior> DesktopBehavior();
|
||||
static winrt::Windows::Foundation::Collections::IMap<winrt::hstring, winrt::Microsoft::Terminal::Settings::Model::MonitorBehavior> MonitorBehavior();
|
||||
static winrt::Windows::Foundation::Collections::IMap<winrt::hstring, winrt::Microsoft::Terminal::Control::ClearBufferType> ClearBufferType();
|
||||
static winrt::Windows::Foundation::Collections::IMap<winrt::hstring, winrt::Microsoft::Terminal::Settings::Model::SelectOutputDirection> SelectOutputDirection();
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -31,5 +31,21 @@ namespace Microsoft.Terminal.Settings.Model
|
||||
static Windows.Foundation.Collections.IMap<String, UInt16> FontWeight { get; };
|
||||
static Windows.Foundation.Collections.IMap<String, Microsoft.Terminal.Settings.Model.IntenseStyle> IntenseTextStyle { get; };
|
||||
static Windows.Foundation.Collections.IMap<String, Microsoft.Terminal.Control.PathTranslationStyle> PathTranslationStyle { get; };
|
||||
|
||||
// Actions
|
||||
static Windows.Foundation.Collections.IMap<String, Microsoft.Terminal.Settings.Model.ResizeDirection> ResizeDirection { get; };
|
||||
static Windows.Foundation.Collections.IMap<String, Microsoft.Terminal.Settings.Model.FocusDirection> FocusDirection { get; };
|
||||
static Windows.Foundation.Collections.IMap<String, Microsoft.Terminal.Settings.Model.SplitDirection> SplitDirection { get; };
|
||||
static Windows.Foundation.Collections.IMap<String, Microsoft.Terminal.Settings.Model.SplitType> SplitType { get; };
|
||||
static Windows.Foundation.Collections.IMap<String, Microsoft.Terminal.Settings.Model.SettingsTarget> SettingsTarget { get; };
|
||||
static Windows.Foundation.Collections.IMap<String, Microsoft.Terminal.Settings.Model.MoveTabDirection> MoveTabDirection { get; };
|
||||
static Windows.Foundation.Collections.IMap<String, Microsoft.Terminal.Control.ScrollToMarkDirection> ScrollToMarkDirection { get; };
|
||||
static Windows.Foundation.Collections.IMap<String, Microsoft.Terminal.Settings.Model.CommandPaletteLaunchMode> CommandPaletteLaunchMode { get; };
|
||||
static Windows.Foundation.Collections.IMap<String, Microsoft.Terminal.Settings.Model.SuggestionsSource> SuggestionsSource { get; };
|
||||
static Windows.Foundation.Collections.IMap<String, Microsoft.Terminal.Settings.Model.FindMatchDirection> FindMatchDirection { get; };
|
||||
static Windows.Foundation.Collections.IMap<String, Microsoft.Terminal.Settings.Model.DesktopBehavior> DesktopBehavior { get; };
|
||||
static Windows.Foundation.Collections.IMap<String, Microsoft.Terminal.Settings.Model.MonitorBehavior> MonitorBehavior { get; };
|
||||
static Windows.Foundation.Collections.IMap<String, Microsoft.Terminal.Control.ClearBufferType> ClearBufferType { get; };
|
||||
static Windows.Foundation.Collections.IMap<String, Microsoft.Terminal.Settings.Model.SelectOutputDirection> SelectOutputDirection { get; };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,6 +61,7 @@ winrt::com_ptr<GlobalAppSettings> GlobalAppSettings::Copy() const
|
||||
|
||||
globals->_defaultProfile = _defaultProfile;
|
||||
globals->_actionMap = _actionMap->Copy();
|
||||
globals->_actionMap->PropagateCommandIDChanged({ globals.get(), &GlobalAppSettings::_CommandIDChangedHandler });
|
||||
globals->_keybindingsWarnings = _keybindingsWarnings;
|
||||
|
||||
#define GLOBAL_SETTINGS_COPY(type, name, jsonKey, ...) \
|
||||
@@ -143,6 +144,7 @@ winrt::com_ptr<GlobalAppSettings> GlobalAppSettings::FromJson(const Json::Value&
|
||||
{
|
||||
auto result = winrt::make_self<GlobalAppSettings>();
|
||||
result->LayerJson(json, origin);
|
||||
result->_actionMap->PropagateCommandIDChanged({ result.get(), &GlobalAppSettings::_CommandIDChangedHandler });
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -438,6 +440,44 @@ void GlobalAppSettings::_logSettingSet(const std::string_view& setting)
|
||||
}
|
||||
}
|
||||
|
||||
void GlobalAppSettings::_CommandIDChangedHandler(const Model::Command& senderCmd, const winrt::hstring& oldID)
|
||||
{
|
||||
if (_NewTabMenu)
|
||||
{
|
||||
const auto newID = senderCmd.ID();
|
||||
|
||||
// Recursive lambda function to look through all the new tab menu entries and update IDs accordingly
|
||||
std::function<void(const Model::NewTabMenuEntry&)> recursiveEntryIdUpdate;
|
||||
recursiveEntryIdUpdate = [&](const Model::NewTabMenuEntry& entry) {
|
||||
if (entry.Type() == NewTabMenuEntryType::Action)
|
||||
{
|
||||
if (const auto actionEntry{ entry.try_as<ActionEntry>() })
|
||||
{
|
||||
if (actionEntry.ActionId() == oldID)
|
||||
{
|
||||
actionEntry.ActionId(newID);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (entry.Type() == NewTabMenuEntryType::Folder)
|
||||
{
|
||||
if (const auto folderEntry{ entry.try_as<FolderEntry>() })
|
||||
{
|
||||
for (const auto& nestedEntry : folderEntry.RawEntries())
|
||||
{
|
||||
recursiveEntryIdUpdate(nestedEntry);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
for (const auto& entry : *_NewTabMenu)
|
||||
{
|
||||
recursiveEntryIdUpdate(entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GlobalAppSettings::_logSettingIfSet(const std::string_view& setting, const bool isSet)
|
||||
{
|
||||
if (isSet)
|
||||
|
||||
@@ -100,6 +100,8 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
Windows::Foundation::Collections::IMap<winrt::hstring, Model::ColorScheme> _colorSchemes{ winrt::single_threaded_map<winrt::hstring, Model::ColorScheme>() };
|
||||
Windows::Foundation::Collections::IMap<winrt::hstring, Model::Theme> _themes{ winrt::single_threaded_map<winrt::hstring, Model::Theme>() };
|
||||
|
||||
void _CommandIDChangedHandler(const Model::Command& senderCmd, const winrt::hstring& oldID);
|
||||
|
||||
void _logSettingSet(const std::string_view& setting);
|
||||
void _logSettingIfSet(const std::string_view& setting, const bool isSet);
|
||||
};
|
||||
|
||||
@@ -32,6 +32,6 @@ namespace winrt::Microsoft::Terminal::Settings::Model
|
||||
virtual std::wstring_view GetNamespace() const noexcept = 0;
|
||||
virtual std::wstring_view GetDisplayName() const noexcept = 0;
|
||||
virtual std::wstring_view GetIcon() const noexcept = 0;
|
||||
virtual void GenerateProfiles(std::vector<winrt::com_ptr<implementation::Profile>>& profiles) const = 0;
|
||||
virtual void GenerateProfiles(std::vector<winrt::com_ptr<implementation::Profile>>& profiles) = 0;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -147,7 +147,8 @@ Author(s):
|
||||
X(winrt::Microsoft::Terminal::Settings::Model::WindowTheme, Window, "window", nullptr) \
|
||||
X(winrt::Microsoft::Terminal::Settings::Model::SettingsTheme, Settings, "settings", nullptr) \
|
||||
X(winrt::Microsoft::Terminal::Settings::Model::TabRowTheme, TabRow, "tabRow", nullptr) \
|
||||
X(winrt::Microsoft::Terminal::Settings::Model::TabTheme, Tab, "tab", nullptr)
|
||||
X(winrt::Microsoft::Terminal::Settings::Model::TabTheme, Tab, "tab", nullptr) \
|
||||
X(winrt::Microsoft::Terminal::Settings::Model::PaneTheme, Pane, "pane", nullptr)
|
||||
|
||||
#define MTSM_THEME_WINDOW_SETTINGS(X) \
|
||||
X(winrt::Windows::UI::Xaml::ElementTheme, RequestedTheme, "applicationTheme", winrt::Windows::UI::Xaml::ElementTheme::Default) \
|
||||
@@ -163,6 +164,11 @@ Author(s):
|
||||
X(winrt::Microsoft::Terminal::Settings::Model::ThemeColor, Background, "background", nullptr) \
|
||||
X(winrt::Microsoft::Terminal::Settings::Model::ThemeColor, UnfocusedBackground, "unfocusedBackground", nullptr)
|
||||
|
||||
#define MTSM_THEME_PANE_SETTINGS(X) \
|
||||
X(winrt::Microsoft::Terminal::Settings::Model::ThemeColor, ActiveBorderColor, "activeBorderColor", nullptr) \
|
||||
X(winrt::Microsoft::Terminal::Settings::Model::ThemeColor, InactiveBorderColor, "inactiveBorderColor", nullptr) \
|
||||
X(winrt::Microsoft::Terminal::Settings::Model::ThemeColor, BroadcastBorderColor, "broadcastBorderColor", nullptr)
|
||||
|
||||
#define MTSM_THEME_TAB_SETTINGS(X) \
|
||||
X(winrt::Microsoft::Terminal::Settings::Model::ThemeColor, Background, "background", nullptr) \
|
||||
X(winrt::Microsoft::Terminal::Settings::Model::ThemeColor, UnfocusedBackground, "unfocusedBackground", nullptr) \
|
||||
|
||||
@@ -90,6 +90,7 @@
|
||||
<DependentUpon>KeyChordSerialization.idl</DependentUpon>
|
||||
</ClInclude>
|
||||
<ClInclude Include="PowershellCoreProfileGenerator.h" />
|
||||
<ClInclude Include="PowershellInstallationProfileGenerator.h" />
|
||||
<ClInclude Include="Profile.h">
|
||||
<DependentUpon>Profile.idl</DependentUpon>
|
||||
</ClInclude>
|
||||
@@ -167,6 +168,7 @@
|
||||
<DependentUpon>KeyChordSerialization.idl</DependentUpon>
|
||||
</ClCompile>
|
||||
<ClCompile Include="PowershellCoreProfileGenerator.cpp" />
|
||||
<ClCompile Include="PowershellInstallationProfileGenerator.cpp" />
|
||||
<ClCompile Include="Profile.cpp">
|
||||
<DependentUpon>Profile.idl</DependentUpon>
|
||||
</ClCompile>
|
||||
|
||||
@@ -15,6 +15,9 @@
|
||||
<ClCompile Include="PowershellCoreProfileGenerator.cpp">
|
||||
<Filter>profileGeneration</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="PowershellInstallationProfileGenerator.cpp">
|
||||
<Filter>profileGeneration</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="WslDistroGenerator.cpp">
|
||||
<Filter>profileGeneration</Filter>
|
||||
</ClCompile>
|
||||
@@ -57,6 +60,9 @@
|
||||
<ClInclude Include="PowershellCoreProfileGenerator.h">
|
||||
<Filter>profileGeneration</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="PowershellInstallationProfileGenerator.h">
|
||||
<Filter>profileGeneration</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="WslDistroGenerator.h">
|
||||
<Filter>profileGeneration</Filter>
|
||||
</ClInclude>
|
||||
|
||||
@@ -25,336 +25,301 @@ static constexpr std::wstring_view POWERSHELL_PREVIEW_ICON{ L"ms-appx:///Profile
|
||||
static constexpr std::wstring_view GENERATOR_POWERSHELL_ICON{ L"ms-appx:///ProfileGeneratorIcons/PowerShell.png" };
|
||||
static constexpr std::wstring_view POWERSHELL_PREFERRED_PROFILE_NAME{ L"PowerShell" };
|
||||
|
||||
namespace
|
||||
{
|
||||
enum PowerShellFlags
|
||||
{
|
||||
None = 0,
|
||||
|
||||
// These flags are used as a sort key, so they encode some native ordering.
|
||||
// They are ordered such that the "most important" flags have the largest
|
||||
// impact on the sort space. For example, since we want Preview to be very polar
|
||||
// we give it the highest flag value.
|
||||
// The "ideal" powershell instance has 0 flags (stable, native, Program Files location)
|
||||
//
|
||||
// With this ordering, the sort space ends up being (for PowerShell 6)
|
||||
// (numerically greater values are on the left; this is flipped in the final sort)
|
||||
//
|
||||
// <-- Less Valued .................................... More Valued -->
|
||||
// | All instances of PS 6 | All PS7 |
|
||||
// | Preview | Stable | ~~~ |
|
||||
// | Non-Native | Native | Non-Native | Native | ~~~ |
|
||||
// | Trd | Pack | Trd | Pack | Trd | Pack | Trd | Pack | ~~~ |
|
||||
// (where Pack is a stand-in for store, scoop, dotnet, though they have their own orders,
|
||||
// and Trd is a stand-in for "Traditional" (Program Files))
|
||||
//
|
||||
// In short, flags with larger magnitudes are pushed further down (therefore valued less)
|
||||
|
||||
// distribution method (choose one)
|
||||
Store = 1 << 0, // distributed via the store
|
||||
Scoop = 1 << 1, // installed via Scoop
|
||||
Dotnet = 1 << 2, // installed as a dotnet global tool
|
||||
Traditional = 1 << 3, // installed in traditional Program Files locations
|
||||
|
||||
// native architecture (choose one)
|
||||
WOWARM = 1 << 4, // non-native (Windows-on-Windows, ARM variety)
|
||||
WOWx86 = 1 << 5, // non-native (Windows-on-Windows, x86 variety)
|
||||
|
||||
// build type (choose one)
|
||||
Preview = 1 << 6, // preview version
|
||||
};
|
||||
DEFINE_ENUM_FLAG_OPERATORS(PowerShellFlags);
|
||||
|
||||
struct PowerShellInstance
|
||||
{
|
||||
int majorVersion; // 0 = we don't know, sort last.
|
||||
PowerShellFlags flags;
|
||||
std::filesystem::path executablePath;
|
||||
|
||||
constexpr bool operator<(const PowerShellInstance& second) const
|
||||
{
|
||||
if (majorVersion != second.majorVersion)
|
||||
{
|
||||
return majorVersion < second.majorVersion;
|
||||
}
|
||||
if (flags != second.flags)
|
||||
{
|
||||
return flags > second.flags; // flags are inverted because "0" is ideal; see above
|
||||
}
|
||||
return executablePath < second.executablePath; // fall back to path sorting
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Generates a name, based on flags, for a powershell instance.
|
||||
// Return value:
|
||||
// - the name
|
||||
std::wstring Name() const
|
||||
{
|
||||
std::wstringstream namestream;
|
||||
namestream << L"PowerShell";
|
||||
|
||||
if (WI_IsFlagSet(flags, PowerShellFlags::Store))
|
||||
{
|
||||
if (WI_IsFlagSet(flags, PowerShellFlags::Preview))
|
||||
{
|
||||
namestream << L" Preview";
|
||||
}
|
||||
namestream << L" (msix)";
|
||||
}
|
||||
else if (WI_IsFlagSet(flags, PowerShellFlags::Dotnet))
|
||||
{
|
||||
namestream << L" (dotnet global)";
|
||||
}
|
||||
else if (WI_IsFlagSet(flags, PowerShellFlags::Scoop))
|
||||
{
|
||||
namestream << L" (scoop)";
|
||||
}
|
||||
else
|
||||
{
|
||||
if (majorVersion < 7)
|
||||
{
|
||||
namestream << L" Core";
|
||||
}
|
||||
if (majorVersion != 0)
|
||||
{
|
||||
namestream << L" " << majorVersion;
|
||||
}
|
||||
if (WI_IsFlagSet(flags, PowerShellFlags::Preview))
|
||||
{
|
||||
namestream << L" Preview";
|
||||
}
|
||||
if (WI_IsFlagSet(flags, PowerShellFlags::WOWx86))
|
||||
{
|
||||
namestream << L" (x86)";
|
||||
}
|
||||
if (WI_IsFlagSet(flags, PowerShellFlags::WOWARM))
|
||||
{
|
||||
namestream << L" (ARM)";
|
||||
}
|
||||
}
|
||||
return namestream.str();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
using namespace ::Microsoft::Terminal::Settings::Model;
|
||||
using namespace winrt::Microsoft::Terminal::Settings::Model;
|
||||
|
||||
// Function Description:
|
||||
// - Finds all powershell instances with the traditional layout under a directory.
|
||||
// - The "traditional" directory layout requires that pwsh.exe exist in a versioned directory, as in
|
||||
// ROOT\6\pwsh.exe
|
||||
// Arguments:
|
||||
// - directory: the directory under which to search
|
||||
// - flags: flags to apply to all found instances
|
||||
// - out: the list into which to accumulate these instances.
|
||||
static void _accumulateTraditionalLayoutPowerShellInstancesInDirectory(std::wstring_view directory, PowerShellFlags flags, std::vector<PowerShellInstance>& out)
|
||||
namespace winrt::Microsoft::Terminal::Settings::Model
|
||||
{
|
||||
const std::filesystem::path root{ wil::ExpandEnvironmentStringsW<std::wstring>(directory.data()) };
|
||||
if (std::filesystem::exists(root))
|
||||
DEFINE_ENUM_FLAG_OPERATORS(PowershellCoreProfileGenerator::PowerShellFlags);
|
||||
|
||||
constexpr bool PowershellCoreProfileGenerator::PowerShellInstance::operator<(const PowerShellInstance& second) const
|
||||
{
|
||||
for (const auto& versionedDir : std::filesystem::directory_iterator(root))
|
||||
if (majorVersion != second.majorVersion)
|
||||
{
|
||||
const auto versionedPath = versionedDir.path();
|
||||
const auto executable = versionedPath / PWSH_EXE;
|
||||
if (std::filesystem::exists(executable))
|
||||
return majorVersion < second.majorVersion;
|
||||
}
|
||||
if (flags != second.flags)
|
||||
{
|
||||
return flags > second.flags; // flags are inverted because "0" is ideal; see above
|
||||
}
|
||||
return executablePath < second.executablePath; // fall back to path sorting
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Generates a name, based on flags, for a powershell instance.
|
||||
// Return value:
|
||||
// - the name
|
||||
std::wstring PowershellCoreProfileGenerator::PowerShellInstance::Name() const
|
||||
{
|
||||
std::wstringstream namestream;
|
||||
namestream << L"PowerShell";
|
||||
|
||||
if (WI_IsFlagSet(flags, PowerShellFlags::Store))
|
||||
{
|
||||
if (WI_IsFlagSet(flags, PowerShellFlags::Preview))
|
||||
{
|
||||
const auto preview = versionedPath.filename().native().find(L"-preview") != std::wstring::npos;
|
||||
const auto previewFlag = preview ? PowerShellFlags::Preview : PowerShellFlags::None;
|
||||
out.emplace_back(PowerShellInstance{ std::stoi(versionedPath.filename()),
|
||||
PowerShellFlags::Traditional | flags | previewFlag,
|
||||
executable });
|
||||
namestream << L" Preview";
|
||||
}
|
||||
namestream << L" (msix)";
|
||||
}
|
||||
else if (WI_IsFlagSet(flags, PowerShellFlags::Dotnet))
|
||||
{
|
||||
namestream << L" (dotnet global)";
|
||||
}
|
||||
else if (WI_IsFlagSet(flags, PowerShellFlags::Scoop))
|
||||
{
|
||||
namestream << L" (scoop)";
|
||||
}
|
||||
else
|
||||
{
|
||||
if (majorVersion < 7)
|
||||
{
|
||||
namestream << L" Core";
|
||||
}
|
||||
if (majorVersion != 0)
|
||||
{
|
||||
namestream << L" " << majorVersion;
|
||||
}
|
||||
if (WI_IsFlagSet(flags, PowerShellFlags::Preview))
|
||||
{
|
||||
namestream << L" Preview";
|
||||
}
|
||||
if (WI_IsFlagSet(flags, PowerShellFlags::WOWx86))
|
||||
{
|
||||
namestream << L" (x86)";
|
||||
}
|
||||
if (WI_IsFlagSet(flags, PowerShellFlags::WOWARM))
|
||||
{
|
||||
namestream << L" (ARM)";
|
||||
}
|
||||
}
|
||||
return namestream.str();
|
||||
}
|
||||
|
||||
// Function Description:
|
||||
// - Finds all powershell instances with the traditional layout under a directory.
|
||||
// - The "traditional" directory layout requires that pwsh.exe exist in a versioned directory, as in
|
||||
// ROOT\6\pwsh.exe
|
||||
// Arguments:
|
||||
// - directory: the directory under which to search
|
||||
// - flags: flags to apply to all found instances
|
||||
// - out: the list into which to accumulate these instances.
|
||||
static void _accumulateTraditionalLayoutPowerShellInstancesInDirectory(std::wstring_view directory, PowershellCoreProfileGenerator::PowerShellFlags flags, std::vector<PowershellCoreProfileGenerator::PowerShellInstance>& out)
|
||||
{
|
||||
const std::filesystem::path root{ wil::ExpandEnvironmentStringsW<std::wstring>(directory.data()) };
|
||||
if (std::filesystem::exists(root))
|
||||
{
|
||||
for (const auto& versionedDir : std::filesystem::directory_iterator(root))
|
||||
{
|
||||
const auto versionedPath = versionedDir.path();
|
||||
const auto executable = versionedPath / PWSH_EXE;
|
||||
if (std::filesystem::exists(executable))
|
||||
{
|
||||
const auto preview = versionedPath.filename().native().find(L"-preview") != std::wstring::npos;
|
||||
const auto previewFlag = preview ? PowershellCoreProfileGenerator::PowerShellFlags::Preview : PowershellCoreProfileGenerator::PowerShellFlags::None;
|
||||
out.emplace_back(PowershellCoreProfileGenerator::PowerShellInstance{ std::stoi(versionedPath.filename()),
|
||||
PowershellCoreProfileGenerator::PowerShellFlags::Traditional | flags | previewFlag,
|
||||
executable });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Function Description:
|
||||
// - Finds the store package, if one exists, for a given package family name
|
||||
// Arguments:
|
||||
// - packageFamilyName: the package family name
|
||||
// Return Value:
|
||||
// - a package, or nullptr.
|
||||
static winrt::Windows::ApplicationModel::Package _getStorePackage(const std::wstring_view packageFamilyName) noexcept
|
||||
try
|
||||
{
|
||||
winrt::Windows::Management::Deployment::PackageManager packageManager;
|
||||
auto foundPackages = packageManager.FindPackagesForUser(L"", packageFamilyName);
|
||||
auto iterator = foundPackages.First();
|
||||
if (!iterator.HasCurrent())
|
||||
// Function Description:
|
||||
// - Finds the store package, if one exists, for a given package family name
|
||||
// Arguments:
|
||||
// - packageFamilyName: the package family name
|
||||
// Return Value:
|
||||
// - a package, or nullptr.
|
||||
static winrt::Windows::ApplicationModel::Package _getStorePackage(const std::wstring_view packageFamilyName) noexcept
|
||||
try
|
||||
{
|
||||
winrt::Windows::Management::Deployment::PackageManager packageManager;
|
||||
auto foundPackages = packageManager.FindPackagesForUser(L"", packageFamilyName);
|
||||
auto iterator = foundPackages.First();
|
||||
if (!iterator.HasCurrent())
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
return iterator.Current();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
LOG_CAUGHT_EXCEPTION();
|
||||
return nullptr;
|
||||
}
|
||||
return iterator.Current();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
LOG_CAUGHT_EXCEPTION();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Function Description:
|
||||
// - Finds all powershell instances that have App Execution Aliases in the standard location
|
||||
// Arguments:
|
||||
// - out: the list into which to accumulate these instances.
|
||||
static void _accumulateStorePowerShellInstances(std::vector<PowerShellInstance>& out)
|
||||
{
|
||||
wil::unique_cotaskmem_string localAppDataFolder;
|
||||
if (FAILED(SHGetKnownFolderPath(FOLDERID_LocalAppData, 0, nullptr, &localAppDataFolder)))
|
||||
// Function Description:
|
||||
// - Finds all powershell instances that have App Execution Aliases in the standard location
|
||||
// Arguments:
|
||||
// - out: the list into which to accumulate these instances.
|
||||
static void _accumulateStorePowerShellInstances(std::vector<PowershellCoreProfileGenerator::PowerShellInstance>& out)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
std::filesystem::path appExecAliasPath{ localAppDataFolder.get() };
|
||||
appExecAliasPath /= L"Microsoft";
|
||||
appExecAliasPath /= L"WindowsApps";
|
||||
|
||||
if (std::filesystem::exists(appExecAliasPath))
|
||||
{
|
||||
// App execution aliases for preview powershell
|
||||
const auto previewPath = appExecAliasPath / POWERSHELL_PREVIEW_PFN;
|
||||
if (std::filesystem::exists(previewPath))
|
||||
wil::unique_cotaskmem_string localAppDataFolder;
|
||||
if (FAILED(SHGetKnownFolderPath(FOLDERID_LocalAppData, 0, nullptr, &localAppDataFolder)))
|
||||
{
|
||||
const auto previewPackage = _getStorePackage(POWERSHELL_PREVIEW_PFN);
|
||||
if (previewPackage)
|
||||
{
|
||||
out.emplace_back(PowerShellInstance{
|
||||
gsl::narrow_cast<int>(previewPackage.Id().Version().Major),
|
||||
PowerShellFlags::Store | PowerShellFlags::Preview,
|
||||
previewPath / PWSH_EXE });
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// App execution aliases for stable powershell
|
||||
const auto gaPath = appExecAliasPath / POWERSHELL_PFN;
|
||||
if (std::filesystem::exists(gaPath))
|
||||
std::filesystem::path appExecAliasPath{ localAppDataFolder.get() };
|
||||
appExecAliasPath /= L"Microsoft";
|
||||
appExecAliasPath /= L"WindowsApps";
|
||||
|
||||
if (std::filesystem::exists(appExecAliasPath))
|
||||
{
|
||||
const auto gaPackage = _getStorePackage(POWERSHELL_PFN);
|
||||
if (gaPackage)
|
||||
// App execution aliases for preview powershell
|
||||
const auto previewPath = appExecAliasPath / POWERSHELL_PREVIEW_PFN;
|
||||
if (std::filesystem::exists(previewPath))
|
||||
{
|
||||
out.emplace_back(PowerShellInstance{
|
||||
gaPackage.Id().Version().Major,
|
||||
PowerShellFlags::Store,
|
||||
gaPath / PWSH_EXE,
|
||||
});
|
||||
const auto previewPackage = _getStorePackage(POWERSHELL_PREVIEW_PFN);
|
||||
if (previewPackage)
|
||||
{
|
||||
out.emplace_back(PowershellCoreProfileGenerator::PowerShellInstance{
|
||||
gsl::narrow_cast<int>(previewPackage.Id().Version().Major),
|
||||
PowershellCoreProfileGenerator::PowerShellFlags::Store | PowershellCoreProfileGenerator::PowerShellFlags::Preview,
|
||||
previewPath / PWSH_EXE });
|
||||
}
|
||||
}
|
||||
|
||||
// App execution aliases for stable powershell
|
||||
const auto gaPath = appExecAliasPath / POWERSHELL_PFN;
|
||||
if (std::filesystem::exists(gaPath))
|
||||
{
|
||||
const auto gaPackage = _getStorePackage(POWERSHELL_PFN);
|
||||
if (gaPackage)
|
||||
{
|
||||
out.emplace_back(PowershellCoreProfileGenerator::PowerShellInstance{
|
||||
gaPackage.Id().Version().Major,
|
||||
PowershellCoreProfileGenerator::PowerShellFlags::Store,
|
||||
gaPath / PWSH_EXE,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Function Description:
|
||||
// - Finds a powershell instance that's just a pwsh.exe in a folder.
|
||||
// - This function cannot determine the version number of such a powershell instance.
|
||||
// Arguments:
|
||||
// - directory: the directory under which to search
|
||||
// - flags: flags to apply to all found instances
|
||||
// - out: the list into which to accumulate these instances.
|
||||
static void _accumulatePwshExeInDirectory(const std::wstring_view directory, const PowerShellFlags flags, std::vector<PowerShellInstance>& out)
|
||||
{
|
||||
const std::filesystem::path root{ wil::ExpandEnvironmentStringsW<std::wstring>(directory.data()) };
|
||||
const auto pwshPath = root / PWSH_EXE;
|
||||
if (std::filesystem::exists(pwshPath))
|
||||
// Function Description:
|
||||
// - Finds a powershell instance that's just a pwsh.exe in a folder.
|
||||
// - This function cannot determine the version number of such a powershell instance.
|
||||
// Arguments:
|
||||
// - directory: the directory under which to search
|
||||
// - flags: flags to apply to all found instances
|
||||
// - out: the list into which to accumulate these instances.
|
||||
static void _accumulatePwshExeInDirectory(const std::wstring_view directory, const PowershellCoreProfileGenerator::PowerShellFlags flags, std::vector<PowershellCoreProfileGenerator::PowerShellInstance>& out)
|
||||
{
|
||||
out.emplace_back(PowerShellInstance{ 0 /* we can't tell */, flags, pwshPath });
|
||||
const std::filesystem::path root{ wil::ExpandEnvironmentStringsW<std::wstring>(directory.data()) };
|
||||
const auto pwshPath = root / PWSH_EXE;
|
||||
if (std::filesystem::exists(pwshPath))
|
||||
{
|
||||
out.emplace_back(PowershellCoreProfileGenerator::PowerShellInstance{ 0 /* we can't tell */, flags, pwshPath });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Function Description:
|
||||
// - Builds a comprehensive priority-ordered list of powershell instances.
|
||||
// Return value:
|
||||
// - a comprehensive priority-ordered list of powershell instances.
|
||||
static std::vector<PowerShellInstance> _collectPowerShellInstances()
|
||||
{
|
||||
std::vector<PowerShellInstance> versions;
|
||||
// Function Description:
|
||||
// - Builds a comprehensive priority-ordered list of powershell instances.
|
||||
// Return value:
|
||||
// - a comprehensive priority-ordered list of powershell instances.
|
||||
static std::vector<PowershellCoreProfileGenerator::PowerShellInstance> _collectPowerShellInstances()
|
||||
{
|
||||
std::vector<PowershellCoreProfileGenerator::PowerShellInstance> versions;
|
||||
|
||||
_accumulateTraditionalLayoutPowerShellInstancesInDirectory(L"%ProgramFiles%\\PowerShell", PowerShellFlags::None, versions);
|
||||
_accumulateTraditionalLayoutPowerShellInstancesInDirectory(L"%ProgramFiles%\\PowerShell", PowershellCoreProfileGenerator::PowerShellFlags::None, versions);
|
||||
|
||||
#if defined(_M_AMD64) || defined(_M_ARM64) // No point in looking for WOW if we're not somewhere it exists
|
||||
_accumulateTraditionalLayoutPowerShellInstancesInDirectory(L"%ProgramFiles(x86)%\\PowerShell", PowerShellFlags::WOWx86, versions);
|
||||
_accumulateTraditionalLayoutPowerShellInstancesInDirectory(L"%ProgramFiles(x86)%\\PowerShell", PowershellCoreProfileGenerator::PowerShellFlags::WOWx86, versions);
|
||||
#endif
|
||||
|
||||
#if defined(_M_ARM64) // no point in looking for WOA if we're not on ARM64
|
||||
_accumulateTraditionalLayoutPowerShellInstancesInDirectory(L"%ProgramFiles(Arm)%\\PowerShell", PowerShellFlags::WOWARM, versions);
|
||||
_accumulateTraditionalLayoutPowerShellInstancesInDirectory(L"%ProgramFiles(Arm)%\\PowerShell", PowershellCoreProfileGenerator::PowerShellFlags::WOWARM, versions);
|
||||
#endif
|
||||
|
||||
_accumulateStorePowerShellInstances(versions);
|
||||
_accumulateStorePowerShellInstances(versions);
|
||||
|
||||
_accumulatePwshExeInDirectory(L"%USERPROFILE%\\.dotnet\\tools", PowerShellFlags::Dotnet, versions);
|
||||
_accumulatePwshExeInDirectory(L"%USERPROFILE%\\scoop\\shims", PowerShellFlags::Scoop, versions);
|
||||
_accumulatePwshExeInDirectory(L"%USERPROFILE%\\.dotnet\\tools", PowershellCoreProfileGenerator::PowerShellFlags::Dotnet, versions);
|
||||
_accumulatePwshExeInDirectory(L"%USERPROFILE%\\scoop\\shims", PowershellCoreProfileGenerator::PowerShellFlags::Scoop, versions);
|
||||
|
||||
std::sort(versions.rbegin(), versions.rend()); // sort in reverse (best first)
|
||||
std::sort(versions.rbegin(), versions.rend()); // sort in reverse (best first)
|
||||
|
||||
return versions;
|
||||
}
|
||||
return versions;
|
||||
}
|
||||
|
||||
// Legacy GUIDs:
|
||||
// - PowerShell Core 574e775e-4f2a-5b96-ac1e-a2962a402336
|
||||
static constexpr winrt::guid PowershellCoreGuid{ 0x574e775e, 0x4f2a, 0x5b96, { 0xac, 0x1e, 0xa2, 0x96, 0x2a, 0x40, 0x23, 0x36 } };
|
||||
// Legacy GUIDs:
|
||||
// - PowerShell Core 574e775e-4f2a-5b96-ac1e-a2962a402336
|
||||
static constexpr winrt::guid PowershellCoreGuid{ 0x574e775e, 0x4f2a, 0x5b96, { 0xac, 0x1e, 0xa2, 0x96, 0x2a, 0x40, 0x23, 0x36 } };
|
||||
|
||||
std::wstring_view PowershellCoreProfileGenerator::GetNamespace() const noexcept
|
||||
{
|
||||
return PowershellCoreGeneratorNamespace;
|
||||
}
|
||||
|
||||
std::wstring_view PowershellCoreProfileGenerator::GetDisplayName() const noexcept
|
||||
{
|
||||
return RS_(L"PowershellCoreProfileGeneratorDisplayName");
|
||||
}
|
||||
|
||||
std::wstring_view PowershellCoreProfileGenerator::GetIcon() const noexcept
|
||||
{
|
||||
return GENERATOR_POWERSHELL_ICON;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Checks if pwsh is installed, and if it is, creates a profile to launch it.
|
||||
// Arguments:
|
||||
// - <none>
|
||||
// Return Value:
|
||||
// - a vector with the PowerShell Core profile, if available.
|
||||
void PowershellCoreProfileGenerator::GenerateProfiles(std::vector<winrt::com_ptr<implementation::Profile>>& profiles) const
|
||||
{
|
||||
const auto psInstances = _collectPowerShellInstances();
|
||||
auto first = true;
|
||||
|
||||
for (const auto& psI : psInstances)
|
||||
std::wstring_view PowershellCoreProfileGenerator::GetNamespace() const noexcept
|
||||
{
|
||||
const auto name = psI.Name();
|
||||
auto profile{ CreateDynamicProfile(name) };
|
||||
return PowershellCoreGeneratorNamespace;
|
||||
}
|
||||
|
||||
const auto& unquotedCommandline = psI.executablePath.native();
|
||||
std::wstring quotedCommandline;
|
||||
quotedCommandline.reserve(unquotedCommandline.size() + 2);
|
||||
quotedCommandline.push_back(L'"');
|
||||
quotedCommandline.append(unquotedCommandline);
|
||||
quotedCommandline.push_back(L'"');
|
||||
profile->Commandline(winrt::hstring{ quotedCommandline });
|
||||
std::wstring_view PowershellCoreProfileGenerator::GetDisplayName() const noexcept
|
||||
{
|
||||
return RS_(L"PowershellCoreProfileGeneratorDisplayName");
|
||||
}
|
||||
|
||||
profile->StartingDirectory(winrt::hstring{ DEFAULT_STARTING_DIRECTORY });
|
||||
profile->DefaultAppearance().DarkColorSchemeName(L"Campbell");
|
||||
profile->DefaultAppearance().LightColorSchemeName(L"Campbell");
|
||||
profile->Icon(winrt::hstring{ WI_IsFlagSet(psI.flags, PowerShellFlags::Preview) ? POWERSHELL_PREVIEW_ICON : POWERSHELL_ICON });
|
||||
std::wstring_view PowershellCoreProfileGenerator::GetIcon() const noexcept
|
||||
{
|
||||
return GENERATOR_POWERSHELL_ICON;
|
||||
}
|
||||
|
||||
if (first)
|
||||
// Method Description:
|
||||
// - Checks if pwsh is installed, and if it is, creates a profile to launch it.
|
||||
// Arguments:
|
||||
// - <none>
|
||||
// Return Value:
|
||||
// - a vector with the PowerShell Core profile, if available.
|
||||
void PowershellCoreProfileGenerator::GenerateProfiles(std::vector<winrt::com_ptr<implementation::Profile>>& profiles)
|
||||
{
|
||||
GetPowerShellInstances();
|
||||
auto first = true;
|
||||
|
||||
for (const auto& psI : _powerShellInstances)
|
||||
{
|
||||
// Give the first ("algorithmically best") profile the official, and original, "PowerShell Core" GUID.
|
||||
// This will turn the anchored default profile into "PowerShell Core Latest for Native Architecture through Store"
|
||||
// (or the closest approximation thereof). It may choose a preview instance as the "best" if it is a higher version.
|
||||
profile->Guid(PowershellCoreGuid);
|
||||
profile->Name(winrt::hstring{ POWERSHELL_PREFERRED_PROFILE_NAME });
|
||||
const auto name = psI.Name();
|
||||
auto profile{ CreateDynamicProfile(name) };
|
||||
|
||||
first = false;
|
||||
const auto& unquotedCommandline = psI.executablePath.native();
|
||||
std::wstring quotedCommandline;
|
||||
quotedCommandline.reserve(unquotedCommandline.size() + 2);
|
||||
quotedCommandline.push_back(L'"');
|
||||
quotedCommandline.append(unquotedCommandline);
|
||||
quotedCommandline.push_back(L'"');
|
||||
profile->Commandline(winrt::hstring{ quotedCommandline });
|
||||
|
||||
profile->StartingDirectory(winrt::hstring{ DEFAULT_STARTING_DIRECTORY });
|
||||
profile->DefaultAppearance().DarkColorSchemeName(L"Campbell");
|
||||
profile->DefaultAppearance().LightColorSchemeName(L"Campbell");
|
||||
profile->Icon(winrt::hstring{ WI_IsFlagSet(psI.flags, PowerShellFlags::Preview) ? POWERSHELL_PREVIEW_ICON : POWERSHELL_ICON });
|
||||
|
||||
if (first)
|
||||
{
|
||||
// Give the first ("algorithmically best") profile the official, and original, "PowerShell Core" GUID.
|
||||
// This will turn the anchored default profile into "PowerShell Core Latest for Native Architecture through Store"
|
||||
// (or the closest approximation thereof). It may choose a preview instance as the "best" if it is a higher version.
|
||||
profile->Guid(PowershellCoreGuid);
|
||||
profile->Name(winrt::hstring{ POWERSHELL_PREFERRED_PROFILE_NAME });
|
||||
|
||||
first = false;
|
||||
}
|
||||
|
||||
profiles.emplace_back(std::move(profile));
|
||||
}
|
||||
}
|
||||
|
||||
profiles.emplace_back(std::move(profile));
|
||||
std::vector<PowershellCoreProfileGenerator::PowerShellInstance> PowershellCoreProfileGenerator::GetPowerShellInstances() noexcept
|
||||
{
|
||||
if (_powerShellInstances.empty())
|
||||
{
|
||||
_powerShellInstances = _collectPowerShellInstances();
|
||||
}
|
||||
return _powerShellInstances;
|
||||
}
|
||||
|
||||
// Function Description:
|
||||
// - Returns the thing it's named for.
|
||||
// Return value:
|
||||
// - the thing it says in the name
|
||||
const std::wstring_view PowershellCoreProfileGenerator::GetPreferredPowershellProfileName()
|
||||
{
|
||||
return POWERSHELL_PREFERRED_PROFILE_NAME;
|
||||
}
|
||||
}
|
||||
|
||||
// Function Description:
|
||||
// - Returns the thing it's named for.
|
||||
// Return value:
|
||||
// - the thing it says in the name
|
||||
const std::wstring_view PowershellCoreProfileGenerator::GetPreferredPowershellProfileName()
|
||||
{
|
||||
return POWERSHELL_PREFERRED_PROFILE_NAME;
|
||||
}
|
||||
|
||||
@@ -25,9 +25,60 @@ namespace winrt::Microsoft::Terminal::Settings::Model
|
||||
public:
|
||||
static const std::wstring_view GetPreferredPowershellProfileName();
|
||||
|
||||
enum PowerShellFlags
|
||||
{
|
||||
None = 0,
|
||||
|
||||
// These flags are used as a sort key, so they encode some native ordering.
|
||||
// They are ordered such that the "most important" flags have the largest
|
||||
// impact on the sort space. For example, since we want Preview to be very polar
|
||||
// we give it the highest flag value.
|
||||
// The "ideal" powershell instance has 0 flags (stable, native, Program Files location)
|
||||
//
|
||||
// With this ordering, the sort space ends up being (for PowerShell 6)
|
||||
// (numerically greater values are on the left; this is flipped in the final sort)
|
||||
//
|
||||
// <-- Less Valued .................................... More Valued -->
|
||||
// | All instances of PS 6 | All PS7 |
|
||||
// | Preview | Stable | ~~~ |
|
||||
// | Non-Native | Native | Non-Native | Native | ~~~ |
|
||||
// | Trd | Pack | Trd | Pack | Trd | Pack | Trd | Pack | ~~~ |
|
||||
// (where Pack is a stand-in for store, scoop, dotnet, though they have their own orders,
|
||||
// and Trd is a stand-in for "Traditional" (Program Files))
|
||||
//
|
||||
// In short, flags with larger magnitudes are pushed further down (therefore valued less)
|
||||
|
||||
// distribution method (choose one)
|
||||
Store = 1 << 0, // distributed via the store
|
||||
Scoop = 1 << 1, // installed via Scoop
|
||||
Dotnet = 1 << 2, // installed as a dotnet global tool
|
||||
Traditional = 1 << 3, // installed in traditional Program Files locations
|
||||
|
||||
// native architecture (choose one)
|
||||
WOWARM = 1 << 4, // non-native (Windows-on-Windows, ARM variety)
|
||||
WOWx86 = 1 << 5, // non-native (Windows-on-Windows, x86 variety)
|
||||
|
||||
// build type (choose one)
|
||||
Preview = 1 << 6, // preview version
|
||||
};
|
||||
|
||||
struct PowerShellInstance
|
||||
{
|
||||
int majorVersion; // 0 = we don't know, sort last.
|
||||
PowerShellFlags flags;
|
||||
std::filesystem::path executablePath;
|
||||
|
||||
constexpr bool operator<(const PowerShellInstance& second) const;
|
||||
std::wstring Name() const;
|
||||
};
|
||||
|
||||
std::wstring_view GetNamespace() const noexcept override;
|
||||
std::wstring_view GetDisplayName() const noexcept override;
|
||||
std::wstring_view GetIcon() const noexcept override;
|
||||
void GenerateProfiles(std::vector<winrt::com_ptr<implementation::Profile>>& profiles) const override;
|
||||
void GenerateProfiles(std::vector<winrt::com_ptr<implementation::Profile>>& profiles) override;
|
||||
std::vector<PowerShellInstance> GetPowerShellInstances() noexcept;
|
||||
|
||||
private:
|
||||
std::vector<PowerShellInstance> _powerShellInstances;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#include "pch.h"
|
||||
|
||||
#include "PowershellInstallationProfileGenerator.h"
|
||||
#include "DynamicProfileUtils.h"
|
||||
|
||||
#include <LibraryResources.h>
|
||||
|
||||
static constexpr std::wstring_view POWERSHELL_ICON{ L"ms-appx:///ProfileIcons/pwsh.png" };
|
||||
static constexpr std::wstring_view GENERATOR_POWERSHELL_ICON{ L"ms-appx:///ProfileGeneratorIcons/PowerShell.png" };
|
||||
|
||||
namespace winrt::Microsoft::Terminal::Settings::Model
|
||||
{
|
||||
std::wstring_view PowershellInstallationProfileGenerator::Namespace{ L"Windows.Terminal.InstallPowerShell" };
|
||||
|
||||
std::wstring_view PowershellInstallationProfileGenerator::GetNamespace() const noexcept
|
||||
{
|
||||
return Namespace;
|
||||
}
|
||||
|
||||
std::wstring_view PowershellInstallationProfileGenerator::GetDisplayName() const noexcept
|
||||
{
|
||||
return RS_(L"PowerShellInstallationProfileGeneratorDisplayName");
|
||||
}
|
||||
|
||||
std::wstring_view PowershellInstallationProfileGenerator::GetIcon() const noexcept
|
||||
{
|
||||
return GENERATOR_POWERSHELL_ICON;
|
||||
}
|
||||
|
||||
void PowershellInstallationProfileGenerator::GenerateProfiles(std::vector<winrt::com_ptr<implementation::Profile>>& profiles)
|
||||
{
|
||||
auto profile{ CreateDynamicProfile(RS_(L"PowerShellInstallationProfileName")) };
|
||||
profile->Commandline(winrt::hstring{ fmt::format(FMT_COMPILE(L"cmd /k winget install --interactive --id Microsoft.PowerShell --source winget & echo. & echo {} & exit"), RS_(L"PowerShellInstallationInstallerGuidance")) });
|
||||
profile->Icon(winrt::hstring{ POWERSHELL_ICON });
|
||||
profile->CloseOnExit(CloseOnExitMode::Never);
|
||||
|
||||
profiles.emplace_back(std::move(profile));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*++
|
||||
Copyright (c) Microsoft Corporation
|
||||
Licensed under the MIT license.
|
||||
|
||||
Module Name:
|
||||
- PowershellInstallationProfileGenerator
|
||||
|
||||
Abstract:
|
||||
- This is the dynamic profile generator for a PowerShell stub. Checks if pwsh is
|
||||
installed, and if it is NOT installed, creates a profile that installs the
|
||||
latest PowerShell.
|
||||
|
||||
Author(s):
|
||||
- Carlos Zamora - March 2025
|
||||
|
||||
--*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "IDynamicProfileGenerator.h"
|
||||
|
||||
namespace winrt::Microsoft::Terminal::Settings::Model
|
||||
{
|
||||
class PowershellInstallationProfileGenerator final : public IDynamicProfileGenerator
|
||||
{
|
||||
public:
|
||||
static std::wstring_view Namespace;
|
||||
std::wstring_view GetNamespace() const noexcept override;
|
||||
std::wstring_view GetDisplayName() const noexcept override;
|
||||
std::wstring_view GetIcon() const noexcept override;
|
||||
void GenerateProfiles(std::vector<winrt::com_ptr<implementation::Profile>>& profiles) override;
|
||||
};
|
||||
};
|
||||
@@ -740,6 +740,66 @@
|
||||
<data name="OpenCWDCommandKey" xml:space="preserve">
|
||||
<value>Open current working directory</value>
|
||||
</data>
|
||||
<data name="CloseTab" xml:space="preserve">
|
||||
<value>Close tab</value>
|
||||
</data>
|
||||
<data name="SendInput" xml:space="preserve">
|
||||
<value>Send input</value>
|
||||
</data>
|
||||
<data name="SetFocusMode" xml:space="preserve">
|
||||
<value>Set focus mode</value>
|
||||
</data>
|
||||
<data name="SetFullScreen" xml:space="preserve">
|
||||
<value>Set full screen</value>
|
||||
</data>
|
||||
<data name="SetMaximized" xml:space="preserve">
|
||||
<value>Set maximized</value>
|
||||
</data>
|
||||
<data name="SetColorScheme" xml:space="preserve">
|
||||
<value>Set color scheme</value>
|
||||
</data>
|
||||
<data name="CloseOtherTabs" xml:space="preserve">
|
||||
<value>Close other tabs</value>
|
||||
</data>
|
||||
<data name="CloseTabsAfter" xml:space="preserve">
|
||||
<value>Close tabs after</value>
|
||||
</data>
|
||||
<data name="MoveTab" xml:space="preserve">
|
||||
<value>Move tab</value>
|
||||
</data>
|
||||
<data name="FindMatch" xml:space="preserve">
|
||||
<value>Find match</value>
|
||||
</data>
|
||||
<data name="SearchForText" xml:space="preserve">
|
||||
<value>Search for text</value>
|
||||
</data>
|
||||
<data name="FocusPane" xml:space="preserve">
|
||||
<value>Focus pane</value>
|
||||
</data>
|
||||
<data name="ExportBuffer" xml:space="preserve">
|
||||
<value>Export buffer</value>
|
||||
</data>
|
||||
<data name="ClearBuffer" xml:space="preserve">
|
||||
<value>Clear buffer</value>
|
||||
</data>
|
||||
<data name="MultipleActions" xml:space="preserve">
|
||||
<value>Multiple actions</value>
|
||||
</data>
|
||||
<data name="AdjustOpacity" xml:space="preserve">
|
||||
<value>Adjust opacity</value>
|
||||
</data>
|
||||
<data name="SelectCommand" xml:space="preserve">
|
||||
<value>Select command</value>
|
||||
</data>
|
||||
<data name="SelectOutput" xml:space="preserve">
|
||||
<value>Select output</value>
|
||||
</data>
|
||||
<data name="Suggestions" xml:space="preserve">
|
||||
<value>Suggestions</value>
|
||||
</data>
|
||||
<data name="ColorSelection" xml:space="preserve">
|
||||
<value>Color selection</value>
|
||||
</data>
|
||||
<data name="WslDistroGeneratorDisplayName" xml:space="preserve">
|
||||
<value>WSL Distribution Profile Generator</value>
|
||||
<comment>The display name of a dynamic profile generator for WSL distros</comment>
|
||||
@@ -748,6 +808,14 @@
|
||||
<value>PowerShell Profile Generator</value>
|
||||
<comment>The display name of a dynamic profile generator for PowerShell</comment>
|
||||
</data>
|
||||
<data name="PowershellInstallationProfileGeneratorDisplayName" xml:space="preserve">
|
||||
<value>PowerShell Installation Generator</value>
|
||||
<comment>The display name of a dynamic profile generator that installs the latest PowerShell</comment>
|
||||
</data>
|
||||
<data name="PowershellInstallationProfileName" xml:space="preserve">
|
||||
<value>Install Latest PowerShell</value>
|
||||
<comment>The display name of a profile generated by the PowerShellInstallationProfileGenerator. This profile installs the latest PowerShell.</comment>
|
||||
</data>
|
||||
<data name="AzureCloudShellGeneratorDisplayName" xml:space="preserve">
|
||||
<value>Azure Cloud Shell Profile Generator</value>
|
||||
<comment>The display name of a dynamic profile generator for Azure Cloud Shell</comment>
|
||||
@@ -760,4 +828,11 @@
|
||||
<value>SSH Host Profile Generator</value>
|
||||
<comment>The display name of a dynamic profile generator for SSH hosts</comment>
|
||||
</data>
|
||||
</root>
|
||||
<data name="PowerShellInstallationInstallerGuidance" xml:space="preserve">
|
||||
<value>Restart Windows Terminal to apply the new profile.</value>
|
||||
<comment>Guidance displayed by the installer directing the user to restart the app.</comment>
|
||||
</data>
|
||||
<data name="PowerShellInstallationProfileJsonComment" xml:space="preserve">
|
||||
<value>This profile only appears if PowerShell is not installed</value>
|
||||
</data>
|
||||
</root>
|
||||
|
||||
@@ -150,7 +150,7 @@ std::wstring_view SshHostGenerator::GetIcon() const noexcept
|
||||
// - <none>
|
||||
// Return Value:
|
||||
// - <A list of SSH host profiles.>
|
||||
void SshHostGenerator::GenerateProfiles(std::vector<winrt::com_ptr<implementation::Profile>>& profiles) const
|
||||
void SshHostGenerator::GenerateProfiles(std::vector<winrt::com_ptr<implementation::Profile>>& profiles)
|
||||
{
|
||||
std::wstring sshExePath;
|
||||
if (_tryFindSshExePath(sshExePath))
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model
|
||||
std::wstring_view GetNamespace() const noexcept override;
|
||||
std::wstring_view GetDisplayName() const noexcept override;
|
||||
std::wstring_view GetIcon() const noexcept override;
|
||||
void GenerateProfiles(std::vector<winrt::com_ptr<implementation::Profile>>& profiles) const override;
|
||||
void GenerateProfiles(std::vector<winrt::com_ptr<implementation::Profile>>& profiles) override;
|
||||
|
||||
private:
|
||||
static const std::wregex _configKeyValueRegex;
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include "SettingsTheme.g.h"
|
||||
#include "ThemeColor.g.cpp"
|
||||
#include "WindowTheme.g.cpp"
|
||||
#include "PaneTheme.g.cpp"
|
||||
#include "TabRowTheme.g.cpp"
|
||||
#include "TabTheme.g.cpp"
|
||||
#include "ThemePair.g.cpp"
|
||||
@@ -60,6 +61,7 @@ THEME_OBJECT(WindowTheme, MTSM_THEME_WINDOW_SETTINGS);
|
||||
THEME_OBJECT(SettingsTheme, MTSM_THEME_SETTINGS_SETTINGS);
|
||||
THEME_OBJECT(TabRowTheme, MTSM_THEME_TABROW_SETTINGS);
|
||||
THEME_OBJECT(TabTheme, MTSM_THEME_TAB_SETTINGS);
|
||||
THEME_OBJECT(PaneTheme, MTSM_THEME_PANE_SETTINGS);
|
||||
|
||||
#undef THEME_SETTINGS_COPY
|
||||
#undef THEME_SETTINGS_TO_JSON
|
||||
@@ -224,6 +226,7 @@ THEME_OBJECT_CONVERTER(winrt::Microsoft::Terminal::Settings::Model, WindowTheme,
|
||||
THEME_OBJECT_CONVERTER(winrt::Microsoft::Terminal::Settings::Model, SettingsTheme, MTSM_THEME_SETTINGS_SETTINGS);
|
||||
THEME_OBJECT_CONVERTER(winrt::Microsoft::Terminal::Settings::Model, TabRowTheme, MTSM_THEME_TABROW_SETTINGS);
|
||||
THEME_OBJECT_CONVERTER(winrt::Microsoft::Terminal::Settings::Model, TabTheme, MTSM_THEME_TAB_SETTINGS);
|
||||
THEME_OBJECT_CONVERTER(winrt::Microsoft::Terminal::Settings::Model, PaneTheme, MTSM_THEME_PANE_SETTINGS);
|
||||
|
||||
#undef THEME_SETTINGS_FROM_JSON
|
||||
#undef THEME_SETTINGS_TO_JSON
|
||||
@@ -254,6 +257,10 @@ winrt::com_ptr<Theme> Theme::Copy() const
|
||||
{
|
||||
theme->_Tab = *winrt::get_self<implementation::TabTheme>(_Tab)->Copy();
|
||||
}
|
||||
if (_Pane)
|
||||
{
|
||||
theme->_Pane = *winrt::get_self<implementation::PaneTheme>(_Pane)->Copy();
|
||||
}
|
||||
if (_Settings)
|
||||
{
|
||||
theme->_Settings = *winrt::get_self<implementation::SettingsTheme>(_Settings)->Copy();
|
||||
@@ -334,6 +341,13 @@ void Theme::LogSettingChanges(std::set<std::string>& changes, const std::string_
|
||||
const auto outerJsonKey = outerTabJsonKey;
|
||||
MTSM_THEME_TAB_SETTINGS(LOG_IF_SET)
|
||||
}
|
||||
|
||||
if (isPaneSet)
|
||||
{
|
||||
const auto obj = _Pane;
|
||||
const auto outerJsonKey = outerPaneJsonKey;
|
||||
MTSM_THEME_PANE_SETTINGS(LOG_IF_SET);
|
||||
}
|
||||
#undef LOG_IF_SET
|
||||
#undef GENERATE_SET_CHECK_AND_JSON_KEYS
|
||||
#pragma warning(pop)
|
||||
|
||||
@@ -23,6 +23,7 @@ Author(s):
|
||||
#include "WindowTheme.g.h"
|
||||
#include "TabRowTheme.g.h"
|
||||
#include "TabTheme.g.h"
|
||||
#include "PaneTheme.g.h"
|
||||
#include "ThemePair.g.h"
|
||||
#include "Theme.g.h"
|
||||
|
||||
@@ -85,6 +86,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
THEME_OBJECT(SettingsTheme, MTSM_THEME_SETTINGS_SETTINGS);
|
||||
THEME_OBJECT(TabRowTheme, MTSM_THEME_TABROW_SETTINGS);
|
||||
THEME_OBJECT(TabTheme, MTSM_THEME_TAB_SETTINGS);
|
||||
THEME_OBJECT(PaneTheme, MTSM_THEME_PANE_SETTINGS);
|
||||
|
||||
struct Theme : ThemeT<Theme>
|
||||
{
|
||||
|
||||
@@ -71,6 +71,12 @@ namespace Microsoft.Terminal.Settings.Model
|
||||
ThemeColor UnfocusedBackground { get; };
|
||||
}
|
||||
|
||||
runtimeclass PaneTheme {
|
||||
ThemeColor ActiveBorderColor { get; };
|
||||
ThemeColor InactiveBorderColor { get; };
|
||||
ThemeColor BroadcastBorderColor { get; };
|
||||
}
|
||||
|
||||
runtimeclass TabTheme {
|
||||
ThemeColor Background { get; };
|
||||
ThemeColor UnfocusedBackground { get; };
|
||||
@@ -93,6 +99,9 @@ namespace Microsoft.Terminal.Settings.Model
|
||||
// tabRow.* Namespace
|
||||
TabRowTheme TabRow { get; };
|
||||
|
||||
// pane.* Namespace
|
||||
PaneTheme Pane { get; };
|
||||
|
||||
// tab.* Namespace
|
||||
TabTheme Tab { get; };
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ std::wstring_view VisualStudioGenerator::GetIcon() const noexcept
|
||||
return IconPath;
|
||||
}
|
||||
|
||||
void VisualStudioGenerator::GenerateProfiles(std::vector<winrt::com_ptr<implementation::Profile>>& profiles) const
|
||||
void VisualStudioGenerator::GenerateProfiles(std::vector<winrt::com_ptr<implementation::Profile>>& profiles)
|
||||
{
|
||||
const auto instances = VsSetupConfiguration::QueryInstances();
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model
|
||||
std::wstring_view GetNamespace() const noexcept override;
|
||||
std::wstring_view GetDisplayName() const noexcept override;
|
||||
std::wstring_view GetIcon() const noexcept override;
|
||||
void GenerateProfiles(std::vector<winrt::com_ptr<implementation::Profile>>& profiles) const override;
|
||||
void GenerateProfiles(std::vector<winrt::com_ptr<implementation::Profile>>& profiles) override;
|
||||
|
||||
class IVisualStudioProfileGenerator
|
||||
{
|
||||
|
||||
@@ -239,7 +239,7 @@ static bool getWslNames(const wil::unique_hkey& wslRootKey,
|
||||
// - <none>
|
||||
// Return Value:
|
||||
// - A list of WSL profiles.
|
||||
void WslDistroGenerator::GenerateProfiles(std::vector<winrt::com_ptr<implementation::Profile>>& profiles) const
|
||||
void WslDistroGenerator::GenerateProfiles(std::vector<winrt::com_ptr<implementation::Profile>>& profiles)
|
||||
{
|
||||
auto wslRootKey{ openWslRegKey() };
|
||||
if (wslRootKey)
|
||||
|
||||
@@ -26,6 +26,6 @@ namespace winrt::Microsoft::Terminal::Settings::Model
|
||||
std::wstring_view GetNamespace() const noexcept override;
|
||||
std::wstring_view GetDisplayName() const noexcept override;
|
||||
std::wstring_view GetIcon() const noexcept override;
|
||||
void GenerateProfiles(std::vector<winrt::com_ptr<implementation::Profile>>& profiles) const override;
|
||||
void GenerateProfiles(std::vector<winrt::com_ptr<implementation::Profile>>& profiles) override;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -77,4 +77,36 @@ namespace winrt::Microsoft::Terminal::UI::implementation
|
||||
{
|
||||
return fontWeight.Weight;
|
||||
}
|
||||
|
||||
double Converters::MaxValueFromPaddingString(const winrt::hstring& paddingString)
|
||||
{
|
||||
std::wstring buffer;
|
||||
double maxVal = 0;
|
||||
|
||||
auto& errnoRef = errno; // Nonzero cost, pay it once
|
||||
|
||||
// Get padding values till we run out of delimiter separated values in the stream
|
||||
// Non-numeral values detected will default to 0
|
||||
// std::stod will throw invalid_argument exception if the input is an invalid double value
|
||||
// std::stod will throw out_of_range exception if the input value is more than DBL_MAX
|
||||
for (const auto& part : til::split_iterator{ std::wstring_view{ paddingString }, L',' })
|
||||
{
|
||||
buffer.assign(part);
|
||||
|
||||
// wcstod handles whitespace prefix (which is ignored) & stops the
|
||||
// scan when first char outside the range of radix is encountered.
|
||||
// We'll be permissive till the extent that stod function allows us to be by default
|
||||
// Ex. a value like 100.3#535w2 will be read as 100.3, but ;df25 will fail
|
||||
errnoRef = 0;
|
||||
wchar_t* end;
|
||||
const double val = wcstod(buffer.c_str(), &end);
|
||||
|
||||
if (end != buffer.c_str() && errnoRef != ERANGE)
|
||||
{
|
||||
maxVal = std::max(maxVal, val);
|
||||
}
|
||||
}
|
||||
|
||||
return maxVal;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ namespace winrt::Microsoft::Terminal::UI::implementation
|
||||
static winrt::Windows::UI::Text::FontWeight DoubleToFontWeight(double value);
|
||||
static winrt::Windows::UI::Xaml::Media::SolidColorBrush ColorToBrush(winrt::Windows::UI::Color color);
|
||||
static double FontWeightToDouble(winrt::Windows::UI::Text::FontWeight fontWeight);
|
||||
static double MaxValueFromPaddingString(const winrt::hstring& paddingString);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -26,5 +26,6 @@ namespace Microsoft.Terminal.UI
|
||||
static Windows.UI.Text.FontWeight DoubleToFontWeight(Double value);
|
||||
static Windows.UI.Xaml.Media.SolidColorBrush ColorToBrush(Windows.UI.Color color);
|
||||
static Double FontWeightToDouble(Windows.UI.Text.FontWeight fontWeight);
|
||||
static Double MaxValueFromPaddingString(String paddingString);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -197,4 +197,16 @@
|
||||
<alwaysDisabledReleaseTokens/>
|
||||
</feature>
|
||||
|
||||
<feature>
|
||||
<name>Feature_PowerShellInstallerProfileGenerator</name>
|
||||
<description>Enables the PowerShell Installer Dynamic Profile Generator</description>
|
||||
<id>18639</id>
|
||||
<stage>AlwaysDisabled</stage>
|
||||
<alwaysEnabledBrandingTokens>
|
||||
<brandingToken>Dev</brandingToken>
|
||||
<brandingToken>Canary</brandingToken>
|
||||
<brandingToken>Preview</brandingToken>
|
||||
</alwaysEnabledBrandingTokens>
|
||||
</feature>
|
||||
|
||||
</featureStaging>
|
||||
|
||||
@@ -24,6 +24,9 @@ class Microsoft::Console::VirtualTerminal::ITermDispatch
|
||||
{
|
||||
public:
|
||||
using StringHandler = std::function<bool(const wchar_t)>;
|
||||
using PrintHandler = std::function<void(const std::wstring_view)>;
|
||||
// Use this get the StringHandler, meanwhile pass the function to give app a function to print message bypass the parser
|
||||
using StringHandlerProducer = std::function<StringHandler(PrintHandler)>;
|
||||
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 26432) // suppress rule of 5 violation on interface because tampering with this is fraught with peril
|
||||
@@ -185,6 +188,9 @@ public:
|
||||
virtual StringHandler RestorePresentationState(const DispatchTypes::PresentationReportFormat format) = 0; // DECRSPS
|
||||
|
||||
virtual void PlaySounds(const VTParameters parameters) = 0; // DECPS
|
||||
|
||||
virtual StringHandler EnterTmuxControl(const VTParameters parameters) = 0; // tmux -CC
|
||||
virtual void SetTmuxControlHandlerProducer(StringHandlerProducer producer) = 0; // tmux -CC
|
||||
};
|
||||
inline Microsoft::Console::VirtualTerminal::ITermDispatch::~ITermDispatch() = default;
|
||||
#pragma warning(pop)
|
||||
|
||||
@@ -4790,3 +4790,25 @@ void AdaptDispatch::PlaySounds(const VTParameters parameters)
|
||||
_api.PlayMidiNote(noteNumber, noteNumber == 71 ? 0 : velocity, duration);
|
||||
});
|
||||
}
|
||||
|
||||
ITermDispatch::StringHandler AdaptDispatch::EnterTmuxControl(const VTParameters parameters)
|
||||
{
|
||||
if (parameters.size() != 1 || parameters.at(0).value() != 1000) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (_tmuxControlHandlerProducer) {
|
||||
const auto page = _pages.ActivePage();
|
||||
return _tmuxControlHandlerProducer([this, page](auto s) {
|
||||
PrintString(s);
|
||||
_DoLineFeed(page, true, true);
|
||||
});
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void AdaptDispatch::SetTmuxControlHandlerProducer(StringHandlerProducer producer)
|
||||
{
|
||||
_tmuxControlHandlerProducer = producer;
|
||||
}
|
||||
|
||||
@@ -190,6 +190,9 @@ namespace Microsoft::Console::VirtualTerminal
|
||||
|
||||
void SetVtChecksumReportSupport(const bool enabled) noexcept override;
|
||||
|
||||
StringHandler EnterTmuxControl(const VTParameters parameters) override; // tmux -CC
|
||||
void SetTmuxControlHandlerProducer(StringHandlerProducer producer) override; // tmux -CC
|
||||
|
||||
private:
|
||||
enum class Mode
|
||||
{
|
||||
@@ -328,6 +331,7 @@ namespace Microsoft::Console::VirtualTerminal
|
||||
til::enumset<Mode> _modes{ Mode::PageCursorCoupling };
|
||||
|
||||
SgrStack _sgrStack;
|
||||
StringHandlerProducer _tmuxControlHandlerProducer { nullptr };
|
||||
|
||||
void _SetUnderlineStyleHelper(const VTParameter option, TextAttribute& attr) noexcept;
|
||||
size_t _SetRgbColorsHelper(const VTParameters options,
|
||||
|
||||
@@ -179,6 +179,9 @@ public:
|
||||
void PlaySounds(const VTParameters /*parameters*/) override{}; // DECPS
|
||||
|
||||
void SetVtChecksumReportSupport(const bool /*enabled*/) override{};
|
||||
|
||||
StringHandler EnterTmuxControl(const VTParameters /*parameters*/) override { return nullptr; }; // tmux -CC
|
||||
void SetTmuxControlHandlerProducer(StringHandlerProducer /*producer*/) override{}; // tmux -CC
|
||||
};
|
||||
|
||||
#pragma warning(default : 26440) // Restore "can be declared noexcept" warning
|
||||
|
||||
@@ -724,6 +724,9 @@ IStateMachineEngine::StringHandler OutputStateMachineEngine::ActionDcsDispatch(c
|
||||
case DcsActionCodes::DECRSPS_RestorePresentationState:
|
||||
handler = _dispatch->RestorePresentationState(parameters.at(0));
|
||||
break;
|
||||
case DcsActionCodes::TMUX_ControlEnter:
|
||||
handler = _dispatch->EnterTmuxControl(parameters);
|
||||
break;
|
||||
default:
|
||||
handler = nullptr;
|
||||
break;
|
||||
|
||||
@@ -178,6 +178,7 @@ namespace Microsoft::Console::VirtualTerminal
|
||||
DECRSTS_RestoreTerminalState = VTID("$p"),
|
||||
DECRQSS_RequestSetting = VTID("$q"),
|
||||
DECRSPS_RestorePresentationState = VTID("$t"),
|
||||
TMUX_ControlEnter = VTID("p"),
|
||||
};
|
||||
|
||||
enum Vt52ActionCodes : uint64_t
|
||||
|
||||
Reference in New Issue
Block a user