terminal/src/cascadia/TerminalSettingsModel/ActionArgs.cpp

538 lines
16 KiB
C++
Raw Normal View History

// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#include "pch.h"
#include "ActionArgs.h"
#include "ActionEventArgs.g.cpp"
Add support for new panes with specifc profiles and other settings overrides (#3825) ## Summary of the Pull Request This enables the user to set a number of extra settings in the `NewTab` and `SplitPane` `ShortcutAction`s, that enable customizing how a new terminal is created at runtime. The following four properties were added: * `profile` * `commandline` * `tabTitle` * `startingDirectory` `profile` can be used with either a GUID or the name of a profile, and the action will launch that profile instead of the default. `commandline`, `tabTitle`, and `startingDirectory` can all be used to override the profile's values of those settings. This will be more useful for #607. With this PR, you can make bindings like the following: ```json { "keys": ["ctrl+a"], "command": { "action": "splitPane", "split": "vertical" } }, { "keys": ["ctrl+b"], "command": { "action": "splitPane", "split": "vertical", "profile": "{6239a42c-1111-49a3-80bd-e8fdd045185c}" } }, { "keys": ["ctrl+c"], "command": { "action": "splitPane", "split": "vertical", "profile": "profile1" } }, { "keys": ["ctrl+d"], "command": { "action": "splitPane", "split": "vertical", "profile": "profile2" } }, { "keys": ["ctrl+e"], "command": { "action": "splitPane", "split": "horizontal", "commandline": "foo.exe" } }, { "keys": ["ctrl+f"], "command": { "action": "splitPane", "split": "horizontal", "profile": "profile1", "commandline": "foo.exe" } }, { "keys": ["ctrl+g"], "command": { "action": "newTab" } }, { "keys": ["ctrl+h"], "command": { "action": "newTab", "startingDirectory": "c:\\foo" } }, { "keys": ["ctrl+i"], "command": { "action": "newTab", "profile": "profile2", "startingDirectory": "c:\\foo" } }, { "keys": ["ctrl+j"], "command": { "action": "newTab", "tabTitle": "bar" } }, { "keys": ["ctrl+k"], "command": { "action": "newTab", "profile": "profile2", "tabTitle": "bar" } }, { "keys": ["ctrl+l"], "command": { "action": "newTab", "profile": "profile1", "tabTitle": "bar", "startingDirectory": "c:\\foo", "commandline":"foo.exe" } } ``` ## References This is a lot of work that was largely started in pursuit of #607. We want people to be able to override these properties straight from the commandline. While they may not make as much sense as keybindings like this, they'll make more sense as commandline arguments. ## PR Checklist * [x] Closes #998 * [x] I work here * [x] Tests added/passed * [x] Requires documentation to be updated ## Validation Steps Performed There are tests 🎉 Manually added some bindings, they opened the correct profiles in panes/tabs
2019-12-09 14:02:29 +01:00
#include "NewTerminalArgs.g.cpp"
#include "CopyTextArgs.g.cpp"
Add support for arbitrary args in keybindings (#3391) ## Summary of the Pull Request Enables the user to provide arbitrary argument values to shortcut actions through a new `args` member of keybindings. For some keybindings, like `NewTabWithProfile<N>`, we previously needed 9 different `ShortcutAction`s, one for each value of `Index`. If a user wanted to have a `NewTabWithProfile11` keybinding, that was simply impossible. Now that the args are in their own separate json object, each binding can accept any number of arbitrary argument values. So instead of: ```json { "command": "newTab", "keys": ["ctrl+shift+t"] }, { "command": "newTabProfile0", "keys": ["ctrl+shift+1"] }, { "command": "newTabProfile1", "keys": ["ctrl+shift+2"] }, { "command": "newTabProfile2", "keys": ["ctrl+shift+3"] }, { "command": "newTabProfile3", "keys": ["ctrl+shift+4"] }, ``` We can now use: ```json { "command": "newTab", "keys": ["ctrl+shift+t"] }, { "command": { "action": "newTab", "index": 0 }, "keys": ["ctrl+shift+1"] }, { "command": { "action": "newTab", "index": 1 }, "keys": ["ctrl+shift+2"] }, { "command": { "action": "newTab", "index": 2 }, "keys": ["ctrl+shift+3"] }, ``` Initially, this does seem more verbose. However, for cases where there are multiple args, or there's a large range of values for the args, this will quickly become a more powerful system of expressing keybindings. The "legacy" keybindings are _left in_ in this PR. They have helper methods to generate appropriate `IActionArgs` values. Prior to releasing 1.0, I think we should remove them, if only to remove some code bloat. ## References See [the spec](https://github.com/microsoft/terminal/blob/master/doc/specs/%231142%20-%20Keybinding%20Arguments.md) for more details. This is part two of the implementation, part one was #2446 ## PR Checklist * [x] Closes #1142 * [x] I work here * [x] Tests added/passed * [x] Schema updated ## Validation Steps Performed * Ran Tests * Removed the legacy keybindings from the `defaults.json`, everything still works * Tried leaving the legacy keybingings in my `profiles.json`, everything still works. ------------------------------------------------- * this is a start, but there's a weird linker bug if I take the SetKeybinding(ShortcutAction, KeyChord) implementation out, which I don't totally understand * a good old-fashioned clean will fix that right up * all these things work * hey this actually _functionally_ works * Mostly cleanup and completion of implementation * Hey I bet we could just make NewTab the handler for NewTabWithProfile * Start writing tests for Keybinding args * Add tests * Revert a bad sln change, and clean out dead code * Change to include "command" as a single object This is a change to make @dhowett-msft happy. Changes the args to be a part of the "command" object, as opposed to an object on their own. EX: ```jsonc // Old style { "command": "switchToTab0", "keys": ["ctrl+1"] }, { "command": { "action": "switchToTab", "index": 0 }, "keys": ["ctrl+alt+1"] }, // new style { "command": "switchToTab0", "keys": ["ctrl+1"] }, { "command": "switchToTab", "args": { "index": 0 } "keys": ["ctrl+alt+1"] }, ``` * schemas are hard yo * Fix the build? * wonder why my -Wall settings are different than CI... * this makes me hate things * Comments from PR * Add a `Direction::None` * LOAD BEARING * add some GH ids to TODOs * add a comment * PR nits from carlos
2019-11-14 23:23:40 +01:00
#include "NewTabArgs.g.cpp"
#include "SwitchToTabArgs.g.cpp"
#include "ResizePaneArgs.g.cpp"
#include "MoveFocusArgs.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"
Add support for running a `wt` commandline in the curent window WITH A KEYBINDING (#6537) ## Summary of the Pull Request Adds a execute commandline action (`wt`), which lets a user bind a key to a specific `wt` commandline. This commandline will get parsed and run _in the current window_. ## References * Related to #4472 * Related to #5400 - I need this for the commandline mode of the Command Palette * Related to #5970 ## PR Checklist * [x] Closes oh, there's not actually an issue for this. * [x] I work here * [x] Tests added/passed * [ ] Requires documentation to be updated - yes it does ## Detailed Description of the Pull Request / Additional comments One important part of this change concerns how panes are initialized at runtime. We've had some persistent trouble with initializing multiple panes, because they rely on knowing how big they'll actually be, to be able to determine if they can split again. We previously worked around this by ignoring the size check when we were in "startup", processing an initial commandline. This PR however requires us to be able to know the initial size of a pane at runtime, but before the parents have necessarily been added to the tree, or had their renderer's set up. This led to the development of `Pane::PreCalculateCanSplit`, which is very highly similar to `Pane::PreCalculateAutoSplit`. This method attempts to figure out how big a pane _will_ take, before the parent has necessarily laid out. This also involves a small change to `TermControl`, because if its renderer hasn't been set up yet, it'll always think the font is `{0, fontHeight}`, which will let the Terminal keep splitting in the x direction. This change also makes the TermControl set up a renderer to get the real font size when it hasn't yet been initialized. ## Validation Steps Performed This was what the json blob I was using for testing evolved into ```json { "command": { "action":"wt", "commandline": "new-tab cmd.exe /k #work 15 ; split-pane cmd.exe /k #work 15 ; split-pane cmd.exe /k media-commandline ; new-tab powershell dev\\symbols.ps1 ; new-tab -p \"Ubuntu\" ; new-tab -p \"haunter.gif\" ; focus-tab -t 0", }, "keys": ["ctrl+shift+n"] } ``` I also added some tests. # TODO * [x] Creating a `{ "command": "wt" }` action without a commandline will spawn a new `wt.exe` process? - Probably should just do nothing for the empty string
2020-07-17 23:05:29 +02:00
#include "ExecuteCommandlineArgs.g.cpp"
Add Close... option to Tab context menu (#7728) <!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? --> ## Summary of the Pull Request Add a "Close..." option to the tab context menu, with nested entries to close tabs to the right and close other tabs (actions already available) ![immagine](https://user-images.githubusercontent.com/1140981/94178005-c7e03600-fe9a-11ea-9f87-c6f4895d4cf3.png) <!-- Other than the issue solved, is this relevant to any other issues/existing PRs? --> ## References #1912 <!-- Please review the items on the PR checklist before submitting--> ## PR Checklist * [x] Closes #5524 * [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA * [ ] Tests added/passed * [ ] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx * [ ] Schema updated. * [ ] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #xxx <!-- Provide a more detailed description of the PR, other things fixed or any additional comments/features here --> ## Detailed Description of the Pull Request / Additional comments First contribution :slightly_smiling_face: Tried to follow some suggestions from https://github.com/microsoft/terminal/issues/1912#issuecomment-667079311 <!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well --> ## Validation Steps Performed
2020-10-15 13:40:44 +02:00
#include "CloseOtherTabsArgs.g.cpp"
#include "CloseTabsAfterArgs.g.cpp"
#include "MoveTabArgs.g.cpp"
#include "FindMatchArgs.g.cpp"
#include "ToggleCommandPaletteArgs.g.cpp"
#include "NewWindowArgs.g.cpp"
#include <LibraryResources.h>
Rename `Microsoft.Terminal.TerminalControl` to `.Control`; Split into dll & lib (#9472) **BE NOT AFRAID**. I know that there's 107 files in this PR, but almost all of it is just find/replacing `TerminalControl` with `Control`. This is the start of the work to move TermControl into multiple pieces, for #5000. The PR starts this work by: * Splits `TerminalControl` into separate lib and dll projects. We'll want control tests in the future, and for that, we'll need a lib. * Moves `ICoreSettings` back into the `Microsoft.Terminal.Core` namespace. We'll have other types in there soon too. * I could not tell you why this works suddenly. New VS versions? New cppwinrt version? Maybe we're just better at dealing with mdmerge bugs these days. * RENAMES `Microsoft.Terminal.TerminalControl` to `Microsoft.Terminal.Control`. This touches pretty much every file in the sln. Sorry about that (not sorry). An upcoming PR will move much of the logic in TermControl into a new `ControlCore` class that we'll add in `Microsoft.Terminal.Core`. `ControlCore` will then be unittest-able in the `UnitTests_TerminalCore`, which will help prevent regressions like #9455 ## Detailed Description of the Pull Request / Additional comments You're really gonna want to clean the sln first, then merge this into your branch, then rebuild. It's very likely that old winmds will get left behind. If you see something like ``` Error MDM2007 Cannot create type Microsoft.Terminal.TerminalControl.KeyModifiers in read-only metadata file Microsoft.Terminal.TerminalControl. ``` then that's what happened to you.
2021-03-17 21:47:24 +01:00
using namespace winrt::Microsoft::Terminal::Control;
Introduce TerminalSettingsModel project (#7667) Introduces a new TerminalSettingsModel (TSM) project. This project is responsible for (de)serializing and exposing Windows Terminal's settings as WinRT objects. ## References #885: TSM epic #1564: Settings UI is dependent on this for data binding and settings access #6904: TSM Spec In the process of ripping out TSM from TerminalApp, a few other changes were made to make this possible: 1. AppLogic's `ApplicationDisplayName` and `ApplicationVersion` was moved to `CascadiaSettings` - These are defined as static functions. They also no longer check if `AppLogic::Current()` is nullptr. 2. `enum LaunchMode` was moved from TerminalApp to TSM 3. `AzureConnectionType` and `TelnetConnectionType` were moved from the profile generators to their respective TerminalConnections 4. CascadiaSettings' `SettingsPath` and `DefaultSettingsPath` are exposed as `hstring` instead of `std::filesystem::path` 5. `Command::ExpandCommands()` was exposed via the IDL - This required some of the warnings to be saved to an `IVector` instead of `std::vector`, among some other small changes. 6. The localization resources had to be split into two halves. - Resource file linked in init.cpp. Verified at runtime thanks to the StaticResourceLoader. 7. Added constructors to some `ActionArgs` 8. Utils.h/cpp were moved to `cascadia/inc`. `JsonKey()` was moved to `JsonUtils`. Both TermApp and TSM need access to Utils.h/cpp. A large amount of work includes moving to the new namespace (`TerminalApp` --> `Microsoft::Terminal::Settings::Model`). Fixing the tests had its own complications. Testing required us to split up TSM into a DLL and LIB, similar to TermApp. Discussion on creating a non-local test variant can be found in #7743. Closes #885
2020-10-06 18:56:59 +02:00
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 (_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 \"{}\" ", _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 (_SuppressApplicationTitle)
{
if (_SuppressApplicationTitle.Value())
{
ss << fmt::format(L"--suppressApplicationTitle ");
}
else
{
ss << fmt::format(L"--useApplicationTitle ");
}
}
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 != nullptr)
{
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 SwitchToTabArgs::GenerateName() const
{
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");
}
return winrt::hstring{
fmt::format(std::wstring_view(RS_(L"MoveFocusWithArgCommandKey")),
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..."
Introduce TerminalSettingsModel project (#7667) Introduces a new TerminalSettingsModel (TSM) project. This project is responsible for (de)serializing and exposing Windows Terminal's settings as WinRT objects. ## References #885: TSM epic #1564: Settings UI is dependent on this for data binding and settings access #6904: TSM Spec In the process of ripping out TSM from TerminalApp, a few other changes were made to make this possible: 1. AppLogic's `ApplicationDisplayName` and `ApplicationVersion` was moved to `CascadiaSettings` - These are defined as static functions. They also no longer check if `AppLogic::Current()` is nullptr. 2. `enum LaunchMode` was moved from TerminalApp to TSM 3. `AzureConnectionType` and `TelnetConnectionType` were moved from the profile generators to their respective TerminalConnections 4. CascadiaSettings' `SettingsPath` and `DefaultSettingsPath` are exposed as `hstring` instead of `std::filesystem::path` 5. `Command::ExpandCommands()` was exposed via the IDL - This required some of the warnings to be saved to an `IVector` instead of `std::vector`, among some other small changes. 6. The localization resources had to be split into two halves. - Resource file linked in init.cpp. Verified at runtime thanks to the StaticResourceLoader. 7. Added constructors to some `ActionArgs` 8. Utils.h/cpp were moved to `cascadia/inc`. `JsonKey()` was moved to `JsonUtils`. Both TermApp and TSM need access to Utils.h/cpp. A large amount of work includes moving to the new namespace (`TerminalApp` --> `Microsoft::Terminal::Settings::Model`). Fixing the tests had its own complications. Testing required us to split up TSM into a DLL and LIB, similar to TermApp. Discussion on creating a non-local test variant can be found in #7743. Closes #885
2020-10-06 18:56:59 +02:00
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 (_SplitStyle)
{
case SplitState::Vertical:
ss << L"split: vertical, ";
break;
case SplitState::Horizontal:
ss << L"split: horizontal, ";
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");
}
Add support for running a `wt` commandline in the curent window WITH A KEYBINDING (#6537) ## Summary of the Pull Request Adds a execute commandline action (`wt`), which lets a user bind a key to a specific `wt` commandline. This commandline will get parsed and run _in the current window_. ## References * Related to #4472 * Related to #5400 - I need this for the commandline mode of the Command Palette * Related to #5970 ## PR Checklist * [x] Closes oh, there's not actually an issue for this. * [x] I work here * [x] Tests added/passed * [ ] Requires documentation to be updated - yes it does ## Detailed Description of the Pull Request / Additional comments One important part of this change concerns how panes are initialized at runtime. We've had some persistent trouble with initializing multiple panes, because they rely on knowing how big they'll actually be, to be able to determine if they can split again. We previously worked around this by ignoring the size check when we were in "startup", processing an initial commandline. This PR however requires us to be able to know the initial size of a pane at runtime, but before the parents have necessarily been added to the tree, or had their renderer's set up. This led to the development of `Pane::PreCalculateCanSplit`, which is very highly similar to `Pane::PreCalculateAutoSplit`. This method attempts to figure out how big a pane _will_ take, before the parent has necessarily laid out. This also involves a small change to `TermControl`, because if its renderer hasn't been set up yet, it'll always think the font is `{0, fontHeight}`, which will let the Terminal keep splitting in the x direction. This change also makes the TermControl set up a renderer to get the real font size when it hasn't yet been initialized. ## Validation Steps Performed This was what the json blob I was using for testing evolved into ```json { "command": { "action":"wt", "commandline": "new-tab cmd.exe /k #work 15 ; split-pane cmd.exe /k #work 15 ; split-pane cmd.exe /k media-commandline ; new-tab powershell dev\\symbols.ps1 ; new-tab -p \"Ubuntu\" ; new-tab -p \"haunter.gif\" ; focus-tab -t 0", }, "keys": ["ctrl+shift+n"] } ``` I also added some tests. # TODO * [x] Creating a `{ "command": "wt" }` action without a commandline will spawn a new `wt.exe` process? - Probably should just do nothing for the empty string
2020-07-17 23:05:29 +02:00
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"";
}
Add `closeOtherTabs`, `closeTabsAfter` actions (#7176) ## Summary of the Pull Request Adds support for two actions, `closeOtherTabs` and `closeTabsAfter`. Both these actions accept an `index` parameter. * `closeOtherTabs`: Close tabs other than `index` * `closeTabsAfter`: Close tabs after `index` (This is also "Close tabs to the right") ## References * This PR is being made to unblock @RahulRavishankar in #1912 ## PR Checklist * [x] I work here * [ ] Tests added/passed * [x] Requires documentation to be updated * [ ] We should file an issue for "add an `index` param to `closeTab`" to add similar support to the close tab action * [ ] We should file an issue for "make the `index` param to `closeOtherTabs`, `closeTabsAfter` optional" to make them both work on the _active_ tab when there's no `index` provided ## Validation Steps Performed * _Verified that_ closing all tabs when I have the `index`'th tab selected _works as expected_ * _Verified that_ closing all tabs when I have a tab other than the `index`'th tab selected _works as expected_ * _Verified that_ closing tabs to the right when I have the `index`'th tab selected _works as expected_ * _Verified that_ closing tabs to the right when I have a tab other than the `index`'th tab selected _works as expected_ - This one has one caveat: for whatever reason, if you run this action when the tab that's currently focused is _before_ the `index` param, then the tabs will expand to fill the entire width of the tab row, until you mouse over them. Probably has something to do with tabs not resizing down until there's a mouse exit event.
2020-08-06 23:47:50 +02:00
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");
Add `closeOtherTabs`, `closeTabsAfter` actions (#7176) ## Summary of the Pull Request Adds support for two actions, `closeOtherTabs` and `closeTabsAfter`. Both these actions accept an `index` parameter. * `closeOtherTabs`: Close tabs other than `index` * `closeTabsAfter`: Close tabs after `index` (This is also "Close tabs to the right") ## References * This PR is being made to unblock @RahulRavishankar in #1912 ## PR Checklist * [x] I work here * [ ] Tests added/passed * [x] Requires documentation to be updated * [ ] We should file an issue for "add an `index` param to `closeTab`" to add similar support to the close tab action * [ ] We should file an issue for "make the `index` param to `closeOtherTabs`, `closeTabsAfter` optional" to make them both work on the _active_ tab when there's no `index` provided ## Validation Steps Performed * _Verified that_ closing all tabs when I have the `index`'th tab selected _works as expected_ * _Verified that_ closing all tabs when I have a tab other than the `index`'th tab selected _works as expected_ * _Verified that_ closing tabs to the right when I have the `index`'th tab selected _works as expected_ * _Verified that_ closing tabs to the right when I have a tab other than the `index`'th tab selected _works as expected_ - This one has one caveat: for whatever reason, if you run this action when the tab that's currently focused is _before_ the `index` param, then the tabs will expand to fill the entire width of the tab row, until you mouse over them. Probably has something to do with tabs not resizing down until there's a mouse exit event.
2020-08-06 23:47:50 +02:00
}
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");
Add `closeOtherTabs`, `closeTabsAfter` actions (#7176) ## Summary of the Pull Request Adds support for two actions, `closeOtherTabs` and `closeTabsAfter`. Both these actions accept an `index` parameter. * `closeOtherTabs`: Close tabs other than `index` * `closeTabsAfter`: Close tabs after `index` (This is also "Close tabs to the right") ## References * This PR is being made to unblock @RahulRavishankar in #1912 ## PR Checklist * [x] I work here * [ ] Tests added/passed * [x] Requires documentation to be updated * [ ] We should file an issue for "add an `index` param to `closeTab`" to add similar support to the close tab action * [ ] We should file an issue for "make the `index` param to `closeOtherTabs`, `closeTabsAfter` optional" to make them both work on the _active_ tab when there's no `index` provided ## Validation Steps Performed * _Verified that_ closing all tabs when I have the `index`'th tab selected _works as expected_ * _Verified that_ closing all tabs when I have a tab other than the `index`'th tab selected _works as expected_ * _Verified that_ closing tabs to the right when I have the `index`'th tab selected _works as expected_ * _Verified that_ closing tabs to the right when I have a tab other than the `index`'th tab selected _works as expected_ - This one has one caveat: for whatever reason, if you run this action when the tab that's currently focused is _before_ the `index` param, then the tabs will expand to fill the entire width of the tab row, until you mouse over them. Probably has something to do with tabs not resizing down until there's a mouse exit event.
2020-08-06 23:47:50 +02:00
}
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)
};
}
}