mirror of
https://github.com/microsoft/terminal.git
synced 2026-04-14 02:01:01 +00:00
Compare commits
182 Commits
dev/cazamo
...
dev/migrie
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
080540983c | ||
|
|
5c17603a94 | ||
|
|
354e4b00a3 | ||
|
|
8707c03715 | ||
|
|
31b2763be5 | ||
|
|
a000d81fa9 | ||
|
|
d36a08186c | ||
|
|
3b1bb455d8 | ||
|
|
901bc78966 | ||
|
|
23a19c5818 | ||
|
|
7712104983 | ||
|
|
608a49e817 | ||
|
|
10992b77a0 | ||
|
|
f6f5598c9c | ||
|
|
f681d3a1c1 | ||
|
|
d07546a6fe | ||
|
|
ed7c716978 | ||
|
|
0c901edd81 | ||
|
|
acf1ddc9c4 | ||
|
|
cb2f347c2f | ||
|
|
49874d1b9e | ||
|
|
cfdf03c24b | ||
|
|
70d44c84c8 | ||
|
|
1678b58dde | ||
|
|
482dcec60a | ||
|
|
46fd7caf5a | ||
|
|
638c6d0291 | ||
|
|
68294f863d | ||
|
|
59f184aa2d | ||
|
|
4150609b42 | ||
|
|
d5920a8c69 | ||
|
|
fd364db727 | ||
|
|
3a0fbd9f59 | ||
|
|
64533c838a | ||
|
|
aa6b08118f | ||
|
|
b0b44410c6 | ||
|
|
a544f56e17 | ||
|
|
29be8564f6 | ||
|
|
5d36e5d2df | ||
|
|
0220f71883 | ||
|
|
70560a789c | ||
|
|
a0edb12cd6 | ||
|
|
b541179333 | ||
|
|
d3f9859051 | ||
|
|
f1dc649135 | ||
|
|
9eb9bc9235 | ||
|
|
56f1223dc5 | ||
|
|
88d974280d | ||
|
|
d84a31801a | ||
|
|
6910677a11 | ||
|
|
9331cc8e59 | ||
|
|
d465a47bc5 | ||
|
|
9c858cd5b8 | ||
|
|
42bf605e1c | ||
|
|
121fb739fd | ||
|
|
2f64db2765 | ||
|
|
4cc3d39de9 | ||
|
|
ebf41dd6b2 | ||
|
|
d8dcb6f570 | ||
|
|
a14b6f89f6 | ||
|
|
c55888f88d | ||
|
|
7acec306a6 | ||
|
|
cd4aabda84 | ||
|
|
fdffa24a71 | ||
|
|
9f2d40614b | ||
|
|
90ff261c35 | ||
|
|
dcbf7c74f1 | ||
|
|
76793b1e3f | ||
|
|
0b4839d94d | ||
|
|
2bd4670100 | ||
|
|
2eb659717c | ||
|
|
aea725f885 | ||
|
|
8ab3422b57 | ||
|
|
cccaab8545 | ||
|
|
e7108332f7 | ||
|
|
9ba20805ec | ||
|
|
94166942cc | ||
|
|
a2a605050f | ||
|
|
6936ee15fe | ||
|
|
a151607c79 | ||
|
|
fc64ff3029 | ||
|
|
34a6b1913c | ||
|
|
4b45bb8df1 | ||
|
|
f058b08fde | ||
|
|
b1bcc59230 | ||
|
|
10222a2ba2 | ||
|
|
3f5f37d910 | ||
|
|
37e0614554 | ||
|
|
d43a14c63f | ||
|
|
862217b04b | ||
|
|
3a71ead757 | ||
|
|
20e88d3e3e | ||
|
|
3ffaa1714a | ||
|
|
4c16cb278e | ||
|
|
335f69e099 | ||
|
|
cf97a9f772 | ||
|
|
41ade2c57e | ||
|
|
d1f152adcf | ||
|
|
8779249b12 | ||
|
|
10b12ac90c | ||
|
|
6ce2543a94 | ||
|
|
5a5902d580 | ||
|
|
0fefdac414 | ||
|
|
79115e2058 | ||
|
|
9c1331ab2e | ||
|
|
5f2ac4e3e7 | ||
|
|
6e70c4ae07 | ||
|
|
b05a557f48 | ||
|
|
2e246123cf | ||
|
|
fb69aecb19 | ||
|
|
730d6960ab | ||
|
|
7f3bc3cb04 | ||
|
|
8947909121 | ||
|
|
293c36d42f | ||
|
|
cf8f411b8f | ||
|
|
ee6ca81d70 | ||
|
|
b609266d29 | ||
|
|
59e2835736 | ||
|
|
3bf5436122 | ||
|
|
5ea778b2b8 | ||
|
|
cabb83db61 | ||
|
|
769e910e35 | ||
|
|
1d02f82ab7 | ||
|
|
84e30bcd3a | ||
|
|
f68324cd09 | ||
|
|
fca87b2bb5 | ||
|
|
c12835783d | ||
|
|
56bbe86f96 | ||
|
|
d13c37cd60 | ||
|
|
32fbd4cbb6 | ||
|
|
6d7723e3be | ||
|
|
e37fd5e546 | ||
|
|
59166faa27 | ||
|
|
19f8b9c3ca | ||
|
|
17e68a09a8 | ||
|
|
0980a0d50f | ||
|
|
1d33429673 | ||
|
|
ef8ba20bee | ||
|
|
a0e5085b49 | ||
|
|
d57fb84557 | ||
|
|
be2b77653f | ||
|
|
c18e0f5008 | ||
|
|
a89746a869 | ||
|
|
f339705ce7 | ||
|
|
f152573058 | ||
|
|
91b454ac95 | ||
|
|
6409ab91fa | ||
|
|
a0527a1dbe | ||
|
|
f03cacfa5b | ||
|
|
cdecfcd67f | ||
|
|
d6da6ba353 | ||
|
|
96f4a9daef | ||
|
|
1374396f10 | ||
|
|
192d6debba | ||
|
|
a50731119a | ||
|
|
305e3df8fa | ||
|
|
83c6bce73d | ||
|
|
59239e3b07 | ||
|
|
79a18f0825 | ||
|
|
d3b9a780d3 | ||
|
|
9b9b0738c8 | ||
|
|
f3e30d07fa | ||
|
|
ee3259847a | ||
|
|
ab5a8d701d | ||
|
|
6a37818c07 | ||
|
|
4fc283f8b6 | ||
|
|
51e1ae3e8a | ||
|
|
8c057a04a8 | ||
|
|
8c00dd7d55 | ||
|
|
848e353b9c | ||
|
|
e3b7a44b13 | ||
|
|
0d9a357373 | ||
|
|
85c485e94f | ||
|
|
1b79cc87c3 | ||
|
|
b7fc0f2d44 | ||
|
|
2770228e09 | ||
|
|
4f0b57ec8e | ||
|
|
e2005ca5d7 | ||
|
|
c8f00df170 | ||
|
|
c90de69250 | ||
|
|
448684a5f4 | ||
|
|
0d3f85de85 |
15
.github/actions/spelling/README.md
vendored
Normal file
15
.github/actions/spelling/README.md
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
# check-spelling/check-spelling configuration
|
||||
|
||||
File | Purpose | Format | Info
|
||||
-|-|-|-
|
||||
[allow/*.txt](allow/) | Add words to the dictionary | one word per line (only letters and `'`s allowed) | [allow](https://github.com/check-spelling/check-spelling/wiki/Configuration#allow)
|
||||
[reject.txt](reject.txt) | Remove words from the dictionary (after allow) | grep pattern matching whole dictionary words | [reject](https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples%3A-reject)
|
||||
[excludes.txt](excludes.txt) | Files to ignore entirely | perl regular expression | [excludes](https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples%3A-excludes)
|
||||
[patterns/*.txt](patterns/) | Patterns to ignore from checked lines | perl regular expression (order matters, first match wins) | [patterns](https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples%3A-patterns)
|
||||
[candidate.patterns](candidate.patterns) | Patterns that might be worth adding to [patterns.txt](patterns.txt) | perl regular expression with optional comment block introductions (all matches will be suggested) | [candidates](https://github.com/check-spelling/check-spelling/wiki/Feature:-Suggest-patterns)
|
||||
[line_forbidden.patterns](line_forbidden.patterns) | Patterns to flag in checked lines | perl regular expression (order matters, first match wins) | [patterns](https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples%3A-patterns)
|
||||
[expect/*.txt](expect.txt) | Expected words that aren't in the dictionary | one word per line (sorted, alphabetically) | [expect](https://github.com/check-spelling/check-spelling/wiki/Configuration#expect)
|
||||
[advice.md](advice.md) | Supplement for GitHub comment when unrecognized words are found | GitHub Markdown | [advice](https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples%3A-advice)
|
||||
|
||||
Note: you can replace any of these files with a directory by the same name (minus the suffix)
|
||||
and then include multiple files inside that directory (with that suffix) to merge multiple files together.
|
||||
38
.github/actions/spelling/advice.md
vendored
38
.github/actions/spelling/advice.md
vendored
@@ -1,4 +1,4 @@
|
||||
<!-- markdownlint-disable MD033 MD041 -->
|
||||
<!-- See https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples%3A-advice --> <!-- markdownlint-disable MD033 MD041 -->
|
||||
<details>
|
||||
<summary>
|
||||
:pencil2: Contributor please read this
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
By default the command suggestion will generate a file named based on your commit. That's generally ok as long as you add the file to your commit. Someone can reorganize it later.
|
||||
|
||||
:warning: The command is written for posix shells. You can copy the contents of each `perl` command excluding the outer `'` marks and dropping any `'"`/`"'` quotation mark pairs into a file and then run `perl file.pl` from the root of the repository to run the code. Alternatively, you can manually insert the items...
|
||||
:warning: The command is written for posix shells. If it doesn't work for you, you can manually _add_ (one word per line) / _remove_ items to `expect.txt` and the `excludes.txt` files.
|
||||
|
||||
If the listed items are:
|
||||
|
||||
@@ -20,31 +20,29 @@ See the `README.md` in each directory for more information.
|
||||
|
||||
:microscope: You can test your commits **without** *appending* to a PR by creating a new branch with that extra change and pushing it to your fork. The [check-spelling](https://github.com/marketplace/actions/check-spelling) action will run in response to your **push** -- it doesn't require an open pull request. By using such a branch, you can limit the number of typos your peers see you make. :wink:
|
||||
|
||||
<details><summary>:clamp: If you see a bunch of garbage</summary>
|
||||
|
||||
If it relates to a ...
|
||||
<details><summary>well-formed pattern</summary>
|
||||
<details><summary>If the flagged items are :exploding_head: false positives</summary>
|
||||
|
||||
See if there's a [pattern](https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples:-patterns) that would match it.
|
||||
If items relate to a ...
|
||||
* binary file (or some other file you wouldn't want to check at all).
|
||||
|
||||
If not, try writing one and adding it to a `patterns/{file}.txt`.
|
||||
Please add a file path to the `excludes.txt` file matching the containing file.
|
||||
|
||||
Patterns are Perl 5 Regular Expressions - you can [test](
|
||||
https://www.regexplanet.com/advanced/perl/) yours before committing to verify it will match your lines.
|
||||
|
||||
Note that patterns can't match multiline strings.
|
||||
</details>
|
||||
<details><summary>binary-ish string</summary>
|
||||
|
||||
Please add a file path to the `excludes.txt` file instead of just accepting the garbage.
|
||||
|
||||
File paths are Perl 5 Regular Expressions - you can [test](
|
||||
File paths are Perl 5 Regular Expressions - you can [test](
|
||||
https://www.regexplanet.com/advanced/perl/) yours before committing to verify it will match your files.
|
||||
|
||||
`^` refers to the file's path from the root of the repository, so `^README\.md$` would exclude [README.md](
|
||||
`^` refers to the file's path from the root of the repository, so `^README\.md$` would exclude [README.md](
|
||||
../tree/HEAD/README.md) (on whichever branch you're using).
|
||||
</details>
|
||||
|
||||
|
||||
* well-formed pattern.
|
||||
|
||||
If you can write a [pattern](https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples:-patterns) that would match it,
|
||||
try adding it to the `patterns.txt` file.
|
||||
|
||||
Patterns are Perl 5 Regular Expressions - you can [test](
|
||||
https://www.regexplanet.com/advanced/perl/) yours before committing to verify it will match your lines.
|
||||
|
||||
Note that patterns can't match multiline strings.
|
||||
</details>
|
||||
|
||||
</details>
|
||||
|
||||
52
.github/actions/spelling/allow/allow.txt
vendored
52
.github/actions/spelling/allow/allow.txt
vendored
@@ -1,7 +1,18 @@
|
||||
admins
|
||||
allcolors
|
||||
Apc
|
||||
apc
|
||||
breadcrumb
|
||||
breadcrumbs
|
||||
bsd
|
||||
calt
|
||||
ccmp
|
||||
changelog
|
||||
clickable
|
||||
clig
|
||||
CMMI
|
||||
copyable
|
||||
cybersecurity
|
||||
dalet
|
||||
Dcs
|
||||
dcs
|
||||
@@ -11,46 +22,87 @@ downside
|
||||
downsides
|
||||
dze
|
||||
dzhe
|
||||
EDDB
|
||||
EDDC
|
||||
Enum'd
|
||||
Fitt
|
||||
formattings
|
||||
FTCS
|
||||
ftp
|
||||
fvar
|
||||
gantt
|
||||
gcc
|
||||
geeksforgeeks
|
||||
ghe
|
||||
github
|
||||
gje
|
||||
godbolt
|
||||
hostname
|
||||
hostnames
|
||||
https
|
||||
hyperlink
|
||||
hyperlinking
|
||||
hyperlinks
|
||||
iconify
|
||||
img
|
||||
inlined
|
||||
It'd
|
||||
kje
|
||||
libfuzzer
|
||||
libuv
|
||||
liga
|
||||
lje
|
||||
Llast
|
||||
llvm
|
||||
Lmid
|
||||
locl
|
||||
lol
|
||||
lorem
|
||||
Lorigin
|
||||
maxed
|
||||
minimalistic
|
||||
mkmk
|
||||
mnt
|
||||
mru
|
||||
nje
|
||||
noreply
|
||||
ogonek
|
||||
ok'd
|
||||
overlined
|
||||
pipeline
|
||||
postmodern
|
||||
ptys
|
||||
qof
|
||||
qps
|
||||
rclt
|
||||
reimplementation
|
||||
reserialization
|
||||
reserialize
|
||||
reserializes
|
||||
rlig
|
||||
runtimes
|
||||
shcha
|
||||
slnt
|
||||
Sos
|
||||
ssh
|
||||
timeline
|
||||
timelines
|
||||
timestamped
|
||||
TLDR
|
||||
tokenizes
|
||||
tonos
|
||||
toolset
|
||||
tshe
|
||||
ubuntu
|
||||
uiatextrange
|
||||
UIs
|
||||
und
|
||||
unregister
|
||||
versioned
|
||||
vsdevcmd
|
||||
We'd
|
||||
wildcards
|
||||
XBox
|
||||
YBox
|
||||
yeru
|
||||
zhe
|
||||
|
||||
89
.github/actions/spelling/allow/apis.txt
vendored
89
.github/actions/spelling/allow/apis.txt
vendored
@@ -1,30 +1,48 @@
|
||||
ACCEPTFILES
|
||||
ACCESSDENIED
|
||||
acl
|
||||
aclapi
|
||||
alignas
|
||||
alignof
|
||||
APPLYTOSUBMENUS
|
||||
appxrecipe
|
||||
bitfield
|
||||
bitfields
|
||||
BUILDBRANCH
|
||||
BUILDMSG
|
||||
BUILDNUMBER
|
||||
BYCOMMAND
|
||||
BYPOSITION
|
||||
charconv
|
||||
CLASSNOTAVAILABLE
|
||||
CLOSEAPP
|
||||
cmdletbinding
|
||||
COLORPROPERTY
|
||||
colspan
|
||||
COMDLG
|
||||
commandlinetoargv
|
||||
comparand
|
||||
cstdint
|
||||
CXICON
|
||||
CYICON
|
||||
Dacl
|
||||
dataobject
|
||||
dcomp
|
||||
DERR
|
||||
dlldata
|
||||
DNE
|
||||
DONTADDTORECENT
|
||||
DWMSBT
|
||||
DWMWA
|
||||
DWMWA
|
||||
DWORDLONG
|
||||
endfor
|
||||
ENDSESSION
|
||||
enumset
|
||||
environstrings
|
||||
EXPCMDFLAGS
|
||||
EXPCMDSTATE
|
||||
filetime
|
||||
FILTERSPEC
|
||||
FORCEFILESYSTEM
|
||||
FORCEMINIMIZE
|
||||
@@ -33,12 +51,16 @@ fullkbd
|
||||
futex
|
||||
GETDESKWALLPAPER
|
||||
GETHIGHCONTRAST
|
||||
GETMOUSEHOVERTIME
|
||||
Hashtable
|
||||
HIGHCONTRASTON
|
||||
HIGHCONTRASTW
|
||||
hotkeys
|
||||
href
|
||||
hrgn
|
||||
HTCLOSE
|
||||
hwinsta
|
||||
HWINSTA
|
||||
IActivation
|
||||
IApp
|
||||
IAppearance
|
||||
@@ -55,93 +77,157 @@ IDirect
|
||||
IExplorer
|
||||
IFACEMETHOD
|
||||
IFile
|
||||
IGraphics
|
||||
IInheritable
|
||||
IMap
|
||||
IMonarch
|
||||
IObject
|
||||
iosfwd
|
||||
IPackage
|
||||
IPeasant
|
||||
ISetup
|
||||
isspace
|
||||
IStorage
|
||||
istream
|
||||
IStringable
|
||||
ITab
|
||||
ITaskbar
|
||||
itow
|
||||
IUri
|
||||
IVirtual
|
||||
KEYSELECT
|
||||
LCID
|
||||
llabs
|
||||
llu
|
||||
localtime
|
||||
lround
|
||||
Lsa
|
||||
lsass
|
||||
LSHIFT
|
||||
LTGRAY
|
||||
MAINWINDOW
|
||||
memchr
|
||||
memicmp
|
||||
MENUCOMMAND
|
||||
MENUDATA
|
||||
MENUINFO
|
||||
MENUITEMINFOW
|
||||
mmeapi
|
||||
MOUSELEAVE
|
||||
mov
|
||||
mptt
|
||||
msappx
|
||||
MULTIPLEUSE
|
||||
NCHITTEST
|
||||
NCLBUTTONDBLCLK
|
||||
NCMOUSELEAVE
|
||||
NCMOUSEMOVE
|
||||
NCRBUTTONDBLCLK
|
||||
NIF
|
||||
NIN
|
||||
NOAGGREGATION
|
||||
NOASYNC
|
||||
NOCHANGEDIR
|
||||
NOPROGRESS
|
||||
NOREDIRECTIONBITMAP
|
||||
NOREPEAT
|
||||
NOTIFYBYPOS
|
||||
NOTIFYICON
|
||||
NOTIFYICONDATA
|
||||
ntprivapi
|
||||
oaidl
|
||||
ocidl
|
||||
ODR
|
||||
offsetof
|
||||
ofstream
|
||||
onefuzz
|
||||
osver
|
||||
OSVERSIONINFOEXW
|
||||
otms
|
||||
OUTLINETEXTMETRICW
|
||||
overridable
|
||||
PACL
|
||||
PAGESCROLL
|
||||
PATINVERT
|
||||
PEXPLICIT
|
||||
PICKFOLDERS
|
||||
pmr
|
||||
ptstr
|
||||
QUERYENDSESSION
|
||||
rcx
|
||||
REGCLS
|
||||
RETURNCMD
|
||||
rfind
|
||||
ROOTOWNER
|
||||
roundf
|
||||
RSHIFT
|
||||
SACL
|
||||
schandle
|
||||
semver
|
||||
serializer
|
||||
SETVERSION
|
||||
SHELLEXECUTEINFOW
|
||||
shobjidl
|
||||
SHOWHIDE
|
||||
SHOWMINIMIZED
|
||||
SHOWTIP
|
||||
SINGLEUSE
|
||||
SIZENS
|
||||
smoothstep
|
||||
snprintf
|
||||
spsc
|
||||
sregex
|
||||
SRWLOC
|
||||
SRWLOCK
|
||||
STDCPP
|
||||
STDMETHOD
|
||||
strchr
|
||||
strcpy
|
||||
streambuf
|
||||
strtoul
|
||||
Stubless
|
||||
Subheader
|
||||
Subpage
|
||||
syscall
|
||||
SYSTEMBACKDROP
|
||||
TABROW
|
||||
TASKBARCREATED
|
||||
TBPF
|
||||
THEMECHANGED
|
||||
tlg
|
||||
TME
|
||||
tmp
|
||||
tmpdir
|
||||
tolower
|
||||
toupper
|
||||
TRACKMOUSEEVENT
|
||||
TTask
|
||||
TVal
|
||||
UChar
|
||||
UFIELD
|
||||
ULARGE
|
||||
UOI
|
||||
UPDATEINIFILE
|
||||
userenv
|
||||
USEROBJECTFLAGS
|
||||
Viewbox
|
||||
virtualalloc
|
||||
wcsstr
|
||||
wcstoui
|
||||
winmain
|
||||
winsta
|
||||
winstamin
|
||||
wmemcmp
|
||||
wpc
|
||||
WSF
|
||||
wsregex
|
||||
wwinmain
|
||||
xchg
|
||||
XDocument
|
||||
XElement
|
||||
xfacet
|
||||
xhash
|
||||
XIcon
|
||||
xiosbase
|
||||
xlocale
|
||||
xlocbuf
|
||||
@@ -150,6 +236,7 @@ xlocmes
|
||||
xlocmon
|
||||
xlocnum
|
||||
xloctime
|
||||
XMax
|
||||
xmemory
|
||||
XParse
|
||||
xpath
|
||||
@@ -157,3 +244,5 @@ xstddef
|
||||
xstring
|
||||
xtree
|
||||
xutility
|
||||
YIcon
|
||||
YMax
|
||||
|
||||
1
.github/actions/spelling/allow/fonts.txt
vendored
1
.github/actions/spelling/allow/fonts.txt
vendored
@@ -7,3 +7,4 @@ Iosevka
|
||||
MDL
|
||||
Monofur
|
||||
Segoe
|
||||
wght
|
||||
|
||||
8
.github/actions/spelling/allow/math.txt
vendored
8
.github/actions/spelling/allow/math.txt
vendored
@@ -1,3 +1,11 @@
|
||||
atan
|
||||
CPrime
|
||||
HBar
|
||||
HPrime
|
||||
isnan
|
||||
LPrime
|
||||
LStep
|
||||
powf
|
||||
RSub
|
||||
sqrtf
|
||||
ULP
|
||||
|
||||
20
.github/actions/spelling/allow/microsoft.txt
vendored
20
.github/actions/spelling/allow/microsoft.txt
vendored
@@ -1,5 +1,6 @@
|
||||
ACLs
|
||||
ADMINS
|
||||
advapi
|
||||
altform
|
||||
altforms
|
||||
appendwttlogging
|
||||
@@ -15,8 +16,10 @@ CPLs
|
||||
cpptools
|
||||
cppvsdbg
|
||||
CPRs
|
||||
cryptbase
|
||||
DACL
|
||||
DACLs
|
||||
defaultlib
|
||||
diffs
|
||||
disposables
|
||||
dotnetfeed
|
||||
@@ -24,14 +27,24 @@ DTDs
|
||||
DWINRT
|
||||
enablewttlogging
|
||||
Intelli
|
||||
IVisual
|
||||
libucrt
|
||||
libucrtd
|
||||
LKG
|
||||
LOCKFILE
|
||||
Lxss
|
||||
mfcribbon
|
||||
microsoft
|
||||
microsoftonline
|
||||
MSAA
|
||||
msixbundle
|
||||
MSVC
|
||||
MSVCP
|
||||
muxc
|
||||
netcore
|
||||
Onefuzz
|
||||
osgvsowi
|
||||
PFILETIME
|
||||
pgc
|
||||
pgo
|
||||
pgosweep
|
||||
@@ -39,10 +52,14 @@ powerrename
|
||||
powershell
|
||||
propkey
|
||||
pscustomobject
|
||||
QWORD
|
||||
regedit
|
||||
robocopy
|
||||
SACLs
|
||||
sdkddkver
|
||||
Shobjidl
|
||||
Skype
|
||||
SRW
|
||||
sxs
|
||||
Sysinternals
|
||||
sysnative
|
||||
@@ -50,6 +67,8 @@ systemroot
|
||||
taskkill
|
||||
tasklist
|
||||
tdbuildteamid
|
||||
ucrt
|
||||
ucrtd
|
||||
unvirtualized
|
||||
VCRT
|
||||
vcruntime
|
||||
@@ -57,6 +76,7 @@ Virtualization
|
||||
visualstudio
|
||||
vscode
|
||||
VSTHRD
|
||||
winsdkver
|
||||
wlk
|
||||
wslpath
|
||||
wtl
|
||||
|
||||
14
.github/actions/spelling/allow/names.txt
vendored
14
.github/actions/spelling/allow/names.txt
vendored
@@ -1,14 +1,18 @@
|
||||
Anup
|
||||
austdi
|
||||
arkthur
|
||||
Ballmer
|
||||
bhoj
|
||||
Bhojwani
|
||||
Bluloco
|
||||
carlos
|
||||
dhowett
|
||||
Diviness
|
||||
dsafa
|
||||
duhowett
|
||||
DXP
|
||||
ekg
|
||||
eryksun
|
||||
ethanschoonover
|
||||
Firefox
|
||||
Gatta
|
||||
@@ -20,6 +24,7 @@ Hernan
|
||||
Howett
|
||||
Illhardt
|
||||
iquilezles
|
||||
italo
|
||||
jantari
|
||||
jerrysh
|
||||
Kaiyu
|
||||
@@ -31,8 +36,11 @@ Kourosh
|
||||
kowalczyk
|
||||
leonmsft
|
||||
Lepilleur
|
||||
lhecker
|
||||
lukesampson
|
||||
Macbook
|
||||
Manandhar
|
||||
masserano
|
||||
mbadolato
|
||||
Mehrain
|
||||
menger
|
||||
@@ -52,6 +60,7 @@ oldnewthing
|
||||
opengl
|
||||
osgwiki
|
||||
pabhojwa
|
||||
panos
|
||||
paulcam
|
||||
pauldotknopf
|
||||
PGP
|
||||
@@ -60,12 +69,17 @@ Rincewind
|
||||
rprichard
|
||||
Schoonover
|
||||
shadertoy
|
||||
Shomnipotence
|
||||
simioni
|
||||
Somuah
|
||||
sonph
|
||||
sonpham
|
||||
stakx
|
||||
talo
|
||||
thereses
|
||||
Walisch
|
||||
WDX
|
||||
Wellons
|
||||
Wirt
|
||||
Wojciech
|
||||
zadjii
|
||||
|
||||
523
.github/actions/spelling/candidate.patterns
vendored
Normal file
523
.github/actions/spelling/candidate.patterns
vendored
Normal file
@@ -0,0 +1,523 @@
|
||||
# marker to ignore all code on line
|
||||
^.*/\* #no-spell-check-line \*/.*$
|
||||
# marker for ignoring a comment to the end of the line
|
||||
// #no-spell-check.*$
|
||||
|
||||
# patch hunk comments
|
||||
^\@\@ -\d+(?:,\d+|) \+\d+(?:,\d+|) \@\@ .*
|
||||
# git index header
|
||||
index [0-9a-z]{7,40}\.\.[0-9a-z]{7,40}
|
||||
|
||||
# cid urls
|
||||
(['"])cid:.*?\g{-1}
|
||||
|
||||
# data url in parens
|
||||
\(data:[^)]*?(?:[A-Z]{3,}|[A-Z][a-z]{2,}|[a-z]{3,})[^)]*\)
|
||||
# data url in quotes
|
||||
([`'"])data:.*?(?:[A-Z]{3,}|[A-Z][a-z]{2,}|[a-z]{3,}).*\g{-1}
|
||||
# data url
|
||||
data:[-a-zA-Z=;:/0-9+]*,\S*
|
||||
|
||||
# mailto urls
|
||||
mailto:[-a-zA-Z=;:/?%&0-9+@.]{3,}
|
||||
|
||||
# magnet urls
|
||||
magnet:[?=:\w]+
|
||||
|
||||
# magnet urls
|
||||
"magnet:[^"]+"
|
||||
|
||||
# obs:
|
||||
"obs:[^"]*"
|
||||
|
||||
# The `\b` here means a break, it's the fancy way to handle urls, but it makes things harder to read
|
||||
# In this examples content, I'm using a number of different ways to match things to show various approaches
|
||||
# asciinema
|
||||
\basciinema\.org/a/[0-9a-zA-Z]+
|
||||
|
||||
# apple
|
||||
\bdeveloper\.apple\.com/[-\w?=/]+
|
||||
# Apple music
|
||||
\bembed\.music\.apple\.com/fr/playlist/usr-share/[-\w.]+
|
||||
|
||||
# appveyor api
|
||||
\bci\.appveyor\.com/api/projects/status/[0-9a-z]+
|
||||
# appveyor project
|
||||
\bci\.appveyor\.com/project/(?:[^/\s"]*/){2}builds?/\d+/job/[0-9a-z]+
|
||||
|
||||
# Amazon
|
||||
|
||||
# Amazon
|
||||
\bamazon\.com/[-\w]+/(?:dp/[0-9A-Z]+|)
|
||||
# AWS S3
|
||||
\b\w*\.s3[^.]*\.amazonaws\.com/[-\w/&#%_?:=]*
|
||||
# AWS execute-api
|
||||
\b[0-9a-z]{10}\.execute-api\.[-0-9a-z]+\.amazonaws\.com\b
|
||||
# AWS ELB
|
||||
\b\w+\.[-0-9a-z]+\.elb\.amazonaws\.com\b
|
||||
# AWS SNS
|
||||
\bsns\.[-0-9a-z]+.amazonaws\.com/[-\w/&#%_?:=]*
|
||||
# AWS VPC
|
||||
vpc-\w+
|
||||
|
||||
# While you could try to match `http://` and `https://` by using `s?` in `https?://`, sometimes there
|
||||
# YouTube url
|
||||
\b(?:(?:www\.|)youtube\.com|youtu.be)/(?:channel/|embed/|user/|playlist\?list=|watch\?v=|v/|)[-a-zA-Z0-9?&=_%]*
|
||||
# YouTube music
|
||||
\bmusic\.youtube\.com/youtubei/v1/browse(?:[?&]\w+=[-a-zA-Z0-9?&=_]*)
|
||||
# YouTube tag
|
||||
<\s*youtube\s+id=['"][-a-zA-Z0-9?_]*['"]
|
||||
# YouTube image
|
||||
\bimg\.youtube\.com/vi/[-a-zA-Z0-9?&=_]*
|
||||
# Google Accounts
|
||||
\baccounts.google.com/[-_/?=.:;+%&0-9a-zA-Z]*
|
||||
# Google Analytics
|
||||
\bgoogle-analytics\.com/collect.[-0-9a-zA-Z?%=&_.~]*
|
||||
# Google APIs
|
||||
\bgoogleapis\.(?:com|dev)/[a-z]+/(?:v\d+/|)[a-z]+/[-@:./?=\w+|&]+
|
||||
# Google Storage
|
||||
\b[-a-zA-Z0-9.]*\bstorage\d*\.googleapis\.com(?:/\S*|)
|
||||
# Google Calendar
|
||||
\bcalendar\.google\.com/calendar(?:/u/\d+|)/embed\?src=[@./?=\w&%]+
|
||||
\w+\@group\.calendar\.google\.com\b
|
||||
# Google DataStudio
|
||||
\bdatastudio\.google\.com/(?:(?:c/|)u/\d+/|)(?:embed/|)(?:open|reporting|datasources|s)/[-0-9a-zA-Z]+(?:/page/[-0-9a-zA-Z]+|)
|
||||
# The leading `/` here is as opposed to the `\b` above
|
||||
# ... a short way to match `https://` or `http://` since most urls have one of those prefixes
|
||||
# Google Docs
|
||||
/docs\.google\.com/[a-z]+/(?:ccc\?key=\w+|(?:u/\d+|d/(?:e/|)[0-9a-zA-Z_-]+/)?(?:edit\?[-\w=#.]*|/\?[\w=&]*|))
|
||||
# Google Drive
|
||||
\bdrive\.google\.com/(?:file/d/|open)[-0-9a-zA-Z_?=]*
|
||||
# Google Groups
|
||||
\bgroups\.google\.com/(?:(?:forum/#!|d/)(?:msg|topics?|searchin)|a)/[^/\s"]+/[-a-zA-Z0-9$]+(?:/[-a-zA-Z0-9]+)*
|
||||
# Google Maps
|
||||
\bmaps\.google\.com/maps\?[\w&;=]*
|
||||
# Google themes
|
||||
themes\.googleusercontent\.com/static/fonts/[^/\s"]+/v\d+/[^.]+.
|
||||
# Google CDN
|
||||
\bclients2\.google(?:usercontent|)\.com[-0-9a-zA-Z/.]*
|
||||
# Goo.gl
|
||||
/goo\.gl/[a-zA-Z0-9]+
|
||||
# Google Chrome Store
|
||||
\bchrome\.google\.com/webstore/detail/[-\w]*(?:/\w*|)
|
||||
# Google Books
|
||||
\bgoogle\.(?:\w{2,4})/books(?:/\w+)*\?[-\w\d=&#.]*
|
||||
# Google Fonts
|
||||
\bfonts\.(?:googleapis|gstatic)\.com/[-/?=:;+&0-9a-zA-Z]*
|
||||
# Google Forms
|
||||
\bforms\.gle/\w+
|
||||
# Google Scholar
|
||||
\bscholar\.google\.com/citations\?user=[A-Za-z0-9_]+
|
||||
# Google Colab Research Drive
|
||||
\bcolab\.research\.google\.com/drive/[-0-9a-zA-Z_?=]*
|
||||
|
||||
# GitHub SHAs (api)
|
||||
\bapi.github\.com/repos(?:/[^/\s"]+){3}/[0-9a-f]+\b
|
||||
# GitHub SHAs (markdown)
|
||||
(?:\[`?[0-9a-f]+`?\]\(https:/|)/(?:www\.|)github\.com(?:/[^/\s"]+){2,}(?:/[^/\s")]+)(?:[0-9a-f]+(?:[-0-9a-zA-Z/#.]*|)\b|)
|
||||
# GitHub SHAs
|
||||
\bgithub\.com(?:/[^/\s"]+){2}[@#][0-9a-f]+\b
|
||||
# GitHub wiki
|
||||
\bgithub\.com/(?:[^/]+/){2}wiki/(?:(?:[^/]+/|)_history|[^/]+(?:/_compare|)/[0-9a-f.]{40,})\b
|
||||
# githubusercontent
|
||||
/[-a-z0-9]+\.githubusercontent\.com/[-a-zA-Z0-9?&=_\/.]*
|
||||
# githubassets
|
||||
\bgithubassets.com/[0-9a-f]+(?:[-/\w.]+)
|
||||
# gist github
|
||||
\bgist\.github\.com/[^/\s"]+/[0-9a-f]+
|
||||
# git.io
|
||||
\bgit\.io/[0-9a-zA-Z]+
|
||||
# GitHub JSON
|
||||
"node_id": "[-a-zA-Z=;:/0-9+]*"
|
||||
# Contributor
|
||||
\[[^\]]+\]\(https://github\.com/[^/\s"]+\)
|
||||
# GHSA
|
||||
GHSA(?:-[0-9a-z]{4}){3}
|
||||
|
||||
# GitLab commit
|
||||
\bgitlab\.[^/\s"]*/\S+/\S+/commit/[0-9a-f]{7,16}#[0-9a-f]{40}\b
|
||||
# GitLab merge requests
|
||||
\bgitlab\.[^/\s"]*/\S+/\S+/-/merge_requests/\d+/diffs#[0-9a-f]{40}\b
|
||||
# GitLab uploads
|
||||
\bgitlab\.[^/\s"]*/uploads/[-a-zA-Z=;:/0-9+]*
|
||||
# GitLab commits
|
||||
\bgitlab\.[^/\s"]*/(?:[^/\s"]+/){2}commits?/[0-9a-f]+\b
|
||||
|
||||
# binanace
|
||||
accounts.binance.com/[a-z/]*oauth/authorize\?[-0-9a-zA-Z&%]*
|
||||
|
||||
# bitbucket diff
|
||||
\bapi\.bitbucket\.org/\d+\.\d+/repositories/(?:[^/\s"]+/){2}diff(?:stat|)(?:/[^/\s"]+){2}:[0-9a-f]+
|
||||
# bitbucket repositories commits
|
||||
\bapi\.bitbucket\.org/\d+\.\d+/repositories/(?:[^/\s"]+/){2}commits?/[0-9a-f]+
|
||||
# bitbucket commits
|
||||
\bbitbucket\.org/(?:[^/\s"]+/){2}commits?/[0-9a-f]+
|
||||
|
||||
# bit.ly
|
||||
\bbit\.ly/\w+
|
||||
|
||||
# bitrise
|
||||
\bapp\.bitrise\.io/app/[0-9a-f]*/[\w.?=&]*
|
||||
|
||||
# bootstrapcdn.com
|
||||
\bbootstrapcdn\.com/[-./\w]+
|
||||
|
||||
# cdn.cloudflare.com
|
||||
\bcdnjs\.cloudflare\.com/[./\w]+
|
||||
|
||||
# circleci
|
||||
\bcircleci\.com/gh(?:/[^/\s"]+){1,5}.[a-z]+\?[-0-9a-zA-Z=&]+
|
||||
|
||||
# gitter
|
||||
\bgitter\.im(?:/[^/\s"]+){2}\?at=[0-9a-f]+
|
||||
|
||||
# gravatar
|
||||
\bgravatar\.com/avatar/[0-9a-f]+
|
||||
|
||||
# ibm
|
||||
[a-z.]*ibm\.com/[-_#=:%!?~.\\/\d\w]*
|
||||
|
||||
# imgur
|
||||
\bimgur\.com/[^.]+
|
||||
|
||||
# Internet Archive
|
||||
\barchive\.org/web/\d+/(?:[-\w.?,'/\\+&%$#_:]*)
|
||||
|
||||
# discord
|
||||
/discord(?:app\.com|\.gg)/(?:invite/)?[a-zA-Z0-9]{7,}
|
||||
|
||||
# Disqus
|
||||
\bdisqus\.com/[-\w/%.()!?&=_]*
|
||||
|
||||
# medium link
|
||||
\blink\.medium\.com/[a-zA-Z0-9]+
|
||||
# medium
|
||||
\bmedium\.com/\@?[^/\s"]+/[-\w]+
|
||||
|
||||
# microsoft
|
||||
\b(?:https?://|)(?:(?:download\.visualstudio|docs|msdn2?|research)\.microsoft|blogs\.msdn)\.com/[-_a-zA-Z0-9()=./%]*
|
||||
# powerbi
|
||||
\bapp\.powerbi\.com/reportEmbed/[^"' ]*
|
||||
# vs devops
|
||||
\bvisualstudio.com(?::443|)/[-\w/?=%&.]*
|
||||
# microsoft store
|
||||
\bmicrosoft\.com/store/apps/\w+
|
||||
|
||||
# mvnrepository.com
|
||||
\bmvnrepository\.com/[-0-9a-z./]+
|
||||
|
||||
# now.sh
|
||||
/[0-9a-z-.]+\.now\.sh\b
|
||||
|
||||
# oracle
|
||||
\bdocs\.oracle\.com/[-0-9a-zA-Z./_?#&=]*
|
||||
|
||||
# chromatic.com
|
||||
/\S+.chromatic.com\S*[")]
|
||||
|
||||
# codacy
|
||||
\bapi\.codacy\.com/project/badge/Grade/[0-9a-f]+
|
||||
|
||||
# compai
|
||||
\bcompai\.pub/v1/png/[0-9a-f]+
|
||||
|
||||
# mailgun api
|
||||
\.api\.mailgun\.net/v3/domains/[0-9a-z]+\.mailgun.org/messages/[0-9a-zA-Z=@]*
|
||||
# mailgun
|
||||
\b[0-9a-z]+.mailgun.org
|
||||
|
||||
# /message-id/
|
||||
/message-id/[-\w@./%]+
|
||||
|
||||
# Reddit
|
||||
\breddit\.com/r/[/\w_]*
|
||||
|
||||
# requestb.in
|
||||
\brequestb\.in/[0-9a-z]+
|
||||
|
||||
# sched
|
||||
\b[a-z0-9]+\.sched\.com\b
|
||||
|
||||
# Slack url
|
||||
slack://[a-zA-Z0-9?&=]+
|
||||
# Slack
|
||||
\bslack\.com/[-0-9a-zA-Z/_~?&=.]*
|
||||
# Slack edge
|
||||
\bslack-edge\.com/[-a-zA-Z0-9?&=%./]+
|
||||
# Slack images
|
||||
\bslack-imgs\.com/[-a-zA-Z0-9?&=%.]+
|
||||
|
||||
# shields.io
|
||||
\bshields\.io/[-\w/%?=&.:+;,]*
|
||||
|
||||
# stackexchange -- https://stackexchange.com/feeds/sites
|
||||
\b(?:askubuntu|serverfault|stack(?:exchange|overflow)|superuser).com/(?:questions/\w+/[-\w]+|a/)
|
||||
|
||||
# Sentry
|
||||
[0-9a-f]{32}\@o\d+\.ingest\.sentry\.io\b
|
||||
|
||||
# Twitter markdown
|
||||
\[\@[^[/\]:]*?\]\(https://twitter.com/[^/\s"')]*(?:/status/\d+(?:\?[-_0-9a-zA-Z&=]*|)|)\)
|
||||
# Twitter hashtag
|
||||
\btwitter\.com/hashtag/[\w?_=&]*
|
||||
# Twitter status
|
||||
\btwitter\.com/[^/\s"')]*(?:/status/\d+(?:\?[-_0-9a-zA-Z&=]*|)|)
|
||||
# Twitter profile images
|
||||
\btwimg\.com/profile_images/[_\w./]*
|
||||
# Twitter media
|
||||
\btwimg\.com/media/[-_\w./?=]*
|
||||
# Twitter link shortened
|
||||
\bt\.co/\w+
|
||||
|
||||
# facebook
|
||||
\bfburl\.com/[0-9a-z_]+
|
||||
# facebook CDN
|
||||
\bfbcdn\.net/[\w/.,]*
|
||||
# facebook watch
|
||||
\bfb\.watch/[0-9A-Za-z]+
|
||||
|
||||
# dropbox
|
||||
\bdropbox\.com/sh?/[^/\s"]+/[-0-9A-Za-z_.%?=&;]+
|
||||
|
||||
# ipfs protocol
|
||||
ipfs://[0-9a-z]*
|
||||
# ipfs url
|
||||
/ipfs/[0-9a-z]*
|
||||
|
||||
# w3
|
||||
\bw3\.org/[-0-9a-zA-Z/#.]+
|
||||
|
||||
# loom
|
||||
\bloom\.com/embed/[0-9a-f]+
|
||||
|
||||
# regex101
|
||||
\bregex101\.com/r/[^/\s"]+/\d+
|
||||
|
||||
# figma
|
||||
\bfigma\.com/file(?:/[0-9a-zA-Z]+/)+
|
||||
|
||||
# freecodecamp.org
|
||||
\bfreecodecamp\.org/[-\w/.]+
|
||||
|
||||
# image.tmdb.org
|
||||
\bimage\.tmdb\.org/[/\w.]+
|
||||
|
||||
# mermaid
|
||||
\bmermaid\.ink/img/[-\w]+|\bmermaid-js\.github\.io/mermaid-live-editor/#/edit/[-\w]+
|
||||
|
||||
# Wikipedia
|
||||
\ben\.wikipedia\.org/wiki/[-\w%.#]+
|
||||
|
||||
# gitweb
|
||||
[^"\s]+/gitweb/\S+;h=[0-9a-f]+
|
||||
|
||||
# HyperKitty lists
|
||||
/archives/list/[^@/]+\@[^/\s"]*/message/[^/\s"]*/
|
||||
|
||||
# lists
|
||||
/thread\.html/[^"\s]+
|
||||
|
||||
# list-management
|
||||
\blist-manage\.com/subscribe(?:[?&](?:u|id)=[0-9a-f]+)+
|
||||
|
||||
# kubectl.kubernetes.io/last-applied-configuration
|
||||
"kubectl.kubernetes.io/last-applied-configuration": ".*"
|
||||
|
||||
# pgp
|
||||
\bgnupg\.net/pks/lookup[?&=0-9a-zA-Z]*
|
||||
|
||||
# Spotify
|
||||
\bopen\.spotify\.com/embed/playlist/\w+
|
||||
|
||||
# Mastodon
|
||||
\bmastodon\.[-a-z.]*/(?:media/|\@)[?&=0-9a-zA-Z_]*
|
||||
|
||||
# scastie
|
||||
\bscastie\.scala-lang\.org/[^/]+/\w+
|
||||
|
||||
# images.unsplash.com
|
||||
\bimages\.unsplash\.com/(?:(?:flagged|reserve)/|)[-\w./%?=%&.;]+
|
||||
|
||||
# pastebin
|
||||
\bpastebin\.com/[\w/]+
|
||||
|
||||
# heroku
|
||||
\b\w+\.heroku\.com/source/archive/\w+
|
||||
|
||||
# quip
|
||||
\b\w+\.quip\.com/\w+(?:(?:#|/issues/)\w+)?
|
||||
|
||||
# badgen.net
|
||||
\bbadgen\.net/badge/[^")\]'\s]+
|
||||
|
||||
# statuspage.io
|
||||
\w+\.statuspage\.io\b
|
||||
|
||||
# media.giphy.com
|
||||
\bmedia\.giphy\.com/media/[^/]+/[\w.?&=]+
|
||||
|
||||
# tinyurl
|
||||
\btinyurl\.com/\w+
|
||||
|
||||
# getopts
|
||||
\bgetopts\s+(?:"[^"]+"|'[^']+')
|
||||
|
||||
# ANSI color codes
|
||||
(?:\\(?:u00|x)1b|\x1b)\[\d+(?:;\d+|)m
|
||||
|
||||
# URL escaped characters
|
||||
\%[0-9A-F][A-F]
|
||||
# IPv6
|
||||
\b(?:[0-9a-fA-F]{0,4}:){3,7}[0-9a-fA-F]{0,4}\b
|
||||
# c99 hex digits (not the full format, just one I've seen)
|
||||
0x[0-9a-fA-F](?:\.[0-9a-fA-F]*|)[pP]
|
||||
# Punycode
|
||||
\bxn--[-0-9a-z]+
|
||||
# sha
|
||||
sha\d+:[0-9]*[a-f]{3,}[0-9a-f]*
|
||||
# sha-... -- uses a fancy capture
|
||||
(['"]|")[0-9a-f]{40,}\g{-1}
|
||||
# hex runs
|
||||
\b[0-9a-fA-F]{16,}\b
|
||||
# hex in url queries
|
||||
=[0-9a-fA-F]*?(?:[A-F]{3,}|[a-f]{3,})[0-9a-fA-F]*?&
|
||||
# ssh
|
||||
(?:ssh-\S+|-nistp256) [-a-zA-Z=;:/0-9+]{12,}
|
||||
|
||||
# PGP
|
||||
\b(?:[0-9A-F]{4} ){9}[0-9A-F]{4}\b
|
||||
# GPG keys
|
||||
\b(?:[0-9A-F]{4} ){5}(?: [0-9A-F]{4}){5}\b
|
||||
# Well known gpg keys
|
||||
.well-known/openpgpkey/[\w./]+
|
||||
|
||||
# uuid:
|
||||
\b[0-9a-fA-F]{8}-(?:[0-9a-fA-F]{4}-){3}[0-9a-fA-F]{12}\b
|
||||
# hex digits including css/html color classes:
|
||||
(?:[\\0][xX]|\\u|[uU]\+|#x?|\%23)[0-9_a-fA-FgGrR]*?[a-fA-FgGrR]{2,}[0-9_a-fA-FgGrR]*(?:[uUlL]{0,3}|u\d+)\b
|
||||
# integrity
|
||||
integrity="sha\d+-[-a-zA-Z=;:/0-9+]{40,}"
|
||||
|
||||
# https://www.gnu.org/software/groff/manual/groff.html
|
||||
# man troff content
|
||||
\\f[BCIPR]
|
||||
# '
|
||||
\\\(aq
|
||||
|
||||
# .desktop mime types
|
||||
^MimeTypes?=.*$
|
||||
# .desktop localized entries
|
||||
^[A-Z][a-z]+\[[a-z]+\]=.*$
|
||||
# Localized .desktop content
|
||||
Name\[[^\]]+\]=.*
|
||||
|
||||
# IServiceProvider
|
||||
\bI(?=(?:[A-Z][a-z]{2,})+\b)
|
||||
|
||||
# crypt
|
||||
"\$2[ayb]\$.{56}"
|
||||
|
||||
# scrypt / argon
|
||||
\$(?:scrypt|argon\d+[di]*)\$\S+
|
||||
|
||||
# Input to GitHub JSON
|
||||
content: "[-a-zA-Z=;:/0-9+]*="
|
||||
|
||||
# Python stringprefix / binaryprefix
|
||||
# Note that there's a high false positive rate, remove the `?=` and search for the regex to see if the matches seem like reasonable strings
|
||||
(?<!')\b(?:B|BR|Br|F|FR|Fr|R|RB|RF|Rb|Rf|U|UR|Ur|b|bR|br|f|fR|fr|r|rB|rF|rb|rf|u|uR|ur)'(?:[A-Z]{3,}|[A-Z][a-z]{2,}|[a-z]{3,})
|
||||
|
||||
# Regular expressions for (P|p)assword
|
||||
\([A-Z]\|[a-z]\)[a-z]+
|
||||
|
||||
# JavaScript regular expressions
|
||||
# javascript test regex
|
||||
/.*/[gim]*\.test\(
|
||||
# javascript match regex
|
||||
\.match\(/[^/\s"]*/[gim]*\s*
|
||||
# javascript match regex
|
||||
\.match\(/\\[b].*?/[gim]*\s*\)(?:;|$)
|
||||
# javascript regex
|
||||
^\s*/\\[b].*/[gim]*\s*(?:\)(?:;|$)|,$)
|
||||
# javascript replace regex
|
||||
\.replace\(/[^/\s"]*/[gim]*\s*,
|
||||
|
||||
# Go regular expressions
|
||||
regexp?\.MustCompile\(`[^`]*`\)
|
||||
|
||||
# sed regular expressions
|
||||
sed 's/(?:[^/]*?[a-zA-Z]{3,}[^/]*?/){2}
|
||||
|
||||
# go install
|
||||
go install(?:\s+[a-z]+\.[-@\w/.]+)+
|
||||
|
||||
# kubernetes pod status lists
|
||||
# https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#pod-phase
|
||||
\w+(?:-\w+)+\s+\d+/\d+\s+(?:Running|Pending|Succeeded|Failed|Unknown)\s+
|
||||
|
||||
# kubectl - pods in CrashLoopBackOff
|
||||
\w+-[0-9a-f]+-\w+\s+\d+/\d+\s+CrashLoopBackOff\s+
|
||||
|
||||
# kubernetes object suffix
|
||||
-[0-9a-f]{10}-\w{5}\s
|
||||
|
||||
# posthog secrets
|
||||
posthog\.init\((['"])phc_[^"',]+\g{-1},
|
||||
|
||||
# xcode
|
||||
|
||||
# xcodeproject scenes
|
||||
(?:Controller|ID|id)="\w{3}-\w{2}-\w{3}"
|
||||
|
||||
# xcode api botches
|
||||
customObjectInstantitationMethod
|
||||
|
||||
# font awesome classes
|
||||
\.fa-[-a-z0-9]+
|
||||
|
||||
# Update Lorem based on your content (requires `ge` and `w` from https://github.com/jsoref/spelling; and `review` from https://github.com/check-spelling/check-spelling/wiki/Looking-for-items-locally )
|
||||
# grep '^[^#].*lorem' .github/actions/spelling/patterns.txt|perl -pne 's/.*i..\?://;s/\).*//' |tr '|' "\n"|sort -f |xargs -n1 ge|perl -pne 's/^[^:]*://'|sort -u|w|sed -e 's/ .*//'|w|review -
|
||||
# Warning, while `(?i)` is very neat and fancy, if you have some binary files that aren't proper unicode, you might run into:
|
||||
## Operation "substitution (s///)" returns its argument for non-Unicode code point 0x1C19AE (the code point will vary).
|
||||
## You could manually change `(?i)X...` to use `[Xx]...`
|
||||
## or you could add the files to your `excludes` file (a version after 0.0.19 should identify the file path)
|
||||
# Lorem
|
||||
(?:\w|\s|[,.])*\b(?i)(?:amet|consectetur|cursus|dolor|eros|ipsum|lacus|libero|ligula|lorem|magna|neque|nulla|suscipit|tempus)\b(?:\w|\s|[,.])*
|
||||
|
||||
# Non-English
|
||||
[a-zA-Z]*[ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýÿĀāŁłŃńŅņŒœŚśŠšŜŝŸŽžź][a-zA-Z]{3}[a-zA-ZÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýÿĀāŁłŃńŅņŒœŚśŠšŜŝŸŽžź]*
|
||||
|
||||
# French
|
||||
# This corpus only had capital letters, but you probably want lowercase ones as well.
|
||||
\b[LN]'+[a-z]{2,}\b
|
||||
|
||||
# latex
|
||||
\\(?:n(?:ew|ormal|osub)|r(?:enew)|t(?:able(?:of|)|he|itle))(?=[a-z]+)
|
||||
|
||||
# the negative lookahead here is to allow catching 'templatesz' as a misspelling
|
||||
# but to otherwise recognize a Windows path with \templates\foo.template or similar:
|
||||
\\(?:necessary|r(?:eport|esolve[dr]?|esult)|t(?:arget|emplates?))(?![a-z])
|
||||
# ignore long runs of a single character:
|
||||
\b([A-Za-z])\g{-1}{3,}\b
|
||||
# Note that the next example is no longer necessary if you are using
|
||||
# to match a string starting with a `#`, use a character-class:
|
||||
[#]backwards
|
||||
# version suffix <word>v#
|
||||
(?:(?<=[A-Z]{2})V|(?<=[a-z]{2}|[A-Z]{2})v)\d+(?:\b|(?=[a-zA-Z_]))
|
||||
# Compiler flags (Scala)
|
||||
(?:^|[\t ,>"'`=(])-J-[DPWXY](?=[A-Z]{2,}|[A-Z][a-z]|[a-z]{2,})
|
||||
# Compiler flags
|
||||
#(?:^|[\t ,"'`=(])-[DPWXYLlf](?=[A-Z]{2,}|[A-Z][a-z]|[a-z]{2,})
|
||||
|
||||
# Compiler flags (linker)
|
||||
,-B
|
||||
# curl arguments
|
||||
\b(?:\\n|)curl(?:\s+-[a-zA-Z]{1,2}\b)*(?:\s+-[a-zA-Z]{3,})(?:\s+-[a-zA-Z]+)*
|
||||
# set arguments
|
||||
\bset(?:\s+-[abefimouxE]{1,2})*\s+-[abefimouxE]{3,}(?:\s+-[abefimouxE]+)*
|
||||
# tar arguments
|
||||
\b(?:\\n|)g?tar(?:\.exe|)(?:(?:\s+--[-a-zA-Z]+|\s+-[a-zA-Z]+|\s[ABGJMOPRSUWZacdfh-pr-xz]+\b)(?:=[^ ]*|))+
|
||||
# tput arguments -- https://man7.org/linux/man-pages/man5/terminfo.5.html -- technically they can be more than 5 chars long...
|
||||
\btput\s+(?:(?:-[SV]|-T\s*\w+)\s+)*\w{3,5}\b
|
||||
# macOS temp folders
|
||||
/var/folders/\w\w/[+\w]+/(?:T|-Caches-)/
|
||||
48
.github/actions/spelling/excludes.txt
vendored
48
.github/actions/spelling/excludes.txt
vendored
@@ -1,28 +1,39 @@
|
||||
# See https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples:-excludes
|
||||
(?:(?i)\.png$)
|
||||
(?:^|/)(?i)COPYRIGHT
|
||||
(?:^|/)(?i)LICEN[CS]E
|
||||
(?:^|/)3rdparty/
|
||||
(?:^|/)dirs$
|
||||
(?:^|/)go\.mod$
|
||||
(?:^|/)go\.sum$
|
||||
(?:^|/)package-lock\.json$
|
||||
(?:^|/)package(?:-lock|)\.json$
|
||||
(?:^|/)sources(?:|\.dep)$
|
||||
SUMS$
|
||||
(?:^|/)vendor/
|
||||
\.a$
|
||||
\.ai$
|
||||
\.avi$
|
||||
\.bmp$
|
||||
\.bz2$
|
||||
\.cer$
|
||||
\.class$
|
||||
\.crl$
|
||||
\.crt$
|
||||
\.csr$
|
||||
\.dll$
|
||||
\.docx?$
|
||||
\.drawio$
|
||||
\.DS_Store$
|
||||
\.eot$
|
||||
\.eps$
|
||||
\.exe$
|
||||
\.gif$
|
||||
\.gitattributes$
|
||||
\.graffle$
|
||||
\.gz$
|
||||
\.icns$
|
||||
\.ico$
|
||||
\.jar$
|
||||
\.jks$
|
||||
\.jpeg$
|
||||
\.jpg$
|
||||
\.key$
|
||||
@@ -30,28 +41,53 @@ SUMS$
|
||||
\.lock$
|
||||
\.map$
|
||||
\.min\..
|
||||
\.mod$
|
||||
\.mp3$
|
||||
\.mp4$
|
||||
\.o$
|
||||
\.ocf$
|
||||
\.otf$
|
||||
\.pbxproj$
|
||||
\.pdf$
|
||||
\.pem$
|
||||
\.png$
|
||||
\.psd$
|
||||
\.pyc$
|
||||
\.runsettings$
|
||||
\.s$
|
||||
\.sig$
|
||||
\.so$
|
||||
\.svg$
|
||||
\.svgz$
|
||||
\.svgz?$
|
||||
\.tar$
|
||||
\.tgz$
|
||||
\.tiff?$
|
||||
\.ttf$
|
||||
\.vsdx$
|
||||
\.wav$
|
||||
\.webm$
|
||||
\.webp$
|
||||
\.woff
|
||||
\.woff2?$
|
||||
\.xcf$
|
||||
\.xls
|
||||
\.xlsx?$
|
||||
\.xpm$
|
||||
\.yml$
|
||||
\.zip$
|
||||
^\.github/actions/spelling/
|
||||
^\.github/fabricbot.json$
|
||||
^\.gitignore$
|
||||
^\Q.git-blame-ignore-revs\E$
|
||||
^\Q.github/workflows/spelling.yml\E$
|
||||
^\Qdoc/reference/windows-terminal-logo.ans\E$
|
||||
^\Qsamples/ConPTY/EchoCon/EchoCon/EchoCon.vcxproj.filters\E$
|
||||
^\Qsrc/host/exe/Host.EXE.vcxproj.filters\E$
|
||||
^\Qsrc/host/ft_host/chafa.txt\E$
|
||||
^\Qsrc/tools/closetest/CloseTest.vcxproj.filters\E$
|
||||
^\XamlStyler.json$
|
||||
^build/config/
|
||||
^consolegit2gitfilters\.json$
|
||||
^dep/
|
||||
^doc/reference/master-sequence-list.csv$
|
||||
@@ -61,12 +97,14 @@ SUMS$
|
||||
^src/host/runft\.bat$
|
||||
^src/host/runut\.bat$
|
||||
^src/interactivity/onecore/BgfxEngine\.
|
||||
^src/renderer/atlas/
|
||||
^src/renderer/wddmcon/WddmConRenderer\.
|
||||
^src/terminal/adapter/ut_adapter/run\.bat$
|
||||
^src/terminal/parser/delfuzzpayload\.bat$
|
||||
^src/terminal/parser/ft_fuzzer/run\.bat$
|
||||
^src/terminal/parser/ft_fuzzer/VTCommandFuzzer\.cpp$
|
||||
^src/terminal/parser/ft_fuzzwrapper/run\.bat$
|
||||
^src/terminal/parser/ut_parser/Base64Test.cpp$
|
||||
^src/terminal/parser/ut_parser/run\.bat$
|
||||
^src/tools/integrity/packageuwp/ConsoleUWP\.appxSources$
|
||||
^src/tools/lnkd/lnkd\.bat$
|
||||
@@ -74,6 +112,6 @@ SUMS$
|
||||
^src/tools/texttests/fira\.txt$
|
||||
^src/tools/U8U16Test/(?:fr|ru|zh)\.txt$
|
||||
^src/types/ut_types/UtilsTests.cpp$
|
||||
^\.github/actions/spelling/
|
||||
^\.gitignore$
|
||||
^\XamlStyler.json$
|
||||
^tools/ReleaseEngineering/ServicingPipeline.ps1$
|
||||
ignore$
|
||||
SUMS$
|
||||
|
||||
8
.github/actions/spelling/expect/alphabet.txt
vendored
8
.github/actions/spelling/expect/alphabet.txt
vendored
@@ -5,26 +5,19 @@ AAAAAABBBBBBCCC
|
||||
AAAAABBBBBBCCC
|
||||
abcd
|
||||
abcd
|
||||
abcde
|
||||
abcdef
|
||||
ABCDEFG
|
||||
ABCDEFGH
|
||||
ABCDEFGHIJ
|
||||
abcdefghijk
|
||||
ABCDEFGHIJKLMNO
|
||||
abcdefghijklmnop
|
||||
ABCDEFGHIJKLMNOPQRST
|
||||
abcdefghijklmnopqrstuvwxyz
|
||||
ABCG
|
||||
ABE
|
||||
abf
|
||||
BBBBB
|
||||
BBBBBBBB
|
||||
BBBBBBBBBBBBBBDDDD
|
||||
BBBBBCCC
|
||||
BBBBCCCCC
|
||||
BBGGRR
|
||||
CCE
|
||||
EFG
|
||||
EFGh
|
||||
QQQQQQQQQQABCDEFGHIJ
|
||||
@@ -33,7 +26,6 @@ QQQQQQQQQQABCDEFGHIJKLMNOPQRSTQQQQQQQQQQ
|
||||
QQQQQQQQQQABCDEFGHIJPQRSTQQQQQQQQQQ
|
||||
qrstuvwxyz
|
||||
qwerty
|
||||
QWERTYUIOP
|
||||
qwertyuiopasdfg
|
||||
YYYYYYYDDDDDDDDDDD
|
||||
ZAAZZ
|
||||
|
||||
948
.github/actions/spelling/expect/expect.txt
vendored
948
.github/actions/spelling/expect/expect.txt
vendored
File diff suppressed because it is too large
Load Diff
12
.github/actions/spelling/expect/web.txt
vendored
12
.github/actions/spelling/expect/web.txt
vendored
@@ -1,16 +1,6 @@
|
||||
http
|
||||
www
|
||||
ecma
|
||||
rapidtables
|
||||
WCAG
|
||||
freedesktop
|
||||
ycombinator
|
||||
robertelder
|
||||
kovidgoyal
|
||||
leonerd
|
||||
fixterms
|
||||
winui
|
||||
appshellintegration
|
||||
cppreference
|
||||
mdtauk
|
||||
gfycat
|
||||
Guake
|
||||
|
||||
62
.github/actions/spelling/line_forbidden.patterns
vendored
Normal file
62
.github/actions/spelling/line_forbidden.patterns
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
# reject `m_data` as there's a certain OS which has evil defines that break things if it's used elsewhere
|
||||
# \bm_data\b
|
||||
|
||||
# If you have a framework that uses `it()` for testing and `fit()` for debugging a specific test,
|
||||
# you might not want to check in code where you were debugging w/ `fit()`, in which case, you might want
|
||||
# to use this:
|
||||
#\bfit\(
|
||||
|
||||
# s.b. GitHub
|
||||
\bGithub\b
|
||||
|
||||
# s.b. GitLab
|
||||
\bGitlab\b
|
||||
|
||||
# s.b. JavaScript
|
||||
\bJavascript\b
|
||||
|
||||
# s.b. Microsoft
|
||||
\bMicroSoft\b
|
||||
|
||||
# s.b. another
|
||||
\ban[- ]other\b
|
||||
|
||||
# s.b. greater than
|
||||
\bgreater then\b
|
||||
|
||||
# s.b. into
|
||||
#\sin to\s
|
||||
|
||||
# s.b. opt-in
|
||||
\sopt in\s
|
||||
|
||||
# s.b. less than
|
||||
\bless then\b
|
||||
|
||||
# s.b. otherwise
|
||||
\bother[- ]wise\b
|
||||
|
||||
# s.b. nonexistent
|
||||
\bnon existing\b
|
||||
\b[Nn]o[nt][- ]existent\b
|
||||
|
||||
# s.b. preexisting
|
||||
[Pp]re[- ]existing
|
||||
|
||||
# s.b. preempt
|
||||
[Pp]re[- ]empt\b
|
||||
|
||||
# s.b. preemptively
|
||||
[Pp]re[- ]emptively
|
||||
|
||||
# s.b. reentrancy
|
||||
[Rr]e[- ]entrancy
|
||||
|
||||
# s.b. reentrant
|
||||
[Rr]e[- ]entrant
|
||||
|
||||
# s.b. workaround(s)
|
||||
#\bwork[- ]arounds?\b
|
||||
|
||||
# Reject duplicate words
|
||||
\s([A-Z]{3,}|[A-Z][a-z]{2,}|[a-z]{3,})\s\g{-1}\s
|
||||
86
.github/actions/spelling/patterns/patterns.txt
vendored
86
.github/actions/spelling/patterns/patterns.txt
vendored
@@ -1,11 +1,6 @@
|
||||
https://(?:(?:[-a-zA-Z0-9?&=]*\.|)microsoft\.com)/[-a-zA-Z0-9?&=_#\/.]*
|
||||
https://aka\.ms/[-a-zA-Z0-9?&=\/_]*
|
||||
https://www\.itscj\.ipsj\.or\.jp/iso-ir/[-0-9]+\.pdf
|
||||
https://www\.vt100\.net/docs/[-a-zA-Z0-9#_\/.]*
|
||||
https://www.w3.org/[-a-zA-Z0-9?&=\/_#]*
|
||||
https://(?:(?:www\.|)youtube\.com|youtu.be)/[-a-zA-Z0-9?&=]*
|
||||
https://(?:[a-z-]+\.|)github(?:usercontent|)\.com/[-a-zA-Z0-9?%&=_\/.]*
|
||||
https://www.xfree86.org/[-a-zA-Z0-9?&=\/_#]*
|
||||
# See https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples:-patterns
|
||||
|
||||
https?://\S+
|
||||
[Pp]ublicKeyToken="?[0-9a-fA-F]{16}"?
|
||||
(?:[{"]|UniqueIdentifier>)[0-9a-fA-F]{8}-(?:[0-9a-fA-F]{4}-){3}[0-9a-fA-F]{12}(?:[}"]|</UniqueIdentifier)
|
||||
(?:0[Xx]|\\x|U\+|#)[a-f0-9A-FGgRr]{2,}[Uu]?[Ll]{0,2}\b
|
||||
@@ -24,3 +19,78 @@ VERIFY_ARE_EQUAL\(L"[^"]+"
|
||||
std::memory_order_[\w]+
|
||||
D2DERR_SHADER_COMPILE_FAILED
|
||||
TIL_FEATURE_[0-9A-Z_]+
|
||||
vcvars\w*
|
||||
ROY\sG\.\sBIV
|
||||
!(?:(?i)ESC)!\[
|
||||
!(?:(?i)CSI)!(?:\d+(?:;\d+|)m|[ABCDF])
|
||||
|
||||
# Python stringprefix / binaryprefix
|
||||
\b(?:B|BR|Br|F|FR|Fr|R|RB|RF|Rb|Rf|U|UR|Ur|b|bR|br|f|fR|fr|r|rB|rF|rb|rf|u|uR|ur)'
|
||||
|
||||
# Automatically suggested patterns
|
||||
# hit-count: 3831 file-count: 582
|
||||
# IServiceProvider
|
||||
\bI(?=(?:[A-Z][a-z]{2,})+\b)
|
||||
|
||||
# hit-count: 71 file-count: 35
|
||||
# Compiler flags
|
||||
(?:^|[\t ,"'`=(])-[D](?=[A-Z]{2,}|[A-Z][a-z])
|
||||
(?:^|[\t ,"'`=(])-[X](?=[A-Z]{2,}|[A-Z][a-z]|[a-z]{2,})
|
||||
|
||||
# hit-count: 41 file-count: 28
|
||||
# version suffix <word>v#
|
||||
(?:(?<=[A-Z]{2})V|(?<=[a-z]{2}|[A-Z]{2})v)\d+(?:\b|(?=[a-zA-Z_]))
|
||||
|
||||
# hit-count: 20 file-count: 9
|
||||
# hex runs
|
||||
\b[0-9a-fA-F]{16,}\b
|
||||
|
||||
# hit-count: 10 file-count: 7
|
||||
# uuid:
|
||||
\b[0-9a-fA-F]{8}-(?:[0-9a-fA-F]{4}-){3}[0-9a-fA-F]{12}\b
|
||||
|
||||
# hit-count: 4 file-count: 4
|
||||
# mailto urls
|
||||
mailto:[-a-zA-Z=;:/?%&0-9+@.]{3,}
|
||||
|
||||
# hit-count: 4 file-count: 1
|
||||
# ANSI color codes
|
||||
(?:\\(?:u00|x)1b|\x1b)\[\d+(?:;\d+|)m
|
||||
|
||||
# hit-count: 2 file-count: 1
|
||||
# latex
|
||||
\\(?:n(?:ew|ormal|osub)|r(?:enew)|t(?:able(?:of|)|he|itle))(?=[a-z]+)
|
||||
|
||||
# hit-count: 1 file-count: 1
|
||||
# hex digits including css/html color classes:
|
||||
(?:[\\0][xX]|\\u|[uU]\+|#x?|\%23)[0-9_a-fA-FgGrR]*?[a-fA-FgGrR]{2,}[0-9_a-fA-FgGrR]*(?:[uUlL]{0,3}|u\d+)\b
|
||||
|
||||
# hit-count: 1 file-count: 1
|
||||
# Non-English
|
||||
[a-zA-Z]*[ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýÿĀāŁłŃńŅņŒœŚśŠšŜŝŸŽžź][a-zA-Z]{3}[a-zA-ZÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýÿĀāŁłŃńŅņŒœŚśŠšŜŝŸŽžź]*
|
||||
|
||||
# hit-count: 1 file-count: 1
|
||||
# French
|
||||
# This corpus only had capital letters, but you probably want lowercase ones as well.
|
||||
\b[LN]'+[a-z]{2,}\b
|
||||
|
||||
# acceptable duplicates
|
||||
# ls directory listings
|
||||
[-bcdlpsw](?:[-r][-w][-sx]){3}\s+\d+\s+(\S+)\s+\g{-1}\s+\d+\s+
|
||||
# C/idl types + English ...
|
||||
\s(Guid|long|LONG|that) \g{-1}\s
|
||||
|
||||
# javadoc / .net
|
||||
(?:[\\@](?:groupname|param)|(?:public|private)(?:\s+static|\s+readonly)*)\s+(\w+)\s+\g{-1}\s
|
||||
|
||||
# Commit message -- Signed-off-by and friends
|
||||
^\s*(?:(?:Based-on-patch|Co-authored|Helped|Mentored|Reported|Reviewed|Signed-off)-by|Thanks-to): (?:[^<]*<[^>]*>|[^<]*)\s*$
|
||||
|
||||
# Autogenerated revert commit message
|
||||
^This reverts commit [0-9a-f]{40}\.$
|
||||
|
||||
# vtmode
|
||||
--vtmode\s+(\w+)\s+\g{-1}\s
|
||||
|
||||
# ignore long runs of a single character:
|
||||
\b([A-Za-z])\g{-1}{3,}\b
|
||||
|
||||
28
.github/actions/spelling/reject.txt
vendored
28
.github/actions/spelling/reject.txt
vendored
@@ -1,22 +1,12 @@
|
||||
^attache$
|
||||
^attacher$
|
||||
^attachers$
|
||||
^spae$
|
||||
^spaebook$
|
||||
^spaecraft$
|
||||
^spaed$
|
||||
^spaedom$
|
||||
^spaeing$
|
||||
^spaeings$
|
||||
^spae-man$
|
||||
^spaeman$
|
||||
^spaer$
|
||||
^Spaerobee$
|
||||
^spaes$
|
||||
^spaewife$
|
||||
^spaewoman$
|
||||
^spaework$
|
||||
^spaewright$
|
||||
^wether$
|
||||
^wethers$
|
||||
^wetherteg$
|
||||
benefitting
|
||||
occurences?
|
||||
^dependan.*
|
||||
^oer$
|
||||
Sorce
|
||||
^[Ss]pae.*
|
||||
^untill$
|
||||
^untilling$
|
||||
^wether.*
|
||||
|
||||
19
.github/workflows/spelling.yml
vendored
19
.github/workflows/spelling.yml
vendored
@@ -1,19 +0,0 @@
|
||||
name: Spell checking
|
||||
on:
|
||||
pull_request_target:
|
||||
push:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Spell checking
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: checkout-merge
|
||||
if: "contains(github.event_name, 'pull_request')"
|
||||
uses: actions/checkout@v2.0.0
|
||||
with:
|
||||
ref: refs/pull/${{github.event.pull_request.number}}/merge
|
||||
- name: checkout
|
||||
if: "!contains(github.event_name, 'pull_request')"
|
||||
uses: actions/checkout@v2.0.0
|
||||
- uses: check-spelling/check-spelling@v0.0.18
|
||||
134
.github/workflows/spelling2.yml
vendored
Normal file
134
.github/workflows/spelling2.yml
vendored
Normal file
@@ -0,0 +1,134 @@
|
||||
# spelling.yml is blocked per https://github.com/check-spelling/check-spelling/security/advisories/GHSA-g86g-chm8-7r2p
|
||||
name: Spell checking
|
||||
|
||||
# Comment management is handled through a secondary job, for details see:
|
||||
# https://github.com/check-spelling/check-spelling/wiki/Feature%3A-Restricted-Permissions
|
||||
#
|
||||
# `jobs.comment-push` runs when a push is made to a repository and the `jobs.spelling` job needs to make a comment
|
||||
# (in odd cases, it might actually run just to collapse a commment, but that's fairly rare)
|
||||
# it needs `contents: write` in order to add a comment.
|
||||
#
|
||||
# `jobs.comment-pr` runs when a pull_request is made to a repository and the `jobs.spelling` job needs to make a comment
|
||||
# or collapse a comment (in the case where it had previously made a comment and now no longer needs to show a comment)
|
||||
# it needs `pull-requests: write` in order to manipulate those comments.
|
||||
|
||||
# Updating pull request branches is managed via comment handling.
|
||||
# For details, see: https://github.com/check-spelling/check-spelling/wiki/Feature:-Update-expect-list
|
||||
#
|
||||
# These elements work together to make it happen:
|
||||
#
|
||||
# `on.issue_comment`
|
||||
# This event listens to comments by users asking to update the metadata.
|
||||
#
|
||||
# `jobs.update`
|
||||
# This job runs in response to an issue_comment and will push a new commit
|
||||
# to update the spelling metadata.
|
||||
#
|
||||
# `with.experimental_apply_changes_via_bot`
|
||||
# Tells the action to support and generate messages that enable it
|
||||
# to make a commit to update the spelling metadata.
|
||||
#
|
||||
# `with.ssh_key`
|
||||
# In order to trigger workflows when the commit is made, you can provide a
|
||||
# secret (typically, a write-enabled github deploy key).
|
||||
#
|
||||
# For background, see: https://github.com/check-spelling/check-spelling/wiki/Feature:-Update-with-deploy-key
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- "**"
|
||||
tags-ignore:
|
||||
- "**"
|
||||
pull_request_target:
|
||||
branches:
|
||||
- "**"
|
||||
tags-ignore:
|
||||
- "**"
|
||||
types:
|
||||
- 'opened'
|
||||
- 'reopened'
|
||||
- 'synchronize'
|
||||
issue_comment:
|
||||
types:
|
||||
- 'created'
|
||||
|
||||
jobs:
|
||||
spelling:
|
||||
name: Spell checking
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: read
|
||||
actions: read
|
||||
outputs:
|
||||
followup: ${{ steps.spelling.outputs.followup }}
|
||||
runs-on: ubuntu-latest
|
||||
if: "contains(github.event_name, 'pull_request') || github.event_name == 'push'"
|
||||
concurrency:
|
||||
group: spelling-${{ github.event.pull_request.number || github.ref }}
|
||||
# note: If you use only_check_changed_files, you do not want cancel-in-progress
|
||||
cancel-in-progress: true
|
||||
steps:
|
||||
- name: check-spelling
|
||||
id: spelling
|
||||
uses: check-spelling/check-spelling@v0.0.21
|
||||
with:
|
||||
suppress_push_for_open_pull_request: 1
|
||||
checkout: true
|
||||
check_file_names: 1
|
||||
spell_check_this: check-spelling/spell-check-this@prerelease
|
||||
post_comment: 0
|
||||
use_magic_file: 1
|
||||
extra_dictionary_limit: 10
|
||||
extra_dictionaries:
|
||||
cspell:software-terms/src/software-terms.txt
|
||||
cspell:python/src/python/python-lib.txt
|
||||
cspell:node/node.txt
|
||||
cspell:cpp/src/stdlib-c.txt
|
||||
cspell:cpp/src/stdlib-cpp.txt
|
||||
cspell:fullstack/fullstack.txt
|
||||
cspell:filetypes/filetypes.txt
|
||||
cspell:html/html.txt
|
||||
cspell:cpp/src/compiler-msvc.txt
|
||||
cspell:python/src/common/extra.txt
|
||||
cspell:powershell/powershell.txt
|
||||
cspell:aws/aws.txt
|
||||
cspell:cpp/src/lang-keywords.txt
|
||||
cspell:npm/npm.txt
|
||||
cspell:dotnet/dotnet.txt
|
||||
cspell:python/src/python/python.txt
|
||||
cspell:css/css.txt
|
||||
cspell:cpp/src/stdlib-cmath.txt
|
||||
check_extra_dictionaries: ''
|
||||
|
||||
comment-push:
|
||||
name: Report (Push)
|
||||
# If your workflow isn't running on push, you can remove this job
|
||||
runs-on: ubuntu-latest
|
||||
needs: spelling
|
||||
permissions:
|
||||
contents: write
|
||||
if: (success() || failure()) && needs.spelling.outputs.followup && github.event_name == 'push'
|
||||
steps:
|
||||
- name: comment
|
||||
uses: check-spelling/check-spelling@v0.0.21
|
||||
with:
|
||||
checkout: true
|
||||
spell_check_this: check-spelling/spell-check-this@prerelease
|
||||
task: ${{ needs.spelling.outputs.followup }}
|
||||
|
||||
comment-pr:
|
||||
name: Report (PR)
|
||||
# If you workflow isn't running on pull_request*, you can remove this job
|
||||
runs-on: ubuntu-latest
|
||||
needs: spelling
|
||||
permissions:
|
||||
pull-requests: write
|
||||
if: (success() || failure()) && needs.spelling.outputs.followup && contains(github.event_name, 'pull_request')
|
||||
steps:
|
||||
- name: comment
|
||||
uses: check-spelling/check-spelling@v0.0.21
|
||||
with:
|
||||
checkout: true
|
||||
spell_check_this: check-spelling/spell-check-this@prerelease
|
||||
task: ${{ needs.spelling.outputs.followup }}
|
||||
@@ -73,6 +73,7 @@ EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Host.unittest", "src\host\ut_lib\host.unittest.vcxproj", "{06EC74CB-9A12-429C-B551-8562EC954747}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{18D09A24-8240-42D6-8CB6-236EEE820263} = {18D09A24-8240-42D6-8CB6-236EEE820263}
|
||||
{71CC9D78-BA29-4D93-946F-BEF5D9A3A6EF} = {71CC9D78-BA29-4D93-946F-BEF5D9A3A6EF}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Host.Tests.Unit", "src\host\ut_host\Host.UnitTests.vcxproj", "{531C23E7-4B76-4C08-8AAD-04164CB628C9}"
|
||||
@@ -397,6 +398,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "UnitTests_Control", "src\ca
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WindowsTerminal.UIA.Tests", "src\cascadia\WindowsTerminal_UIATests\WindowsTerminal.UIA.Tests.csproj", "{F19DACD5-0C6E-40DC-B6E4-767A3200542C}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "api-ms-win-core-synch-l1-2-0", "src\api-ms-win-core-synch-l1-2-0\api-ms-win-core-synch-l1-2-0.vcxproj", "{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
AuditMode|Any CPU = AuditMode|Any CPU
|
||||
@@ -3292,6 +3295,50 @@ Global
|
||||
{F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Release|x64.Build.0 = Release|x64
|
||||
{F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Release|x86.ActiveCfg = Release|Win32
|
||||
{F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Release|x86.Build.0 = Release|Win32
|
||||
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.AuditMode|Any CPU.ActiveCfg = AuditMode|Win32
|
||||
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.AuditMode|ARM.ActiveCfg = AuditMode|Win32
|
||||
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.AuditMode|ARM64.ActiveCfg = AuditMode|ARM64
|
||||
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.AuditMode|ARM64.Build.0 = AuditMode|ARM64
|
||||
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.AuditMode|DotNet_x64Test.ActiveCfg = AuditMode|Win32
|
||||
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.AuditMode|DotNet_x86Test.ActiveCfg = AuditMode|Win32
|
||||
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.AuditMode|x64.ActiveCfg = AuditMode|x64
|
||||
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.AuditMode|x64.Build.0 = AuditMode|x64
|
||||
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.AuditMode|x86.ActiveCfg = AuditMode|Win32
|
||||
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.AuditMode|x86.Build.0 = AuditMode|Win32
|
||||
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Debug|ARM.ActiveCfg = Debug|Win32
|
||||
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Debug|DotNet_x64Test.ActiveCfg = Debug|x64
|
||||
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Debug|DotNet_x64Test.Build.0 = Debug|x64
|
||||
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Debug|DotNet_x86Test.ActiveCfg = Debug|Win32
|
||||
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Debug|DotNet_x86Test.Build.0 = Debug|Win32
|
||||
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Debug|x64.Build.0 = Debug|x64
|
||||
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Debug|x86.Build.0 = Debug|Win32
|
||||
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Fuzzing|Any CPU.ActiveCfg = Fuzzing|Win32
|
||||
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Fuzzing|ARM.ActiveCfg = Fuzzing|Win32
|
||||
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64
|
||||
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Fuzzing|ARM64.Build.0 = Fuzzing|ARM64
|
||||
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Fuzzing|DotNet_x64Test.ActiveCfg = Fuzzing|Win32
|
||||
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Fuzzing|DotNet_x86Test.ActiveCfg = Fuzzing|Win32
|
||||
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Fuzzing|x64.ActiveCfg = Fuzzing|x64
|
||||
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Fuzzing|x64.Build.0 = Fuzzing|x64
|
||||
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32
|
||||
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Fuzzing|x86.Build.0 = Fuzzing|Win32
|
||||
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Release|ARM.ActiveCfg = Release|Win32
|
||||
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Release|DotNet_x64Test.ActiveCfg = Release|x64
|
||||
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Release|DotNet_x64Test.Build.0 = Release|x64
|
||||
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Release|DotNet_x86Test.ActiveCfg = Release|Win32
|
||||
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Release|DotNet_x86Test.Build.0 = Release|Win32
|
||||
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Release|x64.ActiveCfg = Release|x64
|
||||
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Release|x64.Build.0 = Release|x64
|
||||
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Release|x86.ActiveCfg = Release|Win32
|
||||
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Release|x86.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
@@ -3390,6 +3437,7 @@ Global
|
||||
{05D9052F-D78F-478F-968A-2DE38A6DB996} = {E8F24881-5E37-4362-B191-A3BA0ED7F4EB}
|
||||
{C323DAEE-B307-4C7B-ACE5-7293CBEFCB5B} = {BDB237B6-1D1D-400F-84CC-40A58FA59C8E}
|
||||
{F19DACD5-0C6E-40DC-B6E4-767A3200542C} = {BDB237B6-1D1D-400F-84CC-40A58FA59C8E}
|
||||
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5} = {89CDCC5C-9F53-4054-97A4-639D99F169CD}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {3140B1B7-C8EE-43D1-A772-D82A7061A271}
|
||||
|
||||
@@ -9,7 +9,7 @@ $payloadDir = "HelixPayload\$Configuration\$Platform"
|
||||
|
||||
$repoDirectory = Join-Path (Split-Path -Parent $script:MyInvocation.MyCommand.Path) "..\..\"
|
||||
$nugetPackagesDir = Join-Path (Split-Path -Parent $script:MyInvocation.MyCommand.Path) "packages"
|
||||
|
||||
|
||||
# Create the payload directory. Remove it if it already exists.
|
||||
If(test-path $payloadDir)
|
||||
{
|
||||
@@ -19,8 +19,8 @@ New-Item -ItemType Directory -Force -Path $payloadDir
|
||||
|
||||
# Copy files from nuget packages
|
||||
Copy-Item "$nugetPackagesDir\microsoft.windows.apps.test.1.0.181203002\lib\netcoreapp2.1\*.dll" $payloadDir
|
||||
Copy-Item "$nugetPackagesDir\Microsoft.Taef.10.58.210305002\build\Binaries\$Platform\*" $payloadDir
|
||||
Copy-Item "$nugetPackagesDir\Microsoft.Taef.10.58.210305002\build\Binaries\$Platform\NetFx4.5\*" $payloadDir
|
||||
Copy-Item "$nugetPackagesDir\Microsoft.Taef.10.60.210621002\build\Binaries\$Platform\*" $payloadDir
|
||||
Copy-Item "$nugetPackagesDir\Microsoft.Taef.10.60.210621002\build\Binaries\$Platform\NetFx4.5\*" $payloadDir
|
||||
New-Item -ItemType Directory -Force -Path "$payloadDir\.NETCoreApp2.1\"
|
||||
Copy-Item "$nugetPackagesDir\runtime.win-$Platform.microsoft.netcore.app.2.1.0\runtimes\win-$Platform\lib\netcoreapp2.1\*" "$payloadDir\.NETCoreApp2.1\"
|
||||
Copy-Item "$nugetPackagesDir\runtime.win-$Platform.microsoft.netcore.app.2.1.0\runtimes\win-$Platform\native\*" "$payloadDir\.NETCoreApp2.1\"
|
||||
@@ -59,7 +59,7 @@ Copy-Item "build\Helix\EnsureMachineState.ps1" "$payloadDir"
|
||||
Copy-Item "$repoDirectory\Artifacts\$ArtifactName\appx\CascadiaPackage_0.0.1.0_$Platform.msix" $payloadDir\CascadiaPackage.zip
|
||||
|
||||
# Rename it to extension of ZIP because Expand-Archive is real sassy on the build machines
|
||||
# and refuses to unzip it because of its file extension while on a desktop, it just
|
||||
# and refuses to unzip it because of its file extension while on a desktop, it just
|
||||
# does the job without complaining.
|
||||
|
||||
# Extract the APPX package
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<packages>
|
||||
<package id="MUXCustomBuildTasks" version="1.0.48" targetFramework="native" />
|
||||
<package id="Microsoft.Internal.Windows.Terminal.TestContent" version="1.0.1" />
|
||||
<package id="Microsoft.Taef" version="10.58.210305002" targetFramework="native" />
|
||||
<package id="Microsoft.Taef" version="10.60.210621002" targetFramework="native" />
|
||||
<package id="microsoft.windows.apps.test" version="1.0.181203002" targetFramework="native" />
|
||||
<package id="runtime.win-x86.microsoft.netcore.app" version="2.1.0" targetFramework="native" />
|
||||
<package id="runtime.win-x64.microsoft.netcore.app" version="2.1.0" targetFramework="native" />
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="MUXCustomBuildTasks" version="1.0.48" targetFramework="native" />
|
||||
<package id="Microsoft.Taef" version="10.58.210305002" targetFramework="native" />
|
||||
<package id="Microsoft.Taef" version="10.60.210621002" targetFramework="native" />
|
||||
</packages>
|
||||
|
||||
@@ -1,48 +1,487 @@
|
||||
# This build should never run as CI or against a pull request.
|
||||
trigger: none
|
||||
pr: none
|
||||
|
||||
pool:
|
||||
name: WinDevPool-L
|
||||
demands: ImageOverride -equals WinDevVS16-latest
|
||||
|
||||
parameters:
|
||||
- name: branding
|
||||
displayName: "Branding (Build Type)"
|
||||
type: string
|
||||
default: Release
|
||||
values:
|
||||
- Release
|
||||
- Preview
|
||||
- name: buildTerminal
|
||||
displayName: "Build Windows Terminal MSIX"
|
||||
type: boolean
|
||||
default: true
|
||||
- name: buildTerminalVPack
|
||||
displayName: "Build Windows Terminal VPack"
|
||||
type: boolean
|
||||
default: false
|
||||
- name: buildWPF
|
||||
displayName: "Build Terminal WPF Control"
|
||||
type: boolean
|
||||
default: false
|
||||
- name: pgoBuildMode
|
||||
displayName: "PGO Build Mode"
|
||||
type: string
|
||||
default: Optimize
|
||||
values:
|
||||
- Optimize
|
||||
- Instrument
|
||||
- None
|
||||
|
||||
- name: buildConfigurations
|
||||
type: object
|
||||
default:
|
||||
- Release
|
||||
- name: buildPlatforms
|
||||
type: object
|
||||
default:
|
||||
- x64
|
||||
- x86
|
||||
- arm64
|
||||
|
||||
variables:
|
||||
baseYearForVersioning: 2019 # Used by build-console-int
|
||||
versionMajor: 0
|
||||
versionMinor: 1
|
||||
TerminalInternalPackageVersion: "0.0.7"
|
||||
|
||||
# When we move off PackageES for Versioning, we'll need to switch
|
||||
# name to this format. For now, though, we need to use DayOfYear.Rev
|
||||
# to unique our builds, as mandated by PackageES's Setup task.
|
||||
# name: '$(versionMajor).$(versionMinor).$(DayOfYear)$(Rev:r).0'
|
||||
#
|
||||
# Build name/version number above must end with .0 to make the
|
||||
# store publication machinery happy.
|
||||
name: 'Terminal_$(date:yyMM).$(date:dd)$(rev:rrr)'
|
||||
|
||||
# Build Arguments:
|
||||
# WindowsTerminalOfficialBuild=[true,false]
|
||||
# true - this is running on our build agent
|
||||
# false - running locally
|
||||
# WindowsTerminalBranding=[Dev,Preview,Release]
|
||||
# <none> - Development build resources (default)
|
||||
# Preview - Preview build resources
|
||||
# Release - regular build resources
|
||||
name: $(BuildDefinitionName)_$(date:yyMM).$(date:dd)$(rev:rrr)
|
||||
resources:
|
||||
repositories:
|
||||
- repository: self
|
||||
type: git
|
||||
ref: main
|
||||
jobs:
|
||||
- template: ./templates/build-console-audit-job.yml
|
||||
parameters:
|
||||
platform: x64
|
||||
- job: Build
|
||||
strategy:
|
||||
matrix:
|
||||
${{ each config in parameters.buildConfigurations }}:
|
||||
${{ each platform in parameters.buildPlatforms }}:
|
||||
${{ config }}_${{ platform }}:
|
||||
BuildConfiguration: ${{ config }}
|
||||
BuildPlatform: ${{ platform }}
|
||||
displayName: Build
|
||||
cancelTimeoutInMinutes: 1
|
||||
steps:
|
||||
- checkout: self
|
||||
clean: true
|
||||
submodules: true
|
||||
persistCredentials: True
|
||||
- task: PkgESSetupBuild@12
|
||||
displayName: Package ES - Setup Build
|
||||
inputs:
|
||||
disableOutputRedirect: true
|
||||
- task: PowerShell@2
|
||||
displayName: Rationalize Build Platform
|
||||
inputs:
|
||||
targetType: inline
|
||||
script: >-
|
||||
$Arch = "$(BuildPlatform)"
|
||||
|
||||
- template: ./templates/build-console-int.yml
|
||||
parameters:
|
||||
platform: x64
|
||||
additionalBuildArguments: /p:WindowsTerminalOfficialBuild=true;WindowsTerminalBranding=Preview
|
||||
If ($Arch -Eq "x86") { $Arch = "Win32" }
|
||||
|
||||
- template: ./templates/build-console-int.yml
|
||||
parameters:
|
||||
platform: x86
|
||||
additionalBuildArguments: /p:WindowsTerminalOfficialBuild=true;WindowsTerminalBranding=Preview
|
||||
Write-Host "##vso[task.setvariable variable=RationalizedBuildPlatform]${Arch}"
|
||||
- task: NuGetToolInstaller@1
|
||||
displayName: Use NuGet 5.10
|
||||
inputs:
|
||||
versionSpec: 5.10
|
||||
- task: NuGetCommand@2
|
||||
displayName: NuGet custom
|
||||
inputs:
|
||||
command: custom
|
||||
selectOrConfig: config
|
||||
nugetConfigPath: NuGet.Config
|
||||
arguments: restore OpenConsole.sln -SolutionDirectory $(Build.SourcesDirectory)
|
||||
- task: UniversalPackages@0
|
||||
displayName: Download terminal-internal Universal Package
|
||||
inputs:
|
||||
feedListDownload: 2b3f8893-a6e8-411f-b197-a9e05576da48
|
||||
packageListDownload: e82d490c-af86-4733-9dc4-07b772033204
|
||||
versionListDownload: $(TerminalInternalPackageVersion)
|
||||
- task: TouchdownBuildTask@1
|
||||
displayName: Download Localization Files
|
||||
inputs:
|
||||
teamId: 7105
|
||||
authId: $(TouchdownAppId)
|
||||
authKey: $(TouchdownAppKey)
|
||||
resourceFilePath: >-
|
||||
src\cascadia\TerminalApp\Resources\en-US\Resources.resw
|
||||
|
||||
- template: ./templates/build-console-int.yml
|
||||
parameters:
|
||||
platform: arm64
|
||||
additionalBuildArguments: /p:WindowsTerminalOfficialBuild=true;WindowsTerminalBranding=Preview
|
||||
src\cascadia\TerminalControl\Resources\en-US\Resources.resw
|
||||
|
||||
- template: ./templates/check-formatting.yml
|
||||
src\cascadia\TerminalConnection\Resources\en-US\Resources.resw
|
||||
|
||||
- template: ./templates/release-sign-and-bundle.yml
|
||||
src\cascadia\TerminalSettingsModel\Resources\en-US\Resources.resw
|
||||
|
||||
src\cascadia\TerminalSettingsEditor\Resources\en-US\Resources.resw
|
||||
|
||||
src\cascadia\WindowsTerminalUniversal\Resources\en-US\Resources.resw
|
||||
|
||||
src\cascadia\CascadiaPackage\Resources\en-US\Resources.resw
|
||||
appendRelativeDir: true
|
||||
localizationTarget: false
|
||||
pseudoSetting: Included
|
||||
- task: PowerShell@2
|
||||
displayName: Move Loc files one level up
|
||||
inputs:
|
||||
targetType: inline
|
||||
script: >-
|
||||
$Files = Get-ChildItem . -R -Filter 'Resources.resw' | ? FullName -Like '*en-US\*\Resources.resw'
|
||||
|
||||
$Files | % { Move-Item -Verbose $_.Directory $_.Directory.Parent.Parent -EA:Ignore }
|
||||
pwsh: true
|
||||
- task: PowerShell@2
|
||||
displayName: Generate NOTICE.html from NOTICE.md
|
||||
inputs:
|
||||
filePath: .\build\scripts\Generate-ThirdPartyNotices.ps1
|
||||
arguments: -MarkdownNoticePath .\NOTICE.md -OutputPath .\src\cascadia\CascadiaPackage\NOTICE.html
|
||||
pwsh: true
|
||||
- ${{ if eq(parameters.pgoBuildMode, 'Optimize') }}:
|
||||
- task: PowerShell@2
|
||||
displayName: Restore PGO Database
|
||||
inputs:
|
||||
filePath: tools/PGODatabase/restore-pgodb.ps1
|
||||
workingDirectory: $(Build.SourcesDirectory)\tools\PGODatabase
|
||||
- ${{ if eq(parameters.buildTerminal, true) }}:
|
||||
- task: VSBuild@1
|
||||
displayName: Build solution **\OpenConsole.sln
|
||||
inputs:
|
||||
solution: '**\OpenConsole.sln'
|
||||
vsVersion: 16.0
|
||||
msbuildArgs: /p:WindowsTerminalOfficialBuild=true /p:WindowsTerminalBranding=${{ parameters.branding }} /t:Terminal\CascadiaPackage;Terminal\WindowsTerminalUniversal /p:WindowsTerminalReleaseBuild=true /bl:$(Build.SourcesDirectory)\msbuild.binlog
|
||||
platform: $(BuildPlatform)
|
||||
configuration: $(BuildConfiguration)
|
||||
clean: true
|
||||
maximumCpuCount: true
|
||||
- task: PublishBuildArtifacts@1
|
||||
displayName: 'Publish Artifact: binlog'
|
||||
condition: failed()
|
||||
continueOnError: True
|
||||
inputs:
|
||||
PathtoPublish: $(Build.SourcesDirectory)\msbuild.binlog
|
||||
ArtifactName: binlog-$(BuildPlatform)
|
||||
- ${{ if eq(parameters.pgoBuildMode, 'Optimize') }}:
|
||||
- task: PowerShell@2
|
||||
displayName: Validate binaries are optimized
|
||||
condition: and(succeeded(), eq(variables['BuildPlatform'], 'x64'))
|
||||
inputs:
|
||||
targetType: inline
|
||||
script: >-
|
||||
$Binaries = 'OpenConsole.exe', 'WindowsTerminal.exe', 'TerminalApp.dll', 'TerminalConnection.dll', 'Microsoft.Terminal.Control.dll', 'Microsoft.Terminal.Remoting.dll', 'Microsoft.Terminal.Settings.Editor.dll', 'Microsoft.Terminal.Settings.Model.dll'
|
||||
|
||||
foreach ($BinFile in $Binaries) {
|
||||
|
||||
& "$(Build.SourcesDirectory)\tools\PGODatabase\verify-pgo.ps1" "$(Build.SourcesDirectory)/src/cascadia/CascadiaPackage/bin/$(BuildPlatform)/$(BuildConfiguration)/$BinFile"
|
||||
|
||||
}
|
||||
- task: PowerShell@2
|
||||
displayName: Check MSIX for common regressions
|
||||
inputs:
|
||||
targetType: inline
|
||||
script: >-
|
||||
$Package = Get-ChildItem -Recurse -Filter "CascadiaPackage_*.msix"
|
||||
|
||||
.\build\scripts\Test-WindowsTerminalPackage.ps1 -Verbose -Path $Package.FullName
|
||||
pwsh: true
|
||||
- ${{ if eq(parameters.buildWPF, true) }}:
|
||||
- task: VSBuild@1
|
||||
displayName: Build solution **\OpenConsole.sln for PublicTerminalCore
|
||||
condition: and(succeeded(), ne(variables['BuildPlatform'], 'arm64'))
|
||||
inputs:
|
||||
solution: '**\OpenConsole.sln'
|
||||
vsVersion: 16.0
|
||||
msbuildArgs: /p:WindowsTerminalOfficialBuild=true /p:WindowsTerminalBranding=${{ parameters.branding }} /p:WindowsTerminalReleaseBuild=true /t:Terminal\wpf\PublicTerminalCore
|
||||
platform: $(BuildPlatform)
|
||||
configuration: $(BuildConfiguration)
|
||||
- task: PowerShell@2
|
||||
displayName: Source Index PDBs
|
||||
inputs:
|
||||
filePath: build\scripts\Index-Pdbs.ps1
|
||||
arguments: -SearchDir '$(Build.SourcesDirectory)' -SourceRoot '$(Build.SourcesDirectory)' -recursive -Verbose -CommitId $(Build.SourceVersion)
|
||||
errorActionPreference: silentlyContinue
|
||||
- task: ComponentGovernanceComponentDetection@0
|
||||
displayName: Component Detection
|
||||
- task: PowerShell@2
|
||||
displayName: Run Unit Tests
|
||||
condition: and(succeeded(), or(eq(variables['BuildPlatform'], 'x64'), eq(variables['BuildPlatform'], 'x86')))
|
||||
enabled: False
|
||||
inputs:
|
||||
filePath: build\scripts\Run-Tests.ps1
|
||||
arguments: -MatchPattern '*unit.test*.dll' -Platform '$(RationalizedBuildPlatform)' -Configuration '$(BuildConfiguration)'
|
||||
- task: PowerShell@2
|
||||
displayName: Run Feature Tests
|
||||
condition: and(succeeded(), eq(variables['BuildPlatform'], 'x64'))
|
||||
enabled: False
|
||||
inputs:
|
||||
filePath: build\scripts\Run-Tests.ps1
|
||||
arguments: -MatchPattern '*feature.test*.dll' -Platform '$(RationalizedBuildPlatform)' -Configuration '$(BuildConfiguration)'
|
||||
- ${{ if eq(parameters.buildTerminal, true) }}:
|
||||
- task: CopyFiles@2
|
||||
displayName: Copy *.appx/*.msix to Artifacts
|
||||
inputs:
|
||||
Contents: >-
|
||||
**/*.appx
|
||||
|
||||
**/*.msix
|
||||
|
||||
**/*.appxsym
|
||||
|
||||
!**/Microsoft.VCLibs*.appx
|
||||
TargetFolder: $(Build.ArtifactStagingDirectory)/appx
|
||||
OverWrite: true
|
||||
flattenFolders: true
|
||||
- task: PublishBuildArtifacts@1
|
||||
displayName: Publish Artifact (appx)
|
||||
inputs:
|
||||
PathtoPublish: $(Build.ArtifactStagingDirectory)/appx
|
||||
ArtifactName: appx-$(BuildPlatform)-$(BuildConfiguration)
|
||||
- ${{ if eq(parameters.buildWPF, true) }}:
|
||||
- task: CopyFiles@2
|
||||
displayName: Copy PublicTerminalCore.dll to Artifacts
|
||||
condition: and(succeeded(), ne(variables['BuildPlatform'], 'arm64'))
|
||||
inputs:
|
||||
Contents: >-
|
||||
**/PublicTerminalCore.dll
|
||||
|
||||
**/api-ms-win-core-synch-l1-2-0.dll
|
||||
TargetFolder: $(Build.ArtifactStagingDirectory)/wpf
|
||||
OverWrite: true
|
||||
flattenFolders: true
|
||||
- task: PublishBuildArtifacts@1
|
||||
displayName: Publish Artifact (PublicTerminalCore)
|
||||
condition: and(succeeded(), ne(variables['BuildPlatform'], 'arm64'))
|
||||
inputs:
|
||||
PathtoPublish: $(Build.ArtifactStagingDirectory)/wpf
|
||||
ArtifactName: wpf-dll-$(BuildPlatform)-$(BuildConfiguration)
|
||||
- task: PublishSymbols@2
|
||||
displayName: Publish symbols path
|
||||
continueOnError: True
|
||||
inputs:
|
||||
SearchPattern: '**/*.pdb'
|
||||
IndexSources: false
|
||||
SymbolServerType: TeamServices
|
||||
|
||||
- ${{ if eq(parameters.buildTerminal, true) }}:
|
||||
- job: BundleAndSign
|
||||
displayName: Create and sign AppX/MSIX bundles
|
||||
dependsOn: Build
|
||||
steps:
|
||||
- checkout: self
|
||||
clean: true
|
||||
submodules: true
|
||||
persistCredentials: True
|
||||
- task: PkgESSetupBuild@12
|
||||
displayName: Package ES - Setup Build
|
||||
inputs:
|
||||
disableOutputRedirect: true
|
||||
- task: DownloadBuildArtifacts@0
|
||||
displayName: Download Artifacts (*.appx, *.msix)
|
||||
inputs:
|
||||
downloadType: specific
|
||||
itemPattern: >-
|
||||
**/*.msix
|
||||
|
||||
**/*.appx
|
||||
extractTars: false
|
||||
- task: PowerShell@2
|
||||
displayName: Create WindowsTerminal*.msixbundle
|
||||
inputs:
|
||||
filePath: build\scripts\Create-AppxBundle.ps1
|
||||
arguments: -InputPath "$(System.ArtifactsDirectory)" -ProjectName CascadiaPackage -BundleVersion 0.0.0.0 -OutputPath "$(System.ArtifactsDirectory)\Microsoft.WindowsTerminal_$(XES_APPXMANIFESTVERSION)_8wekyb3d8bbwe.msixbundle"
|
||||
- task: PowerShell@2
|
||||
displayName: Create WindowsTerminalUniversal*.msixbundle
|
||||
inputs:
|
||||
filePath: build\scripts\Create-AppxBundle.ps1
|
||||
arguments: -InputPath "$(System.ArtifactsDirectory)" -ProjectName WindowsTerminalUniversal -BundleVersion $(XES_APPXMANIFESTVERSION) -OutputPath "$(System.ArtifactsDirectory)\Microsoft.WindowsTerminalUniversal_$(XES_APPXMANIFESTVERSION)_8wekyb3d8bbwe.msixbundle"
|
||||
- task: EsrpCodeSigning@1
|
||||
displayName: Submit *.msixbundle to ESRP for code signing
|
||||
inputs:
|
||||
ConnectedServiceName: 9d6d2960-0793-4d59-943e-78dcb434840a
|
||||
FolderPath: $(System.ArtifactsDirectory)
|
||||
Pattern: Microsoft.WindowsTerminal*.msixbundle
|
||||
UseMinimatch: true
|
||||
signConfigType: inlineSignParams
|
||||
inlineOperation: >-
|
||||
[
|
||||
{
|
||||
"KeyCode": "Dynamic",
|
||||
"CertTemplateName": "WINMSAPP1ST",
|
||||
"CertSubjectName": "CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US",
|
||||
"OperationCode": "SigntoolSign",
|
||||
"Parameters": {
|
||||
"OpusName": "Microsoft",
|
||||
"OpusInfo": "http://www.microsoft.com",
|
||||
"FileDigest": "/fd \"SHA256\"",
|
||||
"TimeStamp": "/tr \"http://rfc3161.gtm.corp.microsoft.com/TSS/HttpTspServer\" /td sha256"
|
||||
},
|
||||
"ToolName": "sign",
|
||||
"ToolVersion": "1.0"
|
||||
},
|
||||
{
|
||||
"KeyCode": "Dynamic",
|
||||
"CertTemplateName": "WINMSAPP1ST",
|
||||
"CertSubjectName": "CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US",
|
||||
"OperationCode": "SigntoolVerify",
|
||||
"Parameters": {},
|
||||
"ToolName": "sign",
|
||||
"ToolVersion": "1.0"
|
||||
}
|
||||
]
|
||||
- task: PublishBuildArtifacts@1
|
||||
displayName: 'Publish Artifact: appxbundle-signed'
|
||||
inputs:
|
||||
PathtoPublish: $(System.ArtifactsDirectory)
|
||||
ArtifactName: appxbundle-signed
|
||||
|
||||
- ${{ if eq(parameters.buildWPF, true) }}:
|
||||
- job: PackageAndSignWPF
|
||||
strategy:
|
||||
matrix:
|
||||
${{ each config in parameters.buildConfigurations }}:
|
||||
${{ config }}:
|
||||
BuildConfiguration: ${{ config }}
|
||||
displayName: Create NuGet Package (WPF Terminal Control)
|
||||
dependsOn: Build
|
||||
steps:
|
||||
- checkout: self
|
||||
clean: true
|
||||
submodules: true
|
||||
persistCredentials: True
|
||||
- task: PkgESSetupBuild@12
|
||||
displayName: Package ES - Setup Build
|
||||
inputs:
|
||||
disableOutputRedirect: true
|
||||
- task: DownloadBuildArtifacts@0
|
||||
displayName: Download x86 PublicTerminalCore
|
||||
inputs:
|
||||
artifactName: wpf-dll-x86-$(BuildConfiguration)
|
||||
itemPattern: '**/*.dll'
|
||||
downloadPath: bin\Win32\$(BuildConfiguration)\
|
||||
extractTars: false
|
||||
- task: DownloadBuildArtifacts@0
|
||||
displayName: Download x64 PublicTerminalCore
|
||||
inputs:
|
||||
artifactName: wpf-dll-x64-$(BuildConfiguration)
|
||||
itemPattern: '**/*.dll'
|
||||
downloadPath: bin\x64\$(BuildConfiguration)\
|
||||
extractTars: false
|
||||
- task: PowerShell@2
|
||||
displayName: Move downloaded artifacts up a level
|
||||
inputs:
|
||||
targetType: inline
|
||||
# Find all artifact files and move them up a directory. Ugh.
|
||||
script: >-
|
||||
Get-ChildItem bin -Recurse -Directory -Filter wpf-dll-* | % {
|
||||
$_ | Get-ChildItem -Recurse -File | % {
|
||||
Move-Item -Verbose $_.FullName $_.Directory.Parent.FullName
|
||||
}
|
||||
}
|
||||
- task: NuGetToolInstaller@1
|
||||
displayName: Use NuGet 5.10.0
|
||||
inputs:
|
||||
versionSpec: 5.10.0
|
||||
- task: NuGetCommand@2
|
||||
displayName: NuGet restore copy
|
||||
inputs:
|
||||
selectOrConfig: config
|
||||
nugetConfigPath: NuGet.Config
|
||||
- task: VSBuild@1
|
||||
displayName: Build solution **\OpenConsole.sln for WPF Control
|
||||
inputs:
|
||||
solution: '**\OpenConsole.sln'
|
||||
vsVersion: 16.0
|
||||
msbuildArgs: /p:WindowsTerminalReleaseBuild=$(UseReleaseBranding);Version=$(XES_PACKAGEVERSIONNUMBER) /t:Pack
|
||||
platform: Any CPU
|
||||
configuration: $(BuildConfiguration)
|
||||
maximumCpuCount: true
|
||||
- task: PublishSymbols@2
|
||||
displayName: Publish symbols path
|
||||
continueOnError: True
|
||||
inputs:
|
||||
SearchPattern: '**/*.pdb'
|
||||
IndexSources: false
|
||||
SymbolServerType: TeamServices
|
||||
SymbolsArtifactName: Symbols_WPF_$(BuildConfiguration)
|
||||
- task: CopyFiles@2
|
||||
displayName: Copy *.nupkg to Artifacts
|
||||
inputs:
|
||||
Contents: '**/*Wpf*.nupkg'
|
||||
TargetFolder: $(Build.ArtifactStagingDirectory)/nupkg
|
||||
OverWrite: true
|
||||
flattenFolders: true
|
||||
- task: EsrpCodeSigning@1
|
||||
displayName: Submit *.nupkg to ESRP for code signing
|
||||
inputs:
|
||||
ConnectedServiceName: 9d6d2960-0793-4d59-943e-78dcb434840a
|
||||
FolderPath: $(Build.ArtifactStagingDirectory)/nupkg
|
||||
Pattern: '*.nupkg'
|
||||
UseMinimatch: true
|
||||
signConfigType: inlineSignParams
|
||||
inlineOperation: >-
|
||||
[
|
||||
{
|
||||
"KeyCode": "CP-401405",
|
||||
"OperationCode": "NuGetSign",
|
||||
"Parameters": {},
|
||||
"ToolName": "sign",
|
||||
"ToolVersion": "1.0"
|
||||
},
|
||||
{
|
||||
"KeyCode": "CP-401405",
|
||||
"OperationCode": "NuGetVerify",
|
||||
"Parameters": {},
|
||||
"ToolName": "sign",
|
||||
"ToolVersion": "1.0"
|
||||
}
|
||||
]
|
||||
- task: PublishBuildArtifacts@1
|
||||
displayName: Publish Artifact (nupkg)
|
||||
inputs:
|
||||
PathtoPublish: $(Build.ArtifactStagingDirectory)\nupkg
|
||||
ArtifactName: wpf-nupkg-$(BuildConfiguration)
|
||||
|
||||
- ${{ if eq(parameters.buildTerminalVPack, true) }}:
|
||||
- job: VPack
|
||||
displayName: Create Windows vPack
|
||||
dependsOn: BundleAndSign
|
||||
steps:
|
||||
- checkout: self
|
||||
clean: true
|
||||
submodules: true
|
||||
- task: PkgESSetupBuild@12
|
||||
displayName: Package ES - Setup Build
|
||||
- task: DownloadBuildArtifacts@0
|
||||
displayName: Download Build Artifacts
|
||||
inputs:
|
||||
artifactName: appxbundle-signed
|
||||
extractTars: false
|
||||
- task: PowerShell@2
|
||||
displayName: Rename and stage packages for vpack
|
||||
inputs:
|
||||
targetType: inline
|
||||
script: >-
|
||||
# Rename to known/fixed name for Windows build system
|
||||
|
||||
Get-ChildItem Microsoft.WindowsTerminal_*.msixbundle | Rename-Item -NewName { 'Microsoft.WindowsTerminal_8wekyb3d8bbwe.msixbundle' }
|
||||
|
||||
|
||||
# Create vpack directory and place item inside
|
||||
|
||||
mkdir WindowsTerminal.app
|
||||
|
||||
mv Microsoft.WindowsTerminal_8wekyb3d8bbwe.msixbundle .\WindowsTerminal.app\
|
||||
workingDirectory: $(System.ArtifactsDirectory)\appxbundle-signed
|
||||
- task: PkgESVPack@12
|
||||
displayName: 'Package ES - VPack'
|
||||
env:
|
||||
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
|
||||
inputs:
|
||||
sourceDirectory: $(System.ArtifactsDirectory)\appxbundle-signed\WindowsTerminal.app
|
||||
description: Windows Terminal pre-install application
|
||||
pushPkgName: WindowsTerminal.app
|
||||
owner: condev
|
||||
...
|
||||
|
||||
@@ -8,9 +8,12 @@ jobs:
|
||||
variables:
|
||||
BuildConfiguration: AuditMode
|
||||
BuildPlatform: ${{ parameters.platform }}
|
||||
pool: "windevbuildagents"
|
||||
# The public pool is also an option!
|
||||
# pool: { vmImage: windows-2019 }
|
||||
pool:
|
||||
${{ if eq(variables['System.CollectionUri'], 'https://dev.azure.com/ms/') }}:
|
||||
name: WinDevPoolOSS-L
|
||||
${{ if ne(variables['System.CollectionUri'], 'https://dev.azure.com/ms/') }}:
|
||||
name: WinDevPool-L
|
||||
demands: ImageOverride -equals WinDevVS16-latest
|
||||
|
||||
steps:
|
||||
- checkout: self
|
||||
|
||||
@@ -11,9 +11,12 @@ jobs:
|
||||
variables:
|
||||
BuildConfiguration: ${{ parameters.configuration }}
|
||||
BuildPlatform: ${{ parameters.platform }}
|
||||
pool: "windevbuildagents"
|
||||
# The public pool is also an option!
|
||||
# pool: { vmImage: windows-2019 }
|
||||
pool:
|
||||
${{ if eq(variables['System.CollectionUri'], 'https://dev.azure.com/ms/') }}:
|
||||
name: WinDevPoolOSS-L
|
||||
${{ if ne(variables['System.CollectionUri'], 'https://dev.azure.com/ms/') }}:
|
||||
name: WinDevPool-L
|
||||
demands: ImageOverride -equals WinDevVS16-latest
|
||||
|
||||
steps:
|
||||
- template: build-console-steps.yml
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
parameters:
|
||||
configuration: 'Release'
|
||||
platform: ''
|
||||
additionalBuildArguments: ''
|
||||
|
||||
jobs:
|
||||
- job: Build${{ parameters.platform }}${{ parameters.configuration }}
|
||||
displayName: Build ${{ parameters.platform }} ${{ parameters.configuration }}
|
||||
variables:
|
||||
BuildConfiguration: ${{ parameters.configuration }}
|
||||
BuildPlatform: ${{ parameters.platform }}
|
||||
PGOBuildMode: 'Optimize'
|
||||
|
||||
pool:
|
||||
name: Package ES Lab E
|
||||
demands:
|
||||
- msbuild
|
||||
- visualstudio
|
||||
- vstest
|
||||
|
||||
steps:
|
||||
- task: PkgESSetupBuild@10
|
||||
displayName: 'Package ES - Setup Build'
|
||||
inputs:
|
||||
useDfs: false
|
||||
productName: WindowsTerminal
|
||||
disableOutputRedirect: true
|
||||
|
||||
- template: build-console-steps.yml
|
||||
parameters:
|
||||
additionalBuildArguments: "/p:XesUseOneStoreVersioning=true;XesBaseYearForStoreVersion=$(baseYearForVersioning) ${{ parameters.additionalBuildArguments }}"
|
||||
@@ -12,9 +12,12 @@ jobs:
|
||||
BuildConfiguration: ${{ parameters.configuration }}
|
||||
BuildPlatform: ${{ parameters.platform }}
|
||||
PGOBuildMode: 'Instrument'
|
||||
pool: "windevbuildagents"
|
||||
# The public pool is also an option!
|
||||
# pool: { vmImage: windows-2019 }
|
||||
pool:
|
||||
${{ if eq(variables['System.CollectionUri'], 'https://dev.azure.com/ms/') }}:
|
||||
name: WinDevPoolOSS-L
|
||||
${{ if ne(variables['System.CollectionUri'], 'https://dev.azure.com/ms/') }}:
|
||||
name: WinDevPool-L
|
||||
demands: ImageOverride -equals WinDevVS16-latest
|
||||
|
||||
steps:
|
||||
- template: build-console-steps.yml
|
||||
|
||||
@@ -12,4 +12,4 @@ steps:
|
||||
inputs:
|
||||
targetType: filePath
|
||||
filePath: build\Helix\GenerateTestProjFile.ps1
|
||||
arguments: -TestFile '${{ parameters.testFilePath }}' -OutputProjFile '$(Build.ArtifactStagingDirectory)\$(BuildConfiguration)\$(BuildPlatform)\${{ parameters.outputProjFileName }}' -JobTestSuiteName '${{ parameters.testSuite }}' -TaefPath '$(Build.SourcesDirectory)\build\Helix\packages\Microsoft.Taef.10.58.210305002\build\Binaries\x86' -TaefQuery '${{ parameters.taefQuery }}'
|
||||
arguments: -TestFile '${{ parameters.testFilePath }}' -OutputProjFile '$(Build.ArtifactStagingDirectory)\$(BuildConfiguration)\$(BuildPlatform)\${{ parameters.outputProjFileName }}' -JobTestSuiteName '${{ parameters.testSuite }}' -TaefPath '$(Build.SourcesDirectory)\build\Helix\packages\Microsoft.Taef.10.60.210621002\build\Binaries\x86' -TaefQuery '${{ parameters.taefQuery }}'
|
||||
@@ -30,7 +30,7 @@ jobs:
|
||||
buildPlatform: ${{ parameters.platform }}
|
||||
openHelixTargetQueues: ${{ parameters.openHelixTargetQueues }}
|
||||
artifactsDir: $(Build.SourcesDirectory)\Artifacts
|
||||
taefPath: $(Build.SourcesDirectory)\build\Helix\packages\Microsoft.Taef.10.58.210305002\build\Binaries\$(buildPlatform)
|
||||
taefPath: $(Build.SourcesDirectory)\build\Helix\packages\Microsoft.Taef.10.60.210621002\build\Binaries\$(buildPlatform)
|
||||
helixCommonArgs: '/binaryLogger:$(Build.SourcesDirectory)/${{parameters.name}}.$(buildPlatform).$(buildConfiguration).binlog /p:HelixBuild=$(Build.BuildId).$(buildPlatform).$(buildConfiguration) /p:Platform=$(buildPlatform) /p:Configuration=$(buildConfiguration) /p:HelixType=${{parameters.helixType}} /p:TestSuite=${{parameters.testSuite}} /p:ProjFilesPath=$(Build.ArtifactStagingDirectory) /p:rerunPassesRequiredToAvoidFailure=${{parameters.rerunPassesRequiredToAvoidFailure}}'
|
||||
|
||||
|
||||
@@ -147,4 +147,3 @@ jobs:
|
||||
projects: build\Helix\RunTestsInHelix.proj
|
||||
custom: msbuild
|
||||
arguments: '$(helixCommonArgs) /p:IsExternal=true /p:Creator=Terminal /p:HelixTargetQueues=$(openHelixTargetQueues)'
|
||||
|
||||
|
||||
@@ -1,74 +0,0 @@
|
||||
parameters:
|
||||
configuration: 'Release'
|
||||
|
||||
jobs:
|
||||
- job: SignDeploy${{ parameters.configuration }}
|
||||
displayName: Sign and Deploy for ${{ parameters.configuration }}
|
||||
|
||||
dependsOn:
|
||||
- Buildx64AuditMode
|
||||
- Buildx64Release
|
||||
- Buildx86Release
|
||||
- Buildarm64Release
|
||||
- CodeFormatCheck
|
||||
condition: |
|
||||
and
|
||||
(
|
||||
in(dependencies.Buildx64AuditMode.result, 'Succeeded', 'SucceededWithIssues', 'Skipped'),
|
||||
in(dependencies.Buildx64Release.result, 'Succeeded', 'SucceededWithIssues', 'Skipped'),
|
||||
in(dependencies.Buildx86Release.result, 'Succeeded', 'SucceededWithIssues', 'Skipped'),
|
||||
in(dependencies.Buildarm64Release.result, 'Succeeded', 'SucceededWithIssues', 'Skipped'),
|
||||
in(dependencies.CodeFormatCheck.result, 'Succeeded', 'SucceededWithIssues', 'Skipped')
|
||||
)
|
||||
|
||||
variables:
|
||||
BuildConfiguration: ${{ parameters.configuration }}
|
||||
AppxProjectName: CascadiaPackage
|
||||
AppxBundleName: Microsoft.WindowsTerminal_8wekyb3d8bbwe.msixbundle
|
||||
|
||||
pool:
|
||||
name: Package ES Lab E
|
||||
|
||||
steps:
|
||||
- checkout: self
|
||||
clean: true
|
||||
|
||||
- task: PkgESSetupBuild@10
|
||||
displayName: 'Package ES - Setup Build'
|
||||
inputs:
|
||||
useDfs: false
|
||||
productName: WindowsTerminal
|
||||
disableOutputRedirect: true
|
||||
|
||||
- task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0
|
||||
displayName: 'Component Detection'
|
||||
|
||||
- task: DownloadBuildArtifacts@0
|
||||
displayName: Download AppX artifacts
|
||||
inputs:
|
||||
artifactName: 'appx-$(BuildConfiguration)'
|
||||
itemPattern: |
|
||||
**/*.appx
|
||||
**/*.msix
|
||||
downloadPath: '$(Build.ArtifactStagingDirectory)\appx'
|
||||
|
||||
- task: PowerShell@2
|
||||
displayName: 'Create $(AppxBundleName)'
|
||||
inputs:
|
||||
targetType: filePath
|
||||
filePath: '.\build\scripts\Create-AppxBundle.ps1'
|
||||
arguments: |
|
||||
-InputPath "$(Build.ArtifactStagingDirectory)\appx" -ProjectName $(AppxProjectName) -BundleVersion 0.0.0.0 -OutputPath "$(Build.ArtifactStagingDirectory)\$(AppxBundleName)"
|
||||
|
||||
- task: PkgESCodeSign@10
|
||||
displayName: 'Package ES - SignConfig.WindowsTerminal.xml'
|
||||
inputs:
|
||||
signConfigXml: 'build\config\SignConfig.WindowsTerminal.xml'
|
||||
inPathRoot: '$(Build.ArtifactStagingDirectory)'
|
||||
outPathRoot: '$(Build.ArtifactStagingDirectory)\signed'
|
||||
|
||||
- task: PublishBuildArtifacts@1
|
||||
displayName: 'Publish Signed AppX'
|
||||
inputs:
|
||||
PathtoPublish: '$(Build.ArtifactStagingDirectory)\signed'
|
||||
ArtifactName: 'appxbundle-signed-$(BuildConfiguration)'
|
||||
@@ -19,6 +19,7 @@
|
||||
"/.github/",
|
||||
"/samples/",
|
||||
"/res/terminal/",
|
||||
"/res/fonts/",
|
||||
"/doc/specs/",
|
||||
"/doc/cascadia/",
|
||||
"/doc/user-docs/",
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<XesUseOneStoreVersioning>true</XesUseOneStoreVersioning>
|
||||
<XesBaseYearForStoreVersion>2021</XesBaseYearForStoreVersion>
|
||||
<VersionMajor>1</VersionMajor>
|
||||
<VersionMinor>10</VersionMinor>
|
||||
<VersionMinor>11</VersionMinor>
|
||||
<VersionInfoProductName>Windows Terminal</VersionInfoProductName>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
|
||||
@@ -6,9 +6,9 @@ Adding a setting to Windows Terminal is fairly straightforward. This guide serve
|
||||
|
||||
The Terminal Settings Model (`Microsoft.Terminal.Settings.Model`) is responsible for (de)serializing and exposing settings.
|
||||
|
||||
### `GETSET_SETTING` macro
|
||||
### `INHERITABLE_SETTING` macro
|
||||
|
||||
The `GETSET_SETTING` macro can be used to implement inheritance for your new setting and store the setting in the settings model. It takes three parameters:
|
||||
The `INHERITABLE_SETTING` macro can be used to implement inheritance for your new setting and store the setting in the settings model. It takes three parameters:
|
||||
- `type`: the type that the setting will be stored as
|
||||
- `name`: the name of the variable for storage
|
||||
- `defaultValue`: the value to use if the user does not define the setting anywhere
|
||||
@@ -20,7 +20,7 @@ This tutorial will add `CloseOnExitMode CloseOnExit` as a profile setting.
|
||||
1. In `Profile.h`, declare/define the setting:
|
||||
|
||||
```c++
|
||||
GETSET_SETTING(CloseOnExitMode, CloseOnExit, CloseOnExitMode::Graceful)
|
||||
INHERITABLE_SETTING(CloseOnExitMode, CloseOnExit, CloseOnExitMode::Graceful)
|
||||
```
|
||||
|
||||
2. In `Profile.idl`, expose the setting via WinRT:
|
||||
@@ -141,7 +141,7 @@ struct OpenSettingsArgs : public OpenSettingsArgsT<OpenSettingsArgs>
|
||||
OpenSettingsArgs() = default;
|
||||
|
||||
// adds a getter/setter for your argument, and defines the json key
|
||||
GETSET_PROPERTY(SettingsTarget, Target, SettingsTarget::SettingsFile);
|
||||
WINRT_PROPERTY(SettingsTarget, Target, SettingsTarget::SettingsFile);
|
||||
static constexpr std::string_view TargetKey{ "target" };
|
||||
|
||||
public:
|
||||
@@ -213,9 +213,9 @@ Terminal-level settings are settings that affect a shell session. Generally, the
|
||||
- Declare the setting in `IControlSettings.idl` or `ICoreSettings.idl` (whichever is relevant to your setting). If your setting is an enum setting, declare the enum here instead of in the `TerminalSettingsModel` project.
|
||||
- In `TerminalSettings.h`, declare/define the setting...
|
||||
```c++
|
||||
// The GETSET_PROPERTY macro declares/defines a getter setter for the setting.
|
||||
// Like GETSET_SETTING, it takes in a type, name, and defaultValue.
|
||||
GETSET_PROPERTY(bool, UseAcrylic, false);
|
||||
// The WINRT_PROPERTY macro declares/defines a getter setter for the setting.
|
||||
// Like INHERITABLE_SETTING, it takes in a type, name, and defaultValue.
|
||||
WINRT_PROPERTY(bool, UseAcrylic, false);
|
||||
```
|
||||
- In `TerminalSettings.cpp`...
|
||||
- update `_ApplyProfileSettings` for profile settings
|
||||
|
||||
@@ -4,13 +4,13 @@
|
||||
"title": "Microsoft's Windows Terminal Settings Profile Schema",
|
||||
"definitions": {
|
||||
"KeyChordSegment": {
|
||||
"pattern": "^(?<modifier>(?<mod1>ctrl|alt|shift|win)(?:\\+(?<mod2>ctrl|alt|shift|win)(?<!\\k<mod1>))?(?:\\+(?<mod3>ctrl|alt|shift|win)(?<!\\k<mod1>|\\k<mod2>))?(?:\\+(?<mod4>ctrl|alt|shift|win)(?<!\\k<mod1>|\\k<mod2>|\\k<mod3>))?\\+)?(?<key>[^\\s+]|app|menu|backspace|tab|enter|esc|escape|space|pgup|pageup|pgdn|pagedown|end|home|left|up|right|down|insert|delete|(?<!shift.+)(?:numpad_?[0-9]|numpad_(?:period|decimal))|numpad_(?:multiply|plus|add|minus|subtract|divide)|f[1-9]|f1[0-9]|f2[0-4]|plus)$",
|
||||
"pattern": "^(?:(?:ctrl|alt|shift|win)\\+)*(?:app|backspace|browser_(?:back|forward|refresh|stop|search|favorites|home)|comma|delete|down|end|enter|esc|escape|home|insert|left|menu|minus|pagedown|pageup|period|pgdn|pgup|plus|right|space|tab|up|f(?:1\\d?|2[0-4]?|[3-9])|numpad\\d|numpad_(?:\\d|add|decimal|divide|minus|multiply|period|plus|subtract)|(?:vk|sc)\\((?:[1-9]|1?\\d{2}|2[0-4]\\d|25[0-5])\\)|[^\\s+])(?:\\+(?:ctrl|alt|shift|win))*$",
|
||||
"type": "string",
|
||||
"description": "The string should fit the format \"[ctrl+][alt+][shift+][win+]<keyName>\", where each modifier is optional, separated by + symbols, and keyName is either one of the names listed in the table below, or any single key character. The string should be written in full lowercase.\napp, menu\tMENU key\nbackspace\tBACKSPACE key\ntab\tTAB key\nenter\tENTER key\nesc, escape\tESC key\nspace\tSPACEBAR\npgup, pageup\tPAGE UP key\npgdn, pagedown\tPAGE DOWN key\nend\tEND key\nhome\tHOME key\nleft\tLEFT ARROW key\nup\tUP ARROW key\nright\tRIGHT ARROW key\ndown\tDOWN ARROW key\ninsert\tINS key\ndelete\tDEL key\nnumpad_0-numpad_9, numpad0-numpad9\tNumeric keypad keys 0 to 9. Can't be combined with the shift modifier.\nnumpad_multiply\tNumeric keypad MULTIPLY key (*)\nnumpad_plus, numpad_add\tNumeric keypad ADD key (+)\nnumpad_minus, numpad_subtract\tNumeric keypad SUBTRACT key (-)\nnumpad_period, numpad_decimal\tNumeric keypad DECIMAL key (.). Can't be combined with the shift modifier.\nnumpad_divide\tNumeric keypad DIVIDE key (/)\nf1-f24\tF1 to F24 function keys\nplus\tADD key (+)"
|
||||
"description": "The string should fit the format \"[ctrl+][alt+][shift+][win+]<KeyName>\", where each modifier is optional. KeyName is either any single key character, an explicit virtual key or scan code in the form vk(nnn) and sc(nnn) respectively, or one of the special names listed at https://docs.microsoft.com/en-us/windows/terminal/customize-settings/actions#accepted-modifiers-and-keys"
|
||||
},
|
||||
"Color": {
|
||||
"default": "#",
|
||||
"pattern": "^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$",
|
||||
"pattern": "^#[A-Fa-f0-9]{3}(?:[A-Fa-f0-9]{3})?$",
|
||||
"type": "string",
|
||||
"format": "color"
|
||||
},
|
||||
@@ -154,6 +154,17 @@
|
||||
"description": "Sets how the background image aligns to the boundaries of the window when unfocused. Possible values: \"center\", \"left\", \"top\", \"right\", \"bottom\", \"topLeft\", \"topRight\", \"bottomLeft\", \"bottomRight\"",
|
||||
"type": "string"
|
||||
},
|
||||
"intenseTextStyle": {
|
||||
"default": "bright",
|
||||
"description": "Controls how 'intense' text is rendered. Values are \"bold\", \"bright\", \"all\" and \"none\"",
|
||||
"enum": [
|
||||
"none",
|
||||
"bold",
|
||||
"bright",
|
||||
"all"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"experimental.retroTerminalEffect": {
|
||||
"description": "When set to true, enable retro terminal effects when unfocused. This is an experimental feature, and its continued existence is not guaranteed.",
|
||||
"type": "boolean"
|
||||
@@ -165,6 +176,49 @@
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"FontConfig": {
|
||||
"properties": {
|
||||
"face": {
|
||||
"default": "Cascadia Mono",
|
||||
"description": "Name of the font face used in the profile.",
|
||||
"type": "string"
|
||||
},
|
||||
"size": {
|
||||
"default": 12,
|
||||
"description": "Size of the font in points.",
|
||||
"minimum": 1,
|
||||
"type": "integer"
|
||||
},
|
||||
"weight": {
|
||||
"default": "normal",
|
||||
"description": "Sets the weight (lightness or heaviness of the strokes) for the given font. Possible values:\n -\"thin\"\n -\"extra-light\"\n -\"light\"\n -\"semi-light\"\n -\"normal\" (default)\n -\"medium\"\n -\"semi-bold\"\n -\"bold\"\n -\"extra-bold\"\n -\"black\"\n -\"extra-black\"\n or the corresponding numeric representation of OpenType font weight.",
|
||||
"oneOf": [
|
||||
{
|
||||
"enum": [
|
||||
"thin",
|
||||
"extra-light",
|
||||
"light",
|
||||
"semi-light",
|
||||
"normal",
|
||||
"medium",
|
||||
"semi-bold",
|
||||
"bold",
|
||||
"extra-bold",
|
||||
"black",
|
||||
"extra-black"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"maximum": 990,
|
||||
"minimum": 100,
|
||||
"type": "integer"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"ProfileGuid": {
|
||||
"default": "{}",
|
||||
"pattern": "^\\{[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}\\}$",
|
||||
@@ -195,6 +249,8 @@
|
||||
"identifyWindow",
|
||||
"identifyWindows",
|
||||
"moveFocus",
|
||||
"movePane",
|
||||
"swapPane",
|
||||
"moveTab",
|
||||
"newTab",
|
||||
"newWindow",
|
||||
@@ -227,6 +283,7 @@
|
||||
"toggleFocusMode",
|
||||
"toggleFullscreen",
|
||||
"togglePaneZoom",
|
||||
"toggleSplitOrientation",
|
||||
"toggleReadOnlyMode",
|
||||
"toggleShaderEffects",
|
||||
"wt",
|
||||
@@ -240,7 +297,9 @@
|
||||
"right",
|
||||
"up",
|
||||
"down",
|
||||
"previous"
|
||||
"previous",
|
||||
"nextInOrder",
|
||||
"previousInOrder"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
@@ -448,6 +507,23 @@
|
||||
"type": "integer",
|
||||
"default": 0,
|
||||
"description": "Which tab to switch to, with the first being 0"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"required": [ "index" ]
|
||||
},
|
||||
"MovePaneAction": {
|
||||
"description": "Arguments corresponding to a Move Pane Action",
|
||||
"allOf": [
|
||||
{ "$ref": "#/definitions/ShortcutAction" },
|
||||
{
|
||||
"properties": {
|
||||
"action": { "type": "string", "pattern": "movePane" },
|
||||
"index": {
|
||||
"type": "integer",
|
||||
"default": 0,
|
||||
"description": "Which tab to move the pane to, with the first being 0"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -464,7 +540,24 @@
|
||||
"direction": {
|
||||
"$ref": "#/definitions/FocusDirection",
|
||||
"default": "left",
|
||||
"description": "The direction to move focus in, between panes. Direction can be 'previous' to move to the most recently used pane."
|
||||
"description": "The direction to move focus in, between panes. Direction can be 'previous' to move to the most recently used pane, or 'nextInOrder' or 'previousInOrder' to move to the next or previous pane."
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"required": [ "direction" ]
|
||||
},
|
||||
"SwapPaneAction": {
|
||||
"description": "Arguments corresponding to a Swap Pane Action",
|
||||
"allOf": [
|
||||
{ "$ref": "#/definitions/ShortcutAction" },
|
||||
{
|
||||
"properties": {
|
||||
"action": { "type": "string", "pattern": "swapPane" },
|
||||
"direction": {
|
||||
"$ref": "#/definitions/FocusDirection",
|
||||
"default": "left",
|
||||
"description": "The direction to move the focus pane in, swapping panes. Direction can be 'previous' to swap with the most recently used pane, or 'nextInOrder' or 'previousInOrder' to move to the next or previous pane."
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -546,12 +639,14 @@
|
||||
"action": { "type": "string", "pattern": "openSettings" },
|
||||
"target": {
|
||||
"type": "string",
|
||||
"default": "settingsFile",
|
||||
"description": "The settings file to open.",
|
||||
"default": "settingsUI",
|
||||
"description": "Opens Settings UI or settings file.",
|
||||
"enum": [
|
||||
"settingsFile",
|
||||
"defaultsFile",
|
||||
"allFiles"
|
||||
"allFiles",
|
||||
"settingsUI"
|
||||
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -646,6 +741,25 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"CloseTabAction": {
|
||||
"description": "Arguments for a closeTab action",
|
||||
"allOf": [
|
||||
{ "$ref": "#/definitions/ShortcutAction" },
|
||||
{
|
||||
"properties": {
|
||||
"action": { "type": "string", "pattern": "closeTab" },
|
||||
"index": {
|
||||
"oneOf": [
|
||||
{ "type": "integer" },
|
||||
{ "type": "null" }
|
||||
],
|
||||
"default": null,
|
||||
"description": "Close the tab at this index. If no index is provided, use the focused tab's index."
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"ScrollUpAction": {
|
||||
"description": "Arguments for a scrollUp action",
|
||||
"allOf": [
|
||||
@@ -888,6 +1002,8 @@
|
||||
{ "$ref": "#/definitions/NewTabAction" },
|
||||
{ "$ref": "#/definitions/SwitchToTabAction" },
|
||||
{ "$ref": "#/definitions/MoveFocusAction" },
|
||||
{ "$ref": "#/definitions/MovePaneAction" },
|
||||
{ "$ref": "#/definitions/SwapPaneAction" },
|
||||
{ "$ref": "#/definitions/ResizePaneAction" },
|
||||
{ "$ref": "#/definitions/SendInputAction" },
|
||||
{ "$ref": "#/definitions/SplitPaneAction" },
|
||||
@@ -897,6 +1013,7 @@
|
||||
{ "$ref": "#/definitions/WtAction" },
|
||||
{ "$ref": "#/definitions/CloseOtherTabsAction" },
|
||||
{ "$ref": "#/definitions/CloseTabsAfterAction" },
|
||||
{ "$ref": "#/definitions/CloseTabAction" },
|
||||
{ "$ref": "#/definitions/ScrollUpAction" },
|
||||
{ "$ref": "#/definitions/ScrollDownAction" },
|
||||
{ "$ref": "#/definitions/MoveTabAction" },
|
||||
@@ -1051,6 +1168,10 @@
|
||||
"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": {
|
||||
"description": "Force the terminal to use the legacy input encoding. Certain keys in some applications may stop working when enabling this setting.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"initialCols": {
|
||||
"default": 120,
|
||||
"description": "The number of columns displayed in the window upon first load. If \"launchMode\" is set to \"maximized\" (or \"maximizedFocus\"), this property is ignored.",
|
||||
@@ -1093,6 +1214,16 @@
|
||||
"minimum": 0,
|
||||
"type": [ "integer", "string" ],
|
||||
"deprecated": true
|
||||
},
|
||||
"minimizeToTray": {
|
||||
"default": "false",
|
||||
"description": "When set to true, minimizing a Terminal window will no longer appear in the taskbar. Instead, a Terminal icon will appear in the system tray through which the user can access their windows.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"alwaysShowTrayIcon": {
|
||||
"default": "false",
|
||||
"description": "When set to true, the Terminal's tray icon will always be shown in the system tray.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"actions": {
|
||||
"description": "Properties are specific to each custom action.",
|
||||
@@ -1242,6 +1373,11 @@
|
||||
"description": "Sets the appearance of the terminal when it is unfocused.",
|
||||
"type": ["object", "null"]
|
||||
},
|
||||
"font": {
|
||||
"$ref": "#/definitions/FontConfig",
|
||||
"description": "Sets the font options of the terminal.",
|
||||
"type": ["object", "null"]
|
||||
},
|
||||
"backgroundImage": {
|
||||
"description": "Sets the file location of the image to draw over the window background.",
|
||||
"oneOf": [
|
||||
@@ -1358,18 +1494,20 @@
|
||||
},
|
||||
"fontFace": {
|
||||
"default": "Cascadia Mono",
|
||||
"description": "Name of the font face used in the profile.",
|
||||
"type": "string"
|
||||
"description": "[deprecated] Define 'face' within the 'font' object instead.",
|
||||
"type": "string",
|
||||
"deprecated": true
|
||||
},
|
||||
"fontSize": {
|
||||
"default": 12,
|
||||
"description": "Size of the font in points.",
|
||||
"description": "[deprecated] Define 'size' within the 'font' object instead.",
|
||||
"minimum": 1,
|
||||
"type": "integer"
|
||||
"type": "integer",
|
||||
"deprecated": true
|
||||
},
|
||||
"fontWeight": {
|
||||
"default": "normal",
|
||||
"description": "Sets the weight (lightness or heaviness of the strokes) for the given font. Possible values:\n -\"thin\"\n -\"extra-light\"\n -\"light\"\n -\"semi-light\"\n -\"normal\" (default)\n -\"medium\"\n -\"semi-bold\"\n -\"bold\"\n -\"extra-bold\"\n -\"black\"\n -\"extra-black\"\n or the corresponding numeric representation of OpenType font weight.",
|
||||
"description": "[deprecated] Define 'weight' within the 'font' object instead.",
|
||||
"oneOf": [
|
||||
{
|
||||
"enum": [
|
||||
@@ -1392,7 +1530,8 @@
|
||||
"minimum": 100,
|
||||
"type": "integer"
|
||||
}
|
||||
]
|
||||
],
|
||||
"deprecated": true
|
||||
},
|
||||
"foreground": {
|
||||
"$ref": "#/definitions/Color",
|
||||
|
||||
105
doc/specs/#1790 - Font features and axes-spec.md
Normal file
105
doc/specs/#1790 - Font features and axes-spec.md
Normal file
@@ -0,0 +1,105 @@
|
||||
---
|
||||
author: Pankaj Bhojwani, pabhojwa@microsoft.com
|
||||
created on: 2021-6-17
|
||||
last updated: 2021-6-23
|
||||
issue id: #1790
|
||||
---
|
||||
|
||||
# Font features and axes of variation
|
||||
|
||||
## Abstract
|
||||
|
||||
This spec outlines how we can allow users to specify font features and axes of variation for fonts in Windows Terminal. Font features include things like being able to specify whether ligatures should be used as well as the specific stylistic set used for a font. Axes of variation commonly include things like weight and slant but can also include fancier things like shadow distance, depending on the font.
|
||||
|
||||
## Inspiration
|
||||
|
||||
Reference: [#1790](https://github.com/microsoft/terminal/issues/1790)
|
||||
|
||||
Currently, if a font has ligatures, we offer no way for a user to disable them. Many users would like the option to do so, and would also like the ability to choose stylistic sets for fonts - for example, at the time of this writing, Cascadia Code offers 4 stylistic sets but we offer no way for users to specify any of them.
|
||||
|
||||
In a similar vein, many fonts allow for setting variations on the font along certain attributes, commonly referred to as 'axes of variation'. We can offer users more font customization options by allowing them to configure these font variations.
|
||||
|
||||
## Solution Design
|
||||
|
||||
### Font features
|
||||
|
||||
It is already possible to pass in a list of [font feature structs](https://docs.microsoft.com/en-us/windows/win32/api/dwrite/ns-dwrite-dwrite_font_feature) to DWrite for it to handle. A font feature struct contains only 2 things:
|
||||
|
||||
1. A font feature tag
|
||||
2. A parameter value
|
||||
|
||||
A font feature tag is constructed using a 4-character feature tag and the parameter value defines how the feature is applied. For most features, the parameter value is simply treated as a binary value - a value of 0 means the feature is not applied and a non-zero value means the feature is applied. For example, a font feature struct like {'ss03', 1} enables stylistic set 3 for the font and a font feature struct like {'liga', 0} disables ligatures. (Technically, the feature tag is _constructed_ with the 4-character tag and is not the 4-character tag itself, but they are treated the same in the example here for brevity's sake).
|
||||
|
||||
Currently, we pass in to DWrite a null value for the list of features to apply to the font. This causes DWrite to automatically apply a ['standard' list](https://github.com/fdwr/TextLayoutSampler/blob/master/DrawableObject.ixx#L802) of font features to the font. Naturally, passing in our own list of font features to DWrite means DWrite will _only_ apply the features we defined, and no longer apply the standard list. Since the standard list contains 11 features, we need to consider how we can allow users to specify 1 additional feature or delete 1 of the standard features without needing to redefine all the others.
|
||||
|
||||
We will do this by allowing users to define a dictionary in their settings.json file, where the keys are the 4-character feature tags and the values are the parameter values. This dictionary will then get applied to our internal dictionary (which will contain the standard list of 11 features with their parameter values), meaning that any new key-value pairs will get added to our dictionary and any existing key-value pairs will get updated. Finally, this 'merged' dictionary will be what we use to construct the list of features to pass into DWrite.
|
||||
|
||||
### Axes of variation
|
||||
|
||||
Specifying axes of variation is done in an extremely similar manner to the way font features are specified - a 4-character tag is used to specify which font axis is being modified and a numerical value is provided to specify the value the axis should be set to. For example, {'slnt', 20} specifies that the 'slant' axis should be set to 20.
|
||||
|
||||
There is also a standard list of axes of variation, and each axis has its own default. We will approach this the same way we approached font features, by allowing users to specify additional features or omit features without needing to redefine the defaults.
|
||||
|
||||
## UI/UX Design
|
||||
|
||||
Users will be able to add a new setting to their font objects (added in [#10433](https://github.com/microsoft/terminal/pull/10433)). The resultant font object may look something like this
|
||||
|
||||
```json
|
||||
"font": {
|
||||
"face": "Cascadia Code",
|
||||
"size": 12,
|
||||
"features": {
|
||||
"ss03": 1,
|
||||
"liga": 0
|
||||
},
|
||||
"axes": {
|
||||
"slnt": 20.5
|
||||
}
|
||||
}
|
||||
```
|
||||
There is one point to note here about clashing. For example, if a user has the old "weight" setting defined _as well as_ a "wght" axis defined, we will only use the "wght" axis value. We prioritize that value for a few reasons:
|
||||
|
||||
1. It is the more recent addition to our settings model. Thus, it is likely that a user that has defined both values probably just forgot to remove the old value.
|
||||
2. It is the more precise value, it is a specific float value whereas the the old "weight" setting is an enum (that eventually gets mapped to a float value).
|
||||
|
||||
## Capabilities
|
||||
|
||||
### Accessibility
|
||||
|
||||
Should not affect accessibility.
|
||||
|
||||
### Security
|
||||
|
||||
Should not affect security.
|
||||
|
||||
### Reliability
|
||||
|
||||
Aside from additional parsing required for the settings file (which inherently offers more locations for parsing to fail), we need to be careful about badly formed/non-existant feature tags or axes specified in the user-defined dictionaries. We must make sure to ignore such declarations (perhaps alongside emitting a warning to the user) and only apply those that are correctly formed and exist.
|
||||
|
||||
### Compatibility
|
||||
|
||||
Older versions of Windows may not have the DWrite updates that allow for defining font features and axes of variation. We must make sure to fallback to the current implementation in these cases.
|
||||
|
||||
### Performance, Power, and Efficiency
|
||||
|
||||
Currently when rendering a run of text, if we detect that the given run is simple we will use a shortcut to obtain the glyphs needed, skipping over an expensive `GetGlyphs` call to DWrite. However, when the default feature list is changed in any way (either by adding a new feature or removing one of the defaults), there is no way for us to detect beforehand how the font glyphs would change.
|
||||
|
||||
This means that as long as the user requests a change to the default font feature list, we will _always_ skip the shortcut and call the expensive `GetGlyphs` function for every run of text.
|
||||
|
||||
This will naturally cause a performance cost that we will have to bear for this feature. However, it is worth noting that there are a fair number of glyphs that will cause a run of text to be deemed "not simple" (and thus cause us to call `GetGlyphs` anyway), for example when using Cascadia Code, any run of text that has the letters 'i', 'j', 'l', 'n', 'w' or 'x' is not considered simple (because those glyphs have localized variants).
|
||||
|
||||
## Potential Issues
|
||||
|
||||
See performance issues above.
|
||||
|
||||
## Future considerations
|
||||
|
||||
DWrite additionally offers the ability to vary the font features across runs of text. However, for our initial implementation of this feature, we will only apply font features to the entire buffer. If/when we decide to allow specifying font features for particular runs of text, we can lean into our existing mechanisms of splitting up runs of text to implement that.
|
||||
|
||||
We will also need to consider how we want to represent this in the settings UI. This is slightly more complex than other settings since users should be allowed to manually input 4-character tags.
|
||||
|
||||
## Resources
|
||||
|
||||
[DWRITE_FONT_FEATURE structure](https://docs.microsoft.com/en-us/windows/win32/api/dwrite/ns-dwrite-dwrite_font_feature)
|
||||
|
||||
[DWRITE_FONT_AXIS_VALUE structure](https://docs.microsoft.com/en-us/windows/win32/api/dwrite_3/ns-dwrite_3-dwrite_font_axis_value)
|
||||
@@ -28,7 +28,7 @@ Below is the schedule for when milestones will be included in release builds of
|
||||
| 2021-01-31 | [1.6] in Windows Terminal Preview<br>[1.5] in Windows Terminal | [Windows Terminal Preview 1.6 Release](https://devblogs.microsoft.com/commandline/windows-terminal-preview-1-6-release/) |
|
||||
| 2021-03-01 | [1.7] in Windows Terminal Preview<br>[1.6] in Windows Terminal | [Windows Terminal Preview 1.7 Release](https://devblogs.microsoft.com/commandline/windows-terminal-preview-1-7-release/) |
|
||||
| 2021-04-14 | [1.8] in Windows Terminal Preview<br>[1.7] in Windows Terminal | [Windows Terminal Preview 1.8 Release](https://devblogs.microsoft.com/commandline/windows-terminal-preview-1-8-release/) |
|
||||
| 2021-05-31 | [1.9] in Windows Terminal Preview<br>[1.8] in Windows Terminal | |
|
||||
| 2021-05-31 | [1.9] in Windows Terminal Preview<br>[1.8] in Windows Terminal | [Windows Terminal Preview 1.9 Release](https://devblogs.microsoft.com/commandline/windows-terminal-preview-1-9-release/) |
|
||||
| 2021-07-31 | 1.10 in Windows Terminal Preview<br>[1.9] in Windows Terminal | |
|
||||
| 2021-08-30 | 1.11 in Windows Terminal Preview<br>1.10 in Windows Terminal | |
|
||||
| 2021-10-31 | 1.12 in Windows Terminal Preview<br>1.11 in Windows Terminal | |
|
||||
|
||||
BIN
res/Cascadia.ttf
BIN
res/Cascadia.ttf
Binary file not shown.
Binary file not shown.
@@ -6,16 +6,3 @@ The images in this directory do not fall under the same [license](https://raw.gi
|
||||
of the Windows Terminal code.
|
||||
|
||||
Please consult the [license](./LICENSE) in this directory for terms applicable to the image assets in this directory.
|
||||
|
||||
## Fonts
|
||||
|
||||
The fonts in this directory do not fall under the same [license](https://raw.githubusercontent.com/microsoft/terminal/main/LICENSE) as the rest
|
||||
of the Windows Terminal code.
|
||||
|
||||
Please consult the [license](https://raw.githubusercontent.com/microsoft/cascadia-code/main/LICENSE) in the
|
||||
[microsoft/cascadia-code](https://github.com/microsoft/cascadia-code) repository for terms applicable to the fonts in this directory.
|
||||
|
||||
### Fonts Included
|
||||
|
||||
* Cascadia Code, Cascadia Mono (2102.25)
|
||||
* from microsoft/cascadia-code@911dc421f333e3b72b97381d16fee5b71eb48f04
|
||||
|
||||
BIN
res/fonts/CascadiaCode.ttf
Normal file
BIN
res/fonts/CascadiaCode.ttf
Normal file
Binary file not shown.
BIN
res/fonts/CascadiaCodeItalic.ttf
Normal file
BIN
res/fonts/CascadiaCodeItalic.ttf
Normal file
Binary file not shown.
BIN
res/fonts/CascadiaMono.ttf
Normal file
BIN
res/fonts/CascadiaMono.ttf
Normal file
Binary file not shown.
BIN
res/fonts/CascadiaMonoItalic.ttf
Normal file
BIN
res/fonts/CascadiaMonoItalic.ttf
Normal file
Binary file not shown.
12
res/fonts/README.md
Normal file
12
res/fonts/README.md
Normal file
@@ -0,0 +1,12 @@
|
||||
# Windows Terminal and Console Assets (Fonts)
|
||||
|
||||
The fonts in this directory do not fall under the same [license](https://raw.githubusercontent.com/microsoft/terminal/main/LICENSE) as the rest
|
||||
of the Windows Terminal code.
|
||||
|
||||
Please consult the [license](https://raw.githubusercontent.com/microsoft/cascadia-code/main/LICENSE) in the
|
||||
[microsoft/cascadia-code](https://github.com/microsoft/cascadia-code) repository for terms applicable to the fonts in this directory.
|
||||
|
||||
### Fonts Included
|
||||
|
||||
* Cascadia Code, Cascadia Mono (2106.17)
|
||||
* from microsoft/cascadia-code@fb0bce69c1c12f6c298b8bc1c1d181868f5daa9a
|
||||
@@ -140,12 +140,12 @@
|
||||
<!-- **END VC LIBS HACK** -->
|
||||
|
||||
<!-- This is required to get the package dependency in the AppXManifest. -->
|
||||
<Import Project="..\..\..\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('..\..\..\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets')" />
|
||||
<Import Project="..\..\..\packages\Microsoft.UI.Xaml.2.6.2-prerelease.210818003\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('..\..\..\packages\Microsoft.UI.Xaml.2.6.2-prerelease.210818003\build\native\Microsoft.UI.Xaml.targets')" />
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('..\..\..\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets'))" />
|
||||
<Error Condition="!Exists('..\..\..\packages\Microsoft.UI.Xaml.2.6.2-prerelease.210818003\build\native\Microsoft.UI.Xaml.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.UI.Xaml.2.6.2-prerelease.210818003\build\native\Microsoft.UI.Xaml.targets'))" />
|
||||
</Target>
|
||||
|
||||
|
||||
|
||||
@@ -9,30 +9,22 @@ namespace winrt::SampleApp::implementation
|
||||
|
||||
IXamlType GetXamlType(::winrt::Windows::UI::Xaml::Interop::TypeName const& type)
|
||||
{
|
||||
return AppProvider()->GetXamlType(type);
|
||||
return _appProvider.GetXamlType(type);
|
||||
}
|
||||
|
||||
IXamlType GetXamlType(::winrt::hstring const& fullName)
|
||||
{
|
||||
return AppProvider()->GetXamlType(fullName);
|
||||
return _appProvider.GetXamlType(fullName);
|
||||
}
|
||||
|
||||
::winrt::com_array<::winrt::Windows::UI::Xaml::Markup::XmlnsDefinition> GetXmlnsDefinitions()
|
||||
{
|
||||
return AppProvider()->GetXmlnsDefinitions();
|
||||
return _appProvider.GetXmlnsDefinitions();
|
||||
}
|
||||
|
||||
private:
|
||||
bool _contentLoaded{ false };
|
||||
std::shared_ptr<XamlMetaDataProvider> _appProvider;
|
||||
std::shared_ptr<XamlMetaDataProvider> AppProvider()
|
||||
{
|
||||
if (!_appProvider)
|
||||
{
|
||||
_appProvider = std::make_shared<XamlMetaDataProvider>();
|
||||
}
|
||||
return _appProvider;
|
||||
}
|
||||
winrt::SampleApp::XamlMetaDataProvider _appProvider;
|
||||
};
|
||||
|
||||
template<typename D, typename... I>
|
||||
|
||||
@@ -3,9 +3,11 @@
|
||||
|
||||
#include "pch.h"
|
||||
#include "MyPage.h"
|
||||
#include "MySettings.h"
|
||||
#include <LibraryResources.h>
|
||||
#include "MyPage.g.cpp"
|
||||
#include "..\..\..\src\cascadia\UnitTests_Control\MockControlSettings.h"
|
||||
#include "..\..\..\src\types\inc\utils.hpp"
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
using namespace winrt::Microsoft::Terminal;
|
||||
@@ -26,9 +28,21 @@ namespace winrt::SampleApp::implementation
|
||||
|
||||
void MyPage::Create()
|
||||
{
|
||||
TerminalConnection::EchoConnection conn{};
|
||||
auto settings = winrt::make_self<ControlUnitTests::MockControlSettings>();
|
||||
auto settings = winrt::make_self<MySettings>();
|
||||
|
||||
auto connectionSettings{ TerminalConnection::ConptyConnection::CreateSettings(L"cmd.exe /k echo This TermControl is hosted in-proc...",
|
||||
winrt::hstring{},
|
||||
L"",
|
||||
nullptr,
|
||||
32,
|
||||
80,
|
||||
winrt::guid()) };
|
||||
|
||||
// "Microsoft.Terminal.TerminalConnection.ConptyConnection"
|
||||
winrt::hstring myClass{ winrt::name_of<TerminalConnection::ConptyConnection>() };
|
||||
TerminalConnection::ConnectionInformation connectInfo{ myClass, connectionSettings };
|
||||
|
||||
TerminalConnection::ITerminalConnection conn{ TerminalConnection::ConnectionInformation::CreateConnection(connectInfo) };
|
||||
Control::TermControl control{ *settings, conn };
|
||||
|
||||
InProcContent().Children().Append(control);
|
||||
@@ -39,6 +53,207 @@ namespace winrt::SampleApp::implementation
|
||||
});
|
||||
}
|
||||
|
||||
static wil::unique_process_information _createHostClassProcess(const winrt::guid& g)
|
||||
{
|
||||
auto guidStr{ ::Microsoft::Console::Utils::GuidToString(g) };
|
||||
|
||||
// Create an event that the content process will use to signal it is
|
||||
// ready to go. We won't need the event after this function, so the
|
||||
// unique_event will clean up our handle when we leave this scope. The
|
||||
// ContentProcess is responsible for cleaning up its own handle.
|
||||
wil::unique_event ev{ CreateEvent(nullptr, true, false, L"contentProcessStarted") };
|
||||
// Make sure to mark this handle as inheritable! Even with
|
||||
// bInheritHandles=true, this is only inherited when it's explicitly
|
||||
// allowed to be.
|
||||
SetHandleInformation(ev.get(), HANDLE_FLAG_INHERIT, 1);
|
||||
|
||||
// god bless, fmt::format will format a HANDLE like `0xa80`
|
||||
std::wstring commandline{
|
||||
fmt::format(L"windowsterminal.exe --content {} --signal {}", guidStr, ev.get())
|
||||
};
|
||||
|
||||
STARTUPINFO siOne{ 0 };
|
||||
siOne.cb = sizeof(STARTUPINFOW);
|
||||
wil::unique_process_information piOne;
|
||||
auto succeeded = CreateProcessW(
|
||||
nullptr,
|
||||
commandline.data(),
|
||||
nullptr, // lpProcessAttributes
|
||||
nullptr, // lpThreadAttributes
|
||||
true, // bInheritHandles
|
||||
CREATE_UNICODE_ENVIRONMENT, // dwCreationFlags
|
||||
nullptr, // lpEnvironment
|
||||
nullptr, // startingDirectory
|
||||
&siOne, // lpStartupInfo
|
||||
&piOne // lpProcessInformation
|
||||
);
|
||||
THROW_IF_WIN32_BOOL_FALSE(succeeded);
|
||||
|
||||
// Wait for the child process to signal that they're ready.
|
||||
WaitForSingleObject(ev.get(), INFINITE);
|
||||
|
||||
return std::move(piOne);
|
||||
}
|
||||
|
||||
winrt::fire_and_forget MyPage::_writeToLog(std::wstring_view str)
|
||||
{
|
||||
winrt::hstring copy{ str };
|
||||
// Switch back to the UI thread.
|
||||
co_await resume_foreground(Dispatcher());
|
||||
winrt::WUX::Controls::TextBlock block;
|
||||
block.Text(copy);
|
||||
Log().Children().Append(block);
|
||||
}
|
||||
|
||||
winrt::fire_and_forget MyPage::CreateClicked(const IInspectable& sender,
|
||||
const WUX::Input::TappedRoutedEventArgs& eventArgs)
|
||||
{
|
||||
auto guidString = GuidInput().Text();
|
||||
|
||||
// Capture calling context.
|
||||
winrt::apartment_context ui_thread;
|
||||
|
||||
auto canConvert = guidString.size() == 38 &&
|
||||
guidString.front() == '{' &&
|
||||
guidString.back() == '}';
|
||||
bool tryingToAttach = false;
|
||||
winrt::guid contentGuid{ ::Microsoft::Console::Utils::CreateGuid() };
|
||||
|
||||
if (canConvert)
|
||||
{
|
||||
GUID result{};
|
||||
if (SUCCEEDED(IIDFromString(guidString.c_str(), &result)))
|
||||
{
|
||||
contentGuid = result;
|
||||
tryingToAttach = true;
|
||||
}
|
||||
}
|
||||
_writeToLog(tryingToAttach ? L"Attaching to existing content process" : L"Creating new content process");
|
||||
|
||||
co_await winrt::resume_background();
|
||||
if (!tryingToAttach)
|
||||
{
|
||||
// Spawn a wt.exe, with the guid on the commandline
|
||||
piContentProcess = std::move(_createHostClassProcess(contentGuid));
|
||||
}
|
||||
|
||||
// THIS MUST TAKE PLACE AFTER _createHostClassProcess.
|
||||
// * If we're creating a new OOP control, _createHostClassProcess will
|
||||
// spawn the process that will actually host the ContentProcess
|
||||
// object.
|
||||
// * If we're attaching, then that process already exists.
|
||||
Control::ContentProcess content{nullptr};
|
||||
try
|
||||
{
|
||||
content = create_instance<Control::ContentProcess>(contentGuid, CLSCTX_LOCAL_SERVER);
|
||||
}
|
||||
catch (winrt::hresult_error hr)
|
||||
{
|
||||
_writeToLog(L"CreateInstance the ContentProces object");
|
||||
_writeToLog(fmt::format(L" HR ({}): {}", hr.code(), hr.message().c_str()));
|
||||
co_return; // be sure to co_return or we'll fall through to the part where we clear the log
|
||||
}
|
||||
|
||||
if (content == nullptr)
|
||||
{
|
||||
_writeToLog(L"Failed to connect to the ContentProces object. It may not have been started fast enough.");
|
||||
co_return; // be sure to co_return or we'll fall through to the part where we clear the log
|
||||
}
|
||||
|
||||
TerminalConnection::ConnectionInformation connectInfo{ nullptr };
|
||||
Control::IControlSettings settings{ *winrt::make_self<implementation::MySettings>() };
|
||||
|
||||
// When creating a terminal for the first time, pass it a connection
|
||||
// info
|
||||
//
|
||||
// otherwise, when attaching to an existing one, just pass null, because
|
||||
// we don't need the connection info.
|
||||
if (!tryingToAttach)
|
||||
{
|
||||
auto connectionSettings{ TerminalConnection::ConptyConnection::CreateSettings(L"cmd.exe /k echo This TermControl is hosted out-of-proc...",
|
||||
winrt::hstring{},
|
||||
L"",
|
||||
nullptr,
|
||||
32,
|
||||
80,
|
||||
winrt::guid()) };
|
||||
|
||||
// "Microsoft.Terminal.TerminalConnection.ConptyConnection"
|
||||
winrt::hstring myClass{ winrt::name_of<TerminalConnection::ConptyConnection>() };
|
||||
connectInfo = TerminalConnection::ConnectionInformation(myClass, connectionSettings);
|
||||
|
||||
if (!content.Initialize(settings, connectInfo))
|
||||
{
|
||||
_writeToLog(L"Failed to Initialize the ContentProces object.");
|
||||
co_return; // be sure to co_return or we'll fall through to the part where we clear the log
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// If we're attaching, we don't really need to do anything special.
|
||||
}
|
||||
|
||||
// Switch back to the UI thread.
|
||||
co_await ui_thread;
|
||||
|
||||
// Create the XAML control that will be attached to the content process.
|
||||
// We're not passing in a connection, because the contentGuid will be used instead.
|
||||
Control::TermControl control{ contentGuid, settings, nullptr };
|
||||
control.RaiseNotice([this](auto&&, auto& args) {
|
||||
_writeToLog(L"Content process died, probably.");
|
||||
_writeToLog(args.Message());
|
||||
OutOfProcContent().Children().Clear();
|
||||
GuidInput().Text(L"");
|
||||
if (piContentProcess.hProcess)
|
||||
{
|
||||
piContentProcess.reset();
|
||||
}
|
||||
});
|
||||
control.ConnectionStateChanged([this, control](auto&&, auto&) {
|
||||
const auto newConnectionState = control.ConnectionState();
|
||||
if (newConnectionState == TerminalConnection::ConnectionState::Closed)
|
||||
{
|
||||
_writeToLog(L"Connection was closed");
|
||||
OutOfProcContent().Children().Clear();
|
||||
GuidInput().Text(L"");
|
||||
if (piContentProcess.hProcess)
|
||||
{
|
||||
piContentProcess.reset();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Log().Children().Clear();
|
||||
OutOfProcContent().Children().Append(control);
|
||||
|
||||
if (!tryingToAttach)
|
||||
{
|
||||
auto guidStr{ ::Microsoft::Console::Utils::GuidToString(contentGuid) };
|
||||
GuidInput().Text(guidStr);
|
||||
}
|
||||
}
|
||||
|
||||
void MyPage::CloseClicked(const IInspectable& /*sender*/,
|
||||
const WUX::Input::TappedRoutedEventArgs& /*eventArgs*/)
|
||||
{
|
||||
OutOfProcContent().Children().Clear();
|
||||
GuidInput().Text(L"");
|
||||
if (piContentProcess.hProcess)
|
||||
{
|
||||
piContentProcess.reset();
|
||||
}
|
||||
}
|
||||
|
||||
void MyPage::KillClicked(const IInspectable& /*sender*/,
|
||||
const WUX::Input::TappedRoutedEventArgs& /*eventArgs*/)
|
||||
{
|
||||
if (piContentProcess.hProcess)
|
||||
{
|
||||
TerminateProcess(piContentProcess.hProcess, (UINT)-1);
|
||||
piContentProcess.reset();
|
||||
}
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Gets the title of the currently focused terminal control. If there
|
||||
// isn't a control selected for any reason, returns "Windows Terminal"
|
||||
|
||||
@@ -14,11 +14,18 @@ namespace winrt::SampleApp::implementation
|
||||
MyPage();
|
||||
|
||||
void Create();
|
||||
|
||||
hstring Title();
|
||||
|
||||
winrt::fire_and_forget CreateClicked(const IInspectable& sender, const Windows::UI::Xaml::Input::TappedRoutedEventArgs& eventArgs);
|
||||
void CloseClicked(const IInspectable& sender, const Windows::UI::Xaml::Input::TappedRoutedEventArgs& eventArgs);
|
||||
void KillClicked(const IInspectable& sender, const Windows::UI::Xaml::Input::TappedRoutedEventArgs& eventArgs);
|
||||
|
||||
private:
|
||||
friend struct MyPageT<MyPage>; // for Xaml to bind events
|
||||
|
||||
wil::unique_process_information piContentProcess;
|
||||
|
||||
winrt::fire_and_forget _writeToLog(std::wstring_view str);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -19,10 +19,29 @@
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<Button x:Name="TabRow"
|
||||
Grid.Row="0">
|
||||
"Tabs"
|
||||
</Button>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBox x:Name="GuidInput"
|
||||
Width="400"
|
||||
PlaceholderText="{}{guid here}" />
|
||||
<Button x:Name="CreateOopControl"
|
||||
Grid.Row="0"
|
||||
Tapped="CreateClicked">
|
||||
Create
|
||||
</Button>
|
||||
<Button x:Name="CloseOopControl"
|
||||
Grid.Row="0"
|
||||
Margin="4,0,0,0"
|
||||
Tapped="CloseClicked">
|
||||
Close
|
||||
</Button>
|
||||
<Button x:Name="KillOopControl"
|
||||
Grid.Row="0"
|
||||
Margin="4,0,0,0"
|
||||
Tapped="KillClicked">
|
||||
Kill
|
||||
</Button>
|
||||
|
||||
</StackPanel>
|
||||
|
||||
<Grid x:Name="TabContent"
|
||||
Grid.Row="1"
|
||||
@@ -41,14 +60,26 @@
|
||||
VerticalAlignment="Stretch"
|
||||
Background="#ff0000" />
|
||||
|
||||
<Grid x:Name="OutOfProcContent"
|
||||
Grid.Column="1"
|
||||
Padding="16"
|
||||
<Grid Grid.Column="1"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
Background="#0000ff" />
|
||||
VerticalAlignment="Stretch">
|
||||
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<StackPanel x:Name="Log"
|
||||
Grid.Row="0"
|
||||
Orientation="Vertical" />
|
||||
|
||||
<Grid x:Name="OutOfProcContent"
|
||||
Grid.Row="1"
|
||||
Padding="16"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
Background="#0000ff" />
|
||||
</Grid>
|
||||
|
||||
</Grid>
|
||||
|
||||
|
||||
@@ -4,17 +4,19 @@ Licensed under the MIT license.
|
||||
--*/
|
||||
#pragma once
|
||||
#include "../../inc/cppwinrt_utils.h"
|
||||
#include "../types/inc/colorTable.hpp"
|
||||
|
||||
#include <DefaultSettings.h>
|
||||
#include <conattrs.hpp>
|
||||
#include "MySettings.g.h"
|
||||
|
||||
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
|
||||
{
|
||||
struct MySettings : MySettingsT<MySettings>
|
||||
{
|
||||
public:
|
||||
MySettings() = default;
|
||||
|
||||
// --------------------------- Core Settings ---------------------------
|
||||
// All of these settings are defined in ICoreSettings.
|
||||
|
||||
@@ -42,6 +44,8 @@ namespace winrt::SampleApp::implementation
|
||||
winrt::Microsoft::Terminal::Core::ICoreAppearance UnfocusedAppearance() { return {}; };
|
||||
|
||||
WINRT_PROPERTY(bool, TrimBlockSelection, false);
|
||||
WINRT_PROPERTY(bool, DetectURLs, true);
|
||||
WINRT_PROPERTY(bool, IntenseIsBright, true);
|
||||
// ------------------------ End of Core Settings -----------------------
|
||||
|
||||
WINRT_PROPERTY(winrt::hstring, ProfileName);
|
||||
@@ -79,7 +83,10 @@ namespace winrt::SampleApp::implementation
|
||||
|
||||
WINRT_PROPERTY(winrt::hstring, PixelShaderPath);
|
||||
|
||||
WINRT_PROPERTY(bool, DetectURLs, true);
|
||||
WINRT_PROPERTY(IFontFeatureMap, FontFeatures);
|
||||
WINRT_PROPERTY(IFontAxesMap, FontAxes);
|
||||
|
||||
WINRT_PROPERTY(bool, IntenseIsBold, true);
|
||||
|
||||
private:
|
||||
std::array<winrt::Microsoft::Terminal::Core::Color, COLOR_TABLE_SIZE> _ColorTable;
|
||||
@@ -88,6 +95,14 @@ namespace winrt::SampleApp::implementation
|
||||
winrt::Microsoft::Terminal::Core::Color GetColorTableEntry(int32_t index) noexcept { return _ColorTable.at(index); }
|
||||
std::array<winrt::Microsoft::Terminal::Core::Color, 16> ColorTable() { return _ColorTable; }
|
||||
void ColorTable(std::array<winrt::Microsoft::Terminal::Core::Color, 16> /*colors*/) {}
|
||||
|
||||
MySettings()
|
||||
{
|
||||
const auto campbellSpan = ::Microsoft::Console::Utils::CampbellColorTable();
|
||||
std::transform(campbellSpan.begin(), campbellSpan.end(), _ColorTable.begin(), [](auto&& color) {
|
||||
return static_cast<winrt::Microsoft::Terminal::Core::Color>(til::color{ color });
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
</PropertyGroup>
|
||||
<Import Project="..\..\..\common.openconsole.props" Condition="'$(OpenConsoleDir)'==''" />
|
||||
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.pre.props" />
|
||||
<Import Project="..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.2\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props" Condition="Exists('..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.2\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props')" />
|
||||
<Import Project="..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props" Condition="Exists('..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props')" />
|
||||
<ItemDefinitionGroup>
|
||||
|
||||
<ClCompile>
|
||||
@@ -147,14 +147,14 @@
|
||||
<!-- ========================= Globals ======================== -->
|
||||
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.post.props" />
|
||||
|
||||
<Import Project="..\..\..\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('..\..\..\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets')" />
|
||||
<Import Project="..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.2\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets" Condition="Exists('..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.2\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" />
|
||||
<Import Project="..\..\..\packages\Microsoft.UI.Xaml.2.6.2-prerelease.210818003\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('..\..\..\packages\Microsoft.UI.Xaml.2.6.2-prerelease.210818003\build\native\Microsoft.UI.Xaml.targets')" />
|
||||
<Import Project="..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets" Condition="Exists('..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" />
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('$(OpenConsoleDir)\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(OpenConsoleDir)\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets'))" />
|
||||
<Error Condition="!Exists('$(OpenConsoleDir)\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.2\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(OpenConsoleDir)\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.2\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets'))" />
|
||||
<Error Condition="!Exists('$(OpenConsoleDir)\packages\Microsoft.UI.Xaml.2.6.2-prerelease.210818003\build\native\Microsoft.UI.Xaml.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(OpenConsoleDir)\packages\Microsoft.UI.Xaml.2.6.2-prerelease.210818003\build\native\Microsoft.UI.Xaml.targets'))" />
|
||||
<Error Condition="!Exists('$(OpenConsoleDir)\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(OpenConsoleDir)\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets'))" />
|
||||
</Target>
|
||||
|
||||
<!--
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
</PropertyGroup>
|
||||
<Import Project="..\..\..\..\common.openconsole.props" Condition="'$(OpenConsoleDir)'==''" />
|
||||
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.pre.props" />
|
||||
<Import Project="$(OpenConsoleDir)packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.2\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props" Condition="Exists('$(OpenConsoleDir)packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.2\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props')" />
|
||||
<Import Project="$(OpenConsoleDir)packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props" Condition="Exists('$(OpenConsoleDir)packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props')" />
|
||||
<!-- ========================= XAML files ======================== -->
|
||||
<ItemGroup>
|
||||
<!-- DON'T PUT XAML FILES HERE! Put them in SampleAppLib.vcxproj -->
|
||||
@@ -48,6 +48,10 @@
|
||||
<Private>true</Private>
|
||||
<CopyLocalSatelliteAssemblies>true</CopyLocalSatelliteAssemblies>
|
||||
</ProjectReference>
|
||||
|
||||
<ProjectReference Include="$(OpenConsoleDir)src\types\lib\types.vcxproj">
|
||||
<Project>{18D09A24-8240-42D6-8CB6-236EEE820263}</Project>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -76,14 +80,14 @@
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
<Import Project="$(OpenConsoleDir)packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('$(OpenConsoleDir)packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets')" />
|
||||
<Import Project="$(OpenConsoleDir)packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.2\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets" Condition="Exists('$(OpenConsoleDir)packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.2\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" />
|
||||
<Import Project="$(OpenConsoleDir)packages\Microsoft.UI.Xaml.2.6.2-prerelease.210818003\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('$(OpenConsoleDir)packages\Microsoft.UI.Xaml.2.6.2-prerelease.210818003\build\native\Microsoft.UI.Xaml.targets')" />
|
||||
<Import Project="$(OpenConsoleDir)packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets" Condition="Exists('$(OpenConsoleDir)packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" />
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('$(OpenConsoleDir)\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(OpenConsoleDir)\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets'))" />
|
||||
<Error Condition="!Exists('$(OpenConsoleDir)\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.2\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(OpenConsoleDir)\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.2\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets'))" />
|
||||
<Error Condition="!Exists('$(OpenConsoleDir)\packages\Microsoft.UI.Xaml.2.6.2-prerelease.210818003\build\native\Microsoft.UI.Xaml.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(OpenConsoleDir)\packages\Microsoft.UI.Xaml.2.6.2-prerelease.210818003\build\native\Microsoft.UI.Xaml.targets'))" />
|
||||
<Error Condition="!Exists('$(OpenConsoleDir)\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(OpenConsoleDir)\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets'))" />
|
||||
</Target>
|
||||
|
||||
<ItemDefinitionGroup>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Microsoft.Toolkit.Win32.UI.XamlApplication" version="6.1.2" targetFramework="native" />
|
||||
<package id="Microsoft.UI.Xaml" version="2.5.0-prerelease.201202003" targetFramework="native" />
|
||||
<package id="Microsoft.Toolkit.Win32.UI.XamlApplication" version="6.1.3" targetFramework="native" />
|
||||
<package id="Microsoft.UI.Xaml" version="2.6.2-prerelease.210818003" targetFramework="native" />
|
||||
<package id="Microsoft.Windows.CppWinRT" version="2.0.210309.3" targetFramework="native" />
|
||||
</packages>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<!-- Windows 10 1903 -->
|
||||
<!-- See https://docs.microsoft.com/en-us/windows/apps/desktop/modernize/xaml-islands -->
|
||||
<!-- "maxversiontested" is CASE SENSITIVE. Do not change this.-->
|
||||
<maxversiontested Id="10.0.19041.0"/>
|
||||
<maxversiontested Id="10.0.18362.0"/>
|
||||
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
|
||||
</application>
|
||||
</compatibility>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.2\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props" Condition="Exists('..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.2\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props')" />
|
||||
<Import Project="..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props" Condition="Exists('..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props')" />
|
||||
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{b4427499-9fde-4208-b456-5bc580637633}</ProjectGuid>
|
||||
@@ -120,16 +120,16 @@
|
||||
|
||||
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.post.props" />
|
||||
|
||||
<Import Project="..\..\..\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('..\..\..\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets')" />
|
||||
<Import Project="..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.2\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets" Condition="Exists('..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.2\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" />
|
||||
<Import Project="..\..\..\packages\Microsoft.UI.Xaml.2.6.2-prerelease.210818003\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('..\..\..\packages\Microsoft.UI.Xaml.2.6.2-prerelease.210818003\build\native\Microsoft.UI.Xaml.targets')" />
|
||||
<Import Project="..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets" Condition="Exists('..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" />
|
||||
<Import Project="..\..\..\packages\Microsoft.VCRTForwarders.140.1.0.4\build\native\Microsoft.VCRTForwarders.140.targets" Condition="Exists('..\..\..\packages\Microsoft.VCRTForwarders.140.1.0.4\build\native\Microsoft.VCRTForwarders.140.targets')" />
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('..\..\..\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets'))" />
|
||||
<Error Condition="!Exists('..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.2\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.2\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props'))" />
|
||||
<Error Condition="!Exists('..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.2\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.2\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets'))" />
|
||||
<Error Condition="!Exists('..\..\..\packages\Microsoft.UI.Xaml.2.6.2-prerelease.210818003\build\native\Microsoft.UI.Xaml.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.UI.Xaml.2.6.2-prerelease.210818003\build\native\Microsoft.UI.Xaml.targets'))" />
|
||||
<Error Condition="!Exists('..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props'))" />
|
||||
<Error Condition="!Exists('..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets'))" />
|
||||
<Error Condition="!Exists('..\..\..\packages\Microsoft.VCRTForwarders.140.1.0.4\build\native\Microsoft.VCRTForwarders.140.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.VCRTForwarders.140.1.0.4\build\native\Microsoft.VCRTForwarders.140.targets'))" />
|
||||
</Target>
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Microsoft.Windows.CppWinRT" version="2.0.210309.3" targetFramework="native" />
|
||||
<package id="Microsoft.Toolkit.Win32.UI.XamlApplication" version="6.1.2" targetFramework="native" />
|
||||
<package id="Microsoft.UI.Xaml" version="2.5.0-prerelease.201202003" targetFramework="native" />
|
||||
<package id="Microsoft.Toolkit.Win32.UI.XamlApplication" version="6.1.3" targetFramework="native" />
|
||||
<package id="Microsoft.UI.Xaml" version="2.6.2-prerelease.210818003" targetFramework="native" />
|
||||
<package id="Microsoft.VCRTForwarders.140" version="1.0.4" targetFramework="native" />
|
||||
</packages>
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>16.0</VCProjectVersion>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<ProjectGuid>{9cf74355-f018-4c19-81ad-9dc6b7f2c6f5}</ProjectGuid>
|
||||
<RootNamespace>apimswincoresynchl120</RootNamespace>
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(SolutionDir)src\common.build.pre.props" />
|
||||
<ItemGroup>
|
||||
<ClCompile Include="main.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="definitions.def" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(SolutionDir)src\common.build.post.props" />
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>kernel32.lib</AdditionalDependencies>
|
||||
<ModuleDefinitionFile>definitions.def</ModuleDefinitionFile>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,30 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Resource Files">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="main.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Natvis Include="$(SolutionDir)tools\ConsoleTypes.natvis" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="definitions.def">
|
||||
<Filter>Source Files</Filter>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
19
src/api-ms-win-core-synch-l1-2-0/definitions.def
Normal file
19
src/api-ms-win-core-synch-l1-2-0/definitions.def
Normal file
@@ -0,0 +1,19 @@
|
||||
LIBRARY
|
||||
EXPORTS
|
||||
DeleteSynchronizationBarrier = kernel32.DeleteSynchronizationBarrier
|
||||
EnterSynchronizationBarrier = kernel32.EnterSynchronizationBarrier
|
||||
InitOnceBeginInitialize = kernel32.InitOnceBeginInitialize
|
||||
InitOnceComplete = kernel32.InitOnceComplete
|
||||
InitOnceExecuteOnce = kernel32.InitOnceExecuteOnce
|
||||
InitOnceInitialize = kernel32.InitOnceInitialize
|
||||
InitializeConditionVariable = kernel32.InitializeConditionVariable
|
||||
InitializeSynchronizationBarrier = kernel32.InitializeSynchronizationBarrier
|
||||
SignalObjectAndWait = kernel32.SignalObjectAndWait
|
||||
Sleep = kernel32.Sleep
|
||||
SleepConditionVariableCS = kernel32.SleepConditionVariableCS
|
||||
SleepConditionVariableSRW = kernel32.SleepConditionVariableSRW
|
||||
WaitOnAddress
|
||||
WakeAllConditionVariable = kernel32.WakeAllConditionVariable
|
||||
WakeByAddressAll
|
||||
WakeByAddressSingle
|
||||
WakeConditionVariable = kernel32.WakeConditionVariable
|
||||
189
src/api-ms-win-core-synch-l1-2-0/main.cpp
Normal file
189
src/api-ms-win-core-synch-l1-2-0/main.cpp
Normal file
@@ -0,0 +1,189 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
//
|
||||
// The code in this file was adapted from the STL on the 2021-07-05. Commit:
|
||||
// https://github.com/microsoft/STL/blob/e745bad3b1d05b5b19ec652d68abb37865ffa454/stl/src/atomic_wait.cpp
|
||||
//
|
||||
// It backports the following Windows 8 functions to Windows 7:
|
||||
// * WaitOnAddress
|
||||
// * WakeByAddressSingle
|
||||
// * WakeByAddressAll
|
||||
//
|
||||
|
||||
#include <cstdint>
|
||||
#include <new>
|
||||
|
||||
#include <winsdkver.h>
|
||||
#define _WIN32_WINNT 0x0601
|
||||
#include <sdkddkver.h>
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#define NOMINMAX
|
||||
#include <Windows.h>
|
||||
#include <intrin.h>
|
||||
|
||||
namespace
|
||||
{
|
||||
class [[nodiscard]] SRWLockGuard
|
||||
{
|
||||
public:
|
||||
explicit SRWLockGuard(SRWLOCK & lock) noexcept :
|
||||
_lock(&lock)
|
||||
{
|
||||
AcquireSRWLockExclusive(_lock);
|
||||
}
|
||||
|
||||
~SRWLockGuard()
|
||||
{
|
||||
ReleaseSRWLockExclusive(_lock);
|
||||
}
|
||||
|
||||
SRWLockGuard(const SRWLockGuard&) = delete;
|
||||
SRWLockGuard& operator=(const SRWLockGuard&) = delete;
|
||||
|
||||
SRWLockGuard(SRWLockGuard &&) = delete;
|
||||
SRWLockGuard& operator=(SRWLockGuard&&) = delete;
|
||||
|
||||
private:
|
||||
SRWLOCK* _lock;
|
||||
};
|
||||
|
||||
struct WaitContext
|
||||
{
|
||||
const volatile void* address;
|
||||
WaitContext* next;
|
||||
WaitContext* prev;
|
||||
CONDITION_VARIABLE cv;
|
||||
};
|
||||
|
||||
struct [[nodiscard]] GuardedWaitContext : WaitContext
|
||||
{
|
||||
GuardedWaitContext(const volatile void* storage, WaitContext* head) noexcept :
|
||||
WaitContext{ storage, head, head->prev, CONDITION_VARIABLE_INIT }
|
||||
{
|
||||
prev->next = this;
|
||||
next->prev = this;
|
||||
}
|
||||
|
||||
~GuardedWaitContext()
|
||||
{
|
||||
const auto n = next;
|
||||
const auto p = prev;
|
||||
next->prev = p;
|
||||
prev->next = n;
|
||||
}
|
||||
|
||||
GuardedWaitContext(const GuardedWaitContext&) = delete;
|
||||
GuardedWaitContext& operator=(const GuardedWaitContext&) = delete;
|
||||
|
||||
GuardedWaitContext(GuardedWaitContext &&) = delete;
|
||||
GuardedWaitContext& operator=(GuardedWaitContext&&) = delete;
|
||||
};
|
||||
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4324) // structure was padded due to alignment specifier
|
||||
struct alignas(std::hardware_destructive_interference_size) WaitTableEntry
|
||||
{
|
||||
SRWLOCK lock = SRWLOCK_INIT;
|
||||
WaitContext head = { nullptr, &head, &head, CONDITION_VARIABLE_INIT };
|
||||
};
|
||||
#pragma warning(pop)
|
||||
|
||||
[[nodiscard]] WaitTableEntry& GetWaitTableEntry(const volatile void* const storage) noexcept
|
||||
{
|
||||
// A prime number for the hash table size was chosen to prevent collisions.
|
||||
constexpr size_t size = 251;
|
||||
constexpr std::hash<uintptr_t> hasher;
|
||||
|
||||
static WaitTableEntry table[size];
|
||||
#pragma warning(suppress : 26446) // Prefer to use gsl::at() instead of unchecked subscript operator
|
||||
#pragma warning(suppress : 26482) // Only index into arrays using constant expressions
|
||||
#pragma warning(suppress : 26490) // Don't use reinterpret_cast
|
||||
return table[hasher(reinterpret_cast<uintptr_t>(storage)) % size];
|
||||
}
|
||||
|
||||
#pragma warning(suppress : 26429) // Symbol 'comparand' is never tested for nullness, it can be marked as not_null
|
||||
bool AreEqual(const volatile void* storage, const void* comparand, size_t size) noexcept
|
||||
{
|
||||
switch (size)
|
||||
{
|
||||
case 1:
|
||||
return __iso_volatile_load8(static_cast<const volatile __int8*>(storage)) == *static_cast<const __int8*>(comparand);
|
||||
case 2:
|
||||
return __iso_volatile_load16(static_cast<const volatile __int16*>(storage)) == *static_cast<const __int16*>(comparand);
|
||||
case 4:
|
||||
return __iso_volatile_load32(static_cast<const volatile __int32*>(storage)) == *static_cast<const __int32*>(comparand);
|
||||
case 8:
|
||||
return __iso_volatile_load64(static_cast<const volatile __int64*>(storage)) == *static_cast<const __int64*>(comparand);
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
}
|
||||
} // unnamed namespace
|
||||
|
||||
extern "C" BOOL WINAPI WaitOnAddress(_In_reads_bytes_(AddressSize) volatile VOID* Address, _In_reads_bytes_(AddressSize) PVOID CompareAddress, _In_ SIZE_T AddressSize, _In_opt_ DWORD dwMilliseconds)
|
||||
{
|
||||
auto& entry = GetWaitTableEntry(Address);
|
||||
|
||||
SRWLockGuard guard{ entry.lock };
|
||||
GuardedWaitContext context{ Address, &entry.head };
|
||||
|
||||
for (;;)
|
||||
{
|
||||
// NOTE: under lock to prevent lost wakes
|
||||
if (!AreEqual(Address, CompareAddress, AddressSize))
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (!SleepConditionVariableSRW(&context.cv, &entry.lock, dwMilliseconds, 0))
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
if (GetLastError() != ERROR_TIMEOUT)
|
||||
{
|
||||
abort();
|
||||
}
|
||||
#endif
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (dwMilliseconds != INFINITE)
|
||||
{
|
||||
// spurious wake to recheck the clock
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" VOID WINAPI WakeByAddressSingle(_In_ PVOID Address)
|
||||
{
|
||||
auto& entry = GetWaitTableEntry(Address);
|
||||
SRWLockGuard guard(entry.lock);
|
||||
|
||||
for (auto context = entry.head.next; context != &entry.head; context = context->next)
|
||||
{
|
||||
if (context->address == Address)
|
||||
{
|
||||
// Can't move wake outside SRWLOCKed section: SRWLOCK also protects the context itself
|
||||
WakeAllConditionVariable(&context->cv);
|
||||
// This break; is the difference between WakeByAddressSingle and WakeByAddressAll
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" VOID WINAPI WakeByAddressAll(_In_ PVOID Address)
|
||||
{
|
||||
auto& entry = GetWaitTableEntry(Address);
|
||||
SRWLockGuard guard(entry.lock);
|
||||
|
||||
for (auto context = entry.head.next; context != &entry.head; context = context->next)
|
||||
{
|
||||
if (context->address == Address)
|
||||
{
|
||||
// Can't move wake outside SRWLOCKed section: SRWLOCK also protects the context itself
|
||||
WakeAllConditionVariable(&context->cv);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,7 @@ Module Name:
|
||||
- OutputCellView.hpp
|
||||
|
||||
Abstract:
|
||||
- Read-only view into a single cell of data that someone is attempting to write into the output buffer.
|
||||
- Read view into a single cell of data that someone is attempting to write into the output buffer.
|
||||
- This is done for performance reasons (avoid heap allocs and copies).
|
||||
|
||||
Author:
|
||||
@@ -36,6 +36,21 @@ public:
|
||||
TextAttribute TextAttr() const noexcept;
|
||||
TextAttributeBehavior TextAttrBehavior() const noexcept;
|
||||
|
||||
void UpdateText(const std::wstring_view& view) noexcept
|
||||
{
|
||||
_view = view;
|
||||
};
|
||||
|
||||
void UpdateDbcsAttribute(const DbcsAttribute& dbcsAttr) noexcept
|
||||
{
|
||||
_dbcsAttr = dbcsAttr;
|
||||
}
|
||||
|
||||
void UpdateTextAttribute(const TextAttribute& textAttr) noexcept
|
||||
{
|
||||
_textAttr = textAttr;
|
||||
}
|
||||
|
||||
bool operator==(const OutputCellView& view) const noexcept;
|
||||
bool operator!=(const OutputCellView& view) const noexcept;
|
||||
|
||||
|
||||
@@ -95,16 +95,18 @@ bool TextAttribute::IsLegacy() const noexcept
|
||||
// - defaultFgColor: the default foreground color rgb value.
|
||||
// - defaultBgColor: the default background color rgb value.
|
||||
// - reverseScreenMode: true if the screen mode is reversed.
|
||||
// - blinkingIsFaint: true if blinking should be interpreted as faint.
|
||||
// - blinkingIsFaint: true if blinking should be interpreted as faint. (defaults to false)
|
||||
// - boldIsBright: true if "bold" should be interpreted as bright. (defaults to true)
|
||||
// Return Value:
|
||||
// - the foreground and background colors that should be displayed.
|
||||
std::pair<COLORREF, COLORREF> TextAttribute::CalculateRgbColors(const gsl::span<const COLORREF> colorTable,
|
||||
std::pair<COLORREF, COLORREF> TextAttribute::CalculateRgbColors(const std::array<COLORREF, 256>& colorTable,
|
||||
const COLORREF defaultFgColor,
|
||||
const COLORREF defaultBgColor,
|
||||
const bool reverseScreenMode,
|
||||
const bool blinkingIsFaint) const noexcept
|
||||
const bool blinkingIsFaint,
|
||||
const bool boldIsBright) const noexcept
|
||||
{
|
||||
auto fg = _foreground.GetColor(colorTable, defaultFgColor, IsBold());
|
||||
auto fg = _foreground.GetColor(colorTable, defaultFgColor, boldIsBright && IsBold());
|
||||
auto bg = _background.GetColor(colorTable, defaultBgColor);
|
||||
if (IsFaint() || (IsBlinking() && blinkingIsFaint))
|
||||
{
|
||||
|
||||
@@ -64,11 +64,12 @@ public:
|
||||
static TextAttribute StripErroneousVT16VersionsOfLegacyDefaults(const TextAttribute& attribute) noexcept;
|
||||
WORD GetLegacyAttributes() const noexcept;
|
||||
|
||||
std::pair<COLORREF, COLORREF> CalculateRgbColors(const gsl::span<const COLORREF> colorTable,
|
||||
std::pair<COLORREF, COLORREF> CalculateRgbColors(const std::array<COLORREF, 256>& colorTable,
|
||||
const COLORREF defaultFgColor,
|
||||
const COLORREF defaultBgColor,
|
||||
const bool reverseScreenMode = false,
|
||||
const bool blinkingIsFaint = false) const noexcept;
|
||||
const bool blinkingIsFaint = false,
|
||||
const bool boldIsBright = true) const noexcept;
|
||||
|
||||
bool IsLeadingByte() const noexcept;
|
||||
bool IsTrailingByte() const noexcept;
|
||||
@@ -212,7 +213,7 @@ constexpr bool operator!=(const TextAttribute& a, const TextAttribute& b) noexce
|
||||
#ifdef UNIT_TESTING
|
||||
|
||||
#define LOG_ATTR(attr) (Log::Comment(NoThrowString().Format( \
|
||||
L#attr L"=%s", VerifyOutputTraits<TextAttribute>::ToString(attr).GetBuffer())))
|
||||
L## #attr L"=%s", VerifyOutputTraits<TextAttribute>::ToString(attr).GetBuffer())))
|
||||
|
||||
namespace WEX
|
||||
{
|
||||
|
||||
@@ -50,6 +50,9 @@ constexpr std::array<BYTE, 256> Index256ToIndex16 = {
|
||||
|
||||
// clang-format on
|
||||
|
||||
// We should only need 4B for TextColor. Any more than that is just waste.
|
||||
static_assert(sizeof(TextColor) == 4);
|
||||
|
||||
bool TextColor::CanBeBrightened() const noexcept
|
||||
{
|
||||
return IsIndex16() || IsDefault();
|
||||
@@ -138,15 +141,12 @@ void TextColor::SetDefault() noexcept
|
||||
// - brighten: if true, we'll brighten a dark color table index.
|
||||
// Return Value:
|
||||
// - a COLORREF containing the real value of this TextColor.
|
||||
COLORREF TextColor::GetColor(gsl::span<const COLORREF> colorTable,
|
||||
const COLORREF defaultColor,
|
||||
bool brighten) const noexcept
|
||||
COLORREF TextColor::GetColor(const std::array<COLORREF, 256>& colorTable, const COLORREF defaultColor, bool brighten) const noexcept
|
||||
{
|
||||
if (IsDefault())
|
||||
{
|
||||
if (brighten)
|
||||
{
|
||||
FAIL_FAST_IF(colorTable.size() < 16);
|
||||
// See MSFT:20266024 for context on this fix.
|
||||
// Additionally todo MSFT:20271956 to fix this better for 19H2+
|
||||
// If we're a default color, check to see if the defaultColor exists
|
||||
@@ -156,6 +156,61 @@ COLORREF TextColor::GetColor(gsl::span<const COLORREF> colorTable,
|
||||
// (Settings::_DefaultForeground==INVALID_COLOR, and the index
|
||||
// from _wFillAttribute is being used instead.)
|
||||
// If we find a match, return instead the bright version of this color
|
||||
|
||||
static_assert(sizeof(COLORREF) * 8 == 32, "The vectorized code broke. If you can't fix COLORREF, just remove the vectorized code.");
|
||||
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 26481) // Don't use pointer arithmetic. Use span instead (bounds.1).
|
||||
#pragma warning(disable : 26490) // Don't use reinterpret_cast (type.1).
|
||||
#ifdef __AVX2__
|
||||
// I wrote this vectorized code one day, because the sun was shining so nicely.
|
||||
// There's no other reason for this to exist here, except for being pretty.
|
||||
// This code implements the exact same for loop you can find below, but is ~3x faster.
|
||||
//
|
||||
// A brief explanation for people unfamiliar with vectorized instructions:
|
||||
// Vectorized instructions, like "SSE" or "AVX", allow you to run
|
||||
// common operations like additions, multiplications, comparisons,
|
||||
// or bitwise operations concurrently on multiple values at once.
|
||||
//
|
||||
// We want to find the given defaultColor in the first 8 values of colorTable.
|
||||
// Coincidentally a COLORREF is a DWORD and 8 of them are exactly 256 bits.
|
||||
// -- The size of a single AVX register.
|
||||
//
|
||||
// Thus, the code works like this:
|
||||
// 1. Load all 8 DWORDs at once into one register
|
||||
// 2. Set the same defaultColor 8 times in another register
|
||||
// 3. Compare all 8 values at once
|
||||
// The result is either 0xffffffff or 0x00000000.
|
||||
// 4. Extract the most significant bit of each DWORD
|
||||
// Assuming that no duplicate colors exist in colorTable,
|
||||
// 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(__builtin_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;
|
||||
return _BitScanForward(&index, mask) ? til::at(colorTable, static_cast<size_t>(index) + 8) : defaultColor; // 5.
|
||||
#elif _M_AMD64
|
||||
// If you look closely this SSE2 algorithm is the same as the AVX one.
|
||||
// The two differences are that we need to:
|
||||
// * do everything twice, because SSE is limited to 128 bits and not 256.
|
||||
// * use _mm_packs_epi32 to merge two 128 bits vectors into one in step 3.5.
|
||||
// _mm_packs_epi32 takes two SSE registers and truncates all 8 DWORDs into 8 WORDs,
|
||||
// the latter of which fits into a single register (which is then used in the identical step 4).
|
||||
// * since the result are now 8 WORDs, we need to use _mm_movemask_epi8 (there's no 16-bit variant),
|
||||
// which unlike AVX's step 4 results in in something like 0b0000110000000000.
|
||||
// --> 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(__builtin_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
|
||||
const auto mask = _mm_movemask_epi8(result);
|
||||
unsigned long index;
|
||||
return _BitScanForward(&index, mask) ? til::at(colorTable, static_cast<size_t>(index / 2) + 8) : defaultColor;
|
||||
#else
|
||||
for (size_t i = 0; i < 8; i++)
|
||||
{
|
||||
if (til::at(colorTable, i) == defaultColor)
|
||||
@@ -163,6 +218,8 @@ COLORREF TextColor::GetColor(gsl::span<const COLORREF> colorTable,
|
||||
return til::at(colorTable, i + 8);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#pragma warning(pop)
|
||||
}
|
||||
|
||||
return defaultColor;
|
||||
@@ -199,7 +256,7 @@ BYTE TextColor::GetLegacyIndex(const BYTE defaultIndex) const noexcept
|
||||
}
|
||||
else if (IsIndex256())
|
||||
{
|
||||
return Index256ToIndex16.at(GetIndex());
|
||||
return til::at(Index256ToIndex16, GetIndex());
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -208,7 +265,7 @@ BYTE TextColor::GetLegacyIndex(const BYTE defaultIndex) const noexcept
|
||||
const BYTE compressedRgb = (_red & 0b11100000) +
|
||||
((_green >> 3) & 0b00011100) +
|
||||
((_blue >> 6) & 0b00000011);
|
||||
return CompressedRgbToIndex16.at(compressedRgb);
|
||||
return til::at(CompressedRgbToIndex16, compressedRgb);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -86,10 +86,7 @@ public:
|
||||
void SetIndex(const BYTE index, const bool isIndex256) noexcept;
|
||||
void SetDefault() noexcept;
|
||||
|
||||
COLORREF GetColor(gsl::span<const COLORREF> colorTable,
|
||||
const COLORREF defaultColor,
|
||||
const bool brighten = false) const noexcept;
|
||||
|
||||
COLORREF GetColor(const std::array<COLORREF, 256>& colorTable, const COLORREF defaultColor, bool brighten = false) const noexcept;
|
||||
BYTE GetLegacyIndex(const BYTE defaultIndex) const noexcept;
|
||||
|
||||
constexpr BYTE GetIndex() const noexcept
|
||||
@@ -157,5 +154,3 @@ namespace WEX
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static_assert(sizeof(TextColor) <= 4 * sizeof(BYTE), "We should only need 4B for an entire TextColor. Any more than that is just waste");
|
||||
|
||||
@@ -315,6 +315,11 @@ void Cursor::StartDeferDrawing() noexcept
|
||||
_fDeferCursorRedraw = true;
|
||||
}
|
||||
|
||||
bool Cursor::IsDeferDrawing() noexcept
|
||||
{
|
||||
return _fDeferCursorRedraw;
|
||||
}
|
||||
|
||||
void Cursor::EndDeferDrawing() noexcept
|
||||
{
|
||||
if (_fHaveDeferredCursorRedraw)
|
||||
|
||||
@@ -55,6 +55,7 @@ public:
|
||||
const COLORREF GetColor() const noexcept;
|
||||
|
||||
void StartDeferDrawing() noexcept;
|
||||
bool IsDeferDrawing() noexcept;
|
||||
void EndDeferDrawing() noexcept;
|
||||
|
||||
void SetHasMoved(const bool fHasMoved) noexcept;
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
<ClInclude Include="..\Row.hpp" />
|
||||
<ClInclude Include="..\search.h" />
|
||||
<ClInclude Include="..\TextColor.h" />
|
||||
<ClInclude Include="..\TextAttribute.h" />
|
||||
<ClInclude Include="..\TextAttribute.hpp" />
|
||||
<ClInclude Include="..\textBuffer.hpp" />
|
||||
<ClInclude Include="..\textBufferCellIterator.hpp" />
|
||||
<ClInclude Include="..\textBufferTextIterator.hpp" />
|
||||
|
||||
@@ -418,7 +418,6 @@ bool TextBuffer::InsertCharacter(const std::wstring_view chars,
|
||||
|
||||
// Store character and double byte data
|
||||
CharRow& charRow = Row.GetCharRow();
|
||||
short const cBufferWidth = GetSize().Width();
|
||||
|
||||
try
|
||||
{
|
||||
@@ -1650,13 +1649,14 @@ const TextBuffer::TextAndColor TextBuffer::GetText(const bool includeCRLF,
|
||||
|
||||
if (!cell.DbcsAttr().IsTrailing())
|
||||
{
|
||||
selectionText.append(cell.Chars());
|
||||
const auto chars = cell.Chars();
|
||||
selectionText.append(chars);
|
||||
|
||||
if (copyTextColor)
|
||||
{
|
||||
const auto cellData = cell.TextAttr();
|
||||
const auto [CellFgAttr, CellBkAttr] = GetAttributeColors(cellData);
|
||||
for (const wchar_t wch : cell.Chars())
|
||||
for (size_t j = 0; j < chars.size(); ++j)
|
||||
{
|
||||
selectionFgAttr.push_back(CellFgAttr);
|
||||
selectionBkAttr.push_back(CellBkAttr);
|
||||
|
||||
@@ -94,20 +94,93 @@ bool TextBufferCellIterator::operator!=(const TextBufferCellIterator& it) const
|
||||
// - Reference to self after movement.
|
||||
TextBufferCellIterator& TextBufferCellIterator::operator+=(const ptrdiff_t& movement)
|
||||
{
|
||||
// Note that this method is called intensively when the terminal is under heavy load.
|
||||
// We need to aggressively optimize it, comparing to the -= operator.
|
||||
ptrdiff_t move = movement;
|
||||
auto newPos = _pos;
|
||||
while (move > 0 && !_exceeded)
|
||||
if (move < 0)
|
||||
{
|
||||
_exceeded = !_bounds.IncrementInBounds(newPos);
|
||||
// Early branching to leave the rare case to -= operator.
|
||||
// This helps reducing the instruction count within this method, which is good for instruction cache.
|
||||
return *this -= -move;
|
||||
}
|
||||
|
||||
// The remaining code in this function is functionally equivalent to:
|
||||
// auto newPos = _pos;
|
||||
// while (move > 0 && !_exceeded)
|
||||
// {
|
||||
// _exceeded = !_bounds.IncrementInBounds(newPos);
|
||||
// move--;
|
||||
// }
|
||||
// _SetPos(newPos);
|
||||
//
|
||||
// _SetPos() necessitates calling _GenerateView() and thus the construction
|
||||
// of a new OutputCellView(). This has a high performance impact (ICache spill?).
|
||||
// The code below inlines _bounds.IncrementInBounds as well as SetPos.
|
||||
// In the hot path (_pos.Y doesn't change) we modify the _view directly.
|
||||
|
||||
// Hoist these integers which will be used frequently later.
|
||||
const auto boundsRightInclusive = _bounds.RightInclusive();
|
||||
const auto boundsLeft = _bounds.Left();
|
||||
const auto boundsBottomInclusive = _bounds.BottomInclusive();
|
||||
const auto boundsTop = _bounds.Top();
|
||||
const auto oldX = _pos.X;
|
||||
const auto oldY = _pos.Y;
|
||||
|
||||
// Under MSVC writing the individual members of a COORD generates worse assembly
|
||||
// compared to having them be local variables. This causes a performance impact.
|
||||
auto newX = oldX;
|
||||
auto newY = oldY;
|
||||
|
||||
while (move > 0)
|
||||
{
|
||||
if (newX == boundsRightInclusive)
|
||||
{
|
||||
newX = boundsLeft;
|
||||
newY++;
|
||||
if (newY > boundsBottomInclusive)
|
||||
{
|
||||
newY = boundsTop;
|
||||
_exceeded = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
newX++;
|
||||
_exceeded = false;
|
||||
}
|
||||
move--;
|
||||
}
|
||||
while (move < 0 && !_exceeded)
|
||||
|
||||
if (_exceeded)
|
||||
{
|
||||
_exceeded = !_bounds.DecrementInBounds(newPos);
|
||||
move++;
|
||||
// Early return because nothing needs to be done here.
|
||||
return *this;
|
||||
}
|
||||
_SetPos(newPos);
|
||||
return (*this);
|
||||
|
||||
if (newY == oldY)
|
||||
{
|
||||
// hot path
|
||||
const auto diff = gsl::narrow_cast<ptrdiff_t>(newX) - gsl::narrow_cast<ptrdiff_t>(oldX);
|
||||
_attrIter += diff;
|
||||
_view.UpdateTextAttribute(*_attrIter);
|
||||
|
||||
const CharRow& charRow = _pRow->GetCharRow();
|
||||
_view.UpdateText(charRow.GlyphAt(newX));
|
||||
_view.UpdateDbcsAttribute(charRow.DbcsAttrAt(newX));
|
||||
_pos.X = newX;
|
||||
}
|
||||
else
|
||||
{
|
||||
// cold path (_GenerateView is slow)
|
||||
_pRow = s_GetRow(_buffer, { newX, newY });
|
||||
_attrIter = _pRow->GetAttrRow().cbegin() + newX;
|
||||
_pos.X = newX;
|
||||
_pos.Y = newY;
|
||||
_GenerateView();
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
@@ -118,7 +191,22 @@ TextBufferCellIterator& TextBufferCellIterator::operator+=(const ptrdiff_t& move
|
||||
// - Reference to self after movement.
|
||||
TextBufferCellIterator& TextBufferCellIterator::operator-=(const ptrdiff_t& movement)
|
||||
{
|
||||
return this->operator+=(-movement);
|
||||
ptrdiff_t move = movement;
|
||||
if (move < 0)
|
||||
{
|
||||
return (*this) += (-move);
|
||||
}
|
||||
|
||||
auto newPos = _pos;
|
||||
while (move > 0 && !_exceeded)
|
||||
{
|
||||
_exceeded = !_bounds.DecrementInBounds(newPos);
|
||||
move--;
|
||||
}
|
||||
_SetPos(newPos);
|
||||
|
||||
_GenerateView();
|
||||
return (*this);
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
@@ -265,3 +353,8 @@ const OutputCellView* TextBufferCellIterator::operator->() const noexcept
|
||||
{
|
||||
return &_view;
|
||||
}
|
||||
|
||||
COORD TextBufferCellIterator::Pos() const noexcept
|
||||
{
|
||||
return _pos;
|
||||
}
|
||||
|
||||
@@ -47,6 +47,8 @@ public:
|
||||
const OutputCellView& operator*() const noexcept;
|
||||
const OutputCellView* operator->() const noexcept;
|
||||
|
||||
COORD Pos() const noexcept;
|
||||
|
||||
protected:
|
||||
void _SetPos(const COORD newPos);
|
||||
void _GenerateView();
|
||||
|
||||
@@ -22,12 +22,11 @@ class TextAttributeTests
|
||||
TEST_METHOD(TestTextAttributeColorGetters);
|
||||
TEST_METHOD(TestReverseDefaultColors);
|
||||
TEST_METHOD(TestRoundtripDefaultColors);
|
||||
TEST_METHOD(TestBoldAsBright);
|
||||
|
||||
static const int COLOR_TABLE_SIZE = 16;
|
||||
COLORREF _colorTable[COLOR_TABLE_SIZE];
|
||||
std::array<COLORREF, 256> _colorTable;
|
||||
COLORREF _defaultFg = RGB(1, 2, 3);
|
||||
COLORREF _defaultBg = RGB(4, 5, 6);
|
||||
gsl::span<const COLORREF> _GetTableView();
|
||||
};
|
||||
|
||||
bool TextAttributeTests::ClassSetup()
|
||||
@@ -51,11 +50,6 @@ bool TextAttributeTests::ClassSetup()
|
||||
return true;
|
||||
}
|
||||
|
||||
gsl::span<const COLORREF> TextAttributeTests::_GetTableView()
|
||||
{
|
||||
return gsl::span<const COLORREF>(&_colorTable[0], COLOR_TABLE_SIZE);
|
||||
}
|
||||
|
||||
void TextAttributeTests::TestRoundtripLegacy()
|
||||
{
|
||||
WORD expectedLegacy = FOREGROUND_BLUE | BACKGROUND_RED;
|
||||
@@ -133,23 +127,22 @@ void TextAttributeTests::TestTextAttributeColorGetters()
|
||||
const COLORREF faintRed = RGB(127, 0, 0);
|
||||
const COLORREF green = RGB(0, 255, 0);
|
||||
TextAttribute attr(red, green);
|
||||
auto view = _GetTableView();
|
||||
|
||||
// verify that calculated foreground/background are the same as the direct
|
||||
// values when reverse video is not set
|
||||
VERIFY_IS_FALSE(attr.IsReverseVideo());
|
||||
|
||||
VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(view, _defaultFg));
|
||||
VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(view, _defaultBg));
|
||||
VERIFY_ARE_EQUAL(std::make_pair(red, green), attr.CalculateRgbColors(view, _defaultFg, _defaultBg));
|
||||
VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(_colorTable, _defaultFg));
|
||||
VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(_colorTable, _defaultBg));
|
||||
VERIFY_ARE_EQUAL(std::make_pair(red, green), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg));
|
||||
|
||||
// with reverse video set, calculated foreground/background values should be
|
||||
// switched while getters stay the same
|
||||
attr.SetReverseVideo(true);
|
||||
|
||||
VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(view, _defaultFg));
|
||||
VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(view, _defaultBg));
|
||||
VERIFY_ARE_EQUAL(std::make_pair(green, red), attr.CalculateRgbColors(view, _defaultFg, _defaultBg));
|
||||
VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(_colorTable, _defaultFg));
|
||||
VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(_colorTable, _defaultBg));
|
||||
VERIFY_ARE_EQUAL(std::make_pair(green, red), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg));
|
||||
|
||||
// reset the reverse video
|
||||
attr.SetReverseVideo(false);
|
||||
@@ -158,17 +151,17 @@ void TextAttributeTests::TestTextAttributeColorGetters()
|
||||
// while the background and getters stay the same
|
||||
attr.SetFaint(true);
|
||||
|
||||
VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(view, _defaultFg));
|
||||
VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(view, _defaultBg));
|
||||
VERIFY_ARE_EQUAL(std::make_pair(faintRed, green), attr.CalculateRgbColors(view, _defaultFg, _defaultBg));
|
||||
VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(_colorTable, _defaultFg));
|
||||
VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(_colorTable, _defaultBg));
|
||||
VERIFY_ARE_EQUAL(std::make_pair(faintRed, green), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg));
|
||||
|
||||
// with reverse video set, calculated foreground/background values should be
|
||||
// switched, and the background fainter, while getters stay the same
|
||||
attr.SetReverseVideo(true);
|
||||
|
||||
VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(view, _defaultFg));
|
||||
VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(view, _defaultBg));
|
||||
VERIFY_ARE_EQUAL(std::make_pair(green, faintRed), attr.CalculateRgbColors(view, _defaultFg, _defaultBg));
|
||||
VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(_colorTable, _defaultFg));
|
||||
VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(_colorTable, _defaultBg));
|
||||
VERIFY_ARE_EQUAL(std::make_pair(green, faintRed), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg));
|
||||
|
||||
// reset the reverse video and faint attributes
|
||||
attr.SetReverseVideo(false);
|
||||
@@ -178,17 +171,17 @@ void TextAttributeTests::TestTextAttributeColorGetters()
|
||||
// background, while getters stay the same
|
||||
attr.SetInvisible(true);
|
||||
|
||||
VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(view, _defaultFg));
|
||||
VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(view, _defaultBg));
|
||||
VERIFY_ARE_EQUAL(std::make_pair(green, green), attr.CalculateRgbColors(view, _defaultFg, _defaultBg));
|
||||
VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(_colorTable, _defaultFg));
|
||||
VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(_colorTable, _defaultBg));
|
||||
VERIFY_ARE_EQUAL(std::make_pair(green, green), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg));
|
||||
|
||||
// with reverse video set, the calculated background value should match
|
||||
// the foreground, while getters stay the same
|
||||
attr.SetReverseVideo(true);
|
||||
|
||||
VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(view, _defaultFg));
|
||||
VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(view, _defaultBg));
|
||||
VERIFY_ARE_EQUAL(std::make_pair(red, red), attr.CalculateRgbColors(view, _defaultFg, _defaultBg));
|
||||
VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(_colorTable, _defaultFg));
|
||||
VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(_colorTable, _defaultBg));
|
||||
VERIFY_ARE_EQUAL(std::make_pair(red, red), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg));
|
||||
}
|
||||
|
||||
void TextAttributeTests::TestReverseDefaultColors()
|
||||
@@ -196,40 +189,39 @@ void TextAttributeTests::TestReverseDefaultColors()
|
||||
const COLORREF red = RGB(255, 0, 0);
|
||||
const COLORREF green = RGB(0, 255, 0);
|
||||
TextAttribute attr{};
|
||||
auto view = _GetTableView();
|
||||
|
||||
// verify that calculated foreground/background are the same as the direct
|
||||
// values when reverse video is not set
|
||||
VERIFY_IS_FALSE(attr.IsReverseVideo());
|
||||
|
||||
VERIFY_ARE_EQUAL(_defaultFg, attr.GetForeground().GetColor(view, _defaultFg));
|
||||
VERIFY_ARE_EQUAL(_defaultBg, attr.GetBackground().GetColor(view, _defaultBg));
|
||||
VERIFY_ARE_EQUAL(std::make_pair(_defaultFg, _defaultBg), attr.CalculateRgbColors(view, _defaultFg, _defaultBg));
|
||||
VERIFY_ARE_EQUAL(_defaultFg, attr.GetForeground().GetColor(_colorTable, _defaultFg));
|
||||
VERIFY_ARE_EQUAL(_defaultBg, attr.GetBackground().GetColor(_colorTable, _defaultBg));
|
||||
VERIFY_ARE_EQUAL(std::make_pair(_defaultFg, _defaultBg), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg));
|
||||
|
||||
// with reverse video set, calculated foreground/background values should be
|
||||
// switched while getters stay the same
|
||||
attr.SetReverseVideo(true);
|
||||
VERIFY_IS_TRUE(attr.IsReverseVideo());
|
||||
|
||||
VERIFY_ARE_EQUAL(_defaultFg, attr.GetForeground().GetColor(view, _defaultFg));
|
||||
VERIFY_ARE_EQUAL(_defaultBg, attr.GetBackground().GetColor(view, _defaultBg));
|
||||
VERIFY_ARE_EQUAL(std::make_pair(_defaultBg, _defaultFg), attr.CalculateRgbColors(view, _defaultFg, _defaultBg));
|
||||
VERIFY_ARE_EQUAL(_defaultFg, attr.GetForeground().GetColor(_colorTable, _defaultFg));
|
||||
VERIFY_ARE_EQUAL(_defaultBg, attr.GetBackground().GetColor(_colorTable, _defaultBg));
|
||||
VERIFY_ARE_EQUAL(std::make_pair(_defaultBg, _defaultFg), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg));
|
||||
|
||||
attr.SetForeground(red);
|
||||
VERIFY_IS_TRUE(attr.IsReverseVideo());
|
||||
|
||||
VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(view, _defaultFg));
|
||||
VERIFY_ARE_EQUAL(_defaultBg, attr.GetBackground().GetColor(view, _defaultBg));
|
||||
VERIFY_ARE_EQUAL(std::make_pair(_defaultBg, red), attr.CalculateRgbColors(view, _defaultFg, _defaultBg));
|
||||
VERIFY_ARE_EQUAL(red, attr.GetForeground().GetColor(_colorTable, _defaultFg));
|
||||
VERIFY_ARE_EQUAL(_defaultBg, attr.GetBackground().GetColor(_colorTable, _defaultBg));
|
||||
VERIFY_ARE_EQUAL(std::make_pair(_defaultBg, red), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg));
|
||||
|
||||
attr.Invert();
|
||||
VERIFY_IS_FALSE(attr.IsReverseVideo());
|
||||
attr.SetDefaultForeground();
|
||||
attr.SetBackground(green);
|
||||
|
||||
VERIFY_ARE_EQUAL(_defaultFg, attr.GetForeground().GetColor(view, _defaultFg));
|
||||
VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(view, _defaultBg));
|
||||
VERIFY_ARE_EQUAL(std::make_pair(_defaultFg, green), attr.CalculateRgbColors(view, _defaultFg, _defaultBg));
|
||||
VERIFY_ARE_EQUAL(_defaultFg, attr.GetForeground().GetColor(_colorTable, _defaultFg));
|
||||
VERIFY_ARE_EQUAL(green, attr.GetBackground().GetColor(_colorTable, _defaultBg));
|
||||
VERIFY_ARE_EQUAL(std::make_pair(_defaultFg, green), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg));
|
||||
}
|
||||
|
||||
void TextAttributeTests::TestRoundtripDefaultColors()
|
||||
@@ -272,3 +264,56 @@ void TextAttributeTests::TestRoundtripDefaultColors()
|
||||
// Reset the legacy default colors to white on black.
|
||||
TextAttribute::SetLegacyDefaultAttributes(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
|
||||
}
|
||||
|
||||
void TextAttributeTests::TestBoldAsBright()
|
||||
{
|
||||
const COLORREF darkBlack = til::at(_colorTable, 0);
|
||||
const COLORREF brightBlack = til::at(_colorTable, 8);
|
||||
const COLORREF darkGreen = til::at(_colorTable, 2);
|
||||
|
||||
TextAttribute attr{};
|
||||
|
||||
// verify that calculated foreground/background are the same as the direct
|
||||
// values when not bold
|
||||
VERIFY_IS_FALSE(attr.IsBold());
|
||||
|
||||
VERIFY_ARE_EQUAL(_defaultFg, attr.GetForeground().GetColor(_colorTable, _defaultFg));
|
||||
VERIFY_ARE_EQUAL(_defaultBg, attr.GetBackground().GetColor(_colorTable, _defaultBg));
|
||||
VERIFY_ARE_EQUAL(std::make_pair(_defaultFg, _defaultBg), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg, false, false, true));
|
||||
VERIFY_ARE_EQUAL(std::make_pair(_defaultFg, _defaultBg), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg, false, false, false));
|
||||
|
||||
// with bold set, calculated foreground/background values shouldn't change for the default colors.
|
||||
attr.SetBold(true);
|
||||
VERIFY_IS_TRUE(attr.IsBold());
|
||||
VERIFY_ARE_EQUAL(std::make_pair(_defaultFg, _defaultBg), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg, false, false, true));
|
||||
VERIFY_ARE_EQUAL(std::make_pair(_defaultFg, _defaultBg), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg, false, false, false));
|
||||
|
||||
attr.SetIndexedForeground(0);
|
||||
VERIFY_IS_TRUE(attr.IsBold());
|
||||
|
||||
Log::Comment(L"Foreground should be bright black when bold is bright is enabled");
|
||||
VERIFY_ARE_EQUAL(std::make_pair(brightBlack, _defaultBg), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg, false, false, true));
|
||||
|
||||
Log::Comment(L"Foreground should be dark black when bold is bright is disabled");
|
||||
VERIFY_ARE_EQUAL(std::make_pair(darkBlack, _defaultBg), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg, false, false, false));
|
||||
|
||||
attr.SetIndexedBackground(2);
|
||||
VERIFY_IS_TRUE(attr.IsBold());
|
||||
|
||||
Log::Comment(L"background should be unaffected by 'bold is bright'");
|
||||
VERIFY_ARE_EQUAL(std::make_pair(brightBlack, darkGreen), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg, false, false, true));
|
||||
VERIFY_ARE_EQUAL(std::make_pair(darkBlack, darkGreen), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg, false, false, false));
|
||||
|
||||
attr.SetBold(false);
|
||||
VERIFY_IS_FALSE(attr.IsBold());
|
||||
Log::Comment(L"when not bold, 'bold is bright' changes nothing");
|
||||
VERIFY_ARE_EQUAL(std::make_pair(darkBlack, darkGreen), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg, false, false, true));
|
||||
VERIFY_ARE_EQUAL(std::make_pair(darkBlack, darkGreen), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg, false, false, false));
|
||||
|
||||
Log::Comment(L"When set to a bright color, and bold, 'bold is bright' changes nothing");
|
||||
attr.SetBold(true);
|
||||
attr.SetIndexedForeground(8);
|
||||
VERIFY_IS_TRUE(attr.IsBold());
|
||||
VERIFY_ARE_EQUAL(std::make_pair(brightBlack, darkGreen), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg, false, false, true));
|
||||
VERIFY_ARE_EQUAL(std::make_pair(brightBlack, darkGreen), attr.CalculateRgbColors(_colorTable, _defaultFg, _defaultBg, false, false, false));
|
||||
}
|
||||
|
||||
@@ -23,11 +23,9 @@ class TextColorTests
|
||||
TEST_METHOD(TestRgbColor);
|
||||
TEST_METHOD(TestChangeColor);
|
||||
|
||||
static const int COLOR_TABLE_SIZE = 16;
|
||||
COLORREF _colorTable[COLOR_TABLE_SIZE];
|
||||
std::array<COLORREF, 256> _colorTable;
|
||||
COLORREF _defaultFg = RGB(1, 2, 3);
|
||||
COLORREF _defaultBg = RGB(4, 5, 6);
|
||||
gsl::span<const COLORREF> _GetTableView();
|
||||
};
|
||||
|
||||
bool TextColorTests::ClassSetup()
|
||||
@@ -51,11 +49,6 @@ bool TextColorTests::ClassSetup()
|
||||
return true;
|
||||
}
|
||||
|
||||
gsl::span<const COLORREF> TextColorTests::_GetTableView()
|
||||
{
|
||||
return gsl::span<const COLORREF>(&_colorTable[0], COLOR_TABLE_SIZE);
|
||||
}
|
||||
|
||||
void TextColorTests::TestDefaultColor()
|
||||
{
|
||||
TextColor defaultColor;
|
||||
@@ -64,18 +57,16 @@ void TextColorTests::TestDefaultColor()
|
||||
VERIFY_IS_FALSE(defaultColor.IsLegacy());
|
||||
VERIFY_IS_FALSE(defaultColor.IsRgb());
|
||||
|
||||
auto view = _GetTableView();
|
||||
|
||||
auto color = defaultColor.GetColor(view, _defaultFg, false);
|
||||
auto color = defaultColor.GetColor(_colorTable, _defaultFg, false);
|
||||
VERIFY_ARE_EQUAL(_defaultFg, color);
|
||||
|
||||
color = defaultColor.GetColor(view, _defaultFg, true);
|
||||
color = defaultColor.GetColor(_colorTable, _defaultFg, true);
|
||||
VERIFY_ARE_EQUAL(_defaultFg, color);
|
||||
|
||||
color = defaultColor.GetColor(view, _defaultBg, false);
|
||||
color = defaultColor.GetColor(_colorTable, _defaultBg, false);
|
||||
VERIFY_ARE_EQUAL(_defaultBg, color);
|
||||
|
||||
color = defaultColor.GetColor(view, _defaultBg, true);
|
||||
color = defaultColor.GetColor(_colorTable, _defaultBg, true);
|
||||
VERIFY_ARE_EQUAL(_defaultBg, color);
|
||||
}
|
||||
|
||||
@@ -87,18 +78,16 @@ void TextColorTests::TestDarkIndexColor()
|
||||
VERIFY_IS_TRUE(indexColor.IsLegacy());
|
||||
VERIFY_IS_FALSE(indexColor.IsRgb());
|
||||
|
||||
auto view = _GetTableView();
|
||||
|
||||
auto color = indexColor.GetColor(view, _defaultFg, false);
|
||||
auto color = indexColor.GetColor(_colorTable, _defaultFg, false);
|
||||
VERIFY_ARE_EQUAL(_colorTable[7], color);
|
||||
|
||||
color = indexColor.GetColor(view, _defaultFg, true);
|
||||
color = indexColor.GetColor(_colorTable, _defaultFg, true);
|
||||
VERIFY_ARE_EQUAL(_colorTable[15], color);
|
||||
|
||||
color = indexColor.GetColor(view, _defaultBg, false);
|
||||
color = indexColor.GetColor(_colorTable, _defaultBg, false);
|
||||
VERIFY_ARE_EQUAL(_colorTable[7], color);
|
||||
|
||||
color = indexColor.GetColor(view, _defaultBg, true);
|
||||
color = indexColor.GetColor(_colorTable, _defaultBg, true);
|
||||
VERIFY_ARE_EQUAL(_colorTable[15], color);
|
||||
}
|
||||
|
||||
@@ -110,18 +99,16 @@ void TextColorTests::TestBrightIndexColor()
|
||||
VERIFY_IS_TRUE(indexColor.IsLegacy());
|
||||
VERIFY_IS_FALSE(indexColor.IsRgb());
|
||||
|
||||
auto view = _GetTableView();
|
||||
|
||||
auto color = indexColor.GetColor(view, _defaultFg, false);
|
||||
auto color = indexColor.GetColor(_colorTable, _defaultFg, false);
|
||||
VERIFY_ARE_EQUAL(_colorTable[15], color);
|
||||
|
||||
color = indexColor.GetColor(view, _defaultFg, true);
|
||||
color = indexColor.GetColor(_colorTable, _defaultFg, true);
|
||||
VERIFY_ARE_EQUAL(_colorTable[15], color);
|
||||
|
||||
color = indexColor.GetColor(view, _defaultBg, false);
|
||||
color = indexColor.GetColor(_colorTable, _defaultBg, false);
|
||||
VERIFY_ARE_EQUAL(_colorTable[15], color);
|
||||
|
||||
color = indexColor.GetColor(view, _defaultBg, true);
|
||||
color = indexColor.GetColor(_colorTable, _defaultBg, true);
|
||||
VERIFY_ARE_EQUAL(_colorTable[15], color);
|
||||
}
|
||||
|
||||
@@ -134,18 +121,16 @@ void TextColorTests::TestRgbColor()
|
||||
VERIFY_IS_FALSE(rgbColor.IsLegacy());
|
||||
VERIFY_IS_TRUE(rgbColor.IsRgb());
|
||||
|
||||
auto view = _GetTableView();
|
||||
|
||||
auto color = rgbColor.GetColor(view, _defaultFg, false);
|
||||
auto color = rgbColor.GetColor(_colorTable, _defaultFg, false);
|
||||
VERIFY_ARE_EQUAL(myColor, color);
|
||||
|
||||
color = rgbColor.GetColor(view, _defaultFg, true);
|
||||
color = rgbColor.GetColor(_colorTable, _defaultFg, true);
|
||||
VERIFY_ARE_EQUAL(myColor, color);
|
||||
|
||||
color = rgbColor.GetColor(view, _defaultBg, false);
|
||||
color = rgbColor.GetColor(_colorTable, _defaultBg, false);
|
||||
VERIFY_ARE_EQUAL(myColor, color);
|
||||
|
||||
color = rgbColor.GetColor(view, _defaultBg, true);
|
||||
color = rgbColor.GetColor(_colorTable, _defaultBg, true);
|
||||
VERIFY_ARE_EQUAL(myColor, color);
|
||||
}
|
||||
|
||||
@@ -158,57 +143,55 @@ void TextColorTests::TestChangeColor()
|
||||
VERIFY_IS_FALSE(rgbColor.IsLegacy());
|
||||
VERIFY_IS_TRUE(rgbColor.IsRgb());
|
||||
|
||||
auto view = _GetTableView();
|
||||
|
||||
auto color = rgbColor.GetColor(view, _defaultFg, false);
|
||||
auto color = rgbColor.GetColor(_colorTable, _defaultFg, false);
|
||||
VERIFY_ARE_EQUAL(myColor, color);
|
||||
|
||||
color = rgbColor.GetColor(view, _defaultFg, true);
|
||||
color = rgbColor.GetColor(_colorTable, _defaultFg, true);
|
||||
VERIFY_ARE_EQUAL(myColor, color);
|
||||
|
||||
color = rgbColor.GetColor(view, _defaultBg, false);
|
||||
color = rgbColor.GetColor(_colorTable, _defaultBg, false);
|
||||
VERIFY_ARE_EQUAL(myColor, color);
|
||||
|
||||
color = rgbColor.GetColor(view, _defaultBg, true);
|
||||
color = rgbColor.GetColor(_colorTable, _defaultBg, true);
|
||||
VERIFY_ARE_EQUAL(myColor, color);
|
||||
|
||||
rgbColor.SetDefault();
|
||||
|
||||
color = rgbColor.GetColor(view, _defaultFg, false);
|
||||
color = rgbColor.GetColor(_colorTable, _defaultFg, false);
|
||||
VERIFY_ARE_EQUAL(_defaultFg, color);
|
||||
|
||||
color = rgbColor.GetColor(view, _defaultFg, true);
|
||||
color = rgbColor.GetColor(_colorTable, _defaultFg, true);
|
||||
VERIFY_ARE_EQUAL(_defaultFg, color);
|
||||
|
||||
color = rgbColor.GetColor(view, _defaultBg, false);
|
||||
color = rgbColor.GetColor(_colorTable, _defaultBg, false);
|
||||
VERIFY_ARE_EQUAL(_defaultBg, color);
|
||||
|
||||
color = rgbColor.GetColor(view, _defaultBg, true);
|
||||
color = rgbColor.GetColor(_colorTable, _defaultBg, true);
|
||||
VERIFY_ARE_EQUAL(_defaultBg, color);
|
||||
|
||||
rgbColor.SetIndex(7, false);
|
||||
color = rgbColor.GetColor(view, _defaultFg, false);
|
||||
color = rgbColor.GetColor(_colorTable, _defaultFg, false);
|
||||
VERIFY_ARE_EQUAL(_colorTable[7], color);
|
||||
|
||||
color = rgbColor.GetColor(view, _defaultFg, true);
|
||||
color = rgbColor.GetColor(_colorTable, _defaultFg, true);
|
||||
VERIFY_ARE_EQUAL(_colorTable[15], color);
|
||||
|
||||
color = rgbColor.GetColor(view, _defaultBg, false);
|
||||
color = rgbColor.GetColor(_colorTable, _defaultBg, false);
|
||||
VERIFY_ARE_EQUAL(_colorTable[7], color);
|
||||
|
||||
color = rgbColor.GetColor(view, _defaultBg, true);
|
||||
color = rgbColor.GetColor(_colorTable, _defaultBg, true);
|
||||
VERIFY_ARE_EQUAL(_colorTable[15], color);
|
||||
|
||||
rgbColor.SetIndex(15, false);
|
||||
color = rgbColor.GetColor(view, _defaultFg, false);
|
||||
color = rgbColor.GetColor(_colorTable, _defaultFg, false);
|
||||
VERIFY_ARE_EQUAL(_colorTable[15], color);
|
||||
|
||||
color = rgbColor.GetColor(view, _defaultFg, true);
|
||||
color = rgbColor.GetColor(_colorTable, _defaultFg, true);
|
||||
VERIFY_ARE_EQUAL(_colorTable[15], color);
|
||||
|
||||
color = rgbColor.GetColor(view, _defaultBg, false);
|
||||
color = rgbColor.GetColor(_colorTable, _defaultBg, false);
|
||||
VERIFY_ARE_EQUAL(_colorTable[15], color);
|
||||
|
||||
color = rgbColor.GetColor(view, _defaultBg, true);
|
||||
color = rgbColor.GetColor(_colorTable, _defaultBg, true);
|
||||
VERIFY_ARE_EQUAL(_colorTable[15], color);
|
||||
}
|
||||
|
||||
@@ -146,12 +146,12 @@
|
||||
<!-- **END VC LIBS HACK** -->
|
||||
|
||||
<!-- This is required to get the package dependency in the AppXManifest. -->
|
||||
<Import Project="..\..\..\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('..\..\..\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets')" />
|
||||
<Import Project="..\..\..\packages\Microsoft.UI.Xaml.2.6.2-prerelease.210818003\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('..\..\..\packages\Microsoft.UI.Xaml.2.6.2-prerelease.210818003\build\native\Microsoft.UI.Xaml.targets')" />
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('..\..\..\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets'))" />
|
||||
<Error Condition="!Exists('..\..\..\packages\Microsoft.UI.Xaml.2.6.2-prerelease.210818003\build\native\Microsoft.UI.Xaml.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.UI.Xaml.2.6.2-prerelease.210818003\build\native\Microsoft.UI.Xaml.targets'))" />
|
||||
</Target>
|
||||
|
||||
<Import Project="$(SolutionDir)build\rules\CollectWildcardResources.targets" />
|
||||
|
||||
@@ -140,8 +140,10 @@
|
||||
<Extensions>
|
||||
<uap7:Extension Category="windows.sharedFonts">
|
||||
<uap7:SharedFonts>
|
||||
<uap4:Font File="Cascadia.ttf" />
|
||||
<uap4:Font File="CascadiaCode.ttf" />
|
||||
<uap4:Font File="CascadiaCodeItalic.ttf" />
|
||||
<uap4:Font File="CascadiaMono.ttf" />
|
||||
<uap4:Font File="CascadiaMonoItalic.ttf" />
|
||||
</uap7:SharedFonts>
|
||||
</uap7:Extension>
|
||||
</Extensions>
|
||||
|
||||
@@ -140,8 +140,10 @@
|
||||
<Extensions>
|
||||
<uap7:Extension Category="windows.sharedFonts">
|
||||
<uap7:SharedFonts>
|
||||
<uap4:Font File="Cascadia.ttf" />
|
||||
<uap4:Font File="CascadiaCode.ttf" />
|
||||
<uap4:Font File="CascadiaCodeItalic.ttf" />
|
||||
<uap4:Font File="CascadiaMono.ttf" />
|
||||
<uap4:Font File="CascadiaMonoItalic.ttf" />
|
||||
</uap7:SharedFonts>
|
||||
</uap7:Extension>
|
||||
</Extensions>
|
||||
|
||||
@@ -12,13 +12,9 @@
|
||||
<Link>Images\%(RecursiveDir)%(FileName)%(Extension)</Link>
|
||||
</Content>
|
||||
<!-- Fonts -->
|
||||
<Content Include="$(OpenConsoleDir)res\Cascadia.ttf" Condition="'$(WindowsTerminalOfficialBuild)'=='true'">
|
||||
<Content Include="$(OpenConsoleDir)res\fonts\*.ttf" Condition="'$(WindowsTerminalOfficialBuild)'=='true'">
|
||||
<DeploymentContent>true</DeploymentContent>
|
||||
<Link>%(RecursiveDir)%(FileName)%(Extension)</Link>
|
||||
</Content>
|
||||
<Content Include="$(OpenConsoleDir)res\CascadiaMono.ttf" Condition="'$(WindowsTerminalOfficialBuild)'=='true'">
|
||||
<DeploymentContent>true</DeploymentContent>
|
||||
<Link>%(RecursiveDir)%(FileName)%(Extension)</Link>
|
||||
<Link>%(FileName)%(Extension)</Link>
|
||||
</Content>
|
||||
<!-- Profile Icons -->
|
||||
<Content Include="$(OpenConsoleDir)src\cascadia\CascadiaPackage\ProfileIcons\**\*">
|
||||
|
||||
@@ -397,6 +397,10 @@ namespace SettingsModelLocalTests
|
||||
"name":"action6",
|
||||
"command": { "action": "newWindow", "startingDirectory":"C:\\foo", "commandline": "bar.exe" }
|
||||
},
|
||||
{
|
||||
"name":"action7_startingDirectoryWithTrailingSlash",
|
||||
"command": { "action": "newWindow", "startingDirectory":"C:\\", "commandline": "bar.exe" }
|
||||
},
|
||||
])" };
|
||||
|
||||
const auto commands0Json = VerifyParseSucceeded(commands0String);
|
||||
@@ -405,7 +409,7 @@ namespace SettingsModelLocalTests
|
||||
VERIFY_ARE_EQUAL(0u, commands.Size());
|
||||
auto warnings = implementation::Command::LayerJson(commands, commands0Json);
|
||||
VERIFY_ARE_EQUAL(0u, warnings.size());
|
||||
VERIFY_ARE_EQUAL(7u, commands.Size());
|
||||
VERIFY_ARE_EQUAL(8u, commands.Size());
|
||||
|
||||
{
|
||||
auto command = commands.Lookup(L"action0");
|
||||
@@ -503,5 +507,20 @@ namespace SettingsModelLocalTests
|
||||
L"cmdline: \"%s\"", cmdline.c_str()));
|
||||
VERIFY_ARE_EQUAL(L"--startingDirectory \"C:\\foo\" -- \"bar.exe\"", terminalArgs.ToCommandline());
|
||||
}
|
||||
|
||||
{
|
||||
auto command = commands.Lookup(L"action7_startingDirectoryWithTrailingSlash");
|
||||
VERIFY_IS_NOT_NULL(command);
|
||||
VERIFY_IS_NOT_NULL(command.ActionAndArgs());
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::NewWindow, command.ActionAndArgs().Action());
|
||||
const auto& realArgs = command.ActionAndArgs().Args().try_as<NewWindowArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
const auto& terminalArgs = realArgs.TerminalArgs();
|
||||
VERIFY_IS_NOT_NULL(terminalArgs);
|
||||
auto cmdline = terminalArgs.ToCommandline();
|
||||
Log::Comment(NoThrowString().Format(
|
||||
L"cmdline: \"%s\"", cmdline.c_str()));
|
||||
VERIFY_ARE_EQUAL(L"--startingDirectory \"C:\\\\\" -- \"bar.exe\"", terminalArgs.ToCommandline());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ using namespace WEX::TestExecution;
|
||||
using namespace WEX::Common;
|
||||
using namespace winrt::Microsoft::Terminal::Settings::Model;
|
||||
using namespace winrt::Microsoft::Terminal::Control;
|
||||
using VirtualKeyModifiers = winrt::Windows::System::VirtualKeyModifiers;
|
||||
|
||||
namespace SettingsModelLocalTests
|
||||
{
|
||||
@@ -1970,9 +1971,9 @@ namespace SettingsModelLocalTests
|
||||
auto settings = implementation::CascadiaSettings::FromJson(settingsObject);
|
||||
|
||||
VERIFY_ARE_EQUAL(3u, settings->_globals->_actionMap->_KeyMap.size());
|
||||
VERIFY_IS_NULL(settings->_globals->_actionMap->GetActionByKeyChord({ KeyModifiers::Ctrl, static_cast<int32_t>('a') }));
|
||||
VERIFY_IS_NULL(settings->_globals->_actionMap->GetActionByKeyChord({ KeyModifiers::Ctrl, static_cast<int32_t>('b') }));
|
||||
VERIFY_IS_NULL(settings->_globals->_actionMap->GetActionByKeyChord({ KeyModifiers::Ctrl, static_cast<int32_t>('c') }));
|
||||
VERIFY_IS_NULL(settings->_globals->_actionMap->GetActionByKeyChord({ VirtualKeyModifiers::Control, static_cast<int32_t>('A'), 0 }));
|
||||
VERIFY_IS_NULL(settings->_globals->_actionMap->GetActionByKeyChord({ VirtualKeyModifiers::Control, static_cast<int32_t>('B'), 0 }));
|
||||
VERIFY_IS_NULL(settings->_globals->_actionMap->GetActionByKeyChord({ VirtualKeyModifiers::Control, static_cast<int32_t>('C'), 0 }));
|
||||
|
||||
for (const auto& warning : settings->_globals->_keybindingsWarnings)
|
||||
{
|
||||
@@ -2123,7 +2124,7 @@ namespace SettingsModelLocalTests
|
||||
VERIFY_ARE_EQUAL(1u, nameMap.Size());
|
||||
|
||||
{
|
||||
KeyChord kc{ true, false, false, static_cast<int32_t>('A') };
|
||||
KeyChord kc{ true, false, false, false, static_cast<int32_t>('A'), 0 };
|
||||
auto actionAndArgs = ::TestUtils::GetActionAndArgs(*actionMap, kc);
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, actionAndArgs.Action());
|
||||
const auto& realArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
|
||||
@@ -2140,7 +2141,7 @@ namespace SettingsModelLocalTests
|
||||
Log::Comment(L"Note that we're skipping ctrl+B, since that doesn't have `keys` set.");
|
||||
|
||||
{
|
||||
KeyChord kc{ true, false, false, static_cast<int32_t>('C') };
|
||||
KeyChord kc{ true, false, false, false, static_cast<int32_t>('C'), 0 };
|
||||
auto actionAndArgs = ::TestUtils::GetActionAndArgs(*actionMap, kc);
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, actionAndArgs.Action());
|
||||
const auto& realArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
|
||||
@@ -2154,7 +2155,7 @@ namespace SettingsModelLocalTests
|
||||
VERIFY_IS_TRUE(realArgs.TerminalArgs().Profile().empty());
|
||||
}
|
||||
{
|
||||
KeyChord kc{ true, false, false, static_cast<int32_t>('D') };
|
||||
KeyChord kc{ true, false, false, false, static_cast<int32_t>('D'), 0 };
|
||||
auto actionAndArgs = ::TestUtils::GetActionAndArgs(*actionMap, kc);
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, actionAndArgs.Action());
|
||||
const auto& realArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
|
||||
@@ -2168,7 +2169,7 @@ namespace SettingsModelLocalTests
|
||||
VERIFY_IS_TRUE(realArgs.TerminalArgs().Profile().empty());
|
||||
}
|
||||
{
|
||||
KeyChord kc{ true, false, false, static_cast<int32_t>('E') };
|
||||
KeyChord kc{ true, false, false, false, static_cast<int32_t>('E'), 0 };
|
||||
auto actionAndArgs = ::TestUtils::GetActionAndArgs(*actionMap, kc);
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, actionAndArgs.Action());
|
||||
const auto& realArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
|
||||
@@ -2182,7 +2183,7 @@ namespace SettingsModelLocalTests
|
||||
VERIFY_IS_TRUE(realArgs.TerminalArgs().Profile().empty());
|
||||
}
|
||||
{
|
||||
KeyChord kc{ true, false, false, static_cast<int32_t>('F') };
|
||||
KeyChord kc{ true, false, false, false, static_cast<int32_t>('F'), 0 };
|
||||
auto actionAndArgs = ::TestUtils::GetActionAndArgs(*actionMap, kc);
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, actionAndArgs.Action());
|
||||
const auto& realArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
|
||||
@@ -2840,7 +2841,7 @@ namespace SettingsModelLocalTests
|
||||
VERIFY_ARE_EQUAL(0u, settings->_warnings.Size());
|
||||
VERIFY_ARE_EQUAL(1u, nameMap.Size());
|
||||
|
||||
const KeyChord expectedKeyChord{ true, false, true, static_cast<int>('W') };
|
||||
const KeyChord expectedKeyChord{ true, false, true, false, static_cast<int>('W'), 0 };
|
||||
{
|
||||
// Verify NameMap returns correct value
|
||||
const auto& cmd{ nameMap.TryLookup(L"foo") };
|
||||
|
||||
@@ -15,6 +15,7 @@ using namespace winrt::Microsoft::Terminal::Control;
|
||||
using namespace WEX::Logging;
|
||||
using namespace WEX::TestExecution;
|
||||
using namespace WEX::Common;
|
||||
using VirtualKeyModifiers = winrt::Windows::System::VirtualKeyModifiers;
|
||||
|
||||
namespace SettingsModelLocalTests
|
||||
{
|
||||
@@ -35,10 +36,15 @@ namespace SettingsModelLocalTests
|
||||
TEST_CLASS_PROPERTY(L"UAP:AppXManifest", L"TestHostAppXManifest.xml")
|
||||
END_TEST_CLASS()
|
||||
|
||||
TEST_METHOD(KeyChords);
|
||||
TEST_METHOD(ManyKeysSameAction);
|
||||
TEST_METHOD(LayerKeybindings);
|
||||
TEST_METHOD(UnbindKeybindings);
|
||||
|
||||
TEST_METHOD(LayerScancodeKeybindings);
|
||||
|
||||
TEST_METHOD(TestExplicitUnbind);
|
||||
|
||||
TEST_METHOD(TestArbitraryArgs);
|
||||
TEST_METHOD(TestSplitPaneArgs);
|
||||
|
||||
@@ -52,6 +58,7 @@ namespace SettingsModelLocalTests
|
||||
TEST_METHOD(TestMoveTabArgs);
|
||||
|
||||
TEST_METHOD(TestGetKeyBindingForAction);
|
||||
TEST_METHOD(KeybindingsWithoutVkey);
|
||||
|
||||
TEST_CLASS_SETUP(ClassSetup)
|
||||
{
|
||||
@@ -60,6 +67,69 @@ namespace SettingsModelLocalTests
|
||||
}
|
||||
};
|
||||
|
||||
void KeyBindingsTests::KeyChords()
|
||||
{
|
||||
struct testCase
|
||||
{
|
||||
VirtualKeyModifiers modifiers;
|
||||
int32_t vkey;
|
||||
int32_t scanCode;
|
||||
std::wstring_view expected;
|
||||
};
|
||||
|
||||
static constexpr std::array testCases{
|
||||
testCase{
|
||||
VirtualKeyModifiers::None,
|
||||
'A',
|
||||
0,
|
||||
L"a",
|
||||
},
|
||||
testCase{
|
||||
VirtualKeyModifiers::Control,
|
||||
'A',
|
||||
0,
|
||||
L"ctrl+a",
|
||||
},
|
||||
testCase{
|
||||
VirtualKeyModifiers::Control | VirtualKeyModifiers::Shift,
|
||||
VK_OEM_PLUS,
|
||||
0,
|
||||
L"ctrl+shift+plus",
|
||||
},
|
||||
testCase{
|
||||
VirtualKeyModifiers::Control | VirtualKeyModifiers::Menu | VirtualKeyModifiers::Shift | VirtualKeyModifiers::Windows,
|
||||
255,
|
||||
0,
|
||||
L"win+ctrl+alt+shift+vk(255)",
|
||||
},
|
||||
testCase{
|
||||
VirtualKeyModifiers::Control | VirtualKeyModifiers::Menu | VirtualKeyModifiers::Shift | VirtualKeyModifiers::Windows,
|
||||
0,
|
||||
123,
|
||||
L"win+ctrl+alt+shift+sc(123)",
|
||||
},
|
||||
};
|
||||
|
||||
for (const auto& tc : testCases)
|
||||
{
|
||||
Log::Comment(NoThrowString().Format(L"Testing case:\"%s\"", tc.expected.data()));
|
||||
|
||||
const auto actualString = KeyChordSerialization::ToString({ tc.modifiers, tc.vkey, tc.scanCode });
|
||||
VERIFY_ARE_EQUAL(tc.expected, actualString);
|
||||
|
||||
auto expectedVkey = tc.vkey;
|
||||
if (!expectedVkey)
|
||||
{
|
||||
expectedVkey = MapVirtualKeyW(tc.scanCode, MAPVK_VSC_TO_VK_EX);
|
||||
}
|
||||
|
||||
const auto actualKeyChord = KeyChordSerialization::FromString(actualString);
|
||||
VERIFY_ARE_EQUAL(tc.modifiers, actualKeyChord.Modifiers());
|
||||
VERIFY_ARE_EQUAL(expectedVkey, actualKeyChord.Vkey());
|
||||
VERIFY_ARE_EQUAL(tc.scanCode, actualKeyChord.ScanCode());
|
||||
}
|
||||
}
|
||||
|
||||
void KeyBindingsTests::ManyKeysSameAction()
|
||||
{
|
||||
const std::string bindings0String{ R"([ { "command": "copy", "keys": ["ctrl+c"] } ])" };
|
||||
@@ -74,7 +144,6 @@ namespace SettingsModelLocalTests
|
||||
const auto bindings2Json = VerifyParseSucceeded(bindings2String);
|
||||
|
||||
auto actionMap = winrt::make_self<implementation::ActionMap>();
|
||||
VERIFY_IS_NOT_NULL(actionMap);
|
||||
VERIFY_ARE_EQUAL(0u, actionMap->_KeyMap.size());
|
||||
|
||||
actionMap->LayerJson(bindings0Json);
|
||||
@@ -98,7 +167,6 @@ namespace SettingsModelLocalTests
|
||||
const auto bindings2Json = VerifyParseSucceeded(bindings2String);
|
||||
|
||||
auto actionMap = winrt::make_self<implementation::ActionMap>();
|
||||
VERIFY_IS_NOT_NULL(actionMap);
|
||||
VERIFY_ARE_EQUAL(0u, actionMap->_KeyMap.size());
|
||||
|
||||
actionMap->LayerJson(bindings0Json);
|
||||
@@ -128,7 +196,6 @@ namespace SettingsModelLocalTests
|
||||
const auto bindings5Json = VerifyParseSucceeded(bindings5String);
|
||||
|
||||
auto actionMap = winrt::make_self<implementation::ActionMap>();
|
||||
VERIFY_IS_NOT_NULL(actionMap);
|
||||
VERIFY_ARE_EQUAL(0u, actionMap->_KeyMap.size());
|
||||
|
||||
actionMap->LayerJson(bindings0Json);
|
||||
@@ -141,7 +208,7 @@ namespace SettingsModelLocalTests
|
||||
L"Try unbinding a key using `\"unbound\"` to unbind the key"));
|
||||
actionMap->LayerJson(bindings2Json);
|
||||
VERIFY_ARE_EQUAL(1u, actionMap->_KeyMap.size());
|
||||
VERIFY_IS_NULL(actionMap->GetActionByKeyChord({ KeyModifiers::Ctrl, static_cast<int32_t>('c') }));
|
||||
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"));
|
||||
@@ -151,7 +218,7 @@ namespace SettingsModelLocalTests
|
||||
// Then try layering in the bad setting
|
||||
actionMap->LayerJson(bindings3Json);
|
||||
VERIFY_ARE_EQUAL(1u, actionMap->_KeyMap.size());
|
||||
VERIFY_IS_NULL(actionMap->GetActionByKeyChord({ KeyModifiers::Ctrl, static_cast<int32_t>('c') }));
|
||||
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"));
|
||||
@@ -161,7 +228,7 @@ namespace SettingsModelLocalTests
|
||||
// Then try layering in the bad setting
|
||||
actionMap->LayerJson(bindings4Json);
|
||||
VERIFY_ARE_EQUAL(1u, actionMap->_KeyMap.size());
|
||||
VERIFY_IS_NULL(actionMap->GetActionByKeyChord({ KeyModifiers::Ctrl, static_cast<int32_t>('c') }));
|
||||
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"));
|
||||
@@ -171,13 +238,38 @@ namespace SettingsModelLocalTests
|
||||
// Then try layering in the bad setting
|
||||
actionMap->LayerJson(bindings5Json);
|
||||
VERIFY_ARE_EQUAL(1u, actionMap->_KeyMap.size());
|
||||
VERIFY_IS_NULL(actionMap->GetActionByKeyChord({ KeyModifiers::Ctrl, static_cast<int32_t>('c') }));
|
||||
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);
|
||||
VERIFY_ARE_EQUAL(1u, actionMap->_KeyMap.size());
|
||||
VERIFY_IS_NULL(actionMap->GetActionByKeyChord({ KeyModifiers::Ctrl, static_cast<int32_t>('c') }));
|
||||
VERIFY_IS_NULL(actionMap->GetActionByKeyChord({ VirtualKeyModifiers::Control, static_cast<int32_t>('C'), 0 }));
|
||||
}
|
||||
|
||||
void KeyBindingsTests::TestExplicitUnbind()
|
||||
{
|
||||
const std::string bindings0String{ R"([ { "command": "copy", "keys": ["ctrl+c"] } ])" };
|
||||
const std::string bindings1String{ R"([ { "command": "unbound", "keys": ["ctrl+c"] } ])" };
|
||||
const std::string bindings2String{ R"([ { "command": "copy", "keys": ["ctrl+c"] } ])" };
|
||||
|
||||
const auto bindings0Json = VerifyParseSucceeded(bindings0String);
|
||||
const auto bindings1Json = VerifyParseSucceeded(bindings1String);
|
||||
const auto bindings2Json = VerifyParseSucceeded(bindings2String);
|
||||
|
||||
const KeyChord keyChord{ VirtualKeyModifiers::Control, static_cast<int32_t>('C'), 0 };
|
||||
|
||||
auto actionMap = winrt::make_self<implementation::ActionMap>();
|
||||
VERIFY_IS_FALSE(actionMap->IsKeyChordExplicitlyUnbound(keyChord));
|
||||
|
||||
actionMap->LayerJson(bindings0Json);
|
||||
VERIFY_IS_FALSE(actionMap->IsKeyChordExplicitlyUnbound(keyChord));
|
||||
|
||||
actionMap->LayerJson(bindings1Json);
|
||||
VERIFY_IS_TRUE(actionMap->IsKeyChordExplicitlyUnbound(keyChord));
|
||||
|
||||
actionMap->LayerJson(bindings2Json);
|
||||
VERIFY_IS_FALSE(actionMap->IsKeyChordExplicitlyUnbound(keyChord));
|
||||
}
|
||||
|
||||
void KeyBindingsTests::TestArbitraryArgs()
|
||||
@@ -202,7 +294,6 @@ namespace SettingsModelLocalTests
|
||||
const auto bindings0Json = VerifyParseSucceeded(bindings0String);
|
||||
|
||||
auto actionMap = winrt::make_self<implementation::ActionMap>();
|
||||
VERIFY_IS_NOT_NULL(actionMap);
|
||||
VERIFY_ARE_EQUAL(0u, actionMap->_KeyMap.size());
|
||||
actionMap->LayerJson(bindings0Json);
|
||||
VERIFY_ARE_EQUAL(10u, actionMap->_KeyMap.size());
|
||||
@@ -210,10 +301,9 @@ namespace SettingsModelLocalTests
|
||||
{
|
||||
Log::Comment(NoThrowString().Format(
|
||||
L"Verify that `copy` without args parses as Copy(SingleLine=false)"));
|
||||
KeyChord kc{ true, false, false, static_cast<int32_t>('C') };
|
||||
KeyChord kc{ true, false, false, false, static_cast<int32_t>('C'), 0 };
|
||||
auto actionAndArgs = ::TestUtils::GetActionAndArgs(*actionMap, kc);
|
||||
const auto& realArgs = actionAndArgs.Args().try_as<CopyTextArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
const auto& realArgs = actionAndArgs.Args().as<CopyTextArgs>();
|
||||
// Verify the args have the expected value
|
||||
VERIFY_IS_FALSE(realArgs.SingleLine());
|
||||
}
|
||||
@@ -221,10 +311,9 @@ namespace SettingsModelLocalTests
|
||||
{
|
||||
Log::Comment(NoThrowString().Format(
|
||||
L"Verify that `copy` with args parses them correctly"));
|
||||
KeyChord kc{ true, false, true, static_cast<int32_t>('C') };
|
||||
KeyChord kc{ true, false, true, false, static_cast<int32_t>('C'), 0 };
|
||||
auto actionAndArgs = ::TestUtils::GetActionAndArgs(*actionMap, kc);
|
||||
const auto& realArgs = actionAndArgs.Args().try_as<CopyTextArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
const auto& realArgs = actionAndArgs.Args().as<CopyTextArgs>();
|
||||
// Verify the args have the expected value
|
||||
VERIFY_IS_FALSE(realArgs.SingleLine());
|
||||
}
|
||||
@@ -232,10 +321,9 @@ namespace SettingsModelLocalTests
|
||||
{
|
||||
Log::Comment(NoThrowString().Format(
|
||||
L"Verify that `copy` with args parses them correctly"));
|
||||
KeyChord kc{ false, true, true, static_cast<int32_t>('C') };
|
||||
KeyChord kc{ false, true, true, false, static_cast<int32_t>('C'), 0 };
|
||||
auto actionAndArgs = ::TestUtils::GetActionAndArgs(*actionMap, kc);
|
||||
const auto& realArgs = actionAndArgs.Args().try_as<CopyTextArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
const auto& realArgs = actionAndArgs.Args().as<CopyTextArgs>();
|
||||
// Verify the args have the expected value
|
||||
VERIFY_IS_TRUE(realArgs.SingleLine());
|
||||
}
|
||||
@@ -243,11 +331,10 @@ namespace SettingsModelLocalTests
|
||||
{
|
||||
Log::Comment(NoThrowString().Format(
|
||||
L"Verify that `newTab` without args parses as NewTab(Index=null)"));
|
||||
KeyChord kc{ true, false, false, static_cast<int32_t>('T') };
|
||||
KeyChord kc{ true, false, false, false, static_cast<int32_t>('T'), 0 };
|
||||
auto actionAndArgs = ::TestUtils::GetActionAndArgs(*actionMap, kc);
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::NewTab, actionAndArgs.Action());
|
||||
const auto& realArgs = actionAndArgs.Args().try_as<NewTabArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
const auto& realArgs = actionAndArgs.Args().as<NewTabArgs>();
|
||||
// Verify the args have the expected value
|
||||
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
|
||||
VERIFY_IS_NULL(realArgs.TerminalArgs().ProfileIndex());
|
||||
@@ -255,11 +342,10 @@ namespace SettingsModelLocalTests
|
||||
{
|
||||
Log::Comment(NoThrowString().Format(
|
||||
L"Verify that `newTab` parses args correctly"));
|
||||
KeyChord kc{ true, false, true, static_cast<int32_t>('T') };
|
||||
KeyChord kc{ true, false, true, false, static_cast<int32_t>('T'), 0 };
|
||||
auto actionAndArgs = ::TestUtils::GetActionAndArgs(*actionMap, kc);
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::NewTab, actionAndArgs.Action());
|
||||
const auto& realArgs = actionAndArgs.Args().try_as<NewTabArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
const auto& realArgs = actionAndArgs.Args().as<NewTabArgs>();
|
||||
// Verify the args have the expected value
|
||||
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
|
||||
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs().ProfileIndex());
|
||||
@@ -269,11 +355,10 @@ namespace SettingsModelLocalTests
|
||||
Log::Comment(NoThrowString().Format(
|
||||
L"Verify that `newTab` with an index greater than the legacy "
|
||||
L"args afforded parses correctly"));
|
||||
KeyChord kc{ true, false, true, static_cast<int32_t>('Y') };
|
||||
KeyChord kc{ true, false, true, false, static_cast<int32_t>('Y'), 0 };
|
||||
auto actionAndArgs = ::TestUtils::GetActionAndArgs(*actionMap, kc);
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::NewTab, actionAndArgs.Action());
|
||||
const auto& realArgs = actionAndArgs.Args().try_as<NewTabArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
const auto& realArgs = actionAndArgs.Args().as<NewTabArgs>();
|
||||
// Verify the args have the expected value
|
||||
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
|
||||
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs().ProfileIndex());
|
||||
@@ -283,11 +368,10 @@ namespace SettingsModelLocalTests
|
||||
{
|
||||
Log::Comment(NoThrowString().Format(
|
||||
L"Verify that `copy` ignores args it doesn't understand"));
|
||||
KeyChord kc{ true, false, true, static_cast<int32_t>('B') };
|
||||
KeyChord kc{ true, false, true, false, static_cast<int32_t>('B'), 0 };
|
||||
auto actionAndArgs = ::TestUtils::GetActionAndArgs(*actionMap, kc);
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::CopyText, actionAndArgs.Action());
|
||||
const auto& realArgs = actionAndArgs.Args().try_as<CopyTextArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
const auto& realArgs = actionAndArgs.Args().as<CopyTextArgs>();
|
||||
// Verify the args have the expected value
|
||||
VERIFY_IS_FALSE(realArgs.SingleLine());
|
||||
}
|
||||
@@ -295,11 +379,10 @@ namespace SettingsModelLocalTests
|
||||
{
|
||||
Log::Comment(NoThrowString().Format(
|
||||
L"Verify that `copy` null as it's `args` parses as the default option"));
|
||||
KeyChord kc{ true, false, true, static_cast<int32_t>('B') };
|
||||
KeyChord kc{ true, false, true, false, static_cast<int32_t>('B'), 0 };
|
||||
auto actionAndArgs = ::TestUtils::GetActionAndArgs(*actionMap, kc);
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::CopyText, actionAndArgs.Action());
|
||||
const auto& realArgs = actionAndArgs.Args().try_as<CopyTextArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
const auto& realArgs = actionAndArgs.Args().as<CopyTextArgs>();
|
||||
// Verify the args have the expected value
|
||||
VERIFY_IS_FALSE(realArgs.SingleLine());
|
||||
}
|
||||
@@ -307,11 +390,10 @@ namespace SettingsModelLocalTests
|
||||
{
|
||||
Log::Comment(NoThrowString().Format(
|
||||
L"Verify that `adjustFontSize` with a positive delta parses args correctly"));
|
||||
KeyChord kc{ true, false, false, static_cast<int32_t>('F') };
|
||||
KeyChord kc{ true, false, false, false, static_cast<int32_t>('F'), 0 };
|
||||
auto actionAndArgs = ::TestUtils::GetActionAndArgs(*actionMap, kc);
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::AdjustFontSize, actionAndArgs.Action());
|
||||
const auto& realArgs = actionAndArgs.Args().try_as<AdjustFontSizeArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
const auto& realArgs = actionAndArgs.Args().as<AdjustFontSizeArgs>();
|
||||
// Verify the args have the expected value
|
||||
VERIFY_ARE_EQUAL(1, realArgs.Delta());
|
||||
}
|
||||
@@ -319,11 +401,10 @@ namespace SettingsModelLocalTests
|
||||
{
|
||||
Log::Comment(NoThrowString().Format(
|
||||
L"Verify that `adjustFontSize` with a negative delta parses args correctly"));
|
||||
KeyChord kc{ true, false, false, static_cast<int32_t>('G') };
|
||||
KeyChord kc{ true, false, false, false, static_cast<int32_t>('G'), 0 };
|
||||
auto actionAndArgs = ::TestUtils::GetActionAndArgs(*actionMap, kc);
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::AdjustFontSize, actionAndArgs.Action());
|
||||
const auto& realArgs = actionAndArgs.Args().try_as<AdjustFontSizeArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
const auto& realArgs = actionAndArgs.Args().as<AdjustFontSizeArgs>();
|
||||
// Verify the args have the expected value
|
||||
VERIFY_ARE_EQUAL(-1, realArgs.Delta());
|
||||
}
|
||||
@@ -341,44 +422,39 @@ namespace SettingsModelLocalTests
|
||||
const auto bindings0Json = VerifyParseSucceeded(bindings0String);
|
||||
|
||||
auto actionMap = winrt::make_self<implementation::ActionMap>();
|
||||
VERIFY_IS_NOT_NULL(actionMap);
|
||||
VERIFY_ARE_EQUAL(0u, actionMap->_KeyMap.size());
|
||||
actionMap->LayerJson(bindings0Json);
|
||||
VERIFY_ARE_EQUAL(4u, actionMap->_KeyMap.size());
|
||||
|
||||
{
|
||||
KeyChord kc{ true, false, false, static_cast<int32_t>('D') };
|
||||
KeyChord kc{ true, false, false, false, static_cast<int32_t>('D'), 0 };
|
||||
auto actionAndArgs = ::TestUtils::GetActionAndArgs(*actionMap, kc);
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, actionAndArgs.Action());
|
||||
const auto& realArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
const auto& realArgs = actionAndArgs.Args().as<SplitPaneArgs>();
|
||||
// Verify the args have the expected value
|
||||
VERIFY_ARE_EQUAL(SplitState::Vertical, realArgs.SplitStyle());
|
||||
}
|
||||
{
|
||||
KeyChord kc{ true, false, false, static_cast<int32_t>('E') };
|
||||
KeyChord kc{ true, false, false, false, static_cast<int32_t>('E'), 0 };
|
||||
auto actionAndArgs = ::TestUtils::GetActionAndArgs(*actionMap, kc);
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, actionAndArgs.Action());
|
||||
const auto& realArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
const auto& realArgs = actionAndArgs.Args().as<SplitPaneArgs>();
|
||||
// Verify the args have the expected value
|
||||
VERIFY_ARE_EQUAL(SplitState::Horizontal, realArgs.SplitStyle());
|
||||
}
|
||||
{
|
||||
KeyChord kc{ true, false, false, static_cast<int32_t>('G') };
|
||||
KeyChord kc{ true, false, false, false, static_cast<int32_t>('G'), 0 };
|
||||
auto actionAndArgs = ::TestUtils::GetActionAndArgs(*actionMap, kc);
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, actionAndArgs.Action());
|
||||
const auto& realArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
const auto& realArgs = actionAndArgs.Args().as<SplitPaneArgs>();
|
||||
// Verify the args have the expected value
|
||||
VERIFY_ARE_EQUAL(SplitState::Automatic, realArgs.SplitStyle());
|
||||
}
|
||||
{
|
||||
KeyChord kc{ true, false, false, static_cast<int32_t>('H') };
|
||||
KeyChord kc{ true, false, false, false, static_cast<int32_t>('H'), 0 };
|
||||
auto actionAndArgs = ::TestUtils::GetActionAndArgs(*actionMap, kc);
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, actionAndArgs.Action());
|
||||
const auto& realArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
const auto& realArgs = actionAndArgs.Args().as<SplitPaneArgs>();
|
||||
// Verify the args have the expected value
|
||||
VERIFY_ARE_EQUAL(SplitState::Automatic, realArgs.SplitStyle());
|
||||
}
|
||||
@@ -395,37 +471,33 @@ namespace SettingsModelLocalTests
|
||||
const auto bindings0Json = VerifyParseSucceeded(bindings0String);
|
||||
|
||||
auto actionMap = winrt::make_self<implementation::ActionMap>();
|
||||
VERIFY_IS_NOT_NULL(actionMap);
|
||||
VERIFY_ARE_EQUAL(0u, actionMap->_KeyMap.size());
|
||||
actionMap->LayerJson(bindings0Json);
|
||||
VERIFY_ARE_EQUAL(3u, actionMap->_KeyMap.size());
|
||||
|
||||
{
|
||||
KeyChord kc{ true, false, false, static_cast<int32_t>('C') };
|
||||
KeyChord kc{ true, false, false, false, static_cast<int32_t>('C'), 0 };
|
||||
auto actionAndArgs = ::TestUtils::GetActionAndArgs(*actionMap, kc);
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::SetTabColor, actionAndArgs.Action());
|
||||
const auto& realArgs = actionAndArgs.Args().try_as<SetTabColorArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
const auto& realArgs = actionAndArgs.Args().as<SetTabColorArgs>();
|
||||
// Verify the args have the expected value
|
||||
VERIFY_IS_NULL(realArgs.TabColor());
|
||||
}
|
||||
{
|
||||
KeyChord kc{ true, false, false, static_cast<int32_t>('D') };
|
||||
KeyChord kc{ true, false, false, false, static_cast<int32_t>('D'), 0 };
|
||||
auto actionAndArgs = ::TestUtils::GetActionAndArgs(*actionMap, kc);
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::SetTabColor, actionAndArgs.Action());
|
||||
const auto& realArgs = actionAndArgs.Args().try_as<SetTabColorArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
const auto& realArgs = actionAndArgs.Args().as<SetTabColorArgs>();
|
||||
// Verify the args have the expected value
|
||||
VERIFY_IS_NOT_NULL(realArgs.TabColor());
|
||||
// Remember that COLORREFs are actually BBGGRR order, while the string is in #RRGGBB order
|
||||
VERIFY_ARE_EQUAL(til::color(0x563412), til::color(realArgs.TabColor().Value()));
|
||||
}
|
||||
{
|
||||
KeyChord kc{ true, false, false, static_cast<int32_t>('F') };
|
||||
KeyChord kc{ true, false, false, false, static_cast<int32_t>('F'), 0 };
|
||||
auto actionAndArgs = ::TestUtils::GetActionAndArgs(*actionMap, kc);
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::SetTabColor, actionAndArgs.Action());
|
||||
const auto& realArgs = actionAndArgs.Args().try_as<SetTabColorArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
const auto& realArgs = actionAndArgs.Args().as<SetTabColorArgs>();
|
||||
// Verify the args have the expected value
|
||||
VERIFY_IS_NULL(realArgs.TabColor());
|
||||
}
|
||||
@@ -440,16 +512,14 @@ namespace SettingsModelLocalTests
|
||||
const auto bindings0Json = VerifyParseSucceeded(bindings0String);
|
||||
|
||||
auto actionMap = winrt::make_self<implementation::ActionMap>();
|
||||
VERIFY_IS_NOT_NULL(actionMap);
|
||||
VERIFY_ARE_EQUAL(0u, actionMap->_KeyMap.size());
|
||||
actionMap->LayerJson(bindings0Json);
|
||||
VERIFY_ARE_EQUAL(1u, actionMap->_KeyMap.size());
|
||||
|
||||
{
|
||||
KeyChord kc{ true, false, false, static_cast<int32_t>('C') };
|
||||
KeyChord kc{ true, false, false, false, static_cast<int32_t>('C'), 0 };
|
||||
auto actionAndArgs = ::TestUtils::GetActionAndArgs(*actionMap, kc);
|
||||
const auto& realArgs = actionAndArgs.Args().try_as<CopyTextArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
const auto& realArgs = actionAndArgs.Args().as<CopyTextArgs>();
|
||||
// Verify the args have the expected value
|
||||
VERIFY_IS_FALSE(realArgs.SingleLine());
|
||||
}
|
||||
@@ -469,63 +539,56 @@ namespace SettingsModelLocalTests
|
||||
const auto bindings0Json = VerifyParseSucceeded(bindings0String);
|
||||
|
||||
auto actionMap = winrt::make_self<implementation::ActionMap>();
|
||||
VERIFY_IS_NOT_NULL(actionMap);
|
||||
VERIFY_ARE_EQUAL(0u, actionMap->_KeyMap.size());
|
||||
actionMap->LayerJson(bindings0Json);
|
||||
VERIFY_ARE_EQUAL(6u, actionMap->_KeyMap.size());
|
||||
|
||||
{
|
||||
KeyChord kc{ false, false, false, static_cast<int32_t>(VK_UP) };
|
||||
KeyChord kc{ false, false, false, false, static_cast<int32_t>(VK_UP), 0 };
|
||||
auto actionAndArgs = ::TestUtils::GetActionAndArgs(*actionMap, kc);
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::ScrollUp, actionAndArgs.Action());
|
||||
const auto& realArgs = actionAndArgs.Args().try_as<ScrollUpArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
const auto& realArgs = actionAndArgs.Args().as<ScrollUpArgs>();
|
||||
// Verify the args have the expected value
|
||||
VERIFY_IS_NULL(realArgs.RowsToScroll());
|
||||
}
|
||||
{
|
||||
KeyChord kc{ false, false, false, static_cast<int32_t>(VK_DOWN) };
|
||||
KeyChord kc{ false, false, false, false, static_cast<int32_t>(VK_DOWN), 0 };
|
||||
auto actionAndArgs = ::TestUtils::GetActionAndArgs(*actionMap, kc);
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::ScrollDown, actionAndArgs.Action());
|
||||
const auto& realArgs = actionAndArgs.Args().try_as<ScrollDownArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
const auto& realArgs = actionAndArgs.Args().as<ScrollDownArgs>();
|
||||
// Verify the args have the expected value
|
||||
VERIFY_IS_NULL(realArgs.RowsToScroll());
|
||||
}
|
||||
{
|
||||
KeyChord kc{ true, false, false, static_cast<int32_t>(VK_UP) };
|
||||
KeyChord kc{ true, false, false, false, static_cast<int32_t>(VK_UP), 0 };
|
||||
auto actionAndArgs = ::TestUtils::GetActionAndArgs(*actionMap, kc);
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::ScrollUp, actionAndArgs.Action());
|
||||
const auto& realArgs = actionAndArgs.Args().try_as<ScrollUpArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
const auto& realArgs = actionAndArgs.Args().as<ScrollUpArgs>();
|
||||
// Verify the args have the expected value
|
||||
VERIFY_IS_NULL(realArgs.RowsToScroll());
|
||||
}
|
||||
{
|
||||
KeyChord kc{ true, false, false, static_cast<int32_t>(VK_DOWN) };
|
||||
KeyChord kc{ true, false, false, false, static_cast<int32_t>(VK_DOWN), 0 };
|
||||
auto actionAndArgs = ::TestUtils::GetActionAndArgs(*actionMap, kc);
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::ScrollDown, actionAndArgs.Action());
|
||||
const auto& realArgs = actionAndArgs.Args().try_as<ScrollDownArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
const auto& realArgs = actionAndArgs.Args().as<ScrollDownArgs>();
|
||||
// Verify the args have the expected value
|
||||
VERIFY_IS_NULL(realArgs.RowsToScroll());
|
||||
}
|
||||
{
|
||||
KeyChord kc{ true, false, true, static_cast<int32_t>(VK_UP) };
|
||||
KeyChord kc{ true, false, true, false, static_cast<int32_t>(VK_UP), 0 };
|
||||
auto actionAndArgs = ::TestUtils::GetActionAndArgs(*actionMap, kc);
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::ScrollUp, actionAndArgs.Action());
|
||||
const auto& realArgs = actionAndArgs.Args().try_as<ScrollUpArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
const auto& realArgs = actionAndArgs.Args().as<ScrollUpArgs>();
|
||||
// Verify the args have the expected value
|
||||
VERIFY_IS_NOT_NULL(realArgs.RowsToScroll());
|
||||
VERIFY_ARE_EQUAL(10u, realArgs.RowsToScroll().Value());
|
||||
}
|
||||
{
|
||||
KeyChord kc{ true, false, true, static_cast<int32_t>(VK_DOWN) };
|
||||
KeyChord kc{ true, false, true, false, static_cast<int32_t>(VK_DOWN), 0 };
|
||||
auto actionAndArgs = ::TestUtils::GetActionAndArgs(*actionMap, kc);
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::ScrollDown, actionAndArgs.Action());
|
||||
const auto& realArgs = actionAndArgs.Args().try_as<ScrollDownArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
const auto& realArgs = actionAndArgs.Args().as<ScrollDownArgs>();
|
||||
// Verify the args have the expected value
|
||||
VERIFY_IS_NOT_NULL(realArgs.RowsToScroll());
|
||||
VERIFY_ARE_EQUAL(10u, realArgs.RowsToScroll().Value());
|
||||
@@ -534,7 +597,6 @@ namespace SettingsModelLocalTests
|
||||
const std::string bindingsInvalidString{ R"([{ "keys": ["up"], "command": { "action": "scrollDown", "rowsToScroll": -1 } }])" };
|
||||
const auto bindingsInvalidJson = VerifyParseSucceeded(bindingsInvalidString);
|
||||
auto invalidActionMap = winrt::make_self<implementation::ActionMap>();
|
||||
VERIFY_IS_NOT_NULL(invalidActionMap);
|
||||
VERIFY_ARE_EQUAL(0u, invalidActionMap->_KeyMap.size());
|
||||
VERIFY_THROWS(invalidActionMap->LayerJson(bindingsInvalidJson);, std::exception);
|
||||
}
|
||||
@@ -550,26 +612,23 @@ namespace SettingsModelLocalTests
|
||||
const auto bindings0Json = VerifyParseSucceeded(bindings0String);
|
||||
|
||||
auto actionMap = winrt::make_self<implementation::ActionMap>();
|
||||
VERIFY_IS_NOT_NULL(actionMap);
|
||||
VERIFY_ARE_EQUAL(0u, actionMap->_KeyMap.size());
|
||||
actionMap->LayerJson(bindings0Json);
|
||||
VERIFY_ARE_EQUAL(2u, actionMap->_KeyMap.size());
|
||||
|
||||
{
|
||||
KeyChord kc{ false, false, false, static_cast<int32_t>(VK_UP) };
|
||||
KeyChord kc{ false, false, false, false, static_cast<int32_t>(VK_UP), 0 };
|
||||
auto actionAndArgs = ::TestUtils::GetActionAndArgs(*actionMap, kc);
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::MoveTab, actionAndArgs.Action());
|
||||
const auto& realArgs = actionAndArgs.Args().try_as<MoveTabArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
const auto& realArgs = actionAndArgs.Args().as<MoveTabArgs>();
|
||||
// Verify the args have the expected value
|
||||
VERIFY_ARE_EQUAL(realArgs.Direction(), MoveTabDirection::Forward);
|
||||
}
|
||||
{
|
||||
KeyChord kc{ false, false, false, static_cast<int32_t>(VK_DOWN) };
|
||||
KeyChord kc{ false, false, false, false, static_cast<int32_t>(VK_DOWN), 0 };
|
||||
auto actionAndArgs = ::TestUtils::GetActionAndArgs(*actionMap, kc);
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::MoveTab, actionAndArgs.Action());
|
||||
const auto& realArgs = actionAndArgs.Args().try_as<MoveTabArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
const auto& realArgs = actionAndArgs.Args().as<MoveTabArgs>();
|
||||
// Verify the args have the expected value
|
||||
VERIFY_ARE_EQUAL(realArgs.Direction(), MoveTabDirection::Backward);
|
||||
}
|
||||
@@ -583,7 +642,6 @@ namespace SettingsModelLocalTests
|
||||
const std::string bindingsInvalidString{ R"([{ "keys": ["up"], "command": { "action": "moveTab", "direction": "bad" } }])" };
|
||||
const auto bindingsInvalidJson = VerifyParseSucceeded(bindingsInvalidString);
|
||||
auto invalidActionMap = winrt::make_self<implementation::ActionMap>();
|
||||
VERIFY_IS_NOT_NULL(invalidActionMap);
|
||||
VERIFY_ARE_EQUAL(0u, invalidActionMap->_KeyMap.size());
|
||||
VERIFY_THROWS(invalidActionMap->LayerJson(bindingsInvalidJson);, std::exception);
|
||||
}
|
||||
@@ -600,35 +658,31 @@ namespace SettingsModelLocalTests
|
||||
const auto bindings0Json = VerifyParseSucceeded(bindings0String);
|
||||
|
||||
auto actionMap = winrt::make_self<implementation::ActionMap>();
|
||||
VERIFY_IS_NOT_NULL(actionMap);
|
||||
VERIFY_ARE_EQUAL(0u, actionMap->_KeyMap.size());
|
||||
actionMap->LayerJson(bindings0Json);
|
||||
VERIFY_ARE_EQUAL(3u, actionMap->_KeyMap.size());
|
||||
|
||||
{
|
||||
KeyChord kc{ false, false, false, static_cast<int32_t>(VK_UP) };
|
||||
KeyChord kc{ false, false, false, false, static_cast<int32_t>(VK_UP), 0 };
|
||||
auto actionAndArgs = ::TestUtils::GetActionAndArgs(*actionMap, kc);
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::ToggleCommandPalette, actionAndArgs.Action());
|
||||
const auto& realArgs = actionAndArgs.Args().try_as<ToggleCommandPaletteArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
const auto& realArgs = actionAndArgs.Args().as<ToggleCommandPaletteArgs>();
|
||||
// Verify the args have the expected value
|
||||
VERIFY_ARE_EQUAL(realArgs.LaunchMode(), CommandPaletteLaunchMode::Action);
|
||||
}
|
||||
{
|
||||
KeyChord kc{ true, false, false, static_cast<int32_t>(VK_UP) };
|
||||
KeyChord kc{ true, false, false, false, static_cast<int32_t>(VK_UP), 0 };
|
||||
auto actionAndArgs = ::TestUtils::GetActionAndArgs(*actionMap, kc);
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::ToggleCommandPalette, actionAndArgs.Action());
|
||||
const auto& realArgs = actionAndArgs.Args().try_as<ToggleCommandPaletteArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
const auto& realArgs = actionAndArgs.Args().as<ToggleCommandPaletteArgs>();
|
||||
// Verify the args have the expected value
|
||||
VERIFY_ARE_EQUAL(realArgs.LaunchMode(), CommandPaletteLaunchMode::Action);
|
||||
}
|
||||
{
|
||||
KeyChord kc{ true, false, true, static_cast<int32_t>(VK_UP) };
|
||||
KeyChord kc{ true, false, true, false, static_cast<int32_t>(VK_UP), 0 };
|
||||
auto actionAndArgs = ::TestUtils::GetActionAndArgs(*actionMap, kc);
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::ToggleCommandPalette, actionAndArgs.Action());
|
||||
const auto& realArgs = actionAndArgs.Args().try_as<ToggleCommandPaletteArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
const auto& realArgs = actionAndArgs.Args().as<ToggleCommandPaletteArgs>();
|
||||
// Verify the args have the expected value
|
||||
VERIFY_ARE_EQUAL(realArgs.LaunchMode(), CommandPaletteLaunchMode::CommandLine);
|
||||
}
|
||||
@@ -636,7 +690,6 @@ namespace SettingsModelLocalTests
|
||||
const std::string bindingsInvalidString{ R"([{ "keys": ["up"], "command": { "action": "commandPalette", "launchMode": "bad" } }])" };
|
||||
const auto bindingsInvalidJson = VerifyParseSucceeded(bindingsInvalidString);
|
||||
auto invalidActionMap = winrt::make_self<implementation::ActionMap>();
|
||||
VERIFY_IS_NOT_NULL(invalidActionMap);
|
||||
VERIFY_ARE_EQUAL(0u, invalidActionMap->_KeyMap.size());
|
||||
VERIFY_THROWS(invalidActionMap->LayerJson(bindingsInvalidJson);, std::exception);
|
||||
}
|
||||
@@ -668,7 +721,6 @@ namespace SettingsModelLocalTests
|
||||
};
|
||||
|
||||
auto actionMap = winrt::make_self<implementation::ActionMap>();
|
||||
VERIFY_IS_NOT_NULL(actionMap);
|
||||
VERIFY_ARE_EQUAL(0u, actionMap->_KeyMap.size());
|
||||
|
||||
{
|
||||
@@ -676,7 +728,7 @@ namespace SettingsModelLocalTests
|
||||
actionMap->LayerJson(bindings0Json);
|
||||
VERIFY_ARE_EQUAL(1u, actionMap->_KeyMap.size());
|
||||
const auto& kbd{ actionMap->GetKeyBindingForAction(ShortcutAction::CloseWindow) };
|
||||
VerifyKeyChordEquality({ KeyModifiers::Ctrl, static_cast<int32_t>('A') }, kbd);
|
||||
VerifyKeyChordEquality({ VirtualKeyModifiers::Control, static_cast<int32_t>('A'), 0 }, kbd);
|
||||
}
|
||||
{
|
||||
Log::Comment(L"command with args");
|
||||
@@ -687,7 +739,7 @@ namespace SettingsModelLocalTests
|
||||
args->SingleLine(true);
|
||||
|
||||
const auto& kbd{ actionMap->GetKeyBindingForAction(ShortcutAction::CopyText, *args) };
|
||||
VerifyKeyChordEquality({ KeyModifiers::Ctrl, static_cast<int32_t>('B') }, kbd);
|
||||
VerifyKeyChordEquality({ VirtualKeyModifiers::Control, static_cast<int32_t>('B'), 0 }, kbd);
|
||||
}
|
||||
{
|
||||
Log::Comment(L"command with new terminal args");
|
||||
@@ -699,7 +751,7 @@ namespace SettingsModelLocalTests
|
||||
auto args{ winrt::make_self<implementation::NewTabArgs>(*newTerminalArgs) };
|
||||
|
||||
const auto& kbd{ actionMap->GetKeyBindingForAction(ShortcutAction::NewTab, *args) };
|
||||
VerifyKeyChordEquality({ KeyModifiers::Ctrl, static_cast<int32_t>('C') }, kbd);
|
||||
VerifyKeyChordEquality({ VirtualKeyModifiers::Control, static_cast<int32_t>('C'), 0 }, kbd);
|
||||
}
|
||||
{
|
||||
Log::Comment(L"command with hidden args");
|
||||
@@ -707,7 +759,45 @@ namespace SettingsModelLocalTests
|
||||
VERIFY_ARE_EQUAL(4u, actionMap->_KeyMap.size());
|
||||
|
||||
const auto& kbd{ actionMap->GetKeyBindingForAction(ShortcutAction::ToggleCommandPalette) };
|
||||
VerifyKeyChordEquality({ KeyModifiers::Ctrl | KeyModifiers::Shift, static_cast<int32_t>('P') }, kbd);
|
||||
VerifyKeyChordEquality({ VirtualKeyModifiers::Control | VirtualKeyModifiers::Shift, static_cast<int32_t>('P'), 0 }, kbd);
|
||||
}
|
||||
}
|
||||
|
||||
void KeyBindingsTests::LayerScancodeKeybindings()
|
||||
{
|
||||
Log::Comment(L"Layering a keybinding with a character literal on top of"
|
||||
L" an equivalent sc() key should replace it.");
|
||||
|
||||
// Wrap the first one in `R"!(...)!"` because it has `()` internally.
|
||||
const std::string bindings0String{ R"!([ { "command": "quakeMode", "keys":"win+sc(41)" } ])!" };
|
||||
const std::string bindings1String{ R"([ { "keys": "win+`", "command": { "action": "globalSummon", "monitor": "any" } } ])" };
|
||||
const std::string bindings2String{ R"([ { "keys": "ctrl+shift+`", "command": { "action": "quakeMode" } } ])" };
|
||||
|
||||
const auto bindings0Json = VerifyParseSucceeded(bindings0String);
|
||||
const auto bindings1Json = VerifyParseSucceeded(bindings1String);
|
||||
const auto bindings2Json = VerifyParseSucceeded(bindings2String);
|
||||
|
||||
auto actionMap = winrt::make_self<implementation::ActionMap>();
|
||||
VERIFY_ARE_EQUAL(0u, actionMap->_KeyMap.size());
|
||||
|
||||
actionMap->LayerJson(bindings0Json);
|
||||
VERIFY_ARE_EQUAL(1u, actionMap->_KeyMap.size());
|
||||
|
||||
actionMap->LayerJson(bindings1Json);
|
||||
VERIFY_ARE_EQUAL(1u, actionMap->_KeyMap.size(), L"Layering the second action should replace the first one.");
|
||||
|
||||
actionMap->LayerJson(bindings2Json);
|
||||
VERIFY_ARE_EQUAL(2u, actionMap->_KeyMap.size());
|
||||
}
|
||||
|
||||
void KeyBindingsTests::KeybindingsWithoutVkey()
|
||||
{
|
||||
const auto json = VerifyParseSucceeded(R"!([{"command": "quakeMode", "keys":"shift+sc(255)"}])!");
|
||||
|
||||
const auto actionMap = winrt::make_self<implementation::ActionMap>();
|
||||
actionMap->LayerJson(json);
|
||||
|
||||
const auto action = actionMap->GetActionByKeyChord({ VirtualKeyModifiers::Shift, 0, 255 });
|
||||
VERIFY_IS_NOT_NULL(action);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,6 +41,7 @@ namespace SettingsModelLocalTests
|
||||
TEST_METHOD(ColorScheme);
|
||||
TEST_METHOD(Actions);
|
||||
TEST_METHOD(CascadiaSettings);
|
||||
TEST_METHOD(LegacyFontSettings);
|
||||
|
||||
TEST_CLASS_SETUP(ClassSetup)
|
||||
{
|
||||
@@ -138,9 +139,11 @@ namespace SettingsModelLocalTests
|
||||
"tabTitle": "Cool Tab",
|
||||
"suppressApplicationTitle": false,
|
||||
|
||||
"fontFace": "Cascadia Mono",
|
||||
"fontSize": 12,
|
||||
"fontWeight": "normal",
|
||||
"font": {
|
||||
"face": "Cascadia Mono",
|
||||
"size": 12,
|
||||
"weight": "normal"
|
||||
},
|
||||
"padding": "8, 8, 8, 8",
|
||||
"antialiasingMode": "grayscale",
|
||||
|
||||
@@ -402,11 +405,13 @@ namespace SettingsModelLocalTests
|
||||
|
||||
"profiles": {
|
||||
"defaults": {
|
||||
"fontFace": "Zamora Code"
|
||||
"font": {
|
||||
"face": "Zamora Code"
|
||||
}
|
||||
},
|
||||
"list": [
|
||||
{
|
||||
"fontFace": "Cascadia Code",
|
||||
"font": { "face": "Cascadia Code" },
|
||||
"guid": "{61c54bbd-1111-5271-96e7-009a87ff44bf}",
|
||||
"name": "HowettShell"
|
||||
},
|
||||
@@ -464,4 +469,35 @@ namespace SettingsModelLocalTests
|
||||
const auto result{ settings->ToJson() };
|
||||
VERIFY_ARE_EQUAL(toString(settings->_userSettings), toString(result));
|
||||
}
|
||||
|
||||
void SerializationTests::LegacyFontSettings()
|
||||
{
|
||||
const std::string profileString{ R"(
|
||||
{
|
||||
"name": "Profile with legacy font settings",
|
||||
|
||||
"fontFace": "Cascadia Mono",
|
||||
"fontSize": 12,
|
||||
"fontWeight": "normal"
|
||||
})" };
|
||||
|
||||
const std::string expectedOutput{ R"(
|
||||
{
|
||||
"name": "Profile with legacy font settings",
|
||||
|
||||
"font": {
|
||||
"face": "Cascadia Mono",
|
||||
"size": 12,
|
||||
"weight": "normal"
|
||||
}
|
||||
})" };
|
||||
|
||||
const auto json{ VerifyParseSucceeded(profileString) };
|
||||
const auto settings{ implementation::Profile::FromJson(json) };
|
||||
const auto result{ settings->ToJson() };
|
||||
|
||||
const auto jsonOutput{ VerifyParseSucceeded(expectedOutput) };
|
||||
|
||||
VERIFY_ARE_EQUAL(toString(jsonOutput), toString(result));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,10 +98,10 @@
|
||||
<!-- From Microsoft.UI.Xaml.targets -->
|
||||
<Native-Platform Condition="'$(Platform)' == 'Win32'">x86</Native-Platform>
|
||||
<Native-Platform Condition="'$(Platform)' != 'Win32'">$(Platform)</Native-Platform>
|
||||
<_MUXBinRoot>"$(OpenConsoleDir)packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\runtimes\win10-$(Native-Platform)\native\"</_MUXBinRoot>
|
||||
<_MUXBinRoot>"$(OpenConsoleDir)packages\Microsoft.UI.Xaml.2.6.2-prerelease.210818003\runtimes\win10-$(Native-Platform)\native\"</_MUXBinRoot>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- We actually can just straight up reference MUX here, it's fine -->
|
||||
<Import Project="..\..\..\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('..\..\..\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets')" />
|
||||
<Import Project="..\..\..\packages\Microsoft.UI.Xaml.2.6.2-prerelease.210818003\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('..\..\..\packages\Microsoft.UI.Xaml.2.6.2-prerelease.210818003\build\native\Microsoft.UI.Xaml.targets')" />
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -37,7 +37,7 @@ namespace SettingsModelLocalTests
|
||||
|
||||
TEST_METHOD(TestTerminalArgsForBinding);
|
||||
|
||||
TEST_METHOD(MakeSettingsForProfileThatDoesntExist);
|
||||
TEST_METHOD(MakeSettingsForProfile);
|
||||
TEST_METHOD(MakeSettingsForDefaultProfileThatDoesntExist);
|
||||
|
||||
TEST_METHOD(TestLayerProfileOnColorScheme);
|
||||
@@ -113,7 +113,7 @@ namespace SettingsModelLocalTests
|
||||
VERIFY_ARE_EQUAL(12u, actionMapImpl->_KeyMap.size());
|
||||
|
||||
{
|
||||
KeyChord kc{ true, false, false, static_cast<int32_t>('A') };
|
||||
KeyChord kc{ true, false, false, false, static_cast<int32_t>('A'), 0 };
|
||||
auto actionAndArgs = ::TestUtils::GetActionAndArgs(actionMap, kc);
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, actionAndArgs.Action());
|
||||
const auto& realArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
|
||||
@@ -126,15 +126,15 @@ namespace SettingsModelLocalTests
|
||||
VERIFY_IS_TRUE(realArgs.TerminalArgs().TabTitle().empty());
|
||||
VERIFY_IS_TRUE(realArgs.TerminalArgs().Profile().empty());
|
||||
|
||||
const auto guid{ settings.GetProfileForArgs(realArgs.TerminalArgs()) };
|
||||
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, guid);
|
||||
VERIFY_ARE_EQUAL(guid0, profile.Guid());
|
||||
VERIFY_ARE_EQUAL(L"cmd.exe", termSettings.Commandline());
|
||||
VERIFY_ARE_EQUAL(1, termSettings.HistorySize());
|
||||
}
|
||||
{
|
||||
KeyChord kc{ true, false, false, static_cast<int32_t>('B') };
|
||||
KeyChord kc{ true, false, false, false, static_cast<int32_t>('B'), 0 };
|
||||
auto actionAndArgs = ::TestUtils::GetActionAndArgs(actionMap, kc);
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, actionAndArgs.Action());
|
||||
const auto& realArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
|
||||
@@ -148,15 +148,15 @@ namespace SettingsModelLocalTests
|
||||
VERIFY_IS_FALSE(realArgs.TerminalArgs().Profile().empty());
|
||||
VERIFY_ARE_EQUAL(L"{6239a42c-1111-49a3-80bd-e8fdd045185c}", realArgs.TerminalArgs().Profile());
|
||||
|
||||
const auto guid{ settings.GetProfileForArgs(realArgs.TerminalArgs()) };
|
||||
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, guid);
|
||||
VERIFY_ARE_EQUAL(guid1, profile.Guid());
|
||||
VERIFY_ARE_EQUAL(L"pwsh.exe", termSettings.Commandline());
|
||||
VERIFY_ARE_EQUAL(2, termSettings.HistorySize());
|
||||
}
|
||||
{
|
||||
KeyChord kc{ true, false, false, static_cast<int32_t>('C') };
|
||||
KeyChord kc{ true, false, false, false, static_cast<int32_t>('C'), 0 };
|
||||
auto actionAndArgs = ::TestUtils::GetActionAndArgs(actionMap, kc);
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, actionAndArgs.Action());
|
||||
const auto& realArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
|
||||
@@ -170,15 +170,15 @@ namespace SettingsModelLocalTests
|
||||
VERIFY_IS_FALSE(realArgs.TerminalArgs().Profile().empty());
|
||||
VERIFY_ARE_EQUAL(L"profile1", realArgs.TerminalArgs().Profile());
|
||||
|
||||
const auto guid{ settings.GetProfileForArgs(realArgs.TerminalArgs()) };
|
||||
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, guid);
|
||||
VERIFY_ARE_EQUAL(guid1, profile.Guid());
|
||||
VERIFY_ARE_EQUAL(L"pwsh.exe", termSettings.Commandline());
|
||||
VERIFY_ARE_EQUAL(2, termSettings.HistorySize());
|
||||
}
|
||||
{
|
||||
KeyChord kc{ true, false, false, static_cast<int32_t>('D') };
|
||||
KeyChord kc{ true, false, false, false, static_cast<int32_t>('D'), 0 };
|
||||
auto actionAndArgs = ::TestUtils::GetActionAndArgs(actionMap, kc);
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, actionAndArgs.Action());
|
||||
const auto& realArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
|
||||
@@ -192,15 +192,15 @@ namespace SettingsModelLocalTests
|
||||
VERIFY_IS_FALSE(realArgs.TerminalArgs().Profile().empty());
|
||||
VERIFY_ARE_EQUAL(L"profile2", realArgs.TerminalArgs().Profile());
|
||||
|
||||
const auto guid{ settings.GetProfileForArgs(realArgs.TerminalArgs()) };
|
||||
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, guid);
|
||||
VERIFY_ARE_EQUAL(profile2Guid, profile.Guid());
|
||||
VERIFY_ARE_EQUAL(L"wsl.exe", termSettings.Commandline());
|
||||
VERIFY_ARE_EQUAL(3, termSettings.HistorySize());
|
||||
}
|
||||
{
|
||||
KeyChord kc{ true, false, false, static_cast<int32_t>('E') };
|
||||
KeyChord kc{ true, false, false, false, static_cast<int32_t>('E'), 0 };
|
||||
auto actionAndArgs = ::TestUtils::GetActionAndArgs(actionMap, kc);
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, actionAndArgs.Action());
|
||||
const auto& realArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
|
||||
@@ -214,15 +214,15 @@ namespace SettingsModelLocalTests
|
||||
VERIFY_IS_TRUE(realArgs.TerminalArgs().Profile().empty());
|
||||
VERIFY_ARE_EQUAL(L"foo.exe", realArgs.TerminalArgs().Commandline());
|
||||
|
||||
const auto guid{ settings.GetProfileForArgs(realArgs.TerminalArgs()) };
|
||||
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, guid);
|
||||
VERIFY_ARE_EQUAL(guid0, profile.Guid());
|
||||
VERIFY_ARE_EQUAL(L"foo.exe", termSettings.Commandline());
|
||||
VERIFY_ARE_EQUAL(1, termSettings.HistorySize());
|
||||
}
|
||||
{
|
||||
KeyChord kc{ true, false, false, static_cast<int32_t>('F') };
|
||||
KeyChord kc{ true, false, false, false, static_cast<int32_t>('F'), 0 };
|
||||
auto actionAndArgs = ::TestUtils::GetActionAndArgs(actionMap, kc);
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, actionAndArgs.Action());
|
||||
const auto& realArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
|
||||
@@ -237,15 +237,15 @@ namespace SettingsModelLocalTests
|
||||
VERIFY_ARE_EQUAL(L"profile1", realArgs.TerminalArgs().Profile());
|
||||
VERIFY_ARE_EQUAL(L"foo.exe", realArgs.TerminalArgs().Commandline());
|
||||
|
||||
const auto guid{ settings.GetProfileForArgs(realArgs.TerminalArgs()) };
|
||||
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, guid);
|
||||
VERIFY_ARE_EQUAL(guid1, profile.Guid());
|
||||
VERIFY_ARE_EQUAL(L"foo.exe", termSettings.Commandline());
|
||||
VERIFY_ARE_EQUAL(2, termSettings.HistorySize());
|
||||
}
|
||||
{
|
||||
KeyChord kc{ true, false, false, static_cast<int32_t>('G') };
|
||||
KeyChord kc{ true, false, false, false, static_cast<int32_t>('G'), 0 };
|
||||
auto actionAndArgs = ::TestUtils::GetActionAndArgs(actionMap, kc);
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::NewTab, actionAndArgs.Action());
|
||||
const auto& realArgs = actionAndArgs.Args().try_as<NewTabArgs>();
|
||||
@@ -257,15 +257,15 @@ namespace SettingsModelLocalTests
|
||||
VERIFY_IS_TRUE(realArgs.TerminalArgs().TabTitle().empty());
|
||||
VERIFY_IS_TRUE(realArgs.TerminalArgs().Profile().empty());
|
||||
|
||||
const auto guid{ settings.GetProfileForArgs(realArgs.TerminalArgs()) };
|
||||
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, guid);
|
||||
VERIFY_ARE_EQUAL(guid0, profile.Guid());
|
||||
VERIFY_ARE_EQUAL(L"cmd.exe", termSettings.Commandline());
|
||||
VERIFY_ARE_EQUAL(1, termSettings.HistorySize());
|
||||
}
|
||||
{
|
||||
KeyChord kc{ true, false, false, static_cast<int32_t>('H') };
|
||||
KeyChord kc{ true, false, false, false, static_cast<int32_t>('H'), 0 };
|
||||
auto actionAndArgs = ::TestUtils::GetActionAndArgs(actionMap, kc);
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::NewTab, actionAndArgs.Action());
|
||||
const auto& realArgs = actionAndArgs.Args().try_as<NewTabArgs>();
|
||||
@@ -278,16 +278,16 @@ namespace SettingsModelLocalTests
|
||||
VERIFY_IS_TRUE(realArgs.TerminalArgs().Profile().empty());
|
||||
VERIFY_ARE_EQUAL(L"c:\\foo", realArgs.TerminalArgs().StartingDirectory());
|
||||
|
||||
const auto guid{ settings.GetProfileForArgs(realArgs.TerminalArgs()) };
|
||||
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, guid);
|
||||
VERIFY_ARE_EQUAL(guid0, profile.Guid());
|
||||
VERIFY_ARE_EQUAL(L"cmd.exe", termSettings.Commandline());
|
||||
VERIFY_ARE_EQUAL(L"c:\\foo", termSettings.StartingDirectory());
|
||||
VERIFY_ARE_EQUAL(1, termSettings.HistorySize());
|
||||
}
|
||||
{
|
||||
KeyChord kc{ true, false, false, static_cast<int32_t>('I') };
|
||||
KeyChord kc{ true, false, false, false, static_cast<int32_t>('I'), 0 };
|
||||
auto actionAndArgs = ::TestUtils::GetActionAndArgs(actionMap, kc);
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::NewTab, actionAndArgs.Action());
|
||||
const auto& realArgs = actionAndArgs.Args().try_as<NewTabArgs>();
|
||||
@@ -301,16 +301,16 @@ namespace SettingsModelLocalTests
|
||||
VERIFY_ARE_EQUAL(L"c:\\foo", realArgs.TerminalArgs().StartingDirectory());
|
||||
VERIFY_ARE_EQUAL(L"profile2", realArgs.TerminalArgs().Profile());
|
||||
|
||||
const auto guid{ settings.GetProfileForArgs(realArgs.TerminalArgs()) };
|
||||
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, guid);
|
||||
VERIFY_ARE_EQUAL(profile2Guid, profile.Guid());
|
||||
VERIFY_ARE_EQUAL(L"wsl.exe", termSettings.Commandline());
|
||||
VERIFY_ARE_EQUAL(L"c:\\foo", termSettings.StartingDirectory());
|
||||
VERIFY_ARE_EQUAL(3, termSettings.HistorySize());
|
||||
}
|
||||
{
|
||||
KeyChord kc{ true, false, false, static_cast<int32_t>('J') };
|
||||
KeyChord kc{ true, false, false, false, static_cast<int32_t>('J'), 0 };
|
||||
auto actionAndArgs = ::TestUtils::GetActionAndArgs(actionMap, kc);
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::NewTab, actionAndArgs.Action());
|
||||
const auto& realArgs = actionAndArgs.Args().try_as<NewTabArgs>();
|
||||
@@ -323,16 +323,16 @@ namespace SettingsModelLocalTests
|
||||
VERIFY_IS_TRUE(realArgs.TerminalArgs().Profile().empty());
|
||||
VERIFY_ARE_EQUAL(L"bar", realArgs.TerminalArgs().TabTitle());
|
||||
|
||||
const auto guid{ settings.GetProfileForArgs(realArgs.TerminalArgs()) };
|
||||
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, guid);
|
||||
VERIFY_ARE_EQUAL(guid0, profile.Guid());
|
||||
VERIFY_ARE_EQUAL(L"cmd.exe", termSettings.Commandline());
|
||||
VERIFY_ARE_EQUAL(L"bar", termSettings.StartingTitle());
|
||||
VERIFY_ARE_EQUAL(1, termSettings.HistorySize());
|
||||
}
|
||||
{
|
||||
KeyChord kc{ true, false, false, static_cast<int32_t>('K') };
|
||||
KeyChord kc{ true, false, false, false, static_cast<int32_t>('K'), 0 };
|
||||
auto actionAndArgs = ::TestUtils::GetActionAndArgs(actionMap, kc);
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::NewTab, actionAndArgs.Action());
|
||||
const auto& realArgs = actionAndArgs.Args().try_as<NewTabArgs>();
|
||||
@@ -346,16 +346,16 @@ namespace SettingsModelLocalTests
|
||||
VERIFY_ARE_EQUAL(L"bar", realArgs.TerminalArgs().TabTitle());
|
||||
VERIFY_ARE_EQUAL(L"profile2", realArgs.TerminalArgs().Profile());
|
||||
|
||||
const auto guid{ settings.GetProfileForArgs(realArgs.TerminalArgs()) };
|
||||
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, guid);
|
||||
VERIFY_ARE_EQUAL(profile2Guid, profile.Guid());
|
||||
VERIFY_ARE_EQUAL(L"wsl.exe", termSettings.Commandline());
|
||||
VERIFY_ARE_EQUAL(L"bar", termSettings.StartingTitle());
|
||||
VERIFY_ARE_EQUAL(3, termSettings.HistorySize());
|
||||
}
|
||||
{
|
||||
KeyChord kc{ true, false, false, static_cast<int32_t>('L') };
|
||||
KeyChord kc{ true, false, false, false, static_cast<int32_t>('L'), 0 };
|
||||
auto actionAndArgs = ::TestUtils::GetActionAndArgs(actionMap, kc);
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::NewTab, actionAndArgs.Action());
|
||||
const auto& realArgs = actionAndArgs.Args().try_as<NewTabArgs>();
|
||||
@@ -371,10 +371,10 @@ namespace SettingsModelLocalTests
|
||||
VERIFY_ARE_EQUAL(L"bar", realArgs.TerminalArgs().TabTitle());
|
||||
VERIFY_ARE_EQUAL(L"profile1", realArgs.TerminalArgs().Profile());
|
||||
|
||||
const auto guid{ settings.GetProfileForArgs(realArgs.TerminalArgs()) };
|
||||
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, guid);
|
||||
VERIFY_ARE_EQUAL(guid1, profile.Guid());
|
||||
VERIFY_ARE_EQUAL(L"foo.exe", termSettings.Commandline());
|
||||
VERIFY_ARE_EQUAL(L"bar", termSettings.StartingTitle());
|
||||
VERIFY_ARE_EQUAL(L"c:\\foo", termSettings.StartingDirectory());
|
||||
@@ -382,9 +382,9 @@ namespace SettingsModelLocalTests
|
||||
}
|
||||
}
|
||||
|
||||
void TerminalSettingsTests::MakeSettingsForProfileThatDoesntExist()
|
||||
void TerminalSettingsTests::MakeSettingsForProfile()
|
||||
{
|
||||
// Test that making settings throws when the GUID doesn't exist
|
||||
// Test that making settings generally works.
|
||||
const std::string settingsString{ R"(
|
||||
{
|
||||
"defaultProfile": "{6239a42c-1111-49a3-80bd-e8fdd045185c}",
|
||||
@@ -405,32 +405,32 @@ namespace SettingsModelLocalTests
|
||||
|
||||
const auto guid1 = ::Microsoft::Console::Utils::GuidFromString(L"{6239a42c-1111-49a3-80bd-e8fdd045185c}");
|
||||
const auto guid2 = ::Microsoft::Console::Utils::GuidFromString(L"{6239a42c-2222-49a3-80bd-e8fdd045185c}");
|
||||
const auto guid3 = ::Microsoft::Console::Utils::GuidFromString(L"{6239a42c-3333-49a3-80bd-e8fdd045185c}");
|
||||
|
||||
const auto profile1 = settings.FindProfile(guid1);
|
||||
const auto profile2 = settings.FindProfile(guid2);
|
||||
|
||||
try
|
||||
{
|
||||
auto terminalSettings{ TerminalSettings::CreateWithProfileByID(settings, guid1, nullptr) };
|
||||
auto terminalSettings{ TerminalSettings::CreateWithProfile(settings, profile1, nullptr) };
|
||||
VERIFY_ARE_NOT_EQUAL(nullptr, terminalSettings);
|
||||
VERIFY_ARE_EQUAL(1, terminalSettings.DefaultSettings().HistorySize());
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
VERIFY_IS_TRUE(false, L"This call to CreateWithProfileByID should succeed");
|
||||
VERIFY_IS_TRUE(false, L"This call to CreateWithProfile should succeed");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
auto terminalSettings{ TerminalSettings::CreateWithProfileByID(settings, guid2, nullptr) };
|
||||
auto terminalSettings{ TerminalSettings::CreateWithProfile(settings, profile2, nullptr) };
|
||||
VERIFY_ARE_NOT_EQUAL(nullptr, terminalSettings);
|
||||
VERIFY_ARE_EQUAL(2, terminalSettings.DefaultSettings().HistorySize());
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
VERIFY_IS_TRUE(false, L"This call to CreateWithProfileByID should succeed");
|
||||
VERIFY_IS_TRUE(false, L"This call to CreateWithProfile should succeed");
|
||||
}
|
||||
|
||||
VERIFY_THROWS(auto terminalSettings = TerminalSettings::CreateWithProfileByID(settings, guid3, nullptr), wil::ResultException, L"This call to constructor should fail");
|
||||
|
||||
try
|
||||
{
|
||||
const auto termSettings{ TerminalSettings::CreateWithNewTerminalArgs(settings, nullptr, nullptr) };
|
||||
|
||||
@@ -26,16 +26,18 @@ public:
|
||||
static const winrt::Microsoft::Terminal::Settings::Model::ActionAndArgs GetActionAndArgs(const winrt::Microsoft::Terminal::Settings::Model::ActionMap& actionMap,
|
||||
const winrt::Microsoft::Terminal::Control::KeyChord& kc)
|
||||
{
|
||||
using VirtualKeyModifiers = winrt::Windows::System::VirtualKeyModifiers;
|
||||
|
||||
std::wstring buffer{ L"" };
|
||||
if (WI_IsFlagSet(kc.Modifiers(), winrt::Microsoft::Terminal::Control::KeyModifiers::Ctrl))
|
||||
if (WI_IsFlagSet(kc.Modifiers(), VirtualKeyModifiers::Control))
|
||||
{
|
||||
buffer += L"Ctrl+";
|
||||
}
|
||||
if (WI_IsFlagSet(kc.Modifiers(), winrt::Microsoft::Terminal::Control::KeyModifiers::Shift))
|
||||
if (WI_IsFlagSet(kc.Modifiers(), VirtualKeyModifiers::Shift))
|
||||
{
|
||||
buffer += L"Shift+";
|
||||
}
|
||||
if (WI_IsFlagSet(kc.Modifiers(), winrt::Microsoft::Terminal::Control::KeyModifiers::Alt))
|
||||
if (WI_IsFlagSet(kc.Modifiers(), VirtualKeyModifiers::Menu))
|
||||
{
|
||||
buffer += L"Alt+";
|
||||
}
|
||||
|
||||
@@ -56,6 +56,7 @@ namespace TerminalAppLocalTests
|
||||
TEST_METHOD(ParseComboCommandlineIntoArgs);
|
||||
TEST_METHOD(ParseFocusTabArgs);
|
||||
TEST_METHOD(ParseMoveFocusArgs);
|
||||
TEST_METHOD(ParseSwapPaneArgs);
|
||||
TEST_METHOD(ParseArgumentsWithParsingTerminators);
|
||||
TEST_METHOD(ParseFocusPaneArgs);
|
||||
|
||||
@@ -1207,6 +1208,119 @@ namespace TerminalAppLocalTests
|
||||
}
|
||||
}
|
||||
|
||||
void CommandlineTest::ParseSwapPaneArgs()
|
||||
{
|
||||
const wchar_t* subcommand = L"swap-pane";
|
||||
|
||||
{
|
||||
AppCommandlineArgs appArgs{};
|
||||
std::vector<const wchar_t*> rawCommands{ L"wt.exe", subcommand };
|
||||
Log::Comment(NoThrowString().Format(
|
||||
L"Just the subcommand, without a direction, should fail."));
|
||||
|
||||
_buildCommandlinesExpectFailureHelper(appArgs, 1u, rawCommands);
|
||||
}
|
||||
{
|
||||
AppCommandlineArgs appArgs{};
|
||||
std::vector<const wchar_t*> rawCommands{ L"wt.exe", subcommand, L"left" };
|
||||
_buildCommandlinesHelper(appArgs, 1u, rawCommands);
|
||||
|
||||
VERIFY_ARE_EQUAL(2u, appArgs._startupActions.size());
|
||||
|
||||
// The first action is going to always be a new-tab action
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::NewTab, appArgs._startupActions.at(0).Action());
|
||||
|
||||
auto actionAndArgs = appArgs._startupActions.at(1);
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::SwapPane, actionAndArgs.Action());
|
||||
VERIFY_IS_NOT_NULL(actionAndArgs.Args());
|
||||
auto myArgs = actionAndArgs.Args().try_as<SwapPaneArgs>();
|
||||
VERIFY_IS_NOT_NULL(myArgs);
|
||||
VERIFY_ARE_EQUAL(FocusDirection::Left, myArgs.Direction());
|
||||
}
|
||||
{
|
||||
AppCommandlineArgs appArgs{};
|
||||
std::vector<const wchar_t*> rawCommands{ L"wt.exe", subcommand, L"right" };
|
||||
_buildCommandlinesHelper(appArgs, 1u, rawCommands);
|
||||
|
||||
VERIFY_ARE_EQUAL(2u, appArgs._startupActions.size());
|
||||
|
||||
// The first action is going to always be a new-tab action
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::NewTab, appArgs._startupActions.at(0).Action());
|
||||
|
||||
auto actionAndArgs = appArgs._startupActions.at(1);
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::SwapPane, actionAndArgs.Action());
|
||||
VERIFY_IS_NOT_NULL(actionAndArgs.Args());
|
||||
auto myArgs = actionAndArgs.Args().try_as<SwapPaneArgs>();
|
||||
VERIFY_IS_NOT_NULL(myArgs);
|
||||
VERIFY_ARE_EQUAL(FocusDirection::Right, myArgs.Direction());
|
||||
}
|
||||
{
|
||||
AppCommandlineArgs appArgs{};
|
||||
std::vector<const wchar_t*> rawCommands{ L"wt.exe", subcommand, L"up" };
|
||||
_buildCommandlinesHelper(appArgs, 1u, rawCommands);
|
||||
|
||||
VERIFY_ARE_EQUAL(2u, appArgs._startupActions.size());
|
||||
|
||||
// The first action is going to always be a new-tab action
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::NewTab, appArgs._startupActions.at(0).Action());
|
||||
|
||||
auto actionAndArgs = appArgs._startupActions.at(1);
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::SwapPane, actionAndArgs.Action());
|
||||
VERIFY_IS_NOT_NULL(actionAndArgs.Args());
|
||||
auto myArgs = actionAndArgs.Args().try_as<SwapPaneArgs>();
|
||||
VERIFY_IS_NOT_NULL(myArgs);
|
||||
VERIFY_ARE_EQUAL(FocusDirection::Up, myArgs.Direction());
|
||||
}
|
||||
{
|
||||
AppCommandlineArgs appArgs{};
|
||||
std::vector<const wchar_t*> rawCommands{ L"wt.exe", subcommand, L"down" };
|
||||
_buildCommandlinesHelper(appArgs, 1u, rawCommands);
|
||||
|
||||
VERIFY_ARE_EQUAL(2u, appArgs._startupActions.size());
|
||||
|
||||
// The first action is going to always be a new-tab action
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::NewTab, appArgs._startupActions.at(0).Action());
|
||||
|
||||
auto actionAndArgs = appArgs._startupActions.at(1);
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::SwapPane, actionAndArgs.Action());
|
||||
VERIFY_IS_NOT_NULL(actionAndArgs.Args());
|
||||
auto myArgs = actionAndArgs.Args().try_as<SwapPaneArgs>();
|
||||
VERIFY_IS_NOT_NULL(myArgs);
|
||||
VERIFY_ARE_EQUAL(FocusDirection::Down, myArgs.Direction());
|
||||
}
|
||||
{
|
||||
AppCommandlineArgs appArgs{};
|
||||
std::vector<const wchar_t*> rawCommands{ L"wt.exe", subcommand, L"badDirection" };
|
||||
Log::Comment(NoThrowString().Format(
|
||||
L"move-pane with an invalid direction should fail."));
|
||||
_buildCommandlinesExpectFailureHelper(appArgs, 1u, rawCommands);
|
||||
}
|
||||
{
|
||||
AppCommandlineArgs appArgs{};
|
||||
std::vector<const wchar_t*> rawCommands{ L"wt.exe", subcommand, L"left", L";", subcommand, L"right" };
|
||||
_buildCommandlinesHelper(appArgs, 2u, rawCommands);
|
||||
|
||||
VERIFY_ARE_EQUAL(3u, appArgs._startupActions.size());
|
||||
|
||||
// The first action is going to always be a new-tab action
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::NewTab, appArgs._startupActions.at(0).Action());
|
||||
|
||||
auto actionAndArgs = appArgs._startupActions.at(1);
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::SwapPane, actionAndArgs.Action());
|
||||
VERIFY_IS_NOT_NULL(actionAndArgs.Args());
|
||||
auto myArgs = actionAndArgs.Args().try_as<SwapPaneArgs>();
|
||||
VERIFY_IS_NOT_NULL(myArgs);
|
||||
VERIFY_ARE_EQUAL(FocusDirection::Left, myArgs.Direction());
|
||||
|
||||
actionAndArgs = appArgs._startupActions.at(2);
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::SwapPane, actionAndArgs.Action());
|
||||
VERIFY_IS_NOT_NULL(actionAndArgs.Args());
|
||||
myArgs = actionAndArgs.Args().try_as<SwapPaneArgs>();
|
||||
VERIFY_IS_NOT_NULL(myArgs);
|
||||
VERIFY_ARE_EQUAL(FocusDirection::Right, myArgs.Direction());
|
||||
}
|
||||
}
|
||||
|
||||
void CommandlineTest::ParseFocusPaneArgs()
|
||||
{
|
||||
BEGIN_TEST_METHOD_PROPERTIES()
|
||||
|
||||
@@ -82,6 +82,8 @@ namespace TerminalAppLocalTests
|
||||
TEST_METHOD(MoveFocusFromZoomedPane);
|
||||
TEST_METHOD(CloseZoomedPane);
|
||||
|
||||
TEST_METHOD(SwapPanes);
|
||||
|
||||
TEST_METHOD(NextMRUTab);
|
||||
TEST_METHOD(VerifyCommandPaletteTabSwitcherOrder);
|
||||
|
||||
@@ -93,6 +95,8 @@ namespace TerminalAppLocalTests
|
||||
TEST_METHOD(TestPreviewDismissScheme);
|
||||
TEST_METHOD(TestPreviewSchemeWhilePreviewing);
|
||||
|
||||
TEST_METHOD(TestClampSwitchToTab);
|
||||
|
||||
TEST_CLASS_SETUP(ClassSetup)
|
||||
{
|
||||
return true;
|
||||
@@ -426,7 +430,7 @@ namespace TerminalAppLocalTests
|
||||
Log::Comment(L"Duplicate the tab, and don't crash");
|
||||
result = RunOnUIThread([&page]() {
|
||||
page->_DuplicateFocusedTab();
|
||||
VERIFY_ARE_EQUAL(2u, page->_tabs.Size(), L"We should gracefully do nothing here - the profile no longer exists.");
|
||||
VERIFY_ARE_EQUAL(3u, page->_tabs.Size(), L"We should successfully duplicate a tab hosting a deleted profile.");
|
||||
});
|
||||
VERIFY_SUCCEEDED(result);
|
||||
}
|
||||
@@ -526,9 +530,9 @@ namespace TerminalAppLocalTests
|
||||
|
||||
VERIFY_ARE_EQUAL(1u, page->_tabs.Size());
|
||||
auto tab = page->_GetTerminalTabImpl(page->_tabs.GetAt(0));
|
||||
VERIFY_ARE_EQUAL(2,
|
||||
VERIFY_ARE_EQUAL(3,
|
||||
tab->GetLeafPaneCount(),
|
||||
L"We should gracefully do nothing here - the profile no longer exists.");
|
||||
L"We should successfully duplicate a pane hosting a deleted profile.");
|
||||
});
|
||||
VERIFY_SUCCEEDED(result);
|
||||
|
||||
@@ -817,6 +821,212 @@ namespace TerminalAppLocalTests
|
||||
VERIFY_SUCCEEDED(result);
|
||||
}
|
||||
|
||||
void TabTests::SwapPanes()
|
||||
{
|
||||
auto page = _commonSetup();
|
||||
|
||||
Log::Comment(L"Setup 4 panes.");
|
||||
// Create the following layout
|
||||
// -------------------
|
||||
// | 1 | 2 |
|
||||
// | | |
|
||||
// -------------------
|
||||
// | 3 | 4 |
|
||||
// | | |
|
||||
// -------------------
|
||||
uint32_t firstId = 0, secondId = 0, thirdId = 0, fourthId = 0;
|
||||
TestOnUIThread([&]() {
|
||||
VERIFY_ARE_EQUAL(1u, page->_tabs.Size());
|
||||
auto tab = page->_GetTerminalTabImpl(page->_tabs.GetAt(0));
|
||||
firstId = tab->_activePane->Id().value();
|
||||
// We start with 1 tab, split vertically to get
|
||||
// -------------------
|
||||
// | 1 | 2 |
|
||||
// | | |
|
||||
// -------------------
|
||||
page->_SplitPane(SplitState::Vertical, SplitType::Duplicate, 0.5f, nullptr);
|
||||
secondId = tab->_activePane->Id().value();
|
||||
});
|
||||
Sleep(250);
|
||||
TestOnUIThread([&]() {
|
||||
// After this the `2` pane is focused, go back to `1` being focused
|
||||
page->_MoveFocus(FocusDirection::Left);
|
||||
});
|
||||
Sleep(250);
|
||||
TestOnUIThread([&]() {
|
||||
// Split again to make the 3rd tab
|
||||
// -------------------
|
||||
// | 1 | |
|
||||
// | | |
|
||||
// ---------| 2 |
|
||||
// | 3 | |
|
||||
// | | |
|
||||
// -------------------
|
||||
page->_SplitPane(SplitState::Horizontal, SplitType::Duplicate, 0.5f, nullptr);
|
||||
auto tab = page->_GetTerminalTabImpl(page->_tabs.GetAt(0));
|
||||
// Split again to make the 3rd tab
|
||||
thirdId = tab->_activePane->Id().value();
|
||||
});
|
||||
Sleep(250);
|
||||
TestOnUIThread([&]() {
|
||||
// After this the `3` pane is focused, go back to `2` being focused
|
||||
page->_MoveFocus(FocusDirection::Right);
|
||||
});
|
||||
Sleep(250);
|
||||
TestOnUIThread([&]() {
|
||||
// Split to create the final pane
|
||||
// -------------------
|
||||
// | 1 | 2 |
|
||||
// | | |
|
||||
// -------------------
|
||||
// | 3 | 4 |
|
||||
// | | |
|
||||
// -------------------
|
||||
page->_SplitPane(SplitState::Horizontal, SplitType::Duplicate, 0.5f, nullptr);
|
||||
auto tab = page->_GetTerminalTabImpl(page->_tabs.GetAt(0));
|
||||
fourthId = tab->_activePane->Id().value();
|
||||
});
|
||||
|
||||
Sleep(250);
|
||||
TestOnUIThread([&]() {
|
||||
auto tab = page->_GetTerminalTabImpl(page->_tabs.GetAt(0));
|
||||
VERIFY_ARE_EQUAL(4, tab->GetLeafPaneCount());
|
||||
// just to be complete, make sure we actually have 4 different ids
|
||||
VERIFY_ARE_NOT_EQUAL(firstId, fourthId);
|
||||
VERIFY_ARE_NOT_EQUAL(secondId, fourthId);
|
||||
VERIFY_ARE_NOT_EQUAL(thirdId, fourthId);
|
||||
VERIFY_ARE_NOT_EQUAL(firstId, thirdId);
|
||||
VERIFY_ARE_NOT_EQUAL(secondId, thirdId);
|
||||
VERIFY_ARE_NOT_EQUAL(firstId, secondId);
|
||||
});
|
||||
|
||||
// Gratuitous use of sleep to make sure that the UI has updated properly
|
||||
// after each operation.
|
||||
Sleep(250);
|
||||
// Now try to move the pane through the tree
|
||||
Log::Comment(L"Move pane to the left. This should swap panes 3 and 4");
|
||||
// -------------------
|
||||
// | 1 | 2 |
|
||||
// | | |
|
||||
// -------------------
|
||||
// | 4 | 3 |
|
||||
// | | |
|
||||
// -------------------
|
||||
TestOnUIThread([&]() {
|
||||
// Set up action
|
||||
SwapPaneArgs args{ FocusDirection::Left };
|
||||
ActionEventArgs eventArgs{ args };
|
||||
|
||||
page->_HandleSwapPane(nullptr, eventArgs);
|
||||
});
|
||||
|
||||
Sleep(250);
|
||||
|
||||
TestOnUIThread([&]() {
|
||||
auto tab = page->_GetTerminalTabImpl(page->_tabs.GetAt(0));
|
||||
VERIFY_ARE_EQUAL(4, tab->GetLeafPaneCount());
|
||||
// Our currently focused pane should be `4`
|
||||
VERIFY_ARE_EQUAL(fourthId, tab->_activePane->Id().value());
|
||||
|
||||
// Inspect the tree to make sure we swapped
|
||||
VERIFY_ARE_EQUAL(fourthId, tab->_rootPane->_firstChild->_secondChild->Id().value());
|
||||
VERIFY_ARE_EQUAL(thirdId, tab->_rootPane->_secondChild->_secondChild->Id().value());
|
||||
});
|
||||
|
||||
Sleep(250);
|
||||
|
||||
Log::Comment(L"Move pane to up. This should swap panes 1 and 4");
|
||||
// -------------------
|
||||
// | 4 | 2 |
|
||||
// | | |
|
||||
// -------------------
|
||||
// | 1 | 3 |
|
||||
// | | |
|
||||
// -------------------
|
||||
TestOnUIThread([&]() {
|
||||
// Set up action
|
||||
SwapPaneArgs args{ FocusDirection::Up };
|
||||
ActionEventArgs eventArgs{ args };
|
||||
|
||||
page->_HandleSwapPane(nullptr, eventArgs);
|
||||
});
|
||||
|
||||
Sleep(250);
|
||||
|
||||
TestOnUIThread([&]() {
|
||||
auto tab = page->_GetTerminalTabImpl(page->_tabs.GetAt(0));
|
||||
VERIFY_ARE_EQUAL(4, tab->GetLeafPaneCount());
|
||||
// Our currently focused pane should be `4`
|
||||
VERIFY_ARE_EQUAL(fourthId, tab->_activePane->Id().value());
|
||||
|
||||
// Inspect the tree to make sure we swapped
|
||||
VERIFY_ARE_EQUAL(fourthId, tab->_rootPane->_firstChild->_firstChild->Id().value());
|
||||
VERIFY_ARE_EQUAL(firstId, tab->_rootPane->_firstChild->_secondChild->Id().value());
|
||||
});
|
||||
|
||||
Sleep(250);
|
||||
|
||||
Log::Comment(L"Move pane to the right. This should swap panes 2 and 4");
|
||||
// -------------------
|
||||
// | 2 | 4 |
|
||||
// | | |
|
||||
// -------------------
|
||||
// | 1 | 3 |
|
||||
// | | |
|
||||
// -------------------
|
||||
TestOnUIThread([&]() {
|
||||
// Set up action
|
||||
SwapPaneArgs args{ FocusDirection::Right };
|
||||
ActionEventArgs eventArgs{ args };
|
||||
|
||||
page->_HandleSwapPane(nullptr, eventArgs);
|
||||
});
|
||||
|
||||
Sleep(250);
|
||||
|
||||
TestOnUIThread([&]() {
|
||||
auto tab = page->_GetTerminalTabImpl(page->_tabs.GetAt(0));
|
||||
VERIFY_ARE_EQUAL(4, tab->GetLeafPaneCount());
|
||||
// Our currently focused pane should be `4`
|
||||
VERIFY_ARE_EQUAL(fourthId, tab->_activePane->Id().value());
|
||||
|
||||
// Inspect the tree to make sure we swapped
|
||||
VERIFY_ARE_EQUAL(fourthId, tab->_rootPane->_secondChild->_firstChild->Id().value());
|
||||
VERIFY_ARE_EQUAL(secondId, tab->_rootPane->_firstChild->_firstChild->Id().value());
|
||||
});
|
||||
|
||||
Sleep(250);
|
||||
|
||||
Log::Comment(L"Move pane down. This should swap panes 3 and 4");
|
||||
// -------------------
|
||||
// | 2 | 3 |
|
||||
// | | |
|
||||
// -------------------
|
||||
// | 1 | 4 |
|
||||
// | | |
|
||||
// -------------------
|
||||
TestOnUIThread([&]() {
|
||||
// Set up action
|
||||
SwapPaneArgs args{ FocusDirection::Down };
|
||||
ActionEventArgs eventArgs{ args };
|
||||
|
||||
page->_HandleSwapPane(nullptr, eventArgs);
|
||||
});
|
||||
|
||||
Sleep(250);
|
||||
|
||||
TestOnUIThread([&]() {
|
||||
auto tab = page->_GetTerminalTabImpl(page->_tabs.GetAt(0));
|
||||
VERIFY_ARE_EQUAL(4, tab->GetLeafPaneCount());
|
||||
// Our currently focused pane should be `4`
|
||||
VERIFY_ARE_EQUAL(fourthId, tab->_activePane->Id().value());
|
||||
|
||||
// Inspect the tree to make sure we swapped
|
||||
VERIFY_ARE_EQUAL(fourthId, tab->_rootPane->_secondChild->_secondChild->Id().value());
|
||||
VERIFY_ARE_EQUAL(thirdId, tab->_rootPane->_secondChild->_firstChild->Id().value());
|
||||
});
|
||||
}
|
||||
|
||||
void TabTests::NextMRUTab()
|
||||
{
|
||||
// This is a test for GH#8025 - we want to make sure that we can do both
|
||||
@@ -1342,4 +1552,55 @@ namespace TerminalAppLocalTests
|
||||
});
|
||||
}
|
||||
|
||||
void TabTests::TestClampSwitchToTab()
|
||||
{
|
||||
Log::Comment(L"Test that switching to a tab index higher than the number of tabs just clamps to the last tab.");
|
||||
|
||||
auto page = _commonSetup();
|
||||
VERIFY_IS_NOT_NULL(page);
|
||||
|
||||
Log::Comment(L"Create a second tab");
|
||||
TestOnUIThread([&page]() {
|
||||
NewTerminalArgs newTerminalArgs{ 1 };
|
||||
page->_OpenNewTab(newTerminalArgs);
|
||||
});
|
||||
VERIFY_ARE_EQUAL(2u, page->_tabs.Size());
|
||||
|
||||
Log::Comment(L"Create a third tab");
|
||||
TestOnUIThread([&page]() {
|
||||
NewTerminalArgs newTerminalArgs{ 2 };
|
||||
page->_OpenNewTab(newTerminalArgs);
|
||||
});
|
||||
VERIFY_ARE_EQUAL(3u, page->_tabs.Size());
|
||||
|
||||
TestOnUIThread([&page]() {
|
||||
auto focusedTabIndexOpt{ page->_GetFocusedTabIndex() };
|
||||
VERIFY_IS_TRUE(focusedTabIndexOpt.has_value());
|
||||
VERIFY_ARE_EQUAL(2u, focusedTabIndexOpt.value());
|
||||
});
|
||||
|
||||
TestOnUIThread([&page]() {
|
||||
Log::Comment(L"Switch to the first tab");
|
||||
page->_SelectTab(0);
|
||||
});
|
||||
|
||||
TestOnUIThread([&page]() {
|
||||
auto focusedTabIndexOpt{ page->_GetFocusedTabIndex() };
|
||||
|
||||
VERIFY_IS_TRUE(focusedTabIndexOpt.has_value());
|
||||
VERIFY_ARE_EQUAL(0u, focusedTabIndexOpt.value());
|
||||
});
|
||||
|
||||
TestOnUIThread([&page]() {
|
||||
Log::Comment(L"Switch to the tab 6, which is greater than number of tabs. This should switch to the third tab");
|
||||
page->_SelectTab(6);
|
||||
});
|
||||
|
||||
TestOnUIThread([&page]() {
|
||||
auto focusedTabIndexOpt{ page->_GetFocusedTabIndex() };
|
||||
VERIFY_IS_TRUE(focusedTabIndexOpt.has_value());
|
||||
VERIFY_ARE_EQUAL(2u, focusedTabIndexOpt.value());
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -92,11 +92,11 @@
|
||||
<!-- From Microsoft.UI.Xaml.targets -->
|
||||
<Native-Platform Condition="'$(Platform)' == 'Win32'">x86</Native-Platform>
|
||||
<Native-Platform Condition="'$(Platform)' != 'Win32'">$(Platform)</Native-Platform>
|
||||
<_MUXBinRoot>"$(OpenConsoleDir)packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\runtimes\win10-$(Native-Platform)\native\"</_MUXBinRoot>
|
||||
<_MUXBinRoot>"$(OpenConsoleDir)packages\Microsoft.UI.Xaml.2.6.2-prerelease.210818003\runtimes\win10-$(Native-Platform)\native\"</_MUXBinRoot>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- We actually can just straight up reference MUX here, it's fine -->
|
||||
<Import Project="..\..\..\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('..\..\..\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets')" />
|
||||
<Import Project="..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.2\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets" Condition="Exists('..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.2\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" />
|
||||
<Import Project="..\..\..\packages\Microsoft.UI.Xaml.2.6.2-prerelease.210818003\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('..\..\..\packages\Microsoft.UI.Xaml.2.6.2-prerelease.210818003\build\native\Microsoft.UI.Xaml.targets')" />
|
||||
<Import Project="..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets" Condition="Exists('..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" />
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -115,7 +115,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.VisualStudio.TestPlatform.TestExecutor.WinRTCore">
|
||||
<HintPath>$(OpenConsoleDir)\packages\Microsoft.Taef.10.58.210305002\lib\Microsoft.VisualStudio.TestPlatform.TestExecutor.WinRTCore.winmd</HintPath>
|
||||
<HintPath>$(OpenConsoleDir)\packages\Microsoft.Taef.10.60.210621002\lib\Microsoft.VisualStudio.TestPlatform.TestExecutor.WinRTCore.winmd</HintPath>
|
||||
<IsWinMDFile>true</IsWinMDFile>
|
||||
|
||||
<!-- This path is _relative to the .winmd_ -->
|
||||
@@ -123,7 +123,7 @@
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
|
||||
<Import Project="$(OpenConsoleDir)\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('$(OpenConsoleDir)\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets')" />
|
||||
<Import Project="$(OpenConsoleDir)\packages\Microsoft.UI.Xaml.2.6.2-prerelease.210818003\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('$(OpenConsoleDir)\packages\Microsoft.UI.Xaml.2.6.2-prerelease.210818003\build\native\Microsoft.UI.Xaml.targets')" />
|
||||
|
||||
<Import Project="$(OpenConsoleDir)\src\common.build.post.props" />
|
||||
|
||||
|
||||
@@ -172,7 +172,6 @@ HwndTerminal::HwndTerminal(HWND parentHwnd) :
|
||||
_desiredFont{ L"Consolas", 0, DEFAULT_FONT_WEIGHT, { 0, 14 }, CP_UTF8 },
|
||||
_actualFont{ L"Consolas", 0, DEFAULT_FONT_WEIGHT, { 0, 14 }, CP_UTF8, false },
|
||||
_uiaProvider{ nullptr },
|
||||
_uiaProviderInitialized{ false },
|
||||
_currentDpi{ USER_DEFAULT_SCREEN_DPI },
|
||||
_pfnWriteCallback{ nullptr },
|
||||
_multiClickTime{ 500 } // this will be overwritten by the windows system double-click time
|
||||
@@ -324,26 +323,22 @@ void HwndTerminal::_UpdateFont(int newDpi)
|
||||
|
||||
IRawElementProviderSimple* HwndTerminal::_GetUiaProvider() noexcept
|
||||
{
|
||||
if (nullptr == _uiaProvider && !_uiaProviderInitialized)
|
||||
// If TermControlUiaProvider throws during construction,
|
||||
// we don't want to try constructing an instance again and again.
|
||||
// _uiaProviderInitialized helps us prevent this.
|
||||
if (!_uiaProviderInitialized)
|
||||
{
|
||||
std::unique_lock<std::shared_mutex> lock;
|
||||
try
|
||||
{
|
||||
#pragma warning(suppress : 26441) // The lock is named, this appears to be a false positive
|
||||
lock = _terminal->LockForWriting();
|
||||
if (_uiaProviderInitialized)
|
||||
{
|
||||
return _uiaProvider.Get();
|
||||
}
|
||||
|
||||
auto lock = _terminal->LockForWriting();
|
||||
LOG_IF_FAILED(::Microsoft::WRL::MakeAndInitialize<::Microsoft::Terminal::TermControlUiaProvider>(&_uiaProvider, this->GetUiaData(), this));
|
||||
_uiaProviderInitialized = true;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
LOG_HR(wil::ResultFromCaughtException());
|
||||
_uiaProvider = nullptr;
|
||||
}
|
||||
_uiaProviderInitialized = true;
|
||||
}
|
||||
|
||||
return _uiaProvider.Get();
|
||||
@@ -798,7 +793,7 @@ void _stdcall TerminalSetTheme(void* terminal, TerminalTheme theme, LPCWSTR font
|
||||
}
|
||||
}
|
||||
|
||||
publicTerminal->_terminal->SetCursorStyle(theme.CursorStyle);
|
||||
publicTerminal->_terminal->SetCursorStyle(static_cast<DispatchTypes::CursorStyle>(theme.CursorStyle));
|
||||
|
||||
publicTerminal->_desiredFont = { fontFamily, 0, DEFAULT_FONT_WEIGHT, { 0, fontSize }, CP_UTF8 };
|
||||
publicTerminal->_UpdateFont(newDpi);
|
||||
|
||||
@@ -19,7 +19,7 @@ typedef struct _TerminalTheme
|
||||
COLORREF DefaultForeground;
|
||||
COLORREF DefaultSelectionBackground;
|
||||
float SelectionBackgroundAlpha;
|
||||
DispatchTypes::CursorStyle CursorStyle;
|
||||
uint32_t CursorStyle; // This will be converted to DispatchTypes::CursorStyle (size_t), but C# cannot marshal an enum type and have it fit in a size_t.
|
||||
COLORREF ColorTable[16];
|
||||
} TerminalTheme, *LPTerminalTheme;
|
||||
|
||||
@@ -73,7 +73,6 @@ private:
|
||||
FontInfoDesired _desiredFont;
|
||||
FontInfo _actualFont;
|
||||
int _currentDpi;
|
||||
bool _uiaProviderInitialized;
|
||||
std::function<void(wchar_t*)> _pfnWriteCallback;
|
||||
::Microsoft::WRL::ComPtr<::Microsoft::Terminal::TermControlUiaProvider> _uiaProvider;
|
||||
|
||||
@@ -83,6 +82,7 @@ private:
|
||||
std::unique_ptr<::Microsoft::Console::Render::DxEngine> _renderEngine;
|
||||
|
||||
bool _focused{ false };
|
||||
bool _uiaProviderInitialized{ false };
|
||||
|
||||
std::chrono::milliseconds _multiClickTime;
|
||||
unsigned int _multiClickCounter{};
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
<ProjectName>PublicTerminalCore</ProjectName>
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
</PropertyGroup>
|
||||
<Import Project="..\..\..\common.openconsole.props" Condition="'$(OpenConsoleDir)'==''" />
|
||||
<Import Project="$(SolutionDir)src\common.build.pre.props" />
|
||||
<ItemGroup>
|
||||
<ClCompile Include="pch.cpp">
|
||||
@@ -21,27 +20,24 @@
|
||||
<ClInclude Include="pch.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\terminal\input\lib\terminalinput.vcxproj">
|
||||
<ProjectReference Include="$(SolutionDir)src\terminal\input\lib\terminalinput.vcxproj">
|
||||
<Project>{1cf55140-ef6a-4736-a403-957e4f7430bb}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\TerminalCore\lib\TerminalCore-lib.vcxproj">
|
||||
<ProjectReference Include="$(SolutionDir)src\cascadia\TerminalCore\lib\TerminalCore-lib.vcxproj">
|
||||
<Project>{ca5cad1a-abcd-429c-b551-8562ec954746}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="$(OpenConsoleDir)src\types\lib\types.vcxproj">
|
||||
<ProjectReference Include="$(SolutionDir)src\types\lib\types.vcxproj">
|
||||
<Project>{18D09A24-8240-42D6-8CB6-236EEE820263}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="$(OpenConsoleDir)src\buffer\out\lib\bufferout.vcxproj">
|
||||
<Project>{0cf235bd-2da0-407e-90ee-c467e8bbc714}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="$(OpenConsoleDir)src\renderer\base\lib\base.vcxproj">
|
||||
<ProjectReference Include="$(SolutionDir)src\renderer\base\lib\base.vcxproj">
|
||||
<Project>{af0a096a-8b3a-4949-81ef-7df8f0fee91f}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="$(OpenConsoleDir)src\terminal\parser\lib\parser.vcxproj">
|
||||
<Project>{3ae13314-1939-4dfa-9c14-38ca0834050c}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="$(OpenConsoleDir)src\renderer\dx\lib\dx.vcxproj">
|
||||
<ProjectReference Include="$(SolutionDir)src\renderer\dx\lib\dx.vcxproj">
|
||||
<Project>{48d21369-3d7b-4431-9967-24e81292cf62}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="$(SolutionDir)src\api-ms-win-core-synch-l1-2-0\api-ms-win-core-synch-l1-2-0.vcxproj">
|
||||
<Project>{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}</Project>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
|
||||
@@ -28,8 +28,10 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
|
||||
CATCH_LOG();
|
||||
}
|
||||
|
||||
// This is a private constructor to be used in unit tests, where we don't
|
||||
// want each Monarch to necessarily use the current PID.
|
||||
// This constructor is intended to be used in unit tests,
|
||||
// but we need to make it public in order to use make_self
|
||||
// in the tests. It's not exposed through the idl though
|
||||
// so it's not _truly_ fully public which should be acceptable.
|
||||
Monarch::Monarch(const uint64_t testPID) :
|
||||
_ourPID{ testPID }
|
||||
{
|
||||
@@ -78,6 +80,9 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
|
||||
peasant.IdentifyWindowsRequested({ this, &Monarch::_identifyWindows });
|
||||
peasant.RenameRequested({ this, &Monarch::_renameRequested });
|
||||
|
||||
peasant.ShowTrayIconRequested([this](auto&&, auto&&) { _ShowTrayIconRequestedHandlers(*this, nullptr); });
|
||||
peasant.HideTrayIconRequested([this](auto&&, auto&&) { _HideTrayIconRequestedHandlers(*this, nullptr); });
|
||||
|
||||
_peasants[newPeasantsId] = peasant;
|
||||
|
||||
TraceLoggingWrite(g_hRemotingProvider,
|
||||
@@ -201,6 +206,12 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
|
||||
_clearOldMruEntries(id);
|
||||
}
|
||||
|
||||
TraceLoggingWrite(g_hRemotingProvider,
|
||||
"Monarch_lookupPeasantIdForName",
|
||||
TraceLoggingWideString(std::wstring{ name }.c_str(), "name", "the name we're looking for"),
|
||||
TraceLoggingUInt64(result, "peasantID", "the ID of the peasant with that name"),
|
||||
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
|
||||
TraceLoggingKeyword(TIL_KEYWORD_TRACE));
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -732,24 +743,55 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
|
||||
try
|
||||
{
|
||||
args.FoundMatch(false);
|
||||
|
||||
// If a WindowID is provided from the args, use that first.
|
||||
uint64_t windowId = 0;
|
||||
// If no name was provided, then just summon the MRU window.
|
||||
if (searchedForName.empty())
|
||||
if (args.WindowID())
|
||||
{
|
||||
// Use the value of the `desktop` arg to determine if we should
|
||||
// limit to the current desktop (desktop:onCurrent) or not
|
||||
// (desktop:any or desktop:toCurrent)
|
||||
windowId = _getMostRecentPeasantID(args.OnCurrentDesktop(), false);
|
||||
windowId = args.WindowID().Value();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Try to find a peasant that currently has this name
|
||||
windowId = _lookupPeasantIdForName(searchedForName);
|
||||
// If no name was provided, then just summon the MRU window.
|
||||
if (searchedForName.empty())
|
||||
{
|
||||
// Use the value of the `desktop` arg to determine if we should
|
||||
// limit to the current desktop (desktop:onCurrent) or not
|
||||
// (desktop:any or desktop:toCurrent)
|
||||
windowId = _getMostRecentPeasantID(args.OnCurrentDesktop(), false);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Try to find a peasant that currently has this name
|
||||
windowId = _lookupPeasantIdForName(searchedForName);
|
||||
}
|
||||
}
|
||||
|
||||
if (auto targetPeasant{ _getPeasant(windowId) })
|
||||
{
|
||||
targetPeasant.Summon(args.SummonBehavior());
|
||||
args.FoundMatch(true);
|
||||
|
||||
TraceLoggingWrite(g_hRemotingProvider,
|
||||
"Monarch_SummonWindow_Success",
|
||||
TraceLoggingWideString(searchedForName.c_str(), "searchedForName", "The name of the window we tried to summon"),
|
||||
TraceLoggingUInt64(windowId, "peasantID", "The id of the window we tried to summon"),
|
||||
TraceLoggingBoolean(args.OnCurrentDesktop(), "OnCurrentDesktop", "true iff the window needs to be on the current virtual desktop"),
|
||||
TraceLoggingBoolean(args.SummonBehavior().MoveToCurrentDesktop(), "MoveToCurrentDesktop", "if true, move the window to the current virtual desktop"),
|
||||
TraceLoggingBoolean(args.SummonBehavior().ToggleVisibility(), "ToggleVisibility", "true if we should toggle the visibility of the window"),
|
||||
TraceLoggingUInt32(args.SummonBehavior().DropdownDuration(), "DropdownDuration", "the duration to dropdown the window"),
|
||||
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
|
||||
TraceLoggingKeyword(TIL_KEYWORD_TRACE));
|
||||
}
|
||||
else
|
||||
{
|
||||
TraceLoggingWrite(g_hRemotingProvider,
|
||||
"Monarch_SummonWindow_NoPeasant",
|
||||
TraceLoggingWideString(searchedForName.c_str(), "searchedForName", "The name of the window we tried to summon"),
|
||||
TraceLoggingUInt64(windowId, "peasantID", "The id of the window we tried to summon"),
|
||||
TraceLoggingBoolean(args.OnCurrentDesktop(), "OnCurrentDesktop", "true iff the window needs to be on the current virtual desktop"),
|
||||
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
|
||||
TraceLoggingKeyword(TIL_KEYWORD_TRACE));
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
@@ -762,4 +804,56 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
|
||||
TraceLoggingKeyword(TIL_KEYWORD_TRACE));
|
||||
}
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - This method creates a map of peasant IDs to peasant names
|
||||
// while removing dead peasants.
|
||||
// Arguments:
|
||||
// - <none>
|
||||
// Return Value:
|
||||
// - A map of peasant IDs to their names.
|
||||
Windows::Foundation::Collections::IMapView<uint64_t, winrt::hstring> Monarch::GetPeasantNames()
|
||||
{
|
||||
auto names = winrt::single_threaded_map<uint64_t, winrt::hstring>();
|
||||
|
||||
std::vector<uint64_t> peasantsToErase{};
|
||||
for (const auto& [id, p] : _peasants)
|
||||
{
|
||||
try
|
||||
{
|
||||
names.Insert(id, p.WindowName());
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
LOG_CAUGHT_EXCEPTION();
|
||||
peasantsToErase.push_back(id);
|
||||
}
|
||||
}
|
||||
|
||||
// Remove the dead peasants we came across while iterating.
|
||||
for (const auto& id : peasantsToErase)
|
||||
{
|
||||
_peasants.erase(id);
|
||||
_clearOldMruEntries(id);
|
||||
}
|
||||
|
||||
return names.GetView();
|
||||
}
|
||||
|
||||
void Monarch::SummonAllWindows()
|
||||
{
|
||||
auto callback = [](auto&& p, auto&& /*id*/) {
|
||||
SummonWindowBehavior args{};
|
||||
args.ToggleVisibility(false);
|
||||
p.Summon(args);
|
||||
};
|
||||
auto onError = [](auto&& id) {
|
||||
TraceLoggingWrite(g_hRemotingProvider,
|
||||
"Monarch_SummonAll_Failed",
|
||||
TraceLoggingInt64(id, "peasantID", "The ID of the peasant which we could not summon"),
|
||||
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
|
||||
TraceLoggingKeyword(TIL_KEYWORD_TRACE));
|
||||
};
|
||||
_forAllPeasantsIgnoringTheDead(callback, onError);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,6 +41,7 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
|
||||
struct Monarch : public MonarchT<Monarch>
|
||||
{
|
||||
Monarch();
|
||||
Monarch(const uint64_t testPID);
|
||||
~Monarch();
|
||||
|
||||
uint64_t GetPID();
|
||||
@@ -51,10 +52,14 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
|
||||
void HandleActivatePeasant(const winrt::Microsoft::Terminal::Remoting::WindowActivatedArgs& args);
|
||||
void SummonWindow(const Remoting::SummonWindowSelectionArgs& args);
|
||||
|
||||
void SummonAllWindows();
|
||||
Windows::Foundation::Collections::IMapView<uint64_t, winrt::hstring> GetPeasantNames();
|
||||
|
||||
TYPED_EVENT(FindTargetWindowRequested, winrt::Windows::Foundation::IInspectable, winrt::Microsoft::Terminal::Remoting::FindTargetWindowArgs);
|
||||
TYPED_EVENT(ShowTrayIconRequested, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
|
||||
TYPED_EVENT(HideTrayIconRequested, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
|
||||
|
||||
private:
|
||||
Monarch(const uint64_t testPID);
|
||||
uint64_t _ourPID;
|
||||
|
||||
uint64_t _nextPeasantID{ 1 };
|
||||
|
||||
@@ -28,6 +28,7 @@ namespace Microsoft.Terminal.Remoting
|
||||
|
||||
Boolean FoundMatch;
|
||||
SummonWindowBehavior SummonBehavior;
|
||||
Windows.Foundation.IReference<UInt64> WindowID;
|
||||
}
|
||||
|
||||
|
||||
@@ -40,6 +41,11 @@ namespace Microsoft.Terminal.Remoting
|
||||
void HandleActivatePeasant(WindowActivatedArgs args);
|
||||
void SummonWindow(SummonWindowSelectionArgs args);
|
||||
|
||||
void SummonAllWindows();
|
||||
Windows.Foundation.Collections.IMapView<UInt64, String> GetPeasantNames { get; };
|
||||
|
||||
event Windows.Foundation.TypedEventHandler<Object, FindTargetWindowArgs> FindTargetWindowRequested;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> ShowTrayIconRequested;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> HideTrayIconRequested;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -20,8 +20,10 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
|
||||
{
|
||||
}
|
||||
|
||||
// This is a private constructor to be used in unit tests, where we don't
|
||||
// want each Peasant to necessarily use the current PID.
|
||||
// This constructor is intended to be used in unit tests,
|
||||
// but we need to make it public in order to use make_self
|
||||
// in the tests. It's not exposed through the idl though
|
||||
// so it's not _truly_ fully public which should be acceptable.
|
||||
Peasant::Peasant(const uint64_t testPID) :
|
||||
_ourPID{ testPID }
|
||||
{
|
||||
@@ -31,6 +33,7 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
|
||||
{
|
||||
_id = id;
|
||||
}
|
||||
|
||||
uint64_t Peasant::GetID()
|
||||
{
|
||||
return _id;
|
||||
@@ -222,4 +225,36 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
|
||||
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
|
||||
TraceLoggingKeyword(TIL_KEYWORD_TRACE));
|
||||
}
|
||||
|
||||
void Peasant::RequestShowTrayIcon()
|
||||
{
|
||||
try
|
||||
{
|
||||
_ShowTrayIconRequestedHandlers(*this, nullptr);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
LOG_CAUGHT_EXCEPTION();
|
||||
}
|
||||
TraceLoggingWrite(g_hRemotingProvider,
|
||||
"Peasant_RequestShowTrayIcon",
|
||||
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
|
||||
TraceLoggingKeyword(TIL_KEYWORD_TRACE));
|
||||
}
|
||||
|
||||
void Peasant::RequestHideTrayIcon()
|
||||
{
|
||||
try
|
||||
{
|
||||
_HideTrayIconRequestedHandlers(*this, nullptr);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
LOG_CAUGHT_EXCEPTION();
|
||||
}
|
||||
TraceLoggingWrite(g_hRemotingProvider,
|
||||
"Peasant_RequestHideTrayIcon",
|
||||
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
|
||||
TraceLoggingKeyword(TIL_KEYWORD_TRACE));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,6 +28,8 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
|
||||
void RequestIdentifyWindows();
|
||||
void DisplayWindowId();
|
||||
void RequestRename(const winrt::Microsoft::Terminal::Remoting::RenameRequestArgs& args);
|
||||
void RequestShowTrayIcon();
|
||||
void RequestHideTrayIcon();
|
||||
|
||||
winrt::Microsoft::Terminal::Remoting::WindowActivatedArgs GetLastActivatedArgs();
|
||||
|
||||
@@ -40,6 +42,8 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
|
||||
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(ShowTrayIconRequested, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
|
||||
TYPED_EVENT(HideTrayIconRequested, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
|
||||
|
||||
private:
|
||||
Peasant(const uint64_t testPID);
|
||||
|
||||
@@ -64,6 +64,8 @@ namespace Microsoft.Terminal.Remoting
|
||||
void RequestIdentifyWindows(); // Tells us to raise a IdentifyWindowsRequested
|
||||
void RequestRename(RenameRequestArgs args); // Tells us to raise a RenameRequested
|
||||
void Summon(SummonWindowBehavior behavior);
|
||||
void RequestShowTrayIcon();
|
||||
void RequestHideTrayIcon();
|
||||
|
||||
event Windows.Foundation.TypedEventHandler<Object, WindowActivatedArgs> WindowActivated;
|
||||
event Windows.Foundation.TypedEventHandler<Object, CommandlineArgs> ExecuteCommandlineRequested;
|
||||
@@ -71,6 +73,8 @@ namespace Microsoft.Terminal.Remoting
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> DisplayWindowIdRequested;
|
||||
event Windows.Foundation.TypedEventHandler<Object, RenameRequestArgs> RenameRequested;
|
||||
event Windows.Foundation.TypedEventHandler<Object, SummonWindowBehavior> SummonRequested;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> ShowTrayIconRequested;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> HideTrayIconRequested;
|
||||
};
|
||||
|
||||
[default_interface] runtimeclass Peasant : IPeasant
|
||||
|
||||
@@ -34,6 +34,8 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
|
||||
WINRT_PROPERTY(bool, FoundMatch, false);
|
||||
WINRT_PROPERTY(bool, OnCurrentDesktop, false);
|
||||
WINRT_PROPERTY(SummonWindowBehavior, SummonBehavior);
|
||||
|
||||
WINRT_PROPERTY(Windows::Foundation::IReference<uint64_t>, WindowID);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -254,6 +254,8 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
|
||||
// window, and when the current monarch dies.
|
||||
|
||||
_monarch.FindTargetWindowRequested({ this, &WindowManager::_raiseFindTargetWindowRequested });
|
||||
_monarch.ShowTrayIconRequested([this](auto&&, auto&&) { _ShowTrayIconRequestedHandlers(*this, nullptr); });
|
||||
_monarch.HideTrayIconRequested([this](auto&&, auto&&) { _HideTrayIconRequestedHandlers(*this, nullptr); });
|
||||
|
||||
_BecameMonarchHandlers(*this, nullptr);
|
||||
}
|
||||
@@ -509,4 +511,57 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
|
||||
_monarch.SummonWindow(args);
|
||||
}
|
||||
|
||||
void WindowManager::SummonAllWindows()
|
||||
{
|
||||
if constexpr (Feature_TrayIcon::IsEnabled())
|
||||
{
|
||||
_monarch.SummonAllWindows();
|
||||
}
|
||||
}
|
||||
|
||||
Windows::Foundation::Collections::IMapView<uint64_t, winrt::hstring> WindowManager::GetPeasantNames()
|
||||
{
|
||||
// We should only get called when we're the monarch since the monarch
|
||||
// is the only one that knows about all peasants.
|
||||
return _monarch.GetPeasantNames();
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Ask the monarch to show a tray icon.
|
||||
// Arguments:
|
||||
// - <none>
|
||||
// Return Value:
|
||||
// - <none>
|
||||
winrt::fire_and_forget WindowManager::RequestShowTrayIcon()
|
||||
{
|
||||
co_await winrt::resume_background();
|
||||
_peasant.RequestShowTrayIcon();
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Ask the monarch to hide its tray icon.
|
||||
// Arguments:
|
||||
// - <none>
|
||||
// Return Value:
|
||||
// - <none>
|
||||
winrt::fire_and_forget WindowManager::RequestHideTrayIcon()
|
||||
{
|
||||
auto strongThis{ get_strong() };
|
||||
co_await winrt::resume_background();
|
||||
_peasant.RequestHideTrayIcon();
|
||||
}
|
||||
|
||||
bool WindowManager::DoesQuakeWindowExist()
|
||||
{
|
||||
const auto names = GetPeasantNames();
|
||||
for (const auto [id, name] : names)
|
||||
{
|
||||
if (name == QuakeWindowName)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -40,8 +40,17 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
|
||||
bool IsMonarch();
|
||||
void SummonWindow(const Remoting::SummonWindowSelectionArgs& args);
|
||||
|
||||
void SummonAllWindows();
|
||||
Windows::Foundation::Collections::IMapView<uint64_t, winrt::hstring> GetPeasantNames();
|
||||
|
||||
winrt::fire_and_forget RequestShowTrayIcon();
|
||||
winrt::fire_and_forget RequestHideTrayIcon();
|
||||
bool DoesQuakeWindowExist();
|
||||
|
||||
TYPED_EVENT(FindTargetWindowRequested, winrt::Windows::Foundation::IInspectable, winrt::Microsoft::Terminal::Remoting::FindTargetWindowArgs);
|
||||
TYPED_EVENT(BecameMonarch, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
|
||||
TYPED_EVENT(ShowTrayIconRequested, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
|
||||
TYPED_EVENT(HideTrayIconRequested, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
|
||||
|
||||
private:
|
||||
bool _shouldCreateWindow{ false };
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user