From 8af1b26dc2511c3805ef213922dbcd7247d88e0f Mon Sep 17 00:00:00 2001 From: Rushil Kasetty Date: Thu, 18 Jun 2020 00:38:02 -0400 Subject: [PATCH 1/8] Add .g files to includes and began implementing ActionArgs --- src/cascadia/TerminalApp/ActionArgs.cpp | 1 + src/cascadia/TerminalApp/ActionArgs.h | 30 +++++++++++++++++++ .../AppKeyBindingsSerialization.cpp | 4 +++ .../TerminalApp/ShortcutActionDispatch.cpp | 5 ++++ .../TerminalApp/ShortcutActionDispatch.h | 1 + 5 files changed, 41 insertions(+) diff --git a/src/cascadia/TerminalApp/ActionArgs.cpp b/src/cascadia/TerminalApp/ActionArgs.cpp index b3af876bace..823175214a9 100644 --- a/src/cascadia/TerminalApp/ActionArgs.cpp +++ b/src/cascadia/TerminalApp/ActionArgs.cpp @@ -14,3 +14,4 @@ #include "MoveFocusArgs.g.cpp" #include "AdjustFontSizeArgs.g.cpp" #include "SplitPaneArgs.g.cpp" +#include "RenameTabArgs.g.cpp" diff --git a/src/cascadia/TerminalApp/ActionArgs.h b/src/cascadia/TerminalApp/ActionArgs.h index cf21b68cb5a..3f6bd256249 100644 --- a/src/cascadia/TerminalApp/ActionArgs.h +++ b/src/cascadia/TerminalApp/ActionArgs.h @@ -14,6 +14,7 @@ #include "MoveFocusArgs.g.h" #include "AdjustFontSizeArgs.g.h" #include "SplitPaneArgs.g.h" +#include "RenameTabArgs.g.h" #include "../../cascadia/inc/cppwinrt_utils.h" #include "Utils.h" @@ -381,6 +382,35 @@ namespace winrt::TerminalApp::implementation return { *args, {} }; } }; + struct RenameTabArgs : public RenameTabArgsT + { + RenameTabArgs() = default; + GETSET_PROPERTY(winrt::hstring, Title, L""); + + static constexpr std::string_view TitleKey{ "title" }; + + public: + bool Equals(const IActionArgs& other) + { + auto otherAsUs = other.try_as(); + if (otherAsUs) + { + return otherAsUs->_Title == _Title; + } + return false; + }; + static FromJsonResult FromJson(const Json::Value& json) + { + // LOAD BEARING: Not using make_self here _will_ break you in the future! + auto args = winrt::make_self(); + if (auto title{ json[JsonKey(TitleKey)] }) + { + args->_Title = winrt::to_hstring(title.asString()); + } + //args->_Title = RenameTabArgs::FromJson(json); + return { *args, {} }; + } + }; } namespace winrt::TerminalApp::factory_implementation diff --git a/src/cascadia/TerminalApp/AppKeyBindingsSerialization.cpp b/src/cascadia/TerminalApp/AppKeyBindingsSerialization.cpp index f223236f56f..12b1fdc92b1 100644 --- a/src/cascadia/TerminalApp/AppKeyBindingsSerialization.cpp +++ b/src/cascadia/TerminalApp/AppKeyBindingsSerialization.cpp @@ -49,6 +49,7 @@ static constexpr std::string_view ResizePaneKey{ "resizePane" }; static constexpr std::string_view MoveFocusKey{ "moveFocus" }; static constexpr std::string_view FindKey{ "find" }; static constexpr std::string_view ToggleFullscreenKey{ "toggleFullscreen" }; +static constexpr std::string_view RenameTabKey{ "renameTab" }; // 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. @@ -84,6 +85,7 @@ static const std::map> commandName { SplitPaneKey, ShortcutAction::SplitPane }, { UnboundKey, ShortcutAction::Invalid }, { FindKey, ShortcutAction::Find }, + { RenameTabKey, ShortcutAction::RenameTab }, }; using ParseResult = std::tuple>; @@ -109,6 +111,8 @@ static const std::map> argParse { ShortcutAction::SplitPane, winrt::TerminalApp::implementation::SplitPaneArgs::FromJson }, + { ShortcutAction::RenameTab, winrt::TerminalApp::implementation::RenameTabArgs::FromJson }, + { ShortcutAction::Invalid, nullptr }, }; diff --git a/src/cascadia/TerminalApp/ShortcutActionDispatch.cpp b/src/cascadia/TerminalApp/ShortcutActionDispatch.cpp index 673876af920..b9a6bae6181 100644 --- a/src/cascadia/TerminalApp/ShortcutActionDispatch.cpp +++ b/src/cascadia/TerminalApp/ShortcutActionDispatch.cpp @@ -159,6 +159,11 @@ namespace winrt::TerminalApp::implementation _ToggleFullscreenHandlers(*this, *eventArgs); break; } + case ShortcutAction::RenameTab: + { + _RenameTabHandlers(*this, *eventArgs); + break; + } default: return false; } diff --git a/src/cascadia/TerminalApp/ShortcutActionDispatch.h b/src/cascadia/TerminalApp/ShortcutActionDispatch.h index f7e7ce05d06..f1c485d65e3 100644 --- a/src/cascadia/TerminalApp/ShortcutActionDispatch.h +++ b/src/cascadia/TerminalApp/ShortcutActionDispatch.h @@ -47,6 +47,7 @@ namespace winrt::TerminalApp::implementation TYPED_EVENT(Find, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs); TYPED_EVENT(MoveFocus, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs); TYPED_EVENT(ToggleFullscreen, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs); + TYPED_EVENT(RenameTab, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs); // clang-format on private: From 160628ad0740cf7d695f0306d30a8939dd792d2d Mon Sep 17 00:00:00 2001 From: Rushil Kasetty Date: Fri, 19 Jun 2020 02:03:31 -0400 Subject: [PATCH 2/8] Add more things to for ActionArgs Some things copied from zadjii's PR about TabColor --- src/cascadia/TerminalApp/ActionArgs.idl | 4 +++ .../TerminalApp/AppActionHandlers.cpp | 30 +++++++++++++++++++ .../TerminalApp/ShortcutActionDispatch.idl | 5 +++- src/cascadia/TerminalApp/TerminalPage.cpp | 14 +++++++++ src/cascadia/TerminalApp/TerminalPage.h | 3 ++ 5 files changed, 55 insertions(+), 1 deletion(-) diff --git a/src/cascadia/TerminalApp/ActionArgs.idl b/src/cascadia/TerminalApp/ActionArgs.idl index 96fa3abf587..0c21fc9650b 100644 --- a/src/cascadia/TerminalApp/ActionArgs.idl +++ b/src/cascadia/TerminalApp/ActionArgs.idl @@ -90,4 +90,8 @@ namespace TerminalApp NewTerminalArgs TerminalArgs { get; }; SplitType SplitMode { get; }; }; + [default_interface] runtimeclass RenameTabArgs : IActionArgs + { + String Title { get; }; + }; } diff --git a/src/cascadia/TerminalApp/AppActionHandlers.cpp b/src/cascadia/TerminalApp/AppActionHandlers.cpp index 0bf63758157..3162f0db42b 100644 --- a/src/cascadia/TerminalApp/AppActionHandlers.cpp +++ b/src/cascadia/TerminalApp/AppActionHandlers.cpp @@ -235,4 +235,34 @@ namespace winrt::TerminalApp::implementation ToggleFullscreen(); args.Handled(true); } + + void TerminalPage::_HandleRenameTab(const IInspectable& /*sender*/, + const TerminalApp::ActionEventArgs& args) + { + std::optional title; + + if (const auto& realArgs = args.ActionArgs().try_as()) + { + if (realArgs.Title() != nullptr) + { + title = realArgs.Title().Value(); + } + } + + auto activeTab = _GetFocusedTab(); + if (activeTab) + { + if (title.has_value()) + { + activeTab->RenameTab(title.value()); + } + else + { + activeTab + } + } + args.Handled(true); + } + + } diff --git a/src/cascadia/TerminalApp/ShortcutActionDispatch.idl b/src/cascadia/TerminalApp/ShortcutActionDispatch.idl index 0a51d6b0a3a..ea048a08d5d 100644 --- a/src/cascadia/TerminalApp/ShortcutActionDispatch.idl +++ b/src/cascadia/TerminalApp/ShortcutActionDispatch.idl @@ -35,7 +35,8 @@ namespace TerminalApp MoveFocus, Find, ToggleFullscreen, - OpenSettings + OpenSettings, + RenameTab }; [default_interface] runtimeclass ActionAndArgs { @@ -73,5 +74,7 @@ namespace TerminalApp event Windows.Foundation.TypedEventHandler Find; event Windows.Foundation.TypedEventHandler MoveFocus; event Windows.Foundation.TypedEventHandler ToggleFullscreen; + event Windows.Foundation.TypedEventHandler RenameTab; + } } diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp index f64aeb399e5..999c86f3dc4 100644 --- a/src/cascadia/TerminalApp/TerminalPage.cpp +++ b/src/cascadia/TerminalApp/TerminalPage.cpp @@ -754,6 +754,8 @@ namespace winrt::TerminalApp::implementation _actionDispatch->Find({ this, &TerminalPage::_HandleFind }); _actionDispatch->ResetFontSize({ this, &TerminalPage::_HandleResetFontSize }); _actionDispatch->ToggleFullscreen({ this, &TerminalPage::_HandleToggleFullscreen }); + _actionDispatch->RenameTab({ this, &TerminalPage::_HandleRenameTab }); + } // Method Description: @@ -1095,6 +1097,18 @@ namespace winrt::TerminalApp::implementation return std::nullopt; } + + // Method Description: + // - returns a com_ptr to the currently focused tab. This might return null, + // so make sure to check the result! + winrt::com_ptr TerminalPage::_GetFocusedTab() + { + if (auto index{ _GetFocusedTabIndex() }) + { + return _GetStrongTabImpl(*index); + } + return nullptr; + } // Method Description: // - An async method for changing the focused tab on the UI thread. This // method will _only_ set the selected item of the TabView, which will diff --git a/src/cascadia/TerminalApp/TerminalPage.h b/src/cascadia/TerminalApp/TerminalPage.h index 86af8a51069..209dbc0bbb4 100644 --- a/src/cascadia/TerminalApp/TerminalPage.h +++ b/src/cascadia/TerminalApp/TerminalPage.h @@ -129,6 +129,7 @@ namespace winrt::TerminalApp::implementation winrt::Microsoft::Terminal::TerminalControl::TermControl _GetActiveControl(); std::optional _GetFocusedTabIndex() const noexcept; + winrt::com_ptr _GetFocusedTab(); winrt::fire_and_forget _SetFocusedTabIndex(const uint32_t tabIndex); void _CloseFocusedTab(); void _CloseFocusedPane(); @@ -197,6 +198,8 @@ namespace winrt::TerminalApp::implementation void _HandleFind(const IInspectable& sender, const TerminalApp::ActionEventArgs& args); void _HandleResetFontSize(const IInspectable& sender, const TerminalApp::ActionEventArgs& args); void _HandleToggleFullscreen(const IInspectable& sender, const TerminalApp::ActionEventArgs& args); + void _HandleRenameTab(const IInspectable& sender, const TerminalApp::ActionEventArgs& args); + #pragma endregion friend class TerminalAppLocalTests::TabTests; From 0a9a57cc916409ae94a1c0c9f93defcd9342e363 Mon Sep 17 00:00:00 2001 From: Rushil Kasetty Date: Fri, 19 Jun 2020 03:15:20 -0400 Subject: [PATCH 3/8] Complete as much left as possible Currently not working, error could be anywhere --- src/cascadia/TerminalApp/AppActionHandlers.cpp | 14 +++++++------- src/cascadia/TerminalApp/Tab.cpp | 10 ++++++++++ src/cascadia/TerminalApp/Tab.h | 3 +++ 3 files changed, 20 insertions(+), 7 deletions(-) diff --git a/src/cascadia/TerminalApp/AppActionHandlers.cpp b/src/cascadia/TerminalApp/AppActionHandlers.cpp index 3162f0db42b..91c8f939324 100644 --- a/src/cascadia/TerminalApp/AppActionHandlers.cpp +++ b/src/cascadia/TerminalApp/AppActionHandlers.cpp @@ -239,14 +239,14 @@ namespace winrt::TerminalApp::implementation void TerminalPage::_HandleRenameTab(const IInspectable& /*sender*/, const TerminalApp::ActionEventArgs& args) { - std::optional title; + std::optional title; if (const auto& realArgs = args.ActionArgs().try_as()) { - if (realArgs.Title() != nullptr) - { - title = realArgs.Title().Value(); - } + //if (realArgs.Title() != nullptr) + //{ + title = realArgs.Title(); + //} } auto activeTab = _GetFocusedTab(); @@ -254,11 +254,11 @@ namespace winrt::TerminalApp::implementation { if (title.has_value()) { - activeTab->RenameTab(title.value()); + activeTab->SetTabText(title.value()); } else { - activeTab + activeTab->ResetTabText(); } } args.Handled(true); diff --git a/src/cascadia/TerminalApp/Tab.cpp b/src/cascadia/TerminalApp/Tab.cpp index 8e489e9ee4c..c6d73eaf2bc 100644 --- a/src/cascadia/TerminalApp/Tab.cpp +++ b/src/cascadia/TerminalApp/Tab.cpp @@ -377,6 +377,16 @@ namespace winrt::TerminalApp::implementation _activePane->Close(); } + void Tab::SetTabText(winrt::hstring title) + { + _runtimeTabText = title; + } + + void Tab::ResetTabText() + { + _runtimeTabText = L""; + } + // Method Description: // - Register any event handlers that we may need with the given TermControl. // This should be called on each and every TermControl that we add to the tree diff --git a/src/cascadia/TerminalApp/Tab.h b/src/cascadia/TerminalApp/Tab.h index 830fa65803a..5095311fc83 100644 --- a/src/cascadia/TerminalApp/Tab.h +++ b/src/cascadia/TerminalApp/Tab.h @@ -51,6 +51,9 @@ namespace winrt::TerminalApp::implementation void Shutdown(); void ClosePane(); + void SetTabText(winrt::hstring title); + void ResetTabText(); + std::optional GetTabColor(); WINRT_CALLBACK(Closed, winrt::Windows::Foundation::EventHandler); From d27098bc0328afe60242b8d231d1404895840830 Mon Sep 17 00:00:00 2001 From: Rushil Kasetty Date: Fri, 19 Jun 2020 03:24:22 -0400 Subject: [PATCH 4/8] Add _UpdateTitle call _UpdateTitle call refreshes UI --- src/cascadia/TerminalApp/Tab.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/cascadia/TerminalApp/Tab.cpp b/src/cascadia/TerminalApp/Tab.cpp index c6d73eaf2bc..373ea4abc40 100644 --- a/src/cascadia/TerminalApp/Tab.cpp +++ b/src/cascadia/TerminalApp/Tab.cpp @@ -380,11 +380,13 @@ namespace winrt::TerminalApp::implementation void Tab::SetTabText(winrt::hstring title) { _runtimeTabText = title; + _UpdateTitle(); } void Tab::ResetTabText() { _runtimeTabText = L""; + _UpdateTitle(); } // Method Description: From 6c360c8f9392262c75306b381caca86888fb8203 Mon Sep 17 00:00:00 2001 From: Rushil Kasetty Date: Tue, 23 Jun 2020 20:01:23 -0400 Subject: [PATCH 5/8] Remove dead code --- src/cascadia/TerminalApp/ActionArgs.h | 1 - src/cascadia/TerminalApp/AppActionHandlers.cpp | 3 --- 2 files changed, 4 deletions(-) diff --git a/src/cascadia/TerminalApp/ActionArgs.h b/src/cascadia/TerminalApp/ActionArgs.h index 3f6bd256249..23ed6c32f80 100644 --- a/src/cascadia/TerminalApp/ActionArgs.h +++ b/src/cascadia/TerminalApp/ActionArgs.h @@ -407,7 +407,6 @@ namespace winrt::TerminalApp::implementation { args->_Title = winrt::to_hstring(title.asString()); } - //args->_Title = RenameTabArgs::FromJson(json); return { *args, {} }; } }; diff --git a/src/cascadia/TerminalApp/AppActionHandlers.cpp b/src/cascadia/TerminalApp/AppActionHandlers.cpp index 91c8f939324..4a297bc15e3 100644 --- a/src/cascadia/TerminalApp/AppActionHandlers.cpp +++ b/src/cascadia/TerminalApp/AppActionHandlers.cpp @@ -243,10 +243,7 @@ namespace winrt::TerminalApp::implementation if (const auto& realArgs = args.ActionArgs().try_as()) { - //if (realArgs.Title() != nullptr) - //{ title = realArgs.Title(); - //} } auto activeTab = _GetFocusedTab(); From 6503c03298c6941c2f1cffe0fb25ccb3424cd77a Mon Sep 17 00:00:00 2001 From: Rushil Kasetty Date: Tue, 23 Jun 2020 21:33:57 -0400 Subject: [PATCH 6/8] Fix line ending issue and finish resolve merge conflict --- src/cascadia/TerminalApp/ActionAndArgs.cpp | 6 +- src/cascadia/TerminalApp/ActionArgs.cpp | 36 +- src/cascadia/TerminalApp/ActionArgs.h | 960 +++++++++--------- src/cascadia/TerminalApp/ActionArgs.idl | 220 ++-- .../AppKeyBindingsSerialization.cpp | 328 +++--- 5 files changed, 777 insertions(+), 773 deletions(-) diff --git a/src/cascadia/TerminalApp/ActionAndArgs.cpp b/src/cascadia/TerminalApp/ActionAndArgs.cpp index e59682f80ea..a7cf78bb8ad 100644 --- a/src/cascadia/TerminalApp/ActionAndArgs.cpp +++ b/src/cascadia/TerminalApp/ActionAndArgs.cpp @@ -33,6 +33,7 @@ static constexpr std::string_view ResizePaneKey{ "resizePane" }; static constexpr std::string_view MoveFocusKey{ "moveFocus" }; static constexpr std::string_view FindKey{ "find" }; static constexpr std::string_view ToggleFullscreenKey{ "toggleFullscreen" }; +static constexpr std::string_view RenameTabKey{ "renameTab" }; namespace winrt::TerminalApp::implementation { @@ -69,7 +70,8 @@ namespace winrt::TerminalApp::implementation { ToggleFullscreenKey, ShortcutAction::ToggleFullscreen }, { SplitPaneKey, ShortcutAction::SplitPane }, { UnboundKey, ShortcutAction::Invalid }, - { FindKey, ShortcutAction::Find } + { FindKey, ShortcutAction::Find }, + { RenameTabKey, ShortcutAction::RenameTab } }; using ParseResult = std::tuple>; @@ -97,6 +99,8 @@ namespace winrt::TerminalApp::implementation { ShortcutAction::OpenSettings, winrt::TerminalApp::implementation::OpenSettingsArgs::FromJson }, + { ShortcutAction::RenameTab, winrt::TerminalApp::implementation::RenameTabArgs::FromJson }, + { ShortcutAction::Invalid, nullptr }, }; diff --git a/src/cascadia/TerminalApp/ActionArgs.cpp b/src/cascadia/TerminalApp/ActionArgs.cpp index 821a02b662d..d5355099896 100644 --- a/src/cascadia/TerminalApp/ActionArgs.cpp +++ b/src/cascadia/TerminalApp/ActionArgs.cpp @@ -1,18 +1,18 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT license. - -#include "pch.h" - -#include "ActionArgs.h" - -#include "ActionEventArgs.g.cpp" -#include "NewTerminalArgs.g.cpp" -#include "CopyTextArgs.g.cpp" -#include "NewTabArgs.g.cpp" -#include "SwitchToTabArgs.g.cpp" -#include "ResizePaneArgs.g.cpp" -#include "MoveFocusArgs.g.cpp" -#include "AdjustFontSizeArgs.g.cpp" -#include "SplitPaneArgs.g.cpp" -#include "OpenSettingsArgs.g.cpp" -#include "RenameTabArgs.g.cpp" +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +#include "pch.h" + +#include "ActionArgs.h" + +#include "ActionEventArgs.g.cpp" +#include "NewTerminalArgs.g.cpp" +#include "CopyTextArgs.g.cpp" +#include "NewTabArgs.g.cpp" +#include "SwitchToTabArgs.g.cpp" +#include "ResizePaneArgs.g.cpp" +#include "MoveFocusArgs.g.cpp" +#include "AdjustFontSizeArgs.g.cpp" +#include "SplitPaneArgs.g.cpp" +#include "OpenSettingsArgs.g.cpp" +#include "RenameTabArgs.g.cpp" diff --git a/src/cascadia/TerminalApp/ActionArgs.h b/src/cascadia/TerminalApp/ActionArgs.h index 35400ac32b8..9f245f5144b 100644 --- a/src/cascadia/TerminalApp/ActionArgs.h +++ b/src/cascadia/TerminalApp/ActionArgs.h @@ -1,480 +1,480 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT license. - -#pragma once - -// HEY YOU: When adding ActionArgs types, make sure to add the corresponding -// *.g.cpp to ActionArgs.cpp! -#include "ActionEventArgs.g.h" -#include "NewTerminalArgs.g.h" -#include "CopyTextArgs.g.h" -#include "NewTabArgs.g.h" -#include "SwitchToTabArgs.g.h" -#include "ResizePaneArgs.g.h" -#include "MoveFocusArgs.g.h" -#include "AdjustFontSizeArgs.g.h" -#include "SplitPaneArgs.g.h" -#include "OpenSettingsArgs.g.h" -#include "RenameTabArgs.g.h" - -#include "../../cascadia/inc/cppwinrt_utils.h" -#include "Utils.h" -#include "TerminalWarnings.h" - -// Notes on defining ActionArgs and ActionEventArgs: -// * All properties specific to an action should be defined as an ActionArgs -// class that implements IActionArgs -// * ActionEventArgs holds a single IActionArgs. For events that don't need -// additional args, this can be nullptr. - -namespace winrt::TerminalApp::implementation -{ - using FromJsonResult = std::tuple>; - - struct ActionEventArgs : public ActionEventArgsT - { - ActionEventArgs() = default; - - explicit ActionEventArgs(const TerminalApp::IActionArgs& args) : - _ActionArgs{ args } {}; - GETSET_PROPERTY(IActionArgs, ActionArgs, nullptr); - GETSET_PROPERTY(bool, Handled, false); - }; - - struct NewTerminalArgs : public NewTerminalArgsT - { - NewTerminalArgs() = default; - GETSET_PROPERTY(winrt::hstring, Commandline, L""); - GETSET_PROPERTY(winrt::hstring, StartingDirectory, L""); - GETSET_PROPERTY(winrt::hstring, TabTitle, L""); - GETSET_PROPERTY(Windows::Foundation::IReference, ProfileIndex, nullptr); - GETSET_PROPERTY(winrt::hstring, Profile, L""); - - static constexpr std::string_view CommandlineKey{ "commandline" }; - static constexpr std::string_view StartingDirectoryKey{ "startingDirectory" }; - static constexpr std::string_view TabTitleKey{ "tabTitle" }; - static constexpr std::string_view ProfileIndexKey{ "index" }; - static constexpr std::string_view ProfileKey{ "profile" }; - - public: - bool Equals(const winrt::TerminalApp::NewTerminalArgs& other) - { - return other.Commandline() == _Commandline && - other.StartingDirectory() == _StartingDirectory && - other.TabTitle() == _TabTitle && - other.ProfileIndex() == _ProfileIndex && - other.Profile() == _Profile; - }; - static winrt::TerminalApp::NewTerminalArgs FromJson(const Json::Value& json) - { - // LOAD BEARING: Not using make_self here _will_ break you in the future! - auto args = winrt::make_self(); - if (auto commandline{ json[JsonKey(CommandlineKey)] }) - { - args->_Commandline = winrt::to_hstring(commandline.asString()); - } - if (auto startingDirectory{ json[JsonKey(StartingDirectoryKey)] }) - { - args->_StartingDirectory = winrt::to_hstring(startingDirectory.asString()); - } - if (auto tabTitle{ json[JsonKey(TabTitleKey)] }) - { - args->_TabTitle = winrt::to_hstring(tabTitle.asString()); - } - if (auto index{ json[JsonKey(ProfileIndexKey)] }) - { - args->_ProfileIndex = index.asInt(); - } - if (auto profile{ json[JsonKey(ProfileKey)] }) - { - args->_Profile = winrt::to_hstring(profile.asString()); - } - return *args; - } - }; - - struct CopyTextArgs : public CopyTextArgsT - { - CopyTextArgs() = default; - GETSET_PROPERTY(bool, SingleLine, false); - - static constexpr std::string_view SingleLineKey{ "singleLine" }; - - public: - bool Equals(const IActionArgs& other) - { - auto otherAsUs = other.try_as(); - if (otherAsUs) - { - return otherAsUs->_SingleLine == _SingleLine; - } - return false; - }; - static FromJsonResult FromJson(const Json::Value& json) - { - // LOAD BEARING: Not using make_self here _will_ break you in the future! - auto args = winrt::make_self(); - if (auto singleLine{ json[JsonKey(SingleLineKey)] }) - { - args->_SingleLine = singleLine.asBool(); - } - return { *args, {} }; - } - }; - - struct NewTabArgs : public NewTabArgsT - { - NewTabArgs() = default; - GETSET_PROPERTY(winrt::TerminalApp::NewTerminalArgs, TerminalArgs, nullptr); - - public: - bool Equals(const IActionArgs& other) - { - auto otherAsUs = other.try_as(); - if (otherAsUs) - { - return otherAsUs->_TerminalArgs.Equals(_TerminalArgs); - } - return false; - }; - static FromJsonResult FromJson(const Json::Value& json) - { - // LOAD BEARING: Not using make_self here _will_ break you in the future! - auto args = winrt::make_self(); - args->_TerminalArgs = NewTerminalArgs::FromJson(json); - return { *args, {} }; - } - }; - - struct SwitchToTabArgs : public SwitchToTabArgsT - { - SwitchToTabArgs() = default; - GETSET_PROPERTY(uint32_t, TabIndex, 0); - - static constexpr std::string_view TabIndexKey{ "index" }; - - public: - bool Equals(const IActionArgs& other) - { - auto otherAsUs = other.try_as(); - if (otherAsUs) - { - return otherAsUs->_TabIndex == _TabIndex; - } - return false; - }; - static FromJsonResult FromJson(const Json::Value& json) - { - // LOAD BEARING: Not using make_self here _will_ break you in the future! - auto args = winrt::make_self(); - if (auto tabIndex{ json[JsonKey(TabIndexKey)] }) - { - args->_TabIndex = tabIndex.asUInt(); - } - return { *args, {} }; - } - }; - - // Possible Direction values - // TODO:GH#2550/#3475 - move these to a centralized deserializing place - static constexpr std::string_view LeftString{ "left" }; - static constexpr std::string_view RightString{ "right" }; - static constexpr std::string_view UpString{ "up" }; - static constexpr std::string_view DownString{ "down" }; - - // Function Description: - // - Helper function for parsing a Direction from a string - // Arguments: - // - directionString: the string to attempt to parse - // Return Value: - // - The encoded Direction value, or Direction::None if it was an invalid string - static TerminalApp::Direction ParseDirection(const std::string& directionString) - { - if (directionString == LeftString) - { - return TerminalApp::Direction::Left; - } - else if (directionString == RightString) - { - return TerminalApp::Direction::Right; - } - else if (directionString == UpString) - { - return TerminalApp::Direction::Up; - } - else if (directionString == DownString) - { - return TerminalApp::Direction::Down; - } - // default behavior for invalid data - return TerminalApp::Direction::None; - }; - - struct ResizePaneArgs : public ResizePaneArgsT - { - ResizePaneArgs() = default; - GETSET_PROPERTY(TerminalApp::Direction, Direction, TerminalApp::Direction::None); - - static constexpr std::string_view DirectionKey{ "direction" }; - - public: - bool Equals(const IActionArgs& other) - { - auto otherAsUs = other.try_as(); - if (otherAsUs) - { - return otherAsUs->_Direction == _Direction; - } - return false; - }; - static FromJsonResult FromJson(const Json::Value& json) - { - // LOAD BEARING: Not using make_self here _will_ break you in the future! - auto args = winrt::make_self(); - if (auto directionString{ json[JsonKey(DirectionKey)] }) - { - args->_Direction = ParseDirection(directionString.asString()); - } - if (args->_Direction == TerminalApp::Direction::None) - { - return { nullptr, { ::TerminalApp::SettingsLoadWarnings::MissingRequiredParameter } }; - } - else - { - return { *args, {} }; - } - } - }; - - struct MoveFocusArgs : public MoveFocusArgsT - { - MoveFocusArgs() = default; - GETSET_PROPERTY(TerminalApp::Direction, Direction, TerminalApp::Direction::None); - - static constexpr std::string_view DirectionKey{ "direction" }; - - public: - bool Equals(const IActionArgs& other) - { - auto otherAsUs = other.try_as(); - if (otherAsUs) - { - return otherAsUs->_Direction == _Direction; - } - return false; - }; - static FromJsonResult FromJson(const Json::Value& json) - { - // LOAD BEARING: Not using make_self here _will_ break you in the future! - auto args = winrt::make_self(); - if (auto directionString{ json[JsonKey(DirectionKey)] }) - { - args->_Direction = ParseDirection(directionString.asString()); - } - if (args->_Direction == TerminalApp::Direction::None) - { - return { nullptr, { ::TerminalApp::SettingsLoadWarnings::MissingRequiredParameter } }; - } - else - { - return { *args, {} }; - } - } - }; - - struct AdjustFontSizeArgs : public AdjustFontSizeArgsT - { - AdjustFontSizeArgs() = default; - GETSET_PROPERTY(int32_t, Delta, 0); - - static constexpr std::string_view AdjustFontSizeDelta{ "delta" }; - - public: - bool Equals(const IActionArgs& other) - { - auto otherAsUs = other.try_as(); - if (otherAsUs) - { - return otherAsUs->_Delta == _Delta; - } - return false; - }; - static FromJsonResult FromJson(const Json::Value& json) - { - // LOAD BEARING: Not using make_self here _will_ break you in the future! - auto args = winrt::make_self(); - if (auto jsonDelta{ json[JsonKey(AdjustFontSizeDelta)] }) - { - args->_Delta = jsonDelta.asInt(); - } - return { *args, {} }; - } - }; - - // Possible SplitState values - // TODO:GH#2550/#3475 - move these to a centralized deserializing place - static constexpr std::string_view VerticalKey{ "vertical" }; - static constexpr std::string_view HorizontalKey{ "horizontal" }; - static constexpr std::string_view AutomaticKey{ "auto" }; - static TerminalApp::SplitState ParseSplitState(const std::string& stateString) - { - if (stateString == VerticalKey) - { - return TerminalApp::SplitState::Vertical; - } - else if (stateString == HorizontalKey) - { - return TerminalApp::SplitState::Horizontal; - } - else if (stateString == AutomaticKey) - { - return TerminalApp::SplitState::Automatic; - } - // default behavior for invalid data - return TerminalApp::SplitState::Automatic; - }; - - // Possible SplitType values - static constexpr std::string_view DuplicateKey{ "duplicate" }; - static TerminalApp::SplitType ParseSplitModeState(const std::string& stateString) - { - if (stateString == DuplicateKey) - { - return TerminalApp::SplitType::Duplicate; - } - return TerminalApp::SplitType::Manual; - } - - struct SplitPaneArgs : public SplitPaneArgsT - { - SplitPaneArgs() = default; - GETSET_PROPERTY(winrt::TerminalApp::SplitState, SplitStyle, winrt::TerminalApp::SplitState::Automatic); - GETSET_PROPERTY(winrt::TerminalApp::NewTerminalArgs, TerminalArgs, nullptr); - GETSET_PROPERTY(winrt::TerminalApp::SplitType, SplitMode, winrt::TerminalApp::SplitType::Manual); - - static constexpr std::string_view SplitKey{ "split" }; - static constexpr std::string_view SplitModeKey{ "splitMode" }; - - public: - bool Equals(const IActionArgs& other) - { - auto otherAsUs = other.try_as(); - if (otherAsUs) - { - return otherAsUs->_SplitStyle == _SplitStyle && - otherAsUs->_TerminalArgs == _TerminalArgs && - otherAsUs->_SplitMode == _SplitMode; - } - return false; - }; - static FromJsonResult FromJson(const Json::Value& json) - { - // LOAD BEARING: Not using make_self here _will_ break you in the future! - auto args = winrt::make_self(); - args->_TerminalArgs = NewTerminalArgs::FromJson(json); - if (auto jsonStyle{ json[JsonKey(SplitKey)] }) - { - args->_SplitStyle = ParseSplitState(jsonStyle.asString()); - } - if (auto jsonStyle{ json[JsonKey(SplitModeKey)] }) - { - args->_SplitMode = ParseSplitModeState(jsonStyle.asString()); - } - return { *args, {} }; - } - }; - - // Possible SettingsTarget values - // TODO:GH#2550/#3475 - move these to a centralized deserializing place - static constexpr std::string_view SettingsFileString{ "settingsFile" }; - static constexpr std::string_view DefaultsFileString{ "defaultsFile" }; - static constexpr std::string_view AllFilesString{ "allFiles" }; - - // Function Description: - // - Helper function for parsing a SettingsTarget from a string - // Arguments: - // - targetString: the string to attempt to parse - // Return Value: - // - The encoded SettingsTarget value, or SettingsTarget::SettingsFile if it was an invalid string - static TerminalApp::SettingsTarget ParseSettingsTarget(const std::string& targetString) - { - if (targetString == SettingsFileString) - { - return TerminalApp::SettingsTarget::SettingsFile; - } - else if (targetString == DefaultsFileString) - { - return TerminalApp::SettingsTarget::DefaultsFile; - } - else if (targetString == AllFilesString) - { - return TerminalApp::SettingsTarget::AllFiles; - } - // default behavior for invalid data - return TerminalApp::SettingsTarget::SettingsFile; - }; - - struct OpenSettingsArgs : public OpenSettingsArgsT - { - OpenSettingsArgs() = default; - GETSET_PROPERTY(TerminalApp::SettingsTarget, Target, TerminalApp::SettingsTarget::SettingsFile); - - static constexpr std::string_view TargetKey{ "target" }; - - public: - bool Equals(const IActionArgs& other) - { - auto otherAsUs = other.try_as(); - if (otherAsUs) - { - return otherAsUs->_Target == _Target; - } - return false; - }; - static FromJsonResult FromJson(const Json::Value& json) - { - // LOAD BEARING: Not using make_self here _will_ break you in the future! - auto args = winrt::make_self(); - if (auto targetString{ json[JsonKey(TargetKey)] }) - { - args->_Target = ParseSettingsTarget(targetString.asString()); - } - return { *args, {} }; - } - }; - - struct RenameTabArgs : public RenameTabArgsT - { - RenameTabArgs() = default; - GETSET_PROPERTY(winrt::hstring, Title, L""); - - static constexpr std::string_view TitleKey{ "title" }; - - public: - bool Equals(const IActionArgs& other) - { - auto otherAsUs = other.try_as(); - if (otherAsUs) - { - return otherAsUs->_Title == _Title; - } - return false; - }; - static FromJsonResult FromJson(const Json::Value& json) - { - // LOAD BEARING: Not using make_self here _will_ break you in the future! - auto args = winrt::make_self(); - if (auto title{ json[JsonKey(TitleKey)] }) - { - args->_Title = winrt::to_hstring(title.asString()); - } - return { *args, {} }; - } - }; -} - -namespace winrt::TerminalApp::factory_implementation -{ - BASIC_FACTORY(ActionEventArgs); - BASIC_FACTORY(NewTerminalArgs); -} +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +#pragma once + +// HEY YOU: When adding ActionArgs types, make sure to add the corresponding +// *.g.cpp to ActionArgs.cpp! +#include "ActionEventArgs.g.h" +#include "NewTerminalArgs.g.h" +#include "CopyTextArgs.g.h" +#include "NewTabArgs.g.h" +#include "SwitchToTabArgs.g.h" +#include "ResizePaneArgs.g.h" +#include "MoveFocusArgs.g.h" +#include "AdjustFontSizeArgs.g.h" +#include "SplitPaneArgs.g.h" +#include "OpenSettingsArgs.g.h" +#include "RenameTabArgs.g.h" + +#include "../../cascadia/inc/cppwinrt_utils.h" +#include "Utils.h" +#include "TerminalWarnings.h" + +// Notes on defining ActionArgs and ActionEventArgs: +// * All properties specific to an action should be defined as an ActionArgs +// class that implements IActionArgs +// * ActionEventArgs holds a single IActionArgs. For events that don't need +// additional args, this can be nullptr. + +namespace winrt::TerminalApp::implementation +{ + using FromJsonResult = std::tuple>; + + struct ActionEventArgs : public ActionEventArgsT + { + ActionEventArgs() = default; + + explicit ActionEventArgs(const TerminalApp::IActionArgs& args) : + _ActionArgs{ args } {}; + GETSET_PROPERTY(IActionArgs, ActionArgs, nullptr); + GETSET_PROPERTY(bool, Handled, false); + }; + + struct NewTerminalArgs : public NewTerminalArgsT + { + NewTerminalArgs() = default; + GETSET_PROPERTY(winrt::hstring, Commandline, L""); + GETSET_PROPERTY(winrt::hstring, StartingDirectory, L""); + GETSET_PROPERTY(winrt::hstring, TabTitle, L""); + GETSET_PROPERTY(Windows::Foundation::IReference, ProfileIndex, nullptr); + GETSET_PROPERTY(winrt::hstring, Profile, L""); + + static constexpr std::string_view CommandlineKey{ "commandline" }; + static constexpr std::string_view StartingDirectoryKey{ "startingDirectory" }; + static constexpr std::string_view TabTitleKey{ "tabTitle" }; + static constexpr std::string_view ProfileIndexKey{ "index" }; + static constexpr std::string_view ProfileKey{ "profile" }; + + public: + bool Equals(const winrt::TerminalApp::NewTerminalArgs& other) + { + return other.Commandline() == _Commandline && + other.StartingDirectory() == _StartingDirectory && + other.TabTitle() == _TabTitle && + other.ProfileIndex() == _ProfileIndex && + other.Profile() == _Profile; + }; + static winrt::TerminalApp::NewTerminalArgs FromJson(const Json::Value& json) + { + // LOAD BEARING: Not using make_self here _will_ break you in the future! + auto args = winrt::make_self(); + if (auto commandline{ json[JsonKey(CommandlineKey)] }) + { + args->_Commandline = winrt::to_hstring(commandline.asString()); + } + if (auto startingDirectory{ json[JsonKey(StartingDirectoryKey)] }) + { + args->_StartingDirectory = winrt::to_hstring(startingDirectory.asString()); + } + if (auto tabTitle{ json[JsonKey(TabTitleKey)] }) + { + args->_TabTitle = winrt::to_hstring(tabTitle.asString()); + } + if (auto index{ json[JsonKey(ProfileIndexKey)] }) + { + args->_ProfileIndex = index.asInt(); + } + if (auto profile{ json[JsonKey(ProfileKey)] }) + { + args->_Profile = winrt::to_hstring(profile.asString()); + } + return *args; + } + }; + + struct CopyTextArgs : public CopyTextArgsT + { + CopyTextArgs() = default; + GETSET_PROPERTY(bool, SingleLine, false); + + static constexpr std::string_view SingleLineKey{ "singleLine" }; + + public: + bool Equals(const IActionArgs& other) + { + auto otherAsUs = other.try_as(); + if (otherAsUs) + { + return otherAsUs->_SingleLine == _SingleLine; + } + return false; + }; + static FromJsonResult FromJson(const Json::Value& json) + { + // LOAD BEARING: Not using make_self here _will_ break you in the future! + auto args = winrt::make_self(); + if (auto singleLine{ json[JsonKey(SingleLineKey)] }) + { + args->_SingleLine = singleLine.asBool(); + } + return { *args, {} }; + } + }; + + struct NewTabArgs : public NewTabArgsT + { + NewTabArgs() = default; + GETSET_PROPERTY(winrt::TerminalApp::NewTerminalArgs, TerminalArgs, nullptr); + + public: + bool Equals(const IActionArgs& other) + { + auto otherAsUs = other.try_as(); + if (otherAsUs) + { + return otherAsUs->_TerminalArgs.Equals(_TerminalArgs); + } + return false; + }; + static FromJsonResult FromJson(const Json::Value& json) + { + // LOAD BEARING: Not using make_self here _will_ break you in the future! + auto args = winrt::make_self(); + args->_TerminalArgs = NewTerminalArgs::FromJson(json); + return { *args, {} }; + } + }; + + struct SwitchToTabArgs : public SwitchToTabArgsT + { + SwitchToTabArgs() = default; + GETSET_PROPERTY(uint32_t, TabIndex, 0); + + static constexpr std::string_view TabIndexKey{ "index" }; + + public: + bool Equals(const IActionArgs& other) + { + auto otherAsUs = other.try_as(); + if (otherAsUs) + { + return otherAsUs->_TabIndex == _TabIndex; + } + return false; + }; + static FromJsonResult FromJson(const Json::Value& json) + { + // LOAD BEARING: Not using make_self here _will_ break you in the future! + auto args = winrt::make_self(); + if (auto tabIndex{ json[JsonKey(TabIndexKey)] }) + { + args->_TabIndex = tabIndex.asUInt(); + } + return { *args, {} }; + } + }; + + // Possible Direction values + // TODO:GH#2550/#3475 - move these to a centralized deserializing place + static constexpr std::string_view LeftString{ "left" }; + static constexpr std::string_view RightString{ "right" }; + static constexpr std::string_view UpString{ "up" }; + static constexpr std::string_view DownString{ "down" }; + + // Function Description: + // - Helper function for parsing a Direction from a string + // Arguments: + // - directionString: the string to attempt to parse + // Return Value: + // - The encoded Direction value, or Direction::None if it was an invalid string + static TerminalApp::Direction ParseDirection(const std::string& directionString) + { + if (directionString == LeftString) + { + return TerminalApp::Direction::Left; + } + else if (directionString == RightString) + { + return TerminalApp::Direction::Right; + } + else if (directionString == UpString) + { + return TerminalApp::Direction::Up; + } + else if (directionString == DownString) + { + return TerminalApp::Direction::Down; + } + // default behavior for invalid data + return TerminalApp::Direction::None; + }; + + struct ResizePaneArgs : public ResizePaneArgsT + { + ResizePaneArgs() = default; + GETSET_PROPERTY(TerminalApp::Direction, Direction, TerminalApp::Direction::None); + + static constexpr std::string_view DirectionKey{ "direction" }; + + public: + bool Equals(const IActionArgs& other) + { + auto otherAsUs = other.try_as(); + if (otherAsUs) + { + return otherAsUs->_Direction == _Direction; + } + return false; + }; + static FromJsonResult FromJson(const Json::Value& json) + { + // LOAD BEARING: Not using make_self here _will_ break you in the future! + auto args = winrt::make_self(); + if (auto directionString{ json[JsonKey(DirectionKey)] }) + { + args->_Direction = ParseDirection(directionString.asString()); + } + if (args->_Direction == TerminalApp::Direction::None) + { + return { nullptr, { ::TerminalApp::SettingsLoadWarnings::MissingRequiredParameter } }; + } + else + { + return { *args, {} }; + } + } + }; + + struct MoveFocusArgs : public MoveFocusArgsT + { + MoveFocusArgs() = default; + GETSET_PROPERTY(TerminalApp::Direction, Direction, TerminalApp::Direction::None); + + static constexpr std::string_view DirectionKey{ "direction" }; + + public: + bool Equals(const IActionArgs& other) + { + auto otherAsUs = other.try_as(); + if (otherAsUs) + { + return otherAsUs->_Direction == _Direction; + } + return false; + }; + static FromJsonResult FromJson(const Json::Value& json) + { + // LOAD BEARING: Not using make_self here _will_ break you in the future! + auto args = winrt::make_self(); + if (auto directionString{ json[JsonKey(DirectionKey)] }) + { + args->_Direction = ParseDirection(directionString.asString()); + } + if (args->_Direction == TerminalApp::Direction::None) + { + return { nullptr, { ::TerminalApp::SettingsLoadWarnings::MissingRequiredParameter } }; + } + else + { + return { *args, {} }; + } + } + }; + + struct AdjustFontSizeArgs : public AdjustFontSizeArgsT + { + AdjustFontSizeArgs() = default; + GETSET_PROPERTY(int32_t, Delta, 0); + + static constexpr std::string_view AdjustFontSizeDelta{ "delta" }; + + public: + bool Equals(const IActionArgs& other) + { + auto otherAsUs = other.try_as(); + if (otherAsUs) + { + return otherAsUs->_Delta == _Delta; + } + return false; + }; + static FromJsonResult FromJson(const Json::Value& json) + { + // LOAD BEARING: Not using make_self here _will_ break you in the future! + auto args = winrt::make_self(); + if (auto jsonDelta{ json[JsonKey(AdjustFontSizeDelta)] }) + { + args->_Delta = jsonDelta.asInt(); + } + return { *args, {} }; + } + }; + + // Possible SplitState values + // TODO:GH#2550/#3475 - move these to a centralized deserializing place + static constexpr std::string_view VerticalKey{ "vertical" }; + static constexpr std::string_view HorizontalKey{ "horizontal" }; + static constexpr std::string_view AutomaticKey{ "auto" }; + static TerminalApp::SplitState ParseSplitState(const std::string& stateString) + { + if (stateString == VerticalKey) + { + return TerminalApp::SplitState::Vertical; + } + else if (stateString == HorizontalKey) + { + return TerminalApp::SplitState::Horizontal; + } + else if (stateString == AutomaticKey) + { + return TerminalApp::SplitState::Automatic; + } + // default behavior for invalid data + return TerminalApp::SplitState::Automatic; + }; + + // Possible SplitType values + static constexpr std::string_view DuplicateKey{ "duplicate" }; + static TerminalApp::SplitType ParseSplitModeState(const std::string& stateString) + { + if (stateString == DuplicateKey) + { + return TerminalApp::SplitType::Duplicate; + } + return TerminalApp::SplitType::Manual; + } + + struct SplitPaneArgs : public SplitPaneArgsT + { + SplitPaneArgs() = default; + GETSET_PROPERTY(winrt::TerminalApp::SplitState, SplitStyle, winrt::TerminalApp::SplitState::Automatic); + GETSET_PROPERTY(winrt::TerminalApp::NewTerminalArgs, TerminalArgs, nullptr); + GETSET_PROPERTY(winrt::TerminalApp::SplitType, SplitMode, winrt::TerminalApp::SplitType::Manual); + + static constexpr std::string_view SplitKey{ "split" }; + static constexpr std::string_view SplitModeKey{ "splitMode" }; + + public: + bool Equals(const IActionArgs& other) + { + auto otherAsUs = other.try_as(); + if (otherAsUs) + { + return otherAsUs->_SplitStyle == _SplitStyle && + otherAsUs->_TerminalArgs == _TerminalArgs && + otherAsUs->_SplitMode == _SplitMode; + } + return false; + }; + static FromJsonResult FromJson(const Json::Value& json) + { + // LOAD BEARING: Not using make_self here _will_ break you in the future! + auto args = winrt::make_self(); + args->_TerminalArgs = NewTerminalArgs::FromJson(json); + if (auto jsonStyle{ json[JsonKey(SplitKey)] }) + { + args->_SplitStyle = ParseSplitState(jsonStyle.asString()); + } + if (auto jsonStyle{ json[JsonKey(SplitModeKey)] }) + { + args->_SplitMode = ParseSplitModeState(jsonStyle.asString()); + } + return { *args, {} }; + } + }; + + // Possible SettingsTarget values + // TODO:GH#2550/#3475 - move these to a centralized deserializing place + static constexpr std::string_view SettingsFileString{ "settingsFile" }; + static constexpr std::string_view DefaultsFileString{ "defaultsFile" }; + static constexpr std::string_view AllFilesString{ "allFiles" }; + + // Function Description: + // - Helper function for parsing a SettingsTarget from a string + // Arguments: + // - targetString: the string to attempt to parse + // Return Value: + // - The encoded SettingsTarget value, or SettingsTarget::SettingsFile if it was an invalid string + static TerminalApp::SettingsTarget ParseSettingsTarget(const std::string& targetString) + { + if (targetString == SettingsFileString) + { + return TerminalApp::SettingsTarget::SettingsFile; + } + else if (targetString == DefaultsFileString) + { + return TerminalApp::SettingsTarget::DefaultsFile; + } + else if (targetString == AllFilesString) + { + return TerminalApp::SettingsTarget::AllFiles; + } + // default behavior for invalid data + return TerminalApp::SettingsTarget::SettingsFile; + }; + + struct OpenSettingsArgs : public OpenSettingsArgsT + { + OpenSettingsArgs() = default; + GETSET_PROPERTY(TerminalApp::SettingsTarget, Target, TerminalApp::SettingsTarget::SettingsFile); + + static constexpr std::string_view TargetKey{ "target" }; + + public: + bool Equals(const IActionArgs& other) + { + auto otherAsUs = other.try_as(); + if (otherAsUs) + { + return otherAsUs->_Target == _Target; + } + return false; + }; + static FromJsonResult FromJson(const Json::Value& json) + { + // LOAD BEARING: Not using make_self here _will_ break you in the future! + auto args = winrt::make_self(); + if (auto targetString{ json[JsonKey(TargetKey)] }) + { + args->_Target = ParseSettingsTarget(targetString.asString()); + } + return { *args, {} }; + } + }; + + struct RenameTabArgs : public RenameTabArgsT + { + RenameTabArgs() = default; + GETSET_PROPERTY(winrt::hstring, Title, L""); + + static constexpr std::string_view TitleKey{ "title" }; + + public: + bool Equals(const IActionArgs& other) + { + auto otherAsUs = other.try_as(); + if (otherAsUs) + { + return otherAsUs->_Title == _Title; + } + return false; + }; + static FromJsonResult FromJson(const Json::Value& json) + { + // LOAD BEARING: Not using make_self here _will_ break you in the future! + auto args = winrt::make_self(); + if (auto title{ json[JsonKey(TitleKey)] }) + { + args->_Title = winrt::to_hstring(title.asString()); + } + return { *args, {} }; + } + }; +} + +namespace winrt::TerminalApp::factory_implementation +{ + BASIC_FACTORY(ActionEventArgs); + BASIC_FACTORY(NewTerminalArgs); +} diff --git a/src/cascadia/TerminalApp/ActionArgs.idl b/src/cascadia/TerminalApp/ActionArgs.idl index 33e3c595592..96a3a16431a 100644 --- a/src/cascadia/TerminalApp/ActionArgs.idl +++ b/src/cascadia/TerminalApp/ActionArgs.idl @@ -1,110 +1,110 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT license. - -namespace TerminalApp -{ - interface IActionArgs - { - Boolean Equals(IActionArgs other); - }; - - interface IActionEventArgs - { - Boolean Handled; - IActionArgs ActionArgs { get; }; - }; - - enum Direction - { - None = 0, - Left, - Right, - Up, - Down - }; - - enum SplitState - { - Automatic = -1, - None = 0, - Vertical = 1, - Horizontal = 2 - }; - - enum SplitType - { - Manual = 0, - Duplicate = 1 - }; - - enum SettingsTarget - { - SettingsFile = 0, - DefaultsFile, - AllFiles - }; - - [default_interface] runtimeclass NewTerminalArgs { - NewTerminalArgs(); - String Commandline; - String StartingDirectory; - String TabTitle; - String Profile; // Either a GUID or a profile's name if the GUID isn't a match - // ProfileIndex can be null (for "use the default"), so this needs to be - // a IReference, so it's nullable - Windows.Foundation.IReference ProfileIndex { get; }; - Boolean Equals(NewTerminalArgs other); - }; - - [default_interface] runtimeclass ActionEventArgs : IActionEventArgs - { - ActionEventArgs(IActionArgs args); - }; - - [default_interface] runtimeclass CopyTextArgs : IActionArgs - { - Boolean SingleLine { get; }; - }; - - [default_interface] runtimeclass NewTabArgs : IActionArgs - { - NewTerminalArgs TerminalArgs { get; }; - }; - - [default_interface] runtimeclass SwitchToTabArgs : IActionArgs - { - UInt32 TabIndex { get; }; - }; - - [default_interface] runtimeclass ResizePaneArgs : IActionArgs - { - Direction Direction { get; }; - }; - - [default_interface] runtimeclass MoveFocusArgs : IActionArgs - { - Direction Direction { get; }; - }; - - [default_interface] runtimeclass AdjustFontSizeArgs : IActionArgs - { - Int32 Delta { get; }; - }; - - [default_interface] runtimeclass SplitPaneArgs : IActionArgs - { - SplitState SplitStyle { get; }; - NewTerminalArgs TerminalArgs { get; }; - SplitType SplitMode { get; }; - }; - - [default_interface] runtimeclass OpenSettingsArgs : IActionArgs - { - SettingsTarget Target { get; }; - }; - - [default_interface] runtimeclass RenameTabArgs : IActionArgs - { - String Title { get; }; - }; -} +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +namespace TerminalApp +{ + interface IActionArgs + { + Boolean Equals(IActionArgs other); + }; + + interface IActionEventArgs + { + Boolean Handled; + IActionArgs ActionArgs { get; }; + }; + + enum Direction + { + None = 0, + Left, + Right, + Up, + Down + }; + + enum SplitState + { + Automatic = -1, + None = 0, + Vertical = 1, + Horizontal = 2 + }; + + enum SplitType + { + Manual = 0, + Duplicate = 1 + }; + + enum SettingsTarget + { + SettingsFile = 0, + DefaultsFile, + AllFiles + }; + + [default_interface] runtimeclass NewTerminalArgs { + NewTerminalArgs(); + String Commandline; + String StartingDirectory; + String TabTitle; + String Profile; // Either a GUID or a profile's name if the GUID isn't a match + // ProfileIndex can be null (for "use the default"), so this needs to be + // a IReference, so it's nullable + Windows.Foundation.IReference ProfileIndex { get; }; + Boolean Equals(NewTerminalArgs other); + }; + + [default_interface] runtimeclass ActionEventArgs : IActionEventArgs + { + ActionEventArgs(IActionArgs args); + }; + + [default_interface] runtimeclass CopyTextArgs : IActionArgs + { + Boolean SingleLine { get; }; + }; + + [default_interface] runtimeclass NewTabArgs : IActionArgs + { + NewTerminalArgs TerminalArgs { get; }; + }; + + [default_interface] runtimeclass SwitchToTabArgs : IActionArgs + { + UInt32 TabIndex { get; }; + }; + + [default_interface] runtimeclass ResizePaneArgs : IActionArgs + { + Direction Direction { get; }; + }; + + [default_interface] runtimeclass MoveFocusArgs : IActionArgs + { + Direction Direction { get; }; + }; + + [default_interface] runtimeclass AdjustFontSizeArgs : IActionArgs + { + Int32 Delta { get; }; + }; + + [default_interface] runtimeclass SplitPaneArgs : IActionArgs + { + SplitState SplitStyle { get; }; + NewTerminalArgs TerminalArgs { get; }; + SplitType SplitMode { get; }; + }; + + [default_interface] runtimeclass OpenSettingsArgs : IActionArgs + { + SettingsTarget Target { get; }; + }; + + [default_interface] runtimeclass RenameTabArgs : IActionArgs + { + String Title { get; }; + }; +} diff --git a/src/cascadia/TerminalApp/AppKeyBindingsSerialization.cpp b/src/cascadia/TerminalApp/AppKeyBindingsSerialization.cpp index 2579278fb58..f4856477e3e 100644 --- a/src/cascadia/TerminalApp/AppKeyBindingsSerialization.cpp +++ b/src/cascadia/TerminalApp/AppKeyBindingsSerialization.cpp @@ -1,164 +1,164 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT license. -// - A couple helper functions for serializing/deserializing an AppKeyBindings -// to/from json. -// -// Author(s): -// - Mike Griese - May 2019 - -#include "pch.h" -#include "AppKeyBindings.h" -#include "ActionAndArgs.h" -#include "KeyChordSerialization.h" -#include "Utils.h" -#include "JsonUtils.h" -#include - -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 ActionKey{ "action" }; - -// Function Description: -// - Small helper to create a json value serialization of a single -// KeyBinding->Action mapping. -// { -// 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 winrt::TerminalApp::implementation::AppKeyBindings::ToJson() -{ - Json::Value bindingsArray; - - // Iterate over all the possible actions in the names list, and see if - // it has a binding. - for (auto& actionName : ActionAndArgs::ActionNamesMap) - { - const auto searchedForName = actionName.first; - const auto searchedForAction = actionName.second; - - if (const auto chord{ GetKeyBindingForAction(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 `ActionAndArgs::ActionNamesMap`, and `keys` is an array of -// keypresses. Currently, the array should contain a single string, which can -// be deserialized into a KeyChord. -// - Applies the deserialized keybindings to the provided `bindings` object. If -// a key chord in `json` is already bound to an action, that chord will be -// overwritten with the new action. If a chord is bound to `null` or -// `"unbound"`, then we'll clear the keybinding from the existing keybindings. -// Arguments: -// - json: an array of Json::Value's to deserialize into our _keyShortcuts mapping. -std::vector<::TerminalApp::SettingsLoadWarnings> winrt::TerminalApp::implementation::AppKeyBindings::LayerJson(const Json::Value& json) -{ - // It's possible that the user provided keybindings have some warnings in - // them - problems that we should alert the user to, but we can recover - // from. Most of these warnings cannot be detected later in the Validate - // settings phase, so we'll collect them now. - std::vector<::TerminalApp::SettingsLoadWarnings> warnings; - - for (const auto& value : json) - { - if (!value.isObject()) - { - continue; - } - - const auto commandVal = value[JsonKey(CommandKey)]; - const auto keys = value[JsonKey(KeysKey)]; - - if (keys) - { - const auto validString = keys.isString(); - const auto validArray = keys.isArray() && keys.size() == 1; - - // GH#4239 - If the user provided more than one key - // chord to a "keys" array, warn the user here. - // TODO: GH#1334 - remove this check. - if (keys.isArray() && keys.size() > 1) - { - warnings.push_back(::TerminalApp::SettingsLoadWarnings::TooManyKeysForChord); - } - - if (!validString && !validArray) - { - continue; - } - const auto keyChordString = keys.isString() ? winrt::to_hstring(keys.asString()) : winrt::to_hstring(keys[0].asString()); - - // If the action was null, "unbound", or something we didn't - // understand, this will return nullptr. - auto actionAndArgs = ActionAndArgs::FromJson(commandVal, warnings); - - // Try parsing the chord - try - { - const auto chord = KeyChordSerialization::FromString(keyChordString); - - // If we couldn't find the action they want to set the chord to, - // or the action was `null` or `"unbound"`, just clear out the - // keybinding. Otherwise, set the keybinding to the action we - // found. - if (actionAndArgs) - { - SetKeyBinding(*actionAndArgs, chord); - } - else - { - ClearKeyBinding(chord); - } - } - catch (...) - { - continue; - } - } - } - - return warnings; -} +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. +// - A couple helper functions for serializing/deserializing an AppKeyBindings +// to/from json. +// +// Author(s): +// - Mike Griese - May 2019 + +#include "pch.h" +#include "AppKeyBindings.h" +#include "ActionAndArgs.h" +#include "KeyChordSerialization.h" +#include "Utils.h" +#include "JsonUtils.h" +#include + +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 ActionKey{ "action" }; + +// Function Description: +// - Small helper to create a json value serialization of a single +// KeyBinding->Action mapping. +// { +// 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 winrt::TerminalApp::implementation::AppKeyBindings::ToJson() +{ + Json::Value bindingsArray; + + // Iterate over all the possible actions in the names list, and see if + // it has a binding. + for (auto& actionName : ActionAndArgs::ActionNamesMap) + { + const auto searchedForName = actionName.first; + const auto searchedForAction = actionName.second; + + if (const auto chord{ GetKeyBindingForAction(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 `ActionAndArgs::ActionNamesMap`, and `keys` is an array of +// keypresses. Currently, the array should contain a single string, which can +// be deserialized into a KeyChord. +// - Applies the deserialized keybindings to the provided `bindings` object. If +// a key chord in `json` is already bound to an action, that chord will be +// overwritten with the new action. If a chord is bound to `null` or +// `"unbound"`, then we'll clear the keybinding from the existing keybindings. +// Arguments: +// - json: an array of Json::Value's to deserialize into our _keyShortcuts mapping. +std::vector<::TerminalApp::SettingsLoadWarnings> winrt::TerminalApp::implementation::AppKeyBindings::LayerJson(const Json::Value& json) +{ + // It's possible that the user provided keybindings have some warnings in + // them - problems that we should alert the user to, but we can recover + // from. Most of these warnings cannot be detected later in the Validate + // settings phase, so we'll collect them now. + std::vector<::TerminalApp::SettingsLoadWarnings> warnings; + + for (const auto& value : json) + { + if (!value.isObject()) + { + continue; + } + + const auto commandVal = value[JsonKey(CommandKey)]; + const auto keys = value[JsonKey(KeysKey)]; + + if (keys) + { + const auto validString = keys.isString(); + const auto validArray = keys.isArray() && keys.size() == 1; + + // GH#4239 - If the user provided more than one key + // chord to a "keys" array, warn the user here. + // TODO: GH#1334 - remove this check. + if (keys.isArray() && keys.size() > 1) + { + warnings.push_back(::TerminalApp::SettingsLoadWarnings::TooManyKeysForChord); + } + + if (!validString && !validArray) + { + continue; + } + const auto keyChordString = keys.isString() ? winrt::to_hstring(keys.asString()) : winrt::to_hstring(keys[0].asString()); + + // If the action was null, "unbound", or something we didn't + // understand, this will return nullptr. + auto actionAndArgs = ActionAndArgs::FromJson(commandVal, warnings); + + // Try parsing the chord + try + { + const auto chord = KeyChordSerialization::FromString(keyChordString); + + // If we couldn't find the action they want to set the chord to, + // or the action was `null` or `"unbound"`, just clear out the + // keybinding. Otherwise, set the keybinding to the action we + // found. + if (actionAndArgs) + { + SetKeyBinding(*actionAndArgs, chord); + } + else + { + ClearKeyBinding(chord); + } + } + catch (...) + { + continue; + } + } + } + + return warnings; +} From 5f7c55d4a5fcb2ed618416bc8eceda40929ade4d Mon Sep 17 00:00:00 2001 From: Rushil Kasetty Date: Tue, 23 Jun 2020 22:38:31 -0400 Subject: [PATCH 7/8] clean up more formatting errors using clang-format --- src/cascadia/TerminalApp/ActionArgs.h | 8 ++++---- src/cascadia/TerminalApp/AppActionHandlers.cpp | 3 +-- src/cascadia/TerminalApp/TerminalPage.cpp | 2 -- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/cascadia/TerminalApp/ActionArgs.h b/src/cascadia/TerminalApp/ActionArgs.h index 9f245f5144b..57c3e4a66d9 100644 --- a/src/cascadia/TerminalApp/ActionArgs.h +++ b/src/cascadia/TerminalApp/ActionArgs.h @@ -420,7 +420,7 @@ namespace winrt::TerminalApp::implementation GETSET_PROPERTY(TerminalApp::SettingsTarget, Target, TerminalApp::SettingsTarget::SettingsFile); static constexpr std::string_view TargetKey{ "target" }; - + public: bool Equals(const IActionArgs& other) { @@ -442,14 +442,14 @@ namespace winrt::TerminalApp::implementation return { *args, {} }; } }; - + struct RenameTabArgs : public RenameTabArgsT { RenameTabArgs() = default; GETSET_PROPERTY(winrt::hstring, Title, L""); static constexpr std::string_view TitleKey{ "title" }; - + public: bool Equals(const IActionArgs& other) { @@ -466,7 +466,7 @@ namespace winrt::TerminalApp::implementation auto args = winrt::make_self(); if (auto title{ json[JsonKey(TitleKey)] }) { - args->_Title = winrt::to_hstring(title.asString()); + args->_Title = winrt::to_hstring(title.asString()); } return { *args, {} }; } diff --git a/src/cascadia/TerminalApp/AppActionHandlers.cpp b/src/cascadia/TerminalApp/AppActionHandlers.cpp index 9478a7b5732..c679d4290dd 100644 --- a/src/cascadia/TerminalApp/AppActionHandlers.cpp +++ b/src/cascadia/TerminalApp/AppActionHandlers.cpp @@ -239,7 +239,7 @@ namespace winrt::TerminalApp::implementation } void TerminalPage::_HandleRenameTab(const IInspectable& /*sender*/, - const TerminalApp::ActionEventArgs& args) + const TerminalApp::ActionEventArgs& args) { std::optional title; @@ -262,6 +262,5 @@ namespace winrt::TerminalApp::implementation } args.Handled(true); } - } diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp index e8ff00cbbce..83e4777b071 100644 --- a/src/cascadia/TerminalApp/TerminalPage.cpp +++ b/src/cascadia/TerminalApp/TerminalPage.cpp @@ -756,7 +756,6 @@ namespace winrt::TerminalApp::implementation _actionDispatch->ResetFontSize({ this, &TerminalPage::_HandleResetFontSize }); _actionDispatch->ToggleFullscreen({ this, &TerminalPage::_HandleToggleFullscreen }); _actionDispatch->RenameTab({ this, &TerminalPage::_HandleRenameTab }); - } // Method Description: @@ -1098,7 +1097,6 @@ namespace winrt::TerminalApp::implementation return std::nullopt; } - // Method Description: // - returns a com_ptr to the currently focused tab. This might return null, // so make sure to check the result! From d029755c4dd84f6264d838aa0a336f5d768c05bf Mon Sep 17 00:00:00 2001 From: Rushil Kasetty Date: Wed, 24 Jun 2020 13:03:01 -0400 Subject: [PATCH 8/8] Fix whitespace errors --- src/cascadia/TerminalApp/ActionArgs.idl | 2 +- src/cascadia/TerminalApp/TerminalPage.cpp | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/cascadia/TerminalApp/ActionArgs.idl b/src/cascadia/TerminalApp/ActionArgs.idl index 96a3a16431a..1e353f7c967 100644 --- a/src/cascadia/TerminalApp/ActionArgs.idl +++ b/src/cascadia/TerminalApp/ActionArgs.idl @@ -97,7 +97,7 @@ namespace TerminalApp NewTerminalArgs TerminalArgs { get; }; SplitType SplitMode { get; }; }; - + [default_interface] runtimeclass OpenSettingsArgs : IActionArgs { SettingsTarget Target { get; }; diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp index 83e4777b071..4d12cb4037a 100644 --- a/src/cascadia/TerminalApp/TerminalPage.cpp +++ b/src/cascadia/TerminalApp/TerminalPage.cpp @@ -1108,6 +1108,7 @@ namespace winrt::TerminalApp::implementation } return nullptr; } + // Method Description: // - An async method for changing the focused tab on the UI thread. This // method will _only_ set the selected item of the TabView, which will