Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add --pos and --size cmdline args #13730

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 21 additions & 1 deletion src/cascadia/TerminalApp/AppCommandlineArgs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include "pch.h"
#include "AppCommandlineArgs.h"
#include "../types/inc/utils.hpp"
#include "TerminalSettingsModel/ModelSerializationHelpers.h"
#include <LibraryResources.h>

using namespace winrt::Microsoft::Terminal::Settings::Model;
Expand Down Expand Up @@ -183,6 +184,15 @@ void AppCommandlineArgs::_buildParser()
maximized->excludes(fullscreen);
focus->excludes(fullscreen);

auto positionCallback = [this](std::string string) {
_position = LaunchPositionFromString(string);
};
_app.add_option_function<std::string>("--pos", positionCallback, RS_A(L"CmdPositionDesc"));
auto sizeCallback = [this](std::string string) {
_size = SizeFromString(string);
};
_app.add_option_function<std::string>("--size", sizeCallback, RS_A(L"CmdSizeDesc"));

_app.add_option("-w,--window",
_windowTarget,
RS_A(L"CmdWindowTargetArgDesc"));
Expand Down Expand Up @@ -709,7 +719,7 @@ void AppCommandlineArgs::_resetStateToDefault()
// DON'T clear _launchMode here! This will get called once for every
// subcommand, so we don't want `wt -F new-tab ; split-pane` clearing out
// the "global" fullscreen flag (-F).
// Same with _windowTarget.
// Same with _windowTarget, _position and _size.
}

// Function Description:
Expand Down Expand Up @@ -936,6 +946,16 @@ std::optional<winrt::Microsoft::Terminal::Settings::Model::LaunchMode> AppComman
return _launchMode;
}

std::optional<winrt::Microsoft::Terminal::Settings::Model::LaunchPosition> AppCommandlineArgs::GetPosition() const noexcept
{
return _position;
}

std::optional<til::size> AppCommandlineArgs::GetSize() const noexcept
{
return _size;
}

// Method Description:
// - Attempts to parse an array of commandline args into a list of
// commands to execute, and then parses these commands. As commands are
Expand Down
4 changes: 4 additions & 0 deletions src/cascadia/TerminalApp/AppCommandlineArgs.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ class TerminalApp::AppCommandlineArgs final

std::optional<uint32_t> GetPersistedLayoutIdx() const noexcept;
std::optional<winrt::Microsoft::Terminal::Settings::Model::LaunchMode> GetLaunchMode() const noexcept;
std::optional<winrt::Microsoft::Terminal::Settings::Model::LaunchPosition> GetPosition() const noexcept;
std::optional<til::size> GetSize() const noexcept;

int ParseArgs(const winrt::Microsoft::Terminal::Settings::Model::ExecuteCommandlineArgs& args);
void DisableHelpInExitMessage();
Expand Down Expand Up @@ -119,6 +121,8 @@ class TerminalApp::AppCommandlineArgs final

const Commandline* _currentCommandline{ nullptr };
std::optional<winrt::Microsoft::Terminal::Settings::Model::LaunchMode> _launchMode{ std::nullopt };
std::optional<winrt::Microsoft::Terminal::Settings::Model::LaunchPosition> _position{ std::nullopt };
std::optional<til::size> _size{ std::nullopt };
bool _isHandoffListener{ false };
std::vector<winrt::Microsoft::Terminal::Settings::Model::ActionAndArgs> _startupActions;
std::string _exitMessage;
Expand Down
15 changes: 13 additions & 2 deletions src/cascadia/TerminalApp/AppLogic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -633,12 +633,17 @@ namespace winrt::TerminalApp::implementation
}
}

if (proposedSize.Width == 0 && proposedSize.Height == 0)
if (_appArgs.GetSize().has_value() || (proposedSize.Width == 0 && proposedSize.Height == 0))
{
// Use the default profile to determine how big of a window we need.
const auto settings{ TerminalSettings::CreateWithNewTerminalArgs(_settings, nullptr, nullptr) };

proposedSize = TermControl::GetProposedDimensions(settings.DefaultSettings(), dpi);
const til::size emptySize{};
const auto commandlineSize = _appArgs.GetSize().value_or(emptySize);
proposedSize = TermControl::GetProposedDimensions(settings.DefaultSettings(),
dpi,
commandlineSize.width,
commandlineSize.height);
}

// GH#2061 - If the global setting "Always show tab bar" is
Expand Down Expand Up @@ -738,6 +743,12 @@ namespace winrt::TerminalApp::implementation
}
}

// Commandline args trump everything else
if (_appArgs.GetPosition().has_value())
{
initialPosition = _appArgs.GetPosition().value();
}

