Add a warning when a profile has an unknown color scheme (#3033)

Add a warning when the user sets their colorScheme to a scheme that doesn't exist. When that occurs, we'll set their color table to the campbell scheme, to prevent it from being just entirely black.

This commit also switches scheme storage to a map keyed on name.

Closes #2547
This commit is contained in:
Mike Griese
2019-10-15 00:02:52 -05:00
committed by Dustin L. Howett (MSFT)
parent 6708556079
commit 5d17557edf
13 changed files with 249 additions and 158 deletions

View File

@@ -169,7 +169,7 @@ namespace TerminalAppLocalTests
"background": "#050505"
})" };
const std::string scheme3String{ R"({
// "name": "scheme3",
// by not providing a name, the scheme will have the name ""
"foreground": "#060606",
"background": "#070707"
})" };
@@ -188,47 +188,85 @@ namespace TerminalAppLocalTests
VERIFY_IS_NULL(settings._FindMatchingColorScheme(scheme3Json));
settings._LayerOrCreateColorScheme(scheme0Json);
VERIFY_ARE_EQUAL(1u, settings._globals.GetColorSchemes().size());
VERIFY_IS_NOT_NULL(settings._FindMatchingColorScheme(scheme0Json));
VERIFY_IS_NULL(settings._FindMatchingColorScheme(scheme1Json));
VERIFY_IS_NOT_NULL(settings._FindMatchingColorScheme(scheme2Json));
VERIFY_IS_NULL(settings._FindMatchingColorScheme(scheme3Json));
VERIFY_ARE_EQUAL(ARGB(0, 0, 0, 0), settings._globals.GetColorSchemes().at(0)._defaultForeground);
VERIFY_ARE_EQUAL(ARGB(0, 1, 1, 1), settings._globals.GetColorSchemes().at(0)._defaultBackground);
{
for (auto& kv : settings._globals._colorSchemes)
{
Log::Comment(NoThrowString().Format(
L"kv:%s->%s", kv.first.data(), kv.second.GetName().data()));
}
VERIFY_ARE_EQUAL(1u, settings._globals.GetColorSchemes().size());
VERIFY_IS_TRUE(settings._globals._colorSchemes.find(L"scheme0") != settings._globals._colorSchemes.end());
auto scheme0 = settings._globals._colorSchemes.find(L"scheme0")->second;
VERIFY_IS_NOT_NULL(settings._FindMatchingColorScheme(scheme0Json));
VERIFY_IS_NULL(settings._FindMatchingColorScheme(scheme1Json));
VERIFY_IS_NOT_NULL(settings._FindMatchingColorScheme(scheme2Json));
VERIFY_IS_NULL(settings._FindMatchingColorScheme(scheme3Json));
VERIFY_ARE_EQUAL(ARGB(0, 0, 0, 0), scheme0._defaultForeground);
VERIFY_ARE_EQUAL(ARGB(0, 1, 1, 1), scheme0._defaultBackground);
}
settings._LayerOrCreateColorScheme(scheme1Json);
VERIFY_ARE_EQUAL(2u, settings._globals.GetColorSchemes().size());
VERIFY_IS_NOT_NULL(settings._FindMatchingColorScheme(scheme0Json));
VERIFY_IS_NOT_NULL(settings._FindMatchingColorScheme(scheme1Json));
VERIFY_IS_NOT_NULL(settings._FindMatchingColorScheme(scheme2Json));
VERIFY_IS_NULL(settings._FindMatchingColorScheme(scheme3Json));
VERIFY_ARE_EQUAL(ARGB(0, 0, 0, 0), settings._globals.GetColorSchemes().at(0)._defaultForeground);
VERIFY_ARE_EQUAL(ARGB(0, 1, 1, 1), settings._globals.GetColorSchemes().at(0)._defaultBackground);
VERIFY_ARE_EQUAL(ARGB(0, 2, 2, 2), settings._globals.GetColorSchemes().at(1)._defaultForeground);
VERIFY_ARE_EQUAL(ARGB(0, 3, 3, 3), settings._globals.GetColorSchemes().at(1)._defaultBackground);
{
VERIFY_ARE_EQUAL(2u, settings._globals.GetColorSchemes().size());
VERIFY_IS_TRUE(settings._globals._colorSchemes.find(L"scheme0") != settings._globals._colorSchemes.end());
auto scheme0 = settings._globals._colorSchemes.find(L"scheme0")->second;
VERIFY_IS_TRUE(settings._globals._colorSchemes.find(L"scheme1") != settings._globals._colorSchemes.end());
auto scheme1 = settings._globals._colorSchemes.find(L"scheme1")->second;
VERIFY_IS_NOT_NULL(settings._FindMatchingColorScheme(scheme0Json));
VERIFY_IS_NOT_NULL(settings._FindMatchingColorScheme(scheme1Json));
VERIFY_IS_NOT_NULL(settings._FindMatchingColorScheme(scheme2Json));
VERIFY_IS_NULL(settings._FindMatchingColorScheme(scheme3Json));
VERIFY_ARE_EQUAL(ARGB(0, 0, 0, 0), scheme0._defaultForeground);
VERIFY_ARE_EQUAL(ARGB(0, 1, 1, 1), scheme0._defaultBackground);
VERIFY_ARE_EQUAL(ARGB(0, 2, 2, 2), scheme1._defaultForeground);
VERIFY_ARE_EQUAL(ARGB(0, 3, 3, 3), scheme1._defaultBackground);
}
settings._LayerOrCreateColorScheme(scheme2Json);
VERIFY_ARE_EQUAL(2u, settings._globals.GetColorSchemes().size());
VERIFY_IS_NOT_NULL(settings._FindMatchingColorScheme(scheme0Json));
VERIFY_IS_NOT_NULL(settings._FindMatchingColorScheme(scheme1Json));
VERIFY_IS_NOT_NULL(settings._FindMatchingColorScheme(scheme2Json));
VERIFY_IS_NULL(settings._FindMatchingColorScheme(scheme3Json));
VERIFY_ARE_EQUAL(ARGB(0, 4, 4, 4), settings._globals.GetColorSchemes().at(0)._defaultForeground);
VERIFY_ARE_EQUAL(ARGB(0, 5, 5, 5), settings._globals.GetColorSchemes().at(0)._defaultBackground);
VERIFY_ARE_EQUAL(ARGB(0, 2, 2, 2), settings._globals.GetColorSchemes().at(1)._defaultForeground);
VERIFY_ARE_EQUAL(ARGB(0, 3, 3, 3), settings._globals.GetColorSchemes().at(1)._defaultBackground);
{
VERIFY_ARE_EQUAL(2u, settings._globals.GetColorSchemes().size());
VERIFY_IS_TRUE(settings._globals._colorSchemes.find(L"scheme0") != settings._globals._colorSchemes.end());
auto scheme0 = settings._globals._colorSchemes.find(L"scheme0")->second;
VERIFY_IS_TRUE(settings._globals._colorSchemes.find(L"scheme1") != settings._globals._colorSchemes.end());
auto scheme1 = settings._globals._colorSchemes.find(L"scheme1")->second;
VERIFY_IS_NOT_NULL(settings._FindMatchingColorScheme(scheme0Json));
VERIFY_IS_NOT_NULL(settings._FindMatchingColorScheme(scheme1Json));
VERIFY_IS_NOT_NULL(settings._FindMatchingColorScheme(scheme2Json));
VERIFY_IS_NULL(settings._FindMatchingColorScheme(scheme3Json));
VERIFY_ARE_EQUAL(ARGB(0, 4, 4, 4), scheme0._defaultForeground);
VERIFY_ARE_EQUAL(ARGB(0, 5, 5, 5), scheme0._defaultBackground);
VERIFY_ARE_EQUAL(ARGB(0, 2, 2, 2), scheme1._defaultForeground);
VERIFY_ARE_EQUAL(ARGB(0, 3, 3, 3), scheme1._defaultBackground);
}
settings._LayerOrCreateColorScheme(scheme3Json);
VERIFY_ARE_EQUAL(3u, settings._globals.GetColorSchemes().size());
VERIFY_IS_NOT_NULL(settings._FindMatchingColorScheme(scheme0Json));
VERIFY_IS_NOT_NULL(settings._FindMatchingColorScheme(scheme1Json));
VERIFY_IS_NOT_NULL(settings._FindMatchingColorScheme(scheme2Json));
VERIFY_IS_NULL(settings._FindMatchingColorScheme(scheme3Json));
VERIFY_ARE_EQUAL(ARGB(0, 4, 4, 4), settings._globals.GetColorSchemes().at(0)._defaultForeground);
VERIFY_ARE_EQUAL(ARGB(0, 5, 5, 5), settings._globals.GetColorSchemes().at(0)._defaultBackground);
VERIFY_ARE_EQUAL(ARGB(0, 2, 2, 2), settings._globals.GetColorSchemes().at(1)._defaultForeground);
VERIFY_ARE_EQUAL(ARGB(0, 3, 3, 3), settings._globals.GetColorSchemes().at(1)._defaultBackground);
VERIFY_ARE_EQUAL(ARGB(0, 6, 6, 6), settings._globals.GetColorSchemes().at(2)._defaultForeground);
VERIFY_ARE_EQUAL(ARGB(0, 7, 7, 7), settings._globals.GetColorSchemes().at(2)._defaultBackground);
{
VERIFY_ARE_EQUAL(3u, settings._globals.GetColorSchemes().size());
VERIFY_IS_TRUE(settings._globals._colorSchemes.find(L"scheme0") != settings._globals._colorSchemes.end());
auto scheme0 = settings._globals._colorSchemes.find(L"scheme0")->second;
VERIFY_IS_TRUE(settings._globals._colorSchemes.find(L"scheme1") != settings._globals._colorSchemes.end());
auto scheme1 = settings._globals._colorSchemes.find(L"scheme1")->second;
VERIFY_IS_TRUE(settings._globals._colorSchemes.find(L"") != settings._globals._colorSchemes.end());
auto scheme2 = settings._globals._colorSchemes.find(L"")->second;
VERIFY_IS_NOT_NULL(settings._FindMatchingColorScheme(scheme0Json));
VERIFY_IS_NOT_NULL(settings._FindMatchingColorScheme(scheme1Json));
VERIFY_IS_NOT_NULL(settings._FindMatchingColorScheme(scheme2Json));
VERIFY_IS_NULL(settings._FindMatchingColorScheme(scheme3Json));
VERIFY_ARE_EQUAL(ARGB(0, 4, 4, 4), scheme0._defaultForeground);
VERIFY_ARE_EQUAL(ARGB(0, 5, 5, 5), scheme0._defaultBackground);
VERIFY_ARE_EQUAL(ARGB(0, 2, 2, 2), scheme1._defaultForeground);
VERIFY_ARE_EQUAL(ARGB(0, 3, 3, 3), scheme1._defaultBackground);
VERIFY_ARE_EQUAL(ARGB(0, 6, 6, 6), scheme2._defaultForeground);
VERIFY_ARE_EQUAL(ARGB(0, 7, 7, 7), scheme2._defaultBackground);
}
}
}

