terminal/src/cascadia/TerminalApp/AppCommandlineArgs.h
Mike Griese 830c22b73e Add support for commandline args to wt.exe (#4023)
## Summary of the Pull Request

Adds support for commandline arguments to the Windows Terminal, in accordance with the spec in #3495

## References

* Original issue: #607
* Original spec: #3495

## PR Checklist
* [x] Closes #607
* [x] I work here
* [x] Tests added/passed
* [ ] We should probably add some docs on these commands
* [x] The spec (#3495) needs to be merged first!

## Detailed Description of the Pull Request / Additional comments

🛑 **STOP** 🛑 - have you read #3495 yet? If you haven't, go do that now.

This PR adds support for three initial sub-commands to the `wt.exe` application:
* `new-tab`: Used to create a new tab.
* `split-pane`: Used to create a new split.
* `focus-tab`: Moves focus to another tab.

These commands are largely POC to prove that the commandlines work. They're not totally finished, but they work well enough. Follow up work items will be filed to track adding support for additional parameters and subcommands

Important scenarios added:
* `wt -d .`: Open a new wt instance in the current working directory #878
* `wt -p <profile name>`: Create a wt instance running the given profile, to unblock  #576, #1357, #2339
* `wt ; new-tab ; split-pane -V`: Launch the terminal with multiple tabs, splits, to unblock #756 

## Validation Steps Performed

* Ran tests
* Played with it a bunch
2020-01-27 15:34:12 +00:00

98 lines
3 KiB
C++

// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#pragma once
#include "ActionAndArgs.h"
#include "Commandline.h"
#ifdef UNIT_TESTING
// fwdecl unittest classes
namespace TerminalAppLocalTests
{
class CommandlineTest;
};
#endif
namespace TerminalApp
{
class AppCommandlineArgs;
};
class TerminalApp::AppCommandlineArgs final
{
public:
static constexpr std::string_view NixHelpFlag{ "-?" };
static constexpr std::string_view WindowsHelpFlag{ "/?" };
static constexpr std::wstring_view PlaceholderExeName{ L"wt.exe" };
AppCommandlineArgs();
~AppCommandlineArgs() = default;
int ParseCommand(const Commandline& command);
static std::vector<Commandline> BuildCommands(const std::vector<const wchar_t*>& args);
static std::vector<Commandline> BuildCommands(winrt::array_view<const winrt::hstring>& args);
void ValidateStartupCommands();
std::deque<winrt::TerminalApp::ActionAndArgs>& GetStartupActions();
const std::string& GetExitMessage();
private:
static const std::wregex _commandDelimiterRegex;
CLI::App _app{ "wt - the Windows Terminal" };
// This is a helper struct to encapsulate all the options for a subcommand
// that produces a NewTerminalArgs.
struct NewTerminalSubcommand
{
CLI::App* subcommand;
CLI::Option* commandlineOption;
CLI::Option* profileNameOption;
CLI::Option* startingDirectoryOption;
};
// --- Subcommands ---
NewTerminalSubcommand _newTabCommand;
NewTerminalSubcommand _newPaneCommand;
CLI::App* _focusTabCommand;
// Are you adding a new sub-command? Make sure to update _noCommandsProvided!
CLI::Option* _horizontalOption;
CLI::Option* _verticalOption;
std::string _profileName;
std::string _startingDirectory;
// _commandline will receive the commandline as it's parsed by CLI11
std::vector<std::string> _commandline;
const Commandline* _currentCommandline{ nullptr };
bool _splitVertical{ false };
bool _splitHorizontal{ false };
int _focusTabIndex{ -1 };
bool _focusNextTab{ false };
bool _focusPrevTab{ false };
// Are you adding more args here? Make sure to reset them in _resetStateToDefault
std::deque<winrt::TerminalApp::ActionAndArgs> _startupActions;
std::string _exitMessage;
winrt::TerminalApp::NewTerminalArgs _getNewTerminalArgs(NewTerminalSubcommand& subcommand);
void _addNewTerminalArgs(NewTerminalSubcommand& subcommand);
void _buildParser();
void _buildNewTabParser();
void _buildSplitPaneParser();
void _buildFocusTabParser();
bool _noCommandsProvided();
void _resetStateToDefault();
int _handleExit(const CLI::App& command, const CLI::Error& e);
static void _addCommandsForArg(std::vector<Commandline>& commands, std::wstring_view arg);
#ifdef UNIT_TESTING
friend class TerminalAppLocalTests::CommandlineTest;
#endif
};