Compare commits

..

30 Commits

Author SHA1 Message Date
Dustin L. Howett
3870d61a6f Merge remote-tracking branch 'origin/release-1.20' into selfhost-1.20 2024-04-16 10:41:57 -05:00
Windows Console Service Bot
6e3fc69ae2 Localization Updates - main - associated with #16886 (#17035)
(cherry picked from commit f4d8a74082)
Service-Card-Id: 92350383
Service-Version: 1.20
2024-04-16 10:41:39 -05:00
Harsh Narayan Jha
485b4ab2ab 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

(cherry picked from commit 8bd9578b3c)
Service-Card-Id: 92350387
Service-Version: 1.20
2024-04-16 10:36:49 -05:00
Dustin L. Howett
83bbd2cc1f Pre-merge #17049 (Backport Session Persistence) 2024-04-16 10:33:49 -05:00
Windows Console Service Bot
5a4508a79c Localization Updates - main - 04/06/2024 03:04:16 (#17025)
(cherry picked from commit b90eb93d26)
Service-Card-Id: 92279783
Service-Version: 1.20
2024-04-16 10:32:44 -05:00
Dustin L. Howett
3cfd13d01d 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.

(cherry picked from commit 2bcbe6b492)
Service-Card-Id: 92239368
Service-Version: 1.20
2024-04-16 10:32:44 -05:00
Leonard Hecker
275e8d115a Properly fix ConPTY buffer corking (#16793)
I've found that #16079 was never properly addressed (it still randomly
occurred after even after PR #16349), which later led to the issues
described in #16769 (nushell flickering due to too many flushes).

The crux of the fix is that this brings back the `_noFlushOnEnd` flag
that was removed in PR #15991. This is then combined with a change to
the cork API: An `uncork` on `VtEngine` now only flushes if `_Flush`
got called while it was corked in the first place.

`_noFlushOnEnd` prevents us from flushing in between two "unknown"
VT sequences (like soft fonts or FTCS) which prevents them from being
corrupted. The corking prevents the remaining cases of flushing too
often. Long-term, a proper fix would be to pass through VT unmodified.

Closes #16769

(cherry picked from commit 1ede023331)
Service-Card-Id: 91965217
Service-Version: 1.20
2024-04-16 10:32:44 -05:00
Leonard Hecker
d2862a8386 Backport session persistence improvements 2024-04-12 00:57:32 +02:00
Dustin L. Howett
a50eba1cc9 Remove the "set default terminal" banner (#16873)
**Default Terminal**: Everyone who cares to know, knows. Everyone who
doesn't, has an annoying bar above all terminals

I had to introduce a workaround for the fact that unknown dismissed
message keys in `state.json` result in Terminal exploding on launch.
😁 That's tracked in #16874.

Closes #11930 (but not in the way you'd expect)

(cherry picked from commit febfbebf9b)
Service-Card-Id: 92139784
Service-Version: 1.20
2024-03-21 15:45:29 -05:00
Isaac Blanco
98f675ec11 Update CommandPalette.cpp to ignore _filterTextChanged on TabSwitchMode (#16858)
As mentioned in #11146, when the "Next/Prev" command is executed from
the command line with a string in the search bar, this is setting always
the first tab.

When using the command "Next/Previous Tab" from the command line, we are
creating another tab (as if we are using the keyboard shortcut), and
this triggers the `_filterTextChanged` that resets the index to the
first item in because the current mode that it has.

This could be cause because, It seems that it detects as if we are
deleting the entered letter or creating an empty string, causing the
execution of the mentioned method and resetting its index to 0.

To avoid this, we are making sure that when this action is triggerd and
we are in the `TabSwitchMode`, we should ignore the following execution
of the method.

## Validation Steps Performed
I tested out the following scenarios:
1. Performing the action with the keyboard shorcut
2. Perfoming the action with an empty string
3. Performing the action with a string in the search bar.

Also validated with the current tests.

Closes #11146

(cherry picked from commit 806d5e2d05)
Service-Card-Id: 92139800
Service-Version: 1.20
2024-03-21 15:45:27 -05:00
Dustin L. Howett
f5a6cf6bf9 build: roll back to a build container with the 14.38 compiler (#16907)
The 14.39 compiler seems pretty busted.

Refs #16794

(cherry picked from commit ff47e0c257)
Service-Card-Id: 92139755
Service-Version: 1.20
2024-03-20 15:58:38 -05:00
Leonard Hecker
6ac8bd9ee6 Fix a ReadConsoleOutputCharacter regression (#16898)
The `nLength` parameter of `ReadConsoleOutputCharacterW` indicates
the number of columns that should be read. For single-column (narrow)
surrogate pairs this previously clipped a trailing character of the
returned string. In the major Unicode support update in #13626
surrogate pairs truly got stored as atomic units for the first time.
This now meant that a 120 column read with such codepoints resulted
in 121 characters. Other parts of conhost still assume UCS2 however,
and so this results in the entire read failing.

This fixes the issue by turning surrogate pairs into U+FFFD
which makes it UCS2 compatible.

Closes #16892

* Write U+F15C0 and read it back with `ReadConsoleOutputCharacterW`
* Read succeeds with a single U+FFFD 

(cherry picked from commit 373faf00c9)
Service-Card-Id: 92121912
Service-Version: 1.20
2024-03-20 15:58:36 -05:00
Windows Console Service Bot
4ee7f395bb Localization Updates - main - 03/08/2024 20:28:42 (#16847)
(cherry picked from commit c238416ae1)
Service-Card-Id: 92019656
Service-Version: 1.20
2024-03-08 15:06:36 -06:00
Dustin L. Howett
db2e8d6f93 Check the localizations into the project nightly (#16835)
Right now, the localization submission pipeline runs every night and
sends our localizable resources over to Touchdown. Later, release builds
pick up the localizations directly from Touchdown, move them into place,
and consume them.

This allowed us to avoid having localized content in the repository, but
it came with too many downsides:

- Users could not contribute additional localizations very easily
- We use the same release pipeline and Touchdown configuration for every
  branch, so strings needed to either slightly match or _entirely match_
  across an entire set of active release branches
- Building from day to day can pull in different strings, making the
  product not reproduceable
- Calling TDBuild during release builds requires network access from the
  build machine (so does restoring NuGet packages, but that's neither
  here nor there)
- Local developers and users could not test out other languages

This pull request moves all localization processing into the nightly
build phase and introduces support for checking loc in and submitting a
pull request. The pull request will not be created anew if one already
exists which has not been merged.

Anything we needed to do on release is now done overnight. This includes
moving loc files into the right places and merging the Cascadia
resources with the Context Menu resources (so that we can work around a
relatively lower amount of translations being chosen for the app versus
the context menu; see #12491 for more info.)

There are some smaller downsides to this approach and its
implementation:

- The first commit is going to be huge
- Right now, it only manages a single branch and uses a force push; if a
  PR is not reviewed timely, it will be force-pushed and you cannot see
  the day-to-day changes in the strings. Hopefully there won't be any.

I've taken great care to ensure that repeated runs of this new pipeline
will not result in unnecessary whitespace changes. This required
changing how we merge ContextMenu.resw into CascadiaPackage to always
use the .NET XmlWriter with specific flags.

NOTE that this does not allow users to _contribute_ translation fixes
for the 10 languages which we are importing. We will still need to pull
changes out of those files and submit them as bugs to the localization
team separately, and hope they come back around in another nightly
build. However, there is no reason users cannot contribute
_non-Touchdown_ languages.

(cherry picked from commit ab4b140aa4)
Service-Card-Id: 92019665
Service-Version: 1.20
2024-03-08 15:06:35 -06:00
James Holderness
4234fe48a1 Fix conpty rendering of control characters in the buffer (#16825)
When using the legacy console APIs, it's possible to write arbitrary
codepoints into the buffer. If any of those codepoints are in the C0 or
C1 range, and the buffer contents are forwarded over conpty, they can
end up mistakenly interpreted as controls by the connected terminal.

This PR fixes that issue by converting any C0 and C1 codepoints in the
buffer into printable glyphs before forwarding them over conpty. I've
used the C0 glyphs from the DOS 437 codepage and just a `?` for the C1
codepoints, since that's what you would typically have seen in the v1
console with a raster font.

Although this doesn't address the main problem in #16410, it should at
least fix the rendering issues they're seeing when running their app in
Windows Terminal.

I've confirmed that the test case in #4363 now looks the same in Windows
Terminal as it does in conhost, and I've tested the Windows version of
the terminal game [Gorched], and confirmed that it now works correctly
in Window Terminal.

[Gorched]: https://github.com/zladovan/gorched

Closes #4363
Closes #6265

(cherry picked from commit 563b7312b6)
Service-Card-Id: 92001662
Service-Version: 1.20
2024-03-08 15:06:33 -06:00
Leonard Hecker
c9e226e1c9 Fix bugs in CharToColumnMapper (#16787)
Aside from overall simplifying `CharToColumnMapper` this fixes 2 bugs:
* The backward search loop may have iterated 1 column too far,
  because it didn't stop at `*current <= *target`, but rather at
  `*(current - 1) <= *target`. This issue was only apparent when
  surrogate pairs were being used in a row.
* When the target offset is that of a trailing surrogate pair
  the forward search loop may have iterated 1 column too far.
  It's somewhat unlikely for this to happen since this code is
  only used through ICU, but you never know.

This is a continuation of PR #16775.

(cherry picked from commit 043d5cd484)
Service-Card-Id: 91955569
Service-Version: 1.20
2024-02-29 16:35:52 -06:00
Leonard Hecker
4706697627 AtlasEngine: Improve dotted, dashed and curly underlines (#16719)
This changeset makes 3 improvements:
* Dotted lines now use a 2:1 ratio between gaps and dots (from 1:1).
  This makes the dots a lot easier to spot at small font sizes.
* Dashed lines use a 1:2 ratio and a cells-size independent stride.
  By being cell-size independent it works more consistently with a
  wider variety of fonts with weird cell aspect ratios.
* Curly lines are now cell-size independent as well and have a
  height that equals the double-underline size.
  This ensures that the curve isn't cut off anymore and just like
  with dashed lines, that it works under weird aspect ratios.

Closes #16712

## Validation Steps Performed
This was tested using RenderingTests using Cascadia Mono, Consolas,
Courier New, Lucida Console and MS Gothic.

(cherry picked from commit 9c8058c326)
Service-Card-Id: 91922826
Service-Version: 1.20
2024-02-26 11:51:31 -06:00
Dustin L. Howett
07c6168c9e build: add a tsa configuration for asyncSdl (#16728)
(cherry picked from commit e3ff44bb82)
Service-Card-Id: 91922823
Service-Version: 1.20
2024-02-26 11:51:29 -06:00
Dustin L. Howett
190c76afe0 build: switch to NuGetAuthenticate@1 (#16752)
It keeps warning us that v0 has been deprecated.

(cherry picked from commit 6b29ef51e3)
Service-Card-Id: 91903283
Service-Version: 1.20
2024-02-26 11:44:03 -06:00
Dustin Howett
774e74ae77 Merge remote-tracking branch 'origin/release-1.19' into release-1.20 2024-02-26 11:25:12 -06:00
Leonard Hecker
a2521cc3ef Fix an apparent x86 miscompilation on MSVC 19.38 (#16742)
There's an apparent miscompilation of `dynamic_bitset` on x86 with
MSVC 19.38, where the following code:
```cpp
dynamic_bitset<uint64_t> bits(80 * 24, 0);
bits.set(0, 3 * 80, true);
```

is expected to set the first 3.75 blocks to 1 which should produce
the following blocks:
```
0xffffffffffffffff
0xffffffffffffffff
0xffffffffffffffff
0x0000ffffffffffff
```

but it actually produces:
```
0xffffffffffffffff
0x00000000ffffffff
0xffffffffffffffff
0x0000ffffffffffff
```

The weird thing here is that this only happens if `til::bitmap`
uses a `dynamic_bitset<uint64_t>`. As soon as it uses `<uint32_t>`
any other instantiation of `<uint64_t>` is magically fixed.

Conclusion: Use `size_t` until we know what's going on.
Last known good CL version: 14.37.32822
Current broken CL version: 14.38.33130

## Validation Steps Performed

The following test completes successfully again:
```cpp
til::bitmap map{ { 80, 24 } };
map.translate({ 0, 3 }, true);
VERIFY_ARE_EQUAL(3u, map.runs().size());
```

(cherry picked from commit d3ec47a7fc)
Service-Card-Id: 91885584
Service-Version: 1.20
2024-02-21 11:54:55 -06:00
Leonard Hecker
4c681449cd COOKED_READ: Fix tab not erasing the prompt (#16718)
Write "<command that doesn't exist> foo" in cmd.exe, move yours cursor
past the <command> and press tab. The "foo" will still be there but
will be inaccessible. This commit fixes the issue. As far as I can
tell, this never worked in any conhost version ever.

Closes #16704

(cherry picked from commit 5e9f223a6c)
Service-Card-Id: 91851715
Service-Version: 1.20
2024-02-21 11:53:42 -06:00
Dustin L. Howett
427135aeca Upgrade Microsoft.Windows.ImplementationLibrary to 1.0.240122.1 (#16617)
This includes a fix for the hang on shutdown due to the folder change
reader.

WIL now validates format strings in `LOG...` macros (yay!) and so we
needed to fix some of our `LOG` macros.

Closes #16456

(cherry picked from commit ce30e7c89c)
Service-Card-Id: 91892152
Service-Version: 1.20
2024-02-21 11:53:41 -06:00
Sarim Khan
dcbc17bdbd schema: add experimental.repositionCursorWithMouse (#16652)
Add experimental.repositionCursorWithMouse to profiles.schema.json. So
when editing settings.json with vscode, it autocompletes and don't
complain.

(cherry picked from commit d3a18b9041)
Service-Card-Id: 91808635
Service-Version: 1.20
2024-02-21 11:46:26 -06:00
e82eric
b520c80067 Fix for search selections highlight going backward when the selection wraps to next line (#16691)
Hi, I realized I had a bug in my pull request for search selections
where when the highlight is wrapped it causes the selection to select
back to start of the current line instead of wrapping to the next line.

PR where I introduced this bug: #16227

(cherry picked from commit bef234081a)
Service-Card-Id: 91808626
Service-Version: 1.20
2024-02-21 11:46:25 -06:00
Mike Griese
f01fb266bd Disable DECKPAM mode behind velocity (#16675)
DECKPAM originally tracked in #16506.
Support was added in #16511.
But turns out people didn't expect the Terminal to actually be like,
compliant: #16654

This closes #16654 while we think over in #16672 how we want to solve
this

(cherry picked from commit 71efdcb21b)
Service-Card-Id: 91781164
Service-Version: 1.20
2024-02-21 11:46:24 -06:00
James Holderness
f13ba96e98 Improve handling of Space key combinations (#16645)
This fixes two issues where the `Space` key wasn't being handled
correctly:

* Keyboards with an `AltGr`+`Space` mapping were not generating the
  expected character.
* Pressing a dead key followed by `Space` is supposed to generate the
  accent character associated with that key, but it wasn't doing so.

## References and Relevant Issues

These were both regressions from the keyboard refactor in PR #16511.

## Detailed Description of the Pull Request / Additional comments

The problem was that we were treating `VK_SPACE` as a "functional" key,
which means it gets hardcoded VT mappings which take precedence over
whatever is in the keyboard layout. This was deemed necessary to deal
with the fact that many keyboards incorrectly map `Ctrl`+`Space` as a
`SP` character, when it's expected to be `NUL`.

I've now dropped `VK_SPACE` from the functional mapping table and allow
it be handled by the default mapping algorithm for "graphic" keys.
However, I've also introduced a special case check for `Ctrl`+`Space`
(and other modifier variants), so we can bypass any incorrect keyboard
layouts for those combinations.

## Validation Steps Performed

I couldn't test with a French-BEPO keyboard layout directly, because the
MS Keyboard Layout Creator wouldn't accept a `Space` key mapping that
wasn't whitespace. However, if I remapped the `AltGr`+`Space` combo to
`LF`, I could confirm that we are now generating that correctly.

I've also tested the dead key `Space` combination on various keyboard
layouts and confirmed that that is now working correctly, and checked
that the `Ctrl`+`Space` combinations are still working too.

Closes #16641
Closes #16642

(cherry picked from commit ec91be5995)
Service-Card-Id: 91738880
Service-Version: 1.20
2024-02-21 11:46:23 -06:00
Leonard Hecker
70ac08f264 Restore support for pasting files (#16634)
TIL: You could Ctrl+V files into Windows Terminal and here I am,
always opening the context menu and selecting "Copy as path"... smh

This restores the support by adding a very rudimentary HDROP handler.
The flip side of the regression is that I learned about this and so
conhost also gets this now, because why not!

Closes #16627

## Validation Steps Performed
* Single files can be pasted in WT and conhost 

(cherry picked from commit ef96e225da)
Service-Card-Id: 91727726
Service-Version: 1.20
2024-02-21 11:46:22 -06:00
Leonard Hecker
29a46c36f6 Fix a bug caused by #16592 (#16624)
#16592 passes the return value of `GetEnvironmentStringsW` directly
to the `hstring` constructor even though the former returns a
double-null terminated string and the latter expects a regular one.

This PR fixes the issue by using a basic strlen() loop to compute
the length ourselves. It's still theoretically beneficial over
the previous code, but now it's rather bitter since the code isn't
particularly short anymore and so the biggest benefit is gone.

Closes #16623

## Validation Steps Performed
* Validated the `env` string in a debugger 
  It's 1 character shorter than the old `til::env` string.
  That's fine however, since any `HSTRING` is always null-terminated
  anyways and so we get an extra null-terminator for free.
* `wt powershell` works 

(cherry picked from commit c669afe2a0)
Service-Card-Id: 91719863
Service-Version: 1.20
2024-01-30 18:25:36 -06:00
Dustin L. Howett
d5a3499ed9 build: remove symbols' dependency on the Package phase (#16625)
Due to things outside our control, sometimes the Package phase fails
when VPack publication is enabled. Because of this, symbols won't be
published. We still want these builds to be considered "golden" and we
are still shipping them, so we *must* publish symbols.

(cherry picked from commit bcca7aac1b)
Service-Card-Id: 91719596
Service-Version: 1.20
2024-01-30 18:25:35 -06:00
704 changed files with 36470 additions and 36688 deletions

View File

@@ -18,8 +18,6 @@ consvc
copyable
Counterintuitively
CtrlDToClose
CVS
CUI
cybersecurity
dalet
Dcs
@@ -80,28 +78,22 @@ mnt
mru
nje
noreply
notwrapped
ogonek
ok'd
overlined
perlw
pipeline
postmodern
Powerline
powerline
ptys
pwshw
qof
qps
Remappings
Retargets
rclt
reimplementation
reserialization
reserialize
reserializes
rlig
rubyw
runtimes
servicebus
shcha
@@ -122,7 +114,6 @@ toolset
truthiness
tshe
ubuntu
UEFI
uiatextrange
UIs
und

View File

@@ -1,12 +1,9 @@
aalt
abvm
ACCEPTFILES
ACCESSDENIED
acl
aclapi
alignas
alignof
allocconsolewithoptions
APPLYTOSUBMENUS
appxrecipe
bitfield
@@ -24,9 +21,7 @@ COLORPROPERTY
colspan
COMDLG
commandlinetoargv
commoncontrols
comparand
COPYFROMRESOURCE
cstdint
CXICON
CYICON
@@ -38,7 +33,6 @@ delayimp
DERR
dlldata
DNE
dnom
DONTADDTORECENT
DWMSBT
DWMWA
@@ -47,12 +41,10 @@ endfor
ENDSESSION
enumset
environstrings
EXACTSIZEONLY
EXPCMDFLAGS
EXPCMDSTATE
filetime
FILTERSPEC
fina
FORCEFILESYSTEM
FORCEMINIMIZE
frac
@@ -66,7 +58,6 @@ Hashtable
HIGHCONTRASTON
HIGHCONTRASTW
hinternet
HIGHQUALITYSCALE
HINTERNET
hotkeys
href
@@ -83,7 +74,6 @@ IBox
IClass
IComparable
IComparer
ICONINFO
IConnection
ICustom
IDialog
@@ -93,7 +83,6 @@ IExplorer
IFACEMETHOD
IFile
IGraphics
IImage
IInheritable
IMap
IMonarch
@@ -124,7 +113,6 @@ LSHIFT
LTGRAY
MAINWINDOW
MAXIMIZEBOX
medi
memchr
memicmp
MENUCOMMAND
@@ -155,7 +143,6 @@ NOTIFYBYPOS
NOTIFYICON
NOTIFYICONDATA
ntprivapi
numr
oaidl
ocidl
ODR
@@ -169,7 +156,6 @@ OUTLINETEXTMETRICW
overridable
PACL
PAGESCROLL
PALLOC
PATINVERT
PEXPLICIT
PICKFOLDERS
@@ -181,11 +167,9 @@ REGCLS
RETURNCMD
rfind
RLO
rnrn
ROOTOWNER
roundf
RSHIFT
rvrn
SACL
schandle
SEH

View File

@@ -1,8 +1,6 @@
ACLs
ADMINS
advapi
akv
AKV
altform
altforms
appendwttlogging
@@ -16,14 +14,12 @@ autoexec
backplating
bitmaps
BOMs
checkcflags
COMPUTERNAME
CPLs
cpptools
cppvsdbg
CPRs
cryptbase
cscript
DACL
DACLs
defaultlib
@@ -50,7 +46,6 @@ MSAA
msixbundle
MSVC
MSVCP
mtu
muxc
netcore
Onefuzz
@@ -95,13 +90,10 @@ Virtualization
visualstudio
vscode
VSTHRD
WINBASEAPI
winsdkver
wlk
wscript
wslpath
wtl
wtt
wttlog
Xamarin
xfgcheck

View File

@@ -115,7 +115,6 @@
^src/terminal/parser/ut_parser/Base64Test.cpp$
^src/terminal/parser/ut_parser/run\.bat$
^src/tools/benchcat
^src/tools/ConsoleBench
^src/tools/integrity/dirs$
^src/tools/integrity/packageuwp/ConsoleUWP\.appxSources$
^src/tools/RenderingTests/main\.cpp$

View File

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

View File

@@ -1,4 +1,3 @@
aaaaabbb
aabbcc
ABANDONFONT
abbcc
@@ -10,7 +9,6 @@ ACCESSTOKEN
acidev
ACIOSS
ACover
acp
actctx
ACTCTXW
ADDALIAS
@@ -68,10 +66,10 @@ ASBSET
asdfghjkl
ASetting
ASingle
ASYNCDONTCARE
ASYNCWINDOWPOS
atch
ATest
ATTRCOLOR
aumid
Authenticode
AUTOBUDDY
@@ -93,9 +91,8 @@ backgrounding
backported
backstory
barbaz
Batang
Bazz
bbb
bbccb
BBDM
bbwe
bcount
@@ -125,6 +122,8 @@ Blt
BLUESCROLL
BODGY
BOLDFONT
BOOLIFY
bools
Borland
boutput
boxheader
@@ -155,6 +154,7 @@ cazamor
CBash
cbiex
CBN
CBoolean
cbt
CCCBB
cch
@@ -162,9 +162,12 @@ CCHAR
CCmd
ccolor
CCom
CComp
CConsole
CConversion
CCRT
cdd
CEdit
CELLSIZE
cfae
cfie
@@ -174,17 +177,18 @@ CFuzz
cgscrn
chafa
changelists
chaof
charinfo
CHARSETINFO
chcbpat
chh
chshdng
CHT
CLASSSTRING
Cic
CLE
cleartype
CLICKACTIVE
clickdown
CLIENTID
clipbrd
CLIPCHILDREN
CLIPSIBLINGS
@@ -193,6 +197,7 @@ cloudconsole
cloudvault
CLSCTX
clsids
CLUSTERMAP
cmatrix
cmder
CMDEXT
@@ -208,6 +213,7 @@ codepages
codepath
coinit
colorizing
COLORMATRIX
COLORREFs
colorschemes
colorspec
@@ -215,14 +221,17 @@ colortable
colortbl
colortest
colortool
COLR
combaseapi
comctl
commandline
commctrl
commdlg
COMMITID
commoncontrols
componentization
conapi
conareainfo
conattrs
conbufferout
concfg
@@ -233,7 +242,8 @@ condrv
conechokey
conemu
conhost
CONIME
conime
conimeinfo
conintegrity
conintegrityuwp
coninteractivitybase
@@ -245,7 +255,6 @@ CONKBD
conlibk
conmsgl
CONNECTINFO
connyection
CONOUT
conprops
conpropsp
@@ -272,9 +281,11 @@ contentfiles
conterm
contsf
contypes
convarea
conwinuserrefs
coordnew
COPYCOLOR
COPYFROMRESOURCE
CORESYSTEM
cotaskmem
countof
@@ -306,6 +317,7 @@ csrutil
CSTYLE
CSwitch
CTerminal
CText
ctl
ctlseqs
CTRLEVENT
@@ -313,7 +325,7 @@ CTRLFREQUENCY
CTRLKEYSHORTCUTS
Ctrls
CTRLVOLUME
CUAS
Ctxt
CUF
cupxy
CURRENTFONT
@@ -356,9 +368,11 @@ DBGFONTS
DBGOUTPUT
dbh
dblclk
DBlob
DColor
DCOLORVALUE
dcommon
dcompile
dcompiler
DComposition
dde
@@ -418,7 +432,6 @@ DECRQM
DECRQPSR
DECRQSS
DECRQTSR
DECRQUPSS
DECRSPS
decrst
DECSACE
@@ -441,7 +454,6 @@ DECSTBM
DECSTGLT
DECSTR
DECSWL
DECSWT
DECTABSR
DECTCEM
DECXCPR
@@ -466,6 +478,7 @@ depersist
deprioritized
deserializers
desktopwindowxamlsource
DESTINATIONNAME
devicecode
Dext
DFactory
@@ -477,6 +490,7 @@ DISABLEDELAYEDEXPANSION
DISABLENOSCROLL
DISPATCHNOTIFY
DISPLAYATTRIBUTE
DISPLAYATTRIBUTEPROPERTY
DISPLAYCHANGE
distros
dlg
@@ -524,6 +538,7 @@ DWORDs
dwrite
dxgi
dxgidwm
dxguid
dxinterop
dxsm
dxttbmp
@@ -552,6 +567,7 @@ entrypoints
ENU
ENUMLOGFONT
ENUMLOGFONTEX
enumranges
EOK
EPres
EQU
@@ -565,6 +581,7 @@ EVENTID
eventing
evflags
evt
EXACTSIZEONLY
execd
executionengine
exemain
@@ -589,9 +606,9 @@ FECF
FEEF
fesb
FFAF
ffd
FFDE
FFFDb
FFrom
fgbg
FGCOLOR
FGHIJ
@@ -610,6 +627,7 @@ FINDDOWN
FINDSTRINGEXACT
FINDUP
FIter
FIXEDCONVERTED
FIXEDFILEINFO
Flg
flyouts
@@ -702,6 +720,7 @@ GETWAITTOKILLTIMEOUT
GETWHEELSCROLLCHARACTERS
GETWHEELSCROLLCHARS
GETWHEELSCROLLLINES
GFEh
Gfun
gfx
GGI
@@ -724,8 +743,9 @@ Greyscale
gridline
gset
gsl
GTP
guc
GUIDATOM
guidatom
GValue
GWL
GWLP
@@ -748,7 +768,6 @@ hdr
HDROP
hdrstop
HEIGHTSCROLL
hfind
hfont
hfontresource
hglobal
@@ -758,6 +777,7 @@ hhx
HIBYTE
hicon
HIDEWINDOW
HIGHQUALITYSCALE
hinst
HISTORYBUFS
HISTORYNODUP
@@ -807,6 +827,7 @@ hwnd
HWNDPARENT
iccex
ICONERROR
ICONINFO
ICONINFORMATION
IConsole
ICONSTOP
@@ -824,9 +845,11 @@ IEnd
IEnum
IFACEMETHODIMP
ification
IGNOREEND
IGNORELANGUAGE
IHosted
iid
IImage
IIo
ILC
ILCo
@@ -847,6 +870,8 @@ inkscape
INLINEPREFIX
inproc
Inputkeyinfo
INPUTPROCESSORPROFILE
inputrc
Inputreadhandledata
INSERTMODE
INTERACTIVITYBASE
@@ -858,7 +883,9 @@ INVALIDARG
INVALIDATERECT
Ioctl
ipch
ipp
IProperty
IPSINK
ipsp
IShell
ISwap
@@ -878,12 +905,17 @@ JOBOBJECT
JOBOBJECTINFOCLASS
JPN
jsoncpp
Jsons
jsprovider
jumplist
KAttrs
kawa
Kazu
kazum
kcub
kcud
kcuf
kcuu
kernelbase
kernelbasestaging
KEYBDINPUT
@@ -895,6 +927,7 @@ Keymapping
keyscan
keystate
keyups
khome
KILLACTIVE
KILLFOCUS
kinda
@@ -907,7 +940,6 @@ KLMNOPQRSTY
KOK
KPRIORITY
KVM
kyouhaishaheiku
langid
LANGUAGELIST
lasterror
@@ -970,6 +1002,7 @@ lpdw
lpelfe
lpfn
LPFNADDPROPSHEETPAGE
lpl
LPMEASUREITEMSTRUCT
LPMINMAXINFO
lpmsg
@@ -1032,6 +1065,7 @@ MBUTTON
MBUTTONDBLCLK
MBUTTONDOWN
MBUTTONUP
Mbxy
mdmerge
MDs
MEASUREITEM
@@ -1045,7 +1079,6 @@ MENUITEMINFO
MENUSELECT
messageext
metaproj
Mgrs
microsoftpublicsymbols
midl
mii
@@ -1057,6 +1090,7 @@ minkernel
MINMAXINFO
minwin
minwindef
Mip
MMBB
mmcc
MMCPL
@@ -1100,6 +1134,7 @@ muxes
myapplet
mybranch
mydir
MYMAX
Mypair
Myval
NAMELENGTH
@@ -1142,8 +1177,6 @@ NOCONTEXTHELP
NOCOPYBITS
NODUP
noexcepts
NOFONT
NOHIDDENTEXT
NOINTEGRALHEIGHT
NOINTERFACE
NOLINKINFO
@@ -1167,7 +1200,6 @@ NORMALDISPLAY
NOSCRATCH
NOSEARCH
noselect
NOSELECTION
NOSENDCHANGING
NOSIZE
NOSNAPSHOT
@@ -1193,6 +1225,7 @@ ntdll
ntifs
ntlpcapi
ntm
nto
ntrtl
ntstatus
NTSYSCALLAPI
@@ -1258,7 +1291,6 @@ packageuwp
PACKAGEVERSIONNUMBER
PACKCOORD
PACKVERSION
pacp
pagedown
pageup
PAINTPARAMS
@@ -1269,7 +1301,9 @@ parentable
parms
PATCOPY
pathcch
Pathto
PATTERNID
pcat
pcb
pcch
PCCHAR
@@ -1293,9 +1327,9 @@ PCSTR
PCWCH
PCWCHAR
PCWSTR
pda
pdbs
pdbstr
pdcs
PDPs
pdtobj
pdw
@@ -1325,7 +1359,6 @@ PIDLIST
pids
pii
piml
pimpl
pinvoke
pipename
pipestr
@@ -1357,6 +1390,7 @@ POSXSCROLL
POSYSCROLL
PPEB
ppf
ppguid
ppidl
PPROC
ppropvar
@@ -1386,7 +1420,7 @@ PROCESSINFOCLASS
PRODEXT
PROPERTYID
PROPERTYKEY
propertyval
PROPERTYVAL
propsheet
PROPSHEETHEADER
PROPSHEETPAGE
@@ -1418,17 +1452,15 @@ ptch
ptsz
PTYIn
PUCHAR
pvar
pwch
PWDDMCONSOLECONTEXT
Pwease
pweview
pws
pwstr
pwsz
pythonw
Qaabbcc
QUERYOPEN
QUESTIONMARK
quickedit
QUZ
QWER
@@ -1461,6 +1493,8 @@ READCONSOLE
READCONSOLEOUTPUT
READCONSOLEOUTPUTSTRING
READMODE
reallocs
reamapping
rectread
redef
redefinable
@@ -1488,6 +1522,7 @@ repositorypath
Requiresx
rerasterize
rescap
Resequence
RESETCONTENT
resheader
resmimetype
@@ -1506,7 +1541,6 @@ rgn
rgp
rgpwsz
rgrc
rguid
rgw
RIGHTALIGN
RIGHTBUTTON
@@ -1514,7 +1548,6 @@ riid
RIS
roadmap
robomac
rodata
rosetta
RRF
rrr
@@ -1522,6 +1555,7 @@ RRRGGGBB
rsas
rtcore
RTEXT
RTFTo
RTLREADING
Rtn
ruleset
@@ -1637,6 +1671,7 @@ sidebyside
SIF
SIGDN
Signtool
SINGLEFLAG
SINGLETHREADED
siup
sixel
@@ -1668,6 +1703,7 @@ srcsrv
SRCSRVTRG
srctool
srect
srv
srvinit
srvpipe
ssa
@@ -1699,6 +1735,7 @@ SUA
subcompartment
subkeys
SUBLANG
subresource
subsystemconsole
subsystemwindows
swapchain
@@ -1709,7 +1746,6 @@ SYMED
SYNCPAINT
syscalls
SYSCHAR
SYSCOLOR
SYSCOMMAND
SYSDEADCHAR
SYSKEYDOWN
@@ -1721,7 +1757,6 @@ sysparams
sysparamsext
SYSTEMHAND
SYSTEMMENU
SYSTEMTIME
tabview
TAdd
taef
@@ -1776,6 +1811,7 @@ TEXTMETRIC
TEXTMETRICW
textmode
texttests
TFCAT
TFunction
THUMBPOSITION
THUMBTRACK
@@ -1803,15 +1839,18 @@ tosign
touchpad
Tpp
Tpqrst
tracelog
tracelogging
traceviewpp
trackbar
TRACKCOMPOSITION
trackpad
transitioning
Trd
TREX
triaged
triaging
TRIANGLESTRIP
Tribool
TRIMZEROHEADINGS
trx
@@ -1829,6 +1868,8 @@ TTM
TTo
tvpp
tvtseq
Txtev
typechecked
TYUI
UAC
uap
@@ -1846,8 +1887,10 @@ UIACCESS
uiacore
uiautomationcore
uielem
UIELEMENTENABLEDONLY
UINTs
ul
ulcch
uld
uldash
uldb
@@ -1861,6 +1904,7 @@ unhosted
UNICODETEXT
UNICRT
Unintense
Uniscribe
unittesting
unittests
unk
@@ -1872,7 +1916,7 @@ untextured
UPDATEDISPLAY
UPDOWN
UPKEY
upss
UPSS
uregex
URegular
usebackq
@@ -1901,7 +1945,6 @@ UVWXY
UVWXYZ
uwa
uwp
uwu
uxtheme
Vanara
vararg
@@ -1942,6 +1985,7 @@ vstest
VSTS
VSTT
vswhere
vtapi
vtapp
VTE
VTID
@@ -1955,6 +1999,7 @@ VTRGBTo
vtseq
vtterm
vttest
waitable
WANSUNG
WANTARROWS
WANTTAB
@@ -1975,7 +2020,6 @@ wdm
webpage
websites
wekyb
wewoad
wex
wextest
wextestclass
@@ -2005,6 +2049,7 @@ WINDOWALPHA
windowdpiapi
WINDOWEDGE
windowext
windowime
WINDOWINFO
windowio
windowmetrics
@@ -2055,6 +2100,7 @@ WNDCLASSW
Wndproc
WNegative
WNull
wnwb
workarea
WOutside
WOWARM
@@ -2078,6 +2124,7 @@ wrkstr
wrl
wrp
WRunoff
WScript
wsl
WSLENV
wstr
@@ -2093,6 +2140,7 @@ WTs
WTSOFTFONT
wtw
wtypes
Wubi
WUX
WVerify
WWith
@@ -2111,17 +2159,22 @@ XBUTTONDOWN
XBUTTONUP
XCast
XCENTER
XColors
xcopy
XCount
xdy
XEncoding
xes
xff
XFG
XFile
XFORM
XIn
xin
xinchaof
xinxinchaof
XManifest
XMath
XMFLOAT
xorg
XResource
xsi

View File

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

View File

@@ -13,8 +13,7 @@ jobs:
- id: getBody
uses: craigloewen-msft/GitGudSimilarIssues@main
with:
issueTitle: ${{ github.event.issue.title }}
issueBody: ${{ github.event.issue.body }}
issuetitle: ${{ github.event.issue.title }}
repo: ${{ github.repository }}
similaritytolerance: "0.75"
add-comment:

31
.vscode/settings.json vendored
View File

@@ -1,28 +1,8 @@
{
"C_Cpp.default.browse.databaseFilename": "${workspaceFolder}\\.vscode\\.BROWSE.VC.DB",
"C_Cpp.default.browse.limitSymbolsToIncludedHeaders": true,
"C_Cpp.default.browse.path": [
"${workspaceFolder}"
],
"C_Cpp.default.cppStandard": "c++20",
"C_Cpp.default.cStandard": "c17",
"C_Cpp.default.defines": [
"_DEBUG",
"_UNICODE",
"BUILD_ONECORE_INTERACTIVITY",
"DBG",
"NT_SUCCESS",
"UNICODE",
"UNIT_TESTING",
"INLINE_TEST_METHOD_MARKUP",
],
"C_Cpp.default.includePath": [
"${workspaceFolder}/**",
"${workspaceFolder}/**/Generated Files",
"${workspaceFolder}/**/inc",
"${workspaceFolder}/**/include",
"${workspaceFolder}/**/Include"
],
"C_Cpp.loggingLevel": "None",
"files.associations": {
"xstring": "cpp",
@@ -118,13 +98,14 @@
"coroutine": "cpp",
"format": "cpp",
"forward_list": "cpp",
"latch": "cpp",
"gsl_assert": "cpp"
"latch": "cpp"
},
"files.exclude": {
"**/bin/**": true,
"**/Generated Files/**": true,
"**/obj/**": true,
"**/packages/**": true,
"**/Generated Files/**": true
},
}
"search.exclude": {
"**/packages/**": true
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -4,7 +4,6 @@ trigger:
include:
- main
- feature/*
- gh-readonly-queue/*
paths:
exclude:
- doc/*

View File

@@ -75,7 +75,6 @@ steps:
rm LocOutputMunged.tar
rm -r -fo LocOutput
& ./build/scripts/Copy-ContextMenuResourcesToCascadiaPackage.ps1
& ./build/scripts/Generate-PseudoLocalizations.ps1
displayName: Move Loc files to the right places
- pwsh: |-

View File

@@ -30,13 +30,6 @@ extends:
buildTerminal: true
pgoBuildMode: Optimize
codeSign: true
signingIdentity:
serviceName: $(SigningServiceName)
appId: $(SigningAppId)
tenantId: $(SigningTenantId)
akvName: $(SigningAKVName)
authCertName: $(SigningAuthCertName)
signCertName: $(SigningSignCertName)
publishSymbolsToPublic: true
publishVpackToWindows: false
symbolExpiryTime: 15

View File

@@ -78,13 +78,6 @@ extends:
buildConfigurations: ${{ parameters.buildConfigurations }}
buildPlatforms: ${{ parameters.buildPlatforms }}
codeSign: true
signingIdentity:
serviceName: $(SigningServiceName)
appId: $(SigningAppId)
tenantId: $(SigningTenantId)
akvName: $(SigningAKVName)
authCertName: $(SigningAuthCertName)
signCertName: $(SigningSignCertName)
terminalInternalPackageVersion: ${{ parameters.terminalInternalPackageVersion }}
publishSymbolsToPublic: ${{ parameters.publishSymbolsToPublic }}
publishVpackToWindows: ${{ parameters.publishVpackToWindows }}

View File

@@ -27,9 +27,6 @@ parameters:
- name: publishArtifacts
type: boolean
default: true
- name: signingIdentity
type: object
default: {}
jobs:
- job: ${{ parameters.jobName }}
@@ -100,15 +97,10 @@ jobs:
flattenFolders: true
- ${{ if eq(parameters.codeSign, true) }}:
- task: EsrpCodeSigning@5
- task: EsrpCodeSigning@3
displayName: Submit *.nupkg to ESRP for code signing
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 }}
ConnectedServiceName: 9d6d2960-0793-4d59-943e-78dcb434840a
FolderPath: $(Build.ArtifactStagingDirectory)/nupkg
Pattern: '*.nupkg'
UseMinimatch: true

View File

@@ -65,9 +65,6 @@ parameters:
- name: removeAllNonSignedFiles
type: boolean
default: false
- name: signingIdentity
type: object
default: {}
jobs:
- job: ${{ parameters.jobName }}
@@ -145,10 +142,6 @@ jobs:
- template: .\steps-restore-nuget.yml
- pwsh: |-
.\build\scripts\Set-LatestVCToolsVersion.ps1
displayName: Work around DD-1541167 (VCToolsVersion)
- ${{ parameters.beforeBuildSteps }}
- task: VSBuild@1
@@ -242,15 +235,10 @@ 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@5
- task: EsrpCodeSigning@3
displayName: Submit Signing Request
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 }}
ConnectedServiceName: 9d6d2960-0793-4d59-943e-78dcb434840a
FolderPath: '$(Terminal.BinDir)'
signType: batchSigning
batchSignPolicyFile: '$(Build.SourcesDirectory)/ESRPSigningConfig.json'

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@6
- task: AzureFileCopy@5
displayName: Publish to Storage Account
inputs:
sourcePath: _out/*

View File

@@ -32,9 +32,6 @@ parameters:
- name: afterBuildSteps
type: stepList
default: []
- name: signingIdentity
type: object
default: {}
jobs:
- job: ${{ parameters.jobName }}
@@ -97,15 +94,10 @@ jobs:
displayName: Create msixbundle
- ${{ if eq(parameters.codeSign, true) }}:
- task: EsrpCodeSigning@5
- task: EsrpCodeSigning@3
displayName: Submit *.msixbundle to ESRP for code signing
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 }}
ConnectedServiceName: 9d6d2960-0793-4d59-943e-78dcb434840a
FolderPath: $(System.ArtifactsDirectory)\bundle
Pattern: $(BundleStemName)*.msixbundle
UseMinimatch: true

View File

@@ -27,9 +27,6 @@ parameters:
- name: publishArtifacts
type: boolean
default: true
- name: signingIdentity
type: object
default: {}
jobs:
- job: ${{ parameters.jobName }}
@@ -85,15 +82,10 @@ jobs:
versionEnvVar: XES_PACKAGEVERSIONNUMBER
- ${{ if eq(parameters.codeSign, true) }}:
- task: EsrpCodeSigning@5
- task: EsrpCodeSigning@3
displayName: Submit *.nupkg to ESRP for code signing
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 }}
ConnectedServiceName: 9d6d2960-0793-4d59-943e-78dcb434840a
FolderPath: $(Build.ArtifactStagingDirectory)/nupkg
Pattern: '*.nupkg'
UseMinimatch: true

View File

@@ -56,7 +56,6 @@ jobs:
- task: PowerShell@2
displayName: 'Run PGO Tests'
inputs:
pwsh: true
targetType: filePath
filePath: build\scripts\Run-Tests.ps1
arguments: >-

View File

@@ -44,7 +44,6 @@ jobs:
- task: PowerShell@2
displayName: 'Run Unit Tests'
inputs:
pwsh: true
targetType: filePath
filePath: build\scripts\Run-Tests.ps1
arguments: -MatchPattern '*unit.test*.dll' -Platform '$(OutputBuildPlatform)' -Configuration '$(BuildConfiguration)' -LogPath '${{ parameters.testLogPath }}' -Root "$(Terminal.BinDir)"
@@ -53,7 +52,6 @@ jobs:
- task: PowerShell@2
displayName: 'Run Feature Tests'
inputs:
pwsh: true
targetType: filePath
filePath: build\scripts\Run-Tests.ps1
arguments: -MatchPattern '*feature.test*.dll' -Platform '$(OutputBuildPlatform)' -Configuration '$(BuildConfiguration)' -LogPath '${{ parameters.testLogPath }}' -Root "$(Terminal.BinDir)"

View File

@@ -33,7 +33,7 @@ parameters:
- arm64
- name: codeSign
type: boolean
default: false
default: true
- name: generateSbom
type: boolean
default: true

View File

@@ -60,9 +60,6 @@ parameters:
- name: extraPublishJobs
type: object
default: []
- name: signingIdentity
type: object
default: {}
resources:
repositories:
@@ -85,7 +82,6 @@ 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'
@@ -111,8 +107,6 @@ 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)
@@ -128,7 +122,6 @@ 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
@@ -148,8 +141,6 @@ 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)
@@ -165,7 +156,6 @@ 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
@@ -182,8 +172,6 @@ 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)
@@ -219,7 +207,6 @@ 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: |-
@@ -236,8 +223,6 @@ 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)
@@ -247,15 +232,12 @@ 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)
@@ -265,7 +247,6 @@ extends:
buildPlatforms: ${{ parameters.buildPlatforms }}
generateSbom: false # this is handled by onebranch
codeSign: ${{ parameters.codeSign }}
signingIdentity: ${{ parameters.signingIdentity }}
- stage: Publish
displayName: Publish
@@ -279,8 +260,6 @@ extends:
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

@@ -30,7 +30,6 @@
<IntermediateOutputPath>$(SolutionDir)obj\$(Configuration)\GenerateFeatureFlags\</IntermediateOutputPath>
<OpenConsoleCommonOutDir>$(SolutionDir)bin\$(Configuration)\</OpenConsoleCommonOutDir>
<_WTBrandingName Condition="'$(WindowsTerminalBranding)'=='Canary'">Canary</_WTBrandingName>
<_WTBrandingName Condition="'$(WindowsTerminalBranding)'=='Preview'">Preview</_WTBrandingName>
<_WTBrandingName Condition="'$(WindowsTerminalBranding)'=='Release'">Release</_WTBrandingName>
<_WTBrandingName Condition="'$(_WTBrandingName)'==''">Dev</_WTBrandingName>

View File

@@ -1,16 +0,0 @@
Get-ChildItem -Recurse -Filter *.resw
| Where-Object { $_.Directory.Name.StartsWith("qps-ploc") }
| ForEach-Object {
$source = Join-Path $_.Directory "../en-US/$($_.Name)"
$target = $_
$ploc = ./tools/ConvertTo-PseudoLocalization.ps1 -Path $source
$writerSettings = [System.Xml.XmlWriterSettings]::new()
$writerSettings.NewLineChars = "`r`n"
$writerSettings.Indent = $true
$writer = [System.Xml.XmlWriter]::Create($target, $writerSettings)
$ploc.Save($writer)
$writer.Flush()
$writer.Close()
}

View File

@@ -16,48 +16,22 @@ Param(
# Find test DLLs based on the provided root, match pattern, and recursion
$testDlls = Get-ChildItem -Path $Root -Recurse -Filter $MatchPattern
$teArgs = @()
$args = @()
# Check if the LogPath parameter is provided and enable WTT logging
if ($LogPath) {
$teArgs += '/enablewttlogging'
$teArgs += '/appendwttlogging'
$teArgs += "/logFile:$LogPath"
$args += '/enablewttlogging'
$args += '/appendwttlogging'
$args += "/logFile:$LogPath"
Write-Host "WTT Logging Enabled"
}
$rootTe = "$Root\te.exe"
# Invoke the te.exe executable with arguments and test DLLs
& "$Root\te.exe" $args $testDlls.FullName $AdditionalTaefArguments
# Some of our test fixtures depend on resources.pri in the same folder as the .exe hosting them.
# Unfortunately, that means that we need to run the te.exe *next to* each test DLL we discover.
# This code establishes a mapping from te.exe to test DLL (or DLLs)
$testDllTaefGroups = $testDlls | % {
$localTe = Get-Item (Join-Path (Split-Path $_ -Parent) "te.exe") -EA:Ignore
If ($null -eq $localTe) {
$finalTePath = $rootTe
} Else {
$finalTePath = $localTe.FullName
}
[PSCustomObject]@{
TePath = $finalTePath;
TestDll = $_;
}
}
# Invoke the te.exe executables with arguments and test DLLs
$anyFailed = $false
$testDllTaefGroups | Group-Object TePath | % {
$te = $_.Group[0].TePath
$dlls = $_.Group.TestDll
Write-Verbose "Running $te (for $($dlls.Name))"
& $te $teArgs $dlls.FullName $AdditionalTaefArguments
if ($LASTEXITCODE -ne 0) {
$anyFailed = $true
}
}
if ($anyFailed) {
Exit 1
# Check the exit code of the te.exe process and exit accordingly
if ($LASTEXITCODE -ne 0) {
Exit $LASTEXITCODE
}
Exit 0

View File

@@ -1,8 +0,0 @@
$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.CRT.Source" })
$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

@@ -3,9 +3,9 @@
<!-- This file is read by XES, which we use in our Release builds. -->
<PropertyGroup Label="Version">
<XesUseOneStoreVersioning>true</XesUseOneStoreVersioning>
<XesBaseYearForStoreVersion>2024</XesBaseYearForStoreVersion>
<XesBaseYearForStoreVersion>2023</XesBaseYearForStoreVersion>
<VersionMajor>1</VersionMajor>
<VersionMinor>21</VersionMinor>
<VersionMinor>20</VersionMinor>
<VersionInfoProductName>Windows Terminal</VersionInfoProductName>
</PropertyGroup>
</Project>

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,4 @@
# CLI11
Taken from [release v2.4.1](https://github.com/CLIUtils/CLI11/releases/tag/v2.4.1), source commit
[f4d0731](https://github.com/CLIUtils/CLI11/commit/f4d0731cebb123ff0ace712c099dffbcd2c58e5a)
Taken from [release v1.9.1](https://github.com/CLIUtils/CLI11/releases/tag/v1.9.1), source commit
[5cb3efa](https://github.com/CLIUtils/CLI11/commit/5cb3efabce007c3a0230e4cc2e27da491c646b6c)

View File

@@ -6,7 +6,7 @@
"type": "git",
"git": {
"repositoryUrl": "https://github.com/CLIUtils/CLI11",
"commitHash": "88e9bb17418ee730817d5942894d99a4bdd78fb3"
"commitHash": "5cb3efabce007c3a0230e4cc2e27da491c646b6c"
}
}
}

View File

@@ -65,6 +65,9 @@
* `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

@@ -154,47 +154,3 @@ popd
The `bx` will build just the Terminal package, critically, populating the `CascadiaPackage.build.appxrecipe` file. Once that's been built, then the `DeployAppRecipe.exe` command can be used to deploy a loose layout in the same way that Visual Studio does.
Notably, this method of building the Terminal package can't leverage the FastUpToDate check in Visual Studio, so the builds end up being considerably slower for the whole package, as cppwinrt does a lot of work before confirming that it's up to date and doing nothing.
### Are you seeing `DEP0700: Registration of the app failed`?
Once in a blue moon, I get a `DEP0700: Registration of the app failed.
[0x80073CF6] error 0x80070020: Windows cannot register the package because of an
internal error or low memory.` when trying to deploy in VS. For us, that can
happen if the `OpenConsoleProxy.dll` gets locked up, in use by some other
terminal package.
Doing the equivalent command in powershell can give us more info:
```pwsh
Add-AppxPackage -register "Z:\dev\public\OpenConsole\src\cascadia\CascadiaPackage\bin\x64\Debug\AppX\AppxManifest.xml"
```
That'll suggest `NOTE: For additional information, look for [ActivityId]
dbf551f1-83d0-0007-43e7-9cded083da01 in the Event Log or use the command line
Get-AppPackageLog -ActivityID dbf551f1-83d0-0007-43e7-9cded083da01`. So do that:
```pwsh
Get-AppPackageLog -ActivityID dbf551f1-83d0-0007-43e7-9cded083da01
```
which will give you a lot of info. In my case, that revealed that the platform
couldn't delete the packaged com entries. The key line was: `AppX Deployment
operation failed with error 0x0 from API Logging data because access was denied
for file:
C:\ProgramData\Microsoft\Windows\AppRepository\Packages\WindowsTerminalDev_0.0.1.0_x64__8wekyb3d8bbwe,
user SID: S-1-5-18`
Take that path, and
```pwsh
sudo start C:\ProgramData\Microsoft\Windows\AppRepository\Packages\WindowsTerminalDev_0.0.1.0_x64__8wekyb3d8bbwe
```
(use `sudo`, since the path is otherwise locked down). From there, go into the
`PackagedCom` folder, and open [File
Locksmith](https://learn.microsoft.com/en-us/windows/powertoys/file-locksmith)
(or Process Explorer, if you're more familiar with that) on
`OpenConsoleProxy.dll`. Just go ahead and immediately re-launch it as admin,
too. That should list off a couple terminal processes that are just hanging
around. Go ahead and end them all. You should be good to deploy again after
that.

View File

@@ -349,7 +349,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": {
"^[\\x20-\\x7E]{4}$": {
"^(([A-Za-z0-9]){4})$": {
"type": "integer"
}
},
@@ -359,7 +359,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": {
"^[\\x20-\\x7E]{4}$": {
"^([A-Za-z]{4})$": {
"type": "number"
}
},
@@ -1501,10 +1501,8 @@
"const": "multipleActions"
},
"actions": {
"$ref": "#/$defs/ShortcutAction",
"type": "array",
"items": {
"$ref": "#/$defs/ShortcutAction"
},
"minItems": 1,
"description": "A list of other actions."
}
@@ -1893,14 +1891,6 @@
],
"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": [
@@ -1938,10 +1928,6 @@
"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"
}
}
},
@@ -2079,9 +2065,6 @@
{
"$ref": "#/$defs/SwitchToTabAction"
},
{
"$ref": "#/$defs/ScrollToMarkAction"
},
{
"$ref": "#/$defs/MoveFocusAction"
},
@@ -2217,10 +2200,6 @@
}
}
},
"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\"",
@@ -2232,15 +2211,7 @@
"commands": {
"description": "List of commands to execute",
"items": {
"type": "object",
"properties": {
"command": {
"$ref": "#/$defs/Keybinding/properties/command"
},
"name": {
"$ref": "#/$defs/Keybinding/properties/name"
}
}
"$ref": "#/$defs/Keybinding/properties/command"
},
"minItems": 1,
"type": "array"
@@ -2361,20 +2332,12 @@
},
"type": "array"
},
"rendering.graphicsAPI": {
"description": "Direct3D 11 provides a more performant and feature-rich experience, whereas Direct2D is more stable. The default option \"Automatic\" will pick the API that best fits your graphics hardware. If you experience significant issues, consider using Direct2D.",
"type": "string",
"enum": [
"direct2d",
"direct3d11"
]
},
"rendering.disablePartialInvalidation": {
"description": "By default, the text renderer uses a FLIP_SEQUENTIAL Swap Chain and declares dirty rectangles via the Present1 API. When this setting is enabled, a FLIP_DISCARD Swap Chain will be used instead, and no dirty rectangles will be declared. Whether one or the other is better depends on your hardware and various other factors.",
"experimental.rendering.forceFullRepaint": {
"description": "When set to true, we will redraw the entire screen each frame. When set to false, we will render only the updates to the screen between frames.",
"type": "boolean"
},
"rendering.software": {
"description": "When enabled, the terminal will use a software rasterizer (WARP). This setting should be left disabled under almost all circumstances.",
"experimental.rendering.software": {
"description": "When set to true, we will use the software renderer (a.k.a. WARP) instead of the hardware one.",
"type": "boolean"
},
"experimental.input.forceVT": {
@@ -2801,14 +2764,13 @@
"type": "string"
}
},
"autoMarkPrompts": {
"experimental.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",
"experimental.connection.passthroughMode": {
"description": "When set to true, directs the PTY for this connection to use pass-through mode instead of the original Conhost PTY simulation engine. This is an experimental feature, and its continued existence is not guaranteed.",
"type": "boolean"
},
"experimental.retroTerminalEffect": {
@@ -2816,20 +2778,10 @@
"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.",
@@ -2839,6 +2791,11 @@
"description": "Use to set a path to a pixel shader to use with the Terminal. Overrides `experimental.retroTerminalEffect`. This is an experimental feature, and its continued existence is not guaranteed.",
"type": "string"
},
"useAtlasEngine": {
"description": "Windows Terminal 1.16 and later ship with a new, performant text renderer. Set this to false to revert back to the old text renderer.",
"type": "boolean",
"default": true
},
"fontFace": {
"default": "Cascadia Mono",
"description": "[deprecated] Define 'face' within the 'font' object instead.",

View File

@@ -23,7 +23,7 @@ contexts without needing to replicate an entire json blob.
This spec was largely inspired by the following diagram from @DHowett:
![figure 1](data-mockup-002.png)
![figure 1](data-mockup.png)
The goal is to introduce an `id` parameter by which actions could be uniquely
referred to. If we'd ever like to use an action outside the list of `actions`, we
@@ -36,54 +36,38 @@ Discussion with the team lead to the understanding that the name `actions` would
be even better, as a way of making the meaning of the "list of actions" more
obvious.
We will then restructure `defaults.json`, and also users' settings files (via `fixUpUserSettings`), in the following manner:
* Instead of each `command` json block containing both the `action` (along with additional arguments) and the `keys`, these will now be split up -
* There will now be one json block for just the `command`/`action`, which will also contain the `id`. These json blocks will be in their own list called `actions`.
* There will be another json block for the `keys`, which will refer to the action to be invoked by `id`. These json blocks will be in their own list called `keybindings`.
For example, let's take a look at the `split pane right` action in `defaults.json` as we currently have it:
`"actions": [..., { "command": { "action": "splitPane", "split": "right" }, "keys": "alt+shift+plus" }, ...]`
This will now become:
`"actions": [..., { "command": { "action": "splitPane", "split": "right" }, "id": "Terminal.SplitPaneRight" }, ...]`
`"keybindings": [..., { "keys": "alt+shift+plus", "id": "Terminal.SplitPaneRight" }, ...]`
Here is how we will parse settings file and construct the relevant settings model objects:
* We will first scan the `actions` list. We'll
When we're parsing `actions`, we'll make three passes:
* The first pass will scan the list for objects with an `id` property. We'll
attempt to parse those entries into `ActionAndArgs` which we'll store in the
global `id->ActionAndArgs` map. All actions defined in `defaults.json` must have an `id` specified, and all actions provided by fragments must also have `id`s. Any actions from the defaults or fragments that do not provide `id`s will be ignored. As for user-specified commands, if no `id` is set, we will auto-generate one for that command based on the action and any additional arguments. For example, the `split pane right` command above might result in an autogenerated id `User.SplitPaneRight`.
* Note: this step is also where we will generate _commands_. We will use the name provided in the entry if it's set or the action's `GenerateName` method.
* Next we will scan the `keybindings` list. These entries will
create a `KeyChord->ActionAndArgs` entry in the keybindings map. Since these objects should all contain an `id`, we will simply use the `id->ActionAndArgs` map we created in the previous step. Any object with `keys` set but no `id` will be ignored.
global `id->ActionAndArgs` map. If any entry doesn't have an `id` set, we'll
skip it in this phase. If an entry doesn't have a `command` set, we'll ignore
it in this pass.
* The second pass will scan for _keybindings_. Any entries with `keys` set will
create a `KeyChord->ActionAndArgs` entry in the keybindings map. If the entry
has an `id` set, then we'll simply re-use the action we've already parsed for
the `id`, from the action map. If there isn't an `id`, then we'll parse the
action manually at this time. Entries without a `keys` set will be ignored in
this pass.
* The final pass will be to generate _commands_. Similar to the keybindings
pass, we'll attempt to lookup actions for entries with an `id` set. If there
isn't an `id`, then we'll parse the action manually at this time. We'll then
get the name for the entry, either from the `name` property if it's set, or
the action's `GenerateName` method.
For a visual representation:
For a visual representation, let's assume the user has the following in their
`actions`:
![figure 2](data-mockup-actions-ids-keys-maps.png)
![figure 2](data-mockup-actions.png)
### Nested actions
We'll first parse the `actions` to generate the mapping of `id`->`Actions`:
We allow certain actions that take a form like this:
![figure 3](data-mockup-actions-and-ids.png)
```
{
// Select color scheme...
"name": { "key": "SetColorSchemeParentCommandName" },
"commands": [
{
"iterateOn": "schemes",
"name": "${scheme.name}",
"command": { "action": "setColorScheme", "colorScheme": "${scheme.name}" }
}
]
}
```
Then, we'll parse the `actions` to generate the mapping of keys to actions, with
some actions already being defined in the map of `id`->`Actions`:
For this case, having an `id` on the top level could potentially make sense when it comes to using that `id` in a menu, but not in the case of using that `id` for a keybinding. For the initial implementation, we will not support an `id` for these types of actions, which leaves us open to revisiting this in the future.
![figure 4](data-mockup-actions-and-ids-and-keys.png)
### Layering
When layering `actions`, if a later settings file contains an action with the
same `id`, it will replace the current value. In this way, users can redefine
@@ -103,9 +87,6 @@ As we add additional menus to the Terminal, like the customization for the new
tab dropdown, or the tab context menu, or the `TermControl` context menu, they
could all refer to these actions by `id`, rather than duplicating the same json.
As for fragments, all actions in fragments _must_ have an `id`. If a fragment provides an action without an `id`, or provides an `id` that clashes with one of the actions in `defaults.json`, that action will be ignored.
> 👉 NOTE: This will mean that actions will now need an `OriginTag`, similar to profiles and color schemes
### Existing Scenarios

Binary file not shown.

Before

Width:  |  Height:  |  Size: 172 KiB

View File

@@ -1,396 +0,0 @@
---
author: Dustin Howett @DHowett <duhowett@microsoft.com>
created on: 2020-08-16
last updated: 2023-12-12
issue id: "#7335"
---
# Console Allocation Policy
## Abstract
Due to the design of the console subsystem on Windows as it has existed since Windows 95, every application that is
stamped with the `IMAGE_SUBSYSTEM_WINDOWS_CUI` subsystem in its PE header will be allocated a console by kernel32.
Any application that is stamped `IMAGE_SUBSYSTEM_WINDOWS_GUI` will not automatically be allocated a console.
This has worked fine for many years: when you double-click a console application in your GUI shell, it is allocated a
console. When you run a GUI application from your console shell, it is **not** allocated a console. The shell will
**not** wait for it to exit before returning you to a prompt.
There is a large class of applications that do not fit neatly into this mold. Take Python, Ruby, Perl, Lua, or even
VBScript: These languages are not relegated to running in a console session; they can be used to write fully-fledged GUI
applications like any other language.
Because their interpreters are console subsystem applications, however, any user double-clicking a shortcut to a Python
or Perl application will be presented with a console window that the language runtime may choose to garbage collect, or
may choose not to.
If the runtime chooses to hide the window, there will still be a brief period during which that window is visible. It is
inescapable.
Likewise, any user running that GUI application from a console shell will see their shell hang until the application
terminates.
All of these scripting languages worked around this by shipping two binaries each, identical in every way expect in
their subsystem fields. python/pythonw, perl/perlw, ruby/rubyw, wscript/cscript.
PowerShell[^1] is waiting to deal with this problem because they don't necessarily want to ship a `pwshw.exe` for all
of their GUI-only authors. Every additional `*w` version of an application is an additional maintenance burden and
source of cognitive overhead[^2] for users.
On the other side, you have mostly-GUI applications that want to print output to a console **if there is one
connected**.
These applications are still primarily GUI-driven, but they might support arguments like `/?` or `--help`. They only
need a console when they need to print out some text. Sometimes they'll allocate their own console (which opens a new
window) to display in, and sometimes they'll reattach to the originating console. VSCode does the latter, and so when
you run `code` from CMD, and then `exit` CMD, your console window sticks around because VSCode is still attached to it.
It will never print anything, and your only option is to close it.
There's another risk in reattaching, too. Given that the shell decides whether to wait based on the subsystem
field, GUI subsystem applications that reattach to their owning consoles *just to print some text* end up stomping on
the output of any shell that doesn't wait for them:
```
C:\> application --help
application - the interesting application
C:\> Usage: application [OPTIONS] ...
```
> _(the prompt is interleaved with the output)_
## Solution Design
I propose that we introduce a fusion manifest field, **consoleAllocationPolicy**, with the following values:
* _absent_
* `detached`
This field allows an application to disable the automatic allocation of a console, regardless of the [process creation flags]
passed to [`CreateProcess`] and its subsystem value.
It would look (roughly) like this:
```xml
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<application>
<windowsSettings>
<consoleAllocationPolicy xmlns="http://schemas.microsoft.com/SMI/2024/WindowsSettings">detached</consoleAllocationPolicy>
</windowsSettings>
</application>
</assembly>
```
The effects of this field will only apply to binaries in the `IMAGE_SUBSYSTEM_WINDOWS_CUI` subsystem, as it pertains to
the particulars of their console allocation.
**All console inheritance will proceed as normal.** Since this field takes effect only in the absence of console
inheritance, CUI applications will still be able to run inside an existing console session.
| policy | behavior |
| - | - |
| _absent_ | _default behavior_ |
| `detached` | The new process is not attached to a console session (similar to `DETACHED_PROCESS`) unless one was inherited. |
An application that specifies the `detached` allocation policy will _not_ present a console window when launched by
Explorer, Task Scheduler, etc.
### Interaction with existing APIs
[`CreateProcess`] supports a number of [process creation flags] that dictate how a spawned application will behave with
regards to console allocation:
* `DETACHED_PROCESS`: No console inheritance, no console host spawned for the new process.
* `CREATE_NEW_CONSOLE`: No console inheritance, new console host **is** spawned for the new process.
* `CREATE_NO_WINDOW`: No console inheritance, new console host **is** spawned for the new process.
* this is the same as `CREATE_NEW_CONSOLE`, except that the first connection packet specifies that the window should
be invisible
Due to the design of [`CreateProcess`] and `ShellExecute`, this specification recommends that an allocation policy of
`detached` _override_ the inclusion of `CREATE_NEW_CONSOLE` in the `dwFlags` parameter to [`CreateProcess`].
> **Note**
> `ShellExecute` passes `CREATE_NEW_CONSOLE` _by default_ on all invocations. This impacts our ability to resolve the
> conflicts between these two APIs--`detached` policy and `CREATE_NEW_CONSOLE`--without auditing every call site in
> every Windows application that calls `ShellExecute` on a console application. Doing so is infeasible.
### Application impact
An application that opts into the `detached` console allocation policy will **not** be allocated a console unless one is
inherited. This presents an issue for applications like PowerShell that do want a console window when they are launched
directly.
Applications in this category can call `AllocConsole()` early in their startup to get fine-grained control over when a
console is presented.
The call to `AllocConsole()` will fail safely if the application has already inherited a console handle. It will succeed
if the application does not currently have a console handle.
> **Note**
> **Backwards Compatibility**: The behavior of `AllocConsole()` is not changing in response to this specification;
> therefore, applications that intend to run on older versions of Windows that do not support console allocation
> policies, which call `AllocConsole()`, will continue to behave normally.
### New APIs
Because a console-subsystem application may still want fine-grained control over when and how its console window is
spawned, we propose the inclusion of a new API, `AllocConsoleWithOptions(PALLOC_CONSOLE_OPTIONS)`.
#### `AllocConsoleWithOptions`
```c++
// Console Allocation Modes
typedef enum ALLOC_CONSOLE_MODE {
ALLOC_CONSOLE_MODE_DEFAULT = 0,
ALLOC_CONSOLE_MODE_NEW_WINDOW = 1,
ALLOC_CONSOLE_MODE_NO_WINDOW = 2
} ALLOC_CONSOLE_MODE;
typedef enum ALLOC_CONSOLE_RESULT {
ALLOC_CONSOLE_RESULT_NO_CONSOLE = 0,
ALLOC_CONSOLE_RESULT_NEW_CONSOLE = 1,
ALLOC_CONSOLE_RESULT_EXISTING_CONSOLE = 2
} ALLOC_CONSOLE_RESULT, *PALLOC_CONSOLE_RESULT;
typedef
struct ALLOC_CONSOLE_OPTIONS
{
ALLOC_CONSOLE_MODE mode;
BOOL useShowWindow;
WORD showWindow;
} ALLOC_CONSOLE_OPTIONS, *PALLOC_CONSOLE_OPTIONS;
WINBASEAPI
HRESULT
WINAPI
AllocConsoleWithOptions(_In_opt_ PALLOC_CONSOLE_OPTIONS allocOptions, _Out_opt_ PALLOC_CONSOLE_RESULT result);
```
**AllocConsoleWithOptions** affords an application control over how and when it begins a console session.
> [!NOTE]
> Unlike `AllocConsole`, `AllocConsoleWithOptions` without a mode (`ALLOC_CONSOLE_MODE_DEFAULT`) will only allocate a console if one was
> requested during `CreateProcess`.
>
> To override this behavior, pass one of `ALLOC_CONSOLE_MODE_NEW_WINDOW` (which is equivalent to being spawned with
> `CREATE_NEW_WINDOW`) or `ALLOC_CONSOLE_MODE_NO_WINDOW` (which is equivalent to being spawned with `CREATE_NO_CONSOLE`.)
##### Parameters
**allocOptions**: A pointer to a `ALLOC_CONSOLE_OPTIONS`.
**result**: An optional out pointer, which will be populated with a member of the `ALLOC_CONSOLE_RESULT` enum.
##### `ALLOC_CONSOLE_OPTIONS`
###### Members
**mode**: See the table below for the descriptions of the available modes.
**useShowWindow**: Specifies whether the value in `showWindow` should be used.
**showWindow**: If `useShowWindow` is set, specifies the ["show command"] used to display your
console window.
###### Return Value
`AllocConsoleWithOptions` will return `S_OK` and populate `result` to indicate whether--and how--a console session was
created.
`AllocConsoleWithOptions` will return a failing `HRESULT` if the request could not be completed.
###### Modes
| Mode | Description |
|:-------------------------------:| ------------------------------------------------------------------------------------------------------------------------------ |
| `ALLOC_CONSOLE_MODE_DEFAULT` | Allocate a console session if (and how) one was requested by the parent process. |
| `ALLOC_CONSOLE_MODE_NEW_WINDOW` | Allocate a console session with a window, even if this process was created with `CREATE_NO_CONSOLE` or `DETACHED_PROCESS`. |
| `ALLOC_CONSOLE_MODE_NO_WINDOW` | Allocate a console session _without_ a window, even if this process was created with `CREATE_NEW_WINDOW` or `DETACHED_PROCESS` |
###### Notes
Applications seeking backwards compatibility are encouraged to delay-load `AllocConsoleWithOptions` or check for its presence in
the `api-ms-win-core-console-l1` APISet.
## Inspiration
Fusion manifest entries are used to make application-scoped decisions like this all the time, like `longPathAware` and
`heapType`.
CUI applications that can spawn a UI (or GUI applications that can print to a console) are commonplace on other
platforms because there is no subsystem differentiation.
## UI/UX Design
There is no UI for this feature.
## Capabilities
### Accessibility
This should have no impact on accessibility.
### Security
One reviewer brought up the potential for a malicious actor to spawn an endless stream of headless daemon processes.
This proposal in no way changes the facilities available to malicious people for causing harm: they could have simply
used `IMAGE_SUBSYSTEM_WINDOWS_GUI` and not presented a UI--an option that has been available to them for 35 years.
### Reliability
This should have no impact on reliability.
### Compatibility
An existing application opting into **detached** may constitute a breaking change, but the scope of the breakage is
restricted to that application and is expected to be managed by the application.
All behavioral changes are opt-in.
> **EXAMPLE**: If Python updates python.exe to specify an allocation policy of **detached**, graphical python applications
> will become double-click runnable from the graphical shell without spawning a console window. _However_, console-based
> python applications will no longer spawn a console window when double-clicked from the graphical shell.
>
> In addition, if python.exe specifies **detached**, Console APIs will fail until a console is allocated.
Python could work around this by calling [`AllocConsole`] or [new API `AllocConsoleWithOptions`](#allocconsolewithoptions)
if it can be detected that console I/O is required.
#### Downlevel
On downlevel versions of Windows that do not understand (or expect) this manifest field, applications will allocate
consoles as specified by their image subsystem (described in the [abstract](#abstract) above).
### Performance, Power, and Efficiency
This should have no impact on performance, power or efficiency.
## Potential Issues
### Shell Hang
I am **not** proposing a change in how shells determine whether to wait for an application before returning to a prompt.
This means that a console subsystem application that intends to primarily present a UI but occasionally print text to a
console (therefore choosing the **detached** allocation policy) will cause the shell to "hang" and wait for it to
exit.
The decision to pause/wait is made entirely in the calling shell, and the console subsystem cannot influence that
decision.
Because the vast majority of shells on Windows "hang" by calling `WaitFor...Object` with a HANDLE to the spawned
process, an application that wants to be a "hybrid" CUI/GUI application will be forced to spawn a separate process to
detach from the shell and then terminate its main process.
This is very similar to the forking model seen in many POSIX-compliant operating systems.
### Launching interactively from Explorer, Task Scheduler, etc.
Applications like PowerShell may wish to retain automatic console allocation, and **detached** would be unsuitable for
them. If PowerShell specifies the `detached` console allocation policy, launching `pwsh.exe` from File Explorer it will
no longer spawn a console. This would almost certainly break PowerShell for all users.
Such applications can use `AllocConsole()` early in their startup.
At the same time, PowerShell wants `-WindowStyle Hidden` to suppress the console _before it's created_.
Applications in this category can use `AllocConsoleWithOptions()` to specify additional information about the new console window.
PowerShell, and any other shell that wishes to maintain interactive launch from the graphical shell, can start in
**detached** mode and then allocate a console as necessary. Therefore:
* PowerShell will set `<consoleAllocationPolicy>detached</consoleAllocationPolicy>`
* On startup, it will process its commandline arguments.
* If `-WindowStyle Hidden` is **not** present (the default case), it can:
* `AllocConsole()` or `AllocConsoleWithOptions(NULL)`
* Either of these APIs will present a console window (or not) based on the flags passed through `STARTUPINFO` during
[`CreateProcess`].
* If `-WindowStyle Hidden` is present, it can:
* `AllocConsoleWithOptions(&alloc)` where `alloc.mode` specifies `ALLOC_CONSOLE_MODE_HIDDEN`
## Future considerations
We're introducing a new manifest field today -- what if we want to introduce more? Should we have a `consoleSettings`
manifest block?
Are there other allocation policies we need to consider?
## Resources
### Rejected Solutions
- A new PE subsystem, `IMAGE_SUBSYSTEM_WINDOWS_HYBRID`
- it would behave like **inheritOnly**
- relies on shells to update and check for this
- checking a subsystem doesn't work right with app execution aliases[^3]
- This is not a new problem, but it digs the hole a little deeper.
- requires standardization outside of Microsoft because the PE format is a dependency of the UEFI specification[^4]
- requires coordination between tooling teams both within and without Microsoft (regarding any tool that operates on
or produces PE files)
- An exported symbol that shells can check for to determine whether to wait for the attached process to exit
- relies on shells to update and check for this
- cracking an executable to look for symbols is probably the last thing shells want to do
- we could provide an API to determine whether to wait or return?
- fragile, somewhat silly, exporting symbols from EXEs is annoying and uncommon
An earlier version of this specification offered the **always** allocation policy, with the following behaviors:
> **STRUCK FROM SPECIFICATION**
>
> * A GUI subsystem application would always get a console window.
> * A command-line shell would not wait for it to exit before returning a prompt.
It was cut because a GUI application that wants a console window can simply attach to an existing console session or
allocate a new one. We found no compelling use case that would require the forced allocation of a console session
outside of the application's code.
An earlier version of this specification offered the **inheritOnly** allocation policy, instead of the finer-grained
**hidden** and **detached** policies. We deemed it insufficient for PowerShell's use case because any application
launched by an **inheritOnly** PowerShell would immediately force the uncontrolled allocation of a console window.
> **STRUCK FROM SPECIFICATION**
>
> The move to **hidden** allows PowerShell to offer a fully-fledged console connection that can be itself inherited by a
> downstream application.
#### Additional allocation policies
An earlier revision of this specification suggested two allocation policies:
> **STRUCK FROM SPECIFICATION**
>
> **hidden** is intended to be used by console applications that want finer-grained control over the visibility of their
> console windows, but that still need a console host to service console APIs. This includes most scripting language
> interpreters.
>
> **detached** is intended to be used by primarily graphical applications that would like to operate against a console _if
> one is present_ but do not mind its absence. This includes any graphical tool with a `--help` or `/?` argument.
The `hidden` policy was rejected due to an incompatibility with modern console hosting, as `hidden` would require an
application to interact with the console window via `GetConsoleWindow()` and explicitly show it.
> **STRUCK FROM SPECIFICATION**
>
> ##### ShowWindow and ConPTY
>
> The pseudoconsole creates a hidden window to service `GetConsoleWindow()`, and it can be trivially shown using
> `ShowWindow`. If we recommend that applications `ShowWindow` on startup, we will need to guard the pseudoconsole's
> pseudo-window from being shown.
[^1]: [Powershell -WindowStyle Hidden still shows a window briefly]
[^2]: [StackOverflow: pythonw.exe or python.exe?]
[^3]: [PowerShell: Windows Store applications incorrectly assumed to be console applications]
[^4]: [UEFI spec 2.6 appendix Q.1]
[Powershell -WindowStyle Hidden still shows a window briefly]: https://github.com/PowerShell/PowerShell/issues/3028
[PowerShell: Windows Store applications incorrectly assumed to be console applications]: https://github.com/PowerShell/PowerShell/issues/9970
[StackOverflow: pythonw.exe or python.exe?]: https://stackoverflow.com/questions/9705982/pythonw-exe-or-python-exe
[UEFI spec 2.6 appendix Q.1]: https://www.uefi.org/sites/default/files/resources/UEFI%20Spec%202_6.pdf
[`AllocConsole`]: https://docs.microsoft.com/windows/console/allocconsole
[`CreateProcess`]: https://docs.microsoft.com/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessw
[process creation flags]: https://docs.microsoft.com/en-us/windows/win32/procthread/process-creation-flags
["show command"]: https://learn.microsoft.com/windows/win32/api/winuser/nf-winuser-showwindow

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 (2404.23)
* from microsoft/cascadia-code@1034791e5fc6e060a448d2b29cd94a6c683edb36
* Cascadia Code, Cascadia Mono (2111.01)
* from microsoft/cascadia-code@de36d62e777d34d3bed92a7e23988e5d61e0ba02

View File

@@ -1,23 +0,0 @@
// Demo shader to show passing in an image using
// experimental.pixelShaderImagePath. This shader simply displays the Terminal
// contents on top of the given image.
//
// The image loaded by the terminal will be placed into the `image` texture.
SamplerState samplerState;
Texture2D shaderTexture : register(t0);
Texture2D image : register(t1);
cbuffer PixelShaderSettings {
float Time;
float Scale;
float2 Resolution;
float4 Background;
};
float4 main(float4 pos : SV_POSITION, float2 tex : TEXCOORD) : SV_TARGET
{
float4 terminalColor = shaderTexture.Sample(samplerState, tex);
float4 imageColor = image.Sample(samplerState, tex);
return lerp(imageColor, terminalColor, terminalColor.a);
}

View File

@@ -118,6 +118,6 @@
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="AppDescription" xml:space="preserve">
<value>Ά śςґàτсн ąρφ ƒоř ΧΆΜĻ Ìŝļàиđś τёşτś !!! !!! !!! !</value>
<value>А şςѓάţćћ ǻрр ƒθŗ χÂΜĿ Íŝĺąήðş ŧеšτş !!! !!! !!! !</value>
</data>
</root>

View File

@@ -118,6 +118,6 @@
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="AppDescription" xml:space="preserve">
<value>Ά śςґàτсн ąρφ ƒоř ΧΆΜĻ Ìŝļàиđś τёşτś !!! !!! !!! !</value>
<value>Ă šςґаτćĥ àρφ ƒǿя ЖΆΜĹ Іѕℓаñďş ťêšţŝ !!! !!! !!! !</value>
</data>
</root>

View File

@@ -118,6 +118,6 @@
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="AppDescription" xml:space="preserve">
<value>Ά śςґàτсн ąρφ ƒоř ΧΆΜĻ Ìŝļàиđś τёşτś !!! !!! !!! !</value>
<value>Ă śćяǻт¢н ãрρ ƒσг ХĂМĽ Īşłдήďѕ ťέśτş !!! !!! !!! !</value>
</data>
</root>

View File

@@ -31,12 +31,9 @@ namespace winrt::SampleApp::implementation
auto connectionSettings{ TerminalConnection::ConptyConnection::CreateSettings(L"cmd.exe /k echo This TermControl is hosted in-proc...",
winrt::hstring{},
L"",
false,
L"",
nullptr,
32,
80,
winrt::guid(),
winrt::guid()) };
// "Microsoft.Terminal.TerminalConnection.ConptyConnection"

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, float>;
using IFontFeatureMap = winrt::Windows::Foundation::Collections::IMap<winrt::hstring, uint32_t>;
using IFontAxesMap = winrt::Windows::Foundation::Collections::IMap<winrt::hstring, float>;
namespace winrt::SampleApp::implementation

View File

@@ -23,24 +23,21 @@ 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 ScreenToBufferLineInclusive(const til::point& line, const LineRendition lineRendition)
constexpr til::point ScreenToBufferLine(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 };
}

View File

@@ -1,91 +0,0 @@
/*++
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

@@ -29,8 +29,7 @@ OutputCellView::OutputCellView(const std::wstring_view view,
// - Reference to UTF-16 character data
// C26445 - suppressed to enable the `TextBufferTextIterator::operator->` method which needs a non-temporary memory location holding the wstring_view.
// TODO: GH 2681 - remove this suppression by reconciling the probably bad design of the iterators that leads to this being required.
GSL_SUPPRESS(26445)
const std::wstring_view& OutputCellView::Chars() const noexcept
[[gsl::suppress(26445)]] const std::wstring_view& OutputCellView::Chars() const noexcept
{
return _view;
}

View File

@@ -230,7 +230,6 @@ void ROW::Reset(const TextAttribute& attr) noexcept
_lineRendition = LineRendition::SingleWidth;
_wrapForced = false;
_doubleBytePadded = false;
_promptData = std::nullopt;
_init();
}
@@ -349,6 +348,12 @@ 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;
@@ -360,8 +365,7 @@ void ROW::CopyFrom(const ROW& source)
};
CopyTextFrom(state);
_attr = source.Attributes();
_attr.resize_trailing_extent(_columnCount);
TransferAttributes(source.Attributes(), _columnCount);
}
// Returns the previous possible cursor position, preceding the given column.
@@ -914,7 +918,7 @@ const til::small_rle<TextAttribute, uint16_t, 1>& ROW::Attributes() const noexce
TextAttribute ROW::GetAttrByColumn(const til::CoordType column) const
{
return _attr.at(_clampedColumn(column));
return _attr.at(_clampedUint16(column));
}
std::vector<uint16_t> ROW::GetHyperlinks() const
@@ -1097,6 +1101,12 @@ 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
{
@@ -1171,45 +1181,3 @@ 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,7 +8,6 @@
#include "LineRendition.hpp"
#include "OutputCell.hpp"
#include "OutputCellIterator.hpp"
#include "Marks.hpp"
class ROW;
class TextBuffer;
@@ -132,6 +131,7 @@ 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,11 +167,6 @@ 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;
@@ -230,6 +225,8 @@ 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>
@@ -302,8 +299,6 @@ 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) == 18);
static_assert(sizeof(TextAttribute) == 16);
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,5 +434,4 @@ void TextAttribute::SetStandardErase() noexcept
{
_attrs = CharacterAttributes::Normal;
_hyperlinkId = 0;
_markKind = MarkKind::None;
}

View File

@@ -38,15 +38,6 @@ 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:
@@ -55,8 +46,7 @@ public:
_foreground{},
_background{},
_hyperlinkId{ 0 },
_underlineColor{},
_markKind{ MarkKind::None }
_underlineColor{}
{
}
@@ -65,8 +55,7 @@ public:
_foreground{ gsl::at(s_legacyForegroundColorMap, wLegacyAttr & FG_ATTRS) },
_background{ gsl::at(s_legacyBackgroundColorMap, (wLegacyAttr & BG_ATTRS) >> 4) },
_hyperlinkId{ 0 },
_underlineColor{},
_markKind{ MarkKind::None }
_underlineColor{}
{
}
@@ -77,8 +66,7 @@ public:
_foreground{ rgbForeground },
_background{ rgbBackground },
_hyperlinkId{ 0 },
_underlineColor{ rgbUnderline },
_markKind{ MarkKind::None }
_underlineColor{ rgbUnderline }
{
}
@@ -87,8 +75,7 @@ public:
_foreground{ foreground },
_background{ background },
_hyperlinkId{ hyperlinkId },
_underlineColor{ underlineColor },
_markKind{ MarkKind::None }
_underlineColor{ underlineColor }
{
}
@@ -148,15 +135,6 @@ 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;
@@ -224,7 +202,6 @@ 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

@@ -62,11 +62,6 @@ bool TextColor::CanBeBrightened() const noexcept
return IsIndex16() || IsDefault();
}
ColorType TextColor::GetType() const noexcept
{
return _meta;
}
bool TextColor::IsLegacy() const noexcept
{
return (IsIndex16() || IsIndex256()) && _index < 16;
@@ -207,7 +202,7 @@ COLORREF TextColor::GetColor(const std::array<COLORREF, TextColor::TABLE_SIZE>&
// the result will be something like 0b00100000.
// 5. Use BitScanForward (bsf) to find the index of the most significant 1 bit.
const auto haystack = _mm256_loadu_si256(reinterpret_cast<const __m256i*>(colorTable.data())); // 1.
const auto needle = _mm256_set1_epi32(std::bit_cast<int>(defaultColor)); // 2.
const auto needle = _mm256_set1_epi32(til::bit_cast<int>(defaultColor)); // 2.
const auto result = _mm256_cmpeq_epi32(haystack, needle); // 3.
const auto mask = _mm256_movemask_ps(_mm256_castsi256_ps(result)); // 4.
unsigned long index;
@@ -224,7 +219,7 @@ COLORREF TextColor::GetColor(const std::array<COLORREF, TextColor::TABLE_SIZE>&
// --> the index returned by _BitScanForward must be divided by 2.
const auto haystack1 = _mm_loadu_si128(reinterpret_cast<const __m128i*>(colorTable.data() + 0));
const auto haystack2 = _mm_loadu_si128(reinterpret_cast<const __m128i*>(colorTable.data() + 4));
const auto needle = _mm_set1_epi32(std::bit_cast<int>(defaultColor));
const auto needle = _mm_set1_epi32(til::bit_cast<int>(defaultColor));
const auto result1 = _mm_cmpeq_epi32(haystack1, needle);
const auto result2 = _mm_cmpeq_epi32(haystack2, needle);
const auto result = _mm_packs_epi32(result1, result2); // 3.5
@@ -285,3 +280,15 @@ BYTE TextColor::GetLegacyIndex(const BYTE defaultIndex) const noexcept
return til::at(CompressedRgbToIndex16, compressedRgb);
}
}
// Method Description:
// - Return a COLORREF containing our stored value. Will return garbage if this
//attribute is not a RGB attribute.
// Arguments:
// - <none>
// Return Value:
// - a COLORREF containing our stored value
COLORREF TextColor::GetRGB() const noexcept
{
return RGB(_red, _green, _blue);
}

View File

@@ -119,7 +119,6 @@ public:
}
bool CanBeBrightened() const noexcept;
ColorType GetType() const noexcept;
bool IsLegacy() const noexcept;
bool IsIndex16() const noexcept;
bool IsIndex256() const noexcept;
@@ -134,11 +133,12 @@ public:
COLORREF GetColor(const std::array<COLORREF, TABLE_SIZE>& colorTable, const size_t defaultIndex, bool brighten = false) const noexcept;
BYTE GetLegacyIndex(const BYTE defaultIndex) const noexcept;
constexpr BYTE GetIndex() const noexcept { return _index; }
constexpr BYTE GetR() const noexcept { return _red; }
constexpr BYTE GetG() const noexcept { return _green; }
constexpr BYTE GetB() const noexcept { return _blue; }
constexpr COLORREF GetRGB() const noexcept { return RGB(_red, _green, _blue); }
constexpr BYTE GetIndex() const noexcept
{
return _index;
}
COLORREF GetRGB() const noexcept;
static constexpr BYTE TransposeLegacyIndex(const size_t index)
{

View File

@@ -6,87 +6,19 @@
#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);
}
@@ -124,16 +56,11 @@ 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)
{
return dest;
memcpy(dest, src, sizeof(UText));
}
memcpy(dest, src, sizeof(UText));
if (const auto buf = accessBuffer(dest))
{
buf->AddRef();
}
return dest;
}
@@ -155,9 +82,7 @@ try
for (til::CoordType y = range.begin; y < range.end; ++y)
{
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();
length += textBuffer.GetRowByOffset(y).GetText().size();
}
accessLength(ut) = length;
@@ -201,13 +126,11 @@ try
const auto range = accessRowRange(ut);
auto start = ut->chunkNativeStart;
auto limit = ut->chunkNativeLimit;
auto y = accessCurrentRow(ut);
std::wstring_view text;
if (neededIndex < start || neededIndex >= limit)
{
auto y = accessCurrentRow(ut);
std::wstring_view text;
bool wasWrapForced = false;
if (neededIndex < start)
{
do
@@ -215,17 +138,12 @@ try
--y;
if (y < range.begin)
{
assert(false);
return false;
}
const auto& row = textBuffer.GetRowByOffset(y);
text = row.GetText();
wasWrapForced = row.WasWrapForced();
text = textBuffer.GetRowByOffset(y).GetText();
limit = start;
// 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;
start -= text.size();
} while (neededIndex < start);
}
else
@@ -235,32 +153,15 @@ try
++y;
if (y >= range.end)
{
assert(false);
return false;
}
const auto& row = textBuffer.GetRowByOffset(y);
text = row.GetText();
wasWrapForced = row.WasWrapForced();
text = textBuffer.GetRowByOffset(y).GetText();
start = limit;
// 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;
limit += text.size();
} while (neededIndex >= limit);
}
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;
@@ -355,32 +256,18 @@ 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).
Microsoft::Console::ICU::unique_utext Microsoft::Console::ICU::UTextFromTextBuffer(const TextBuffer& textBuffer, til::CoordType rowBeg, til::CoordType rowEnd) noexcept
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).
unique_utext ut{ UTEXT_INITIALIZER };
UErrorCode status = U_ZERO_ERROR;
utext_setup(&ut, 0, &status);
FAIL_FAST_IF(status > U_ZERO_ERROR);
UText ut = UTEXT_INITIALIZER;
ut.providerProperties = (1 << UTEXT_PROVIDER_LENGTH_IS_EXPENSIVE) | (1 << UTEXT_PROVIDER_STABLE_CHUNKS);
ut.pFuncs = &utextFuncs;
ut.context = &textBuffer;

View File

@@ -10,9 +10,8 @@ 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>;
unique_utext UTextFromTextBuffer(const TextBuffer& textBuffer, til::CoordType rowBeg, til::CoordType rowEnd) noexcept;
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,7 +188,11 @@ void Cursor::_RedrawCursor() noexcept
// - <none>
void Cursor::_RedrawCursorAlways() noexcept
{
_parentBuffer.NotifyPaintFrame();
try
{
_parentBuffer.TriggerRedrawCursor(_cPosition);
}
CATCH_LOG();
}
void Cursor::SetPosition(const til::point cPosition) noexcept

View File

@@ -8,26 +8,28 @@
using namespace Microsoft::Console::Types;
bool Search::IsStale(const Microsoft::Console::Render::IRenderData& renderData, const std::wstring_view& needle, bool caseInsensitive) const noexcept
{
return _renderData != &renderData ||
_needle != needle ||
_caseInsensitive != caseInsensitive ||
_lastMutationId != renderData.GetTextBuffer().GetLastMutationId();
}
bool Search::Reset(Microsoft::Console::Render::IRenderData& renderData, const std::wstring_view& needle, bool caseInsensitive, bool reverse)
bool Search::ResetIfStale(Microsoft::Console::Render::IRenderData& renderData, const std::wstring_view& needle, bool reverse, bool caseInsensitive)
{
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 = textBuffer.GetLastMutationId();
_lastMutationId = lastMutationId;
_results = textBuffer.SearchText(needle, caseInsensitive);
_index = reverse ? gsl::narrow_cast<ptrdiff_t>(_results.size()) - 1 : 0;
_step = reverse ? -1 : 1;
return true;
}
@@ -91,9 +93,8 @@ void Search::MovePastPoint(const til::point anchor) noexcept
_index = (index + count) % count;
}
void Search::FindNext(bool reverse) noexcept
void Search::FindNext() noexcept
{
_step = reverse ? -1 : 1;
if (const auto count{ gsl::narrow_cast<ptrdiff_t>(_results.size()) })
{
_index = (_index + _step + count) % count;
@@ -110,6 +111,28 @@ 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
@@ -135,11 +158,6 @@ 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;

View File

@@ -25,19 +25,18 @@ class Search final
public:
Search() = default;
bool IsStale(const Microsoft::Console::Render::IRenderData& renderData, const std::wstring_view& needle, bool caseInsensitive) const noexcept;
bool Reset(Microsoft::Console::Render::IRenderData& renderData, const std::wstring_view& needle, bool caseInsensitive, bool reverse);
bool ResetIfStale(Microsoft::Console::Render::IRenderData& renderData, const std::wstring_view& needle, bool reverse, bool caseInsensitive);
void MoveToCurrentSelection();
void MoveToPoint(til::point anchor) noexcept;
void MovePastPoint(til::point anchor) noexcept;
void FindNext(bool reverse) noexcept;
void FindNext() 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;
private:

File diff suppressed because it is too large Load Diff

View File

@@ -49,6 +49,8 @@ filling in the last row, and updating the screen.
#pragma once
#include <vector>
#include "cursor.h"
#include "Row.hpp"
#include "TextAttribute.hpp"
@@ -64,6 +66,41 @@ 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:
@@ -105,8 +142,7 @@ public:
til::point NavigateCursor(til::point position, til::CoordType distance) const;
// Text insertion functions
void Replace(til::CoordType row, const TextAttribute& attributes, RowWriteState& state);
void Insert(til::CoordType row, const TextAttribute& attributes, RowWriteState& state);
void Write(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);
@@ -167,8 +203,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);
@@ -196,7 +232,7 @@ public:
size_t SpanLength(const til::point coordStart, const til::point coordEnd) const;
std::wstring GetPlainText(til::point start, til::point end) const;
std::wstring GetPlainText(const til::point& start, const til::point& end) const;
struct CopyRequest
{
@@ -283,8 +319,6 @@ public:
const bool isIntenseBold,
std::function<std::tuple<COLORREF, COLORREF, COLORREF>(const TextAttribute&)> GetAttributeColors) const noexcept;
void Serialize(const wchar_t* destination) const;
struct PositionInformation
{
til::CoordType mutableViewportTop{ 0 };
@@ -296,19 +330,16 @@ public:
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;
// Mark handling
std::vector<ScrollMark> GetMarkRows() const;
std::vector<MarkExtents> GetMarkExtents(size_t limit = SIZE_T_MAX) const;
const std::vector<ScrollMark>& GetMarks() const noexcept;
void ClearMarksInRange(const til::point start, const til::point end);
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);
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;
private:
void _reserve(til::size screenBufferSize, const TextAttribute& defaultAttributes);
@@ -333,11 +364,7 @@ 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();
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();
void _trimMarksOutsideBuffer();
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);
@@ -410,6 +437,7 @@ private:
uint64_t _lastMutationId = 0;
Cursor _cursor;
std::vector<ScrollMark> _marks;
bool _isActiveBuffer = false;
#ifdef UNIT_TESTING

View File

@@ -25,8 +25,7 @@ TextBufferTextIterator::TextBufferTextIterator(const TextBufferCellIterator& cel
// Return Value:
// - Read only UTF-16 text data
// TODO GH 2682, fix design so this doesn't have to be suppressed.
GSL_SUPPRESS(26434)
const std::wstring_view TextBufferTextIterator::operator*() const noexcept
[[gsl::suppress(26434)]] const std::wstring_view TextBufferTextIterator::operator*() const noexcept
{
return _view.Chars();
}
@@ -36,8 +35,7 @@ const std::wstring_view TextBufferTextIterator::operator*() const noexcept
// Return Value:
// - Read only UTF-16 text data
// TODO GH 2682, fix design so this doesn't have to be suppressed.
GSL_SUPPRESS(26434)
const std::wstring_view* TextBufferTextIterator::operator->() const noexcept
[[gsl::suppress(26434)]] const std::wstring_view* TextBufferTextIterator::operator->() const noexcept
{
return &_view.Chars();
}

View File

@@ -41,7 +41,7 @@ class UTextAdapterTests
RowWriteState state{
.text = L"abc 𝒶𝒷𝒸 abc ネコちゃん",
};
buffer.Replace(0, TextAttribute{}, state);
buffer.Write(0, TextAttribute{}, state);
VERIFY_IS_TRUE(state.text.empty());
static constexpr auto s = [](til::CoordType beg, til::CoordType end) -> til::point_span {

View File

@@ -166,7 +166,7 @@
<comment>{Locked=qps-ploc,qps-ploca,qps-plocm}</comment>
</data>
<data name="AppDescription" xml:space="preserve">
<value>Τĥз Йéщ Ẃįńđôẃѕ Тéѓmĩиâļ !!! !!! !</value>
<value>Τнĕ Ņëω Ẅίηđŏẃś Ťėŗmįйάĺ !!! !!! !</value>
</data>
<data name="AppDescriptionDev" xml:space="preserve">
<value>The Windows Terminal, but Unofficial</value>
@@ -177,22 +177,22 @@
<comment>{Locked}</comment>
</data>
<data name="AppDescriptionPre" xml:space="preserve">
<value>Щΐňδόŵѕ Ŧęřмĭʼnäℓ ẅîťħ à φřеνίëẃ θƒ џрсøмΐʼnğ ƒĕāŧųřэś !!! !!! !!! !!! !!! </value>
<value>Ŵíňďōẁŝ Тєřмīπǻļ ωїτĥ å ρѓēνіéŵ θƒ ũφсőмϊπġ ƒєąτΰґёѕ !!! !!! !!! !!! !!! </value>
</data>
<data name="ShellExtension_OpenInTerminalMenuItem_Dev" xml:space="preserve">
<value>Open in Terminal (&amp;Dev)</value>
<comment>{Locked} The dev build will never be seen in multiple languages</comment>
</data>
<data name="ShellExtension_OpenInTerminalMenuItem_Canary" xml:space="preserve">
<value>Θρēņ ïη Ţéгmĭηäŀ (&amp;Çäņдѓγ) !!! !!! !</value>
<value>Ŏрέи ìη Тèřmīŋªŀ (&amp;Cãńãґγ) !!! !!! !</value>
<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>Όрèп ìņ Ţêŕmїʼnåļ &amp;Рѓзνι℮ω !!! !!! !</value>
<value>Φφєň ΐñ Ŧéгмϊñаľ &amp;Pŕėνĭώ !!! !!! !</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>Óрêп ìл &amp;Ťěѓmιиåĺ !!! !!</value>
<value>Ωρєⁿ ïπ &amp;Těѓmĭñäĺ !!! !!</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

@@ -166,7 +166,7 @@
<comment>{Locked=qps-ploc,qps-ploca,qps-plocm}</comment>
</data>
<data name="AppDescription" xml:space="preserve">
<value>Τĥз Йéщ Ẃįńđôẃѕ Тéѓmĩиâļ !!! !!! !</value>
<value>Ťĥё Ñēщ Шίⁿðоẅś Ťėгмîήāľ !!! !!! !</value>
</data>
<data name="AppDescriptionDev" xml:space="preserve">
<value>The Windows Terminal, but Unofficial</value>
@@ -177,22 +177,22 @@
<comment>{Locked}</comment>
</data>
<data name="AppDescriptionPre" xml:space="preserve">
<value>Щΐňδόŵѕ Ŧęřмĭʼnäℓ ẅîťħ à φřеνίëẃ θƒ џрсøмΐʼnğ ƒĕāŧųřэś !!! !!! !!! !!! !!! </value>
<value>Шίηđóŵš Ŧĕяmїйà ẁітħ ª φяęνîёщ όƒ ûφĉбмíήĝ ƒêåťµřεŝ !!! !!! !!! !!! !!! </value>
</data>
<data name="ShellExtension_OpenInTerminalMenuItem_Dev" xml:space="preserve">
<value>Open in Terminal (&amp;Dev)</value>
<comment>{Locked} The dev build will never be seen in multiple languages</comment>
</data>
<data name="ShellExtension_OpenInTerminalMenuItem_Canary" xml:space="preserve">
<value>Θρēņ ïη Ţéгmĭηäŀ (&amp;Çäņдѓγ) !!! !!! !</value>
<value>Óрëπ íи Ťēяmілǻŀ (&amp;Cäηàřÿ) !!! !!! !</value>
<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>Όрèп ìņ Ţêŕmїʼnåļ &amp;Рѓзνι℮ω !!! !!! !</value>
<value>Óрзń ΐή Ŧěґмιлāℓ &amp;Pѓéνīĕω !!! !!! !</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>Óрêп ìл &amp;Ťěѓmιиåĺ !!! !!</value>
<value>Ôрëη ïп &amp;Tēѓмϊŋãł !!! !!</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

@@ -166,7 +166,7 @@
<comment>{Locked=qps-ploc,qps-ploca,qps-plocm}</comment>
</data>
<data name="AppDescription" xml:space="preserve">
<value>Τĥз Йéщ Ẃįńđôẃѕ Тéѓmĩиâļ !!! !!! !</value>
<value>Тĥё Ńēẁ Шіπđοωš Тěřмιňαŀ !!! !!! !</value>
</data>
<data name="AppDescriptionDev" xml:space="preserve">
<value>The Windows Terminal, but Unofficial</value>
@@ -177,22 +177,22 @@
<comment>{Locked}</comment>
</data>
<data name="AppDescriptionPre" xml:space="preserve">
<value>Щΐňδόŵѕ Ŧęřмĭʼnäℓ ẅîťħ à φřеνίëẃ θƒ џрсøмΐʼnğ ƒĕāŧųřэś !!! !!! !!! !!! !!! </value>
<value>Шίήďŏшś Ŧêямĩňāľ ŵíτн ă ρѓëνιêω øƒ ũρčŏмįηğ ƒєáţũŗêš !!! !!! !!! !!! !!! </value>
</data>
<data name="ShellExtension_OpenInTerminalMenuItem_Dev" xml:space="preserve">
<value>Open in Terminal (&amp;Dev)</value>
<comment>{Locked} The dev build will never be seen in multiple languages</comment>
</data>
<data name="ShellExtension_OpenInTerminalMenuItem_Canary" xml:space="preserve">
<value>Θρēņ ïη Ţéгmĭηäŀ (&amp;Çäņдѓγ) !!! !!! !</value>
<value>Фφěй ĩń Тêřmιπâł (&amp;Cãⁿǻřу) !!! !!! !</value>
<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>Όрèп ìņ Ţêŕmїʼnåļ &amp;Рѓзνι℮ω !!! !!! !</value>
<value>Óφ℮ʼn ΐŋ Τėřmīйäĺ &amp;Pяєνϊëẃ !!! !!! !</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>Óрêп ìл &amp;Ťěѓmιиåĺ !!! !!</value>
<value>Ορέл ϊŋ &amp;Téŕmįñā !!! !!</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

@@ -0,0 +1,404 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#include "pch.h"
#include "../TerminalSettingsModel/ColorScheme.h"
#include "../TerminalSettingsModel/CascadiaSettings.h"
#include "../types/inc/colorTable.hpp"
#include "JsonTestClass.h"
using namespace Microsoft::Console;
using namespace winrt::Microsoft::Terminal;
using namespace winrt::Microsoft::Terminal::Settings::Model::implementation;
using namespace WEX::Logging;
using namespace WEX::TestExecution;
using namespace WEX::Common;
namespace SettingsModelLocalTests
{
// TODO:microsoft/terminal#3838:
// Unfortunately, these tests _WILL NOT_ work in our CI. We're waiting for
// an updated TAEF that will let us install framework packages when the test
// package is deployed. Until then, these tests won't deploy in CI.
class ColorSchemeTests : public JsonTestClass
{
// Use a custom AppxManifest to ensure that we can activate winrt types
// from our test. This property will tell taef to manually use this as
// the AppxManifest for this test class.
// This does not yet work for anything XAML-y. See TabTests.cpp for more
// details on that.
BEGIN_TEST_CLASS(ColorSchemeTests)
TEST_CLASS_PROPERTY(L"RunAs", L"UAP")
TEST_CLASS_PROPERTY(L"UAP:AppXManifest", L"TestHostAppXManifest.xml")
END_TEST_CLASS()
TEST_METHOD(ParseSimpleColorScheme);
TEST_METHOD(LayerColorSchemesOnArray);
TEST_METHOD(UpdateSchemeReferences);
static Core::Color rgb(uint8_t r, uint8_t g, uint8_t b) noexcept
{
return Core::Color{ r, g, b, 255 };
}
};
void ColorSchemeTests::ParseSimpleColorScheme()
{
const std::string campbellScheme{ "{"
"\"background\" : \"#0C0C0C\","
"\"black\" : \"#0C0C0C\","
"\"blue\" : \"#0037DA\","
"\"brightBlack\" : \"#767676\","
"\"brightBlue\" : \"#3B78FF\","
"\"brightCyan\" : \"#61D6D6\","
"\"brightGreen\" : \"#16C60C\","
"\"brightPurple\" : \"#B4009E\","
"\"brightRed\" : \"#E74856\","
"\"brightWhite\" : \"#F2F2F2\","
"\"brightYellow\" : \"#F9F1A5\","
"\"cursorColor\" : \"#FFFFFF\","
"\"cyan\" : \"#3A96DD\","
"\"foreground\" : \"#F2F2F2\","
"\"green\" : \"#13A10E\","
"\"name\" : \"Campbell\","
"\"purple\" : \"#881798\","
"\"red\" : \"#C50F1F\","
"\"selectionBackground\" : \"#131313\","
"\"white\" : \"#CCCCCC\","
"\"yellow\" : \"#C19C00\""
"}" };
const auto schemeObject = VerifyParseSucceeded(campbellScheme);
auto scheme = ColorScheme::FromJson(schemeObject);
VERIFY_ARE_EQUAL(L"Campbell", scheme->Name());
VERIFY_ARE_EQUAL(til::color(0xf2, 0xf2, 0xf2, 255), til::color{ scheme->Foreground() });
VERIFY_ARE_EQUAL(til::color(0x0c, 0x0c, 0x0c, 255), til::color{ scheme->Background() });
VERIFY_ARE_EQUAL(til::color(0x13, 0x13, 0x13, 255), til::color{ scheme->SelectionBackground() });
VERIFY_ARE_EQUAL(til::color(0xFF, 0xFF, 0xFF, 255), til::color{ scheme->CursorColor() });
std::array<COLORREF, COLOR_TABLE_SIZE> expectedCampbellTable;
const auto campbellSpan = std::span{ expectedCampbellTable };
Utils::InitializeColorTable(campbellSpan);
for (size_t i = 0; i < expectedCampbellTable.size(); i++)
{
const til::color expected{ expectedCampbellTable.at(i) };
const til::color actual{ scheme->Table().at(static_cast<uint32_t>(i)) };
VERIFY_ARE_EQUAL(expected, actual);
}
Log::Comment(L"Roundtrip Test for Color Scheme");
auto outJson{ scheme->ToJson() };
VERIFY_ARE_EQUAL(schemeObject, outJson);
}
void ColorSchemeTests::LayerColorSchemesOnArray()
{
static constexpr std::string_view inboxSettings{ R"({
"schemes": [
{
"background": "#0C0C0C",
"black": "#0C0C0C",
"blue": "#0037DA",
"brightBlack": "#767676",
"brightBlue": "#3B78FF",
"brightCyan": "#61D6D6",
"brightGreen": "#16C60C",
"brightPurple": "#B4009E",
"brightRed": "#E74856",
"brightWhite": "#F2F2F2",
"brightYellow": "#F9F1A5",
"cursorColor": "#FFFFFF",
"cyan": "#3A96DD",
"foreground": "#CCCCCC",
"green": "#13A10E",
"name": "Campbell",
"purple": "#881798",
"red": "#C50F1F",
"selectionBackground": "#FFFFFF",
"white": "#CCCCCC",
"yellow": "#C19C00"
}
]
})" };
static constexpr std::string_view userSettings{ R"({
"profiles": [
{
"name" : "profile0"
}
],
"schemes": [
{
"background": "#121314",
"black": "#121314",
"blue": "#121314",
"brightBlack": "#121314",
"brightBlue": "#121314",
"brightCyan": "#121314",
"brightGreen": "#121314",
"brightPurple": "#121314",
"brightRed": "#121314",
"brightWhite": "#121314",
"brightYellow": "#121314",
"cursorColor": "#121314",
"cyan": "#121314",
"foreground": "#121314",
"green": "#121314",
"name": "Campbell",
"purple": "#121314",
"red": "#121314",
"selectionBackground": "#121314",
"white": "#121314",
"yellow": "#121314"
},
{
"background": "#012456",
"black": "#0C0C0C",
"blue": "#0037DA",
"brightBlack": "#767676",
"brightBlue": "#3B78FF",
"brightCyan": "#61D6D6",
"brightGreen": "#16C60C",
"brightPurple": "#B4009E",
"brightRed": "#E74856",
"brightWhite": "#F2F2F2",
"brightYellow": "#F9F1A5",
"cursorColor": "#FFFFFF",
"cyan": "#3A96DD",
"foreground": "#CCCCCC",
"green": "#13A10E",
"name": "Campbell Powershell",
"purple": "#881798",
"red": "#C50F1F",
"selectionBackground": "#FFFFFF",
"white": "#CCCCCC",
"yellow": "#C19C00"
}
]
})" };
const auto settings = winrt::make_self<CascadiaSettings>(userSettings, inboxSettings);
const auto colorSchemes = settings->GlobalSettings().ColorSchemes();
VERIFY_ARE_EQUAL(2u, colorSchemes.Size());
const auto scheme0 = winrt::get_self<ColorScheme>(colorSchemes.Lookup(L"Campbell"));
VERIFY_ARE_EQUAL(rgb(0x12, 0x13, 0x14), scheme0->Foreground());
VERIFY_ARE_EQUAL(rgb(0x12, 0x13, 0x14), scheme0->Background());
const auto scheme1 = winrt::get_self<ColorScheme>(colorSchemes.Lookup(L"Campbell Powershell"));
VERIFY_ARE_EQUAL(rgb(0xCC, 0xCC, 0xCC), scheme1->Foreground());
VERIFY_ARE_EQUAL(rgb(0x01, 0x24, 0x56), scheme1->Background());
}
void ColorSchemeTests::UpdateSchemeReferences()
{
static constexpr std::string_view settingsString{ R"json({
"defaultProfile": "Inherited reference",
"profiles": {
"defaults": {
"colorScheme": "Campbell"
},
"list": [
{
"name": "Explicit scheme reference",
"colorScheme": "Campbell"
},
{
"name": "Explicit reference; hidden",
"colorScheme": "Campbell",
"hidden": true
},
{
"name": "Inherited reference"
},
{
"name": "Different reference",
"colorScheme": "One Half Dark"
},
{
"name": "rename neither",
"colorScheme":
{
"dark": "One Half Dark",
"light": "One Half Light"
}
},
{
"name": "rename only light",
"colorScheme":
{
"dark": "One Half Dark",
"light": "Campbell"
}
},
{
"name": "rename only dark",
"colorScheme":
{
"dark": "Campbell",
"light": "One Half Light"
}
}
]
},
"schemes": [
{
"background": "#0C0C0C",
"black": "#0C0C0C",
"blue": "#0037DA",
"brightBlack": "#767676",
"brightBlue": "#3B78FF",
"brightCyan": "#61D6D6",
"brightGreen": "#16C60C",
"brightPurple": "#B4009E",
"brightRed": "#E74856",
"brightWhite": "#F2F2F2",
"brightYellow": "#F9F1A5",
"cursorColor": "#FFFFFF",
"cyan": "#3A96DD",
"foreground": "#CCCCCC",
"green": "#13A10E",
"name": "Campbell",
"purple": "#881798",
"red": "#C50F1F",
"selectionBackground": "#FFFFFF",
"white": "#CCCCCC",
"yellow": "#C19C00"
},
{
"background": "#0C0C0C",
"black": "#0C0C0C",
"blue": "#0037DA",
"brightBlack": "#767676",
"brightBlue": "#3B78FF",
"brightCyan": "#61D6D6",
"brightGreen": "#16C60C",
"brightPurple": "#B4009E",
"brightRed": "#E74856",
"brightWhite": "#F2F2F2",
"brightYellow": "#F9F1A5",
"cursorColor": "#FFFFFF",
"cyan": "#3A96DD",
"foreground": "#CCCCCC",
"green": "#13A10E",
"name": "Campbell (renamed)",
"purple": "#881798",
"red": "#C50F1F",
"selectionBackground": "#FFFFFF",
"white": "#CCCCCC",
"yellow": "#C19C00"
},
{
"background": "#282C34",
"black": "#282C34",
"blue": "#61AFEF",
"brightBlack": "#5A6374",
"brightBlue": "#61AFEF",
"brightCyan": "#56B6C2",
"brightGreen": "#98C379",
"brightPurple": "#C678DD",
"brightRed": "#E06C75",
"brightWhite": "#DCDFE4",
"brightYellow": "#E5C07B",
"cursorColor": "#FFFFFF",
"cyan": "#56B6C2",
"foreground": "#DCDFE4",
"green": "#98C379",
"name": "One Half Dark",
"purple": "#C678DD",
"red": "#E06C75",
"selectionBackground": "#FFFFFF",
"white": "#DCDFE4",
"yellow": "#E5C07B"
},
{
"name": "One Half Light",
"foreground": "#383A42",
"background": "#FAFAFA",
"cursorColor": "#4F525D",
"black": "#383A42",
"red": "#E45649",
"green": "#50A14F",
"yellow": "#C18301",
"blue": "#0184BC",
"purple": "#A626A4",
"cyan": "#0997B3",
"white": "#FAFAFA",
"brightBlack": "#4F525D",
"brightRed": "#DF6C75",
"brightGreen": "#98C379",
"brightYellow": "#E4C07A",
"brightBlue": "#61AFEF",
"brightPurple": "#C577DD",
"brightCyan": "#56B5C1",
"brightWhite": "#FFFFFF"
}
]
})json" };
const auto settings{ winrt::make_self<CascadiaSettings>(settingsString) };
const auto newName{ L"Campbell (renamed)" };
settings->UpdateColorSchemeReferences(L"Campbell", newName);
VERIFY_ARE_EQUAL(newName, settings->ProfileDefaults().DefaultAppearance().DarkColorSchemeName());
VERIFY_ARE_EQUAL(newName, settings->ProfileDefaults().DefaultAppearance().LightColorSchemeName());
VERIFY_IS_TRUE(settings->ProfileDefaults().DefaultAppearance().HasDarkColorSchemeName());
VERIFY_IS_TRUE(settings->ProfileDefaults().DefaultAppearance().HasLightColorSchemeName());
const auto& profiles{ settings->AllProfiles() };
{
const auto& prof{ profiles.GetAt(0) };
VERIFY_ARE_EQUAL(newName, prof.DefaultAppearance().DarkColorSchemeName());
VERIFY_IS_TRUE(prof.DefaultAppearance().HasDarkColorSchemeName());
VERIFY_ARE_EQUAL(newName, prof.DefaultAppearance().LightColorSchemeName());
VERIFY_IS_TRUE(prof.DefaultAppearance().HasLightColorSchemeName());
}
{
const auto& prof{ profiles.GetAt(1) };
VERIFY_ARE_EQUAL(newName, prof.DefaultAppearance().DarkColorSchemeName());
VERIFY_IS_TRUE(prof.DefaultAppearance().HasDarkColorSchemeName());
VERIFY_ARE_EQUAL(newName, prof.DefaultAppearance().LightColorSchemeName());
VERIFY_IS_TRUE(prof.DefaultAppearance().HasLightColorSchemeName());
}
{
const auto& prof{ profiles.GetAt(2) };
VERIFY_ARE_EQUAL(newName, prof.DefaultAppearance().DarkColorSchemeName());
VERIFY_IS_FALSE(prof.DefaultAppearance().HasDarkColorSchemeName());
VERIFY_ARE_EQUAL(newName, prof.DefaultAppearance().LightColorSchemeName());
VERIFY_IS_FALSE(prof.DefaultAppearance().HasLightColorSchemeName());
}
{
const auto& prof{ profiles.GetAt(3) };
VERIFY_ARE_EQUAL(L"One Half Dark", prof.DefaultAppearance().DarkColorSchemeName());
VERIFY_IS_TRUE(prof.DefaultAppearance().HasDarkColorSchemeName());
VERIFY_ARE_EQUAL(L"One Half Dark", prof.DefaultAppearance().LightColorSchemeName());
VERIFY_IS_TRUE(prof.DefaultAppearance().HasLightColorSchemeName());
}
{
const auto& prof{ profiles.GetAt(4) };
VERIFY_ARE_EQUAL(L"One Half Dark", prof.DefaultAppearance().DarkColorSchemeName());
VERIFY_ARE_EQUAL(L"One Half Light", prof.DefaultAppearance().LightColorSchemeName());
VERIFY_IS_TRUE(prof.DefaultAppearance().HasDarkColorSchemeName());
VERIFY_IS_TRUE(prof.DefaultAppearance().HasLightColorSchemeName());
}
{
const auto& prof{ profiles.GetAt(5) };
VERIFY_ARE_EQUAL(L"One Half Dark", prof.DefaultAppearance().DarkColorSchemeName());
VERIFY_ARE_EQUAL(newName, prof.DefaultAppearance().LightColorSchemeName());
VERIFY_IS_TRUE(prof.DefaultAppearance().HasDarkColorSchemeName());
VERIFY_IS_TRUE(prof.DefaultAppearance().HasLightColorSchemeName());
}
{
const auto& prof{ profiles.GetAt(6) };
VERIFY_ARE_EQUAL(newName, prof.DefaultAppearance().DarkColorSchemeName());
VERIFY_ARE_EQUAL(L"One Half Light", prof.DefaultAppearance().LightColorSchemeName());
VERIFY_IS_TRUE(prof.DefaultAppearance().HasDarkColorSchemeName());
VERIFY_IS_TRUE(prof.DefaultAppearance().HasLightColorSchemeName());
}
}
}

View File

@@ -15,11 +15,24 @@ using namespace WEX::Logging;
using namespace WEX::TestExecution;
using namespace WEX::Common;
namespace SettingsModelUnitTests
namespace SettingsModelLocalTests
{
// TODO:microsoft/terminal#3838:
// Unfortunately, these tests _WILL NOT_ work in our CI. We're waiting for
// an updated TAEF that will let us install framework packages when the test
// package is deployed. Until then, these tests won't deploy in CI.
class CommandTests : public JsonTestClass
{
TEST_CLASS(CommandTests);
// Use a custom AppxManifest to ensure that we can activate winrt types
// from our test. This property will tell taef to manually use this as
// the AppxManifest for this test class.
// This does not yet work for anything XAML-y. See TabTests.cpp for more
// details on that.
BEGIN_TEST_CLASS(CommandTests)
TEST_CLASS_PROPERTY(L"RunAs", L"UAP")
TEST_CLASS_PROPERTY(L"UAP:AppXManifest", L"TestHostAppXManifest.xml")
END_TEST_CLASS()
TEST_METHOD(ManyCommandsSameAction);
TEST_METHOD(LayerCommand);
@@ -48,19 +61,19 @@ namespace SettingsModelUnitTests
auto commands = winrt::single_threaded_map<winrt::hstring, Command>();
VERIFY_ARE_EQUAL(0u, commands.Size());
{
auto warnings = implementation::Command::LayerJson(commands, commands0Json, OriginTag::None);
auto warnings = implementation::Command::LayerJson(commands, commands0Json);
VERIFY_ARE_EQUAL(0u, warnings.size());
}
VERIFY_ARE_EQUAL(1u, commands.Size());
{
auto warnings = implementation::Command::LayerJson(commands, commands1Json, OriginTag::None);
auto warnings = implementation::Command::LayerJson(commands, commands1Json);
VERIFY_ARE_EQUAL(0u, warnings.size());
}
VERIFY_ARE_EQUAL(2u, commands.Size());
{
auto warnings = implementation::Command::LayerJson(commands, commands2Json, OriginTag::None);
auto warnings = implementation::Command::LayerJson(commands, commands2Json);
VERIFY_ARE_EQUAL(0u, warnings.size());
}
VERIFY_ARE_EQUAL(4u, commands.Size());
@@ -82,7 +95,7 @@ namespace SettingsModelUnitTests
auto commands = winrt::single_threaded_map<winrt::hstring, Command>();
VERIFY_ARE_EQUAL(0u, commands.Size());
{
auto warnings = implementation::Command::LayerJson(commands, commands0Json, OriginTag::None);
auto warnings = implementation::Command::LayerJson(commands, commands0Json);
VERIFY_ARE_EQUAL(0u, warnings.size());
VERIFY_ARE_EQUAL(1u, commands.Size());
auto command = commands.Lookup(L"action0");
@@ -93,7 +106,7 @@ namespace SettingsModelUnitTests
VERIFY_IS_NOT_NULL(realArgs);
}
{
auto warnings = implementation::Command::LayerJson(commands, commands1Json, OriginTag::None);
auto warnings = implementation::Command::LayerJson(commands, commands1Json);
VERIFY_ARE_EQUAL(0u, warnings.size());
VERIFY_ARE_EQUAL(1u, commands.Size());
auto command = commands.Lookup(L"action0");
@@ -103,7 +116,7 @@ namespace SettingsModelUnitTests
VERIFY_IS_NULL(command.ActionAndArgs().Args());
}
{
auto warnings = implementation::Command::LayerJson(commands, commands2Json, OriginTag::None);
auto warnings = implementation::Command::LayerJson(commands, commands2Json);
VERIFY_ARE_EQUAL(0u, warnings.size());
VERIFY_ARE_EQUAL(1u, commands.Size());
auto command = commands.Lookup(L"action0");
@@ -115,7 +128,7 @@ namespace SettingsModelUnitTests
}
{
// This last command should "unbind" the action.
auto warnings = implementation::Command::LayerJson(commands, commands3Json, OriginTag::None);
auto warnings = implementation::Command::LayerJson(commands, commands3Json);
VERIFY_ARE_EQUAL(0u, warnings.size());
VERIFY_ARE_EQUAL(0u, commands.Size());
}
@@ -143,7 +156,7 @@ namespace SettingsModelUnitTests
auto commands = winrt::single_threaded_map<winrt::hstring, Command>();
VERIFY_ARE_EQUAL(0u, commands.Size());
auto warnings = implementation::Command::LayerJson(commands, commands0Json, OriginTag::None);
auto warnings = implementation::Command::LayerJson(commands, commands0Json);
VERIFY_ARE_EQUAL(0u, warnings.size());
VERIFY_ARE_EQUAL(9u, commands.Size());
@@ -156,7 +169,7 @@ namespace SettingsModelUnitTests
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_ARE_EQUAL(SplitDirection::Right, realArgs.SplitDirection());
VERIFY_ARE_EQUAL(0.5f, realArgs.SplitSize());
VERIFY_ARE_EQUAL(0.5, realArgs.SplitSize());
}
{
auto command = commands.Lookup(L"command2");
@@ -167,7 +180,7 @@ namespace SettingsModelUnitTests
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_ARE_EQUAL(SplitDirection::Down, realArgs.SplitDirection());
VERIFY_ARE_EQUAL(0.5f, realArgs.SplitSize());
VERIFY_ARE_EQUAL(0.5, realArgs.SplitSize());
}
{
auto command = commands.Lookup(L"command4");
@@ -178,7 +191,7 @@ namespace SettingsModelUnitTests
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_ARE_EQUAL(SplitDirection::Automatic, realArgs.SplitDirection());
VERIFY_ARE_EQUAL(0.5f, realArgs.SplitSize());
VERIFY_ARE_EQUAL(0.5, realArgs.SplitSize());
}
{
auto command = commands.Lookup(L"command5");
@@ -189,7 +202,7 @@ namespace SettingsModelUnitTests
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_ARE_EQUAL(SplitDirection::Automatic, realArgs.SplitDirection());
VERIFY_ARE_EQUAL(0.5f, realArgs.SplitSize());
VERIFY_ARE_EQUAL(0.5, realArgs.SplitSize());
}
{
auto command = commands.Lookup(L"command6");
@@ -211,7 +224,7 @@ namespace SettingsModelUnitTests
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_ARE_EQUAL(SplitDirection::Right, realArgs.SplitDirection());
VERIFY_ARE_EQUAL(0.5f, realArgs.SplitSize());
VERIFY_ARE_EQUAL(0.5, realArgs.SplitSize());
}
{
auto command = commands.Lookup(L"command8");
@@ -222,7 +235,7 @@ namespace SettingsModelUnitTests
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_ARE_EQUAL(SplitDirection::Left, realArgs.SplitDirection());
VERIFY_ARE_EQUAL(0.5f, realArgs.SplitSize());
VERIFY_ARE_EQUAL(0.5, realArgs.SplitSize());
}
{
auto command = commands.Lookup(L"command9");
@@ -233,7 +246,7 @@ namespace SettingsModelUnitTests
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_ARE_EQUAL(SplitDirection::Up, realArgs.SplitDirection());
VERIFY_ARE_EQUAL(0.5f, realArgs.SplitSize());
VERIFY_ARE_EQUAL(0.5, realArgs.SplitSize());
}
{
auto command = commands.Lookup(L"command10");
@@ -244,7 +257,7 @@ namespace SettingsModelUnitTests
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_ARE_EQUAL(SplitDirection::Down, realArgs.SplitDirection());
VERIFY_ARE_EQUAL(0.5f, realArgs.SplitSize());
VERIFY_ARE_EQUAL(0.5, realArgs.SplitSize());
}
}
@@ -261,7 +274,7 @@ namespace SettingsModelUnitTests
auto commands = winrt::single_threaded_map<winrt::hstring, Command>();
VERIFY_ARE_EQUAL(0u, commands.Size());
auto warnings = implementation::Command::LayerJson(commands, commands0Json, OriginTag::None);
auto warnings = implementation::Command::LayerJson(commands, commands0Json);
VERIFY_ARE_EQUAL(3u, warnings.size());
VERIFY_ARE_EQUAL(1u, commands.Size());
@@ -274,7 +287,7 @@ namespace SettingsModelUnitTests
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_ARE_EQUAL(SplitDirection::Automatic, realArgs.SplitDirection());
VERIFY_ARE_EQUAL(0.25f, realArgs.SplitSize());
VERIFY_ARE_EQUAL(0.25, realArgs.SplitSize());
}
}
@@ -288,7 +301,7 @@ namespace SettingsModelUnitTests
auto commands = winrt::single_threaded_map<winrt::hstring, Command>();
VERIFY_ARE_EQUAL(0u, commands.Size());
{
auto warnings = implementation::Command::LayerJson(commands, commands0Json, OriginTag::None);
auto warnings = implementation::Command::LayerJson(commands, commands0Json);
VERIFY_ARE_EQUAL(0u, warnings.size());
VERIFY_ARE_EQUAL(1u, commands.Size());
@@ -329,7 +342,7 @@ namespace SettingsModelUnitTests
auto commands = winrt::single_threaded_map<winrt::hstring, Command>();
VERIFY_ARE_EQUAL(0u, commands.Size());
auto warnings = implementation::Command::LayerJson(commands, commands0Json, OriginTag::None);
auto warnings = implementation::Command::LayerJson(commands, commands0Json);
VERIFY_ARE_EQUAL(0u, warnings.size());
// There are only 5 commands here: all of the `"none"`, `"auto"`,
@@ -399,7 +412,7 @@ namespace SettingsModelUnitTests
auto commands = winrt::single_threaded_map<winrt::hstring, Command>();
VERIFY_ARE_EQUAL(0u, commands.Size());
auto warnings = implementation::Command::LayerJson(commands, commands0Json, OriginTag::None);
auto warnings = implementation::Command::LayerJson(commands, commands0Json);
VERIFY_ARE_EQUAL(0u, warnings.size());
VERIFY_ARE_EQUAL(1u, commands.Size());
@@ -462,7 +475,7 @@ namespace SettingsModelUnitTests
auto commands = winrt::single_threaded_map<winrt::hstring, Command>();
VERIFY_ARE_EQUAL(0u, commands.Size());
auto warnings = implementation::Command::LayerJson(commands, commands0Json, OriginTag::None);
auto warnings = implementation::Command::LayerJson(commands, commands0Json);
VERIFY_ARE_EQUAL(0u, warnings.size());
VERIFY_ARE_EQUAL(9u, commands.Size());
@@ -473,8 +486,7 @@ namespace SettingsModelUnitTests
VERIFY_ARE_EQUAL(ShortcutAction::NewWindow, command.ActionAndArgs().Action());
const auto& realArgs = command.ActionAndArgs().Args().try_as<NewWindowArgs>();
VERIFY_IS_NOT_NULL(realArgs);
VERIFY_IS_NOT_NULL(realArgs.ContentArgs());
const auto& terminalArgs = realArgs.ContentArgs().try_as<NewTerminalArgs>();
const auto& terminalArgs = realArgs.TerminalArgs();
VERIFY_IS_NOT_NULL(terminalArgs);
auto cmdline = terminalArgs.ToCommandline();
VERIFY_ARE_EQUAL(L"", cmdline);
@@ -487,8 +499,7 @@ namespace SettingsModelUnitTests
VERIFY_ARE_EQUAL(ShortcutAction::NewTab, command.ActionAndArgs().Action());
const auto& realArgs = command.ActionAndArgs().Args().try_as<NewTabArgs>();
VERIFY_IS_NOT_NULL(realArgs);
VERIFY_IS_NOT_NULL(realArgs.ContentArgs());
const auto& terminalArgs = realArgs.ContentArgs().try_as<NewTerminalArgs>();
const auto& terminalArgs = realArgs.TerminalArgs();
VERIFY_IS_NOT_NULL(terminalArgs);
auto cmdline = terminalArgs.ToCommandline();
VERIFY_ARE_EQUAL(L"--profile \"foo\"", cmdline);
@@ -501,8 +512,7 @@ namespace SettingsModelUnitTests
VERIFY_ARE_EQUAL(ShortcutAction::NewWindow, command.ActionAndArgs().Action());
const auto& realArgs = command.ActionAndArgs().Args().try_as<NewWindowArgs>();
VERIFY_IS_NOT_NULL(realArgs);
VERIFY_IS_NOT_NULL(realArgs.ContentArgs());
const auto& terminalArgs = realArgs.ContentArgs().try_as<NewTerminalArgs>();
const auto& terminalArgs = realArgs.TerminalArgs();
VERIFY_IS_NOT_NULL(terminalArgs);
auto cmdline = terminalArgs.ToCommandline();
VERIFY_ARE_EQUAL(L"--profile \"foo\"", cmdline);
@@ -515,8 +525,7 @@ namespace SettingsModelUnitTests
VERIFY_ARE_EQUAL(ShortcutAction::NewWindow, command.ActionAndArgs().Action());
const auto& realArgs = command.ActionAndArgs().Args().try_as<NewWindowArgs>();
VERIFY_IS_NOT_NULL(realArgs);
VERIFY_IS_NOT_NULL(realArgs.ContentArgs());
const auto& terminalArgs = realArgs.ContentArgs().try_as<NewTerminalArgs>();
const auto& terminalArgs = realArgs.TerminalArgs();
VERIFY_IS_NOT_NULL(terminalArgs);
auto cmdline = terminalArgs.ToCommandline();
VERIFY_ARE_EQUAL(L"-- \"bar.exe\"", cmdline);
@@ -529,8 +538,7 @@ namespace SettingsModelUnitTests
VERIFY_ARE_EQUAL(ShortcutAction::NewWindow, command.ActionAndArgs().Action());
const auto& realArgs = command.ActionAndArgs().Args().try_as<NewWindowArgs>();
VERIFY_IS_NOT_NULL(realArgs);
VERIFY_IS_NOT_NULL(realArgs.ContentArgs());
const auto& terminalArgs = realArgs.ContentArgs().try_as<NewTerminalArgs>();
const auto& terminalArgs = realArgs.TerminalArgs();
VERIFY_IS_NOT_NULL(terminalArgs);
auto cmdline = terminalArgs.ToCommandline();
Log::Comment(NoThrowString().Format(
@@ -545,8 +553,7 @@ namespace SettingsModelUnitTests
VERIFY_ARE_EQUAL(ShortcutAction::NewWindow, command.ActionAndArgs().Action());
const auto& realArgs = command.ActionAndArgs().Args().try_as<NewWindowArgs>();
VERIFY_IS_NOT_NULL(realArgs);
VERIFY_IS_NOT_NULL(realArgs.ContentArgs());
const auto& terminalArgs = realArgs.ContentArgs().try_as<NewTerminalArgs>();
const auto& terminalArgs = realArgs.TerminalArgs();
VERIFY_IS_NOT_NULL(terminalArgs);
auto cmdline = terminalArgs.ToCommandline();
Log::Comment(NoThrowString().Format(
@@ -561,8 +568,7 @@ namespace SettingsModelUnitTests
VERIFY_ARE_EQUAL(ShortcutAction::NewWindow, command.ActionAndArgs().Action());
const auto& realArgs = command.ActionAndArgs().Args().try_as<NewWindowArgs>();
VERIFY_IS_NOT_NULL(realArgs);
VERIFY_IS_NOT_NULL(realArgs.ContentArgs());
const auto& terminalArgs = realArgs.ContentArgs().try_as<NewTerminalArgs>();
const auto& terminalArgs = realArgs.TerminalArgs();
VERIFY_IS_NOT_NULL(terminalArgs);
auto cmdline = terminalArgs.ToCommandline();
Log::Comment(NoThrowString().Format(
@@ -577,8 +583,7 @@ namespace SettingsModelUnitTests
VERIFY_ARE_EQUAL(ShortcutAction::NewWindow, command.ActionAndArgs().Action());
const auto& realArgs = command.ActionAndArgs().Args().try_as<NewWindowArgs>();
VERIFY_IS_NOT_NULL(realArgs);
VERIFY_IS_NOT_NULL(realArgs.ContentArgs());
const auto& terminalArgs = realArgs.ContentArgs().try_as<NewTerminalArgs>();
const auto& terminalArgs = realArgs.TerminalArgs();
VERIFY_IS_NOT_NULL(terminalArgs);
auto cmdline = terminalArgs.ToCommandline();
Log::Comment(NoThrowString().Format(
@@ -593,8 +598,7 @@ namespace SettingsModelUnitTests
VERIFY_ARE_EQUAL(ShortcutAction::NewWindow, command.ActionAndArgs().Action());
const auto& realArgs = command.ActionAndArgs().Args().try_as<NewWindowArgs>();
VERIFY_IS_NOT_NULL(realArgs);
VERIFY_IS_NOT_NULL(realArgs.ContentArgs());
const auto& terminalArgs = realArgs.ContentArgs().try_as<NewTerminalArgs>();
const auto& terminalArgs = realArgs.TerminalArgs();
VERIFY_IS_NOT_NULL(terminalArgs);
auto cmdline = terminalArgs.ToCommandline();
Log::Comment(NoThrowString().Format(

View File

@@ -5,10 +5,12 @@
#include "../TerminalSettingsModel/ColorScheme.h"
#include "../TerminalSettingsModel/CascadiaSettings.h"
#include "../TerminalSettingsModel/resource.h"
#include "JsonTestClass.h"
#include "TestUtils.h"
#include <defaults.h>
#include <userDefaults.h>
using namespace Microsoft::Console;
using namespace WEX::Logging;
using namespace WEX::TestExecution;
@@ -17,11 +19,24 @@ using namespace winrt::Microsoft::Terminal::Settings::Model;
using namespace winrt::Microsoft::Terminal::Control;
using VirtualKeyModifiers = winrt::Windows::System::VirtualKeyModifiers;
namespace SettingsModelUnitTests
namespace SettingsModelLocalTests
{
// TODO:microsoft/terminal#3838:
// Unfortunately, these tests _WILL NOT_ work in our CI. We're waiting for
// an updated TAEF that will let us install framework packages when the test
// package is deployed. Until then, these tests won't deploy in CI.
class DeserializationTests : public JsonTestClass
{
TEST_CLASS(DeserializationTests);
// Use a custom AppxManifest to ensure that we can activate winrt types
// from our test. This property will tell taef to manually use this as
// the AppxManifest for this test class.
// This does not yet work for anything XAML-y. See TabTests.cpp for more
// details on that.
BEGIN_TEST_CLASS(DeserializationTests)
TEST_CLASS_PROPERTY(L"RunAs", L"UAP")
TEST_CLASS_PROPERTY(L"UAP:AppXManifest", L"TestHostAppXManifest.xml")
END_TEST_CLASS()
TEST_METHOD(ValidateProfilesExist);
TEST_METHOD(ValidateDefaultProfileExists);
@@ -47,7 +62,6 @@ namespace SettingsModelUnitTests
TEST_METHOD(ValidateKeybindingsWarnings);
TEST_METHOD(ValidateColorSchemeInCommands);
TEST_METHOD(ValidateExecuteCommandlineWarning);
TEST_METHOD(TestClampingOfStartupColumnAndViewProperties);
TEST_METHOD(TestTrailingCommas);
TEST_METHOD(TestCommandsAndKeybindings);
TEST_METHOD(TestNestedCommandWithoutName);
@@ -60,13 +74,6 @@ namespace SettingsModelUnitTests
TEST_METHOD(TestInheritedCommand);
TEST_METHOD(LoadFragmentsWithMultipleUpdates);
TEST_METHOD(FragmentActionSimple);
TEST_METHOD(FragmentActionNoKeys);
TEST_METHOD(FragmentActionNested);
TEST_METHOD(FragmentActionNestedNoName);
TEST_METHOD(FragmentActionIterable);
TEST_METHOD(FragmentActionRoundtrip);
TEST_METHOD(MigrateReloadEnvVars);
private:
@@ -540,7 +547,7 @@ namespace SettingsModelUnitTests
]
})" };
const auto settings = winrt::make_self<implementation::CascadiaSettings>(settings0String, implementation::LoadStringResource(IDR_DEFAULTS));
const auto settings = winrt::make_self<implementation::CascadiaSettings>(settings0String, DefaultJson);
VERIFY_ARE_EQUAL(0u, settings->Warnings().Size());
VERIFY_ARE_EQUAL(4u, settings->AllProfiles().Size());
@@ -618,7 +625,7 @@ namespace SettingsModelUnitTests
]
})" };
const auto settings = winrt::make_self<implementation::CascadiaSettings>(settings0String, implementation::LoadStringResource(IDR_DEFAULTS));
const auto settings = winrt::make_self<implementation::CascadiaSettings>(settings0String, DefaultJson);
VERIFY_ARE_EQUAL(0u, settings->Warnings().Size());
VERIFY_ARE_EQUAL(4u, settings->AllProfiles().Size());
@@ -655,7 +662,7 @@ namespace SettingsModelUnitTests
]
})" };
const auto settings = winrt::make_self<implementation::CascadiaSettings>(settings0String, implementation::LoadStringResource(IDR_DEFAULTS));
const auto settings = winrt::make_self<implementation::CascadiaSettings>(settings0String, DefaultJson);
const auto profiles = settings->AllProfiles();
VERIFY_ARE_EQUAL(5u, profiles.Size());
VERIFY_ARE_EQUAL(L"ThisProfileIsGood", profiles.GetAt(0).Name());
@@ -1064,7 +1071,7 @@ namespace SettingsModelUnitTests
const auto guid1String = L"{6239a42c-1111-49a3-80bd-e8fdd045185c}";
const winrt::guid guid1{ Utils::GuidFromString(guid1String) };
const auto settings = winrt::make_self<implementation::CascadiaSettings>(settings0String, implementation::LoadStringResource(IDR_DEFAULTS));
const auto settings = winrt::make_self<implementation::CascadiaSettings>(settings0String, DefaultJson);
VERIFY_ARE_EQUAL(guid1String, settings->GlobalSettings().UnparsedDefaultProfile());
VERIFY_ARE_EQUAL(4u, settings->AllProfiles().Size());
@@ -1302,20 +1309,6 @@ namespace SettingsModelUnitTests
VERIFY_ARE_EQUAL(SettingsLoadWarnings::MissingRequiredParameter, settings->Warnings().GetAt(3));
}
void DeserializationTests::TestClampingOfStartupColumnAndViewProperties()
{
static constexpr std::string_view inputSettings{ R"({
"initialCols" : 1000000,
"initialRows" : -1000000,
"profiles": [{ "name": "profile0" }]
})" };
const auto settings = createSettings(inputSettings);
VERIFY_ARE_EQUAL(999, settings->GlobalSettings().InitialCols());
VERIFY_ARE_EQUAL(1, settings->GlobalSettings().InitialRows());
}
void DeserializationTests::TestTrailingCommas()
{
static constexpr std::string_view badSettings{ R"({
@@ -1390,13 +1383,11 @@ namespace SettingsModelUnitTests
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_ARE_EQUAL(SplitDirection::Right, realArgs.SplitDirection());
VERIFY_IS_NOT_NULL(realArgs.ContentArgs());
const 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_TRUE(terminalArgs.Profile().empty());
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_TRUE(realArgs.TerminalArgs().Profile().empty());
}
Log::Comment(L"Note that we're skipping ctrl+B, since that doesn't have `keys` set.");
@@ -1409,13 +1400,11 @@ namespace SettingsModelUnitTests
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_ARE_EQUAL(SplitDirection::Right, realArgs.SplitDirection());
VERIFY_IS_NOT_NULL(realArgs.ContentArgs());
const 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_TRUE(terminalArgs.Profile().empty());
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_TRUE(realArgs.TerminalArgs().Profile().empty());
}
{
const KeyChord kc{ true, false, false, false, static_cast<int32_t>('D'), 0 };
@@ -1425,13 +1414,11 @@ namespace SettingsModelUnitTests
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_ARE_EQUAL(SplitDirection::Right, realArgs.SplitDirection());
VERIFY_IS_NOT_NULL(realArgs.ContentArgs());
const 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_TRUE(terminalArgs.Profile().empty());
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_TRUE(realArgs.TerminalArgs().Profile().empty());
}
{
const KeyChord kc{ true, false, false, false, static_cast<int32_t>('E'), 0 };
@@ -1441,13 +1428,11 @@ namespace SettingsModelUnitTests
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_ARE_EQUAL(SplitDirection::Down, realArgs.SplitDirection());
VERIFY_IS_NOT_NULL(realArgs.ContentArgs());
const 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_TRUE(terminalArgs.Profile().empty());
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_TRUE(realArgs.TerminalArgs().Profile().empty());
}
{
const KeyChord kc{ true, false, false, false, static_cast<int32_t>('F'), 0 };
@@ -1457,13 +1442,11 @@ namespace SettingsModelUnitTests
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_ARE_EQUAL(SplitDirection::Down, realArgs.SplitDirection());
VERIFY_IS_NOT_NULL(realArgs.ContentArgs());
const 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_TRUE(terminalArgs.Profile().empty());
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_TRUE(realArgs.TerminalArgs().Profile().empty());
}
Log::Comment(L"Now verify the commands");
@@ -1488,13 +1471,11 @@ namespace SettingsModelUnitTests
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_ARE_EQUAL(SplitDirection::Right, realArgs.SplitDirection());
VERIFY_IS_NOT_NULL(realArgs.ContentArgs());
const 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_TRUE(terminalArgs.Profile().empty());
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_TRUE(realArgs.TerminalArgs().Profile().empty());
}
{
// This was renamed to null (aka removed from the name map) in F. So this does not exist.
@@ -2031,7 +2012,7 @@ namespace SettingsModelUnitTests
]
})" };
implementation::SettingsLoader loader{ std::string_view{}, implementation::LoadStringResource(IDR_DEFAULTS) };
implementation::SettingsLoader loader{ std::string_view{}, DefaultJson };
loader.MergeInboxIntoUserSettings();
loader.MergeFragmentIntoUserSettings(winrt::hstring{ fragmentSource }, fragmentJson);
loader.FinalizeLayering();
@@ -2042,189 +2023,6 @@ namespace SettingsModelUnitTests
VERIFY_ARE_EQUAL(L"NewName", loader.userSettings.profiles[0]->Name());
}
void DeserializationTests::FragmentActionSimple()
{
static constexpr std::wstring_view fragmentSource{ L"fragment" };
static constexpr std::string_view fragmentJson{ R"({
"actions": [
{
"command": { "action": "addMark" },
"name": "Test Action"
},
]
})" };
implementation::SettingsLoader loader{ std::string_view{}, implementation::LoadStringResource(IDR_DEFAULTS) };
loader.MergeInboxIntoUserSettings();
loader.MergeFragmentIntoUserSettings(winrt::hstring{ fragmentSource }, fragmentJson);
loader.FinalizeLayering();
const auto settings = winrt::make_self<implementation::CascadiaSettings>(std::move(loader));
const auto actionMap = winrt::get_self<implementation::ActionMap>(settings->GlobalSettings().ActionMap());
const auto actionsByName = actionMap->NameMap();
VERIFY_IS_NOT_NULL(actionsByName.TryLookup(L"Test Action"));
}
void DeserializationTests::FragmentActionNoKeys()
{
static constexpr std::wstring_view fragmentSource{ L"fragment" };
static constexpr std::string_view fragmentJson{ R"({
"actions": [
{
"command": { "action": "addMark" },
"keys": "ctrl+f",
"name": "Test Action"
},
]
})" };
implementation::SettingsLoader loader{ std::string_view{}, implementation::LoadStringResource(IDR_DEFAULTS) };
loader.MergeInboxIntoUserSettings();
loader.MergeFragmentIntoUserSettings(winrt::hstring{ fragmentSource }, fragmentJson);
loader.FinalizeLayering();
const auto settings = winrt::make_self<implementation::CascadiaSettings>(std::move(loader));
const auto actionMap = winrt::get_self<implementation::ActionMap>(settings->GlobalSettings().ActionMap());
const auto actionsByName = actionMap->NameMap();
VERIFY_IS_NOT_NULL(actionsByName.TryLookup(L"Test Action"));
VERIFY_IS_NULL(actionMap->GetActionByKeyChord({ VirtualKeyModifiers::Control, static_cast<int32_t>('F'), 0 }));
}
void DeserializationTests::FragmentActionNested()
{
static constexpr std::wstring_view fragmentSource{ L"fragment" };
static constexpr std::string_view fragmentJson{ R"({
"actions": [
{
"name": "nested command",
"commands": [
{
"name": "child1",
"command": { "action": "newTab", "commandline": "ssh me@first.com" }
},
{
"name": "child2",
"command": { "action": "newTab", "commandline": "ssh me@second.com" }
}
]
},
]
})" };
implementation::SettingsLoader loader{ std::string_view{}, implementation::LoadStringResource(IDR_DEFAULTS) };
loader.MergeInboxIntoUserSettings();
loader.MergeFragmentIntoUserSettings(winrt::hstring{ fragmentSource }, fragmentJson);
loader.FinalizeLayering();
const auto settings = winrt::make_self<implementation::CascadiaSettings>(std::move(loader));
const auto actionMap = winrt::get_self<implementation::ActionMap>(settings->GlobalSettings().ActionMap());
const auto actionsByName = actionMap->NameMap();
const auto& nested{ actionsByName.TryLookup(L"nested command") };
VERIFY_IS_NOT_NULL(nested);
VERIFY_IS_TRUE(nested.HasNestedCommands());
}
void DeserializationTests::FragmentActionNestedNoName()
{
// Basically the same as TestNestedCommandWithoutName
static constexpr std::wstring_view fragmentSource{ L"fragment" };
static constexpr std::string_view fragmentJson{ R"({
"actions": [
{
"commands": [
{
"name": "child1",
"command": { "action": "newTab", "commandline": "ssh me@first.com" }
},
{
"name": "child2",
"command": { "action": "newTab", "commandline": "ssh me@second.com" }
}
]
},
]
})" };
implementation::SettingsLoader loader{ std::string_view{}, implementation::LoadStringResource(IDR_DEFAULTS) };
loader.MergeInboxIntoUserSettings();
loader.MergeFragmentIntoUserSettings(winrt::hstring{ fragmentSource }, fragmentJson);
loader.FinalizeLayering();
const auto settings = winrt::make_self<implementation::CascadiaSettings>(std::move(loader));
VERIFY_ARE_EQUAL(0u, settings->Warnings().Size());
}
void DeserializationTests::FragmentActionIterable()
{
static constexpr std::wstring_view fragmentSource{ L"fragment" };
static constexpr std::string_view fragmentJson{ R"({
"actions": [
{
"name": "nested",
"commands": [
{
"iterateOn": "schemes",
"name": "${scheme.name}",
"command": { "action": "setColorScheme", "colorScheme": "${scheme.name}" }
}
]
},
]
})" };
implementation::SettingsLoader loader{ std::string_view{}, implementation::LoadStringResource(IDR_DEFAULTS) };
loader.MergeInboxIntoUserSettings();
loader.MergeFragmentIntoUserSettings(winrt::hstring{ fragmentSource }, fragmentJson);
loader.FinalizeLayering();
const auto settings = winrt::make_self<implementation::CascadiaSettings>(std::move(loader));
const auto actionMap = winrt::get_self<implementation::ActionMap>(settings->GlobalSettings().ActionMap());
const auto actionsByName = actionMap->NameMap();
const auto& nested{ actionsByName.TryLookup(L"nested") };
VERIFY_IS_NOT_NULL(nested);
VERIFY_IS_TRUE(nested.HasNestedCommands());
VERIFY_ARE_EQUAL(settings->GlobalSettings().ColorSchemes().Size(), nested.NestedCommands().Size());
}
void DeserializationTests::FragmentActionRoundtrip()
{
static constexpr std::wstring_view fragmentSource{ L"fragment" };
static constexpr std::string_view fragmentJson{ R"({
"actions": [
{
"command": { "action": "addMark" },
"name": "Test Action"
},
]
})" };
implementation::SettingsLoader loader{ std::string_view{}, implementation::LoadStringResource(IDR_DEFAULTS) };
loader.MergeInboxIntoUserSettings();
loader.MergeFragmentIntoUserSettings(winrt::hstring{ fragmentSource }, fragmentJson);
loader.FinalizeLayering();
const auto oldSettings = winrt::make_self<implementation::CascadiaSettings>(std::move(loader));
const auto actionMap = winrt::get_self<implementation::ActionMap>(oldSettings->GlobalSettings().ActionMap());
const auto actionsByName = actionMap->NameMap();
VERIFY_IS_NOT_NULL(actionsByName.TryLookup(L"Test Action"));
const auto oldResult{ oldSettings->ToJson() };
Log::Comment(L"Now, create a _new_ settings object from the re-serialization of the first");
implementation::SettingsLoader newLoader{ toString(oldResult), implementation::LoadStringResource(IDR_DEFAULTS) };
// NOTABLY! Don't load the fragment here.
newLoader.MergeInboxIntoUserSettings();
newLoader.FinalizeLayering();
const auto newSettings = winrt::make_self<implementation::CascadiaSettings>(std::move(newLoader));
const auto& newActionMap = winrt::get_self<implementation::ActionMap>(newSettings->GlobalSettings().ActionMap());
const auto newActionsByName = newActionMap->NameMap();
VERIFY_IS_NULL(newActionsByName.TryLookup(L"Test Action"));
}
void DeserializationTests::MigrateReloadEnvVars()
{
static constexpr std::string_view settings1Json{ R"(
@@ -2248,7 +2046,7 @@ namespace SettingsModelUnitTests
]
})" };
implementation::SettingsLoader loader{ settings1Json, implementation::LoadStringResource(IDR_DEFAULTS) };
implementation::SettingsLoader loader{ settings1Json, DefaultJson };
loader.MergeInboxIntoUserSettings();
loader.FinalizeLayering();

View File

@@ -17,17 +17,29 @@ using namespace WEX::TestExecution;
using namespace WEX::Common;
using VirtualKeyModifiers = winrt::Windows::System::VirtualKeyModifiers;
namespace SettingsModelUnitTests
namespace SettingsModelLocalTests
{
// TODO:microsoft/terminal#3838:
// Unfortunately, these tests _WILL NOT_ work in our CI. We're waiting for
// an updated TAEF that will let us install framework packages when the test
// package is deployed. Until then, these tests won't deploy in CI.
class KeyBindingsTests : public JsonTestClass
{
TEST_CLASS(KeyBindingsTests);
// Use a custom AppxManifest to ensure that we can activate winrt types
// from our test. This property will tell taef to manually use this as
// the AppxManifest for this test class.
// This does not yet work for anything XAML-y. See TabTests.cpp for more
// details on that.
BEGIN_TEST_CLASS(KeyBindingsTests)
TEST_CLASS_PROPERTY(L"RunAs", L"UAP")
TEST_CLASS_PROPERTY(L"UAP:AppXManifest", L"TestHostAppXManifest.xml")
END_TEST_CLASS()
TEST_METHOD(KeyChords);
TEST_METHOD(ManyKeysSameAction);
TEST_METHOD(LayerKeybindings);
TEST_METHOD(HashDeduplication);
TEST_METHOD(HashContentArgs);
TEST_METHOD(UnbindKeybindings);
TEST_METHOD(LayerScancodeKeybindings);
TEST_METHOD(TestExplicitUnbind);
@@ -121,13 +133,13 @@ namespace SettingsModelUnitTests
auto actionMap = winrt::make_self<implementation::ActionMap>();
VERIFY_ARE_EQUAL(0u, actionMap->_KeyMap.size());
actionMap->LayerJson(bindings0Json, OriginTag::None);
actionMap->LayerJson(bindings0Json);
VERIFY_ARE_EQUAL(1u, actionMap->_KeyMap.size());
actionMap->LayerJson(bindings1Json, OriginTag::None);
actionMap->LayerJson(bindings1Json);
VERIFY_ARE_EQUAL(2u, actionMap->_KeyMap.size());
actionMap->LayerJson(bindings2Json, OriginTag::None);
actionMap->LayerJson(bindings2Json);
VERIFY_ARE_EQUAL(4u, actionMap->_KeyMap.size());
}
@@ -144,50 +156,24 @@ namespace SettingsModelUnitTests
auto actionMap = winrt::make_self<implementation::ActionMap>();
VERIFY_ARE_EQUAL(0u, actionMap->_KeyMap.size());
actionMap->LayerJson(bindings0Json, OriginTag::None);
actionMap->LayerJson(bindings0Json);
VERIFY_ARE_EQUAL(1u, actionMap->_KeyMap.size());
actionMap->LayerJson(bindings1Json, OriginTag::None);
actionMap->LayerJson(bindings1Json);
VERIFY_ARE_EQUAL(1u, actionMap->_KeyMap.size());
actionMap->LayerJson(bindings2Json, OriginTag::None);
actionMap->LayerJson(bindings2Json);
VERIFY_ARE_EQUAL(2u, actionMap->_KeyMap.size());
}
void KeyBindingsTests::HashDeduplication()
{
const auto actionMap = winrt::make_self<implementation::ActionMap>();
actionMap->LayerJson(VerifyParseSucceeded(R"([ { "command": "splitPane", "keys": ["ctrl+c"] } ])"), OriginTag::None);
actionMap->LayerJson(VerifyParseSucceeded(R"([ { "command": "splitPane", "keys": ["ctrl+c"] } ])"), OriginTag::None);
actionMap->LayerJson(VerifyParseSucceeded(R"([ { "command": "splitPane", "keys": ["ctrl+c"] } ])"));
actionMap->LayerJson(VerifyParseSucceeded(R"([ { "command": "splitPane", "keys": ["ctrl+c"] } ])"));
VERIFY_ARE_EQUAL(1u, actionMap->_ActionMap.size());
}
void KeyBindingsTests::HashContentArgs()
{
Log::Comment(L"These are two actions with different content args. They should have different hashes for their terminal args.");
const auto actionMap = winrt::make_self<implementation::ActionMap>();
actionMap->LayerJson(VerifyParseSucceeded(R"([ { "command": { "action": "newTab", } , "keys": ["ctrl+c"] } ])"), OriginTag::None);
actionMap->LayerJson(VerifyParseSucceeded(R"([ { "command": { "action": "newTab", "index": 0 } , "keys": ["ctrl+shift+c"] } ])"), OriginTag::None);
VERIFY_ARE_EQUAL(2u, actionMap->_ActionMap.size());
KeyChord ctrlC{ VirtualKeyModifiers::Control, static_cast<int32_t>('C'), 0 };
KeyChord ctrlShiftC{ VirtualKeyModifiers::Control | VirtualKeyModifiers::Shift, static_cast<int32_t>('C'), 0 };
auto hashFromKey = [&](auto& kc) {
auto actionAndArgs = ::TestUtils::GetActionAndArgs(*actionMap, kc);
VERIFY_ARE_EQUAL(ShortcutAction::NewTab, actionAndArgs.Action());
const auto& realArgs = actionAndArgs.Args().as<NewTabArgs>();
VERIFY_IS_NOT_NULL(realArgs.ContentArgs());
const auto terminalArgs{ realArgs.ContentArgs().try_as<NewTerminalArgs>() };
return terminalArgs.Hash();
};
const auto hashOne = hashFromKey(ctrlC);
const auto hashTwo = hashFromKey(ctrlShiftC);
VERIFY_ARE_NOT_EQUAL(hashOne, hashTwo);
}
void KeyBindingsTests::UnbindKeybindings()
{
const std::string bindings0String{ R"([ { "command": "copy", "keys": ["ctrl+c"] } ])" };
@@ -207,51 +193,51 @@ namespace SettingsModelUnitTests
auto actionMap = winrt::make_self<implementation::ActionMap>();
VERIFY_ARE_EQUAL(0u, actionMap->_KeyMap.size());
actionMap->LayerJson(bindings0Json, OriginTag::None);
actionMap->LayerJson(bindings0Json);
VERIFY_ARE_EQUAL(1u, actionMap->_KeyMap.size());
actionMap->LayerJson(bindings1Json, OriginTag::None);
actionMap->LayerJson(bindings1Json);
VERIFY_ARE_EQUAL(1u, actionMap->_KeyMap.size());
Log::Comment(NoThrowString().Format(
L"Try unbinding a key using `\"unbound\"` to unbind the key"));
actionMap->LayerJson(bindings2Json, OriginTag::None);
actionMap->LayerJson(bindings2Json);
VERIFY_ARE_EQUAL(1u, actionMap->_KeyMap.size());
VERIFY_IS_NULL(actionMap->GetActionByKeyChord({ VirtualKeyModifiers::Control, static_cast<int32_t>('C'), 0 }));
Log::Comment(NoThrowString().Format(
L"Try unbinding a key using `null` to unbind the key"));
// First add back a good binding
actionMap->LayerJson(bindings0Json, OriginTag::None);
actionMap->LayerJson(bindings0Json);
VERIFY_ARE_EQUAL(1u, actionMap->_KeyMap.size());
// Then try layering in the bad setting
actionMap->LayerJson(bindings3Json, OriginTag::None);
actionMap->LayerJson(bindings3Json);
VERIFY_ARE_EQUAL(1u, actionMap->_KeyMap.size());
VERIFY_IS_NULL(actionMap->GetActionByKeyChord({ VirtualKeyModifiers::Control, static_cast<int32_t>('C'), 0 }));
Log::Comment(NoThrowString().Format(
L"Try unbinding a key using an unrecognized command to unbind the key"));
// First add back a good binding
actionMap->LayerJson(bindings0Json, OriginTag::None);
actionMap->LayerJson(bindings0Json);
VERIFY_ARE_EQUAL(1u, actionMap->_KeyMap.size());
// Then try layering in the bad setting
actionMap->LayerJson(bindings4Json, OriginTag::None);
actionMap->LayerJson(bindings4Json);
VERIFY_ARE_EQUAL(1u, actionMap->_KeyMap.size());
VERIFY_IS_NULL(actionMap->GetActionByKeyChord({ VirtualKeyModifiers::Control, static_cast<int32_t>('C'), 0 }));
Log::Comment(NoThrowString().Format(
L"Try unbinding a key using a straight up invalid value to unbind the key"));
// First add back a good binding
actionMap->LayerJson(bindings0Json, OriginTag::None);
actionMap->LayerJson(bindings0Json);
VERIFY_ARE_EQUAL(1u, actionMap->_KeyMap.size());
// Then try layering in the bad setting
actionMap->LayerJson(bindings5Json, OriginTag::None);
actionMap->LayerJson(bindings5Json);
VERIFY_ARE_EQUAL(1u, actionMap->_KeyMap.size());
VERIFY_IS_NULL(actionMap->GetActionByKeyChord({ VirtualKeyModifiers::Control, static_cast<int32_t>('C'), 0 }));
Log::Comment(NoThrowString().Format(
L"Try unbinding a key that wasn't bound at all"));
actionMap->LayerJson(bindings2Json, OriginTag::None);
actionMap->LayerJson(bindings2Json);
VERIFY_ARE_EQUAL(1u, actionMap->_KeyMap.size());
VERIFY_IS_NULL(actionMap->GetActionByKeyChord({ VirtualKeyModifiers::Control, static_cast<int32_t>('C'), 0 }));
}
@@ -271,13 +257,13 @@ namespace SettingsModelUnitTests
auto actionMap = winrt::make_self<implementation::ActionMap>();
VERIFY_IS_FALSE(actionMap->IsKeyChordExplicitlyUnbound(keyChord));
actionMap->LayerJson(bindings0Json, OriginTag::None);
actionMap->LayerJson(bindings0Json);
VERIFY_IS_FALSE(actionMap->IsKeyChordExplicitlyUnbound(keyChord));
actionMap->LayerJson(bindings1Json, OriginTag::None);
actionMap->LayerJson(bindings1Json);
VERIFY_IS_TRUE(actionMap->IsKeyChordExplicitlyUnbound(keyChord));
actionMap->LayerJson(bindings2Json, OriginTag::None);
actionMap->LayerJson(bindings2Json);
VERIFY_IS_FALSE(actionMap->IsKeyChordExplicitlyUnbound(keyChord));
}
@@ -304,7 +290,7 @@ namespace SettingsModelUnitTests
auto actionMap = winrt::make_self<implementation::ActionMap>();
VERIFY_ARE_EQUAL(0u, actionMap->_KeyMap.size());
actionMap->LayerJson(bindings0Json, OriginTag::None);
actionMap->LayerJson(bindings0Json);
VERIFY_ARE_EQUAL(10u, actionMap->_KeyMap.size());
{
@@ -345,10 +331,8 @@ namespace SettingsModelUnitTests
VERIFY_ARE_EQUAL(ShortcutAction::NewTab, actionAndArgs.Action());
const auto& realArgs = actionAndArgs.Args().as<NewTabArgs>();
// Verify the args have the expected value
VERIFY_IS_NOT_NULL(realArgs.ContentArgs());
const auto terminalArgs{ realArgs.ContentArgs().try_as<NewTerminalArgs>() };
VERIFY_IS_NOT_NULL(terminalArgs);
VERIFY_IS_NULL(terminalArgs.ProfileIndex());
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
VERIFY_IS_NULL(realArgs.TerminalArgs().ProfileIndex());
}
{
Log::Comment(NoThrowString().Format(
@@ -358,11 +342,9 @@ namespace SettingsModelUnitTests
VERIFY_ARE_EQUAL(ShortcutAction::NewTab, actionAndArgs.Action());
const auto& realArgs = actionAndArgs.Args().as<NewTabArgs>();
// Verify the args have the expected value
VERIFY_IS_NOT_NULL(realArgs.ContentArgs());
const auto terminalArgs{ realArgs.ContentArgs().try_as<NewTerminalArgs>() };
VERIFY_IS_NOT_NULL(terminalArgs);
VERIFY_IS_NOT_NULL(terminalArgs.ProfileIndex());
VERIFY_ARE_EQUAL(0, terminalArgs.ProfileIndex().Value());
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs().ProfileIndex());
VERIFY_ARE_EQUAL(0, realArgs.TerminalArgs().ProfileIndex().Value());
}
{
Log::Comment(NoThrowString().Format(
@@ -373,11 +355,9 @@ namespace SettingsModelUnitTests
VERIFY_ARE_EQUAL(ShortcutAction::NewTab, actionAndArgs.Action());
const auto& realArgs = actionAndArgs.Args().as<NewTabArgs>();
// Verify the args have the expected value
VERIFY_IS_NOT_NULL(realArgs.ContentArgs());
const auto terminalArgs{ realArgs.ContentArgs().try_as<NewTerminalArgs>() };
VERIFY_IS_NOT_NULL(terminalArgs);
VERIFY_IS_NOT_NULL(terminalArgs.ProfileIndex());
VERIFY_ARE_EQUAL(11, terminalArgs.ProfileIndex().Value());
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs().ProfileIndex());
VERIFY_ARE_EQUAL(11, realArgs.TerminalArgs().ProfileIndex().Value());
}
{
@@ -438,7 +418,7 @@ namespace SettingsModelUnitTests
auto actionMap = winrt::make_self<implementation::ActionMap>();
VERIFY_ARE_EQUAL(0u, actionMap->_KeyMap.size());
actionMap->LayerJson(bindings0Json, OriginTag::None);
actionMap->LayerJson(bindings0Json);
VERIFY_ARE_EQUAL(4u, actionMap->_KeyMap.size());
{
@@ -487,7 +467,7 @@ namespace SettingsModelUnitTests
auto actionMap = winrt::make_self<implementation::ActionMap>();
VERIFY_ARE_EQUAL(0u, actionMap->_KeyMap.size());
actionMap->LayerJson(bindings0Json, OriginTag::None);
actionMap->LayerJson(bindings0Json);
VERIFY_ARE_EQUAL(3u, actionMap->_KeyMap.size());
{
@@ -528,7 +508,7 @@ namespace SettingsModelUnitTests
auto actionMap = winrt::make_self<implementation::ActionMap>();
VERIFY_ARE_EQUAL(0u, actionMap->_KeyMap.size());
actionMap->LayerJson(bindings0Json, OriginTag::None);
actionMap->LayerJson(bindings0Json);
VERIFY_ARE_EQUAL(1u, actionMap->_KeyMap.size());
{
@@ -555,7 +535,7 @@ namespace SettingsModelUnitTests
auto actionMap = winrt::make_self<implementation::ActionMap>();
VERIFY_ARE_EQUAL(0u, actionMap->_KeyMap.size());
actionMap->LayerJson(bindings0Json, OriginTag::None);
actionMap->LayerJson(bindings0Json);
VERIFY_ARE_EQUAL(6u, actionMap->_KeyMap.size());
{
@@ -613,7 +593,7 @@ namespace SettingsModelUnitTests
const auto bindingsInvalidJson = VerifyParseSucceeded(bindingsInvalidString);
auto invalidActionMap = winrt::make_self<implementation::ActionMap>();
VERIFY_ARE_EQUAL(0u, invalidActionMap->_KeyMap.size());
VERIFY_THROWS(invalidActionMap->LayerJson(bindingsInvalidJson, OriginTag::None);, std::exception);
VERIFY_THROWS(invalidActionMap->LayerJson(bindingsInvalidJson);, std::exception);
}
}
@@ -628,7 +608,7 @@ namespace SettingsModelUnitTests
auto actionMap = winrt::make_self<implementation::ActionMap>();
VERIFY_ARE_EQUAL(0u, actionMap->_KeyMap.size());
actionMap->LayerJson(bindings0Json, OriginTag::None);
actionMap->LayerJson(bindings0Json);
VERIFY_ARE_EQUAL(2u, actionMap->_KeyMap.size());
{
@@ -650,7 +630,7 @@ namespace SettingsModelUnitTests
{
const std::string bindingsInvalidString{ R"([{ "keys": ["up"], "command": "moveTab" }])" };
auto actionMapNoArgs = winrt::make_self<implementation::ActionMap>();
actionMapNoArgs->LayerJson(bindingsInvalidString, OriginTag::None);
actionMapNoArgs->LayerJson(bindingsInvalidString);
VERIFY_ARE_EQUAL(0u, actionMapNoArgs->_KeyMap.size());
}
{
@@ -658,7 +638,7 @@ namespace SettingsModelUnitTests
const auto bindingsInvalidJson = VerifyParseSucceeded(bindingsInvalidString);
auto invalidActionMap = winrt::make_self<implementation::ActionMap>();
VERIFY_ARE_EQUAL(0u, invalidActionMap->_KeyMap.size());
VERIFY_THROWS(invalidActionMap->LayerJson(bindingsInvalidJson, OriginTag::None);, std::exception);
VERIFY_THROWS(invalidActionMap->LayerJson(bindingsInvalidJson);, std::exception);
}
}
@@ -674,7 +654,7 @@ namespace SettingsModelUnitTests
auto actionMap = winrt::make_self<implementation::ActionMap>();
VERIFY_ARE_EQUAL(0u, actionMap->_KeyMap.size());
actionMap->LayerJson(bindings0Json, OriginTag::None);
actionMap->LayerJson(bindings0Json);
VERIFY_ARE_EQUAL(3u, actionMap->_KeyMap.size());
{
@@ -706,7 +686,7 @@ namespace SettingsModelUnitTests
const auto bindingsInvalidJson = VerifyParseSucceeded(bindingsInvalidString);
auto invalidActionMap = winrt::make_self<implementation::ActionMap>();
VERIFY_ARE_EQUAL(0u, invalidActionMap->_KeyMap.size());
VERIFY_THROWS(invalidActionMap->LayerJson(bindingsInvalidJson, OriginTag::None);, std::exception);
VERIFY_THROWS(invalidActionMap->LayerJson(bindingsInvalidJson);, std::exception);
}
}
@@ -740,14 +720,14 @@ namespace SettingsModelUnitTests
{
Log::Comment(L"simple command: no args");
actionMap->LayerJson(bindings0Json, OriginTag::None);
actionMap->LayerJson(bindings0Json);
VERIFY_ARE_EQUAL(1u, actionMap->_KeyMap.size());
const auto& kbd{ actionMap->GetKeyBindingForAction(ShortcutAction::CloseWindow) };
VerifyKeyChordEquality({ VirtualKeyModifiers::Control, static_cast<int32_t>('A'), 0 }, kbd);
}
{
Log::Comment(L"command with args");
actionMap->LayerJson(bindings1Json, OriginTag::None);
actionMap->LayerJson(bindings1Json);
VERIFY_ARE_EQUAL(2u, actionMap->_KeyMap.size());
auto args{ winrt::make_self<implementation::CopyTextArgs>() };
@@ -758,7 +738,7 @@ namespace SettingsModelUnitTests
}
{
Log::Comment(L"command with new terminal args");
actionMap->LayerJson(bindings2Json, OriginTag::None);
actionMap->LayerJson(bindings2Json);
VERIFY_ARE_EQUAL(3u, actionMap->_KeyMap.size());
auto newTerminalArgs{ winrt::make_self<implementation::NewTerminalArgs>() };
@@ -770,7 +750,7 @@ namespace SettingsModelUnitTests
}
{
Log::Comment(L"command with hidden args");
actionMap->LayerJson(bindings3Json, OriginTag::None);
actionMap->LayerJson(bindings3Json);
VERIFY_ARE_EQUAL(4u, actionMap->_KeyMap.size());
const auto& kbd{ actionMap->GetKeyBindingForAction(ShortcutAction::ToggleCommandPalette) };
@@ -795,13 +775,13 @@ namespace SettingsModelUnitTests
auto actionMap = winrt::make_self<implementation::ActionMap>();
VERIFY_ARE_EQUAL(0u, actionMap->_KeyMap.size());
actionMap->LayerJson(bindings0Json, OriginTag::None);
actionMap->LayerJson(bindings0Json);
VERIFY_ARE_EQUAL(1u, actionMap->_KeyMap.size());
actionMap->LayerJson(bindings1Json, OriginTag::None);
actionMap->LayerJson(bindings1Json);
VERIFY_ARE_EQUAL(1u, actionMap->_KeyMap.size(), L"Layering the second action should replace the first one.");
actionMap->LayerJson(bindings2Json, OriginTag::None);
actionMap->LayerJson(bindings2Json);
VERIFY_ARE_EQUAL(2u, actionMap->_KeyMap.size());
}
@@ -810,7 +790,7 @@ namespace SettingsModelUnitTests
const auto json = VerifyParseSucceeded(R"!([{"command": "quakeMode", "keys":"shift+sc(255)"}])!");
const auto actionMap = winrt::make_self<implementation::ActionMap>();
actionMap->LayerJson(json, OriginTag::None);
actionMap->LayerJson(json);
const auto action = actionMap->GetActionByKeyChord({ VirtualKeyModifiers::Shift, 0, 255 });
VERIFY_IS_NOT_NULL(action);

View File

@@ -6,10 +6,11 @@
#include "../TerminalSettingsModel/NewTabMenuEntry.h"
#include "../TerminalSettingsModel/FolderEntry.h"
#include "../TerminalSettingsModel/CascadiaSettings.h"
#include "../TerminalSettingsModel/resource.h"
#include "../types/inc/colorTable.hpp"
#include "JsonTestClass.h"
#include <defaults.h>
using namespace Microsoft::Console;
using namespace winrt::Microsoft::Terminal;
using namespace winrt::Microsoft::Terminal::Settings::Model::implementation;
@@ -17,11 +18,24 @@ using namespace WEX::Logging;
using namespace WEX::TestExecution;
using namespace WEX::Common;
namespace SettingsModelUnitTests
namespace SettingsModelLocalTests
{
// TODO:microsoft/terminal#3838:
// Unfortunately, these tests _WILL NOT_ work in our CI. We're waiting for
// an updated TAEF that will let us install framework packages when the test
// package is deployed. Until then, these tests won't deploy in CI.
class NewTabMenuTests : public JsonTestClass
{
TEST_CLASS(NewTabMenuTests);
// Use a custom AppxManifest to ensure that we can activate winrt types
// from our test. This property will tell taef to manually use this as
// the AppxManifest for this test class.
// This does not yet work for anything XAML-y. See TabTests.cpp for more
// details on that.
BEGIN_TEST_CLASS(NewTabMenuTests)
TEST_CLASS_PROPERTY(L"RunAs", L"UAP")
TEST_CLASS_PROPERTY(L"UAP:AppXManifest", L"TestHostAppXManifest.xml")
END_TEST_CLASS()
TEST_METHOD(DefaultsToRemainingProfiles);
TEST_METHOD(ParseEmptyFolder);
@@ -36,7 +50,7 @@ namespace SettingsModelUnitTests
try
{
const auto settings{ winrt::make_self<CascadiaSettings>(settingsString, LoadStringResource(IDR_DEFAULTS)) };
const auto settings{ winrt::make_self<CascadiaSettings>(settingsString, DefaultJson) };
VERIFY_ARE_EQUAL(0u, settings->Warnings().Size());
@@ -70,7 +84,7 @@ namespace SettingsModelUnitTests
try
{
const auto settings{ winrt::make_self<CascadiaSettings>(settingsString, LoadStringResource(IDR_DEFAULTS)) };
const auto settings{ winrt::make_self<CascadiaSettings>(settingsString, DefaultJson) };
VERIFY_ARE_EQUAL(0u, settings->Warnings().Size());

View File

@@ -5,20 +5,34 @@
#include "../TerminalSettingsModel/ColorScheme.h"
#include "../TerminalSettingsModel/CascadiaSettings.h"
#include "../TerminalSettingsModel/resource.h"
#include "JsonTestClass.h"
#include <defaults.h>
using namespace Microsoft::Console;
using namespace winrt::Microsoft::Terminal::Settings::Model;
using namespace WEX::Logging;
using namespace WEX::TestExecution;
using namespace WEX::Common;
namespace SettingsModelUnitTests
namespace SettingsModelLocalTests
{
// TODO:microsoft/terminal#3838:
// Unfortunately, these tests _WILL NOT_ work in our CI. We're waiting for
// an updated TAEF that will let us install framework packages when the test
// package is deployed. Until then, these tests won't deploy in CI.
class ProfileTests : public JsonTestClass
{
TEST_CLASS(ProfileTests);
// Use a custom AppxManifest to ensure that we can activate winrt types
// from our test. This property will tell taef to manually use this as
// the AppxManifest for this test class.
// This does not yet work for anything XAML-y. See TabTests.cpp for more
// details on that.
BEGIN_TEST_CLASS(ProfileTests)
TEST_CLASS_PROPERTY(L"RunAs", L"UAP")
TEST_CLASS_PROPERTY(L"UAP:AppXManifest", L"TestHostAppXManifest.xml")
END_TEST_CLASS()
TEST_METHOD(ProfileGeneratesGuid);
TEST_METHOD(LayerProfileProperties);
@@ -45,15 +59,6 @@ namespace SettingsModelUnitTests
// this test that includes synthesizing GUIDS for profiles without GUIDs
// set
const auto parseAndVerifyProfile = [](const std::string profile, const bool hasGuid) {
const auto profileAsJson = VerifyParseSucceeded(profile);
const auto profileParsed = implementation::Profile::FromJson(profileAsJson);
VERIFY_ARE_EQUAL(profileParsed->HasGuid(), hasGuid);
return profileParsed;
};
// Invalid GUID Values
const std::string profileWithoutGuid{ R"({
"name" : "profile0"
})" };
@@ -64,50 +69,37 @@ namespace SettingsModelUnitTests
"name" : "profile2",
"guid" : null
})" };
const std::string profileWithHyphenlessGuid{ R"({
"name" : "profile4",
"guid" : "{6239A42C1DE449A380BDE8FDD045185C}"
})" };
const std::string profileWithRawGuid{ R"({
"name" : "profile4",
"guid" : "6239a42c-1de4-49a3-80bd-e8fdd045185c"
})" };
const std::string profileWithGuidFormatP{ R"({
"name" : "profile4",
"guid" : "(6239a42c-1de4-49a3-80bd-e8fdd045185c)\\"
})" };
// Valid GUIDs
const std::string profileWithNullGuid{ R"({
"name" : "profile3",
"guid" : "{00000000-0000-0000-0000-000000000000}"
})" };
const std::string profileWithGuidFormatB{ R"({
const std::string profileWithGuid{ R"({
"name" : "profile4",
"guid" : "{6239a42c-1de4-49a3-80bd-e8fdd045185c}"
})" };
const std::string profileWithGuidUpperCaseFormatB{ R"({
"name" : "profile4",
"guid" : "{6239A42C-1DE4-49A3-80BD-E8FDD045185C}"
})" };
parseAndVerifyProfile(profileWithoutGuid, false);
parseAndVerifyProfile(secondProfileWithoutGuid, false);
const auto profile0Json = VerifyParseSucceeded(profileWithoutGuid);
const auto profile1Json = VerifyParseSucceeded(secondProfileWithoutGuid);
const auto profile2Json = VerifyParseSucceeded(profileWithNullForGuid);
const auto profile3Json = VerifyParseSucceeded(profileWithNullGuid);
const auto profile4Json = VerifyParseSucceeded(profileWithGuid);
// The following crash JSON parsing
VERIFY_THROWS(parseAndVerifyProfile(profileWithHyphenlessGuid, false), std::exception);
VERIFY_THROWS(parseAndVerifyProfile(profileWithRawGuid, false), std::exception);
VERIFY_THROWS(parseAndVerifyProfile(profileWithGuidFormatP, false), std::exception);
const auto parsedNullGuidProfile = parseAndVerifyProfile(profileWithNullGuid, true);
const auto parsedGuidProfileFormatB = parseAndVerifyProfile(profileWithGuidFormatB, true);
const auto parsedGuidProfileUpperCaseFormatB = parseAndVerifyProfile(profileWithGuidUpperCaseFormatB, true);
const winrt::guid nullGuid{};
const auto profile0 = implementation::Profile::FromJson(profile0Json);
const auto profile1 = implementation::Profile::FromJson(profile1Json);
const auto profile2 = implementation::Profile::FromJson(profile2Json);
const auto profile3 = implementation::Profile::FromJson(profile3Json);
const auto profile4 = implementation::Profile::FromJson(profile4Json);
const winrt::guid cmdGuid = Utils::GuidFromString(L"{6239a42c-1de4-49a3-80bd-e8fdd045185c}");
const winrt::guid nullGuid{};
VERIFY_ARE_EQUAL(parsedNullGuidProfile->Guid(), nullGuid);
VERIFY_ARE_EQUAL(parsedGuidProfileFormatB->Guid(), cmdGuid);
VERIFY_ARE_EQUAL(parsedGuidProfileUpperCaseFormatB->Guid(), cmdGuid);
VERIFY_IS_FALSE(profile0->HasGuid());
VERIFY_IS_FALSE(profile1->HasGuid());
VERIFY_IS_FALSE(profile2->HasGuid());
VERIFY_IS_TRUE(profile3->HasGuid());
VERIFY_IS_TRUE(profile4->HasGuid());
VERIFY_ARE_EQUAL(profile3->Guid(), nullGuid);
VERIFY_ARE_EQUAL(profile4->Guid(), cmdGuid);
}
void ProfileTests::LayerProfileProperties()

View File

@@ -5,9 +5,9 @@
#include "../TerminalSettingsModel/ColorScheme.h"
#include "../TerminalSettingsModel/CascadiaSettings.h"
#include "../TerminalSettingsModel/resource.h"
#include "JsonTestClass.h"
#include "TestUtils.h"
#include <defaults.h>
using namespace Microsoft::Console;
using namespace WEX::Logging;
@@ -16,19 +16,24 @@ using namespace WEX::Common;
using namespace winrt::Microsoft::Terminal::Settings::Model;
using namespace winrt::Microsoft::Terminal::Control;
// Different architectures will hash the same SendInput command to a different ID
// Check for the correct ID based on the architecture
#if defined(_M_IX86)
#define SEND_INPUT_ARCH_SPECIFIC_ACTION_HASH "56911147"
#else
#define SEND_INPUT_ARCH_SPECIFIC_ACTION_HASH "A020D2"
#endif
namespace SettingsModelUnitTests
namespace SettingsModelLocalTests
{
// TODO:microsoft/terminal#3838:
// Unfortunately, these tests _WILL NOT_ work in our CI. We're waiting for
// an updated TAEF that will let us install framework packages when the test
// package is deployed. Until then, these tests won't deploy in CI.
class SerializationTests : public JsonTestClass
{
TEST_CLASS(SerializationTests);
// Use a custom AppxManifest to ensure that we can activate winrt types
// from our test. This property will tell taef to manually use this as
// the AppxManifest for this test class.
// This does not yet work for anything XAML-y. See TabTests.cpp for more
// details on that.
BEGIN_TEST_CLASS(SerializationTests)
TEST_CLASS_PROPERTY(L"RunAs", L"UAP")
TEST_CLASS_PROPERTY(L"UAP:AppXManifest", L"TestHostAppXManifest.xml")
END_TEST_CLASS()
TEST_METHOD(GlobalSettings);
TEST_METHOD(Profile);
@@ -40,14 +45,6 @@ namespace SettingsModelUnitTests
TEST_METHOD(RoundtripReloadEnvVars);
TEST_METHOD(DontRoundtripNoReloadEnvVars);
TEST_METHOD(RoundtripUserModifiedColorSchemeCollision);
TEST_METHOD(RoundtripUserModifiedColorSchemeCollisionUnusedByProfiles);
TEST_METHOD(RoundtripUserDeletedColorSchemeCollision);
TEST_METHOD(RoundtripGenerateActionID);
TEST_METHOD(NoGeneratedIDsForIterableAndNestedCommands);
TEST_METHOD(GeneratedActionIDsEqualForIdenticalCommands);
private:
// Method Description:
// - deserializes and reserializes a json string representing a settings object model of type T
@@ -71,19 +68,6 @@ namespace SettingsModelUnitTests
// written alphabetically.
VERIFY_ARE_EQUAL(toString(json), toString(result));
}
// Helper to remove the `$schema` property from a json object. We
// populate that based off the local path to the settings file. Of
// course, that's entirely unpredictable in tests. So cut it out before
// we do any sort of roundtrip testing.
static Json::Value removeSchema(Json::Value json)
{
if (json.isMember("$schema"))
{
json.removeMember("$schema");
}
return json;
}
};
void SerializationTests::GlobalSettings()
@@ -119,6 +103,8 @@ namespace SettingsModelUnitTests
"trimPaste": true,
"experimental.input.forceVT": false,
"experimental.rendering.forceFullRepaint": false,
"experimental.rendering.software": false,
"actions": []
})" };
@@ -151,7 +137,7 @@ namespace SettingsModelUnitTests
"font": {
"face": "Cascadia Mono",
"size": 12,
"size": 12.0,
"weight": "normal"
},
"padding": "8, 8, 8, 8",
@@ -175,7 +161,7 @@ namespace SettingsModelUnitTests
"backgroundImage": "made_you_look.jpeg",
"backgroundImageStretchMode": "uniformToFill",
"backgroundImageAlignment": "center",
"backgroundImageOpacity": 1,
"backgroundImageOpacity": 1.0,
"scrollbarState": "visible",
"snapOnInput": true,
@@ -209,34 +195,9 @@ namespace SettingsModelUnitTests
"source": "local"
})" };
static constexpr std::string_view profileWithIcon{ R"(
{
"guid" : "{8b039d4d-77ca-5a83-88e1-dfc8e895a127}",
"name": "profileWithIcon",
"hidden": false,
"icon": "foo.png"
})" };
static constexpr std::string_view profileWithNullIcon{ R"(
{
"guid" : "{8b039d4d-77ca-5a83-88e1-dfc8e895a127}",
"name": "profileWithNullIcon",
"hidden": false,
"icon": null
})" };
static constexpr std::string_view profileWithNoIcon{ R"(
{
"guid" : "{8b039d4d-77ca-5a83-88e1-dfc8e895a127}",
"name": "profileWithNoIcon",
"hidden": false,
"icon": "none"
})" };
RoundtripTest<implementation::Profile>(profileString);
RoundtripTest<implementation::Profile>(smallProfileString);
RoundtripTest<implementation::Profile>(weirdProfileString);
RoundtripTest<implementation::Profile>(profileWithIcon);
RoundtripTest<implementation::Profile>(profileWithNullIcon);
RoundtripTest<implementation::Profile>(profileWithNoIcon);
}
void SerializationTests::ColorScheme()
@@ -298,8 +259,17 @@ namespace SettingsModelUnitTests
// complex command with key chords
static constexpr std::string_view actionsString4A{ R"([
{ "command": { "action": "adjustFontSize", "delta": 1 }, "keys": "ctrl+c" },
{ "command": { "action": "adjustFontSize", "delta": 1 }, "keys": "ctrl+d" }
{ "command": { "action": "adjustFontSize", "delta": 1.0 }, "keys": "ctrl+c" },
{ "command": { "action": "adjustFontSize", "delta": 1.0 }, "keys": "ctrl+d" }
])" };
// GH#13323 - these can be fragile. In the past, the order these get
// re-serialized as has been not entirely stable. We don't really care
// about the order they get re-serialized in, but the tests aren't
// clever enough to compare the structure, only the literal string
// itself. Feel free to change as needed.
static constexpr std::string_view actionsString4B{ R"([
{ "command": { "action": "findMatch", "direction": "prev" }, "keys": "ctrl+shift+r" },
{ "command": { "action": "adjustFontSize", "delta": 1.0 }, "keys": "ctrl+d" }
])" };
// command with name and icon and multiple key chords
@@ -323,8 +293,8 @@ namespace SettingsModelUnitTests
{
"name": "Change font size...",
"commands": [
{ "command": { "action": "adjustFontSize", "delta": 1 } },
{ "command": { "action": "adjustFontSize", "delta": -1 } },
{ "command": { "action": "adjustFontSize", "delta": 1.0 } },
{ "command": { "action": "adjustFontSize", "delta": -1.0 } },
{ "command": "resetFontSize" },
]
}
@@ -414,6 +384,7 @@ namespace SettingsModelUnitTests
Log::Comment(L"complex commands with key chords");
RoundtripTest<implementation::ActionMap>(actionsString4A);
RoundtripTest<implementation::ActionMap>(actionsString4B);
Log::Comment(L"command with name and icon and multiple key chords");
RoundtripTest<implementation::ActionMap>(actionsString5);
@@ -503,7 +474,7 @@ namespace SettingsModelUnitTests
}
],
"actions": [
{ "command": { "action": "sendInput", "input": "VT Griese Mode" }, "id": "User.sendInput.E02B3DF9", "keys": "ctrl+k" }
{ "command": { "action": "sendInput", "input": "VT Griese Mode" }, "keys": "ctrl+k" }
],
"theme": "system",
"themes": []
@@ -512,8 +483,7 @@ namespace SettingsModelUnitTests
const auto settings{ winrt::make_self<implementation::CascadiaSettings>(settingsString) };
const auto result{ settings->ToJson() };
VERIFY_ARE_EQUAL(toString(removeSchema(VerifyParseSucceeded(settingsString))),
toString(removeSchema(result)));
VERIFY_ARE_EQUAL(toString(VerifyParseSucceeded(settingsString)), toString(result));
}
void SerializationTests::LegacyFontSettings()
@@ -523,7 +493,7 @@ namespace SettingsModelUnitTests
"name": "Profile with legacy font settings",
"fontFace": "Cascadia Mono",
"fontSize": 12,
"fontSize": 12.0,
"fontWeight": "normal"
})" };
@@ -533,7 +503,7 @@ namespace SettingsModelUnitTests
"font": {
"face": "Cascadia Mono",
"size": 12,
"size": 12.0,
"weight": "normal"
}
})" };
@@ -598,14 +568,14 @@ namespace SettingsModelUnitTests
]
})" };
implementation::SettingsLoader oldLoader{ oldSettingsJson, implementation::LoadStringResource(IDR_DEFAULTS) };
implementation::SettingsLoader oldLoader{ oldSettingsJson, DefaultJson };
oldLoader.MergeInboxIntoUserSettings();
oldLoader.FinalizeLayering();
VERIFY_IS_TRUE(oldLoader.FixupUserSettings(), L"Validate that this will indicate we need to write them back to disk");
const auto oldSettings = winrt::make_self<implementation::CascadiaSettings>(std::move(oldLoader));
const auto oldResult{ oldSettings->ToJson() };
implementation::SettingsLoader newLoader{ newSettingsJson, implementation::LoadStringResource(IDR_DEFAULTS) };
implementation::SettingsLoader newLoader{ newSettingsJson, DefaultJson };
newLoader.MergeInboxIntoUserSettings();
newLoader.FinalizeLayering();
newLoader.FixupUserSettings();
@@ -640,7 +610,7 @@ namespace SettingsModelUnitTests
]
})" };
implementation::SettingsLoader oldLoader{ oldSettingsJson, implementation::LoadStringResource(IDR_DEFAULTS) };
implementation::SettingsLoader oldLoader{ oldSettingsJson, DefaultJson };
oldLoader.MergeInboxIntoUserSettings();
oldLoader.FinalizeLayering();
oldLoader.FixupUserSettings();
@@ -648,7 +618,7 @@ namespace SettingsModelUnitTests
const auto oldResult{ oldSettings->ToJson() };
Log::Comment(L"Now, create a _new_ settings object from the re-serialization of the first");
implementation::SettingsLoader newLoader{ toString(oldResult), implementation::LoadStringResource(IDR_DEFAULTS) };
implementation::SettingsLoader newLoader{ toString(oldResult), DefaultJson };
newLoader.MergeInboxIntoUserSettings();
newLoader.FinalizeLayering();
newLoader.FixupUserSettings();
@@ -656,413 +626,4 @@ namespace SettingsModelUnitTests
VERIFY_IS_FALSE(newSettings->ProfileDefaults().HasReloadEnvironmentVariables(),
L"Ensure that the new settings object didn't find a reloadEnvironmentVariables");
}
void SerializationTests::RoundtripUserModifiedColorSchemeCollision()
{
static constexpr std::string_view oldSettingsJson{ R"(
{
"defaultProfile": "{6239a42c-0000-49a3-80bd-e8fdd045185c}",
"profiles": [
{
"name": "profile0",
"guid": "{6239a42c-0000-49a3-80bd-e8fdd045185c}"
},
{
"name": "profile1",
"colorScheme": "Tango Dark",
"guid": "{d0a65a9d-8665-4128-97a4-a581aa747aa7}"
}
],
"schemes": [
{
"background": "#121314",
"black": "#121314",
"blue": "#121314",
"brightBlack": "#121314",
"brightBlue": "#121314",
"brightCyan": "#121314",
"brightGreen": "#121314",
"brightPurple": "#121314",
"brightRed": "#121314",
"brightWhite": "#121314",
"brightYellow": "#121314",
"cursorColor": "#121314",
"cyan": "#121314",
"foreground": "#121314",
"green": "#121314",
"name": "Campbell",
"purple": "#121314",
"red": "#121314",
"selectionBackground": "#121314",
"white": "#121314",
"yellow": "#121314"
},
{
"background": "#000000",
"black": "#000000",
"blue": "#3465A4",
"brightBlack": "#555753",
"brightBlue": "#729FCF",
"brightCyan": "#34E2E2",
"brightGreen": "#8AE234",
"brightPurple": "#AD7FA8",
"brightRed": "#EF2929",
"brightWhite": "#EEEEEC",
"brightYellow": "#FCE94F",
"cursorColor": "#FFFFFF",
"cyan": "#06989A",
"foreground": "#D3D7CF",
"green": "#4E9A06",
"name": "Tango Dark",
"purple": "#75507B",
"red": "#CC0000",
"selectionBackground": "#FFFFFF",
"white": "#D3D7CF",
"yellow": "#C4A000"
},
]
})" };
// Key differences: one fewer color scheme (Tango Dark has been deleted) and defaults.colorScheme is set.
static constexpr std::string_view newSettingsJson{ R"-(
{
"defaultProfile": "{6239a42c-0000-49a3-80bd-e8fdd045185c}",
"profiles":
{
"defaults": {
"colorScheme": "Campbell (modified)"
},
"list":
[
{
"name": "profile0",
"guid": "{6239a42c-0000-49a3-80bd-e8fdd045185c}"
},
{
"name": "profile1",
"colorScheme": "Tango Dark",
"guid": "{d0a65a9d-8665-4128-97a4-a581aa747aa7}"
}
]
},
"actions": [ ],
"schemes": [
{
"background": "#121314",
"black": "#121314",
"blue": "#121314",
"brightBlack": "#121314",
"brightBlue": "#121314",
"brightCyan": "#121314",
"brightGreen": "#121314",
"brightPurple": "#121314",
"brightRed": "#121314",
"brightWhite": "#121314",
"brightYellow": "#121314",
"cursorColor": "#121314",
"cyan": "#121314",
"foreground": "#121314",
"green": "#121314",
"name": "Campbell",
"purple": "#121314",
"red": "#121314",
"selectionBackground": "#121314",
"white": "#121314",
"yellow": "#121314"
}
]
})-" };
implementation::SettingsLoader oldLoader{ oldSettingsJson, implementation::LoadStringResource(IDR_DEFAULTS) };
oldLoader.MergeInboxIntoUserSettings();
oldLoader.FinalizeLayering();
VERIFY_IS_TRUE(oldLoader.FixupUserSettings(), L"Validate that this will indicate we need to write them back to disk");
const auto oldSettings = winrt::make_self<implementation::CascadiaSettings>(std::move(oldLoader));
const auto oldResult{ oldSettings->ToJson() };
implementation::SettingsLoader newLoader{ newSettingsJson, implementation::LoadStringResource(IDR_DEFAULTS) };
newLoader.MergeInboxIntoUserSettings();
newLoader.FinalizeLayering();
newLoader.FixupUserSettings();
const auto newSettings = winrt::make_self<implementation::CascadiaSettings>(std::move(newLoader));
const auto newResult{ newSettings->ToJson() };
VERIFY_ARE_EQUAL(toString(newResult), toString(oldResult));
}
void SerializationTests::RoundtripUserModifiedColorSchemeCollisionUnusedByProfiles()
{
static constexpr std::string_view oldSettingsJson{ R"(
{
"defaultProfile": "{6239a42c-0000-49a3-80bd-e8fdd045185c}",
"profiles": [
{
"name": "profile0",
"guid": "{6239a42c-0000-49a3-80bd-e8fdd045185c}"
}
],
"schemes": [
{
"background": "#111111",
"black": "#111111",
"blue": "#111111",
"brightBlack": "#111111",
"brightBlue": "#111111",
"brightCyan": "#111111",
"brightGreen": "#111111",
"brightPurple": "#111111",
"brightRed": "#111111",
"brightWhite": "#111111",
"brightYellow": "#111111",
"cursorColor": "#111111",
"cyan": "#111111",
"foreground": "#111111",
"green": "#111111",
"name": "Tango Dark",
"purple": "#111111",
"red": "#111111",
"selectionBackground": "#111111",
"white": "#111111",
"yellow": "#111111"
},
]
})" };
// Key differences: Tango Dark has been renamed; nothing else has changed
static constexpr std::string_view newSettingsJson{ R"-(
{
"defaultProfile": "{6239a42c-0000-49a3-80bd-e8fdd045185c}",
"profiles":
{
"list":
[
{
"name": "profile0",
"guid": "{6239a42c-0000-49a3-80bd-e8fdd045185c}"
}
]
},
"actions": [ ],
"schemes": [
{
"background": "#111111",
"black": "#111111",
"blue": "#111111",
"brightBlack": "#111111",
"brightBlue": "#111111",
"brightCyan": "#111111",
"brightGreen": "#111111",
"brightPurple": "#111111",
"brightRed": "#111111",
"brightWhite": "#111111",
"brightYellow": "#111111",
"cursorColor": "#111111",
"cyan": "#111111",
"foreground": "#111111",
"green": "#111111",
"name": "Tango Dark (modified)",
"purple": "#111111",
"red": "#111111",
"selectionBackground": "#111111",
"white": "#111111",
"yellow": "#111111"
},
]
})-" };
implementation::SettingsLoader oldLoader{ oldSettingsJson, implementation::LoadStringResource(IDR_DEFAULTS) };
oldLoader.MergeInboxIntoUserSettings();
oldLoader.FinalizeLayering();
VERIFY_IS_TRUE(oldLoader.FixupUserSettings(), L"Validate that this will indicate we need to write them back to disk");
const auto oldSettings = winrt::make_self<implementation::CascadiaSettings>(std::move(oldLoader));
const auto oldResult{ oldSettings->ToJson() };
implementation::SettingsLoader newLoader{ newSettingsJson, implementation::LoadStringResource(IDR_DEFAULTS) };
newLoader.MergeInboxIntoUserSettings();
newLoader.FinalizeLayering();
newLoader.FixupUserSettings();
const auto newSettings = winrt::make_self<implementation::CascadiaSettings>(std::move(newLoader));
const auto newResult{ newSettings->ToJson() };
VERIFY_ARE_EQUAL(toString(newResult), toString(oldResult));
}
void SerializationTests::RoundtripUserDeletedColorSchemeCollision()
{
static constexpr std::string_view oldSettingsJson{ R"(
{
"defaultProfile": "{6239a42c-0000-49a3-80bd-e8fdd045185c}",
"profiles": [
{
"name": "profile0",
"guid": "{6239a42c-0000-49a3-80bd-e8fdd045185c}"
}
],
"schemes": [
{
"name": "Tango Dark",
"foreground": "#D3D7CF",
"background": "#000000",
"cursorColor": "#FFFFFF",
"black": "#000000",
"red": "#CC0000",
"green": "#4E9A06",
"yellow": "#C4A000",
"blue": "#3465A4",
"purple": "#75507B",
"cyan": "#06989A",
"white": "#D3D7CF",
"brightBlack": "#555753",
"brightRed": "#EF2929",
"brightGreen": "#8AE234",
"brightYellow": "#FCE94F",
"brightBlue": "#729FCF",
"brightPurple": "#AD7FA8",
"brightCyan": "#34E2E2",
"brightWhite": "#EEEEEC"
}
]
})" };
// Key differences: Tango Dark has been deleted, as it was identical to the inbox one.
static constexpr std::string_view newSettingsJson{ R"-(
{
"defaultProfile": "{6239a42c-0000-49a3-80bd-e8fdd045185c}",
"profiles":
{
"list":
[
{
"name": "profile0",
"guid": "{6239a42c-0000-49a3-80bd-e8fdd045185c}"
}
]
},
"actions": [ ],
"schemes": [ ]
})-" };
implementation::SettingsLoader oldLoader{ oldSettingsJson, implementation::LoadStringResource(IDR_DEFAULTS) };
oldLoader.MergeInboxIntoUserSettings();
oldLoader.FinalizeLayering();
VERIFY_IS_TRUE(oldLoader.FixupUserSettings(), L"Validate that this will indicate we need to write them back to disk");
const auto oldSettings = winrt::make_self<implementation::CascadiaSettings>(std::move(oldLoader));
const auto oldResult{ oldSettings->ToJson() };
implementation::SettingsLoader newLoader{ newSettingsJson, implementation::LoadStringResource(IDR_DEFAULTS) };
newLoader.MergeInboxIntoUserSettings();
newLoader.FinalizeLayering();
newLoader.FixupUserSettings();
const auto newSettings = winrt::make_self<implementation::CascadiaSettings>(std::move(newLoader));
const auto newResult{ newSettings->ToJson() };
VERIFY_ARE_EQUAL(toString(newResult), toString(oldResult));
}
void SerializationTests::RoundtripGenerateActionID()
{
static constexpr std::string_view oldSettingsJson{ R"(
{
"actions": [
{
"name": "foo",
"command": { "action": "sendInput", "input": "just some input" },
"keys": "ctrl+shift+w"
}
]
})" };
implementation::SettingsLoader loader{ oldSettingsJson, implementation::LoadStringResource(IDR_DEFAULTS) };
loader.MergeInboxIntoUserSettings();
loader.FinalizeLayering();
loader.FixupUserSettings();
const auto settings = winrt::make_self<implementation::CascadiaSettings>(std::move(loader));
const auto oldResult{ settings->ToJson() };
const auto sendInputCmd = settings->ActionMap().GetActionByKeyChord(KeyChord{ true, false, true, false, 87, 0 });
std::string_view expectedID{ R"(User.sendInput.)" SEND_INPUT_ARCH_SPECIFIC_ACTION_HASH };
VERIFY_ARE_EQUAL(sendInputCmd.ID(), winrt::to_hstring(expectedID));
}
void SerializationTests::NoGeneratedIDsForIterableAndNestedCommands()
{
// for iterable commands, nested commands, and user-defined actions that already have
// an ID, we do not need to generate an ID
static constexpr std::string_view oldSettingsJson{ R"(
{
"actions": [
{
"name": "foo",
"command": "closePane",
"keys": "ctrl+shift+w",
"id": "thisIsMyClosePane"
},
{
"iterateOn": "profiles",
"icon": "${profile.icon}",
"name": "${profile.name}",
"command": { "action": "newTab", "profile": "${profile.name}" }
},
{
"name": "Change font size...",
"commands": [
{ "command": { "action": "adjustFontSize", "delta": 1 } },
{ "command": { "action": "adjustFontSize", "delta": -1 } },
{ "command": "resetFontSize" },
]
}
]
})" };
implementation::SettingsLoader oldLoader{ oldSettingsJson, implementation::LoadStringResource(IDR_DEFAULTS) };
oldLoader.MergeInboxIntoUserSettings();
oldLoader.FinalizeLayering();
VERIFY_IS_FALSE(oldLoader.FixupUserSettings(), L"Validate that there is no need to write back to disk");
}
void SerializationTests::GeneratedActionIDsEqualForIdenticalCommands()
{
static constexpr std::string_view settingsJson1{ R"(
{
"actions": [
{
"name": "foo",
"command": { "action": "sendInput", "input": "this is some other input string" },
"keys": "ctrl+shift+w"
}
]
})" };
// Both settings files define the same action, so the generated ID should be the same for both
static constexpr std::string_view settingsJson2{ R"(
{
"actions": [
{
"name": "foo",
"command": { "action": "sendInput", "input": "this is some other input string" },
"keys": "ctrl+shift+w"
}
]
})" };
implementation::SettingsLoader loader1{ settingsJson1, implementation::LoadStringResource(IDR_DEFAULTS) };
loader1.MergeInboxIntoUserSettings();
loader1.FinalizeLayering();
loader1.FixupUserSettings();
const auto settings1 = winrt::make_self<implementation::CascadiaSettings>(std::move(loader1));
const auto result1{ settings1->ToJson() };
implementation::SettingsLoader loader2{ settingsJson2, implementation::LoadStringResource(IDR_DEFAULTS) };
loader2.MergeInboxIntoUserSettings();
loader2.FinalizeLayering();
loader2.FixupUserSettings();
const auto settings2 = winrt::make_self<implementation::CascadiaSettings>(std::move(loader2));
const auto result2{ settings2->ToJson() };
const auto sendInputCmd1 = settings1->ActionMap().GetActionByKeyChord(KeyChord{ true, false, true, false, 87, 0 });
const auto sendInputCmd2 = settings2->ActionMap().GetActionByKeyChord(KeyChord{ true, false, true, false, 87, 0 });
VERIFY_ARE_EQUAL(sendInputCmd1.ID(), sendInputCmd1.ID());
}
}

View File

@@ -14,9 +14,9 @@
<PropertyGroup>
<ProjectGuid>{CA5CAD1A-9B68-456A-B13E-C8218070DC42}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>SettingsModelUnitTests</RootNamespace>
<ProjectName>UnitTests_SettingsModel</ProjectName>
<TargetName>SettingsModel.Unit.Tests</TargetName>
<RootNamespace>SettingsModelLocalTests</RootNamespace>
<ProjectName>LocalTests_SettingsModel</ProjectName>
<TargetName>SettingsModel.LocalTests</TargetName>
<ConfigurationType>DynamicLibrary</ConfigurationType>
<OpenConsoleCppWinRTProject>true</OpenConsoleCppWinRTProject>
<!-- TerminalCppWinrt is not set intentionally -->
@@ -64,6 +64,7 @@
_ConsoleGenerateAdditionalWinmdManifests step won't gather the winmd's -->
<ProjectReference Include="$(OpenConsoleDir)src\cascadia\TerminalControl\dll\TerminalControl.vcxproj" />
<ProjectReference Include="$(OpenConsoleDir)src\cascadia\TerminalConnection\TerminalConnection.vcxproj" />
<ProjectReference Include="$(OpenConsoleDir)\src\cascadia\TerminalSettingsModel\dll\Microsoft.Terminal.Settings.Model.vcxproj" />
</ItemGroup>
<!-- ========================= Globals ======================== -->
@@ -77,7 +78,7 @@
<DisableSpecificWarnings>4702;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>
<Link>
<AdditionalDependencies>onecoreuap.lib;%(AdditionalDependencies);$(IntDir)\..\Microsoft.Terminal.Settings.Model.lib\Microsoft.Terminal.Settings.Model.res</AdditionalDependencies>
<AdditionalDependencies>onecoreuap.lib;%(AdditionalDependencies)</AdditionalDependencies>
<!--
SettingsModelLib contains a DllMain that we need to force the use of.
If you don't have this, then you'll see an error like
@@ -97,16 +98,4 @@
<Import Project="$(OpenConsoleDir)src\common.build.post.props" />
<Import Project="$(OpenConsoleDir)src\common.build.tests.props" />
<Import Project="$(OpenConsoleDir)src\common.nugetversions.targets" />
<ItemGroup>
<ProjectPriFiles Include="$(TargetDir)\Microsoft.Terminal.Settings.Model.pri" />
<OutputPriFiles Include="$(TargetDir)\resources.pri" />
</ItemGroup>
<Target Name="AfterBuild" Inputs="@(ProjectPriFiles)" Outputs="@(OutputPriFiles)">
<Copy SourceFiles="@(ProjectPriFiles)"
DestinationFiles="@(OutputPriFiles)"
UseHardLinksIfPossible="true"
SkipUnchangedFiles="true" />
</Target>
</Project>

View File

@@ -16,11 +16,24 @@ using namespace WEX::Common;
using namespace winrt::Microsoft::Terminal::Settings::Model;
using namespace winrt::Microsoft::Terminal::Control;
namespace SettingsModelUnitTests
namespace SettingsModelLocalTests
{
// TODO:microsoft/terminal#3838:
// Unfortunately, these tests _WILL NOT_ work in our CI. We're waiting for
// an updated TAEF that will let us install framework packages when the test
// package is deployed. Until then, these tests won't deploy in CI.
class TerminalSettingsTests
{
TEST_CLASS(TerminalSettingsTests);
// Use a custom AppxManifest to ensure that we can activate winrt types
// from our test. This property will tell taef to manually use this as
// the AppxManifest for this test class.
// This does not yet work for anything XAML-y. See TabTests.cpp for more
// details on that.
BEGIN_TEST_CLASS(TerminalSettingsTests)
TEST_CLASS_PROPERTY(L"RunAs", L"UAP")
TEST_CLASS_PROPERTY(L"UAP:AppXManifest", L"TestHostAppXManifest.xml")
END_TEST_CLASS()
TEST_METHOD(TryCreateWinRTType);
TEST_METHOD(TestTerminalArgsForBinding);
@@ -140,7 +153,7 @@ namespace SettingsModelUnitTests
g.Data4[7]);
}
const auto tmpdir = std::filesystem::canonical(std::filesystem::temp_directory_path());
const auto tmpdir = std::filesystem::temp_directory_path();
const auto dir1 = tmpdir / guid;
const auto dir2 = tmpdir / (guid + L" two");
const auto file1 = dir1 / L"file 1.exe";
@@ -160,13 +173,13 @@ namespace SettingsModelUnitTests
{
const auto commandLine = file2.native() + LR"( -foo "bar1 bar2" -baz)"s;
const auto expected = file2.native() + L"\0-foo\0bar1 bar2\0-baz"s;
const auto actual = implementation::Profile::NormalizeCommandLine(commandLine.c_str());
const auto actual = implementation::CascadiaSettings::NormalizeCommandLine(commandLine.c_str());
VERIFY_ARE_EQUAL(expected, actual);
}
{
const auto commandLine = L"C:\\";
const auto expected = L"C:\\";
const auto actual = implementation::Profile::NormalizeCommandLine(commandLine);
const auto actual = implementation::CascadiaSettings::NormalizeCommandLine(commandLine);
VERIFY_ARE_EQUAL(expected, actual);
}
}
@@ -320,16 +333,14 @@ namespace SettingsModelUnitTests
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_ARE_EQUAL(SplitDirection::Right, realArgs.SplitDirection());
VERIFY_IS_NOT_NULL(realArgs.ContentArgs());
const 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_TRUE(terminalArgs.Profile().empty());
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_TRUE(realArgs.TerminalArgs().Profile().empty());
const auto profile{ settings->GetProfileForArgs(terminalArgs) };
const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(*settings, terminalArgs, nullptr) };
const auto profile{ settings->GetProfileForArgs(realArgs.TerminalArgs()) };
const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(*settings, realArgs.TerminalArgs(), nullptr) };
const auto termSettings = settingsStruct.DefaultSettings();
VERIFY_ARE_EQUAL(guid0, profile.Guid());
VERIFY_ARE_EQUAL(L"cmd.exe", termSettings.Commandline());
@@ -343,17 +354,15 @@ namespace SettingsModelUnitTests
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_ARE_EQUAL(SplitDirection::Right, realArgs.SplitDirection());
VERIFY_IS_NOT_NULL(realArgs.ContentArgs());
const 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"{6239a42c-1111-49a3-80bd-e8fdd045185c}", terminalArgs.Profile());
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"{6239a42c-1111-49a3-80bd-e8fdd045185c}", realArgs.TerminalArgs().Profile());
const auto profile{ settings->GetProfileForArgs(terminalArgs) };
const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(*settings, terminalArgs, nullptr) };
const auto profile{ settings->GetProfileForArgs(realArgs.TerminalArgs()) };
const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(*settings, realArgs.TerminalArgs(), nullptr) };
const auto termSettings = settingsStruct.DefaultSettings();
VERIFY_ARE_EQUAL(guid1, profile.Guid());
VERIFY_ARE_EQUAL(L"pwsh.exe", termSettings.Commandline());
@@ -367,17 +376,15 @@ namespace SettingsModelUnitTests
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_ARE_EQUAL(SplitDirection::Right, realArgs.SplitDirection());
VERIFY_IS_NOT_NULL(realArgs.ContentArgs());
const 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(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());
const auto profile{ settings->GetProfileForArgs(terminalArgs) };
const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(*settings, terminalArgs, nullptr) };
const auto profile{ settings->GetProfileForArgs(realArgs.TerminalArgs()) };
const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(*settings, realArgs.TerminalArgs(), nullptr) };
const auto termSettings = settingsStruct.DefaultSettings();
VERIFY_ARE_EQUAL(guid1, profile.Guid());
VERIFY_ARE_EQUAL(L"pwsh.exe", termSettings.Commandline());
@@ -391,17 +398,15 @@ namespace SettingsModelUnitTests
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_ARE_EQUAL(SplitDirection::Right, realArgs.SplitDirection());
VERIFY_IS_NOT_NULL(realArgs.ContentArgs());
const 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(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());
const auto profile{ settings->GetProfileForArgs(terminalArgs) };
const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(*settings, terminalArgs, nullptr) };
const auto profile{ settings->GetProfileForArgs(realArgs.TerminalArgs()) };
const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(*settings, realArgs.TerminalArgs(), nullptr) };
const auto termSettings = settingsStruct.DefaultSettings();
VERIFY_ARE_EQUAL(profile2Guid, profile.Guid());
VERIFY_ARE_EQUAL(L"wsl.exe", termSettings.Commandline());
@@ -415,17 +420,15 @@ namespace SettingsModelUnitTests
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_ARE_EQUAL(SplitDirection::Down, realArgs.SplitDirection());
VERIFY_IS_NOT_NULL(realArgs.ContentArgs());
const 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"foo.exe", terminalArgs.Commandline());
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"foo.exe", realArgs.TerminalArgs().Commandline());
const auto profile{ settings->GetProfileForArgs(terminalArgs) };
const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(*settings, terminalArgs, nullptr) };
const auto profile{ settings->GetProfileForArgs(realArgs.TerminalArgs()) };
const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(*settings, realArgs.TerminalArgs(), nullptr) };
const auto termSettings = settingsStruct.DefaultSettings();
// This action specified a command but no profile; it gets reassigned to the base profile
VERIFY_ARE_EQUAL(settings->ProfileDefaults(), profile);
@@ -440,18 +443,16 @@ namespace SettingsModelUnitTests
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_ARE_EQUAL(SplitDirection::Down, realArgs.SplitDirection());
VERIFY_IS_NOT_NULL(realArgs.ContentArgs());
const 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_FALSE(terminalArgs.Profile().empty());
VERIFY_ARE_EQUAL(L"profile1", terminalArgs.Profile());
VERIFY_ARE_EQUAL(L"foo.exe", terminalArgs.Commandline());
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_FALSE(realArgs.TerminalArgs().Profile().empty());
VERIFY_ARE_EQUAL(L"profile1", realArgs.TerminalArgs().Profile());
VERIFY_ARE_EQUAL(L"foo.exe", realArgs.TerminalArgs().Commandline());
const auto profile{ settings->GetProfileForArgs(terminalArgs) };
const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(*settings, terminalArgs, nullptr) };
const auto profile{ settings->GetProfileForArgs(realArgs.TerminalArgs()) };
const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(*settings, realArgs.TerminalArgs(), nullptr) };
const auto termSettings = settingsStruct.DefaultSettings();
VERIFY_ARE_EQUAL(guid1, profile.Guid());
VERIFY_ARE_EQUAL(L"foo.exe", termSettings.Commandline());
@@ -464,16 +465,14 @@ namespace SettingsModelUnitTests
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.ContentArgs());
const 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_TRUE(terminalArgs.Profile().empty());
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_TRUE(realArgs.TerminalArgs().Profile().empty());
const auto profile{ settings->GetProfileForArgs(terminalArgs) };
const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(*settings, terminalArgs, nullptr) };
const auto profile{ settings->GetProfileForArgs(realArgs.TerminalArgs()) };
const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(*settings, realArgs.TerminalArgs(), nullptr) };
const auto termSettings = settingsStruct.DefaultSettings();
VERIFY_ARE_EQUAL(guid0, profile.Guid());
VERIFY_ARE_EQUAL(L"cmd.exe", termSettings.Commandline());
@@ -486,17 +485,15 @@ namespace SettingsModelUnitTests
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.ContentArgs());
const auto terminalArgs{ realArgs.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_TRUE(terminalArgs.Profile().empty());
VERIFY_ARE_EQUAL(L"c:\\foo", terminalArgs.StartingDirectory());
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
VERIFY_IS_TRUE(realArgs.TerminalArgs().Commandline().empty());
VERIFY_IS_FALSE(realArgs.TerminalArgs().StartingDirectory().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().TabTitle().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().Profile().empty());
VERIFY_ARE_EQUAL(L"c:\\foo", realArgs.TerminalArgs().StartingDirectory());
const auto profile{ settings->GetProfileForArgs(terminalArgs) };
const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(*settings, terminalArgs, nullptr) };
const auto profile{ settings->GetProfileForArgs(realArgs.TerminalArgs()) };
const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(*settings, realArgs.TerminalArgs(), nullptr) };
const auto termSettings = settingsStruct.DefaultSettings();
VERIFY_ARE_EQUAL(guid0, profile.Guid());
VERIFY_ARE_EQUAL(L"cmd.exe", termSettings.Commandline());
@@ -510,18 +507,16 @@ namespace SettingsModelUnitTests
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.ContentArgs());
const auto terminalArgs{ realArgs.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_FALSE(terminalArgs.Profile().empty());
VERIFY_ARE_EQUAL(L"c:\\foo", terminalArgs.StartingDirectory());
VERIFY_ARE_EQUAL(L"profile2", terminalArgs.Profile());
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
VERIFY_IS_TRUE(realArgs.TerminalArgs().Commandline().empty());
VERIFY_IS_FALSE(realArgs.TerminalArgs().StartingDirectory().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().TabTitle().empty());
VERIFY_IS_FALSE(realArgs.TerminalArgs().Profile().empty());
VERIFY_ARE_EQUAL(L"c:\\foo", realArgs.TerminalArgs().StartingDirectory());
VERIFY_ARE_EQUAL(L"profile2", realArgs.TerminalArgs().Profile());
const auto profile{ settings->GetProfileForArgs(terminalArgs) };
const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(*settings, terminalArgs, nullptr) };
const auto profile{ settings->GetProfileForArgs(realArgs.TerminalArgs()) };
const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(*settings, realArgs.TerminalArgs(), nullptr) };
const auto termSettings = settingsStruct.DefaultSettings();
VERIFY_ARE_EQUAL(profile2Guid, profile.Guid());
VERIFY_ARE_EQUAL(L"wsl.exe", termSettings.Commandline());
@@ -535,17 +530,15 @@ namespace SettingsModelUnitTests
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.ContentArgs());
const 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_FALSE(terminalArgs.TabTitle().empty());
VERIFY_IS_TRUE(terminalArgs.Profile().empty());
VERIFY_ARE_EQUAL(L"bar", terminalArgs.TabTitle());
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
VERIFY_IS_TRUE(realArgs.TerminalArgs().Commandline().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().StartingDirectory().empty());
VERIFY_IS_FALSE(realArgs.TerminalArgs().TabTitle().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().Profile().empty());
VERIFY_ARE_EQUAL(L"bar", realArgs.TerminalArgs().TabTitle());
const auto profile{ settings->GetProfileForArgs(terminalArgs) };
const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(*settings, terminalArgs, nullptr) };
const auto profile{ settings->GetProfileForArgs(realArgs.TerminalArgs()) };
const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(*settings, realArgs.TerminalArgs(), nullptr) };
const auto termSettings = settingsStruct.DefaultSettings();
VERIFY_ARE_EQUAL(guid0, profile.Guid());
VERIFY_ARE_EQUAL(L"cmd.exe", termSettings.Commandline());
@@ -559,18 +552,16 @@ namespace SettingsModelUnitTests
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.ContentArgs());
const 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_FALSE(terminalArgs.TabTitle().empty());
VERIFY_IS_FALSE(terminalArgs.Profile().empty());
VERIFY_ARE_EQUAL(L"bar", terminalArgs.TabTitle());
VERIFY_ARE_EQUAL(L"profile2", terminalArgs.Profile());
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
VERIFY_IS_TRUE(realArgs.TerminalArgs().Commandline().empty());
VERIFY_IS_TRUE(realArgs.TerminalArgs().StartingDirectory().empty());
VERIFY_IS_FALSE(realArgs.TerminalArgs().TabTitle().empty());
VERIFY_IS_FALSE(realArgs.TerminalArgs().Profile().empty());
VERIFY_ARE_EQUAL(L"bar", realArgs.TerminalArgs().TabTitle());
VERIFY_ARE_EQUAL(L"profile2", realArgs.TerminalArgs().Profile());
const auto profile{ settings->GetProfileForArgs(terminalArgs) };
const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(*settings, terminalArgs, nullptr) };
const auto profile{ settings->GetProfileForArgs(realArgs.TerminalArgs()) };
const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(*settings, realArgs.TerminalArgs(), nullptr) };
const auto termSettings = settingsStruct.DefaultSettings();
VERIFY_ARE_EQUAL(profile2Guid, profile.Guid());
VERIFY_ARE_EQUAL(L"wsl.exe", termSettings.Commandline());
@@ -584,20 +575,18 @@ namespace SettingsModelUnitTests
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.ContentArgs());
const auto terminalArgs{ realArgs.ContentArgs().try_as<NewTerminalArgs>() };
VERIFY_IS_NOT_NULL(terminalArgs);
VERIFY_IS_FALSE(terminalArgs.Commandline().empty());
VERIFY_IS_FALSE(terminalArgs.StartingDirectory().empty());
VERIFY_IS_FALSE(terminalArgs.TabTitle().empty());
VERIFY_IS_FALSE(terminalArgs.Profile().empty());
VERIFY_ARE_EQUAL(L"foo.exe", terminalArgs.Commandline());
VERIFY_ARE_EQUAL(L"c:\\foo", terminalArgs.StartingDirectory());
VERIFY_ARE_EQUAL(L"bar", terminalArgs.TabTitle());
VERIFY_ARE_EQUAL(L"profile1", terminalArgs.Profile());
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
VERIFY_IS_FALSE(realArgs.TerminalArgs().Commandline().empty());
VERIFY_IS_FALSE(realArgs.TerminalArgs().StartingDirectory().empty());
VERIFY_IS_FALSE(realArgs.TerminalArgs().TabTitle().empty());
VERIFY_IS_FALSE(realArgs.TerminalArgs().Profile().empty());
VERIFY_ARE_EQUAL(L"foo.exe", realArgs.TerminalArgs().Commandline());
VERIFY_ARE_EQUAL(L"c:\\foo", realArgs.TerminalArgs().StartingDirectory());
VERIFY_ARE_EQUAL(L"bar", realArgs.TerminalArgs().TabTitle());
VERIFY_ARE_EQUAL(L"profile1", realArgs.TerminalArgs().Profile());
const auto profile{ settings->GetProfileForArgs(terminalArgs) };
const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(*settings, terminalArgs, nullptr) };
const auto profile{ settings->GetProfileForArgs(realArgs.TerminalArgs()) };
const auto settingsStruct{ TerminalSettings::CreateWithNewTerminalArgs(*settings, realArgs.TerminalArgs(), nullptr) };
const auto termSettings = settingsStruct.DefaultSettings();
VERIFY_ARE_EQUAL(guid1, profile.Guid());
VERIFY_ARE_EQUAL(L"foo.exe", termSettings.Commandline());

View File

@@ -5,10 +5,11 @@
#include "../TerminalSettingsModel/Theme.h"
#include "../TerminalSettingsModel/CascadiaSettings.h"
#include "../TerminalSettingsModel/resource.h"
#include "../types/inc/colorTable.hpp"
#include "JsonTestClass.h"
#include <defaults.h>
using namespace Microsoft::Console;
using namespace winrt::Microsoft::Terminal;
using namespace winrt::Microsoft::Terminal::Settings::Model::implementation;
@@ -16,11 +17,24 @@ using namespace WEX::Logging;
using namespace WEX::TestExecution;
using namespace WEX::Common;
namespace SettingsModelUnitTests
namespace SettingsModelLocalTests
{
// TODO:microsoft/terminal#3838:
// Unfortunately, these tests _WILL NOT_ work in our CI. We're waiting for
// an updated TAEF that will let us install framework packages when the test
// package is deployed. Until then, these tests won't deploy in CI.
class ThemeTests : public JsonTestClass
{
TEST_CLASS(ThemeTests);
// Use a custom AppxManifest to ensure that we can activate winrt types
// from our test. This property will tell taef to manually use this as
// the AppxManifest for this test class.
// This does not yet work for anything XAML-y. See TabTests.cpp for more
// details on that.
BEGIN_TEST_CLASS(ThemeTests)
TEST_CLASS_PROPERTY(L"RunAs", L"UAP")
TEST_CLASS_PROPERTY(L"UAP:AppXManifest", L"TestHostAppXManifest.xml")
END_TEST_CLASS()
TEST_METHOD(ParseSimpleTheme);
TEST_METHOD(ParseEmptyTheme);
@@ -179,7 +193,7 @@ namespace SettingsModelUnitTests
try
{
const auto settings{ winrt::make_self<CascadiaSettings>(settingsString, LoadStringResource(IDR_DEFAULTS)) };
const auto settings{ winrt::make_self<CascadiaSettings>(settingsString, DefaultJson) };
const auto& themes{ settings->GlobalSettings().Themes() };
{
@@ -235,7 +249,7 @@ namespace SettingsModelUnitTests
try
{
const auto settings{ winrt::make_self<CascadiaSettings>(settingsString, LoadStringResource(IDR_DEFAULTS)) };
const auto settings{ winrt::make_self<CascadiaSettings>(settingsString, DefaultJson) };
VERIFY_ARE_EQUAL(1u, settings->Warnings().Size());
VERIFY_ARE_EQUAL(Settings::Model::SettingsLoadWarnings::UnknownTheme, settings->Warnings().GetAt(0));

View File

@@ -42,6 +42,7 @@ Author(s):
#include <winrt/Windows.system.h>
#include <winrt/Windows.Foundation.h>
#include <winrt/Windows.Foundation.Collections.h>
#include <Windows.Graphics.Imaging.Interop.h>
#include <winrt/windows.ui.core.h>
#include <winrt/Windows.ui.input.h>
#include <winrt/Windows.UI.ViewManagement.h>

View File

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

View File

@@ -4,7 +4,7 @@
#include "pch.h"
#include "../TerminalApp/TerminalPage.h"
#include "../UnitTests_SettingsModel/TestUtils.h"
#include "../LocalTests_SettingsModel/TestUtils.h"
using namespace Microsoft::Console;
using namespace WEX::Logging;
@@ -176,13 +176,12 @@ namespace TerminalAppLocalTests
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_ARE_EQUAL(SplitDirection::Automatic, realArgs.SplitDirection());
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());
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());
}
const auto& expandedCommands{ settings.GlobalSettings().ActionMap().ExpandedCommands() };
@@ -202,13 +201,12 @@ namespace TerminalAppLocalTests
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_ARE_EQUAL(SplitDirection::Automatic, realArgs.SplitDirection());
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(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());
}
{
@@ -222,13 +220,12 @@ namespace TerminalAppLocalTests
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_ARE_EQUAL(SplitDirection::Automatic, realArgs.SplitDirection());
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(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());
}
{
@@ -242,13 +239,12 @@ namespace TerminalAppLocalTests
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_ARE_EQUAL(SplitDirection::Automatic, realArgs.SplitDirection());
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(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());
}
}
@@ -306,13 +302,12 @@ namespace TerminalAppLocalTests
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_ARE_EQUAL(SplitDirection::Automatic, realArgs.SplitDirection());
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());
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());
}
const auto& expandedCommands{ settings.GlobalSettings().ActionMap().ExpandedCommands() };
@@ -333,13 +328,12 @@ namespace TerminalAppLocalTests
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_ARE_EQUAL(SplitDirection::Automatic, realArgs.SplitDirection());
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(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());
}
{
@@ -354,13 +348,12 @@ namespace TerminalAppLocalTests
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_ARE_EQUAL(SplitDirection::Automatic, realArgs.SplitDirection());
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(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());
}
{
@@ -375,13 +368,12 @@ namespace TerminalAppLocalTests
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_ARE_EQUAL(SplitDirection::Automatic, realArgs.SplitDirection());
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(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());
}
}
@@ -441,13 +433,12 @@ namespace TerminalAppLocalTests
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_ARE_EQUAL(SplitDirection::Automatic, realArgs.SplitDirection());
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());
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());
}
const auto& expandedCommands{ settings.GlobalSettings().ActionMap().ExpandedCommands() };
@@ -468,13 +459,12 @@ namespace TerminalAppLocalTests
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_ARE_EQUAL(SplitDirection::Automatic, realArgs.SplitDirection());
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(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());
}
{
@@ -489,13 +479,12 @@ namespace TerminalAppLocalTests
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_ARE_EQUAL(SplitDirection::Automatic, realArgs.SplitDirection());
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(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());
}
{
@@ -510,13 +499,12 @@ namespace TerminalAppLocalTests
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_ARE_EQUAL(SplitDirection::Automatic, realArgs.SplitDirection());
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(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());
}
}
@@ -704,13 +692,12 @@ namespace TerminalAppLocalTests
const auto& realArgs = childActionAndArgs.Args().try_as<NewTabArgs>();
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
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_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());
VERIFY_IS_FALSE(child.HasNestedCommands());
}
@@ -725,13 +712,12 @@ namespace TerminalAppLocalTests
const auto& realArgs = childActionAndArgs.Args().try_as<NewTabArgs>();
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
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_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());
VERIFY_IS_FALSE(child.HasNestedCommands());
}
@@ -832,13 +818,12 @@ namespace TerminalAppLocalTests
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_ARE_EQUAL(SplitDirection::Automatic, realArgs.SplitDirection());
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_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());
VERIFY_IS_FALSE(childCommand.HasNestedCommands());
}
@@ -854,13 +839,12 @@ namespace TerminalAppLocalTests
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_ARE_EQUAL(SplitDirection::Down, realArgs.SplitDirection());
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_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());
VERIFY_IS_FALSE(childCommand.HasNestedCommands());
}
@@ -876,13 +860,12 @@ namespace TerminalAppLocalTests
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_ARE_EQUAL(SplitDirection::Right, realArgs.SplitDirection());
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_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());
VERIFY_IS_FALSE(childCommand.HasNestedCommands());
}
@@ -968,13 +951,12 @@ namespace TerminalAppLocalTests
const auto& realArgs = actionAndArgs.Args().try_as<NewTabArgs>();
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected 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(name, terminalArgs.Profile());
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());
VERIFY_IS_FALSE(command.HasNestedCommands());
}
@@ -1087,13 +1069,12 @@ namespace TerminalAppLocalTests
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_ARE_EQUAL(SplitDirection::Automatic, realArgs.SplitDirection());
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_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());
VERIFY_IS_FALSE(childCommand.HasNestedCommands());
}
@@ -1109,13 +1090,12 @@ namespace TerminalAppLocalTests
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_ARE_EQUAL(SplitDirection::Down, realArgs.SplitDirection());
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_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());
VERIFY_IS_FALSE(childCommand.HasNestedCommands());
}
@@ -1131,13 +1111,12 @@ namespace TerminalAppLocalTests
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_ARE_EQUAL(SplitDirection::Right, realArgs.SplitDirection());
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_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());
VERIFY_IS_FALSE(childCommand.HasNestedCommands());
}
@@ -1266,13 +1245,12 @@ namespace TerminalAppLocalTests
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_ARE_EQUAL(SplitDirection::Automatic, realArgs.SplitDirection());
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());
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());
}
const auto& expandedCommands{ settings.GlobalSettings().ActionMap().ExpandedCommands() };
@@ -1296,13 +1274,12 @@ namespace TerminalAppLocalTests
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_ARE_EQUAL(SplitDirection::Automatic, realArgs.SplitDirection());
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());
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());
}
{
@@ -1317,13 +1294,12 @@ namespace TerminalAppLocalTests
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_ARE_EQUAL(SplitDirection::Automatic, realArgs.SplitDirection());
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());
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());
}
{
@@ -1338,13 +1314,12 @@ namespace TerminalAppLocalTests
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected value
VERIFY_ARE_EQUAL(SplitDirection::Automatic, realArgs.SplitDirection());
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());
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());
}
}
@@ -1410,16 +1385,15 @@ namespace TerminalAppLocalTests
const auto& realArgs = actionAndArgs.Args().try_as<NewTabArgs>();
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected 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_NULL(terminalArgs.Elevate());
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());
const auto termSettingsResult = TerminalSettings::CreateWithNewTerminalArgs(settings, terminalArgs, nullptr);
const auto termSettingsResult = TerminalSettings::CreateWithNewTerminalArgs(settings, realArgs.TerminalArgs(), nullptr);
const auto termSettings = termSettingsResult.DefaultSettings();
VERIFY_ARE_EQUAL(L"cmd.exe", termSettings.Commandline());
VERIFY_ARE_EQUAL(false, termSettings.Elevate());
@@ -1433,16 +1407,15 @@ namespace TerminalAppLocalTests
const auto& realArgs = actionAndArgs.Args().try_as<NewTabArgs>();
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected 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_NULL(terminalArgs.Elevate());
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());
const auto termSettingsResult = TerminalSettings::CreateWithNewTerminalArgs(settings, terminalArgs, nullptr);
const auto termSettingsResult = TerminalSettings::CreateWithNewTerminalArgs(settings, realArgs.TerminalArgs(), nullptr);
const auto termSettings = termSettingsResult.DefaultSettings();
VERIFY_ARE_EQUAL(L"pwsh.exe", termSettings.Commandline());
VERIFY_ARE_EQUAL(true, termSettings.Elevate());
@@ -1456,16 +1429,15 @@ namespace TerminalAppLocalTests
const auto& realArgs = actionAndArgs.Args().try_as<NewTabArgs>();
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected 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_NULL(terminalArgs.Elevate());
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());
const auto termSettingsResult = TerminalSettings::CreateWithNewTerminalArgs(settings, terminalArgs, nullptr);
const auto termSettingsResult = TerminalSettings::CreateWithNewTerminalArgs(settings, realArgs.TerminalArgs(), nullptr);
const auto termSettings = termSettingsResult.DefaultSettings();
VERIFY_ARE_EQUAL(L"wsl.exe", termSettings.Commandline());
VERIFY_ARE_EQUAL(false, termSettings.Elevate());
@@ -1480,17 +1452,16 @@ namespace TerminalAppLocalTests
const auto& realArgs = actionAndArgs.Args().try_as<NewTabArgs>();
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected 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());
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());
const auto termSettingsResult = TerminalSettings::CreateWithNewTerminalArgs(settings, terminalArgs, nullptr);
const auto termSettingsResult = TerminalSettings::CreateWithNewTerminalArgs(settings, realArgs.TerminalArgs(), nullptr);
const auto termSettings = termSettingsResult.DefaultSettings();
VERIFY_ARE_EQUAL(L"cmd.exe", termSettings.Commandline());
VERIFY_ARE_EQUAL(false, termSettings.Elevate());
@@ -1504,17 +1475,16 @@ namespace TerminalAppLocalTests
const auto& realArgs = actionAndArgs.Args().try_as<NewTabArgs>();
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected 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());
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());
const auto termSettingsResult = TerminalSettings::CreateWithNewTerminalArgs(settings, terminalArgs, nullptr);
const auto termSettingsResult = TerminalSettings::CreateWithNewTerminalArgs(settings, realArgs.TerminalArgs(), nullptr);
const auto termSettings = termSettingsResult.DefaultSettings();
VERIFY_ARE_EQUAL(L"pwsh.exe", termSettings.Commandline());
VERIFY_ARE_EQUAL(false, termSettings.Elevate());
@@ -1528,17 +1498,16 @@ namespace TerminalAppLocalTests
const auto& realArgs = actionAndArgs.Args().try_as<NewTabArgs>();
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected 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());
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());
const auto termSettingsResult = TerminalSettings::CreateWithNewTerminalArgs(settings, terminalArgs, nullptr);
const auto termSettingsResult = TerminalSettings::CreateWithNewTerminalArgs(settings, realArgs.TerminalArgs(), nullptr);
const auto termSettings = termSettingsResult.DefaultSettings();
VERIFY_ARE_EQUAL(L"wsl.exe", termSettings.Commandline());
VERIFY_ARE_EQUAL(false, termSettings.Elevate());
@@ -1553,17 +1522,16 @@ namespace TerminalAppLocalTests
const auto& realArgs = actionAndArgs.Args().try_as<NewTabArgs>();
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected 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());
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());
const auto termSettingsResult = TerminalSettings::CreateWithNewTerminalArgs(settings, terminalArgs, nullptr);
const auto termSettingsResult = TerminalSettings::CreateWithNewTerminalArgs(settings, realArgs.TerminalArgs(), nullptr);
const auto termSettings = termSettingsResult.DefaultSettings();
VERIFY_ARE_EQUAL(L"cmd.exe", termSettings.Commandline());
VERIFY_ARE_EQUAL(true, termSettings.Elevate());
@@ -1576,17 +1544,16 @@ namespace TerminalAppLocalTests
const auto& realArgs = actionAndArgs.Args().try_as<NewTabArgs>();
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected 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());
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());
const auto termSettingsResult = TerminalSettings::CreateWithNewTerminalArgs(settings, terminalArgs, nullptr);
const auto termSettingsResult = TerminalSettings::CreateWithNewTerminalArgs(settings, realArgs.TerminalArgs(), nullptr);
const auto termSettings = termSettingsResult.DefaultSettings();
VERIFY_ARE_EQUAL(L"pwsh.exe", termSettings.Commandline());
VERIFY_ARE_EQUAL(true, termSettings.Elevate());
@@ -1600,17 +1567,16 @@ namespace TerminalAppLocalTests
const auto& realArgs = actionAndArgs.Args().try_as<NewTabArgs>();
VERIFY_IS_NOT_NULL(realArgs);
// Verify the args have the expected 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());
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());
const auto termSettingsResult = TerminalSettings::CreateWithNewTerminalArgs(settings, terminalArgs, nullptr);
const auto termSettingsResult = TerminalSettings::CreateWithNewTerminalArgs(settings, realArgs.TerminalArgs(), nullptr);
const auto termSettings = termSettingsResult.DefaultSettings();
VERIFY_ARE_EQUAL(L"wsl.exe", termSettings.Commandline());
VERIFY_ARE_EQUAL(true, termSettings.Elevate());

View File

@@ -1326,7 +1326,7 @@ namespace TerminalAppLocalTests
const auto& controlSettings = activeControl.Settings();
VERIFY_IS_NOT_NULL(controlSettings);
VERIFY_ARE_EQUAL(til::color{ 0xff0c0c0c }, til::color{ controlSettings.DefaultBackground() });
VERIFY_ARE_EQUAL(til::color{ 0xff0c0c0c }, controlSettings.DefaultBackground());
});
TestOnUIThread([&page]() {
@@ -1344,7 +1344,7 @@ namespace TerminalAppLocalTests
VERIFY_IS_NOT_NULL(controlSettings);
Log::Comment(L"Color should be changed to the preview");
VERIFY_ARE_EQUAL(til::color{ 0xff000000 }, til::color{ controlSettings.DefaultBackground() });
VERIFY_ARE_EQUAL(til::color{ 0xff000000 }, controlSettings.DefaultBackground());
// And we should have stored a function to revert the change.
VERIFY_ARE_EQUAL(1u, page->_restorePreviewFuncs.size());
@@ -1366,7 +1366,7 @@ namespace TerminalAppLocalTests
VERIFY_IS_NOT_NULL(controlSettings);
Log::Comment(L"Color should be changed");
VERIFY_ARE_EQUAL(til::color{ 0xff000000 }, til::color{ controlSettings.DefaultBackground() });
VERIFY_ARE_EQUAL(til::color{ 0xff000000 }, controlSettings.DefaultBackground());
// After preview there should be no more restore functions to execute.
VERIFY_ARE_EQUAL(0u, page->_restorePreviewFuncs.size());
@@ -1394,7 +1394,7 @@ namespace TerminalAppLocalTests
const auto& controlSettings = activeControl.Settings();
VERIFY_IS_NOT_NULL(controlSettings);
VERIFY_ARE_EQUAL(til::color{ 0xff0c0c0c }, til::color{ controlSettings.DefaultBackground() });
VERIFY_ARE_EQUAL(til::color{ 0xff0c0c0c }, controlSettings.DefaultBackground());
});
TestOnUIThread([&page]() {
@@ -1412,7 +1412,7 @@ namespace TerminalAppLocalTests
VERIFY_IS_NOT_NULL(controlSettings);
Log::Comment(L"Color should be changed to the preview");
VERIFY_ARE_EQUAL(til::color{ 0xff000000 }, til::color{ controlSettings.DefaultBackground() });
VERIFY_ARE_EQUAL(til::color{ 0xff000000 }, controlSettings.DefaultBackground());
});
TestOnUIThread([&page]() {
@@ -1428,7 +1428,7 @@ namespace TerminalAppLocalTests
VERIFY_IS_NOT_NULL(controlSettings);
Log::Comment(L"Color should be the same as it originally was");
VERIFY_ARE_EQUAL(til::color{ 0xff0c0c0c }, til::color{ controlSettings.DefaultBackground() });
VERIFY_ARE_EQUAL(til::color{ 0xff0c0c0c }, controlSettings.DefaultBackground());
});
Log::Comment(L"Sleep to let events propagate");
Sleep(250);
@@ -1450,7 +1450,7 @@ namespace TerminalAppLocalTests
const auto& controlSettings = activeControl.Settings();
VERIFY_IS_NOT_NULL(controlSettings);
VERIFY_ARE_EQUAL(til::color{ 0xff0c0c0c }, til::color{ controlSettings.DefaultBackground() });
VERIFY_ARE_EQUAL(til::color{ 0xff0c0c0c }, controlSettings.DefaultBackground());
});
TestOnUIThread([&page]() {
@@ -1467,7 +1467,7 @@ namespace TerminalAppLocalTests
VERIFY_IS_NOT_NULL(controlSettings);
Log::Comment(L"Color should be changed to the preview");
VERIFY_ARE_EQUAL(til::color{ 0xff000000 }, til::color{ controlSettings.DefaultBackground() });
VERIFY_ARE_EQUAL(til::color{ 0xff000000 }, controlSettings.DefaultBackground());
});
TestOnUIThread([&page]() {
@@ -1484,7 +1484,7 @@ namespace TerminalAppLocalTests
VERIFY_IS_NOT_NULL(controlSettings);
Log::Comment(L"Color should be changed to the preview");
VERIFY_ARE_EQUAL(til::color{ 0xffFAFAFA }, til::color{ controlSettings.DefaultBackground() });
VERIFY_ARE_EQUAL(til::color{ 0xffFAFAFA }, controlSettings.DefaultBackground());
});
TestOnUIThread([&page]() {
@@ -1503,7 +1503,7 @@ namespace TerminalAppLocalTests
VERIFY_IS_NOT_NULL(controlSettings);
Log::Comment(L"Color should be changed");
VERIFY_ARE_EQUAL(til::color{ 0xffFAFAFA }, til::color{ controlSettings.DefaultBackground() });
VERIFY_ARE_EQUAL(til::color{ 0xffFAFAFA }, controlSettings.DefaultBackground());
});
Log::Comment(L"Sleep to let events propagate");
Sleep(250);

View File

@@ -133,6 +133,7 @@
<ItemGroup>
<TestDll Include="$(OpenConsoleCommonOutDir)\LocalTests_TerminalApp\TerminalApp.LocalTests.dll" />
<TestDll Include="$(OpenConsoleCommonOutDir)\LocalTests_SettingsModel\SettingsModel.LocalTests.dll" />
</ItemGroup>
<Target Name="AfterBuild" Inputs="@(TestDll)" Outputs="@(TestDll->'$(TargetDir)'\%(Filename)%(Extension)')">

View File

@@ -56,8 +56,6 @@ Author(s):
#include <winrt/windows.applicationmodel.core.h>
#include <winrt/Microsoft.Terminal.TerminalConnection.h>
#include <winrt/Microsoft.Terminal.Core.h>
#include <winrt/Microsoft.Terminal.Control.h>
#include <winrt/Microsoft.Terminal.Settings.Model.h>
#include <winrt/Microsoft.UI.Xaml.Controls.h>

View File

@@ -94,8 +94,8 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
peasant.IdentifyWindowsRequested({ this, &Monarch::_identifyWindows });
peasant.RenameRequested({ this, &Monarch::_renameRequested });
peasant.ShowNotificationIconRequested([this](auto&&, auto&&) { ShowNotificationIconRequested.raise(*this, nullptr); });
peasant.HideNotificationIconRequested([this](auto&&, auto&&) { HideNotificationIconRequested.raise(*this, nullptr); });
peasant.ShowNotificationIconRequested([this](auto&&, auto&&) { _ShowNotificationIconRequestedHandlers(*this, nullptr); });
peasant.HideNotificationIconRequested([this](auto&&, auto&&) { _HideNotificationIconRequestedHandlers(*this, nullptr); });
peasant.QuitAllRequested({ this, &Monarch::_handleQuitAll });
{
@@ -110,7 +110,7 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
TraceLoggingKeyword(TIL_KEYWORD_TRACE));
WindowCreated.raise(nullptr, nullptr);
_WindowCreatedHandlers(nullptr, nullptr);
return newPeasantsId;
}
catch (...)
@@ -198,7 +198,7 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
std::unique_lock lock{ _peasantsMutex };
_peasants.erase(peasantId);
}
WindowClosed.raise(nullptr, nullptr);
_WindowClosedHandlers(nullptr, nullptr);
}
// Method Description:
@@ -641,7 +641,7 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
auto findWindowArgs{ winrt::make_self<Remoting::implementation::FindTargetWindowArgs>(args) };
// This is handled by some handler in-proc
FindTargetWindowRequested.raise(*this, *findWindowArgs);
_FindTargetWindowRequestedHandlers(*this, *findWindowArgs);
// After the event was handled, ResultTargetWindow() will be filled with
// the parsed result.
@@ -732,7 +732,7 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
result->WindowName(targetWindowName);
result->ShouldCreateWindow(true);
RequestNewWindow.raise(*this, *winrt::make_self<WindowRequestedArgs>(*result, args));
_RequestNewWindowHandlers(*this, *winrt::make_self<WindowRequestedArgs>(*result, args));
// If this fails, it'll be logged in the following
// TraceLoggingWrite statement, with succeeded=false
@@ -770,7 +770,7 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
result->Id(windowID);
result->WindowName(targetWindowName);
RequestNewWindow.raise(*this, *winrt::make_self<WindowRequestedArgs>(*result, args));
_RequestNewWindowHandlers(*this, *winrt::make_self<WindowRequestedArgs>(*result, args));
return *result;
}
@@ -787,7 +787,7 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
auto result = winrt::make_self<Remoting::implementation::ProposeCommandlineResult>(true);
result->WindowName(targetWindowName);
RequestNewWindow.raise(*this, *winrt::make_self<WindowRequestedArgs>(*result, args));
_RequestNewWindowHandlers(*this, *winrt::make_self<WindowRequestedArgs>(*result, args));
return *result;
}
@@ -1082,7 +1082,7 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
auto request = winrt::make_self<implementation::WindowRequestedArgs>(nameIsReserved ? L"" : window,
content,
windowBounds);
RequestNewWindow.raise(*this, *request);
_RequestNewWindowHandlers(*this, *request);
}
}

View File

@@ -100,13 +100,12 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
void RequestMoveContent(winrt::hstring window, winrt::hstring content, uint32_t tabIndex, const Windows::Foundation::IReference<Windows::Foundation::Rect>& windowBounds);
void RequestSendContent(const Remoting::RequestReceiveContentArgs& args);
til::typed_event<winrt::Windows::Foundation::IInspectable, winrt::Microsoft::Terminal::Remoting::FindTargetWindowArgs> FindTargetWindowRequested;
til::typed_event<> ShowNotificationIconRequested;
til::typed_event<> HideNotificationIconRequested;
til::typed_event<> WindowCreated;
til::typed_event<> WindowClosed;
til::typed_event<winrt::Windows::Foundation::IInspectable, winrt::Microsoft::Terminal::Remoting::WindowRequestedArgs> RequestNewWindow;
TYPED_EVENT(FindTargetWindowRequested, winrt::Windows::Foundation::IInspectable, winrt::Microsoft::Terminal::Remoting::FindTargetWindowArgs);
TYPED_EVENT(ShowNotificationIconRequested, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
TYPED_EVENT(HideNotificationIconRequested, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
TYPED_EVENT(WindowCreated, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
TYPED_EVENT(WindowClosed, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
TYPED_EVENT(RequestNewWindow, winrt::Windows::Foundation::IInspectable, winrt::Microsoft::Terminal::Remoting::WindowRequestedArgs);
private:
uint64_t _ourPID;
@@ -221,7 +220,7 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
// A peasant died, let the app host know that the number of
// windows has changed.
WindowClosed.raise(nullptr, nullptr);
_WindowClosedHandlers(nullptr, nullptr);
}
}

View File

@@ -66,7 +66,7 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
// Raise an event with these args. The AppHost will listen for this
// event to know when to take these args and dispatch them to a
// currently-running window.
ExecuteCommandlineRequested.raise(*this, args);
_ExecuteCommandlineRequestedHandlers(*this, args);
return true;
}
@@ -96,7 +96,7 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
// by the monarch. The monarch might have died. If they have, this
// will throw an exception. Just eat it, the election thread will
// handle hooking up the new one.
WindowActivated.raise(*this, args);
_WindowActivatedHandlers(*this, args);
successfullyNotified = true;
}
catch (...)
@@ -145,7 +145,7 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
TraceLoggingKeyword(TIL_KEYWORD_TRACE));
SummonRequested.raise(*this, localCopy);
_SummonRequestedHandlers(*this, localCopy);
}
// Method Description:
@@ -160,7 +160,7 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
{
// Not worried about try/catching this. The handler is in AppHost, which
// is in-proc for us.
DisplayWindowIdRequested.raise(*this, nullptr);
_DisplayWindowIdRequestedHandlers(*this, nullptr);
}
// Method Description:
@@ -181,7 +181,7 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
// by the monarch. The monarch might have died. If they have, this
// will throw an exception. Just eat it, the election thread will
// handle hooking up the new one.
IdentifyWindowsRequested.raise(*this, nullptr);
_IdentifyWindowsRequestedHandlers(*this, nullptr);
successfullyNotified = true;
}
catch (...)
@@ -206,7 +206,7 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
// by the monarch. The monarch might have died. If they have, this
// will throw an exception. Just eat it, the election thread will
// handle hooking up the new one.
RenameRequested.raise(*this, args);
_RenameRequestedHandlers(*this, args);
if (args.Succeeded())
{
_WindowName = args.NewName();
@@ -232,7 +232,7 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
{
try
{
ShowNotificationIconRequested.raise(*this, nullptr);
_ShowNotificationIconRequestedHandlers(*this, nullptr);
}
catch (...)
{
@@ -248,7 +248,7 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
{
try
{
HideNotificationIconRequested.raise(*this, nullptr);
_HideNotificationIconRequestedHandlers(*this, nullptr);
}
catch (...)
{
@@ -264,7 +264,7 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
{
try
{
QuitAllRequested.raise(*this, nullptr);
_QuitAllRequestedHandlers(*this, nullptr);
}
catch (...)
{
@@ -280,7 +280,7 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
{
try
{
AttachRequested.raise(*this, request);
_AttachRequestedHandlers(*this, request);
}
catch (...)
{
@@ -296,7 +296,7 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
{
try
{
QuitRequested.raise(*this, nullptr);
_QuitRequestedHandlers(*this, nullptr);
}
catch (...)
{
@@ -310,6 +310,6 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
void Peasant::SendContent(const Remoting::RequestReceiveContentArgs& args)
{
SendContentRequested.raise(*this, args);
_SendContentRequestedHandlers(*this, args);
}
}

View File

@@ -67,24 +67,24 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
void SendContent(const winrt::Microsoft::Terminal::Remoting::RequestReceiveContentArgs& args);
til::typed_event<winrt::Windows::Foundation::IInspectable, winrt::Microsoft::Terminal::Remoting::WindowActivatedArgs> WindowActivated;
til::typed_event<winrt::Windows::Foundation::IInspectable, winrt::Microsoft::Terminal::Remoting::CommandlineArgs> ExecuteCommandlineRequested;
til::typed_event<> IdentifyWindowsRequested;
til::typed_event<> DisplayWindowIdRequested;
til::typed_event<winrt::Windows::Foundation::IInspectable, winrt::Microsoft::Terminal::Remoting::RenameRequestArgs> RenameRequested;
til::typed_event<winrt::Windows::Foundation::IInspectable, winrt::Microsoft::Terminal::Remoting::SummonWindowBehavior> SummonRequested;
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;
til::typed_event<winrt::Windows::Foundation::IInspectable, winrt::Microsoft::Terminal::Remoting::RequestReceiveContentArgs> SendContentRequested;
WINRT_PROPERTY(winrt::hstring, WindowName);
WINRT_PROPERTY(winrt::hstring, ActiveTabTitle);
TYPED_EVENT(WindowActivated, winrt::Windows::Foundation::IInspectable, winrt::Microsoft::Terminal::Remoting::WindowActivatedArgs);
TYPED_EVENT(ExecuteCommandlineRequested, winrt::Windows::Foundation::IInspectable, winrt::Microsoft::Terminal::Remoting::CommandlineArgs);
TYPED_EVENT(IdentifyWindowsRequested, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
TYPED_EVENT(DisplayWindowIdRequested, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
TYPED_EVENT(RenameRequested, winrt::Windows::Foundation::IInspectable, winrt::Microsoft::Terminal::Remoting::RenameRequestArgs);
TYPED_EVENT(SummonRequested, winrt::Windows::Foundation::IInspectable, winrt::Microsoft::Terminal::Remoting::SummonWindowBehavior);
TYPED_EVENT(ShowNotificationIconRequested, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
TYPED_EVENT(HideNotificationIconRequested, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
TYPED_EVENT(QuitAllRequested, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
TYPED_EVENT(QuitRequested, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
TYPED_EVENT(AttachRequested, winrt::Windows::Foundation::IInspectable, winrt::Microsoft::Terminal::Remoting::AttachRequest);
TYPED_EVENT(SendContentRequested, winrt::Windows::Foundation::IInspectable, winrt::Microsoft::Terminal::Remoting::RequestReceiveContentArgs);
private:
Peasant(const uint64_t testPID);
uint64_t _ourPID;

View File

@@ -89,10 +89,9 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
// done when we become the king. This will be called both for the first
// window, and when the current monarch dies.
_monarch.WindowCreated({ get_weak(), &WindowManager::_bubbleWindowCreated });
_monarch.WindowClosed({ get_weak(), &WindowManager::_bubbleWindowClosed });
_monarch.WindowCreated({ get_weak(), &WindowManager::_WindowCreatedHandlers });
_monarch.WindowClosed({ get_weak(), &WindowManager::_WindowClosedHandlers });
_monarch.FindTargetWindowRequested({ this, &WindowManager::_raiseFindTargetWindowRequested });
_monarch.RequestNewWindow({ get_weak(), &WindowManager::_raiseRequestNewWindow });
}
@@ -108,12 +107,12 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
void WindowManager::_raiseFindTargetWindowRequested(const winrt::Windows::Foundation::IInspectable& sender,
const winrt::Microsoft::Terminal::Remoting::FindTargetWindowArgs& args)
{
FindTargetWindowRequested.raise(sender, args);
_FindTargetWindowRequestedHandlers(sender, args);
}
void WindowManager::_raiseRequestNewWindow(const winrt::Windows::Foundation::IInspectable& sender,
const winrt::Microsoft::Terminal::Remoting::WindowRequestedArgs& args)
{
RequestNewWindow.raise(sender, args);
_RequestNewWindowHandlers(sender, args);
}
Remoting::ProposeCommandlineResult WindowManager::ProposeCommandline(const Remoting::CommandlineArgs& args, const bool isolatedMode)
@@ -161,7 +160,7 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
auto findWindowArgs{ winrt::make_self<Remoting::implementation::FindTargetWindowArgs>(args) };
// This is handled by some handler in-proc
FindTargetWindowRequested.raise(*this, *findWindowArgs);
_FindTargetWindowRequestedHandlers(*this, *findWindowArgs);
// After the event was handled, ResultTargetWindow() will be filled with
// the parsed result.
@@ -364,15 +363,6 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
return *p;
}
void WindowManager::_bubbleWindowCreated(const winrt::Windows::Foundation::IInspectable& s, const winrt::Windows::Foundation::IInspectable& e)
{
WindowCreated.raise(s, e);
}
void WindowManager::_bubbleWindowClosed(const winrt::Windows::Foundation::IInspectable& s, const winrt::Windows::Foundation::IInspectable& e)
{
WindowClosed.raise(s, e);
}
void WindowManager::SignalClose(const Remoting::Peasant& peasant)
{
if (_monarch)

View File

@@ -45,11 +45,11 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
winrt::fire_and_forget RequestMoveContent(winrt::hstring window, winrt::hstring content, uint32_t tabIndex, Windows::Foundation::IReference<Windows::Foundation::Rect> windowBounds);
winrt::fire_and_forget RequestSendContent(Remoting::RequestReceiveContentArgs args);
til::typed_event<winrt::Windows::Foundation::IInspectable, winrt::Microsoft::Terminal::Remoting::FindTargetWindowArgs> FindTargetWindowRequested;
TYPED_EVENT(FindTargetWindowRequested, winrt::Windows::Foundation::IInspectable, winrt::Microsoft::Terminal::Remoting::FindTargetWindowArgs);
til::typed_event<> WindowCreated;
til::typed_event<> WindowClosed;
til::typed_event<winrt::Windows::Foundation::IInspectable, winrt::Microsoft::Terminal::Remoting::WindowRequestedArgs> RequestNewWindow;
TYPED_EVENT(WindowCreated, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
TYPED_EVENT(WindowClosed, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
TYPED_EVENT(RequestNewWindow, winrt::Windows::Foundation::IInspectable, winrt::Microsoft::Terminal::Remoting::WindowRequestedArgs);
private:
DWORD _registrationHostClass{ 0 };
@@ -65,8 +65,6 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
const winrt::Microsoft::Terminal::Remoting::FindTargetWindowArgs& args);
void _raiseRequestNewWindow(const winrt::Windows::Foundation::IInspectable& sender,
const winrt::Microsoft::Terminal::Remoting::WindowRequestedArgs& args);
void _bubbleWindowCreated(const winrt::Windows::Foundation::IInspectable& s, const winrt::Windows::Foundation::IInspectable& e);
void _bubbleWindowClosed(const winrt::Windows::Foundation::IInspectable& s, const winrt::Windows::Foundation::IInspectable& e);
};
}

View File

@@ -15,9 +15,9 @@ namespace winrt::TerminalApp::implementation
winrt::hstring ApplicationDisplayName();
winrt::hstring ApplicationVersion();
til::property_changed_event PropertyChanged;
WINRT_OBSERVABLE_PROPERTY(bool, UpdatesAvailable, PropertyChanged.raise, false);
WINRT_OBSERVABLE_PROPERTY(bool, CheckingForUpdates, PropertyChanged.raise, false);
WINRT_CALLBACK(PropertyChanged, Windows::UI::Xaml::Data::PropertyChangedEventHandler);
WINRT_OBSERVABLE_PROPERTY(bool, UpdatesAvailable, _PropertyChangedHandlers, false);
WINRT_OBSERVABLE_PROPERTY(bool, CheckingForUpdates, _PropertyChangedHandlers, false);
private:
friend struct AboutDialogT<AboutDialog>; // for Xaml to bind events

View File

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

View File

@@ -5,8 +5,6 @@
#include "App.h"
#include "TerminalPage.h"
#include "ScratchpadContent.h"
#include "TasksPaneContent.h"
#include "../WinRTUtils/inc/WtExeUtils.h"
#include "../../types/inc/utils.hpp"
#include "Utils.h"
@@ -119,7 +117,7 @@ namespace winrt::TerminalApp::implementation
void TerminalPage::_HandleCloseWindow(const IInspectable& /*sender*/,
const ActionEventArgs& args)
{
CloseRequested.raise(nullptr, nullptr);
_CloseRequestedHandlers(nullptr, nullptr);
args.Handled(true);
}
@@ -239,32 +237,6 @@ 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)
{
@@ -274,10 +246,16 @@ namespace winrt::TerminalApp::implementation
}
else if (const auto& realArgs = args.ActionArgs().try_as<SplitPaneArgs>())
{
if (_shouldBailForInvalidProfileIndex(_settings, realArgs.ContentArgs()))
if (const auto& newTerminalArgs{ realArgs.TerminalArgs() })
{
args.Handled(false);
return;
if (const auto index = realArgs.TerminalArgs().ProfileIndex())
{
if (gsl::narrow<uint32_t>(index.Value()) >= _settings.ActiveProfiles().Size())
{
args.Handled(false);
return;
}
}
}
const auto& duplicateFromTab{ realArgs.SplitMode() == SplitType::Duplicate ? _GetFocusedTab() : nullptr };
@@ -287,8 +265,8 @@ namespace winrt::TerminalApp::implementation
_SplitPane(terminalTab,
realArgs.SplitDirection(),
// This is safe, we're already filtering so the value is (0, 1)
realArgs.SplitSize(),
_MakePane(realArgs.ContentArgs(), duplicateFromTab));
::base::saturated_cast<float>(realArgs.SplitSize()),
_MakePane(realArgs.TerminalArgs(), duplicateFromTab));
args.Handled(true);
}
}
@@ -466,13 +444,19 @@ namespace winrt::TerminalApp::implementation
}
else if (const auto& realArgs = args.ActionArgs().try_as<NewTabArgs>())
{
if (_shouldBailForInvalidProfileIndex(_settings, realArgs.ContentArgs()))
if (const auto& newTerminalArgs{ realArgs.TerminalArgs() })
{
args.Handled(false);
return;
if (const auto index = newTerminalArgs.ProfileIndex())
{
if (gsl::narrow<uint32_t>(index.Value()) >= _settings.ActiveProfiles().Size())
{
args.Handled(false);
return;
}
}
}
LOG_IF_FAILED(_OpenNewTab(realArgs.ContentArgs()));
LOG_IF_FAILED(_OpenNewTab(realArgs.TerminalArgs()));
args.Handled(true);
}
}
@@ -753,8 +737,8 @@ namespace winrt::TerminalApp::implementation
{
if (const auto& realArgs = actionArgs.ActionArgs().try_as<ExecuteCommandlineArgs>())
{
auto actions = winrt::single_threaded_vector<ActionAndArgs>(
TerminalPage::ConvertExecuteCommandlineToActions(realArgs));
auto actions = winrt::single_threaded_vector<ActionAndArgs>(std::move(
TerminalPage::ConvertExecuteCommandlineToActions(realArgs)));
if (actions.Size() != 0)
{
@@ -884,23 +868,8 @@ 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 INewContentArgs newContentArgs)
fire_and_forget TerminalPage::_OpenNewWindow(const NewTerminalArgs newTerminalArgs)
{
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();
@@ -913,7 +882,8 @@ namespace winrt::TerminalApp::implementation
// `-w -1` will ensure a new window is created.
winrt::hstring cmdline{
fmt::format(L"-w -1 new-tab {}",
terminalArgs.ToCommandline().c_str())
newTerminalArgs ? newTerminalArgs.ToCommandline().c_str() :
L"")
};
// Build the args to ShellExecuteEx. We need to use ShellExecuteEx so we
@@ -938,32 +908,29 @@ namespace winrt::TerminalApp::implementation
void TerminalPage::_HandleNewWindow(const IInspectable& /*sender*/,
const ActionEventArgs& actionArgs)
{
INewContentArgs newContentArgs{ nullptr };
NewTerminalArgs newTerminalArgs{ nullptr };
// If the caller provided NewTerminalArgs, then try to use those
if (actionArgs)
{
if (const auto& realArgs = actionArgs.ActionArgs().try_as<NewWindowArgs>())
{
newContentArgs = realArgs.ContentArgs();
newTerminalArgs = realArgs.TerminalArgs();
}
}
// 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 (!newContentArgs)
if (!newTerminalArgs)
{
newContentArgs = NewTerminalArgs{};
newTerminalArgs = NewTerminalArgs();
}
if (const auto& terminalArgs{ newContentArgs.try_as<NewTerminalArgs>() })
{
const auto profile{ _settings.GetProfileForArgs(terminalArgs) };
terminalArgs.Profile(::Microsoft::Console::Utils::GuidToString(profile.Guid()));
}
const auto profile{ _settings.GetProfileForArgs(newTerminalArgs) };
// Manually fill in the evaluated profile.
_OpenNewWindow(newContentArgs);
newTerminalArgs.Profile(::Microsoft::Console::Utils::GuidToString(profile.Guid()));
_OpenNewWindow(newTerminalArgs);
actionArgs.Handled(true);
}
@@ -981,7 +948,7 @@ namespace winrt::TerminalApp::implementation
void TerminalPage::_HandleIdentifyWindows(const IInspectable& /*sender*/,
const ActionEventArgs& args)
{
IdentifyWindowsRequested.raise(*this, nullptr);
_IdentifyWindowsRequestedHandlers(*this, nullptr);
args.Handled(true);
}
@@ -1010,7 +977,7 @@ namespace winrt::TerminalApp::implementation
{
const auto newName = realArgs.Name();
const auto request = winrt::make_self<implementation::RenameWindowRequestedArgs>(newName);
RenameWindowRequested.raise(*this, *request);
_RenameWindowRequestedHandlers(*this, *request);
args.Handled(true);
}
}
@@ -1180,7 +1147,7 @@ namespace winrt::TerminalApp::implementation
void TerminalPage::_HandleOpenSystemMenu(const IInspectable& /*sender*/,
const ActionEventArgs& args)
{
OpenSystemMenu.raise(*this, nullptr);
_OpenSystemMenuHandlers(*this, nullptr);
args.Handled(true);
}
@@ -1248,7 +1215,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.0f, realArgs.Relative());
control.AdjustOpacity(realArgs.Opacity() / 100.0, realArgs.Relative());
});
args.Handled(res);
}
@@ -1434,7 +1401,7 @@ namespace winrt::TerminalApp::implementation
{
if (const auto activePane{ activeTab->GetActivePane() })
{
_restartPaneConnection(activePane->GetContent().try_as<TerminalApp::TerminalPaneContent>(), nullptr);
_restartPaneConnection(activePane);
}
}
args.Handled(true);
@@ -1449,50 +1416,10 @@ namespace winrt::TerminalApp::implementation
}
args.Handled(true);
}
void TerminalPage::_HandleOpenScratchpad(const IInspectable& sender,
const ActionEventArgs& args)
{
if (Feature_ScratchpadPane::IsEnabled())
{
const auto& scratchPane{ winrt::make_self<ScratchpadContent>() };
// This is maybe a little wacky - add our key event handler to the pane
// we made. So that we can get actions for keys that the content didn't
// handle.
scratchPane->GetRoot().KeyDown({ this, &TerminalPage::_KeyDownHandler });
const auto resultPane = std::make_shared<Pane>(*scratchPane);
_SplitPane(_senderOrFocusedTab(sender), SplitDirection::Automatic, 0.5f, resultPane);
args.Handled(true);
}
}
void TerminalPage::_HandleOpenAbout(const IInspectable& /*sender*/,
const ActionEventArgs& args)
{
_ShowAboutDialog();
args.Handled(true);
}
void TerminalPage::_HandleOpenTasksPane(const IInspectable& sender,
const ActionEventArgs& args)
{
if (Feature_ScratchpadPane::IsEnabled())
{
const auto& scratchPane{ winrt::make_self<TasksPaneContent>() };
scratchPane->UpdateSettings(_settings);
// This is maybe a little wacky - add our key event handler to the pane
// we made. So that we can get actions for keys that the content didn't
// handle.
scratchPane->GetRoot().KeyDown({ this, &TerminalPage::_KeyDownHandler });
scratchPane->DispatchCommandRequested({ this, &TerminalPage::_OnDispatchCommandRequested });
const auto resultPane = std::make_shared<Pane>(*scratchPane);
_SplitPane(_senderOrFocusedTab(sender), SplitDirection::Automatic, 0.5f, resultPane);
args.Handled(true);
}
}
}

View File

@@ -549,9 +549,6 @@ void AppCommandlineArgs::_addNewTerminalArgs(AppCommandlineArgs::NewTerminalSubc
subcommand.profileNameOption = subcommand.subcommand->add_option("-p,--profile",
_profileName,
RS_A(L"CmdProfileArgDesc"));
subcommand.sessionIdOption = subcommand.subcommand->add_option("--sessionId",
_sessionId,
RS_A(L"CmdSessionIdArgDesc"));
subcommand.startingDirectoryOption = subcommand.subcommand->add_option("-d,--startingDirectory",
_startingDirectory,
RS_A(L"CmdStartingDirArgDesc"));
@@ -631,13 +628,6 @@ NewTerminalArgs AppCommandlineArgs::_getNewTerminalArgs(AppCommandlineArgs::NewT
args.Profile(winrt::to_hstring(_profileName));
}
if (*subcommand.sessionIdOption)
{
const auto str = winrt::to_hstring(_sessionId);
const auto id = ::Microsoft::Console::Utils::GuidFromString(str.c_str());
args.SessionId(id);
}
if (*subcommand.startingDirectoryOption)
{
args.StartingDirectory(winrt::to_hstring(_startingDirectory));
@@ -724,7 +714,6 @@ bool AppCommandlineArgs::_noCommandsProvided()
void AppCommandlineArgs::_resetStateToDefault()
{
_profileName.clear();
_sessionId.clear();
_startingDirectory.clear();
_startingTitle.clear();
_startingTabColor.clear();

View File

@@ -62,7 +62,6 @@ private:
CLI::App* subcommand;
CLI::Option* commandlineOption;
CLI::Option* profileNameOption;
CLI::Option* sessionIdOption;
CLI::Option* startingDirectoryOption;
CLI::Option* titleOption;
CLI::Option* tabColorOption;
@@ -97,7 +96,6 @@ private:
// Are you adding a new sub-command? Make sure to update _noCommandsProvided!
std::string _profileName;
std::string _sessionId;
std::string _startingDirectory;
std::string _startingTitle;
std::string _startingTabColor;

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