mirror of
https://github.com/microsoft/terminal.git
synced 2026-04-06 14:19:45 +00:00
Compare commits
22 Commits
dev/migrie
...
dev/cazamo
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
99fa2805f0 | ||
|
|
efa955719e | ||
|
|
f256a551e8 | ||
|
|
0564cae164 | ||
|
|
a961fc26af | ||
|
|
17fc18b893 | ||
|
|
d6f3864242 | ||
|
|
3d3f355553 | ||
|
|
dc1de34bb7 | ||
|
|
8507ef0471 | ||
|
|
4fde1b0891 | ||
|
|
d1b71eddb6 | ||
|
|
9a1af76830 | ||
|
|
8840bc58f7 | ||
|
|
a00b84f86a | ||
|
|
bc996c0170 | ||
|
|
460f91477c | ||
|
|
9de4f58999 | ||
|
|
68984c811b | ||
|
|
c0c5a49ffd | ||
|
|
42c43ff2e9 | ||
|
|
e8dd48625c |
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.
|
||||
48
.github/actions/spelling/advice.md
vendored
Normal file
48
.github/actions/spelling/advice.md
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
<!-- See https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples%3A-advice --> <!-- markdownlint-disable MD033 MD041 -->
|
||||
<details>
|
||||
<summary>
|
||||
:pencil2: Contributor please read this
|
||||
</summary>
|
||||
|
||||
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. 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:
|
||||
|
||||
* ... **misspelled**, then please *correct* them instead of using the command.
|
||||
* ... *names*, please add them to `.github/actions/spelling/allow/names.txt`.
|
||||
* ... APIs, you can add them to a file in `.github/actions/spelling/allow/`.
|
||||
* ... just things you're using, please add them to an appropriate file in `.github/actions/spelling/expect/`.
|
||||
* ... tokens you only need in one place and shouldn't *generally be used*, you can add an item in an appropriate file in `.github/actions/spelling/patterns/`.
|
||||
|
||||
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>If the flagged items are :exploding_head: false positives</summary>
|
||||
|
||||
If items relate to a ...
|
||||
* binary file (or some other file you wouldn't want to check at all).
|
||||
|
||||
Please add a file path to the `excludes.txt` file matching the containing file.
|
||||
|
||||
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](
|
||||
../tree/HEAD/README.md) (on whichever branch you're using).
|
||||
|
||||
* 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>
|
||||
27
.github/actions/spelling/advice.txt
vendored
27
.github/actions/spelling/advice.txt
vendored
@@ -1,27 +0,0 @@
|
||||
<details>
|
||||
<summary>
|
||||
:pencil2: Contributor please read this
|
||||
</summary>
|
||||
|
||||
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...
|
||||
|
||||
If the listed items are:
|
||||
* ... **misspelled**, then please *correct* them instead of using the command.
|
||||
* ... *names*, please add them to `.github/actions/spelling/dictionary/names.txt`.
|
||||
* ... APIs, you can add them to a file in `.github/actions/spelling/dictionary/`.
|
||||
* ... just things you're using, please add them to an appropriate file in `.github/actions/spelling/expect/`.
|
||||
* ... tokens you only need in one place and shouldn't *generally be used*, you can add an item in an appropriate file in `.github/actions/spelling/patterns/`.
|
||||
|
||||
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:
|
||||
|
||||
:clamp: If you see a bunch of garbage and it relates to a binary-ish string, please add a file path to the `.github/actions/spelling/excludes.txt` file instead of just accepting the garbage.
|
||||
|
||||
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](https://github.com/microsoft/terminal/blob/main/README.md) (on whichever branch you're using).
|
||||
</details>
|
||||
@@ -1,4 +1,4 @@
|
||||
# Dictionaries are lists of words to accept unconditionally
|
||||
# Allow files are lists of words to accept unconditionally
|
||||
|
||||
While check spelling will complain about an expected word
|
||||
which is no longer present, you can include things here even if
|
||||
@@ -8,11 +8,11 @@ E.g., you could include a list of system APIs here, or potential
|
||||
contributors (so that if a future commit includes their name,
|
||||
it'll be accepted).
|
||||
|
||||
### Files
|
||||
## Files
|
||||
|
||||
| File | Description |
|
||||
| ---- | ----------- |
|
||||
| [Dictionary](dictionary.txt) | Primary US English dictionary |
|
||||
| [Allow](allow.txt) | Supplements to the dictionary |
|
||||
| [Chinese](chinese.txt) | Chinese words |
|
||||
| [Japanese](japanese.txt) | Japanese words |
|
||||
| [Microsoft](microsoft.txt) | Microsoft brand items |
|
||||
108
.github/actions/spelling/allow/allow.txt
vendored
Normal file
108
.github/actions/spelling/allow/allow.txt
vendored
Normal file
@@ -0,0 +1,108 @@
|
||||
admins
|
||||
allcolors
|
||||
Apc
|
||||
apc
|
||||
breadcrumb
|
||||
breadcrumbs
|
||||
bsd
|
||||
calt
|
||||
ccmp
|
||||
changelog
|
||||
clickable
|
||||
clig
|
||||
CMMI
|
||||
copyable
|
||||
cybersecurity
|
||||
dalet
|
||||
Dcs
|
||||
dcs
|
||||
dialytika
|
||||
dje
|
||||
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
|
||||
@@ -1,23 +1,48 @@
|
||||
ACCEPTFILES
|
||||
ACCESSDENIED
|
||||
acl
|
||||
aclapi
|
||||
alignas
|
||||
alignof
|
||||
APPLYTOSUBMENUS
|
||||
appxrecipe
|
||||
bitfield
|
||||
bitfields
|
||||
BUILDBRANCH
|
||||
BUILDMSG
|
||||
BUILDNUMBER
|
||||
BYCOMMAND
|
||||
BYPOSITION
|
||||
charconv
|
||||
CLASSNOTAVAILABLE
|
||||
CLOSEAPP
|
||||
cmdletbinding
|
||||
colspan
|
||||
COLORPROPERTY
|
||||
colspan
|
||||
COMDLG
|
||||
commandlinetoargv
|
||||
comparand
|
||||
cstdint
|
||||
CXICON
|
||||
CYICON
|
||||
D2DERR_SHADER_COMPILE_FAILED
|
||||
Dacl
|
||||
dataobject
|
||||
dcomp
|
||||
DERR
|
||||
dlldata
|
||||
DNE
|
||||
DONTADDTORECENT
|
||||
DWMSBT
|
||||
DWMWA
|
||||
DWMWA
|
||||
DWORDLONG
|
||||
endfor
|
||||
ENDSESSION
|
||||
enumset
|
||||
environstrings
|
||||
EXPCMDFLAGS
|
||||
EXPCMDSTATE
|
||||
filetime
|
||||
FILTERSPEC
|
||||
FORCEFILESYSTEM
|
||||
FORCEMINIMIZE
|
||||
@@ -26,11 +51,16 @@ fullkbd
|
||||
futex
|
||||
GETDESKWALLPAPER
|
||||
GETHIGHCONTRAST
|
||||
GETMOUSEHOVERTIME
|
||||
Hashtable
|
||||
HIGHCONTRASTON
|
||||
HIGHCONTRASTW
|
||||
hotkeys
|
||||
href
|
||||
hrgn
|
||||
HTCLOSE
|
||||
hwinsta
|
||||
HWINSTA
|
||||
IActivation
|
||||
IApp
|
||||
IAppearance
|
||||
@@ -39,97 +69,180 @@ IBind
|
||||
IBox
|
||||
IClass
|
||||
IComparable
|
||||
IComparer
|
||||
IConnection
|
||||
ICustom
|
||||
IDialog
|
||||
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
|
||||
MULTIPLEUSE
|
||||
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
|
||||
REGCLS
|
||||
ptstr
|
||||
QUERYENDSESSION
|
||||
rcx
|
||||
REGCLS
|
||||
RETURNCMD
|
||||
rfind
|
||||
ROOTOWNER
|
||||
roundf
|
||||
RSHIFT
|
||||
rx
|
||||
SACL
|
||||
schandle
|
||||
semver
|
||||
serializer
|
||||
SETVERSION
|
||||
SHELLEXECUTEINFOW
|
||||
shobjidl
|
||||
SINGLEUSE
|
||||
SHOWHIDE
|
||||
SHOWMINIMIZED
|
||||
SHOWTIP
|
||||
SINGLEUSE
|
||||
SIZENS
|
||||
smoothstep
|
||||
GETDESKWALLPAPER
|
||||
SHELLEXECUTEINFOW
|
||||
snprintf
|
||||
spsc
|
||||
sregex
|
||||
SRWLOC
|
||||
SRWLOCK
|
||||
STDCPP
|
||||
strchr
|
||||
STDMETHOD
|
||||
strchr
|
||||
strcpy
|
||||
streambuf
|
||||
strtoul
|
||||
Stubless
|
||||
Subheader
|
||||
Subpage
|
||||
UPDATEINIFILE
|
||||
syscall
|
||||
SYSTEMBACKDROP
|
||||
TABROW
|
||||
TASKBARCREATED
|
||||
TBPF
|
||||
THEMECHANGED
|
||||
tlg
|
||||
TME
|
||||
tmp
|
||||
tmpdir
|
||||
tolower
|
||||
toupper
|
||||
TRACKMOUSEEVENT
|
||||
TTask
|
||||
TVal
|
||||
tx
|
||||
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
|
||||
xlocinfo
|
||||
xlocmes
|
||||
xlocmon
|
||||
xlocnum
|
||||
xloctime
|
||||
XMax
|
||||
xmemory
|
||||
XParse
|
||||
xpath
|
||||
xstddef
|
||||
xstring
|
||||
xtree
|
||||
xutility
|
||||
YIcon
|
||||
YMax
|
||||
117
.github/actions/spelling/allow/colors.txt
vendored
Normal file
117
.github/actions/spelling/allow/colors.txt
vendored
Normal file
@@ -0,0 +1,117 @@
|
||||
alice
|
||||
aliceblue
|
||||
antiquewhite
|
||||
blanchedalmond
|
||||
blueviolet
|
||||
burlywood
|
||||
cadetblue
|
||||
cornflowerblue
|
||||
cornsilk
|
||||
cyan
|
||||
darkblue
|
||||
darkcyan
|
||||
darkgoldenrod
|
||||
darkgray
|
||||
darkgreen
|
||||
darkgrey
|
||||
darkkhaki
|
||||
darkmagenta
|
||||
darkolivegreen
|
||||
darkorange
|
||||
darkorchid
|
||||
darkred
|
||||
darksalmon
|
||||
darkseagreen
|
||||
darkslateblue
|
||||
darkslategray
|
||||
darkslategrey
|
||||
darkturquoise
|
||||
darkviolet
|
||||
deeppink
|
||||
deepskyblue
|
||||
dimgray
|
||||
dimgrey
|
||||
dodgerblue
|
||||
firebrick
|
||||
floralwhite
|
||||
forestgreen
|
||||
gainsboro
|
||||
ghostwhite
|
||||
greenyellow
|
||||
hotpink
|
||||
indian
|
||||
indianred
|
||||
lavenderblush
|
||||
lawngreen
|
||||
lemonchiffon
|
||||
lightblue
|
||||
lightcoral
|
||||
lightcyan
|
||||
lightgoldenrod
|
||||
lightgoldenrodyellow
|
||||
lightgray
|
||||
lightgreen
|
||||
lightgrey
|
||||
lightpink
|
||||
lightsalmon
|
||||
lightseagreen
|
||||
lightskyblue
|
||||
lightslateblue
|
||||
lightslategray
|
||||
lightslategrey
|
||||
lightsteelblue
|
||||
lightyellow
|
||||
limegreen
|
||||
mediumaquamarine
|
||||
mediumblue
|
||||
mediumorchid
|
||||
mediumpurple
|
||||
mediumseagreen
|
||||
mediumslateblue
|
||||
mediumspringgreen
|
||||
mediumturquoise
|
||||
mediumvioletred
|
||||
midnightblue
|
||||
mintcream
|
||||
mistyrose
|
||||
navajo
|
||||
navajowhite
|
||||
navyblue
|
||||
oldlace
|
||||
olivedrab
|
||||
orangered
|
||||
palegoldenrod
|
||||
palegreen
|
||||
paleturquoise
|
||||
palevioletred
|
||||
papayawhip
|
||||
peachpuff
|
||||
peru
|
||||
powderblue
|
||||
rebecca
|
||||
rebeccapurple
|
||||
rosybrown
|
||||
royalblue
|
||||
saddlebrown
|
||||
sandybrown
|
||||
seagreen
|
||||
sienna
|
||||
skyblue
|
||||
slateblue
|
||||
slategray
|
||||
slategrey
|
||||
springgreen
|
||||
steelblue
|
||||
violetred
|
||||
webgray
|
||||
webgreen
|
||||
webgrey
|
||||
webmaroon
|
||||
webpurple
|
||||
whitesmoke
|
||||
xaroon
|
||||
xray
|
||||
xreen
|
||||
xrey
|
||||
xurple
|
||||
yellowgreen
|
||||
@@ -7,3 +7,4 @@ Iosevka
|
||||
MDL
|
||||
Monofur
|
||||
Segoe
|
||||
wght
|
||||
11
.github/actions/spelling/allow/math.txt
vendored
Normal file
11
.github/actions/spelling/allow/math.txt
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
atan
|
||||
CPrime
|
||||
HBar
|
||||
HPrime
|
||||
isnan
|
||||
LPrime
|
||||
LStep
|
||||
powf
|
||||
RSub
|
||||
sqrtf
|
||||
ULP
|
||||
@@ -1,17 +1,25 @@
|
||||
ACLs
|
||||
ADMINS
|
||||
advapi
|
||||
altform
|
||||
altforms
|
||||
appendwttlogging
|
||||
appx
|
||||
appxbundle
|
||||
appxerror
|
||||
appxmanifest
|
||||
ATL
|
||||
backplating
|
||||
bitmaps
|
||||
BOMs
|
||||
CPLs
|
||||
CPRs
|
||||
cpptools
|
||||
cppvsdbg
|
||||
CPRs
|
||||
cryptbase
|
||||
DACL
|
||||
DACLs
|
||||
defaultlib
|
||||
diffs
|
||||
disposables
|
||||
dotnetfeed
|
||||
@@ -19,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
|
||||
@@ -34,20 +52,31 @@ powerrename
|
||||
powershell
|
||||
propkey
|
||||
pscustomobject
|
||||
QWORD
|
||||
regedit
|
||||
robocopy
|
||||
SACLs
|
||||
sdkddkver
|
||||
Shobjidl
|
||||
Skype
|
||||
SRW
|
||||
sxs
|
||||
Sysinternals
|
||||
sysnative
|
||||
systemroot
|
||||
taskkill
|
||||
tasklist
|
||||
tdbuildteamid
|
||||
ucrt
|
||||
ucrtd
|
||||
unvirtualized
|
||||
VCRT
|
||||
vcruntime
|
||||
Virtualization
|
||||
visualstudio
|
||||
vscode
|
||||
VSTHRD
|
||||
winsdkver
|
||||
wlk
|
||||
wslpath
|
||||
wtl
|
||||
@@ -1,24 +1,30 @@
|
||||
Anup
|
||||
austdi
|
||||
arkthur
|
||||
Ballmer
|
||||
bhoj
|
||||
Bhojwani
|
||||
Bluloco
|
||||
carlos
|
||||
dhowett
|
||||
Diviness
|
||||
dsafa
|
||||
duhowett
|
||||
DXP
|
||||
ekg
|
||||
eryksun
|
||||
ethanschoonover
|
||||
Firefox
|
||||
Gatta
|
||||
glsl
|
||||
Gravell
|
||||
Grie
|
||||
Griese
|
||||
Hernan
|
||||
Howett
|
||||
Illhardt
|
||||
iquilezles
|
||||
italo
|
||||
jantari
|
||||
jerrysh
|
||||
Kaiyu
|
||||
@@ -30,8 +36,11 @@ Kourosh
|
||||
kowalczyk
|
||||
leonmsft
|
||||
Lepilleur
|
||||
lhecker
|
||||
lukesampson
|
||||
Macbook
|
||||
Manandhar
|
||||
masserano
|
||||
mbadolato
|
||||
Mehrain
|
||||
menger
|
||||
@@ -51,6 +60,7 @@ oldnewthing
|
||||
opengl
|
||||
osgwiki
|
||||
pabhojwa
|
||||
panos
|
||||
paulcam
|
||||
pauldotknopf
|
||||
PGP
|
||||
@@ -59,18 +69,23 @@ Rincewind
|
||||
rprichard
|
||||
Schoonover
|
||||
shadertoy
|
||||
Shomnipotence
|
||||
simioni
|
||||
Somuah
|
||||
sonph
|
||||
sonpham
|
||||
stakx
|
||||
talo
|
||||
thereses
|
||||
Walisch
|
||||
WDX
|
||||
Wellons
|
||||
Wirt
|
||||
Wojciech
|
||||
zadjii
|
||||
Zamor
|
||||
zamora
|
||||
Zamora
|
||||
zamora
|
||||
Zoey
|
||||
zorio
|
||||
Zverovich
|
||||
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-)/
|
||||
782
.github/actions/spelling/dictionary/colors.txt
vendored
782
.github/actions/spelling/dictionary/colors.txt
vendored
@@ -1,782 +0,0 @@
|
||||
snow
|
||||
ghost-white
|
||||
ghostwhite
|
||||
white-smoke
|
||||
whitesmoke
|
||||
gainsboro
|
||||
floral-white
|
||||
floralwhite
|
||||
old-lace
|
||||
oldlace
|
||||
linen
|
||||
antique-white
|
||||
antiquewhite
|
||||
papaya-whip
|
||||
papayawhip
|
||||
blanched-almond
|
||||
blanchedalmond
|
||||
bisque
|
||||
peach-puff
|
||||
peachpuff
|
||||
navajo-white
|
||||
navajowhite
|
||||
moccasin
|
||||
cornsilk
|
||||
ivory
|
||||
lemon-chiffon
|
||||
lemonchiffon
|
||||
seashell
|
||||
honeydew
|
||||
mint-cream
|
||||
mintcream
|
||||
azure
|
||||
alice-blue
|
||||
aliceblue
|
||||
lavender
|
||||
lavender-blush
|
||||
lavenderblush
|
||||
misty-rose
|
||||
mistyrose
|
||||
white
|
||||
black
|
||||
dark-slate-gray
|
||||
darkslategray
|
||||
dark-slate-grey
|
||||
darkslategrey
|
||||
dim-gray
|
||||
dimgray
|
||||
dim-grey
|
||||
dimgrey
|
||||
slate-gray
|
||||
slategray
|
||||
slate-grey
|
||||
slategrey
|
||||
light-slate-gray
|
||||
lightslategray
|
||||
light-slate-grey
|
||||
lightslategrey
|
||||
gray
|
||||
grey
|
||||
xray
|
||||
x11gray
|
||||
xrey
|
||||
x11grey
|
||||
web-gray
|
||||
webgray
|
||||
web-grey
|
||||
webgrey
|
||||
light-grey
|
||||
lightgrey
|
||||
light-gray
|
||||
lightgray
|
||||
midnight-blue
|
||||
midnightblue
|
||||
navy
|
||||
navy-blue
|
||||
navyblue
|
||||
cornflower-blue
|
||||
cornflowerblue
|
||||
dark-slate-blue
|
||||
darkslateblue
|
||||
slate-blue
|
||||
slateblue
|
||||
medium-slate-blue
|
||||
mediumslateblue
|
||||
light-slate-blue
|
||||
lightslateblue
|
||||
medium-blue
|
||||
mediumblue
|
||||
royal-blue
|
||||
royalblue
|
||||
blue
|
||||
dodger-blue
|
||||
dodgerblue
|
||||
deep-sky-blue
|
||||
deepskyblue
|
||||
sky-blue
|
||||
skyblue
|
||||
light-sky-blue
|
||||
lightskyblue
|
||||
steel-blue
|
||||
steelblue
|
||||
light-steel-blue
|
||||
lightsteelblue
|
||||
light-blue
|
||||
lightblue
|
||||
powder-blue
|
||||
powderblue
|
||||
pale-turquoise
|
||||
paleturquoise
|
||||
dark-turquoise
|
||||
darkturquoise
|
||||
medium-turquoise
|
||||
mediumturquoise
|
||||
turquoise
|
||||
cyan
|
||||
aqua
|
||||
light-cyan
|
||||
lightcyan
|
||||
cadet-blue
|
||||
cadetblue
|
||||
medium-aquamarine
|
||||
mediumaquamarine
|
||||
aquamarine
|
||||
dark-green
|
||||
darkgreen
|
||||
dark-olive-green
|
||||
darkolivegreen
|
||||
dark-sea-green
|
||||
darkseagreen
|
||||
sea-green
|
||||
seagreen
|
||||
medium-sea-green
|
||||
mediumseagreen
|
||||
light-sea-green
|
||||
lightseagreen
|
||||
pale-green
|
||||
palegreen
|
||||
spring-green
|
||||
springgreen
|
||||
lawn-green
|
||||
lawngreen
|
||||
green
|
||||
lime
|
||||
xreen
|
||||
x11green
|
||||
web-green
|
||||
webgreen
|
||||
chartreuse
|
||||
medium-spring-green
|
||||
mediumspringgreen
|
||||
green-yellow
|
||||
greenyellow
|
||||
lime-green
|
||||
limegreen
|
||||
yellow-green
|
||||
yellowgreen
|
||||
forest-green
|
||||
forestgreen
|
||||
olive-drab
|
||||
olivedrab
|
||||
dark-khaki
|
||||
darkkhaki
|
||||
khaki
|
||||
pale-goldenrod
|
||||
palegoldenrod
|
||||
light-goldenrod-yellow
|
||||
lightgoldenrodyellow
|
||||
light-yellow
|
||||
lightyellow
|
||||
yellow
|
||||
gold
|
||||
light-goldenrod
|
||||
lightgoldenrod
|
||||
goldenrod
|
||||
dark-goldenrod
|
||||
darkgoldenrod
|
||||
rosy-brown
|
||||
rosybrown
|
||||
indian-red
|
||||
indianred
|
||||
saddle-brown
|
||||
saddlebrown
|
||||
sienna
|
||||
peru
|
||||
burlywood
|
||||
beige
|
||||
wheat
|
||||
sandy-brown
|
||||
sandybrown
|
||||
tan
|
||||
chocolate
|
||||
firebrick
|
||||
brown
|
||||
dark-salmon
|
||||
darksalmon
|
||||
salmon
|
||||
light-salmon
|
||||
lightsalmon
|
||||
orange
|
||||
dark-orange
|
||||
darkorange
|
||||
coral
|
||||
light-coral
|
||||
lightcoral
|
||||
tomato
|
||||
orange-red
|
||||
orangered
|
||||
red
|
||||
hot-pink
|
||||
hotpink
|
||||
deep-pink
|
||||
deeppink
|
||||
pink
|
||||
light-pink
|
||||
lightpink
|
||||
pale-violet-red
|
||||
palevioletred
|
||||
maroon
|
||||
xaroon
|
||||
x11maroon
|
||||
web-maroon
|
||||
webmaroon
|
||||
medium-violet-red
|
||||
mediumvioletred
|
||||
violet-red
|
||||
violetred
|
||||
magenta
|
||||
fuchsia
|
||||
violet
|
||||
plum
|
||||
orchid
|
||||
medium-orchid
|
||||
mediumorchid
|
||||
dark-orchid
|
||||
darkorchid
|
||||
dark-violet
|
||||
darkviolet
|
||||
blue-violet
|
||||
blueviolet
|
||||
purple
|
||||
xurple
|
||||
x11purple
|
||||
web-purple
|
||||
webpurple
|
||||
medium-purple
|
||||
mediumpurple
|
||||
thistle
|
||||
snow1
|
||||
snow2
|
||||
snow3
|
||||
snow4
|
||||
seashell1
|
||||
seashell2
|
||||
seashell3
|
||||
seashell4
|
||||
antiquewhite1
|
||||
antiquewhite2
|
||||
antiquewhite3
|
||||
antiquewhite4
|
||||
bisque1
|
||||
bisque2
|
||||
bisque3
|
||||
bisque4
|
||||
peachpuff1
|
||||
peachpuff2
|
||||
peachpuff3
|
||||
peachpuff4
|
||||
navajowhite1
|
||||
navajowhite2
|
||||
navajowhite3
|
||||
navajowhite4
|
||||
lemonchiffon1
|
||||
lemonchiffon2
|
||||
lemonchiffon3
|
||||
lemonchiffon4
|
||||
cornsilk1
|
||||
cornsilk2
|
||||
cornsilk3
|
||||
cornsilk4
|
||||
ivory1
|
||||
ivory2
|
||||
ivory3
|
||||
ivory4
|
||||
honeydew1
|
||||
honeydew2
|
||||
honeydew3
|
||||
honeydew4
|
||||
lavenderblush1
|
||||
lavenderblush2
|
||||
lavenderblush3
|
||||
lavenderblush4
|
||||
mistyrose1
|
||||
mistyrose2
|
||||
mistyrose3
|
||||
mistyrose4
|
||||
azure1
|
||||
azure2
|
||||
azure3
|
||||
azure4
|
||||
slateblue1
|
||||
slateblue2
|
||||
slateblue3
|
||||
slateblue4
|
||||
royalblue1
|
||||
royalblue2
|
||||
royalblue3
|
||||
royalblue4
|
||||
blue1
|
||||
blue2
|
||||
blue3
|
||||
blue4
|
||||
dodgerblue1
|
||||
dodgerblue2
|
||||
dodgerblue3
|
||||
dodgerblue4
|
||||
steelblue1
|
||||
steelblue2
|
||||
steelblue3
|
||||
steelblue4
|
||||
deepskyblue1
|
||||
deepskyblue2
|
||||
deepskyblue3
|
||||
deepskyblue4
|
||||
skyblue1
|
||||
skyblue2
|
||||
skyblue3
|
||||
skyblue4
|
||||
lightskyblue1
|
||||
lightskyblue2
|
||||
lightskyblue3
|
||||
lightskyblue4
|
||||
slategray1
|
||||
slategray2
|
||||
slategray3
|
||||
slategray4
|
||||
lightsteelblue1
|
||||
lightsteelblue2
|
||||
lightsteelblue3
|
||||
lightsteelblue4
|
||||
lightblue1
|
||||
lightblue2
|
||||
lightblue3
|
||||
lightblue4
|
||||
lightcyan1
|
||||
lightcyan2
|
||||
lightcyan3
|
||||
lightcyan4
|
||||
paleturquoise1
|
||||
paleturquoise2
|
||||
paleturquoise3
|
||||
paleturquoise4
|
||||
cadetblue1
|
||||
cadetblue2
|
||||
cadetblue3
|
||||
cadetblue4
|
||||
turquoise1
|
||||
turquoise2
|
||||
turquoise3
|
||||
turquoise4
|
||||
cyan1
|
||||
cyan2
|
||||
cyan3
|
||||
cyan4
|
||||
darkslategray1
|
||||
darkslategray2
|
||||
darkslategray3
|
||||
darkslategray4
|
||||
aquamarine1
|
||||
aquamarine2
|
||||
aquamarine3
|
||||
aquamarine4
|
||||
darkseagreen1
|
||||
darkseagreen2
|
||||
darkseagreen3
|
||||
darkseagreen4
|
||||
seagreen1
|
||||
seagreen2
|
||||
seagreen3
|
||||
seagreen4
|
||||
palegreen1
|
||||
palegreen2
|
||||
palegreen3
|
||||
palegreen4
|
||||
springgreen1
|
||||
springgreen2
|
||||
springgreen3
|
||||
springgreen4
|
||||
green1
|
||||
green2
|
||||
green3
|
||||
green4
|
||||
chartreuse1
|
||||
chartreuse2
|
||||
chartreuse3
|
||||
chartreuse4
|
||||
olivedrab1
|
||||
olivedrab2
|
||||
olivedrab3
|
||||
olivedrab4
|
||||
darkolivegreen1
|
||||
darkolivegreen2
|
||||
darkolivegreen3
|
||||
darkolivegreen4
|
||||
khaki1
|
||||
khaki2
|
||||
khaki3
|
||||
khaki4
|
||||
lightgoldenrod1
|
||||
lightgoldenrod2
|
||||
lightgoldenrod3
|
||||
lightgoldenrod4
|
||||
lightyellow1
|
||||
lightyellow2
|
||||
lightyellow3
|
||||
lightyellow4
|
||||
yellow1
|
||||
yellow2
|
||||
yellow3
|
||||
yellow4
|
||||
gold1
|
||||
gold2
|
||||
gold3
|
||||
gold4
|
||||
goldenrod1
|
||||
goldenrod2
|
||||
goldenrod3
|
||||
goldenrod4
|
||||
darkgoldenrod1
|
||||
darkgoldenrod2
|
||||
darkgoldenrod3
|
||||
darkgoldenrod4
|
||||
rosybrown1
|
||||
rosybrown2
|
||||
rosybrown3
|
||||
rosybrown4
|
||||
indianred1
|
||||
indianred2
|
||||
indianred3
|
||||
indianred4
|
||||
sienna1
|
||||
sienna2
|
||||
sienna3
|
||||
sienna4
|
||||
burlywood1
|
||||
burlywood2
|
||||
burlywood3
|
||||
burlywood4
|
||||
wheat1
|
||||
wheat2
|
||||
wheat3
|
||||
wheat4
|
||||
tan1
|
||||
tan2
|
||||
tan3
|
||||
tan4
|
||||
chocolate1
|
||||
chocolate2
|
||||
chocolate3
|
||||
chocolate4
|
||||
firebrick1
|
||||
firebrick2
|
||||
firebrick3
|
||||
firebrick4
|
||||
brown1
|
||||
brown2
|
||||
brown3
|
||||
brown4
|
||||
salmon1
|
||||
salmon2
|
||||
salmon3
|
||||
salmon4
|
||||
lightsalmon1
|
||||
lightsalmon2
|
||||
lightsalmon3
|
||||
lightsalmon4
|
||||
orange1
|
||||
orange2
|
||||
orange3
|
||||
orange4
|
||||
darkorange1
|
||||
darkorange2
|
||||
darkorange3
|
||||
darkorange4
|
||||
coral1
|
||||
coral2
|
||||
coral3
|
||||
coral4
|
||||
tomato1
|
||||
tomato2
|
||||
tomato3
|
||||
tomato4
|
||||
orangered1
|
||||
orangered2
|
||||
orangered3
|
||||
orangered4
|
||||
red1
|
||||
red2
|
||||
red3
|
||||
red4
|
||||
deeppink1
|
||||
deeppink2
|
||||
deeppink3
|
||||
deeppink4
|
||||
hotpink1
|
||||
hotpink2
|
||||
hotpink3
|
||||
hotpink4
|
||||
pink1
|
||||
pink2
|
||||
pink3
|
||||
pink4
|
||||
lightpink1
|
||||
lightpink2
|
||||
lightpink3
|
||||
lightpink4
|
||||
palevioletred1
|
||||
palevioletred2
|
||||
palevioletred3
|
||||
palevioletred4
|
||||
maroon1
|
||||
maroon2
|
||||
maroon3
|
||||
maroon4
|
||||
violetred1
|
||||
violetred2
|
||||
violetred3
|
||||
violetred4
|
||||
magenta1
|
||||
magenta2
|
||||
magenta3
|
||||
magenta4
|
||||
orchid1
|
||||
orchid2
|
||||
orchid3
|
||||
orchid4
|
||||
plum1
|
||||
plum2
|
||||
plum3
|
||||
plum4
|
||||
mediumorchid1
|
||||
mediumorchid2
|
||||
mediumorchid3
|
||||
mediumorchid4
|
||||
darkorchid1
|
||||
darkorchid2
|
||||
darkorchid3
|
||||
darkorchid4
|
||||
purple1
|
||||
purple2
|
||||
purple3
|
||||
purple4
|
||||
mediumpurple1
|
||||
mediumpurple2
|
||||
mediumpurple3
|
||||
mediumpurple4
|
||||
thistle1
|
||||
thistle2
|
||||
thistle3
|
||||
thistle4
|
||||
gray0
|
||||
grey0
|
||||
gray1
|
||||
grey1
|
||||
gray2
|
||||
grey2
|
||||
gray3
|
||||
grey3
|
||||
gray4
|
||||
grey4
|
||||
gray5
|
||||
grey5
|
||||
gray6
|
||||
grey6
|
||||
gray7
|
||||
grey7
|
||||
gray8
|
||||
grey8
|
||||
gray9
|
||||
grey9
|
||||
gray10
|
||||
grey10
|
||||
gray11
|
||||
grey11
|
||||
gray12
|
||||
grey12
|
||||
gray13
|
||||
grey13
|
||||
gray14
|
||||
grey14
|
||||
gray15
|
||||
grey15
|
||||
gray16
|
||||
grey16
|
||||
gray17
|
||||
grey17
|
||||
gray18
|
||||
grey18
|
||||
gray19
|
||||
grey19
|
||||
gray20
|
||||
grey20
|
||||
gray21
|
||||
grey21
|
||||
gray22
|
||||
grey22
|
||||
gray23
|
||||
grey23
|
||||
gray24
|
||||
grey24
|
||||
gray25
|
||||
grey25
|
||||
gray26
|
||||
grey26
|
||||
gray27
|
||||
grey27
|
||||
gray28
|
||||
grey28
|
||||
gray29
|
||||
grey29
|
||||
gray30
|
||||
grey30
|
||||
gray31
|
||||
grey31
|
||||
gray32
|
||||
grey32
|
||||
gray33
|
||||
grey33
|
||||
gray34
|
||||
grey34
|
||||
gray35
|
||||
grey35
|
||||
gray36
|
||||
grey36
|
||||
gray37
|
||||
grey37
|
||||
gray38
|
||||
grey38
|
||||
gray39
|
||||
grey39
|
||||
gray40
|
||||
grey40
|
||||
gray41
|
||||
grey41
|
||||
gray42
|
||||
grey42
|
||||
gray43
|
||||
grey43
|
||||
gray44
|
||||
grey44
|
||||
gray45
|
||||
grey45
|
||||
gray46
|
||||
grey46
|
||||
gray47
|
||||
grey47
|
||||
gray48
|
||||
grey48
|
||||
gray49
|
||||
grey49
|
||||
gray50
|
||||
grey50
|
||||
gray51
|
||||
grey51
|
||||
gray52
|
||||
grey52
|
||||
gray53
|
||||
grey53
|
||||
gray54
|
||||
grey54
|
||||
gray55
|
||||
grey55
|
||||
gray56
|
||||
grey56
|
||||
gray57
|
||||
grey57
|
||||
gray58
|
||||
grey58
|
||||
gray59
|
||||
grey59
|
||||
gray60
|
||||
grey60
|
||||
gray61
|
||||
grey61
|
||||
gray62
|
||||
grey62
|
||||
gray63
|
||||
grey63
|
||||
gray64
|
||||
grey64
|
||||
gray65
|
||||
grey65
|
||||
gray66
|
||||
grey66
|
||||
gray67
|
||||
grey67
|
||||
gray68
|
||||
grey68
|
||||
gray69
|
||||
grey69
|
||||
gray70
|
||||
grey70
|
||||
gray71
|
||||
grey71
|
||||
gray72
|
||||
grey72
|
||||
gray73
|
||||
grey73
|
||||
gray74
|
||||
grey74
|
||||
gray75
|
||||
grey75
|
||||
gray76
|
||||
grey76
|
||||
gray77
|
||||
grey77
|
||||
gray78
|
||||
grey78
|
||||
gray79
|
||||
grey79
|
||||
gray80
|
||||
grey80
|
||||
gray81
|
||||
grey81
|
||||
gray82
|
||||
grey82
|
||||
gray83
|
||||
grey83
|
||||
gray84
|
||||
grey84
|
||||
gray85
|
||||
grey85
|
||||
gray86
|
||||
grey86
|
||||
gray87
|
||||
grey87
|
||||
gray88
|
||||
grey88
|
||||
gray89
|
||||
grey89
|
||||
gray90
|
||||
grey90
|
||||
gray91
|
||||
grey91
|
||||
gray92
|
||||
grey92
|
||||
gray93
|
||||
grey93
|
||||
gray94
|
||||
grey94
|
||||
gray95
|
||||
grey95
|
||||
gray96
|
||||
grey96
|
||||
gray97
|
||||
grey97
|
||||
gray98
|
||||
grey98
|
||||
gray99
|
||||
grey99
|
||||
gray100
|
||||
grey100
|
||||
dark-grey
|
||||
darkgrey
|
||||
dark-gray
|
||||
darkgray
|
||||
dark-blue
|
||||
darkblue
|
||||
dark-cyan
|
||||
darkcyan
|
||||
dark-magenta
|
||||
darkmagenta
|
||||
dark-red
|
||||
darkred
|
||||
light-green
|
||||
lightgreen
|
||||
crimson
|
||||
indigo
|
||||
olive
|
||||
rebecca-purple
|
||||
rebeccapurple
|
||||
silver
|
||||
teal
|
||||
479851
.github/actions/spelling/dictionary/dictionary.txt
vendored
479851
.github/actions/spelling/dictionary/dictionary.txt
vendored
File diff suppressed because it is too large
Load Diff
3
.github/actions/spelling/dictionary/math.txt
vendored
3
.github/actions/spelling/dictionary/math.txt
vendored
@@ -1,3 +0,0 @@
|
||||
powf
|
||||
sqrtf
|
||||
isnan
|
||||
76
.github/actions/spelling/excludes.txt
vendored
76
.github/actions/spelling/excludes.txt
vendored
@@ -1,27 +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$
|
||||
@@ -29,39 +41,77 @@ SUMS$
|
||||
\.lock$
|
||||
\.map$
|
||||
\.min\..
|
||||
\.mod$
|
||||
\.mp3$
|
||||
\.mp4$
|
||||
\.o$
|
||||
\.ocf$
|
||||
\.otf$
|
||||
\.pbxproj$
|
||||
\.pdf$
|
||||
\.pem$
|
||||
(?:(?i)\.png$)
|
||||
\.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/
|
||||
^oss/
|
||||
^doc/reference/UTF8-torture-test\.txt$
|
||||
^src/interactivity/onecore/BgfxEngine\.
|
||||
^src/renderer/wddmcon/WddmConRenderer\.
|
||||
^src/terminal/parser/ft_fuzzer/VTCommandFuzzer\.cpp$
|
||||
^src/types/ut_types/UtilsTests.cpp$
|
||||
^src/tools/U8U16Test/(?:fr|ru|zh)\.txt$
|
||||
^\.github/actions/spelling/
|
||||
^\.gitignore$
|
||||
^doc/reference/master-sequence-list.csv$
|
||||
^\XamlStyler.json$
|
||||
^doc/reference/UTF8-torture-test\.txt$
|
||||
^oss/
|
||||
^src/host/ft_uia/run\.bat$
|
||||
^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$
|
||||
^src/tools/pixels/pixels\.bat$
|
||||
^src/tools/texttests/fira\.txt$
|
||||
^src/tools/U8U16Test/(?:fr|ru|zh)\.txt$
|
||||
^src/types/ut_types/UtilsTests.cpp$
|
||||
^tools/ReleaseEngineering/ServicingPipeline.ps1$
|
||||
ignore$
|
||||
SUMS$
|
||||
|
||||
20
.github/actions/spelling/expect/alphabet.txt
vendored
20
.github/actions/spelling/expect/alphabet.txt
vendored
@@ -1,17 +1,23 @@
|
||||
AAAa
|
||||
AAAAA
|
||||
AAAAAAAAAAAAA
|
||||
AAAAAABBBBBBCCC
|
||||
AAAAABBBBBBCCC
|
||||
abcd
|
||||
abcd
|
||||
abcde
|
||||
abcdef
|
||||
ABCDEFG
|
||||
ABCDEFGH
|
||||
ABCDEFGHIJ
|
||||
abcdefghijk
|
||||
ABCDEFGHIJKLMNO
|
||||
abcdefghijklmnop
|
||||
ABCDEFGHIJKLMNOPQRST
|
||||
abcdefghijklmnopqrstuvwxyz
|
||||
ABCG
|
||||
ABE
|
||||
abf
|
||||
BBBBB
|
||||
BBBBBBBB
|
||||
BBBBBCCC
|
||||
BBBBCCCCC
|
||||
BBGGRR
|
||||
BBBBBBBBBBBBBBDDDD
|
||||
EFG
|
||||
EFGh
|
||||
QQQQQQQQQQABCDEFGHIJ
|
||||
@@ -20,7 +26,6 @@ QQQQQQQQQQABCDEFGHIJKLMNOPQRSTQQQQQQQQQQ
|
||||
QQQQQQQQQQABCDEFGHIJPQRSTQQQQQQQQQQ
|
||||
qrstuvwxyz
|
||||
qwerty
|
||||
QWERTYUIOP
|
||||
qwertyuiopasdfg
|
||||
YYYYYYYDDDDDDDDDDD
|
||||
ZAAZZ
|
||||
@@ -32,3 +37,4 @@ ZYXWVUT
|
||||
ZZBBZ
|
||||
ZZZBB
|
||||
ZZZBZ
|
||||
ZZZZZ
|
||||
|
||||
1079
.github/actions/spelling/expect/expect.txt
vendored
1079
.github/actions/spelling/expect/expect.txt
vendored
File diff suppressed because it is too large
Load Diff
15
.github/actions/spelling/expect/web.txt
vendored
15
.github/actions/spelling/expect/web.txt
vendored
@@ -1,19 +1,6 @@
|
||||
http
|
||||
td
|
||||
www
|
||||
ecma
|
||||
rapidtables
|
||||
WCAG
|
||||
freedesktop
|
||||
ycombinator
|
||||
robertelder
|
||||
kovidgoyal
|
||||
leonerd
|
||||
fixterms
|
||||
uk
|
||||
winui
|
||||
appshellintegration
|
||||
cppreference
|
||||
mdtauk
|
||||
gfycat
|
||||
what3words
|
||||
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
|
||||
88
.github/actions/spelling/patterns/patterns.txt
vendored
88
.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
|
||||
@@ -22,3 +17,80 @@ Base64::s_(?:En|De)code\(L"[^"]+"
|
||||
VERIFY_ARE_EQUAL\(L"[^"]+"
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\+/"
|
||||
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
|
||||
|
||||
12
.github/actions/spelling/reject.txt
vendored
Normal file
12
.github/actions/spelling/reject.txt
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
^attache$
|
||||
^attacher$
|
||||
^attachers$
|
||||
benefitting
|
||||
occurences?
|
||||
^dependan.*
|
||||
^oer$
|
||||
Sorce
|
||||
^[Ss]pae.*
|
||||
^untill$
|
||||
^untilling$
|
||||
^wether.*
|
||||
15
.github/workflows/spelling.yml
vendored
15
.github/workflows/spelling.yml
vendored
@@ -1,15 +0,0 @@
|
||||
name: Spell checking
|
||||
on:
|
||||
pull_request_target:
|
||||
push:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Spell checking
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2.0.0
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
fetch-depth: 5
|
||||
- uses: check-spelling/check-spelling@0.0.17-alpha
|
||||
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 }}
|
||||
@@ -106,9 +106,9 @@ namespace SettingsModelLocalTests
|
||||
VERIFY_ARE_EQUAL(1u, commands.Size());
|
||||
auto command = commands.Lookup(L"action0");
|
||||
VERIFY_IS_NOT_NULL(command);
|
||||
VERIFY_IS_NOT_NULL(command.Action());
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::CopyText, command.Action().Action());
|
||||
const auto& realArgs = command.Action().Args().try_as<CopyTextArgs>();
|
||||
VERIFY_IS_NOT_NULL(command.ActionAndArgs());
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::CopyText, command.ActionAndArgs().Action());
|
||||
const auto& realArgs = command.ActionAndArgs().Args().try_as<CopyTextArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
}
|
||||
{
|
||||
@@ -117,9 +117,9 @@ namespace SettingsModelLocalTests
|
||||
VERIFY_ARE_EQUAL(1u, commands.Size());
|
||||
auto command = commands.Lookup(L"action0");
|
||||
VERIFY_IS_NOT_NULL(command);
|
||||
VERIFY_IS_NOT_NULL(command.Action());
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::PasteText, command.Action().Action());
|
||||
VERIFY_IS_NULL(command.Action().Args());
|
||||
VERIFY_IS_NOT_NULL(command.ActionAndArgs());
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::PasteText, command.ActionAndArgs().Action());
|
||||
VERIFY_IS_NULL(command.ActionAndArgs().Args());
|
||||
}
|
||||
{
|
||||
auto warnings = implementation::Command::LayerJson(commands, commands2Json);
|
||||
@@ -127,9 +127,9 @@ namespace SettingsModelLocalTests
|
||||
VERIFY_ARE_EQUAL(1u, commands.Size());
|
||||
auto command = commands.Lookup(L"action0");
|
||||
VERIFY_IS_NOT_NULL(command);
|
||||
VERIFY_IS_NOT_NULL(command.Action());
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::NewTab, command.Action().Action());
|
||||
const auto& realArgs = command.Action().Args().try_as<NewTabArgs>();
|
||||
VERIFY_IS_NOT_NULL(command.ActionAndArgs());
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::NewTab, command.ActionAndArgs().Action());
|
||||
const auto& realArgs = command.ActionAndArgs().Args().try_as<NewTabArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
}
|
||||
{
|
||||
@@ -165,9 +165,9 @@ namespace SettingsModelLocalTests
|
||||
{
|
||||
auto command = commands.Lookup(L"command1");
|
||||
VERIFY_IS_NOT_NULL(command);
|
||||
VERIFY_IS_NOT_NULL(command.Action());
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, command.Action().Action());
|
||||
const auto& realArgs = command.Action().Args().try_as<SplitPaneArgs>();
|
||||
VERIFY_IS_NOT_NULL(command.ActionAndArgs());
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, command.ActionAndArgs().Action());
|
||||
const auto& realArgs = command.ActionAndArgs().Args().try_as<SplitPaneArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
// Verify the args have the expected value
|
||||
VERIFY_ARE_EQUAL(SplitState::Vertical, realArgs.SplitStyle());
|
||||
@@ -176,9 +176,9 @@ namespace SettingsModelLocalTests
|
||||
{
|
||||
auto command = commands.Lookup(L"command2");
|
||||
VERIFY_IS_NOT_NULL(command);
|
||||
VERIFY_IS_NOT_NULL(command.Action());
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, command.Action().Action());
|
||||
const auto& realArgs = command.Action().Args().try_as<SplitPaneArgs>();
|
||||
VERIFY_IS_NOT_NULL(command.ActionAndArgs());
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, command.ActionAndArgs().Action());
|
||||
const auto& realArgs = command.ActionAndArgs().Args().try_as<SplitPaneArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
// Verify the args have the expected value
|
||||
VERIFY_ARE_EQUAL(SplitState::Horizontal, realArgs.SplitStyle());
|
||||
@@ -187,9 +187,9 @@ namespace SettingsModelLocalTests
|
||||
{
|
||||
auto command = commands.Lookup(L"command4");
|
||||
VERIFY_IS_NOT_NULL(command);
|
||||
VERIFY_IS_NOT_NULL(command.Action());
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, command.Action().Action());
|
||||
const auto& realArgs = command.Action().Args().try_as<SplitPaneArgs>();
|
||||
VERIFY_IS_NOT_NULL(command.ActionAndArgs());
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, command.ActionAndArgs().Action());
|
||||
const auto& realArgs = command.ActionAndArgs().Args().try_as<SplitPaneArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
// Verify the args have the expected value
|
||||
VERIFY_ARE_EQUAL(SplitState::Automatic, realArgs.SplitStyle());
|
||||
@@ -198,9 +198,9 @@ namespace SettingsModelLocalTests
|
||||
{
|
||||
auto command = commands.Lookup(L"command5");
|
||||
VERIFY_IS_NOT_NULL(command);
|
||||
VERIFY_IS_NOT_NULL(command.Action());
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, command.Action().Action());
|
||||
const auto& realArgs = command.Action().Args().try_as<SplitPaneArgs>();
|
||||
VERIFY_IS_NOT_NULL(command.ActionAndArgs());
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, command.ActionAndArgs().Action());
|
||||
const auto& realArgs = command.ActionAndArgs().Args().try_as<SplitPaneArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
// Verify the args have the expected value
|
||||
VERIFY_ARE_EQUAL(SplitState::Automatic, realArgs.SplitStyle());
|
||||
@@ -209,9 +209,9 @@ namespace SettingsModelLocalTests
|
||||
{
|
||||
auto command = commands.Lookup(L"command6");
|
||||
VERIFY_IS_NOT_NULL(command);
|
||||
VERIFY_IS_NOT_NULL(command.Action());
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, command.Action().Action());
|
||||
const auto& realArgs = command.Action().Args().try_as<SplitPaneArgs>();
|
||||
VERIFY_IS_NOT_NULL(command.ActionAndArgs());
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, command.ActionAndArgs().Action());
|
||||
const auto& realArgs = command.ActionAndArgs().Args().try_as<SplitPaneArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
// Verify the args have the expected value
|
||||
VERIFY_ARE_EQUAL(SplitState::Automatic, realArgs.SplitStyle());
|
||||
@@ -239,9 +239,9 @@ namespace SettingsModelLocalTests
|
||||
{
|
||||
auto command = commands.Lookup(L"command1");
|
||||
VERIFY_IS_NOT_NULL(command);
|
||||
VERIFY_IS_NOT_NULL(command.Action());
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, command.Action().Action());
|
||||
const auto& realArgs = command.Action().Args().try_as<SplitPaneArgs>();
|
||||
VERIFY_IS_NOT_NULL(command.ActionAndArgs());
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, command.ActionAndArgs().Action());
|
||||
const auto& realArgs = command.ActionAndArgs().Args().try_as<SplitPaneArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
// Verify the args have the expected value
|
||||
VERIFY_ARE_EQUAL(SplitState::Automatic, realArgs.SplitStyle());
|
||||
@@ -268,9 +268,9 @@ namespace SettingsModelLocalTests
|
||||
// this test will break.
|
||||
auto command = commands.Lookup(L"Duplicate tab");
|
||||
VERIFY_IS_NOT_NULL(command);
|
||||
VERIFY_IS_NOT_NULL(command.Action());
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::CopyText, command.Action().Action());
|
||||
const auto& realArgs = command.Action().Args().try_as<CopyTextArgs>();
|
||||
VERIFY_IS_NOT_NULL(command.ActionAndArgs());
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::CopyText, command.ActionAndArgs().Action());
|
||||
const auto& realArgs = command.ActionAndArgs().Args().try_as<CopyTextArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
}
|
||||
}
|
||||
@@ -309,9 +309,9 @@ namespace SettingsModelLocalTests
|
||||
{
|
||||
auto command = commands.Lookup(L"Split pane");
|
||||
VERIFY_IS_NOT_NULL(command);
|
||||
VERIFY_IS_NOT_NULL(command.Action());
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, command.Action().Action());
|
||||
const auto& realArgs = command.Action().Args().try_as<SplitPaneArgs>();
|
||||
VERIFY_IS_NOT_NULL(command.ActionAndArgs());
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, command.ActionAndArgs().Action());
|
||||
const auto& realArgs = command.ActionAndArgs().Args().try_as<SplitPaneArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
// Verify the args have the expected value
|
||||
VERIFY_ARE_EQUAL(SplitState::Automatic, realArgs.SplitStyle());
|
||||
@@ -319,9 +319,9 @@ namespace SettingsModelLocalTests
|
||||
{
|
||||
auto command = commands.Lookup(L"Split pane, split: vertical");
|
||||
VERIFY_IS_NOT_NULL(command);
|
||||
VERIFY_IS_NOT_NULL(command.Action());
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, command.Action().Action());
|
||||
const auto& realArgs = command.Action().Args().try_as<SplitPaneArgs>();
|
||||
VERIFY_IS_NOT_NULL(command.ActionAndArgs());
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, command.ActionAndArgs().Action());
|
||||
const auto& realArgs = command.ActionAndArgs().Args().try_as<SplitPaneArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
// Verify the args have the expected value
|
||||
VERIFY_ARE_EQUAL(SplitState::Vertical, realArgs.SplitStyle());
|
||||
@@ -329,9 +329,9 @@ namespace SettingsModelLocalTests
|
||||
{
|
||||
auto command = commands.Lookup(L"Split pane, split: horizontal");
|
||||
VERIFY_IS_NOT_NULL(command);
|
||||
VERIFY_IS_NOT_NULL(command.Action());
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, command.Action().Action());
|
||||
const auto& realArgs = command.Action().Args().try_as<SplitPaneArgs>();
|
||||
VERIFY_IS_NOT_NULL(command.ActionAndArgs());
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, command.ActionAndArgs().Action());
|
||||
const auto& realArgs = command.ActionAndArgs().Args().try_as<SplitPaneArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
// Verify the args have the expected value
|
||||
VERIFY_ARE_EQUAL(SplitState::Horizontal, realArgs.SplitStyle());
|
||||
@@ -355,9 +355,9 @@ namespace SettingsModelLocalTests
|
||||
{
|
||||
auto command = commands.Lookup(L"Split pane");
|
||||
VERIFY_IS_NOT_NULL(command);
|
||||
VERIFY_IS_NOT_NULL(command.Action());
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, command.Action().Action());
|
||||
const auto& realArgs = command.Action().Args().try_as<SplitPaneArgs>();
|
||||
VERIFY_IS_NOT_NULL(command.ActionAndArgs());
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, command.ActionAndArgs().Action());
|
||||
const auto& realArgs = command.ActionAndArgs().Args().try_as<SplitPaneArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
// Verify the args have the expected value
|
||||
VERIFY_ARE_EQUAL(SplitState::Vertical, realArgs.SplitStyle());
|
||||
@@ -410,9 +410,9 @@ namespace SettingsModelLocalTests
|
||||
{
|
||||
auto command = commands.Lookup(L"action0");
|
||||
VERIFY_IS_NOT_NULL(command);
|
||||
VERIFY_IS_NOT_NULL(command.Action());
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::NewWindow, command.Action().Action());
|
||||
const auto& realArgs = command.Action().Args().try_as<NewWindowArgs>();
|
||||
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);
|
||||
@@ -423,9 +423,9 @@ namespace SettingsModelLocalTests
|
||||
{
|
||||
auto command = commands.Lookup(L"action1");
|
||||
VERIFY_IS_NOT_NULL(command);
|
||||
VERIFY_IS_NOT_NULL(command.Action());
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::NewTab, command.Action().Action());
|
||||
const auto& realArgs = command.Action().Args().try_as<NewTabArgs>();
|
||||
VERIFY_IS_NOT_NULL(command.ActionAndArgs());
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::NewTab, command.ActionAndArgs().Action());
|
||||
const auto& realArgs = command.ActionAndArgs().Args().try_as<NewTabArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
const auto& terminalArgs = realArgs.TerminalArgs();
|
||||
VERIFY_IS_NOT_NULL(terminalArgs);
|
||||
@@ -436,9 +436,9 @@ namespace SettingsModelLocalTests
|
||||
{
|
||||
auto command = commands.Lookup(L"action2");
|
||||
VERIFY_IS_NOT_NULL(command);
|
||||
VERIFY_IS_NOT_NULL(command.Action());
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::NewWindow, command.Action().Action());
|
||||
const auto& realArgs = command.Action().Args().try_as<NewWindowArgs>();
|
||||
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);
|
||||
@@ -449,9 +449,9 @@ namespace SettingsModelLocalTests
|
||||
{
|
||||
auto command = commands.Lookup(L"action3");
|
||||
VERIFY_IS_NOT_NULL(command);
|
||||
VERIFY_IS_NOT_NULL(command.Action());
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::NewWindow, command.Action().Action());
|
||||
const auto& realArgs = command.Action().Args().try_as<NewWindowArgs>();
|
||||
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);
|
||||
@@ -462,9 +462,9 @@ namespace SettingsModelLocalTests
|
||||
{
|
||||
auto command = commands.Lookup(L"action4");
|
||||
VERIFY_IS_NOT_NULL(command);
|
||||
VERIFY_IS_NOT_NULL(command.Action());
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::NewWindow, command.Action().Action());
|
||||
const auto& realArgs = command.Action().Args().try_as<NewWindowArgs>();
|
||||
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);
|
||||
@@ -477,9 +477,9 @@ namespace SettingsModelLocalTests
|
||||
{
|
||||
auto command = commands.Lookup(L"action5");
|
||||
VERIFY_IS_NOT_NULL(command);
|
||||
VERIFY_IS_NOT_NULL(command.Action());
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::NewWindow, command.Action().Action());
|
||||
const auto& realArgs = command.Action().Args().try_as<NewWindowArgs>();
|
||||
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);
|
||||
@@ -492,9 +492,9 @@ namespace SettingsModelLocalTests
|
||||
{
|
||||
auto command = commands.Lookup(L"action6");
|
||||
VERIFY_IS_NOT_NULL(command);
|
||||
VERIFY_IS_NOT_NULL(command.Action());
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::NewWindow, command.Action().Action());
|
||||
const auto& realArgs = command.Action().Args().try_as<NewWindowArgs>();
|
||||
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);
|
||||
|
||||
@@ -1918,7 +1918,12 @@ namespace SettingsModelLocalTests
|
||||
const auto settingsObject = VerifyParseSucceeded(badSettings);
|
||||
auto settings = implementation::CascadiaSettings::FromJson(settingsObject);
|
||||
|
||||
VERIFY_ARE_EQUAL(0u, settings->_globals->_keymap->_keyShortcuts.size());
|
||||
// KeyMap: ctrl+a/b are mapped to "invalid"
|
||||
// ActionMap: "splitPane" and "invalid" are the only deserialized actions
|
||||
// NameMap: "splitPane" has no key binding, but it is still added to the name map
|
||||
VERIFY_ARE_EQUAL(2u, settings->_globals->_actionMap->_KeyMap.size());
|
||||
VERIFY_ARE_EQUAL(2u, settings->_globals->_actionMap->_ActionMap.size());
|
||||
VERIFY_ARE_EQUAL(1u, settings->_globals->_actionMap->NameMap().Size());
|
||||
|
||||
VERIFY_ARE_EQUAL(4u, settings->_globals->_keybindingsWarnings.size());
|
||||
VERIFY_ARE_EQUAL(SettingsLoadWarnings::TooManyKeysForChord, settings->_globals->_keybindingsWarnings.at(0));
|
||||
@@ -1962,7 +1967,10 @@ namespace SettingsModelLocalTests
|
||||
|
||||
auto settings = implementation::CascadiaSettings::FromJson(settingsObject);
|
||||
|
||||
VERIFY_ARE_EQUAL(0u, settings->_globals->_keymap->_keyShortcuts.size());
|
||||
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') }));
|
||||
|
||||
for (const auto& warning : settings->_globals->_keybindingsWarnings)
|
||||
{
|
||||
@@ -2103,18 +2111,18 @@ namespace SettingsModelLocalTests
|
||||
const auto profile2Guid = settings->_allProfiles.GetAt(2).Guid();
|
||||
VERIFY_ARE_NOT_EQUAL(winrt::guid{}, profile2Guid);
|
||||
|
||||
auto keymap = winrt::get_self<implementation::KeyMapping>(settings->_globals->KeyMap());
|
||||
VERIFY_ARE_EQUAL(5u, keymap->_keyShortcuts.size());
|
||||
auto actionMap = winrt::get_self<implementation::ActionMap>(settings->_globals->ActionMap());
|
||||
VERIFY_ARE_EQUAL(5u, actionMap->_KeyMap.size());
|
||||
|
||||
// A/D, B, C, E will be in the list of commands, for 4 total.
|
||||
// * A and D share the same name, so they'll only generate a single action.
|
||||
// * F's name is set manually to `null`
|
||||
auto commands = settings->_globals->Commands();
|
||||
VERIFY_ARE_EQUAL(4u, commands.Size());
|
||||
const auto& nameMap{ actionMap->NameMap() };
|
||||
VERIFY_ARE_EQUAL(1u, nameMap.Size());
|
||||
|
||||
{
|
||||
KeyChord kc{ true, false, false, static_cast<int32_t>('A') };
|
||||
auto actionAndArgs = ::TestUtils::GetActionAndArgs(*keymap, kc);
|
||||
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);
|
||||
@@ -2131,7 +2139,7 @@ namespace SettingsModelLocalTests
|
||||
|
||||
{
|
||||
KeyChord kc{ true, false, false, static_cast<int32_t>('C') };
|
||||
auto actionAndArgs = ::TestUtils::GetActionAndArgs(*keymap, kc);
|
||||
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);
|
||||
@@ -2145,7 +2153,7 @@ namespace SettingsModelLocalTests
|
||||
}
|
||||
{
|
||||
KeyChord kc{ true, false, false, static_cast<int32_t>('D') };
|
||||
auto actionAndArgs = ::TestUtils::GetActionAndArgs(*keymap, kc);
|
||||
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);
|
||||
@@ -2159,7 +2167,7 @@ namespace SettingsModelLocalTests
|
||||
}
|
||||
{
|
||||
KeyChord kc{ true, false, false, static_cast<int32_t>('E') };
|
||||
auto actionAndArgs = ::TestUtils::GetActionAndArgs(*keymap, kc);
|
||||
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);
|
||||
@@ -2173,7 +2181,7 @@ namespace SettingsModelLocalTests
|
||||
}
|
||||
{
|
||||
KeyChord kc{ true, false, false, static_cast<int32_t>('F') };
|
||||
auto actionAndArgs = ::TestUtils::GetActionAndArgs(*keymap, kc);
|
||||
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);
|
||||
@@ -2187,11 +2195,21 @@ namespace SettingsModelLocalTests
|
||||
}
|
||||
|
||||
Log::Comment(L"Now verify the commands");
|
||||
_logCommandNames(commands);
|
||||
_logCommandNames(nameMap);
|
||||
{
|
||||
auto command = commands.Lookup(L"Split pane, split: vertical");
|
||||
// This was renamed to "ctrl+c" in C. So this does not exist.
|
||||
auto command = nameMap.TryLookup(L"Split pane, split: vertical");
|
||||
VERIFY_IS_NULL(command);
|
||||
}
|
||||
{
|
||||
// This was renamed to "ctrl+c" in C. So this does not exist.
|
||||
auto command = nameMap.TryLookup(L"ctrl+b");
|
||||
VERIFY_IS_NULL(command);
|
||||
}
|
||||
{
|
||||
auto command = nameMap.TryLookup(L"ctrl+c");
|
||||
VERIFY_IS_NOT_NULL(command);
|
||||
auto actionAndArgs = command.Action();
|
||||
auto actionAndArgs = command.ActionAndArgs();
|
||||
VERIFY_IS_NOT_NULL(actionAndArgs);
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, actionAndArgs.Action());
|
||||
const auto& realArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
|
||||
@@ -2205,52 +2223,9 @@ namespace SettingsModelLocalTests
|
||||
VERIFY_IS_TRUE(realArgs.TerminalArgs().Profile().empty());
|
||||
}
|
||||
{
|
||||
auto command = commands.Lookup(L"ctrl+b");
|
||||
VERIFY_IS_NOT_NULL(command);
|
||||
auto actionAndArgs = command.Action();
|
||||
VERIFY_IS_NOT_NULL(actionAndArgs);
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, actionAndArgs.Action());
|
||||
const auto& realArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
// Verify the args have the expected value
|
||||
VERIFY_ARE_EQUAL(SplitState::Vertical, realArgs.SplitStyle());
|
||||
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
|
||||
VERIFY_IS_TRUE(realArgs.TerminalArgs().Commandline().empty());
|
||||
VERIFY_IS_TRUE(realArgs.TerminalArgs().StartingDirectory().empty());
|
||||
VERIFY_IS_TRUE(realArgs.TerminalArgs().TabTitle().empty());
|
||||
VERIFY_IS_TRUE(realArgs.TerminalArgs().Profile().empty());
|
||||
}
|
||||
{
|
||||
auto command = commands.Lookup(L"ctrl+c");
|
||||
VERIFY_IS_NOT_NULL(command);
|
||||
auto actionAndArgs = command.Action();
|
||||
VERIFY_IS_NOT_NULL(actionAndArgs);
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, actionAndArgs.Action());
|
||||
const auto& realArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
// Verify the args have the expected value
|
||||
VERIFY_ARE_EQUAL(SplitState::Vertical, realArgs.SplitStyle());
|
||||
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
|
||||
VERIFY_IS_TRUE(realArgs.TerminalArgs().Commandline().empty());
|
||||
VERIFY_IS_TRUE(realArgs.TerminalArgs().StartingDirectory().empty());
|
||||
VERIFY_IS_TRUE(realArgs.TerminalArgs().TabTitle().empty());
|
||||
VERIFY_IS_TRUE(realArgs.TerminalArgs().Profile().empty());
|
||||
}
|
||||
{
|
||||
auto command = commands.Lookup(L"Split pane, split: horizontal");
|
||||
VERIFY_IS_NOT_NULL(command);
|
||||
auto actionAndArgs = command.Action();
|
||||
VERIFY_IS_NOT_NULL(actionAndArgs);
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, actionAndArgs.Action());
|
||||
const auto& realArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
// Verify the args have the expected value
|
||||
VERIFY_ARE_EQUAL(SplitState::Horizontal, realArgs.SplitStyle());
|
||||
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
|
||||
VERIFY_IS_TRUE(realArgs.TerminalArgs().Commandline().empty());
|
||||
VERIFY_IS_TRUE(realArgs.TerminalArgs().StartingDirectory().empty());
|
||||
VERIFY_IS_TRUE(realArgs.TerminalArgs().TabTitle().empty());
|
||||
VERIFY_IS_TRUE(realArgs.TerminalArgs().Profile().empty());
|
||||
// This was renamed to null (aka removed from the name map) in F. So this does not exist.
|
||||
auto command = nameMap.TryLookup(L"Split pane, split: horizontal");
|
||||
VERIFY_IS_NULL(command);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2308,16 +2283,16 @@ namespace SettingsModelLocalTests
|
||||
VERIFY_ARE_EQUAL(0u, settings->_warnings.Size());
|
||||
VERIFY_ARE_EQUAL(3u, settings->_allProfiles.Size());
|
||||
|
||||
auto commands = settings->_globals->Commands();
|
||||
settings->_ValidateSettings();
|
||||
_logCommandNames(commands);
|
||||
const auto& nameMap{ settings->ActionMap().NameMap() };
|
||||
_logCommandNames(nameMap);
|
||||
|
||||
VERIFY_ARE_EQUAL(0u, settings->_warnings.Size());
|
||||
|
||||
// Because the "parent" command didn't have a name, it couldn't be
|
||||
// placed into the list of commands. It and it's children are just
|
||||
// ignored.
|
||||
VERIFY_ARE_EQUAL(0u, commands.Size());
|
||||
VERIFY_ARE_EQUAL(0u, nameMap.Size());
|
||||
}
|
||||
|
||||
void DeserializationTests::TestNestedCommandWithBadSubCommands()
|
||||
@@ -2358,13 +2333,13 @@ namespace SettingsModelLocalTests
|
||||
auto settings = winrt::make_self<implementation::CascadiaSettings>();
|
||||
settings->_ParseJsonString(settingsJson, false);
|
||||
settings->LayerJson(settings->_userSettings);
|
||||
auto commands = settings->_globals->Commands();
|
||||
settings->_ValidateSettings();
|
||||
|
||||
VERIFY_ARE_EQUAL(2u, settings->_warnings.Size());
|
||||
VERIFY_ARE_EQUAL(SettingsLoadWarnings::AtLeastOneKeybindingWarning, settings->_warnings.GetAt(0));
|
||||
VERIFY_ARE_EQUAL(SettingsLoadWarnings::FailedToParseSubCommands, settings->_warnings.GetAt(1));
|
||||
VERIFY_ARE_EQUAL(0u, commands.Size());
|
||||
const auto& nameMap{ settings->ActionMap().NameMap() };
|
||||
VERIFY_ARE_EQUAL(0u, nameMap.Size());
|
||||
}
|
||||
|
||||
void DeserializationTests::TestUnbindNestedCommand()
|
||||
@@ -2432,22 +2407,23 @@ namespace SettingsModelLocalTests
|
||||
VERIFY_ARE_EQUAL(0u, settings->_warnings.Size());
|
||||
VERIFY_ARE_EQUAL(3u, settings->_allProfiles.Size());
|
||||
|
||||
auto commands = settings->_globals->Commands();
|
||||
settings->_ValidateSettings();
|
||||
_logCommandNames(commands);
|
||||
auto nameMap{ settings->ActionMap().NameMap() };
|
||||
_logCommandNames(nameMap);
|
||||
|
||||
VERIFY_ARE_EQUAL(0u, settings->_warnings.Size());
|
||||
VERIFY_ARE_EQUAL(1u, commands.Size());
|
||||
VERIFY_ARE_EQUAL(1u, nameMap.Size());
|
||||
|
||||
Log::Comment(L"Layer second bit of json, to unbind the original command.");
|
||||
|
||||
settings->_ParseJsonString(settings1Json, false);
|
||||
settings->LayerJson(settings->_userSettings);
|
||||
settings->_ValidateSettings();
|
||||
commands = settings->_globals->Commands();
|
||||
_logCommandNames(commands);
|
||||
|
||||
nameMap = settings->ActionMap().NameMap();
|
||||
_logCommandNames(nameMap);
|
||||
VERIFY_ARE_EQUAL(0u, settings->_warnings.Size());
|
||||
VERIFY_ARE_EQUAL(0u, commands.Size());
|
||||
VERIFY_ARE_EQUAL(0u, nameMap.Size());
|
||||
}
|
||||
|
||||
void DeserializationTests::TestRebindNestedCommand()
|
||||
@@ -2516,16 +2492,17 @@ namespace SettingsModelLocalTests
|
||||
VERIFY_ARE_EQUAL(0u, settings->_warnings.Size());
|
||||
VERIFY_ARE_EQUAL(3u, settings->_allProfiles.Size());
|
||||
|
||||
auto commands = settings->_globals->Commands();
|
||||
const auto& actionMap{ settings->ActionMap() };
|
||||
settings->_ValidateSettings();
|
||||
_logCommandNames(commands);
|
||||
auto nameMap{ actionMap.NameMap() };
|
||||
_logCommandNames(nameMap);
|
||||
|
||||
VERIFY_ARE_EQUAL(0u, settings->_warnings.Size());
|
||||
VERIFY_ARE_EQUAL(1u, commands.Size());
|
||||
VERIFY_ARE_EQUAL(1u, nameMap.Size());
|
||||
|
||||
{
|
||||
winrt::hstring commandName{ L"parent" };
|
||||
auto commandProj = commands.Lookup(commandName);
|
||||
auto commandProj = nameMap.TryLookup(commandName);
|
||||
VERIFY_IS_NOT_NULL(commandProj);
|
||||
|
||||
winrt::com_ptr<implementation::Command> commandImpl;
|
||||
@@ -2539,17 +2516,18 @@ namespace SettingsModelLocalTests
|
||||
settings->_ParseJsonString(settings1Json, false);
|
||||
settings->LayerJson(settings->_userSettings);
|
||||
settings->_ValidateSettings();
|
||||
commands = settings->_globals->Commands();
|
||||
_logCommandNames(commands);
|
||||
|
||||
nameMap = settings->ActionMap().NameMap();
|
||||
_logCommandNames(nameMap);
|
||||
VERIFY_ARE_EQUAL(0u, settings->_warnings.Size());
|
||||
VERIFY_ARE_EQUAL(1u, commands.Size());
|
||||
VERIFY_ARE_EQUAL(1u, nameMap.Size());
|
||||
|
||||
{
|
||||
winrt::hstring commandName{ L"parent" };
|
||||
auto commandProj = commands.Lookup(commandName);
|
||||
auto commandProj = nameMap.TryLookup(commandName);
|
||||
|
||||
VERIFY_IS_NOT_NULL(commandProj);
|
||||
auto actionAndArgs = commandProj.Action();
|
||||
auto actionAndArgs = commandProj.ActionAndArgs();
|
||||
VERIFY_IS_NOT_NULL(actionAndArgs);
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::NewTab, actionAndArgs.Action());
|
||||
const auto& realArgs = actionAndArgs.Args().try_as<NewTabArgs>();
|
||||
@@ -2642,8 +2620,10 @@ namespace SettingsModelLocalTests
|
||||
VERIFY_ARE_EQUAL(settings->_globals->_colorSchemes.HasKey(schemeName), copyImpl->_globals->_colorSchemes.HasKey(schemeName));
|
||||
|
||||
// test actions
|
||||
VERIFY_ARE_EQUAL(settings->_globals->_keymap->_keyShortcuts.size(), copyImpl->_globals->_keymap->_keyShortcuts.size());
|
||||
VERIFY_ARE_EQUAL(settings->_globals->_commands.Size(), copyImpl->_globals->_commands.Size());
|
||||
VERIFY_ARE_EQUAL(settings->_globals->_actionMap->_KeyMap.size(), copyImpl->_globals->_actionMap->_KeyMap.size());
|
||||
const auto& nameMapOriginal{ settings->_globals->_actionMap->NameMap() };
|
||||
const auto& nameMapCopy{ copyImpl->_globals->_actionMap->NameMap() };
|
||||
VERIFY_ARE_EQUAL(nameMapOriginal.Size(), nameMapCopy.Size());
|
||||
|
||||
// Test that changing the copy should not change the original
|
||||
VERIFY_ARE_EQUAL(settings->_globals->WordDelimiters(), copyImpl->_globals->WordDelimiters());
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
#include "../TerminalSettingsModel/ColorScheme.h"
|
||||
#include "../TerminalSettingsModel/CascadiaSettings.h"
|
||||
#include "../TerminalSettingsModel/KeyMapping.h"
|
||||
#include "../TerminalSettingsModel/ActionMap.h"
|
||||
#include "JsonTestClass.h"
|
||||
#include "TestUtils.h"
|
||||
|
||||
@@ -51,6 +51,8 @@ namespace SettingsModelLocalTests
|
||||
TEST_METHOD(TestToggleCommandPaletteArgs);
|
||||
TEST_METHOD(TestMoveTabArgs);
|
||||
|
||||
TEST_METHOD(TestGetKeyBindingForAction);
|
||||
|
||||
TEST_CLASS_SETUP(ClassSetup)
|
||||
{
|
||||
InitializeJsonReader();
|
||||
@@ -71,18 +73,18 @@ namespace SettingsModelLocalTests
|
||||
const auto bindings1Json = VerifyParseSucceeded(bindings1String);
|
||||
const auto bindings2Json = VerifyParseSucceeded(bindings2String);
|
||||
|
||||
auto keymap = winrt::make_self<implementation::KeyMapping>();
|
||||
VERIFY_IS_NOT_NULL(keymap);
|
||||
VERIFY_ARE_EQUAL(0u, keymap->_keyShortcuts.size());
|
||||
auto actionMap = winrt::make_self<implementation::ActionMap>();
|
||||
VERIFY_IS_NOT_NULL(actionMap);
|
||||
VERIFY_ARE_EQUAL(0u, actionMap->_KeyMap.size());
|
||||
|
||||
keymap->LayerJson(bindings0Json);
|
||||
VERIFY_ARE_EQUAL(1u, keymap->_keyShortcuts.size());
|
||||
actionMap->LayerJson(bindings0Json);
|
||||
VERIFY_ARE_EQUAL(1u, actionMap->_KeyMap.size());
|
||||
|
||||
keymap->LayerJson(bindings1Json);
|
||||
VERIFY_ARE_EQUAL(2u, keymap->_keyShortcuts.size());
|
||||
actionMap->LayerJson(bindings1Json);
|
||||
VERIFY_ARE_EQUAL(2u, actionMap->_KeyMap.size());
|
||||
|
||||
keymap->LayerJson(bindings2Json);
|
||||
VERIFY_ARE_EQUAL(4u, keymap->_keyShortcuts.size());
|
||||
actionMap->LayerJson(bindings2Json);
|
||||
VERIFY_ARE_EQUAL(4u, actionMap->_KeyMap.size());
|
||||
}
|
||||
|
||||
void KeyBindingsTests::LayerKeybindings()
|
||||
@@ -95,18 +97,18 @@ namespace SettingsModelLocalTests
|
||||
const auto bindings1Json = VerifyParseSucceeded(bindings1String);
|
||||
const auto bindings2Json = VerifyParseSucceeded(bindings2String);
|
||||
|
||||
auto keymap = winrt::make_self<implementation::KeyMapping>();
|
||||
VERIFY_IS_NOT_NULL(keymap);
|
||||
VERIFY_ARE_EQUAL(0u, keymap->_keyShortcuts.size());
|
||||
auto actionMap = winrt::make_self<implementation::ActionMap>();
|
||||
VERIFY_IS_NOT_NULL(actionMap);
|
||||
VERIFY_ARE_EQUAL(0u, actionMap->_KeyMap.size());
|
||||
|
||||
keymap->LayerJson(bindings0Json);
|
||||
VERIFY_ARE_EQUAL(1u, keymap->_keyShortcuts.size());
|
||||
actionMap->LayerJson(bindings0Json);
|
||||
VERIFY_ARE_EQUAL(1u, actionMap->_KeyMap.size());
|
||||
|
||||
keymap->LayerJson(bindings1Json);
|
||||
VERIFY_ARE_EQUAL(1u, keymap->_keyShortcuts.size());
|
||||
actionMap->LayerJson(bindings1Json);
|
||||
VERIFY_ARE_EQUAL(1u, actionMap->_KeyMap.size());
|
||||
|
||||
keymap->LayerJson(bindings2Json);
|
||||
VERIFY_ARE_EQUAL(2u, keymap->_keyShortcuts.size());
|
||||
actionMap->LayerJson(bindings2Json);
|
||||
VERIFY_ARE_EQUAL(2u, actionMap->_KeyMap.size());
|
||||
}
|
||||
|
||||
void KeyBindingsTests::UnbindKeybindings()
|
||||
@@ -125,52 +127,57 @@ namespace SettingsModelLocalTests
|
||||
const auto bindings4Json = VerifyParseSucceeded(bindings4String);
|
||||
const auto bindings5Json = VerifyParseSucceeded(bindings5String);
|
||||
|
||||
auto keymap = winrt::make_self<implementation::KeyMapping>();
|
||||
VERIFY_IS_NOT_NULL(keymap);
|
||||
VERIFY_ARE_EQUAL(0u, keymap->_keyShortcuts.size());
|
||||
auto actionMap = winrt::make_self<implementation::ActionMap>();
|
||||
VERIFY_IS_NOT_NULL(actionMap);
|
||||
VERIFY_ARE_EQUAL(0u, actionMap->_KeyMap.size());
|
||||
|
||||
keymap->LayerJson(bindings0Json);
|
||||
VERIFY_ARE_EQUAL(1u, keymap->_keyShortcuts.size());
|
||||
actionMap->LayerJson(bindings0Json);
|
||||
VERIFY_ARE_EQUAL(1u, actionMap->_KeyMap.size());
|
||||
|
||||
keymap->LayerJson(bindings1Json);
|
||||
VERIFY_ARE_EQUAL(1u, keymap->_keyShortcuts.size());
|
||||
actionMap->LayerJson(bindings1Json);
|
||||
VERIFY_ARE_EQUAL(1u, actionMap->_KeyMap.size());
|
||||
|
||||
Log::Comment(NoThrowString().Format(
|
||||
L"Try unbinding a key using `\"unbound\"` to unbind the key"));
|
||||
keymap->LayerJson(bindings2Json);
|
||||
VERIFY_ARE_EQUAL(0u, keymap->_keyShortcuts.size());
|
||||
actionMap->LayerJson(bindings2Json);
|
||||
VERIFY_ARE_EQUAL(1u, actionMap->_KeyMap.size());
|
||||
VERIFY_IS_NULL(actionMap->GetActionByKeyChord({ KeyModifiers::Ctrl, static_cast<int32_t>('c') }));
|
||||
|
||||
Log::Comment(NoThrowString().Format(
|
||||
L"Try unbinding a key using `null` to unbind the key"));
|
||||
// First add back a good binding
|
||||
keymap->LayerJson(bindings0Json);
|
||||
VERIFY_ARE_EQUAL(1u, keymap->_keyShortcuts.size());
|
||||
actionMap->LayerJson(bindings0Json);
|
||||
VERIFY_ARE_EQUAL(1u, actionMap->_KeyMap.size());
|
||||
// Then try layering in the bad setting
|
||||
keymap->LayerJson(bindings3Json);
|
||||
VERIFY_ARE_EQUAL(0u, keymap->_keyShortcuts.size());
|
||||
actionMap->LayerJson(bindings3Json);
|
||||
VERIFY_ARE_EQUAL(1u, actionMap->_KeyMap.size());
|
||||
VERIFY_IS_NULL(actionMap->GetActionByKeyChord({ KeyModifiers::Ctrl, static_cast<int32_t>('c') }));
|
||||
|
||||
Log::Comment(NoThrowString().Format(
|
||||
L"Try unbinding a key using an unrecognized command to unbind the key"));
|
||||
// First add back a good binding
|
||||
keymap->LayerJson(bindings0Json);
|
||||
VERIFY_ARE_EQUAL(1u, keymap->_keyShortcuts.size());
|
||||
actionMap->LayerJson(bindings0Json);
|
||||
VERIFY_ARE_EQUAL(1u, actionMap->_KeyMap.size());
|
||||
// Then try layering in the bad setting
|
||||
keymap->LayerJson(bindings4Json);
|
||||
VERIFY_ARE_EQUAL(0u, keymap->_keyShortcuts.size());
|
||||
actionMap->LayerJson(bindings4Json);
|
||||
VERIFY_ARE_EQUAL(1u, actionMap->_KeyMap.size());
|
||||
VERIFY_IS_NULL(actionMap->GetActionByKeyChord({ KeyModifiers::Ctrl, static_cast<int32_t>('c') }));
|
||||
|
||||
Log::Comment(NoThrowString().Format(
|
||||
L"Try unbinding a key using a straight up invalid value to unbind the key"));
|
||||
// First add back a good binding
|
||||
keymap->LayerJson(bindings0Json);
|
||||
VERIFY_ARE_EQUAL(1u, keymap->_keyShortcuts.size());
|
||||
actionMap->LayerJson(bindings0Json);
|
||||
VERIFY_ARE_EQUAL(1u, actionMap->_KeyMap.size());
|
||||
// Then try layering in the bad setting
|
||||
keymap->LayerJson(bindings5Json);
|
||||
VERIFY_ARE_EQUAL(0u, keymap->_keyShortcuts.size());
|
||||
actionMap->LayerJson(bindings5Json);
|
||||
VERIFY_ARE_EQUAL(1u, actionMap->_KeyMap.size());
|
||||
VERIFY_IS_NULL(actionMap->GetActionByKeyChord({ KeyModifiers::Ctrl, static_cast<int32_t>('c') }));
|
||||
|
||||
Log::Comment(NoThrowString().Format(
|
||||
L"Try unbinding a key that wasn't bound at all"));
|
||||
keymap->LayerJson(bindings2Json);
|
||||
VERIFY_ARE_EQUAL(0u, keymap->_keyShortcuts.size());
|
||||
actionMap->LayerJson(bindings2Json);
|
||||
VERIFY_ARE_EQUAL(1u, actionMap->_KeyMap.size());
|
||||
VERIFY_IS_NULL(actionMap->GetActionByKeyChord({ KeyModifiers::Ctrl, static_cast<int32_t>('c') }));
|
||||
}
|
||||
|
||||
void KeyBindingsTests::TestArbitraryArgs()
|
||||
@@ -194,17 +201,17 @@ namespace SettingsModelLocalTests
|
||||
|
||||
const auto bindings0Json = VerifyParseSucceeded(bindings0String);
|
||||
|
||||
auto keymap = winrt::make_self<implementation::KeyMapping>();
|
||||
VERIFY_IS_NOT_NULL(keymap);
|
||||
VERIFY_ARE_EQUAL(0u, keymap->_keyShortcuts.size());
|
||||
keymap->LayerJson(bindings0Json);
|
||||
VERIFY_ARE_EQUAL(10u, keymap->_keyShortcuts.size());
|
||||
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());
|
||||
|
||||
{
|
||||
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') };
|
||||
auto actionAndArgs = ::TestUtils::GetActionAndArgs(*keymap, kc);
|
||||
auto actionAndArgs = ::TestUtils::GetActionAndArgs(*actionMap, kc);
|
||||
const auto& realArgs = actionAndArgs.Args().try_as<CopyTextArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
// Verify the args have the expected value
|
||||
@@ -215,7 +222,7 @@ 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') };
|
||||
auto actionAndArgs = ::TestUtils::GetActionAndArgs(*keymap, kc);
|
||||
auto actionAndArgs = ::TestUtils::GetActionAndArgs(*actionMap, kc);
|
||||
const auto& realArgs = actionAndArgs.Args().try_as<CopyTextArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
// Verify the args have the expected value
|
||||
@@ -226,7 +233,7 @@ 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') };
|
||||
auto actionAndArgs = ::TestUtils::GetActionAndArgs(*keymap, kc);
|
||||
auto actionAndArgs = ::TestUtils::GetActionAndArgs(*actionMap, kc);
|
||||
const auto& realArgs = actionAndArgs.Args().try_as<CopyTextArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
// Verify the args have the expected value
|
||||
@@ -237,7 +244,7 @@ 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') };
|
||||
auto actionAndArgs = ::TestUtils::GetActionAndArgs(*keymap, kc);
|
||||
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);
|
||||
@@ -249,7 +256,7 @@ namespace SettingsModelLocalTests
|
||||
Log::Comment(NoThrowString().Format(
|
||||
L"Verify that `newTab` parses args correctly"));
|
||||
KeyChord kc{ true, false, true, static_cast<int32_t>('T') };
|
||||
auto actionAndArgs = ::TestUtils::GetActionAndArgs(*keymap, kc);
|
||||
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);
|
||||
@@ -263,7 +270,7 @@ namespace SettingsModelLocalTests
|
||||
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') };
|
||||
auto actionAndArgs = ::TestUtils::GetActionAndArgs(*keymap, kc);
|
||||
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);
|
||||
@@ -277,7 +284,7 @@ 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') };
|
||||
auto actionAndArgs = ::TestUtils::GetActionAndArgs(*keymap, kc);
|
||||
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);
|
||||
@@ -289,7 +296,7 @@ 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') };
|
||||
auto actionAndArgs = ::TestUtils::GetActionAndArgs(*keymap, kc);
|
||||
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);
|
||||
@@ -301,7 +308,7 @@ 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') };
|
||||
auto actionAndArgs = ::TestUtils::GetActionAndArgs(*keymap, kc);
|
||||
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);
|
||||
@@ -313,7 +320,7 @@ 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') };
|
||||
auto actionAndArgs = ::TestUtils::GetActionAndArgs(*keymap, kc);
|
||||
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);
|
||||
@@ -333,15 +340,15 @@ namespace SettingsModelLocalTests
|
||||
|
||||
const auto bindings0Json = VerifyParseSucceeded(bindings0String);
|
||||
|
||||
auto keymap = winrt::make_self<implementation::KeyMapping>();
|
||||
VERIFY_IS_NOT_NULL(keymap);
|
||||
VERIFY_ARE_EQUAL(0u, keymap->_keyShortcuts.size());
|
||||
keymap->LayerJson(bindings0Json);
|
||||
VERIFY_ARE_EQUAL(4u, keymap->_keyShortcuts.size());
|
||||
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') };
|
||||
auto actionAndArgs = ::TestUtils::GetActionAndArgs(*keymap, kc);
|
||||
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);
|
||||
@@ -350,7 +357,7 @@ namespace SettingsModelLocalTests
|
||||
}
|
||||
{
|
||||
KeyChord kc{ true, false, false, static_cast<int32_t>('E') };
|
||||
auto actionAndArgs = ::TestUtils::GetActionAndArgs(*keymap, kc);
|
||||
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);
|
||||
@@ -359,7 +366,7 @@ namespace SettingsModelLocalTests
|
||||
}
|
||||
{
|
||||
KeyChord kc{ true, false, false, static_cast<int32_t>('G') };
|
||||
auto actionAndArgs = ::TestUtils::GetActionAndArgs(*keymap, kc);
|
||||
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);
|
||||
@@ -368,7 +375,7 @@ namespace SettingsModelLocalTests
|
||||
}
|
||||
{
|
||||
KeyChord kc{ true, false, false, static_cast<int32_t>('H') };
|
||||
auto actionAndArgs = ::TestUtils::GetActionAndArgs(*keymap, kc);
|
||||
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);
|
||||
@@ -387,15 +394,15 @@ namespace SettingsModelLocalTests
|
||||
|
||||
const auto bindings0Json = VerifyParseSucceeded(bindings0String);
|
||||
|
||||
auto keymap = winrt::make_self<implementation::KeyMapping>();
|
||||
VERIFY_IS_NOT_NULL(keymap);
|
||||
VERIFY_ARE_EQUAL(0u, keymap->_keyShortcuts.size());
|
||||
keymap->LayerJson(bindings0Json);
|
||||
VERIFY_ARE_EQUAL(3u, keymap->_keyShortcuts.size());
|
||||
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') };
|
||||
auto actionAndArgs = ::TestUtils::GetActionAndArgs(*keymap, kc);
|
||||
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);
|
||||
@@ -404,7 +411,7 @@ namespace SettingsModelLocalTests
|
||||
}
|
||||
{
|
||||
KeyChord kc{ true, false, false, static_cast<int32_t>('D') };
|
||||
auto actionAndArgs = ::TestUtils::GetActionAndArgs(*keymap, kc);
|
||||
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);
|
||||
@@ -415,7 +422,7 @@ namespace SettingsModelLocalTests
|
||||
}
|
||||
{
|
||||
KeyChord kc{ true, false, false, static_cast<int32_t>('F') };
|
||||
auto actionAndArgs = ::TestUtils::GetActionAndArgs(*keymap, kc);
|
||||
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);
|
||||
@@ -432,15 +439,15 @@ namespace SettingsModelLocalTests
|
||||
|
||||
const auto bindings0Json = VerifyParseSucceeded(bindings0String);
|
||||
|
||||
auto keymap = winrt::make_self<implementation::KeyMapping>();
|
||||
VERIFY_IS_NOT_NULL(keymap);
|
||||
VERIFY_ARE_EQUAL(0u, keymap->_keyShortcuts.size());
|
||||
keymap->LayerJson(bindings0Json);
|
||||
VERIFY_ARE_EQUAL(1u, keymap->_keyShortcuts.size());
|
||||
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') };
|
||||
auto actionAndArgs = ::TestUtils::GetActionAndArgs(*keymap, kc);
|
||||
auto actionAndArgs = ::TestUtils::GetActionAndArgs(*actionMap, kc);
|
||||
const auto& realArgs = actionAndArgs.Args().try_as<CopyTextArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
// Verify the args have the expected value
|
||||
@@ -461,15 +468,15 @@ namespace SettingsModelLocalTests
|
||||
|
||||
const auto bindings0Json = VerifyParseSucceeded(bindings0String);
|
||||
|
||||
auto keymap = winrt::make_self<implementation::KeyMapping>();
|
||||
VERIFY_IS_NOT_NULL(keymap);
|
||||
VERIFY_ARE_EQUAL(0u, keymap->_keyShortcuts.size());
|
||||
keymap->LayerJson(bindings0Json);
|
||||
VERIFY_ARE_EQUAL(6u, keymap->_keyShortcuts.size());
|
||||
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) };
|
||||
auto actionAndArgs = ::TestUtils::GetActionAndArgs(*keymap, kc);
|
||||
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);
|
||||
@@ -478,7 +485,7 @@ namespace SettingsModelLocalTests
|
||||
}
|
||||
{
|
||||
KeyChord kc{ false, false, false, static_cast<int32_t>(VK_DOWN) };
|
||||
auto actionAndArgs = ::TestUtils::GetActionAndArgs(*keymap, kc);
|
||||
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);
|
||||
@@ -487,7 +494,7 @@ namespace SettingsModelLocalTests
|
||||
}
|
||||
{
|
||||
KeyChord kc{ true, false, false, static_cast<int32_t>(VK_UP) };
|
||||
auto actionAndArgs = ::TestUtils::GetActionAndArgs(*keymap, kc);
|
||||
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);
|
||||
@@ -496,7 +503,7 @@ namespace SettingsModelLocalTests
|
||||
}
|
||||
{
|
||||
KeyChord kc{ true, false, false, static_cast<int32_t>(VK_DOWN) };
|
||||
auto actionAndArgs = ::TestUtils::GetActionAndArgs(*keymap, kc);
|
||||
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);
|
||||
@@ -505,7 +512,7 @@ namespace SettingsModelLocalTests
|
||||
}
|
||||
{
|
||||
KeyChord kc{ true, false, true, static_cast<int32_t>(VK_UP) };
|
||||
auto actionAndArgs = ::TestUtils::GetActionAndArgs(*keymap, kc);
|
||||
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);
|
||||
@@ -515,7 +522,7 @@ namespace SettingsModelLocalTests
|
||||
}
|
||||
{
|
||||
KeyChord kc{ true, false, true, static_cast<int32_t>(VK_DOWN) };
|
||||
auto actionAndArgs = ::TestUtils::GetActionAndArgs(*keymap, kc);
|
||||
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);
|
||||
@@ -526,10 +533,10 @@ namespace SettingsModelLocalTests
|
||||
{
|
||||
const std::string bindingsInvalidString{ R"([{ "keys": ["up"], "command": { "action": "scrollDown", "rowsToScroll": -1 } }])" };
|
||||
const auto bindingsInvalidJson = VerifyParseSucceeded(bindingsInvalidString);
|
||||
auto invalidKeyMap = winrt::make_self<implementation::KeyMapping>();
|
||||
VERIFY_IS_NOT_NULL(invalidKeyMap);
|
||||
VERIFY_ARE_EQUAL(0u, invalidKeyMap->_keyShortcuts.size());
|
||||
VERIFY_THROWS(invalidKeyMap->LayerJson(bindingsInvalidJson);, std::exception);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -542,15 +549,15 @@ namespace SettingsModelLocalTests
|
||||
|
||||
const auto bindings0Json = VerifyParseSucceeded(bindings0String);
|
||||
|
||||
auto keymap = winrt::make_self<implementation::KeyMapping>();
|
||||
VERIFY_IS_NOT_NULL(keymap);
|
||||
VERIFY_ARE_EQUAL(0u, keymap->_keyShortcuts.size());
|
||||
keymap->LayerJson(bindings0Json);
|
||||
VERIFY_ARE_EQUAL(2u, keymap->_keyShortcuts.size());
|
||||
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) };
|
||||
auto actionAndArgs = ::TestUtils::GetActionAndArgs(*keymap, kc);
|
||||
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);
|
||||
@@ -559,7 +566,7 @@ namespace SettingsModelLocalTests
|
||||
}
|
||||
{
|
||||
KeyChord kc{ false, false, false, static_cast<int32_t>(VK_DOWN) };
|
||||
auto actionAndArgs = ::TestUtils::GetActionAndArgs(*keymap, kc);
|
||||
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);
|
||||
@@ -568,17 +575,17 @@ namespace SettingsModelLocalTests
|
||||
}
|
||||
{
|
||||
const std::string bindingsInvalidString{ R"([{ "keys": ["up"], "command": "moveTab" }])" };
|
||||
auto keyMapNoArgs = winrt::make_self<implementation::KeyMapping>();
|
||||
keyMapNoArgs->LayerJson(bindingsInvalidString);
|
||||
VERIFY_ARE_EQUAL(0u, keyMapNoArgs->_keyShortcuts.size());
|
||||
auto actionMapNoArgs = winrt::make_self<implementation::ActionMap>();
|
||||
actionMapNoArgs->LayerJson(bindingsInvalidString);
|
||||
VERIFY_ARE_EQUAL(0u, actionMapNoArgs->_KeyMap.size());
|
||||
}
|
||||
{
|
||||
const std::string bindingsInvalidString{ R"([{ "keys": ["up"], "command": { "action": "moveTab", "direction": "bad" } }])" };
|
||||
const auto bindingsInvalidJson = VerifyParseSucceeded(bindingsInvalidString);
|
||||
auto invalidKeyMap = winrt::make_self<implementation::KeyMapping>();
|
||||
VERIFY_IS_NOT_NULL(invalidKeyMap);
|
||||
VERIFY_ARE_EQUAL(0u, invalidKeyMap->_keyShortcuts.size());
|
||||
VERIFY_THROWS(invalidKeyMap->LayerJson(bindingsInvalidJson);, std::exception);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -592,15 +599,15 @@ namespace SettingsModelLocalTests
|
||||
|
||||
const auto bindings0Json = VerifyParseSucceeded(bindings0String);
|
||||
|
||||
auto keymap = winrt::make_self<implementation::KeyMapping>();
|
||||
VERIFY_IS_NOT_NULL(keymap);
|
||||
VERIFY_ARE_EQUAL(0u, keymap->_keyShortcuts.size());
|
||||
keymap->LayerJson(bindings0Json);
|
||||
VERIFY_ARE_EQUAL(3u, keymap->_keyShortcuts.size());
|
||||
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) };
|
||||
auto actionAndArgs = ::TestUtils::GetActionAndArgs(*keymap, kc);
|
||||
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);
|
||||
@@ -609,7 +616,7 @@ namespace SettingsModelLocalTests
|
||||
}
|
||||
{
|
||||
KeyChord kc{ true, false, false, static_cast<int32_t>(VK_UP) };
|
||||
auto actionAndArgs = ::TestUtils::GetActionAndArgs(*keymap, kc);
|
||||
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);
|
||||
@@ -618,7 +625,7 @@ namespace SettingsModelLocalTests
|
||||
}
|
||||
{
|
||||
KeyChord kc{ true, false, true, static_cast<int32_t>(VK_UP) };
|
||||
auto actionAndArgs = ::TestUtils::GetActionAndArgs(*keymap, kc);
|
||||
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);
|
||||
@@ -628,10 +635,69 @@ namespace SettingsModelLocalTests
|
||||
{
|
||||
const std::string bindingsInvalidString{ R"([{ "keys": ["up"], "command": { "action": "commandPalette", "launchMode": "bad" } }])" };
|
||||
const auto bindingsInvalidJson = VerifyParseSucceeded(bindingsInvalidString);
|
||||
auto invalidKeyMap = winrt::make_self<implementation::KeyMapping>();
|
||||
VERIFY_IS_NOT_NULL(invalidKeyMap);
|
||||
VERIFY_ARE_EQUAL(0u, invalidKeyMap->_keyShortcuts.size());
|
||||
VERIFY_THROWS(invalidKeyMap->LayerJson(bindingsInvalidJson);, std::exception);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
void KeyBindingsTests::TestGetKeyBindingForAction()
|
||||
{
|
||||
const std::string bindings0String{ R"([ { "command": "closeWindow", "keys": "ctrl+a" } ])" };
|
||||
const std::string bindings1String{ R"([ { "command": { "action": "copy", "singleLine": true }, "keys": "ctrl+b" } ])" };
|
||||
const std::string bindings2String{ R"([ { "command": { "action": "newTab", "index": 0 }, "keys": "ctrl+c" } ])" };
|
||||
|
||||
const auto bindings0Json = VerifyParseSucceeded(bindings0String);
|
||||
const auto bindings1Json = VerifyParseSucceeded(bindings1String);
|
||||
const auto bindings2Json = VerifyParseSucceeded(bindings2String);
|
||||
|
||||
auto VerifyKeyChordEquality = [](const KeyChord& expected, const KeyChord& actual) {
|
||||
if (expected)
|
||||
{
|
||||
VERIFY_IS_NOT_NULL(actual);
|
||||
VERIFY_ARE_EQUAL(expected.Modifiers(), actual.Modifiers());
|
||||
VERIFY_ARE_EQUAL(expected.Vkey(), actual.Vkey());
|
||||
}
|
||||
else
|
||||
{
|
||||
VERIFY_IS_NULL(actual);
|
||||
}
|
||||
};
|
||||
|
||||
auto actionMap = winrt::make_self<implementation::ActionMap>();
|
||||
VERIFY_IS_NOT_NULL(actionMap);
|
||||
VERIFY_ARE_EQUAL(0u, actionMap->_KeyMap.size());
|
||||
|
||||
{
|
||||
Log::Comment(L"simple command: no args");
|
||||
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);
|
||||
}
|
||||
{
|
||||
Log::Comment(L"command with args");
|
||||
actionMap->LayerJson(bindings1Json);
|
||||
VERIFY_ARE_EQUAL(2u, actionMap->_KeyMap.size());
|
||||
|
||||
auto args{ winrt::make_self<implementation::CopyTextArgs>() };
|
||||
args->SingleLine(true);
|
||||
|
||||
const auto& kbd{ actionMap->GetKeyBindingForAction(ShortcutAction::CopyText, *args) };
|
||||
VerifyKeyChordEquality({ KeyModifiers::Ctrl, static_cast<int32_t>('B') }, kbd);
|
||||
}
|
||||
{
|
||||
Log::Comment(L"command with new terminal args");
|
||||
actionMap->LayerJson(bindings2Json);
|
||||
VERIFY_ARE_EQUAL(3u, actionMap->_KeyMap.size());
|
||||
|
||||
auto newTerminalArgs{ winrt::make_self<implementation::NewTerminalArgs>() };
|
||||
newTerminalArgs->ProfileIndex(0);
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,6 +76,13 @@
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>onecoreuap.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<!--
|
||||
SettingsModelLib contains a DllMain that we need to force the use of.
|
||||
If you don't have this, then you'll see an error like
|
||||
"(init.obj) : error LNK2005: DllMain already defined in MSVCRTD.lib(dll_dllmain_stub.obj)"
|
||||
-->
|
||||
<AdditionalOptions Condition="'$(Platform)'=='Win32'">/INCLUDE:_DllMain@12</AdditionalOptions>
|
||||
<AdditionalOptions Condition="'$(Platform)'!='Win32'">/INCLUDE:DllMain</AdditionalOptions>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
|
||||
|
||||
@@ -103,17 +103,18 @@ namespace SettingsModelLocalTests
|
||||
|
||||
CascadiaSettings settings{ til::u8u16(settingsJson) };
|
||||
|
||||
auto keymap = settings.GlobalSettings().KeyMap();
|
||||
auto actionMap = settings.GlobalSettings().ActionMap();
|
||||
VERIFY_ARE_EQUAL(3u, settings.ActiveProfiles().Size());
|
||||
|
||||
const auto profile2Guid = settings.ActiveProfiles().GetAt(2).Guid();
|
||||
VERIFY_ARE_NOT_EQUAL(winrt::guid{}, profile2Guid);
|
||||
|
||||
VERIFY_ARE_EQUAL(12u, keymap.Size());
|
||||
const auto& actionMapImpl{ winrt::get_self<implementation::ActionMap>(actionMap) };
|
||||
VERIFY_ARE_EQUAL(12u, actionMapImpl->_KeyMap.size());
|
||||
|
||||
{
|
||||
KeyChord kc{ true, false, false, static_cast<int32_t>('A') };
|
||||
auto actionAndArgs = ::TestUtils::GetActionAndArgs(keymap, kc);
|
||||
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);
|
||||
@@ -134,7 +135,7 @@ namespace SettingsModelLocalTests
|
||||
}
|
||||
{
|
||||
KeyChord kc{ true, false, false, static_cast<int32_t>('B') };
|
||||
auto actionAndArgs = ::TestUtils::GetActionAndArgs(keymap, kc);
|
||||
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);
|
||||
@@ -156,7 +157,7 @@ namespace SettingsModelLocalTests
|
||||
}
|
||||
{
|
||||
KeyChord kc{ true, false, false, static_cast<int32_t>('C') };
|
||||
auto actionAndArgs = ::TestUtils::GetActionAndArgs(keymap, kc);
|
||||
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);
|
||||
@@ -178,7 +179,7 @@ namespace SettingsModelLocalTests
|
||||
}
|
||||
{
|
||||
KeyChord kc{ true, false, false, static_cast<int32_t>('D') };
|
||||
auto actionAndArgs = ::TestUtils::GetActionAndArgs(keymap, kc);
|
||||
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);
|
||||
@@ -200,7 +201,7 @@ namespace SettingsModelLocalTests
|
||||
}
|
||||
{
|
||||
KeyChord kc{ true, false, false, static_cast<int32_t>('E') };
|
||||
auto actionAndArgs = ::TestUtils::GetActionAndArgs(keymap, kc);
|
||||
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);
|
||||
@@ -222,7 +223,7 @@ namespace SettingsModelLocalTests
|
||||
}
|
||||
{
|
||||
KeyChord kc{ true, false, false, static_cast<int32_t>('F') };
|
||||
auto actionAndArgs = ::TestUtils::GetActionAndArgs(keymap, kc);
|
||||
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);
|
||||
@@ -245,7 +246,7 @@ namespace SettingsModelLocalTests
|
||||
}
|
||||
{
|
||||
KeyChord kc{ true, false, false, static_cast<int32_t>('G') };
|
||||
auto actionAndArgs = ::TestUtils::GetActionAndArgs(keymap, kc);
|
||||
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);
|
||||
@@ -265,7 +266,7 @@ namespace SettingsModelLocalTests
|
||||
}
|
||||
{
|
||||
KeyChord kc{ true, false, false, static_cast<int32_t>('H') };
|
||||
auto actionAndArgs = ::TestUtils::GetActionAndArgs(keymap, kc);
|
||||
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);
|
||||
@@ -287,7 +288,7 @@ namespace SettingsModelLocalTests
|
||||
}
|
||||
{
|
||||
KeyChord kc{ true, false, false, static_cast<int32_t>('I') };
|
||||
auto actionAndArgs = ::TestUtils::GetActionAndArgs(keymap, kc);
|
||||
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);
|
||||
@@ -310,7 +311,7 @@ namespace SettingsModelLocalTests
|
||||
}
|
||||
{
|
||||
KeyChord kc{ true, false, false, static_cast<int32_t>('J') };
|
||||
auto actionAndArgs = ::TestUtils::GetActionAndArgs(keymap, kc);
|
||||
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);
|
||||
@@ -332,7 +333,7 @@ namespace SettingsModelLocalTests
|
||||
}
|
||||
{
|
||||
KeyChord kc{ true, false, false, static_cast<int32_t>('K') };
|
||||
auto actionAndArgs = ::TestUtils::GetActionAndArgs(keymap, kc);
|
||||
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);
|
||||
@@ -355,7 +356,7 @@ namespace SettingsModelLocalTests
|
||||
}
|
||||
{
|
||||
KeyChord kc{ true, false, false, static_cast<int32_t>('L') };
|
||||
auto actionAndArgs = ::TestUtils::GetActionAndArgs(keymap, kc);
|
||||
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);
|
||||
|
||||
@@ -19,11 +19,11 @@ public:
|
||||
// - This is a helper to retrieve the ActionAndArgs from the keybindings
|
||||
// for a given chord.
|
||||
// Arguments:
|
||||
// - keymap: The AppKeyBindings to lookup the ActionAndArgs from.
|
||||
// - actionMap: The ActionMap to lookup the ActionAndArgs from.
|
||||
// - kc: The key chord to look up the bound ActionAndArgs for.
|
||||
// Return Value:
|
||||
// - The ActionAndArgs bound to the given key, or nullptr if nothing is bound to it.
|
||||
static const winrt::Microsoft::Terminal::Settings::Model::ActionAndArgs GetActionAndArgs(const winrt::Microsoft::Terminal::Settings::Model::KeyMapping& keymap,
|
||||
static const winrt::Microsoft::Terminal::Settings::Model::ActionAndArgs GetActionAndArgs(const winrt::Microsoft::Terminal::Settings::Model::ActionMap& actionMap,
|
||||
const winrt::Microsoft::Terminal::Control::KeyChord& kc)
|
||||
{
|
||||
std::wstring buffer{ L"" };
|
||||
@@ -42,8 +42,8 @@ public:
|
||||
buffer += static_cast<wchar_t>(MapVirtualKeyW(kc.Vkey(), MAPVK_VK_TO_CHAR));
|
||||
WEX::Logging::Log::Comment(WEX::Common::NoThrowString().Format(L"Looking for key:%s", buffer.c_str()));
|
||||
|
||||
const auto action = keymap.TryLookup(kc);
|
||||
VERIFY_IS_NOT_NULL(action, L"Expected to find an action bound to the given KeyChord");
|
||||
return action;
|
||||
const auto cmd = actionMap.GetActionByKeyChord(kc);
|
||||
VERIFY_IS_NOT_NULL(cmd, L"Expected to find an action bound to the given KeyChord");
|
||||
return cmd.ActionAndArgs();
|
||||
};
|
||||
};
|
||||
|
||||
@@ -120,13 +120,13 @@ namespace TerminalAppLocalTests
|
||||
|
||||
VERIFY_ARE_EQUAL(3u, settings.ActiveProfiles().Size());
|
||||
|
||||
auto commands = settings.GlobalSettings().Commands();
|
||||
VERIFY_ARE_EQUAL(1u, commands.Size());
|
||||
auto nameMap{ settings.ActionMap().NameMap() };
|
||||
VERIFY_ARE_EQUAL(1u, nameMap.Size());
|
||||
|
||||
{
|
||||
auto command = commands.Lookup(L"iterable command ${profile.name}");
|
||||
auto command = nameMap.TryLookup(L"iterable command ${profile.name}");
|
||||
VERIFY_IS_NOT_NULL(command);
|
||||
auto actionAndArgs = command.Action();
|
||||
auto actionAndArgs = command.ActionAndArgs();
|
||||
VERIFY_IS_NOT_NULL(actionAndArgs);
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, actionAndArgs.Action());
|
||||
const auto& realArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
|
||||
@@ -141,7 +141,7 @@ namespace TerminalAppLocalTests
|
||||
VERIFY_ARE_EQUAL(L"${profile.name}", realArgs.TerminalArgs().Profile());
|
||||
}
|
||||
|
||||
auto expandedCommands = winrt::TerminalApp::implementation::TerminalPage::_ExpandCommands(commands, settings.ActiveProfiles().GetView(), settings.GlobalSettings().ColorSchemes());
|
||||
auto expandedCommands = winrt::TerminalApp::implementation::TerminalPage::_ExpandCommands(nameMap, settings.ActiveProfiles().GetView(), settings.GlobalSettings().ColorSchemes());
|
||||
_logCommandNames(expandedCommands.GetView());
|
||||
|
||||
VERIFY_ARE_EQUAL(0u, settings.Warnings().Size());
|
||||
@@ -150,7 +150,7 @@ namespace TerminalAppLocalTests
|
||||
{
|
||||
auto command = expandedCommands.Lookup(L"iterable command profile0");
|
||||
VERIFY_IS_NOT_NULL(command);
|
||||
auto actionAndArgs = command.Action();
|
||||
auto actionAndArgs = command.ActionAndArgs();
|
||||
VERIFY_IS_NOT_NULL(actionAndArgs);
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, actionAndArgs.Action());
|
||||
const auto& realArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
|
||||
@@ -168,7 +168,7 @@ namespace TerminalAppLocalTests
|
||||
{
|
||||
auto command = expandedCommands.Lookup(L"iterable command profile1");
|
||||
VERIFY_IS_NOT_NULL(command);
|
||||
auto actionAndArgs = command.Action();
|
||||
auto actionAndArgs = command.ActionAndArgs();
|
||||
VERIFY_IS_NOT_NULL(actionAndArgs);
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, actionAndArgs.Action());
|
||||
const auto& realArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
|
||||
@@ -186,7 +186,7 @@ namespace TerminalAppLocalTests
|
||||
{
|
||||
auto command = expandedCommands.Lookup(L"iterable command profile2");
|
||||
VERIFY_IS_NOT_NULL(command);
|
||||
auto actionAndArgs = command.Action();
|
||||
auto actionAndArgs = command.ActionAndArgs();
|
||||
VERIFY_IS_NOT_NULL(actionAndArgs);
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, actionAndArgs.Action());
|
||||
const auto& realArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
|
||||
@@ -247,13 +247,13 @@ namespace TerminalAppLocalTests
|
||||
|
||||
VERIFY_ARE_EQUAL(3u, settings.ActiveProfiles().Size());
|
||||
|
||||
auto commands = settings.GlobalSettings().Commands();
|
||||
VERIFY_ARE_EQUAL(1u, commands.Size());
|
||||
auto nameMap{ settings.ActionMap().NameMap() };
|
||||
VERIFY_ARE_EQUAL(1u, nameMap.Size());
|
||||
|
||||
{
|
||||
auto command = commands.Lookup(L"Split pane, profile: ${profile.name}");
|
||||
auto command = nameMap.TryLookup(L"Split pane, profile: ${profile.name}");
|
||||
VERIFY_IS_NOT_NULL(command);
|
||||
auto actionAndArgs = command.Action();
|
||||
auto actionAndArgs = command.ActionAndArgs();
|
||||
VERIFY_IS_NOT_NULL(actionAndArgs);
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, actionAndArgs.Action());
|
||||
const auto& realArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
|
||||
@@ -268,7 +268,7 @@ namespace TerminalAppLocalTests
|
||||
VERIFY_ARE_EQUAL(L"${profile.name}", realArgs.TerminalArgs().Profile());
|
||||
}
|
||||
|
||||
auto expandedCommands = winrt::TerminalApp::implementation::TerminalPage::_ExpandCommands(commands, settings.ActiveProfiles().GetView(), settings.GlobalSettings().ColorSchemes());
|
||||
auto expandedCommands = winrt::TerminalApp::implementation::TerminalPage::_ExpandCommands(nameMap, settings.ActiveProfiles().GetView(), settings.GlobalSettings().ColorSchemes());
|
||||
_logCommandNames(expandedCommands.GetView());
|
||||
|
||||
VERIFY_ARE_EQUAL(0u, settings.Warnings().Size());
|
||||
@@ -277,7 +277,7 @@ namespace TerminalAppLocalTests
|
||||
{
|
||||
auto command = expandedCommands.Lookup(L"Split pane, profile: profile0");
|
||||
VERIFY_IS_NOT_NULL(command);
|
||||
auto actionAndArgs = command.Action();
|
||||
auto actionAndArgs = command.ActionAndArgs();
|
||||
VERIFY_IS_NOT_NULL(actionAndArgs);
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, actionAndArgs.Action());
|
||||
const auto& realArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
|
||||
@@ -295,7 +295,7 @@ namespace TerminalAppLocalTests
|
||||
{
|
||||
auto command = expandedCommands.Lookup(L"Split pane, profile: profile1");
|
||||
VERIFY_IS_NOT_NULL(command);
|
||||
auto actionAndArgs = command.Action();
|
||||
auto actionAndArgs = command.ActionAndArgs();
|
||||
VERIFY_IS_NOT_NULL(actionAndArgs);
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, actionAndArgs.Action());
|
||||
const auto& realArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
|
||||
@@ -313,7 +313,7 @@ namespace TerminalAppLocalTests
|
||||
{
|
||||
auto command = expandedCommands.Lookup(L"Split pane, profile: profile2");
|
||||
VERIFY_IS_NOT_NULL(command);
|
||||
auto actionAndArgs = command.Action();
|
||||
auto actionAndArgs = command.ActionAndArgs();
|
||||
VERIFY_IS_NOT_NULL(actionAndArgs);
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, actionAndArgs.Action());
|
||||
const auto& realArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
|
||||
@@ -376,13 +376,13 @@ namespace TerminalAppLocalTests
|
||||
|
||||
VERIFY_ARE_EQUAL(3u, settings.ActiveProfiles().Size());
|
||||
|
||||
auto commands = settings.GlobalSettings().Commands();
|
||||
VERIFY_ARE_EQUAL(1u, commands.Size());
|
||||
auto nameMap{ settings.ActionMap().NameMap() };
|
||||
VERIFY_ARE_EQUAL(1u, nameMap.Size());
|
||||
|
||||
{
|
||||
auto command = commands.Lookup(L"iterable command ${profile.name}");
|
||||
auto command = nameMap.TryLookup(L"iterable command ${profile.name}");
|
||||
VERIFY_IS_NOT_NULL(command);
|
||||
auto actionAndArgs = command.Action();
|
||||
auto actionAndArgs = command.ActionAndArgs();
|
||||
VERIFY_IS_NOT_NULL(actionAndArgs);
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, actionAndArgs.Action());
|
||||
const auto& realArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
|
||||
@@ -397,7 +397,7 @@ namespace TerminalAppLocalTests
|
||||
VERIFY_ARE_EQUAL(L"${profile.name}", realArgs.TerminalArgs().Profile());
|
||||
}
|
||||
|
||||
auto expandedCommands = winrt::TerminalApp::implementation::TerminalPage::_ExpandCommands(commands, settings.ActiveProfiles().GetView(), settings.GlobalSettings().ColorSchemes());
|
||||
auto expandedCommands = winrt::TerminalApp::implementation::TerminalPage::_ExpandCommands(nameMap, settings.ActiveProfiles().GetView(), settings.GlobalSettings().ColorSchemes());
|
||||
_logCommandNames(expandedCommands.GetView());
|
||||
|
||||
VERIFY_ARE_EQUAL(0u, settings.Warnings().Size());
|
||||
@@ -406,7 +406,7 @@ namespace TerminalAppLocalTests
|
||||
{
|
||||
auto command = expandedCommands.Lookup(L"iterable command profile0");
|
||||
VERIFY_IS_NOT_NULL(command);
|
||||
auto actionAndArgs = command.Action();
|
||||
auto actionAndArgs = command.ActionAndArgs();
|
||||
VERIFY_IS_NOT_NULL(actionAndArgs);
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, actionAndArgs.Action());
|
||||
const auto& realArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
|
||||
@@ -424,7 +424,7 @@ namespace TerminalAppLocalTests
|
||||
{
|
||||
auto command = expandedCommands.Lookup(L"iterable command profile1\"");
|
||||
VERIFY_IS_NOT_NULL(command);
|
||||
auto actionAndArgs = command.Action();
|
||||
auto actionAndArgs = command.ActionAndArgs();
|
||||
VERIFY_IS_NOT_NULL(actionAndArgs);
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, actionAndArgs.Action());
|
||||
const auto& realArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
|
||||
@@ -442,7 +442,7 @@ namespace TerminalAppLocalTests
|
||||
{
|
||||
auto command = expandedCommands.Lookup(L"iterable command profile2");
|
||||
VERIFY_IS_NOT_NULL(command);
|
||||
auto actionAndArgs = command.Action();
|
||||
auto actionAndArgs = command.ActionAndArgs();
|
||||
VERIFY_IS_NOT_NULL(actionAndArgs);
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, actionAndArgs.Action());
|
||||
const auto& realArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
|
||||
@@ -513,8 +513,7 @@ namespace TerminalAppLocalTests
|
||||
VERIFY_ARE_EQUAL(0u, settings.Warnings().Size());
|
||||
VERIFY_ARE_EQUAL(3u, settings.ActiveProfiles().Size());
|
||||
|
||||
auto commands = settings.GlobalSettings().Commands();
|
||||
auto expandedCommands = winrt::TerminalApp::implementation::TerminalPage::_ExpandCommands(commands, settings.ActiveProfiles().GetView(), settings.GlobalSettings().ColorSchemes());
|
||||
auto expandedCommands = winrt::TerminalApp::implementation::TerminalPage::_ExpandCommands(settings.ActionMap().NameMap(), settings.ActiveProfiles().GetView(), settings.GlobalSettings().ColorSchemes());
|
||||
_logCommandNames(expandedCommands.GetView());
|
||||
|
||||
VERIFY_ARE_EQUAL(0u, settings.Warnings().Size());
|
||||
@@ -522,8 +521,9 @@ namespace TerminalAppLocalTests
|
||||
|
||||
auto rootCommand = expandedCommands.Lookup(L"Connect to ssh...");
|
||||
VERIFY_IS_NOT_NULL(rootCommand);
|
||||
auto rootActionAndArgs = rootCommand.Action();
|
||||
VERIFY_IS_NULL(rootActionAndArgs);
|
||||
auto rootActionAndArgs = rootCommand.ActionAndArgs();
|
||||
VERIFY_IS_NOT_NULL(rootActionAndArgs);
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::Invalid, rootActionAndArgs.Action());
|
||||
|
||||
VERIFY_ARE_EQUAL(2u, rootCommand.NestedCommands().Size());
|
||||
|
||||
@@ -531,7 +531,7 @@ namespace TerminalAppLocalTests
|
||||
winrt::hstring commandName{ L"first.com" };
|
||||
auto command = rootCommand.NestedCommands().Lookup(commandName);
|
||||
VERIFY_IS_NOT_NULL(command);
|
||||
auto actionAndArgs = command.Action();
|
||||
auto actionAndArgs = command.ActionAndArgs();
|
||||
VERIFY_IS_NOT_NULL(actionAndArgs);
|
||||
|
||||
VERIFY_IS_FALSE(command.HasNestedCommands());
|
||||
@@ -540,7 +540,7 @@ namespace TerminalAppLocalTests
|
||||
winrt::hstring commandName{ L"second.com" };
|
||||
auto command = rootCommand.NestedCommands().Lookup(commandName);
|
||||
VERIFY_IS_NOT_NULL(command);
|
||||
auto actionAndArgs = command.Action();
|
||||
auto actionAndArgs = command.ActionAndArgs();
|
||||
VERIFY_IS_NOT_NULL(actionAndArgs);
|
||||
|
||||
VERIFY_IS_FALSE(command.HasNestedCommands());
|
||||
@@ -608,8 +608,7 @@ namespace TerminalAppLocalTests
|
||||
VERIFY_ARE_EQUAL(0u, settings.Warnings().Size());
|
||||
VERIFY_ARE_EQUAL(3u, settings.ActiveProfiles().Size());
|
||||
|
||||
auto commands = settings.GlobalSettings().Commands();
|
||||
auto expandedCommands = winrt::TerminalApp::implementation::TerminalPage::_ExpandCommands(commands, settings.ActiveProfiles().GetView(), settings.GlobalSettings().ColorSchemes());
|
||||
auto expandedCommands = winrt::TerminalApp::implementation::TerminalPage::_ExpandCommands(settings.ActionMap().NameMap(), settings.ActiveProfiles().GetView(), settings.GlobalSettings().ColorSchemes());
|
||||
_logCommandNames(expandedCommands.GetView());
|
||||
|
||||
VERIFY_ARE_EQUAL(0u, settings.Warnings().Size());
|
||||
@@ -617,23 +616,25 @@ namespace TerminalAppLocalTests
|
||||
|
||||
auto grandparentCommand = expandedCommands.Lookup(L"grandparent");
|
||||
VERIFY_IS_NOT_NULL(grandparentCommand);
|
||||
auto grandparentActionAndArgs = grandparentCommand.Action();
|
||||
VERIFY_IS_NULL(grandparentActionAndArgs);
|
||||
auto grandparentActionAndArgs = grandparentCommand.ActionAndArgs();
|
||||
VERIFY_IS_NOT_NULL(grandparentActionAndArgs);
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::Invalid, grandparentActionAndArgs.Action());
|
||||
|
||||
VERIFY_ARE_EQUAL(1u, grandparentCommand.NestedCommands().Size());
|
||||
|
||||
winrt::hstring parentName{ L"parent" };
|
||||
auto parent = grandparentCommand.NestedCommands().Lookup(parentName);
|
||||
VERIFY_IS_NOT_NULL(parent);
|
||||
auto parentActionAndArgs = parent.Action();
|
||||
VERIFY_IS_NULL(parentActionAndArgs);
|
||||
auto parentActionAndArgs = parent.ActionAndArgs();
|
||||
VERIFY_IS_NOT_NULL(parentActionAndArgs);
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::Invalid, parentActionAndArgs.Action());
|
||||
|
||||
VERIFY_ARE_EQUAL(2u, parent.NestedCommands().Size());
|
||||
{
|
||||
winrt::hstring childName{ L"child1" };
|
||||
auto child = parent.NestedCommands().Lookup(childName);
|
||||
VERIFY_IS_NOT_NULL(child);
|
||||
auto childActionAndArgs = child.Action();
|
||||
auto childActionAndArgs = child.ActionAndArgs();
|
||||
VERIFY_IS_NOT_NULL(childActionAndArgs);
|
||||
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::NewTab, childActionAndArgs.Action());
|
||||
@@ -653,7 +654,7 @@ namespace TerminalAppLocalTests
|
||||
winrt::hstring childName{ L"child2" };
|
||||
auto child = parent.NestedCommands().Lookup(childName);
|
||||
VERIFY_IS_NOT_NULL(child);
|
||||
auto childActionAndArgs = child.Action();
|
||||
auto childActionAndArgs = child.ActionAndArgs();
|
||||
VERIFY_IS_NOT_NULL(childActionAndArgs);
|
||||
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::NewTab, childActionAndArgs.Action());
|
||||
@@ -731,8 +732,7 @@ namespace TerminalAppLocalTests
|
||||
VERIFY_ARE_EQUAL(0u, settings.Warnings().Size());
|
||||
VERIFY_ARE_EQUAL(3u, settings.ActiveProfiles().Size());
|
||||
|
||||
auto commands = settings.GlobalSettings().Commands();
|
||||
auto expandedCommands = winrt::TerminalApp::implementation::TerminalPage::_ExpandCommands(commands, settings.ActiveProfiles().GetView(), settings.GlobalSettings().ColorSchemes());
|
||||
auto expandedCommands = winrt::TerminalApp::implementation::TerminalPage::_ExpandCommands(settings.ActionMap().NameMap(), settings.ActiveProfiles().GetView(), settings.GlobalSettings().ColorSchemes());
|
||||
_logCommandNames(expandedCommands.GetView());
|
||||
|
||||
VERIFY_ARE_EQUAL(0u, settings.Warnings().Size());
|
||||
@@ -744,8 +744,9 @@ namespace TerminalAppLocalTests
|
||||
winrt::hstring commandName{ name + L"..." };
|
||||
auto command = expandedCommands.Lookup(commandName);
|
||||
VERIFY_IS_NOT_NULL(command);
|
||||
auto actionAndArgs = command.Action();
|
||||
VERIFY_IS_NULL(actionAndArgs);
|
||||
auto actionAndArgs = command.ActionAndArgs();
|
||||
VERIFY_IS_NOT_NULL(actionAndArgs);
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::Invalid, actionAndArgs.Action());
|
||||
|
||||
VERIFY_IS_TRUE(command.HasNestedCommands());
|
||||
VERIFY_ARE_EQUAL(3u, command.NestedCommands().Size());
|
||||
@@ -754,7 +755,7 @@ namespace TerminalAppLocalTests
|
||||
winrt::hstring childCommandName{ fmt::format(L"Split pane, profile: {}", name) };
|
||||
auto childCommand = command.NestedCommands().Lookup(childCommandName);
|
||||
VERIFY_IS_NOT_NULL(childCommand);
|
||||
auto childActionAndArgs = childCommand.Action();
|
||||
auto childActionAndArgs = childCommand.ActionAndArgs();
|
||||
VERIFY_IS_NOT_NULL(childActionAndArgs);
|
||||
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, childActionAndArgs.Action());
|
||||
@@ -775,7 +776,7 @@ namespace TerminalAppLocalTests
|
||||
winrt::hstring childCommandName{ fmt::format(L"Split pane, split: horizontal, profile: {}", name) };
|
||||
auto childCommand = command.NestedCommands().Lookup(childCommandName);
|
||||
VERIFY_IS_NOT_NULL(childCommand);
|
||||
auto childActionAndArgs = childCommand.Action();
|
||||
auto childActionAndArgs = childCommand.ActionAndArgs();
|
||||
VERIFY_IS_NOT_NULL(childActionAndArgs);
|
||||
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, childActionAndArgs.Action());
|
||||
@@ -796,7 +797,7 @@ namespace TerminalAppLocalTests
|
||||
winrt::hstring childCommandName{ fmt::format(L"Split pane, split: vertical, profile: {}", name) };
|
||||
auto childCommand = command.NestedCommands().Lookup(childCommandName);
|
||||
VERIFY_IS_NOT_NULL(childCommand);
|
||||
auto childActionAndArgs = childCommand.Action();
|
||||
auto childActionAndArgs = childCommand.ActionAndArgs();
|
||||
VERIFY_IS_NOT_NULL(childActionAndArgs);
|
||||
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, childActionAndArgs.Action());
|
||||
@@ -868,8 +869,7 @@ namespace TerminalAppLocalTests
|
||||
VERIFY_ARE_EQUAL(0u, settings.Warnings().Size());
|
||||
VERIFY_ARE_EQUAL(3u, settings.ActiveProfiles().Size());
|
||||
|
||||
auto commands = settings.GlobalSettings().Commands();
|
||||
auto expandedCommands = winrt::TerminalApp::implementation::TerminalPage::_ExpandCommands(commands, settings.ActiveProfiles().GetView(), settings.GlobalSettings().ColorSchemes());
|
||||
auto expandedCommands = winrt::TerminalApp::implementation::TerminalPage::_ExpandCommands(settings.ActionMap().NameMap(), settings.ActiveProfiles().GetView(), settings.GlobalSettings().ColorSchemes());
|
||||
_logCommandNames(expandedCommands.GetView());
|
||||
|
||||
VERIFY_ARE_EQUAL(0u, settings.Warnings().Size());
|
||||
@@ -877,8 +877,9 @@ namespace TerminalAppLocalTests
|
||||
|
||||
auto rootCommand = expandedCommands.Lookup(L"New Tab With Profile...");
|
||||
VERIFY_IS_NOT_NULL(rootCommand);
|
||||
auto rootActionAndArgs = rootCommand.Action();
|
||||
VERIFY_IS_NULL(rootActionAndArgs);
|
||||
auto rootActionAndArgs = rootCommand.ActionAndArgs();
|
||||
VERIFY_IS_NOT_NULL(rootActionAndArgs);
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::Invalid, rootActionAndArgs.Action());
|
||||
|
||||
VERIFY_ARE_EQUAL(3u, rootCommand.NestedCommands().Size());
|
||||
|
||||
@@ -887,7 +888,7 @@ namespace TerminalAppLocalTests
|
||||
winrt::hstring commandName{ fmt::format(L"New tab, profile: {}", name) };
|
||||
auto command = rootCommand.NestedCommands().Lookup(commandName);
|
||||
VERIFY_IS_NOT_NULL(command);
|
||||
auto actionAndArgs = command.Action();
|
||||
auto actionAndArgs = command.ActionAndArgs();
|
||||
VERIFY_IS_NOT_NULL(actionAndArgs);
|
||||
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::NewTab, actionAndArgs.Action());
|
||||
@@ -971,8 +972,7 @@ namespace TerminalAppLocalTests
|
||||
VERIFY_ARE_EQUAL(0u, settings.Warnings().Size());
|
||||
VERIFY_ARE_EQUAL(3u, settings.ActiveProfiles().Size());
|
||||
|
||||
auto commands = settings.GlobalSettings().Commands();
|
||||
auto expandedCommands = winrt::TerminalApp::implementation::TerminalPage::_ExpandCommands(commands, settings.ActiveProfiles().GetView(), settings.GlobalSettings().ColorSchemes());
|
||||
auto expandedCommands = winrt::TerminalApp::implementation::TerminalPage::_ExpandCommands(settings.ActionMap().NameMap(), settings.ActiveProfiles().GetView(), settings.GlobalSettings().ColorSchemes());
|
||||
_logCommandNames(expandedCommands.GetView());
|
||||
|
||||
VERIFY_ARE_EQUAL(0u, settings.Warnings().Size());
|
||||
@@ -980,8 +980,9 @@ namespace TerminalAppLocalTests
|
||||
|
||||
auto rootCommand = expandedCommands.Lookup(L"New Pane...");
|
||||
VERIFY_IS_NOT_NULL(rootCommand);
|
||||
auto rootActionAndArgs = rootCommand.Action();
|
||||
VERIFY_IS_NULL(rootActionAndArgs);
|
||||
auto rootActionAndArgs = rootCommand.ActionAndArgs();
|
||||
VERIFY_IS_NOT_NULL(rootActionAndArgs);
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::Invalid, rootActionAndArgs.Action());
|
||||
|
||||
VERIFY_ARE_EQUAL(3u, rootCommand.NestedCommands().Size());
|
||||
|
||||
@@ -990,8 +991,9 @@ namespace TerminalAppLocalTests
|
||||
winrt::hstring commandName{ name + L"..." };
|
||||
auto command = rootCommand.NestedCommands().Lookup(commandName);
|
||||
VERIFY_IS_NOT_NULL(command);
|
||||
auto actionAndArgs = command.Action();
|
||||
VERIFY_IS_NULL(actionAndArgs);
|
||||
auto actionAndArgs = command.ActionAndArgs();
|
||||
VERIFY_IS_NOT_NULL(actionAndArgs);
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::Invalid, actionAndArgs.Action());
|
||||
|
||||
VERIFY_IS_TRUE(command.HasNestedCommands());
|
||||
VERIFY_ARE_EQUAL(3u, command.NestedCommands().Size());
|
||||
@@ -1001,7 +1003,7 @@ namespace TerminalAppLocalTests
|
||||
winrt::hstring childCommandName{ fmt::format(L"Split pane, profile: {}", name) };
|
||||
auto childCommand = command.NestedCommands().Lookup(childCommandName);
|
||||
VERIFY_IS_NOT_NULL(childCommand);
|
||||
auto childActionAndArgs = childCommand.Action();
|
||||
auto childActionAndArgs = childCommand.ActionAndArgs();
|
||||
VERIFY_IS_NOT_NULL(childActionAndArgs);
|
||||
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, childActionAndArgs.Action());
|
||||
@@ -1022,7 +1024,7 @@ namespace TerminalAppLocalTests
|
||||
winrt::hstring childCommandName{ fmt::format(L"Split pane, split: horizontal, profile: {}", name) };
|
||||
auto childCommand = command.NestedCommands().Lookup(childCommandName);
|
||||
VERIFY_IS_NOT_NULL(childCommand);
|
||||
auto childActionAndArgs = childCommand.Action();
|
||||
auto childActionAndArgs = childCommand.ActionAndArgs();
|
||||
VERIFY_IS_NOT_NULL(childActionAndArgs);
|
||||
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, childActionAndArgs.Action());
|
||||
@@ -1043,7 +1045,7 @@ namespace TerminalAppLocalTests
|
||||
winrt::hstring childCommandName{ fmt::format(L"Split pane, split: vertical, profile: {}", name) };
|
||||
auto childCommand = command.NestedCommands().Lookup(childCommandName);
|
||||
VERIFY_IS_NOT_NULL(childCommand);
|
||||
auto childActionAndArgs = childCommand.Action();
|
||||
auto childActionAndArgs = childCommand.ActionAndArgs();
|
||||
VERIFY_IS_NOT_NULL(childActionAndArgs);
|
||||
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, childActionAndArgs.Action());
|
||||
@@ -1113,13 +1115,13 @@ namespace TerminalAppLocalTests
|
||||
|
||||
VERIFY_ARE_EQUAL(3u, settings.ActiveProfiles().Size());
|
||||
|
||||
auto commands = settings.GlobalSettings().Commands();
|
||||
VERIFY_ARE_EQUAL(1u, commands.Size());
|
||||
auto nameMap{ settings.ActionMap().NameMap() };
|
||||
VERIFY_ARE_EQUAL(1u, nameMap.Size());
|
||||
|
||||
{
|
||||
auto command = commands.Lookup(L"iterable command ${scheme.name}");
|
||||
auto command = nameMap.TryLookup(L"iterable command ${scheme.name}");
|
||||
VERIFY_IS_NOT_NULL(command);
|
||||
auto actionAndArgs = command.Action();
|
||||
auto actionAndArgs = command.ActionAndArgs();
|
||||
VERIFY_IS_NOT_NULL(actionAndArgs);
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, actionAndArgs.Action());
|
||||
const auto& realArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
|
||||
@@ -1134,7 +1136,7 @@ namespace TerminalAppLocalTests
|
||||
VERIFY_ARE_EQUAL(L"${scheme.name}", realArgs.TerminalArgs().Profile());
|
||||
}
|
||||
|
||||
auto expandedCommands = winrt::TerminalApp::implementation::TerminalPage::_ExpandCommands(commands, settings.ActiveProfiles().GetView(), settings.GlobalSettings().ColorSchemes());
|
||||
auto expandedCommands = winrt::TerminalApp::implementation::TerminalPage::_ExpandCommands(nameMap, settings.ActiveProfiles().GetView(), settings.GlobalSettings().ColorSchemes());
|
||||
_logCommandNames(expandedCommands.GetView());
|
||||
|
||||
// This is the same warning as above
|
||||
@@ -1148,7 +1150,7 @@ namespace TerminalAppLocalTests
|
||||
{
|
||||
auto command = expandedCommands.Lookup(L"iterable command scheme_0");
|
||||
VERIFY_IS_NOT_NULL(command);
|
||||
auto actionAndArgs = command.Action();
|
||||
auto actionAndArgs = command.ActionAndArgs();
|
||||
VERIFY_IS_NOT_NULL(actionAndArgs);
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, actionAndArgs.Action());
|
||||
const auto& realArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
|
||||
@@ -1166,7 +1168,7 @@ namespace TerminalAppLocalTests
|
||||
{
|
||||
auto command = expandedCommands.Lookup(L"iterable command scheme_1");
|
||||
VERIFY_IS_NOT_NULL(command);
|
||||
auto actionAndArgs = command.Action();
|
||||
auto actionAndArgs = command.ActionAndArgs();
|
||||
VERIFY_IS_NOT_NULL(actionAndArgs);
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, actionAndArgs.Action());
|
||||
const auto& realArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
|
||||
@@ -1184,7 +1186,7 @@ namespace TerminalAppLocalTests
|
||||
{
|
||||
auto command = expandedCommands.Lookup(L"iterable command scheme_2");
|
||||
VERIFY_IS_NOT_NULL(command);
|
||||
auto actionAndArgs = command.Action();
|
||||
auto actionAndArgs = command.ActionAndArgs();
|
||||
VERIFY_IS_NOT_NULL(actionAndArgs);
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, actionAndArgs.Action());
|
||||
const auto& realArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
|
||||
|
||||
@@ -42,11 +42,11 @@ namespace winrt::TerminalApp::implementation
|
||||
// - <none>
|
||||
void TerminalPage::_EndPreview()
|
||||
{
|
||||
if (_lastPreviewedCommand == nullptr || _lastPreviewedCommand.Action() == nullptr)
|
||||
if (_lastPreviewedCommand == nullptr || _lastPreviewedCommand.ActionAndArgs() == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
switch (_lastPreviewedCommand.Action().Action())
|
||||
switch (_lastPreviewedCommand.ActionAndArgs().Action())
|
||||
{
|
||||
case ShortcutAction::SetColorScheme:
|
||||
{
|
||||
@@ -160,17 +160,17 @@ namespace winrt::TerminalApp::implementation
|
||||
void TerminalPage::_PreviewActionHandler(const IInspectable& /*sender*/,
|
||||
const Microsoft::Terminal::Settings::Model::Command& args)
|
||||
{
|
||||
if (args == nullptr || args.Action() == nullptr)
|
||||
if (args == nullptr || args.ActionAndArgs() == nullptr)
|
||||
{
|
||||
_EndPreview();
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (args.Action().Action())
|
||||
switch (args.ActionAndArgs().Action())
|
||||
{
|
||||
case ShortcutAction::SetColorScheme:
|
||||
{
|
||||
_PreviewColorScheme(args.Action().Args().try_as<SetColorSchemeArgs>());
|
||||
_PreviewColorScheme(args.ActionAndArgs().Args().try_as<SetColorSchemeArgs>());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,10 +14,9 @@ namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
bool AppKeyBindings::TryKeyChord(const KeyChord& kc)
|
||||
{
|
||||
const auto actionAndArgs = _keymap.TryLookup(kc);
|
||||
if (actionAndArgs)
|
||||
if (const auto cmd{ _actionMap.GetActionByKeyChord(kc) })
|
||||
{
|
||||
return _dispatch.DoAction(actionAndArgs);
|
||||
return _dispatch.DoAction(cmd.ActionAndArgs());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -27,8 +26,8 @@ namespace winrt::TerminalApp::implementation
|
||||
_dispatch = dispatch;
|
||||
}
|
||||
|
||||
void AppKeyBindings::SetKeyMapping(const winrt::Microsoft::Terminal::Settings::Model::KeyMapping& keymap)
|
||||
void AppKeyBindings::SetActionMap(const winrt::Microsoft::Terminal::Settings::Model::ActionMap& actionMap)
|
||||
{
|
||||
_keymap = keymap;
|
||||
_actionMap = actionMap;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,10 +22,10 @@ namespace winrt::TerminalApp::implementation
|
||||
bool TryKeyChord(winrt::Microsoft::Terminal::Control::KeyChord const& kc);
|
||||
|
||||
void SetDispatch(const winrt::TerminalApp::ShortcutActionDispatch& dispatch);
|
||||
void SetKeyMapping(const Microsoft::Terminal::Settings::Model::KeyMapping& keymap);
|
||||
void SetActionMap(const Microsoft::Terminal::Settings::Model::ActionMap& actionMap);
|
||||
|
||||
private:
|
||||
winrt::Microsoft::Terminal::Settings::Model::KeyMapping _keymap{ nullptr };
|
||||
winrt::Microsoft::Terminal::Settings::Model::ActionMap _actionMap{ nullptr };
|
||||
|
||||
winrt::TerminalApp::ShortcutActionDispatch _dispatch{ nullptr };
|
||||
|
||||
|
||||
@@ -9,6 +9,6 @@ namespace TerminalApp
|
||||
AppKeyBindings();
|
||||
|
||||
void SetDispatch(ShortcutActionDispatch dispatch);
|
||||
void SetKeyMapping(Microsoft.Terminal.Settings.Model.KeyMapping keymap);
|
||||
void SetActionMap(Microsoft.Terminal.Settings.Model.ActionMap actionMap);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -261,19 +261,18 @@ namespace winrt::TerminalApp::implementation
|
||||
// Only give anchored tab switcher the ability to cycle through tabs with the tab button.
|
||||
// For unanchored mode, accessibility becomes an issue when we try to hijack tab since it's
|
||||
// a really widely used keyboard navigation key.
|
||||
if (_currentMode == CommandPaletteMode::TabSwitchMode && _keymap)
|
||||
if (_currentMode == CommandPaletteMode::TabSwitchMode && _actionMap)
|
||||
{
|
||||
winrt::Microsoft::Terminal::Control::KeyChord kc{ ctrlDown, altDown, shiftDown, static_cast<int32_t>(key) };
|
||||
const auto action = _keymap.TryLookup(kc);
|
||||
if (action)
|
||||
if (const auto cmd{ _actionMap.GetActionByKeyChord(kc) })
|
||||
{
|
||||
if (action.Action() == ShortcutAction::PrevTab)
|
||||
if (cmd.ActionAndArgs().Action() == ShortcutAction::PrevTab)
|
||||
{
|
||||
SelectNextItem(false);
|
||||
e.Handled(true);
|
||||
return;
|
||||
}
|
||||
else if (action.Action() == ShortcutAction::NextTab)
|
||||
else if (cmd.ActionAndArgs().Action() == ShortcutAction::NextTab)
|
||||
{
|
||||
SelectNextItem(true);
|
||||
e.Handled(true);
|
||||
@@ -864,9 +863,9 @@ namespace winrt::TerminalApp::implementation
|
||||
return _filteredActions;
|
||||
}
|
||||
|
||||
void CommandPalette::SetKeyMap(const Microsoft::Terminal::Settings::Model::KeyMapping& keymap)
|
||||
void CommandPalette::SetActionMap(const Microsoft::Terminal::Settings::Model::ActionMap& actionMap)
|
||||
{
|
||||
_keymap = keymap;
|
||||
_actionMap = actionMap;
|
||||
}
|
||||
|
||||
void CommandPalette::SetCommands(Collections::IVector<Command> const& actions)
|
||||
|
||||
@@ -32,7 +32,7 @@ namespace winrt::TerminalApp::implementation
|
||||
|
||||
void SetCommands(Windows::Foundation::Collections::IVector<Microsoft::Terminal::Settings::Model::Command> const& actions);
|
||||
void SetTabs(Windows::Foundation::Collections::IObservableVector<winrt::TerminalApp::TabBase> const& tabs, Windows::Foundation::Collections::IObservableVector<winrt::TerminalApp::TabBase> const& mruTabs);
|
||||
void SetKeyMap(const Microsoft::Terminal::Settings::Model::KeyMapping& keymap);
|
||||
void SetActionMap(const Microsoft::Terminal::Settings::Model::ActionMap& actionMap);
|
||||
|
||||
bool OnDirectKeyEvent(const uint32_t vkey, const uint8_t scanCode, const bool down);
|
||||
|
||||
@@ -107,7 +107,7 @@ namespace winrt::TerminalApp::implementation
|
||||
std::wstring _getTrimmedInput();
|
||||
void _evaluatePrefix();
|
||||
|
||||
Microsoft::Terminal::Settings::Model::KeyMapping _keymap{ nullptr };
|
||||
Microsoft::Terminal::Settings::Model::ActionMap _actionMap{ nullptr };
|
||||
|
||||
// Tab Switcher
|
||||
Windows::Foundation::Collections::IVector<winrt::TerminalApp::FilteredCommand> _tabActions{ nullptr };
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace TerminalApp
|
||||
|
||||
void SetTabs(Windows.Foundation.Collections.IObservableVector<TabBase> tabs, Windows.Foundation.Collections.IObservableVector<TabBase> mruTabs);
|
||||
|
||||
void SetKeyMap(Microsoft.Terminal.Settings.Model.KeyMapping keymap);
|
||||
void SetActionMap(Microsoft.Terminal.Settings.Model.ActionMap actionMap);
|
||||
|
||||
void SelectNextItem(Boolean moveDown);
|
||||
|
||||
|
||||
@@ -148,9 +148,9 @@ namespace winrt::TerminalApp::implementation
|
||||
_dispatch = dispatch;
|
||||
}
|
||||
|
||||
void TabBase::SetKeyMap(const Microsoft::Terminal::Settings::Model::KeyMapping& keymap)
|
||||
void TabBase::SetActionMap(const Microsoft::Terminal::Settings::Model::ActionMap& actionMap)
|
||||
{
|
||||
_keymap = keymap;
|
||||
_actionMap = actionMap;
|
||||
_UpdateSwitchToTabKeyChord();
|
||||
}
|
||||
|
||||
@@ -163,9 +163,7 @@ namespace winrt::TerminalApp::implementation
|
||||
// - <none>
|
||||
winrt::fire_and_forget TabBase::_UpdateSwitchToTabKeyChord()
|
||||
{
|
||||
SwitchToTabArgs args{ _TabViewIndex };
|
||||
ActionAndArgs switchToTab{ ShortcutAction::SwitchToTab, args };
|
||||
const auto keyChord = _keymap ? _keymap.GetKeyBindingForActionWithArgs(switchToTab) : nullptr;
|
||||
const auto keyChord = _actionMap ? _actionMap.GetKeyBindingForAction(ShortcutAction::SwitchToTab, SwitchToTabArgs{ _TabViewIndex }) : nullptr;
|
||||
const auto keyChordText = keyChord ? KeyChordSerialization::ToString(keyChord) : L"";
|
||||
|
||||
if (_keyChord == keyChordText)
|
||||
|
||||
@@ -23,7 +23,7 @@ namespace winrt::TerminalApp::implementation
|
||||
void SetDispatch(const winrt::TerminalApp::ShortcutActionDispatch& dispatch);
|
||||
|
||||
void UpdateTabViewIndex(const uint32_t idx, const uint32_t numTabs);
|
||||
void SetKeyMap(const Microsoft::Terminal::Settings::Model::KeyMapping& keymap);
|
||||
void SetActionMap(const Microsoft::Terminal::Settings::Model::ActionMap& actionMap);
|
||||
|
||||
WINRT_CALLBACK(Closed, winrt::Windows::Foundation::EventHandler<winrt::Windows::Foundation::IInspectable>);
|
||||
WINRT_CALLBACK(CloseRequested, winrt::Windows::Foundation::EventHandler<winrt::Windows::Foundation::IInspectable>);
|
||||
@@ -46,7 +46,7 @@ namespace winrt::TerminalApp::implementation
|
||||
winrt::Windows::UI::Xaml::Controls::MenuFlyoutItem _closeOtherTabsMenuItem{};
|
||||
winrt::Windows::UI::Xaml::Controls::MenuFlyoutItem _closeTabsAfterMenuItem{};
|
||||
winrt::TerminalApp::ShortcutActionDispatch _dispatch;
|
||||
Microsoft::Terminal::Settings::Model::KeyMapping _keymap{ nullptr };
|
||||
Microsoft::Terminal::Settings::Model::ActionMap _actionMap{ nullptr };
|
||||
winrt::hstring _keyChord{};
|
||||
|
||||
virtual void _CreateContextMenu();
|
||||
|
||||
@@ -130,7 +130,7 @@ namespace winrt::TerminalApp::implementation
|
||||
_mruTabs.Append(*newTabImpl);
|
||||
|
||||
newTabImpl->SetDispatch(*_actionDispatch);
|
||||
newTabImpl->SetKeyMap(_settings.KeyMap());
|
||||
newTabImpl->SetActionMap(_settings.ActionMap());
|
||||
|
||||
// Give the tab its index in the _tabs vector so it can manage its own SwitchToTab command.
|
||||
_UpdateTabIndices();
|
||||
|
||||
@@ -75,21 +75,19 @@ namespace winrt::TerminalApp::implementation
|
||||
for (const auto& nameAndCmd : commands)
|
||||
{
|
||||
const auto& command = nameAndCmd.Value();
|
||||
// If there's a keybinding that's bound to exactly this command,
|
||||
// then get the string for that keychord and display it as a
|
||||
// part of the command in the UI. Each Command's KeyChordText is
|
||||
// unset by default, so we don't need to worry about clearing it
|
||||
// if there isn't a key associated with it.
|
||||
auto keyChord{ settings.KeyMap().GetKeyBindingForActionWithArgs(command.Action()) };
|
||||
|
||||
if (keyChord)
|
||||
{
|
||||
command.KeyChordText(KeyChordSerialization::ToString(keyChord));
|
||||
}
|
||||
if (command.HasNestedCommands())
|
||||
{
|
||||
_recursiveUpdateCommandKeybindingLabels(settings, command.NestedCommands());
|
||||
}
|
||||
else
|
||||
{
|
||||
// If there's a keybinding that's bound to exactly this command,
|
||||
// then get the keychord and display it as a
|
||||
// part of the command in the UI.
|
||||
// We specifically need to do this for nested commands.
|
||||
const auto keyChord{ settings.ActionMap().GetKeyBindingForAction(command.ActionAndArgs().Action(), command.ActionAndArgs().Args()) };
|
||||
command.RegisterKey(keyChord);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,7 +105,7 @@ namespace winrt::TerminalApp::implementation
|
||||
// happen before the Settings UI is reloaded and tries to re-read
|
||||
// those values.
|
||||
_UpdateCommandsForPalette();
|
||||
CommandPalette().SetKeyMap(_settings.KeyMap());
|
||||
CommandPalette().SetActionMap(_settings.ActionMap());
|
||||
|
||||
if (needRefreshUI)
|
||||
{
|
||||
@@ -123,7 +121,7 @@ namespace winrt::TerminalApp::implementation
|
||||
void TerminalPage::Create()
|
||||
{
|
||||
// Hookup the key bindings
|
||||
_HookupKeyBindings(_settings.KeyMap());
|
||||
_HookupKeyBindings(_settings.ActionMap());
|
||||
|
||||
_tabContent = this->TabContent();
|
||||
_tabRow = this->TabRow();
|
||||
@@ -276,7 +274,7 @@ namespace winrt::TerminalApp::implementation
|
||||
// - <none>
|
||||
void TerminalPage::_OnDispatchCommandRequested(const IInspectable& /*sender*/, const Microsoft::Terminal::Settings::Model::Command& command)
|
||||
{
|
||||
const auto& actionAndArgs = command.Action();
|
||||
const auto& actionAndArgs = command.ActionAndArgs();
|
||||
_actionDispatch->DoAction(actionAndArgs);
|
||||
}
|
||||
|
||||
@@ -523,7 +521,7 @@ namespace winrt::TerminalApp::implementation
|
||||
void TerminalPage::_CreateNewTabFlyout()
|
||||
{
|
||||
auto newTabFlyout = WUX::Controls::MenuFlyout{};
|
||||
auto keyBindings = _settings.KeyMap();
|
||||
auto actionMap = _settings.ActionMap();
|
||||
|
||||
const auto defaultProfileGuid = _settings.GlobalSettings().DefaultProfile();
|
||||
// the number of profiles should not change in the loop for this to work
|
||||
@@ -538,8 +536,7 @@ namespace winrt::TerminalApp::implementation
|
||||
// NewTab(ProfileIndex=N) action
|
||||
NewTerminalArgs newTerminalArgs{ profileIndex };
|
||||
NewTabArgs newTabArgs{ newTerminalArgs };
|
||||
ActionAndArgs actionAndArgs{ ShortcutAction::NewTab, newTabArgs };
|
||||
auto profileKeyChord{ keyBindings.GetKeyBindingForActionWithArgs(actionAndArgs) };
|
||||
auto profileKeyChord{ actionMap.GetKeyBindingForAction(ShortcutAction::NewTab, newTabArgs) };
|
||||
|
||||
// make sure we find one to display
|
||||
if (profileKeyChord)
|
||||
@@ -663,9 +660,7 @@ namespace winrt::TerminalApp::implementation
|
||||
settingsItem.Click({ this, &TerminalPage::_SettingsButtonOnClick });
|
||||
newTabFlyout.Items().Append(settingsItem);
|
||||
|
||||
Microsoft::Terminal::Settings::Model::OpenSettingsArgs args{ SettingsTarget::SettingsUI };
|
||||
Microsoft::Terminal::Settings::Model::ActionAndArgs settingsAction{ ShortcutAction::OpenSettings, args };
|
||||
const auto settingsKeyChord{ keyBindings.GetKeyBindingForActionWithArgs(settingsAction) };
|
||||
const auto settingsKeyChord{ actionMap.GetKeyBindingForAction(ShortcutAction::OpenSettings, OpenSettingsArgs{ SettingsTarget::SettingsUI }) };
|
||||
if (settingsKeyChord)
|
||||
{
|
||||
_SetAcceleratorForMenuItem(settingsItem, settingsKeyChord);
|
||||
@@ -892,14 +887,13 @@ namespace winrt::TerminalApp::implementation
|
||||
auto const shiftDown = WI_IsFlagSet(CoreWindow::GetForCurrentThread().GetKeyState(winrt::Windows::System::VirtualKey::Shift), CoreVirtualKeyStates::Down);
|
||||
|
||||
winrt::Microsoft::Terminal::Control::KeyChord kc{ ctrlDown, altDown, shiftDown, static_cast<int32_t>(key) };
|
||||
const auto actionAndArgs = _settings.KeyMap().TryLookup(kc);
|
||||
if (actionAndArgs)
|
||||
if (const auto cmd{ _settings.ActionMap().GetActionByKeyChord(kc) })
|
||||
{
|
||||
if (CommandPalette().Visibility() == Visibility::Visible && actionAndArgs.Action() != ShortcutAction::ToggleCommandPalette)
|
||||
if (CommandPalette().Visibility() == Visibility::Visible && cmd.ActionAndArgs().Action() != ShortcutAction::ToggleCommandPalette)
|
||||
{
|
||||
CommandPalette().Visibility(Visibility::Collapsed);
|
||||
}
|
||||
_actionDispatch->DoAction(actionAndArgs);
|
||||
_actionDispatch->DoAction(cmd.ActionAndArgs());
|
||||
e.Handled(true);
|
||||
}
|
||||
}
|
||||
@@ -920,23 +914,23 @@ namespace winrt::TerminalApp::implementation
|
||||
auto const shiftDown = WI_IsFlagSet(CoreWindow::GetForCurrentThread().GetKeyState(winrt::Windows::System::VirtualKey::Shift), CoreVirtualKeyStates::Down);
|
||||
|
||||
winrt::Microsoft::Terminal::Control::KeyChord kc{ ctrlDown, altDown, shiftDown, static_cast<int32_t>(key) };
|
||||
const auto actionAndArgs = _settings.KeyMap().TryLookup(kc);
|
||||
if (actionAndArgs && (actionAndArgs.Action() == ShortcutAction::CloseTab || actionAndArgs.Action() == ShortcutAction::NextTab || actionAndArgs.Action() == ShortcutAction::PrevTab || actionAndArgs.Action() == ShortcutAction::ClosePane))
|
||||
const auto cmd{ _settings.ActionMap().GetActionByKeyChord(kc) };
|
||||
if (cmd && (cmd.ActionAndArgs().Action() == ShortcutAction::CloseTab || cmd.ActionAndArgs().Action() == ShortcutAction::NextTab || cmd.ActionAndArgs().Action() == ShortcutAction::PrevTab || cmd.ActionAndArgs().Action() == ShortcutAction::ClosePane))
|
||||
{
|
||||
_actionDispatch->DoAction(actionAndArgs);
|
||||
_actionDispatch->DoAction(cmd.ActionAndArgs());
|
||||
e.Handled(true);
|
||||
}
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Configure the AppKeyBindings to use our ShortcutActionDispatch and the updated KeyMapping
|
||||
// as the object to handle dispatching ShortcutAction events.
|
||||
// - Configure the AppKeyBindings to use our ShortcutActionDispatch and the updated ActionMap
|
||||
// as the object to handle dispatching ShortcutAction events.
|
||||
// Arguments:
|
||||
// - bindings: A AppKeyBindings object to wire up with our event handlers
|
||||
void TerminalPage::_HookupKeyBindings(const KeyMapping& keymap) noexcept
|
||||
// - bindings: An ActionMap object to wire up with our event handlers
|
||||
void TerminalPage::_HookupKeyBindings(const ActionMap& actionMap) noexcept
|
||||
{
|
||||
_bindings->SetDispatch(*_actionDispatch);
|
||||
_bindings->SetKeyMapping(keymap);
|
||||
_bindings->SetActionMap(actionMap);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
@@ -1388,7 +1382,7 @@ namespace winrt::TerminalApp::implementation
|
||||
menuShortcut.Key(static_cast<Windows::System::VirtualKey>(keyChord.Vkey()));
|
||||
|
||||
// inspect the modifiers from the KeyChord and set the flags int he XAML value
|
||||
auto modifiers = AppKeyBindings::ConvertVKModifiers(keyChord.Modifiers());
|
||||
auto modifiers = ActionMap::ConvertVKModifiers(keyChord.Modifiers());
|
||||
|
||||
// add the modifiers to the shortcut
|
||||
menuShortcut.Modifiers(modifiers);
|
||||
@@ -1812,7 +1806,7 @@ namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
// Re-wire the keybindings to their handlers, as we'll have created a
|
||||
// new AppKeyBindings object.
|
||||
_HookupKeyBindings(_settings.KeyMap());
|
||||
_HookupKeyBindings(_settings.ActionMap());
|
||||
|
||||
// Refresh UI elements
|
||||
auto profiles = _settings.ActiveProfiles();
|
||||
@@ -1860,7 +1854,7 @@ namespace winrt::TerminalApp::implementation
|
||||
}
|
||||
|
||||
auto tabImpl{ winrt::get_self<TabBase>(tab) };
|
||||
tabImpl->SetKeyMap(_settings.KeyMap());
|
||||
tabImpl->SetActionMap(_settings.ActionMap());
|
||||
}
|
||||
|
||||
auto weakThis{ get_weak() };
|
||||
@@ -1941,7 +1935,7 @@ namespace winrt::TerminalApp::implementation
|
||||
// - <none>
|
||||
void TerminalPage::_UpdateCommandsForPalette()
|
||||
{
|
||||
IMap<winrt::hstring, Command> copyOfCommands = _ExpandCommands(_settings.GlobalSettings().Commands(),
|
||||
IMap<winrt::hstring, Command> copyOfCommands = _ExpandCommands(_settings.GlobalSettings().ActionMap().NameMap(),
|
||||
_settings.ActiveProfiles().GetView(),
|
||||
_settings.GlobalSettings().ColorSchemes());
|
||||
|
||||
@@ -2335,7 +2329,7 @@ namespace winrt::TerminalApp::implementation
|
||||
_mruTabs.Append(*newTabImpl);
|
||||
|
||||
newTabImpl->SetDispatch(*_actionDispatch);
|
||||
newTabImpl->SetKeyMap(_settings.KeyMap());
|
||||
newTabImpl->SetActionMap(_settings.ActionMap());
|
||||
|
||||
// Give the tab its index in the _tabs vector so it can manage its own SwitchToTab command.
|
||||
_UpdateTabIndices();
|
||||
|
||||
@@ -198,7 +198,7 @@ namespace winrt::TerminalApp::implementation
|
||||
|
||||
void _KeyDownHandler(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::Input::KeyRoutedEventArgs const& e);
|
||||
void _SUIPreviewKeyDownHandler(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::Input::KeyRoutedEventArgs const& e);
|
||||
void _HookupKeyBindings(const Microsoft::Terminal::Settings::Model::KeyMapping& keymap) noexcept;
|
||||
void _HookupKeyBindings(const Microsoft::Terminal::Settings::Model::ActionMap& actionMap) noexcept;
|
||||
void _RegisterActionCallbacks();
|
||||
|
||||
void _UpdateTitle(const TerminalTab& tab);
|
||||
|
||||
@@ -5,11 +5,13 @@
|
||||
#include "Actions.h"
|
||||
#include "Actions.g.cpp"
|
||||
#include "ActionsPageNavigationState.g.cpp"
|
||||
#include "EnumEntry.h"
|
||||
#include "KeyBindingContainer.h"
|
||||
|
||||
using namespace winrt::Windows::Foundation;
|
||||
using namespace winrt::Windows::System;
|
||||
using namespace winrt::Windows::UI::Core;
|
||||
using namespace winrt::Windows::UI::Xaml;
|
||||
using namespace winrt::Windows::UI::Xaml::Controls;
|
||||
using namespace winrt::Windows::UI::Xaml::Navigation;
|
||||
using namespace winrt::Microsoft::Terminal::Settings::Model;
|
||||
|
||||
@@ -18,44 +20,31 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
Actions::Actions()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
_filteredActions = winrt::single_threaded_observable_vector<winrt::Microsoft::Terminal::Settings::Model::Command>();
|
||||
}
|
||||
|
||||
void Actions::OnNavigatedTo(const NavigationEventArgs& e)
|
||||
{
|
||||
_State = e.Parameter().as<Editor::ActionsPageNavigationState>();
|
||||
|
||||
for (const auto& [k, command] : _State.Settings().GlobalSettings().Commands())
|
||||
std::vector<Command> keyBindingList;
|
||||
for (const auto& [_, command] : _State.Settings().GlobalSettings().ActionMap().NameMap())
|
||||
{
|
||||
// Filter out nested commands, and commands that aren't bound to a
|
||||
// key. This page is currently just for displaying the actions that
|
||||
// _are_ bound to keys.
|
||||
if (command.HasNestedCommands() || command.KeyChordText().empty())
|
||||
if (command.HasNestedCommands() || !command.Keys())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
_filteredActions.Append(command);
|
||||
keyBindingList.push_back(command);
|
||||
}
|
||||
std::sort(begin(keyBindingList), end(keyBindingList), CommandComparator{});
|
||||
|
||||
for (const auto& cmd : keyBindingList)
|
||||
{
|
||||
//const auto& container{ make<KeyBindingContainer>(cmd) };
|
||||
const auto& container{ make<CommandViewModel>(cmd) };
|
||||
KeyBindingListView().Items().Append(container);
|
||||
}
|
||||
}
|
||||
|
||||
Collections::IObservableVector<Command> Actions::FilteredActions()
|
||||
{
|
||||
return _filteredActions;
|
||||
}
|
||||
|
||||
void Actions::_OpenSettingsClick(const IInspectable& /*sender*/,
|
||||
const Windows::UI::Xaml::RoutedEventArgs& /*eventArgs*/)
|
||||
{
|
||||
const CoreWindow window = CoreWindow::GetForCurrentThread();
|
||||
const auto rAltState = window.GetKeyState(VirtualKey::RightMenu);
|
||||
const auto lAltState = window.GetKeyState(VirtualKey::LeftMenu);
|
||||
const bool altPressed = WI_IsFlagSet(lAltState, CoreVirtualKeyStates::Down) ||
|
||||
WI_IsFlagSet(rAltState, CoreVirtualKeyStates::Down);
|
||||
|
||||
const auto target = altPressed ? SettingsTarget::DefaultsFile : SettingsTarget::SettingsFile;
|
||||
|
||||
_State.RequestOpenJson(target);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -9,19 +9,21 @@
|
||||
|
||||
namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
{
|
||||
struct CommandComparator
|
||||
{
|
||||
bool operator()(const Model::Command& lhs, const Model::Command& rhs) const
|
||||
{
|
||||
return lhs.Name() < rhs.Name();
|
||||
}
|
||||
};
|
||||
|
||||
struct ActionsPageNavigationState : ActionsPageNavigationStateT<ActionsPageNavigationState>
|
||||
{
|
||||
public:
|
||||
ActionsPageNavigationState(const Model::CascadiaSettings& settings) :
|
||||
_Settings{ settings } {}
|
||||
|
||||
void RequestOpenJson(const Model::SettingsTarget target)
|
||||
{
|
||||
_OpenJsonHandlers(nullptr, target);
|
||||
}
|
||||
|
||||
WINRT_PROPERTY(Model::CascadiaSettings, Settings, nullptr)
|
||||
TYPED_EVENT(OpenJson, Windows::Foundation::IInspectable, Model::SettingsTarget);
|
||||
};
|
||||
|
||||
struct Actions : ActionsT<Actions>
|
||||
@@ -31,15 +33,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
|
||||
void OnNavigatedTo(const winrt::Windows::UI::Xaml::Navigation::NavigationEventArgs& e);
|
||||
|
||||
Windows::Foundation::Collections::IObservableVector<winrt::Microsoft::Terminal::Settings::Model::Command> FilteredActions();
|
||||
|
||||
WINRT_PROPERTY(Editor::ActionsPageNavigationState, State, nullptr);
|
||||
|
||||
private:
|
||||
friend struct ActionsT<Actions>; // for Xaml to bind events
|
||||
Windows::Foundation::Collections::IObservableVector<winrt::Microsoft::Terminal::Settings::Model::Command> _filteredActions{ nullptr };
|
||||
|
||||
void _OpenSettingsClick(const IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& eventArgs);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -8,16 +8,11 @@ namespace Microsoft.Terminal.Settings.Editor
|
||||
runtimeclass ActionsPageNavigationState
|
||||
{
|
||||
Microsoft.Terminal.Settings.Model.CascadiaSettings Settings;
|
||||
void RequestOpenJson(Microsoft.Terminal.Settings.Model.SettingsTarget target);
|
||||
event Windows.Foundation.TypedEventHandler<Object, Microsoft.Terminal.Settings.Model.SettingsTarget> OpenJson;
|
||||
};
|
||||
|
||||
[default_interface] runtimeclass Actions : Windows.UI.Xaml.Controls.Page
|
||||
{
|
||||
Actions();
|
||||
ActionsPageNavigationState State { get; };
|
||||
|
||||
IObservableVector<Microsoft.Terminal.Settings.Model.Command> FilteredActions { get; };
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,11 +5,8 @@
|
||||
<Page x:Class="Microsoft.Terminal.Settings.Editor.Actions"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:SettingsModel="using:Microsoft.Terminal.Settings.Model"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="using:Microsoft.Terminal.Settings.Editor"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:muxc="using:Microsoft.UI.Xaml.Controls"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<Page.Resources>
|
||||
@@ -18,210 +15,20 @@
|
||||
<ResourceDictionary Source="CommonResources.xaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
|
||||
<local:StringIsEmptyConverter x:Key="CommandKeyChordVisibilityConverter" />
|
||||
|
||||
<!--
|
||||
Template for actions. This is _heavily_ copied from the command
|
||||
palette, with modifications:
|
||||
* We don't need to use a HighlightedTextControl, because we're
|
||||
not filtering this list
|
||||
* We don't need the chevron for nested commands
|
||||
* We're not displaying the icon
|
||||
* We're binding directly to a Command, not a FilteredCommand
|
||||
|
||||
If we wanted to reuse the command palette's list more directly,
|
||||
that's theoretically possible, but then it would need to be
|
||||
lifted out of TerminalApp and either moved into the
|
||||
TerminalSettingsEditor or moved to it's own project consumed by
|
||||
both TSE and TerminalApp.
|
||||
-->
|
||||
<DataTemplate x:Key="GeneralItemTemplate"
|
||||
x:DataType="SettingsModel:Command">
|
||||
|
||||
<!--
|
||||
This HorizontalContentAlignment="Stretch" is important
|
||||
to make sure it takes the entire width of the line
|
||||
-->
|
||||
<ListViewItem HorizontalContentAlignment="Stretch"
|
||||
AutomationProperties.AcceleratorKey="{x:Bind KeyChordText, Mode=OneWay}"
|
||||
AutomationProperties.Name="{x:Bind Name, Mode=OneWay}">
|
||||
|
||||
<Grid HorizontalAlignment="Stretch"
|
||||
ColumnSpacing="8">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<!-- command label -->
|
||||
<ColumnDefinition Width="*" />
|
||||
<!-- key chord -->
|
||||
<ColumnDefinition Width="32" />
|
||||
<!-- gutter for scrollbar -->
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<TextBlock Grid.Column="0"
|
||||
HorizontalAlignment="Left"
|
||||
Text="{x:Bind Name, Mode=OneWay}" />
|
||||
|
||||
<!--
|
||||
The block for the key chord is only visible
|
||||
when there's actual text set as the label. See
|
||||
CommandKeyChordVisibilityConverter for details.
|
||||
Inexplicably, we don't need to set the
|
||||
AutomationProperties to Raw here, unlike in the
|
||||
CommandPalette. We're not quite sure why.
|
||||
-->
|
||||
<Border Grid.Column="1"
|
||||
Padding="2,0,2,0"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Center"
|
||||
Style="{ThemeResource KeyChordBorderStyle}"
|
||||
Visibility="{x:Bind KeyChordText, Mode=OneWay, Converter={StaticResource CommandKeyChordVisibilityConverter}}">
|
||||
|
||||
<TextBlock FontSize="12"
|
||||
Style="{ThemeResource KeyChordTextBlockStyle}"
|
||||
Text="{x:Bind KeyChordText, Mode=OneWay}" />
|
||||
</Border>
|
||||
</Grid>
|
||||
</ListViewItem>
|
||||
</DataTemplate>
|
||||
|
||||
<!-- These resources again, HEAVILY copied from the command palette -->
|
||||
<ResourceDictionary.ThemeDictionaries>
|
||||
<ResourceDictionary x:Key="Dark">
|
||||
<!-- TextBox colors ! -->
|
||||
<SolidColorBrush x:Key="TextControlBackground"
|
||||
Color="#333333" />
|
||||
<SolidColorBrush x:Key="TextBoxPlaceholderTextThemeBrush"
|
||||
Color="#B5B5B5" />
|
||||
<SolidColorBrush x:Key="TextControlForeground"
|
||||
Color="#B5B5B5" />
|
||||
<SolidColorBrush x:Key="TextControlBorderBrush"
|
||||
Color="#404040" />
|
||||
<SolidColorBrush x:Key="TextControlButtonForeground"
|
||||
Color="#B5B5B5" />
|
||||
|
||||
<SolidColorBrush x:Key="TextControlBackgroundPointerOver"
|
||||
Color="#404040" />
|
||||
<SolidColorBrush x:Key="TextControlForegroundPointerOver"
|
||||
Color="#FFFFFF" />
|
||||
<SolidColorBrush x:Key="TextControlBorderBrushPointerOver"
|
||||
Color="#404040" />
|
||||
<SolidColorBrush x:Key="TextControlButtonForegroundPointerOver"
|
||||
Color="#FF4343" />
|
||||
|
||||
<SolidColorBrush x:Key="TextControlBackgroundFocused"
|
||||
Color="#333333" />
|
||||
<SolidColorBrush x:Key="TextControlForegroundFocused"
|
||||
Color="#FFFFFF" />
|
||||
<SolidColorBrush x:Key="TextControlBorderBrushFocused"
|
||||
Color="#404040" />
|
||||
<SolidColorBrush x:Key="TextControlButtonForegroundPressed"
|
||||
Color="#FFFFFF" />
|
||||
<SolidColorBrush x:Key="TextControlButtonBackgroundPressed"
|
||||
Color="#FF4343" />
|
||||
|
||||
<!-- KeyChordText styles -->
|
||||
<Style x:Key="KeyChordBorderStyle"
|
||||
TargetType="Border">
|
||||
<Setter Property="BorderThickness" Value="1" />
|
||||
<Setter Property="CornerRadius" Value="1" />
|
||||
<Setter Property="Background" Value="{ThemeResource SystemAltMediumLowColor}" />
|
||||
<Setter Property="BorderBrush" Value="{ThemeResource SystemControlForegroundBaseMediumBrush}" />
|
||||
</Style>
|
||||
<Style x:Key="KeyChordTextBlockStyle"
|
||||
TargetType="TextBlock">
|
||||
<Setter Property="Foreground" Value="{ThemeResource SystemControlForegroundBaseMediumBrush}" />
|
||||
</Style>
|
||||
|
||||
</ResourceDictionary>
|
||||
<ResourceDictionary x:Key="Light">
|
||||
<!-- TextBox colors ! -->
|
||||
<SolidColorBrush x:Key="TextControlBackground"
|
||||
Color="#CCCCCC" />
|
||||
<SolidColorBrush x:Key="TextBoxPlaceholderTextThemeBrush"
|
||||
Color="#636363" />
|
||||
<SolidColorBrush x:Key="TextControlBorderBrush"
|
||||
Color="#636363" />
|
||||
<SolidColorBrush x:Key="TextControlButtonForeground"
|
||||
Color="#636363" />
|
||||
|
||||
<SolidColorBrush x:Key="TextControlBackgroundPointerOver"
|
||||
Color="#DADADA" />
|
||||
<SolidColorBrush x:Key="TextControlBorderBrushPointerOver"
|
||||
Color="#636363" />
|
||||
<SolidColorBrush x:Key="TextControlButtonForegroundPointerOver"
|
||||
Color="#FF4343" />
|
||||
|
||||
<SolidColorBrush x:Key="TextControlBackgroundFocused"
|
||||
Color="#CCCCCC" />
|
||||
<SolidColorBrush x:Key="TextControlBorderBrushFocused"
|
||||
Color="#636363" />
|
||||
<SolidColorBrush x:Key="TextControlButtonForegroundPressed"
|
||||
Color="#FFFFFF" />
|
||||
<SolidColorBrush x:Key="TextControlButtonBackgroundPressed"
|
||||
Color="#FF4343" />
|
||||
|
||||
<!-- KeyChordText styles -->
|
||||
<Style x:Key="KeyChordBorderStyle"
|
||||
TargetType="Border">
|
||||
<Setter Property="BorderThickness" Value="1" />
|
||||
<Setter Property="CornerRadius" Value="1" />
|
||||
<Setter Property="Background" Value="{ThemeResource SystemAltMediumLowColor}" />
|
||||
<Setter Property="BorderBrush" Value="{ThemeResource SystemControlForegroundBaseMediumBrush}" />
|
||||
</Style>
|
||||
<Style x:Key="KeyChordTextBlockStyle"
|
||||
TargetType="TextBlock">
|
||||
<Setter Property="Foreground" Value="{ThemeResource SystemControlForegroundBaseMediumBrush}" />
|
||||
</Style>
|
||||
|
||||
</ResourceDictionary>
|
||||
<ResourceDictionary x:Key="HighContrast">
|
||||
|
||||
<!-- KeyChordText styles (use XAML defaults for High Contrast theme) -->
|
||||
<Style x:Key="KeyChordBorderStyle"
|
||||
TargetType="Border" />
|
||||
<Style x:Key="KeyChordTextBlockStyle"
|
||||
TargetType="TextBlock" />
|
||||
|
||||
</ResourceDictionary>
|
||||
</ResourceDictionary.ThemeDictionaries>
|
||||
|
||||
|
||||
</ResourceDictionary>
|
||||
</Page.Resources>
|
||||
|
||||
<ScrollViewer>
|
||||
<StackPanel Style="{StaticResource SettingsStackStyle}">
|
||||
<TextBlock x:Uid="Globals_KeybindingsDisclaimer"
|
||||
Style="{StaticResource DisclaimerStyle}" />
|
||||
|
||||
<!--
|
||||
The Nav_OpenJSON resource just so happens to have a .Content
|
||||
and .Tooltip that are _exactly_ what we're looking for here.
|
||||
-->
|
||||
|
||||
<HyperlinkButton x:Uid="Nav_OpenJSON"
|
||||
Click="_OpenSettingsClick" />
|
||||
|
||||
<StackPanel HorizontalAlignment="Stretch"
|
||||
Style="{StaticResource SettingsStackStyle}">
|
||||
<!-- Keybindings -->
|
||||
|
||||
<!--
|
||||
NOTE: Globals_Keybindings.Header is not defined, because that
|
||||
would result in the page having "Keybindings" displayed twice, which
|
||||
looks quite redundant
|
||||
-->
|
||||
<ContentPresenter x:Uid="Globals_Keybindings"
|
||||
Margin="0">
|
||||
|
||||
<ListView HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
AllowDrop="False"
|
||||
CanReorderItems="False"
|
||||
IsItemClickEnabled="False"
|
||||
ItemTemplate="{StaticResource GeneralItemTemplate}"
|
||||
ItemsSource="{x:Bind FilteredActions, Mode=OneWay}"
|
||||
SelectionMode="None" />
|
||||
|
||||
</ContentPresenter>
|
||||
<ListView x:Name="KeyBindingListView"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
AllowDrop="False"
|
||||
CanReorderItems="False"
|
||||
IsItemClickEnabled="False"
|
||||
SelectionMode="None" />
|
||||
|
||||
</StackPanel>
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
<Style x:Key="SettingsStackStyle"
|
||||
TargetType="StackPanel">
|
||||
<Setter Property="HorizontalAlignment" Value="Left" />
|
||||
<Setter Property="Margin" Value="13,0,0,48" />
|
||||
<Setter Property="Margin" Value="13,0,13,48" />
|
||||
</Style>
|
||||
|
||||
<!-- Used to stack a group of settings inside a pivot -->
|
||||
|
||||
@@ -58,5 +58,4 @@ namespace Microsoft.Terminal.Settings.Editor
|
||||
{
|
||||
DesktopWallpaperToEmptyStringConverter();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
20
src/cascadia/TerminalSettingsEditor/KeyBindingContainer.cpp
Normal file
20
src/cascadia/TerminalSettingsEditor/KeyBindingContainer.cpp
Normal file
@@ -0,0 +1,20 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#include "pch.h"
|
||||
#include "KeyBindingContainer.h"
|
||||
#include "KeyBindingContainer.g.cpp"
|
||||
//#include "LibraryResources.h"
|
||||
|
||||
using namespace winrt::Microsoft::Terminal::Settings::Model;
|
||||
using namespace winrt::Windows::UI::Xaml;
|
||||
|
||||
namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
{
|
||||
KeyBindingContainer::KeyBindingContainer(Command cmd) :
|
||||
_Action{ cmd }
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
}
|
||||
37
src/cascadia/TerminalSettingsEditor/KeyBindingContainer.h
Normal file
37
src/cascadia/TerminalSettingsEditor/KeyBindingContainer.h
Normal file
@@ -0,0 +1,37 @@
|
||||
/*++
|
||||
Copyright (c) Microsoft Corporation
|
||||
Licensed under the MIT license.
|
||||
|
||||
Module Name:
|
||||
- KeyBindingContainer
|
||||
|
||||
Abstract:
|
||||
- This is a XAML data template to represent a key binding as a list view item.
|
||||
|
||||
Author(s):
|
||||
- Carlos Zamora - April 2021
|
||||
|
||||
--*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "KeyBindingContainer.g.h"
|
||||
#include "Utils.h"
|
||||
|
||||
namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
{
|
||||
struct KeyBindingContainer : KeyBindingContainerT<KeyBindingContainer>
|
||||
{
|
||||
public:
|
||||
KeyBindingContainer() = delete;
|
||||
KeyBindingContainer(Model::Command cmd);
|
||||
|
||||
WINRT_PROPERTY(Model::Command, Action, nullptr);
|
||||
//TYPED_EVENT(Unbind, Editor::KeyBindingContainer, Windows::Foundation::IInspectable);
|
||||
};
|
||||
}
|
||||
|
||||
namespace winrt::Microsoft::Terminal::Settings::Editor::factory_implementation
|
||||
{
|
||||
BASIC_FACTORY(KeyBindingContainer);
|
||||
}
|
||||
14
src/cascadia/TerminalSettingsEditor/KeyBindingContainer.idl
Normal file
14
src/cascadia/TerminalSettingsEditor/KeyBindingContainer.idl
Normal file
@@ -0,0 +1,14 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
namespace Microsoft.Terminal.Settings.Editor
|
||||
{
|
||||
[default_interface] runtimeclass KeyBindingContainer : Windows.UI.Xaml.Controls.ListViewItem
|
||||
{
|
||||
KeyBindingContainer(Microsoft.Terminal.Settings.Model.Command cmd);
|
||||
|
||||
Microsoft.Terminal.Settings.Model.Command Action { get; };
|
||||
|
||||
//event Windows.Foundation.TypedEventHandler<KeyBindingContainer, Object> Unbind;
|
||||
};
|
||||
}
|
||||
238
src/cascadia/TerminalSettingsEditor/KeyBindingContainer.xaml
Normal file
238
src/cascadia/TerminalSettingsEditor/KeyBindingContainer.xaml
Normal file
@@ -0,0 +1,238 @@
|
||||
<!--
|
||||
Copyright (c) Microsoft Corporation. All rights reserved. Licensed under
|
||||
the MIT License. See LICENSE in the project root for license information.
|
||||
-->
|
||||
<ListViewItem x:Class="Microsoft.Terminal.Settings.Editor.KeyBindingContainer"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:local="using:Microsoft.Terminal.Settings.Editor"
|
||||
xmlns:model="using:Microsoft.Terminal.Settings.Model"
|
||||
HorizontalContentAlignment="Stretch"
|
||||
AutomationProperties.AcceleratorKey="{x:Bind Action.KeyChordText, Mode=OneWay}"
|
||||
AutomationProperties.Name="{x:Bind Action.Name, Mode=OneWay}"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<ListViewItem.Resources>
|
||||
<ResourceDictionary>
|
||||
<!-- These resources are HEAVILY copied from the command palette -->
|
||||
<ResourceDictionary.ThemeDictionaries>
|
||||
<ResourceDictionary x:Key="Dark">
|
||||
<!-- TextBox colors ! -->
|
||||
<SolidColorBrush x:Key="TextControlBackground"
|
||||
Color="#333333" />
|
||||
<SolidColorBrush x:Key="TextBoxPlaceholderTextThemeBrush"
|
||||
Color="#B5B5B5" />
|
||||
<SolidColorBrush x:Key="TextControlForeground"
|
||||
Color="#B5B5B5" />
|
||||
<SolidColorBrush x:Key="TextControlBorderBrush"
|
||||
Color="#404040" />
|
||||
<SolidColorBrush x:Key="TextControlButtonForeground"
|
||||
Color="#B5B5B5" />
|
||||
|
||||
<SolidColorBrush x:Key="TextControlBackgroundPointerOver"
|
||||
Color="#404040" />
|
||||
<SolidColorBrush x:Key="TextControlForegroundPointerOver"
|
||||
Color="#FFFFFF" />
|
||||
<SolidColorBrush x:Key="TextControlBorderBrushPointerOver"
|
||||
Color="#404040" />
|
||||
<SolidColorBrush x:Key="TextControlButtonForegroundPointerOver"
|
||||
Color="#FF4343" />
|
||||
|
||||
<SolidColorBrush x:Key="TextControlBackgroundFocused"
|
||||
Color="#333333" />
|
||||
<SolidColorBrush x:Key="TextControlForegroundFocused"
|
||||
Color="#FFFFFF" />
|
||||
<SolidColorBrush x:Key="TextControlBorderBrushFocused"
|
||||
Color="#404040" />
|
||||
<SolidColorBrush x:Key="TextControlButtonForegroundPressed"
|
||||
Color="#FFFFFF" />
|
||||
<SolidColorBrush x:Key="TextControlButtonBackgroundPressed"
|
||||
Color="#FF4343" />
|
||||
|
||||
<!-- KeyChordText styles -->
|
||||
<Style x:Key="KeyChordBorderStyle"
|
||||
TargetType="Border">
|
||||
<Setter Property="BorderThickness" Value="1" />
|
||||
<Setter Property="CornerRadius" Value="1" />
|
||||
<Setter Property="Background" Value="{ThemeResource SystemAltMediumLowColor}" />
|
||||
<Setter Property="BorderBrush" Value="{ThemeResource SystemControlForegroundBaseMediumBrush}" />
|
||||
</Style>
|
||||
<Style x:Key="KeyChordTextBlockStyle"
|
||||
TargetType="TextBlock">
|
||||
<Setter Property="Foreground" Value="{ThemeResource SystemControlForegroundBaseMediumBrush}" />
|
||||
</Style>
|
||||
|
||||
</ResourceDictionary>
|
||||
<ResourceDictionary x:Key="Light">
|
||||
<!-- TextBox colors ! -->
|
||||
<SolidColorBrush x:Key="TextControlBackground"
|
||||
Color="#CCCCCC" />
|
||||
<SolidColorBrush x:Key="TextBoxPlaceholderTextThemeBrush"
|
||||
Color="#636363" />
|
||||
<SolidColorBrush x:Key="TextControlBorderBrush"
|
||||
Color="#636363" />
|
||||
<SolidColorBrush x:Key="TextControlButtonForeground"
|
||||
Color="#636363" />
|
||||
|
||||
<SolidColorBrush x:Key="TextControlBackgroundPointerOver"
|
||||
Color="#DADADA" />
|
||||
<SolidColorBrush x:Key="TextControlBorderBrushPointerOver"
|
||||
Color="#636363" />
|
||||
<SolidColorBrush x:Key="TextControlButtonForegroundPointerOver"
|
||||
Color="#FF4343" />
|
||||
|
||||
<SolidColorBrush x:Key="TextControlBackgroundFocused"
|
||||
Color="#CCCCCC" />
|
||||
<SolidColorBrush x:Key="TextControlBorderBrushFocused"
|
||||
Color="#636363" />
|
||||
<SolidColorBrush x:Key="TextControlButtonForegroundPressed"
|
||||
Color="#FFFFFF" />
|
||||
<SolidColorBrush x:Key="TextControlButtonBackgroundPressed"
|
||||
Color="#FF4343" />
|
||||
|
||||
<!-- KeyChordText styles -->
|
||||
<Style x:Key="KeyChordBorderStyle"
|
||||
TargetType="Border">
|
||||
<Setter Property="BorderThickness" Value="1" />
|
||||
<Setter Property="CornerRadius" Value="1" />
|
||||
<Setter Property="Background" Value="{ThemeResource SystemAltMediumLowColor}" />
|
||||
<Setter Property="BorderBrush" Value="{ThemeResource SystemControlForegroundBaseMediumBrush}" />
|
||||
</Style>
|
||||
<Style x:Key="KeyChordTextBlockStyle"
|
||||
TargetType="TextBlock">
|
||||
<Setter Property="Foreground" Value="{ThemeResource SystemControlForegroundBaseMediumBrush}" />
|
||||
</Style>
|
||||
|
||||
</ResourceDictionary>
|
||||
<ResourceDictionary x:Key="HighContrast">
|
||||
|
||||
<!-- KeyChordText styles (use XAML defaults for High Contrast theme) -->
|
||||
<Style x:Key="KeyChordBorderStyle"
|
||||
TargetType="Border" />
|
||||
<Style x:Key="KeyChordTextBlockStyle"
|
||||
TargetType="TextBlock" />
|
||||
|
||||
</ResourceDictionary>
|
||||
</ResourceDictionary.ThemeDictionaries>
|
||||
|
||||
<local:StringIsEmptyConverter x:Key="CommandKeyChordVisibilityConverter" />
|
||||
<model:IconPathConverter x:Key="IconSourceConverter" />
|
||||
</ResourceDictionary>
|
||||
</ListViewItem.Resources>
|
||||
|
||||
<!--This layout is strongly inspired by the Command Palette-->
|
||||
<Grid ColumnSpacing="8">
|
||||
<Grid.ColumnDefinitions>
|
||||
<!-- command label -->
|
||||
<ColumnDefinition Width="*"
|
||||
MaxWidth="400" />
|
||||
<!-- key chord -->
|
||||
<ColumnDefinition Width="*"
|
||||
MaxWidth="100" />
|
||||
<!-- edit button -->
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<TextBlock Grid.Column="0"
|
||||
Text="{x:Bind Action.Name, Mode=OneWay}" />
|
||||
|
||||
<!--
|
||||
Inexplicably, we don't need to set the
|
||||
AutomationProperties to Raw here, unlike in the
|
||||
CommandPalette. We're not quite sure why.
|
||||
-->
|
||||
<Border Grid.Column="1"
|
||||
Padding="2,0,2,0"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Center"
|
||||
Style="{ThemeResource KeyChordBorderStyle}">
|
||||
|
||||
<TextBlock FontSize="12"
|
||||
Style="{ThemeResource KeyChordTextBlockStyle}"
|
||||
Text="{x:Bind Action.KeyChordText, Mode=OneWay}" />
|
||||
</Border>
|
||||
|
||||
<!-- Edit Button -->
|
||||
<Button x:Name="EditButton"
|
||||
Grid.Column="2"
|
||||
Padding="3">
|
||||
<!--CARLOS: Click="Edit_Click">-->
|
||||
<FontIcon FontSize="12"
|
||||
Glyph="" />
|
||||
</Button>
|
||||
|
||||
<!-- Edit Mode Controls -->
|
||||
<StackPanel x:Name="EditModeStackPanel"
|
||||
Grid.Column="2"
|
||||
Orientation="Horizontal"
|
||||
Visibility="Collapsed">
|
||||
|
||||
<!-- Cancel editing the action -->
|
||||
<Button x:Uid="EditCancel">
|
||||
<!--CARLOS Click="EditCancel_Click">-->
|
||||
<FontIcon FontSize="12"
|
||||
Glyph="" />
|
||||
</Button>
|
||||
|
||||
<!-- Delete the current key binding -->
|
||||
<Button x:Uid="Delete">
|
||||
<!--CARLOS Click="Delete_Click">-->
|
||||
<Button.Content>
|
||||
<FontIcon FontSize="12"
|
||||
Glyph="" />
|
||||
</Button.Content>
|
||||
<Button.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.ThemeDictionaries>
|
||||
<ResourceDictionary x:Key="Light">
|
||||
<SolidColorBrush x:Key="ButtonBackground"
|
||||
Color="Firebrick" />
|
||||
<SolidColorBrush x:Key="ButtonBackgroundPointerOver"
|
||||
Color="#C23232" />
|
||||
<SolidColorBrush x:Key="ButtonBackgroundPressed"
|
||||
Color="#A21212" />
|
||||
<SolidColorBrush x:Key="ButtonForeground"
|
||||
Color="White" />
|
||||
<SolidColorBrush x:Key="ButtonForegroundPointerOver"
|
||||
Color="White" />
|
||||
<SolidColorBrush x:Key="ButtonForegroundPressed"
|
||||
Color="White" />
|
||||
</ResourceDictionary>
|
||||
<ResourceDictionary x:Key="Dark">
|
||||
<SolidColorBrush x:Key="ButtonBackground"
|
||||
Color="Firebrick" />
|
||||
<SolidColorBrush x:Key="ButtonBackgroundPointerOver"
|
||||
Color="#C23232" />
|
||||
<SolidColorBrush x:Key="ButtonBackgroundPressed"
|
||||
Color="#A21212" />
|
||||
<SolidColorBrush x:Key="ButtonForeground"
|
||||
Color="White" />
|
||||
<SolidColorBrush x:Key="ButtonForegroundPointerOver"
|
||||
Color="White" />
|
||||
<SolidColorBrush x:Key="ButtonForegroundPressed"
|
||||
Color="White" />
|
||||
</ResourceDictionary>
|
||||
<ResourceDictionary x:Key="HighContrast">
|
||||
<SolidColorBrush x:Key="ButtonBackground"
|
||||
Color="{ThemeResource SystemColorButtonFaceColor}" />
|
||||
<SolidColorBrush x:Key="ButtonBackgroundPointerOver"
|
||||
Color="{ThemeResource SystemColorHighlightColor}" />
|
||||
<SolidColorBrush x:Key="ButtonBackgroundPressed"
|
||||
Color="{ThemeResource SystemColorHighlightColor}" />
|
||||
<SolidColorBrush x:Key="ButtonForeground"
|
||||
Color="{ThemeResource SystemColorButtonTextColor}" />
|
||||
<SolidColorBrush x:Key="ButtonForegroundPointerOver"
|
||||
Color="{ThemeResource SystemColorHighlightTextColor}" />
|
||||
<SolidColorBrush x:Key="ButtonForegroundPressed"
|
||||
Color="{ThemeResource SystemColorHighlightTextColor}" />
|
||||
</ResourceDictionary>
|
||||
</ResourceDictionary.ThemeDictionaries>
|
||||
</ResourceDictionary>
|
||||
</Button.Resources>
|
||||
</Button>
|
||||
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</ListViewItem>
|
||||
9
src/cascadia/TerminalSettingsEditor/KeyChordConverter.h
Normal file
9
src/cascadia/TerminalSettingsEditor/KeyChordConverter.h
Normal file
@@ -0,0 +1,9 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "NullCheckToVisibilityConverter.g.h"
|
||||
#include "../inc/cppwinrt_utils.h"
|
||||
|
||||
DECLARE_CONVERTER(winrt::Microsoft::Terminal::Settings::Editor, NullCheckToVisibilityConverter);
|
||||
@@ -264,14 +264,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
}
|
||||
else if (clickedItemTag == actionsTag)
|
||||
{
|
||||
auto actionsState{ winrt::make<ActionsPageNavigationState>(_settingsClone) };
|
||||
actionsState.OpenJson([weakThis = get_weak()](auto&&, auto&& arg) {
|
||||
if (auto self{ weakThis.get() })
|
||||
{
|
||||
self->_OpenJsonHandlers(nullptr, arg);
|
||||
}
|
||||
});
|
||||
contentFrame().Navigate(xaml_typename<Editor::Actions>(), actionsState);
|
||||
contentFrame().Navigate(xaml_typename<Editor::Actions>(), winrt::make<ActionsPageNavigationState>(_settingsClone));
|
||||
}
|
||||
else if (clickedItemTag == colorSchemesTag)
|
||||
{
|
||||
|
||||
@@ -81,6 +81,9 @@
|
||||
<ClInclude Include="Interaction.h">
|
||||
<DependentUpon>Interaction.xaml</DependentUpon>
|
||||
</ClInclude>
|
||||
<ClInclude Include="KeyBindingContainer.h">
|
||||
<DependentUpon>KeyBindingContainer.idl</DependentUpon>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Launch.h">
|
||||
<DependentUpon>Launch.xaml</DependentUpon>
|
||||
</ClInclude>
|
||||
@@ -117,6 +120,9 @@
|
||||
<Page Include="Interaction.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="KeyBindingContainer.xaml">
|
||||
<Type>Designer</Type>
|
||||
</Page>
|
||||
<Page Include="Launch.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
@@ -178,6 +184,9 @@
|
||||
<ClCompile Include="Interaction.cpp">
|
||||
<DependentUpon>Interaction.xaml</DependentUpon>
|
||||
</ClCompile>
|
||||
<ClCompile Include="KeyBindingContainer.cpp">
|
||||
<DependentUpon>KeyBindingContainer.idl</DependentUpon>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Launch.cpp">
|
||||
<DependentUpon>Launch.xaml</DependentUpon>
|
||||
</ClCompile>
|
||||
@@ -216,6 +225,10 @@
|
||||
<DependentUpon>ColorSchemes.xaml</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
</Midl>
|
||||
<Midl Include="KeyBindingContainer.idl">
|
||||
<DependentUpon>KeyBindingContainer.xaml</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
</Midl>
|
||||
<Midl Include="Launch.idl">
|
||||
<DependentUpon>Launch.xaml</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
|
||||
@@ -20,27 +20,6 @@ Author(s):
|
||||
#include "SettingContainer.g.h"
|
||||
#include "Utils.h"
|
||||
|
||||
// This macro defines a dependency property for a WinRT class.
|
||||
// Use this in your class' header file after declaring it in the idl.
|
||||
// Remember to register your dependency property in the respective cpp file.
|
||||
#define DEPENDENCY_PROPERTY(type, name) \
|
||||
public: \
|
||||
static winrt::Windows::UI::Xaml::DependencyProperty name##Property() \
|
||||
{ \
|
||||
return _##name##Property; \
|
||||
} \
|
||||
type name() const \
|
||||
{ \
|
||||
return winrt::unbox_value<type>(GetValue(_##name##Property)); \
|
||||
} \
|
||||
void name(type const& value) \
|
||||
{ \
|
||||
SetValue(_##name##Property, winrt::box_value(value)); \
|
||||
} \
|
||||
\
|
||||
private: \
|
||||
static winrt::Windows::UI::Xaml::DependencyProperty _##name##Property;
|
||||
|
||||
namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
{
|
||||
struct SettingContainer : SettingContainerT<SettingContainer>
|
||||
|
||||
@@ -70,6 +70,27 @@ private:
|
||||
winrt::Windows::Foundation::Collections::IObservableVector<winrt::Microsoft::Terminal::Settings::Editor::EnumEntry> _##name##List; \
|
||||
winrt::Windows::Foundation::Collections::IMap<enumType, winrt::Microsoft::Terminal::Settings::Editor::EnumEntry> _##name##Map;
|
||||
|
||||
// This macro defines a dependency property for a WinRT class.
|
||||
// Use this in your class' header file after declaring it in the idl.
|
||||
// Remember to register your dependency property in the respective cpp file.
|
||||
#define DEPENDENCY_PROPERTY(type, name) \
|
||||
public: \
|
||||
static winrt::Windows::UI::Xaml::DependencyProperty name##Property() \
|
||||
{ \
|
||||
return _##name##Property; \
|
||||
} \
|
||||
type name() const \
|
||||
{ \
|
||||
return winrt::unbox_value<type>(GetValue(_##name##Property)); \
|
||||
} \
|
||||
void name(type const& value) \
|
||||
{ \
|
||||
SetValue(_##name##Property, winrt::box_value(value)); \
|
||||
} \
|
||||
\
|
||||
private: \
|
||||
static winrt::Windows::UI::Xaml::DependencyProperty _##name##Property;
|
||||
|
||||
namespace winrt::Microsoft::Terminal::Settings
|
||||
{
|
||||
winrt::hstring GetSelectedItemTag(winrt::Windows::Foundation::IInspectable const& comboBoxAsInspectable);
|
||||
|
||||
@@ -200,7 +200,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
// appended to this vector.
|
||||
// Return Value:
|
||||
// - a deserialized ActionAndArgs corresponding to the values in json, or
|
||||
// null if we failed to deserialize an action.
|
||||
// an "invalid" action if we failed to deserialize an action.
|
||||
winrt::com_ptr<ActionAndArgs> ActionAndArgs::FromJson(const Json::Value& json,
|
||||
std::vector<SettingsLoadWarnings>& warnings)
|
||||
{
|
||||
@@ -255,22 +255,14 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
// if an arg parser was registered, but failed, bail
|
||||
if (pfn && args == nullptr)
|
||||
{
|
||||
return nullptr;
|
||||
return make_self<ActionAndArgs>();
|
||||
}
|
||||
}
|
||||
|
||||
if (action != ShortcutAction::Invalid)
|
||||
{
|
||||
auto actionAndArgs = winrt::make_self<ActionAndArgs>();
|
||||
actionAndArgs->Action(action);
|
||||
actionAndArgs->Args(args);
|
||||
|
||||
return actionAndArgs;
|
||||
}
|
||||
else
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
// Something like
|
||||
// { name: "foo", action: "unbound" }
|
||||
// will _remove_ the "foo" command, by returning an "invalid" action here.
|
||||
return make_self<ActionAndArgs>(action, args);
|
||||
}
|
||||
|
||||
com_ptr<ActionAndArgs> ActionAndArgs::Copy() const
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "ActionAndArgs.g.h"
|
||||
#include "ActionArgs.h"
|
||||
#include "TerminalWarnings.h"
|
||||
#include "../inc/cppwinrt_utils.h"
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
|
||||
#include "../../cascadia/inc/cppwinrt_utils.h"
|
||||
#include "JsonUtils.h"
|
||||
#include "HashUtils.h"
|
||||
#include "TerminalWarnings.h"
|
||||
|
||||
#include "TerminalSettingsSerializationHelpers.h"
|
||||
@@ -44,6 +45,18 @@
|
||||
// * ActionEventArgs holds a single IActionArgs. For events that don't need
|
||||
// additional args, this can be nullptr.
|
||||
|
||||
template<>
|
||||
constexpr size_t Microsoft::Terminal::Settings::Model::HashUtils::HashProperty(const winrt::Microsoft::Terminal::Settings::Model::IActionArgs& args)
|
||||
{
|
||||
return gsl::narrow_cast<size_t>(args.Hash());
|
||||
}
|
||||
|
||||
template<>
|
||||
constexpr size_t Microsoft::Terminal::Settings::Model::HashUtils::HashProperty(const winrt::Microsoft::Terminal::Settings::Model::NewTerminalArgs& args)
|
||||
{
|
||||
return gsl::narrow_cast<size_t>(args.Hash());
|
||||
}
|
||||
|
||||
namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
{
|
||||
using namespace ::Microsoft::Terminal::Settings::Model;
|
||||
@@ -124,6 +137,10 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
copy->_ColorScheme = _ColorScheme;
|
||||
return *copy;
|
||||
}
|
||||
size_t Hash() const
|
||||
{
|
||||
return ::Microsoft::Terminal::Settings::Model::HashUtils::HashProperty(_Commandline, _StartingDirectory, _TabTitle, _TabColor, _ProfileIndex, _Profile, _SuppressApplicationTitle, _ColorScheme);
|
||||
}
|
||||
};
|
||||
|
||||
struct CopyTextArgs : public CopyTextArgsT<CopyTextArgs>
|
||||
@@ -164,6 +181,10 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
copy->_CopyFormatting = _CopyFormatting;
|
||||
return *copy;
|
||||
}
|
||||
size_t Hash() const
|
||||
{
|
||||
return ::Microsoft::Terminal::Settings::Model::HashUtils::HashProperty(_SingleLine, _CopyFormatting);
|
||||
}
|
||||
};
|
||||
|
||||
struct NewTabArgs : public NewTabArgsT<NewTabArgs>
|
||||
@@ -198,6 +219,10 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
copy->_TerminalArgs = _TerminalArgs.Copy();
|
||||
return *copy;
|
||||
}
|
||||
size_t Hash() const
|
||||
{
|
||||
return ::Microsoft::Terminal::Settings::Model::HashUtils::HashProperty(_TerminalArgs);
|
||||
}
|
||||
};
|
||||
|
||||
struct SwitchToTabArgs : public SwitchToTabArgsT<SwitchToTabArgs>
|
||||
@@ -234,6 +259,10 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
copy->_TabIndex = _TabIndex;
|
||||
return *copy;
|
||||
}
|
||||
size_t Hash() const
|
||||
{
|
||||
return ::Microsoft::Terminal::Settings::Model::HashUtils::HashProperty(_TabIndex);
|
||||
}
|
||||
};
|
||||
|
||||
struct ResizePaneArgs : public ResizePaneArgsT<ResizePaneArgs>
|
||||
@@ -275,6 +304,10 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
copy->_ResizeDirection = _ResizeDirection;
|
||||
return *copy;
|
||||
}
|
||||
size_t Hash() const
|
||||
{
|
||||
return ::Microsoft::Terminal::Settings::Model::HashUtils::HashProperty(_ResizeDirection);
|
||||
}
|
||||
};
|
||||
|
||||
struct MoveFocusArgs : public MoveFocusArgsT<MoveFocusArgs>
|
||||
@@ -319,6 +352,10 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
copy->_FocusDirection = _FocusDirection;
|
||||
return *copy;
|
||||
}
|
||||
size_t Hash() const
|
||||
{
|
||||
return ::Microsoft::Terminal::Settings::Model::HashUtils::HashProperty(_FocusDirection);
|
||||
}
|
||||
};
|
||||
|
||||
struct AdjustFontSizeArgs : public AdjustFontSizeArgsT<AdjustFontSizeArgs>
|
||||
@@ -353,6 +390,10 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
copy->_Delta = _Delta;
|
||||
return *copy;
|
||||
}
|
||||
size_t Hash() const
|
||||
{
|
||||
return ::Microsoft::Terminal::Settings::Model::HashUtils::HashProperty(_Delta);
|
||||
}
|
||||
};
|
||||
|
||||
struct SendInputArgs : public SendInputArgsT<SendInputArgs>
|
||||
@@ -390,6 +431,10 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
copy->_Input = _Input;
|
||||
return *copy;
|
||||
}
|
||||
size_t Hash() const
|
||||
{
|
||||
return ::Microsoft::Terminal::Settings::Model::HashUtils::HashProperty(_Input);
|
||||
}
|
||||
};
|
||||
|
||||
struct SplitPaneArgs : public SplitPaneArgsT<SplitPaneArgs>
|
||||
@@ -457,6 +502,10 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
copy->_SplitSize = _SplitSize;
|
||||
return *copy;
|
||||
}
|
||||
size_t Hash() const
|
||||
{
|
||||
return ::Microsoft::Terminal::Settings::Model::HashUtils::HashProperty(_SplitStyle, _TerminalArgs, _SplitMode, _SplitSize);
|
||||
}
|
||||
};
|
||||
|
||||
struct OpenSettingsArgs : public OpenSettingsArgsT<OpenSettingsArgs>
|
||||
@@ -493,6 +542,10 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
copy->_Target = _Target;
|
||||
return *copy;
|
||||
}
|
||||
size_t Hash() const
|
||||
{
|
||||
return ::Microsoft::Terminal::Settings::Model::HashUtils::HashProperty(_Target);
|
||||
}
|
||||
};
|
||||
|
||||
struct SetColorSchemeArgs : public SetColorSchemeArgsT<SetColorSchemeArgs>
|
||||
@@ -533,6 +586,10 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
copy->_SchemeName = _SchemeName;
|
||||
return *copy;
|
||||
}
|
||||
size_t Hash() const
|
||||
{
|
||||
return ::Microsoft::Terminal::Settings::Model::HashUtils::HashProperty(_SchemeName);
|
||||
}
|
||||
};
|
||||
|
||||
struct SetTabColorArgs : public SetTabColorArgsT<SetTabColorArgs>
|
||||
@@ -567,6 +624,10 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
copy->_TabColor = _TabColor;
|
||||
return *copy;
|
||||
}
|
||||
size_t Hash() const
|
||||
{
|
||||
return ::Microsoft::Terminal::Settings::Model::HashUtils::HashProperty(_TabColor);
|
||||
}
|
||||
};
|
||||
|
||||
struct RenameTabArgs : public RenameTabArgsT<RenameTabArgs>
|
||||
@@ -601,6 +662,10 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
copy->_Title = _Title;
|
||||
return *copy;
|
||||
}
|
||||
size_t Hash() const
|
||||
{
|
||||
return ::Microsoft::Terminal::Settings::Model::HashUtils::HashProperty(_Title);
|
||||
}
|
||||
};
|
||||
|
||||
struct ExecuteCommandlineArgs : public ExecuteCommandlineArgsT<ExecuteCommandlineArgs>
|
||||
@@ -641,6 +706,10 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
copy->_Commandline = _Commandline;
|
||||
return *copy;
|
||||
}
|
||||
size_t Hash() const
|
||||
{
|
||||
return ::Microsoft::Terminal::Settings::Model::HashUtils::HashProperty(_Commandline);
|
||||
}
|
||||
};
|
||||
|
||||
struct CloseOtherTabsArgs : public CloseOtherTabsArgsT<CloseOtherTabsArgs>
|
||||
@@ -677,6 +746,10 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
copy->_Index = _Index;
|
||||
return *copy;
|
||||
}
|
||||
size_t Hash() const
|
||||
{
|
||||
return ::Microsoft::Terminal::Settings::Model::HashUtils::HashProperty(_Index);
|
||||
}
|
||||
};
|
||||
|
||||
struct CloseTabsAfterArgs : public CloseTabsAfterArgsT<CloseTabsAfterArgs>
|
||||
@@ -713,6 +786,10 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
copy->_Index = _Index;
|
||||
return *copy;
|
||||
}
|
||||
size_t Hash() const
|
||||
{
|
||||
return ::Microsoft::Terminal::Settings::Model::HashUtils::HashProperty(_Index);
|
||||
}
|
||||
};
|
||||
|
||||
struct MoveTabArgs : public MoveTabArgsT<MoveTabArgs>
|
||||
@@ -756,6 +833,10 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
copy->_Direction = _Direction;
|
||||
return *copy;
|
||||
}
|
||||
size_t Hash() const
|
||||
{
|
||||
return ::Microsoft::Terminal::Settings::Model::HashUtils::HashProperty(_Direction);
|
||||
}
|
||||
};
|
||||
|
||||
struct ScrollUpArgs : public ScrollUpArgsT<ScrollUpArgs>
|
||||
@@ -790,6 +871,10 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
copy->_RowsToScroll = _RowsToScroll;
|
||||
return *copy;
|
||||
}
|
||||
size_t Hash() const
|
||||
{
|
||||
return ::Microsoft::Terminal::Settings::Model::HashUtils::HashProperty(_RowsToScroll);
|
||||
}
|
||||
};
|
||||
|
||||
struct ScrollDownArgs : public ScrollDownArgsT<ScrollDownArgs>
|
||||
@@ -824,6 +909,10 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
copy->_RowsToScroll = _RowsToScroll;
|
||||
return *copy;
|
||||
}
|
||||
size_t Hash() const
|
||||
{
|
||||
return ::Microsoft::Terminal::Settings::Model::HashUtils::HashProperty(_RowsToScroll);
|
||||
}
|
||||
};
|
||||
|
||||
struct ToggleCommandPaletteArgs : public ToggleCommandPaletteArgsT<ToggleCommandPaletteArgs>
|
||||
@@ -860,6 +949,10 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
copy->_LaunchMode = _LaunchMode;
|
||||
return *copy;
|
||||
}
|
||||
size_t Hash() const
|
||||
{
|
||||
return ::Microsoft::Terminal::Settings::Model::HashUtils::HashProperty(_LaunchMode);
|
||||
}
|
||||
};
|
||||
|
||||
struct FindMatchArgs : public FindMatchArgsT<FindMatchArgs>
|
||||
@@ -903,6 +996,10 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
copy->_Direction = _Direction;
|
||||
return *copy;
|
||||
}
|
||||
size_t Hash() const
|
||||
{
|
||||
return ::Microsoft::Terminal::Settings::Model::HashUtils::HashProperty(_Direction);
|
||||
}
|
||||
};
|
||||
|
||||
struct NewWindowArgs : public NewWindowArgsT<NewWindowArgs>
|
||||
@@ -937,6 +1034,10 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
copy->_TerminalArgs = _TerminalArgs.Copy();
|
||||
return *copy;
|
||||
}
|
||||
size_t Hash() const
|
||||
{
|
||||
return ::Microsoft::Terminal::Settings::Model::HashUtils::HashProperty(_TerminalArgs);
|
||||
}
|
||||
};
|
||||
|
||||
struct PrevTabArgs : public PrevTabArgsT<PrevTabArgs>
|
||||
@@ -970,6 +1071,10 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
copy->_SwitcherMode = _SwitcherMode;
|
||||
return *copy;
|
||||
}
|
||||
size_t Hash() const
|
||||
{
|
||||
return ::Microsoft::Terminal::Settings::Model::HashUtils::HashProperty(_SwitcherMode);
|
||||
}
|
||||
};
|
||||
|
||||
struct NextTabArgs : public NextTabArgsT<NextTabArgs>
|
||||
@@ -1003,6 +1108,10 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
copy->_SwitcherMode = _SwitcherMode;
|
||||
return *copy;
|
||||
}
|
||||
size_t Hash() const
|
||||
{
|
||||
return ::Microsoft::Terminal::Settings::Model::HashUtils::HashProperty(_SwitcherMode);
|
||||
}
|
||||
};
|
||||
|
||||
struct RenameWindowArgs : public RenameWindowArgsT<RenameWindowArgs>
|
||||
@@ -1036,6 +1145,10 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
copy->_Name = _Name;
|
||||
return *copy;
|
||||
}
|
||||
size_t Hash() const
|
||||
{
|
||||
return ::Microsoft::Terminal::Settings::Model::HashUtils::HashProperty(_Name);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ namespace Microsoft.Terminal.Settings.Model
|
||||
Boolean Equals(IActionArgs other);
|
||||
String GenerateName();
|
||||
IActionArgs Copy();
|
||||
UInt64 Hash();
|
||||
};
|
||||
|
||||
interface IActionEventArgs
|
||||
@@ -105,6 +106,7 @@ namespace Microsoft.Terminal.Settings.Model
|
||||
Boolean Equals(NewTerminalArgs other);
|
||||
String GenerateName();
|
||||
String ToCommandline();
|
||||
UInt64 Hash();
|
||||
};
|
||||
|
||||
[default_interface] runtimeclass ActionEventArgs : IActionEventArgs
|
||||
|
||||
370
src/cascadia/TerminalSettingsModel/ActionMap.cpp
Normal file
370
src/cascadia/TerminalSettingsModel/ActionMap.cpp
Normal file
@@ -0,0 +1,370 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#include "pch.h"
|
||||
#include "ActionMap.h"
|
||||
|
||||
#include "ActionMap.g.cpp"
|
||||
|
||||
using namespace winrt::Microsoft::Terminal::Settings::Model;
|
||||
using namespace winrt::Microsoft::Terminal::Control;
|
||||
|
||||
namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
{
|
||||
ActionMap::ActionMap() :
|
||||
_NestedCommands{ single_threaded_map<hstring, Model::Command>() }
|
||||
{
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Retrieves the Command in the ActionList, if it's valid
|
||||
// - We internally store invalid commands as full commands.
|
||||
// This helper function returns nullptr when we get an invalid
|
||||
// command. This allows us to simply check for null when we
|
||||
// want a valid command.
|
||||
// Arguments:
|
||||
// - actionID: the internal ID associated with a Command
|
||||
// Return Value:
|
||||
// - If the command is valid, the command itself.
|
||||
// - If the command is explicitly unbound, nullptr.
|
||||
// - If the command cannot be found in this layer, nullopt.
|
||||
std::optional<Model::Command> ActionMap::_GetActionByID(InternalActionID actionID) const
|
||||
{
|
||||
const auto& cmdPair{ _ActionMap.find(actionID) };
|
||||
if (cmdPair == _ActionMap.end())
|
||||
{
|
||||
// we don't have an answer
|
||||
return std::nullopt;
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto& cmd{ cmdPair->second };
|
||||
|
||||
// ActionMap should never point to nullptr
|
||||
FAIL_FAST_IF_NULL(cmd);
|
||||
|
||||
return !cmd.HasNestedCommands() && cmd.ActionAndArgs().Action() == ShortcutAction::Invalid ?
|
||||
nullptr : // explicitly unbound
|
||||
cmd;
|
||||
}
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Retrieves a map of command names to the commands themselves
|
||||
// - These commands should not be modified directly because they may result in
|
||||
// an invalid state for the `ActionMap`
|
||||
Windows::Foundation::Collections::IMapView<hstring, Model::Command> ActionMap::NameMap()
|
||||
{
|
||||
if (!_NameMapCache)
|
||||
{
|
||||
// populate _NameMapCache
|
||||
std::unordered_map<hstring, Model::Command> nameMap{};
|
||||
std::set<InternalActionID> visitedActionIDs{ ActionHash()(make<implementation::ActionAndArgs>()) };
|
||||
_PopulateNameMapWithNestedCommands(nameMap);
|
||||
_PopulateNameMapWithStandardCommands(nameMap, visitedActionIDs);
|
||||
|
||||
_NameMapCache = single_threaded_map<hstring, Model::Command>(std::move(nameMap));
|
||||
}
|
||||
return _NameMapCache.GetView();
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Populates the provided nameMap with all of our nested commands and our parents nested commands
|
||||
// - Performs a top-down approach by going to the root first, then recursively adding the nested commands layer-by-layer
|
||||
// Arguments:
|
||||
// - nameMap: the nameMap we're populating. This maps the name (hstring) of a command to the command itself.
|
||||
void ActionMap::_PopulateNameMapWithNestedCommands(std::unordered_map<hstring, Model::Command>& nameMap) const
|
||||
{
|
||||
// Update NameMap with our parents.
|
||||
// Starting with this means we're doing a top-down approach.
|
||||
for (const auto& parent : _parents)
|
||||
{
|
||||
parent->_PopulateNameMapWithNestedCommands(nameMap);
|
||||
}
|
||||
|
||||
// Add NestedCommands to NameMap _after_ we handle our parents.
|
||||
// This allows us to override whatever our parents tell us.
|
||||
for (const auto& [name, cmd] : _NestedCommands)
|
||||
{
|
||||
if (cmd.HasNestedCommands())
|
||||
{
|
||||
// add a valid cmd
|
||||
nameMap.insert_or_assign(name, cmd);
|
||||
}
|
||||
else
|
||||
{
|
||||
// remove the invalid cmd
|
||||
nameMap.erase(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Populates the provided nameMap with all of our actions and our parents actions
|
||||
// while omitting the actions that were already added before
|
||||
// - This needs to be a bottom up approach to ensure that we only add each action (identified by action ID) once.
|
||||
// Arguments:
|
||||
// - nameMap: the nameMap we're populating. This maps the name (hstring) of a command to the command itself.
|
||||
// There should only ever by one of each command (identified by the actionID) in the nameMap.
|
||||
// - visitedActionIDs: the actionIDs that we've already added to the nameMap. Commands with a matching actionID
|
||||
// have already been added, and should be ignored.
|
||||
void ActionMap::_PopulateNameMapWithStandardCommands(std::unordered_map<hstring, Model::Command>& nameMap, std::set<InternalActionID>& visitedActionIDs) const
|
||||
{
|
||||
// Update NameMap and visitedActionIDs with our current layer
|
||||
for (const auto& [actionID, cmd] : _ActionMap)
|
||||
{
|
||||
// Only populate NameMap with actions that haven't been visited already.
|
||||
if (visitedActionIDs.find(actionID) == visitedActionIDs.end())
|
||||
{
|
||||
const auto& name{ cmd.Name() };
|
||||
if (!name.empty())
|
||||
{
|
||||
// Update NameMap.
|
||||
nameMap.insert_or_assign(name, cmd);
|
||||
}
|
||||
|
||||
// Record that we already handled adding this action to the NameMap.
|
||||
visitedActionIDs.insert(actionID);
|
||||
}
|
||||
}
|
||||
|
||||
// Update NameMap and visitedActionIDs with our parents
|
||||
for (const auto& parent : _parents)
|
||||
{
|
||||
parent->_PopulateNameMapWithStandardCommands(nameMap, visitedActionIDs);
|
||||
}
|
||||
}
|
||||
|
||||
com_ptr<ActionMap> ActionMap::Copy() const
|
||||
{
|
||||
auto actionMap{ make_self<ActionMap>() };
|
||||
|
||||
// copy _KeyMap (KeyChord --> ID)
|
||||
std::for_each(_KeyMap.begin(), _KeyMap.end(), [actionMap](const auto& pair) {
|
||||
actionMap->_KeyMap.insert(pair);
|
||||
});
|
||||
|
||||
// copy _ActionMap (ID --> Command)
|
||||
for (const auto& [actionID, cmd] : _ActionMap)
|
||||
{
|
||||
actionMap->_ActionMap.insert({ actionID, *(get_self<Command>(cmd)->Copy()) });
|
||||
}
|
||||
|
||||
// copy _NestedCommands (Name --> Command)
|
||||
for (const auto& [name, cmd] : _NestedCommands)
|
||||
{
|
||||
actionMap->_NestedCommands.Insert(name, *(get_self<Command>(cmd)->Copy()));
|
||||
}
|
||||
|
||||
// repeat this for each of our parents
|
||||
for (const auto& parent : _parents)
|
||||
{
|
||||
actionMap->_parents.push_back(std::move(parent->Copy()));
|
||||
}
|
||||
|
||||
return actionMap;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Adds a command to the ActionMap
|
||||
// Arguments:
|
||||
// - cmd: the command we're adding
|
||||
void ActionMap::AddAction(const Model::Command& cmd)
|
||||
{
|
||||
// _Never_ add null to the ActionMap
|
||||
if (!cmd)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle nested commands
|
||||
const auto cmdImpl{ get_self<Command>(cmd) };
|
||||
if (cmdImpl->IsNestedCommand())
|
||||
{
|
||||
// But check if it actually has a name to bind to first
|
||||
const auto name{ cmd.Name() };
|
||||
if (!name.empty())
|
||||
{
|
||||
_NestedCommands.Insert(name, cmd);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// General Case:
|
||||
// Add the new command to the NameMap and KeyMap (whichever is applicable).
|
||||
// These maps direct you to an entry in the ActionMap.
|
||||
|
||||
// Removing Actions from the Command Palette:
|
||||
// cmd.Name and cmd.Action have a one-to-one relationship.
|
||||
// If cmd.Name is empty, we must retrieve the old name and remove it.
|
||||
|
||||
// Removing Key Bindings:
|
||||
// cmd.Keys and cmd.Action have a many-to-one relationship.
|
||||
// If cmd.Keys is empty, we don't care.
|
||||
// If action is "unbound"/"invalid", you're explicitly unbinding the provided cmd.keys.
|
||||
|
||||
Model::Command oldCmd{ nullptr };
|
||||
const auto actionID{ ActionHash()(cmd.ActionAndArgs()) };
|
||||
auto actionPair{ _ActionMap.find(actionID) };
|
||||
if (actionPair != _ActionMap.end())
|
||||
{
|
||||
// We're adding an action that already exists.
|
||||
// Record it and update it with any new information.
|
||||
oldCmd = actionPair->second;
|
||||
|
||||
// Update Name
|
||||
const auto cmdImpl{ get_self<Command>(cmd) };
|
||||
if (cmdImpl->HasName())
|
||||
{
|
||||
// This command has a name, check if it's new.
|
||||
const auto newName{ cmd.Name() };
|
||||
if (newName != oldCmd.Name())
|
||||
{
|
||||
// The new name differs from the old name,
|
||||
// update our name.
|
||||
auto oldCmdImpl{ get_self<Command>(oldCmd) };
|
||||
oldCmdImpl->Name(newName);
|
||||
}
|
||||
|
||||
// Handle a collision with NestedCommands
|
||||
_NestedCommands.TryRemove(newName);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// add this action in for the first time
|
||||
_ActionMap.insert({ actionID, cmd });
|
||||
|
||||
// Handle a collision with NestedCommands
|
||||
_NestedCommands.TryRemove(cmd.Name());
|
||||
}
|
||||
|
||||
// Update KeyMap
|
||||
if (const auto keys{ cmd.Keys() })
|
||||
{
|
||||
const auto oldKeyPair{ _KeyMap.find(keys) };
|
||||
if (oldKeyPair != _KeyMap.end())
|
||||
{
|
||||
// Collision: The key chord was already in use.
|
||||
// Remove the old one.
|
||||
actionPair = _ActionMap.find(oldKeyPair->second);
|
||||
const auto& conflictingCmd{ actionPair->second };
|
||||
const auto& conflictingCmdImpl{ get_self<implementation::Command>(conflictingCmd) };
|
||||
conflictingCmdImpl->EraseKey(keys);
|
||||
}
|
||||
|
||||
// Assign the new action.
|
||||
_KeyMap.insert_or_assign(keys, actionID);
|
||||
|
||||
if (oldCmd)
|
||||
{
|
||||
// Update inner Command with new key chord
|
||||
auto oldCmdImpl{ get_self<Command>(oldCmd) };
|
||||
oldCmdImpl->RegisterKey(keys);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Retrieves the assigned command that can be invoked with the given key chord
|
||||
// Arguments:
|
||||
// - keys: the key chord of the command to search for
|
||||
// Return Value:
|
||||
// - the command with the given key chord
|
||||
// - nullptr if the key chord is explicitly unbound
|
||||
Model::Command ActionMap::GetActionByKeyChord(Control::KeyChord const& keys) const
|
||||
{
|
||||
// Check the current layer
|
||||
const auto& cmd{ _GetActionByKeyChordInternal(keys) };
|
||||
if (cmd.has_value())
|
||||
{
|
||||
return *cmd;
|
||||
}
|
||||
|
||||
// This key chord is not explicitly bound
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Retrieves the assigned command with the given key chord.
|
||||
// - Can return nullopt to differentiate explicit unbinding vs lack of binding.
|
||||
// Arguments:
|
||||
// - keys: the key chord of the command to search for
|
||||
// Return Value:
|
||||
// - the command with the given key chord
|
||||
// - nullptr if the key chord is explicitly unbound
|
||||
// - nullopt if it was not bound in this layer
|
||||
std::optional<Model::Command> ActionMap::_GetActionByKeyChordInternal(Control::KeyChord const& keys) const
|
||||
{
|
||||
// Check the current layer
|
||||
const auto actionIDPair{ _KeyMap.find(keys) };
|
||||
if (actionIDPair != _KeyMap.end())
|
||||
{
|
||||
// the command was explicitly bound,
|
||||
// return what we found (invalid commands exposed as nullptr)
|
||||
return _GetActionByID(actionIDPair->second);
|
||||
}
|
||||
|
||||
// the command was not bound in this layer,
|
||||
// ask my parents
|
||||
for (const auto& parent : _parents)
|
||||
{
|
||||
const auto& inheritedCmd{ parent->_GetActionByKeyChordInternal(keys) };
|
||||
if (inheritedCmd.has_value())
|
||||
{
|
||||
return *inheritedCmd;
|
||||
}
|
||||
}
|
||||
|
||||
// This action is not explicitly bound
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Retrieves the key chord for the provided action
|
||||
// Arguments:
|
||||
// - action: the shortcut action (an action type) we're looking for
|
||||
// Return Value:
|
||||
// - the key chord that executes the given action
|
||||
// - nullptr if the action is not bound to a key chord
|
||||
Control::KeyChord ActionMap::GetKeyBindingForAction(ShortcutAction const& action) const
|
||||
{
|
||||
return GetKeyBindingForAction(action, nullptr);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Retrieves the key chord for the provided action
|
||||
// Arguments:
|
||||
// - action: the shortcut action (an action type) we're looking for
|
||||
// - myArgs: the action args for the action we're looking for
|
||||
// Return Value:
|
||||
// - the key chord that executes the given action
|
||||
// - nullptr if the action is not bound to a key chord
|
||||
Control::KeyChord ActionMap::GetKeyBindingForAction(ShortcutAction const& myAction, IActionArgs const& myArgs) const
|
||||
{
|
||||
if (myAction == ShortcutAction::Invalid)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Check our internal state.
|
||||
const ActionAndArgs& actionAndArgs{ myAction, myArgs };
|
||||
const auto hash{ ActionHash()(actionAndArgs) };
|
||||
if (const auto& cmd{ _GetActionByID(hash) })
|
||||
{
|
||||
return cmd.value().Keys();
|
||||
}
|
||||
|
||||
// Check our parents
|
||||
for (const auto& parent : _parents)
|
||||
{
|
||||
if (const auto& keys{ parent->GetKeyBindingForAction(myAction, myArgs) })
|
||||
{
|
||||
return keys;
|
||||
}
|
||||
}
|
||||
|
||||
// This key binding does not exist
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
107
src/cascadia/TerminalSettingsModel/ActionMap.h
Normal file
107
src/cascadia/TerminalSettingsModel/ActionMap.h
Normal file
@@ -0,0 +1,107 @@
|
||||
/*++
|
||||
Copyright (c) Microsoft Corporation
|
||||
Licensed under the MIT license.
|
||||
|
||||
Module Name:
|
||||
- ActionMap.h
|
||||
|
||||
Abstract:
|
||||
- A mapping of key chords to actions. Includes (de)serialization logic.
|
||||
|
||||
Author(s):
|
||||
- Carlos Zamora - September 2020
|
||||
|
||||
--*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ActionMap.g.h"
|
||||
#include "IInheritable.h"
|
||||
#include "Command.h"
|
||||
#include "../inc/cppwinrt_utils.h"
|
||||
|
||||
// fwdecl unittest classes
|
||||
namespace SettingsModelLocalTests
|
||||
{
|
||||
class KeyBindingsTests;
|
||||
class DeserializationTests;
|
||||
class TerminalSettingsTests;
|
||||
}
|
||||
|
||||
namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
{
|
||||
typedef size_t InternalActionID;
|
||||
|
||||
struct KeyChordHash
|
||||
{
|
||||
std::size_t operator()(const Control::KeyChord& key) const
|
||||
{
|
||||
return ::Microsoft::Terminal::Settings::Model::HashUtils::HashProperty(key.Modifiers(), key.Vkey());
|
||||
}
|
||||
};
|
||||
|
||||
struct KeyChordEquality
|
||||
{
|
||||
bool operator()(const Control::KeyChord& lhs, const Control::KeyChord& rhs) const
|
||||
{
|
||||
return lhs.Modifiers() == rhs.Modifiers() && lhs.Vkey() == rhs.Vkey();
|
||||
}
|
||||
};
|
||||
|
||||
struct ActionHash
|
||||
{
|
||||
InternalActionID operator()(const Model::ActionAndArgs& actionAndArgs) const
|
||||
{
|
||||
std::hash<Model::ShortcutAction> actionHash;
|
||||
std::size_t hashedAction{ actionHash(actionAndArgs.Action()) };
|
||||
|
||||
std::size_t hashedArgs;
|
||||
if (const auto& args{ actionAndArgs.Args() })
|
||||
{
|
||||
hashedArgs = gsl::narrow_cast<size_t>(args.Hash());
|
||||
}
|
||||
else
|
||||
{
|
||||
std::hash<IActionArgs> argsHash;
|
||||
hashedArgs = argsHash(nullptr);
|
||||
}
|
||||
return hashedAction ^ hashedArgs;
|
||||
}
|
||||
};
|
||||
|
||||
struct ActionMap : ActionMapT<ActionMap>, IInheritable<ActionMap>
|
||||
{
|
||||
ActionMap();
|
||||
|
||||
// views
|
||||
Windows::Foundation::Collections::IMapView<hstring, Model::Command> NameMap();
|
||||
com_ptr<ActionMap> Copy() const;
|
||||
|
||||
// queries
|
||||
Model::Command GetActionByKeyChord(Control::KeyChord const& keys) const;
|
||||
Control::KeyChord GetKeyBindingForAction(ShortcutAction const& action) const;
|
||||
Control::KeyChord GetKeyBindingForAction(ShortcutAction const& action, IActionArgs const& actionArgs) const;
|
||||
|
||||
// population
|
||||
void AddAction(const Model::Command& cmd);
|
||||
std::vector<SettingsLoadWarnings> LayerJson(const Json::Value& json);
|
||||
|
||||
static Windows::System::VirtualKeyModifiers ConvertVKModifiers(Control::KeyModifiers modifiers);
|
||||
|
||||
private:
|
||||
std::optional<Model::Command> _GetActionByID(InternalActionID actionID) const;
|
||||
std::optional<Model::Command> _GetActionByKeyChordInternal(Control::KeyChord const& keys) const;
|
||||
|
||||
void _PopulateNameMapWithNestedCommands(std::unordered_map<hstring, Model::Command>& nameMap) const;
|
||||
void _PopulateNameMapWithStandardCommands(std::unordered_map<hstring, Model::Command>& nameMap, std::set<InternalActionID>& visitedActionIDs) const;
|
||||
|
||||
Windows::Foundation::Collections::IMap<hstring, Model::Command> _NameMapCache{ nullptr };
|
||||
Windows::Foundation::Collections::IMap<hstring, Model::Command> _NestedCommands{ nullptr };
|
||||
std::unordered_map<Control::KeyChord, InternalActionID, KeyChordHash, KeyChordEquality> _KeyMap;
|
||||
std::unordered_map<InternalActionID, Model::Command> _ActionMap;
|
||||
|
||||
friend class SettingsModelLocalTests::KeyBindingsTests;
|
||||
friend class SettingsModelLocalTests::DeserializationTests;
|
||||
friend class SettingsModelLocalTests::TerminalSettingsTests;
|
||||
};
|
||||
}
|
||||
16
src/cascadia/TerminalSettingsModel/ActionMap.idl
Normal file
16
src/cascadia/TerminalSettingsModel/ActionMap.idl
Normal file
@@ -0,0 +1,16 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import "Command.idl";
|
||||
|
||||
namespace Microsoft.Terminal.Settings.Model
|
||||
{
|
||||
[default_interface] runtimeclass ActionMap {
|
||||
Command GetActionByKeyChord(Microsoft.Terminal.Control.KeyChord keys);
|
||||
|
||||
Microsoft.Terminal.Control.KeyChord GetKeyBindingForAction(ShortcutAction action);
|
||||
Microsoft.Terminal.Control.KeyChord GetKeyBindingForAction(ShortcutAction action, IActionArgs actionArgs);
|
||||
|
||||
Windows.Foundation.Collections.IMapView<String, Command> NameMap { get; };
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
// - A couple helper functions for serializing/deserializing a KeyMapping
|
||||
// to/from json.
|
||||
//
|
||||
// Author(s):
|
||||
// - Mike Griese - May 2019
|
||||
|
||||
#include "pch.h"
|
||||
#include "ActionMap.h"
|
||||
#include "ActionAndArgs.h"
|
||||
#include "KeyChordSerialization.h"
|
||||
#include "JsonUtils.h"
|
||||
|
||||
#include "Command.h"
|
||||
|
||||
using namespace winrt::Microsoft::Terminal::Control;
|
||||
using namespace winrt::Microsoft::Terminal::Settings::Model;
|
||||
|
||||
namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
{
|
||||
// Method Description:
|
||||
// - Deserialize an ActionMap from the array `json`. The json array should contain
|
||||
// an array of serialized `Command` objects.
|
||||
// - These actions are added to the `ActionMap`, where we automatically handle
|
||||
// overwriting and unbinding actions.
|
||||
// Arguments:
|
||||
// - json: an array of Json::Value's to deserialize into our ActionMap.
|
||||
// Return value:
|
||||
// - a list of warnings encountered while deserializing the json
|
||||
std::vector<SettingsLoadWarnings> ActionMap::LayerJson(const Json::Value& json)
|
||||
{
|
||||
// It's possible that the user provided keybindings have some warnings in
|
||||
// them - problems that we should alert the user to, but we can recover
|
||||
// from. Most of these warnings cannot be detected later in the Validate
|
||||
// settings phase, so we'll collect them now.
|
||||
std::vector<SettingsLoadWarnings> warnings;
|
||||
|
||||
for (const auto& cmdJson : json)
|
||||
{
|
||||
if (!cmdJson.isObject())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
AddAction(*Command::FromJson(cmdJson, warnings));
|
||||
}
|
||||
|
||||
return warnings;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Takes the KeyModifier flags from Terminal and maps them to the WinRT types which are used by XAML
|
||||
// Return Value:
|
||||
// - a Windows::System::VirtualKeyModifiers object with the flags of which modifiers used.
|
||||
Windows::System::VirtualKeyModifiers ActionMap::ConvertVKModifiers(KeyModifiers modifiers)
|
||||
{
|
||||
Windows::System::VirtualKeyModifiers keyModifiers = Windows::System::VirtualKeyModifiers::None;
|
||||
|
||||
if (WI_IsFlagSet(modifiers, KeyModifiers::Ctrl))
|
||||
{
|
||||
keyModifiers |= Windows::System::VirtualKeyModifiers::Control;
|
||||
}
|
||||
if (WI_IsFlagSet(modifiers, KeyModifiers::Shift))
|
||||
{
|
||||
keyModifiers |= Windows::System::VirtualKeyModifiers::Shift;
|
||||
}
|
||||
if (WI_IsFlagSet(modifiers, KeyModifiers::Alt))
|
||||
{
|
||||
// note: Menu is the Alt VK_MENU
|
||||
keyModifiers |= Windows::System::VirtualKeyModifiers::Menu;
|
||||
}
|
||||
if (WI_IsFlagSet(modifiers, KeyModifiers::Windows))
|
||||
{
|
||||
keyModifiers |= Windows::System::VirtualKeyModifiers::Windows;
|
||||
}
|
||||
|
||||
return keyModifiers;
|
||||
}
|
||||
}
|
||||
@@ -186,9 +186,9 @@ IObservableVector<winrt::Microsoft::Terminal::Settings::Model::Profile> Cascadia
|
||||
// - <none>
|
||||
// Return Value:
|
||||
// - the globally configured keybindings
|
||||
winrt::Microsoft::Terminal::Settings::Model::KeyMapping CascadiaSettings::KeyMap() const noexcept
|
||||
winrt::Microsoft::Terminal::Settings::Model::ActionMap CascadiaSettings::ActionMap() const noexcept
|
||||
{
|
||||
return _globals->KeyMap();
|
||||
return _globals->ActionMap();
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
@@ -780,7 +780,7 @@ void CascadiaSettings::_ValidateKeybindings()
|
||||
void CascadiaSettings::_ValidateColorSchemesInCommands()
|
||||
{
|
||||
bool foundInvalidScheme{ false };
|
||||
for (const auto& nameAndCmd : _globals->Commands())
|
||||
for (const auto& nameAndCmd : _globals->ActionMap().NameMap())
|
||||
{
|
||||
if (_HasInvalidColorScheme(nameAndCmd.Value()))
|
||||
{
|
||||
@@ -809,7 +809,7 @@ bool CascadiaSettings::_HasInvalidColorScheme(const Model::Command& command)
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (const auto& actionAndArgs = command.Action())
|
||||
else if (const auto& actionAndArgs = command.ActionAndArgs())
|
||||
{
|
||||
if (const auto& realArgs = actionAndArgs.Args().try_as<Model::SetColorSchemeArgs>())
|
||||
{
|
||||
|
||||
@@ -70,7 +70,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
Model::GlobalAppSettings GlobalSettings() const;
|
||||
Windows::Foundation::Collections::IObservableVector<Model::Profile> AllProfiles() const noexcept;
|
||||
Windows::Foundation::Collections::IObservableVector<Model::Profile> ActiveProfiles() const noexcept;
|
||||
Model::KeyMapping KeyMap() const noexcept;
|
||||
Model::ActionMap ActionMap() const noexcept;
|
||||
|
||||
static com_ptr<CascadiaSettings> FromJson(const Json::Value& json);
|
||||
void LayerJson(const Json::Value& json);
|
||||
|
||||
@@ -30,7 +30,7 @@ namespace Microsoft.Terminal.Settings.Model
|
||||
Windows.Foundation.Collections.IObservableVector<Profile> AllProfiles { get; };
|
||||
Windows.Foundation.Collections.IObservableVector<Profile> ActiveProfiles { get; };
|
||||
|
||||
KeyMapping KeyMap { get; };
|
||||
ActionMap ActionMap { get; };
|
||||
|
||||
Windows.Foundation.Collections.IVectorView<SettingsLoadWarnings> Warnings { get; };
|
||||
Windows.Foundation.IReference<SettingsLoadErrors> GetLoadingError { get; };
|
||||
|
||||
@@ -248,57 +248,6 @@ winrt::Microsoft::Terminal::Settings::Model::CascadiaSettings CascadiaSettings::
|
||||
// If this throws, the app will catch it and use the default settings
|
||||
resultPtr->_ValidateSettings();
|
||||
|
||||
// GH 3855 - Gathering Data on custom profiles to inform better defaults
|
||||
// Do it after everything else so it won't happen unless validation passed.
|
||||
// Also, avoid processing unless someone's listening for measures. The keybindings work, at least,
|
||||
// is a lot of computation we can skip if no one cares.
|
||||
if (TraceLoggingProviderEnabled(g_hSettingsModelProvider, 0, MICROSOFT_KEYWORD_MEASURES))
|
||||
{
|
||||
const auto guid = resultPtr->GlobalSettings().DefaultProfile();
|
||||
|
||||
// Compare to the defaults.json one that we set on install.
|
||||
// If it's different, log what the user chose.
|
||||
if (hardcodedDefaultGuid != guid)
|
||||
{
|
||||
TraceLoggingWrite(
|
||||
g_hSettingsModelProvider, // handle to TerminalApp tracelogging provider
|
||||
"CustomDefaultProfile",
|
||||
TraceLoggingDescription("Event emitted when user has chosen a different default profile than hardcoded one on load/reload"),
|
||||
TraceLoggingGuid(guid, "DefaultProfile", "ID of user-chosen default profile"),
|
||||
TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES),
|
||||
TelemetryPrivacyDataTag(PDT_ProductAndServiceUsage));
|
||||
}
|
||||
|
||||
// If the user had keybinding settings preferences, we want to learn from them to make better defaults
|
||||
auto userKeybindings = resultPtr->_userSettings[JsonKey(LegacyKeybindingsKey)];
|
||||
if (!userKeybindings.empty())
|
||||
{
|
||||
// If there are custom key bindings, let's understand what they are because maybe the defaults aren't good enough
|
||||
|
||||
// Run it through the object so we can parse it apart and then only serialize the fields we're interested in
|
||||
// and avoid extraneous data.
|
||||
auto km = winrt::make_self<implementation::KeyMapping>();
|
||||
km->LayerJson(userKeybindings);
|
||||
auto value = km->ToJson();
|
||||
|
||||
// Reserialize the keybindings
|
||||
Json::StreamWriterBuilder wbuilder;
|
||||
// Use 4 spaces to indent instead of \t
|
||||
wbuilder.settings_["indentation"] = " ";
|
||||
wbuilder.settings_["enableYAMLCompatibility"] = true; // suppress spaces around colons
|
||||
|
||||
const auto keybindingsString = Json::writeString(wbuilder, value);
|
||||
|
||||
TraceLoggingWrite(
|
||||
g_hSettingsModelProvider, // handle to TerminalApp tracelogging provider
|
||||
"CustomKeybindings",
|
||||
TraceLoggingDescription("Event emitted when custom keybindings are identified on load/reload"),
|
||||
TraceLoggingUtf8String(keybindingsString.c_str(), "Keybindings", "Keybindings as JSON"),
|
||||
TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES),
|
||||
TelemetryPrivacyDataTag(PDT_ProductAndServiceUsage));
|
||||
}
|
||||
}
|
||||
|
||||
return *resultPtr;
|
||||
}
|
||||
catch (const SettingsException& ex)
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
#include "Command.g.cpp"
|
||||
|
||||
#include "ActionAndArgs.h"
|
||||
#include "JsonUtils.h"
|
||||
#include "KeyChordSerialization.h"
|
||||
#include <LibraryResources.h>
|
||||
#include "TerminalSettingsSerializationHelpers.h"
|
||||
|
||||
@@ -26,6 +26,7 @@ static constexpr std::string_view ActionKey{ "command" };
|
||||
static constexpr std::string_view ArgsKey{ "args" };
|
||||
static constexpr std::string_view IterateOnKey{ "iterateOn" };
|
||||
static constexpr std::string_view CommandsKey{ "commands" };
|
||||
static constexpr std::string_view KeysKey{ "keys" };
|
||||
|
||||
static constexpr std::string_view ProfileNameToken{ "${profile.name}" };
|
||||
static constexpr std::string_view ProfileIconToken{ "${profile.icon}" };
|
||||
@@ -35,16 +36,22 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
{
|
||||
Command::Command()
|
||||
{
|
||||
_setAction(nullptr);
|
||||
}
|
||||
|
||||
com_ptr<Command> Command::Copy() const
|
||||
{
|
||||
auto command{ winrt::make_self<Command>() };
|
||||
command->_Name = _Name;
|
||||
command->_Action = _Action;
|
||||
command->_KeyChordText = _KeyChordText;
|
||||
command->_IconPath = _IconPath;
|
||||
command->_name = _name;
|
||||
|
||||
// TODO GH#6900: We probably want ActionAndArgs::Copy here
|
||||
// This is fine for now because SUI can't actually
|
||||
// modify the copy yet.
|
||||
command->_ActionAndArgs = _ActionAndArgs;
|
||||
for (const auto& keys : _keyMappings)
|
||||
{
|
||||
command->_keyMappings.emplace_back(keys.Modifiers(), keys.Vkey());
|
||||
}
|
||||
command->_iconPath = _iconPath;
|
||||
command->_IterateOn = _IterateOn;
|
||||
|
||||
command->_originalJson = _originalJson;
|
||||
@@ -65,10 +72,158 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
return _subcommands ? _subcommands.GetView() : nullptr;
|
||||
}
|
||||
|
||||
// Function Description:
|
||||
// - reports if the current command has nested commands
|
||||
// - This CANNOT detect { "name": "foo", "commands": null }
|
||||
bool Command::HasNestedCommands() const
|
||||
{
|
||||
return _subcommands ? _subcommands.Size() > 0 : false;
|
||||
}
|
||||
|
||||
// Function Description:
|
||||
// - reports if the current command IS a nested command
|
||||
// - This CAN be used to detect cases like { "name": "foo", "commands": null }
|
||||
bool Command::IsNestedCommand() const noexcept
|
||||
{
|
||||
return _nestedCommand;
|
||||
}
|
||||
|
||||
bool Command::HasName() const noexcept
|
||||
{
|
||||
return _name.has_value();
|
||||
}
|
||||
|
||||
hstring Command::Name() const noexcept
|
||||
{
|
||||
if (_name.has_value())
|
||||
{
|
||||
// name was explicitly set, return that value.
|
||||
return hstring{ _name.value() };
|
||||
}
|
||||
else if (_ActionAndArgs)
|
||||
{
|
||||
// generate a name from our action
|
||||
return get_self<implementation::ActionAndArgs>(_ActionAndArgs)->GenerateName();
|
||||
}
|
||||
else
|
||||
{
|
||||
// we have no name
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
void Command::Name(const hstring& value)
|
||||
{
|
||||
if (!_name.has_value() || _name.value() != value)
|
||||
{
|
||||
_name = value;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<Control::KeyChord> Command::KeyMappings() const noexcept
|
||||
{
|
||||
return _keyMappings;
|
||||
}
|
||||
|
||||
// Function Description:
|
||||
// - Add the key chord to the command's list of key mappings.
|
||||
// - If the key chord was already registered, move it to the back
|
||||
// of the line, and dispatch a notification that Command::Keys changed.
|
||||
// Arguments:
|
||||
// - keys: the new key chord that we are registering this command to
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void Command::RegisterKey(const Control::KeyChord& keys)
|
||||
{
|
||||
if (!keys)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if we registered this key chord before
|
||||
for (auto pos = _keyMappings.begin(); pos < _keyMappings.end(); ++pos)
|
||||
{
|
||||
if (keys.Modifiers() == pos->Modifiers() && keys.Vkey() == pos->Vkey())
|
||||
{
|
||||
// KeyChord was already registered.
|
||||
if (*pos == _keyMappings.back())
|
||||
{
|
||||
// It's already the latest key registered.
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Move the new KeyChord to the back of the line.
|
||||
_keyMappings.erase(pos);
|
||||
_keyMappings.push_back(*pos);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add the KeyChord to the back of the line.
|
||||
_keyMappings.push_back(keys);
|
||||
}
|
||||
|
||||
// Function Description:
|
||||
// - Remove the key chord from the command's list of key mappings.
|
||||
// Arguments:
|
||||
// - keys: the key chord that we are unregistering
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void Command::EraseKey(const Control::KeyChord& keys)
|
||||
{
|
||||
for (auto pos = _keyMappings.begin(); pos < _keyMappings.end(); ++pos)
|
||||
{
|
||||
if (keys.Modifiers() == pos->Modifiers() && keys.Vkey() == pos->Vkey())
|
||||
{
|
||||
// Found the KeyChord, remove it.
|
||||
_keyMappings.erase(pos);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Function Description:
|
||||
// - Keys is the Command's identifying KeyChord. The command may have multiple keys associated
|
||||
// with it, but we'll only ever display the most recently added one externally. To do this,
|
||||
// _keyMappings stores all of the associated key chords, but ensures that the last entry
|
||||
// is the most recently added one.
|
||||
// Arguments:
|
||||
// - <none>
|
||||
// Return Value:
|
||||
// - the primary key chord associated with this Command
|
||||
Control::KeyChord Command::Keys() const noexcept
|
||||
{
|
||||
if (_keyMappings.empty())
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
return _keyMappings.back();
|
||||
}
|
||||
|
||||
hstring Command::KeyChordText() const noexcept
|
||||
{
|
||||
return KeyChordSerialization::ToString(Keys());
|
||||
}
|
||||
|
||||
hstring Command::IconPath() const noexcept
|
||||
{
|
||||
if (_iconPath.has_value())
|
||||
{
|
||||
return hstring{ *_iconPath };
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
void Command::IconPath(const hstring& val)
|
||||
{
|
||||
if (!_iconPath.has_value() || _iconPath.value() != val)
|
||||
{
|
||||
_iconPath = val;
|
||||
}
|
||||
}
|
||||
|
||||
// Function Description:
|
||||
// - attempt to get the name of this command from the provided json object.
|
||||
// * If the "name" property is a string, return that value.
|
||||
@@ -79,7 +234,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
// - json: The Json::Value representing the command object we should get the name for.
|
||||
// Return Value:
|
||||
// - the empty string if we couldn't find a name, otherwise the command's name.
|
||||
static winrt::hstring _nameFromJson(const Json::Value& json)
|
||||
static std::optional<std::wstring> _nameFromJson(const Json::Value& json)
|
||||
{
|
||||
if (const auto name{ json[JsonKey(NameKey)] })
|
||||
{
|
||||
@@ -89,43 +244,23 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
{
|
||||
if (HasLibraryResourceWithName(*resourceKey))
|
||||
{
|
||||
return GetLibraryResourceString(*resourceKey);
|
||||
return std::wstring{ GetLibraryResourceString(*resourceKey) };
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (name.isString())
|
||||
{
|
||||
return JsonUtils::GetValue<winrt::hstring>(name);
|
||||
return JsonUtils::GetValue<std::wstring>(name);
|
||||
}
|
||||
}
|
||||
|
||||
return L"";
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Get the name for the command specified in `json`. If there is no "name"
|
||||
// property in the provided json object, then instead generate a name for
|
||||
// the provided ActionAndArgs.
|
||||
// Arguments:
|
||||
// - json: json for the command to generate a name for.
|
||||
// - actionAndArgs: An ActionAndArgs object to use to generate a name for,
|
||||
// if the json object doesn't contain a "name".
|
||||
// Return Value:
|
||||
// - The "name" from the json, or the generated name from ActionAndArgs::GenerateName
|
||||
static winrt::hstring _nameFromJsonOrAction(const Json::Value& json,
|
||||
winrt::com_ptr<ActionAndArgs> actionAndArgs)
|
||||
{
|
||||
auto manualName = _nameFromJson(json);
|
||||
if (!manualName.empty())
|
||||
else if (json.isMember(JsonKey(NameKey)))
|
||||
{
|
||||
return manualName;
|
||||
}
|
||||
if (!actionAndArgs)
|
||||
{
|
||||
return L"";
|
||||
// { "name": null, "command": "copy" } will land in this case, which
|
||||
// should also be used for unbinding.
|
||||
return std::wstring{};
|
||||
}
|
||||
|
||||
return actionAndArgs->GenerateName();
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
@@ -158,6 +293,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
{
|
||||
// Initialize our list of subcommands.
|
||||
result->_subcommands = winrt::single_threaded_map<winrt::hstring, Model::Command>();
|
||||
result->_nestedCommand = true;
|
||||
auto nestedWarnings = Command::LayerJson(result->_subcommands, nestedCommandsJson);
|
||||
// It's possible that the nested commands have some warnings
|
||||
warnings.insert(warnings.end(), nestedWarnings.begin(), nestedWarnings.end());
|
||||
@@ -165,7 +301,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
if (result->_subcommands.Size() == 0)
|
||||
{
|
||||
warnings.push_back(SettingsLoadWarnings::FailedToParseSubCommands);
|
||||
return nullptr;
|
||||
result->_ActionAndArgs = make<implementation::ActionAndArgs>();
|
||||
}
|
||||
|
||||
nested = true;
|
||||
@@ -174,59 +310,60 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
{
|
||||
// { "name": "foo", "commands": null } will land in this case, which
|
||||
// should also be used for unbinding.
|
||||
return nullptr;
|
||||
|
||||
// create an "invalid" ActionAndArgs
|
||||
result->_ActionAndArgs = make<implementation::ActionAndArgs>();
|
||||
result->_nestedCommand = true;
|
||||
}
|
||||
|
||||
JsonUtils::GetValueForKey(json, IconKey, result->_IconPath);
|
||||
JsonUtils::GetValueForKey(json, IconKey, result->_iconPath);
|
||||
|
||||
// If we're a nested command, we can ignore the current action.
|
||||
if (!nested)
|
||||
{
|
||||
if (const auto actionJson{ json[JsonKey(ActionKey)] })
|
||||
{
|
||||
auto actionAndArgs = ActionAndArgs::FromJson(actionJson, warnings);
|
||||
|
||||
if (actionAndArgs)
|
||||
{
|
||||
result->_setAction(*actionAndArgs);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Something like
|
||||
// { name: "foo", action: "unbound" }
|
||||
// will _remove_ the "foo" command, by returning null here.
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// If an iterable command doesn't have a name set, we'll still just
|
||||
// try and generate a fake name for the command give the string we
|
||||
// currently have. It'll probably generate something like "New tab,
|
||||
// profile: ${profile.name}". This string will only be temporarily
|
||||
// used internally, so there's no problem.
|
||||
result->_setName(_nameFromJsonOrAction(json, actionAndArgs));
|
||||
result->_ActionAndArgs = *ActionAndArgs::FromJson(actionJson, warnings);
|
||||
}
|
||||
else
|
||||
{
|
||||
// { name: "foo", action: null } will land in this case, which
|
||||
// should also be used for unbinding.
|
||||
return nullptr;
|
||||
|
||||
// create an "invalid" ActionAndArgs
|
||||
result->_ActionAndArgs = make<implementation::ActionAndArgs>();
|
||||
}
|
||||
|
||||
// GH#4239 - If the user provided more than one key
|
||||
// chord to a "keys" array, warn the user here.
|
||||
// TODO: GH#1334 - remove this check.
|
||||
const auto keysJson{ json[JsonKey(KeysKey)] };
|
||||
if (keysJson.isArray() && keysJson.size() > 1)
|
||||
{
|
||||
warnings.push_back(SettingsLoadWarnings::TooManyKeysForChord);
|
||||
}
|
||||
else
|
||||
{
|
||||
Control::KeyChord keys{ nullptr };
|
||||
if (JsonUtils::GetValueForKey(json, KeysKey, keys))
|
||||
{
|
||||
result->RegisterKey(keys);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result->_setName(_nameFromJson(json));
|
||||
}
|
||||
|
||||
// If an iterable command doesn't have a name set, we'll still just
|
||||
// try and generate a fake name for the command give the string we
|
||||
// currently have. It'll probably generate something like "New tab,
|
||||
// profile: ${profile.name}". This string will only be temporarily
|
||||
// used internally, so there's no problem.
|
||||
result->_name = _nameFromJson(json);
|
||||
|
||||
// Stash the original json value in this object. If the command is
|
||||
// iterable, we'll need to re-parse it later, once we know what all the
|
||||
// values we can iterate on are.
|
||||
result->_originalJson = json;
|
||||
|
||||
if (result->_Name.empty())
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -252,23 +389,23 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
{
|
||||
try
|
||||
{
|
||||
auto result = Command::FromJson(value, warnings);
|
||||
if (result)
|
||||
{
|
||||
// Override commands with the same name
|
||||
commands.Insert(result->Name(), *result);
|
||||
}
|
||||
else
|
||||
const auto result = Command::FromJson(value, warnings);
|
||||
if (result->ActionAndArgs().Action() == ShortcutAction::Invalid && !result->HasNestedCommands())
|
||||
{
|
||||
// If there wasn't a parsed command, then try to get the
|
||||
// name from the json blob. If that name currently
|
||||
// exists in our list of commands, we should remove it.
|
||||
const auto name = _nameFromJson(value);
|
||||
if (!name.empty())
|
||||
if (name.has_value() && !name->empty())
|
||||
{
|
||||
commands.Remove(name);
|
||||
commands.Remove(*name);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Override commands with the same name
|
||||
commands.Insert(result->Name(), *result);
|
||||
}
|
||||
}
|
||||
CATCH_LOG();
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ Author(s):
|
||||
#include "Command.g.h"
|
||||
#include "TerminalWarnings.h"
|
||||
#include "Profile.h"
|
||||
#include "ActionAndArgs.h"
|
||||
#include "../inc/cppwinrt_utils.h"
|
||||
#include "SettingsTypes.h"
|
||||
|
||||
@@ -49,21 +50,35 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
static std::vector<SettingsLoadWarnings> LayerJson(Windows::Foundation::Collections::IMap<winrt::hstring, Model::Command>& commands,
|
||||
const Json::Value& json);
|
||||
bool HasNestedCommands() const;
|
||||
bool IsNestedCommand() const noexcept;
|
||||
Windows::Foundation::Collections::IMapView<winrt::hstring, Model::Command> NestedCommands() const;
|
||||
|
||||
bool HasName() const noexcept;
|
||||
hstring Name() const noexcept;
|
||||
void Name(const hstring& name);
|
||||
|
||||
Control::KeyChord Keys() const noexcept;
|
||||
hstring KeyChordText() const noexcept;
|
||||
std::vector<Control::KeyChord> KeyMappings() const noexcept;
|
||||
void RegisterKey(const Control::KeyChord& keys);
|
||||
void EraseKey(const Control::KeyChord& keys);
|
||||
|
||||
hstring IconPath() const noexcept;
|
||||
void IconPath(const hstring& val);
|
||||
|
||||
winrt::Windows::UI::Xaml::Data::INotifyPropertyChanged::PropertyChanged_revoker propertyChangedRevoker;
|
||||
|
||||
WINRT_CALLBACK(PropertyChanged, Windows::UI::Xaml::Data::PropertyChangedEventHandler);
|
||||
WINRT_OBSERVABLE_PROPERTY(winrt::hstring, Name, _PropertyChangedHandlers);
|
||||
WINRT_OBSERVABLE_PROPERTY(Model::ActionAndArgs, Action, _PropertyChangedHandlers);
|
||||
WINRT_OBSERVABLE_PROPERTY(winrt::hstring, KeyChordText, _PropertyChangedHandlers);
|
||||
WINRT_OBSERVABLE_PROPERTY(winrt::hstring, IconPath, _PropertyChangedHandlers);
|
||||
|
||||
WINRT_PROPERTY(ExpandCommandType, IterateOn, ExpandCommandType::None);
|
||||
WINRT_PROPERTY(Model::ActionAndArgs, ActionAndArgs);
|
||||
|
||||
private:
|
||||
Json::Value _originalJson;
|
||||
Windows::Foundation::Collections::IMap<winrt::hstring, Model::Command> _subcommands{ nullptr };
|
||||
std::vector<Control::KeyChord> _keyMappings;
|
||||
std::optional<std::wstring> _name;
|
||||
std::optional<std::wstring> _iconPath;
|
||||
bool _nestedCommand{ false };
|
||||
|
||||
static std::vector<Model::Command> _expandCommand(Command* const expandable,
|
||||
Windows::Foundation::Collections::IVectorView<Model::Profile> profiles,
|
||||
|
||||
@@ -1,20 +1,42 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import "KeyMapping.idl";
|
||||
#include "AllShortcutActions.h"
|
||||
|
||||
import "ActionArgs.idl";
|
||||
import "Profile.idl";
|
||||
import "ColorScheme.idl";
|
||||
import "TerminalWarnings.idl";
|
||||
|
||||
namespace Microsoft.Terminal.Settings.Model
|
||||
{
|
||||
enum ShortcutAction
|
||||
{
|
||||
Invalid = 0, // treat Invalid as unbound actions
|
||||
|
||||
// When adding a new action, add them to AllShortcutActions.h!
|
||||
#define ON_ALL_ACTIONS(action) action,
|
||||
ALL_SHORTCUT_ACTIONS
|
||||
#undef ON_ALL_ACTIONS
|
||||
};
|
||||
|
||||
[default_interface] runtimeclass ActionAndArgs {
|
||||
ActionAndArgs();
|
||||
ActionAndArgs(ShortcutAction action, IActionArgs args);
|
||||
|
||||
IActionArgs Args;
|
||||
ShortcutAction Action;
|
||||
};
|
||||
|
||||
[default_interface] runtimeclass Command : Windows.UI.Xaml.Data.INotifyPropertyChanged
|
||||
{
|
||||
Command();
|
||||
|
||||
String Name;
|
||||
ActionAndArgs Action;
|
||||
String KeyChordText;
|
||||
String Name { get; };
|
||||
ActionAndArgs ActionAndArgs { get; };
|
||||
Microsoft.Terminal.Control.KeyChord Keys { get; };
|
||||
void RegisterKey(Microsoft.Terminal.Control.KeyChord keys);
|
||||
String KeyChordText { get; };
|
||||
|
||||
String IconPath;
|
||||
|
||||
|
||||
@@ -64,12 +64,11 @@ bool GlobalAppSettings::_getDefaultDebugFeaturesValue()
|
||||
}
|
||||
|
||||
GlobalAppSettings::GlobalAppSettings() :
|
||||
_keymap{ winrt::make_self<KeyMapping>() },
|
||||
_actionMap{ winrt::make_self<implementation::ActionMap>() },
|
||||
_keybindingsWarnings{},
|
||||
_validDefaultProfile{ false },
|
||||
_defaultProfile{}
|
||||
{
|
||||
_commands = winrt::single_threaded_map<winrt::hstring, Model::Command>();
|
||||
_colorSchemes = winrt::single_threaded_map<winrt::hstring, Model::ColorScheme>();
|
||||
}
|
||||
|
||||
@@ -85,10 +84,9 @@ void GlobalAppSettings::_FinalizeInheritance()
|
||||
FAIL_FAST_IF(_parents.size() > 1);
|
||||
for (auto parent : _parents)
|
||||
{
|
||||
_keymap = std::move(parent->_keymap);
|
||||
_actionMap->InsertParent(parent->_actionMap);
|
||||
_keybindingsWarnings = std::move(parent->_keybindingsWarnings);
|
||||
_colorSchemes = std::move(parent->_colorSchemes);
|
||||
_commands = std::move(parent->_commands);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -128,10 +126,7 @@ winrt::com_ptr<GlobalAppSettings> GlobalAppSettings::Copy() const
|
||||
globals->_UnparsedDefaultProfile = _UnparsedDefaultProfile;
|
||||
globals->_validDefaultProfile = _validDefaultProfile;
|
||||
globals->_defaultProfile = _defaultProfile;
|
||||
if (_keymap)
|
||||
{
|
||||
globals->_keymap = _keymap->Copy();
|
||||
}
|
||||
globals->_actionMap = _actionMap->Copy();
|
||||
std::copy(_keybindingsWarnings.begin(), _keybindingsWarnings.end(), std::back_inserter(globals->_keybindingsWarnings));
|
||||
|
||||
if (_colorSchemes)
|
||||
@@ -143,15 +138,6 @@ winrt::com_ptr<GlobalAppSettings> GlobalAppSettings::Copy() const
|
||||
}
|
||||
}
|
||||
|
||||
if (_commands)
|
||||
{
|
||||
for (auto kv : _commands)
|
||||
{
|
||||
const auto commandImpl{ winrt::get_self<Command>(kv.Value()) };
|
||||
globals->_commands.Insert(kv.Key(), *commandImpl->Copy());
|
||||
}
|
||||
}
|
||||
|
||||
// Globals only ever has 1 parent
|
||||
FAIL_FAST_IF(_parents.size() > 1);
|
||||
for (auto parent : _parents)
|
||||
@@ -232,9 +218,9 @@ std::optional<winrt::hstring> GlobalAppSettings::_getUnparsedDefaultProfileImpl(
|
||||
}
|
||||
#pragma endregion
|
||||
|
||||
winrt::Microsoft::Terminal::Settings::Model::KeyMapping GlobalAppSettings::KeyMap() const noexcept
|
||||
winrt::Microsoft::Terminal::Settings::Model::ActionMap GlobalAppSettings::ActionMap() const noexcept
|
||||
{
|
||||
return *_keymap;
|
||||
return *_actionMap;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
@@ -326,7 +312,8 @@ void GlobalAppSettings::LayerJson(const Json::Value& json)
|
||||
auto parseBindings = [this, &json](auto jsonKey) {
|
||||
if (auto bindings{ json[JsonKey(jsonKey)] })
|
||||
{
|
||||
auto warnings = _keymap->LayerJson(bindings);
|
||||
auto warnings = _actionMap->LayerJson(bindings);
|
||||
|
||||
// It's possible that the user provided keybindings have some warnings
|
||||
// in them - problems that we should alert the user to, but we can
|
||||
// recover from. Most of these warnings cannot be detected later in the
|
||||
@@ -334,16 +321,6 @@ void GlobalAppSettings::LayerJson(const Json::Value& json)
|
||||
// warnings generated from parsing these keybindings, add them to our
|
||||
// list of warnings.
|
||||
_keybindingsWarnings.insert(_keybindingsWarnings.end(), warnings.begin(), warnings.end());
|
||||
|
||||
// Now parse the array again, but this time as a list of commands.
|
||||
warnings = implementation::Command::LayerJson(_commands, bindings);
|
||||
|
||||
// We cannot add all warnings, as some of them were already populated while parsing key mapping.
|
||||
// Hence let's cherry-pick the ones relevant for command parsing.
|
||||
if (std::count(warnings.begin(), warnings.end(), SettingsLoadWarnings::FailedToParseSubCommands))
|
||||
{
|
||||
_keybindingsWarnings.push_back(SettingsLoadWarnings::FailedToParseSubCommands);
|
||||
}
|
||||
}
|
||||
};
|
||||
parseBindings(LegacyKeybindingsKey);
|
||||
@@ -380,11 +357,6 @@ std::vector<winrt::Microsoft::Terminal::Settings::Model::SettingsLoadWarnings> G
|
||||
return _keybindingsWarnings;
|
||||
}
|
||||
|
||||
winrt::Windows::Foundation::Collections::IMapView<winrt::hstring, winrt::Microsoft::Terminal::Settings::Model::Command> GlobalAppSettings::Commands() noexcept
|
||||
{
|
||||
return _commands.GetView();
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Create a new serialized JsonObject from an instance of this class
|
||||
// Arguments:
|
||||
|
||||
@@ -18,7 +18,7 @@ Author(s):
|
||||
#include "GlobalAppSettings.g.h"
|
||||
#include "IInheritable.h"
|
||||
|
||||
#include "KeyMapping.h"
|
||||
#include "ActionMap.h"
|
||||
#include "Command.h"
|
||||
#include "ColorScheme.h"
|
||||
|
||||
@@ -42,7 +42,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
void AddColorScheme(const Model::ColorScheme& scheme);
|
||||
void RemoveColorScheme(hstring schemeName);
|
||||
|
||||
Model::KeyMapping KeyMap() const noexcept;
|
||||
Model::ActionMap ActionMap() const noexcept;
|
||||
|
||||
static com_ptr<GlobalAppSettings> FromJson(const Json::Value& json);
|
||||
void LayerJson(const Json::Value& json);
|
||||
@@ -51,8 +51,6 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
|
||||
std::vector<SettingsLoadWarnings> KeybindingsWarnings() const;
|
||||
|
||||
Windows::Foundation::Collections::IMapView<hstring, Model::Command> Commands() noexcept;
|
||||
|
||||
// These are implemented manually to handle the string/GUID exchange
|
||||
// by higher layers in the app.
|
||||
void DefaultProfile(const guid& defaultProfile) noexcept;
|
||||
@@ -97,11 +95,10 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
std::optional<hstring> _UnparsedDefaultProfile{ std::nullopt };
|
||||
bool _validDefaultProfile;
|
||||
|
||||
com_ptr<KeyMapping> _keymap;
|
||||
com_ptr<implementation::ActionMap> _actionMap;
|
||||
std::vector<SettingsLoadWarnings> _keybindingsWarnings;
|
||||
|
||||
Windows::Foundation::Collections::IMap<hstring, Model::ColorScheme> _colorSchemes;
|
||||
Windows::Foundation::Collections::IMap<hstring, Model::Command> _commands;
|
||||
|
||||
std::optional<hstring> _getUnparsedDefaultProfileImpl() const;
|
||||
static bool _getDefaultDebugFeaturesValue();
|
||||
|
||||
@@ -4,8 +4,7 @@
|
||||
#include "IInheritable.idl.h"
|
||||
|
||||
import "ColorScheme.idl";
|
||||
import "KeyMapping.idl";
|
||||
import "Command.idl";
|
||||
import "ActionMap.idl";
|
||||
|
||||
namespace Microsoft.Terminal.Settings.Model
|
||||
{
|
||||
@@ -73,8 +72,6 @@ namespace Microsoft.Terminal.Settings.Model
|
||||
void AddColorScheme(ColorScheme scheme);
|
||||
void RemoveColorScheme(String schemeName);
|
||||
|
||||
KeyMapping KeyMap();
|
||||
|
||||
Windows.Foundation.Collections.IMapView<String, Command> Commands();
|
||||
ActionMap ActionMap { get; };
|
||||
}
|
||||
}
|
||||
|
||||
66
src/cascadia/TerminalSettingsModel/HashUtils.h
Normal file
66
src/cascadia/TerminalSettingsModel/HashUtils.h
Normal file
@@ -0,0 +1,66 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
/*++
|
||||
Module Name:
|
||||
- HashUtils.h
|
||||
|
||||
Abstract:
|
||||
- This module is used for hashing data consistently
|
||||
|
||||
Author(s):
|
||||
- Carlos Zamora (CaZamor) 15-Apr-2021
|
||||
|
||||
Revision History:
|
||||
- N/A
|
||||
--*/
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace Microsoft::Terminal::Settings::Model::HashUtils
|
||||
{
|
||||
// This is a helper template function for hashing multiple variables in conjunction to each other.
|
||||
template<typename T>
|
||||
constexpr size_t HashProperty(const T& val)
|
||||
{
|
||||
std::hash<T> hashFunc;
|
||||
return hashFunc(val);
|
||||
}
|
||||
|
||||
template<typename T, typename... Args>
|
||||
constexpr size_t HashProperty(const T& val, Args&&... more)
|
||||
{
|
||||
return HashProperty(val) ^ HashProperty(std::forward<Args>(more)...);
|
||||
}
|
||||
|
||||
template<>
|
||||
constexpr size_t HashProperty(const til::color& val)
|
||||
{
|
||||
return HashProperty(val.a, val.r, val.g, val.b);
|
||||
}
|
||||
|
||||
#ifdef WINRT_Windows_Foundation_H
|
||||
template<typename T>
|
||||
constexpr size_t HashProperty(const winrt::Windows::Foundation::IReference<T>& val)
|
||||
{
|
||||
return val ? HashProperty(val.Value()) : 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef WINRT_Windows_UI_H
|
||||
template<>
|
||||
constexpr size_t HashProperty(const winrt::Windows::UI::Color& val)
|
||||
{
|
||||
return HashProperty(til::color{ val });
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef WINRT_Microsoft_Terminal_Core_H
|
||||
template<>
|
||||
constexpr size_t HashProperty(const winrt::Microsoft::Terminal::Core::Color& val)
|
||||
{
|
||||
return HashProperty(til::color{ val });
|
||||
}
|
||||
#endif
|
||||
|
||||
};
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
using namespace winrt::Microsoft::Terminal::Control;
|
||||
using namespace winrt::Microsoft::Terminal::Settings::Model::implementation;
|
||||
using namespace Microsoft::Terminal::Settings::Model::JsonUtils;
|
||||
|
||||
static constexpr std::wstring_view CTRL_KEY{ L"ctrl" };
|
||||
static constexpr std::wstring_view SHIFT_KEY{ L"shift" };
|
||||
@@ -104,14 +105,12 @@ static const std::unordered_map<std::wstring_view, int32_t> vkeyNamePairs {
|
||||
// - hstr: the string to parse into a keychord.
|
||||
// Return Value:
|
||||
// - a newly constructed KeyChord
|
||||
KeyChord KeyChordSerialization::FromString(const winrt::hstring& hstr)
|
||||
static KeyChord _FromString(const std::wstring_view& wstr)
|
||||
{
|
||||
std::wstring wstr{ hstr };
|
||||
|
||||
// Split the string on '+'
|
||||
std::wstring temp;
|
||||
std::vector<std::wstring> parts;
|
||||
std::wstringstream wss(wstr);
|
||||
std::wstringstream wss(wstr.data());
|
||||
|
||||
while (std::getline(wss, temp, L'+'))
|
||||
{
|
||||
@@ -220,8 +219,13 @@ KeyChord KeyChordSerialization::FromString(const winrt::hstring& hstr)
|
||||
// names listed in the vkeyNamePairs vector above, or is one of 0-9a-z.
|
||||
// Return Value:
|
||||
// - a string which is an equivalent serialization of this object.
|
||||
winrt::hstring KeyChordSerialization::ToString(const KeyChord& chord)
|
||||
static std::wstring _ToString(const KeyChord& chord)
|
||||
{
|
||||
if (!chord)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
bool serializedSuccessfully = false;
|
||||
const auto modifiers = chord.Modifiers();
|
||||
const auto vkey = chord.Vkey();
|
||||
@@ -292,5 +296,57 @@ winrt::hstring KeyChordSerialization::ToString(const KeyChord& chord)
|
||||
buffer = L"";
|
||||
}
|
||||
|
||||
return winrt::hstring{ buffer };
|
||||
return buffer;
|
||||
}
|
||||
|
||||
KeyChord KeyChordSerialization::FromString(const winrt::hstring& hstr)
|
||||
{
|
||||
return _FromString(hstr);
|
||||
}
|
||||
|
||||
winrt::hstring KeyChordSerialization::ToString(const KeyChord& chord)
|
||||
{
|
||||
return hstring{ _ToString(chord) };
|
||||
}
|
||||
|
||||
KeyChord ConversionTrait<KeyChord>::FromJson(const Json::Value& json)
|
||||
{
|
||||
try
|
||||
{
|
||||
std::string keyChordText;
|
||||
if (json.isString())
|
||||
{
|
||||
// "keys": "ctrl+c"
|
||||
keyChordText = json.asString();
|
||||
}
|
||||
else if (json.isArray() && json.size() == 1)
|
||||
{
|
||||
// "keys": [ "ctrl+c" ]
|
||||
keyChordText = json[0].asString();
|
||||
}
|
||||
else
|
||||
{
|
||||
throw winrt::hresult_invalid_argument{};
|
||||
}
|
||||
return _FromString(til::u8u16(keyChordText));
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool ConversionTrait<KeyChord>::CanConvert(const Json::Value& json)
|
||||
{
|
||||
return json.isString() || (json.isArray() && json.size() == 1);
|
||||
}
|
||||
|
||||
Json::Value ConversionTrait<KeyChord>::ToJson(const KeyChord& val)
|
||||
{
|
||||
return til::u16u8(_ToString(val));
|
||||
}
|
||||
|
||||
std::string ConversionTrait<KeyChord>::TypeDescription() const
|
||||
{
|
||||
return "key chord";
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "KeyChordSerialization.g.h"
|
||||
#include "JsonUtils.h"
|
||||
#include "../inc/cppwinrt_utils.h"
|
||||
|
||||
namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
@@ -17,6 +18,15 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
};
|
||||
}
|
||||
|
||||
template<>
|
||||
struct Microsoft::Terminal::Settings::Model::JsonUtils::ConversionTrait<winrt::Microsoft::Terminal::Control::KeyChord>
|
||||
{
|
||||
winrt::Microsoft::Terminal::Control::KeyChord FromJson(const Json::Value& json);
|
||||
bool CanConvert(const Json::Value& json);
|
||||
Json::Value ToJson(const winrt::Microsoft::Terminal::Control::KeyChord& val);
|
||||
std::string TypeDescription() const;
|
||||
};
|
||||
|
||||
namespace winrt::Microsoft::Terminal::Settings::Model::factory_implementation
|
||||
{
|
||||
// C++/WinRT generates a constructor even though one is not specified in the IDL
|
||||
|
||||
@@ -1,144 +0,0 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#include "pch.h"
|
||||
#include "KeyMapping.h"
|
||||
#include "KeyChordSerialization.h"
|
||||
#include "ActionAndArgs.h"
|
||||
|
||||
#include "KeyMapping.g.cpp"
|
||||
|
||||
using namespace winrt::Microsoft::Terminal::Settings::Model;
|
||||
using namespace winrt::Microsoft::Terminal::Control;
|
||||
|
||||
namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
{
|
||||
winrt::com_ptr<KeyMapping> KeyMapping::Copy() const
|
||||
{
|
||||
auto keymap{ winrt::make_self<KeyMapping>() };
|
||||
std::for_each(_keyShortcuts.begin(), _keyShortcuts.end(), [keymap](auto& kv) {
|
||||
const auto actionAndArgsImpl{ winrt::get_self<ActionAndArgs>(kv.second) };
|
||||
keymap->_keyShortcuts[kv.first] = *actionAndArgsImpl->Copy();
|
||||
});
|
||||
return keymap;
|
||||
}
|
||||
|
||||
Microsoft::Terminal::Settings::Model::ActionAndArgs KeyMapping::TryLookup(KeyChord const& chord) const
|
||||
{
|
||||
const auto result = _keyShortcuts.find(chord);
|
||||
if (result != _keyShortcuts.end())
|
||||
{
|
||||
return result->second;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
uint64_t KeyMapping::Size() const
|
||||
{
|
||||
return _keyShortcuts.size();
|
||||
}
|
||||
|
||||
void KeyMapping::SetKeyBinding(const Microsoft::Terminal::Settings::Model::ActionAndArgs& actionAndArgs,
|
||||
const KeyChord& chord)
|
||||
{
|
||||
// if the chord is already mapped - clear the mapping
|
||||
if (_keyShortcuts.find(chord) != _keyShortcuts.end())
|
||||
{
|
||||
ClearKeyBinding(chord);
|
||||
}
|
||||
|
||||
_keyShortcuts[chord] = actionAndArgs;
|
||||
_keyShortcutsByInsertionOrder.push_back(std::make_pair(chord, actionAndArgs));
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Remove the action that's bound to a particular KeyChord.
|
||||
// Arguments:
|
||||
// - chord: the keystroke to remove the action for.
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void KeyMapping::ClearKeyBinding(const KeyChord& chord)
|
||||
{
|
||||
_keyShortcuts.erase(chord);
|
||||
|
||||
KeyChordEquality keyChordEquality;
|
||||
_keyShortcutsByInsertionOrder.erase(std::remove_if(_keyShortcutsByInsertionOrder.begin(), _keyShortcutsByInsertionOrder.end(), [keyChordEquality, chord](const auto& keyBinding) {
|
||||
return keyChordEquality(keyBinding.first, chord);
|
||||
}),
|
||||
_keyShortcutsByInsertionOrder.end());
|
||||
}
|
||||
|
||||
KeyChord KeyMapping::GetKeyBindingForAction(Microsoft::Terminal::Settings::Model::ShortcutAction const& action)
|
||||
{
|
||||
for (auto it = _keyShortcutsByInsertionOrder.rbegin(); it != _keyShortcutsByInsertionOrder.rend(); ++it)
|
||||
{
|
||||
const auto& kv = *it;
|
||||
if (kv.second.Action() == action)
|
||||
{
|
||||
return kv.first;
|
||||
}
|
||||
}
|
||||
return { nullptr };
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Lookup the keychord bound to a particular combination of ShortcutAction
|
||||
// and IActionArgs. This enables searching no only for the binding of a
|
||||
// particular ShortcutAction, but also a particular set of values for
|
||||
// arguments to that action.
|
||||
// If several bindings might match the lookup, prefers the one that was added last.
|
||||
// Arguments:
|
||||
// - actionAndArgs: The ActionAndArgs to lookup the keybinding for.
|
||||
// Return Value:
|
||||
// - The bound keychord, if this ActionAndArgs is bound to a key, otherwise nullptr.
|
||||
KeyChord KeyMapping::GetKeyBindingForActionWithArgs(Microsoft::Terminal::Settings::Model::ActionAndArgs const& actionAndArgs)
|
||||
{
|
||||
if (actionAndArgs == nullptr)
|
||||
{
|
||||
return { nullptr };
|
||||
}
|
||||
|
||||
for (auto it = _keyShortcutsByInsertionOrder.rbegin(); it != _keyShortcutsByInsertionOrder.rend(); ++it)
|
||||
{
|
||||
const auto& kv = *it;
|
||||
const auto action = kv.second.Action();
|
||||
const auto args = kv.second.Args();
|
||||
const auto actionMatched = action == actionAndArgs.Action();
|
||||
const auto argsMatched = args ? args.Equals(actionAndArgs.Args()) : args == actionAndArgs.Args();
|
||||
if (actionMatched && argsMatched)
|
||||
{
|
||||
return kv.first;
|
||||
}
|
||||
}
|
||||
return { nullptr };
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Takes the KeyModifier flags from Terminal and maps them to the WinRT types which are used by XAML
|
||||
// Return Value:
|
||||
// - a Windows::System::VirtualKeyModifiers object with the flags of which modifiers used.
|
||||
Windows::System::VirtualKeyModifiers KeyMapping::ConvertVKModifiers(KeyModifiers modifiers)
|
||||
{
|
||||
Windows::System::VirtualKeyModifiers keyModifiers = Windows::System::VirtualKeyModifiers::None;
|
||||
|
||||
if (WI_IsFlagSet(modifiers, KeyModifiers::Ctrl))
|
||||
{
|
||||
keyModifiers |= Windows::System::VirtualKeyModifiers::Control;
|
||||
}
|
||||
if (WI_IsFlagSet(modifiers, KeyModifiers::Shift))
|
||||
{
|
||||
keyModifiers |= Windows::System::VirtualKeyModifiers::Shift;
|
||||
}
|
||||
if (WI_IsFlagSet(modifiers, KeyModifiers::Alt))
|
||||
{
|
||||
// note: Menu is the Alt VK_MENU
|
||||
keyModifiers |= Windows::System::VirtualKeyModifiers::Menu;
|
||||
}
|
||||
if (WI_IsFlagSet(modifiers, KeyModifiers::Windows))
|
||||
{
|
||||
keyModifiers |= Windows::System::VirtualKeyModifiers::Windows;
|
||||
}
|
||||
|
||||
return keyModifiers;
|
||||
}
|
||||
}
|
||||
@@ -1,80 +0,0 @@
|
||||
/*++
|
||||
Copyright (c) Microsoft Corporation
|
||||
Licensed under the MIT license.
|
||||
|
||||
Module Name:
|
||||
- KeyMapping.h
|
||||
|
||||
Abstract:
|
||||
- A mapping of key chords to actions. Includes (de)serialization logic.
|
||||
|
||||
Author(s):
|
||||
- Carlos Zamora - September 2020
|
||||
|
||||
--*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "KeyMapping.g.h"
|
||||
#include "ActionArgs.h"
|
||||
#include "../inc/cppwinrt_utils.h"
|
||||
|
||||
// fwdecl unittest classes
|
||||
namespace SettingsModelLocalTests
|
||||
{
|
||||
class DeserializationTests;
|
||||
class KeyBindingsTests;
|
||||
class TestUtils;
|
||||
}
|
||||
|
||||
namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
{
|
||||
struct KeyChordHash
|
||||
{
|
||||
std::size_t operator()(const Control::KeyChord& key) const
|
||||
{
|
||||
std::hash<int32_t> keyHash;
|
||||
std::hash<Control::KeyModifiers> modifiersHash;
|
||||
std::size_t hashedKey = keyHash(key.Vkey());
|
||||
std::size_t hashedMods = modifiersHash(key.Modifiers());
|
||||
return hashedKey ^ hashedMods;
|
||||
}
|
||||
};
|
||||
|
||||
struct KeyChordEquality
|
||||
{
|
||||
bool operator()(const Control::KeyChord& lhs, const Control::KeyChord& rhs) const
|
||||
{
|
||||
return lhs.Modifiers() == rhs.Modifiers() && lhs.Vkey() == rhs.Vkey();
|
||||
}
|
||||
};
|
||||
|
||||
struct KeyMapping : KeyMappingT<KeyMapping>
|
||||
{
|
||||
KeyMapping() = default;
|
||||
com_ptr<KeyMapping> Copy() const;
|
||||
|
||||
Model::ActionAndArgs TryLookup(Control::KeyChord const& chord) const;
|
||||
uint64_t Size() const;
|
||||
|
||||
void SetKeyBinding(Model::ActionAndArgs const& actionAndArgs,
|
||||
Control::KeyChord const& chord);
|
||||
void ClearKeyBinding(Control::KeyChord const& chord);
|
||||
Control::KeyChord GetKeyBindingForAction(Model::ShortcutAction const& action);
|
||||
Control::KeyChord GetKeyBindingForActionWithArgs(Model::ActionAndArgs const& actionAndArgs);
|
||||
|
||||
static Windows::System::VirtualKeyModifiers ConvertVKModifiers(Control::KeyModifiers modifiers);
|
||||
|
||||
// Defined in KeyMappingSerialization.cpp
|
||||
std::vector<Model::SettingsLoadWarnings> LayerJson(const Json::Value& json);
|
||||
Json::Value ToJson();
|
||||
|
||||
private:
|
||||
std::unordered_map<Control::KeyChord, Model::ActionAndArgs, KeyChordHash, KeyChordEquality> _keyShortcuts;
|
||||
std::vector<std::pair<Control::KeyChord, Model::ActionAndArgs>> _keyShortcutsByInsertionOrder;
|
||||
|
||||
friend class SettingsModelLocalTests::DeserializationTests;
|
||||
friend class SettingsModelLocalTests::KeyBindingsTests;
|
||||
friend class SettingsModelLocalTests::TestUtils;
|
||||
};
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#include "AllShortcutActions.h"
|
||||
|
||||
import "ActionArgs.idl";
|
||||
|
||||
namespace Microsoft.Terminal.Settings.Model
|
||||
{
|
||||
enum ShortcutAction
|
||||
{
|
||||
Invalid = 0,
|
||||
|
||||
// When adding a new action, add them to AllShortcutActions.h!
|
||||
#define ON_ALL_ACTIONS(action) action,
|
||||
ALL_SHORTCUT_ACTIONS
|
||||
#undef ON_ALL_ACTIONS
|
||||
};
|
||||
|
||||
[default_interface] runtimeclass ActionAndArgs {
|
||||
ActionAndArgs();
|
||||
ActionAndArgs(ShortcutAction action, IActionArgs args);
|
||||
|
||||
IActionArgs Args;
|
||||
ShortcutAction Action;
|
||||
};
|
||||
|
||||
[default_interface] runtimeclass KeyMapping
|
||||
{
|
||||
ActionAndArgs TryLookup(Microsoft.Terminal.Control.KeyChord chord);
|
||||
UInt64 Size();
|
||||
|
||||
void SetKeyBinding(ActionAndArgs actionAndArgs, Microsoft.Terminal.Control.KeyChord chord);
|
||||
void ClearKeyBinding(Microsoft.Terminal.Control.KeyChord chord);
|
||||
|
||||
Microsoft.Terminal.Control.KeyChord GetKeyBindingForAction(ShortcutAction action);
|
||||
Microsoft.Terminal.Control.KeyChord GetKeyBindingForActionWithArgs(ActionAndArgs actionAndArgs);
|
||||
}
|
||||
}
|
||||
@@ -1,162 +0,0 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
// - A couple helper functions for serializing/deserializing a KeyMapping
|
||||
// to/from json.
|
||||
//
|
||||
// Author(s):
|
||||
// - Mike Griese - May 2019
|
||||
|
||||
#include "pch.h"
|
||||
#include "KeyMapping.h"
|
||||
#include "ActionAndArgs.h"
|
||||
#include "KeyChordSerialization.h"
|
||||
#include "JsonUtils.h"
|
||||
|
||||
using namespace winrt::Microsoft::Terminal::Control;
|
||||
using namespace winrt::Microsoft::Terminal::Settings::Model;
|
||||
|
||||
static constexpr std::string_view KeysKey{ "keys" };
|
||||
static constexpr std::string_view CommandKey{ "command" };
|
||||
static constexpr std::string_view ActionKey{ "action" };
|
||||
|
||||
// Function Description:
|
||||
// - Small helper to create a json value serialization of a single
|
||||
// KeyBinding->Action mapping.
|
||||
// {
|
||||
// keys:[String],
|
||||
// command:String
|
||||
// }
|
||||
// Arguments:
|
||||
// - chord: The KeyChord to serialize
|
||||
// - actionName: the name of the ShortcutAction to use with this KeyChord
|
||||
// Return Value:
|
||||
// - a Json::Value which is an equivalent serialization of this object.
|
||||
static Json::Value _ShortcutAsJsonObject(const KeyChord& chord,
|
||||
const std::string_view actionName)
|
||||
{
|
||||
const auto keyString = KeyChordSerialization::ToString(chord);
|
||||
if (keyString == L"")
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Json::Value jsonObject;
|
||||
Json::Value keysArray;
|
||||
keysArray.append(winrt::to_string(keyString));
|
||||
|
||||
jsonObject[JsonKey(KeysKey)] = keysArray;
|
||||
jsonObject[JsonKey(CommandKey)] = actionName.data();
|
||||
|
||||
return jsonObject;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Serialize this KeyMapping to a json array of objects. Each object in
|
||||
// the array represents a single keybinding, mapping a KeyChord to a
|
||||
// ShortcutAction.
|
||||
// Return Value:
|
||||
// - a Json::Value which is an equivalent serialization of this object.
|
||||
Json::Value winrt::Microsoft::Terminal::Settings::Model::implementation::KeyMapping::ToJson()
|
||||
{
|
||||
Json::Value bindingsArray;
|
||||
|
||||
// Iterate over all the possible actions in the names list, and see if
|
||||
// it has a binding.
|
||||
for (auto& actionName : ActionAndArgs::ActionKeyNamesMap)
|
||||
{
|
||||
const auto searchedForName = actionName.first;
|
||||
const auto searchedForAction = actionName.second;
|
||||
|
||||
if (const auto chord{ GetKeyBindingForAction(searchedForAction) })
|
||||
{
|
||||
if (const auto serialization{ _ShortcutAsJsonObject(chord, searchedForName) })
|
||||
{
|
||||
bindingsArray.append(serialization);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return bindingsArray;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Deserialize a KeyMapping from the key mappings that are in the array
|
||||
// `json`. The json array should contain an array of objects with both a
|
||||
// `command` string and a `keys` array, where `command` is one of the names
|
||||
// listed in `ActionAndArgs::ActionKeyNamesMap`, and `keys` is an array of
|
||||
// keypresses. Currently, the array should contain a single string, which can
|
||||
// be deserialized into a KeyChord.
|
||||
// - Applies the deserialized keybindings to the provided `bindings` object. If
|
||||
// a key chord in `json` is already bound to an action, that chord will be
|
||||
// overwritten with the new action. If a chord is bound to `null` or
|
||||
// `"unbound"`, then we'll clear the keybinding from the existing keybindings.
|
||||
// Arguments:
|
||||
// - json: an array of Json::Value's to deserialize into our _keyShortcuts mapping.
|
||||
std::vector<SettingsLoadWarnings> winrt::Microsoft::Terminal::Settings::Model::implementation::KeyMapping::LayerJson(const Json::Value& json)
|
||||
{
|
||||
// It's possible that the user provided keybindings have some warnings in
|
||||
// them - problems that we should alert the user to, but we can recover
|
||||
// from. Most of these warnings cannot be detected later in the Validate
|
||||
// settings phase, so we'll collect them now.
|
||||
std::vector<SettingsLoadWarnings> warnings;
|
||||
|
||||
for (const auto& value : json)
|
||||
{
|
||||
if (!value.isObject())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto commandVal = value[JsonKey(CommandKey)];
|
||||
const auto keys = value[JsonKey(KeysKey)];
|
||||
|
||||
if (keys)
|
||||
{
|
||||
const auto validString = keys.isString();
|
||||
const auto validArray = keys.isArray() && keys.size() == 1;
|
||||
|
||||
// GH#4239 - If the user provided more than one key
|
||||
// chord to a "keys" array, warn the user here.
|
||||
// TODO: GH#1334 - remove this check.
|
||||
if (keys.isArray() && keys.size() > 1)
|
||||
{
|
||||
warnings.push_back(SettingsLoadWarnings::TooManyKeysForChord);
|
||||
}
|
||||
|
||||
if (!validString && !validArray)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
const auto keyChordString = keys.isString() ? winrt::to_hstring(keys.asString()) : winrt::to_hstring(keys[0].asString());
|
||||
|
||||
// If the action was null, "unbound", or something we didn't
|
||||
// understand, this will return nullptr.
|
||||
auto actionAndArgs = ActionAndArgs::FromJson(commandVal, warnings);
|
||||
|
||||
// Try parsing the chord
|
||||
try
|
||||
{
|
||||
const auto chord = KeyChordSerialization::FromString(keyChordString);
|
||||
|
||||
// If we couldn't find the action they want to set the chord to,
|
||||
// or the action was `null` or `"unbound"`, just clear out the
|
||||
// keybinding. Otherwise, set the keybinding to the action we
|
||||
// found.
|
||||
if (actionAndArgs)
|
||||
{
|
||||
SetKeyBinding(*actionAndArgs, chord);
|
||||
}
|
||||
else
|
||||
{
|
||||
ClearKeyBinding(chord);
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return warnings;
|
||||
}
|
||||
@@ -26,6 +26,9 @@
|
||||
<ClInclude Include="ActionAndArgs.h">
|
||||
<DependentUpon>ActionArgs.idl</DependentUpon>
|
||||
</ClInclude>
|
||||
<ClInclude Include="ActionMap.h">
|
||||
<DependentUpon>ActionMap.idl</DependentUpon>
|
||||
</ClInclude>
|
||||
<ClInclude Include="AzureCloudShellGenerator.h" />
|
||||
<ClInclude Include="CascadiaSettings.h">
|
||||
<DependentUpon>CascadiaSettings.idl</DependentUpon>
|
||||
@@ -43,12 +46,10 @@
|
||||
<ClInclude Include="IInheritable.h" />
|
||||
<ClInclude Include="IDynamicProfileGenerator.h" />
|
||||
<ClInclude Include="JsonUtils.h" />
|
||||
<ClInclude Include="HashUtils.h" />
|
||||
<ClInclude Include="KeyChordSerialization.h">
|
||||
<DependentUpon>KeyChordSerialization.idl</DependentUpon>
|
||||
</ClInclude>
|
||||
<ClInclude Include="KeyMapping.h">
|
||||
<DependentUpon>KeyMapping.idl</DependentUpon>
|
||||
</ClInclude>
|
||||
<ClInclude Include="PowershellCoreProfileGenerator.h" />
|
||||
<ClInclude Include="Profile.h">
|
||||
<DependentUpon>Profile.idl</DependentUpon>
|
||||
@@ -84,6 +85,12 @@
|
||||
<ClCompile Include="ActionArgs.cpp">
|
||||
<DependentUpon>ActionArgs.idl</DependentUpon>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ActionMap.cpp">
|
||||
<DependentUpon>ActionMap.idl</DependentUpon>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ActionMapSerialization.cpp">
|
||||
<DependentUpon>ActionMap.idl</DependentUpon>
|
||||
</ClCompile>
|
||||
<ClCompile Include="AzureCloudShellGenerator.cpp" />
|
||||
<ClCompile Include="CascadiaSettings.cpp">
|
||||
<DependentUpon>CascadiaSettings.idl</DependentUpon>
|
||||
@@ -104,12 +111,6 @@
|
||||
<ClCompile Include="KeyChordSerialization.cpp">
|
||||
<DependentUpon>KeyChordSerialization.idl</DependentUpon>
|
||||
</ClCompile>
|
||||
<ClCompile Include="KeyMapping.cpp">
|
||||
<DependentUpon>KeyMapping.idl</DependentUpon>
|
||||
</ClCompile>
|
||||
<ClCompile Include="KeyMappingSerialization.cpp">
|
||||
<DependentUpon>KeyMapping.idl</DependentUpon>
|
||||
</ClCompile>
|
||||
<ClCompile Include="PowershellCoreProfileGenerator.cpp" />
|
||||
<ClCompile Include="Profile.cpp">
|
||||
<DependentUpon>Profile.idl</DependentUpon>
|
||||
@@ -134,12 +135,12 @@
|
||||
<!-- ========================= idl Files ======================== -->
|
||||
<ItemGroup>
|
||||
<Midl Include="ActionArgs.idl" />
|
||||
<Midl Include="ActionMap.idl" />
|
||||
<Midl Include="CascadiaSettings.idl" />
|
||||
<Midl Include="ColorScheme.idl" />
|
||||
<Midl Include="Command.idl" />
|
||||
<Midl Include="GlobalAppSettings.idl" />
|
||||
<Midl Include="IconPathConverter.idl" />
|
||||
<Midl Include="KeyMapping.idl" />
|
||||
<Midl Include="Profile.idl" />
|
||||
<Midl Include="EnumMappings.idl" />
|
||||
<Midl Include="TerminalSettings.idl" />
|
||||
|
||||
@@ -67,16 +67,17 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Midl Include="ActionArgs.idl" />
|
||||
<Midl Include="ActionMap.idl" />
|
||||
<Midl Include="ColorScheme.idl" />
|
||||
<Midl Include="Command.idl" />
|
||||
<Midl Include="GlobalAppSettings.idl" />
|
||||
<Midl Include="KeyMapping.idl" />
|
||||
<Midl Include="Profile.idl" />
|
||||
<Midl Include="TerminalWarnings.idl" />
|
||||
<Midl Include="CascadiaSettings.idl" />
|
||||
<Midl Include="KeyChordSerialization.idl" />
|
||||
<Midl Include="EnumMappings.idl" />
|
||||
<Midl Include="IconPathConverter.idl" />
|
||||
<Midl Include="TerminalSettings.idl" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
@@ -89,4 +90,4 @@
|
||||
<UniqueIdentifier>{81a6314f-aa5b-4533-a499-13bc3a5c4af0}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
@@ -22,6 +22,7 @@
|
||||
<!-- Only put headers for winrt types in here. Don't put other header files
|
||||
in here - put them in the lib's vcxproj instead! -->
|
||||
<ClInclude Include="../ActionArgs.h" />
|
||||
<ClInclude Include="../ActionMap.h" />
|
||||
<ClInclude Include="../CascadiaSettings.h" />
|
||||
<ClInclude Include="../ColorScheme.h" />
|
||||
<ClInclude Include="../Command.h" />
|
||||
|
||||
@@ -71,6 +71,13 @@
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>WindowsApp.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<!--
|
||||
SettingsModelLib contains a DllMain that we need to force the use of.
|
||||
If you don't have this, then you'll see an error like
|
||||
"(init.obj) : error LNK2005: DllMain already defined in MSVCRTD.lib(dll_dllmain_stub.obj)"
|
||||
-->
|
||||
<AdditionalOptions Condition="'$(Platform)'=='Win32'">/INCLUDE:_DllMain@12</AdditionalOptions>
|
||||
<AdditionalOptions Condition="'$(Platform)'!='Win32'">/INCLUDE:DllMain</AdditionalOptions>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user