View File

@@ -48,6 +48,7 @@ namespace TerminalAppLocalTests
TEST_METHOD(TestLayeringNameOnlyProfiles);
TEST_METHOD(TestExplodingNameOnlyProfiles);
TEST_METHOD(TestHideAllProfiles);
TEST_METHOD(TestInvalidColorSchemeName);
TEST_METHOD(TestLayerGlobalsOnRoot);
@@ -395,9 +396,10 @@ namespace TerminalAppLocalTests
settings->_ValidateSettings();
VERIFY_ARE_EQUAL(2u, settings->_warnings.size());
VERIFY_ARE_EQUAL(3u, settings->_warnings.size());
VERIFY_ARE_EQUAL(::TerminalApp::SettingsLoadWarnings::DuplicateProfile, settings->_warnings.at(0));
VERIFY_ARE_EQUAL(::TerminalApp::SettingsLoadWarnings::MissingDefaultProfile, settings->_warnings.at(1));
VERIFY_ARE_EQUAL(::TerminalApp::SettingsLoadWarnings::UnknownColorScheme, settings->_warnings.at(2));
VERIFY_ARE_EQUAL(3u, settings->_profiles.size());
VERIFY_ARE_EQUAL(settings->_globals.GetDefaultProfile(), settings->_profiles.at(0).GetGuid());
@@ -795,6 +797,9 @@ namespace TerminalAppLocalTests
{
"name" : "profile1"
}
],
"schemes": [
{ "name": "Campbell" }
]
})" };
@@ -1194,6 +1199,65 @@ namespace TerminalAppLocalTests
}
}
void SettingsTests::TestInvalidColorSchemeName()
{
Log::Comment(NoThrowString().Format(
L"Ensure that setting a profile's scheme to a non-existent scheme causes a warning."));
const std::string settings0String{ R"(
{
"profiles": [
{
"name" : "profile0",
"colorScheme": "schemeOne"
},
{
"name" : "profile1",
"colorScheme": "InvalidSchemeName"
},
{
"name" : "profile2"
// Will use the Profile default value, "Campbell"
}
],
"schemes": [
{
"name": "schemeOne",
"foreground": "#111111"
},
{
"name": "schemeTwo",
"foreground": "#222222"
}
]
})" };
VerifyParseSucceeded(settings0String);
CascadiaSettings settings;
settings._ParseJsonString(settings0String, false);
settings.LayerJson(settings._userSettings);
VERIFY_ARE_EQUAL(3u, settings._profiles.size());
VERIFY_ARE_EQUAL(2u, settings._globals._colorSchemes.size());
VERIFY_ARE_EQUAL(L"schemeOne", settings._profiles.at(0)._schemeName.value());
VERIFY_ARE_EQUAL(L"InvalidSchemeName", settings._profiles.at(1)._schemeName.value());
VERIFY_ARE_EQUAL(L"Campbell", settings._profiles.at(2)._schemeName.value());
settings._ValidateAllSchemesExist();
VERIFY_ARE_EQUAL(1u, settings._warnings.size());
VERIFY_ARE_EQUAL(::TerminalApp::SettingsLoadWarnings::UnknownColorScheme, settings._warnings.at(0));
VERIFY_ARE_EQUAL(3u, settings._profiles.size());
VERIFY_ARE_EQUAL(2u, settings._globals._colorSchemes.size());
VERIFY_ARE_EQUAL(L"schemeOne", settings._profiles.at(0)._schemeName.value());
VERIFY_ARE_EQUAL(L"Campbell", settings._profiles.at(1)._schemeName.value());
VERIFY_ARE_EQUAL(L"Campbell", settings._profiles.at(2)._schemeName.value());
}
void SettingsTests::TestLayerGlobalsOnRoot()
{
// Test for microsoft/terminal#2906. We added the ability for the root
@@ -1302,5 +1366,4 @@ namespace TerminalAppLocalTests
VERIFY_ARE_EQUAL(guid3, settings._globals._defaultProfile);
}
}
}

