Address Carlos' comments

This commit is contained in:
Leonard Hecker 2021-09-10 21:26:10 +02:00
parent cdf07bb2bd
commit 2247297c31
14 changed files with 89 additions and 109 deletions

View file

@ -50,7 +50,6 @@
<PRIResource Include="Resources\Resources.resw" />
<OCResourceDirectory Include="Resources" />
</ItemGroup>
<!-- This is picked up by CascadiaResources.build.items. -->
<PropertyGroup Condition="'$(WindowsTerminalBranding)'==''">
<WindowsTerminalAssetSuffix>-Dev</WindowsTerminalAssetSuffix>
@ -58,7 +57,6 @@
<PropertyGroup Condition="'$(WindowsTerminalBranding)'=='Preview'">
<WindowsTerminalAssetSuffix>-Pre</WindowsTerminalAssetSuffix>
</PropertyGroup>
<Import Project="$(MSBuildThisFileDirectory)..\CascadiaResources.build.items" />
<Import Project="$(OpenConsoleDir)src\wap-common.build.post.props" />
<ItemGroup>
@ -69,7 +67,9 @@
<ProjectReference Include="..\ShellExtension\WindowsTerminalShellExt.vcxproj" />
<ProjectReference Include="..\wt\wt.vcxproj" />
</ItemGroup>
<ItemGroup>
<None Include="CascadiaPackage_TemporaryKey.pfx" />
</ItemGroup>
<Target Name="OpenConsoleStompSourceProjectForWapProject" BeforeTargets="_ConvertItems">
<ItemGroup>
<!-- Stomp all "SourceProject" values for all incoming dependencies to flatten the package. -->
@ -111,6 +111,29 @@
<WapProjBeforeGenerateAppxManifestDependsOn>
$([MSBuild]::Unescape('$(WapProjBeforeGenerateAppxManifestDependsOn.Replace('_RemoveAllNonWapUWPItems', '_OpenConsoleRemoveAllNonWapUWPItems'))'))
</WapProjBeforeGenerateAppxManifestDependsOn>
<GenerateAppInstallerFile>False</GenerateAppInstallerFile>
<AppxPackageSigningTimestampDigestAlgorithm>SHA256</AppxPackageSigningTimestampDigestAlgorithm>
<GenerateTestArtifacts>True</GenerateTestArtifacts>
<HoursBetweenUpdateChecks>0</HoursBetweenUpdateChecks>
<AppxBundlePlatforms>x64</AppxBundlePlatforms>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
<AppxBundle>Always</AppxBundle>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<AppxBundle>Always</AppxBundle>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<AppxBundle>Always</AppxBundle>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
<AppxBundle>Always</AppxBundle>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x86'">
<AppxBundle>Always</AppxBundle>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x86'">
<AppxBundle>Always</AppxBundle>
</PropertyGroup>
<Target Name="_OpenConsoleRemoveAllNonWapUWPItems">
<ItemGroup>
@ -121,7 +144,6 @@
<AppxUploadPackagePayload Remove="@(AppxUploadPackagePayload)" Condition="'%(Extension)' == '.pri' and '%(Filename)' != 'resources'" />
</ItemGroup>
</Target>
<!-- **BEGIN VC LIBS HACK** -->
<!--
For our release builds, we're just going to integrate the UWPDesktop CRT into our package and delete the package dependencies.
@ -136,7 +158,6 @@
<FrameworkSdkReference Remove="@(FrameworkSdkReference)" />
</ItemGroup>
</Target>
<!-- This target removes the FrameworkSdkPackages from before the *desktop bridge* manifest generation happens. -->
<Target Name="_OpenConsoleStripAllDependenciesFromPackageSecondManifest" BeforeTargets="_GenerateDesktopBridgeAppxManifest" DependsOnTargets="_ResolveVCLibDependencies">
<ItemGroup Condition="'$(WindowsTerminalOfficialBuild)'=='true'">
@ -144,7 +165,6 @@
</ItemGroup>
</Target>
<!-- **END VC LIBS HACK** -->
<!-- This is required to get the package dependency in the AppXManifest. -->
<Import Project="..\..\..\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('..\..\..\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
@ -153,6 +173,5 @@
</PropertyGroup>
<Error Condition="!Exists('..\..\..\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets'))" />
</Target>
<Import Project="$(SolutionDir)build\rules\CollectWildcardResources.targets" />
</Project>
</Project>