return {
initialPosition.X ? initialPosition.X.Value() : defaultInitialX,
initialPosition.Y ? initialPosition.Y.Value() : defaultInitialY
Expand Down
6 changes: 6 additions & 0 deletions src/cascadia/TerminalApp/Resources/en-US/Resources.resw
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,12 @@
<data name="CmdWindowTargetArgDesc" xml:space="preserve">
<value>Specify a terminal window to run the given commandline in. "0" always refers to the current window. </value>
</data>
<data name="CmdPositionDesc" xml:space="preserve">
<value>Specify the position for the terminal, in "x,y" format.</value>
</data>
<data name="CmdSizeDesc" xml:space="preserve">
<value>Specify the number of columns and rows for the terminal, in "c,r" format.</value>
</data>
<data name="NewTabSplitButton.[using:Windows.UI.Xaml.Automation]AutomationProperties.HelpText" xml:space="preserve">
<value>Press the button to open a new terminal tab with your default profile. Open the flyout to select which profile you want to open.</value>
</data>
Expand Down
17 changes: 14 additions & 3 deletions src/cascadia/TerminalControl/TermControl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2032,15 +2032,26 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// - dpi: The DPI we should create the terminal at. This affects things such
// as font size, scrollbar and other control scaling, etc. Make sure the
// caller knows what monitor the control is about to appear on.
// - commandlineCols: Number of cols specified on the commandline
// - commandlineRows: Number of rows specified on the commandline
// Return Value:
// - a size containing the requested dimensions in pixels.
winrt::Windows::Foundation::Size TermControl::GetProposedDimensions(const IControlSettings& settings, const uint32_t dpi)
winrt::Windows::Foundation::Size TermControl::GetProposedDimensions(const IControlSettings& settings,
const uint32_t dpi,
int32_t commandlineCols,
int32_t commandlineRows)
{
// If the settings have negative or zero row or column counts, ignore those counts.
// (The lower TerminalCore layer also has upper bounds as well, but at this layer
// we may eventually impose different ones depending on how many pixels we can address.)
const auto cols = ::base::saturated_cast<float>(std::max(settings.InitialCols(), 1));
const auto rows = ::base::saturated_cast<float>(std::max(settings.InitialRows(), 1));
const auto cols = ::base::saturated_cast<float>(std::max(commandlineCols > 0 ?
commandlineCols :
settings.InitialCols(),
1));
const auto rows = ::base::saturated_cast<float>(std::max(commandlineRows > 0 ?
commandlineRows :
settings.InitialRows(),
1));

const winrt::Windows::Foundation::Size initialSize{ cols, rows };

Expand Down
5 changes: 4 additions & 1 deletion src/cascadia/TerminalControl/TermControl.h
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,10 @@ namespace winrt::Microsoft::Terminal::Control::implementation
Windows::UI::Xaml::Automation::Peers::AutomationPeer OnCreateAutomationPeer();
const Windows::UI::Xaml::Thickness GetPadding();

static Windows::Foundation::Size GetProposedDimensions(const IControlSettings& settings, const uint32_t dpi);
static Windows::Foundation::Size GetProposedDimensions(const IControlSettings& settings,
const uint32_t dpi,
int32_t commandlineCols,
int32_t commandlineRows);
static Windows::Foundation::Size GetProposedDimensions(const IControlSettings& settings, const uint32_t dpi, const winrt::Windows::Foundation::Size& initialSizeInChars);

void BellLightOn();
Expand Down
5 changes: 4 additions & 1 deletion src/cascadia/TerminalControl/TermControl.idl
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,10 @@ namespace Microsoft.Terminal.Control
IControlAppearance unfocusedAppearance,
Microsoft.Terminal.TerminalConnection.ITerminalConnection connection);

static Windows.Foundation.Size GetProposedDimensions(IControlSettings settings, UInt32 dpi);
static Windows.Foundation.Size GetProposedDimensions(IControlSettings settings,
UInt32 dpi,
Int32 commandlineCols,
Int32 commandlineRows);

void UpdateControlSettings(IControlSettings settings);
void UpdateControlSettings(IControlSettings settings, IControlAppearance unfocusedAppearance);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@
<ClInclude Include="VsDevShellGenerator.h" />
<ClInclude Include="VsSetupConfiguration.h" />
<ClInclude Include="WslDistroGenerator.h" />
<ClInclude Include="ModelSerializationHelpers.h" />
</ItemGroup>
<!-- ========================= Cpp Files ======================== -->
<ItemGroup>
Expand Down
82 changes: 82 additions & 0 deletions src/cascadia/TerminalSettingsModel/ModelSerializationHelpers.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/*++
Copyright (c) Microsoft Corporation
Licensed under the MIT license.
Module Name:
- ModelSerializationHelpers.h
Abstract:
- Helper methods for serializing/de-serializing model data.
--*/

#pragma once

// Function Description:
// - Helper for converting a pair of comma separated, potentially absent integer values
// into the corresponding left and right values. The leftValue and rightValue functions
// will be called back with the associated parsed integer value, assuming it's present.
// (100, 100): leftValue and rightValue functions both called back with 100.
// (100, ), (100, abc): leftValue function called back with 100
// (, 100), (abc, 100): rightValue function called back with 100
// (,): no function called back
// (100, 100, 100): we only read the first two values, this is equivalent to (100, 100)
// Arguments:
// - string: The string to parse
// - leftValue: Function called back with the value before the comma
// - rightValue: Function called back with the value after the comma
_TIL_INLINEPREFIX void ParseCommaSeparatedPair(const std::string& string,
std::function<void(int32_t)> leftValue,
std::function<void(int32_t)> rightValue)
{
static constexpr auto singleCharDelim = ',';
std::stringstream tokenStream(string);
std::string token;
uint8_t index = 0;

// Get values till we run out of delimiter separated values in the stream
// or we hit max number of allowable values (= 2)
// Non-numeral values or empty string will be caught as exception and we do not assign them
for (; std::getline(tokenStream, token, singleCharDelim) && (index < 2); index++)
{
try
{
int32_t value = std::stol(token);
if (index == 0)
{
leftValue(value);
}

if (index == 1)
{
rightValue(value);
}
}
catch (...)
{
// Do nothing
}
}
}

// See: ParseCommaSeparatedPair
_TIL_INLINEPREFIX ::winrt::Microsoft::Terminal::Settings::Model::LaunchPosition LaunchPositionFromString(const std::string& string)
{
::winrt::Microsoft::Terminal::Settings::Model::LaunchPosition initialPosition;
ParseCommaSeparatedPair(
string,
[&initialPosition](int32_t left) { initialPosition.X = left; },
[&initialPosition](int32_t right) { initialPosition.Y = right; });
return initialPosition;
}

// See: ParseCommaSeparatedPair
_TIL_INLINEPREFIX ::til::size SizeFromString(const std::string& string)
{
til::size size{};
ParseCommaSeparatedPair(
string,
[&size](int32_t left) { size.width = left; },
[&size](int32_t right) { size.height = right; });
return size;
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ Module Name:

#include "JsonUtils.h"
#include "SettingsTypes.h"
#include "ModelSerializationHelpers.h"

JSON_ENUM_MAPPER(::winrt::Microsoft::Terminal::Core::CursorStyle)
{
Expand Down Expand Up @@ -317,51 +318,12 @@ JSON_FLAG_MAPPER(::winrt::Microsoft::Terminal::Control::CopyFormat)
}
};

// Type Description:
// - Helper for converting the initial position string into
// 2 coordinate values. We allow users to only provide one coordinate,
// thus, we use comma as the separator:
// (100, 100): standard input string
// (, 100), (100, ): if a value is missing, we set this value as a default
// (,): both x and y are set to default
// (abc, 100): if a value is not valid, we treat it as default
// (100, 100, 100): we only read the first two values, this is equivalent to (100, 100)
template<>
struct ::Microsoft::Terminal::Settings::Model::JsonUtils::ConversionTrait<::winrt::Microsoft::Terminal::Settings::Model::LaunchPosition>
{
::winrt::Microsoft::Terminal::Settings::Model::LaunchPosition FromJson(const Json::Value& json)
{
::winrt::Microsoft::Terminal::Settings::Model::LaunchPosition ret;
auto initialPosition{ json.asString() };
static constexpr auto singleCharDelim = ',';
std::stringstream tokenStream(initialPosition);
std::string token;
uint8_t initialPosIndex = 0;

// Get initial position values till we run out of delimiter separated values in the stream
// or we hit max number of allowable values (= 2)
// Non-numeral values or empty string will be caught as exception and we do not assign them
for (; std::getline(tokenStream, token, singleCharDelim) && (initialPosIndex < 2); initialPosIndex++)
{
try
{
int64_t position = std::stol(token);
if (initialPosIndex == 0)
{
ret.X = position;
}

if (initialPosIndex == 1)
{
ret.Y = position;
}
}
catch (...)
{
// Do nothing
}
}
return ret;
return LaunchPositionFromString(json.asString());
}

bool CanConvert(const Json::Value& json)
Expand Down