View File

@@ -26,9 +26,10 @@ namespace winrt
// !!! IMPORTANT !!!
// Make sure that these keys are in the same order as the
// SettingsLoadWarnings/Errors enum is!
static const std::array<std::wstring_view, 2> settingsLoadWarningsLabels {
static const std::array<std::wstring_view, 3> settingsLoadWarningsLabels {
L"MissingDefaultProfileText",
L"DuplicateProfileText"
L"DuplicateProfileText",
L"UnknownColorSchemeText"
};
static const std::array<std::wstring_view, 2> settingsLoadErrorsLabels {
L"NoProfilesText",

View File

@@ -174,9 +174,10 @@ void CascadiaSettings::_ValidateSettings()
_ValidateNoDuplicateProfiles();
_ValidateDefaultProfileExists();
// TODO:GH#2547 ensure that all the profile's color scheme names are
// Ensure that all the profile's color scheme names are
// actually the names of schemes we've parsed. If the scheme doesn't exist,
// just use the hardcoded defaults
_ValidateAllSchemesExist();
// 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
@@ -366,3 +367,36 @@ void CascadiaSettings::_RemoveHiddenProfiles()
throw ::TerminalApp::SettingsException(::TerminalApp::SettingsLoadErrors::AllProfilesHidden);
}
}
// Method Description:
// - Ensures that every profile has a valid "color scheme" set. If any profile
// has a colorScheme set to a value which is _not_ the name of an actual color
// scheme, we'll set the color table of the profile to something reasonable.
// Arguments:
// - <none>
// Return Value:
// - <none>
// - Appends a SettingsLoadWarnings::UnknownColorScheme to our list of warnings if
// we find any such duplicate.
void CascadiaSettings::_ValidateAllSchemesExist()
{
bool foundInvalidScheme = false;
for (auto& profile : _profiles)
{
auto schemeName = profile.GetSchemeName();
if (schemeName.has_value())
{
const auto found = _globals.GetColorSchemes().find(schemeName.value());
if (found == _globals.GetColorSchemes().end())
{
profile.SetColorScheme({ L"Campbell" });
foundInvalidScheme = true;
}
}
}
if (foundInvalidScheme)
{
_warnings.push_back(::TerminalApp::SettingsLoadWarnings::UnknownColorScheme);
}
}

