Move commandline->title promotion into TerminalSettings (#11029)

It was insufficient to only promote commandline components to titles
during commandline parsing, because we also have a whole complement of
actions that contain NewTerminalArgs. The tests caught me out a little
too late (sorry!). I decided it was better move promotion down to
TerminalSettings.

Fixes #6776
Re-implements #10998
This commit is contained in:
Dustin L. Howett 2021-08-24 16:31:27 -07:00 committed by GitHub
parent f3cc4c0328
commit 7b6df26411
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 98 additions and 7 deletions

View file

@ -42,6 +42,8 @@ namespace SettingsModelLocalTests
TEST_METHOD(TestLayerProfileOnColorScheme);
TEST_METHOD(TestCommandlineToTitlePromotion);
TEST_CLASS_SETUP(ClassSetup)
{
return true;
@ -554,4 +556,85 @@ namespace SettingsModelLocalTests
VERIFY_ARE_EQUAL(ARGB(0, 0x45, 0x67, 0x89), terminalSettings4->CursorColor()); // from profile (no color scheme)
VERIFY_ARE_EQUAL(DEFAULT_CURSOR_COLOR, terminalSettings5->CursorColor()); // default
}
void TerminalSettingsTests::TestCommandlineToTitlePromotion()
{
const std::string settingsJson{ R"(
{
"defaultProfile": "{6239a42c-0000-49a3-80bd-e8fdd045185c}",
"profiles": { "list": [
{
"name": "profile0",
"guid": "{6239a42c-0000-49a3-80bd-e8fdd045185c}",
"historySize": 1,
"commandline": "cmd.exe"
},
],
"defaults": {
"historySize": 29
} }
})" };
const winrt::guid guid0{ ::Microsoft::Console::Utils::GuidFromString(L"{6239a42c-0000-49a3-80bd-e8fdd045185c}") };
CascadiaSettings settings{ til::u8u16(settingsJson) };
{ // just a profile (profile wins)
NewTerminalArgs args{};
args.Profile(L"profile0");
const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(settings, args, nullptr) };
VERIFY_ARE_EQUAL(L"profile0", settingsStruct.DefaultSettings().StartingTitle());
}
{ // profile and command line -> no promotion (profile wins)
NewTerminalArgs args{};
args.Profile(L"profile0");
args.Commandline(L"foo.exe");
const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(settings, args, nullptr) };
VERIFY_ARE_EQUAL(L"profile0", settingsStruct.DefaultSettings().StartingTitle());
}
{ // just a title -> it is propagated
NewTerminalArgs args{};
args.TabTitle(L"Analog Kid");
const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(settings, args, nullptr) };
VERIFY_ARE_EQUAL(L"Analog Kid", settingsStruct.DefaultSettings().StartingTitle());
}
{ // title and command line -> no promotion
NewTerminalArgs args{};
args.TabTitle(L"Digital Man");
args.Commandline(L"foo.exe");
const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(settings, args, nullptr) };
VERIFY_ARE_EQUAL(L"Digital Man", settingsStruct.DefaultSettings().StartingTitle());
}
{ // just a commandline -> promotion
NewTerminalArgs args{};
args.Commandline(L"foo.exe");
const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(settings, args, nullptr) };
VERIFY_ARE_EQUAL(L"foo.exe", settingsStruct.DefaultSettings().StartingTitle());
}
// various typesof commandline follow
{
NewTerminalArgs args{};
args.Commandline(L"foo.exe bar");
const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(settings, args, nullptr) };
VERIFY_ARE_EQUAL(L"foo.exe", settingsStruct.DefaultSettings().StartingTitle());
}
{
NewTerminalArgs args{};
args.Commandline(L"\"foo exe.exe\" bar");
const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(settings, args, nullptr) };
VERIFY_ARE_EQUAL(L"foo exe.exe", settingsStruct.DefaultSettings().StartingTitle());
}
{
NewTerminalArgs args{};
args.Commandline(L"\"\" grand designs");
const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(settings, args, nullptr) };
VERIFY_ARE_EQUAL(L"", settingsStruct.DefaultSettings().StartingTitle());
}
{
NewTerminalArgs args{};
args.Commandline(L" imagine a man");
const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(settings, args, nullptr) };
VERIFY_ARE_EQUAL(L"", settingsStruct.DefaultSettings().StartingTitle());
}
}
}

View file

@ -603,13 +603,6 @@ NewTerminalArgs AppCommandlineArgs::_getNewTerminalArgs(AppCommandlineArgs::NewT
args.Profile(winrt::to_hstring(_profileName));
}
if (!*subcommand.profileNameOption && !_commandline.empty())
{
// If there's no profile, but there IS a command line, set the tab title to the first part of the command
// This will ensure that the tab we spawn has a name (since it didn't get one from its profile!)
args.TabTitle(winrt::to_hstring(til::at(_commandline, 0)));
}
if (*subcommand.startingDirectoryOption)
{
args.StartingDirectory(winrt::to_hstring(_startingDirectory));

View file

@ -124,6 +124,21 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
{
defaultSettings.StartingTitle(newTerminalArgs.TabTitle());
}
else
{
// There was no title, and no profile from which to infer the title.
// Per GH#6776, promote the first component of the command line to the title.
// This will ensure that the tab we spawn has a name (since it didn't get one from its profile!)
if (newTerminalArgs.Profile().empty() && !newTerminalArgs.Commandline().empty())
{
const std::wstring_view commandLine{ newTerminalArgs.Commandline() };
const auto start{ til::at(commandLine, 0) == L'"' ? 1 : 0 };
const auto terminator{ commandLine.find_first_of(start ? L'"' : L' ', start) }; // look past the first character if it starts with "
// We have to take a copy here; winrt::param::hstring requires a null-terminated string
const std::wstring firstComponent{ commandLine.substr(start, terminator - start) };
defaultSettings.StartingTitle(firstComponent);
}
}
if (newTerminalArgs.TabColor())
{
defaultSettings.StartingTabColor(winrt::Windows::Foundation::IReference<winrt::Microsoft::Terminal::Core::Color>{ til::color{ newTerminalArgs.TabColor().Value() } });