View file

@ -16,7 +16,7 @@
<Identity
Name="WindowsTerminalDev"
Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US"
Publisher="CN=lhecker"
Version="0.0.1.0" />
<Properties>

View file

@ -29,7 +29,7 @@ void AzureCloudShellGenerator::GenerateProfiles(std::vector<winrt::com_ptr<imple
{
if (AzureConnection::IsAzureConnectionAvailable())
{
auto azureCloudShellProfile{ CreateDefaultProfile(AzureGeneratorNamespace, L"Azure Cloud Shell") };
auto azureCloudShellProfile{ CreateDynamicProfile(AzureGeneratorNamespace, L"Azure Cloud Shell") };
azureCloudShellProfile->Commandline(L"Azure");
azureCloudShellProfile->StartingDirectory(winrt::hstring{ DEFAULT_STARTING_DIRECTORY });
azureCloudShellProfile->DefaultAppearance().ColorSchemeName(L"Vintage");

View file

@ -15,7 +15,7 @@ using namespace winrt::Microsoft::Terminal::Control;
using namespace winrt::Windows::Foundation::Collections;
using namespace Microsoft::Console;
winrt::com_ptr<Profile> Model::implementation::ReproduceProfile(const winrt::com_ptr<Profile>& parent)
winrt::com_ptr<Profile> Model::implementation::CreateChild(const winrt::com_ptr<Profile>& parent)
{
const auto profile = winrt::make_self<Profile>();
profile->Origin(OriginTag::User);
@ -365,7 +365,7 @@ winrt::com_ptr<Profile> CascadiaSettings::_createNewProfile(const std::wstring_v
GUID guid{};
LOG_IF_FAILED(CoCreateGuid(&guid));
const auto profile = ReproduceProfile(_baseLayerProfile);
const auto profile = CreateChild(_baseLayerProfile);
profile->Guid(guid);
profile->Name(winrt::hstring{ name });
return profile;
@ -642,9 +642,6 @@ Model::Profile CascadiaSettings::GetProfileByIndex(uint32_t index) const
// set a keybinding without all the required args for an action.
// Display a warning if an action didn't have a required arg.
// This will also catch other keybinding warnings, like from GH#4239.
// - TODO: GH#2548 ensure there's at least one key bound.
// Display a warning if there's _NO_ keys bound to any actions.
// That's highly irregular, and likely an indication of an error somehow.
// Arguments:
// - <none>
// Return Value:

View file

@ -26,7 +26,7 @@ Author(s):
namespace winrt::Microsoft::Terminal::Settings::Model::implementation
{
winrt::com_ptr<Profile> ReproduceProfile(const winrt::com_ptr<Profile>& parent);
winrt::com_ptr<Profile> CreateChild(const winrt::com_ptr<Profile>& parent);
class SettingsTypedDeserializationException final : public std::runtime_error
{
@ -49,7 +49,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
SettingsLoader(const std::string_view& userJSON, const std::string_view& inboxJSON);
void GenerateProfiles();
void FillBlanksInDefaultsJson();
void ApplyRuntimeInitialSettings();
void MergeInboxIntoUserProfiles();
void MergeFragmentsIntoUserProfiles();
void DisableDeletedProfiles();
@ -68,12 +68,12 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
void _parse(const OriginTag origin, const std::string_view& content, ParsedSettings& settings);
void _appendProfile(winrt::com_ptr<implementation::Profile>&& profile, ParsedSettings& settings);
std::unordered_set<std::wstring_view> ignoredNamespaces;
std::unordered_set<std::wstring_view> _ignoredNamespaces;
// We treat userSettings.profiles as an append-only array and will
// append profiles into the userSettings as necessary in this function.
// We can thus get the gsl::span of user-given profiles, by preserving the size here
// and restoring it with gsl::make_span(userSettings.profiles).subspan(userProfileCount).
size_t userProfileCount = 0;
// and restoring it with gsl::make_span(userSettings.profiles).subspan(_userProfileCount).
size_t _userProfileCount = 0;
};
struct CascadiaSettings : CascadiaSettingsT<CascadiaSettings>

View file

@ -100,15 +100,15 @@ SettingsLoader::SettingsLoader(const std::string_view& userJSON, const std::stri
if (const auto sources = userSettings.globals->DisabledProfileSources())
{
ignoredNamespaces.reserve(sources.Size());
_ignoredNamespaces.reserve(sources.Size());
for (const auto& id : sources)
{
ignoredNamespaces.emplace(id);
_ignoredNamespaces.emplace(id);
}
}
// See member description of userProfileCount.
userProfileCount = userSettings.profiles.size();
// See member description of _userProfileCount.
_userProfileCount = userSettings.profiles.size();
}
// Generate dynamic profiles and add them as parents of user profiles.
@ -118,7 +118,7 @@ void SettingsLoader::GenerateProfiles()
const auto executeGenerator = [&](const auto& generator) {
const auto generatorNamespace = generator.GetNamespace();
if (!ignoredNamespaces.count(generatorNamespace))
if (!_ignoredNamespaces.count(generatorNamespace))
{
try
{
@ -137,7 +137,7 @@ void SettingsLoader::GenerateProfiles()
// 1. The default profile is a PowerShell 7+ one, if one was generated,
// and falls back to the standard PowerShell 5 profile otherwise.
// 2. cmd.exe gets a localized name.
void SettingsLoader::FillBlanksInDefaultsJson()
void SettingsLoader::ApplyRuntimeInitialSettings()
{
// 1.
{
@ -179,7 +179,7 @@ void SettingsLoader::MergeInboxIntoUserProfiles()
}
else
{
userSettings.profiles.emplace_back(ReproduceProfile(generatedProfile));
userSettings.profiles.emplace_back(CreateChild(generatedProfile));
}
}
}
@ -212,7 +212,7 @@ void SettingsLoader::MergeFragmentsIntoUserProfiles()
{
// TODO: GUID uniqueness?
fragmentProfile->Source(source);
_appendProfile(ReproduceProfile(fragmentProfile), userSettings);
_appendProfile(CreateChild(fragmentProfile), userSettings);
}
}
@ -240,7 +240,7 @@ void SettingsLoader::MergeFragmentsIntoUserProfiles()
const auto filename = fragmentExtFolder.path().filename();
const auto& source = filename.native();
if (!ignoredNamespaces.count(std::wstring_view{ source }) && fragmentExtFolder.is_directory())
if (!_ignoredNamespaces.count(std::wstring_view{ source }) && fragmentExtFolder.is_directory())
{
parseAndLayerFragmentFiles(fragmentExtFolder.path(), winrt::hstring{ source });
}
@ -256,7 +256,7 @@ void SettingsLoader::MergeFragmentsIntoUserProfiles()
for (const auto& ext : extensions)
{
const auto packageName = ext.Package().Id().FamilyName();
if (ignoredNamespaces.count(std::wstring_view{ packageName }))
if (_ignoredNamespaces.count(std::wstring_view{ packageName }))
{
continue;
}
@ -288,8 +288,8 @@ void SettingsLoader::DisableDeletedProfiles()
auto generatedProfileIds = state->GeneratedProfiles();
bool newGeneratedProfiles = false;
// See member description of userProfileCount.
for (const auto& profile : gsl::make_span(userSettings.profiles).subspan(userProfileCount))
// See member description of _userProfileCount.
for (const auto& profile : gsl::make_span(userSettings.profiles).subspan(_userProfileCount))
{
// Let's say a user doesn't know that they need to write `"hidden": true` in
// order to prevent a profile from showing up (and a settings UI doesn't exist).
@ -486,7 +486,7 @@ void SettingsLoader::_parse(const OriginTag origin, const std::string_view& cont
void SettingsLoader::_appendProfile(winrt::com_ptr<Profile>&& profile, ParsedSettings& settings)
{
// FYI: The static_cast ensures we don't move don't move the profile into
// FYI: The static_cast ensures we don't move the profile into
// `profilesByGuid`, even though we still need it later for `profiles`.
if (settings.profilesByGuid.emplace(profile->Guid(), static_cast<const winrt::com_ptr<Profile>&>(profile)).second)
{
@ -525,7 +525,7 @@ try
if (firstTimeSetup)
{
loader.FillBlanksInDefaultsJson();
loader.ApplyRuntimeInitialSettings();
}
loader.MergeInboxIntoUserProfiles();

View file

@ -3,7 +3,6 @@
#include "pch.h"
#include "ColorScheme.h"
#include "DefaultSettings.h"
#include "../../types/inc/Utils.hpp"
#include "../../types/inc/colorTable.hpp"
#include "Utils.h"
@ -42,19 +41,12 @@ static constexpr std::array<std::string_view, 16> TableColors = {
};
ColorScheme::ColorScheme() noexcept :
_Foreground(DEFAULT_FOREGROUND),
_Background(DEFAULT_BACKGROUND),
_SelectionBackground(DEFAULT_FOREGROUND),
_CursorColor(DEFAULT_CURSOR_COLOR)
ColorScheme{ winrt::hstring{} }
{
}
ColorScheme::ColorScheme(winrt::hstring name) :
_Name{ std::move(name) },
_Foreground(DEFAULT_FOREGROUND),
_Background(DEFAULT_BACKGROUND),
_SelectionBackground(DEFAULT_FOREGROUND),
_CursorColor(DEFAULT_CURSOR_COLOR)
ColorScheme::ColorScheme(const winrt::hstring& name) noexcept :
_Name{ name }
{
const auto table = Utils::CampbellColorTable();
std::copy_n(table.data(), table.size(), _table.data());
@ -80,8 +72,8 @@ winrt::com_ptr<ColorScheme> ColorScheme::Copy() const
// - Returns nullptr for invalid JSON.
winrt::com_ptr<ColorScheme> ColorScheme::FromJson(const Json::Value& json)
{
auto result = winrt::make_self<ColorScheme>();
return result->LayerJson(json) ? result : nullptr;
auto result = winrt::make_self<ColorScheme>(uninitialized_t{});
return result->_layerJson(json) ? result : nullptr;
}
// Method Description:
@ -93,23 +85,25 @@ winrt::com_ptr<ColorScheme> ColorScheme::FromJson(const Json::Value& json)
// Arguments:
// - json: an object which should be a full serialization of a ColorScheme object.
// Return Value:
// <none>
bool ColorScheme::LayerJson(const Json::Value& json)
// - Returns true if the given JSON was valid.
bool ColorScheme::_layerJson(const Json::Value& json)
{
bool good = true;
// Required fields
auto isValid = JsonUtils::GetValueForKey(json, NameKey, _Name);
good &= JsonUtils::GetValueForKey(json, NameKey, _Name);
// Optional fields (they have defaults in ColorScheme.h)
JsonUtils::GetValueForKey(json, ForegroundKey, _Foreground);
JsonUtils::GetValueForKey(json, BackgroundKey, _Background);
JsonUtils::GetValueForKey(json, SelectionBackgroundKey, _SelectionBackground);
JsonUtils::GetValueForKey(json, CursorColorKey, _CursorColor);
// Required fields
for (unsigned int i = 0; i < TableColors.size(); ++i)
{
good &= JsonUtils::GetValueForKey(json, til::at(TableColors, i), til::at(_table, i));
isValid &= JsonUtils::GetValueForKey(json, til::at(TableColors, i), til::at(_table, i));
}
return good;
return isValid;
}
// Method Description:
@ -136,11 +130,6 @@ Json::Value ColorScheme::ToJson() const
return json;
}
const std::array<winrt::Microsoft::Terminal::Core::Color, COLOR_TABLE_SIZE>& ColorScheme::TableReference() const noexcept
{
return _table;
}
winrt::com_array<winrt::Microsoft::Terminal::Core::Color> ColorScheme::Table() const noexcept
{
return winrt::com_array<Core::Color>{ _table };

View file

@ -15,39 +15,28 @@ Author(s):
--*/
#pragma once
#include "../../inc/conattrs.hpp"
#include "inc/cppwinrt_utils.h"
#include "DefaultSettings.h"
#include "ColorScheme.g.h"
// fwdecl unittest classes
namespace SettingsModelLocalTests
{
class SettingsTests;
class ColorSchemeTests;
};
// Use this macro to quick implement both the getter and setter for a color property.
// This should only be used for color types where there's no logic in the
// getter/setter beyond just accessing/updating the value.
#define WINRT_TERMINAL_COLOR_PROPERTY(name, ...) \
public: \
Core::Color name() const noexcept { return _##name; } \
void name(const Core::Color& value) noexcept { _##name = value; } \
\
private: \
Core::Color _##name{ __VA_ARGS__ };
namespace winrt::Microsoft::Terminal::Settings::Model::implementation
{
struct ColorScheme : ColorSchemeT<ColorScheme>
{
public:
// This default constructor creates an instance with an
// uninitialized color table. Use FromJson() instead.
ColorScheme() noexcept;
// A ColorScheme constructed with uninitialized_t
// leaves _table uninitialized.
struct uninitialized_t
{
};
public:
ColorScheme() noexcept;
explicit ColorScheme(uninitialized_t) noexcept {}
explicit ColorScheme(const winrt::hstring& name) noexcept;
ColorScheme(hstring name);
com_ptr<ColorScheme> Copy() const;
hstring ToString()
@ -58,18 +47,17 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
static com_ptr<ColorScheme> FromJson(const Json::Value& json);
Json::Value ToJson() const;
const std::array<Core::Color, COLOR_TABLE_SIZE>& TableReference() const noexcept;
com_array<Core::Color> Table() const noexcept;
void SetColorTableEntry(uint8_t index, const Core::Color& value) noexcept;
WINRT_PROPERTY(winrt::hstring, Name);
WINRT_TERMINAL_COLOR_PROPERTY(Foreground); // defined in constructor
WINRT_TERMINAL_COLOR_PROPERTY(Background); // defined in constructor
WINRT_TERMINAL_COLOR_PROPERTY(SelectionBackground); // defined in constructor
WINRT_TERMINAL_COLOR_PROPERTY(CursorColor); // defined in constructor
WINRT_PROPERTY(Core::Color, Foreground, static_cast<Core::Color>(DEFAULT_FOREGROUND)); // defined in constructor
WINRT_PROPERTY(Core::Color, Background, static_cast<Core::Color>(DEFAULT_BACKGROUND)); // defined in constructor
WINRT_PROPERTY(Core::Color, SelectionBackground, static_cast<Core::Color>(DEFAULT_FOREGROUND)); // defined in constructor
WINRT_PROPERTY(Core::Color, CursorColor, static_cast<Core::Color>(DEFAULT_CURSOR_COLOR)); // defined in constructor
private:
bool LayerJson(const Json::Value& json);
bool _layerJson(const Json::Value& json);
std::array<Core::Color, COLOR_TABLE_SIZE> _table;
};

View file

@ -15,7 +15,7 @@ static constexpr std::wstring_view PACKAGED_PROFILE_ICON_EXTENSION{ L".png" };
// - name: the name of the new profile.
// Return Value:
// - A Profile, ready to be filled in
winrt::com_ptr<winrt::Microsoft::Terminal::Settings::Model::implementation::Profile> CreateDefaultProfile(const std::wstring_view& source, const std::wstring_view& name)
winrt::com_ptr<winrt::Microsoft::Terminal::Settings::Model::implementation::Profile> CreateDynamicProfile(const std::wstring_view& source, const std::wstring_view& name)
{
const winrt::guid profileGuid{ Microsoft::Console::Utils::CreateV5Uuid(TERMINAL_PROFILE_NAMESPACE_GUID,
gsl::as_bytes(gsl::make_span(name))) };

View file

@ -23,4 +23,4 @@ Author(s):
// uuidv5 properties: name format is UTF-16LE bytes
static constexpr GUID TERMINAL_PROFILE_NAMESPACE_GUID = { 0x2bde4a90, 0xd05f, 0x401c, { 0x94, 0x92, 0xe4, 0x8, 0x84, 0xea, 0xd1, 0xd8 } };
winrt::com_ptr<winrt::Microsoft::Terminal::Settings::Model::implementation::Profile> CreateDefaultProfile(const std::wstring_view& source, const std::wstring_view& name);
winrt::com_ptr<winrt::Microsoft::Terminal::Settings::Model::implementation::Profile> CreateDynamicProfile(const std::wstring_view& source, const std::wstring_view& name);

View file

@ -227,9 +227,6 @@ void GlobalAppSettings::LayerJson(const Json::Value& json)
JsonUtils::GetValueForKey(json, AlwaysShowTrayIconKey, _AlwaysShowTrayIcon);
JsonUtils::GetValueForKey(json, DisabledProfileSourcesKey, _DisabledProfileSources);
// This is a helper lambda to get the keybindings and commands out of both
// and array of objects. We'll use this twice, once on the legacy
// `keybindings` key, and again on the newer `bindings` key.
static constexpr std::array bindingsKeys{ LegacyKeybindingsKey, ActionsKey };
for (const auto& jsonKey : bindingsKeys)
{

View file

@ -308,7 +308,7 @@ void PowershellCoreProfileGenerator::GenerateProfiles(std::vector<winrt::com_ptr
for (const auto& psI : psInstances)
{
const auto name = psI.Name();
auto profile{ CreateDefaultProfile(PowershellCoreGeneratorNamespace, name) };
auto profile{ CreateDynamicProfile(PowershellCoreGeneratorNamespace, name) };
profile->Commandline(winrt::hstring{ psI.executablePath.native() });
profile->StartingDirectory(winrt::hstring{ DEFAULT_STARTING_DIRECTORY });
profile->DefaultAppearance().ColorSchemeName(L"Campbell");

View file

@ -36,7 +36,7 @@ std::wstring_view WslDistroGenerator::GetNamespace() const noexcept
static winrt::com_ptr<implementation::Profile> makeProfile(const std::wstring& distName)
{
const auto WSLDistro{ CreateDefaultProfile(WslGeneratorNamespace, distName) };
const auto WSLDistro{ CreateDynamicProfile(WslGeneratorNamespace, distName) };
WSLDistro->Commandline(winrt::hstring{ L"wsl.exe -d " + distName });
WSLDistro->DefaultAppearance().ColorSchemeName(L"Campbell");
WSLDistro->StartingDirectory(winrt::hstring{ DEFAULT_STARTING_DIRECTORY });

View file

@ -70,7 +70,7 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned"
{
}
operator COLORREF() const noexcept
constexpr operator COLORREF() const noexcept
{
return static_cast<COLORREF>(abgr & 0x00FFFFFFu);
}
@ -147,14 +147,9 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned"
{
}
operator winrt::Windows::UI::Color() const
constexpr operator winrt::Windows::UI::Color() const
{
winrt::Windows::UI::Color ret;
ret.R = r;
ret.G = g;
ret.B = b;
ret.A = a;
return ret;
return { a, r, g, b };
}
#endif
@ -164,14 +159,9 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned"
{
}
operator winrt::Microsoft::Terminal::Core::Color() const noexcept
constexpr operator winrt::Microsoft::Terminal::Core::Color() const noexcept
{
winrt::Microsoft::Terminal::Core::Color ret;
ret.R = r;
ret.G = g;
ret.B = b;
ret.A = a;
return ret;
return { r, g, b, a };
}
#endif