Commit graph

44 commits

Author SHA1 Message Date
Carlos Zamora 2608e94822
Introduce TerminalSettingsModel project (#7667)
Introduces a new TerminalSettingsModel (TSM) project. This project is
responsible for (de)serializing and exposing Windows Terminal's settings
as WinRT objects.

## References
#885: TSM epic
#1564: Settings UI is dependent on this for data binding and settings access
#6904: TSM Spec

In the process of ripping out TSM from TerminalApp, a few other changes
were made to make this possible:
1. AppLogic's `ApplicationDisplayName` and `ApplicationVersion` was
   moved to `CascadiaSettings`
   - These are defined as static functions. They also no longer check if
     `AppLogic::Current()` is nullptr.
2. `enum LaunchMode` was moved from TerminalApp to TSM
3. `AzureConnectionType` and `TelnetConnectionType` were moved from the
   profile generators to their respective TerminalConnections
4. CascadiaSettings' `SettingsPath` and `DefaultSettingsPath` are
   exposed as `hstring` instead of `std::filesystem::path`
5. `Command::ExpandCommands()` was exposed via the IDL
   - This required some of the warnings to be saved to an `IVector`
     instead of `std::vector`, among some other small changes.
6. The localization resources had to be split into two halves.
   - Resource file linked in init.cpp. Verified at runtime thanks to the
     StaticResourceLoader.
7. Added constructors to some `ActionArgs`
8. Utils.h/cpp were moved to `cascadia/inc`. `JsonKey()` was moved to
   `JsonUtils`. Both TermApp and TSM need access to Utils.h/cpp.

A large amount of work includes moving to the new namespace
(`TerminalApp` --> `Microsoft::Terminal::Settings::Model`).

Fixing the tests had its own complications. Testing required us to split
up TSM into a DLL and LIB, similar to TermApp. Discussion on creating a
non-local test variant can be found in #7743.

Closes #885
2020-10-06 09:56:59 -07:00
Carlos Zamora abf8805e00
Introduce KeyMapping and Move TerminalSettings construction (#7537)
`KeyMapping` was introduced to break up `AppKeyBindings`. `KeyMapping`
records the keybindings from the JSON and lets you query them.
`AppKeyBindings` now just holds a `ShortcutActionDispatcher` to run
actions, and a `KeyMapping` to record/query your existing keybindings.
This refactor allows `KeyMapping` to be moved to the
TerminalSettingsModel, and `ShortcutActionDispatcher` and
`AppKeyBindings` will stay in TerminalApp.

`AppKeyBindings` had to be passed down to a terminal via
`TerminalSettings`. Since each settings object had its own
responsibility to update/create a `TerminalSettings` object, I moved all
of that logic to `TerminalSettings`. This helps with the
TerminalSettingsModel refactor, and makes the construction of
`TerminalSettings` a bit cleaner and more centralized.

## References
#885 - this is all in preparation for the TerminalSettingsModel

## Validation Steps Performed
- [x] Tests passed
- [X] Deployment succeeded
2020-09-14 20:38:56 +00:00
Carlos Zamora 892cf05fe6
Add serialization error handling to settings projection layer (#7576)
Now that CascadiaSettings is a WinRT object, we need to update the error
handling a bit. Making it a WinRT object limits our errors to be
hresults. So we moved all the error handling down a layer to when we
load the settings object.

- Warnings encountered during validation are saved to `Warnings()`.
- Errors encountered during validation are saved to `GetLoadingError()`.
- Deserialization errors (mainly from JsonUtils) are saved to
  `GetDeserializationErrorMessage()`.

## References
#7141 - CascadiaSettings is a settings object
#885 - this makes ripping out CascadiaSettings into
     TerminalSettingsModel much easier

## Validation Steps Performed
* [x] Tests passed
- [x] Deployment succeeded
   - tested with invalid JSON (deserialization error)
   - tested with missing DefaultProfile (validation error)
2020-09-10 17:57:02 -07:00
Carlos Zamora c5cf7b817a
Make CascadiaSettings a WinRT object (#7457)
CascadiaSettings is now a WinRT object in the TerminalApp project.

## References
#7141 - CascadiaSettings is a settings object
#885 - this new settings object will be moved to a new TerminalSettingsModel project

This one _looks_ big, but most of it is really just propagating the
changes to the tests. In fact, you can probably save yourself some time
because the tests were about an hour of Find&Replace.

`CascadiaSettings::GetCurrentAppSettings()` was only being used in
Pane.cpp. So I ripped out the 3 lines of code and stuffed them in there.

Follow-up work:
- There's a few places in AppLogic where I `get_self` to be able to get
  the warnings out. This will go away in the next PR (wrapping up #885)

## Validation Steps Performed
- [x] Tests passed
- [X] Deployment succeeded

Closes #7141
2020-09-09 20:49:53 +00:00
Carlos Zamora 7803efa6fe
Make GlobalAppSettings a WinRT object (#7349)
GlobalAppSettings is now a WinRT object in the TerminalApp project.

## References
#7141 - GlobalAppSettings is a settings object
#885 - this new settings object will be moved to a new TerminalSettingsModel project

## PR Checklist
* [x] Tests passed

## Detailed Description of the Pull Request / Additional comments
This one was probably the easiest thus far.

The only weird thing is how we handle InitialPosition. Today, we lose a
little bit of fidelity when we convert from LaunchPosition (int) -->
Point (float) --> RECT (long). The current change converts
LaunchPosition (optional<long>) --> InitialPosition (long) --> RECT
(long).

NOTE: Though I could use LaunchPosition to go directly from TermApp to
AppHost, I decided to introduce InitialPosition because LaunchPosition
will be a part of TerminalSettingsModel soon.

## Validation Steps Performed
- [x] Tests passed
- [x] Deployment succeeded
2020-08-28 03:49:16 +00:00
Carlos Zamora a51091c615
Make Profile a WinRT object (#7283)
Profile is now a WinRT object in the TerminalApp project.

As with ColorScheme, all of the serialization logic is not exposed via
the idl. TerminalSetingsModel will handle it when it's all moved over.

I removed the "Get" and "Set" prefixes from all of the Profile
functions. It just makes more sense to use the `GETSET_PROPERTY` macro
to do most of the work for us.

`CloseOnExitMode` is now an enum off of the Profile.idl.

`std::optional<wstring>` got converted to `hstring` (as opposed to
`IReference<hstring>`). `IReference<hstring>` is not valid to MIDL.

## References
#7141 - Profile is a settings object
#885 - this new settings object will be moved to a new TerminalSettingsModel project

## Validation Steps Performed
- [x] Tests passed
- [x] Deployment succeeded

Closes #7435
2020-08-28 01:09:22 +00:00
Carlos Zamora e9a7053629
Make ColorScheme a WinRT object (#7238)
ColorScheme is now a WinRT object.

All of the JSON stuff can't be exposed via the idl. So the plan here is
that we'll have the TerminalSettingsModel project handle all of the
serialization when it's moved over. These functions will be exposed off
of the `implementation` namespace, not projected namespace.

References #7141 - ColorScheme is a settings object
References #885 - this new settings object will be moved to a new
TerminalSettingsModel project

## Validation Steps Performed
- [x] Tests passed
- [x] Deployment succeeded
2020-08-14 17:54:35 -07:00
Dustin L. Howett 7ccd1f6f1a
Display meaningful errors when JSON types don't match (#7241)
This pull request completes (and somewhat rewrites) the JsonUtils error
handling arc. Deserialization errors, no longer represented by trees of
exceptions that must be rethrown and caught, are now transformed at
catch time into a message explaining what we expected and where we
expected it.

Instead of exception trees, a deserialization failure will result in a
single type of exception with the originating JSON object from which we
can determine the contents and location of the failure.

Because most of the error message actually comes from the JSON schema
or the actual supported types, and the other jsoncpp errors are not
localized I've made the decision to **not** localize these messages.
2020-08-11 19:50:13 +00:00
Mike Griese aee803e694
Add support for changing the active color scheme with an action (#6993)
## Summary of the Pull Request

Adds the `setColorScheme` action, to change the color scheme of the active control to one given by the `name` parameter. `name` is required. If `name` is not the name of a color scheme, the action does nothing.

## References

* Being done as a stepping stone to #6689 

## PR Checklist
* [x] Closes #5401
* [x] I work here
* [ ] Tests added/passed
* [n/a] Requires documentation to be updated

## Detailed Description of the Pull Request / Additional comments

Technically, the action is being done by changing the settings of the current `TerminalSettings` of the `TermControl`. Frankly, it should be operating on a copy of the `TermControl`'s `IControlSettings`, then updating the control's settings, or the Control should just listen for changes to it's setting's properties, and update in real time (without a manual call to `UpdateSettings`. However, both those paths are somewhere unknowable beyond #6904, so we'll just do this for now.

## Validation Steps Performed

* tested manually with a scheme that exists
* tested manually with a scheme that doesn't exist
2020-08-10 16:21:56 +00:00
Carlos Zamora eb8bb09e5b
Move TerminalSettings object to TermApp Project (#7163)
Move TerminalSettings object from TerminalSettings project
(Microsoft.Terminal.Settings) to TerminalApp project. `TerminalSettings`
specifically operates as a bridge that exposes any necessary information
to a TerminalControl.

Closes #7139 
Related Epic: #885
Related Spec: #6904

## PR Checklist
* [X] Closes #7139 
* [X] CLA signed
* [X] Tests ~added~/passed (no additional tests necessary)
* [X] ~Documentation updated~
* [X] ~Schema updated~

## Validation Steps Performed
Deployed Windows Terminal and opened a few new tabs.
2020-08-03 22:54:22 +00:00
Dustin L. Howett 80da24ecf8
Replace basic_string_view<T> with span<const T> (#6921)
We were using std::basic_string_view as a stand-in for std::span so that
we could change over all at once when C++20 dropped with full span
support. That day's not here yet, but as of 54a7fce3e we're using GSL 3,
whose span is C++20-compliant.

This commit replaces every instance of basic_string_view that was not
referring to an actual string with a span of the appropriate type.

I moved the `const` qualifier into span's `T` because while
`basic_string_view.at()` returns `const T&`, `span.at()` returns `T&`
(without the const). I wanted to maintain the invariant that members of
the span were immutable.

* Mechanical Changes
   * `sv.at(x)` -> `gsl::at(sp, x)`
   * `sv.c{begin,end}` -> `sp.{begin,end}` (span's iterators are const)

I had to replace a `std::basic_string<>` with a `std::vector<>` in
ConImeInfo, and I chose to replace a manual array walk in
ScreenInfoUiaProviderBase with a ranged-for. Please review those
specifically.

This will almost certainly cause a code size regression in Windows
because I'm blowing out all the PGO counts. Whoops.

Related: #3956, #975.
2020-07-15 16:40:42 +00:00
Mike Griese ceeaadc311
Add some trace logging concerning which schemes are in use (#6803)
## Summary of the Pull Request

Let's try and figure out just how many people are actually using Solarized. I emailed @DHowett about this a week ago, but otherwise we don't really have any other tasks for this.

## PR Checklist
* [x] I work here
* [n/a] Requires documentation to be updated
2020-07-07 17:01:42 +00:00
Dustin L. Howett (MSFT) 9ed776bf3e
Allow the default profile to be specified by name (#5706)
## Summary of the Pull Request

This looks like a big diff, but there's a bunch of existing code that
just got moved around, and there's a cool new Utils template.

The tests all pass, and this passed manual validation. I tried weird
things like "making a profile named `{                            }`"
(w/ enough spaces to look like a guid), and yeah it doesn't let you
specify that one as a name, but _why would you do that?!_

Okay, this pull request abstracts the conversion of a profile name into
an optional profile guid out of the "New Terminal Tab Args" handler and
into a common space for all of CascadiaSettings to use.

It also cleans up the conversion of indices and names into optional
GUIDs and turns _those_ into further helpers.

It also introduces a cool new template for running value_or multiple
times on a chain of optionals. CoalesceOptionals is a "choose first,
with fallback" for N>1 optionals.

On top of all this, I've built support for an "unparsed default GUID":
we load the user's defaultProfile as a string, and as part of settings
validation we unpack that string using the helpers outlined above.

## References

Couples well with #5690.

## PR Checklist
* [x] Incidentally fixes #2876
* [x] Core Contributor
* [x] Tests added/passed
* [x] Requires documentation to be updated (done)
* [x] I've discussed this with core contributors already

## Validation Steps Performed

Added additional test collateral to make sure that this works.
2020-06-01 20:26:00 +00:00
pi1024e fb22eae072
Add explicit identifier to some constructors (#5652)
If a class has a constructor which can be called with a single argument,
then this constructor becomes conversion constructor because such a
constructor allows conversion of the single argument to the class being
constructed. To ensure these constructors are passed the argument of its
type, I labeled them explicit.

In some header files, there were constructors that took a value that
could involve implicit conversions, so I added explicit to ensure that
does not happen.
2020-04-29 16:50:47 -07:00
Mike Griese d6cae40d26
Add a warning about using the globals property (#5597)
This property was deprecated in 0.11. We probably should have also added a warning
message to help the community figure out that this property is gone and won't work
anymore.

This PR adds that warning.

* I'm not going to list the enormous number of duped threads _wait yes I am_
    * #5581
    * #5547
    * #5555
    * #5557
    * #5573 
    * #5532
    * #5527
    * #5535 
    * #5510
    * #5511
    * #5512
    * #5513
    * #5516
    * #5515
    * #5521 
    * This literally isn't even all of them 

* [x] Also mainly related to #5458
* [x] I work here
* [x] Tests added/passed
2020-04-27 22:20:18 +00:00
Dustin L. Howett (MSFT) 52d6c03e64
Patch the default profile and version into the settings template (#5232)
This pull request introduces unexpanded variables (`%DEFAULT_PROFILE%`,
`%VERSION%` and `%PRODUCT%`) to the user settings template and code to
expand them.

While doing this, I ran into a couple things that needed to widen from
accepting strings to accepting string views. I also had to move
application name and version detection up to AppLogic and expose the
AppLogic singleton.

The dynamic profile generation logic had to be moved to before we inject
the templated variables, as the new default profile depends on the
generated dynamic profiles.

References #5189, #5217 (because it has a dependency on `VERSION` and
`PRODUCT`).

## PR Checklist
* [x] Closes #2721 
* [x] CLA signed
* [x] Tests added/passed
* [ ] Requires documentation to be updated
* [x] I've discussed this with core contributors already

## Validation Steps Performed
Deleted my settings and watched them regenerate.
2020-04-07 11:35:05 -07:00
Dustin L. Howett (MSFT) 64489b1ec1
rename profiles.json to settings.json, clean up the defaults (#5199)
This pull request migrates `profiles.json` to `settings.json` and removes the legacy roaming AppData settings migrator.

It also:

* separates the key bindings in defaults.json into logical groups
* syncs the universal terminal defaults with the primary defaults
* removes some stray newlines that ended up at the beginning of settings.json and defaults.json

Fixes #5186.
Fixes #3291.

### categorize key bindings

### sync universal with main

### kill stray newlines in template files

### move profiles.json to settings.json

This commit also changes Get*Settings from returning a string to
returning a std::filesystem::path. We gain in expressiveness without a
loss in clarity (since path still supports .c_str()).

NOTE: I tried to do an atomic rename with the handle open, but it didn't
work for reparse points (it moves the destination of a symbolic link
out into the settings folder directly.)

(snip for atomic rename code)

```c++
auto path{ pathToSettingsFile.wstring() };
auto renameBufferSize{ sizeof(FILE_RENAME_INFO) + (path.size() * sizeof(wchar_t)) };
auto renameBuffer{ std::make_unique<std::byte[]>(renameBufferSize) };
auto renameInfo{ reinterpret_cast<FILE_RENAME_INFO*>(renameBuffer.get()) };
renameInfo->Flags = FILE_RENAME_FLAG_REPLACE_IF_EXISTS | FILE_RENAME_FLAG_POSIX_SEMANTICS;
renameInfo->RootDirectory = nullptr;
renameInfo->FileNameLength = gsl::narrow_cast<DWORD>(path.size());
std::copy(path.cbegin(), path.cend(), std::begin(renameInfo->FileName));

THROW_IF_WIN32_BOOL_FALSE(SetFileInformationByHandle(hLegacyFile.get(),
                          FileRenameInfo,
                          renameBuffer.get(),
                          gsl::narrow_cast<DWORD>(renameBufferSize)));
```

(end snip)

### Stop resurrecting dead roaming profiles
2020-04-01 19:09:42 +00:00
Mike Griese 99fa9460fd
Gracefully handle json data with the wrong value types (#4961)
## Summary of the Pull Request

Currently, if the Terminal attempts to parse a setting that _should_ be a `bool`
and the user provided a string, then we'll throw an exception while parsing the
settings, and display an error message that's pretty unrelated to the actual
problem.

The same goes for `bool`s as `int`s, `float`s as `int`s, etc.

This PR instead updates our settings parsing to ensure that we check the type of
a json value before actually trying to get its parsed value.

## References

## PR Checklist
* [x] Closes #4299
* [x] I work here
* [x] Tests added/passed
* [n/a] Requires documentation to be updated

## Detailed Description of the Pull Request / Additional comments

I made a bunch of `JsonUtils` helpers for this in the same vein as the
`GetOptionalValue` ones.

Notably, any other value type can safely be treated as a string value.

## Validation Steps Performed
* added tests
* ran the Terminal and verified we can parse settings with the wrong types
2020-03-20 20:35:51 +00:00
msftbot[bot] 2cba4c628e
Add warning messages for bad keybindings (#4746)
## Summary of the Pull Request

Adds warning messages for a pair of keybindings-related scenarios. This covers the following two bugs:
* #4239 - If the user has supplied more than one key chord in their `"keys"` array.
* #3522 - If a keybinding has a _required_ argument, then we'll display a message to the user
  - currently, the only required parameter is the `direction` parameter for both `resizePane` and `moveFocus`

## References

When we get to #1334, we'll want to remove the `TooManyKeysForChord` warning.

## PR Checklist
* [x] Closes #4239
* [x] Closes #3522
* [x] I work here
* [x] Tests added/passed
* [n/a] Requires documentation to be updated

![image](https://user-images.githubusercontent.com/18356694/75593132-f18ec700-5a49-11ea-9d26-6acd0d28b0b7.png)


## Validation Steps Performed
Tested manually, added tests.
2020-03-05 21:06:58 +00:00
Michael Kitzan 77dd51af39 Fix crash related to unparseable/invalid media resource paths (#4194)
WT crashes when an unparseable/invalid `backgroundImage` or `icon`
resource path is provided in `profiles.json`. This PR averts the crash
by the validating and correcting resource paths as a part of the
`_ValidateSettings()` function in `CascadiaSettings`.
`_ValidateSettings()` is run on start up and any time `profiles.json` is
changed, so a user can not change a file path and avoid the validation
step. 

When a bad `backgroundImage` or `icon` resource path is detected, a
warning screen will be presented.

References #4002, which identified a consistent repro for the crash.

To validate the resource, a `Windows::Foundation::Uri` object is
constructed with the path. The ctor will throw if the resource path is
invalid. Whether or not this validation method is robust enough is a
subject worth review. The correction method for when a bad resource path
is detected is to reset the `std::optional<winrt::hstring>` holding the
file path. 

The text in the warning display was cribbed from the text used when an
invalid `colorScheme` is used. Whether or not the case of a bad
background image file path warrants a warning display is a subject worth
review.

Ensured the repro steps in #4002 did not trigger a crash. Additionally,
some potential backdoor paths to a crash were tested: 

- Deleting the file of a validated background image file path
- Changing the actual file name of a validated background image file
  path
- Replacing the file of a validated background image file path with a
  non-image file (of the same name)
- Using a non-image file as a background image

In all the above cases WT does not crash, and instead defaults to the
background color specified in the profile's `colorScheme`. This PR does
not implement this recovery behavior (existing error catching code
does).

Closes #2329
2020-01-16 17:48:37 -08:00
Mike Griese 3fcc935782 Fix unittesting our .xaml classes (#4105)
## Summary of the Pull Request

New year, new unittests.

This PR introduces a new project, `TestHostApp`. This project is largely taken from the TAEF samples, and allows us to easily construct a helper executable and `resources.pri` for running TerminalApp unittests.

## References

## PR Checklist
* [x] Closes #3986
* [x] I work here
* [x] is Tests
* [n/a] Requires documentation to be updated
* [x] **Waiting for an updated version of TAEF to be available**

## Detailed Description of the Pull Request / Additional comments

Unittesting for the TerminalApp project has been a horrifying process to try getting everything pieced together just right. Dependencies need to get added to manifests, binplaced correctly, and XAML resources need to get compiled together as well. In addition, using a MUX `Application` (as opposed to the Windows.UI.Xaml `Application`) has led to additional problems. 

This was always a horrifying house of cards for us. Turns out, the reason this was so horrible is that the test infrastructure for doing what we're doing _literally didn't exist_ when I started doing all that work last year.

So, with help from the TAEF team, I was able to get rid of our entire house of cards, and use a much simpler project to build and run the tests.

Unfortunately, the latest TAEF release has a minor bug in it's build rules, and only publishes the x86 version of a dll we need from them. But, the rest of this PR works for x86, and I'll bump this when that updated version is available. We should be able to review this even in the state it's in.

## Validation Steps Performed
ran the tests yo
2020-01-10 18:55:31 +00:00
Mike Griese 3ccc999e1f Add support for "User Default" settings II (#3892)
## Summary of the Pull Request

_This is attempt 2 at this feature_. The original PR can be found at #3369. 

These are settings that apply to _every_ profile, before user customizations. 

If the user wants to add "default profile settings", they can make the `"profiles"` property an _object_, instead of a list, and add `"defaults"` key underneath that object. The users list of profiles should then be under the `list` property of the `profiles` object.

## References
#2515, #2603, #3369, #3569

## PR Checklist
* [x] Closes #2325
* [x] I work here
* [x] Tests added/passed
* [x] schema, docs updated

## Detailed Description of the Pull Request / Additional comments
~~Discussion in #2325 itself serves as the "spec" for this task. I thought we'd need more discussion on the topic, but it ended up being pretty straightforward.~~

I should not have said that in the original PR. We've had a better spec review now that I think we're happier with.

## Validation Steps Performed
_ran the tests_
2019-12-11 00:39:29 +00:00
Michael Niksa 402b7ff0e0
Create Telnet connection type and default loopback profile for… (#3858)
For our Universal terminal for development purposes, we will use telnet to escape the universal application container and empower developers to debug/diagnose issues with their own machine on loopback to the already-elevated telnet context.
2019-12-09 11:07:08 -08:00
Mike Griese dd1c7b3e52 Add support for new panes with specifc profiles and other settings overrides (#3825)
## Summary of the Pull Request


This enables the user to set a number of extra settings in the `NewTab` and `SplitPane` `ShortcutAction`s, that enable customizing how a new terminal is created at runtime. The following four properties were added:
* `profile`
* `commandline`
* `tabTitle`
* `startingDirectory`

`profile` can be used with either a GUID or the name of a profile, and the action will launch that profile instead of the default.

`commandline`, `tabTitle`, and `startingDirectory` can all be used to override the profile's values of those settings. This will be more useful for #607.

With this PR, you can make bindings like the following:

```json

{ "keys": ["ctrl+a"], "command": { "action": "splitPane", "split": "vertical" } },
{ "keys": ["ctrl+b"], "command": { "action": "splitPane", "split": "vertical", "profile": "{6239a42c-1111-49a3-80bd-e8fdd045185c}" } },
{ "keys": ["ctrl+c"], "command": { "action": "splitPane", "split": "vertical", "profile": "profile1" } },
{ "keys": ["ctrl+d"], "command": { "action": "splitPane", "split": "vertical", "profile": "profile2" } },
{ "keys": ["ctrl+e"], "command": { "action": "splitPane", "split": "horizontal", "commandline": "foo.exe" } },
{ "keys": ["ctrl+f"], "command": { "action": "splitPane", "split": "horizontal", "profile": "profile1", "commandline": "foo.exe" } },
{ "keys": ["ctrl+g"], "command": { "action": "newTab" } },
{ "keys": ["ctrl+h"], "command": { "action": "newTab", "startingDirectory": "c:\\foo" } },
{ "keys": ["ctrl+i"], "command": { "action": "newTab", "profile": "profile2", "startingDirectory": "c:\\foo" } },
{ "keys": ["ctrl+j"], "command": { "action": "newTab", "tabTitle": "bar" } },
{ "keys": ["ctrl+k"], "command": { "action": "newTab", "profile": "profile2", "tabTitle": "bar" } },
{ "keys": ["ctrl+l"], "command": { "action": "newTab", "profile": "profile1", "tabTitle": "bar", "startingDirectory": "c:\\foo", "commandline":"foo.exe" } }
```

## References

This is a lot of work that was largely started in pursuit of #607. We want people to be able to override these properties straight from the commandline. While they may not make as much sense as keybindings like this, they'll make more sense as commandline arguments.

## PR Checklist
* [x] Closes #998
* [x] I work here
* [x] Tests added/passed
* [x] Requires documentation to be updated

## Validation Steps Performed
There are tests 🎉

Manually added some bindings, they opened the correct profiles in panes/tabs
2019-12-09 13:02:29 +00:00
Michael Kitzan e9a3fe5578 FindGuid helper function (#3762)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
## Summary of the Pull Request
Adds a simple helper function to look up the GUID associated with a profile name.

<!-- Other than the issue solved, is this relevant to any other issues/existing PRs? --> 
## References

<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [x] Closes #3680
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [x] Tests added/passed. Yes, new test group in `SettingsTests`!
* [ ] Requires documentation to be updated
* [x] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #3680

<!-- Provide a more detailed description of the PR, other things fixed or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments
Very simple function, for-each through profiles checking for a match. Returns the associated GUID if found, else returns the null GUID.

This function is marked as `noexcept` to comply with assumption made by other `CascadiaSettings` functions that [`Profiles::GetGuid`](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalApp/Profile.cpp#L141) does not throw, despite it throwing.

<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
The new function is simple and can be visually validated, but added tests regardless. A new test group was added in `SettingsTests` called `TestHelperFunctions` to validate the new function `FindGuid` and older function `FindProfile`. This test group could be used to validate more helper functions in `CascadiaSettings` as they're added. The new test group passes after running `te.exe TerminalApp.LocalTests.dll`. 


--------------------------------------------

* Added FindGuid helper function

* Style change

* Tests for FindGuid and FindProfile

* Fixed code format?

* Code format guess

No feedback from the Azure pipeline

* optional<GUID> fix

* Updated function desc
2019-12-02 08:24:21 -06:00
Dustin L. Howett (MSFT) 901a1e1a09
Implement ConnectionState and closeOnExit=graceful/always/never (#3623)
This pull request implements the new
`ITerminalConnection::ConnectionState` interface (enum, event) and
connects it through TerminalControl to Pane, Tab and App as specified in
#2039. It does so to implement `closeOnExit` = `graceful` in addition to
the other two normal CoE types.

It also:

* exposes the singleton `CascadiaSettings` through a function that
  looks it up by using the current Xaml application's `AppLogic`.
  * In so doing, we've broken up the weird runaround where App tells
    TerminalSettings to CloseOnExit and then later another part of App
    _asks TerminalControl_ to tell it what TerminalSettings said App
    told it earlier. `:crazy_eyes:`
* wires up a bunch of connection state points to `AzureConnection`.
  This required moving the Azure connection's state machine to use another
  enum name (oops).
* ships a helper class for managing connection state transitions.
* contains a bunch of template magic.
* introduces `WINRT_CALLBACK`, a oneshot callback like `TYPED_EVENT`.
* replaces a bunch of disparate `_connecting` and `_closing` members
  with just one uberstate.
* updates the JSON schema and defaults to prefer closeOnExit: graceful
* updates all relevant documentation

Specified in #2039
Fixes #2563

Co-authored-by: mcpiroman <38111589+mcpiroman@users.noreply.github.com>
2019-11-25 14:22:29 -08:00
Mike Griese 5d17557edf Add a warning when a profile has an unknown color scheme (#3033)
Add a warning when the user sets their colorScheme to a scheme that doesn't exist. When that occurs, we'll set their color table to the campbell scheme, to prevent it from being just entirely black.

This commit also switches scheme storage to a map keyed on name.

Closes #2547
2019-10-14 22:02:52 -07:00
Dustin L. Howett (MSFT) 5a57c5a6c9
Add a schema reference to the userDefaults and patch one into user data (#2803)
* Add a schema reference to the userDefaults and patch one into existing files
* Only add the , if there's another object in there.
2019-09-18 18:37:23 -07:00
Mike Griese 0df02343f1
Add Dynamic Profile Generators (#2603)
_**This PR targets the #2515 PR**_. It does that for the sake of diffing. When this PR and #2515 are both ready, I'll merge #2515 first, then change the target of this branch, and merge this one.

<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
## Summary of the Pull Request

This PR adds support for "dynamic profiles", in accordance with the [Cascading Settings Spec](https://github.com/microsoft/terminal/blob/master/doc/cascadia/Cascading-Default-Settings.md#dynamic-profiles). Currently, we have three types of default profiles that fit the category of dynamic profile generators. These are profiles that we want to create on behalf of the user, but require runtime information to be able to create correctly. Because they require runtime information, we can't ship a static version of these profiles as a part of `defaults.json`. These three profile generators are:
* The Powershell Core generator
* The WSL Distro generator
* The Azure Cloud Shell generator

<!-- Other than the issue solved, is this relevant to any other issues/existing PRs? --> 
## References

<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [x] Closes #754
* [x] I work here
* [x] look at all these **Tests**
* [x] Requires documentation to be updated - This is done as part of the parent PR

<!-- Provide a more detailed description of the PR, other things fixed or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments

We want to be able to enable the user to edit dynamic profiles that are generated from DPGs. When dynamic profiles are added, we'll add entries for them to the user's `profiles.json`. We do this _without re-serializing_ the settings. Instead, we insert a partial serialization for the profile into the user's settings. 

### Remaining TODOs:
* Make sure that dynamic profiles appear in the right place in the order of profiles -> #2722
* [x] don't serialize the `colorTable` key for dynamic profiles.
* [x] re-parse the user settings string if we've changed it.
*  Handle changing the default profile to pwsh if it exists on first launch, or file a follow-up issue -> #2721

<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed


<hr>

* Create profiles by layering them

* Update test to layer multiple times on the same profile

* Add support for layering an array of profiles, but break a couple tests

* Add a defaults.json to the package

* Layer colorschemes

  * Moves tests into individual classes
  * adds support for layering a colorscheme on top of another

* Layer an array of color schemes

* oh no, this was missed with #2481

  must have committed without staging this change, uh oh. Not like those tests actually work so nbd

* Layer keybindings

* Read settings from defaults.json + profiles.json, layer appropriately

  This is like 80% of #754. Needs tests.

* Add tests for keybindings

  * add support to unbind a key with `null` or `"unbound"` or `"garbage"`

* Layer or clear optional properties

* Add a helper to get an optional variable for a bunch of different types

  In the end, I think we need to ask _was this worth it_

* Do this with the stretch mode too

* Add back in the GUID check for profiles

* Add some tests for global settings layering

* M A D  W I T H  P O W E R

  Add a MsBuild target to auto-generate a header with the defaults.json as a
  string in the file. That way, we can _always_ load the defaults. Literally impossible to not.

* When the user's profile.json doesn't exist, create it from a template

* Re-order profiles to match the order set in the user's profiles.json

* Add tests for re-ordering profiles to match user ordering

* Add support for hiding profiles using `"hidden": true`

* Use the hardcoded defaults.json for the exception->"use defaults" case

* Somehow I messed up the git submodules?

* woo documentation

* Fix a Terminal.App.Unit.Tests failure

* signed/unsigned is hard

* Use Alt+Settings button to open the default settings

* Missed a signed/unsigned

* Start dynamically creating profiles

* Give the inbox generators a namespace

  and generally hack this a lot less

* Some very preliminary PR feedback

* More PR feedback

  Use the wil helper for the exe path
  Move jsonutils into their own file
  kill some dead code

* Add templates to these bois

* remove some code for generating defaults, reorder defaults.json a tad

* Make guid a std::optional

* Large block of PR feedback

  * Remove some dead code
  * add some comments
  * tag some todos

* stl is love, stl is life

* Serialize the source key

* Make the Azure cloud shell a dynamic profile

* Make the built-in namespaces public

* Add a mechanism for quick-diffing a profile

  This will be used to generate the json snippets for dynamically generated profiles.

* Generate partial serializations of dynamic profiles _not_ in the user settings

* Start writing tests for generating dyn profiles

  * dyn profiles generate GUIDs based on _source
  * we won't run DPGs when they'd disabled?

* Add more DPG tests - TestDontRunDisabledGenerators

* Don't layer profiles with a source that's also different

* Add another test, DoLayerUserProfilesOnDynamicsWhenSourceMatches

* Actually insert new dynamic profiles into the file

* Minor cleanup of `Profile::ShouldBeLayered`

* Migrate legacy profiles gracefully

* using namespace winrt::Windows::UI::Xaml;

* _Only_ layer dynamic profiles from user settings, never create

* Write a test for migrating dynamic profiles

* Comments for dayssssss

* add `-noprofile`

* Fix the crash that dustin found

* -Encoding ASCII

* Set a profile's default scheme to Campbell

* Fix the tests I regressed

* Update UsingJsonSetting.md to reflect that changes from these PRs

* Change how GenerateGuidForProfile works

* Make AppKeyBindings do its own serialization

* Remove leftover dead code from the previous commit

* Fix up an enormous number of PR nits

* Don't layer a profile if the json doesn't have a GUID

* Fix a test I unfixed

* get rid of extraneous bois{};

* Piles of PR feedback

* Collection of PR nits

* PR nits

* Fix a typo; Update the defaults to match #2378

* Tiny nits

* In-den-taition!

* Some typos, PR nits

* Fix this broken defaults case

* Apply suggestions from code review

Co-Authored-By: Carlos Zamora <carlos.zamora@microsoft.com>

* PR nits
2019-09-16 13:34:27 -07:00
Mike Griese 8ba8f35dc5
Add Cascading User + Default Settings (#2515)
This PR represents the start of the work on Cascading User + default settings, #754.

Cascading settings will be done in two parts: 
* [ ] Layered Default+User settings (this PR)
* [ ] Dynamic Profile Generation (#2603).

Until _both_ are done, _neither are going in. The dynamic profiles PR will target this PR when it's ready, but will go in as a separate commit into master.

This PR covers adding one primary feature: the settings are now in two separate files:
* a static `defaults.json` that ships with the package (the "default settings")
* a `profiles.json` with the user's customizations (the "user settings)

User settings are _layered_ upon the settings in the defaults settings.

## References

Other things that might be related here:
* #1378 - This seems like it's definitely fixed. The default keybindings are _much_ cleaner, and without the save-on-load behavior, the user's keybindings will be left in a good state 
* #1398 - This might have honestly been solved by #2475 

## PR Checklist
* [x] Closes #754
* [x] Closes #1378 
* [x] Closes #2566
* [x] I work here
* [x] Tests added/passed
* [x] Requires documentation to be updated - it **ABSOLUTELY DOES**


## Detailed Description of the Pull Request / Additional comments

1. We start by taking all of the `FromJson` functions in Profile, ColorScheme, Globals, etc, and converting them to `LayerJson` methods. These are effectively the same, with the change that instead of building a new object, they are simply layering the values on top of `this` object. 
2. Next, we add tests for layering properties like that.
3. Now, we add a `defaults.json` to the package. This is the file the users can refer to as our default settings.
4. We then take that `defaults.json` and stamp it into an auto generated `.h` file, so we can use it's data without having to worry about reading it from disk.
5. We then change the `LoadAll` function in `CascadiaSettings`. Now, the function does two loads - one from the defaults, and then a second load from the `profiles.json` file, layering the settings from each source upon the previous values.
6. If the `profiles.json` file doesn't exist, we'll create it from a hardcoded `userDefaults.json`, which is stamped in similar to how `defaults.json` is.
7. We also add support for _unbinding_ keybindings that might exist in the `defaults.json`, but the user doesn't want to be bound to anything.
8. We add support for _hiding_ a profile, which is useful if a user doesn't want one of the default profiles to appear in the list of profiles.

## TODO:
* [x] Still need to make Alt+Click work on the settings button
* [x] Need to write some user documentation on how the new settings model works
* [x] Fix the pair of tests I broke (re: Duplicate profiles)


<hr>

* Create profiles by layering them

* Update test to layer multiple times on the same profile

* Add support for layering an array of profiles, but break a couple tests

* Add a defaults.json to the package

* Layer colorschemes

  * Moves tests into individual classes
  * adds support for layering a colorscheme on top of another

* Layer an array of color schemes

* oh no, this was missed with #2481

  must have committed without staging this change, uh oh. Not like those tests actually work so nbd

* Layer keybindings

* Read settings from defaults.json + profiles.json, layer appropriately

  This is like 80% of #754. Needs tests.

* Add tests for keybindings

  * add support to unbind a key with `null` or `"unbound"` or `"garbage"`

* Layer or clear optional properties

* Add a helper to get an optional variable for a bunch of different types

  In the end, I think we need to ask _was this worth it_

* Do this with the stretch mode too

* Add back in the GUID check for profiles

* Add some tests for global settings layering

* M A D  W I T H  P O W E R

  Add a MsBuild target to auto-generate a header with the defaults.json as a
  string in the file. That way, we can _always_ load the defaults. Literally impossible to not.

* When the user's profile.json doesn't exist, create it from a template

* Re-order profiles to match the order set in the user's profiles.json

* Add tests for re-ordering profiles to match user ordering

* Add support for hiding profiles using `"hidden": true`

* Use the hardcoded defaults.json for the exception->"use defaults" case

* Somehow I messed up the git submodules?

* woo documentation

* Fix a Terminal.App.Unit.Tests failure

* signed/unsigned is hard

* Use Alt+Settings button to open the default settings

* Missed a signed/unsigned

* Some very preliminary PR feedback

* More PR feedback

  Use the wil helper for the exe path
  Move jsonutils into their own file
  kill some dead code

* Add templates to these bois

* remove some code for generating defaults, reorder defaults.json a tad

* Make guid a std::optional

* Large block of PR feedback

  * Remove some dead code
  * add some comments
  * tag some todos

* stl is love, stl is life

* add `-noprofile`

* Fix the crash that dustin found

* -Encoding ASCII

* Set a profile's default scheme to Campbell

* Fix the tests I regressed

* Update UsingJsonSetting.md to reflect that changes from these PRs

* Change how GenerateGuidForProfile works

* Make AppKeyBindings do its own serialization

* Remove leftover dead code from the previous commit

* Fix up an enormous number of PR nits

* Fix a typo; Update the defaults to match #2378

* Tiny nits

* Some typos, PR nits

* Fix this broken defaults case
2019-09-16 12:57:10 -07:00
Mike Griese 8096d7cf2f Don't overwrite the settings file (#2475)
This is more trouble than it's worth. We had code before to re-serialize
  settings when they changed, to try and gracefully migrate settings from old
  schemas to new ones. This is good in theory, but with #754 coming soon, this
  is going to become a minefield. In the future we'll just always be providing a
  base schema that's reasonable, so this won't matter so much. Keys that users
  have that aren't understood will just be ignored, and that's _fine_.
2019-08-20 15:46:42 -07:00
Mike Griese d7d96f723a Add Warnings during settings load (#2422)
* Warn the user when their settings are bad

  The start of work on #1348

* Display an error dialog for errors during validation

* Polish for PR

  * Add a ton of tests
  * Polish the _GetMessageText bits
  * Add code to check for duplicate profiles
  * Verify that many warnings work at the same time
  * comments y'all

* Apply fixes for dustin's thoughts from PR

* Add a proper exception type, use an array instead of a map

* PR Fixes

  * Fix x86 build break
  * Add a bit on "using the defaults" when we encountering an exception
  * remove a redundant variable

* guid->GUID

* Address Michael's PR comments

* Clean up this error text, and catch exceptions better

* Update src/cascadia/TerminalApp/Resources/en-US/Resources.resw
2019-08-16 21:21:43 +00:00
Mike Griese 1e4e12507d
Stop Roaming settings (#2298)
* Stop Roaming settings

  Also migrate existing settings from RoamingState to LocalState.

  Fixes #1770.

* * de-dupe these functions
* const a pair of things

* This should be in the previous commit

* use `unique_hfile`'s

* Make some of these wil things cleaner
2019-08-08 17:02:34 -05:00
PankajBhojwani 63347f47fb
The Azure cloud shell connector (#1808)
* We can now connect to the Azure cloud shell #1235
2019-07-25 13:31:41 -07:00
Michael Ratanapintha 66d46ed8ed Allow empty strings and env vars in profile "icon" settings - fixes #1468, #1867 (#2050)
First, I tried reusing the existing ExpandEnvironmentVariableStrings()
helper in TerminalApp/CascadiaSettings.cpp, but then I realized that
WIL already provides its own wrapper for ExpandEnvironmentStrings(),
so instead I deleted ExpandEnvironmentVariableStrings() and replaced
its usages with wil::ExpandEnvironmentStringsW().

I then used wil::ExpandEnvironmentStringsW() when resolving the
icon path as well. In addition, to allow empty strings,
I made changes to treat empty strings for "icon" the same
as JSON `null` or not setting the property at all.

Co-Authored-By: Michael Niksa <miniksa@microsoft.com>
2019-07-25 10:44:58 -07:00
Dustin L. Howett (MSFT) 8d21a75a9e
Switch away from Windows.Storage.ApplicationData (#1293)
This commit drops all of the special packaged app code in
CascadiaSettingsSerialization. It can all be replaced with passing
KF_FLAG_FORCE_APP_DATA_REDIRECTION to SHGetKnownFolderPath, which will
automatically handle the different paths used in packaged context.

We'll still store profiles.json under %APPDATA%\Microsoft\Windows
Terminal in an unpackaged context.

I've also taken the liberty of fixing a settings reload crash. Using the
Application storage APIs would cause us to throw an exception when
profiles.json was deleted, which it absolutely was for certain editors
that do an atomic replace.

Because we're not using W.S.A any more, this cuts down our load time
significantly and fixes all of our known STA/MTA-on-startup issues.

Fixes #1102, #1292.
2019-06-18 11:52:34 -07:00
adiviness 9b92986b49
add clang-format conf to the project, format the c++ code (#1141) 2019-06-11 13:27:09 -07:00
Jeremy Banks 31b614d5b2 Code to add WSLProfiles. (#1050)
* Code to add WSLProfiles.

* Updates recomended by miniksa

* Corrections from Mauve

* More updates from miniska (clarified WaitForSingleObject errors, and moved the try block to the calling function)

* Added THROW_LAST_ERROR for WAIT_FAILED instead of passing an unhandled exception.

* Migrate STL dependancies to LibraryIncludes.h

* Renamed function to provide more clarity

* Set WSL starting directory.

* Default Linux icon and brackets on new lines.

* Added system path so we don't rely on execution from the PATH environment variable.  Removed incorrect error useage.  Removed variable that was not required.

* Remove default directory setting.
2019-06-07 16:12:32 -05:00
Mike Griese 8a69be0cc7
Switch to jsoncpp as our json library (#1005)
Switch to using jsoncpp as our json library. This lets us pretty-print the json file by default, and lets users place comments in the json file.

We will now only re-write the file when the actual logical structure of the json object changes, not only when the serialization changes.

Unfortunately, this will remove any existing ordering of profiles, and make the order random. We don't terribly care though, because when #754 lands, this will be less painful.

It also introduces a top-level globals object to hold all the global properties, including keybindings. Existing profiles should gracefully upgrade.
2019-06-04 16:55:27 -05:00
Mike Griese 2fdcb679ab
Update the default settings (#918)
* Update the default settings

  * [x] `alwaysShowTabs` -> `true`
  * [x] `experimental_showTabsInTitlebar` -> `true`
  * [x] always include Windows Powershell (`background`: `#012456`)
  * [x] include PowerShell Core separately (`background`: unset)
  * [x] drop `Courier New` for powershell
  * [x] drop `experimental_` for `experimental_showTabsInTitlebar`
  * [x] reduce default font size to 10pt.

  Fixes #869
2019-05-23 17:02:32 -05:00
Mike Griese 8dab297bd1
Add an error dialog when we fail to parse settings (#903)
* Load messages from the Resources.resw file
  * Display a message when we fail to parse the settings on an initial parse, or
    on a reload.
2019-05-23 15:09:35 -05:00
Dustin L. Howett (MSFT) 8c3af2d066
Add default icons for the default profiles (#934)
This commit introduces a handful of default icons whose paths will be
emitted into the default profiles.

Icons are named after the profile GUIDs, which for the default profiles
are stable v5 UUIDs based on the name of the profile. The plan is that
we'll never have a duplicate default profile, and if the user wants to
duplicate it they'll need to issue it a new GUID.

Eventually, when icons can be inserted through the settings UI, we can
keep the GUID name (to unique them among all icons for all profiles) and
move them into ms-appdata:///roaming/.

The currently included icons are named for the following profiles:

"cmd" `{0caa0dad-35be-5f56-a8ff-afceeeaa6101}`
"PowerShell Core" `{574e775e-4f2a-5b96-ac1e-a2962a402336}`
"Windows PowerShell" `{61c54bbd-c2c6-5271-96e7-009a87ff44bf}`
"WSL" `{9acb9455-ca41-5af7-950f-6bca1bc9722f}`

The PowerShell profile names aren't being used yet, but this is in
preparation for #918 merging.

Fixes #933.
2019-05-22 13:03:10 -07:00
Dustin L. Howett (MSFT) 8da6737d64
Switch to v5 UUIDs as profile GUIDs for the default profiles (#913)
This commit switches the GUIDs for default profiles from being randomly generated to being version 5 UUIDs. More info in #870.

## PR Checklist
* [x] Closes #870
* [x] CLA signed
* [x] Tests added/passed
* [x] Requires documentation to be updated (#883)
* [x] I've discussed this with core contributors already.

## Detailed Description of the Pull Request / Additional comments
This commit has a number of changes that seem ancillary, but they're general goodness. Let me explain:

* I've added a whole new Types test library with only two tests in
* Since UUIDv5 generation requires SHA1, we needed to take a dependency on bcrypt
* I honestly don't think we should have to link bcrypt in conhost, but LTO should take care of that
  * I considered adding a new Terminal-specific Utils/Types library, but that seemed like a waste
* The best way to link bcrypt turned out to be in line with a discussion @miniksa and I had, where we decided we both love APISets and think that the console should link against them exclusively... so I've added `onecore_apiset.lib` to the front of the link line, where it will deflect the linker away from most of the other libs automagically.

```
StartGroup: UuidTests::TestV5UuidU8String
Verify: AreEqual(uuidExpected, uuidActual)
EndGroup: UuidTests::TestV5UuidU8String [Passed]

StartGroup: UuidTests::TestV5UuidU16String
Verify: AreEqual(uuidExpected, uuidActual)
EndGroup: UuidTests::TestV5UuidU16String [Passed]
```
2019-05-21 13:29:16 -07:00
Dustin Howett d4d59fa339 Initial release of the Windows Terminal source code
This commit introduces all of the Windows Terminal and Console Host source,
under the MIT license.
2019-05-02 15:29:04 -07:00