mirror of
https://github.com/microsoft/terminal.git
synced 2026-04-06 14:19:45 +00:00
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:
committed by
Dustin L. Howett (MSFT)
parent
6708556079
commit
5d17557edf
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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++)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user