View File

@@ -48,7 +48,6 @@ public:
static std::unique_ptr<CascadiaSettings> LoadDefaults();
static std::unique_ptr<CascadiaSettings> LoadAll();
void SaveAll() const;
winrt::Microsoft::Terminal::Settings::TerminalSettings MakeSettings(std::optional<GUID> profileGuid) const;
@@ -58,7 +57,6 @@ public:
winrt::TerminalApp::AppKeyBindings GetKeybindings() const noexcept;
Json::Value ToJson() const;
static std::unique_ptr<CascadiaSettings> FromJson(const Json::Value& json);
void LayerJson(const Json::Value& json);
@@ -104,6 +102,7 @@ private:
void _ValidateNoDuplicateProfiles();
void _ReorderProfilesToMatchUserSettingsOrder();
void _RemoveHiddenProfiles();
void _ValidateAllSchemesExist();
friend class TerminalAppLocalTests::SettingsTests;
friend class TerminalAppLocalTests::ProfileTests;

View File

@@ -240,26 +240,6 @@ void CascadiaSettings::_ParseJsonString(std::string_view fileData, const bool is
}
}
// Method Description:
// - Serialize this settings structure, and save it to a file. The location of
// the file changes depending whether we're running as a packaged
// application or not.
// Arguments:
// - <none>
// Return Value:
// - <none>
void CascadiaSettings::SaveAll() const
{
const auto json = ToJson();
Json::StreamWriterBuilder wbuilder;
// Use 4 spaces to indent instead of \t
wbuilder.settings_["indentation"] = " ";
wbuilder.settings_["enableYAMLCompatibility"] = true; // suppress spaces around colons
const auto serializedString = Json::writeString(wbuilder, json);
_WriteSettings(serializedString);
}
// Method Description:
// - Determines whether the user's settings file is missing a schema directive
// and, if so, inserts one.
@@ -402,36 +382,6 @@ bool CascadiaSettings::_AppendDynamicProfilesToUserSettings()
return changedFile;
}
// Method Description:
// - Serialize this object to a JsonObject.
// Arguments:
// - <none>
// Return Value:
// - a JsonObject which is an equivalent serialization of this object.
Json::Value CascadiaSettings::ToJson() const
{
Json::Value root;
Json::Value profilesArray;
for (const auto& profile : _profiles)
{
profilesArray.append(profile.ToJson());
}
Json::Value schemesArray;
const auto& colorSchemes = _globals.GetColorSchemes();
for (auto& scheme : colorSchemes)
{
schemesArray.append(scheme.ToJson());
}
root[GlobalsKey.data()] = _globals.ToJson();
root[ProfilesKey.data()] = profilesArray;
root[SchemesKey.data()] = schemesArray;
return root;
}
// Method Description:
// - Create a new instance of this class from a serialized JsonObject.
// Arguments:
@@ -568,8 +518,7 @@ void CascadiaSettings::_LayerOrCreateColorScheme(const Json::Value& schemeJson)
}
else
{
auto scheme = ColorScheme::FromJson(schemeJson);
_globals.GetColorSchemes().emplace_back(scheme);
_globals.AddColorScheme(ColorScheme::FromJson(schemeJson));
}
}
@@ -588,13 +537,13 @@ ColorScheme* CascadiaSettings::_FindMatchingColorScheme(const Json::Value& schem
{
for (auto& scheme : _globals.GetColorSchemes())
{
if (scheme.ShouldBeLayered(schemeJson))
if (scheme.second.ShouldBeLayered(schemeJson))
{
// HERE BE DRAGONS: Returning a pointer to a type in the vector is
// maybe not the _safest_ thing, but we have a mind to make Profile
// and ColorScheme winrt types in the future, so this will be safer
// then.
return &scheme;
return &scheme.second;
}
}
return nullptr;

View File

@@ -49,12 +49,12 @@ GlobalAppSettings::~GlobalAppSettings()
{
}
const std::vector<ColorScheme>& GlobalAppSettings::GetColorSchemes() const noexcept
std::unordered_map<std::wstring, ColorScheme>& GlobalAppSettings::GetColorSchemes() noexcept
{
return _colorSchemes;
}
std::vector<ColorScheme>& GlobalAppSettings::GetColorSchemes() noexcept
const std::unordered_map<std::wstring, ColorScheme>& GlobalAppSettings::GetColorSchemes() const noexcept
{
return _colorSchemes;
}
@@ -280,3 +280,15 @@ std::wstring_view GlobalAppSettings::_SerializeTheme(const ElementTheme theme) n
return SystemThemeValue;
}
}
// Method Description:
// - Adds the given colorscheme to our map of schemes, using its name as the key.
// Arguments:
// - scheme: the color scheme to add
// Return Value:
// - <none>
void GlobalAppSettings::AddColorScheme(ColorScheme scheme)
{
std::wstring name{ scheme.GetName() };
_colorSchemes[name] = std::move(scheme);
}

