Skip to content

Commit

Permalink
Introduce startupActions in settings (#8770)
Browse files Browse the repository at this point in the history
Procedural solution for #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: MicrosoftDocs/terminal#217
  • Loading branch information
Don-Vito authored Jan 15, 2021
1 parent 9aea904 commit 3c044f2
Show file tree
Hide file tree
Showing 9 changed files with 67 additions and 4 deletions.
4 changes: 4 additions & 0 deletions doc/cascadia/profiles.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -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": {
Expand Down
46 changes: 42 additions & 4 deletions src/cascadia/TerminalApp/AppLogic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"),
Expand Down Expand Up @@ -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&&) {
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -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());
}
Expand Down
5 changes: 5 additions & 0 deletions src/cascadia/TerminalApp/AppLogic.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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.
Expand Down
4 changes: 4 additions & 0 deletions src/cascadia/TerminalApp/Resources/en-US/Resources.resw
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down
5 changes: 5 additions & 0 deletions src/cascadia/TerminalSettingsModel/GlobalAppSettings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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" };

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions src/cascadia/TerminalSettingsModel/GlobalAppSettings.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
4 changes: 4 additions & 0 deletions src/cascadia/TerminalSettingsModel/GlobalAppSettings.idl
Original file line number Diff line number Diff line change
Expand Up @@ -142,5 +142,9 @@ namespace Microsoft.Terminal.Settings.Model
KeyMapping KeyMap();

Windows.Foundation.Collections.IMapView<String, Command> Commands();

Boolean HasStartupActions();
void ClearStartupActions();
String StartupActions();
}
}
1 change: 1 addition & 0 deletions src/cascadia/TerminalSettingsModel/TerminalWarnings.idl
Original file line number Diff line number Diff line change
Expand Up @@ -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.
};

Expand Down
1 change: 1 addition & 0 deletions src/cascadia/TerminalSettingsModel/defaults.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"theme": "system",
"snapToGridOnResize": true,
"disableAnimations": false,
"startupActions": "",

"profiles":
[
Expand Down

0 comments on commit 3c044f2

Please sign in to comment.