diff --git a/src/cascadia/LocalTests_SettingsModel/TerminalSettingsTests.cpp b/src/cascadia/LocalTests_SettingsModel/TerminalSettingsTests.cpp index e274767d3..cecfade05 100644 --- a/src/cascadia/LocalTests_SettingsModel/TerminalSettingsTests.cpp +++ b/src/cascadia/LocalTests_SettingsModel/TerminalSettingsTests.cpp @@ -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()); + } + } } diff --git a/src/cascadia/TerminalApp/AppCommandlineArgs.cpp b/src/cascadia/TerminalApp/AppCommandlineArgs.cpp index ae8bced53..a2da96205 100644 --- a/src/cascadia/TerminalApp/AppCommandlineArgs.cpp +++ b/src/cascadia/TerminalApp/AppCommandlineArgs.cpp @@ -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)); diff --git a/src/cascadia/TerminalSettingsModel/TerminalSettings.cpp b/src/cascadia/TerminalSettingsModel/TerminalSettings.cpp index f547e27d2..de6b01347 100644 --- a/src/cascadia/TerminalSettingsModel/TerminalSettings.cpp +++ b/src/cascadia/TerminalSettingsModel/TerminalSettings.cpp @@ -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{ til::color{ newTerminalArgs.TabColor().Value() } });