Add a schema reference to the userDefaults and patch one into user data (#2803)

* Add a schema reference to the userDefaults and patch one into existing files
* Only add the , if there's another object in there.
This commit is contained in:
Dustin L. Howett (MSFT) 2019-09-18 18:37:23 -07:00 committed by GitHub
parent 4b439cf290
commit 5a57c5a6c9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 47 additions and 0 deletions

View file

@ -87,6 +87,7 @@ private:
void _ParseJsonString(std::string_view fileData, const bool isDefaultSettings);
static const Json::Value& _GetProfilesJsonObject(const Json::Value& json);
static const Json::Value& _GetDisabledProfileSourcesJsonObject(const Json::Value& json);
bool _PrependSchemaDirective();
bool _AppendDynamicProfilesToUserSettings();
void _LoadDynamicProfiles();

View file

@ -27,6 +27,7 @@ static constexpr std::wstring_view UnpackagedSettingsFolderName{ L"Microsoft\\Wi
static constexpr std::wstring_view DefaultsFilename{ L"defaults.json" };
static constexpr std::string_view SchemaKey{ "$schema" };
static constexpr std::string_view ProfilesKey{ "profiles" };
static constexpr std::string_view KeybindingsKey{ "keybindings" };
static constexpr std::string_view GlobalsKey{ "globals" };
@ -36,6 +37,8 @@ static constexpr std::string_view DisabledProfileSourcesKey{ "disabledProfileSou
static constexpr std::string_view Utf8Bom{ u8"\uFEFF" };
static constexpr std::string_view DefaultProfilesIndentation{ " " };
static constexpr std::string_view SettingsSchemaFragment{ "\n"
R"( "$schema": "https://aka.ms/terminal-profiles-schema")" };
// Method Description:
// - Creates a CascadiaSettings from whatever's saved on disk, or instantiates
@ -85,6 +88,16 @@ std::unique_ptr<CascadiaSettings> CascadiaSettings::LoadAll()
// that need to be inserted into their user settings file.
needToWriteFile = resultPtr->_AppendDynamicProfilesToUserSettings() || needToWriteFile;
if (needToWriteFile)
{
// For safety's sake, we need to re-parse the JSON document to ensure that
// all future patches are applied with updated object offsets.
resultPtr->_ParseJsonString(resultPtr->_userSettingsString, false);
}
// Make sure there's a $schema at the top of the file.
needToWriteFile = resultPtr->_PrependSchemaDirective() || needToWriteFile;
// TODO:GH#2721 If powershell core is installed, we need to set that to the
// default profile, but only when the settings file was newly created. We'll
// re-write the segment of the user settings for "default profile" to have
@ -241,11 +254,41 @@ void CascadiaSettings::SaveAll() const
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.
// - Assumes that the body of the root object is at an indentation of 4 spaces, and
// therefore each member should be indented 4 spaces. If the user's settings
// have a different indentation, we'll still insert valid json, it'll just be
// indented incorrectly.
// Arguments:
// - <none>
// Return Value:
// - true iff we've made changes to the _userSettingsString that should be persisted.
bool CascadiaSettings::_PrependSchemaDirective()
{
if (_userSettings.isMember(JsonKey(SchemaKey)))
{
return false;
}
// start points at the opening { for the root object.
auto offset = _userSettings.getOffsetStart() + 1;
_userSettingsString.insert(offset, SettingsSchemaFragment);
offset += SettingsSchemaFragment.size();
if (_userSettings.size() > 0)
{
_userSettingsString.insert(offset, ",");
}
return true;
}
// Method Description:
// - Finds all the dynamic profiles we've generated that _don't_ exist in the
// user's settings. Generates a minimal blob of json for them, and inserts
@ -276,6 +319,7 @@ bool CascadiaSettings::_AppendDynamicProfilesToUserSettings()
Json::StreamWriterBuilder wbuilder;
// Use 4 spaces to indent instead of \t
wbuilder.settings_["indentation"] = " ";
wbuilder.settings_["enableYAMLCompatibility"] = true; // suppress spaces around colons
auto isInJsonObj = [](const auto& profile, const auto& json) {
for (auto profileJson : _GetProfilesJsonObject(json))

View file

@ -2,6 +2,8 @@
// For documentation on these settings, see: https://aka.ms/terminal-documentation
{
"$schema": "https://aka.ms/terminal-profiles-schema",
"defaultProfile": "{61c54bbd-c2c6-5271-96e7-009a87ff44bf}",
"profiles":