Compare commits

..

168 Commits

Author SHA1 Message Date
Leonard Hecker
12c6b0a240 Add Oklab based color scheme "Ottosson" (#18502)
Campbell has been the default color scheme for a long time now,
but it has quite some issues with hue and chroma.

This PR introduces a new scheme which was created using the Oklab
color space to find colors with maximal distance to each other
and well distributed and consistent hue and chroma.
Because of this, I've named the scheme after the creator of Oklab.
 
Closes #17818

(cherry picked from commit e60acbc12a)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgW-IC8
Service-Version: 1.21
2025-02-03 17:12:06 -06:00
Dustin L. Howett
580b7b7d36 Update Cascadia Code to 2407.24 (#18499)
This update fixes a hinting issue in Arabic glyphs.

See microsoft/cascadia-code#746 for more details.

(cherry picked from commit bf074f3e40)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgW99Sw
Service-Version: 1.21
2025-02-03 15:20:43 -06:00
Dustin L. Howett
c60a006e77 build: change how we find the latest VC tools version (#18468)
Apparently, we were using the package containing the CRT _source code_
to determine the version of the tools.

Also apparently, VS does not guarantee that that package has the same
version as the tools package.

We should use the version of the tools package instead.

(cherry picked from commit 8e4da6e938)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgWyLAM
Service-Version: 1.21
2025-01-28 17:02:43 -06:00
Carlos Zamora
c9a1f12894 Fix 'closeWindow' ignoring confirmation (#18434)
Reroutes the `closeWindow` action to use the `CloseWindow()` method like
the window's X button does. This includes logic to display the
confirmation dialog.

Also removes `CloseRequested` as it was only used by this action
handler. We already have `CloseWindowRequested` so we're just using that
instead.

## Validation Steps Performed
 `closeWindow` action while multiple tabs opened brings up the
confirmation dialog

Closes #17613

(cherry picked from commit fb7b0e1218)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgWkUeM
Service-Version: 1.21
2025-01-28 17:02:42 -06:00
Javier
318fd6abd6 propsheet: add a CodeQL supression comment (#18431)
CodeQL is raising errors when building Visual Studio since they have a
dependency on Windows Terminal for our integrated terminal. The issue
raised by CodeQL refers to a non-constant string format, but in this
case the string comes from a resource file and should be considered
constant.

(cherry picked from commit 25392ea604)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgWYgYM
Service-Version: 1.21
2025-01-15 14:59:23 -06:00
Carlos Zamora
fd434197f1 Fix tag for SessionBecameInteractive event (#18426)
Adds a description and keyword for the `SessionBecameInteractive` event

Follow-up from #17682

(cherry picked from commit 3772fc3fc5)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgWWlDk
Service-Version: 1.21
2025-01-14 19:59:01 -06:00
Dustin L. Howett
9f0d9a5d14 Teach ServicingPipeline to paginate project board items (#18328)
Oops, it didn't support more than 100 items!

(cherry picked from commit 3e6690290f)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgWLtrI
Service-Version: 1.21
2025-01-08 15:36:29 -06:00
Dustin L. Howett
63e85e84c1 build: add a couple more signing variables to ESRP (#18411)
This is in support of some identity changes we need to make.

(cherry picked from commit a3a4464667)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgWLo5U
Service-Version: 1.21
2025-01-08 15:36:27 -06:00
Carlos Zamora
fc8c6f6802 Add "Windows.Terminal.VisualStudio" to schema (#18322)
Closes #18037

(cherry picked from commit 8598ed78d5)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgVq2uo
Service-Version: 1.21
2024-12-13 14:41:12 -06:00
Javier
64e57344be Add CodeQL suppression comment to propsheet (#18315)
CodeQL is raising errors when building Visual Studio since we have a
dependency on Windows Terminal for our integrated terminal. The issue
raised is not applicable to this case and therefore requires a
suppression comment to ignore the raised error.

(cherry picked from commit 19460f98e0)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgVqzx8
Service-Version: 1.21
2024-12-13 14:29:04 -06:00
Leonard Hecker
cb4403e8b3 Fix infinite recursion in TSF (#18248)
The current `FindWindowOfActiveTSF` implementation can
result in infinite recursion which we must guard again.
This change is not tested as I don't know how to trigger
the issue to begin with (a missing CoreInput thread).

(cherry picked from commit 924310481a)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgVIDM8
Service-Version: 1.21
2024-11-26 13:20:44 -06:00
Tsukasa OI
f62754397d Escape single quotes while translating dropped Win32 paths (#18007)
When file/folder is dropped to the terminal, its path is translated and
quoted with a pair of single quotes if necessary.

However, the terminal control does not escape single quotes (allowed in
the Win32 subsystem) that need escapes when translated.

On the translation styles other than `"none"` (note: all other
translation styles are currently intended for the POSIX shell), it
causes incorrect path to be pasted when the path contains one or more
single quotes (see #18006 for an example).

With this commit, the terminal control escapes a single quote with a
valid escape sequence `'\''` (finish quote, print a single quote then
begin quote again) when the path translation is required.

* Changed escape sequence from `'"'"'` to much shorter `'\''`.
* Reflected comments by the reviewer.

* Overhaul after addition of multiple path translation styles (not just
WSL but Cygwin and MSYS).
* More clarification both in the code and in the commit message.

* Minor clarification both in the code and in the commit message.

* #18006
* #16214
* #18195

This is a follow-up of #16214 and #18195, fixing #18006.

Closes #18006

(cherry picked from commit ae90d52bb1)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgVEvdY
Service-Version: 1.21
2024-11-25 14:58:36 -06:00
Dustin L. Howett
0c98216d2f [<= 1.22] Retain (BUT DON'T INDICATE) orphaned dynamic profiles (#18206)
The original intent with dynamic profiles was that they could be
uninstalled but that Terminal would remember your settings in case they
ever came back.

After we implemented dynamic profile _deletion_, however, we
accidentally made it so that saving your settings after a dynamic
profile disappeared scoured it from the planet _forever_ (since we
remembered that we generated it, but now it was no longer in the
settings file).

This pull request implements:

- Tracking for orphaned dynamic profiles

Closes #14061
Closes #11510
Refs #13916
Refs #9997

Modified for 1.22. I am not including any of the UI affordances.

(cherry picked from commit 90866c7c93)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmQzgU1-p4
Service-Version: 1.22
(cherry picked from commit 2143ca1c92)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgU2frw
Service-Version: 1.21
2024-11-18 16:00:16 -06:00
Dustin L. Howett
ca6af92561 [<= 1.22] Do path translation for multiple types of WSL (#18205)
In #18195, we introduced a real `pathTranslationStyle` setting.

I'm not backporting that whole thing.

(cherry picked from commit e476dd2b9c)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgU2fsY
Service-Version: 1.21
2024-11-18 14:44:44 -06:00
Dustin L. Howett
f4bffcfdb6 wsl: skip distributions that indicate they are "Modern" (#18183)
(cherry picked from commit 00ff803ace)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgUu4sc
Service-Version: 1.21
2024-11-15 10:49:08 -06:00
Carlos Zamora
ef89e13ea9 Fix High Contrast mode in Settings UI (#18130)
"HighContrast" is not a possible requested theme. So `_UpdateBackgroundForMica()` would force the settings UI to be light or dark. To fix this, we just check if we're in high contrast mode and, if so, we don't bother setting the requested theme.

(cherry picked from commit d04381ec05)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgUZ6MY
Service-Version: 1.21
2024-11-15 10:49:06 -06:00
Carlos Zamora
fa91fd6940 Fix High Contrast mode in Command Palette (#18132)
Turns out that having the styles for the KeyChordText and ParsedCommandLineText be empty for high contrast mode caused the issue. Since we're already using theme resources for the colors, we automatically adjust properly to whatever the high contrast theme is (Thanks XAML!).

Bonus points:
- we didn't need the theme dictionaries anymore, so I just moved them to the ResourceDictionary directly
- ParsedCommandLineTextBlockStyle isn't used. So I removed it altogether.

Validated command palette with multiple high contrast themes. See PR thread for demo.

Closes #17914

(cherry picked from commit e83434ff7e)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgUZ6Mk
Service-Version: 1.21
2024-11-15 10:49:03 -06:00
Windows Console Service Bot
91f7063d2d Localization Updates - 10/22/2024 03:06:53 (#18031)
Closes #17752

(cherry picked from commit b58aa26e7a)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgUIJdQ
Service-Version: 1.21
2024-11-15 10:49:01 -06:00
Leonard Hecker
f5b8e98243 Add a policy for profile sources (#18009)
This adds a basic policy check for DisabledProfileSources, so that
organizations can easily disable certain profiles like the Azure one.

Closes #17964

* Add a policy to disable Azure under HKCU. Disabled 
* Add a policy to disable nothing under HKLM. Enabled 
  (...because it overrides the HKCU setting.)

(cherry picked from commit 3a06826915)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgT6i0Y
Service-Version: 1.21
2024-10-17 16:46:40 -05:00
Carlos Zamora
90a9d15659 Fix hiding the icon when it's set to "none" (#18030)
The settings UI and settings model allow you to set the icon to "none"
to hide the icon (you can actually see this effect in the settings UI
when changing the value of the profile icon). However, during settings
validation, "none" is considered a file path, which is then failed to be
parsed, resulting in the icon being marked as invalid and immediately
clearing the value.

This PR fixes this issue by considering "none" to be an accepted value
during validation.

Related to #15843
Closes #17943

## Validation Steps Performed
When an icon is set to "none", ...
 no more warning
 the icon is hidden

(cherry picked from commit 36f064cfc8)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgTyV8A
Service-Version: 1.21
2024-10-17 16:45:00 -05:00
Dustin L. Howett
f16f5133f3 Revert "Stop updating AutoSuggestBox on selection" (#17989)
Reverts microsoft/terminal#17961
Closes #17987
Reopens #17916

(cherry picked from commit b715008de3)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgTiWbM
Service-Version: 1.21
2024-10-08 17:42:58 -05:00
Leonard Hecker
cba3d71378 Add input scope startup setting (#17953)
This adds a "defaultInputScope" setting, hooks it up to our TSF,
and exposes it as a setting in the UI under the startup page.
In order to stay close with the other language setting, I moved that
one from the appearance to the startup page as well.
20 out of the 26 files in this PR are boilerplate unfortunately.

Closes #17816

* Install and use the Chinese IME
* Launch WT
* Chinese input 
* Change setting to `alphanumericHalfWidth`
* Restart WT
* English input 

(cherry picked from commit fc606d2bae)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgTTKAE
Service-Version: 1.21
2024-09-26 15:05:39 -05:00
Windows Console Service Bot
49e96f22be Localization Updates - main - 09/26/2024 19:14:21 (#17958)
Closes #17752
Closes #17764
Closes #17830

(cherry picked from commit 59dc5eff42)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgTX8OQ
Service-Version: 1.21
2024-09-26 14:22:44 -05:00
Leonard Hecker
b690855cf5 Stop updating AutoSuggestBox on selection (#17961)
`AutoSuggestBox` has a `SuggestionChosen` event and any reasonable
person would assume that this means one of the items was chosen.
But with WinUI it's raised whenever a suggestion is merely highlighted.
`QuerySubmitted` is the right event instead. Clearly that naming is
a lot better than `SuggestionChosen`, since the property to get the
chosen item is called `ChosenSuggestion`.
WinUI, like the unrelenting wilderness of a world indifferent to human
suffering, stands as a testament to the futility of human aspiration.

Closes #17916

## Validation Steps Performed
* Type "Casc"
* Move up/down with the arrow keys
* Neither the filtered list nor the text updates 
* Press Enter on an item
* Text updates 

(cherry picked from commit bcac9993cb)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgTW9-g
Service-Version: 1.21
2024-09-26 14:22:43 -05:00
Carlos Zamora
117eb9b8fb Improve color contrast of reset button in SUI (#17912)
Adds a theme resource for the color of the reset button in the settings UI.

Closes #17902

(cherry picked from commit 0bd19e9cfc)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgTTb0s
Service-Version: 1.21
2024-09-26 14:22:42 -05:00
James Holderness
0982abe762 Fix input sequences split across the buffer boundary (#17738)
## Summary of the Pull Request

When conhost receives input from a conpty connection, and that input
arrives in a block larger than our 4K buffer, we can end up with a VT
sequence that's split at the buffer boundary. Previously that could
result in the start of the sequence being dropped, and the remaining
characters being interpreted as individual key presses.

This PR attempts to fix the issue by caching the unprocessed characters
from the start of the sequence, and then combining them with the second
half of the sequence when it's later received.

## Validation Steps Performed

I've confirmed that pasting into vim now works correctly with the sample
data from issue #16655. I've also tested with a `DECCTR` report larger
than 4K which would previously have been corrupted, and which now works
as expected.

## PR Checklist
- [x] Closes #16655

(cherry picked from commit 131728b17d)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgSCpCk
Service-Version: 1.21
2024-09-26 14:22:42 -05:00
Windows Console Service Bot
78c36ca25d Localization Updates - main - regex search (#17349)
(cherry picked from commit 13568e6b73)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgTTOd4
Service-Version: 1.21
2024-09-24 14:54:59 -05:00
Dustin Howett
df9df3d4ee Remove the regex search button (as part of backporting regex fundamentals) 2024-09-24 14:54:59 -05:00
Leonard Hecker
99df9e9444 Stop scrolling on output when search is open (#17885)
* Don't reset the position entirely when changing the needle
* Don't change the scroll position when output arrives
* Don't interfere with the search when output arrives constantly

Closes #17301

## Validation Steps Performed
* In pwsh, run `10000..20000 | % { sleep 0.25; $_ }`
  * You can search for e.g. `1004` and it'll find 10 results. 
  * You can scroll up and down past it and it won't snap back
    when new output arrives. 
* `while ($true) { Write-Host -NoNewline "`e[Ha"; sleep 0.0001; }`
  * You can cycle between the hits effortlessly.  (This tests that
    the constantly reset `OutputIdle` event won't interfere.)
* On input change, the focused result is near the previous one. 

(cherry picked from commit d9131c6889)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgS3elk PVTI_lADOAF3p4s4AmhmszgTEciI
Service-Version: 1.21
2024-09-24 14:38:26 -05:00
e82eric
d1ac37599c Avoid covering current search highlight with search box (#17516)
Adds a scroll offset to avoid hiding the current search highlight with
the search box.
- Offset is based on the number of rows that the search box takes up.
  (I am not totally sure I am calculating this right)
- This won't help when the current highlight is in the first couple
  rows of the buffer.

Fixes: #4407
(cherry picked from commit 0bafab9a0f)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgTTNTE
Service-Version: 1.21
2024-09-24 14:38:24 -05:00
Dustin L. Howett
87c87b51fc Add support for regex search to conhost and Terminal (#17316)
This is broken down into individual reviewable commits.

[Here
is](https://github.com/microsoft/terminal/assets/189190/3b2ffd50-1350-4f3c-86b0-75abbd846969)
a video of it in action!

Part of #3920

(cherry picked from commit ecb5631476)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgTTM0g
Service-Version: 1.21
2024-09-24 14:36:23 -05:00
Mike Griese
dc8a830fea Fix two ConPTY HWND focus issues (#17828)
Worked with @ekoschik on this one.

## Bug the first: the MSAL window `ixptools` spawns

> The auth prompt in pwsh.exe is disabling the terminal window while its
opened and re-enabling it when the window closes. BUT it is enabling
Terminal after dismissing itself, instead of before, which means
terminal is disabled when activated.
>
> Terminal wants focus on the ISLAND window (a grandchild; island is
parented to bridge, which is parented to terminal’s TLW). When it is
activated, it gets a `WM_SETFOCUS` (in response to DefWindowProc
`WM_ACTIVATE`). From `WM_SETFOCUS` it calls `SetFocus` on the bridge
window, and similarly the bridge calls `SetFocus` on the island.
>
> If the TLW is disabled, these `SetFocus` calls fail (see [this
check](#internal-link-redacted) in `SetFocus`). In the case above, this
leaves Terminal’s TLW as focus, and it doesn’t handle keyboard input.
Note that the window IS foreground/active, but because focus is not on
the island it doesn’t see the keyboard input. Another thing to note is
that clicking on the space to the right of the tabs does NOT revive
keyboard input, but clicking on the tabs or main area does.

> **I recommend having the TLW handle WM_ENABLE and call SetFocus on the
island window.**

And guess what, that works!

## Bug the second: When sublime text is the git `EDITOR`, it doesn't
toss focus back to the Terminal

> In this case, Sublime is calling SFW on the pseudo console window. I
don’t have its code, but it is presumably doing something like
SetForegroundWindow(GetConsoleWindow()). This queues an event to the
pseudo window, and when that event is processed the pseudo window
becomes the active and focus window on the queue (which is shared with
Terminal).
>
> The sublime window dismisses itself and does the above SFW call.
Dismissing immediately activates the Terminal TLW, which does the
triple-focus dance (TLW sets focus on itself, then bridge, then island).
This completes but is overwritten immediately when the pseudo window
activates itself. Note that the pseudo window is active at this point
(not the terminal window).

> **I recommend having the Pseudo console window handle WM_ACTIVATE by
calling SetFocus on the island window (and not passing the message to
DefWindowProc).**

And guess what, that works!

----

Closes #15956 (I did test this)
This might be related to #13388, we'll have folks try canary and check

(cherry picked from commit 17a55da0f9)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgSwIkA
Service-Version: 1.21
2024-09-24 14:28:49 -05:00
Leonard Hecker
41bb31f5dc Check EnableHexNumpad before enabling it (#17954)
This just adds a quick registry check for `EnableHexNumpad`.

Depends on #17774
Closes #17762 (again)

## Validation Steps Performed
* Alt + NumpadAdd + 221E doesn't do anything 
* Set the `EnableHexNumpad` registry key
* Restart
* Alt + NumpadAdd + 221E inserts ∞ 

(cherry picked from commit b520da26d4)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgTQsd8
Service-Version: 1.21
2024-09-24 14:07:04 -05:00
Leonard Hecker
6b380cb7e0 ConPTY: Raise the MAX_PATH limit (#17768)
Swapped the `swprintf_s` with no failure checks against a
`str_printf_nothrow` with checks. I also deduplicated the
`CreateProcess` calls since they're mostly identical.

Closes #16860

(cherry picked from commit b3f41626b4)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgS25_o
Service-Version: 1.21
2024-09-17 16:10:25 -05:00
Carlos Zamora
84a33afb8c Fix text scaling issues in settings UI (#17910)
## Summary of the Pull Request
Fixes some issues with truncated text in the settings UI when 200% text
scaling is applied.

For #17897, a minimum height was applied instead of a plain "height".
This ensures that the desired height is applied in general, but under
200% text scaling, we are allowed to grow past that, thus preventing the
truncation of the text.

For #17898, flyouts have a scroll viewer inside them by default. We
actually don't want the scroll viewer because that means the text will
appear "truncated" when in reality, the user is expected to notice the
small scrollbar and scroll horizontally (why that's the default, I will
never know). This PR introduces a new style that can be applied to these
flyouts to cause text wrapping instead of horizontal scrolling. Looked
through the app for any instances where this happens.

For #12006, simply changing the column width from a static value to
"auto" fixes the issue. Frankly, we care more about the text appearing
as a whole (and as whole words). The name of the actions wrap properly
anyways.

Closes #17897
Closes #17898
Closes #12006

(cherry picked from commit a7e47b711a)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgTEfj0
Service-Version: 1.21
2024-09-17 16:05:06 -05:00
Dustin L. Howett
ef586f6bf5 build: fix the TSA configuration (#17929)
We are, quite literally, shipping the org chart.

(cherry picked from commit 2c97c0555d)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgTGRAk
Service-Version: 1.21
2024-09-17 16:05:05 -05:00
Leonard Hecker
bdb67a382a Fix a crash on pane close (#17886)
The underlying issue is that the "Pane" is used both as a model and as
a UI element and so a pane loses its content as soon as it is closed,
but the tree only gets reordered after the animation has finished.
This PR is truly just a hotfix, because it doesn't solve this issue,
it only adds checks to the function that crashes.

Closes #17869
Closes #17871

## Validation Steps Performed
* `Split pane` a few times
* Run the "Close all other panes" action
* Doesn't crash 

(cherry picked from commit bc6f3e2275)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgTEJYE
Service-Version: 1.21
2024-09-16 15:59:32 -05:00
Dustin L. Howett
b6326cf23e Remove PackageES in favor of our own versioning package (#17872)
PackageES is deprecated by known scourge-on-earth OneBranch, and is now
the cause of some non-compliance.

I got permission from them to open-source it, so that's coming next.

For now, we can just depend on a package based on our code based on
theirs.

Tested and working for C++ (DLL, EXE), C#, NuGet and MSIX.

(cherry picked from commit 4aa1624cd2)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgTD8ik
Service-Version: 1.21
2024-09-16 15:59:30 -05:00
Leonard Hecker
e27ebe7681 Fix crash in AppHost::_QuitRequested (#17848)
(cherry picked from commit 00f46e400a)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgSwXpU
Service-Version: 1.21
2024-09-06 18:36:49 -05:00
Leonard Hecker
c47d9e1ad9 Dedup command history by default (#17852)
Under ConPTY we don't load any user settings. `SetUpConsole` notes:
> If we are [ConPTY], we don't want to load any user settings,
> because that could result in some strange rendering results [...]

This enables deduplication by default, which I figured wouldn't cause
any regressions since it's a user-controllable setting anyway, while
it's clearly something the average user wants enabled, for the same
reason that PSReadLine has HistoryNoDuplicates enabled by default.

Closes #17797

## Validation Steps Performed
* Launch conhost, enter 2 commands, press F7, select the older one,
  press Enter, press F7. 2 entries 
* Launch WT, enter 2 commands, press F7, select the older one,
  press Enter, press F7. 2 entries 

(cherry picked from commit 5fdfd51209)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgSN1FM
Service-Version: 1.21
2024-09-04 15:00:54 -05:00
Leonard Hecker
b95cc19e87 Fix typing multiple emojis on Windows 10 (#17213)
On Windows 10 Emojis don't finish composition until the Emoji picker
panel is closed. Each emoji is thus its own composition range.
`firstRange` thus caused only the first emoji to finish composition.
The end result was that all remaining emojis would stay around
forever, with the user entirely unable to clear them.

## Validation Steps Performed
* Windows 10 VM
* Open Emoji picker (Win+.)
* Press and hold Enter on any Emoji
* Press Esc to finish the composition
* All of the Emoji can be backspaced / deleted

(cherry picked from commit 49e4eea60f)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgSLR0g
Service-Version: 1.21
2024-09-04 15:00:54 -05:00
Dustin L. Howett
e8c15683a7 Reapply "nuget: move to shine-oss tenant rather than ms tenant (#17451)"
This reverts commit 67d2636c81.

(cherry picked from commit 955b1d2683)
2024-08-23 15:11:49 -05:00
Windows Console Service Bot
6d4ff2e5a7 Localization Updates - main - 08/22/2024 03:06:16 (#17767)
(cherry picked from commit 0a91023df8)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgSK_vc
Service-Version: 1.21
2024-08-23 14:35:09 -05:00
Leonard Hecker
e60afb6f4e Improve reliability of VT responses (#17786)
* Repurposes `_sendInputToConnection` to send output to the connection
  no matter whether the terminal is read-only or not.
  Now `SendInput` is the function responsible for the UI handling.
* Buffers responses in a VT string into a single string
  before sending it as a response all at once.

This reduces the chances for the UI thread to insert cursor positions
and similar into the input pipe, because we're not constantly unlocking
the terminal lock anymore for every response. The only way now that
unrelated inputs are inserted into the input pipe is because the VT
requests (e.g. DA1, DSR, etc.) are broken up across >1 reads.

This also fixes VT responses in read-only panes.

Closes #17775

* Repeatedly run `echo ^[[c` in cmd.
  DA1 responses don't stack & always stay the same 
* Run nvim in WSL. Doesn't deadlock when pasting 1MB. 
* Run the repro from #17775, which requests a ton of OSC 4
  (color palette) responses. Jiggle the cursor on top of the window.
  Responses never get split up. 

(cherry picked from commit b07589e7a8)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgSK_Dw
Service-Version: 1.21
2024-08-23 14:35:08 -05:00
Dustin L. Howett
1519b6feb2 During Alt+Numpad composition, stash keys in case we bail out (#17774)
We were erroneously eating Alt followed by VK_ADD. This change makes
sure we cache key presses and releases that happen once a numpad
composition is active so that we can send them when you release Alt.

Right now, we only send them when you release Alt after composing Alt
and VK_ADD (entering hex mode) and only if you haven't inserted an
actual hex numpad code. This does mean that `Alt VK_ADD 0 0 H I` will
result in an input of "+hi". That... seems like a small price to pay for
Alt VK_ADD working again.

Closes #17762

(cherry picked from commit e006f75f6c)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgSF50M
Service-Version: 1.21
2024-08-23 14:31:20 -05:00
Leonard Hecker
6d9fb78bfc Implement Alt-Numpad handling (#17637)
This adds an indirection for `_KeyHandler` so that `OnDirectKeyEvent`
can call `_KeyHandler`. This allows us to consistently handle
Alt-key-up events. Then I added custom handling for Alt+ddd (OEM),
Alt+0ddd (ANSI), and Alt+'+'+xxxx (Unicode) sequences, due to the
absence of Alt-key events with xaml islands and our TSF control.

Closes #17327

## Validation Steps Performed
* Tested it according to https://conemu.github.io/en/AltNumpad.html
* Unbind Alt+Space
* Run `showkey -a`
* Alt+Space generates `^[ `
* F7 generates `^[[18~`

(cherry picked from commit 2fab9866b2)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgSCpCg
Service-Version: 1.21
2024-08-23 14:31:18 -05:00
Dustin L. Howett
102181f109 build: switch back to the "latest" OneBranch build image (#17630)
Thanks to a string of compiler bugs, we had to use an older container
image that shipped with VS 17.9.

Unfortunately, that container image is falling further and further out
of date. The build agents don't cache it any longer, so they spend 30-45
minutes of every build pulling it from the registry.

With the changes to ConPTY in #17510 removing the need for til::bitmap,
we no longer need to work around the compiler bugs it exposed.

Furthermore, 17.10.6+ has a much more robust and presumably "working"
compiler.

(cherry picked from commit 39108a7a1b)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgSI7RU
Service-Version: 1.21
2024-08-22 20:21:11 -05:00
Dustin L. Howett
b028a5764b onebranch: allow publish/package to run in :latest container (#17514)
We have to run in an older OneBranch Windows container image due to
compiler bugs.

This change prevents us from having to wait for the container image to
download for build legs that _aren't_ using the compiler.

(cherry picked from commit bc20225b08)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgSI7Rw
Service-Version: 1.21
2024-08-22 20:21:10 -05:00
Dustin L. Howett
cf7a6617ab Guard Control UpdateAppearance/Settings against UAF (#17770)
When you close a window, it naturally loses focus.

We were trying to use members of the control to update its appearance on
focus loss after it got torn down.

Closes #17520

(cherry picked from commit eabebc4cb2)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgSIM6I
Service-Version: 1.21
2024-08-22 18:00:25 -05:00
Carlos Zamora
f2e9041aa0 Log action dispatch occurrence (#17718)
Some simple logic to report whenever an action has successfully occurred
(and what ShortcutAction was used).

Note, there will be some false positives here from startup. I noticed we
get a `newTab` on launch. This is probably a result of restoring the
window layout of the previous session since we're using ActionAndArgs
for that.

(cherry picked from commit 56cfb77c6d)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgSCpCo
Service-Version: 1.21
2024-08-22 11:33:18 -05:00
Dustin L. Howett
8e7137dbde Disable PGO for Release builds (#17765)
Same justification as #17749.

We will revert this when either OneBranch Custom Pools become
fit-for-purpose or they upgrade to VS 17.11. Or the heat death of the
universe.

(cherry picked from commit 628e99f5d2)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgSGCaA
Service-Version: 1.21
2024-08-21 18:21:23 -05:00
Leonard Hecker
0cbe706f48 Fix pane event handlers being unbound (#17750)
I don't know what has changed between #17450 and now, but that fix
doesn't seem necessary anymore. If you add this action:
```json
{
    "keys": "ctrl+a",
    "command":
    {
        "action": "splitPane",
        "commandline": "cmd /c exit"
    }
}
```

and repeatedly spam Ctrl-A it used to lead to crashes. That doesn't
happen anymore, because some other PR must've fixed that.

Reverting #17450 fixes the issue found in #17578: Because the content
pointer didn't get reset to null anymore it meant that the root
pane retained the pointer after a split. After closing the split off
pane, it would assign the remaining one back to the root, which would
cause the still existing content pointer to be closed. That pointer
is potentially the same as the remaining pane and so no close events
would get received anymore.

Closes #17578

## Validation Steps Performed
* Add the above action and spam it 
* Start with an empty window, split pane, type `exit` in the new pane
  then type it in the original pane. It closes the window 

(cherry picked from commit 056af83994)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgSGCfE
Service-Version: 1.21
2024-08-21 18:21:22 -05:00
Leonard Hecker
8c2c88e44f Fix session persistence when the session ends (#17714)
Once all applications that have received a `WM_ENDSESSION` message
have returned from processing said message, windows will terminate
all processes. This forces us to process the message synchronously.
This meant that this issue was timing dependent. If Windows Terminal
was quick at persisting buffers and you had some other application that
was slow to shut down (e.g. Steam), you would never see this issue.

Closes #17179
Closes #17250

## Validation Steps Performed
* Set up a lean Hyper-V VM for fast reboots
* `Set-VMComPort <vm> 1 \\.pipe\\<pipe>`
* Hook up WIL to write to COM1
* Add a ton of debug prints all over the place
* Read COM output with Putty for hours
* RTFM, and notice that the `WM_ENDSESSION` documentation states
  "the session can end any time after all applications
  have returned from processing this message"
* Be very very sad 
* Fix it
* Rebooting now shows on COM1 that persistence runs 
* Windows get restored after reboot 

(cherry picked from commit b439925acc)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgSGCik
Service-Version: 1.21
2024-08-21 18:21:20 -05:00
Leonard Hecker
1742dc03ff Align the OSS ConPTY API with Windows 11 24H2 (#17704)
(cherry picked from commit 7fd9c5c789)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgSGCkE
Service-Version: 1.21
2024-08-21 18:21:16 -05:00
Leonard Hecker
42ab9bbd69 Fix a crash during settings update (#17751)
* Adds a check whether the thread dispatcher is already null.
  (See code comments.)
* Moves the `_settings` to only happen on the UI thread.
  Anything else wouldn't be thread safe.

Closes #17620

## Validation Steps Performed
Not reproducible. 🚫

(cherry picked from commit e0dae59f38)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgSGBis
Service-Version: 1.21
2024-08-21 18:17:50 -05:00
PankajBhojwani
cb8a3f6ef1 Fix overwrite key binding warning in the SUI (#17763)
Fixes a regression from the actions MVVM change in #14292 - attempting
to overwrite a keybinding was displaying a warning but propagating the
change before the user acknowledged it.

The overwrite key binding warning in the SUI works like before

Closes #17754

(cherry picked from commit ce92b18507)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgSF01Y
Service-Version: 1.21
2024-08-21 18:12:26 -05:00
Dustin L. Howett
ed08108e32 Port ServicingPipeline.ps1 to ProjectsV2 (#17756)
(cherry picked from commit 516ade54cb)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgSF-7E
Service-Version: 1.21
2024-08-21 18:12:25 -05:00
Carlos Zamora
8aa56c25f4 Add ellipses back in to some command names (#17715)
In #16886, the key for the nested action got renamed from `Split
Pane...` to `Split pane`. This accidentally caused a collision because
now there's two actions with the same name! The settings model then
prefers the user's action over the one defined in defaults.json, thus
completely hiding the nested version.

I tried to balance the stylistic recommendations from #16846 (mainly
[this
comment](https://github.com/microsoft/terminal/issues/16846#issuecomment-2005007519)
since it gave some excellent examples) while trying to maintain muscle
memory as much as possible (with similar substring sequences). There was
also one case where we still used "the tab" so I removed the "the" for
consistency.

Side effect of #16886 which closed #16846
Closes #17294
Closes #17684

(cherry picked from commit 0a7c2585a2)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgSFdXc
Service-Version: 1.21
2024-08-21 13:17:57 -05:00
Carlos Zamora
e866a6c66f Fix UIA RangeFromPoint API (#17695)
## Summary of the Pull Request
Fixes the `RangeFromPoint` API such that we're now properly locking when
we attempt to retrieve the viewport data. This also corrects the
conversion from `UiaPoint` (screen position) to buffer coordinates
(buffer cell).

Closes #17579

## Detailed Description of the Pull Request / Additional comments
- `UiaTextRangeBase::Initialize(UiaPoint)`:
- reordered logic to clamp to client area first, then begin conversion
to buffer coordinates
   - properly lock when retrieving the viewport data
- updated `_TranslatePointToScreen` and `_TranslatePointFromScreen` to
use `&` instead of `*`
   - we weren't properly updating the parameter before
- `TermControlUiaTextRange::_TranslatePointFromScreen()`
- `includeOffsets` was basically copied over from
`_TranslatePointToScreen`. The math itself was straight up wrong since
we had to do it backwards.

## Validation Steps Performed
 Moved WT to top-left of monitor, then used inspect.exe to call
`RangeFromPoint` API when mouse cursor is on top-left buffer cell (also
meticulously stepped through the two functions ensuring everything was
correct).

(cherry picked from commit 7b39d24913)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmszgSC930 PVTI_lADOAF3p4s4AmhmszgSCpCs
Service-Version: 1.21
2024-08-20 21:13:55 -05:00
Mike Griese
2890e8a3d4 Log when WindowsTerminal.exe starts (#17745)
as discussed in team sync

(cherry picked from commit 60ac45c239)
Service-Card-Id: 93750273
Service-Version: 1.21
2024-08-20 11:44:32 -05:00
Dustin L. Howett
6b6167ec2b Restore the ability to disable checking for URLs (#17731)
Fixes #17727

(cherry picked from commit 735ef2823e)
Service-Card-Id: 93736213
Service-Version: 1.21
2024-08-20 11:44:31 -05:00
Carlos Zamora
5d1638f187 schema: add reloadEnvironmentVariables to newTerminalArgs (#17696)
(cherry picked from commit 1511d2c2ad)
Service-Card-Id: 93522519
Service-Version: 1.21
2024-08-20 11:44:29 -05:00
Dustin L. Howett
2befaa1669 Switch to the new and beautiful VS Dev Shell icons (#17706)
We got some new icons for Developer Command Prompt and Developer
PowerShell from our friends over on Visual Studio!

This pull request includes them in the package, and fixes up the VS
dynamic profiles to reset any icons that matched the old paths.

This may be a minor breaking change for user settings, but we're making
the assumption that if they didn't change their VS profile icons from
the defaults, they probably want to follow us to the new defaults.

To prevent anything like this from happening again, we're going to stop
serializing icons for stub profiles.

I've also included a VS version of the PowerShell "black" icon which is
currently unused, but can be used in the future for PS7+-based VS Dev
Shell.

Closes #17627

(cherry picked from commit 06c07ab50d)
Service-Card-Id: 93531229
Service-Version: 1.21
2024-08-20 11:44:28 -05:00
Leonard Hecker
83a9baa797 AtlasEngine: Fix a buffer overrun (#17536)
The strided `memcpy` between buffers failed to account for situations
where the destination stride is smaller than the source stride.
The solution is to only copy as many bytes as are in each row.

## Validation Steps Performed
Even with AppVerifier the issue could not be reproduced.
Adding an `assert(srcStride <= mapped.RowPitch)`, however, did trap
the bug when WARP is used while BackendD3D is force-enabled.

(cherry picked from commit ae8c868a1c)
Service-Card-Id: 92972720
Service-Version: 1.21
2024-08-13 17:26:56 -05:00
Leonard Hecker
5a99621856 AtlasEngine: Curly line redux (#17508)
See #17501.

(cherry picked from commit 7f2249c810)
Service-Card-Id: 92942980
Service-Version: 1.21
2024-08-13 17:26:56 -05:00
Leonard Hecker
09aa541d56 AtlasEngine: Improve appearance of curly underlines (#17501)
We'd previously subtract one underline-height from the curly line
offset, even though we already had subtracted its complete height.

Additionally, the pixel shader received some fine tuning:
* Shrink the stroke width so that the anti-aliasing can be seen
  all the way up to the horizontal edges of the bounding box.
* Add a phase shift to break apart the symmetry of the curve.

Closes #17482

Co-authored-by: Carlos Zamora <carlos.zamora@microsoft.com>
(cherry picked from commit ad3797ace9)
Service-Card-Id: 92942049
Service-Version: 1.21
2024-08-13 17:26:56 -05:00
Dustin L. Howett
4040e4c654 atlas,d2d: overdraw background bitmap by one cell on all sides (#17674)
BackendD2D will now draw one extra cell on all sides when rendering the
background, filled with the expected background color, starting at (-1,
-1) to ensure that cell backgrounds do not bleed over the edges of the
viewport where the is swapchain but no content.

Fixes #17672

(cherry picked from commit 9007fc2894)
Service-Card-Id: 93494324
Service-Version: 1.21
2024-08-13 16:22:03 -05:00
Carlos Zamora
8f4775df96 Log number of interactive sessions (#17682)
This sends a telemetry event if a session is interacted with.
Specifically, key events are essential to have an interactive session in
Windows Terminal, so we're tracking sessions that have had a key down
event.

(cherry picked from commit ac865e6666)
Service-Card-Id: 93498660
Service-Version: 1.21
2024-08-13 16:20:00 -05:00
Leonard Hecker
3ab8921aa7 Fix colors getting lost on reflow (#17568)
The "copy the remaining attributes" loop assumes that it has full
ownership over the rows that it copies. For that to be true,
we have to of course make sure that the current write-cursor
is at a fresh, new row in the first place.

## Validation Steps Performed
* In a new pwsh tab with 120 colums:
  ``Write-Host -NoNewline "`e[36m$('a'*120)`e[m"; sleep 10``
* Resize the window wider
* Color doesn't get lost

(cherry picked from commit 2f43886ab5)
Service-Card-Id: 93441137
Service-Version: 1.21
2024-08-13 16:19:59 -05:00
Windows Console Service Bot
2a15717f69 Localization Updates - builtin glyphs (ONLY) (#17458)
(partially cherry picked from commit 9f7032afd8)
Service-Card-Id: 92889853
Service-Version: 1.21
2024-06-24 15:05:00 -05:00
Leonard Hecker
846a8aa7a6 Fix builtin glyph corruption in the D2D renderer (#17464)
The initial contents of a texture are undefined. That's not good.
Now they are. That's good.

(cherry picked from commit 8c14a34263)
Service-Card-Id: 92788897
Service-Version: 1.21
2024-06-24 15:02:59 -05:00
Dustin L. Howett
9cccef7224 Remove the D2D warning from the Builtin Glyphs setting (#17454)
(cherry picked from commit 34d4dc5a5f)
Service-Card-Id: 92777925
Service-Version: 1.21
2024-06-24 15:02:58 -05:00
Leonard Hecker
196a60c7c2 AtlasEngine: Implement remaining underlines and builtin glyphs for D2D (#17278)
This implements builtin glyphs for our Direct2D renderer, as well as
dashed and curly underlines. With this in place the only two features
it doesn't support are inverted cursors and VT soft fonts.
This allows us to remove the `_hack*` members introduced in a6a0e44.

The implementation of dashed underlines is trivial, while curly
underlines use quadratic bezier curves. Caching the curve as a sprite
is possible, however I feel like that can be done in the future.

Builtin glyphs on the other hand require a cache, because otherwise
filling the entire viewport with shaded glyphs would result in poor
performance. This is why it's built on top of `ID2D1SpriteBatch`.
Unfortunately the API causes an eager flush of other pending graphics
instructions, which is why there's still a decent perf hit.

Finally, as a little extra, this fixes the rounded powerline glyph
shapes being slightly cut off. The fix is to simply don't round the
position and radius of the ellipsis/semi-circle.

Closes #17224

## Validation Steps Performed
* RenderingTests.exe updated 
* All supported builtin glyphs look sorta right at different sizes 

(cherry picked from commit 3486111722)
Service-Card-Id: 92572076
Service-Version: 1.21
2024-06-24 15:02:57 -05:00
flyingcat
aff77650e4 Make subsequent windows open in the foreground (#17368)
Sometimes subsequent WT windows open in the background behind other
applications. This PR tries to fix it.

Refs #15895
Refs #15479

Mysterious bug (and annoying). There are even some discussions about
happening to the first startup, not just subsequent ones. Sometimes the
window may show up without animation too. So I don't think this is the
final solution, but it did get solved on my computer, for now.

## Validation Steps Performed
0. Quit all WT windows if some.
1. Open File Explorer, click "Open in Terminal" in context menu.
2. Move the newly opened window and minimize it.
3. Back to step 1 and repeat several times.
4. All the windows should open in the foreground correctly (yet possibly
without animation).

---------

Co-authored-by: Mike Griese <migrie@microsoft.com>
(cherry picked from commit c52ba7dec6)
Service-Card-Id: 92715122
Service-Version: 1.21
2024-06-20 14:25:40 -05:00
PankajBhojwani
8f3b38fb81 Fix crash when closing panes very quickly (#17450)
#17358 introduced a bug where if you open/close panes very rapidly
Terminal will crash. This was because `_content` was being set to `null`
and then a `Close` event was being emitted, but several functions
attempt to access the pane's `_content` as part of the close routine.
For example, `TerminalTab` tries to update the `TaskbarProgress` every
time a pane is closed and as part of that update sequence it queries the
pane - which has `null` content now - for the taskbar progress,
resulting in a crash. This PR fixes that crash.

Refs #17358

(cherry picked from commit 5d46e317b2)
Service-Card-Id: 92776947
Service-Version: 1.21
2024-06-20 14:13:30 -05:00
Tushar Singh
d960c89634 Fix some search highlights scenarios (#17352)
Fixes:
- Snapping the current match to the current selection doesn't work.
- Fast closing and re-opening SearchBox would leave search highlights in
an inconsistent state. The highlights would be active even when SB is
not on the screen, and results are not updated as more text is added to
the buffer.
- Search highlights scroll marks are not cleared when the search box is
closed.

(cherry picked from commit 7c1e2298f8)
Service-Card-Id: 92736967
Service-Version: 1.21
2024-06-20 14:13:29 -05:00
Windows Console Service Bot
332c5ad937 Localization Updates for #17369 (#17380)
(cherry picked from commit 5359e71ca1)
Service-Card-Id: 92701124
Service-Version: 1.21
2024-06-20 14:12:18 -05:00
Leonard Hecker
5f6783b01f Warn when using old MacType versions (#17369)
This adds a check for whether MacType is injected and whether it's
a known bad version (pre-2023). In that case we avoid calling the
known faulty `ID2D1Device4` interface. We could avoid it in general to
fix the issue without a warning (it's only a very mild optimization),
but on the other hand, the bug that MacType has is a very serious one
and it's probably better overall to suggest users to update.

See: https://github.com/snowie2000/mactype/pull/938

## Validation Steps Performed
* MacType 2021.1-RC1 results in a warning and no crash 
* MacType 2023.5.31 results in no warning 

---------

Co-authored-by: Dustin L. Howett <duhowett@microsoft.com>
(cherry picked from commit 9317d42045)
Service-Card-Id: 92687129
Service-Version: 1.21
2024-06-07 18:01:29 -05:00
Leonard Hecker
334335fd43 Fix spurious clear-to-end sequence in buffer dumps (#17374)
I think I forgot to complete that section of the code...
The parentheses were missing and `beg` was repeated twice. The last
line in the comment above this explains what I intended it to be.

Closes #17365

## Validation Steps Performed
* In a new PowerShell tab
* Run ``"`e[999C`e[2D`e[42mfoo`e[m"``
* Newline until it scrolls
* Run it again
* Close and reopen
* The green "foo" is still green 

(cherry picked from commit 640424e03f)
Service-Card-Id: 92687334
Service-Version: 1.21
2024-06-07 18:01:28 -05:00
Leonard Hecker
30df31fd9b Support valid out-of-bounds access in utextAccess (#17361)
`utextAccess` apparently doesn't actually need to clamp the
`chunkOffset` to be in range of the current chunk. Also, I missed to
implement the part of the spec that says to leave the iterator on the
first/last chunk of the `UText` in case of an out-of-bounds index.

This PR fixes the issue by simply not returning early, doing a more
liberal clamp of the offset, and then checking whether it was in range.

As an aside, this also fixes a one-off bug when hovering URLs that
end on the very last cell of the viewport (or are cut off).

Closes #17343

## Validation Steps Performed
* Write an URL that wraps across the last 2 lines in the buffer
* Scroll 1 line up
* No assert 
* Hovering the URL shows the full, still visible parts of the URL 

(cherry picked from commit 261a3fec7a)
Service-Card-Id: 92678596
Service-Version: 1.21
2024-06-07 18:01:26 -05:00
Leonard Hecker
0030a1d52e Fix two panes being closed when just one is (#17358)
#17333 introduced a regression: While it fixes a recursion *into*
`Pane::Close()` that doesn't fix the recursion outside of it.
In this case, `Close()` raises the `Closed` event which results
in another tab being closed because it's bound to `_RemoveTab`.
The recursion is now obvious, because I made the entire process
synchronous. Previously, it would (hopefully) just be scheduled
after the pane and its content are already gone.

The issue can be fixed by moving the recursion check from
`Pane::Close()` to `TerminalTab::Shutdown()` but I felt like
it would better to fix the issue a bit more thoroughly.

`IPaneContent` can raise a `CloseRequested` event to indicate it wants
to be closed. However, that also contained recursion, because the
content would call its own `Close()` to raise the event, which the
tab catches, calls `Close()` on the `Pane` which calls `Close()` on
the content which raises the event again and so on. That's what was
fixed in #17333 among others. We can do this better by not raising
the event from `IPaneContent::Close()`. Instead, that method will now
be exclusively called by `Pane`. The `CloseRequested` event will now
truly be just a request and nothing more. Furthermore, the ownership
of the event handling was moved from the `TerminalTab` to the `Pane`.

To make all of this a bit simpler and more robust, two new methods
were added to `Pane`: `_takePaneContent` and `_setPaneContent`.
These methods ensure that `Close()` is called on the content,
that the event handlers are always added and revoked
and that the ownership transfers cleanly between panes.

## Validation Steps Performed
* Open 3 tabs, close the middle one 
* Open 3 vertical panes, close the middle one 
* Drag tabs with multiple panes between windows 

(cherry picked from commit ce0f8d6db2)
Service-Card-Id: 92678790
Service-Version: 1.21
2024-06-07 18:01:25 -05:00
Leonard Hecker
082d166ac6 Fix a crash when closing panes (#17333)
Calling Close() from within WalkPanes is not safe. Simply using
_FindPane is enough to fix this.

This PR also fixes another potential source of infinite recursion, and
fixes panes being passed by-value into the callbacks.

Closes #17305

## Validation Steps Performed
* Split panes vertically 3 times
* `exit` the middle, the bottom and final one, in that order
* Doesn't crash 

(cherry picked from commit baba406a07)
Service-Card-Id: 92643006
Service-Version: 1.21
2024-06-07 18:01:24 -05:00
Windows Console Service Bot
3e661bfad2 Localization Updates - fix issues in Korean, Italian, Spanish (#17304)
Closes #12665
Closes #12712
Closes #16867

(cherry picked from commit 13de7c6685)
Service-Card-Id: 92614020
Service-Version: 1.21
2024-06-07 18:01:23 -05:00
Tushar Singh
7b59a9eafb Fix hyperlinks using an extra character at the end (#17326)
Closes: #17323

## Validation Steps Performed
- Run `echo Hello ^(https://github.com/microsoft/terminal^)` in cmd.
- Ctrl+click on the URL opens `https://github.com/microsoft/terminal` in
the browser.
- Hovering over the url in the terminal shows
`https://github.com/microsoft/terminal` in the hover UI.

(cherry picked from commit 212f43e7fb)
Service-Card-Id: 92637505
Service-Version: 1.21
2024-06-07 18:01:22 -05:00
Mike Griese
8038dc67cd Clean up command history context passed to suggestions UI (#17245)
This is fallout from #16937.

* Typing a command then backspacing the chars then asking for
suggestions would think the current commandline ended with spaces,
making filtering very hard.
* The currently typed command would _also_ appear in the command
history, which isn't useful.

I actually did TDD for this and wrote the test first, then confirmed
again running through the build script, I wasn't hitting any of the
earlier issues.

Closes #17241
Closes #17243

(cherry picked from commit bf8a647788)
Service-Card-Id: 92638413
Service-Version: 1.21
2024-06-07 18:01:21 -05:00
Windows Console Service Bot
bc365c9542 Localization Updates - main - associated with #17259 (#17272)
(cherry picked from commit 26cc5da7f1)
Service-Card-Id: 92577949
Service-Version: 1.21
2024-05-17 12:44:25 -05:00
Leonard Hecker
0d8e43c697 Improve font related help text (#17259)
A few minor changes to better guide people along new features in 1.21.
The font face box gets a sub-text that explains how to add multiple
fonts and the builtin glyph toggle now explains its dependence to D3D.

(cherry picked from commit 0d39c008cb)
Service-Card-Id: 92546504
Service-Version: 1.21
2024-05-17 12:44:23 -05:00
Dustin L. Howett
967dcfc5b0 build: move ESRP to a parameterized subtask which takes signingId (#17216)
This centralized all our ESRP calls in one file, which will make it
easier in the future when we are invariable required to change how we
call it again.

(cherry picked from commit 5ce7fb7403)
Service-Card-Id: 92577955
Service-Version: 1.21
2024-05-17 12:44:21 -05:00
Leonard Hecker
e56a557c93 Fix persistence of handoff'd tabs (#17268)
As it turns out, for handoff'd connections `Initialize` isn't called
and this meant the `_sessionId` was always null.
After this PR we still don't have a `_profileGuid` but that's probably
not a critical issue, since that's an inherent flaw with handoff.
It can only be solved in a robust manner if WT gets launched before the
console app is launched, but it's unlikely for that to ever happen.

## Validation Steps Performed
* Launch
* Register that version of WT as the default
* Close all tabs (Ctrl+Shift+W)
* `persistedWindowLayouts` is empty 
* Launch cmd/pwsh via handoff
* You get 1 window 
* Close the window (= press the X button)
* Launch
* You get 2 windows 

(cherry picked from commit 9054c81934)
Service-Card-Id: 92556178
Service-Version: 1.21
2024-05-16 19:00:48 -05:00
Leonard Hecker
52eba74316 AtlasEngine: Improve robustness against weird font sizes (#17258)
This clamps the font sizes between 1 and 100. Additionally, it fixes
a warning that I randomly noticed when reproducing the issue: D2D
complained that `EndDraw` must be called before releasing resources.
Finally, this fixes a crash when the terminal size is exactly (1,1)
cells, which happened because the initial (invalid) size was (1,1) too.

This doesn't fully fix all font-size related issues, but that's
currently difficult to achieve, as for instance the swap chain size
isn't actually based on the window size, nay, it's based on the cell
size multiplied by the cell count. So if the cell size is egregiously
large then we get a swap chain size that's larger than the display and
potentially larger than what the GPU supports which results in errors.

Closes #17227

(cherry picked from commit f62d2d5d2c)
Service-Card-Id: 92546470
Service-Version: 1.21
2024-05-16 19:00:48 -05:00
Dustin L. Howett
27de22d0e5 ServicingPipeline: Warn when local release-XX branch is not uptodate (#17260)
This prevents me from making dumb mistakes, really.

(cherry picked from commit bf55c44460)
Service-Card-Id: 92546838
Service-Version: 1.21
2024-05-16 19:00:48 -05:00
Leonard Hecker
52ab4c467a Fix race conditions in UiaTextRangeBase (#17257)
We need to lock the buffer when getting the viewport/cursor position.
This caused the UIA overlay to randomly fail to update.

## Validation Steps Performed
* Open a cmd tab and hold any key immediately
* Repeat until you're somewhat confident it's gone 

(cherry picked from commit e1b102a354)
Service-Card-Id: 92546408
Service-Version: 1.21
2024-05-13 12:34:05 -05:00
Mike Griese
ece2ef7f84 Remove the animations from the suggestions UI (#17247)
gotta go fast, and these animations are not fast

noted in #15845

(cherry picked from commit 46526bc00c)
Service-Card-Id: 92546875
Service-Version: 1.21
2024-05-13 12:34:04 -05:00
Tushar Singh
ef283da5cb Fix single-tab window tear-off crash (#17251)
## Validation Steps Performed
- Opened multi-tab terminal window with Narrator. Narrator can read
characters from the tabs.
- Started a drag and drop (tear-off) of a tab, and it didn't crash. This
was repeated multiple times.

(cherry picked from commit 30ef1f461d)
Service-Card-Id: 92546869
Service-Version: 1.21
2024-05-13 12:34:03 -05:00
krzysdz
18c3f72fe0 PowerShell menu completion parser thread-safety fix (#17221)
Fix Terminal crashing when experimental PowerShell menu completion is
very quickly invoked multiple times.

`Command::ParsePowerShellMenuComplete` can be called from multiple
threads, but it uses a `static` `Json::CharReader`, which cannot safely
parse data from multiple threads at the same time. Removing `static`
fixes the problem, since every function call gets its own `reader`.

Validation: Pressed Ctrl+Space quickly a few times with hardcoded huge
JSON as the completion payload. Also shown at the end of the second
video in #17220.

Closes #17220

(cherry picked from commit 44516ad7cf)
Service-Card-Id: 92524217
Service-Version: 1.21
2024-05-13 11:32:09 -05:00
Leonard Hecker
4d1b543a9e Fix session being persisted even when disabled (#17211)
This fixes 2 bugs:
* `PersistState` being called when the window is closed
  (as opposed to closing the tab). The settings check was missing.
* Session cleanup running depending on whether the feature is
  currently enabled as opposed to whether it was enabled on launch.

Closes #17206
Closes #17207

## Validation Steps Performed
* Create a bunch of leftover buffer_*.txt files by running
  the current Dev version off of main
* Build this branch, then open and close a window
* All buffer_*.txt are gone and state.json is cleaned up 

(cherry picked from commit dbac3a1fa3)
Service-Card-Id: 92515454
Service-Version: 1.21
2024-05-13 11:32:08 -05:00
Leonard Hecker
d838ce5e67 Fix !_noFlushOnEnd not flushing (#17212)
This simply copies a bit more from `VtEngine::EndPaint`'s
`_noFlushOnEnd` handling which already seems to fix the linked issue.

Closes #17204

(cherry picked from commit 0b76c51ba1)
Service-Card-Id: 92516193
Service-Version: 1.21
2024-05-13 11:32:06 -05:00
Leonard Hecker
1f54562f04 Add nullptr checks to shared_ptr conversions (#17199)
We use `if (auto self = weakSelf.get())` in a lot of places.
That assigns the value to `self` and then checks if it's truthy.
Sometimes we need to add a "is (app) closing" check because XAML,
so we wrote something akin to `if (self = ...; !closing)`.

But that's wrong because the correct `if (foo)` is the same as
`if (void; foo)` and not `if (foo; void)` and that meant that
we didn't check for `self`'s truthiness anymore.

This issue became apparent now, because we added a new kind of
delayed callback invocation (which is a lot cheaper).
This made the lack of a `nullptr` check finally obvious.

(cherry picked from commit 6d0342f0bb)
Service-Card-Id: 92509288
Service-Version: 1.21
2024-05-07 17:14:56 -05:00
James Holderness
f0fc1b5701 Make sure DCS strings are flushed to conpty without delay (#17195)
When the `DCS` passthrough code was first implemented, it relied on the
`ActionPassThroughString` method flushing the given string immediately.
However, that has since stopped being the case, so `DCS` operations end
up being delayed until the entire sequence has been parsed.

This PR fixes the issue by introducing a `flush` parameter to force an
immediate flush on the `ActionPassThroughString` method, as well as the
`XtermEngine::WriteTerminalW` method that it calls.

## Validation Steps Performed

I've confirmed that the test case in issue #17111 now updates the color
table as soon as each color entry is parsed, instead of delaying the
updates until the end of the sequence.

Closes #17111

(cherry picked from commit 9c16c5ca82)
Service-Card-Id: 92501226
Service-Version: 1.21
2024-05-06 16:02:40 -05:00
Windows Console Service Bot
a6819c5384 Localization Updates - 05/03/2024 19:01:37 (#17188)
(cherry picked from commit 80d2e58944)
Service-Card-Id: 92501389
Service-Version: 1.21
2024-05-06 16:02:38 -05:00
James Holderness
3c6b2af578 Prevent the VT engine painting unnecessarily (#17194)
When the VT render engine starts a paint operation, it first checks to
see whether there is actually something to do, and if not it can end the
frame early. However, the result of that check was being ignored, which
could sometimes result in an unwanted `SGR` reset being written to the
conpty pipe.

This was particular concerning when passing through `DCS` sequences,
because an unexpected `SGR` in the middle of the `DCS` string would
cause it to abort early.

This PR addresses the problem by making sure the `VtEngine::StartPaint`
return value is appropriately handled in the `XtermEngine` class.

## Detailed Description of the Pull Request / Additional comments

To make this work, I also needed to correct the `_cursorMoved` flag,
because that is one of things that determines whether a paint is needed
or not, but it was being set in the `InvalidateCursor` method at the
start of ever frame, regardless of whether the cursor had actually
moved.

I also took this opportunity to get rid of the `_WillWriteSingleChar`
method and the `_quickReturn` flag, which have been mostly obsolete for
a long time now. The only place the flag was still used was to optimize
single char writes when line renditions are active. But that could more
easily be handled by testing the `_invalidMap` directly.

## Validation Steps Performed

I've confirmed that the test case in issue #17117 is no longer aborting
the `DCS` color table sequence early.

Closes #17117

(cherry picked from commit 432dfcc490)
Service-Card-Id: 92501130
Service-Version: 1.21
2024-05-06 16:02:37 -05:00
Leonard Hecker
fe237afc25 AtlasEngine: Fix several error handling bugs (#17193)
This fixes:
* `HRESULT`s not being shown as unsigned hex
* `D2DERR_RECREATE_TARGET` not being handled
* 4 calls not checking their `HRESULT` return
  Out of the 4 only `CreateCompatibleRenderTarget` will throw in
  practice, however it throws `D2DERR_RECREATE_TARGET` which is common.
  Without this error handling, AtlasEngine may crash.

## Validation Steps Performed
* Set Graphics API to Direct2D
* Use `DXGIAdapterRemovalSupportTest.exe` to trigger
  `D2DERR_RECREATE_TARGET`
* No error message is shown 
* If the `D2DERR_RECREATE_TARGET` handling is removed, the application
  never crashes due to `cursorRenderTarget` being `nullptr` 

(cherry picked from commit b31059e53e)
Service-Card-Id: 92492429
Service-Version: 1.21
2024-05-06 16:02:36 -05:00
Dustin L. Howett
3600ee42f0 PGO: train 1.21 separately 2024-05-06 16:02:22 -05:00
Windows Console Service Bot
5c758974e5 Localization Updates - main - 05/02/2024 23:37:23 (#17185) 2024-05-02 18:39:10 -05:00
Leonard Hecker
4fbcd65e1a Fix multiple cursor invalidation issues (#17181)
There were multiple bugs:
* GDI engine only paints whatever has been invalidated.
  This means we need to not just invalidate the old cursor rect
  but also the new one, or else movements may not be visible.
* The composition should be drawn at the cursor position even if
  the cursor is invisible, but inside the renderer viewport.
* Conceptually, scrolling the viewport moves the relative cursor
  position even if the cursor is invisible.
* An invisible cursor is not the same as one that's outside the
  viewport. It's more like a cursor that's not turned on.

To resolve the first issue we simply need to call `InvalidateCursor`
again. To do so, it was abstracted into `_invalidateCurrentCursor()`.

The next 2 issues are resolved by un-`optional`-izing `CursorOptions`.
After all, even an invisible or an out-of-bounds cursor still has a
coordinate and it may still be scrolled into view.
Instead, it has the new `inViewport` property as a replacement.
This allows for instance the IME composition code in the renderer
to use the cursor coordinate while the cursor is invisible.

The last issue is fixed by simply changing the `.isOn` logic.

Closes #17150

## Validation Steps Performed
* In conhost with the GDI renderer:
  `printf "\e[2 q"; sleep 2; printf "\e[A"; sleep 2; printf "\e[B"`
  Cursor moves up after 2s and then down again after 2s. 
* Hide the cursor (`"\e[?25l"`) and use a CJK IME.
  Words can still be written and deleted correctly. 
* Turning the cursor back on (`"\e[?25h"`) works 
* Scrolling shows/hides the cursor 
2024-05-02 18:33:25 -05:00
Mike Griese
92e05f246a Fix clearing marks (#17144)
Tests are good, I should write more of them. 


Closes #17130
2024-05-02 18:27:12 -05:00
Leonard Hecker
d4faf98455 Fix remaining buffer serialization bugs (#17182)
It may be more accurate to say: "Fix _known_ remaining buffer
serialization bugs", but I'll try to be positive about my code.

Initially, the buffer is initialized with the default attributes,
but once it begins to scroll, newly scrolled in rows are initialized
with the current attributes. This means we need to set the current
attributes to those of the upcoming row before the row comes up.

This is related to #17074.

## Validation Steps Performed
* Persist and restore a buffer 10 times
* All previous "Restore" status messages look correct 
* The escape sequences in the buffer file look correct 
2024-05-02 18:26:03 -05:00
Leonard Hecker
c52dca40d2 Fix doskey macros for inputs with >1 consecutive whitespace (#17129)
Initially the PR restored the original v1 conhost code for
`MatchAndCopyAlias` which fixed the linked issue.
Afterwards, I've taken the liberty to rewrite the code to use modern
constructs again, primarily `string_view`. Additionally, the v1 code
first counted the number of arguments and then iterated through it
again to assemble them. This new code does both things at once.

Closes #15736

## Validation Steps Performed
The unit tests have been extended to cover multiple consecutive
spaces. All tests pass.
2024-05-02 19:38:04 +00:00
Mike Griese
8dd4512067 Some schema updates for 1.21 (#17183)
Noticed all these while prepping for Build:

* Promotes the stabilized features out of `experimental.`
* fixes a bug where a nested command with a `name` would match to a
`renameWindow` action, instead of a command.
* Adds the tab theme icon style
* fixes a bug where `ScrollToMarkAction` wasn't in the list of possible
args, so they would incorrectly get flagged as `moveTab`
* outright adds `experimental.rightClickContextMenu` which was missing
(?)
2024-05-02 14:15:25 -05:00
Dustin L. Howett
6cda6797f8 Take wrapping into account when expanding wordwise selections (#17170)
Closes #17165
2024-05-02 11:14:20 -05:00
Windows Console Service Bot
a9446a12df Localization Updates - main - 05/02/2024 03:05:18 (#17175) 2024-05-02 11:13:50 -05:00
Leonard Hecker
475b3878f6 Fix font axis/feature SUI issues (#17173)
Something something code changes, fixes issue. Events need throwing,
some events don't need throwing, some events need throttling to
not overwhelm the flurble function within the gumbies component.
This is all boilerplate and it works now.

Closes #17171
Closes #17172

## Validation Steps Performed
* Resetting the font axis/feature expander keeps
  the add new button flyout sorted 
* Changing a font axis/feature value updates the preview 
* After changing the font, features/axes can still be edited 
2024-05-02 11:12:34 -05:00
Mike Griese
c2b8f99582 Don't always focus pane content on Tapped, if the pane is already focused (#17174)
You'll never believe this. Clicking on the dropdown button on a ComboBox
doesn't set `e.Tapped = true`. It bubbles up, and lands in our `Pane`'s
`Border`'s tapped handler. And in there, we yeet focus to the first
content. We end up stealing focus from the combobox, and then the
combobox doesn't actually open its dropdown.

So yea we can just fix that. Easy enough. 

Closes #17062

---------

Co-authored-by: Dustin L. Howett <duhowett@microsoft.com>
Co-authored-by: Leonard Hecker <lhecker@microsoft.com>
2024-05-02 11:12:19 -05:00
Mike Griese
015055c246 Move the AttachConsole in the feature tests in the retry loop (#17180)
These feature tests continue to plague us. Seems like the most likely
outcome nowadays is that the test fails to attach immediately, so we
don't even get to the retry loop.

Easy enough. Let's move the AttachConsole into the loop too.
2024-05-02 11:12:06 -05:00
Mike Griese
a5835b01b1 Prevent multiple settings tabs from being persisted (#17169)
Re-add some machinery to special case settings tabs. When we're going to
persist a tab that only has a single settings pane in it, we'll now
promote that to the first-class "openSettings" action. This will allow
our other code in TerminalPage to route multiple settings tabs all to
the same tab.

This of course doesn't stop you from opening multiple settings tabs with
`{ "command": {"action": "newTab", "type": "settings"} }` actions. If we
did that, then that would prevent someone from having a settings pane in
the first pane, and a terminal to the right.

Closes #17070
2024-05-02 02:11:25 +00:00
Dustin L. Howett
2f52f27197 build: switch to ESRP v5, which supports managed identities (#17134)
This required me to push a bunch more parameters through the build
pipeline, but it gave me the opportunity to define them as variables
that can be set at queue time.
2024-05-01 20:17:49 +00:00
Leonard Hecker
d3803943ca Fix font axes/features settings UI (#17164)
Due to #16821 everything about #16104 broke. This PR rights the wrongs
by rewriting all the `Font`-based code to not use `Font` at all.
Instead we split the font spec once into font families, do a lot of
complex logic to split font axes/features into used and unused ones
and construct all the UI elements. So. much. boilerplate. code.

Closes #16943

## Validation Steps Performed
There are more edge cases than I can list here... Some ideas:
* Edit the settings.json with invalid axis/feature keys 
* ...out of range values 
* Settings UI reloads when the settings.json changes 
* Adding axes/features works 
* Removing axes/features works 
* Resetting axes/features works 
* Axes/features apply in the renderer when saving 
2024-05-01 17:09:20 +00:00
Mike Griese
77087e6282 Fix the location that selecting a mark uses (#17138)
I think this subtly regressed in #16611. Jump to
90b8bb7c2d (diff-f9112caf8cb75e7a48a7b84987724d754181227385fbfcc2cc09a879b1f97c12L171-L223)

`Terminal::SelectNewRegion` is the only thing that uses the return value
from `Terminal::_ScrollToPoints`. Before that PR, `_ScrollToPoints` was
just a part of `SelectNewRegion`, and it moved the start & end coords by
the `_VisibleStartIndex`, not the `_scrollOffset`.

Kinda weird there weren't any _other_ tests for `SelectNewRegion`?

I also caught a second bug while I was here - If you had a line with an
exact wrap, and tried to select that like with selectOutput, we'd
explode.

Closes #17131
2024-05-01 15:06:33 +00:00
Leonard Hecker
32fbb16d43 Fix search constantly triggering a scroll (#17132)
This addresses a review comment left by tusharsnx in #17092 which I
forgot to fix before merging the PR. The fix itself is somewhat simple:
`Terminal::SetSearchHighlightFocused` triggers a scroll if the target
is outside of the current (scrolled) viewport and avoiding the call
unless necessary fixes it. To do it properly though, I've split up
`Search::ResetIfStale` into `IsStale` and `Reset`. Now we can properly
detect staleness in advance and branch out the search reset cleanly.

Additionally, I've taken the liberty to replace the `IVector` in
`SearchResultRows` with a direct `const std::vector&` into `Searcher`.
This removes a bunch of code and makes it faster to boot.

## Validation Steps Performed
* Print lots of text
* Search a common letter
* Scroll up
* Doesn't scroll back down 
* Hold enter to search more occurrences scrolls up as needed 
* `showMarksOnScrollbar` still works 
2024-04-30 20:48:05 +00:00
Yusuf Al-Khawaldeh
6bc7b9e68b Fix the bad default light theme selection background color (#16789)
## Summary of the Pull Request
Fixed default selection background colors with light schemes. Default
color now matches the scheme and contrasts well
## References and Relevant Issues
none
## Detailed Description of the Pull Request / Additional comments
This is my first contribution ever :) Even though its simple, im happy
to help
## Validation Steps Performed

## PR Checklist
- [ ] Closes #8716 
- [ ] Tests added/passed
- [ ] Documentation updated
- If checked, please file a pull request on [our docs
repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
- [ ] Schema updated (if necessary)
2024-04-29 18:59:59 +00:00
Dustin L. Howett
af91e6ef58 [clang-tidy] Remove in-product uses of std::bind (#16870)
These changes were automatically generated by clang-tidy.

```
clang-tidy --checks=modernize-avoid-bind --fix
```

I have not bothered with the test code.

---------

Co-authored-by: Mike Griese <migrie@microsoft.com>
2024-04-29 17:58:55 +00:00
Dustin L. Howett
5d2d3856a7 build: force the latest VCToolsVersion; see DD-1541167 for more (#17156)
Stolen from PowerToys.

BODGY
2024-04-29 17:52:00 +00:00
Leonard Hecker
5b8eadb2ea Make UTextFromTextBuffer newline aware (#17120)
This PR achieves two things:
* When encountering rows with newlines (`WasForceWrapped` = `false`)
  we'll now copy the contents out of the row and append a `\n`.
  To make `utext_clone` cheap, it adds a reference counted buffer.
* Text extraction in `Terminal::GetHyperlinkAtBufferPosition`
  was fixed by using a higher level `TextBuffer::GetPlainText`
  instead of iterating through each cell.

Closes #16676
Closes #17065

## Validation Steps Performed
* In pwsh execute the following:
  ``"`e[999C`e[22Dhttps://example.com/foo`nbar"``
* Hovering over the URL only underlines `.../foo` and not `bar` 
* The tooltip ends in `.../foo` and not `.../fo` 
2024-04-29 16:43:47 +00:00
PankajBhojwani
be5a240ec6 No longer serialize generated IDs (#17145)
We will no longer serialize IDs that we generated for the user.
This change is being made so that we can release user action IDs at the
same time as the features that require them!

Validation: Generated IDs do not get written to the json, user-made IDs
still do

Closes #17109
2024-04-29 14:57:47 +00:00
James Holderness
ef318a1450 Fix the DECTCEM reset position in the conpty stream (#17148)
## Summary of the Pull Request

When the conpty renderer determines that it needs to hide the cursor,
it does so by inserting a `DECTCEM` reset sequence at the start of the
output buffer, assuming that is the start of the frame. But when the
`_noFlushOnEnd` flag is set, you can have multiple frames pending in the
buffer, and the `DECTCEM` sequence will then end up in the wrong place.

This PR fixes the issue by saving the buffer size at the start of the
frame, and using that saved offset as the insert position for the
`DECTCEM` sequence.

## Validation Steps Performed

I have a game that was frequently affected by this issue (the cursor
would be visible when it was meant to be hidden). With this PR applied,
it now works perfectly.

## PR Checklist
- [x] Closes #15449
2024-04-29 11:55:09 +00:00
PankajBhojwani
378b6594bd Add action ID to schema (#17146)
Closes #17122
2024-04-26 16:34:01 -07:00
Mike Griese
d14ff939dc Fix repositioning with the cursor, again (#17141)
This shouldn't have ever worked...? This looks like it was a typo and
should have been `mark.end`.

Thanks @joadoumie for asking about the moving the cursor in the prompt,
that convo lead to me finding this.
2024-04-26 21:23:39 +00:00
Dustin L. Howett
41bb28c46d Update Cascadia Code to 2404.23 (#17137)
This update adds support for:

- Unicode 16 Large Type Pieces (they are really cool, you *have* to see
them)
- Unicode 13 Sextants (U+1FB00 - U+1FB3B)
- Octants, sedecimants, eights, miscellanrous blocks, separated
quadrants and sextants, and diagonals
- Segmented digits (think LED numbers)
- Checkerboards

It also fixes the coordinate system used in all of the blocks,
half-blocks, quadrants and eights for consistency.

This update does **not** include the new "Nerd Fonts" variant of
Cascadia Code or Cascadia Mono.

With big thanks to @PhMajerus for contributing all of the new symbols
for legacy computing.

See microsoft/cascadia-code#723, microsoft/cascadia-code#708 and
microsoft/cascadia-code#727 for more details.
2024-04-26 08:08:37 -07:00
Leonard Hecker
8d67477a1a AtlasEngine: Improve debuggability (#17136)
This is some test code and natvis fixes that I used to trace down
an issue during font rendering.
2024-04-26 11:20:21 +00:00
Windows Console Service Bot
26900ca472 Localization Updates - main - 04/25/2024 03:04:34 (#17125) 2024-04-25 22:16:02 -05:00
Mike Griese
f36d589a8e Fix persisting the size of a focus mode window (#17068)
While I was fixing the initial position thing, I figured I'd fix this
too. We were mistakenly accounting for the size of the titlebar when we
should launch into focus mode (without one)

Closes #10730
2024-04-25 11:55:28 +00:00
Leonard Hecker
0c3c7470b0 Add a system message to session restore (#17113)
This adds a system message which displays the time at which the
buffer snapshot was written to disk.

Additionally, this PR moves the snapshot loading into a background
thread, so that the UI thread is unblocked and that multiple
tabs/panes can load simultaneously.

Closes #17031
Closes #17074

## Validation Steps Performed
Repeatedly closing and opening WT adds more and more messages.
Currently, the messages get somewhat corrupted due to a bug
in our line-wrap handling, or some similar part.
2024-04-24 14:23:50 -07:00
Dustin L. Howett
19f43f70bd build: disable CheckCFlags for now, as it is blowing up the build (#17116)
OneBranch no likey. A test build is running now.
2024-04-24 13:00:57 -05:00
Dustin L. Howett
3a63832c31 [REPLAY] Move to AzureFileCopy@6 for Managed Identity support (#17121)
This is required for us to move off Entra ID Application identity.

(cherry picked from commit 2e7c3fa313)

This was approved in #16957, so I will merge with one signoff.
2024-04-24 12:28:02 -05:00
PankajBhojwani
ce4e0df7b0 Update Azure Cloud Shell API to the newer version (#17115)
Updates the `api-version` to `2023-02-01-preview` when requesting for
CloudShell settings and shell

## Validation Steps Performed
Can still use Azure Cloud Shell through Windows Terminal
2024-04-23 19:17:08 -05:00
Leonard Hecker
360e86b536 Fix search highlights during reflow (#17092)
This PR extends `til::throttled_func` to also support debouncing:
* throttling: "At most 1 call every N seconds"
* debouncing: "Exactly 1 call after N seconds of inactivity"

Based on the latter the following series of changes were made:
* An `OutputIdle` event was added to `ControlCore` which is
  raised once there hasn't been any incoming data in 100ms.
  This also triggers an update of our regex patterns (URL detection).
* The event is then caught by `TermControl` which calls `Search()`.
* `Search()` in turn was modified to return its results by-value
  as a struct, which avoids the need for a search-update event
  and simplifies how we update the UI.

This architectural change, most importantly the removal of the
`TextLayoutUpdated` event, fixes a DoS bug in Windows Terminal:
As the event leads to UI thread activity, printing lots of text
continuously results in the UI thread becoming unresponsive.

On top of these, a number of improvements were made:
* `IRenderEngine::InvalidateHighlight` was changed to take the
  `TextBuffer` by-reference which avoids the need to accumulate the
  line renditions in a `std::vector` first. This improves Debug build
  performance during reflow by what I guess must be roughly
  a magnitude faster. This difference is very noticeable.
* When closing the search box, `ClearSearch()` is called to remove
  the highlights. The search text is restored when it's reopened,
  however the current search position isn't.

Closes #17073
Closes #17089

## Validation Steps Performed
* UIA announcements:
  * Pressing Ctrl+Shift+F the first time does not lead to one 
  * Typing the first letter does 
  * Closing doesn't 
  * Reopening does (as it restores the letter) 
* Closing the search box dismisses the highlights 
* Resizing the window recalculates the highlights 
* Changing the terminal output while the box is open
  recalculates the highlights 
2024-04-23 22:04:35 +00:00
Mike Griese
87a9f72b9a Don't explode when duplicating a pane (#17110)
I forgot to check here if the `INewContentArgs` were null or not. Pretty
dumb mistake honestly.

Closes #17075
Closes #17076
2024-04-23 19:41:59 +00:00
Leonard Hecker
daffb2dbbf AtlasEngine: Fix custom shader time imprecision (#17104)
Since floats are imprecise we need to constrain the time value into a
range that can be accurately represented. Assuming a monitor refresh
rate of 1000 Hz, we can still easily represent 1000 seconds accurately
(roughly 16 minutes). So to solve this, we'll simply treat the shader
time modulo 1000s. This may lead to some unexpected jank every 16min
but it keeps any ongoing animation smooth otherwise.
2024-04-23 16:19:38 +00:00
Leonard Hecker
a590a1bff0 Fix TerminalPage not being released on window close (#17107)
Because this holds onto the root element, `TerminalPage` gets "leaked"
on Windows 10 when a window is closed until another is opened.

## Validation Steps Performed
* Set a breakpoint in `Renderer::~Renderer`
* Open and close a window
* Breakpoint used to not get hit and now it does 
2024-04-23 16:18:12 +00:00
Jvr
19c24aced9 Update actions/add-to-project to 1.0.1 (#17097) 2024-04-23 09:16:46 -07:00
Leonard Hecker
99061ee272 Use float instead of double by default (#17100)
While `double` is probably generally preferable for UI code,
our application is essentially a complex wrapper wrapper around
DWrite, D2D and D3D, all of which use `float` exclusively.

Of course it also uses XAML, but that one uses `float` for roughly
1/3rd of its API functions, so I'm not sure what it prefers.
Additionally, it's mostly a coincidence that we use WinUI/XAML for
Windows Terminal whereas DWrite/D2D/D3D are effectively essential.
This is demonstrated by the fact that we have a `HwndTerminal`,
while there's no alternative to e.g. D3D on Windows.

The goal of this PR is that DIP based calculations never end up
mixing `float` and `double`. This PR also changes opacity-related
values to `float` because I felt like that fits the theme.
2024-04-23 00:07:00 +00:00
Leonard Hecker
f49cf44b79 Add more TraceLogging to ApiDispatchers (#17085)
More TraceLogging = More better?
I made this change as I noticed that most calls are not being logged.
Even after this change some crucial information won't be logged
(for instance arrays of `INPUT_RECORD`), because I couldn't come up
with a clever way to do so, but I think this is better than nothing.
2024-04-22 20:45:10 +00:00
Leonard Hecker
4e7b63c664 A minor TSF refactoring (#17067)
Next in the popular series of minor refactorings:
Out with the old, in with the new!

This PR removes all of the existing TSF code, both for conhost and
Windows Terminal. conhost's TSF implementation was awful:
It allocated an entire text buffer _per line_ of input.
Additionally, its implementation spanned a whopping 40 files and
almost 5000 lines of code. Windows Terminal's implementation was
absolutely fine in comparison, but it was user unfriendly due to
two reasons: Its usage of the `CoreTextServices` WinRT API indirectly
meant that it used a non-transitory TSF document, which is not the
right choice for a terminal. A `TF_SS_TRANSITORY` document (-context)
indicates to TSF that it cannot undo a previously completed composition
which is exactly what we need: Once composition has completed we send
the result to the shell and we cannot undo this later on.
The WinRT API does not allow us to use `TF_SS_TRANSITORY` and so it's
unsuitable for our application. Additionally, the implementation used
XAML to render the composition instead of being part of our text
renderer, which resulted in the text looking weird and hard to read.

The new implementation spans just 8 files and is ~1000 lines which
should make it significantly easier to maintain. The architecture is
not particularly great, but it's certainly better than what we had.
The implementation is almost entirely identical between both conhost
and Windows Terminal and thus they both also behave identical.
It fixes an uncountable number of subtle bugs in the conhost TSF
implementation, as it failed to check for status codes after calls.
It also adds several new features, like support for wavy underlines
(as used by the Japanese IME), dashed underlines (the default for
various languages now, like Vietnamese), colored underlines,
colored foreground/background controlled by the IME, and more!

I have tried to replicate the following issues and have a high
confidence that they're resolved now:
Closes #1304
Closes #3730
Closes #4052
Closes #5007  (as it is not applicable anymore)
Closes #5110
Closes #6186
Closes #6192
Closes #13805
Closes #14349
Closes #14407
Closes #16180

For the following issues I'm not entirely sure if it'll fix it,
but I suspect it's somewhat likely:
#13681
#16305
#16817

Lastly, there's one remaining bug that I don't know how to resolve.
However, that issue also plagues conhost and Windows Terminal
right now, so it's at least not a regression:
* Press Win+. (emoji picker) and close it
* Move the window around
* Press Win+.

This will open the emoji picker at the old window location.
It also occurs when the cursor moves within the window.
While this is super annoying, I could not find a way to fix it.

## Validation Steps Performed
* See the above closed issues
* Use Vietnamese Telex and type "xin choaf"
  Results in "xin chào" 
* Use the MS Japanese IME and press Alt+`
  Toggles between the last 2 modes 
* Use the MS Japanese IME, type "kyouhaishaheiku", and press Space
  * The text is converted, underlined and the first part is
    doubly underlined 
  * Left/Right moves between the 3 segments 
  * Home/End moves between start/end 
  * Esc puts a wavy line under the current segment 
* Use the Korean IME, type "gksgks"
  This results in "한한" 
* Use the Korean IME, type "gks", and press Right Ctrl
  Opens a popup which allows you to navigate with Arrow/Tab keys 
2024-04-18 17:47:28 +00:00
PankajBhojwani
06ab6f3e1f Add IDs to Commands (#16904)
As laid out in #16816, adds an `ID` field to `Command`.

**This first PR only adds IDs for built-in commands in defaults, and
generates IDs for user-created commands that don't define an ID.** Also
note that for now we **will not** be allowing IDs for iterable/nested
commands.

The follow-up PR is where we will actually use the IDs by referring to
commands with them.

Refs #16816 

## Validation Steps Performed
User-created commands in the settings file get rewritten with generated
IDs
2024-04-18 00:30:25 +00:00
Mike Griese
643f7167a6 Also remember to persist window positions (#17066)
This got lost in #16598. `TerminalPage` needs to ask the window where
the it actually is, so it can persist it. More details in
https://github.com/microsoft/terminal/pull/16598#discussion_r1511519304

Closes #17010
2024-04-17 17:52:29 +00:00
Tushar Singh
90b8bb7c2d Improve Search Highlighting (#16611)
### The changeset involves:
- Decoupling Selection and Search Highlighting code paths.
- We no longer invalidate search highlights when:
  - Left-clicking on terminal
  - A new selection is made
  - Left-clicking on Search-box
- Dispatching Find Next/Prev Match Action. (The search highlight was
removed after pressing the first key of the Action's key combination)
- And, anything that doesn't change buffer content, shouldn't invalidate
the highlighted region (E.g. Cursor movement)
- Highlighting foreground color is *actually* applied to the highlighted
text.
- Double-clicking on SearchBox no longer starts a text selection in the
terminal.
- Selected text is properly populated in the Search Box (#16355)

Closes: #16355


![image](https://github.com/microsoft/terminal/assets/55626797/8fd0345b-a8b2-4bc2-a25e-15d710127b63)

## Some Implementation Details

### Detecting text layout changes in the Control layer

As Search Highlight regions need to be removed when new text is added,
or the existing text is re-arranged due to window resize or similar
events, a new event `TextLayoutUpdated` is added that notifies
`CoreControl` of any text layout changes. The event is used to
invalidate and remove all search highlight regions from the buffer
(because the regions might not be _fresh_ anymore.

The new event is raised when:
1. `AdaptDispatch` writes new text into the buffer.
2. MainBuffer is switched to AltBuffer or vice-versa.
3. The user resized the window.
4. Font size changed.
5. Zoom level changed.

(Intensionally,) It's not raised when:
1. Buffer is scrolled.
2. The text cursor is moved.

When `ControlCore` receives a `TextLayoutUpdated` event, it clears the
Search Highlights in the *render data*, and raises an
`UpdateSearchResults` event to notify `TermControl` to update the Search
UI (`SearchBoxControl`).

In the future, we can use `TextLayoutUpdated` event to start a new
search which would refresh the results automatically after a slight
delay (throttled). *VSCode already does this today*.

### How does AtlasEngine draw the highlighted regions?

We follow a similar idea as for drawing the Selection region. When new
regions are available, the old+new regions are marked invalidated.
Later, a call to `_drawHighlighted()` is made at the end of
`PaintBufferLine()` to override the highlighted regions' colors with
highlight colors. The highlighting colors replace the buffer colors
while search highlights are active.

Note that to paint search highlights, we currently invalidate the row
completely. This forces text shaping for the rows in the viewport that
have at least one highlighted region. This is done to keep the (already
lengthy) PR... simple. We could take advantage of the fact that only
colors have changed and not the characters (or glyphs). I'm expecting
that this could be improved like:
1. When search regions are added, we add the highlighting colors to the
color bitmaps without causing text shaping.
2. When search regions are removed, we re-fill the color bitmaps with
the original colors from the Buffer.

## Validation Steps:
- New text, window resize, font size changes, zooming, and pasting
content into the terminal removes search highlights.
- highlighting colors override the foreground and background color of
the text (in the rendered output).
- Blinking, faded, reverse video, Intense text is highlighted as
expected.
2024-04-17 16:11:31 +00:00
Tushar Singh
d632c39cc3 Fix wrong CommandPallete access (#17069)
Closes: #17032

We were wrongly calling the Ctor of CommandPalette which led to the
creation of an uninitialized winrt command palette object, and then
OnCreateAutomationPeer() was called on that. This seems to be the cause
of #17032.

## Validation Steps Performed
- Open WT.
- Try to tear off a tab out of the tab headers view.
- WT doesn't crash.
2024-04-16 19:00:31 +00:00
Tushar Singh
11c4aa459d Fix window style under minimized state (#17058)
Closes: #13961

This PR changes the window styling we use under the minimized state. We
now retain the active window styling so the content's height doesn't
change when switching between minimized and maximized states.

## Validation Steps Performed
- Open Terminal and go into Maximized mode.
- Click on the Minimize button.
- No `SizeChanged` event in `ControlCore`.
- Click on the WT icon in the taskbar to restore it.
- No `SizeChanged` event in `ControlCore`.
2024-04-16 15:36:59 +00:00
Windows Console Service Bot
f4d8a74082 Localization Updates - main - associated with #16886 (#17035) 2024-04-16 08:36:13 -07:00
Leonard Hecker
5f3a857192 Replace WinRT clipboard API with Win32 for copying (#17006)
In the spirit of #15360 this implements the copy part.
The problem is that we have an issue accessing the clipboard while
other applications continue to work just fine. The major difference
between us and the others is that we use the WinRT clipboard APIs.
So, the idea is that we just use the Win32 APIs instead.

The feel-good side-effect is that this is (no joke) 200-1000x faster,
but I suspect no one will notice the -3ms difference down to <0.01ms.

The objective effect however is that it just works.

This may resolve #16982.

## Validation Steps Performed
* Cycle through Text/HTML/RTF-only in the Interaction settings
* Paste the contents into Word each time
* Text is plain and HTML/RTF are colored 
2024-04-10 19:35:11 +00:00
Leonard Hecker
20b0bed46d Reduce cost of cursor invalidation (#15500)
Performance of printing enwik8.txt at the following block sizes:
4KiB (printf): 53MB/s -> 58MB/s
128KiB (cat): 170MB/s -> 235MB/s

This commit is imperfect. Support for more than one rendering
engine was "hacked" into `Renderer` and is not quite correct.
As such, this commit cannot fix cursor invalidation correctly either,
and while some bugs are fixed (engines may see highly inconsistent
TextBuffer and Cursor states), it introduces others (an error in the
first engine may result in the second engine not executing).
Neither of those are good and the underlying issue remains to be fixed.

## Validation Steps Performed
* Seems ok? 
2024-04-10 18:51:02 +00:00
Leonard Hecker
4fd15c9937 Remove dependency on IsGlyphFullWidth for IRM/DECSWL (#16903)
This gets rid off the implicit dependency on `IsGlyphFullWidth`
for the IRM and DECSWL/DECDWL/DECDHL implementations.

## Validation Steps Performed
In pwsh:
* ``"`e[31mab`e[m`b`e[4h`e[32m$('*'*10)`e[m`e[4l"``
  prints a red "a", 10 green "*" and a red "b" 
* ``"`e[31mab`e[m`b`e[4h`e[32m$('*'*1000)`e[m`e[4l"``
  prints a red "a" and a couple lines of green "*" 
* ``"`e[31mf$('o'*70)`e[m`e#6`e#5"``
  the right half of the row is erased 
2024-04-10 15:12:40 +00:00
Harsh Narayan Jha
8bd9578b3c Fix: UI style errors: Menu items capitalization and … (ellipses) mark misuse (#16886)
I changed the improper capitalization and misuse of ellipses mark (...)
in the context menu and various other places.

Fixes issues #16819 and #16846

## PR Checklist
- [ ] Closes #16846
- [x] Tests added/passed - NA
- [x] Documentation updated - NA
- If checked, please file a pull request on [our docs
repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
- [x] Schema updated (if necessary) - NA
2024-04-10 00:11:43 +00:00
Marcel W
7adc3743d8 Add more profile GUID tests (#17030)
## Summary of the Pull Request
Adding more profile GUID tests
## References and Relevant Issues
Closes #2119 
## Detailed Description of the Pull Request / Additional comments

Currently, there are formats that simply break GUID parsing (the
commented out test cases). Should we catch that and treat it like a
"null" GUID or should we generate a new GUID for those profiles?

## Validation Steps Performed

## PR Checklist
- [x] Closes #2119 
- [x] Tests added/passed
- [ ] Documentation updated
- If checked, please file a pull request on [our docs
repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
- [ ] Schema updated (if necessary)
2024-04-09 19:43:00 +00:00
Windows Console Service Bot
b90eb93d26 Localization Updates - main - 04/06/2024 03:04:16 (#17025) 2024-04-08 12:25:58 -05:00
Mike Griese
156b9aeea6 Make marks a stable feature (#16938)
* Switches the marks feature to being stable. 
* Renames the settings, to remove "experimental."



Stacked on top of #16937, so that we actually finish reflow before
merging this.

Closes #15057
2024-04-05 20:43:44 +00:00
Mike Griese
c3f44f7730 Rewrite how marks are stored & add reflow (#16937)
This is pretty much a huge refactoring of how marks are stored in the
buffer.

Gone is the list of `ScrollMark`s in the buffer that store regions of
text as points marking the ends. Those would be nigh impossible to
reflow nicely.

Instead, we're going to use `TextAttribute`s to store the kind of output
we've got - `Prompt`, `Command`, `Output`, or, the default, `None`.
Those already reflow nicely!

But we also need to store things like, the exit code for the command.
That's why we've now added `ScrollbarData` to `ROW`s. There's really
only going to be one prompt->output on a single row. So, we only need to
store one ScrollbarData per-row. When a command ends, we can just go
update the mark on the row that started that command.

But iterating over the whole buffer to find the next/previous
prompt/command/output region sounds complicated. So, to avoid everyone
needing to do some variant of that, we've added `MarkExtents` (which is
literally just the same mark structure as before). TextBuffer can figure
out where all the mark regions are, and hand that back to callers. This
allows ControlCore to be basically unchanged.

_But collecting up all the regions for all the marks sounds expensive!
We need to update the scrollbar frequently, we can't just collect those
up every time!_ No we can't! But we also don't need to. The scrollbar
doesn't need to know where all the marks start and end and if they have
commands and this and that - no. We only need to know the rows that have
marks on them. So, we've now also got `ScrollMark` to represent just a
mark on a scrollbar at a specific row on the buffer. We can get those
quickly.

* [x] I added a bunch of tests for this. 
* [x] I played with it and it feels good, even after a reflow (finally)
* See:
  * #11000
* #15057 (I'm not marking this as closed. The stacked PR will close
this, when I move marks to Stable)
2024-04-05 20:16:10 +00:00
Mike Griese
dc4026d184 Add support for restoring non-terminal panes, and opening them with splitPane, newTab (#16914)
This changes `NewTabArgs`, `SplitPaneArgs`, and `NewWindowArgs` to
accept a `INewContentArgs`, rather than just a `NewTerminalArgs`. This
allows a couple things:
* Users can open arbitrary types of panes with the existing `splitPane`,
`newWindow` actions, just by passing `"type": "scartchpad"` (for
example). This is a lot more flexible than re-defining different
`"openScratchpad"`, `"openTasksPane"`, etc, etc actions for every kind
of pane.
* This allows us to use the existing machinery of session restore to
also restore non-terminal panes.

The `type` property was added to `newTab`, `splitPane`, `newWindow`.
When omitted, we still just treat the json as a blob of NewTerminalArgs.

There's not actually any other kinds of `INewContentArgs` in this PR
(other than the placeholder `GenericContentArgs`). In
[`dev/migrie/fhl/md-pane`](https://github.com/microsoft/terminal/compare/dev/migrie/f/tasks-pane...dev/migrie/fhl/md-pane),
I have a type of pane that would LOVE to add some args here. So that's
forward-thinking.

There's really just two stealth types of pane for now: `settings`, and
`scratchpad`. Those I DON'T have as constants or anything in this PR.
They probably should be? Though, I suspect around the time of the tasks
& MD panes, I'll come up with whatever structure I actually want them to
take.

### future considerations here

* In the future, this should allow extensions to say "I know how to host
`foo` content", for 3p content.
* The `wt` CLI args were not yet updated to also accept `--type` yet.
There's no reason we couldn't easily do that.
* I considered adding `ICanHasCommandline` to allow arbitrary content to
generate a `wt` commandline-serializable string. Punted on that for now.


## other PRs
* #16170
  * #16171 
    * #16172 
      * #16895 
      * #16914 <-- you are here 

Closes #17014
2024-04-05 19:29:27 +00:00
Mike Griese
c063d2bad6 Change default pane keybindings to duplicate, rather than use default profile (#16951)
As we discussed in length over at #7657. 

This changes the default <kbd>alt+shift+-</kbd> and
<kbd>alt+shift+plus</kbd> keybindings to split panes by duplicating the
pane by default.

Closes #7657
2024-04-05 19:24:07 +00:00
Leonard Hecker
6a69b94fc6 Increase usage of fmt and FMT_COMPILE (#17012)
This is a rather simple PR overall. It mostly touches either test
or tracing code. Only a few changes affect the actual runtime.

The goal of this changeset is to get rid of the `double` format tables
in the OpenConsole build by using `FMT_COMPILE` everywhere.
2024-04-05 18:55:04 +00:00
Leonard Hecker
8d6e7a8a78 Buffer Restore: Fix serializing >32KiB (#17022)
I forgot to `buffer.clear()` after a write. Whoops.

This includes 2 additional, smaller improvements that I just happened
to notice: The `GenRTF` code calls `to_string` despite using `fmt`.
2024-04-05 18:54:31 +00:00
Mike Griese
1a6ba43dd2 Get rid of UpdateTerminalSettings (#17009)
As @lhecker noted in the #16172 review, `UpdateTerminalSettings` is
wacky. We can just pass the cache in at the start, then reset it and
reuse it in `UpdateSettings`. One fewer `try_as`!
2024-04-05 14:45:21 +00:00
Mike Griese
67ae9f6c3e Refactor the SettingsTab to be a pane (#16172)
... technically. We still won't let it actually _be_ a pane, but now it
acts like one. It's hosted in a `SettingsPaneContent`. There's no more
`SettingsTab`. It totally _can_ be in a pane (but don't?)

## Validation Steps Performed

* Still opens the settings
* Only opens a single settings tab, or re-activates the existing one
* Session restores!
* Updates the title of the tab appropriately
* I previously _did_ use the scratchpad action to open the settings in a
pane, and that worked.

## Related PRs
* #16170
  * #16171 
    * #16172 <-- you are here 
      * #16895

Refs #997
Closes #8452
2024-04-03 15:31:13 +00:00
Dustin L. Howett
2bcbe6b492 ci/rel: publish symbols using the internal symbol request API instead (#16991)
Work is ongoing to remove individually-authenticated service accounts
from some pipelines. This moves us closer to that goal.

Tested in Nightly 2403.28002.
2024-04-02 22:52:29 +00:00
Mike Griese
04fa18de71 Scratch tool: generate a fragment extension with every color scheme (#16962)
#16953 got me thinking: what if we just published an extension ourselves
that just packages up every color scheme in the ever-amazing
https://github.com/mbadolato/iTerm2-Color-Schemes?

Well, this isn't a package for that file. 

But it is a script to generate a fragment with all of them, and blat it
into your `%LOCALAPPDATA%\Microsoft\Windows Terminal\Fragments`.

It's a notebook because I've been really fascinated with the Polyglot
Notebooks recently.
2024-04-02 20:27:43 +00:00
Tushar Singh
4d58137bd4 Fix selection expansion for Double-Width and Double-Height rows (#16812)
Closes #16782

### Validation Steps Performed
- Double-clicking on a Double-Width row selects the word (identified by
delimiters) under the cursor.
- Tripple-clicking on a Double-Width row selects the whole line under
the cursor.
- The same works for Double-Height rows also.
- The same works for Single-Width rows also.
2024-04-02 19:57:19 +00:00
Marcel W
ad0c28b30d Add clamping of initial rows and columns settings (#16989)
This clamps the initial rows and columns settings in two areas:
- When reading the JSON file
- In the settings dialogue

For consistency, I've also added a minimum value to the NumberBoxes even
though the default Minimum is 1. The Maximum and Minimum are taken from
the JSON Schema file (Min 1, Max 999).

Closes #11957

---------

Co-authored-by: Dustin L. Howett <dustin@howett.net>
2024-04-02 17:56:26 +00:00
Mike Griese
5f1015953f Don't explode on session restore (#16998)
As noted in #16995. 

Don't persist us if we weren't ever initialized. In that case, we
never got an initial size, never instantiated a buffer, and didn't
start the connection yet, so there's nothing for us to add here.

If we were supposed to be restored from a path, then we don't need to
do anything special here. We'll leave the original file untouched,
and the next time we actually are initialized, we'll just use that
file then.

Closes #16995
2024-04-02 17:08:03 +00:00
462 changed files with 14194 additions and 12150 deletions

View File

@@ -80,6 +80,7 @@ mnt
mru
nje
noreply
notwrapped
ogonek
ok'd
overlined

View File

@@ -1,6 +1,8 @@
ACLs
ADMINS
advapi
akv
AKV
altform
altforms
appendwttlogging
@@ -14,6 +16,7 @@ autoexec
backplating
bitmaps
BOMs
checkcflags
COMPUTERNAME
CPLs
cpptools
@@ -32,6 +35,7 @@ DWINRT
enablewttlogging
HOMESHARE
Intelli
issecret
IVisual
libucrt
libucrtd
@@ -74,6 +78,7 @@ sid
Skype
SRW
sxs
symbolrequestprod
Sysinternals
sysnative
systemroot
@@ -99,3 +104,4 @@ wtl
wtt
wttlog
Xamarin
xfgcheck

View File

@@ -1,5 +0,0 @@
EOB
swrapped
wordi
wordiswrapped
wrappe

View File

@@ -1,4 +1,3 @@
AAAa
AAAAA
AAAAAAAAAAAAA
AAAAAABBBBBBCCC

View File

@@ -1,3 +1,4 @@
aaaaabbb
aabbcc
ABANDONFONT
abbcc
@@ -9,6 +10,7 @@ ACCESSTOKEN
acidev
ACIOSS
ACover
acp
actctx
ACTCTXW
ADDALIAS
@@ -16,6 +18,8 @@ ADDREF
ADDSTRING
ADDTOOL
AFew
adml
admx
AFill
AFX
AHelper
@@ -66,10 +70,10 @@ ASBSET
asdfghjkl
ASetting
ASingle
ASYNCDONTCARE
ASYNCWINDOWPOS
atch
ATest
ATTRCOLOR
aumid
Authenticode
AUTOBUDDY
@@ -92,6 +96,8 @@ backported
backstory
barbaz
Bazz
bbb
bbccb
BBDM
bbwe
bcount
@@ -121,8 +127,6 @@ Blt
BLUESCROLL
BODGY
BOLDFONT
BOOLIFY
bools
Borland
boutput
boxheader
@@ -153,7 +157,6 @@ cazamor
CBash
cbiex
CBN
CBoolean
cbt
CCCBB
cch
@@ -161,12 +164,9 @@ CCHAR
CCmd
ccolor
CCom
CComp
CConsole
CConversion
CCRT
cdd
CEdit
CELLSIZE
cfae
cfie
@@ -176,18 +176,17 @@ CFuzz
cgscrn
chafa
changelists
chaof
charinfo
CHARSETINFO
chh
chshdng
CHT
Cic
CLASSSTRING
CLE
cleartype
CLICKACTIVE
clickdown
CLIENTID
clipbrd
CLIPCHILDREN
CLIPSIBLINGS
@@ -226,7 +225,6 @@ commdlg
COMMITID
componentization
conapi
conareainfo
conattrs
conbufferout
concfg
@@ -237,8 +235,7 @@ condrv
conechokey
conemu
conhost
conime
conimeinfo
CONIME
conintegrity
conintegrityuwp
coninteractivitybase
@@ -250,6 +247,7 @@ CONKBD
conlibk
conmsgl
CONNECTINFO
connyection
CONOUT
conprops
conpropsp
@@ -276,7 +274,6 @@ contentfiles
conterm
contsf
contypes
convarea
conwinuserrefs
coordnew
COPYCOLOR
@@ -311,7 +308,6 @@ csrutil
CSTYLE
CSwitch
CTerminal
CText
ctl
ctlseqs
CTRLEVENT
@@ -319,7 +315,7 @@ CTRLFREQUENCY
CTRLKEYSHORTCUTS
Ctrls
CTRLVOLUME
Ctxt
CUAS
CUF
cupxy
CURRENTFONT
@@ -483,7 +479,6 @@ DISABLEDELAYEDEXPANSION
DISABLENOSCROLL
DISPATCHNOTIFY
DISPLAYATTRIBUTE
DISPLAYATTRIBUTEPROPERTY
DISPLAYCHANGE
distros
dlg
@@ -559,7 +554,7 @@ entrypoints
ENU
ENUMLOGFONT
ENUMLOGFONTEX
enumranges
EOB
EOK
EPres
EQU
@@ -615,10 +610,10 @@ FILTERONPASTE
FINDCASE
FINDDLG
FINDDOWN
FINDREGEX
FINDSTRINGEXACT
FINDUP
FIter
FIXEDCONVERTED
FIXEDFILEINFO
Flg
flyouts
@@ -733,9 +728,8 @@ Greyscale
gridline
gset
gsl
GTP
guc
guidatom
GUIDATOM
GValue
GWL
GWLP
@@ -777,6 +771,7 @@ HIWORD
HKCU
hkey
hkl
HKLM
hlocal
hlsl
HMB
@@ -834,7 +829,6 @@ IEnd
IEnum
IFACEMETHODIMP
ification
IGNOREEND
IGNORELANGUAGE
IHosted
iid
@@ -858,8 +852,8 @@ inkscape
INLINEPREFIX
inproc
Inputkeyinfo
INPUTPROCESSORPROFILE
Inputreadhandledata
INPUTSCOPE
INSERTMODE
INTERACTIVITYBASE
INTERCEPTCOPYPASTE
@@ -870,9 +864,7 @@ INVALIDARG
INVALIDATERECT
Ioctl
ipch
ipp
IProperty
IPSINK
ipsp
IShell
ISwap
@@ -892,7 +884,6 @@ JOBOBJECT
JOBOBJECTINFOCLASS
JPN
jsoncpp
Jsons
jsprovider
jumplist
KAttrs
@@ -922,6 +913,7 @@ KLMNOPQRSTY
KOK
KPRIORITY
KVM
kyouhaishaheiku
langid
LANGUAGELIST
lasterror
@@ -984,7 +976,6 @@ lpdw
lpelfe
lpfn
LPFNADDPROPSHEETPAGE
lpl
LPMEASUREITEMSTRUCT
LPMINMAXINFO
lpmsg
@@ -1060,6 +1051,7 @@ MENUITEMINFO
MENUSELECT
messageext
metaproj
Mgrs
microsoftpublicsymbols
midl
mii
@@ -1114,7 +1106,6 @@ muxes
myapplet
mybranch
mydir
MYMAX
Mypair
Myval
NAMELENGTH
@@ -1158,6 +1149,7 @@ NOCOPYBITS
NODUP
noexcepts
NOFONT
NOHIDDENTEXT
NOINTEGRALHEIGHT
NOINTERFACE
NOLINKINFO
@@ -1181,6 +1173,7 @@ NORMALDISPLAY
NOSCRATCH
NOSEARCH
noselect
NOSELECTION
NOSENDCHANGING
NOSIZE
NOSNAPSHOT
@@ -1271,6 +1264,7 @@ packageuwp
PACKAGEVERSIONNUMBER
PACKCOORD
PACKVERSION
pacp
pagedown
pageup
PAINTPARAMS
@@ -1282,7 +1276,7 @@ parms
PATCOPY
pathcch
PATTERNID
pcat
pbstr
pcb
pcch
PCCHAR
@@ -1306,9 +1300,9 @@ PCSTR
PCWCH
PCWCHAR
PCWSTR
pda
pdbs
pdbstr
pdcs
PDPs
pdtobj
pdw
@@ -1338,6 +1332,7 @@ PIDLIST
pids
pii
piml
pimpl
pinvoke
pipename
pipestr
@@ -1367,10 +1362,11 @@ POSTCHARBREAKS
POSX
POSXSCROLL
POSYSCROLL
ppbstr
PPEB
ppf
ppguid
ppidl
pprg
PPROC
ppropvar
ppsi
@@ -1399,7 +1395,7 @@ PROCESSINFOCLASS
PRODEXT
PROPERTYID
PROPERTYKEY
PROPERTYVAL
propertyval
propsheet
PROPSHEETHEADER
PROPSHEETPAGE
@@ -1431,8 +1427,11 @@ ptch
ptsz
PTYIn
PUCHAR
pvar
pwch
PWDDMCONSOLECONTEXT
Pwease
pweview
pws
pwstr
pwsz
@@ -1516,6 +1515,7 @@ rgn
rgp
rgpwsz
rgrc
rguid
rgw
RIGHTALIGN
RIGHTBUTTON
@@ -1523,6 +1523,7 @@ riid
RIS
roadmap
robomac
rodata
rosetta
RRF
rrr
@@ -1645,7 +1646,6 @@ sidebyside
SIF
SIGDN
Signtool
SINGLEFLAG
SINGLETHREADED
siup
sixel
@@ -1677,6 +1677,7 @@ srcsrv
SRCSRVTRG
srctool
srect
SRGS
srvinit
srvpipe
ssa
@@ -1714,10 +1715,12 @@ swapchain
swapchainpanel
SWMR
SWP
swrapped
SYMED
SYNCPAINT
syscalls
SYSCHAR
SYSCOLOR
SYSCOMMAND
SYSDEADCHAR
SYSKEYDOWN
@@ -1729,6 +1732,7 @@ sysparams
sysparamsext
SYSTEMHAND
SYSTEMMENU
SYSTEMTIME
tabview
TAdd
taef
@@ -1783,7 +1787,6 @@ TEXTMETRIC
TEXTMETRICW
textmode
texttests
TFCAT
TFunction
THUMBPOSITION
THUMBTRACK
@@ -1814,7 +1817,6 @@ Tpqrst
tracelogging
traceviewpp
trackbar
TRACKCOMPOSITION
trackpad
transitioning
Trd
@@ -1825,7 +1827,6 @@ Tribool
TRIMZEROHEADINGS
trx
tsa
tsattrs
tsgr
tsm
TStr
@@ -1838,8 +1839,6 @@ TTM
TTo
tvpp
tvtseq
Txtev
typechecked
TYUI
UAC
uap
@@ -1857,10 +1856,8 @@ UIACCESS
uiacore
uiautomationcore
uielem
UIELEMENTENABLEDONLY
UINTs
ul
ulcch
uld
uldash
uldb
@@ -1914,6 +1911,7 @@ UVWXY
UVWXYZ
uwa
uwp
uwu
uxtheme
Vanara
vararg
@@ -1954,11 +1952,9 @@ vstest
VSTS
VSTT
vswhere
vtapi
vtapp
VTE
VTID
vtio
vtmode
vtpipeterm
vtpt
@@ -1988,6 +1984,7 @@ wdm
webpage
websites
wekyb
wewoad
wex
wextest
wextestclass
@@ -2017,7 +2014,6 @@ WINDOWALPHA
windowdpiapi
WINDOWEDGE
windowext
windowime
WINDOWINFO
windowio
windowmetrics
@@ -2068,7 +2064,8 @@ WNDCLASSW
Wndproc
WNegative
WNull
wnwb
wordi
wordiswrapped
workarea
WOutside
WOWARM
@@ -2082,6 +2079,7 @@ WPrep
WPresent
wprp
wprpi
wrappe
wregex
writeback
WRITECONSOLE
@@ -2107,7 +2105,6 @@ WTs
WTSOFTFONT
wtw
wtypes
Wubi
WUX
WVerify
WWith
@@ -2134,9 +2131,7 @@ xes
XFG
XFile
XFORM
xin
xinchaof
xinxinchaof
XIn
XManifest
XMath
xorg

View File

@@ -13,7 +13,7 @@ jobs:
name: Add issue to project
runs-on: ubuntu-latest
steps:
- uses: actions/add-to-project@v0.5.0
- uses: actions/add-to-project@v1.0.1
with:
project-url: https://github.com/orgs/microsoft/projects/159
github-token: ${{ secrets.ADD_TO_PROJECT_PAT }}

View File

@@ -4,7 +4,7 @@
<clear />
<!-- Dependencies that we can turn on to force override for testing purposes before uploading. -->
<!--<add key="Static Package Dependencies" value="dep\packages" />-->
<add key="TerminalDependencies" value="https://pkgs.dev.azure.com/ms/terminal/_packaging/TerminalDependencies/nuget/v3/index.json" />
<add key="TerminalDependencies" value="https://pkgs.dev.azure.com/shine-oss/terminal/_packaging/TerminalDependencies/nuget/v3/index.json" />
</packageSources>
<disabledPackageSources>
<clear />

View File

@@ -171,6 +171,7 @@ EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Microsoft.Terminal.Control.Lib", "src\cascadia\TerminalControl\TerminalControlLib.vcxproj", "{CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED}"
ProjectSection(ProjectDependencies) = postProject
{1CF55140-EF6A-4736-A403-957E4F7430BB} = {1CF55140-EF6A-4736-A403-957E4F7430BB}
{2FD12FBB-1DDB-46D8-B818-1023C624CACA} = {2FD12FBB-1DDB-46D8-B818-1023C624CACA}
{48D21369-3D7B-4431-9967-24E81292CF63} = {48D21369-3D7B-4431-9967-24E81292CF63}
{8222900C-8B6C-452A-91AC-BE95DB04B95F} = {8222900C-8B6C-452A-91AC-BE95DB04B95F}
{AF0A096A-8B3A-4949-81EF-7DF8F0FEE91F} = {AF0A096A-8B3A-4949-81EF-7DF8F0FEE91F}
@@ -412,7 +413,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TerminalStress", "src\tools
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RenderingTests", "src\tools\RenderingTests\RenderingTests.vcxproj", "{37C995E0-2349-4154-8E77-4A52C0C7F46D}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "UIHelpers", "src\cascadia\UIHelpers\UIHelpers.vcxproj", "{6515F03F-E56D-4DB4-B23D-AC4FB80DB36F}"
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Microsoft.Terminal.UI", "src\cascadia\UIHelpers\UIHelpers.vcxproj", "{6515F03F-E56D-4DB4-B23D-AC4FB80DB36F}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "benchcat", "src\tools\benchcat\benchcat.vcxproj", "{2C836962-9543-4CE5-B834-D28E1F124B66}"
EndProject
@@ -477,6 +478,7 @@ Global
{9CBD7DFA-1754-4A9D-93D7-857A9D17CB1B}.Debug|ARM64.Build.0 = Debug|ARM64
{9CBD7DFA-1754-4A9D-93D7-857A9D17CB1B}.Debug|x64.ActiveCfg = Debug|x64
{9CBD7DFA-1754-4A9D-93D7-857A9D17CB1B}.Debug|x64.Build.0 = Debug|x64
{9CBD7DFA-1754-4A9D-93D7-857A9D17CB1B}.Debug|x64.Deploy.0 = Debug|x64
{9CBD7DFA-1754-4A9D-93D7-857A9D17CB1B}.Debug|x86.ActiveCfg = Debug|Win32
{9CBD7DFA-1754-4A9D-93D7-857A9D17CB1B}.Debug|x86.Build.0 = Debug|Win32
{9CBD7DFA-1754-4A9D-93D7-857A9D17CB1B}.Fuzzing|Any CPU.ActiveCfg = Fuzzing|Win32
@@ -2443,7 +2445,7 @@ Global
{345FD5A4-B32B-4F29-BD1C-B033BD2C35CC} = {E8F24881-5E37-4362-B191-A3BA0ED7F4EB}
{4C8E6BB0-4713-4ADB-BD04-81628ECEAF20} = {81C352DB-1818-45B7-A284-18E259F1CC87}
{D57841D1-8294-4F2B-BB8B-D2A35738DECD} = {81C352DB-1818-45B7-A284-18E259F1CC87}
{2FD12FBB-1DDB-46D8-B818-1023C624CACA} = {E8F24881-5E37-4362-B191-A3BA0ED7F4EB}
{2FD12FBB-1DDB-46D8-B818-1023C624CACA} = {89CDCC5C-9F53-4054-97A4-639D99F169CD}
{3AE13314-1939-4DFA-9C14-38CA0834050C} = {F1995847-4AE5-479A-BBAF-382E51A63532}
{DCF55140-EF6A-4736-A403-957E4F7430BB} = {F1995847-4AE5-479A-BBAF-382E51A63532}
{1CF55140-EF6A-4736-A403-957E4F7430BB} = {F1995847-4AE5-479A-BBAF-382E51A63532}

View File

@@ -1,6 +1,6 @@
{
"instanceUrl": "https://microsoft.visualstudio.com",
"projectName": "OS",
"areaPath": "OS\\Windows Client and Services\\ADEPT\\E4D-Engineered for Developers\\SHINE\\Terminal",
"areaPath": "OS\\Windows Client and Services\\WinPD\\DEEP-Developer Experience, Ecosystem and Partnerships\\SHINE\\Terminal",
"notificationAliases": ["condev@microsoft.com", "duhowett@microsoft.com"]
}

View File

@@ -9,7 +9,7 @@
<PropertyGroup>
<!-- Optional, defaults to main. Name of the branch which will be used for calculating branch point. -->
<PGOBranch>main</PGOBranch>
<PGOBranch>release-1.21</PGOBranch>
<!-- Mandatory. Name of the NuGet package which will contain PGO databases for consumption by build system. -->
<PGOPackageName>Microsoft.Internal.Windows.Terminal.PGODatabase</PGOPackageName>

View File

@@ -30,9 +30,20 @@ extends:
buildTerminal: true
pgoBuildMode: Optimize
codeSign: true
signingIdentity:
serviceName: $(SigningServiceName)
appId: $(SigningAppId)
tenantId: $(SigningTenantId)
akvName: $(SigningAKVName)
authCertName: $(SigningAuthCertName)
signCertName: $(SigningSignCertName)
useManagedIdentity: $(SigningUseManagedIdentity)
clientId: $(SigningOriginalClientId)
publishSymbolsToPublic: true
publishVpackToWindows: false
symbolExpiryTime: 15
symbolPublishingSubscription: $(SymbolPublishingServiceConnection)
symbolPublishingProject: $(SymbolPublishingProject)
${{ if eq(true, parameters.publishToAzure) }}:
extraPublishJobs:
- template: build/pipelines/templates-v2/job-deploy-to-azure-storage.yml@self

View File

@@ -27,7 +27,7 @@ parameters:
- name: pgoBuildMode
displayName: "PGO Build Mode"
type: string
default: Optimize
default: None # BODGY - OneBranch is on VS 17.10, which is known to be the worst
values:
- Optimize
- Instrument
@@ -78,6 +78,17 @@ extends:
buildConfigurations: ${{ parameters.buildConfigurations }}
buildPlatforms: ${{ parameters.buildPlatforms }}
codeSign: true
signingIdentity:
serviceName: $(SigningServiceName)
appId: $(SigningAppId)
tenantId: $(SigningTenantId)
akvName: $(SigningAKVName)
authCertName: $(SigningAuthCertName)
signCertName: $(SigningSignCertName)
useManagedIdentity: $(SigningUseManagedIdentity)
clientId: $(SigningOriginalClientId)
terminalInternalPackageVersion: ${{ parameters.terminalInternalPackageVersion }}
publishSymbolsToPublic: ${{ parameters.publishSymbolsToPublic }}
publishVpackToWindows: ${{ parameters.publishVpackToWindows }}
symbolPublishingSubscription: $(SymbolPublishingServiceConnection)
symbolPublishingProject: $(SymbolPublishingProject)

View File

@@ -27,6 +27,9 @@ parameters:
- name: publishArtifacts
type: boolean
default: true
- name: signingIdentity
type: object
default: {}
jobs:
- job: ${{ parameters.jobName }}
@@ -56,10 +59,7 @@ jobs:
submodules: true
persistCredentials: True
- task: PkgESSetupBuild@12
displayName: Package ES - Setup Build
inputs:
disableOutputRedirect: true
- template: steps-setup-versioning.yml
- template: steps-download-bin-dir-artifact.yml
parameters:
@@ -97,31 +97,32 @@ jobs:
flattenFolders: true
- ${{ if eq(parameters.codeSign, true) }}:
- task: EsrpCodeSigning@3
displayName: Submit *.nupkg to ESRP for code signing
inputs:
ConnectedServiceName: 9d6d2960-0793-4d59-943e-78dcb434840a
FolderPath: $(Build.ArtifactStagingDirectory)/nupkg
Pattern: '*.nupkg'
UseMinimatch: true
signConfigType: inlineSignParams
inlineOperation: >-
[
{
"KeyCode": "CP-401405",
"OperationCode": "NuGetSign",
"Parameters": {},
"ToolName": "sign",
"ToolVersion": "1.0"
},
{
"KeyCode": "CP-401405",
"OperationCode": "NuGetVerify",
"Parameters": {},
"ToolName": "sign",
"ToolVersion": "1.0"
}
]
- template: steps-esrp-signing.yml
parameters:
displayName: Submit *.nupkg to ESRP for code signing
signingIdentity: ${{ parameters.signingIdentity }}
inputs:
FolderPath: $(Build.ArtifactStagingDirectory)/nupkg
Pattern: '*.nupkg'
UseMinimatch: true
signConfigType: inlineSignParams
inlineOperation: >-
[
{
"KeyCode": "CP-401405",
"OperationCode": "NuGetSign",
"Parameters": {},
"ToolName": "sign",
"ToolVersion": "1.0"
},
{
"KeyCode": "CP-401405",
"OperationCode": "NuGetVerify",
"Parameters": {},
"ToolName": "sign",
"ToolVersion": "1.0"
}
]
- ${{ if eq(parameters.generateSbom, true) }}:
- task: AzureArtifacts.manifest-generator-task.manifest-generator-task.ManifestGeneratorTask@0

View File

@@ -65,6 +65,9 @@ parameters:
- name: removeAllNonSignedFiles
type: boolean
default: false
- name: signingIdentity
type: object
default: {}
jobs:
- job: ${{ parameters.jobName }}
@@ -142,6 +145,10 @@ jobs:
- template: .\steps-restore-nuget.yml
- pwsh: |-
.\build\scripts\Set-LatestVCToolsVersion.ps1
displayName: Work around DD-1541167 (VCToolsVersion)
- ${{ parameters.beforeBuildSteps }}
- task: VSBuild@1
@@ -152,7 +159,6 @@ jobs:
/p:WindowsTerminalOfficialBuild=true;WindowsTerminalBranding=${{ parameters.branding }};PGOBuildMode=${{ parameters.pgoBuildMode }}
${{ parameters.additionalBuildOptions }}
/bl:$(Build.SourcesDirectory)\msbuild.binlog
/graph
$(BuildTargetParameter)
platform: $(BuildPlatform)
configuration: $(BuildConfiguration)
@@ -236,13 +242,14 @@ jobs:
# Code-sign everything we just put together.
# We run the signing in Terminal.BinDir, because all of the signing batches are relative to the final architecture/configuration output folder.
- task: EsrpCodeSigning@3
displayName: Submit Signing Request
inputs:
ConnectedServiceName: 9d6d2960-0793-4d59-943e-78dcb434840a
FolderPath: '$(Terminal.BinDir)'
signType: batchSigning
batchSignPolicyFile: '$(Build.SourcesDirectory)/ESRPSigningConfig.json'
- template: steps-esrp-signing.yml
parameters:
displayName: Submit Signing Request
signingIdentity: ${{ parameters.signingIdentity }}
inputs:
FolderPath: '$(Terminal.BinDir)'
signType: batchSigning
batchSignPolicyFile: '$(Build.SourcesDirectory)/ESRPSigningConfig.json'
# We only need to re-pack the MSIX if we actually signed, so this can stay in the codeSign conditional
- ${{ if or(parameters.buildTerminal, parameters.buildEverything) }}:

View File

@@ -80,7 +80,7 @@ jobs:
Install-Module -Verbose -AllowClobber -Force Az.Accounts, Az.Storage, Az.Network, Az.Resources, Az.Compute
displayName: Install Azure Module Dependencies
- task: AzureFileCopy@5
- task: AzureFileCopy@6
displayName: Publish to Storage Account
inputs:
sourcePath: _out/*

View File

@@ -32,6 +32,9 @@ parameters:
- name: afterBuildSteps
type: stepList
default: []
- name: signingIdentity
type: object
default: {}
jobs:
- job: ${{ parameters.jobName }}
@@ -66,10 +69,9 @@ jobs:
fetchTags: false # Tags still result in depth > 1 fetch; we don't need them here
submodules: true
persistCredentials: True
- task: PkgESSetupBuild@12
displayName: Package ES - Setup Build
inputs:
disableOutputRedirect: true
- template: steps-setup-versioning.yml
- template: steps-download-bin-dir-artifact.yml
parameters:
buildPlatforms: ${{ parameters.buildPlatforms }}
@@ -94,40 +96,41 @@ jobs:
displayName: Create msixbundle
- ${{ if eq(parameters.codeSign, true) }}:
- task: EsrpCodeSigning@3
displayName: Submit *.msixbundle to ESRP for code signing
inputs:
ConnectedServiceName: 9d6d2960-0793-4d59-943e-78dcb434840a
FolderPath: $(System.ArtifactsDirectory)\bundle
Pattern: $(BundleStemName)*.msixbundle
UseMinimatch: true
signConfigType: inlineSignParams
inlineOperation: >-
[
{
"KeyCode": "Dynamic",
"CertTemplateName": "WINMSAPP1ST",
"CertSubjectName": "CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US",
"OperationCode": "SigntoolSign",
"Parameters": {
"OpusName": "Microsoft",
"OpusInfo": "http://www.microsoft.com",
"FileDigest": "/fd \"SHA256\"",
"TimeStamp": "/tr \"http://rfc3161.gtm.corp.microsoft.com/TSS/HttpTspServer\" /td sha256"
},
"ToolName": "sign",
"ToolVersion": "1.0"
},
{
"KeyCode": "Dynamic",
"CertTemplateName": "WINMSAPP1ST",
"CertSubjectName": "CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US",
"OperationCode": "SigntoolVerify",
"Parameters": {},
"ToolName": "sign",
"ToolVersion": "1.0"
}
]
- template: steps-esrp-signing.yml
parameters:
displayName: Submit *.msixbundle to ESRP for code signing
signingIdentity: ${{ parameters.signingIdentity }}
inputs:
FolderPath: $(System.ArtifactsDirectory)\bundle
Pattern: $(BundleStemName)*.msixbundle
UseMinimatch: true
signConfigType: inlineSignParams
inlineOperation: >-
[
{
"KeyCode": "Dynamic",
"CertTemplateName": "WINMSAPP1ST",
"CertSubjectName": "CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US",
"OperationCode": "SigntoolSign",
"Parameters": {
"OpusName": "Microsoft",
"OpusInfo": "http://www.microsoft.com",
"FileDigest": "/fd \"SHA256\"",
"TimeStamp": "/tr \"http://rfc3161.gtm.corp.microsoft.com/TSS/HttpTspServer\" /td sha256"
},
"ToolName": "sign",
"ToolVersion": "1.0"
},
{
"KeyCode": "Dynamic",
"CertTemplateName": "WINMSAPP1ST",
"CertSubjectName": "CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US",
"OperationCode": "SigntoolVerify",
"Parameters": {},
"ToolName": "sign",
"ToolVersion": "1.0"
}
]
- ${{ if eq(parameters.generateSbom, true) }}:
- task: AzureArtifacts.manifest-generator-task.manifest-generator-task.ManifestGeneratorTask@0

View File

@@ -27,6 +27,9 @@ parameters:
- name: publishArtifacts
type: boolean
default: true
- name: signingIdentity
type: object
default: {}
jobs:
- job: ${{ parameters.jobName }}
@@ -54,10 +57,7 @@ jobs:
submodules: true
persistCredentials: True
- task: PkgESSetupBuild@12
displayName: Package ES - Setup Build
inputs:
disableOutputRedirect: true
- template: steps-setup-versioning.yml
- template: steps-download-bin-dir-artifact.yml
parameters:
@@ -82,31 +82,32 @@ jobs:
versionEnvVar: XES_PACKAGEVERSIONNUMBER
- ${{ if eq(parameters.codeSign, true) }}:
- task: EsrpCodeSigning@3
displayName: Submit *.nupkg to ESRP for code signing
inputs:
ConnectedServiceName: 9d6d2960-0793-4d59-943e-78dcb434840a
FolderPath: $(Build.ArtifactStagingDirectory)/nupkg
Pattern: '*.nupkg'
UseMinimatch: true
signConfigType: inlineSignParams
inlineOperation: >-
[
{
"KeyCode": "CP-401405",
"OperationCode": "NuGetSign",
"Parameters": {},
"ToolName": "sign",
"ToolVersion": "1.0"
},
{
"KeyCode": "CP-401405",
"OperationCode": "NuGetVerify",
"Parameters": {},
"ToolName": "sign",
"ToolVersion": "1.0"
}
]
- template: steps-esrp-signing.yml
parameters:
displayName: Submit *.nupkg to ESRP for code signing
signingIdentity: ${{ parameters.signingIdentity }}
inputs:
FolderPath: $(Build.ArtifactStagingDirectory)/nupkg
Pattern: '*.nupkg'
UseMinimatch: true
signConfigType: inlineSignParams
inlineOperation: >-
[
{
"KeyCode": "CP-401405",
"OperationCode": "NuGetSign",
"Parameters": {},
"ToolName": "sign",
"ToolVersion": "1.0"
},
{
"KeyCode": "CP-401405",
"OperationCode": "NuGetVerify",
"Parameters": {},
"ToolName": "sign",
"ToolVersion": "1.0"
}
]
- ${{ if eq(parameters.generateSbom, true) }}:
- task: AzureArtifacts.manifest-generator-task.manifest-generator-task.ManifestGeneratorTask@0

View File

@@ -0,0 +1,114 @@
parameters:
- name: includePublicSymbolServer
type: boolean
default: false
- name: pool
type: object
default: []
- name: dependsOn
type: object
default: null
- name: artifactStem
type: string
default: ''
- name: jobName
type: string
default: PublishSymbols
- name: symbolExpiryTime
type: string
default: 36530 # This is the default from PublishSymbols@2
- name: variables
type: object
default: {}
- name: subscription
type: string
- name: symbolProject
type: string
jobs:
- job: ${{ parameters.jobName }}
${{ if ne(length(parameters.pool), 0) }}:
pool: ${{ parameters.pool }}
${{ if eq(parameters.includePublicSymbolServer, true) }}:
displayName: Publish Symbols to Internal and MSDL
${{ else }}:
displayName: Publish Symbols Internally
dependsOn: ${{ parameters.dependsOn }}
variables:
${{ insert }}: ${{ parameters.variables }}
steps:
- checkout: self
clean: true
fetchDepth: 1
fetchTags: false # Tags still result in depth > 1 fetch; we don't need them here
submodules: true
persistCredentials: True
- template: steps-setup-versioning.yml
- task: DownloadPipelineArtifact@2
displayName: Download all PDBs from all prior build phases
inputs:
itemPattern: '**/*.pdb'
targetPath: '$(Build.SourcesDirectory)/bin'
- powershell: |-
Get-PackageProvider -Name NuGet -ForceBootstrap
Install-Module -Verbose -AllowClobber -Force Az.Accounts, Az.Storage, Az.Network, Az.Resources, Az.Compute
displayName: Install Azure Module Dependencies
# Transit the Azure token from the Service Connection into a secret variable for the rest of the pipeline to use.
- task: AzurePowerShell@5
displayName: Generate an Azure Token
inputs:
azureSubscription: ${{ parameters.subscription }}
azurePowerShellVersion: LatestVersion
pwsh: true
ScriptType: InlineScript
Inline: |-
$AzToken = (Get-AzAccessToken -ResourceUrl api://30471ccf-0966-45b9-a979-065dbedb24c1).Token
Write-Host "##vso[task.setvariable variable=SymbolAccessToken;issecret=true]$AzToken"
- task: PublishSymbols@2
displayName: Publish Symbols (to current Azure DevOps tenant)
continueOnError: True
inputs:
SymbolsFolder: '$(Build.SourcesDirectory)/bin'
SearchPattern: '**/*.pdb'
IndexSources: false
DetailedLog: true
SymbolsMaximumWaitTime: 30
SymbolServerType: 'TeamServices'
SymbolsProduct: 'Windows Terminal Converged Symbols'
SymbolsVersion: '$(XES_APPXMANIFESTVERSION)'
SymbolsArtifactName: 'WindowsTerminal_$(XES_APPXMANIFESTVERSION)'
SymbolExpirationInDays: ${{ parameters.symbolExpiryTime }}
env:
LIB: $(Build.SourcesDirectory)
- pwsh: |-
# Prepare the defaults for IRM
$PSDefaultParameterValues['Invoke-RestMethod:Headers'] = @{ Authorization = "Bearer $(SymbolAccessToken)" }
$PSDefaultParameterValues['Invoke-RestMethod:ContentType'] = "application/json"
$PSDefaultParameterValues['Invoke-RestMethod:Method'] = "POST"
$BaseUri = "https://symbolrequestprod.trafficmanager.net/projects/${{ parameters.symbolProject }}/requests"
# Prepare the request
$expiration = (Get-Date).Add([TimeSpan]::FromDays(${{ parameters.symbolExpiryTime }}))
$createRequestBody = @{
requestName = "WindowsTerminal_$(XES_APPXMANIFESTVERSION)";
expirationTime = $expiration.ToString();
}
Write-Host "##[debug]Starting request $($createRequestBody.requestName) with expiration date of $($createRequestBody.expirationTime)"
Invoke-RestMethod -Uri "$BaseUri" -Body ($createRequestBody | ConvertTo-Json -Compress) -Verbose
# Request symbol publication
$publishRequestBody = @{
publishToInternalServer = $true;
publishToPublicServer = $${{ parameters.includePublicSymbolServer }};
}
Write-Host "##[debug]Submitting request $($createRequestBody.requestName) ($($publishRequestBody | ConvertTo-Json -Compress))"
Invoke-RestMethod -Uri "$BaseUri/$($createRequestBody.requestName)" -Body ($publishRequestBody | ConvertTo-Json -Compress) -Verbose
displayName: Publish Symbols using internal REST API

View File

@@ -43,10 +43,7 @@ jobs:
submodules: true
persistCredentials: True
- task: PkgESSetupBuild@12
displayName: Package ES - Setup Build
inputs:
disableOutputRedirect: true
- template: steps-setup-versioning.yml
- task: DownloadPipelineArtifact@2
displayName: Download all PDBs from all prior build phases

View File

@@ -38,10 +38,7 @@ jobs:
submodules: true
persistCredentials: True
- task: PkgESSetupBuild@12
displayName: Package ES - Setup Build
inputs:
disableOutputRedirect: true
- template: steps-setup-versioning.yml
- task: DownloadPipelineArtifact@2
displayName: Download MSIX Bundle Artifact

View File

@@ -33,7 +33,7 @@ parameters:
- arm64
- name: codeSign
type: boolean
default: true
default: false
- name: generateSbom
type: boolean
default: true
@@ -92,10 +92,7 @@ stages:
generateSbom: ${{ parameters.generateSbom }}
codeSign: ${{ parameters.codeSign }}
beforeBuildSteps: # Right before we build, lay down the universal package and localizations
- task: PkgESSetupBuild@12
displayName: Package ES - Setup Build
inputs:
disableOutputRedirect: true
- template: ./build/pipelines/templates-v2/steps-setup-versioning.yml@self
- task: UniversalPackages@0
displayName: Download terminal-internal Universal Package
@@ -119,10 +116,7 @@ stages:
generateSbom: ${{ parameters.generateSbom }}
codeSign: ${{ parameters.codeSign }}
beforeBuildSteps:
- task: PkgESSetupBuild@12
displayName: Package ES - Setup Build
inputs:
disableOutputRedirect: true
- template: ./build/pipelines/templates-v2/steps-setup-versioning.yml@self
# WPF doesn't need the localizations or the universal package, but if it does... put them here.
- stage: Package

View File

@@ -52,10 +52,17 @@ parameters:
- name: publishVpackToWindows
type: boolean
default: false
- name: symbolPublishingSubscription
type: string
- name: symbolPublishingProject
type: string
- name: extraPublishJobs
type: object
default: []
- name: signingIdentity
type: object
default: {}
resources:
repositories:
@@ -78,6 +85,7 @@ extends:
cloudvault: # https://aka.ms/obpipelines/cloudvault
enabled: false
globalSdl: # https://aka.ms/obpipelines/sdl
enableCheckCFlags: false # CheckCFlags is broken and exploding our builds; to remove, :g/BAD-FLAGS/d
asyncSdl:
enabled: true
tsaOptionsFile: 'build/config/tsa.json'
@@ -103,6 +111,8 @@ extends:
parameters:
pool: { type: windows }
variables:
ob_sdl_checkcflags_enabled: false # BAD-FLAGS
ob_sdl_xfgcheck_enabled: false # BAD-FLAGS
ob_git_checkout: false # This job checks itself out
ob_git_skip_checkout_none: true
ob_outputDirectory: $(JobOutputDirectory)
@@ -118,11 +128,9 @@ extends:
generateSbom: false # this is handled by onebranch
removeAllNonSignedFiles: true # appease the overlords
codeSign: ${{ parameters.codeSign }}
signingIdentity: ${{ parameters.signingIdentity }}
beforeBuildSteps: # Right before we build, lay down the universal package and localizations
- task: PkgESSetupBuild@12
displayName: Package ES - Setup Build
inputs:
disableOutputRedirect: true
- template: ./build/pipelines/templates-v2/steps-setup-versioning.yml@self
- task: UniversalPackages@0
displayName: Download terminal-internal Universal Package
@@ -137,6 +145,8 @@ extends:
parameters:
pool: { type: windows }
variables:
ob_sdl_checkcflags_enabled: false # BAD-FLAGS
ob_sdl_xfgcheck_enabled: false # BAD-FLAGS
ob_git_checkout: false # This job checks itself out
ob_git_skip_checkout_none: true
ob_outputDirectory: $(JobOutputDirectory)
@@ -152,11 +162,9 @@ extends:
generateSbom: false # this is handled by onebranch
removeAllNonSignedFiles: true # appease the overlords
codeSign: ${{ parameters.codeSign }}
signingIdentity: ${{ parameters.signingIdentity }}
beforeBuildSteps:
- task: PkgESSetupBuild@12
displayName: Package ES - Setup Build
inputs:
disableOutputRedirect: true
- template: ./build/pipelines/templates-v2/steps-setup-versioning.yml@self
# WPF doesn't need the localizations or the universal package, but if it does... put them here.
- stage: Package
@@ -168,6 +176,8 @@ extends:
parameters:
pool: { type: windows }
variables:
ob_sdl_checkcflags_enabled: false # BAD-FLAGS
ob_sdl_xfgcheck_enabled: false # BAD-FLAGS
ob_git_checkout: false # This job checks itself out
ob_git_skip_checkout_none: true
ob_outputDirectory: $(JobOutputDirectory)
@@ -203,6 +213,7 @@ extends:
buildPlatforms: ${{ parameters.buildPlatforms }}
generateSbom: false # Handled by onebranch
codeSign: ${{ parameters.codeSign }}
signingIdentity: ${{ parameters.signingIdentity }}
afterBuildSteps:
# This directory has to exist, even if we aren't using createvpack, because the Guardian rules demand it.
- pwsh: |-
@@ -219,6 +230,8 @@ extends:
parameters:
pool: { type: windows }
variables:
ob_sdl_checkcflags_enabled: false # BAD-FLAGS
ob_sdl_xfgcheck_enabled: false # BAD-FLAGS
ob_git_checkout: false # This job checks itself out
ob_git_skip_checkout_none: true
ob_outputDirectory: $(JobOutputDirectory)
@@ -228,12 +241,15 @@ extends:
buildPlatforms: ${{ parameters.buildPlatforms }}
generateSbom: false # this is handled by onebranch
codeSign: ${{ parameters.codeSign }}
signingIdentity: ${{ parameters.signingIdentity }}
- ${{ if eq(parameters.buildWPF, true) }}:
- template: ./build/pipelines/templates-v2/job-build-package-wpf.yml@self
parameters:
pool: { type: windows }
variables:
ob_sdl_checkcflags_enabled: false # BAD-FLAGS
ob_sdl_xfgcheck_enabled: false # BAD-FLAGS
ob_git_checkout: false # This job checks itself out
ob_git_skip_checkout_none: true
ob_outputDirectory: $(JobOutputDirectory)
@@ -243,18 +259,22 @@ extends:
buildPlatforms: ${{ parameters.buildPlatforms }}
generateSbom: false # this is handled by onebranch
codeSign: ${{ parameters.codeSign }}
signingIdentity: ${{ parameters.signingIdentity }}
- stage: Publish
displayName: Publish
dependsOn: [Build]
jobs:
- template: ./build/pipelines/templates-v2/job-publish-symbols.yml@self
- template: ./build/pipelines/templates-v2/job-publish-symbols-using-symbolrequestprod-api.yml@self
parameters:
pool: { type: windows }
includePublicSymbolServer: ${{ parameters.publishSymbolsToPublic }}
symbolPatGoesInTaskInputs: true # onebranch tries to muck with the PAT variable, so we need to change how it get the PAT
symbolExpiryTime: ${{ parameters.symbolExpiryTime }}
subscription: ${{ parameters.symbolPublishingSubscription }}
symbolProject: ${{ parameters.symbolPublishingProject }}
variables:
ob_sdl_checkcflags_enabled: false # BAD-FLAGS
ob_sdl_xfgcheck_enabled: false # BAD-FLAGS
ob_git_checkout: false # This job checks itself out
ob_git_skip_checkout_none: true
ob_outputDirectory: $(Build.ArtifactStagingDirectory)

View File

@@ -0,0 +1,24 @@
parameters:
- name: displayName
type: string
default: ESRP Code Signing
- name: inputs
type: object
default: {}
- name: signingIdentity
type: object
default: {}
steps:
- task: EsrpCodeSigning@5
displayName: ${{ parameters.displayName }}
inputs:
ConnectedServiceName: ${{ parameters.signingIdentity.serviceName }}
AppRegistrationClientId: ${{ parameters.signingIdentity.appId }}
AppRegistrationTenantId: ${{ parameters.signingIdentity.tenantId }}
AuthAKVName: ${{ parameters.signingIdentity.akvName }}
AuthCertName: ${{ parameters.signingIdentity.authCertName }}
AuthSignCertName: ${{ parameters.signingIdentity.signCertName }}
UseMSIAuthentication: ${{ coalesce(parameters.signingIdentity.useManagedIdentity, 'false') }}
EsrpClientId: ${{ parameters.signingIdentity.clientId }}
${{ insert }}: ${{ parameters.inputs }}

View File

@@ -0,0 +1,6 @@
steps:
- pwsh: |-
nuget install Microsoft.Windows.Terminal.Versioning -OutputDirectory _versioning
$VersionRoot = (Get-Item _versioning\Microsoft.Windows.*).FullName
& "$VersionRoot\build\Setup.ps1" -ProjectDirectory "$(Build.SourcesDirectory)" -Verbose
displayName: Set up versioning via M.W.T.V

View File

@@ -1,2 +1,7 @@
parameters:
- name: containerVersion
type: string
default: latest
variables:
WindowsContainerImage: 'onebranch.azurecr.io/windows/ltsc2022/vse2022:1.0.02566.28'
WindowsContainerImage: 'onebranch.azurecr.io/windows/ltsc2022/vse2022:${{ parameters.containerVersion }}'

View File

@@ -0,0 +1,8 @@
$VSInstances = ([xml](& 'C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe' -latest -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -include packages -format xml))
$VSPackages = $VSInstances.instances.instance.packages.package
$LatestVCPackage = ($VSInstances.instances.instance.packages.package | ? { $_.id -eq "Microsoft.VisualCpp.Tools.Core" })
$LatestVCToolsVersion = $LatestVCPackage.version;
Write-Output "Latest VCToolsVersion: $LatestVCToolsVersion"
Write-Output "Updating VCToolsVersion environment variable for job"
Write-Output "##vso[task.setvariable variable=VCToolsVersion]$LatestVCToolsVersion"

View File

@@ -65,9 +65,6 @@
* `clipboard.cpp`
* Handles the command prompt line as you see in CMD.exe (known as the processed input line… most other shells handle this themselves with raw input and dont use ours. This is a legacy of bad architectural design, putting stuff in conhost not in CMD)
* `cmdline.cpp`
* Handles shunting IME data back and forth to the TSF library and to and from the various buffers
* `Conimeinfo.cpp`
* `Convarea.cpp`
* Contains the global state for the entire console application
* `consoleInformation.cpp`
* Stuff related to the low-level server communication over our protocol with the driver

View File

@@ -35,7 +35,8 @@
"enum": [
"Windows.Terminal.Wsl",
"Windows.Terminal.Azure",
"Windows.Terminal.PowershellCore"
"Windows.Terminal.PowershellCore",
"Windows.Terminal.VisualStudio"
],
"type": "string"
},
@@ -349,7 +350,7 @@
"description": "Sets the DWrite font features for the given font. For example, { \"ss01\": 1, \"liga\":0 } will enable ss01 and disable ligatures.",
"type": "object",
"patternProperties": {
"^(([A-Za-z0-9]){4})$": {
"^[\\x20-\\x7E]{4}$": {
"type": "integer"
}
},
@@ -359,7 +360,7 @@
"description": "Sets the DWrite font axes for the given font. For example, { \"wght\": 200 } will set the font weight to 200.",
"type": "object",
"patternProperties": {
"^([A-Za-z]{4})$": {
"^[\\x20-\\x7E]{4}$": {
"type": "number"
}
},
@@ -618,6 +619,11 @@
"type": "boolean",
"default": false,
"description": "This will override the profile's `elevate` setting."
},
"reloadEnvironmentVariables": {
"type": "boolean",
"default": true,
"description": "When set to true, a new environment block will be generated when creating a new session. Otherwise, the session will inherit the variables the Terminal was started with."
}
},
"type": "object"
@@ -1501,8 +1507,10 @@
"const": "multipleActions"
},
"actions": {
"$ref": "#/$defs/ShortcutAction",
"type": "array",
"items": {
"$ref": "#/$defs/ShortcutAction"
},
"minItems": 1,
"description": "A list of other actions."
}
@@ -1891,6 +1899,14 @@
],
"type": "string"
},
"IconStyle": {
"enum": [
"default",
"hidden",
"monochrome"
],
"type": "string"
},
"ThemeColor": {
"description": "A special kind of color for use in themes. Can be an #rrggbb color, #rrggbbaa color, or a special value. 'accent' is evaluated as the user's selected Accent color in the OS, and 'terminalBackground' will be evaluated as the background color of the active terminal pane.",
"oneOf": [
@@ -1928,6 +1944,10 @@
"showCloseButton": {
"description": "Controls the visibility of the close button on the tab",
"$ref": "#/$defs/ShowCloseButton"
},
"iconStyle": {
"description": "Controls the appearance of a tab's icon",
"$ref": "#/$defs/IconStyle"
}
}
},
@@ -2065,6 +2085,9 @@
{
"$ref": "#/$defs/SwitchToTabAction"
},
{
"$ref": "#/$defs/ScrollToMarkAction"
},
{
"$ref": "#/$defs/MoveFocusAction"
},
@@ -2200,6 +2223,10 @@
}
}
},
"id": {
"description": "The ID of this command. If one isn't provided, we will generate one internally.",
"type": "string"
},
"iterateOn": {
"type": "string",
"description": "Used to create iterable commands based on other objects in your settings. Possible values:\n- \"profiles\" \n- \"schemes\"",
@@ -2211,7 +2238,15 @@
"commands": {
"description": "List of commands to execute",
"items": {
"$ref": "#/$defs/Keybinding/properties/command"
"type": "object",
"properties": {
"command": {
"$ref": "#/$defs/Keybinding/properties/command"
},
"name": {
"$ref": "#/$defs/Keybinding/properties/name"
}
}
},
"minItems": 1,
"type": "array"
@@ -2772,20 +2807,35 @@
"type": "string"
}
},
"experimental.autoMarkPrompts": {
"autoMarkPrompts": {
"default": false,
"description": "When set to true, prompts will automatically be marked.",
"type": "boolean"
},
"experimental.autoMarkPrompts": {
"deprecated": true,
"description": "This has been replaced by autoMarkPrompts in 1.21",
"type": "boolean"
},
"experimental.retroTerminalEffect": {
"description": "When set to true, enable retro terminal effects. This is an experimental feature, and its continued existence is not guaranteed.",
"type": "boolean"
},
"experimental.showMarksOnScrollbar": {
"deprecated": true,
"description": "This has been replaced by showMarksOnScrollbar in 1.21",
"type": "boolean"
},
"showMarksOnScrollbar": {
"default": false,
"description": "When set to true, marks added to the buffer via the addMark action will appear on the scrollbar.",
"type": "boolean"
},
"experimental.rightClickContextMenu": {
"default": false,
"description": "When set to true, right-clicking on the terminal will show a context menu. When set to false, right-click will copy",
"type": "boolean"
},
"experimental.repositionCursorWithMouse": {
"default": false,
"description": "When set to true, you can move the text cursor by clicking with the mouse on the current commandline. This is an experimental feature - there are lots of edge cases where this will not work as expected.",

View File

@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- (c) 2024 Microsoft Corporation -->
<policyDefinitions xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" revision="1.0" schemaVersion="1.0" xmlns="http://schemas.microsoft.com/GroupPolicy/2006/07/PolicyDefinitions">
<policyNamespaces>
<target prefix="terminal" namespace="Microsoft.Policies.WindowsTerminal" />
<using prefix="windows" namespace="Microsoft.Policies.Windows" />
</policyNamespaces>
<resources minRequiredRevision="1.0" />
<supportedOn>
<definitions>
<definition name="SUPPORTED_WindowsTerminal_1_21" displayName="$(string.SUPPORTED_WindowsTerminal_1_21)" />
</definitions>
</supportedOn>
<categories>
<category name="WindowsTerminal" displayName="$(string.WindowsTerminal)">
<parentCategory ref="windows:WindowsComponents" />
</category>
</categories>
<policies>
<policy name="DisabledProfileSources" class="Both" displayName="$(string.DisabledProfileSources)" explainText="$(string.DisabledProfileSourcesText)" presentation="$(presentation.DisabledProfileSources)" key="Software\Policies\Microsoft\Windows Terminal">
<parentCategory ref="WindowsTerminal" />
<supportedOn ref="SUPPORTED_WindowsTerminal_1_21" />
<elements>
<multiText id="DisabledProfileSources" valueName="DisabledProfileSources" required="true" />
</elements>
</policy>
</policies>
</policyDefinitions>

View File

@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- (c) 2024 Microsoft Corporation -->
<policyDefinitionResources xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" revision="1.0" schemaVersion="1.0" xmlns="http://schemas.microsoft.com/GroupPolicy/2006/07/PolicyDefinitions">
<displayName>Windows Terminal</displayName>
<description>Windows Terminal</description>
<resources>
<stringTable>
<string id="WindowsTerminal">Windows Terminal</string>
<string id="SUPPORTED_WindowsTerminal_1_21">At least Windows Terminal 1.21</string>
<string id="DisabledProfileSources">Disabled Profile Sources</string>
<string id="DisabledProfileSourcesText">Profiles will not be generated from any sources listed here. Source names can be arbitrary strings. Potential candidates can be found as the "source" property on profile definitions in Windows Terminal's settings.json file.
Common sources are:
- Windows.Terminal.Azure
- Windows.Terminal.PowershellCore
- Windows.Terminal.Wsl
For instance, setting this policy to Windows.Terminal.Wsl will disable the builtin WSL integration of Windows Terminal.
Note: Existing profiles will disappear from Windows Terminal after adding their source to this policy.</string>
</stringTable>
<presentationTable>
<presentation id="DisabledProfileSources">
<multiTextBox refId="DisabledProfileSources">List of disabled sources (one per line)</multiTextBox>
</presentation>
</presentationTable>
</resources>
</policyDefinitionResources>

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -8,5 +8,5 @@ Please consult the [license](https://raw.githubusercontent.com/microsoft/cascadi
### Fonts Included
* Cascadia Code, Cascadia Mono (2111.01)
* from microsoft/cascadia-code@de36d62e777d34d3bed92a7e23988e5d61e0ba02
* Cascadia Code, Cascadia Mono (2407.24)
* from microsoft/cascadia-code@56bcca3f2c1e4cb19458954f0e2bb4635960df91

View File

@@ -11,7 +11,7 @@ Licensed under the MIT license.
#include <conattrs.hpp>
#include "MySettings.g.h"
using IFontFeatureMap = winrt::Windows::Foundation::Collections::IMap<winrt::hstring, uint32_t>;
using IFontFeatureMap = winrt::Windows::Foundation::Collections::IMap<winrt::hstring, float>;
using IFontAxesMap = winrt::Windows::Foundation::Collections::IMap<winrt::hstring, float>;
namespace winrt::SampleApp::implementation

View File

@@ -23,21 +23,24 @@ enum class LineRendition : uint8_t
constexpr til::inclusive_rect ScreenToBufferLine(const til::inclusive_rect& line, const LineRendition lineRendition)
{
// Use shift right to quickly divide the Left and Right by 2 for double width lines.
const auto scale = lineRendition == LineRendition::SingleWidth ? 0 : 1;
return { line.left >> scale, line.top, line.right >> scale, line.bottom };
}
constexpr til::point ScreenToBufferLine(const til::point& line, const LineRendition lineRendition)
constexpr til::point ScreenToBufferLineInclusive(const til::point& line, const LineRendition lineRendition)
{
// Use shift right to quickly divide the Left and Right by 2 for double width lines.
const auto scale = lineRendition == LineRendition::SingleWidth ? 0 : 1;
return { line.x >> scale, line.y };
}
constexpr til::rect BufferToScreenLine(const til::rect& line, const LineRendition lineRendition)
{
const auto scale = lineRendition == LineRendition::SingleWidth ? 0 : 1;
return { line.left << scale, line.top, line.right << scale, line.bottom };
}
constexpr til::inclusive_rect BufferToScreenLine(const til::inclusive_rect& line, const LineRendition lineRendition)
{
// Use shift left to quickly multiply the Left and Right by 2 for double width lines.
const auto scale = lineRendition == LineRendition::SingleWidth ? 0 : 1;
return { line.left << scale, line.top, (line.right << scale) + scale, line.bottom };
}

91
src/buffer/out/Marks.hpp Normal file
View File

@@ -0,0 +1,91 @@
/*++
Copyright (c) Microsoft Corporation
Licensed under the MIT license.
Module Name:
- marks.hpp
Abstract:
- Definitions for types that are used for "scroll marks" and shell integration
in the buffer.
- Scroll marks are identified by the existence of "ScrollbarData" on a ROW in the buffer.
- Shell integration will then also markup the buffer with special
TextAttributes, to identify regions of text as the Prompt, the Command, the
Output, etc.
- MarkExtents are used to abstract away those regions of text, so a caller
doesn't need to iterate over the buffer themselves.
--*/
#pragma once
enum class MarkCategory : uint8_t
{
Default = 0,
Error = 1,
Warning = 2,
Success = 3,
Prompt = 4
};
// This is the data that's stored on each ROW, to suggest that there's something
// interesting on this row to show in the scrollbar. Also used in conjunction
// with shell integration - when a prompt is added through shell integration,
// we'll also add a scrollbar mark as a quick "bookmark" to the start of that
// command.
struct ScrollbarData
{
MarkCategory category{ MarkCategory::Default };
// Scrollbar marks may have been given a color, or not.
std::optional<til::color> color;
// Prompts without an exit code haven't had a matching FTCS CommandEnd
// called yet. Any value other than 0 is an error.
std::optional<uint32_t> exitCode;
// Future consideration: stick the literal command as a string on here, if
// we were given it with the 633;E sequence.
};
// Helper struct for describing the bounds of a command and it's output,
// * The Prompt is between the start & end
// * The Command is between the end & commandEnd
// * The Output is between the commandEnd & outputEnd
//
// These are not actually stored in the buffer. The buffer can produce them for
// callers, to make reasoning about regions of the buffer easier.
struct MarkExtents
{
// Data from the row
ScrollbarData data;
til::point start;
til::point end; // exclusive
std::optional<til::point> commandEnd;
std::optional<til::point> outputEnd;
// MarkCategory category{ MarkCategory::Info };
// Other things we may want to think about in the future are listed in
// GH#11000
bool HasCommand() const noexcept
{
return commandEnd.has_value() && *commandEnd != end;
}
bool HasOutput() const noexcept
{
return outputEnd.has_value() && *outputEnd != *commandEnd;
}
std::pair<til::point, til::point> GetExtent() const
{
til::point realEnd{ til::coalesce_value(outputEnd, commandEnd, end) };
return std::make_pair(start, realEnd);
}
};
// Another helper, for when callers would like to know just about the data of
// the scrollbar, but don't actually need all the extents of prompts.
struct ScrollMark
{
til::CoordType row{ 0 };
ScrollbarData data;
};

View File

@@ -230,6 +230,7 @@ void ROW::Reset(const TextAttribute& attr) noexcept
_lineRendition = LineRendition::SingleWidth;
_wrapForced = false;
_doubleBytePadded = false;
_promptData = std::nullopt;
_init();
}
@@ -348,12 +349,6 @@ void ROW::_init() noexcept
#pragma warning(push)
}
void ROW::TransferAttributes(const til::small_rle<TextAttribute, uint16_t, 1>& attr, til::CoordType newWidth)
{
_attr = attr;
_attr.resize_trailing_extent(gsl::narrow<uint16_t>(newWidth));
}
void ROW::CopyFrom(const ROW& source)
{
_lineRendition = source._lineRendition;
@@ -365,7 +360,8 @@ void ROW::CopyFrom(const ROW& source)
};
CopyTextFrom(state);
TransferAttributes(source.Attributes(), _columnCount);
_attr = source.Attributes();
_attr.resize_trailing_extent(_columnCount);
}
// Returns the previous possible cursor position, preceding the given column.
@@ -918,7 +914,7 @@ const til::small_rle<TextAttribute, uint16_t, 1>& ROW::Attributes() const noexce
TextAttribute ROW::GetAttrByColumn(const til::CoordType column) const
{
return _attr.at(_clampedUint16(column));
return _attr.at(_clampedColumn(column));
}
std::vector<uint16_t> ROW::GetHyperlinks() const
@@ -1101,12 +1097,6 @@ DelimiterClass ROW::DelimiterClassAt(til::CoordType column, const std::wstring_v
}
}
template<typename T>
constexpr uint16_t ROW::_clampedUint16(T v) noexcept
{
return static_cast<uint16_t>(clamp(v, 0, 65535));
}
template<typename T>
constexpr uint16_t ROW::_clampedColumn(T v) const noexcept
{
@@ -1181,3 +1171,45 @@ CharToColumnMapper ROW::_createCharToColumnMapper(ptrdiff_t offset) const noexce
const auto guessedColumn = gsl::narrow_cast<til::CoordType>(clamp(offset, 0, _columnCount));
return CharToColumnMapper{ _chars.data(), _charOffsets.data(), lastChar, guessedColumn };
}
const std::optional<ScrollbarData>& ROW::GetScrollbarData() const noexcept
{
return _promptData;
}
void ROW::SetScrollbarData(std::optional<ScrollbarData> data) noexcept
{
_promptData = data;
}
void ROW::StartPrompt() noexcept
{
if (!_promptData.has_value())
{
// You'd be tempted to write:
//
// _promptData = ScrollbarData{
// .category = MarkCategory::Prompt,
// .color = std::nullopt,
// .exitCode = std::nullopt,
// };
//
// But that's not very optimal! Read this thread for a breakdown of how
// weird std::optional can be some times:
//
// https://github.com/microsoft/terminal/pull/16937#discussion_r1553660833
_promptData.emplace(MarkCategory::Prompt);
}
}
void ROW::EndOutput(std::optional<unsigned int> error) noexcept
{
if (_promptData.has_value())
{
_promptData->exitCode = error;
if (error.has_value())
{
_promptData->category = *error == 0 ? MarkCategory::Success : MarkCategory::Error;
}
}
}

View File

@@ -8,6 +8,7 @@
#include "LineRendition.hpp"
#include "OutputCell.hpp"
#include "OutputCellIterator.hpp"
#include "Marks.hpp"
class ROW;
class TextBuffer;
@@ -131,7 +132,6 @@ public:
til::CoordType GetReadableColumnCount() const noexcept;
void Reset(const TextAttribute& attr) noexcept;
void TransferAttributes(const til::small_rle<TextAttribute, uint16_t, 1>& attr, til::CoordType newWidth);
void CopyFrom(const ROW& source);
til::CoordType NavigateToPrevious(til::CoordType column) const noexcept;
@@ -167,6 +167,11 @@ public:
auto AttrBegin() const noexcept { return _attr.begin(); }
auto AttrEnd() const noexcept { return _attr.end(); }
const std::optional<ScrollbarData>& GetScrollbarData() const noexcept;
void SetScrollbarData(std::optional<ScrollbarData> data) noexcept;
void StartPrompt() noexcept;
void EndOutput(std::optional<unsigned int> error) noexcept;
#ifdef UNIT_TESTING
friend constexpr bool operator==(const ROW& a, const ROW& b) noexcept;
friend class RowTests;
@@ -225,8 +230,6 @@ private:
static constexpr uint16_t CharOffsetsTrailer = 0x8000;
static constexpr uint16_t CharOffsetsMask = 0x7fff;
template<typename T>
static constexpr uint16_t _clampedUint16(T v) noexcept;
template<typename T>
constexpr uint16_t _clampedColumn(T v) const noexcept;
template<typename T>
@@ -299,6 +302,8 @@ private:
bool _wrapForced = false;
// Occurs when the user runs out of text to support a double byte character and we're forced to the next line
bool _doubleBytePadded = false;
std::optional<ScrollbarData> _promptData = std::nullopt;
};
#ifdef UNIT_TESTING

View File

@@ -7,7 +7,7 @@
// Keeping TextColor compact helps us keeping TextAttribute compact,
// which in turn ensures that our buffer memory usage is low.
static_assert(sizeof(TextAttribute) == 16);
static_assert(sizeof(TextAttribute) == 18);
static_assert(alignof(TextAttribute) == 2);
// Ensure that we can memcpy() and memmove() the struct for performance.
static_assert(std::is_trivially_copyable_v<TextAttribute>);
@@ -434,4 +434,5 @@ void TextAttribute::SetStandardErase() noexcept
{
_attrs = CharacterAttributes::Normal;
_hyperlinkId = 0;
_markKind = MarkKind::None;
}

View File

@@ -38,6 +38,15 @@ enum class UnderlineStyle
Max = DashedUnderlined
};
// We only need a few bits, but uint8_t apparently doesn't satisfy std::has_unique_object_representations_v
enum class MarkKind : uint16_t
{
None = 0,
Prompt = 1,
Command = 2,
Output = 3,
};
class TextAttribute final
{
public:
@@ -46,7 +55,8 @@ public:
_foreground{},
_background{},
_hyperlinkId{ 0 },
_underlineColor{}
_underlineColor{},
_markKind{ MarkKind::None }
{
}
@@ -55,7 +65,8 @@ public:
_foreground{ gsl::at(s_legacyForegroundColorMap, wLegacyAttr & FG_ATTRS) },
_background{ gsl::at(s_legacyBackgroundColorMap, (wLegacyAttr & BG_ATTRS) >> 4) },
_hyperlinkId{ 0 },
_underlineColor{}
_underlineColor{},
_markKind{ MarkKind::None }
{
}
@@ -66,7 +77,8 @@ public:
_foreground{ rgbForeground },
_background{ rgbBackground },
_hyperlinkId{ 0 },
_underlineColor{ rgbUnderline }
_underlineColor{ rgbUnderline },
_markKind{ MarkKind::None }
{
}
@@ -75,7 +87,8 @@ public:
_foreground{ foreground },
_background{ background },
_hyperlinkId{ hyperlinkId },
_underlineColor{ underlineColor }
_underlineColor{ underlineColor },
_markKind{ MarkKind::None }
{
}
@@ -135,6 +148,15 @@ public:
return _attrs;
}
constexpr void SetMarkAttributes(const MarkKind attrs) noexcept
{
_markKind = attrs;
}
constexpr MarkKind GetMarkAttributes() const noexcept
{
return _markKind;
}
bool IsHyperlink() const noexcept;
TextColor GetForeground() const noexcept;
@@ -202,6 +224,7 @@ private:
TextColor _foreground; // sizeof: 4, alignof: 1
TextColor _background; // sizeof: 4, alignof: 1
TextColor _underlineColor; // sizeof: 4, alignof: 1
MarkKind _markKind; // sizeof: 2, alignof: 1
#ifdef UNIT_TESTING
friend class TextBufferTests;

View File

@@ -6,19 +6,87 @@
#include "textBuffer.hpp"
// All of these are somewhat annoying when trying to implement RefcountBuffer.
// You can't stuff a unique_ptr into ut->q (= void*) after all.
#pragma warning(disable : 26402) // Return a scoped object instead of a heap-allocated if it has a move constructor (r.3).
#pragma warning(disable : 26403) // Reset or explicitly delete an owner<T> pointer '...' (r.3).
#pragma warning(disable : 26409) // Avoid calling new and delete explicitly, use std::make_unique<T> instead (r.11).
struct RowRange
{
til::CoordType begin;
til::CoordType end;
};
struct RefcountBuffer
{
size_t references;
size_t capacity;
wchar_t data[1];
static RefcountBuffer* EnsureCapacityForOverwrite(RefcountBuffer* buffer, size_t capacity)
{
// We must not just ensure that `buffer` has at least `capacity`, but also that its reference count is <= 1, because otherwise we would resize a shared buffer.
if (buffer != nullptr && buffer->references <= 1 && buffer->capacity >= capacity)
{
return buffer;
}
const auto oldCapacity = buffer ? buffer->capacity << 1 : 0;
const auto newCapacity = std::max(capacity + 128, oldCapacity);
const auto newBuffer = static_cast<RefcountBuffer*>(::operator new(sizeof(RefcountBuffer) - sizeof(data) + newCapacity * sizeof(wchar_t)));
if (!newBuffer)
{
return nullptr;
}
if (buffer)
{
buffer->Release();
}
// Copying the old buffer's data is not necessary because utextAccess() will scribble right over it.
newBuffer->references = 1;
newBuffer->capacity = newCapacity;
return newBuffer;
}
void AddRef() noexcept
{
// With our usage patterns, either of these two would indicate
// an unbalanced AddRef/Release or a memory corruption.
assert(references > 0 && references < 1000);
references++;
}
void Release() noexcept
{
// With our usage patterns, either of these two would indicate
// an unbalanced AddRef/Release or a memory corruption.
assert(references > 0 && references < 1000);
if (--references == 0)
{
::operator delete(this);
}
}
};
constexpr size_t& accessLength(UText* ut) noexcept
{
static_assert(sizeof(ut->p) == sizeof(size_t));
return *std::bit_cast<size_t*>(&ut->p);
}
constexpr RefcountBuffer*& accessBuffer(UText* ut) noexcept
{
static_assert(sizeof(ut->q) == sizeof(RefcountBuffer*));
return *std::bit_cast<RefcountBuffer**>(&ut->q);
}
constexpr RowRange& accessRowRange(UText* ut) noexcept
{
static_assert(sizeof(ut->a) == sizeof(RowRange));
return *std::bit_cast<RowRange*>(&ut->a);
}
@@ -56,11 +124,16 @@ static UText* U_CALLCONV utextClone(UText* dest, const UText* src, UBool deep, U
}
dest = utext_setup(dest, 0, status);
if (*status <= U_ZERO_ERROR)
if (*status > U_ZERO_ERROR)
{
memcpy(dest, src, sizeof(UText));
return dest;
}
memcpy(dest, src, sizeof(UText));
if (const auto buf = accessBuffer(dest))
{
buf->AddRef();
}
return dest;
}
@@ -82,7 +155,9 @@ try
for (til::CoordType y = range.begin; y < range.end; ++y)
{
length += textBuffer.GetRowByOffset(y).GetText().size();
const auto& row = textBuffer.GetRowByOffset(y);
// Later down below we'll add a newline to the text if !wasWrapForced, so we need to account for that here.
length += row.GetText().size() + !row.WasWrapForced();
}
accessLength(ut) = length;
@@ -111,12 +186,9 @@ catch (...)
static UBool U_CALLCONV utextAccess(UText* ut, int64_t nativeIndex, UBool forward) noexcept
try
{
if (nativeIndex < 0)
{
nativeIndex = 0;
}
auto neededIndex = nativeIndex;
// This will make it simpler for us to search the row that contains the nativeIndex,
// because we'll now only need to check for `start<=index<limit` and nothing else.
if (!forward)
{
neededIndex--;
@@ -124,13 +196,17 @@ try
const auto& textBuffer = *static_cast<const TextBuffer*>(ut->context);
const auto range = accessRowRange(ut);
auto start = ut->chunkNativeStart;
auto limit = ut->chunkNativeLimit;
auto y = accessCurrentRow(ut);
std::wstring_view text;
const auto startOld = ut->chunkNativeStart;
const auto limitOld = ut->chunkNativeLimit;
auto start = startOld;
auto limit = limitOld;
if (neededIndex < start || neededIndex >= limit)
if (neededIndex < startOld || neededIndex >= limitOld)
{
auto y = accessCurrentRow(ut);
std::wstring_view text;
bool wasWrapForced = false;
if (neededIndex < start)
{
do
@@ -138,12 +214,16 @@ try
--y;
if (y < range.begin)
{
return false;
break;
}
text = textBuffer.GetRowByOffset(y).GetText();
const auto& row = textBuffer.GetRowByOffset(y);
text = row.GetText();
wasWrapForced = row.WasWrapForced();
limit = start;
start -= text.size();
// Later down below we'll add a newline to the text if !wasWrapForced, so we need to account for that here.
start -= text.size() + !wasWrapForced;
} while (neededIndex < start);
}
else
@@ -153,35 +233,63 @@ try
++y;
if (y >= range.end)
{
return false;
break;
}
text = textBuffer.GetRowByOffset(y).GetText();
const auto& row = textBuffer.GetRowByOffset(y);
text = row.GetText();
wasWrapForced = row.WasWrapForced();
start = limit;
limit += text.size();
// Later down below we'll add a newline to the text if !wasWrapForced, so we need to account for that here.
limit += text.size() + !wasWrapForced;
} while (neededIndex >= limit);
}
accessCurrentRow(ut) = y;
ut->chunkNativeStart = start;
ut->chunkNativeLimit = limit;
ut->chunkLength = gsl::narrow_cast<int32_t>(text.size());
assert(start >= 0);
// If we have already calculated the total length we can also assert that the limit is in range.
assert(ut->p == nullptr || static_cast<size_t>(limit) <= accessLength(ut));
// Even if we went out-of-bounds, we still need to update the chunkContents to contain the first/last chunk.
if (limit != limitOld)
{
if (!wasWrapForced)
{
const auto newSize = text.size() + 1;
const auto buffer = RefcountBuffer::EnsureCapacityForOverwrite(accessBuffer(ut), newSize);
memcpy(&buffer->data[0], text.data(), text.size() * sizeof(wchar_t));
til::at(buffer->data, text.size()) = L'\n';
text = { &buffer->data[0], newSize };
accessBuffer(ut) = buffer;
}
accessCurrentRow(ut) = y;
ut->chunkNativeStart = start;
ut->chunkNativeLimit = limit;
ut->chunkLength = gsl::narrow_cast<int32_t>(text.size());
#pragma warning(suppress : 26490) // Don't use reinterpret_cast (type.1).
ut->chunkContents = reinterpret_cast<const char16_t*>(text.data());
ut->nativeIndexingLimit = ut->chunkLength;
ut->chunkContents = reinterpret_cast<const char16_t*>(text.data());
ut->nativeIndexingLimit = ut->chunkLength;
}
}
auto offset = gsl::narrow_cast<int32_t>(nativeIndex - start);
// The ICU documentation is a little bit misleading. It states:
// > @param forward [...] If true, start<=index<limit. If false, [...] start<index<=limit.
// but that's just for finding the target chunk. The chunkOffset is not actually constrained to that!
// std::clamp will perform a<=b<=c, which is what we want.
const auto clampedIndex = std::clamp(nativeIndex, start, limit);
auto offset = gsl::narrow_cast<int32_t>(clampedIndex - start);
// Don't leave the offset on a trailing surrogate pair. See U16_SET_CP_START.
// This assumes that the TextBuffer contains valid UTF-16 which may theoretically not be the case.
if (offset > 0 && offset < ut->chunkLength && U16_IS_TRAIL(til::at(ut->chunkContents, offset)))
{
offset--;
}
ut->chunkOffset = offset;
return true;
return neededIndex >= start && neededIndex < limit;
}
catch (...)
{
@@ -256,18 +364,32 @@ catch (...)
return 0;
}
static void U_CALLCONV utextClose(UText* ut) noexcept
{
if (const auto buffer = accessBuffer(ut))
{
buffer->Release();
}
}
static constexpr UTextFuncs utextFuncs{
.tableSize = sizeof(UTextFuncs),
.clone = utextClone,
.nativeLength = utextNativeLength,
.access = utextAccess,
.close = utextClose,
};
// Creates a UText from the given TextBuffer that spans rows [rowBeg,RowEnd).
UText Microsoft::Console::ICU::UTextFromTextBuffer(const TextBuffer& textBuffer, til::CoordType rowBeg, til::CoordType rowEnd) noexcept
Microsoft::Console::ICU::unique_utext Microsoft::Console::ICU::UTextFromTextBuffer(const TextBuffer& textBuffer, til::CoordType rowBeg, til::CoordType rowEnd) noexcept
{
#pragma warning(suppress : 26477) // Use 'nullptr' rather than 0 or NULL (es.47).
UText ut = UTEXT_INITIALIZER;
unique_utext ut{ UTEXT_INITIALIZER };
UErrorCode status = U_ZERO_ERROR;
utext_setup(&ut, 0, &status);
FAIL_FAST_IF(status > U_ZERO_ERROR);
ut.providerProperties = (1 << UTEXT_PROVIDER_LENGTH_IS_EXPENSIVE) | (1 << UTEXT_PROVIDER_STABLE_CHUNKS);
ut.pFuncs = &utextFuncs;
ut.context = &textBuffer;

View File

@@ -10,8 +10,9 @@ class TextBuffer;
namespace Microsoft::Console::ICU
{
using unique_uregex = wistd::unique_ptr<URegularExpression, wil::function_deleter<decltype(&uregex_close), &uregex_close>>;
using unique_utext = wil::unique_struct<UText, decltype(&utext_close), &utext_close>;
UText UTextFromTextBuffer(const TextBuffer& textBuffer, til::CoordType rowBeg, til::CoordType rowEnd) noexcept;
unique_utext UTextFromTextBuffer(const TextBuffer& textBuffer, til::CoordType rowBeg, til::CoordType rowEnd) noexcept;
unique_uregex CreateRegex(const std::wstring_view& pattern, uint32_t flags, UErrorCode* status) noexcept;
til::point_span BufferRangeFromMatch(UText* ut, URegularExpression* re);
}

View File

@@ -188,11 +188,7 @@ void Cursor::_RedrawCursor() noexcept
// - <none>
void Cursor::_RedrawCursorAlways() noexcept
{
try
{
_parentBuffer.TriggerRedrawCursor(_cPosition);
}
CATCH_LOG();
_parentBuffer.NotifyPaintFrame();
}
void Cursor::SetPosition(const til::point cPosition) noexcept

View File

@@ -8,37 +8,37 @@
using namespace Microsoft::Console::Types;
bool Search::ResetIfStale(Microsoft::Console::Render::IRenderData& renderData, const std::wstring_view& needle, bool reverse, bool caseInsensitive)
bool Search::IsStale(const Microsoft::Console::Render::IRenderData& renderData, const std::wstring_view& needle, SearchFlag flags) const noexcept
{
return _renderData != &renderData ||
_needle != needle ||
_flags != flags ||
_lastMutationId != renderData.GetTextBuffer().GetLastMutationId();
}
void Search::Reset(Microsoft::Console::Render::IRenderData& renderData, const std::wstring_view& needle, SearchFlag flags, bool reverse)
{
const auto& textBuffer = renderData.GetTextBuffer();
const auto lastMutationId = textBuffer.GetLastMutationId();
if (_needle == needle &&
_caseInsensitive == caseInsensitive &&
_lastMutationId == lastMutationId)
{
_step = reverse ? -1 : 1;
return false;
}
_renderData = &renderData;
_needle = needle;
_caseInsensitive = caseInsensitive;
_lastMutationId = lastMutationId;
_flags = flags;
_lastMutationId = textBuffer.GetLastMutationId();
_results = textBuffer.SearchText(needle, caseInsensitive);
auto result = textBuffer.SearchText(needle, _flags);
_ok = result.has_value();
_results = std::move(result).value_or(std::vector<til::point_span>{});
_index = reverse ? gsl::narrow_cast<ptrdiff_t>(_results.size()) - 1 : 0;
_step = reverse ? -1 : 1;
return true;
}
void Search::MoveToCurrentSelection()
{
if (_renderData->IsSelectionActive())
{
MoveToPoint(_renderData->GetTextBuffer().ScreenToBufferPosition(_renderData->GetSelectionAnchor()));
}
else if (const auto span = _renderData->GetSearchHighlightFocused())
{
MoveToPoint(_step > 0 ? span->start : span->end);
}
}
void Search::MoveToPoint(const til::point anchor) noexcept
@@ -93,8 +93,9 @@ void Search::MovePastPoint(const til::point anchor) noexcept
_index = (index + count) % count;
}
void Search::FindNext() noexcept
void Search::FindNext(bool reverse) noexcept
{
_step = reverse ? -1 : 1;
if (const auto count{ gsl::narrow_cast<ptrdiff_t>(_results.size()) })
{
_index = (_index + _step + count) % count;
@@ -111,28 +112,6 @@ const til::point_span* Search::GetCurrent() const noexcept
return nullptr;
}
void Search::HighlightResults() const
{
std::vector<til::inclusive_rect> toSelect;
const auto& textBuffer = _renderData->GetTextBuffer();
for (const auto& r : _results)
{
const auto rbStart = textBuffer.BufferToScreenPosition(r.start);
const auto rbEnd = textBuffer.BufferToScreenPosition(r.end);
til::inclusive_rect re;
re.top = rbStart.y;
re.bottom = rbEnd.y;
re.left = rbStart.x;
re.right = rbEnd.x;
toSelect.emplace_back(re);
}
_renderData->SelectSearchRegions(std::move(toSelect));
}
// Routine Description:
// - Takes the found word and selects it in the screen buffer
@@ -158,7 +137,17 @@ const std::vector<til::point_span>& Search::Results() const noexcept
return _results;
}
std::vector<til::point_span>&& Search::ExtractResults() noexcept
{
return std::move(_results);
}
ptrdiff_t Search::CurrentMatch() const noexcept
{
return _index;
}
bool Search::IsOk() const noexcept
{
return _ok;
}

View File

@@ -20,32 +20,44 @@ Revision History:
#include "textBuffer.hpp"
#include "../renderer/inc/IRenderData.hpp"
enum class SearchFlag : unsigned int
{
None = 0,
CaseInsensitive = 1 << 0,
RegularExpression = 1 << 1,
};
DEFINE_ENUM_FLAG_OPERATORS(SearchFlag);
class Search final
{
public:
Search() = default;
bool ResetIfStale(Microsoft::Console::Render::IRenderData& renderData, const std::wstring_view& needle, bool reverse, bool caseInsensitive);
bool IsStale(const Microsoft::Console::Render::IRenderData& renderData, const std::wstring_view& needle, SearchFlag flags) const noexcept;
void Reset(Microsoft::Console::Render::IRenderData& renderData, const std::wstring_view& needle, SearchFlag flags, bool reverse);
void MoveToCurrentSelection();
void MoveToPoint(til::point anchor) noexcept;
void MovePastPoint(til::point anchor) noexcept;
void FindNext() noexcept;
void FindNext(bool reverse) noexcept;
const til::point_span* GetCurrent() const noexcept;
void HighlightResults() const;
bool SelectCurrent() const;
const std::vector<til::point_span>& Results() const noexcept;
std::vector<til::point_span>&& ExtractResults() noexcept;
ptrdiff_t CurrentMatch() const noexcept;
bool IsOk() const noexcept;
private:
// _renderData is a pointer so that Search() is constexpr default constructable.
Microsoft::Console::Render::IRenderData* _renderData = nullptr;
std::wstring _needle;
bool _caseInsensitive = false;
SearchFlag _flags{};
uint64_t _lastMutationId = 0;
bool _ok{ false };
std::vector<til::point_span> _results;
ptrdiff_t _index = 0;
ptrdiff_t _step = 0;

View File

@@ -12,6 +12,7 @@
#include "../../types/inc/GlyphWidth.hpp"
#include "../renderer/base/renderer.hpp"
#include "../types/inc/utils.hpp"
#include "search.h"
using namespace Microsoft::Console;
using namespace Microsoft::Console::Types;
@@ -562,7 +563,7 @@ til::point TextBuffer::NavigateCursor(til::point position, til::CoordType distan
// This function is intended for writing regular "lines" of text as it'll set the wrap flag on the given row.
// You can continue calling the function on the same row as long as state.columnEnd < state.columnLimit.
void TextBuffer::Write(til::CoordType row, const TextAttribute& attributes, RowWriteState& state)
void TextBuffer::Replace(til::CoordType row, const TextAttribute& attributes, RowWriteState& state)
{
auto& r = GetMutableRowByOffset(row);
r.ReplaceText(state);
@@ -570,6 +571,36 @@ void TextBuffer::Write(til::CoordType row, const TextAttribute& attributes, RowW
TriggerRedraw(Viewport::FromExclusive({ state.columnBeginDirty, row, state.columnEndDirty, row + 1 }));
}
void TextBuffer::Insert(til::CoordType row, const TextAttribute& attributes, RowWriteState& state)
{
auto& r = GetMutableRowByOffset(row);
auto& scratch = GetScratchpadRow();
scratch.CopyFrom(r);
r.ReplaceText(state);
r.ReplaceAttributes(state.columnBegin, state.columnEnd, attributes);
// Restore trailing text from our backup in scratch.
RowWriteState restoreState{
.text = scratch.GetText(state.columnBegin, state.columnLimit),
.columnBegin = state.columnEnd,
.columnLimit = state.columnLimit,
};
r.ReplaceText(restoreState);
// Restore trailing attributes as well.
if (const auto copyAmount = restoreState.columnEnd - restoreState.columnBegin; copyAmount > 0)
{
auto& rowAttr = r.Attributes();
const auto& scratchAttr = scratch.Attributes();
const auto restoreAttr = scratchAttr.slice(gsl::narrow<uint16_t>(state.columnBegin), gsl::narrow<uint16_t>(state.columnBegin + copyAmount));
rowAttr.replace(gsl::narrow<uint16_t>(restoreState.columnBegin), gsl::narrow<uint16_t>(restoreState.columnEnd), restoreAttr);
}
TriggerRedraw(Viewport::FromExclusive({ state.columnBeginDirty, row, restoreState.columnEndDirty, row + 1 }));
}
// Fills an area of the buffer with a given fill character(s) and attributes.
void TextBuffer::FillRect(const til::rect& rect, const std::wstring_view& fill, const TextAttribute& attributes)
{
@@ -1083,11 +1114,8 @@ void TextBuffer::SetCurrentLineRendition(const LineRendition lineRendition, cons
// And if it's no longer single width, the right half of the row should be erased.
if (lineRendition != LineRendition::SingleWidth)
{
const auto fillChar = L' ';
const auto fillOffset = GetLineWidth(rowIndex);
const auto fillLength = gsl::narrow<size_t>(GetSize().Width() - fillOffset);
const OutputCellIterator fillData{ fillChar, fillAttributes, fillLength };
row.WriteCells(fillData, fillOffset, false);
FillRect({ fillOffset, rowIndex, til::CoordTypeMax, rowIndex + 1 }, L" ", fillAttributes);
// We also need to make sure the cursor is clamped within the new width.
GetCursor().SetPosition(ClampPositionWithinLine(cursorPosition));
}
@@ -1149,37 +1177,40 @@ void TextBuffer::Reset() noexcept
_initialAttributes = _currentAttributes;
}
void TextBuffer::ClearScrollback(const til::CoordType start, const til::CoordType height)
// Arguments:
// - newFirstRow: The current y-position of the viewport. We'll clear up until here.
// - rowsToKeep: the number of rows to keep in the buffer.
void TextBuffer::ClearScrollback(const til::CoordType newFirstRow, const til::CoordType rowsToKeep)
{
if (start <= 0)
// We're already at the top? don't clear anything. There's no scrollback.
if (newFirstRow <= 0)
{
return;
}
if (height <= 0)
// The new viewport should keep 0 rows? Then just reset everything.
if (rowsToKeep <= 0)
{
_decommit();
return;
}
ClearMarksInRange(til::point{ 0, 0 }, til::point{ _width, std::max(0, newFirstRow - 1) });
// Our goal is to move the viewport to the absolute start of the underlying memory buffer so that we can
// MEM_DECOMMIT the remaining memory. _firstRow is used to make the TextBuffer behave like a circular buffer.
// The start parameter is relative to the _firstRow. The trick to get the content to the absolute start
// The newFirstRow parameter is relative to the _firstRow. The trick to get the content to the absolute start
// is to simply add _firstRow ourselves and then reset it to 0. This causes ScrollRows() to write into
// the absolute start while reading from relative coordinates. This works because GetRowByOffset()
// operates modulo the buffer height and so the possibly-too-large startAbsolute won't be an issue.
const auto startAbsolute = _firstRow + start;
const auto startAbsolute = _firstRow + newFirstRow;
_firstRow = 0;
ScrollRows(startAbsolute, height, -startAbsolute);
ScrollRows(startAbsolute, rowsToKeep, -startAbsolute);
const auto end = _estimateOffsetOfLastCommittedRow();
for (auto y = height; y <= end; ++y)
for (auto y = rowsToKeep; y <= end; ++y)
{
GetMutableRowByOffset(y).Reset(_initialAttributes);
}
ScrollMarks(-start);
ClearMarksInRange(til::point{ 0, height }, til::point{ _width, _height });
}
// Routine Description:
@@ -1239,6 +1270,14 @@ Microsoft::Console::Render::Renderer& TextBuffer::GetRenderer() noexcept
return _renderer;
}
void TextBuffer::NotifyPaintFrame() noexcept
{
if (_isActiveBuffer)
{
_renderer.NotifyPaintFrame();
}
}
void TextBuffer::TriggerRedraw(const Viewport& viewport)
{
if (_isActiveBuffer)
@@ -1247,14 +1286,6 @@ void TextBuffer::TriggerRedraw(const Viewport& viewport)
}
}
void TextBuffer::TriggerRedrawCursor(const til::point position)
{
if (_isActiveBuffer)
{
_renderer.TriggerRedrawCursor(&position);
}
}
void TextBuffer::TriggerRedrawAll()
{
if (_isActiveBuffer)
@@ -1297,7 +1328,8 @@ void TextBuffer::TriggerNewTextNotification(const std::wstring_view newText)
// - the delimiter class for the given char
DelimiterClass TextBuffer::_GetDelimiterClassAt(const til::point pos, const std::wstring_view wordDelimiters) const
{
return GetRowByOffset(pos.y).DelimiterClassAt(pos.x, wordDelimiters);
const auto realPos = ScreenToBufferPosition(pos);
return GetRowByOffset(realPos.y).DelimiterClassAt(realPos.x, wordDelimiters);
}
// Method Description:
@@ -1413,10 +1445,23 @@ til::point TextBuffer::_GetWordStartForSelection(const til::point target, const
// expand left until we hit the left boundary or a different delimiter class
while (result != bufferSize.Origin() && _GetDelimiterClassAt(result, wordDelimiters) == initialDelimiter)
{
//prevent selection wrapping on whitespace selection
if (isControlChar && result.x == bufferSize.Left())
if (result.x == bufferSize.Left())
{
break;
// Prevent wrapping to the previous line if the selection begins on whitespace
if (isControlChar)
{
break;
}
if (result.y > 0)
{
// Prevent wrapping to the previous line if it was hard-wrapped (e.g. not forced by us to wrap)
const auto& priorRow = GetRowByOffset(result.y - 1);
if (!priorRow.WasWrapForced())
{
break;
}
}
}
bufferSize.DecrementInBounds(result);
}
@@ -1536,10 +1581,22 @@ til::point TextBuffer::_GetWordEndForSelection(const til::point target, const st
// expand right until we hit the right boundary as a ControlChar or a different delimiter class
while (result != bufferSize.BottomRightInclusive() && _GetDelimiterClassAt(result, wordDelimiters) == initialDelimiter)
{
if (isControlChar && result.x == bufferSize.RightInclusive())
if (result.x == bufferSize.RightInclusive())
{
break;
// Prevent wrapping to the next line if the selection begins on whitespace
if (isControlChar)
{
break;
}
// Prevent wrapping to the next line if this one was hard-wrapped (e.g. not forced by us to wrap)
const auto& row = GetRowByOffset(result.y);
if (!row.WasWrapForced())
{
break;
}
}
bufferSize.IncrementInBoundsCircular(result);
}
@@ -1893,8 +1950,8 @@ std::vector<til::point_span> TextBuffer::GetTextSpans(til::point start, til::poi
// equivalent buffer offsets, taking line rendition into account.
if (!bufferCoordinates)
{
higherCoord = ScreenToBufferLine(higherCoord, GetLineRendition(higherCoord.y));
lowerCoord = ScreenToBufferLine(lowerCoord, GetLineRendition(lowerCoord.y));
higherCoord = ScreenToBufferLineInclusive(higherCoord, GetLineRendition(higherCoord.y));
lowerCoord = ScreenToBufferLineInclusive(lowerCoord, GetLineRendition(lowerCoord.y));
}
til::inclusive_rect asRect = { higherCoord.x, higherCoord.y, lowerCoord.x, lowerCoord.y };
@@ -1968,25 +2025,10 @@ size_t TextBuffer::SpanLength(const til::point coordStart, const til::point coor
// - end - where to end getting text
// Return Value:
// - Just the text.
std::wstring TextBuffer::GetPlainText(const til::point& start, const til::point& end) const
std::wstring TextBuffer::GetPlainText(const til::point start, const til::point end) const
{
std::wstring text;
auto spanLength = SpanLength(start, end);
text.reserve(spanLength);
auto it = GetCellDataAt(start);
for (; it && spanLength > 0; ++it, --spanLength)
{
const auto& cell = *it;
if (cell.DbcsAttr() != DbcsAttribute::Trailing)
{
const auto chars = cell.Chars();
text.append(chars);
}
}
return text;
const auto req = CopyRequest::FromConfig(*this, start, end, true, false, false, false);
return GetPlainText(req);
}
// Routine Description:
@@ -2005,8 +2047,8 @@ std::tuple<til::CoordType, til::CoordType, bool> TextBuffer::_RowCopyHelper(cons
if (req.blockSelection)
{
const auto lineRendition = row.GetLineRendition();
const auto minX = req.bufferCoordinates ? req.minX : ScreenToBufferLine(til::point{ req.minX, iRow }, lineRendition).x;
const auto maxX = req.bufferCoordinates ? req.maxX : ScreenToBufferLine(til::point{ req.maxX, iRow }, lineRendition).x;
const auto minX = req.bufferCoordinates ? req.minX : ScreenToBufferLineInclusive(til::point{ req.minX, iRow }, lineRendition).x;
const auto maxX = req.bufferCoordinates ? req.maxX : ScreenToBufferLineInclusive(til::point{ req.maxX, iRow }, lineRendition).x;
rowBeg = minX;
rowEnd = maxX + 1; // +1 to get an exclusive end
@@ -2014,8 +2056,8 @@ std::tuple<til::CoordType, til::CoordType, bool> TextBuffer::_RowCopyHelper(cons
else
{
const auto lineRendition = row.GetLineRendition();
const auto beg = req.bufferCoordinates ? req.beg : ScreenToBufferLine(req.beg, lineRendition);
const auto end = req.bufferCoordinates ? req.end : ScreenToBufferLine(req.end, lineRendition);
const auto beg = req.bufferCoordinates ? req.beg : ScreenToBufferLineInclusive(req.beg, lineRendition);
const auto end = req.bufferCoordinates ? req.end : ScreenToBufferLineInclusive(req.end, lineRendition);
rowBeg = iRow != beg.y ? 0 : beg.x;
rowEnd = iRow != end.y ? row.GetReadableColumnCount() : end.x + 1; // +1 to get an exclusive end
@@ -2374,7 +2416,7 @@ std::string TextBuffer::GenRTF(const CopyRequest& req,
// \fsN: specifies font size in half-points. E.g. \fs20 results in a font
// size of 10 pts. That's why, font size is multiplied by 2 here.
fmt::format_to(std::back_inserter(contentBuilder), FMT_COMPILE("\\fs{}"), std::to_string(2 * fontHeightPoints));
fmt::format_to(std::back_inserter(contentBuilder), FMT_COMPILE("\\fs{}"), 2 * fontHeightPoints);
// Set the background color for the page. But the standard way (\cbN) to do
// this isn't supported in Word. However, the following control words sequence
@@ -2501,8 +2543,7 @@ void TextBuffer::_AppendRTFText(std::string& contentBuilder, const std::wstring_
{
// Windows uses unsigned wchar_t - RTF uses signed ones.
// '?' is the fallback ascii character.
const auto codeUnitRTFStr = std::to_string(std::bit_cast<int16_t>(codeUnit));
fmt::format_to(std::back_inserter(contentBuilder), FMT_COMPILE("\\u{}?"), codeUnitRTFStr);
fmt::format_to(std::back_inserter(contentBuilder), FMT_COMPILE("\\u{}?"), std::bit_cast<int16_t>(codeUnit));
}
}
}
@@ -2523,6 +2564,7 @@ void TextBuffer::Serialize(const wchar_t* destination) const
TextColor previousBg;
TextColor previousUl;
uint16_t previousHyperlinkId = 0;
bool delayedLineBreak = false;
// This iterates through each row. The exit condition is at the end
// of the for() loop so that we can properly handle file flushing.
@@ -2542,9 +2584,11 @@ void TextBuffer::Serialize(const wchar_t* destination) const
}
const auto& runs = row.Attributes().runs();
auto it = runs.begin();
const auto beg = runs.begin();
const auto end = runs.end();
auto it = beg;
const auto last = end - 1;
const auto lastCharX = row.MeasureRight();
til::CoordType oldX = 0;
for (; it != end; ++it)
@@ -2724,24 +2768,55 @@ void TextBuffer::Serialize(const wchar_t* destination) const
}
}
auto newX = oldX + it->length;
// Trim whitespace with default attributes from the end of each line.
if (it == last && it->value == TextAttribute{})
// Initially, the buffer is initialized with the default attributes, but once it begins to scroll,
// newly scrolled in rows are initialized with the current attributes. This means we need to set
// the current attributes to those of the upcoming row before the row comes up. Or inversely:
// We let the row come up, let it set its attributes and only then print the newline.
if (delayedLineBreak)
{
// This can result in oldX > newX, but that's okay because GetText()
// is robust against that and returns an empty string.
newX = row.MeasureRight();
buffer.append(L"\r\n");
delayedLineBreak = false;
}
auto newX = oldX + it->length;
// Since our text buffer doesn't store the original input text, the information over the amount of trailing
// whitespaces was lost. If we don't do anything here then a row that just says "Hello" would be serialized
// to "Hello ...". If the user restores the buffer dump with a different window size,
// this would result in some fairly ugly reflow. This code attempts to at least trim trailing whitespaces.
//
// As mentioned above for `delayedLineBreak`, rows are initialized with their first attribute, BUT
// only if the viewport has begun to scroll. Otherwise, they're initialized with the default attributes.
// In other words, we can only skip \x1b[K = Erase in Line, if both the first/last attribute are the default attribute.
static constexpr TextAttribute defaultAttr;
const auto trimTrailingWhitespaces = it == last && lastCharX < newX;
const auto clearToEndOfLine = trimTrailingWhitespaces && (beg->value != defaultAttr || last->value != defaultAttr);
if (trimTrailingWhitespaces)
{
newX = lastCharX;
}
buffer.append(row.GetText(oldX, newX));
if (clearToEndOfLine)
{
buffer.append(L"\x1b[K");
}
oldX = newX;
}
const auto moreRowsRemaining = currentRow < lastRowWithText;
delayedLineBreak = !row.WasWrapForced();
if (!row.WasWrapForced() || !moreRowsRemaining)
if (!moreRowsRemaining)
{
buffer.append(L"\r\n");
if (previousHyperlinkId)
{
buffer.append(L"\x1b]8;;\x1b\\");
}
buffer.append(L"\x1b[m\r\n");
}
if (buffer.size() >= writeThreshold || !moreRowsRemaining)
@@ -2749,10 +2824,8 @@ void TextBuffer::Serialize(const wchar_t* destination) const
const auto fileSize = gsl::narrow<DWORD>(buffer.size() * sizeof(wchar_t));
DWORD bytesWritten = 0;
THROW_IF_WIN32_BOOL_FALSE(WriteFile(file.get(), buffer.data(), fileSize, &bytesWritten, nullptr));
if (bytesWritten != fileSize)
{
THROW_WIN32_MSG(ERROR_WRITE_FAULT, "failed to write");
}
THROW_WIN32_IF_MSG(ERROR_WRITE_FAULT, bytesWritten != fileSize, "failed to write");
buffer.clear();
}
if (!moreRowsRemaining)
@@ -2871,6 +2944,18 @@ void TextBuffer::Reflow(TextBuffer& oldBuffer, TextBuffer& newBuffer, const View
oldRowLimit = std::max(oldRowLimit, oldCursorPos.x + 1);
}
// Immediately copy this mark over to our new row. The positions of the
// marks themselves will be preserved, since they're just text
// attributes. But the "bookmark" needs to get moved to the new row too.
// * If a row wraps as it reflows, that's fine - we want to leave the
// mark on the row it started on.
// * If the second row of a wrapped row had a mark, and it de-flows onto a
// single row, that's fine! The mark was on that logical row.
if (oldRow.GetScrollbarData().has_value())
{
newBuffer.GetMutableRowByOffset(newY).SetScrollbarData(oldRow.GetScrollbarData());
}
til::CoordType oldX = 0;
// Copy oldRow into newBuffer until oldRow has been fully consumed.
@@ -2956,6 +3041,15 @@ void TextBuffer::Reflow(TextBuffer& oldBuffer, TextBuffer& newBuffer, const View
}
}
// The for loop right after this if condition will copy entire rows of attributes at a time.
// This assumes of course that the "write cursor" (newX, newY) is at the start of a row.
// If we didn't check for this, we may otherwise copy attributes from a later row into a previous one.
if (newX != 0)
{
newX = 0;
newY++;
}
// Finish copying buffer attributes to remaining rows below the last
// printable character. This is to fix the `color 2f` scenario, where you
// change the buffer colors then resize and everything below the last
@@ -2990,9 +3084,6 @@ void TextBuffer::Reflow(TextBuffer& oldBuffer, TextBuffer& newBuffer, const View
assert(newCursorPos.y >= 0 && newCursorPos.y < newHeight);
newCursor.SetSize(oldCursor.GetSize());
newCursor.SetPosition(newCursorPos);
newBuffer._marks = oldBuffer._marks;
newBuffer._trimMarksOutsideBuffer();
}
// Method Description:
@@ -3103,14 +3194,15 @@ void TextBuffer::CopyHyperlinkMaps(const TextBuffer& other)
// Searches through the entire (committed) text buffer for `needle` and returns the coordinates in absolute coordinates.
// The end coordinates of the returned ranges are considered inclusive.
std::vector<til::point_span> TextBuffer::SearchText(const std::wstring_view& needle, bool caseInsensitive) const
std::optional<std::vector<til::point_span>> TextBuffer::SearchText(const std::wstring_view& needle, SearchFlag flags) const
{
return SearchText(needle, caseInsensitive, 0, til::CoordTypeMax);
return SearchText(needle, flags, 0, til::CoordTypeMax);
}
// Searches through the given rows [rowBeg,rowEnd) for `needle` and returns the coordinates in absolute coordinates.
// While the end coordinates of the returned ranges are considered inclusive, the [rowBeg,rowEnd) range is half-open.
std::vector<til::point_span> TextBuffer::SearchText(const std::wstring_view& needle, bool caseInsensitive, til::CoordType rowBeg, til::CoordType rowEnd) const
// Returns nullopt if the parameters were invalid (e.g. regex search was requested with an invalid regex)
std::optional<std::vector<til::point_span>> TextBuffer::SearchText(const std::wstring_view& needle, SearchFlag flags, til::CoordType rowBeg, til::CoordType rowEnd) const
{
rowEnd = std::min(rowEnd, _estimateOffsetOfLastCommittedRow() + 1);
@@ -3124,11 +3216,25 @@ std::vector<til::point_span> TextBuffer::SearchText(const std::wstring_view& nee
auto text = ICU::UTextFromTextBuffer(*this, rowBeg, rowEnd);
uint32_t flags = UREGEX_LITERAL;
WI_SetFlagIf(flags, UREGEX_CASE_INSENSITIVE, caseInsensitive);
uint32_t icuFlags{ 0 };
WI_SetFlagIf(icuFlags, UREGEX_CASE_INSENSITIVE, WI_IsFlagSet(flags, SearchFlag::CaseInsensitive));
if (WI_IsFlagSet(flags, SearchFlag::RegularExpression))
{
WI_SetFlag(icuFlags, UREGEX_MULTILINE);
}
else
{
WI_SetFlag(icuFlags, UREGEX_LITERAL);
}
UErrorCode status = U_ZERO_ERROR;
const auto re = ICU::CreateRegex(needle, flags, &status);
const auto re = ICU::CreateRegex(needle, icuFlags, &status);
if (status > U_ZERO_ERROR)
{
return std::nullopt;
}
uregex_setUText(re.get(), &text, &status);
if (uregex_find(re.get(), -1, &status))
@@ -3142,9 +3248,82 @@ std::vector<til::point_span> TextBuffer::SearchText(const std::wstring_view& nee
return results;
}
const std::vector<ScrollMark>& TextBuffer::GetMarks() const noexcept
// Collect up all the rows that were marked, and the data marked on that row.
// This is what should be used for hot paths, like updating the scrollbar.
std::vector<ScrollMark> TextBuffer::GetMarkRows() const
{
return _marks;
std::vector<ScrollMark> marks;
const auto bottom = _estimateOffsetOfLastCommittedRow();
for (auto y = 0; y <= bottom; y++)
{
const auto& row = GetRowByOffset(y);
const auto& data{ row.GetScrollbarData() };
if (data.has_value())
{
marks.emplace_back(y, *data);
}
}
return marks;
}
// Get all the regions for all the shell integration marks in the buffer.
// Marks will be returned in top-down order.
//
// This possibly iterates over every run in the buffer, so don't do this on a
// hot path. Just do this once per user input, if at all possible.
//
// Use `limit` to control how many you get, _starting from the bottom_. (e.g.
// limit=1 will just give you the "most recent mark").
std::vector<MarkExtents> TextBuffer::GetMarkExtents(size_t limit) const
{
if (limit == 0u)
{
return {};
}
std::vector<MarkExtents> marks{};
const auto bottom = _estimateOffsetOfLastCommittedRow();
auto lastPromptY = bottom;
for (auto promptY = bottom; promptY >= 0; promptY--)
{
const auto& currRow = GetRowByOffset(promptY);
auto& rowPromptData = currRow.GetScrollbarData();
if (!rowPromptData.has_value())
{
// This row didn't start a prompt, don't even look here.
continue;
}
// Future thought! In #11000 & #14792, we considered the possibility of
// scrolling to only an error mark, or something like that. Perhaps in
// the future, add a customizable filter that's a set of types of mark
// to include?
//
// For now, skip any "Default" marks, since those came from the UI. We
// just want the ones that correspond to shell integration.
if (rowPromptData->category == MarkCategory::Default)
{
continue;
}
// This row did start a prompt! Find the prompt that starts here.
// Presumably, no rows below us will have prompts, so pass in the last
// row with text as the bottom
marks.push_back(_scrollMarkExtentForRow(promptY, lastPromptY));
// operator>=(T, optional<U>) will return true if the optional is
// nullopt, unfortunately.
if (marks.size() >= limit)
{
break;
}
lastPromptY = promptY;
}
std::reverse(marks.begin(), marks.end());
return marks;
}
// Remove all marks between `start` & `end`, inclusive.
@@ -3152,115 +3331,318 @@ void TextBuffer::ClearMarksInRange(
const til::point start,
const til::point end)
{
auto inRange = [&start, &end](const ScrollMark& m) {
return (m.start >= start && m.start <= end) ||
(m.end >= start && m.end <= end);
auto top = std::clamp(std::min(start.y, end.y), 0, _height - 1);
auto bottom = std::clamp(std::max(start.y, end.y), 0, _estimateOffsetOfLastCommittedRow());
for (auto y = top; y <= bottom; y++)
{
auto& row = GetMutableRowByOffset(y);
auto& runs = row.Attributes().runs();
row.SetScrollbarData(std::nullopt);
for (auto& [attr, length] : runs)
{
attr.SetMarkAttributes(MarkKind::None);
}
}
}
void TextBuffer::ClearAllMarks()
{
ClearMarksInRange({ 0, 0 }, { _width - 1, _height - 1 });
}
// Collect up the extent of the prompt and possibly command and output for the
// mark that starts on this row.
MarkExtents TextBuffer::_scrollMarkExtentForRow(const til::CoordType rowOffset,
const til::CoordType bottomInclusive) const
{
const auto& startRow = GetRowByOffset(rowOffset);
const auto& rowPromptData = startRow.GetScrollbarData();
assert(rowPromptData.has_value());
MarkExtents mark{
.data = *rowPromptData,
};
_marks.erase(std::remove_if(_marks.begin(),
_marks.end(),
inRange),
_marks.end());
}
void TextBuffer::ClearAllMarks() noexcept
{
_marks.clear();
}
bool startedPrompt = false;
bool startedCommand = false;
bool startedOutput = false;
MarkKind lastMarkKind = MarkKind::Output;
// Adjust all the marks in the y-direction by `delta`. Positive values move the
// marks down (the positive y direction). Negative values move up. This will
// trim marks that are no longer have a start in the bounds of the buffer
void TextBuffer::ScrollMarks(const int delta)
{
for (auto& mark : _marks)
{
mark.start.y += delta;
// If the mark had sub-regions, then move those pointers too
if (mark.commandEnd.has_value())
const auto endThisMark = [&](auto x, auto y) {
if (startedOutput)
{
(*mark.commandEnd).y += delta;
mark.outputEnd = til::point{ x, y };
}
if (mark.outputEnd.has_value())
if (!startedOutput && startedCommand)
{
(*mark.outputEnd).y += delta;
mark.commandEnd = til::point{ x, y };
}
if (!startedCommand)
{
mark.end = til::point{ x, y };
}
};
auto x = 0;
auto y = rowOffset;
til::point lastMarkedText{ x, y };
for (; y <= bottomInclusive; y++)
{
// Now we need to iterate over text attributes. We need to find a
// segment of Prompt attributes, we'll skip those. Then there should be
// Command attributes. Collect up all of those, till we get to the next
// Output attribute.
const auto& row = GetRowByOffset(y);
const auto runs = row.Attributes().runs();
x = 0;
for (const auto& [attr, length] : runs)
{
const auto nextX = gsl::narrow_cast<uint16_t>(x + length);
const auto markKind{ attr.GetMarkAttributes() };
if (markKind != MarkKind::None)
{
lastMarkedText = { nextX, y };
if (markKind == MarkKind::Prompt)
{
if (startedCommand || startedOutput)
{
// we got a _new_ prompt. bail out.
break;
}
if (!startedPrompt)
{
// We entered the first prompt here
startedPrompt = true;
mark.start = til::point{ x, y };
}
endThisMark(lastMarkedText.x, lastMarkedText.y);
}
else if (markKind == MarkKind::Command && startedPrompt)
{
startedCommand = true;
endThisMark(lastMarkedText.x, lastMarkedText.y);
}
else if ((markKind == MarkKind::Output) && startedPrompt)
{
startedOutput = true;
if (!mark.commandEnd.has_value())
{
// immediately just end the command at the start here, so we can treat this whole run as output
mark.commandEnd = mark.end;
startedCommand = true;
}
endThisMark(lastMarkedText.x, lastMarkedText.y);
}
// Otherwise, we've changed from any state -> any state, and it doesn't really matter.
lastMarkKind = markKind;
}
// advance to next run of text
x = nextX;
}
// we went over all the runs in this row, but we're not done yet. Keep iterating on the next row.
}
// Okay, we're at the bottom of the buffer? Yea, just return what we found.
if (!startedCommand)
{
// If we never got to a Command or Output run, then we never set .end.
// Set it here to the last run we saw.
endThisMark(lastMarkedText.x, lastMarkedText.y);
}
return mark;
}
std::wstring TextBuffer::_commandForRow(const til::CoordType rowOffset, const til::CoordType bottomInclusive) const
{
std::wstring commandBuilder;
MarkKind lastMarkKind = MarkKind::Prompt;
for (auto y = rowOffset; y <= bottomInclusive; y++)
{
// Now we need to iterate over text attributes. We need to find a
// segment of Prompt attributes, we'll skip those. Then there should be
// Command attributes. Collect up all of those, till we get to the next
// Output attribute.
const auto& row = GetRowByOffset(y);
const auto runs = row.Attributes().runs();
auto x = 0;
for (const auto& [attr, length] : runs)
{
const auto nextX = gsl::narrow_cast<uint16_t>(x + length);
const auto markKind{ attr.GetMarkAttributes() };
if (markKind != lastMarkKind)
{
if (lastMarkKind == MarkKind::Command)
{
// We've changed away from being in a command. We're done.
// Return what we've gotten so far.
return commandBuilder;
}
// Otherwise, we've changed from any state -> any state, and it doesn't really matter.
lastMarkKind = markKind;
}
if (markKind == MarkKind::Command)
{
commandBuilder += row.GetText(x, nextX);
}
// advance to next run of text
x = nextX;
}
// we went over all the runs in this row, but we're not done yet. Keep iterating on the next row.
}
// Okay, we're at the bottom of the buffer? Yea, just return what we found.
return commandBuilder;
}
std::wstring TextBuffer::CurrentCommand() const
{
auto promptY = GetCursor().GetPosition().y;
for (; promptY >= 0; promptY--)
{
const auto& currRow = GetRowByOffset(promptY);
auto& rowPromptData = currRow.GetScrollbarData();
if (!rowPromptData.has_value())
{
// This row didn't start a prompt, don't even look here.
continue;
}
// This row did start a prompt! Find the prompt that starts here.
// Presumably, no rows below us will have prompts, so pass in the last
// row with text as the bottom
return _commandForRow(promptY, _estimateOffsetOfLastCommittedRow());
}
return L"";
}
std::vector<std::wstring> TextBuffer::Commands() const
{
std::vector<std::wstring> commands{};
const auto bottom = _estimateOffsetOfLastCommittedRow();
auto lastPromptY = bottom;
for (auto promptY = bottom; promptY >= 0; promptY--)
{
const auto& currRow = GetRowByOffset(promptY);
auto& rowPromptData = currRow.GetScrollbarData();
if (!rowPromptData.has_value())
{
// This row didn't start a prompt, don't even look here.
continue;
}
// This row did start a prompt! Find the prompt that starts here.
// Presumably, no rows below us will have prompts, so pass in the last
// row with text as the bottom
auto foundCommand = _commandForRow(promptY, lastPromptY);
if (!foundCommand.empty())
{
commands.emplace_back(std::move(foundCommand));
}
lastPromptY = promptY;
}
std::reverse(commands.begin(), commands.end());
return commands;
}
void TextBuffer::StartPrompt()
{
const auto currentRowOffset = GetCursor().GetPosition().y;
auto& currentRow = GetMutableRowByOffset(currentRowOffset);
currentRow.StartPrompt();
_currentAttributes.SetMarkAttributes(MarkKind::Prompt);
}
bool TextBuffer::_createPromptMarkIfNeeded()
{
// We might get here out-of-order, without seeing a StartPrompt (FTCS A)
// first. Since StartPrompt actually sets up the prompt mark on the ROW, we
// need to do a bit of extra work here to start a new mark (if the last one
// wasn't in an appropriate state).
const auto mostRecentMarks = GetMarkExtents(1u);
if (!mostRecentMarks.empty())
{
const auto& mostRecentMark = til::at(mostRecentMarks, 0);
if (!mostRecentMark.HasOutput())
{
// The most recent command mark _didn't_ have output yet. Great!
// we'll leave it alone, and just start treating text as Command or Output.
return false;
}
// The most recent command mark had output. That suggests that either:
// * shell integration wasn't enabled (but the user would still
// like lines with enters to be marked as prompts)
// * or we're in the middle of a command that's ongoing.
// If it does have a command, then we're still in the output of
// that command.
// --> the current attrs should already be set to Output.
if (mostRecentMark.HasCommand())
{
return false;
}
// If the mark doesn't have any command - then we know we're
// playing silly games with just marking whole lines as prompts,
// then immediately going to output.
// --> Below, we'll add a new mark to this row.
}
// There were no marks at all!
// --> add a new mark to this row, set all the attrs in this row
// to be Prompt, and set the current attrs to Output.
auto& row = GetMutableRowByOffset(GetCursor().GetPosition().y);
row.StartPrompt();
return true;
}
bool TextBuffer::StartCommand()
{
const auto createdMark = _createPromptMarkIfNeeded();
_currentAttributes.SetMarkAttributes(MarkKind::Command);
return createdMark;
}
bool TextBuffer::StartOutput()
{
const auto createdMark = _createPromptMarkIfNeeded();
_currentAttributes.SetMarkAttributes(MarkKind::Output);
return createdMark;
}
// Find the row above the cursor where this most recent prompt started, and set
// the exit code on that row's scroll mark.
void TextBuffer::EndCurrentCommand(std::optional<unsigned int> error)
{
_currentAttributes.SetMarkAttributes(MarkKind::None);
for (auto y = GetCursor().GetPosition().y; y >= 0; y--)
{
auto& currRow = GetMutableRowByOffset(y);
auto& rowPromptData = currRow.GetScrollbarData();
if (rowPromptData.has_value())
{
currRow.EndOutput(error);
return;
}
}
_trimMarksOutsideBuffer();
}
// Method Description:
// - Add a mark to our list of marks, and treat it as the active "prompt". For
// the sake of shell integration, we need to know which mark represents the
// current prompt/command/output. Internally, we'll always treat the _last_
// mark in the list as the current prompt.
// Arguments:
// - m: the mark to add.
void TextBuffer::StartPromptMark(const ScrollMark& m)
void TextBuffer::SetScrollbarData(ScrollbarData mark, til::CoordType y)
{
_marks.push_back(m);
auto& row = GetMutableRowByOffset(y);
row.SetScrollbarData(mark);
}
// Method Description:
// - Add a mark to our list of marks. Don't treat this as the active prompt.
// This should be used for marks created by the UI or from other user input.
// By inserting at the start of the list, we can separate out marks that were
// generated by client programs vs ones created by the user.
// Arguments:
// - m: the mark to add.
void TextBuffer::AddMark(const ScrollMark& m)
void TextBuffer::ManuallyMarkRowAsPrompt(til::CoordType y)
{
_marks.insert(_marks.begin(), m);
}
void TextBuffer::_trimMarksOutsideBuffer()
{
const til::CoordType height = _height;
std::erase_if(_marks, [height](const auto& m) {
return (m.start.y < 0) || (m.start.y >= height);
});
}
std::wstring_view TextBuffer::CurrentCommand() const
{
if (_marks.size() == 0)
auto& row = GetMutableRowByOffset(y);
for (auto& [attr, len] : row.Attributes().runs())
{
return L"";
attr.SetMarkAttributes(MarkKind::Prompt);
}
const auto& curr{ _marks.back() };
const auto& start{ curr.end };
const auto& end{ GetCursor().GetPosition() };
const auto line = start.y;
const auto& row = GetRowByOffset(line);
return row.GetText(start.x, end.x);
}
void TextBuffer::SetCurrentPromptEnd(const til::point pos) noexcept
{
if (_marks.empty())
{
return;
}
auto& curr{ _marks.back() };
curr.end = pos;
}
void TextBuffer::SetCurrentCommandEnd(const til::point pos) noexcept
{
if (_marks.empty())
{
return;
}
auto& curr{ _marks.back() };
curr.commandEnd = pos;
}
void TextBuffer::SetCurrentOutputEnd(const til::point pos, ::MarkCategory category) noexcept
{
if (_marks.empty())
{
return;
}
auto& curr{ _marks.back() };
curr.outputEnd = pos;
curr.category = category;
}

View File

@@ -49,8 +49,6 @@ filling in the last row, and updating the screen.
#pragma once
#include <vector>
#include "cursor.h"
#include "Row.hpp"
#include "TextAttribute.hpp"
@@ -60,47 +58,13 @@ filling in the last row, and updating the screen.
#include "../buffer/out/textBufferTextIterator.hpp"
struct URegularExpression;
enum class SearchFlag : unsigned int;
namespace Microsoft::Console::Render
{
class Renderer;
}
enum class MarkCategory
{
Prompt = 0,
Error = 1,
Warning = 2,
Success = 3,
Info = 4
};
struct ScrollMark
{
std::optional<til::color> color;
til::point start;
til::point end; // exclusive
std::optional<til::point> commandEnd;
std::optional<til::point> outputEnd;
MarkCategory category{ MarkCategory::Info };
// Other things we may want to think about in the future are listed in
// GH#11000
bool HasCommand() const noexcept
{
return commandEnd.has_value() && *commandEnd != end;
}
bool HasOutput() const noexcept
{
return outputEnd.has_value() && *outputEnd != *commandEnd;
}
std::pair<til::point, til::point> GetExtent() const
{
til::point realEnd{ til::coalesce_value(outputEnd, commandEnd, end) };
return std::make_pair(til::point{ start }, realEnd);
}
};
class TextBuffer final
{
public:
@@ -142,7 +106,8 @@ public:
til::point NavigateCursor(til::point position, til::CoordType distance) const;
// Text insertion functions
void Write(til::CoordType row, const TextAttribute& attributes, RowWriteState& state);
void Replace(til::CoordType row, const TextAttribute& attributes, RowWriteState& state);
void Insert(til::CoordType row, const TextAttribute& attributes, RowWriteState& state);
void FillRect(const til::rect& rect, const std::wstring_view& fill, const TextAttribute& attributes);
OutputCellIterator Write(const OutputCellIterator givenIt);
@@ -203,8 +168,8 @@ public:
Microsoft::Console::Render::Renderer& GetRenderer() noexcept;
void NotifyPaintFrame() noexcept;
void TriggerRedraw(const Microsoft::Console::Types::Viewport& viewport);
void TriggerRedrawCursor(const til::point position);
void TriggerRedrawAll();
void TriggerScroll();
void TriggerScroll(const til::point delta);
@@ -232,7 +197,7 @@ public:
size_t SpanLength(const til::point coordStart, const til::point coordEnd) const;
std::wstring GetPlainText(const til::point& start, const til::point& end) const;
std::wstring GetPlainText(til::point start, til::point end) const;
struct CopyRequest
{
@@ -329,19 +294,22 @@ public:
static void Reflow(TextBuffer& oldBuffer, TextBuffer& newBuffer, const Microsoft::Console::Types::Viewport* lastCharacterViewport = nullptr, PositionInformation* positionInfo = nullptr);
std::vector<til::point_span> SearchText(const std::wstring_view& needle, bool caseInsensitive) const;
std::vector<til::point_span> SearchText(const std::wstring_view& needle, bool caseInsensitive, til::CoordType rowBeg, til::CoordType rowEnd) const;
std::optional<std::vector<til::point_span>> SearchText(const std::wstring_view& needle, SearchFlag flags) const;
std::optional<std::vector<til::point_span>> SearchText(const std::wstring_view& needle, SearchFlag flags, til::CoordType rowBeg, til::CoordType rowEnd) const;
const std::vector<ScrollMark>& GetMarks() const noexcept;
// Mark handling
std::vector<ScrollMark> GetMarkRows() const;
std::vector<MarkExtents> GetMarkExtents(size_t limit = SIZE_T_MAX) const;
void ClearMarksInRange(const til::point start, const til::point end);
void ClearAllMarks() noexcept;
void ScrollMarks(const int delta);
void StartPromptMark(const ScrollMark& m);
void AddMark(const ScrollMark& m);
void SetCurrentPromptEnd(const til::point pos) noexcept;
void SetCurrentCommandEnd(const til::point pos) noexcept;
void SetCurrentOutputEnd(const til::point pos, ::MarkCategory category) noexcept;
std::wstring_view CurrentCommand() const;
void ClearAllMarks();
std::wstring CurrentCommand() const;
std::vector<std::wstring> Commands() const;
void StartPrompt();
bool StartCommand();
bool StartOutput();
void EndCurrentCommand(std::optional<unsigned int> error);
void SetScrollbarData(ScrollbarData mark, til::CoordType y);
void ManuallyMarkRowAsPrompt(til::CoordType y);
private:
void _reserve(til::size screenBufferSize, const TextAttribute& defaultAttributes);
@@ -366,7 +334,11 @@ private:
til::point _GetWordEndForAccessibility(const til::point target, const std::wstring_view wordDelimiters, const til::point limit) const;
til::point _GetWordEndForSelection(const til::point target, const std::wstring_view wordDelimiters) const;
void _PruneHyperlinks();
void _trimMarksOutsideBuffer();
std::wstring _commandForRow(const til::CoordType rowOffset, const til::CoordType bottomInclusive) const;
MarkExtents _scrollMarkExtentForRow(const til::CoordType rowOffset, const til::CoordType bottomInclusive) const;
bool _createPromptMarkIfNeeded();
std::tuple<til::CoordType, til::CoordType, bool> _RowCopyHelper(const CopyRequest& req, const til::CoordType iRow, const ROW& row) const;
static void _AppendRTFText(std::string& contentBuilder, const std::wstring_view& text);
@@ -439,7 +411,6 @@ private:
uint64_t _lastMutationId = 0;
Cursor _cursor;
std::vector<ScrollMark> _marks;
bool _isActiveBuffer = false;
#ifdef UNIT_TESTING

View File

@@ -589,13 +589,13 @@ namespace
TestBuffer{
{ 2, 5 }, // reduce width aggressively
{
{ L" ", true },
{ L" ", true },
{ L" ", true },
{ L" ", true },
{ L" ", false },
{ L" ", true },
{ L" ", true },
{ L" ", true },
{ L" ", true },
},
{ 1, 0 },
{ 1, 4 },
},
},
},

View File

@@ -6,6 +6,7 @@
#include "WexTestClass.h"
#include "../textBuffer.hpp"
#include "../../renderer/inc/DummyRenderer.hpp"
#include "../search.h"
template<>
class WEX::TestExecution::VerifyOutputTraits<std::vector<til::point_span>>
@@ -41,7 +42,7 @@ class UTextAdapterTests
RowWriteState state{
.text = L"abc 𝒶𝒷𝒸 abc ネコちゃん",
};
buffer.Write(0, TextAttribute{}, state);
buffer.Replace(0, TextAttribute{}, state);
VERIFY_IS_TRUE(state.text.empty());
static constexpr auto s = [](til::CoordType beg, til::CoordType end) -> til::point_span {
@@ -49,15 +50,15 @@ class UTextAdapterTests
};
auto expected = std::vector{ s(0, 2), s(8, 10) };
auto actual = buffer.SearchText(L"abc", false);
auto actual = buffer.SearchText(L"abc", SearchFlag::None);
VERIFY_ARE_EQUAL(expected, actual);
expected = std::vector{ s(5, 5) };
actual = buffer.SearchText(L"𝒷", false);
actual = buffer.SearchText(L"𝒷", SearchFlag::None);
VERIFY_ARE_EQUAL(expected, actual);
expected = std::vector{ s(12, 15) };
actual = buffer.SearchText(L"ネコ", false);
actual = buffer.SearchText(L"ネコ", SearchFlag::None);
VERIFY_ARE_EQUAL(expected, actual);
}
};

Binary file not shown.

After

Width:  |  Height:  |  Size: 433 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 804 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 758 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 819 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@@ -154,7 +154,7 @@
<comment>{Locked=qps-ploc,qps-ploca,qps-plocm}</comment>
</data>
<data name="AppDescription" xml:space="preserve">
<value>Nová Terminál Windows</value>
<value>Nový Terminál Windows</value>
</data>
<data name="AppDescriptionPre" xml:space="preserve">
<value>Terminál Windows s náhledem připravovaných funkcí</value>
@@ -164,11 +164,11 @@
<comment>This is a menu item that will be displayed in the Windows File Explorer that launches the Canary version of Windows Terminal. Please mark one of the characters to be an accelerator key.</comment>
</data>
<data name="ShellExtension_OpenInTerminalMenuItem_Preview" xml:space="preserve">
<value>Otevřít náhled &amp;aplikace Terminal</value>
<value>Otevřít &amp;náhled Terminálu</value>
<comment>This is a menu item that will be displayed in the Windows File Explorer that launches the Preview version of Windows Terminal. Please mark one of the characters to be an accelerator key.</comment>
</data>
<data name="ShellExtension_OpenInTerminalMenuItem" xml:space="preserve">
<value>Otevřít v aplikaci &amp;Terminal</value>
<value>Otevřít v &amp;Terminálu</value>
<comment>This is a menu item that will be displayed in the Windows File Explorer that launches the non-preview version of Windows Terminal. Please mark one of the characters to be an accelerator key.</comment>
</data>
</root>

View File

@@ -381,14 +381,15 @@ namespace TerminalAppLocalTests
VERIFY_IS_NOT_NULL(actionAndArgs.Args());
auto myArgs = actionAndArgs.Args().try_as<NewTabArgs>();
VERIFY_IS_NOT_NULL(myArgs);
VERIFY_IS_NOT_NULL(myArgs.TerminalArgs());
VERIFY_IS_FALSE(myArgs.TerminalArgs().Commandline().empty());
VERIFY_IS_TRUE(myArgs.TerminalArgs().StartingDirectory().empty());
VERIFY_IS_TRUE(myArgs.TerminalArgs().TabTitle().empty());
VERIFY_IS_NULL(myArgs.TerminalArgs().TabColor());
VERIFY_IS_NULL(myArgs.TerminalArgs().ProfileIndex());
VERIFY_IS_TRUE(myArgs.TerminalArgs().Profile().empty());
auto myCommand = myArgs.TerminalArgs().Commandline();
auto terminalArgs{ myArgs.ContentArgs().try_as<NewTerminalArgs>() };
VERIFY_IS_NOT_NULL(terminalArgs);
VERIFY_IS_FALSE(terminalArgs.Commandline().empty());
VERIFY_IS_TRUE(terminalArgs.StartingDirectory().empty());
VERIFY_IS_TRUE(terminalArgs.TabTitle().empty());
VERIFY_IS_NULL(terminalArgs.TabColor());
VERIFY_IS_NULL(terminalArgs.ProfileIndex());
VERIFY_IS_TRUE(terminalArgs.Profile().empty());
auto myCommand = terminalArgs.Commandline();
VERIFY_ARE_EQUAL(L"powershell.exe \"This is an arg \"", myCommand);
}
{
@@ -397,14 +398,15 @@ namespace TerminalAppLocalTests
VERIFY_IS_NOT_NULL(actionAndArgs.Args());
auto myArgs = actionAndArgs.Args().try_as<NewTabArgs>();
VERIFY_IS_NOT_NULL(myArgs);
VERIFY_IS_NOT_NULL(myArgs.TerminalArgs());
VERIFY_IS_FALSE(myArgs.TerminalArgs().Commandline().empty());
VERIFY_IS_TRUE(myArgs.TerminalArgs().StartingDirectory().empty());
VERIFY_IS_TRUE(myArgs.TerminalArgs().TabTitle().empty());
VERIFY_IS_NULL(myArgs.TerminalArgs().TabColor());
VERIFY_IS_NULL(myArgs.TerminalArgs().ProfileIndex());
VERIFY_IS_TRUE(myArgs.TerminalArgs().Profile().empty());
auto myCommand = myArgs.TerminalArgs().Commandline();
auto terminalArgs{ myArgs.ContentArgs().try_as<NewTerminalArgs>() };
VERIFY_IS_NOT_NULL(terminalArgs);
VERIFY_IS_FALSE(terminalArgs.Commandline().empty());
VERIFY_IS_TRUE(terminalArgs.StartingDirectory().empty());
VERIFY_IS_TRUE(terminalArgs.TabTitle().empty());
VERIFY_IS_NULL(terminalArgs.TabColor());
VERIFY_IS_NULL(terminalArgs.ProfileIndex());
VERIFY_IS_TRUE(terminalArgs.Profile().empty());
auto myCommand = terminalArgs.Commandline();
VERIFY_ARE_EQUAL(L"\" with spaces\"", myCommand);
}
}
@@ -421,14 +423,15 @@ namespace TerminalAppLocalTests
VERIFY_IS_NOT_NULL(actionAndArgs.Args());
auto myArgs = actionAndArgs.Args().try_as<NewTabArgs>();
VERIFY_IS_NOT_NULL(myArgs);
VERIFY_IS_NOT_NULL(myArgs.TerminalArgs());
VERIFY_IS_FALSE(myArgs.TerminalArgs().Commandline().empty());
VERIFY_IS_TRUE(myArgs.TerminalArgs().StartingDirectory().empty());
VERIFY_IS_TRUE(myArgs.TerminalArgs().TabTitle().empty());
VERIFY_IS_NULL(myArgs.TerminalArgs().TabColor());
VERIFY_IS_NULL(myArgs.TerminalArgs().ProfileIndex());
VERIFY_IS_TRUE(myArgs.TerminalArgs().Profile().empty());
auto myCommand = myArgs.TerminalArgs().Commandline();
auto terminalArgs{ myArgs.ContentArgs().try_as<NewTerminalArgs>() };
VERIFY_IS_NOT_NULL(terminalArgs);
VERIFY_IS_FALSE(terminalArgs.Commandline().empty());
VERIFY_IS_TRUE(terminalArgs.StartingDirectory().empty());
VERIFY_IS_TRUE(terminalArgs.TabTitle().empty());
VERIFY_IS_NULL(terminalArgs.TabColor());
VERIFY_IS_NULL(terminalArgs.ProfileIndex());
VERIFY_IS_TRUE(terminalArgs.Profile().empty());
auto myCommand = terminalArgs.Commandline();
VERIFY_ARE_EQUAL(L"powershell.exe \"This is an arg ; with spaces\"", myCommand);
}
}
@@ -468,14 +471,15 @@ namespace TerminalAppLocalTests
VERIFY_IS_NOT_NULL(actionAndArgs.Args());
auto myArgs = actionAndArgs.Args().try_as<NewTabArgs>();
VERIFY_IS_NOT_NULL(myArgs);
VERIFY_IS_NOT_NULL(myArgs.TerminalArgs());
VERIFY_IS_TRUE(myArgs.TerminalArgs().Commandline().empty());
VERIFY_IS_TRUE(myArgs.TerminalArgs().StartingDirectory().empty());
VERIFY_IS_TRUE(myArgs.TerminalArgs().TabTitle().empty());
VERIFY_IS_NULL(myArgs.TerminalArgs().TabColor());
VERIFY_IS_NULL(myArgs.TerminalArgs().ProfileIndex());
VERIFY_IS_TRUE(myArgs.TerminalArgs().Profile().empty());
VERIFY_IS_TRUE(myArgs.TerminalArgs().ColorScheme().empty());
auto terminalArgs{ myArgs.ContentArgs().try_as<NewTerminalArgs>() };
VERIFY_IS_NOT_NULL(terminalArgs);
VERIFY_IS_TRUE(terminalArgs.Commandline().empty());
VERIFY_IS_TRUE(terminalArgs.StartingDirectory().empty());
VERIFY_IS_TRUE(terminalArgs.TabTitle().empty());
VERIFY_IS_NULL(terminalArgs.TabColor());
VERIFY_IS_NULL(terminalArgs.ProfileIndex());
VERIFY_IS_TRUE(terminalArgs.Profile().empty());
VERIFY_IS_TRUE(terminalArgs.ColorScheme().empty());
}
{
AppCommandlineArgs appArgs{};
@@ -489,15 +493,16 @@ namespace TerminalAppLocalTests
VERIFY_IS_NOT_NULL(actionAndArgs.Args());
auto myArgs = actionAndArgs.Args().try_as<NewTabArgs>();
VERIFY_IS_NOT_NULL(myArgs);
VERIFY_IS_NOT_NULL(myArgs.TerminalArgs());
VERIFY_IS_TRUE(myArgs.TerminalArgs().Commandline().empty());
VERIFY_IS_TRUE(myArgs.TerminalArgs().StartingDirectory().empty());
VERIFY_IS_TRUE(myArgs.TerminalArgs().TabTitle().empty());
VERIFY_IS_NULL(myArgs.TerminalArgs().TabColor());
VERIFY_IS_NULL(myArgs.TerminalArgs().ProfileIndex());
VERIFY_IS_FALSE(myArgs.TerminalArgs().Profile().empty());
VERIFY_ARE_EQUAL(L"cmd", myArgs.TerminalArgs().Profile());
VERIFY_IS_TRUE(myArgs.TerminalArgs().ColorScheme().empty());
auto terminalArgs{ myArgs.ContentArgs().try_as<NewTerminalArgs>() };
VERIFY_IS_NOT_NULL(terminalArgs);
VERIFY_IS_TRUE(terminalArgs.Commandline().empty());
VERIFY_IS_TRUE(terminalArgs.StartingDirectory().empty());
VERIFY_IS_TRUE(terminalArgs.TabTitle().empty());
VERIFY_IS_NULL(terminalArgs.TabColor());
VERIFY_IS_NULL(terminalArgs.ProfileIndex());
VERIFY_IS_FALSE(terminalArgs.Profile().empty());
VERIFY_ARE_EQUAL(L"cmd", terminalArgs.Profile());
VERIFY_IS_TRUE(terminalArgs.ColorScheme().empty());
}
{
AppCommandlineArgs appArgs{};
@@ -511,15 +516,16 @@ namespace TerminalAppLocalTests
VERIFY_IS_NOT_NULL(actionAndArgs.Args());
auto myArgs = actionAndArgs.Args().try_as<NewTabArgs>();
VERIFY_IS_NOT_NULL(myArgs);
VERIFY_IS_NOT_NULL(myArgs.TerminalArgs());
VERIFY_IS_TRUE(myArgs.TerminalArgs().Commandline().empty());
VERIFY_IS_FALSE(myArgs.TerminalArgs().StartingDirectory().empty());
VERIFY_IS_TRUE(myArgs.TerminalArgs().TabTitle().empty());
VERIFY_IS_NULL(myArgs.TerminalArgs().TabColor());
VERIFY_IS_NULL(myArgs.TerminalArgs().ProfileIndex());
VERIFY_IS_TRUE(myArgs.TerminalArgs().Profile().empty());
VERIFY_ARE_EQUAL(L"c:\\Foo", myArgs.TerminalArgs().StartingDirectory());
VERIFY_IS_TRUE(myArgs.TerminalArgs().ColorScheme().empty());
auto terminalArgs{ myArgs.ContentArgs().try_as<NewTerminalArgs>() };
VERIFY_IS_NOT_NULL(terminalArgs);
VERIFY_IS_TRUE(terminalArgs.Commandline().empty());
VERIFY_IS_FALSE(terminalArgs.StartingDirectory().empty());
VERIFY_IS_TRUE(terminalArgs.TabTitle().empty());
VERIFY_IS_NULL(terminalArgs.TabColor());
VERIFY_IS_NULL(terminalArgs.ProfileIndex());
VERIFY_IS_TRUE(terminalArgs.Profile().empty());
VERIFY_ARE_EQUAL(L"c:\\Foo", terminalArgs.StartingDirectory());
VERIFY_IS_TRUE(terminalArgs.ColorScheme().empty());
}
{
AppCommandlineArgs appArgs{};
@@ -533,15 +539,16 @@ namespace TerminalAppLocalTests
VERIFY_IS_NOT_NULL(actionAndArgs.Args());
auto myArgs = actionAndArgs.Args().try_as<NewTabArgs>();
VERIFY_IS_NOT_NULL(myArgs);
VERIFY_IS_NOT_NULL(myArgs.TerminalArgs());
VERIFY_IS_FALSE(myArgs.TerminalArgs().Commandline().empty());
VERIFY_IS_TRUE(myArgs.TerminalArgs().StartingDirectory().empty());
VERIFY_IS_TRUE(myArgs.TerminalArgs().TabTitle().empty());
VERIFY_IS_NULL(myArgs.TerminalArgs().TabColor());
VERIFY_IS_NULL(myArgs.TerminalArgs().ProfileIndex());
VERIFY_IS_TRUE(myArgs.TerminalArgs().Profile().empty());
VERIFY_ARE_EQUAL(L"powershell.exe", myArgs.TerminalArgs().Commandline());
VERIFY_IS_TRUE(myArgs.TerminalArgs().ColorScheme().empty());
auto terminalArgs{ myArgs.ContentArgs().try_as<NewTerminalArgs>() };
VERIFY_IS_NOT_NULL(terminalArgs);
VERIFY_IS_FALSE(terminalArgs.Commandline().empty());
VERIFY_IS_TRUE(terminalArgs.StartingDirectory().empty());
VERIFY_IS_TRUE(terminalArgs.TabTitle().empty());
VERIFY_IS_NULL(terminalArgs.TabColor());
VERIFY_IS_NULL(terminalArgs.ProfileIndex());
VERIFY_IS_TRUE(terminalArgs.Profile().empty());
VERIFY_ARE_EQUAL(L"powershell.exe", terminalArgs.Commandline());
VERIFY_IS_TRUE(terminalArgs.ColorScheme().empty());
}
{
AppCommandlineArgs appArgs{};
@@ -555,16 +562,17 @@ namespace TerminalAppLocalTests
VERIFY_IS_NOT_NULL(actionAndArgs.Args());
auto myArgs = actionAndArgs.Args().try_as<NewTabArgs>();
VERIFY_IS_NOT_NULL(myArgs);
VERIFY_IS_NOT_NULL(myArgs.TerminalArgs());
VERIFY_IS_FALSE(myArgs.TerminalArgs().Commandline().empty());
VERIFY_IS_TRUE(myArgs.TerminalArgs().StartingDirectory().empty());
VERIFY_IS_TRUE(myArgs.TerminalArgs().TabTitle().empty());
VERIFY_IS_NULL(myArgs.TerminalArgs().TabColor());
VERIFY_IS_NULL(myArgs.TerminalArgs().ProfileIndex());
VERIFY_IS_TRUE(myArgs.TerminalArgs().Profile().empty());
auto myCommand = myArgs.TerminalArgs().Commandline();
auto terminalArgs{ myArgs.ContentArgs().try_as<NewTerminalArgs>() };
VERIFY_IS_NOT_NULL(terminalArgs);
VERIFY_IS_FALSE(terminalArgs.Commandline().empty());
VERIFY_IS_TRUE(terminalArgs.StartingDirectory().empty());
VERIFY_IS_TRUE(terminalArgs.TabTitle().empty());
VERIFY_IS_NULL(terminalArgs.TabColor());
VERIFY_IS_NULL(terminalArgs.ProfileIndex());
VERIFY_IS_TRUE(terminalArgs.Profile().empty());
auto myCommand = terminalArgs.Commandline();
VERIFY_ARE_EQUAL(L"powershell.exe \"This is an arg with spaces\"", myCommand);
VERIFY_IS_TRUE(myArgs.TerminalArgs().ColorScheme().empty());
VERIFY_IS_TRUE(terminalArgs.ColorScheme().empty());
}
{
AppCommandlineArgs appArgs{};
@@ -578,16 +586,17 @@ namespace TerminalAppLocalTests
VERIFY_IS_NOT_NULL(actionAndArgs.Args());
auto myArgs = actionAndArgs.Args().try_as<NewTabArgs>();
VERIFY_IS_NOT_NULL(myArgs);
VERIFY_IS_NOT_NULL(myArgs.TerminalArgs());
VERIFY_IS_FALSE(myArgs.TerminalArgs().Commandline().empty());
VERIFY_IS_TRUE(myArgs.TerminalArgs().StartingDirectory().empty());
VERIFY_IS_TRUE(myArgs.TerminalArgs().TabTitle().empty());
VERIFY_IS_NULL(myArgs.TerminalArgs().TabColor());
VERIFY_IS_NULL(myArgs.TerminalArgs().ProfileIndex());
VERIFY_IS_TRUE(myArgs.TerminalArgs().Profile().empty());
auto myCommand = myArgs.TerminalArgs().Commandline();
auto terminalArgs{ myArgs.ContentArgs().try_as<NewTerminalArgs>() };
VERIFY_IS_NOT_NULL(terminalArgs);
VERIFY_IS_FALSE(terminalArgs.Commandline().empty());
VERIFY_IS_TRUE(terminalArgs.StartingDirectory().empty());
VERIFY_IS_TRUE(terminalArgs.TabTitle().empty());
VERIFY_IS_NULL(terminalArgs.TabColor());
VERIFY_IS_NULL(terminalArgs.ProfileIndex());
VERIFY_IS_TRUE(terminalArgs.Profile().empty());
auto myCommand = terminalArgs.Commandline();
VERIFY_ARE_EQUAL(L"powershell.exe \"This is an arg with spaces\" another-arg \"more spaces in this one\"", myCommand);
VERIFY_IS_TRUE(myArgs.TerminalArgs().ColorScheme().empty());
VERIFY_IS_TRUE(terminalArgs.ColorScheme().empty());
}
{
AppCommandlineArgs appArgs{};
@@ -601,15 +610,16 @@ namespace TerminalAppLocalTests
VERIFY_IS_NOT_NULL(actionAndArgs.Args());
auto myArgs = actionAndArgs.Args().try_as<NewTabArgs>();
VERIFY_IS_NOT_NULL(myArgs);
VERIFY_IS_NOT_NULL(myArgs.TerminalArgs());
VERIFY_IS_TRUE(myArgs.TerminalArgs().Commandline().empty());
VERIFY_IS_TRUE(myArgs.TerminalArgs().StartingDirectory().empty());
VERIFY_IS_TRUE(myArgs.TerminalArgs().TabTitle().empty());
VERIFY_IS_NULL(myArgs.TerminalArgs().TabColor());
VERIFY_IS_NULL(myArgs.TerminalArgs().ProfileIndex());
VERIFY_IS_FALSE(myArgs.TerminalArgs().Profile().empty());
VERIFY_ARE_EQUAL(L"Windows PowerShell", myArgs.TerminalArgs().Profile());
VERIFY_IS_TRUE(myArgs.TerminalArgs().ColorScheme().empty());
auto terminalArgs{ myArgs.ContentArgs().try_as<NewTerminalArgs>() };
VERIFY_IS_NOT_NULL(terminalArgs);
VERIFY_IS_TRUE(terminalArgs.Commandline().empty());
VERIFY_IS_TRUE(terminalArgs.StartingDirectory().empty());
VERIFY_IS_TRUE(terminalArgs.TabTitle().empty());
VERIFY_IS_NULL(terminalArgs.TabColor());
VERIFY_IS_NULL(terminalArgs.ProfileIndex());
VERIFY_IS_FALSE(terminalArgs.Profile().empty());
VERIFY_ARE_EQUAL(L"Windows PowerShell", terminalArgs.Profile());
VERIFY_IS_TRUE(terminalArgs.ColorScheme().empty());
}
{
AppCommandlineArgs appArgs{};
@@ -623,14 +633,15 @@ namespace TerminalAppLocalTests
VERIFY_IS_NOT_NULL(actionAndArgs.Args());
auto myArgs = actionAndArgs.Args().try_as<NewTabArgs>();
VERIFY_IS_NOT_NULL(myArgs);
VERIFY_IS_NOT_NULL(myArgs.TerminalArgs());
VERIFY_IS_FALSE(myArgs.TerminalArgs().Commandline().empty());
VERIFY_IS_TRUE(myArgs.TerminalArgs().StartingDirectory().empty());
VERIFY_IS_TRUE(myArgs.TerminalArgs().TabTitle().empty());
VERIFY_IS_NULL(myArgs.TerminalArgs().ProfileIndex());
VERIFY_IS_TRUE(myArgs.TerminalArgs().Profile().empty());
VERIFY_ARE_EQUAL(L"wsl -d Alpine", myArgs.TerminalArgs().Commandline());
VERIFY_IS_TRUE(myArgs.TerminalArgs().ColorScheme().empty());
auto terminalArgs{ myArgs.ContentArgs().try_as<NewTerminalArgs>() };
VERIFY_IS_NOT_NULL(terminalArgs);
VERIFY_IS_FALSE(terminalArgs.Commandline().empty());
VERIFY_IS_TRUE(terminalArgs.StartingDirectory().empty());
VERIFY_IS_TRUE(terminalArgs.TabTitle().empty());
VERIFY_IS_NULL(terminalArgs.ProfileIndex());
VERIFY_IS_TRUE(terminalArgs.Profile().empty());
VERIFY_ARE_EQUAL(L"wsl -d Alpine", terminalArgs.Commandline());
VERIFY_IS_TRUE(terminalArgs.ColorScheme().empty());
}
{
AppCommandlineArgs appArgs{};
@@ -644,16 +655,17 @@ namespace TerminalAppLocalTests
VERIFY_IS_NOT_NULL(actionAndArgs.Args());
auto myArgs = actionAndArgs.Args().try_as<NewTabArgs>();
VERIFY_IS_NOT_NULL(myArgs);
VERIFY_IS_NOT_NULL(myArgs.TerminalArgs());
VERIFY_IS_FALSE(myArgs.TerminalArgs().Commandline().empty());
VERIFY_IS_TRUE(myArgs.TerminalArgs().StartingDirectory().empty());
VERIFY_IS_TRUE(myArgs.TerminalArgs().TabTitle().empty());
VERIFY_IS_NULL(myArgs.TerminalArgs().TabColor());
VERIFY_IS_NULL(myArgs.TerminalArgs().ProfileIndex());
VERIFY_IS_FALSE(myArgs.TerminalArgs().Profile().empty());
VERIFY_ARE_EQUAL(L"wsl -d Alpine", myArgs.TerminalArgs().Commandline());
VERIFY_ARE_EQUAL(L"1", myArgs.TerminalArgs().Profile());
VERIFY_IS_TRUE(myArgs.TerminalArgs().ColorScheme().empty());
auto terminalArgs{ myArgs.ContentArgs().try_as<NewTerminalArgs>() };
VERIFY_IS_NOT_NULL(terminalArgs);
VERIFY_IS_FALSE(terminalArgs.Commandline().empty());
VERIFY_IS_TRUE(terminalArgs.StartingDirectory().empty());
VERIFY_IS_TRUE(terminalArgs.TabTitle().empty());
VERIFY_IS_NULL(terminalArgs.TabColor());
VERIFY_IS_NULL(terminalArgs.ProfileIndex());
VERIFY_IS_FALSE(terminalArgs.Profile().empty());
VERIFY_ARE_EQUAL(L"wsl -d Alpine", terminalArgs.Commandline());
VERIFY_ARE_EQUAL(L"1", terminalArgs.Profile());
VERIFY_IS_TRUE(terminalArgs.ColorScheme().empty());
}
{
AppCommandlineArgs appArgs{};
@@ -669,15 +681,16 @@ namespace TerminalAppLocalTests
VERIFY_IS_NOT_NULL(actionAndArgs.Args());
auto myArgs = actionAndArgs.Args().try_as<NewTabArgs>();
VERIFY_IS_NOT_NULL(myArgs);
VERIFY_IS_NOT_NULL(myArgs.TerminalArgs());
VERIFY_IS_TRUE(myArgs.TerminalArgs().Commandline().empty());
VERIFY_IS_TRUE(myArgs.TerminalArgs().StartingDirectory().empty());
VERIFY_IS_TRUE(myArgs.TerminalArgs().TabTitle().empty());
VERIFY_IS_NOT_NULL(myArgs.TerminalArgs().TabColor());
VERIFY_ARE_EQUAL(til::color(myArgs.TerminalArgs().TabColor().Value()), expectedColor);
VERIFY_IS_NULL(myArgs.TerminalArgs().ProfileIndex());
VERIFY_IS_TRUE(myArgs.TerminalArgs().Profile().empty());
VERIFY_IS_TRUE(myArgs.TerminalArgs().ColorScheme().empty());
auto terminalArgs{ myArgs.ContentArgs().try_as<NewTerminalArgs>() };
VERIFY_IS_NOT_NULL(terminalArgs);
VERIFY_IS_TRUE(terminalArgs.Commandline().empty());
VERIFY_IS_TRUE(terminalArgs.StartingDirectory().empty());
VERIFY_IS_TRUE(terminalArgs.TabTitle().empty());
VERIFY_IS_NOT_NULL(terminalArgs.TabColor());
VERIFY_ARE_EQUAL(til::color(terminalArgs.TabColor().Value()), expectedColor);
VERIFY_IS_NULL(terminalArgs.ProfileIndex());
VERIFY_IS_TRUE(terminalArgs.Profile().empty());
VERIFY_IS_TRUE(terminalArgs.ColorScheme().empty());
}
{
AppCommandlineArgs appArgs{};
@@ -693,15 +706,16 @@ namespace TerminalAppLocalTests
VERIFY_IS_NOT_NULL(actionAndArgs.Args());
auto myArgs = actionAndArgs.Args().try_as<NewTabArgs>();
VERIFY_IS_NOT_NULL(myArgs);
VERIFY_IS_NOT_NULL(myArgs.TerminalArgs());
VERIFY_IS_TRUE(myArgs.TerminalArgs().Commandline().empty());
VERIFY_IS_TRUE(myArgs.TerminalArgs().StartingDirectory().empty());
VERIFY_IS_TRUE(myArgs.TerminalArgs().TabTitle().empty());
VERIFY_IS_NULL(myArgs.TerminalArgs().TabColor());
VERIFY_IS_NULL(myArgs.TerminalArgs().ProfileIndex());
VERIFY_IS_TRUE(myArgs.TerminalArgs().Profile().empty());
VERIFY_IS_FALSE(myArgs.TerminalArgs().ColorScheme().empty());
VERIFY_ARE_EQUAL(expectedScheme, myArgs.TerminalArgs().ColorScheme());
auto terminalArgs{ myArgs.ContentArgs().try_as<NewTerminalArgs>() };
VERIFY_IS_NOT_NULL(terminalArgs);
VERIFY_IS_TRUE(terminalArgs.Commandline().empty());
VERIFY_IS_TRUE(terminalArgs.StartingDirectory().empty());
VERIFY_IS_TRUE(terminalArgs.TabTitle().empty());
VERIFY_IS_NULL(terminalArgs.TabColor());
VERIFY_IS_NULL(terminalArgs.ProfileIndex());
VERIFY_IS_TRUE(terminalArgs.Profile().empty());
VERIFY_IS_FALSE(terminalArgs.ColorScheme().empty());
VERIFY_ARE_EQUAL(expectedScheme, terminalArgs.ColorScheme());
}
}
@@ -732,7 +746,8 @@ namespace TerminalAppLocalTests
VERIFY_IS_NOT_NULL(myArgs);
VERIFY_ARE_EQUAL(SplitDirection::Automatic, myArgs.SplitDirection());
VERIFY_ARE_EQUAL(SplitType::Manual, myArgs.SplitMode());
VERIFY_IS_NOT_NULL(myArgs.TerminalArgs());
auto terminalArgs{ myArgs.ContentArgs().try_as<NewTerminalArgs>() };
VERIFY_IS_NOT_NULL(terminalArgs);
}
{
AppCommandlineArgs appArgs{};
@@ -752,7 +767,8 @@ namespace TerminalAppLocalTests
VERIFY_IS_NOT_NULL(myArgs);
VERIFY_ARE_EQUAL(SplitDirection::Down, myArgs.SplitDirection());
VERIFY_ARE_EQUAL(SplitType::Manual, myArgs.SplitMode());
VERIFY_IS_NOT_NULL(myArgs.TerminalArgs());
auto terminalArgs{ myArgs.ContentArgs().try_as<NewTerminalArgs>() };
VERIFY_IS_NOT_NULL(terminalArgs);
}
{
AppCommandlineArgs appArgs{};
@@ -774,7 +790,8 @@ namespace TerminalAppLocalTests
VERIFY_IS_NOT_NULL(myArgs);
VERIFY_ARE_EQUAL(SplitDirection::Right, myArgs.SplitDirection());
VERIFY_ARE_EQUAL(SplitType::Manual, myArgs.SplitMode());
VERIFY_IS_NOT_NULL(myArgs.TerminalArgs());
auto terminalArgs{ myArgs.ContentArgs().try_as<NewTerminalArgs>() };
VERIFY_IS_NOT_NULL(terminalArgs);
}
{
AppCommandlineArgs appArgs{};
@@ -795,7 +812,8 @@ namespace TerminalAppLocalTests
auto myArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
VERIFY_IS_NOT_NULL(myArgs);
VERIFY_ARE_EQUAL(SplitType::Duplicate, myArgs.SplitMode());
VERIFY_IS_NOT_NULL(myArgs.TerminalArgs());
auto terminalArgs{ myArgs.ContentArgs().try_as<NewTerminalArgs>() };
VERIFY_IS_NOT_NULL(terminalArgs);
}
{
AppCommandlineArgs appArgs{};
@@ -815,16 +833,17 @@ namespace TerminalAppLocalTests
auto myArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
VERIFY_IS_NOT_NULL(myArgs);
VERIFY_ARE_EQUAL(SplitDirection::Automatic, myArgs.SplitDirection());
VERIFY_IS_NOT_NULL(myArgs.TerminalArgs());
VERIFY_IS_FALSE(myArgs.TerminalArgs().Commandline().empty());
VERIFY_IS_TRUE(myArgs.TerminalArgs().StartingDirectory().empty());
VERIFY_IS_TRUE(myArgs.TerminalArgs().TabTitle().empty());
VERIFY_IS_NULL(myArgs.TerminalArgs().TabColor());
VERIFY_IS_NULL(myArgs.TerminalArgs().ProfileIndex());
VERIFY_IS_FALSE(myArgs.TerminalArgs().Profile().empty());
VERIFY_ARE_EQUAL(L"wsl -d Alpine", myArgs.TerminalArgs().Commandline());
VERIFY_ARE_EQUAL(L"1", myArgs.TerminalArgs().Profile());
VERIFY_IS_TRUE(myArgs.TerminalArgs().ColorScheme().empty());
auto terminalArgs{ myArgs.ContentArgs().try_as<NewTerminalArgs>() };
VERIFY_IS_NOT_NULL(terminalArgs);
VERIFY_IS_FALSE(terminalArgs.Commandline().empty());
VERIFY_IS_TRUE(terminalArgs.StartingDirectory().empty());
VERIFY_IS_TRUE(terminalArgs.TabTitle().empty());
VERIFY_IS_NULL(terminalArgs.TabColor());
VERIFY_IS_NULL(terminalArgs.ProfileIndex());
VERIFY_IS_FALSE(terminalArgs.Profile().empty());
VERIFY_ARE_EQUAL(L"wsl -d Alpine", terminalArgs.Commandline());
VERIFY_ARE_EQUAL(L"1", terminalArgs.Profile());
VERIFY_IS_TRUE(terminalArgs.ColorScheme().empty());
}
{
AppCommandlineArgs appArgs{};
@@ -844,16 +863,17 @@ namespace TerminalAppLocalTests
auto myArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
VERIFY_IS_NOT_NULL(myArgs);
VERIFY_ARE_EQUAL(SplitDirection::Down, myArgs.SplitDirection());
VERIFY_IS_NOT_NULL(myArgs.TerminalArgs());
VERIFY_IS_FALSE(myArgs.TerminalArgs().Commandline().empty());
VERIFY_IS_TRUE(myArgs.TerminalArgs().StartingDirectory().empty());
VERIFY_IS_TRUE(myArgs.TerminalArgs().TabTitle().empty());
VERIFY_IS_NULL(myArgs.TerminalArgs().TabColor());
VERIFY_IS_NULL(myArgs.TerminalArgs().ProfileIndex());
VERIFY_IS_FALSE(myArgs.TerminalArgs().Profile().empty());
VERIFY_ARE_EQUAL(L"wsl -d Alpine", myArgs.TerminalArgs().Commandline());
VERIFY_ARE_EQUAL(L"1", myArgs.TerminalArgs().Profile());
VERIFY_IS_TRUE(myArgs.TerminalArgs().ColorScheme().empty());
auto terminalArgs{ myArgs.ContentArgs().try_as<NewTerminalArgs>() };
VERIFY_IS_NOT_NULL(terminalArgs);
VERIFY_IS_FALSE(terminalArgs.Commandline().empty());
VERIFY_IS_TRUE(terminalArgs.StartingDirectory().empty());
VERIFY_IS_TRUE(terminalArgs.TabTitle().empty());
VERIFY_IS_NULL(terminalArgs.TabColor());
VERIFY_IS_NULL(terminalArgs.ProfileIndex());
VERIFY_IS_FALSE(terminalArgs.Profile().empty());
VERIFY_ARE_EQUAL(L"wsl -d Alpine", terminalArgs.Commandline());
VERIFY_ARE_EQUAL(L"1", terminalArgs.Profile());
VERIFY_IS_TRUE(terminalArgs.ColorScheme().empty());
}
{
AppCommandlineArgs appArgs{};
@@ -873,16 +893,17 @@ namespace TerminalAppLocalTests
auto myArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
VERIFY_IS_NOT_NULL(myArgs);
VERIFY_ARE_EQUAL(SplitDirection::Automatic, myArgs.SplitDirection());
VERIFY_IS_NOT_NULL(myArgs.TerminalArgs());
VERIFY_IS_FALSE(myArgs.TerminalArgs().Commandline().empty());
VERIFY_IS_TRUE(myArgs.TerminalArgs().StartingDirectory().empty());
VERIFY_IS_TRUE(myArgs.TerminalArgs().TabTitle().empty());
VERIFY_IS_NULL(myArgs.TerminalArgs().TabColor());
VERIFY_IS_NULL(myArgs.TerminalArgs().ProfileIndex());
VERIFY_IS_FALSE(myArgs.TerminalArgs().Profile().empty());
VERIFY_ARE_EQUAL(L"wsl -d Alpine -H", myArgs.TerminalArgs().Commandline());
VERIFY_ARE_EQUAL(L"1", myArgs.TerminalArgs().Profile());
VERIFY_IS_TRUE(myArgs.TerminalArgs().ColorScheme().empty());
auto terminalArgs{ myArgs.ContentArgs().try_as<NewTerminalArgs>() };
VERIFY_IS_NOT_NULL(terminalArgs);
VERIFY_IS_FALSE(terminalArgs.Commandline().empty());
VERIFY_IS_TRUE(terminalArgs.StartingDirectory().empty());
VERIFY_IS_TRUE(terminalArgs.TabTitle().empty());
VERIFY_IS_NULL(terminalArgs.TabColor());
VERIFY_IS_NULL(terminalArgs.ProfileIndex());
VERIFY_IS_FALSE(terminalArgs.Profile().empty());
VERIFY_ARE_EQUAL(L"wsl -d Alpine -H", terminalArgs.Commandline());
VERIFY_ARE_EQUAL(L"1", terminalArgs.Profile());
VERIFY_IS_TRUE(terminalArgs.ColorScheme().empty());
}
}
@@ -923,13 +944,14 @@ namespace TerminalAppLocalTests
VERIFY_IS_NOT_NULL(actionAndArgs.Args());
auto myArgs = actionAndArgs.Args().try_as<NewTabArgs>();
VERIFY_IS_NOT_NULL(myArgs);
VERIFY_IS_NOT_NULL(myArgs.TerminalArgs());
VERIFY_IS_TRUE(myArgs.TerminalArgs().Commandline().empty());
VERIFY_IS_TRUE(myArgs.TerminalArgs().StartingDirectory().empty());
VERIFY_IS_TRUE(myArgs.TerminalArgs().TabTitle().empty());
VERIFY_IS_NULL(myArgs.TerminalArgs().TabColor());
VERIFY_IS_NULL(myArgs.TerminalArgs().ProfileIndex());
VERIFY_IS_TRUE(myArgs.TerminalArgs().Profile().empty());
auto terminalArgs{ myArgs.ContentArgs().try_as<NewTerminalArgs>() };
VERIFY_IS_NOT_NULL(terminalArgs);
VERIFY_IS_TRUE(terminalArgs.Commandline().empty());
VERIFY_IS_TRUE(terminalArgs.StartingDirectory().empty());
VERIFY_IS_TRUE(terminalArgs.TabTitle().empty());
VERIFY_IS_NULL(terminalArgs.TabColor());
VERIFY_IS_NULL(terminalArgs.ProfileIndex());
VERIFY_IS_TRUE(terminalArgs.Profile().empty());
}
{
AppCommandlineArgs appArgs{};
@@ -943,14 +965,15 @@ namespace TerminalAppLocalTests
VERIFY_IS_NOT_NULL(actionAndArgs.Args());
auto myArgs = actionAndArgs.Args().try_as<NewTabArgs>();
VERIFY_IS_NOT_NULL(myArgs);
VERIFY_IS_NOT_NULL(myArgs.TerminalArgs());
VERIFY_IS_TRUE(myArgs.TerminalArgs().Commandline().empty());
VERIFY_IS_TRUE(myArgs.TerminalArgs().StartingDirectory().empty());
VERIFY_IS_TRUE(myArgs.TerminalArgs().TabTitle().empty());
VERIFY_IS_NULL(myArgs.TerminalArgs().TabColor());
VERIFY_IS_NULL(myArgs.TerminalArgs().ProfileIndex());
VERIFY_IS_FALSE(myArgs.TerminalArgs().Profile().empty());
VERIFY_ARE_EQUAL(L"cmd", myArgs.TerminalArgs().Profile());
auto terminalArgs{ myArgs.ContentArgs().try_as<NewTerminalArgs>() };
VERIFY_IS_NOT_NULL(terminalArgs);
VERIFY_IS_TRUE(terminalArgs.Commandline().empty());
VERIFY_IS_TRUE(terminalArgs.StartingDirectory().empty());
VERIFY_IS_TRUE(terminalArgs.TabTitle().empty());
VERIFY_IS_NULL(terminalArgs.TabColor());
VERIFY_IS_NULL(terminalArgs.ProfileIndex());
VERIFY_IS_FALSE(terminalArgs.Profile().empty());
VERIFY_ARE_EQUAL(L"cmd", terminalArgs.Profile());
}
{
AppCommandlineArgs appArgs{};
@@ -964,14 +987,15 @@ namespace TerminalAppLocalTests
VERIFY_IS_NOT_NULL(actionAndArgs.Args());
auto myArgs = actionAndArgs.Args().try_as<NewTabArgs>();
VERIFY_IS_NOT_NULL(myArgs);
VERIFY_IS_NOT_NULL(myArgs.TerminalArgs());
VERIFY_IS_TRUE(myArgs.TerminalArgs().Commandline().empty());
VERIFY_IS_FALSE(myArgs.TerminalArgs().StartingDirectory().empty());
VERIFY_IS_TRUE(myArgs.TerminalArgs().TabTitle().empty());
VERIFY_IS_NULL(myArgs.TerminalArgs().TabColor());
VERIFY_IS_NULL(myArgs.TerminalArgs().ProfileIndex());
VERIFY_IS_TRUE(myArgs.TerminalArgs().Profile().empty());
VERIFY_ARE_EQUAL(L"c:\\Foo", myArgs.TerminalArgs().StartingDirectory());
auto terminalArgs{ myArgs.ContentArgs().try_as<NewTerminalArgs>() };
VERIFY_IS_NOT_NULL(terminalArgs);
VERIFY_IS_TRUE(terminalArgs.Commandline().empty());
VERIFY_IS_FALSE(terminalArgs.StartingDirectory().empty());
VERIFY_IS_TRUE(terminalArgs.TabTitle().empty());
VERIFY_IS_NULL(terminalArgs.TabColor());
VERIFY_IS_NULL(terminalArgs.ProfileIndex());
VERIFY_IS_TRUE(terminalArgs.Profile().empty());
VERIFY_ARE_EQUAL(L"c:\\Foo", terminalArgs.StartingDirectory());
}
{
AppCommandlineArgs appArgs{};
@@ -985,14 +1009,15 @@ namespace TerminalAppLocalTests
VERIFY_IS_NOT_NULL(actionAndArgs.Args());
auto myArgs = actionAndArgs.Args().try_as<NewTabArgs>();
VERIFY_IS_NOT_NULL(myArgs);
VERIFY_IS_NOT_NULL(myArgs.TerminalArgs());
VERIFY_IS_FALSE(myArgs.TerminalArgs().Commandline().empty());
VERIFY_IS_TRUE(myArgs.TerminalArgs().StartingDirectory().empty());
VERIFY_IS_TRUE(myArgs.TerminalArgs().TabTitle().empty());
VERIFY_IS_NULL(myArgs.TerminalArgs().TabColor());
VERIFY_IS_NULL(myArgs.TerminalArgs().ProfileIndex());
VERIFY_IS_TRUE(myArgs.TerminalArgs().Profile().empty());
VERIFY_ARE_EQUAL(L"powershell.exe", myArgs.TerminalArgs().Commandline());
auto terminalArgs{ myArgs.ContentArgs().try_as<NewTerminalArgs>() };
VERIFY_IS_NOT_NULL(terminalArgs);
VERIFY_IS_FALSE(terminalArgs.Commandline().empty());
VERIFY_IS_TRUE(terminalArgs.StartingDirectory().empty());
VERIFY_IS_TRUE(terminalArgs.TabTitle().empty());
VERIFY_IS_NULL(terminalArgs.TabColor());
VERIFY_IS_NULL(terminalArgs.ProfileIndex());
VERIFY_IS_TRUE(terminalArgs.Profile().empty());
VERIFY_ARE_EQUAL(L"powershell.exe", terminalArgs.Commandline());
}
{
AppCommandlineArgs appArgs{};
@@ -1006,14 +1031,15 @@ namespace TerminalAppLocalTests
VERIFY_IS_NOT_NULL(actionAndArgs.Args());
auto myArgs = actionAndArgs.Args().try_as<NewTabArgs>();
VERIFY_IS_NOT_NULL(myArgs);
VERIFY_IS_NOT_NULL(myArgs.TerminalArgs());
VERIFY_IS_FALSE(myArgs.TerminalArgs().Commandline().empty());
VERIFY_IS_TRUE(myArgs.TerminalArgs().StartingDirectory().empty());
VERIFY_IS_TRUE(myArgs.TerminalArgs().TabTitle().empty());
VERIFY_IS_NULL(myArgs.TerminalArgs().TabColor());
VERIFY_IS_NULL(myArgs.TerminalArgs().ProfileIndex());
VERIFY_IS_TRUE(myArgs.TerminalArgs().Profile().empty());
VERIFY_ARE_EQUAL(L"powershell.exe \"This is an arg with spaces\"", myArgs.TerminalArgs().Commandline());
auto terminalArgs{ myArgs.ContentArgs().try_as<NewTerminalArgs>() };
VERIFY_IS_NOT_NULL(terminalArgs);
VERIFY_IS_FALSE(terminalArgs.Commandline().empty());
VERIFY_IS_TRUE(terminalArgs.StartingDirectory().empty());
VERIFY_IS_TRUE(terminalArgs.TabTitle().empty());
VERIFY_IS_NULL(terminalArgs.TabColor());
VERIFY_IS_NULL(terminalArgs.ProfileIndex());
VERIFY_IS_TRUE(terminalArgs.Profile().empty());
VERIFY_ARE_EQUAL(L"powershell.exe \"This is an arg with spaces\"", terminalArgs.Commandline());
}
}
@@ -1469,32 +1495,38 @@ namespace TerminalAppLocalTests
VERIFY_ARE_EQUAL(2u, appArgs._startupActions.size());
auto actionAndArgs = appArgs._startupActions.at(0);
VERIFY_ARE_EQUAL(ShortcutAction::NewTab, actionAndArgs.Action());
VERIFY_IS_NOT_NULL(actionAndArgs.Args());
auto myArgs = actionAndArgs.Args().try_as<NewTabArgs>();
VERIFY_IS_NOT_NULL(myArgs);
VERIFY_IS_NOT_NULL(myArgs.TerminalArgs());
VERIFY_IS_TRUE(myArgs.TerminalArgs().Commandline().empty());
VERIFY_IS_TRUE(myArgs.TerminalArgs().StartingDirectory().empty());
VERIFY_IS_TRUE(myArgs.TerminalArgs().TabTitle().empty());
VERIFY_IS_NULL(myArgs.TerminalArgs().TabColor());
VERIFY_IS_NULL(myArgs.TerminalArgs().ProfileIndex());
VERIFY_IS_TRUE(myArgs.TerminalArgs().Profile().empty());
{
auto actionAndArgs = appArgs._startupActions.at(0);
VERIFY_ARE_EQUAL(ShortcutAction::NewTab, actionAndArgs.Action());
VERIFY_IS_NOT_NULL(actionAndArgs.Args());
auto myArgs = actionAndArgs.Args().try_as<NewTabArgs>();
VERIFY_IS_NOT_NULL(myArgs);
auto terminalArgs{ myArgs.ContentArgs().try_as<NewTerminalArgs>() };
VERIFY_IS_NOT_NULL(terminalArgs);
VERIFY_IS_TRUE(terminalArgs.Commandline().empty());
VERIFY_IS_TRUE(terminalArgs.StartingDirectory().empty());
VERIFY_IS_TRUE(terminalArgs.TabTitle().empty());
VERIFY_IS_NULL(terminalArgs.TabColor());
VERIFY_IS_NULL(terminalArgs.ProfileIndex());
VERIFY_IS_TRUE(terminalArgs.Profile().empty());
}
actionAndArgs = appArgs._startupActions.at(1);
VERIFY_ARE_EQUAL(ShortcutAction::NewTab, actionAndArgs.Action());
VERIFY_IS_NOT_NULL(actionAndArgs.Args());
myArgs = actionAndArgs.Args().try_as<NewTabArgs>();
VERIFY_IS_NOT_NULL(myArgs);
VERIFY_IS_NOT_NULL(myArgs.TerminalArgs());
VERIFY_IS_FALSE(myArgs.TerminalArgs().Commandline().empty());
VERIFY_IS_TRUE(myArgs.TerminalArgs().StartingDirectory().empty());
VERIFY_IS_TRUE(myArgs.TerminalArgs().TabTitle().empty());
VERIFY_IS_NULL(myArgs.TerminalArgs().TabColor());
VERIFY_IS_NULL(myArgs.TerminalArgs().ProfileIndex());
VERIFY_IS_TRUE(myArgs.TerminalArgs().Profile().empty());
VERIFY_ARE_EQUAL(L"slpit-pane", myArgs.TerminalArgs().Commandline());
{
auto actionAndArgs = appArgs._startupActions.at(1);
VERIFY_ARE_EQUAL(ShortcutAction::NewTab, actionAndArgs.Action());
VERIFY_IS_NOT_NULL(actionAndArgs.Args());
auto myArgs = actionAndArgs.Args().try_as<NewTabArgs>();
VERIFY_IS_NOT_NULL(myArgs);
auto terminalArgs{ myArgs.ContentArgs().try_as<NewTerminalArgs>() };
VERIFY_IS_NOT_NULL(terminalArgs);
VERIFY_IS_FALSE(terminalArgs.Commandline().empty());
VERIFY_IS_TRUE(terminalArgs.StartingDirectory().empty());
VERIFY_IS_TRUE(terminalArgs.TabTitle().empty());
VERIFY_IS_NULL(terminalArgs.TabColor());
VERIFY_IS_NULL(terminalArgs.ProfileIndex());
VERIFY_IS_TRUE(terminalArgs.Profile().empty());
VERIFY_ARE_EQUAL(L"slpit-pane", terminalArgs.Commandline());
}
}
{
@@ -1511,8 +1543,9 @@ namespace TerminalAppLocalTests
auto myArgs = actionAndArgs.Args().try_as<NewTabArgs>();
VERIFY_IS_NOT_NULL(myArgs);
VERIFY_IS_NOT_NULL(myArgs.TerminalArgs());
VERIFY_ARE_EQUAL(L"slpit-pane -H", myArgs.TerminalArgs().Commandline());
auto terminalArgs{ myArgs.ContentArgs().try_as<NewTerminalArgs>() };
VERIFY_IS_NOT_NULL(terminalArgs);
VERIFY_ARE_EQUAL(L"slpit-pane -H", terminalArgs.Commandline());
}
}
@@ -1530,9 +1563,10 @@ namespace TerminalAppLocalTests
VERIFY_IS_NOT_NULL(actionAndArgs.Args());
auto myArgs = actionAndArgs.Args().try_as<NewTabArgs>();
VERIFY_IS_NOT_NULL(myArgs);
VERIFY_IS_NOT_NULL(myArgs.TerminalArgs());
VERIFY_ARE_EQUAL(L"wsl -d Alpine", myArgs.TerminalArgs().Commandline());
VERIFY_ARE_EQUAL(L"C:\\", myArgs.TerminalArgs().StartingDirectory());
auto terminalArgs{ myArgs.ContentArgs().try_as<NewTerminalArgs>() };
VERIFY_IS_NOT_NULL(terminalArgs);
VERIFY_ARE_EQUAL(L"wsl -d Alpine", terminalArgs.Commandline());
VERIFY_ARE_EQUAL(L"C:\\", terminalArgs.StartingDirectory());
}
{ // two parsing terminators, new-tab command
AppCommandlineArgs appArgs{};
@@ -1546,9 +1580,10 @@ namespace TerminalAppLocalTests
VERIFY_IS_NOT_NULL(actionAndArgs.Args());
auto myArgs = actionAndArgs.Args().try_as<NewTabArgs>();
VERIFY_IS_NOT_NULL(myArgs);
VERIFY_IS_NOT_NULL(myArgs.TerminalArgs());
VERIFY_ARE_EQUAL(L"wsl -d Alpine -- sleep 10", myArgs.TerminalArgs().Commandline());
VERIFY_ARE_EQUAL(L"C:\\", myArgs.TerminalArgs().StartingDirectory());
auto terminalArgs{ myArgs.ContentArgs().try_as<NewTerminalArgs>() };
VERIFY_IS_NOT_NULL(terminalArgs);
VERIFY_ARE_EQUAL(L"wsl -d Alpine -- sleep 10", terminalArgs.Commandline());
VERIFY_ARE_EQUAL(L"C:\\", terminalArgs.StartingDirectory());
}
{ // two parsing terminators, *no* command
AppCommandlineArgs appArgs{};
@@ -1562,9 +1597,10 @@ namespace TerminalAppLocalTests
VERIFY_IS_NOT_NULL(actionAndArgs.Args());
auto myArgs = actionAndArgs.Args().try_as<NewTabArgs>();
VERIFY_IS_NOT_NULL(myArgs);
VERIFY_IS_NOT_NULL(myArgs.TerminalArgs());
VERIFY_ARE_EQUAL(L"wsl -d Alpine -- sleep 10", myArgs.TerminalArgs().Commandline());
VERIFY_ARE_EQUAL(L"C:\\", myArgs.TerminalArgs().StartingDirectory());
auto terminalArgs{ myArgs.ContentArgs().try_as<NewTerminalArgs>() };
VERIFY_IS_NOT_NULL(terminalArgs);
VERIFY_ARE_EQUAL(L"wsl -d Alpine -- sleep 10", terminalArgs.Commandline());
VERIFY_ARE_EQUAL(L"C:\\", terminalArgs.StartingDirectory());
}
}
@@ -1578,13 +1614,14 @@ namespace TerminalAppLocalTests
VERIFY_IS_NOT_NULL(actionAndArgs.Args());
auto myArgs = actionAndArgs.Args().try_as<NewTabArgs>();
VERIFY_IS_NOT_NULL(myArgs);
VERIFY_IS_NOT_NULL(myArgs.TerminalArgs());
VERIFY_IS_TRUE(myArgs.TerminalArgs().Commandline().empty());
VERIFY_IS_TRUE(myArgs.TerminalArgs().StartingDirectory().empty());
VERIFY_IS_TRUE(myArgs.TerminalArgs().TabTitle().empty());
VERIFY_IS_NULL(myArgs.TerminalArgs().TabColor());
VERIFY_IS_NULL(myArgs.TerminalArgs().ProfileIndex());
VERIFY_IS_TRUE(myArgs.TerminalArgs().Profile().empty());
auto terminalArgs{ myArgs.ContentArgs().try_as<NewTerminalArgs>() };
VERIFY_IS_NOT_NULL(terminalArgs);
VERIFY_IS_TRUE(terminalArgs.Commandline().empty());
VERIFY_IS_TRUE(terminalArgs.StartingDirectory().empty());
VERIFY_IS_TRUE(terminalArgs.TabTitle().empty());
VERIFY_IS_NULL(terminalArgs.TabColor());
VERIFY_IS_NULL(terminalArgs.ProfileIndex());
VERIFY_IS_TRUE(terminalArgs.Profile().empty());
}
void CommandlineTest::TestMultipleCommandExecuteCommandlineAction()
@@ -1598,13 +1635,14 @@ namespace TerminalAppLocalTests
VERIFY_IS_NOT_NULL(actionAndArgs.Args());
auto myArgs = actionAndArgs.Args().try_as<NewTabArgs>();
VERIFY_IS_NOT_NULL(myArgs);
VERIFY_IS_NOT_NULL(myArgs.TerminalArgs());
VERIFY_IS_TRUE(myArgs.TerminalArgs().Commandline().empty());
VERIFY_IS_TRUE(myArgs.TerminalArgs().StartingDirectory().empty());
VERIFY_IS_TRUE(myArgs.TerminalArgs().TabTitle().empty());
VERIFY_IS_NULL(myArgs.TerminalArgs().TabColor());
VERIFY_IS_NULL(myArgs.TerminalArgs().ProfileIndex());
VERIFY_IS_TRUE(myArgs.TerminalArgs().Profile().empty());
auto terminalArgs{ myArgs.ContentArgs().try_as<NewTerminalArgs>() };
VERIFY_IS_NOT_NULL(terminalArgs);
VERIFY_IS_TRUE(terminalArgs.Commandline().empty());
VERIFY_IS_TRUE(terminalArgs.StartingDirectory().empty());
VERIFY_IS_TRUE(terminalArgs.TabTitle().empty());
VERIFY_IS_NULL(terminalArgs.TabColor());
VERIFY_IS_NULL(terminalArgs.ProfileIndex());
VERIFY_IS_TRUE(terminalArgs.Profile().empty());
}
{
auto actionAndArgs = actions.at(1);
@@ -1612,13 +1650,14 @@ namespace TerminalAppLocalTests
VERIFY_IS_NOT_NULL(actionAndArgs.Args());
auto myArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
VERIFY_IS_NOT_NULL(myArgs);
VERIFY_IS_NOT_NULL(myArgs.TerminalArgs());
VERIFY_IS_TRUE(myArgs.TerminalArgs().Commandline().empty());
VERIFY_IS_TRUE(myArgs.TerminalArgs().StartingDirectory().empty());
VERIFY_IS_TRUE(myArgs.TerminalArgs().TabTitle().empty());
VERIFY_IS_NULL(myArgs.TerminalArgs().TabColor());
VERIFY_IS_NULL(myArgs.TerminalArgs().ProfileIndex());
VERIFY_IS_TRUE(myArgs.TerminalArgs().Profile().empty());
auto terminalArgs{ myArgs.ContentArgs().try_as<NewTerminalArgs>() };
VERIFY_IS_NOT_NULL(terminalArgs);
VERIFY_IS_TRUE(terminalArgs.Commandline().empty());
VERIFY_IS_TRUE(terminalArgs.StartingDirectory().empty());
VERIFY_IS_TRUE(terminalArgs.TabTitle().empty());
VERIFY_IS_NULL(terminalArgs.TabColor());
VERIFY_IS_NULL(terminalArgs.ProfileIndex());
VERIFY_IS_TRUE(terminalArgs.Profile().empty());
}
}
@@ -1739,13 +1778,14 @@ namespace TerminalAppLocalTests
VERIFY_IS_NOT_NULL(actionAndArgs.Args());
auto myArgs = actionAndArgs.Args().try_as<NewTabArgs>();
VERIFY_IS_NOT_NULL(myArgs);
VERIFY_IS_NOT_NULL(myArgs.TerminalArgs());
VERIFY_IS_TRUE(myArgs.TerminalArgs().Commandline().empty());
VERIFY_IS_TRUE(myArgs.TerminalArgs().StartingDirectory().empty());
VERIFY_IS_TRUE(myArgs.TerminalArgs().TabTitle().empty());
VERIFY_IS_TRUE(myArgs.TerminalArgs().ProfileIndex() == nullptr);
VERIFY_IS_FALSE(myArgs.TerminalArgs().Profile().empty());
VERIFY_ARE_EQUAL(L"cmd", myArgs.TerminalArgs().Profile());
auto terminalArgs{ myArgs.ContentArgs().try_as<NewTerminalArgs>() };
VERIFY_IS_NOT_NULL(terminalArgs);
VERIFY_IS_TRUE(terminalArgs.Commandline().empty());
VERIFY_IS_TRUE(terminalArgs.StartingDirectory().empty());
VERIFY_IS_TRUE(terminalArgs.TabTitle().empty());
VERIFY_IS_TRUE(terminalArgs.ProfileIndex() == nullptr);
VERIFY_IS_FALSE(terminalArgs.Profile().empty());
VERIFY_ARE_EQUAL(L"cmd", terminalArgs.Profile());
}
{
Log::Comment(NoThrowString().Format(L"Pass a launch mode and command line"));
@@ -1763,13 +1803,14 @@ namespace TerminalAppLocalTests
VERIFY_IS_NOT_NULL(actionAndArgs.Args());
auto myArgs = actionAndArgs.Args().try_as<NewTabArgs>();
VERIFY_IS_NOT_NULL(myArgs);
VERIFY_IS_NOT_NULL(myArgs.TerminalArgs());
VERIFY_IS_FALSE(myArgs.TerminalArgs().Commandline().empty());
VERIFY_IS_TRUE(myArgs.TerminalArgs().StartingDirectory().empty());
VERIFY_IS_TRUE(myArgs.TerminalArgs().TabTitle().empty());
VERIFY_IS_TRUE(myArgs.TerminalArgs().ProfileIndex() == nullptr);
VERIFY_IS_TRUE(myArgs.TerminalArgs().Profile().empty());
VERIFY_ARE_EQUAL(L"powershell.exe", myArgs.TerminalArgs().Commandline());
auto terminalArgs{ myArgs.ContentArgs().try_as<NewTerminalArgs>() };
VERIFY_IS_NOT_NULL(terminalArgs);
VERIFY_IS_FALSE(terminalArgs.Commandline().empty());
VERIFY_IS_TRUE(terminalArgs.StartingDirectory().empty());
VERIFY_IS_TRUE(terminalArgs.TabTitle().empty());
VERIFY_IS_TRUE(terminalArgs.ProfileIndex() == nullptr);
VERIFY_IS_TRUE(terminalArgs.Profile().empty());
VERIFY_ARE_EQUAL(L"powershell.exe", terminalArgs.Commandline());
}
}
@@ -1800,7 +1841,8 @@ namespace TerminalAppLocalTests
VERIFY_IS_NOT_NULL(myArgs);
VERIFY_ARE_EQUAL(SplitDirection::Automatic, myArgs.SplitDirection());
VERIFY_ARE_EQUAL(0.5f, myArgs.SplitSize());
VERIFY_IS_NOT_NULL(myArgs.TerminalArgs());
auto terminalArgs{ myArgs.ContentArgs().try_as<NewTerminalArgs>() };
VERIFY_IS_NOT_NULL(terminalArgs);
}
{
AppCommandlineArgs appArgs{};
@@ -1820,7 +1862,8 @@ namespace TerminalAppLocalTests
VERIFY_IS_NOT_NULL(myArgs);
VERIFY_ARE_EQUAL(SplitDirection::Automatic, myArgs.SplitDirection());
VERIFY_ARE_EQUAL(0.3f, myArgs.SplitSize());
VERIFY_IS_NOT_NULL(myArgs.TerminalArgs());
auto terminalArgs{ myArgs.ContentArgs().try_as<NewTerminalArgs>() };
VERIFY_IS_NOT_NULL(terminalArgs);
}
{
AppCommandlineArgs appArgs{};
@@ -1841,7 +1884,8 @@ namespace TerminalAppLocalTests
VERIFY_IS_NOT_NULL(myArgs);
VERIFY_ARE_EQUAL(SplitDirection::Automatic, myArgs.SplitDirection());
VERIFY_ARE_EQUAL(0.3f, myArgs.SplitSize());
VERIFY_IS_NOT_NULL(myArgs.TerminalArgs());
auto terminalArgs{ myArgs.ContentArgs().try_as<NewTerminalArgs>() };
VERIFY_IS_NOT_NULL(terminalArgs);
}
{
auto actionAndArgs = appArgs._startupActions.at(2);
@@ -1851,7 +1895,8 @@ namespace TerminalAppLocalTests
VERIFY_IS_NOT_NULL(myArgs);
VERIFY_ARE_EQUAL(SplitDirection::Automatic, myArgs.SplitDirection());
VERIFY_ARE_EQUAL(0.5f, myArgs.SplitSize());
VERIFY_IS_NOT_NULL(myArgs.TerminalArgs());
auto terminalArgs{ myArgs.ContentArgs().try_as<NewTerminalArgs>() };
VERIFY_IS_NOT_NULL(terminalArgs);
}
}
{
@@ -1873,7 +1918,8 @@ namespace TerminalAppLocalTests
VERIFY_IS_NOT_NULL(myArgs);
VERIFY_ARE_EQUAL(SplitDirection::Automatic, myArgs.SplitDirection());
VERIFY_ARE_EQUAL(0.3f, myArgs.SplitSize());
VERIFY_IS_NOT_NULL(myArgs.TerminalArgs());
auto terminalArgs{ myArgs.ContentArgs().try_as<NewTerminalArgs>() };
VERIFY_IS_NOT_NULL(terminalArgs);
}
{
auto actionAndArgs = appArgs._startupActions.at(2);
@@ -1883,7 +1929,8 @@ namespace TerminalAppLocalTests
VERIFY_IS_NOT_NULL(myArgs);
VERIFY_ARE_EQUAL(SplitDirection::Automatic, myArgs.SplitDirection());
VERIFY_ARE_EQUAL(0.7f, myArgs.SplitSize());
VERIFY_IS_NOT_NULL(myArgs.TerminalArgs());
auto terminalArgs{ myArgs.ContentArgs().try_as<NewTerminalArgs>() };
VERIFY_IS_NOT_NULL(terminalArgs);
}
}
}

View File

@@ -176,12 +176,13 @@ namespace TerminalAppLocalTests
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_ARE_EQUAL(SplitDirection::Automatic, realArgs.SplitDirection());
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
VERIFY_IS_TRUE(realArgs.TerminalArgs().Commandline().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().StartingDirectory().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().TabTitle().empty());
VERIFY_IS_FALSE(realArgs.TerminalArgs().Profile().empty());
VERIFY_ARE_EQUAL(L"${profile.name}", realArgs.TerminalArgs().Profile());
auto terminalArgs{ realArgs.ContentArgs().try_as<NewTerminalArgs>() };
VERIFY_IS_NOT_NULL(terminalArgs);
VERIFY_IS_TRUE(terminalArgs.Commandline().empty());
VERIFY_IS_TRUE(terminalArgs.StartingDirectory().empty());
VERIFY_IS_TRUE(terminalArgs.TabTitle().empty());
VERIFY_IS_FALSE(terminalArgs.Profile().empty());
VERIFY_ARE_EQUAL(L"${profile.name}", terminalArgs.Profile());
}
const auto& expandedCommands{ settings.GlobalSettings().ActionMap().ExpandedCommands() };
@@ -201,12 +202,13 @@ namespace TerminalAppLocalTests
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_ARE_EQUAL(SplitDirection::Automatic, realArgs.SplitDirection());
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
VERIFY_IS_TRUE(realArgs.TerminalArgs().Commandline().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().StartingDirectory().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().TabTitle().empty());
VERIFY_IS_FALSE(realArgs.TerminalArgs().Profile().empty());
VERIFY_ARE_EQUAL(L"profile0", realArgs.TerminalArgs().Profile());
auto terminalArgs{ realArgs.ContentArgs().try_as<NewTerminalArgs>() };
VERIFY_IS_NOT_NULL(terminalArgs);
VERIFY_IS_TRUE(terminalArgs.Commandline().empty());
VERIFY_IS_TRUE(terminalArgs.StartingDirectory().empty());
VERIFY_IS_TRUE(terminalArgs.TabTitle().empty());
VERIFY_IS_FALSE(terminalArgs.Profile().empty());
VERIFY_ARE_EQUAL(L"profile0", terminalArgs.Profile());
}
{
@@ -220,12 +222,13 @@ namespace TerminalAppLocalTests
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_ARE_EQUAL(SplitDirection::Automatic, realArgs.SplitDirection());
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
VERIFY_IS_TRUE(realArgs.TerminalArgs().Commandline().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().StartingDirectory().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().TabTitle().empty());
VERIFY_IS_FALSE(realArgs.TerminalArgs().Profile().empty());
VERIFY_ARE_EQUAL(L"profile1", realArgs.TerminalArgs().Profile());
auto terminalArgs{ realArgs.ContentArgs().try_as<NewTerminalArgs>() };
VERIFY_IS_NOT_NULL(terminalArgs);
VERIFY_IS_TRUE(terminalArgs.Commandline().empty());
VERIFY_IS_TRUE(terminalArgs.StartingDirectory().empty());
VERIFY_IS_TRUE(terminalArgs.TabTitle().empty());
VERIFY_IS_FALSE(terminalArgs.Profile().empty());
VERIFY_ARE_EQUAL(L"profile1", terminalArgs.Profile());
}
{
@@ -239,12 +242,13 @@ namespace TerminalAppLocalTests
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_ARE_EQUAL(SplitDirection::Automatic, realArgs.SplitDirection());
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
VERIFY_IS_TRUE(realArgs.TerminalArgs().Commandline().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().StartingDirectory().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().TabTitle().empty());
VERIFY_IS_FALSE(realArgs.TerminalArgs().Profile().empty());
VERIFY_ARE_EQUAL(L"profile2", realArgs.TerminalArgs().Profile());
auto terminalArgs{ realArgs.ContentArgs().try_as<NewTerminalArgs>() };
VERIFY_IS_NOT_NULL(terminalArgs);
VERIFY_IS_TRUE(terminalArgs.Commandline().empty());
VERIFY_IS_TRUE(terminalArgs.StartingDirectory().empty());
VERIFY_IS_TRUE(terminalArgs.TabTitle().empty());
VERIFY_IS_FALSE(terminalArgs.Profile().empty());
VERIFY_ARE_EQUAL(L"profile2", terminalArgs.Profile());
}
}
@@ -302,12 +306,13 @@ namespace TerminalAppLocalTests
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_ARE_EQUAL(SplitDirection::Automatic, realArgs.SplitDirection());
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
VERIFY_IS_TRUE(realArgs.TerminalArgs().Commandline().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().StartingDirectory().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().TabTitle().empty());
VERIFY_IS_FALSE(realArgs.TerminalArgs().Profile().empty());
VERIFY_ARE_EQUAL(L"${profile.name}", realArgs.TerminalArgs().Profile());
auto terminalArgs{ realArgs.ContentArgs().try_as<NewTerminalArgs>() };
VERIFY_IS_NOT_NULL(terminalArgs);
VERIFY_IS_TRUE(terminalArgs.Commandline().empty());
VERIFY_IS_TRUE(terminalArgs.StartingDirectory().empty());
VERIFY_IS_TRUE(terminalArgs.TabTitle().empty());
VERIFY_IS_FALSE(terminalArgs.Profile().empty());
VERIFY_ARE_EQUAL(L"${profile.name}", terminalArgs.Profile());
}
const auto& expandedCommands{ settings.GlobalSettings().ActionMap().ExpandedCommands() };
@@ -328,12 +333,13 @@ namespace TerminalAppLocalTests
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_ARE_EQUAL(SplitDirection::Automatic, realArgs.SplitDirection());
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
VERIFY_IS_TRUE(realArgs.TerminalArgs().Commandline().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().StartingDirectory().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().TabTitle().empty());
VERIFY_IS_FALSE(realArgs.TerminalArgs().Profile().empty());
VERIFY_ARE_EQUAL(L"profile0", realArgs.TerminalArgs().Profile());
auto terminalArgs{ realArgs.ContentArgs().try_as<NewTerminalArgs>() };
VERIFY_IS_NOT_NULL(terminalArgs);
VERIFY_IS_TRUE(terminalArgs.Commandline().empty());
VERIFY_IS_TRUE(terminalArgs.StartingDirectory().empty());
VERIFY_IS_TRUE(terminalArgs.TabTitle().empty());
VERIFY_IS_FALSE(terminalArgs.Profile().empty());
VERIFY_ARE_EQUAL(L"profile0", terminalArgs.Profile());
}
{
@@ -348,12 +354,13 @@ namespace TerminalAppLocalTests
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_ARE_EQUAL(SplitDirection::Automatic, realArgs.SplitDirection());
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
VERIFY_IS_TRUE(realArgs.TerminalArgs().Commandline().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().StartingDirectory().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().TabTitle().empty());
VERIFY_IS_FALSE(realArgs.TerminalArgs().Profile().empty());
VERIFY_ARE_EQUAL(L"profile1", realArgs.TerminalArgs().Profile());
auto terminalArgs{ realArgs.ContentArgs().try_as<NewTerminalArgs>() };
VERIFY_IS_NOT_NULL(terminalArgs);
VERIFY_IS_TRUE(terminalArgs.Commandline().empty());
VERIFY_IS_TRUE(terminalArgs.StartingDirectory().empty());
VERIFY_IS_TRUE(terminalArgs.TabTitle().empty());
VERIFY_IS_FALSE(terminalArgs.Profile().empty());
VERIFY_ARE_EQUAL(L"profile1", terminalArgs.Profile());
}
{
@@ -368,12 +375,13 @@ namespace TerminalAppLocalTests
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_ARE_EQUAL(SplitDirection::Automatic, realArgs.SplitDirection());
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
VERIFY_IS_TRUE(realArgs.TerminalArgs().Commandline().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().StartingDirectory().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().TabTitle().empty());
VERIFY_IS_FALSE(realArgs.TerminalArgs().Profile().empty());
VERIFY_ARE_EQUAL(L"profile2", realArgs.TerminalArgs().Profile());
auto terminalArgs{ realArgs.ContentArgs().try_as<NewTerminalArgs>() };
VERIFY_IS_NOT_NULL(terminalArgs);
VERIFY_IS_TRUE(terminalArgs.Commandline().empty());
VERIFY_IS_TRUE(terminalArgs.StartingDirectory().empty());
VERIFY_IS_TRUE(terminalArgs.TabTitle().empty());
VERIFY_IS_FALSE(terminalArgs.Profile().empty());
VERIFY_ARE_EQUAL(L"profile2", terminalArgs.Profile());
}
}
@@ -433,12 +441,13 @@ namespace TerminalAppLocalTests
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_ARE_EQUAL(SplitDirection::Automatic, realArgs.SplitDirection());
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
VERIFY_IS_TRUE(realArgs.TerminalArgs().Commandline().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().StartingDirectory().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().TabTitle().empty());
VERIFY_IS_FALSE(realArgs.TerminalArgs().Profile().empty());
VERIFY_ARE_EQUAL(L"${profile.name}", realArgs.TerminalArgs().Profile());
auto terminalArgs{ realArgs.ContentArgs().try_as<NewTerminalArgs>() };
VERIFY_IS_NOT_NULL(terminalArgs);
VERIFY_IS_TRUE(terminalArgs.Commandline().empty());
VERIFY_IS_TRUE(terminalArgs.StartingDirectory().empty());
VERIFY_IS_TRUE(terminalArgs.TabTitle().empty());
VERIFY_IS_FALSE(terminalArgs.Profile().empty());
VERIFY_ARE_EQUAL(L"${profile.name}", terminalArgs.Profile());
}
const auto& expandedCommands{ settings.GlobalSettings().ActionMap().ExpandedCommands() };
@@ -459,12 +468,13 @@ namespace TerminalAppLocalTests
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_ARE_EQUAL(SplitDirection::Automatic, realArgs.SplitDirection());
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
VERIFY_IS_TRUE(realArgs.TerminalArgs().Commandline().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().StartingDirectory().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().TabTitle().empty());
VERIFY_IS_FALSE(realArgs.TerminalArgs().Profile().empty());
VERIFY_ARE_EQUAL(L"profile0", realArgs.TerminalArgs().Profile());
auto terminalArgs{ realArgs.ContentArgs().try_as<NewTerminalArgs>() };
VERIFY_IS_NOT_NULL(terminalArgs);
VERIFY_IS_TRUE(terminalArgs.Commandline().empty());
VERIFY_IS_TRUE(terminalArgs.StartingDirectory().empty());
VERIFY_IS_TRUE(terminalArgs.TabTitle().empty());
VERIFY_IS_FALSE(terminalArgs.Profile().empty());
VERIFY_ARE_EQUAL(L"profile0", terminalArgs.Profile());
}
{
@@ -479,12 +489,13 @@ namespace TerminalAppLocalTests
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_ARE_EQUAL(SplitDirection::Automatic, realArgs.SplitDirection());
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
VERIFY_IS_TRUE(realArgs.TerminalArgs().Commandline().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().StartingDirectory().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().TabTitle().empty());
VERIFY_IS_FALSE(realArgs.TerminalArgs().Profile().empty());
VERIFY_ARE_EQUAL(L"profile1\"", realArgs.TerminalArgs().Profile());
auto terminalArgs{ realArgs.ContentArgs().try_as<NewTerminalArgs>() };
VERIFY_IS_NOT_NULL(terminalArgs);
VERIFY_IS_TRUE(terminalArgs.Commandline().empty());
VERIFY_IS_TRUE(terminalArgs.StartingDirectory().empty());
VERIFY_IS_TRUE(terminalArgs.TabTitle().empty());
VERIFY_IS_FALSE(terminalArgs.Profile().empty());
VERIFY_ARE_EQUAL(L"profile1\"", terminalArgs.Profile());
}
{
@@ -499,12 +510,13 @@ namespace TerminalAppLocalTests
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_ARE_EQUAL(SplitDirection::Automatic, realArgs.SplitDirection());
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
VERIFY_IS_TRUE(realArgs.TerminalArgs().Commandline().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().StartingDirectory().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().TabTitle().empty());
VERIFY_IS_FALSE(realArgs.TerminalArgs().Profile().empty());
VERIFY_ARE_EQUAL(L"profile2", realArgs.TerminalArgs().Profile());
auto terminalArgs{ realArgs.ContentArgs().try_as<NewTerminalArgs>() };
VERIFY_IS_NOT_NULL(terminalArgs);
VERIFY_IS_TRUE(terminalArgs.Commandline().empty());
VERIFY_IS_TRUE(terminalArgs.StartingDirectory().empty());
VERIFY_IS_TRUE(terminalArgs.TabTitle().empty());
VERIFY_IS_FALSE(terminalArgs.Profile().empty());
VERIFY_ARE_EQUAL(L"profile2", terminalArgs.Profile());
}
}
@@ -692,12 +704,13 @@ namespace TerminalAppLocalTests
const auto& realArgs = childActionAndArgs.Args().try_as<NewTabArgs>();
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
VERIFY_IS_FALSE(realArgs.TerminalArgs().Commandline().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().StartingDirectory().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().TabTitle().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().Profile().empty());
VERIFY_ARE_EQUAL(L"ssh me@first.com", realArgs.TerminalArgs().Commandline());
auto terminalArgs{ realArgs.ContentArgs().try_as<NewTerminalArgs>() };
VERIFY_IS_NOT_NULL(terminalArgs);
VERIFY_IS_FALSE(terminalArgs.Commandline().empty());
VERIFY_IS_TRUE(terminalArgs.StartingDirectory().empty());
VERIFY_IS_TRUE(terminalArgs.TabTitle().empty());
VERIFY_IS_TRUE(terminalArgs.Profile().empty());
VERIFY_ARE_EQUAL(L"ssh me@first.com", terminalArgs.Commandline());
VERIFY_IS_FALSE(child.HasNestedCommands());
}
@@ -712,12 +725,13 @@ namespace TerminalAppLocalTests
const auto& realArgs = childActionAndArgs.Args().try_as<NewTabArgs>();
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
VERIFY_IS_FALSE(realArgs.TerminalArgs().Commandline().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().StartingDirectory().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().TabTitle().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().Profile().empty());
VERIFY_ARE_EQUAL(L"ssh me@second.com", realArgs.TerminalArgs().Commandline());
auto terminalArgs{ realArgs.ContentArgs().try_as<NewTerminalArgs>() };
VERIFY_IS_NOT_NULL(terminalArgs);
VERIFY_IS_FALSE(terminalArgs.Commandline().empty());
VERIFY_IS_TRUE(terminalArgs.StartingDirectory().empty());
VERIFY_IS_TRUE(terminalArgs.TabTitle().empty());
VERIFY_IS_TRUE(terminalArgs.Profile().empty());
VERIFY_ARE_EQUAL(L"ssh me@second.com", terminalArgs.Commandline());
VERIFY_IS_FALSE(child.HasNestedCommands());
}
@@ -818,12 +832,13 @@ namespace TerminalAppLocalTests
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_ARE_EQUAL(SplitDirection::Automatic, realArgs.SplitDirection());
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
VERIFY_IS_TRUE(realArgs.TerminalArgs().Commandline().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().StartingDirectory().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().TabTitle().empty());
VERIFY_IS_FALSE(realArgs.TerminalArgs().Profile().empty());
VERIFY_ARE_EQUAL(name, realArgs.TerminalArgs().Profile());
auto terminalArgs{ realArgs.ContentArgs().try_as<NewTerminalArgs>() };
VERIFY_IS_NOT_NULL(terminalArgs);
VERIFY_IS_TRUE(terminalArgs.Commandline().empty());
VERIFY_IS_TRUE(terminalArgs.StartingDirectory().empty());
VERIFY_IS_TRUE(terminalArgs.TabTitle().empty());
VERIFY_IS_FALSE(terminalArgs.Profile().empty());
VERIFY_ARE_EQUAL(name, terminalArgs.Profile());
VERIFY_IS_FALSE(childCommand.HasNestedCommands());
}
@@ -839,12 +854,13 @@ namespace TerminalAppLocalTests
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_ARE_EQUAL(SplitDirection::Down, realArgs.SplitDirection());
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
VERIFY_IS_TRUE(realArgs.TerminalArgs().Commandline().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().StartingDirectory().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().TabTitle().empty());
VERIFY_IS_FALSE(realArgs.TerminalArgs().Profile().empty());
VERIFY_ARE_EQUAL(name, realArgs.TerminalArgs().Profile());
auto terminalArgs{ realArgs.ContentArgs().try_as<NewTerminalArgs>() };
VERIFY_IS_NOT_NULL(terminalArgs);
VERIFY_IS_TRUE(terminalArgs.Commandline().empty());
VERIFY_IS_TRUE(terminalArgs.StartingDirectory().empty());
VERIFY_IS_TRUE(terminalArgs.TabTitle().empty());
VERIFY_IS_FALSE(terminalArgs.Profile().empty());
VERIFY_ARE_EQUAL(name, terminalArgs.Profile());
VERIFY_IS_FALSE(childCommand.HasNestedCommands());
}
@@ -860,12 +876,13 @@ namespace TerminalAppLocalTests
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_ARE_EQUAL(SplitDirection::Right, realArgs.SplitDirection());
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
VERIFY_IS_TRUE(realArgs.TerminalArgs().Commandline().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().StartingDirectory().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().TabTitle().empty());
VERIFY_IS_FALSE(realArgs.TerminalArgs().Profile().empty());
VERIFY_ARE_EQUAL(name, realArgs.TerminalArgs().Profile());
auto terminalArgs{ realArgs.ContentArgs().try_as<NewTerminalArgs>() };
VERIFY_IS_NOT_NULL(terminalArgs);
VERIFY_IS_TRUE(terminalArgs.Commandline().empty());
VERIFY_IS_TRUE(terminalArgs.StartingDirectory().empty());
VERIFY_IS_TRUE(terminalArgs.TabTitle().empty());
VERIFY_IS_FALSE(terminalArgs.Profile().empty());
VERIFY_ARE_EQUAL(name, terminalArgs.Profile());
VERIFY_IS_FALSE(childCommand.HasNestedCommands());
}
@@ -951,12 +968,13 @@ namespace TerminalAppLocalTests
const auto& realArgs = actionAndArgs.Args().try_as<NewTabArgs>();
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
VERIFY_IS_TRUE(realArgs.TerminalArgs().Commandline().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().StartingDirectory().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().TabTitle().empty());
VERIFY_IS_FALSE(realArgs.TerminalArgs().Profile().empty());
VERIFY_ARE_EQUAL(name, realArgs.TerminalArgs().Profile());
auto terminalArgs{ realArgs.ContentArgs().try_as<NewTerminalArgs>() };
VERIFY_IS_NOT_NULL(terminalArgs);
VERIFY_IS_TRUE(terminalArgs.Commandline().empty());
VERIFY_IS_TRUE(terminalArgs.StartingDirectory().empty());
VERIFY_IS_TRUE(terminalArgs.TabTitle().empty());
VERIFY_IS_FALSE(terminalArgs.Profile().empty());
VERIFY_ARE_EQUAL(name, terminalArgs.Profile());
VERIFY_IS_FALSE(command.HasNestedCommands());
}
@@ -1069,12 +1087,13 @@ namespace TerminalAppLocalTests
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_ARE_EQUAL(SplitDirection::Automatic, realArgs.SplitDirection());
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
VERIFY_IS_TRUE(realArgs.TerminalArgs().Commandline().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().StartingDirectory().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().TabTitle().empty());
VERIFY_IS_FALSE(realArgs.TerminalArgs().Profile().empty());
VERIFY_ARE_EQUAL(name, realArgs.TerminalArgs().Profile());
auto terminalArgs{ realArgs.ContentArgs().try_as<NewTerminalArgs>() };
VERIFY_IS_NOT_NULL(terminalArgs);
VERIFY_IS_TRUE(terminalArgs.Commandline().empty());
VERIFY_IS_TRUE(terminalArgs.StartingDirectory().empty());
VERIFY_IS_TRUE(terminalArgs.TabTitle().empty());
VERIFY_IS_FALSE(terminalArgs.Profile().empty());
VERIFY_ARE_EQUAL(name, terminalArgs.Profile());
VERIFY_IS_FALSE(childCommand.HasNestedCommands());
}
@@ -1090,12 +1109,13 @@ namespace TerminalAppLocalTests
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_ARE_EQUAL(SplitDirection::Down, realArgs.SplitDirection());
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
VERIFY_IS_TRUE(realArgs.TerminalArgs().Commandline().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().StartingDirectory().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().TabTitle().empty());
VERIFY_IS_FALSE(realArgs.TerminalArgs().Profile().empty());
VERIFY_ARE_EQUAL(name, realArgs.TerminalArgs().Profile());
auto terminalArgs{ realArgs.ContentArgs().try_as<NewTerminalArgs>() };
VERIFY_IS_NOT_NULL(terminalArgs);
VERIFY_IS_TRUE(terminalArgs.Commandline().empty());
VERIFY_IS_TRUE(terminalArgs.StartingDirectory().empty());
VERIFY_IS_TRUE(terminalArgs.TabTitle().empty());
VERIFY_IS_FALSE(terminalArgs.Profile().empty());
VERIFY_ARE_EQUAL(name, terminalArgs.Profile());
VERIFY_IS_FALSE(childCommand.HasNestedCommands());
}
@@ -1111,12 +1131,13 @@ namespace TerminalAppLocalTests
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_ARE_EQUAL(SplitDirection::Right, realArgs.SplitDirection());
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
VERIFY_IS_TRUE(realArgs.TerminalArgs().Commandline().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().StartingDirectory().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().TabTitle().empty());
VERIFY_IS_FALSE(realArgs.TerminalArgs().Profile().empty());
VERIFY_ARE_EQUAL(name, realArgs.TerminalArgs().Profile());
auto terminalArgs{ realArgs.ContentArgs().try_as<NewTerminalArgs>() };
VERIFY_IS_NOT_NULL(terminalArgs);
VERIFY_IS_TRUE(terminalArgs.Commandline().empty());
VERIFY_IS_TRUE(terminalArgs.StartingDirectory().empty());
VERIFY_IS_TRUE(terminalArgs.TabTitle().empty());
VERIFY_IS_FALSE(terminalArgs.Profile().empty());
VERIFY_ARE_EQUAL(name, terminalArgs.Profile());
VERIFY_IS_FALSE(childCommand.HasNestedCommands());
}
@@ -1245,12 +1266,13 @@ namespace TerminalAppLocalTests
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_ARE_EQUAL(SplitDirection::Automatic, realArgs.SplitDirection());
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
VERIFY_IS_TRUE(realArgs.TerminalArgs().Commandline().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().StartingDirectory().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().TabTitle().empty());
VERIFY_IS_FALSE(realArgs.TerminalArgs().Profile().empty());
VERIFY_ARE_EQUAL(L"${scheme.name}", realArgs.TerminalArgs().Profile());
auto terminalArgs{ realArgs.ContentArgs().try_as<NewTerminalArgs>() };
VERIFY_IS_NOT_NULL(terminalArgs);
VERIFY_IS_TRUE(terminalArgs.Commandline().empty());
VERIFY_IS_TRUE(terminalArgs.StartingDirectory().empty());
VERIFY_IS_TRUE(terminalArgs.TabTitle().empty());
VERIFY_IS_FALSE(terminalArgs.Profile().empty());
VERIFY_ARE_EQUAL(L"${scheme.name}", terminalArgs.Profile());
}
const auto& expandedCommands{ settings.GlobalSettings().ActionMap().ExpandedCommands() };
@@ -1274,12 +1296,13 @@ namespace TerminalAppLocalTests
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_ARE_EQUAL(SplitDirection::Automatic, realArgs.SplitDirection());
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
VERIFY_IS_TRUE(realArgs.TerminalArgs().Commandline().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().StartingDirectory().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().TabTitle().empty());
VERIFY_IS_FALSE(realArgs.TerminalArgs().Profile().empty());
VERIFY_ARE_EQUAL(L"Campbell", realArgs.TerminalArgs().Profile());
auto terminalArgs{ realArgs.ContentArgs().try_as<NewTerminalArgs>() };
VERIFY_IS_NOT_NULL(terminalArgs);
VERIFY_IS_TRUE(terminalArgs.Commandline().empty());
VERIFY_IS_TRUE(terminalArgs.StartingDirectory().empty());
VERIFY_IS_TRUE(terminalArgs.TabTitle().empty());
VERIFY_IS_FALSE(terminalArgs.Profile().empty());
VERIFY_ARE_EQUAL(L"Campbell", terminalArgs.Profile());
}
{
@@ -1294,12 +1317,13 @@ namespace TerminalAppLocalTests
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_ARE_EQUAL(SplitDirection::Automatic, realArgs.SplitDirection());
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
VERIFY_IS_TRUE(realArgs.TerminalArgs().Commandline().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().StartingDirectory().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().TabTitle().empty());
VERIFY_IS_FALSE(realArgs.TerminalArgs().Profile().empty());
VERIFY_ARE_EQUAL(L"Campbell PowerShell", realArgs.TerminalArgs().Profile());
auto terminalArgs{ realArgs.ContentArgs().try_as<NewTerminalArgs>() };
VERIFY_IS_NOT_NULL(terminalArgs);
VERIFY_IS_TRUE(terminalArgs.Commandline().empty());
VERIFY_IS_TRUE(terminalArgs.StartingDirectory().empty());
VERIFY_IS_TRUE(terminalArgs.TabTitle().empty());
VERIFY_IS_FALSE(terminalArgs.Profile().empty());
VERIFY_ARE_EQUAL(L"Campbell PowerShell", terminalArgs.Profile());
}
{
@@ -1314,12 +1338,13 @@ namespace TerminalAppLocalTests
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_ARE_EQUAL(SplitDirection::Automatic, realArgs.SplitDirection());
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
VERIFY_IS_TRUE(realArgs.TerminalArgs().Commandline().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().StartingDirectory().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().TabTitle().empty());
VERIFY_IS_FALSE(realArgs.TerminalArgs().Profile().empty());
VERIFY_ARE_EQUAL(L"Vintage", realArgs.TerminalArgs().Profile());
auto terminalArgs{ realArgs.ContentArgs().try_as<NewTerminalArgs>() };
VERIFY_IS_NOT_NULL(terminalArgs);
VERIFY_IS_TRUE(terminalArgs.Commandline().empty());
VERIFY_IS_TRUE(terminalArgs.StartingDirectory().empty());
VERIFY_IS_TRUE(terminalArgs.TabTitle().empty());
VERIFY_IS_FALSE(terminalArgs.Profile().empty());
VERIFY_ARE_EQUAL(L"Vintage", terminalArgs.Profile());
}
}
@@ -1385,15 +1410,16 @@ namespace TerminalAppLocalTests
const auto& realArgs = actionAndArgs.Args().try_as<NewTabArgs>();
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
VERIFY_IS_TRUE(realArgs.TerminalArgs().Commandline().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().StartingDirectory().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().TabTitle().empty());
VERIFY_IS_FALSE(realArgs.TerminalArgs().Profile().empty());
VERIFY_ARE_EQUAL(L"profile0", realArgs.TerminalArgs().Profile());
VERIFY_IS_NULL(realArgs.TerminalArgs().Elevate());
auto terminalArgs{ realArgs.ContentArgs().try_as<NewTerminalArgs>() };
VERIFY_IS_NOT_NULL(terminalArgs);
VERIFY_IS_TRUE(terminalArgs.Commandline().empty());
VERIFY_IS_TRUE(terminalArgs.StartingDirectory().empty());
VERIFY_IS_TRUE(terminalArgs.TabTitle().empty());
VERIFY_IS_FALSE(terminalArgs.Profile().empty());
VERIFY_ARE_EQUAL(L"profile0", terminalArgs.Profile());
VERIFY_IS_NULL(terminalArgs.Elevate());
const auto termSettingsResult = TerminalSettings::CreateWithNewTerminalArgs(settings, realArgs.TerminalArgs(), nullptr);
const auto termSettingsResult = TerminalSettings::CreateWithNewTerminalArgs(settings, terminalArgs, nullptr);
const auto termSettings = termSettingsResult.DefaultSettings();
VERIFY_ARE_EQUAL(L"cmd.exe", termSettings.Commandline());
VERIFY_ARE_EQUAL(false, termSettings.Elevate());
@@ -1407,15 +1433,16 @@ namespace TerminalAppLocalTests
const auto& realArgs = actionAndArgs.Args().try_as<NewTabArgs>();
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
VERIFY_IS_TRUE(realArgs.TerminalArgs().Commandline().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().StartingDirectory().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().TabTitle().empty());
VERIFY_IS_FALSE(realArgs.TerminalArgs().Profile().empty());
VERIFY_ARE_EQUAL(L"profile1", realArgs.TerminalArgs().Profile());
VERIFY_IS_NULL(realArgs.TerminalArgs().Elevate());
auto terminalArgs{ realArgs.ContentArgs().try_as<NewTerminalArgs>() };
VERIFY_IS_NOT_NULL(terminalArgs);
VERIFY_IS_TRUE(terminalArgs.Commandline().empty());
VERIFY_IS_TRUE(terminalArgs.StartingDirectory().empty());
VERIFY_IS_TRUE(terminalArgs.TabTitle().empty());
VERIFY_IS_FALSE(terminalArgs.Profile().empty());
VERIFY_ARE_EQUAL(L"profile1", terminalArgs.Profile());
VERIFY_IS_NULL(terminalArgs.Elevate());
const auto termSettingsResult = TerminalSettings::CreateWithNewTerminalArgs(settings, realArgs.TerminalArgs(), nullptr);
const auto termSettingsResult = TerminalSettings::CreateWithNewTerminalArgs(settings, terminalArgs, nullptr);
const auto termSettings = termSettingsResult.DefaultSettings();
VERIFY_ARE_EQUAL(L"pwsh.exe", termSettings.Commandline());
VERIFY_ARE_EQUAL(true, termSettings.Elevate());
@@ -1429,15 +1456,16 @@ namespace TerminalAppLocalTests
const auto& realArgs = actionAndArgs.Args().try_as<NewTabArgs>();
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
VERIFY_IS_TRUE(realArgs.TerminalArgs().Commandline().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().StartingDirectory().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().TabTitle().empty());
VERIFY_IS_FALSE(realArgs.TerminalArgs().Profile().empty());
VERIFY_ARE_EQUAL(L"profile2", realArgs.TerminalArgs().Profile());
VERIFY_IS_NULL(realArgs.TerminalArgs().Elevate());
auto terminalArgs{ realArgs.ContentArgs().try_as<NewTerminalArgs>() };
VERIFY_IS_NOT_NULL(terminalArgs);
VERIFY_IS_TRUE(terminalArgs.Commandline().empty());
VERIFY_IS_TRUE(terminalArgs.StartingDirectory().empty());
VERIFY_IS_TRUE(terminalArgs.TabTitle().empty());
VERIFY_IS_FALSE(terminalArgs.Profile().empty());
VERIFY_ARE_EQUAL(L"profile2", terminalArgs.Profile());
VERIFY_IS_NULL(terminalArgs.Elevate());
const auto termSettingsResult = TerminalSettings::CreateWithNewTerminalArgs(settings, realArgs.TerminalArgs(), nullptr);
const auto termSettingsResult = TerminalSettings::CreateWithNewTerminalArgs(settings, terminalArgs, nullptr);
const auto termSettings = termSettingsResult.DefaultSettings();
VERIFY_ARE_EQUAL(L"wsl.exe", termSettings.Commandline());
VERIFY_ARE_EQUAL(false, termSettings.Elevate());
@@ -1452,16 +1480,17 @@ namespace TerminalAppLocalTests
const auto& realArgs = actionAndArgs.Args().try_as<NewTabArgs>();
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
VERIFY_IS_TRUE(realArgs.TerminalArgs().Commandline().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().StartingDirectory().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().TabTitle().empty());
VERIFY_IS_FALSE(realArgs.TerminalArgs().Profile().empty());
VERIFY_ARE_EQUAL(L"profile0", realArgs.TerminalArgs().Profile());
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs().Elevate());
VERIFY_IS_FALSE(realArgs.TerminalArgs().Elevate().Value());
auto terminalArgs{ realArgs.ContentArgs().try_as<NewTerminalArgs>() };
VERIFY_IS_NOT_NULL(terminalArgs);
VERIFY_IS_TRUE(terminalArgs.Commandline().empty());
VERIFY_IS_TRUE(terminalArgs.StartingDirectory().empty());
VERIFY_IS_TRUE(terminalArgs.TabTitle().empty());
VERIFY_IS_FALSE(terminalArgs.Profile().empty());
VERIFY_ARE_EQUAL(L"profile0", terminalArgs.Profile());
VERIFY_IS_NOT_NULL(terminalArgs.Elevate());
VERIFY_IS_FALSE(terminalArgs.Elevate().Value());
const auto termSettingsResult = TerminalSettings::CreateWithNewTerminalArgs(settings, realArgs.TerminalArgs(), nullptr);
const auto termSettingsResult = TerminalSettings::CreateWithNewTerminalArgs(settings, terminalArgs, nullptr);
const auto termSettings = termSettingsResult.DefaultSettings();
VERIFY_ARE_EQUAL(L"cmd.exe", termSettings.Commandline());
VERIFY_ARE_EQUAL(false, termSettings.Elevate());
@@ -1475,16 +1504,17 @@ namespace TerminalAppLocalTests
const auto& realArgs = actionAndArgs.Args().try_as<NewTabArgs>();
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
VERIFY_IS_TRUE(realArgs.TerminalArgs().Commandline().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().StartingDirectory().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().TabTitle().empty());
VERIFY_IS_FALSE(realArgs.TerminalArgs().Profile().empty());
VERIFY_ARE_EQUAL(L"profile1", realArgs.TerminalArgs().Profile());
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs().Elevate());
VERIFY_IS_FALSE(realArgs.TerminalArgs().Elevate().Value());
auto terminalArgs{ realArgs.ContentArgs().try_as<NewTerminalArgs>() };
VERIFY_IS_NOT_NULL(terminalArgs);
VERIFY_IS_TRUE(terminalArgs.Commandline().empty());
VERIFY_IS_TRUE(terminalArgs.StartingDirectory().empty());
VERIFY_IS_TRUE(terminalArgs.TabTitle().empty());
VERIFY_IS_FALSE(terminalArgs.Profile().empty());
VERIFY_ARE_EQUAL(L"profile1", terminalArgs.Profile());
VERIFY_IS_NOT_NULL(terminalArgs.Elevate());
VERIFY_IS_FALSE(terminalArgs.Elevate().Value());
const auto termSettingsResult = TerminalSettings::CreateWithNewTerminalArgs(settings, realArgs.TerminalArgs(), nullptr);
const auto termSettingsResult = TerminalSettings::CreateWithNewTerminalArgs(settings, terminalArgs, nullptr);
const auto termSettings = termSettingsResult.DefaultSettings();
VERIFY_ARE_EQUAL(L"pwsh.exe", termSettings.Commandline());
VERIFY_ARE_EQUAL(false, termSettings.Elevate());
@@ -1498,16 +1528,17 @@ namespace TerminalAppLocalTests
const auto& realArgs = actionAndArgs.Args().try_as<NewTabArgs>();
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
VERIFY_IS_TRUE(realArgs.TerminalArgs().Commandline().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().StartingDirectory().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().TabTitle().empty());
VERIFY_IS_FALSE(realArgs.TerminalArgs().Profile().empty());
VERIFY_ARE_EQUAL(L"profile2", realArgs.TerminalArgs().Profile());
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs().Elevate());
VERIFY_IS_FALSE(realArgs.TerminalArgs().Elevate().Value());
auto terminalArgs{ realArgs.ContentArgs().try_as<NewTerminalArgs>() };
VERIFY_IS_NOT_NULL(terminalArgs);
VERIFY_IS_TRUE(terminalArgs.Commandline().empty());
VERIFY_IS_TRUE(terminalArgs.StartingDirectory().empty());
VERIFY_IS_TRUE(terminalArgs.TabTitle().empty());
VERIFY_IS_FALSE(terminalArgs.Profile().empty());
VERIFY_ARE_EQUAL(L"profile2", terminalArgs.Profile());
VERIFY_IS_NOT_NULL(terminalArgs.Elevate());
VERIFY_IS_FALSE(terminalArgs.Elevate().Value());
const auto termSettingsResult = TerminalSettings::CreateWithNewTerminalArgs(settings, realArgs.TerminalArgs(), nullptr);
const auto termSettingsResult = TerminalSettings::CreateWithNewTerminalArgs(settings, terminalArgs, nullptr);
const auto termSettings = termSettingsResult.DefaultSettings();
VERIFY_ARE_EQUAL(L"wsl.exe", termSettings.Commandline());
VERIFY_ARE_EQUAL(false, termSettings.Elevate());
@@ -1522,16 +1553,17 @@ namespace TerminalAppLocalTests
const auto& realArgs = actionAndArgs.Args().try_as<NewTabArgs>();
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
VERIFY_IS_TRUE(realArgs.TerminalArgs().Commandline().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().StartingDirectory().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().TabTitle().empty());
VERIFY_IS_FALSE(realArgs.TerminalArgs().Profile().empty());
VERIFY_ARE_EQUAL(L"profile0", realArgs.TerminalArgs().Profile());
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs().Elevate());
VERIFY_IS_TRUE(realArgs.TerminalArgs().Elevate().Value());
auto terminalArgs{ realArgs.ContentArgs().try_as<NewTerminalArgs>() };
VERIFY_IS_NOT_NULL(terminalArgs);
VERIFY_IS_TRUE(terminalArgs.Commandline().empty());
VERIFY_IS_TRUE(terminalArgs.StartingDirectory().empty());
VERIFY_IS_TRUE(terminalArgs.TabTitle().empty());
VERIFY_IS_FALSE(terminalArgs.Profile().empty());
VERIFY_ARE_EQUAL(L"profile0", terminalArgs.Profile());
VERIFY_IS_NOT_NULL(terminalArgs.Elevate());
VERIFY_IS_TRUE(terminalArgs.Elevate().Value());
const auto termSettingsResult = TerminalSettings::CreateWithNewTerminalArgs(settings, realArgs.TerminalArgs(), nullptr);
const auto termSettingsResult = TerminalSettings::CreateWithNewTerminalArgs(settings, terminalArgs, nullptr);
const auto termSettings = termSettingsResult.DefaultSettings();
VERIFY_ARE_EQUAL(L"cmd.exe", termSettings.Commandline());
VERIFY_ARE_EQUAL(true, termSettings.Elevate());
@@ -1544,16 +1576,17 @@ namespace TerminalAppLocalTests
const auto& realArgs = actionAndArgs.Args().try_as<NewTabArgs>();
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
VERIFY_IS_TRUE(realArgs.TerminalArgs().Commandline().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().StartingDirectory().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().TabTitle().empty());
VERIFY_IS_FALSE(realArgs.TerminalArgs().Profile().empty());
VERIFY_ARE_EQUAL(L"profile1", realArgs.TerminalArgs().Profile());
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs().Elevate());
VERIFY_IS_TRUE(realArgs.TerminalArgs().Elevate().Value());
auto terminalArgs{ realArgs.ContentArgs().try_as<NewTerminalArgs>() };
VERIFY_IS_NOT_NULL(terminalArgs);
VERIFY_IS_TRUE(terminalArgs.Commandline().empty());
VERIFY_IS_TRUE(terminalArgs.StartingDirectory().empty());
VERIFY_IS_TRUE(terminalArgs.TabTitle().empty());
VERIFY_IS_FALSE(terminalArgs.Profile().empty());
VERIFY_ARE_EQUAL(L"profile1", terminalArgs.Profile());
VERIFY_IS_NOT_NULL(terminalArgs.Elevate());
VERIFY_IS_TRUE(terminalArgs.Elevate().Value());
const auto termSettingsResult = TerminalSettings::CreateWithNewTerminalArgs(settings, realArgs.TerminalArgs(), nullptr);
const auto termSettingsResult = TerminalSettings::CreateWithNewTerminalArgs(settings, terminalArgs, nullptr);
const auto termSettings = termSettingsResult.DefaultSettings();
VERIFY_ARE_EQUAL(L"pwsh.exe", termSettings.Commandline());
VERIFY_ARE_EQUAL(true, termSettings.Elevate());
@@ -1567,16 +1600,17 @@ namespace TerminalAppLocalTests
const auto& realArgs = actionAndArgs.Args().try_as<NewTabArgs>();
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
VERIFY_IS_TRUE(realArgs.TerminalArgs().Commandline().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().StartingDirectory().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().TabTitle().empty());
VERIFY_IS_FALSE(realArgs.TerminalArgs().Profile().empty());
VERIFY_ARE_EQUAL(L"profile2", realArgs.TerminalArgs().Profile());
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs().Elevate());
VERIFY_IS_TRUE(realArgs.TerminalArgs().Elevate().Value());
auto terminalArgs{ realArgs.ContentArgs().try_as<NewTerminalArgs>() };
VERIFY_IS_NOT_NULL(terminalArgs);
VERIFY_IS_TRUE(terminalArgs.Commandline().empty());
VERIFY_IS_TRUE(terminalArgs.StartingDirectory().empty());
VERIFY_IS_TRUE(terminalArgs.TabTitle().empty());
VERIFY_IS_FALSE(terminalArgs.Profile().empty());
VERIFY_ARE_EQUAL(L"profile2", terminalArgs.Profile());
VERIFY_IS_NOT_NULL(terminalArgs.Elevate());
VERIFY_IS_TRUE(terminalArgs.Elevate().Value());
const auto termSettingsResult = TerminalSettings::CreateWithNewTerminalArgs(settings, realArgs.TerminalArgs(), nullptr);
const auto termSettingsResult = TerminalSettings::CreateWithNewTerminalArgs(settings, terminalArgs, nullptr);
const auto termSettings = termSettingsResult.DefaultSettings();
VERIFY_ARE_EQUAL(L"wsl.exe", termSettings.Commandline());
VERIFY_ARE_EQUAL(true, termSettings.Elevate());

View File

@@ -96,7 +96,6 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
peasant.ShowNotificationIconRequested([this](auto&&, auto&&) { ShowNotificationIconRequested.raise(*this, nullptr); });
peasant.HideNotificationIconRequested([this](auto&&, auto&&) { HideNotificationIconRequested.raise(*this, nullptr); });
peasant.QuitAllRequested({ this, &Monarch::_handleQuitAll });
{
std::unique_lock lock{ _peasantsMutex };
@@ -134,7 +133,7 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
// - <none> used
// Return Value:
// - <none>
void Monarch::_handleQuitAll(const winrt::Windows::Foundation::IInspectable& /*sender*/, const winrt::Windows::Foundation::IInspectable& /*args*/)
void Monarch::QuitAll()
{
if (_quitting.exchange(true, std::memory_order_relaxed))
{
@@ -166,12 +165,6 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
{
peasantSearch->second.Quit();
}
else
{
// Somehow we don't have our own peasant, this should never happen.
// We are trying to quit anyways so just fail here.
assert(peasantSearch != _peasants.end());
}
}
}

View File

@@ -86,6 +86,7 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
uint64_t AddPeasant(winrt::Microsoft::Terminal::Remoting::IPeasant peasant);
void SignalClose(const uint64_t peasantId);
void QuitAll();
uint64_t GetNumberOfPeasants();

View File

@@ -63,6 +63,7 @@ namespace Microsoft.Terminal.Remoting
void HandleActivatePeasant(WindowActivatedArgs args);
void SummonWindow(SummonWindowSelectionArgs args);
void SignalClose(UInt64 peasantId);
void QuitAll();
void SummonAllWindows();
Boolean DoesQuakeWindowExist();

View File

@@ -260,22 +260,6 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
TraceLoggingKeyword(TIL_KEYWORD_TRACE));
}
void Peasant::RequestQuitAll()
{
try
{
QuitAllRequested.raise(*this, nullptr);
}
catch (...)
{
LOG_CAUGHT_EXCEPTION();
}
TraceLoggingWrite(g_hRemotingProvider,
"Peasant_RequestQuit",
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
TraceLoggingKeyword(TIL_KEYWORD_TRACE));
}
void Peasant::AttachContentToWindow(Remoting::AttachRequest request)
{
try

View File

@@ -56,7 +56,6 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
void RequestRename(const winrt::Microsoft::Terminal::Remoting::RenameRequestArgs& args);
void RequestShowNotificationIcon();
void RequestHideNotificationIcon();
void RequestQuitAll();
void Quit();
void AttachContentToWindow(Remoting::AttachRequest request);
@@ -76,7 +75,6 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
til::typed_event<> ShowNotificationIconRequested;
til::typed_event<> HideNotificationIconRequested;
til::typed_event<> QuitAllRequested;
til::typed_event<> QuitRequested;
til::typed_event<winrt::Windows::Foundation::IInspectable, winrt::Microsoft::Terminal::Remoting::AttachRequest> AttachRequested;

View File

@@ -80,7 +80,6 @@ namespace Microsoft.Terminal.Remoting
void RequestShowNotificationIcon();
void RequestHideNotificationIcon();
void RequestQuitAll();
void Quit();
void AttachContentToWindow(AttachRequest request);
@@ -95,7 +94,6 @@ namespace Microsoft.Terminal.Remoting
event Windows.Foundation.TypedEventHandler<Object, Object> ShowNotificationIconRequested;
event Windows.Foundation.TypedEventHandler<Object, Object> HideNotificationIconRequested;
event Windows.Foundation.TypedEventHandler<Object, Object> QuitAllRequested;
event Windows.Foundation.TypedEventHandler<Object, Object> QuitRequested;
event Windows.Foundation.TypedEventHandler<Object, AttachRequest> AttachRequested;

View File

@@ -130,6 +130,8 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
// We connected to a monarch instance, not us though. This won't hit
// in isolated mode.
LOG_IF_FAILED(CoAllowSetForegroundWindow(winrt::get_unknown(_monarch), nullptr));
// Send the commandline over to the monarch process
if (_proposeToMonarch(args))
{
@@ -373,6 +375,18 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
WindowClosed.raise(s, e);
}
void WindowManager::QuitAll()
{
if (_monarch)
{
try
{
_monarch.QuitAll();
}
CATCH_LOG()
}
}
void WindowManager::SignalClose(const Remoting::Peasant& peasant)
{
if (_monarch)

View File

@@ -32,6 +32,7 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
Remoting::Peasant CreatePeasant(const Remoting::WindowRequestedArgs& args);
void SignalClose(const Remoting::Peasant& peasant);
void QuitAll();
void SummonWindow(const Remoting::SummonWindowSelectionArgs& args);
void SummonAllWindows();
Windows::Foundation::Collections::IVectorView<winrt::Microsoft::Terminal::Remoting::PeasantInfo> GetPeasantInfos();

View File

@@ -12,6 +12,7 @@ namespace Microsoft.Terminal.Remoting
Peasant CreatePeasant(WindowRequestedArgs args);
void SignalClose(Peasant p);
void QuitAll();
void UpdateActiveTabTitle(String title, Peasant p);

View File

@@ -127,7 +127,7 @@ namespace winrt::TerminalApp::implementation
auto originalOpacity{ control.BackgroundOpacity() };
// Apply the new opacity
control.AdjustOpacity(args.Opacity() / 100.0, args.Relative());
control.AdjustOpacity(args.Opacity() / 100.0f, args.Relative());
if (backup)
{

View File

@@ -118,7 +118,7 @@ namespace winrt::TerminalApp::implementation
void TerminalPage::_HandleCloseWindow(const IInspectable& /*sender*/,
const ActionEventArgs& args)
{
CloseRequested.raise(nullptr, nullptr);
CloseWindow();
args.Handled(true);
}
@@ -238,6 +238,32 @@ namespace winrt::TerminalApp::implementation
}
}
// * Helper to try and get a ProfileIndex out of a NewTerminalArgs out of a
// NewContentArgs. For the new tab and split pane action, we want to _not_
// handle the event if an invalid profile index was passed.
//
// Return value:
// * True if the args are NewTerminalArgs, and the profile index was out of bounds.
// * False otherwise.
static bool _shouldBailForInvalidProfileIndex(const CascadiaSettings& settings, const INewContentArgs& args)
{
if (!args)
{
return false;
}
if (const auto& terminalArgs{ args.try_as<NewTerminalArgs>() })
{
if (const auto index = terminalArgs.ProfileIndex())
{
if (gsl::narrow<uint32_t>(index.Value()) >= settings.ActiveProfiles().Size())
{
return true;
}
}
}
return false;
}
void TerminalPage::_HandleSplitPane(const IInspectable& sender,
const ActionEventArgs& args)
{
@@ -247,16 +273,10 @@ namespace winrt::TerminalApp::implementation
}
else if (const auto& realArgs = args.ActionArgs().try_as<SplitPaneArgs>())
{
if (const auto& newTerminalArgs{ realArgs.TerminalArgs() })
if (_shouldBailForInvalidProfileIndex(_settings, realArgs.ContentArgs()))
{
if (const auto index = realArgs.TerminalArgs().ProfileIndex())
{
if (gsl::narrow<uint32_t>(index.Value()) >= _settings.ActiveProfiles().Size())
{
args.Handled(false);
return;
}
}
args.Handled(false);
return;
}
const auto& duplicateFromTab{ realArgs.SplitMode() == SplitType::Duplicate ? _GetFocusedTab() : nullptr };
@@ -266,8 +286,8 @@ namespace winrt::TerminalApp::implementation
_SplitPane(terminalTab,
realArgs.SplitDirection(),
// This is safe, we're already filtering so the value is (0, 1)
::base::saturated_cast<float>(realArgs.SplitSize()),
_MakePane(realArgs.TerminalArgs(), duplicateFromTab));
realArgs.SplitSize(),
_MakePane(realArgs.ContentArgs(), duplicateFromTab));
args.Handled(true);
}
}
@@ -445,19 +465,13 @@ namespace winrt::TerminalApp::implementation
}
else if (const auto& realArgs = args.ActionArgs().try_as<NewTabArgs>())
{
if (const auto& newTerminalArgs{ realArgs.TerminalArgs() })
if (_shouldBailForInvalidProfileIndex(_settings, realArgs.ContentArgs()))
{
if (const auto index = newTerminalArgs.ProfileIndex())
{
if (gsl::narrow<uint32_t>(index.Value()) >= _settings.ActiveProfiles().Size())
{
args.Handled(false);
return;
}
}
args.Handled(false);
return;
}
LOG_IF_FAILED(_OpenNewTab(realArgs.TerminalArgs()));
LOG_IF_FAILED(_OpenNewTab(realArgs.ContentArgs()));
args.Handled(true);
}
}
@@ -869,8 +883,23 @@ namespace winrt::TerminalApp::implementation
// - <none>
// Important: Don't take the param by reference, since we'll be doing work
// on another thread.
fire_and_forget TerminalPage::_OpenNewWindow(const NewTerminalArgs newTerminalArgs)
fire_and_forget TerminalPage::_OpenNewWindow(const INewContentArgs newContentArgs)
{
auto terminalArgs{ newContentArgs.try_as<NewTerminalArgs>() };
// Do nothing for non-terminal panes.
//
// Theoretically, we could define a `IHasCommandline` interface, and
// stick `ToCommandline` on that interface, for any kind of pane that
// wants to be convertable to a wt commandline.
//
// Another idea we're thinking about is just `wt do {literal json for an
// action}`, which might be less leaky
if (terminalArgs == nullptr)
{
co_return;
}
// Hop to the BG thread
co_await winrt::resume_background();
@@ -883,8 +912,7 @@ namespace winrt::TerminalApp::implementation
// `-w -1` will ensure a new window is created.
winrt::hstring cmdline{
fmt::format(L"-w -1 new-tab {}",
newTerminalArgs ? newTerminalArgs.ToCommandline().c_str() :
L"")
terminalArgs.ToCommandline().c_str())
};
// Build the args to ShellExecuteEx. We need to use ShellExecuteEx so we
@@ -909,29 +937,32 @@ namespace winrt::TerminalApp::implementation
void TerminalPage::_HandleNewWindow(const IInspectable& /*sender*/,
const ActionEventArgs& actionArgs)
{
NewTerminalArgs newTerminalArgs{ nullptr };
INewContentArgs newContentArgs{ nullptr };
// If the caller provided NewTerminalArgs, then try to use those
if (actionArgs)
{
if (const auto& realArgs = actionArgs.ActionArgs().try_as<NewWindowArgs>())
{
newTerminalArgs = realArgs.TerminalArgs();
newContentArgs = realArgs.ContentArgs();
}
}
// Otherwise, if no NewTerminalArgs were provided, then just use a
// default-constructed one. The default-constructed one implies that
// nothing about the launch should be modified (just use the default
// profile).
if (!newTerminalArgs)
if (!newContentArgs)
{
newTerminalArgs = NewTerminalArgs();
newContentArgs = NewTerminalArgs{};
}
const auto profile{ _settings.GetProfileForArgs(newTerminalArgs) };
if (const auto& terminalArgs{ newContentArgs.try_as<NewTerminalArgs>() })
{
const auto profile{ _settings.GetProfileForArgs(terminalArgs) };
terminalArgs.Profile(::Microsoft::Console::Utils::GuidToString(profile.Guid()));
}
// Manually fill in the evaluated profile.
newTerminalArgs.Profile(::Microsoft::Console::Utils::GuidToString(profile.Guid()));
_OpenNewWindow(newTerminalArgs);
_OpenNewWindow(newContentArgs);
actionArgs.Handled(true);
}
@@ -1216,7 +1247,7 @@ namespace winrt::TerminalApp::implementation
if (const auto& realArgs = args.ActionArgs().try_as<AdjustOpacityArgs>())
{
const auto res = _ApplyToActiveControls([&](auto& control) {
control.AdjustOpacity(realArgs.Opacity() / 100.0, realArgs.Relative());
control.AdjustOpacity(realArgs.Opacity() / 100.0f, realArgs.Relative());
});
args.Handled(res);
}
@@ -1418,7 +1449,7 @@ namespace winrt::TerminalApp::implementation
args.Handled(true);
}
void TerminalPage::_HandleOpenScratchpad(const IInspectable& /*sender*/,
void TerminalPage::_HandleOpenScratchpad(const IInspectable& sender,
const ActionEventArgs& args)
{
if (Feature_ScratchpadPane::IsEnabled())
@@ -1431,7 +1462,7 @@ namespace winrt::TerminalApp::implementation
scratchPane->GetRoot().KeyDown({ this, &TerminalPage::_KeyDownHandler });
const auto resultPane = std::make_shared<Pane>(*scratchPane);
_SplitPane(_GetFocusedTabImpl(), SplitDirection::Automatic, 0.5f, resultPane);
_SplitPane(_senderOrFocusedTab(sender), SplitDirection::Automatic, 0.5f, resultPane);
args.Handled(true);
}
}

View File

@@ -23,6 +23,27 @@
<UserControl.Resources>
<ResourceDictionary>
<!-- KeyChordText styles -->
<Style x:Key="KeyChordBorderStyle"
TargetType="Border">
<Setter Property="BorderThickness" Value="1" />
<Setter Property="CornerRadius" Value="2" />
<Setter Property="Background" Value="Transparent" />
<Setter Property="BorderBrush" Value="{ThemeResource SystemControlForegroundBaseMediumBrush}" />
</Style>
<Style x:Key="KeyChordTextBlockStyle"
TargetType="TextBlock">
<Setter Property="Foreground" Value="{ThemeResource SystemControlForegroundBaseMediumBrush}" />
</Style>
<!-- ParsedCommandLineText styles -->
<Style x:Key="ParsedCommandLineBorderStyle"
TargetType="Border">
<Setter Property="BorderThickness" Value="1" />
<Setter Property="CornerRadius" Value="{ThemeResource ControlCornerRadius}" />
<Setter Property="Background" Value="{ThemeResource CardBackgroundFillColorDefaultBrush}" />
<Setter Property="BorderBrush" Value="{ThemeResource CardStrokeColorDefaultBrush}" />
</Style>
<DataTemplate x:Key="ListItemTemplate"
x:DataType="local:FilteredCommand">
<ListViewItem HorizontalContentAlignment="Stretch"
@@ -69,12 +90,12 @@
VerticalAlignment="Center"
AutomationProperties.AccessibilityView="Raw"
Background="{ThemeResource FlyoutPresenterBackground}"
Style="{ThemeResource KeyChordBorderStyle}"
Style="{StaticResource KeyChordBorderStyle}"
Visibility="{x:Bind mtu:Converters.StringNotEmptyToVisibility(Item.KeyChordText), Mode=OneWay}">
<TextBlock AutomationProperties.AccessibilityView="Raw"
FontSize="12"
Style="{ThemeResource KeyChordTextBlockStyle}"
Style="{StaticResource KeyChordTextBlockStyle}"
Text="{x:Bind Item.KeyChordText, Mode=OneWay}" />
</Border>
</Grid>
@@ -118,12 +139,12 @@
HorizontalAlignment="Right"
VerticalAlignment="Center"
AutomationProperties.AccessibilityView="Raw"
Style="{ThemeResource KeyChordBorderStyle}"
Style="{StaticResource KeyChordBorderStyle}"
Visibility="{x:Bind mtu:Converters.StringNotEmptyToVisibility(Item.KeyChordText), Mode=OneWay}">
<TextBlock AutomationProperties.AccessibilityView="Raw"
FontSize="12"
Style="{ThemeResource KeyChordTextBlockStyle}"
Style="{StaticResource KeyChordTextBlockStyle}"
Text="{x:Bind Item.KeyChordText, Mode=OneWay}" />
</Border>
@@ -212,79 +233,6 @@
GeneralItemTemplate="{StaticResource GeneralItemTemplate}"
NestedItemTemplate="{StaticResource NestedItemTemplate}"
TabItemTemplate="{StaticResource TabItemTemplate}" />
<ResourceDictionary.ThemeDictionaries>
<ResourceDictionary x:Key="Dark">
<!-- KeyChordText styles -->
<Style x:Key="KeyChordBorderStyle"
TargetType="Border">
<Setter Property="BorderThickness" Value="1" />
<Setter Property="CornerRadius" Value="2" />
<Setter Property="Background" Value="Transparent" />
<Setter Property="BorderBrush" Value="{ThemeResource SystemControlForegroundBaseMediumBrush}" />
</Style>
<Style x:Key="KeyChordTextBlockStyle"
TargetType="TextBlock">
<Setter Property="Foreground" Value="{ThemeResource SystemControlForegroundBaseMediumBrush}" />
</Style>
<!-- ParsedCommandLineText styles -->
<Style x:Key="ParsedCommandLineBorderStyle"
TargetType="Border">
<Setter Property="BorderThickness" Value="1" />
<Setter Property="CornerRadius" Value="{ThemeResource ControlCornerRadius}" />
<Setter Property="Background" Value="{ThemeResource CardBackgroundFillColorDefaultBrush}" />
<Setter Property="BorderBrush" Value="{ThemeResource CardStrokeColorDefaultBrush}" />
</Style>
<Style x:Key="ParsedCommandLineTextBlockStyle"
TargetType="TextBlock">
<Setter Property="Foreground" Value="{ThemeResource SystemControlForegroundBaseMediumBrush}" />
</Style>
</ResourceDictionary>
<ResourceDictionary x:Key="Light">
<!-- KeyChordText styles -->
<Style x:Key="KeyChordBorderStyle"
TargetType="Border">
<Setter Property="BorderThickness" Value="1" />
<Setter Property="CornerRadius" Value="2" />
<Setter Property="Background" Value="Transparent" />
<Setter Property="BorderBrush" Value="{ThemeResource SystemControlForegroundBaseMediumBrush}" />
</Style>
<Style x:Key="KeyChordTextBlockStyle"
TargetType="TextBlock">
<Setter Property="Foreground" Value="{ThemeResource SystemControlForegroundBaseMediumBrush}" />
</Style>
<!-- ParsedCommandLineText styles -->
<Style x:Key="ParsedCommandLineBorderStyle"
TargetType="Border">
<Setter Property="BorderThickness" Value="1" />
<Setter Property="CornerRadius" Value="{ThemeResource ControlCornerRadius}" />
<Setter Property="Background" Value="{ThemeResource CardBackgroundFillColorDefaultBrush}" />
<Setter Property="BorderBrush" Value="{ThemeResource CardStrokeColorDefaultBrush}" />
</Style>
<Style x:Key="ParsedCommandLineTextBlockStyle"
TargetType="TextBlock">
<Setter Property="Foreground" Value="{ThemeResource SystemControlForegroundBaseMediumBrush}" />
</Style>
</ResourceDictionary>
<ResourceDictionary x:Key="HighContrast">
<!-- KeyChordText styles (use XAML defaults for High Contrast theme) -->
<Style x:Key="KeyChordBorderStyle"
TargetType="Border" />
<Style x:Key="KeyChordTextBlockStyle"
TargetType="TextBlock" />
<!-- ParsedCommandLineText styles (use XAML defaults for High Contrast theme) -->
<Style x:Key="ParsedCommandLineBorderStyle"
TargetType="Border" />
<Style x:Key="ParsedCommandLineTextBlockStyle"
TargetType="TextBlock" />
</ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>
</ResourceDictionary>
</UserControl.Resources>
@@ -368,7 +316,7 @@
Padding="16,12"
HorizontalAlignment="Stretch"
VerticalAlignment="Center"
Style="{ThemeResource ParsedCommandLineBorderStyle}"
Style="{StaticResource ParsedCommandLineBorderStyle}"
Visibility="{x:Bind mtu:Converters.StringNotEmptyToVisibility(ParsedCommandLineText), Mode=OneWay}">
<ScrollViewer MaxHeight="200"

View File

@@ -19,6 +19,7 @@ namespace TerminalApp
interface IPaneContent
{
Windows.UI.Xaml.FrameworkElement GetRoot();
void UpdateSettings(Microsoft.Terminal.Settings.Model.CascadiaSettings settings);
Windows.Foundation.Size MinimumSize { get; };
@@ -26,8 +27,11 @@ namespace TerminalApp
UInt64 TaskbarState { get; };
UInt64 TaskbarProgress { get; };
Boolean ReadOnly { get; };
String Icon { get; };
Windows.Foundation.IReference<Windows.UI.Color> TabColor { get; };
Windows.UI.Xaml.Media.Brush BackgroundBrush { get; };
Microsoft.Terminal.Settings.Model.NewTerminalArgs GetNewTerminalArgs(BuildStartupKind kind);
Microsoft.Terminal.Settings.Model.INewContentArgs GetNewTerminalArgs(BuildStartupKind kind);
void Focus(Windows.UI.Xaml.FocusState reason);

View File

@@ -116,6 +116,9 @@ namespace winrt::TerminalApp::implementation
switch (visualState)
{
case WindowVisualState::WindowVisualStateIconified:
// Iconified (aka minimized) state should preserve the active window styling
break;
case WindowVisualState::WindowVisualStateMaximized:
VisualStateManager::GoToState(MaximizeButton(), L"WindowStateMaximized", false);
@@ -124,9 +127,7 @@ namespace winrt::TerminalApp::implementation
CloseButton().Height(maximizedHeight);
MaximizeToolTip().Text(RS_(L"WindowRestoreDownButtonToolTip"));
break;
case WindowVisualState::WindowVisualStateNormal:
case WindowVisualState::WindowVisualStateIconified:
default:
VisualStateManager::GoToState(MaximizeButton(), L"WindowStateNormal", false);

View File

@@ -27,10 +27,10 @@ static const int CombinedPaneBorderSize = 2 * PaneBorderSize;
static const int AnimationDurationInMilliseconds = 200;
static const Duration AnimationDuration = DurationHelper::FromTimeSpan(winrt::Windows::Foundation::TimeSpan(std::chrono::milliseconds(AnimationDurationInMilliseconds)));
Pane::Pane(const IPaneContent& content, const bool lastFocused) :
_content{ content },
Pane::Pane(IPaneContent content, const bool lastFocused) :
_lastActive{ lastFocused }
{
_setPaneContent(std::move(content));
_root.Children().Append(_borderFirst);
const auto& control{ _content.GetRoot() };
@@ -47,14 +47,8 @@ Pane::Pane(const IPaneContent& content, const bool lastFocused) :
// LOAD-BEARING: This will NOT work if the border's BorderBrush is set to
// Colors::Transparent! The border won't get Tapped events, and they'll fall
// through to something else.
_borderFirst.Tapped([this](auto&, auto& e) {
_FocusFirstChild();
e.Handled(true);
});
_borderSecond.Tapped([this](auto&, auto& e) {
_FocusFirstChild();
e.Handled(true);
});
_borderFirst.Tapped({ this, &Pane::_borderTappedHandler });
_borderSecond.Tapped({ this, &Pane::_borderTappedHandler });
}
Pane::Pane(std::shared_ptr<Pane> first,
@@ -88,19 +82,13 @@ Pane::Pane(std::shared_ptr<Pane> first,
// LOAD-BEARING: This will NOT work if the border's BorderBrush is set to
// Colors::Transparent! The border won't get Tapped events, and they'll fall
// through to something else.
_borderFirst.Tapped([this](auto&, auto& e) {
_FocusFirstChild();
e.Handled(true);
});
_borderSecond.Tapped([this](auto&, auto& e) {
_FocusFirstChild();
e.Handled(true);
});
_borderFirst.Tapped({ this, &Pane::_borderTappedHandler });
_borderSecond.Tapped({ this, &Pane::_borderTappedHandler });
}
// Extract the terminal settings from the current (leaf) pane's control
// to be used to create an equivalent control
NewTerminalArgs Pane::GetTerminalArgsForPane(BuildStartupKind kind) const
INewContentArgs Pane::GetTerminalArgsForPane(BuildStartupKind kind) const
{
// Leaves are the only things that have controls
assert(_IsLeaf());
@@ -151,7 +139,7 @@ Pane::BuildStartupState Pane::BuildStartupActions(uint32_t currentId, uint32_t n
// When creating a pane the split size is the size of the new pane
// and not position.
const auto splitDirection = _splitState == SplitState::Horizontal ? SplitDirection::Down : SplitDirection::Right;
const auto splitSize = (kind != BuildStartupKind::None && _IsLeaf() ? .5 : 1. - _desiredSplitPosition);
const auto splitSize = (kind != BuildStartupKind::None && _IsLeaf() ? 0.5f : 1.0f - _desiredSplitPosition);
SplitPaneArgs args{ SplitType::Manual, splitDirection, splitSize, terminalArgs };
actionAndArgs.Args(args);
@@ -479,7 +467,7 @@ std::shared_ptr<Pane> Pane::NextPane(const std::shared_ptr<Pane> targetPane)
std::shared_ptr<Pane> nextPane = nullptr;
auto foundTarget = false;
auto foundNext = WalkTree([&](auto pane) {
auto foundNext = WalkTree([&](const auto& pane) {
// If we are a parent pane we don't want to move to one of our children
if (foundTarget && targetPane->_HasChild(pane))
{
@@ -997,6 +985,7 @@ void Pane::_ContentLostFocusHandler(const winrt::Windows::Foundation::IInspectab
// - <none>
void Pane::Close()
{
_setPaneContent(nullptr);
// Fire our Closed event to tell our parent that we should be removed.
Closed.raise(nullptr, nullptr);
}
@@ -1008,7 +997,7 @@ void Pane::Shutdown()
{
if (_IsLeaf())
{
_content.Close();
_setPaneContent(nullptr);
}
else
{
@@ -1075,6 +1064,29 @@ TermControl Pane::GetLastFocusedTerminalControl()
return GetTerminalControl();
}
IPaneContent Pane::GetLastFocusedContent()
{
if (!_IsLeaf())
{
if (_lastActive)
{
auto pane = shared_from_this();
while (const auto p = pane->_parentChildPath.lock())
{
if (p->_IsLeaf())
{
return p->_content;
}
pane = p;
}
// We didn't find our child somehow, they might have closed under us.
}
return _firstChild->GetLastFocusedContent();
}
return _content;
}
// Method Description:
// - Gets the TermControl of this pane. If this Pane is not a leaf this will
// return the nullptr;
@@ -1214,8 +1226,19 @@ void Pane::UpdateVisuals()
// - <none>
void Pane::_Focus()
{
// Don't focus our content if we're already focused. This prevents a bug
// where tapping on the arrow in a ComboBox will land in our Tapped handler,
// and if we steal focus from the ComboBox, it won't open. See GH#17062
if (WasLastFocused())
{
return;
}
GotFocus.raise(shared_from_this(), FocusState::Programmatic);
_content.Focus(FocusState::Programmatic);
if (const auto& lastContent{ GetLastFocusedContent() })
{
lastContent.Focus(FocusState::Programmatic);
}
}
// Method Description:
@@ -1254,20 +1277,11 @@ void Pane::_FocusFirstChild()
}
}
// Method Description:
// - Updates the settings of this pane, presuming that it is a leaf.
// Arguments:
// - settings: The new TerminalSettings to apply to any matching controls
// - profile: The profile from which these settings originated.
// Return Value:
// - <none>
void Pane::UpdateSettings(const TerminalSettingsCreateResult& settings, const Profile& profile)
void Pane::UpdateSettings(const CascadiaSettings& settings)
{
assert(_IsLeaf());
if (const auto& terminalPane{ _getTerminalContent() })
if (_content)
{
return terminalPane.UpdateSettings(settings, profile);
_content.UpdateSettings(settings);
}
}
@@ -1328,7 +1342,7 @@ std::shared_ptr<Pane> Pane::DetachPane(std::shared_ptr<Pane> pane)
detached->_ApplySplitDefinitions();
// Trigger the detached event on each child
detached->WalkTree([](auto pane) {
detached->WalkTree([](const auto& pane) {
pane->Detached.raise(pane);
});
@@ -1387,7 +1401,7 @@ void Pane::_CloseChild(const bool closeFirst)
_borders = _GetCommonBorders();
// take the control, profile, id and isDefTermSession of the pane that _wasn't_ closed.
_content = remainingChild->_content;
_setPaneContent(remainingChild->_takePaneContent());
_id = remainingChild->Id();
// Revoke the old event handlers. Remove both the handlers for the panes
@@ -1529,7 +1543,7 @@ void Pane::_CloseChild(const bool closeFirst)
{
// update our path to our first remaining leaf
_parentChildPath = _firstChild;
_firstChild->WalkTree([](auto p) {
_firstChild->WalkTree([](const auto& p) {
if (p->_IsLeaf())
{
return true;
@@ -1578,12 +1592,12 @@ void Pane::_CloseChildRoutine(const bool closeFirst)
const auto splitWidth = _splitState == SplitState::Vertical;
Size removedOriginalSize{
::base::saturated_cast<float>(removedChild->_root.ActualWidth()),
::base::saturated_cast<float>(removedChild->_root.ActualHeight())
static_cast<float>(removedChild->_root.ActualWidth()),
static_cast<float>(removedChild->_root.ActualHeight())
};
Size remainingOriginalSize{
::base::saturated_cast<float>(remainingChild->_root.ActualWidth()),
::base::saturated_cast<float>(remainingChild->_root.ActualHeight())
static_cast<float>(remainingChild->_root.ActualWidth()),
static_cast<float>(remainingChild->_root.ActualHeight())
};
// Remove both children from the grid
@@ -1692,6 +1706,33 @@ void Pane::_SetupChildCloseHandlers()
});
}
// With this method you take ownership of the control from this Pane.
// Assign it to another Pane with _setPaneContent() or Close() it.
IPaneContent Pane::_takePaneContent()
{
_closeRequestedRevoker.revoke();
return std::move(_content);
}
// This method safely sets the content of the Pane. It'll ensure to revoke and
// assign event handlers, and to Close() the existing content if there's any.
// The new content can be nullptr to remove any content.
void Pane::_setPaneContent(IPaneContent content)
{
// The IPaneContent::Close() implementation may be buggy and raise the CloseRequested event again.
// _takePaneContent() avoids this as it revokes the event handler.
if (const auto c = _takePaneContent())
{
c.Close();
}
if (content)
{
_content = std::move(content);
_closeRequestedRevoker = _content.CloseRequested(winrt::auto_revoke, [this](auto&&, auto&&) { Close(); });
}
}
// Method Description:
// - Sets up row/column definitions for this pane. There are three total
// row/cols. The middle one is for the separator. The first and third are for
@@ -1885,7 +1926,7 @@ void Pane::_SetupEntranceAnimation()
// looks bad.
_secondChild->_root.Background(_themeResources.unfocusedBorderBrush);
const auto [firstSize, secondSize] = _CalcChildrenSizes(::base::saturated_cast<float>(totalSize));
const auto [firstSize, secondSize] = _CalcChildrenSizes(static_cast<float>(totalSize));
// This is safe to capture this, because it's only being called in the
// context of this method (not on another thread)
@@ -1893,7 +1934,7 @@ void Pane::_SetupEntranceAnimation()
auto child = isFirstChild ? _firstChild : _secondChild;
auto childGrid = child->_root;
// If we are splitting a parent pane this may be null
auto control = child->_content.GetRoot();
auto control = child->_content ? child->_content.GetRoot() : nullptr;
// Build up our animation:
// * it'll take as long as our duration (200ms)
// * it'll change the value of our property from 0 to secondSize
@@ -2242,8 +2283,7 @@ std::pair<std::shared_ptr<Pane>, std::shared_ptr<Pane>> Pane::_Split(SplitDirect
else
{
// Move our control, guid, isDefTermSession into the first one.
_firstChild = std::make_shared<Pane>(_content);
_content = nullptr;
_firstChild = std::make_shared<Pane>(_takePaneContent());
_firstChild->_broadcastEnabled = _broadcastEnabled;
}
@@ -2385,7 +2425,7 @@ void Pane::Id(uint32_t id) noexcept
bool Pane::FocusPane(const uint32_t id)
{
// Always clear the parent child path if we are focusing a leaf
return WalkTree([=](auto p) {
return WalkTree([=](const auto& p) {
p->_parentChildPath.reset();
if (p->_id == id)
{
@@ -2408,7 +2448,7 @@ bool Pane::FocusPane(const uint32_t id)
// - true if focus was set
bool Pane::FocusPane(const std::shared_ptr<Pane> pane)
{
return WalkTree([&](auto p) {
return WalkTree([&](const auto& p) {
if (p == pane)
{
p->_Focus();
@@ -2438,6 +2478,11 @@ bool Pane::_HasChild(const std::shared_ptr<Pane> child)
});
}
winrt::TerminalApp::TerminalPaneContent Pane::_getTerminalContent() const
{
return _IsLeaf() ? _content.try_as<winrt::TerminalApp::TerminalPaneContent>() : nullptr;
}
// Method Description:
// - Recursive function that finds a pane with the given ID
// Arguments:
@@ -2910,13 +2955,13 @@ bool Pane::ContainsReadOnly() const
// - <none>
void Pane::CollectTaskbarStates(std::vector<winrt::TerminalApp::TaskbarState>& states)
{
if (_IsLeaf())
if (_content)
{
auto tbState{ winrt::make<winrt::TerminalApp::implementation::TaskbarState>(_content.TaskbarState(),
_content.TaskbarProgress()) };
states.push_back(tbState);
}
else
else if (_firstChild && _secondChild)
{
_firstChild->CollectTaskbarStates(states);
_secondChild->CollectTaskbarStates(states);
@@ -3004,3 +3049,9 @@ winrt::Windows::UI::Xaml::Media::SolidColorBrush Pane::_ComputeBorderColor()
return _themeResources.unfocusedBorderBrush;
}
void Pane::_borderTappedHandler(const winrt::Windows::Foundation::IInspectable& /*sender*/, const winrt::Windows::UI::Xaml::Input::TappedRoutedEventArgs& e)
{
_FocusFirstChild();
e.Handled(true);
}

View File

@@ -62,7 +62,7 @@ struct PaneResources
class Pane : public std::enable_shared_from_this<Pane>
{
public:
Pane(const winrt::TerminalApp::IPaneContent& content,
Pane(winrt::TerminalApp::IPaneContent content,
const bool lastFocused = false);
Pane(std::shared_ptr<Pane> first,
@@ -73,6 +73,7 @@ public:
std::shared_ptr<Pane> GetActivePane();
winrt::Microsoft::Terminal::Control::TermControl GetLastFocusedTerminalControl();
winrt::TerminalApp::IPaneContent GetLastFocusedContent();
winrt::Microsoft::Terminal::Control::TermControl GetTerminalControl() const;
winrt::Microsoft::Terminal::Settings::Model::Profile GetFocusedProfile();
bool IsConnectionClosed() const;
@@ -105,10 +106,9 @@ public:
uint32_t panesCreated;
};
BuildStartupState BuildStartupActions(uint32_t currentId, uint32_t nextId, winrt::TerminalApp::BuildStartupKind kind);
winrt::Microsoft::Terminal::Settings::Model::NewTerminalArgs GetTerminalArgsForPane(winrt::TerminalApp::BuildStartupKind kind) const;
winrt::Microsoft::Terminal::Settings::Model::INewContentArgs GetTerminalArgsForPane(winrt::TerminalApp::BuildStartupKind kind) const;
void UpdateSettings(const winrt::Microsoft::Terminal::Settings::Model::TerminalSettingsCreateResult& settings,
const winrt::Microsoft::Terminal::Settings::Model::Profile& profile);
void UpdateSettings(const winrt::Microsoft::Terminal::Settings::Model::CascadiaSettings& settings);
bool ResizePane(const winrt::Microsoft::Terminal::Settings::Model::ResizeDirection& direction);
std::shared_ptr<Pane> NavigateDirection(const std::shared_ptr<Pane> sourcePane,
const winrt::Microsoft::Terminal::Settings::Model::FocusDirection& direction,
@@ -248,13 +248,13 @@ private:
std::optional<uint32_t> _id;
std::weak_ptr<Pane> _parentChildPath{};
bool _lastActive{ false };
winrt::event_token _firstClosedToken{ 0 };
winrt::event_token _secondClosedToken{ 0 };
winrt::Windows::UI::Xaml::UIElement::GotFocus_revoker _gotFocusRevoker;
winrt::Windows::UI::Xaml::UIElement::LostFocus_revoker _lostFocusRevoker;
winrt::TerminalApp::IPaneContent::CloseRequested_revoker _closeRequestedRevoker;
Borders _borders{ Borders::None };
@@ -264,11 +264,10 @@ private:
bool _IsLeaf() const noexcept;
bool _HasFocusedChild() const noexcept;
void _SetupChildCloseHandlers();
winrt::TerminalApp::IPaneContent _takePaneContent();
void _setPaneContent(winrt::TerminalApp::IPaneContent content);
bool _HasChild(const std::shared_ptr<Pane> child);
winrt::TerminalApp::TerminalPaneContent _getTerminalContent() const
{
return _IsLeaf() ? _content.try_as<winrt::TerminalApp::TerminalPaneContent>() : nullptr;
}
winrt::TerminalApp::TerminalPaneContent _getTerminalContent() const;
std::pair<std::shared_ptr<Pane>, std::shared_ptr<Pane>> _Split(winrt::Microsoft::Terminal::Settings::Model::SplitDirection splitType,
const float splitSize,
@@ -314,6 +313,8 @@ private:
SplitState _convertAutomaticOrDirectionalSplitState(const winrt::Microsoft::Terminal::Settings::Model::SplitDirection& splitType) const;
void _borderTappedHandler(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::UI::Xaml::Input::TappedRoutedEventArgs& e);
// Function Description:
// - Returns true if the given direction can be used with the given split
// type.

View File

@@ -154,7 +154,7 @@
<comment>{Locked=qps-ploc,qps-ploca,qps-plocm}</comment>
</data>
<data name="AppDescription" xml:space="preserve">
<value>Nová Terminál Windows</value>
<value>Nový Terminál Windows</value>
</data>
<data name="AppDescriptionPre" xml:space="preserve">
<value>Terminál Windows s náhledem připravovaných funkcí</value>
@@ -164,11 +164,11 @@
<comment>This is a menu item that will be displayed in the Windows File Explorer that launches the Canary version of Windows Terminal. Please mark one of the characters to be an accelerator key.</comment>
</data>
<data name="ShellExtension_OpenInTerminalMenuItem_Preview" xml:space="preserve">
<value>Otevřít náhled &amp;aplikace Terminal</value>
<value>Otevřít &amp;náhled Terminálu</value>
<comment>This is a menu item that will be displayed in the Windows File Explorer that launches the Preview version of Windows Terminal. Please mark one of the characters to be an accelerator key.</comment>
</data>
<data name="ShellExtension_OpenInTerminalMenuItem" xml:space="preserve">
<value>Otevřít v aplikaci &amp;Terminal</value>
<value>Otevřít v &amp;Terminálu</value>
<comment>This is a menu item that will be displayed in the Windows File Explorer that launches the non-preview version of Windows Terminal. Please mark one of the characters to be an accelerator key.</comment>
</data>
</root>

View File

@@ -190,16 +190,16 @@
<value>Mehrere Bereiche</value>
</data>
<data name="TabCloseSubMenu" xml:space="preserve">
<value>Schließen...</value>
<value>Schließen</value>
</data>
<data name="TabCloseAfter" xml:space="preserve">
<value>Registerkarten auf der rechten Seite schließen</value>
<value>Tabs nach rechts schließen</value>
</data>
<data name="TabCloseOther" xml:space="preserve">
<value>Andere Registerkarten schließen</value>
</data>
<data name="TabClose" xml:space="preserve">
<value>Registerkarte schließen</value>
<value>Tab schließen</value>
</data>
<data name="PaneClose" xml:space="preserve">
<value>Bereich schließen</value>
@@ -208,16 +208,16 @@
<value>Registerkarte teilen</value>
</data>
<data name="SplitPaneText" xml:space="preserve">
<value>Geteilter Bereich</value>
<value>Bereich teilen</value>
</data>
<data name="SearchWebText" xml:space="preserve">
<value>Websuche</value>
</data>
<data name="TabColorChoose" xml:space="preserve">
<value>Farbe...</value>
<value>Registerkartenfarbe ändern</value>
</data>
<data name="TabColorCustomButton.Content" xml:space="preserve">
<value>Benutzerdefiniert...</value>
<value>Benutzerdefiniert</value>
</data>
<data name="TabColorClearButton.Content" xml:space="preserve">
<value>Zurücksetzen</value>
@@ -226,7 +226,7 @@
<value>Registerkarte umbenennen</value>
</data>
<data name="DuplicateTabText" xml:space="preserve">
<value>Registerkarte duplizieren</value>
<value>Registerkarte kopieren</value>
</data>
<data name="InvalidBackgroundImage" xml:space="preserve">
<value>Profil mit einem ungültigen "backgroundImage" gefunden. Dieses Profil hat standardmäßig kein Hintergrundbild. Stellen Sie sicher, dass beim Festlegen eines "backgroundImage" der Wert ein gültiger Dateipfad zu einem Bild ist.</value>
@@ -487,7 +487,7 @@
<comment>A hyperlink name for the Terminal's privacy policy</comment>
</data>
<data name="AboutDialog_ThirdPartyNoticesLink.Content" xml:space="preserve">
<value>Drittanbieter-Hinweise</value>
<value>Hinweise von Drittanbietern</value>
<comment>A hyperlink name for the Terminal's third-party notices</comment>
</data>
<data name="QuitDialog.CloseButtonText" xml:space="preserve">
@@ -761,7 +761,7 @@
<value>Suchen</value>
</data>
<data name="PlainText" xml:space="preserve">
<value>Nur Text</value>
<value>Unformatierter Text</value>
</data>
<data name="CloseOnExitInfoBar.Message" xml:space="preserve">
<value>Das Beendigungsverhalten kann in den erweiterten Profileinstellungen konfiguriert werden.</value>
@@ -830,7 +830,7 @@
<value>Diese Registerkarte schließen</value>
</data>
<data name="NewTabMenuFolderEmpty" xml:space="preserve">
<value>Leer...</value>
<value>Leer</value>
</data>
<data name="ClosePaneText" xml:space="preserve">
<value>Bereich schließen</value>

View File

@@ -191,43 +191,43 @@
<value>Multiple panes</value>
</data>
<data name="TabCloseSubMenu" xml:space="preserve">
<value>Close...</value>
<value>Close</value>
</data>
<data name="TabCloseAfter" xml:space="preserve">
<value>Close Tabs to the Right</value>
<value>Close tabs to the right</value>
</data>
<data name="TabCloseOther" xml:space="preserve">
<value>Close Other Tabs</value>
<value>Close other tabs</value>
</data>
<data name="TabClose" xml:space="preserve">
<value>Close Tab</value>
<value>Close tab</value>
</data>
<data name="PaneClose" xml:space="preserve">
<value>Close Pane</value>
<value>Close pane</value>
</data>
<data name="SplitTabText" xml:space="preserve">
<value>Split Tab</value>
<value>Split tab</value>
</data>
<data name="SplitPaneText" xml:space="preserve">
<value>Split Pane</value>
<value>Split pane</value>
</data>
<data name="SearchWebText" xml:space="preserve">
<value>Web Search</value>
<value>Web search</value>
</data>
<data name="TabColorChoose" xml:space="preserve">
<value>Color...</value>
<value>Change tab color</value>
</data>
<data name="TabColorCustomButton.Content" xml:space="preserve">
<value>Custom...</value>
<value>Custom</value>
</data>
<data name="TabColorClearButton.Content" xml:space="preserve">
<value>Reset</value>
</data>
<data name="RenameTabText" xml:space="preserve">
<value>Rename Tab</value>
<value>Rename tab</value>
</data>
<data name="DuplicateTabText" xml:space="preserve">
<value>Duplicate Tab</value>
<value>Duplicate tab</value>
</data>
<data name="InvalidBackgroundImage" xml:space="preserve">
<value>Found a profile with an invalid "backgroundImage". Defaulting that profile to have no background image. Make sure that when setting a "backgroundImage", the value is a valid file path to an image.</value>
@@ -462,7 +462,7 @@
<value>About</value>
</data>
<data name="AboutDialog.PrimaryButtonText" xml:space="preserve">
<value>Send Feedback</value>
<value>Send feedback</value>
</data>
<data name="AboutDialog.CloseButtonText" xml:space="preserve">
<value>OK</value>
@@ -472,11 +472,11 @@
<comment>This is the heading for a version number label</comment>
</data>
<data name="AboutDialog_GettingStartedLink.Content" xml:space="preserve">
<value>Getting Started</value>
<value>Getting started</value>
<comment>A hyperlink name for a guide on how to get started using Terminal</comment>
</data>
<data name="AboutDialog_SourceCodeLink.Content" xml:space="preserve">
<value>Source Code</value>
<value>Source code</value>
<comment>A hyperlink name for the Terminal's documentation</comment>
</data>
<data name="AboutDialog_DocumentationLink.Content" xml:space="preserve">
@@ -484,15 +484,15 @@
<comment>A hyperlink name for user documentation</comment>
</data>
<data name="AboutDialog_ReleaseNotesLink.Content" xml:space="preserve">
<value>Release Notes</value>
<value>Release notes</value>
<comment>A hyperlink name for the Terminal's release notes</comment>
</data>
<data name="AboutDialog_PrivacyPolicyLink.Content" xml:space="preserve">
<value>Privacy Policy</value>
<value>Privacy policy</value>
<comment>A hyperlink name for the Terminal's privacy policy</comment>
</data>
<data name="AboutDialog_ThirdPartyNoticesLink.Content" xml:space="preserve">
<value>Third-Party Notices</value>
<value>Third-Party notices</value>
<comment>A hyperlink name for the Terminal's third-party notices</comment>
</data>
<data name="QuitDialog.CloseButtonText" xml:space="preserve">
@@ -579,10 +579,10 @@
<value>Failed parsing command line:</value>
</data>
<data name="CommandPaletteControlName" xml:space="preserve">
<value>Command Palette</value>
<value>Command palette</value>
</data>
<data name="TabSwitcherControlName" xml:space="preserve">
<value>Tab Switcher</value>
<value>Tab switcher</value>
</data>
<data name="TabSwitcher_SearchBoxText" xml:space="preserve">
<value>Type a tab name...</value>
@@ -731,10 +731,10 @@
<value>Maximize</value>
</data>
<data name="WindowRestoreDownButtonToolTip" xml:space="preserve">
<value>Restore Down</value>
<value>Restore down</value>
</data>
<data name="CommandPaletteMenuItem" xml:space="preserve">
<value>Command Palette</value>
<value>Command palette</value>
</data>
<data name="NotificationIconFocusTerminal" xml:space="preserve">
<value>Focus Terminal</value>
@@ -754,7 +754,7 @@
<value>Split the window and start in given directory</value>
</data>
<data name="ExportTabText" xml:space="preserve">
<value>Export Text</value>
<value>Export text</value>
</data>
<data name="ExportFailure" xml:space="preserve">
<value>Failed to export terminal content</value>
@@ -766,7 +766,7 @@
<value>Find</value>
</data>
<data name="PlainText" xml:space="preserve">
<value>Plain Text</value>
<value>Plain text</value>
</data>
<data name="CloseOnExitInfoBar.Message" xml:space="preserve">
<value>Termination behavior can be configured in advanced profile settings.</value>
@@ -775,7 +775,7 @@
<value>Don't show again</value>
</data>
<data name="ElevationShield.[using:Windows.UI.Xaml.Controls]ToolTipService.ToolTip" xml:space="preserve">
<value>This Terminal window is running as Admin</value>
<value>This Terminal window is running as administrator</value>
</data>
<data name="CommandPalette_MatchesAvailable" xml:space="preserve">
<value>Suggestions found: {0}</value>
@@ -835,10 +835,10 @@
<value>Close this tab</value>
</data>
<data name="NewTabMenuFolderEmpty" xml:space="preserve">
<value>Empty...</value>
<value>Empty</value>
</data>
<data name="ClosePaneText" xml:space="preserve">
<value>Close Pane</value>
<value>Close pane</value>
</data>
<data name="ClosePaneToolTip" xml:space="preserve">
<value>Close the active pane if multiple panes are present</value>
@@ -848,13 +848,13 @@
<comment>Text used to identify the reset button</comment>
</data>
<data name="MoveTabToNewWindowText" xml:space="preserve">
<value>Move Tab to New Window</value>
<value>Move tab to new window</value>
</data>
<data name="MoveTabToNewWindowToolTip" xml:space="preserve">
<value>Moves tab to a new window </value>
</data>
<data name="RunAsAdminFlyout.Text" xml:space="preserve">
<value>Run as Administrator</value>
<value>Run as administrator</value>
<comment>This text is displayed on context menu for profile entries in add new tab button.</comment>
</data>
<data name="TerminalPage_PaneMovedAnnouncement_ExistingTab" xml:space="preserve">
@@ -893,7 +893,7 @@
<value>If set, the command will be appended to the profile's default command instead of replacing it.</value>
</data>
<data name="RestartConnectionText" xml:space="preserve">
<value>Restart Connection</value>
<value>Restart connection</value>
</data>
<data name="RestartConnectionToolTip" xml:space="preserve">
<value>Restart the active pane connection</value>

View File

@@ -187,7 +187,7 @@
<value>Varios paneles</value>
</data>
<data name="TabCloseSubMenu" xml:space="preserve">
<value>Cerrar...</value>
<value>Cerrar</value>
</data>
<data name="TabCloseAfter" xml:space="preserve">
<value>Cerrar las pestañas de la derecha</value>
@@ -202,19 +202,19 @@
<value>Cerrar panel</value>
</data>
<data name="SplitTabText" xml:space="preserve">
<value>Dividir tabla</value>
<value>Dividir pestaña</value>
</data>
<data name="SplitPaneText" xml:space="preserve">
<value>Panel dividido</value>
<value>Dividir panel</value>
</data>
<data name="SearchWebText" xml:space="preserve">
<value>Búsqueda en la Web</value>
<value>Búsqueda en la web</value>
</data>
<data name="TabColorChoose" xml:space="preserve">
<value>Color...</value>
<value>Cambiar color de pestaña</value>
</data>
<data name="TabColorCustomButton.Content" xml:space="preserve">
<value>Configuración personalizada...</value>
<value>Personalizar</value>
</data>
<data name="TabColorClearButton.Content" xml:space="preserve">
<value>Restablecer</value>
@@ -464,7 +464,7 @@
<comment>This is the heading for a version number label</comment>
</data>
<data name="AboutDialog_GettingStartedLink.Content" xml:space="preserve">
<value>Tareas iniciales</value>
<value>Introducción</value>
<comment>A hyperlink name for a guide on how to get started using Terminal</comment>
</data>
<data name="AboutDialog_SourceCodeLink.Content" xml:space="preserve">
@@ -480,7 +480,7 @@
<comment>A hyperlink name for the Terminal's release notes</comment>
</data>
<data name="AboutDialog_PrivacyPolicyLink.Content" xml:space="preserve">
<value>Directiva de privacidad</value>
<value>Política de privacidad</value>
<comment>A hyperlink name for the Terminal's privacy policy</comment>
</data>
<data name="AboutDialog_ThirdPartyNoticesLink.Content" xml:space="preserve">
@@ -723,7 +723,7 @@
<value>Maximizar</value>
</data>
<data name="WindowRestoreDownButtonToolTip" xml:space="preserve">
<value>Restaurar a tamaño normal</value>
<value>Restaurar</value>
</data>
<data name="CommandPaletteMenuItem" xml:space="preserve">
<value>Paleta de comandos</value>
@@ -827,7 +827,7 @@
<value>Cerrar esta pestaña</value>
</data>
<data name="NewTabMenuFolderEmpty" xml:space="preserve">
<value>Vacío...</value>
<value>Vacío</value>
</data>
<data name="ClosePaneText" xml:space="preserve">
<value>Cerrar panel</value>
@@ -840,7 +840,7 @@
<comment>Text used to identify the reset button</comment>
</data>
<data name="MoveTabToNewWindowText" xml:space="preserve">
<value>Mover la Pestaña a una Nueva ventana</value>
<value>Mover pestaña a nueva ventana</value>
</data>
<data name="MoveTabToNewWindowToolTip" xml:space="preserve">
<value>Mueve la pestaña a una nueva ventana </value>

View File

@@ -187,13 +187,13 @@
<value>Volets multiples</value>
</data>
<data name="TabCloseSubMenu" xml:space="preserve">
<value>Fermez...</value>
<value>Fermer</value>
</data>
<data name="TabCloseAfter" xml:space="preserve">
<value>Fermer les Onglets à Droite</value>
<value>Fermer les onglets à droite</value>
</data>
<data name="TabCloseOther" xml:space="preserve">
<value>Fermez les Autres onglets</value>
<value>Fermer les autres onglets</value>
</data>
<data name="TabClose" xml:space="preserve">
<value>Fermer longlet</value>
@@ -205,16 +205,16 @@
<value>Fractionner longlet</value>
</data>
<data name="SplitPaneText" xml:space="preserve">
<value>Fractionner le volet...</value>
<value>Fractionner le volet</value>
</data>
<data name="SearchWebText" xml:space="preserve">
<value>Recherche web</value>
</data>
<data name="TabColorChoose" xml:space="preserve">
<value>Couleur...</value>
<value>Modifier la couleur de longlet</value>
</data>
<data name="TabColorCustomButton.Content" xml:space="preserve">
<value>Personnalisée...</value>
<value>Personnalisé</value>
</data>
<data name="TabColorClearButton.Content" xml:space="preserve">
<value>Réinitialiser</value>
@@ -464,7 +464,7 @@
<comment>This is the heading for a version number label</comment>
</data>
<data name="AboutDialog_GettingStartedLink.Content" xml:space="preserve">
<value>Prise en main</value>
<value>Bien démarrer</value>
<comment>A hyperlink name for a guide on how to get started using Terminal</comment>
</data>
<data name="AboutDialog_SourceCodeLink.Content" xml:space="preserve">
@@ -480,11 +480,11 @@
<comment>A hyperlink name for the Terminal's release notes</comment>
</data>
<data name="AboutDialog_PrivacyPolicyLink.Content" xml:space="preserve">
<value>Politique de confidentialité</value>
<value>Charte de confidentialité</value>
<comment>A hyperlink name for the Terminal's privacy policy</comment>
</data>
<data name="AboutDialog_ThirdPartyNoticesLink.Content" xml:space="preserve">
<value>Avis de tiers</value>
<value>Mentions tierces</value>
<comment>A hyperlink name for the Terminal's third-party notices</comment>
</data>
<data name="QuitDialog.CloseButtonText" xml:space="preserve">
@@ -723,7 +723,7 @@
<value>Agrandir</value>
</data>
<data name="WindowRestoreDownButtonToolTip" xml:space="preserve">
<value>Niveau inférieur</value>
<value>Restaurer</value>
</data>
<data name="CommandPaletteMenuItem" xml:space="preserve">
<value>Palette de commandes</value>
@@ -767,7 +767,7 @@
<value>Ne plus afficher</value>
</data>
<data name="ElevationShield.[using:Windows.UI.Xaml.Controls]ToolTipService.ToolTip" xml:space="preserve">
<value>Cette fenêtre de terminal sexécute en tant quAdministrateur</value>
<value>Cette fenêtre de terminal sexécute en tant quadministrateur</value>
</data>
<data name="CommandPalette_MatchesAvailable" xml:space="preserve">
<value>{0} suggestions trouvées</value>
@@ -827,7 +827,7 @@
<value>Fermer cet onglet</value>
</data>
<data name="NewTabMenuFolderEmpty" xml:space="preserve">
<value>Vide...</value>
<value>Vide</value>
</data>
<data name="ClosePaneText" xml:space="preserve">
<value>Fermer le volet</value>
@@ -846,7 +846,7 @@
<value>Déplacer l'onglet vers une nouvelle fenêtre </value>
</data>
<data name="RunAsAdminFlyout.Text" xml:space="preserve">
<value>Exécuter en tant qu'administrateur</value>
<value>Exécuter en temps qu'administrateur (restreint)</value>
<comment>This text is displayed on context menu for profile entries in add new tab button.</comment>
</data>
<data name="TerminalPage_PaneMovedAnnouncement_ExistingTab" xml:space="preserve">

View File

@@ -187,7 +187,7 @@
<value>Più riquadri</value>
</data>
<data name="TabCloseSubMenu" xml:space="preserve">
<value>Chiudi...</value>
<value>Chiudi</value>
</data>
<data name="TabCloseAfter" xml:space="preserve">
<value>Chiudi schede a destra</value>
@@ -199,7 +199,7 @@
<value>Chiudi scheda</value>
</data>
<data name="PaneClose" xml:space="preserve">
<value>Chiudi riquadro</value>
<value>Chiudi il riquadro</value>
</data>
<data name="SplitTabText" xml:space="preserve">
<value>Dividi scheda</value>
@@ -211,10 +211,10 @@
<value>Ricerca nel Web</value>
</data>
<data name="TabColorChoose" xml:space="preserve">
<value>Colore...</value>
<value>Cambia colore scheda</value>
</data>
<data name="TabColorCustomButton.Content" xml:space="preserve">
<value>Personalizzato...</value>
<value>Personalizzato</value>
</data>
<data name="TabColorClearButton.Content" xml:space="preserve">
<value>Reimposta</value>
@@ -421,13 +421,13 @@
<value>Apri nuova scheda</value>
</data>
<data name="NewPaneRun.Text" xml:space="preserve">
<value>ALT + clic per dividere la finestra corrente</value>
<value>ALT+CLIC per dividere la finestra corrente</value>
</data>
<data name="NewWindowRun.Text" xml:space="preserve">
<value>MAIUSC+clic per aprire una nuova finestra</value>
<value>MAIUSC+CLIC per aprire una nuova finestra</value>
</data>
<data name="ElevatedRun.Text" xml:space="preserve">
<value>CTRL+Clic per aprire come amministratore</value>
<value>CTRL+CLIC per aprire come amministratore</value>
</data>
<data name="WindowCloseButton.[using:Windows.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
<value>Chiudi</value>
@@ -464,7 +464,7 @@
<comment>This is the heading for a version number label</comment>
</data>
<data name="AboutDialog_GettingStartedLink.Content" xml:space="preserve">
<value>Attività iniziali</value>
<value>Introduzione</value>
<comment>A hyperlink name for a guide on how to get started using Terminal</comment>
</data>
<data name="AboutDialog_SourceCodeLink.Content" xml:space="preserve">
@@ -484,7 +484,7 @@
<comment>A hyperlink name for the Terminal's privacy policy</comment>
</data>
<data name="AboutDialog_ThirdPartyNoticesLink.Content" xml:space="preserve">
<value>Informative di terze parti</value>
<value>Comunicazioni di terze parti</value>
<comment>A hyperlink name for the Terminal's third-party notices</comment>
</data>
<data name="QuitDialog.CloseButtonText" xml:space="preserve">
@@ -723,7 +723,7 @@
<value>Ingrandisci</value>
</data>
<data name="WindowRestoreDownButtonToolTip" xml:space="preserve">
<value>Ripristina visualizzazione normale</value>
<value>Ripristina in basso</value>
</data>
<data name="CommandPaletteMenuItem" xml:space="preserve">
<value>Riquadro comandi</value>
@@ -830,7 +830,7 @@
<value>Vuoto</value>
</data>
<data name="ClosePaneText" xml:space="preserve">
<value>Chiudi riquadro</value>
<value>Chiudi il riquadro</value>
</data>
<data name="ClosePaneToolTip" xml:space="preserve">
<value>Chiude il riquadro attivo se sono presenti più riquadri</value>

View File

@@ -188,7 +188,7 @@
<value>複数ウィンドウ</value>
</data>
<data name="TabCloseSubMenu" xml:space="preserve">
<value>閉じる...</value>
<value>閉じる</value>
</data>
<data name="TabCloseAfter" xml:space="preserve">
<value>タブを右側に閉じる</value>
@@ -203,28 +203,28 @@
<value>ウィンドウを閉じる</value>
</data>
<data name="SplitTabText" xml:space="preserve">
<value>分割タブ</value>
<value>[分割] タブ</value>
</data>
<data name="SplitPaneText" xml:space="preserve">
<value>分割ウィンドウ</value>
<value>ウィンドウを分割する</value>
</data>
<data name="SearchWebText" xml:space="preserve">
<value>Web 検索</value>
</data>
<data name="TabColorChoose" xml:space="preserve">
<value>色...</value>
<value>タブの色の変更</value>
</data>
<data name="TabColorCustomButton.Content" xml:space="preserve">
<value>カスタム...</value>
<value>カスタム</value>
</data>
<data name="TabColorClearButton.Content" xml:space="preserve">
<value>リセット</value>
</data>
<data name="RenameTabText" xml:space="preserve">
<value>タブ名を変更</value>
<value>[名前の変更] タブ</value>
</data>
<data name="DuplicateTabText" xml:space="preserve">
<value>タブ複製</value>
<value>タブ複製する</value>
</data>
<data name="InvalidBackgroundImage" xml:space="preserve">
<value>無効な "backgroundImage" を持つプロファイルが見つかりました。既定では、そのプロファイルに背景画像はありません。"backgroundImage" を設定するときに、値が画像への有効なファイル パスとなっていることをご確認ください。</value>
@@ -485,7 +485,7 @@
<comment>A hyperlink name for the Terminal's privacy policy</comment>
</data>
<data name="AboutDialog_ThirdPartyNoticesLink.Content" xml:space="preserve">
<value>サードパーティに関する通知</value>
<value>サード パーティ通知</value>
<comment>A hyperlink name for the Terminal's third-party notices</comment>
</data>
<data name="QuitDialog.CloseButtonText" xml:space="preserve">
@@ -724,7 +724,7 @@
<value>最大化</value>
</data>
<data name="WindowRestoreDownButtonToolTip" xml:space="preserve">
<value>元に戻す</value>
<value>元に戻す (縮小)</value>
</data>
<data name="CommandPaletteMenuItem" xml:space="preserve">
<value>コマンド パレット</value>
@@ -759,7 +759,7 @@
<value>検索する</value>
</data>
<data name="PlainText" xml:space="preserve">
<value>プレーンテキスト</value>
<value>テキスト</value>
</data>
<data name="CloseOnExitInfoBar.Message" xml:space="preserve">
<value>終了動作は、プロファイルの詳細設定で構成できます。</value>
@@ -828,7 +828,7 @@
<value>このタブを閉じます</value>
</data>
<data name="NewTabMenuFolderEmpty" xml:space="preserve">
<value>空っぽ...</value>
<value>なし</value>
</data>
<data name="ClosePaneText" xml:space="preserve">
<value>ウィンドウを閉じる</value>
@@ -847,7 +847,7 @@
<value>タブを新しいウィンドウに移動 </value>
</data>
<data name="RunAsAdminFlyout.Text" xml:space="preserve">
<value>管理者として実行する</value>
<value>管理者として実行</value>
<comment>This text is displayed on context menu for profile entries in add new tab button.</comment>
</data>
<data name="TerminalPage_PaneMovedAnnouncement_ExistingTab" xml:space="preserve">

View File

@@ -118,7 +118,7 @@
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="InitialJsonParseErrorText" xml:space="preserve">
<value>파일에서 설정을 로드 하지 못했습니다. 후행 쉼표를 포함여 구문 오류가 있는지 확인 합니다.</value>
<value>파일에서 설정을 로드하지 못했습니다. 후행 쉼표를 포함여 구문 오류가 있는지 확인합니다.</value>
</data>
<data name="MissingDefaultProfileText" xml:space="preserve">
<value>첫 번째 프로필을 사용하여 프로필 목록에서 기본 프로필을 찾을 수 없습니다. "defaultProfile"이 프로필 중 하나의 GUID와 일치하는지 확인합니다.</value>
@@ -187,10 +187,10 @@
<value>여러 창</value>
</data>
<data name="TabCloseSubMenu" xml:space="preserve">
<value>닫기...</value>
<value>닫기</value>
</data>
<data name="TabCloseAfter" xml:space="preserve">
<value>오른쪽으로 탭 닫기</value>
<value>오른쪽에 있는 탭 닫기</value>
</data>
<data name="TabCloseOther" xml:space="preserve">
<value>다른 탭 닫기</value>
@@ -211,10 +211,10 @@
<value>웹 검색</value>
</data>
<data name="TabColorChoose" xml:space="preserve">
<value>색...</value>
<value>탭 색 변경</value>
</data>
<data name="TabColorCustomButton.Content" xml:space="preserve">
<value>사용자 정의...</value>
<value>사용자 정</value>
</data>
<data name="TabColorClearButton.Content" xml:space="preserve">
<value>다시 설정</value>
@@ -310,7 +310,7 @@
<value>상위 창의 백분율로 크기를 지정합니다. (0,1) 사이 값만 유효합니다.</value>
</data>
<data name="CmdNewTabDesc" xml:space="preserve">
<value>새 작업 만들기</value>
<value>새 만들기</value>
</data>
<data name="CmdNTDesc" xml:space="preserve">
<value>"new-tab" 하위 명령의 별칭입니다.</value>
@@ -454,7 +454,7 @@
<value>정보</value>
</data>
<data name="AboutDialog.PrimaryButtonText" xml:space="preserve">
<value>피드백 보내기</value>
<value>의견 보내기</value>
</data>
<data name="AboutDialog.CloseButtonText" xml:space="preserve">
<value>확인</value>
@@ -468,7 +468,7 @@
<comment>A hyperlink name for a guide on how to get started using Terminal</comment>
</data>
<data name="AboutDialog_SourceCodeLink.Content" xml:space="preserve">
<value>소스 코드</value>
<value>원본 코드</value>
<comment>A hyperlink name for the Terminal's documentation</comment>
</data>
<data name="AboutDialog_DocumentationLink.Content" xml:space="preserve">
@@ -480,11 +480,11 @@
<comment>A hyperlink name for the Terminal's release notes</comment>
</data>
<data name="AboutDialog_PrivacyPolicyLink.Content" xml:space="preserve">
<value>개인정보 취급방침</value>
<value>개인정보 보호정책</value>
<comment>A hyperlink name for the Terminal's privacy policy</comment>
</data>
<data name="AboutDialog_ThirdPartyNoticesLink.Content" xml:space="preserve">
<value>타사 통지 사항</value>
<value>타사 통지</value>
<comment>A hyperlink name for the Terminal's third-party notices</comment>
</data>
<data name="QuitDialog.CloseButtonText" xml:space="preserve">
@@ -515,7 +515,7 @@
<value>경고</value>
</data>
<data name="CloseReadOnlyDialog.Content" xml:space="preserve">
<value>읽기 전용 터미널을 닫으려고 합니다. 계속하시겠어요?</value>
<value>읽기 전용 터미널을 닫으려고 합니다. 계속하시겠습니까?</value>
</data>
<data name="LargePasteDialog.CloseButtonText" xml:space="preserve">
<value>취소</value>
@@ -571,7 +571,7 @@
<value>명령줄 구문 분석 오류:</value>
</data>
<data name="CommandPaletteControlName" xml:space="preserve">
<value>명령 도구 모음</value>
<value>명령 팔레트</value>
</data>
<data name="TabSwitcherControlName" xml:space="preserve">
<value>탭 전환기</value>
@@ -607,7 +607,7 @@
<comment>{0} will be replaced with a number.</comment>
</data>
<data name="CrimsonColorButton.[using:Windows.UI.Xaml.Controls]ToolTipService.ToolTip" xml:space="preserve">
<value>홍</value>
<value>홍</value>
</data>
<data name="SteelBlueColorButton.[using:Windows.UI.Xaml.Controls]ToolTipService.ToolTip" xml:space="preserve">
<value>강철색</value>
@@ -723,10 +723,10 @@
<value>최대화</value>
</data>
<data name="WindowRestoreDownButtonToolTip" xml:space="preserve">
<value>아래로 복원</value>
<value>이전 크기로 복원</value>
</data>
<data name="CommandPaletteMenuItem" xml:space="preserve">
<value>명령 도구 모음</value>
<value>명령 팔레트</value>
</data>
<data name="NotificationIconFocusTerminal" xml:space="preserve">
<value>포커스 터미널</value>
@@ -827,7 +827,7 @@
<value>이 탭 닫기</value>
</data>
<data name="NewTabMenuFolderEmpty" xml:space="preserve">
<value>비어 있음...</value>
<value>비어 있음</value>
</data>
<data name="ClosePaneText" xml:space="preserve">
<value>창 닫기</value>
@@ -840,13 +840,13 @@
<comment>Text used to identify the reset button</comment>
</data>
<data name="MoveTabToNewWindowText" xml:space="preserve">
<value>새 창으로 이동</value>
<value>탭을 새 창으로 이동</value>
</data>
<data name="MoveTabToNewWindowToolTip" xml:space="preserve">
<value>탭을 새 창으로 이동 </value>
</data>
<data name="RunAsAdminFlyout.Text" xml:space="preserve">
<value>관리자로 실행</value>
<value>관리자 권한으로 실행</value>
<comment>This text is displayed on context menu for profile entries in add new tab button.</comment>
</data>
<data name="TerminalPage_PaneMovedAnnouncement_ExistingTab" xml:space="preserve">

View File

@@ -187,34 +187,34 @@
<value>Vários painéis</value>
</data>
<data name="TabCloseSubMenu" xml:space="preserve">
<value>Fechar...</value>
<value>Fechar</value>
</data>
<data name="TabCloseAfter" xml:space="preserve">
<value>Fechar Guias à Direita</value>
<value>Fechar guias à direita</value>
</data>
<data name="TabCloseOther" xml:space="preserve">
<value>Fechar Outras Guias</value>
<value>Fechar outras guias</value>
</data>
<data name="TabClose" xml:space="preserve">
<value>Fechar guia</value>
</data>
<data name="PaneClose" xml:space="preserve">
<value>Fechar Painel</value>
<value>Fechar o painel</value>
</data>
<data name="SplitTabText" xml:space="preserve">
<value>Dividir Guia</value>
<value>Guia Dividir</value>
</data>
<data name="SplitPaneText" xml:space="preserve">
<value>Painel dividido</value>
<value>Dividir painel</value>
</data>
<data name="SearchWebText" xml:space="preserve">
<value>Pesquisa na web</value>
<value>Pesquisa na Web</value>
</data>
<data name="TabColorChoose" xml:space="preserve">
<value>Cor...</value>
<value>Alterar cor da guia</value>
</data>
<data name="TabColorCustomButton.Content" xml:space="preserve">
<value>Personalizados...</value>
<value>Personalizado</value>
</data>
<data name="TabColorClearButton.Content" xml:space="preserve">
<value>Restaurar</value>
@@ -223,7 +223,7 @@
<value>Renomear guia</value>
</data>
<data name="DuplicateTabText" xml:space="preserve">
<value>Duplicar Guia</value>
<value>Duplicar guia</value>
</data>
<data name="InvalidBackgroundImage" xml:space="preserve">
<value>Foi encontrado um perfil com um "backgroundImage" inválido. O perfil deve ser o padrão para que não haja nenhuma imagem de tela de fundo. Certifique-se de que, ao definir um "backgroundImage", o valor é um caminho de arquivo válido para uma imagem.</value>
@@ -454,7 +454,7 @@
<value>Sobre</value>
</data>
<data name="AboutDialog.PrimaryButtonText" xml:space="preserve">
<value>Enviar Comentários</value>
<value>Enviar comentários</value>
</data>
<data name="AboutDialog.CloseButtonText" xml:space="preserve">
<value>OK</value>
@@ -464,7 +464,7 @@
<comment>This is the heading for a version number label</comment>
</data>
<data name="AboutDialog_GettingStartedLink.Content" xml:space="preserve">
<value>Ponto de Partida</value>
<value>Introdução</value>
<comment>A hyperlink name for a guide on how to get started using Terminal</comment>
</data>
<data name="AboutDialog_SourceCodeLink.Content" xml:space="preserve">
@@ -484,7 +484,7 @@
<comment>A hyperlink name for the Terminal's privacy policy</comment>
</data>
<data name="AboutDialog_ThirdPartyNoticesLink.Content" xml:space="preserve">
<value>Avisos de terceiros</value>
<value>Avisos de Terceiros</value>
<comment>A hyperlink name for the Terminal's third-party notices</comment>
</data>
<data name="QuitDialog.CloseButtonText" xml:space="preserve">
@@ -571,10 +571,10 @@
<value>Falha ao analisar a linha de comando:</value>
</data>
<data name="CommandPaletteControlName" xml:space="preserve">
<value>Paleta de Comandos</value>
<value>Paleta de comandos</value>
</data>
<data name="TabSwitcherControlName" xml:space="preserve">
<value>Seletor de guias</value>
<value>Alternador de guias</value>
</data>
<data name="TabSwitcher_SearchBoxText" xml:space="preserve">
<value>Digite o nome da guia...</value>
@@ -726,7 +726,7 @@
<value>Restaurar Tamanho Original</value>
</data>
<data name="CommandPaletteMenuItem" xml:space="preserve">
<value>Paleta de Comandos</value>
<value>Paleta de comandos</value>
</data>
<data name="NotificationIconFocusTerminal" xml:space="preserve">
<value>Terminal de foco</value>
@@ -746,7 +746,7 @@
<value>Dividir a janela e iniciar em determinado diretório</value>
</data>
<data name="ExportTabText" xml:space="preserve">
<value>Exportar Texto</value>
<value>Exportar texto</value>
</data>
<data name="ExportFailure" xml:space="preserve">
<value>Falha ao exportar o conteúdo do terminal</value>
@@ -758,7 +758,7 @@
<value>Localizar</value>
</data>
<data name="PlainText" xml:space="preserve">
<value>Texto Simples</value>
<value>Texto sem formatação</value>
</data>
<data name="CloseOnExitInfoBar.Message" xml:space="preserve">
<value>O comportamento de término pode ser configurado nas configurações avançadas do perfil.</value>
@@ -767,7 +767,7 @@
<value>Não mostra de novo</value>
</data>
<data name="ElevationShield.[using:Windows.UI.Xaml.Controls]ToolTipService.ToolTip" xml:space="preserve">
<value>Esta janela do Terminal está funcionando como Administrador</value>
<value>Esta janela do Terminal está sendo executada como administrador</value>
</data>
<data name="CommandPalette_MatchesAvailable" xml:space="preserve">
<value>Sugestões encontradas: {0}</value>
@@ -827,10 +827,10 @@
<value>Fechar esta guia</value>
</data>
<data name="NewTabMenuFolderEmpty" xml:space="preserve">
<value>Vazio...</value>
<value>Vazio</value>
</data>
<data name="ClosePaneText" xml:space="preserve">
<value>Fechar Painel</value>
<value>Fechar o painel</value>
</data>
<data name="ClosePaneToolTip" xml:space="preserve">
<value>Feche o painel ativo se vários painéis estiverem presentes</value>
@@ -840,13 +840,13 @@
<comment>Text used to identify the reset button</comment>
</data>
<data name="MoveTabToNewWindowText" xml:space="preserve">
<value>Mover Guia para Nova Janela</value>
<value>Mover guia para nova janela</value>
</data>
<data name="MoveTabToNewWindowToolTip" xml:space="preserve">
<value>Move a guia para uma nova janela</value>
</data>
<data name="RunAsAdminFlyout.Text" xml:space="preserve">
<value>Executar como Administrador</value>
<value>Executar como administrador</value>
<comment>This text is displayed on context menu for profile entries in add new tab button.</comment>
</data>
<data name="TerminalPage_PaneMovedAnnouncement_ExistingTab" xml:space="preserve">
@@ -885,7 +885,7 @@
<value>Se definido, o comando será acrescentado ao comando padrão do perfil em vez de substituí-lo.</value>
</data>
<data name="RestartConnectionText" xml:space="preserve">
<value>Reiniciar Conexão</value>
<value>Reiniciar conexão</value>
</data>
<data name="RestartConnectionToolTip" xml:space="preserve">
<value>Reiniciar a conexão do painel ativo</value>

View File

@@ -191,43 +191,43 @@
<value>Мµļтíрłĕ φдпėŝ !!! !</value>
</data>
<data name="TabCloseSubMenu" xml:space="preserve">
<value>Ćļôŝέ... !!</value>
<value>Ćļôŝέ !</value>
</data>
<data name="TabCloseAfter" xml:space="preserve">
<value>Ċĺοşέ Ţаъş ťό ŧђé Яΐğђт !!! !!! </value>
<value>Ċĺοşέ ţаъş ťό ŧђé яΐğђт !!! !!! </value>
</data>
<data name="TabCloseOther" xml:space="preserve">
<value>Ćĺόѕ℮ Όтђèř Ŧâьś !!! !</value>
<value>Ćĺόѕ℮ őтђèř ŧâьś !!! !</value>
</data>
<data name="TabClose" xml:space="preserve">
<value>Сĺôšę Ťăв !!!</value>
<value>Сĺôšę ťăв !!!</value>
</data>
<data name="PaneClose" xml:space="preserve">
<value>Ćŀöśё Раņé !!!</value>
<value>Ćŀöśё ρаņé !!!</value>
</data>
<data name="SplitTabText" xml:space="preserve">
<value>Šрľīτ Τàв !!!</value>
<value>Šрľīτ τàв !!!</value>
</data>
<data name="SplitPaneText" xml:space="preserve">
<value>Šрŀіт Ρªňë !!!</value>
<value>Šрŀіт φªňë !!!</value>
</data>
<data name="SearchWebText" xml:space="preserve">
<value>Ẅёв Şĕаŕčĥ !!!</value>
<value>Ẅёв şĕаŕčĥ !!!</value>
</data>
<data name="TabColorChoose" xml:space="preserve">
<value>Ċõŀόř... !!</value>
<value>Ċħāņğě τāв ςōĺöя !!! !</value>
</data>
<data name="TabColorCustomButton.Content" xml:space="preserve">
<value>Ċµѕťøм... !!!</value>
<value>Ċµѕťøм !</value>
</data>
<data name="TabColorClearButton.Content" xml:space="preserve">
<value>Яěšěŧ !</value>
</data>
<data name="RenameTabText" xml:space="preserve">
<value>Γεñамē Ťãв !!!</value>
<value>Γεñамē ťãв !!!</value>
</data>
<data name="DuplicateTabText" xml:space="preserve">
<value>Ďϋφľіčάтέ Τàв !!! </value>
<value>Ďϋφľіčάтέ τàв !!! </value>
</data>
<data name="InvalidBackgroundImage" xml:space="preserve">
<value>₣σúŋδ ą φѓοƒĩļé ẃϊţħ äй ïηνàĺìď "backgroundImage". Đēƒãųŀŧϊпğ ťнªт φѓőƒĭļè το нªνе πō ьąçќġгθúпδ ιмãġė. Маĸē śμѓē ŧћäţ ẁђēή šêťτϊлġ å "backgroundImage", ţĥě νаłųё ïŝ ά νάľîď ƒĩŀê φąťħ ţŏ άń ΐмąġė. !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !</value>
@@ -462,7 +462,7 @@
<value>Åвōύţ !</value>
</data>
<data name="AboutDialog.PrimaryButtonText" xml:space="preserve">
<value>Ѕеηð ę℮đвäçк !!! </value>
<value>Ѕеηð ƒę℮đвäçк !!! </value>
</data>
<data name="AboutDialog.CloseButtonText" xml:space="preserve">
<value>ΦΚ </value>
@@ -472,11 +472,11 @@
<comment>This is the heading for a version number label</comment>
</data>
<data name="AboutDialog_GettingStartedLink.Content" xml:space="preserve">
<value>Ġеťтΐñĝ Ѕτдŗτęď !!! !</value>
<value>Ġеťтΐñĝ ѕτдŗτęď !!! !</value>
<comment>A hyperlink name for a guide on how to get started using Terminal</comment>
</data>
<data name="AboutDialog_SourceCodeLink.Content" xml:space="preserve">
<value>Ѕοџŗсė Çŏđе !!!</value>
<value>Ѕοџŗсė ¢ŏđе !!!</value>
<comment>A hyperlink name for the Terminal's documentation</comment>
</data>
<data name="AboutDialog_DocumentationLink.Content" xml:space="preserve">
@@ -484,15 +484,15 @@
<comment>A hyperlink name for user documentation</comment>
</data>
<data name="AboutDialog_ReleaseNotesLink.Content" xml:space="preserve">
<value>Ŗеľ℮àşε Ŋòτéš !!! </value>
<value>Ŗеľ℮àşε πòτéš !!! </value>
<comment>A hyperlink name for the Terminal's release notes</comment>
</data>
<data name="AboutDialog_PrivacyPolicyLink.Content" xml:space="preserve">
<value>Ρґїνãсÿ Рöĺĩςỳ !!! !</value>
<value>Ρґїνãсÿ ρöĺĩςỳ !!! !</value>
<comment>A hyperlink name for the Terminal's privacy policy</comment>
</data>
<data name="AboutDialog_ThirdPartyNoticesLink.Content" xml:space="preserve">
<value>Ţћĩřð-Ρářŧγ οŧīĉęŝ !!! !!!</value>
<value>Ţћĩřð-Ρářŧγ ñοŧīĉęŝ !!! !!!</value>
<comment>A hyperlink name for the Terminal's third-party notices</comment>
</data>
<data name="QuitDialog.CloseButtonText" xml:space="preserve">
@@ -579,10 +579,10 @@
<value>₣āіľ℮ď рàгśīпģ ¢бммäⁿδ ĺīñè: !!! !!! !!</value>
</data>
<data name="CommandPaletteControlName" xml:space="preserve">
<value>Ćσmmăηδ Рάŀĕтţ℮ !!! !</value>
<value>Ćσmmăηδ ράŀĕтţ℮ !!! !</value>
</data>
<data name="TabSwitcherControlName" xml:space="preserve">
<value>Τăь Ѕωîťςћêг !!! </value>
<value>Τăь ѕωîťςћêг !!! </value>
</data>
<data name="TabSwitcher_SearchBoxText" xml:space="preserve">
<value>Ţýρё ă тăъ пâmě... !!! !!</value>
@@ -731,10 +731,10 @@
<value>Μą×ìmϊżé !!</value>
</data>
<data name="WindowRestoreDownButtonToolTip" xml:space="preserve">
<value>Ŕèšŧòяё Ðǿẃи !!! </value>
<value>Ŕèšŧòяё ďǿẃи !!! </value>
</data>
<data name="CommandPaletteMenuItem" xml:space="preserve">
<value>Ċòмmāńδ Рªľėτťë !!! !</value>
<value>Ċòмmāńδ рªľėτťë !!! !</value>
</data>
<data name="NotificationIconFocusTerminal" xml:space="preserve">
<value>₣ôćűŝ Ţеґмĭйâŀ !!! !</value>
@@ -754,7 +754,7 @@
<value>Ŝρℓΐŧ ŧнė ẁίňďõŵ άпδ ŝţâґţ ίń ģįνëʼn δϊгέ¢ŧøяў !!! !!! !!! !!! !</value>
</data>
<data name="ExportTabText" xml:space="preserve">
<value>Ė×φōŗŧ Ţєхŧ !!!</value>
<value>Ė×φōŗŧ ţєхŧ !!!</value>
</data>
<data name="ExportFailure" xml:space="preserve">
<value>₣ăìľεď ťθ эхроґт ţеґmίñдļ ¢ōйт℮лť !!! !!! !!! </value>
@@ -766,7 +766,7 @@
<value>₣ìпđ !</value>
</data>
<data name="PlainText" xml:space="preserve">
<value>Ρĺáīň Тěхт !!!</value>
<value>Ρĺáīň тěхт !!!</value>
</data>
<data name="CloseOnExitInfoBar.Message" xml:space="preserve">
<value>Ťéямїлâŧîόň ь℮ћäνįőř čªή вĕ ċοñƒĩġџřèδ įŋ ăδνåл¢êð ряòƒιļє şėŧтіиĝś. !!! !!! !!! !!! !!! !!! !!</value>
@@ -775,7 +775,7 @@
<value>Ďόń'ţ šħόω ãĝάϊл !!! !</value>
</data>
<data name="ElevationShield.[using:Windows.UI.Xaml.Controls]ToolTipService.ToolTip" xml:space="preserve">
<value>Ţђіś Тĕřмїηǻℓ шĩⁿðöŵ ïѕ ѓüñňĩñģ ãŝ Ãðmĭⁿ !!! !!! !!! !!!</value>
<value>Ţђіś Тĕřмїηǻℓ шĩⁿðöŵ ïѕ ѓüñňĩñģ ãŝ áðmĭⁿîşŧŕãţθŕ !!! !!! !!! !!! !!</value>
</data>
<data name="CommandPalette_MatchesAvailable" xml:space="preserve">
<value>Ѕũğġεšтįóпş ƒōцʼnđ: {0} !!! !!! </value>
@@ -835,10 +835,10 @@
<value>Ĉłоśэ ťĥìŝ ţªъ !!! !</value>
</data>
<data name="NewTabMenuFolderEmpty" xml:space="preserve">
<value>Ёмφţγ... !!</value>
<value>Ёмφţγ !</value>
</data>
<data name="ClosePaneText" xml:space="preserve">
<value>Ĉĺοŝе Ρаиę !!!</value>
<value>Ĉĺοŝе φаиę !!!</value>
</data>
<data name="ClosePaneToolTip" xml:space="preserve">
<value>Çĺόś℮ τнĕ ă¢τίν℮ рáлĕ ιƒ mϋŀţїрĺë φàńęś άŗє рřęšеńт !!! !!! !!! !!! !!!</value>
@@ -848,13 +848,13 @@
<comment>Text used to identify the reset button</comment>
</data>
<data name="MoveTabToNewWindowText" xml:space="preserve">
<value>Мόνз Ţǻь ŧö П℮ω Щĭŋδōώ !!! !!! </value>
<value>Мόνз ţǻь ŧö ʼn℮ω ώĭŋδōώ !!! !!! </value>
</data>
<data name="MoveTabToNewWindowToolTip" xml:space="preserve">
<value>Мøνëŝ ŧªъ ŧǿ ã пεẃ шίŋđоẁ !!! !!! !</value>
</data>
<data name="RunAsAdminFlyout.Text" xml:space="preserve">
<value>Ŕμŋ ąś Āďmįиíšťґąţőя !!! !!!</value>
<value>Ŕμŋ ąś åďmįиíšťґąţőя !!! !!!</value>
<comment>This text is displayed on context menu for profile entries in add new tab button.</comment>
</data>
<data name="TerminalPage_PaneMovedAnnouncement_ExistingTab" xml:space="preserve">
@@ -893,7 +893,7 @@
<value>Ĩƒ šęţ, ŧнĕ ¢ömmдлδ ŵîĺł ьέ åφрєйδĕđ τσ ŧђė рřŏƒїłє'ş đзƒªūľţ ¢οmмăńδ іñѕţέáđ øƒ ѓēρļąċĭлĝ їţ. !!! !!! !!! !!! !!! !!! !!! !!! !!! !</value>
</data>
<data name="RestartConnectionText" xml:space="preserve">
<value>Γēѕŧâяŧ Ĉǿńńēčťїöл !!! !!</value>
<value>Γēѕŧâяŧ ćǿńńēčťїöл !!! !!</value>
</data>
<data name="RestartConnectionToolTip" xml:space="preserve">
<value>Γėşťáгţ ŧħ℮ ãčтĩνέ ρăйё сǿηńëςтιóņ !!! !!! !!! !</value>

View File

@@ -191,43 +191,43 @@
<value>Мµļтíрłĕ φдпėŝ !!! !</value>
</data>
<data name="TabCloseSubMenu" xml:space="preserve">
<value>Ćļôŝέ... !!</value>
<value>Ćļôŝέ !</value>
</data>
<data name="TabCloseAfter" xml:space="preserve">
<value>Ċĺοşέ Ţаъş ťό ŧђé Яΐğђт !!! !!! </value>
<value>Ċĺοşέ ţаъş ťό ŧђé яΐğђт !!! !!! </value>
</data>
<data name="TabCloseOther" xml:space="preserve">
<value>Ćĺόѕ℮ Όтђèř Ŧâьś !!! !</value>
<value>Ćĺόѕ℮ őтђèř ŧâьś !!! !</value>
</data>
<data name="TabClose" xml:space="preserve">
<value>Сĺôšę Ťăв !!!</value>
<value>Сĺôšę ťăв !!!</value>
</data>
<data name="PaneClose" xml:space="preserve">
<value>Ćŀöśё Раņé !!!</value>
<value>Ćŀöśё ρаņé !!!</value>
</data>
<data name="SplitTabText" xml:space="preserve">
<value>Šрľīτ Τàв !!!</value>
<value>Šрľīτ τàв !!!</value>
</data>
<data name="SplitPaneText" xml:space="preserve">
<value>Šрŀіт Ρªňë !!!</value>
<value>Šрŀіт φªňë !!!</value>
</data>
<data name="SearchWebText" xml:space="preserve">
<value>Ẅёв Şĕаŕčĥ !!!</value>
<value>Ẅёв şĕаŕčĥ !!!</value>
</data>
<data name="TabColorChoose" xml:space="preserve">
<value>Ċõŀόř... !!</value>
<value>Ċħāņğě τāв ςōĺöя !!! !</value>
</data>
<data name="TabColorCustomButton.Content" xml:space="preserve">
<value>Ċµѕťøм... !!!</value>
<value>Ċµѕťøм !</value>
</data>
<data name="TabColorClearButton.Content" xml:space="preserve">
<value>Яěšěŧ !</value>
</data>
<data name="RenameTabText" xml:space="preserve">
<value>Γεñамē Ťãв !!!</value>
<value>Γεñамē ťãв !!!</value>
</data>
<data name="DuplicateTabText" xml:space="preserve">
<value>Ďϋφľіčάтέ Τàв !!! </value>
<value>Ďϋφľіčάтέ τàв !!! </value>
</data>
<data name="InvalidBackgroundImage" xml:space="preserve">
<value>₣σúŋδ ą φѓοƒĩļé ẃϊţħ äй ïηνàĺìď "backgroundImage". Đēƒãųŀŧϊпğ ťнªт φѓőƒĭļè το нªνе πō ьąçќġгθúпδ ιмãġė. Маĸē śμѓē ŧћäţ ẁђēή šêťτϊлġ å "backgroundImage", ţĥě νаłųё ïŝ ά νάľîď ƒĩŀê φąťħ ţŏ άń ΐмąġė. !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !</value>
@@ -462,7 +462,7 @@
<value>Åвōύţ !</value>
</data>
<data name="AboutDialog.PrimaryButtonText" xml:space="preserve">
<value>Ѕеηð ę℮đвäçк !!! </value>
<value>Ѕеηð ƒę℮đвäçк !!! </value>
</data>
<data name="AboutDialog.CloseButtonText" xml:space="preserve">
<value>ΦΚ </value>
@@ -472,11 +472,11 @@
<comment>This is the heading for a version number label</comment>
</data>
<data name="AboutDialog_GettingStartedLink.Content" xml:space="preserve">
<value>Ġеťтΐñĝ Ѕτдŗτęď !!! !</value>
<value>Ġеťтΐñĝ ѕτдŗτęď !!! !</value>
<comment>A hyperlink name for a guide on how to get started using Terminal</comment>
</data>
<data name="AboutDialog_SourceCodeLink.Content" xml:space="preserve">
<value>Ѕοџŗсė Çŏđе !!!</value>
<value>Ѕοџŗсė ¢ŏđе !!!</value>
<comment>A hyperlink name for the Terminal's documentation</comment>
</data>
<data name="AboutDialog_DocumentationLink.Content" xml:space="preserve">
@@ -484,15 +484,15 @@
<comment>A hyperlink name for user documentation</comment>
</data>
<data name="AboutDialog_ReleaseNotesLink.Content" xml:space="preserve">
<value>Ŗеľ℮àşε Ŋòτéš !!! </value>
<value>Ŗеľ℮àşε πòτéš !!! </value>
<comment>A hyperlink name for the Terminal's release notes</comment>
</data>
<data name="AboutDialog_PrivacyPolicyLink.Content" xml:space="preserve">
<value>Ρґїνãсÿ Рöĺĩςỳ !!! !</value>
<value>Ρґїνãсÿ ρöĺĩςỳ !!! !</value>
<comment>A hyperlink name for the Terminal's privacy policy</comment>
</data>
<data name="AboutDialog_ThirdPartyNoticesLink.Content" xml:space="preserve">
<value>Ţћĩřð-Ρářŧγ οŧīĉęŝ !!! !!!</value>
<value>Ţћĩřð-Ρářŧγ ñοŧīĉęŝ !!! !!!</value>
<comment>A hyperlink name for the Terminal's third-party notices</comment>
</data>
<data name="QuitDialog.CloseButtonText" xml:space="preserve">
@@ -579,10 +579,10 @@
<value>₣āіľ℮ď рàгśīпģ ¢бммäⁿδ ĺīñè: !!! !!! !!</value>
</data>
<data name="CommandPaletteControlName" xml:space="preserve">
<value>Ćσmmăηδ Рάŀĕтţ℮ !!! !</value>
<value>Ćσmmăηδ ράŀĕтţ℮ !!! !</value>
</data>
<data name="TabSwitcherControlName" xml:space="preserve">
<value>Τăь Ѕωîťςћêг !!! </value>
<value>Τăь ѕωîťςћêг !!! </value>
</data>
<data name="TabSwitcher_SearchBoxText" xml:space="preserve">
<value>Ţýρё ă тăъ пâmě... !!! !!</value>
@@ -731,10 +731,10 @@
<value>Μą×ìmϊżé !!</value>
</data>
<data name="WindowRestoreDownButtonToolTip" xml:space="preserve">
<value>Ŕèšŧòяё Ðǿẃи !!! </value>
<value>Ŕèšŧòяё ďǿẃи !!! </value>
</data>
<data name="CommandPaletteMenuItem" xml:space="preserve">
<value>Ċòмmāńδ Рªľėτťë !!! !</value>
<value>Ċòмmāńδ рªľėτťë !!! !</value>
</data>
<data name="NotificationIconFocusTerminal" xml:space="preserve">
<value>₣ôćűŝ Ţеґмĭйâŀ !!! !</value>
@@ -754,7 +754,7 @@
<value>Ŝρℓΐŧ ŧнė ẁίňďõŵ άпδ ŝţâґţ ίń ģįνëʼn δϊгέ¢ŧøяў !!! !!! !!! !!! !</value>
</data>
<data name="ExportTabText" xml:space="preserve">
<value>Ė×φōŗŧ Ţєхŧ !!!</value>
<value>Ė×φōŗŧ ţєхŧ !!!</value>
</data>
<data name="ExportFailure" xml:space="preserve">
<value>₣ăìľεď ťθ эхроґт ţеґmίñдļ ¢ōйт℮лť !!! !!! !!! </value>
@@ -766,7 +766,7 @@
<value>₣ìпđ !</value>
</data>
<data name="PlainText" xml:space="preserve">
<value>Ρĺáīň Тěхт !!!</value>
<value>Ρĺáīň тěхт !!!</value>
</data>
<data name="CloseOnExitInfoBar.Message" xml:space="preserve">
<value>Ťéямїлâŧîόň ь℮ћäνįőř čªή вĕ ċοñƒĩġџřèδ įŋ ăδνåл¢êð ряòƒιļє şėŧтіиĝś. !!! !!! !!! !!! !!! !!! !!</value>
@@ -775,7 +775,7 @@
<value>Ďόń'ţ šħόω ãĝάϊл !!! !</value>
</data>
<data name="ElevationShield.[using:Windows.UI.Xaml.Controls]ToolTipService.ToolTip" xml:space="preserve">
<value>Ţђіś Тĕřмїηǻℓ шĩⁿðöŵ ïѕ ѓüñňĩñģ ãŝ Ãðmĭⁿ !!! !!! !!! !!!</value>
<value>Ţђіś Тĕřмїηǻℓ шĩⁿðöŵ ïѕ ѓüñňĩñģ ãŝ áðmĭⁿîşŧŕãţθŕ !!! !!! !!! !!! !!</value>
</data>
<data name="CommandPalette_MatchesAvailable" xml:space="preserve">
<value>Ѕũğġεšтįóпş ƒōцʼnđ: {0} !!! !!! </value>
@@ -835,10 +835,10 @@
<value>Ĉłоśэ ťĥìŝ ţªъ !!! !</value>
</data>
<data name="NewTabMenuFolderEmpty" xml:space="preserve">
<value>Ёмφţγ... !!</value>
<value>Ёмφţγ !</value>
</data>
<data name="ClosePaneText" xml:space="preserve">
<value>Ĉĺοŝе Ρаиę !!!</value>
<value>Ĉĺοŝе φаиę !!!</value>
</data>
<data name="ClosePaneToolTip" xml:space="preserve">
<value>Çĺόś℮ τнĕ ă¢τίν℮ рáлĕ ιƒ mϋŀţїрĺë φàńęś άŗє рřęšеńт !!! !!! !!! !!! !!!</value>
@@ -848,13 +848,13 @@
<comment>Text used to identify the reset button</comment>
</data>
<data name="MoveTabToNewWindowText" xml:space="preserve">
<value>Мόνз Ţǻь ŧö П℮ω Щĭŋδōώ !!! !!! </value>
<value>Мόνз ţǻь ŧö ʼn℮ω ώĭŋδōώ !!! !!! </value>
</data>
<data name="MoveTabToNewWindowToolTip" xml:space="preserve">
<value>Мøνëŝ ŧªъ ŧǿ ã пεẃ шίŋđоẁ !!! !!! !</value>
</data>
<data name="RunAsAdminFlyout.Text" xml:space="preserve">
<value>Ŕμŋ ąś Āďmįиíšťґąţőя !!! !!!</value>
<value>Ŕμŋ ąś åďmįиíšťґąţőя !!! !!!</value>
<comment>This text is displayed on context menu for profile entries in add new tab button.</comment>
</data>
<data name="TerminalPage_PaneMovedAnnouncement_ExistingTab" xml:space="preserve">
@@ -893,7 +893,7 @@
<value>Ĩƒ šęţ, ŧнĕ ¢ömmдлδ ŵîĺł ьέ åφрєйδĕđ τσ ŧђė рřŏƒїłє'ş đзƒªūľţ ¢οmмăńδ іñѕţέáđ øƒ ѓēρļąċĭлĝ їţ. !!! !!! !!! !!! !!! !!! !!! !!! !!! !</value>
</data>
<data name="RestartConnectionText" xml:space="preserve">
<value>Γēѕŧâяŧ Ĉǿńńēčťїöл !!! !!</value>
<value>Γēѕŧâяŧ ćǿńńēčťїöл !!! !!</value>
</data>
<data name="RestartConnectionToolTip" xml:space="preserve">
<value>Γėşťáгţ ŧħ℮ ãčтĩνέ ρăйё сǿηńëςтιóņ !!! !!! !!! !</value>

View File

@@ -191,43 +191,43 @@
<value>Мµļтíрłĕ φдпėŝ !!! !</value>
</data>
<data name="TabCloseSubMenu" xml:space="preserve">
<value>Ćļôŝέ... !!</value>
<value>Ćļôŝέ !</value>
</data>
<data name="TabCloseAfter" xml:space="preserve">
<value>Ċĺοşέ Ţаъş ťό ŧђé Яΐğђт !!! !!! </value>
<value>Ċĺοşέ ţаъş ťό ŧђé яΐğђт !!! !!! </value>
</data>
<data name="TabCloseOther" xml:space="preserve">
<value>Ćĺόѕ℮ Όтђèř Ŧâьś !!! !</value>
<value>Ćĺόѕ℮ őтђèř ŧâьś !!! !</value>
</data>
<data name="TabClose" xml:space="preserve">
<value>Сĺôšę Ťăв !!!</value>
<value>Сĺôšę ťăв !!!</value>
</data>
<data name="PaneClose" xml:space="preserve">
<value>Ćŀöśё Раņé !!!</value>
<value>Ćŀöśё ρаņé !!!</value>
</data>
<data name="SplitTabText" xml:space="preserve">
<value>Šрľīτ Τàв !!!</value>
<value>Šрľīτ τàв !!!</value>
</data>
<data name="SplitPaneText" xml:space="preserve">
<value>Šрŀіт Ρªňë !!!</value>
<value>Šрŀіт φªňë !!!</value>
</data>
<data name="SearchWebText" xml:space="preserve">
<value>Ẅёв Şĕаŕčĥ !!!</value>
<value>Ẅёв şĕаŕčĥ !!!</value>
</data>
<data name="TabColorChoose" xml:space="preserve">
<value>Ċõŀόř... !!</value>
<value>Ċħāņğě τāв ςōĺöя !!! !</value>
</data>
<data name="TabColorCustomButton.Content" xml:space="preserve">
<value>Ċµѕťøм... !!!</value>
<value>Ċµѕťøм !</value>
</data>
<data name="TabColorClearButton.Content" xml:space="preserve">
<value>Яěšěŧ !</value>
</data>
<data name="RenameTabText" xml:space="preserve">
<value>Γεñамē Ťãв !!!</value>
<value>Γεñамē ťãв !!!</value>
</data>
<data name="DuplicateTabText" xml:space="preserve">
<value>Ďϋφľіčάтέ Τàв !!! </value>
<value>Ďϋφľіčάтέ τàв !!! </value>
</data>
<data name="InvalidBackgroundImage" xml:space="preserve">
<value>₣σúŋδ ą φѓοƒĩļé ẃϊţħ äй ïηνàĺìď "backgroundImage". Đēƒãųŀŧϊпğ ťнªт φѓőƒĭļè το нªνе πō ьąçќġгθúпδ ιмãġė. Маĸē śμѓē ŧћäţ ẁђēή šêťτϊлġ å "backgroundImage", ţĥě νаłųё ïŝ ά νάľîď ƒĩŀê φąťħ ţŏ άń ΐмąġė. !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !</value>
@@ -462,7 +462,7 @@
<value>Åвōύţ !</value>
</data>
<data name="AboutDialog.PrimaryButtonText" xml:space="preserve">
<value>Ѕеηð ę℮đвäçк !!! </value>
<value>Ѕеηð ƒę℮đвäçк !!! </value>
</data>
<data name="AboutDialog.CloseButtonText" xml:space="preserve">
<value>ΦΚ </value>
@@ -472,11 +472,11 @@
<comment>This is the heading for a version number label</comment>
</data>
<data name="AboutDialog_GettingStartedLink.Content" xml:space="preserve">
<value>Ġеťтΐñĝ Ѕτдŗτęď !!! !</value>
<value>Ġеťтΐñĝ ѕτдŗτęď !!! !</value>
<comment>A hyperlink name for a guide on how to get started using Terminal</comment>
</data>
<data name="AboutDialog_SourceCodeLink.Content" xml:space="preserve">
<value>Ѕοџŗсė Çŏđе !!!</value>
<value>Ѕοџŗсė ¢ŏđе !!!</value>
<comment>A hyperlink name for the Terminal's documentation</comment>
</data>
<data name="AboutDialog_DocumentationLink.Content" xml:space="preserve">
@@ -484,15 +484,15 @@
<comment>A hyperlink name for user documentation</comment>
</data>
<data name="AboutDialog_ReleaseNotesLink.Content" xml:space="preserve">
<value>Ŗеľ℮àşε Ŋòτéš !!! </value>
<value>Ŗеľ℮àşε πòτéš !!! </value>
<comment>A hyperlink name for the Terminal's release notes</comment>
</data>
<data name="AboutDialog_PrivacyPolicyLink.Content" xml:space="preserve">
<value>Ρґїνãсÿ Рöĺĩςỳ !!! !</value>
<value>Ρґїνãсÿ ρöĺĩςỳ !!! !</value>
<comment>A hyperlink name for the Terminal's privacy policy</comment>
</data>
<data name="AboutDialog_ThirdPartyNoticesLink.Content" xml:space="preserve">
<value>Ţћĩřð-Ρářŧγ οŧīĉęŝ !!! !!!</value>
<value>Ţћĩřð-Ρářŧγ ñοŧīĉęŝ !!! !!!</value>
<comment>A hyperlink name for the Terminal's third-party notices</comment>
</data>
<data name="QuitDialog.CloseButtonText" xml:space="preserve">
@@ -579,10 +579,10 @@
<value>₣āіľ℮ď рàгśīпģ ¢бммäⁿδ ĺīñè: !!! !!! !!</value>
</data>
<data name="CommandPaletteControlName" xml:space="preserve">
<value>Ćσmmăηδ Рάŀĕтţ℮ !!! !</value>
<value>Ćσmmăηδ ράŀĕтţ℮ !!! !</value>
</data>
<data name="TabSwitcherControlName" xml:space="preserve">
<value>Τăь Ѕωîťςћêг !!! </value>
<value>Τăь ѕωîťςћêг !!! </value>
</data>
<data name="TabSwitcher_SearchBoxText" xml:space="preserve">
<value>Ţýρё ă тăъ пâmě... !!! !!</value>
@@ -731,10 +731,10 @@
<value>Μą×ìmϊżé !!</value>
</data>
<data name="WindowRestoreDownButtonToolTip" xml:space="preserve">
<value>Ŕèšŧòяё Ðǿẃи !!! </value>
<value>Ŕèšŧòяё ďǿẃи !!! </value>
</data>
<data name="CommandPaletteMenuItem" xml:space="preserve">
<value>Ċòмmāńδ Рªľėτťë !!! !</value>
<value>Ċòмmāńδ рªľėτťë !!! !</value>
</data>
<data name="NotificationIconFocusTerminal" xml:space="preserve">
<value>₣ôćűŝ Ţеґмĭйâŀ !!! !</value>
@@ -754,7 +754,7 @@
<value>Ŝρℓΐŧ ŧнė ẁίňďõŵ άпδ ŝţâґţ ίń ģįνëʼn δϊгέ¢ŧøяў !!! !!! !!! !!! !</value>
</data>
<data name="ExportTabText" xml:space="preserve">
<value>Ė×φōŗŧ Ţєхŧ !!!</value>
<value>Ė×φōŗŧ ţєхŧ !!!</value>
</data>
<data name="ExportFailure" xml:space="preserve">
<value>₣ăìľεď ťθ эхроґт ţеґmίñдļ ¢ōйт℮лť !!! !!! !!! </value>
@@ -766,7 +766,7 @@
<value>₣ìпđ !</value>
</data>
<data name="PlainText" xml:space="preserve">
<value>Ρĺáīň Тěхт !!!</value>
<value>Ρĺáīň тěхт !!!</value>
</data>
<data name="CloseOnExitInfoBar.Message" xml:space="preserve">
<value>Ťéямїлâŧîόň ь℮ћäνįőř čªή вĕ ċοñƒĩġџřèδ įŋ ăδνåл¢êð ряòƒιļє şėŧтіиĝś. !!! !!! !!! !!! !!! !!! !!</value>
@@ -775,7 +775,7 @@
<value>Ďόń'ţ šħόω ãĝάϊл !!! !</value>
</data>
<data name="ElevationShield.[using:Windows.UI.Xaml.Controls]ToolTipService.ToolTip" xml:space="preserve">
<value>Ţђіś Тĕřмїηǻℓ шĩⁿðöŵ ïѕ ѓüñňĩñģ ãŝ Ãðmĭⁿ !!! !!! !!! !!!</value>
<value>Ţђіś Тĕřмїηǻℓ шĩⁿðöŵ ïѕ ѓüñňĩñģ ãŝ áðmĭⁿîşŧŕãţθŕ !!! !!! !!! !!! !!</value>
</data>
<data name="CommandPalette_MatchesAvailable" xml:space="preserve">
<value>Ѕũğġεšтįóпş ƒōцʼnđ: {0} !!! !!! </value>
@@ -835,10 +835,10 @@
<value>Ĉłоśэ ťĥìŝ ţªъ !!! !</value>
</data>
<data name="NewTabMenuFolderEmpty" xml:space="preserve">
<value>Ёмφţγ... !!</value>
<value>Ёмφţγ !</value>
</data>
<data name="ClosePaneText" xml:space="preserve">
<value>Ĉĺοŝе Ρаиę !!!</value>
<value>Ĉĺοŝе φаиę !!!</value>
</data>
<data name="ClosePaneToolTip" xml:space="preserve">
<value>Çĺόś℮ τнĕ ă¢τίν℮ рáлĕ ιƒ mϋŀţїрĺë φàńęś άŗє рřęšеńт !!! !!! !!! !!! !!!</value>
@@ -848,13 +848,13 @@
<comment>Text used to identify the reset button</comment>
</data>
<data name="MoveTabToNewWindowText" xml:space="preserve">
<value>Мόνз Ţǻь ŧö П℮ω Щĭŋδōώ !!! !!! </value>
<value>Мόνз ţǻь ŧö ʼn℮ω ώĭŋδōώ !!! !!! </value>
</data>
<data name="MoveTabToNewWindowToolTip" xml:space="preserve">
<value>Мøνëŝ ŧªъ ŧǿ ã пεẃ шίŋđоẁ !!! !!! !</value>
</data>
<data name="RunAsAdminFlyout.Text" xml:space="preserve">
<value>Ŕμŋ ąś Āďmįиíšťґąţőя !!! !!!</value>
<value>Ŕμŋ ąś åďmįиíšťґąţőя !!! !!!</value>
<comment>This text is displayed on context menu for profile entries in add new tab button.</comment>
</data>
<data name="TerminalPage_PaneMovedAnnouncement_ExistingTab" xml:space="preserve">
@@ -893,7 +893,7 @@
<value>Ĩƒ šęţ, ŧнĕ ¢ömmдлδ ŵîĺł ьέ åφрєйδĕđ τσ ŧђė рřŏƒїłє'ş đзƒªūľţ ¢οmмăńδ іñѕţέáđ øƒ ѓēρļąċĭлĝ їţ. !!! !!! !!! !!! !!! !!! !!! !!! !!! !</value>
</data>
<data name="RestartConnectionText" xml:space="preserve">
<value>Γēѕŧâяŧ Ĉǿńńēčťїöл !!! !!</value>
<value>Γēѕŧâяŧ ćǿńńēčťїöл !!! !!</value>
</data>
<data name="RestartConnectionToolTip" xml:space="preserve">
<value>Γėşťáгţ ŧħ℮ ãčтĩνέ ρăйё сǿηńëςтιóņ !!! !!! !!! !</value>

View File

@@ -193,7 +193,7 @@
<value>Закрыть вкладки справа</value>
</data>
<data name="TabCloseOther" xml:space="preserve">
<value>Закрыть другие вкладки</value>
<value>Закрыть остальные вкладки</value>
</data>
<data name="TabClose" xml:space="preserve">
<value>Закрыть вкладку</value>
@@ -211,10 +211,10 @@
<value>Поиск в Интернете</value>
</data>
<data name="TabColorChoose" xml:space="preserve">
<value>Цвет...</value>
<value>Изменить цвет вкладки</value>
</data>
<data name="TabColorCustomButton.Content" xml:space="preserve">
<value>Настраиваемый...</value>
<value>Настраиваемый</value>
</data>
<data name="TabColorClearButton.Content" xml:space="preserve">
<value>Сбросить</value>
@@ -464,7 +464,7 @@
<comment>This is the heading for a version number label</comment>
</data>
<data name="AboutDialog_GettingStartedLink.Content" xml:space="preserve">
<value>Начало работы</value>
<value>Приступая к работе</value>
<comment>A hyperlink name for a guide on how to get started using Terminal</comment>
</data>
<data name="AboutDialog_SourceCodeLink.Content" xml:space="preserve">
@@ -484,7 +484,7 @@
<comment>A hyperlink name for the Terminal's privacy policy</comment>
</data>
<data name="AboutDialog_ThirdPartyNoticesLink.Content" xml:space="preserve">
<value>Уведомления сторонних производителей</value>
<value>Уведомления третьих лиц</value>
<comment>A hyperlink name for the Terminal's third-party notices</comment>
</data>
<data name="QuitDialog.CloseButtonText" xml:space="preserve">
@@ -723,7 +723,7 @@
<value>Развернуть</value>
</data>
<data name="WindowRestoreDownButtonToolTip" xml:space="preserve">
<value>Восстановить размер</value>
<value>Кнопка "Свернуть в окно"</value>
</data>
<data name="CommandPaletteMenuItem" xml:space="preserve">
<value>Палитра команд</value>
@@ -827,7 +827,7 @@
<value>Закрыть эту вкладку</value>
</data>
<data name="NewTabMenuFolderEmpty" xml:space="preserve">
<value>Пусто...</value>
<value>Очистить</value>
</data>
<data name="ClosePaneText" xml:space="preserve">
<value>Закрыть панель</value>

View File

@@ -187,7 +187,7 @@
<value>多个窗格</value>
</data>
<data name="TabCloseSubMenu" xml:space="preserve">
<value>关闭</value>
<value>关闭</value>
</data>
<data name="TabCloseAfter" xml:space="preserve">
<value>关闭右侧标签页</value>
@@ -208,13 +208,13 @@
<value>拆分窗格</value>
</data>
<data name="SearchWebText" xml:space="preserve">
<value>Web 搜索</value>
<value>网络搜索</value>
</data>
<data name="TabColorChoose" xml:space="preserve">
<value>颜色...</value>
<value>更改选项卡颜色</value>
</data>
<data name="TabColorCustomButton.Content" xml:space="preserve">
<value>自定义...</value>
<value>自定义</value>
</data>
<data name="TabColorClearButton.Content" xml:space="preserve">
<value>重置</value>
@@ -223,7 +223,7 @@
<value>重命名选项卡</value>
</data>
<data name="DuplicateTabText" xml:space="preserve">
<value>复制选项卡</value>
<value>复制标签页</value>
</data>
<data name="InvalidBackgroundImage" xml:space="preserve">
<value>找到一个具有无效 "backgroundImage" 的配置文件。将该配置文件设置为默认设置为不包含背景图像。请确保在设置 "backgroundImage" 时,该值是指向图像的有效文件路径。</value>
@@ -480,7 +480,7 @@
<comment>A hyperlink name for the Terminal's release notes</comment>
</data>
<data name="AboutDialog_PrivacyPolicyLink.Content" xml:space="preserve">
<value>隐私策</value>
<value>隐私策</value>
<comment>A hyperlink name for the Terminal's privacy policy</comment>
</data>
<data name="AboutDialog_ThirdPartyNoticesLink.Content" xml:space="preserve">
@@ -827,7 +827,7 @@
<value>关闭此选项卡</value>
</data>
<data name="NewTabMenuFolderEmpty" xml:space="preserve">
<value>空白...</value>
<value>空</value>
</data>
<data name="ClosePaneText" xml:space="preserve">
<value>关闭窗格</value>

View File

@@ -187,7 +187,7 @@
<value>多個窗格</value>
</data>
<data name="TabCloseSubMenu" xml:space="preserve">
<value>關閉...</value>
<value>關閉</value>
</data>
<data name="TabCloseAfter" xml:space="preserve">
<value>關閉右側的索引標籤</value>
@@ -202,19 +202,19 @@
<value>關閉窗格</value>
</data>
<data name="SplitTabText" xml:space="preserve">
<value>分割 Tab</value>
<value>分割索引標籤</value>
</data>
<data name="SplitPaneText" xml:space="preserve">
<value>分割窗格</value>
</data>
<data name="SearchWebText" xml:space="preserve">
<value>Web 搜尋</value>
<value>網頁搜尋</value>
</data>
<data name="TabColorChoose" xml:space="preserve">
<value>色彩...</value>
<value>變更索引標籤色彩</value>
</data>
<data name="TabColorCustomButton.Content" xml:space="preserve">
<value>自訂...</value>
<value>自訂</value>
</data>
<data name="TabColorClearButton.Content" xml:space="preserve">
<value>重設</value>
@@ -468,7 +468,7 @@
<comment>A hyperlink name for a guide on how to get started using Terminal</comment>
</data>
<data name="AboutDialog_SourceCodeLink.Content" xml:space="preserve">
<value>原始程式碼</value>
<value>原始碼</value>
<comment>A hyperlink name for the Terminal's documentation</comment>
</data>
<data name="AboutDialog_DocumentationLink.Content" xml:space="preserve">
@@ -480,11 +480,11 @@
<comment>A hyperlink name for the Terminal's release notes</comment>
</data>
<data name="AboutDialog_PrivacyPolicyLink.Content" xml:space="preserve">
<value>隱私權原則</value>
<value>隱私權政策</value>
<comment>A hyperlink name for the Terminal's privacy policy</comment>
</data>
<data name="AboutDialog_ThirdPartyNoticesLink.Content" xml:space="preserve">
<value>第三方聲明</value>
<value>第三方注意事項</value>
<comment>A hyperlink name for the Terminal's third-party notices</comment>
</data>
<data name="QuitDialog.CloseButtonText" xml:space="preserve">
@@ -827,7 +827,7 @@
<value>關閉此索引標籤</value>
</data>
<data name="NewTabMenuFolderEmpty" xml:space="preserve">
<value>空白...</value>
<value>空</value>
</data>
<data name="ClosePaneText" xml:space="preserve">
<value>關閉窗格</value>

View File

@@ -26,6 +26,11 @@ namespace winrt::TerminalApp::implementation
_root.Children().Append(_box);
}
void ScratchpadContent::UpdateSettings(const CascadiaSettings& /*settings*/)
{
// Nothing to do.
}
winrt::Windows::UI::Xaml::FrameworkElement ScratchpadContent::GetRoot()
{
return _root;
@@ -40,11 +45,21 @@ namespace winrt::TerminalApp::implementation
}
void ScratchpadContent::Close()
{
CloseRequested.raise(*this, nullptr);
}
NewTerminalArgs ScratchpadContent::GetNewTerminalArgs(const BuildStartupKind /* kind */) const
INewContentArgs ScratchpadContent::GetNewTerminalArgs(const BuildStartupKind /* kind */) const
{
return nullptr;
return BaseContentArgs(L"scratchpad");
}
winrt::hstring ScratchpadContent::Icon() const
{
static constexpr std::wstring_view glyph{ L"\xe70b" }; // QuickNote
return winrt::hstring{ glyph };
}
winrt::Windows::UI::Xaml::Media::Brush ScratchpadContent::BackgroundBrush()
{
return _root.Background();
}
}

View File

@@ -13,16 +13,21 @@ namespace winrt::TerminalApp::implementation
winrt::Windows::UI::Xaml::FrameworkElement GetRoot();
void UpdateSettings(const winrt::Microsoft::Terminal::Settings::Model::CascadiaSettings& settings);
winrt::Windows::Foundation::Size MinimumSize();
void Focus(winrt::Windows::UI::Xaml::FocusState reason = winrt::Windows::UI::Xaml::FocusState::Programmatic);
void Close();
winrt::Microsoft::Terminal::Settings::Model::NewTerminalArgs GetNewTerminalArgs(BuildStartupKind kind) const;
winrt::Microsoft::Terminal::Settings::Model::INewContentArgs GetNewTerminalArgs(BuildStartupKind kind) const;
winrt::hstring Title() { return L"Scratchpad"; }
uint64_t TaskbarState() { return 0; }
uint64_t TaskbarProgress() { return 0; }
bool ReadOnly() { return false; }
winrt::hstring Icon() const;
Windows::Foundation::IReference<winrt::Windows::UI::Color> TabColor() const noexcept { return nullptr; }
winrt::Windows::UI::Xaml::Media::Brush BackgroundBrush();
til::typed_event<> ConnectionStateChanged;
til::typed_event<IPaneContent> CloseRequested;

View File

@@ -0,0 +1,80 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#include "pch.h"
#include "SettingsPaneContent.h"
#include "Utils.h"
using namespace winrt::Windows::Foundation;
using namespace winrt::Windows::UI::Xaml;
using namespace winrt::Microsoft::Terminal::Settings::Model;
#define ASSERT_UI_THREAD() assert(_sui.Dispatcher().HasThreadAccess())
namespace winrt::TerminalApp::implementation
{
SettingsPaneContent::SettingsPaneContent(CascadiaSettings settings)
{
_sui = winrt::Microsoft::Terminal::Settings::Editor::MainPage{ settings };
// Stash away the current requested theme of the app. We'll need that in
// _BackgroundBrush() to do a theme-aware resource lookup
_requestedTheme = settings.GlobalSettings().CurrentTheme().RequestedTheme();
}
void SettingsPaneContent::UpdateSettings(const CascadiaSettings& settings)
{
ASSERT_UI_THREAD();
_sui.UpdateSettings(settings);
_requestedTheme = settings.GlobalSettings().CurrentTheme().RequestedTheme();
}
winrt::Windows::UI::Xaml::FrameworkElement SettingsPaneContent::GetRoot()
{
return _sui;
}
winrt::Windows::Foundation::Size SettingsPaneContent::MinimumSize()
{
return { 1, 1 };
}
void SettingsPaneContent::Focus(winrt::Windows::UI::Xaml::FocusState reason)
{
if (reason != FocusState::Unfocused)
{
_sui.as<Controls::Page>().Focus(reason);
}
}
void SettingsPaneContent::Close()
{
}
INewContentArgs SettingsPaneContent::GetNewTerminalArgs(const BuildStartupKind /*kind*/) const
{
return BaseContentArgs(L"settings");
}
winrt::hstring SettingsPaneContent::Icon() const
{
// This is the Setting icon (looks like a gear)
static constexpr std::wstring_view glyph{ L"\xE713" };
return winrt::hstring{ glyph };
}
Windows::Foundation::IReference<winrt::Windows::UI::Color> SettingsPaneContent::TabColor() const noexcept
{
return nullptr;
}
winrt::Windows::UI::Xaml::Media::Brush SettingsPaneContent::BackgroundBrush()
{
// Look up the color we should use for the settings tab item from our
// resources. This should only be used for when "terminalBackground" is
// requested.
static const auto key = winrt::box_value(L"SettingsUiTabBrush");
// You can't just do a Application::Current().Resources().TryLookup
// lookup, cause the app theme never changes! Do the hacky version
// instead.
return ThemeLookup(Application::Current().Resources(), _requestedTheme, key).try_as<winrt::Windows::UI::Xaml::Media::Brush>();
}
}

View File

@@ -0,0 +1,46 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#pragma once
#include "winrt/TerminalApp.h"
#include <LibraryResources.h>
namespace winrt::TerminalApp::implementation
{
class SettingsPaneContent : public winrt::implements<SettingsPaneContent, IPaneContent>
{
public:
SettingsPaneContent(winrt::Microsoft::Terminal::Settings::Model::CascadiaSettings settings);
void UpdateSettings(const winrt::Microsoft::Terminal::Settings::Model::CascadiaSettings& settings);
winrt::Windows::UI::Xaml::FrameworkElement GetRoot();
winrt::Microsoft::Terminal::Settings::Editor::MainPage SettingsUI() { return _sui; }
winrt::Windows::Foundation::Size MinimumSize();
void Focus(winrt::Windows::UI::Xaml::FocusState reason = winrt::Windows::UI::Xaml::FocusState::Programmatic);
void Close();
winrt::Microsoft::Terminal::Settings::Model::INewContentArgs GetNewTerminalArgs(const BuildStartupKind kind) const;
winrt::hstring Title() { return RS_(L"SettingsTab"); }
uint64_t TaskbarState() { return 0; }
uint64_t TaskbarProgress() { return 0; }
bool ReadOnly() { return false; }
winrt::hstring Icon() const;
Windows::Foundation::IReference<winrt::Windows::UI::Color> TabColor() const noexcept;
winrt::Windows::UI::Xaml::Media::Brush BackgroundBrush();
til::typed_event<> ConnectionStateChanged;
til::typed_event<IPaneContent> CloseRequested;
til::typed_event<IPaneContent, winrt::TerminalApp::BellEventArgs> BellRequested;
til::typed_event<IPaneContent> TitleChanged;
til::typed_event<IPaneContent> TabColorChanged;
til::typed_event<IPaneContent> TaskbarProgressChanged;
til::typed_event<IPaneContent> ReadOnlyChanged;
til::typed_event<IPaneContent> FocusRequested;
private:
winrt::Microsoft::Terminal::Settings::Editor::MainPage _sui{ nullptr };
winrt::Windows::UI::Xaml::ElementTheme _requestedTheme;
};
}

View File

@@ -1,131 +0,0 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#include "pch.h"
#include <LibraryResources.h>
#include "SettingsTab.h"
#include "SettingsTab.g.cpp"
#include "Utils.h"
using namespace winrt;
using namespace winrt::Windows::UI::Xaml;
using namespace winrt::Windows::UI::Core;
using namespace winrt::Microsoft::Terminal::Control;
using namespace winrt::Microsoft::Terminal::Settings::Model;
using namespace winrt::Microsoft::Terminal::Settings::Editor;
using namespace winrt::Windows::System;
namespace winrt
{
namespace MUX = Microsoft::UI::Xaml;
namespace WUX = Windows::UI::Xaml;
}
#define ASSERT_UI_THREAD() assert(TabViewItem().Dispatcher().HasThreadAccess())
namespace winrt::TerminalApp::implementation
{
SettingsTab::SettingsTab(MainPage settingsUI,
winrt::Windows::UI::Xaml::ElementTheme requestedTheme)
{
Content(settingsUI);
_requestedTheme = requestedTheme;
_MakeTabViewItem();
_CreateContextMenu();
_CreateIcon();
}
void SettingsTab::UpdateSettings(CascadiaSettings settings)
{
ASSERT_UI_THREAD();
auto settingsUI{ Content().as<MainPage>() };
settingsUI.UpdateSettings(settings);
// Stash away the current requested theme of the app. We'll need that in
// _BackgroundBrush() to do a theme-aware resource lookup
_requestedTheme = settings.GlobalSettings().CurrentTheme().RequestedTheme();
}
// Method Description:
// - Creates a list of actions that can be run to recreate the state of this tab
// Arguments:
// - asContent: unused. There's nothing different we need to do when
// serializing the settings tab for moving to another window. If we ever
// really want to support opening the SUI to a specific page, we can
// re-evaluate including that arg in this action then.
// Return Value:
// - The list of actions.
std::vector<ActionAndArgs> SettingsTab::BuildStartupActions(BuildStartupKind) const
{
ASSERT_UI_THREAD();
ActionAndArgs action;
action.Action(ShortcutAction::OpenSettings);
OpenSettingsArgs args{ SettingsTarget::SettingsUI };
action.Args(args);
return std::vector{ std::move(action) };
}
// Method Description:
// - Focus the settings UI
// Arguments:
// - focusState: The FocusState mode by which focus is to be obtained.
// Return Value:
// - <none>
void SettingsTab::Focus(WUX::FocusState focusState)
{
ASSERT_UI_THREAD();
_focusState = focusState;
if (_focusState != FocusState::Unfocused)
{
Content().as<WUX::Controls::Page>().Focus(focusState);
}
}
// Method Description:
// - Initializes a TabViewItem for this Tab instance.
// Arguments:
// - <none>
// Return Value:
// - <none>
void SettingsTab::_MakeTabViewItem()
{
TabBase::_MakeTabViewItem();
Title(RS_(L"SettingsTab"));
TabViewItem().Header(winrt::box_value(Title()));
}
// Method Description:
// - Set the icon on the TabViewItem for this tab.
// Arguments:
// - <none>
// Return Value:
// - <none>
void SettingsTab::_CreateIcon()
{
// This is the Setting icon (looks like a gear)
static constexpr std::wstring_view glyph{ L"\xE713" };
// The TabViewItem Icon needs MUX while the IconSourceElement in the CommandPalette needs WUX...
Icon(winrt::hstring{ glyph });
TabViewItem().IconSource(Microsoft::Terminal::UI::IconPathConverter::IconSourceMUX(glyph, false));
}
winrt::Windows::UI::Xaml::Media::Brush SettingsTab::_BackgroundBrush()
{
// Look up the color we should use for the settings tab item from our
// resources. This should only be used for when "terminalBackground" is
// requested.
static const auto key = winrt::box_value(L"SettingsUiTabBrush");
// You can't just do a Application::Current().Resources().TryLookup
// lookup, cause the app theme never changes! Do the hacky version
// instead.
return ThemeLookup(Application::Current().Resources(), _requestedTheme, key).try_as<winrt::Windows::UI::Xaml::Media::Brush>();
}
}

View File

@@ -1,43 +0,0 @@
/*++
Copyright (c) Microsoft Corporation
Licensed under the MIT license.
Module Name:
- SettingsTab.h
Abstract:
- The SettingsTab is a tab whose content is a Settings UI control. They can
coexist in a TabView with all other types of tabs, like the TerminalTab.
There should only be at most one SettingsTab open at any given time.
Author(s):
- Leon Liang - October 2020
--*/
#pragma once
#include "TabBase.h"
#include "SettingsTab.g.h"
namespace winrt::TerminalApp::implementation
{
struct SettingsTab : SettingsTabT<SettingsTab, TabBase>
{
public:
SettingsTab(winrt::Microsoft::Terminal::Settings::Editor::MainPage settingsUI,
winrt::Windows::UI::Xaml::ElementTheme requestedTheme);
void UpdateSettings(Microsoft::Terminal::Settings::Model::CascadiaSettings settings);
void Focus(winrt::Windows::UI::Xaml::FocusState focusState) override;
std::vector<Microsoft::Terminal::Settings::Model::ActionAndArgs> BuildStartupActions(BuildStartupKind kind) const override;
private:
winrt::Windows::UI::Xaml::ElementTheme _requestedTheme;
void _MakeTabViewItem() override;
void _CreateIcon();
virtual winrt::Windows::UI::Xaml::Media::Brush _BackgroundBrush() override;
};
}

Some files were not shown because too many files have changed in this diff Show More