mirror of
https://github.com/microsoft/terminal.git
synced 2026-04-13 09:41:02 +00:00
Compare commits
81 Commits
dev/lhecke
...
dev/migrie
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6e1ce8de26 | ||
|
|
5e13c37217 | ||
|
|
6328b1adda | ||
|
|
177cf1caae | ||
|
|
75473c50fb | ||
|
|
76cb9654e1 | ||
|
|
e967801cdf | ||
|
|
50cfd84dd2 | ||
|
|
33860f7c1a | ||
|
|
860a3c7b23 | ||
|
|
eae88a9fdb | ||
|
|
137aea367a | ||
|
|
8a93b1dd5d | ||
|
|
6ca7d0e054 | ||
|
|
6f1dc5c9fa | ||
|
|
b5be04c3ae | ||
|
|
48d4e248b7 | ||
|
|
264618ae88 | ||
|
|
f892e52077 | ||
|
|
b90cc38f0f | ||
|
|
92b3453119 | ||
|
|
e25da60775 | ||
|
|
cee5fc9226 | ||
|
|
10e91a823d | ||
|
|
d1a72613c7 | ||
|
|
3e5eb73597 | ||
|
|
cc2fd9b490 | ||
|
|
45243bbee6 | ||
|
|
52eb2e5faa | ||
|
|
8b094fdfde | ||
|
|
7a94b8f725 | ||
|
|
e2f5f75471 | ||
|
|
7ac7fd1de9 | ||
|
|
dd684cbca1 | ||
|
|
edc8b557e1 | ||
|
|
82f968d8d5 | ||
|
|
67c7969879 | ||
|
|
b3d8f0e279 | ||
|
|
10ace041c3 | ||
|
|
4d23121a7e | ||
|
|
414007fdd8 | ||
|
|
72c0601d00 | ||
|
|
b3225db167 | ||
|
|
2517183b63 | ||
|
|
9fbcbcc9d8 | ||
|
|
73aefc18e8 | ||
|
|
a02585da35 | ||
|
|
2cf69338cd | ||
|
|
d71d8d7b32 | ||
|
|
9d411d405c | ||
|
|
58be8cd117 | ||
|
|
487f33ee89 | ||
|
|
829beda501 | ||
|
|
6e6979abe8 | ||
|
|
1fbe8e415d | ||
|
|
fa93fdc034 | ||
|
|
cf6e1f273a | ||
|
|
99059451d8 | ||
|
|
a309191461 | ||
|
|
e1be26b184 | ||
|
|
bc546dbdb0 | ||
|
|
00763fda9e | ||
|
|
b88be4534b | ||
|
|
207666e34d | ||
|
|
62b9a0d1c0 | ||
|
|
02f47f49c3 | ||
|
|
6905065fcf | ||
|
|
0416a944a2 | ||
|
|
3627d8abd5 | ||
|
|
33a9e32736 | ||
|
|
75af4cabbb | ||
|
|
43bd483962 | ||
|
|
0672812e6f | ||
|
|
f53553f4e4 | ||
|
|
11130a4895 | ||
|
|
0886e8f12d | ||
|
|
2e564368c8 | ||
|
|
ead76d7f16 | ||
|
|
614d1b21d6 | ||
|
|
fe640ff894 | ||
|
|
c56eb8fd93 |
25
.github/actions/spell-check/advice.txt
vendored
25
.github/actions/spell-check/advice.txt
vendored
@@ -1,25 +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/spell-check/dictionary/names.txt`.
|
|
||||||
* ... APIs, you can add them to a file in `.github/actions/spell-check/dictionary/`.
|
|
||||||
* ... just things you're using, please add them to an appropriate file in `.github/actions/spell-check/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/spell-check/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>
|
|
||||||
|
|
||||||
#### :warning: Reviewers
|
|
||||||
At present, the action that triggered this message will not show its :x: in this PR unless the branch is within this repository.
|
|
||||||
Thus, you **should** make sure that this comment has been addressed before encouraging the merge bot to merge this PR.
|
|
||||||
35
.github/actions/spell-check/dictionary/apis.txt
vendored
35
.github/actions/spell-check/dictionary/apis.txt
vendored
@@ -1,35 +0,0 @@
|
|||||||
ACCEPTFILES
|
|
||||||
ACCESSDENIED
|
|
||||||
bitfield
|
|
||||||
bitfields
|
|
||||||
CLASSNOTAVAILABLE
|
|
||||||
EXPCMDFLAGS
|
|
||||||
EXPCMDSTATE
|
|
||||||
fullkbd
|
|
||||||
href
|
|
||||||
IAsync
|
|
||||||
IBox
|
|
||||||
IBind
|
|
||||||
IClass
|
|
||||||
IComparable
|
|
||||||
ICustom
|
|
||||||
IDirect
|
|
||||||
IExplorer
|
|
||||||
IMap
|
|
||||||
IObject
|
|
||||||
IStorage
|
|
||||||
LCID
|
|
||||||
LSHIFT
|
|
||||||
NCHITTEST
|
|
||||||
NCLBUTTONDBLCLK
|
|
||||||
NCRBUTTONDBLCLK
|
|
||||||
NOAGGREGATION
|
|
||||||
NOREDIRECTIONBITMAP
|
|
||||||
oaidl
|
|
||||||
ocidl
|
|
||||||
RETURNCMD
|
|
||||||
rfind
|
|
||||||
roundf
|
|
||||||
RSHIFT
|
|
||||||
SIZENS
|
|
||||||
tmp
|
|
||||||
479828
.github/actions/spell-check/dictionary/dictionary.txt
vendored
479828
.github/actions/spell-check/dictionary/dictionary.txt
vendored
File diff suppressed because it is too large
Load Diff
@@ -1,3 +0,0 @@
|
|||||||
powf
|
|
||||||
sqrtf
|
|
||||||
isnan
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
ACLs
|
|
||||||
DACL
|
|
||||||
DACLs
|
|
||||||
LKG
|
|
||||||
mfcribbon
|
|
||||||
microsoft
|
|
||||||
microsoftonline
|
|
||||||
osgvsowi
|
|
||||||
powerrename
|
|
||||||
powershell
|
|
||||||
SACLs
|
|
||||||
tdbuildteamid
|
|
||||||
vcruntime
|
|
||||||
visualstudio
|
|
||||||
63
.github/actions/spell-check/excludes.txt
vendored
63
.github/actions/spell-check/excludes.txt
vendored
@@ -1,63 +0,0 @@
|
|||||||
(?:^|/)dirs$
|
|
||||||
(?:^|/)go\.mod$
|
|
||||||
(?:^|/)go\.sum$
|
|
||||||
(?:^|/)package-lock\.json$
|
|
||||||
(?:^|/)sources(?:|\.dep)$
|
|
||||||
SUMS$
|
|
||||||
\.ai$
|
|
||||||
\.bmp$
|
|
||||||
\.cer$
|
|
||||||
\.class$
|
|
||||||
\.crl$
|
|
||||||
\.crt$
|
|
||||||
\.csr$
|
|
||||||
\.dll$
|
|
||||||
\.DS_Store$
|
|
||||||
\.eot$
|
|
||||||
\.eps$
|
|
||||||
\.exe$
|
|
||||||
\.gif$
|
|
||||||
\.graffle$
|
|
||||||
\.gz$
|
|
||||||
\.icns$
|
|
||||||
\.ico$
|
|
||||||
\.jar$
|
|
||||||
\.jpeg$
|
|
||||||
\.jpg$
|
|
||||||
\.key$
|
|
||||||
\.lib$
|
|
||||||
\.lock$
|
|
||||||
\.map$
|
|
||||||
\.min\..
|
|
||||||
\.mp3$
|
|
||||||
\.mp4$
|
|
||||||
\.otf$
|
|
||||||
\.pbxproj$
|
|
||||||
\.pdf$
|
|
||||||
\.pem$
|
|
||||||
\.png$
|
|
||||||
\.psd$
|
|
||||||
\.runsettings$
|
|
||||||
\.sig$
|
|
||||||
\.so$
|
|
||||||
\.svg$
|
|
||||||
\.svgz$
|
|
||||||
\.tar$
|
|
||||||
\.tgz$
|
|
||||||
\.ttf$
|
|
||||||
\.woff
|
|
||||||
\.xcf$
|
|
||||||
\.xls
|
|
||||||
\.xpm$
|
|
||||||
\.yml$
|
|
||||||
\.zip$
|
|
||||||
^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/tools/U8U16Test/(?:fr|ru|zh)\.txt$
|
|
||||||
^\.github/actions/spell-check/
|
|
||||||
^\.gitignore$
|
|
||||||
15
.github/actions/spell-check/expect/web.txt
vendored
15
.github/actions/spell-check/expect/web.txt
vendored
@@ -1,15 +0,0 @@
|
|||||||
http
|
|
||||||
td
|
|
||||||
www
|
|
||||||
ecma
|
|
||||||
rapidtables
|
|
||||||
WCAG
|
|
||||||
freedesktop
|
|
||||||
ycombinator
|
|
||||||
robertelder
|
|
||||||
kovidgoyal
|
|
||||||
leonerd
|
|
||||||
fixterms
|
|
||||||
uk
|
|
||||||
winui
|
|
||||||
appshellintegration
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
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-]+\.githubusercontent\.com/[-a-zA-Z0-9?&=_\/.]*
|
|
||||||
[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
|
|
||||||
microsoft/cascadia-code\@[0-9a-fA-F]{40}
|
|
||||||
\d+x\d+Logo
|
|
||||||
Scro\&ll
|
|
||||||
# selectionInput.cpp
|
|
||||||
:\\windows\\syste\b
|
|
||||||
TestUtils::VerifyExpectedString\(tb, L"[^"]+"
|
|
||||||
hostSm\.ProcessString\(L"[^"]+"
|
|
||||||
\b([A-Za-z])\1{3,}\b
|
|
||||||
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>
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
# Dictionaries are lists of words to accept unconditionally
|
# Allow files are lists of words to accept unconditionally
|
||||||
|
|
||||||
While check spelling will complain about a whitelisted word
|
While check spelling will complain about an expected word
|
||||||
which is no longer present, you can include things here even if
|
which is no longer present, you can include things here even if
|
||||||
they are not otherwise present in the repository.
|
they are not otherwise present in the repository.
|
||||||
|
|
||||||
@@ -8,13 +8,14 @@ E.g., you could include a list of system APIs here, or potential
|
|||||||
contributors (so that if a future commit includes their name,
|
contributors (so that if a future commit includes their name,
|
||||||
it'll be accepted).
|
it'll be accepted).
|
||||||
|
|
||||||
### Files
|
## Files
|
||||||
|
|
||||||
| File | Description |
|
| File | Description |
|
||||||
| ---- | ----------- |
|
| ---- | ----------- |
|
||||||
| [Dictionary](dictionary.txt) | Primary US English dictionary |
|
| [Allow](allow.txt) | Supplements to the dictionary |
|
||||||
| [Chinese](chinese.txt) | Chinese words |
|
| [Chinese](chinese.txt) | Chinese words |
|
||||||
| [Japanese](japanese.txt) | Japanese words |
|
| [Japanese](japanese.txt) | Japanese words |
|
||||||
| [Microsoft](microsoft.txt) | Microsoft brand items |
|
| [Microsoft](microsoft.txt) | Microsoft brand items |
|
||||||
| [Fonts](fonts.txt) | Font names |
|
| [Fonts](fonts.txt) | Font names |
|
||||||
| [Names](names.txt) | Names of people |
|
| [Names](names.txt) | Names of people |
|
||||||
|
| [Colors](colors.txt) | Names of color |
|
||||||
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
|
||||||
248
.github/actions/spelling/allow/apis.txt
vendored
Normal file
248
.github/actions/spelling/allow/apis.txt
vendored
Normal file
@@ -0,0 +1,248 @@
|
|||||||
|
ACCEPTFILES
|
||||||
|
ACCESSDENIED
|
||||||
|
acl
|
||||||
|
aclapi
|
||||||
|
alignas
|
||||||
|
alignof
|
||||||
|
APPLYTOSUBMENUS
|
||||||
|
appxrecipe
|
||||||
|
bitfield
|
||||||
|
bitfields
|
||||||
|
BUILDBRANCH
|
||||||
|
BUILDMSG
|
||||||
|
BUILDNUMBER
|
||||||
|
BYCOMMAND
|
||||||
|
BYPOSITION
|
||||||
|
charconv
|
||||||
|
CLASSNOTAVAILABLE
|
||||||
|
CLOSEAPP
|
||||||
|
cmdletbinding
|
||||||
|
COLORPROPERTY
|
||||||
|
colspan
|
||||||
|
COMDLG
|
||||||
|
commandlinetoargv
|
||||||
|
comparand
|
||||||
|
cstdint
|
||||||
|
CXICON
|
||||||
|
CYICON
|
||||||
|
Dacl
|
||||||
|
dataobject
|
||||||
|
dcomp
|
||||||
|
DERR
|
||||||
|
dlldata
|
||||||
|
DNE
|
||||||
|
DONTADDTORECENT
|
||||||
|
DWMSBT
|
||||||
|
DWMWA
|
||||||
|
DWMWA
|
||||||
|
DWORDLONG
|
||||||
|
endfor
|
||||||
|
ENDSESSION
|
||||||
|
enumset
|
||||||
|
environstrings
|
||||||
|
EXPCMDFLAGS
|
||||||
|
EXPCMDSTATE
|
||||||
|
filetime
|
||||||
|
FILTERSPEC
|
||||||
|
FORCEFILESYSTEM
|
||||||
|
FORCEMINIMIZE
|
||||||
|
frac
|
||||||
|
fullkbd
|
||||||
|
futex
|
||||||
|
GETDESKWALLPAPER
|
||||||
|
GETHIGHCONTRAST
|
||||||
|
GETMOUSEHOVERTIME
|
||||||
|
Hashtable
|
||||||
|
HIGHCONTRASTON
|
||||||
|
HIGHCONTRASTW
|
||||||
|
hotkeys
|
||||||
|
href
|
||||||
|
hrgn
|
||||||
|
HTCLOSE
|
||||||
|
hwinsta
|
||||||
|
HWINSTA
|
||||||
|
IActivation
|
||||||
|
IApp
|
||||||
|
IAppearance
|
||||||
|
IAsync
|
||||||
|
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
|
||||||
|
LTGRAY
|
||||||
|
MAINWINDOW
|
||||||
|
memchr
|
||||||
|
memicmp
|
||||||
|
MENUCOMMAND
|
||||||
|
MENUDATA
|
||||||
|
MENUINFO
|
||||||
|
MENUITEMINFOW
|
||||||
|
mmeapi
|
||||||
|
MOUSELEAVE
|
||||||
|
mov
|
||||||
|
mptt
|
||||||
|
msappx
|
||||||
|
MULTIPLEUSE
|
||||||
|
NCHITTEST
|
||||||
|
NCLBUTTONDBLCLK
|
||||||
|
NCMOUSELEAVE
|
||||||
|
NCMOUSEMOVE
|
||||||
|
NCRBUTTONDBLCLK
|
||||||
|
NIF
|
||||||
|
NIN
|
||||||
|
NOAGGREGATION
|
||||||
|
NOASYNC
|
||||||
|
NOCHANGEDIR
|
||||||
|
NOPROGRESS
|
||||||
|
NOREDIRECTIONBITMAP
|
||||||
|
NOREPEAT
|
||||||
|
NOTIFYBYPOS
|
||||||
|
NOTIFYICON
|
||||||
|
NOTIFYICONDATA
|
||||||
|
ntprivapi
|
||||||
|
oaidl
|
||||||
|
ocidl
|
||||||
|
ODR
|
||||||
|
offsetof
|
||||||
|
ofstream
|
||||||
|
onefuzz
|
||||||
|
osver
|
||||||
|
OSVERSIONINFOEXW
|
||||||
|
otms
|
||||||
|
OUTLINETEXTMETRICW
|
||||||
|
overridable
|
||||||
|
PACL
|
||||||
|
PAGESCROLL
|
||||||
|
PATINVERT
|
||||||
|
PEXPLICIT
|
||||||
|
PICKFOLDERS
|
||||||
|
pmr
|
||||||
|
ptstr
|
||||||
|
QUERYENDSESSION
|
||||||
|
rcx
|
||||||
|
REGCLS
|
||||||
|
RETURNCMD
|
||||||
|
rfind
|
||||||
|
ROOTOWNER
|
||||||
|
roundf
|
||||||
|
RSHIFT
|
||||||
|
SACL
|
||||||
|
schandle
|
||||||
|
semver
|
||||||
|
serializer
|
||||||
|
SETVERSION
|
||||||
|
SHELLEXECUTEINFOW
|
||||||
|
shobjidl
|
||||||
|
SHOWHIDE
|
||||||
|
SHOWMINIMIZED
|
||||||
|
SHOWTIP
|
||||||
|
SINGLEUSE
|
||||||
|
SIZENS
|
||||||
|
smoothstep
|
||||||
|
snprintf
|
||||||
|
spsc
|
||||||
|
sregex
|
||||||
|
SRWLOC
|
||||||
|
SRWLOCK
|
||||||
|
STDCPP
|
||||||
|
STDMETHOD
|
||||||
|
strchr
|
||||||
|
strcpy
|
||||||
|
streambuf
|
||||||
|
strtoul
|
||||||
|
Stubless
|
||||||
|
Subheader
|
||||||
|
Subpage
|
||||||
|
syscall
|
||||||
|
SYSTEMBACKDROP
|
||||||
|
TABROW
|
||||||
|
TASKBARCREATED
|
||||||
|
TBPF
|
||||||
|
THEMECHANGED
|
||||||
|
tlg
|
||||||
|
TME
|
||||||
|
tmp
|
||||||
|
tmpdir
|
||||||
|
tolower
|
||||||
|
toupper
|
||||||
|
TRACKMOUSEEVENT
|
||||||
|
TTask
|
||||||
|
TVal
|
||||||
|
UChar
|
||||||
|
UFIELD
|
||||||
|
ULARGE
|
||||||
|
UOI
|
||||||
|
UPDATEINIFILE
|
||||||
|
userenv
|
||||||
|
USEROBJECTFLAGS
|
||||||
|
Viewbox
|
||||||
|
virtualalloc
|
||||||
|
wcsstr
|
||||||
|
wcstoui
|
||||||
|
winmain
|
||||||
|
winsta
|
||||||
|
winstamin
|
||||||
|
wmemcmp
|
||||||
|
wpc
|
||||||
|
WSF
|
||||||
|
wsregex
|
||||||
|
wwinmain
|
||||||
|
xchg
|
||||||
|
XDocument
|
||||||
|
XElement
|
||||||
|
xfacet
|
||||||
|
xhash
|
||||||
|
XIcon
|
||||||
|
xiosbase
|
||||||
|
xlocale
|
||||||
|
xlocbuf
|
||||||
|
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
|
||||||
@@ -1,8 +1,10 @@
|
|||||||
Consolas
|
Consolas
|
||||||
emoji
|
emoji
|
||||||
|
emojis
|
||||||
Extralight
|
Extralight
|
||||||
Gabriola
|
Gabriola
|
||||||
Iosevka
|
Iosevka
|
||||||
MDL
|
MDL
|
||||||
Monofur
|
Monofur
|
||||||
Segoe
|
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
|
||||||
85
.github/actions/spelling/allow/microsoft.txt
vendored
Normal file
85
.github/actions/spelling/allow/microsoft.txt
vendored
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
ACLs
|
||||||
|
ADMINS
|
||||||
|
advapi
|
||||||
|
altform
|
||||||
|
altforms
|
||||||
|
appendwttlogging
|
||||||
|
appx
|
||||||
|
appxbundle
|
||||||
|
appxerror
|
||||||
|
appxmanifest
|
||||||
|
ATL
|
||||||
|
backplating
|
||||||
|
bitmaps
|
||||||
|
BOMs
|
||||||
|
CPLs
|
||||||
|
cpptools
|
||||||
|
cppvsdbg
|
||||||
|
CPRs
|
||||||
|
cryptbase
|
||||||
|
DACL
|
||||||
|
DACLs
|
||||||
|
defaultlib
|
||||||
|
diffs
|
||||||
|
disposables
|
||||||
|
dotnetfeed
|
||||||
|
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
|
||||||
|
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
|
||||||
|
wtt
|
||||||
|
wttlog
|
||||||
|
Xamarin
|
||||||
@@ -1,43 +1,66 @@
|
|||||||
Anup
|
Anup
|
||||||
austdi
|
austdi
|
||||||
|
arkthur
|
||||||
Ballmer
|
Ballmer
|
||||||
bhoj
|
bhoj
|
||||||
Bhojwani
|
Bhojwani
|
||||||
|
Bluloco
|
||||||
carlos
|
carlos
|
||||||
dhowett
|
dhowett
|
||||||
Diviness
|
Diviness
|
||||||
dsafa
|
dsafa
|
||||||
duhowett
|
duhowett
|
||||||
|
DXP
|
||||||
|
ekg
|
||||||
|
eryksun
|
||||||
ethanschoonover
|
ethanschoonover
|
||||||
Firefox
|
Firefox
|
||||||
Gatta
|
Gatta
|
||||||
|
glsl
|
||||||
|
Gravell
|
||||||
Grie
|
Grie
|
||||||
Griese
|
Griese
|
||||||
Hernan
|
Hernan
|
||||||
Howett
|
Howett
|
||||||
Illhardt
|
Illhardt
|
||||||
|
iquilezles
|
||||||
|
italo
|
||||||
jantari
|
jantari
|
||||||
jerrysh
|
jerrysh
|
||||||
Kaiyu
|
Kaiyu
|
||||||
kimwalisch
|
kimwalisch
|
||||||
KMehrain
|
KMehrain
|
||||||
|
KODELIFE
|
||||||
|
Kodelife
|
||||||
Kourosh
|
Kourosh
|
||||||
kowalczyk
|
kowalczyk
|
||||||
leonmsft
|
leonmsft
|
||||||
Lepilleur
|
Lepilleur
|
||||||
|
lhecker
|
||||||
|
lukesampson
|
||||||
|
Macbook
|
||||||
Manandhar
|
Manandhar
|
||||||
|
masserano
|
||||||
mbadolato
|
mbadolato
|
||||||
Mehrain
|
Mehrain
|
||||||
|
menger
|
||||||
mgravell
|
mgravell
|
||||||
michaelniksa
|
michaelniksa
|
||||||
|
michkap
|
||||||
migrie
|
migrie
|
||||||
mikegr
|
mikegr
|
||||||
mikemaccana
|
mikemaccana
|
||||||
|
miloush
|
||||||
miniksa
|
miniksa
|
||||||
niksa
|
niksa
|
||||||
|
nvaccess
|
||||||
|
nvda
|
||||||
oising
|
oising
|
||||||
oldnewthing
|
oldnewthing
|
||||||
|
opengl
|
||||||
osgwiki
|
osgwiki
|
||||||
|
pabhojwa
|
||||||
|
panos
|
||||||
paulcam
|
paulcam
|
||||||
pauldotknopf
|
pauldotknopf
|
||||||
PGP
|
PGP
|
||||||
@@ -45,11 +68,18 @@ Pham
|
|||||||
Rincewind
|
Rincewind
|
||||||
rprichard
|
rprichard
|
||||||
Schoonover
|
Schoonover
|
||||||
|
shadertoy
|
||||||
|
Shomnipotence
|
||||||
|
simioni
|
||||||
Somuah
|
Somuah
|
||||||
sonph
|
sonph
|
||||||
sonpham
|
sonpham
|
||||||
stakx
|
stakx
|
||||||
|
talo
|
||||||
|
thereses
|
||||||
Walisch
|
Walisch
|
||||||
|
WDX
|
||||||
|
Wellons
|
||||||
Wirt
|
Wirt
|
||||||
Wojciech
|
Wojciech
|
||||||
zadjii
|
zadjii
|
||||||
523
.github/actions/spelling/candidate.patterns
vendored
Normal file
523
.github/actions/spelling/candidate.patterns
vendored
Normal file
@@ -0,0 +1,523 @@
|
|||||||
|
# marker to ignore all code on line
|
||||||
|
^.*/\* #no-spell-check-line \*/.*$
|
||||||
|
# marker for ignoring a comment to the end of the line
|
||||||
|
// #no-spell-check.*$
|
||||||
|
|
||||||
|
# patch hunk comments
|
||||||
|
^\@\@ -\d+(?:,\d+|) \+\d+(?:,\d+|) \@\@ .*
|
||||||
|
# git index header
|
||||||
|
index [0-9a-z]{7,40}\.\.[0-9a-z]{7,40}
|
||||||
|
|
||||||
|
# cid urls
|
||||||
|
(['"])cid:.*?\g{-1}
|
||||||
|
|
||||||
|
# data url in parens
|
||||||
|
\(data:[^)]*?(?:[A-Z]{3,}|[A-Z][a-z]{2,}|[a-z]{3,})[^)]*\)
|
||||||
|
# data url in quotes
|
||||||
|
([`'"])data:.*?(?:[A-Z]{3,}|[A-Z][a-z]{2,}|[a-z]{3,}).*\g{-1}
|
||||||
|
# data url
|
||||||
|
data:[-a-zA-Z=;:/0-9+]*,\S*
|
||||||
|
|
||||||
|
# mailto urls
|
||||||
|
mailto:[-a-zA-Z=;:/?%&0-9+@.]{3,}
|
||||||
|
|
||||||
|
# magnet urls
|
||||||
|
magnet:[?=:\w]+
|
||||||
|
|
||||||
|
# magnet urls
|
||||||
|
"magnet:[^"]+"
|
||||||
|
|
||||||
|
# obs:
|
||||||
|
"obs:[^"]*"
|
||||||
|
|
||||||
|
# The `\b` here means a break, it's the fancy way to handle urls, but it makes things harder to read
|
||||||
|
# In this examples content, I'm using a number of different ways to match things to show various approaches
|
||||||
|
# asciinema
|
||||||
|
\basciinema\.org/a/[0-9a-zA-Z]+
|
||||||
|
|
||||||
|
# apple
|
||||||
|
\bdeveloper\.apple\.com/[-\w?=/]+
|
||||||
|
# Apple music
|
||||||
|
\bembed\.music\.apple\.com/fr/playlist/usr-share/[-\w.]+
|
||||||
|
|
||||||
|
# appveyor api
|
||||||
|
\bci\.appveyor\.com/api/projects/status/[0-9a-z]+
|
||||||
|
# appveyor project
|
||||||
|
\bci\.appveyor\.com/project/(?:[^/\s"]*/){2}builds?/\d+/job/[0-9a-z]+
|
||||||
|
|
||||||
|
# Amazon
|
||||||
|
|
||||||
|
# Amazon
|
||||||
|
\bamazon\.com/[-\w]+/(?:dp/[0-9A-Z]+|)
|
||||||
|
# AWS S3
|
||||||
|
\b\w*\.s3[^.]*\.amazonaws\.com/[-\w/&#%_?:=]*
|
||||||
|
# AWS execute-api
|
||||||
|
\b[0-9a-z]{10}\.execute-api\.[-0-9a-z]+\.amazonaws\.com\b
|
||||||
|
# AWS ELB
|
||||||
|
\b\w+\.[-0-9a-z]+\.elb\.amazonaws\.com\b
|
||||||
|
# AWS SNS
|
||||||
|
\bsns\.[-0-9a-z]+.amazonaws\.com/[-\w/&#%_?:=]*
|
||||||
|
# AWS VPC
|
||||||
|
vpc-\w+
|
||||||
|
|
||||||
|
# While you could try to match `http://` and `https://` by using `s?` in `https?://`, sometimes there
|
||||||
|
# YouTube url
|
||||||
|
\b(?:(?:www\.|)youtube\.com|youtu.be)/(?:channel/|embed/|user/|playlist\?list=|watch\?v=|v/|)[-a-zA-Z0-9?&=_%]*
|
||||||
|
# YouTube music
|
||||||
|
\bmusic\.youtube\.com/youtubei/v1/browse(?:[?&]\w+=[-a-zA-Z0-9?&=_]*)
|
||||||
|
# YouTube tag
|
||||||
|
<\s*youtube\s+id=['"][-a-zA-Z0-9?_]*['"]
|
||||||
|
# YouTube image
|
||||||
|
\bimg\.youtube\.com/vi/[-a-zA-Z0-9?&=_]*
|
||||||
|
# Google Accounts
|
||||||
|
\baccounts.google.com/[-_/?=.:;+%&0-9a-zA-Z]*
|
||||||
|
# Google Analytics
|
||||||
|
\bgoogle-analytics\.com/collect.[-0-9a-zA-Z?%=&_.~]*
|
||||||
|
# Google APIs
|
||||||
|
\bgoogleapis\.(?:com|dev)/[a-z]+/(?:v\d+/|)[a-z]+/[-@:./?=\w+|&]+
|
||||||
|
# Google Storage
|
||||||
|
\b[-a-zA-Z0-9.]*\bstorage\d*\.googleapis\.com(?:/\S*|)
|
||||||
|
# Google Calendar
|
||||||
|
\bcalendar\.google\.com/calendar(?:/u/\d+|)/embed\?src=[@./?=\w&%]+
|
||||||
|
\w+\@group\.calendar\.google\.com\b
|
||||||
|
# Google DataStudio
|
||||||
|
\bdatastudio\.google\.com/(?:(?:c/|)u/\d+/|)(?:embed/|)(?:open|reporting|datasources|s)/[-0-9a-zA-Z]+(?:/page/[-0-9a-zA-Z]+|)
|
||||||
|
# The leading `/` here is as opposed to the `\b` above
|
||||||
|
# ... a short way to match `https://` or `http://` since most urls have one of those prefixes
|
||||||
|
# Google Docs
|
||||||
|
/docs\.google\.com/[a-z]+/(?:ccc\?key=\w+|(?:u/\d+|d/(?:e/|)[0-9a-zA-Z_-]+/)?(?:edit\?[-\w=#.]*|/\?[\w=&]*|))
|
||||||
|
# Google Drive
|
||||||
|
\bdrive\.google\.com/(?:file/d/|open)[-0-9a-zA-Z_?=]*
|
||||||
|
# Google Groups
|
||||||
|
\bgroups\.google\.com/(?:(?:forum/#!|d/)(?:msg|topics?|searchin)|a)/[^/\s"]+/[-a-zA-Z0-9$]+(?:/[-a-zA-Z0-9]+)*
|
||||||
|
# Google Maps
|
||||||
|
\bmaps\.google\.com/maps\?[\w&;=]*
|
||||||
|
# Google themes
|
||||||
|
themes\.googleusercontent\.com/static/fonts/[^/\s"]+/v\d+/[^.]+.
|
||||||
|
# Google CDN
|
||||||
|
\bclients2\.google(?:usercontent|)\.com[-0-9a-zA-Z/.]*
|
||||||
|
# Goo.gl
|
||||||
|
/goo\.gl/[a-zA-Z0-9]+
|
||||||
|
# Google Chrome Store
|
||||||
|
\bchrome\.google\.com/webstore/detail/[-\w]*(?:/\w*|)
|
||||||
|
# Google Books
|
||||||
|
\bgoogle\.(?:\w{2,4})/books(?:/\w+)*\?[-\w\d=&#.]*
|
||||||
|
# Google Fonts
|
||||||
|
\bfonts\.(?:googleapis|gstatic)\.com/[-/?=:;+&0-9a-zA-Z]*
|
||||||
|
# Google Forms
|
||||||
|
\bforms\.gle/\w+
|
||||||
|
# Google Scholar
|
||||||
|
\bscholar\.google\.com/citations\?user=[A-Za-z0-9_]+
|
||||||
|
# Google Colab Research Drive
|
||||||
|
\bcolab\.research\.google\.com/drive/[-0-9a-zA-Z_?=]*
|
||||||
|
|
||||||
|
# GitHub SHAs (api)
|
||||||
|
\bapi.github\.com/repos(?:/[^/\s"]+){3}/[0-9a-f]+\b
|
||||||
|
# GitHub SHAs (markdown)
|
||||||
|
(?:\[`?[0-9a-f]+`?\]\(https:/|)/(?:www\.|)github\.com(?:/[^/\s"]+){2,}(?:/[^/\s")]+)(?:[0-9a-f]+(?:[-0-9a-zA-Z/#.]*|)\b|)
|
||||||
|
# GitHub SHAs
|
||||||
|
\bgithub\.com(?:/[^/\s"]+){2}[@#][0-9a-f]+\b
|
||||||
|
# GitHub wiki
|
||||||
|
\bgithub\.com/(?:[^/]+/){2}wiki/(?:(?:[^/]+/|)_history|[^/]+(?:/_compare|)/[0-9a-f.]{40,})\b
|
||||||
|
# githubusercontent
|
||||||
|
/[-a-z0-9]+\.githubusercontent\.com/[-a-zA-Z0-9?&=_\/.]*
|
||||||
|
# githubassets
|
||||||
|
\bgithubassets.com/[0-9a-f]+(?:[-/\w.]+)
|
||||||
|
# gist github
|
||||||
|
\bgist\.github\.com/[^/\s"]+/[0-9a-f]+
|
||||||
|
# git.io
|
||||||
|
\bgit\.io/[0-9a-zA-Z]+
|
||||||
|
# GitHub JSON
|
||||||
|
"node_id": "[-a-zA-Z=;:/0-9+]*"
|
||||||
|
# Contributor
|
||||||
|
\[[^\]]+\]\(https://github\.com/[^/\s"]+\)
|
||||||
|
# GHSA
|
||||||
|
GHSA(?:-[0-9a-z]{4}){3}
|
||||||
|
|
||||||
|
# GitLab commit
|
||||||
|
\bgitlab\.[^/\s"]*/\S+/\S+/commit/[0-9a-f]{7,16}#[0-9a-f]{40}\b
|
||||||
|
# GitLab merge requests
|
||||||
|
\bgitlab\.[^/\s"]*/\S+/\S+/-/merge_requests/\d+/diffs#[0-9a-f]{40}\b
|
||||||
|
# GitLab uploads
|
||||||
|
\bgitlab\.[^/\s"]*/uploads/[-a-zA-Z=;:/0-9+]*
|
||||||
|
# GitLab commits
|
||||||
|
\bgitlab\.[^/\s"]*/(?:[^/\s"]+/){2}commits?/[0-9a-f]+\b
|
||||||
|
|
||||||
|
# binanace
|
||||||
|
accounts.binance.com/[a-z/]*oauth/authorize\?[-0-9a-zA-Z&%]*
|
||||||
|
|
||||||
|
# bitbucket diff
|
||||||
|
\bapi\.bitbucket\.org/\d+\.\d+/repositories/(?:[^/\s"]+/){2}diff(?:stat|)(?:/[^/\s"]+){2}:[0-9a-f]+
|
||||||
|
# bitbucket repositories commits
|
||||||
|
\bapi\.bitbucket\.org/\d+\.\d+/repositories/(?:[^/\s"]+/){2}commits?/[0-9a-f]+
|
||||||
|
# bitbucket commits
|
||||||
|
\bbitbucket\.org/(?:[^/\s"]+/){2}commits?/[0-9a-f]+
|
||||||
|
|
||||||
|
# bit.ly
|
||||||
|
\bbit\.ly/\w+
|
||||||
|
|
||||||
|
# bitrise
|
||||||
|
\bapp\.bitrise\.io/app/[0-9a-f]*/[\w.?=&]*
|
||||||
|
|
||||||
|
# bootstrapcdn.com
|
||||||
|
\bbootstrapcdn\.com/[-./\w]+
|
||||||
|
|
||||||
|
# cdn.cloudflare.com
|
||||||
|
\bcdnjs\.cloudflare\.com/[./\w]+
|
||||||
|
|
||||||
|
# circleci
|
||||||
|
\bcircleci\.com/gh(?:/[^/\s"]+){1,5}.[a-z]+\?[-0-9a-zA-Z=&]+
|
||||||
|
|
||||||
|
# gitter
|
||||||
|
\bgitter\.im(?:/[^/\s"]+){2}\?at=[0-9a-f]+
|
||||||
|
|
||||||
|
# gravatar
|
||||||
|
\bgravatar\.com/avatar/[0-9a-f]+
|
||||||
|
|
||||||
|
# ibm
|
||||||
|
[a-z.]*ibm\.com/[-_#=:%!?~.\\/\d\w]*
|
||||||
|
|
||||||
|
# imgur
|
||||||
|
\bimgur\.com/[^.]+
|
||||||
|
|
||||||
|
# Internet Archive
|
||||||
|
\barchive\.org/web/\d+/(?:[-\w.?,'/\\+&%$#_:]*)
|
||||||
|
|
||||||
|
# discord
|
||||||
|
/discord(?:app\.com|\.gg)/(?:invite/)?[a-zA-Z0-9]{7,}
|
||||||
|
|
||||||
|
# Disqus
|
||||||
|
\bdisqus\.com/[-\w/%.()!?&=_]*
|
||||||
|
|
||||||
|
# medium link
|
||||||
|
\blink\.medium\.com/[a-zA-Z0-9]+
|
||||||
|
# medium
|
||||||
|
\bmedium\.com/\@?[^/\s"]+/[-\w]+
|
||||||
|
|
||||||
|
# microsoft
|
||||||
|
\b(?:https?://|)(?:(?:download\.visualstudio|docs|msdn2?|research)\.microsoft|blogs\.msdn)\.com/[-_a-zA-Z0-9()=./%]*
|
||||||
|
# powerbi
|
||||||
|
\bapp\.powerbi\.com/reportEmbed/[^"' ]*
|
||||||
|
# vs devops
|
||||||
|
\bvisualstudio.com(?::443|)/[-\w/?=%&.]*
|
||||||
|
# microsoft store
|
||||||
|
\bmicrosoft\.com/store/apps/\w+
|
||||||
|
|
||||||
|
# mvnrepository.com
|
||||||
|
\bmvnrepository\.com/[-0-9a-z./]+
|
||||||
|
|
||||||
|
# now.sh
|
||||||
|
/[0-9a-z-.]+\.now\.sh\b
|
||||||
|
|
||||||
|
# oracle
|
||||||
|
\bdocs\.oracle\.com/[-0-9a-zA-Z./_?#&=]*
|
||||||
|
|
||||||
|
# chromatic.com
|
||||||
|
/\S+.chromatic.com\S*[")]
|
||||||
|
|
||||||
|
# codacy
|
||||||
|
\bapi\.codacy\.com/project/badge/Grade/[0-9a-f]+
|
||||||
|
|
||||||
|
# compai
|
||||||
|
\bcompai\.pub/v1/png/[0-9a-f]+
|
||||||
|
|
||||||
|
# mailgun api
|
||||||
|
\.api\.mailgun\.net/v3/domains/[0-9a-z]+\.mailgun.org/messages/[0-9a-zA-Z=@]*
|
||||||
|
# mailgun
|
||||||
|
\b[0-9a-z]+.mailgun.org
|
||||||
|
|
||||||
|
# /message-id/
|
||||||
|
/message-id/[-\w@./%]+
|
||||||
|
|
||||||
|
# Reddit
|
||||||
|
\breddit\.com/r/[/\w_]*
|
||||||
|
|
||||||
|
# requestb.in
|
||||||
|
\brequestb\.in/[0-9a-z]+
|
||||||
|
|
||||||
|
# sched
|
||||||
|
\b[a-z0-9]+\.sched\.com\b
|
||||||
|
|
||||||
|
# Slack url
|
||||||
|
slack://[a-zA-Z0-9?&=]+
|
||||||
|
# Slack
|
||||||
|
\bslack\.com/[-0-9a-zA-Z/_~?&=.]*
|
||||||
|
# Slack edge
|
||||||
|
\bslack-edge\.com/[-a-zA-Z0-9?&=%./]+
|
||||||
|
# Slack images
|
||||||
|
\bslack-imgs\.com/[-a-zA-Z0-9?&=%.]+
|
||||||
|
|
||||||
|
# shields.io
|
||||||
|
\bshields\.io/[-\w/%?=&.:+;,]*
|
||||||
|
|
||||||
|
# stackexchange -- https://stackexchange.com/feeds/sites
|
||||||
|
\b(?:askubuntu|serverfault|stack(?:exchange|overflow)|superuser).com/(?:questions/\w+/[-\w]+|a/)
|
||||||
|
|
||||||
|
# Sentry
|
||||||
|
[0-9a-f]{32}\@o\d+\.ingest\.sentry\.io\b
|
||||||
|
|
||||||
|
# Twitter markdown
|
||||||
|
\[\@[^[/\]:]*?\]\(https://twitter.com/[^/\s"')]*(?:/status/\d+(?:\?[-_0-9a-zA-Z&=]*|)|)\)
|
||||||
|
# Twitter hashtag
|
||||||
|
\btwitter\.com/hashtag/[\w?_=&]*
|
||||||
|
# Twitter status
|
||||||
|
\btwitter\.com/[^/\s"')]*(?:/status/\d+(?:\?[-_0-9a-zA-Z&=]*|)|)
|
||||||
|
# Twitter profile images
|
||||||
|
\btwimg\.com/profile_images/[_\w./]*
|
||||||
|
# Twitter media
|
||||||
|
\btwimg\.com/media/[-_\w./?=]*
|
||||||
|
# Twitter link shortened
|
||||||
|
\bt\.co/\w+
|
||||||
|
|
||||||
|
# facebook
|
||||||
|
\bfburl\.com/[0-9a-z_]+
|
||||||
|
# facebook CDN
|
||||||
|
\bfbcdn\.net/[\w/.,]*
|
||||||
|
# facebook watch
|
||||||
|
\bfb\.watch/[0-9A-Za-z]+
|
||||||
|
|
||||||
|
# dropbox
|
||||||
|
\bdropbox\.com/sh?/[^/\s"]+/[-0-9A-Za-z_.%?=&;]+
|
||||||
|
|
||||||
|
# ipfs protocol
|
||||||
|
ipfs://[0-9a-z]*
|
||||||
|
# ipfs url
|
||||||
|
/ipfs/[0-9a-z]*
|
||||||
|
|
||||||
|
# w3
|
||||||
|
\bw3\.org/[-0-9a-zA-Z/#.]+
|
||||||
|
|
||||||
|
# loom
|
||||||
|
\bloom\.com/embed/[0-9a-f]+
|
||||||
|
|
||||||
|
# regex101
|
||||||
|
\bregex101\.com/r/[^/\s"]+/\d+
|
||||||
|
|
||||||
|
# figma
|
||||||
|
\bfigma\.com/file(?:/[0-9a-zA-Z]+/)+
|
||||||
|
|
||||||
|
# freecodecamp.org
|
||||||
|
\bfreecodecamp\.org/[-\w/.]+
|
||||||
|
|
||||||
|
# image.tmdb.org
|
||||||
|
\bimage\.tmdb\.org/[/\w.]+
|
||||||
|
|
||||||
|
# mermaid
|
||||||
|
\bmermaid\.ink/img/[-\w]+|\bmermaid-js\.github\.io/mermaid-live-editor/#/edit/[-\w]+
|
||||||
|
|
||||||
|
# Wikipedia
|
||||||
|
\ben\.wikipedia\.org/wiki/[-\w%.#]+
|
||||||
|
|
||||||
|
# gitweb
|
||||||
|
[^"\s]+/gitweb/\S+;h=[0-9a-f]+
|
||||||
|
|
||||||
|
# HyperKitty lists
|
||||||
|
/archives/list/[^@/]+\@[^/\s"]*/message/[^/\s"]*/
|
||||||
|
|
||||||
|
# lists
|
||||||
|
/thread\.html/[^"\s]+
|
||||||
|
|
||||||
|
# list-management
|
||||||
|
\blist-manage\.com/subscribe(?:[?&](?:u|id)=[0-9a-f]+)+
|
||||||
|
|
||||||
|
# kubectl.kubernetes.io/last-applied-configuration
|
||||||
|
"kubectl.kubernetes.io/last-applied-configuration": ".*"
|
||||||
|
|
||||||
|
# pgp
|
||||||
|
\bgnupg\.net/pks/lookup[?&=0-9a-zA-Z]*
|
||||||
|
|
||||||
|
# Spotify
|
||||||
|
\bopen\.spotify\.com/embed/playlist/\w+
|
||||||
|
|
||||||
|
# Mastodon
|
||||||
|
\bmastodon\.[-a-z.]*/(?:media/|\@)[?&=0-9a-zA-Z_]*
|
||||||
|
|
||||||
|
# scastie
|
||||||
|
\bscastie\.scala-lang\.org/[^/]+/\w+
|
||||||
|
|
||||||
|
# images.unsplash.com
|
||||||
|
\bimages\.unsplash\.com/(?:(?:flagged|reserve)/|)[-\w./%?=%&.;]+
|
||||||
|
|
||||||
|
# pastebin
|
||||||
|
\bpastebin\.com/[\w/]+
|
||||||
|
|
||||||
|
# heroku
|
||||||
|
\b\w+\.heroku\.com/source/archive/\w+
|
||||||
|
|
||||||
|
# quip
|
||||||
|
\b\w+\.quip\.com/\w+(?:(?:#|/issues/)\w+)?
|
||||||
|
|
||||||
|
# badgen.net
|
||||||
|
\bbadgen\.net/badge/[^")\]'\s]+
|
||||||
|
|
||||||
|
# statuspage.io
|
||||||
|
\w+\.statuspage\.io\b
|
||||||
|
|
||||||
|
# media.giphy.com
|
||||||
|
\bmedia\.giphy\.com/media/[^/]+/[\w.?&=]+
|
||||||
|
|
||||||
|
# tinyurl
|
||||||
|
\btinyurl\.com/\w+
|
||||||
|
|
||||||
|
# getopts
|
||||||
|
\bgetopts\s+(?:"[^"]+"|'[^']+')
|
||||||
|
|
||||||
|
# ANSI color codes
|
||||||
|
(?:\\(?:u00|x)1b|\x1b)\[\d+(?:;\d+|)m
|
||||||
|
|
||||||
|
# URL escaped characters
|
||||||
|
\%[0-9A-F][A-F]
|
||||||
|
# IPv6
|
||||||
|
\b(?:[0-9a-fA-F]{0,4}:){3,7}[0-9a-fA-F]{0,4}\b
|
||||||
|
# c99 hex digits (not the full format, just one I've seen)
|
||||||
|
0x[0-9a-fA-F](?:\.[0-9a-fA-F]*|)[pP]
|
||||||
|
# Punycode
|
||||||
|
\bxn--[-0-9a-z]+
|
||||||
|
# sha
|
||||||
|
sha\d+:[0-9]*[a-f]{3,}[0-9a-f]*
|
||||||
|
# sha-... -- uses a fancy capture
|
||||||
|
(['"]|")[0-9a-f]{40,}\g{-1}
|
||||||
|
# hex runs
|
||||||
|
\b[0-9a-fA-F]{16,}\b
|
||||||
|
# hex in url queries
|
||||||
|
=[0-9a-fA-F]*?(?:[A-F]{3,}|[a-f]{3,})[0-9a-fA-F]*?&
|
||||||
|
# ssh
|
||||||
|
(?:ssh-\S+|-nistp256) [-a-zA-Z=;:/0-9+]{12,}
|
||||||
|
|
||||||
|
# PGP
|
||||||
|
\b(?:[0-9A-F]{4} ){9}[0-9A-F]{4}\b
|
||||||
|
# GPG keys
|
||||||
|
\b(?:[0-9A-F]{4} ){5}(?: [0-9A-F]{4}){5}\b
|
||||||
|
# Well known gpg keys
|
||||||
|
.well-known/openpgpkey/[\w./]+
|
||||||
|
|
||||||
|
# uuid:
|
||||||
|
\b[0-9a-fA-F]{8}-(?:[0-9a-fA-F]{4}-){3}[0-9a-fA-F]{12}\b
|
||||||
|
# hex digits including css/html color classes:
|
||||||
|
(?:[\\0][xX]|\\u|[uU]\+|#x?|\%23)[0-9_a-fA-FgGrR]*?[a-fA-FgGrR]{2,}[0-9_a-fA-FgGrR]*(?:[uUlL]{0,3}|u\d+)\b
|
||||||
|
# integrity
|
||||||
|
integrity="sha\d+-[-a-zA-Z=;:/0-9+]{40,}"
|
||||||
|
|
||||||
|
# https://www.gnu.org/software/groff/manual/groff.html
|
||||||
|
# man troff content
|
||||||
|
\\f[BCIPR]
|
||||||
|
# '
|
||||||
|
\\\(aq
|
||||||
|
|
||||||
|
# .desktop mime types
|
||||||
|
^MimeTypes?=.*$
|
||||||
|
# .desktop localized entries
|
||||||
|
^[A-Z][a-z]+\[[a-z]+\]=.*$
|
||||||
|
# Localized .desktop content
|
||||||
|
Name\[[^\]]+\]=.*
|
||||||
|
|
||||||
|
# IServiceProvider
|
||||||
|
\bI(?=(?:[A-Z][a-z]{2,})+\b)
|
||||||
|
|
||||||
|
# crypt
|
||||||
|
"\$2[ayb]\$.{56}"
|
||||||
|
|
||||||
|
# scrypt / argon
|
||||||
|
\$(?:scrypt|argon\d+[di]*)\$\S+
|
||||||
|
|
||||||
|
# Input to GitHub JSON
|
||||||
|
content: "[-a-zA-Z=;:/0-9+]*="
|
||||||
|
|
||||||
|
# Python stringprefix / binaryprefix
|
||||||
|
# Note that there's a high false positive rate, remove the `?=` and search for the regex to see if the matches seem like reasonable strings
|
||||||
|
(?<!')\b(?:B|BR|Br|F|FR|Fr|R|RB|RF|Rb|Rf|U|UR|Ur|b|bR|br|f|fR|fr|r|rB|rF|rb|rf|u|uR|ur)'(?:[A-Z]{3,}|[A-Z][a-z]{2,}|[a-z]{3,})
|
||||||
|
|
||||||
|
# Regular expressions for (P|p)assword
|
||||||
|
\([A-Z]\|[a-z]\)[a-z]+
|
||||||
|
|
||||||
|
# JavaScript regular expressions
|
||||||
|
# javascript test regex
|
||||||
|
/.*/[gim]*\.test\(
|
||||||
|
# javascript match regex
|
||||||
|
\.match\(/[^/\s"]*/[gim]*\s*
|
||||||
|
# javascript match regex
|
||||||
|
\.match\(/\\[b].*?/[gim]*\s*\)(?:;|$)
|
||||||
|
# javascript regex
|
||||||
|
^\s*/\\[b].*/[gim]*\s*(?:\)(?:;|$)|,$)
|
||||||
|
# javascript replace regex
|
||||||
|
\.replace\(/[^/\s"]*/[gim]*\s*,
|
||||||
|
|
||||||
|
# Go regular expressions
|
||||||
|
regexp?\.MustCompile\(`[^`]*`\)
|
||||||
|
|
||||||
|
# sed regular expressions
|
||||||
|
sed 's/(?:[^/]*?[a-zA-Z]{3,}[^/]*?/){2}
|
||||||
|
|
||||||
|
# go install
|
||||||
|
go install(?:\s+[a-z]+\.[-@\w/.]+)+
|
||||||
|
|
||||||
|
# kubernetes pod status lists
|
||||||
|
# https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#pod-phase
|
||||||
|
\w+(?:-\w+)+\s+\d+/\d+\s+(?:Running|Pending|Succeeded|Failed|Unknown)\s+
|
||||||
|
|
||||||
|
# kubectl - pods in CrashLoopBackOff
|
||||||
|
\w+-[0-9a-f]+-\w+\s+\d+/\d+\s+CrashLoopBackOff\s+
|
||||||
|
|
||||||
|
# kubernetes object suffix
|
||||||
|
-[0-9a-f]{10}-\w{5}\s
|
||||||
|
|
||||||
|
# posthog secrets
|
||||||
|
posthog\.init\((['"])phc_[^"',]+\g{-1},
|
||||||
|
|
||||||
|
# xcode
|
||||||
|
|
||||||
|
# xcodeproject scenes
|
||||||
|
(?:Controller|ID|id)="\w{3}-\w{2}-\w{3}"
|
||||||
|
|
||||||
|
# xcode api botches
|
||||||
|
customObjectInstantitationMethod
|
||||||
|
|
||||||
|
# font awesome classes
|
||||||
|
\.fa-[-a-z0-9]+
|
||||||
|
|
||||||
|
# Update Lorem based on your content (requires `ge` and `w` from https://github.com/jsoref/spelling; and `review` from https://github.com/check-spelling/check-spelling/wiki/Looking-for-items-locally )
|
||||||
|
# grep '^[^#].*lorem' .github/actions/spelling/patterns.txt|perl -pne 's/.*i..\?://;s/\).*//' |tr '|' "\n"|sort -f |xargs -n1 ge|perl -pne 's/^[^:]*://'|sort -u|w|sed -e 's/ .*//'|w|review -
|
||||||
|
# Warning, while `(?i)` is very neat and fancy, if you have some binary files that aren't proper unicode, you might run into:
|
||||||
|
## Operation "substitution (s///)" returns its argument for non-Unicode code point 0x1C19AE (the code point will vary).
|
||||||
|
## You could manually change `(?i)X...` to use `[Xx]...`
|
||||||
|
## or you could add the files to your `excludes` file (a version after 0.0.19 should identify the file path)
|
||||||
|
# Lorem
|
||||||
|
(?:\w|\s|[,.])*\b(?i)(?:amet|consectetur|cursus|dolor|eros|ipsum|lacus|libero|ligula|lorem|magna|neque|nulla|suscipit|tempus)\b(?:\w|\s|[,.])*
|
||||||
|
|
||||||
|
# Non-English
|
||||||
|
[a-zA-Z]*[ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýÿĀāŁłŃńŅņŒœŚśŠšŜŝŸŽžź][a-zA-Z]{3}[a-zA-ZÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýÿĀāŁłŃńŅņŒœŚśŠšŜŝŸŽžź]*
|
||||||
|
|
||||||
|
# French
|
||||||
|
# This corpus only had capital letters, but you probably want lowercase ones as well.
|
||||||
|
\b[LN]'+[a-z]{2,}\b
|
||||||
|
|
||||||
|
# latex
|
||||||
|
\\(?:n(?:ew|ormal|osub)|r(?:enew)|t(?:able(?:of|)|he|itle))(?=[a-z]+)
|
||||||
|
|
||||||
|
# the negative lookahead here is to allow catching 'templatesz' as a misspelling
|
||||||
|
# but to otherwise recognize a Windows path with \templates\foo.template or similar:
|
||||||
|
\\(?:necessary|r(?:eport|esolve[dr]?|esult)|t(?:arget|emplates?))(?![a-z])
|
||||||
|
# ignore long runs of a single character:
|
||||||
|
\b([A-Za-z])\g{-1}{3,}\b
|
||||||
|
# Note that the next example is no longer necessary if you are using
|
||||||
|
# to match a string starting with a `#`, use a character-class:
|
||||||
|
[#]backwards
|
||||||
|
# version suffix <word>v#
|
||||||
|
(?:(?<=[A-Z]{2})V|(?<=[a-z]{2}|[A-Z]{2})v)\d+(?:\b|(?=[a-zA-Z_]))
|
||||||
|
# Compiler flags (Scala)
|
||||||
|
(?:^|[\t ,>"'`=(])-J-[DPWXY](?=[A-Z]{2,}|[A-Z][a-z]|[a-z]{2,})
|
||||||
|
# Compiler flags
|
||||||
|
#(?:^|[\t ,"'`=(])-[DPWXYLlf](?=[A-Z]{2,}|[A-Z][a-z]|[a-z]{2,})
|
||||||
|
|
||||||
|
# Compiler flags (linker)
|
||||||
|
,-B
|
||||||
|
# curl arguments
|
||||||
|
\b(?:\\n|)curl(?:\s+-[a-zA-Z]{1,2}\b)*(?:\s+-[a-zA-Z]{3,})(?:\s+-[a-zA-Z]+)*
|
||||||
|
# set arguments
|
||||||
|
\bset(?:\s+-[abefimouxE]{1,2})*\s+-[abefimouxE]{3,}(?:\s+-[abefimouxE]+)*
|
||||||
|
# tar arguments
|
||||||
|
\b(?:\\n|)g?tar(?:\.exe|)(?:(?:\s+--[-a-zA-Z]+|\s+-[a-zA-Z]+|\s[ABGJMOPRSUWZacdfh-pr-xz]+\b)(?:=[^ ]*|))+
|
||||||
|
# tput arguments -- https://man7.org/linux/man-pages/man5/terminfo.5.html -- technically they can be more than 5 chars long...
|
||||||
|
\btput\s+(?:(?:-[SV]|-T\s*\w+)\s+)*\w{3,5}\b
|
||||||
|
# macOS temp folders
|
||||||
|
/var/folders/\w\w/[+\w]+/(?:T|-Caches-)/
|
||||||
117
.github/actions/spelling/excludes.txt
vendored
Normal file
117
.github/actions/spelling/excludes.txt
vendored
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
# 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$
|
||||||
|
(?:^|/)sources(?:|\.dep)$
|
||||||
|
(?:^|/)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$
|
||||||
|
\.lib$
|
||||||
|
\.lock$
|
||||||
|
\.map$
|
||||||
|
\.min\..
|
||||||
|
\.mod$
|
||||||
|
\.mp3$
|
||||||
|
\.mp4$
|
||||||
|
\.o$
|
||||||
|
\.ocf$
|
||||||
|
\.otf$
|
||||||
|
\.pbxproj$
|
||||||
|
\.pdf$
|
||||||
|
\.pem$
|
||||||
|
\.png$
|
||||||
|
\.psd$
|
||||||
|
\.pyc$
|
||||||
|
\.runsettings$
|
||||||
|
\.s$
|
||||||
|
\.sig$
|
||||||
|
\.so$
|
||||||
|
\.svg$
|
||||||
|
\.svgz$
|
||||||
|
\.svgz?$
|
||||||
|
\.tar$
|
||||||
|
\.tgz$
|
||||||
|
\.tiff?$
|
||||||
|
\.ttf$
|
||||||
|
\.vsdx$
|
||||||
|
\.wav$
|
||||||
|
\.webm$
|
||||||
|
\.webp$
|
||||||
|
\.woff
|
||||||
|
\.woff2?$
|
||||||
|
\.xcf$
|
||||||
|
\.xls
|
||||||
|
\.xlsx?$
|
||||||
|
\.xpm$
|
||||||
|
\.yml$
|
||||||
|
\.zip$
|
||||||
|
^\.github/actions/spelling/
|
||||||
|
^\.github/fabricbot.json$
|
||||||
|
^\.gitignore$
|
||||||
|
^\Q.git-blame-ignore-revs\E$
|
||||||
|
^\Q.github/workflows/spelling.yml\E$
|
||||||
|
^\Qdoc/reference/windows-terminal-logo.ans\E$
|
||||||
|
^\Qsamples/ConPTY/EchoCon/EchoCon/EchoCon.vcxproj.filters\E$
|
||||||
|
^\Qsrc/host/exe/Host.EXE.vcxproj.filters\E$
|
||||||
|
^\Qsrc/host/ft_host/chafa.txt\E$
|
||||||
|
^\Qsrc/tools/closetest/CloseTest.vcxproj.filters\E$
|
||||||
|
^\XamlStyler.json$
|
||||||
|
^build/config/
|
||||||
|
^consolegit2gitfilters\.json$
|
||||||
|
^dep/
|
||||||
|
^doc/reference/master-sequence-list.csv$
|
||||||
|
^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$
|
||||||
@@ -1,22 +1,31 @@
|
|||||||
abcde
|
AAAa
|
||||||
abcdef
|
AAAAA
|
||||||
ABCDEFG
|
AAAAAAAAAAAAA
|
||||||
ABCDEFGH
|
AAAAAABBBBBBCCC
|
||||||
|
AAAAABBBBBBCCC
|
||||||
|
abcd
|
||||||
|
abcd
|
||||||
ABCDEFGHIJ
|
ABCDEFGHIJ
|
||||||
abcdefghijk
|
abcdefghijk
|
||||||
|
ABCDEFGHIJKLMNO
|
||||||
abcdefghijklmnop
|
abcdefghijklmnop
|
||||||
ABCDEFGHIJKLMNOPQRST
|
ABCDEFGHIJKLMNOPQRST
|
||||||
abcdefghijklmnopqrstuvwxyz
|
ABCG
|
||||||
ABE
|
ABE
|
||||||
|
abf
|
||||||
|
BBBBB
|
||||||
|
BBBBBBBB
|
||||||
|
BBBBBCCC
|
||||||
|
BBBBCCCCC
|
||||||
BBGGRR
|
BBGGRR
|
||||||
BBBBBBBBBBBBBBDDDD
|
EFG
|
||||||
|
EFGh
|
||||||
QQQQQQQQQQABCDEFGHIJ
|
QQQQQQQQQQABCDEFGHIJ
|
||||||
QQQQQQQQQQABCDEFGHIJKLMNOPQRSTQQQQQQQQQ
|
QQQQQQQQQQABCDEFGHIJKLMNOPQRSTQQQQQQQQQ
|
||||||
QQQQQQQQQQABCDEFGHIJKLMNOPQRSTQQQQQQQQQQ
|
QQQQQQQQQQABCDEFGHIJKLMNOPQRSTQQQQQQQQQQ
|
||||||
QQQQQQQQQQABCDEFGHIJPQRSTQQQQQQQQQQ
|
QQQQQQQQQQABCDEFGHIJPQRSTQQQQQQQQQQ
|
||||||
qrstuvwxyz
|
qrstuvwxyz
|
||||||
qwerty
|
qwerty
|
||||||
QWERTYUIOP
|
|
||||||
qwertyuiopasdfg
|
qwertyuiopasdfg
|
||||||
YYYYYYYDDDDDDDDDDD
|
YYYYYYYDDDDDDDDDDD
|
||||||
ZAAZZ
|
ZAAZZ
|
||||||
@@ -28,3 +37,4 @@ ZYXWVUT
|
|||||||
ZZBBZ
|
ZZBBZ
|
||||||
ZZZBB
|
ZZZBB
|
||||||
ZZZBZ
|
ZZZBZ
|
||||||
|
ZZZZZ
|
||||||
File diff suppressed because it is too large
Load Diff
6
.github/actions/spelling/expect/web.txt
vendored
Normal file
6
.github/actions/spelling/expect/web.txt
vendored
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
WCAG
|
||||||
|
winui
|
||||||
|
appshellintegration
|
||||||
|
mdtauk
|
||||||
|
gfycat
|
||||||
|
Guake
|
||||||
62
.github/actions/spelling/line_forbidden.patterns
vendored
Normal file
62
.github/actions/spelling/line_forbidden.patterns
vendored
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
# reject `m_data` as there's a certain OS which has evil defines that break things if it's used elsewhere
|
||||||
|
# \bm_data\b
|
||||||
|
|
||||||
|
# If you have a framework that uses `it()` for testing and `fit()` for debugging a specific test,
|
||||||
|
# you might not want to check in code where you were debugging w/ `fit()`, in which case, you might want
|
||||||
|
# to use this:
|
||||||
|
#\bfit\(
|
||||||
|
|
||||||
|
# s.b. GitHub
|
||||||
|
\bGithub\b
|
||||||
|
|
||||||
|
# s.b. GitLab
|
||||||
|
\bGitlab\b
|
||||||
|
|
||||||
|
# s.b. JavaScript
|
||||||
|
\bJavascript\b
|
||||||
|
|
||||||
|
# s.b. Microsoft
|
||||||
|
\bMicroSoft\b
|
||||||
|
|
||||||
|
# s.b. another
|
||||||
|
\ban[- ]other\b
|
||||||
|
|
||||||
|
# s.b. greater than
|
||||||
|
\bgreater then\b
|
||||||
|
|
||||||
|
# s.b. into
|
||||||
|
#\sin to\s
|
||||||
|
|
||||||
|
# s.b. opt-in
|
||||||
|
\sopt in\s
|
||||||
|
|
||||||
|
# s.b. less than
|
||||||
|
\bless then\b
|
||||||
|
|
||||||
|
# s.b. otherwise
|
||||||
|
\bother[- ]wise\b
|
||||||
|
|
||||||
|
# s.b. nonexistent
|
||||||
|
\bnon existing\b
|
||||||
|
\b[Nn]o[nt][- ]existent\b
|
||||||
|
|
||||||
|
# s.b. preexisting
|
||||||
|
[Pp]re[- ]existing
|
||||||
|
|
||||||
|
# s.b. preempt
|
||||||
|
[Pp]re[- ]empt\b
|
||||||
|
|
||||||
|
# s.b. preemptively
|
||||||
|
[Pp]re[- ]emptively
|
||||||
|
|
||||||
|
# s.b. reentrancy
|
||||||
|
[Rr]e[- ]entrancy
|
||||||
|
|
||||||
|
# s.b. reentrant
|
||||||
|
[Rr]e[- ]entrant
|
||||||
|
|
||||||
|
# s.b. workaround(s)
|
||||||
|
#\bwork[- ]arounds?\b
|
||||||
|
|
||||||
|
# Reject duplicate words
|
||||||
|
\s([A-Z]{3,}|[A-Z][a-z]{2,}|[a-z]{3,})\s\g{-1}\s
|
||||||
96
.github/actions/spelling/patterns/patterns.txt
vendored
Normal file
96
.github/actions/spelling/patterns/patterns.txt
vendored
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
# 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
|
||||||
|
microsoft/cascadia-code\@[0-9a-fA-F]{40}
|
||||||
|
\d+x\d+Logo
|
||||||
|
Scro\&ll
|
||||||
|
# selectionInput.cpp
|
||||||
|
:\\windows\\syste\b
|
||||||
|
TestUtils::VerifyExpectedString\(tb, L"[^"]+"
|
||||||
|
(?:hostSm|mach)\.ProcessString\(L"[^"]+"
|
||||||
|
\b([A-Za-z])\g{-1}{3,}\b
|
||||||
|
0x[0-9A-Za-z]+
|
||||||
|
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.*
|
||||||
20
.github/workflows/spelling.yml
vendored
20
.github/workflows/spelling.yml
vendored
@@ -1,20 +0,0 @@
|
|||||||
name: Spell checking
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
schedule:
|
|
||||||
# * is a special character in YAML so you have to quote this string
|
|
||||||
- cron: '15 * * * *'
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
name: Spell checking
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2.0.0
|
|
||||||
with:
|
|
||||||
fetch-depth: 5
|
|
||||||
- uses: check-spelling/check-spelling@0.0.16-alpha
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
bucket: .github/actions
|
|
||||||
project: spell-check
|
|
||||||
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 }}
|
||||||
349
src/cascadia/LocalTests_TerminalApp/CommandTests.cpp
Normal file
349
src/cascadia/LocalTests_TerminalApp/CommandTests.cpp
Normal file
@@ -0,0 +1,349 @@
|
|||||||
|
// Copyright (c) Microsoft Corporation.
|
||||||
|
// Licensed under the MIT license.
|
||||||
|
|
||||||
|
#include "pch.h"
|
||||||
|
|
||||||
|
#include "../TerminalApp/CascadiaSettings.h"
|
||||||
|
#include "JsonTestClass.h"
|
||||||
|
#include "TestUtils.h"
|
||||||
|
|
||||||
|
using namespace Microsoft::Console;
|
||||||
|
using namespace TerminalApp;
|
||||||
|
using namespace winrt::TerminalApp;
|
||||||
|
using namespace winrt::Microsoft::Terminal::Settings;
|
||||||
|
using namespace WEX::Logging;
|
||||||
|
using namespace WEX::TestExecution;
|
||||||
|
using namespace WEX::Common;
|
||||||
|
|
||||||
|
namespace TerminalAppLocalTests
|
||||||
|
{
|
||||||
|
// TODO:microsoft/terminal#3838:
|
||||||
|
// Unfortunately, these tests _WILL NOT_ work in our CI. We're waiting for
|
||||||
|
// an updated TAEF that will let us install framework packages when the test
|
||||||
|
// package is deployed. Until then, these tests won't deploy in CI.
|
||||||
|
|
||||||
|
class CommandTests : public JsonTestClass
|
||||||
|
{
|
||||||
|
// Use a custom AppxManifest to ensure that we can activate winrt types
|
||||||
|
// from our test. This property will tell taef to manually use this as
|
||||||
|
// the AppxManifest for this test class.
|
||||||
|
// This does not yet work for anything XAML-y. See TabTests.cpp for more
|
||||||
|
// details on that.
|
||||||
|
BEGIN_TEST_CLASS(CommandTests)
|
||||||
|
TEST_CLASS_PROPERTY(L"RunAs", L"UAP")
|
||||||
|
TEST_CLASS_PROPERTY(L"UAP:AppXManifest", L"TestHostAppXManifest.xml")
|
||||||
|
END_TEST_CLASS()
|
||||||
|
|
||||||
|
TEST_METHOD(ManyCommandsSameAction);
|
||||||
|
TEST_METHOD(LayerCommand);
|
||||||
|
TEST_METHOD(TestSplitPaneArgs);
|
||||||
|
TEST_METHOD(TestResourceKeyName);
|
||||||
|
TEST_METHOD(TestAutogeneratedName);
|
||||||
|
TEST_METHOD(TestLayerOnAutogeneratedName);
|
||||||
|
|
||||||
|
TEST_CLASS_SETUP(ClassSetup)
|
||||||
|
{
|
||||||
|
InitializeJsonReader();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void CommandTests::ManyCommandsSameAction()
|
||||||
|
{
|
||||||
|
const std::string commands0String{ R"([ { "name":"action0", "command": "copy" } ])" };
|
||||||
|
const std::string commands1String{ R"([ { "name":"action1", "command": { "action": "copy", "singleLine": false } } ])" };
|
||||||
|
const std::string commands2String{ R"([
|
||||||
|
{ "name":"action2", "command": "paste" },
|
||||||
|
{ "name":"action3", "command": "paste" }
|
||||||
|
])" };
|
||||||
|
|
||||||
|
const auto commands0Json = VerifyParseSucceeded(commands0String);
|
||||||
|
const auto commands1Json = VerifyParseSucceeded(commands1String);
|
||||||
|
const auto commands2Json = VerifyParseSucceeded(commands2String);
|
||||||
|
|
||||||
|
std::map<winrt::hstring, Command> commands;
|
||||||
|
VERIFY_ARE_EQUAL(0u, commands.size());
|
||||||
|
{
|
||||||
|
auto warnings = implementation::Command::LayerJson(commands, commands0Json);
|
||||||
|
VERIFY_ARE_EQUAL(0u, warnings.size());
|
||||||
|
}
|
||||||
|
VERIFY_ARE_EQUAL(1u, commands.size());
|
||||||
|
|
||||||
|
{
|
||||||
|
auto warnings = implementation::Command::LayerJson(commands, commands1Json);
|
||||||
|
VERIFY_ARE_EQUAL(0u, warnings.size());
|
||||||
|
}
|
||||||
|
VERIFY_ARE_EQUAL(2u, commands.size());
|
||||||
|
|
||||||
|
{
|
||||||
|
auto warnings = implementation::Command::LayerJson(commands, commands2Json);
|
||||||
|
VERIFY_ARE_EQUAL(0u, warnings.size());
|
||||||
|
}
|
||||||
|
VERIFY_ARE_EQUAL(4u, commands.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
void CommandTests::LayerCommand()
|
||||||
|
{
|
||||||
|
// Each one of the commands in this test should layer upon the previous, overriding the action.
|
||||||
|
const std::string commands0String{ R"([ { "name":"action0", "command": "copy" } ])" };
|
||||||
|
const std::string commands1String{ R"([ { "name":"action0", "command": "paste" } ])" };
|
||||||
|
const std::string commands2String{ R"([ { "name":"action0", "command": "newTab" } ])" };
|
||||||
|
const std::string commands3String{ R"([ { "name":"action0", "command": null } ])" };
|
||||||
|
|
||||||
|
const auto commands0Json = VerifyParseSucceeded(commands0String);
|
||||||
|
const auto commands1Json = VerifyParseSucceeded(commands1String);
|
||||||
|
const auto commands2Json = VerifyParseSucceeded(commands2String);
|
||||||
|
const auto commands3Json = VerifyParseSucceeded(commands3String);
|
||||||
|
|
||||||
|
std::map<winrt::hstring, Command> commands;
|
||||||
|
VERIFY_ARE_EQUAL(0u, commands.size());
|
||||||
|
{
|
||||||
|
auto warnings = implementation::Command::LayerJson(commands, commands0Json);
|
||||||
|
VERIFY_ARE_EQUAL(0u, warnings.size());
|
||||||
|
VERIFY_ARE_EQUAL(1u, commands.size());
|
||||||
|
auto command = commands.at(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(realArgs);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto warnings = implementation::Command::LayerJson(commands, commands1Json);
|
||||||
|
VERIFY_ARE_EQUAL(0u, warnings.size());
|
||||||
|
VERIFY_ARE_EQUAL(1u, commands.size());
|
||||||
|
auto command = commands.at(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());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto warnings = implementation::Command::LayerJson(commands, commands2Json);
|
||||||
|
VERIFY_ARE_EQUAL(0u, warnings.size());
|
||||||
|
VERIFY_ARE_EQUAL(1u, commands.size());
|
||||||
|
auto command = commands.at(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(realArgs);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// This last command should "unbind" the action.
|
||||||
|
auto warnings = implementation::Command::LayerJson(commands, commands3Json);
|
||||||
|
VERIFY_ARE_EQUAL(0u, warnings.size());
|
||||||
|
VERIFY_ARE_EQUAL(0u, commands.size());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CommandTests::TestSplitPaneArgs()
|
||||||
|
{
|
||||||
|
// This is the same as KeyBindingsTests::TestSplitPaneArgs, but with
|
||||||
|
// looking up the action and its args from a map of commands, instead
|
||||||
|
// of from keybindings.
|
||||||
|
|
||||||
|
const std::string commands0String{ R"([
|
||||||
|
{ "name": "command0", "command": { "action": "splitPane", "split": null } },
|
||||||
|
{ "name": "command1", "command": { "action": "splitPane", "split": "vertical" } },
|
||||||
|
{ "name": "command2", "command": { "action": "splitPane", "split": "horizontal" } },
|
||||||
|
{ "name": "command3", "command": { "action": "splitPane", "split": "none" } },
|
||||||
|
{ "name": "command4", "command": { "action": "splitPane" } },
|
||||||
|
{ "name": "command5", "command": { "action": "splitPane", "split": "auto" } },
|
||||||
|
{ "name": "command6", "command": { "action": "splitPane", "split": "foo" } }
|
||||||
|
])" };
|
||||||
|
|
||||||
|
const auto commands0Json = VerifyParseSucceeded(commands0String);
|
||||||
|
|
||||||
|
std::map<winrt::hstring, Command> commands;
|
||||||
|
VERIFY_ARE_EQUAL(0u, commands.size());
|
||||||
|
auto warnings = implementation::Command::LayerJson(commands, commands0Json);
|
||||||
|
VERIFY_ARE_EQUAL(0u, warnings.size());
|
||||||
|
VERIFY_ARE_EQUAL(7u, commands.size());
|
||||||
|
|
||||||
|
{
|
||||||
|
auto command = commands.at(L"command0");
|
||||||
|
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(realArgs);
|
||||||
|
// Verify the args have the expected value
|
||||||
|
VERIFY_ARE_EQUAL(winrt::TerminalApp::SplitState::Automatic, realArgs.SplitStyle());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto command = commands.at(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(realArgs);
|
||||||
|
// Verify the args have the expected value
|
||||||
|
VERIFY_ARE_EQUAL(winrt::TerminalApp::SplitState::Vertical, realArgs.SplitStyle());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto command = commands.at(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(realArgs);
|
||||||
|
// Verify the args have the expected value
|
||||||
|
VERIFY_ARE_EQUAL(winrt::TerminalApp::SplitState::Horizontal, realArgs.SplitStyle());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto command = commands.at(L"command3");
|
||||||
|
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(realArgs);
|
||||||
|
// Verify the args have the expected value
|
||||||
|
VERIFY_ARE_EQUAL(winrt::TerminalApp::SplitState::Automatic, realArgs.SplitStyle());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto command = commands.at(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(realArgs);
|
||||||
|
// Verify the args have the expected value
|
||||||
|
VERIFY_ARE_EQUAL(winrt::TerminalApp::SplitState::Automatic, realArgs.SplitStyle());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto command = commands.at(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(realArgs);
|
||||||
|
// Verify the args have the expected value
|
||||||
|
VERIFY_ARE_EQUAL(winrt::TerminalApp::SplitState::Automatic, realArgs.SplitStyle());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto command = commands.at(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(realArgs);
|
||||||
|
// Verify the args have the expected value
|
||||||
|
VERIFY_ARE_EQUAL(winrt::TerminalApp::SplitState::Automatic, realArgs.SplitStyle());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void CommandTests::TestResourceKeyName()
|
||||||
|
{
|
||||||
|
// This test checks looking up a name from a resource key.
|
||||||
|
|
||||||
|
const std::string commands0String{ R"([ { "name": { "key": "DuplicateTabCommandKey"}, "command": "copy" } ])" };
|
||||||
|
const auto commands0Json = VerifyParseSucceeded(commands0String);
|
||||||
|
|
||||||
|
std::map<winrt::hstring, Command> commands;
|
||||||
|
VERIFY_ARE_EQUAL(0u, commands.size());
|
||||||
|
{
|
||||||
|
auto warnings = implementation::Command::LayerJson(commands, commands0Json);
|
||||||
|
VERIFY_ARE_EQUAL(0u, warnings.size());
|
||||||
|
VERIFY_ARE_EQUAL(1u, commands.size());
|
||||||
|
|
||||||
|
// NOTE: We're relying on DuplicateTabCommandKey being defined as
|
||||||
|
// "Duplicate Tab" here. If that string changes in our resources,
|
||||||
|
// this test will break.
|
||||||
|
auto command = commands.at(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(realArgs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CommandTests::TestAutogeneratedName()
|
||||||
|
{
|
||||||
|
// This test ensures that we'll correctly create commands for actions
|
||||||
|
// that don't have given names, pursuant to the spec in GH#6532.
|
||||||
|
|
||||||
|
// NOTE: The keys used to look up these commands are partially generated
|
||||||
|
// from strings in our Resources.resw. If those string values should
|
||||||
|
// change, it's likely that this test will break.
|
||||||
|
|
||||||
|
const std::string commands0String{ R"([
|
||||||
|
{ "command": { "action": "splitPane", "split": null } },
|
||||||
|
{ "command": { "action": "splitPane", "split": "vertical" } },
|
||||||
|
{ "command": { "action": "splitPane", "split": "horizontal" } },
|
||||||
|
{ "command": { "action": "splitPane", "split": "none" } },
|
||||||
|
{ "command": { "action": "splitPane" } },
|
||||||
|
{ "command": { "action": "splitPane", "split": "auto" } },
|
||||||
|
{ "command": { "action": "splitPane", "split": "foo" } }
|
||||||
|
])" };
|
||||||
|
|
||||||
|
const auto commands0Json = VerifyParseSucceeded(commands0String);
|
||||||
|
|
||||||
|
std::map<winrt::hstring, Command> commands;
|
||||||
|
VERIFY_ARE_EQUAL(0u, commands.size());
|
||||||
|
auto warnings = implementation::Command::LayerJson(commands, commands0Json);
|
||||||
|
VERIFY_ARE_EQUAL(0u, warnings.size());
|
||||||
|
|
||||||
|
// There are only 3 commands here: all of the `"none"`, `"auto"`,
|
||||||
|
// `"foo"`, `null`, and <no args> bindings all generate the same action,
|
||||||
|
// which will generate just a single name for all of them.
|
||||||
|
VERIFY_ARE_EQUAL(3u, commands.size());
|
||||||
|
|
||||||
|
{
|
||||||
|
auto command = commands.at(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(realArgs);
|
||||||
|
// Verify the args have the expected value
|
||||||
|
VERIFY_ARE_EQUAL(winrt::TerminalApp::SplitState::Automatic, realArgs.SplitStyle());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto command = commands.at(L"Split pane, direction: 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(realArgs);
|
||||||
|
// Verify the args have the expected value
|
||||||
|
VERIFY_ARE_EQUAL(winrt::TerminalApp::SplitState::Vertical, realArgs.SplitStyle());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto command = commands.at(L"Split pane, direction: 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(realArgs);
|
||||||
|
// Verify the args have the expected value
|
||||||
|
VERIFY_ARE_EQUAL(winrt::TerminalApp::SplitState::Horizontal, realArgs.SplitStyle());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void CommandTests::TestLayerOnAutogeneratedName()
|
||||||
|
{
|
||||||
|
const std::string commands0String{ R"([
|
||||||
|
{ "command": { "action": "splitPane" } },
|
||||||
|
{ "name":"Split pane", "command": { "action": "splitPane", "split": "vertical" } },
|
||||||
|
])" };
|
||||||
|
|
||||||
|
const auto commands0Json = VerifyParseSucceeded(commands0String);
|
||||||
|
|
||||||
|
std::map<winrt::hstring, Command> commands;
|
||||||
|
VERIFY_ARE_EQUAL(0u, commands.size());
|
||||||
|
auto warnings = implementation::Command::LayerJson(commands, commands0Json);
|
||||||
|
VERIFY_ARE_EQUAL(0u, warnings.size());
|
||||||
|
VERIFY_ARE_EQUAL(1u, commands.size());
|
||||||
|
|
||||||
|
{
|
||||||
|
auto command = commands.at(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(realArgs);
|
||||||
|
// Verify the args have the expected value
|
||||||
|
VERIFY_ARE_EQUAL(winrt::TerminalApp::SplitState::Vertical, realArgs.SplitStyle());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -80,6 +80,8 @@ namespace TerminalAppLocalTests
|
|||||||
|
|
||||||
TEST_METHOD(TestTrailingCommas);
|
TEST_METHOD(TestTrailingCommas);
|
||||||
|
|
||||||
|
TEST_METHOD(TestCommandsAndKeybindings);
|
||||||
|
|
||||||
TEST_CLASS_SETUP(ClassSetup)
|
TEST_CLASS_SETUP(ClassSetup)
|
||||||
{
|
{
|
||||||
InitializeJsonReader();
|
InitializeJsonReader();
|
||||||
@@ -2331,4 +2333,204 @@ namespace TerminalAppLocalTests
|
|||||||
VERIFY_IS_TRUE(false, L"This call to LayerJson should succeed, even with the trailing comma");
|
VERIFY_IS_TRUE(false, L"This call to LayerJson should succeed, even with the trailing comma");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SettingsTests::TestCommandsAndKeybindings()
|
||||||
|
{
|
||||||
|
const std::string settingsJson{ R"(
|
||||||
|
{
|
||||||
|
"defaultProfile": "{6239a42c-0000-49a3-80bd-e8fdd045185c}",
|
||||||
|
"profiles": [
|
||||||
|
{
|
||||||
|
"name": "profile0",
|
||||||
|
"guid": "{6239a42c-0000-49a3-80bd-e8fdd045185c}",
|
||||||
|
"historySize": 1,
|
||||||
|
"commandline": "cmd.exe"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "profile1",
|
||||||
|
"guid": "{6239a42c-1111-49a3-80bd-e8fdd045185c}",
|
||||||
|
"historySize": 2,
|
||||||
|
"commandline": "pwsh.exe"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "profile2",
|
||||||
|
"historySize": 3,
|
||||||
|
"commandline": "wsl.exe"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"bindings": [
|
||||||
|
{ "keys": "ctrl+a", "command": { "action": "splitPane", "split": "vertical" } },
|
||||||
|
{ "name": "ctrl+b", "command": { "action": "splitPane", "split": "vertical" } },
|
||||||
|
{ "keys": "ctrl+c", "name": "ctrl+c", "command": { "action": "splitPane", "split": "vertical" } },
|
||||||
|
{ "keys": "ctrl+d", "command": { "action": "splitPane", "split": "vertical" } },
|
||||||
|
{ "keys": "ctrl+e", "command": { "action": "splitPane", "split": "horizontal" } },
|
||||||
|
{ "keys": "ctrl+f", "name":null, "command": { "action": "splitPane", "split": "horizontal" } }
|
||||||
|
]
|
||||||
|
})" };
|
||||||
|
|
||||||
|
const auto guid0 = Microsoft::Console::Utils::GuidFromString(L"{6239a42c-0000-49a3-80bd-e8fdd045185c}");
|
||||||
|
const auto guid1 = Microsoft::Console::Utils::GuidFromString(L"{6239a42c-1111-49a3-80bd-e8fdd045185c}");
|
||||||
|
|
||||||
|
VerifyParseSucceeded(settingsJson);
|
||||||
|
CascadiaSettings settings{};
|
||||||
|
settings._ParseJsonString(settingsJson, false);
|
||||||
|
settings.LayerJson(settings._userSettings);
|
||||||
|
settings._ValidateSettings();
|
||||||
|
|
||||||
|
VERIFY_ARE_EQUAL(3u, settings.GetProfiles().size());
|
||||||
|
|
||||||
|
const auto profile2Guid = settings._profiles.at(2).GetGuid();
|
||||||
|
VERIFY_ARE_NOT_EQUAL(GUID{ 0 }, profile2Guid);
|
||||||
|
|
||||||
|
auto appKeyBindings = settings._globals._keybindings;
|
||||||
|
VERIFY_ARE_EQUAL(5u, appKeyBindings->_keyShortcuts.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.GetCommands();
|
||||||
|
VERIFY_ARE_EQUAL(4u, commands.size());
|
||||||
|
|
||||||
|
{
|
||||||
|
KeyChord kc{ true, false, false, static_cast<int32_t>('A') };
|
||||||
|
auto actionAndArgs = TestUtils::GetActionAndArgs(*appKeyBindings, kc);
|
||||||
|
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(winrt::TerminalApp::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());
|
||||||
|
}
|
||||||
|
|
||||||
|
Log::Comment(L"Note that we're skipping ctrl+B, since that doesn't have `keys` set.");
|
||||||
|
|
||||||
|
{
|
||||||
|
KeyChord kc{ true, false, false, static_cast<int32_t>('C') };
|
||||||
|
auto actionAndArgs = TestUtils::GetActionAndArgs(*appKeyBindings, kc);
|
||||||
|
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(winrt::TerminalApp::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());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
KeyChord kc{ true, false, false, static_cast<int32_t>('D') };
|
||||||
|
auto actionAndArgs = TestUtils::GetActionAndArgs(*appKeyBindings, kc);
|
||||||
|
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(winrt::TerminalApp::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());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
KeyChord kc{ true, false, false, static_cast<int32_t>('E') };
|
||||||
|
auto actionAndArgs = TestUtils::GetActionAndArgs(*appKeyBindings, kc);
|
||||||
|
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(winrt::TerminalApp::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());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
KeyChord kc{ true, false, false, static_cast<int32_t>('F') };
|
||||||
|
auto actionAndArgs = TestUtils::GetActionAndArgs(*appKeyBindings, kc);
|
||||||
|
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(winrt::TerminalApp::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());
|
||||||
|
}
|
||||||
|
|
||||||
|
Log::Comment(L"Now verify the commands");
|
||||||
|
|
||||||
|
{
|
||||||
|
auto command = commands.at(L"Split pane, direction: Vertical");
|
||||||
|
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(winrt::TerminalApp::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.at(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(winrt::TerminalApp::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.at(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(winrt::TerminalApp::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.at(L"Split pane, direction: 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(winrt::TerminalApp::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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,6 +60,7 @@
|
|||||||
<ClCompile Include="ProfileTests.cpp" />
|
<ClCompile Include="ProfileTests.cpp" />
|
||||||
<ClCompile Include="ColorSchemeTests.cpp" />
|
<ClCompile Include="ColorSchemeTests.cpp" />
|
||||||
<ClCompile Include="KeyBindingsTests.cpp" />
|
<ClCompile Include="KeyBindingsTests.cpp" />
|
||||||
|
<ClCompile Include="CommandTests.cpp" />
|
||||||
<ClCompile Include="TabTests.cpp" />
|
<ClCompile Include="TabTests.cpp" />
|
||||||
<ClCompile Include="pch.cpp">
|
<ClCompile Include="pch.cpp">
|
||||||
<PrecompiledHeader>Create</PrecompiledHeader>
|
<PrecompiledHeader>Create</PrecompiledHeader>
|
||||||
|
|||||||
@@ -2,11 +2,7 @@
|
|||||||
#include "ActionArgs.h"
|
#include "ActionArgs.h"
|
||||||
#include "ActionAndArgs.h"
|
#include "ActionAndArgs.h"
|
||||||
#include "ActionAndArgs.g.cpp"
|
#include "ActionAndArgs.g.cpp"
|
||||||
|
#include <LibraryResources.h>
|
||||||
static constexpr std::string_view ActionKey{ "action" };
|
|
||||||
|
|
||||||
// This key is reserved to remove a keybinding, instead of mapping it to an action.
|
|
||||||
static constexpr std::string_view UnboundKey{ "unbound" };
|
|
||||||
|
|
||||||
static constexpr std::string_view CopyTextKey{ "copy" };
|
static constexpr std::string_view CopyTextKey{ "copy" };
|
||||||
static constexpr std::string_view PasteTextKey{ "paste" };
|
static constexpr std::string_view PasteTextKey{ "paste" };
|
||||||
@@ -33,9 +29,16 @@ static constexpr std::string_view ResizePaneKey{ "resizePane" };
|
|||||||
static constexpr std::string_view MoveFocusKey{ "moveFocus" };
|
static constexpr std::string_view MoveFocusKey{ "moveFocus" };
|
||||||
static constexpr std::string_view FindKey{ "find" };
|
static constexpr std::string_view FindKey{ "find" };
|
||||||
static constexpr std::string_view ToggleFullscreenKey{ "toggleFullscreen" };
|
static constexpr std::string_view ToggleFullscreenKey{ "toggleFullscreen" };
|
||||||
|
static constexpr std::string_view ExecuteCommandlineKey{ "wt" };
|
||||||
static constexpr std::string_view SetTabColorKey{ "setTabColor" };
|
static constexpr std::string_view SetTabColorKey{ "setTabColor" };
|
||||||
static constexpr std::string_view OpenTabColorPickerKey{ "openTabColorPicker" };
|
static constexpr std::string_view OpenTabColorPickerKey{ "openTabColorPicker" };
|
||||||
static constexpr std::string_view RenameTabKey{ "renameTab" };
|
static constexpr std::string_view RenameTabKey{ "renameTab" };
|
||||||
|
static constexpr std::string_view ToggleCommandPaletteKey{ "commandPalette" };
|
||||||
|
|
||||||
|
static constexpr std::string_view ActionKey{ "action" };
|
||||||
|
|
||||||
|
// This key is reserved to remove a keybinding, instead of mapping it to an action.
|
||||||
|
static constexpr std::string_view UnboundKey{ "unbound" };
|
||||||
|
|
||||||
namespace winrt::TerminalApp::implementation
|
namespace winrt::TerminalApp::implementation
|
||||||
{
|
{
|
||||||
@@ -47,7 +50,7 @@ namespace winrt::TerminalApp::implementation
|
|||||||
// the actual strings being pointed to. However, since both these strings and
|
// the actual strings being pointed to. However, since both these strings and
|
||||||
// the map are all const for the lifetime of the app, we have nothing to worry
|
// the map are all const for the lifetime of the app, we have nothing to worry
|
||||||
// about here.
|
// about here.
|
||||||
const std::map<std::string_view, ShortcutAction, std::less<>> ActionAndArgs::ActionNamesMap{
|
const std::map<std::string_view, ShortcutAction, std::less<>> ActionAndArgs::ActionKeyNamesMap{
|
||||||
{ CopyTextKey, ShortcutAction::CopyText },
|
{ CopyTextKey, ShortcutAction::CopyText },
|
||||||
{ PasteTextKey, ShortcutAction::PasteText },
|
{ PasteTextKey, ShortcutAction::PasteText },
|
||||||
{ OpenNewTabDropdownKey, ShortcutAction::OpenNewTabDropdown },
|
{ OpenNewTabDropdownKey, ShortcutAction::OpenNewTabDropdown },
|
||||||
@@ -75,7 +78,9 @@ namespace winrt::TerminalApp::implementation
|
|||||||
{ OpenTabColorPickerKey, ShortcutAction::OpenTabColorPicker },
|
{ OpenTabColorPickerKey, ShortcutAction::OpenTabColorPicker },
|
||||||
{ UnboundKey, ShortcutAction::Invalid },
|
{ UnboundKey, ShortcutAction::Invalid },
|
||||||
{ FindKey, ShortcutAction::Find },
|
{ FindKey, ShortcutAction::Find },
|
||||||
{ RenameTabKey, ShortcutAction::RenameTab }
|
{ RenameTabKey, ShortcutAction::RenameTab },
|
||||||
|
{ ToggleCommandPaletteKey, ShortcutAction::ToggleCommandPalette },
|
||||||
|
{ ExecuteCommandlineKey, ShortcutAction::ExecuteCommandline },
|
||||||
};
|
};
|
||||||
|
|
||||||
using ParseResult = std::tuple<IActionArgs, std::vector<::TerminalApp::SettingsLoadWarnings>>;
|
using ParseResult = std::tuple<IActionArgs, std::vector<::TerminalApp::SettingsLoadWarnings>>;
|
||||||
@@ -101,6 +106,8 @@ namespace winrt::TerminalApp::implementation
|
|||||||
|
|
||||||
{ ShortcutAction::SplitPane, winrt::TerminalApp::implementation::SplitPaneArgs::FromJson },
|
{ ShortcutAction::SplitPane, winrt::TerminalApp::implementation::SplitPaneArgs::FromJson },
|
||||||
|
|
||||||
|
{ ShortcutAction::ExecuteCommandline, winrt::TerminalApp::implementation::ExecuteCommandlineArgs::FromJson },
|
||||||
|
|
||||||
{ ShortcutAction::OpenSettings, winrt::TerminalApp::implementation::OpenSettingsArgs::FromJson },
|
{ ShortcutAction::OpenSettings, winrt::TerminalApp::implementation::OpenSettingsArgs::FromJson },
|
||||||
|
|
||||||
{ ShortcutAction::SetTabColor, winrt::TerminalApp::implementation::SetTabColorArgs::FromJson },
|
{ ShortcutAction::SetTabColor, winrt::TerminalApp::implementation::SetTabColorArgs::FromJson },
|
||||||
@@ -121,8 +128,8 @@ namespace winrt::TerminalApp::implementation
|
|||||||
{
|
{
|
||||||
// Try matching the command to one we have. If we can't find the
|
// Try matching the command to one we have. If we can't find the
|
||||||
// action name in our list of names, let's just unbind that key.
|
// action name in our list of names, let's just unbind that key.
|
||||||
const auto found = ActionAndArgs::ActionNamesMap.find(actionString);
|
const auto found = ActionAndArgs::ActionKeyNamesMap.find(actionString);
|
||||||
return found != ActionAndArgs::ActionNamesMap.end() ? found->second : ShortcutAction::Invalid;
|
return found != ActionAndArgs::ActionKeyNamesMap.end() ? found->second : ShortcutAction::Invalid;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Method Description:
|
// Method Description:
|
||||||
@@ -219,4 +226,56 @@ namespace winrt::TerminalApp::implementation
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
winrt::hstring ActionAndArgs::GenerateName() const
|
||||||
|
{
|
||||||
|
// Use a magic static to initialize this map, because we won't be able
|
||||||
|
// to load the resources at _init_, only at runtime.
|
||||||
|
static const auto GeneratedActionNames = []() {
|
||||||
|
return std::unordered_map<ShortcutAction, winrt::hstring>{
|
||||||
|
{ ShortcutAction::CopyText, RS_(L"CopyTextCommandKey") },
|
||||||
|
{ ShortcutAction::PasteText, RS_(L"PasteTextCommandKey") },
|
||||||
|
{ ShortcutAction::OpenNewTabDropdown, RS_(L"OpenNewTabDropdownCommandKey") },
|
||||||
|
{ ShortcutAction::DuplicateTab, RS_(L"DuplicateTabCommandKey") },
|
||||||
|
{ ShortcutAction::NewTab, RS_(L"NewTabCommandKey") },
|
||||||
|
{ ShortcutAction::NewWindow, RS_(L"NewWindowCommandKey") },
|
||||||
|
{ ShortcutAction::CloseWindow, RS_(L"CloseWindowCommandKey") },
|
||||||
|
{ ShortcutAction::CloseTab, RS_(L"CloseTabCommandKey") },
|
||||||
|
{ ShortcutAction::ClosePane, RS_(L"ClosePaneCommandKey") },
|
||||||
|
{ ShortcutAction::NextTab, RS_(L"NextTabCommandKey") },
|
||||||
|
{ ShortcutAction::PrevTab, RS_(L"PrevTabCommandKey") },
|
||||||
|
{ ShortcutAction::AdjustFontSize, RS_(L"AdjustFontSizeCommandKey") },
|
||||||
|
{ ShortcutAction::ResetFontSize, RS_(L"ResetFontSizeCommandKey") },
|
||||||
|
{ ShortcutAction::ScrollUp, RS_(L"ScrollUpCommandKey") },
|
||||||
|
{ ShortcutAction::ScrollDown, RS_(L"ScrollDownCommandKey") },
|
||||||
|
{ ShortcutAction::ScrollUpPage, RS_(L"ScrollUpPageCommandKey") },
|
||||||
|
{ ShortcutAction::ScrollDownPage, RS_(L"ScrollDownPageCommandKey") },
|
||||||
|
{ ShortcutAction::SwitchToTab, RS_(L"SwitchToTabCommandKey") },
|
||||||
|
{ ShortcutAction::ResizePane, RS_(L"ResizePaneCommandKey") },
|
||||||
|
{ ShortcutAction::MoveFocus, RS_(L"MoveFocusCommandKey") },
|
||||||
|
{ ShortcutAction::OpenSettings, RS_(L"OpenSettingsCommandKey") },
|
||||||
|
{ ShortcutAction::ToggleFullscreen, RS_(L"ToggleFullscreenCommandKey") },
|
||||||
|
{ ShortcutAction::SplitPane, RS_(L"SplitPaneCommandKey") },
|
||||||
|
{ ShortcutAction::Invalid, L"" },
|
||||||
|
{ ShortcutAction::ExecuteCommandline, L"" },
|
||||||
|
{ ShortcutAction::Find, RS_(L"FindCommandKey") },
|
||||||
|
{ ShortcutAction::SetTabColor, RS_(L"ResetTabColorCommandKey") },
|
||||||
|
{ ShortcutAction::OpenTabColorPicker, RS_(L"OpenTabColorPickerCommandKey") },
|
||||||
|
{ ShortcutAction::RenameTab, RS_(L"ResetTabNameCommandKey") },
|
||||||
|
{ ShortcutAction::ToggleCommandPalette, RS_(L"ToggleCommandPaletteCommandKey") },
|
||||||
|
};
|
||||||
|
}();
|
||||||
|
|
||||||
|
if (_Args)
|
||||||
|
{
|
||||||
|
auto nameFromArgs = _Args.GenerateName();
|
||||||
|
if (!nameFromArgs.empty())
|
||||||
|
{
|
||||||
|
return nameFromArgs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto found = GeneratedActionNames.find(_Action);
|
||||||
|
return found != GeneratedActionNames.end() ? found->second : L"";
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,11 +7,13 @@ namespace winrt::TerminalApp::implementation
|
|||||||
{
|
{
|
||||||
struct ActionAndArgs : public ActionAndArgsT<ActionAndArgs>
|
struct ActionAndArgs : public ActionAndArgsT<ActionAndArgs>
|
||||||
{
|
{
|
||||||
static const std::map<std::string_view, ShortcutAction, std::less<>> ActionNamesMap;
|
static const std::map<std::string_view, ShortcutAction, std::less<>> ActionKeyNamesMap;
|
||||||
static winrt::com_ptr<ActionAndArgs> FromJson(const Json::Value& json,
|
static winrt::com_ptr<ActionAndArgs> FromJson(const Json::Value& json,
|
||||||
std::vector<::TerminalApp::SettingsLoadWarnings>& warnings);
|
std::vector<::TerminalApp::SettingsLoadWarnings>& warnings);
|
||||||
|
|
||||||
ActionAndArgs() = default;
|
ActionAndArgs() = default;
|
||||||
|
hstring GenerateName() const;
|
||||||
|
|
||||||
GETSET_PROPERTY(TerminalApp::ShortcutAction, Action, TerminalApp::ShortcutAction::Invalid);
|
GETSET_PROPERTY(TerminalApp::ShortcutAction, Action, TerminalApp::ShortcutAction::Invalid);
|
||||||
GETSET_PROPERTY(IActionArgs, Args, nullptr);
|
GETSET_PROPERTY(IActionArgs, Args, nullptr);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -14,6 +14,257 @@
|
|||||||
#include "MoveFocusArgs.g.cpp"
|
#include "MoveFocusArgs.g.cpp"
|
||||||
#include "AdjustFontSizeArgs.g.cpp"
|
#include "AdjustFontSizeArgs.g.cpp"
|
||||||
#include "SplitPaneArgs.g.cpp"
|
#include "SplitPaneArgs.g.cpp"
|
||||||
|
#include "ExecuteCommandlineArgs.g.cpp"
|
||||||
#include "OpenSettingsArgs.g.cpp"
|
#include "OpenSettingsArgs.g.cpp"
|
||||||
#include "SetTabColorArgs.g.cpp"
|
#include "SetTabColorArgs.g.cpp"
|
||||||
#include "RenameTabArgs.g.cpp"
|
#include "RenameTabArgs.g.cpp"
|
||||||
|
|
||||||
|
#include <LibraryResources.h>
|
||||||
|
|
||||||
|
namespace winrt::TerminalApp::implementation
|
||||||
|
{
|
||||||
|
winrt::hstring NewTerminalArgs::GenerateName() const
|
||||||
|
{
|
||||||
|
std::wstringstream ss;
|
||||||
|
|
||||||
|
if (!_Profile.empty())
|
||||||
|
{
|
||||||
|
ss << fmt::format(L"profile: {}, ", _Profile);
|
||||||
|
}
|
||||||
|
else if (_ProfileIndex)
|
||||||
|
{
|
||||||
|
ss << fmt::format(L"profile index: {}, ", _ProfileIndex.Value());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_Commandline.empty())
|
||||||
|
{
|
||||||
|
ss << fmt::format(L"commandline: {}, ", _Commandline);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_StartingDirectory.empty())
|
||||||
|
{
|
||||||
|
ss << fmt::format(L"directory: {}, ", _StartingDirectory);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_TabTitle.empty())
|
||||||
|
{
|
||||||
|
ss << fmt::format(L"title: {}, ", _TabTitle);
|
||||||
|
}
|
||||||
|
auto s = ss.str();
|
||||||
|
if (s.empty())
|
||||||
|
{
|
||||||
|
return L"";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Chop off the last ", "
|
||||||
|
return winrt::hstring{ s.substr(0, s.size() - 2) };
|
||||||
|
}
|
||||||
|
|
||||||
|
winrt::hstring CopyTextArgs::GenerateName() const
|
||||||
|
{
|
||||||
|
if (_SingleLine)
|
||||||
|
{
|
||||||
|
return RS_(L"CopyTextAsSingleLineCommandKey");
|
||||||
|
}
|
||||||
|
return RS_(L"CopyTextCommandKey");
|
||||||
|
}
|
||||||
|
|
||||||
|
winrt::hstring NewTabArgs::GenerateName() const
|
||||||
|
{
|
||||||
|
winrt::hstring newTerminalArgsStr;
|
||||||
|
if (_TerminalArgs)
|
||||||
|
{
|
||||||
|
newTerminalArgsStr = _TerminalArgs.GenerateName();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newTerminalArgsStr.empty())
|
||||||
|
{
|
||||||
|
return RS_(L"NewTabCommandKey");
|
||||||
|
}
|
||||||
|
return winrt::hstring{
|
||||||
|
fmt::format(L"{}, {}", RS_(L"NewTabCommandKey"), newTerminalArgsStr)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
winrt::hstring SwitchToTabArgs::GenerateName() const
|
||||||
|
{
|
||||||
|
return winrt::hstring{
|
||||||
|
fmt::format(L"{}, index:{}", RS_(L"SwitchToTabCommandKey"), _TabIndex)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
winrt::hstring ResizePaneArgs::GenerateName() const
|
||||||
|
{
|
||||||
|
winrt::hstring directionString;
|
||||||
|
switch (_Direction)
|
||||||
|
{
|
||||||
|
case Direction::Left:
|
||||||
|
directionString = RS_(L"DirectionLeft");
|
||||||
|
break;
|
||||||
|
case Direction::Right:
|
||||||
|
directionString = RS_(L"DirectionRight");
|
||||||
|
break;
|
||||||
|
case Direction::Up:
|
||||||
|
directionString = RS_(L"DirectionUp");
|
||||||
|
break;
|
||||||
|
case Direction::Down:
|
||||||
|
directionString = RS_(L"DirectionDown");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return winrt::hstring{
|
||||||
|
fmt::format(std::wstring_view(RS_(L"ResizePaneWithArgCommandKey")),
|
||||||
|
directionString)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
winrt::hstring MoveFocusArgs::GenerateName() const
|
||||||
|
{
|
||||||
|
winrt::hstring directionString;
|
||||||
|
switch (_Direction)
|
||||||
|
{
|
||||||
|
case Direction::Left:
|
||||||
|
directionString = RS_(L"DirectionLeft");
|
||||||
|
break;
|
||||||
|
case Direction::Right:
|
||||||
|
directionString = RS_(L"DirectionRight");
|
||||||
|
break;
|
||||||
|
case Direction::Up:
|
||||||
|
directionString = RS_(L"DirectionUp");
|
||||||
|
break;
|
||||||
|
case Direction::Down:
|
||||||
|
directionString = RS_(L"DirectionDown");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return winrt::hstring{
|
||||||
|
fmt::format(std::wstring_view(RS_(L"MoveFocusWithArgCommandKey")),
|
||||||
|
directionString)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
winrt::hstring AdjustFontSizeArgs::GenerateName() const
|
||||||
|
{
|
||||||
|
// If the amount is just 1 (or -1), we'll just return "Increase font
|
||||||
|
// size" (or "Decrease font size"). If the amount delta has a greater
|
||||||
|
// absolute value, we'll include it like"
|
||||||
|
// * Decrease font size, amount: {delta}"
|
||||||
|
if (_Delta < 0)
|
||||||
|
{
|
||||||
|
return _Delta == -1 ? RS_(L"DecreaseFontSizeCommandKey") :
|
||||||
|
winrt::hstring{
|
||||||
|
fmt::format(std::wstring_view(RS_(L"DecreaseFontSizeWithAmountCommandKey")),
|
||||||
|
-_Delta)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return _Delta == 1 ? RS_(L"IncreaseFontSizeCommandKey") :
|
||||||
|
winrt::hstring{
|
||||||
|
fmt::format(std::wstring_view(RS_(L"IncreaseFontSizeWithAmountCommandKey")),
|
||||||
|
_Delta)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
winrt::hstring SplitPaneArgs::GenerateName() const
|
||||||
|
{
|
||||||
|
// The string will be similar to the following:
|
||||||
|
// * "Duplicate pane[, split: <direction>][, new terminal arguments...]"
|
||||||
|
// * "Split pane[, split: <direction>][, new terminal arguments...]"
|
||||||
|
//
|
||||||
|
// Direction will only be added to the string if the split direction is
|
||||||
|
// not "auto".
|
||||||
|
// If this is a "duplicate pane" action, then the new terminal arguments
|
||||||
|
// will be omitted (as they're unused)
|
||||||
|
|
||||||
|
std::wstringstream ss;
|
||||||
|
if (_SplitMode == SplitType::Duplicate)
|
||||||
|
{
|
||||||
|
ss << std::wstring_view(RS_(L"DuplicatePaneCommandKey"));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ss << std::wstring_view(RS_(L"SplitPaneCommandKey"));
|
||||||
|
}
|
||||||
|
ss << L", ";
|
||||||
|
|
||||||
|
// This text is intentionally _not_ localized, to attempt to mirror the
|
||||||
|
// exact syntax that the property would have in JSON.
|
||||||
|
switch (_SplitStyle)
|
||||||
|
{
|
||||||
|
case SplitState::Vertical:
|
||||||
|
ss << L"split: vertical, ";
|
||||||
|
break;
|
||||||
|
case SplitState::Horizontal:
|
||||||
|
ss << L"split: horizontal, ";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
winrt::hstring newTerminalArgsStr;
|
||||||
|
if (_TerminalArgs)
|
||||||
|
{
|
||||||
|
newTerminalArgsStr = _TerminalArgs.GenerateName();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_SplitMode != SplitType::Duplicate && !newTerminalArgsStr.empty())
|
||||||
|
{
|
||||||
|
ss << newTerminalArgsStr.c_str();
|
||||||
|
ss << L", ";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Chop off the last ", "
|
||||||
|
auto s = ss.str();
|
||||||
|
return winrt::hstring{ s.substr(0, s.size() - 2) };
|
||||||
|
}
|
||||||
|
|
||||||
|
winrt::hstring OpenSettingsArgs::GenerateName() const
|
||||||
|
{
|
||||||
|
switch (_Target)
|
||||||
|
{
|
||||||
|
case SettingsTarget::DefaultsFile:
|
||||||
|
return RS_(L"OpenDefaultSettingsCommandKey");
|
||||||
|
case SettingsTarget::AllFiles:
|
||||||
|
return RS_(L"OpenBothSettingsFilesCommandKey");
|
||||||
|
default:
|
||||||
|
return RS_(L"OpenSettingsCommandKey");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
winrt::hstring ExecuteCommandlineArgs::GenerateName() const
|
||||||
|
{
|
||||||
|
return winrt::hstring{
|
||||||
|
fmt::format(std::wstring_view(RS_(L"ExecuteCommandlineCommandKey")),
|
||||||
|
_Commandline)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
winrt::hstring SetTabColorArgs::GenerateName() const
|
||||||
|
{
|
||||||
|
// "Set tab color to #RRGGBB"
|
||||||
|
// "Reset tab color"
|
||||||
|
if (_TabColor)
|
||||||
|
{
|
||||||
|
til::color c{ _TabColor.Value() };
|
||||||
|
return winrt::hstring{
|
||||||
|
fmt::format(std::wstring_view(RS_(L"SetTabColorCommandKey")),
|
||||||
|
c.ToHexString(true))
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return RS_(L"ResetTabColorCommandKey");
|
||||||
|
}
|
||||||
|
|
||||||
|
winrt::hstring RenameTabArgs::GenerateName() const
|
||||||
|
{
|
||||||
|
// "Rename tab to \"{_Title}\""
|
||||||
|
// "Reset tab title"
|
||||||
|
if (!_Title.empty())
|
||||||
|
{
|
||||||
|
return winrt::hstring{
|
||||||
|
fmt::format(std::wstring_view(RS_(L"RenameTabCommandKey")),
|
||||||
|
_Title.c_str())
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return RS_(L"ResetTabNameCommandKey");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
#include "MoveFocusArgs.g.h"
|
#include "MoveFocusArgs.g.h"
|
||||||
#include "AdjustFontSizeArgs.g.h"
|
#include "AdjustFontSizeArgs.g.h"
|
||||||
#include "SplitPaneArgs.g.h"
|
#include "SplitPaneArgs.g.h"
|
||||||
|
#include "ExecuteCommandlineArgs.g.h"
|
||||||
#include "OpenSettingsArgs.g.h"
|
#include "OpenSettingsArgs.g.h"
|
||||||
#include "SetTabColorArgs.g.h"
|
#include "SetTabColorArgs.g.h"
|
||||||
#include "RenameTabArgs.g.h"
|
#include "RenameTabArgs.g.h"
|
||||||
@@ -59,6 +60,8 @@ namespace winrt::TerminalApp::implementation
|
|||||||
static constexpr std::string_view ProfileKey{ "profile" };
|
static constexpr std::string_view ProfileKey{ "profile" };
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
hstring GenerateName() const;
|
||||||
|
|
||||||
bool Equals(const winrt::TerminalApp::NewTerminalArgs& other)
|
bool Equals(const winrt::TerminalApp::NewTerminalArgs& other)
|
||||||
{
|
{
|
||||||
return other.Commandline() == _Commandline &&
|
return other.Commandline() == _Commandline &&
|
||||||
@@ -103,6 +106,8 @@ namespace winrt::TerminalApp::implementation
|
|||||||
static constexpr std::string_view SingleLineKey{ "singleLine" };
|
static constexpr std::string_view SingleLineKey{ "singleLine" };
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
hstring GenerateName() const;
|
||||||
|
|
||||||
bool Equals(const IActionArgs& other)
|
bool Equals(const IActionArgs& other)
|
||||||
{
|
{
|
||||||
auto otherAsUs = other.try_as<CopyTextArgs>();
|
auto otherAsUs = other.try_as<CopyTextArgs>();
|
||||||
@@ -130,6 +135,8 @@ namespace winrt::TerminalApp::implementation
|
|||||||
GETSET_PROPERTY(winrt::TerminalApp::NewTerminalArgs, TerminalArgs, nullptr);
|
GETSET_PROPERTY(winrt::TerminalApp::NewTerminalArgs, TerminalArgs, nullptr);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
hstring GenerateName() const;
|
||||||
|
|
||||||
bool Equals(const IActionArgs& other)
|
bool Equals(const IActionArgs& other)
|
||||||
{
|
{
|
||||||
auto otherAsUs = other.try_as<NewTabArgs>();
|
auto otherAsUs = other.try_as<NewTabArgs>();
|
||||||
@@ -156,6 +163,8 @@ namespace winrt::TerminalApp::implementation
|
|||||||
static constexpr std::string_view TabIndexKey{ "index" };
|
static constexpr std::string_view TabIndexKey{ "index" };
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
hstring GenerateName() const;
|
||||||
|
|
||||||
bool Equals(const IActionArgs& other)
|
bool Equals(const IActionArgs& other)
|
||||||
{
|
{
|
||||||
auto otherAsUs = other.try_as<SwitchToTabArgs>();
|
auto otherAsUs = other.try_as<SwitchToTabArgs>();
|
||||||
@@ -220,6 +229,8 @@ namespace winrt::TerminalApp::implementation
|
|||||||
static constexpr std::string_view DirectionKey{ "direction" };
|
static constexpr std::string_view DirectionKey{ "direction" };
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
hstring GenerateName() const;
|
||||||
|
|
||||||
bool Equals(const IActionArgs& other)
|
bool Equals(const IActionArgs& other)
|
||||||
{
|
{
|
||||||
auto otherAsUs = other.try_as<ResizePaneArgs>();
|
auto otherAsUs = other.try_as<ResizePaneArgs>();
|
||||||
@@ -256,6 +267,8 @@ namespace winrt::TerminalApp::implementation
|
|||||||
static constexpr std::string_view DirectionKey{ "direction" };
|
static constexpr std::string_view DirectionKey{ "direction" };
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
hstring GenerateName() const;
|
||||||
|
|
||||||
bool Equals(const IActionArgs& other)
|
bool Equals(const IActionArgs& other)
|
||||||
{
|
{
|
||||||
auto otherAsUs = other.try_as<MoveFocusArgs>();
|
auto otherAsUs = other.try_as<MoveFocusArgs>();
|
||||||
@@ -292,6 +305,8 @@ namespace winrt::TerminalApp::implementation
|
|||||||
static constexpr std::string_view AdjustFontSizeDelta{ "delta" };
|
static constexpr std::string_view AdjustFontSizeDelta{ "delta" };
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
hstring GenerateName() const;
|
||||||
|
|
||||||
bool Equals(const IActionArgs& other)
|
bool Equals(const IActionArgs& other)
|
||||||
{
|
{
|
||||||
auto otherAsUs = other.try_as<AdjustFontSizeArgs>();
|
auto otherAsUs = other.try_as<AdjustFontSizeArgs>();
|
||||||
@@ -358,13 +373,16 @@ namespace winrt::TerminalApp::implementation
|
|||||||
static constexpr std::string_view SplitModeKey{ "splitMode" };
|
static constexpr std::string_view SplitModeKey{ "splitMode" };
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
hstring GenerateName() const;
|
||||||
|
|
||||||
bool Equals(const IActionArgs& other)
|
bool Equals(const IActionArgs& other)
|
||||||
{
|
{
|
||||||
auto otherAsUs = other.try_as<SplitPaneArgs>();
|
auto otherAsUs = other.try_as<SplitPaneArgs>();
|
||||||
if (otherAsUs)
|
if (otherAsUs)
|
||||||
{
|
{
|
||||||
return otherAsUs->_SplitStyle == _SplitStyle &&
|
return otherAsUs->_SplitStyle == _SplitStyle &&
|
||||||
otherAsUs->_TerminalArgs == _TerminalArgs &&
|
(otherAsUs->_TerminalArgs ? otherAsUs->_TerminalArgs.Equals(_TerminalArgs) :
|
||||||
|
otherAsUs->_TerminalArgs == _TerminalArgs) &&
|
||||||
otherAsUs->_SplitMode == _SplitMode;
|
otherAsUs->_SplitMode == _SplitMode;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -386,6 +404,37 @@ namespace winrt::TerminalApp::implementation
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ExecuteCommandlineArgs : public ExecuteCommandlineArgsT<ExecuteCommandlineArgs>
|
||||||
|
{
|
||||||
|
ExecuteCommandlineArgs() = default;
|
||||||
|
GETSET_PROPERTY(winrt::hstring, Commandline, false);
|
||||||
|
|
||||||
|
static constexpr std::string_view CommandlineKey{ "commandline" };
|
||||||
|
|
||||||
|
public:
|
||||||
|
hstring GenerateName() const;
|
||||||
|
|
||||||
|
bool Equals(const IActionArgs& other)
|
||||||
|
{
|
||||||
|
auto otherAsUs = other.try_as<ExecuteCommandlineArgs>();
|
||||||
|
if (otherAsUs)
|
||||||
|
{
|
||||||
|
return otherAsUs->_Commandline == _Commandline;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
static FromJsonResult FromJson(const Json::Value& json)
|
||||||
|
{
|
||||||
|
// LOAD BEARING: Not using make_self here _will_ break you in the future!
|
||||||
|
auto args = winrt::make_self<ExecuteCommandlineArgs>();
|
||||||
|
if (auto commandline{ json[JsonKey(CommandlineKey)] })
|
||||||
|
{
|
||||||
|
args->_Commandline = winrt::to_hstring(commandline.asString());
|
||||||
|
}
|
||||||
|
return { *args, {} };
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Possible SettingsTarget values
|
// Possible SettingsTarget values
|
||||||
// TODO:GH#2550/#3475 - move these to a centralized deserializing place
|
// TODO:GH#2550/#3475 - move these to a centralized deserializing place
|
||||||
static constexpr std::string_view SettingsFileString{ "settingsFile" };
|
static constexpr std::string_view SettingsFileString{ "settingsFile" };
|
||||||
@@ -424,6 +473,8 @@ namespace winrt::TerminalApp::implementation
|
|||||||
static constexpr std::string_view TargetKey{ "target" };
|
static constexpr std::string_view TargetKey{ "target" };
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
hstring GenerateName() const;
|
||||||
|
|
||||||
bool Equals(const IActionArgs& other)
|
bool Equals(const IActionArgs& other)
|
||||||
{
|
{
|
||||||
auto otherAsUs = other.try_as<OpenSettingsArgs>();
|
auto otherAsUs = other.try_as<OpenSettingsArgs>();
|
||||||
@@ -453,6 +504,8 @@ namespace winrt::TerminalApp::implementation
|
|||||||
static constexpr std::string_view ColorKey{ "color" };
|
static constexpr std::string_view ColorKey{ "color" };
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
hstring GenerateName() const;
|
||||||
|
|
||||||
bool Equals(const IActionArgs& other)
|
bool Equals(const IActionArgs& other)
|
||||||
{
|
{
|
||||||
auto otherAsUs = other.try_as<SetTabColorArgs>();
|
auto otherAsUs = other.try_as<SetTabColorArgs>();
|
||||||
@@ -488,6 +541,8 @@ namespace winrt::TerminalApp::implementation
|
|||||||
static constexpr std::string_view TitleKey{ "title" };
|
static constexpr std::string_view TitleKey{ "title" };
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
hstring GenerateName() const;
|
||||||
|
|
||||||
bool Equals(const IActionArgs& other)
|
bool Equals(const IActionArgs& other)
|
||||||
{
|
{
|
||||||
auto otherAsUs = other.try_as<RenameTabArgs>();
|
auto otherAsUs = other.try_as<RenameTabArgs>();
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ namespace TerminalApp
|
|||||||
interface IActionArgs
|
interface IActionArgs
|
||||||
{
|
{
|
||||||
Boolean Equals(IActionArgs other);
|
Boolean Equals(IActionArgs other);
|
||||||
|
String GenerateName();
|
||||||
};
|
};
|
||||||
|
|
||||||
interface IActionEventArgs
|
interface IActionEventArgs
|
||||||
@@ -53,7 +54,9 @@ namespace TerminalApp
|
|||||||
// ProfileIndex can be null (for "use the default"), so this needs to be
|
// ProfileIndex can be null (for "use the default"), so this needs to be
|
||||||
// a IReference, so it's nullable
|
// a IReference, so it's nullable
|
||||||
Windows.Foundation.IReference<Int32> ProfileIndex { get; };
|
Windows.Foundation.IReference<Int32> ProfileIndex { get; };
|
||||||
|
|
||||||
Boolean Equals(NewTerminalArgs other);
|
Boolean Equals(NewTerminalArgs other);
|
||||||
|
String GenerateName();
|
||||||
};
|
};
|
||||||
|
|
||||||
[default_interface] runtimeclass ActionEventArgs : IActionEventArgs
|
[default_interface] runtimeclass ActionEventArgs : IActionEventArgs
|
||||||
@@ -98,6 +101,11 @@ namespace TerminalApp
|
|||||||
SplitType SplitMode { get; };
|
SplitType SplitMode { get; };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
[default_interface] runtimeclass ExecuteCommandlineArgs : IActionArgs
|
||||||
|
{
|
||||||
|
String Commandline;
|
||||||
|
}
|
||||||
|
|
||||||
[default_interface] runtimeclass OpenSettingsArgs : IActionArgs
|
[default_interface] runtimeclass OpenSettingsArgs : IActionArgs
|
||||||
{
|
{
|
||||||
SettingsTarget Target { get; };
|
SettingsTarget Target { get; };
|
||||||
|
|||||||
@@ -238,6 +238,17 @@ namespace winrt::TerminalApp::implementation
|
|||||||
args.Handled(true);
|
args.Handled(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TerminalPage::_HandleToggleCommandPalette(const IInspectable& /*sender*/,
|
||||||
|
const TerminalApp::ActionEventArgs& args)
|
||||||
|
{
|
||||||
|
// TODO GH#6677: When we add support for commandline mode, first set the
|
||||||
|
// mode that the command palette should be in, before making it visible.
|
||||||
|
CommandPalette().Visibility(CommandPalette().Visibility() == Visibility::Visible ?
|
||||||
|
Visibility::Collapsed :
|
||||||
|
Visibility::Visible);
|
||||||
|
args.Handled(true);
|
||||||
|
}
|
||||||
|
|
||||||
void TerminalPage::_HandleSetTabColor(const IInspectable& /*sender*/,
|
void TerminalPage::_HandleSetTabColor(const IInspectable& /*sender*/,
|
||||||
const TerminalApp::ActionEventArgs& args)
|
const TerminalApp::ActionEventArgs& args)
|
||||||
{
|
{
|
||||||
@@ -301,4 +312,40 @@ namespace winrt::TerminalApp::implementation
|
|||||||
}
|
}
|
||||||
args.Handled(true);
|
args.Handled(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TerminalPage::_HandleExecuteCommandline(const IInspectable& /*sender*/,
|
||||||
|
const TerminalApp::ActionEventArgs& actionArgs)
|
||||||
|
{
|
||||||
|
if (const auto& realArgs = actionArgs.ActionArgs().try_as<TerminalApp::ExecuteCommandlineArgs>())
|
||||||
|
{
|
||||||
|
// Convert the commandline into an array of args with
|
||||||
|
// CommandLineToArgvW, similar to how the app typically does when
|
||||||
|
// called from the commandline.
|
||||||
|
int argc = 0;
|
||||||
|
wil::unique_any<LPWSTR*, decltype(&::LocalFree), ::LocalFree> argv{ CommandLineToArgvW(realArgs.Commandline().c_str(), &argc) };
|
||||||
|
if (argv)
|
||||||
|
{
|
||||||
|
std::vector<winrt::hstring> args;
|
||||||
|
|
||||||
|
// Make sure the first argument is wt.exe, because ParseArgs
|
||||||
|
// will always skip the program name.
|
||||||
|
args.emplace_back(L"wt.exe");
|
||||||
|
for (auto& elem : wil::make_range(argv.get(), argc))
|
||||||
|
{
|
||||||
|
args.emplace_back(elem);
|
||||||
|
}
|
||||||
|
winrt::array_view<const winrt::hstring> argsView{ args };
|
||||||
|
|
||||||
|
::TerminalApp::AppCommandlineArgs appArgs;
|
||||||
|
bool handled = appArgs.ParseArgs(argsView) == 0;
|
||||||
|
if (handled)
|
||||||
|
{
|
||||||
|
_startupActions = appArgs.GetStartupActions();
|
||||||
|
_ProcessStartupActions(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
actionArgs.Handled(handled);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -637,3 +637,52 @@ std::optional<winrt::TerminalApp::LaunchMode> AppCommandlineArgs::GetLaunchMode(
|
|||||||
{
|
{
|
||||||
return _launchMode;
|
return _launchMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Method Description:
|
||||||
|
// - Attempts to parse an array of commandline args into a list of
|
||||||
|
// commands to execute, and then parses these commands. As commands are
|
||||||
|
// successfully parsed, they will generate ShortcutActions for us to be
|
||||||
|
// able to execute. If we fail to parse any commands, we'll return the
|
||||||
|
// error code from the failure to parse that command, and stop processing
|
||||||
|
// additional commands.
|
||||||
|
// - The first arg in args should be the program name "wt" (or some variant). It
|
||||||
|
// will be ignored during parsing.
|
||||||
|
// Arguments:
|
||||||
|
// - args: an array of strings to process as a commandline. These args can contain spaces
|
||||||
|
// Return Value:
|
||||||
|
// - 0 if the commandline was successfully parsed
|
||||||
|
int AppCommandlineArgs::ParseArgs(winrt::array_view<const winrt::hstring>& args)
|
||||||
|
{
|
||||||
|
auto commands = ::TerminalApp::AppCommandlineArgs::BuildCommands(args);
|
||||||
|
|
||||||
|
for (auto& cmdBlob : commands)
|
||||||
|
{
|
||||||
|
// On one hand, it seems like we should be able to have one
|
||||||
|
// AppCommandlineArgs for parsing all of them, and collect the
|
||||||
|
// results one at a time.
|
||||||
|
//
|
||||||
|
// On the other hand, re-using a CLI::App seems to leave state from
|
||||||
|
// previous parsings around, so we could get mysterious behavior
|
||||||
|
// where one command affects the values of the next.
|
||||||
|
//
|
||||||
|
// From https://cliutils.github.io/CLI11/book/chapters/options.html:
|
||||||
|
// > If that option is not given, CLI11 will not touch the initial
|
||||||
|
// > value. This allows you to set up defaults by simply setting
|
||||||
|
// > your value beforehand.
|
||||||
|
//
|
||||||
|
// So we pretty much need the to either manually reset the state
|
||||||
|
// each command, or build new ones.
|
||||||
|
const auto result = ParseCommand(cmdBlob);
|
||||||
|
|
||||||
|
// If this succeeded, result will be 0. Otherwise, the caller should
|
||||||
|
// exit(result), to exit the program.
|
||||||
|
if (result != 0)
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If all the args were successfully parsed, we'll have some commands
|
||||||
|
// built in _appArgs, which we'll use when the application starts up.
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|||||||
@@ -28,7 +28,9 @@ public:
|
|||||||
|
|
||||||
AppCommandlineArgs();
|
AppCommandlineArgs();
|
||||||
~AppCommandlineArgs() = default;
|
~AppCommandlineArgs() = default;
|
||||||
|
|
||||||
int ParseCommand(const Commandline& command);
|
int ParseCommand(const Commandline& command);
|
||||||
|
int ParseArgs(winrt::array_view<const winrt::hstring>& args);
|
||||||
|
|
||||||
static std::vector<Commandline> BuildCommands(const std::vector<const wchar_t*>& args);
|
static std::vector<Commandline> BuildCommands(const std::vector<const wchar_t*>& args);
|
||||||
static std::vector<Commandline> BuildCommands(winrt::array_view<const winrt::hstring>& args);
|
static std::vector<Commandline> BuildCommands(winrt::array_view<const winrt::hstring>& args);
|
||||||
|
|||||||
@@ -55,8 +55,11 @@ namespace winrt::TerminalApp::implementation
|
|||||||
{
|
{
|
||||||
for (auto& kv : _keyShortcuts)
|
for (auto& kv : _keyShortcuts)
|
||||||
{
|
{
|
||||||
if (kv.second.Action() == actionAndArgs.Action() &&
|
const auto action = kv.second.Action();
|
||||||
kv.second.Args().Equals(actionAndArgs.Args()))
|
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 kv.first;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ Json::Value winrt::TerminalApp::implementation::AppKeyBindings::ToJson()
|
|||||||
|
|
||||||
// Iterate over all the possible actions in the names list, and see if
|
// Iterate over all the possible actions in the names list, and see if
|
||||||
// it has a binding.
|
// it has a binding.
|
||||||
for (auto& actionName : ActionAndArgs::ActionNamesMap)
|
for (auto& actionName : ActionAndArgs::ActionKeyNamesMap)
|
||||||
{
|
{
|
||||||
const auto searchedForName = actionName.first;
|
const auto searchedForName = actionName.first;
|
||||||
const auto searchedForAction = actionName.second;
|
const auto searchedForAction = actionName.second;
|
||||||
@@ -85,7 +85,7 @@ Json::Value winrt::TerminalApp::implementation::AppKeyBindings::ToJson()
|
|||||||
// - Deserialize an AppKeyBindings from the key mappings that are in the array
|
// - Deserialize an AppKeyBindings from the key mappings that are in the array
|
||||||
// `json`. The json array should contain an array of objects with both a
|
// `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
|
// `command` string and a `keys` array, where `command` is one of the names
|
||||||
// listed in `ActionAndArgs::ActionNamesMap`, and `keys` is an array of
|
// listed in `ActionAndArgs::ActionKeyNamesMap`, and `keys` is an array of
|
||||||
// keypresses. Currently, the array should contain a single string, which can
|
// keypresses. Currently, the array should contain a single string, which can
|
||||||
// be deserialized into a KeyChord.
|
// be deserialized into a KeyChord.
|
||||||
// - Applies the deserialized keybindings to the provided `bindings` object. If
|
// - Applies the deserialized keybindings to the provided `bindings` object. If
|
||||||
|
|||||||
@@ -472,7 +472,7 @@ namespace winrt::TerminalApp::implementation
|
|||||||
// - <none>
|
// - <none>
|
||||||
// Return Value:
|
// Return Value:
|
||||||
// - a point containing the requested dimensions in pixels.
|
// - a point containing the requested dimensions in pixels.
|
||||||
winrt::Windows::Foundation::Point AppLogic::GetLaunchDimensions(uint32_t dpi)
|
winrt::Windows::Foundation::Size AppLogic::GetLaunchDimensions(uint32_t dpi)
|
||||||
{
|
{
|
||||||
if (!_loadedInitialSettings)
|
if (!_loadedInitialSettings)
|
||||||
{
|
{
|
||||||
@@ -502,7 +502,7 @@ namespace winrt::TerminalApp::implementation
|
|||||||
// of the height calculation here.
|
// of the height calculation here.
|
||||||
auto titlebar = TitlebarControl{ static_cast<uint64_t>(0) };
|
auto titlebar = TitlebarControl{ static_cast<uint64_t>(0) };
|
||||||
titlebar.Measure({ SHRT_MAX, SHRT_MAX });
|
titlebar.Measure({ SHRT_MAX, SHRT_MAX });
|
||||||
proposedSize.Y += (titlebar.DesiredSize().Height) * scale;
|
proposedSize.Height += (titlebar.DesiredSize().Height) * scale;
|
||||||
}
|
}
|
||||||
else if (_settings->GlobalSettings().AlwaysShowTabs())
|
else if (_settings->GlobalSettings().AlwaysShowTabs())
|
||||||
{
|
{
|
||||||
@@ -517,7 +517,7 @@ namespace winrt::TerminalApp::implementation
|
|||||||
// For whatever reason, there's about 6px of unaccounted-for space
|
// For whatever reason, there's about 6px of unaccounted-for space
|
||||||
// in the application. I couldn't tell you where these 6px are
|
// in the application. I couldn't tell you where these 6px are
|
||||||
// coming from, but they need to be included in this math.
|
// coming from, but they need to be included in this math.
|
||||||
proposedSize.Y += (tabControl.DesiredSize().Height + 6) * scale;
|
proposedSize.Width += (tabControl.DesiredSize().Height + 6) * scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
return proposedSize;
|
return proposedSize;
|
||||||
@@ -972,7 +972,7 @@ namespace winrt::TerminalApp::implementation
|
|||||||
// or 0. (see AppLogic::_ParseArgs)
|
// or 0. (see AppLogic::_ParseArgs)
|
||||||
int32_t AppLogic::SetStartupCommandline(array_view<const winrt::hstring> args)
|
int32_t AppLogic::SetStartupCommandline(array_view<const winrt::hstring> args)
|
||||||
{
|
{
|
||||||
const auto result = _ParseArgs(args);
|
const auto result = _appArgs.ParseArgs(args);
|
||||||
if (result == 0)
|
if (result == 0)
|
||||||
{
|
{
|
||||||
_appArgs.ValidateStartupCommands();
|
_appArgs.ValidateStartupCommands();
|
||||||
@@ -982,53 +982,6 @@ namespace winrt::TerminalApp::implementation
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Method Description:
|
|
||||||
// - Attempts to parse an array of commandline args into a list of
|
|
||||||
// commands to execute, and then parses these commands. As commands are
|
|
||||||
// successfully parsed, they will generate ShortcutActions for us to be
|
|
||||||
// able to execute. If we fail to parse any commands, we'll return the
|
|
||||||
// error code from the failure to parse that command, and stop processing
|
|
||||||
// additional commands.
|
|
||||||
// Arguments:
|
|
||||||
// - args: an array of strings to process as a commandline. These args can contain spaces
|
|
||||||
// Return Value:
|
|
||||||
// - 0 if the commandline was successfully parsed
|
|
||||||
int AppLogic::_ParseArgs(winrt::array_view<const hstring>& args)
|
|
||||||
{
|
|
||||||
auto commands = ::TerminalApp::AppCommandlineArgs::BuildCommands(args);
|
|
||||||
|
|
||||||
for (auto& cmdBlob : commands)
|
|
||||||
{
|
|
||||||
// On one hand, it seems like we should be able to have one
|
|
||||||
// AppCommandlineArgs for parsing all of them, and collect the
|
|
||||||
// results one at a time.
|
|
||||||
//
|
|
||||||
// On the other hand, re-using a CLI::App seems to leave state from
|
|
||||||
// previous parsings around, so we could get mysterious behavior
|
|
||||||
// where one command affects the values of the next.
|
|
||||||
//
|
|
||||||
// From https://cliutils.github.io/CLI11/book/chapters/options.html:
|
|
||||||
// > If that option is not given, CLI11 will not touch the initial
|
|
||||||
// > value. This allows you to set up defaults by simply setting
|
|
||||||
// > your value beforehand.
|
|
||||||
//
|
|
||||||
// So we pretty much need the to either manually reset the state
|
|
||||||
// each command, or build new ones.
|
|
||||||
const auto result = _appArgs.ParseCommand(cmdBlob);
|
|
||||||
|
|
||||||
// If this succeeded, result will be 0. Otherwise, the caller should
|
|
||||||
// exit(result), to exit the program.
|
|
||||||
if (result != 0)
|
|
||||||
{
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If all the args were successfully parsed, we'll have some commands
|
|
||||||
// built in _appArgs, which we'll use when the application starts up.
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Method Description:
|
// Method Description:
|
||||||
// - If there were any errors parsing the commandline that was used to
|
// - If there were any errors parsing the commandline that was used to
|
||||||
// initialize the terminal, this will return a string containing that
|
// initialize the terminal, this will return a string containing that
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ namespace winrt::TerminalApp::implementation
|
|||||||
winrt::hstring ApplicationDisplayName() const;
|
winrt::hstring ApplicationDisplayName() const;
|
||||||
winrt::hstring ApplicationVersion() const;
|
winrt::hstring ApplicationVersion() const;
|
||||||
|
|
||||||
Windows::Foundation::Point GetLaunchDimensions(uint32_t dpi);
|
Windows::Foundation::Size GetLaunchDimensions(uint32_t dpi);
|
||||||
winrt::Windows::Foundation::Point GetLaunchInitialPositions(int32_t defaultInitialX, int32_t defaultInitialY);
|
winrt::Windows::Foundation::Point GetLaunchInitialPositions(int32_t defaultInitialX, int32_t defaultInitialY);
|
||||||
winrt::Windows::UI::Xaml::ElementTheme GetRequestedTheme();
|
winrt::Windows::UI::Xaml::ElementTheme GetRequestedTheme();
|
||||||
LaunchMode GetLaunchMode();
|
LaunchMode GetLaunchMode();
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ namespace TerminalApp
|
|||||||
String ApplicationDisplayName { get; };
|
String ApplicationDisplayName { get; };
|
||||||
String ApplicationVersion { get; };
|
String ApplicationVersion { get; };
|
||||||
|
|
||||||
Windows.Foundation.Point GetLaunchDimensions(UInt32 dpi);
|
Windows.Foundation.Size GetLaunchDimensions(UInt32 dpi);
|
||||||
Windows.Foundation.Point GetLaunchInitialPositions(Int32 defaultInitialX, Int32 defaultInitialY);
|
Windows.Foundation.Point GetLaunchInitialPositions(Int32 defaultInitialX, Int32 defaultInitialY);
|
||||||
Windows.UI.Xaml.ElementTheme GetRequestedTheme();
|
Windows.UI.Xaml.ElementTheme GetRequestedTheme();
|
||||||
LaunchMode GetLaunchMode();
|
LaunchMode GetLaunchMode();
|
||||||
|
|||||||
191
src/cascadia/TerminalApp/Command.cpp
Normal file
191
src/cascadia/TerminalApp/Command.cpp
Normal file
@@ -0,0 +1,191 @@
|
|||||||
|
// Copyright (c) Microsoft Corporation.
|
||||||
|
// Licensed under the MIT license.
|
||||||
|
|
||||||
|
#include "pch.h"
|
||||||
|
#include "Command.h"
|
||||||
|
#include "Command.g.cpp"
|
||||||
|
|
||||||
|
#include "Utils.h"
|
||||||
|
#include "ActionAndArgs.h"
|
||||||
|
#include <LibraryResources.h>
|
||||||
|
|
||||||
|
using namespace winrt::Microsoft::Terminal::Settings;
|
||||||
|
using namespace winrt::TerminalApp;
|
||||||
|
|
||||||
|
static constexpr std::string_view NameKey{ "name" };
|
||||||
|
static constexpr std::string_view IconPathKey{ "iconPath" };
|
||||||
|
static constexpr std::string_view ActionKey{ "command" };
|
||||||
|
static constexpr std::string_view ArgsKey{ "args" };
|
||||||
|
|
||||||
|
namespace winrt::TerminalApp::implementation
|
||||||
|
{
|
||||||
|
// 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.
|
||||||
|
// * If the "name" property is an object, attempt to lookup the string
|
||||||
|
// resource specified by the "key" property, to support localizable
|
||||||
|
// command names.
|
||||||
|
// Arguments:
|
||||||
|
// - 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)
|
||||||
|
{
|
||||||
|
if (const auto name{ json[JsonKey(NameKey)] })
|
||||||
|
{
|
||||||
|
if (name.isObject())
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (const auto keyJson{ name[JsonKey("key")] })
|
||||||
|
{
|
||||||
|
// Make sure the key is present before we try
|
||||||
|
// loading it. Otherwise we'll crash
|
||||||
|
const auto resourceKey = GetWstringFromJson(keyJson);
|
||||||
|
if (HasLibraryResourceWithName(resourceKey))
|
||||||
|
{
|
||||||
|
return GetLibraryResourceString(resourceKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CATCH_LOG();
|
||||||
|
}
|
||||||
|
else if (name.isString())
|
||||||
|
{
|
||||||
|
auto nameStr = name.asString();
|
||||||
|
return winrt::to_hstring(nameStr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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())
|
||||||
|
{
|
||||||
|
return manualName;
|
||||||
|
}
|
||||||
|
if (!actionAndArgs)
|
||||||
|
{
|
||||||
|
return L"";
|
||||||
|
}
|
||||||
|
|
||||||
|
return actionAndArgs->GenerateName();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Method Description:
|
||||||
|
// - Deserialize a Command from the `json` object. The json object should
|
||||||
|
// contain a "name" and "action", and optionally an "icon".
|
||||||
|
// * "name": string|object - the name of the command to display in the
|
||||||
|
// command palette. If this is an object, look for the "key" property,
|
||||||
|
// and try to load the string from our resources instead.
|
||||||
|
// * "action": string|object - A ShortcutAction, either as a name or as an
|
||||||
|
// ActionAndArgs serialization. See ActionAndArgs::FromJson for details.
|
||||||
|
// If this is null, we'll remove this command from the list of commands.
|
||||||
|
// Arguments:
|
||||||
|
// - json: the Json::Value to deserialize into a Command
|
||||||
|
// - warnings: If there were any warnings during parsing, they'll be
|
||||||
|
// appended to this vector.
|
||||||
|
// Return Value:
|
||||||
|
// - the newly constructed Command object.
|
||||||
|
winrt::com_ptr<Command> Command::FromJson(const Json::Value& json,
|
||||||
|
std::vector<::TerminalApp::SettingsLoadWarnings>& warnings)
|
||||||
|
{
|
||||||
|
auto result = winrt::make_self<Command>();
|
||||||
|
|
||||||
|
// TODO GH#6644: iconPath not implemented quite yet. Can't seem to get
|
||||||
|
// the binding quite right. Additionally, do we want it to be an image,
|
||||||
|
// or a FontIcon? I've had difficulty binding either/or.
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
result->_setName(_nameFromJsonOrAction(json, actionAndArgs));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// { name: "foo", action: null } will land in this case, which
|
||||||
|
// should also be used for unbinding.
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result->_Name.empty())
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function Description:
|
||||||
|
// - Attempt to parse all the json objects in `json` into new Command
|
||||||
|
// objects, and add them to the map of commands.
|
||||||
|
// - If any parsed command has
|
||||||
|
// the same Name as an existing command in commands, the new one will
|
||||||
|
// layer on top of the existing one.
|
||||||
|
// Arguments:
|
||||||
|
// - commands: a map of Name->Command which new commands should be layered upon.
|
||||||
|
// - json: A Json::Value containing an array of serialized commands
|
||||||
|
// Return Value:
|
||||||
|
// - A vector containing any warnings detected while parsing
|
||||||
|
std::vector<::TerminalApp::SettingsLoadWarnings> Command::LayerJson(std::unordered_map<winrt::hstring, winrt::TerminalApp::Command>& commands,
|
||||||
|
const Json::Value& json)
|
||||||
|
{
|
||||||
|
std::vector<::TerminalApp::SettingsLoadWarnings> warnings;
|
||||||
|
|
||||||
|
for (const auto& value : json)
|
||||||
|
{
|
||||||
|
if (value.isObject())
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
auto result = Command::FromJson(value, warnings);
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
// Override commands with the same name
|
||||||
|
commands.insert_or_assign(result->Name(), *result);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// 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())
|
||||||
|
{
|
||||||
|
commands.erase(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CATCH_LOG();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return warnings;
|
||||||
|
}
|
||||||
|
}
|
||||||
45
src/cascadia/TerminalApp/Command.h
Normal file
45
src/cascadia/TerminalApp/Command.h
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
/*++
|
||||||
|
Copyright (c) Microsoft Corporation
|
||||||
|
Licensed under the MIT license.
|
||||||
|
|
||||||
|
Module Name:
|
||||||
|
- Command.h
|
||||||
|
|
||||||
|
Abstract:
|
||||||
|
- A command represents a single entry in the Command Palette. This is an object
|
||||||
|
that has a user facing "name" to display to the user, and an associated action
|
||||||
|
which can be dispatched.
|
||||||
|
|
||||||
|
- For more information, see GH#2046, #5400, #5674, and #6635
|
||||||
|
|
||||||
|
Author(s):
|
||||||
|
- Mike Griese - June 2020
|
||||||
|
|
||||||
|
--*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Command.g.h"
|
||||||
|
#include "TerminalWarnings.h"
|
||||||
|
#include "..\inc\cppwinrt_utils.h"
|
||||||
|
|
||||||
|
namespace winrt::TerminalApp::implementation
|
||||||
|
{
|
||||||
|
struct Command : CommandT<Command>
|
||||||
|
{
|
||||||
|
Command() = default;
|
||||||
|
|
||||||
|
static winrt::com_ptr<Command> FromJson(const Json::Value& json, std::vector<::TerminalApp::SettingsLoadWarnings>& warnings);
|
||||||
|
static std::vector<::TerminalApp::SettingsLoadWarnings> LayerJson(std::unordered_map<winrt::hstring, winrt::TerminalApp::Command>& commands,
|
||||||
|
const Json::Value& json);
|
||||||
|
|
||||||
|
WINRT_CALLBACK(PropertyChanged, Windows::UI::Xaml::Data::PropertyChangedEventHandler);
|
||||||
|
OBSERVABLE_GETSET_PROPERTY(winrt::hstring, Name, _PropertyChangedHandlers);
|
||||||
|
OBSERVABLE_GETSET_PROPERTY(winrt::TerminalApp::ActionAndArgs, Action, _PropertyChangedHandlers);
|
||||||
|
OBSERVABLE_GETSET_PROPERTY(winrt::hstring, KeyChordText, _PropertyChangedHandlers);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace winrt::TerminalApp::factory_implementation
|
||||||
|
{
|
||||||
|
BASIC_FACTORY(Command);
|
||||||
|
}
|
||||||
16
src/cascadia/TerminalApp/Command.idl
Normal file
16
src/cascadia/TerminalApp/Command.idl
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
// Copyright (c) Microsoft Corporation.
|
||||||
|
// Licensed under the MIT license.
|
||||||
|
|
||||||
|
import "../ShortcutActionDispatch.idl";
|
||||||
|
|
||||||
|
namespace TerminalApp
|
||||||
|
{
|
||||||
|
[default_interface] runtimeclass Command : Windows.UI.Xaml.Data.INotifyPropertyChanged
|
||||||
|
{
|
||||||
|
Command();
|
||||||
|
|
||||||
|
String Name;
|
||||||
|
ActionAndArgs Action;
|
||||||
|
String KeyChordText;
|
||||||
|
}
|
||||||
|
}
|
||||||
480
src/cascadia/TerminalApp/CommandPalette.cpp
Normal file
480
src/cascadia/TerminalApp/CommandPalette.cpp
Normal file
@@ -0,0 +1,480 @@
|
|||||||
|
// Copyright (c) Microsoft Corporation.
|
||||||
|
// Licensed under the MIT license.
|
||||||
|
|
||||||
|
#include "pch.h"
|
||||||
|
#include "CommandPalette.h"
|
||||||
|
#include "ActionArgs.h"
|
||||||
|
#include "ActionAndArgs.h"
|
||||||
|
|
||||||
|
#include "CommandPalette.g.cpp"
|
||||||
|
#include <winrt/Microsoft.Terminal.Settings.h>
|
||||||
|
|
||||||
|
using namespace winrt;
|
||||||
|
using namespace winrt::TerminalApp;
|
||||||
|
using namespace winrt::Windows::UI::Core;
|
||||||
|
using namespace winrt::Windows::UI::Xaml;
|
||||||
|
using namespace winrt::Windows::System;
|
||||||
|
using namespace winrt::Windows::Foundation;
|
||||||
|
|
||||||
|
namespace winrt::TerminalApp::implementation
|
||||||
|
{
|
||||||
|
CommandPalette::CommandPalette()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
|
||||||
|
_filteredActions = winrt::single_threaded_observable_vector<winrt::TerminalApp::Command>();
|
||||||
|
_allActions = winrt::single_threaded_vector<winrt::TerminalApp::Command>();
|
||||||
|
|
||||||
|
if (CommandPaletteShadow())
|
||||||
|
{
|
||||||
|
// Hook up the shadow on the command palette to the backdrop that
|
||||||
|
// will actually show it. This needs to be done at runtime, and only
|
||||||
|
// if the shadow actually exists. ThemeShadow isn't supported below
|
||||||
|
// version 18362.
|
||||||
|
CommandPaletteShadow().Receivers().Append(_shadowBackdrop());
|
||||||
|
// "raise" the command palette up by 16 units, so it will cast a shadow.
|
||||||
|
_backdrop().Translation({ 0, 0, 16 });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Whatever is hosting us will enable us by setting our visibility to
|
||||||
|
// "Visible". When that happens, set focus to our search box.
|
||||||
|
RegisterPropertyChangedCallback(UIElement::VisibilityProperty(), [this](auto&&, auto&&) {
|
||||||
|
if (Visibility() == Visibility::Visible)
|
||||||
|
{
|
||||||
|
_searchBox().Focus(FocusState::Programmatic);
|
||||||
|
_filteredActionsView().SelectedIndex(0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Raise an event to return control to the Terminal.
|
||||||
|
_close();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Method Description:
|
||||||
|
// - Moves the focus up or down the list of commands. If we're at the top,
|
||||||
|
// we'll loop around to the bottom, and vice-versa.
|
||||||
|
// Arguments:
|
||||||
|
// - moveDown: if true, we're attempting to move to the next item in the
|
||||||
|
// list. Otherwise, we're attempting to move to the previous.
|
||||||
|
// Return Value:
|
||||||
|
// - <none>
|
||||||
|
void CommandPalette::_selectNextItem(const bool moveDown)
|
||||||
|
{
|
||||||
|
const auto selected = _filteredActionsView().SelectedIndex();
|
||||||
|
const int numItems = ::base::saturated_cast<int>(_filteredActionsView().Items().Size());
|
||||||
|
// Wraparound math. By adding numItems and then calculating modulo numItems,
|
||||||
|
// we clamp the values to the range [0, numItems) while still supporting moving
|
||||||
|
// upward from 0 to numItems - 1.
|
||||||
|
const auto newIndex = ((numItems + selected + (moveDown ? 1 : -1)) % numItems);
|
||||||
|
_filteredActionsView().SelectedIndex(newIndex);
|
||||||
|
_filteredActionsView().ScrollIntoView(_filteredActionsView().SelectedItem());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Method Description:
|
||||||
|
// - Process keystrokes in the input box. This is used for moving focus up
|
||||||
|
// and down the list of commands in Action mode, and for executing
|
||||||
|
// commands in both Action mode and Commandline mode.
|
||||||
|
// Arguments:
|
||||||
|
// - e: the KeyRoutedEventArgs containing info about the keystroke.
|
||||||
|
// Return Value:
|
||||||
|
// - <none>
|
||||||
|
void CommandPalette::_keyDownHandler(IInspectable const& /*sender*/,
|
||||||
|
Windows::UI::Xaml::Input::KeyRoutedEventArgs const& e)
|
||||||
|
{
|
||||||
|
auto key = e.OriginalKey();
|
||||||
|
|
||||||
|
if (key == VirtualKey::Up)
|
||||||
|
{
|
||||||
|
// Action Mode: Move focus to the next item in the list.
|
||||||
|
_selectNextItem(false);
|
||||||
|
e.Handled(true);
|
||||||
|
}
|
||||||
|
else if (key == VirtualKey::Down)
|
||||||
|
{
|
||||||
|
// Action Mode: Move focus to the previous item in the list.
|
||||||
|
_selectNextItem(true);
|
||||||
|
e.Handled(true);
|
||||||
|
}
|
||||||
|
else if (key == VirtualKey::Enter)
|
||||||
|
{
|
||||||
|
if (_mode == PaletteMode::ActionMode)
|
||||||
|
{
|
||||||
|
// Action Mode: Dispatch the action of the selected command.
|
||||||
|
if (const auto selectedItem = _filteredActionsView().SelectedItem())
|
||||||
|
{
|
||||||
|
_dispatchAction();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_dispatchCommandline();
|
||||||
|
}
|
||||||
|
|
||||||
|
e.Handled(true);
|
||||||
|
}
|
||||||
|
else if (key == VirtualKey::Escape)
|
||||||
|
{
|
||||||
|
// Action Mode: Dismiss the palette if the text is empty, otherwise clear the search string.
|
||||||
|
if (_searchBox().Text().empty())
|
||||||
|
{
|
||||||
|
_close();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_searchBox().Text(L"");
|
||||||
|
}
|
||||||
|
|
||||||
|
e.Handled(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Method Description:
|
||||||
|
// - This event is triggered when someone clicks anywhere in the bounds of
|
||||||
|
// the window that's _not_ the command palette UI. When that happens,
|
||||||
|
// we'll want to dismiss the palette.
|
||||||
|
// Arguments:
|
||||||
|
// - <unused>
|
||||||
|
// Return Value:
|
||||||
|
// - <none>
|
||||||
|
void CommandPalette::_rootPointerPressed(Windows::Foundation::IInspectable const& /*sender*/,
|
||||||
|
Windows::UI::Xaml::Input::PointerRoutedEventArgs const& /*e*/)
|
||||||
|
{
|
||||||
|
_close();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Method Description:
|
||||||
|
// - This event is only triggered when someone clicks in the space right
|
||||||
|
// next to the text box in the command palette. We _don't_ want that click
|
||||||
|
// to light dismiss the palette, so we'll mark it handled here.
|
||||||
|
// Arguments:
|
||||||
|
// - e: the PointerRoutedEventArgs that we want to mark as handled
|
||||||
|
// Return Value:
|
||||||
|
// - <none>
|
||||||
|
void CommandPalette::_backdropPointerPressed(Windows::Foundation::IInspectable const& /*sender*/,
|
||||||
|
Windows::UI::Xaml::Input::PointerRoutedEventArgs const& e)
|
||||||
|
{
|
||||||
|
e.Handled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Method Description:
|
||||||
|
// - This event is called when the user clicks on an individual item from
|
||||||
|
// the list. We'll get the item that was clicked and dispatch the command
|
||||||
|
// that the user clicked on.
|
||||||
|
// Arguments:
|
||||||
|
// - e: an ItemClickEventArgs who's ClickedItem() will be the command that was clicked on.
|
||||||
|
// Return Value:
|
||||||
|
// - <none>
|
||||||
|
void CommandPalette::_listItemClicked(Windows::Foundation::IInspectable const& /*sender*/,
|
||||||
|
Windows::UI::Xaml::Controls::ItemClickEventArgs const& e)
|
||||||
|
{
|
||||||
|
if (auto command{ e.ClickedItem().try_as<TerminalApp::Command>() })
|
||||||
|
{
|
||||||
|
const auto actionAndArgs = command.Action();
|
||||||
|
_dispatch.DoAction(actionAndArgs);
|
||||||
|
_close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Method Description:
|
||||||
|
// - Event handler for when the text in the input box changes. In Action
|
||||||
|
// Mode, we'll update the list of displayed commands, and select the first one.
|
||||||
|
// Arguments:
|
||||||
|
// - <unused>
|
||||||
|
// Return Value:
|
||||||
|
// - <none>
|
||||||
|
void CommandPalette::_filterTextChanged(IInspectable const& /*sender*/,
|
||||||
|
Windows::UI::Xaml::RoutedEventArgs const& /*args*/)
|
||||||
|
{
|
||||||
|
_checkMode();
|
||||||
|
_updateFilteredActions();
|
||||||
|
_filteredActionsView().SelectedIndex(0);
|
||||||
|
|
||||||
|
_noMatchesText().Visibility(_filteredActions.Size() > 0 ? Visibility::Collapsed : Visibility::Visible);
|
||||||
|
}
|
||||||
|
|
||||||
|
Collections::IObservableVector<Command> CommandPalette::FilteredActions()
|
||||||
|
{
|
||||||
|
return _filteredActions;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CommandPalette::SetActions(Collections::IVector<TerminalApp::Command> const& actions)
|
||||||
|
{
|
||||||
|
_allActions = actions;
|
||||||
|
_updateFilteredActions();
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is a helper to aid in sorting commands by their `Name`s, alphabetically.
|
||||||
|
static bool _compareCommandNames(const TerminalApp::Command& lhs, const TerminalApp::Command& rhs)
|
||||||
|
{
|
||||||
|
std::wstring_view leftName{ lhs.Name() };
|
||||||
|
std::wstring_view rightName{ rhs.Name() };
|
||||||
|
return leftName.compare(rightName) < 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is a helper struct to aid in sorting Commands by a given weighting.
|
||||||
|
struct WeightedCommand
|
||||||
|
{
|
||||||
|
TerminalApp::Command command;
|
||||||
|
int weight;
|
||||||
|
|
||||||
|
bool operator<(const WeightedCommand& other) const
|
||||||
|
{
|
||||||
|
// If two commands have the same weight, then we'll sort them alphabetically.
|
||||||
|
if (weight == other.weight)
|
||||||
|
{
|
||||||
|
return !_compareCommandNames(command, other.command);
|
||||||
|
}
|
||||||
|
return weight < other.weight;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Method Description:
|
||||||
|
// - Update our list of filtered actions to reflect the current contents of
|
||||||
|
// the input box. For more details on which commands will be displayed,
|
||||||
|
// see `_getWeight`.
|
||||||
|
// Arguments:
|
||||||
|
// - <none>
|
||||||
|
// Return Value:
|
||||||
|
// - <none>
|
||||||
|
void CommandPalette::_updateFilteredActions()
|
||||||
|
{
|
||||||
|
_filteredActions.Clear();
|
||||||
|
|
||||||
|
if (_mode == PaletteMode::CommandlineMode)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto searchText = _searchBox().Text();
|
||||||
|
const bool addAll = searchText.empty();
|
||||||
|
|
||||||
|
// If there's no filter text, then just add all the commands in order to the list.
|
||||||
|
// - TODO GH#6647:Possibly add the MRU commands first in order, followed
|
||||||
|
// by the rest of the commands.
|
||||||
|
if (addAll)
|
||||||
|
{
|
||||||
|
// Add all the commands, but make sure they're sorted alphabetically.
|
||||||
|
std::vector<TerminalApp::Command> sortedCommands;
|
||||||
|
sortedCommands.reserve(_allActions.Size());
|
||||||
|
|
||||||
|
for (auto action : _allActions)
|
||||||
|
{
|
||||||
|
sortedCommands.push_back(action);
|
||||||
|
}
|
||||||
|
std::sort(sortedCommands.begin(),
|
||||||
|
sortedCommands.end(),
|
||||||
|
_compareCommandNames);
|
||||||
|
|
||||||
|
for (auto action : sortedCommands)
|
||||||
|
{
|
||||||
|
_filteredActions.Append(action);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Here, there was some filter text.
|
||||||
|
// Show these actions in a weighted order.
|
||||||
|
// - Matching the first character of a word, then the first char of a
|
||||||
|
// subsequent word seems better than just "the order they appear in
|
||||||
|
// the list".
|
||||||
|
// - TODO GH#6647:"Recently used commands" ordering also seems valuable.
|
||||||
|
// * This could be done by weighting the recently used commands
|
||||||
|
// higher the more recently they were used, then weighting all
|
||||||
|
// the unused commands as 1
|
||||||
|
|
||||||
|
// Use a priority queue to order commands so that "better" matches
|
||||||
|
// appear first in the list. The ordering will be determined by the
|
||||||
|
// match weight produced by _getWeight.
|
||||||
|
std::priority_queue<WeightedCommand> heap;
|
||||||
|
for (auto action : _allActions)
|
||||||
|
{
|
||||||
|
const auto weight = CommandPalette::_getWeight(searchText, action.Name());
|
||||||
|
if (weight > 0)
|
||||||
|
{
|
||||||
|
WeightedCommand wc;
|
||||||
|
wc.command = action;
|
||||||
|
wc.weight = weight;
|
||||||
|
heap.push(wc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// At this point, all the commands in heap are matches. We've also
|
||||||
|
// sorted commands with the same weight alphabetically.
|
||||||
|
// Remove everything in-order from the queue, and add to the list of
|
||||||
|
// filtered actions.
|
||||||
|
while (!heap.empty())
|
||||||
|
{
|
||||||
|
auto top = heap.top();
|
||||||
|
heap.pop();
|
||||||
|
_filteredActions.Append(top.command);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function Description:
|
||||||
|
// - Calculates a "weighting" by which should be used to order a command
|
||||||
|
// name relative to other names, given a specific search string.
|
||||||
|
// Currently, this is based off of two factors:
|
||||||
|
// * The weight is incremented once for each matched character of the
|
||||||
|
// search text.
|
||||||
|
// * If a matching character from the search text was found at the start
|
||||||
|
// of a word in the name, then we increment the weight again.
|
||||||
|
// * For example, for a search string "sp", we want "Split Pane" to
|
||||||
|
// appear in the list before "Close Pane"
|
||||||
|
// * Consecutive matches will be weighted higher than matches with
|
||||||
|
// characters in between the search characters.
|
||||||
|
// - This will return 0 if the command should not be shown. If all the
|
||||||
|
// characters of search text appear in order in `name`, then this function
|
||||||
|
// will return a positive number. There can be any number of characters
|
||||||
|
// separating consecutive characters in searchText.
|
||||||
|
// * For example:
|
||||||
|
// "name": "New Tab"
|
||||||
|
// "name": "Close Tab"
|
||||||
|
// "name": "Close Pane"
|
||||||
|
// "name": "[-] Split Horizontal"
|
||||||
|
// "name": "[ | ] Split Vertical"
|
||||||
|
// "name": "Next Tab"
|
||||||
|
// "name": "Prev Tab"
|
||||||
|
// "name": "Open Settings"
|
||||||
|
// "name": "Open Media Controls"
|
||||||
|
// * "open" should return both "**Open** Settings" and "**Open** Media Controls".
|
||||||
|
// * "Tab" would return "New **Tab**", "Close **Tab**", "Next **Tab**" and "Prev
|
||||||
|
// **Tab**".
|
||||||
|
// * "P" would return "Close **P**ane", "[-] S**p**lit Horizontal", "[ | ]
|
||||||
|
// S**p**lit Vertical", "**P**rev Tab", "O**p**en Settings" and "O**p**en Media
|
||||||
|
// Controls".
|
||||||
|
// * "sv" would return "[ | ] Split Vertical" (by matching the **S** in
|
||||||
|
// "Split", then the **V** in "Vertical").
|
||||||
|
// Arguments:
|
||||||
|
// - searchText: the string of text to search for in `name`
|
||||||
|
// - name: the name to check
|
||||||
|
// Return Value:
|
||||||
|
// - the relative weight of this match
|
||||||
|
int CommandPalette::_getWeight(const winrt::hstring& searchText,
|
||||||
|
const winrt::hstring& name)
|
||||||
|
{
|
||||||
|
int totalWeight = 0;
|
||||||
|
bool lastWasSpace = true;
|
||||||
|
|
||||||
|
auto it = name.cbegin();
|
||||||
|
|
||||||
|
for (auto searchChar : searchText)
|
||||||
|
{
|
||||||
|
searchChar = std::towlower(searchChar);
|
||||||
|
// Advance the iterator to the next character that we're looking
|
||||||
|
// for.
|
||||||
|
|
||||||
|
bool lastWasMatch = true;
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
// If we are at the end of the name string, we haven't found
|
||||||
|
// it.
|
||||||
|
if (it == name.cend())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// found it
|
||||||
|
if (std::towlower(*it) == searchChar)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
lastWasSpace = *it == L' ';
|
||||||
|
++it;
|
||||||
|
lastWasMatch = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Advance the iterator by one character so that we don't
|
||||||
|
// end up on the same character in the next iteration.
|
||||||
|
++it;
|
||||||
|
|
||||||
|
totalWeight += 1;
|
||||||
|
totalWeight += lastWasSpace ? 1 : 0;
|
||||||
|
totalWeight += (lastWasMatch) ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return totalWeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CommandPalette::SetDispatch(const winrt::TerminalApp::ShortcutActionDispatch& dispatch)
|
||||||
|
{
|
||||||
|
_dispatch = dispatch;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Method Description:
|
||||||
|
// - Dismiss the command palette. This will:
|
||||||
|
// * select all the current text in the input box
|
||||||
|
// * set our visibility to Hidden
|
||||||
|
// * raise our Closed event, so the page can return focus to the active Terminal
|
||||||
|
// Arguments:
|
||||||
|
// - <none>
|
||||||
|
// Return Value:
|
||||||
|
// - <none>
|
||||||
|
void CommandPalette::_close()
|
||||||
|
{
|
||||||
|
Visibility(Visibility::Collapsed);
|
||||||
|
|
||||||
|
// Clear the text box each time we close the dialog. This is consistent with VsCode.
|
||||||
|
_searchBox().Text(L"");
|
||||||
|
}
|
||||||
|
|
||||||
|
void CommandPalette::_checkMode()
|
||||||
|
{
|
||||||
|
_mode = PaletteMode::ActionMode;
|
||||||
|
|
||||||
|
auto inputText = _searchBox().Text();
|
||||||
|
if (inputText.size() > 0)
|
||||||
|
{
|
||||||
|
if (inputText[0] == L'>')
|
||||||
|
{
|
||||||
|
_mode = PaletteMode::CommandlineMode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CommandPalette::_dispatchAction()
|
||||||
|
{
|
||||||
|
// Action Mode: Dispatch the action of the selected command.
|
||||||
|
|
||||||
|
if (const auto selectedItem = _filteredActionsView().SelectedItem())
|
||||||
|
{
|
||||||
|
if (const auto data = selectedItem.try_as<Command>())
|
||||||
|
{
|
||||||
|
const auto actionAndArgs = data.Action();
|
||||||
|
_dispatch.DoAction(actionAndArgs);
|
||||||
|
_close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CommandPalette::_dispatchCommandline()
|
||||||
|
{
|
||||||
|
const auto inputText = _searchBox().Text();
|
||||||
|
const std::wstring input{ _searchBox().Text() };
|
||||||
|
const auto rawCmdline{ input.substr(1) };
|
||||||
|
|
||||||
|
// Trim leading whitespace
|
||||||
|
const auto firstNonSpace = rawCmdline.find_first_not_of(L" ");
|
||||||
|
if (firstNonSpace == std::wstring::npos)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
winrt::hstring cmdline{ rawCmdline.substr(firstNonSpace) };
|
||||||
|
|
||||||
|
// Build the NewTab action from the values we've parsed on the commandline.
|
||||||
|
auto executeActionAndArgs = winrt::make_self<implementation::ActionAndArgs>();
|
||||||
|
executeActionAndArgs->Action(ShortcutAction::ExecuteCommandline);
|
||||||
|
auto args = winrt::make_self<implementation::ExecuteCommandlineArgs>();
|
||||||
|
args->Commandline(cmdline);
|
||||||
|
executeActionAndArgs->Args(*args);
|
||||||
|
|
||||||
|
if (_dispatch.DoAction(*executeActionAndArgs))
|
||||||
|
{
|
||||||
|
_close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
61
src/cascadia/TerminalApp/CommandPalette.h
Normal file
61
src/cascadia/TerminalApp/CommandPalette.h
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
// Copyright (c) Microsoft Corporation.
|
||||||
|
// Licensed under the MIT license.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "CommandPalette.g.h"
|
||||||
|
#include "../../cascadia/inc/cppwinrt_utils.h"
|
||||||
|
|
||||||
|
namespace winrt::TerminalApp::implementation
|
||||||
|
{
|
||||||
|
enum class PaletteMode : uint32_t
|
||||||
|
{
|
||||||
|
ActionMode = 0,
|
||||||
|
CommandlineMode
|
||||||
|
};
|
||||||
|
|
||||||
|
struct CommandPalette : CommandPaletteT<CommandPalette>
|
||||||
|
{
|
||||||
|
CommandPalette();
|
||||||
|
|
||||||
|
Windows::Foundation::Collections::IObservableVector<TerminalApp::Command> FilteredActions();
|
||||||
|
void SetActions(Windows::Foundation::Collections::IVector<TerminalApp::Command> const& actions);
|
||||||
|
|
||||||
|
void SetDispatch(const winrt::TerminalApp::ShortcutActionDispatch& dispatch);
|
||||||
|
|
||||||
|
private:
|
||||||
|
friend struct CommandPaletteT<CommandPalette>; // for Xaml to bind events
|
||||||
|
|
||||||
|
Windows::Foundation::Collections::IObservableVector<TerminalApp::Command> _filteredActions{ nullptr };
|
||||||
|
Windows::Foundation::Collections::IVector<TerminalApp::Command> _allActions{ nullptr };
|
||||||
|
winrt::TerminalApp::ShortcutActionDispatch _dispatch;
|
||||||
|
|
||||||
|
PaletteMode _mode{ PaletteMode::ActionMode };
|
||||||
|
|
||||||
|
void _filterTextChanged(Windows::Foundation::IInspectable const& sender,
|
||||||
|
Windows::UI::Xaml::RoutedEventArgs const& args);
|
||||||
|
void _keyDownHandler(Windows::Foundation::IInspectable const& sender,
|
||||||
|
Windows::UI::Xaml::Input::KeyRoutedEventArgs const& e);
|
||||||
|
|
||||||
|
void _rootPointerPressed(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::Input::PointerRoutedEventArgs const& e);
|
||||||
|
void _backdropPointerPressed(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::Input::PointerRoutedEventArgs const& e);
|
||||||
|
|
||||||
|
void _listItemClicked(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::Controls::ItemClickEventArgs const& e);
|
||||||
|
|
||||||
|
void _selectNextItem(const bool moveDown);
|
||||||
|
|
||||||
|
void _checkMode();
|
||||||
|
|
||||||
|
void _updateFilteredActions();
|
||||||
|
static int _getWeight(const winrt::hstring& searchText, const winrt::hstring& name);
|
||||||
|
void _close();
|
||||||
|
|
||||||
|
void _dispatchAction();
|
||||||
|
void _dispatchCommandline();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace winrt::TerminalApp::factory_implementation
|
||||||
|
{
|
||||||
|
BASIC_FACTORY(CommandPalette);
|
||||||
|
}
|
||||||
18
src/cascadia/TerminalApp/CommandPalette.idl
Normal file
18
src/cascadia/TerminalApp/CommandPalette.idl
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
// Copyright (c) Microsoft Corporation.
|
||||||
|
// Licensed under the MIT license.
|
||||||
|
|
||||||
|
import "../Command.idl";
|
||||||
|
|
||||||
|
namespace TerminalApp
|
||||||
|
{
|
||||||
|
[default_interface] runtimeclass CommandPalette : Windows.UI.Xaml.Controls.Grid
|
||||||
|
{
|
||||||
|
CommandPalette();
|
||||||
|
|
||||||
|
Windows.Foundation.Collections.IObservableVector<Command> FilteredActions { get; };
|
||||||
|
|
||||||
|
void SetActions(Windows.Foundation.Collections.IVector<Command> actions);
|
||||||
|
|
||||||
|
void SetDispatch(ShortcutActionDispatch dispatch);
|
||||||
|
}
|
||||||
|
}
|
||||||
204
src/cascadia/TerminalApp/CommandPalette.xaml
Normal file
204
src/cascadia/TerminalApp/CommandPalette.xaml
Normal file
@@ -0,0 +1,204 @@
|
|||||||
|
<!-- Copyright (c) Microsoft Corporation. All rights reserved. Licensed under
|
||||||
|
the MIT License. See LICENSE in the project root for license information. -->
|
||||||
|
<Grid
|
||||||
|
x:Class="TerminalApp.CommandPalette"
|
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:local="using:TerminalApp"
|
||||||
|
xmlns:mux="using:Microsoft.UI.Xaml.Controls"
|
||||||
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
xmlns:Windows10version1903="http://schemas.microsoft.com/winfx/2006/xaml/presentation?IsApiContractPresent(Windows.Foundation.UniversalApiContract, 8)"
|
||||||
|
PointerPressed="_rootPointerPressed"
|
||||||
|
mc:Ignorable="d">
|
||||||
|
|
||||||
|
<Grid.Resources>
|
||||||
|
<ResourceDictionary>
|
||||||
|
|
||||||
|
<!-- ThemeShadow is only on 18362. This "Windows10version1903" bit
|
||||||
|
adds it conditionally -->
|
||||||
|
<Windows10version1903:ThemeShadow x:Name="CommandPaletteShadow" />
|
||||||
|
|
||||||
|
<ResourceDictionary.ThemeDictionaries>
|
||||||
|
<ResourceDictionary x:Key="Dark">
|
||||||
|
<Style x:Key="CommandPaletteBackground" TargetType="Grid">
|
||||||
|
<Setter Property="Background" Value="#333333" />
|
||||||
|
</Style>
|
||||||
|
<!-- 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"/>
|
||||||
|
|
||||||
|
</ResourceDictionary>
|
||||||
|
<ResourceDictionary x:Key="Light">
|
||||||
|
<Style x:Key="CommandPaletteBackground" TargetType="Grid">
|
||||||
|
<Setter Property="Background" Value="#CCCCCC" />
|
||||||
|
</Style>
|
||||||
|
<!-- 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"/>
|
||||||
|
|
||||||
|
</ResourceDictionary>
|
||||||
|
<ResourceDictionary x:Key="HighContrast">
|
||||||
|
<Style x:Key="CommandPaletteBackground" TargetType="Grid">
|
||||||
|
<Setter Property="Background" Value="{ThemeResource SystemColorWindowColor}" />
|
||||||
|
</Style>
|
||||||
|
</ResourceDictionary>
|
||||||
|
</ResourceDictionary.ThemeDictionaries>
|
||||||
|
</ResourceDictionary>
|
||||||
|
|
||||||
|
</Grid.Resources>
|
||||||
|
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="2*" />
|
||||||
|
<ColumnDefinition Width="6*" />
|
||||||
|
<ColumnDefinition Width="2*" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="8*"/>
|
||||||
|
<RowDefinition Height="2*"/>
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
|
||||||
|
<!-- Setting the row/col span of this shadow backdrop is a bit of a hack. In
|
||||||
|
order to receive pointer events, an element needs to be _not_ transparent.
|
||||||
|
However, we want to be able to eat all the clicks outside the immediate
|
||||||
|
bounds of the command palette, and we don't want a semi-transparent overlay
|
||||||
|
over all of the UI. Fortunately, if we make this _shadowBackdrop the size of
|
||||||
|
the entire page, then it can be mostly transparent, and cause the root grid
|
||||||
|
to receive clicks _anywhere_ in its bounds. -->
|
||||||
|
|
||||||
|
<Grid
|
||||||
|
x:Name="_shadowBackdrop"
|
||||||
|
Background="Transparent"
|
||||||
|
Grid.Column="0"
|
||||||
|
Grid.Row="0"
|
||||||
|
Grid.ColumnSpan="3"
|
||||||
|
Grid.RowSpan="2"
|
||||||
|
HorizontalAlignment="Stretch"
|
||||||
|
VerticalAlignment="Stretch">
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<Grid
|
||||||
|
x:Name="_backdrop"
|
||||||
|
Style="{ThemeResource CommandPaletteBackground}"
|
||||||
|
CornerRadius="{ThemeResource ControlCornerRadius}"
|
||||||
|
PointerPressed="_backdropPointerPressed"
|
||||||
|
Margin="8"
|
||||||
|
Grid.Column="1"
|
||||||
|
Grid.Row="0"
|
||||||
|
Windows10version1903:Shadow="{StaticResource CommandPaletteShadow}"
|
||||||
|
HorizontalAlignment="Stretch"
|
||||||
|
VerticalAlignment="Top">
|
||||||
|
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="Auto"/>
|
||||||
|
<RowDefinition Height="Auto"/>
|
||||||
|
<RowDefinition Height="*"/>
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
|
||||||
|
<TextBox
|
||||||
|
Grid.Row="0"
|
||||||
|
x:Uid="CommandPalette_SearchBox"
|
||||||
|
x:Name="_searchBox"
|
||||||
|
Margin="8"
|
||||||
|
IsSpellCheckEnabled="False"
|
||||||
|
TextChanged="_filterTextChanged"
|
||||||
|
KeyDown="_keyDownHandler"
|
||||||
|
Text="">
|
||||||
|
</TextBox>
|
||||||
|
|
||||||
|
<TextBlock
|
||||||
|
Padding="16"
|
||||||
|
x:Name="_noMatchesText"
|
||||||
|
x:Uid="CommandPalette_NoMatchesText"
|
||||||
|
FontStyle="Italic"
|
||||||
|
Visibility="Collapsed"
|
||||||
|
Grid.Row="1">
|
||||||
|
</TextBlock>
|
||||||
|
|
||||||
|
<ListView
|
||||||
|
Grid.Row="2"
|
||||||
|
x:Name="_filteredActionsView"
|
||||||
|
HorizontalAlignment="Stretch"
|
||||||
|
VerticalAlignment="Stretch"
|
||||||
|
SelectionMode="Single"
|
||||||
|
CanReorderItems="False"
|
||||||
|
AllowDrop="False"
|
||||||
|
IsItemClickEnabled="True"
|
||||||
|
ItemClick="_listItemClicked"
|
||||||
|
ItemsSource="{x:Bind FilteredActions}">
|
||||||
|
|
||||||
|
<ItemsControl.ItemTemplate >
|
||||||
|
<DataTemplate x:DataType="local:Command">
|
||||||
|
|
||||||
|
<!-- This HorizontalContentAlignment="Stretch" is important
|
||||||
|
to make sure it takes the entire width of the line -->
|
||||||
|
<ListViewItem HorizontalContentAlignment="Stretch"
|
||||||
|
AutomationProperties.Name="{x:Bind Name, Mode=OneWay}"
|
||||||
|
AutomationProperties.AcceleratorKey="{x:Bind KeyChordText, Mode=OneWay}">
|
||||||
|
|
||||||
|
<Grid HorizontalAlignment="Stretch" >
|
||||||
|
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="16"/>
|
||||||
|
<ColumnDefinition Width="Auto"/>
|
||||||
|
<ColumnDefinition Width="*"/>
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
|
||||||
|
<!-- TODO GH#6644: Add Icon to command palette entries, in column 0 -->
|
||||||
|
|
||||||
|
<TextBlock Grid.Column="1"
|
||||||
|
HorizontalAlignment="Left"
|
||||||
|
Text="{x:Bind Name, Mode=OneWay}" />
|
||||||
|
|
||||||
|
<Border
|
||||||
|
Grid.Column="2"
|
||||||
|
BorderBrush="{ThemeResource SystemControlForegroundBaseMediumBrush}"
|
||||||
|
Background="{ThemeResource SystemControlForegroundBaseLowBrush}"
|
||||||
|
BorderThickness="1"
|
||||||
|
CornerRadius="1"
|
||||||
|
Padding="2,0,2,0"
|
||||||
|
HorizontalAlignment="Right"
|
||||||
|
VerticalAlignment="Center">
|
||||||
|
|
||||||
|
<TextBlock
|
||||||
|
Foreground="{ThemeResource SystemControlForegroundBaseMediumBrush}"
|
||||||
|
FontSize="12"
|
||||||
|
Text="{x:Bind KeyChordText, Mode=OneWay}" />
|
||||||
|
</Border>
|
||||||
|
|
||||||
|
</Grid>
|
||||||
|
</ListViewItem>
|
||||||
|
</DataTemplate>
|
||||||
|
</ItemsControl.ItemTemplate>
|
||||||
|
</ListView>
|
||||||
|
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
|
||||||
|
</Grid>
|
||||||
@@ -7,7 +7,6 @@
|
|||||||
#include "../../inc/DefaultSettings.h"
|
#include "../../inc/DefaultSettings.h"
|
||||||
#include "Utils.h"
|
#include "Utils.h"
|
||||||
#include "JsonUtils.h"
|
#include "JsonUtils.h"
|
||||||
#include <sstream>
|
|
||||||
|
|
||||||
using namespace TerminalApp;
|
using namespace TerminalApp;
|
||||||
using namespace winrt::Microsoft::Terminal::Settings;
|
using namespace winrt::Microsoft::Terminal::Settings;
|
||||||
@@ -17,7 +16,8 @@ using namespace winrt::Windows::UI::Xaml;
|
|||||||
using namespace ::Microsoft::Console;
|
using namespace ::Microsoft::Console;
|
||||||
using namespace winrt::Microsoft::UI::Xaml::Controls;
|
using namespace winrt::Microsoft::UI::Xaml::Controls;
|
||||||
|
|
||||||
static constexpr std::string_view KeybindingsKey{ "keybindings" };
|
static constexpr std::string_view LegacyKeybindingsKey{ "keybindings" };
|
||||||
|
static constexpr std::string_view BindingsKey{ "bindings" };
|
||||||
static constexpr std::string_view DefaultProfileKey{ "defaultProfile" };
|
static constexpr std::string_view DefaultProfileKey{ "defaultProfile" };
|
||||||
static constexpr std::string_view AlwaysShowTabsKey{ "alwaysShowTabs" };
|
static constexpr std::string_view AlwaysShowTabsKey{ "alwaysShowTabs" };
|
||||||
static constexpr std::string_view InitialRowsKey{ "initialRows" };
|
static constexpr std::string_view InitialRowsKey{ "initialRows" };
|
||||||
@@ -205,18 +205,6 @@ void GlobalAppSettings::LayerJson(const Json::Value& json)
|
|||||||
_TabWidthMode = _ParseTabWidthMode(GetWstringFromJson(tabWidthMode));
|
_TabWidthMode = _ParseTabWidthMode(GetWstringFromJson(tabWidthMode));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (auto keybindings{ json[JsonKey(KeybindingsKey)] })
|
|
||||||
{
|
|
||||||
auto warnings = _keybindings->LayerJson(keybindings);
|
|
||||||
// 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. If there were any
|
|
||||||
// warnings generated from parsing these keybindings, add them to our
|
|
||||||
// list of warnings.
|
|
||||||
_keybindingsWarnings.insert(_keybindingsWarnings.end(), warnings.begin(), warnings.end());
|
|
||||||
}
|
|
||||||
|
|
||||||
JsonUtils::GetBool(json, SnapToGridOnResizeKey, _SnapToGridOnResize);
|
JsonUtils::GetBool(json, SnapToGridOnResizeKey, _SnapToGridOnResize);
|
||||||
|
|
||||||
JsonUtils::GetBool(json, ForceFullRepaintRenderingKey, _ForceFullRepaintRendering);
|
JsonUtils::GetBool(json, ForceFullRepaintRenderingKey, _ForceFullRepaintRendering);
|
||||||
@@ -228,6 +216,31 @@ void GlobalAppSettings::LayerJson(const Json::Value& json)
|
|||||||
JsonUtils::GetBool(json, DebugFeaturesKey, _DebugFeaturesEnabled);
|
JsonUtils::GetBool(json, DebugFeaturesKey, _DebugFeaturesEnabled);
|
||||||
|
|
||||||
JsonUtils::GetBool(json, EnableStartupTaskKey, _StartOnUserLogin);
|
JsonUtils::GetBool(json, EnableStartupTaskKey, _StartOnUserLogin);
|
||||||
|
|
||||||
|
// This is a helper lambda to get the keybindings and commands out of both
|
||||||
|
// and array of objects. We'll use this twice, once on the legacy
|
||||||
|
// `keybindings` key, and again on the newer `bindings` key.
|
||||||
|
auto parseBindings = [this, &json](auto jsonKey) {
|
||||||
|
if (auto bindings{ json[JsonKey(jsonKey)] })
|
||||||
|
{
|
||||||
|
auto warnings = _keybindings->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
|
||||||
|
// Validate settings phase, so we'll collect them now. If there were any
|
||||||
|
// 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 = winrt::TerminalApp::implementation::Command::LayerJson(_commands, bindings);
|
||||||
|
// It's possible that the user provided commands have some warnings
|
||||||
|
// in them, similar to the keybindings.
|
||||||
|
_keybindingsWarnings.insert(_keybindingsWarnings.end(), warnings.begin(), warnings.end());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
parseBindings(LegacyKeybindingsKey);
|
||||||
|
parseBindings(BindingsKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Method Description:
|
// Method Description:
|
||||||
@@ -365,3 +378,8 @@ std::vector<TerminalApp::SettingsLoadWarnings> GlobalAppSettings::GetKeybindings
|
|||||||
{
|
{
|
||||||
return _keybindingsWarnings;
|
return _keybindingsWarnings;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::unordered_map<winrt::hstring, winrt::TerminalApp::Command>& GlobalAppSettings::GetCommands() const noexcept
|
||||||
|
{
|
||||||
|
return _commands;
|
||||||
|
}
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ Author(s):
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "AppKeyBindings.h"
|
#include "AppKeyBindings.h"
|
||||||
#include "ColorScheme.h"
|
#include "ColorScheme.h"
|
||||||
|
#include "Command.h"
|
||||||
|
|
||||||
// fwdecl unittest classes
|
// fwdecl unittest classes
|
||||||
namespace TerminalAppLocalTests
|
namespace TerminalAppLocalTests
|
||||||
@@ -54,6 +55,8 @@ public:
|
|||||||
|
|
||||||
std::vector<TerminalApp::SettingsLoadWarnings> GetKeybindingsWarnings() const;
|
std::vector<TerminalApp::SettingsLoadWarnings> GetKeybindingsWarnings() const;
|
||||||
|
|
||||||
|
const std::unordered_map<winrt::hstring, winrt::TerminalApp::Command>& GetCommands() const noexcept;
|
||||||
|
|
||||||
// These are implemented manually to handle the string/GUID exchange
|
// These are implemented manually to handle the string/GUID exchange
|
||||||
// by higher layers in the app.
|
// by higher layers in the app.
|
||||||
void DefaultProfile(const GUID defaultProfile) noexcept;
|
void DefaultProfile(const GUID defaultProfile) noexcept;
|
||||||
@@ -79,7 +82,6 @@ public:
|
|||||||
GETSET_PROPERTY(bool, SoftwareRendering, false);
|
GETSET_PROPERTY(bool, SoftwareRendering, false);
|
||||||
GETSET_PROPERTY(bool, ForceVTInput, false);
|
GETSET_PROPERTY(bool, ForceVTInput, false);
|
||||||
GETSET_PROPERTY(bool, DebugFeaturesEnabled); // default value set in constructor
|
GETSET_PROPERTY(bool, DebugFeaturesEnabled); // default value set in constructor
|
||||||
|
|
||||||
GETSET_PROPERTY(bool, StartOnUserLogin, false);
|
GETSET_PROPERTY(bool, StartOnUserLogin, false);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -90,6 +92,7 @@ private:
|
|||||||
std::vector<::TerminalApp::SettingsLoadWarnings> _keybindingsWarnings;
|
std::vector<::TerminalApp::SettingsLoadWarnings> _keybindingsWarnings;
|
||||||
|
|
||||||
std::unordered_map<std::wstring, ColorScheme> _colorSchemes;
|
std::unordered_map<std::wstring, ColorScheme> _colorSchemes;
|
||||||
|
std::unordered_map<winrt::hstring, winrt::TerminalApp::Command> _commands;
|
||||||
|
|
||||||
static winrt::Windows::UI::Xaml::ElementTheme _ParseTheme(const std::wstring& themeString) noexcept;
|
static winrt::Windows::UI::Xaml::ElementTheme _ParseTheme(const std::wstring& themeString) noexcept;
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
#include "CascadiaSettings.h"
|
#include "CascadiaSettings.h"
|
||||||
|
|
||||||
using namespace winrt::Windows::Foundation;
|
using namespace winrt::Windows::Foundation;
|
||||||
|
using namespace winrt::Windows::Graphics::Display;
|
||||||
using namespace winrt::Windows::UI;
|
using namespace winrt::Windows::UI;
|
||||||
using namespace winrt::Windows::UI::Xaml;
|
using namespace winrt::Windows::UI::Xaml;
|
||||||
using namespace winrt::Windows::UI::Core;
|
using namespace winrt::Windows::UI::Core;
|
||||||
@@ -921,6 +922,102 @@ bool Pane::CanSplit(SplitState splitType)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Method Description:
|
||||||
|
// - This is a helper to determine if a given Pane can be split, but without
|
||||||
|
// using the ActualWidth() and ActualHeight() methods. This is used during
|
||||||
|
// processing of many "split-pane" commands, which could happen _before_ we've
|
||||||
|
// laid out a Pane for the first time. When this happens, the Pane's don't
|
||||||
|
// have an actual size yet. However, we'd still like to figure out if the pane
|
||||||
|
// could be split, once they're all laid out.
|
||||||
|
// - This method assumes that the Pane we're attempting to split is `target`,
|
||||||
|
// and this method should be called on the root of a tree of Panes.
|
||||||
|
// - We'll walk down the tree attempting to find `target`. As we traverse the
|
||||||
|
// tree, we'll reduce the size passed to each subsequent recursive call. The
|
||||||
|
// size passed to this method represents how much space this Pane _will_ have
|
||||||
|
// to use.
|
||||||
|
// * If this pane is a leaf, and it's the pane we're looking for, use the
|
||||||
|
// available space to calculate which direction to split in.
|
||||||
|
// * If this pane is _any other leaf_, then just return nullopt, to indicate
|
||||||
|
// that the `target` Pane is not down this branch.
|
||||||
|
// * If this pane is a parent, calculate how much space our children will be
|
||||||
|
// able to use, and recurse into them.
|
||||||
|
// Arguments:
|
||||||
|
// - target: The Pane we're attempting to split.
|
||||||
|
// - splitType: The direction we're attempting to split in.
|
||||||
|
// - availableSpace: The theoretical space that's available for this pane to be able to split.
|
||||||
|
// Return Value:
|
||||||
|
// - nullopt if `target` is not this pane or a child of this pane, otherwise
|
||||||
|
// true iff we could split this pane, given `availableSpace`
|
||||||
|
// Note:
|
||||||
|
// - This method is highly similar to Pane::PreCalculateAutoSplit
|
||||||
|
std::optional<bool> Pane::PreCalculateCanSplit(const std::shared_ptr<Pane> target,
|
||||||
|
SplitState splitType,
|
||||||
|
const winrt::Windows::Foundation::Size availableSpace) const
|
||||||
|
{
|
||||||
|
if (_IsLeaf())
|
||||||
|
{
|
||||||
|
if (target.get() == this)
|
||||||
|
{
|
||||||
|
//If this pane is a leaf, and it's the pane we're looking for, use
|
||||||
|
//the available space to calculate which direction to split in.
|
||||||
|
const Size minSize = _GetMinSize();
|
||||||
|
|
||||||
|
if (splitType == SplitState::None)
|
||||||
|
{
|
||||||
|
return { false };
|
||||||
|
}
|
||||||
|
|
||||||
|
if (splitType == SplitState::Vertical)
|
||||||
|
{
|
||||||
|
const auto widthMinusSeparator = availableSpace.Width - CombinedPaneBorderSize;
|
||||||
|
const auto newWidth = widthMinusSeparator * Half;
|
||||||
|
|
||||||
|
return { newWidth > minSize.Width };
|
||||||
|
}
|
||||||
|
|
||||||
|
if (splitType == SplitState::Horizontal)
|
||||||
|
{
|
||||||
|
const auto heightMinusSeparator = availableSpace.Height - CombinedPaneBorderSize;
|
||||||
|
const auto newHeight = heightMinusSeparator * Half;
|
||||||
|
|
||||||
|
return { newHeight > minSize.Height };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// If this pane is _any other leaf_, then just return nullopt, to
|
||||||
|
// indicate that the `target` Pane is not down this branch.
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// If this pane is a parent, calculate how much space our children will
|
||||||
|
// be able to use, and recurse into them.
|
||||||
|
|
||||||
|
const bool isVerticalSplit = _splitState == SplitState::Vertical;
|
||||||
|
const float firstWidth = isVerticalSplit ?
|
||||||
|
(availableSpace.Width * _desiredSplitPosition) - PaneBorderSize :
|
||||||
|
availableSpace.Width;
|
||||||
|
const float secondWidth = isVerticalSplit ?
|
||||||
|
(availableSpace.Width - firstWidth) - PaneBorderSize :
|
||||||
|
availableSpace.Width;
|
||||||
|
const float firstHeight = !isVerticalSplit ?
|
||||||
|
(availableSpace.Height * _desiredSplitPosition) - PaneBorderSize :
|
||||||
|
availableSpace.Height;
|
||||||
|
const float secondHeight = !isVerticalSplit ?
|
||||||
|
(availableSpace.Height - firstHeight) - PaneBorderSize :
|
||||||
|
availableSpace.Height;
|
||||||
|
|
||||||
|
const auto firstResult = _firstChild->PreCalculateCanSplit(target, splitType, { firstWidth, firstHeight });
|
||||||
|
return firstResult.has_value() ? firstResult : _secondChild->PreCalculateCanSplit(target, splitType, { secondWidth, secondHeight });
|
||||||
|
}
|
||||||
|
|
||||||
|
// We should not possibly be getting here - both the above branches should
|
||||||
|
// return a value.
|
||||||
|
FAIL_FAST();
|
||||||
|
}
|
||||||
|
|
||||||
// Method Description:
|
// Method Description:
|
||||||
// - Split the focused pane in our tree of panes, and place the given
|
// - Split the focused pane in our tree of panes, and place the given
|
||||||
// TermControl into the newly created pane. If we're the focused pane, then
|
// TermControl into the newly created pane. If we're the focused pane, then
|
||||||
|
|||||||
@@ -64,7 +64,9 @@ public:
|
|||||||
const winrt::Microsoft::Terminal::TerminalControl::TermControl& control);
|
const winrt::Microsoft::Terminal::TerminalControl::TermControl& control);
|
||||||
float CalcSnappedDimension(const bool widthOrHeight, const float dimension) const;
|
float CalcSnappedDimension(const bool widthOrHeight, const float dimension) const;
|
||||||
std::optional<winrt::TerminalApp::SplitState> PreCalculateAutoSplit(const std::shared_ptr<Pane> target, const winrt::Windows::Foundation::Size parentSize) const;
|
std::optional<winrt::TerminalApp::SplitState> PreCalculateAutoSplit(const std::shared_ptr<Pane> target, const winrt::Windows::Foundation::Size parentSize) const;
|
||||||
|
std::optional<bool> PreCalculateCanSplit(const std::shared_ptr<Pane> target,
|
||||||
|
winrt::TerminalApp::SplitState splitType,
|
||||||
|
const winrt::Windows::Foundation::Size availableSpace) const;
|
||||||
void Shutdown();
|
void Shutdown();
|
||||||
void Close();
|
void Close();
|
||||||
|
|
||||||
|
|||||||
@@ -347,4 +347,158 @@
|
|||||||
<value>Command Prompt</value>
|
<value>Command Prompt</value>
|
||||||
<comment>This is the name of "Command Prompt", as localized in Windows. The localization here should match the one in the Windows product for "Command Prompt"</comment>
|
<comment>This is the name of "Command Prompt", as localized in Windows. The localization here should match the one in the Windows product for "Command Prompt"</comment>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="CommandPalette_SearchBox.PlaceholderText" xml:space="preserve">
|
||||||
|
<value>Type a command name...</value>
|
||||||
|
</data>
|
||||||
|
<data name="CommandPalette_NoMatchesText.Text" xml:space="preserve">
|
||||||
|
<value>No matching commands</value>
|
||||||
|
</data>
|
||||||
|
<data name="CloseWindowCommandKey" xml:space="preserve">
|
||||||
|
<value>Close window</value>
|
||||||
|
</data>
|
||||||
|
<data name="ToggleFullscreenCommandKey" xml:space="preserve">
|
||||||
|
<value>Toggle fullscreen</value>
|
||||||
|
</data>
|
||||||
|
<data name="OpenNewTabDropdownCommandKey" xml:space="preserve">
|
||||||
|
<value>Open new tab dropdown</value>
|
||||||
|
</data>
|
||||||
|
<data name="OpenSettingsCommandKey" xml:space="preserve">
|
||||||
|
<value>Open settings file</value>
|
||||||
|
</data>
|
||||||
|
<data name="OpenDefaultSettingsCommandKey" xml:space="preserve">
|
||||||
|
<value>Open default settings file</value>
|
||||||
|
</data>
|
||||||
|
<data name="OpenBothSettingsFilesCommandKey" xml:space="preserve">
|
||||||
|
<value>Open both settings and default settings files</value>
|
||||||
|
</data>
|
||||||
|
<data name="FindCommandKey" xml:space="preserve">
|
||||||
|
<value>Find</value>
|
||||||
|
</data>
|
||||||
|
<data name="ResizePaneCommandKey" xml:space="preserve">
|
||||||
|
<value>Resize pane</value>
|
||||||
|
</data>
|
||||||
|
<data name="MoveFocusCommandKey" xml:space="preserve">
|
||||||
|
<value>Move focus</value>
|
||||||
|
</data>
|
||||||
|
<data name="MoveFocusWithArgCommandKey" xml:space="preserve">
|
||||||
|
<value>Move focus {0}</value>
|
||||||
|
<comment>{0} will be replaced with one of the four directions "DirectionLeft", "DirectionRight", "DirectionUp", or "DirectionDown"</comment>
|
||||||
|
</data>
|
||||||
|
<data name="ResizePaneWithArgCommandKey" xml:space="preserve">
|
||||||
|
<value>Resize pane {0}</value>
|
||||||
|
<comment>{0} will be replaced with one of the four directions "DirectionLeft", "DirectionRight", "DirectionUp", or "DirectionDown"</comment>
|
||||||
|
</data>
|
||||||
|
<data name="DirectionLeft" xml:space="preserve">
|
||||||
|
<value>left</value>
|
||||||
|
</data>
|
||||||
|
<data name="DirectionRight" xml:space="preserve">
|
||||||
|
<value>right</value>
|
||||||
|
</data>
|
||||||
|
<data name="DirectionUp" xml:space="preserve">
|
||||||
|
<value>up</value>
|
||||||
|
</data>
|
||||||
|
<data name="DirectionDown" xml:space="preserve">
|
||||||
|
<value>down</value>
|
||||||
|
</data>
|
||||||
|
<data name="SwitchToTabCommandKey" xml:space="preserve">
|
||||||
|
<value>Switch to tab</value>
|
||||||
|
</data>
|
||||||
|
<data name="NewTabCommandKey" xml:space="preserve">
|
||||||
|
<value>New tab</value>
|
||||||
|
</data>
|
||||||
|
<data name="SplitPaneCommandKey" xml:space="preserve">
|
||||||
|
<value>Split pane</value>
|
||||||
|
</data>
|
||||||
|
<data name="NewWindowCommandKey" xml:space="preserve">
|
||||||
|
<value>New window</value>
|
||||||
|
</data>
|
||||||
|
<data name="DuplicateTabCommandKey" xml:space="preserve">
|
||||||
|
<value>Duplicate tab</value>
|
||||||
|
</data>
|
||||||
|
<data name="DuplicatePaneCommandKey" xml:space="preserve">
|
||||||
|
<value>Duplicate pane</value>
|
||||||
|
</data>
|
||||||
|
<data name="NextTabCommandKey" xml:space="preserve">
|
||||||
|
<value>Next tab</value>
|
||||||
|
</data>
|
||||||
|
<data name="PrevTabCommandKey" xml:space="preserve">
|
||||||
|
<value>Previous tab</value>
|
||||||
|
</data>
|
||||||
|
<data name="ClosePaneCommandKey" xml:space="preserve">
|
||||||
|
<value>Close pane</value>
|
||||||
|
</data>
|
||||||
|
<data name="CloseTabCommandKey" xml:space="preserve">
|
||||||
|
<value>Close tab</value>
|
||||||
|
</data>
|
||||||
|
<data name="SplitHorizontalCommandKey" xml:space="preserve">
|
||||||
|
<value>Split pane horizontally</value>
|
||||||
|
</data>
|
||||||
|
<data name="SplitVerticalCommandKey" xml:space="preserve">
|
||||||
|
<value>Split pane vertically</value>
|
||||||
|
</data>
|
||||||
|
<data name="CopyTextCommandKey" xml:space="preserve">
|
||||||
|
<value>Copy text</value>
|
||||||
|
</data>
|
||||||
|
<data name="CopyTextAsSingleLineCommandKey" xml:space="preserve">
|
||||||
|
<value>Copy text as a single line</value>
|
||||||
|
</data>
|
||||||
|
<data name="PasteTextCommandKey" xml:space="preserve">
|
||||||
|
<value>Paste</value>
|
||||||
|
</data>
|
||||||
|
<data name="ScrollDownCommandKey" xml:space="preserve">
|
||||||
|
<value>Scroll down one line</value>
|
||||||
|
</data>
|
||||||
|
<data name="ScrollDownPageCommandKey" xml:space="preserve">
|
||||||
|
<value>Scroll down one page</value>
|
||||||
|
</data>
|
||||||
|
<data name="ScrollUpCommandKey" xml:space="preserve">
|
||||||
|
<value>Scroll up one line</value>
|
||||||
|
</data>
|
||||||
|
<data name="ScrollUpPageCommandKey" xml:space="preserve">
|
||||||
|
<value>Scroll up one page</value>
|
||||||
|
</data>
|
||||||
|
<data name="AdjustFontSizeCommandKey" xml:space="preserve">
|
||||||
|
<value>Adjust font size</value>
|
||||||
|
</data>
|
||||||
|
<data name="IncreaseFontSizeCommandKey" xml:space="preserve">
|
||||||
|
<value>Increase font size</value>
|
||||||
|
</data>
|
||||||
|
<data name="DecreaseFontSizeCommandKey" xml:space="preserve">
|
||||||
|
<value>Decrease font size</value>
|
||||||
|
</data>
|
||||||
|
<data name="IncreaseFontSizeWithAmountCommandKey" xml:space="preserve">
|
||||||
|
<value>Increase font size, amount: {0}</value>
|
||||||
|
<comment>{0} will be replaced with a positive number</comment>
|
||||||
|
</data>
|
||||||
|
<data name="DecreaseFontSizeWithAmountCommandKey" xml:space="preserve">
|
||||||
|
<value>Decrease font size, amount: {0}</value>
|
||||||
|
<comment>{0} will be replaced with a positive number</comment>
|
||||||
|
</data>
|
||||||
|
<data name="ResetFontSizeCommandKey" xml:space="preserve">
|
||||||
|
<value>Reset font size</value>
|
||||||
|
</data>
|
||||||
|
<data name="ToggleCommandPaletteCommandKey" xml:space="preserve">
|
||||||
|
<value>Toggle command palette</value>
|
||||||
|
</data>
|
||||||
|
<data name="ExecuteCommandlineCommandKey" xml:space="preserve">
|
||||||
|
<value>Run the commandline "{0}" in this window</value>
|
||||||
|
<comment>{0} will be replaced with a user-provided commandline</comment>
|
||||||
|
</data>
|
||||||
|
<data name="SetTabColorCommandKey" xml:space="preserve">
|
||||||
|
<value>Set tab color to {0}</value>
|
||||||
|
<comment>{0} will be replaced with a color, displayed in hexadecimal (#RRGGBB) notation.</comment>
|
||||||
|
</data>
|
||||||
|
<data name="ResetTabColorCommandKey" xml:space="preserve">
|
||||||
|
<value>Reset tab color</value>
|
||||||
|
</data>
|
||||||
|
<data name="OpenTabColorPickerCommandKey" xml:space="preserve">
|
||||||
|
<value>Set the tab color...</value>
|
||||||
|
</data>
|
||||||
|
<data name="RenameTabCommandKey" xml:space="preserve">
|
||||||
|
<value>Rename tab to "{0}"</value>
|
||||||
|
<comment>{0} will be replaced with user-defined string</comment>
|
||||||
|
</data>
|
||||||
|
<data name="ResetTabNameCommandKey" xml:space="preserve">
|
||||||
|
<value>Reset tab title</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
|
|||||||
@@ -159,6 +159,15 @@ namespace winrt::TerminalApp::implementation
|
|||||||
_ToggleFullscreenHandlers(*this, *eventArgs);
|
_ToggleFullscreenHandlers(*this, *eventArgs);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case ShortcutAction::ToggleCommandPalette:
|
||||||
|
{
|
||||||
|
_ToggleCommandPaletteHandlers(*this, *eventArgs);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ShortcutAction::ExecuteCommandline:
|
||||||
|
{
|
||||||
|
_ExecuteCommandlineHandlers(*this, *eventArgs);
|
||||||
|
}
|
||||||
case ShortcutAction::SetTabColor:
|
case ShortcutAction::SetTabColor:
|
||||||
{
|
{
|
||||||
_SetTabColorHandlers(*this, *eventArgs);
|
_SetTabColorHandlers(*this, *eventArgs);
|
||||||
|
|||||||
@@ -23,33 +23,35 @@ namespace winrt::TerminalApp::implementation
|
|||||||
bool DoAction(const ActionAndArgs& actionAndArgs);
|
bool DoAction(const ActionAndArgs& actionAndArgs);
|
||||||
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
TYPED_EVENT(CopyText, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs);
|
TYPED_EVENT(CopyText, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs);
|
||||||
TYPED_EVENT(PasteText, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs);
|
TYPED_EVENT(PasteText, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs);
|
||||||
TYPED_EVENT(OpenNewTabDropdown,TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs);
|
TYPED_EVENT(OpenNewTabDropdown, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs);
|
||||||
TYPED_EVENT(DuplicateTab, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs);
|
TYPED_EVENT(DuplicateTab, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs);
|
||||||
TYPED_EVENT(NewTab, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs);
|
TYPED_EVENT(NewTab, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs);
|
||||||
TYPED_EVENT(NewWindow, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs);
|
TYPED_EVENT(NewWindow, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs);
|
||||||
TYPED_EVENT(CloseWindow, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs);
|
TYPED_EVENT(CloseWindow, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs);
|
||||||
TYPED_EVENT(CloseTab, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs);
|
TYPED_EVENT(CloseTab, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs);
|
||||||
TYPED_EVENT(ClosePane, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs);
|
TYPED_EVENT(ClosePane, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs);
|
||||||
TYPED_EVENT(SwitchToTab, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs);
|
TYPED_EVENT(SwitchToTab, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs);
|
||||||
TYPED_EVENT(NextTab, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs);
|
TYPED_EVENT(NextTab, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs);
|
||||||
TYPED_EVENT(PrevTab, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs);
|
TYPED_EVENT(PrevTab, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs);
|
||||||
TYPED_EVENT(SplitPane, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs);
|
TYPED_EVENT(SplitPane, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs);
|
||||||
TYPED_EVENT(AdjustFontSize, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs);
|
TYPED_EVENT(AdjustFontSize, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs);
|
||||||
TYPED_EVENT(ResetFontSize, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs);
|
TYPED_EVENT(ResetFontSize, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs);
|
||||||
TYPED_EVENT(ScrollUp, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs);
|
TYPED_EVENT(ScrollUp, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs);
|
||||||
TYPED_EVENT(ScrollDown, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs);
|
TYPED_EVENT(ScrollDown, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs);
|
||||||
TYPED_EVENT(ScrollUpPage, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs);
|
TYPED_EVENT(ScrollUpPage, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs);
|
||||||
TYPED_EVENT(ScrollDownPage, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs);
|
TYPED_EVENT(ScrollDownPage, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs);
|
||||||
TYPED_EVENT(OpenSettings, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs);
|
TYPED_EVENT(OpenSettings, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs);
|
||||||
TYPED_EVENT(ResizePane, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs);
|
TYPED_EVENT(ResizePane, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs);
|
||||||
TYPED_EVENT(Find, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs);
|
TYPED_EVENT(Find, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs);
|
||||||
TYPED_EVENT(MoveFocus, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs);
|
TYPED_EVENT(MoveFocus, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs);
|
||||||
TYPED_EVENT(ToggleFullscreen, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs);
|
TYPED_EVENT(ToggleFullscreen, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs);
|
||||||
TYPED_EVENT(SetTabColor, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs);
|
TYPED_EVENT(ToggleCommandPalette, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs);
|
||||||
TYPED_EVENT(OpenTabColorPicker,TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs);
|
TYPED_EVENT(ExecuteCommandline, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs);
|
||||||
TYPED_EVENT(RenameTab, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs);
|
TYPED_EVENT(SetTabColor, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs);
|
||||||
|
TYPED_EVENT(OpenTabColorPicker, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs);
|
||||||
|
TYPED_EVENT(RenameTab, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs);
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -35,7 +35,9 @@ namespace TerminalApp
|
|||||||
SetTabColor,
|
SetTabColor,
|
||||||
OpenTabColorPicker,
|
OpenTabColorPicker,
|
||||||
OpenSettings,
|
OpenSettings,
|
||||||
RenameTab
|
ExecuteCommandline,
|
||||||
|
RenameTab,
|
||||||
|
ToggleCommandPalette
|
||||||
};
|
};
|
||||||
|
|
||||||
[default_interface] runtimeclass ActionAndArgs {
|
[default_interface] runtimeclass ActionAndArgs {
|
||||||
@@ -73,6 +75,8 @@ namespace TerminalApp
|
|||||||
event Windows.Foundation.TypedEventHandler<ShortcutActionDispatch, ActionEventArgs> Find;
|
event Windows.Foundation.TypedEventHandler<ShortcutActionDispatch, ActionEventArgs> Find;
|
||||||
event Windows.Foundation.TypedEventHandler<ShortcutActionDispatch, ActionEventArgs> MoveFocus;
|
event Windows.Foundation.TypedEventHandler<ShortcutActionDispatch, ActionEventArgs> MoveFocus;
|
||||||
event Windows.Foundation.TypedEventHandler<ShortcutActionDispatch, ActionEventArgs> ToggleFullscreen;
|
event Windows.Foundation.TypedEventHandler<ShortcutActionDispatch, ActionEventArgs> ToggleFullscreen;
|
||||||
|
event Windows.Foundation.TypedEventHandler<ShortcutActionDispatch, ActionEventArgs> ToggleCommandPalette;
|
||||||
|
event Windows.Foundation.TypedEventHandler<ShortcutActionDispatch, ActionEventArgs> ExecuteCommandline;
|
||||||
event Windows.Foundation.TypedEventHandler<ShortcutActionDispatch, ActionEventArgs> SetTabColor;
|
event Windows.Foundation.TypedEventHandler<ShortcutActionDispatch, ActionEventArgs> SetTabColor;
|
||||||
event Windows.Foundation.TypedEventHandler<ShortcutActionDispatch, ActionEventArgs> OpenTabColorPicker;
|
event Windows.Foundation.TypedEventHandler<ShortcutActionDispatch, ActionEventArgs> OpenTabColorPicker;
|
||||||
event Windows.Foundation.TypedEventHandler<ShortcutActionDispatch, ActionEventArgs> RenameTab;
|
event Windows.Foundation.TypedEventHandler<ShortcutActionDispatch, ActionEventArgs> RenameTab;
|
||||||
|
|||||||
@@ -875,6 +875,10 @@ namespace winrt::TerminalApp::implementation
|
|||||||
return _rootPane->PreCalculateAutoSplit(_activePane, availableSpace).value_or(SplitState::Vertical);
|
return _rootPane->PreCalculateAutoSplit(_activePane, availableSpace).value_or(SplitState::Vertical);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Tab::PreCalculateCanSplit(SplitState splitType, winrt::Windows::Foundation::Size availableSpace) const
|
||||||
|
{
|
||||||
|
return _rootPane->PreCalculateCanSplit(_activePane, splitType, availableSpace).value_or(false);
|
||||||
|
}
|
||||||
DEFINE_EVENT(Tab, ActivePaneChanged, _ActivePaneChangedHandlers, winrt::delegate<>);
|
DEFINE_EVENT(Tab, ActivePaneChanged, _ActivePaneChangedHandlers, winrt::delegate<>);
|
||||||
DEFINE_EVENT(Tab, ColorSelected, _colorSelected, winrt::delegate<winrt::Windows::UI::Color>);
|
DEFINE_EVENT(Tab, ColorSelected, _colorSelected, winrt::delegate<winrt::Windows::UI::Color>);
|
||||||
DEFINE_EVENT(Tab, ColorCleared, _colorCleared, winrt::delegate<>);
|
DEFINE_EVENT(Tab, ColorCleared, _colorCleared, winrt::delegate<>);
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ namespace winrt::TerminalApp::implementation
|
|||||||
|
|
||||||
float CalcSnappedDimension(const bool widthOrHeight, const float dimension) const;
|
float CalcSnappedDimension(const bool widthOrHeight, const float dimension) const;
|
||||||
SplitState PreCalculateAutoSplit(winrt::Windows::Foundation::Size rootSize) const;
|
SplitState PreCalculateAutoSplit(winrt::Windows::Foundation::Size rootSize) const;
|
||||||
|
bool PreCalculateCanSplit(SplitState splitType, winrt::Windows::Foundation::Size availableSpace) const;
|
||||||
|
|
||||||
void ResizeContent(const winrt::Windows::Foundation::Size& newSize);
|
void ResizeContent(const winrt::Windows::Foundation::Size& newSize);
|
||||||
void ResizePane(const winrt::TerminalApp::Direction& direction);
|
void ResizePane(const winrt::TerminalApp::Direction& direction);
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
#include <winrt/Windows.Storage.h>
|
#include <winrt/Windows.Storage.h>
|
||||||
#include <winrt/Microsoft.UI.Xaml.XamlTypeInfo.h>
|
#include <winrt/Microsoft.UI.Xaml.XamlTypeInfo.h>
|
||||||
|
|
||||||
|
#include "KeyChordSerialization.h"
|
||||||
#include "AzureCloudShellGenerator.h" // For AzureConnectionType
|
#include "AzureCloudShellGenerator.h" // For AzureConnectionType
|
||||||
#include "TelnetGenerator.h" // For TelnetConnectionType
|
#include "TelnetGenerator.h" // For TelnetConnectionType
|
||||||
#include "TabRowControl.h"
|
#include "TabRowControl.h"
|
||||||
@@ -49,13 +50,39 @@ namespace winrt::TerminalApp::implementation
|
|||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TerminalPage::SetSettings(std::shared_ptr<::TerminalApp::CascadiaSettings> settings, bool needRefreshUI)
|
winrt::fire_and_forget TerminalPage::SetSettings(std::shared_ptr<::TerminalApp::CascadiaSettings> settings,
|
||||||
|
bool needRefreshUI)
|
||||||
{
|
{
|
||||||
_settings = settings;
|
_settings = settings;
|
||||||
if (needRefreshUI)
|
if (needRefreshUI)
|
||||||
{
|
{
|
||||||
_RefreshUIForSettingsReload();
|
_RefreshUIForSettingsReload();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto weakThis{ get_weak() };
|
||||||
|
co_await winrt::resume_foreground(Dispatcher());
|
||||||
|
if (auto page{ weakThis.get() })
|
||||||
|
{
|
||||||
|
// Update the command palette when settings reload
|
||||||
|
auto commandsCollection = winrt::single_threaded_vector<winrt::TerminalApp::Command>();
|
||||||
|
for (auto& nameAndCommand : _settings->GlobalSettings().GetCommands())
|
||||||
|
{
|
||||||
|
auto command = nameAndCommand.second;
|
||||||
|
|
||||||
|
// 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->GetKeybindings().GetKeyBindingForActionWithArgs(command.Action()) };
|
||||||
|
if (keyChord)
|
||||||
|
{
|
||||||
|
command.KeyChordText(KeyChordSerialization::ToString(keyChord));
|
||||||
|
}
|
||||||
|
commandsCollection.Append(command);
|
||||||
|
}
|
||||||
|
CommandPalette().SetActions(commandsCollection);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TerminalPage::Create()
|
void TerminalPage::Create()
|
||||||
@@ -151,6 +178,17 @@ namespace winrt::TerminalApp::implementation
|
|||||||
|
|
||||||
_tabContent.SizeChanged({ this, &TerminalPage::_OnContentSizeChanged });
|
_tabContent.SizeChanged({ this, &TerminalPage::_OnContentSizeChanged });
|
||||||
|
|
||||||
|
CommandPalette().SetDispatch(*_actionDispatch);
|
||||||
|
// When the visibility of the command palette changes to "collapsed",
|
||||||
|
// the palette has been closed. Toss focus back to the currently active
|
||||||
|
// control.
|
||||||
|
CommandPalette().RegisterPropertyChangedCallback(UIElement::VisibilityProperty(), [this](auto&&, auto&&) {
|
||||||
|
if (CommandPalette().Visibility() == Visibility::Collapsed)
|
||||||
|
{
|
||||||
|
_CommandPaletteClosed(nullptr, nullptr);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Once the page is actually laid out on the screen, trigger all our
|
// Once the page is actually laid out on the screen, trigger all our
|
||||||
// startup actions. Things like Panes need to know at least how big the
|
// startup actions. Things like Panes need to know at least how big the
|
||||||
// window will be, so they can subdivide that space.
|
// window will be, so they can subdivide that space.
|
||||||
@@ -192,7 +230,7 @@ namespace winrt::TerminalApp::implementation
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_ProcessStartupActions();
|
_ProcessStartupActions(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -201,10 +239,11 @@ namespace winrt::TerminalApp::implementation
|
|||||||
// - Process all the startup actions in our list of startup actions. We'll
|
// - Process all the startup actions in our list of startup actions. We'll
|
||||||
// do this all at once here.
|
// do this all at once here.
|
||||||
// Arguments:
|
// Arguments:
|
||||||
// - <none>
|
// - initial: if true, we're parsing these args during startup, and we
|
||||||
|
// should fire an Initialized event.
|
||||||
// Return Value:
|
// Return Value:
|
||||||
// - <none>
|
// - <none>
|
||||||
winrt::fire_and_forget TerminalPage::_ProcessStartupActions()
|
winrt::fire_and_forget TerminalPage::_ProcessStartupActions(const bool initial)
|
||||||
{
|
{
|
||||||
// If there are no actions left, do nothing.
|
// If there are no actions left, do nothing.
|
||||||
if (_startupActions.empty())
|
if (_startupActions.empty())
|
||||||
@@ -214,15 +253,24 @@ namespace winrt::TerminalApp::implementation
|
|||||||
auto weakThis{ get_weak() };
|
auto weakThis{ get_weak() };
|
||||||
|
|
||||||
// Handle it on a subsequent pass of the UI thread.
|
// Handle it on a subsequent pass of the UI thread.
|
||||||
co_await winrt::resume_foreground(Dispatcher(), CoreDispatcherPriority::Normal);
|
for (const auto& action : _startupActions)
|
||||||
if (auto page{ weakThis.get() })
|
|
||||||
{
|
{
|
||||||
for (const auto& action : _startupActions)
|
co_await winrt::resume_foreground(Dispatcher(), CoreDispatcherPriority::Normal);
|
||||||
|
if (auto page{ weakThis.get() })
|
||||||
{
|
{
|
||||||
_actionDispatch->DoAction(action);
|
_actionDispatch->DoAction(action);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
_CompleteInitialization();
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (auto page{ weakThis.get() })
|
||||||
|
{
|
||||||
|
if (initial)
|
||||||
|
{
|
||||||
|
_CompleteInitialization();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -755,6 +803,8 @@ namespace winrt::TerminalApp::implementation
|
|||||||
_actionDispatch->Find({ this, &TerminalPage::_HandleFind });
|
_actionDispatch->Find({ this, &TerminalPage::_HandleFind });
|
||||||
_actionDispatch->ResetFontSize({ this, &TerminalPage::_HandleResetFontSize });
|
_actionDispatch->ResetFontSize({ this, &TerminalPage::_HandleResetFontSize });
|
||||||
_actionDispatch->ToggleFullscreen({ this, &TerminalPage::_HandleToggleFullscreen });
|
_actionDispatch->ToggleFullscreen({ this, &TerminalPage::_HandleToggleFullscreen });
|
||||||
|
_actionDispatch->ToggleCommandPalette({ this, &TerminalPage::_HandleToggleCommandPalette });
|
||||||
|
_actionDispatch->ExecuteCommandline({ this, &TerminalPage::_HandleExecuteCommandline });
|
||||||
_actionDispatch->SetTabColor({ this, &TerminalPage::_HandleSetTabColor });
|
_actionDispatch->SetTabColor({ this, &TerminalPage::_HandleSetTabColor });
|
||||||
_actionDispatch->OpenTabColorPicker({ this, &TerminalPage::_HandleOpenTabColorPicker });
|
_actionDispatch->OpenTabColorPicker({ this, &TerminalPage::_HandleOpenTabColorPicker });
|
||||||
_actionDispatch->RenameTab({ this, &TerminalPage::_HandleRenameTab });
|
_actionDispatch->RenameTab({ this, &TerminalPage::_HandleRenameTab });
|
||||||
@@ -1265,19 +1315,20 @@ namespace winrt::TerminalApp::implementation
|
|||||||
|
|
||||||
const auto controlConnection = _CreateConnectionFromSettings(realGuid, controlSettings);
|
const auto controlConnection = _CreateConnectionFromSettings(realGuid, controlSettings);
|
||||||
|
|
||||||
const auto canSplit = focusedTab->CanSplitPane(splitType);
|
float contentWidth = gsl::narrow_cast<float>(_tabContent.ActualWidth());
|
||||||
|
float contentHeight = gsl::narrow_cast<float>(_tabContent.ActualHeight());
|
||||||
if (!canSplit && _startupState == StartupState::Initialized)
|
winrt::Windows::Foundation::Size availableSpace{ contentWidth, contentHeight };
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto realSplitType = splitType;
|
auto realSplitType = splitType;
|
||||||
if (realSplitType == SplitState::Automatic && _startupState < StartupState::Initialized)
|
if (realSplitType == SplitState::Automatic)
|
||||||
{
|
{
|
||||||
float contentWidth = gsl::narrow_cast<float>(_tabContent.ActualWidth());
|
realSplitType = focusedTab->PreCalculateAutoSplit(availableSpace);
|
||||||
float contentHeight = gsl::narrow_cast<float>(_tabContent.ActualHeight());
|
}
|
||||||
realSplitType = focusedTab->PreCalculateAutoSplit({ contentWidth, contentHeight });
|
|
||||||
|
const auto canSplit = focusedTab->PreCalculateCanSplit(realSplitType, availableSpace);
|
||||||
|
if (!canSplit)
|
||||||
|
{
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
TermControl newControl{ controlSettings, controlConnection };
|
TermControl newControl{ controlSettings, controlConnection };
|
||||||
@@ -2031,6 +2082,16 @@ namespace winrt::TerminalApp::implementation
|
|||||||
// TODO GH#3327: Look at what to do with the NC area when we have XAML theming
|
// TODO GH#3327: Look at what to do with the NC area when we have XAML theming
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TerminalPage::_CommandPaletteClosed(const IInspectable& /*sender*/,
|
||||||
|
const RoutedEventArgs& /*eventArgs*/)
|
||||||
|
{
|
||||||
|
// Return focus to the active control
|
||||||
|
if (auto index{ _GetFocusedTabIndex() })
|
||||||
|
{
|
||||||
|
_GetStrongTabImpl(index.value())->SetFocused(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// -------------------------------- WinRT Events ---------------------------------
|
// -------------------------------- WinRT Events ---------------------------------
|
||||||
// Winrt events need a method for adding a callback to the event and removing the callback.
|
// Winrt events need a method for adding a callback to the event and removing the callback.
|
||||||
// These macros will define them both for you.
|
// These macros will define them both for you.
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ namespace winrt::TerminalApp::implementation
|
|||||||
public:
|
public:
|
||||||
TerminalPage();
|
TerminalPage();
|
||||||
|
|
||||||
void SetSettings(std::shared_ptr<::TerminalApp::CascadiaSettings> settings, bool needRefreshUI);
|
winrt::fire_and_forget SetSettings(std::shared_ptr<::TerminalApp::CascadiaSettings> settings, bool needRefreshUI);
|
||||||
|
|
||||||
void Create();
|
void Create();
|
||||||
|
|
||||||
@@ -93,7 +93,7 @@ namespace winrt::TerminalApp::implementation
|
|||||||
StartupState _startupState{ StartupState::NotInitialized };
|
StartupState _startupState{ StartupState::NotInitialized };
|
||||||
|
|
||||||
std::deque<winrt::TerminalApp::ActionAndArgs> _startupActions;
|
std::deque<winrt::TerminalApp::ActionAndArgs> _startupActions;
|
||||||
winrt::fire_and_forget _ProcessStartupActions();
|
winrt::fire_and_forget _ProcessStartupActions(const bool initial);
|
||||||
|
|
||||||
void _ShowAboutDialog();
|
void _ShowAboutDialog();
|
||||||
void _ShowCloseWarningDialog();
|
void _ShowCloseWarningDialog();
|
||||||
@@ -173,6 +173,8 @@ namespace winrt::TerminalApp::implementation
|
|||||||
|
|
||||||
void _CompleteInitialization();
|
void _CompleteInitialization();
|
||||||
|
|
||||||
|
void _CommandPaletteClosed(const IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& eventArgs);
|
||||||
|
|
||||||
#pragma region ActionHandlers
|
#pragma region ActionHandlers
|
||||||
// These are all defined in AppActionHandlers.cpp
|
// These are all defined in AppActionHandlers.cpp
|
||||||
void _HandleOpenNewTabDropdown(const IInspectable& sender, const TerminalApp::ActionEventArgs& args);
|
void _HandleOpenNewTabDropdown(const IInspectable& sender, const TerminalApp::ActionEventArgs& args);
|
||||||
@@ -201,6 +203,9 @@ namespace winrt::TerminalApp::implementation
|
|||||||
void _HandleSetTabColor(const IInspectable& sender, const TerminalApp::ActionEventArgs& args);
|
void _HandleSetTabColor(const IInspectable& sender, const TerminalApp::ActionEventArgs& args);
|
||||||
void _HandleOpenTabColorPicker(const IInspectable& sender, const TerminalApp::ActionEventArgs& args);
|
void _HandleOpenTabColorPicker(const IInspectable& sender, const TerminalApp::ActionEventArgs& args);
|
||||||
void _HandleRenameTab(const IInspectable& sender, const TerminalApp::ActionEventArgs& args);
|
void _HandleRenameTab(const IInspectable& sender, const TerminalApp::ActionEventArgs& args);
|
||||||
|
void _HandleToggleCommandPalette(const IInspectable& sender, const TerminalApp::ActionEventArgs& args);
|
||||||
|
void _HandleExecuteCommandline(const IInspectable& sender, const TerminalApp::ActionEventArgs& args);
|
||||||
|
// Make sure to hook new actions up in _RegisterActionCallbacks!
|
||||||
#pragma endregion
|
#pragma endregion
|
||||||
|
|
||||||
friend class TerminalAppLocalTests::TabTests;
|
friend class TerminalAppLocalTests::TabTests;
|
||||||
|
|||||||
@@ -53,5 +53,11 @@ the MIT License. See LICENSE in the project root for license information. -->
|
|||||||
DefaultButton="Primary"
|
DefaultButton="Primary"
|
||||||
PrimaryButtonClick="_CloseWarningPrimaryButtonOnClick">
|
PrimaryButtonClick="_CloseWarningPrimaryButtonOnClick">
|
||||||
</ContentDialog>
|
</ContentDialog>
|
||||||
|
|
||||||
|
<local:CommandPalette
|
||||||
|
x:Name="CommandPalette"
|
||||||
|
Grid.Row="1"
|
||||||
|
Visibility="Collapsed"
|
||||||
|
VerticalAlignment="Stretch" />
|
||||||
</Grid>
|
</Grid>
|
||||||
</Page>
|
</Page>
|
||||||
|
|||||||
@@ -63,6 +63,9 @@
|
|||||||
<Page Include="../ColorPickupFlyout.xaml">
|
<Page Include="../ColorPickupFlyout.xaml">
|
||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
</Page>
|
</Page>
|
||||||
|
<Page Include="../CommandPalette.xaml">
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
</Page>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<!-- ========================= Headers ======================== -->
|
<!-- ========================= Headers ======================== -->
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@@ -85,6 +88,12 @@
|
|||||||
<ClInclude Include="../ColorPickupFlyout.h">
|
<ClInclude Include="../ColorPickupFlyout.h">
|
||||||
<DependentUpon>../ColorPickupFlyout.xaml</DependentUpon>
|
<DependentUpon>../ColorPickupFlyout.xaml</DependentUpon>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="../CommandPalette.h">
|
||||||
|
<DependentUpon>../CommandPalette.xaml</DependentUpon>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="../Command.h">
|
||||||
|
<DependentUpon>../Command.idl</DependentUpon>
|
||||||
|
</ClInclude>
|
||||||
<ClInclude Include="../Tab.h">
|
<ClInclude Include="../Tab.h">
|
||||||
<DependentUpon>../Tab.idl</DependentUpon>
|
<DependentUpon>../Tab.idl</DependentUpon>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
@@ -103,7 +112,7 @@
|
|||||||
<ClInclude Include="../WslDistroGenerator.h" />
|
<ClInclude Include="../WslDistroGenerator.h" />
|
||||||
<ClInclude Include="../AzureCloudShellGenerator.h" />
|
<ClInclude Include="../AzureCloudShellGenerator.h" />
|
||||||
<ClInclude Include="../TelnetGenerator.h" />
|
<ClInclude Include="../TelnetGenerator.h" />
|
||||||
<ClInclude Include="..\ColorHelper.h" />
|
<ClInclude Include="../ColorHelper.h" />
|
||||||
<ClInclude Include="pch.h" />
|
<ClInclude Include="pch.h" />
|
||||||
<ClInclude Include="../ShortcutActionDispatch.h">
|
<ClInclude Include="../ShortcutActionDispatch.h">
|
||||||
<DependentUpon>../ShortcutActionDispatch.idl</DependentUpon>
|
<DependentUpon>../ShortcutActionDispatch.idl</DependentUpon>
|
||||||
@@ -146,6 +155,12 @@
|
|||||||
<ClCompile Include="../ColorPickupFlyout.cpp">
|
<ClCompile Include="../ColorPickupFlyout.cpp">
|
||||||
<DependentUpon>../ColorPickupFlyout.xaml</DependentUpon>
|
<DependentUpon>../ColorPickupFlyout.xaml</DependentUpon>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="../CommandPalette.cpp">
|
||||||
|
<DependentUpon>../CommandPalette.xaml</DependentUpon>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="../Command.cpp">
|
||||||
|
<DependentUpon>../Command.idl</DependentUpon>
|
||||||
|
</ClCompile>
|
||||||
<ClCompile Include="../Tab.cpp">
|
<ClCompile Include="../Tab.cpp">
|
||||||
<DependentUpon>../Tab.idl</DependentUpon>
|
<DependentUpon>../Tab.idl</DependentUpon>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
@@ -229,7 +244,12 @@
|
|||||||
<DependentUpon>../ColorPickupFlyout.xaml</DependentUpon>
|
<DependentUpon>../ColorPickupFlyout.xaml</DependentUpon>
|
||||||
<SubType>Code</SubType>
|
<SubType>Code</SubType>
|
||||||
</Midl>
|
</Midl>
|
||||||
<Midl Include="../Tab.idl"/>
|
<Midl Include="../CommandPalette.idl">
|
||||||
|
<DependentUpon>../CommandPalette.xaml</DependentUpon>
|
||||||
|
<SubType>Code</SubType>
|
||||||
|
</Midl>
|
||||||
|
<Midl Include="../Command.idl" />
|
||||||
|
<Midl Include="../Tab.idl" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<!-- ========================= Misc Files ======================== -->
|
<!-- ========================= Misc Files ======================== -->
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<Natvis Include="$(SolutionDir)tools\ConsoleTypes.natvis" />
|
<Natvis Include="$(SolutionDir)tools\ConsoleTypes.natvis" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PRIResource Include="../Resources/en-US/Resources.resw" />
|
<PRIResource Include="..\Resources\en-US\Resources.resw" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="../init.cpp" />
|
<ClCompile Include="../init.cpp" />
|
||||||
@@ -59,7 +59,13 @@
|
|||||||
<ClCompile Include="../Pane.LayoutSizeNode.cpp">
|
<ClCompile Include="../Pane.LayoutSizeNode.cpp">
|
||||||
<Filter>pane</Filter>
|
<Filter>pane</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\ColorHelper.cpp" />
|
<ClCompile Include="../AppCommandlineArgs.cpp" />
|
||||||
|
<ClCompile Include="../Commandline.cpp" />
|
||||||
|
<ClCompile Include="../ColorHelper.cpp" />
|
||||||
|
<ClCompile Include="../DebugTapConnection.cpp" />
|
||||||
|
<ClCompile Include="../CommandSerialization.cpp">
|
||||||
|
<Filter>settings</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="../Utils.h" />
|
<ClInclude Include="../Utils.h" />
|
||||||
@@ -107,8 +113,16 @@
|
|||||||
<ClInclude Include="../Tab.h">
|
<ClInclude Include="../Tab.h">
|
||||||
<Filter>tab</Filter>
|
<Filter>tab</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="../TelnetGenerator.h" />
|
<ClInclude Include="../AppCommandlineArgs.h" />
|
||||||
<ClInclude Include="..\ColorHelper.h" />
|
<ClInclude Include="../Commandline.h" />
|
||||||
|
<ClInclude Include="../DebugTapConnection.h" />
|
||||||
|
<ClInclude Include="../ColorHelper.h" />
|
||||||
|
<ClInclude Include="../TelnetGenerator.h">
|
||||||
|
<Filter>profileGeneration</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="../CommandSerialization.h">
|
||||||
|
<Filter>settings</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Midl Include="../AppLogic.idl">
|
<Midl Include="../AppLogic.idl">
|
||||||
@@ -126,6 +140,10 @@
|
|||||||
<Midl Include="../Tab.idl">
|
<Midl Include="../Tab.idl">
|
||||||
<Filter>tab</Filter>
|
<Filter>tab</Filter>
|
||||||
</Midl>
|
</Midl>
|
||||||
|
<Midl Include="../IF7Listener.idl" />
|
||||||
|
<Midl Include="../Command.idl">
|
||||||
|
<Filter>commandPalette</Filter>
|
||||||
|
</Midl>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="../packages.config" />
|
<None Include="../packages.config" />
|
||||||
@@ -146,6 +164,9 @@
|
|||||||
<Page Include="../ColorPickupFlyout.xaml">
|
<Page Include="../ColorPickupFlyout.xaml">
|
||||||
<Filter>controls</Filter>
|
<Filter>controls</Filter>
|
||||||
</Page>
|
</Page>
|
||||||
|
<Page Include="../CommandPalette.xaml">
|
||||||
|
<Filter>commandPalette</Filter>
|
||||||
|
</Page>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Filter Include="app">
|
<Filter Include="app">
|
||||||
@@ -169,6 +190,9 @@
|
|||||||
<Filter Include="tab">
|
<Filter Include="tab">
|
||||||
<UniqueIdentifier>{6d40e12f-b83f-462e-8f93-fa421f87b27e}</UniqueIdentifier>
|
<UniqueIdentifier>{6d40e12f-b83f-462e-8f93-fa421f87b27e}</UniqueIdentifier>
|
||||||
</Filter>
|
</Filter>
|
||||||
|
<Filter Include="commandPalette">
|
||||||
|
<UniqueIdentifier>{2ad498e1-d8ea-4381-9464-a74c141bd7dd}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ApplicationDefinition Include="..\App.xaml">
|
<ApplicationDefinition Include="..\App.xaml">
|
||||||
|
|||||||
@@ -28,6 +28,8 @@
|
|||||||
|
|
||||||
#include <winrt/Windows.Foundation.h>
|
#include <winrt/Windows.Foundation.h>
|
||||||
#include <winrt/Windows.Foundation.Collections.h>
|
#include <winrt/Windows.Foundation.Collections.h>
|
||||||
|
#include <winrt/Windows.Foundation.Metadata.h>
|
||||||
|
#include <winrt/Windows.Graphics.Display.h>
|
||||||
#include <winrt/windows.ui.core.h>
|
#include <winrt/windows.ui.core.h>
|
||||||
#include <winrt/Windows.ui.input.h>
|
#include <winrt/Windows.ui.input.h>
|
||||||
#include <winrt/Windows.UI.Text.h>
|
#include <winrt/Windows.UI.Text.h>
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
|
|
||||||
using namespace ::Microsoft::Console::Types;
|
using namespace ::Microsoft::Console::Types;
|
||||||
using namespace ::Microsoft::Terminal::Core;
|
using namespace ::Microsoft::Terminal::Core;
|
||||||
|
using namespace winrt::Windows::Graphics::Display;
|
||||||
using namespace winrt::Windows::UI::Xaml;
|
using namespace winrt::Windows::UI::Xaml;
|
||||||
using namespace winrt::Windows::UI::Xaml::Input;
|
using namespace winrt::Windows::UI::Xaml::Input;
|
||||||
using namespace winrt::Windows::UI::Xaml::Automation::Peers;
|
using namespace winrt::Windows::UI::Xaml::Automation::Peers;
|
||||||
@@ -621,7 +622,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
|
|||||||
// Then, using the font, get the number of characters that can fit.
|
// Then, using the font, get the number of characters that can fit.
|
||||||
// Resize our terminal connection to match that size, and initialize the terminal with that size.
|
// Resize our terminal connection to match that size, and initialize the terminal with that size.
|
||||||
const auto viewInPixels = Viewport::FromDimensions({ 0, 0 }, windowSize);
|
const auto viewInPixels = Viewport::FromDimensions({ 0, 0 }, windowSize);
|
||||||
THROW_IF_FAILED(dxEngine->SetWindowSize({ viewInPixels.Width(), viewInPixels.Height() }));
|
LOG_IF_FAILED(dxEngine->SetWindowSize({ viewInPixels.Width(), viewInPixels.Height() }));
|
||||||
|
|
||||||
// Update DxEngine's SelectionBackground
|
// Update DxEngine's SelectionBackground
|
||||||
dxEngine->SetSelectionBackground(_settings.SelectionBackground());
|
dxEngine->SetSelectionBackground(_settings.SelectionBackground());
|
||||||
@@ -2242,28 +2243,68 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
|
|||||||
// as font size, scrollbar and other control scaling, etc. Make sure the
|
// as font size, scrollbar and other control scaling, etc. Make sure the
|
||||||
// caller knows what monitor the control is about to appear on.
|
// caller knows what monitor the control is about to appear on.
|
||||||
// Return Value:
|
// Return Value:
|
||||||
// - a point containing the requested dimensions in pixels.
|
// - a size containing the requested dimensions in pixels.
|
||||||
winrt::Windows::Foundation::Point TermControl::GetProposedDimensions(IControlSettings const& settings, const uint32_t dpi)
|
winrt::Windows::Foundation::Size TermControl::GetProposedDimensions(IControlSettings const& settings, const uint32_t dpi)
|
||||||
{
|
{
|
||||||
|
// If the settings have negative or zero row or column counts, ignore those counts.
|
||||||
|
// (The lower TerminalCore layer also has upper bounds as well, but at this layer
|
||||||
|
// we may eventually impose different ones depending on how many pixels we can address.)
|
||||||
|
const auto cols = ::base::saturated_cast<float>(std::max(settings.InitialCols(), 1));
|
||||||
|
const auto rows = ::base::saturated_cast<float>(std::max(settings.InitialRows(), 1));
|
||||||
|
|
||||||
|
const winrt::Windows::Foundation::Size initialSize{ cols, rows };
|
||||||
|
|
||||||
|
return GetProposedDimensions(initialSize,
|
||||||
|
settings.FontSize(),
|
||||||
|
settings.FontWeight(),
|
||||||
|
settings.FontFace(),
|
||||||
|
settings.ScrollState(),
|
||||||
|
settings.Padding(),
|
||||||
|
dpi);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function Description:
|
||||||
|
// - Determines how much space (in pixels) an app would need to reserve to
|
||||||
|
// create a control with the settings stored in the settings param. This
|
||||||
|
// accounts for things like the font size and face, the initialRows and
|
||||||
|
// initialCols, and scrollbar visibility. The returned sized is based upon
|
||||||
|
// the provided DPI value
|
||||||
|
// Arguments:
|
||||||
|
// - initialSizeInChars: The size to get the proposed dimensions for.
|
||||||
|
// - fontHeight: The font height to use to calculate the proposed size for.
|
||||||
|
// - fontWeight: The font weight to use to calculate the proposed size for.
|
||||||
|
// - fontFace: The font name to use to calculate the proposed size for.
|
||||||
|
// - scrollState: The ScrollbarState to use to calculate the proposed size for.
|
||||||
|
// - padding: The padding to use to calculate the proposed size for.
|
||||||
|
// - dpi: The DPI we should create the terminal at. This affects things such
|
||||||
|
// as font size, scrollbar and other control scaling, etc. Make sure the
|
||||||
|
// caller knows what monitor the control is about to appear on.
|
||||||
|
// Return Value:
|
||||||
|
// - a size containing the requested dimensions in pixels.
|
||||||
|
winrt::Windows::Foundation::Size TermControl::GetProposedDimensions(const winrt::Windows::Foundation::Size& initialSizeInChars,
|
||||||
|
const int32_t& fontHeight,
|
||||||
|
const winrt::Windows::UI::Text::FontWeight& fontWeight,
|
||||||
|
const winrt::hstring& fontFace,
|
||||||
|
const Microsoft::Terminal::Settings::ScrollbarState& scrollState,
|
||||||
|
const winrt::hstring& padding,
|
||||||
|
const uint32_t dpi)
|
||||||
|
{
|
||||||
|
const auto cols = ::base::saturated_cast<int>(initialSizeInChars.Width);
|
||||||
|
const auto rows = ::base::saturated_cast<int>(initialSizeInChars.Height);
|
||||||
|
|
||||||
// Initialize our font information.
|
// Initialize our font information.
|
||||||
const auto fontFace = settings.FontFace();
|
// const auto fontFace = settings.FontFace();
|
||||||
const short fontHeight = gsl::narrow_cast<short>(settings.FontSize());
|
// const short fontHeight = gsl::narrow_cast<short>(fontSize);
|
||||||
const auto fontWeight = settings.FontWeight();
|
// const auto fontWeight = settings.FontWeight();
|
||||||
// The font width doesn't terribly matter, we'll only be using the
|
// The font width doesn't terribly matter, we'll only be using the
|
||||||
// height to look it up
|
// height to look it up
|
||||||
// The other params here also largely don't matter.
|
// The other params here also largely don't matter.
|
||||||
// The family is only used to determine if the font is truetype or
|
// The family is only used to determine if the font is truetype or
|
||||||
// not, but DX doesn't use that info at all.
|
// not, but DX doesn't use that info at all.
|
||||||
// The Codepage is additionally not actually used by the DX engine at all.
|
// The Codepage is additionally not actually used by the DX engine at all.
|
||||||
FontInfo actualFont = { fontFace, 0, fontWeight.Weight, { 0, fontHeight }, CP_UTF8, false };
|
FontInfo actualFont = { fontFace, 0, fontWeight.Weight, { 0, gsl::narrow_cast<short>(fontHeight) }, CP_UTF8, false };
|
||||||
FontInfoDesired desiredFont = { actualFont };
|
FontInfoDesired desiredFont = { actualFont };
|
||||||
|
|
||||||
// If the settings have negative or zero row or column counts, ignore those counts.
|
|
||||||
// (The lower TerminalCore layer also has upper bounds as well, but at this layer
|
|
||||||
// we may eventually impose different ones depending on how many pixels we can address.)
|
|
||||||
const auto cols = std::max(settings.InitialCols(), 1);
|
|
||||||
const auto rows = std::max(settings.InitialRows(), 1);
|
|
||||||
|
|
||||||
// Create a DX engine and initialize it with our font and DPI. We'll
|
// Create a DX engine and initialize it with our font and DPI. We'll
|
||||||
// then use it to measure how much space the requested rows and columns
|
// then use it to measure how much space the requested rows and columns
|
||||||
// will take up.
|
// will take up.
|
||||||
@@ -2283,13 +2324,13 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
|
|||||||
double width = cols * fontSize.X;
|
double width = cols * fontSize.X;
|
||||||
|
|
||||||
// Reserve additional space if scrollbar is intended to be visible
|
// Reserve additional space if scrollbar is intended to be visible
|
||||||
if (settings.ScrollState() == ScrollbarState::Visible)
|
if (scrollState == ScrollbarState::Visible)
|
||||||
{
|
{
|
||||||
width += scrollbarSize;
|
width += scrollbarSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
double height = rows * fontSize.Y;
|
double height = rows * fontSize.Y;
|
||||||
auto thickness = _ParseThicknessFromPadding(settings.Padding());
|
auto thickness = _ParseThicknessFromPadding(padding);
|
||||||
// GH#2061 - make sure to account for the size the padding _will be_ scaled to
|
// GH#2061 - make sure to account for the size the padding _will be_ scaled to
|
||||||
width += scale * (thickness.Left + thickness.Right);
|
width += scale * (thickness.Left + thickness.Right);
|
||||||
height += scale * (thickness.Top + thickness.Bottom);
|
height += scale * (thickness.Top + thickness.Bottom);
|
||||||
@@ -2322,21 +2363,41 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
|
|||||||
// have a visible character.
|
// have a visible character.
|
||||||
winrt::Windows::Foundation::Size TermControl::MinimumSize()
|
winrt::Windows::Foundation::Size TermControl::MinimumSize()
|
||||||
{
|
{
|
||||||
const auto fontSize = _actualFont.GetSize();
|
if (_initializedTerminal)
|
||||||
double width = fontSize.X;
|
|
||||||
double height = fontSize.Y;
|
|
||||||
// Reserve additional space if scrollbar is intended to be visible
|
|
||||||
if (_settings.ScrollState() == ScrollbarState::Visible)
|
|
||||||
{
|
{
|
||||||
width += ScrollBar().ActualWidth();
|
const auto fontSize = _actualFont.GetSize();
|
||||||
|
double width = fontSize.X;
|
||||||
|
double height = fontSize.Y;
|
||||||
|
// Reserve additional space if scrollbar is intended to be visible
|
||||||
|
if (_settings.ScrollState() == ScrollbarState::Visible)
|
||||||
|
{
|
||||||
|
width += ScrollBar().ActualWidth();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Account for the size of any padding
|
||||||
|
const auto padding = SwapChainPanel().Margin();
|
||||||
|
width += padding.Left + padding.Right;
|
||||||
|
height += padding.Top + padding.Bottom;
|
||||||
|
|
||||||
|
return { gsl::narrow_cast<float>(width), gsl::narrow_cast<float>(height) };
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// If the terminal hasn't been initialized yet, then the font size will
|
||||||
|
// have dimensions {1, fontSize.Y}, which can mess with consumers of
|
||||||
|
// this method. In that case, we'll need to pre-calculate the font
|
||||||
|
// width, before we actually have a renderer or swapchain.
|
||||||
|
const winrt::Windows::Foundation::Size minSize{ 1, 1 };
|
||||||
|
const double scaleFactor = DisplayInformation::GetForCurrentView().RawPixelsPerViewPixel();
|
||||||
|
const auto dpi = ::base::saturated_cast<uint32_t>(USER_DEFAULT_SCREEN_DPI * scaleFactor);
|
||||||
|
return GetProposedDimensions(minSize,
|
||||||
|
_settings.FontSize(),
|
||||||
|
_settings.FontWeight(),
|
||||||
|
_settings.FontFace(),
|
||||||
|
_settings.ScrollState(),
|
||||||
|
_settings.Padding(),
|
||||||
|
dpi);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Account for the size of any padding
|
|
||||||
const auto padding = SwapChainPanel().Margin();
|
|
||||||
width += padding.Left + padding.Right;
|
|
||||||
height += padding.Top + padding.Bottom;
|
|
||||||
|
|
||||||
return { gsl::narrow_cast<float>(width), gsl::narrow_cast<float>(height) };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Method Description:
|
// Method Description:
|
||||||
|
|||||||
@@ -98,7 +98,14 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
|
|||||||
|
|
||||||
TerminalConnection::ConnectionState ConnectionState() const;
|
TerminalConnection::ConnectionState ConnectionState() const;
|
||||||
|
|
||||||
static Windows::Foundation::Point GetProposedDimensions(Microsoft::Terminal::Settings::IControlSettings const& settings, const uint32_t dpi);
|
static Windows::Foundation::Size GetProposedDimensions(Microsoft::Terminal::Settings::IControlSettings const& settings, const uint32_t dpi);
|
||||||
|
static Windows::Foundation::Size GetProposedDimensions(const winrt::Windows::Foundation::Size& initialSizeInChars,
|
||||||
|
const int32_t& fontSize,
|
||||||
|
const winrt::Windows::UI::Text::FontWeight& fontWeight,
|
||||||
|
const winrt::hstring& fontFace,
|
||||||
|
const Microsoft::Terminal::Settings::ScrollbarState& scrollState,
|
||||||
|
const winrt::hstring& padding,
|
||||||
|
const uint32_t dpi);
|
||||||
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
// -------------------------------- WinRT Events ---------------------------------
|
// -------------------------------- WinRT Events ---------------------------------
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ namespace Microsoft.Terminal.TerminalControl
|
|||||||
TermControl();
|
TermControl();
|
||||||
TermControl(Microsoft.Terminal.Settings.IControlSettings settings, Microsoft.Terminal.TerminalConnection.ITerminalConnection connection);
|
TermControl(Microsoft.Terminal.Settings.IControlSettings settings, Microsoft.Terminal.TerminalConnection.ITerminalConnection connection);
|
||||||
|
|
||||||
static Windows.Foundation.Point GetProposedDimensions(Microsoft.Terminal.Settings.IControlSettings settings, UInt32 dpi);
|
static Windows.Foundation.Size GetProposedDimensions(Microsoft.Terminal.Settings.IControlSettings settings, UInt32 dpi);
|
||||||
|
|
||||||
void UpdateSettings(Microsoft.Terminal.Settings.IControlSettings newSettings);
|
void UpdateSettings(Microsoft.Terminal.Settings.IControlSettings newSettings);
|
||||||
|
|
||||||
|
|||||||
@@ -94,3 +94,11 @@ try
|
|||||||
return loader.GetLocalizedString(key);
|
return loader.GetLocalizedString(key);
|
||||||
}
|
}
|
||||||
CATCH_FAIL_FAST()
|
CATCH_FAIL_FAST()
|
||||||
|
|
||||||
|
bool HasLibraryResourceWithName(const std::wstring_view key)
|
||||||
|
try
|
||||||
|
{
|
||||||
|
static auto loader{ GetLibraryResourceLoader() };
|
||||||
|
return loader.HasResourceWithName(key);
|
||||||
|
}
|
||||||
|
CATCH_FAIL_FAST()
|
||||||
|
|||||||
@@ -68,3 +68,4 @@ namespace Microsoft::Console::Utils
|
|||||||
__declspec(selectany) extern const wchar_t* g_WinRTUtilsLibraryResourceScope{ (x) };
|
__declspec(selectany) extern const wchar_t* g_WinRTUtilsLibraryResourceScope{ (x) };
|
||||||
|
|
||||||
winrt::hstring GetLibraryResourceString(const std::wstring_view key);
|
winrt::hstring GetLibraryResourceString(const std::wstring_view key);
|
||||||
|
bool HasLibraryResourceWithName(const std::wstring_view key);
|
||||||
|
|||||||
@@ -283,9 +283,9 @@ void AppHost::_HandleCreateWindow(const HWND hwnd, RECT proposedRect, winrt::Ter
|
|||||||
auto initialSize = _logic.GetLaunchDimensions(dpix);
|
auto initialSize = _logic.GetLaunchDimensions(dpix);
|
||||||
|
|
||||||
const short islandWidth = Utils::ClampToShortMax(
|
const short islandWidth = Utils::ClampToShortMax(
|
||||||
static_cast<long>(ceil(initialSize.X)), 1);
|
static_cast<long>(ceil(initialSize.Width)), 1);
|
||||||
const short islandHeight = Utils::ClampToShortMax(
|
const short islandHeight = Utils::ClampToShortMax(
|
||||||
static_cast<long>(ceil(initialSize.Y)), 1);
|
static_cast<long>(ceil(initialSize.Height)), 1);
|
||||||
|
|
||||||
// Get the size of a window we'd need to host that client rect. This will
|
// Get the size of a window we'd need to host that client rect. This will
|
||||||
// add the titlebar space.
|
// add the titlebar space.
|
||||||
|
|||||||
@@ -107,15 +107,16 @@ public: \
|
|||||||
private: \
|
private: \
|
||||||
type _##name{ __VA_ARGS__ };
|
type _##name{ __VA_ARGS__ };
|
||||||
|
|
||||||
// Use this macro to quickly implement both the getter and setter for an observable property.
|
// Use this macro to quickly implement both the getter and setter for an
|
||||||
// This is similar to the GETSET_PROPERTY macro above, except this will also raise a
|
// observable property. This is similar to the GETSET_PROPERTY macro above,
|
||||||
// PropertyChanged event with the name of the property that has changed inside of the setter.
|
// except this will also raise a PropertyChanged event with the name of the
|
||||||
|
// property that has changed inside of the setter. This also implements a
|
||||||
|
// private _setName() method, that the class can internally use to change the
|
||||||
|
// value when it _knows_ it doesn't need to raise the PropertyChanged event
|
||||||
|
// (like when the class is being initialized).
|
||||||
#define OBSERVABLE_GETSET_PROPERTY(type, name, event) \
|
#define OBSERVABLE_GETSET_PROPERTY(type, name, event) \
|
||||||
public: \
|
public: \
|
||||||
type name() { return _##name; }; \
|
type name() { return _##name; }; \
|
||||||
\
|
|
||||||
private: \
|
|
||||||
const type _##name; \
|
|
||||||
void name(const type& value) \
|
void name(const type& value) \
|
||||||
{ \
|
{ \
|
||||||
if (_##name != value) \
|
if (_##name != value) \
|
||||||
@@ -123,6 +124,13 @@ private:
|
|||||||
const_cast<type&>(_##name) = value; \
|
const_cast<type&>(_##name) = value; \
|
||||||
event(*this, Windows::UI::Xaml::Data::PropertyChangedEventArgs{ L#name }); \
|
event(*this, Windows::UI::Xaml::Data::PropertyChangedEventArgs{ L#name }); \
|
||||||
} \
|
} \
|
||||||
|
}; \
|
||||||
|
\
|
||||||
|
private: \
|
||||||
|
const type _##name; \
|
||||||
|
void _set##name(const type& value) \
|
||||||
|
{ \
|
||||||
|
const_cast<type&>(_##name) = value; \
|
||||||
};
|
};
|
||||||
|
|
||||||
// Use this macro for quickly defining the factory_implementation part of a
|
// Use this macro for quickly defining the factory_implementation part of a
|
||||||
|
|||||||
@@ -148,10 +148,19 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned"
|
|||||||
std::wstring to_string() const
|
std::wstring to_string() const
|
||||||
{
|
{
|
||||||
std::wstringstream wss;
|
std::wstringstream wss;
|
||||||
wss << L"Color #" << std::uppercase << std::setfill(L'0') << std::hex;
|
wss << L"Color " << ToHexString(false);
|
||||||
|
return wss.str();
|
||||||
|
}
|
||||||
|
std::wstring ToHexString(const bool omitAlpha = false) const
|
||||||
|
{
|
||||||
|
std::wstringstream wss;
|
||||||
|
wss << L"#" << std::uppercase << std::setfill(L'0') << std::hex;
|
||||||
// Force the compiler to promote from byte to int. Without it, the
|
// Force the compiler to promote from byte to int. Without it, the
|
||||||
// stringstream will try to write the components as chars
|
// stringstream will try to write the components as chars
|
||||||
wss << std::setw(2) << static_cast<int>(a);
|
if (!omitAlpha)
|
||||||
|
{
|
||||||
|
wss << std::setw(2) << static_cast<int>(a);
|
||||||
|
}
|
||||||
wss << std::setw(2) << static_cast<int>(r);
|
wss << std::setw(2) << static_cast<int>(r);
|
||||||
wss << std::setw(2) << static_cast<int>(g);
|
wss << std::setw(2) << static_cast<int>(g);
|
||||||
wss << std::setw(2) << static_cast<int>(b);
|
wss << std::setw(2) << static_cast<int>(b);
|
||||||
|
|||||||
Reference in New Issue
Block a user