Introduce startupActions in settings (#8770)

Procedural solution for https://github.com/microsoft/terminal/issues/756.

Introduces a `startupActions` global setting. 

This setting is as string with the same format as actions in command line arguments.
It is used only if command line arguments were not provided
(aka running pure wt.exe).

The setting allows implicit new-tabs.
In the case of invalid syntax we show the warning dialog and ignore the setting.

The documentation PR is here: https://github.com/MicrosoftDocs/terminal/pull/217
This commit is contained in:
Don-Vito 2021-01-15 20:30:11 +02:00 committed by GitHub
parent 9aea904229
commit 3c044f20cf
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 67 additions and 4 deletions

View file

@ -656,6 +656,10 @@
"description": "Sets the default profile. Opens by clicking the \"+\" icon or typing the key binding assigned to \"newTab\".",
"type": "string"
},
"startupActions": {
"description": "Sets the list of actions to apply if no command line is provided. Uses the same format as command line arguments",
"type": "string"
},
"disabledProfileSources": {
"description": "Disables all the dynamic profile generators in this list, preventing them from adding their profiles to the list of profiles on startup.",
"items": {

View file

@ -43,7 +43,8 @@ static const std::array<std::wstring_view, static_cast<uint32_t>(SettingsLoadWar
USES_RESOURCE(L"FailedToParseCommandJson"),
USES_RESOURCE(L"FailedToWriteToSettings"),
USES_RESOURCE(L"InvalidColorSchemeInCmd"),
USES_RESOURCE(L"InvalidSplitSize")
USES_RESOURCE(L"InvalidSplitSize"),
USES_RESOURCE(L"FailedToParseStartupActions")
};
static const std::array<std::wstring_view, static_cast<uint32_t>(SettingsLoadErrors::ERRORS_SIZE)> settingsLoadErrorsLabels {
USES_RESOURCE(L"NoProfilesText"),
@ -263,6 +264,14 @@ namespace winrt::TerminalApp::implementation
_settings.GlobalSettings().ShowTabsInTitlebar(false);
}
// Pay attention, that even if some command line arguments were parsed (like launch mode),
// we will not use the startup actions from settings.
// While this simplifies the logic, we might want to reconsider this behavior in the future.
if (!_hasCommandLineArguments && _hasSettingsStartupActions)
{
_root->SetStartupActions(_settingsAppArgs.GetStartupActions());
}
_root->SetSettings(_settings, false);
_root->Loaded({ this, &AppLogic::_OnLoaded });
_root->Initialized([this](auto&&, auto&&) {
@ -426,8 +435,7 @@ namespace winrt::TerminalApp::implementation
// Make sure the lines of text wrap
warningsTextBlock.TextWrapping(TextWrapping::Wrap);
const auto warnings = _settings.Warnings();
for (const auto& warning : warnings)
for (const auto& warning : _warnings)
{
// Try looking up the warning message key for each warning.
const auto warningText = _GetWarningText(warning);
@ -716,7 +724,34 @@ namespace winrt::TerminalApp::implementation
return E_INVALIDARG;
}
hr = _settings.Warnings().Size() == 0 ? S_OK : S_FALSE;
_warnings.clear();
for (uint32_t i = 0; i < _settings.Warnings().Size(); i++)
{
_warnings.push_back(_settings.Warnings().GetAt(i));
}
_hasSettingsStartupActions = false;
const auto startupActions = _settings.GlobalSettings().StartupActions();
if (!startupActions.empty())
{
_settingsAppArgs.FullResetState();
ExecuteCommandlineArgs args{ _settings.GlobalSettings().StartupActions() };
auto result = _settingsAppArgs.ParseArgs(args);
if (result == 0)
{
_hasSettingsStartupActions = true;
// Validation also injects new-tab command if implicit new-tab was provided.
_settingsAppArgs.ValidateStartupCommands();
}
else
{
_warnings.push_back(SettingsLoadWarnings::FailedToParseStartupActions);
}
}
hr = _warnings.empty() ? S_OK : S_FALSE;
}
catch (const winrt::hresult_error& e)
{
@ -1105,6 +1140,9 @@ namespace winrt::TerminalApp::implementation
const auto result = _appArgs.ParseArgs(args);
if (result == 0)
{
// If the size of the arguments list is 1,
// then it contains only the executable name and no other arguments.
_hasCommandLineArguments = args.size() > 1;
_appArgs.ValidateStartupCommands();
_root->SetStartupActions(_appArgs.GetStartupActions());
}

View file

@ -86,6 +86,7 @@ namespace winrt::TerminalApp::implementation
std::atomic<bool> _settingsReloadQueued{ false };
::TerminalApp::AppCommandlineArgs _appArgs;
::TerminalApp::AppCommandlineArgs _settingsAppArgs;
int _ParseArgs(winrt::array_view<const hstring>& args);
void _ShowLoadErrorsDialog(const winrt::hstring& titleKey, const winrt::hstring& contentKey, HRESULT settingsLoadedResult);
@ -107,6 +108,10 @@ namespace winrt::TerminalApp::implementation
void _ApplyTheme(const Windows::UI::Xaml::ElementTheme& newTheme);
bool _hasCommandLineArguments{ false };
bool _hasSettingsStartupActions{ false };
std::vector<Microsoft::Terminal::Settings::Model::SettingsLoadWarnings> _warnings;
// These are events that are handled by the TerminalPage, but are
// exposed through the AppLogic. This macro is used to forward the event
// directly to them.

View file

@ -253,6 +253,10 @@
<value>Found a "splitPane" command with an invalid "size". This command will be ignored. Make sure the size is between 0 and 1, exclusive.</value>
<comment>{Locked="\"splitPane\"","\"size\""}</comment>
</data>
<data name="FailedToParseStartupActions" xml:space="preserve">
<value>Failed to parse "startupActions".</value>
<comment>{Locked="\"startupActions\""}</comment>
</data>
<data name="CmdCommandArgDesc" xml:space="preserve">
<value>An optional command, with arguments, to be spawned in the new tab or pane</value>
</data>

View file

@ -40,6 +40,7 @@ static constexpr std::string_view AlwaysOnTopKey{ "alwaysOnTop" };
static constexpr std::string_view LegacyUseTabSwitcherModeKey{ "useTabSwitcher" };
static constexpr std::string_view TabSwitcherModeKey{ "tabSwitcherMode" };
static constexpr std::string_view DisableAnimationsKey{ "disableAnimations" };
static constexpr std::string_view StartupActionsKey{ "startupActions" };
static constexpr std::string_view DebugFeaturesKey{ "debugFeatures" };
@ -114,6 +115,7 @@ winrt::com_ptr<GlobalAppSettings> GlobalAppSettings::Copy() const
globals->_AlwaysOnTop = _AlwaysOnTop;
globals->_TabSwitcherMode = _TabSwitcherMode;
globals->_DisableAnimations = _DisableAnimations;
globals->_StartupActions = _StartupActions;
globals->_UnparsedDefaultProfile = _UnparsedDefaultProfile;
globals->_validDefaultProfile = _validDefaultProfile;
@ -300,6 +302,8 @@ void GlobalAppSettings::LayerJson(const Json::Value& json)
JsonUtils::GetValueForKey(json, DisableAnimationsKey, _DisableAnimations);
JsonUtils::GetValueForKey(json, StartupActionsKey, _StartupActions);
// This is a helper lambda to get the keybindings and commands out of both
// and array of objects. We'll use this twice, once on the legacy
// `keybindings` key, and again on the newer `bindings` key.
@ -394,6 +398,7 @@ Json::Value GlobalAppSettings::ToJson() const
JsonUtils::SetValueForKey(json, AlwaysOnTopKey, _AlwaysOnTop);
JsonUtils::SetValueForKey(json, TabSwitcherModeKey, _TabSwitcherMode);
JsonUtils::SetValueForKey(json, DisableAnimationsKey, _DisableAnimations);
JsonUtils::SetValueForKey(json, StartupActionsKey, _StartupActions);
// clang-format on
// TODO GH#8100: keymap needs to be serialized here

View file

@ -86,6 +86,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
GETSET_SETTING(bool, AlwaysOnTop, false);
GETSET_SETTING(Model::TabSwitcherMode, TabSwitcherMode, Model::TabSwitcherMode::InOrder);
GETSET_SETTING(bool, DisableAnimations, false);
GETSET_SETTING(hstring, StartupActions, L"");
private:
guid _defaultProfile;

View file

@ -142,5 +142,9 @@ namespace Microsoft.Terminal.Settings.Model
KeyMapping KeyMap();
Windows.Foundation.Collections.IMapView<String, Command> Commands();
Boolean HasStartupActions();
void ClearStartupActions();
String StartupActions();
}
}

View file

@ -20,6 +20,7 @@ namespace Microsoft.Terminal.Settings.Model
FailedToWriteToSettings = 10,
InvalidColorSchemeInCmd = 11,
InvalidSplitSize = 12,
FailedToParseStartupActions = 13,
WARNINGS_SIZE // IMPORTANT: This MUST be the last value in this enum. It's an unused placeholder.
};

View file

@ -26,6 +26,7 @@
"theme": "system",
"snapToGridOnResize": true,
"disableAnimations": false,
"startupActions": "",
"profiles":
[