mirror of
https://github.com/microsoft/terminal.git
synced 2026-04-14 02:01:01 +00:00
Compare commits
35 Commits
dev/migrie
...
dev/miniks
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6005dd863d | ||
|
|
954e23c126 | ||
|
|
3e257594ad | ||
|
|
04dc2190b2 | ||
|
|
ef8aef4c26 | ||
|
|
120ad1f12d | ||
|
|
3f8e8184f7 | ||
|
|
d16ebd2669 | ||
|
|
6de06001f3 | ||
|
|
1f91789cfb | ||
|
|
001c2d3cb2 | ||
|
|
06bfc9607d | ||
|
|
f16c26482a | ||
|
|
ca287fe519 | ||
|
|
b339fd7926 | ||
|
|
7fd7aa4c3b | ||
|
|
1d3b2c78b0 | ||
|
|
d43d888bd7 | ||
|
|
27c1a6daa4 | ||
|
|
ddd13141cc | ||
|
|
69235d8dd3 | ||
|
|
76b1356d9e | ||
|
|
5f9bb815b1 | ||
|
|
5079c0f79f | ||
|
|
29d8857066 | ||
|
|
d8d35ef3da | ||
|
|
fbb7334c5c | ||
|
|
a41ede3f17 | ||
|
|
895e71d840 | ||
|
|
66606e0a8a | ||
|
|
35183a4e58 | ||
|
|
7cdc3187fe | ||
|
|
e09f0ace37 | ||
|
|
e3e788b52b | ||
|
|
136817e337 |
15
.github/actions/spelling/README.md
vendored
15
.github/actions/spelling/README.md
vendored
@@ -1,15 +0,0 @@
|
||||
# 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
48
.github/actions/spelling/advice.md
vendored
@@ -1,48 +0,0 @@
|
||||
<!-- 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>
|
||||
21
.github/actions/spelling/allow/README.md
vendored
21
.github/actions/spelling/allow/README.md
vendored
@@ -1,21 +0,0 @@
|
||||
# Allow files are lists of words to accept unconditionally
|
||||
|
||||
While check spelling will complain about an expected word
|
||||
which is no longer present, you can include things here even if
|
||||
they are not otherwise present in the repository.
|
||||
|
||||
E.g., you could include a list of system APIs here, or potential
|
||||
contributors (so that if a future commit includes their name,
|
||||
it'll be accepted).
|
||||
|
||||
## Files
|
||||
|
||||
| File | Description |
|
||||
| ---- | ----------- |
|
||||
| [Allow](allow.txt) | Supplements to the dictionary |
|
||||
| [Chinese](chinese.txt) | Chinese words |
|
||||
| [Japanese](japanese.txt) | Japanese words |
|
||||
| [Microsoft](microsoft.txt) | Microsoft brand items |
|
||||
| [Fonts](fonts.txt) | Font names |
|
||||
| [Names](names.txt) | Names of people |
|
||||
| [Colors](colors.txt) | Names of color |
|
||||
108
.github/actions/spelling/allow/allow.txt
vendored
108
.github/actions/spelling/allow/allow.txt
vendored
@@ -1,108 +0,0 @@
|
||||
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
248
.github/actions/spelling/allow/apis.txt
vendored
@@ -1,248 +0,0 @@
|
||||
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
|
||||
5
.github/actions/spelling/allow/chinese.txt
vendored
5
.github/actions/spelling/allow/chinese.txt
vendored
@@ -1,5 +0,0 @@
|
||||
CHINESEBIG
|
||||
choseong
|
||||
Jongseong
|
||||
Jungseong
|
||||
ssangtikeut
|
||||
117
.github/actions/spelling/allow/colors.txt
vendored
117
.github/actions/spelling/allow/colors.txt
vendored
@@ -1,117 +0,0 @@
|
||||
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
|
||||
10
.github/actions/spelling/allow/fonts.txt
vendored
10
.github/actions/spelling/allow/fonts.txt
vendored
@@ -1,10 +0,0 @@
|
||||
Consolas
|
||||
emoji
|
||||
emojis
|
||||
Extralight
|
||||
Gabriola
|
||||
Iosevka
|
||||
MDL
|
||||
Monofur
|
||||
Segoe
|
||||
wght
|
||||
4
.github/actions/spelling/allow/japanese.txt
vendored
4
.github/actions/spelling/allow/japanese.txt
vendored
@@ -1,4 +0,0 @@
|
||||
arigatoo
|
||||
doomo
|
||||
Kaomojis
|
||||
TATEGAKI
|
||||
11
.github/actions/spelling/allow/math.txt
vendored
11
.github/actions/spelling/allow/math.txt
vendored
@@ -1,11 +0,0 @@
|
||||
atan
|
||||
CPrime
|
||||
HBar
|
||||
HPrime
|
||||
isnan
|
||||
LPrime
|
||||
LStep
|
||||
powf
|
||||
RSub
|
||||
sqrtf
|
||||
ULP
|
||||
85
.github/actions/spelling/allow/microsoft.txt
vendored
85
.github/actions/spelling/allow/microsoft.txt
vendored
@@ -1,85 +0,0 @@
|
||||
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
|
||||
91
.github/actions/spelling/allow/names.txt
vendored
91
.github/actions/spelling/allow/names.txt
vendored
@@ -1,91 +0,0 @@
|
||||
Anup
|
||||
austdi
|
||||
arkthur
|
||||
Ballmer
|
||||
bhoj
|
||||
Bhojwani
|
||||
Bluloco
|
||||
carlos
|
||||
dhowett
|
||||
Diviness
|
||||
dsafa
|
||||
duhowett
|
||||
DXP
|
||||
ekg
|
||||
eryksun
|
||||
ethanschoonover
|
||||
Firefox
|
||||
Gatta
|
||||
glsl
|
||||
Gravell
|
||||
Grie
|
||||
Griese
|
||||
Hernan
|
||||
Howett
|
||||
Illhardt
|
||||
iquilezles
|
||||
italo
|
||||
jantari
|
||||
jerrysh
|
||||
Kaiyu
|
||||
kimwalisch
|
||||
KMehrain
|
||||
KODELIFE
|
||||
Kodelife
|
||||
Kourosh
|
||||
kowalczyk
|
||||
leonmsft
|
||||
Lepilleur
|
||||
lhecker
|
||||
lukesampson
|
||||
Macbook
|
||||
Manandhar
|
||||
masserano
|
||||
mbadolato
|
||||
Mehrain
|
||||
menger
|
||||
mgravell
|
||||
michaelniksa
|
||||
michkap
|
||||
migrie
|
||||
mikegr
|
||||
mikemaccana
|
||||
miloush
|
||||
miniksa
|
||||
niksa
|
||||
nvaccess
|
||||
nvda
|
||||
oising
|
||||
oldnewthing
|
||||
opengl
|
||||
osgwiki
|
||||
pabhojwa
|
||||
panos
|
||||
paulcam
|
||||
pauldotknopf
|
||||
PGP
|
||||
Pham
|
||||
Rincewind
|
||||
rprichard
|
||||
Schoonover
|
||||
shadertoy
|
||||
Shomnipotence
|
||||
simioni
|
||||
Somuah
|
||||
sonph
|
||||
sonpham
|
||||
stakx
|
||||
talo
|
||||
thereses
|
||||
Walisch
|
||||
WDX
|
||||
Wellons
|
||||
Wirt
|
||||
Wojciech
|
||||
zadjii
|
||||
Zamor
|
||||
Zamora
|
||||
zamora
|
||||
Zoey
|
||||
zorio
|
||||
Zverovich
|
||||
523
.github/actions/spelling/candidate.patterns
vendored
523
.github/actions/spelling/candidate.patterns
vendored
@@ -1,523 +0,0 @@
|
||||
# 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
117
.github/actions/spelling/excludes.txt
vendored
@@ -1,117 +0,0 @@
|
||||
# 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$
|
||||
13
.github/actions/spelling/expect/README.md
vendored
13
.github/actions/spelling/expect/README.md
vendored
@@ -1,13 +0,0 @@
|
||||
The contents of each `.txt` file in this directory are merged together.
|
||||
|
||||
* [alphabet](alphabet.txt) is a sample for alphabet related items
|
||||
* [web](web.txt) is a sample for web/html related items
|
||||
* [expect](expect.txt) is the main list of expected items -- there is nothing
|
||||
particularly special about the file name (beyond the extension which is
|
||||
important).
|
||||
|
||||
These terms are things which temporarily exist in the project, but which
|
||||
aren't necessarily words.
|
||||
|
||||
If something is a word that could come and go, it probably belongs in a
|
||||
[dictionary](../dictionary/README.md).
|
||||
40
.github/actions/spelling/expect/alphabet.txt
vendored
40
.github/actions/spelling/expect/alphabet.txt
vendored
@@ -1,40 +0,0 @@
|
||||
AAAa
|
||||
AAAAA
|
||||
AAAAAAAAAAAAA
|
||||
AAAAAABBBBBBCCC
|
||||
AAAAABBBBBBCCC
|
||||
abcd
|
||||
abcd
|
||||
ABCDEFGHIJ
|
||||
abcdefghijk
|
||||
ABCDEFGHIJKLMNO
|
||||
abcdefghijklmnop
|
||||
ABCDEFGHIJKLMNOPQRST
|
||||
ABCG
|
||||
ABE
|
||||
abf
|
||||
BBBBB
|
||||
BBBBBBBB
|
||||
BBBBBCCC
|
||||
BBBBCCCCC
|
||||
BBGGRR
|
||||
EFG
|
||||
EFGh
|
||||
QQQQQQQQQQABCDEFGHIJ
|
||||
QQQQQQQQQQABCDEFGHIJKLMNOPQRSTQQQQQQQQQ
|
||||
QQQQQQQQQQABCDEFGHIJKLMNOPQRSTQQQQQQQQQQ
|
||||
QQQQQQQQQQABCDEFGHIJPQRSTQQQQQQQQQQ
|
||||
qrstuvwxyz
|
||||
qwerty
|
||||
qwertyuiopasdfg
|
||||
YYYYYYYDDDDDDDDDDD
|
||||
ZAAZZ
|
||||
ZABBZ
|
||||
ZBAZZ
|
||||
ZBBBZ
|
||||
ZBBZZ
|
||||
ZYXWVUT
|
||||
ZZBBZ
|
||||
ZZZBB
|
||||
ZZZBZ
|
||||
ZZZZZ
|
||||
2296
.github/actions/spelling/expect/expect.txt
vendored
2296
.github/actions/spelling/expect/expect.txt
vendored
File diff suppressed because it is too large
Load Diff
6
.github/actions/spelling/expect/web.txt
vendored
6
.github/actions/spelling/expect/web.txt
vendored
@@ -1,6 +0,0 @@
|
||||
WCAG
|
||||
winui
|
||||
appshellintegration
|
||||
mdtauk
|
||||
gfycat
|
||||
Guake
|
||||
62
.github/actions/spelling/line_forbidden.patterns
vendored
62
.github/actions/spelling/line_forbidden.patterns
vendored
@@ -1,62 +0,0 @@
|
||||
# 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
|
||||
2
.github/actions/spelling/patterns/0_n.txt
vendored
2
.github/actions/spelling/patterns/0_n.txt
vendored
@@ -1,2 +0,0 @@
|
||||
\\native(?![a-z])
|
||||
\\nihilist(?![a-z])
|
||||
8
.github/actions/spelling/patterns/0_r.txt
vendored
8
.github/actions/spelling/patterns/0_r.txt
vendored
@@ -1,8 +0,0 @@
|
||||
\\registry(?![a-z])
|
||||
\\release(?![a-z])
|
||||
\\resources?(?![a-z])
|
||||
\\result(?![a-z])
|
||||
\\resultmacros(?![a-z])
|
||||
\\rules(?![a-z])
|
||||
\\renderer(?![a-z])
|
||||
\\rectread(?![a-z])
|
||||
13
.github/actions/spelling/patterns/0_t.txt
vendored
13
.github/actions/spelling/patterns/0_t.txt
vendored
@@ -1,13 +0,0 @@
|
||||
\\telemetry(?![a-z])
|
||||
\\templates(?![a-z])
|
||||
\\term(?![a-z])
|
||||
\\terminal(?![a-z])
|
||||
\\terminalcore(?![a-z])
|
||||
\\terminalinput(?![a-z])
|
||||
\\testlist(?![a-z])
|
||||
\\testmd(?![a-z])
|
||||
\\testpasses(?![a-z])
|
||||
\\tests(?![a-z])
|
||||
\\thread(?![a-z])
|
||||
\\tools(?![a-z])
|
||||
\\types(?![a-z])
|
||||
16
.github/actions/spelling/patterns/README.md
vendored
16
.github/actions/spelling/patterns/README.md
vendored
@@ -1,16 +0,0 @@
|
||||
The contents of each `.txt` file in this directory are merged together.
|
||||
Each line is a Perl 5 regular expression.
|
||||
Nothing is guaranteed about the order in which they're merged.
|
||||
-- If this is a problem, please reach out.
|
||||
|
||||
Note: order of the contents of these files can matter.
|
||||
Lines from an individual file are handled in file order.
|
||||
Files are selected in alphabetical order.
|
||||
|
||||
* [n](0_n.txt), [r](0_r.txt), and [t](0_t.txt) are specifically to work around
|
||||
a quirk in the spell checker:
|
||||
it often sees C strings of the form "Hello\nwerld". And would prefer to
|
||||
spot the typo of `werld`.
|
||||
* [patterns](patterns.txt) is the main list -- there is nothing
|
||||
particularly special about the file name (beyond the extension which is
|
||||
important).
|
||||
96
.github/actions/spelling/patterns/patterns.txt
vendored
96
.github/actions/spelling/patterns/patterns.txt
vendored
@@ -1,96 +0,0 @@
|
||||
# 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
12
.github/actions/spelling/reject.txt
vendored
@@ -1,12 +0,0 @@
|
||||
^attache$
|
||||
^attacher$
|
||||
^attachers$
|
||||
benefitting
|
||||
occurences?
|
||||
^dependan.*
|
||||
^oer$
|
||||
Sorce
|
||||
^[Ss]pae.*
|
||||
^untill$
|
||||
^untilling$
|
||||
^wether.*
|
||||
134
.github/workflows/spelling2.yml
vendored
134
.github/workflows/spelling2.yml
vendored
@@ -1,134 +0,0 @@
|
||||
# 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 }}
|
||||
4
.gitignore
vendored
4
.gitignore
vendored
@@ -144,13 +144,13 @@ publish/
|
||||
# Publish Web Output
|
||||
*.[Pp]ublish.xml
|
||||
*.azurePubxml
|
||||
# TODO: Comment the next line if you want to check in your web deploy settings
|
||||
# TODO: Comment the next line if you want to checkin your web deploy settings
|
||||
# but database connection strings (with potential passwords) will be unencrypted
|
||||
*.pubxml
|
||||
*.publishproj
|
||||
|
||||
# Microsoft Azure Web App publish settings. Comment the next line if you want to
|
||||
# check in your Azure Web App publish settings, but sensitive information contained
|
||||
# checkin your Azure Web App publish settings, but sensitive information contained
|
||||
# in these scripts will be unencrypted
|
||||
PublishScripts/
|
||||
|
||||
|
||||
69
NOTICE.md
69
NOTICE.md
@@ -80,7 +80,7 @@ SOFTWARE.
|
||||
|
||||
## chromium/base/numerics
|
||||
|
||||
**Source**: https://github.com/chromium/chromium/tree/master/base/numerics
|
||||
**Source**:
|
||||
|
||||
### License
|
||||
|
||||
@@ -112,71 +112,4 @@ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
```
|
||||
|
||||
## kimwalisch/libpopcnt
|
||||
|
||||
**Source**: https://github.com/kimwalisch/libpopcnt
|
||||
|
||||
### License
|
||||
|
||||
```
|
||||
BSD 2-Clause License
|
||||
|
||||
Copyright (c) 2016 - 2019, Kim Walisch
|
||||
Copyright (c) 2016 - 2019, Wojciech Muła
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
```
|
||||
|
||||
## dynamic_bitset
|
||||
|
||||
**Source**: https://github.com/pinam45/dynamic_bitset
|
||||
|
||||
### License
|
||||
|
||||
```
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 Maxime Pinard
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
```
|
||||
@@ -150,6 +150,7 @@ Please file new issues, feature requests and suggestions, but **DO search for si
|
||||
If you would like to ask a question that you feel doesn't warrant an issue (yet), please reach out to us via Twitter:
|
||||
|
||||
* Kayla Cinnamon, Program Manager: [@cinnamon\_msft](https://twitter.com/cinnamon_msft)
|
||||
* Rich Turner, Program Manager: [@richturn\_ms](https://twitter.com/richturn_ms)
|
||||
* Dustin Howett, Engineering Lead: [@dhowett](https://twitter.com/DHowett)
|
||||
* Michael Niksa, Senior Developer: [@michaelniksa](https://twitter.com/MichaelNiksa)
|
||||
* Mike Griese, Developer: [@zadjii](https://twitter.com/zadjii)
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Modules>
|
||||
<Module name="Microsoft.WindowsTerminal" tdbuildteamid="7105">
|
||||
<File location="TerminalApp"
|
||||
path="%BUILD_SOURCESDIRECTORY%\src\cascadia\TerminalApp\Resources\en-US\Resources.resw" />
|
||||
<File location="TerminalControl"
|
||||
path="%BUILD_SOURCESDIRECTORY%\src\cascadia\TerminalControl\Resources\en-US\Resources.resw" />
|
||||
<File location="TerminalConnection"
|
||||
path="%BUILD_SOURCESDIRECTORY%\src\cascadia\TerminalConnection\Resources\en-US\Resources.resw" />
|
||||
<File location="WindowsTerminalUniversal"
|
||||
path="%BUILD_SOURCESDIRECTORY%\src\cascadia\WindowsTerminalUniversal\Resources\en-US\Resources.resw" />
|
||||
<File location="CascadiaPackage"
|
||||
path="%BUILD_SOURCESDIRECTORY%\src\cascadia\CascadiaPackage\Resources\en-US\Resources.resw" />
|
||||
</Module>
|
||||
</Modules>
|
||||
@@ -27,43 +27,21 @@ variables:
|
||||
# 0.0.1904.0900
|
||||
name: 0.0.$(Date:yyMM).$(Date:dd)$(Rev:rr)
|
||||
|
||||
stages:
|
||||
- stage: Audit_x64
|
||||
displayName: Audit Mode
|
||||
dependsOn: []
|
||||
condition: succeeded()
|
||||
jobs:
|
||||
- template: ./templates/build-console-audit-job.yml
|
||||
parameters:
|
||||
platform: x64
|
||||
- stage: Build_x64
|
||||
displayName: Build x64
|
||||
dependsOn: []
|
||||
condition: succeeded()
|
||||
jobs:
|
||||
- template: ./templates/build-console-ci.yml
|
||||
parameters:
|
||||
platform: x64
|
||||
- stage: Build_x86
|
||||
displayName: Build x86
|
||||
dependsOn: []
|
||||
condition: not(eq(variables['Build.Reason'], 'PullRequest'))
|
||||
jobs:
|
||||
- template: ./templates/build-console-ci.yml
|
||||
parameters:
|
||||
platform: x86
|
||||
- stage: Build_ARM64
|
||||
displayName: Build ARM64
|
||||
dependsOn: []
|
||||
condition: not(eq(variables['Build.Reason'], 'PullRequest'))
|
||||
jobs:
|
||||
- template: ./templates/build-console-ci.yml
|
||||
parameters:
|
||||
platform: ARM64
|
||||
- stage: Scripts
|
||||
displayName: Code Health Scripts
|
||||
dependsOn: []
|
||||
condition: succeeded()
|
||||
jobs:
|
||||
- template: ./templates/check-formatting.yml
|
||||
jobs:
|
||||
- template: ./templates/build-console-audit-job.yml
|
||||
parameters:
|
||||
platform: x64
|
||||
|
||||
- template: ./templates/build-console-ci.yml
|
||||
parameters:
|
||||
platform: x64
|
||||
|
||||
- template: ./templates/build-console-ci.yml
|
||||
parameters:
|
||||
platform: x86
|
||||
|
||||
- template: ./templates/build-console-ci.yml
|
||||
parameters:
|
||||
platform: ARM64
|
||||
|
||||
- template: ./templates/check-formatting.yml
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<XesUseOneStoreVersioning>true</XesUseOneStoreVersioning>
|
||||
<XesBaseYearForStoreVersion>2020</XesBaseYearForStoreVersion>
|
||||
<VersionMajor>0</VersionMajor>
|
||||
<VersionMinor>11</VersionMinor>
|
||||
<VersionMinor>10</VersionMinor>
|
||||
<VersionInfoProductName>Windows Terminal</VersionInfoProductName>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 Maxime Pinard
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -1,17 +0,0 @@
|
||||
### Notes for Future Maintainers
|
||||
|
||||
This was originally imported by @miniksa in March 2020.
|
||||
|
||||
The provenance information (where it came from and which commit) is stored in the file `cgmanifest.json` in the same directory as this readme.
|
||||
Please update the provenance information in that file when ingesting an updated version of the dependent library.
|
||||
That provenance file is automatically read and inventoried by Microsoft systems to ensure compliance with appropiate governance standards.
|
||||
|
||||
## What should be done to update this in the future?
|
||||
|
||||
1. Go to pinam45/dynamic_bitset repository on GitHub.
|
||||
2. Take the entire contents of the include directory wholesale and drop it in the root directory here.
|
||||
3. Don't change anything about it.
|
||||
4. Validate that the license in the root of the repository didn't change and update it if so. It is sitting in the same directory as this readme.
|
||||
If it changed dramatically, ensure that it is still compatible with our license scheme. Also update the NOTICE file in the root of our repository to declare the third-party usage.
|
||||
5. Submit the pull.
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
{"Registrations":[
|
||||
{
|
||||
"component": {
|
||||
"type": "git",
|
||||
"git": {
|
||||
"repositoryUrl": "https://github.com/pinam45/dynamic_bitset",
|
||||
"commitHash": "00f2d066ce9deebf28b006636150e5a882beb83f"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"Version": 1
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
2
dep/gsl
2
dep/gsl
Submodule dep/gsl updated: 7e99e76c97...1212beae77
@@ -1,26 +0,0 @@
|
||||
BSD 2-Clause License
|
||||
|
||||
Copyright (c) 2016 - 2019, Kim Walisch
|
||||
Copyright (c) 2016 - 2019, Wojciech Muła
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
@@ -1,17 +0,0 @@
|
||||
### Notes for Future Maintainers
|
||||
|
||||
This was originally imported by @miniksa in March 2020.
|
||||
|
||||
The provenance information (where it came from and which commit) is stored in the file `cgmanifest.json` in the same directory as this readme.
|
||||
Please update the provenance information in that file when ingesting an updated version of the dependent library.
|
||||
That provenance file is automatically read and inventoried by Microsoft systems to ensure compliance with appropiate governance standards.
|
||||
|
||||
## What should be done to update this in the future?
|
||||
|
||||
1. Go to kimwalisch/libpopcnt repository on GitHub.
|
||||
2. Take the `libpopcnt.h` file.
|
||||
3. Don't change anything about it.
|
||||
4. Validate that the `LICENSE` in the root of the repository didn't change and update it if so. It is sitting in the same directory as this readme.
|
||||
If it changed dramatically, ensure that it is still compatible with our license scheme. Also update the NOTICE file in the root of our repository to declare the third-party usage.
|
||||
5. Submit the pull.
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
{"Registrations":[
|
||||
{
|
||||
"component": {
|
||||
"type": "git",
|
||||
"git": {
|
||||
"repositoryUrl": "https://github.com/kimwalisch/libpopcnt",
|
||||
"commitHash": "043a99fba31121a70bcb2f589faa17f534ae6085"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"Version": 1
|
||||
}
|
||||
@@ -1,841 +0,0 @@
|
||||
/*
|
||||
* libpopcnt.h - C/C++ library for counting the number of 1 bits (bit
|
||||
* population count) in an array as quickly as possible using
|
||||
* specialized CPU instructions i.e. POPCNT, AVX2, AVX512, NEON.
|
||||
*
|
||||
* Copyright (c) 2016 - 2019, Kim Walisch
|
||||
* Copyright (c) 2016 - 2018, Wojciech Muła
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef LIBPOPCNT_H
|
||||
#define LIBPOPCNT_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifndef __has_builtin
|
||||
#define __has_builtin(x) 0
|
||||
#endif
|
||||
|
||||
#ifndef __has_attribute
|
||||
#define __has_attribute(x) 0
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define GNUC_PREREQ(x, y) \
|
||||
(__GNUC__ > x || (__GNUC__ == x && __GNUC_MINOR__ >= y))
|
||||
#else
|
||||
#define GNUC_PREREQ(x, y) 0
|
||||
#endif
|
||||
|
||||
#ifdef __clang__
|
||||
#define CLANG_PREREQ(x, y) \
|
||||
(__clang_major__ > x || (__clang_major__ == x && __clang_minor__ >= y))
|
||||
#else
|
||||
#define CLANG_PREREQ(x, y) 0
|
||||
#endif
|
||||
|
||||
#if (_MSC_VER < 1900) && \
|
||||
!defined(__cplusplus)
|
||||
#define inline __inline
|
||||
#endif
|
||||
|
||||
#if (defined(__i386__) || \
|
||||
defined(__x86_64__) || \
|
||||
defined(_M_IX86) || \
|
||||
defined(_M_X64))
|
||||
#define X86_OR_X64
|
||||
#endif
|
||||
|
||||
#if defined(X86_OR_X64) && \
|
||||
(defined(__cplusplus) || \
|
||||
defined(_MSC_VER) || \
|
||||
(GNUC_PREREQ(4, 2) || \
|
||||
__has_builtin(__sync_val_compare_and_swap)))
|
||||
#define HAVE_CPUID
|
||||
#endif
|
||||
|
||||
#if GNUC_PREREQ(4, 2) || \
|
||||
__has_builtin(__builtin_popcount)
|
||||
#define HAVE_BUILTIN_POPCOUNT
|
||||
#endif
|
||||
|
||||
#if GNUC_PREREQ(4, 2) || \
|
||||
CLANG_PREREQ(3, 0)
|
||||
#define HAVE_ASM_POPCNT
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_CPUID) && \
|
||||
(defined(HAVE_ASM_POPCNT) || \
|
||||
defined(_MSC_VER))
|
||||
#define HAVE_POPCNT
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_CPUID) && \
|
||||
GNUC_PREREQ(4, 9)
|
||||
#define HAVE_AVX2
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_CPUID) && \
|
||||
GNUC_PREREQ(5, 0)
|
||||
#define HAVE_AVX512
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_CPUID) && \
|
||||
defined(_MSC_VER) && \
|
||||
defined(__AVX2__)
|
||||
#define HAVE_AVX2
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_CPUID) && \
|
||||
defined(_MSC_VER) && \
|
||||
defined(__AVX512__)
|
||||
#define HAVE_AVX512
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_CPUID) && \
|
||||
CLANG_PREREQ(3, 8) && \
|
||||
__has_attribute(target) && \
|
||||
(!defined(_MSC_VER) || defined(__AVX2__)) && \
|
||||
(!defined(__apple_build_version__) || __apple_build_version__ >= 8000000)
|
||||
#define HAVE_AVX2
|
||||
#define HAVE_AVX512
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This uses fewer arithmetic operations than any other known
|
||||
* implementation on machines with fast multiplication.
|
||||
* It uses 12 arithmetic operations, one of which is a multiply.
|
||||
* http://en.wikipedia.org/wiki/Hamming_weight#Efficient_implementation
|
||||
*/
|
||||
static inline uint64_t popcount64(uint64_t x)
|
||||
{
|
||||
uint64_t m1 = 0x5555555555555555ll;
|
||||
uint64_t m2 = 0x3333333333333333ll;
|
||||
uint64_t m4 = 0x0F0F0F0F0F0F0F0Fll;
|
||||
uint64_t h01 = 0x0101010101010101ll;
|
||||
|
||||
x -= (x >> 1) & m1;
|
||||
x = (x & m2) + ((x >> 2) & m2);
|
||||
x = (x + (x >> 4)) & m4;
|
||||
|
||||
return (x * h01) >> 56;
|
||||
}
|
||||
|
||||
#if defined(HAVE_ASM_POPCNT) && \
|
||||
defined(__x86_64__)
|
||||
|
||||
static inline uint64_t popcnt64(uint64_t x)
|
||||
{
|
||||
__asm__ ("popcnt %1, %0" : "=r" (x) : "0" (x));
|
||||
return x;
|
||||
}
|
||||
|
||||
#elif defined(HAVE_ASM_POPCNT) && \
|
||||
defined(__i386__)
|
||||
|
||||
static inline uint32_t popcnt32(uint32_t x)
|
||||
{
|
||||
__asm__ ("popcnt %1, %0" : "=r" (x) : "0" (x));
|
||||
return x;
|
||||
}
|
||||
|
||||
static inline uint64_t popcnt64(uint64_t x)
|
||||
{
|
||||
return popcnt32((uint32_t) x) +
|
||||
popcnt32((uint32_t)(x >> 32));
|
||||
}
|
||||
|
||||
#elif defined(_MSC_VER) && \
|
||||
defined(_M_X64)
|
||||
|
||||
#include <nmmintrin.h>
|
||||
|
||||
static inline uint64_t popcnt64(uint64_t x)
|
||||
{
|
||||
return _mm_popcnt_u64(x);
|
||||
}
|
||||
|
||||
#elif defined(_MSC_VER) && \
|
||||
defined(_M_IX86)
|
||||
|
||||
#include <nmmintrin.h>
|
||||
|
||||
static inline uint64_t popcnt64(uint64_t x)
|
||||
{
|
||||
return _mm_popcnt_u32((uint32_t) x) +
|
||||
_mm_popcnt_u32((uint32_t)(x >> 32));
|
||||
}
|
||||
|
||||
/* non x86 CPUs */
|
||||
#elif defined(HAVE_BUILTIN_POPCOUNT)
|
||||
|
||||
static inline uint64_t popcnt64(uint64_t x)
|
||||
{
|
||||
return __builtin_popcountll(x);
|
||||
}
|
||||
|
||||
/* no hardware POPCNT,
|
||||
* use pure integer algorithm */
|
||||
#else
|
||||
|
||||
static inline uint64_t popcnt64(uint64_t x)
|
||||
{
|
||||
return popcount64(x);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static inline uint64_t popcnt64_unrolled(const uint64_t* data, uint64_t size)
|
||||
{
|
||||
uint64_t i = 0;
|
||||
uint64_t limit = size - size % 4;
|
||||
uint64_t cnt = 0;
|
||||
|
||||
for (; i < limit; i += 4)
|
||||
{
|
||||
cnt += popcnt64(data[i+0]);
|
||||
cnt += popcnt64(data[i+1]);
|
||||
cnt += popcnt64(data[i+2]);
|
||||
cnt += popcnt64(data[i+3]);
|
||||
}
|
||||
|
||||
for (; i < size; i++)
|
||||
cnt += popcnt64(data[i]);
|
||||
|
||||
return cnt;
|
||||
}
|
||||
|
||||
#if defined(HAVE_CPUID)
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#include <intrin.h>
|
||||
#include <immintrin.h>
|
||||
#endif
|
||||
|
||||
/* %ecx bit flags */
|
||||
#define bit_POPCNT (1 << 23)
|
||||
|
||||
/* %ebx bit flags */
|
||||
#define bit_AVX2 (1 << 5)
|
||||
#define bit_AVX512 (1 << 30)
|
||||
|
||||
/* xgetbv bit flags */
|
||||
#define XSTATE_SSE (1 << 1)
|
||||
#define XSTATE_YMM (1 << 2)
|
||||
#define XSTATE_ZMM (7 << 5)
|
||||
|
||||
static inline void run_cpuid(int eax, int ecx, int* abcd)
|
||||
{
|
||||
#if defined(_MSC_VER)
|
||||
__cpuidex(abcd, eax, ecx);
|
||||
#else
|
||||
int ebx = 0;
|
||||
int edx = 0;
|
||||
|
||||
#if defined(__i386__) && \
|
||||
defined(__PIC__)
|
||||
/* in case of PIC under 32-bit EBX cannot be clobbered */
|
||||
__asm__ ("movl %%ebx, %%edi;"
|
||||
"cpuid;"
|
||||
"xchgl %%ebx, %%edi;"
|
||||
: "=D" (ebx),
|
||||
"+a" (eax),
|
||||
"+c" (ecx),
|
||||
"=d" (edx));
|
||||
#else
|
||||
__asm__ ("cpuid;"
|
||||
: "+b" (ebx),
|
||||
"+a" (eax),
|
||||
"+c" (ecx),
|
||||
"=d" (edx));
|
||||
#endif
|
||||
|
||||
abcd[0] = eax;
|
||||
abcd[1] = ebx;
|
||||
abcd[2] = ecx;
|
||||
abcd[3] = edx;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(HAVE_AVX2) || \
|
||||
defined(HAVE_AVX512)
|
||||
|
||||
static inline int get_xcr0()
|
||||
{
|
||||
int xcr0;
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
xcr0 = (int) _xgetbv(0);
|
||||
#else
|
||||
__asm__ ("xgetbv" : "=a" (xcr0) : "c" (0) : "%edx" );
|
||||
#endif
|
||||
|
||||
return xcr0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static inline int get_cpuid()
|
||||
{
|
||||
int flags = 0;
|
||||
int abcd[4];
|
||||
|
||||
run_cpuid(1, 0, abcd);
|
||||
|
||||
if ((abcd[2] & bit_POPCNT) == bit_POPCNT)
|
||||
flags |= bit_POPCNT;
|
||||
|
||||
#if defined(HAVE_AVX2) || \
|
||||
defined(HAVE_AVX512)
|
||||
|
||||
int osxsave_mask = (1 << 27);
|
||||
|
||||
/* ensure OS supports extended processor state management */
|
||||
if ((abcd[2] & osxsave_mask) != osxsave_mask)
|
||||
return 0;
|
||||
|
||||
int ymm_mask = XSTATE_SSE | XSTATE_YMM;
|
||||
int zmm_mask = XSTATE_SSE | XSTATE_YMM | XSTATE_ZMM;
|
||||
|
||||
int xcr0 = get_xcr0();
|
||||
|
||||
if ((xcr0 & ymm_mask) == ymm_mask)
|
||||
{
|
||||
run_cpuid(7, 0, abcd);
|
||||
|
||||
if ((abcd[1] & bit_AVX2) == bit_AVX2)
|
||||
flags |= bit_AVX2;
|
||||
|
||||
if ((xcr0 & zmm_mask) == zmm_mask)
|
||||
{
|
||||
if ((abcd[1] & bit_AVX512) == bit_AVX512)
|
||||
flags |= bit_AVX512;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
#endif /* cpuid */
|
||||
|
||||
#if defined(HAVE_AVX2)
|
||||
|
||||
#include <immintrin.h>
|
||||
|
||||
#if !defined(_MSC_VER)
|
||||
__attribute__ ((target ("avx2")))
|
||||
#endif
|
||||
static inline void CSA256(__m256i* h, __m256i* l, __m256i a, __m256i b, __m256i c)
|
||||
{
|
||||
__m256i u = _mm256_xor_si256(a, b);
|
||||
*h = _mm256_or_si256(_mm256_and_si256(a, b), _mm256_and_si256(u, c));
|
||||
*l = _mm256_xor_si256(u, c);
|
||||
}
|
||||
|
||||
#if !defined(_MSC_VER)
|
||||
__attribute__ ((target ("avx2")))
|
||||
#endif
|
||||
static inline __m256i popcnt256(__m256i v)
|
||||
{
|
||||
__m256i lookup1 = _mm256_setr_epi8(
|
||||
4, 5, 5, 6, 5, 6, 6, 7,
|
||||
5, 6, 6, 7, 6, 7, 7, 8,
|
||||
4, 5, 5, 6, 5, 6, 6, 7,
|
||||
5, 6, 6, 7, 6, 7, 7, 8
|
||||
);
|
||||
|
||||
__m256i lookup2 = _mm256_setr_epi8(
|
||||
4, 3, 3, 2, 3, 2, 2, 1,
|
||||
3, 2, 2, 1, 2, 1, 1, 0,
|
||||
4, 3, 3, 2, 3, 2, 2, 1,
|
||||
3, 2, 2, 1, 2, 1, 1, 0
|
||||
);
|
||||
|
||||
__m256i low_mask = _mm256_set1_epi8(0x0f);
|
||||
__m256i lo = _mm256_and_si256(v, low_mask);
|
||||
__m256i hi = _mm256_and_si256(_mm256_srli_epi16(v, 4), low_mask);
|
||||
__m256i popcnt1 = _mm256_shuffle_epi8(lookup1, lo);
|
||||
__m256i popcnt2 = _mm256_shuffle_epi8(lookup2, hi);
|
||||
|
||||
return _mm256_sad_epu8(popcnt1, popcnt2);
|
||||
}
|
||||
|
||||
/*
|
||||
* AVX2 Harley-Seal popcount (4th iteration).
|
||||
* The algorithm is based on the paper "Faster Population Counts
|
||||
* using AVX2 Instructions" by Daniel Lemire, Nathan Kurz and
|
||||
* Wojciech Mula (23 Nov 2016).
|
||||
* @see https://arxiv.org/abs/1611.07612
|
||||
*/
|
||||
#if !defined(_MSC_VER)
|
||||
__attribute__ ((target ("avx2")))
|
||||
#endif
|
||||
static inline uint64_t popcnt_avx2(const __m256i* data, uint64_t size)
|
||||
{
|
||||
__m256i cnt = _mm256_setzero_si256();
|
||||
__m256i ones = _mm256_setzero_si256();
|
||||
__m256i twos = _mm256_setzero_si256();
|
||||
__m256i fours = _mm256_setzero_si256();
|
||||
__m256i eights = _mm256_setzero_si256();
|
||||
__m256i sixteens = _mm256_setzero_si256();
|
||||
__m256i twosA, twosB, foursA, foursB, eightsA, eightsB;
|
||||
|
||||
uint64_t i = 0;
|
||||
uint64_t limit = size - size % 16;
|
||||
uint64_t* cnt64;
|
||||
|
||||
for(; i < limit; i += 16)
|
||||
{
|
||||
CSA256(&twosA, &ones, ones, data[i+0], data[i+1]);
|
||||
CSA256(&twosB, &ones, ones, data[i+2], data[i+3]);
|
||||
CSA256(&foursA, &twos, twos, twosA, twosB);
|
||||
CSA256(&twosA, &ones, ones, data[i+4], data[i+5]);
|
||||
CSA256(&twosB, &ones, ones, data[i+6], data[i+7]);
|
||||
CSA256(&foursB, &twos, twos, twosA, twosB);
|
||||
CSA256(&eightsA, &fours, fours, foursA, foursB);
|
||||
CSA256(&twosA, &ones, ones, data[i+8], data[i+9]);
|
||||
CSA256(&twosB, &ones, ones, data[i+10], data[i+11]);
|
||||
CSA256(&foursA, &twos, twos, twosA, twosB);
|
||||
CSA256(&twosA, &ones, ones, data[i+12], data[i+13]);
|
||||
CSA256(&twosB, &ones, ones, data[i+14], data[i+15]);
|
||||
CSA256(&foursB, &twos, twos, twosA, twosB);
|
||||
CSA256(&eightsB, &fours, fours, foursA, foursB);
|
||||
CSA256(&sixteens, &eights, eights, eightsA, eightsB);
|
||||
|
||||
cnt = _mm256_add_epi64(cnt, popcnt256(sixteens));
|
||||
}
|
||||
|
||||
cnt = _mm256_slli_epi64(cnt, 4);
|
||||
cnt = _mm256_add_epi64(cnt, _mm256_slli_epi64(popcnt256(eights), 3));
|
||||
cnt = _mm256_add_epi64(cnt, _mm256_slli_epi64(popcnt256(fours), 2));
|
||||
cnt = _mm256_add_epi64(cnt, _mm256_slli_epi64(popcnt256(twos), 1));
|
||||
cnt = _mm256_add_epi64(cnt, popcnt256(ones));
|
||||
|
||||
for(; i < size; i++)
|
||||
cnt = _mm256_add_epi64(cnt, popcnt256(data[i]));
|
||||
|
||||
cnt64 = (uint64_t*) &cnt;
|
||||
|
||||
return cnt64[0] +
|
||||
cnt64[1] +
|
||||
cnt64[2] +
|
||||
cnt64[3];
|
||||
}
|
||||
|
||||
/* Align memory to 32 bytes boundary */
|
||||
static inline void align_avx2(const uint8_t** p, uint64_t* size, uint64_t* cnt)
|
||||
{
|
||||
for (; (uintptr_t) *p % 8; (*p)++)
|
||||
{
|
||||
*cnt += popcnt64(**p);
|
||||
*size -= 1;
|
||||
}
|
||||
for (; (uintptr_t) *p % 32; (*p) += 8)
|
||||
{
|
||||
*cnt += popcnt64(
|
||||
*(const uint64_t*) *p);
|
||||
*size -= 8;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_AVX512)
|
||||
|
||||
#include <immintrin.h>
|
||||
|
||||
#if !defined(_MSC_VER)
|
||||
__attribute__ ((target ("avx512bw")))
|
||||
#endif
|
||||
static inline __m512i popcnt512(__m512i v)
|
||||
{
|
||||
__m512i m1 = _mm512_set1_epi8(0x55);
|
||||
__m512i m2 = _mm512_set1_epi8(0x33);
|
||||
__m512i m4 = _mm512_set1_epi8(0x0F);
|
||||
__m512i t1 = _mm512_sub_epi8(v, (_mm512_srli_epi16(v, 1) & m1));
|
||||
__m512i t2 = _mm512_add_epi8(t1 & m2, (_mm512_srli_epi16(t1, 2) & m2));
|
||||
__m512i t3 = _mm512_add_epi8(t2, _mm512_srli_epi16(t2, 4)) & m4;
|
||||
|
||||
return _mm512_sad_epu8(t3, _mm512_setzero_si512());
|
||||
}
|
||||
|
||||
#if !defined(_MSC_VER)
|
||||
__attribute__ ((target ("avx512bw")))
|
||||
#endif
|
||||
static inline void CSA512(__m512i* h, __m512i* l, __m512i a, __m512i b, __m512i c)
|
||||
{
|
||||
*l = _mm512_ternarylogic_epi32(c, b, a, 0x96);
|
||||
*h = _mm512_ternarylogic_epi32(c, b, a, 0xe8);
|
||||
}
|
||||
|
||||
/*
|
||||
* AVX512 Harley-Seal popcount (4th iteration).
|
||||
* The algorithm is based on the paper "Faster Population Counts
|
||||
* using AVX2 Instructions" by Daniel Lemire, Nathan Kurz and
|
||||
* Wojciech Mula (23 Nov 2016).
|
||||
* @see https://arxiv.org/abs/1611.07612
|
||||
*/
|
||||
#if !defined(_MSC_VER)
|
||||
__attribute__ ((target ("avx512bw")))
|
||||
#endif
|
||||
static inline uint64_t popcnt_avx512(const __m512i* data, const uint64_t size)
|
||||
{
|
||||
__m512i cnt = _mm512_setzero_si512();
|
||||
__m512i ones = _mm512_setzero_si512();
|
||||
__m512i twos = _mm512_setzero_si512();
|
||||
__m512i fours = _mm512_setzero_si512();
|
||||
__m512i eights = _mm512_setzero_si512();
|
||||
__m512i sixteens = _mm512_setzero_si512();
|
||||
__m512i twosA, twosB, foursA, foursB, eightsA, eightsB;
|
||||
|
||||
uint64_t i = 0;
|
||||
uint64_t limit = size - size % 16;
|
||||
uint64_t* cnt64;
|
||||
|
||||
for(; i < limit; i += 16)
|
||||
{
|
||||
CSA512(&twosA, &ones, ones, data[i+0], data[i+1]);
|
||||
CSA512(&twosB, &ones, ones, data[i+2], data[i+3]);
|
||||
CSA512(&foursA, &twos, twos, twosA, twosB);
|
||||
CSA512(&twosA, &ones, ones, data[i+4], data[i+5]);
|
||||
CSA512(&twosB, &ones, ones, data[i+6], data[i+7]);
|
||||
CSA512(&foursB, &twos, twos, twosA, twosB);
|
||||
CSA512(&eightsA, &fours, fours, foursA, foursB);
|
||||
CSA512(&twosA, &ones, ones, data[i+8], data[i+9]);
|
||||
CSA512(&twosB, &ones, ones, data[i+10], data[i+11]);
|
||||
CSA512(&foursA, &twos, twos, twosA, twosB);
|
||||
CSA512(&twosA, &ones, ones, data[i+12], data[i+13]);
|
||||
CSA512(&twosB, &ones, ones, data[i+14], data[i+15]);
|
||||
CSA512(&foursB, &twos, twos, twosA, twosB);
|
||||
CSA512(&eightsB, &fours, fours, foursA, foursB);
|
||||
CSA512(&sixteens, &eights, eights, eightsA, eightsB);
|
||||
|
||||
cnt = _mm512_add_epi64(cnt, popcnt512(sixteens));
|
||||
}
|
||||
|
||||
cnt = _mm512_slli_epi64(cnt, 4);
|
||||
cnt = _mm512_add_epi64(cnt, _mm512_slli_epi64(popcnt512(eights), 3));
|
||||
cnt = _mm512_add_epi64(cnt, _mm512_slli_epi64(popcnt512(fours), 2));
|
||||
cnt = _mm512_add_epi64(cnt, _mm512_slli_epi64(popcnt512(twos), 1));
|
||||
cnt = _mm512_add_epi64(cnt, popcnt512(ones));
|
||||
|
||||
for(; i < size; i++)
|
||||
cnt = _mm512_add_epi64(cnt, popcnt512(data[i]));
|
||||
|
||||
cnt64 = (uint64_t*) &cnt;
|
||||
|
||||
return cnt64[0] +
|
||||
cnt64[1] +
|
||||
cnt64[2] +
|
||||
cnt64[3] +
|
||||
cnt64[4] +
|
||||
cnt64[5] +
|
||||
cnt64[6] +
|
||||
cnt64[7];
|
||||
}
|
||||
|
||||
/* Align memory to 64 bytes boundary */
|
||||
static inline void align_avx512(const uint8_t** p, uint64_t* size, uint64_t* cnt)
|
||||
{
|
||||
for (; (uintptr_t) *p % 8; (*p)++)
|
||||
{
|
||||
*cnt += popcnt64(**p);
|
||||
*size -= 1;
|
||||
}
|
||||
for (; (uintptr_t) *p % 64; (*p) += 8)
|
||||
{
|
||||
*cnt += popcnt64(
|
||||
*(const uint64_t*) *p);
|
||||
*size -= 8;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* x86 CPUs */
|
||||
#if defined(X86_OR_X64)
|
||||
|
||||
/* Align memory to 8 bytes boundary */
|
||||
static inline void align_8(const uint8_t** p, uint64_t* size, uint64_t* cnt)
|
||||
{
|
||||
for (; *size > 0 && (uintptr_t) *p % 8; (*p)++)
|
||||
{
|
||||
*cnt += popcount64(**p);
|
||||
*size -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
static inline uint64_t popcount64_unrolled(const uint64_t* data, uint64_t size)
|
||||
{
|
||||
uint64_t i = 0;
|
||||
uint64_t limit = size - size % 4;
|
||||
uint64_t cnt = 0;
|
||||
|
||||
for (; i < limit; i += 4)
|
||||
{
|
||||
cnt += popcount64(data[i+0]);
|
||||
cnt += popcount64(data[i+1]);
|
||||
cnt += popcount64(data[i+2]);
|
||||
cnt += popcount64(data[i+3]);
|
||||
}
|
||||
|
||||
for (; i < size; i++)
|
||||
cnt += popcount64(data[i]);
|
||||
|
||||
return cnt;
|
||||
}
|
||||
|
||||
/*
|
||||
* Count the number of 1 bits in the data array
|
||||
* @data: An array
|
||||
* @size: Size of data in bytes
|
||||
*/
|
||||
static inline uint64_t popcnt(const void* data, uint64_t size)
|
||||
{
|
||||
const uint8_t* ptr = (const uint8_t*) data;
|
||||
uint64_t cnt = 0;
|
||||
uint64_t i;
|
||||
|
||||
#if defined(HAVE_CPUID)
|
||||
#if defined(__cplusplus)
|
||||
/* C++11 thread-safe singleton */
|
||||
static const int cpuid = get_cpuid();
|
||||
#else
|
||||
static int cpuid_ = -1;
|
||||
int cpuid = cpuid_;
|
||||
if (cpuid == -1)
|
||||
{
|
||||
cpuid = get_cpuid();
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
_InterlockedCompareExchange(&cpuid_, cpuid, -1);
|
||||
#else
|
||||
__sync_val_compare_and_swap(&cpuid_, -1, cpuid);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_AVX512)
|
||||
|
||||
/* AVX512 requires arrays >= 1024 bytes */
|
||||
if ((cpuid & bit_AVX512) &&
|
||||
size >= 1024)
|
||||
{
|
||||
align_avx512(&ptr, &size, &cnt);
|
||||
cnt += popcnt_avx512((const __m512i*) ptr, size / 64);
|
||||
ptr += size - size % 64;
|
||||
size = size % 64;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_AVX2)
|
||||
|
||||
/* AVX2 requires arrays >= 512 bytes */
|
||||
if ((cpuid & bit_AVX2) &&
|
||||
size >= 512)
|
||||
{
|
||||
align_avx2(&ptr, &size, &cnt);
|
||||
cnt += popcnt_avx2((const __m256i*) ptr, size / 32);
|
||||
ptr += size - size % 32;
|
||||
size = size % 32;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_POPCNT)
|
||||
|
||||
if (cpuid & bit_POPCNT)
|
||||
{
|
||||
cnt += popcnt64_unrolled((const uint64_t*) ptr, size / 8);
|
||||
ptr += size - size % 8;
|
||||
size = size % 8;
|
||||
for (i = 0; i < size; i++)
|
||||
cnt += popcnt64(ptr[i]);
|
||||
|
||||
return cnt;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* pure integer popcount algorithm */
|
||||
if (size >= 8)
|
||||
{
|
||||
align_8(&ptr, &size, &cnt);
|
||||
cnt += popcount64_unrolled((const uint64_t*) ptr, size / 8);
|
||||
ptr += size - size % 8;
|
||||
size = size % 8;
|
||||
}
|
||||
|
||||
/* pure integer popcount algorithm */
|
||||
for (i = 0; i < size; i++)
|
||||
cnt += popcount64(ptr[i]);
|
||||
|
||||
return cnt;
|
||||
}
|
||||
|
||||
#elif defined(__ARM_NEON) || \
|
||||
defined(__aarch64__)
|
||||
|
||||
#include <arm_neon.h>
|
||||
|
||||
/* Align memory to 8 bytes boundary */
|
||||
static inline void align_8(const uint8_t** p, uint64_t* size, uint64_t* cnt)
|
||||
{
|
||||
for (; *size > 0 && (uintptr_t) *p % 8; (*p)++)
|
||||
{
|
||||
*cnt += popcnt64(**p);
|
||||
*size -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
static inline uint64x2_t vpadalq(uint64x2_t sum, uint8x16_t t)
|
||||
{
|
||||
return vpadalq_u32(sum, vpaddlq_u16(vpaddlq_u8(t)));
|
||||
}
|
||||
|
||||
/*
|
||||
* Count the number of 1 bits in the data array
|
||||
* @data: An array
|
||||
* @size: Size of data in bytes
|
||||
*/
|
||||
static inline uint64_t popcnt(const void* data, uint64_t size)
|
||||
{
|
||||
uint64_t cnt = 0;
|
||||
uint64_t chunk_size = 64;
|
||||
const uint8_t* ptr = (const uint8_t*) data;
|
||||
|
||||
if (size >= chunk_size)
|
||||
{
|
||||
uint64_t i = 0;
|
||||
uint64_t iters = size / chunk_size;
|
||||
uint64x2_t sum = vcombine_u64(vcreate_u64(0), vcreate_u64(0));
|
||||
uint8x16_t zero = vcombine_u8(vcreate_u8(0), vcreate_u8(0));
|
||||
|
||||
do
|
||||
{
|
||||
uint8x16_t t0 = zero;
|
||||
uint8x16_t t1 = zero;
|
||||
uint8x16_t t2 = zero;
|
||||
uint8x16_t t3 = zero;
|
||||
|
||||
/*
|
||||
* After every 31 iterations we need to add the
|
||||
* temporary sums (t0, t1, t2, t3) to the total sum.
|
||||
* We must ensure that the temporary sums <= 255
|
||||
* and 31 * 8 bits = 248 which is OK.
|
||||
*/
|
||||
uint64_t limit = (i + 31 < iters) ? i + 31 : iters;
|
||||
|
||||
/* Each iteration processes 64 bytes */
|
||||
for (; i < limit; i++)
|
||||
{
|
||||
uint8x16x4_t input = vld4q_u8(ptr);
|
||||
ptr += chunk_size;
|
||||
|
||||
t0 = vaddq_u8(t0, vcntq_u8(input.val[0]));
|
||||
t1 = vaddq_u8(t1, vcntq_u8(input.val[1]));
|
||||
t2 = vaddq_u8(t2, vcntq_u8(input.val[2]));
|
||||
t3 = vaddq_u8(t3, vcntq_u8(input.val[3]));
|
||||
}
|
||||
|
||||
sum = vpadalq(sum, t0);
|
||||
sum = vpadalq(sum, t1);
|
||||
sum = vpadalq(sum, t2);
|
||||
sum = vpadalq(sum, t3);
|
||||
}
|
||||
while (i < iters);
|
||||
|
||||
uint64_t tmp[2];
|
||||
vst1q_u64(tmp, sum);
|
||||
cnt += tmp[0];
|
||||
cnt += tmp[1];
|
||||
}
|
||||
|
||||
size %= chunk_size;
|
||||
align_8(&ptr, &size, &cnt);
|
||||
const uint64_t* ptr64 = (const uint64_t*) ptr;
|
||||
uint64_t iters = size / 8;
|
||||
|
||||
for (uint64_t i = 0; i < iters; i++)
|
||||
cnt += popcnt64(ptr64[i]);
|
||||
|
||||
ptr += size - size % 8;
|
||||
size = size % 8;
|
||||
|
||||
for (uint64_t i = 0; i < size; i++)
|
||||
cnt += popcnt64(ptr[i]);
|
||||
|
||||
return cnt;
|
||||
}
|
||||
|
||||
/* all other CPUs */
|
||||
#else
|
||||
|
||||
/* Align memory to 8 bytes boundary */
|
||||
static inline void align_8(const uint8_t** p, uint64_t* size, uint64_t* cnt)
|
||||
{
|
||||
for (; *size > 0 && (uintptr_t) *p % 8; (*p)++)
|
||||
{
|
||||
*cnt += popcnt64(**p);
|
||||
*size -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Count the number of 1 bits in the data array
|
||||
* @data: An array
|
||||
* @size: Size of data in bytes
|
||||
*/
|
||||
static inline uint64_t popcnt(const void* data, uint64_t size)
|
||||
{
|
||||
const uint8_t* ptr = (const uint8_t*) data;
|
||||
uint64_t cnt = 0;
|
||||
uint64_t i;
|
||||
|
||||
align_8(&ptr, &size, &cnt);
|
||||
cnt += popcnt64_unrolled((const uint64_t*) ptr, size / 8);
|
||||
ptr += size - size % 8;
|
||||
size = size % 8;
|
||||
for (i = 0; i < size; i++)
|
||||
cnt += popcnt64(ptr[i]);
|
||||
|
||||
return cnt;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* LIBPOPCNT_H */
|
||||
@@ -57,27 +57,3 @@ Openconsole has three configuration types:
|
||||
- AuditMode
|
||||
|
||||
AuditMode is an experimental mode that enables some additional static analysis from CppCoreCheck.
|
||||
|
||||
## Updating Nuget package references
|
||||
Certain Nuget package references in this project, like `Microsoft.UI.Xaml`, must be updated outside of the Visual Studio NuGet package manager. This can be done using the snippet below.
|
||||
> Note that to run this snippet, you need to use WSL as the command uses `sed`.
|
||||
To update the version of a given package, use the following snippet
|
||||
|
||||
`git grep -z -l $PackageName | xargs -0 sed -i -e 's/$OldVersionNumber/$NewVersionNumber/g'`
|
||||
|
||||
where:
|
||||
- `$PackageName` is the name of the package, e.g. Microsoft.UI.Xaml
|
||||
- `$OldVersionNumber` is the version number currently used, e.g. 2.3.191217003-prerelease
|
||||
- `$NewVersionNumber` is the version number you want to migrate to, e.g. 2.4.200117003-prerelease
|
||||
|
||||
Example usage:
|
||||
|
||||
`git grep -z -l Microsoft.UI.Xaml | xargs -0 sed -i -e 's/2.3.191217003-prerelease/2.4.200117003-prerelease/g'`
|
||||
|
||||
## Using .nupkg files instead of downloaded Nuget packages
|
||||
If you want to use .nupkg files instead of the downloaded Nuget package, you can do this with the following steps:
|
||||
|
||||
1. Open the Nuget.config file and uncomment line 8 ("Static Package Dependencies")
|
||||
2. Create the folder /dep/packages
|
||||
3. Put your .nupkg files in /dep/packages
|
||||
4. If you are using different versions than those already being used, you need to update the references as well. How to do that is explained under "Updating Nuget package references".
|
||||
|
||||
@@ -7,14 +7,13 @@ Properties listed below affect the entire window, regardless of the profile sett
|
||||
| -------- | --------- | ---- | ------- | ----------- |
|
||||
| `alwaysShowTabs` | _Required_ | Boolean | `true` | When set to `true`, tabs are always displayed. When set to `false` and `showTabsInTitlebar` is set to `false`, tabs only appear after typing <kbd>Ctrl</kbd> + <kbd>T</kbd>. |
|
||||
| `copyOnSelect` | Optional | Boolean | `false` | When set to `true`, a selection is immediately copied to your clipboard upon creation. When set to `false`, the selection persists and awaits further action. |
|
||||
| `copyFormatting` | Optional | Boolean | `false` | When set to `true`, the color and font formatting of selected text is also copied to your clipboard. When set to `false`, only plain text is copied to your clipboard. |
|
||||
| `defaultProfile` | _Required_ | String | PowerShell guid | Sets the default profile. Opens by typing <kbd>Ctrl</kbd> + <kbd>T</kbd> or by clicking the '+' icon. The guid of the desired default profile is used as the value. |
|
||||
| `initialCols` | _Required_ | Integer | `120` | The number of columns displayed in the window upon first load. |
|
||||
| `initialPosition` | Optional | String | `","` | The position of the top left corner of the window upon first load. On a system with multiple displays, these coordinates are relative to the top left of the primary display. If `launchMode` is set to `"maximized"`, the window will be maximized on the monitor specified by those coordinates. |
|
||||
| `initialRows` | _Required_ | Integer | `30` | The number of rows displayed in the window upon first load. |
|
||||
| `launchMode` | Optional | String | `default` | Defines whether the Terminal will launch as maximized or not. Possible values: `"default"`, `"maximized"` |
|
||||
| `rowsToScroll` | Optional | Integer | `system` | The number of rows to scroll at a time with the mouse wheel. This will override the system setting if the value is not zero or "system". |
|
||||
| `theme` | _Required_ | String | `system` | Sets the theme of the application. Possible values: `"light"`, `"dark"`, `"system"` |
|
||||
| `requestedTheme` | _Required_ | String | `system` | Sets the theme of the application. Possible values: `"light"`, `"dark"`, `"system"` |
|
||||
| `showTerminalTitleInTitlebar` | _Required_ | Boolean | `true` | When set to `true`, titlebar displays the title of the selected tab. When set to `false`, titlebar displays "Windows Terminal". |
|
||||
| `showTabsInTitlebar` | Optional | Boolean | `true` | When set to `true`, the tabs are moved into the titlebar and the titlebar disappears. When set to `false`, the titlebar sits above the tabs. |
|
||||
| `snapToGridOnResize` | Optional | Boolean | `false` | When set to `true`, the window will snap to the nearest character boundary on resize. When `false`, the window will resize "smoothly" |
|
||||
@@ -38,23 +37,24 @@ Properties listed below are specific to each unique profile.
|
||||
| `backgroundImageStretchMode` | Optional | String | `uniformToFill` | Sets how the background image is resized to fill the window. Possible values: `"none"`, `"fill"`, `"uniform"`, `"uniformToFill"` |
|
||||
| `closeOnExit` | Optional | String | `graceful` | Sets how the profile reacts to termination or failure to launch. Possible values: `"graceful"` (close when `exit` is typed or the process exits normally), `"always"` (always close) and `"never"` (never close). `true` and `false` are accepted as synonyms for `"graceful"` and `"never"` respectively. |
|
||||
| `colorScheme` | Optional | String | `Campbell` | Name of the terminal color scheme to use. Color schemes are defined under `schemes`. |
|
||||
| `colorTable` | Optional | Array[String] | | Array of colors used in the profile if `colorscheme` is not set. Array follows the format defined in `schemes`. |
|
||||
| `commandline` | Optional | String | | Executable used in the profile. |
|
||||
| `cursorColor` | Optional | String | | Sets the cursor color of the profile. Overrides `cursorColor` set in color scheme if `colorscheme` is set. Uses hex color format: `"#rrggbb"`. |
|
||||
| `cursorColor` | Optional | String | `#FFFFFF` | Sets the cursor color for the profile. Uses hex color format: `"#rrggbb"`. |
|
||||
| `cursorHeight` | Optional | Integer | | Sets the percentage height of the cursor starting from the bottom. Only works when `cursorShape` is set to `"vintage"`. Accepts values from 25-100. |
|
||||
| `cursorShape` | Optional | String | `bar` | Sets the cursor shape for the profile. Possible values: `"vintage"` ( ▃ ), `"bar"` ( ┃ ), `"underscore"` ( ▁ ), `"filledBox"` ( █ ), `"emptyBox"` ( ▯ ) |
|
||||
| `fontFace` | Optional | String | `Cascadia Code` | Name of the font face used in the profile. We will try to fallback to Consolas if this can't be found or is invalid. |
|
||||
| `fontFace` | Optional | String | `Consolas` | Name of the font face used in the profile. We will try to fallback to Consolas if this can't be found or is invalid. |
|
||||
| `fontSize` | Optional | Integer | `12` | Sets the font size. |
|
||||
| `foreground` | Optional | String | | Sets the foreground color of the profile. Overrides `foreground` set in color scheme if `colorscheme` is set. Uses hex color format: `#rgb` or `"#rrggbb"`. |
|
||||
| `hidden` | Optional | Boolean | `false` | If set to true, the profile will not appear in the list of profiles. This can be used to hide default profiles and dynamically generated profiles, while leaving them in your settings file. |
|
||||
| `historySize` | Optional | Integer | `9001` | The number of lines above the ones displayed in the window you can scroll back to. |
|
||||
| `icon` | Optional | String | | Image file location of the icon used in the profile. Displays within the tab and the dropdown menu. |
|
||||
| `padding` | Optional | String | `8, 8, 8, 8` | Sets the padding around the text within the window. Can have three different formats: `"#"` sets the same padding for all sides, `"#, #"` sets the same padding for left-right and top-bottom, and `"#, #, #, #"` sets the padding individually for left, top, right, and bottom. |
|
||||
| `scrollbarState` | Optional | String | `"visible"` | Defines the visibility of the scrollbar. Possible values: `"visible"`, `"hidden"` |
|
||||
| `scrollbarState` | Optional | String | | Defines the visibility of the scrollbar. Possible values: `"visible"`, `"hidden"` |
|
||||
| `selectionBackground` | Optional | String | | Sets the selection background color of the profile. Overrides `selectionBackground` set in color scheme if `colorscheme` is set. Uses hex color format: `"#rrggbb"`. |
|
||||
| `snapOnInput` | Optional | Boolean | `true` | When set to `true`, the window will scroll to the command input line when typing. When set to `false`, the window will not scroll when you start typing. |
|
||||
| `source` | Optional | String | | Stores the name of the profile generator that originated this profile. _There are no discoverable values for this field._ |
|
||||
| `startingDirectory` | Optional | String | `%USERPROFILE%` | The directory the shell starts in when it is loaded. |
|
||||
| `suppressApplicationTitle` | Optional | Boolean | `false` | When set to `true`, `tabTitle` overrides the default title of the tab and any title change messages from the application will be suppressed. When set to `false`, `tabTitle` behaves as normal. |
|
||||
| `suppressApplicationTitle` | Optional | Boolean | | When set to `true`, `tabTitle` overrides the default title of the tab and any title change messages from the application will be suppressed. When set to `false`, `tabTitle` behaves as normal. |
|
||||
| `tabTitle` | Optional | String | | If set, will replace the `name` as the title to pass to the shell on startup. Some shells (like `bash`) may choose to ignore this initial value, while others (`cmd`, `powershell`) may use this value over the lifetime of the application. |
|
||||
| `useAcrylic` | Optional | Boolean | `false` | When set to `true`, the window will have an acrylic background. When set to `false`, the window will have a plain, untextured background. The transparency only applies to focused windows due to OS limitation. |
|
||||
| `experimental.retroTerminalEffect` | Optional | Boolean | `false` | When set to `true`, enable retro terminal effects. This is an experimental feature, and its continued existence is not guaranteed. |
|
||||
@@ -68,7 +68,6 @@ Properties listed below are specific to each color scheme. [ColorTool](https://g
|
||||
| `foreground` | _Required_ | String | Sets the foreground color of the color scheme. |
|
||||
| `background` | _Required_ | String | Sets the background color of the color scheme. |
|
||||
| `selectionBackground` | Optional | String | Sets the selection background color of the color scheme. |
|
||||
| `cursorColor` | Optional | String | Sets the cursor color of the color scheme. |
|
||||
| `black` | _Required_ | String | Sets the color used as ANSI black. |
|
||||
| `blue` | _Required_ | String | Sets the color used as ANSI blue. |
|
||||
| `brightBlack` | _Required_ | String | Sets the color used as ANSI bright black. |
|
||||
@@ -111,30 +110,31 @@ For commands with arguments:
|
||||
|
||||
| Command | Command Description | Action (*=required) | Action Arguments | Argument Descriptions |
|
||||
| ------- | ------------------- | ------ | ---------------- | ----------------- |
|
||||
| `adjustFontSize` | Change the text size by a specified point amount. | `delta` | integer | Amount of size change per command invocation. |
|
||||
| `closePane` | Close the active pane. | | | |
|
||||
| `closeTab` | Close the current tab. | | | |
|
||||
| `closeWindow` | Close the current window and all tabs within it. | | | |
|
||||
| `copy` | Copy the selected terminal content to your Windows Clipboard. | `singleLine` | boolean | When `true`, the copied content will be copied as a single line. When `false`, newlines persist from the selected text. |
|
||||
| `duplicateTab` | Make a copy and open the current tab. | | | |
|
||||
| `find` | Open the search dialog box. | | | |
|
||||
| `moveFocus` | Focus on a different pane depending on direction. | `direction`* | `left`, `right`, `up`, `down` | Direction in which the focus will move. |
|
||||
| `newTab` | Create a new tab. Without any arguments, this will open the default profile in a new tab. | 1. `commandLine`<br>2. `startingDirectory`<br>3. `tabTitle`<br>4. `index`<br>5. `profile` | 1. string<br>2. string<br>3. string<br>4. integer<br>5. string | 1. Executable run within the tab.<br>2. Directory in which the tab will open.<br>3. Title of the new tab.<br>4. Profile that will open based on its position in the dropdown (starting at 0).<br>5. Profile that will open based on its GUID or name. |
|
||||
| `nextTab` | Open the tab to the right of the current one. | | | |
|
||||
| `openNewTabDropdown` | Open the dropdown menu. | | | |
|
||||
| `openSettings` | Open the settings file. | | | |
|
||||
| `paste` | Insert the content that was copied onto the clipboard. | | | |
|
||||
| `prevTab` | Open the tab to the left of the current one. | | | |
|
||||
| `resetFontSize` | Reset the text size to the default value. | | | |
|
||||
| `resizePane` | Change the size of the active pane. | `direction`* | `left`, `right`, `up`, `down` | Direction in which the pane will be resized. |
|
||||
| `scrollDown` | Move the screen down. | | | |
|
||||
| `scrollUp` | Move the screen up. | | | |
|
||||
| `scrollUpPage` | Move the screen up a whole page. | | | |
|
||||
| `scrollDownPage` | Move the screen down a whole page. | | | |
|
||||
| `splitPane` | Halve the size of the active pane and open another. Without any arguments, this will open the default profile in the new pane. | 1. `split`*<br>2. `commandLine`<br>3. `startingDirectory`<br>4. `tabTitle`<br>5. `index`<br>6. `profile`<br>7. `splitMode` | 1. `vertical`, `horizontal`, `auto`<br>2. string<br>3. string<br>4. string<br>5. integer<br>6. string<br>7. string | 1. How the pane will split. `auto` will split in the direction that provides the most surface area.<br>2. Executable run within the pane.<br>3. Directory in which the pane will open.<br>4. Title of the tab when the new pane is focused.<br>5. Profile that will open based on its position in the dropdown (starting at 0).<br>6. Profile that will open based on its GUID or name.<br>7. Controls how the pane splits. Only accepts `duplicate` which will duplicate the focused pane's profile into a new pane. |
|
||||
| `switchToTab` | Open a specific tab depending on index. | `index`* | integer | Tab that will open based on its position in the tab bar (starting at 0). |
|
||||
| `toggleFullscreen` | Switch between fullscreen and default window sizes. | | | |
|
||||
| `unbound` | Unbind the associated keys from any command. | | | |
|
||||
| closePane | Close the active pane. | | | |
|
||||
| closeTab | Close the current tab. | | | |
|
||||
| closeWindow | Close the current window and all tabs within it. | | | |
|
||||
| copy | Copy the selected terminal content to your Windows Clipboard. | `trimWhitespace` | boolean | When `true`, newlines persist from the selected text. When `false`, copied content will paste on one line. |
|
||||
| decreaseFontSize | Make the text smaller by one delta. | `delta` | integer | Amount of size decrease per command invocation. |
|
||||
| duplicateTab | Make a copy and open the current tab. | | | |
|
||||
| find | Open the search dialog box. | | | |
|
||||
| increaseFontSize | Make the text larger by one delta. | `delta` | integer | Amount of size increase per command invocation. |
|
||||
| moveFocus | Focus on a different pane depending on direction. | `direction`* | `left`, `right`, `up`, `down` | Direction in which the focus will move. |
|
||||
| newTab | Create a new tab. Without any arguments, this will open the default profile in a new tab. | 1. `commandLine`<br>2. `startingDirectory`<br>3. `tabTitle`<br>4. `index`<br>5. `profile` | 1. string<br>2. string<br>3. string<br>4. integer<br>5. string | 1. Executable run within the tab.<br>2. Directory in which the tab will open.<br>3. Title of the new tab.<br>4. Profile that will open based on its position in the dropdown (starting at 0).<br>5. Profile that will open based on its GUID or name. |
|
||||
| nextTab | Open the tab to the right of the current one. | | | |
|
||||
| openNewTabDropdown | Open the dropdown menu. | | | |
|
||||
| openSettings | Open the settings file. | | | |
|
||||
| paste | Insert the content that was copied onto the clipboard. | | | |
|
||||
| prevTab | Open the tab to the left of the current one. | | | |
|
||||
| resetFontSize | Reset the text size to the default value. | | | |
|
||||
| resizePane | Change the size of the active pane. | `direction`* | `left`, `right`, `up`, `down` | Direction in which the pane will be resized. |
|
||||
| scrollDown | Move the screen down. | | | |
|
||||
| scrollUp | Move the screen up. | | | |
|
||||
| scrollUpPage | Move the screen up a whole page. | | | |
|
||||
| scrollDownPage | Move the screen down a whole page. | | | |
|
||||
| splitPane | Halve the size of the active pane and open another. Without any arguments, this will open the default profile in the new pane. | 1. `split`*<br>2. `commandLine`<br>3. `startingDirectory`<br>4. `tabTitle`<br>5. `index`<br>6. `profile` | 1. `vertical`, `horizontal`, `auto`<br>2. string<br>3. string<br>4. string<br>5. integer<br>6. string | 1. How the pane will split. `auto` will split in the direction that provides the most surface area.<br>2. Executable run within the pane.<br>3. Directory in which the pane will open.<br>4. Title of the tab when the new pane is focused.<br>5. Profile that will open based on its position in the dropdown (starting at 0).<br>6. Profile that will open based on its GUID or name. |
|
||||
| switchToTab | Open a specific tab depending on index. | `index`* | integer | Tab that will open based on its position in the tab bar (starting at 0). |
|
||||
| toggleFullscreen | Switch between fullscreen and default window sizes. | | | |
|
||||
| unbound | Unbind the associated keys from any command. | | | |
|
||||
|
||||
### Accepted Modifiers and Keys
|
||||
|
||||
|
||||
@@ -4,9 +4,8 @@
|
||||
"title": "Microsoft's Windows Terminal Settings Profile Schema'",
|
||||
"definitions": {
|
||||
"KeyChordSegment": {
|
||||
"pattern": "^(?<modifier>(ctrl|alt|shift)(?:\\+(ctrl|alt|shift)(?<!\\2))?(?:\\+(ctrl|alt|shift)(?<!\\2|\\3))?\\+)?(?<key>[^\\s+]|backspace|tab|enter|esc|escape|space|pgup|pageup|pgdn|pagedown|end|home|left|up|right|down|insert|delete|(?<!shift.+)(?:numpad_?[0-9]|numpad_(?:period|decimal))|numpad_(?:multiply|plus|add|minus|subtract|divide)|f[1-9]|f1[0-9]|f2[0-4]|plus)$",
|
||||
"type": "string",
|
||||
"description": "The string should fit the format \"[ctrl+][alt+][shift+]<keyName>\", where each modifier is optional, separated by + symbols, and keyName is either one of the names listed in the table below, or any single key character. The string should be written in full lowercase.\nbackspace\tBACKSPACE key\ntab\tTAB key\nenter\tENTER key\nesc, escape\tESC key\nspace\tSPACEBAR\npgup, pageup\tPAGE UP key\npgdn, pagedown\tPAGE DOWN key\nend\tEND key\nhome\tHOME key\nleft\tLEFT ARROW key\nup\tUP ARROW key\nright\tRIGHT ARROW key\ndown\tDOWN ARROW key\ninsert\tINS key\ndelete\tDEL key\nnumpad_0-numpad_9, numpad0-numpad9\tNumeric keypad keys 0 to 9. Can't be combined with the shift modifier.\nnumpad_multiply\tNumeric keypad MULTIPLY key (*)\nnumpad_plus, numpad_add\tNumeric keypad ADD key (+)\nnumpad_minus, numpad_subtract\tNumeric keypad SUBTRACT key (-)\nnumpad_period, numpad_decimal\tNumeric keypad DECIMAL key (.). Can't be combined with the shift modifier.\nnumpad_divide\tNumeric keypad DIVIDE key (/)\nf1-f24\tF1 to F24 function keys\nplus\tADD key (+)"
|
||||
"pattern": "^(?<modifier>(ctrl|alt|shift)\\+?((ctrl|alt|shift)(?<!\\2)\\+?)?((ctrl|alt|shift)(?<!\\2|\\4))?\\+?)?(?<key>[^+\\s]+?)?(?<=[^+\\s])$",
|
||||
"type": "string"
|
||||
},
|
||||
"Color": {
|
||||
"default": "#",
|
||||
@@ -25,15 +24,29 @@
|
||||
},
|
||||
"ShortcutActionName": {
|
||||
"enum": [
|
||||
"adjustFontSize",
|
||||
"closePane",
|
||||
"closeTab",
|
||||
"closeWindow",
|
||||
"copy",
|
||||
"copyTextWithoutNewlines",
|
||||
"decreaseFontSize",
|
||||
"duplicateTab",
|
||||
"increaseFontSize",
|
||||
"moveFocus",
|
||||
"moveFocusDown",
|
||||
"moveFocusLeft",
|
||||
"moveFocusRight",
|
||||
"moveFocusUp",
|
||||
"newTab",
|
||||
"newTabProfile0",
|
||||
"newTabProfile1",
|
||||
"newTabProfile2",
|
||||
"newTabProfile3",
|
||||
"newTabProfile4",
|
||||
"newTabProfile5",
|
||||
"newTabProfile6",
|
||||
"newTabProfile7",
|
||||
"newTabProfile8",
|
||||
"nextTab",
|
||||
"openNewTabDropdown",
|
||||
"openSettings",
|
||||
@@ -41,15 +54,29 @@
|
||||
"prevTab",
|
||||
"resetFontSize",
|
||||
"resizePane",
|
||||
"resizePaneDown",
|
||||
"resizePaneLeft",
|
||||
"resizePaneRight",
|
||||
"resizePaneUp",
|
||||
"scrollDown",
|
||||
"scrollDownPage",
|
||||
"scrollUp",
|
||||
"scrollUpPage",
|
||||
"splitHorizontal",
|
||||
"splitVertical",
|
||||
"splitPane",
|
||||
"switchToTab",
|
||||
"switchToTab0",
|
||||
"switchToTab1",
|
||||
"switchToTab2",
|
||||
"switchToTab3",
|
||||
"switchToTab4",
|
||||
"switchToTab5",
|
||||
"switchToTab6",
|
||||
"switchToTab7",
|
||||
"switchToTab8",
|
||||
"toggleFullscreen",
|
||||
"find",
|
||||
"unbound"
|
||||
"find"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
@@ -107,23 +134,6 @@
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"AdjustFontSizeAction": {
|
||||
"description": "Arguments corresponding to an Adjust Font Size Action",
|
||||
"allOf": [
|
||||
{ "$ref": "#/definitions/ShortcutAction" },
|
||||
{
|
||||
"properties": {
|
||||
"action": { "type": "string", "pattern": "adjustFontSize" },
|
||||
"delta": {
|
||||
"type": "integer",
|
||||
"default": 0,
|
||||
"description": "How much to change the current font point size"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"required": [ "delta" ]
|
||||
},
|
||||
"CopyAction": {
|
||||
"description": "Arguments corresponding to a Copy Text Action",
|
||||
"allOf": [
|
||||
@@ -131,10 +141,10 @@
|
||||
{
|
||||
"properties": {
|
||||
"action": { "type": "string", "pattern": "copy" },
|
||||
"singleLine": {
|
||||
"trimWhitespace": {
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"description": "If true, newlines are removed and whitespace is maintained. If false, whitespace is removed and newlines are maintained."
|
||||
"default": true,
|
||||
"description": "If true, whitespace is removed and newlines are maintained. If false, newlines are removed and whitespace is maintained."
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -215,14 +225,11 @@
|
||||
"$ref": "#/definitions/SplitState",
|
||||
"default": "auto",
|
||||
"description": "The orientation to split the pane in, either vertical (think [|]), horizontal (think [-]), or auto (splits pane based on remaining space)"
|
||||
},
|
||||
"splitMode": {
|
||||
"default": "duplicate",
|
||||
"description": "Control how the pane splits. Only accepts `duplicate` which will duplicate the focused pane's profile into a new pane."
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
],
|
||||
"required": [ "split" ]
|
||||
},
|
||||
"Keybinding": {
|
||||
"additionalProperties": false,
|
||||
@@ -230,15 +237,13 @@
|
||||
"command": {
|
||||
"description": "The action executed when the associated key bindings are pressed.",
|
||||
"oneOf": [
|
||||
{ "$ref": "#/definitions/AdjustFontSizeAction" },
|
||||
{ "$ref": "#/definitions/CopyAction" },
|
||||
{ "$ref": "#/definitions/ShortcutActionName" },
|
||||
{ "$ref": "#/definitions/NewTabAction" },
|
||||
{ "$ref": "#/definitions/SwitchToTabAction" },
|
||||
{ "$ref": "#/definitions/MoveFocusAction" },
|
||||
{ "$ref": "#/definitions/ResizePaneAction" },
|
||||
{ "$ref": "#/definitions/SplitPaneAction" },
|
||||
{ "type": "null" }
|
||||
{ "$ref": "#/definitions/SplitPaneAction" }
|
||||
]
|
||||
},
|
||||
"keys": {
|
||||
@@ -277,11 +282,6 @@
|
||||
"description": "When set to true, a selection is immediately copied to your clipboard upon creation. When set to false, the selection persists and awaits further action.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"copyFormatting": {
|
||||
"default": false,
|
||||
"description": "When set to `true`, the color and font formatting of selected text is also copied to your clipboard. When set to `false`, only plain text is copied to your clipboard.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"defaultProfile": {
|
||||
"$ref": "#/definitions/ProfileGuid",
|
||||
"description": "Sets the default profile. Opens by clicking the '+' icon or typing the key binding assigned to 'newTab'. The guid of the desired default profile is used as the value."
|
||||
@@ -327,7 +327,7 @@
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"theme": {
|
||||
"requestedTheme": {
|
||||
"default": "system",
|
||||
"description": "Sets the theme of the application.",
|
||||
"enum": [
|
||||
@@ -406,7 +406,7 @@
|
||||
},
|
||||
"backgroundImage": {
|
||||
"description": "Sets the file location of the Image to draw over the window background.",
|
||||
"type": ["string", "null"]
|
||||
"type": "string"
|
||||
},
|
||||
"backgroundImageAlignment": {
|
||||
"default": "center",
|
||||
@@ -554,13 +554,14 @@
|
||||
},
|
||||
"cursorColor": {
|
||||
"$ref": "#/definitions/Color",
|
||||
"description": "Sets the cursor color of the profile. Overrides cursor color set in color scheme if colorscheme is set. Uses hex color format: \"#rrggbb\"."
|
||||
"default": "#FFFFFF",
|
||||
"description": "Sets the cursor color for the profile. Uses hex color format: \"#rrggbb\"."
|
||||
},
|
||||
"cursorHeight": {
|
||||
"description": "Sets the percentage height of the cursor starting from the bottom. Only works when cursorShape is set to \"vintage\". Accepts values from 25-100.",
|
||||
"maximum": 100,
|
||||
"minimum": 25,
|
||||
"type": ["integer","null"]
|
||||
"type": "integer"
|
||||
},
|
||||
"cursorShape": {
|
||||
"default": "bar",
|
||||
@@ -579,7 +580,7 @@
|
||||
"type": "boolean"
|
||||
},
|
||||
"fontFace": {
|
||||
"default": "Cascadia Code",
|
||||
"default": "Consolas",
|
||||
"description": "Name of the font face used in the profile.",
|
||||
"type": "string"
|
||||
},
|
||||
@@ -612,7 +613,7 @@
|
||||
},
|
||||
"icon": {
|
||||
"description": "Image file location of the icon used in the profile. Displays within the tab and the dropdown menu.",
|
||||
"type": ["string", "null"]
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"description": "Name of the profile. Displays in the dropdown menu.",
|
||||
@@ -645,7 +646,7 @@
|
||||
},
|
||||
"source": {
|
||||
"description": "Stores the name of the profile generator that originated this profile.",
|
||||
"type": ["string", "null"]
|
||||
"type": "string"
|
||||
},
|
||||
"startingDirectory": {
|
||||
"description": "The directory the shell starts in when it is loaded.",
|
||||
@@ -657,7 +658,7 @@
|
||||
},
|
||||
"tabTitle": {
|
||||
"description": "If set, will replace the name as the title to pass to the shell on startup. Some shells (like bash) may choose to ignore this initial value, while others (cmd, powershell) may use this value over the lifetime of the application.",
|
||||
"type": ["string", "null"]
|
||||
"type": "string"
|
||||
},
|
||||
"useAcrylic": {
|
||||
"default": false,
|
||||
@@ -745,11 +746,6 @@
|
||||
"$ref": "#/definitions/Color",
|
||||
"description": "Sets the color used as ANSI bright yellow."
|
||||
},
|
||||
"cursorColor": {
|
||||
"$ref": "#/definitions/Color",
|
||||
"default": "#FFFFFF",
|
||||
"description": "Sets the cursor color of the color scheme."
|
||||
},
|
||||
"cyan": {
|
||||
"$ref": "#/definitions/Color",
|
||||
"description": "Sets the color used as ANSI cyan."
|
||||
@@ -788,15 +784,37 @@
|
||||
"type": "array"
|
||||
}
|
||||
},
|
||||
"allOf": [
|
||||
{ "$ref": "#/definitions/Globals" },
|
||||
"oneOf": [
|
||||
{
|
||||
"additionalItems": true,
|
||||
"allOf": [
|
||||
{ "$ref": "#/definitions/Globals" },
|
||||
{
|
||||
"additionalItems": true,
|
||||
"properties": {
|
||||
"profiles": {
|
||||
"oneOf": [
|
||||
{ "$ref": "#/definitions/ProfileList" },
|
||||
{ "$ref": "#/definitions/ProfilesObject" }
|
||||
]
|
||||
},
|
||||
"schemes": { "$ref": "#/definitions/SchemeList" }
|
||||
},
|
||||
"required": [
|
||||
"profiles",
|
||||
"schemes",
|
||||
"defaultProfile"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"additionalItems": false,
|
||||
"properties": {
|
||||
"globals": { "$ref": "#/definitions/Globals" },
|
||||
"profiles": {
|
||||
"oneOf": [
|
||||
{ "$ref": "#/definitions/ProfileList" },
|
||||
{ "$ref": "#/definitions/ProfilesObject" }
|
||||
{ "$ref": "#/definitions/ProfileList" },
|
||||
{ "$ref": "#/definitions/ProfilesObject" }
|
||||
]
|
||||
},
|
||||
"schemes": { "$ref": "#/definitions/SchemeList" }
|
||||
@@ -804,7 +822,7 @@
|
||||
"required": [
|
||||
"profiles",
|
||||
"schemes",
|
||||
"defaultProfile"
|
||||
"globals"
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
@@ -1,88 +0,0 @@
|
||||
---
|
||||
author: Kayla Cinnamon @cinnamon-msft
|
||||
created on: 2020-04-01
|
||||
last updated: 2020-04-07
|
||||
issue id: #4191
|
||||
---
|
||||
|
||||
# Formatted Copy
|
||||
|
||||
## Abstract
|
||||
|
||||
When copying text, the Terminal should provide the option of including formatting. Not all apps that receive text allow for picking which format you want when pasting. The default should be to only copy plain text, based on the response from this poll on Twitter.
|
||||
|
||||

|
||||
|
||||
## Solution Proposals
|
||||
|
||||
A proposal for the right click behavior as well as two user settings proposals are described below. The conclusion the team arrived at is at the bottom under the [Conclusions section](#conclusions).
|
||||
|
||||
1. [Settings option 1 - global setting](#settings-option-1---global-setting)
|
||||
2. [Settings option 2 - key binding argument](#settings-option-2---key-binding-argument)
|
||||
3. [Right click behavior](#right-click-behavior)
|
||||
|
||||
### Settings option 1 - global setting
|
||||
|
||||
We could have a global setting that when enabled, would copy formatting to the clipboard on all copy operations.
|
||||
|
||||
### Settings option 2 - key binding argument
|
||||
|
||||
We could add an argument to the `copy` key binding argument to allow for formatted copying when the user chooses to do so.
|
||||
|
||||
### Right click behavior
|
||||
|
||||
By default, right clicking to copy would only copy the plain text.
|
||||
|
||||
## UI/UX Design
|
||||
|
||||
### Settings option 1 - global setting
|
||||
|
||||
a. The user could list which kinds of formats they want included when they copy. When right clicking, they would copy with these formats.
|
||||
|
||||
`"copyFormats": ["html","rtf","plain"]`
|
||||
|
||||
b. We could also just combine html and rtf into a single boolean. Users would either get plain text only (`false`) or all formatting (`true`) onto their clipboard. If this is set to `true`, the default right click behavior is reversed: right clicking copies the formatting.
|
||||
|
||||
`"copyFormatting": true`
|
||||
|
||||
### Settings option 2 - key binding argument
|
||||
|
||||
a. Just like the `trimWhitespace` argument you can add to the `copy` key binding, we could add one for text formatting. This would not change the right click behavior.
|
||||
|
||||
`{"command": {"action": "copy", "keepFormatting": true}, "keys": "ctrl+a"}`
|
||||
|
||||
b. We could also split out the html and rtf formats. The right click behavior would still stay as default.
|
||||
|
||||
`{"command": {"action": "copy", "formats": ["html","rtf","plain"]}, "keys": "ctrl+a"}`
|
||||
|
||||
## Capabilities
|
||||
|
||||
### Accessibility
|
||||
|
||||
This shouldn't affect accessibility.
|
||||
|
||||
### Security
|
||||
|
||||
This does not affect security.
|
||||
|
||||
### Reliability
|
||||
|
||||
This does not affect reliability.
|
||||
|
||||
### Compatibility
|
||||
|
||||
This breaks the existing behavior of always copying the formatting. The justification for breaking this default behavior is in response to the community saying the default should be plain text only.
|
||||
|
||||
### Performance, Power, and Efficiency
|
||||
|
||||
## Potential Issues
|
||||
|
||||
One possible issue is that discovering how to copy the formatting might be difficult to find. We could mitigate this by adding it into the settings.json file and commenting it out.
|
||||
|
||||
## Conclusions
|
||||
|
||||
The team has decided to have plain text as the default copy behavior and to enable formatted copying with a global setting that accepts a boolean value (settings option 1 - global setting, option b). In the future, we can modify this setting to also accept an array, so the user can specify which formats they would like to copy. Additionally, a key binding can be added to allow for greater flexibility.
|
||||
|
||||
## Future considerations
|
||||
|
||||
We could always add an additional option if people want more flexibility. For example, if we ship a global setting now, we could ship a key binding later that lets you choose how you want to copy, and vice versa. Additionally, we can add functionality to the global setting that allows for specific formats or styles to be copied.
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 60 KiB |
@@ -30,7 +30,7 @@ Conhost already has a module for search. It implements case sensitive or insensi
|
||||
|
||||
We will create a `SearchBoxControl` Xaml `UserControl` element. When a search process begins, a `SearchBoxControl` object will be created and attached to `TermControl` root grid. In other words, one SearchBox is added for each `TermControl`. The reasons for this design is:
|
||||
|
||||
1. Each `TermControl` object is a Terminal Window and has a individual text buffer. In phase 1 we are going to search within the current terminal text buffer.
|
||||
1. Each `TermControl` object is a Terminal Window and has a individual text buffer. In phase 1 we are going to search witin the current terminal text buffer.
|
||||
2. If we put the search box under TerminalApp, then the search can only happen on the current focused Terminal.
|
||||
3. If the community does not like the current design, we can lift SearchBox to a higher level.
|
||||
|
||||
|
||||
@@ -92,7 +92,7 @@ would quickly become hard to parse and understand for the user.
|
||||
|
||||
### Proposal 2 - Commands and Parameters
|
||||
|
||||
Instead, we'll try to separate these arguments by their responsibilities. Some
|
||||
Instead, we'll try to seperate these arguments by their responsibilities. Some
|
||||
of these arguments cause something to happen, like `help`, `version`, or
|
||||
`open-settings`. Other arguments act more like modifiers, like for example
|
||||
`--profile` or `--startingDirectory`, which provide additional information to
|
||||
@@ -275,7 +275,7 @@ terminal window.
|
||||
`list-profiles [--all,-A] [--showGuids,-g]`
|
||||
|
||||
Displays a list of each of the available profiles. Each profile displays it's
|
||||
name, separated by newlines.
|
||||
name, seperated by newlines.
|
||||
|
||||
**Parameters**:
|
||||
* `--all,-A`: Show all profiles, including profiles marked `"hidden": true`.
|
||||
@@ -323,7 +323,7 @@ vertically or horizontally.
|
||||
**Parameters**:
|
||||
* `--target,-t target-pane`: Creates a new split in the given `target-pane`.
|
||||
Each pane has a unique index (per-tab) which can be used to identify them.
|
||||
These indices are assigned in the order the panes were created. If omitted,
|
||||
These indicies are assigned in the order the panes were created. If omitted,
|
||||
defaults to the index of the currently focused pane.
|
||||
* `-H`, `-V`: Used to indicate which direction to split the pane. `-V` is
|
||||
"vertically" (think `[|]`), and `-H` is "horizontally" (think `[-]`). If
|
||||
@@ -355,7 +355,7 @@ Moves focus within the currently focused tab to a given pane.
|
||||
|
||||
* `--target,-t target-pane`: moves focus to the given `target-pane`. Each pane
|
||||
has a unique index (per-tab) which can be used to identify them. These
|
||||
indices are assigned in the order the panes were created. If omitted,
|
||||
indicies are assigned in the order the panes were created. If omitted,
|
||||
defaults to the index of the currently focused pane (which is effectively a
|
||||
no-op).
|
||||
|
||||
@@ -410,7 +410,7 @@ like `guid` and `name`, as well as high priority properties to add as arguments.
|
||||
Following an investigation performed the week of Nov 18th, 2019, I've determined
|
||||
that we should be able to use the [CLI11] open-source library to parse
|
||||
our arguments. We'll need to add some additional logic on top of CLI11 in order
|
||||
to properly separate commands with `;`, but that's not impossible to achieve.
|
||||
to properly seperate commands with `;`, but that's not impossible to achieve.
|
||||
|
||||
CLI11 will allow us to parse commandlines as a series of options, with a
|
||||
possible sub-command that takes its own set of parameters. This functionality
|
||||
@@ -507,7 +507,7 @@ runtimeclass TerminalParameters {
|
||||
* [ ] Add a `ShortcutAction` for `FocusPane`, which accepts a single parameter
|
||||
`index`.
|
||||
- We'll need to track each `Pane`'s ID as `Pane`s are created, so that we can
|
||||
quickly switch to the nth `Pane`.
|
||||
quickly switch to the i'th `Pane`.
|
||||
- This is in order to support the `-t,--target` parameter of `split-pane`.
|
||||
|
||||
## Capabilities
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
This doc will hopefully provide a useful guide for adding profiles for common
|
||||
third-party tools to your
|
||||
[settings.json](https://github.com/microsoft/terminal/blob/master/doc/user-docs/UsingJsonSettings.md)
|
||||
[profiles.json](https://github.com/microsoft/terminal/blob/master/doc/user-docs/UsingJsonSettings.md)
|
||||
file.
|
||||
|
||||
All of these profiles are provided _without_ their `guid` set. If you'd like to
|
||||
@@ -30,7 +30,6 @@ Assuming that you've installed cmder into `%CMDER_ROOT%`:
|
||||
{
|
||||
"commandline" : "cmd.exe /k \"%CMDER_ROOT%\\vendor\\init.bat\"",
|
||||
"name" : "cmder",
|
||||
"icon" : "%CMDER_ROOT%/icons/cmder.ico",
|
||||
"startingDirectory" : "%USERPROFILE%"
|
||||
}
|
||||
```
|
||||
@@ -72,48 +71,10 @@ Assuming that you've installed Git Bash into `C:/Program Files/Git`:
|
||||
```json
|
||||
{
|
||||
"name" : "Git Bash",
|
||||
"commandline" : "C:/Program Files/Git/bin/bash.exe -li",
|
||||
"commandline" : "C:/Program Files/Git/bin/bash.exe",
|
||||
"icon" : "C:/Program Files/Git/mingw64/share/git/git-for-windows.ico",
|
||||
"startingDirectory" : "%USERPROFILE%"
|
||||
}
|
||||
````
|
||||
|
||||
## Git Bash (WOW64)
|
||||
|
||||
Assuming that you've installed Git Bash into `C:/Program Files (x86)/Git`:
|
||||
|
||||
```json
|
||||
{
|
||||
"name" : "Git Bash",
|
||||
"commandline" : "%ProgramFiles(x86)%/Git/bin/bash.exe -li",
|
||||
"icon" : "%ProgramFiles(x86)%/Git/mingw32/share/git/git-for-windows.ico",
|
||||
"startingDirectory" : "%USERPROFILE%"
|
||||
}
|
||||
```
|
||||
|
||||
## MSYS2
|
||||
|
||||
Assuming that you've installed MSYS2 into `C:/msys64`:
|
||||
|
||||
```json
|
||||
{
|
||||
"name" : "MSYS2",
|
||||
"commandline" : "C:/msys64/msys2_shell.cmd -defterm -no-start -mingw64",
|
||||
"icon": "C:/msys64/msys2.ico",
|
||||
"startingDirectory" : "C:/msys64/home/user"
|
||||
}
|
||||
````
|
||||
|
||||
## Developer Command Prompt for Visual Studio
|
||||
|
||||
Assuming that you've installed VS 2019 Professional:
|
||||
|
||||
```json
|
||||
{
|
||||
"name" : "Developer Command Prompt for VS 2019",
|
||||
"commandline" : "cmd.exe /k \"C:/Program Files (x86)/Microsoft Visual Studio/2019/Professional/Common7/Tools/VsDevCmd.bat\"",
|
||||
"startingDirectory" : "%USERPROFILE%"
|
||||
}
|
||||
```
|
||||
|
||||
<!-- Adding a tool here? Make sure to add it in alphabetical order! -->
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
# Editing Windows Terminal JSON Settings
|
||||
|
||||
One way (currently the only way) to configure Windows Terminal is by editing the
|
||||
`settings.json` settings file. At the time of writing you can open the settings
|
||||
`profiles.json` settings file. At the time of writing you can open the settings
|
||||
file in your default editor by selecting `Settings` from the WT pull down menu.
|
||||
|
||||
The settings are stored in the file `$env:LocalAppData\Packages\Microsoft.WindowsTerminal_8wekyb3d8bbwe\LocalState\settings.json`.
|
||||
The settings are stored in the file `$env:LocalAppData\Packages\Microsoft.WindowsTerminal_8wekyb3d8bbwe\LocalState\profiles.json`.
|
||||
|
||||
As of [#2515](https://github.com/microsoft/terminal/pull/2515), the settings are
|
||||
split into _two_ files: a hardcoded `defaults.json`, and `settings.json`, which
|
||||
split into _two_ files: a hardcoded `defaults.json`, and `profiles.json`, which
|
||||
contains the user settings. Users should only be concerned with the contents of
|
||||
the `settings.json`, which contains their customizations. The `defaults.json`
|
||||
the `profiles.json`, which contains their customizations. The `defaults.json`
|
||||
file is only provided as a reference of what the default settings are. For more
|
||||
details on how these two files work, see [Settings
|
||||
Layering](#settings-layering). To view the default settings file, click on the
|
||||
@@ -107,22 +107,6 @@ add the following to your keybindings:
|
||||
This will _unbind_ <kbd>Ctrl+Shift+6</kbd>, allowing vim to use the keystroke
|
||||
instead of the terminal.
|
||||
|
||||
### Binding multiple keys
|
||||
|
||||
You can have multiple key chords bound to the same action. To do this, simply
|
||||
add multiple bindings for the same action. For example:
|
||||
|
||||
```json
|
||||
"keybindings" :
|
||||
[
|
||||
{ "command": "copy", "keys": "ctrl+shift+c" },
|
||||
{ "command": "copy", "keys": "ctrl+c" },
|
||||
{ "command": "copy", "keys": "enter" }
|
||||
]
|
||||
```
|
||||
|
||||
In this snippet, all three of <kbd>ctrl+shift+c</kbd>, <kbd>ctrl+c</kbd> and <kbd>enter</kbd> are bound to `copy`.
|
||||
|
||||
## Profiles
|
||||
|
||||
A profile contains the settings applied when a new WT tab is opened. Each
|
||||
@@ -164,7 +148,7 @@ The values for background image stretch mode are documented [here](https://docs.
|
||||
### Hiding a profile
|
||||
|
||||
If you want to remove a profile from the list of profiles in the new tab
|
||||
dropdown, but keep the profile around in your `settings.json` file, you can add
|
||||
dropdown, but keep the profile around in your `profiles.json` file, you can add
|
||||
the property `"hidden": true` to the profile's json. This can also be used to
|
||||
remove the default `cmd` and PowerShell profiles, if the user does not wish to
|
||||
see them.
|
||||
@@ -198,10 +182,10 @@ The runtime settings are actually constructed from _three_ sources:
|
||||
profiles for both Windows PowerShell and Command Prompt (`cmd.exe`).
|
||||
* Dynamic Profiles, which are generated at runtime. These include Powershell
|
||||
Core, the Azure Cloud Shell connector, and profiles for and WSL distros.
|
||||
* The user settings from `settings.json`.
|
||||
* The user settings from `profiles.json`.
|
||||
|
||||
Settings from each of these sources are "layered" upon the settings from
|
||||
previous sources. In this manner, the user settings in `settings.json` can
|
||||
previous sources. In this manner, the user settings in `profiles.json` can
|
||||
contain _only the changes from the default settings_. For example, if a user
|
||||
would like to only change the color scheme of the default `cmd` profile to
|
||||
"Solarized Dark", you could change your cmd profile to the following:
|
||||
@@ -220,19 +204,19 @@ with that GUID will all be treated as the same object. Any changes in that
|
||||
profile will overwrite those from the defaults.
|
||||
|
||||
Similarly, you can overwrite settings from a color scheme by defining a color
|
||||
scheme in `settings.json` with the same name as a default color scheme.
|
||||
scheme in `profiles.json` with the same name as a default color scheme.
|
||||
|
||||
If you'd like to unbind a keystroke that's bound to an action in the default
|
||||
keybindings, you can set the `"command"` to `"unbound"` or `null`. This will
|
||||
allow the keystroke to fallthrough to the commandline application instead of
|
||||
allow the keystroke to fallthough to the commandline application instead of
|
||||
performing the default action.
|
||||
|
||||
### Dynamic Profiles
|
||||
|
||||
When dynamic profiles are created at runtime, they'll be added to the
|
||||
`settings.json` file. You can identify these profiles by the presence of a
|
||||
`profiles.json` file. You can identify these profiles by the presence of a
|
||||
`"source"` property. These profiles are tied to their source - if you uninstall
|
||||
a linux distro, then the profile will remain in your `settings.json` file, but
|
||||
a linux distro, then the profile will remain in your `profiles.json` file, but
|
||||
the profile will be hidden.
|
||||
|
||||
The Windows Terminal uses the `guid` property of these dynamically-generated
|
||||
@@ -246,7 +230,7 @@ like to hide all the WSL profiles, you could add the following setting:
|
||||
|
||||
```json
|
||||
|
||||
"disabledProfileSources": ["Windows.Terminal.WSL"],
|
||||
"disabledProfileSources": ["Microsoft.Terminal.WSL"],
|
||||
...
|
||||
|
||||
```
|
||||
@@ -371,7 +355,7 @@ In the above settings, the `"fontFace"` in the `cmd.exe` profile overrides the
|
||||
1. Download the [Debian JPG logo](https://www.debian.org/logos/openlogo-100.jpg)
|
||||
2. Put the image in the
|
||||
`$env:LocalAppData\Packages\Microsoft.WindowsTerminal_<randomString>\LocalState\`
|
||||
directory (same directory as your `settings.json` file).
|
||||
directory (same directory as your `profiles.json` file).
|
||||
|
||||
__NOTE__: You can put the image anywhere you like, the above suggestion happens to be convenient.
|
||||
3. Open your WT json properties file.
|
||||
@@ -392,7 +376,7 @@ Notes:
|
||||
|
||||
1. You will need to experiment with different color settings
|
||||
and schemes to make your terminal text visible on top of your image
|
||||
2. If you store the image in the UWP directory (the same directory as your settings.json file),
|
||||
2. If you store the image in the UWP directory (the same directory as your profiles.json file),
|
||||
then you should use the URI style path name given in the above example.
|
||||
More information about UWP URI schemes [here](https://docs.microsoft.com/en-us/windows/uwp/app-resources/uri-schemes).
|
||||
3. Instead of using a UWP URI you can use a:
|
||||
@@ -414,7 +398,7 @@ following objects into your `globals.keybindings` array:
|
||||
{ "command": "paste", "keys": ["ctrl+shift+v"] }
|
||||
```
|
||||
|
||||
> 👉 **Note**: you can also add a keybinding for the `copy` command with the argument `"trimWhitespace": true`. This removes newlines as the text is copied to your clipboard.
|
||||
> 👉 **Note**: you can also add a keybinding for the `copyTextWithoutNewlines` command. This removes newlines as the text is copied to your clipboard.
|
||||
|
||||
This will add copy and paste on <kbd>ctrl+shift+c</kbd>
|
||||
and <kbd>ctrl+shift+v</kbd> respectively.
|
||||
|
||||
@@ -65,7 +65,7 @@ Not currently supported "out of the box". See issue [#1060](https://github.com/m
|
||||
|
||||
## Configuring Windows Terminal
|
||||
|
||||
All Windows Terminal settings are currently managed using the `settings.json` file, located within `$env:LocalAppData\Packages\Microsoft.WindowsTerminal_8wekyb3d8bbwe/LocalState`.
|
||||
All Windows Terminal settings are currently managed using the `profiles.json` file, located within `$env:LocalAppData\Packages\Microsoft.WindowsTerminal_8wekyb3d8bbwe/LocalState`.
|
||||
|
||||
To open the settings file from Windows Terminal:
|
||||
|
||||
@@ -73,7 +73,7 @@ To open the settings file from Windows Terminal:
|
||||
2. From the dropdown list, click `Settings`. You can also use a shortcut: <kbd>Ctrl</kbd>+<kbd>,</kbd>.
|
||||
3. Your default `json` editor will open the settings file.
|
||||
|
||||
For an introduction to the various settings, see [Using Json Settings](UsingJsonSettings.md). The list of valid settings can be found in the [settings.json documentation](../cascadia/SettingsSchema.md) section.
|
||||
For an introduction to the various settings, see [Using Json Settings](UsingJsonSettings.md). The list of valid settings can be found in the [profiles.json documentation](../cascadia/SettingsSchema.md) section.
|
||||
|
||||
## Tips and Tricks
|
||||
|
||||
|
||||
@@ -64,7 +64,7 @@ OutputCellIterator::OutputCellIterator(const wchar_t& wch, const TextAttribute&
|
||||
// Routine Description:
|
||||
// - This is a fill-mode iterator for one particular CHAR_INFO. It will repeat forever if fillLimit is 0.
|
||||
// Arguments:
|
||||
// - charInfo - The legacy character and color data to use for filling (uses Unicode portion of text data)
|
||||
// - charInfo - The legacy character and color data to use for fililng (uses Unicode portion of text data)
|
||||
// - fillLimit - How many times to allow this value to be viewed/filled. Infinite if 0.
|
||||
OutputCellIterator::OutputCellIterator(const CHAR_INFO& charInfo, const size_t fillLimit) noexcept :
|
||||
_mode(Mode::Fill),
|
||||
|
||||
@@ -31,7 +31,7 @@ public:
|
||||
RowCellIterator(const ROW& row, const size_t start, const size_t length);
|
||||
~RowCellIterator() = default;
|
||||
|
||||
RowCellIterator& operator=(const RowCellIterator& it) = delete;
|
||||
RowCellIterator& operator=(const RowCellIterator& it) = default;
|
||||
|
||||
operator bool() const noexcept;
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ public:
|
||||
Cursor& operator=(const Cursor&) & = delete;
|
||||
|
||||
Cursor(Cursor&&) = default;
|
||||
Cursor& operator=(Cursor&&) & = delete;
|
||||
Cursor& operator=(Cursor&&) & = default;
|
||||
|
||||
bool HasMoved() const noexcept;
|
||||
bool IsVisible() const noexcept;
|
||||
|
||||
@@ -1260,94 +1260,6 @@ bool TextBuffer::MoveToPreviousWord(COORD& pos, std::wstring_view wordDelimiters
|
||||
return true;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Update pos to be the beginning of the current glyph/character. This is used for accessibility
|
||||
// Arguments:
|
||||
// - pos - a COORD on the word you are currently on
|
||||
// Return Value:
|
||||
// - pos - The COORD for the first cell of the current glyph (inclusive)
|
||||
const til::point TextBuffer::GetGlyphStart(const til::point pos) const
|
||||
{
|
||||
COORD resultPos = pos;
|
||||
|
||||
const auto bufferSize = GetSize();
|
||||
if (resultPos != bufferSize.EndExclusive() && GetCellDataAt(resultPos)->DbcsAttr().IsTrailing())
|
||||
{
|
||||
bufferSize.DecrementInBounds(resultPos, true);
|
||||
}
|
||||
|
||||
return resultPos;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Update pos to be the end of the current glyph/character. This is used for accessibility
|
||||
// Arguments:
|
||||
// - pos - a COORD on the word you are currently on
|
||||
// Return Value:
|
||||
// - pos - The COORD for the last cell of the current glyph (exclusive)
|
||||
const til::point TextBuffer::GetGlyphEnd(const til::point pos) const
|
||||
{
|
||||
COORD resultPos = pos;
|
||||
|
||||
const auto bufferSize = GetSize();
|
||||
if (resultPos != bufferSize.EndExclusive() && GetCellDataAt(resultPos)->DbcsAttr().IsLeading())
|
||||
{
|
||||
bufferSize.IncrementInBounds(resultPos, true);
|
||||
}
|
||||
|
||||
// increment one more time to become exclusive
|
||||
bufferSize.IncrementInBounds(resultPos, true);
|
||||
return resultPos;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Update pos to be the beginning of the next glyph/character. This is used for accessibility
|
||||
// Arguments:
|
||||
// - pos - a COORD on the word you are currently on
|
||||
// - allowBottomExclusive - allow the nonexistent end-of-buffer cell to be encountered
|
||||
// Return Value:
|
||||
// - true, if successfully updated pos. False, if we are unable to move (usually due to a buffer boundary)
|
||||
// - pos - The COORD for the first cell of the current glyph (inclusive)
|
||||
bool TextBuffer::MoveToNextGlyph(til::point& pos, bool allowBottomExclusive) const
|
||||
{
|
||||
COORD resultPos = pos;
|
||||
|
||||
// try to move. If we can't, we're done.
|
||||
const auto bufferSize = GetSize();
|
||||
const bool success = bufferSize.IncrementInBounds(resultPos, allowBottomExclusive);
|
||||
if (resultPos != bufferSize.EndExclusive() && GetCellDataAt(resultPos)->DbcsAttr().IsTrailing())
|
||||
{
|
||||
bufferSize.IncrementInBounds(resultPos, allowBottomExclusive);
|
||||
}
|
||||
|
||||
pos = resultPos;
|
||||
return success;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Update pos to be the beginning of the previous glyph/character. This is used for accessibility
|
||||
// Arguments:
|
||||
// - pos - a COORD on the word you are currently on
|
||||
// - allowBottomExclusive - allow the nonexistent end-of-buffer cell to be encountered
|
||||
// Return Value:
|
||||
// - true, if successfully updated pos. False, if we are unable to move (usually due to a buffer boundary)
|
||||
// - pos - The COORD for the first cell of the previous glyph (inclusive)
|
||||
bool TextBuffer::MoveToPreviousGlyph(til::point& pos, bool allowBottomExclusive) const
|
||||
{
|
||||
COORD resultPos = pos;
|
||||
|
||||
// try to move. If we can't, we're done.
|
||||
const auto bufferSize = GetSize();
|
||||
const bool success = bufferSize.DecrementInBounds(resultPos, allowBottomExclusive);
|
||||
if (resultPos != bufferSize.EndExclusive() && GetCellDataAt(resultPos)->DbcsAttr().IsLeading())
|
||||
{
|
||||
bufferSize.DecrementInBounds(resultPos, allowBottomExclusive);
|
||||
}
|
||||
|
||||
pos = resultPos;
|
||||
return success;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Determines the line-by-line rectangles based on two COORDs
|
||||
// - expands the rectangles to support wide glyphs
|
||||
|
||||
@@ -134,11 +134,6 @@ public:
|
||||
bool MoveToNextWord(COORD& pos, const std::wstring_view wordDelimiters, COORD lastCharPos) const;
|
||||
bool MoveToPreviousWord(COORD& pos, const std::wstring_view wordDelimiters) const;
|
||||
|
||||
const til::point GetGlyphStart(const til::point pos) const;
|
||||
const til::point GetGlyphEnd(const til::point pos) const;
|
||||
bool MoveToNextGlyph(til::point& pos, bool allowBottomExclusive = false) const;
|
||||
bool MoveToPreviousGlyph(til::point& pos, bool allowBottomExclusive = false) const;
|
||||
|
||||
const std::vector<SMALL_RECT> GetTextRects(COORD start, COORD end, bool blockSelection = false) const;
|
||||
|
||||
class TextAndColor
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
<!-- Resources -->
|
||||
<!-- This resw only defines things that are used in this package's AppxManifest,
|
||||
so it's not in the common resource items. -->
|
||||
<PRIResource Include="Resources\*\Resources.resw" />
|
||||
<PRIResource Include="Resources\Resources.language-en.resw" />
|
||||
<PRIResource Include="Resources\Resources.resw" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup Condition="'$(WindowsTerminalReleaseBuild)'!='true'">
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
Version="1.0.0.0" />
|
||||
|
||||
<Properties>
|
||||
<DisplayName>Windows Terminal</DisplayName>
|
||||
<DisplayName>ms-resource:AppName</DisplayName>
|
||||
<PublisherDisplayName>Microsoft Corporation</PublisherDisplayName>
|
||||
<Logo>Images\StoreLogo.png</Logo>
|
||||
</Properties>
|
||||
|
||||
@@ -100,7 +100,6 @@ namespace TerminalAppLocalTests
|
||||
"foreground": "#000000",
|
||||
"background": "#010101",
|
||||
"selectionBackground": "#010100",
|
||||
"cursorColor": "#010001",
|
||||
"red": "#010000",
|
||||
"green": "#000100",
|
||||
"blue": "#000001"
|
||||
@@ -110,7 +109,6 @@ namespace TerminalAppLocalTests
|
||||
"foreground": "#020202",
|
||||
"background": "#030303",
|
||||
"selectionBackground": "#020200",
|
||||
"cursorColor": "#040004",
|
||||
"red": "#020000",
|
||||
|
||||
"blue": "#000002"
|
||||
@@ -120,7 +118,6 @@ namespace TerminalAppLocalTests
|
||||
"foreground": "#040404",
|
||||
"background": "#050505",
|
||||
"selectionBackground": "#030300",
|
||||
"cursorColor": "#060006",
|
||||
"red": "#030000",
|
||||
"green": "#000300"
|
||||
})" };
|
||||
@@ -133,8 +130,8 @@ namespace TerminalAppLocalTests
|
||||
VERIFY_ARE_EQUAL(L"scheme0", scheme0._schemeName);
|
||||
VERIFY_ARE_EQUAL(ARGB(0, 0, 0, 0), scheme0._defaultForeground);
|
||||
VERIFY_ARE_EQUAL(ARGB(0, 1, 1, 1), scheme0._defaultBackground);
|
||||
VERIFY_ARE_EQUAL(ARGB(0, 1, 1, 1), scheme0._defaultBackground);
|
||||
VERIFY_ARE_EQUAL(ARGB(0, 1, 1, 0), scheme0._selectionBackground);
|
||||
VERIFY_ARE_EQUAL(ARGB(0, 1, 0, 1), scheme0._cursorColor);
|
||||
VERIFY_ARE_EQUAL(ARGB(0, 1, 0, 0), scheme0._table[XTERM_RED_ATTR]);
|
||||
VERIFY_ARE_EQUAL(ARGB(0, 0, 1, 0), scheme0._table[XTERM_GREEN_ATTR]);
|
||||
VERIFY_ARE_EQUAL(ARGB(0, 0, 0, 1), scheme0._table[XTERM_BLUE_ATTR]);
|
||||
@@ -146,7 +143,6 @@ namespace TerminalAppLocalTests
|
||||
VERIFY_ARE_EQUAL(ARGB(0, 2, 2, 2), scheme0._defaultForeground);
|
||||
VERIFY_ARE_EQUAL(ARGB(0, 3, 3, 3), scheme0._defaultBackground);
|
||||
VERIFY_ARE_EQUAL(ARGB(0, 2, 2, 0), scheme0._selectionBackground);
|
||||
VERIFY_ARE_EQUAL(ARGB(0, 4, 0, 4), scheme0._cursorColor);
|
||||
VERIFY_ARE_EQUAL(ARGB(0, 2, 0, 0), scheme0._table[XTERM_RED_ATTR]);
|
||||
VERIFY_ARE_EQUAL(ARGB(0, 0, 1, 0), scheme0._table[XTERM_GREEN_ATTR]);
|
||||
VERIFY_ARE_EQUAL(ARGB(0, 0, 0, 2), scheme0._table[XTERM_BLUE_ATTR]);
|
||||
@@ -158,7 +154,6 @@ namespace TerminalAppLocalTests
|
||||
VERIFY_ARE_EQUAL(ARGB(0, 4, 4, 4), scheme0._defaultForeground);
|
||||
VERIFY_ARE_EQUAL(ARGB(0, 5, 5, 5), scheme0._defaultBackground);
|
||||
VERIFY_ARE_EQUAL(ARGB(0, 3, 3, 0), scheme0._selectionBackground);
|
||||
VERIFY_ARE_EQUAL(ARGB(0, 6, 0, 6), scheme0._cursorColor);
|
||||
VERIFY_ARE_EQUAL(ARGB(0, 3, 0, 0), scheme0._table[XTERM_RED_ATTR]);
|
||||
VERIFY_ARE_EQUAL(ARGB(0, 0, 3, 0), scheme0._table[XTERM_GREEN_ATTR]);
|
||||
VERIFY_ARE_EQUAL(ARGB(0, 0, 0, 2), scheme0._table[XTERM_BLUE_ATTR]);
|
||||
|
||||
@@ -590,7 +590,7 @@ namespace TerminalAppLocalTests
|
||||
VERIFY_IS_NOT_NULL(actionAndArgs.Args());
|
||||
auto myArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
|
||||
VERIFY_IS_NOT_NULL(myArgs);
|
||||
VERIFY_ARE_EQUAL(SplitState::Automatic, myArgs.SplitStyle());
|
||||
VERIFY_ARE_EQUAL(SplitState::Vertical, myArgs.SplitStyle());
|
||||
VERIFY_IS_NOT_NULL(myArgs.TerminalArgs());
|
||||
}
|
||||
{
|
||||
@@ -650,7 +650,7 @@ namespace TerminalAppLocalTests
|
||||
VERIFY_IS_NOT_NULL(actionAndArgs.Args());
|
||||
auto myArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
|
||||
VERIFY_IS_NOT_NULL(myArgs);
|
||||
VERIFY_ARE_EQUAL(SplitState::Automatic, myArgs.SplitStyle());
|
||||
VERIFY_ARE_EQUAL(SplitState::Vertical, myArgs.SplitStyle());
|
||||
VERIFY_IS_NOT_NULL(myArgs.TerminalArgs());
|
||||
VERIFY_IS_FALSE(myArgs.TerminalArgs().Commandline().empty());
|
||||
VERIFY_IS_TRUE(myArgs.TerminalArgs().StartingDirectory().empty());
|
||||
@@ -704,7 +704,7 @@ namespace TerminalAppLocalTests
|
||||
VERIFY_IS_NOT_NULL(actionAndArgs.Args());
|
||||
auto myArgs = actionAndArgs.Args().try_as<SplitPaneArgs>();
|
||||
VERIFY_IS_NOT_NULL(myArgs);
|
||||
VERIFY_ARE_EQUAL(SplitState::Automatic, myArgs.SplitStyle());
|
||||
VERIFY_ARE_EQUAL(SplitState::Vertical, myArgs.SplitStyle());
|
||||
VERIFY_IS_NOT_NULL(myArgs.TerminalArgs());
|
||||
VERIFY_IS_FALSE(myArgs.TerminalArgs().Commandline().empty());
|
||||
VERIFY_IS_TRUE(myArgs.TerminalArgs().StartingDirectory().empty());
|
||||
|
||||
@@ -170,18 +170,21 @@ namespace TerminalAppLocalTests
|
||||
{
|
||||
const std::string bindings0String{ R"([
|
||||
{ "command": "copy", "keys": ["ctrl+c"] },
|
||||
{ "command": { "action": "copy", "singleLine": false }, "keys": ["ctrl+shift+c"] },
|
||||
{ "command": { "action": "copy", "singleLine": true }, "keys": ["alt+shift+c"] },
|
||||
{ "command": "copyTextWithoutNewlines", "keys": ["alt+c"] },
|
||||
{ "command": { "action": "copy", "trimWhitespace": false }, "keys": ["ctrl+shift+c"] },
|
||||
{ "command": { "action": "copy", "trimWhitespace": true }, "keys": ["alt+shift+c"] },
|
||||
|
||||
{ "command": "newTab", "keys": ["ctrl+t"] },
|
||||
{ "command": { "action": "newTab", "index": 0 }, "keys": ["ctrl+shift+t"] },
|
||||
{ "command": "newTabProfile0", "keys": ["alt+shift+t"] },
|
||||
{ "command": { "action": "newTab", "index": 11 }, "keys": ["ctrl+shift+y"] },
|
||||
{ "command": "newTabProfile8", "keys": ["alt+shift+y"] },
|
||||
|
||||
{ "command": { "action": "copy", "madeUpBool": true }, "keys": ["ctrl+b"] },
|
||||
{ "command": { "action": "copy" }, "keys": ["ctrl+shift+b"] },
|
||||
|
||||
{ "command": { "action": "adjustFontSize", "delta": 1 }, "keys": ["ctrl+f"] },
|
||||
{ "command": { "action": "adjustFontSize", "delta": -1 }, "keys": ["ctrl+g"] }
|
||||
{ "command": "increaseFontSize", "keys": ["ctrl+f"] },
|
||||
{ "command": "decreaseFontSize", "keys": ["ctrl+g"] }
|
||||
|
||||
])" };
|
||||
|
||||
@@ -191,17 +194,28 @@ namespace TerminalAppLocalTests
|
||||
VERIFY_IS_NOT_NULL(appKeyBindings);
|
||||
VERIFY_ARE_EQUAL(0u, appKeyBindings->_keyShortcuts.size());
|
||||
appKeyBindings->LayerJson(bindings0Json);
|
||||
VERIFY_ARE_EQUAL(10u, appKeyBindings->_keyShortcuts.size());
|
||||
VERIFY_ARE_EQUAL(13u, appKeyBindings->_keyShortcuts.size());
|
||||
|
||||
{
|
||||
Log::Comment(NoThrowString().Format(
|
||||
L"Verify that `copy` without args parses as Copy(SingleLine=false)"));
|
||||
L"Verify that `copy` without args parses as Copy(TrimWhitespace=true)"));
|
||||
KeyChord kc{ true, false, false, static_cast<int32_t>('C') };
|
||||
auto actionAndArgs = TestUtils::GetActionAndArgs(*appKeyBindings, kc);
|
||||
const auto& realArgs = actionAndArgs.Args().try_as<CopyTextArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
// Verify the args have the expected value
|
||||
VERIFY_IS_FALSE(realArgs.SingleLine());
|
||||
VERIFY_IS_TRUE(realArgs.TrimWhitespace());
|
||||
}
|
||||
|
||||
{
|
||||
Log::Comment(NoThrowString().Format(
|
||||
L"Verify that `copyTextWithoutNewlines` parses as Copy(TrimWhitespace=false)"));
|
||||
KeyChord kc{ false, true, false, static_cast<int32_t>('C') };
|
||||
auto actionAndArgs = TestUtils::GetActionAndArgs(*appKeyBindings, kc);
|
||||
const auto& realArgs = actionAndArgs.Args().try_as<CopyTextArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
// Verify the args have the expected value
|
||||
VERIFY_IS_FALSE(realArgs.TrimWhitespace());
|
||||
}
|
||||
|
||||
{
|
||||
@@ -212,7 +226,7 @@ namespace TerminalAppLocalTests
|
||||
const auto& realArgs = actionAndArgs.Args().try_as<CopyTextArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
// Verify the args have the expected value
|
||||
VERIFY_IS_FALSE(realArgs.SingleLine());
|
||||
VERIFY_IS_FALSE(realArgs.TrimWhitespace());
|
||||
}
|
||||
|
||||
{
|
||||
@@ -223,7 +237,7 @@ namespace TerminalAppLocalTests
|
||||
const auto& realArgs = actionAndArgs.Args().try_as<CopyTextArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
// Verify the args have the expected value
|
||||
VERIFY_IS_TRUE(realArgs.SingleLine());
|
||||
VERIFY_IS_TRUE(realArgs.TrimWhitespace());
|
||||
}
|
||||
|
||||
{
|
||||
@@ -251,6 +265,19 @@ namespace TerminalAppLocalTests
|
||||
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs().ProfileIndex());
|
||||
VERIFY_ARE_EQUAL(0, realArgs.TerminalArgs().ProfileIndex().Value());
|
||||
}
|
||||
{
|
||||
Log::Comment(NoThrowString().Format(
|
||||
L"Verify that `newTabProfile0` parses as NewTab(Index=0)"));
|
||||
KeyChord kc{ false, true, true, static_cast<int32_t>('T') };
|
||||
auto actionAndArgs = TestUtils::GetActionAndArgs(*appKeyBindings, kc);
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::NewTabProfile0, actionAndArgs.Action());
|
||||
const auto& realArgs = actionAndArgs.Args().try_as<NewTabArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
// Verify the args have the expected value
|
||||
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
|
||||
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs().ProfileIndex());
|
||||
VERIFY_ARE_EQUAL(0, realArgs.TerminalArgs().ProfileIndex().Value());
|
||||
}
|
||||
{
|
||||
Log::Comment(NoThrowString().Format(
|
||||
L"Verify that `newTab` with an index greater than the legacy "
|
||||
@@ -265,6 +292,19 @@ namespace TerminalAppLocalTests
|
||||
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs().ProfileIndex());
|
||||
VERIFY_ARE_EQUAL(11, realArgs.TerminalArgs().ProfileIndex().Value());
|
||||
}
|
||||
{
|
||||
Log::Comment(NoThrowString().Format(
|
||||
L"Verify that `newTabProfile8` parses as NewTab(Index=8)"));
|
||||
KeyChord kc{ false, true, true, static_cast<int32_t>('Y') };
|
||||
auto actionAndArgs = TestUtils::GetActionAndArgs(*appKeyBindings, kc);
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::NewTabProfile8, actionAndArgs.Action());
|
||||
const auto& realArgs = actionAndArgs.Args().try_as<NewTabArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
// Verify the args have the expected value
|
||||
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs());
|
||||
VERIFY_IS_NOT_NULL(realArgs.TerminalArgs().ProfileIndex());
|
||||
VERIFY_ARE_EQUAL(8, realArgs.TerminalArgs().ProfileIndex().Value());
|
||||
}
|
||||
|
||||
{
|
||||
Log::Comment(NoThrowString().Format(
|
||||
@@ -275,7 +315,7 @@ namespace TerminalAppLocalTests
|
||||
const auto& realArgs = actionAndArgs.Args().try_as<CopyTextArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
// Verify the args have the expected value
|
||||
VERIFY_IS_FALSE(realArgs.SingleLine());
|
||||
VERIFY_IS_TRUE(realArgs.TrimWhitespace());
|
||||
}
|
||||
|
||||
{
|
||||
@@ -287,15 +327,15 @@ namespace TerminalAppLocalTests
|
||||
const auto& realArgs = actionAndArgs.Args().try_as<CopyTextArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
// Verify the args have the expected value
|
||||
VERIFY_IS_FALSE(realArgs.SingleLine());
|
||||
VERIFY_IS_TRUE(realArgs.TrimWhitespace());
|
||||
}
|
||||
|
||||
{
|
||||
Log::Comment(NoThrowString().Format(
|
||||
L"Verify that `adjustFontSize` with a positive delta parses args correctly"));
|
||||
L"Verify that `increaseFontSize` without args parses as AdjustFontSize(Delta=1)"));
|
||||
KeyChord kc{ true, false, false, static_cast<int32_t>('F') };
|
||||
auto actionAndArgs = TestUtils::GetActionAndArgs(*appKeyBindings, kc);
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::AdjustFontSize, actionAndArgs.Action());
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::IncreaseFontSize, actionAndArgs.Action());
|
||||
const auto& realArgs = actionAndArgs.Args().try_as<AdjustFontSizeArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
// Verify the args have the expected value
|
||||
@@ -304,10 +344,10 @@ namespace TerminalAppLocalTests
|
||||
|
||||
{
|
||||
Log::Comment(NoThrowString().Format(
|
||||
L"Verify that `adjustFontSize` with a negative delta parses args correctly"));
|
||||
L"Verify that `decreaseFontSize` without args parses as AdjustFontSize(Delta=-1)"));
|
||||
KeyChord kc{ true, false, false, static_cast<int32_t>('G') };
|
||||
auto actionAndArgs = TestUtils::GetActionAndArgs(*appKeyBindings, kc);
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::AdjustFontSize, actionAndArgs.Action());
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::DecreaseFontSize, actionAndArgs.Action());
|
||||
const auto& realArgs = actionAndArgs.Args().try_as<AdjustFontSizeArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
// Verify the args have the expected value
|
||||
@@ -318,6 +358,8 @@ namespace TerminalAppLocalTests
|
||||
void KeyBindingsTests::TestSplitPaneArgs()
|
||||
{
|
||||
const std::string bindings0String{ R"([
|
||||
{ "keys": ["ctrl+a"], "command": "splitVertical" },
|
||||
{ "keys": ["ctrl+b"], "command": "splitHorizontal" },
|
||||
{ "keys": ["ctrl+c"], "command": { "action": "splitPane", "split": null } },
|
||||
{ "keys": ["ctrl+d"], "command": { "action": "splitPane", "split": "vertical" } },
|
||||
{ "keys": ["ctrl+e"], "command": { "action": "splitPane", "split": "horizontal" } },
|
||||
@@ -333,8 +375,26 @@ namespace TerminalAppLocalTests
|
||||
VERIFY_IS_NOT_NULL(appKeyBindings);
|
||||
VERIFY_ARE_EQUAL(0u, appKeyBindings->_keyShortcuts.size());
|
||||
appKeyBindings->LayerJson(bindings0Json);
|
||||
VERIFY_ARE_EQUAL(7u, appKeyBindings->_keyShortcuts.size());
|
||||
VERIFY_ARE_EQUAL(9u, appKeyBindings->_keyShortcuts.size());
|
||||
|
||||
{
|
||||
KeyChord kc{ true, false, false, static_cast<int32_t>('A') };
|
||||
auto actionAndArgs = TestUtils::GetActionAndArgs(*appKeyBindings, kc);
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::SplitVertical, 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());
|
||||
}
|
||||
{
|
||||
KeyChord kc{ true, false, false, static_cast<int32_t>('B') };
|
||||
auto actionAndArgs = TestUtils::GetActionAndArgs(*appKeyBindings, kc);
|
||||
VERIFY_ARE_EQUAL(ShortcutAction::SplitHorizontal, 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());
|
||||
}
|
||||
{
|
||||
KeyChord kc{ true, false, false, static_cast<int32_t>('C') };
|
||||
auto actionAndArgs = TestUtils::GetActionAndArgs(*appKeyBindings, kc);
|
||||
@@ -342,7 +402,7 @@ namespace TerminalAppLocalTests
|
||||
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::Automatic, realArgs.SplitStyle());
|
||||
VERIFY_ARE_EQUAL(winrt::TerminalApp::SplitState::None, realArgs.SplitStyle());
|
||||
}
|
||||
{
|
||||
KeyChord kc{ true, false, false, static_cast<int32_t>('D') };
|
||||
@@ -369,7 +429,7 @@ namespace TerminalAppLocalTests
|
||||
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::Automatic, realArgs.SplitStyle());
|
||||
VERIFY_ARE_EQUAL(winrt::TerminalApp::SplitState::None, realArgs.SplitStyle());
|
||||
}
|
||||
{
|
||||
KeyChord kc{ true, false, false, static_cast<int32_t>('G') };
|
||||
@@ -378,7 +438,7 @@ namespace TerminalAppLocalTests
|
||||
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::Automatic, realArgs.SplitStyle());
|
||||
VERIFY_ARE_EQUAL(winrt::TerminalApp::SplitState::None, realArgs.SplitStyle());
|
||||
}
|
||||
{
|
||||
KeyChord kc{ true, false, false, static_cast<int32_t>('H') };
|
||||
@@ -396,7 +456,7 @@ namespace TerminalAppLocalTests
|
||||
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::Automatic, realArgs.SplitStyle());
|
||||
VERIFY_ARE_EQUAL(winrt::TerminalApp::SplitState::None, realArgs.SplitStyle());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -420,7 +480,7 @@ namespace TerminalAppLocalTests
|
||||
const auto& realArgs = actionAndArgs.Args().try_as<CopyTextArgs>();
|
||||
VERIFY_IS_NOT_NULL(realArgs);
|
||||
// Verify the args have the expected value
|
||||
VERIFY_IS_FALSE(realArgs.SingleLine());
|
||||
VERIFY_IS_TRUE(realArgs.TrimWhitespace());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,6 +56,8 @@ namespace TerminalAppLocalTests
|
||||
TEST_METHOD(TestInvalidColorSchemeName);
|
||||
TEST_METHOD(TestHelperFunctions);
|
||||
|
||||
TEST_METHOD(TestLayerGlobalsOnRoot);
|
||||
|
||||
TEST_METHOD(TestProfileIconWithEnvVar);
|
||||
TEST_METHOD(TestProfileBackgroundImageWithEnvVar);
|
||||
|
||||
@@ -68,12 +70,6 @@ namespace TerminalAppLocalTests
|
||||
|
||||
TEST_METHOD(TestTerminalArgsForBinding);
|
||||
|
||||
TEST_METHOD(FindMissingProfile);
|
||||
TEST_METHOD(MakeSettingsForProfileThatDoesntExist);
|
||||
TEST_METHOD(MakeSettingsForDefaultProfileThatDoesntExist);
|
||||
|
||||
TEST_METHOD(TestLayerProfileOnColorScheme);
|
||||
|
||||
TEST_METHOD(ValidateKeybindingsWarnings);
|
||||
|
||||
TEST_CLASS_SETUP(ClassSetup)
|
||||
@@ -158,7 +154,9 @@ namespace TerminalAppLocalTests
|
||||
{
|
||||
const std::string goodProfiles{ R"(
|
||||
{
|
||||
"defaultProfile": "{6239a42c-1111-49a3-80bd-e8fdd045185c}",
|
||||
"globals": {
|
||||
"defaultProfile": "{6239a42c-1111-49a3-80bd-e8fdd045185c}"
|
||||
},
|
||||
"profiles": [
|
||||
{
|
||||
"name" : "profile0",
|
||||
@@ -173,7 +171,9 @@ namespace TerminalAppLocalTests
|
||||
|
||||
const std::string badProfiles{ R"(
|
||||
{
|
||||
"defaultProfile": "{6239a42c-1111-49a3-80bd-e8fdd045185c}",
|
||||
"globals": {
|
||||
"defaultProfile": "{6239a42c-1111-49a3-80bd-e8fdd045185c}"
|
||||
},
|
||||
"profiles": [
|
||||
{
|
||||
"name" : "profile0",
|
||||
@@ -188,7 +188,9 @@ namespace TerminalAppLocalTests
|
||||
|
||||
const std::string noDefaultAtAll{ R"(
|
||||
{
|
||||
"alwaysShowTabs": true,
|
||||
"globals": {
|
||||
"alwaysShowTabs": true
|
||||
},
|
||||
"profiles": [
|
||||
{
|
||||
"name" : "profile0",
|
||||
@@ -380,7 +382,9 @@ namespace TerminalAppLocalTests
|
||||
{
|
||||
const std::string badProfiles{ R"(
|
||||
{
|
||||
"defaultProfile": "{6239a42c-1111-49a3-80bd-e8fdd045185c}",
|
||||
"globals": {
|
||||
"defaultProfile": "{6239a42c-1111-49a3-80bd-e8fdd045185c}"
|
||||
},
|
||||
"profiles": [
|
||||
{
|
||||
"name" : "profile0",
|
||||
@@ -428,17 +432,21 @@ namespace TerminalAppLocalTests
|
||||
{
|
||||
const std::string settings0String{ R"(
|
||||
{
|
||||
"alwaysShowTabs": true,
|
||||
"initialCols" : 120,
|
||||
"initialRows" : 30,
|
||||
"rowsToScroll" : 4
|
||||
"globals": {
|
||||
"alwaysShowTabs": true,
|
||||
"initialCols" : 120,
|
||||
"initialRows" : 30,
|
||||
"rowsToScroll" : 4
|
||||
}
|
||||
})" };
|
||||
const std::string settings1String{ R"(
|
||||
{
|
||||
"showTabsInTitlebar": false,
|
||||
"initialCols" : 240,
|
||||
"initialRows" : 60,
|
||||
"rowsToScroll" : 8
|
||||
"globals": {
|
||||
"showTabsInTitlebar": false,
|
||||
"initialCols" : 240,
|
||||
"initialRows" : 60,
|
||||
"rowsToScroll" : 8
|
||||
}
|
||||
})" };
|
||||
const auto settings0Json = VerifyParseSucceeded(settings0String);
|
||||
const auto settings1Json = VerifyParseSucceeded(settings1String);
|
||||
@@ -1334,6 +1342,114 @@ namespace TerminalAppLocalTests
|
||||
VERIFY_ARE_EQUAL(name2, prof2->GetName());
|
||||
}
|
||||
|
||||
void SettingsTests::TestLayerGlobalsOnRoot()
|
||||
{
|
||||
// Test for microsoft/terminal#2906. We added the ability for the root
|
||||
// to be used as the globals object in #2515. However, if you have a
|
||||
// globals object, then the settings in the root would get ignored.
|
||||
// This test ensures that settings from a child "globals" element
|
||||
// _layer_ on top of root properties, and they don't cause the root
|
||||
// properties to be totally ignored.
|
||||
|
||||
const std::string settings0String{ R"(
|
||||
{
|
||||
"globals": {
|
||||
"defaultProfile": "{6239a42c-1111-49a3-80bd-e8fdd045185c}",
|
||||
"initialRows": 123
|
||||
}
|
||||
})" };
|
||||
const std::string settings1String{ R"(
|
||||
{
|
||||
"defaultProfile": "{6239a42c-1111-49a3-80bd-e8fdd045185c}",
|
||||
"initialRows": 234
|
||||
})" };
|
||||
const std::string settings2String{ R"(
|
||||
{
|
||||
"defaultProfile": "{6239a42c-2222-49a3-80bd-e8fdd045185c}",
|
||||
"initialRows": 345,
|
||||
"globals": {
|
||||
"defaultProfile": "{6239a42c-1111-49a3-80bd-e8fdd045185c}"
|
||||
// initialRows should not be cleared here
|
||||
}
|
||||
})" };
|
||||
const std::string settings3String{ R"(
|
||||
{
|
||||
"defaultProfile": "{6239a42c-2222-49a3-80bd-e8fdd045185c}",
|
||||
"globals": {
|
||||
"initialRows": 456
|
||||
// defaultProfile should not be cleared here
|
||||
}
|
||||
})" };
|
||||
const std::string settings4String{ R"(
|
||||
{
|
||||
"defaultProfile": "{6239a42c-2222-49a3-80bd-e8fdd045185c}",
|
||||
"globals": {
|
||||
"defaultProfile": "{6239a42c-1111-49a3-80bd-e8fdd045185c}"
|
||||
},
|
||||
"defaultProfile": "{6239a42c-3333-49a3-80bd-e8fdd045185c}"
|
||||
})" };
|
||||
const std::string settings5String{ R"(
|
||||
{
|
||||
"globals": {
|
||||
"defaultProfile": "{6239a42c-1111-49a3-80bd-e8fdd045185c}"
|
||||
},
|
||||
"defaultProfile": "{6239a42c-2222-49a3-80bd-e8fdd045185c}",
|
||||
"globals": {
|
||||
"defaultProfile": "{6239a42c-3333-49a3-80bd-e8fdd045185c}"
|
||||
}
|
||||
})" };
|
||||
|
||||
VerifyParseSucceeded(settings0String);
|
||||
VerifyParseSucceeded(settings1String);
|
||||
VerifyParseSucceeded(settings2String);
|
||||
VerifyParseSucceeded(settings3String);
|
||||
VerifyParseSucceeded(settings4String);
|
||||
VerifyParseSucceeded(settings5String);
|
||||
const auto guid1 = Microsoft::Console::Utils::GuidFromString(L"{6239a42c-1111-49a3-80bd-e8fdd045185c}");
|
||||
const auto guid2 = Microsoft::Console::Utils::GuidFromString(L"{6239a42c-2222-49a3-80bd-e8fdd045185c}");
|
||||
const auto guid3 = Microsoft::Console::Utils::GuidFromString(L"{6239a42c-3333-49a3-80bd-e8fdd045185c}");
|
||||
|
||||
{
|
||||
CascadiaSettings settings;
|
||||
settings._ParseJsonString(settings0String, false);
|
||||
settings.LayerJson(settings._userSettings);
|
||||
VERIFY_ARE_EQUAL(guid1, settings._globals._defaultProfile);
|
||||
VERIFY_ARE_EQUAL(123, settings._globals._initialRows);
|
||||
}
|
||||
{
|
||||
CascadiaSettings settings;
|
||||
settings._ParseJsonString(settings1String, false);
|
||||
settings.LayerJson(settings._userSettings);
|
||||
VERIFY_ARE_EQUAL(guid1, settings._globals._defaultProfile);
|
||||
VERIFY_ARE_EQUAL(234, settings._globals._initialRows);
|
||||
}
|
||||
{
|
||||
CascadiaSettings settings;
|
||||
settings._ParseJsonString(settings2String, false);
|
||||
settings.LayerJson(settings._userSettings);
|
||||
VERIFY_ARE_EQUAL(guid1, settings._globals._defaultProfile);
|
||||
VERIFY_ARE_EQUAL(345, settings._globals._initialRows);
|
||||
}
|
||||
{
|
||||
CascadiaSettings settings;
|
||||
settings._ParseJsonString(settings3String, false);
|
||||
settings.LayerJson(settings._userSettings);
|
||||
VERIFY_ARE_EQUAL(guid2, settings._globals._defaultProfile);
|
||||
VERIFY_ARE_EQUAL(456, settings._globals._initialRows);
|
||||
}
|
||||
{
|
||||
CascadiaSettings settings;
|
||||
settings._ParseJsonString(settings4String, false);
|
||||
settings.LayerJson(settings._userSettings);
|
||||
VERIFY_ARE_EQUAL(guid1, settings._globals._defaultProfile);
|
||||
}
|
||||
{
|
||||
CascadiaSettings settings;
|
||||
settings._ParseJsonString(settings5String, false);
|
||||
settings.LayerJson(settings._userSettings);
|
||||
VERIFY_ARE_EQUAL(guid3, settings._globals._defaultProfile);
|
||||
}
|
||||
}
|
||||
void SettingsTests::TestProfileIconWithEnvVar()
|
||||
{
|
||||
const auto expectedPath = wil::ExpandEnvironmentStringsW<std::wstring>(L"%WINDIR%\\System32\\x_80.png");
|
||||
@@ -1352,7 +1468,7 @@ namespace TerminalAppLocalTests
|
||||
CascadiaSettings settings{};
|
||||
settings._ParseJsonString(settingsJson, false);
|
||||
settings.LayerJson(settings._userSettings);
|
||||
VERIFY_IS_FALSE(settings._profiles.empty());
|
||||
VERIFY_IS_FALSE(settings._profiles.empty(), 0);
|
||||
VERIFY_ARE_EQUAL(expectedPath, settings._profiles[0].GetExpandedIconPath());
|
||||
}
|
||||
void SettingsTests::TestProfileBackgroundImageWithEnvVar()
|
||||
@@ -1373,7 +1489,7 @@ namespace TerminalAppLocalTests
|
||||
CascadiaSettings settings{};
|
||||
settings._ParseJsonString(settingsJson, false);
|
||||
settings.LayerJson(settings._userSettings);
|
||||
VERIFY_IS_FALSE(settings._profiles.empty());
|
||||
VERIFY_IS_FALSE(settings._profiles.empty(), 0);
|
||||
|
||||
GlobalAppSettings globalSettings{};
|
||||
auto terminalSettings = settings._profiles[0].CreateTerminalSettings(globalSettings.GetColorSchemes());
|
||||
@@ -1976,220 +2092,13 @@ namespace TerminalAppLocalTests
|
||||
}
|
||||
}
|
||||
|
||||
void SettingsTests::FindMissingProfile()
|
||||
{
|
||||
// Test that CascadiaSettings::FindProfile returns null for a GUID that
|
||||
// doesn't exist
|
||||
const std::string settingsString{ R"(
|
||||
{
|
||||
"defaultProfile": "{6239a42c-1111-49a3-80bd-e8fdd045185c}",
|
||||
"profiles": [
|
||||
{
|
||||
"name" : "profile0",
|
||||
"guid": "{6239a42c-1111-49a3-80bd-e8fdd045185c}"
|
||||
},
|
||||
{
|
||||
"name" : "profile1",
|
||||
"guid": "{6239a42c-2222-49a3-80bd-e8fdd045185c}"
|
||||
}
|
||||
]
|
||||
})" };
|
||||
const auto settingsJsonObj = VerifyParseSucceeded(settingsString);
|
||||
auto settings = CascadiaSettings::FromJson(settingsJsonObj);
|
||||
|
||||
const auto guid1 = Microsoft::Console::Utils::GuidFromString(L"{6239a42c-1111-49a3-80bd-e8fdd045185c}");
|
||||
const auto guid2 = Microsoft::Console::Utils::GuidFromString(L"{6239a42c-2222-49a3-80bd-e8fdd045185c}");
|
||||
const auto guid3 = Microsoft::Console::Utils::GuidFromString(L"{6239a42c-3333-49a3-80bd-e8fdd045185c}");
|
||||
|
||||
const Profile* const profile1 = settings->FindProfile(guid1);
|
||||
const Profile* const profile2 = settings->FindProfile(guid2);
|
||||
const Profile* const profile3 = settings->FindProfile(guid3);
|
||||
|
||||
VERIFY_IS_NOT_NULL(profile1);
|
||||
VERIFY_IS_NOT_NULL(profile2);
|
||||
VERIFY_IS_NULL(profile3);
|
||||
|
||||
VERIFY_ARE_EQUAL(L"profile0", profile1->GetName());
|
||||
VERIFY_ARE_EQUAL(L"profile1", profile2->GetName());
|
||||
}
|
||||
|
||||
void SettingsTests::MakeSettingsForProfileThatDoesntExist()
|
||||
{
|
||||
// Test that MakeSettings throws when the GUID doesn't exist
|
||||
const std::string settingsString{ R"(
|
||||
{
|
||||
"defaultProfile": "{6239a42c-1111-49a3-80bd-e8fdd045185c}",
|
||||
"profiles": [
|
||||
{
|
||||
"name" : "profile0",
|
||||
"guid": "{6239a42c-1111-49a3-80bd-e8fdd045185c}",
|
||||
"historySize": 1
|
||||
},
|
||||
{
|
||||
"name" : "profile1",
|
||||
"guid": "{6239a42c-2222-49a3-80bd-e8fdd045185c}",
|
||||
"historySize": 2
|
||||
}
|
||||
]
|
||||
})" };
|
||||
const auto settingsJsonObj = VerifyParseSucceeded(settingsString);
|
||||
auto settings = CascadiaSettings::FromJson(settingsJsonObj);
|
||||
|
||||
const auto guid1 = Microsoft::Console::Utils::GuidFromString(L"{6239a42c-1111-49a3-80bd-e8fdd045185c}");
|
||||
const auto guid2 = Microsoft::Console::Utils::GuidFromString(L"{6239a42c-2222-49a3-80bd-e8fdd045185c}");
|
||||
const auto guid3 = Microsoft::Console::Utils::GuidFromString(L"{6239a42c-3333-49a3-80bd-e8fdd045185c}");
|
||||
|
||||
try
|
||||
{
|
||||
auto terminalSettings = settings->BuildSettings(guid1);
|
||||
VERIFY_ARE_NOT_EQUAL(nullptr, terminalSettings);
|
||||
VERIFY_ARE_EQUAL(1, terminalSettings.HistorySize());
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
VERIFY_IS_TRUE(false, L"This call to BuildSettings should succeed");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
auto terminalSettings = settings->BuildSettings(guid2);
|
||||
VERIFY_ARE_NOT_EQUAL(nullptr, terminalSettings);
|
||||
VERIFY_ARE_EQUAL(2, terminalSettings.HistorySize());
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
VERIFY_IS_TRUE(false, L"This call to BuildSettings should succeed");
|
||||
}
|
||||
|
||||
VERIFY_THROWS(auto terminalSettings = settings->BuildSettings(guid3), wil::ResultException, L"This call to BuildSettings should fail");
|
||||
|
||||
try
|
||||
{
|
||||
const auto [guid, termSettings] = settings->BuildSettings(nullptr);
|
||||
VERIFY_ARE_NOT_EQUAL(nullptr, termSettings);
|
||||
VERIFY_ARE_EQUAL(1, termSettings.HistorySize());
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
VERIFY_IS_TRUE(false, L"This call to BuildSettings should succeed");
|
||||
}
|
||||
}
|
||||
|
||||
void SettingsTests::MakeSettingsForDefaultProfileThatDoesntExist()
|
||||
{
|
||||
// Test that MakeSettings _doesnt_ throw when we load settings with a
|
||||
// defaultProfile that's not in the list, we validate the settings, and
|
||||
// then call MakeSettings(nullopt). The validation should ensure that
|
||||
// the default profile is something reasonable
|
||||
const std::string settingsString{ R"(
|
||||
{
|
||||
"defaultProfile": "{6239a42c-3333-49a3-80bd-e8fdd045185c}",
|
||||
"profiles": [
|
||||
{
|
||||
"name" : "profile0",
|
||||
"guid": "{6239a42c-1111-49a3-80bd-e8fdd045185c}",
|
||||
"historySize": 1
|
||||
},
|
||||
{
|
||||
"name" : "profile1",
|
||||
"guid": "{6239a42c-2222-49a3-80bd-e8fdd045185c}",
|
||||
"historySize": 2
|
||||
}
|
||||
]
|
||||
})" };
|
||||
const auto settingsJsonObj = VerifyParseSucceeded(settingsString);
|
||||
auto settings = CascadiaSettings::FromJson(settingsJsonObj);
|
||||
settings->_ValidateSettings();
|
||||
|
||||
VERIFY_ARE_EQUAL(2u, settings->_warnings.size());
|
||||
VERIFY_ARE_EQUAL(2u, settings->_profiles.size());
|
||||
VERIFY_ARE_EQUAL(settings->_globals.GetDefaultProfile(), settings->_profiles.at(0).GetGuid());
|
||||
try
|
||||
{
|
||||
const auto [guid, termSettings] = settings->BuildSettings(nullptr);
|
||||
VERIFY_ARE_NOT_EQUAL(nullptr, termSettings);
|
||||
VERIFY_ARE_EQUAL(1, termSettings.HistorySize());
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
VERIFY_IS_TRUE(false, L"This call to BuildSettings should succeed");
|
||||
}
|
||||
}
|
||||
|
||||
void SettingsTests::TestLayerProfileOnColorScheme()
|
||||
{
|
||||
Log::Comment(NoThrowString().Format(
|
||||
L"Ensure that setting (or not) a property in the profile that should override a property of the color scheme works correctly."));
|
||||
|
||||
const std::string settings0String{ R"(
|
||||
{
|
||||
"profiles": [
|
||||
{
|
||||
"name" : "profile0",
|
||||
"colorScheme": "schemeWithCursorColor"
|
||||
},
|
||||
{
|
||||
"name" : "profile1",
|
||||
"colorScheme": "schemeWithoutCursorColor"
|
||||
},
|
||||
{
|
||||
"name" : "profile2",
|
||||
"colorScheme": "schemeWithCursorColor",
|
||||
"cursorColor": "#234567"
|
||||
},
|
||||
{
|
||||
"name" : "profile3",
|
||||
"colorScheme": "schemeWithoutCursorColor",
|
||||
"cursorColor": "#345678"
|
||||
},
|
||||
{
|
||||
"name" : "profile4",
|
||||
"cursorColor": "#456789"
|
||||
},
|
||||
{
|
||||
"name" : "profile5"
|
||||
}
|
||||
],
|
||||
"schemes": [
|
||||
{
|
||||
"name": "schemeWithCursorColor",
|
||||
"cursorColor": "#123456"
|
||||
},
|
||||
{
|
||||
"name": "schemeWithoutCursorColor"
|
||||
}
|
||||
]
|
||||
})" };
|
||||
|
||||
VerifyParseSucceeded(settings0String);
|
||||
|
||||
CascadiaSettings settings;
|
||||
settings._ParseJsonString(settings0String, false);
|
||||
settings.LayerJson(settings._userSettings);
|
||||
|
||||
VERIFY_ARE_EQUAL(6u, settings._profiles.size());
|
||||
VERIFY_ARE_EQUAL(2u, settings._globals._colorSchemes.size());
|
||||
|
||||
auto terminalSettings0 = settings._profiles[0].CreateTerminalSettings(settings._globals._colorSchemes);
|
||||
auto terminalSettings1 = settings._profiles[1].CreateTerminalSettings(settings._globals._colorSchemes);
|
||||
auto terminalSettings2 = settings._profiles[2].CreateTerminalSettings(settings._globals._colorSchemes);
|
||||
auto terminalSettings3 = settings._profiles[3].CreateTerminalSettings(settings._globals._colorSchemes);
|
||||
auto terminalSettings4 = settings._profiles[4].CreateTerminalSettings(settings._globals._colorSchemes);
|
||||
auto terminalSettings5 = settings._profiles[5].CreateTerminalSettings(settings._globals._colorSchemes);
|
||||
|
||||
VERIFY_ARE_EQUAL(ARGB(0, 0x12, 0x34, 0x56), terminalSettings0.CursorColor()); // from color scheme
|
||||
VERIFY_ARE_EQUAL(DEFAULT_CURSOR_COLOR, terminalSettings1.CursorColor()); // default
|
||||
VERIFY_ARE_EQUAL(ARGB(0, 0x23, 0x45, 0x67), terminalSettings2.CursorColor()); // from profile (trumps color scheme)
|
||||
VERIFY_ARE_EQUAL(ARGB(0, 0x34, 0x56, 0x78), terminalSettings3.CursorColor()); // from profile (not set in color scheme)
|
||||
VERIFY_ARE_EQUAL(ARGB(0, 0x45, 0x67, 0x89), terminalSettings4.CursorColor()); // from profile (no color scheme)
|
||||
VERIFY_ARE_EQUAL(DEFAULT_CURSOR_COLOR, terminalSettings5.CursorColor()); // default
|
||||
}
|
||||
|
||||
void SettingsTests::ValidateKeybindingsWarnings()
|
||||
{
|
||||
const std::string badSettings{ R"(
|
||||
{
|
||||
"defaultProfile": "{6239a42c-2222-49a3-80bd-e8fdd045185c}",
|
||||
"globals": {
|
||||
"defaultProfile": "{6239a42c-2222-49a3-80bd-e8fdd045185c}"
|
||||
},
|
||||
"profiles": [
|
||||
{
|
||||
"name" : "profile0",
|
||||
@@ -2225,4 +2134,5 @@ namespace TerminalAppLocalTests
|
||||
VERIFY_ARE_EQUAL(::TerminalApp::SettingsLoadWarnings::MissingRequiredParameter, settings->_warnings.at(2));
|
||||
VERIFY_ARE_EQUAL(::TerminalApp::SettingsLoadWarnings::MissingRequiredParameter, settings->_warnings.at(3));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -13,10 +13,8 @@
|
||||
|
||||
using namespace Microsoft::Console;
|
||||
using namespace TerminalApp;
|
||||
using namespace winrt::TerminalApp;
|
||||
using namespace WEX::Logging;
|
||||
using namespace WEX::TestExecution;
|
||||
using namespace WEX::Common;
|
||||
|
||||
namespace TerminalAppLocalTests
|
||||
{
|
||||
@@ -55,20 +53,11 @@ namespace TerminalAppLocalTests
|
||||
TEST_METHOD(CreateSimpleTerminalXamlType);
|
||||
TEST_METHOD(CreateTerminalMuxXamlType);
|
||||
|
||||
TEST_METHOD(CreateTerminalPage);
|
||||
|
||||
TEST_METHOD(TryDuplicateBadTab);
|
||||
TEST_METHOD(TryDuplicateBadPane);
|
||||
|
||||
TEST_CLASS_SETUP(ClassSetup)
|
||||
{
|
||||
InitializeJsonReader();
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
void _initializeTerminalPage(winrt::com_ptr<winrt::TerminalApp::implementation::TerminalPage>& page,
|
||||
std::shared_ptr<CascadiaSettings> initialSettings);
|
||||
};
|
||||
|
||||
void TabTests::EnsureTestsActivate()
|
||||
@@ -97,8 +86,8 @@ namespace TerminalAppLocalTests
|
||||
// Just creating it is enough to know that everything is working.
|
||||
winrt::Microsoft::Terminal::TerminalConnection::EchoConnection conn{};
|
||||
VERIFY_IS_NOT_NULL(conn);
|
||||
// We're doing this test separately from the TryCreateSettingsType test,
|
||||
// to ensure both dependent binaries (TerminalSettings and
|
||||
// We're doing this test seperately from the TryCreateSettingsType test,
|
||||
// to ensure both dependent binaries (TemrinalSettings and
|
||||
// TerminalConnection) both work individually.
|
||||
}
|
||||
|
||||
@@ -175,329 +164,4 @@ namespace TerminalAppLocalTests
|
||||
VERIFY_SUCCEEDED(result);
|
||||
}
|
||||
|
||||
void TabTests::CreateTerminalPage()
|
||||
{
|
||||
winrt::com_ptr<winrt::TerminalApp::implementation::TerminalPage> page{ nullptr };
|
||||
|
||||
auto result = RunOnUIThread([&page]() {
|
||||
page = winrt::make_self<winrt::TerminalApp::implementation::TerminalPage>();
|
||||
VERIFY_IS_NOT_NULL(page);
|
||||
});
|
||||
VERIFY_SUCCEEDED(result);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - This is a helper to set up a TerminalPage for a unittest. This method
|
||||
// does a couple things:
|
||||
// * Create()'s a TerminalPage with the given settings. Constructing a
|
||||
// TerminalPage so that we can get at its implementation is wacky, so
|
||||
// this helper will do it correctly for you, even if this doesn't make a
|
||||
// ton of sense on the surface. This is also why you need to pass both a
|
||||
// projection and a com_ptr to this method.
|
||||
// * It will use the provided settings object to initialize the TerminalPage
|
||||
// * It will add the TerminalPage to the test Application, so that we can
|
||||
// get actual layout events. Much of the Terminal assumes there's a
|
||||
// non-zero ActualSize to the Terminal window, and adding the Page to
|
||||
// the Application will make it behave as expected.
|
||||
// * It will wait for the TerminalPage to finish initialization before
|
||||
// returning control to the caller. It does this by creating an event and
|
||||
// only setting the event when the TerminalPage raises its Initialized
|
||||
// event, to signal that startup is complete. At this point, there will
|
||||
// be one tab with the default profile in the page.
|
||||
// * It will also ensure that the first tab is focused, since that happens
|
||||
// asynchronously in the application typically.
|
||||
// Arguments:
|
||||
// - page: a TerminalPage implementation ptr that will receive the new TerminalPage instance
|
||||
// - initialSettings: a CascadiaSettings to initialize the TerminalPage with.
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void TabTests::_initializeTerminalPage(winrt::com_ptr<winrt::TerminalApp::implementation::TerminalPage>& page,
|
||||
std::shared_ptr<CascadiaSettings> initialSettings)
|
||||
{
|
||||
// This is super wacky, but we can't just initialize the
|
||||
// com_ptr<impl::TerminalPage> in the lambda and assign it back out of
|
||||
// the lambda. We'll crash trying to get a weak_ref to the TerminalPage
|
||||
// during TerminalPage::Create() below.
|
||||
//
|
||||
// Instead, create the winrt object, then get a com_ptr to the
|
||||
// implementation _from_ the winrt object. This seems to work, even if
|
||||
// it's weird.
|
||||
winrt::TerminalApp::TerminalPage projectedPage{ nullptr };
|
||||
|
||||
Log::Comment(NoThrowString().Format(L"Construct the TerminalPage"));
|
||||
auto result = RunOnUIThread([&projectedPage, &page, initialSettings]() {
|
||||
projectedPage = winrt::TerminalApp::TerminalPage();
|
||||
page.copy_from(winrt::get_self<winrt::TerminalApp::implementation::TerminalPage>(projectedPage));
|
||||
page->_settings = initialSettings;
|
||||
});
|
||||
VERIFY_SUCCEEDED(result);
|
||||
|
||||
VERIFY_IS_NOT_NULL(page);
|
||||
VERIFY_IS_NOT_NULL(page->_settings);
|
||||
|
||||
::details::Event waitForInitEvent;
|
||||
if (!waitForInitEvent.IsValid())
|
||||
{
|
||||
VERIFY_SUCCEEDED(HRESULT_FROM_WIN32(::GetLastError()));
|
||||
}
|
||||
page->Initialized([&waitForInitEvent](auto&&, auto&&) {
|
||||
waitForInitEvent.Set();
|
||||
});
|
||||
|
||||
Log::Comment(L"Create() the TerminalPage");
|
||||
|
||||
result = RunOnUIThread([&page]() {
|
||||
VERIFY_IS_NOT_NULL(page);
|
||||
VERIFY_IS_NOT_NULL(page->_settings);
|
||||
page->Create();
|
||||
Log::Comment(L"Create()'d the page successfully");
|
||||
|
||||
auto app = ::winrt::Windows::UI::Xaml::Application::Current();
|
||||
|
||||
winrt::TerminalApp::TerminalPage pp = *page;
|
||||
winrt::Windows::UI::Xaml::Window::Current().Content(pp);
|
||||
winrt::Windows::UI::Xaml::Window::Current().Activate();
|
||||
});
|
||||
VERIFY_SUCCEEDED(result);
|
||||
|
||||
Log::Comment(L"Wait for the page to finish initializing...");
|
||||
VERIFY_SUCCEEDED(waitForInitEvent.Wait());
|
||||
Log::Comment(L"...Done");
|
||||
|
||||
result = RunOnUIThread([&page]() {
|
||||
// In the real app, this isn't a problem, but doesn't happen
|
||||
// reliably in the unit tests.
|
||||
Log::Comment(L"Ensure we set the first tab as the selected one.");
|
||||
auto tab{ page->_GetStrongTabImpl(0) };
|
||||
page->_tabView.SelectedItem(tab->GetTabViewItem());
|
||||
page->_UpdatedSelectedTab(0);
|
||||
});
|
||||
VERIFY_SUCCEEDED(result);
|
||||
}
|
||||
|
||||
void TabTests::TryDuplicateBadTab()
|
||||
{
|
||||
Log::Comment(L"This test regressed recently - it is temporarily disabled while GH#5169 is investigated");
|
||||
Log::Result(WEX::Logging::TestResults::Skipped);
|
||||
return;
|
||||
|
||||
// // * Create a tab with a profile with GUID 1
|
||||
// // * Reload the settings so that GUID 1 is no longer in the list of profiles
|
||||
// // * Try calling _DuplicateTabViewItem on tab 1
|
||||
// // * No new tab should be created (and more importantly, the app should not crash)
|
||||
// //
|
||||
// // Created to test GH#2455
|
||||
|
||||
// const std::string settingsJson0{ R"(
|
||||
// {
|
||||
// "defaultProfile": "{6239a42c-1111-49a3-80bd-e8fdd045185c}",
|
||||
// "profiles": [
|
||||
// {
|
||||
// "name" : "profile0",
|
||||
// "guid": "{6239a42c-1111-49a3-80bd-e8fdd045185c}",
|
||||
// "historySize": 1
|
||||
// },
|
||||
// {
|
||||
// "name" : "profile1",
|
||||
// "guid": "{6239a42c-2222-49a3-80bd-e8fdd045185c}",
|
||||
// "historySize": 2
|
||||
// }
|
||||
// ]
|
||||
// })" };
|
||||
|
||||
// const std::string settingsJson1{ R"(
|
||||
// {
|
||||
// "defaultProfile": "{6239a42c-1111-49a3-80bd-e8fdd045185c}",
|
||||
// "profiles": [
|
||||
// {
|
||||
// "name" : "profile1",
|
||||
// "guid": "{6239a42c-2222-49a3-80bd-e8fdd045185c}",
|
||||
// "historySize": 2
|
||||
// }
|
||||
// ]
|
||||
// })" };
|
||||
|
||||
// VerifyParseSucceeded(settingsJson0);
|
||||
// auto settings0 = std::make_shared<CascadiaSettings>(false);
|
||||
// VERIFY_IS_NOT_NULL(settings0);
|
||||
// settings0->_ParseJsonString(settingsJson0, false);
|
||||
// settings0->LayerJson(settings0->_userSettings);
|
||||
// settings0->_ValidateSettings();
|
||||
|
||||
// VerifyParseSucceeded(settingsJson1);
|
||||
// auto settings1 = std::make_shared<CascadiaSettings>(false);
|
||||
// VERIFY_IS_NOT_NULL(settings1);
|
||||
// settings1->_ParseJsonString(settingsJson1, false);
|
||||
// settings1->LayerJson(settings1->_userSettings);
|
||||
// settings1->_ValidateSettings();
|
||||
|
||||
// const auto guid1 = Microsoft::Console::Utils::GuidFromString(L"{6239a42c-1111-49a3-80bd-e8fdd045185c}");
|
||||
// const auto guid2 = Microsoft::Console::Utils::GuidFromString(L"{6239a42c-2222-49a3-80bd-e8fdd045185c}");
|
||||
// const auto guid3 = Microsoft::Console::Utils::GuidFromString(L"{6239a42c-3333-49a3-80bd-e8fdd045185c}");
|
||||
|
||||
// // This is super wacky, but we can't just initialize the
|
||||
// // com_ptr<impl::TerminalPage> in the lambda and assign it back out of
|
||||
// // the lambda. We'll crash trying to get a weak_ref to the TerminalPage
|
||||
// // during TerminalPage::Create() below.
|
||||
// //
|
||||
// // Instead, create the winrt object, then get a com_ptr to the
|
||||
// // implementation _from_ the winrt object. This seems to work, even if
|
||||
// // it's weird.
|
||||
// winrt::com_ptr<winrt::TerminalApp::implementation::TerminalPage> page{ nullptr };
|
||||
// _initializeTerminalPage(page, settings0);
|
||||
|
||||
// auto result = RunOnUIThread([&page]() {
|
||||
// VERIFY_ARE_EQUAL(1u, page->_tabs.Size());
|
||||
// });
|
||||
// VERIFY_SUCCEEDED(result);
|
||||
|
||||
// Log::Comment(L"Duplicate the first tab");
|
||||
// result = RunOnUIThread([&page]() {
|
||||
// page->_DuplicateTabViewItem();
|
||||
// VERIFY_ARE_EQUAL(2u, page->_tabs.Size());
|
||||
// });
|
||||
// VERIFY_SUCCEEDED(result);
|
||||
|
||||
// Log::Comment(NoThrowString().Format(
|
||||
// L"Change the settings of the TerminalPage so the first profile is "
|
||||
// L"no longer in the list of profiles"));
|
||||
// result = RunOnUIThread([&page, settings1]() {
|
||||
// page->_settings = settings1;
|
||||
// });
|
||||
// VERIFY_SUCCEEDED(result);
|
||||
|
||||
// Log::Comment(L"Duplicate the tab, and don't crash");
|
||||
// result = RunOnUIThread([&page]() {
|
||||
// page->_DuplicateTabViewItem();
|
||||
// VERIFY_ARE_EQUAL(2u, page->_tabs.Size(), L"We should gracefully do nothing here - the profile no longer exists.");
|
||||
// });
|
||||
// VERIFY_SUCCEEDED(result);
|
||||
}
|
||||
|
||||
void TabTests::TryDuplicateBadPane()
|
||||
{
|
||||
Log::Comment(L"This test regressed recently - it is temporarily disabled while GH#5169 is investigated");
|
||||
Log::Result(WEX::Logging::TestResults::Skipped);
|
||||
return;
|
||||
|
||||
// // * Create a tab with a profile with GUID 1
|
||||
// // * Reload the settings so that GUID 1 is no longer in the list of profiles
|
||||
// // * Try calling _SplitPane(Duplicate) on tab 1
|
||||
// // * No new pane should be created (and more importantly, the app should not crash)
|
||||
// //
|
||||
// // Created to test GH#2455
|
||||
|
||||
// const std::string settingsJson0{ R"(
|
||||
// {
|
||||
// "defaultProfile": "{6239a42c-1111-49a3-80bd-e8fdd045185c}",
|
||||
// "profiles": [
|
||||
// {
|
||||
// "name" : "profile0",
|
||||
// "guid": "{6239a42c-1111-49a3-80bd-e8fdd045185c}",
|
||||
// "historySize": 1
|
||||
// },
|
||||
// {
|
||||
// "name" : "profile1",
|
||||
// "guid": "{6239a42c-2222-49a3-80bd-e8fdd045185c}",
|
||||
// "historySize": 2
|
||||
// }
|
||||
// ]
|
||||
// })" };
|
||||
|
||||
// const std::string settingsJson1{ R"(
|
||||
// {
|
||||
// "defaultProfile": "{6239a42c-1111-49a3-80bd-e8fdd045185c}",
|
||||
// "profiles": [
|
||||
// {
|
||||
// "name" : "profile1",
|
||||
// "guid": "{6239a42c-2222-49a3-80bd-e8fdd045185c}",
|
||||
// "historySize": 2
|
||||
// }
|
||||
// ]
|
||||
// })" };
|
||||
|
||||
// VerifyParseSucceeded(settingsJson0);
|
||||
// auto settings0 = std::make_shared<CascadiaSettings>(false);
|
||||
// VERIFY_IS_NOT_NULL(settings0);
|
||||
// settings0->_ParseJsonString(settingsJson0, false);
|
||||
// settings0->LayerJson(settings0->_userSettings);
|
||||
// settings0->_ValidateSettings();
|
||||
|
||||
// VerifyParseSucceeded(settingsJson1);
|
||||
// auto settings1 = std::make_shared<CascadiaSettings>(false);
|
||||
// VERIFY_IS_NOT_NULL(settings1);
|
||||
// settings1->_ParseJsonString(settingsJson1, false);
|
||||
// settings1->LayerJson(settings1->_userSettings);
|
||||
// settings1->_ValidateSettings();
|
||||
|
||||
// const auto guid1 = Microsoft::Console::Utils::GuidFromString(L"{6239a42c-1111-49a3-80bd-e8fdd045185c}");
|
||||
// const auto guid2 = Microsoft::Console::Utils::GuidFromString(L"{6239a42c-2222-49a3-80bd-e8fdd045185c}");
|
||||
// const auto guid3 = Microsoft::Console::Utils::GuidFromString(L"{6239a42c-3333-49a3-80bd-e8fdd045185c}");
|
||||
|
||||
// // This is super wacky, but we can't just initialize the
|
||||
// // com_ptr<impl::TerminalPage> in the lambda and assign it back out of
|
||||
// // the lambda. We'll crash trying to get a weak_ref to the TerminalPage
|
||||
// // during TerminalPage::Create() below.
|
||||
// //
|
||||
// // Instead, create the winrt object, then get a com_ptr to the
|
||||
// // implementation _from_ the winrt object. This seems to work, even if
|
||||
// // it's weird.
|
||||
// winrt::com_ptr<winrt::TerminalApp::implementation::TerminalPage> page{ nullptr };
|
||||
// _initializeTerminalPage(page, settings0);
|
||||
|
||||
// auto result = RunOnUIThread([&page]() {
|
||||
// VERIFY_ARE_EQUAL(1u, page->_tabs.Size());
|
||||
// });
|
||||
// VERIFY_SUCCEEDED(result);
|
||||
|
||||
// result = RunOnUIThread([&page]() {
|
||||
// VERIFY_ARE_EQUAL(1u, page->_tabs.Size());
|
||||
// auto tab = page->_GetStrongTabImpl(0);
|
||||
// VERIFY_ARE_EQUAL(1, tab->_GetLeafPaneCount());
|
||||
// });
|
||||
// VERIFY_SUCCEEDED(result);
|
||||
|
||||
// Log::Comment(NoThrowString().Format(L"Duplicate the first pane"));
|
||||
// result = RunOnUIThread([&page]() {
|
||||
// page->_SplitPane(SplitState::Automatic, SplitType::Duplicate, nullptr);
|
||||
|
||||
// VERIFY_ARE_EQUAL(1u, page->_tabs.Size());
|
||||
// auto tab = page->_GetStrongTabImpl(0);
|
||||
// VERIFY_ARE_EQUAL(2, tab->_GetLeafPaneCount());
|
||||
// });
|
||||
// VERIFY_SUCCEEDED(result);
|
||||
|
||||
// Log::Comment(NoThrowString().Format(
|
||||
// L"Change the settings of the TerminalPage so the first profile is "
|
||||
// L"no longer in the list of profiles"));
|
||||
// result = RunOnUIThread([&page, settings1]() {
|
||||
// page->_settings = settings1;
|
||||
// });
|
||||
// VERIFY_SUCCEEDED(result);
|
||||
|
||||
// Log::Comment(NoThrowString().Format(L"Duplicate the pane, and don't crash"));
|
||||
// result = RunOnUIThread([&page]() {
|
||||
// page->_SplitPane(SplitState::Automatic, SplitType::Duplicate, nullptr);
|
||||
|
||||
// VERIFY_ARE_EQUAL(1u, page->_tabs.Size());
|
||||
// auto tab = page->_GetStrongTabImpl(0);
|
||||
// VERIFY_ARE_EQUAL(2,
|
||||
// tab->_GetLeafPaneCount(),
|
||||
// L"We should gracefully do nothing here - the profile no longer exists.");
|
||||
// });
|
||||
// VERIFY_SUCCEEDED(result);
|
||||
|
||||
// auto cleanup = wil::scope_exit([] {
|
||||
// auto result = RunOnUIThread([]() {
|
||||
// // There's something causing us to crash north of
|
||||
// // TSFInputControl::NotifyEnter, or LayoutRequested. It's very
|
||||
// // unclear what that issue is. Since these tests don't run in
|
||||
// // CI, simply log a message so that the dev running these tests
|
||||
// // knows it's expected.
|
||||
// Log::Comment(L"This test often crashes on cleanup, even when it succeeds. If it succeeded, then crashes, that's okay.");
|
||||
// });
|
||||
// VERIFY_SUCCEEDED(result);
|
||||
// });
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -89,8 +89,8 @@ static bool RegisterTermClass(HINSTANCE hInstance) noexcept
|
||||
}
|
||||
|
||||
HwndTerminal::HwndTerminal(HWND parentHwnd) :
|
||||
_desiredFont{ L"Consolas", 0, 10, { 0, 14 }, CP_UTF8 },
|
||||
_actualFont{ L"Consolas", 0, 10, { 0, 14 }, CP_UTF8, false },
|
||||
_desiredFont{ DEFAULT_FONT_FACE, 0, 10, { 0, 14 }, CP_UTF8 },
|
||||
_actualFont{ DEFAULT_FONT_FACE, 0, 10, { 0, 14 }, CP_UTF8, false },
|
||||
_uiaProvider{ nullptr },
|
||||
_uiaProviderInitialized{ false },
|
||||
_currentDpi{ USER_DEFAULT_SCREEN_DPI },
|
||||
@@ -289,7 +289,7 @@ HRESULT _stdcall CreateTerminal(HWND parentHwnd, _Out_ void** hwnd, _Out_ void**
|
||||
parentHwnd,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr);
|
||||
0);
|
||||
auto _terminal = std::make_unique<HwndTerminal>(_hostWindow);
|
||||
RETURN_IF_FAILED(_terminal->Initialize());
|
||||
|
||||
@@ -427,8 +427,10 @@ const wchar_t* _stdcall TerminalGetSelection(void* terminal)
|
||||
return returnText.release();
|
||||
}
|
||||
|
||||
static ControlKeyStates getControlKeyState() noexcept
|
||||
void _stdcall TerminalSendKeyEvent(void* terminal, WPARAM wParam)
|
||||
{
|
||||
const auto publicTerminal = static_cast<const HwndTerminal*>(terminal);
|
||||
const auto scanCode = MapVirtualKeyW((UINT)wParam, MAPVK_VK_TO_VSC);
|
||||
struct KeyModifier
|
||||
{
|
||||
int vkey;
|
||||
@@ -456,17 +458,10 @@ static ControlKeyStates getControlKeyState() noexcept
|
||||
}
|
||||
}
|
||||
|
||||
return flags;
|
||||
publicTerminal->_terminal->SendKeyEvent((WORD)wParam, (WORD)scanCode, flags);
|
||||
}
|
||||
|
||||
void _stdcall TerminalSendKeyEvent(void* terminal, WORD vkey, WORD scanCode)
|
||||
{
|
||||
const auto publicTerminal = static_cast<const HwndTerminal*>(terminal);
|
||||
const auto flags = getControlKeyState();
|
||||
publicTerminal->_terminal->SendKeyEvent(vkey, scanCode, flags);
|
||||
}
|
||||
|
||||
void _stdcall TerminalSendCharEvent(void* terminal, wchar_t ch, WORD scanCode)
|
||||
void _stdcall TerminalSendCharEvent(void* terminal, wchar_t ch)
|
||||
{
|
||||
if (ch == '\t')
|
||||
{
|
||||
@@ -474,8 +469,7 @@ void _stdcall TerminalSendCharEvent(void* terminal, wchar_t ch, WORD scanCode)
|
||||
}
|
||||
|
||||
const auto publicTerminal = static_cast<const HwndTerminal*>(terminal);
|
||||
const auto flags = getControlKeyState();
|
||||
publicTerminal->_terminal->SendCharEvent(ch, scanCode, flags);
|
||||
publicTerminal->_terminal->SendCharEvent(ch);
|
||||
}
|
||||
|
||||
void _stdcall DestroyTerminal(void* terminal)
|
||||
|
||||
@@ -34,8 +34,8 @@ __declspec(dllexport) bool _stdcall TerminalIsSelectionActive(void* terminal);
|
||||
__declspec(dllexport) void _stdcall DestroyTerminal(void* terminal);
|
||||
__declspec(dllexport) void _stdcall TerminalSetTheme(void* terminal, TerminalTheme theme, LPCWSTR fontFamily, short fontSize, int newDpi);
|
||||
__declspec(dllexport) void _stdcall TerminalRegisterWriteCallback(void* terminal, const void __stdcall callback(wchar_t*));
|
||||
__declspec(dllexport) void _stdcall TerminalSendKeyEvent(void* terminal, WORD vkey, WORD scanCode);
|
||||
__declspec(dllexport) void _stdcall TerminalSendCharEvent(void* terminal, wchar_t ch, WORD scanCode);
|
||||
__declspec(dllexport) void _stdcall TerminalSendKeyEvent(void* terminal, WPARAM wParam);
|
||||
__declspec(dllexport) void _stdcall TerminalSendCharEvent(void* terminal, wchar_t ch);
|
||||
__declspec(dllexport) void _stdcall TerminalBlinkCursor(void* terminal);
|
||||
__declspec(dllexport) void _stdcall TerminalSetCursorVisible(void* terminal, const bool visible);
|
||||
};
|
||||
@@ -82,8 +82,8 @@ private:
|
||||
friend void _stdcall TerminalClearSelection(void* terminal);
|
||||
friend const wchar_t* _stdcall TerminalGetSelection(void* terminal);
|
||||
friend bool _stdcall TerminalIsSelectionActive(void* terminal);
|
||||
friend void _stdcall TerminalSendKeyEvent(void* terminal, WORD vkey, WORD scanCode);
|
||||
friend void _stdcall TerminalSendCharEvent(void* terminal, wchar_t ch, WORD scanCode);
|
||||
friend void _stdcall TerminalSendKeyEvent(void* terminal, WPARAM wParam);
|
||||
friend void _stdcall TerminalSendCharEvent(void* terminal, wchar_t ch);
|
||||
friend void _stdcall TerminalSetTheme(void* terminal, TerminalTheme theme, LPCWSTR fontFamily, short fontSize, int newDpi);
|
||||
friend void _stdcall TerminalBlinkCursor(void* terminal);
|
||||
friend void _stdcall TerminalSetCursorVisible(void* terminal, const bool visible);
|
||||
|
||||
@@ -93,9 +93,9 @@ namespace winrt::TerminalApp::implementation
|
||||
struct CopyTextArgs : public CopyTextArgsT<CopyTextArgs>
|
||||
{
|
||||
CopyTextArgs() = default;
|
||||
GETSET_PROPERTY(bool, SingleLine, false);
|
||||
GETSET_PROPERTY(bool, TrimWhitespace, true);
|
||||
|
||||
static constexpr std::string_view SingleLineKey{ "singleLine" };
|
||||
static constexpr std::string_view TrimWhitespaceKey{ "trimWhitespace" };
|
||||
|
||||
public:
|
||||
bool Equals(const IActionArgs& other)
|
||||
@@ -103,7 +103,7 @@ namespace winrt::TerminalApp::implementation
|
||||
auto otherAsUs = other.try_as<CopyTextArgs>();
|
||||
if (otherAsUs)
|
||||
{
|
||||
return otherAsUs->_SingleLine == _SingleLine;
|
||||
return otherAsUs->_TrimWhitespace == _TrimWhitespace;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
@@ -111,9 +111,9 @@ namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
// LOAD BEARING: Not using make_self here _will_ break you in the future!
|
||||
auto args = winrt::make_self<CopyTextArgs>();
|
||||
if (auto singleLine{ json[JsonKey(SingleLineKey)] })
|
||||
if (auto trimWhitespace{ json[JsonKey(TrimWhitespaceKey)] })
|
||||
{
|
||||
args->_SingleLine = singleLine.asBool();
|
||||
args->_TrimWhitespace = trimWhitespace.asBool();
|
||||
}
|
||||
return { *args, {} };
|
||||
}
|
||||
@@ -328,7 +328,7 @@ namespace winrt::TerminalApp::implementation
|
||||
return TerminalApp::SplitState::Automatic;
|
||||
}
|
||||
// default behavior for invalid data
|
||||
return TerminalApp::SplitState::Automatic;
|
||||
return TerminalApp::SplitState::None;
|
||||
};
|
||||
|
||||
// Possible SplitType values
|
||||
@@ -345,7 +345,7 @@ namespace winrt::TerminalApp::implementation
|
||||
struct SplitPaneArgs : public SplitPaneArgsT<SplitPaneArgs>
|
||||
{
|
||||
SplitPaneArgs() = default;
|
||||
GETSET_PROPERTY(winrt::TerminalApp::SplitState, SplitStyle, winrt::TerminalApp::SplitState::Automatic);
|
||||
GETSET_PROPERTY(winrt::TerminalApp::SplitState, SplitStyle, winrt::TerminalApp::SplitState::None);
|
||||
GETSET_PROPERTY(winrt::TerminalApp::NewTerminalArgs, TerminalArgs, nullptr);
|
||||
GETSET_PROPERTY(winrt::TerminalApp::SplitType, SplitMode, winrt::TerminalApp::SplitType::Manual);
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@ namespace TerminalApp
|
||||
|
||||
[default_interface] runtimeclass CopyTextArgs : IActionArgs
|
||||
{
|
||||
Boolean SingleLine { get; };
|
||||
Boolean TrimWhitespace { get; };
|
||||
};
|
||||
|
||||
[default_interface] runtimeclass NewTabArgs : IActionArgs
|
||||
|
||||
@@ -198,7 +198,7 @@ namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
if (const auto& realArgs = args.ActionArgs().try_as<TerminalApp::CopyTextArgs>())
|
||||
{
|
||||
const auto handled = _CopyText(realArgs.SingleLine());
|
||||
const auto handled = _CopyText(realArgs.TrimWhitespace());
|
||||
args.Handled(handled);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
using namespace winrt::TerminalApp;
|
||||
using namespace TerminalApp;
|
||||
|
||||
// Either a ; at the start of a line, or a ; preceded by any non-\ char.
|
||||
// Either a ; at the start of a line, or a ; preceeded by any non-\ char.
|
||||
const std::wregex AppCommandlineArgs::_commandDelimiterRegex{ LR"(^;|[^\\];)" };
|
||||
|
||||
AppCommandlineArgs::AppCommandlineArgs()
|
||||
@@ -172,7 +172,7 @@ void AppCommandlineArgs::_buildNewTabParser()
|
||||
// that `this` will still be safe - this function just lets us know this
|
||||
// command was parsed.
|
||||
_newTabCommand.subcommand->callback([&, this]() {
|
||||
// Build the NewTab action from the values we've parsed on the commandline.
|
||||
// Buld the NewTab action from the values we've parsed on the commandline.
|
||||
auto newTabAction = winrt::make_self<implementation::ActionAndArgs>();
|
||||
newTabAction->Action(ShortcutAction::NewTab);
|
||||
auto args = winrt::make_self<implementation::NewTabArgs>();
|
||||
@@ -207,7 +207,7 @@ void AppCommandlineArgs::_buildSplitPaneParser()
|
||||
// that `this` will still be safe - this function just lets us know this
|
||||
// command was parsed.
|
||||
_newPaneCommand.subcommand->callback([&, this]() {
|
||||
// Build the SplitPane action from the values we've parsed on the commandline.
|
||||
// Buld the SplitPane action from the values we've parsed on the commandline.
|
||||
auto splitPaneActionAndArgs = winrt::make_self<implementation::ActionAndArgs>();
|
||||
splitPaneActionAndArgs->Action(ShortcutAction::SplitPane);
|
||||
auto args = winrt::make_self<implementation::SplitPaneArgs>();
|
||||
@@ -217,7 +217,7 @@ void AppCommandlineArgs::_buildSplitPaneParser()
|
||||
args->SplitStyle(SplitState::Automatic);
|
||||
// Make sure to use the `Option`s here to check if they were set -
|
||||
// _getNewTerminalArgs might reset them while parsing a commandline
|
||||
if ((*_horizontalOption || *_verticalOption))
|
||||
if ((*_horizontalOption || *_verticalOption) && (_splitHorizontal))
|
||||
{
|
||||
if (_splitHorizontal)
|
||||
{
|
||||
@@ -225,7 +225,7 @@ void AppCommandlineArgs::_buildSplitPaneParser()
|
||||
}
|
||||
else if (_splitVertical)
|
||||
{
|
||||
args->SplitStyle(SplitState::Vertical);
|
||||
args->SplitStyle(SplitState::Horizontal);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -259,7 +259,7 @@ void AppCommandlineArgs::_buildFocusTabParser()
|
||||
// that `this` will still be safe - this function just lets us know this
|
||||
// command was parsed.
|
||||
_focusTabCommand->callback([&, this]() {
|
||||
// Build the action from the values we've parsed on the commandline.
|
||||
// Buld the action from the values we've parsed on the commandline.
|
||||
auto focusTabAction = winrt::make_self<implementation::ActionAndArgs>();
|
||||
|
||||
if (_focusTabIndex >= 0)
|
||||
@@ -393,7 +393,7 @@ void AppCommandlineArgs::_resetStateToDefault()
|
||||
// Function Description:
|
||||
// - Builds a list of Commandline objects for the given argc,argv. Each
|
||||
// Commandline represents a single command to parse. These commands can be
|
||||
// separated by ";", which indicates the start of the next commandline. If the
|
||||
// seperated by ";", which indicates the start of the next commandline. If the
|
||||
// user would like to provide ';' in the text of the commandline, they can
|
||||
// escape it as "\;".
|
||||
// Arguments:
|
||||
@@ -423,7 +423,7 @@ std::vector<Commandline> AppCommandlineArgs::BuildCommands(winrt::array_view<con
|
||||
// Function Description:
|
||||
// - Builds a list of Commandline objects for the given argc,argv. Each
|
||||
// Commandline represents a single command to parse. These commands can be
|
||||
// separated by ";", which indicates the start of the next commandline. If the
|
||||
// seperated by ";", which indicates the start of the next commandline. If the
|
||||
// user would like to provide ';' in the text of the commandline, they can
|
||||
// escape it as "\;".
|
||||
// Arguments:
|
||||
@@ -457,7 +457,7 @@ std::vector<Commandline> AppCommandlineArgs::BuildCommands(const std::vector<con
|
||||
// Function Description:
|
||||
// - Update and append Commandline objects for the given arg to the given list
|
||||
// of commands. Each Commandline represents a single command to parse. These
|
||||
// commands can be separated by ";", which indicates the start of the next
|
||||
// commands can be seperated by ";", which indicates the start of the next
|
||||
// commandline. If the user would like to provide ';' in the text of the
|
||||
// commandline, they can escape it as "\;".
|
||||
// - As we parse arg, if it doesn't contain a delimiter in it, we'll add it to
|
||||
|
||||
@@ -25,10 +25,20 @@ static constexpr std::string_view ActionKey{ "action" };
|
||||
static constexpr std::string_view UnboundKey{ "unbound" };
|
||||
|
||||
static constexpr std::string_view CopyTextKey{ "copy" };
|
||||
static constexpr std::string_view CopyTextWithoutNewlinesKey{ "copyTextWithoutNewlines" }; // Legacy
|
||||
static constexpr std::string_view PasteTextKey{ "paste" };
|
||||
static constexpr std::string_view OpenNewTabDropdownKey{ "openNewTabDropdown" };
|
||||
static constexpr std::string_view DuplicateTabKey{ "duplicateTab" };
|
||||
static constexpr std::string_view NewTabKey{ "newTab" };
|
||||
static constexpr std::string_view NewTabWithProfile0Key{ "newTabProfile0" }; // Legacy
|
||||
static constexpr std::string_view NewTabWithProfile1Key{ "newTabProfile1" }; // Legacy
|
||||
static constexpr std::string_view NewTabWithProfile2Key{ "newTabProfile2" }; // Legacy
|
||||
static constexpr std::string_view NewTabWithProfile3Key{ "newTabProfile3" }; // Legacy
|
||||
static constexpr std::string_view NewTabWithProfile4Key{ "newTabProfile4" }; // Legacy
|
||||
static constexpr std::string_view NewTabWithProfile5Key{ "newTabProfile5" }; // Legacy
|
||||
static constexpr std::string_view NewTabWithProfile6Key{ "newTabProfile6" }; // Legacy
|
||||
static constexpr std::string_view NewTabWithProfile7Key{ "newTabProfile7" }; // Legacy
|
||||
static constexpr std::string_view NewTabWithProfile8Key{ "newTabProfile8" }; // Legacy
|
||||
static constexpr std::string_view NewWindowKey{ "newWindow" };
|
||||
static constexpr std::string_view CloseWindowKey{ "closeWindow" };
|
||||
static constexpr std::string_view CloseTabKey{ "closeTab" };
|
||||
@@ -36,17 +46,37 @@ static constexpr std::string_view ClosePaneKey{ "closePane" };
|
||||
static constexpr std::string_view SwitchtoTabKey{ "switchToTab" };
|
||||
static constexpr std::string_view NextTabKey{ "nextTab" };
|
||||
static constexpr std::string_view PrevTabKey{ "prevTab" };
|
||||
static constexpr std::string_view AdjustFontSizeKey{ "adjustFontSize" };
|
||||
static constexpr std::string_view IncreaseFontSizeKey{ "increaseFontSize" };
|
||||
static constexpr std::string_view DecreaseFontSizeKey{ "decreaseFontSize" };
|
||||
static constexpr std::string_view ResetFontSizeKey{ "resetFontSize" };
|
||||
static constexpr std::string_view ScrollupKey{ "scrollUp" };
|
||||
static constexpr std::string_view ScrolldownKey{ "scrollDown" };
|
||||
static constexpr std::string_view ScrolluppageKey{ "scrollUpPage" };
|
||||
static constexpr std::string_view ScrolldownpageKey{ "scrollDownPage" };
|
||||
static constexpr std::string_view SwitchToTabKey{ "switchToTab" };
|
||||
static constexpr std::string_view OpenSettingsKey{ "openSettings" }; // TODO GH#2557: Add args for OpenSettings
|
||||
static constexpr std::string_view SwitchToTab0Key{ "switchToTab0" }; // Legacy
|
||||
static constexpr std::string_view SwitchToTab1Key{ "switchToTab1" }; // Legacy
|
||||
static constexpr std::string_view SwitchToTab2Key{ "switchToTab2" }; // Legacy
|
||||
static constexpr std::string_view SwitchToTab3Key{ "switchToTab3" }; // Legacy
|
||||
static constexpr std::string_view SwitchToTab4Key{ "switchToTab4" }; // Legacy
|
||||
static constexpr std::string_view SwitchToTab5Key{ "switchToTab5" }; // Legacy
|
||||
static constexpr std::string_view SwitchToTab6Key{ "switchToTab6" }; // Legacy
|
||||
static constexpr std::string_view SwitchToTab7Key{ "switchToTab7" }; // Legacy
|
||||
static constexpr std::string_view SwitchToTab8Key{ "switchToTab8" }; // Legacy
|
||||
static constexpr std::string_view OpenSettingsKey{ "openSettings" }; // Legacy
|
||||
static constexpr std::string_view SplitPaneKey{ "splitPane" };
|
||||
static constexpr std::string_view SplitHorizontalKey{ "splitHorizontal" }; // Legacy
|
||||
static constexpr std::string_view SplitVerticalKey{ "splitVertical" }; // Legacy
|
||||
static constexpr std::string_view ResizePaneKey{ "resizePane" };
|
||||
static constexpr std::string_view ResizePaneLeftKey{ "resizePaneLeft" }; // Legacy
|
||||
static constexpr std::string_view ResizePaneRightKey{ "resizePaneRight" }; // Legacy
|
||||
static constexpr std::string_view ResizePaneUpKey{ "resizePaneUp" }; // Legacy
|
||||
static constexpr std::string_view ResizePaneDownKey{ "resizePaneDown" }; // Legacy
|
||||
static constexpr std::string_view MoveFocusKey{ "moveFocus" };
|
||||
static constexpr std::string_view MoveFocusLeftKey{ "moveFocusLeft" }; // Legacy
|
||||
static constexpr std::string_view MoveFocusRightKey{ "moveFocusRight" }; // Legacy
|
||||
static constexpr std::string_view MoveFocusUpKey{ "moveFocusUp" }; // Legacy
|
||||
static constexpr std::string_view MoveFocusDownKey{ "moveFocusDown" }; // Legacy
|
||||
static constexpr std::string_view FindKey{ "find" };
|
||||
static constexpr std::string_view ToggleFullscreenKey{ "toggleFullscreen" };
|
||||
|
||||
@@ -60,25 +90,55 @@ static constexpr std::string_view ToggleFullscreenKey{ "toggleFullscreen" };
|
||||
// about here.
|
||||
static const std::map<std::string_view, ShortcutAction, std::less<>> commandNames{
|
||||
{ CopyTextKey, ShortcutAction::CopyText },
|
||||
{ CopyTextWithoutNewlinesKey, ShortcutAction::CopyTextWithoutNewlines },
|
||||
{ PasteTextKey, ShortcutAction::PasteText },
|
||||
{ OpenNewTabDropdownKey, ShortcutAction::OpenNewTabDropdown },
|
||||
{ DuplicateTabKey, ShortcutAction::DuplicateTab },
|
||||
{ NewTabKey, ShortcutAction::NewTab },
|
||||
{ NewTabWithProfile0Key, ShortcutAction::NewTabProfile0 },
|
||||
{ NewTabWithProfile1Key, ShortcutAction::NewTabProfile1 },
|
||||
{ NewTabWithProfile2Key, ShortcutAction::NewTabProfile2 },
|
||||
{ NewTabWithProfile3Key, ShortcutAction::NewTabProfile3 },
|
||||
{ NewTabWithProfile4Key, ShortcutAction::NewTabProfile4 },
|
||||
{ NewTabWithProfile5Key, ShortcutAction::NewTabProfile5 },
|
||||
{ NewTabWithProfile6Key, ShortcutAction::NewTabProfile6 },
|
||||
{ NewTabWithProfile7Key, ShortcutAction::NewTabProfile7 },
|
||||
{ NewTabWithProfile8Key, ShortcutAction::NewTabProfile8 },
|
||||
{ NewWindowKey, ShortcutAction::NewWindow },
|
||||
{ CloseWindowKey, ShortcutAction::CloseWindow },
|
||||
{ CloseTabKey, ShortcutAction::CloseTab },
|
||||
{ ClosePaneKey, ShortcutAction::ClosePane },
|
||||
{ NextTabKey, ShortcutAction::NextTab },
|
||||
{ PrevTabKey, ShortcutAction::PrevTab },
|
||||
{ AdjustFontSizeKey, ShortcutAction::AdjustFontSize },
|
||||
{ IncreaseFontSizeKey, ShortcutAction::IncreaseFontSize },
|
||||
{ DecreaseFontSizeKey, ShortcutAction::DecreaseFontSize },
|
||||
{ ResetFontSizeKey, ShortcutAction::ResetFontSize },
|
||||
{ ScrollupKey, ShortcutAction::ScrollUp },
|
||||
{ ScrolldownKey, ShortcutAction::ScrollDown },
|
||||
{ ScrolluppageKey, ShortcutAction::ScrollUpPage },
|
||||
{ ScrolldownpageKey, ShortcutAction::ScrollDownPage },
|
||||
{ SwitchToTabKey, ShortcutAction::SwitchToTab },
|
||||
{ SwitchToTab0Key, ShortcutAction::SwitchToTab0 },
|
||||
{ SwitchToTab1Key, ShortcutAction::SwitchToTab1 },
|
||||
{ SwitchToTab2Key, ShortcutAction::SwitchToTab2 },
|
||||
{ SwitchToTab3Key, ShortcutAction::SwitchToTab3 },
|
||||
{ SwitchToTab4Key, ShortcutAction::SwitchToTab4 },
|
||||
{ SwitchToTab5Key, ShortcutAction::SwitchToTab5 },
|
||||
{ SwitchToTab6Key, ShortcutAction::SwitchToTab6 },
|
||||
{ SwitchToTab7Key, ShortcutAction::SwitchToTab7 },
|
||||
{ SwitchToTab8Key, ShortcutAction::SwitchToTab8 },
|
||||
{ SplitHorizontalKey, ShortcutAction::SplitHorizontal },
|
||||
{ SplitVerticalKey, ShortcutAction::SplitVertical },
|
||||
{ ResizePaneKey, ShortcutAction::ResizePane },
|
||||
{ ResizePaneLeftKey, ShortcutAction::ResizePaneLeft },
|
||||
{ ResizePaneRightKey, ShortcutAction::ResizePaneRight },
|
||||
{ ResizePaneUpKey, ShortcutAction::ResizePaneUp },
|
||||
{ ResizePaneDownKey, ShortcutAction::ResizePaneDown },
|
||||
{ MoveFocusKey, ShortcutAction::MoveFocus },
|
||||
{ MoveFocusLeftKey, ShortcutAction::MoveFocusLeft },
|
||||
{ MoveFocusRightKey, ShortcutAction::MoveFocusRight },
|
||||
{ MoveFocusUpKey, ShortcutAction::MoveFocusUp },
|
||||
{ MoveFocusDownKey, ShortcutAction::MoveFocusDown },
|
||||
{ OpenSettingsKey, ShortcutAction::OpenSettings },
|
||||
{ ToggleFullscreenKey, ShortcutAction::ToggleFullscreen },
|
||||
{ SplitPaneKey, ShortcutAction::SplitPane },
|
||||
@@ -89,6 +149,146 @@ static const std::map<std::string_view, ShortcutAction, std::less<>> commandName
|
||||
using ParseResult = std::tuple<IActionArgs, std::vector<TerminalApp::SettingsLoadWarnings>>;
|
||||
using ParseActionFunction = std::function<ParseResult(const Json::Value&)>;
|
||||
|
||||
// Function Description:
|
||||
// - Creates a function that can be used to generate a SplitPaneArgs for the
|
||||
// legacy Split[SplitState] actions. These actions don't accept args from
|
||||
// json, instead, they just return a SplitPaneArgs with the style already
|
||||
// pre-defined, based on the input param.
|
||||
// - TODO: GH#1069 Remove this before 1.0, and force an upgrade to the new args.
|
||||
// Arguments:
|
||||
// - style: the split style to create the parse function for.
|
||||
// Return Value:
|
||||
// - A function that can be used to "parse" json into one of the legacy
|
||||
// Split[SplitState] args.
|
||||
ParseActionFunction LegacyParseSplitPaneArgs(SplitState style)
|
||||
{
|
||||
auto pfn = [style](const Json::Value & /*value*/) -> ParseResult {
|
||||
auto args = winrt::make_self<winrt::TerminalApp::implementation::SplitPaneArgs>();
|
||||
args->SplitStyle(style);
|
||||
return { *args, {} };
|
||||
};
|
||||
return pfn;
|
||||
}
|
||||
|
||||
// Function Description:
|
||||
// - Creates a function that can be used to generate a MoveFocusArgs for the
|
||||
// legacy MoveFocus[Direction] actions. These actions don't accept args from
|
||||
// json, instead, they just return a MoveFocusArgs with the Direction already
|
||||
// per-defined, based on the input param.
|
||||
// - TODO: GH#1069 Remove this before 1.0, and force an upgrade to the new args.
|
||||
// Arguments:
|
||||
// - direction: the direction to create the parse function for.
|
||||
// Return Value:
|
||||
// - A function that can be used to "parse" json into one of the legacy
|
||||
// MoveFocus[Direction] args.
|
||||
ParseActionFunction LegacyParseMoveFocusArgs(Direction direction)
|
||||
{
|
||||
auto pfn = [direction](const Json::Value & /*value*/) -> ParseResult {
|
||||
auto args = winrt::make_self<winrt::TerminalApp::implementation::MoveFocusArgs>();
|
||||
args->Direction(direction);
|
||||
return { *args, {} };
|
||||
};
|
||||
return pfn;
|
||||
}
|
||||
|
||||
// Function Description:
|
||||
// - Creates a function that can be used to generate a ResizePaneArgs for the
|
||||
// legacy ResizePane[Direction] actions. These actions don't accept args from
|
||||
// json, instead, they just return a ResizePaneArgs with the Direction already
|
||||
// per-defined, based on the input param.
|
||||
// - TODO: GH#1069 Remove this before 1.0, and force an upgrade to the new args.
|
||||
// Arguments:
|
||||
// - direction: the direction to create the parse function for.
|
||||
// Return Value:
|
||||
// - A function that can be used to "parse" json into one of the legacy
|
||||
// ResizePane[Direction] args.
|
||||
ParseActionFunction LegacyParseResizePaneArgs(Direction direction)
|
||||
{
|
||||
auto pfn = [direction](const Json::Value & /*value*/) -> ParseResult {
|
||||
auto args = winrt::make_self<winrt::TerminalApp::implementation::ResizePaneArgs>();
|
||||
args->Direction(direction);
|
||||
return { *args, {} };
|
||||
};
|
||||
return pfn;
|
||||
}
|
||||
|
||||
// Function Description:
|
||||
// - Creates a function that can be used to generate a NewTabWithProfileArgs for
|
||||
// the legacy NewTabWithProfile[Index] actions. These actions don't accept
|
||||
// args from json, instead, they just return a NewTabWithProfileArgs with the
|
||||
// index already per-defined, based on the input param.
|
||||
// - TODO: GH#1069 Remove this before 1.0, and force an upgrade to the new args.
|
||||
// Arguments:
|
||||
// - index: the profile index to create the parse function for.
|
||||
// Return Value:
|
||||
// - A function that can be used to "parse" json into one of the legacy
|
||||
// NewTabWithProfile[Index] args.
|
||||
ParseActionFunction LegacyParseNewTabWithProfileArgs(int index)
|
||||
{
|
||||
auto pfn = [index](const Json::Value & /*value*/) -> ParseResult {
|
||||
auto args = winrt::make_self<winrt::TerminalApp::implementation::NewTabArgs>();
|
||||
auto newTerminalArgs = winrt::make_self<winrt::TerminalApp::implementation::NewTerminalArgs>();
|
||||
newTerminalArgs->ProfileIndex(index);
|
||||
args->TerminalArgs(*newTerminalArgs);
|
||||
return { *args, {} };
|
||||
};
|
||||
return pfn;
|
||||
}
|
||||
|
||||
// Function Description:
|
||||
// - Creates a function that can be used to generate a SwitchToTabArgs for the
|
||||
// legacy SwitchToTab[Index] actions. These actions don't accept args from
|
||||
// json, instead, they just return a SwitchToTabArgs with the index already
|
||||
// per-defined, based on the input param.
|
||||
// - TODO: GH#1069 Remove this before 1.0, and force an upgrade to the new args.
|
||||
// Arguments:
|
||||
// - index: the tab index to create the parse function for.
|
||||
// Return Value:
|
||||
// - A function that can be used to "parse" json into one of the legacy
|
||||
// SwitchToTab[Index] args.
|
||||
ParseActionFunction LegacyParseSwitchToTabArgs(int index)
|
||||
{
|
||||
auto pfn = [index](const Json::Value & /*value*/) -> ParseResult {
|
||||
auto args = winrt::make_self<winrt::TerminalApp::implementation::SwitchToTabArgs>();
|
||||
args->TabIndex(index);
|
||||
return { *args, {} };
|
||||
};
|
||||
return pfn;
|
||||
}
|
||||
|
||||
// Function Description:
|
||||
// - Used to generate a CopyTextArgs for the legacy CopyTextWithoutNewlines
|
||||
// action.
|
||||
// - TODO: GH#1069 Remove this before 1.0, and force an upgrade to the new args.
|
||||
// Arguments:
|
||||
// - direction: the direction to create the parse function for.
|
||||
// Return Value:
|
||||
// - A CopyTextArgs with TrimWhitespace set to true, to emulate "CopyTextWithoutNewlines".
|
||||
ParseResult LegacyParseCopyTextWithoutNewlinesArgs(const Json::Value& /*json*/)
|
||||
{
|
||||
auto args = winrt::make_self<winrt::TerminalApp::implementation::CopyTextArgs>();
|
||||
args->TrimWhitespace(false);
|
||||
return { *args, {} };
|
||||
};
|
||||
|
||||
// Function Description:
|
||||
// - Used to generate a AdjustFontSizeArgs for IncreaseFontSize/DecreaseFontSize
|
||||
// actions with a delta of 1/-1.
|
||||
// - TODO: GH#1069 Remove this before 1.0, and force an upgrade to the new args.
|
||||
// Arguments:
|
||||
// - delta: the font size delta to create the parse function for.
|
||||
// Return Value:
|
||||
// - A function that can be used to "parse" json into an AdjustFontSizeArgs.
|
||||
ParseActionFunction LegacyParseAdjustFontSizeArgs(int delta)
|
||||
{
|
||||
auto pfn = [delta](const Json::Value & /*value*/) -> ParseResult {
|
||||
auto args = winrt::make_self<winrt::TerminalApp::implementation::AdjustFontSizeArgs>();
|
||||
args->Delta(delta);
|
||||
return { *args, {} };
|
||||
};
|
||||
return pfn;
|
||||
}
|
||||
|
||||
// This is a map of ShortcutAction->function<IActionArgs(Json::Value)>. It holds
|
||||
// a set of deserializer functions that can be used to deserialize a IActionArgs
|
||||
// from json. Each type of IActionArgs that can accept arbitrary args should be
|
||||
@@ -96,25 +296,55 @@ using ParseActionFunction = std::function<ParseResult(const Json::Value&)>;
|
||||
// value.
|
||||
static const std::map<ShortcutAction, ParseActionFunction, std::less<>> argParsers{
|
||||
{ ShortcutAction::CopyText, winrt::TerminalApp::implementation::CopyTextArgs::FromJson },
|
||||
{ ShortcutAction::CopyTextWithoutNewlines, LegacyParseCopyTextWithoutNewlinesArgs },
|
||||
|
||||
{ ShortcutAction::NewTab, winrt::TerminalApp::implementation::NewTabArgs::FromJson },
|
||||
{ ShortcutAction::NewTabProfile0, LegacyParseNewTabWithProfileArgs(0) },
|
||||
{ ShortcutAction::NewTabProfile1, LegacyParseNewTabWithProfileArgs(1) },
|
||||
{ ShortcutAction::NewTabProfile2, LegacyParseNewTabWithProfileArgs(2) },
|
||||
{ ShortcutAction::NewTabProfile3, LegacyParseNewTabWithProfileArgs(3) },
|
||||
{ ShortcutAction::NewTabProfile4, LegacyParseNewTabWithProfileArgs(4) },
|
||||
{ ShortcutAction::NewTabProfile5, LegacyParseNewTabWithProfileArgs(5) },
|
||||
{ ShortcutAction::NewTabProfile6, LegacyParseNewTabWithProfileArgs(6) },
|
||||
{ ShortcutAction::NewTabProfile7, LegacyParseNewTabWithProfileArgs(7) },
|
||||
{ ShortcutAction::NewTabProfile8, LegacyParseNewTabWithProfileArgs(8) },
|
||||
|
||||
{ ShortcutAction::SwitchToTab, winrt::TerminalApp::implementation::SwitchToTabArgs::FromJson },
|
||||
{ ShortcutAction::SwitchToTab0, LegacyParseSwitchToTabArgs(0) },
|
||||
{ ShortcutAction::SwitchToTab1, LegacyParseSwitchToTabArgs(1) },
|
||||
{ ShortcutAction::SwitchToTab2, LegacyParseSwitchToTabArgs(2) },
|
||||
{ ShortcutAction::SwitchToTab3, LegacyParseSwitchToTabArgs(3) },
|
||||
{ ShortcutAction::SwitchToTab4, LegacyParseSwitchToTabArgs(4) },
|
||||
{ ShortcutAction::SwitchToTab5, LegacyParseSwitchToTabArgs(5) },
|
||||
{ ShortcutAction::SwitchToTab6, LegacyParseSwitchToTabArgs(6) },
|
||||
{ ShortcutAction::SwitchToTab7, LegacyParseSwitchToTabArgs(7) },
|
||||
{ ShortcutAction::SwitchToTab8, LegacyParseSwitchToTabArgs(8) },
|
||||
|
||||
{ ShortcutAction::ResizePane, winrt::TerminalApp::implementation::ResizePaneArgs::FromJson },
|
||||
{ ShortcutAction::ResizePaneLeft, LegacyParseResizePaneArgs(Direction::Left) },
|
||||
{ ShortcutAction::ResizePaneRight, LegacyParseResizePaneArgs(Direction::Right) },
|
||||
{ ShortcutAction::ResizePaneUp, LegacyParseResizePaneArgs(Direction::Up) },
|
||||
{ ShortcutAction::ResizePaneDown, LegacyParseResizePaneArgs(Direction::Down) },
|
||||
|
||||
{ ShortcutAction::MoveFocus, winrt::TerminalApp::implementation::MoveFocusArgs::FromJson },
|
||||
{ ShortcutAction::MoveFocusLeft, LegacyParseMoveFocusArgs(Direction::Left) },
|
||||
{ ShortcutAction::MoveFocusRight, LegacyParseMoveFocusArgs(Direction::Right) },
|
||||
{ ShortcutAction::MoveFocusUp, LegacyParseMoveFocusArgs(Direction::Up) },
|
||||
{ ShortcutAction::MoveFocusDown, LegacyParseMoveFocusArgs(Direction::Down) },
|
||||
|
||||
{ ShortcutAction::AdjustFontSize, winrt::TerminalApp::implementation::AdjustFontSizeArgs::FromJson },
|
||||
{ ShortcutAction::DecreaseFontSize, LegacyParseAdjustFontSizeArgs(-1) },
|
||||
{ ShortcutAction::IncreaseFontSize, LegacyParseAdjustFontSizeArgs(1) },
|
||||
|
||||
{ ShortcutAction::SplitPane, winrt::TerminalApp::implementation::SplitPaneArgs::FromJson },
|
||||
{ ShortcutAction::SplitVertical, LegacyParseSplitPaneArgs(SplitState::Vertical) },
|
||||
{ ShortcutAction::SplitHorizontal, LegacyParseSplitPaneArgs(SplitState::Horizontal) },
|
||||
|
||||
{ ShortcutAction::Invalid, nullptr },
|
||||
};
|
||||
|
||||
// Function Description:
|
||||
// - Small helper to create a json value serialization of a single
|
||||
// KeyBinding->Action mapping.
|
||||
// KeyBinding->Action maping.
|
||||
// {
|
||||
// keys:[String],
|
||||
// command:String
|
||||
@@ -286,7 +516,7 @@ std::vector<::TerminalApp::SettingsLoadWarnings> winrt::TerminalApp::implementat
|
||||
warnings.insert(warnings.end(), parseWarnings.begin(), parseWarnings.end());
|
||||
|
||||
// if an arg parser was registered, but failed, bail
|
||||
if (pfn && args == nullptr)
|
||||
if (args == nullptr)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -138,29 +138,6 @@ catch (...)
|
||||
|
||||
namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
// Function Description:
|
||||
// - Get the AppLogic for the current active Xaml application, or null if there isn't one.
|
||||
// Return value:
|
||||
// - A pointer (bare) to the applogic, or nullptr. The app logic outlives all other objects,
|
||||
// unless the application is in a terrible way, so this is "safe."
|
||||
AppLogic* AppLogic::Current() noexcept
|
||||
try
|
||||
{
|
||||
if (auto currentXamlApp{ winrt::Windows::UI::Xaml::Application::Current().try_as<winrt::TerminalApp::App>() })
|
||||
{
|
||||
if (auto appLogicPointer{ winrt::get_self<AppLogic>(currentXamlApp.Logic()) })
|
||||
{
|
||||
return appLogicPointer;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
LOG_CAUGHT_EXCEPTION();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
AppLogic::AppLogic() :
|
||||
_dialogLock{},
|
||||
_loadedInitialSettings{ false },
|
||||
@@ -241,7 +218,7 @@ namespace winrt::TerminalApp::implementation
|
||||
_root->Loaded({ this, &AppLogic::_OnLoaded });
|
||||
_root->Create();
|
||||
|
||||
_ApplyTheme(_settings->GlobalSettings().GetTheme());
|
||||
_ApplyTheme(_settings->GlobalSettings().GetRequestedTheme());
|
||||
|
||||
TraceLoggingWrite(
|
||||
g_hTerminalAppProvider,
|
||||
@@ -283,27 +260,7 @@ namespace winrt::TerminalApp::implementation
|
||||
// IMPORTANT: Set the requested theme of the dialog, because the
|
||||
// PopupRoot isn't directly in the Xaml tree of our root. So the dialog
|
||||
// won't inherit our RequestedTheme automagically.
|
||||
// GH#5195, GH#3654 Because we cannot set RequestedTheme at the application level,
|
||||
// we occasionally run into issues where parts of our UI end up themed incorrectly.
|
||||
// Dialogs, for example, live under a different Xaml root element than the rest of
|
||||
// our application. This makes our popup menus and buttons "disappear" when the
|
||||
// user wants Terminal to be in a different theme than the rest of the system.
|
||||
// This hack---and it _is_ a hack--walks up a dialog's ancestry and forces the
|
||||
// theme on each element up to the root. We're relying a bit on Xaml's implementation
|
||||
// details here, but it does have the desired effect.
|
||||
// It's not enough to set the theme on the dialog alone.
|
||||
auto themingLambda{ [this](const Windows::Foundation::IInspectable& sender, const RoutedEventArgs&) {
|
||||
auto theme{ _settings->GlobalSettings().GetTheme() };
|
||||
auto element{ sender.try_as<winrt::Windows::UI::Xaml::FrameworkElement>() };
|
||||
while (element)
|
||||
{
|
||||
element.RequestedTheme(theme);
|
||||
element = element.Parent().try_as<winrt::Windows::UI::Xaml::FrameworkElement>();
|
||||
}
|
||||
} };
|
||||
|
||||
themingLambda(dialog, nullptr); // if it's already in the tree
|
||||
auto loadedRevoker{ dialog.Loaded(winrt::auto_revoke, themingLambda) }; // if it's not yet in the tree
|
||||
dialog.RequestedTheme(_settings->GlobalSettings().GetRequestedTheme());
|
||||
|
||||
// Display the dialog.
|
||||
co_await dialog.ShowAsync(Controls::ContentDialogPlacement::Popup);
|
||||
@@ -453,7 +410,7 @@ namespace winrt::TerminalApp::implementation
|
||||
if (_settings->GlobalSettings().GetShowTabsInTitlebar())
|
||||
{
|
||||
// If we're showing the tabs in the titlebar, we need to use a
|
||||
// TitlebarControl here to calculate how much space to reserve.
|
||||
// TitlebarContol here to calculate how much space to reserve.
|
||||
//
|
||||
// We'll create a fake TitlebarControl, and we'll propose an
|
||||
// available size to it with Measure(). After Measure() is called,
|
||||
@@ -545,7 +502,7 @@ namespace winrt::TerminalApp::implementation
|
||||
LoadSettings();
|
||||
}
|
||||
|
||||
return _settings->GlobalSettings().GetTheme();
|
||||
return _settings->GlobalSettings().GetRequestedTheme();
|
||||
}
|
||||
|
||||
bool AppLogic::GetShowTabsInTitlebar()
|
||||
@@ -660,7 +617,7 @@ namespace winrt::TerminalApp::implementation
|
||||
void AppLogic::_RegisterSettingsChange()
|
||||
{
|
||||
// Get the containing folder.
|
||||
const auto settingsPath{ CascadiaSettings::GetSettingsPath() };
|
||||
std::filesystem::path settingsPath{ CascadiaSettings::GetSettingsPath() };
|
||||
const auto folder = settingsPath.parent_path();
|
||||
|
||||
_reader.create(folder.c_str(),
|
||||
@@ -726,7 +683,7 @@ namespace winrt::TerminalApp::implementation
|
||||
co_await winrt::resume_foreground(_root->Dispatcher());
|
||||
|
||||
// Refresh the UI theme
|
||||
_ApplyTheme(_settings->GlobalSettings().GetTheme());
|
||||
_ApplyTheme(_settings->GlobalSettings().GetRequestedTheme());
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
@@ -885,65 +842,6 @@ namespace winrt::TerminalApp::implementation
|
||||
return { L"" };
|
||||
}
|
||||
|
||||
winrt::hstring AppLogic::ApplicationDisplayName() const
|
||||
{
|
||||
try
|
||||
{
|
||||
const auto package{ winrt::Windows::ApplicationModel::Package::Current() };
|
||||
return package.DisplayName();
|
||||
}
|
||||
CATCH_LOG();
|
||||
|
||||
return RS_(L"ApplicationDisplayNameUnpackaged");
|
||||
}
|
||||
|
||||
winrt::hstring AppLogic::ApplicationVersion() const
|
||||
{
|
||||
try
|
||||
{
|
||||
const auto package{ winrt::Windows::ApplicationModel::Package::Current() };
|
||||
const auto version{ package.Id().Version() };
|
||||
winrt::hstring formatted{ wil::str_printf<std::wstring>(L"%u.%u.%u.%u", version.Major, version.Minor, version.Build, version.Revision) };
|
||||
return formatted;
|
||||
}
|
||||
CATCH_LOG();
|
||||
|
||||
// Try to get the version the old-fashioned way
|
||||
try
|
||||
{
|
||||
struct LocalizationInfo
|
||||
{
|
||||
WORD language, codepage;
|
||||
};
|
||||
// Use the current module instance handle for TerminalApp.dll, nullptr for WindowsTerminal.exe
|
||||
auto filename{ wil::GetModuleFileNameW<std::wstring>(wil::GetModuleInstanceHandle()) };
|
||||
auto size{ GetFileVersionInfoSizeExW(0, filename.c_str(), nullptr) };
|
||||
THROW_LAST_ERROR_IF(size == 0);
|
||||
auto versionBuffer{ std::make_unique<std::byte[]>(size) };
|
||||
THROW_IF_WIN32_BOOL_FALSE(GetFileVersionInfoExW(0, filename.c_str(), 0, size, versionBuffer.get()));
|
||||
|
||||
// Get the list of Version localizations
|
||||
LocalizationInfo* pVarLocalization{ nullptr };
|
||||
UINT varLen{ 0 };
|
||||
THROW_IF_WIN32_BOOL_FALSE(VerQueryValueW(versionBuffer.get(), L"\\VarFileInfo\\Translation", reinterpret_cast<void**>(&pVarLocalization), &varLen));
|
||||
THROW_HR_IF(E_UNEXPECTED, varLen < sizeof(*pVarLocalization)); // there must be at least one translation
|
||||
|
||||
// Get the product version from the localized version compartment
|
||||
// We're using String/ProductVersion here because our build pipeline puts more rich information in it (like the branch name)
|
||||
// than in the unlocalized numeric version fields.
|
||||
WCHAR* pProductVersion{ nullptr };
|
||||
UINT versionLen{ 0 };
|
||||
const auto localizedVersionName{ wil::str_printf<std::wstring>(L"\\StringFileInfo\\%04x%04x\\ProductVersion",
|
||||
pVarLocalization->language ? pVarLocalization->language : 0x0409, // well-known en-US LCID
|
||||
pVarLocalization->codepage) };
|
||||
THROW_IF_WIN32_BOOL_FALSE(VerQueryValueW(versionBuffer.get(), localizedVersionName.c_str(), reinterpret_cast<void**>(&pProductVersion), &versionLen));
|
||||
return { pProductVersion };
|
||||
}
|
||||
CATCH_LOG();
|
||||
|
||||
return RS_(L"ApplicationVersionUnknown");
|
||||
}
|
||||
|
||||
// -------------------------------- WinRT Events ---------------------------------
|
||||
// Winrt events need a method for adding a callback to the event and removing the callback.
|
||||
// These macros will define them both for you.
|
||||
|
||||
@@ -15,8 +15,6 @@ namespace winrt::TerminalApp::implementation
|
||||
struct AppLogic : AppLogicT<AppLogic>
|
||||
{
|
||||
public:
|
||||
static AppLogic* Current() noexcept;
|
||||
|
||||
AppLogic();
|
||||
~AppLogic() = default;
|
||||
|
||||
@@ -30,9 +28,6 @@ namespace winrt::TerminalApp::implementation
|
||||
int32_t SetStartupCommandline(array_view<const winrt::hstring> actions);
|
||||
winrt::hstring EarlyExitMessage();
|
||||
|
||||
winrt::hstring ApplicationDisplayName() const;
|
||||
winrt::hstring ApplicationVersion() const;
|
||||
|
||||
Windows::Foundation::Point GetLaunchDimensions(uint32_t dpi);
|
||||
winrt::Windows::Foundation::Point GetLaunchInitialPositions(int32_t defaultInitialX, int32_t defaultInitialY);
|
||||
winrt::Windows::UI::Xaml::ElementTheme GetRequestedTheme();
|
||||
|
||||
@@ -35,9 +35,6 @@ namespace TerminalApp
|
||||
|
||||
String Title { get; };
|
||||
|
||||
String ApplicationDisplayName { get; };
|
||||
String ApplicationVersion { get; };
|
||||
|
||||
Windows.Foundation.Point GetLaunchDimensions(UInt32 dpi);
|
||||
Windows.Foundation.Point GetLaunchInitialPositions(Int32 defaultInitialX, Int32 defaultInitialY);
|
||||
Windows.UI.Xaml.ElementTheme GetRequestedTheme();
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
#include "../../inc/DefaultSettings.h"
|
||||
#include "AppLogic.h"
|
||||
#include "Utils.h"
|
||||
#include "LibraryResources.h"
|
||||
|
||||
#include "PowershellCoreProfileGenerator.h"
|
||||
#include "WslDistroGenerator.h"
|
||||
@@ -28,17 +27,18 @@ static constexpr std::wstring_view PACKAGED_PROFILE_ICON_PATH{ L"ms-appx:///Prof
|
||||
static constexpr std::wstring_view PACKAGED_PROFILE_ICON_EXTENSION{ L".png" };
|
||||
static constexpr std::wstring_view DEFAULT_LINUX_ICON_GUID{ L"{9acb9455-ca41-5af7-950f-6bca1bc9722f}" };
|
||||
|
||||
// make sure this matches defaults.json.
|
||||
static constexpr std::wstring_view DEFAULT_WINDOWS_POWERSHELL_GUID{ L"{61c54bbd-c2c6-5271-96e7-009a87ff44bf}" };
|
||||
|
||||
// Method Description:
|
||||
// - Returns the settings currently in use by the entire Terminal application.
|
||||
// Throws:
|
||||
// - HR E_INVALIDARG if the app isn't up and running.
|
||||
const CascadiaSettings& CascadiaSettings::GetCurrentAppSettings()
|
||||
{
|
||||
auto appLogic{ ::winrt::TerminalApp::implementation::AppLogic::Current() };
|
||||
auto currentXamlApp{ winrt::Windows::UI::Xaml::Application::Current().as<winrt::TerminalApp::App>() };
|
||||
THROW_HR_IF_NULL(E_INVALIDARG, currentXamlApp);
|
||||
|
||||
auto appLogic = winrt::get_self<winrt::TerminalApp::implementation::AppLogic>(currentXamlApp.Logic());
|
||||
THROW_HR_IF_NULL(E_INVALIDARG, appLogic);
|
||||
|
||||
return *(appLogic->GetSettings());
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@ CascadiaSettings::CascadiaSettings(const bool addDynamicProfiles)
|
||||
// - profileName: the name of the profile's GUID to return.
|
||||
// Return Value:
|
||||
// - the GUID associated with the profile name.
|
||||
std::optional<GUID> CascadiaSettings::FindGuid(const std::wstring_view profileName) const noexcept
|
||||
std::optional<GUID> CascadiaSettings::FindGuid(const std::wstring& profileName) const noexcept
|
||||
{
|
||||
std::optional<GUID> profileGuid{};
|
||||
|
||||
@@ -244,7 +244,7 @@ void CascadiaSettings::_ValidateProfilesHaveGuid()
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Checks if the "defaultProfile" is set to one of the profiles we
|
||||
// - Checks if the "globals.defaultProfile" is set to one of the profiles we
|
||||
// actually have. If the value is unset, or the value is set to something that
|
||||
// doesn't exist in the list of profiles, we'll arbitrarily pick the first
|
||||
// profile to use temporarily as the default.
|
||||
@@ -673,40 +673,3 @@ void CascadiaSettings::_ValidateKeybindings()
|
||||
_warnings.insert(_warnings.end(), keybindingWarnings.begin(), keybindingWarnings.end());
|
||||
}
|
||||
}
|
||||
|
||||
// Method Description
|
||||
// - Replaces known tokens DEFAULT_PROFILE, PRODUCT and VERSION in the settings template
|
||||
// with their expected values. DEFAULT_PROFILE is updated to match PowerShell Core's GUID
|
||||
// if such a profile is detected. If it isn't, it'll be set to Windows PowerShell's GUID.
|
||||
// Arguments:
|
||||
// - settingsTemplate: a settings template
|
||||
// Return value:
|
||||
// - The new settings string.
|
||||
std::string CascadiaSettings::_ApplyFirstRunChangesToSettingsTemplate(std::string_view settingsTemplate) const
|
||||
{
|
||||
std::string finalSettings{ settingsTemplate };
|
||||
auto replace{ [](std::string& haystack, std::string_view needle, std::string_view replacement) {
|
||||
auto pos{ std::string::npos };
|
||||
while ((pos = haystack.rfind(needle, pos)) != std::string::npos)
|
||||
{
|
||||
haystack.replace(pos, needle.size(), replacement);
|
||||
}
|
||||
} };
|
||||
|
||||
std::wstring defaultProfileGuid{ DEFAULT_WINDOWS_POWERSHELL_GUID };
|
||||
if (const auto psCoreProfileGuid{ FindGuid(PowershellCoreProfileGenerator::GetPreferredPowershellProfileName()) })
|
||||
{
|
||||
defaultProfileGuid = Utils::GuidToString(*psCoreProfileGuid);
|
||||
}
|
||||
|
||||
replace(finalSettings, "%DEFAULT_PROFILE%", til::u16u8(defaultProfileGuid));
|
||||
if (const auto appLogic{ winrt::TerminalApp::implementation::AppLogic::Current() })
|
||||
{
|
||||
replace(finalSettings, "%VERSION%", til::u16u8(appLogic->ApplicationVersion()));
|
||||
replace(finalSettings, "%PRODUCT%", til::u16u8(appLogic->ApplicationDisplayName()));
|
||||
}
|
||||
|
||||
replace(finalSettings, "%COMMAND_PROMPT_LOCALIZED_NAME%", RS_A(L"CommandPromptDisplayName"));
|
||||
|
||||
return finalSettings;
|
||||
}
|
||||
|
||||
@@ -34,7 +34,6 @@ namespace TerminalAppLocalTests
|
||||
namespace TerminalAppUnitTests
|
||||
{
|
||||
class DynamicProfileTests;
|
||||
class JsonTests;
|
||||
};
|
||||
|
||||
namespace TerminalApp
|
||||
@@ -66,10 +65,10 @@ public:
|
||||
static std::unique_ptr<CascadiaSettings> FromJson(const Json::Value& json);
|
||||
void LayerJson(const Json::Value& json);
|
||||
|
||||
static std::filesystem::path GetSettingsPath();
|
||||
static std::filesystem::path GetDefaultSettingsPath();
|
||||
static std::wstring GetSettingsPath(const bool useRoamingPath = false);
|
||||
static std::wstring GetDefaultSettingsPath();
|
||||
|
||||
std::optional<GUID> FindGuid(const std::wstring_view profileName) const noexcept;
|
||||
std::optional<GUID> FindGuid(const std::wstring& profileName) const noexcept;
|
||||
const Profile* FindProfile(GUID profileGuid) const noexcept;
|
||||
|
||||
std::vector<TerminalApp::SettingsLoadWarnings>& GetWarnings();
|
||||
@@ -95,7 +94,6 @@ private:
|
||||
static const Json::Value& _GetDisabledProfileSourcesJsonObject(const Json::Value& json);
|
||||
bool _PrependSchemaDirective();
|
||||
bool _AppendDynamicProfilesToUserSettings();
|
||||
std::string _ApplyFirstRunChangesToSettingsTemplate(std::string_view settingsTemplate) const;
|
||||
|
||||
void _ApplyDefaultsFromUserSettings();
|
||||
|
||||
@@ -126,5 +124,4 @@ private:
|
||||
friend class TerminalAppLocalTests::KeyBindingsTests;
|
||||
friend class TerminalAppLocalTests::TabTests;
|
||||
friend class TerminalAppUnitTests::DynamicProfileTests;
|
||||
friend class TerminalAppUnitTests::JsonTests;
|
||||
};
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
// defaults.h is a file containing the default json settings in a std::string_view
|
||||
#include "defaults.h"
|
||||
#include "defaults-universal.h"
|
||||
// userDefault.h is like the above, but with a default template for the user's settings.json.
|
||||
// userDefault.h is like the above, but with a default template for the user's profiles.json.
|
||||
#include "userDefaults.h"
|
||||
// Both defaults.h and userDefaults.h are generated at build time into the
|
||||
// "Generated Files" directory.
|
||||
@@ -23,8 +23,7 @@ using namespace winrt::Microsoft::Terminal::TerminalControl;
|
||||
using namespace winrt::TerminalApp;
|
||||
using namespace ::Microsoft::Console;
|
||||
|
||||
static constexpr std::wstring_view SettingsFilename{ L"settings.json" };
|
||||
static constexpr std::wstring_view LegacySettingsFilename{ L"profiles.json" };
|
||||
static constexpr std::wstring_view SettingsFilename{ L"profiles.json" };
|
||||
static constexpr std::wstring_view UnpackagedSettingsFolderName{ L"Microsoft\\Windows Terminal\\" };
|
||||
|
||||
static constexpr std::wstring_view DefaultsFilename{ L"defaults.json" };
|
||||
@@ -34,6 +33,7 @@ static constexpr std::string_view ProfilesKey{ "profiles" };
|
||||
static constexpr std::string_view DefaultSettingsKey{ "defaults" };
|
||||
static constexpr std::string_view ProfilesListKey{ "list" };
|
||||
static constexpr std::string_view KeybindingsKey{ "keybindings" };
|
||||
static constexpr std::string_view GlobalsKey{ "globals" };
|
||||
static constexpr std::string_view SchemesKey{ "schemes" };
|
||||
|
||||
static constexpr std::string_view DisabledProfileSourcesKey{ "disabledProfileSources" };
|
||||
@@ -48,7 +48,7 @@ static constexpr std::string_view SettingsSchemaFragment{ "\n"
|
||||
// it will load the settings from our packaged localappdata. If we're
|
||||
// running as an unpackaged application, it will read it from the path
|
||||
// we've set under localappdata.
|
||||
// - Loads both the settings from the defaults.json and the user's settings.json
|
||||
// - Loads both the settings from the defaults.json and the user's profiles.json
|
||||
// - Also runs and dynamic profile generators. If any of those generators create
|
||||
// new profiles, we'll write the user settings back to the file, with the new
|
||||
// profiles inserted into their list of profiles.
|
||||
@@ -74,22 +74,20 @@ std::unique_ptr<CascadiaSettings> CascadiaSettings::LoadAll()
|
||||
{
|
||||
resultPtr->_ParseJsonString(fileData.value(), false);
|
||||
}
|
||||
|
||||
// Load profiles from dynamic profile generators. _userSettings should be
|
||||
// created by now, because we're going to check in there for any generators
|
||||
// that should be disabled (if the user had any settings.)
|
||||
resultPtr->_LoadDynamicProfiles();
|
||||
|
||||
if (!fileHasData)
|
||||
else
|
||||
{
|
||||
// We didn't find the user settings. We'll need to create a file
|
||||
// to use as the user defaults.
|
||||
// For now, just parse our user settings template as their user settings.
|
||||
auto userSettings{ resultPtr->_ApplyFirstRunChangesToSettingsTemplate(UserSettingsJson) };
|
||||
resultPtr->_ParseJsonString(userSettings, false);
|
||||
resultPtr->_ParseJsonString(UserSettingsJson, false);
|
||||
needToWriteFile = true;
|
||||
}
|
||||
|
||||
// Load profiles from dynamic profile generators. _userSettings should be
|
||||
// created by now, because we're going to check in there for any generators
|
||||
// that should be disabled.
|
||||
resultPtr->_LoadDynamicProfiles();
|
||||
|
||||
// See microsoft/terminal#2325: find the defaultSettings from the user's
|
||||
// settings. Layer those settings upon all the existing profiles we have
|
||||
// (defaults and dynamic profiles). We'll also set
|
||||
@@ -179,7 +177,7 @@ std::unique_ptr<CascadiaSettings> CascadiaSettings::LoadAll()
|
||||
TraceLoggingWrite(
|
||||
g_hTerminalAppProvider, // handle to TerminalApp tracelogging provider
|
||||
"CustomKeybindings",
|
||||
TraceLoggingDescription("Event emitted when custom keybindings are identified on load/reload"),
|
||||
TraceLoggingDescription("Event emitted when custom keybindings are idenfitied on load/reload"),
|
||||
TraceLoggingUtf8String(keybindingsString.c_str(), "Keybindings", "Keybindings as JSON"),
|
||||
TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES),
|
||||
TelemetryPrivacyDataTag(PDT_ProductAndServiceUsage));
|
||||
@@ -503,8 +501,19 @@ std::unique_ptr<CascadiaSettings> CascadiaSettings::FromJson(const Json::Value&
|
||||
// <none>
|
||||
void CascadiaSettings::LayerJson(const Json::Value& json)
|
||||
{
|
||||
// microsoft/terminal#2906: First layer the root object as our globals. If
|
||||
// there is also a `globals` object, layer that one on top of the settings
|
||||
// from the root.
|
||||
_globals.LayerJson(json);
|
||||
|
||||
if (auto globals{ json[GlobalsKey.data()] })
|
||||
{
|
||||
if (globals.isObject())
|
||||
{
|
||||
_globals.LayerJson(globals);
|
||||
}
|
||||
}
|
||||
|
||||
if (auto schemes{ json[SchemesKey.data()] })
|
||||
{
|
||||
for (auto schemeJson : schemes)
|
||||
@@ -610,6 +619,7 @@ void CascadiaSettings::_ApplyDefaultsFromUserSettings()
|
||||
// If `profiles` was an object, then look for the `defaults` object
|
||||
// underneath it for the default profile settings.
|
||||
auto defaultSettings{ Json::Value::null };
|
||||
|
||||
if (const auto profiles{ _userSettings[JsonKey(ProfilesKey)] })
|
||||
{
|
||||
if (profiles.isObject())
|
||||
@@ -618,8 +628,6 @@ void CascadiaSettings::_ApplyDefaultsFromUserSettings()
|
||||
}
|
||||
}
|
||||
|
||||
// cache and apply default profile settings
|
||||
// from user settings file
|
||||
if (defaultSettings)
|
||||
{
|
||||
_userDefaultProfileSettings = defaultSettings;
|
||||
@@ -696,7 +704,7 @@ ColorScheme* CascadiaSettings::_FindMatchingColorScheme(const Json::Value& schem
|
||||
bool CascadiaSettings::_IsPackaged()
|
||||
{
|
||||
UINT32 length = 0;
|
||||
LONG rc = GetCurrentPackageFullName(&length, nullptr);
|
||||
LONG rc = GetCurrentPackageFullName(&length, NULL);
|
||||
return rc != APPMODEL_ERROR_NO_PACKAGE;
|
||||
}
|
||||
|
||||
@@ -716,15 +724,15 @@ void CascadiaSettings::_WriteSettings(const std::string_view content)
|
||||
wil::unique_hfile hOut{ CreateFileW(pathToSettingsFile.c_str(),
|
||||
GENERIC_WRITE,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
nullptr,
|
||||
NULL,
|
||||
CREATE_ALWAYS,
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
nullptr) };
|
||||
NULL) };
|
||||
if (!hOut)
|
||||
{
|
||||
THROW_LAST_ERROR();
|
||||
}
|
||||
THROW_LAST_ERROR_IF(!WriteFile(hOut.get(), content.data(), gsl::narrow<DWORD>(content.size()), nullptr, nullptr));
|
||||
THROW_LAST_ERROR_IF(!WriteFile(hOut.get(), content.data(), gsl::narrow<DWORD>(content.size()), 0, 0));
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
@@ -749,31 +757,33 @@ std::optional<std::string> CascadiaSettings::_ReadUserSettings()
|
||||
|
||||
if (!hFile)
|
||||
{
|
||||
// GH#5186 - We moved from profiles.json to settings.json; we want to
|
||||
// migrate any file we find. We're using MoveFile in case their settings.json
|
||||
// is a symbolic link.
|
||||
auto pathToLegacySettingsFile{ pathToSettingsFile };
|
||||
pathToLegacySettingsFile.replace_filename(LegacySettingsFilename);
|
||||
// GH#1770 - Now that we're _not_ roaming our settings, do a quick check
|
||||
// to see if there's a file in the Roaming App data folder. If there is
|
||||
// a file there, but not in the LocalAppData, it's likely the user is
|
||||
// upgrading from a version of the terminal from before this change.
|
||||
// We'll try moving the file from the Roaming app data folder to the
|
||||
// local appdata folder.
|
||||
|
||||
wil::unique_hfile hLegacyFile{ CreateFileW(pathToLegacySettingsFile.c_str(),
|
||||
GENERIC_READ,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
nullptr,
|
||||
OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
nullptr) };
|
||||
const auto pathToRoamingSettingsFile{ CascadiaSettings::GetSettingsPath(true) };
|
||||
wil::unique_hfile hRoamingFile{ CreateFileW(pathToRoamingSettingsFile.c_str(),
|
||||
GENERIC_READ,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
nullptr,
|
||||
OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
nullptr) };
|
||||
|
||||
if (hLegacyFile)
|
||||
if (hRoamingFile)
|
||||
{
|
||||
// Close the file handle, move it, and re-open the file in its new location.
|
||||
hLegacyFile.reset();
|
||||
hRoamingFile.reset();
|
||||
|
||||
// Note: We're unsure if this is unsafe. Theoretically it's possible
|
||||
// that two instances of the app will try and move the settings file
|
||||
// simultaneously. We don't know what might happen in that scenario,
|
||||
// but we're also not sure how to safely lock the file to prevent
|
||||
// that from occurring.
|
||||
THROW_LAST_ERROR_IF(!MoveFile(pathToLegacySettingsFile.c_str(),
|
||||
THROW_LAST_ERROR_IF(!MoveFile(pathToRoamingSettingsFile.c_str(),
|
||||
pathToSettingsFile.c_str()));
|
||||
|
||||
hFile.reset(CreateFileW(pathToSettingsFile.c_str(),
|
||||
@@ -831,18 +841,22 @@ std::optional<std::string> CascadiaSettings::_ReadFile(HANDLE hFile)
|
||||
// package, or in its unpackaged location. This path is under the "Local
|
||||
// AppData" folder, so it _doesn't_ roam to other machines.
|
||||
// - If the application is unpackaged,
|
||||
// the file will end up under e.g. C:\Users\admin\AppData\Local\Microsoft\Windows Terminal\settings.json
|
||||
// the file will end up under e.g. C:\Users\admin\AppData\Local\Microsoft\Windows Terminal\profiles.json
|
||||
// Arguments:
|
||||
// - <none>
|
||||
// Return Value:
|
||||
// - the full path to the settings file
|
||||
std::filesystem::path CascadiaSettings::GetSettingsPath()
|
||||
std::wstring CascadiaSettings::GetSettingsPath(const bool useRoamingPath)
|
||||
{
|
||||
wil::unique_cotaskmem_string localAppDataFolder;
|
||||
// KF_FLAG_FORCE_APP_DATA_REDIRECTION, when engaged, causes SHGet... to return
|
||||
// the new AppModel paths (Packages/xxx/RoamingState, etc.) for standard path requests.
|
||||
// Using this flag allows us to avoid Windows.Storage.ApplicationData completely.
|
||||
THROW_IF_FAILED(SHGetKnownFolderPath(FOLDERID_LocalAppData, KF_FLAG_FORCE_APP_DATA_REDIRECTION, nullptr, &localAppDataFolder));
|
||||
const auto knowFolderId = useRoamingPath ? FOLDERID_RoamingAppData : FOLDERID_LocalAppData;
|
||||
if (FAILED(SHGetKnownFolderPath(knowFolderId, KF_FLAG_FORCE_APP_DATA_REDIRECTION, 0, &localAppDataFolder)))
|
||||
{
|
||||
THROW_LAST_ERROR();
|
||||
}
|
||||
|
||||
std::filesystem::path parentDirectoryForSettingsFile{ localAppDataFolder.get() };
|
||||
|
||||
@@ -857,7 +871,7 @@ std::filesystem::path CascadiaSettings::GetSettingsPath()
|
||||
return parentDirectoryForSettingsFile / SettingsFilename;
|
||||
}
|
||||
|
||||
std::filesystem::path CascadiaSettings::GetDefaultSettingsPath()
|
||||
std::wstring CascadiaSettings::GetDefaultSettingsPath()
|
||||
{
|
||||
// Both of these posts suggest getting the path to the exe, then removing
|
||||
// the exe's name to get the package root:
|
||||
@@ -905,9 +919,10 @@ const Json::Value& CascadiaSettings::_GetProfilesJsonObject(const Json::Value& j
|
||||
// given object
|
||||
const Json::Value& CascadiaSettings::_GetDisabledProfileSourcesJsonObject(const Json::Value& json)
|
||||
{
|
||||
if (!json)
|
||||
// Check the globals first, then look in the root.
|
||||
if (json.isMember(JsonKey(GlobalsKey)))
|
||||
{
|
||||
return Json::Value::nullSingleton();
|
||||
return json[JsonKey(GlobalsKey)][JsonKey(DisabledProfileSourcesKey)];
|
||||
}
|
||||
return json[JsonKey(DisabledProfileSourcesKey)];
|
||||
}
|
||||
|
||||
@@ -14,10 +14,10 @@ using namespace winrt::Microsoft::Terminal::Settings;
|
||||
using namespace winrt::Microsoft::Terminal::TerminalControl;
|
||||
|
||||
static constexpr std::string_view NameKey{ "name" };
|
||||
static constexpr std::string_view TableKey{ "colors" };
|
||||
static constexpr std::string_view ForegroundKey{ "foreground" };
|
||||
static constexpr std::string_view BackgroundKey{ "background" };
|
||||
static constexpr std::string_view SelectionBackgroundKey{ "selectionBackground" };
|
||||
static constexpr std::string_view CursorColorKey{ "cursorColor" };
|
||||
static constexpr std::array<std::string_view, 16> TableColors = {
|
||||
"black",
|
||||
"red",
|
||||
@@ -42,18 +42,16 @@ ColorScheme::ColorScheme() :
|
||||
_table{},
|
||||
_defaultForeground{ DEFAULT_FOREGROUND_WITH_ALPHA },
|
||||
_defaultBackground{ DEFAULT_BACKGROUND_WITH_ALPHA },
|
||||
_selectionBackground{ DEFAULT_FOREGROUND },
|
||||
_cursorColor{ DEFAULT_CURSOR_COLOR }
|
||||
_selectionBackground{ DEFAULT_FOREGROUND }
|
||||
{
|
||||
}
|
||||
|
||||
ColorScheme::ColorScheme(std::wstring name, COLORREF defaultFg, COLORREF defaultBg, COLORREF cursorColor) :
|
||||
ColorScheme::ColorScheme(std::wstring name, COLORREF defaultFg, COLORREF defaultBg) :
|
||||
_schemeName{ name },
|
||||
_table{},
|
||||
_defaultForeground{ defaultFg },
|
||||
_defaultBackground{ defaultBg },
|
||||
_selectionBackground{ DEFAULT_FOREGROUND },
|
||||
_cursorColor{ cursorColor }
|
||||
_selectionBackground{ DEFAULT_FOREGROUND }
|
||||
{
|
||||
}
|
||||
|
||||
@@ -73,7 +71,6 @@ void ColorScheme::ApplyScheme(TerminalSettings terminalSettings) const
|
||||
terminalSettings.DefaultForeground(_defaultForeground);
|
||||
terminalSettings.DefaultBackground(_defaultBackground);
|
||||
terminalSettings.SelectionBackground(_selectionBackground);
|
||||
terminalSettings.CursorColor(_cursorColor);
|
||||
|
||||
auto const tableCount = gsl::narrow_cast<int>(_table.size());
|
||||
for (int i = 0; i < tableCount; i++)
|
||||
@@ -95,7 +92,6 @@ Json::Value ColorScheme::ToJson() const
|
||||
root[JsonKey(ForegroundKey)] = Utils::ColorToHexString(_defaultForeground);
|
||||
root[JsonKey(BackgroundKey)] = Utils::ColorToHexString(_defaultBackground);
|
||||
root[JsonKey(SelectionBackgroundKey)] = Utils::ColorToHexString(_selectionBackground);
|
||||
root[JsonKey(CursorColorKey)] = Utils::ColorToHexString(_cursorColor);
|
||||
|
||||
int i = 0;
|
||||
for (const auto& colorName : TableColors)
|
||||
@@ -170,10 +166,21 @@ void ColorScheme::LayerJson(const Json::Value& json)
|
||||
const auto color = Utils::ColorFromHexString(sbString.asString());
|
||||
_selectionBackground = color;
|
||||
}
|
||||
if (auto sbString{ json[JsonKey(CursorColorKey)] })
|
||||
|
||||
// Legacy Deserialization. Leave in place to allow forward compatibility
|
||||
if (auto table{ json[JsonKey(TableKey)] })
|
||||
{
|
||||
const auto color = Utils::ColorFromHexString(sbString.asString());
|
||||
_cursorColor = color;
|
||||
int i = 0;
|
||||
|
||||
for (const auto& tableEntry : table)
|
||||
{
|
||||
if (tableEntry.isString())
|
||||
{
|
||||
auto color = Utils::ColorFromHexString(tableEntry.asString());
|
||||
_table.at(i) = color;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
int i = 0;
|
||||
@@ -213,11 +220,6 @@ COLORREF ColorScheme::GetSelectionBackground() const noexcept
|
||||
return _selectionBackground;
|
||||
}
|
||||
|
||||
COLORREF ColorScheme::GetCursorColor() const noexcept
|
||||
{
|
||||
return _cursorColor;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Parse the name from the JSON representation of a ColorScheme.
|
||||
// Arguments:
|
||||
|
||||
@@ -35,7 +35,7 @@ class TerminalApp::ColorScheme
|
||||
{
|
||||
public:
|
||||
ColorScheme();
|
||||
ColorScheme(std::wstring name, COLORREF defaultFg, COLORREF defaultBg, COLORREF cursorColor);
|
||||
ColorScheme(std::wstring name, COLORREF defaultFg, COLORREF defaultBg);
|
||||
~ColorScheme();
|
||||
|
||||
void ApplyScheme(winrt::Microsoft::Terminal::Settings::TerminalSettings terminalSettings) const;
|
||||
@@ -50,7 +50,6 @@ public:
|
||||
COLORREF GetForeground() const noexcept;
|
||||
COLORREF GetBackground() const noexcept;
|
||||
COLORREF GetSelectionBackground() const noexcept;
|
||||
COLORREF GetCursorColor() const noexcept;
|
||||
|
||||
static std::optional<std::wstring> GetNameFromJson(const Json::Value& json);
|
||||
|
||||
@@ -60,7 +59,6 @@ private:
|
||||
COLORREF _defaultForeground;
|
||||
COLORREF _defaultBackground;
|
||||
COLORREF _selectionBackground;
|
||||
COLORREF _cursorColor;
|
||||
|
||||
friend class TerminalAppLocalTests::SettingsTests;
|
||||
friend class TerminalAppLocalTests::ColorSchemeTests;
|
||||
|
||||
@@ -1,147 +0,0 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#include "pch.h"
|
||||
#include "DebugTapConnection.h"
|
||||
|
||||
using namespace ::winrt::Microsoft::Terminal::TerminalConnection;
|
||||
using namespace ::winrt::Windows::Foundation;
|
||||
namespace winrt::Microsoft::TerminalApp::implementation
|
||||
{
|
||||
// DebugInputTapConnection is an implementation detail of DebugTapConnection.
|
||||
// It wraps the _actual_ connection so it can hook WriteInput and forward it
|
||||
// into the actual debug panel.
|
||||
class DebugInputTapConnection : public winrt::implements<DebugInputTapConnection, ITerminalConnection>
|
||||
{
|
||||
public:
|
||||
DebugInputTapConnection(winrt::com_ptr<DebugTapConnection> pairedTap, ITerminalConnection wrappedConnection) :
|
||||
_pairedTap{ pairedTap },
|
||||
_wrappedConnection{ std::move(wrappedConnection) }
|
||||
{
|
||||
}
|
||||
~DebugInputTapConnection() = default;
|
||||
void Start()
|
||||
{
|
||||
_wrappedConnection.Start();
|
||||
}
|
||||
void WriteInput(hstring const& data)
|
||||
{
|
||||
_pairedTap->_PrintInput(data);
|
||||
_wrappedConnection.WriteInput(data);
|
||||
}
|
||||
void Resize(uint32_t rows, uint32_t columns) { _wrappedConnection.Resize(rows, columns); }
|
||||
void Close() { _wrappedConnection.Close(); }
|
||||
winrt::event_token TerminalOutput(TerminalOutputHandler const& args) { return _wrappedConnection.TerminalOutput(args); };
|
||||
void TerminalOutput(winrt::event_token const& token) noexcept { _wrappedConnection.TerminalOutput(token); };
|
||||
winrt::event_token StateChanged(TypedEventHandler<ITerminalConnection, IInspectable> const& handler) { return _wrappedConnection.StateChanged(handler); };
|
||||
void StateChanged(winrt::event_token const& token) noexcept { _wrappedConnection.StateChanged(token); };
|
||||
ConnectionState State() const noexcept { return _wrappedConnection.State(); }
|
||||
|
||||
private:
|
||||
winrt::com_ptr<DebugTapConnection> _pairedTap;
|
||||
ITerminalConnection _wrappedConnection;
|
||||
};
|
||||
|
||||
DebugTapConnection::DebugTapConnection(ITerminalConnection wrappedConnection)
|
||||
{
|
||||
_outputRevoker = wrappedConnection.TerminalOutput(winrt::auto_revoke, { this, &DebugTapConnection::_OutputHandler });
|
||||
_stateChangedRevoker = wrappedConnection.StateChanged(winrt::auto_revoke, [this](auto&& /*s*/, auto&& /*e*/) {
|
||||
_StateChangedHandlers(*this, nullptr);
|
||||
});
|
||||
_wrappedConnection = wrappedConnection;
|
||||
}
|
||||
|
||||
DebugTapConnection::~DebugTapConnection()
|
||||
{
|
||||
}
|
||||
|
||||
void DebugTapConnection::Start()
|
||||
{
|
||||
// presume the wrapped connection is started.
|
||||
}
|
||||
|
||||
void DebugTapConnection::WriteInput(hstring const& data)
|
||||
{
|
||||
// If the user types into the tap side, forward it to the input side
|
||||
if (auto strongInput{ _inputSide.get() })
|
||||
{
|
||||
auto inputAsTap{ winrt::get_self<DebugInputTapConnection>(strongInput) };
|
||||
inputAsTap->WriteInput(data);
|
||||
}
|
||||
}
|
||||
|
||||
void DebugTapConnection::Resize(uint32_t /*rows*/, uint32_t /*columns*/)
|
||||
{
|
||||
// no resize events are propagated
|
||||
}
|
||||
|
||||
void DebugTapConnection::Close()
|
||||
{
|
||||
_outputRevoker.revoke();
|
||||
_stateChangedRevoker.revoke();
|
||||
_wrappedConnection = nullptr;
|
||||
}
|
||||
|
||||
ConnectionState DebugTapConnection::State() const noexcept
|
||||
{
|
||||
if (auto strongConnection{ _wrappedConnection.get() })
|
||||
{
|
||||
return strongConnection.State();
|
||||
}
|
||||
return ConnectionState::Failed;
|
||||
}
|
||||
|
||||
static std::wstring _sanitizeString(const std::wstring_view str)
|
||||
{
|
||||
std::wstring newString{ str.begin(), str.end() };
|
||||
for (auto& ch : newString)
|
||||
{
|
||||
if (ch < 0x20)
|
||||
{
|
||||
ch += 0x2400;
|
||||
}
|
||||
else if (ch == 0x20)
|
||||
{
|
||||
ch = 0x2423; // replace space with ␣
|
||||
}
|
||||
else if (ch == 0x7f)
|
||||
{
|
||||
ch = 0x2421; // replace del with ␡
|
||||
}
|
||||
}
|
||||
return newString;
|
||||
}
|
||||
|
||||
void DebugTapConnection::_OutputHandler(const hstring str)
|
||||
{
|
||||
_TerminalOutputHandlers(_sanitizeString(str));
|
||||
}
|
||||
|
||||
// Called by the DebugInputTapConnection to print user input
|
||||
void DebugTapConnection::_PrintInput(const hstring& str)
|
||||
{
|
||||
auto clean{ _sanitizeString(str) };
|
||||
auto formatted{ wil::str_printf<std::wstring>(L"\x1b[91m%ls\x1b[m", clean.data()) };
|
||||
_TerminalOutputHandlers(formatted);
|
||||
}
|
||||
|
||||
// Wire us up so that we can forward input through
|
||||
void DebugTapConnection::SetInputTap(const Microsoft::Terminal::TerminalConnection::ITerminalConnection& inputTap)
|
||||
{
|
||||
_inputSide = inputTap;
|
||||
}
|
||||
}
|
||||
|
||||
// Function Description
|
||||
// - Takes one connection and returns two connections:
|
||||
// 1. One that can be used in place of the original connection (wrapped)
|
||||
// 2. One that will print raw VT sequences sent into and received _from_ the original connection.
|
||||
std::tuple<ITerminalConnection, ITerminalConnection> OpenDebugTapConnection(ITerminalConnection baseConnection)
|
||||
{
|
||||
using namespace winrt::Microsoft::TerminalApp::implementation;
|
||||
auto debugSide{ winrt::make_self<DebugTapConnection>(baseConnection) };
|
||||
auto inputSide{ winrt::make_self<DebugInputTapConnection>(debugSide, baseConnection) };
|
||||
debugSide->SetInputTap(*inputSide);
|
||||
std::tuple<ITerminalConnection, ITerminalConnection> p{ *inputSide, *debugSide };
|
||||
return p;
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <winrt/Microsoft.Terminal.TerminalConnection.h>
|
||||
#include "../../inc/cppwinrt_utils.h"
|
||||
|
||||
namespace winrt::Microsoft::TerminalApp::implementation
|
||||
{
|
||||
class DebugInputTapConnection;
|
||||
class DebugTapConnection : public winrt::implements<DebugTapConnection, winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection>
|
||||
{
|
||||
public:
|
||||
DebugTapConnection(Microsoft::Terminal::TerminalConnection::ITerminalConnection wrappedConnection);
|
||||
~DebugTapConnection();
|
||||
void Start();
|
||||
void WriteInput(hstring const& data);
|
||||
void Resize(uint32_t rows, uint32_t columns);
|
||||
void Close();
|
||||
winrt::Microsoft::Terminal::TerminalConnection::ConnectionState State() const noexcept;
|
||||
|
||||
void SetInputTap(const Microsoft::Terminal::TerminalConnection::ITerminalConnection& inputTap);
|
||||
|
||||
WINRT_CALLBACK(TerminalOutput, winrt::Microsoft::Terminal::TerminalConnection::TerminalOutputHandler);
|
||||
|
||||
TYPED_EVENT(StateChanged, winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection, winrt::Windows::Foundation::IInspectable);
|
||||
|
||||
private:
|
||||
void _PrintInput(const hstring& data);
|
||||
void _OutputHandler(const hstring str);
|
||||
|
||||
winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection::TerminalOutput_revoker _outputRevoker;
|
||||
winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection::StateChanged_revoker _stateChangedRevoker;
|
||||
winrt::weak_ref<Microsoft::Terminal::TerminalConnection::ITerminalConnection> _wrappedConnection;
|
||||
winrt::weak_ref<Microsoft::Terminal::TerminalConnection::ITerminalConnection> _inputSide;
|
||||
|
||||
friend class DebugInputTapConnection;
|
||||
};
|
||||
}
|
||||
|
||||
std::tuple<winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection, winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection> OpenDebugTapConnection(winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection baseConnection);
|
||||
@@ -21,7 +21,7 @@ TerminalApp::Profile CreateDefaultProfile(const std::wstring_view name)
|
||||
gsl::as_bytes(gsl::make_span(name))) };
|
||||
TerminalApp::Profile newProfile{ profileGuid };
|
||||
|
||||
newProfile.SetName(name);
|
||||
newProfile.SetName(static_cast<std::wstring>(name));
|
||||
|
||||
std::wstring iconPath{ PACKAGED_PROFILE_ICON_PATH };
|
||||
iconPath.append(Microsoft::Console::Utils::GuidToString(profileGuid));
|
||||
|
||||
@@ -25,14 +25,13 @@ static constexpr std::string_view InitialColsKey{ "initialCols" };
|
||||
static constexpr std::string_view RowsToScrollKey{ "rowsToScroll" };
|
||||
static constexpr std::string_view InitialPositionKey{ "initialPosition" };
|
||||
static constexpr std::string_view ShowTitleInTitlebarKey{ "showTerminalTitleInTitlebar" };
|
||||
static constexpr std::string_view ThemeKey{ "theme" };
|
||||
static constexpr std::string_view RequestedThemeKey{ "requestedTheme" };
|
||||
static constexpr std::string_view TabWidthModeKey{ "tabWidthMode" };
|
||||
static constexpr std::wstring_view EqualTabWidthModeValue{ L"equal" };
|
||||
static constexpr std::wstring_view TitleLengthTabWidthModeValue{ L"titleLength" };
|
||||
static constexpr std::string_view ShowTabsInTitlebarKey{ "showTabsInTitlebar" };
|
||||
static constexpr std::string_view WordDelimitersKey{ "wordDelimiters" };
|
||||
static constexpr std::string_view CopyOnSelectKey{ "copyOnSelect" };
|
||||
static constexpr std::string_view CopyFormattingKey{ "copyFormatting" };
|
||||
static constexpr std::string_view LaunchModeKey{ "launchMode" };
|
||||
static constexpr std::string_view ConfirmCloseAllKey{ "confirmCloseAllTabs" };
|
||||
static constexpr std::string_view SnapToGridOnResizeKey{ "snapToGridOnResize" };
|
||||
@@ -42,14 +41,6 @@ static constexpr std::wstring_view LightThemeValue{ L"light" };
|
||||
static constexpr std::wstring_view DarkThemeValue{ L"dark" };
|
||||
static constexpr std::wstring_view SystemThemeValue{ L"system" };
|
||||
|
||||
static constexpr std::string_view DebugFeaturesKey{ "debugFeatures" };
|
||||
|
||||
#ifdef _DEBUG
|
||||
static constexpr bool debugFeaturesDefault{ true };
|
||||
#else
|
||||
static constexpr bool debugFeaturesDefault{ false };
|
||||
#endif
|
||||
|
||||
GlobalAppSettings::GlobalAppSettings() :
|
||||
_keybindings{ winrt::make_self<winrt::TerminalApp::implementation::AppKeyBindings>() },
|
||||
_keybindingsWarnings{},
|
||||
@@ -64,13 +55,11 @@ GlobalAppSettings::GlobalAppSettings() :
|
||||
_initialY{},
|
||||
_showTitleInTitlebar{ true },
|
||||
_showTabsInTitlebar{ true },
|
||||
_theme{ ElementTheme::Default },
|
||||
_requestedTheme{ ElementTheme::Default },
|
||||
_tabWidthMode{ TabViewWidthMode::Equal },
|
||||
_wordDelimiters{ DEFAULT_WORD_DELIMITERS },
|
||||
_copyOnSelect{ false },
|
||||
_copyFormatting{ false },
|
||||
_launchMode{ LaunchMode::DefaultMode },
|
||||
_debugFeatures{ debugFeaturesDefault }
|
||||
_launchMode{ LaunchMode::DefaultMode }
|
||||
{
|
||||
}
|
||||
|
||||
@@ -123,14 +112,14 @@ void GlobalAppSettings::SetShowTitleInTitlebar(const bool showTitleInTitlebar) n
|
||||
_showTitleInTitlebar = showTitleInTitlebar;
|
||||
}
|
||||
|
||||
ElementTheme GlobalAppSettings::GetTheme() const noexcept
|
||||
ElementTheme GlobalAppSettings::GetRequestedTheme() const noexcept
|
||||
{
|
||||
return _theme;
|
||||
return _requestedTheme;
|
||||
}
|
||||
|
||||
void GlobalAppSettings::SetTheme(const ElementTheme theme) noexcept
|
||||
void GlobalAppSettings::SetRequestedTheme(const ElementTheme requestedTheme) noexcept
|
||||
{
|
||||
_theme = theme;
|
||||
_requestedTheme = requestedTheme;
|
||||
}
|
||||
|
||||
TabViewWidthMode GlobalAppSettings::GetTabWidthMode() const noexcept
|
||||
@@ -163,11 +152,6 @@ void GlobalAppSettings::SetCopyOnSelect(const bool copyOnSelect) noexcept
|
||||
_copyOnSelect = copyOnSelect;
|
||||
}
|
||||
|
||||
bool GlobalAppSettings::GetCopyFormatting() const noexcept
|
||||
{
|
||||
return _copyFormatting;
|
||||
}
|
||||
|
||||
LaunchMode GlobalAppSettings::GetLaunchMode() const noexcept
|
||||
{
|
||||
return _launchMode;
|
||||
@@ -187,11 +171,6 @@ void GlobalAppSettings::SetConfirmCloseAllTabs(const bool confirmCloseAllTabs) n
|
||||
_confirmCloseAllTabs = confirmCloseAllTabs;
|
||||
}
|
||||
|
||||
bool GlobalAppSettings::DebugFeaturesEnabled() const noexcept
|
||||
{
|
||||
return _debugFeatures;
|
||||
}
|
||||
|
||||
#pragma region ExperimentalSettings
|
||||
bool GlobalAppSettings::GetShowTabsInTitlebar() const noexcept
|
||||
{
|
||||
@@ -252,14 +231,12 @@ Json::Value GlobalAppSettings::ToJson() const
|
||||
jsonObject[JsonKey(ShowTabsInTitlebarKey)] = _showTabsInTitlebar;
|
||||
jsonObject[JsonKey(WordDelimitersKey)] = winrt::to_string(_wordDelimiters);
|
||||
jsonObject[JsonKey(CopyOnSelectKey)] = _copyOnSelect;
|
||||
jsonObject[JsonKey(CopyFormattingKey)] = _copyFormatting;
|
||||
jsonObject[JsonKey(LaunchModeKey)] = winrt::to_string(_SerializeLaunchMode(_launchMode));
|
||||
jsonObject[JsonKey(ThemeKey)] = winrt::to_string(_SerializeTheme(_theme));
|
||||
jsonObject[JsonKey(RequestedThemeKey)] = winrt::to_string(_SerializeTheme(_requestedTheme));
|
||||
jsonObject[JsonKey(TabWidthModeKey)] = winrt::to_string(_SerializeTabWidthMode(_tabWidthMode));
|
||||
jsonObject[JsonKey(KeybindingsKey)] = _keybindings->ToJson();
|
||||
jsonObject[JsonKey(ConfirmCloseAllKey)] = _confirmCloseAllTabs;
|
||||
jsonObject[JsonKey(SnapToGridOnResizeKey)] = _SnapToGridOnResize;
|
||||
jsonObject[JsonKey(DebugFeaturesKey)] = _debugFeatures;
|
||||
|
||||
return jsonObject;
|
||||
}
|
||||
@@ -285,14 +262,22 @@ void GlobalAppSettings::LayerJson(const Json::Value& json)
|
||||
_defaultProfile = guid;
|
||||
}
|
||||
|
||||
JsonUtils::GetBool(json, AlwaysShowTabsKey, _alwaysShowTabs);
|
||||
|
||||
JsonUtils::GetBool(json, ConfirmCloseAllKey, _confirmCloseAllTabs);
|
||||
|
||||
JsonUtils::GetInt(json, InitialRowsKey, _initialRows);
|
||||
|
||||
JsonUtils::GetInt(json, InitialColsKey, _initialCols);
|
||||
|
||||
if (auto alwaysShowTabs{ json[JsonKey(AlwaysShowTabsKey)] })
|
||||
{
|
||||
_alwaysShowTabs = alwaysShowTabs.asBool();
|
||||
}
|
||||
if (auto confirmCloseAllTabs{ json[JsonKey(ConfirmCloseAllKey)] })
|
||||
{
|
||||
_confirmCloseAllTabs = confirmCloseAllTabs.asBool();
|
||||
}
|
||||
if (auto initialRows{ json[JsonKey(InitialRowsKey)] })
|
||||
{
|
||||
_initialRows = initialRows.asInt();
|
||||
}
|
||||
if (auto initialCols{ json[JsonKey(InitialColsKey)] })
|
||||
{
|
||||
_initialCols = initialCols.asInt();
|
||||
}
|
||||
if (auto rowsToScroll{ json[JsonKey(RowsToScrollKey)] })
|
||||
{
|
||||
//if it's not an int we fall back to setting it to 0, which implies using the system setting. This will be the case if it's set to "system"
|
||||
@@ -305,30 +290,38 @@ void GlobalAppSettings::LayerJson(const Json::Value& json)
|
||||
_rowsToScroll = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (auto initialPosition{ json[JsonKey(InitialPositionKey)] })
|
||||
{
|
||||
_ParseInitialPosition(GetWstringFromJson(initialPosition), _initialX, _initialY);
|
||||
}
|
||||
if (auto showTitleInTitlebar{ json[JsonKey(ShowTitleInTitlebarKey)] })
|
||||
{
|
||||
_showTitleInTitlebar = showTitleInTitlebar.asBool();
|
||||
}
|
||||
|
||||
JsonUtils::GetBool(json, ShowTitleInTitlebarKey, _showTitleInTitlebar);
|
||||
if (auto showTabsInTitlebar{ json[JsonKey(ShowTabsInTitlebarKey)] })
|
||||
{
|
||||
_showTabsInTitlebar = showTabsInTitlebar.asBool();
|
||||
}
|
||||
|
||||
JsonUtils::GetBool(json, ShowTabsInTitlebarKey, _showTabsInTitlebar);
|
||||
if (auto wordDelimiters{ json[JsonKey(WordDelimitersKey)] })
|
||||
{
|
||||
_wordDelimiters = GetWstringFromJson(wordDelimiters);
|
||||
}
|
||||
|
||||
JsonUtils::GetWstring(json, WordDelimitersKey, _wordDelimiters);
|
||||
|
||||
JsonUtils::GetBool(json, CopyOnSelectKey, _copyOnSelect);
|
||||
|
||||
JsonUtils::GetBool(json, CopyFormattingKey, _copyFormatting);
|
||||
if (auto copyOnSelect{ json[JsonKey(CopyOnSelectKey)] })
|
||||
{
|
||||
_copyOnSelect = copyOnSelect.asBool();
|
||||
}
|
||||
|
||||
if (auto launchMode{ json[JsonKey(LaunchModeKey)] })
|
||||
{
|
||||
_launchMode = _ParseLaunchMode(GetWstringFromJson(launchMode));
|
||||
}
|
||||
|
||||
if (auto theme{ json[JsonKey(ThemeKey)] })
|
||||
if (auto requestedTheme{ json[JsonKey(RequestedThemeKey)] })
|
||||
{
|
||||
_theme = _ParseTheme(GetWstringFromJson(theme));
|
||||
_requestedTheme = _ParseTheme(GetWstringFromJson(requestedTheme));
|
||||
}
|
||||
|
||||
if (auto tabWidthMode{ json[JsonKey(TabWidthModeKey)] })
|
||||
@@ -348,10 +341,10 @@ void GlobalAppSettings::LayerJson(const Json::Value& json)
|
||||
_keybindingsWarnings.insert(_keybindingsWarnings.end(), warnings.begin(), warnings.end());
|
||||
}
|
||||
|
||||
JsonUtils::GetBool(json, SnapToGridOnResizeKey, _SnapToGridOnResize);
|
||||
|
||||
// GetBool will only override the current value if the key exists
|
||||
JsonUtils::GetBool(json, DebugFeaturesKey, _debugFeatures);
|
||||
if (auto snapToGridOnResize{ json[JsonKey(SnapToGridOnResizeKey)] })
|
||||
{
|
||||
_SnapToGridOnResize = snapToGridOnResize.asBool();
|
||||
}
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
|
||||
@@ -53,10 +53,8 @@ public:
|
||||
bool GetConfirmCloseAllTabs() const noexcept;
|
||||
void SetConfirmCloseAllTabs(const bool confirmCloseAllTabs) noexcept;
|
||||
|
||||
winrt::Windows::UI::Xaml::ElementTheme GetTheme() const noexcept;
|
||||
void SetTheme(const winrt::Windows::UI::Xaml::ElementTheme requestedTheme) noexcept;
|
||||
void SetRequestedTheme(const winrt::Windows::UI::Xaml::ElementTheme requestedTheme) noexcept;
|
||||
|
||||
winrt::Microsoft::UI::Xaml::Controls::TabViewWidthMode GetTabWidthMode() const noexcept;
|
||||
void SetTabWidthMode(const winrt::Microsoft::UI::Xaml::Controls::TabViewWidthMode tabWidthMode);
|
||||
|
||||
bool GetShowTabsInTitlebar() const noexcept;
|
||||
@@ -68,8 +66,6 @@ public:
|
||||
bool GetCopyOnSelect() const noexcept;
|
||||
void SetCopyOnSelect(const bool copyOnSelect) noexcept;
|
||||
|
||||
bool GetCopyFormatting() const noexcept;
|
||||
|
||||
std::optional<int32_t> GetInitialX() const noexcept;
|
||||
|
||||
std::optional<int32_t> GetInitialY() const noexcept;
|
||||
@@ -77,7 +73,9 @@ public:
|
||||
winrt::TerminalApp::LaunchMode GetLaunchMode() const noexcept;
|
||||
void SetLaunchMode(const winrt::TerminalApp::LaunchMode launchMode);
|
||||
|
||||
bool DebugFeaturesEnabled() const noexcept;
|
||||
winrt::Windows::UI::Xaml::ElementTheme GetRequestedTheme() const noexcept;
|
||||
|
||||
winrt::Microsoft::UI::Xaml::Controls::TabViewWidthMode GetTabWidthMode() const noexcept;
|
||||
|
||||
Json::Value ToJson() const;
|
||||
static GlobalAppSettings FromJson(const Json::Value& json);
|
||||
@@ -112,14 +110,11 @@ private:
|
||||
bool _showTabsInTitlebar;
|
||||
std::wstring _wordDelimiters;
|
||||
bool _copyOnSelect;
|
||||
bool _copyFormatting;
|
||||
winrt::Windows::UI::Xaml::ElementTheme _theme;
|
||||
winrt::Windows::UI::Xaml::ElementTheme _requestedTheme;
|
||||
winrt::Microsoft::UI::Xaml::Controls::TabViewWidthMode _tabWidthMode;
|
||||
|
||||
winrt::TerminalApp::LaunchMode _launchMode;
|
||||
|
||||
bool _debugFeatures;
|
||||
|
||||
static winrt::Windows::UI::Xaml::ElementTheme _ParseTheme(const std::wstring& themeString) noexcept;
|
||||
static std::wstring_view _SerializeTheme(const winrt::Windows::UI::Xaml::ElementTheme theme) noexcept;
|
||||
|
||||
|
||||
@@ -52,74 +52,8 @@ void TerminalApp::JsonUtils::GetOptionalDouble(const Json::Value& json,
|
||||
const auto conversionFn = [](const Json::Value& value) -> double {
|
||||
return value.asFloat();
|
||||
};
|
||||
const auto validationFn = [](const Json::Value& value) -> bool {
|
||||
return value.isNumeric();
|
||||
};
|
||||
GetOptionalValue(json,
|
||||
key,
|
||||
target,
|
||||
conversionFn,
|
||||
validationFn);
|
||||
}
|
||||
|
||||
void TerminalApp::JsonUtils::GetInt(const Json::Value& json,
|
||||
std::string_view key,
|
||||
int& target)
|
||||
{
|
||||
const auto conversionFn = [](const Json::Value& value) -> int {
|
||||
return value.asInt();
|
||||
};
|
||||
const auto validationFn = [](const Json::Value& value) -> bool {
|
||||
return value.isInt();
|
||||
};
|
||||
GetValue(json, key, target, conversionFn, validationFn);
|
||||
}
|
||||
|
||||
void TerminalApp::JsonUtils::GetUInt(const Json::Value& json,
|
||||
std::string_view key,
|
||||
uint32_t& target)
|
||||
{
|
||||
const auto conversionFn = [](const Json::Value& value) -> uint32_t {
|
||||
return value.asUInt();
|
||||
};
|
||||
const auto validationFn = [](const Json::Value& value) -> bool {
|
||||
return value.isUInt();
|
||||
};
|
||||
GetValue(json, key, target, conversionFn, validationFn);
|
||||
}
|
||||
|
||||
void TerminalApp::JsonUtils::GetDouble(const Json::Value& json,
|
||||
std::string_view key,
|
||||
double& target)
|
||||
{
|
||||
const auto conversionFn = [](const Json::Value& value) -> double {
|
||||
return value.asFloat();
|
||||
};
|
||||
const auto validationFn = [](const Json::Value& value) -> bool {
|
||||
return value.isNumeric();
|
||||
};
|
||||
GetValue(json, key, target, conversionFn, validationFn);
|
||||
}
|
||||
|
||||
void TerminalApp::JsonUtils::GetBool(const Json::Value& json,
|
||||
std::string_view key,
|
||||
bool& target)
|
||||
{
|
||||
const auto conversionFn = [](const Json::Value& value) -> bool {
|
||||
return value.asBool();
|
||||
};
|
||||
const auto validationFn = [](const Json::Value& value) -> bool {
|
||||
return value.isBool();
|
||||
};
|
||||
GetValue(json, key, target, conversionFn, validationFn);
|
||||
}
|
||||
|
||||
void TerminalApp::JsonUtils::GetWstring(const Json::Value& json,
|
||||
std::string_view key,
|
||||
std::wstring& target)
|
||||
{
|
||||
const auto conversionFn = [](const Json::Value& value) -> std::wstring {
|
||||
return GetWstringFromJson(value);
|
||||
};
|
||||
GetValue(json, key, target, conversionFn, nullptr);
|
||||
conversionFn);
|
||||
}
|
||||
|
||||
@@ -46,99 +46,24 @@ namespace TerminalApp::JsonUtils
|
||||
// - target: the optional object to receive the value from json
|
||||
// - conversion: a std::function<T(const Json::Value&)> which can be used to
|
||||
// convert the Json::Value to the appropriate type.
|
||||
// - validation: optional, if provided, will be called first to ensure that
|
||||
// the json::value is of the correct type before attempting to call
|
||||
// `conversion`.
|
||||
// Return Value:
|
||||
// - <none>
|
||||
template<typename T, typename F>
|
||||
void GetOptionalValue(const Json::Value& json,
|
||||
std::string_view key,
|
||||
std::optional<T>& target,
|
||||
F&& conversion,
|
||||
const std::function<bool(const Json::Value&)>& validation = nullptr)
|
||||
F&& conversion)
|
||||
{
|
||||
if (json.isMember(JsonKey(key)))
|
||||
{
|
||||
if (auto jsonVal{ json[JsonKey(key)] })
|
||||
{
|
||||
if (validation == nullptr || validation(jsonVal))
|
||||
{
|
||||
target = conversion(jsonVal);
|
||||
}
|
||||
target = conversion(jsonVal);
|
||||
}
|
||||
else
|
||||
{
|
||||
// This branch is hit when the json object contained the key,
|
||||
// but the key was set to `null`. In this case, explicitly clear
|
||||
// the target.
|
||||
target = std::nullopt;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Helper that can be used for retrieving a value from a json
|
||||
// object, and parsing it's value to set on a given target object.
|
||||
// - If the key we're looking for _doesn't_ exist in the json object,
|
||||
// we'll leave the target object unmodified.
|
||||
// - If the key exists in the json object, we'll use the provided
|
||||
// `validation` function to ensure that the json value is of the
|
||||
// correct type.
|
||||
// - If we successfully validate the json value type (or no validation
|
||||
// function was provided), then we'll use `conversion` to parse the
|
||||
// value and place the result into `target`
|
||||
// - Each caller should provide a conversion function that takes a
|
||||
// Json::Value and returns an object of the same type as target.
|
||||
// - Unlike GetOptionalValue, if the key exists but is set to `null`, we'll
|
||||
// just ignore it.
|
||||
// Arguments:
|
||||
// - json: The json object to search for the given key
|
||||
// - key: The key to look for in the json object
|
||||
// - target: the optional object to receive the value from json
|
||||
// - conversion: a std::function<T(const Json::Value&)> which can be used to
|
||||
// convert the Json::Value to the appropriate type.
|
||||
// - validation: optional, if provided, will be called first to ensure that
|
||||
// the json::value is of the correct type before attempting to call
|
||||
// `conversion`.
|
||||
// Return Value:
|
||||
// - <none>
|
||||
template<typename T, typename F>
|
||||
void GetValue(const Json::Value& json,
|
||||
std::string_view key,
|
||||
T& target,
|
||||
F&& conversion,
|
||||
const std::function<bool(const Json::Value&)>& validation = nullptr)
|
||||
{
|
||||
if (json.isMember(JsonKey(key)))
|
||||
{
|
||||
if (auto jsonVal{ json[JsonKey(key)] })
|
||||
{
|
||||
if (validation == nullptr || validation(jsonVal))
|
||||
{
|
||||
target = conversion(jsonVal);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GetInt(const Json::Value& json,
|
||||
std::string_view key,
|
||||
int& target);
|
||||
|
||||
void GetUInt(const Json::Value& json,
|
||||
std::string_view key,
|
||||
uint32_t& target);
|
||||
|
||||
void GetDouble(const Json::Value& json,
|
||||
std::string_view key,
|
||||
double& target);
|
||||
|
||||
void GetBool(const Json::Value& json,
|
||||
std::string_view key,
|
||||
bool& target);
|
||||
|
||||
void GetWstring(const Json::Value& json,
|
||||
std::string_view key,
|
||||
std::wstring& target);
|
||||
};
|
||||
|
||||
@@ -70,7 +70,7 @@ void Pane::ResizeContent(const Size& newSize)
|
||||
const auto width = newSize.Width;
|
||||
const auto height = newSize.Height;
|
||||
|
||||
_CreateRowColDefinitions();
|
||||
_CreateRowColDefinitions(newSize);
|
||||
|
||||
if (_splitState == SplitState::Vertical)
|
||||
{
|
||||
@@ -790,24 +790,23 @@ void Pane::_SetupChildCloseHandlers()
|
||||
// which is stored in _desiredSplitPosition
|
||||
// - Does nothing if our split state is currently set to SplitState::None
|
||||
// Arguments:
|
||||
// - <none>
|
||||
// - rootSize: The dimensions in pixels that this pane (and its children should consume.)
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void Pane::_CreateRowColDefinitions()
|
||||
void Pane::_CreateRowColDefinitions(const Size& rootSize)
|
||||
{
|
||||
const auto first = _desiredSplitPosition * 100.0f;
|
||||
const auto second = 100.0f - first;
|
||||
if (_splitState == SplitState::Vertical)
|
||||
{
|
||||
_root.ColumnDefinitions().Clear();
|
||||
|
||||
// Create two columns in this grid: one for each pane
|
||||
const auto paneSizes = _CalcChildrenSizes(rootSize.Width);
|
||||
|
||||
auto firstColDef = Controls::ColumnDefinition();
|
||||
firstColDef.Width(GridLengthHelper::FromValueAndType(first, GridUnitType::Star));
|
||||
firstColDef.Width(GridLengthHelper::FromPixels(paneSizes.first));
|
||||
|
||||
auto secondColDef = Controls::ColumnDefinition();
|
||||
secondColDef.Width(GridLengthHelper::FromValueAndType(second, GridUnitType::Star));
|
||||
secondColDef.Width(GridLengthHelper::FromPixels(paneSizes.second));
|
||||
|
||||
_root.ColumnDefinitions().Append(firstColDef);
|
||||
_root.ColumnDefinitions().Append(secondColDef);
|
||||
@@ -817,18 +816,35 @@ void Pane::_CreateRowColDefinitions()
|
||||
_root.RowDefinitions().Clear();
|
||||
|
||||
// Create two rows in this grid: one for each pane
|
||||
const auto paneSizes = _CalcChildrenSizes(rootSize.Height);
|
||||
|
||||
auto firstRowDef = Controls::RowDefinition();
|
||||
firstRowDef.Height(GridLengthHelper::FromValueAndType(first, GridUnitType::Star));
|
||||
firstRowDef.Height(GridLengthHelper::FromPixels(paneSizes.first));
|
||||
|
||||
auto secondRowDef = Controls::RowDefinition();
|
||||
secondRowDef.Height(GridLengthHelper::FromValueAndType(second, GridUnitType::Star));
|
||||
secondRowDef.Height(GridLengthHelper::FromPixels(paneSizes.second));
|
||||
|
||||
_root.RowDefinitions().Append(firstRowDef);
|
||||
_root.RowDefinitions().Append(secondRowDef);
|
||||
}
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Initializes our UI for a new split in this pane. Sets up row/column
|
||||
// definitions, and initializes the separator grid. Does nothing if our split
|
||||
// state is currently set to SplitState::None
|
||||
// Arguments:
|
||||
// - <none>
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void Pane::_CreateSplitContent()
|
||||
{
|
||||
Size actualSize{ gsl::narrow_cast<float>(_root.ActualWidth()),
|
||||
gsl::narrow_cast<float>(_root.ActualHeight()) };
|
||||
|
||||
_CreateRowColDefinitions(actualSize);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Sets the thickness of each side of our borders to match our _borders state.
|
||||
// Arguments:
|
||||
@@ -1061,7 +1077,7 @@ std::pair<std::shared_ptr<Pane>, std::shared_ptr<Pane>> Pane::_Split(SplitState
|
||||
_control = { nullptr };
|
||||
_secondChild = std::make_shared<Pane>(profile, control);
|
||||
|
||||
_CreateRowColDefinitions();
|
||||
_CreateSplitContent();
|
||||
|
||||
_root.Children().Append(_firstChild->GetRootElement());
|
||||
_root.Children().Append(_secondChild->GetRootElement());
|
||||
@@ -1265,7 +1281,7 @@ Pane::SnapSizeResult Pane::_CalcSnappedDimension(const bool widthOrHeight, const
|
||||
// already snapped or minimum size.
|
||||
// Arguments:
|
||||
// - widthOrHeight: if true operates on width, otherwise on height.
|
||||
// - sizeNode: a layout size node that corresponds to this pane.
|
||||
// - sizeNode: a layouting node that corresponds to this pane.
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void Pane::_AdvanceSnappedDimension(const bool widthOrHeight, LayoutSizeNode& sizeNode) const
|
||||
@@ -1506,74 +1522,4 @@ void Pane::_SetupResources()
|
||||
}
|
||||
}
|
||||
|
||||
int Pane::GetLeafPaneCount() const noexcept
|
||||
{
|
||||
return _IsLeaf() ? 1 : (_firstChild->GetLeafPaneCount() + _secondChild->GetLeafPaneCount());
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - This is a helper to determine which direction an "Automatic" split should
|
||||
// happen in for a given pane, but without using the ActualWidth() and
|
||||
// ActualHeight() methods. This is used during the initialization of the
|
||||
// Terminal, when we could be processing many "split-pane" commands _before_
|
||||
// we've ever laid out the Terminal 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 how to do an "auto" split when these Panes are 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.
|
||||
// - 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 the
|
||||
// SplitState that `target` would use for an `Automatic` split given
|
||||
// `availableSpace`
|
||||
std::optional<winrt::TerminalApp::SplitState> Pane::PreCalculateAutoSplit(const std::shared_ptr<Pane> target,
|
||||
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.
|
||||
return availableSpace.Width > availableSpace.Height ? SplitState::Vertical : SplitState::Horizontal;
|
||||
}
|
||||
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) : availableSpace.Width;
|
||||
const float secondWidth = isVerticalSplit ? (availableSpace.Width - firstWidth) : availableSpace.Width;
|
||||
const float firstHeight = !isVerticalSplit ? (availableSpace.Height * _desiredSplitPosition) : availableSpace.Height;
|
||||
const float secondHeight = !isVerticalSplit ? (availableSpace.Height - firstHeight) : availableSpace.Height;
|
||||
|
||||
const auto firstResult = _firstChild->PreCalculateAutoSplit(target, { firstWidth, firstHeight });
|
||||
return firstResult.has_value() ? firstResult : _secondChild->PreCalculateAutoSplit(target, { secondWidth, secondHeight });
|
||||
}
|
||||
|
||||
// We should not possibly be getting here - both the above branches should
|
||||
// return a value.
|
||||
FAIL_FAST();
|
||||
}
|
||||
|
||||
DEFINE_EVENT(Pane, GotFocus, _GotFocusHandlers, winrt::delegate<std::shared_ptr<Pane>>);
|
||||
|
||||
@@ -63,13 +63,10 @@ public:
|
||||
const GUID& profile,
|
||||
const winrt::Microsoft::Terminal::TerminalControl::TermControl& control);
|
||||
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;
|
||||
|
||||
void Shutdown();
|
||||
void Close();
|
||||
|
||||
int GetLeafPaneCount() const noexcept;
|
||||
|
||||
WINRT_CALLBACK(Closed, winrt::Windows::Foundation::EventHandler<winrt::Windows::Foundation::IInspectable>);
|
||||
DECLARE_EVENT(GotFocus, _GotFocusHandlers, winrt::delegate<std::shared_ptr<Pane>>);
|
||||
|
||||
@@ -110,7 +107,8 @@ private:
|
||||
const GUID& profile,
|
||||
const winrt::Microsoft::Terminal::TerminalControl::TermControl& control);
|
||||
|
||||
void _CreateRowColDefinitions();
|
||||
void _CreateRowColDefinitions(const winrt::Windows::Foundation::Size& rootSize);
|
||||
void _CreateSplitContent();
|
||||
void _ApplySplitDefinitions();
|
||||
void _UpdateBorders();
|
||||
|
||||
@@ -135,9 +133,6 @@ private:
|
||||
float _ClampSplitPosition(const bool widthOrHeight, const float requestedValue, const float totalSize) const;
|
||||
|
||||
winrt::TerminalApp::SplitState _convertAutomaticSplitState(const winrt::TerminalApp::SplitState& splitType) const;
|
||||
|
||||
std::optional<winrt::TerminalApp::SplitState> _preCalculateAutoSplit(const std::shared_ptr<Pane> target, const winrt::Windows::Foundation::Size parentSize) const;
|
||||
|
||||
// Function Description:
|
||||
// - Returns true if the given direction can be used with the given split
|
||||
// type.
|
||||
@@ -187,7 +182,7 @@ private:
|
||||
};
|
||||
|
||||
// Helper structure that builds a (roughly) binary tree corresponding
|
||||
// to the pane tree. Used for laying out panes with snapped sizes.
|
||||
// to the pane tree. Used for layouting panes with snapped sizes.
|
||||
struct LayoutSizeNode
|
||||
{
|
||||
float size;
|
||||
|
||||
@@ -21,7 +21,6 @@ static constexpr std::wstring_view POWERSHELL_PREVIEW_PFN{ L"Microsoft.PowerShel
|
||||
static constexpr std::wstring_view PWSH_EXE{ L"pwsh.exe" };
|
||||
static constexpr std::wstring_view POWERSHELL_ICON{ L"ms-appx:///ProfileIcons/pwsh.png" };
|
||||
static constexpr std::wstring_view POWERSHELL_PREVIEW_ICON{ L"ms-appx:///ProfileIcons/pwsh-preview.png" };
|
||||
static constexpr std::wstring_view POWERSHELL_PREFERRED_PROFILE_NAME{ L"PowerShell" };
|
||||
|
||||
namespace
|
||||
{
|
||||
@@ -54,7 +53,7 @@ namespace
|
||||
Dotnet = 1 << 2, // installed as a dotnet global tool
|
||||
Traditional = 1 << 3, // installed in traditional Program Files locations
|
||||
|
||||
// native architecture (choose one)
|
||||
// native architecutre (choose one)
|
||||
WOWARM = 1 << 4, // non-native (Windows-on-Windows, ARM variety)
|
||||
WOWx86 = 1 << 5, // non-native (Windows-on-Windows, x86 variety)
|
||||
|
||||
@@ -197,7 +196,7 @@ catch (...)
|
||||
static void _accumulateStorePowerShellInstances(std::vector<PowerShellInstance>& out)
|
||||
{
|
||||
wil::unique_cotaskmem_string localAppDataFolder;
|
||||
if (FAILED(SHGetKnownFolderPath(FOLDERID_LocalAppData, 0, nullptr, &localAppDataFolder)))
|
||||
if (FAILED(SHGetKnownFolderPath(FOLDERID_LocalAppData, 0, 0, &localAppDataFolder)))
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -323,17 +322,8 @@ std::vector<TerminalApp::Profile> PowershellCoreProfileGenerator::GenerateProfil
|
||||
// (or the closest approximation thereof). It may choose a preview instance as the "best" if it is a higher version.
|
||||
auto firstProfile = profiles.begin();
|
||||
firstProfile->SetGuid(PowershellCoreGuid);
|
||||
firstProfile->SetName(POWERSHELL_PREFERRED_PROFILE_NAME);
|
||||
firstProfile->SetName(L"PowerShell");
|
||||
}
|
||||
|
||||
return profiles;
|
||||
}
|
||||
|
||||
// Function Description:
|
||||
// - Returns the thing it's named for.
|
||||
// Return value:
|
||||
// - the thing it says in the name
|
||||
const std::wstring_view PowershellCoreProfileGenerator::GetPreferredPowershellProfileName()
|
||||
{
|
||||
return POWERSHELL_PREFERRED_PROFILE_NAME;
|
||||
}
|
||||
|
||||
@@ -23,8 +23,6 @@ namespace TerminalApp
|
||||
class PowershellCoreProfileGenerator : public TerminalApp::IDynamicProfileGenerator
|
||||
{
|
||||
public:
|
||||
static const std::wstring_view GetPreferredPowershellProfileName();
|
||||
|
||||
PowershellCoreProfileGenerator() = default;
|
||||
~PowershellCoreProfileGenerator() = default;
|
||||
std::wstring_view GetNamespace() override;
|
||||
|
||||
@@ -19,11 +19,13 @@ static constexpr std::string_view NameKey{ "name" };
|
||||
static constexpr std::string_view GuidKey{ "guid" };
|
||||
static constexpr std::string_view SourceKey{ "source" };
|
||||
static constexpr std::string_view ColorSchemeKey{ "colorScheme" };
|
||||
static constexpr std::string_view ColorSchemeKeyOld{ "colorscheme" };
|
||||
static constexpr std::string_view HiddenKey{ "hidden" };
|
||||
|
||||
static constexpr std::string_view ForegroundKey{ "foreground" };
|
||||
static constexpr std::string_view BackgroundKey{ "background" };
|
||||
static constexpr std::string_view SelectionBackgroundKey{ "selectionBackground" };
|
||||
static constexpr std::string_view ColorTableKey{ "colorTable" };
|
||||
static constexpr std::string_view TabTitleKey{ "tabTitle" };
|
||||
static constexpr std::string_view SuppressApplicationTitleKey{ "suppressApplicationTitle" };
|
||||
static constexpr std::string_view HistorySizeKey{ "historySize" };
|
||||
@@ -102,11 +104,12 @@ Profile::Profile(const std::optional<GUID>& guid) :
|
||||
_defaultForeground{},
|
||||
_defaultBackground{},
|
||||
_selectionBackground{},
|
||||
_cursorColor{},
|
||||
_colorTable{},
|
||||
_tabTitle{},
|
||||
_suppressApplicationTitle{},
|
||||
_historySize{ DEFAULT_HISTORY_SIZE },
|
||||
_snapOnInput{ true },
|
||||
_cursorColor{ DEFAULT_CURSOR_COLOR },
|
||||
_cursorShape{ CursorStyle::Bar },
|
||||
_cursorHeight{ DEFAULT_CURSOR_HEIGHT },
|
||||
|
||||
@@ -168,8 +171,14 @@ TerminalSettings Profile::CreateTerminalSettings(const std::unordered_map<std::w
|
||||
TerminalSettings terminalSettings{};
|
||||
|
||||
// Fill in the Terminal Setting's CoreSettings from the profile
|
||||
auto const colorTableCount = gsl::narrow_cast<int>(_colorTable.size());
|
||||
for (int i = 0; i < colorTableCount; i++)
|
||||
{
|
||||
terminalSettings.SetColorTableEntry(i, _colorTable[i]);
|
||||
}
|
||||
terminalSettings.HistorySize(_historySize);
|
||||
terminalSettings.SnapOnInput(_snapOnInput);
|
||||
terminalSettings.CursorColor(_cursorColor);
|
||||
terminalSettings.CursorHeight(_cursorHeight);
|
||||
terminalSettings.CursorShape(_cursorShape);
|
||||
|
||||
@@ -219,10 +228,6 @@ TerminalSettings Profile::CreateTerminalSettings(const std::unordered_map<std::w
|
||||
{
|
||||
terminalSettings.SelectionBackground(_selectionBackground.value());
|
||||
}
|
||||
if (_cursorColor)
|
||||
{
|
||||
terminalSettings.CursorColor(_cursorColor.value());
|
||||
}
|
||||
|
||||
if (_scrollbarState)
|
||||
{
|
||||
@@ -291,17 +296,23 @@ Json::Value Profile::ToJson() const
|
||||
{
|
||||
root[JsonKey(SelectionBackgroundKey)] = Utils::ColorToHexString(_selectionBackground.value());
|
||||
}
|
||||
if (_cursorColor)
|
||||
{
|
||||
root[JsonKey(CursorColorKey)] = Utils::ColorToHexString(_cursorColor.value());
|
||||
}
|
||||
if (_schemeName)
|
||||
{
|
||||
const auto scheme = winrt::to_string(_schemeName.value());
|
||||
root[JsonKey(ColorSchemeKey)] = scheme;
|
||||
}
|
||||
else
|
||||
{
|
||||
Json::Value tableArray{};
|
||||
for (auto& color : _colorTable)
|
||||
{
|
||||
tableArray.append(Utils::ColorToHexString(color));
|
||||
}
|
||||
root[JsonKey(ColorTableKey)] = tableArray;
|
||||
}
|
||||
root[JsonKey(HistorySizeKey)] = _historySize;
|
||||
root[JsonKey(SnapOnInputKey)] = _snapOnInput;
|
||||
root[JsonKey(CursorColorKey)] = Utils::ColorToHexString(_cursorColor);
|
||||
// Only add the cursor height property if we're a legacy-style cursor.
|
||||
if (_cursorShape == CursorStyle::Vintage)
|
||||
{
|
||||
@@ -611,11 +622,19 @@ bool Profile::_ConvertJsonToBool(const Json::Value& json)
|
||||
void Profile::LayerJson(const Json::Value& json)
|
||||
{
|
||||
// Profile-specific Settings
|
||||
JsonUtils::GetWstring(json, NameKey, _name);
|
||||
if (json.isMember(JsonKey(NameKey)))
|
||||
{
|
||||
auto name{ json[JsonKey(NameKey)] };
|
||||
_name = GetWstringFromJson(name);
|
||||
}
|
||||
|
||||
JsonUtils::GetOptionalGuid(json, GuidKey, _guid);
|
||||
|
||||
JsonUtils::GetBool(json, HiddenKey, _hidden);
|
||||
if (json.isMember(JsonKey(HiddenKey)))
|
||||
{
|
||||
auto hidden{ json[JsonKey(HiddenKey)] };
|
||||
_hidden = hidden.asBool();
|
||||
}
|
||||
|
||||
// Core Settings
|
||||
JsonUtils::GetOptionalColor(json, ForegroundKey, _defaultForeground);
|
||||
@@ -624,17 +643,49 @@ void Profile::LayerJson(const Json::Value& json)
|
||||
|
||||
JsonUtils::GetOptionalColor(json, SelectionBackgroundKey, _selectionBackground);
|
||||
|
||||
JsonUtils::GetOptionalColor(json, CursorColorKey, _cursorColor);
|
||||
|
||||
JsonUtils::GetOptionalString(json, ColorSchemeKey, _schemeName);
|
||||
// TODO:GH#1069 deprecate old settings key
|
||||
JsonUtils::GetOptionalString(json, ColorSchemeKeyOld, _schemeName);
|
||||
|
||||
// TODO:MSFT:20642297 - Use a sentinel value (-1) for "Infinite scrollback"
|
||||
JsonUtils::GetInt(json, HistorySizeKey, _historySize);
|
||||
|
||||
JsonUtils::GetBool(json, SnapOnInputKey, _snapOnInput);
|
||||
|
||||
JsonUtils::GetUInt(json, CursorHeightKey, _cursorHeight);
|
||||
|
||||
// Only look for the "table" if there's no "schemeName"
|
||||
if (!(json.isMember(JsonKey(ColorSchemeKey))) &&
|
||||
!(json.isMember(JsonKey(ColorSchemeKeyOld))) &&
|
||||
json.isMember(JsonKey(ColorTableKey)))
|
||||
{
|
||||
auto colortable{ json[JsonKey(ColorTableKey)] };
|
||||
int i = 0;
|
||||
for (const auto& tableEntry : colortable)
|
||||
{
|
||||
if (tableEntry.isString())
|
||||
{
|
||||
const auto color = Utils::ColorFromHexString(tableEntry.asString());
|
||||
_colorTable[i] = color;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
if (json.isMember(JsonKey(HistorySizeKey)))
|
||||
{
|
||||
auto historySize{ json[JsonKey(HistorySizeKey)] };
|
||||
// TODO:MSFT:20642297 - Use a sentinel value (-1) for "Infinite scrollback"
|
||||
_historySize = historySize.asInt();
|
||||
}
|
||||
if (json.isMember(JsonKey(SnapOnInputKey)))
|
||||
{
|
||||
auto snapOnInput{ json[JsonKey(SnapOnInputKey)] };
|
||||
_snapOnInput = snapOnInput.asBool();
|
||||
}
|
||||
if (json.isMember(JsonKey(CursorColorKey)))
|
||||
{
|
||||
auto cursorColor{ json[JsonKey(CursorColorKey)] };
|
||||
const auto color = Utils::ColorFromHexString(cursorColor.asString());
|
||||
_cursorColor = color;
|
||||
}
|
||||
if (json.isMember(JsonKey(CursorHeightKey)))
|
||||
{
|
||||
auto cursorHeight{ json[JsonKey(CursorHeightKey)] };
|
||||
_cursorHeight = cursorHeight.asUInt();
|
||||
}
|
||||
if (json.isMember(JsonKey(CursorShapeKey)))
|
||||
{
|
||||
auto cursorShape{ json[JsonKey(CursorShapeKey)] };
|
||||
@@ -645,25 +696,46 @@ void Profile::LayerJson(const Json::Value& json)
|
||||
// Control Settings
|
||||
JsonUtils::GetOptionalGuid(json, ConnectionTypeKey, _connectionType);
|
||||
|
||||
JsonUtils::GetWstring(json, CommandlineKey, _commandline);
|
||||
|
||||
JsonUtils::GetWstring(json, FontFaceKey, _fontFace);
|
||||
|
||||
JsonUtils::GetInt(json, FontSizeKey, _fontSize);
|
||||
|
||||
JsonUtils::GetDouble(json, AcrylicTransparencyKey, _acrylicTransparency);
|
||||
|
||||
JsonUtils::GetBool(json, UseAcrylicKey, _useAcrylic);
|
||||
|
||||
JsonUtils::GetBool(json, SuppressApplicationTitleKey, _suppressApplicationTitle);
|
||||
|
||||
if (json.isMember(JsonKey(CommandlineKey)))
|
||||
{
|
||||
auto commandline{ json[JsonKey(CommandlineKey)] };
|
||||
_commandline = GetWstringFromJson(commandline);
|
||||
}
|
||||
if (json.isMember(JsonKey(FontFaceKey)))
|
||||
{
|
||||
auto fontFace{ json[JsonKey(FontFaceKey)] };
|
||||
_fontFace = GetWstringFromJson(fontFace);
|
||||
}
|
||||
if (json.isMember(JsonKey(FontSizeKey)))
|
||||
{
|
||||
auto fontSize{ json[JsonKey(FontSizeKey)] };
|
||||
_fontSize = fontSize.asInt();
|
||||
}
|
||||
if (json.isMember(JsonKey(AcrylicTransparencyKey)))
|
||||
{
|
||||
auto acrylicTransparency{ json[JsonKey(AcrylicTransparencyKey)] };
|
||||
_acrylicTransparency = acrylicTransparency.asFloat();
|
||||
}
|
||||
if (json.isMember(JsonKey(UseAcrylicKey)))
|
||||
{
|
||||
auto useAcrylic{ json[JsonKey(UseAcrylicKey)] };
|
||||
_useAcrylic = useAcrylic.asBool();
|
||||
}
|
||||
if (json.isMember(JsonKey(SuppressApplicationTitleKey)))
|
||||
{
|
||||
auto suppressApplicationTitle{ json[JsonKey(SuppressApplicationTitleKey)] };
|
||||
_suppressApplicationTitle = suppressApplicationTitle.asBool();
|
||||
}
|
||||
if (json.isMember(JsonKey(CloseOnExitKey)))
|
||||
{
|
||||
auto closeOnExit{ json[JsonKey(CloseOnExitKey)] };
|
||||
_closeOnExitMode = ParseCloseOnExitMode(closeOnExit);
|
||||
}
|
||||
|
||||
JsonUtils::GetWstring(json, PaddingKey, _padding);
|
||||
if (json.isMember(JsonKey(PaddingKey)))
|
||||
{
|
||||
auto padding{ json[JsonKey(PaddingKey)] };
|
||||
_padding = GetWstringFromJson(padding);
|
||||
}
|
||||
|
||||
JsonUtils::GetOptionalString(json, ScrollbarStateKey, _scrollbarState);
|
||||
|
||||
@@ -718,9 +790,9 @@ void Profile::SetStartingDirectory(std::wstring startingDirectory) noexcept
|
||||
_startingDirectory = std::move(startingDirectory);
|
||||
}
|
||||
|
||||
void Profile::SetName(const std::wstring_view name) noexcept
|
||||
void Profile::SetName(std::wstring name) noexcept
|
||||
{
|
||||
_name = static_cast<std::wstring>(name);
|
||||
_name = std::move(name);
|
||||
}
|
||||
|
||||
void Profile::SetUseAcrylic(bool useAcrylic) noexcept
|
||||
|
||||
@@ -79,7 +79,7 @@ public:
|
||||
void SetAcrylicOpacity(double opacity) noexcept;
|
||||
void SetCommandline(std::wstring cmdline) noexcept;
|
||||
void SetStartingDirectory(std::wstring startingDirectory) noexcept;
|
||||
void SetName(const std::wstring_view name) noexcept;
|
||||
void SetName(std::wstring name) noexcept;
|
||||
void SetUseAcrylic(bool useAcrylic) noexcept;
|
||||
void SetDefaultForeground(COLORREF defaultForeground) noexcept;
|
||||
void SetDefaultBackground(COLORREF defaultBackground) noexcept;
|
||||
@@ -142,11 +142,12 @@ private:
|
||||
std::optional<uint32_t> _defaultForeground;
|
||||
std::optional<uint32_t> _defaultBackground;
|
||||
std::optional<uint32_t> _selectionBackground;
|
||||
std::optional<uint32_t> _cursorColor;
|
||||
std::array<uint32_t, COLOR_TABLE_SIZE> _colorTable;
|
||||
std::optional<std::wstring> _tabTitle;
|
||||
bool _suppressApplicationTitle;
|
||||
int32_t _historySize;
|
||||
bool _snapOnInput;
|
||||
uint32_t _cursorColor;
|
||||
uint32_t _cursorHeight;
|
||||
winrt::Microsoft::Terminal::Settings::CursorStyle _cursorShape;
|
||||
|
||||
|
||||
@@ -162,8 +162,42 @@ Temporarily using the Windows Terminal default settings.
|
||||
<data name="ReloadJsonParseErrorTitle" xml:space="preserve">
|
||||
<value>Failed to reload settings</value>
|
||||
</data>
|
||||
<data name="AboutTitleText" xml:space="preserve">
|
||||
<value>About</value>
|
||||
</data>
|
||||
<data name="VersionLabelText" xml:space="preserve">
|
||||
<value>Version:</value>
|
||||
</data>
|
||||
<data name="DocumentationLabelText" xml:space="preserve">
|
||||
<value>Documentation
|
||||
</value>
|
||||
</data>
|
||||
<data name="GettingStartedLabelText" xml:space="preserve">
|
||||
<value>Getting Started
|
||||
</value>
|
||||
</data>
|
||||
<data name="ReleaseNotesLabelText" xml:space="preserve">
|
||||
<value>Release Notes
|
||||
</value>
|
||||
</data>
|
||||
<data name="PrivacyPolicyLabelText" xml:space="preserve">
|
||||
<value>Privacy Policy
|
||||
</value>
|
||||
</data>
|
||||
<data name="DocumentationUriValue" xml:space="preserve">
|
||||
<value>https://aka.ms/terminal-documentation</value>
|
||||
</data>
|
||||
<data name="GettingStartedUriValue" xml:space="preserve">
|
||||
<value>https://aka.ms/terminal-getting-started</value>
|
||||
</data>
|
||||
<data name="ReleaseNotesUriValue" xml:space="preserve">
|
||||
<value>https://aka.ms/terminal-release-notes</value>
|
||||
</data>
|
||||
<data name="PrivacyPolicyUriValue" xml:space="preserve">
|
||||
<value>https://aka.ms/terminal-privacy-policy</value>
|
||||
</data>
|
||||
<data name="FeedbackUriValue" xml:space="preserve">
|
||||
<value>https://go.microsoft.com/fwlink/?linkid=2125419</value>
|
||||
<value>https://aka.ms/terminal-feedback</value>
|
||||
</data>
|
||||
<data name="AboutMenuItem" xml:space="preserve">
|
||||
<value>About</value>
|
||||
@@ -174,6 +208,15 @@ Temporarily using the Windows Terminal default settings.
|
||||
<data name="SettingsMenuItem" xml:space="preserve">
|
||||
<value>Settings</value>
|
||||
</data>
|
||||
<data name="Cancel" xml:space="preserve">
|
||||
<value>Cancel</value>
|
||||
</data>
|
||||
<data name="CloseAll" xml:space="preserve">
|
||||
<value>Close all</value>
|
||||
</data>
|
||||
<data name="CloseWindowWarningTitle" xml:space="preserve">
|
||||
<value>Do you want to close all tabs?</value>
|
||||
</data>
|
||||
<data name="InvalidBackgroundImage" xml:space="preserve">
|
||||
<value>Found a profile with an invalid "backgroundImage". Defaulting that profile to have no background image. Make sure that when setting a "backgroundImage", the value is a valid file path to an image.</value>
|
||||
</data>
|
||||
@@ -240,51 +283,4 @@ Temporarily using the Windows Terminal default settings.
|
||||
<data name="WindowMinimizeButton.[using:Windows.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
|
||||
<value>Minimize</value>
|
||||
</data>
|
||||
<data name="AboutDialog.Title" xml:space="preserve">
|
||||
<value>About</value>
|
||||
</data>
|
||||
<data name="AboutDialog.CloseButtonText" xml:space="preserve">
|
||||
<value>OK</value>
|
||||
</data>
|
||||
<data name="AboutDialog_VersionLabel.Text" xml:space="preserve">
|
||||
<value>Version:</value>
|
||||
<comment>This is the heading for a version number label</comment>
|
||||
</data>
|
||||
<data name="AboutDialog_GettingStartedLink.Content" xml:space="preserve">
|
||||
<value>Getting Started</value>
|
||||
<comment>A hyperlink name for a guide on how to get started using Terminal</comment>
|
||||
</data>
|
||||
<data name="AboutDialog_DocumentationLink.Content" xml:space="preserve">
|
||||
<value>Documentation</value>
|
||||
<comment>A hyperlink name for user documentation</comment>
|
||||
</data>
|
||||
<data name="AboutDialog_ReleaseNotesLink.Content" xml:space="preserve">
|
||||
<value>Release Notes</value>
|
||||
<comment>A hyperlink name for the Terminal's release notes</comment>
|
||||
</data>
|
||||
<data name="AboutDialog_PrivacyPolicyLink.Content" xml:space="preserve">
|
||||
<value>Privacy Policy</value>
|
||||
<comment>A hyperlink name for the Terminal's privacy policy</comment>
|
||||
</data>
|
||||
<data name="ApplicationDisplayNameUnpackaged" xml:space="preserve">
|
||||
<value>Windows Terminal (Unpackaged)</value>
|
||||
<comment>This display name is used when the application's name cannot be determined</comment>
|
||||
</data>
|
||||
<data name="ApplicationVersionUnknown" xml:space="preserve">
|
||||
<value>Unknown</value>
|
||||
<comment>This is displayed when the version of the application cannot be determined</comment>
|
||||
</data>
|
||||
<data name="CloseAllDialog.CloseButtonText" xml:space="preserve">
|
||||
<value>Cancel</value>
|
||||
</data>
|
||||
<data name="CloseAllDialog.PrimaryButtonText" xml:space="preserve">
|
||||
<value>Close all</value>
|
||||
</data>
|
||||
<data name="CloseAllDialog.Title" xml:space="preserve">
|
||||
<value>Do you want to close all tabs?</value>
|
||||
</data>
|
||||
<data name="CommandPromptDisplayName" xml:space="preserve">
|
||||
<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>
|
||||
</data>
|
||||
</root>
|
||||
@@ -33,6 +33,11 @@ namespace winrt::TerminalApp::implementation
|
||||
_CopyTextHandlers(*this, *eventArgs);
|
||||
break;
|
||||
}
|
||||
case ShortcutAction::CopyTextWithoutNewlines:
|
||||
{
|
||||
_CopyTextHandlers(*this, *eventArgs);
|
||||
break;
|
||||
}
|
||||
case ShortcutAction::PasteText:
|
||||
{
|
||||
_PasteTextHandlers(*this, *eventArgs);
|
||||
@@ -55,6 +60,15 @@ namespace winrt::TerminalApp::implementation
|
||||
}
|
||||
|
||||
case ShortcutAction::NewTab:
|
||||
case ShortcutAction::NewTabProfile0:
|
||||
case ShortcutAction::NewTabProfile1:
|
||||
case ShortcutAction::NewTabProfile2:
|
||||
case ShortcutAction::NewTabProfile3:
|
||||
case ShortcutAction::NewTabProfile4:
|
||||
case ShortcutAction::NewTabProfile5:
|
||||
case ShortcutAction::NewTabProfile6:
|
||||
case ShortcutAction::NewTabProfile7:
|
||||
case ShortcutAction::NewTabProfile8:
|
||||
{
|
||||
_NewTabHandlers(*this, *eventArgs);
|
||||
break;
|
||||
@@ -122,24 +136,46 @@ namespace winrt::TerminalApp::implementation
|
||||
}
|
||||
|
||||
case ShortcutAction::SwitchToTab:
|
||||
case ShortcutAction::SwitchToTab0:
|
||||
case ShortcutAction::SwitchToTab1:
|
||||
case ShortcutAction::SwitchToTab2:
|
||||
case ShortcutAction::SwitchToTab3:
|
||||
case ShortcutAction::SwitchToTab4:
|
||||
case ShortcutAction::SwitchToTab5:
|
||||
case ShortcutAction::SwitchToTab6:
|
||||
case ShortcutAction::SwitchToTab7:
|
||||
case ShortcutAction::SwitchToTab8:
|
||||
{
|
||||
_SwitchToTabHandlers(*this, *eventArgs);
|
||||
break;
|
||||
}
|
||||
|
||||
case ShortcutAction::ResizePane:
|
||||
case ShortcutAction::ResizePaneLeft:
|
||||
case ShortcutAction::ResizePaneRight:
|
||||
case ShortcutAction::ResizePaneUp:
|
||||
case ShortcutAction::ResizePaneDown:
|
||||
{
|
||||
_ResizePaneHandlers(*this, *eventArgs);
|
||||
break;
|
||||
}
|
||||
|
||||
case ShortcutAction::MoveFocus:
|
||||
case ShortcutAction::MoveFocusLeft:
|
||||
case ShortcutAction::MoveFocusRight:
|
||||
case ShortcutAction::MoveFocusUp:
|
||||
case ShortcutAction::MoveFocusDown:
|
||||
{
|
||||
_MoveFocusHandlers(*this, *eventArgs);
|
||||
break;
|
||||
}
|
||||
|
||||
case ShortcutAction::AdjustFontSize:
|
||||
case ShortcutAction::IncreaseFontSize:
|
||||
{
|
||||
_AdjustFontSizeHandlers(*this, *eventArgs);
|
||||
break;
|
||||
}
|
||||
case ShortcutAction::DecreaseFontSize:
|
||||
{
|
||||
_AdjustFontSizeHandlers(*this, *eventArgs);
|
||||
break;
|
||||
|
||||
@@ -11,10 +11,20 @@ namespace TerminalApp
|
||||
{
|
||||
Invalid = 0,
|
||||
CopyText,
|
||||
CopyTextWithoutNewlines,
|
||||
PasteText,
|
||||
OpenNewTabDropdown,
|
||||
DuplicateTab,
|
||||
NewTab,
|
||||
NewTabProfile0, // Legacy
|
||||
NewTabProfile1, // Legacy
|
||||
NewTabProfile2, // Legacy
|
||||
NewTabProfile3, // Legacy
|
||||
NewTabProfile4, // Legacy
|
||||
NewTabProfile5, // Legacy
|
||||
NewTabProfile6, // Legacy
|
||||
NewTabProfile7, // Legacy
|
||||
NewTabProfile8, // Legacy
|
||||
NewWindow,
|
||||
CloseWindow,
|
||||
CloseTab,
|
||||
@@ -25,14 +35,32 @@ namespace TerminalApp
|
||||
SplitHorizontal,
|
||||
SplitPane,
|
||||
SwitchToTab,
|
||||
AdjustFontSize,
|
||||
SwitchToTab0, // Legacy
|
||||
SwitchToTab1, // Legacy
|
||||
SwitchToTab2, // Legacy
|
||||
SwitchToTab3, // Legacy
|
||||
SwitchToTab4, // Legacy
|
||||
SwitchToTab5, // Legacy
|
||||
SwitchToTab6, // Legacy
|
||||
SwitchToTab7, // Legacy
|
||||
SwitchToTab8, // Legacy
|
||||
IncreaseFontSize,
|
||||
DecreaseFontSize,
|
||||
ResetFontSize,
|
||||
ScrollUp,
|
||||
ScrollDown,
|
||||
ScrollUpPage,
|
||||
ScrollDownPage,
|
||||
ResizePane,
|
||||
ResizePaneLeft, // Legacy
|
||||
ResizePaneRight, // Legacy
|
||||
ResizePaneUp, // Legacy
|
||||
ResizePaneDown, // Legacy
|
||||
MoveFocus,
|
||||
MoveFocusLeft, // Legacy
|
||||
MoveFocusRight, // Legacy
|
||||
MoveFocusUp, // Legacy
|
||||
MoveFocusDown, // Legacy
|
||||
Find,
|
||||
ToggleFullscreen,
|
||||
OpenSettings
|
||||
|
||||
@@ -277,12 +277,6 @@ namespace winrt::TerminalApp::implementation
|
||||
// gains focus, we'll mark it as the new active pane.
|
||||
_AttachEventHandlersToPane(first);
|
||||
_AttachEventHandlersToPane(second);
|
||||
|
||||
// Immediately update our tracker of the focused pane now. If we're
|
||||
// splitting panes during startup (from a commandline), then it's
|
||||
// possible that the focus events won't propagate immediately. Updating
|
||||
// the focus here will give the same effect though.
|
||||
_UpdateActivePane(second);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
@@ -393,28 +387,6 @@ namespace winrt::TerminalApp::implementation
|
||||
});
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Mark the given pane as the active pane in this tab. All other panes
|
||||
// will be marked as inactive. We'll also update our own UI state to
|
||||
// reflect this newly active pane.
|
||||
// Arguments:
|
||||
// - pane: a Pane to mark as active.
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void Tab::_UpdateActivePane(std::shared_ptr<Pane> pane)
|
||||
{
|
||||
// Clear the active state of the entire tree, and mark only the pane as active.
|
||||
_rootPane->ClearActive();
|
||||
_activePane = pane;
|
||||
_activePane->SetActive();
|
||||
|
||||
// Update our own title text to match the newly-active pane.
|
||||
SetTabText(GetActiveTitle());
|
||||
|
||||
// Raise our own ActivePaneChanged event.
|
||||
_ActivePaneChangedHandlers();
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Add an event handler to this pane's GotFocus event. When that pane gains
|
||||
// focus, we'll mark it as the new active pane. We'll also query the title of
|
||||
@@ -434,37 +406,19 @@ namespace winrt::TerminalApp::implementation
|
||||
|
||||
if (tab && sender != tab->_activePane)
|
||||
{
|
||||
tab->_UpdateActivePane(sender);
|
||||
// Clear the active state of the entire tree, and mark only the sender as active.
|
||||
tab->_rootPane->ClearActive();
|
||||
tab->_activePane = sender;
|
||||
tab->_activePane->SetActive();
|
||||
|
||||
// Update our own title text to match the newly-active pane.
|
||||
tab->SetTabText(tab->GetActiveTitle());
|
||||
|
||||
// Raise our own ActivePaneChanged event.
|
||||
tab->_ActivePaneChangedHandlers();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Get the total number of leaf panes in this tab. This will be the number
|
||||
// of actual controls hosted by this tab.
|
||||
// Arguments:
|
||||
// - <none>
|
||||
// Return Value:
|
||||
// - The total number of leaf panes hosted by this tab.
|
||||
int Tab::_GetLeafPaneCount() const noexcept
|
||||
{
|
||||
return _rootPane->GetLeafPaneCount();
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - This is a helper to determine which direction an "Automatic" split should
|
||||
// happen in for the active pane of this tab, but without using the ActualWidth() and
|
||||
// ActualHeight() methods.
|
||||
// - See Pane::PreCalculateAutoSplit
|
||||
// Arguments:
|
||||
// - availableSpace: The theoretical space that's available for this Tab's content
|
||||
// Return Value:
|
||||
// - The SplitState that we should use for an `Automatic` split given
|
||||
// `availableSpace`
|
||||
SplitState Tab::PreCalculateAutoSplit(winrt::Windows::Foundation::Size availableSpace) const
|
||||
{
|
||||
return _rootPane->PreCalculateAutoSplit(_activePane, availableSpace).value_or(SplitState::Vertical);
|
||||
}
|
||||
|
||||
DEFINE_EVENT(Tab, ActivePaneChanged, _ActivePaneChangedHandlers, winrt::delegate<>);
|
||||
}
|
||||
|
||||
@@ -5,12 +5,6 @@
|
||||
#include "Pane.h"
|
||||
#include "Tab.g.h"
|
||||
|
||||
// fwdecl unittest classes
|
||||
namespace TerminalAppLocalTests
|
||||
{
|
||||
class TabTests;
|
||||
};
|
||||
|
||||
namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
struct Tab : public TabT<Tab>
|
||||
@@ -38,7 +32,6 @@ namespace winrt::TerminalApp::implementation
|
||||
winrt::fire_and_forget UpdateIcon(const winrt::hstring iconPath);
|
||||
|
||||
float CalcSnappedDimension(const bool widthOrHeight, const float dimension) const;
|
||||
SplitState PreCalculateAutoSplit(winrt::Windows::Foundation::Size rootSize) const;
|
||||
|
||||
void ResizeContent(const winrt::Windows::Foundation::Size& newSize);
|
||||
void ResizePane(const winrt::TerminalApp::Direction& direction);
|
||||
@@ -71,10 +64,5 @@ namespace winrt::TerminalApp::implementation
|
||||
|
||||
void _AttachEventHandlersToControl(const winrt::Microsoft::Terminal::TerminalControl::TermControl& control);
|
||||
void _AttachEventHandlersToPane(std::shared_ptr<Pane> pane);
|
||||
|
||||
int _GetLeafPaneCount() const noexcept;
|
||||
void _UpdateActivePane(std::shared_ptr<Pane> pane);
|
||||
|
||||
friend class ::TerminalAppLocalTests::TabTests;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
</PropertyGroup>
|
||||
<Import Project="..\..\..\common.openconsole.props" Condition="'$(OpenConsoleDir)'==''" />
|
||||
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.pre.props" />
|
||||
<Import Project="..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.0.0\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props" Condition="Exists('..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.0.0\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props')" />
|
||||
<!-- ========================= XAML files ======================== -->
|
||||
<ItemGroup>
|
||||
<!-- DON'T PUT XAML FILES HERE! Put them in TerminalAppLib.vcxproj -->
|
||||
@@ -78,17 +77,11 @@
|
||||
<CopyLocalSatelliteAssemblies>true</CopyLocalSatelliteAssemblies>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
|
||||
<Import Project="..\..\..\packages\Microsoft.UI.Xaml.2.3.191217003-prerelease\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('..\..\..\packages\Microsoft.UI.Xaml.2.3.191217003-prerelease\build\native\Microsoft.UI.Xaml.targets')" />
|
||||
<Import Project="..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.0.0\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets" Condition="Exists('..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.0.0\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" />
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('$(OpenConsoleDir)\packages\Microsoft.UI.Xaml.2.3.191217003-prerelease\build\native\Microsoft.UI.Xaml.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(OpenConsoleDir)\packages\Microsoft.UI.Xaml.2.3.191217003-prerelease\build\native\Microsoft.UI.Xaml.targets'))" />
|
||||
<Error Condition="!Exists('$(OpenConsoleDir)\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.0.0\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(OpenConsoleDir)\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.0.0\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets'))" />
|
||||
</Target>
|
||||
|
||||
<PropertyGroup>
|
||||
<!-- A small helper for paths to the compiled cppwinrt projects -->
|
||||
<_BinRoot Condition="'$(Platform)' != 'Win32'">$(OpenConsoleDir)$(Platform)\$(Configuration)\</_BinRoot>
|
||||
<_BinRoot Condition="'$(Platform)' == 'Win32'">$(OpenConsoleDir)$(Configuration)\</_BinRoot>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>$(OpenConsoleDir)\dep\jsoncpp\json;%(AdditionalIncludeDirectories);</AdditionalIncludeDirectories>
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
#include "TerminalPage.h"
|
||||
#include "ActionAndArgs.h"
|
||||
#include "Utils.h"
|
||||
#include "AppLogic.h"
|
||||
#include "../../types/inc/utils.hpp"
|
||||
|
||||
#include <LibraryResources.h>
|
||||
@@ -16,7 +15,6 @@
|
||||
#include "AzureCloudShellGenerator.h" // For AzureConnectionType
|
||||
#include "TelnetGenerator.h" // For TelnetConnectionType
|
||||
#include "TabRowControl.h"
|
||||
#include "DebugTapConnection.h"
|
||||
|
||||
using namespace winrt;
|
||||
using namespace winrt::Windows::UI::Xaml;
|
||||
@@ -65,20 +63,11 @@ namespace winrt::TerminalApp::implementation
|
||||
_tabView = _tabRow.TabView();
|
||||
_rearranging = false;
|
||||
|
||||
// GH#2455 - Make sure to try/catch calls to Application::Current,
|
||||
// because that _won't_ be an instance of TerminalApp::App in the
|
||||
// LocalTests
|
||||
auto isElevated = false;
|
||||
try
|
||||
{
|
||||
// GH#3581 - There's a platform limitation that causes us to crash when we rearrange tabs.
|
||||
// Xaml tries to send a drag visual (to wit: a screenshot) to the drag hosting process,
|
||||
// but that process is running at a different IL than us.
|
||||
// For now, we're disabling elevated drag.
|
||||
isElevated = ::winrt::Windows::UI::Xaml::Application::Current().as<::winrt::TerminalApp::App>().Logic().IsUwp();
|
||||
}
|
||||
CATCH_LOG();
|
||||
|
||||
// GH#3581 - There's a platform limitation that causes us to crash when we rearrange tabs.
|
||||
// Xaml tries to send a drag visual (to wit: a screenshot) to the drag hosting process,
|
||||
// but that process is running at a different IL than us.
|
||||
// For now, we're disabling elevated drag.
|
||||
const auto isElevated = ::winrt::Windows::UI::Xaml::Application::Current().as<::winrt::TerminalApp::App>().Logic().IsElevated();
|
||||
_tabView.CanReorderTabs(!isElevated);
|
||||
_tabView.CanDragTabs(!isElevated);
|
||||
|
||||
@@ -148,109 +137,161 @@ namespace winrt::TerminalApp::implementation
|
||||
|
||||
_tabContent.SizeChanged({ this, &TerminalPage::_OnContentSizeChanged });
|
||||
|
||||
// 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
|
||||
// window will be, so they can subdivide that space.
|
||||
//
|
||||
// _OnFirstLayout will remove this handler so it doesn't get called more than once.
|
||||
_layoutUpdatedRevoker = _tabContent.LayoutUpdated(winrt::auto_revoke, { this, &TerminalPage::_OnFirstLayout });
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - This method is called once on startup, on the first LayoutUpdated event.
|
||||
// We'll use this event to know that we have an ActualWidth and
|
||||
// ActualHeight, so we can now attempt to process our list of startup
|
||||
// actions.
|
||||
// - We'll remove this event handler when the event is first handled.
|
||||
// - If there are no startup actions, we'll open a single tab with the
|
||||
// default profile.
|
||||
// Arguments:
|
||||
// - <unused>
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void TerminalPage::_OnFirstLayout(const IInspectable& /*sender*/, const IInspectable& /*eventArgs*/)
|
||||
{
|
||||
// Only let this succeed once.
|
||||
_layoutUpdatedRevoker.revoke();
|
||||
|
||||
// This event fires every time the layout changes, but it is always the
|
||||
// last one to fire in any layout change chain. That gives us great
|
||||
// flexibility in finding the right point at which to initialize our
|
||||
// renderer (and our terminal). Any earlier than the last layout update
|
||||
// and we may not know the terminal's starting size.
|
||||
if (_startupState == StartupState::NotInitialized)
|
||||
// Actually start the terminal.
|
||||
if (_appArgs.GetStartupActions().empty())
|
||||
{
|
||||
_OpenNewTab(nullptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
_startupState = StartupState::InStartup;
|
||||
_appArgs.ValidateStartupCommands();
|
||||
if (_appArgs.GetStartupActions().empty())
|
||||
{
|
||||
_OpenNewTab(nullptr);
|
||||
_startupState = StartupState::Initialized;
|
||||
_InitializedHandlers(*this, nullptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
_ProcessStartupActions();
|
||||
}
|
||||
|
||||
// This will kick off a chain of events to perform each startup
|
||||
// action. As each startup action is completed, the next will be
|
||||
// fired.
|
||||
_ProcessNextStartupAction();
|
||||
}
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Process all the startup actions in our list of startup actions. We'll
|
||||
// do this all at once here.
|
||||
// - Process the next startup action in our list of startup actions. When
|
||||
// that action is complete, fire the next (if there are any more).
|
||||
// Arguments:
|
||||
// - <none>
|
||||
// Return Value:
|
||||
// - <none>
|
||||
winrt::fire_and_forget TerminalPage::_ProcessStartupActions()
|
||||
fire_and_forget TerminalPage::_ProcessNextStartupAction()
|
||||
{
|
||||
// If there are no actions left, do nothing.
|
||||
if (_appArgs.GetStartupActions().empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the next action to be processed
|
||||
auto nextAction = _appArgs.GetStartupActions().front();
|
||||
_appArgs.GetStartupActions().pop_front();
|
||||
|
||||
auto weakThis{ get_weak() };
|
||||
|
||||
// Handle it on a subsequent pass of the UI thread.
|
||||
co_await winrt::resume_foreground(Dispatcher(), CoreDispatcherPriority::Normal);
|
||||
// Handle it on the UI thread.
|
||||
co_await winrt::resume_foreground(Dispatcher(), CoreDispatcherPriority::Low);
|
||||
if (auto page{ weakThis.get() })
|
||||
{
|
||||
for (const auto& action : _appArgs.GetStartupActions())
|
||||
{
|
||||
_actionDispatch->DoAction(action);
|
||||
}
|
||||
_startupState = StartupState::Initialized;
|
||||
_InitializedHandlers(*this, nullptr);
|
||||
page->_actionDispatch->DoAction(nextAction);
|
||||
|
||||
// Kick off the next action to be handled (if necessary)
|
||||
page->_ProcessNextStartupAction();
|
||||
}
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Show a ContentDialog with a single "Ok" button to dismiss. Looks up the
|
||||
// the title and text from our Resources using the provided keys.
|
||||
// - Only one dialog can be visible at a time. If another dialog is visible
|
||||
// when this is called, nothing happens. See _ShowDialog for details
|
||||
// Arguments:
|
||||
// - titleKey: The key to use to lookup the title text from our resources.
|
||||
// - contentKey: The key to use to lookup the content text from our resources.
|
||||
void TerminalPage::ShowOkDialog(const winrt::hstring& titleKey,
|
||||
const winrt::hstring& contentKey)
|
||||
{
|
||||
auto title = GetLibraryResourceString(titleKey);
|
||||
auto message = GetLibraryResourceString(contentKey);
|
||||
auto buttonText = RS_(L"Ok");
|
||||
|
||||
WUX::Controls::ContentDialog dialog;
|
||||
dialog.Title(winrt::box_value(title));
|
||||
dialog.Content(winrt::box_value(message));
|
||||
dialog.CloseButtonText(buttonText);
|
||||
dialog.DefaultButton(WUX::Controls::ContentDialogButton::Close);
|
||||
|
||||
_showDialogHandlers(*this, dialog);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Show a dialog with "About" information. Displays the app's Display
|
||||
// Name, version, getting started link, documentation link, release
|
||||
// Notes link, and privacy policy link.
|
||||
void TerminalPage::_ShowAboutDialog()
|
||||
{
|
||||
_showDialogHandlers(*this, FindName(L"AboutDialog").try_as<WUX::Controls::ContentDialog>());
|
||||
}
|
||||
const auto title = RS_(L"AboutTitleText");
|
||||
const auto versionLabel = RS_(L"VersionLabelText");
|
||||
const auto gettingStartedLabel = RS_(L"GettingStartedLabelText");
|
||||
const auto documentationLabel = RS_(L"DocumentationLabelText");
|
||||
const auto releaseNotesLabel = RS_(L"ReleaseNotesLabelText");
|
||||
const auto privacyPolicyLabel = RS_(L"PrivacyPolicyLabelText");
|
||||
const auto gettingStartedUriValue = RS_(L"GettingStartedUriValue");
|
||||
const auto documentationUriValue = RS_(L"DocumentationUriValue");
|
||||
const auto releaseNotesUriValue = RS_(L"ReleaseNotesUriValue");
|
||||
const auto privacyPolicyUriValue = RS_(L"PrivacyPolicyUriValue");
|
||||
const auto package = winrt::Windows::ApplicationModel::Package::Current();
|
||||
const auto packageName = package.DisplayName();
|
||||
const auto version = package.Id().Version();
|
||||
winrt::Windows::UI::Xaml::Documents::Run about;
|
||||
winrt::Windows::UI::Xaml::Documents::Run gettingStarted;
|
||||
winrt::Windows::UI::Xaml::Documents::Run documentation;
|
||||
winrt::Windows::UI::Xaml::Documents::Run releaseNotes;
|
||||
winrt::Windows::UI::Xaml::Documents::Run privacyPolicy;
|
||||
winrt::Windows::UI::Xaml::Documents::Hyperlink gettingStartedLink;
|
||||
winrt::Windows::UI::Xaml::Documents::Hyperlink documentationLink;
|
||||
winrt::Windows::UI::Xaml::Documents::Hyperlink releaseNotesLink;
|
||||
winrt::Windows::UI::Xaml::Documents::Hyperlink privacyPolicyLink;
|
||||
std::wstringstream aboutTextStream;
|
||||
|
||||
winrt::hstring TerminalPage::ApplicationDisplayName()
|
||||
{
|
||||
if (const auto appLogic{ implementation::AppLogic::Current() })
|
||||
{
|
||||
return appLogic->ApplicationDisplayName();
|
||||
}
|
||||
gettingStarted.Text(gettingStartedLabel);
|
||||
documentation.Text(documentationLabel);
|
||||
releaseNotes.Text(releaseNotesLabel);
|
||||
privacyPolicy.Text(privacyPolicyLabel);
|
||||
|
||||
return RS_(L"ApplicationDisplayNameUnpackaged");
|
||||
}
|
||||
winrt::Windows::Foundation::Uri gettingStartedUri{ gettingStartedUriValue };
|
||||
winrt::Windows::Foundation::Uri documentationUri{ documentationUriValue };
|
||||
winrt::Windows::Foundation::Uri releaseNotesUri{ releaseNotesUriValue };
|
||||
winrt::Windows::Foundation::Uri privacyPolicyUri{ privacyPolicyUriValue };
|
||||
|
||||
winrt::hstring TerminalPage::ApplicationVersion()
|
||||
{
|
||||
if (const auto appLogic{ implementation::AppLogic::Current() })
|
||||
{
|
||||
return appLogic->ApplicationVersion();
|
||||
}
|
||||
gettingStartedLink.NavigateUri(gettingStartedUri);
|
||||
documentationLink.NavigateUri(documentationUri);
|
||||
releaseNotesLink.NavigateUri(releaseNotesUri);
|
||||
privacyPolicyLink.NavigateUri(privacyPolicyUri);
|
||||
|
||||
return RS_(L"ApplicationVersionUnknown");
|
||||
gettingStartedLink.Inlines().Append(gettingStarted);
|
||||
documentationLink.Inlines().Append(documentation);
|
||||
releaseNotesLink.Inlines().Append(releaseNotes);
|
||||
privacyPolicyLink.Inlines().Append(privacyPolicy);
|
||||
|
||||
// Format our about text. It will look like the following:
|
||||
// <Display Name>
|
||||
// Version: <Major>.<Minor>.<Build>.<Revision>
|
||||
// Getting Started
|
||||
// Documentation
|
||||
// Release Notes
|
||||
// Privacy Policy
|
||||
|
||||
aboutTextStream << packageName.c_str() << L"\n";
|
||||
|
||||
aboutTextStream << versionLabel.c_str() << L" ";
|
||||
aboutTextStream << version.Major << L"." << version.Minor << L"." << version.Build << L"." << version.Revision << L"\n";
|
||||
|
||||
winrt::hstring aboutText{ aboutTextStream.str() };
|
||||
about.Text(aboutText);
|
||||
|
||||
const auto buttonText = RS_(L"Ok");
|
||||
|
||||
WUX::Controls::TextBlock aboutTextBlock;
|
||||
aboutTextBlock.Inlines().Append(about);
|
||||
aboutTextBlock.Inlines().Append(gettingStartedLink);
|
||||
aboutTextBlock.Inlines().Append(documentationLink);
|
||||
aboutTextBlock.Inlines().Append(releaseNotesLink);
|
||||
aboutTextBlock.Inlines().Append(privacyPolicyLink);
|
||||
aboutTextBlock.IsTextSelectionEnabled(true);
|
||||
|
||||
WUX::Controls::ContentDialog dialog;
|
||||
dialog.Title(winrt::box_value(title));
|
||||
dialog.Content(aboutTextBlock);
|
||||
dialog.CloseButtonText(buttonText);
|
||||
dialog.DefaultButton(WUX::Controls::ContentDialogButton::Close);
|
||||
|
||||
_showDialogHandlers(*this, dialog);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
@@ -262,7 +303,19 @@ namespace winrt::TerminalApp::implementation
|
||||
// when this is called, nothing happens. See _ShowDialog for details
|
||||
void TerminalPage::_ShowCloseWarningDialog()
|
||||
{
|
||||
_showDialogHandlers(*this, FindName(L"CloseAllDialog").try_as<WUX::Controls::ContentDialog>());
|
||||
auto title = RS_(L"CloseWindowWarningTitle");
|
||||
auto primaryButtonText = RS_(L"CloseAll");
|
||||
auto closeButtonText = RS_(L"Cancel");
|
||||
|
||||
WUX::Controls::ContentDialog dialog;
|
||||
dialog.Title(winrt::box_value(title));
|
||||
|
||||
dialog.CloseButtonText(closeButtonText);
|
||||
dialog.PrimaryButtonText(primaryButtonText);
|
||||
dialog.DefaultButton(WUX::Controls::ContentDialogButton::Primary);
|
||||
auto token = dialog.PrimaryButtonClick({ this, &TerminalPage::_CloseWarningPrimaryButtonOnClick });
|
||||
|
||||
_showDialogHandlers(*this, dialog);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
@@ -287,16 +340,25 @@ namespace winrt::TerminalApp::implementation
|
||||
// add the keyboard shortcuts for the first 9 profiles
|
||||
if (profileIndex < 9)
|
||||
{
|
||||
// Look for a keychord that is bound to the equivalent
|
||||
// NewTab(ProfileIndex=N) action
|
||||
auto actionAndArgs = winrt::make_self<winrt::TerminalApp::implementation::ActionAndArgs>();
|
||||
actionAndArgs->Action(ShortcutAction::NewTab);
|
||||
auto newTabArgs = winrt::make_self<winrt::TerminalApp::implementation::NewTabArgs>();
|
||||
auto newTerminalArgs = winrt::make_self<winrt::TerminalApp::implementation::NewTerminalArgs>();
|
||||
newTerminalArgs->ProfileIndex(profileIndex);
|
||||
newTabArgs->TerminalArgs(*newTerminalArgs);
|
||||
actionAndArgs->Args(*newTabArgs);
|
||||
auto profileKeyChord{ keyBindings.GetKeyBindingForActionWithArgs(*actionAndArgs) };
|
||||
// enum value for ShortcutAction::NewTabProfileX; 0==NewTabProfile0
|
||||
const auto action = static_cast<ShortcutAction>(profileIndex + static_cast<int>(ShortcutAction::NewTabProfile0));
|
||||
// First, attempt to search for the keybinding for the simple
|
||||
// NewTabProfile0-9 ShortcutActions.
|
||||
auto profileKeyChord = keyBindings.GetKeyBindingForAction(action);
|
||||
if (!profileKeyChord)
|
||||
{
|
||||
// If NewTabProfileN didn't have a binding, look for a
|
||||
// keychord that is bound to the equivalent
|
||||
// NewTab(ProfileIndex=N) action
|
||||
auto actionAndArgs = winrt::make_self<winrt::TerminalApp::implementation::ActionAndArgs>();
|
||||
actionAndArgs->Action(ShortcutAction::NewTab);
|
||||
auto newTabArgs = winrt::make_self<winrt::TerminalApp::implementation::NewTabArgs>();
|
||||
auto newTerminalArgs = winrt::make_self<winrt::TerminalApp::implementation::NewTerminalArgs>();
|
||||
newTerminalArgs->ProfileIndex(profileIndex);
|
||||
newTabArgs->TerminalArgs(*newTerminalArgs);
|
||||
actionAndArgs->Args(*newTabArgs);
|
||||
profileKeyChord = keyBindings.GetKeyBindingForActionWithArgs(*actionAndArgs);
|
||||
}
|
||||
|
||||
// make sure we find one to display
|
||||
if (profileKeyChord)
|
||||
@@ -344,15 +406,7 @@ namespace winrt::TerminalApp::implementation
|
||||
|
||||
// add static items
|
||||
{
|
||||
// GH#2455 - Make sure to try/catch calls to Application::Current,
|
||||
// because that _won't_ be an instance of TerminalApp::App in the
|
||||
// LocalTests
|
||||
auto isUwp = false;
|
||||
try
|
||||
{
|
||||
isUwp = ::winrt::Windows::UI::Xaml::Application::Current().as<::winrt::TerminalApp::App>().Logic().IsUwp();
|
||||
}
|
||||
CATCH_LOG();
|
||||
const auto isUwp = ::winrt::Windows::UI::Xaml::Application::Current().as<::winrt::TerminalApp::App>().Logic().IsUwp();
|
||||
|
||||
if (!isUwp)
|
||||
{
|
||||
@@ -422,7 +476,6 @@ namespace winrt::TerminalApp::implementation
|
||||
// control which profile is created and with possible other
|
||||
// configurations. See CascadiaSettings::BuildSettings for more details.
|
||||
void TerminalPage::_OpenNewTab(const winrt::TerminalApp::NewTerminalArgs& newTerminalArgs)
|
||||
try
|
||||
{
|
||||
const auto [profileGuid, settings] = _settings->BuildSettings(newTerminalArgs);
|
||||
|
||||
@@ -446,7 +499,6 @@ namespace winrt::TerminalApp::implementation
|
||||
TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES),
|
||||
TelemetryPrivacyDataTag(PDT_ProductAndServicePerformance));
|
||||
}
|
||||
CATCH_LOG();
|
||||
|
||||
winrt::fire_and_forget TerminalPage::_RemoveOnCloseRoutine(Microsoft::UI::Xaml::Controls::TabViewItem tabViewItem, winrt::com_ptr<TerminalPage> page)
|
||||
{
|
||||
@@ -462,25 +514,11 @@ namespace winrt::TerminalApp::implementation
|
||||
// - settings: the TerminalSettings object to use to create the TerminalControl with.
|
||||
void TerminalPage::_CreateNewTabFromSettings(GUID profileGuid, TerminalSettings settings)
|
||||
{
|
||||
const bool isFirstTab = _tabs.Size() == 0;
|
||||
// Initialize the new tab
|
||||
|
||||
// Create a connection based on the values in our settings object.
|
||||
auto connection = _CreateConnectionFromSettings(profileGuid, settings);
|
||||
|
||||
TerminalConnection::ITerminalConnection debugConnection{ nullptr };
|
||||
if (_settings->GlobalSettings().DebugFeaturesEnabled())
|
||||
{
|
||||
const CoreWindow window = CoreWindow::GetForCurrentThread();
|
||||
const auto rAltState = window.GetKeyState(VirtualKey::RightMenu);
|
||||
const auto lAltState = window.GetKeyState(VirtualKey::LeftMenu);
|
||||
const bool bothAltsPressed = WI_IsFlagSet(lAltState, CoreVirtualKeyStates::Down) &&
|
||||
WI_IsFlagSet(rAltState, CoreVirtualKeyStates::Down);
|
||||
if (bothAltsPressed)
|
||||
{
|
||||
std::tie(connection, debugConnection) = OpenDebugTapConnection(connection);
|
||||
}
|
||||
}
|
||||
|
||||
const auto connection = _CreateConnectionFromSettings(profileGuid, settings);
|
||||
TermControl term{ settings, connection };
|
||||
|
||||
// Add the new tab to the list of our tabs.
|
||||
@@ -530,17 +568,20 @@ namespace winrt::TerminalApp::implementation
|
||||
}
|
||||
});
|
||||
|
||||
if (debugConnection) // this will only be set if global debugging is on and tap is active
|
||||
// If this is the first tab, we don't need to kick off the event to get
|
||||
// the tab's content added to the root of the page. just do it
|
||||
// immediately.
|
||||
if (isFirstTab)
|
||||
{
|
||||
TermControl newControl{ settings, debugConnection };
|
||||
_RegisterTerminalEvents(newControl, *newTabImpl);
|
||||
// Split (auto) with the debug tap.
|
||||
newTabImpl->SplitPane(SplitState::Automatic, profileGuid, newControl);
|
||||
_tabContent.Children().Clear();
|
||||
_tabContent.Children().Append(newTabImpl->GetRootElement());
|
||||
}
|
||||
else
|
||||
{
|
||||
// This kicks off TabView::SelectionChanged, in response to which
|
||||
// we'll attach the terminal's Xaml control to the Xaml root.
|
||||
_tabView.SelectedItem(tabViewItem);
|
||||
}
|
||||
|
||||
// This kicks off TabView::SelectionChanged, in response to which
|
||||
// we'll attach the terminal's Xaml control to the Xaml root.
|
||||
_tabView.SelectedItem(tabViewItem);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
@@ -632,9 +673,8 @@ namespace winrt::TerminalApp::implementation
|
||||
const RoutedEventArgs&)
|
||||
{
|
||||
const auto feedbackUriValue = RS_(L"FeedbackUriValue");
|
||||
winrt::Windows::Foundation::Uri feedbackUri{ feedbackUriValue };
|
||||
|
||||
winrt::Windows::System::Launcher::LaunchUriAsync(feedbackUri);
|
||||
winrt::Windows::System::Launcher::LaunchUriAsync({ feedbackUriValue });
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
@@ -769,30 +809,13 @@ namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
if (auto index{ _GetFocusedTabIndex() })
|
||||
{
|
||||
try
|
||||
auto focusedTab = _GetStrongTabImpl(*index);
|
||||
const auto& profileGuid = focusedTab->GetFocusedProfile();
|
||||
if (profileGuid.has_value())
|
||||
{
|
||||
auto focusedTab = _GetStrongTabImpl(*index);
|
||||
// TODO: GH#5047 - In the future, we should get the Profile of
|
||||
// the focused pane, and use that to build a new instance of the
|
||||
// settings so we can duplicate this tab/pane.
|
||||
//
|
||||
// Currently, if the profile doesn't exist anymore in our
|
||||
// settings, we'll silently do nothing.
|
||||
//
|
||||
// In the future, it will be preferable to just duplicate the
|
||||
// current control's settings, but we can't do that currently,
|
||||
// because we won't be able to create a new instance of the
|
||||
// connection without keeping an instance of the original Profile
|
||||
// object around.
|
||||
|
||||
const auto& profileGuid = focusedTab->GetFocusedProfile();
|
||||
if (profileGuid.has_value())
|
||||
{
|
||||
const auto settings = _settings->BuildSettings(profileGuid.value());
|
||||
_CreateNewTabFromSettings(profileGuid.value(), settings);
|
||||
}
|
||||
const auto settings = _settings->BuildSettings(profileGuid.value());
|
||||
_CreateNewTabFromSettings(profileGuid.value(), settings);
|
||||
}
|
||||
CATCH_LOG();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -877,36 +900,20 @@ namespace winrt::TerminalApp::implementation
|
||||
// Wraparound math. By adding tabCount and then calculating modulo tabCount,
|
||||
// we clamp the values to the range [0, tabCount) while still supporting moving
|
||||
// leftward from 0 to tabCount - 1.
|
||||
const auto newTabIndex = ((tabCount + *index + (bMoveRight ? 1 : -1)) % tabCount);
|
||||
_SelectTab(newTabIndex);
|
||||
_SetFocusedTabIndex(((tabCount + *index + (bMoveRight ? 1 : -1)) % tabCount));
|
||||
}
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Sets focus to the desired tab. Returns false if the provided tabIndex
|
||||
// is greater than the number of tabs we have.
|
||||
// - During startup, we'll immediately set the selected tab as focused.
|
||||
// - After startup, we'll dispatch an async method to set the the selected
|
||||
// item of the TabView, which will then also trigger a
|
||||
// TabView::SelectionChanged, handled in
|
||||
// TerminalPage::_OnTabSelectionChanged
|
||||
// Return Value:
|
||||
// true iff we were able to select that tab index, false otherwise
|
||||
bool TerminalPage::_SelectTab(const uint32_t tabIndex)
|
||||
{
|
||||
if (tabIndex >= 0 && tabIndex < _tabs.Size())
|
||||
{
|
||||
if (_startupState == StartupState::InStartup)
|
||||
{
|
||||
auto tab{ _GetStrongTabImpl(tabIndex) };
|
||||
_tabView.SelectedItem(tab->GetTabViewItem());
|
||||
_UpdatedSelectedTab(tabIndex);
|
||||
}
|
||||
else
|
||||
{
|
||||
_SetFocusedTabIndex(tabIndex);
|
||||
}
|
||||
|
||||
_SetFocusedTabIndex(tabIndex);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -959,16 +966,6 @@ namespace winrt::TerminalApp::implementation
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - An async method for changing the focused tab on the UI thread. This
|
||||
// method will _only_ set the selected item of the TabView, which will
|
||||
// then also trigger a TabView::SelectionChanged event, which we'll handle
|
||||
// in TerminalPage::_OnTabSelectionChanged, where we'll mark the new tab
|
||||
// as focused.
|
||||
// Arguments:
|
||||
// - tabIndex: the index in the list of tabs to focus.
|
||||
// Return Value:
|
||||
// - <none>
|
||||
winrt::fire_and_forget TerminalPage::_SetFocusedTabIndex(const uint32_t tabIndex)
|
||||
{
|
||||
// GH#1117: This is a workaround because _tabView.SelectedIndex(tabIndex)
|
||||
@@ -1077,65 +1074,42 @@ namespace winrt::TerminalApp::implementation
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
auto focusedTab = _GetStrongTabImpl(*indexOpt);
|
||||
|
||||
winrt::Microsoft::Terminal::Settings::TerminalSettings controlSettings;
|
||||
GUID realGuid;
|
||||
bool profileFound = false;
|
||||
|
||||
if (splitMode == TerminalApp::SplitType::Duplicate)
|
||||
{
|
||||
auto focusedTab = _GetStrongTabImpl(*indexOpt);
|
||||
winrt::Microsoft::Terminal::Settings::TerminalSettings controlSettings;
|
||||
GUID realGuid;
|
||||
bool profileFound = false;
|
||||
|
||||
if (splitMode == TerminalApp::SplitType::Duplicate)
|
||||
std::optional<GUID> current_guid = focusedTab->GetFocusedProfile();
|
||||
if (current_guid)
|
||||
{
|
||||
std::optional<GUID> current_guid = focusedTab->GetFocusedProfile();
|
||||
if (current_guid)
|
||||
{
|
||||
profileFound = true;
|
||||
controlSettings = _settings->BuildSettings(current_guid.value());
|
||||
realGuid = current_guid.value();
|
||||
}
|
||||
// TODO: GH#5047 - In the future, we should get the Profile of
|
||||
// the focused pane, and use that to build a new instance of the
|
||||
// settings so we can duplicate this tab/pane.
|
||||
//
|
||||
// Currently, if the profile doesn't exist anymore in our
|
||||
// settings, we'll silently do nothing.
|
||||
//
|
||||
// In the future, it will be preferable to just duplicate the
|
||||
// current control's settings, but we can't do that currently,
|
||||
// because we won't be able to create a new instance of the
|
||||
// connection without keeping an instance of the original Profile
|
||||
// object around.
|
||||
profileFound = true;
|
||||
controlSettings = _settings->BuildSettings(current_guid.value());
|
||||
realGuid = current_guid.value();
|
||||
}
|
||||
if (!profileFound)
|
||||
{
|
||||
std::tie(realGuid, controlSettings) = _settings->BuildSettings(newTerminalArgs);
|
||||
}
|
||||
|
||||
const auto controlConnection = _CreateConnectionFromSettings(realGuid, controlSettings);
|
||||
|
||||
const auto canSplit = focusedTab->CanSplitPane(splitType);
|
||||
|
||||
if (!canSplit && _startupState == StartupState::Initialized)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
auto realSplitType = splitType;
|
||||
if (realSplitType == SplitState::Automatic && _startupState < StartupState::Initialized)
|
||||
{
|
||||
float contentWidth = gsl::narrow_cast<float>(_tabContent.ActualWidth());
|
||||
float contentHeight = gsl::narrow_cast<float>(_tabContent.ActualHeight());
|
||||
realSplitType = focusedTab->PreCalculateAutoSplit({ contentWidth, contentHeight });
|
||||
}
|
||||
|
||||
TermControl newControl{ controlSettings, controlConnection };
|
||||
|
||||
// Hookup our event handlers to the new terminal
|
||||
_RegisterTerminalEvents(newControl, *focusedTab);
|
||||
|
||||
focusedTab->SplitPane(realSplitType, realGuid, newControl);
|
||||
}
|
||||
CATCH_LOG();
|
||||
if (!profileFound)
|
||||
{
|
||||
std::tie(realGuid, controlSettings) = _settings->BuildSettings(newTerminalArgs);
|
||||
}
|
||||
|
||||
const auto controlConnection = _CreateConnectionFromSettings(realGuid, controlSettings);
|
||||
|
||||
const auto canSplit = focusedTab->CanSplitPane(splitType);
|
||||
|
||||
if (!canSplit)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
TermControl newControl{ controlSettings, controlConnection };
|
||||
|
||||
// Hookup our event handlers to the new terminal
|
||||
_RegisterTerminalEvents(newControl, *focusedTab);
|
||||
|
||||
focusedTab->SplitPane(splitType, realGuid, newControl);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
@@ -1310,21 +1284,18 @@ namespace winrt::TerminalApp::implementation
|
||||
// copy text to dataPack
|
||||
dataPack.SetText(copiedData.Text());
|
||||
|
||||
if (_settings->GlobalSettings().GetCopyFormatting())
|
||||
// copy html to dataPack
|
||||
const auto htmlData = copiedData.Html();
|
||||
if (!htmlData.empty())
|
||||
{
|
||||
// copy html to dataPack
|
||||
const auto htmlData = copiedData.Html();
|
||||
if (!htmlData.empty())
|
||||
{
|
||||
dataPack.SetHtmlFormat(htmlData);
|
||||
}
|
||||
dataPack.SetHtmlFormat(htmlData);
|
||||
}
|
||||
|
||||
// copy rtf data to dataPack
|
||||
const auto rtfData = copiedData.Rtf();
|
||||
if (!rtfData.empty())
|
||||
{
|
||||
dataPack.SetRtf(rtfData);
|
||||
}
|
||||
// copy rtf data to dataPack
|
||||
const auto rtfData = copiedData.Rtf();
|
||||
if (!rtfData.empty())
|
||||
{
|
||||
dataPack.SetRtf(rtfData);
|
||||
}
|
||||
|
||||
try
|
||||
@@ -1374,13 +1345,14 @@ namespace winrt::TerminalApp::implementation
|
||||
// Method Description:
|
||||
// - Copy text from the focused terminal to the Windows Clipboard
|
||||
// Arguments:
|
||||
// - singleLine: if enabled, copy contents as a single line of text
|
||||
// - trimTrailingWhitespace: enable removing any whitespace from copied selection
|
||||
// and get text to appear on separate lines.
|
||||
// Return Value:
|
||||
// - true iff we we able to copy text (if a selection was active)
|
||||
bool TerminalPage::_CopyText(const bool singleLine)
|
||||
bool TerminalPage::_CopyText(const bool trimTrailingWhitespace)
|
||||
{
|
||||
const auto control = _GetActiveControl();
|
||||
return control.CopySelectionToClipboard(singleLine);
|
||||
return control.CopySelectionToClipboard(!trimTrailingWhitespace);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
@@ -1453,31 +1425,6 @@ namespace winrt::TerminalApp::implementation
|
||||
}
|
||||
}
|
||||
|
||||
void TerminalPage::_UpdatedSelectedTab(const int32_t index)
|
||||
{
|
||||
// Unfocus all the tabs.
|
||||
for (auto tab : _tabs)
|
||||
{
|
||||
auto tabImpl{ _GetStrongTabImpl(tab) };
|
||||
tabImpl->SetFocused(false);
|
||||
}
|
||||
|
||||
if (index >= 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
auto tab{ _GetStrongTabImpl(index) };
|
||||
|
||||
_tabContent.Children().Clear();
|
||||
_tabContent.Children().Append(tab->GetRootElement());
|
||||
|
||||
tab->SetFocused(true);
|
||||
_titleChangeHandlers(*this, Title());
|
||||
}
|
||||
CATCH_LOG();
|
||||
}
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Responds to the TabView control's Selection Changed event (to move a
|
||||
// new terminal control into focus) when not in in the middle of a tab rearrangement.
|
||||
@@ -1490,7 +1437,28 @@ namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
auto tabView = sender.as<MUX::Controls::TabView>();
|
||||
auto selectedIndex = tabView.SelectedIndex();
|
||||
_UpdatedSelectedTab(selectedIndex);
|
||||
|
||||
// Unfocus all the tabs.
|
||||
for (auto tab : _tabs)
|
||||
{
|
||||
auto tabImpl{ _GetStrongTabImpl(tab) };
|
||||
tabImpl->SetFocused(false);
|
||||
}
|
||||
|
||||
if (selectedIndex >= 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
auto tab{ _GetStrongTabImpl(selectedIndex) };
|
||||
|
||||
_tabContent.Children().Clear();
|
||||
_tabContent.Children().Append(tab->GetRootElement());
|
||||
|
||||
tab->SetFocused(true);
|
||||
_titleChangeHandlers(*this, Title());
|
||||
}
|
||||
CATCH_LOG();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1556,28 +1524,16 @@ namespace winrt::TerminalApp::implementation
|
||||
for (auto& profile : profiles)
|
||||
{
|
||||
const GUID profileGuid = profile.GetGuid();
|
||||
const auto settings = _settings->BuildSettings(profileGuid);
|
||||
|
||||
try
|
||||
for (auto tab : _tabs)
|
||||
{
|
||||
// BuildSettings can throw an exception if the profileGuid does
|
||||
// not belong to an actual profile in the list of profiles.
|
||||
const auto settings = _settings->BuildSettings(profileGuid);
|
||||
|
||||
for (auto tab : _tabs)
|
||||
{
|
||||
// Attempt to reload the settings of any panes with this profile
|
||||
auto tabImpl{ _GetStrongTabImpl(tab) };
|
||||
tabImpl->UpdateSettings(settings, profileGuid);
|
||||
}
|
||||
// Attempt to reload the settings of any panes with this profile
|
||||
auto tabImpl{ _GetStrongTabImpl(tab) };
|
||||
tabImpl->UpdateSettings(settings, profileGuid);
|
||||
}
|
||||
CATCH_LOG();
|
||||
}
|
||||
|
||||
// GH#2455: If there are any panes with controls that had been
|
||||
// initialized with a Profile that no longer exists in our list of
|
||||
// profiles, we'll leave it unmodified. The profile doesn't exist
|
||||
// anymore, so we can't possibly update its settings.
|
||||
|
||||
// Update the icon of the tab for the currently focused profile in that tab.
|
||||
for (auto tab : _tabs)
|
||||
{
|
||||
@@ -1621,7 +1577,7 @@ namespace winrt::TerminalApp::implementation
|
||||
// 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
|
||||
// succesfully 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.
|
||||
@@ -1719,7 +1675,7 @@ namespace winrt::TerminalApp::implementation
|
||||
// Arguments:
|
||||
// - <none>
|
||||
// Return Value:
|
||||
// - the help text or error message for the provided commandline, if one
|
||||
// - the help text or error message for the providied commandline, if one
|
||||
// exists, otherwise the empty string.
|
||||
winrt::hstring TerminalPage::EarlyExitMessage()
|
||||
{
|
||||
|
||||
@@ -20,13 +20,6 @@ namespace TerminalAppLocalTests
|
||||
|
||||
namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
enum StartupState : int
|
||||
{
|
||||
NotInitialized = 0,
|
||||
InStartup = 1,
|
||||
Initialized = 2
|
||||
};
|
||||
|
||||
struct TerminalPage : TerminalPageT<TerminalPage>
|
||||
{
|
||||
public:
|
||||
@@ -38,13 +31,12 @@ namespace winrt::TerminalApp::implementation
|
||||
|
||||
hstring Title();
|
||||
|
||||
void ShowOkDialog(const winrt::hstring& titleKey, const winrt::hstring& contentKey);
|
||||
|
||||
void TitlebarClicked();
|
||||
|
||||
float CalcSnappedDimension(const bool widthOrHeight, const float dimension) const;
|
||||
|
||||
winrt::hstring ApplicationDisplayName();
|
||||
winrt::hstring ApplicationVersion();
|
||||
|
||||
void CloseWindow();
|
||||
|
||||
int32_t SetStartupCommandline(winrt::array_view<const hstring> args);
|
||||
@@ -56,11 +48,8 @@ namespace winrt::TerminalApp::implementation
|
||||
DECLARE_EVENT_WITH_TYPED_EVENT_HANDLER(SetTitleBarContent, _setTitleBarContentHandlers, winrt::Windows::Foundation::IInspectable, winrt::Windows::UI::Xaml::UIElement);
|
||||
DECLARE_EVENT_WITH_TYPED_EVENT_HANDLER(ShowDialog, _showDialogHandlers, winrt::Windows::Foundation::IInspectable, winrt::Windows::UI::Xaml::Controls::ContentDialog);
|
||||
DECLARE_EVENT_WITH_TYPED_EVENT_HANDLER(ToggleFullscreen, _toggleFullscreenHandlers, winrt::Windows::Foundation::IInspectable, winrt::TerminalApp::ToggleFullscreenEventArgs);
|
||||
TYPED_EVENT(Initialized, winrt::Windows::Foundation::IInspectable, winrt::Windows::UI::Xaml::RoutedEventArgs);
|
||||
|
||||
private:
|
||||
friend struct TerminalPageT<TerminalPage>; // for Xaml to bind events
|
||||
|
||||
// If you add controls here, but forget to null them either here or in
|
||||
// the ctor, you're going to have a bad time. It'll mysteriously fail to
|
||||
// activate the app.
|
||||
@@ -86,12 +75,9 @@ namespace winrt::TerminalApp::implementation
|
||||
|
||||
winrt::com_ptr<ShortcutActionDispatch> _actionDispatch{ winrt::make_self<ShortcutActionDispatch>() };
|
||||
|
||||
winrt::Windows::UI::Xaml::Controls::Grid::LayoutUpdated_revoker _layoutUpdatedRevoker;
|
||||
StartupState _startupState{ StartupState::NotInitialized };
|
||||
|
||||
::TerminalApp::AppCommandlineArgs _appArgs;
|
||||
int _ParseArgs(winrt::array_view<const hstring>& args);
|
||||
winrt::fire_and_forget _ProcessStartupActions();
|
||||
fire_and_forget _ProcessNextStartupAction();
|
||||
|
||||
void _ShowAboutDialog();
|
||||
void _ShowCloseWarningDialog();
|
||||
@@ -155,8 +141,6 @@ namespace winrt::TerminalApp::implementation
|
||||
void _OnTabItemsChanged(const IInspectable& sender, const Windows::Foundation::Collections::IVectorChangedEventArgs& eventArgs);
|
||||
void _OnContentSizeChanged(const IInspectable& /*sender*/, Windows::UI::Xaml::SizeChangedEventArgs const& e);
|
||||
void _OnTabCloseRequested(const IInspectable& sender, const Microsoft::UI::Xaml::Controls::TabViewTabCloseRequestedEventArgs& eventArgs);
|
||||
void _OnFirstLayout(const IInspectable& sender, const IInspectable& eventArgs);
|
||||
void _UpdatedSelectedTab(const int32_t index);
|
||||
|
||||
void _Find();
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user