Compare commits

...

5 commits

Author SHA1 Message Date
Mike Griese 80a4fedc16 hackathon week is my favorite week
This is basically the complete #8797.
2021-07-29 15:14:53 -05:00
Mike Griese 84e95cf06a I'm shocked at how well this is working 2021-07-29 14:34:32 -05:00
Mike Griese 5f5f47a2ac plumb input all the way through. Now need to attach to command palette 2021-07-29 13:10:48 -05:00
Mike Griese 445b985474 collect the input from stdin and pass to Remoting::CommandlineArgs 2021-07-29 11:35:47 -05:00
Mike Griese cf96475498 update wt.exe to pass handles through to windowsterminal.exe 2021-07-29 09:42:42 -05:00
17 changed files with 220 additions and 9 deletions

View file

@ -15,13 +15,16 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
}
CommandlineArgs(const winrt::array_view<const winrt::hstring>& args,
winrt::hstring currentDirectory) :
winrt::hstring currentDirectory,
winrt::hstring stdInput) :
_args{ args.begin(), args.end() },
_cwd{ currentDirectory }
_cwd{ currentDirectory },
_stdInput{ stdInput }
{
}
winrt::hstring CurrentDirectory() { return _cwd; };
winrt::hstring StdInput() { return _stdInput; };
void Commandline(winrt::array_view<const winrt::hstring> const& value);
winrt::com_array<winrt::hstring> Commandline();
@ -29,6 +32,7 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
private:
winrt::com_array<winrt::hstring> _args;
winrt::hstring _cwd;
winrt::hstring _stdInput;
};
}

View file

@ -7,10 +7,11 @@ namespace Microsoft.Terminal.Remoting
runtimeclass CommandlineArgs
{
CommandlineArgs();
CommandlineArgs(String[] args, String cwd);
CommandlineArgs(String[] args, String cwd, String stdInput);
String[] Commandline { get; set; };
String CurrentDirectory();
String StdInput{ get; };
};
runtimeclass RenameRequestArgs

View file

