diff --git a/src/cascadia/TerminalSettingsModel/ActionAndArgs.cpp b/src/cascadia/TerminalSettingsModel/ActionAndArgs.cpp index a9967193081..a3eb7053512 100644 --- a/src/cascadia/TerminalSettingsModel/ActionAndArgs.cpp +++ b/src/cascadia/TerminalSettingsModel/ActionAndArgs.cpp @@ -342,107 +342,6 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation winrt::hstring ActionAndArgs::GenerateName(const winrt::Windows::ApplicationModel::Resources::Core::ResourceContext& context) const { - // Sentinel used to indicate this command must ALWAYS be generated by GenerateName - static constexpr wil::zwstring_view MustGenerate{}; - // Use a magic static to initialize this map, because we won't be able - // to load the resources at _init_, only at runtime. - static const auto GeneratedActionNames = []() { - return std::unordered_map{ - { ShortcutAction::AdjustFontSize, USES_RESOURCE(L"AdjustFontSizeCommandKey") }, - { ShortcutAction::CloseOtherPanes, USES_RESOURCE(L"CloseOtherPanesCommandKey") }, - { ShortcutAction::CloseOtherTabs, MustGenerate }, - { ShortcutAction::ClosePane, USES_RESOURCE(L"ClosePaneCommandKey") }, - { ShortcutAction::CloseTab, MustGenerate }, - { ShortcutAction::CloseTabsAfter, MustGenerate }, - { ShortcutAction::CloseWindow, USES_RESOURCE(L"CloseWindowCommandKey") }, - { ShortcutAction::CopyText, USES_RESOURCE(L"CopyTextCommandKey") }, - { ShortcutAction::DuplicateTab, USES_RESOURCE(L"DuplicateTabCommandKey") }, - { ShortcutAction::ExecuteCommandline, USES_RESOURCE(L"ExecuteCommandlineCommandKey") }, - { ShortcutAction::Find, USES_RESOURCE(L"FindCommandKey") }, - { ShortcutAction::Invalid, MustGenerate }, - { ShortcutAction::MoveFocus, USES_RESOURCE(L"MoveFocusCommandKey") }, - { ShortcutAction::MovePane, USES_RESOURCE(L"MovePaneCommandKey") }, - { ShortcutAction::SwapPane, USES_RESOURCE(L"SwapPaneCommandKey") }, - { ShortcutAction::NewTab, USES_RESOURCE(L"NewTabCommandKey") }, - { ShortcutAction::NextTab, USES_RESOURCE(L"NextTabCommandKey") }, - { ShortcutAction::OpenNewTabDropdown, USES_RESOURCE(L"OpenNewTabDropdownCommandKey") }, - { ShortcutAction::OpenSettings, USES_RESOURCE(L"OpenSettingsUICommandKey") }, - { ShortcutAction::OpenTabColorPicker, USES_RESOURCE(L"OpenTabColorPickerCommandKey") }, - { ShortcutAction::PasteText, USES_RESOURCE(L"PasteTextCommandKey") }, - { ShortcutAction::PrevTab, USES_RESOURCE(L"PrevTabCommandKey") }, - { ShortcutAction::RenameTab, USES_RESOURCE(L"ResetTabNameCommandKey") }, - { ShortcutAction::OpenTabRenamer, USES_RESOURCE(L"OpenTabRenamerCommandKey") }, - { ShortcutAction::ResetFontSize, USES_RESOURCE(L"ResetFontSizeCommandKey") }, - { ShortcutAction::ResizePane, USES_RESOURCE(L"ResizePaneCommandKey") }, - { ShortcutAction::ScrollDown, USES_RESOURCE(L"ScrollDownCommandKey") }, - { ShortcutAction::ScrollDownPage, USES_RESOURCE(L"ScrollDownPageCommandKey") }, - { ShortcutAction::ScrollUp, USES_RESOURCE(L"ScrollUpCommandKey") }, - { ShortcutAction::ScrollUpPage, USES_RESOURCE(L"ScrollUpPageCommandKey") }, - { ShortcutAction::ScrollToTop, USES_RESOURCE(L"ScrollToTopCommandKey") }, - { ShortcutAction::ScrollToBottom, USES_RESOURCE(L"ScrollToBottomCommandKey") }, - { ShortcutAction::ScrollToMark, USES_RESOURCE(L"ScrollToPreviousMarkCommandKey") }, - { ShortcutAction::AddMark, USES_RESOURCE(L"AddMarkCommandKey") }, - { ShortcutAction::ClearMark, USES_RESOURCE(L"ClearMarkCommandKey") }, - { ShortcutAction::ClearAllMarks, USES_RESOURCE(L"ClearAllMarksCommandKey") }, - { ShortcutAction::SendInput, MustGenerate }, - { ShortcutAction::SetColorScheme, MustGenerate }, - { ShortcutAction::SetTabColor, USES_RESOURCE(L"ResetTabColorCommandKey") }, - { ShortcutAction::SplitPane, USES_RESOURCE(L"SplitPaneCommandKey") }, - { ShortcutAction::SwitchToTab, USES_RESOURCE(L"SwitchToTabCommandKey") }, - { ShortcutAction::TabSearch, USES_RESOURCE(L"TabSearchCommandKey") }, - { ShortcutAction::ToggleAlwaysOnTop, USES_RESOURCE(L"ToggleAlwaysOnTopCommandKey") }, - { ShortcutAction::ToggleCommandPalette, MustGenerate }, - { ShortcutAction::SaveSnippet, MustGenerate }, - { ShortcutAction::Suggestions, MustGenerate }, - { ShortcutAction::ToggleFocusMode, USES_RESOURCE(L"ToggleFocusModeCommandKey") }, - { ShortcutAction::SetFocusMode, MustGenerate }, - { ShortcutAction::ToggleFullscreen, USES_RESOURCE(L"ToggleFullscreenCommandKey") }, - { ShortcutAction::SetFullScreen, MustGenerate }, - { ShortcutAction::SetMaximized, MustGenerate }, - { ShortcutAction::TogglePaneZoom, USES_RESOURCE(L"TogglePaneZoomCommandKey") }, - { ShortcutAction::ToggleSplitOrientation, USES_RESOURCE(L"ToggleSplitOrientationCommandKey") }, - { ShortcutAction::ToggleShaderEffects, USES_RESOURCE(L"ToggleShaderEffectsCommandKey") }, - { ShortcutAction::MoveTab, MustGenerate }, - { ShortcutAction::BreakIntoDebugger, USES_RESOURCE(L"BreakIntoDebuggerCommandKey") }, - { ShortcutAction::FindMatch, MustGenerate }, - { ShortcutAction::TogglePaneReadOnly, USES_RESOURCE(L"TogglePaneReadOnlyCommandKey") }, - { ShortcutAction::EnablePaneReadOnly, USES_RESOURCE(L"EnablePaneReadOnlyCommandKey") }, - { ShortcutAction::DisablePaneReadOnly, USES_RESOURCE(L"DisablePaneReadOnlyCommandKey") }, - { ShortcutAction::NewWindow, USES_RESOURCE(L"NewWindowCommandKey") }, - { ShortcutAction::IdentifyWindow, USES_RESOURCE(L"IdentifyWindowCommandKey") }, - { ShortcutAction::IdentifyWindows, USES_RESOURCE(L"IdentifyWindowsCommandKey") }, - { ShortcutAction::RenameWindow, USES_RESOURCE(L"ResetWindowNameCommandKey") }, - { ShortcutAction::OpenWindowRenamer, USES_RESOURCE(L"OpenWindowRenamerCommandKey") }, - { ShortcutAction::DisplayWorkingDirectory, USES_RESOURCE(L"DisplayWorkingDirectoryCommandKey") }, - { ShortcutAction::GlobalSummon, MustGenerate }, - { ShortcutAction::SearchForText, MustGenerate }, - { ShortcutAction::QuakeMode, USES_RESOURCE(L"QuakeModeCommandKey") }, - { ShortcutAction::FocusPane, MustGenerate }, - { ShortcutAction::OpenSystemMenu, USES_RESOURCE(L"OpenSystemMenuCommandKey") }, - { ShortcutAction::ExportBuffer, MustGenerate }, - { ShortcutAction::ClearBuffer, MustGenerate }, - { ShortcutAction::MultipleActions, MustGenerate }, - { ShortcutAction::Quit, USES_RESOURCE(L"QuitCommandKey") }, - { ShortcutAction::AdjustOpacity, MustGenerate }, - { ShortcutAction::RestoreLastClosed, USES_RESOURCE(L"RestoreLastClosedCommandKey") }, - { ShortcutAction::SelectCommand, MustGenerate }, - { ShortcutAction::SelectOutput, MustGenerate }, - { ShortcutAction::SelectAll, USES_RESOURCE(L"SelectAllCommandKey") }, - { ShortcutAction::MarkMode, USES_RESOURCE(L"MarkModeCommandKey") }, - { ShortcutAction::ToggleBlockSelection, USES_RESOURCE(L"ToggleBlockSelectionCommandKey") }, - { ShortcutAction::SwitchSelectionEndpoint, USES_RESOURCE(L"SwitchSelectionEndpointCommandKey") }, - { ShortcutAction::ColorSelection, MustGenerate }, - { ShortcutAction::ShowContextMenu, USES_RESOURCE(L"ShowContextMenuCommandKey") }, - { ShortcutAction::ExpandSelectionToWord, USES_RESOURCE(L"ExpandSelectionToWordCommandKey") }, - { ShortcutAction::RestartConnection, USES_RESOURCE(L"RestartConnectionKey") }, - { ShortcutAction::ToggleBroadcastInput, USES_RESOURCE(L"ToggleBroadcastInputCommandKey") }, - { ShortcutAction::OpenScratchpad, USES_RESOURCE(L"OpenScratchpadKey") }, - { ShortcutAction::OpenAbout, USES_RESOURCE(L"OpenAboutCommandKey") }, - { ShortcutAction::QuickFix, USES_RESOURCE(L"QuickFixCommandKey") }, - { ShortcutAction::OpenCWD, USES_RESOURCE(L"OpenCWDCommandKey") }, - }; - }(); - if (_Args) { auto nameFromArgs = _Args.GenerateName(context); @@ -452,12 +351,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation } } - const auto found = GeneratedActionNames.find(_Action); - if (found != GeneratedActionNames.end() && !found->second.empty()) - { - return GetLibraryResourceLoader().ResourceMap().GetValue(found->second, context).ValueAsString(); - } - return winrt::hstring{}; + return ActionArgFactory::GetNameForAction(_Action, context); } winrt::hstring ActionAndArgs::GenerateName() const diff --git a/src/cascadia/TerminalSettingsModel/ActionArgs.h b/src/cascadia/TerminalSettingsModel/ActionArgs.h index d72db038df8..b6b75bd2df6 100644 --- a/src/cascadia/TerminalSettingsModel/ActionArgs.h +++ b/src/cascadia/TerminalSettingsModel/ActionArgs.h @@ -56,6 +56,7 @@ #include "JsonUtils.h" #include "HashUtils.h" #include "TerminalWarnings.h" +#include "../WinRTUtils/inc/LibraryResources.h" #include "TerminalSettingsSerializationHelpers.h" @@ -105,189 +106,208 @@ protected: \ // false, if we don't really care if the parameter is required or not. //////////////////////////////////////////////////////////////////////////////// -#define COPY_TEXT_ARGS(X) \ - X(bool, DismissSelection, "dismissSelection", false, true) \ - X(bool, SingleLine, "singleLine", false, false) \ - X(bool, WithControlSequences, "withControlSequences", false, false) \ - X(Windows::Foundation::IReference, CopyFormatting, "copyFormatting", false, nullptr) +#define COPY_TEXT_ARGS(X) \ + X(bool, DismissSelection, "dismissSelection", false, ArgTypeHint::None, true) \ + X(bool, SingleLine, "singleLine", false, ArgTypeHint::None, false) \ + X(bool, WithControlSequences, "withControlSequences", false, ArgTypeHint::None, false) \ + X(Windows::Foundation::IReference, CopyFormatting, "copyFormatting", false, ArgTypeHint::None, nullptr) //////////////////////////////////////////////////////////////////////////////// -#define MOVE_PANE_ARGS(X) \ - X(uint32_t, TabIndex, "index", false, 0) \ - X(winrt::hstring, Window, "window", false, L"") +#define MOVE_PANE_ARGS(X) \ + X(uint32_t, TabIndex, "index", false, ArgTypeHint::None, 0) \ + X(winrt::hstring, Window, "window", false, ArgTypeHint::None, L"") //////////////////////////////////////////////////////////////////////////////// #define SWITCH_TO_TAB_ARGS(X) \ - X(uint32_t, TabIndex, "index", false, 0) + X(uint32_t, TabIndex, "index", false, ArgTypeHint::None, 0) //////////////////////////////////////////////////////////////////////////////// #define RESIZE_PANE_ARGS(X) \ - X(Model::ResizeDirection, ResizeDirection, "direction", args->ResizeDirection() == ResizeDirection::None, Model::ResizeDirection::None) + X(Model::ResizeDirection, ResizeDirection, "direction", args->ResizeDirection() == ResizeDirection::None, ArgTypeHint::None, Model::ResizeDirection::None) //////////////////////////////////////////////////////////////////////////////// #define MOVE_FOCUS_ARGS(X) \ - X(Model::FocusDirection, FocusDirection, "direction", args->FocusDirection() == Model::FocusDirection::None, Model::FocusDirection::None) + X(Model::FocusDirection, FocusDirection, "direction", args->FocusDirection() == Model::FocusDirection::None, ArgTypeHint::None, Model::FocusDirection::None) //////////////////////////////////////////////////////////////////////////////// #define SWAP_PANE_ARGS(X) \ - X(Model::FocusDirection, Direction, "direction", args->Direction() == Model::FocusDirection::None, Model::FocusDirection::None) + X(Model::FocusDirection, Direction, "direction", args->Direction() == Model::FocusDirection::None, ArgTypeHint::None, Model::FocusDirection::None) //////////////////////////////////////////////////////////////////////////////// #define ADJUST_FONT_SIZE_ARGS(X) \ - X(float, Delta, "delta", false, 0) + X(float, Delta, "delta", false, ArgTypeHint::None, 0) //////////////////////////////////////////////////////////////////////////////// #define SEND_INPUT_ARGS(X) \ - X(winrt::hstring, Input, "input", args->Input().empty(), L"") + X(winrt::hstring, Input, "input", args->Input().empty(), ArgTypeHint::None, L"") //////////////////////////////////////////////////////////////////////////////// #define OPEN_SETTINGS_ARGS(X) \ - X(SettingsTarget, Target, "target", false, SettingsTarget::SettingsFile) + X(SettingsTarget, Target, "target", false, ArgTypeHint::None, SettingsTarget::SettingsFile) //////////////////////////////////////////////////////////////////////////////// #define SET_FOCUS_MODE_ARGS(X) \ - X(bool, IsFocusMode, "isFocusMode", false, false) + X(bool, IsFocusMode, "isFocusMode", false, ArgTypeHint::None, false) //////////////////////////////////////////////////////////////////////////////// #define SET_MAXIMIZED_ARGS(X) \ - X(bool, IsMaximized, "isMaximized", false, false) + X(bool, IsMaximized, "isMaximized", false, ArgTypeHint::None, false) //////////////////////////////////////////////////////////////////////////////// #define SET_FULL_SCREEN_ARGS(X) \ - X(bool, IsFullScreen, "isFullScreen", false, false) + X(bool, IsFullScreen, "isFullScreen", false, ArgTypeHint::None, false) //////////////////////////////////////////////////////////////////////////////// #define SET_MAXIMIZED_ARGS(X) \ - X(bool, IsMaximized, "isMaximized", false, false) + X(bool, IsMaximized, "isMaximized", false, ArgTypeHint::None, false) //////////////////////////////////////////////////////////////////////////////// #define SET_COLOR_SCHEME_ARGS(X) \ - X(winrt::hstring, SchemeName, "colorScheme", args->SchemeName().empty(), L"") + X(winrt::hstring, SchemeName, "colorScheme", args->SchemeName().empty(), ArgTypeHint::ColorScheme, L"") //////////////////////////////////////////////////////////////////////////////// #define SET_TAB_COLOR_ARGS(X) \ - X(Windows::Foundation::IReference, TabColor, "color", false, nullptr) + X(Windows::Foundation::IReference, TabColor, "color", false, ArgTypeHint::None, nullptr) //////////////////////////////////////////////////////////////////////////////// #define RENAME_TAB_ARGS(X) \ - X(winrt::hstring, Title, "title", false, L"") + X(winrt::hstring, Title, "title", false, ArgTypeHint::None, L"") //////////////////////////////////////////////////////////////////////////////// #define EXECUTE_COMMANDLINE_ARGS(X) \ - X(winrt::hstring, Commandline, "commandline", args->Commandline().empty(), L"") + X(winrt::hstring, Commandline, "commandline", args->Commandline().empty(), ArgTypeHint::None, L"") //////////////////////////////////////////////////////////////////////////////// #define CLOSE_OTHER_TABS_ARGS(X) \ - X(Windows::Foundation::IReference, Index, "index", false, nullptr) + X(Windows::Foundation::IReference, Index, "index", false, ArgTypeHint::None, nullptr) //////////////////////////////////////////////////////////////////////////////// #define CLOSE_TABS_AFTER_ARGS(X) \ - X(Windows::Foundation::IReference, Index, "index", false, nullptr) + X(Windows::Foundation::IReference, Index, "index", false, ArgTypeHint::None, nullptr) //////////////////////////////////////////////////////////////////////////////// #define CLOSE_TAB_ARGS(X) \ - X(Windows::Foundation::IReference, Index, "index", false, nullptr) + X(Windows::Foundation::IReference, Index, "index", false, ArgTypeHint::None, nullptr) //////////////////////////////////////////////////////////////////////////////// // Interestingly, the order MATTERS here. Window has to be BEFORE Direction, // because otherwise we won't have parsed the Window yet when we validate the // Direction. -#define MOVE_TAB_ARGS(X) \ - X(winrt::hstring, Window, "window", false, L"") \ - X(MoveTabDirection, Direction, "direction", (args->Direction() == MoveTabDirection::None) && (args->Window().empty()), MoveTabDirection::None) +#define MOVE_TAB_ARGS(X) \ + X(winrt::hstring, Window, "window", false, ArgTypeHint::None, L"") \ + X(MoveTabDirection, Direction, "direction", (args->Direction() == MoveTabDirection::None) && (args->Window().empty()), ArgTypeHint::None, MoveTabDirection::None) // Other ideas: // X(uint32_t, TabIndex, "index", false, 0) \ // target? source? //////////////////////////////////////////////////////////////////////////////// #define SCROLL_UP_ARGS(X) \ - X(Windows::Foundation::IReference, RowsToScroll, "rowsToScroll", false, nullptr) + X(Windows::Foundation::IReference, RowsToScroll, "rowsToScroll", false, ArgTypeHint::None, nullptr) //////////////////////////////////////////////////////////////////////////////// #define SCROLL_DOWN_ARGS(X) \ - X(Windows::Foundation::IReference, RowsToScroll, "rowsToScroll", false, nullptr) + X(Windows::Foundation::IReference, RowsToScroll, "rowsToScroll", false, ArgTypeHint::None, nullptr) //////////////////////////////////////////////////////////////////////////////// #define SCROLL_TO_MARK_ARGS(X) \ - X(Microsoft::Terminal::Control::ScrollToMarkDirection, Direction, "direction", false, Microsoft::Terminal::Control::ScrollToMarkDirection::Previous) + X(Microsoft::Terminal::Control::ScrollToMarkDirection, Direction, "direction", false, ArgTypeHint::None, Microsoft::Terminal::Control::ScrollToMarkDirection::Previous) //////////////////////////////////////////////////////////////////////////////// #define ADD_MARK_ARGS(X) \ - X(Windows::Foundation::IReference, Color, "color", false, nullptr) + X(Windows::Foundation::IReference, Color, "color", false, ArgTypeHint::None, nullptr) //////////////////////////////////////////////////////////////////////////////// #define TOGGLE_COMMAND_PALETTE_ARGS(X) \ - X(CommandPaletteLaunchMode, LaunchMode, "launchMode", false, CommandPaletteLaunchMode::Action) + X(CommandPaletteLaunchMode, LaunchMode, "launchMode", false, ArgTypeHint::None, CommandPaletteLaunchMode::Action) //////////////////////////////////////////////////////////////////////////////// -#define SAVE_TASK_ARGS(X) \ - X(winrt::hstring, Name, "name", false, L"") \ - X(winrt::hstring, Commandline, "commandline", args->Commandline().empty(), L"") \ - X(winrt::hstring, KeyChord, "keyChord", false, L"") +#define SAVE_TASK_ARGS(X) \ + X(winrt::hstring, Name, "name", false, ArgTypeHint::None, L"") \ + X(winrt::hstring, Commandline, "commandline", args->Commandline().empty(), ArgTypeHint::None, L"") \ + X(winrt::hstring, KeyChord, "keyChord", false, ArgTypeHint::None, L"") //////////////////////////////////////////////////////////////////////////////// -#define SUGGESTIONS_ARGS(X) \ - X(SuggestionsSource, Source, "source", false, SuggestionsSource::Tasks) \ - X(bool, UseCommandline, "useCommandline", false, false) +#define SUGGESTIONS_ARGS(X) \ + X(SuggestionsSource, Source, "source", false, ArgTypeHint::None, SuggestionsSource::Tasks) \ + X(bool, UseCommandline, "useCommandline", false, ArgTypeHint::None, false) //////////////////////////////////////////////////////////////////////////////// #define FIND_MATCH_ARGS(X) \ - X(FindMatchDirection, Direction, "direction", args->Direction() == FindMatchDirection::None, FindMatchDirection::None) + X(FindMatchDirection, Direction, "direction", args->Direction() == FindMatchDirection::None, ArgTypeHint::None, FindMatchDirection::None) //////////////////////////////////////////////////////////////////////////////// #define PREV_TAB_ARGS(X) \ - X(Windows::Foundation::IReference, SwitcherMode, "tabSwitcherMode", false, nullptr) + X(Windows::Foundation::IReference, SwitcherMode, "tabSwitcherMode", false, ArgTypeHint::None, nullptr) //////////////////////////////////////////////////////////////////////////////// #define NEXT_TAB_ARGS(X) \ - X(Windows::Foundation::IReference, SwitcherMode, "tabSwitcherMode", false, nullptr) + X(Windows::Foundation::IReference, SwitcherMode, "tabSwitcherMode", false, ArgTypeHint::None, nullptr) //////////////////////////////////////////////////////////////////////////////// #define RENAME_WINDOW_ARGS(X) \ - X(winrt::hstring, Name, "name", false, L"") + X(winrt::hstring, Name, "name", false, ArgTypeHint::None, L"") //////////////////////////////////////////////////////////////////////////////// #define SEARCH_FOR_TEXT_ARGS(X) \ - X(winrt::hstring, QueryUrl, "queryUrl", false, L"") + X(winrt::hstring, QueryUrl, "queryUrl", false, ArgTypeHint::None, L"") //////////////////////////////////////////////////////////////////////////////// -#define GLOBAL_SUMMON_ARGS(X) \ - X(winrt::hstring, Name, "name", false, L"") \ - X(Model::DesktopBehavior, Desktop, "desktop", false, Model::DesktopBehavior::ToCurrent) \ - X(Model::MonitorBehavior, Monitor, "monitor", false, Model::MonitorBehavior::ToMouse) \ - X(bool, ToggleVisibility, "toggleVisibility", false, true) \ - X(uint32_t, DropdownDuration, "dropdownDuration", false, 0) +#define GLOBAL_SUMMON_ARGS(X) \ + X(winrt::hstring, Name, "name", false, ArgTypeHint::None, L"") \ + X(Model::DesktopBehavior, Desktop, "desktop", false, ArgTypeHint::None, Model::DesktopBehavior::ToCurrent) \ + X(Model::MonitorBehavior, Monitor, "monitor", false, ArgTypeHint::None, Model::MonitorBehavior::ToMouse) \ + X(bool, ToggleVisibility, "toggleVisibility", false, ArgTypeHint::None, true) \ + X(uint32_t, DropdownDuration, "dropdownDuration", false, ArgTypeHint::None, 0) //////////////////////////////////////////////////////////////////////////////// #define FOCUS_PANE_ARGS(X) \ - X(uint32_t, Id, "id", false, 0u) + X(uint32_t, Id, "id", false, ArgTypeHint::None, 0u) //////////////////////////////////////////////////////////////////////////////// #define EXPORT_BUFFER_ARGS(X) \ - X(winrt::hstring, Path, "path", false, L"") + X(winrt::hstring, Path, "path", false, ArgTypeHint::FilePath, L"") //////////////////////////////////////////////////////////////////////////////// #define CLEAR_BUFFER_ARGS(X) \ - X(winrt::Microsoft::Terminal::Control::ClearBufferType, Clear, "clear", false, winrt::Microsoft::Terminal::Control::ClearBufferType::All) + X(winrt::Microsoft::Terminal::Control::ClearBufferType, Clear, "clear", false, ArgTypeHint::None, winrt::Microsoft::Terminal::Control::ClearBufferType::All) //////////////////////////////////////////////////////////////////////////////// -#define ADJUST_OPACITY_ARGS(X) \ - X(int32_t, Opacity, "opacity", false, 0) \ - X(bool, Relative, "relative", false, true) +#define ADJUST_OPACITY_ARGS(X) \ + X(int32_t, Opacity, "opacity", false, ArgTypeHint::None, 0) \ + X(bool, Relative, "relative", false, ArgTypeHint::None, true) //////////////////////////////////////////////////////////////////////////////// #define SELECT_COMMAND_ARGS(X) \ - X(SelectOutputDirection, Direction, "direction", false, SelectOutputDirection::Previous) + X(SelectOutputDirection, Direction, "direction", false, ArgTypeHint::None, SelectOutputDirection::Previous) //////////////////////////////////////////////////////////////////////////////// #define SELECT_OUTPUT_ARGS(X) \ - X(SelectOutputDirection, Direction, "direction", false, SelectOutputDirection::Previous) + X(SelectOutputDirection, Direction, "direction", false, ArgTypeHint::None, SelectOutputDirection::Previous) //////////////////////////////////////////////////////////////////////////////// -#define COLOR_SELECTION_ARGS(X) \ - X(winrt::Microsoft::Terminal::Control::SelectionColor, Foreground, "foreground", false, nullptr) \ - X(winrt::Microsoft::Terminal::Control::SelectionColor, Background, "background", false, nullptr) \ - X(winrt::Microsoft::Terminal::Core::MatchMode, MatchMode, "matchMode", false, winrt::Microsoft::Terminal::Core::MatchMode::None) +#define COLOR_SELECTION_ARGS(X) \ + X(winrt::Microsoft::Terminal::Control::SelectionColor, Foreground, "foreground", false, ArgTypeHint::None, nullptr) \ + X(winrt::Microsoft::Terminal::Control::SelectionColor, Background, "background", false, ArgTypeHint::None, nullptr) \ + X(winrt::Microsoft::Terminal::Core::MatchMode, MatchMode, "matchMode", false, ArgTypeHint::None, winrt::Microsoft::Terminal::Core::MatchMode::None) + +//////////////////////////////////////////////////////////////////////////////// +#define NEW_TERMINAL_ARGS(X) \ + X(winrt::hstring, Commandline, "commandline", false, ArgTypeHint::None, L"") \ + X(winrt::hstring, StartingDirectory, "startingDirectory", false, ArgTypeHint::FolderPath, L"") \ + X(winrt::hstring, TabTitle, "tabTitle", false, ArgTypeHint::None, L"") \ + X(Windows::Foundation::IReference, TabColor, "tabColor", false, ArgTypeHint::None, nullptr) \ + X(Windows::Foundation::IReference, ProfileIndex, "index", false, ArgTypeHint::None, nullptr) \ + X(winrt::hstring, Profile, "profile", false, ArgTypeHint::None, L"") \ + X(Windows::Foundation::IReference, SuppressApplicationTitle, "suppressApplicationTitle", false, ArgTypeHint::None, nullptr) \ + X(winrt::hstring, ColorScheme, "colorScheme", args->SchemeName().empty(), ArgTypeHint::ColorScheme, L"") \ + X(Windows::Foundation::IReference, Elevate, "elevate", false, ArgTypeHint::None, nullptr) \ + X(Windows::Foundation::IReference, ReloadEnvironmentVariables, "reloadEnvironmentVariables", false, ArgTypeHint::None, nullptr) + +//////////////////////////////////////////////////////////////////////////////// +#define SPLIT_PANE_ARGS(X) \ + X(Model::SplitDirection, SplitDirection, "split", false, ArgTypeHint::None, SplitDirection::Automatic) \ + X(SplitType, SplitMode, "splitMode", false, ArgTypeHint::None, SplitType::Manual) \ + X(float, SplitSize, "size", false, ArgTypeHint::None, 0.5f) //////////////////////////////////////////////////////////////////////////////// @@ -362,41 +382,19 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation // assumptions made in the macro. struct NewTerminalArgs : public NewTerminalArgsT { - NewTerminalArgs() = default; - NewTerminalArgs(int32_t& profileIndex) : - _ProfileIndex{ profileIndex } {}; - + PARTIAL_ACTION_ARG_BODY(NewTerminalArgs, NEW_TERMINAL_ARGS); ACTION_ARG(winrt::hstring, Type, L""); - - ACTION_ARG(winrt::hstring, Commandline, L""); - ACTION_ARG(winrt::hstring, StartingDirectory, L""); - ACTION_ARG(winrt::hstring, TabTitle, L""); - ACTION_ARG(Windows::Foundation::IReference, TabColor, nullptr); - ACTION_ARG(Windows::Foundation::IReference, ProfileIndex, nullptr); - ACTION_ARG(winrt::hstring, Profile, L""); ACTION_ARG(winrt::guid, SessionId, winrt::guid{}); ACTION_ARG(bool, AppendCommandLine, false); - ACTION_ARG(Windows::Foundation::IReference, SuppressApplicationTitle, nullptr); - ACTION_ARG(winrt::hstring, ColorScheme); - ACTION_ARG(Windows::Foundation::IReference, Elevate, nullptr); - ACTION_ARG(Windows::Foundation::IReference, ReloadEnvironmentVariables, nullptr); ACTION_ARG(uint64_t, ContentId); - 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 TabColorKey{ "tabColor" }; - static constexpr std::string_view ProfileIndexKey{ "index" }; - static constexpr std::string_view ProfileKey{ "profile" }; static constexpr std::string_view SessionIdKey{ "sessionId" }; static constexpr std::string_view AppendCommandLineKey{ "appendCommandLine" }; - static constexpr std::string_view SuppressApplicationTitleKey{ "suppressApplicationTitle" }; - static constexpr std::string_view ColorSchemeKey{ "colorScheme" }; - static constexpr std::string_view ElevateKey{ "elevate" }; - static constexpr std::string_view ReloadEnvironmentVariablesKey{ "reloadEnvironmentVariables" }; static constexpr std::string_view ContentKey{ "__content" }; public: + NewTerminalArgs(int32_t& profileIndex) : + _ProfileIndex{ profileIndex } {}; hstring GenerateName() const { return GenerateName(GetLibraryResourceLoader().ResourceContext()); } hstring GenerateName(const winrt::Windows::ApplicationModel::Resources::Core::ResourceContext&) const; hstring ToCommandline() const; @@ -638,6 +636,38 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation h.write(ContentArgs()); return h.finalize(); } + winrt::Windows::Foundation::Collections::IVectorView GetArgDescriptors() + { + if (_ContentArgs) + { + if (const auto contentArgs = _ContentArgs.try_as()) + { + return contentArgs.GetArgDescriptors(); + } + } + return {}; + } + IInspectable GetArgAt(uint32_t index) const + { + if (_ContentArgs) + { + if (const auto contentArgs = _ContentArgs.try_as()) + { + return contentArgs.GetArgAt(index); + } + } + return nullptr; + } + void SetArgAt(uint32_t index, IInspectable value) + { + if (_ContentArgs) + { + if (const auto contentArgs = _ContentArgs.try_as()) + { + contentArgs.SetArgAt(index, value); + } + } + } }; struct SplitPaneArgs : public SplitPaneArgsT @@ -658,14 +688,8 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation SplitPaneArgs(SplitType splitMode) : _SplitMode{ splitMode } {}; - ACTION_ARG(Model::SplitDirection, SplitDirection, SplitDirection::Automatic); + SPLIT_PANE_ARGS(DECLARE_ARGS); WINRT_PROPERTY(Model::INewContentArgs, ContentArgs, nullptr); - ACTION_ARG(SplitType, SplitMode, SplitType::Manual); - ACTION_ARG(float, SplitSize, 0.5f); - - static constexpr std::string_view SplitKey{ "split" }; - static constexpr std::string_view SplitModeKey{ "splitMode" }; - static constexpr std::string_view SplitSizeKey{ "size" }; public: hstring GenerateName() const { return GenerateName(GetLibraryResourceLoader().ResourceContext()); } @@ -688,7 +712,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation { // LOAD BEARING: Not using make_self here _will_ break you in the future! auto args = winrt::make_self(); - JsonUtils::GetValueForKey(json, SplitKey, args->_SplitDirection); + JsonUtils::GetValueForKey(json, SplitDirectionKey, args->_SplitDirection); JsonUtils::GetValueForKey(json, SplitModeKey, args->_SplitMode); JsonUtils::GetValueForKey(json, SplitSizeKey, args->_SplitSize); if (args->SplitSize() >= 1 || args->SplitSize() <= 0) @@ -708,7 +732,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation } const auto args{ get_self(val) }; auto json{ ContentArgsToJson(args->_ContentArgs) }; - JsonUtils::SetValueForKey(json, SplitKey, args->_SplitDirection); + JsonUtils::SetValueForKey(json, SplitDirectionKey, args->_SplitDirection); JsonUtils::SetValueForKey(json, SplitModeKey, args->_SplitMode); JsonUtils::SetValueForKey(json, SplitSizeKey, args->_SplitSize); return json; @@ -731,6 +755,65 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation h.write(SplitSize()); return h.finalize(); } + winrt::Windows::Foundation::Collections::IVectorView GetArgDescriptors() + { + // Base args for SplitPane + static const auto baseArgs = INIT_ARG_DESCRIPTORS(SPLIT_PANE_ARGS); + + // Cached merged variant: SplitPane + NewTerminalArgs + static const auto mergedArgs = [] { + std::vector temp; + + // copy baseArgs + for (const auto& desc : baseArgs) + { + temp.push_back(desc); + } + + // append NewTerminalArgs args + const auto newTerminalArgsDesc{ Model::NewTerminalArgs{}.GetArgDescriptors() }; + for (const auto& desc : newTerminalArgsDesc) + { + temp.push_back(desc); + } + + return winrt::single_threaded_vector(std::move(temp)).GetView(); + }(); + + // Pick which cached vector to return + if (_ContentArgs && _ContentArgs.try_as()) + { + return mergedArgs; + } + return baseArgs; + } + IInspectable GetArgAt(uint32_t index) + { + const auto additionalArgCount = ARG_COUNT(SPLIT_PANE_ARGS); + if (index < additionalArgCount) + { + X_MACRO_INDEX_BASE(); + SPLIT_PANE_ARGS(GET_ARG_BY_INDEX); + } + else + { + return _ContentArgs.as().GetArgAt(index - additionalArgCount); + } + return nullptr; + } + void SetArgAt(uint32_t index, IInspectable value) + { + const auto additionalArgCount = ARG_COUNT(SPLIT_PANE_ARGS); + if (index < additionalArgCount) + { + X_MACRO_INDEX_BASE(); + SPLIT_PANE_ARGS(SET_ARG_BY_INDEX); + } + else + { + _ContentArgs.as().SetArgAt(index - additionalArgCount, value); + } + } }; struct NewWindowArgs : public NewWindowArgsT @@ -782,6 +865,18 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation h.write(ContentArgs()); return h.finalize(); } + winrt::Windows::Foundation::Collections::IVectorView GetArgDescriptors() + { + return _ContentArgs.as().GetArgDescriptors(); + } + IInspectable GetArgAt(uint32_t index) const + { + return _ContentArgs.as().GetArgAt(index); + } + void SetArgAt(uint32_t index, IInspectable value) + { + _ContentArgs.as().SetArgAt(index, value); + } }; ACTION_ARGS_STRUCT(CopyTextArgs, COPY_TEXT_ARGS); @@ -922,6 +1017,18 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation h.write(winrt::get_abi(_Actions)); return h.finalize(); } + winrt::Windows::Foundation::Collections::IVectorView GetArgDescriptors() + { + return {}; + } + IInspectable GetArgAt(uint32_t /*index*/) const + { + return nullptr; + } + void SetArgAt(uint32_t /*index*/, IInspectable /*value*/) + { + throw winrt::hresult_not_implemented(); + } }; ACTION_ARGS_STRUCT(AdjustOpacityArgs, ADJUST_OPACITY_ARGS); diff --git a/src/cascadia/TerminalSettingsModel/ActionArgs.idl b/src/cascadia/TerminalSettingsModel/ActionArgs.idl index 9b904efa7fb..a58e95c6cb6 100644 --- a/src/cascadia/TerminalSettingsModel/ActionArgs.idl +++ b/src/cascadia/TerminalSettingsModel/ActionArgs.idl @@ -5,6 +5,29 @@ import "Command.idl"; namespace Microsoft.Terminal.Settings.Model { + enum ArgTypeHint + { + None = 0, + FilePath, + FolderPath, + ColorScheme + }; + + struct ArgDescriptor + { + String Name; + String Type; + Boolean Required; + ArgTypeHint TypeHint; + }; + + interface IActionArgsDescriptorAccess + { + Windows.Foundation.Collections.IVectorView GetArgDescriptors(); + IInspectable GetArgAt(UInt32 index); + void SetArgAt(UInt32 index, Object value); + }; + interface IActionArgs { Boolean Equals(IActionArgs other); @@ -139,7 +162,7 @@ namespace Microsoft.Terminal.Settings.Model BaseContentArgs(String type); }; - runtimeclass NewTerminalArgs : INewContentArgs { + runtimeclass NewTerminalArgs : INewContentArgs, IActionArgsDescriptorAccess { NewTerminalArgs(); NewTerminalArgs(Int32 profileIndex); @@ -178,7 +201,7 @@ namespace Microsoft.Terminal.Settings.Model ActionEventArgs(IActionArgs args); }; - [default_interface] runtimeclass CopyTextArgs : IActionArgs + [default_interface] runtimeclass CopyTextArgs : IActionArgs, IActionArgsDescriptorAccess { CopyTextArgs(); Boolean DismissSelection { get; }; @@ -187,55 +210,55 @@ namespace Microsoft.Terminal.Settings.Model Windows.Foundation.IReference CopyFormatting { get; }; }; - [default_interface] runtimeclass NewTabArgs : IActionArgs + [default_interface] runtimeclass NewTabArgs : IActionArgs, IActionArgsDescriptorAccess { NewTabArgs(INewContentArgs contentArgs); INewContentArgs ContentArgs { get; }; }; - [default_interface] runtimeclass MovePaneArgs : IActionArgs + [default_interface] runtimeclass MovePaneArgs : IActionArgs, IActionArgsDescriptorAccess { MovePaneArgs(UInt32 tabIndex, String Window); UInt32 TabIndex; String Window; }; - [default_interface] runtimeclass SwitchToTabArgs : IActionArgs + [default_interface] runtimeclass SwitchToTabArgs : IActionArgs, IActionArgsDescriptorAccess { SwitchToTabArgs(UInt32 tabIndex); UInt32 TabIndex; }; - [default_interface] runtimeclass ResizePaneArgs : IActionArgs + [default_interface] runtimeclass ResizePaneArgs : IActionArgs, IActionArgsDescriptorAccess { ResizeDirection ResizeDirection { get; }; }; - [default_interface] runtimeclass MoveFocusArgs : IActionArgs + [default_interface] runtimeclass MoveFocusArgs : IActionArgs, IActionArgsDescriptorAccess { MoveFocusArgs(FocusDirection direction); FocusDirection FocusDirection { get; }; }; - [default_interface] runtimeclass SwapPaneArgs : IActionArgs + [default_interface] runtimeclass SwapPaneArgs : IActionArgs, IActionArgsDescriptorAccess { SwapPaneArgs(FocusDirection direction); FocusDirection Direction { get; }; }; - [default_interface] runtimeclass AdjustFontSizeArgs : IActionArgs + [default_interface] runtimeclass AdjustFontSizeArgs : IActionArgs, IActionArgsDescriptorAccess { Single Delta { get; }; }; - [default_interface] runtimeclass SendInputArgs : IActionArgs + [default_interface] runtimeclass SendInputArgs : IActionArgs, IActionArgsDescriptorAccess { SendInputArgs(String input); String Input { get; }; }; - [default_interface] runtimeclass SplitPaneArgs : IActionArgs + [default_interface] runtimeclass SplitPaneArgs : IActionArgs, IActionArgsDescriptorAccess { SplitPaneArgs(SplitType splitMode, SplitDirection split, Single size, INewContentArgs contentArgs); SplitPaneArgs(SplitDirection split, Single size, INewContentArgs contentArgs); @@ -248,106 +271,106 @@ namespace Microsoft.Terminal.Settings.Model Single SplitSize { get; }; }; - [default_interface] runtimeclass OpenSettingsArgs : IActionArgs + [default_interface] runtimeclass OpenSettingsArgs : IActionArgs, IActionArgsDescriptorAccess { OpenSettingsArgs(SettingsTarget target); SettingsTarget Target { get; }; }; - [default_interface] runtimeclass SetFocusModeArgs : IActionArgs + [default_interface] runtimeclass SetFocusModeArgs : IActionArgs, IActionArgsDescriptorAccess { SetFocusModeArgs(Boolean isFocusMode); Boolean IsFocusMode { get; }; }; - [default_interface] runtimeclass SetFullScreenArgs : IActionArgs + [default_interface] runtimeclass SetFullScreenArgs : IActionArgs, IActionArgsDescriptorAccess { SetFullScreenArgs(Boolean isFullScreen); Boolean IsFullScreen { get; }; }; - [default_interface] runtimeclass SetMaximizedArgs : IActionArgs + [default_interface] runtimeclass SetMaximizedArgs : IActionArgs, IActionArgsDescriptorAccess { SetMaximizedArgs(Boolean isMaximized); Boolean IsMaximized { get; }; }; - [default_interface] runtimeclass SetColorSchemeArgs : IActionArgs + [default_interface] runtimeclass SetColorSchemeArgs : IActionArgs, IActionArgsDescriptorAccess { SetColorSchemeArgs(String name); String SchemeName { get; }; }; - [default_interface] runtimeclass SetTabColorArgs : IActionArgs + [default_interface] runtimeclass SetTabColorArgs : IActionArgs, IActionArgsDescriptorAccess { SetTabColorArgs(Windows.UI.Color tabColor); Windows.Foundation.IReference TabColor { get; }; }; - [default_interface] runtimeclass RenameTabArgs : IActionArgs + [default_interface] runtimeclass RenameTabArgs : IActionArgs, IActionArgsDescriptorAccess { RenameTabArgs(String title); String Title { get; }; }; - [default_interface] runtimeclass ExecuteCommandlineArgs : IActionArgs + [default_interface] runtimeclass ExecuteCommandlineArgs : IActionArgs, IActionArgsDescriptorAccess { ExecuteCommandlineArgs(String commandline); String Commandline; }; - [default_interface] runtimeclass CloseOtherTabsArgs : IActionArgs + [default_interface] runtimeclass CloseOtherTabsArgs : IActionArgs, IActionArgsDescriptorAccess { CloseOtherTabsArgs(UInt32 tabIndex); Windows.Foundation.IReference Index { get; }; }; - [default_interface] runtimeclass CloseTabsAfterArgs : IActionArgs + [default_interface] runtimeclass CloseTabsAfterArgs : IActionArgs, IActionArgsDescriptorAccess { CloseTabsAfterArgs(UInt32 tabIndex); Windows.Foundation.IReference Index { get; }; }; - [default_interface] runtimeclass CloseTabArgs : IActionArgs + [default_interface] runtimeclass CloseTabArgs : IActionArgs, IActionArgsDescriptorAccess { CloseTabArgs(UInt32 tabIndex); Windows.Foundation.IReference Index { get; }; }; - [default_interface] runtimeclass MoveTabArgs : IActionArgs + [default_interface] runtimeclass MoveTabArgs : IActionArgs, IActionArgsDescriptorAccess { MoveTabArgs(String window, MoveTabDirection direction); MoveTabDirection Direction { get; }; String Window { get; }; }; - [default_interface] runtimeclass ScrollUpArgs : IActionArgs + [default_interface] runtimeclass ScrollUpArgs : IActionArgs, IActionArgsDescriptorAccess { Windows.Foundation.IReference RowsToScroll { get; }; }; - [default_interface] runtimeclass ScrollDownArgs : IActionArgs + [default_interface] runtimeclass ScrollDownArgs : IActionArgs, IActionArgsDescriptorAccess { Windows.Foundation.IReference RowsToScroll { get; }; }; - [default_interface] runtimeclass ScrollToMarkArgs : IActionArgs + [default_interface] runtimeclass ScrollToMarkArgs : IActionArgs, IActionArgsDescriptorAccess { Microsoft.Terminal.Control.ScrollToMarkDirection Direction { get; }; }; - [default_interface] runtimeclass AddMarkArgs : IActionArgs + [default_interface] runtimeclass AddMarkArgs : IActionArgs, IActionArgsDescriptorAccess { Windows.Foundation.IReference Color { get; }; }; - [default_interface] runtimeclass ToggleCommandPaletteArgs : IActionArgs + [default_interface] runtimeclass ToggleCommandPaletteArgs : IActionArgs, IActionArgsDescriptorAccess { CommandPaletteLaunchMode LaunchMode { get; }; }; - [default_interface] runtimeclass SuggestionsArgs : IActionArgs + [default_interface] runtimeclass SuggestionsArgs : IActionArgs, IActionArgsDescriptorAccess { SuggestionsArgs(); SuggestionsArgs(SuggestionsSource source, Boolean useCommandline); @@ -355,13 +378,13 @@ namespace Microsoft.Terminal.Settings.Model Boolean UseCommandline { get; }; }; - [default_interface] runtimeclass FindMatchArgs : IActionArgs + [default_interface] runtimeclass FindMatchArgs : IActionArgs, IActionArgsDescriptorAccess { FindMatchArgs(FindMatchDirection direction); FindMatchDirection Direction { get; }; }; - [default_interface] runtimeclass SaveSnippetArgs : IActionArgs + [default_interface] runtimeclass SaveSnippetArgs : IActionArgs, IActionArgsDescriptorAccess { SaveSnippetArgs(); SaveSnippetArgs(String Name, String Commandline, String KeyChord); @@ -370,38 +393,38 @@ namespace Microsoft.Terminal.Settings.Model String KeyChord; }; - [default_interface] runtimeclass NewWindowArgs : IActionArgs + [default_interface] runtimeclass NewWindowArgs : IActionArgs, IActionArgsDescriptorAccess { NewWindowArgs(INewContentArgs contentArgs); INewContentArgs ContentArgs { get; }; }; - [default_interface] runtimeclass PrevTabArgs : IActionArgs + [default_interface] runtimeclass PrevTabArgs : IActionArgs, IActionArgsDescriptorAccess { PrevTabArgs(); PrevTabArgs(TabSwitcherMode SwitcherMode); Windows.Foundation.IReference SwitcherMode; }; - [default_interface] runtimeclass NextTabArgs : IActionArgs + [default_interface] runtimeclass NextTabArgs : IActionArgs, IActionArgsDescriptorAccess { NextTabArgs(); NextTabArgs(TabSwitcherMode SwitcherMode); Windows.Foundation.IReference SwitcherMode; }; - [default_interface] runtimeclass RenameWindowArgs : IActionArgs + [default_interface] runtimeclass RenameWindowArgs : IActionArgs, IActionArgsDescriptorAccess { RenameWindowArgs(String name); String Name { get; }; }; - [default_interface] runtimeclass SearchForTextArgs : IActionArgs + [default_interface] runtimeclass SearchForTextArgs : IActionArgs, IActionArgsDescriptorAccess { String QueryUrl { get; }; }; - [default_interface] runtimeclass GlobalSummonArgs : IActionArgs + [default_interface] runtimeclass GlobalSummonArgs : IActionArgs, IActionArgsDescriptorAccess { String Name { get; }; DesktopBehavior Desktop { get; }; @@ -410,50 +433,50 @@ namespace Microsoft.Terminal.Settings.Model UInt32 DropdownDuration { get; }; }; - [default_interface] runtimeclass FocusPaneArgs : IActionArgs + [default_interface] runtimeclass FocusPaneArgs : IActionArgs, IActionArgsDescriptorAccess { FocusPaneArgs(UInt32 Id); UInt32 Id { get; }; }; - [default_interface] runtimeclass ExportBufferArgs : IActionArgs + [default_interface] runtimeclass ExportBufferArgs : IActionArgs, IActionArgsDescriptorAccess { ExportBufferArgs(String path); String Path { get; }; }; - [default_interface] runtimeclass ClearBufferArgs : IActionArgs + [default_interface] runtimeclass ClearBufferArgs : IActionArgs, IActionArgsDescriptorAccess { ClearBufferArgs(Microsoft.Terminal.Control.ClearBufferType clear); Microsoft.Terminal.Control.ClearBufferType Clear { get; }; }; - [default_interface] runtimeclass MultipleActionsArgs : IActionArgs + [default_interface] runtimeclass MultipleActionsArgs : IActionArgs, IActionArgsDescriptorAccess { MultipleActionsArgs(); Windows.Foundation.Collections.IVector Actions; }; - [default_interface] runtimeclass AdjustOpacityArgs : IActionArgs + [default_interface] runtimeclass AdjustOpacityArgs : IActionArgs, IActionArgsDescriptorAccess { AdjustOpacityArgs(); Int32 Opacity { get; }; Boolean Relative { get; }; }; - [default_interface] runtimeclass ColorSelectionArgs : IActionArgs + [default_interface] runtimeclass ColorSelectionArgs : IActionArgs, IActionArgsDescriptorAccess { Microsoft.Terminal.Control.SelectionColor Foreground; Microsoft.Terminal.Control.SelectionColor Background; Microsoft.Terminal.Core.MatchMode MatchMode { get; }; }; - [default_interface] runtimeclass SelectCommandArgs : IActionArgs + [default_interface] runtimeclass SelectCommandArgs : IActionArgs, IActionArgsDescriptorAccess { SelectCommandArgs(SelectOutputDirection direction); SelectOutputDirection Direction { get; }; } - [default_interface] runtimeclass SelectOutputArgs : IActionArgs + [default_interface] runtimeclass SelectOutputArgs : IActionArgs, IActionArgsDescriptorAccess { SelectOutputArgs(SelectOutputDirection direction); SelectOutputDirection Direction { get; }; diff --git a/src/cascadia/TerminalSettingsModel/ActionArgsMagic.h b/src/cascadia/TerminalSettingsModel/ActionArgsMagic.h index 2623bb707be..f8d8a1b742d 100644 --- a/src/cascadia/TerminalSettingsModel/ActionArgsMagic.h +++ b/src/cascadia/TerminalSettingsModel/ActionArgsMagic.h @@ -54,24 +54,79 @@ struct InitListPlaceholder // expanded. Pretty critical for tracking down extraneous commas, etc. // Property definitions, and JSON keys -#define DECLARE_ARGS(type, name, jsonKey, required, ...) \ - static constexpr std::string_view name##Key{ jsonKey }; \ +#define DECLARE_ARGS(type, name, jsonKey, required, typeHint, ...) \ + static constexpr std::string_view name##Key{ jsonKey }; \ ACTION_ARG(type, name, ##__VA_ARGS__); // Parameters to the non-default ctor -#define CTOR_PARAMS(type, name, jsonKey, required, ...) \ +#define CTOR_PARAMS(type, name, jsonKey, required, typeHint, ...) \ const type &name##Param, // initializers in the ctor -#define CTOR_INIT(type, name, jsonKey, required, ...) \ +#define CTOR_INIT(type, name, jsonKey, required, typeHint, ...) \ _##name{ name##Param }, +// Expands to `+1` for every arg in the list +#define COUNT_ONE(type, name, jsonKey, required, typeHint, ...) +1 + +// Arg count macro +#define ARG_COUNT(argsMacro) (0 argsMacro(COUNT_ONE)) + +#define ARG_DESC_STRINGIFY2(x) #x +#define ARG_DESC_STRINGIFY(x) ARG_DESC_STRINGIFY2(x) +#define ARG_DESC_WIDEN2(x) L##x +#define ARG_DESC_WIDEN(x) ARG_DESC_WIDEN2(x) +#define LOCALIZED_NAME(name) ARG_DESC_WIDEN(ARG_DESC_STRINGIFY(name##ActionArgumentLocalized)) + +// append this argument's description to the internal vector +#define APPEND_ARG_DESCRIPTION(type, name, jsonKey, required, typeHint, ...) \ + temp.push_back({ RS_(LOCALIZED_NAME(name)), L## #type, std::wstring_view(L## #required) != L"false", typeHint }); + +#define INIT_ARG_DESCRIPTORS(argsMacro) \ + ([]() -> winrt::Windows::Foundation::Collections::IVectorView { \ + std::vector temp; \ + argsMacro(APPEND_ARG_DESCRIPTION) return winrt::single_threaded_vector(std::move(temp)).GetView(); \ + }()) + // check each property in the Equals() method. You'll note there's a stray // `true` in the definition of Equals() below, that's to deal with trailing // commas -#define EQUALS_ARGS(type, name, jsonKey, required, ...) \ +#define EQUALS_ARGS(type, name, jsonKey, required, typeHint, ...) \ &&(otherAsUs->_##name == _##name) +#define X_MACRO_INDEX_BASE() \ + constexpr auto X_MACRO_INDEXED_BASE__ = __COUNTER__ + +#define X_MACRO_INDEX() \ + (__COUNTER__ - X_MACRO_INDEXED_BASE__ - 1) + +// getter and setter for each property by index +#define GET_ARG_BY_INDEX(type, name, jsonKey, required, typeHint, ...) \ + if (index == X_MACRO_INDEX()) \ + { \ + if (_##name.has_value()) \ + { \ + return winrt::box_value(_##name.value()); \ + } \ + else \ + { \ + return winrt::box_value(static_cast(__VA_ARGS__)); \ + } \ + } + +#define SET_ARG_BY_INDEX(type, name, jsonKey, required, typeHint, ...) \ + if (index == X_MACRO_INDEX()) \ + { \ + if (value) \ + { \ + _##name = winrt::unbox_value(value); \ + } \ + else \ + { \ + _##name = std::nullopt; \ + } \ + } + // JSON deserialization. If the parameter is required to pass any validation, // add that as the `required` parameter here, as the body of a conditional // EX: For the RESIZE_PANE_ARGS @@ -79,7 +134,7 @@ struct InitListPlaceholder // the bit // args->ResizeDirection() == ResizeDirection::None // is used as the conditional for the validation here. -#define FROM_JSON_ARGS(type, name, jsonKey, required, ...) \ +#define FROM_JSON_ARGS(type, name, jsonKey, required, typeHint, ...) \ JsonUtils::GetValueForKey(json, jsonKey, args->_##name); \ if (required) \ { \ @@ -87,17 +142,17 @@ struct InitListPlaceholder } // JSON serialization -#define TO_JSON_ARGS(type, name, jsonKey, required, ...) \ +#define TO_JSON_ARGS(type, name, jsonKey, required, typeHint, ...) \ JsonUtils::SetValueForKey(json, jsonKey, args->_##name); // Copy each property in the Copy() method -#define COPY_ARGS(type, name, jsonKey, required, ...) \ +#define COPY_ARGS(type, name, jsonKey, required, typeHint, ...) \ copy->_##name = _##name; // hash each property in Hash(). You'll note there's a stray `0` in the // definition of Hash() below, that's to deal with trailing commas (or in this // case, leading.) -#define HASH_ARGS(type, name, jsonKey, required, ...) \ +#define HASH_ARGS(type, name, jsonKey, required, typeHint, ...) \ h.write(name()); // Use ACTION_ARGS_STRUCT when you've got no other customizing to do. @@ -112,14 +167,7 @@ struct InitListPlaceholder // * GlobalSummonArgs has the QuakeModeFromJson helper #define ACTION_ARG_BODY(className, argsMacro) \ - className() = default; \ - className( \ - argsMacro(CTOR_PARAMS) InitListPlaceholder = {}) : \ - argsMacro(CTOR_INIT) _placeholder{} {}; \ - argsMacro(DECLARE_ARGS); \ - \ -private: \ - InitListPlaceholder _placeholder; \ + PARTIAL_ACTION_ARG_BODY(className, argsMacro) \ \ public: \ hstring GenerateName() const \ @@ -167,3 +215,31 @@ public: argsMacro(HASH_ARGS); \ return h.finalize(); \ } + +#define PARTIAL_ACTION_ARG_BODY(className, argsMacro) \ + className() = default; \ + className( \ + argsMacro(CTOR_PARAMS) InitListPlaceholder = {}) : \ + argsMacro(CTOR_INIT) \ + _placeholder{} {}; \ + argsMacro(DECLARE_ARGS); \ + \ +private: \ + InitListPlaceholder _placeholder; \ + \ +public: \ + winrt::Windows::Foundation::Collections::IVectorView GetArgDescriptors() \ + { \ + static const auto descriptors = INIT_ARG_DESCRIPTORS(argsMacro); \ + return descriptors; \ + } \ + IInspectable GetArgAt(uint32_t index) const \ + { \ + X_MACRO_INDEX_BASE(); \ + argsMacro(GET_ARG_BY_INDEX) return nullptr; \ + } \ + void SetArgAt(uint32_t index, IInspectable value) \ + { \ + X_MACRO_INDEX_BASE(); \ + argsMacro(SET_ARG_BY_INDEX) \ + } diff --git a/src/cascadia/TerminalSettingsModel/ActionMap.cpp b/src/cascadia/TerminalSettingsModel/ActionMap.cpp index c5f23f55eff..ebc8c4f9310 100644 --- a/src/cascadia/TerminalSettingsModel/ActionMap.cpp +++ b/src/cascadia/TerminalSettingsModel/ActionMap.cpp @@ -5,11 +5,11 @@ #include "AllShortcutActions.h" #include "ActionMap.h" #include "Command.h" -#include "AllShortcutActions.h" #include #include #include "ActionMap.g.cpp" +#include "ActionArgFactory.g.cpp" using namespace winrt::Microsoft::Terminal::Settings::Model; using namespace winrt::Microsoft::Terminal::Control; @@ -61,6 +61,228 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation return hasher.finalize(); } + winrt::hstring ActionArgFactory::GetNameForAction(Model::ShortcutAction action) + { + return GetNameForAction(action, GetLibraryResourceLoader().ResourceContext()); + } + + winrt::hstring ActionArgFactory::GetNameForAction(Model::ShortcutAction action, Windows::ApplicationModel::Resources::Core::ResourceContext context) + { + // Use a magic static to initialize this map, because we won't be able + // to load the resources at _init_, only at runtime. + static auto actionNames = []() { + return std::unordered_map{ + { ShortcutAction::AddMark, USES_RESOURCE(L"AddMarkCommandKey") }, + { ShortcutAction::AdjustFontSize, USES_RESOURCE(L"AdjustFontSizeCommandKey") }, + { ShortcutAction::AdjustOpacity, USES_RESOURCE(L"AdjustOpacity") }, + { ShortcutAction::BreakIntoDebugger, USES_RESOURCE(L"BreakIntoDebuggerCommandKey") }, + { ShortcutAction::ClearAllMarks, USES_RESOURCE(L"ClearAllMarksCommandKey") }, + { ShortcutAction::ClearBuffer, USES_RESOURCE(L"ClearBuffer") }, + { ShortcutAction::ClearMark, USES_RESOURCE(L"ClearMarkCommandKey") }, + { ShortcutAction::CloseOtherPanes, USES_RESOURCE(L"CloseOtherPanesCommandKey") }, + { ShortcutAction::CloseOtherTabs, USES_RESOURCE(L"CloseOtherTabs") }, + { ShortcutAction::ClosePane, USES_RESOURCE(L"ClosePaneCommandKey") }, + { ShortcutAction::CloseTab, USES_RESOURCE(L"CloseTab") }, + { ShortcutAction::CloseTabsAfter, USES_RESOURCE(L"CloseTabsAfter") }, + { ShortcutAction::CloseWindow, USES_RESOURCE(L"CloseWindowCommandKey") }, + { ShortcutAction::ColorSelection, USES_RESOURCE(L"ColorSelection") }, + { ShortcutAction::CopyText, USES_RESOURCE(L"CopyTextCommandKey") }, + { ShortcutAction::DisplayWorkingDirectory, USES_RESOURCE(L"DisplayWorkingDirectoryCommandKey") }, + { ShortcutAction::DisablePaneReadOnly, USES_RESOURCE(L"DisablePaneReadOnlyCommandKey") }, + { ShortcutAction::DuplicateTab, USES_RESOURCE(L"DuplicateTabCommandKey") }, + { ShortcutAction::EnablePaneReadOnly, USES_RESOURCE(L"EnablePaneReadOnlyCommandKey") }, + { ShortcutAction::ExecuteCommandline, USES_RESOURCE(L"ExecuteCommandlineCommandKey") }, + { ShortcutAction::ExportBuffer, USES_RESOURCE(L"ExportBuffer") }, + { ShortcutAction::ExpandSelectionToWord, USES_RESOURCE(L"ExpandSelectionToWordCommandKey") }, + { ShortcutAction::Find, USES_RESOURCE(L"FindCommandKey") }, + { ShortcutAction::FindMatch, USES_RESOURCE(L"FindMatch") }, + { ShortcutAction::FocusPane, USES_RESOURCE(L"FocusPane") }, + { ShortcutAction::GlobalSummon, USES_RESOURCE(L"GlobalSummonCommandKey") }, + { ShortcutAction::IdentifyWindow, USES_RESOURCE(L"IdentifyWindowCommandKey") }, + { ShortcutAction::IdentifyWindows, USES_RESOURCE(L"IdentifyWindowsCommandKey") }, + { ShortcutAction::MarkMode, USES_RESOURCE(L"MarkModeCommandKey") }, + { ShortcutAction::MoveFocus, USES_RESOURCE(L"MoveFocusCommandKey") }, + { ShortcutAction::MovePane, USES_RESOURCE(L"MovePaneCommandKey") }, + { ShortcutAction::MoveTab, USES_RESOURCE(L"MoveTab") }, + { ShortcutAction::MultipleActions, USES_RESOURCE(L"MultipleActions") }, + { ShortcutAction::NewTab, USES_RESOURCE(L"NewTabCommandKey") }, + { ShortcutAction::NewWindow, USES_RESOURCE(L"NewWindowCommandKey") }, + { ShortcutAction::NextTab, USES_RESOURCE(L"NextTabCommandKey") }, + { ShortcutAction::OpenAbout, USES_RESOURCE(L"OpenAboutCommandKey") }, + { ShortcutAction::OpenCWD, USES_RESOURCE(L"OpenCWDCommandKey") }, + { ShortcutAction::OpenNewTabDropdown, USES_RESOURCE(L"OpenNewTabDropdownCommandKey") }, + { ShortcutAction::OpenScratchpad, USES_RESOURCE(L"OpenScratchpadKey") }, + { ShortcutAction::OpenSettings, USES_RESOURCE(L"OpenSettingsUICommandKey") }, + { ShortcutAction::OpenSystemMenu, USES_RESOURCE(L"OpenSystemMenuCommandKey") }, + { ShortcutAction::OpenTabColorPicker, USES_RESOURCE(L"OpenTabColorPickerCommandKey") }, + { ShortcutAction::OpenTabRenamer, USES_RESOURCE(L"OpenTabRenamerCommandKey") }, + { ShortcutAction::OpenWindowRenamer, USES_RESOURCE(L"OpenWindowRenamerCommandKey") }, + { ShortcutAction::PasteText, USES_RESOURCE(L"PasteTextCommandKey") }, + { ShortcutAction::PrevTab, USES_RESOURCE(L"PrevTabCommandKey") }, + { ShortcutAction::QuickFix, USES_RESOURCE(L"QuickFixCommandKey") }, + { ShortcutAction::QuakeMode, USES_RESOURCE(L"QuakeModeCommandKey") }, + { ShortcutAction::Quit, USES_RESOURCE(L"QuitCommandKey") }, + { ShortcutAction::RenameTab, USES_RESOURCE(L"ResetTabNameCommandKey") }, + { ShortcutAction::RenameWindow, USES_RESOURCE(L"ResetWindowNameCommandKey") }, + { ShortcutAction::ResetFontSize, USES_RESOURCE(L"ResetFontSizeCommandKey") }, + { ShortcutAction::RestartConnection, USES_RESOURCE(L"RestartConnectionKey") }, + { ShortcutAction::ResizePane, USES_RESOURCE(L"ResizePaneCommandKey") }, + { ShortcutAction::RestoreLastClosed, USES_RESOURCE(L"RestoreLastClosedCommandKey") }, + { ShortcutAction::SaveSnippet, USES_RESOURCE(L"SaveSnippetNamePrefix") }, + { ShortcutAction::ScrollDown, USES_RESOURCE(L"ScrollDownCommandKey") }, + { ShortcutAction::ScrollDownPage, USES_RESOURCE(L"ScrollDownPageCommandKey") }, + { ShortcutAction::ScrollToBottom, USES_RESOURCE(L"ScrollToBottomCommandKey") }, + { ShortcutAction::ScrollToMark, USES_RESOURCE(L"ScrollToPreviousMarkCommandKey") }, + { ShortcutAction::ScrollToTop, USES_RESOURCE(L"ScrollToTopCommandKey") }, + { ShortcutAction::ScrollUp, USES_RESOURCE(L"ScrollUpCommandKey") }, + { ShortcutAction::ScrollUpPage, USES_RESOURCE(L"ScrollUpPageCommandKey") }, + { ShortcutAction::SearchForText, USES_RESOURCE(L"SearchForText") }, + { ShortcutAction::SelectAll, USES_RESOURCE(L"SelectAllCommandKey") }, + { ShortcutAction::SelectCommand, USES_RESOURCE(L"SelectCommand") }, + { ShortcutAction::SelectOutput, USES_RESOURCE(L"SelectOutput") }, + { ShortcutAction::SendInput, USES_RESOURCE(L"SendInput") }, + { ShortcutAction::SetColorScheme, USES_RESOURCE(L"SetColorScheme") }, + { ShortcutAction::SetFocusMode, USES_RESOURCE(L"SetFocusMode") }, + { ShortcutAction::SetFullScreen, USES_RESOURCE(L"SetFullScreen") }, + { ShortcutAction::SetMaximized, USES_RESOURCE(L"SetMaximized") }, + { ShortcutAction::SetTabColor, USES_RESOURCE(L"ResetTabColorCommandKey") }, + { ShortcutAction::ShowContextMenu, USES_RESOURCE(L"ShowContextMenuCommandKey") }, + { ShortcutAction::SplitPane, USES_RESOURCE(L"SplitPaneCommandKey") }, + { ShortcutAction::Suggestions, USES_RESOURCE(L"Suggestions") }, + { ShortcutAction::SwapPane, USES_RESOURCE(L"SwapPaneCommandKey") }, + { ShortcutAction::SwitchSelectionEndpoint, USES_RESOURCE(L"SwitchSelectionEndpointCommandKey") }, + { ShortcutAction::SwitchToTab, USES_RESOURCE(L"SwitchToTabCommandKey") }, + { ShortcutAction::TabSearch, USES_RESOURCE(L"TabSearchCommandKey") }, + { ShortcutAction::ToggleAlwaysOnTop, USES_RESOURCE(L"ToggleAlwaysOnTopCommandKey") }, + { ShortcutAction::ToggleBlockSelection, USES_RESOURCE(L"ToggleBlockSelectionCommandKey") }, + { ShortcutAction::ToggleBroadcastInput, USES_RESOURCE(L"ToggleBroadcastInputCommandKey") }, + { ShortcutAction::ToggleCommandPalette, USES_RESOURCE(L"ToggleCommandPaletteCommandKey") }, + { ShortcutAction::ToggleFocusMode, USES_RESOURCE(L"ToggleFocusModeCommandKey") }, + { ShortcutAction::ToggleFullscreen, USES_RESOURCE(L"ToggleFullscreenCommandKey") }, + { ShortcutAction::TogglePaneReadOnly, USES_RESOURCE(L"TogglePaneReadOnlyCommandKey") }, + { ShortcutAction::TogglePaneZoom, USES_RESOURCE(L"TogglePaneZoomCommandKey") }, + { ShortcutAction::ToggleShaderEffects, USES_RESOURCE(L"ToggleShaderEffectsCommandKey") }, + { ShortcutAction::ToggleSplitOrientation, USES_RESOURCE(L"ToggleSplitOrientationCommandKey") }, + }; + }(); + + const auto found = actionNames.find(action); + if (found != actionNames.end() && !found->second.empty()) + { + return GetLibraryResourceLoader().ResourceMap().GetValue(found->second, context).ValueAsString(); + } + return winrt::hstring{}; + } + + winrt::Windows::Foundation::Collections::IMap ActionArgFactory::AvailableShortcutActionsAndNames() + { + std::unordered_map actionNames; +#define ON_ALL_ACTIONS(action) actionNames.emplace(ShortcutAction::action, GetNameForAction(ShortcutAction::action)); + + ALL_SHORTCUT_ACTIONS + +#undef ON_ALL_ACTIONS + return winrt::single_threaded_map(std::move(actionNames)); + } + + Model::IActionArgs ActionArgFactory::GetEmptyArgsForAction(Model::ShortcutAction shortcutAction) + { + // TODO: GH 19056 - we cannot cleanly macro this because of some special cases (SplitPaneArgs, NewTabArgs, NewWindowArgs) + // where we initialize a NewTerminalArgs object to pass in to them because the settings UI cannot currently handle + // a ContentArgs object that is not a NewTerminalArgs + switch (shortcutAction) + { + case Model::ShortcutAction::AdjustFontSize: + return winrt::make(); + case Model::ShortcutAction::CloseOtherTabs: + return winrt::make(); + case Model::ShortcutAction::CloseTabsAfter: + return winrt::make(); + case Model::ShortcutAction::CloseTab: + return winrt::make(); + case Model::ShortcutAction::CopyText: + return winrt::make(); + case Model::ShortcutAction::ExecuteCommandline: + return winrt::make(); + case Model::ShortcutAction::FindMatch: + return winrt::make(); + case Model::ShortcutAction::SearchForText: + return winrt::make(); + case Model::ShortcutAction::GlobalSummon: + return winrt::make(); + case Model::ShortcutAction::MoveFocus: + return winrt::make(); + case Model::ShortcutAction::MovePane: + return winrt::make(); + case Model::ShortcutAction::SwapPane: + return winrt::make(); + case Model::ShortcutAction::MoveTab: + return winrt::make(); + case Model::ShortcutAction::NewTab: + return winrt::make(Model::NewTerminalArgs{}); + case Model::ShortcutAction::NewWindow: + return winrt::make(Model::NewTerminalArgs{}); + case Model::ShortcutAction::NextTab: + return winrt::make(); + case Model::ShortcutAction::OpenSettings: + return winrt::make(); + case Model::ShortcutAction::SetFocusMode: + return winrt::make(); + case Model::ShortcutAction::SetFullScreen: + return winrt::make(); + case Model::ShortcutAction::SetMaximized: + return winrt::make(); + case Model::ShortcutAction::PrevTab: + return winrt::make(); + case Model::ShortcutAction::RenameTab: + return winrt::make(); + case Model::ShortcutAction::RenameWindow: + return winrt::make(); + case Model::ShortcutAction::ResizePane: + return winrt::make(); + case Model::ShortcutAction::ScrollDown: + return winrt::make(); + case Model::ShortcutAction::ScrollUp: + return winrt::make(); + case Model::ShortcutAction::ScrollToMark: + return winrt::make(); + case Model::ShortcutAction::AddMark: + return winrt::make(); + case Model::ShortcutAction::SendInput: + return winrt::make(); + case Model::ShortcutAction::SetColorScheme: + return winrt::make(); + case Model::ShortcutAction::SetTabColor: + return winrt::make(); + case Model::ShortcutAction::SplitPane: + return winrt::make(SplitDirection::Automatic, Model::NewTerminalArgs{}); + case Model::ShortcutAction::SwitchToTab: + return winrt::make(); + case Model::ShortcutAction::ToggleCommandPalette: + return winrt::make(); + case Model::ShortcutAction::FocusPane: + return winrt::make(); + case Model::ShortcutAction::ExportBuffer: + return winrt::make(); + case Model::ShortcutAction::ClearBuffer: + return winrt::make(); + case Model::ShortcutAction::MultipleActions: + return winrt::make(); + case Model::ShortcutAction::AdjustOpacity: + return winrt::make(); + case Model::ShortcutAction::Suggestions: + return winrt::make(); + case Model::ShortcutAction::SelectCommand: + return winrt::make(); + case Model::ShortcutAction::SelectOutput: + return winrt::make(); + case Model::ShortcutAction::ColorSelection: + return winrt::make(); + default: + return nullptr; + } + } + // Method Description: // - Detects if any of the user's actions are identical to the inbox actions, // and if so, deletes them and redirects their keybindings to the inbox actions @@ -380,6 +602,15 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation return _ResolvedKeyToActionMapCache.GetView(); } + IVectorView ActionMap::AllCommands() + { + if (!_ResolvedKeyToActionMapCache) + { + _RefreshKeyBindingCaches(); + } + return _AllCommandsCache.GetView(); + } + void ActionMap::_RefreshKeyBindingCaches() { _CumulativeKeyToActionMapCache.clear(); @@ -387,6 +618,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation _CumulativeActionToKeyMapCache.clear(); std::unordered_map globalHotkeys; std::unordered_map resolvedKeyToActionMap; + std::vector allCommandsVector; _PopulateCumulativeKeyMaps(_CumulativeKeyToActionMapCache, _CumulativeActionToKeyMapCache); _PopulateCumulativeActionMap(_CumulativeIDToActionMapCache); @@ -406,8 +638,14 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation } } + for (const auto& [_, cmd] : _CumulativeIDToActionMapCache) + { + allCommandsVector.emplace_back(cmd); + } + _ResolvedKeyToActionMapCache = single_threaded_map(std::move(resolvedKeyToActionMap)); _GlobalHotkeysCache = single_threaded_map(std::move(globalHotkeys)); + _AllCommandsCache = single_threaded_vector(std::move(allCommandsVector)); } com_ptr ActionMap::Copy() const @@ -421,7 +659,8 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation actionMap->_ActionMap.reserve(_ActionMap.size()); for (const auto& [actionID, cmd] : _ActionMap) { - actionMap->_ActionMap.emplace(actionID, *winrt::get_self(cmd)->Copy()); + const auto copiedCmd = winrt::get_self(cmd)->Copy(); + actionMap->_ActionMap.emplace(actionID, *copiedCmd); } // Name --> Command @@ -686,6 +925,24 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation return nullptr; } + IVector ActionMap::AllKeyBindingsForAction(const winrt::hstring& cmdID) + { + if (!_ResolvedKeyToActionMapCache) + { + _RefreshKeyBindingCaches(); + } + + std::vector keybindingsList; + for (const auto& [key, ID] : _CumulativeKeyToActionMapCache) + { + if (ID == cmdID) + { + keybindingsList.emplace_back(key); + } + } + return single_threaded_vector(std::move(keybindingsList)); + } + // Method Description: // - Rebinds a key binding to a new key chord // Arguments: @@ -741,6 +998,13 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation } } + void ActionMap::AddKeyBinding(Control::KeyChord keys, const winrt::hstring& cmdID) + { + _KeyMap.insert_or_assign(keys, cmdID); + _changeLog.emplace(KeysKey); + _RefreshKeyBindingCaches(); + } + // Method Description: // - Add a new key binding // - If the key chord is already in use, the conflicting command is overwritten. @@ -757,6 +1021,12 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation AddAction(*cmd, keys); } + void ActionMap::DeleteUserCommand(const winrt::hstring& cmdID) + { + _ActionMap.erase(cmdID); + _RefreshKeyBindingCaches(); + } + // This is a helper to aid in sorting commands by their `Name`s, alphabetically. static bool _compareSchemeNames(const ColorScheme& lhs, const ColorScheme& rhs) { @@ -936,6 +1206,52 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation AddAction(*cmd, keys); } + void ActionMap::UpdateCommandID(const Model::Command& cmd, winrt::hstring newID) + { + const auto oldID = cmd.ID(); + if (newID.empty()) + { + // if the new ID is empty, that means we need to generate a new one + newID = winrt::get_self(cmd.ActionAndArgs())->GenerateID(); + } + if (newID != oldID) + { + if (const auto foundCmd{ _GetActionByID(newID) }) + { + const auto foundCmdActionAndArgs = foundCmd.ActionAndArgs(); + if (foundCmdActionAndArgs != cmd.ActionAndArgs()) + { + // we found a command that has the same ID as this one, but that command has different ActionAndArgs + // this means that foundCommand's action and/or args have been changed since its ID was generated, + // generate a new one for it + // Note: this is recursive! We're calling UpdateCommandID again wich lands us back in here to resolve any cascading collisions + auto foundCmdNewID = winrt::get_self(foundCmdActionAndArgs)->GenerateID(); + UpdateCommandID(foundCmd, foundCmdNewID); + } + } + winrt::get_self(cmd)->ID(newID); + // update _ActionMap with the ID change + _ActionMap.erase(oldID); + _ActionMap.emplace(newID, cmd); + + // update _KeyMap so that all keys that pointed to the old ID now point to the new ID + std::vector keysToRemap; + for (const auto& [keys, cmdID] : _KeyMap) + { + if (cmdID == oldID) + { + keysToRemap.push_back(keys); + } + } + for (const auto& keys : keysToRemap) + { + _KeyMap.erase(keys); + _KeyMap.emplace(keys, newID); + } + } + _RefreshKeyBindingCaches(); + } + // Look for a .wt.json file in the given directory. If it exists, // read it, parse it's JSON, and retrieve all the sendInput actions. std::unordered_map ActionMap::_loadLocalSnippets(const std::filesystem::path& currentWorkingDirectory) diff --git a/src/cascadia/TerminalSettingsModel/ActionMap.h b/src/cascadia/TerminalSettingsModel/ActionMap.h index 9ab7cef282a..e0001d8186c 100644 --- a/src/cascadia/TerminalSettingsModel/ActionMap.h +++ b/src/cascadia/TerminalSettingsModel/ActionMap.h @@ -16,6 +16,7 @@ Author(s): #pragma once #include "ActionMap.g.h" +#include "ActionArgFactory.g.h" #include "IInheritable.h" #include "Command.h" @@ -47,6 +48,16 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation } }; + struct ActionArgFactory + { + ActionArgFactory() = default; + + static winrt::hstring GetNameForAction(ShortcutAction action); + static winrt::hstring GetNameForAction(ShortcutAction action, Windows::ApplicationModel::Resources::Core::ResourceContext context); + static Windows::Foundation::Collections::IMap AvailableShortcutActionsAndNames(); + static Model::IActionArgs GetEmptyArgsForAction(Model::ShortcutAction shortcutAction); + }; + struct ActionMap : ActionMapT, IInheritable { void _FinalizeInheritance() override; @@ -56,6 +67,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation Windows::Foundation::Collections::IMapView NameMap(); Windows::Foundation::Collections::IMapView GlobalHotkeys(); Windows::Foundation::Collections::IMapView KeyBindings(); + Windows::Foundation::Collections::IVectorView AllCommands(); com_ptr Copy() const; // queries @@ -63,6 +75,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation Model::Command GetActionByID(const winrt::hstring& cmdID) const; bool IsKeyChordExplicitlyUnbound(const Control::KeyChord& keys) const; Control::KeyChord GetKeyBindingForAction(const winrt::hstring& cmdID); + Windows::Foundation::Collections::IVector AllKeyBindingsForAction(const winrt::hstring& cmdID); // population void AddAction(const Model::Command& cmd, const Control::KeyChord& keys); @@ -78,8 +91,11 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation // modification bool RebindKeys(const Control::KeyChord& oldKeys, const Control::KeyChord& newKeys); void DeleteKeyBinding(const Control::KeyChord& keys); + void AddKeyBinding(Control::KeyChord keys, const winrt::hstring& cmdID); void RegisterKeyBinding(Control::KeyChord keys, Model::ActionAndArgs action); + void DeleteUserCommand(const winrt::hstring& cmdID); void AddSendInputAction(winrt::hstring name, winrt::hstring input, const Control::KeyChord keys); + void UpdateCommandID(const Model::Command& cmd, winrt::hstring newID); Windows::Foundation::Collections::IVector ExpandedCommands(); void ExpandCommands(const Windows::Foundation::Collections::IVectorView& profiles, @@ -138,6 +154,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation // This is effectively a combination of _CumulativeKeyMapCache and _CumulativeActionMapCache and its purpose is so that // we can give the SUI a view of the key chords and the commands they map to Windows::Foundation::Collections::IMap _ResolvedKeyToActionMapCache{ nullptr }; + Windows::Foundation::Collections::IVector _AllCommandsCache{ nullptr }; til::shared_mutex>> _cwdLocalSnippetsCache{}; @@ -148,3 +165,8 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation friend class SettingsModelUnitTests::TerminalSettingsTests; }; } + +namespace winrt::Microsoft::Terminal::Settings::Model::factory_implementation +{ + BASIC_FACTORY(ActionArgFactory); +} diff --git a/src/cascadia/TerminalSettingsModel/ActionMap.idl b/src/cascadia/TerminalSettingsModel/ActionMap.idl index 5c89a13cb96..097275def9d 100644 --- a/src/cascadia/TerminalSettingsModel/ActionMap.idl +++ b/src/cascadia/TerminalSettingsModel/ActionMap.idl @@ -6,6 +6,14 @@ import "ISettingsModelObject.idl"; namespace Microsoft.Terminal.Settings.Model { + static runtimeclass ActionArgFactory + { + static String GetNameForAction(Microsoft.Terminal.Settings.Model.ShortcutAction action); + static String GetNameForAction(Microsoft.Terminal.Settings.Model.ShortcutAction action, Windows.ApplicationModel.Resources.Core.ResourceContext context); + static Windows.Foundation.Collections.IMap AvailableShortcutActionsAndNames { get; }; + static IActionArgs GetEmptyArgsForAction(Microsoft.Terminal.Settings.Model.ShortcutAction shortcutAction); + } + // This interface ensures that no changes are made to ActionMap interface IActionMapView { @@ -14,12 +22,14 @@ namespace Microsoft.Terminal.Settings.Model Command GetActionByKeyChord(Microsoft.Terminal.Control.KeyChord keys); Command GetActionByID(String cmdID); Microsoft.Terminal.Control.KeyChord GetKeyBindingForAction(String cmdID); + IVector AllKeyBindingsForAction(String cmdID); Windows.Foundation.Collections.IMapView AvailableActions { get; }; Windows.Foundation.Collections.IMapView NameMap { get; }; Windows.Foundation.Collections.IMapView KeyBindings { get; }; Windows.Foundation.Collections.IMapView GlobalHotkeys { get; }; + Windows.Foundation.Collections.IVectorView AllCommands { get; }; IVector ExpandedCommands { get; }; @@ -28,9 +38,11 @@ namespace Microsoft.Terminal.Settings.Model runtimeclass ActionMap : IActionMapView { + void AddAction(Command cmd, Microsoft.Terminal.Control.KeyChord keys); void RebindKeys(Microsoft.Terminal.Control.KeyChord oldKeys, Microsoft.Terminal.Control.KeyChord newKeys); void DeleteKeyBinding(Microsoft.Terminal.Control.KeyChord keys); - + void DeleteUserCommand(String cmdID); + void AddKeyBinding(Microsoft.Terminal.Control.KeyChord keys, String cmdID); void RegisterKeyBinding(Microsoft.Terminal.Control.KeyChord keys, ActionAndArgs action); void AddSendInputAction(String name, String input, Microsoft.Terminal.Control.KeyChord keys); } diff --git a/src/cascadia/TerminalSettingsModel/CascadiaSettings.cpp b/src/cascadia/TerminalSettingsModel/CascadiaSettings.cpp index 4b0f1f83e16..ada39cea720 100644 --- a/src/cascadia/TerminalSettingsModel/CascadiaSettings.cpp +++ b/src/cascadia/TerminalSettingsModel/CascadiaSettings.cpp @@ -1258,3 +1258,8 @@ void CascadiaSettings::ExpandCommands() { _globals->ExpandCommands(ActiveProfiles().GetView(), GlobalSettings().ColorSchemes()); } + +void CascadiaSettings::UpdateCommandID(const Model::Command& cmd, winrt::hstring newID) +{ + _globals->UpdateCommandID(cmd, newID); +} diff --git a/src/cascadia/TerminalSettingsModel/CascadiaSettings.h b/src/cascadia/TerminalSettingsModel/CascadiaSettings.h index 5e235d62af2..dc927c32cec 100644 --- a/src/cascadia/TerminalSettingsModel/CascadiaSettings.h +++ b/src/cascadia/TerminalSettingsModel/CascadiaSettings.h @@ -191,6 +191,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation void CurrentDefaultTerminal(const Model::DefaultTerminal& terminal); void ExpandCommands(); + void UpdateCommandID(const Model::Command& cmd, winrt::hstring newID); void ResolveMediaResources() { _validateMediaResources(); } void LogSettingChanges(bool isJsonLoad) const; diff --git a/src/cascadia/TerminalSettingsModel/CascadiaSettings.idl b/src/cascadia/TerminalSettingsModel/CascadiaSettings.idl index 30730236524..cf6e258ddb5 100644 --- a/src/cascadia/TerminalSettingsModel/CascadiaSettings.idl +++ b/src/cascadia/TerminalSettingsModel/CascadiaSettings.idl @@ -64,6 +64,7 @@ namespace Microsoft.Terminal.Settings.Model DefaultTerminal CurrentDefaultTerminal; void ExpandCommands(); + void UpdateCommandID(Command cmd, String newID); void ResolveMediaResources(); } diff --git a/src/cascadia/TerminalSettingsModel/Command.cpp b/src/cascadia/TerminalSettingsModel/Command.cpp index 1e28f8cf457..ec032770454 100644 --- a/src/cascadia/TerminalSettingsModel/Command.cpp +++ b/src/cascadia/TerminalSettingsModel/Command.cpp @@ -84,6 +84,21 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation { Command::Command() = default; + Model::Command Command::NewUserCommand() + { + auto newCmd{ winrt::make_self() }; + newCmd->_Origin = OriginTag::User; + return *newCmd; + } + + Model::Command Command::CopyAsUserCommand(const Model::Command& originalCmd) + { + auto command{ winrt::get_self(originalCmd) }; + auto copy{ command->Copy() }; + copy->_Origin = OriginTag::User; + return *copy; + } + com_ptr Command::Copy() const { auto command{ winrt::make_self() }; @@ -197,6 +212,11 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation return hstring{ _ID }; } + void Command::ID(const hstring& ID) noexcept + { + _ID = ID; + } + void Command::GenerateID() { if (_ActionAndArgs) @@ -204,8 +224,8 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation auto actionAndArgsImpl{ winrt::get_self(_ActionAndArgs) }; if (const auto generatedID = actionAndArgsImpl->GenerateID(); !generatedID.empty()) { - _ID = generatedID; _IDWasGenerated = true; + ID(generatedID); } } } diff --git a/src/cascadia/TerminalSettingsModel/Command.h b/src/cascadia/TerminalSettingsModel/Command.h index de654e6960d..65dd0c9244d 100644 --- a/src/cascadia/TerminalSettingsModel/Command.h +++ b/src/cascadia/TerminalSettingsModel/Command.h @@ -51,6 +51,8 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation }; Command(); + static Model::Command NewUserCommand(); + static Model::Command CopyAsUserCommand(const Model::Command& originalCmd); com_ptr Copy() const; static winrt::com_ptr FromJson(const Json::Value& json, @@ -80,6 +82,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation hstring LanguageNeutralName() const noexcept; hstring ID() const noexcept; + void ID(const hstring& ID) noexcept; void GenerateID(); bool IDWasGenerated(); @@ -94,8 +97,8 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation bool directories, hstring iconPath); + WINRT_PROPERTY(Model::ActionAndArgs, ActionAndArgs, Model::ActionAndArgs{}); WINRT_PROPERTY(ExpandCommandType, IterateOn, ExpandCommandType::None); - WINRT_PROPERTY(Model::ActionAndArgs, ActionAndArgs); WINRT_PROPERTY(OriginTag, Origin); WINRT_PROPERTY(winrt::hstring, Description, L""); diff --git a/src/cascadia/TerminalSettingsModel/Command.idl b/src/cascadia/TerminalSettingsModel/Command.idl index cba4d68ea32..5722b4b9184 100644 --- a/src/cascadia/TerminalSettingsModel/Command.idl +++ b/src/cascadia/TerminalSettingsModel/Command.idl @@ -35,14 +35,18 @@ namespace Microsoft.Terminal.Settings.Model runtimeclass Command : ISettingsModelObject { Command(); + static Command NewUserCommand(); + static Command CopyAsUserCommand(Command originalCmd); - String Name { get; }; + String Name; + Boolean HasName(); String LanguageNeutralName { get; }; String ID { get; }; + void GenerateID(); String Description { get; }; - ActionAndArgs ActionAndArgs { get; }; + ActionAndArgs ActionAndArgs; IMediaResource Icon; @@ -51,6 +55,5 @@ namespace Microsoft.Terminal.Settings.Model static IVector ParsePowerShellMenuComplete(String json, Int32 replaceLength); static IVector HistoryToCommands(IVector commandHistory, String commandline, Boolean directories, String iconPath); - } } diff --git a/src/cascadia/TerminalSettingsModel/EnumMappings.cpp b/src/cascadia/TerminalSettingsModel/EnumMappings.cpp index 6f867db0b65..e6e5d25e74b 100644 --- a/src/cascadia/TerminalSettingsModel/EnumMappings.cpp +++ b/src/cascadia/TerminalSettingsModel/EnumMappings.cpp @@ -54,6 +54,22 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation DEFINE_ENUM_MAP(Microsoft::Terminal::Core::AdjustTextMode, AdjustIndistinguishableColors); DEFINE_ENUM_MAP(Microsoft::Terminal::Control::PathTranslationStyle, PathTranslationStyle); + // Actions + DEFINE_ENUM_MAP(Microsoft::Terminal::Settings::Model::ResizeDirection, ResizeDirection); + DEFINE_ENUM_MAP(Microsoft::Terminal::Settings::Model::FocusDirection, FocusDirection); + DEFINE_ENUM_MAP(Microsoft::Terminal::Settings::Model::SplitDirection, SplitDirection); + DEFINE_ENUM_MAP(Microsoft::Terminal::Settings::Model::SplitType, SplitType); + DEFINE_ENUM_MAP(Microsoft::Terminal::Settings::Model::SettingsTarget, SettingsTarget); + DEFINE_ENUM_MAP(Microsoft::Terminal::Settings::Model::MoveTabDirection, MoveTabDirection); + DEFINE_ENUM_MAP(Microsoft::Terminal::Control::ScrollToMarkDirection, ScrollToMarkDirection); + DEFINE_ENUM_MAP(Microsoft::Terminal::Settings::Model::CommandPaletteLaunchMode, CommandPaletteLaunchMode); + DEFINE_ENUM_MAP(Microsoft::Terminal::Settings::Model::SuggestionsSource, SuggestionsSource); + DEFINE_ENUM_MAP(Microsoft::Terminal::Settings::Model::FindMatchDirection, FindMatchDirection); + DEFINE_ENUM_MAP(Microsoft::Terminal::Settings::Model::DesktopBehavior, DesktopBehavior); + DEFINE_ENUM_MAP(Microsoft::Terminal::Settings::Model::MonitorBehavior, MonitorBehavior); + DEFINE_ENUM_MAP(Microsoft::Terminal::Control::ClearBufferType, ClearBufferType); + DEFINE_ENUM_MAP(Microsoft::Terminal::Settings::Model::SelectOutputDirection, SelectOutputDirection); + // FontWeight is special because the JsonUtils::ConversionTrait for it // creates a FontWeight object, but we need to use the uint16_t value. winrt::Windows::Foundation::Collections::IMap EnumMappings::FontWeight() diff --git a/src/cascadia/TerminalSettingsModel/EnumMappings.h b/src/cascadia/TerminalSettingsModel/EnumMappings.h index a3412185952..cca552546f4 100644 --- a/src/cascadia/TerminalSettingsModel/EnumMappings.h +++ b/src/cascadia/TerminalSettingsModel/EnumMappings.h @@ -50,6 +50,22 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation static winrt::Windows::Foundation::Collections::IMap IntenseTextStyle(); static winrt::Windows::Foundation::Collections::IMap AdjustIndistinguishableColors(); static winrt::Windows::Foundation::Collections::IMap PathTranslationStyle(); + + // Actions + static winrt::Windows::Foundation::Collections::IMap ResizeDirection(); + static winrt::Windows::Foundation::Collections::IMap FocusDirection(); + static winrt::Windows::Foundation::Collections::IMap SplitDirection(); + static winrt::Windows::Foundation::Collections::IMap SplitType(); + static winrt::Windows::Foundation::Collections::IMap SettingsTarget(); + static winrt::Windows::Foundation::Collections::IMap MoveTabDirection(); + static winrt::Windows::Foundation::Collections::IMap ScrollToMarkDirection(); + static winrt::Windows::Foundation::Collections::IMap CommandPaletteLaunchMode(); + static winrt::Windows::Foundation::Collections::IMap SuggestionsSource(); + static winrt::Windows::Foundation::Collections::IMap FindMatchDirection(); + static winrt::Windows::Foundation::Collections::IMap DesktopBehavior(); + static winrt::Windows::Foundation::Collections::IMap MonitorBehavior(); + static winrt::Windows::Foundation::Collections::IMap ClearBufferType(); + static winrt::Windows::Foundation::Collections::IMap SelectOutputDirection(); }; } diff --git a/src/cascadia/TerminalSettingsModel/EnumMappings.idl b/src/cascadia/TerminalSettingsModel/EnumMappings.idl index befb2cea5db..7b0ac90e1f6 100644 --- a/src/cascadia/TerminalSettingsModel/EnumMappings.idl +++ b/src/cascadia/TerminalSettingsModel/EnumMappings.idl @@ -32,5 +32,21 @@ namespace Microsoft.Terminal.Settings.Model static Windows.Foundation.Collections.IMap FontWeight { get; }; static Windows.Foundation.Collections.IMap IntenseTextStyle { get; }; static Windows.Foundation.Collections.IMap PathTranslationStyle { get; }; + + // Actions + static Windows.Foundation.Collections.IMap ResizeDirection { get; }; + static Windows.Foundation.Collections.IMap FocusDirection { get; }; + static Windows.Foundation.Collections.IMap SplitDirection { get; }; + static Windows.Foundation.Collections.IMap SplitType { get; }; + static Windows.Foundation.Collections.IMap SettingsTarget { get; }; + static Windows.Foundation.Collections.IMap MoveTabDirection { get; }; + static Windows.Foundation.Collections.IMap ScrollToMarkDirection { get; }; + static Windows.Foundation.Collections.IMap CommandPaletteLaunchMode { get; }; + static Windows.Foundation.Collections.IMap SuggestionsSource { get; }; + static Windows.Foundation.Collections.IMap FindMatchDirection { get; }; + static Windows.Foundation.Collections.IMap DesktopBehavior { get; }; + static Windows.Foundation.Collections.IMap MonitorBehavior { get; }; + static Windows.Foundation.Collections.IMap ClearBufferType { get; }; + static Windows.Foundation.Collections.IMap SelectOutputDirection { get; }; } } diff --git a/src/cascadia/TerminalSettingsModel/GlobalAppSettings.cpp b/src/cascadia/TerminalSettingsModel/GlobalAppSettings.cpp index d7c0e5a6a74..afb2a3f187e 100644 --- a/src/cascadia/TerminalSettingsModel/GlobalAppSettings.cpp +++ b/src/cascadia/TerminalSettingsModel/GlobalAppSettings.cpp @@ -459,6 +459,46 @@ void GlobalAppSettings::_logSettingSet(const std::string_view& setting) } } +void GlobalAppSettings::UpdateCommandID(const Model::Command& cmd, winrt::hstring newID) +{ + const auto oldID = cmd.ID(); + _actionMap->UpdateCommandID(cmd, newID); + // newID might have been empty when this function was called, if so actionMap would have generated a new ID, use that + newID = cmd.ID(); + if (_NewTabMenu) + { + // Recursive lambda function to look through all the new tab menu entries and update IDs accordingly + std::function recursiveEntryIdUpdate; + recursiveEntryIdUpdate = [&](const Model::NewTabMenuEntry& entry) { + if (entry.Type() == NewTabMenuEntryType::Action) + { + if (const auto actionEntry{ entry.try_as() }) + { + if (actionEntry.ActionId() == oldID) + { + actionEntry.ActionId(newID); + } + } + } + else if (entry.Type() == NewTabMenuEntryType::Folder) + { + if (const auto folderEntry{ entry.try_as() }) + { + for (const auto& nestedEntry : folderEntry.RawEntries()) + { + recursiveEntryIdUpdate(nestedEntry); + } + } + } + }; + + for (const auto& entry : *_NewTabMenu) + { + recursiveEntryIdUpdate(entry); + } + } +} + void GlobalAppSettings::_logSettingIfSet(const std::string_view& setting, const bool isSet) { if (isSet) diff --git a/src/cascadia/TerminalSettingsModel/GlobalAppSettings.h b/src/cascadia/TerminalSettingsModel/GlobalAppSettings.h index b2e1ccf23f0..58147fac442 100644 --- a/src/cascadia/TerminalSettingsModel/GlobalAppSettings.h +++ b/src/cascadia/TerminalSettingsModel/GlobalAppSettings.h @@ -47,6 +47,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation Model::ColorScheme DuplicateColorScheme(const Model::ColorScheme& scheme); Model::ActionMap ActionMap() const noexcept; + void UpdateCommandID(const Model::Command& cmd, winrt::hstring newID); static com_ptr FromJson(const Json::Value& json, const OriginTag origin = OriginTag::None); void LayerJson(const Json::Value& json, const OriginTag origin); diff --git a/src/cascadia/TerminalSettingsModel/Resources/en-US/Resources.resw b/src/cascadia/TerminalSettingsModel/Resources/en-US/Resources.resw index a0126304df7..16a129c61fd 100644 --- a/src/cascadia/TerminalSettingsModel/Resources/en-US/Resources.resw +++ b/src/cascadia/TerminalSettingsModel/Resources/en-US/Resources.resw @@ -415,7 +415,7 @@ Clear all marks - Send Input: "{0}" + Send input: "{0}" {0} will be replaced with a string of input as defined by the user @@ -740,6 +740,66 @@ Open current working directory + + Close tab + + + Send input + + + Set focus mode + + + Set full screen + + + Set maximized + + + Set color scheme + + + Close other tabs + + + Close tabs after + + + Move tab + + + Find match + + + Search for text + + + Focus pane + + + Export buffer + + + Clear buffer + + + Multiple actions + + + Adjust opacity + + + Select command + + + Select output + + + Suggestions + + + Color selection + WSL Distribution Profile Generator The display name of a dynamic profile generator for WSL distros @@ -760,4 +820,160 @@ SSH Host Profile Generator The display name of a dynamic profile generator for SSH hosts - \ No newline at end of file + + Dismiss Selection + + + Single Line + + + With Control Sequences + + + Copy Formatting + + + Tab Index + + + Window + + + Resize Direction + + + Focus Direction + + + Direction + + + Delta + + + Input + + + Target + + + Is Focus Mode + + + Is Maximized + + + Is Full Screen + + + Scheme Name + + + Tab Color + + + Title + + + Commandline + + + Index + + + Rows To Scroll + + + Color + + + Launch Mode + + + Name + + + Key Chord + + + Source + + + Use Commandline + + + Switcher Mode + + + Query URL + + + Desktop + + + Monitor + + + Toggle Visibility + + + Dropdown Duration + + + Id + + + Path + + + Clear + + + Opacity + + + Relative + + + Foreground + + + Background + + + Match Mode + + + Starting Directory + + + Tab Title + + + Profile Index + + + Profile + + + Suppress Application Title + + + Color Scheme + + + Elevate + + + Reload Environment Variables + + + Split Direction + + + Split Mode + + + Split Size + +