Switch to jsoncpp as our json library (#1005)

Switch to using jsoncpp as our json library. This lets us pretty-print the json file by default, and lets users place comments in the json file.

We will now only re-write the file when the actual logical structure of the json object changes, not only when the serialization changes.

Unfortunately, this will remove any existing ordering of profiles, and make the order random. We don't terribly care though, because when #754 lands, this will be less painful.

It also introduces a top-level globals object to hold all the global properties, including keybindings. Existing profiles should gracefully upgrade.
This commit is contained in:
Mike Griese 2019-06-04 16:55:27 -05:00 committed by GitHub
parent 69e88cd921
commit 8a69be0cc7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
25 changed files with 8681 additions and 637 deletions

49
NOTICE.md Normal file
View File

@ -0,0 +1,49 @@
# NOTICES AND INFORMATION
Do Not Translate or Localize
This software incorporates material from third parties. Microsoft makes certain
open source code available at http://3rdpartysource.microsoft.com, or you may
send a check or money order for US $5.00, including the product name, the open
source component name, and version number, to:
```
Source Code Compliance Team
Microsoft Corporation
One Microsoft Way
Redmond, WA 98052
USA
```
Notwithstanding any other terms, you may reverse engineer this software to the
extent required to debug changes to any libraries licensed under the GNU Lesser
General Public License.
## jsoncpp
**Source**: https://github.com/open-source-parsers/jsoncpp
### License
```
Copyright (c) 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use, copy,
modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
```

7
dep/jsoncpp/README.md Normal file
View File

@ -0,0 +1,7 @@
# jsoncpp
[Amalgamated](https://github.com/open-source-parsers/jsoncpp/wiki/Amalgamated)
from source commit
[ddabf50](https://github.com/open-source-parsers/jsoncpp/commit/ddabf50f72cf369bf652a95c4d9fe31a1865a781),
release 1.8.4.

View File

@ -0,0 +1,333 @@
/// Json-cpp amalgamated forward header (http://jsoncpp.sourceforge.net/).
/// It is intended to be used with #include "json/json-forwards.h"
/// This header provides forward declaration for all JsonCpp types.
// //////////////////////////////////////////////////////////////////////
// Beginning of content of file: LICENSE
// //////////////////////////////////////////////////////////////////////
/*
The JsonCpp library's source code, including accompanying documentation,
tests and demonstration applications, are licensed under the following
conditions...
Baptiste Lepilleur and The JsonCpp Authors explicitly disclaim copyright in all
jurisdictions which recognize such a disclaimer. In such jurisdictions,
this software is released into the Public Domain.
In jurisdictions which do not recognize Public Domain property (e.g. Germany as of
2010), this software is Copyright (c) 2007-2010 by Baptiste Lepilleur and
The JsonCpp Authors, and is released under the terms of the MIT License (see below).
In jurisdictions which recognize Public Domain property, the user of this
software may choose to accept it either as 1) Public Domain, 2) under the
conditions of the MIT License (see below), or 3) under the terms of dual
Public Domain/MIT License conditions described here, as they choose.
The MIT License is about as close to Public Domain as a license can get, and is
described in clear, concise terms at:
http://en.wikipedia.org/wiki/MIT_License
The full text of the MIT License follows:
========================================================================
Copyright (c) 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use, copy,
modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
========================================================================
(END LICENSE TEXT)
The MIT license is compatible with both the GPL and commercial
software, affording one all of the rights of Public Domain with the
minor nuisance of being required to keep the above copyright notice
and license text in the source code. Note also that by accepting the
Public Domain "license" you can re-license your copy using whatever
license you like.
*/
// //////////////////////////////////////////////////////////////////////
// End of content of file: LICENSE
// //////////////////////////////////////////////////////////////////////
#ifndef JSON_FORWARD_AMALGAMATED_H_INCLUDED
# define JSON_FORWARD_AMALGAMATED_H_INCLUDED
/// If defined, indicates that the source file is amalgamated
/// to prevent private header inclusion.
#define JSON_IS_AMALGAMATION
// //////////////////////////////////////////////////////////////////////
// Beginning of content of file: include/json/config.h
// //////////////////////////////////////////////////////////////////////
// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
// Distributed under MIT license, or public domain if desired and
// recognized in your jurisdiction.
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
#ifndef JSON_CONFIG_H_INCLUDED
#define JSON_CONFIG_H_INCLUDED
#include <stddef.h>
#include <string> //typedef String
#include <stdint.h> //typedef int64_t, uint64_t
/// If defined, indicates that json library is embedded in CppTL library.
//# define JSON_IN_CPPTL 1
/// If defined, indicates that json may leverage CppTL library
//# define JSON_USE_CPPTL 1
/// If defined, indicates that cpptl vector based map should be used instead of
/// std::map
/// as Value container.
//# define JSON_USE_CPPTL_SMALLMAP 1
// If non-zero, the library uses exceptions to report bad input instead of C
// assertion macros. The default is to use exceptions.
#ifndef JSON_USE_EXCEPTION
#define JSON_USE_EXCEPTION 1
#endif
/// If defined, indicates that the source file is amalgamated
/// to prevent private header inclusion.
/// Remarks: it is automatically defined in the generated amalgamated header.
// #define JSON_IS_AMALGAMATION
#ifdef JSON_IN_CPPTL
#include <cpptl/config.h>
#ifndef JSON_USE_CPPTL
#define JSON_USE_CPPTL 1
#endif
#endif
#ifdef JSON_IN_CPPTL
#define JSON_API CPPTL_API
#elif defined(JSON_DLL_BUILD)
#if defined(_MSC_VER) || defined(__MINGW32__)
#define JSON_API __declspec(dllexport)
#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING
#endif // if defined(_MSC_VER)
#elif defined(JSON_DLL)
#if defined(_MSC_VER) || defined(__MINGW32__)
#define JSON_API __declspec(dllimport)
#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING
#endif // if defined(_MSC_VER)
#endif // ifdef JSON_IN_CPPTL
#if !defined(JSON_API)
#define JSON_API
#endif
// If JSON_NO_INT64 is defined, then Json only support C++ "int" type for
// integer
// Storages, and 64 bits integer support is disabled.
// #define JSON_NO_INT64 1
#if defined(_MSC_VER) // MSVC
# if _MSC_VER <= 1200 // MSVC 6
// Microsoft Visual Studio 6 only support conversion from __int64 to double
// (no conversion from unsigned __int64).
# define JSON_USE_INT64_DOUBLE_CONVERSION 1
// Disable warning 4786 for VS6 caused by STL (identifier was truncated to '255'
// characters in the debug information)
// All projects I've ever seen with VS6 were using this globally (not bothering
// with pragma push/pop).
# pragma warning(disable : 4786)
# endif // MSVC 6
# if _MSC_VER >= 1500 // MSVC 2008
/// Indicates that the following function is deprecated.
# define JSONCPP_DEPRECATED(message) __declspec(deprecated(message))
# endif
#endif // defined(_MSC_VER)
// In c++11 the override keyword allows you to explicitly define that a function
// is intended to override the base-class version. This makes the code more
// managable and fixes a set of common hard-to-find bugs.
#if __cplusplus >= 201103L
# define JSONCPP_OVERRIDE override
# define JSONCPP_NOEXCEPT noexcept
#elif defined(_MSC_VER) && _MSC_VER > 1600 && _MSC_VER < 1900
# define JSONCPP_OVERRIDE override
# define JSONCPP_NOEXCEPT throw()
#elif defined(_MSC_VER) && _MSC_VER >= 1900
# define JSONCPP_OVERRIDE override
# define JSONCPP_NOEXCEPT noexcept
#else
# define JSONCPP_OVERRIDE
# define JSONCPP_NOEXCEPT throw()
#endif
#ifndef JSON_HAS_RVALUE_REFERENCES
#if defined(_MSC_VER) && _MSC_VER >= 1600 // MSVC >= 2010
#define JSON_HAS_RVALUE_REFERENCES 1
#endif // MSVC >= 2010
#ifdef __clang__
#if __has_feature(cxx_rvalue_references)
#define JSON_HAS_RVALUE_REFERENCES 1
#endif // has_feature
#elif defined __GNUC__ // not clang (gcc comes later since clang emulates gcc)
#if defined(__GXX_EXPERIMENTAL_CXX0X__) || (__cplusplus >= 201103L)
#define JSON_HAS_RVALUE_REFERENCES 1
#endif // GXX_EXPERIMENTAL
#endif // __clang__ || __GNUC__
#endif // not defined JSON_HAS_RVALUE_REFERENCES
#ifndef JSON_HAS_RVALUE_REFERENCES
#define JSON_HAS_RVALUE_REFERENCES 0
#endif
#ifdef __clang__
# if __has_extension(attribute_deprecated_with_message)
# define JSONCPP_DEPRECATED(message) __attribute__ ((deprecated(message)))
# endif
#elif defined __GNUC__ // not clang (gcc comes later since clang emulates gcc)
# if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5))
# define JSONCPP_DEPRECATED(message) __attribute__ ((deprecated(message)))
# elif (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
# define JSONCPP_DEPRECATED(message) __attribute__((__deprecated__))
# endif // GNUC version
#endif // __clang__ || __GNUC__
#if !defined(JSONCPP_DEPRECATED)
#define JSONCPP_DEPRECATED(message)
#endif // if !defined(JSONCPP_DEPRECATED)
#if __GNUC__ >= 6
# define JSON_USE_INT64_DOUBLE_CONVERSION 1
#endif
#if !defined(JSON_IS_AMALGAMATION)
# include "version.h"
# if JSONCPP_USING_SECURE_MEMORY
# include "allocator.h" //typedef Allocator
# endif
#endif // if !defined(JSON_IS_AMALGAMATION)
namespace Json {
typedef int Int;
typedef unsigned int UInt;
#if defined(JSON_NO_INT64)
typedef int LargestInt;
typedef unsigned int LargestUInt;
#undef JSON_HAS_INT64
#else // if defined(JSON_NO_INT64)
// For Microsoft Visual use specific types as long long is not supported
#if defined(_MSC_VER) // Microsoft Visual Studio
typedef __int64 Int64;
typedef unsigned __int64 UInt64;
#else // if defined(_MSC_VER) // Other platforms, use long long
typedef int64_t Int64;
typedef uint64_t UInt64;
#endif // if defined(_MSC_VER)
typedef Int64 LargestInt;
typedef UInt64 LargestUInt;
#define JSON_HAS_INT64
#endif // if defined(JSON_NO_INT64)
#if JSONCPP_USING_SECURE_MEMORY
#define JSONCPP_STRING std::basic_string<char, std::char_traits<char>, Json::SecureAllocator<char> >
#define JSONCPP_OSTRINGSTREAM std::basic_ostringstream<char, std::char_traits<char>, Json::SecureAllocator<char> >
#define JSONCPP_OSTREAM std::basic_ostream<char, std::char_traits<char>>
#define JSONCPP_ISTRINGSTREAM std::basic_istringstream<char, std::char_traits<char>, Json::SecureAllocator<char> >
#define JSONCPP_ISTREAM std::istream
#else
#define JSONCPP_STRING std::string
#define JSONCPP_OSTRINGSTREAM std::ostringstream
#define JSONCPP_OSTREAM std::ostream
#define JSONCPP_ISTRINGSTREAM std::istringstream
#define JSONCPP_ISTREAM std::istream
#endif // if JSONCPP_USING_SECURE_MEMORY
} // end namespace Json
#endif // JSON_CONFIG_H_INCLUDED
// //////////////////////////////////////////////////////////////////////
// End of content of file: include/json/config.h
// //////////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////////
// Beginning of content of file: include/json/forwards.h
// //////////////////////////////////////////////////////////////////////
// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
// Distributed under MIT license, or public domain if desired and
// recognized in your jurisdiction.
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
#ifndef JSON_FORWARDS_H_INCLUDED
#define JSON_FORWARDS_H_INCLUDED
#if !defined(JSON_IS_AMALGAMATION)
#include "config.h"
#endif // if !defined(JSON_IS_AMALGAMATION)
namespace Json {
// writer.h
class FastWriter;
class StyledWriter;
// reader.h
class Reader;
// features.h
class Features;
// value.h
typedef unsigned int ArrayIndex;
class StaticString;
class Path;
class PathArgument;
class Value;
class ValueIteratorBase;
class ValueIterator;
class ValueConstIterator;
} // namespace Json
#endif // JSON_FORWARDS_H_INCLUDED
// //////////////////////////////////////////////////////////////////////
// End of content of file: include/json/forwards.h
// //////////////////////////////////////////////////////////////////////
#endif //ifndef JSON_FORWARD_AMALGAMATED_H_INCLUDED

2207
dep/jsoncpp/json/json.h Normal file

File diff suppressed because it is too large Load Diff

5386
dep/jsoncpp/jsoncpp.cpp Normal file

File diff suppressed because it is too large Load Diff

View File

@ -62,7 +62,6 @@ namespace winrt::TerminalApp::implementation
std::vector<std::shared_ptr<Tab>> _tabs;
std::unique_ptr<::TerminalApp::CascadiaSettings> _settings;
std::unique_ptr<TerminalApp::AppKeyBindings> _keyBindings;
HRESULT _settingsLoadedResult;

View File

@ -11,82 +11,6 @@ using namespace winrt::Microsoft::Terminal;
using namespace winrt::TerminalApp;
using namespace winrt::Windows::Data::Json;
static constexpr std::wstring_view KEYS_KEY{ L"keys" };
static constexpr std::wstring_view COMMAND_KEY{ L"command" };
static constexpr std::wstring_view COPYTEXT_KEY{ L"copy" };
static constexpr std::wstring_view PASTETEXT_KEY{ L"paste" };
static constexpr std::wstring_view NEWTAB_KEY{ L"newTab" };
static constexpr std::wstring_view NEWTABWITHPROFILE0_KEY{ L"newTabProfile0" };
static constexpr std::wstring_view NEWTABWITHPROFILE1_KEY{ L"newTabProfile1" };
static constexpr std::wstring_view NEWTABWITHPROFILE2_KEY{ L"newTabProfile2" };
static constexpr std::wstring_view NEWTABWITHPROFILE3_KEY{ L"newTabProfile3" };
static constexpr std::wstring_view NEWTABWITHPROFILE4_KEY{ L"newTabProfile4" };
static constexpr std::wstring_view NEWTABWITHPROFILE5_KEY{ L"newTabProfile5" };
static constexpr std::wstring_view NEWTABWITHPROFILE6_KEY{ L"newTabProfile6" };
static constexpr std::wstring_view NEWTABWITHPROFILE7_KEY{ L"newTabProfile7" };
static constexpr std::wstring_view NEWTABWITHPROFILE8_KEY{ L"newTabProfile8" };
static constexpr std::wstring_view NEWWINDOW_KEY{ L"newWindow" };
static constexpr std::wstring_view CLOSEWINDOW_KEY{ L"closeWindow" };
static constexpr std::wstring_view CLOSETAB_KEY{ L"closeTab" };
static constexpr std::wstring_view SWITCHTOTAB_KEY{ L"switchToTab" };
static constexpr std::wstring_view NEXTTAB_KEY{ L"nextTab" };
static constexpr std::wstring_view PREVTAB_KEY{ L"prevTab" };
static constexpr std::wstring_view INCREASEFONTSIZE_KEY{ L"increaseFontSize" };
static constexpr std::wstring_view DECREASEFONTSIZE_KEY{ L"decreaseFontSize" };
static constexpr std::wstring_view SCROLLUP_KEY{ L"scrollUp" };
static constexpr std::wstring_view SCROLLDOWN_KEY{ L"scrollDown" };
static constexpr std::wstring_view SCROLLUPPAGE_KEY{ L"scrollUpPage" };
static constexpr std::wstring_view SCROLLDOWNPAGE_KEY{ L"scrollDownPage" };
static constexpr std::wstring_view SWITCHTOTAB0_KEY{ L"switchToTab0" };
static constexpr std::wstring_view SWITCHTOTAB1_KEY{ L"switchToTab1" };
static constexpr std::wstring_view SWITCHTOTAB2_KEY{ L"switchToTab2" };
static constexpr std::wstring_view SWITCHTOTAB3_KEY{ L"switchToTab3" };
static constexpr std::wstring_view SWITCHTOTAB4_KEY{ L"switchToTab4" };
static constexpr std::wstring_view SWITCHTOTAB5_KEY{ L"switchToTab5" };
static constexpr std::wstring_view SWITCHTOTAB6_KEY{ L"switchToTab6" };
static constexpr std::wstring_view SWITCHTOTAB7_KEY{ L"switchToTab7" };
static constexpr std::wstring_view SWITCHTOTAB8_KEY{ L"switchToTab8" };
static constexpr std::wstring_view OPENSETTINGS_KEY{ L"openSettings" };
// Specifically use a map here over an unordered_map. We want to be able to
// iterate over these entries in-order when we're serializing the keybindings.
static const std::map<std::wstring_view, ShortcutAction> commandNames {
{ COPYTEXT_KEY, ShortcutAction::CopyText },
{ PASTETEXT_KEY, ShortcutAction::PasteText },
{ NEWTAB_KEY, ShortcutAction::NewTab },
{ NEWTABWITHPROFILE0_KEY, ShortcutAction::NewTabProfile0 },
{ NEWTABWITHPROFILE1_KEY, ShortcutAction::NewTabProfile1 },
{ NEWTABWITHPROFILE2_KEY, ShortcutAction::NewTabProfile2 },
{ NEWTABWITHPROFILE3_KEY, ShortcutAction::NewTabProfile3 },
{ NEWTABWITHPROFILE4_KEY, ShortcutAction::NewTabProfile4 },
{ NEWTABWITHPROFILE5_KEY, ShortcutAction::NewTabProfile5 },
{ NEWTABWITHPROFILE6_KEY, ShortcutAction::NewTabProfile6 },
{ NEWTABWITHPROFILE7_KEY, ShortcutAction::NewTabProfile7 },
{ NEWTABWITHPROFILE8_KEY, ShortcutAction::NewTabProfile8 },
{ NEWWINDOW_KEY, ShortcutAction::NewWindow },
{ CLOSEWINDOW_KEY, ShortcutAction::CloseWindow },
{ CLOSETAB_KEY, ShortcutAction::CloseTab },
{ NEXTTAB_KEY, ShortcutAction::NextTab },
{ PREVTAB_KEY, ShortcutAction::PrevTab },
{ INCREASEFONTSIZE_KEY, ShortcutAction::IncreaseFontSize },
{ DECREASEFONTSIZE_KEY, ShortcutAction::DecreaseFontSize },
{ SCROLLUP_KEY, ShortcutAction::ScrollUp },
{ SCROLLDOWN_KEY, ShortcutAction::ScrollDown },
{ SCROLLUPPAGE_KEY, ShortcutAction::ScrollUpPage },
{ SCROLLDOWNPAGE_KEY, ShortcutAction::ScrollDownPage },
{ SWITCHTOTAB0_KEY, ShortcutAction::SwitchToTab0 },
{ SWITCHTOTAB1_KEY, ShortcutAction::SwitchToTab1 },
{ SWITCHTOTAB2_KEY, ShortcutAction::SwitchToTab2 },
{ SWITCHTOTAB3_KEY, ShortcutAction::SwitchToTab3 },
{ SWITCHTOTAB4_KEY, ShortcutAction::SwitchToTab4 },
{ SWITCHTOTAB5_KEY, ShortcutAction::SwitchToTab5 },
{ SWITCHTOTAB6_KEY, ShortcutAction::SwitchToTab6 },
{ SWITCHTOTAB7_KEY, ShortcutAction::SwitchToTab7 },
{ SWITCHTOTAB8_KEY, ShortcutAction::SwitchToTab8 },
{ OPENSETTINGS_KEY, ShortcutAction::OpenSettings },
};
namespace winrt::TerminalApp::implementation
{
void AppKeyBindings::SetKeyBinding(const TerminalApp::ShortcutAction& action,
@ -224,139 +148,6 @@ namespace winrt::TerminalApp::implementation
return false;
}
// -------------------------------- Events ---------------------------------
DEFINE_EVENT(AppKeyBindings, CopyText, _CopyTextHandlers, TerminalApp::CopyTextEventArgs);
DEFINE_EVENT(AppKeyBindings, PasteText, _PasteTextHandlers, TerminalApp::PasteTextEventArgs);
DEFINE_EVENT(AppKeyBindings, NewTab, _NewTabHandlers, TerminalApp::NewTabEventArgs);
DEFINE_EVENT(AppKeyBindings, NewTabWithProfile, _NewTabWithProfileHandlers, TerminalApp::NewTabWithProfileEventArgs);
DEFINE_EVENT(AppKeyBindings, NewWindow, _NewWindowHandlers, TerminalApp::NewWindowEventArgs);
DEFINE_EVENT(AppKeyBindings, CloseWindow, _CloseWindowHandlers, TerminalApp::CloseWindowEventArgs);
DEFINE_EVENT(AppKeyBindings, CloseTab, _CloseTabHandlers, TerminalApp::CloseTabEventArgs);
DEFINE_EVENT(AppKeyBindings, SwitchToTab, _SwitchToTabHandlers, TerminalApp::SwitchToTabEventArgs);
DEFINE_EVENT(AppKeyBindings, NextTab, _NextTabHandlers, TerminalApp::NextTabEventArgs);
DEFINE_EVENT(AppKeyBindings, PrevTab, _PrevTabHandlers, TerminalApp::PrevTabEventArgs);
DEFINE_EVENT(AppKeyBindings, IncreaseFontSize, _IncreaseFontSizeHandlers, TerminalApp::IncreaseFontSizeEventArgs);
DEFINE_EVENT(AppKeyBindings, DecreaseFontSize, _DecreaseFontSizeHandlers, TerminalApp::DecreaseFontSizeEventArgs);
DEFINE_EVENT(AppKeyBindings, ScrollUp, _ScrollUpHandlers, TerminalApp::ScrollUpEventArgs);
DEFINE_EVENT(AppKeyBindings, ScrollDown, _ScrollDownHandlers, TerminalApp::ScrollDownEventArgs);
DEFINE_EVENT(AppKeyBindings, ScrollUpPage, _ScrollUpPageHandlers, TerminalApp::ScrollUpPageEventArgs);
DEFINE_EVENT(AppKeyBindings, ScrollDownPage, _ScrollDownPageHandlers, TerminalApp::ScrollDownPageEventArgs);
DEFINE_EVENT(AppKeyBindings, OpenSettings, _OpenSettingsHandlers, TerminalApp::OpenSettingsEventArgs);
// Method Description:
// - Deserialize an AppKeyBindings from the key mappings that are in the
// array `json`. The json array should contain an array of objects with
// both a `command` string and a `keys` array, where `command` is one of
// the names listed in `commandNames`, and `keys` is an array of
// keypresses. Currently, the array should contain a single string, which
// can be deserialized into a KeyChord.
// Arguments:
// - json: and array of JsonObject's to deserialize into our _keyShortcuts mapping.
// Return Value:
// - the newly constructed AppKeyBindings object.
TerminalApp::AppKeyBindings AppKeyBindings::FromJson(const JsonArray& json)
{
TerminalApp::AppKeyBindings newBindings{};
for (const auto& value : json)
{
if (value.ValueType() == JsonValueType::Object)
{
JsonObject obj = value.GetObjectW();
if (obj.HasKey(COMMAND_KEY) && obj.HasKey(KEYS_KEY))
{
const auto commandString = obj.GetNamedString(COMMAND_KEY);
const auto keys = obj.GetNamedArray(KEYS_KEY);
if (keys.Size() != 1)
{
continue;
}
const auto keyChordString = keys.GetAt(0).GetString();
ShortcutAction action;
// Try matching the command to one we have
auto found = commandNames.find(commandString);
if (found != commandNames.end())
{
action = found->second;
}
else
{
continue;
}
// Try parsing the chord
try
{
auto chord = KeyChordSerialization::FromString(keyChordString);
newBindings.SetKeyBinding(action, chord);
}
catch (...)
{
continue;
}
}
}
}
return newBindings;
}
// Function Description:
// - Small helper to insert a given KeyChord, ShortcutAction pair into the
// given json array
// Arguments:
// - bindingsArray: The JsonArray to insert the object into.
// - chord: The KeyChord to serailize and place in the json array
// - actionName: the name of the ShortcutAction to use with this KeyChord
static void _AddShortcutToJsonArray(const JsonArray& bindingsArray,
const Settings::KeyChord& chord,
const std::wstring_view& actionName)
{
const auto keyString = KeyChordSerialization::ToString(chord);
if (keyString == L"")
{
return;
}
winrt::Windows::Data::Json::JsonObject jsonObject;
winrt::Windows::Data::Json::JsonArray keysArray;
keysArray.Append(JsonValue::CreateStringValue(keyString));
jsonObject.Insert(KEYS_KEY, keysArray);
jsonObject.Insert(COMMAND_KEY, JsonValue::CreateStringValue(actionName));
bindingsArray.Append(jsonObject);
}
// Method Description:
// - Serialize this AppKeyBindings to a json array of objects. Each object
// in the array represents a single keybinding, mapping a KeyChord to a
// ShortcutAction.
// Return Value:
// - a JsonArray which is an equivalent serialization of this object.
Windows::Data::Json::JsonArray AppKeyBindings::ToJson()
{
winrt::Windows::Data::Json::JsonArray bindingsArray;
// Iterate over all the possible actions in the names list, and see if
// it has a binding.
for (auto& actionName : commandNames)
{
const auto searchedForName = actionName.first;
const auto searchedForAction = actionName.second;
for (const auto& kv : _keyShortcuts)
{
const auto chord = kv.first;
const auto command = kv.second;
if (command == searchedForAction)
{
_AddShortcutToJsonArray(bindingsArray, chord, searchedForName);
}
}
}
return bindingsArray;
}
// Method Description:
// - Takes the KeyModifier flags from Terminal and maps them to the WinRT types which are used by XAML
// Return Value:
@ -364,7 +155,7 @@ namespace winrt::TerminalApp::implementation
Windows::System::VirtualKeyModifiers AppKeyBindings::ConvertVKModifiers(Settings::KeyModifiers modifiers)
{
Windows::System::VirtualKeyModifiers keyModifiers = Windows::System::VirtualKeyModifiers::None;
if (WI_IsFlagSet(modifiers, Settings::KeyModifiers::Ctrl))
{
keyModifiers |= Windows::System::VirtualKeyModifiers::Control;
@ -408,4 +199,23 @@ namespace winrt::TerminalApp::implementation
return winrt::hstring{ buffer };
}
// -------------------------------- Events ---------------------------------
DEFINE_EVENT(AppKeyBindings, CopyText, _CopyTextHandlers, TerminalApp::CopyTextEventArgs);
DEFINE_EVENT(AppKeyBindings, PasteText, _PasteTextHandlers, TerminalApp::PasteTextEventArgs);
DEFINE_EVENT(AppKeyBindings, NewTab, _NewTabHandlers, TerminalApp::NewTabEventArgs);
DEFINE_EVENT(AppKeyBindings, NewTabWithProfile, _NewTabWithProfileHandlers, TerminalApp::NewTabWithProfileEventArgs);
DEFINE_EVENT(AppKeyBindings, NewWindow, _NewWindowHandlers, TerminalApp::NewWindowEventArgs);
DEFINE_EVENT(AppKeyBindings, CloseWindow, _CloseWindowHandlers, TerminalApp::CloseWindowEventArgs);
DEFINE_EVENT(AppKeyBindings, CloseTab, _CloseTabHandlers, TerminalApp::CloseTabEventArgs);
DEFINE_EVENT(AppKeyBindings, SwitchToTab, _SwitchToTabHandlers, TerminalApp::SwitchToTabEventArgs);
DEFINE_EVENT(AppKeyBindings, NextTab, _NextTabHandlers, TerminalApp::NextTabEventArgs);
DEFINE_EVENT(AppKeyBindings, PrevTab, _PrevTabHandlers, TerminalApp::PrevTabEventArgs);
DEFINE_EVENT(AppKeyBindings, IncreaseFontSize, _IncreaseFontSizeHandlers, TerminalApp::IncreaseFontSizeEventArgs);
DEFINE_EVENT(AppKeyBindings, DecreaseFontSize, _DecreaseFontSizeHandlers, TerminalApp::DecreaseFontSizeEventArgs);
DEFINE_EVENT(AppKeyBindings, ScrollUp, _ScrollUpHandlers, TerminalApp::ScrollUpEventArgs);
DEFINE_EVENT(AppKeyBindings, ScrollDown, _ScrollDownHandlers, TerminalApp::ScrollDownEventArgs);
DEFINE_EVENT(AppKeyBindings, ScrollUpPage, _ScrollUpPageHandlers, TerminalApp::ScrollUpPageEventArgs);
DEFINE_EVENT(AppKeyBindings, ScrollDownPage, _ScrollDownPageHandlers, TerminalApp::ScrollDownPageEventArgs);
DEFINE_EVENT(AppKeyBindings, OpenSettings, _OpenSettingsHandlers, TerminalApp::OpenSettingsEventArgs);
}

View File

@ -32,15 +32,13 @@ namespace winrt::TerminalApp::implementation
{
AppKeyBindings() = default;
static TerminalApp::AppKeyBindings FromJson(Windows::Data::Json::JsonArray const& json);
Windows::Data::Json::JsonArray ToJson();
static Windows::System::VirtualKeyModifiers ConvertVKModifiers(winrt::Microsoft::Terminal::Settings::KeyModifiers modifiers);
static winrt::hstring FormatOverrideShortcutText(winrt::Microsoft::Terminal::Settings::KeyModifiers modifiers);
bool TryKeyChord(winrt::Microsoft::Terminal::Settings::KeyChord const& kc);
void SetKeyBinding(TerminalApp::ShortcutAction const& action, winrt::Microsoft::Terminal::Settings::KeyChord const& chord);
Microsoft::Terminal::Settings::KeyChord GetKeyBinding(TerminalApp::ShortcutAction const& action);
static Windows::System::VirtualKeyModifiers ConvertVKModifiers(winrt::Microsoft::Terminal::Settings::KeyModifiers modifiers);
static winrt::hstring FormatOverrideShortcutText(winrt::Microsoft::Terminal::Settings::KeyModifiers modifiers);
DECLARE_EVENT(CopyText, _CopyTextHandlers, TerminalApp::CopyTextEventArgs);
DECLARE_EVENT(PasteText, _PasteTextHandlers, TerminalApp::PasteTextEventArgs);
DECLARE_EVENT(NewTab, _NewTabHandlers, TerminalApp::NewTabEventArgs);

View File

@ -63,9 +63,6 @@ namespace TerminalApp
{
AppKeyBindings();
Windows.Data.Json.JsonArray ToJson();
static AppKeyBindings FromJson(Windows.Data.Json.JsonArray json);
void SetKeyBinding(ShortcutAction action, Microsoft.Terminal.Settings.KeyChord chord);
Microsoft.Terminal.Settings.KeyChord GetKeyBinding(ShortcutAction action);

View File

@ -0,0 +1,211 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#include "pch.h"
#include "AppKeyBindingsSerialization.h"
#include "KeyChordSerialization.h"
#include "Utils.h"
#include <winrt/Microsoft.Terminal.Settings.h>
using namespace winrt::Microsoft::Terminal::Settings;
using namespace winrt::TerminalApp;
static constexpr std::string_view KeysKey{ "keys" };
static constexpr std::string_view CommandKey{ "command" };
static constexpr std::string_view CopyTextKey{ "copy" };
static constexpr std::string_view PasteTextKey{ "paste" };
static constexpr std::string_view NewTabKey{ "newTab" };
static constexpr std::string_view NewTabWithProfile0Key{ "newTabProfile0" };
static constexpr std::string_view NewTabWithProfile1Key{ "newTabProfile1" };
static constexpr std::string_view NewTabWithProfile2Key{ "newTabProfile2" };
static constexpr std::string_view NewTabWithProfile3Key{ "newTabProfile3" };
static constexpr std::string_view NewTabWithProfile4Key{ "newTabProfile4" };
static constexpr std::string_view NewTabWithProfile5Key{ "newTabProfile5" };
static constexpr std::string_view NewTabWithProfile6Key{ "newTabProfile6" };
static constexpr std::string_view NewTabWithProfile7Key{ "newTabProfile7" };
static constexpr std::string_view NewTabWithProfile8Key{ "newTabProfile8" };
static constexpr std::string_view NewWindowKey{ "newWindow" };
static constexpr std::string_view CloseWindowKey{ "closeWindow" };
static constexpr std::string_view CloseTabKey{ "closeTab" };
static constexpr std::string_view SwitchtoTabKey{ "switchToTab" };
static constexpr std::string_view NextTabKey{ "nextTab" };
static constexpr std::string_view PrevTabKey{ "prevTab" };
static constexpr std::string_view IncreaseFontSizeKey{ "increaseFontSize" };
static constexpr std::string_view DecreaseFontSizeKey{ "decreaseFontSize" };
static constexpr std::string_view ScrollupKey{ "scrollUp" };
static constexpr std::string_view ScrolldownKey{ "scrollDown" };
static constexpr std::string_view ScrolluppageKey{ "scrollUpPage" };
static constexpr std::string_view ScrolldownpageKey{ "scrollDownPage" };
static constexpr std::string_view SwitchToTab0Key{ "switchToTab0" };
static constexpr std::string_view SwitchToTab1Key{ "switchToTab1" };
static constexpr std::string_view SwitchToTab2Key{ "switchToTab2" };
static constexpr std::string_view SwitchToTab3Key{ "switchToTab3" };
static constexpr std::string_view SwitchToTab4Key{ "switchToTab4" };
static constexpr std::string_view SwitchToTab5Key{ "switchToTab5" };
static constexpr std::string_view SwitchToTab6Key{ "switchToTab6" };
static constexpr std::string_view SwitchToTab7Key{ "switchToTab7" };
static constexpr std::string_view SwitchToTab8Key{ "switchToTab8" };
static constexpr std::string_view OpenSettingsKey{ "openSettings" };
// Specifically use a map here over an unordered_map. We want to be able to
// iterate over these entries in-order when we're serializing the keybindings.
// HERE BE DRAGONS:
// These are string_views that are being used as keys. These string_views are
// just pointers to other strings. This could be dangerous, if the map outlived
// the actual strings being pointed to. However, since both these strings and
// the map are all const for the lifetime of the app, we have nothing to worry
// about here.
static const std::map<std::string_view, ShortcutAction, std::less<>> commandNames {
{ CopyTextKey, ShortcutAction::CopyText },
{ PasteTextKey, ShortcutAction::PasteText },
{ NewTabKey, ShortcutAction::NewTab },
{ NewTabWithProfile0Key, ShortcutAction::NewTabProfile0 },
{ NewTabWithProfile1Key, ShortcutAction::NewTabProfile1 },
{ NewTabWithProfile2Key, ShortcutAction::NewTabProfile2 },
{ NewTabWithProfile3Key, ShortcutAction::NewTabProfile3 },
{ NewTabWithProfile4Key, ShortcutAction::NewTabProfile4 },
{ NewTabWithProfile5Key, ShortcutAction::NewTabProfile5 },
{ NewTabWithProfile6Key, ShortcutAction::NewTabProfile6 },
{ NewTabWithProfile7Key, ShortcutAction::NewTabProfile7 },
{ NewTabWithProfile8Key, ShortcutAction::NewTabProfile8 },
{ NewWindowKey, ShortcutAction::NewWindow },
{ CloseWindowKey, ShortcutAction::CloseWindow },
{ CloseTabKey, ShortcutAction::CloseTab },
{ NextTabKey, ShortcutAction::NextTab },
{ PrevTabKey, ShortcutAction::PrevTab },
{ IncreaseFontSizeKey, ShortcutAction::IncreaseFontSize },
{ DecreaseFontSizeKey, ShortcutAction::DecreaseFontSize },
{ ScrollupKey, ShortcutAction::ScrollUp },
{ ScrolldownKey, ShortcutAction::ScrollDown },
{ ScrolluppageKey, ShortcutAction::ScrollUpPage },
{ ScrolldownpageKey, ShortcutAction::ScrollDownPage },
{ SwitchToTab0Key, ShortcutAction::SwitchToTab0 },
{ SwitchToTab1Key, ShortcutAction::SwitchToTab1 },
{ SwitchToTab2Key, ShortcutAction::SwitchToTab2 },
{ SwitchToTab3Key, ShortcutAction::SwitchToTab3 },
{ SwitchToTab4Key, ShortcutAction::SwitchToTab4 },
{ SwitchToTab5Key, ShortcutAction::SwitchToTab5 },
{ SwitchToTab6Key, ShortcutAction::SwitchToTab6 },
{ SwitchToTab7Key, ShortcutAction::SwitchToTab7 },
{ SwitchToTab8Key, ShortcutAction::SwitchToTab8 },
};
// Function Description:
// - Small helper to create a json value serialization of a single
// KeyBinding->Action maping. The created object is of schema:
// {
// keys:[String],
// command:String
// }
// Arguments:
// - chord: The KeyChord to serialize
// - actionName: the name of the ShortcutAction to use with this KeyChord
// Return Value:
// - a Json::Value which is an equivalent serialization of this object.
static Json::Value _ShortcutAsJsonObject(const KeyChord& chord,
const std::string_view actionName)
{
const auto keyString = KeyChordSerialization::ToString(chord);
if (keyString == L"")
{
return nullptr;
}
Json::Value jsonObject;
Json::Value keysArray;
keysArray.append(winrt::to_string(keyString));
jsonObject[JsonKey(KeysKey)] = keysArray;
jsonObject[JsonKey(CommandKey)] = actionName.data();
return jsonObject;
}
// Method Description:
// - Serialize this AppKeyBindings to a json array of objects. Each object in
// the array represents a single keybinding, mapping a KeyChord to a
// ShortcutAction.
// Return Value:
// - a Json::Value which is an equivalent serialization of this object.
Json::Value AppKeyBindingsSerialization::ToJson(const winrt::TerminalApp::AppKeyBindings& bindings)
{
Json::Value bindingsArray;
// Iterate over all the possible actions in the names list, and see if
// it has a binding.
for (auto& actionName : commandNames)
{
const auto searchedForName = actionName.first;
const auto searchedForAction = actionName.second;
if (const auto chord{ bindings.GetKeyBinding(searchedForAction) })
{
if (const auto serialization{ _ShortcutAsJsonObject(chord, searchedForName) })
{
bindingsArray.append(serialization);
}
}
}
return bindingsArray;
}
// Method Description:
// - Deserialize an AppKeyBindings from the key mappings that are in the array
// `json`. The json array should contain an array of objects with both a
// `command` string and a `keys` array, where `command` is one of the names
// listed in `commandNames`, and `keys` is an array of keypresses. Currently,
// the array should contain a single string, which can be deserialized into a
// KeyChord.
// Arguments:
// - json: and array of JsonObject's to deserialize into our _keyShortcuts mapping.
// Return Value:
// - the newly constructed AppKeyBindings object.
winrt::TerminalApp::AppKeyBindings AppKeyBindingsSerialization::FromJson(const Json::Value& json)
{
winrt::TerminalApp::AppKeyBindings newBindings{};
for (const auto& value : json)
{
if (value.isObject())
{
const auto commandString = value[JsonKey(CommandKey)];
const auto keys = value[JsonKey(KeysKey)];
if (commandString && keys)
{
if (!keys.isArray() || keys.size() != 1)
{
continue;
}
const auto keyChordString = winrt::to_hstring(keys[0].asString());
ShortcutAction action;
// Try matching the command to one we have
const auto found = commandNames.find(commandString.asString());
if (found != commandNames.end())
{
action = found->second;
}
else
{
continue;
}
// Try parsing the chord
try
{
const auto chord = KeyChordSerialization::FromString(keyChordString);
newBindings.SetKeyBinding(action, chord);
}
catch (...)
{
continue;
}
}
}
}
return newBindings;
}

View File

@ -0,0 +1,28 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
//
// Module Name:
// - Profile.hpp
//
// Abstract:
// - A couple helper functions for serializing/deserializing an AppKeyBindings
// to/from json. We need this to exist as external helper functions, rather
// than defining these as methods on the AppKeyBindings class, because
// AppKeyBindings is a winrt type. When we're working with a AppKeyBindings
// object, we only have access to methods defined on the winrt interface (in
// the idl). We don't have access to methods we define on the
// implementation. Since JsonValue is not a winrt type, we can't define any
// methods that operate on it in the idl.
//
// Author(s):
// - Mike Griese - May 2019
#pragma once
#include "AppKeyBindings.h"
class AppKeyBindingsSerialization final
{
public:
static winrt::TerminalApp::AppKeyBindings FromJson(const Json::Value& json);
static Json::Value ToJson(const winrt::TerminalApp::AppKeyBindings& bindings);
};

View File

@ -44,8 +44,8 @@ public:
winrt::TerminalApp::AppKeyBindings GetKeybindings() const noexcept;
winrt::Windows::Data::Json::JsonObject ToJson() const;
static std::unique_ptr<CascadiaSettings> FromJson(winrt::Windows::Data::Json::JsonObject json);
Json::Value ToJson() const;
static std::unique_ptr<CascadiaSettings> FromJson(const Json::Value& json);
static winrt::hstring GetSettingsPath();
@ -62,12 +62,12 @@ private:
void _CreateDefaultProfiles();
static bool _IsPackaged();
static void _SaveAsPackagedApp(const winrt::hstring content);
static void _SaveAsUnpackagedApp(const winrt::hstring content);
static void _SaveAsPackagedApp(const std::string& content);
static void _SaveAsUnpackagedApp(const std::string& content);
static std::wstring _GetFullPathToUnpackagedSettingsFile();
static winrt::hstring _GetPackagedSettingsPath();
static std::optional<winrt::hstring> _LoadAsPackagedApp();
static std::optional<winrt::hstring> _LoadAsUnpackagedApp();
static std::optional<std::string> _LoadAsPackagedApp();
static std::optional<std::string> _LoadAsUnpackagedApp();
static bool _isPowerShellCoreInstalledInPath(const std::wstring_view programFileEnv, std::filesystem::path& cmdline);
static bool _isPowerShellCoreInstalled(std::filesystem::path& cmdline);
static std::wstring ExpandEnvironmentVariableString(std::wstring_view source);

View File

@ -4,6 +4,7 @@
#include "pch.h"
#include <argb.h>
#include "CascadiaSettings.h"
#include "AppKeyBindingsSerialization.h"
#include "../../types/inc/utils.hpp"
#include <appmodel.h>
#include <shlobj.h>
@ -19,9 +20,10 @@ using namespace ::Microsoft::Console;
static constexpr std::wstring_view FILENAME { L"profiles.json" };
static constexpr std::wstring_view SETTINGS_FOLDER_NAME{ L"\\Microsoft\\Windows Terminal\\" };
static constexpr std::wstring_view PROFILES_KEY{ L"profiles" };
static constexpr std::wstring_view KEYBINDINGS_KEY{ L"keybindings" };
static constexpr std::wstring_view SCHEMES_KEY{ L"schemes" };
static constexpr std::string_view ProfilesKey{ "profiles" };
static constexpr std::string_view KeybindingsKey{ "keybindings" };
static constexpr std::string_view GlobalsKey{ "globals" };
static constexpr std::string_view SchemesKey{ "schemes" };
// Method Description:
// - Creates a CascadiaSettings from whatever's saved on disk, or instantiates
@ -37,26 +39,34 @@ static constexpr std::wstring_view SCHEMES_KEY{ L"schemes" };
std::unique_ptr<CascadiaSettings> CascadiaSettings::LoadAll(const bool saveOnLoad)
{
std::unique_ptr<CascadiaSettings> resultPtr;
std::optional<winrt::hstring> fileData = _IsPackaged() ?
_LoadAsPackagedApp() : _LoadAsUnpackagedApp();
std::optional<std::string> fileData = _IsPackaged() ?
_LoadAsPackagedApp() : _LoadAsUnpackagedApp();
const bool foundFile = fileData.has_value();
if (foundFile)
{
const auto actualData = fileData.value();
// If Parse fails, it'll throw a hresult_error
JsonObject root = JsonObject::Parse(actualData);
// Parse the json data.
Json::Value root;
std::unique_ptr<Json::CharReader> reader{ Json::CharReaderBuilder::CharReaderBuilder().newCharReader() };
std::string errs; // This string will recieve any error text from failing to parse.
// `parse` will return false if it fails.
if (!reader->parse(actualData.c_str(), actualData.c_str() + actualData.size(), &root, &errs))
{
// TODO:GH#990 display this exception text to the user, in a
// copy-pasteable way.
throw winrt::hresult_error(WEB_E_INVALID_JSON_STRING, winrt::to_hstring(errs));
}
resultPtr = FromJson(root);
// Update profile only if it has changed.
if (saveOnLoad)
{
const JsonObject json = resultPtr->ToJson();
auto serializedSettings = json.Stringify();
if (actualData != serializedSettings)
// Logically compare the json we've parsed from the file to what
// we'd serialize at runtime. If the values are different, then
// write the updated schema back out.
const Json::Value reserialized = resultPtr->ToJson();
if (reserialized != root)
{
resultPtr->SaveAll();
}
@ -84,16 +94,19 @@ std::unique_ptr<CascadiaSettings> CascadiaSettings::LoadAll(const bool saveOnLoa
// - <none>
void CascadiaSettings::SaveAll() const
{
const JsonObject json = ToJson();
auto serializedSettings = json.Stringify();
const auto json = ToJson();
Json::StreamWriterBuilder wbuilder;
// Use 4 spaces to indent instead of \t
wbuilder.settings_["indentation"] = " ";
const auto serializedString = Json::writeString(wbuilder, json);
if (_IsPackaged())
{
_SaveAsPackagedApp(serializedSettings);
_SaveAsPackagedApp(serializedString);
}
else
{
_SaveAsUnpackagedApp(serializedSettings);
_SaveAsUnpackagedApp(serializedString);
}
}
@ -103,32 +116,28 @@ void CascadiaSettings::SaveAll() const
// - <none>
// Return Value:
// - a JsonObject which is an equivalent serialization of this object.
JsonObject CascadiaSettings::ToJson() const
Json::Value CascadiaSettings::ToJson() const
{
// _globals.ToJson will initialize the settings object will all the global
// settings in the root of the object.
winrt::Windows::Data::Json::JsonObject jsonObject = _globals.ToJson();
Json::Value root;
JsonArray schemesArray{};
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());
schemesArray.append(scheme.ToJson());
}
JsonArray profilesArray{};
for (auto& profile : _profiles)
{
profilesArray.Append(profile.ToJson());
}
root[GlobalsKey.data()] = _globals.ToJson();
root[ProfilesKey.data()] = profilesArray;
root[SchemesKey.data()] = schemesArray;
jsonObject.Insert(PROFILES_KEY, profilesArray);
jsonObject.Insert(SCHEMES_KEY, schemesArray);
jsonObject.Insert(KEYBINDINGS_KEY,
_globals.GetKeybindings().ToJson());
return jsonObject;
return root;
}
// Method Description:
@ -137,11 +146,33 @@ JsonObject CascadiaSettings::ToJson() const
// - json: an object which should be a serialization of a CascadiaSettings object.
// Return Value:
// - a new CascadiaSettings instance created from the values in `json`
std::unique_ptr<CascadiaSettings> CascadiaSettings::FromJson(JsonObject json)
std::unique_ptr<CascadiaSettings> CascadiaSettings::FromJson(const Json::Value& json)
{
std::unique_ptr<CascadiaSettings> resultPtr = std::make_unique<CascadiaSettings>();
resultPtr->_globals = GlobalAppSettings::FromJson(json);
if (auto globals{ json[GlobalsKey.data()] })
{
if (globals.isObject())
{
resultPtr->_globals = GlobalAppSettings::FromJson(globals);
}
}
else
{
// If there's no globals key in the root object, then try looking at the
// root object for those properties instead, to gracefully upgrade.
// This will attempt to do the legacy keybindings loading too
resultPtr->_globals = GlobalAppSettings::FromJson(json);
// If we didn't find keybindings in the legacy path, then they probably
// don't exist in the file. Create the default keybindings if we
// couldn't find any keybindings.
auto keybindings{ json[KeybindingsKey.data()] };
if (!keybindings)
{
resultPtr->_CreateDefaultKeybindings();
}
}
// TODO:MSFT:20737698 - Display an error if we failed to parse settings
// What should we do here if these keys aren't found?For default profile,
@ -153,47 +184,30 @@ std::unique_ptr<CascadiaSettings> CascadiaSettings::FromJson(JsonObject json)
// Or should we just recreate the default profiles?
auto& resultSchemes = resultPtr->_globals.GetColorSchemes();
if (json.HasKey(SCHEMES_KEY))
if (auto schemes{ json[SchemesKey.data()] })
{
auto schemes = json.GetNamedArray(SCHEMES_KEY);
for (auto schemeJson : schemes)
{
if (schemeJson.ValueType() == JsonValueType::Object)
if (schemeJson.isObject())
{
auto schemeObj = schemeJson.GetObjectW();
auto scheme = ColorScheme::FromJson(schemeObj);
auto scheme = ColorScheme::FromJson(schemeJson);
resultSchemes.emplace_back(std::move(scheme));
}
}
}
if (json.HasKey(PROFILES_KEY))
if (auto profiles{ json[ProfilesKey.data()] })
{
auto profiles = json.GetNamedArray(PROFILES_KEY);
for (auto profileJson : profiles)
{
if (profileJson.ValueType() == JsonValueType::Object)
if (profileJson.isObject())
{
auto profileObj = profileJson.GetObjectW();
auto profile = Profile::FromJson(profileObj);
resultPtr->_profiles.emplace_back(std::move(profile));
auto profile = Profile::FromJson(profileJson);
resultPtr->_profiles.emplace_back(profile);
}
}
}
// Load the keybindings from the file as well
if (json.HasKey(KEYBINDINGS_KEY))
{
const auto keybindingsObj = json.GetNamedArray(KEYBINDINGS_KEY);
auto loadedBindings = AppKeyBindings::FromJson(keybindingsObj);
resultPtr->_globals.SetKeybindings(loadedBindings);
}
else
{
// Create the default keybindings if we couldn't find any keybindings.
resultPtr->_CreateDefaultKeybindings();
}
return resultPtr;
}
@ -221,7 +235,7 @@ bool CascadiaSettings::_IsPackaged()
// - content: the given string of content to write to the file.
// Return Value:
// - <none>
void CascadiaSettings::_SaveAsPackagedApp(const winrt::hstring content)
void CascadiaSettings::_SaveAsPackagedApp(const std::string& content)
{
auto curr = ApplicationData::Current();
auto folder = curr.RoamingFolder();
@ -232,11 +246,13 @@ void CascadiaSettings::_SaveAsPackagedApp(const winrt::hstring content)
auto file = file_async.get();
DataWriter dw = DataWriter();
const char* firstChar = content.c_str();
const char* lastChar = firstChar + content.size();
// DataWriter will convert UTF-16 string to UTF-8 (expected settings file encoding)
dw.UnicodeEncoding(UnicodeEncoding::Utf8);
dw.WriteString(content);
const uint8_t* firstByte = reinterpret_cast<const uint8_t*>(firstChar);
const uint8_t* lastByte = reinterpret_cast<const uint8_t*>(lastChar);
winrt::array_view<const uint8_t> bytes{ firstByte, lastByte };
dw.WriteBytes(bytes);
FileIO::WriteBufferAsync(file, dw.DetachBuffer()).get();
}
@ -250,11 +266,8 @@ void CascadiaSettings::_SaveAsPackagedApp(const winrt::hstring content)
// - <none>
// This can throw an exception if we fail to open the file for writing, or we
// fail to write the file
void CascadiaSettings::_SaveAsUnpackagedApp(const winrt::hstring content)
void CascadiaSettings::_SaveAsUnpackagedApp(const std::string& content)
{
// convert UTF-16 to UTF-8
auto contentString = winrt::to_string(content);
// Get path to output file
// In this scenario, the settings file will end up under e.g. C:\Users\admin\AppData\Roaming\Microsoft\Windows Terminal\profiles.json
std::wstring pathToSettingsFile = CascadiaSettings::_GetFullPathToUnpackagedSettingsFile();
@ -264,7 +277,7 @@ void CascadiaSettings::_SaveAsUnpackagedApp(const winrt::hstring content)
{
THROW_LAST_ERROR();
}
THROW_LAST_ERROR_IF(!WriteFile(hOut, contentString.c_str(), gsl::narrow<DWORD>(contentString.length()), 0, 0));
THROW_LAST_ERROR_IF(!WriteFile(hOut, content.c_str(), gsl::narrow<DWORD>(content.length()), 0, 0));
CloseHandle(hOut);
}
@ -306,7 +319,7 @@ std::wstring CascadiaSettings::_GetFullPathToUnpackagedSettingsFile()
// Return Value:
// - an optional with the content of the file if we were able to open it,
// otherwise the optional will be empty
std::optional<winrt::hstring> CascadiaSettings::_LoadAsPackagedApp()
std::optional<std::string> CascadiaSettings::_LoadAsPackagedApp()
{
auto curr = ApplicationData::Current();
auto folder = curr.RoamingFolder();
@ -320,7 +333,11 @@ std::optional<winrt::hstring> CascadiaSettings::_LoadAsPackagedApp()
const auto storageFile = file.as<StorageFile>();
// settings file is UTF-8 without BOM
return { FileIO::ReadTextAsync(storageFile, UnicodeEncoding::Utf8).get() };
auto buffer = FileIO::ReadBufferAsync(storageFile).get();
auto bufferData = buffer.data();
std::vector<uint8_t> bytes{ bufferData, bufferData + buffer.Length() };
std::string resultString{ bytes.begin(), bytes.end() };
return { resultString };
}
@ -333,7 +350,7 @@ std::optional<winrt::hstring> CascadiaSettings::_LoadAsPackagedApp()
// otherwise the optional will be empty.
// If the file exists, but we fail to read it, this can throw an exception
// from reading the file
std::optional<winrt::hstring> CascadiaSettings::_LoadAsUnpackagedApp()
std::optional<std::string> CascadiaSettings::_LoadAsUnpackagedApp()
{
std::wstring pathToSettingsFile = CascadiaSettings::_GetFullPathToUnpackagedSettingsFile();
const auto hFile = CreateFileW(pathToSettingsFile.c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
@ -358,10 +375,7 @@ std::optional<winrt::hstring> CascadiaSettings::_LoadAsUnpackagedApp()
// convert buffer to UTF-8 string
std::string utf8string(utf8buffer.get(), fileSize);
// UTF-8 to UTF-16
const winrt::hstring fileData = winrt::to_hstring(utf8string);
return { fileData };
return { utf8string };
}
// function Description:

View File

@ -4,6 +4,7 @@
#include "pch.h"
#include "ColorScheme.h"
#include "../../types/inc/Utils.hpp"
#include "Utils.h"
using namespace TerminalApp;
using namespace ::Microsoft::Console;
@ -12,28 +13,28 @@ using namespace winrt::Microsoft::Terminal::TerminalControl;
using namespace winrt::TerminalApp;
using namespace winrt::Windows::Data::Json;
static constexpr std::wstring_view NAME_KEY{ L"name" };
static constexpr std::wstring_view TABLE_KEY{ L"colors" };
static constexpr std::wstring_view FOREGROUND_KEY{ L"foreground" };
static constexpr std::wstring_view BACKGROUND_KEY{ L"background" };
static const std::array<std::wstring, 16> TABLE_COLORS =
static constexpr std::string_view NameKey{ "name" };
static constexpr std::string_view TableKey{ "colors" };
static constexpr std::string_view ForegroundKey{ "foreground" };
static constexpr std::string_view BackgroundKey{ "background" };
static constexpr std::array<std::string_view, 16> TableColors =
{
L"black",
L"red",
L"green",
L"yellow",
L"blue",
L"purple",
L"cyan",
L"white",
L"brightBlack",
L"brightRed",
L"brightGreen",
L"brightYellow",
L"brightBlue",
L"brightPurple",
L"brightCyan",
L"brightWhite"
"black",
"red",
"green",
"yellow",
"blue",
"purple",
"cyan",
"white",
"brightBlack",
"brightRed",
"brightGreen",
"brightYellow",
"brightBlue",
"brightPurple",
"brightCyan",
"brightWhite"
};
ColorScheme::ColorScheme() :
@ -83,29 +84,22 @@ void ColorScheme::ApplyScheme(TerminalSettings terminalSettings) const
// - <none>
// Return Value:
// - a JsonObject which is an equivalent serialization of this object.
JsonObject ColorScheme::ToJson() const
Json::Value ColorScheme::ToJson() const
{
winrt::Windows::Data::Json::JsonObject jsonObject;
Json::Value root;
root[JsonKey(NameKey)] = winrt::to_string(_schemeName);
root[JsonKey(ForegroundKey)] = Utils::ColorToHexString(_defaultForeground);
root[JsonKey(BackgroundKey)] = Utils::ColorToHexString(_defaultBackground);
auto fg = JsonValue::CreateStringValue(Utils::ColorToHexString(_defaultForeground));
auto bg = JsonValue::CreateStringValue(Utils::ColorToHexString(_defaultBackground));
auto name = JsonValue::CreateStringValue(_schemeName);
jsonObject.Insert(NAME_KEY, name);
jsonObject.Insert(FOREGROUND_KEY, fg);
jsonObject.Insert(BACKGROUND_KEY, bg);
int i = 0;
for (const auto& current : TABLE_COLORS)
for (const auto& colorName : TableColors)
{
auto& color = _table.at(i);
auto s = JsonValue::CreateStringValue(Utils::ColorToHexString(color));
jsonObject.Insert(current, s);
auto& colorValue = _table.at(i);
root[JsonKey(colorName)] = Utils::ColorToHexString(colorValue);
i++;
}
return jsonObject;
return root;
}
// Method Description:
@ -114,39 +108,35 @@ JsonObject ColorScheme::ToJson() const
// - json: an object which should be a serialization of a ColorScheme object.
// Return Value:
// - a new ColorScheme instance created from the values in `json`
ColorScheme ColorScheme::FromJson(winrt::Windows::Data::Json::JsonObject json)
ColorScheme ColorScheme::FromJson(const Json::Value& json)
{
ColorScheme result{};
if (json.HasKey(NAME_KEY))
if (auto name{ json[JsonKey(NameKey)] })
{
result._schemeName = json.GetNamedString(NAME_KEY);
result._schemeName = winrt::to_hstring(name.asString());
}
if (json.HasKey(FOREGROUND_KEY))
if (auto fgString{ json[JsonKey(ForegroundKey)] })
{
const auto fgString = json.GetNamedString(FOREGROUND_KEY);
const auto color = Utils::ColorFromHexString(fgString.c_str());
const auto color = Utils::ColorFromHexString(fgString.asString());
result._defaultForeground = color;
}
if (json.HasKey(BACKGROUND_KEY))
if (auto bgString{ json[JsonKey(BackgroundKey)] })
{
const auto bgString = json.GetNamedString(BACKGROUND_KEY);
const auto color = Utils::ColorFromHexString(bgString.c_str());
const auto color = Utils::ColorFromHexString(bgString.asString());
result._defaultBackground = color;
}
// Legacy Deserialization. Leave in place to allow forward compatibility
if (json.HasKey(TABLE_KEY))
if (auto table{ json[JsonKey(TableKey)] })
{
const auto table = json.GetNamedArray(TABLE_KEY);
int i = 0;
for (auto v : table)
for (const auto& tableEntry : table)
{
if (v.ValueType() == JsonValueType::String)
if (tableEntry.isString())
{
auto str = v.GetString();
auto color = Utils::ColorFromHexString(str.c_str());
auto color = Utils::ColorFromHexString(tableEntry.asString());
result._table.at(i) = color;
}
i++;
@ -154,12 +144,11 @@ ColorScheme ColorScheme::FromJson(winrt::Windows::Data::Json::JsonObject json)
}
int i = 0;
for (const auto& current : TABLE_COLORS)
for (const auto& current : TableColors)
{
if (json.HasKey(current))
if (auto str{ json[JsonKey(current)] })
{
const auto str = json.GetNamedString(current);
const auto color = Utils::ColorFromHexString(str.c_str());
const auto color = Utils::ColorFromHexString(str.asString());
result._table.at(i) = color;
}
i++;
@ -168,6 +157,7 @@ ColorScheme ColorScheme::FromJson(winrt::Windows::Data::Json::JsonObject json)
return result;
}
std::wstring_view ColorScheme::GetName() const noexcept
{
return { _schemeName };

View File

@ -19,7 +19,6 @@ Author(s):
#include <winrt/Microsoft.Terminal.TerminalControl.h>
#include <winrt/TerminalApp.h>
#include "../../inc/conattrs.hpp"
#include <conattrs.hpp>
namespace TerminalApp
{
@ -36,8 +35,8 @@ public:
void ApplyScheme(winrt::Microsoft::Terminal::Settings::TerminalSettings terminalSettings) const;
winrt::Windows::Data::Json::JsonObject ToJson() const;
static ColorScheme FromJson(winrt::Windows::Data::Json::JsonObject json);
Json::Value ToJson() const;
static ColorScheme FromJson(const Json::Value& json);
std::wstring_view GetName() const noexcept;
std::array<COLORREF, COLOR_TABLE_SIZE>& GetTable() noexcept;

View File

@ -5,6 +5,8 @@
#include "GlobalAppSettings.h"
#include "../../types/inc/Utils.hpp"
#include "../../inc/DefaultSettings.h"
#include "AppKeyBindingsSerialization.h"
#include "Utils.h"
using namespace TerminalApp;
using namespace winrt::Microsoft::Terminal::Settings;
@ -13,17 +15,18 @@ using namespace winrt::Windows::Data::Json;
using namespace winrt::Windows::UI::Xaml;
using namespace ::Microsoft::Console;
static constexpr std::wstring_view DEFAULTPROFILE_KEY{ L"defaultProfile" };
static constexpr std::wstring_view ALWAYS_SHOW_TABS_KEY{ L"alwaysShowTabs" };
static constexpr std::wstring_view INITIALROWS_KEY{ L"initialRows" };
static constexpr std::wstring_view INITIALCOLS_KEY{ L"initialCols" };
static constexpr std::wstring_view SHOW_TITLE_IN_TITLEBAR_KEY{ L"showTerminalTitleInTitlebar" };
static constexpr std::wstring_view REQUESTED_THEME_KEY{ L"requestedTheme" };
static constexpr std::wstring_view SHOW_TABS_IN_TITLEBAR_KEY{ L"showTabsInTitlebar" };
static constexpr std::string_view KeybindingsKey{ "keybindings" };
static constexpr std::string_view DefaultProfileKey{ "defaultProfile" };
static constexpr std::string_view AlwaysShowTabsKey{ "alwaysShowTabs" };
static constexpr std::string_view InitialRowsKey{ "initialRows" };
static constexpr std::string_view InitialColsKey{ "initialCols" };
static constexpr std::string_view ShowTitleInTitlebarKey{ "showTerminalTitleInTitlebar" };
static constexpr std::string_view RequestedThemeKey{ "requestedTheme" };
static constexpr std::string_view ShowTabsInTitlebarKey{ "showTabsInTitlebar" };
static constexpr std::wstring_view LIGHT_THEME_VALUE{ L"light" };
static constexpr std::wstring_view DARK_THEME_VALUE{ L"dark" };
static constexpr std::wstring_view SYSTEM_THEME_VALUE{ L"system" };
static constexpr std::wstring_view LightThemeValue{ L"light" };
static constexpr std::wstring_view DarkThemeValue{ L"dark" };
static constexpr std::wstring_view SystemThemeValue{ L"system" };
GlobalAppSettings::GlobalAppSettings() :
_keybindings{},
@ -136,30 +139,18 @@ void GlobalAppSettings::ApplyToSettings(TerminalSettings& settings) const noexce
// - <none>
// Return Value:
// - a JsonObject which is an equivalent serialization of this object.
JsonObject GlobalAppSettings::ToJson() const
Json::Value GlobalAppSettings::ToJson() const
{
winrt::Windows::Data::Json::JsonObject jsonObject;
Json::Value jsonObject;
const auto guidStr = Utils::GuidToString(_defaultProfile);
const auto defaultProfile = JsonValue::CreateStringValue(guidStr);
const auto initialRows = JsonValue::CreateNumberValue(_initialRows);
const auto initialCols = JsonValue::CreateNumberValue(_initialCols);
jsonObject.Insert(DEFAULTPROFILE_KEY, defaultProfile);
jsonObject.Insert(INITIALROWS_KEY, initialRows);
jsonObject.Insert(INITIALCOLS_KEY, initialCols);
jsonObject.Insert(ALWAYS_SHOW_TABS_KEY,
JsonValue::CreateBooleanValue(_alwaysShowTabs));
jsonObject.Insert(SHOW_TITLE_IN_TITLEBAR_KEY,
JsonValue::CreateBooleanValue(_showTitleInTitlebar));
jsonObject.Insert(SHOW_TABS_IN_TITLEBAR_KEY,
JsonValue::CreateBooleanValue(_showTabsInTitlebar));
jsonObject.Insert(REQUESTED_THEME_KEY,
JsonValue::CreateStringValue(_SerializeTheme(_requestedTheme)));
// We'll add the keybindings later in CascadiaSettings, because if we do it
// here, they'll appear before the profiles.
jsonObject[JsonKey(DefaultProfileKey)] = winrt::to_string(Utils::GuidToString(_defaultProfile));
jsonObject[JsonKey(InitialRowsKey)] = _initialRows;
jsonObject[JsonKey(InitialColsKey)] = _initialCols;
jsonObject[JsonKey(AlwaysShowTabsKey)] = _alwaysShowTabs;
jsonObject[JsonKey(ShowTitleInTitlebarKey)] = _showTitleInTitlebar;
jsonObject[JsonKey(ShowTabsInTitlebarKey)] = _showTabsInTitlebar;
jsonObject[JsonKey(RequestedThemeKey)] = winrt::to_string(_SerializeTheme(_requestedTheme));
jsonObject[JsonKey(KeybindingsKey)] = AppKeyBindingsSerialization::ToJson(_keybindings);
return jsonObject;
}
@ -170,49 +161,53 @@ JsonObject GlobalAppSettings::ToJson() const
// - json: an object which should be a serialization of a GlobalAppSettings object.
// Return Value:
// - a new GlobalAppSettings instance created from the values in `json`
GlobalAppSettings GlobalAppSettings::FromJson(winrt::Windows::Data::Json::JsonObject json)
GlobalAppSettings GlobalAppSettings::FromJson(const Json::Value& json)
{
GlobalAppSettings result{};
if (json.HasKey(DEFAULTPROFILE_KEY))
if (auto defaultProfile{ json[JsonKey(DefaultProfileKey)] })
{
auto guidString = json.GetNamedString(DEFAULTPROFILE_KEY);
auto guid = Utils::GuidFromString(guidString.c_str());
auto guid = Utils::GuidFromString(GetWstringFromJson(defaultProfile));
result._defaultProfile = guid;
}
if (json.HasKey(ALWAYS_SHOW_TABS_KEY))
if (auto alwaysShowTabs{ json[JsonKey(AlwaysShowTabsKey)] })
{
result._alwaysShowTabs = json.GetNamedBoolean(ALWAYS_SHOW_TABS_KEY);
result._alwaysShowTabs = alwaysShowTabs.asBool();
}
if (json.HasKey(INITIALROWS_KEY))
if (auto initialRows{ json[JsonKey(InitialRowsKey)] })
{
result._initialRows = static_cast<int32_t>(json.GetNamedNumber(INITIALROWS_KEY));
result._initialRows = initialRows.asInt();
}
if (json.HasKey(INITIALCOLS_KEY))
if (auto initialCols{ json[JsonKey(InitialColsKey)] })
{
result._initialCols = static_cast<int32_t>(json.GetNamedNumber(INITIALCOLS_KEY));
result._initialCols = initialCols.asInt();
}
if (json.HasKey(SHOW_TITLE_IN_TITLEBAR_KEY))
if (auto showTitleInTitlebar{ json[JsonKey(ShowTitleInTitlebarKey)] })
{
result._showTitleInTitlebar = json.GetNamedBoolean(SHOW_TITLE_IN_TITLEBAR_KEY);
result._showTitleInTitlebar = showTitleInTitlebar.asBool();
}
if (json.HasKey(SHOW_TABS_IN_TITLEBAR_KEY))
if (auto showTabsInTitlebar{ json[JsonKey(ShowTabsInTitlebarKey)] })
{
result._showTabsInTitlebar = json.GetNamedBoolean(SHOW_TABS_IN_TITLEBAR_KEY);
result._showTabsInTitlebar = showTabsInTitlebar.asBool();
}
if (json.HasKey(REQUESTED_THEME_KEY))
if (auto requestedTheme{ json[JsonKey(RequestedThemeKey)] })
{
const auto themeStr = json.GetNamedString(REQUESTED_THEME_KEY);
result._requestedTheme = _ParseTheme(themeStr.c_str());
result._requestedTheme = _ParseTheme(GetWstringFromJson(requestedTheme));
}
if (auto keybindings{ json[JsonKey(KeybindingsKey)] })
{
result._keybindings = AppKeyBindingsSerialization::FromJson(keybindings);
}
return result;
}
// Method Description:
// - Helper function for converting a user-specified cursor style corresponding
// CursorStyle enum value
@ -222,15 +217,15 @@ GlobalAppSettings GlobalAppSettings::FromJson(winrt::Windows::Data::Json::JsonOb
// - The corresponding enum value which maps to the string provided by the user
ElementTheme GlobalAppSettings::_ParseTheme(const std::wstring& themeString) noexcept
{
if (themeString == LIGHT_THEME_VALUE)
if (themeString == LightThemeValue)
{
return ElementTheme::Light;
}
else if (themeString == DARK_THEME_VALUE)
else if (themeString == DarkThemeValue)
{
return ElementTheme::Dark;
}
// default behavior for invalid data or SYSTEM_THEME_VALUE
// default behavior for invalid data or SystemThemeValue
return ElementTheme::Default;
}
@ -246,10 +241,10 @@ std::wstring_view GlobalAppSettings::_SerializeTheme(const ElementTheme theme) n
switch (theme)
{
case ElementTheme::Light:
return LIGHT_THEME_VALUE;
return LightThemeValue;
case ElementTheme::Dark:
return DARK_THEME_VALUE;
return DarkThemeValue;
default:
return SYSTEM_THEME_VALUE;
return SystemThemeValue;
}
}

View File

@ -50,8 +50,8 @@ public:
winrt::Windows::UI::Xaml::ElementTheme GetRequestedTheme() const noexcept;
winrt::Windows::Data::Json::JsonObject ToJson() const;
static GlobalAppSettings FromJson(winrt::Windows::Data::Json::JsonObject json);
Json::Value ToJson() const;
static GlobalAppSettings FromJson(const Json::Value& json);
void ApplyToSettings(winrt::Microsoft::Terminal::Settings::TerminalSettings& settings) const noexcept;

View File

@ -3,6 +3,7 @@
#include "pch.h"
#include "Profile.h"
#include "Utils.h"
#include "../../types/inc/Utils.hpp"
#include <DefaultSettings.h>
@ -12,50 +13,50 @@ using namespace winrt::TerminalApp;
using namespace winrt::Windows::Data::Json;
using namespace ::Microsoft::Console;
static constexpr std::wstring_view NAME_KEY{ L"name" };
static constexpr std::wstring_view GUID_KEY{ L"guid" };
static constexpr std::wstring_view COLORSCHEME_KEY{ L"colorScheme" };
static constexpr std::wstring_view COLORSCHEME_KEY_OLD{ L"colorscheme" };
static constexpr std::string_view NameKey{ "name" };
static constexpr std::string_view GuidKey{ "guid" };
static constexpr std::string_view ColorSchemeKey{ "colorScheme" };
static constexpr std::string_view ColorSchemeKeyOld{ "colorscheme" };
static constexpr std::wstring_view FOREGROUND_KEY{ L"foreground" };
static constexpr std::wstring_view BACKGROUND_KEY{ L"background" };
static constexpr std::wstring_view COLORTABLE_KEY{ L"colorTable" };
static constexpr std::wstring_view HISTORYSIZE_KEY{ L"historySize" };
static constexpr std::wstring_view SNAPONINPUT_KEY{ L"snapOnInput" };
static constexpr std::wstring_view CURSORCOLOR_KEY{ L"cursorColor" };
static constexpr std::wstring_view CURSORSHAPE_KEY{ L"cursorShape" };
static constexpr std::wstring_view CURSORHEIGHT_KEY{ L"cursorHeight" };
static constexpr std::string_view ForegroundKey{ "foreground" };
static constexpr std::string_view BackgroundKey{ "background" };
static constexpr std::string_view ColorTableKey{ "colorTable" };
static constexpr std::string_view HistorySizeKey{ "historySize" };
static constexpr std::string_view SnapOnInputKey{ "snapOnInput" };
static constexpr std::string_view CursorColorKey{ "cursorColor" };
static constexpr std::string_view CursorShapeKey{ "cursorShape" };
static constexpr std::string_view CursorHeightKey{ "cursorHeight" };
static constexpr std::wstring_view COMMANDLINE_KEY{ L"commandline" };
static constexpr std::wstring_view FONTFACE_KEY{ L"fontFace" };
static constexpr std::wstring_view FONTSIZE_KEY{ L"fontSize" };
static constexpr std::wstring_view ACRYLICTRANSPARENCY_KEY{ L"acrylicOpacity" };
static constexpr std::wstring_view USEACRYLIC_KEY{ L"useAcrylic" };
static constexpr std::wstring_view SCROLLBARSTATE_KEY{ L"scrollbarState" };
static constexpr std::wstring_view CLOSEONEXIT_KEY{ L"closeOnExit" };
static constexpr std::wstring_view PADDING_KEY{ L"padding" };
static constexpr std::wstring_view STARTINGDIRECTORY_KEY{ L"startingDirectory" };
static constexpr std::wstring_view ICON_KEY{ L"icon" };
static constexpr std::wstring_view BACKGROUNDIMAGE_KEY{ L"backgroundImage" };
static constexpr std::wstring_view BACKGROUNDIMAGEOPACITY_KEY{ L"backgroundImageOpacity" };
static constexpr std::wstring_view BACKGROUNDIMAGESTRETCHMODE_KEY{ L"backgroundImageStretchMode" };
static constexpr std::string_view CommandlineKey{ "commandline" };
static constexpr std::string_view FontFaceKey{ "fontFace" };
static constexpr std::string_view FontSizeKey{ "fontSize" };
static constexpr std::string_view AcrylicTransparencyKey{ "acrylicOpacity" };
static constexpr std::string_view UseAcrylicKey{ "useAcrylic" };
static constexpr std::string_view ScrollbarStateKey{ "scrollbarState" };
static constexpr std::string_view CloseOnExitKey{ "closeOnExit" };
static constexpr std::string_view PaddingKey{ "padding" };
static constexpr std::string_view StartingDirectoryKey{ "startingDirectory" };
static constexpr std::string_view IconKey{ "icon" };
static constexpr std::string_view BackgroundImageKey{ "backgroundImage" };
static constexpr std::string_view BackgroundImageOpacityKey{ "backgroundImageOpacity" };
static constexpr std::string_view BackgroundimageStretchModeKey{ "backgroundImageStretchMode" };
// Possible values for Scrollbar state
static constexpr std::wstring_view ALWAYS_VISIBLE{ L"visible" };
static constexpr std::wstring_view ALWAYS_HIDE{ L"hidden" };
static constexpr std::wstring_view AlwaysVisible{ L"visible" };
static constexpr std::wstring_view AlwaysHide{ L"hidden" };
// Possible values for Cursor Shape
static constexpr std::wstring_view CURSORSHAPE_VINTAGE{ L"vintage" };
static constexpr std::wstring_view CURSORSHAPE_BAR{ L"bar" };
static constexpr std::wstring_view CURSORSHAPE_UNDERSCORE{ L"underscore" };
static constexpr std::wstring_view CURSORSHAPE_FILLEDBOX{ L"filledBox" };
static constexpr std::wstring_view CURSORSHAPE_EMPTYBOX{ L"emptyBox" };
static constexpr std::wstring_view CursorShapeVintage{ L"vintage" };
static constexpr std::wstring_view CursorShapeBar{ L"bar" };
static constexpr std::wstring_view CursorShapeUnderscore{ L"underscore" };
static constexpr std::wstring_view CursorShapeFilledbox{ L"filledBox" };
static constexpr std::wstring_view CursorShapeEmptybox{ L"emptyBox" };
// Possible values for Image Stretch Mode
static constexpr std::wstring_view IMAGESTRETCHMODE_NONE{ L"none" };
static constexpr std::wstring_view IMAGESTRETCHMODE_FILL{ L"fill" };
static constexpr std::wstring_view IMAGESTRETCHMODE_UNIFORM{ L"uniform" };
static constexpr std::wstring_view IMAGESTRETCHMODE_UNIFORMTOFILL{ L"uniformToFill" };
static constexpr std::string_view ImageStretchModeNone{ "none" };
static constexpr std::string_view ImageStretchModeFill{ "fill" };
static constexpr std::string_view ImageStretchModeUniform{ "uniform" };
static constexpr std::string_view ImageStretchModeUniformTofill{ "uniformToFill" };
Profile::Profile() :
Profile(Utils::CreateGuid())
@ -209,118 +210,89 @@ TerminalSettings Profile::CreateTerminalSettings(const std::vector<ColorScheme>&
// - <none>
// Return Value:
// - a JsonObject which is an equivalent serialization of this object.
JsonObject Profile::ToJson() const
Json::Value Profile::ToJson() const
{
winrt::Windows::Data::Json::JsonObject jsonObject;
Json::Value root;
// Profile-specific settings
const auto guidStr = Utils::GuidToString(_guid);
const auto guid = JsonValue::CreateStringValue(guidStr);
const auto name = JsonValue::CreateStringValue(_name);
///// Profile-specific settings /////
root[JsonKey(GuidKey)] = winrt::to_string(Utils::GuidToString(_guid));
root[JsonKey(NameKey)] = winrt::to_string(_name);
// Core Settings
const auto historySize = JsonValue::CreateNumberValue(_historySize);
const auto snapOnInput = JsonValue::CreateBooleanValue(_snapOnInput);
const auto cursorColor = JsonValue::CreateStringValue(Utils::ColorToHexString(_cursorColor));
// Control Settings
const auto cmdline = JsonValue::CreateStringValue(_commandline);
const auto fontFace = JsonValue::CreateStringValue(_fontFace);
const auto fontSize = JsonValue::CreateNumberValue(_fontSize);
const auto acrylicTransparency = JsonValue::CreateNumberValue(_acrylicTransparency);
const auto useAcrylic = JsonValue::CreateBooleanValue(_useAcrylic);
const auto closeOnExit = JsonValue::CreateBooleanValue(_closeOnExit);
const auto padding = JsonValue::CreateStringValue(_padding);
if (_startingDirectory)
{
const auto startingDirectory = JsonValue::CreateStringValue(_startingDirectory.value());
jsonObject.Insert(STARTINGDIRECTORY_KEY, startingDirectory);
}
jsonObject.Insert(GUID_KEY, guid);
jsonObject.Insert(NAME_KEY, name);
// Core Settings
///// Core Settings /////
if (_defaultForeground)
{
const auto defaultForeground = JsonValue::CreateStringValue(Utils::ColorToHexString(_defaultForeground.value()));
jsonObject.Insert(FOREGROUND_KEY, defaultForeground);
root[JsonKey(ForegroundKey)] = Utils::ColorToHexString(_defaultForeground.value());
}
if (_defaultBackground)
{
const auto defaultBackground = JsonValue::CreateStringValue(Utils::ColorToHexString(_defaultBackground.value()));
jsonObject.Insert(BACKGROUND_KEY, defaultBackground);
root[JsonKey(BackgroundKey)] = Utils::ColorToHexString(_defaultBackground.value());
}
if (_schemeName)
{
const auto scheme = JsonValue::CreateStringValue(_schemeName.value());
jsonObject.Insert(COLORSCHEME_KEY, scheme);
const auto scheme = winrt::to_string(_schemeName.value());
root[JsonKey(ColorSchemeKey)] = scheme;
}
else
{
JsonArray tableArray{};
Json::Value tableArray{};
for (auto& color : _colorTable)
{
auto s = Utils::ColorToHexString(color);
tableArray.Append(JsonValue::CreateStringValue(s));
tableArray.append(Utils::ColorToHexString(color));
}
jsonObject.Insert(COLORTABLE_KEY, tableArray);
root[JsonKey(ColorTableKey)] = tableArray;
}
jsonObject.Insert(HISTORYSIZE_KEY, historySize);
jsonObject.Insert(SNAPONINPUT_KEY, snapOnInput);
jsonObject.Insert(CURSORCOLOR_KEY, cursorColor);
root[JsonKey(HistorySizeKey)] = _historySize;
root[JsonKey(SnapOnInputKey)] = _snapOnInput;
root[JsonKey(CursorColorKey)] = Utils::ColorToHexString(_cursorColor);
// Only add the cursor height property if we're a legacy-style cursor.
if (_cursorShape == CursorStyle::Vintage)
{
jsonObject.Insert(CURSORHEIGHT_KEY, JsonValue::CreateNumberValue(_cursorHeight));
root[JsonKey(CursorHeightKey)] = _cursorHeight;
}
jsonObject.Insert(CURSORSHAPE_KEY, JsonValue::CreateStringValue(_SerializeCursorStyle(_cursorShape)));
root[JsonKey(CursorShapeKey)] = winrt::to_string(_SerializeCursorStyle(_cursorShape));
// Control Settings
jsonObject.Insert(COMMANDLINE_KEY, cmdline);
jsonObject.Insert(FONTFACE_KEY, fontFace);
jsonObject.Insert(FONTSIZE_KEY, fontSize);
jsonObject.Insert(ACRYLICTRANSPARENCY_KEY, acrylicTransparency);
jsonObject.Insert(USEACRYLIC_KEY, useAcrylic);
jsonObject.Insert(CLOSEONEXIT_KEY, closeOnExit);
jsonObject.Insert(PADDING_KEY, padding);
///// Control Settings /////
root[JsonKey(CommandlineKey)] = winrt::to_string(_commandline);
root[JsonKey(FontFaceKey)] = winrt::to_string(_fontFace);
root[JsonKey(FontSizeKey)] = _fontSize;
root[JsonKey(AcrylicTransparencyKey)] = _acrylicTransparency;
root[JsonKey(UseAcrylicKey)] = _useAcrylic;
root[JsonKey(CloseOnExitKey)] = _closeOnExit;
root[JsonKey(PaddingKey)] = winrt::to_string(_padding);
if (_scrollbarState)
{
const auto scrollbarState = JsonValue::CreateStringValue(_scrollbarState.value());
jsonObject.Insert(SCROLLBARSTATE_KEY, scrollbarState);
const auto scrollbarState = winrt::to_string(_scrollbarState.value());
root[JsonKey(ScrollbarStateKey)] = scrollbarState;
}
if (_icon)
{
const auto icon = JsonValue::CreateStringValue(_icon.value());
jsonObject.Insert(ICON_KEY, icon);
const auto icon = winrt::to_string(_icon.value());
root[JsonKey(IconKey)] = icon;
}
if (_startingDirectory)
{
root[JsonKey(StartingDirectoryKey)] = winrt::to_string(_startingDirectory.value());
}
if (_backgroundImage)
{
const auto backgroundImage = JsonValue::CreateStringValue(_backgroundImage.value());
jsonObject.Insert(BACKGROUNDIMAGE_KEY, backgroundImage);
root[JsonKey(BackgroundImageKey)] = winrt::to_string(_backgroundImage.value());
}
if (_backgroundImageOpacity)
{
const auto opacity = JsonValue::CreateNumberValue(_backgroundImageOpacity.value());
jsonObject.Insert(BACKGROUNDIMAGEOPACITY_KEY, opacity);
root[JsonKey(BackgroundImageOpacityKey)] = _backgroundImageOpacity.value();
}
if (_backgroundImageStretchMode)
{
const auto imageStretchMode = JsonValue::CreateStringValue(
SerializeImageStretchMode(_backgroundImageStretchMode.value()));
jsonObject.Insert(BACKGROUNDIMAGESTRETCHMODE_KEY, imageStretchMode);
root[JsonKey(BackgroundimageStretchModeKey)] = SerializeImageStretchMode(_backgroundImageStretchMode.value()).data();
}
return jsonObject;
return root;
}
// Method Description:
@ -329,149 +301,133 @@ JsonObject Profile::ToJson() const
// - json: an object which should be a serialization of a Profile object.
// Return Value:
// - a new Profile instance created from the values in `json`
Profile Profile::FromJson(winrt::Windows::Data::Json::JsonObject json)
Profile Profile::FromJson(const Json::Value& json)
{
Profile result{};
// Profile-specific Settings
if (json.HasKey(NAME_KEY))
if (auto name{ json[JsonKey(NameKey)] })
{
result._name = json.GetNamedString(NAME_KEY);
result._name = GetWstringFromJson(name);
}
if (json.HasKey(GUID_KEY))
if (auto guid{ json[JsonKey(GuidKey)] })
{
const auto guidString = json.GetNamedString(GUID_KEY);
// TODO: MSFT:20737698 - if this fails, display an approriate error
const auto guid = Utils::GuidFromString(guidString.c_str());
result._guid = guid;
result._guid = Utils::GuidFromString(GetWstringFromJson(guid));
}
// Core Settings
if (json.HasKey(FOREGROUND_KEY))
if (auto foreground{ json[JsonKey(ForegroundKey)] })
{
const auto fgString = json.GetNamedString(FOREGROUND_KEY);
// TODO: MSFT:20737698 - if this fails, display an approriate error
const auto color = Utils::ColorFromHexString(fgString.c_str());
const auto color = Utils::ColorFromHexString(foreground.asString());
result._defaultForeground = color;
}
if (json.HasKey(BACKGROUND_KEY))
if (auto background{ json[JsonKey(BackgroundKey)] })
{
const auto bgString = json.GetNamedString(BACKGROUND_KEY);
// TODO: MSFT:20737698 - if this fails, display an approriate error
const auto color = Utils::ColorFromHexString(bgString.c_str());
const auto color = Utils::ColorFromHexString(background.asString());
result._defaultBackground = color;
}
if (json.HasKey(COLORSCHEME_KEY))
if (auto colorScheme{ json[JsonKey(ColorSchemeKey)] })
{
result._schemeName = json.GetNamedString(COLORSCHEME_KEY);
result._schemeName = GetWstringFromJson(colorScheme);
}
else if (json.HasKey(COLORSCHEME_KEY_OLD))
else if (auto colorScheme{ json[JsonKey(ColorSchemeKeyOld)] })
{
// TODO: deprecate old settings key
result._schemeName = json.GetNamedString(COLORSCHEME_KEY_OLD);
// TODO:GH#1069 deprecate old settings key
result._schemeName = GetWstringFromJson(colorScheme);
}
else if (json.HasKey(COLORTABLE_KEY))
else if (auto colortable{ json[JsonKey(ColorTableKey)] })
{
const auto table = json.GetNamedArray(COLORTABLE_KEY);
int i = 0;
for (auto v : table)
for (const auto& tableEntry : colortable)
{
if (v.ValueType() == JsonValueType::String)
if (tableEntry.isString())
{
const auto str = v.GetString();
// TODO: MSFT:20737698 - if this fails, display an approriate error
const auto color = Utils::ColorFromHexString(str.c_str());
const auto color = Utils::ColorFromHexString(tableEntry.asString());
result._colorTable[i] = color;
}
i++;
}
}
if (json.HasKey(HISTORYSIZE_KEY))
if (auto historySize{ json[JsonKey(HistorySizeKey)] })
{
// TODO:MSFT:20642297 - Use a sentinel value (-1) for "Infinite scrollback"
result._historySize = static_cast<int32_t>(json.GetNamedNumber(HISTORYSIZE_KEY));
result._historySize = historySize.asInt();
}
if (json.HasKey(SNAPONINPUT_KEY))
if (auto snapOnInput{ json[JsonKey(SnapOnInputKey)] })
{
result._snapOnInput = json.GetNamedBoolean(SNAPONINPUT_KEY);
result._snapOnInput = snapOnInput.asBool();
}
if (json.HasKey(CURSORCOLOR_KEY))
if (auto cursorColor{ json[JsonKey(CursorColorKey)] })
{
const auto cursorString = json.GetNamedString(CURSORCOLOR_KEY);
// TODO: MSFT:20737698 - if this fails, display an approriate error
const auto color = Utils::ColorFromHexString(cursorString.c_str());
const auto color = Utils::ColorFromHexString(cursorColor.asString());
result._cursorColor = color;
}
if (json.HasKey(CURSORHEIGHT_KEY))
if (auto cursorHeight{ json[JsonKey(CursorHeightKey)] })
{
result._cursorHeight = static_cast<uint32_t>(json.GetNamedNumber(CURSORHEIGHT_KEY));
result._cursorHeight = cursorHeight.asUInt();
}
if (json.HasKey(CURSORSHAPE_KEY))
if (auto cursorShape{ json[JsonKey(CursorShapeKey)] })
{
const auto shapeString = json.GetNamedString(CURSORSHAPE_KEY);
result._cursorShape = _ParseCursorShape(shapeString.c_str());
result._cursorShape = _ParseCursorShape(GetWstringFromJson(cursorShape));
}
// Control Settings
if (json.HasKey(COMMANDLINE_KEY))
if (auto commandline{ json[JsonKey(CommandlineKey)] })
{
result._commandline = json.GetNamedString(COMMANDLINE_KEY);
result._commandline = GetWstringFromJson(commandline);
}
if (json.HasKey(FONTFACE_KEY))
if (auto fontFace{ json[JsonKey(FontFaceKey)] })
{
result._fontFace = json.GetNamedString(FONTFACE_KEY);
result._fontFace = GetWstringFromJson(fontFace);
}
if (json.HasKey(FONTSIZE_KEY))
if (auto fontSize{ json[JsonKey(FontSizeKey)] })
{
result._fontSize = static_cast<int32_t>(json.GetNamedNumber(FONTSIZE_KEY));
result._fontSize = fontSize.asInt();
}
if (json.HasKey(ACRYLICTRANSPARENCY_KEY))
if (auto acrylicTransparency{ json[JsonKey(AcrylicTransparencyKey)] })
{
result._acrylicTransparency = json.GetNamedNumber(ACRYLICTRANSPARENCY_KEY);
result._acrylicTransparency = acrylicTransparency.asFloat();
}
if (json.HasKey(USEACRYLIC_KEY))
if (auto useAcrylic{ json[JsonKey(UseAcrylicKey)] })
{
result._useAcrylic = json.GetNamedBoolean(USEACRYLIC_KEY);
result._useAcrylic = useAcrylic.asBool();
}
if (json.HasKey(CLOSEONEXIT_KEY))
if (auto closeOnExit{ json[JsonKey(CloseOnExitKey)] })
{
result._closeOnExit = json.GetNamedBoolean(CLOSEONEXIT_KEY);
result._closeOnExit = closeOnExit.asBool();
}
if (json.HasKey(PADDING_KEY))
if (auto padding{ json[JsonKey(PaddingKey)] })
{
result._padding = json.GetNamedString(PADDING_KEY);
result._padding = GetWstringFromJson(padding);
}
if (json.HasKey(SCROLLBARSTATE_KEY))
if (auto scrollbarState{ json[JsonKey(ScrollbarStateKey)] })
{
result._scrollbarState = json.GetNamedString(SCROLLBARSTATE_KEY);
result._scrollbarState = GetWstringFromJson(scrollbarState);
}
if (json.HasKey(STARTINGDIRECTORY_KEY))
if (auto startingDirectory{ json[JsonKey(StartingDirectoryKey)] })
{
result._startingDirectory = json.GetNamedString(STARTINGDIRECTORY_KEY);
result._startingDirectory = GetWstringFromJson(startingDirectory);
}
if (json.HasKey(ICON_KEY))
if (auto icon{ json[JsonKey(IconKey)] })
{
result._icon = json.GetNamedString(ICON_KEY);
result._icon = GetWstringFromJson(icon);
}
if (json.HasKey(BACKGROUNDIMAGE_KEY))
if (auto backgroundImage{ json[JsonKey(BackgroundImageKey)] })
{
result._backgroundImage = json.GetNamedString(BACKGROUNDIMAGE_KEY);
result._backgroundImage = GetWstringFromJson(backgroundImage);
}
if (json.HasKey(BACKGROUNDIMAGEOPACITY_KEY))
if (auto backgroundImageOpacity{ json[JsonKey(BackgroundImageOpacityKey)] })
{
result._backgroundImageOpacity = json.GetNamedNumber(BACKGROUNDIMAGEOPACITY_KEY);
result._backgroundImageOpacity = backgroundImageOpacity.asFloat();
}
if (json.HasKey(BACKGROUNDIMAGESTRETCHMODE_KEY))
if (auto backgroundImageStretchMode{ json[JsonKey(BackgroundimageStretchModeKey)] })
{
const auto stretchMode = json.GetNamedString(BACKGROUNDIMAGESTRETCHMODE_KEY);
result._backgroundImageStretchMode = ParseImageStretchMode(stretchMode.c_str());
result._backgroundImageStretchMode = ParseImageStretchMode(backgroundImageStretchMode.asString());
}
return result;
}
void Profile::SetFontFace(std::wstring fontFace) noexcept
{
_fontFace = fontFace;
@ -597,17 +553,16 @@ std::wstring Profile::EvaluateStartingDirectory(const std::wstring& directory)
// - The corresponding enum value which maps to the string provided by the user
ScrollbarState Profile::ParseScrollbarState(const std::wstring& scrollbarState)
{
if (scrollbarState == ALWAYS_VISIBLE)
if (scrollbarState == AlwaysVisible)
{
return ScrollbarState::Visible;
}
else if (scrollbarState == ALWAYS_HIDE)
else if (scrollbarState == AlwaysHide)
{
return ScrollbarState::Hidden;
}
else
{
// default behavior for invalid data
return ScrollbarState::Visible;
}
}
@ -619,17 +574,17 @@ ScrollbarState Profile::ParseScrollbarState(const std::wstring& scrollbarState)
// - The value from the profiles.json file
// Return Value:
// - The corresponding enum value which maps to the string provided by the user
winrt::Windows::UI::Xaml::Media::Stretch Profile::ParseImageStretchMode(const std::wstring& imageStretchMode)
winrt::Windows::UI::Xaml::Media::Stretch Profile::ParseImageStretchMode(const std::string_view imageStretchMode)
{
if (imageStretchMode == IMAGESTRETCHMODE_NONE)
if (imageStretchMode == ImageStretchModeNone)
{
return winrt::Windows::UI::Xaml::Media::Stretch::None;
}
else if (imageStretchMode == IMAGESTRETCHMODE_FILL)
else if (imageStretchMode == ImageStretchModeFill)
{
return winrt::Windows::UI::Xaml::Media::Stretch::Fill;
}
else if (imageStretchMode == IMAGESTRETCHMODE_UNIFORM)
else if (imageStretchMode == ImageStretchModeUniform)
{
return winrt::Windows::UI::Xaml::Media::Stretch::Uniform;
}
@ -640,30 +595,28 @@ winrt::Windows::UI::Xaml::Media::Stretch Profile::ParseImageStretchMode(const st
}
// Method Description:
// - Helper function for converting an ImageStretchMode to the
// - Helper function for converting an ImageStretchMode to the
// correct string value.
// Arguments:
// - imageStretchMode: The enum value to convert to a string.
// Return Value:
// - The string value for the given ImageStretchMode
std::wstring_view Profile::SerializeImageStretchMode(const winrt::Windows::UI::Xaml::Media::Stretch imageStretchMode)
std::string_view Profile::SerializeImageStretchMode(const winrt::Windows::UI::Xaml::Media::Stretch imageStretchMode)
{
switch (imageStretchMode)
{
case winrt::Windows::UI::Xaml::Media::Stretch::None:
return IMAGESTRETCHMODE_NONE;
return ImageStretchModeNone;
case winrt::Windows::UI::Xaml::Media::Stretch::Fill:
return IMAGESTRETCHMODE_FILL;
return ImageStretchModeFill;
case winrt::Windows::UI::Xaml::Media::Stretch::Uniform:
return IMAGESTRETCHMODE_UNIFORM;
return ImageStretchModeUniform;
default:
case winrt::Windows::UI::Xaml::Media::Stretch::UniformToFill:
return IMAGESTRETCHMODE_UNIFORMTOFILL;
return ImageStretchModeUniformTofill;
}
}
// Method Description:
// - Helper function for converting a user-specified cursor style corresponding
// CursorStyle enum value
@ -673,23 +626,23 @@ std::wstring_view Profile::SerializeImageStretchMode(const winrt::Windows::UI::X
// - The corresponding enum value which maps to the string provided by the user
CursorStyle Profile::_ParseCursorShape(const std::wstring& cursorShapeString)
{
if (cursorShapeString == CURSORSHAPE_VINTAGE)
if (cursorShapeString == CursorShapeVintage)
{
return CursorStyle::Vintage;
}
else if (cursorShapeString == CURSORSHAPE_BAR)
else if (cursorShapeString == CursorShapeBar)
{
return CursorStyle::Bar;
}
else if (cursorShapeString == CURSORSHAPE_UNDERSCORE)
else if (cursorShapeString == CursorShapeUnderscore)
{
return CursorStyle::Underscore;
}
else if (cursorShapeString == CURSORSHAPE_FILLEDBOX)
else if (cursorShapeString == CursorShapeFilledbox)
{
return CursorStyle::FilledBox;
}
else if (cursorShapeString == CURSORSHAPE_EMPTYBOX)
else if (cursorShapeString == CursorShapeEmptybox)
{
return CursorStyle::EmptyBox;
}
@ -709,15 +662,15 @@ std::wstring_view Profile::_SerializeCursorStyle(const CursorStyle cursorShape)
switch (cursorShape)
{
case CursorStyle::Underscore:
return CURSORSHAPE_UNDERSCORE;
return CursorShapeUnderscore;
case CursorStyle::FilledBox:
return CURSORSHAPE_FILLEDBOX;
return CursorShapeFilledbox;
case CursorStyle::EmptyBox:
return CURSORSHAPE_EMPTYBOX;
return CursorShapeEmptybox;
case CursorStyle::Vintage:
return CURSORSHAPE_VINTAGE;
return CursorShapeVintage;
default:
case CursorStyle::Bar:
return CURSORSHAPE_BAR;
return CursorShapeBar;
}
}

View File

@ -32,8 +32,8 @@ public:
winrt::Microsoft::Terminal::Settings::TerminalSettings CreateTerminalSettings(const std::vector<::TerminalApp::ColorScheme>& schemes) const;
winrt::Windows::Data::Json::JsonObject ToJson() const;
static Profile FromJson(winrt::Windows::Data::Json::JsonObject json);
Json::Value ToJson() const;
static Profile FromJson(const Json::Value& json);
GUID GetGuid() const noexcept;
std::wstring_view GetName() const noexcept;
@ -59,8 +59,8 @@ private:
static std::wstring EvaluateStartingDirectory(const std::wstring& directory);
static winrt::Microsoft::Terminal::Settings::ScrollbarState ParseScrollbarState(const std::wstring& scrollbarState);
static winrt::Windows::UI::Xaml::Media::Stretch ParseImageStretchMode(const std::wstring& imageStretchMode);
static std::wstring_view SerializeImageStretchMode(const winrt::Windows::UI::Xaml::Media::Stretch imageStretchMode);
static winrt::Windows::UI::Xaml::Media::Stretch ParseImageStretchMode(const std::string_view imageStretchMode);
static std::string_view SerializeImageStretchMode(const winrt::Windows::UI::Xaml::Media::Stretch imageStretchMode);
static winrt::Microsoft::Terminal::Settings::CursorStyle _ParseCursorShape(const std::wstring& cursorShapeString);
static std::wstring_view _SerializeCursorStyle(const winrt::Microsoft::Terminal::Settings::CursorStyle cursorShape);

View File

@ -41,7 +41,9 @@
<ClInclude Include="GlobalAppSettings.h" />
<ClInclude Include="Profile.h" />
<ClInclude Include="CascadiaSettings.h" />
<ClInclude Include="AppKeyBindingsSerialization.h" />
<ClInclude Include="KeyChordSerialization.h" />
<ClInclude Include="Utils.h" />
<ClInclude Include="pch.h" />
<ClInclude Include="AppKeyBindings.h">
<DependentUpon>AppKeyBindings.idl</DependentUpon>
@ -59,7 +61,9 @@
<ClCompile Include="Profile.cpp" />
<ClCompile Include="CascadiaSettings.cpp" />
<ClCompile Include="CascadiaSettingsSerialization.cpp" />
<ClCompile Include="AppKeyBindingsSerialization.cpp" />
<ClCompile Include="KeyChordSerialization.cpp" />
<ClCompile Include="Utils.cpp" />
<ClCompile Include="pch.cpp">
<PrecompiledHeader>Create</PrecompiledHeader>
</ClCompile>
@ -70,6 +74,13 @@
<DependentUpon>App.xaml</DependentUpon>
</ClCompile>
<ClCompile Include="$(GeneratedFilesDir)module.g.cpp" />
<!-- You _NEED_ to include this file and the jsoncpp IncludePath (below) if
you want to use jsoncpp -->
<ClCompile Include="$(OpenConsoleDir)\dep\jsoncpp\jsoncpp.cpp">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
</ItemGroup>
<!-- ========================= idl Files ======================== -->
@ -117,6 +128,10 @@
<NoOutputRedirection>true</NoOutputRedirection>
</PropertyGroup>
<ItemDefinitionGroup>
<ClCompile>
<AdditionalIncludeDirectories>$(OpenConsoleDir)\dep\jsoncpp\json;%(AdditionalIncludeDirectories);</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<AdditionalDependencies>WindowsApp.lib;shell32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>

View File

@ -0,0 +1,18 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#include "pch.h"
#include "Utils.h"
// Method Description:
// - Contstructs a wstring from a given Json::Value object. Reads the object as
// a std::string using asString, then builds an hstring from that std::string,
// then converts that hstring into a std::wstring.
// Arguments:
// - json: the Json::Value to parse as a string
// Return Value:
// - the wstring equivalent of the value in json
std::wstring GetWstringFromJson(const Json::Value& json)
{
return winrt::to_hstring(json.asString()).c_str();
}

View File

@ -0,0 +1,30 @@
/*++
Copyright (c) Microsoft Corporation
Licensed under the MIT license.
Module Name:
- Utils.h
Abstract:
- Helpers for the TerminalApp project
Author(s):
- Mike Griese - May 2019
--*/
#pragma once
std::wstring GetWstringFromJson(const Json::Value& json);
// Method Description:
// - Create a std::string from a string_view. We do this because we can't look
// up a key in a Json::Value with a string_view directly, so instead we'll use
// this helper. Should a string_view lookup ever be added to jsoncpp, we can
// remove this entirely.
// Arguments:
// - key: the string_view to build a string from
// Return Value:
// - a std::string to use for looking up a value from a Json::Value
inline std::string JsonKey(const std::string_view key)
{
return static_cast<std::string>(key);
}

View File

@ -49,3 +49,6 @@
TRACELOGGING_DECLARE_PROVIDER(g_hTerminalWin32Provider);
#include <telemetry\ProjectTelemetry.h>
#include <TraceLoggingActivity.h>
// JsonCpp
#include <json.h>

View File

@ -19,8 +19,8 @@ namespace Microsoft::Console::Utils
GUID GuidFromString(const std::wstring wstr);
GUID CreateGuid();
std::wstring ColorToHexString(const COLORREF color);
COLORREF ColorFromHexString(const std::wstring wstr);
std::string ColorToHexString(const COLORREF color);
COLORREF ColorFromHexString(const std::string wstr);
void InitializeCampbellColorTable(gsl::span<COLORREF>& table);
void Initialize256ColorTable(gsl::span<COLORREF>& table);

View File

@ -60,31 +60,33 @@ GUID Utils::CreateGuid()
// - color: the COLORREF to create the string for
// Return Value:
// - a string representation of the color
std::wstring Utils::ColorToHexString(const COLORREF color)
std::string Utils::ColorToHexString(const COLORREF color)
{
std::wstringstream ss;
ss << L"#" << std::uppercase << std::setfill(L'0') << std::hex;
ss << std::setw(2) << GetRValue(color);
ss << std::setw(2) << GetGValue(color);
ss << std::setw(2) << GetBValue(color);
std::stringstream ss;
ss << "#" << std::uppercase << std::setfill('0') << std::hex;
// Force the compiler to promote from byte to int. Without it, the
// stringstream will try to write the components as chars
ss << std::setw(2) << static_cast<int>(GetRValue(color));
ss << std::setw(2) << static_cast<int>(GetGValue(color));
ss << std::setw(2) << static_cast<int>(GetBValue(color));
return ss.str();
}
// Function Description:
// - Parses a color from a string. The string should be in the format "#RRGGBB"
// Arguments:
// - wstr: a string representation of the COLORREF to parse
// - str: a string representation of the COLORREF to parse
// Return Value:
// - A COLORREF if the string could successfully be parsed. If the string is not
// the correct format, throws E_INVALIDARG
COLORREF Utils::ColorFromHexString(const std::wstring wstr)
COLORREF Utils::ColorFromHexString(const std::string str)
{
THROW_HR_IF(E_INVALIDARG, wstr.size() < 7 || wstr.size() >= 8);
THROW_HR_IF(E_INVALIDARG, wstr[0] != L'#');
THROW_HR_IF(E_INVALIDARG, str.size() < 7 || str.size() >= 8);
THROW_HR_IF(E_INVALIDARG, str[0] != '#');
std::wstring rStr{ &wstr[1], 2 };
std::wstring gStr{ &wstr[3], 2 };
std::wstring bStr{ &wstr[5], 2 };
std::string rStr{ &str[1], 2 };
std::string gStr{ &str[3], 2 };
std::string bStr{ &str[5], 2 };
BYTE r = static_cast<BYTE>(std::stoul(rStr, nullptr, 16));
BYTE g = static_cast<BYTE>(std::stoul(gStr, nullptr, 16));