@ -819,6 +819,36 @@ namespace winrt::TerminalApp::implementation
args.Handled(true);
}
void TerminalPage::_HandleSelectList(const IInspectable& /*sender*/,
const ActionEventArgs& args)
{
if (args)
{
if (const auto& realArgs = args.ActionArgs().try_as<SelectListArgs>())
{
const auto& prefix{ realArgs.Prefix() };
const auto& options{ realArgs.Options() };
auto actions = winrt::single_threaded_vector<Command>();
for (const auto& opt : options)
{
ActionAndArgs aaa{};
aaa.Action(ShortcutAction::SendInput);
SendInputArgs args{ fmt::format(L"{} {}", prefix.c_str(), opt.c_str()) };
aaa.Args(args);
Command cmd{ opt, aaa };
actions.Append(cmd);
}
CommandPalette().SetCommands(actions);
// EnableCommandPaletteMode will make sure to trigger
// _updateFilteredActions, which we need to update the command
// list.
CommandPalette().EnableCommandPaletteMode(CommandPaletteLaunchMode::Action);
CommandPalette().Visibility(Visibility::Visible);
}
}
}
void TerminalPage::_HandleGlobalSummon(const IInspectable& /*sender*/,
const ActionEventArgs& args)
{

View file

@ -194,6 +194,7 @@ void AppCommandlineArgs::_buildParser()
_buildMoveFocusParser();
_buildMovePaneParser();
_buildFocusPaneParser();
_buildSelectListParser();
}
// Method Description:
@ -486,6 +487,60 @@ void AppCommandlineArgs::_buildFocusPaneParser()
setupSubcommand(_focusPaneShort);
}
// Method Description:
// - Adds the `new-tab` subcommand and related options to the commandline parser.
// - Additionally adds the `nt` subcommand, which is just a shortened version of `new-tab`
// Arguments:
// - <none>
// Return Value:
// - <none>
void AppCommandlineArgs::_buildSelectListParser()
{
_selectListCommand = _app.add_subcommand("select-list", "select-list TODO");
// _newTabShort.subcommand = _app.add_subcommand("nt", RS_A(L"CmdNTDesc"));
auto setupSubcommand = [this](auto& subcommand) {
subcommand->add_option("--prefix",
_selectListPrefix,
"prefix to append to the input");
// When ParseCommand is called, if this subcommand was provided, this
// callback function will be triggered on the same thread. We can be sure
// that `this` will still be safe - this function just lets us know this
// command was parsed.
subcommand->callback([&, this]() {
// Build the action from the values we've parsed on the commandline.
ActionAndArgs aaa{};
aaa.Action(ShortcutAction::SelectList);
std::vector<winrt::hstring> lines{};
std::string_view view{ _stdInput };
std::string delim = "\n";
size_t start = 0u;
auto end = view.find(delim);
while (end != std::string::npos)
{
// std::cout << s.substr(start, end - start) << std::endl;
lines.push_back(winrt::to_hstring(view.substr(start, end - start)));
start = end + delim.length();
end = view.find(delim, start);
}
// std::stringstream stream{ _stdInput };
// std::string line;
// while (std::getline(stream, line, L'\n'))
// {
// lines.push_back(winrt::to_hstring{ line });
// }
auto hstringLines = winrt::single_threaded_vector<winrt::hstring>(std::move(lines));
SelectListArgs args{ winrt::to_hstring(_selectListPrefix), hstringLines };
aaa.Args(args);
_startupActions.push_back(aaa);
});
};
setupSubcommand(_selectListCommand);
}
// Method Description:
// - Add the `NewTerminalArgs` parameters to the given subcommand. This enables
// that subcommand to support all the properties in a NewTerminalArgs.
@ -627,6 +682,7 @@ bool AppCommandlineArgs::_noCommandsProvided()
*_movePaneShort ||
*_focusPaneCommand ||
*_focusPaneShort ||
*_selectListCommand ||
*_newPaneShort.subcommand ||
*_newPaneCommand.subcommand);
}
@ -983,6 +1039,11 @@ int AppCommandlineArgs::ParseArgs(const winrt::Microsoft::Terminal::Settings::Mo
return 0;
}
void AppCommandlineArgs::SetStdInput(const winrt::hstring& stdInput)
{
_stdInput = winrt::to_string(stdInput);
}
// Method Description:
// - Allows disabling addition of help-related info in the exit message
// Arguments:
@ -1013,6 +1074,8 @@ void AppCommandlineArgs::FullResetState()
_isHandoffListener = false;
_windowTarget = {};
_stdInput = "";
}
std::string_view AppCommandlineArgs::GetTargetWindow() const noexcept

View file

@ -29,6 +29,7 @@ public:
int ParseCommand(const Commandline& command);
int ParseArgs(winrt::array_view<const winrt::hstring>& args);
void SetStdInput(const winrt::hstring& stdInput);
static std::vector<Commandline> BuildCommands(const std::vector<const wchar_t*>& args);
static std::vector<Commandline> BuildCommands(winrt::array_view<const winrt::hstring>& args);
@ -86,6 +87,7 @@ private:
CLI::App* _movePaneShort;
CLI::App* _focusPaneCommand;
CLI::App* _focusPaneShort;
CLI::App* _selectListCommand;
// Are you adding a new sub-command? Make sure to update _noCommandsProvided!
@ -112,6 +114,8 @@ private:
bool _focusPrevTab{ false };
int _focusPaneTarget{ -1 };
std::string _selectListPrefix{};
// Are you adding more args here? Make sure to reset them in _resetStateToDefault
const Commandline* _currentCommandline{ nullptr };
@ -122,6 +126,8 @@ private:
bool _shouldExitEarly{ false };
std::string _windowTarget{};
std::string _stdInput{};
// Are you adding more args or attributes here? If they are not reset in _resetStateToDefault, make sure to reset them in FullResetState
winrt::Microsoft::Terminal::Settings::Model::NewTerminalArgs _getNewTerminalArgs(NewTerminalSubcommand& subcommand);
@ -133,6 +139,7 @@ private:
void _buildMoveFocusParser();
void _buildMovePaneParser();
void _buildFocusPaneParser();
void _buildSelectListParser();
bool _noCommandsProvided();
void _resetStateToDefault();
int _handleExit(const CLI::App& command, const CLI::Error& e);