View File

@@ -21,6 +21,7 @@ Author(s):
namespace TerminalAppLocalTests
{
class SettingsTests;
class ColorSchemeTests;
};
namespace TerminalApp
@@ -34,8 +35,10 @@ public:
GlobalAppSettings();
~GlobalAppSettings();
const std::vector<ColorScheme>& GetColorSchemes() const noexcept;
std::vector<ColorScheme>& GetColorSchemes() noexcept;
std::unordered_map<std::wstring, ColorScheme>& GetColorSchemes() noexcept;
const std::unordered_map<std::wstring, ColorScheme>& GetColorSchemes() const noexcept;
void AddColorScheme(ColorScheme scheme);
void SetDefaultProfile(const GUID defaultProfile) noexcept;
GUID GetDefaultProfile() const noexcept;
@@ -70,7 +73,7 @@ private:
GUID _defaultProfile;
winrt::com_ptr<winrt::TerminalApp::implementation::AppKeyBindings> _keybindings;
std::vector<ColorScheme> _colorSchemes;
std::unordered_map<std::wstring, ColorScheme> _colorSchemes;
int32_t _initialRows;
int32_t _initialCols;
@@ -88,4 +91,5 @@ private:
static std::wstring_view _SerializeTheme(const winrt::Windows::UI::Xaml::ElementTheme theme) noexcept;
friend class TerminalAppLocalTests::SettingsTests;
friend class TerminalAppLocalTests::ColorSchemeTests;
};

