-
Notifications
You must be signed in to change notification settings - Fork 8.4k
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
Support environment variables in the settings #15082
Support environment variables in the settings #15082
Conversation
* use StringMap as a container * recursively resolve ${env:NAME} vars in values in the StringMap or in the process' environment * implement some tests
* add comments to ResolveEnvironmentVariableValue * use wil helper * remove unused code
* allow appending or prepending process environment variables * don't handle all exceptions on validation failure
* Use INHERITABLE_SETTING macro
holy shit the madman actually did it |
idle thought before reading the code: the original PR might predate layering. Lets see how this works with layering. Can the defaults say (for example) |
Currently the concrete profile's environment completely replaces the one specified in defaults. So if you've got: "defaults": {
"environment": {
"Foo": "Bar"
}
},
"list": [
{
"name": "PowerShell",
"environment": {
"Baz": "Qux"
}
}
] Your PowerShell profile will get |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
bunch of notes. thanks for bringing this back from the dead @ianjoneill :)
@@ -288,6 +289,7 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation | |||
} | |||
_reloadEnvironmentVariables = winrt::unbox_value_or<bool>(settings.TryLookup(L"reloadEnvironmentVariables").try_as<Windows::Foundation::IPropertyValue>(), | |||
_reloadEnvironmentVariables); | |||
_profileGuid = winrt::unbox_value_or<winrt::guid>(settings.TryLookup(L"profileGuid").try_as<Windows::Foundation::IPropertyValue>(), _profileGuid); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
in an ideal world (which is not the world in which we live), the Connection classes would not have any concept of a "profile". Even so, I'm cool with this since we've committed so many other layering violations in the past five years.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you don't need to do anything about this, i just felt like I had a duty to say it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah - it seemed silly both this and TerminalPage
doing the same dance fiddling with WSLENV
though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmmmm... now that we have the WSLENV
dance happening over all provided environment variables in ConptyConnection
, do you think that we could get away with moving profile GUID up to TerminalPage?
It could become annoying because now we need to copy the user's provided environment map (if there is one! but we do have to copy it because we don't want to edit it inplace since the one living on the profile is durable)... but after all, if TPage provides WT_PROFILE_ID
via the environment map it will automatically show up in WSLENV
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that depends on if we think people will try and override that environment variable.
The keys in the IMap
are case sensitive - so if someone has added say wt_profile_id
as an environment variable, that'll be stored separately - so back in ConptyConnection
one of the two values will be put into the connection's environment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fair!
We can fix the interface later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One potential solution would be to pass two environment variable maps to ConptyConnection
- one containing user variables and one containing "terminal" variables. We'd insert the "terminal" ones into the environment first, and then the user ones. I can implement that as a follow-up if you're happy with that approach (and please say if you have a better name for "terminal" variables too!).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some thoughts before I open Visual Studio
til::env environment; | ||
auto zeroEnvMap = wil::scope_exit([&]() noexcept { | ||
// Can't zero the keys, but at least we can zero the values. | ||
for (auto& [name, value] : environment) | ||
for (auto& [name, value] : environment.as_map()) | ||
{ | ||
::SecureZeroMemory(value.data(), value.size() * sizeof(decltype(value.begin())::value_type)); | ||
} | ||
|
||
environment.clear(); | ||
environment.as_map().clear(); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unless I'm missing something, if we did this as part of regenerate()
the map would be cleared on exit of the method which would mean the map would be populated and immediately cleared.
It would probably make sense to extract this for loop into a clear()
method on til::env
, so that the caller doesn't need to worry about the internal representation.
With regards to whether it's necessary, I can't answer that - I don't know why the code originally did this. It's possible the environment could contain sensitive information (e.g. temporary credentials), which you may want to clear out.
@@ -288,6 +289,7 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation | |||
} | |||
_reloadEnvironmentVariables = winrt::unbox_value_or<bool>(settings.TryLookup(L"reloadEnvironmentVariables").try_as<Windows::Foundation::IPropertyValue>(), | |||
_reloadEnvironmentVariables); | |||
_profileGuid = winrt::unbox_value_or<winrt::guid>(settings.TryLookup(L"profileGuid").try_as<Windows::Foundation::IPropertyValue>(), _profileGuid); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah - it seemed silly both this and TerminalPage
doing the same dance fiddling with WSLENV
though.
Just FYI I should be able to take a look at this tomorrow (Friday). |
This is very subtle (and I am only testing as of >5 hours ago, so please ignore if changed), but you can resurrect inherited environment variables depending on sort order. I don't know if I think this is an issue worth fixing, but it is fun!
|
Oh, no, I'm totally happy with how it works today! I legitimately found it interesting 😄 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I love it. Thanks @ianjoneill and @christapley :)
Just to clarify: as of this PR, it is possible to set environment variables in |
@DHowett Oh, that sucks. Just when I thought that I had finally found a way to easily manage my |
Existing environment variables can be referenced by enclosing the name in percent characters (e.g.
%PATH%
).Resurrects #9287 by @christapley.
Tests added and manually tested.
Closes #2785
Closes #9233
Co-authored-by: Chris Tapley chris.tapley.81@gmail.com