View file

@ -1220,9 +1220,11 @@ namespace winrt::TerminalApp::implementation
// - the result of the first command who's parsing returned a non-zero code,
// or 0. (see AppLogic::_ParseArgs)
int32_t AppLogic::ExecuteCommandline(array_view<const winrt::hstring> args,
const winrt::hstring& cwd)
const winrt::hstring& cwd,
const winrt::hstring& stdInput)
{
::TerminalApp::AppCommandlineArgs appArgs;
appArgs.SetStdInput(stdInput);
auto result = appArgs.ParseArgs(args);
if (result == 0)
{

View file

@ -53,7 +53,7 @@ namespace winrt::TerminalApp::implementation
[[nodiscard]] Microsoft::Terminal::Settings::Model::CascadiaSettings GetSettings() const noexcept;
int32_t SetStartupCommandline(array_view<const winrt::hstring> actions);
int32_t ExecuteCommandline(array_view<const winrt::hstring> actions, const winrt::hstring& cwd);
int32_t ExecuteCommandline(array_view<const winrt::hstring> actions, const winrt::hstring& cwd, const winrt::hstring& stdInput);
TerminalApp::FindTargetWindowResult FindTargetWindow(array_view<const winrt::hstring> actions);
winrt::hstring ParseCommandlineMessage();
bool ShouldExitEarly();

View file

@ -35,7 +35,7 @@ namespace TerminalApp
Boolean IsElevated();
Int32 SetStartupCommandline(String[] commands);
Int32 ExecuteCommandline(String[] commands, String cwd);
Int32 ExecuteCommandline(String[] commands, String cwd, String stdInput);
String ParseCommandlineMessage { get; };
Boolean ShouldExitEarly { get; };

View file

@ -60,6 +60,7 @@ static constexpr std::string_view IdentifyWindowKey{ "identifyWindow" };
static constexpr std::string_view IdentifyWindowsKey{ "identifyWindows" };
static constexpr std::string_view RenameWindowKey{ "renameWindow" };
static constexpr std::string_view OpenWindowRenamerKey{ "openWindowRenamer" };
static constexpr std::string_view SelectListKey{ "selectList" };
static constexpr std::string_view GlobalSummonKey{ "globalSummon" };
static constexpr std::string_view QuakeModeKey{ "quakeMode" };
static constexpr std::string_view FocusPaneKey{ "focusPane" };
@ -359,6 +360,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
{ ShortcutAction::IdentifyWindows, RS_(L"IdentifyWindowsCommandKey") },
{ ShortcutAction::RenameWindow, RS_(L"ResetWindowNameCommandKey") },
{ ShortcutAction::OpenWindowRenamer, RS_(L"OpenWindowRenamerCommandKey") },
{ ShortcutAction::SelectList, L"" }, // Intentionally omitted, must be generated by GenerateName
{ ShortcutAction::GlobalSummon, L"" }, // Intentionally omitted, must be generated by GenerateName
{ ShortcutAction::QuakeMode, RS_(L"QuakeModeCommandKey") },
{ ShortcutAction::FocusPane, L"" }, // Intentionally omitted, must be generated by GenerateName

View file

@ -31,6 +31,7 @@
#include "PrevTabArgs.g.cpp"
#include "NextTabArgs.g.cpp"
#include "RenameWindowArgs.g.cpp"
#include "SelectListArgs.g.cpp"
#include "GlobalSummonArgs.g.cpp"
#include "FocusPaneArgs.g.cpp"
@ -631,6 +632,12 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
return RS_(L"ResetWindowNameCommandKey");
}
winrt::hstring SelectListArgs::GenerateName() const
{
// TODO!
return winrt::hstring{};
}
winrt::hstring GlobalSummonArgs::GenerateName() const
{
// GH#10210 - Is this action literally the same thing as the `quakeMode`

View file

@ -33,6 +33,7 @@
#include "PrevTabArgs.g.h"
#include "NextTabArgs.g.h"
#include "RenameWindowArgs.g.h"
#include "SelectListArgs.g.h"
#include "GlobalSummonArgs.g.h"
#include "FocusPaneArgs.g.h"
@ -563,6 +564,8 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
struct SendInputArgs : public SendInputArgsT<SendInputArgs>
{
SendInputArgs() = default;
SendInputArgs(winrt::hstring input) :
_Input{ input } {};
ACTION_ARG(winrt::hstring, Input, L"");
static constexpr std::string_view InputKey{ "input" };
@ -1564,6 +1567,50 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
}
};
struct SelectListArgs : public SelectListArgsT<SelectListArgs>
{
SelectListArgs() = default;
using OptionsType = winrt::Windows::Foundation::Collections::IVector<winrt::hstring>;
SelectListArgs(winrt::hstring prefix, OptionsType options) :
_Prefix{ prefix },
_Options{ options } {};
ACTION_ARG(winrt::hstring, Prefix);
ACTION_ARG(OptionsType, Options);
public:
hstring GenerateName() const;
bool Equals(const IActionArgs& /*other*/)
{
return false;
};
static FromJsonResult FromJson(const Json::Value& /*json*/)
{
return { nullptr, { /*TODO! add a warning here? or just do nothing*/ } };
}
static Json::Value ToJson(const IActionArgs& val)
{
if (!val)
{
return {};
}
Json::Value json{ Json::Value::null };
return json;
}
IActionArgs Copy() const
{
auto copy{ winrt::make_self<SelectListArgs>() };
copy->_Prefix = _Prefix;
copy->_Options = _Options;
return *copy;
}
size_t Hash() const
{
// TODO
return ::Microsoft::Terminal::Settings::Model::HashUtils::HashProperty(Prefix());
}
};
struct GlobalSummonArgs : public GlobalSummonArgsT<GlobalSummonArgs>
{
GlobalSummonArgs() = default;
@ -1709,6 +1756,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::factory_implementation
BASIC_FACTORY(MoveFocusArgs);
BASIC_FACTORY(MovePaneArgs);
BASIC_FACTORY(SplitPaneArgs);
BASIC_FACTORY(SendInputArgs);
BASIC_FACTORY(SetColorSchemeArgs);
BASIC_FACTORY(ExecuteCommandlineArgs);
BASIC_FACTORY(CloseOtherTabsArgs);
@ -1718,5 +1766,6 @@ namespace winrt::Microsoft::Terminal::Settings::Model::factory_implementation
BASIC_FACTORY(OpenSettingsArgs);
BASIC_FACTORY(FindMatchArgs);
BASIC_FACTORY(NewWindowArgs);
BASIC_FACTORY(SelectListArgs);
BASIC_FACTORY(FocusPaneArgs);
}

View file

@ -171,6 +171,7 @@ namespace Microsoft.Terminal.Settings.Model
[default_interface] runtimeclass SendInputArgs : IActionArgs
{
SendInputArgs(String input);
String Input { get; };
};
@ -281,6 +282,13 @@ namespace Microsoft.Terminal.Settings.Model
String Name { get; };
};
[default_interface] runtimeclass SelectListArgs : IActionArgs
{
SelectListArgs(String Prefix, IVector<String> Options);
String Prefix { get; };
IVector<String> Options { get; };
};
[default_interface] runtimeclass GlobalSummonArgs : IActionArgs
{
String Name { get; };

View file

@ -74,6 +74,7 @@
ON_ALL_ACTIONS(IdentifyWindows) \
ON_ALL_ACTIONS(RenameWindow) \
ON_ALL_ACTIONS(OpenWindowRenamer) \
ON_ALL_ACTIONS(SelectList) \
ON_ALL_ACTIONS(GlobalSummon) \
ON_ALL_ACTIONS(QuakeMode) \
ON_ALL_ACTIONS(FocusPane)
@ -100,6 +101,7 @@
ON_ALL_ACTIONS_WITH_ARGS(ResizePane) \
ON_ALL_ACTIONS_WITH_ARGS(ScrollDown) \
ON_ALL_ACTIONS_WITH_ARGS(ScrollUp) \
ON_ALL_ACTIONS_WITH_ARGS(SelectList) \
ON_ALL_ACTIONS_WITH_ARGS(SendInput) \
ON_ALL_ACTIONS_WITH_ARGS(SetColorScheme) \
ON_ALL_ACTIONS_WITH_ARGS(SetTabColor) \

View file

@ -37,6 +37,9 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
struct Command : CommandT<Command>
{
Command();
Command(winrt::hstring name, Model::ActionAndArgs aaa) :
_ActionAndArgs{ aaa },
_name{ name } {};
com_ptr<Command> Copy() const;
static winrt::com_ptr<Command> FromJson(const Json::Value& json,

View file

@ -31,6 +31,7 @@ namespace Microsoft.Terminal.Settings.Model
[default_interface] runtimeclass Command : Windows.UI.Xaml.Data.INotifyPropertyChanged
{
Command();
Command(String name, ActionAndArgs action);
String Name { get; };
ActionAndArgs ActionAndArgs { get; };

View file

@ -158,6 +158,35 @@ void _buildArgsFromCommandline(std::vector<winrt::hstring>& args)
}
}
winrt::hstring _getStdin()
{
HANDLE hIn = GetStdHandle(STD_INPUT_HANDLE);
if (hIn)
{
std::stringstream ss;
DWORD read{};
do
{
std::array<char, 4096> _buffer{};
const auto readFail{ !ReadFile(hIn, _buffer.data(), gsl::narrow_cast<DWORD>(_buffer.size()), &read, nullptr) };
// reading failed (we must check this first, because read will also be 0.)
if (readFail)
{
const auto lastError = GetLastError();
return winrt::hstring{};
}
ss << std::string_view{ _buffer.data(), read };
} while (read == 4096);
// keep reading until we don't read enough to fill the buffer. The
// subsequent read will return ERROR_BROKEN_PIPE.
return winrt::to_hstring(ss.str());
}
return winrt::hstring{};
}
// Method Description:
// - Retrieve any commandline args passed on the commandline, and pass them to
// the WindowManager, to ask if we should become a window process.
@ -181,7 +210,10 @@ void AppHost::_HandleCommandlineArgs()
_buildArgsFromCommandline(args);
std::wstring cwd{ wil::GetCurrentDirectoryW<std::wstring>() };
Remoting::CommandlineArgs eventArgs{ { args }, { cwd } };
auto stdIn{ _getStdin() };
Remoting::CommandlineArgs eventArgs{ { args }, { cwd }, stdIn };
_windowManager.ProposeCommandline(eventArgs);
_shouldCreateWindow = _windowManager.ShouldCreateWindow();
@ -612,7 +644,7 @@ void AppHost::_DispatchCommandline(winrt::Windows::Foundation::IInspectable send
// Summon the window whenever we dispatch a commandline to it. This will
// make it obvious when a new tab/pane is created in a window.
_HandleSummon(sender, summonArgs);
_logic.ExecuteCommandline(args.Commandline(), args.CurrentDirectory());
_logic.ExecuteCommandline(args.Commandline(), args.CurrentDirectory(), args.StdInput());
}
// Method Description:

View file

@ -32,5 +32,5 @@ int __stdcall wWinMain(HINSTANCE, HINSTANCE, LPWSTR pCmdLine, int)
// Go!
wil::unique_process_information pi;
return !CreateProcessW(module.c_str(), cmdline.data(), nullptr, nullptr, FALSE, 0, nullptr, nullptr, &si, &pi);
return !CreateProcessW(module.c_str(), cmdline.data(), nullptr, nullptr, true, 0, nullptr, nullptr, &si, &pi);
}