View File

@@ -141,27 +141,6 @@ void Profile::SetSource(std::wstring_view sourceNamespace) noexcept
_source = sourceNamespace;
}
// Function Description:
// - Searches a list of color schemes to find one matching the given name. Will
//return the first match in the list, if the list has multiple schemes with the same name.
// Arguments:
// - schemes: a list of schemes to search
// - schemeName: the name of the sceme to look for
// Return Value:
// - a non-ownership pointer to the matching scheme if we found one, else nullptr
const ColorScheme* _FindScheme(const std::vector<ColorScheme>& schemes,
const std::wstring& schemeName)
{
for (auto& scheme : schemes)
{
if (scheme.GetName() == schemeName)
{
return &scheme;
}
}
return nullptr;
}
// Method Description:
// - Create a TerminalSettings from this object. Apply our settings, as well as
// any colors from our color scheme, if we have one.
@@ -169,7 +148,7 @@ const ColorScheme* _FindScheme(const std::vector<ColorScheme>& schemes,
// - schemes: a list of schemes to look for our color scheme in, if we have one.
// Return Value:
// - a new TerminalSettings object with our settings in it.
TerminalSettings Profile::CreateTerminalSettings(const std::vector<ColorScheme>& schemes) const
TerminalSettings Profile::CreateTerminalSettings(const std::unordered_map<std::wstring, ColorScheme>& schemes) const
{
TerminalSettings terminalSettings{};
@@ -208,10 +187,10 @@ TerminalSettings Profile::CreateTerminalSettings(const std::vector<ColorScheme>&
if (_schemeName)
{
const ColorScheme* const matchingScheme = _FindScheme(schemes, _schemeName.value());
if (matchingScheme)
const auto found = schemes.find(_schemeName.value());
if (found != schemes.end())
{
matchingScheme->ApplyScheme(terminalSettings);
found->second.ApplyScheme(terminalSettings);
}
}
if (_defaultForeground)
@@ -714,6 +693,11 @@ void Profile::SetColorScheme(std::optional<std::wstring> schemeName) noexcept
_schemeName = std::move(schemeName);
}
std::optional<std::wstring>& Profile::GetSchemeName() noexcept
{
return _schemeName;
}
void Profile::SetAcrylicOpacity(double opacity) noexcept
{
_acrylicTransparency = opacity;

View File

@@ -45,7 +45,7 @@ public:
~Profile();
winrt::Microsoft::Terminal::Settings::TerminalSettings CreateTerminalSettings(const std::vector<::TerminalApp::ColorScheme>& schemes) const;
winrt::Microsoft::Terminal::Settings::TerminalSettings CreateTerminalSettings(const std::unordered_map<std::wstring, ColorScheme>& schemes) const;
Json::Value ToJson() const;
Json::Value DiffToJson(const Profile& other) const;
@@ -65,6 +65,7 @@ public:
void SetFontFace(std::wstring fontFace) noexcept;
void SetColorScheme(std::optional<std::wstring> schemeName) noexcept;
std::optional<std::wstring>& GetSchemeName() noexcept;
void SetTabTitle(std::wstring tabTitle) noexcept;
void SetAcrylicOpacity(double opacity) noexcept;
void SetCommandline(std::wstring cmdline) noexcept;

View File

@@ -1,17 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
@@ -26,36 +26,36 @@
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
@@ -127,6 +127,10 @@
</data>
<data name="DuplicateProfileText" xml:space="preserve">
<value>Found multiple profiles with the same GUID in your settings file - ignoring duplicates. Make sure each profile's GUID is unique.
</value>
</data>
<data name="UnknownColorSchemeText" xml:space="preserve">
<value>Found a profile with an invalid "colorScheme". Defaulting that profile to the default colors. Make sure that when setting a "colorScheme", the value matches the "name" of a color scheme in the "schemes" list.
</value>
</data>
<data name="NoProfilesText" xml:space="preserve">
@@ -206,4 +210,4 @@ Temporarily using the Windows Terminal default settings.
<data name="CloseWindowWarningTitle" xml:space="preserve">
<value>Do you want to close all tabs?</value>
</data>
</root>
</root>

View File

@@ -22,7 +22,8 @@ namespace TerminalApp
enum class SettingsLoadWarnings : uint32_t
{
MissingDefaultProfile = 0,
DuplicateProfile = 1
DuplicateProfile = 1,
UnknownColorScheme = 2
};
// SettingsLoadWarnings are scenarios where the settings had invalid state

View File

@@ -98,6 +98,7 @@ namespace TerminalAppUnitTests
std::array<COLORREF, COLOR_TABLE_SIZE> expectedCampbellTable;
auto campbellSpan = gsl::span<COLORREF>(&expectedCampbellTable[0], gsl::narrow<ptrdiff_t>(COLOR_TABLE_SIZE));
Utils::InitializeCampbellColorTable(campbellSpan);
Utils::SetColorTableAlpha(campbellSpan, 0);
for (size_t i = 0; i < expectedCampbellTable.size(); i++)
{