mirror of
https://github.com/microsoft/terminal.git
synced 2026-04-06 22:29:43 +00:00
Compare commits
5 Commits
dev/miniks
...
dev/migrie
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
068a98c40e | ||
|
|
c0bb37c291 | ||
|
|
9d79c5c3fe | ||
|
|
112cb0ab8d | ||
|
|
d972b5e07a |
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/
|
||||
|
||||
|
||||
@@ -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>
|
||||
@@ -42,7 +42,7 @@ Properties listed below are specific to each unique 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"`. |
|
||||
| `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. |
|
||||
|
||||
@@ -580,7 +580,7 @@
|
||||
"type": "boolean"
|
||||
},
|
||||
"fontFace": {
|
||||
"default": "Cascadia Code",
|
||||
"default": "Consolas",
|
||||
"description": "Name of the font face used in the profile.",
|
||||
"type": "string"
|
||||
},
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -72,25 +72,12 @@ 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`:
|
||||
@@ -104,16 +91,4 @@ Assuming that you've installed MSYS2 into `C:/msys64`:
|
||||
}
|
||||
````
|
||||
|
||||
## 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! -->
|
||||
|
||||
@@ -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
|
||||
@@ -224,7 +208,7 @@ 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
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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'">
|
||||
|
||||
@@ -70,10 +70,6 @@ namespace TerminalAppLocalTests
|
||||
|
||||
TEST_METHOD(TestTerminalArgsForBinding);
|
||||
|
||||
TEST_METHOD(FindMissingProfile);
|
||||
TEST_METHOD(MakeSettingsForProfileThatDoesntExist);
|
||||
TEST_METHOD(MakeSettingsForDefaultProfileThatDoesntExist);
|
||||
|
||||
TEST_METHOD(TestLayerProfileOnColorScheme);
|
||||
|
||||
TEST_METHOD(ValidateKeybindingsWarnings);
|
||||
@@ -2098,146 +2094,6 @@ 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(
|
||||
|
||||
@@ -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,321 +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()
|
||||
{
|
||||
// * 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()
|
||||
{
|
||||
// * 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 },
|
||||
|
||||
@@ -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>();
|
||||
@@ -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
|
||||
|
||||
@@ -344,7 +344,7 @@ static const std::map<ShortcutAction, ParseActionFunction, std::less<>> argParse
|
||||
|
||||
// Function Description:
|
||||
// - Small helper to create a json value serialization of a single
|
||||
// KeyBinding->Action mapping.
|
||||
// KeyBinding->Action maping.
|
||||
// {
|
||||
// keys:[String],
|
||||
// command:String
|
||||
|
||||
@@ -410,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,
|
||||
|
||||
@@ -177,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));
|
||||
|
||||
@@ -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);
|
||||
@@ -41,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{},
|
||||
@@ -67,8 +59,7 @@ GlobalAppSettings::GlobalAppSettings() :
|
||||
_tabWidthMode{ TabViewWidthMode::Equal },
|
||||
_wordDelimiters{ DEFAULT_WORD_DELIMITERS },
|
||||
_copyOnSelect{ false },
|
||||
_launchMode{ LaunchMode::DefaultMode },
|
||||
_debugFeatures{ debugFeaturesDefault }
|
||||
_launchMode{ LaunchMode::DefaultMode }
|
||||
{
|
||||
}
|
||||
|
||||
@@ -180,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
|
||||
{
|
||||
@@ -251,7 +237,6 @@ Json::Value GlobalAppSettings::ToJson() const
|
||||
jsonObject[JsonKey(KeybindingsKey)] = _keybindings->ToJson();
|
||||
jsonObject[JsonKey(ConfirmCloseAllKey)] = _confirmCloseAllTabs;
|
||||
jsonObject[JsonKey(SnapToGridOnResizeKey)] = _SnapToGridOnResize;
|
||||
jsonObject[JsonKey(DebugFeaturesKey)] = _debugFeatures;
|
||||
|
||||
return jsonObject;
|
||||
}
|
||||
@@ -339,9 +324,6 @@ void GlobalAppSettings::LayerJson(const Json::Value& json)
|
||||
}
|
||||
|
||||
JsonUtils::GetBool(json, SnapToGridOnResizeKey, _SnapToGridOnResize);
|
||||
|
||||
// GetBool will only override the current value if the key exists
|
||||
JsonUtils::GetBool(json, DebugFeaturesKey, _debugFeatures);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
|
||||
@@ -77,8 +77,6 @@ public:
|
||||
|
||||
winrt::Microsoft::UI::Xaml::Controls::TabViewWidthMode GetTabWidthMode() const noexcept;
|
||||
|
||||
bool DebugFeaturesEnabled() const noexcept;
|
||||
|
||||
Json::Value ToJson() const;
|
||||
static GlobalAppSettings FromJson(const Json::Value& json);
|
||||
void LayerJson(const Json::Value& json);
|
||||
@@ -117,8 +115,6 @@ private:
|
||||
|
||||
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;
|
||||
|
||||
|
||||
@@ -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::FromValueAndType(paneSizes.first, GridUnitType::Star));
|
||||
|
||||
auto secondColDef = Controls::ColumnDefinition();
|
||||
secondColDef.Width(GridLengthHelper::FromValueAndType(second, GridUnitType::Star));
|
||||
secondColDef.Width(GridLengthHelper::FromValueAndType(paneSizes.second, GridUnitType::Star));
|
||||
|
||||
_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::FromValueAndType(paneSizes.first, GridUnitType::Star));
|
||||
|
||||
auto secondRowDef = Controls::RowDefinition();
|
||||
secondRowDef.Height(GridLengthHelper::FromValueAndType(second, GridUnitType::Star));
|
||||
secondRowDef.Height(GridLengthHelper::FromValueAndType(paneSizes.second, GridUnitType::Star));
|
||||
|
||||
_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;
|
||||
|
||||
@@ -53,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)
|
||||
|
||||
|
||||
@@ -162,6 +162,40 @@ 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://aka.ms/terminal-feedback</value>
|
||||
</data>
|
||||
@@ -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,47 +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="AboutDialog_DisplayNameUnpackaged" 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="AboutDialog_VersionUnknown" 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>
|
||||
</root>
|
||||
</root>
|
||||
@@ -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;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -15,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;
|
||||
@@ -64,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);
|
||||
|
||||
@@ -147,115 +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()
|
||||
{
|
||||
try
|
||||
{
|
||||
const auto package{ winrt::Windows::ApplicationModel::Package::Current() };
|
||||
return package.DisplayName();
|
||||
}
|
||||
CATCH_LOG();
|
||||
gettingStarted.Text(gettingStartedLabel);
|
||||
documentation.Text(documentationLabel);
|
||||
releaseNotes.Text(releaseNotesLabel);
|
||||
privacyPolicy.Text(privacyPolicyLabel);
|
||||
|
||||
return RS_(L"AboutDialog_DisplayNameUnpackaged");
|
||||
}
|
||||
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()
|
||||
{
|
||||
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();
|
||||
gettingStartedLink.NavigateUri(gettingStartedUri);
|
||||
documentationLink.NavigateUri(documentationUri);
|
||||
releaseNotesLink.NavigateUri(releaseNotesUri);
|
||||
privacyPolicyLink.NavigateUri(privacyPolicyUri);
|
||||
|
||||
return RS_(L"AboutDialog_VersionUnknown");
|
||||
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:
|
||||
@@ -267,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:
|
||||
@@ -358,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)
|
||||
{
|
||||
@@ -436,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);
|
||||
|
||||
@@ -460,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)
|
||||
{
|
||||
@@ -476,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.
|
||||
@@ -544,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:
|
||||
@@ -783,30 +810,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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -891,36 +901,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;
|
||||
@@ -973,16 +967,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)
|
||||
@@ -1091,65 +1075,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:
|
||||
@@ -1465,31 +1426,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.
|
||||
@@ -1502,7 +1438,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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1568,28 +1525,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)
|
||||
{
|
||||
@@ -1633,7 +1578,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.
|
||||
@@ -1731,7 +1676,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();
|
||||
|
||||
|
||||
@@ -13,15 +13,10 @@ namespace TerminalApp
|
||||
Int32 SetStartupCommandline(String[] commands);
|
||||
String EarlyExitMessage { get; };
|
||||
|
||||
// XAML bound properties
|
||||
String ApplicationDisplayName { get; };
|
||||
String ApplicationVersion { get; };
|
||||
|
||||
event Windows.Foundation.TypedEventHandler<Object, String> TitleChanged;
|
||||
event Windows.Foundation.TypedEventHandler<Object, LastTabClosedEventArgs> LastTabClosed;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Windows.UI.Xaml.UIElement> SetTitleBarContent;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Windows.UI.Xaml.Controls.ContentDialog> ShowDialog;
|
||||
event Windows.Foundation.TypedEventHandler<Object, ToggleFullscreenEventArgs> ToggleFullscreen;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Windows.UI.Xaml.RoutedEventArgs> Initialized;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,39 +19,5 @@ the MIT License. See LICENSE in the project root for license information. -->
|
||||
<local:TabRowControl x:Name="TabRow" Grid.Row="0" />
|
||||
|
||||
<Grid x:Name="TabContent" Grid.Row="1" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" />
|
||||
|
||||
<ContentDialog
|
||||
x:Load="False"
|
||||
x:Name="AboutDialog"
|
||||
x:Uid="AboutDialog"
|
||||
DefaultButton="Close">
|
||||
<StackPanel Orientation="Vertical">
|
||||
<TextBlock IsTextSelectionEnabled="True">
|
||||
<Run Text="{x:Bind ApplicationDisplayName}" /> <LineBreak />
|
||||
<Run x:Uid="AboutDialog_VersionLabel" />
|
||||
<Run Text="{x:Bind ApplicationVersion}" />
|
||||
</TextBlock>
|
||||
<HyperlinkButton
|
||||
x:Uid="AboutDialog_GettingStartedLink"
|
||||
NavigateUri="https://aka.ms/terminal-getting-started" />
|
||||
<HyperlinkButton
|
||||
x:Uid="AboutDialog_DocumentationLink"
|
||||
NavigateUri="https://aka.ms/terminal-documentation" />
|
||||
<HyperlinkButton
|
||||
x:Uid="AboutDialog_ReleaseNotesLink"
|
||||
NavigateUri="https://aka.ms/terminal-release-notes" />
|
||||
<HyperlinkButton
|
||||
x:Uid="AboutDialog_PrivacyPolicyLink"
|
||||
NavigateUri="https://aka.ms/terminal-privacy-policy" />
|
||||
</StackPanel>
|
||||
</ContentDialog>
|
||||
|
||||
<ContentDialog
|
||||
x:Load="False"
|
||||
x:Name="CloseAllDialog"
|
||||
x:Uid="CloseAllDialog"
|
||||
DefaultButton="Primary"
|
||||
PrimaryButtonClick="_CloseWarningPrimaryButtonOnClick">
|
||||
</ContentDialog>
|
||||
</Grid>
|
||||
</Page>
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
"colorScheme": "Vintage",
|
||||
"cursorColor": "#FFFFFF",
|
||||
"cursorShape": "bar",
|
||||
"fontFace": "Cascadia Code",
|
||||
"icon": "ms-appx:///ProfileIcons/{550ce7b8-d500-50ad-8a1a-c400c3262db3}.png",
|
||||
"padding": "8, 8, 8, 8",
|
||||
"snapOnInput": true,
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
"closeOnExit": "graceful",
|
||||
"colorScheme": "Campbell Powershell",
|
||||
"cursorShape": "bar",
|
||||
"fontFace": "Cascadia Code",
|
||||
"fontFace": "Consolas",
|
||||
"fontSize": 12,
|
||||
"historySize": 9001,
|
||||
"icon": "ms-appx:///ProfileIcons/{61c54bbd-c2c6-5271-96e7-009a87ff44bf}.png",
|
||||
@@ -41,7 +41,7 @@
|
||||
"closeOnExit": "graceful",
|
||||
"colorScheme": "Campbell",
|
||||
"cursorShape": "bar",
|
||||
"fontFace": "Cascadia Code",
|
||||
"fontFace": "Consolas",
|
||||
"fontSize": 12,
|
||||
"historySize": 9001,
|
||||
"icon": "ms-appx:///ProfileIcons/{0caa0dad-35be-5f56-a8ff-afceeeaa6101}.png",
|
||||
|
||||
@@ -107,7 +107,6 @@
|
||||
<ClInclude Include="../ActionAndArgs.h">
|
||||
<DependentUpon>../ActionArgs.idl</DependentUpon>
|
||||
</ClInclude>
|
||||
<ClInclude Include="../DebugTapConnection.h" />
|
||||
<ClInclude Include="../AppKeyBindings.h">
|
||||
<DependentUpon>../AppKeyBindings.idl</DependentUpon>
|
||||
</ClInclude>
|
||||
@@ -154,7 +153,6 @@
|
||||
<ClCompile Include="../WslDistroGenerator.cpp" />
|
||||
<ClCompile Include="../AzureCloudShellGenerator.cpp" />
|
||||
<ClCompile Include="../Pane.LayoutSizeNode.cpp" />
|
||||
<ClCompile Include="../DebugTapConnection.cpp" />
|
||||
<ClCompile Include="pch.cpp">
|
||||
<PrecompiledHeader>Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
@@ -218,7 +216,7 @@
|
||||
</ItemGroup>
|
||||
<!-- ========================= Misc Files ======================== -->
|
||||
<ItemGroup>
|
||||
<PRIResource Include="..\Resources\*\Resources.resw" />
|
||||
<PRIResource Include="../Resources/Resources.language-en.resw" />
|
||||
<None Include="../packages.config" />
|
||||
</ItemGroup>
|
||||
<!-- ========================= Project References ======================== -->
|
||||
|
||||
@@ -53,7 +53,7 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
||||
|
||||
_transitionToState(ConnectionState::Connecting);
|
||||
|
||||
// Set initial window title.
|
||||
// Set initial winodw title.
|
||||
_TerminalOutputHandlers(L"\x1b]0;Telnet\x7");
|
||||
}
|
||||
catch (...)
|
||||
|
||||
@@ -59,7 +59,7 @@
|
||||
<Midl Include="TelnetConnection.idl" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PRIResource Include="Resources\*\Resources.resw" />
|
||||
<PRIResource Include="Resources/Resources.language-en.resw" />
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<!-- ========================= Project References ======================== -->
|
||||
|
||||
@@ -159,7 +159,7 @@
|
||||
</data>
|
||||
<data name="TerminalControl_ControlType" xml:space="preserve">
|
||||
<value>terminal</value>
|
||||
<comment>The type of control that the terminal adheres to. Used to identify how a user can interact with this kind of control.</comment>
|
||||
<comment>The type of control that the terminal ahderes to. Used to identify how a user can interact with this kind of control.</comment>
|
||||
</data>
|
||||
<data name="SearchBox_Close.[using:Windows.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
|
||||
<value>Close Search Box</value>
|
||||
@@ -172,13 +172,8 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
|
||||
TextBlock().FontSize(fontSizePx);
|
||||
TextBlock().FontFamily(Media::FontFamily(fontArgs->FontFace()));
|
||||
|
||||
const auto canvasActualWidth = Canvas().ActualWidth();
|
||||
const auto widthToTerminalEnd = canvasActualWidth - ::base::ClampedNumeric<double>(clientCursorPos.X);
|
||||
// Make sure that we're setting the MaxWidth to a positive number - a
|
||||
// negative number here will crash us in mysterious ways with a useless
|
||||
// stack trace
|
||||
const auto newMaxWidth = std::max<double>(0.0, widthToTerminalEnd);
|
||||
TextBlock().MaxWidth(newMaxWidth);
|
||||
const auto widthToTerminalEnd = Canvas().ActualWidth() - ::base::ClampedNumeric<double>(clientCursorPos.X);
|
||||
TextBlock().MaxWidth(widthToTerminalEnd);
|
||||
|
||||
// Set the text block bounds
|
||||
const auto yOffset = ::base::ClampedNumeric<float>(TextBlock().ActualHeight()) - fontHeight;
|
||||
|
||||
@@ -69,37 +69,13 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
|
||||
_cursorTimer{},
|
||||
_lastMouseClickTimestamp{},
|
||||
_lastMouseClickPos{},
|
||||
_selectionNeedsToBeCopied{ false },
|
||||
_searchBox{ nullptr }
|
||||
_searchBox{ nullptr },
|
||||
_focusRaisedClickPos{ std::nullopt },
|
||||
_clickDrag{ false }
|
||||
{
|
||||
_EnsureStaticInitialization();
|
||||
InitializeComponent();
|
||||
|
||||
_terminal = std::make_unique<::Microsoft::Terminal::Core::Terminal>();
|
||||
|
||||
auto pfnTitleChanged = std::bind(&TermControl::_TerminalTitleChanged, this, std::placeholders::_1);
|
||||
_terminal->SetTitleChangedCallback(pfnTitleChanged);
|
||||
|
||||
auto pfnBackgroundColorChanged = std::bind(&TermControl::_BackgroundColorChanged, this, std::placeholders::_1);
|
||||
_terminal->SetBackgroundCallback(pfnBackgroundColorChanged);
|
||||
|
||||
auto pfnScrollPositionChanged = std::bind(&TermControl::_TerminalScrollPositionChanged, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3);
|
||||
_terminal->SetScrollPositionChangedCallback(pfnScrollPositionChanged);
|
||||
|
||||
// This event is explicitly revoked in the destructor: does not need weak_ref
|
||||
auto onReceiveOutputFn = [this](const hstring str) {
|
||||
_terminal->Write(str);
|
||||
};
|
||||
_connectionOutputEventToken = _connection.TerminalOutput(onReceiveOutputFn);
|
||||
|
||||
auto inputFn = std::bind(&TermControl::_SendInputToConnection, this, std::placeholders::_1);
|
||||
_terminal->SetWriteInputCallback(inputFn);
|
||||
|
||||
// Subscribe to the connection's disconnected event and call our connection closed handlers.
|
||||
_connectionStateChangedRevoker = _connection.StateChanged(winrt::auto_revoke, [this](auto&& /*s*/, auto&& /*v*/) {
|
||||
_ConnectionStateChangedHandlers(*this, nullptr);
|
||||
});
|
||||
|
||||
// Initialize the terminal only once the swapchainpanel is loaded - that
|
||||
// way, we'll be able to query the real pixel size it got on layout
|
||||
_layoutUpdatedRevoker = SwapChainPanel().LayoutUpdated(winrt::auto_revoke, [this](auto /*s*/, auto /*e*/) {
|
||||
@@ -115,9 +91,10 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
|
||||
}
|
||||
});
|
||||
|
||||
static constexpr auto AutoScrollUpdateInterval = std::chrono::microseconds(static_cast<int>(1.0 / 30.0 * 1000000));
|
||||
_autoScrollTimer.Interval(AutoScrollUpdateInterval);
|
||||
_autoScrollTimer.Tick({ this, &TermControl::_UpdateAutoScroll });
|
||||
// Subscribe to the connection's disconnected event and call our connection closed handlers.
|
||||
_connectionStateChangedRevoker = _connection.StateChanged(winrt::auto_revoke, [this](auto&& /*s*/, auto&& /*v*/) {
|
||||
_ConnectionStateChangedHandlers(*this, nullptr);
|
||||
});
|
||||
|
||||
_ApplyUISettings();
|
||||
}
|
||||
@@ -150,7 +127,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
|
||||
// - <none>
|
||||
void TermControl::_Search(const winrt::hstring& text, const bool goForward, const bool caseSensitive)
|
||||
{
|
||||
if (text.size() == 0 || _closing)
|
||||
if (text.size() == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -207,11 +184,6 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
|
||||
// If 'weakThis' is locked, then we can safely work with 'this'
|
||||
if (auto control{ weakThis.get() })
|
||||
{
|
||||
if (_closing)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Update our control settings
|
||||
_ApplyUISettings();
|
||||
|
||||
@@ -281,7 +253,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
|
||||
// Apply settings for scrollbar
|
||||
if (_settings.ScrollState() == ScrollbarState::Hidden)
|
||||
{
|
||||
// In the scenario where the user has turned off the OS setting to automatically hide scrollbars, the
|
||||
// In the scenario where the user has turned off the OS setting to automatically hide scollbars, the
|
||||
// Terminal scrollbar would still be visible; so, we need to set the control's visibility accordingly to
|
||||
// achieve the intended effect.
|
||||
ScrollBar().IndicatorMode(Controls::Primitives::ScrollingIndicatorMode::None);
|
||||
@@ -441,7 +413,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
|
||||
Windows::UI::Xaml::Automation::Peers::AutomationPeer TermControl::OnCreateAutomationPeer()
|
||||
try
|
||||
{
|
||||
if (_initializedTerminal && !_closing) // only set up the automation peer if we're ready to go live
|
||||
if (GetUiaData())
|
||||
{
|
||||
// create a custom automation peer with this code pattern:
|
||||
// (https://docs.microsoft.com/en-us/windows/uwp/design/accessibility/custom-automation-peers)
|
||||
@@ -479,14 +451,11 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
|
||||
return _connection.State();
|
||||
}
|
||||
|
||||
winrt::fire_and_forget TermControl::RenderEngineSwapChainChanged()
|
||||
winrt::fire_and_forget TermControl::SwapChainChanged()
|
||||
{
|
||||
{ // lock scope
|
||||
auto terminalLock = _terminal->LockForReading();
|
||||
if (!_initializedTerminal)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (!_initializedTerminal)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
auto chain = _renderEngine->GetSwapChain();
|
||||
@@ -494,153 +463,186 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
|
||||
|
||||
co_await winrt::resume_foreground(Dispatcher());
|
||||
|
||||
// If 'weakThis' is locked, then we can safely work with 'this'
|
||||
if (auto control{ weakThis.get() })
|
||||
{
|
||||
auto terminalLock = _terminal->LockForWriting();
|
||||
|
||||
_AttachDxgiSwapChainToXaml(chain.Get());
|
||||
if (_terminal)
|
||||
{
|
||||
auto lock = _terminal->LockForWriting();
|
||||
auto nativePanel = SwapChainPanel().as<ISwapChainPanelNative>();
|
||||
nativePanel->SetSwapChain(chain.Get());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TermControl::_AttachDxgiSwapChainToXaml(IDXGISwapChain1* swapChain)
|
||||
winrt::fire_and_forget TermControl::_SwapChainRoutine()
|
||||
{
|
||||
auto nativePanel = SwapChainPanel().as<ISwapChainPanelNative>();
|
||||
nativePanel->SetSwapChain(swapChain);
|
||||
auto chain = _renderEngine->GetSwapChain();
|
||||
auto weakThis{ get_weak() };
|
||||
|
||||
co_await winrt::resume_foreground(Dispatcher());
|
||||
|
||||
if (auto control{ weakThis.get() })
|
||||
{
|
||||
if (_terminal)
|
||||
{
|
||||
auto lock = _terminal->LockForWriting();
|
||||
auto nativePanel = SwapChainPanel().as<ISwapChainPanelNative>();
|
||||
nativePanel->SetSwapChain(chain.Get());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool TermControl::_InitializeTerminal()
|
||||
{
|
||||
{ // scope for terminalLock
|
||||
auto terminalLock = _terminal->LockForWriting();
|
||||
if (_initializedTerminal)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_initializedTerminal)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
const auto windowWidth = SwapChainPanel().ActualWidth(); // Width() and Height() are NaN?
|
||||
const auto windowHeight = SwapChainPanel().ActualHeight();
|
||||
|
||||
const auto windowWidth = SwapChainPanel().ActualWidth(); // Width() and Height() are NaN?
|
||||
const auto windowHeight = SwapChainPanel().ActualHeight();
|
||||
if (windowWidth == 0 || windowHeight == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (windowWidth == 0 || windowHeight == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
_terminal = std::make_unique<::Microsoft::Terminal::Core::Terminal>();
|
||||
|
||||
// First create the render thread.
|
||||
// Then stash a local pointer to the render thread so we can initialize it and enable it
|
||||
// to paint itself *after* we hand off its ownership to the renderer.
|
||||
// We split up construction and initialization of the render thread object this way
|
||||
// because the renderer and render thread have circular references to each other.
|
||||
auto renderThread = std::make_unique<::Microsoft::Console::Render::RenderThread>();
|
||||
auto* const localPointerToThread = renderThread.get();
|
||||
// First create the render thread.
|
||||
// Then stash a local pointer to the render thread so we can initialize it and enable it
|
||||
// to paint itself *after* we hand off its ownership to the renderer.
|
||||
// We split up construction and initialization of the render thread object this way
|
||||
// because the renderer and render thread have circular references to each other.
|
||||
auto renderThread = std::make_unique<::Microsoft::Console::Render::RenderThread>();
|
||||
auto* const localPointerToThread = renderThread.get();
|
||||
|
||||
// Now create the renderer and initialize the render thread.
|
||||
_renderer = std::make_unique<::Microsoft::Console::Render::Renderer>(_terminal.get(), nullptr, 0, std::move(renderThread));
|
||||
::Microsoft::Console::Render::IRenderTarget& renderTarget = *_renderer;
|
||||
// Now create the renderer and initialize the render thread.
|
||||
_renderer = std::make_unique<::Microsoft::Console::Render::Renderer>(_terminal.get(), nullptr, 0, std::move(renderThread));
|
||||
::Microsoft::Console::Render::IRenderTarget& renderTarget = *_renderer;
|
||||
|
||||
THROW_IF_FAILED(localPointerToThread->Initialize(_renderer.get()));
|
||||
THROW_IF_FAILED(localPointerToThread->Initialize(_renderer.get()));
|
||||
|
||||
// Set up the DX Engine
|
||||
auto dxEngine = std::make_unique<::Microsoft::Console::Render::DxEngine>();
|
||||
_renderer->AddRenderEngine(dxEngine.get());
|
||||
// Set up the DX Engine
|
||||
auto dxEngine = std::make_unique<::Microsoft::Console::Render::DxEngine>();
|
||||
_renderer->AddRenderEngine(dxEngine.get());
|
||||
|
||||
// Initialize our font with the renderer
|
||||
// We don't have to care about DPI. We'll get a change message immediately if it's not 96
|
||||
// and react accordingly.
|
||||
_UpdateFont(true);
|
||||
// Initialize our font with the renderer
|
||||
// We don't have to care about DPI. We'll get a change message immediately if it's not 96
|
||||
// and react accordingly.
|
||||
_UpdateFont(true);
|
||||
|
||||
const COORD windowSize{ static_cast<short>(windowWidth), static_cast<short>(windowHeight) };
|
||||
const COORD windowSize{ static_cast<short>(windowWidth), static_cast<short>(windowHeight) };
|
||||
|
||||
// Fist set up the dx engine with the window size in pixels.
|
||||
// Then, using the font, get the number of characters that can fit.
|
||||
// Resize our terminal connection to match that size, and initialize the terminal with that size.
|
||||
const auto viewInPixels = Viewport::FromDimensions({ 0, 0 }, windowSize);
|
||||
THROW_IF_FAILED(dxEngine->SetWindowSize({ viewInPixels.Width(), viewInPixels.Height() }));
|
||||
// Fist set up the dx engine with the window size in pixels.
|
||||
// Then, using the font, get the number of characters that can fit.
|
||||
// Resize our terminal connection to match that size, and initialize the terminal with that size.
|
||||
const auto viewInPixels = Viewport::FromDimensions({ 0, 0 }, windowSize);
|
||||
THROW_IF_FAILED(dxEngine->SetWindowSize({ viewInPixels.Width(), viewInPixels.Height() }));
|
||||
|
||||
// Update DxEngine's SelectionBackground
|
||||
dxEngine->SetSelectionBackground(_settings.SelectionBackground());
|
||||
// Update DxEngine's SelectionBackground
|
||||
dxEngine->SetSelectionBackground(_settings.SelectionBackground());
|
||||
|
||||
const auto vp = dxEngine->GetViewportInCharacters(viewInPixels);
|
||||
const auto width = vp.Width();
|
||||
const auto height = vp.Height();
|
||||
_connection.Resize(height, width);
|
||||
const auto vp = dxEngine->GetViewportInCharacters(viewInPixels);
|
||||
const auto width = vp.Width();
|
||||
const auto height = vp.Height();
|
||||
_connection.Resize(height, width);
|
||||
|
||||
// Override the default width and height to match the size of the swapChainPanel
|
||||
_settings.InitialCols(width);
|
||||
_settings.InitialRows(height);
|
||||
// Override the default width and height to match the size of the swapChainPanel
|
||||
_settings.InitialCols(width);
|
||||
_settings.InitialRows(height);
|
||||
|
||||
_terminal->CreateFromSettings(_settings, renderTarget);
|
||||
_terminal->CreateFromSettings(_settings, renderTarget);
|
||||
|
||||
// TODO:GH#3927 - Make it possible to hot-reload this setting. Right
|
||||
// here, the setting will only be used when the Terminal is initialized.
|
||||
dxEngine->SetRetroTerminalEffects(_settings.RetroTerminalEffect());
|
||||
// Tell the DX Engine to notify us when the swap chain changes.
|
||||
dxEngine->SetCallback(std::bind(&TermControl::SwapChainChanged, this));
|
||||
|
||||
// TODO:GH#3927 - hot-reload this one too
|
||||
// Update DxEngine's AntialiasingMode
|
||||
switch (_settings.AntialiasingMode())
|
||||
{
|
||||
case TextAntialiasingMode::Cleartype:
|
||||
dxEngine->SetAntialiasingMode(D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE);
|
||||
break;
|
||||
case TextAntialiasingMode::Aliased:
|
||||
dxEngine->SetAntialiasingMode(D2D1_TEXT_ANTIALIAS_MODE_ALIASED);
|
||||
break;
|
||||
case TextAntialiasingMode::Grayscale:
|
||||
default:
|
||||
dxEngine->SetAntialiasingMode(D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE);
|
||||
break;
|
||||
}
|
||||
// TODO:GH#3927 - Make it possible to hot-reload this setting. Right
|
||||
// here, the setting will only be used when the Terminal is initialized.
|
||||
dxEngine->SetRetroTerminalEffects(_settings.RetroTerminalEffect());
|
||||
|
||||
THROW_IF_FAILED(dxEngine->Enable());
|
||||
_renderEngine = std::move(dxEngine);
|
||||
// TODO:GH#3927 - hot-reload this one too
|
||||
// Update DxEngine's AntialiasingMode
|
||||
switch (_settings.AntialiasingMode())
|
||||
{
|
||||
case TextAntialiasingMode::Cleartype:
|
||||
dxEngine->SetAntialiasingMode(D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE);
|
||||
break;
|
||||
case TextAntialiasingMode::Aliased:
|
||||
dxEngine->SetAntialiasingMode(D2D1_TEXT_ANTIALIAS_MODE_ALIASED);
|
||||
break;
|
||||
case TextAntialiasingMode::Grayscale:
|
||||
default:
|
||||
dxEngine->SetAntialiasingMode(D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE);
|
||||
break;
|
||||
}
|
||||
|
||||
_AttachDxgiSwapChainToXaml(_renderEngine->GetSwapChain().Get());
|
||||
THROW_IF_FAILED(dxEngine->Enable());
|
||||
_renderEngine = std::move(dxEngine);
|
||||
|
||||
// Tell the DX Engine to notify us when the swap chain changes.
|
||||
// We do this after we initially set the swapchain so as to avoid unnecessary callbacks (and locking problems)
|
||||
_renderEngine->SetCallback(std::bind(&TermControl::RenderEngineSwapChainChanged, this));
|
||||
// This event is explicitly revoked in the destructor: does not need weak_ref
|
||||
auto onReceiveOutputFn = [this](const hstring str) {
|
||||
_terminal->Write(str);
|
||||
};
|
||||
_connectionOutputEventToken = _connection.TerminalOutput(onReceiveOutputFn);
|
||||
|
||||
auto bottom = _terminal->GetViewport().BottomExclusive();
|
||||
auto bufferHeight = bottom;
|
||||
auto inputFn = std::bind(&TermControl::_SendInputToConnection, this, std::placeholders::_1);
|
||||
_terminal->SetWriteInputCallback(inputFn);
|
||||
|
||||
ScrollBar().Maximum(bufferHeight - bufferHeight);
|
||||
ScrollBar().Minimum(0);
|
||||
ScrollBar().Value(0);
|
||||
ScrollBar().ViewportSize(bufferHeight);
|
||||
_SwapChainRoutine();
|
||||
|
||||
localPointerToThread->EnablePainting();
|
||||
// Set up the height of the ScrollViewer and the grid we're using to fake our scrolling height
|
||||
auto bottom = _terminal->GetViewport().BottomExclusive();
|
||||
auto bufferHeight = bottom;
|
||||
|
||||
// Set up blinking cursor
|
||||
int blinkTime = GetCaretBlinkTime();
|
||||
if (blinkTime != INFINITE)
|
||||
{
|
||||
// Create a timer
|
||||
DispatcherTimer cursorTimer;
|
||||
cursorTimer.Interval(std::chrono::milliseconds(blinkTime));
|
||||
cursorTimer.Tick({ get_weak(), &TermControl::_CursorTimerTick });
|
||||
cursorTimer.Start();
|
||||
_cursorTimer.emplace(std::move(cursorTimer));
|
||||
}
|
||||
else
|
||||
{
|
||||
// The user has disabled cursor blinking
|
||||
_cursorTimer = std::nullopt;
|
||||
}
|
||||
ScrollBar().Maximum(bufferHeight - bufferHeight);
|
||||
ScrollBar().Minimum(0);
|
||||
ScrollBar().Value(0);
|
||||
ScrollBar().ViewportSize(bufferHeight);
|
||||
|
||||
// import value from WinUser (convert from milli-seconds to micro-seconds)
|
||||
_multiClickTimer = GetDoubleClickTime() * 1000;
|
||||
localPointerToThread->EnablePainting();
|
||||
|
||||
// Focus the control here. If we do it during control initialization, then
|
||||
// focus won't actually get passed to us. I believe this is because
|
||||
// we're not technically a part of the UI tree yet, so focusing us
|
||||
// becomes a no-op.
|
||||
this->Focus(FocusState::Programmatic);
|
||||
auto pfnTitleChanged = std::bind(&TermControl::_TerminalTitleChanged, this, std::placeholders::_1);
|
||||
_terminal->SetTitleChangedCallback(pfnTitleChanged);
|
||||
|
||||
_connection.Start();
|
||||
_initializedTerminal = true;
|
||||
} // scope for TerminalLock
|
||||
// call this event dispatcher outside of lock
|
||||
auto pfnBackgroundColorChanged = std::bind(&TermControl::_BackgroundColorChanged, this, std::placeholders::_1);
|
||||
_terminal->SetBackgroundCallback(pfnBackgroundColorChanged);
|
||||
|
||||
auto pfnScrollPositionChanged = std::bind(&TermControl::_TerminalScrollPositionChanged, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3);
|
||||
_terminal->SetScrollPositionChangedCallback(pfnScrollPositionChanged);
|
||||
|
||||
static constexpr auto AutoScrollUpdateInterval = std::chrono::microseconds(static_cast<int>(1.0 / 30.0 * 1000000));
|
||||
_autoScrollTimer.Interval(AutoScrollUpdateInterval);
|
||||
_autoScrollTimer.Tick({ get_weak(), &TermControl::_UpdateAutoScroll });
|
||||
|
||||
// Set up blinking cursor
|
||||
int blinkTime = GetCaretBlinkTime();
|
||||
if (blinkTime != INFINITE)
|
||||
{
|
||||
// Create a timer
|
||||
_cursorTimer = std::make_optional(DispatcherTimer());
|
||||
_cursorTimer.value().Interval(std::chrono::milliseconds(blinkTime));
|
||||
_cursorTimer.value().Tick({ get_weak(), &TermControl::_BlinkCursor });
|
||||
_cursorTimer.value().Start();
|
||||
}
|
||||
else
|
||||
{
|
||||
// The user has disabled cursor blinking
|
||||
_cursorTimer = std::nullopt;
|
||||
}
|
||||
|
||||
// import value from WinUser (convert from milli-seconds to micro-seconds)
|
||||
_multiClickTimer = GetDoubleClickTime() * 1000;
|
||||
|
||||
// Focus the control here. If we do it during control initialization, then
|
||||
// focus won't actually get passed to us. I believe this is because
|
||||
// we're not technically a part of the UI tree yet, so focusing us
|
||||
// becomes a no-op.
|
||||
this->Focus(FocusState::Programmatic);
|
||||
|
||||
_connection.Start();
|
||||
_initializedTerminal = true;
|
||||
_InitializedHandlers(*this, nullptr);
|
||||
return true;
|
||||
}
|
||||
@@ -877,10 +879,6 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
|
||||
// - point: the PointerPoint object representing a mouse event from our XAML input handler
|
||||
bool TermControl::_CanSendVTMouseInput()
|
||||
{
|
||||
if (!_terminal)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// If the user is holding down Shift, suppress mouse events
|
||||
// TODO GH#4875: disable/customize this functionality
|
||||
const auto modifiers = _GetPressedModifierKeys();
|
||||
@@ -899,11 +897,6 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
|
||||
void TermControl::_PointerPressedHandler(Windows::Foundation::IInspectable const& sender,
|
||||
Input::PointerRoutedEventArgs const& args)
|
||||
{
|
||||
if (_closing)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_CapturePointer(sender, args);
|
||||
|
||||
const auto ptr = args.Pointer();
|
||||
@@ -918,6 +911,9 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
|
||||
if (!_focused)
|
||||
{
|
||||
Focus(FocusState::Pointer);
|
||||
// Save the click position that brought this control into focus
|
||||
// in case the user wants to perform a click-drag selection.
|
||||
_focusRaisedClickPos = point.Position();
|
||||
}
|
||||
|
||||
if (ptr.PointerDeviceType() == Windows::Devices::Input::PointerDeviceType::Mouse || ptr.PointerDeviceType() == Windows::Devices::Input::PointerDeviceType::Pen)
|
||||
@@ -937,6 +933,13 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
|
||||
|
||||
if (point.Properties().IsLeftButtonPressed())
|
||||
{
|
||||
// A single left click from out of focus should only focus.
|
||||
if (_focusRaisedClickPos)
|
||||
{
|
||||
args.Handled(true);
|
||||
return;
|
||||
}
|
||||
|
||||
const auto cursorPosition = point.Position();
|
||||
const auto terminalPosition = _GetTerminalPosition(cursorPosition);
|
||||
|
||||
@@ -953,26 +956,20 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
|
||||
if (multiClickMapper == 3)
|
||||
{
|
||||
_terminal->MultiClickSelection(terminalPosition, ::Terminal::SelectionExpansionMode::Line);
|
||||
_selectionNeedsToBeCopied = true;
|
||||
}
|
||||
else if (multiClickMapper == 2)
|
||||
{
|
||||
_terminal->MultiClickSelection(terminalPosition, ::Terminal::SelectionExpansionMode::Word);
|
||||
_selectionNeedsToBeCopied = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (shiftEnabled && _terminal->IsSelectionActive())
|
||||
{
|
||||
_terminal->SetSelectionEnd(terminalPosition, ::Terminal::SelectionExpansionMode::Cell);
|
||||
_selectionNeedsToBeCopied = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// A single click down resets the selection and begins a new one.
|
||||
_terminal->ClearSelection();
|
||||
_singleClickTouchdownPos = cursorPosition;
|
||||
_selectionNeedsToBeCopied = false; // there's no selection, so there's nothing to update
|
||||
_terminal->SetSelectionAnchor(terminalPosition);
|
||||
}
|
||||
|
||||
_lastMouseClickTimestamp = point.Timestamp();
|
||||
@@ -983,7 +980,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
|
||||
else if (point.Properties().IsRightButtonPressed())
|
||||
{
|
||||
// CopyOnSelect right click always pastes
|
||||
if (_settings.CopyOnSelect() || !_terminal->IsSelectionActive())
|
||||
if (_terminal->IsCopyOnSelectActive() || !_terminal->IsSelectionActive())
|
||||
{
|
||||
PasteTextFromClipboard();
|
||||
}
|
||||
@@ -1011,11 +1008,6 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
|
||||
void TermControl::_PointerMovedHandler(Windows::Foundation::IInspectable const& /*sender*/,
|
||||
Input::PointerRoutedEventArgs const& args)
|
||||
{
|
||||
if (_closing)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const auto ptr = args.Pointer();
|
||||
const auto point = args.GetCurrentPoint(*this);
|
||||
|
||||
@@ -1036,22 +1028,16 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
|
||||
|
||||
if (point.Properties().IsLeftButtonPressed())
|
||||
{
|
||||
const auto cursorPosition = point.Position();
|
||||
_clickDrag = true;
|
||||
|
||||
if (_singleClickTouchdownPos)
|
||||
// PointerPressedHandler doesn't set the SelectionAnchor when the click was
|
||||
// from out of focus, so PointerMoved has to set it.
|
||||
if (_focusRaisedClickPos)
|
||||
{
|
||||
// Figure out if the user's moved a quarter of a cell's smaller axis away from the clickdown point
|
||||
auto& touchdownPoint{ *_singleClickTouchdownPos };
|
||||
auto distance{ std::sqrtf(std::powf(cursorPosition.X - touchdownPoint.X, 2) + std::powf(cursorPosition.Y - touchdownPoint.Y, 2)) };
|
||||
const auto fontSize{ _actualFont.GetSize() };
|
||||
if (distance >= (std::min(fontSize.X, fontSize.Y) / 4.f))
|
||||
{
|
||||
_terminal->SetSelectionAnchor(_GetTerminalPosition(touchdownPoint));
|
||||
// stop tracking the touchdown point
|
||||
_singleClickTouchdownPos = std::nullopt;
|
||||
}
|
||||
_terminal->SetSelectionAnchor(_GetTerminalPosition(*_focusRaisedClickPos));
|
||||
}
|
||||
|
||||
const auto cursorPosition = point.Position();
|
||||
_SetEndSelectionPointAtCursor(cursorPosition);
|
||||
|
||||
const double cursorBelowBottomDist = cursorPosition.Y - SwapChainPanel().Margin().Top - SwapChainPanel().ActualHeight();
|
||||
@@ -1119,11 +1105,6 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
|
||||
void TermControl::_PointerReleasedHandler(Windows::Foundation::IInspectable const& sender,
|
||||
Input::PointerRoutedEventArgs const& args)
|
||||
{
|
||||
if (_closing)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const auto ptr = args.Pointer();
|
||||
const auto point = args.GetCurrentPoint(*this);
|
||||
|
||||
@@ -1140,14 +1121,17 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
|
||||
|
||||
// Only a left click release when copy on select is active should perform a copy.
|
||||
// Right clicks and middle clicks should not need to do anything when released.
|
||||
if (_settings.CopyOnSelect() && point.Properties().PointerUpdateKind() == Windows::UI::Input::PointerUpdateKind::LeftButtonReleased)
|
||||
if (_terminal->IsCopyOnSelectActive() && point.Properties().PointerUpdateKind() == Windows::UI::Input::PointerUpdateKind::LeftButtonReleased)
|
||||
{
|
||||
const auto modifiers = static_cast<uint32_t>(args.KeyModifiers());
|
||||
// static_cast to a uint32_t because we can't use the WI_IsFlagSet
|
||||
// macro directly with a VirtualKeyModifiers
|
||||
const auto shiftEnabled = WI_IsFlagSet(modifiers, static_cast<uint32_t>(VirtualKeyModifiers::Shift));
|
||||
|
||||
if (_selectionNeedsToBeCopied)
|
||||
// In a Copy on Select scenario,
|
||||
// All left click drags should copy,
|
||||
// All left clicks on a focused control should copy if a selection is active.
|
||||
if (_clickDrag || !_focusRaisedClickPos)
|
||||
{
|
||||
CopySelectionToClipboard(shiftEnabled);
|
||||
}
|
||||
@@ -1158,7 +1142,8 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
|
||||
_touchAnchor = std::nullopt;
|
||||
}
|
||||
|
||||
_singleClickTouchdownPos = std::nullopt;
|
||||
_focusRaisedClickPos = std::nullopt;
|
||||
_clickDrag = false;
|
||||
|
||||
_TryStopAutoScroll(ptr.PointerId());
|
||||
|
||||
@@ -1174,11 +1159,6 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
|
||||
void TermControl::_MouseWheelHandler(Windows::Foundation::IInspectable const& /*sender*/,
|
||||
Input::PointerRoutedEventArgs const& args)
|
||||
{
|
||||
if (_closing)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const auto point = args.GetCurrentPoint(*this);
|
||||
|
||||
if (_CanSendVTMouseInput())
|
||||
@@ -1309,7 +1289,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
|
||||
void TermControl::_ScrollbarChangeHandler(Windows::Foundation::IInspectable const& /*sender*/,
|
||||
Controls::Primitives::RangeBaseValueChangedEventArgs const& args)
|
||||
{
|
||||
if (_isTerminalInitiatedScroll || _closing)
|
||||
if (_isTerminalInitiatedScroll)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -1494,7 +1474,6 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_focused = false;
|
||||
|
||||
if (_uiaEngine.get())
|
||||
@@ -1566,6 +1545,8 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
|
||||
// concerned with initialization process. Value forwarded to event handler.
|
||||
void TermControl::_UpdateFont(const bool initialUpdate)
|
||||
{
|
||||
auto lock = _terminal->LockForWriting();
|
||||
|
||||
const int newDpi = static_cast<int>(static_cast<double>(USER_DEFAULT_SCREEN_DPI) * SwapChainPanel().CompositionScaleX());
|
||||
|
||||
// TODO: MSFT:20895307 If the font doesn't exist, this doesn't
|
||||
@@ -1592,12 +1573,11 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
|
||||
|
||||
// Refresh our font with the renderer
|
||||
_UpdateFont();
|
||||
|
||||
auto lock = _terminal->LockForWriting();
|
||||
// Resize the terminal's BUFFER to match the new font size. This does
|
||||
// NOT change the size of the window, because that can lead to more
|
||||
// problems (like what happens when you change the font size while the
|
||||
// window is maximized?)
|
||||
auto lock = _terminal->LockForWriting();
|
||||
_DoResize(SwapChainPanel().ActualWidth(), SwapChainPanel().ActualHeight());
|
||||
}
|
||||
CATCH_LOG();
|
||||
@@ -1611,7 +1591,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
|
||||
void TermControl::_SwapChainSizeChanged(winrt::Windows::Foundation::IInspectable const& /*sender*/,
|
||||
SizeChangedEventArgs const& e)
|
||||
{
|
||||
if (!_initializedTerminal || _closing)
|
||||
if (!_initializedTerminal)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -1642,8 +1622,8 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
|
||||
// Arguments:
|
||||
// - sender: not used
|
||||
// - e: not used
|
||||
void TermControl::_CursorTimerTick(Windows::Foundation::IInspectable const& /* sender */,
|
||||
Windows::Foundation::IInspectable const& /* e */)
|
||||
void TermControl::_BlinkCursor(Windows::Foundation::IInspectable const& /* sender */,
|
||||
Windows::Foundation::IInspectable const& /* e */)
|
||||
{
|
||||
if ((_closing) || (!_terminal->IsCursorBlinkingAllowed() && _terminal->IsCursorVisible()))
|
||||
{
|
||||
@@ -1669,7 +1649,6 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
|
||||
// save location (for rendering) + render
|
||||
_terminal->SetSelectionEnd(terminalPosition);
|
||||
_renderer->TriggerSelection();
|
||||
_selectionNeedsToBeCopied = true;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
@@ -1795,7 +1774,10 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
|
||||
|
||||
hstring TermControl::Title()
|
||||
{
|
||||
hstring hstr{ _terminal->GetConsoleTitle() };
|
||||
if (!_initializedTerminal)
|
||||
return L"";
|
||||
|
||||
hstring hstr(_terminal->GetConsoleTitle());
|
||||
return hstr;
|
||||
}
|
||||
|
||||
@@ -1812,20 +1794,11 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
|
||||
// - collapseText: collapse all of the text to one line
|
||||
bool TermControl::CopySelectionToClipboard(bool collapseText)
|
||||
{
|
||||
if (_closing)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// no selection --> nothing to copy
|
||||
if (!_terminal->IsSelectionActive())
|
||||
if (_terminal == nullptr || !_terminal->IsSelectionActive())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Mark the current selection as copied
|
||||
_selectionNeedsToBeCopied = false;
|
||||
|
||||
// extract text from buffer
|
||||
const auto bufferData = _terminal->RetrieveSelectedTextFromBuffer(collapseText);
|
||||
|
||||
@@ -1849,7 +1822,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
|
||||
_actualFont.GetFaceName(),
|
||||
_settings.DefaultBackground());
|
||||
|
||||
if (!_settings.CopyOnSelect())
|
||||
if (!_terminal->IsCopyOnSelectActive())
|
||||
{
|
||||
_terminal->ClearSelection();
|
||||
_renderer->TriggerSelection();
|
||||
@@ -1885,7 +1858,6 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
|
||||
_connectionStateChangedRevoker.revoke();
|
||||
|
||||
TSFInputControl().Close(); // Disconnect the TSF input control so it doesn't receive EditContext events.
|
||||
_autoScrollTimer.Stop();
|
||||
|
||||
if (auto localConnection{ std::exchange(_connection, nullptr) })
|
||||
{
|
||||
@@ -1903,8 +1875,11 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
|
||||
// renderEngine is destroyed
|
||||
}
|
||||
|
||||
// we don't destroy _terminal here; it now has the same lifetime as the
|
||||
// control.
|
||||
if (auto localTerminal{ std::exchange(_terminal, nullptr) })
|
||||
{
|
||||
_initializedTerminal = false;
|
||||
// terminal is destroyed.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2218,11 +2193,6 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
|
||||
// - <none>
|
||||
void TermControl::_CompositionCompleted(winrt::hstring text)
|
||||
{
|
||||
if (_closing)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_connection.WriteInput(text);
|
||||
}
|
||||
|
||||
@@ -2235,14 +2205,11 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
|
||||
// - <none>
|
||||
void TermControl::_CurrentCursorPositionHandler(const IInspectable& /*sender*/, const CursorPositionEventArgs& eventArgs)
|
||||
{
|
||||
auto lock = _terminal->LockForReading();
|
||||
if (!_initializedTerminal)
|
||||
// If we haven't initialized yet, just quick return.
|
||||
if (!_terminal)
|
||||
{
|
||||
// fake it
|
||||
eventArgs.CurrentPosition({ 0, 0 });
|
||||
return;
|
||||
}
|
||||
|
||||
const COORD cursorPos = _terminal->GetCursorPosition();
|
||||
Windows::Foundation::Point p = { gsl::narrow_cast<float>(cursorPos.X), gsl::narrow_cast<float>(cursorPos.Y) };
|
||||
eventArgs.CurrentPosition(p);
|
||||
@@ -2312,14 +2279,8 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
|
||||
// - e: The DragEventArgs from the Drop event
|
||||
// Return Value:
|
||||
// - <none>
|
||||
winrt::fire_and_forget TermControl::_DragDropHandler(Windows::Foundation::IInspectable const& /*sender*/,
|
||||
DragEventArgs const e)
|
||||
winrt::fire_and_forget TermControl::_DoDragDrop(DragEventArgs const e)
|
||||
{
|
||||
if (_closing)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (e.DataView().Contains(StandardDataFormats::StorageItems()))
|
||||
{
|
||||
auto items = co_await e.DataView().GetStorageItemsAsync();
|
||||
@@ -2354,6 +2315,22 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
|
||||
}
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Synchronous handler for the "Drop" event. We'll dispatch the async
|
||||
// _DoDragDrop method to handle this, because getting information about
|
||||
// the file that was potentially dropped onto us must be done off the UI
|
||||
// thread.
|
||||
// Arguments:
|
||||
// - e: The DragEventArgs from the Drop event
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void TermControl::_DragDropHandler(Windows::Foundation::IInspectable const& /*sender*/,
|
||||
DragEventArgs const& e)
|
||||
{
|
||||
// Dispatch an async method to handle the drop event.
|
||||
_DoDragDrop(e);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Handle the DragOver event. We'll signal that the drag operation we
|
||||
// support is the "copy" operation, and we'll also customize the
|
||||
@@ -2367,11 +2344,6 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
|
||||
void TermControl::_DragOverHandler(Windows::Foundation::IInspectable const& /*sender*/,
|
||||
DragEventArgs const& e)
|
||||
{
|
||||
if (_closing)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!e.DataView().Contains(StandardDataFormats::StorageItems()))
|
||||
{
|
||||
// We can't do anything for non-storageitems right now.
|
||||
@@ -2387,7 +2359,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
|
||||
e.DragUIOverride().IsCaptionVisible(true);
|
||||
// Sets if the dragged content is visible
|
||||
e.DragUIOverride().IsContentVisible(false);
|
||||
// Sets if the glyph is visible
|
||||
// Sets if the glyph is visibile
|
||||
e.DragUIOverride().IsGlyphVisible(false);
|
||||
}
|
||||
|
||||
|
||||
@@ -77,8 +77,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
|
||||
void AdjustFontSize(int fontSizeDelta);
|
||||
void ResetFontSize();
|
||||
|
||||
winrt::fire_and_forget RenderEngineSwapChainChanged();
|
||||
void _AttachDxgiSwapChainToXaml(IDXGISwapChain1* swapChain);
|
||||
winrt::fire_and_forget SwapChainChanged();
|
||||
|
||||
void CreateSearchBoxControl();
|
||||
|
||||
@@ -156,15 +155,12 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
|
||||
// imported from WinUser
|
||||
// Used for PointerPoint.Timestamp Property (https://docs.microsoft.com/en-us/uwp/api/windows.ui.input.pointerpoint.timestamp#Windows_UI_Input_PointerPoint_Timestamp)
|
||||
Timestamp _multiClickTimer;
|
||||
unsigned int _multiClickCounter;
|
||||
Timestamp _lastMouseClickTimestamp;
|
||||
unsigned int _multiClickCounter;
|
||||
std::optional<winrt::Windows::Foundation::Point> _lastMouseClickPos;
|
||||
std::optional<winrt::Windows::Foundation::Point> _singleClickTouchdownPos;
|
||||
// This field tracks whether the selection has changed meaningfully
|
||||
// since it was last copied. It's generally used to prevent copyOnSelect
|
||||
// from firing when the pointer _just happens_ to be released over the
|
||||
// terminal.
|
||||
bool _selectionNeedsToBeCopied;
|
||||
|
||||
std::optional<winrt::Windows::Foundation::Point> _focusRaisedClickPos;
|
||||
bool _clickDrag;
|
||||
|
||||
winrt::Windows::UI::Xaml::Controls::SwapChainPanel::LayoutUpdated_revoker _layoutUpdatedRevoker;
|
||||
|
||||
@@ -184,13 +180,15 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
|
||||
void _ScrollbarChangeHandler(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::Controls::Primitives::RangeBaseValueChangedEventArgs const& e);
|
||||
void _GotFocusHandler(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::RoutedEventArgs const& e);
|
||||
void _LostFocusHandler(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::RoutedEventArgs const& e);
|
||||
winrt::fire_and_forget _DragDropHandler(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::DragEventArgs const e);
|
||||
void _DragDropHandler(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::DragEventArgs const& e);
|
||||
void _DragOverHandler(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::DragEventArgs const& e);
|
||||
winrt::fire_and_forget _DoDragDrop(Windows::UI::Xaml::DragEventArgs const e);
|
||||
|
||||
void _CursorTimerTick(Windows::Foundation::IInspectable const& sender, Windows::Foundation::IInspectable const& e);
|
||||
void _BlinkCursor(Windows::Foundation::IInspectable const& sender, Windows::Foundation::IInspectable const& e);
|
||||
void _SetEndSelectionPointAtCursor(Windows::Foundation::Point const& cursorPosition);
|
||||
void _SendInputToConnection(const std::wstring& wstr);
|
||||
void _SendPastedTextToConnection(const std::wstring& wstr);
|
||||
winrt::fire_and_forget _SwapChainRoutine();
|
||||
void _SwapChainSizeChanged(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::SizeChangedEventArgs const& e);
|
||||
void _SwapChainScaleChanged(Windows::UI::Xaml::Controls::SwapChainPanel const& sender, Windows::Foundation::IInspectable const& args);
|
||||
void _DoResize(const double newWidth, const double newHeight);
|
||||
|
||||
@@ -85,7 +85,7 @@
|
||||
<None Include="TerminalControl.def" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PRIResource Include="Resources\*\Resources.resw" />
|
||||
<PRIResource Include="Resources/Resources.language-en.resw" />
|
||||
</ItemGroup>
|
||||
<!-- ========================= Project References ======================== -->
|
||||
<ItemGroup>
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
<Natvis Include="$(SolutionDir)tools\ConsoleTypes.natvis" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PRIResource Include="Resources\*\Resources.resw">
|
||||
<PRIResource Include="Resources/Resources.language-en.resw">
|
||||
<Filter>Resources</Filter>
|
||||
</PRIResource>
|
||||
</ItemGroup>
|
||||
|
||||
@@ -45,7 +45,9 @@ Terminal::Terminal() :
|
||||
_scrollOffset{ 0 },
|
||||
_snapOnInput{ true },
|
||||
_blockSelection{ false },
|
||||
_selection{ std::nullopt }
|
||||
_selection{ std::nullopt },
|
||||
_allowSingleCharSelection{ true },
|
||||
_copyOnSelect{ false }
|
||||
{
|
||||
auto dispatch = std::make_unique<TerminalDispatch>(*this);
|
||||
auto engine = std::make_unique<OutputStateMachineEngine>(std::move(dispatch));
|
||||
@@ -143,6 +145,8 @@ void Terminal::UpdateSettings(winrt::Microsoft::Terminal::Settings::ICoreSetting
|
||||
|
||||
_wordDelimiters = settings.WordDelimiters();
|
||||
|
||||
_copyOnSelect = settings.CopyOnSelect();
|
||||
|
||||
_suppressApplicationTitle = settings.SuppressApplicationTitle();
|
||||
|
||||
_startingTitle = settings.StartingTitle();
|
||||
@@ -207,7 +211,7 @@ void Terminal::UpdateSettings(winrt::Microsoft::Terminal::Settings::ICoreSetting
|
||||
// requires a bit of trickiness to remain consistent with conpty's
|
||||
// buffer (as seen below).
|
||||
// * the new value of visibleViewportTop will be used to calculate the
|
||||
// new scrollOffset in the new buffer, so that the visible lines on
|
||||
// new scrollOffsett in the new buffer, so that the visible lines on
|
||||
// the screen remain roughly the same.
|
||||
TextBuffer::PositionInformation oldRows{ 0 };
|
||||
oldRows.mutableViewportTop = oldViewportTop;
|
||||
@@ -701,7 +705,6 @@ void Terminal::_AdjustCursorPosition(const COORD proposedPosition)
|
||||
|
||||
if (notifyScroll)
|
||||
{
|
||||
// TODO: don't do this, thanks migrie
|
||||
_buffer->GetRenderTarget().TriggerRedrawAll();
|
||||
_NotifyScrollEvent();
|
||||
}
|
||||
|
||||
@@ -181,6 +181,7 @@ public:
|
||||
Word,
|
||||
Line
|
||||
};
|
||||
const bool IsCopyOnSelectActive() const noexcept;
|
||||
void MultiClickSelection(const COORD viewportPos, SelectionExpansionMode expansionMode);
|
||||
void SetSelectionAnchor(const COORD position);
|
||||
void SetSelectionEnd(const COORD position, std::optional<SelectionExpansionMode> newExpansionMode = std::nullopt);
|
||||
@@ -221,6 +222,8 @@ private:
|
||||
};
|
||||
std::optional<SelectionAnchors> _selection;
|
||||
bool _blockSelection;
|
||||
bool _allowSingleCharSelection;
|
||||
bool _copyOnSelect;
|
||||
std::wstring _wordDelimiters;
|
||||
SelectionExpansionMode _multiClickSelectionMode;
|
||||
#pragma endregion
|
||||
@@ -237,7 +240,7 @@ private:
|
||||
// If _scrollOffset is 0, then the visible region of the buffer is the viewport.
|
||||
int _scrollOffset;
|
||||
// TODO this might not be the value we want to store.
|
||||
// We might want to store the height in the scrollback that's currently visible.
|
||||
// We might want to store the height in the scrollback that's currenty visible.
|
||||
// Think on this some more.
|
||||
// For example: While looking at the scrollback, we probably want the visible region to "stick"
|
||||
// to the region they scrolled to. If that were the case, then every time we move _mutableViewport,
|
||||
@@ -272,6 +275,7 @@ private:
|
||||
std::pair<COORD, COORD> _PivotSelection(const COORD targetPos) const;
|
||||
std::pair<COORD, COORD> _ExpandSelectionAnchors(std::pair<COORD, COORD> anchors) const;
|
||||
COORD _ConvertToBufferCell(const COORD viewportPos) const;
|
||||
const bool _IsSingleCellSelection() const noexcept;
|
||||
#pragma endregion
|
||||
|
||||
#ifdef UNIT_TESTING
|
||||
|
||||
@@ -396,7 +396,7 @@ try
|
||||
return false;
|
||||
}
|
||||
|
||||
// Move the viewport, adjust the scroll bar if needed, and restore the old cursor position
|
||||
// Move the viewport, adjust the scoll bar if needed, and restore the old cursor position
|
||||
_mutableViewport = Viewport::FromExclusive(newWin);
|
||||
Terminal::_NotifyScrollEvent();
|
||||
SetCursorPosition(relativeCursor.X, relativeCursor.Y);
|
||||
|
||||
@@ -82,12 +82,27 @@ const COORD Terminal::GetSelectionEnd() const noexcept
|
||||
return _selection->end;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Checks if selection is on a single cell
|
||||
// Return Value:
|
||||
// - bool representing if selection is only a single cell. Used for copyOnSelect
|
||||
const bool Terminal::_IsSingleCellSelection() const noexcept
|
||||
{
|
||||
return (_selection->start == _selection->end);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Checks if selection is active
|
||||
// Return Value:
|
||||
// - bool representing if selection is active. Used to decide copy/paste on right click
|
||||
const bool Terminal::IsSelectionActive() const noexcept
|
||||
{
|
||||
// A single cell selection is not considered an active selection,
|
||||
// if it's not allowed
|
||||
if (!_allowSingleCharSelection && _IsSingleCellSelection())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return _selection.has_value();
|
||||
}
|
||||
|
||||
@@ -96,6 +111,15 @@ const bool Terminal::IsBlockSelection() const noexcept
|
||||
return _blockSelection;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Checks if the CopyOnSelect setting is active
|
||||
// Return Value:
|
||||
// - true if feature is active, false otherwise.
|
||||
const bool Terminal::IsCopyOnSelectActive() const noexcept
|
||||
{
|
||||
return _copyOnSelect;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Perform a multi-click selection at viewportPos expanding according to the expansionMode
|
||||
// Arguments:
|
||||
@@ -124,6 +148,8 @@ void Terminal::SetSelectionAnchor(const COORD viewportPos)
|
||||
_selection = SelectionAnchors{};
|
||||
_selection->pivot = _ConvertToBufferCell(viewportPos);
|
||||
|
||||
_allowSingleCharSelection = (_copyOnSelect) ? false : true;
|
||||
|
||||
_multiClickSelectionMode = SelectionExpansionMode::Cell;
|
||||
SetSelectionEnd(viewportPos);
|
||||
|
||||
@@ -146,6 +172,13 @@ void Terminal::SetSelectionEnd(const COORD viewportPos, std::optional<SelectionE
|
||||
|
||||
const auto anchors = _PivotSelection(textBufferPos);
|
||||
std::tie(_selection->start, _selection->end) = _ExpandSelectionAnchors(anchors);
|
||||
|
||||
// moving the endpoint of what used to be a single cell selection
|
||||
// allows the user to drag back and select just one cell
|
||||
if (_copyOnSelect && !_IsSingleCellSelection())
|
||||
{
|
||||
_allowSingleCharSelection = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
@@ -215,6 +248,7 @@ void Terminal::SetBlockSelection(const bool isEnabled) noexcept
|
||||
#pragma warning(disable : 26440) // changing this to noexcept would require a change to ConHost's selection model
|
||||
void Terminal::ClearSelection()
|
||||
{
|
||||
_allowSingleCharSelection = false;
|
||||
_selection = std::nullopt;
|
||||
}
|
||||
|
||||
|
||||
@@ -38,8 +38,6 @@ namespace Microsoft.Terminal.Settings
|
||||
|
||||
IKeyBindings KeyBindings;
|
||||
|
||||
Boolean CopyOnSelect;
|
||||
|
||||
String Commandline;
|
||||
String StartingDirectory;
|
||||
String EnvironmentVariables;
|
||||
|
||||
@@ -32,6 +32,7 @@ namespace Microsoft.Terminal.Settings
|
||||
String StartingTitle;
|
||||
Boolean SuppressApplicationTitle;
|
||||
String WordDelimiters;
|
||||
Boolean CopyOnSelect;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -53,9 +53,6 @@ class TerminalCoreUnitTests::ConptyRoundtripTests final
|
||||
static const SHORT TerminalViewWidth = 80;
|
||||
static const SHORT TerminalViewHeight = 32;
|
||||
|
||||
// This test class is for tests that are supposed to emit something in the PTY layer
|
||||
// and then check that they've been staged for presentation correctly inside
|
||||
// the Terminal application. Which sequences were used to get here don't matter.
|
||||
TEST_CLASS(ConptyRoundtripTests);
|
||||
|
||||
TEST_CLASS_SETUP(ClassSetup)
|
||||
@@ -174,8 +171,6 @@ class TerminalCoreUnitTests::ConptyRoundtripTests final
|
||||
|
||||
TEST_METHOD(TestResizeHeight);
|
||||
|
||||
TEST_METHOD(ScrollWithMargins);
|
||||
|
||||
private:
|
||||
bool _writeCallback(const char* const pch, size_t const cch);
|
||||
void _flushFirstFrame();
|
||||
@@ -476,7 +471,7 @@ void ConptyRoundtripTests::TestExactWrappingWithoutSpaces()
|
||||
//
|
||||
// If a line _exactly_ wraps to the next line, we can't tell if the line
|
||||
// should really wrap, or manually break. The client app is writing a line
|
||||
// that's exactly the width of the buffer that manually breaks at the
|
||||
// that's exactly the width of the buffer that manually linebreaked at the
|
||||
// end of the line, followed by another line.
|
||||
//
|
||||
// With the old PaintBufferLine interface, there's no way to know if this
|
||||
@@ -633,7 +628,7 @@ void ConptyRoundtripTests::MoveCursorAtEOL()
|
||||
// might change, but the buffer contents shouldn't.
|
||||
// If they do change and these tests break, that's to be expected.
|
||||
expectedOutput.push_back(std::string(TerminalViewWidth, 'A'));
|
||||
expectedOutput.push_back("\x1b[1;80H");
|
||||
// expectedOutput.push_back("\x1b[1;80H");
|
||||
|
||||
VERIFY_SUCCEEDED(renderer.PaintFrame());
|
||||
|
||||
@@ -659,8 +654,11 @@ void ConptyRoundtripTests::MoveCursorAtEOL()
|
||||
|
||||
verifyData1(hostTb);
|
||||
|
||||
// expectedOutput.push_back(" ");
|
||||
// expectedOutput.push_back("\x1b[1;80H");
|
||||
expectedOutput.push_back("\x08");
|
||||
expectedOutput.push_back(" ");
|
||||
expectedOutput.push_back("\x1b[1;80H");
|
||||
expectedOutput.push_back("\x08");
|
||||
VERIFY_SUCCEEDED(renderer.PaintFrame());
|
||||
|
||||
verifyData1(termTb);
|
||||
@@ -950,7 +948,7 @@ void ConptyRoundtripTests::PassthroughClearScrollback()
|
||||
else
|
||||
{
|
||||
// After we hit the bottom of the viewport, the newlines come in
|
||||
// separated for whatever reason.
|
||||
// seperated for whatever reason.
|
||||
expectedOutput.push_back("\r");
|
||||
expectedOutput.push_back("\n");
|
||||
expectedOutput.push_back("");
|
||||
@@ -1060,245 +1058,3 @@ void ConptyRoundtripTests::PassthroughHardReset()
|
||||
TestUtils::VerifyExpectedString(termTb, std::wstring(TerminalViewWidth, L' '), { 0, y });
|
||||
}
|
||||
}
|
||||
|
||||
void ConptyRoundtripTests::ScrollWithMargins()
|
||||
{
|
||||
auto& g = ServiceLocator::LocateGlobals();
|
||||
auto& renderer = *g.pRender;
|
||||
auto& gci = g.getConsoleInformation();
|
||||
auto& si = gci.GetActiveOutputBuffer();
|
||||
auto& hostSm = si.GetStateMachine();
|
||||
|
||||
auto& hostTb = si.GetTextBuffer();
|
||||
auto& termTb = *term->_buffer;
|
||||
const auto initialTermView = term->GetViewport();
|
||||
|
||||
Log::Comment(L"Flush first frame.");
|
||||
_flushFirstFrame();
|
||||
|
||||
// Fill up the buffer with some text.
|
||||
// We're going to write something like this:
|
||||
// AAAA
|
||||
// BBBB
|
||||
// CCCC
|
||||
// ........
|
||||
// QQQQ
|
||||
// ****************
|
||||
// The letters represent the data in the TMUX pane.
|
||||
// The final *** line represents the mode line which we will
|
||||
// attempt to hold in place and not scroll.
|
||||
|
||||
Log::Comment(L"Fill host with text pattern by feeding it into VT parser.");
|
||||
const auto rowsToWrite = initialTermView.Height() - 1;
|
||||
|
||||
// For all lines but the last one, write out a few of a letter.
|
||||
for (auto i = 0; i < rowsToWrite; ++i)
|
||||
{
|
||||
const wchar_t wch = static_cast<wchar_t>(L'A' + i);
|
||||
hostSm.ProcessCharacter(wch);
|
||||
hostSm.ProcessCharacter(wch);
|
||||
hostSm.ProcessCharacter(wch);
|
||||
hostSm.ProcessCharacter(wch);
|
||||
hostSm.ProcessCharacter('\n');
|
||||
}
|
||||
|
||||
// For the last one, write out the asterisks for the mode line.
|
||||
for (auto i = 0; i < initialTermView.Width(); ++i)
|
||||
{
|
||||
hostSm.ProcessCharacter('*');
|
||||
}
|
||||
|
||||
// no newline in the bottom right corner or it will move unexpectedly.
|
||||
|
||||
// Now set up the verification that the buffers are full of the pattern we expect.
|
||||
// This function will verify the text backing buffers.
|
||||
auto verifyBuffer = [&](const TextBuffer& tb) {
|
||||
auto& cursor = tb.GetCursor();
|
||||
// Verify the cursor is waiting in the bottom right corner
|
||||
VERIFY_ARE_EQUAL(initialTermView.Height() - 1, cursor.GetPosition().Y);
|
||||
VERIFY_ARE_EQUAL(initialTermView.Width() - 1, cursor.GetPosition().X);
|
||||
|
||||
// For all rows except the last one, verify that we have a run of four letters.
|
||||
for (auto i = 0; i < rowsToWrite; ++i)
|
||||
{
|
||||
const std::wstring expectedString(4, static_cast<wchar_t>(L'A' + i));
|
||||
const COORD expectedPos{ 0, gsl::narrow<SHORT>(i) };
|
||||
TestUtils::VerifyExpectedString(tb, expectedString, expectedPos);
|
||||
}
|
||||
|
||||
// For the last row, verify we have an entire row of asterisks for the mode line.
|
||||
const std::wstring expectedModeLine(initialTermView.Width(), L'*');
|
||||
const COORD expectedPos{ 0, gsl::narrow<SHORT>(rowsToWrite) };
|
||||
TestUtils::VerifyExpectedString(tb, expectedModeLine, expectedPos);
|
||||
};
|
||||
|
||||
// This will verify the text emitted from the PTY.
|
||||
for (auto i = 0; i < rowsToWrite; ++i)
|
||||
{
|
||||
const std::string expectedString(4, static_cast<char>('A' + i));
|
||||
expectedOutput.push_back(expectedString);
|
||||
expectedOutput.push_back("\r\n");
|
||||
}
|
||||
{
|
||||
const std::string expectedString(initialTermView.Width(), '*');
|
||||
expectedOutput.push_back(expectedString);
|
||||
|
||||
// Cursor gets reset into bottom right corner as we're writing all the way into that corner.
|
||||
std::stringstream ss;
|
||||
ss << "\x1b[" << initialTermView.Height() << ";" << initialTermView.Width() << "H";
|
||||
expectedOutput.push_back(ss.str());
|
||||
}
|
||||
|
||||
Log::Comment(L"Verify host buffer contains pattern.");
|
||||
// Verify the host side.
|
||||
verifyBuffer(hostTb);
|
||||
|
||||
Log::Comment(L"Emit PTY frame and validate it transmits the right data.");
|
||||
// Paint the frame
|
||||
VERIFY_SUCCEEDED(renderer.PaintFrame());
|
||||
|
||||
Log::Comment(L"Verify terminal buffer contains pattern.");
|
||||
// Verify the terminal side.
|
||||
verifyBuffer(termTb);
|
||||
|
||||
Log::Comment(L"!!! OK. Set up the scroll region and let's get scrolling!");
|
||||
// This is a simulation of what TMUX does to scroll everything except the mode line.
|
||||
// First build up our VT strings...
|
||||
std::wstring reducedScrollRegion;
|
||||
{
|
||||
std::wstringstream wss;
|
||||
// For 20 tall buffer...
|
||||
// ESC[1;19r
|
||||
// Set scroll region to lines 1-19.
|
||||
wss << L"\x1b[1;" << initialTermView.Height() - 1 << L"r";
|
||||
reducedScrollRegion = wss.str();
|
||||
}
|
||||
std::wstring completeScrollRegion;
|
||||
{
|
||||
std::wstringstream wss;
|
||||
// For 20 tall buffer...
|
||||
// ESC[1;20r
|
||||
// Set scroll region to lines 1-20. (or the whole buffer)
|
||||
wss << L"\x1b[1;" << initialTermView.Height() << L"r";
|
||||
completeScrollRegion = wss.str();
|
||||
}
|
||||
std::wstring reducedCursorBottomRight;
|
||||
{
|
||||
std::wstringstream wss;
|
||||
// For 20 tall and 100 wide buffer
|
||||
// ESC[19;100H
|
||||
// Put cursor on line 19 (1 before last) and the right most column 100.
|
||||
// (Remember that in VT, we start counting from 1 not 0.)
|
||||
wss << L"\x1b[" << initialTermView.Height() - 1 << L";" << initialTermView.Width() << "H";
|
||||
reducedCursorBottomRight = wss.str();
|
||||
}
|
||||
std::wstring completeCursorAtPromptLine;
|
||||
{
|
||||
std::wstringstream wss;
|
||||
// For 20 tall and 100 wide buffer
|
||||
// ESC[19;1H
|
||||
// Put cursor on line 19 (1 before last) and the left most column 1.
|
||||
// (Remember that in VT, we start counting from 1 not 0.)
|
||||
wss << L"\x1b[" << initialTermView.Height() - 1 << L";1H";
|
||||
completeCursorAtPromptLine = wss.str();
|
||||
}
|
||||
|
||||
Log::Comment(L"Perform all the operations on the buffer.");
|
||||
|
||||
// OK this is what TMUX does.
|
||||
// 1. Mark off the scroll area as everything but the mode line.
|
||||
hostSm.ProcessString(reducedScrollRegion);
|
||||
// 2. Put the cursor in the bottom-right corner of the scroll region.
|
||||
hostSm.ProcessString(reducedCursorBottomRight);
|
||||
// 3. Send a single newline which should do the heavy lifting
|
||||
// of pushing everything in the scroll region up by 1 line and
|
||||
// leave everything outside the region alone.
|
||||
|
||||
// This entire block is subject to change in the future with optimizations.
|
||||
{
|
||||
// Cursor gets redrawn in the bottom right of the scroll region with the repaint that is forced
|
||||
// early while the screen is rotated.
|
||||
std::stringstream ss;
|
||||
ss << "\x1b[" << initialTermView.Height() - 1 << ";" << initialTermView.Width() << "H";
|
||||
expectedOutput.push_back(ss.str());
|
||||
|
||||
expectedOutput.push_back("\x1b[?25h"); // turn the cursor back on too.
|
||||
}
|
||||
|
||||
hostSm.ProcessString(L"\n");
|
||||
// 4. Remove the scroll area by setting it to the entire size of the viewport.
|
||||
hostSm.ProcessString(completeScrollRegion);
|
||||
// 5. Put the cursor back at the beginning of the new line that was just revealed.
|
||||
hostSm.ProcessString(completeCursorAtPromptLine);
|
||||
|
||||
// Set up the verifications like above.
|
||||
auto verifyBufferAfter = [&](const TextBuffer& tb) {
|
||||
auto& cursor = tb.GetCursor();
|
||||
// Verify the cursor is waiting on the freshly revealed line (1 above mode line)
|
||||
// and in the left most column.
|
||||
VERIFY_ARE_EQUAL(initialTermView.Height() - 2, cursor.GetPosition().Y);
|
||||
VERIFY_ARE_EQUAL(0, cursor.GetPosition().X);
|
||||
|
||||
// For all rows except the last two, verify that we have a run of four letters.
|
||||
for (auto i = 0; i < rowsToWrite - 1; ++i)
|
||||
{
|
||||
// Start with B this time because the A line got scrolled off the top.
|
||||
const std::wstring expectedString(4, static_cast<wchar_t>(L'B' + i));
|
||||
const COORD expectedPos{ 0, gsl::narrow<SHORT>(i) };
|
||||
TestUtils::VerifyExpectedString(tb, expectedString, expectedPos);
|
||||
}
|
||||
|
||||
// For the second to last row, verify that it is blank.
|
||||
{
|
||||
const std::wstring expectedBlankLine(initialTermView.Width(), L' ');
|
||||
const COORD blankLinePos{ 0, gsl::narrow<SHORT>(rowsToWrite - 1) };
|
||||
TestUtils::VerifyExpectedString(tb, expectedBlankLine, blankLinePos);
|
||||
}
|
||||
|
||||
// For the last row, verify we have an entire row of asterisks for the mode line.
|
||||
{
|
||||
const std::wstring expectedModeLine(initialTermView.Width(), L'*');
|
||||
const COORD modeLinePos{ 0, gsl::narrow<SHORT>(rowsToWrite) };
|
||||
TestUtils::VerifyExpectedString(tb, expectedModeLine, modeLinePos);
|
||||
}
|
||||
};
|
||||
|
||||
// This will verify the text emitted from the PTY.
|
||||
|
||||
expectedOutput.push_back("\x1b[H"); // cursor returns to top left corner.
|
||||
for (auto i = 0; i < rowsToWrite - 1; ++i)
|
||||
{
|
||||
const std::string expectedString(4, static_cast<char>('B' + i));
|
||||
expectedOutput.push_back(expectedString);
|
||||
expectedOutput.push_back("\x1b[K"); // erase the rest of the line.
|
||||
expectedOutput.push_back("\r\n");
|
||||
}
|
||||
{
|
||||
expectedOutput.push_back(""); // nothing for the empty line
|
||||
expectedOutput.push_back("\x1b[K"); // erase the rest of the line.
|
||||
expectedOutput.push_back("\r\n");
|
||||
}
|
||||
{
|
||||
const std::string expectedString(initialTermView.Width(), '*');
|
||||
expectedOutput.push_back(expectedString);
|
||||
}
|
||||
{
|
||||
// Cursor gets reset into second line from bottom, left most column
|
||||
std::stringstream ss;
|
||||
ss << "\x1b[" << initialTermView.Height() - 1 << ";1H";
|
||||
expectedOutput.push_back(ss.str());
|
||||
}
|
||||
expectedOutput.push_back("\x1b[?25h"); // turn the cursor back on too.
|
||||
|
||||
Log::Comment(L"Verify host buffer contains pattern moved up one and mode line still in place.");
|
||||
// Verify the host side.
|
||||
verifyBufferAfter(hostTb);
|
||||
|
||||
Log::Comment(L"Emit PTY frame and validate it transmits the right data.");
|
||||
// Paint the frame
|
||||
VERIFY_SUCCEEDED(renderer.PaintFrame());
|
||||
|
||||
Log::Comment(L"Verify terminal buffer contains pattern moved up one and mode line still in place.");
|
||||
// Verify the terminal side.
|
||||
verifyBufferAfter(termTb);
|
||||
}
|
||||
|
||||
@@ -672,5 +672,49 @@ namespace TerminalCoreUnitTests
|
||||
selection = term.GetViewport().ConvertToOrigin(selectionRects.at(1)).ToInclusive();
|
||||
VERIFY_ARE_EQUAL(selection, SMALL_RECT({ 0, 11, 99, 11 }));
|
||||
}
|
||||
|
||||
TEST_METHOD(CopyOnSelect)
|
||||
{
|
||||
Terminal term;
|
||||
DummyRenderTarget emptyRT;
|
||||
term.Create({ 100, 100 }, 0, emptyRT);
|
||||
|
||||
// set copyOnSelect for terminal
|
||||
auto settings = winrt::make<MockTermSettings>(0, 100, 100);
|
||||
settings.CopyOnSelect(true);
|
||||
term.UpdateSettings(settings);
|
||||
|
||||
// Simulate click at (x,y) = (5,10)
|
||||
term.SetSelectionAnchor({ 5, 10 });
|
||||
|
||||
// Simulate move to (x,y) = (5,10)
|
||||
// (So, no movement)
|
||||
term.SetSelectionEnd({ 5, 10 });
|
||||
|
||||
// Case 1: single cell selection not allowed
|
||||
{
|
||||
// Simulate renderer calling TriggerSelection and acquiring selection area
|
||||
auto selectionRects = term.GetSelectionRects();
|
||||
|
||||
// Validate selection area
|
||||
VERIFY_ARE_EQUAL(selectionRects.size(), static_cast<size_t>(0));
|
||||
|
||||
// single cell selection should not be allowed
|
||||
// thus, selection is NOT active
|
||||
VERIFY_IS_FALSE(term.IsSelectionActive());
|
||||
}
|
||||
|
||||
// Case 2: move off of single cell
|
||||
term.SetSelectionEnd({ 6, 10 });
|
||||
ValidateSingleRowSelection(term, { 5, 10, 6, 10 });
|
||||
VERIFY_IS_TRUE(term.IsSelectionActive());
|
||||
|
||||
// Case 3: move back onto single cell (now allowed)
|
||||
term.SetSelectionEnd({ 5, 10 });
|
||||
ValidateSingleRowSelection(term, { 5, 10, 5, 10 });
|
||||
|
||||
// single cell selection should now be allowed
|
||||
VERIFY_IS_TRUE(term.IsSelectionActive());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -403,7 +403,7 @@ int NonClientIslandWindow::_GetResizeHandleHeight() const noexcept
|
||||
// However, testing a bunch of other apps with fullscreen modes
|
||||
// and an auto-hiding taskbar has shown that _none_ of them
|
||||
// reveal the taskbar from fullscreen mode. This includes Edge,
|
||||
// Firefox, Chrome, Sublime Text, PowerPoint - none seemed to
|
||||
// Firefox, Chrome, Sublime Text, Powerpoint - none seemed to
|
||||
// support this.
|
||||
//
|
||||
// This does however work fine for maximized.
|
||||
|
||||
@@ -123,7 +123,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" />
|
||||
<PRIResource Include="Resources\Resources.devicefamily-core.resw" />
|
||||
</ItemGroup>
|
||||
|
||||
@@ -18,12 +18,15 @@
|
||||
<Filter Include="Resources">
|
||||
<UniqueIdentifier>{4718a03b-f768-4d96-9106-096573a315a3}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Resources\en-US">
|
||||
<UniqueIdentifier>{943541d5-c1da-435d-9f61-85d1b118f041}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PRIResource Include="Resources.devicefamily-core.resw">
|
||||
<Filter>Resources</Filter>
|
||||
</PRIResource>
|
||||
<PRIResource Include="Resources\*\Resources.resw">
|
||||
<PRIResource Include="Resources.language-en.resw">
|
||||
<Filter>Resources</Filter>
|
||||
</PRIResource>
|
||||
<PRIResource Include="Resources.resw">
|
||||
|
||||
@@ -38,7 +38,7 @@ namespace Microsoft.Terminal.Wpf
|
||||
WM_MOUSEACTIVATE = 0x0021,
|
||||
|
||||
WM_GETOBJECT = 0x003D,
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The WM_WINDOWPOSCHANGED message is sent to a window whose size, position, or place in the Z order has changed as a result of a call to the SetWindowPos function or another window-management function.
|
||||
/// </summary>
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace Microsoft.Terminal.Wpf
|
||||
private DispatcherTimer blinkTimer;
|
||||
private NativeMethods.ScrollCallback scrollCallback;
|
||||
private NativeMethods.WriteCallback writeCallback;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="TerminalContainer"/> class.
|
||||
/// </summary>
|
||||
@@ -35,7 +35,7 @@ namespace Microsoft.Terminal.Wpf
|
||||
this.MessageHook += this.TerminalContainer_MessageHook;
|
||||
this.GotFocus += this.TerminalContainer_GotFocus;
|
||||
this.Focusable = true;
|
||||
|
||||
|
||||
var blinkTime = NativeMethods.GetCaretBlinkTime();
|
||||
|
||||
if (blinkTime != uint.MaxValue)
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace Microsoft.Terminal.Wpf
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A basic terminal control. This control can receive and render standard VT100 sequences.
|
||||
/// </summary>
|
||||
|
||||
@@ -109,7 +109,7 @@ private: \
|
||||
|
||||
// Use this macro to quickly implement both the getter and setter for an observable property.
|
||||
// This is similar to the GETSET_PROPERTY macro above, except this will also raise a
|
||||
// PropertyChanged event with the name of the property that has changed inside of the setter.
|
||||
// PropertyChanged event with the name of the property that has changed inside of the settter.
|
||||
#define OBSERVABLE_GETSET_PROPERTY(type, name, event) \
|
||||
public: \
|
||||
type name() { return _##name; }; \
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
1. All of our winrt types are included in this manifest, including types from
|
||||
MUX.dll. Should this list of types ever change, we'll need to manually
|
||||
update this file. The easiest way of doing that is deploying the app from
|
||||
VS, then copying the Extensions from the appxmanifest.xml that's generated
|
||||
VS, then copying the Extensions from the Appxmandifest.xml that's generated
|
||||
under `src/cascadia/CascadiaPackage/bin/$(platform)/$(configuration)/appx`.
|
||||
|
||||
2. We also _NEED_ the two vclibs listed under the `PackageDependency` block.
|
||||
|
||||
@@ -171,33 +171,7 @@ constexpr unsigned int LOCAL_BUFFER_SIZE = 100;
|
||||
// displays the correct text.
|
||||
if (newViewOrigin == viewport.Origin())
|
||||
{
|
||||
// Inside this block, we're shifting down at the bottom.
|
||||
// This means that we had something like this:
|
||||
// AAAA
|
||||
// BBBB
|
||||
// CCCC
|
||||
// DDDD
|
||||
// EEEE
|
||||
//
|
||||
// Our margins were set for lines A-D, but not on line E.
|
||||
// So we circled the whole buffer up by one:
|
||||
// BBBB
|
||||
// CCCC
|
||||
// DDDD
|
||||
// EEEE
|
||||
// <blank, was AAAA>
|
||||
//
|
||||
// Then we scrolled the contents of everything OUTSIDE the margin frame down.
|
||||
// BBBB
|
||||
// CCCC
|
||||
// DDDD
|
||||
// <blank, filled during scroll down of EEEE>
|
||||
// EEEE
|
||||
//
|
||||
// And now we need to report that only the bottom line didn't "move" as we put the EEEE
|
||||
// back where it started, but everything else moved.
|
||||
// In this case, delta was 1. So the amount that moved is the entire viewport height minus the delta.
|
||||
Viewport invalid = Viewport::FromDimensions(viewport.Origin(), { viewport.Width(), viewport.Height() - delta });
|
||||
Viewport invalid = Viewport::FromDimensions(viewport.Origin(), { viewport.Width(), delta });
|
||||
screenInfo.GetRenderTarget().TriggerRedraw(invalid);
|
||||
}
|
||||
|
||||
|
||||
@@ -481,7 +481,7 @@ namespace Conhost.UIA.Tests
|
||||
TextPatternRange testRange = visibleRanges.First().Clone();
|
||||
|
||||
// assumes that range is a line range at the top of the screen buffer
|
||||
Action<TextPatternRange> testTopBoundary = delegate (TextPatternRange range)
|
||||
Action<TextPatternRange> testTopBoundary = delegate(TextPatternRange range)
|
||||
{
|
||||
// the first visible range is at the top of the screen
|
||||
// buffer, we shouldn't be able to move the starting endpoint up
|
||||
|
||||
@@ -31,7 +31,7 @@ namespace Conhost.UIA.Tests.Common
|
||||
|
||||
~ShortcutHelper()
|
||||
{
|
||||
this.Dispose(false);
|
||||
this.Dispose(false);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
|
||||
@@ -52,7 +52,7 @@ namespace Conhost.UIA.Tests.Elements
|
||||
|
||||
tab.Click();
|
||||
Globals.WaitForTimeout();
|
||||
|
||||
|
||||
this.PopulateItemsOnNavigate(this.propDialog.PropWindow);
|
||||
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ namespace Conhost.UIA.Tests.Elements
|
||||
this.tabs.Add(new FontTab(this.propDialog));
|
||||
this.tabs.Add(new LayoutTab(this.propDialog));
|
||||
this.tabs.Add(new ColorsTab(this.propDialog));
|
||||
|
||||
|
||||
}
|
||||
|
||||
private Tabs()
|
||||
|
||||
@@ -105,7 +105,7 @@ namespace Conhost.UIA.Tests.Elements
|
||||
app.UIRoot.SendKeys(Keys.Escape);
|
||||
this.state = ViewportStates.Normal;
|
||||
}
|
||||
|
||||
|
||||
public void EnterMode(ViewportStates state)
|
||||
{
|
||||
if (state == ViewportStates.Normal)
|
||||
|
||||
@@ -111,7 +111,7 @@ namespace Conhost.UIA.Tests
|
||||
default:
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
|
||||
afterScroll = app.GetScreenBufferInfo();
|
||||
|
||||
switch (dir)
|
||||
|
||||
@@ -57,7 +57,7 @@ namespace Conhost.UIA.Tests
|
||||
reg.BackupRegistry(); // we're going to modify the virtual terminal state for this, so back it up first.
|
||||
VersionSelector.SetConsoleVersion(reg, ConsoleVersion.V2);
|
||||
reg.SetDefaultValue(VIRTUAL_TERMINAL_KEY_NAME, VIRTUAL_TERMINAL_ON_VALUE);
|
||||
|
||||
|
||||
bool haveVtAppPath = !string.IsNullOrEmpty(vtAppLocation);
|
||||
|
||||
Verify.IsTrue(haveVtAppPath, "Ensure that we passed in the location to VtApp.exe");
|
||||
@@ -114,12 +114,12 @@ namespace Conhost.UIA.Tests
|
||||
Log.Comment("Move cursor to the middle-ish");
|
||||
Point cursorExpected = new Point();
|
||||
// H is at 5, 1. VT coords are 1-based and buffer is 0-based so adjust.
|
||||
cursorExpected.Y = 5 - 1;
|
||||
cursorExpected.Y = 5 - 1;
|
||||
cursorExpected.X = 1 - 1;
|
||||
app.UIRoot.SendKeys("H");
|
||||
|
||||
// Move to middle-ish from here. 10 Bs and 10 Cs should about do it.
|
||||
for (int i = 0; i < 10; i++)
|
||||
for (int i=0; i < 10; i++)
|
||||
{
|
||||
app.UIRoot.SendKeys("BC");
|
||||
cursorExpected.Y++;
|
||||
@@ -715,7 +715,7 @@ namespace Conhost.UIA.Tests
|
||||
}
|
||||
|
||||
delegate char GetExpectedChar(int rowId, int colId, int height, int width);
|
||||
|
||||
|
||||
private static void ScreenFillHelper(CmdApp app, ViewportArea area, IntPtr hConsole)
|
||||
{
|
||||
Log.Comment("Fill screen with junk");
|
||||
|
||||
@@ -212,7 +212,7 @@ namespace Conhost.UIA.Tests
|
||||
[TestMethod]
|
||||
public void TestSelection()
|
||||
{
|
||||
RunTest(TestSelectionImpl);
|
||||
RunTest(TestSelectionImpl);
|
||||
}
|
||||
|
||||
private void TestSelectionImpl(CmdApp app, ViewportArea area, IntPtr hConsole, WinCon.CONSOLE_SCREEN_BUFFER_INFO_EX sbiex, Queue<EventData> expected, WinCon.CONSOLE_SCREEN_BUFFER_INFO_EX sbiexOriginal)
|
||||
@@ -295,7 +295,7 @@ namespace Conhost.UIA.Tests
|
||||
[TestMethod]
|
||||
public void TestLaunchAndExitChild()
|
||||
{
|
||||
RunTest(TestLaunchAndExitChildImpl);
|
||||
RunTest(TestLaunchAndExitChildImpl);
|
||||
}
|
||||
|
||||
private void TestLaunchAndExitChildImpl(CmdApp app, ViewportArea area, IntPtr hConsole, WinCon.CONSOLE_SCREEN_BUFFER_INFO_EX sbiex, Queue<EventData> expected, WinCon.CONSOLE_SCREEN_BUFFER_INFO_EX sbiexOriginal)
|
||||
@@ -357,11 +357,11 @@ namespace Conhost.UIA.Tests
|
||||
{
|
||||
RunTest(TestScrollByWheelImpl);
|
||||
}
|
||||
|
||||
|
||||
private void TestScrollByWheelImpl(CmdApp app, ViewportArea area, IntPtr hConsole, WinCon.CONSOLE_SCREEN_BUFFER_INFO_EX sbiex, Queue<EventData> expected, WinCon.CONSOLE_SCREEN_BUFFER_INFO_EX sbiexOriginal)
|
||||
{
|
||||
int rowsPerScroll = app.GetRowsPerScroll();
|
||||
int scrollDelta;
|
||||
int scrollDelta;
|
||||
|
||||
// A. Scroll down.
|
||||
{
|
||||
|
||||
@@ -316,7 +316,7 @@ void ProcessCtrlEvents()
|
||||
{
|
||||
/*
|
||||
* Status will be non-successful if a process attached to this console
|
||||
* vetoes shutdown. In that case, we don't want to try to kill any more
|
||||
* vetos shutdown. In that case, we don't want to try to kill any more
|
||||
* processes, but we do need to make sure we continue looping so we
|
||||
* can close any remaining process handles. The exception is if the
|
||||
* process is inaccessible, such that we can't even open a handle for
|
||||
|
||||
@@ -467,7 +467,7 @@ size_t InputBuffer::Prepend(_Inout_ std::deque<std::unique_ptr<IInputEvent>>& in
|
||||
try
|
||||
{
|
||||
_vtInputShouldSuppress = true;
|
||||
auto resetVtInputSuppress = wil::scope_exit([&]() { _vtInputShouldSuppress = false; });
|
||||
auto resetVtInputSupress = wil::scope_exit([&]() { _vtInputShouldSuppress = false; });
|
||||
_HandleConsoleSuspensionEvents(inEvents);
|
||||
if (inEvents.empty())
|
||||
{
|
||||
|
||||
@@ -123,7 +123,12 @@ COORD RenderData::GetCursorPosition() const noexcept
|
||||
{
|
||||
const CONSOLE_INFORMATION& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
|
||||
const auto& cursor = gci.GetActiveOutputBuffer().GetTextBuffer().GetCursor();
|
||||
return cursor.GetPosition();
|
||||
COORD effectiveCursor = cursor.GetPosition();
|
||||
if (cursor.IsDelayedEOLWrap() && cursor.GetDelayedAtPosition() == effectiveCursor)
|
||||
{
|
||||
effectiveCursor.X++;
|
||||
}
|
||||
return effectiveCursor;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
@@ -307,7 +312,7 @@ const bool RenderData::IsGridLineDrawingAllowed() noexcept
|
||||
{
|
||||
// Otherwise, for compatibility reasons with legacy applications that used the additional CHAR_INFO bits by accident or for their own purposes,
|
||||
// we must enable grid line drawing only in a DBCS output codepage. (Line drawing historically only worked in DBCS codepages.)
|
||||
// The only known instance of this is Image for Windows by TeraByte, Inc. (TeraByte Unlimited) which used the bits accidentally and for no purpose
|
||||
// The only known instance of this is Image for Windows by TeraByte, Inc. (TeryByte Unlimited) which used the bits accidentally and for no purpose
|
||||
// (according to the app developer) in conjunction with the Borland Turbo C cgscrn library.
|
||||
return !!IsAvailableEastAsianCodePage(gci.OutputCP);
|
||||
}
|
||||
@@ -411,7 +416,7 @@ const COORD RenderData::GetSelectionEnd() const noexcept
|
||||
// - SelectionAnchor: the initial position where the selection was started
|
||||
// - SelectionRect: the rectangular region denoting a portion of the buffer that is selected
|
||||
|
||||
// The following is an excerpt from Selection::s_GetSelectionRects
|
||||
// The following is an exerpt from Selection::s_GetSelectionRects
|
||||
// if the anchor (start of select) was in the top right or bottom left of the box,
|
||||
// we need to remove rectangular overlap in the middle.
|
||||
// e.g.
|
||||
|
||||
@@ -166,7 +166,7 @@ Viewport SCREEN_INFORMATION::GetBufferSize() const
|
||||
// Arguments:
|
||||
// - <none>
|
||||
// Return Value:
|
||||
// - a viewport whose height is the height of the "terminal" portion of the
|
||||
// - a viewport whos height is the height of the "terminal" portion of the
|
||||
// buffer in terminal scrolling mode, and is the height of the full buffer
|
||||
// in normal scrolling mode.
|
||||
Viewport SCREEN_INFORMATION::GetTerminalBufferSize() const
|
||||
@@ -765,7 +765,7 @@ void SCREEN_INFORMATION::SetViewportSize(const COORD* const pcoordSize)
|
||||
|
||||
const CONSOLE_INFORMATION& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
|
||||
|
||||
// If we're in terminal scrolling mode, and we're trying to set the viewport
|
||||
// If we're in terminal scrolling mode, and we're rying to set the viewport
|
||||
// below the logical viewport, without updating our virtual bottom
|
||||
// (the logical viewport's position), dont.
|
||||
// Instead move us to the bottom of the logical viewport.
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user