terminal/src/cascadia/TerminalSettingsModel/ActionArgs.cpp
2021-11-24 02:50:24 +01:00

727 lines
22 KiB
C++

// 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 "MovePaneArgs.g.cpp"
#include "SwapPaneArgs.g.cpp"
#include "AdjustFontSizeArgs.g.cpp"
#include "SendInputArgs.g.cpp"
#include "SplitPaneArgs.g.cpp"
#include "OpenSettingsArgs.g.cpp"
#include "SetColorSchemeArgs.g.cpp"
#include "SetTabColorArgs.g.cpp"
#include "RenameTabArgs.g.cpp"
#include "ExecuteCommandlineArgs.g.cpp"
#include "CloseOtherTabsArgs.g.cpp"
#include "CloseTabsAfterArgs.g.cpp"
#include "CloseTabArgs.g.cpp"
#include "MoveTabArgs.g.cpp"
#include "FindMatchArgs.g.cpp"
#include "ToggleCommandPaletteArgs.g.cpp"
#include "NewWindowArgs.g.cpp"
#include "PrevTabArgs.g.cpp"
#include "NextTabArgs.g.cpp"
#include "RenameWindowArgs.g.cpp"
#include "GlobalSummonArgs.g.cpp"
#include "FocusPaneArgs.g.cpp"
#include "ClearBufferArgs.g.cpp"
#include "MultipleActionsArgs.g.cpp"
#include <LibraryResources.h>
#include <WtExeUtils.h>
#include "TerminalSettingsSerializationHelpers.h"
#include "JsonUtils.h"
using namespace winrt::Microsoft::Terminal::Control;
namespace winrt::Microsoft::Terminal::Settings::Model::implementation
{
winrt::hstring NewTerminalArgs::GenerateName() const
{
std::wstringstream ss;
if (!Profile().empty())
{
ss << fmt::format(L"profile: {}, ", Profile());
}
else if (ProfileIndex())
{
ss << fmt::format(L"profile index: {}, ", ProfileIndex().Value());
}
if (!Commandline().empty())
{
ss << fmt::format(L"commandline: {}, ", Commandline());
}
if (!StartingDirectory().empty())
{
ss << fmt::format(L"directory: {}, ", StartingDirectory());
}
if (!TabTitle().empty())
{
ss << fmt::format(L"title: {}, ", TabTitle());
}
if (TabColor())
{
const til::color tabColor{ TabColor().Value() };
ss << fmt::format(L"tabColor: {}, ", tabColor.ToHexString(true));
}
if (!ColorScheme().empty())
{
ss << fmt::format(L"colorScheme: {}, ", ColorScheme());
}
if (SuppressApplicationTitle())
{
if (SuppressApplicationTitle().Value())
{
ss << fmt::format(L"suppress application title, ");
}
else
{
ss << fmt::format(L"use application title, ");
}
}
auto s = ss.str();
if (s.empty())
{
return L"";
}
// Chop off the last ", "
return winrt::hstring{ s.substr(0, s.size() - 2) };
}
winrt::hstring NewTerminalArgs::ToCommandline() const
{
std::wstringstream ss;
if (!Profile().empty())
{
ss << fmt::format(L"--profile \"{}\" ", Profile());
}
// The caller is always expected to provide the evaluated profile in the
// NewTerminalArgs, not the index
//
// else if (ProfileIndex())
// {
// ss << fmt::format(L"profile index: {}, ", ProfileIndex().Value());
// }
if (!StartingDirectory().empty())
{
ss << fmt::format(L"--startingDirectory {} ", QuoteAndEscapeCommandlineArg(StartingDirectory()));
}
if (!TabTitle().empty())
{
ss << fmt::format(L"--title {} ", QuoteAndEscapeCommandlineArg(TabTitle()));
}
if (TabColor())
{
const til::color tabColor{ TabColor().Value() };
ss << fmt::format(L"--tabColor \"{}\" ", tabColor.ToHexString(true));
}
if (SuppressApplicationTitle())
{
if (SuppressApplicationTitle().Value())
{
ss << fmt::format(L"--suppressApplicationTitle ");
}
else
{
ss << fmt::format(L"--useApplicationTitle ");
}
}
if (!ColorScheme().empty())
{
ss << fmt::format(L"--colorScheme {} ", QuoteAndEscapeCommandlineArg(ColorScheme()));
}
if (!Commandline().empty())
{
ss << fmt::format(L"-- \"{}\" ", Commandline());
}
auto s = ss.str();
if (s.empty())
{
return L"";
}
// Chop off the last " "
return winrt::hstring{ s.substr(0, s.size() - 1) };
}
winrt::hstring CopyTextArgs::GenerateName() const
{
std::wstringstream ss;
if (SingleLine())
{
ss << RS_(L"CopyTextAsSingleLineCommandKey").c_str();
}
else
{
ss << RS_(L"CopyTextCommandKey").c_str();
}
if (CopyFormatting())
{
ss << L", copyFormatting: ";
if (CopyFormatting().Value() == CopyFormat::All)
{
ss << L"all, ";
}
else if (CopyFormatting().Value() == static_cast<CopyFormat>(0))
{
ss << L"none, ";
}
else
{
if (WI_IsFlagSet(CopyFormatting().Value(), CopyFormat::HTML))
{
ss << L"html, ";
}
if (WI_IsFlagSet(CopyFormatting().Value(), CopyFormat::RTF))
{
ss << L"rtf, ";
}
}
// Chop off the last ","
auto result = ss.str();
return winrt::hstring{ result.substr(0, result.size() - 2) };
}
return winrt::hstring{ ss.str() };
}
winrt::hstring NewTabArgs::GenerateName() const
{
winrt::hstring newTerminalArgsStr;
if (TerminalArgs())
{
newTerminalArgsStr = TerminalArgs().GenerateName();
}
if (newTerminalArgsStr.empty())
{
return RS_(L"NewTabCommandKey");
}
return winrt::hstring{
fmt::format(L"{}, {}", RS_(L"NewTabCommandKey"), newTerminalArgsStr)
};
}
winrt::hstring MovePaneArgs::GenerateName() const
{
return winrt::hstring{
fmt::format(L"{}, tab index:{}", RS_(L"MovePaneCommandKey"), TabIndex())
};
}
winrt::hstring SwitchToTabArgs::GenerateName() const
{
if (TabIndex() == UINT32_MAX)
{
return RS_(L"SwitchToLastTabCommandKey");
}
return winrt::hstring{
fmt::format(L"{}, index:{}", RS_(L"SwitchToTabCommandKey"), TabIndex())
};
}
winrt::hstring ResizePaneArgs::GenerateName() const
{
winrt::hstring directionString;
switch (ResizeDirection())
{
case ResizeDirection::Left:
directionString = RS_(L"DirectionLeft");
break;
case ResizeDirection::Right:
directionString = RS_(L"DirectionRight");
break;
case ResizeDirection::Up:
directionString = RS_(L"DirectionUp");
break;
case ResizeDirection::Down:
directionString = RS_(L"DirectionDown");
break;
}
return winrt::hstring{
fmt::format(std::wstring_view(RS_(L"ResizePaneWithArgCommandKey")),
directionString)
};
}
winrt::hstring MoveFocusArgs::GenerateName() const
{
winrt::hstring directionString;
switch (FocusDirection())
{
case FocusDirection::Left:
directionString = RS_(L"DirectionLeft");
break;
case FocusDirection::Right:
directionString = RS_(L"DirectionRight");
break;
case FocusDirection::Up:
directionString = RS_(L"DirectionUp");
break;
case FocusDirection::Down:
directionString = RS_(L"DirectionDown");
break;
case FocusDirection::Previous:
return RS_(L"MoveFocusToLastUsedPane");
case FocusDirection::NextInOrder:
return RS_(L"MoveFocusNextInOrder");
case FocusDirection::PreviousInOrder:
return RS_(L"MoveFocusPreviousInOrder");
case FocusDirection::First:
return RS_(L"MoveFocusFirstPane");
case FocusDirection::Parent:
return RS_(L"MoveFocusParentPane");
case FocusDirection::Child:
return RS_(L"MoveFocusChildPane");
}
return winrt::hstring{
fmt::format(std::wstring_view(RS_(L"MoveFocusWithArgCommandKey")),
directionString)
};
}
winrt::hstring SwapPaneArgs::GenerateName() const
{
winrt::hstring directionString;
switch (Direction())
{
case FocusDirection::Left:
directionString = RS_(L"DirectionLeft");
break;
case FocusDirection::Right:
directionString = RS_(L"DirectionRight");
break;
case FocusDirection::Up:
directionString = RS_(L"DirectionUp");
break;
case FocusDirection::Down:
directionString = RS_(L"DirectionDown");
break;
case FocusDirection::Previous:
return RS_(L"SwapPaneToLastUsedPane");
case FocusDirection::NextInOrder:
return RS_(L"SwapPaneNextInOrder");
case FocusDirection::PreviousInOrder:
return RS_(L"SwapPanePreviousInOrder");
case FocusDirection::First:
return RS_(L"SwapPaneFirstPane");
}
return winrt::hstring{
fmt::format(std::wstring_view(RS_(L"SwapPaneWithArgCommandKey")),
directionString)
};
}
winrt::hstring AdjustFontSizeArgs::GenerateName() const
{
// If the amount is just 1 (or -1), we'll just return "Increase font
// size" (or "Decrease font size"). If the amount delta has a greater
// absolute value, we'll include it like"
// * Decrease font size, amount: {delta}"
if (Delta() < 0)
{
return Delta() == -1 ? RS_(L"DecreaseFontSizeCommandKey") :
winrt::hstring{
fmt::format(std::wstring_view(RS_(L"DecreaseFontSizeWithAmountCommandKey")),
-Delta())
};
}
else
{
return Delta() == 1 ? RS_(L"IncreaseFontSizeCommandKey") :
winrt::hstring{
fmt::format(std::wstring_view(RS_(L"IncreaseFontSizeWithAmountCommandKey")),
Delta())
};
}
}
winrt::hstring SendInputArgs::GenerateName() const
{
// The string will be similar to the following:
// * "Send Input: ...input..."
auto escapedInput = til::visualize_control_codes(Input());
auto name = fmt::format(std::wstring_view(RS_(L"SendInputCommandKey")), escapedInput);
return winrt::hstring{ name };
}
winrt::hstring SplitPaneArgs::GenerateName() const
{
// The string will be similar to the following:
// * "Duplicate pane[, split: <direction>][, size: <size>%][, new terminal arguments...]"
// * "Split pane[, split: <direction>][, size: <size>%][, new terminal arguments...]"
//
// Direction will only be added to the string if the split direction is
// not "auto".
// If this is a "duplicate pane" action, then the new terminal arguments
// will be omitted (as they're unused)
std::wstringstream ss;
if (SplitMode() == SplitType::Duplicate)
{
ss << std::wstring_view(RS_(L"DuplicatePaneCommandKey"));
}
else
{
ss << std::wstring_view(RS_(L"SplitPaneCommandKey"));
}
ss << L", ";
// This text is intentionally _not_ localized, to attempt to mirror the
// exact syntax that the property would have in JSON.
switch (SplitDirection())
{
case SplitDirection::Up:
ss << L"split: up, ";
break;
case SplitDirection::Right:
ss << L"split: right, ";
break;
case SplitDirection::Down:
ss << L"split: down, ";
break;
case SplitDirection::Left:
ss << L"split: left, ";
break;
}
if (SplitSize() != .5f)
{
ss << L"size: " << (SplitSize() * 100) << L"%, ";
}
winrt::hstring newTerminalArgsStr;
if (TerminalArgs())
{
newTerminalArgsStr = TerminalArgs().GenerateName();
}
if (SplitMode() != SplitType::Duplicate && !newTerminalArgsStr.empty())
{
ss << newTerminalArgsStr.c_str();
ss << L", ";
}
// Chop off the last ", "
auto s = ss.str();
return winrt::hstring{ s.substr(0, s.size() - 2) };
}
winrt::hstring OpenSettingsArgs::GenerateName() const
{
switch (Target())
{
case SettingsTarget::DefaultsFile:
return RS_(L"OpenDefaultSettingsCommandKey");
case SettingsTarget::AllFiles:
return RS_(L"OpenBothSettingsFilesCommandKey");
case SettingsTarget::SettingsFile:
return RS_(L"OpenSettingsCommandKey");
case SettingsTarget::SettingsUI:
default:
return RS_(L"OpenSettingsUICommandKey");
}
}
winrt::hstring SetColorSchemeArgs::GenerateName() const
{
// "Set color scheme to "{_SchemeName}""
if (!SchemeName().empty())
{
return winrt::hstring{
fmt::format(std::wstring_view(RS_(L"SetColorSchemeCommandKey")),
SchemeName().c_str())
};
}
return L"";
}
winrt::hstring SetTabColorArgs::GenerateName() const
{
// "Set tab color to #RRGGBB"
// "Reset tab color"
if (TabColor())
{
til::color tabColor{ TabColor().Value() };
return winrt::hstring{
fmt::format(std::wstring_view(RS_(L"SetTabColorCommandKey")),
tabColor.ToHexString(true))
};
}
return RS_(L"ResetTabColorCommandKey");
}
winrt::hstring RenameTabArgs::GenerateName() const
{
// "Rename tab to \"{_Title}\""
// "Reset tab title"
if (!Title().empty())
{
return winrt::hstring{
fmt::format(std::wstring_view(RS_(L"RenameTabCommandKey")),
Title().c_str())
};
}
return RS_(L"ResetTabNameCommandKey");
}
winrt::hstring ExecuteCommandlineArgs::GenerateName() const
{
// "Run commandline "{_Commandline}" in this window"
if (!Commandline().empty())
{
return winrt::hstring{
fmt::format(std::wstring_view(RS_(L"ExecuteCommandlineCommandKey")),
Commandline().c_str())
};
}
return L"";
}
winrt::hstring CloseOtherTabsArgs::GenerateName() const
{
if (Index())
{
// "Close tabs other than index {0}"
return winrt::hstring{
fmt::format(std::wstring_view(RS_(L"CloseOtherTabsCommandKey")),
Index().Value())
};
}
return RS_(L"CloseOtherTabsDefaultCommandKey");
}
winrt::hstring CloseTabsAfterArgs::GenerateName() const
{
if (Index())
{
// "Close tabs after index {0}"
return winrt::hstring{
fmt::format(std::wstring_view(RS_(L"CloseTabsAfterCommandKey")),
Index().Value())
};
}
return RS_(L"CloseTabsAfterDefaultCommandKey");
}
winrt::hstring CloseTabArgs::GenerateName() const
{
if (Index())
{
// "Close tab at index {0}"
return winrt::hstring{
fmt::format(std::wstring_view(RS_(L"CloseTabAtIndexCommandKey")),
Index().Value())
};
}
return RS_(L"CloseTabCommandKey");
}
winrt::hstring ScrollUpArgs::GenerateName() const
{
if (RowsToScroll())
{
return winrt::hstring{
fmt::format(std::wstring_view(RS_(L"ScrollUpSeveralRowsCommandKey")),
RowsToScroll().Value())
};
}
return RS_(L"ScrollUpCommandKey");
}
winrt::hstring ScrollDownArgs::GenerateName() const
{
if (RowsToScroll())
{
return winrt::hstring{
fmt::format(std::wstring_view(RS_(L"ScrollDownSeveralRowsCommandKey")),
RowsToScroll().Value())
};
}
return RS_(L"ScrollDownCommandKey");
}
winrt::hstring MoveTabArgs::GenerateName() const
{
winrt::hstring directionString;
switch (Direction())
{
case MoveTabDirection::Forward:
directionString = RS_(L"MoveTabDirectionForward");
break;
case MoveTabDirection::Backward:
directionString = RS_(L"MoveTabDirectionBackward");
break;
}
return winrt::hstring{
fmt::format(std::wstring_view(RS_(L"MoveTabCommandKey")),
directionString)
};
}
winrt::hstring ToggleCommandPaletteArgs::GenerateName() const
{
if (LaunchMode() == CommandPaletteLaunchMode::CommandLine)
{
return RS_(L"ToggleCommandPaletteCommandLineModeCommandKey");
}
return RS_(L"ToggleCommandPaletteCommandKey");
}
winrt::hstring FindMatchArgs::GenerateName() const
{
switch (Direction())
{
case FindMatchDirection::Next:
return winrt::hstring{ RS_(L"FindNextCommandKey") };
case FindMatchDirection::Previous:
return winrt::hstring{ RS_(L"FindPrevCommandKey") };
}
return L"";
}
winrt::hstring NewWindowArgs::GenerateName() const
{
winrt::hstring newTerminalArgsStr;
if (TerminalArgs())
{
newTerminalArgsStr = TerminalArgs().GenerateName();
}
if (newTerminalArgsStr.empty())
{
return RS_(L"NewWindowCommandKey");
}
return winrt::hstring{
fmt::format(L"{}, {}", RS_(L"NewWindowCommandKey"), newTerminalArgsStr)
};
}
winrt::hstring PrevTabArgs::GenerateName() const
{
if (!SwitcherMode())
{
return RS_(L"PrevTabCommandKey");
}
const auto mode = SwitcherMode().Value() == TabSwitcherMode::MostRecentlyUsed ? L"most recently used" : L"in order";
return winrt::hstring(fmt::format(L"{}, {}", RS_(L"PrevTabCommandKey"), mode));
}
winrt::hstring NextTabArgs::GenerateName() const
{
if (!SwitcherMode())
{
return RS_(L"NextTabCommandKey");
}
const auto mode = SwitcherMode().Value() == TabSwitcherMode::MostRecentlyUsed ? L"most recently used" : L"in order";
return winrt::hstring(fmt::format(L"{}, {}", RS_(L"NextTabCommandKey"), mode));
}
winrt::hstring RenameWindowArgs::GenerateName() const
{
// "Rename window to \"{_Name}\""
// "Clear window name"
if (!Name().empty())
{
return winrt::hstring{
fmt::format(std::wstring_view(RS_(L"RenameWindowCommandKey")),
Name().c_str())
};
}
return RS_(L"ResetWindowNameCommandKey");
}
winrt::hstring GlobalSummonArgs::GenerateName() const
{
// GH#10210 - Is this action literally the same thing as the `quakeMode`
// action? That has a special name.
static const auto quakeModeArgs{ std::get<0>(GlobalSummonArgs::QuakeModeFromJson(Json::Value::null)) };
if (quakeModeArgs.Equals(*this))
{
return RS_(L"QuakeModeCommandKey");
}
std::wstringstream ss;
ss << std::wstring_view(RS_(L"GlobalSummonCommandKey"));
// "Summon the Terminal window"
// "Summon the Terminal window, name:\"{_Name}\""
if (!Name().empty())
{
ss << L", name: ";
ss << std::wstring_view(Name());
}
return winrt::hstring{ ss.str() };
}
winrt::hstring FocusPaneArgs::GenerateName() const
{
// "Focus pane {Id}"
return winrt::hstring{
fmt::format(std::wstring_view(RS_(L"FocusPaneCommandKey")),
Id())
};
}
winrt::hstring ClearBufferArgs::GenerateName() const
{
// "Clear Buffer"
// "Clear Viewport"
// "Clear Scrollback"
switch (Clear())
{
case Control::ClearBufferType::All:
return RS_(L"ClearAllCommandKey");
case Control::ClearBufferType::Screen:
return RS_(L"ClearViewportCommandKey");
case Control::ClearBufferType::Scrollback:
return RS_(L"ClearScrollbackCommandKey");
}
// Return the empty string - the Clear() should be one of these values
return winrt::hstring{ L"" };
}
winrt::hstring MultipleActionsArgs::GenerateName() const
{
return L"";
}
}