mirror of
https://github.com/microsoft/terminal.git
synced 2025-12-10 00:48:23 -06:00
conflict
This commit is contained in:
commit
da0a7a0fa0
@ -3,7 +3,7 @@
|
||||
"isRoot": true,
|
||||
"tools": {
|
||||
"XamlStyler.Console": {
|
||||
"version": "3.2311.2",
|
||||
"version": "3.2501.8",
|
||||
"commands": [
|
||||
"xstyler"
|
||||
]
|
||||
|
||||
24
.github/actions/spelling/allow/allow.txt
vendored
24
.github/actions/spelling/allow/allow.txt
vendored
@ -11,34 +11,25 @@ colorbrewer
|
||||
commandlines
|
||||
consvc
|
||||
copyable
|
||||
CText
|
||||
dalet
|
||||
dcs
|
||||
deselection
|
||||
dialytika
|
||||
diffing
|
||||
Dimidium
|
||||
dje
|
||||
downsides
|
||||
dze
|
||||
dzhe
|
||||
Emacspeak
|
||||
Fitt
|
||||
FTCS
|
||||
flac
|
||||
FTCS
|
||||
gantt
|
||||
gfm
|
||||
ghe
|
||||
gje
|
||||
godbolt
|
||||
hstrings
|
||||
hyperlinking
|
||||
hyperlinks
|
||||
Kbds
|
||||
kje
|
||||
libfuzzer
|
||||
liga
|
||||
lje
|
||||
Llast
|
||||
Lmid
|
||||
locl
|
||||
@ -50,10 +41,8 @@ minimalistic
|
||||
mkmk
|
||||
mnt
|
||||
mru
|
||||
nje
|
||||
notwrapped
|
||||
NTMTo
|
||||
ogonek
|
||||
overlined
|
||||
perlw
|
||||
postmodern
|
||||
@ -61,8 +50,8 @@ Powerline
|
||||
ptys
|
||||
pwn
|
||||
pwshw
|
||||
QOL
|
||||
qof
|
||||
QOL
|
||||
qps
|
||||
quickfix
|
||||
rclt
|
||||
@ -75,17 +64,13 @@ rlig
|
||||
rubyw
|
||||
runtimes
|
||||
servicebus
|
||||
shcha
|
||||
similaritytolerance
|
||||
slnt
|
||||
stakeholders
|
||||
subpage
|
||||
sustainability
|
||||
sxn
|
||||
TLDR
|
||||
tonos
|
||||
Tencent
|
||||
toolset
|
||||
tshe
|
||||
UEFI
|
||||
uiatextrange
|
||||
und
|
||||
@ -93,8 +78,5 @@ vsdevcmd
|
||||
westus
|
||||
workarounds
|
||||
WSLs
|
||||
wtconfig
|
||||
XBox
|
||||
YBox
|
||||
yeru
|
||||
zhe
|
||||
|
||||
73
.github/actions/spelling/allow/apis.txt
vendored
73
.github/actions/spelling/allow/apis.txt
vendored
@ -2,11 +2,8 @@ aalt
|
||||
abvm
|
||||
ACCEPTFILES
|
||||
ACCESSDENIED
|
||||
acl
|
||||
aclapi
|
||||
alignas
|
||||
alignof
|
||||
allocconsolewithoptions
|
||||
APPLYTOSUBMENUS
|
||||
appxrecipe
|
||||
bitfield
|
||||
@ -15,29 +12,20 @@ BUILDBRANCH
|
||||
BUILDMSG
|
||||
BUILDNUMBER
|
||||
BYCOMMAND
|
||||
BYPOSITION
|
||||
charconv
|
||||
CLASSNOTAVAILABLE
|
||||
CLOSEAPP
|
||||
cmdletbinding
|
||||
COLORPROPERTY
|
||||
colspan
|
||||
COMDLG
|
||||
commandlinetoargv
|
||||
commoncontrols
|
||||
comparand
|
||||
COPYFROMRESOURCE
|
||||
cstdint
|
||||
CXICON
|
||||
CYICON
|
||||
Dacl
|
||||
dataobject
|
||||
dcomp
|
||||
debugbreak
|
||||
delayimp
|
||||
DERR
|
||||
dlldata
|
||||
DNE
|
||||
dnom
|
||||
DONTADDTORECENT
|
||||
DWMSBT
|
||||
@ -64,81 +52,42 @@ GETHIGHCONTRAST
|
||||
GETMOUSEHOVERTIME
|
||||
GETTEXTLENGTH
|
||||
HARDBREAKS
|
||||
Hashtable
|
||||
HIGHCONTRASTON
|
||||
HIGHCONTRASTW
|
||||
HIGHQUALITYSCALE
|
||||
hinternet
|
||||
HINTERNET
|
||||
hotkeys
|
||||
href
|
||||
hrgn
|
||||
HTCLOSE
|
||||
hwinsta
|
||||
HWINSTA
|
||||
IActivation
|
||||
IApp
|
||||
IAppearance
|
||||
IAsync
|
||||
IBind
|
||||
IBox
|
||||
IClass
|
||||
IComparable
|
||||
IComparer
|
||||
ICONINFO
|
||||
IConnection
|
||||
ICustom
|
||||
IDialog
|
||||
IDirect
|
||||
Idn
|
||||
IExplorer
|
||||
IFACEMETHOD
|
||||
IFile
|
||||
IGraphics
|
||||
IImage
|
||||
IInheritable
|
||||
IMap
|
||||
imm
|
||||
IObject
|
||||
iosfwd
|
||||
IPackage
|
||||
isa
|
||||
ISetup
|
||||
isspace
|
||||
IStorage
|
||||
istream
|
||||
IStringable
|
||||
ITab
|
||||
ITaskbar
|
||||
itow
|
||||
IUri
|
||||
IVirtual
|
||||
KEYSELECT
|
||||
LCID
|
||||
LINEBREAK
|
||||
llabs
|
||||
llu
|
||||
localtime
|
||||
lround
|
||||
Lsa
|
||||
lsass
|
||||
LSHIFT
|
||||
LTGRAY
|
||||
MAINWINDOW
|
||||
MAXIMIZEBOX
|
||||
medi
|
||||
memchr
|
||||
memicmp
|
||||
MENUCOMMAND
|
||||
MENUDATA
|
||||
MENUINFO
|
||||
MENUITEMINFOW
|
||||
MINIMIZEBOX
|
||||
mmeapi
|
||||
MOUSELEAVE
|
||||
mov
|
||||
mptt
|
||||
msappx
|
||||
MULTIPLEUSE
|
||||
NCHITTEST
|
||||
NCLBUTTONDBLCLK
|
||||
@ -148,7 +97,6 @@ NCPOINTERUPDATE
|
||||
NCRBUTTONDBLCLK
|
||||
NIF
|
||||
NIN
|
||||
NOAGGREGATION
|
||||
NOASYNC
|
||||
NOBREAKS
|
||||
NOCHANGEDIR
|
||||
@ -161,8 +109,6 @@ NOTIFYICONDATA
|
||||
ntprivapi
|
||||
NTSYSCALLAPI
|
||||
numr
|
||||
oaidl
|
||||
ocidl
|
||||
ODR
|
||||
offsetof
|
||||
ofstream
|
||||
@ -172,22 +118,17 @@ OSVERSIONINFOEXW
|
||||
otms
|
||||
OUTLINETEXTMETRICW
|
||||
overridable
|
||||
PACL
|
||||
PAGESCROLL
|
||||
PALLOC
|
||||
PATINVERT
|
||||
PEXPLICIT
|
||||
PICKFOLDERS
|
||||
PINPUT
|
||||
pmr
|
||||
ptstr
|
||||
QUERYENDSESSION
|
||||
rcx
|
||||
REGCLS
|
||||
RETURNCMD
|
||||
rfind
|
||||
RLO
|
||||
rnrn
|
||||
ROOTOWNER
|
||||
roundf
|
||||
RSHIFT
|
||||
@ -206,22 +147,17 @@ SHOWTIP
|
||||
SINGLEUSE
|
||||
SIZENS
|
||||
smoothstep
|
||||
snprintf
|
||||
SOFTBREAK
|
||||
spsc
|
||||
sregex
|
||||
SRWLOC
|
||||
srwlock
|
||||
SRWLOCK
|
||||
STDCPP
|
||||
STDMETHOD
|
||||
strchr
|
||||
strcpy
|
||||
streambuf
|
||||
strtoul
|
||||
Stubless
|
||||
Subheader
|
||||
Subpage
|
||||
syscall
|
||||
syscolors
|
||||
SYSTEMBACKDROP
|
||||
@ -238,23 +174,18 @@ tokeninfo
|
||||
tolower
|
||||
toupper
|
||||
TRACKMOUSEEVENT
|
||||
TTask
|
||||
TVal
|
||||
ubrk
|
||||
UChar
|
||||
UFIELD
|
||||
ULARGE
|
||||
UOI
|
||||
UPDATEINIFILE
|
||||
urlmon
|
||||
userenv
|
||||
USEROBJECTFLAGS
|
||||
Vcpp
|
||||
Viewbox
|
||||
virtualalloc
|
||||
vsnwprintf
|
||||
wcsnlen
|
||||
wcsstr
|
||||
wcstoui
|
||||
WDJ
|
||||
winhttp
|
||||
wininet
|
||||
@ -264,10 +195,8 @@ winstamin
|
||||
wmemcmp
|
||||
wpc
|
||||
WSF
|
||||
wsregex
|
||||
WWH
|
||||
wwinmain
|
||||
xchg
|
||||
XDocument
|
||||
XElement
|
||||
xfacet
|
||||
|
||||
5
.github/actions/spelling/allow/chinese.txt
vendored
5
.github/actions/spelling/allow/chinese.txt
vendored
@ -1,5 +1,4 @@
|
||||
CHINESEBIG
|
||||
choseong
|
||||
Jongseong
|
||||
Jungseong
|
||||
ssangtikeut
|
||||
Choseong
|
||||
CHOSEONG
|
||||
|
||||
9
.github/actions/spelling/allow/colors.txt
vendored
9
.github/actions/spelling/allow/colors.txt
vendored
@ -1,4 +1,3 @@
|
||||
alice
|
||||
aliceblue
|
||||
antiquewhite
|
||||
blanchedalmond
|
||||
@ -39,7 +38,6 @@ gainsboro
|
||||
ghostwhite
|
||||
greenyellow
|
||||
hotpink
|
||||
indian
|
||||
indianred
|
||||
lavenderblush
|
||||
lawngreen
|
||||
@ -74,7 +72,6 @@ mediumvioletred
|
||||
midnightblue
|
||||
mintcream
|
||||
mistyrose
|
||||
navajo
|
||||
navajowhite
|
||||
navyblue
|
||||
oldlace
|
||||
@ -88,7 +85,6 @@ papayawhip
|
||||
peachpuff
|
||||
peru
|
||||
powderblue
|
||||
rebecca
|
||||
rebeccapurple
|
||||
rosybrown
|
||||
royalblue
|
||||
@ -109,9 +105,4 @@ webgrey
|
||||
webmaroon
|
||||
webpurple
|
||||
whitesmoke
|
||||
xaroon
|
||||
xray
|
||||
xreen
|
||||
xrey
|
||||
xurple
|
||||
yellowgreen
|
||||
|
||||
2
.github/actions/spelling/allow/fonts.txt
vendored
2
.github/actions/spelling/allow/fonts.txt
vendored
@ -1,8 +1,8 @@
|
||||
Consolas
|
||||
emoji
|
||||
emojis
|
||||
Emojis
|
||||
Extralight
|
||||
Gabriola
|
||||
Iosevka
|
||||
MDL
|
||||
Monofur
|
||||
|
||||
3
.github/actions/spelling/allow/japanese.txt
vendored
3
.github/actions/spelling/allow/japanese.txt
vendored
@ -1,4 +1 @@
|
||||
arigatoo
|
||||
doomo
|
||||
Kaomojis
|
||||
TATEGAKI
|
||||
|
||||
9
.github/actions/spelling/allow/math.txt
vendored
9
.github/actions/spelling/allow/math.txt
vendored
@ -1,11 +1,2 @@
|
||||
atan
|
||||
CPrime
|
||||
HBar
|
||||
HPrime
|
||||
isnan
|
||||
LPrime
|
||||
LStep
|
||||
powf
|
||||
RSub
|
||||
sqrtf
|
||||
ULP
|
||||
|
||||
30
.github/actions/spelling/allow/microsoft.txt
vendored
30
.github/actions/spelling/allow/microsoft.txt
vendored
@ -4,12 +4,11 @@ advapi
|
||||
akv
|
||||
AKV
|
||||
altform
|
||||
altforms
|
||||
Altforms
|
||||
appendwttlogging
|
||||
appinstaller
|
||||
appx
|
||||
appxbundle
|
||||
appxerror
|
||||
appxmanifest
|
||||
ATL
|
||||
autoexec
|
||||
@ -25,66 +24,44 @@ CPRs
|
||||
cryptbase
|
||||
cscript
|
||||
DACL
|
||||
DACLs
|
||||
defaultlib
|
||||
diffs
|
||||
disposables
|
||||
dotnetfeed
|
||||
DTDs
|
||||
DWINRT
|
||||
enablewttlogging
|
||||
HOMESHARE
|
||||
Intelli
|
||||
issecret
|
||||
IVisual
|
||||
libucrt
|
||||
libucrtd
|
||||
LKG
|
||||
LOCKFILE
|
||||
LTCG
|
||||
Lxss
|
||||
makepri
|
||||
mfcribbon
|
||||
microsoft
|
||||
microsoftonline
|
||||
MSAA
|
||||
msixbundle
|
||||
MSVC
|
||||
MSVCP
|
||||
mtu
|
||||
muxc
|
||||
netcore
|
||||
Onefuzz
|
||||
osgvsowi
|
||||
PFILETIME
|
||||
pgc
|
||||
pgo
|
||||
pgosweep
|
||||
powerrename
|
||||
powershell
|
||||
priconfig
|
||||
PRIINFO
|
||||
propkey
|
||||
pscustomobject
|
||||
QWORD
|
||||
rdpclip
|
||||
regedit
|
||||
resfiles
|
||||
robocopy
|
||||
SACLs
|
||||
sdkddkver
|
||||
segoe
|
||||
Shobjidl
|
||||
sid
|
||||
Skype
|
||||
SRW
|
||||
sxs
|
||||
symbolrequestprod
|
||||
Sysinternals
|
||||
sysnative
|
||||
systemroot
|
||||
taskkill
|
||||
tasklist
|
||||
tdbuildteamid
|
||||
ucrt
|
||||
ucrtd
|
||||
unvirtualized
|
||||
@ -92,12 +69,9 @@ USERDNSDOMAIN
|
||||
VCRT
|
||||
vcruntime
|
||||
Virtualization
|
||||
visualstudio
|
||||
vscode
|
||||
VSTHRD
|
||||
WINBASEAPI
|
||||
winsdkver
|
||||
wlk
|
||||
wscript
|
||||
wslpath
|
||||
wtl
|
||||
|
||||
35
.github/actions/spelling/allow/names.txt
vendored
35
.github/actions/spelling/allow/names.txt
vendored
@ -1,4 +1,3 @@
|
||||
Anup
|
||||
arkthur
|
||||
austdi
|
||||
Ballmer
|
||||
@ -6,13 +5,11 @@ bhoj
|
||||
Bhojwani
|
||||
Bluloco
|
||||
carlos
|
||||
craigloewen
|
||||
dhowett
|
||||
Diviness
|
||||
dsafa
|
||||
duhowett
|
||||
DXP
|
||||
ekg
|
||||
eryksun
|
||||
ethanschoonover
|
||||
Firefox
|
||||
@ -25,70 +22,43 @@ Hernan
|
||||
Howett
|
||||
Illhardt
|
||||
Imms
|
||||
iquilezles
|
||||
italo
|
||||
jantari
|
||||
jerrysh
|
||||
Kaiyu
|
||||
kimwalisch
|
||||
KMehrain
|
||||
Kodelife
|
||||
KODELIFE
|
||||
Kourosh
|
||||
kowalczyk
|
||||
leonardder
|
||||
leonmsft
|
||||
Lepilleur
|
||||
lhecker
|
||||
lukesampson
|
||||
Macbook
|
||||
Manandhar
|
||||
Lovecraft
|
||||
masserano
|
||||
mbadolato
|
||||
Mehrain
|
||||
menger
|
||||
mgravell
|
||||
michaelniksa
|
||||
michkap
|
||||
migrie
|
||||
mikegr
|
||||
mikemaccana
|
||||
miloush
|
||||
miniksa
|
||||
nguyen
|
||||
niksa
|
||||
nvaccess
|
||||
nvda
|
||||
oising
|
||||
oldnewthing
|
||||
opengl
|
||||
osgwiki
|
||||
Ottosson
|
||||
pabhojwa
|
||||
panos
|
||||
Panos
|
||||
paulcam
|
||||
pauldotknopf
|
||||
PGP
|
||||
Pham
|
||||
Rincewind
|
||||
rprichard
|
||||
Schoonover
|
||||
shadertoy
|
||||
Shomnipotence
|
||||
simioni
|
||||
Somuah
|
||||
sonph
|
||||
sonpham
|
||||
stakx
|
||||
talo
|
||||
thereses
|
||||
Thysell
|
||||
Walisch
|
||||
WDX
|
||||
Wellons
|
||||
Westerman
|
||||
Wirt
|
||||
Wojciech
|
||||
zadjii
|
||||
Zamor
|
||||
zamora
|
||||
@ -96,4 +66,3 @@ Zamora
|
||||
zljubisic
|
||||
Zoey
|
||||
zorio
|
||||
Zverovich
|
||||
|
||||
89
.github/actions/spelling/candidate.patterns
vendored
89
.github/actions/spelling/candidate.patterns
vendored
@ -1,3 +1,6 @@
|
||||
# Repeated letters
|
||||
\b([a-z])\g{-1}{2,}\b
|
||||
|
||||
# marker to ignore all code on line
|
||||
^.*/\* #no-spell-check-line \*/.*$
|
||||
# marker to ignore all code on line
|
||||
@ -7,6 +10,9 @@
|
||||
# cspell inline
|
||||
^.*\b[Cc][Ss][Pp][Ee][Ll]{2}:\s*[Dd][Ii][Ss][Aa][Bb][Ll][Ee]-[Ll][Ii][Nn][Ee]\b
|
||||
|
||||
# copyright
|
||||
Copyright (?:\([Cc]\)|)(?:[-\d, ]|and)+(?: [A-Z][a-z]+ [A-Z][a-z]+,?)+
|
||||
|
||||
# patch hunk comments
|
||||
^@@ -\d+(?:,\d+|) \+\d+(?:,\d+|) @@ .*
|
||||
# git index header
|
||||
@ -15,6 +21,9 @@ index (?:[0-9a-z]{7,40},|)[0-9a-z]{7,40}\.\.[0-9a-z]{7,40}
|
||||
# file permissions
|
||||
['"`\s][-bcdLlpsw](?:[-r][-w][-Ssx]){2}[-r][-w][-SsTtx]\+?['"`\s]
|
||||
|
||||
# css fonts
|
||||
\bfont(?:-family|):[^;}]+
|
||||
|
||||
# css url wrappings
|
||||
\burl\([^)]+\)
|
||||
|
||||
@ -32,9 +41,6 @@ index (?:[0-9a-z]{7,40},|)[0-9a-z]{7,40}\.\.[0-9a-z]{7,40}
|
||||
# https/http/file urls
|
||||
(?:\b(?:https?|ftp|file)://)[-A-Za-z0-9+&@#/*%?=~_|!:,.;]+[-A-Za-z0-9+&@#/*%=~_|]
|
||||
|
||||
# https/http/file urls
|
||||
(?:\b(?:https?|ftp|file)://)[-A-Za-z0-9+&@#/%?=~_|!:,.;]+[-A-Za-z0-9+&@#/%=~_|]
|
||||
|
||||
# mailto urls
|
||||
mailto:[-a-zA-Z=;:/?%&0-9+@._]{3,}
|
||||
|
||||
@ -69,6 +75,8 @@ magnet:[?=:\w]+
|
||||
|
||||
# Amazon
|
||||
\bamazon\.com/[-\w]+/(?:dp/[0-9A-Z]+|)
|
||||
# AWS ARN
|
||||
arn:aws:[-/:\w]+
|
||||
# AWS S3
|
||||
\b\w*\.s3[^.]*\.amazonaws\.com/[-\w/&#%_?:=]*
|
||||
# AWS execute-api
|
||||
@ -95,6 +103,8 @@ vpc-\w+
|
||||
\bgoogle-analytics\.com/collect.[-0-9a-zA-Z?%=&_.~]*
|
||||
# Google APIs
|
||||
\bgoogleapis\.(?:com|dev)/[a-z]+/(?:v\d+/|)[a-z]+/[-@:./?=\w+|&]+
|
||||
# Google Artifact Registry
|
||||
\.pkg\.dev(?:/[-\w]+)+(?::[-\w]+|)
|
||||
# Google Storage
|
||||
\b[-a-zA-Z0-9.]*\bstorage\d*\.googleapis\.com(?:/\S*|)
|
||||
# Google Calendar
|
||||
@ -130,6 +140,8 @@ themes\.googleusercontent\.com/static/fonts/[^/\s"]+/v\d+/[^.]+.
|
||||
\bscholar\.google\.com/citations\?user=[A-Za-z0-9_]+
|
||||
# Google Colab Research Drive
|
||||
\bcolab\.research\.google\.com/drive/[-0-9a-zA-Z_?=]*
|
||||
# Google Cloud regions
|
||||
(?:us|(?:north|south)america|europe|asia|australia|me|africa)-(?:north|south|east|west|central){1,2}\d+
|
||||
|
||||
# GitHub SHAs (api)
|
||||
\bapi.github\.com/repos(?:/[^/\s"]+){3}/[0-9a-f]+\b
|
||||
@ -168,6 +180,12 @@ GHSA(?:-[0-9a-z]{4}){3}
|
||||
# GitLab commits
|
||||
\bgitlab\.[^/\s"]*/(?:[^/\s"]+/){2}commits?/[0-9a-f]+\b
|
||||
|
||||
# #includes
|
||||
^\s*#include\s*(?:<.*?>|".*?")
|
||||
|
||||
# #pragma lib
|
||||
^\s*#pragma comment\(lib, ".*?"\)
|
||||
|
||||
# binance
|
||||
accounts\.binance\.com/[a-z/]*oauth/authorize\?[-0-9a-zA-Z&%]*
|
||||
|
||||
@ -220,7 +238,7 @@ accounts\.binance\.com/[a-z/]*oauth/authorize\?[-0-9a-zA-Z&%]*
|
||||
\bmedium\.com/@?[^/\s"]+/[-\w]+
|
||||
|
||||
# microsoft
|
||||
\b(?:https?://|)(?:(?:download\.visualstudio|docs|msdn2?|research)\.microsoft|blogs\.msdn)\.com/[-_a-zA-Z0-9()=./%]*
|
||||
\b(?:https?://|)(?:(?:(?:blogs|download\.visualstudio|docs|msdn2?|research)\.|)microsoft|blogs\.msdn)\.co(?:m|\.\w\w)/[-_a-zA-Z0-9()=./%]*
|
||||
# powerbi
|
||||
\bapp\.powerbi\.com/reportEmbed/[^"' ]*
|
||||
# vs devops
|
||||
@ -394,7 +412,7 @@ ipfs://[0-9a-zA-Z]{3,}
|
||||
\bgetopts\s+(?:"[^"]+"|'[^']+')
|
||||
|
||||
# ANSI color codes
|
||||
(?:\\(?:u00|x)1[Bb]|\x1b|\\u\{1[Bb]\})\[\d+(?:;\d+|)m
|
||||
(?:\\(?:u00|x)1[Bb]|\\03[1-7]|\x1b|\\u\{1[Bb]\})\[\d+(?:;\d+)*m
|
||||
|
||||
# URL escaped characters
|
||||
%[0-9A-F][A-F](?=[A-Za-z])
|
||||
@ -431,10 +449,14 @@ sha\d+:[0-9a-f]*?[a-f]{3,}[0-9a-f]*
|
||||
# pki (base64)
|
||||
LS0tLS1CRUdJT.*
|
||||
|
||||
# C# includes
|
||||
^\s*using [^;]+;
|
||||
|
||||
# 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}|[iu]\d+)\b
|
||||
(?:[\\0][xX]|\\u|[uU]\+|#x?|%23|&H)[0-9_a-fA-FgGrR]*?[a-fA-FgGrR]{2,}[0-9_a-fA-FgGrR]*(?:[uUlL]{0,3}|[iu]\d+)\b
|
||||
|
||||
# integrity
|
||||
integrity=(['"])(?:\s*sha\d+-[-a-zA-Z=;:/0-9+]{40,})+\g{-1}
|
||||
|
||||
@ -452,7 +474,10 @@ integrity=(['"])(?:\s*sha\d+-[-a-zA-Z=;:/0-9+]{40,})+\g{-1}
|
||||
Name\[[^\]]+\]=.*
|
||||
|
||||
# IServiceProvider / isAThing
|
||||
(?:\b|_)(?:(?:ns|)I|isA)(?=(?:[A-Z][a-z]{2,})+(?:[A-Z\d]|\b))
|
||||
(?:(?:\b|_|(?<=[a-z]))I|(?:\b|_)(?:nsI|isA))(?=(?:[A-Z][a-z]{2,})+(?:[A-Z\d]|\b))
|
||||
|
||||
# python
|
||||
\b(?i)py(?!gments|gmy|lon|ramid|ro|th)(?=[a-z]{2,})
|
||||
|
||||
# crypt
|
||||
(['"])\$2[ayb]\$.{56}\g{-1}
|
||||
@ -466,17 +491,14 @@ Name\[[^\]]+\]=.*
|
||||
# machine learning (?)
|
||||
\b(?i)ml(?=[a-z]{2,})
|
||||
|
||||
# python
|
||||
\b(?i)py(?!gments|gmy|lon|ramid|ro|th)(?=[a-z]{2,})
|
||||
|
||||
# scrypt / argon
|
||||
\$(?:scrypt|argon\d+[di]*)\$\S+
|
||||
|
||||
# go.sum
|
||||
\bh1:\S+
|
||||
|
||||
# scala imports
|
||||
^import (?:[\w.]|\{\w*?(?:,\s*(?:\w*|\*))+\})+
|
||||
# imports
|
||||
^import\s+(?:(?:static|type)\s+|)(?:[\w.]|\{\s*\w*?(?:,\s*(?:\w*|\*))+\s*\})+
|
||||
|
||||
# scala modules
|
||||
("[^"]+"\s*%%?\s*){2,3}"[^"]+"
|
||||
@ -485,7 +507,7 @@ Name\[[^\]]+\]=.*
|
||||
image: [-\w./:@]+
|
||||
|
||||
# Docker images
|
||||
^\s*FROM\s+\S+:\S+(?:\s+AS\s+\S+|)
|
||||
^\s*(?i)FROM\s+\S+:\S+(?:\s+AS\s+\S+|)
|
||||
|
||||
# `docker images` REPOSITORY TAG IMAGE ID CREATED SIZE
|
||||
\s*\S+/\S+\s+\S+\s+[0-9a-f]{8,}\s+\d+\s+(?:hour|day|week)s ago\s+[\d.]+[KMGT]B
|
||||
@ -501,6 +523,7 @@ content: (['"])[-a-zA-Z=;:/0-9+]*=\g{-1}
|
||||
# The `(?=.*?")` suffix should limit the false positives rate
|
||||
# printf
|
||||
#%(?:(?:(?:hh?|ll?|[jzt])?[diuoxn]|l?[cs]|L?[fega]|p)(?=[a-z]{2,})|(?:X|L?[FEGA])(?=[a-zA-Z]{2,}))(?!%)(?=[_a-zA-Z]+(?!%)\b)(?=.*?['"])
|
||||
|
||||
# Alternative printf
|
||||
# %s
|
||||
%(?:s(?=[a-z]{2,}))(?!%)(?=[_a-zA-Z]+(?!%[^s])\b)(?=.*?['"])
|
||||
@ -524,7 +547,7 @@ content: (['"])[-a-zA-Z=;:/0-9+]*=\g{-1}
|
||||
# javascript replace regex
|
||||
\.replace\(/[^/\s"]{3,}/[gim]*\s*,
|
||||
# assign regex
|
||||
= /[^*].*?(?:[a-z]{3,}|[A-Z]{3,}|[A-Z][a-z]{2,}).*/[gi]?(?=\W|$)
|
||||
= /[^*].*?(?:[a-z]{3,}|[A-Z]{3,}|[A-Z][a-z]{2,}).*/[gim]*(?=\W|$)
|
||||
# perl regex test
|
||||
[!=]~ (?:/.*/|m\{.*?\}|m<.*?>|m([|!/@#,;']).*?\g{-1})
|
||||
|
||||
@ -538,7 +561,7 @@ perl(?:\s+-[a-zA-Z]\w*)+
|
||||
(?:\d|\bh)to(?!ken)(?=[a-z])|to(?=[adhiklpun]\()
|
||||
|
||||
# Go regular expressions
|
||||
regexp?\.MustCompile\(`[^`]*`\)
|
||||
regexp?\.MustCompile\((?:`[^`]*`|".*"|'.*')\)
|
||||
|
||||
# regex choice
|
||||
\(\?:[^)]+\|[^)]+\)
|
||||
@ -586,7 +609,7 @@ urn:shemas-jetbrains-com
|
||||
# xcode
|
||||
|
||||
# xcodeproject scenes
|
||||
(?:Controller|destination|ID|id)="\w{3}-\w{2}-\w{3}"
|
||||
(?:Controller|destination|(?:first|second)Item|ID|id)="\w{3}-\w{2}-\w{3}"
|
||||
|
||||
# xcode api botches
|
||||
customObjectInstantitationMethod
|
||||
@ -601,14 +624,17 @@ PrependWithABINamepsace
|
||||
\.fa-[-a-z0-9]+
|
||||
|
||||
# bearer auth
|
||||
(['"])[Bb]ear[e][r] .*?\g{-1}
|
||||
(['"])[Bb]ear[e][r] .{3,}?\g{-1}
|
||||
|
||||
# bearer auth
|
||||
\b[Bb]ear[e][r]:? [-a-zA-Z=;:/0-9+.]+
|
||||
\b[Bb]ear[e][r]:? [-a-zA-Z=;:/0-9+.]{3,}
|
||||
|
||||
# basic auth
|
||||
(['"])[Bb]asic [-a-zA-Z=;:/0-9+]{3,}\g{-1}
|
||||
|
||||
# basic auth
|
||||
: [Bb]asic [-a-zA-Z=;:/0-9+.]{3,}
|
||||
|
||||
# base64 encoded content
|
||||
#([`'"])[-a-zA-Z=;:/0-9+]{3,}=\g{-1}
|
||||
# base64 encoded content in xml/sgml
|
||||
@ -620,6 +646,9 @@ PrependWithABINamepsace
|
||||
# base64 encoded pkcs
|
||||
#\bMII[-a-zA-Z=;:/0-9+]+
|
||||
|
||||
# uuencoded
|
||||
#[!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_]{40,}
|
||||
|
||||
# DNS rr data
|
||||
#(?:\d+\s+){3}(?:[-+/=.\w]{2,}\s*){1,2}
|
||||
|
||||
@ -630,7 +659,7 @@ PrependWithABINamepsace
|
||||
\bnumer\b(?=.*denom)
|
||||
|
||||
# Time Zones
|
||||
\b(?:Africa|Atlantic|America|Antarctica|Asia|Australia|Europe|Indian|Pacific)(?:/\w+)+
|
||||
\b(?:Africa|Atlantic|America|Antarctica|Arctic|Asia|Australia|Europe|Indian|Pacific)(?:/[-\w]+)+
|
||||
|
||||
# linux kernel info
|
||||
^(?:bugs|flags|Features)\s+:.*
|
||||
@ -676,11 +705,17 @@ TeX/AMS
|
||||
"varsIgnorePattern": ".+"
|
||||
|
||||
# nolint
|
||||
nolint:\w+
|
||||
nolint:\s*[\w,]+
|
||||
|
||||
# Windows short paths
|
||||
[/\\][^/\\]{5,6}~\d{1,2}(?=[/\\])
|
||||
|
||||
# Windows Resources with accelerators
|
||||
\b[A-Z]&[a-z]+\b(?!;)
|
||||
|
||||
# signed off by
|
||||
(?i)Signed-off-by: .*
|
||||
|
||||
# cygwin paths
|
||||
/cygdrive/[a-zA-Z]/(?:Program Files(?: \(.*?\)| ?)(?:/[-+.~\\/()\w ]+)*|[-+.~\\/()\w])+
|
||||
|
||||
@ -715,29 +750,29 @@ W/"[^"]+"
|
||||
|
||||
# Compiler flags (Unix, Java/Scala)
|
||||
# Use if you have things like `-Pdocker` and want to treat them as `docker`
|
||||
#(?:^|[\t ,>"'`=(])-(?:(?:J-|)[DPWXY]|[Llf])(?=[A-Z]{2,}|[A-Z][a-z]|[a-z]{2,})
|
||||
#(?:^|[\t ,>"'`=(#])-(?:(?:J-|)[DPWXY]|[Llf])(?=[A-Z]{2,}|[A-Z][a-z]|[a-z]{2,})
|
||||
|
||||
# Compiler flags (Windows / PowerShell)
|
||||
# This is a subset of the more general compiler flags pattern.
|
||||
# It avoids matching `-Path` to prevent it from being treated as `ath`
|
||||
#(?:^|[\t ,"'`=(])-(?:[DPL](?=[A-Z]{2,})|[WXYlf](?=[A-Z]{2,}|[A-Z][a-z]|[a-z]{2,}))
|
||||
#(?:^|[\t ,"'`=(#])-(?:[DPL](?=[A-Z]{2,})|[WXYlf](?=[A-Z]{2,}|[A-Z][a-z]|[a-z]{2,}))
|
||||
|
||||
# Compiler flags (linker)
|
||||
,-B
|
||||
|
||||
# libraries
|
||||
#(?:\b|_)lib(?:re(?=office)|)(?!era[lt]|ero|erty|rar(?:i(?:an|es)|y))(?=[a-z])
|
||||
|
||||
# WWNN/WWPN (NAA identifiers)
|
||||
\b(?:0x)?10[0-9a-f]{14}\b|\b(?:0x|3)?[25][0-9a-f]{15}\b|\b(?:0x|3)?6[0-9a-f]{31}\b
|
||||
#(?:\b|_)[Ll]ib(?:re(?=office)|)(?!era[lt]|ero|erty|rar(?:i(?:an|es)|y))(?=[a-z])
|
||||
|
||||
# iSCSI iqn (approximate regex)
|
||||
\biqn\.[0-9]{4}-[0-9]{2}(?:[\.-][a-z][a-z0-9]*)*\b
|
||||
|
||||
# WWNN/WWPN (NAA identifiers)
|
||||
\b(?:0x)?10[0-9a-f]{14}\b|\b(?:0x|3)?[25][0-9a-f]{15}\b|\b(?:0x|3)?6[0-9a-f]{31}\b
|
||||
|
||||
# curl arguments
|
||||
\b(?:\\n|)curl(?:\.exe|)(?:\s+-[a-zA-Z]{1,2}\b)*(?:\s+-[a-zA-Z]{3,})(?:\s+-[a-zA-Z]+)*
|
||||
# set arguments
|
||||
\b(?:bash|sh|set)(?:\s+-[abefimouxE]{1,2})*\s+-[abefimouxE]{3,}(?:\s+-[abefimouxE]+)*
|
||||
\b(?:bash|sh|set)(?:\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...
|
||||
|
||||
5
.github/actions/spelling/excludes.txt
vendored
5
.github/actions/spelling/excludes.txt
vendored
@ -97,7 +97,7 @@ Resources/(?!en)
|
||||
^doc/reference/UTF8-torture-test\.txt$
|
||||
^doc/reference/windows-terminal-logo\.ans$
|
||||
^NOTICE.md
|
||||
^oss/
|
||||
^oss/.*?/
|
||||
^samples/PixelShaders/Screenshots/
|
||||
^src/cascadia/TerminalSettingsEditor/SegoeFluentIconList.h$
|
||||
^src/interactivity/onecore/BgfxEngine\.
|
||||
@ -121,8 +121,8 @@ Resources/(?!en)
|
||||
^tools/ReleaseEngineering/ServicingPipeline\.ps1$
|
||||
^XamlStyler\.json$
|
||||
^\.github/actions/spelling/
|
||||
^\.github/workflows/spelling\d*\.yml$
|
||||
^\.vsconfig$
|
||||
^\Q.github/workflows/spelling.yml\E$
|
||||
^\Qbuild/config/release.gdnbaselines\E$
|
||||
^\Qdep/WinAppDriver/EULA.rtf\E$
|
||||
^\Qdoc/reference/windows-terminal-logo.ans\E$
|
||||
@ -133,3 +133,4 @@ Resources/(?!en)
|
||||
^\Qsrc/terminal/parser/ft_fuzzwrapper/run.bat\E$
|
||||
^\Qsrc/tools/lnkd/lnkd.bat\E$
|
||||
^\Qsrc/tools/pixels/pixels.bat\E$
|
||||
^\Qsrc/cascadia/ut_app/FzfTests.cpp\E$
|
||||
|
||||
41
.github/actions/spelling/expect/alphabet.txt
vendored
41
.github/actions/spelling/expect/alphabet.txt
vendored
@ -1,38 +1,19 @@
|
||||
AAAAAABBBBBBCCC
|
||||
AAAAABBBBBBCCC
|
||||
abcd
|
||||
ABCDEFGHIJ
|
||||
abcdefghijk
|
||||
ABCDEFGHIJKLMNOPQRS
|
||||
ABCDEFGHIJKLMNOPQRST
|
||||
ABCDEFGHIJKLMNOPQRSTUVWXY
|
||||
ABCG
|
||||
ABE
|
||||
abf
|
||||
BBBBB
|
||||
BBBBBCCC
|
||||
BBBBCCCCC
|
||||
AZZ
|
||||
BBDM
|
||||
BBGGRR
|
||||
EFG
|
||||
CBN
|
||||
cbt
|
||||
Ccc
|
||||
cch
|
||||
efg
|
||||
EFGh
|
||||
efgh
|
||||
KLMNOQQQQQQQQQQ
|
||||
QQQQQQQQQQABCDEFGHIJ
|
||||
QQQQQQQQQQABCDEFGHIJKLMNOPQRS
|
||||
QQQQQQQQQQABCDEFGHIJKLMNOPQRSTQQQQQQQQQ
|
||||
QQQQQQQQQQABCDEFGHIJKLMNOPQRSTQQQQQQQQQQ
|
||||
QQQQQQQQQQABCDEFGHIJPQRST
|
||||
QQQQQQQQQQABCDEFGHIJPQRSTQQQQQQQQQQ
|
||||
fdw
|
||||
fesb
|
||||
ffd
|
||||
FFFD
|
||||
qwerty
|
||||
qwertyuiopasdfg
|
||||
ZAAZZ
|
||||
ZABBZ
|
||||
ZBAZZ
|
||||
ZBBBZ
|
||||
ZBBZZ
|
||||
ZYXWVUT
|
||||
ZZBBZ
|
||||
ZZZBB
|
||||
ZZZBZ
|
||||
ZZZZZ
|
||||
zzf
|
||||
|
||||
191
.github/actions/spelling/expect/expect.txt
vendored
191
.github/actions/spelling/expect/expect.txt
vendored
@ -2,7 +2,7 @@ aaaaabbb
|
||||
aabbcc
|
||||
ABANDONFONT
|
||||
abbcc
|
||||
ABCF
|
||||
abcc
|
||||
abgr
|
||||
ABORTIFHUNG
|
||||
ACCESSTOKEN
|
||||
@ -26,13 +26,11 @@ AImpl
|
||||
AInplace
|
||||
ALIGNRIGHT
|
||||
allocing
|
||||
allocs
|
||||
alpc
|
||||
ALTERNATENAME
|
||||
ALTF
|
||||
ALTNUMPAD
|
||||
ALWAYSTIP
|
||||
aml
|
||||
ansicpg
|
||||
ANSISYS
|
||||
ANSISYSRC
|
||||
@ -49,22 +47,17 @@ APIENTRY
|
||||
apiset
|
||||
APPBARDATA
|
||||
appcontainer
|
||||
appium
|
||||
appletname
|
||||
applicationmodel
|
||||
APPLMODAL
|
||||
Applocal
|
||||
appmodel
|
||||
appshellintegration
|
||||
APPWINDOW
|
||||
APPXMANIFESTVERSION
|
||||
APrep
|
||||
apsect
|
||||
APSTUDIO
|
||||
archeologists
|
||||
Argb
|
||||
ARRAYSIZE
|
||||
ARROWKEYS
|
||||
asan
|
||||
ASBSET
|
||||
ASetting
|
||||
ASingle
|
||||
@ -72,11 +65,11 @@ ASYNCDONTCARE
|
||||
ASYNCWINDOWPOS
|
||||
atch
|
||||
ATest
|
||||
atg
|
||||
aumid
|
||||
Authenticode
|
||||
AUTOBUDDY
|
||||
AUTOCHECKBOX
|
||||
autocrlf
|
||||
autohide
|
||||
AUTOHSCROLL
|
||||
automagically
|
||||
@ -86,16 +79,13 @@ autoscrolling
|
||||
Autowrap
|
||||
AVerify
|
||||
awch
|
||||
AZCOPY
|
||||
azurecr
|
||||
AZZ
|
||||
backgrounded
|
||||
Backgrounder
|
||||
backgrounding
|
||||
backported
|
||||
backstory
|
||||
Bazz
|
||||
bbb
|
||||
bbccb
|
||||
BBDM
|
||||
bbwe
|
||||
@ -123,13 +113,13 @@ bitmasks
|
||||
BITOPERATION
|
||||
BKCOLOR
|
||||
BKGND
|
||||
BKMK
|
||||
Bksp
|
||||
Blt
|
||||
blu
|
||||
BLUESCROLL
|
||||
bmi
|
||||
bodgy
|
||||
BODGY
|
||||
BOLDFONT
|
||||
Borland
|
||||
boutput
|
||||
@ -148,9 +138,7 @@ buflen
|
||||
buildsystems
|
||||
buildtransitive
|
||||
BValue
|
||||
bytebuffer
|
||||
cac
|
||||
cacafire
|
||||
Cacafire
|
||||
CALLCONV
|
||||
CANDRABINDU
|
||||
capslock
|
||||
@ -161,12 +149,6 @@ catid
|
||||
cazamor
|
||||
CBash
|
||||
cbiex
|
||||
CBN
|
||||
cbt
|
||||
Ccc
|
||||
CCCBB
|
||||
CCCDDD
|
||||
cch
|
||||
CCHAR
|
||||
CCmd
|
||||
ccolor
|
||||
@ -181,15 +163,14 @@ cfie
|
||||
cfiex
|
||||
cfte
|
||||
CFuzz
|
||||
cgmanifest
|
||||
cgscrn
|
||||
chafa
|
||||
changelists
|
||||
CHARSETINFO
|
||||
chh
|
||||
chshdng
|
||||
CHT
|
||||
CLASSSTRING
|
||||
CLE
|
||||
cleartype
|
||||
CLICKACTIVE
|
||||
clickdown
|
||||
@ -212,9 +193,7 @@ cmw
|
||||
CNL
|
||||
cnn
|
||||
Codeflow
|
||||
codenav
|
||||
codepages
|
||||
codepath
|
||||
coinit
|
||||
colorizing
|
||||
COLORONCOLOR
|
||||
@ -226,13 +205,8 @@ colortbl
|
||||
colortest
|
||||
colortool
|
||||
COLORVALUE
|
||||
combaseapi
|
||||
comctl
|
||||
commandline
|
||||
commctrl
|
||||
commdlg
|
||||
COMMITID
|
||||
componentization
|
||||
conapi
|
||||
conattrs
|
||||
conbufferout
|
||||
@ -250,7 +224,6 @@ conintegrityuwp
|
||||
coninteractivitybase
|
||||
coninteractivityonecore
|
||||
coninteractivitywin
|
||||
conio
|
||||
coniosrv
|
||||
CONKBD
|
||||
conlibk
|
||||
@ -263,13 +236,13 @@ conpropsp
|
||||
conpty
|
||||
conptylib
|
||||
conserv
|
||||
consoleaccessibility
|
||||
consoleapi
|
||||
CONSOLECONTROL
|
||||
CONSOLEENDTASK
|
||||
consolegit
|
||||
consolehost
|
||||
CONSOLEIME
|
||||
consoleinternal
|
||||
CONSOLESETFOREGROUND
|
||||
consoletaeftemplates
|
||||
consoleuwp
|
||||
@ -277,7 +250,6 @@ Consolewait
|
||||
CONSOLEWINDOWOWNER
|
||||
consrv
|
||||
constexprable
|
||||
constness
|
||||
contentfiles
|
||||
conterm
|
||||
contsf
|
||||
@ -311,7 +283,6 @@ csbi
|
||||
csbiex
|
||||
CSHORT
|
||||
Cspace
|
||||
csrmsg
|
||||
CSRSS
|
||||
csrutil
|
||||
CSTYLE
|
||||
@ -368,16 +339,14 @@ DBGFONTS
|
||||
DBGOUTPUT
|
||||
dbh
|
||||
dblclk
|
||||
DBUILD
|
||||
Dcd
|
||||
DColor
|
||||
dcommon
|
||||
DCOMMON
|
||||
DComposition
|
||||
DDDCCC
|
||||
dde
|
||||
DDESHARE
|
||||
DDevice
|
||||
DEADCHAR
|
||||
dealloc
|
||||
Debian
|
||||
debugtype
|
||||
DECAC
|
||||
@ -482,18 +451,16 @@ DELAYLOAD
|
||||
DELETEONRELEASE
|
||||
depersist
|
||||
deprioritized
|
||||
deserializers
|
||||
desktopwindowxamlsource
|
||||
devicecode
|
||||
Dext
|
||||
DFactory
|
||||
DFF
|
||||
dialogbox
|
||||
DINLINE
|
||||
directio
|
||||
DIRECTX
|
||||
DISABLEDELAYEDEXPANSION
|
||||
DISABLENOSCROLL
|
||||
DISPATCHNOTIFY
|
||||
DISPLAYATTRIBUTE
|
||||
DISPLAYCHANGE
|
||||
distros
|
||||
@ -530,9 +497,10 @@ dsm
|
||||
dsound
|
||||
DSSCL
|
||||
DSwap
|
||||
DTest
|
||||
DTo
|
||||
DTTERM
|
||||
DUNICODE
|
||||
DUNIT
|
||||
dup'ed
|
||||
dvi
|
||||
dwl
|
||||
@ -542,8 +510,6 @@ dwmapi
|
||||
DWORDs
|
||||
dwrite
|
||||
dxgi
|
||||
dxgidwm
|
||||
dxinterop
|
||||
dxsm
|
||||
dxttbmp
|
||||
Dyreen
|
||||
@ -557,7 +523,6 @@ EDITKEYS
|
||||
EDITTEXT
|
||||
EDITUPDATE
|
||||
Efast
|
||||
efghijklmn
|
||||
EHsc
|
||||
EINS
|
||||
ELEMENTNOTAVAILABLE
|
||||
@ -566,7 +531,6 @@ enabledelayedexpansion
|
||||
ENDCAP
|
||||
endptr
|
||||
ENTIREBUFFER
|
||||
entrypoints
|
||||
ENU
|
||||
ENUMLOGFONT
|
||||
ENUMLOGFONTEX
|
||||
@ -581,7 +545,6 @@ esrp
|
||||
ESV
|
||||
ETW
|
||||
EUDC
|
||||
EVENTID
|
||||
eventing
|
||||
evflags
|
||||
evt
|
||||
@ -603,16 +566,6 @@ FACESIZE
|
||||
FAILIFTHERE
|
||||
fastlink
|
||||
fcharset
|
||||
FDEA
|
||||
fdw
|
||||
FECF
|
||||
FEEF
|
||||
fesb
|
||||
FFAF
|
||||
ffd
|
||||
FFDE
|
||||
FFFD
|
||||
FFFDb
|
||||
fgbg
|
||||
FGCOLOR
|
||||
FGHIJ
|
||||
@ -630,7 +583,6 @@ FINDDLG
|
||||
FINDDOWN
|
||||
FINDREGEX
|
||||
FINDSTRINGEXACT
|
||||
FINDUP
|
||||
FITZPATRICK
|
||||
FIXEDFILEINFO
|
||||
Flg
|
||||
@ -651,6 +603,7 @@ FONTSTRING
|
||||
FONTTYPE
|
||||
FONTWIDTH
|
||||
FONTWINDOW
|
||||
foob
|
||||
FORCEOFFFEEDBACK
|
||||
FORCEONFEEDBACK
|
||||
FRAMECHANGED
|
||||
@ -664,13 +617,14 @@ Ftm
|
||||
Fullscreens
|
||||
Fullwidth
|
||||
FUNCTIONCALL
|
||||
fuzzer
|
||||
fuzzmain
|
||||
fuzzmap
|
||||
fuzzwrapper
|
||||
fuzzyfinder
|
||||
fwdecl
|
||||
fwe
|
||||
fwlink
|
||||
fzf
|
||||
gci
|
||||
gcx
|
||||
gdi
|
||||
@ -726,6 +680,7 @@ GETWHEELSCROLLCHARS
|
||||
GETWHEELSCROLLLINES
|
||||
Gfun
|
||||
gfx
|
||||
gfycat
|
||||
GGI
|
||||
GHgh
|
||||
GHIJK
|
||||
@ -746,6 +701,7 @@ Greyscale
|
||||
gridline
|
||||
gset
|
||||
gsl
|
||||
Guake
|
||||
guc
|
||||
GUIDATOM
|
||||
GValue
|
||||
@ -775,7 +731,6 @@ hfind
|
||||
hfont
|
||||
hfontresource
|
||||
hglobal
|
||||
hhh
|
||||
hhook
|
||||
hhx
|
||||
HIBYTE
|
||||
@ -791,7 +746,6 @@ HKCU
|
||||
hkey
|
||||
hkl
|
||||
HKLM
|
||||
hlocal
|
||||
hlsl
|
||||
HMB
|
||||
HMK
|
||||
@ -810,7 +764,6 @@ HREDRAW
|
||||
hresult
|
||||
hscroll
|
||||
hstr
|
||||
hstring
|
||||
HTBOTTOMLEFT
|
||||
HTBOTTOMRIGHT
|
||||
HTCAPTION
|
||||
@ -839,14 +792,12 @@ idl
|
||||
idllib
|
||||
IDOK
|
||||
IDR
|
||||
idth
|
||||
IDTo
|
||||
IDXGI
|
||||
IFACEMETHODIMP
|
||||
ification
|
||||
IGNORELANGUAGE
|
||||
iid
|
||||
IInput
|
||||
IIo
|
||||
ILC
|
||||
ILCo
|
||||
@ -860,20 +811,18 @@ INFOEX
|
||||
inheritcursor
|
||||
INITCOMMONCONTROLSEX
|
||||
INITDIALOG
|
||||
initguid
|
||||
INITGUID
|
||||
INITMENU
|
||||
inkscape
|
||||
INLINEPREFIX
|
||||
inproc
|
||||
Inputkeyinfo
|
||||
inputpaneinterop
|
||||
Inputreadhandledata
|
||||
INPUTSCOPE
|
||||
INSERTMODE
|
||||
INTERACTIVITYBASE
|
||||
INTERCEPTCOPYPASTE
|
||||
INTERNALNAME
|
||||
Interner
|
||||
intsafe
|
||||
INVALIDARG
|
||||
INVALIDATERECT
|
||||
@ -885,8 +834,6 @@ itermcolors
|
||||
itf
|
||||
Ith
|
||||
IUI
|
||||
IUnknown
|
||||
ivalid
|
||||
IWIC
|
||||
IXP
|
||||
jconcpp
|
||||
@ -910,7 +857,6 @@ keydowns
|
||||
KEYFIRST
|
||||
KEYLAST
|
||||
Keymapping
|
||||
keyscan
|
||||
keystate
|
||||
keyups
|
||||
Kickstart
|
||||
@ -920,10 +866,6 @@ kinda
|
||||
KIYEOK
|
||||
KLF
|
||||
KLMNO
|
||||
KLMNOPQRST
|
||||
KLMNOPQRSTQQQQQ
|
||||
KLMNOPQRSTUVWXY
|
||||
KLMNOPQRSTY
|
||||
KOK
|
||||
KPRIORITY
|
||||
KVM
|
||||
@ -945,6 +887,8 @@ LCONTROL
|
||||
LCTRL
|
||||
lcx
|
||||
LEFTALIGN
|
||||
libsancov
|
||||
libtickit
|
||||
LIMITTEXT
|
||||
LINEDOWN
|
||||
LINESELECTION
|
||||
@ -1049,6 +993,7 @@ MBUTTONDOWN
|
||||
MBUTTONUP
|
||||
mdmerge
|
||||
MDs
|
||||
mdtauk
|
||||
MEASUREITEM
|
||||
megamix
|
||||
memallocator
|
||||
@ -1058,7 +1003,6 @@ MENUCONTROL
|
||||
MENUDROPALIGNMENT
|
||||
MENUITEMINFO
|
||||
MENUSELECT
|
||||
messageext
|
||||
metaproj
|
||||
Mgrs
|
||||
microsoftpublicsymbols
|
||||
@ -1075,11 +1019,9 @@ minwindef
|
||||
MMBB
|
||||
mmcc
|
||||
MMCPL
|
||||
mmsystem
|
||||
MNC
|
||||
MNOPQ
|
||||
MNOPQR
|
||||
MNOPQRSTUVWXY
|
||||
MODALFRAME
|
||||
MODERNCORE
|
||||
MONITORINFO
|
||||
@ -1091,7 +1033,6 @@ MOUSEHWHEEL
|
||||
MOVESTART
|
||||
msb
|
||||
msbuildcache
|
||||
msctf
|
||||
msctls
|
||||
msdata
|
||||
MSDL
|
||||
@ -1106,10 +1047,9 @@ MSGSELECTMODE
|
||||
msiexec
|
||||
MSIL
|
||||
msix
|
||||
msrc
|
||||
MSRC
|
||||
MSVCRTD
|
||||
MTSM
|
||||
Munged
|
||||
murmurhash
|
||||
muxes
|
||||
myapplet
|
||||
@ -1148,7 +1088,6 @@ Newtonsoft
|
||||
NEXTLINE
|
||||
nfe
|
||||
NLSMODE
|
||||
nnn
|
||||
NOACTIVATE
|
||||
NOAPPLYNOW
|
||||
NOCLIP
|
||||
@ -1201,40 +1140,31 @@ NPFS
|
||||
nrcs
|
||||
NSTATUS
|
||||
ntapi
|
||||
ntcon
|
||||
ntcsrdll
|
||||
ntdef
|
||||
NTDEV
|
||||
ntdll
|
||||
ntifs
|
||||
ntlpcapi
|
||||
ntm
|
||||
ntrtl
|
||||
ntstatus
|
||||
nttree
|
||||
nturtl
|
||||
ntuser
|
||||
NTVDM
|
||||
ntverp
|
||||
nugetversions
|
||||
NUKTA
|
||||
nullness
|
||||
nullonfailure
|
||||
nullopts
|
||||
numlock
|
||||
NUMSCROLL
|
||||
NUnit
|
||||
nupkg
|
||||
NVIDIA
|
||||
NVT
|
||||
OACR
|
||||
objbase
|
||||
ocolor
|
||||
oemcp
|
||||
OEMFONT
|
||||
OEMFORMAT
|
||||
OEMs
|
||||
offboarded
|
||||
OLEAUT
|
||||
OLECHAR
|
||||
onebranch
|
||||
@ -1248,6 +1178,7 @@ onecoreuuid
|
||||
ONECOREWINDOWS
|
||||
onehalf
|
||||
oneseq
|
||||
oob
|
||||
openbash
|
||||
opencode
|
||||
opencon
|
||||
@ -1283,7 +1214,6 @@ PALPC
|
||||
pankaj
|
||||
parentable
|
||||
PATCOPY
|
||||
pathcch
|
||||
PATTERNID
|
||||
pbstr
|
||||
pcb
|
||||
@ -1338,7 +1268,6 @@ phicon
|
||||
phwnd
|
||||
pidl
|
||||
PIDLIST
|
||||
pids
|
||||
pii
|
||||
piml
|
||||
pimpl
|
||||
@ -1363,11 +1292,9 @@ POINTERUPDATE
|
||||
POINTSLIST
|
||||
policheck
|
||||
POLYTEXTW
|
||||
poppack
|
||||
POPUPATTR
|
||||
popups
|
||||
PORFLG
|
||||
positionals
|
||||
POSTCHARBREAKS
|
||||
POSX
|
||||
POSXSCROLL
|
||||
@ -1400,11 +1327,9 @@ PREVLINE
|
||||
prg
|
||||
pri
|
||||
prioritization
|
||||
processenv
|
||||
processhost
|
||||
PROCESSINFOCLASS
|
||||
PRODEXT
|
||||
Productize
|
||||
PROPERTYID
|
||||
PROPERTYKEY
|
||||
propertyval
|
||||
@ -1416,16 +1341,12 @@ propsys
|
||||
PROPTITLE
|
||||
propvar
|
||||
propvariant
|
||||
propvarutil
|
||||
psa
|
||||
PSCRED
|
||||
PSECURITY
|
||||
pseudoconsole
|
||||
pseudoterminal
|
||||
psh
|
||||
pshn
|
||||
PSHNOTIFY
|
||||
pshpack
|
||||
PSINGLE
|
||||
psl
|
||||
psldl
|
||||
@ -1497,8 +1418,6 @@ REGISTERVDM
|
||||
regkey
|
||||
REGSTR
|
||||
RELBINPATH
|
||||
remoting
|
||||
renamer
|
||||
rendersize
|
||||
reparented
|
||||
reparenting
|
||||
@ -1533,19 +1452,16 @@ RIGHTALIGN
|
||||
RIGHTBUTTON
|
||||
riid
|
||||
ris
|
||||
roadmap
|
||||
robomac
|
||||
rodata
|
||||
rosetta
|
||||
RRF
|
||||
rrr
|
||||
RRRGGGBB
|
||||
rsas
|
||||
rtcore
|
||||
RTEXT
|
||||
RTLREADING
|
||||
Rtn
|
||||
ruleset
|
||||
runas
|
||||
RUNDLL
|
||||
runformat
|
||||
@ -1563,7 +1479,6 @@ rvpa
|
||||
RWIN
|
||||
rxvt
|
||||
safemath
|
||||
sancov
|
||||
sba
|
||||
SBCS
|
||||
SBCSDBCS
|
||||
@ -1591,10 +1506,8 @@ SCROLLSCREENBUFFER
|
||||
scursor
|
||||
sddl
|
||||
SDKDDK
|
||||
securityappcontainer
|
||||
segfault
|
||||
SELCHANGE
|
||||
SELECTALL
|
||||
SELECTEDFONT
|
||||
SELECTSTRING
|
||||
Selfhosters
|
||||
@ -1638,14 +1551,10 @@ SFUI
|
||||
sgr
|
||||
SHCo
|
||||
shcore
|
||||
shellapi
|
||||
shellex
|
||||
shellscalingapi
|
||||
SHFILEINFO
|
||||
SHGFI
|
||||
SHIFTJIS
|
||||
shlguid
|
||||
shlobj
|
||||
shlwapi
|
||||
SHORTPATH
|
||||
SHOWCURSOR
|
||||
@ -1683,7 +1592,6 @@ snapcy
|
||||
snk
|
||||
SOLIDBOX
|
||||
Solutiondir
|
||||
somefile
|
||||
sourced
|
||||
SRCAND
|
||||
SRCCODEPAGE
|
||||
@ -1715,9 +1623,8 @@ STDEXT
|
||||
STDMETHODCALLTYPE
|
||||
STDMETHODIMP
|
||||
STGM
|
||||
Stringable
|
||||
STRINGTABLE
|
||||
strsafe
|
||||
STRSAFE
|
||||
STUBHEAD
|
||||
STUVWX
|
||||
stylecop
|
||||
@ -1743,32 +1650,27 @@ SYSLIB
|
||||
SYSLINK
|
||||
SYSMENU
|
||||
sysparams
|
||||
sysparamsext
|
||||
SYSTEMHAND
|
||||
SYSTEMMENU
|
||||
SYSTEMTIME
|
||||
tabview
|
||||
TAdd
|
||||
taef
|
||||
TARG
|
||||
targetentrypoint
|
||||
TARGETLIBS
|
||||
TARGETNAME
|
||||
targetver
|
||||
TBase
|
||||
tbc
|
||||
tbi
|
||||
Tbl
|
||||
TBM
|
||||
tchar
|
||||
TCHAR
|
||||
TCHFORMAT
|
||||
TCI
|
||||
tcommands
|
||||
tdbuild
|
||||
Tdd
|
||||
TDelegated
|
||||
TDP
|
||||
tearoff
|
||||
Teb
|
||||
Techo
|
||||
tellp
|
||||
@ -1778,7 +1680,6 @@ terminalinput
|
||||
terminalrenderdata
|
||||
TERMINALSCROLLING
|
||||
terminfo
|
||||
TEs
|
||||
testcon
|
||||
testd
|
||||
testenvs
|
||||
@ -1790,7 +1691,6 @@ TESTNULL
|
||||
testpass
|
||||
testpasses
|
||||
TEXCOORD
|
||||
TExpected
|
||||
textattribute
|
||||
TEXTATTRIBUTEID
|
||||
textboxes
|
||||
@ -1801,39 +1701,28 @@ TEXTMETRIC
|
||||
TEXTMETRICW
|
||||
textmode
|
||||
texttests
|
||||
TFunction
|
||||
THUMBPOSITION
|
||||
THUMBTRACK
|
||||
tickit
|
||||
TIcon
|
||||
tilunittests
|
||||
titlebars
|
||||
TITLEISLINKNAME
|
||||
TJson
|
||||
TLambda
|
||||
TLDP
|
||||
TLEN
|
||||
TMAE
|
||||
TMPF
|
||||
TMult
|
||||
tmultiple
|
||||
TODOs
|
||||
tofrom
|
||||
tokenhelpers
|
||||
toolbars
|
||||
TOOLINFO
|
||||
TOOLWINDOW
|
||||
TOPDOWNDIB
|
||||
TOpt
|
||||
tosign
|
||||
touchpad
|
||||
tracelogging
|
||||
traceviewpp
|
||||
trackbar
|
||||
trackpad
|
||||
transitioning
|
||||
Trd
|
||||
TREX
|
||||
triaged
|
||||
triaging
|
||||
TRIMZEROHEADINGS
|
||||
@ -1841,9 +1730,7 @@ trx
|
||||
tsa
|
||||
tsgr
|
||||
tsm
|
||||
TStr
|
||||
TSTRFORMAT
|
||||
TSub
|
||||
TTBITMAP
|
||||
TTFONT
|
||||
TTFONTLIST
|
||||
@ -1852,7 +1739,6 @@ TTo
|
||||
tvpp
|
||||
tvtseq
|
||||
TYUI
|
||||
UAC
|
||||
uap
|
||||
uapadmin
|
||||
UAX
|
||||
@ -1888,7 +1774,6 @@ unk
|
||||
unknwn
|
||||
UNORM
|
||||
unparseable
|
||||
Unregistering
|
||||
untextured
|
||||
UPDATEDISPLAY
|
||||
UPDOWN
|
||||
@ -1906,7 +1791,6 @@ USEFILLATTRIBUTE
|
||||
USEGLYPHCHARS
|
||||
USEHICON
|
||||
USEPOSITION
|
||||
USERDATA
|
||||
userdpiapi
|
||||
Userp
|
||||
userprivapi
|
||||
@ -1919,7 +1803,6 @@ USRDLL
|
||||
utext
|
||||
utr
|
||||
UVWXY
|
||||
UVWXYZ
|
||||
uwa
|
||||
uwp
|
||||
uwu
|
||||
@ -1928,17 +1811,16 @@ Vanara
|
||||
vararg
|
||||
vclib
|
||||
vcxitems
|
||||
vectorize
|
||||
VERCTRL
|
||||
VERTBAR
|
||||
VFT
|
||||
vga
|
||||
vgaoem
|
||||
viewkind
|
||||
viewports
|
||||
VIRAMA
|
||||
Virt
|
||||
VIRTTERM
|
||||
visualstudiosdk
|
||||
vkey
|
||||
VKKEYSCAN
|
||||
VMs
|
||||
@ -1997,7 +1879,6 @@ wekyb
|
||||
wewoad
|
||||
wex
|
||||
wextest
|
||||
wextestclass
|
||||
WFill
|
||||
wfopen
|
||||
WHelper
|
||||
@ -2008,9 +1889,7 @@ Wiggum
|
||||
wil
|
||||
WImpl
|
||||
WINAPI
|
||||
winbase
|
||||
winbasep
|
||||
wincodec
|
||||
wincon
|
||||
winconp
|
||||
winconpty
|
||||
@ -2025,10 +1904,8 @@ windll
|
||||
WINDOWALPHA
|
||||
windowdpiapi
|
||||
WINDOWEDGE
|
||||
windowext
|
||||
WINDOWINFO
|
||||
windowio
|
||||
windowmetrics
|
||||
WINDOWPLACEMENT
|
||||
windowpos
|
||||
WINDOWPOSCHANGED
|
||||
@ -2036,20 +1913,15 @@ WINDOWPOSCHANGING
|
||||
windowproc
|
||||
windowrect
|
||||
windowsapp
|
||||
windowsinternalstring
|
||||
WINDOWSIZE
|
||||
windowsshell
|
||||
windowsterminal
|
||||
windowsx
|
||||
windowtheme
|
||||
winevent
|
||||
wingdi
|
||||
winget
|
||||
wingetcreate
|
||||
WINIDE
|
||||
winioctl
|
||||
winmd
|
||||
winmeta
|
||||
winmgr
|
||||
winmm
|
||||
WINMSAPP
|
||||
@ -2059,8 +1931,8 @@ WInplace
|
||||
winres
|
||||
winrt
|
||||
winternl
|
||||
winui
|
||||
winuser
|
||||
winuserp
|
||||
WINVER
|
||||
wistd
|
||||
wmain
|
||||
@ -2097,10 +1969,9 @@ WRITECONSOLEINPUT
|
||||
WRITECONSOLEOUTPUT
|
||||
WRITECONSOLEOUTPUTSTRING
|
||||
wrkstr
|
||||
wrl
|
||||
WRL
|
||||
wrp
|
||||
WRunoff
|
||||
wsl
|
||||
WSLENV
|
||||
wstr
|
||||
wstrings
|
||||
@ -2113,7 +1984,7 @@ wtof
|
||||
WTs
|
||||
WTSOFTFONT
|
||||
wtw
|
||||
wtypes
|
||||
Wtypes
|
||||
WUX
|
||||
WVerify
|
||||
WWith
|
||||
@ -2132,7 +2003,6 @@ XBUTTONDOWN
|
||||
XBUTTONUP
|
||||
XCast
|
||||
XCENTER
|
||||
xchar
|
||||
xcopy
|
||||
XCount
|
||||
xdy
|
||||
@ -2142,6 +2012,7 @@ XFG
|
||||
XFile
|
||||
XFORM
|
||||
XIn
|
||||
xkcd
|
||||
XManifest
|
||||
XMath
|
||||
XNamespace
|
||||
@ -2168,7 +2039,6 @@ YLimit
|
||||
YPan
|
||||
YSubstantial
|
||||
YVIRTUALSCREEN
|
||||
Zab
|
||||
zabcd
|
||||
Zabcdefghijklmn
|
||||
Zabcdefghijklmnopqrstuvwxyz
|
||||
@ -2177,4 +2047,3 @@ ZCtrl
|
||||
ZWJs
|
||||
ZYXWVU
|
||||
ZYXWVUTd
|
||||
zzf
|
||||
|
||||
232
.github/actions/spelling/line_forbidden.patterns
vendored
232
.github/actions/spelling/line_forbidden.patterns
vendored
@ -8,6 +8,24 @@
|
||||
# you might not want to check in code where you skip all the other tests.
|
||||
#\bfit\(
|
||||
|
||||
# English does not use a hyphen between adverbs and nouns
|
||||
# https://twitter.com/nyttypos/status/1894815686192685239
|
||||
(?:^|\s)[A-Z]?[a-z]+ly-(?=[a-z]{3,})(?:[.,?!]?\s|$)
|
||||
|
||||
# Don't use `requires that` + `to be`
|
||||
# https://twitter.com/nyttypos/status/1894816551435641027
|
||||
\brequires that \w+\b[^.]+to be\b
|
||||
|
||||
# A fully parenthetical sentence’s period goes inside the parentheses, not outside.
|
||||
# https://twitter.com/nyttypos/status/1898844061873639490
|
||||
\([A-Z][a-z]{2,}(?: [a-z]+){3,}\)\.\s
|
||||
|
||||
# Complete sentences shouldn't be in the middle of another sentence as a parenthetical.
|
||||
(?<!\.)(?<!\betc)\.\),
|
||||
|
||||
# Complete sentences in parentheticals should not have a space before the period.
|
||||
\s\.\)(?!.*\}\})
|
||||
|
||||
# Should be `HH:MM:SS`
|
||||
\bHH:SS:MM\b
|
||||
|
||||
@ -24,18 +42,52 @@
|
||||
# Should be `a priori` or `and prior`
|
||||
(?i)(?<!posteriori)\sand priori\s
|
||||
|
||||
# Should be `a`
|
||||
\san (?=(?:[b-df-gj-np-rtv-xz]|h(?!our|sl|tml|ttp)|s(?!sh|vg))[a-z])
|
||||
|
||||
# Should only be one of `a`, `an`, or `the`
|
||||
\b(?:(?:an?|the)\s+){2,}\b
|
||||
|
||||
# Should only be `are` or `can`, not both
|
||||
\b(?:(?:are|can)\s+){2,}\b
|
||||
|
||||
# Should probably be `ABCDEFGHIJKLMNOPQRSTUVWXYZ`
|
||||
(?i)(?!ABCDEFGHIJKLMNOPQRSTUVWXYZ)ABC[A-Z]{21}YZ
|
||||
|
||||
# Should be `an`
|
||||
(?<!\b[Ii] )\bam\b
|
||||
|
||||
# Should be `anymore`
|
||||
\bany more[,.]
|
||||
|
||||
# Should be `Ask`
|
||||
(?:^|[.?]\s+)As\s+[A-Z][a-z]{2,}\s[^.?]*?(?:how|if|wh\w+)\b
|
||||
|
||||
# Should be `at one fell swoop`
|
||||
# and only when talking about killing, not some other completion
|
||||
# Act 4 Scene 3, Macbeth
|
||||
# https://www.opensourceshakespeare.org/views/plays/play_view.php?WorkID=macbeth&Act=4&Scene=3&Scope=scene
|
||||
\bin one fell s[lw]?oop\b
|
||||
|
||||
# Should be `'`
|
||||
(?i)\b(?:(?:i|s?he|they|what|who|you)"ll|(?:are|ca|did|do|does|ha[ds]|have|is|should|were|wo|would)n"t|(?:s?he|let|that|there|what|where|who)"s|(?:i|they|we|what|who|you)"ve)\b
|
||||
(?i)\b(?:(?:i|s?he|they|what|who|you)[`"]ll|(?:are|ca|did|do|does|ha[ds]|have|is|should|were|wo|would)n[`"]t|(?:s?he|let|that|there|what|where|who)[`"]s|(?:i|they|we|what|who|you)[`"]ve)\b
|
||||
|
||||
# Should be `background` / `intro text` / `introduction` / `prologue` unless it's a brand or relates to _subterfuge_
|
||||
(?i)\bpretext\b
|
||||
|
||||
# Should be `bearer`
|
||||
\b(?<=the )burden(?= of bad news\b)
|
||||
|
||||
# Should be `branches`
|
||||
# ... unless it's really about the meal that replaces breakfast and lunch.
|
||||
\b[Bb]runches\b
|
||||
|
||||
# Should be `briefcase`
|
||||
\bbrief-case\b
|
||||
|
||||
# Should be `by far` or `far and away`
|
||||
\bby far and away\b
|
||||
|
||||
# Should be `can, not only ..., ... also...`
|
||||
\bcan not only.*can also\b
|
||||
|
||||
@ -46,7 +98,10 @@
|
||||
# > In formal writing and where contractions are frowned upon, use `cannot`.
|
||||
# > It is possible to write `can not`, but you generally find it only as part of some other construction, such as `not only . . . but also.`
|
||||
# - if you encounter such a case, add a pattern for that case to patterns.txt.
|
||||
\b[Cc]an not\b
|
||||
\b[Cc]an not\b(?! only\b)
|
||||
|
||||
# Should be `chart`
|
||||
(?i)\bhelm\b.*\bchard\b
|
||||
|
||||
# Do not use `(click) here` links
|
||||
# For more information, see:
|
||||
@ -56,9 +111,27 @@
|
||||
# * https://heyoka.medium.com/dont-use-click-here-f32f445d1021
|
||||
(?i)(?:>|\[)(?:(?:click |)here|link|(?:read |)more)(?:</|\]\()
|
||||
|
||||
# Including "image of" or "picture of" in alt text is unnecessary.
|
||||
\balt=['"](?:an? |)(?:image|picture) of
|
||||
|
||||
# Alt text should be short
|
||||
\balt=(?:'[^']{126,}'|"[^"]{126,}")
|
||||
|
||||
# Should be `equals` to `is equal to`
|
||||
\bequals to\b
|
||||
|
||||
# Should be `ECMA` 262 (JavaScript)
|
||||
(?i)\bTS\/EMCA\b|\bEMCA(?: \d|\s*Script)|\bEMCA\b(?=.*\bTS\b)
|
||||
|
||||
# Should be `ECMA` 340 (Near Field Communications)
|
||||
(?i)EMCA[- ]340
|
||||
|
||||
# Should be `fall back`
|
||||
(?<!\ba )(?<!\bthe )\bfallback(?= to(?! ask))\b
|
||||
|
||||
# Should be `for`, `for, to` or `to`
|
||||
\b(?:for to|to for)\b
|
||||
|
||||
# Should be `GitHub`
|
||||
(?<![&*.]|// |\b(?:from|import|type) )\bGithub\b(?![{()])
|
||||
|
||||
@ -84,11 +157,14 @@
|
||||
# Should be `RabbitMQ`
|
||||
\bRabbitmq\b
|
||||
|
||||
# Should be `TensorFlow`
|
||||
\bTensorflow\b
|
||||
|
||||
# Should be `TypeScript`
|
||||
\bTypescript\b
|
||||
|
||||
# Should be `another`
|
||||
\ban[- ]other\b
|
||||
\ban[- ]other(?!-)\b
|
||||
|
||||
# Should be `case-(in)sensitive`
|
||||
\bcase (?:in|)sensitive\b
|
||||
@ -108,11 +184,14 @@
|
||||
# Should be `here-in`, `the`, `them`, `this`, `these` or reworded in some other way
|
||||
\bthe here(?:\.|,| (?!and|defined))
|
||||
|
||||
# Should be `going to bed` or `going to a bad`
|
||||
\bgoing to bad(?!-)\b
|
||||
|
||||
# Should be `greater than`
|
||||
#\bhigher than\b
|
||||
|
||||
# Should be `ID`
|
||||
#\bId\b
|
||||
# Should be `ID` (unless it's a flag/property)
|
||||
#(?<![-\.])\bId\b(?![(])
|
||||
|
||||
# Should be `in front of`
|
||||
\bin from of\b
|
||||
@ -125,6 +204,12 @@
|
||||
# Should be `use`
|
||||
\sin used by\b
|
||||
|
||||
# Should be `in-depth` if used as an adjective (but `in depth` when used as an adverb)
|
||||
\bin depth\s(?!rather\b)\w{6,}
|
||||
|
||||
# Should be `in-flight` or `on the fly` (unless actually talking about airline flights)
|
||||
\bon[- ]flight\b(?!=\s+(?:(?:\w{2}|)\d+|availability|booking|computer|data|delay|departure|management|performance|radar|reservation|scheduling|software|status|ticket|time|type|.*(?:hotel|taxi)))
|
||||
|
||||
# Should be `is obsolete`
|
||||
\bis obsolescent\b
|
||||
|
||||
@ -132,7 +217,10 @@
|
||||
\bits['’]
|
||||
|
||||
# Should be `its`
|
||||
\bit's(?= own\b)
|
||||
\bit's(?= (?:child|only purpose|own(?:er|)|parent|sibling)\b)
|
||||
|
||||
# Should be `for its` (possessive) or `because it is`
|
||||
\bfor it(?:'s| is)\b
|
||||
|
||||
# Should be `log in`
|
||||
\blogin to the
|
||||
@ -140,6 +228,25 @@
|
||||
# Should be `long-standing`
|
||||
\blong standing\b
|
||||
|
||||
# Should be `lose`
|
||||
(?<=\bwill )loose\b
|
||||
|
||||
# `apt-key` is deprecated
|
||||
# ... instead you should be writing a pair of files:
|
||||
# ... * the gpg key added to a distinct key ring file based on your project/distro/key...
|
||||
# ... * the sources.list in a district file -- not simply appended to `/etc/apt/sources.list` -- (there is a newer format [DEB822](https://manpages.debian.org/bookworm/dpkg-dev/deb822.5.en.html)) that references the gpg key.
|
||||
# Consider:
|
||||
# ````sh
|
||||
# curl http://download.something.example.com/$DISTRO/Release.key | \
|
||||
# gpg --dearmor --yes --output /usr/share/keyrings/something-distro.gpg
|
||||
# echo "deb [signed-by=/usr/share/keyrings/something-distro.gpg] http://download.something.example.com/repositories/home:/$DISTRO ./" \
|
||||
# >> /etc/apt/sources.list.d/something-distro.list
|
||||
# ````
|
||||
\bapt-key add\b
|
||||
|
||||
# Should be `nearby`
|
||||
\bnear by\b
|
||||
|
||||
# Should probably be a person named `Nick` or the abbreviation `NIC`
|
||||
\bNic\b
|
||||
|
||||
@ -153,7 +260,7 @@
|
||||
\bperform it's\b
|
||||
|
||||
# Should be `opt-in`
|
||||
#(?<!\scan|for)(?<!\sif)\sopt in\s
|
||||
#(?<!\scan|for)(?<!\smust)(?<!\sif)\sopt in\s
|
||||
|
||||
# Should be `less than`
|
||||
\bless then\b
|
||||
@ -170,24 +277,77 @@
|
||||
# Should be `on the other hand`
|
||||
\b(?i)on another hand\b
|
||||
|
||||
# Reword to `on at runtime` or `enabled at launch`
|
||||
# The former if you mean it can be changed dynamically.
|
||||
# The latter if you mean that it can be changed without recompiling but not after the program starts.
|
||||
\bswitched on runtime\b
|
||||
|
||||
# Should be `Of course,`
|
||||
[?.!]\s+Of course\s(?=[-\w\s]+[.?;!,])
|
||||
|
||||
# Most people only have two hands. Reword.
|
||||
\b(?i)on the third hand\b
|
||||
|
||||
# Should be `Open Graph`
|
||||
# unless talking about a specific Open Graph implementation:
|
||||
# - Java
|
||||
# - Node
|
||||
# - Py
|
||||
# - Ruby
|
||||
\bOpenGraph\b
|
||||
|
||||
# Should be `OpenShift`
|
||||
\bOpenshift\b
|
||||
|
||||
# Should be `otherwise`
|
||||
\bother[- ]wise\b
|
||||
|
||||
# Should be `; otherwise` or `. Otherwise`
|
||||
# https://study.com/learn/lesson/otherwise-in-a-sentence.html
|
||||
, [Oo]therwise\b
|
||||
|
||||
# Should probably be `Otherwise,`
|
||||
(?<=\. )Otherwise\s
|
||||
|
||||
# Should be `or (more|less)`
|
||||
\bore (?:more|less)\b
|
||||
|
||||
# Should be reworded.
|
||||
# `passthrough` is an adjective
|
||||
# `pass-through` could be a noun
|
||||
# `pass through` would be a verb phrase
|
||||
\b(?i)passthrough(?= an?\b)
|
||||
|
||||
# Should be `rather than`
|
||||
\brather then\b
|
||||
|
||||
# Should be `Red Hat`
|
||||
\bRed[Hh]at\b
|
||||
|
||||
# Should be `regardless, ...` or `regardless of (whether)`
|
||||
\b[Rr]egardless if you\b
|
||||
|
||||
# Should be `self-signed`
|
||||
\bself signed\b
|
||||
|
||||
# Should be `SendGrid`
|
||||
\bSendgrid\b
|
||||
|
||||
# Should be `set up` (`setup` is a noun / `set up` is a verb)
|
||||
\b[Ss]etup(?= (?:an?|the)\b)
|
||||
|
||||
# Should be `state`
|
||||
\bsate(?=\b|[A-Z])|(?<=[a-z])Sate(?=\b|[A-Z])|(?<=[A-Z]{2})Sate(?=\b|[A-Z])
|
||||
|
||||
# Should be `no longer needed`
|
||||
\bno more needed\b(?! than\b)
|
||||
|
||||
# Should be `<see|look> below for the`
|
||||
(?i)\bfind below the\b
|
||||
|
||||
# Should be `then any` unless there's a comparison before the `,`
|
||||
, than any\b
|
||||
|
||||
# Should be `did not exist`
|
||||
\bwere not existent\b
|
||||
|
||||
@ -197,9 +357,18 @@
|
||||
# Should be `nonexistent`
|
||||
\b[Nn]o[nt][- ]existent\b
|
||||
|
||||
# Should be `our`
|
||||
\bspending out time\b
|
||||
|
||||
# Should be `@brief` / `@details` / `@param` / `@return` / `@retval`
|
||||
(?:^\s*|(?:\*|//|/*)\s+`)[\\@](?:breif|(?:detail|detials)|(?:params(?!\.)|prama?)|ret(?:uns?)|retvl)\b
|
||||
|
||||
# Should be `more than` or `more, then`
|
||||
\bmore then\b
|
||||
|
||||
# Should be `Pipeline`/`pipeline`
|
||||
(?:(?<=\b|[A-Z])p|P)ipeLine(?:\b|(?=[A-Z]))
|
||||
|
||||
# Should be `preexisting`
|
||||
[Pp]re[- ]existing
|
||||
|
||||
@ -224,14 +393,27 @@
|
||||
# Should be `reentrant`
|
||||
[Rr]e[- ]entrant
|
||||
|
||||
# Should be `room for`
|
||||
\brooms for (?!lease|rent|sale)
|
||||
|
||||
# Should be `socioeconomic`
|
||||
# https://dictionary.cambridge.org/us/dictionary/english/socioeconomic
|
||||
socio-economic
|
||||
|
||||
# Should be `strong suit`
|
||||
\b(?:my|his|her|their) strong suite\b
|
||||
|
||||
# Should probably be `temperatures` unless actually talking about thermal drafts (things birds may fly on)
|
||||
\bthermals\b
|
||||
|
||||
# Should be `there are` or `they are` (or `they're`)
|
||||
(?i)\btheir are\b
|
||||
|
||||
# Should be `understand`
|
||||
\bunder stand\b
|
||||
|
||||
# Should be `URI` or `uri` unless it refers to a person named `Uri`
|
||||
#(?<!\.)\bUri\b(?![(])
|
||||
# Should be `URI` or `uri` unless it refers to a person named `Uri` (or a flag)
|
||||
#(?<![-\.])\bUri\b(?![(])
|
||||
|
||||
# Should be `it uses is`
|
||||
/\bis uses is\b/
|
||||
@ -245,12 +427,36 @@
|
||||
# Should be `where`
|
||||
\bwere they are\b
|
||||
|
||||
# Should be `why`
|
||||
, way(?= is [^.]*\?)
|
||||
|
||||
# should be `vCenter`
|
||||
\bV[Cc]enter\b
|
||||
|
||||
# Should be `VM`
|
||||
\bVm\b
|
||||
|
||||
# Should be `walkthrough(s)`
|
||||
\bwalk-throughs?\b
|
||||
|
||||
# Should be `want`
|
||||
\bdon't ant\b
|
||||
|
||||
# Should be `we'll`
|
||||
\bwe 'll\b
|
||||
|
||||
# Should be `whereas`
|
||||
\bwhere as\b
|
||||
|
||||
# Should be `WinGet`
|
||||
\bWinget\b
|
||||
|
||||
# Should be `without` (unless `out` is a modifier of the next word)
|
||||
\bwith out\b(?!-)
|
||||
|
||||
# Should be `work around`
|
||||
\b[Ww]orkaround(?= an?\b)
|
||||
|
||||
# Should be `workarounds`
|
||||
#\bwork[- ]arounds\b
|
||||
|
||||
@ -270,12 +476,12 @@
|
||||
\b(?:coarse|fine) grained\b
|
||||
|
||||
# Homoglyph (Cyrillic) should be `A`/`B`/`C`/`E`/`H`/`I`/`I`/`J`/`K`/`M`/`O`/`P`/`S`/`T`/`Y`
|
||||
# It's possible that your content is intentionally mixing Cyrllic and Latin scripts, but if it isn't, you definitely want to correct this.
|
||||
# It's possible that your content is intentionally mixing Cyrillic and Latin scripts, but if it isn't, you definitely want to correct this.
|
||||
(?<=[A-Z]{2})[АВСЕНІӀЈКМОРЅТУ]|[АВСЕНІӀЈКМОРЅТУ](?=[A-Z]+(?:\b|[a-z]+)|[a-z]+(?:[^a-z]|$))
|
||||
|
||||
# Homoglyph (Cyrillic) should be `a`/`b`/`e`
|
||||
# It's possible that your content is intentionally mixing Cyrllic and Latin scripts, but if it isn't, you definitely want to correct this.
|
||||
[аве](?=[A-Za-z]{2,})|(?<=[A-Za-z]{2})[аве]|(?<=[A-Za-z])[аве](?=[A-Za-z])
|
||||
# Homoglyph (Cyrillic) should be `a`/`b`/`c`/`e`/`o`/`p`/`x`/`y`
|
||||
# It's possible that your content is intentionally mixing Cyrillic and Latin scripts, but if it isn't, you definitely want to correct this.
|
||||
[авсеорху](?=[A-Za-z]{2,})|(?<=[A-Za-z]{2})[авсеорху]|(?<=[A-Za-z])[авсеорху](?=[A-Za-z])
|
||||
|
||||
# Should be `neither/nor` -- or reword
|
||||
#(?!<do )\bnot\b([^.?!"/(](?!neither|,.*?,))+\bnor\b
|
||||
|
||||
239
.github/actions/spelling/patterns/patterns.txt
vendored
239
.github/actions/spelling/patterns/patterns.txt
vendored
@ -1,5 +1,35 @@
|
||||
# See https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples:-patterns
|
||||
|
||||
# Windows accelerators
|
||||
\b[A-Z][a-z]*&[a-z]+(?!;)\b
|
||||
|
||||
# charsets.hpp
|
||||
\{ L.*\}, // (?:Cyrillic|Greek|Hebrew).*
|
||||
|
||||
# Screen buffer tests
|
||||
\bQQ[A-Z]+\s*[A-Z]*Q+\b
|
||||
|
||||
# Unicode references
|
||||
(?<=\W)(?:U\+?|)[0-9A-F]+b?\b
|
||||
|
||||
# Verify
|
||||
VERIFY_IS_TRUE\(.*\)
|
||||
|
||||
# TEST_METHOD(ApiScrollConsoleScreenBufferW)
|
||||
\bZ[A-Z]+$
|
||||
|
||||
# TerminalApiTest
|
||||
stateMachine\.ProcessString\(L".*"
|
||||
|
||||
# bundles
|
||||
[0-9a-z]+\\?\.msixbundle
|
||||
|
||||
# text file names
|
||||
"[a-z]+\.txt"
|
||||
|
||||
# Checksum
|
||||
L"[0-9A-F]{4}"
|
||||
|
||||
# Direct 2D/3D
|
||||
\b(?:d[23]d(?=[a-z])|D[23]D(?=[A-Z]))
|
||||
|
||||
@ -9,39 +39,127 @@
|
||||
# Windows Resources with accelerators
|
||||
\b[A-Z]&[a-z]+\b(?!;)
|
||||
|
||||
# bug in check-spelling v0.0.24 (fixed later)
|
||||
\bok'd\b
|
||||
|
||||
# Automatically suggested patterns
|
||||
|
||||
# hit-count: 83 file-count: 18
|
||||
# hit-count: 3904 file-count: 577
|
||||
# IServiceProvider / isAThing
|
||||
(?:(?:\b|_|(?<=[a-z]))[IT]|(?:\b|_)(?:nsI|isA))(?=(?:[A-Z][a-z]{2,})+(?:[A-Z\d]|\b))
|
||||
|
||||
# hit-count: 2437 file-count: 826
|
||||
# #includes
|
||||
^\s*#include\s*(?:<.*?>|".*?")
|
||||
|
||||
# hit-count: 1131 file-count: 326
|
||||
# C# includes
|
||||
^\s*using [^;]+;
|
||||
|
||||
# hit-count: 128 file-count: 47
|
||||
# C network byte conversions
|
||||
(?:\d|\bh)to(?!ken)(?=[a-z])|to(?=[adhiklpun]\()
|
||||
|
||||
# hit-count: 59 file-count: 36
|
||||
# IServiceProvider / isAThing
|
||||
(?:\b|_)(?:(?:ns|)I|isA)(?=(?:[A-Z][a-z]{2,})+(?:[A-Z\d]|\b))
|
||||
# hit-count: 53 file-count: 10
|
||||
# ANSI color codes
|
||||
(?:\\(?:u00|x)1[Bb]|\\03[1-7]|\x1b|\\u\{1[Bb]\})\[\d+(?:;\d+)*m
|
||||
|
||||
# hit-count: 9 file-count: 6
|
||||
# hit-count: 45 file-count: 29
|
||||
# version suffix <word>v#
|
||||
(?:(?<=[A-Z]{2})V|(?<=[a-z]{2}|[A-Z]{2})v)\d+(?:\b|(?=[a-zA-Z_]))
|
||||
|
||||
# hit-count: 30 file-count: 19
|
||||
# uuid:
|
||||
\b[0-9a-fA-F]{8}-(?:[0-9a-fA-F]{4}-){3}[0-9a-fA-F]{12}\b
|
||||
|
||||
# hit-count: 17 file-count: 7
|
||||
# File extensions
|
||||
\*\.[+\w]+,
|
||||
|
||||
# hit-count: 15 file-count: 9
|
||||
# Markdown anchor links
|
||||
\(#\S*?[a-zA-Z]\S*?\)
|
||||
|
||||
# hit-count: 5 file-count: 5
|
||||
# libraries
|
||||
(?:\b|_)lib(?:re(?=office)|)(?!era[lt]|ero|ert(?:ies|y)|rar(?:i(?:an|es)|y))(?=[a-z])
|
||||
# hit-count: 14 file-count: 8
|
||||
# hex runs
|
||||
\b[0-9a-fA-F]{16,}\b
|
||||
|
||||
# hit-count: 12 file-count: 8
|
||||
# hex digits including css/html color classes:
|
||||
(?:[\\0][xX]|\\u|[uU]\+|#x?|%23|&H)[0-9_a-fA-FgGrR]*?[a-fA-FgGrR]{2,}[0-9_a-fA-FgGrR]*(?:[uUlL]{0,3}|[iu]\d+)\b
|
||||
|
||||
# hit-count: 12 file-count: 7
|
||||
# tar arguments
|
||||
\b(?:\\n|)g?tar(?:\.exe|)(?:(?:\s+--[-a-zA-Z]+|\s+-[a-zA-Z]+|\s[ABGJMOPRSUWZacdfh-pr-xz]+\b)(?:=[^ ]*|))+
|
||||
|
||||
# hit-count: 9 file-count: 6
|
||||
# Repeated letters
|
||||
\b([a-z])\g{-1}{2,}\b
|
||||
|
||||
# hit-count: 8 file-count: 2
|
||||
# regex choice
|
||||
\(\?:[^)]+\|[^)]+\)
|
||||
|
||||
# hit-count: 8 file-count: 1
|
||||
# latex (check-spelling >= 0.0.22)
|
||||
\\\w{2,}\{
|
||||
|
||||
# hit-count: 7 file-count: 4
|
||||
# Python string prefix / binary prefix
|
||||
# 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,})
|
||||
|
||||
# hit-count: 5 file-count: 3
|
||||
# Alternatively, if you're using check-spelling v0.0.25+, and you would like to _check_ the Non-English content for spelling errors, you can. For information on how to do so, see:
|
||||
# https://docs.check-spelling.dev/Feature:-Configurable-word-characters.html#unicode
|
||||
[a-zA-Z]*[ÀÁÂÃÄÅÆČÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝßàáâãäåæčçèéêëìíîïðñòóôõöøùúûüýÿĀāŁłŃńŅņŒœŚśŠšŜŝŸŽžź][a-zA-Z]{3}[a-zA-ZÀÁÂÃÄÅÆČÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝßàáâãäåæčçèéêëìíîïðñòóôõöøùúûüýÿĀāŁłŃńŅņŒœŚśŠšŜŝŸŽžź]*|[a-zA-Z]{3,}[ÀÁÂÃÄÅÆČÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝßàáâãäåæčçèéêëìíîïðñòóôõöøùúûüýÿĀāŁłŃńŅņŒœŚśŠšŜŝŸŽžź]|[ÀÁÂÃÄÅÆČÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝßàáâãäåæčçèéêëìíîïðñòóôõöøùúûüýÿĀāŁłŃńŅņŒœŚśŠšŜŝŸŽžź][a-zA-Z]{3,}
|
||||
|
||||
# hit-count: 3 file-count: 3
|
||||
# File extensions
|
||||
\*\.[+\w]+,
|
||||
# mailto urls
|
||||
mailto:[-a-zA-Z=;:/?%&0-9+@._]{3,}
|
||||
|
||||
# hit-count: 2 file-count: 2
|
||||
# Alternative printf
|
||||
# %s
|
||||
%(?:s(?=[a-z]{2,}))(?!%)(?=[_a-zA-Z]+(?!%[^s])\b)(?=.*?['"])
|
||||
|
||||
# hit-count: 2 file-count: 1
|
||||
# kubernetes crd patterns
|
||||
^\s*pattern: .*$
|
||||
|
||||
# hit-count: 1 file-count: 1
|
||||
# css fonts
|
||||
\bfont(?:-family|):[^;}]+
|
||||
|
||||
# hit-count: 1 file-count: 1
|
||||
# microsoft
|
||||
\b(?:https?://|)(?:(?:(?:blogs|download\.visualstudio|docs|msdn2?|research)\.|)microsoft|blogs\.msdn)\.co(?:m|\.\w\w)/[-_a-zA-Z0-9()=./%]*
|
||||
|
||||
# hit-count: 1 file-count: 1
|
||||
# Punycode
|
||||
\bxn--[-0-9a-z]+
|
||||
|
||||
# hit-count: 1 file-count: 1
|
||||
# sha-... -- uses a fancy capture
|
||||
(\\?['"]|")[0-9a-f]{40,}\g{-1}
|
||||
|
||||
# hit-count: 1 file-count: 1
|
||||
# Docker images
|
||||
^\s*(?i)FROM\s+\S+:\S+(?:\s+AS\s+\S+|)
|
||||
|
||||
# hit-count: 1 file-count: 1
|
||||
# WWNN/WWPN (NAA identifiers)
|
||||
\b(?:0x)?10[0-9a-f]{14}\b|\b(?:0x|3)?[25][0-9a-f]{15}\b|\b(?:0x|3)?6[0-9a-f]{31}\b
|
||||
|
||||
# hit-count: 1 file-count: 1
|
||||
# curl arguments
|
||||
\b(?:\\n|)curl(?:\.exe|)(?:\s+-[a-zA-Z]{1,2}\b)*(?:\s+-[a-zA-Z]{3,})(?:\s+-[a-zA-Z]+)*
|
||||
|
||||
# hit-count: 1 file-count: 1
|
||||
# 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
|
||||
|
||||
# bug in check-spelling v0.0.24 (fixed later)
|
||||
\bok'd\b
|
||||
|
||||
|
||||
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)
|
||||
@ -72,24 +190,11 @@ ROY\sG\.\sBIV
|
||||
# ARM NEON intrinsics like "vsubq_u16"
|
||||
\bv\w+_[fsu](?:8|16|32|64)\b
|
||||
|
||||
# color floating numbers
|
||||
0x[0-9a-f](?:\.[0-9a-f]*p)[-+]\d+f
|
||||
|
||||
# AppX package
|
||||
_\d[0-9a-z]{12}['\.]
|
||||
|
||||
# string test
|
||||
equals_insensitive_ascii\("\w+", "\w+"
|
||||
|
||||
# Automatically suggested patterns
|
||||
# hit-count: 3788 file-count: 599
|
||||
# IServiceProvider / isAThing
|
||||
\b(?:I|isA)(?=(?:[A-Z][a-z]{2,})+\b)
|
||||
|
||||
# hit-count: 314 file-count: 21
|
||||
# hex runs
|
||||
\b[0-9a-fA-F]{16,}\b
|
||||
|
||||
# hit-count: 47 file-count: 11
|
||||
# special cased printf markers
|
||||
\\r\\n(?=[a-z])|(?<!\\)\\[nrt](?=[a-z]{2,})(?=.*(?:<.*['"`]|"(?:[;,]|\);)$|\) \+$))
|
||||
@ -97,84 +202,6 @@ equals_insensitive_ascii\("\w+", "\w+"
|
||||
# ConsoleArgumentsTests
|
||||
--headless\\.*?"
|
||||
|
||||
# hit-count: 109 file-count: 62
|
||||
# Compiler flags (Unix, Java/Scala)
|
||||
# Use if you have things like `-Pdocker` and want to treat them as `docker`
|
||||
(?:^|[\t ,>"'`=(])-(?:D(?=[A-Z])|W(?!ork)|X|f(?=[ms]))(?=[A-Z]{2,}|[A-Z][a-z]|[a-z]{2,})
|
||||
|
||||
# hit-count: 60 file-count: 35
|
||||
# version suffix <word>v#
|
||||
(?:(?<=[A-Z]{2})V|(?<=[a-z]{2}|[A-Z]{2})v)\d+(?:\b|(?=[a-zA-Z_]))
|
||||
|
||||
# hit-count: 2 file-count: 2
|
||||
# This does not cover multiline strings, if your repository has them,
|
||||
# you'll want to remove the `(?=.*?")` suffix.
|
||||
# The `(?=.*?")` suffix should limit the false positives rate
|
||||
# printf
|
||||
%(?:s)(?!ize)(?=[a-z]{2,})
|
||||
|
||||
# hit-count: 16 file-count: 10
|
||||
# uuid:
|
||||
\b[0-9a-fA-F]{8}-(?:[0-9a-fA-F]{4}-){3}[0-9a-fA-F]{12}\b
|
||||
|
||||
# hit-count: 13 file-count: 4
|
||||
# Non-English
|
||||
[a-zA-Z]*[ÀÁÂÃÄÅÆČÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝßàáâãäåæčçèéêëìíîïðñòóôõöøùúûüýÿĀāŁłŃńŅņŒœŚśŠšŜŝŸŽžź][a-zA-Z]{3}[a-zA-ZÀÁÂÃÄÅÆČÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝßàáâãäåæčçèéêëìíîïðñòóôõöøùúûüýÿĀāŁłŃńŅņŒœŚśŠšŜŝŸŽžź]*|[a-zA-Z]{3,}[ÀÁÂÃÄÅÆČÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝßàáâãäåæčçèéêëìíîïðñòóôõöøùúûüýÿĀāŁłŃńŅņŒœŚśŠšŜŝŸŽžź]|[ÀÁÂÃÄÅÆČÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝßàáâãäåæčçèéêëìíîïðñòóôõöøùúûüýÿĀāŁłŃńŅņŒœŚśŠšŜŝŸŽžź][a-zA-Z]{3,}
|
||||
|
||||
# hit-count: 7 file-count: 5
|
||||
# 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}|[iu]\d+)\b
|
||||
|
||||
# hit-count: 7 file-count: 1
|
||||
# regex choice
|
||||
\(\?:[^)]+\|[^)]+\)
|
||||
|
||||
# hit-count: 4 file-count: 4
|
||||
# tar arguments
|
||||
\b(?:\\n|)g?tar(?:\.exe|)(?:(?:\s+--[-a-zA-Z]+|\s+-[a-zA-Z]+|\s[ABGJMOPRSUWZacdfh-pr-xz]+\b)(?:=[^ ]*|))+
|
||||
|
||||
# hit-count: 4 file-count: 1
|
||||
# ANSI color codes
|
||||
(?:\\(?:u00|x)1[Bb]|\x1b|\\u\{1[Bb]\})\[\d+(?:;\d+|)m
|
||||
|
||||
# hit-count: 4 file-count: 1
|
||||
# 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|[,.])*
|
||||
|
||||
# hit-count: 3 file-count: 3
|
||||
# mailto urls
|
||||
mailto:[-a-zA-Z=;:/?%&0-9+@.]{3,}
|
||||
|
||||
# hit-count: 2 file-count: 1
|
||||
# Python string prefix / binary prefix
|
||||
# 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,})
|
||||
|
||||
# hit-count: 1 file-count: 1
|
||||
# Punycode
|
||||
\bxn--[-0-9a-z]+
|
||||
|
||||
# hit-count: 1 file-count: 1
|
||||
# latex (check-spelling >= 0.0.22)
|
||||
\\\w{2,}\{
|
||||
|
||||
# hit-count: 1 file-count: 1
|
||||
# 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
|
||||
|
||||
# Questionably acceptable forms of `in to`
|
||||
# Personally, I prefer `log into`, but people object
|
||||
# https://www.tprteaching.com/log-into-log-in-to-login/
|
||||
\b(?:[Ll]og|[Ss]ign) in to\b
|
||||
|
||||
# to opt in
|
||||
\bto opt in\b
|
||||
|
||||
# Questionably acceptable forms of `in to`
|
||||
# Personally, I prefer `log into`, but people object
|
||||
@ -183,6 +210,10 @@ mailto:[-a-zA-Z=;:/?%&0-9+@.]{3,}
|
||||
|
||||
# to opt in
|
||||
\bto opt in\b
|
||||
|
||||
# pass(ed|ing) in
|
||||
\bpass(?:ed|ing) in\b
|
||||
|
||||
# acceptable duplicates
|
||||
# ls directory listings
|
||||
[-bcdlpsw](?:[-r][-w][-SsTtx]){3}[\.+*]?\s+\d+\s+\S+\s+\S+\s+[.\d]+(?:[KMGT]|)\s+
|
||||
|
||||
12
.github/actions/spelling/reject.txt
vendored
12
.github/actions/spelling/reject.txt
vendored
@ -1,10 +1,19 @@
|
||||
^attache$
|
||||
^attacher$
|
||||
^attachers$
|
||||
^bellow$
|
||||
^bellow?$
|
||||
benefitting
|
||||
occurences?
|
||||
^dependan.*
|
||||
^develope$
|
||||
^developement$
|
||||
^developpe
|
||||
^Devers?$
|
||||
^devex
|
||||
^devide
|
||||
^Devinn?[ae]
|
||||
^devisal
|
||||
^devisor
|
||||
^diables?$
|
||||
^oer$
|
||||
Sorce
|
||||
@ -12,4 +21,5 @@ Sorce
|
||||
^Teh$
|
||||
^untill$
|
||||
^untilling$
|
||||
^venders?$
|
||||
^wether.*
|
||||
|
||||
41
.github/workflows/spelling2.yml
vendored
41
.github/workflows/spelling2.yml
vendored
@ -93,7 +93,7 @@ jobs:
|
||||
steps:
|
||||
- name: check-spelling
|
||||
id: spelling
|
||||
uses: check-spelling/check-spelling@v0.0.24
|
||||
uses: check-spelling/check-spelling@v0.0.25
|
||||
with:
|
||||
suppress_push_for_open_pull_request: ${{ github.actor != 'dependabot[bot]' && 1 }}
|
||||
checkout: true
|
||||
@ -104,7 +104,7 @@ jobs:
|
||||
report-timing: 1
|
||||
warnings: bad-regex,binary-file,deprecated-feature,ignored-expect-variant,large-file,limited-references,no-newline-at-eof,noisy-file,non-alpha-in-dictionary,token-is-substring,unexpected-line-ending,whitespace-in-dictionary,minified-file,unsupported-configuration,no-files-to-check,unclosed-block-ignore-begin,unclosed-block-ignore-end
|
||||
experimental_apply_changes_via_bot: ${{ github.repository_owner != 'microsoft' && 1 }}
|
||||
use_sarif: ${{ (!github.event.pull_request || (github.event.pull_request.head.repo.full_name == github.repository)) && 1 }}
|
||||
use_sarif: 1
|
||||
check_extra_dictionaries: ""
|
||||
dictionary_source_prefixes: >
|
||||
{
|
||||
@ -114,34 +114,33 @@ jobs:
|
||||
cspell:software-terms/softwareTerms.txt
|
||||
cspell:cpp/stdlib-cpp.txt
|
||||
cspell:cpp/stdlib-c.txt
|
||||
cspell:lorem-ipsum/dictionary.txt
|
||||
cspell:python/python/python-lib.txt
|
||||
cspell:php/php.txt
|
||||
cspell:node/node.txt
|
||||
cspell:dart/dart.txt
|
||||
cspell:filetypes/filetypes.txt
|
||||
cspell:java/java.txt
|
||||
cspell:node/node.txt
|
||||
cspell:golang/go.txt
|
||||
cspell:java/java-terms.txt
|
||||
cspell:mnemonics/mnemonics.txt
|
||||
cspell:css/css.txt
|
||||
cspell:dotnet/dotnet.txt
|
||||
cspell:npm/npm.txt
|
||||
cspell:fullstack/fullstack.txt
|
||||
cspell:python/python/python-lib.txt
|
||||
cspell:dotnet/dotnet.txt
|
||||
cspell:dart/dart.txt
|
||||
cspell:aws/aws.txt
|
||||
cspell:python/common/extra.txt
|
||||
cspell:css/css.txt
|
||||
cspell:java/java-terms.txt
|
||||
cspell:r/r.txt
|
||||
cspell:golang/go.txt
|
||||
cspell:cpp/stdlib-cmath.txt
|
||||
cspell:typescript/typescript.txt
|
||||
cspell:html/html.txt
|
||||
cspell:cpp/compiler-msvc.txt
|
||||
cspell:django/django.txt
|
||||
cspell:html/html.txt
|
||||
cspell:cpp/lang-keywords.txt
|
||||
cspell:aws/aws.txt
|
||||
cspell:python/common/extra.txt
|
||||
cspell:cpp/ecosystem.txt
|
||||
cspell:r/r.txt
|
||||
cspell:cpp/compiler-clang-attributes.txt
|
||||
cspell:powershell/powershell.txt
|
||||
cspell:cpp/lang-keywords.txt
|
||||
cspell:csharp/csharp.txt
|
||||
cspell:cpp/compiler-clang-attributes.txt
|
||||
cspell:python/python/python.txt
|
||||
cspell:mnemonics/mnemonics.txt
|
||||
cspell:powershell/powershell.txt
|
||||
|
||||
comment-push:
|
||||
name: Report (Push)
|
||||
@ -154,7 +153,7 @@ jobs:
|
||||
if: (success() || failure()) && needs.spelling.outputs.followup && github.event_name == 'push'
|
||||
steps:
|
||||
- name: comment
|
||||
uses: check-spelling/check-spelling@v0.0.24
|
||||
uses: check-spelling/check-spelling@v0.0.25
|
||||
with:
|
||||
checkout: true
|
||||
spell_check_this: microsoft/terminal@main
|
||||
@ -172,7 +171,7 @@ jobs:
|
||||
if: (success() || failure()) && needs.spelling.outputs.followup && contains(github.event_name, 'pull_request')
|
||||
steps:
|
||||
- name: comment
|
||||
uses: check-spelling/check-spelling@v0.0.24
|
||||
uses: check-spelling/check-spelling@v0.0.25
|
||||
with:
|
||||
checkout: true
|
||||
spell_check_this: microsoft/terminal@main
|
||||
@ -198,7 +197,7 @@ jobs:
|
||||
cancel-in-progress: false
|
||||
steps:
|
||||
- name: apply spelling updates
|
||||
uses: check-spelling/check-spelling@v0.0.24
|
||||
uses: check-spelling/check-spelling@v0.0.25
|
||||
with:
|
||||
experimental_apply_changes_via_bot: ${{ github.repository_owner != 'microsoft' && 1 }}
|
||||
checkout: true
|
||||
|
||||
7
.github/workflows/winget.yml
vendored
7
.github/workflows/winget.yml
vendored
@ -1,4 +1,4 @@
|
||||
name: Publish to Winget
|
||||
name: Publish to WinGet
|
||||
|
||||
on:
|
||||
release:
|
||||
@ -6,6 +6,9 @@ on:
|
||||
|
||||
env:
|
||||
REGEX: 'Microsoft\.WindowsTerminal(?:Preview)?_([\d.]+)_8wekyb3d8bbwe\.msixbundle$'
|
||||
# winget-create will read the following environment variable to access the GitHub token needed for submitting a PR
|
||||
# See https://aka.ms/winget-create-token
|
||||
WINGET_CREATE_GITHUB_TOKEN: ${{ secrets.WINGET_TOKEN }}
|
||||
|
||||
jobs:
|
||||
publish:
|
||||
@ -21,4 +24,4 @@ jobs:
|
||||
$wingetPackage = "Microsoft.WindowsTerminal${{ github.event.release.prerelease && '.Preview' || '' }}"
|
||||
|
||||
& curl.exe -JLO https://aka.ms/wingetcreate/latest
|
||||
& .\wingetcreate.exe update $wingetPackage -s -v $version -u $wingetRelevantAsset.browser_download_url -t "${{ secrets.WINGET_TOKEN }}"
|
||||
& .\wingetcreate.exe update $wingetPackage -s -v $version -u $wingetRelevantAsset.browser_download_url
|
||||
|
||||
@ -17,7 +17,6 @@
|
||||
"Microsoft.VisualStudio.Component.AppInsights.Tools",
|
||||
"Microsoft.Net.Component.4.8.TargetingPack",
|
||||
"Microsoft.VisualStudio.Component.DiagnosticTools",
|
||||
"Microsoft.NetCore.Component.Runtime.6.0",
|
||||
"Microsoft.VisualStudio.Component.ClassDesigner",
|
||||
"Microsoft.VisualStudio.Component.GraphDocument",
|
||||
"Microsoft.VisualStudio.Component.CodeMap",
|
||||
|
||||
32
NOTICE.md
32
NOTICE.md
@ -285,6 +285,8 @@ specific language governing permissions and limitations under the License.
|
||||
**Source**: [https://github.com/commonmark/cmark](https://github.com/commonmark/cmark)
|
||||
|
||||
### License
|
||||
|
||||
```
|
||||
Copyright (c) 2014, John MacFarlane
|
||||
|
||||
All rights reserved.
|
||||
@ -455,6 +457,36 @@ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
```
|
||||
|
||||
## fzf
|
||||
|
||||
### License
|
||||
|
||||
```
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2013-2024 Junegunn Choi
|
||||
Copyright (c) 2021-2025 Simon Hauser
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
```
|
||||
|
||||
# Microsoft Open Source
|
||||
|
||||
|
||||
@ -28,7 +28,7 @@ namespace HelixTestHelpers
|
||||
public List<string> Screenshots { get; private set; }
|
||||
public List<TestResult> RerunResults { get; private set; }
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Azure DevOps doesn't currently provide a way to directly report sub-results for tests that failed at least once
|
||||
// that were run multiple times. To get around that limitation, we'll mark the test as "Skip" since
|
||||
@ -49,46 +49,46 @@ namespace HelixTestHelpers
|
||||
// TODO (https://github.com/dotnet/arcade/issues/2773): Once we're able to directly report things in a
|
||||
// more granular fashion than just a binary pass/fail result, we should do that.
|
||||
//
|
||||
[DataContract]
|
||||
[DataContract]
|
||||
internal class JsonSerializableTestResults
|
||||
{
|
||||
{
|
||||
[DataMember]
|
||||
internal string blobPrefix;
|
||||
|
||||
|
||||
[DataMember]
|
||||
internal string blobSuffix;
|
||||
|
||||
|
||||
[DataMember]
|
||||
internal string[] errors;
|
||||
|
||||
|
||||
[DataMember]
|
||||
internal JsonSerializableTestResult[] results;
|
||||
}
|
||||
|
||||
[DataContract]
|
||||
internal class JsonSerializableTestResult
|
||||
|
||||
[DataContract]
|
||||
internal class JsonSerializableTestResult
|
||||
{
|
||||
[DataMember]
|
||||
internal string outcome;
|
||||
|
||||
[DataMember]
|
||||
internal int duration;
|
||||
|
||||
|
||||
[DataMember(EmitDefaultValue = false)]
|
||||
internal string log;
|
||||
|
||||
|
||||
[DataMember(EmitDefaultValue = false)]
|
||||
internal string[] screenshots;
|
||||
|
||||
|
||||
[DataMember(EmitDefaultValue = false)]
|
||||
internal int errorIndex;
|
||||
}
|
||||
|
||||
|
||||
public class TestPass
|
||||
{
|
||||
public TimeSpan TestPassExecutionTime { get; set; }
|
||||
public List<TestResult> TestResults { get; set; }
|
||||
|
||||
|
||||
public static TestPass ParseTestWttFile(string fileName, bool cleanupFailuresAreRegressions, bool truncateTestNames)
|
||||
{
|
||||
using (var stream = File.OpenRead(fileName))
|
||||
@ -174,7 +174,7 @@ namespace HelixTestHelpers
|
||||
if (testsExecuting == 1)
|
||||
{
|
||||
string testName = element.Attribute("Title").Value;
|
||||
|
||||
|
||||
if (truncateTestNames)
|
||||
{
|
||||
const string xamlNativePrefix = "Windows::UI::Xaml::Tests::";
|
||||
@ -243,7 +243,7 @@ namespace HelixTestHelpers
|
||||
|
||||
|
||||
// The test cleanup errors will often come after the test claimed to have
|
||||
// 'passed'. We treat them as errors as well.
|
||||
// 'passed'. We treat them as errors as well.
|
||||
if (inTestCleanup)
|
||||
{
|
||||
currentResult.CleanupPassed = false;
|
||||
@ -292,7 +292,7 @@ namespace HelixTestHelpers
|
||||
foreach(var screenshot in screenshots)
|
||||
{
|
||||
string fileNameSuffix = string.Empty;
|
||||
|
||||
|
||||
if (fileName.Contains("_rerun_multiple"))
|
||||
{
|
||||
fileNameSuffix = "_rerun_multiple";
|
||||
@ -301,7 +301,7 @@ namespace HelixTestHelpers
|
||||
{
|
||||
fileNameSuffix = "_rerun";
|
||||
}
|
||||
|
||||
|
||||
currentResult.Screenshots.Add(screenshot.Replace(".jpg", fileNameSuffix + ".jpg"));
|
||||
}
|
||||
}
|
||||
@ -313,7 +313,7 @@ namespace HelixTestHelpers
|
||||
testPassStopTime = Int64.Parse(doc.Root.Descendants("WexTraceInfo").Last().Attribute("TimeStamp").Value);
|
||||
|
||||
var testPassTime = TimeSpan.FromSeconds((double)(testPassStopTime - testPassStartTime) / frequency);
|
||||
|
||||
|
||||
foreach (TestResult testResult in testResults)
|
||||
{
|
||||
if (testResult.Details != null)
|
||||
@ -331,13 +331,13 @@ namespace HelixTestHelpers
|
||||
return testpass;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static TestPass ParseTestWttFileWithReruns(string fileName, string singleRerunFileName, string multipleRerunFileName, bool cleanupFailuresAreRegressions, bool truncateTestNames)
|
||||
{
|
||||
TestPass testPass = ParseTestWttFile(fileName, cleanupFailuresAreRegressions, truncateTestNames);
|
||||
TestPass singleRerunTestPass = File.Exists(singleRerunFileName) ? ParseTestWttFile(singleRerunFileName, cleanupFailuresAreRegressions, truncateTestNames) : null;
|
||||
TestPass multipleRerunTestPass = File.Exists(multipleRerunFileName) ? ParseTestWttFile(multipleRerunFileName, cleanupFailuresAreRegressions, truncateTestNames) : null;
|
||||
|
||||
|
||||
List<TestResult> rerunTestResults = new List<TestResult>();
|
||||
|
||||
if (singleRerunTestPass != null)
|
||||
@ -377,9 +377,9 @@ namespace HelixTestHelpers
|
||||
public static void OutputFailedTestQuery(string wttInputPath)
|
||||
{
|
||||
var testPass = TestPass.ParseTestWttFile(wttInputPath, cleanupFailuresAreRegressions: true, truncateTestNames: false);
|
||||
|
||||
|
||||
List<string> failedTestNames = new List<string>();
|
||||
|
||||
|
||||
foreach (var result in testPass.TestResults)
|
||||
{
|
||||
if (!result.Passed)
|
||||
@ -387,23 +387,23 @@ namespace HelixTestHelpers
|
||||
failedTestNames.Add(result.Name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (failedTestNames.Count > 0)
|
||||
{
|
||||
string failedTestSelectQuery = "(@Name='";
|
||||
|
||||
|
||||
for (int i = 0; i < failedTestNames.Count; i++)
|
||||
{
|
||||
failedTestSelectQuery += failedTestNames[i];
|
||||
|
||||
|
||||
if (i < failedTestNames.Count - 1)
|
||||
{
|
||||
failedTestSelectQuery += "' or @Name='";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
failedTestSelectQuery += "')";
|
||||
|
||||
|
||||
Console.WriteLine(failedTestSelectQuery);
|
||||
}
|
||||
else
|
||||
@ -418,7 +418,7 @@ namespace HelixTestHelpers
|
||||
private string testNamePrefix;
|
||||
private string helixResultsContainerUri;
|
||||
private string helixResultsContainerRsas;
|
||||
|
||||
|
||||
public TestResultParser(string testNamePrefix, string helixResultsContainerUri, string helixResultsContainerRsas)
|
||||
{
|
||||
this.testNamePrefix = testNamePrefix;
|
||||
@ -430,7 +430,7 @@ namespace HelixTestHelpers
|
||||
{
|
||||
Dictionary<string, string> subResultsJsonByMethod = new Dictionary<string, string>();
|
||||
TestPass testPass = TestPass.ParseTestWttFileWithReruns(wttInputPath, wttSingleRerunInputPath, wttMultipleRerunInputPath, cleanupFailuresAreRegressions: true, truncateTestNames: false);
|
||||
|
||||
|
||||
foreach (var result in testPass.TestResults)
|
||||
{
|
||||
var methodName = result.Name.Substring(result.Name.LastIndexOf('.') + 1);
|
||||
@ -488,7 +488,7 @@ namespace HelixTestHelpers
|
||||
|
||||
int resultCount = results.Count;
|
||||
int passedCount = results.Where(r => r.Passed).Count();
|
||||
|
||||
|
||||
// Since we re-run tests on failure, we'll mark every test that failed at least once as "skipped" rather than "failed".
|
||||
// If the test failed sufficiently often enough for it to count as a failed test (determined by a property on the
|
||||
// Azure DevOps job), we'll later mark it as failed during test results processing.
|
||||
@ -504,15 +504,15 @@ namespace HelixTestHelpers
|
||||
assembly.SetAttributeValue("run-date", DateTime.Now.ToString("yyyy-MM-dd"));
|
||||
|
||||
// This doesn't need to be completely accurate since it's not exposed anywhere.
|
||||
// If we need accurate an start time we can probably calculate it from the te.wtl file, but for
|
||||
// If we need an accurate start time we can probably calculate it from the te.wtl file, but for
|
||||
// now this is fine.
|
||||
assembly.SetAttributeValue("run-time", (DateTime.Now - testPass.TestPassExecutionTime).ToString("hh:mm:ss"));
|
||||
|
||||
|
||||
assembly.SetAttributeValue("total", resultCount);
|
||||
assembly.SetAttributeValue("passed", passedCount);
|
||||
assembly.SetAttributeValue("failed", failedCount);
|
||||
assembly.SetAttributeValue("skipped", skippedCount);
|
||||
|
||||
|
||||
assembly.SetAttributeValue("time", (int)testPass.TestPassExecutionTime.TotalSeconds);
|
||||
assembly.SetAttributeValue("errors", 0);
|
||||
root.Add(assembly);
|
||||
@ -537,9 +537,9 @@ namespace HelixTestHelpers
|
||||
test.SetAttributeValue("method", methodName);
|
||||
|
||||
test.SetAttributeValue("time", result.ExecutionTime.TotalSeconds);
|
||||
|
||||
|
||||
string resultString = string.Empty;
|
||||
|
||||
|
||||
if (result.Passed && !result.Skipped)
|
||||
{
|
||||
resultString = "Pass";
|
||||
@ -554,7 +554,7 @@ namespace HelixTestHelpers
|
||||
resultString = "Fail";
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (!result.Passed)
|
||||
{
|
||||
if (result.Skipped)
|
||||
@ -579,36 +579,36 @@ namespace HelixTestHelpers
|
||||
|
||||
File.WriteAllText(xunitOutputPath, root.ToString());
|
||||
}
|
||||
|
||||
|
||||
private JsonSerializableTestResult ConvertToSerializableResult(TestResult rerunResult, string[] uniqueErrors)
|
||||
{
|
||||
var serializableResult = new JsonSerializableTestResult();
|
||||
|
||||
|
||||
serializableResult.outcome = rerunResult.Passed ? "Passed" : "Failed";
|
||||
serializableResult.duration = (int)Math.Round(rerunResult.ExecutionTime.TotalMilliseconds);
|
||||
|
||||
|
||||
if (!rerunResult.Passed)
|
||||
{
|
||||
serializableResult.log = Path.GetFileName(rerunResult.SourceWttFile);
|
||||
|
||||
|
||||
if (rerunResult.Screenshots.Any())
|
||||
{
|
||||
List<string> screenshots = new List<string>();
|
||||
|
||||
|
||||
foreach (var screenshot in rerunResult.Screenshots)
|
||||
{
|
||||
screenshots.Add(Path.GetFileName(screenshot));
|
||||
}
|
||||
|
||||
|
||||
serializableResult.screenshots = screenshots.ToArray();
|
||||
}
|
||||
|
||||
|
||||
// To conserve space, we'll log the index of the error to index in a list of unique errors rather than
|
||||
// jotting down every single error in its entirety. We'll add one to the result so we can avoid
|
||||
// serializing this property when it has the default value of 0.
|
||||
serializableResult.errorIndex = Array.IndexOf(uniqueErrors, rerunResult.Details) + 1;
|
||||
}
|
||||
|
||||
|
||||
return serializableResult;
|
||||
}
|
||||
|
||||
@ -617,7 +617,7 @@ namespace HelixTestHelpers
|
||||
var filename = Path.GetFileName(filePath);
|
||||
return string.Format("{0}/{1}{2}", helixResultsContainerUri, filename, helixResultsContainerRsas);
|
||||
}
|
||||
|
||||
|
||||
private string GetTestNameSeparator(string testname)
|
||||
{
|
||||
var separatorString = ".";
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
{
|
||||
"MatchedPath": [
|
||||
"WpfTerminalControl/net472/Microsoft.Terminal.Wpf.dll",
|
||||
"WpfTerminalControl/net6.0-windows/Microsoft.Terminal.Wpf.dll"
|
||||
"WpfTerminalControl/net8.0-windows/Microsoft.Terminal.Wpf.dll"
|
||||
],
|
||||
"SigningInfo": {
|
||||
"Operations": [
|
||||
|
||||
@ -14,21 +14,21 @@
|
||||
<Package
|
||||
Name="Microsoft.UI.Xaml.2.8"
|
||||
Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US"
|
||||
Version="8.2305.5001.0"
|
||||
Version="8.2306.22001.0"
|
||||
ProcessorArchitecture="x64"
|
||||
Uri="https://github.com/microsoft/microsoft-ui-xaml/releases/download/v2.8.4/Microsoft.UI.Xaml.2.8.x64.appx" />
|
||||
Uri="https://github.com/microsoft/microsoft-ui-xaml/releases/download/v2.8.5/Microsoft.UI.Xaml.2.8.x64.appx" />
|
||||
<Package
|
||||
Name="Microsoft.UI.Xaml.2.8"
|
||||
Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US"
|
||||
Version="8.2305.5001.0"
|
||||
Version="8.2306.22001.0"
|
||||
ProcessorArchitecture="x86"
|
||||
Uri="https://github.com/microsoft/microsoft-ui-xaml/releases/download/v2.8.4/Microsoft.UI.Xaml.2.8.x86.appx" />
|
||||
Uri="https://github.com/microsoft/microsoft-ui-xaml/releases/download/v2.8.5/Microsoft.UI.Xaml.2.8.x86.appx" />
|
||||
<Package
|
||||
Name="Microsoft.UI.Xaml.2.8"
|
||||
Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US"
|
||||
Version="8.2305.5001.0"
|
||||
Version="8.2306.22001.0"
|
||||
ProcessorArchitecture="arm64"
|
||||
Uri="https://github.com/microsoft/microsoft-ui-xaml/releases/download/v2.8.4/Microsoft.UI.Xaml.2.8.arm64.appx" />
|
||||
Uri="https://github.com/microsoft/microsoft-ui-xaml/releases/download/v2.8.5/Microsoft.UI.Xaml.2.8.arm64.appx" />
|
||||
</Dependencies>
|
||||
|
||||
<UpdateSettings>
|
||||
|
||||
@ -50,6 +50,7 @@ extends:
|
||||
parameters:
|
||||
pool: { type: windows }
|
||||
variables:
|
||||
ob_sdl_prefast_enabled: false # This is a collection of powershell scripts
|
||||
ob_git_checkout: false # This job checks itself out
|
||||
ob_git_skip_checkout_none: true
|
||||
ob_outputDirectory: "$(Build.SourcesDirectory)/_none"
|
||||
|
||||
@ -75,13 +75,30 @@ jobs:
|
||||
}
|
||||
displayName: "Wrangle Unpackaged builds into place, rename"
|
||||
|
||||
- task: AzurePowerShell@5
|
||||
- task: PowerShell@2
|
||||
displayName: Install Azure Modules from custom PowerShell Gallery Repo
|
||||
env:
|
||||
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
|
||||
inputs:
|
||||
pwsh: false # We are preparing modules for AzureFileCopy, which uses PowerShell 5.1
|
||||
targetType: inline
|
||||
script: |-
|
||||
$MachineToken = $env:SYSTEM_ACCESSTOKEN | ConvertTo-SecureString -AsPlainText -Force
|
||||
$Credential = [PSCredential]::new("ONEBRANCH_TOKEN", $MachineToken)
|
||||
$MachineToken = $null
|
||||
$Feed = "https://pkgs.dev.azure.com/shine-oss/terminal/_packaging/TerminalDependencies/nuget/v3/index.json"
|
||||
Register-PSResourceRepository -Name "PSGalleryUpstream" -Uri $Feed -Trusted
|
||||
Get-PSResourceRepository
|
||||
|
||||
Install-PSResource -Name Az.Accounts, Az.Storage, Az.Network, Az.Resources, Az.Compute -Repository "PSGalleryUpstream" -Credential $Credential
|
||||
|
||||
- task: AzureFileCopy@6
|
||||
displayName: Publish to Storage Account
|
||||
inputs:
|
||||
sourcePath: _out/*
|
||||
Destination: AzureBlob
|
||||
azureSubscription: ${{ parameters.subscription }}
|
||||
azurePowerShellVersion: LatestVersion
|
||||
pwsh: true
|
||||
ScriptType: InlineScript
|
||||
Inline: |-
|
||||
$Env:AZCOPY_AUTO_LOGIN_TYPE="PSCRED"
|
||||
& AzCopy copy "_out\*" "https://${{ parameters.storageAccount }}.blob.core.windows.net/${{ parameters.storageContainer }}/" --content-type application/octet-stream
|
||||
storage: ${{ parameters.storageAccount }}
|
||||
ContainerName: ${{ parameters.storageContainer }}
|
||||
AdditionalArgumentsForBlobCopy: "--content-type application/octet-stream"
|
||||
|
||||
|
||||
@ -30,7 +30,7 @@ jobs:
|
||||
steps:
|
||||
- checkout: self
|
||||
clean: true
|
||||
# It is important that this be 0, otherwise git will not fetch the branch ref names that the PGO rules require.
|
||||
# It is important that this be 0; otherwise, git will not fetch the branch ref names that the PGO rules require.
|
||||
fetchDepth: 0
|
||||
submodules: false
|
||||
persistCredentials: false
|
||||
|
||||
@ -61,7 +61,7 @@ jobs:
|
||||
pwsh: true
|
||||
ScriptType: InlineScript
|
||||
Inline: |-
|
||||
$AzToken = (Get-AzAccessToken -ResourceUrl api://30471ccf-0966-45b9-a979-065dbedb24c1).Token
|
||||
$AzToken = (Get-AzAccessToken -AsSecureString -ResourceUrl api://30471ccf-0966-45b9-a979-065dbedb24c1).Token | ConvertFrom-SecureString -AsPlainText
|
||||
Write-Host "##vso[task.setvariable variable=SymbolAccessToken;issecret=true]$AzToken"
|
||||
|
||||
|
||||
|
||||
@ -88,6 +88,9 @@ extends:
|
||||
enabled: false
|
||||
globalSdl: # https://aka.ms/obpipelines/sdl
|
||||
enableCheckCFlags: false # CheckCFlags is broken and exploding our builds; to remove, :g/BAD-FLAGS/d
|
||||
isNativeCode: true
|
||||
prefast:
|
||||
enabled: true
|
||||
asyncSdl:
|
||||
enabled: true
|
||||
tsaOptionsFile: 'build/config/tsa.json'
|
||||
@ -115,6 +118,8 @@ extends:
|
||||
variables:
|
||||
ob_sdl_checkcflags_enabled: false # BAD-FLAGS
|
||||
ob_sdl_xfgcheck_enabled: false # BAD-FLAGS
|
||||
ob_sdl_prefast_runDuring: Build
|
||||
ob_sdl_checkCompliantCompilerWarnings: true
|
||||
ob_git_checkout: false # This job checks itself out
|
||||
ob_git_skip_checkout_none: true
|
||||
ob_outputDirectory: $(JobOutputDirectory)
|
||||
@ -149,6 +154,7 @@ extends:
|
||||
variables:
|
||||
ob_sdl_checkcflags_enabled: false # BAD-FLAGS
|
||||
ob_sdl_xfgcheck_enabled: false # BAD-FLAGS
|
||||
ob_sdl_prefast_enabled: false # This is a C# build job
|
||||
ob_git_checkout: false # This job checks itself out
|
||||
ob_git_skip_checkout_none: true
|
||||
ob_outputDirectory: $(JobOutputDirectory)
|
||||
@ -180,6 +186,7 @@ extends:
|
||||
variables:
|
||||
ob_sdl_checkcflags_enabled: false # BAD-FLAGS
|
||||
ob_sdl_xfgcheck_enabled: false # BAD-FLAGS
|
||||
ob_sdl_prefast_enabled: false # This is a collection of powershell scripts
|
||||
ob_git_checkout: false # This job checks itself out
|
||||
ob_git_skip_checkout_none: true
|
||||
ob_outputDirectory: $(JobOutputDirectory)
|
||||
@ -234,6 +241,7 @@ extends:
|
||||
variables:
|
||||
ob_sdl_checkcflags_enabled: false # BAD-FLAGS
|
||||
ob_sdl_xfgcheck_enabled: false # BAD-FLAGS
|
||||
ob_sdl_prefast_enabled: false # This is a collection of powershell scripts
|
||||
ob_git_checkout: false # This job checks itself out
|
||||
ob_git_skip_checkout_none: true
|
||||
ob_outputDirectory: $(JobOutputDirectory)
|
||||
@ -252,6 +260,7 @@ extends:
|
||||
variables:
|
||||
ob_sdl_checkcflags_enabled: false # BAD-FLAGS
|
||||
ob_sdl_xfgcheck_enabled: false # BAD-FLAGS
|
||||
ob_sdl_prefast_enabled: false # This is a collection of powershell scripts
|
||||
ob_git_checkout: false # This job checks itself out
|
||||
ob_git_skip_checkout_none: true
|
||||
ob_outputDirectory: $(JobOutputDirectory)
|
||||
@ -277,6 +286,7 @@ extends:
|
||||
variables:
|
||||
ob_sdl_checkcflags_enabled: false # BAD-FLAGS
|
||||
ob_sdl_xfgcheck_enabled: false # BAD-FLAGS
|
||||
ob_sdl_prefast_enabled: false # This is a collection of powershell scripts
|
||||
ob_git_checkout: false # This job checks itself out
|
||||
ob_git_skip_checkout_none: true
|
||||
ob_outputDirectory: $(Build.ArtifactStagingDirectory)
|
||||
|
||||
@ -1,8 +1,28 @@
|
||||
$VSInstances = ([xml](& 'C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe' -latest -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -include packages -format xml))
|
||||
$VSPackages = $VSInstances.instances.instance.packages.package
|
||||
$LatestVCPackage = ($VSInstances.instances.instance.packages.package | ? { $_.id -eq "Microsoft.VisualCpp.Tools.Core" })
|
||||
$LatestVCPackage = ($VSPackages | ? { $_.id -eq "Microsoft.VisualCpp.Tools.Core" })
|
||||
$LatestVCToolsVersion = $LatestVCPackage.version;
|
||||
|
||||
$VSRoot = (& 'C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe' -latest -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property 'resolvedInstallationPath')
|
||||
$VCToolsRoot = Join-Path $VSRoot "VC\Tools\MSVC"
|
||||
|
||||
# We have observed a few instances where the VC tools package version actually
|
||||
# differs from the version on the files themselves. We might as well check
|
||||
# whether the version we just found _actually exists_ before we use it.
|
||||
# We'll use whichever highest version exists.
|
||||
$PackageVCToolPath = Join-Path $VCToolsRoot $LatestVCToolsVersion
|
||||
If ($Null -Eq (Get-Item $PackageVCToolPath -ErrorAction:Ignore)) {
|
||||
$VCToolsVersions = Get-ChildItem $VCToolsRoot | ForEach-Object {
|
||||
[Version]$_.Name
|
||||
} | Sort -Descending
|
||||
$LatestActualVCToolsVersion = $VCToolsVersions | Select -First 1
|
||||
|
||||
If ([Version]$LatestVCToolsVersion -Ne $LatestActualVCToolsVersion) {
|
||||
Write-Output "VC Tools Mismatch: Directory = $LatestActualVCToolsVersion, Package = $LatestVCToolsVersion"
|
||||
$LatestVCToolsVersion = $LatestActualVCToolsVersion.ToString(3)
|
||||
}
|
||||
}
|
||||
|
||||
Write-Output "Latest VCToolsVersion: $LatestVCToolsVersion"
|
||||
Write-Output "Updating VCToolsVersion environment variable for job"
|
||||
Write-Output "##vso[task.setvariable variable=VCToolsVersion]$LatestVCToolsVersion"
|
||||
|
||||
@ -7,5 +7,8 @@
|
||||
<VersionMajor>1</VersionMajor>
|
||||
<VersionMinor>24</VersionMinor>
|
||||
<VersionInfoProductName>Windows Terminal</VersionInfoProductName>
|
||||
<VersionInfoCulture>1033</VersionInfoCulture>
|
||||
<!-- The default has a spacing problem -->
|
||||
<VersionInfoCopyRight>\xa9 Microsoft Corporation. All rights reserved.</VersionInfoCopyRight>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
|
||||
40
doc/Niksa.md
40
doc/Niksa.md
@ -15,7 +15,7 @@ This document serves as a storage point for those posts.
|
||||
## <a name="cmd"></a>Why do we avoid changing CMD.exe?
|
||||
`setlocal` doesn't behave the same way as an environment variable. It's a thing that would have to be put in at the top of the batch script that is `somefile.cmd` as one of its first commands to adjust the way that one specific batch file is processed by the `cmd.exe` engine. That's probably not suitable for your needs, but that's the way we have to go.
|
||||
|
||||
I don't think anyone is disagreeing with you, @mikemaccana, that this would be a five minute development change to read that environment variable and change the behavior of `cmd.exe`. It absolutely would be a tiny development time.
|
||||
I don't think anyone is disagreeing with you, @mikemaccana, that this would be a five minute development change to read that environment variable and change the behavior of `cmd.exe`. It absolutely would be a tiny development time.
|
||||
|
||||
It's just that from our experience, we know there's going to be a 3-24 month bug tail here where we get massive investigation callbacks by some billion dollar enterprise customer who for whatever reason was already using the environment variable we pick for another purpose. Their script that they give their rank-and-file folks will tell them to press Ctrl+C at some point in the batch script to do whatever happens, it will do something different, those people will notice the script doesn't match the computer anymore. They will then halt the production line and tell their supervisor. The supervisor tells some director. Their director comes screaming at their Microsoft enterprise support contract person that we've introduced a change to the OS that is costing them millions if not billions of dollars in shipments per month. Our directors at Microsoft then come bashing down our doors angry with us and make us fix it ASAP or revert it, we don't get to go home at 5pm to our families or friends because we're fixing it, we get stressed the heck out, we have to spin up servicing potentially for already shipped operating systems which is expensive and headache-causing...etc.
|
||||
|
||||
@ -27,7 +27,7 @@ I would highly recommend that Gulp convert to using PowerShell scripts and that
|
||||
|
||||
Original Source: https://github.com/microsoft/terminal/issues/217#issuecomment-404240443
|
||||
|
||||
_Addendum_: cmd.exe is the literal embodiment of [xkcd#1172]([url](https://xkcd.com/1172/)). Every change, no matter how small, will break _someone_.
|
||||
_Addendum_: cmd.exe is the literal embodiment of [xkcd#1172]([url](https://xkcd.com/1172/)). Every change, no matter how small, will break _someone_.
|
||||
|
||||
## <a name="screenPerf"></a>Why is typing-to-screen performance better than every other app?
|
||||
|
||||
@ -37,33 +37,33 @@ Also, I'm happy to discuss this with you until you're utterly sick of reading it
|
||||
|
||||
If I had to take an educated guess as to what is making us faster than pretty much any other application on Windows at putting your text on the screen... I would say it is because that is literally our only job! Also probably because we are using darn near the oldest and lowest level APIs that Windows has to accomplish this work.
|
||||
|
||||
Pretty much everything else you've listed has some sort of layer or framework involved, or many, many layers and frameworks, when you start talking about Electron and JavaScript. We don't.
|
||||
Pretty much everything else you've listed has some sort of layer or framework involved, or many, many layers and frameworks, when you start talking about Electron and JavaScript. We don't.
|
||||
|
||||
We have one bare, super un-special window with no additional controls attached to it. We get our keys fed into us from just barely above the kernel given that we're processing them from window messages and not from some sort of eventing framework common to pretty much any other more complicated UI framework than ours (WPF, WinForms, UWP, Electron). And we dump our text straight onto the window surface using GDI's [PolyTextOut](https://docs.microsoft.com/en-us/windows/desktop/api/wingdi/nf-wingdi-polytextoutw) with no frills.
|
||||
We have one bare, super un-special window with no additional controls attached to it. We get our keys fed into us from just barely above the kernel given that we're processing them from window messages and not from some sort of eventing framework common to pretty much any other more complicated UI framework than ours (WPF, WinForms, UWP, Electron). And we dump our text straight onto the window surface using GDI's [PolyTextOut](https://docs.microsoft.com/en-us/windows/desktop/api/wingdi/nf-wingdi-polytextoutw) with no frills.
|
||||
|
||||
Even `notepad.exe` has multiple controls on its window at the very least and is probably (I haven't looked) using some sort of library framework in the edit control to figure out its text layout (which probably is using another library framework for internationalization support...)
|
||||
|
||||
Of course this also means that we have trade offs. We don't support fully international text like pretty much every other application will. RTL? No go zone right now. Surrogate pairs and emoji? We're getting there but not there yet. Indic scripts? Nope.
|
||||
Of course this also means that we have trade offs. We don't support fully international text like pretty much every other application will. RTL? No go zone right now. Surrogate pairs and emoji? We're getting there but not there yet. Indic scripts? Nope.
|
||||
|
||||
Why are we like this? For one, `conhost.exe` is old as dirt. It has to use the bare metal bottom layer of everything because it was created before most of those other frameworks were created. And also it maintains as low/bottom level as possible because it is pretty much the first thing that one needs to bring up when bringing up a new operating system edition or device before you have all the nice things like frameworks or what those frameworks require to operate. Also it's written in C/C++ which is about as low and bare metal as we can get.
|
||||
|
||||
Will this UI enhancement come to other apps on Windows? Almost certainly not. They have too much going on which is both a good and a bad thing. I'm jealous of their ability to just call one method and layout text in an uncomplicated manner in any language without manually calculating pixels or caring about what styles apply to their font. But my manual pixel calculations, dirty region math, scroll region madness, and more makes it so we go faster than them. I'm also jealous that when someone says "hey can you add a status bar to the bottom of your window" that they can pretty much click and drag that into place with their UI Framework and it will just work where as for us, it's been a backlog item forever and gives me heartburn to think about implementing.
|
||||
Will this UI enhancement come to other apps on Windows? Almost certainly not. They have too much going on which is both a good and a bad thing. I'm jealous of their ability to just call one method and layout text in an uncomplicated manner in any language without manually calculating pixels or caring about what styles apply to their font. But my manual pixel calculations, dirty region math, scroll region madness, and more makes it so we go faster than them. I'm also jealous that when someone says "hey can you add a status bar to the bottom of your window" that they can pretty much click and drag that into place with their UI Framework and it will just work whereas for us, it's been a backlog item forever and gives me heartburn to think about implementing.
|
||||
|
||||
Will we try to keep it from regressing? Yes! Right now it's sort of a manual process. We identify that something is getting slow and then we go haul out [WPR](https://docs.microsoft.com/en-us/windows-hardware/test/wpt/windows-performance-recorder) and start taking traces. We stare down the hot paths and try to reason out what is going on and then improve them. For instance, in the last cycle or two, we focused on heap allocations as a major area where we could improve our end-to-end performance, changing a ton of our code to use stack-constructed iterator-like facades over the underlying request buffer instead of translating and allocating it into a new heap space for each level of processing.
|
||||
Will we try to keep it from regressing? Yes! Right now it's sort of a manual process. We identify that something is getting slow and then we go haul out [WPR](https://docs.microsoft.com/en-us/windows-hardware/test/wpt/windows-performance-recorder) and start taking traces. We stare down the hot paths and try to reason out what is going on and then improve them. For instance, in the last cycle or two, we focused on heap allocations as a major area where we could improve our end-to-end performance, changing a ton of our code to use stack-constructed iterator-like facades over the underlying request buffer instead of translating and allocating it into a new heap space for each level of processing.
|
||||
|
||||
As an aside, @bitcrazed wants us to automate performance tests in some conhost specific way, but I haven't quite figured out a controlled environment to do this in yet. The Windows Engineering System runs performance tests each night that give us a coarse-grained way of knowing if we messed something up for the whole operating system, and they technically offer a fine-grained way for us to insert our own performance tests... but I just haven't got around to that yet. If you have an idea for a way for us to do this in an automated fashion, I'm all ears.
|
||||
|
||||
If there's anything else you'd like to know, let me know. I could go on all day. I deleted like 15 tangents from this reply before posting it....
|
||||
If there's anything else you'd like to know, let me know. I could go on all day. I deleted like 15 tangents from this reply before posting it....
|
||||
|
||||
Original Source: https://github.com/microsoft/terminal/issues/327#issuecomment-447391705
|
||||
|
||||
## <a name="gfxMsgStack"></a>How are the Windows graphics/messaging stack assembled?
|
||||
|
||||
@stakx, I am referring to USER32 and GDI32.
|
||||
@stakx, I am referring to USER32 and GDI32.
|
||||
|
||||
I'll give you a cursory overview of what I know off the top of my head without spending hours confirming the details. As such, some of this is subject to handwaving and could be mildly incorrect but is probably in the right direction. Consider every statement to be my personal knowledge on how the world works and subject to opinion or error.
|
||||
|
||||
For the graphics part of the pipeline (GDI32), the user-mode portions of GDI are pretty far down. The app calls GDI32, some work is done in that DLL on the user-mode side, then a kernel call jumps over to the kernel and drawing occurs.
|
||||
For the graphics part of the pipeline (GDI32), the user-mode portions of GDI are pretty far down. The app calls GDI32, some work is done in that DLL on the user-mode side, then a kernel call jumps over to the kernel and drawing occurs.
|
||||
|
||||
The portion that you're thinking of regarding "silently converted to sit on top of other stuff" is probably that once we hit the kernel calls, a bunch of the kernel GDI stuff tends to be re-platformed on top of the same stuff as DirectX when it is actually handled by the NVIDIA/AMD/Intel/etc. graphics driver and the GPU at the bottom of the stack. I think this happened with the graphics driver re-architecture that came as a part of WDDM for Windows Vista. There's a document out there somewhere about what calls are still really fast in GDI and which are slower as a result of the re-platforming. Last time I found that document and checked, we were using the fast ones.
|
||||
|
||||
@ -71,11 +71,11 @@ On top of GDI, I believe there are things like Common Controls or comctl32.dll w
|
||||
|
||||
As for DirectWrite and D2D and D3D and DXGI themselves, they're a separate set of commands and paths that are completely off to the side from GDI at all both in user and kernel mode. They're not really related other than that there's some interoperability provisions between the two. Most of our other UI frameworks tend to be built on top of the DirectX stack though. XAML is for sure. I think WPF is. Not sure about WinForms. And I believe the composition stack and the window manager are using DirectX as well.
|
||||
|
||||
As for the input/interaction part of the pipeline (USER32), I tend to find most other newer things (at least for desktop PCs) are built on top of what is already there. USER32's major concept is windows and window handles and everything is sent to a window handle. As long as you're on a desktop machine (or a laptop or whatever... I mean a classic-style Windows-powered machine), there's a window handle involved and messages floating around and that means we're talking USER32.
|
||||
As for the input/interaction part of the pipeline (USER32), I tend to find most other newer things (at least for desktop PCs) are built on top of what is already there. USER32's major concept is windows and window handles and everything is sent to a window handle. As long as you're on a desktop machine (or a laptop or whatever... I mean a classic-style Windows-powered machine), there's a window handle involved and messages floating around and that means we're talking USER32.
|
||||
|
||||
The window message queue is just a straight up FIFO (more or less) of whatever input has occurred relevant to that window while it's in the foreground + whatever has been sent to the window by other components in the system.
|
||||
The window message queue is just a straight up FIFO (more or less) of whatever input has occurred relevant to that window while it's in the foreground + whatever has been sent to the window by other components in the system.
|
||||
|
||||
The newer technologies and the frameworks like XAML and WPF and WinForms tend to receive the messages from the window message queue one way or another and process them and turn them into event callbacks to various objects that they've provisioned within their world.
|
||||
The newer technologies and the frameworks like XAML and WPF and WinForms tend to receive the messages from the window message queue one way or another and process them and turn them into event callbacks to various objects that they've provisioned within their world.
|
||||
|
||||
However, the newer technologies that also work on other non-desktop platforms like XAML tend to have the ability to process stuff off of a completely different non-USER32 stack as well. There's a separate parallel stack to USER32 with all of our new innovations and realizations on how input and interaction should occur that doesn't exactly deal with classic messaging queues and window handles the same way. This is the whole Core* family of things like CoreWindow and CoreMessaging. They also have a different concept of "what is a user" that isn't so centric around your butt in rolling chair in front of a screen with a keyboard and mouse on the desk.
|
||||
|
||||
@ -83,7 +83,7 @@ Now, if you're on XAML or one of the other Frameworks... all this intricacy is h
|
||||
|
||||
The trick is that GDI32 and USER32 were designed for a limited world with a limited set of commands. Desktop PCs were the only thing that existed, single user at the keyboard and mouse, simple graphics output to a VGA monitor. So using them directly at the "low level" like conhost does is pretty easy. The new platforms could be used at the "low level" but they're orders of magnitude more complicated because they now account for everything that has happened with personal computing in 20+ years like different form factors, multiple active users, multiple graphics adapters, and on and on and on and on. So you tend to use a framework when using the new stuff so your head doesn't explode. They handle it for you, but they handle more than they ever did before so they're slower to some degree.
|
||||
|
||||
So are GDI32 and USER32 "lower" than the new stuff? Sort of.
|
||||
So are GDI32 and USER32 "lower" than the new stuff? Sort of.
|
||||
Can you get that low with the newer stuff? Mostly yes, but you probably shouldn't and don't want to.
|
||||
Does new live on top of old or is old replatformed on the new? Sometimes and/or partially.
|
||||
Basically... it's like the answer to anything software... "it's an unmitigated disaster and if we all stepped back a moment, we should be astounded that it works at all." :P
|
||||
@ -94,7 +94,7 @@ Original Source: https://github.com/microsoft/terminal/issues/327#issuecomment-4
|
||||
|
||||
## <a name="fesb"></a>Output Processing between "Far East" and "Western"
|
||||
|
||||
>
|
||||
>
|
||||
> ```
|
||||
> if (WI_IsFlagSet(CharType, C1_CNTRL))
|
||||
> ```
|
||||
@ -120,7 +120,7 @@ Note in both of these, there is a little bit of indirection before `MultiByteToW
|
||||
When we took over the console codebase, this variation between "Western" and "Eastern" countries was especially painful because `conhost.exe` would choose which one it was in based on the `Codepage for Non-Unicode Applications` set in the Control Panel's Regional > Administrative panel and it could only be changed with a reboot. It wouldn't even change properly when you `chcp` to a different codepage. Heck, `chcp` would deny you from switching into many codepages. There was a block in place to prevent going to an "Eastern" codepage if you booted up in a "Western" codepage. There was also a block preventing you from going between "Eastern" codepages, if I recall correctly.
|
||||
|
||||
In modernizing, I decided a few things:
|
||||
1. What's good for the "Far East" should be good for the rest of the world. CJK languages that encompassed the "Far East" code have to be able to handle "Western" text as well even if the reverse wasn't true.
|
||||
1. What's good for the "Far East" should be good for the rest of the world. CJK languages that encompassed the "Far East" code have to be able to handle "Western" text as well even if the reverse wasn't true.
|
||||
2. We need to scrub all usages of "Far East" from the code. Someone already started that and replaced them with "East Asia" except then they left behind the shorthand of "FE" prefixing dozens of functions which made it hard to follow the code. It took us months to realize "FE" and "East Asia" were the same thing.
|
||||
3. It's obnoxious that the way this was handled was to literally double-define every output function in the code base to have two definitions, compile them both into the conhost, then choose to run down the SB_ versions or the FE_ versions depending on the startup Non-Unicode codepage. It was a massive pile of complex pre-compilation `#ifdef` and `#else`s that would sometimes surround individual lines in the function bodies. Gross.
|
||||
4. The fact that the FE_ versions of the functions were way slower than the SB_ ones was unacceptable even for the same output of Latin-character text.
|
||||
@ -139,13 +139,13 @@ Original Source: https://github.com/microsoft/terminal/issues/166#issuecomment-5
|
||||
|
||||
## <a name="backport"></a>Why do we not backport things?
|
||||
|
||||
Someone has to prove that this is costing millions to billions of dollars of lost productivity or revenue to outweigh the risks of shipping the fix to hundreds of millions of Windows machines and potentially breaking something.
|
||||
Someone has to prove that this is costing millions to billions of dollars of lost productivity or revenue to outweigh the risks of shipping the fix to hundreds of millions of Windows machines and potentially breaking something.
|
||||
|
||||
Our team generally finds it pretty hard to prove that against the developer audience given that they're only a small portion of the total installed market of Windows machines.
|
||||
Our team generally finds it pretty hard to prove that against the developer audience given that they're only a small portion of the total installed market of Windows machines.
|
||||
|
||||
Our only backport successes really come from corporations with massive addressable market (like OEMs shipping PCs) who complain that this is fouling up their manufacturing line (or something of that ilk). Otherwise, our management typically says that the risks don't outweigh the benefits.
|
||||
|
||||
It's also costly in terms of time, effort, and testing for us to validate a modification to a released OS. We have a mindbogglingly massive amount of automated machinery dedicated to processing and validating the things that we check in while developing the current OS builds. But it's a special costly ask to spin up some to all of those activities to validate backported fixes. We do it all the time for Patch Tuesday, but in those patches, they only pass through the minimum number of fixes required to maximize the restoration of productivity/security/revenue/etc. because every additional fix adds additional complexity and additional risk.
|
||||
It's also costly in terms of time, effort, and testing for us to validate a modification to a released OS. We have a mindbogglingly massive amount of automated machinery dedicated to processing and validating the things that we check in while developing the current OS builds. But it's a special costly ask to spin up some to all of those activities to validate backported fixes. We do it all the time for Patch Tuesday, but in those patches, they only pass through the minimum number of fixes required to maximize the restoration of productivity/security/revenue/etc. because every additional fix adds additional complexity and additional risk.
|
||||
|
||||
So from our little team working hard to make developers happy, we virtually never make the cut for servicing. We're sorry, but we hope you can understand. It's just the reality of the situation to say "nope" when people ask for a backport. In our team's ideal world, you would all be running the latest console bits everywhere every time we make a change. But that's just not how it is today.
|
||||
|
||||
@ -189,7 +189,7 @@ _guest speaker @zadjii-msft_
|
||||
|
||||
I think there might be a bit of a misunderstanding here - there are two different kinds of applications we're talking about here:
|
||||
* shell applications, like `cmd.exe`, `powershell`, `zsh`, etc. These are text-only applications that emit streams of characters. They don't care at all about how they're eventually rendered to the user. These are also sometimes referred to as "commandline client" applications.
|
||||
* terminal applications, like the Windows Terminal, gnome-terminal, xterm, iterm2, hyper. These are graphical applications that can be used to render the output of commandline clients.
|
||||
* terminal applications, like the Windows Terminal, gnome-terminal, xterm, iterm2, hyper. These are graphical applications that can be used to render the output of commandline clients.
|
||||
|
||||
On Windows, if you just run `cmd.exe` directly, the OS will create an instance of `conhost.exe` as the _terminal_ for `cmd.exe`. The same thing happens for `powershell.exe`, the system will create a new conhost window for any client that's not already connected to a terminal of some sort. This has lead to an enormous amount of confusion for people thinking that a conhost window is actually a "`cmd` window". `cmd` can't have a window, it's just a commandline application. Its window is always some other terminal.
|
||||
|
||||
|
||||
@ -31,12 +31,12 @@ Prerequisites:
|
||||
1. Right click the machine name in the `Device Manager` list and choose `Launch T-Shell`. You can also use `Connect via Console` to get a "remote desktop"-like session to the KVM port on the VM.
|
||||
1. In T-shell, use `testd Microsoft.Console.TestLab.Desktop.testlist` or a command of that format with a different TESTLIST or TESTMD name from our project (see the [UniversalTest.md] documentation). The `testd` utility will automatically resolve the build/branch/flavor information, dig through the build shares for the matching TESTLIST/TESTMD metadata, and attempt to deploy all relevant packages and dependencies on the device. When it's successful, it will move onto running all the tests and giving you the results. On conclusion, the test results should pop up in the web browser or the `Hubble - Log Viewer` tool provided by the Engineering Systems team.
|
||||
|
||||
If some of the above things do not work, go to [https://osgwiki.com] and type them into the Search bar. For instance, if T-Shell isn't found or working, you can find out where to get it or download it on `OSGWiki`. The same goes for the other commands besides `testd` to use in T-shell and more information on what `Hubble` or `Nebula` are.
|
||||
If some of the above things do not work, go to [https://osgwiki.com] and type them into the Search bar. For instance, if T-Shell isn't found or working, you can find out where to get it or download it on `OSGWiki`. The same goes for the other commands besides `testd` to use in T-shell and more information on what `Hubble` or `Nebula` are.
|
||||
|
||||
Presumably now you have a failure. Or a success. You can attempt to spelunk the logs in `Hubble` and you might come to a conclusion. Or you can move onto debugging directly.
|
||||
|
||||
Now that you've relied on `testd` to get everything deployed and orchestrated and run once on the device, you can use `execd` to run things again or to run a smaller subset of things on the remote device through `T-Shell`.
|
||||
Now that you've relied on `testd` to get everything deployed and orchestrated and run once on the device, you can use `execd` to run things again or to run a smaller subset of things on the remote device through `T-Shell`.
|
||||
|
||||
By default, in the `Universal Test` world, everything will be deployed onto the remote machine at `C:\data\test\bin`. In T-Shell, use `cdd C:\data\test\bin` to change to that directory and then `execd te.exe Microsoft.Console.Host.FeatureTests.dll /name:*TestReadFileEcho*` to run just one specific test. Of course you should substitute the file name and test name parameters as makes sense. And of course you can find out more about `cdd` and `execd` on the `T-shell` page of `OSGWiki`.
|
||||
By default, in the `Universal Test` world, everything will be deployed onto the remote machine at `C:\data\test\bin`. In T-Shell, use `cdd C:\data\test\bin` to change to that directory and then `execd te.exe Microsoft.Console.Host.FeatureTests.dll /name:*TestReadFileEcho*` to run just one specific test. Of course, you should substitute the file name and test name parameters as makes sense. And of course you can find out more about `cdd` and `execd` on the `T-shell` page of `OSGWiki`.
|
||||
|
||||
Fortunately, running things through `T-shell` in this fashion is exactly the same way that the testlab orchestrates the tests. If you still don't get good data this way, you can use the `Connect via Console` mechanism way above to try to run things under `WinDBG` or the `Visual Studio Remote Debugger` manually on the machine to get them to repro or under the debugger more completely.
|
||||
|
||||
@ -32,13 +32,21 @@
|
||||
]
|
||||
},
|
||||
"DynamicProfileSource": {
|
||||
"enum": [
|
||||
"Windows.Terminal.Wsl",
|
||||
"Windows.Terminal.Azure",
|
||||
"Windows.Terminal.PowershellCore",
|
||||
"Windows.Terminal.VisualStudio"
|
||||
],
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"enum": [
|
||||
"Microsoft.WSL",
|
||||
"Windows.Terminal.Wsl",
|
||||
"Windows.Terminal.Azure",
|
||||
"Windows.Terminal.PowershellCore",
|
||||
"Windows.Terminal.VisualStudio"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"BellStyle": {
|
||||
"oneOf": [
|
||||
@ -2368,6 +2376,16 @@
|
||||
"description": "When set to true, the terminal will focus the pane on mouse hover.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"experimental.scrollToZoom": {
|
||||
"default": true,
|
||||
"description": "When set to true, holding the Ctrl key while scrolling will increase or decrease the terminal font size.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"experimental.scrollToChangeOpacity": {
|
||||
"default": true,
|
||||
"description": "When set to true, holding the Ctrl and Shift keys while scrolling will change the window opacity.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"compatibility.allowHeadless": {
|
||||
"default": false,
|
||||
"description": "When set to true, Windows Terminal will run in the background. This allows globalSummon and quakeMode actions to work even when no windows are open.",
|
||||
|
||||
@ -6,7 +6,7 @@ When creating a new DLL, it was really helpful to reference an existing DLL's `.
|
||||
|
||||
- [ ] Make sure to `<Import>` our pre props at the _top_ of the vcxproj, and our post props at the _bottom_ of the vcxproj.
|
||||
```
|
||||
<!-- pre props -->
|
||||
<!-- pre props -->
|
||||
<Import Project="..\..\..\common.openconsole.props" Condition="'$(OpenConsoleDir)'==''" />
|
||||
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.pre.props" />
|
||||
|
||||
@ -35,7 +35,7 @@ DllGetActivationFactory = WINRT_GetActivationFactory PRIVATE
|
||||
- _Note_: If your new library eventually rolls up as a reference to our Centennial Packaging project `CascadiaPackage`, you don't have to worry about manually adding your definitions to the `AppXManifest.xml` because the Centennial Packaging project automatically enumerates the reference tree of WinMDs and stitches that information into the `AppXManifest.xml`. However, if your new project does _not_ ultimately roll up to a packaging project that will automatically put the references into `AppXManifest`, you will have to add them in manually.
|
||||
|
||||
### Troubleshooting
|
||||
- If you hit an error that looks like this:
|
||||
- If you hit an error that looks like this:
|
||||
```
|
||||
X found processing metadata file ..\blah1\Microsoft.UI.Xaml.winmd, type already exists in file ..\blah\NewDLLProject\Microsoft.UI.Xaml.winmd.
|
||||
```
|
||||
@ -51,4 +51,4 @@ DllGetActivationFactory = WINRT_GetActivationFactory PRIVATE
|
||||
|
||||
- If you hit a `Class not Registered` error, this might be because a class isn't getting registered in the app manifest. You can go check `src/cascadia/CascadiaPackage/bin/x64/Debug/AppX/AppXManifest.xml` to see if there exist entries to the classes of your newly created DLL. If the references aren't there, double check that you've added `<ProjectReference>` blocks to both `WindowsTerminal.vcxproj` and `TerminalApp.vcxproj`.
|
||||
|
||||
- If you hit an extremely vague error along the lines of `Error in the DLL`, and right before that line you notice that your new DLL is loaded and unloaded right after each other, double check that your new DLL's definitions show up in the `AppXManifest.xml` file. If your new DLL is included as a reference to a project that rolls up to `CascadiaPackage`, double check that you've created a `.def` file for the project. Otherwise if your new project _does not_ roll up to a package that populates the `AppXManifest` references for you, you'll have to add those references yourself.
|
||||
- If you hit an extremely vague error along the lines of `Error in the DLL`, and right before that line you notice that your new DLL is loaded and unloaded right after each other, double check that your new DLL's definitions show up in the `AppXManifest.xml` file. If your new DLL is included as a reference to a project that rolls up to `CascadiaPackage`, double check that you've created a `.def` file for the project. Otherwise, if your new project _does not_ roll up to a package that populates the `AppXManifest` references for you, you'll have to add those references yourself.
|
||||
|
||||
@ -9,7 +9,7 @@ issue id: 1564
|
||||
|
||||
## Abstract
|
||||
|
||||
Windows Terminal's settings model adheres to a cascading settings architecture. This allows a settings object to be defined incrementally across multiple layers of declarations. The value for any global setting like `copyOnSelect`, for example, is set to your settings.json value if one is defined, otherwise defaults.json, and otherwise a system set value. Profiles in particular are more complicated in that they must also take into account the values in `profiles.defaults` and dynamic profile generators.
|
||||
Windows Terminal's settings model adheres to a cascading settings architecture. This allows a settings object to be defined incrementally across multiple layers of declarations. The value for any global setting like `copyOnSelect`, for example, is set to your settings.json value if one is defined; otherwise, defaults.json, and otherwise a system set value. Profiles in particular are more complicated in that they must also take into account the values in `profiles.defaults` and dynamic profile generators.
|
||||
|
||||
This spec explores how to represent this feature in the Settings UI.
|
||||
|
||||
|
||||
@ -529,7 +529,7 @@ their own workflows.
|
||||
* `--local`: Save to the `.wt.json` in the CWD, if there is one (or create
|
||||
one)
|
||||
* `--parent`: Save to the `.wt.json` in the first ancestor of the CWD, if
|
||||
there is one. Otherwise create one here.
|
||||
there is one. Otherwise, create one here.
|
||||
* `--settings`: Manually save to the settings file?
|
||||
* `--profile`: save to this profile???? Not sure if this is actually possible.
|
||||
Maybe with the `WT_SESSION_ID` env var to figure out which profile is in use
|
||||
|
||||
@ -23,7 +23,7 @@ In a similar vein, many fonts allow for setting variations on the font along cer
|
||||
|
||||
### Font features
|
||||
|
||||
It is already possible to pass in a list of [font feature structs](https://docs.microsoft.com/en-us/windows/win32/api/dwrite/ns-dwrite-dwrite_font_feature) to DWrite for it to handle. A font feature struct contains only 2 things:
|
||||
It is already possible to pass in a list of [font feature structs](https://docs.microsoft.com/en-us/windows/win32/api/dwrite/ns-dwrite-dwrite_font_feature) to DWrite for it to handle. A font feature struct contains only 2 things:
|
||||
|
||||
1. A font feature tag
|
||||
2. A parameter value
|
||||
@ -78,7 +78,7 @@ Aside from additional parsing required for the settings file (which inherently o
|
||||
|
||||
### Compatibility
|
||||
|
||||
Older versions of Windows may not have the DWrite updates that allow for defining font features and axes of variation. We must make sure to fallback to the current implementation in these cases.
|
||||
Older versions of Windows may not have the DWrite updates that allow for defining font features and axes of variation. We must make sure to fall back to the current implementation in these cases.
|
||||
|
||||
### Performance, Power, and Efficiency
|
||||
|
||||
@ -102,4 +102,4 @@ We will also need to consider how we want to represent this in the settings UI.
|
||||
|
||||
[DWRITE_FONT_FEATURE structure](https://docs.microsoft.com/en-us/windows/win32/api/dwrite/ns-dwrite-dwrite_font_feature)
|
||||
|
||||
[DWRITE_FONT_AXIS_VALUE structure](https://docs.microsoft.com/en-us/windows/win32/api/dwrite_3/ns-dwrite_3-dwrite_font_axis_value)
|
||||
[DWRITE_FONT_AXIS_VALUE structure](https://docs.microsoft.com/en-us/windows/win32/api/dwrite_3/ns-dwrite_3-dwrite_font_axis_value)
|
||||
|
||||
@ -17,7 +17,7 @@ I work remotely as a developer, so I have to spend a lot of hours in front of my
|
||||
|
||||
Normally I like dark modes in all the programs and apps I use, but when there's too much sunlight, it becomes annoying, and sometimes even painful, to work in dark mode. So, I have all the programs and apps I use (at least, those that can) set to switch their color themes to what the system has.
|
||||
|
||||
The company I work for sent me a Macbook Pro, and my personal phone is an Android, both with automatic dark mode at sunset and light mode at sunrise, and in those devices it's been working relatively well. In Windows, as it is known, there's no such feature, so I manually change between dark and light mode when it's needed, and most of the programs and apps I use go along with this change. Windows Terminal, is not one of them.
|
||||
The company I work for sent me a MacBook Pro, and my personal phone is an Android, both with automatic dark mode at sunset and light mode at sunrise, and in those devices it's been working relatively well. In Windows, as it is known, there's no such feature, so I manually change between dark and light mode when it's needed, and most of the programs and apps I use go along with this change. Windows Terminal, is not one of them.
|
||||
|
||||
The theme changes just as expected, but in an app like this, this change only affects the top of the window, leaving almost all of the screen at the mercy of what the color scheme is, and it doesn't depend on the theme, which defeats any attempt to make a good use of the `system` theme feature.
|
||||
|
||||
|
||||
@ -94,7 +94,7 @@ configurations:
|
||||
|
||||
- `"useExisting"`: always glom to the most recent window, regardless of desktop.
|
||||
- `"useExistingOnSameDesktop"`: Only glom if there's an existing window on this
|
||||
virtual desktop, otherwise create a new window. This will be the new default
|
||||
virtual desktop; otherwise, create a new window. This will be the new default
|
||||
value.
|
||||
- `"useNew"`: Never glom, always create a new window. This is technically the
|
||||
current behavior of the Terminal.
|
||||
|
||||
@ -362,7 +362,7 @@ Essentially, the probabilistic elective monarchy will work in the following way:
|
||||
register.
|
||||
3. After registering as a server for `Monarch`s, attempt to create a `Monarch`
|
||||
using `winrt::create_instance`.
|
||||
4. Using that `Monarch`, ask it for it's PID.
|
||||
4. Using that `Monarch`, ask it for its PID.
|
||||
- If that PID is the same as the PID of the current process, then the window
|
||||
process knows that it is the monarch.
|
||||
- If that PID is some other process, then we know that we're not currently
|
||||
@ -1102,7 +1102,7 @@ launch to use seems like an obvious next step. See also [#961].
|
||||
- `true` or `"always"`: always glom to the most recent window, regardless of
|
||||
desktop
|
||||
- `"sameDesktop"`: Only glom if there's an existing window on this virtual
|
||||
desktop, otherwise create a new window
|
||||
desktop; otherwise, create a new window
|
||||
- `false` or `"never"`: Never glom, always create a new window.
|
||||
|
||||
|
||||
|
||||
@ -13,7 +13,7 @@ This spec is for feature request #605 "Search". It goes over the details of a ne
|
||||
|
||||
## Inspiration
|
||||
|
||||
One of the superior features of iTerm2 is it's content search. The search comes in two variants: search from active tab and search from all tabs. In almost any editor, there is an roughly equivalent string search. We also want to realize search experience in Terminal. There will be two variants, search within one tab or from multiple tabs. We will start with one-tab search implementation.
|
||||
One of the superior features of iTerm2 is it's content search. The search comes in two variants: search from active tab and search from all tabs. In almost any editor, there is a roughly equivalent string search. We also want to realize search experience in Terminal. There will be two variants, search within one tab or from multiple tabs. We will start with one-tab search implementation.
|
||||
|
||||
## Solution Design
|
||||
|
||||
|
||||
@ -331,7 +331,7 @@ Are there other allocation policies we need to consider?
|
||||
- requires coordination between tooling teams both within and without Microsoft (regarding any tool that operates on
|
||||
or produces PE files)
|
||||
|
||||
- An exported symbol that shells can check for to determine whether to wait for the attached process to exit
|
||||
- An exported symbol that shells can check for in order to determine whether to wait for the attached process to exit
|
||||
- relies on shells to update and check for this
|
||||
- cracking an executable to look for symbols is probably the last thing shells want to do
|
||||
- we could provide an API to determine whether to wait or return?
|
||||
|
||||
@ -360,7 +360,7 @@ GUID GetNamespaceGuid(IDynamicProfileGenerator& generator);
|
||||
GUID GetGuidForName(IDynamicProfileGenerator& generator, std::wstring& name);
|
||||
```
|
||||
|
||||
The generator does not _need_ to use `GetGuidForName` to generate guids for it's
|
||||
The generator does not _need_ to use `GetGuidForName` to generate guids for its
|
||||
profiles. If the generator can determine another way to generate stable GUIDs
|
||||
for its profiles, it's free to use whatever method it wants. `GetGuidForName` is
|
||||
provided as a convenience.
|
||||
|
||||
@ -151,11 +151,11 @@ void CascadiaSettings::LayerJson(const Json::Value& json)
|
||||
// repeat the same for Profiles...
|
||||
}
|
||||
```
|
||||
For `defaults.json`, `_globals` will now hold all of the values set in `defaults.json`. If any settings were omitted from the `defaults.json`, `_globals` will fallback to its parent (a `GlobalAppSettings` consisting purely of system-defined values).
|
||||
For `defaults.json`, `_globals` will now hold all of the values set in `defaults.json`. If any settings were omitted from the `defaults.json`, `_globals` will fall back to its parent (a `GlobalAppSettings` consisting purely of system-defined values).
|
||||
|
||||
For `settings.json`, `_globals` will only hold the values set in `settings.json`. If any settings were omitted from `settings.json`, `_globals` will fallback to its parent (the `GlobalAppSettings` built from `defaults.json`).
|
||||
For `settings.json`, `_globals` will only hold the values set in `settings.json`. If any settings were omitted from `settings.json`, `_globals` will fall back to its parent (the `GlobalAppSettings` built from `defaults.json`).
|
||||
|
||||
This process becomes a bit more complex for `Profile` because it can fallback in the following order:
|
||||
This process becomes a bit more complex for `Profile` because it can fall back in the following order:
|
||||
1. `settings.json` profile
|
||||
2. `settings.json` `profiles.defaults`
|
||||
3. (if a dynamic profile) the hard-coded value in the dynamic profile generator
|
||||
|
||||
@ -101,8 +101,8 @@ The scopes would work as follows:
|
||||
this tab.
|
||||
- **TODO!: FOR DISCUSSION**: Should this disable the tab's
|
||||
"broadcastToAllPanes" setting? Or should it leave that alone?
|
||||
* `"disableBroadcastInput"`: Set the global setting to false, the tab's setting
|
||||
to false, and clear the set of panes being broadcasted to for this tab.
|
||||
* `"disableBroadcastInput"`: For this tab, set the global setting to false,
|
||||
the tab's setting to false, and clear the set of panes being broadcasted.
|
||||
- **TODO!** This could also just be `"action": "toggleBroadcastInput",
|
||||
"scope": "none"`
|
||||
|
||||
@ -161,7 +161,7 @@ As far as actions, we're looking at something like:
|
||||
from the broadcast set. Otherwise, add all the panes from this tab to the
|
||||
broadcast set.
|
||||
* **D** toggle sending input to the current pane
|
||||
* If this pane is in the broadcast set, remove it. Otherwise add it.
|
||||
* If this pane is in the broadcast set, remove it. Otherwise, add it.
|
||||
This seems to break down into the following actions:
|
||||
|
||||
```json
|
||||
|
||||
@ -8,12 +8,12 @@ Since accessibility is a very broad area, this document is intended to present r
|
||||
### First-party terminals
|
||||
For many years, Console Host (Conhost) was the only first-party terminal on Windows. In 2019, Windows Terminal was released to the world as an open source first-party terminal. Windows Terminal was distributed through the Microsoft Store and received regular updates throughout the year, much more frequently than Conhost. In October 2022, Windows Terminal was enabled as the default terminal on Windows.
|
||||
|
||||
A significant amount of code is shared between Conhost and Windows Terminal to create the terminal area. To enable an accessible experience for this area, a shared UI Automation provider was introduced in 2019[^1], enabling accessibility tools to navigate and read contents from the terminal area. In 2020, Windows Terminal was updated to dispatch UIA events signaling when the cursor position, text output, or selection changed; this left the work of identifying what changed in the output to the attached screen reader application[^2]. In 2022, Windows Terminal was updated to dispatch UIA notifications with a payload of what text was written to the screen[^3].
|
||||
A significant amount of code is shared between Conhost and Windows Terminal to create the terminal area. To enable an accessible experience for this area, a shared UI Automation provider was introduced in 2019[^1], enabling accessibility tools to navigate and read contents from the terminal area. In 2020, Windows Terminal was updated to dispatch UIA events signaling when the cursor position, text output, or selection changed; this left the work of identifying what changed in the output to the attached screen reader application[^2]. In 2022, Windows Terminal was updated to dispatch UIA notifications with a payload of what text was written to the screen[^3].
|
||||
|
||||
### Internal Partners
|
||||
There are many first-party command-line applications on Windows. The following are a few examples of those that are regularly updated:
|
||||
- [**GitHub CLI**](https://cli.github.com/): a tool that can be used to query and interact with GitHub repos (open source)
|
||||
- [**Winget**](https://github.com/microsoft/winget-cli): a tool to install applications and other packages
|
||||
- [**WinGet**](https://github.com/microsoft/winget-cli): a tool to install applications and other packages
|
||||
- [**PSReadLine**](https://github.com/PowerShell/PSReadLine): a PowerShell module that enhances the input line experience
|
||||
- [**Windows Subsystem for Linux (WSL)**](https://learn.microsoft.com/en-us/windows/wsl/): a tool to manage and run GNU/Linux environments without a traditional virtual machine
|
||||
- [**PowerShell**](https://github.com/PowerShell/PowerShell): a cross-platform command-line shell (open source)
|
||||
@ -33,7 +33,7 @@ The following examples don't take over the entire viewport:
|
||||
- [**Oh My Posh**](https://ohmyposh.dev/): a tool to customize shell prompts
|
||||
- **git**: a tool for version control
|
||||
The following examples operate as command-line shells:
|
||||
- [**Bash**](https://www.gnu.org/software/bash/) is the default shell for most Linux distributions
|
||||
- [**Bash**](https://www.gnu.org/software/bash/) is the default shell for most Linux distributions
|
||||
- [**Fish shell**](https://fishshell.com/) provides a rich shell experience with features like autosuggestion support and VGA colors
|
||||
- [**Z shell**](https://zsh.sourceforge.io/) is an extended Bourne shell
|
||||
|
||||
@ -113,7 +113,7 @@ This issue is tracked by [megathread: Scrollbar Marks · Issue #11000](https://g
|
||||
### Mark Mode support for degenerate range
|
||||
[PR #13053](https://github.com/microsoft/terminal/pull/13053) added support for mark mode in Windows Terminal. Mark mode allows users to create and modify selections by exclusively using the keyboard. However, screen reader users have reported it as a strange experience because it always has a cell of text selected; this results in the screen reader reading "x selected, y unselected" as opposed to the expected "x" when moving the cursor around.
|
||||
|
||||
Unfortunately, the changes required to fix this are very extensive because selections are stored as two inclusive terminal coordinates, which makes it impossible to represent an empty selection.
|
||||
Unfortunately, the changes required to fix this are very extensive because selections are stored as two inclusive terminal coordinates, which makes it impossible to represent an empty selection.
|
||||
|
||||
This is tracked by [A11y: windows terminal emits selection/deselection events in mark mode when navigating with arrow keys · Issue #13447](https://github.com/microsoft/terminal/issues/13447).
|
||||
|
||||
@ -158,7 +158,7 @@ In 2022, Windows Terminal added UI Automation notifications that contained a pay
|
||||
UIA notifications have provided many compatibility benefits since screen readers automatically read notifications they receive. Additionally, this has provided the possibility for major performance enhancements as screen readers may no longer be required to diff the text buffer and figure out what has changed. NVDA has prototyped listening to notifications and ignoring text changed events entirely[^7]. However, it reveals underlying challenges with this new model such as how to handle passwords. The proposals listed in this section are intended to have Windows Terminal achieve improved performance and accessibility quality.
|
||||
|
||||
#### VT Screen Reader Control
|
||||
Some command-line applications are simply too difficult to create a consistent accessible experience. Applications that draw decorative content, for example, may have that content read by a screen reader.
|
||||
Some command-line applications are simply too difficult to create a consistent accessible experience. Applications that draw decorative content, for example, may have that content read by a screen reader.
|
||||
|
||||
In 2019, Daniel Imms wrote a spec proposing a VT sequence that can partially control the attached screen reader[^8]. This VT sequence consists of three main formats:
|
||||
1. Stop announcing incoming data to the screen reader. The screen reader will resume announcing incoming data if any key is pressed.
|
||||
@ -214,4 +214,4 @@ Generally, the reasoning behind these priorities can be broken down as follows:
|
||||
[^5]: [Implement the Delta E algorithm to improve color perception by PankajBhojwani · Pull Request #11095](https://github.com/microsoft/terminal/pull/11095)
|
||||
[^6]: [Change AdjustIndistinguishableColors to an enum setting instead of a boolean setting by PankajBhojwani · Pull Request #13512](https://github.com/microsoft/terminal/pull/13512)
|
||||
[^7]: [Prototype for Windows Terminal: Use notifications instead of monitoring for new text by leonardder · Pull Request #14047 · nvaccess/nvda (github.com)](https://github.com/nvaccess/nvda/pull/14047)
|
||||
[^8]: [Control Screen Reader from Applications (#18) · Issues · terminal-wg / specifications · GitLab](https://gitlab.freedesktop.org/terminal-wg/specifications/-/issues/18)
|
||||
[^8]: [Control Screen Reader from Applications (#18) · Issues · terminal-wg / specifications · GitLab](https://gitlab.freedesktop.org/terminal-wg/specifications/-/issues/18)
|
||||
|
||||
@ -22,7 +22,7 @@ Note: Existing profiles will disappear from Windows Terminal after adding their
|
||||
<string id="DefaultTerminalApplication">Default terminal application</string>
|
||||
<string id="DefaultTerminalApplicationText">Select the default terminal application used in Windows.
|
||||
|
||||
If you select Windows Terminal Preview and it is not installed the system will fallback to the legacy Windows Console Host. (Please note that the settings interfaces showing "Let windows decide" in this case as configuration.)</string>
|
||||
If you select Windows Terminal Preview and it is not installed the system will fall back to the legacy Windows Console Host. (Please note that the settings interfaces showing "Let windows decide" in this case as configuration.)</string>
|
||||
<string id="TermAppAutomatic">Automatic selection (Windows Terminal, if available)</string>
|
||||
<string id="TermAppConsoleHost">Windows Console Host (legacy)</string>
|
||||
<string id="TermAppWindowsTerminal">Windows Terminal</string>
|
||||
|
||||
@ -32,7 +32,7 @@
|
||||
BasedOn="{StaticResource TitleBarButtonStyle}"
|
||||
TargetType="{x:Type Button}">
|
||||
<Setter Property="Content" Value="" />
|
||||
<!-- Remove the default Button template's Triggers, otherwise they'll override our trigger below. -->
|
||||
<!-- Remove the default Button template's Triggers; otherwise, they'll override our trigger below. -->
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="{x:Type Button}">
|
||||
|
||||
@ -2969,7 +2969,7 @@ void TextBuffer::_SerializeRow(const ROW& row, const til::CoordType startX, cons
|
||||
// parameter and we'll calculate the position of the _end_ of those rows in
|
||||
// the new buffer. The rows's new value is placed back into this parameter.
|
||||
// Return Value:
|
||||
// - S_OK if we successfully copied the contents to the new buffer, otherwise an appropriate HRESULT.
|
||||
// - S_OK if we successfully copied the contents to the new buffer; otherwise, an appropriate HRESULT.
|
||||
void TextBuffer::Reflow(TextBuffer& oldBuffer, TextBuffer& newBuffer, const Viewport* lastCharacterViewport, PositionInformation* positionInfo)
|
||||
{
|
||||
const auto& oldCursor = oldBuffer.GetCursor();
|
||||
|
||||
@ -573,7 +573,7 @@ namespace
|
||||
TestCase{
|
||||
// This triggers the cursor being walked forward w/ newlines to maintain
|
||||
// distance from the last char in the buffer
|
||||
L"SBCS, cursor at end of buffer, otherwise same as previous test",
|
||||
L"SBCS, cursor at end of buffer; otherwise, same as previous test",
|
||||
{
|
||||
TestBuffer{
|
||||
{ 6, 5 },
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 647 B |
Binary file not shown.
|
Before Width: | Height: | Size: 787 B |
@ -7,6 +7,7 @@
|
||||
<ProjectName>elevate-shim</ProjectName>
|
||||
<TargetName>elevate-shim</TargetName>
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<VersionInfoFileDescription>Windows Terminal Administrator Launch Helper</VersionInfoFileDescription>
|
||||
</PropertyGroup>
|
||||
|
||||
<Import Project="..\..\..\common.openconsole.props" Condition="'$(OpenConsoleDir)'==''" />
|
||||
|
||||
@ -2,8 +2,8 @@
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#include "pch.h"
|
||||
#include "../TerminalApp/CommandLinePaletteItem.h"
|
||||
#include "../TerminalApp/CommandPalette.h"
|
||||
#include "../TerminalApp/BasePaletteItem.h"
|
||||
#include "CppWinrtTailored.h"
|
||||
|
||||
using namespace Microsoft::Console;
|
||||
@ -15,6 +15,20 @@ using namespace winrt::Microsoft::Terminal::Control;
|
||||
|
||||
namespace TerminalAppLocalTests
|
||||
{
|
||||
struct StringPaletteItem : winrt::implements<StringPaletteItem, winrt::TerminalApp::IPaletteItem, winrt::Windows::UI::Xaml::Data::INotifyPropertyChanged>, winrt::TerminalApp::implementation::BasePaletteItem<StringPaletteItem, winrt::TerminalApp::PaletteItemType::CommandLine>
|
||||
{
|
||||
StringPaletteItem(std::wstring_view value) :
|
||||
_value{ value } {}
|
||||
|
||||
winrt::hstring Name() { return _value; }
|
||||
winrt::hstring Subtitle() { return {}; }
|
||||
winrt::hstring KeyChordText() { return {}; }
|
||||
winrt::hstring Icon() { return {}; }
|
||||
|
||||
private:
|
||||
winrt::hstring _value;
|
||||
};
|
||||
|
||||
class FilteredCommandTests
|
||||
{
|
||||
BEGIN_TEST_CLASS(FilteredCommandTests)
|
||||
@ -28,81 +42,81 @@ namespace TerminalAppLocalTests
|
||||
TEST_METHOD(VerifyCompareIgnoreCase);
|
||||
};
|
||||
|
||||
static void _verifySegment(auto&& segments, uint32_t index, uint64_t start, uint64_t end)
|
||||
{
|
||||
const auto& segment{ segments.GetAt(index) };
|
||||
VERIFY_ARE_EQUAL(segment.Start, start, NoThrowString().Format(L"segment %zu", index));
|
||||
VERIFY_ARE_EQUAL(segment.End, end, NoThrowString().Format(L"segment %zu", index));
|
||||
}
|
||||
|
||||
void FilteredCommandTests::VerifyHighlighting()
|
||||
{
|
||||
auto result = RunOnUIThread([]() {
|
||||
const auto paletteItem{ winrt::make<winrt::TerminalApp::implementation::CommandLinePaletteItem>(L"AAAAAABBBBBBCCC") };
|
||||
const WEX::TestExecution::DisableVerifyExceptions disableExceptionsScope;
|
||||
|
||||
const auto paletteItem{ winrt::make<StringPaletteItem>(L"AAAAAABBBBBBCCC") };
|
||||
const auto filteredCommand = winrt::make_self<winrt::TerminalApp::implementation::FilteredCommand>(paletteItem);
|
||||
|
||||
{
|
||||
Log::Comment(L"Testing command name segmentation with no filter");
|
||||
const auto filteredCommand = winrt::make_self<winrt::TerminalApp::implementation::FilteredCommand>(paletteItem);
|
||||
auto segments = filteredCommand->_computeHighlightedName().Segments();
|
||||
VERIFY_ARE_EQUAL(segments.Size(), 1u);
|
||||
VERIFY_ARE_EQUAL(segments.GetAt(0).TextSegment(), L"AAAAAABBBBBBCCC");
|
||||
VERIFY_IS_FALSE(segments.GetAt(0).IsHighlighted());
|
||||
const auto segments = filteredCommand->NameHighlights();
|
||||
|
||||
VERIFY_IS_NULL(segments); // No matches = no segments
|
||||
}
|
||||
{
|
||||
Log::Comment(L"Testing command name segmentation with empty filter");
|
||||
const auto filteredCommand = winrt::make_self<winrt::TerminalApp::implementation::FilteredCommand>(paletteItem);
|
||||
filteredCommand->_Filter = L"";
|
||||
auto segments = filteredCommand->_computeHighlightedName().Segments();
|
||||
VERIFY_ARE_EQUAL(segments.Size(), 1u);
|
||||
VERIFY_ARE_EQUAL(segments.GetAt(0).TextSegment(), L"AAAAAABBBBBBCCC");
|
||||
VERIFY_IS_FALSE(segments.GetAt(0).IsHighlighted());
|
||||
filteredCommand->UpdateFilter(std::make_shared<fzf::matcher::Pattern>(fzf::matcher::ParsePattern(L"")));
|
||||
const auto segments = filteredCommand->NameHighlights();
|
||||
|
||||
VERIFY_IS_NULL(segments); // No matches = no segments
|
||||
}
|
||||
{
|
||||
Log::Comment(L"Testing command name segmentation with filter equal to the string");
|
||||
const auto filteredCommand = winrt::make_self<winrt::TerminalApp::implementation::FilteredCommand>(paletteItem);
|
||||
filteredCommand->_Filter = L"AAAAAABBBBBBCCC";
|
||||
auto segments = filteredCommand->_computeHighlightedName().Segments();
|
||||
filteredCommand->UpdateFilter(std::make_shared<fzf::matcher::Pattern>(fzf::matcher::ParsePattern(L"AAAAAABBBBBBCCC")));
|
||||
const auto segments = filteredCommand->NameHighlights();
|
||||
|
||||
VERIFY_ARE_EQUAL(segments.Size(), 1u);
|
||||
VERIFY_ARE_EQUAL(segments.GetAt(0).TextSegment(), L"AAAAAABBBBBBCCC");
|
||||
VERIFY_IS_TRUE(segments.GetAt(0).IsHighlighted());
|
||||
_verifySegment(segments, 0, 0, 14); // one segment for the entire string
|
||||
}
|
||||
{
|
||||
Log::Comment(L"Testing command name segmentation with filter with first character matching");
|
||||
const auto filteredCommand = winrt::make_self<winrt::TerminalApp::implementation::FilteredCommand>(paletteItem);
|
||||
filteredCommand->_Filter = L"A";
|
||||
auto segments = filteredCommand->_computeHighlightedName().Segments();
|
||||
VERIFY_ARE_EQUAL(segments.Size(), 2u);
|
||||
VERIFY_ARE_EQUAL(segments.GetAt(0).TextSegment(), L"A");
|
||||
VERIFY_IS_TRUE(segments.GetAt(0).IsHighlighted());
|
||||
VERIFY_ARE_EQUAL(segments.GetAt(1).TextSegment(), L"AAAAABBBBBBCCC");
|
||||
VERIFY_IS_FALSE(segments.GetAt(1).IsHighlighted());
|
||||
filteredCommand->UpdateFilter(std::make_shared<fzf::matcher::Pattern>(fzf::matcher::ParsePattern(L"A")));
|
||||
const auto segments = filteredCommand->NameHighlights();
|
||||
|
||||
VERIFY_ARE_EQUAL(segments.Size(), 1u); // only one bold segment
|
||||
_verifySegment(segments, 0, 0, 0); // it only covers the first character
|
||||
}
|
||||
{
|
||||
Log::Comment(L"Testing command name segmentation with filter with other case");
|
||||
const auto filteredCommand = winrt::make_self<winrt::TerminalApp::implementation::FilteredCommand>(paletteItem);
|
||||
filteredCommand->_Filter = L"a";
|
||||
auto segments = filteredCommand->_computeHighlightedName().Segments();
|
||||
VERIFY_ARE_EQUAL(segments.Size(), 2u);
|
||||
VERIFY_ARE_EQUAL(segments.GetAt(0).TextSegment(), L"A");
|
||||
VERIFY_IS_TRUE(segments.GetAt(0).IsHighlighted());
|
||||
VERIFY_ARE_EQUAL(segments.GetAt(1).TextSegment(), L"AAAAABBBBBBCCC");
|
||||
VERIFY_IS_FALSE(segments.GetAt(1).IsHighlighted());
|
||||
filteredCommand->UpdateFilter(std::make_shared<fzf::matcher::Pattern>(fzf::matcher::ParsePattern(L"a")));
|
||||
const auto segments = filteredCommand->NameHighlights();
|
||||
|
||||
VERIFY_ARE_EQUAL(segments.Size(), 1u); // only one bold segment
|
||||
_verifySegment(segments, 0, 0, 0); // it only covers the first character
|
||||
}
|
||||
{
|
||||
Log::Comment(L"Testing command name segmentation with filter matching several characters");
|
||||
const auto filteredCommand = winrt::make_self<winrt::TerminalApp::implementation::FilteredCommand>(paletteItem);
|
||||
filteredCommand->_Filter = L"ab";
|
||||
auto segments = filteredCommand->_computeHighlightedName().Segments();
|
||||
VERIFY_ARE_EQUAL(segments.Size(), 4u);
|
||||
VERIFY_ARE_EQUAL(segments.GetAt(0).TextSegment(), L"A");
|
||||
VERIFY_IS_TRUE(segments.GetAt(0).IsHighlighted());
|
||||
VERIFY_ARE_EQUAL(segments.GetAt(1).TextSegment(), L"AAAAA");
|
||||
VERIFY_IS_FALSE(segments.GetAt(1).IsHighlighted());
|
||||
VERIFY_ARE_EQUAL(segments.GetAt(2).TextSegment(), L"B");
|
||||
VERIFY_IS_TRUE(segments.GetAt(2).IsHighlighted());
|
||||
VERIFY_ARE_EQUAL(segments.GetAt(3).TextSegment(), L"BBBBBCCC");
|
||||
VERIFY_IS_FALSE(segments.GetAt(3).IsHighlighted());
|
||||
filteredCommand->UpdateFilter(std::make_shared<fzf::matcher::Pattern>(fzf::matcher::ParsePattern(L"ab")));
|
||||
const auto segments = filteredCommand->NameHighlights();
|
||||
|
||||
VERIFY_ARE_EQUAL(segments.Size(), 1u); // one bold segment
|
||||
_verifySegment(segments, 0, 5, 6); // middle 'ab'
|
||||
}
|
||||
{
|
||||
Log::Comment(L"Testing command name segmentation with filter matching several regions");
|
||||
filteredCommand->UpdateFilter(std::make_shared<fzf::matcher::Pattern>(fzf::matcher::ParsePattern(L"abcc")));
|
||||
const auto segments = filteredCommand->NameHighlights();
|
||||
|
||||
VERIFY_ARE_EQUAL(segments.Size(), 2u); // two bold segments
|
||||
_verifySegment(segments, 0, 5, 6); // middle 'ab'
|
||||
_verifySegment(segments, 1, 12, 13); // start of 'cc'
|
||||
}
|
||||
{
|
||||
Log::Comment(L"Testing command name segmentation with non matching filter");
|
||||
const auto filteredCommand = winrt::make_self<winrt::TerminalApp::implementation::FilteredCommand>(paletteItem);
|
||||
filteredCommand->_Filter = L"abcd";
|
||||
auto segments = filteredCommand->_computeHighlightedName().Segments();
|
||||
VERIFY_ARE_EQUAL(segments.Size(), 1u);
|
||||
VERIFY_ARE_EQUAL(segments.GetAt(0).TextSegment(), L"AAAAAABBBBBBCCC");
|
||||
VERIFY_IS_FALSE(segments.GetAt(0).IsHighlighted());
|
||||
filteredCommand->UpdateFilter(std::make_shared<fzf::matcher::Pattern>(fzf::matcher::ParsePattern(L"abcd")));
|
||||
const auto segments = filteredCommand->NameHighlights();
|
||||
|
||||
VERIFY_IS_NULL(segments); // No matches = no segments
|
||||
}
|
||||
});
|
||||
|
||||
@ -112,54 +126,38 @@ namespace TerminalAppLocalTests
|
||||
void FilteredCommandTests::VerifyWeight()
|
||||
{
|
||||
auto result = RunOnUIThread([]() {
|
||||
const auto paletteItem{ winrt::make<winrt::TerminalApp::implementation::CommandLinePaletteItem>(L"AAAAAABBBBBBCCC") };
|
||||
{
|
||||
Log::Comment(L"Testing weight of command with no filter");
|
||||
const auto filteredCommand = winrt::make_self<winrt::TerminalApp::implementation::FilteredCommand>(paletteItem);
|
||||
filteredCommand->_HighlightedName = filteredCommand->_computeHighlightedName();
|
||||
auto weight = filteredCommand->_computeWeight();
|
||||
VERIFY_ARE_EQUAL(weight, 0);
|
||||
}
|
||||
{
|
||||
Log::Comment(L"Testing weight of command with empty filter");
|
||||
const auto filteredCommand = winrt::make_self<winrt::TerminalApp::implementation::FilteredCommand>(paletteItem);
|
||||
filteredCommand->_Filter = L"";
|
||||
filteredCommand->_HighlightedName = filteredCommand->_computeHighlightedName();
|
||||
auto weight = filteredCommand->_computeWeight();
|
||||
VERIFY_ARE_EQUAL(weight, 0);
|
||||
}
|
||||
{
|
||||
Log::Comment(L"Testing weight of command with filter equal to the string");
|
||||
const auto filteredCommand = winrt::make_self<winrt::TerminalApp::implementation::FilteredCommand>(paletteItem);
|
||||
filteredCommand->_Filter = L"AAAAAABBBBBBCCC";
|
||||
filteredCommand->_HighlightedName = filteredCommand->_computeHighlightedName();
|
||||
auto weight = filteredCommand->_computeWeight();
|
||||
VERIFY_ARE_EQUAL(weight, 30); // 1 point for the first char and 2 points for the 14 consequent ones + 1 point for the beginning of the word
|
||||
}
|
||||
{
|
||||
Log::Comment(L"Testing weight of command with filter with first character matching");
|
||||
const auto filteredCommand = winrt::make_self<winrt::TerminalApp::implementation::FilteredCommand>(paletteItem);
|
||||
filteredCommand->_Filter = L"A";
|
||||
filteredCommand->_HighlightedName = filteredCommand->_computeHighlightedName();
|
||||
auto weight = filteredCommand->_computeWeight();
|
||||
VERIFY_ARE_EQUAL(weight, 2); // 1 point for the first char match + 1 point for the beginning of the word
|
||||
}
|
||||
{
|
||||
Log::Comment(L"Testing weight of command with filter with other case");
|
||||
const auto filteredCommand = winrt::make_self<winrt::TerminalApp::implementation::FilteredCommand>(paletteItem);
|
||||
filteredCommand->_Filter = L"a";
|
||||
filteredCommand->_HighlightedName = filteredCommand->_computeHighlightedName();
|
||||
auto weight = filteredCommand->_computeWeight();
|
||||
VERIFY_ARE_EQUAL(weight, 2); // 1 point for the first char match + 1 point for the beginning of the word
|
||||
}
|
||||
{
|
||||
Log::Comment(L"Testing weight of command with filter matching several characters");
|
||||
const auto filteredCommand = winrt::make_self<winrt::TerminalApp::implementation::FilteredCommand>(paletteItem);
|
||||
filteredCommand->_Filter = L"ab";
|
||||
filteredCommand->_HighlightedName = filteredCommand->_computeHighlightedName();
|
||||
auto weight = filteredCommand->_computeWeight();
|
||||
VERIFY_ARE_EQUAL(weight, 3); // 1 point for the first char match + 1 point for the beginning of the word + 1 point for the match of "b"
|
||||
}
|
||||
const auto paletteItem{ winrt::make<StringPaletteItem>(L"AAAAAABBBBBBCCC") };
|
||||
const auto filteredCommand = winrt::make_self<winrt::TerminalApp::implementation::FilteredCommand>(paletteItem);
|
||||
|
||||
const auto weigh = [&](const wchar_t* str) {
|
||||
std::shared_ptr<fzf::matcher::Pattern> pattern;
|
||||
if (str)
|
||||
{
|
||||
pattern = std::make_shared<fzf::matcher::Pattern>(fzf::matcher::ParsePattern(str));
|
||||
}
|
||||
filteredCommand->UpdateFilter(std::move(pattern));
|
||||
return filteredCommand->Weight();
|
||||
};
|
||||
|
||||
const auto null = weigh(nullptr);
|
||||
const auto empty = weigh(L"");
|
||||
const auto full = weigh(L"AAAAAABBBBBBCCC");
|
||||
const auto firstChar = weigh(L"A");
|
||||
const auto otherCase = weigh(L"a");
|
||||
const auto severalChars = weigh(L"ab");
|
||||
|
||||
VERIFY_ARE_EQUAL(null, 0);
|
||||
VERIFY_ARE_EQUAL(empty, 0);
|
||||
VERIFY_IS_GREATER_THAN(full, 100);
|
||||
|
||||
VERIFY_IS_GREATER_THAN(firstChar, 0);
|
||||
VERIFY_IS_LESS_THAN(firstChar, full);
|
||||
|
||||
VERIFY_IS_GREATER_THAN(otherCase, 0);
|
||||
VERIFY_IS_LESS_THAN(otherCase, full);
|
||||
|
||||
VERIFY_IS_GREATER_THAN(severalChars, otherCase);
|
||||
VERIFY_IS_LESS_THAN(severalChars, full);
|
||||
});
|
||||
|
||||
VERIFY_SUCCEEDED(result);
|
||||
@ -168,8 +166,8 @@ namespace TerminalAppLocalTests
|
||||
void FilteredCommandTests::VerifyCompare()
|
||||
{
|
||||
auto result = RunOnUIThread([]() {
|
||||
const auto paletteItem{ winrt::make<winrt::TerminalApp::implementation::CommandLinePaletteItem>(L"AAAAAABBBBBBCCC") };
|
||||
const auto paletteItem2{ winrt::make<winrt::TerminalApp::implementation::CommandLinePaletteItem>(L"BBBBBCCC") };
|
||||
const auto paletteItem{ winrt::make<StringPaletteItem>(L"AAAAAABBBBBBCCC") };
|
||||
const auto paletteItem2{ winrt::make<StringPaletteItem>(L"BBBBBCCC") };
|
||||
{
|
||||
Log::Comment(L"Testing comparison of commands with no filter");
|
||||
const auto filteredCommand = winrt::make_self<winrt::TerminalApp::implementation::FilteredCommand>(paletteItem);
|
||||
@ -181,14 +179,10 @@ namespace TerminalAppLocalTests
|
||||
{
|
||||
Log::Comment(L"Testing comparison of commands with empty filter");
|
||||
const auto filteredCommand = winrt::make_self<winrt::TerminalApp::implementation::FilteredCommand>(paletteItem);
|
||||
filteredCommand->_Filter = L"";
|
||||
filteredCommand->_HighlightedName = filteredCommand->_computeHighlightedName();
|
||||
filteredCommand->_Weight = filteredCommand->_computeWeight();
|
||||
filteredCommand->UpdateFilter(std::make_shared<fzf::matcher::Pattern>(fzf::matcher::ParsePattern(L"")));
|
||||
|
||||
const auto filteredCommand2 = winrt::make_self<winrt::TerminalApp::implementation::FilteredCommand>(paletteItem2);
|
||||
filteredCommand2->_Filter = L"";
|
||||
filteredCommand2->_HighlightedName = filteredCommand2->_computeHighlightedName();
|
||||
filteredCommand2->_Weight = filteredCommand2->_computeWeight();
|
||||
filteredCommand2->UpdateFilter(std::make_shared<fzf::matcher::Pattern>(fzf::matcher::ParsePattern(L"")));
|
||||
|
||||
VERIFY_ARE_EQUAL(filteredCommand->Weight(), filteredCommand2->Weight());
|
||||
VERIFY_IS_TRUE(winrt::TerminalApp::implementation::FilteredCommand::Compare(*filteredCommand, *filteredCommand2));
|
||||
@ -196,16 +190,12 @@ namespace TerminalAppLocalTests
|
||||
{
|
||||
Log::Comment(L"Testing comparison of commands with different weights");
|
||||
const auto filteredCommand = winrt::make_self<winrt::TerminalApp::implementation::FilteredCommand>(paletteItem);
|
||||
filteredCommand->_Filter = L"B";
|
||||
filteredCommand->_HighlightedName = filteredCommand->_computeHighlightedName();
|
||||
filteredCommand->_Weight = filteredCommand->_computeWeight();
|
||||
filteredCommand->UpdateFilter(std::make_shared<fzf::matcher::Pattern>(fzf::matcher::ParsePattern(L"B")));
|
||||
|
||||
const auto filteredCommand2 = winrt::make_self<winrt::TerminalApp::implementation::FilteredCommand>(paletteItem2);
|
||||
filteredCommand2->_Filter = L"B";
|
||||
filteredCommand2->_HighlightedName = filteredCommand2->_computeHighlightedName();
|
||||
filteredCommand2->_Weight = filteredCommand2->_computeWeight();
|
||||
filteredCommand2->UpdateFilter(std::make_shared<fzf::matcher::Pattern>(fzf::matcher::ParsePattern(L"B")));
|
||||
|
||||
VERIFY_IS_TRUE(filteredCommand->Weight() < filteredCommand2->Weight()); // Second command gets more points due to the beginning of the word
|
||||
VERIFY_IS_LESS_THAN(filteredCommand->Weight(), filteredCommand2->Weight()); // Second command gets more points due to the beginning of the word
|
||||
VERIFY_IS_FALSE(winrt::TerminalApp::implementation::FilteredCommand::Compare(*filteredCommand, *filteredCommand2));
|
||||
}
|
||||
});
|
||||
@ -216,8 +206,8 @@ namespace TerminalAppLocalTests
|
||||
void FilteredCommandTests::VerifyCompareIgnoreCase()
|
||||
{
|
||||
auto result = RunOnUIThread([]() {
|
||||
const auto paletteItem{ winrt::make<winrt::TerminalApp::implementation::CommandLinePaletteItem>(L"a") };
|
||||
const auto paletteItem2{ winrt::make<winrt::TerminalApp::implementation::CommandLinePaletteItem>(L"B") };
|
||||
const auto paletteItem{ winrt::make<StringPaletteItem>(L"a") };
|
||||
const auto paletteItem2{ winrt::make<StringPaletteItem>(L"B") };
|
||||
{
|
||||
const auto filteredCommand = winrt::make_self<winrt::TerminalApp::implementation::FilteredCommand>(paletteItem);
|
||||
const auto filteredCommand2 = winrt::make_self<winrt::TerminalApp::implementation::FilteredCommand>(paletteItem2);
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
#include "../TerminalApp/MinMaxCloseControl.h"
|
||||
#include "../TerminalApp/TabRowControl.h"
|
||||
#include "../TerminalApp/ShortcutActionDispatch.h"
|
||||
#include "../TerminalApp/TerminalTab.h"
|
||||
#include "../TerminalApp/Tab.h"
|
||||
#include "../TerminalApp/CommandPalette.h"
|
||||
#include "../TerminalApp/ContentManager.h"
|
||||
#include "CppWinrtTailored.h"
|
||||
@ -307,7 +307,7 @@ namespace TerminalAppLocalTests
|
||||
// reliably in the unit tests.
|
||||
Log::Comment(L"Ensure we set the first tab as the selected one.");
|
||||
auto tab = page->_tabs.GetAt(0);
|
||||
auto tabImpl = page->_GetTerminalTabImpl(tab);
|
||||
auto tabImpl = page->_GetTabImpl(tab);
|
||||
page->_tabView.SelectedItem(tabImpl->TabViewItem());
|
||||
page->_UpdatedSelectedTab(tab);
|
||||
});
|
||||
@ -510,7 +510,7 @@ namespace TerminalAppLocalTests
|
||||
|
||||
result = RunOnUIThread([&page]() {
|
||||
VERIFY_ARE_EQUAL(1u, page->_tabs.Size());
|
||||
auto tab = page->_GetTerminalTabImpl(page->_tabs.GetAt(0));
|
||||
auto tab = page->_GetTabImpl(page->_tabs.GetAt(0));
|
||||
VERIFY_ARE_EQUAL(1, tab->GetLeafPaneCount());
|
||||
});
|
||||
VERIFY_SUCCEEDED(result);
|
||||
@ -520,7 +520,7 @@ namespace TerminalAppLocalTests
|
||||
page->_SplitPane(nullptr, SplitDirection::Automatic, 0.5f, page->_MakePane(nullptr, page->_GetFocusedTab(), nullptr));
|
||||
|
||||
VERIFY_ARE_EQUAL(1u, page->_tabs.Size());
|
||||
auto tab = page->_GetTerminalTabImpl(page->_tabs.GetAt(0));
|
||||
auto tab = page->_GetTabImpl(page->_tabs.GetAt(0));
|
||||
VERIFY_ARE_EQUAL(2, tab->GetLeafPaneCount());
|
||||
});
|
||||
VERIFY_SUCCEEDED(result);
|
||||
@ -538,7 +538,7 @@ namespace TerminalAppLocalTests
|
||||
page->_SplitPane(nullptr, SplitDirection::Automatic, 0.5f, page->_MakePane(nullptr, page->_GetFocusedTab(), nullptr));
|
||||
|
||||
VERIFY_ARE_EQUAL(1u, page->_tabs.Size());
|
||||
auto tab = page->_GetTerminalTabImpl(page->_tabs.GetAt(0));
|
||||
auto tab = page->_GetTabImpl(page->_tabs.GetAt(0));
|
||||
VERIFY_ARE_EQUAL(3,
|
||||
tab->GetLeafPaneCount(),
|
||||
L"We should successfully duplicate a pane hosting a deleted profile.");
|
||||
@ -706,7 +706,7 @@ namespace TerminalAppLocalTests
|
||||
SplitPaneArgs args{ SplitType::Duplicate };
|
||||
ActionEventArgs eventArgs{ args };
|
||||
page->_HandleSplitPane(nullptr, eventArgs);
|
||||
auto firstTab = page->_GetTerminalTabImpl(page->_tabs.GetAt(0));
|
||||
auto firstTab = page->_GetTabImpl(page->_tabs.GetAt(0));
|
||||
|
||||
VERIFY_ARE_EQUAL(2, firstTab->GetLeafPaneCount());
|
||||
VERIFY_IS_FALSE(firstTab->IsZoomed());
|
||||
@ -717,7 +717,7 @@ namespace TerminalAppLocalTests
|
||||
result = RunOnUIThread([&page]() {
|
||||
ActionEventArgs eventArgs{};
|
||||
page->_HandleTogglePaneZoom(nullptr, eventArgs);
|
||||
auto firstTab = page->_GetTerminalTabImpl(page->_tabs.GetAt(0));
|
||||
auto firstTab = page->_GetTabImpl(page->_tabs.GetAt(0));
|
||||
VERIFY_ARE_EQUAL(2, firstTab->GetLeafPaneCount());
|
||||
VERIFY_IS_TRUE(firstTab->IsZoomed());
|
||||
});
|
||||
@ -727,7 +727,7 @@ namespace TerminalAppLocalTests
|
||||
result = RunOnUIThread([&page]() {
|
||||
ActionEventArgs eventArgs{};
|
||||
page->_HandleTogglePaneZoom(nullptr, eventArgs);
|
||||
auto firstTab = page->_GetTerminalTabImpl(page->_tabs.GetAt(0));
|
||||
auto firstTab = page->_GetTabImpl(page->_tabs.GetAt(0));
|
||||
VERIFY_ARE_EQUAL(2, firstTab->GetLeafPaneCount());
|
||||
VERIFY_IS_FALSE(firstTab->IsZoomed());
|
||||
});
|
||||
@ -744,7 +744,7 @@ namespace TerminalAppLocalTests
|
||||
SplitPaneArgs args{ SplitType::Duplicate };
|
||||
ActionEventArgs eventArgs{ args };
|
||||
page->_HandleSplitPane(nullptr, eventArgs);
|
||||
auto firstTab = page->_GetTerminalTabImpl(page->_tabs.GetAt(0));
|
||||
auto firstTab = page->_GetTabImpl(page->_tabs.GetAt(0));
|
||||
|
||||
VERIFY_ARE_EQUAL(2, firstTab->GetLeafPaneCount());
|
||||
VERIFY_IS_FALSE(firstTab->IsZoomed());
|
||||
@ -758,7 +758,7 @@ namespace TerminalAppLocalTests
|
||||
|
||||
page->_HandleTogglePaneZoom(nullptr, eventArgs);
|
||||
|
||||
auto firstTab = page->_GetTerminalTabImpl(page->_tabs.GetAt(0));
|
||||
auto firstTab = page->_GetTabImpl(page->_tabs.GetAt(0));
|
||||
VERIFY_ARE_EQUAL(2, firstTab->GetLeafPaneCount());
|
||||
VERIFY_IS_TRUE(firstTab->IsZoomed());
|
||||
});
|
||||
@ -772,7 +772,7 @@ namespace TerminalAppLocalTests
|
||||
|
||||
page->_HandleMoveFocus(nullptr, eventArgs);
|
||||
|
||||
auto firstTab = page->_GetTerminalTabImpl(page->_tabs.GetAt(0));
|
||||
auto firstTab = page->_GetTabImpl(page->_tabs.GetAt(0));
|
||||
VERIFY_ARE_EQUAL(2, firstTab->GetLeafPaneCount());
|
||||
VERIFY_IS_TRUE(firstTab->IsZoomed());
|
||||
});
|
||||
@ -789,7 +789,7 @@ namespace TerminalAppLocalTests
|
||||
SplitPaneArgs args{ SplitType::Duplicate };
|
||||
ActionEventArgs eventArgs{ args };
|
||||
page->_HandleSplitPane(nullptr, eventArgs);
|
||||
auto firstTab = page->_GetTerminalTabImpl(page->_tabs.GetAt(0));
|
||||
auto firstTab = page->_GetTabImpl(page->_tabs.GetAt(0));
|
||||
|
||||
VERIFY_ARE_EQUAL(2, firstTab->GetLeafPaneCount());
|
||||
VERIFY_IS_FALSE(firstTab->IsZoomed());
|
||||
@ -803,7 +803,7 @@ namespace TerminalAppLocalTests
|
||||
|
||||
page->_HandleTogglePaneZoom(nullptr, eventArgs);
|
||||
|
||||
auto firstTab = page->_GetTerminalTabImpl(page->_tabs.GetAt(0));
|
||||
auto firstTab = page->_GetTabImpl(page->_tabs.GetAt(0));
|
||||
VERIFY_ARE_EQUAL(2, firstTab->GetLeafPaneCount());
|
||||
VERIFY_IS_TRUE(firstTab->IsZoomed());
|
||||
});
|
||||
@ -816,7 +816,7 @@ namespace TerminalAppLocalTests
|
||||
|
||||
page->_HandleClosePane(nullptr, eventArgs);
|
||||
|
||||
auto firstTab = page->_GetTerminalTabImpl(page->_tabs.GetAt(0));
|
||||
auto firstTab = page->_GetTabImpl(page->_tabs.GetAt(0));
|
||||
VERIFY_IS_FALSE(firstTab->IsZoomed());
|
||||
});
|
||||
VERIFY_SUCCEEDED(result);
|
||||
@ -827,7 +827,7 @@ namespace TerminalAppLocalTests
|
||||
Log::Comment(L"Check to ensure there's only one pane left.");
|
||||
|
||||
result = RunOnUIThread([&page]() {
|
||||
auto firstTab = page->_GetTerminalTabImpl(page->_tabs.GetAt(0));
|
||||
auto firstTab = page->_GetTabImpl(page->_tabs.GetAt(0));
|
||||
VERIFY_ARE_EQUAL(1, firstTab->GetLeafPaneCount());
|
||||
VERIFY_IS_FALSE(firstTab->IsZoomed());
|
||||
});
|
||||
@ -850,7 +850,7 @@ namespace TerminalAppLocalTests
|
||||
uint32_t firstId = 0, secondId = 0, thirdId = 0, fourthId = 0;
|
||||
TestOnUIThread([&]() {
|
||||
VERIFY_ARE_EQUAL(1u, page->_tabs.Size());
|
||||
auto tab = page->_GetTerminalTabImpl(page->_tabs.GetAt(0));
|
||||
auto tab = page->_GetTabImpl(page->_tabs.GetAt(0));
|
||||
firstId = tab->_activePane->Id().value();
|
||||
// We start with 1 tab, split vertically to get
|
||||
// -------------------
|
||||
@ -876,7 +876,7 @@ namespace TerminalAppLocalTests
|
||||
// | | |
|
||||
// -------------------
|
||||
page->_SplitPane(nullptr, SplitDirection::Down, 0.5f, page->_MakePane(nullptr, page->_GetFocusedTab(), nullptr));
|
||||
auto tab = page->_GetTerminalTabImpl(page->_tabs.GetAt(0));
|
||||
auto tab = page->_GetTabImpl(page->_tabs.GetAt(0));
|
||||
// Split again to make the 3rd tab
|
||||
thirdId = tab->_activePane->Id().value();
|
||||
});
|
||||
@ -896,13 +896,13 @@ namespace TerminalAppLocalTests
|
||||
// | | |
|
||||
// -------------------
|
||||
page->_SplitPane(nullptr, SplitDirection::Down, 0.5f, page->_MakePane(nullptr, page->_GetFocusedTab(), nullptr));
|
||||
auto tab = page->_GetTerminalTabImpl(page->_tabs.GetAt(0));
|
||||
auto tab = page->_GetTabImpl(page->_tabs.GetAt(0));
|
||||
fourthId = tab->_activePane->Id().value();
|
||||
});
|
||||
|
||||
Sleep(250);
|
||||
TestOnUIThread([&]() {
|
||||
auto tab = page->_GetTerminalTabImpl(page->_tabs.GetAt(0));
|
||||
auto tab = page->_GetTabImpl(page->_tabs.GetAt(0));
|
||||
VERIFY_ARE_EQUAL(4, tab->GetLeafPaneCount());
|
||||
// just to be complete, make sure we actually have 4 different ids
|
||||
VERIFY_ARE_NOT_EQUAL(firstId, fourthId);
|
||||
@ -936,7 +936,7 @@ namespace TerminalAppLocalTests
|
||||
Sleep(250);
|
||||
|
||||
TestOnUIThread([&]() {
|
||||
auto tab = page->_GetTerminalTabImpl(page->_tabs.GetAt(0));
|
||||
auto tab = page->_GetTabImpl(page->_tabs.GetAt(0));
|
||||
VERIFY_ARE_EQUAL(4, tab->GetLeafPaneCount());
|
||||
// Our currently focused pane should be `4`
|
||||
VERIFY_ARE_EQUAL(fourthId, tab->_activePane->Id().value());
|
||||
@ -967,7 +967,7 @@ namespace TerminalAppLocalTests
|
||||
Sleep(250);
|
||||
|
||||
TestOnUIThread([&]() {
|
||||
auto tab = page->_GetTerminalTabImpl(page->_tabs.GetAt(0));
|
||||
auto tab = page->_GetTabImpl(page->_tabs.GetAt(0));
|
||||
VERIFY_ARE_EQUAL(4, tab->GetLeafPaneCount());
|
||||
// Our currently focused pane should be `4`
|
||||
VERIFY_ARE_EQUAL(fourthId, tab->_activePane->Id().value());
|
||||
@ -998,7 +998,7 @@ namespace TerminalAppLocalTests
|
||||
Sleep(250);
|
||||
|
||||
TestOnUIThread([&]() {
|
||||
auto tab = page->_GetTerminalTabImpl(page->_tabs.GetAt(0));
|
||||
auto tab = page->_GetTabImpl(page->_tabs.GetAt(0));
|
||||
VERIFY_ARE_EQUAL(4, tab->GetLeafPaneCount());
|
||||
// Our currently focused pane should be `4`
|
||||
VERIFY_ARE_EQUAL(fourthId, tab->_activePane->Id().value());
|
||||
@ -1029,7 +1029,7 @@ namespace TerminalAppLocalTests
|
||||
Sleep(250);
|
||||
|
||||
TestOnUIThread([&]() {
|
||||
auto tab = page->_GetTerminalTabImpl(page->_tabs.GetAt(0));
|
||||
auto tab = page->_GetTabImpl(page->_tabs.GetAt(0));
|
||||
VERIFY_ARE_EQUAL(4, tab->GetLeafPaneCount());
|
||||
// Our currently focused pane should be `4`
|
||||
VERIFY_ARE_EQUAL(fourthId, tab->_activePane->Id().value());
|
||||
@ -1174,16 +1174,16 @@ namespace TerminalAppLocalTests
|
||||
|
||||
Log::Comment(L"give alphabetical names to all switch tab actions");
|
||||
TestOnUIThread([&page]() {
|
||||
page->_GetTerminalTabImpl(page->_tabs.GetAt(0))->Title(L"a");
|
||||
page->_GetTabImpl(page->_tabs.GetAt(0))->Title(L"a");
|
||||
});
|
||||
TestOnUIThread([&page]() {
|
||||
page->_GetTerminalTabImpl(page->_tabs.GetAt(1))->Title(L"b");
|
||||
page->_GetTabImpl(page->_tabs.GetAt(1))->Title(L"b");
|
||||
});
|
||||
TestOnUIThread([&page]() {
|
||||
page->_GetTerminalTabImpl(page->_tabs.GetAt(2))->Title(L"c");
|
||||
page->_GetTabImpl(page->_tabs.GetAt(2))->Title(L"c");
|
||||
});
|
||||
TestOnUIThread([&page]() {
|
||||
page->_GetTerminalTabImpl(page->_tabs.GetAt(3))->Title(L"d");
|
||||
page->_GetTabImpl(page->_tabs.GetAt(3))->Title(L"d");
|
||||
});
|
||||
|
||||
TestOnUIThread([&page]() {
|
||||
|
||||
@ -21,7 +21,7 @@ static constexpr std::wstring_view VerbName{ L"WindowsTerminalOpenHere" };
|
||||
// Arguments:
|
||||
// - psiItemArray: a IShellItemArray which contains the item that's selected.
|
||||
// Return Value:
|
||||
// - S_OK if we successfully attempted to launch the Terminal, otherwise a
|
||||
// - S_OK if we successfully attempted to launch the Terminal; otherwise, a
|
||||
// failure from an earlier HRESULT.
|
||||
HRESULT OpenTerminalHere::Invoke(IShellItemArray* psiItemArray,
|
||||
IBindCtx* /*pBindContext*/)
|
||||
|
||||
@ -10,6 +10,7 @@
|
||||
<SubSystem>Console</SubSystem>
|
||||
<!-- suppress a bunch of Windows Universal properties from cppwinrt.props -->
|
||||
<OpenConsoleUniversalApp>false</OpenConsoleUniversalApp>
|
||||
<VersionInfoFileDescription>Windows Terminal Open Here Shell Extension</VersionInfoFileDescription>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="NuGet Dependencies">
|
||||
<TerminalCppWinrt>true</TerminalCppWinrt>
|
||||
|
||||
@ -28,18 +28,18 @@
|
||||
</TextBlock>
|
||||
|
||||
<StackPanel Orientation="Vertical">
|
||||
<StackPanel Padding="0,4,0,4"
|
||||
<StackPanel Padding="0,16,0,16"
|
||||
VerticalAlignment="Center"
|
||||
Orientation="Horizontal"
|
||||
Spacing="8"
|
||||
Visibility="{x:Bind CheckingForUpdates, Mode=OneWay}">
|
||||
<mux:ProgressRing Width="16"
|
||||
Height="16"
|
||||
IsActive="True"
|
||||
IsIndeterminate="True" />
|
||||
<TextBlock x:Uid="AboutDialog_CheckingForUpdatesLabel"
|
||||
Padding="4,0,0,0" />
|
||||
<TextBlock x:Uid="AboutDialog_CheckingForUpdatesLabel" />
|
||||
</StackPanel>
|
||||
<StackPanel Padding="0,4,0,4"
|
||||
<StackPanel Padding="0,16,0,16"
|
||||
VerticalAlignment="Center"
|
||||
Orientation="Vertical"
|
||||
Visibility="{x:Bind UpdatesAvailable, Mode=OneWay}">
|
||||
@ -51,15 +51,18 @@
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
|
||||
<HyperlinkButton x:Uid="AboutDialog_SourceCodeLink"
|
||||
NavigateUri="https://go.microsoft.com/fwlink/?linkid=2203152" />
|
||||
<HyperlinkButton x:Uid="AboutDialog_DocumentationLink"
|
||||
NavigateUri="https://go.microsoft.com/fwlink/?linkid=2125416" />
|
||||
<HyperlinkButton x:Uid="AboutDialog_ReleaseNotesLink"
|
||||
NavigateUri="https://go.microsoft.com/fwlink/?linkid=2125417" />
|
||||
<HyperlinkButton x:Uid="AboutDialog_PrivacyPolicyLink"
|
||||
NavigateUri="https://go.microsoft.com/fwlink/?linkid=2125418" />
|
||||
<HyperlinkButton x:Uid="AboutDialog_ThirdPartyNoticesLink"
|
||||
Click="_ThirdPartyNoticesOnClick" />
|
||||
<StackPanel Margin="-12,0,0,0"
|
||||
Orientation="Vertical">
|
||||
<HyperlinkButton x:Uid="AboutDialog_SourceCodeLink"
|
||||
NavigateUri="https://go.microsoft.com/fwlink/?linkid=2203152" />
|
||||
<HyperlinkButton x:Uid="AboutDialog_DocumentationLink"
|
||||
NavigateUri="https://go.microsoft.com/fwlink/?linkid=2125416" />
|
||||
<HyperlinkButton x:Uid="AboutDialog_ReleaseNotesLink"
|
||||
NavigateUri="https://go.microsoft.com/fwlink/?linkid=2125417" />
|
||||
<HyperlinkButton x:Uid="AboutDialog_PrivacyPolicyLink"
|
||||
NavigateUri="https://go.microsoft.com/fwlink/?linkid=2125418" />
|
||||
<HyperlinkButton x:Uid="AboutDialog_ThirdPartyNoticesLink"
|
||||
Click="_ThirdPartyNoticesOnClick" />
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</ContentDialog>
|
||||
|
||||
@ -1,28 +0,0 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#include "pch.h"
|
||||
#include "ActionPaletteItem.h"
|
||||
#include <LibraryResources.h>
|
||||
|
||||
#include "ActionPaletteItem.g.cpp"
|
||||
|
||||
using namespace winrt;
|
||||
using namespace winrt::TerminalApp;
|
||||
using namespace winrt::Windows::UI::Core;
|
||||
using namespace winrt::Windows::UI::Xaml;
|
||||
using namespace winrt::Windows::System;
|
||||
using namespace winrt::Windows::Foundation;
|
||||
using namespace winrt::Windows::Foundation::Collections;
|
||||
using namespace winrt::Microsoft::Terminal::Settings::Model;
|
||||
|
||||
namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
ActionPaletteItem::ActionPaletteItem(const Microsoft::Terminal::Settings::Model::Command& command, const winrt::hstring keyChordText) :
|
||||
_Command(command)
|
||||
{
|
||||
Name(command.Name());
|
||||
KeyChordText(keyChordText);
|
||||
Icon(command.IconPath());
|
||||
}
|
||||
}
|
||||
@ -1,26 +0,0 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "PaletteItem.h"
|
||||
#include "ActionPaletteItem.g.h"
|
||||
|
||||
namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
struct ActionPaletteItem : ActionPaletteItemT<ActionPaletteItem, PaletteItem>
|
||||
{
|
||||
ActionPaletteItem() = default;
|
||||
ActionPaletteItem(const Microsoft::Terminal::Settings::Model::Command& command, const winrt::hstring keyChordText);
|
||||
|
||||
WINRT_PROPERTY(Microsoft::Terminal::Settings::Model::Command, Command, nullptr);
|
||||
|
||||
private:
|
||||
Windows::UI::Xaml::Data::INotifyPropertyChanged::PropertyChanged_revoker _commandChangedRevoker;
|
||||
};
|
||||
}
|
||||
|
||||
namespace winrt::TerminalApp::factory_implementation
|
||||
{
|
||||
BASIC_FACTORY(ActionPaletteItem);
|
||||
}
|
||||
@ -1,14 +0,0 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import "PaletteItem.idl";
|
||||
|
||||
namespace TerminalApp
|
||||
{
|
||||
[default_interface] runtimeclass ActionPaletteItem : PaletteItem
|
||||
{
|
||||
ActionPaletteItem(Microsoft.Terminal.Settings.Model.Command command, String keyChordText);
|
||||
|
||||
Microsoft.Terminal.Settings.Model.Command Command { get; };
|
||||
}
|
||||
}
|
||||
@ -243,6 +243,8 @@
|
||||
</ResourceDictionary.ThemeDictionaries>
|
||||
|
||||
</ResourceDictionary>
|
||||
|
||||
<ResourceDictionary Source="ms-resource:///Files/TerminalApp/HighlightedTextControlStyle.xaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
</ResourceDictionary>
|
||||
|
||||
|
||||
@ -41,13 +41,13 @@ namespace winrt::TerminalApp::implementation
|
||||
}
|
||||
return _GetActiveControl();
|
||||
}
|
||||
winrt::com_ptr<TerminalTab> TerminalPage::_senderOrFocusedTab(const IInspectable& sender)
|
||||
winrt::com_ptr<Tab> TerminalPage::_senderOrFocusedTab(const IInspectable& sender)
|
||||
{
|
||||
if (sender)
|
||||
{
|
||||
if (auto tab{ sender.try_as<TerminalApp::TerminalTab>() })
|
||||
if (auto tab = sender.try_as<TerminalApp::Tab>())
|
||||
{
|
||||
return _GetTerminalTabImpl(tab);
|
||||
return _GetTabImpl(tab);
|
||||
}
|
||||
}
|
||||
return _GetFocusedTabImpl();
|
||||
@ -193,17 +193,17 @@ namespace winrt::TerminalApp::implementation
|
||||
void TerminalPage::_HandleCloseOtherPanes(const IInspectable& sender,
|
||||
const ActionEventArgs& args)
|
||||
{
|
||||
if (const auto& terminalTab{ _senderOrFocusedTab(sender) })
|
||||
if (const auto& activeTab{ _senderOrFocusedTab(sender) })
|
||||
{
|
||||
const auto activePane = terminalTab->GetActivePane();
|
||||
if (terminalTab->GetRootPane() != activePane)
|
||||
const auto activePane = activeTab->GetActivePane();
|
||||
if (activeTab->GetRootPane() != activePane)
|
||||
{
|
||||
_UnZoomIfNeeded();
|
||||
|
||||
// Accumulate list of all unfocused leaf panes, ignore read-only panes
|
||||
std::vector<uint32_t> unfocusedPaneIds;
|
||||
const auto activePaneId = activePane->Id();
|
||||
terminalTab->GetRootPane()->WalkTree([&](auto&& p) {
|
||||
activeTab->GetRootPane()->WalkTree([&](auto&& p) {
|
||||
const auto id = p->Id();
|
||||
if (id.has_value() && id != activePaneId && !p->ContainsReadOnly())
|
||||
{
|
||||
@ -215,7 +215,7 @@ namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
// Start by removing the panes that were least recently added
|
||||
sort(begin(unfocusedPaneIds), end(unfocusedPaneIds), std::less<uint32_t>());
|
||||
_ClosePanes(terminalTab->get_weak(), std::move(unfocusedPaneIds));
|
||||
_ClosePanes(activeTab->get_weak(), std::move(unfocusedPaneIds));
|
||||
args.Handled(true);
|
||||
return;
|
||||
}
|
||||
@ -281,9 +281,9 @@ namespace winrt::TerminalApp::implementation
|
||||
|
||||
const auto& duplicateFromTab{ realArgs.SplitMode() == SplitType::Duplicate ? _GetFocusedTab() : nullptr };
|
||||
|
||||
const auto& terminalTab{ _senderOrFocusedTab(sender) };
|
||||
const auto& activeTab{ _senderOrFocusedTab(sender) };
|
||||
|
||||
_SplitPane(terminalTab,
|
||||
_SplitPane(activeTab,
|
||||
realArgs.SplitDirection(),
|
||||
// This is safe, we're already filtering so the value is (0, 1)
|
||||
realArgs.SplitSize(),
|
||||
@ -302,14 +302,14 @@ namespace winrt::TerminalApp::implementation
|
||||
void TerminalPage::_HandleTogglePaneZoom(const IInspectable& sender,
|
||||
const ActionEventArgs& args)
|
||||
{
|
||||
if (const auto terminalTab{ _senderOrFocusedTab(sender) })
|
||||
if (const auto activeTab{ _senderOrFocusedTab(sender) })
|
||||
{
|
||||
// Don't do anything if there's only one pane. It's already zoomed.
|
||||
if (terminalTab->GetLeafPaneCount() > 1)
|
||||
if (activeTab->GetLeafPaneCount() > 1)
|
||||
{
|
||||
// Togging the zoom on the tab will cause the tab to inform us of
|
||||
// the new root Content for this tab.
|
||||
terminalTab->ToggleZoom();
|
||||
activeTab->ToggleZoom();
|
||||
}
|
||||
}
|
||||
|
||||
@ -517,7 +517,7 @@ namespace winrt::TerminalApp::implementation
|
||||
else
|
||||
{
|
||||
// Mark as handled only when the move succeeded (e.g. when there
|
||||
// is a pane to move to), otherwise mark as unhandled so the
|
||||
// is a pane to move to); otherwise, mark as unhandled so the
|
||||
// keychord can propagate to the terminal (GH#6129)
|
||||
const auto moveSucceeded = _MoveFocus(realArgs.FocusDirection());
|
||||
args.Handled(moveSucceeded);
|
||||
@ -548,7 +548,9 @@ namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
if (const auto& realArgs = args.ActionArgs().try_as<CopyTextArgs>())
|
||||
{
|
||||
const auto handled = _CopyText(realArgs.DismissSelection(), realArgs.SingleLine(), realArgs.WithControlSequences(), realArgs.CopyFormatting());
|
||||
const auto copyFormatting = realArgs.CopyFormatting();
|
||||
const auto format = copyFormatting ? copyFormatting.Value() : _settings.GlobalSettings().CopyFormatting();
|
||||
const auto handled = _CopyText(realArgs.DismissSelection(), realArgs.SingleLine(), realArgs.WithControlSequences(), format);
|
||||
args.Handled(handled);
|
||||
}
|
||||
}
|
||||
@ -756,7 +758,7 @@ namespace winrt::TerminalApp::implementation
|
||||
if (!actions.empty())
|
||||
{
|
||||
actionArgs.Handled(true);
|
||||
ProcessStartupActions(std::move(actions), false);
|
||||
ProcessStartupActions(std::move(actions));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -783,7 +785,7 @@ namespace winrt::TerminalApp::implementation
|
||||
}
|
||||
|
||||
// Since _RemoveTabs is asynchronous, create a snapshot of the tabs we want to remove
|
||||
std::vector<winrt::TerminalApp::TabBase> tabsToRemove;
|
||||
std::vector<winrt::TerminalApp::Tab> tabsToRemove;
|
||||
if (index > 0)
|
||||
{
|
||||
std::copy(begin(_tabs), begin(_tabs) + index, std::back_inserter(tabsToRemove));
|
||||
@ -822,7 +824,7 @@ namespace winrt::TerminalApp::implementation
|
||||
}
|
||||
|
||||
// Since _RemoveTabs is asynchronous, create a snapshot of the tabs we want to remove
|
||||
std::vector<winrt::TerminalApp::TabBase> tabsToRemove;
|
||||
std::vector<winrt::TerminalApp::Tab> tabsToRemove;
|
||||
std::copy(begin(_tabs) + index + 1, end(_tabs), std::back_inserter(tabsToRemove));
|
||||
_RemoveTabs(tabsToRemove);
|
||||
|
||||
@ -1559,7 +1561,6 @@ namespace winrt::TerminalApp::implementation
|
||||
activeTab->ToggleBroadcastInput();
|
||||
args.Handled(true);
|
||||
}
|
||||
// If the focused tab wasn't a TerminalTab, then leave handled=false
|
||||
}
|
||||
|
||||
void TerminalPage::_HandleRestartConnection(const IInspectable& sender,
|
||||
|
||||
@ -961,18 +961,6 @@ std::vector<ActionAndArgs>& AppCommandlineArgs::GetStartupActions()
|
||||
return _startupActions;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Returns whether we should start listening for inbound PTY connections
|
||||
// coming from the operating system default application feature.
|
||||
// Arguments:
|
||||
// - <none>
|
||||
// Return Value:
|
||||
// - True if the listener should be started. False otherwise.
|
||||
bool AppCommandlineArgs::IsHandoffListener() const noexcept
|
||||
{
|
||||
return _isHandoffListener;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Get the string of text that should be displayed to the user on exit. This
|
||||
// is usually helpful for cases where the user entered some sort of invalid
|
||||
@ -1015,34 +1003,28 @@ bool AppCommandlineArgs::ShouldExitEarly() const noexcept
|
||||
// - <none>
|
||||
void AppCommandlineArgs::ValidateStartupCommands()
|
||||
{
|
||||
// Only check over the actions list for the potential to add a new-tab
|
||||
// command if we are not starting for the purposes of receiving an inbound
|
||||
// handoff connection from the operating system.
|
||||
if (!_isHandoffListener)
|
||||
// If we only have a single x-save command, then set our target to the
|
||||
// current terminal window. This will prevent us from spawning a new
|
||||
// window just to save the commandline.
|
||||
if (_startupActions.size() == 1 &&
|
||||
_startupActions.front().Action() == ShortcutAction::SaveSnippet &&
|
||||
_windowTarget.empty())
|
||||
{
|
||||
// If we only have a single x-save command, then set our target to the
|
||||
// current terminal window. This will prevent us from spawning a new
|
||||
// window just to save the commandline.
|
||||
if (_startupActions.size() == 1 &&
|
||||
_startupActions.front().Action() == ShortcutAction::SaveSnippet &&
|
||||
_windowTarget.empty())
|
||||
{
|
||||
_windowTarget = "0";
|
||||
}
|
||||
// If we parsed no commands, or the first command we've parsed is not a new
|
||||
// tab action, prepend a new-tab command to the front of the list.
|
||||
// (also, we don't need to do this if the only action is a x-save)
|
||||
else if (_startupActions.empty() ||
|
||||
(_startupActions.front().Action() != ShortcutAction::NewTab &&
|
||||
_startupActions.front().Action() != ShortcutAction::SaveSnippet))
|
||||
{
|
||||
// Build the NewTab action from the values we've parsed on the commandline.
|
||||
NewTerminalArgs newTerminalArgs{};
|
||||
NewTabArgs args{ newTerminalArgs };
|
||||
ActionAndArgs newTabAction{ ShortcutAction::NewTab, args };
|
||||
// push the arg onto the front
|
||||
_startupActions.insert(_startupActions.begin(), 1, newTabAction);
|
||||
}
|
||||
_windowTarget = "0";
|
||||
}
|
||||
// If we parsed no commands, or the first command we've parsed is not a new
|
||||
// tab action, prepend a new-tab command to the front of the list.
|
||||
// (also, we don't need to do this if the only action is a x-save)
|
||||
else if (_startupActions.empty() ||
|
||||
(_startupActions.front().Action() != ShortcutAction::NewTab &&
|
||||
_startupActions.front().Action() != ShortcutAction::SaveSnippet))
|
||||
{
|
||||
// Build the NewTab action from the values we've parsed on the commandline.
|
||||
NewTerminalArgs newTerminalArgs{};
|
||||
NewTabArgs args{ newTerminalArgs };
|
||||
ActionAndArgs newTabAction{ ShortcutAction::NewTab, args };
|
||||
// push the arg onto the front
|
||||
_startupActions.insert(_startupActions.begin(), 1, newTabAction);
|
||||
}
|
||||
}
|
||||
std::optional<uint32_t> AppCommandlineArgs::GetPersistedLayoutIdx() const noexcept
|
||||
@ -1082,13 +1064,9 @@ std::optional<til::size> AppCommandlineArgs::GetSize() const noexcept
|
||||
// - 0 if the commandline was successfully parsed
|
||||
int AppCommandlineArgs::ParseArgs(winrt::array_view<const winrt::hstring> args)
|
||||
{
|
||||
for (const auto& arg : args)
|
||||
if (args.size() == 2 && args[1] == L"-Embedding")
|
||||
{
|
||||
if (arg == L"-Embedding")
|
||||
{
|
||||
_isHandoffListener = true;
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto commands = ::TerminalApp::AppCommandlineArgs::BuildCommands(args);
|
||||
@ -1195,7 +1173,6 @@ void AppCommandlineArgs::FullResetState()
|
||||
_startupActions.clear();
|
||||
_exitMessage = "";
|
||||
_shouldExitEarly = false;
|
||||
_isHandoffListener = false;
|
||||
|
||||
_windowTarget = {};
|
||||
}
|
||||
|
||||
@ -35,7 +35,6 @@ public:
|
||||
|
||||
void ValidateStartupCommands();
|
||||
std::vector<winrt::Microsoft::Terminal::Settings::Model::ActionAndArgs>& GetStartupActions();
|
||||
bool IsHandoffListener() const noexcept;
|
||||
const std::string& GetExitMessage() const noexcept;
|
||||
bool ShouldExitEarly() const noexcept;
|
||||
|
||||
@ -132,7 +131,6 @@ private:
|
||||
std::optional<winrt::Microsoft::Terminal::Settings::Model::LaunchMode> _launchMode{ std::nullopt };
|
||||
std::optional<winrt::Microsoft::Terminal::Settings::Model::LaunchPosition> _position{ std::nullopt };
|
||||
std::optional<til::size> _size{ std::nullopt };
|
||||
bool _isHandoffListener{ false };
|
||||
std::vector<winrt::Microsoft::Terminal::Settings::Model::ActionAndArgs> _startupActions;
|
||||
std::string _exitMessage;
|
||||
bool _shouldExitEarly{ false };
|
||||
|
||||
@ -135,12 +135,19 @@ namespace winrt::TerminalApp::implementation
|
||||
_isElevated = ::Microsoft::Console::Utils::IsRunningElevated();
|
||||
_canDragDrop = ::Microsoft::Console::Utils::CanUwpDragDrop();
|
||||
|
||||
_reloadSettings = std::make_shared<ThrottledFuncTrailing<>>(winrt::Windows::System::DispatcherQueue::GetForCurrentThread(), std::chrono::milliseconds(100), [weakSelf = get_weak()]() {
|
||||
if (auto self{ weakSelf.get() })
|
||||
{
|
||||
self->ReloadSettings();
|
||||
}
|
||||
});
|
||||
_reloadSettings = std::make_shared<ThrottledFunc<>>(
|
||||
DispatcherQueue::GetForCurrentThread(),
|
||||
til::throttled_func_options{
|
||||
.delay = std::chrono::milliseconds{ 100 },
|
||||
.debounce = true,
|
||||
.trailing = true,
|
||||
},
|
||||
[weakSelf = get_weak()]() {
|
||||
if (auto self{ weakSelf.get() })
|
||||
{
|
||||
self->ReloadSettings();
|
||||
}
|
||||
});
|
||||
|
||||
_languageProfileNotifier = winrt::make_self<LanguageProfileNotifier>([this]() {
|
||||
_reloadSettings->Run();
|
||||
@ -194,7 +201,7 @@ namespace winrt::TerminalApp::implementation
|
||||
// Method Description:
|
||||
// - Attempt to load the settings. If we fail for any reason, returns an error.
|
||||
// Return Value:
|
||||
// - S_OK if we successfully parsed the settings, otherwise an appropriate HRESULT.
|
||||
// - S_OK if we successfully parsed the settings; otherwise, an appropriate HRESULT.
|
||||
[[nodiscard]] HRESULT AppLogic::_TryLoadSettings() noexcept
|
||||
{
|
||||
auto hr = E_FAIL;
|
||||
@ -392,7 +399,7 @@ namespace winrt::TerminalApp::implementation
|
||||
auto ev = winrt::make_self<SettingsLoadEventArgs>(true,
|
||||
static_cast<uint64_t>(_settingsLoadedResult),
|
||||
_settingsLoadExceptionText,
|
||||
warnings,
|
||||
warnings.GetView(),
|
||||
_settings);
|
||||
SettingsChanged.raise(*this, *ev);
|
||||
return;
|
||||
@ -424,7 +431,7 @@ namespace winrt::TerminalApp::implementation
|
||||
auto ev = winrt::make_self<SettingsLoadEventArgs>(!initialLoad,
|
||||
_settingsLoadedResult,
|
||||
_settingsLoadExceptionText,
|
||||
warnings,
|
||||
warnings.GetView(),
|
||||
_settings);
|
||||
SettingsChanged.raise(*this, *ev);
|
||||
}
|
||||
@ -491,7 +498,7 @@ namespace winrt::TerminalApp::implementation
|
||||
auto ev = winrt::make_self<SettingsLoadEventArgs>(false,
|
||||
_settingsLoadedResult,
|
||||
_settingsLoadExceptionText,
|
||||
warnings,
|
||||
warnings.GetView(),
|
||||
_settings);
|
||||
|
||||
auto window = winrt::make_self<implementation::TerminalWindow>(*ev, _contentManager);
|
||||
|
||||
@ -64,7 +64,7 @@ namespace winrt::TerminalApp::implementation
|
||||
bool _hasSettingsStartupActions{ false };
|
||||
::TerminalApp::AppCommandlineArgs _settingsAppArgs;
|
||||
|
||||
std::shared_ptr<ThrottledFuncTrailing<>> _reloadSettings;
|
||||
std::shared_ptr<ThrottledFunc<>> _reloadSettings;
|
||||
|
||||
std::vector<Microsoft::Terminal::Settings::Model::SettingsLoadWarnings> _warnings{};
|
||||
|
||||
|
||||
40
src/cascadia/TerminalApp/BasePaletteItem.h
Normal file
40
src/cascadia/TerminalApp/BasePaletteItem.h
Normal file
@ -0,0 +1,40 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
template<typename T, winrt::TerminalApp::PaletteItemType Ty>
|
||||
struct BasePaletteItem
|
||||
{
|
||||
public:
|
||||
winrt::TerminalApp::PaletteItemType Type() { return Ty; }
|
||||
|
||||
Windows::UI::Xaml::Controls::IconElement ResolvedIcon()
|
||||
{
|
||||
const auto icon{ static_cast<T*>(this)->Icon() };
|
||||
if (!icon.empty())
|
||||
{
|
||||
const auto resolvedIcon{ Microsoft::Terminal::UI::IconPathConverter::IconWUX(icon) };
|
||||
resolvedIcon.Width(16);
|
||||
resolvedIcon.Height(16);
|
||||
return resolvedIcon;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
til::property_changed_event PropertyChanged;
|
||||
|
||||
protected:
|
||||
void BaseRaisePropertyChanged(wil::zwstring_view property)
|
||||
{
|
||||
PropertyChanged.raise(*static_cast<T*>(this), winrt::Windows::UI::Xaml::Data::PropertyChangedEventArgs{ property });
|
||||
}
|
||||
|
||||
void InvalidateResolvedIcon()
|
||||
{
|
||||
BaseRaisePropertyChanged(L"ResolvedIcon");
|
||||
}
|
||||
};
|
||||
}
|
||||
@ -1,267 +0,0 @@
|
||||
#include "ColorHelper.h"
|
||||
|
||||
using namespace winrt::TerminalApp;
|
||||
|
||||
// Method Description:
|
||||
// Determines whether or not a given color is light
|
||||
// Arguments:
|
||||
// - color: this color is going to be examined whether it
|
||||
// is light or not
|
||||
// Return Value:
|
||||
// - true of light, false if dark
|
||||
bool ColorHelper::IsBrightColor(const winrt::Windows::UI::Color& color)
|
||||
{
|
||||
// https://www.w3.org/TR/AERT#color-contrast
|
||||
auto brightness = (color.R * 299 + color.G * 587 + color.B * 114) / 1000.f;
|
||||
return brightness > 128.f;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// Converts a rgb color to an hsl one
|
||||
// Arguments:
|
||||
// - color: the rgb color, which is going to be converted
|
||||
// Return Value:
|
||||
// - a hsl color with the following ranges
|
||||
// - H: [0.f -360.f]
|
||||
// - L: [0.f - 1.f] (rounded to the third decimal place)
|
||||
// - S: [0.f - 1.f] (rounded to the third decimal place)
|
||||
HSL ColorHelper::RgbToHsl(const winrt::Windows::UI::Color& color)
|
||||
{
|
||||
// https://www.rapidtables.com/convert/color/rgb-to-hsl.html
|
||||
auto epsilon = std::numeric_limits<float>::epsilon();
|
||||
auto r = color.R / 255.f;
|
||||
auto g = color.G / 255.f;
|
||||
auto b = color.B / 255.f;
|
||||
|
||||
auto max = std::max(r, std::max(g, b));
|
||||
auto min = std::min(r, std::min(g, b));
|
||||
|
||||
auto delta = max - min;
|
||||
|
||||
auto h = 0.f;
|
||||
auto s = 0.f;
|
||||
auto l = (max + min) / 2;
|
||||
|
||||
if (delta < epsilon || max < epsilon) /* delta == 0 || max == 0*/
|
||||
{
|
||||
l = std::roundf(l * 1000) / 1000;
|
||||
return HSL{ h, s, l };
|
||||
}
|
||||
|
||||
s = l > 0.5 ? delta / (2 - max - min) : delta / (max + min);
|
||||
|
||||
if (max - r < epsilon) // max == r
|
||||
{
|
||||
h = (g - b) / delta + (g < b ? 6 : 0);
|
||||
}
|
||||
else if (max - g < epsilon) // max == g
|
||||
{
|
||||
h = (b - r) / delta + 2;
|
||||
}
|
||||
else if (max - b < epsilon) // max == b
|
||||
{
|
||||
h = (r - g) / delta + 4;
|
||||
}
|
||||
|
||||
// three decimal places after the comma ought
|
||||
// to be enough for everybody - Bill Gates, 1981
|
||||
auto finalH = std::roundf(h * 60);
|
||||
auto finalS = std::roundf(s * 1000) / 1000;
|
||||
auto finalL = std::roundf(l * 1000) / 1000;
|
||||
|
||||
return HSL{ finalH, finalS, finalL };
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// Converts a hsl color to rgb one
|
||||
// Arguments:
|
||||
// - color: the hsl color, which is going to be converted
|
||||
// Return Value:
|
||||
// - the rgb color (r,g,b - [0, 255] range)
|
||||
winrt::Windows::UI::Color ColorHelper::HslToRgb(const HSL& color)
|
||||
{
|
||||
auto epsilon = std::numeric_limits<float>::epsilon();
|
||||
|
||||
auto h = (color.H - 1.f > epsilon) ? color.H / 360.f : color.H;
|
||||
auto s = (color.S - 1.f > epsilon) ? color.S / 100.f : color.S;
|
||||
auto l = (color.L - 1.f > epsilon) ? color.L / 100.f : color.L;
|
||||
|
||||
auto r = l;
|
||||
auto g = l;
|
||||
auto b = l;
|
||||
|
||||
if (s > epsilon)
|
||||
{
|
||||
auto q = l < 0.5 ? l * (1 + s) : l + s - l * s;
|
||||
auto p = 2 * l - q;
|
||||
r = HueToRgb(p, q, h + 1.f / 3.f);
|
||||
g = HueToRgb(p, q, h);
|
||||
b = HueToRgb(p, q, h - 1.f / 3.f);
|
||||
}
|
||||
|
||||
auto finalR = static_cast<uint8_t>(std::roundf(r * 255));
|
||||
auto finalG = static_cast<uint8_t>(std::roundf(g * 255));
|
||||
auto finalB = static_cast<uint8_t>(std::roundf(b * 255));
|
||||
uint8_t finalA = 255; //opaque
|
||||
|
||||
return winrt::Windows::UI::ColorHelper::FromArgb(finalA, finalR, finalG, finalB);
|
||||
}
|
||||
|
||||
float ColorHelper::HueToRgb(float p, float q, float t)
|
||||
{
|
||||
auto epsilon = std::numeric_limits<float>::epsilon();
|
||||
|
||||
if (t < 0)
|
||||
t += 1;
|
||||
if (t > 1)
|
||||
t -= 1;
|
||||
if (t - (1.f / 6.f) < epsilon)
|
||||
return p + (q - p) * 6 * t;
|
||||
if (t - .5f < epsilon)
|
||||
return q;
|
||||
if (t - 2.f / 3.f < epsilon)
|
||||
return p + (q - p) * (2.f / 3.f - t) * 6;
|
||||
return p;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// Lightens a color by a given amount
|
||||
// Arguments:
|
||||
// - color: the color which is going to be lightened
|
||||
// - amount: the lighten amount (0-100)
|
||||
// Return Value:
|
||||
// - the lightened color in RGB format
|
||||
winrt::Windows::UI::Color ColorHelper::Lighten(const winrt::Windows::UI::Color& color, float amount /* = 10.f*/)
|
||||
{
|
||||
auto hsl = RgbToHsl(color);
|
||||
hsl.L += amount / 100;
|
||||
hsl.L = std::clamp(hsl.L, 0.f, 1.f);
|
||||
return HslToRgb(hsl);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// Darkens a color by a given amount
|
||||
// Arguments:
|
||||
// - color: the color which is going to be darkened
|
||||
// - amount: the darken amount (0-100)
|
||||
// Return Value:
|
||||
// - the darkened color in RGB format
|
||||
winrt::Windows::UI::Color ColorHelper::Darken(const winrt::Windows::UI::Color& color, float amount /* = 10.f*/)
|
||||
{
|
||||
auto hsl = RgbToHsl(color);
|
||||
hsl.L -= amount / 100;
|
||||
hsl.L = std::clamp(hsl.L, 0.f, 1.f);
|
||||
return HslToRgb(hsl);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// Gets an accent color to a given color. Basically, generates
|
||||
// 16 shades of the color and finds the first which has a good
|
||||
// contrast according to https://www.w3.org/TR/2008/REC-WCAG20-20081211/#contrast-ratiodef (WCAG Version 2)
|
||||
// Readability ratio of 3.5 seems to look quite nicely
|
||||
// Arguments:
|
||||
// - color: the color for which we need an accent
|
||||
// Return Value:
|
||||
// - the accent color in RGB format
|
||||
winrt::Windows::UI::Color ColorHelper::GetAccentColor(const winrt::Windows::UI::Color& color)
|
||||
{
|
||||
auto accentColor = RgbToHsl(color);
|
||||
|
||||
if (accentColor.S < 0.15)
|
||||
{
|
||||
accentColor.S = 0.15f;
|
||||
}
|
||||
|
||||
constexpr auto shadeCount = 16;
|
||||
constexpr auto shadeStep = 1.f / shadeCount;
|
||||
auto shades = std::map<float, HSL>();
|
||||
for (auto i = 0; i < 15; i++)
|
||||
{
|
||||
auto shade = HSL{ accentColor.H, accentColor.S, i * shadeStep };
|
||||
auto contrast = GetReadability(shade, accentColor);
|
||||
shades.insert(std::make_pair(contrast, shade));
|
||||
}
|
||||
|
||||
// 3f is quite nice if the whole non-client area is painted
|
||||
constexpr auto readability = 1.75f;
|
||||
for (auto shade : shades)
|
||||
{
|
||||
if (shade.first >= readability)
|
||||
{
|
||||
return HslToRgb(shade.second);
|
||||
}
|
||||
}
|
||||
return HslToRgb(shades.end()->second);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// Gets the readability of two colors according to
|
||||
// https://www.w3.org/TR/2008/REC-WCAG20-20081211/#contrast-ratiodef (WCAG Version 2)
|
||||
// Arguments:
|
||||
// - firstColor: the first color for the readability check (hsl)
|
||||
// - secondColor: the second color for the readability check (hsl)
|
||||
// Return Value:
|
||||
// - the readability of the colors according to (WCAG Version 2)
|
||||
float ColorHelper::GetReadability(const HSL& first, const HSL& second)
|
||||
{
|
||||
return GetReadability(HslToRgb(first), HslToRgb(second));
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// Gets the readability of two colors according to
|
||||
// https://www.w3.org/TR/2008/REC-WCAG20-20081211/#contrast-ratiodef (WCAG Version 2)
|
||||
// Arguments:
|
||||
// - firstColor: the first color for the readability check (rgb)
|
||||
// - secondColor: the second color for the readability check (rgb)
|
||||
// Return Value:
|
||||
// - the readability of the colors according to (WCAG Version 2)
|
||||
float ColorHelper::GetReadability(const winrt::Windows::UI::Color& first, const winrt::Windows::UI::Color& second)
|
||||
{
|
||||
auto l1 = GetLuminance(first);
|
||||
auto l2 = GetLuminance(second);
|
||||
|
||||
return (std::max(l1, l2) + 0.05f) / std::min(l1, l2) + 0.05f;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// Calculates the luminance of a given color according to
|
||||
// https://www.w3.org/TR/2008/REC-WCAG20-20081211/#relativeluminancedef
|
||||
// Arguments:
|
||||
// - color: its luminance is going to be calculated
|
||||
// Return Value:
|
||||
// - the luminance of the color
|
||||
float ColorHelper::GetLuminance(const winrt::Windows::UI::Color& color)
|
||||
{
|
||||
auto epsilon = std::numeric_limits<float>::epsilon();
|
||||
float R, G, B;
|
||||
auto RsRGB = color.R / 255.f;
|
||||
auto GsRGB = color.G / 255.f;
|
||||
auto BsRGB = color.B / 255.f;
|
||||
|
||||
if (RsRGB - 0.03928f <= epsilon)
|
||||
{
|
||||
R = RsRGB / 12.92f;
|
||||
}
|
||||
else
|
||||
{
|
||||
R = std::pow(((RsRGB + 0.055f) / 1.055f), 2.4f);
|
||||
}
|
||||
if (GsRGB - 0.03928f <= epsilon)
|
||||
{
|
||||
G = GsRGB / 12.92f;
|
||||
}
|
||||
else
|
||||
{
|
||||
G = std::pow(((GsRGB + 0.055f) / 1.055f), 2.4f);
|
||||
}
|
||||
if (BsRGB - 0.03928f <= epsilon)
|
||||
{
|
||||
B = BsRGB / 12.92f;
|
||||
}
|
||||
else
|
||||
{
|
||||
B = std::pow(((BsRGB + 0.055f) / 1.055f), 2.4f);
|
||||
}
|
||||
auto luminance = (0.2126f * R) + (0.7152f * G) + (0.0722f * B);
|
||||
return std::roundf(luminance * 10000) / 10000.f;
|
||||
}
|
||||
@ -1,31 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <winrt/Windows.UI.h>
|
||||
|
||||
namespace winrt::TerminalApp
|
||||
{
|
||||
class HSL
|
||||
{
|
||||
public:
|
||||
float H;
|
||||
float S;
|
||||
float L;
|
||||
};
|
||||
|
||||
class ColorHelper
|
||||
{
|
||||
public:
|
||||
static bool IsBrightColor(const Windows::UI::Color& color);
|
||||
static HSL RgbToHsl(const Windows::UI::Color& color);
|
||||
static Windows::UI::Color HslToRgb(const HSL& color);
|
||||
static Windows::UI::Color Lighten(const Windows::UI::Color& color, float amount = 10.f);
|
||||
static Windows::UI::Color Darken(const Windows::UI::Color& color, float amount = 10.f);
|
||||
static Windows::UI::Color GetAccentColor(const Windows::UI::Color& color);
|
||||
static float GetLuminance(const Windows::UI::Color& color);
|
||||
static float GetReadability(const Windows::UI::Color& first, const Windows::UI::Color& second);
|
||||
static float GetReadability(const HSL& first, const HSL& second);
|
||||
|
||||
private:
|
||||
static float HueToRgb(float p, float q, float t);
|
||||
};
|
||||
}
|
||||
@ -1,26 +0,0 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#include "pch.h"
|
||||
#include "CommandLinePaletteItem.h"
|
||||
#include <LibraryResources.h>
|
||||
|
||||
#include "CommandLinePaletteItem.g.cpp"
|
||||
|
||||
using namespace winrt;
|
||||
using namespace winrt::TerminalApp;
|
||||
using namespace winrt::Windows::UI::Core;
|
||||
using namespace winrt::Windows::UI::Xaml;
|
||||
using namespace winrt::Windows::System;
|
||||
using namespace winrt::Windows::Foundation;
|
||||
using namespace winrt::Windows::Foundation::Collections;
|
||||
using namespace winrt::Microsoft::Terminal::Settings::Model;
|
||||
|
||||
namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
CommandLinePaletteItem::CommandLinePaletteItem(const winrt::hstring& commandLine) :
|
||||
_CommandLine(commandLine)
|
||||
{
|
||||
Name(commandLine);
|
||||
}
|
||||
}
|
||||
@ -1,23 +0,0 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "PaletteItem.h"
|
||||
#include "CommandLinePaletteItem.g.h"
|
||||
|
||||
namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
struct CommandLinePaletteItem : CommandLinePaletteItemT<CommandLinePaletteItem, PaletteItem>
|
||||
{
|
||||
CommandLinePaletteItem() = default;
|
||||
CommandLinePaletteItem(const winrt::hstring& commandLine);
|
||||
|
||||
WINRT_PROPERTY(winrt::hstring, CommandLine);
|
||||
};
|
||||
}
|
||||
|
||||
namespace winrt::TerminalApp::factory_implementation
|
||||
{
|
||||
BASIC_FACTORY(CommandLinePaletteItem);
|
||||
}
|
||||
@ -1,12 +0,0 @@
|
||||
import "PaletteItem.idl";
|
||||
import "TabBase.idl";
|
||||
|
||||
namespace TerminalApp
|
||||
{
|
||||
[default_interface] runtimeclass CommandLinePaletteItem : PaletteItem
|
||||
{
|
||||
CommandLinePaletteItem(String commandLine);
|
||||
|
||||
String CommandLine { get; };
|
||||
}
|
||||
}
|
||||
@ -2,10 +2,8 @@
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#include "pch.h"
|
||||
#include "ActionPaletteItem.h"
|
||||
#include "TabPaletteItem.h"
|
||||
#include "CommandLinePaletteItem.h"
|
||||
#include "CommandPalette.h"
|
||||
#include "CommandPaletteItems.h"
|
||||
#include <LibraryResources.h>
|
||||
|
||||
#include "CommandPalette.g.cpp"
|
||||
@ -233,9 +231,11 @@ namespace winrt::TerminalApp::implementation
|
||||
}
|
||||
else if (_currentMode == CommandPaletteMode::ActionMode && filteredCommand != nullptr)
|
||||
{
|
||||
if (const auto actionPaletteItem{ filteredCommand.Item().try_as<winrt::TerminalApp::ActionPaletteItem>() })
|
||||
const auto item{ filteredCommand.Item() };
|
||||
if (item.Type() == PaletteItemType::Action)
|
||||
{
|
||||
PreviewAction.raise(*this, actionPaletteItem.Command());
|
||||
const auto actionPaletteItem{ winrt::get_self<ActionPaletteItem>(item) };
|
||||
PreviewAction.raise(*this, actionPaletteItem->Command());
|
||||
}
|
||||
}
|
||||
else if (_currentMode == CommandPaletteMode::CommandlineMode)
|
||||
@ -338,7 +338,7 @@ namespace winrt::TerminalApp::implementation
|
||||
}
|
||||
else if (key == VirtualKey::Escape)
|
||||
{
|
||||
// Dismiss the palette if the text is empty, otherwise clear the
|
||||
// Dismiss the palette if the text is empty; otherwise, clear the
|
||||
// search string.
|
||||
if (_searchBox().Text().empty())
|
||||
{
|
||||
@ -555,10 +555,11 @@ namespace winrt::TerminalApp::implementation
|
||||
const auto enteredItem = listViewItem.Content();
|
||||
if (const auto filteredCommand{ enteredItem.try_as<winrt::TerminalApp::FilteredCommand>() })
|
||||
{
|
||||
if (const auto actionPaletteItem{ filteredCommand.Item().try_as<winrt::TerminalApp::ActionPaletteItem>() })
|
||||
const auto item{ filteredCommand.Item() };
|
||||
if (item.Type() == PaletteItemType::Action)
|
||||
{
|
||||
// immediately preview the hovered command
|
||||
PreviewAction.raise(*this, actionPaletteItem.Command());
|
||||
const auto actionPaletteItem{ winrt::get_self<ActionPaletteItem>(item) };
|
||||
PreviewAction.raise(*this, actionPaletteItem->Command());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -589,9 +590,11 @@ namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
if (_currentMode == CommandPaletteMode::ActionMode && filteredCommand)
|
||||
{
|
||||
if (const auto actionPaletteItem{ filteredCommand.Item().try_as<winrt::TerminalApp::ActionPaletteItem>() })
|
||||
const auto item{ filteredCommand.Item() };
|
||||
if (item.Type() == PaletteItemType::Action)
|
||||
{
|
||||
PreviewAction.raise(*this, actionPaletteItem.Command());
|
||||
const auto actionPaletteItem{ winrt::get_self<ActionPaletteItem>(item) };
|
||||
PreviewAction.raise(*this, actionPaletteItem->Command());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -617,7 +620,7 @@ namespace winrt::TerminalApp::implementation
|
||||
const auto selectedCommand = selectedList.GetAt(0);
|
||||
if (const auto filteredCmd = selectedCommand.try_as<TerminalApp::FilteredCommand>())
|
||||
{
|
||||
if (const auto paletteItem = filteredCmd.Item().try_as<TerminalApp::PaletteItem>())
|
||||
if (const auto paletteItem = filteredCmd.Item())
|
||||
{
|
||||
automationPeer.RaiseNotificationEvent(
|
||||
Automation::Peers::AutomationNotificationKind::ItemAdded,
|
||||
@ -652,10 +655,13 @@ namespace winrt::TerminalApp::implementation
|
||||
if (_nestedActionStack.Size() > 0)
|
||||
{
|
||||
const auto newPreviousAction{ _nestedActionStack.GetAt(_nestedActionStack.Size() - 1) };
|
||||
const auto actionPaletteItem{ newPreviousAction.Item().try_as<winrt::TerminalApp::ActionPaletteItem>() };
|
||||
|
||||
ParentCommandName(actionPaletteItem.Command().Name());
|
||||
_updateCurrentNestedCommands(actionPaletteItem.Command());
|
||||
const auto item{ newPreviousAction.Item() };
|
||||
if (item.Type() == PaletteItemType::Action)
|
||||
{
|
||||
const auto actionPaletteItem{ winrt::get_self<ActionPaletteItem>(item) };
|
||||
ParentCommandName(actionPaletteItem->Command().Name());
|
||||
_updateCurrentNestedCommands(actionPaletteItem->Command());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -757,16 +763,19 @@ namespace winrt::TerminalApp::implementation
|
||||
}
|
||||
else if (filteredCommand)
|
||||
{
|
||||
if (const auto actionPaletteItem{ filteredCommand.Item().try_as<winrt::TerminalApp::ActionPaletteItem>() })
|
||||
auto item{ filteredCommand.Item() };
|
||||
if (item.Type() == PaletteItemType::Action)
|
||||
{
|
||||
if (actionPaletteItem.Command().HasNestedCommands())
|
||||
const auto actionPaletteItem{ winrt::get_self<ActionPaletteItem>(item) };
|
||||
auto command{ actionPaletteItem->Command() };
|
||||
if (command.HasNestedCommands())
|
||||
{
|
||||
// If this Command had subcommands, then don't dispatch the
|
||||
// action. Instead, display a new list of commands for the user
|
||||
// to pick from.
|
||||
_nestedActionStack.Append(filteredCommand);
|
||||
ParentCommandName(actionPaletteItem.Command().Name());
|
||||
_updateCurrentNestedCommands(actionPaletteItem.Command());
|
||||
ParentCommandName(command.Name());
|
||||
_updateCurrentNestedCommands(command);
|
||||
|
||||
_updateUIForStackChange();
|
||||
}
|
||||
@ -785,9 +794,9 @@ namespace winrt::TerminalApp::implementation
|
||||
// But make an exception for the Toggle Command Palette action: we don't want the dispatch
|
||||
// make the command palette - that was just closed - visible again.
|
||||
// All other actions can just be dispatched.
|
||||
if (actionPaletteItem.Command().ActionAndArgs().Action() != ShortcutAction::ToggleCommandPalette)
|
||||
if (command.ActionAndArgs().Action() != ShortcutAction::ToggleCommandPalette)
|
||||
{
|
||||
DispatchCommandRequested.raise(*this, actionPaletteItem.Command());
|
||||
DispatchCommandRequested.raise(*this, command);
|
||||
}
|
||||
|
||||
TraceLoggingWrite(
|
||||
@ -837,9 +846,11 @@ namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
if (filteredCommand)
|
||||
{
|
||||
if (const auto tabPaletteItem{ filteredCommand.Item().try_as<winrt::TerminalApp::TabPaletteItem>() })
|
||||
const auto item{ filteredCommand.Item() };
|
||||
if (item.Type() == PaletteItemType::Tab)
|
||||
{
|
||||
if (const auto tab{ tabPaletteItem.Tab() })
|
||||
const auto tabPaletteItem{ winrt::get_self<TabPaletteItem>(item) };
|
||||
if (const auto tab{ tabPaletteItem->Tab() })
|
||||
{
|
||||
SwitchToTabRequested.raise(*this, tab);
|
||||
}
|
||||
@ -867,9 +878,11 @@ namespace winrt::TerminalApp::implementation
|
||||
TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES),
|
||||
TelemetryPrivacyDataTag(PDT_ProductAndServiceUsage));
|
||||
|
||||
if (const auto commandLinePaletteItem{ filteredCommand.value().Item().try_as<winrt::TerminalApp::CommandLinePaletteItem>() })
|
||||
const auto item{ filteredCommand->Item() };
|
||||
if (item.Type() == PaletteItemType::CommandLine)
|
||||
{
|
||||
CommandLineExecutionRequested.raise(*this, commandLinePaletteItem.CommandLine());
|
||||
const auto commandLinePaletteItem{ winrt::get_self<CommandLinePaletteItem>(item) };
|
||||
CommandLineExecutionRequested.raise(*this, commandLinePaletteItem->CommandLine());
|
||||
_close();
|
||||
}
|
||||
}
|
||||
@ -1059,7 +1072,7 @@ namespace winrt::TerminalApp::implementation
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void CommandPalette::_bindTabs(
|
||||
const Windows::Foundation::Collections::IObservableVector<winrt::TerminalApp::TabBase>& source,
|
||||
const Windows::Foundation::Collections::IObservableVector<winrt::TerminalApp::Tab>& source,
|
||||
const Windows::Foundation::Collections::IVector<winrt::TerminalApp::FilteredCommand>& target)
|
||||
{
|
||||
target.Clear();
|
||||
@ -1071,7 +1084,7 @@ namespace winrt::TerminalApp::implementation
|
||||
}
|
||||
}
|
||||
|
||||
void CommandPalette::SetTabs(const Collections::IObservableVector<TabBase>& tabs, const Collections::IObservableVector<TabBase>& mruTabs)
|
||||
void CommandPalette::SetTabs(const Collections::IObservableVector<Tab>& tabs, const Collections::IObservableVector<Tab>& mruTabs)
|
||||
{
|
||||
_bindTabs(tabs, _tabActions);
|
||||
_bindTabs(mruTabs, _mruTabActions);
|
||||
@ -1174,12 +1187,15 @@ namespace winrt::TerminalApp::implementation
|
||||
}
|
||||
else if (_currentMode == CommandPaletteMode::TabSearchMode || _currentMode == CommandPaletteMode::ActionMode || _currentMode == CommandPaletteMode::CommandlineMode)
|
||||
{
|
||||
auto pattern = std::make_shared<fzf::matcher::Pattern>(fzf::matcher::ParsePattern(searchText));
|
||||
|
||||
for (const auto& action : commandsToFilter)
|
||||
{
|
||||
// Update filter for all commands
|
||||
// This will modify the highlighting but will also lead to re-computation of weight (and consequently sorting).
|
||||
// Pay attention that it already updates the highlighting in the UI
|
||||
action.UpdateFilter(searchText);
|
||||
auto impl = winrt::get_self<implementation::FilteredCommand>(action);
|
||||
impl->UpdateFilter(pattern);
|
||||
|
||||
// if there is active search we skip commands with 0 weight
|
||||
if (searchText.empty() || action.Weight() > 0)
|
||||
|
||||
@ -31,7 +31,7 @@ namespace winrt::TerminalApp::implementation
|
||||
|
||||
Windows::Foundation::Collections::IObservableVector<winrt::TerminalApp::FilteredCommand> FilteredActions();
|
||||
|
||||
void SetTabs(const Windows::Foundation::Collections::IObservableVector<winrt::TerminalApp::TabBase>& tabs, const Windows::Foundation::Collections::IObservableVector<winrt::TerminalApp::TabBase>& mruTabs);
|
||||
void SetTabs(const Windows::Foundation::Collections::IObservableVector<winrt::TerminalApp::Tab>& tabs, const Windows::Foundation::Collections::IObservableVector<winrt::TerminalApp::Tab>& mruTabs);
|
||||
void SetActionMap(const Microsoft::Terminal::Settings::Model::IActionMapView& actionMap);
|
||||
|
||||
bool OnDirectKeyEvent(const uint32_t vkey, const uint8_t scanCode, const bool down);
|
||||
@ -48,7 +48,7 @@ namespace winrt::TerminalApp::implementation
|
||||
void EnableTabSearchMode();
|
||||
|
||||
til::property_changed_event PropertyChanged;
|
||||
til::typed_event<winrt::TerminalApp::CommandPalette, winrt::TerminalApp::TabBase> SwitchToTabRequested;
|
||||
til::typed_event<winrt::TerminalApp::CommandPalette, winrt::TerminalApp::Tab> SwitchToTabRequested;
|
||||
til::typed_event<winrt::TerminalApp::CommandPalette, winrt::hstring> CommandLineExecutionRequested;
|
||||
til::typed_event<winrt::TerminalApp::CommandPalette, Microsoft::Terminal::Settings::Model::Command> DispatchCommandRequested;
|
||||
til::typed_event<Windows::Foundation::IInspectable, Microsoft::Terminal::Settings::Model::Command> PreviewAction;
|
||||
@ -135,7 +135,7 @@ namespace winrt::TerminalApp::implementation
|
||||
Microsoft::Terminal::Settings::Model::TabSwitcherMode _tabSwitcherMode;
|
||||
uint32_t _switcherStartIdx;
|
||||
|
||||
void _bindTabs(const Windows::Foundation::Collections::IObservableVector<winrt::TerminalApp::TabBase>& source, const Windows::Foundation::Collections::IVector<winrt::TerminalApp::FilteredCommand>& target);
|
||||
void _bindTabs(const Windows::Foundation::Collections::IObservableVector<winrt::TerminalApp::Tab>& source, const Windows::Foundation::Collections::IVector<winrt::TerminalApp::FilteredCommand>& target);
|
||||
void _anchorKeyUpHandler();
|
||||
|
||||
winrt::Windows::UI::Xaml::Controls::ListView::SizeChanged_revoker _sizeChangedRevoker;
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import "TabBase.idl";
|
||||
import "Tab.idl";
|
||||
import "HighlightedTextControl.idl";
|
||||
import "FilteredCommand.idl";
|
||||
|
||||
@ -20,7 +20,7 @@ namespace TerminalApp
|
||||
|
||||
Windows.Foundation.Collections.IObservableVector<FilteredCommand> FilteredActions { get; };
|
||||
|
||||
void SetTabs(Windows.Foundation.Collections.IObservableVector<TabBase> tabs, Windows.Foundation.Collections.IObservableVector<TabBase> mruTabs);
|
||||
void SetTabs(Windows.Foundation.Collections.IObservableVector<Tab> tabs, Windows.Foundation.Collections.IObservableVector<Tab> mruTabs);
|
||||
|
||||
void SetActionMap(Microsoft.Terminal.Settings.Model.IActionMapView actionMap);
|
||||
|
||||
@ -30,7 +30,7 @@ namespace TerminalApp
|
||||
void EnableTabSwitcherMode(UInt32 startIdx, Microsoft.Terminal.Settings.Model.TabSwitcherMode tabSwitcherMode);
|
||||
void EnableTabSearchMode();
|
||||
|
||||
event Windows.Foundation.TypedEventHandler<CommandPalette, TabBase> SwitchToTabRequested;
|
||||
event Windows.Foundation.TypedEventHandler<CommandPalette, Tab> SwitchToTabRequested;
|
||||
event Windows.Foundation.TypedEventHandler<CommandPalette, Microsoft.Terminal.Settings.Model.Command> DispatchCommandRequested;
|
||||
event Windows.Foundation.TypedEventHandler<CommandPalette, String> CommandLineExecutionRequested;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Microsoft.Terminal.Settings.Model.Command> PreviewAction;
|
||||
|
||||
@ -44,6 +44,12 @@
|
||||
<Setter Property="BorderBrush" Value="{ThemeResource CardStrokeColorDefaultBrush}" />
|
||||
</Style>
|
||||
|
||||
<Style x:Key="SubtitleTextStyle"
|
||||
TargetType="TextBlock">
|
||||
<Setter Property="FontSize" Value="10" />
|
||||
<Setter Property="Foreground" Value="{ThemeResource SystemBaseMediumColor}" />
|
||||
</Style>
|
||||
|
||||
<DataTemplate x:Key="ListItemTemplate"
|
||||
x:DataType="local:FilteredCommand">
|
||||
<ListViewItem HorizontalContentAlignment="Stretch"
|
||||
@ -71,10 +77,19 @@
|
||||
Height="16"
|
||||
Content="{x:Bind Item.ResolvedIcon, Mode=OneWay}" />
|
||||
|
||||
<local:HighlightedTextControl Grid.Column="1"
|
||||
HorizontalAlignment="Left"
|
||||
Text="{x:Bind HighlightedName, Mode=OneWay}" />
|
||||
<StackPanel Grid.Column="1"
|
||||
HorizontalAlignment="Left"
|
||||
Orientation="Vertical">
|
||||
<local:HighlightedTextControl HorizontalAlignment="Left"
|
||||
HighlightedRuns="{x:Bind NameHighlights, Mode=OneWay}"
|
||||
Text="{x:Bind Item.Name, Mode=OneWay}" />
|
||||
<local:HighlightedTextControl HorizontalAlignment="Left"
|
||||
HighlightedRuns="{x:Bind SubtitleHighlights, Mode=OneWay}"
|
||||
Text="{x:Bind Item.Subtitle, Mode=OneWay}"
|
||||
TextBlockStyle="{StaticResource SubtitleTextStyle}"
|
||||
Visibility="{x:Bind HasSubtitle, Mode=OneWay}" />
|
||||
|
||||
</StackPanel>
|
||||
<!--
|
||||
The block for the key chord is only visible
|
||||
when there's actual text set as the label.
|
||||
@ -121,9 +136,19 @@
|
||||
Height="16"
|
||||
Content="{x:Bind Item.ResolvedIcon, Mode=OneWay}" />
|
||||
|
||||
<local:HighlightedTextControl Grid.Column="1"
|
||||
HorizontalAlignment="Left"
|
||||
Text="{x:Bind HighlightedName, Mode=OneWay}" />
|
||||
<StackPanel Grid.Column="1"
|
||||
HorizontalAlignment="Left"
|
||||
Orientation="Vertical">
|
||||
<local:HighlightedTextControl HorizontalAlignment="Left"
|
||||
HighlightedRuns="{x:Bind NameHighlights, Mode=OneWay}"
|
||||
Text="{x:Bind Item.Name, Mode=OneWay}" />
|
||||
<local:HighlightedTextControl HorizontalAlignment="Left"
|
||||
HighlightedRuns="{x:Bind SubtitleHighlights, Mode=OneWay}"
|
||||
Text="{x:Bind Item.Subtitle, Mode=OneWay}"
|
||||
TextBlockStyle="{StaticResource SubtitleTextStyle}"
|
||||
Visibility="{x:Bind HasSubtitle, Mode=OneWay}" />
|
||||
|
||||
</StackPanel>
|
||||
|
||||
<!--
|
||||
The block for the key chord is only visible
|
||||
@ -192,7 +217,8 @@
|
||||
|
||||
<local:HighlightedTextControl Grid.Column="1"
|
||||
HorizontalAlignment="Left"
|
||||
Text="{x:Bind HighlightedName, Mode=OneWay}" />
|
||||
HighlightedRuns="{x:Bind NameHighlights, Mode=OneWay}"
|
||||
Text="{x:Bind Item.Name, Mode=OneWay}" />
|
||||
|
||||
<StackPanel Grid.Column="2"
|
||||
HorizontalAlignment="Right"
|
||||
|
||||
@ -2,11 +2,11 @@
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#include "pch.h"
|
||||
#include "TabPaletteItem.h"
|
||||
#include "TerminalTab.h"
|
||||
#include "Tab.h"
|
||||
|
||||
#include <LibraryResources.h>
|
||||
|
||||
#include "TabPaletteItem.g.cpp"
|
||||
#include "CommandPaletteItems.h"
|
||||
|
||||
using namespace winrt;
|
||||
using namespace winrt::TerminalApp;
|
||||
@ -19,42 +19,31 @@ using namespace winrt::Microsoft::Terminal::Settings::Model;
|
||||
|
||||
namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
TabPaletteItem::TabPaletteItem(const winrt::TerminalApp::TabBase& tab) :
|
||||
_tab(tab)
|
||||
TabPaletteItem::TabPaletteItem(const winrt::TerminalApp::Tab& tab) :
|
||||
_tab{ tab }
|
||||
{
|
||||
Name(tab.Title());
|
||||
Icon(tab.Icon());
|
||||
|
||||
_tabChangedRevoker = tab.PropertyChanged(winrt::auto_revoke, [weakThis{ get_weak() }](auto& sender, auto& e) {
|
||||
auto item{ weakThis.get() };
|
||||
auto senderTab{ sender.try_as<winrt::TerminalApp::TabBase>() };
|
||||
|
||||
if (item && senderTab)
|
||||
_tabChangedRevoker = tab.PropertyChanged(winrt::auto_revoke, [=](auto& sender, auto& e) {
|
||||
if (auto senderTab{ sender.try_as<winrt::TerminalApp::Tab>() })
|
||||
{
|
||||
auto changedProperty = e.PropertyName();
|
||||
if (changedProperty == L"Title")
|
||||
{
|
||||
item->Name(senderTab.Title());
|
||||
BaseRaisePropertyChanged(L"Name");
|
||||
}
|
||||
else if (changedProperty == L"Icon")
|
||||
{
|
||||
item->Icon(senderTab.Icon());
|
||||
BaseRaisePropertyChanged(L"Icon");
|
||||
InvalidateResolvedIcon();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (const auto terminalTab{ tab.try_as<winrt::TerminalApp::TerminalTab>() })
|
||||
if (const auto status = tab.TabStatus())
|
||||
{
|
||||
const auto status = terminalTab.TabStatus();
|
||||
TabStatus(status);
|
||||
|
||||
_tabStatusChangedRevoker = status.PropertyChanged(winrt::auto_revoke, [weakThis{ get_weak() }](auto& /*sender*/, auto& /*e*/) {
|
||||
_tabStatusChangedRevoker = status.PropertyChanged(winrt::auto_revoke, [=](auto& /*sender*/, auto& /*e*/) {
|
||||
// Sometimes nested bindings do not get updated,
|
||||
// thus let's notify property changed on TabStatus when one of its properties changes
|
||||
if (auto item{ weakThis.get() })
|
||||
{
|
||||
item->PropertyChanged.raise(*item, Windows::UI::Xaml::Data::PropertyChangedEventArgs{ L"TabStatus" });
|
||||
}
|
||||
BaseRaisePropertyChanged(L"TabStatus");
|
||||
});
|
||||
}
|
||||
}
|
||||
159
src/cascadia/TerminalApp/CommandPaletteItems.h
Normal file
159
src/cascadia/TerminalApp/CommandPaletteItems.h
Normal file
@ -0,0 +1,159 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "BasePaletteItem.h"
|
||||
#include "TabPaletteItem.g.h"
|
||||
|
||||
#include "../inc/cppwinrt_utils.h"
|
||||
|
||||
namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
struct ActionPaletteItem :
|
||||
public winrt::implements<ActionPaletteItem, IPaletteItem, winrt::Windows::UI::Xaml::Data::INotifyPropertyChanged>,
|
||||
BasePaletteItem<ActionPaletteItem, winrt::TerminalApp::PaletteItemType::Action>
|
||||
{
|
||||
ActionPaletteItem(const Microsoft::Terminal::Settings::Model::Command& command, const winrt::hstring keyChordText) :
|
||||
_Command{ command }, _name{ command.Name() }, _keyChordText{ keyChordText }
|
||||
{
|
||||
static bool shouldShowSubtitles = [] {
|
||||
try
|
||||
{
|
||||
const auto context{ winrt::Windows::ApplicationModel::Resources::Core::ResourceContext::GetForViewIndependentUse() };
|
||||
const auto qualifiers{ context.QualifierValues() };
|
||||
if (const auto language{ qualifiers.TryLookup(L"language") })
|
||||
{
|
||||
return !til::starts_with_insensitive_ascii(*language, L"en-");
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
LOG_CAUGHT_EXCEPTION();
|
||||
}
|
||||
return false;
|
||||
}();
|
||||
|
||||
if (shouldShowSubtitles)
|
||||
{
|
||||
const auto subtitle = _Command.LanguageNeutralName();
|
||||
if (subtitle != _name)
|
||||
{
|
||||
_subtitle = std::move(subtitle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
winrt::hstring Name()
|
||||
{
|
||||
return _name;
|
||||
}
|
||||
|
||||
winrt::hstring Subtitle()
|
||||
{
|
||||
return _subtitle;
|
||||
}
|
||||
|
||||
winrt::hstring KeyChordText()
|
||||
{
|
||||
return _keyChordText;
|
||||
}
|
||||
|
||||
winrt::hstring Icon()
|
||||
{
|
||||
return _Command.Icon().Resolved();
|
||||
}
|
||||
|
||||
WINRT_PROPERTY(Microsoft::Terminal::Settings::Model::Command, Command, nullptr);
|
||||
|
||||
private:
|
||||
Windows::UI::Xaml::Data::INotifyPropertyChanged::PropertyChanged_revoker _commandChangedRevoker;
|
||||
winrt::hstring _name;
|
||||
winrt::hstring _subtitle;
|
||||
winrt::hstring _keyChordText;
|
||||
};
|
||||
|
||||
struct CommandLinePaletteItem :
|
||||
public winrt::implements<CommandLinePaletteItem, IPaletteItem, winrt::Windows::UI::Xaml::Data::INotifyPropertyChanged>,
|
||||
BasePaletteItem<CommandLinePaletteItem, winrt::TerminalApp::PaletteItemType::CommandLine>
|
||||
{
|
||||
CommandLinePaletteItem(const winrt::hstring& commandLine) :
|
||||
_CommandLine{ commandLine } {}
|
||||
|
||||
winrt::hstring Name()
|
||||
{
|
||||
return _CommandLine;
|
||||
}
|
||||
|
||||
winrt::hstring Subtitle()
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
winrt::hstring KeyChordText()
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
winrt::hstring Icon()
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
WINRT_PROPERTY(winrt::hstring, CommandLine);
|
||||
};
|
||||
|
||||
struct TabPaletteItem :
|
||||
public TabPaletteItemT<TabPaletteItem>,
|
||||
BasePaletteItem<TabPaletteItem, winrt::TerminalApp::PaletteItemType::Tab>
|
||||
{
|
||||
TabPaletteItem(const winrt::TerminalApp::Tab& tab);
|
||||
|
||||
winrt::TerminalApp::Tab Tab() const noexcept
|
||||
{
|
||||
return _tab.get();
|
||||
}
|
||||
|
||||
winrt::hstring Name()
|
||||
{
|
||||
if (auto tab = _tab.get())
|
||||
{
|
||||
return tab.Title();
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
winrt::hstring Subtitle()
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
winrt::hstring KeyChordText()
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
winrt::hstring Icon()
|
||||
{
|
||||
if (auto tab = _tab.get())
|
||||
{
|
||||
return tab.Icon();
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
winrt::TerminalApp::TerminalTabStatus TabStatus()
|
||||
{
|
||||
if (auto tab = _tab.get())
|
||||
{
|
||||
return tab.TabStatus();
|
||||
}
|
||||
return { nullptr };
|
||||
}
|
||||
|
||||
private:
|
||||
winrt::weak_ref<winrt::TerminalApp::Tab> _tab;
|
||||
Windows::UI::Xaml::Data::INotifyPropertyChanged::PropertyChanged_revoker _tabChangedRevoker;
|
||||
Windows::UI::Xaml::Data::INotifyPropertyChanged::PropertyChanged_revoker _tabStatusChangedRevoker;
|
||||
};
|
||||
}
|
||||
@ -3,8 +3,8 @@
|
||||
|
||||
#include "pch.h"
|
||||
#include "CommandPalette.h"
|
||||
#include "HighlightedText.h"
|
||||
#include <LibraryResources.h>
|
||||
#include "fzf/fzf.h"
|
||||
|
||||
#include "FilteredCommand.g.cpp"
|
||||
|
||||
@ -19,213 +19,96 @@ using namespace winrt::Microsoft::Terminal::Settings::Model;
|
||||
|
||||
namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
// This class is a wrapper of PaletteItem, that is used as an item of a filterable list in CommandPalette.
|
||||
// This class is a wrapper of IPaletteItem, that is used as an item of a filterable list in CommandPalette.
|
||||
// It manages a highlighted text that is computed by matching search filter characters to item name
|
||||
FilteredCommand::FilteredCommand(const winrt::TerminalApp::PaletteItem& item)
|
||||
FilteredCommand::FilteredCommand(const winrt::TerminalApp::IPaletteItem& item) :
|
||||
_Item{ item }, _Weight{ 0 }
|
||||
{
|
||||
// Actually implement the ctor in _constructFilteredCommand
|
||||
_constructFilteredCommand(item);
|
||||
}
|
||||
|
||||
// We need to actually implement the ctor in a separate helper. This is
|
||||
// because we have a FilteredTask class which derives from FilteredCommand.
|
||||
// HOWEVER, for cppwinrt ~ r e a s o n s ~, it doesn't actually derive from
|
||||
// FilteredCommand directly, so we can't just use the FilteredCommand ctor
|
||||
// directly in the base class.
|
||||
void FilteredCommand::_constructFilteredCommand(const winrt::TerminalApp::PaletteItem& item)
|
||||
{
|
||||
_Item = item;
|
||||
_Filter = L"";
|
||||
_Weight = 0;
|
||||
_HighlightedName = _computeHighlightedName();
|
||||
|
||||
// Recompute the highlighted name if the item name changes
|
||||
_itemChangedRevoker = _Item.PropertyChanged(winrt::auto_revoke, [weakThis{ get_weak() }](auto& /*sender*/, auto& e) {
|
||||
auto filteredCommand{ weakThis.get() };
|
||||
if (filteredCommand && e.PropertyName() == L"Name")
|
||||
// Our Item will not change, so we don't need to update the revoker if it does.
|
||||
_itemChangedRevoker = _Item.as<winrt::Windows::UI::Xaml::Data::INotifyPropertyChanged>().PropertyChanged(winrt::auto_revoke, [=](auto& /*sender*/, auto& e) {
|
||||
const auto property{ e.PropertyName() };
|
||||
if (property == L"Name")
|
||||
{
|
||||
filteredCommand->HighlightedName(filteredCommand->_computeHighlightedName());
|
||||
filteredCommand->Weight(filteredCommand->_computeWeight());
|
||||
_update();
|
||||
}
|
||||
else if (property == L"Subtitle")
|
||||
{
|
||||
_update();
|
||||
PropertyChanged.raise(*this, winrt::Windows::UI::Xaml::Data::PropertyChangedEventArgs{ L"HasSubtitle" });
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void FilteredCommand::UpdateFilter(const winrt::hstring& filter)
|
||||
void FilteredCommand::UpdateFilter(std::shared_ptr<fzf::matcher::Pattern> pattern)
|
||||
{
|
||||
// If the filter was not changed we want to prevent the re-computation of matching
|
||||
// that might result in triggering a notification event
|
||||
if (filter != _Filter)
|
||||
if (pattern != _pattern)
|
||||
{
|
||||
Filter(filter);
|
||||
HighlightedName(_computeHighlightedName());
|
||||
Weight(_computeWeight());
|
||||
_pattern = pattern;
|
||||
_update();
|
||||
}
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Looks up the filter characters within the item name.
|
||||
// Iterating through the filter and the item name it tries to associate the next filter character
|
||||
// with the first appearance of this character in the item name suffix.
|
||||
//
|
||||
// E.g., for filter="c l t s" and name="close all tabs after this", the match will be "CLose TabS after this".
|
||||
//
|
||||
// The item name is then split into segments (groupings of matched and non matched characters).
|
||||
//
|
||||
// E.g., the segments were the example above will be "CL", "ose ", "T", "ab", "S", "after this".
|
||||
//
|
||||
// The segments matching the filter characters are marked as highlighted.
|
||||
//
|
||||
// E.g., ("CL", true) ("ose ", false), ("T", true), ("ab", false), ("S", true), ("after this", false)
|
||||
//
|
||||
// TODO: we probably need to merge this logic with _getWeight computation?
|
||||
//
|
||||
// Return Value:
|
||||
// - The HighlightedText object initialized with the segments computed according to the algorithm above.
|
||||
winrt::TerminalApp::HighlightedText FilteredCommand::_computeHighlightedName()
|
||||
bool FilteredCommand::HasSubtitle()
|
||||
{
|
||||
const auto segments = winrt::single_threaded_observable_vector<winrt::TerminalApp::HighlightedTextSegment>();
|
||||
auto commandName = _Item.Name();
|
||||
auto isProcessingMatchedSegment = false;
|
||||
uint32_t nextOffsetToReport = 0;
|
||||
uint32_t currentOffset = 0;
|
||||
|
||||
for (const auto searchChar : _Filter)
|
||||
{
|
||||
const WCHAR searchCharAsString[] = { searchChar, L'\0' };
|
||||
while (true)
|
||||
{
|
||||
if (currentOffset == commandName.size())
|
||||
{
|
||||
// There are still unmatched filter characters but we finished scanning the name.
|
||||
// In this case we return the entire item name as unmatched
|
||||
auto entireNameSegment{ winrt::make<HighlightedTextSegment>(commandName, false) };
|
||||
segments.Clear();
|
||||
segments.Append(entireNameSegment);
|
||||
return winrt::make<HighlightedText>(segments);
|
||||
}
|
||||
|
||||
// GH#9941: search should be locale-aware as well
|
||||
// We use the same comparison method as upon sorting to guarantee consistent behavior
|
||||
const WCHAR currentCharAsString[] = { commandName[currentOffset], L'\0' };
|
||||
auto isCurrentCharMatched = lstrcmpi(searchCharAsString, currentCharAsString) == 0;
|
||||
if (isProcessingMatchedSegment != isCurrentCharMatched)
|
||||
{
|
||||
// We reached the end of the region (matched character came after a series of unmatched or vice versa).
|
||||
// Conclude the segment and add it to the list.
|
||||
// Skip segment if it is empty (might happen when the first character of the name is matched)
|
||||
auto sizeToReport = currentOffset - nextOffsetToReport;
|
||||
if (sizeToReport > 0)
|
||||
{
|
||||
winrt::hstring segment{ commandName.data() + nextOffsetToReport, sizeToReport };
|
||||
auto highlightedSegment{ winrt::make<HighlightedTextSegment>(segment, isProcessingMatchedSegment) };
|
||||
segments.Append(highlightedSegment);
|
||||
nextOffsetToReport = currentOffset;
|
||||
}
|
||||
isProcessingMatchedSegment = isCurrentCharMatched;
|
||||
}
|
||||
|
||||
currentOffset++;
|
||||
|
||||
if (isCurrentCharMatched)
|
||||
{
|
||||
// We have matched this filter character, let's move to matching the next filter char
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Either the filter or the item name were fully processed.
|
||||
// If we were in the middle of the matched segment - add it.
|
||||
if (isProcessingMatchedSegment)
|
||||
{
|
||||
auto sizeToReport = currentOffset - nextOffsetToReport;
|
||||
if (sizeToReport > 0)
|
||||
{
|
||||
winrt::hstring segment{ commandName.data() + nextOffsetToReport, sizeToReport };
|
||||
auto highlightedSegment{ winrt::make<HighlightedTextSegment>(segment, true) };
|
||||
segments.Append(highlightedSegment);
|
||||
nextOffsetToReport = currentOffset;
|
||||
}
|
||||
}
|
||||
|
||||
// Now create a segment for all remaining characters.
|
||||
// We will have remaining characters as long as the filter is shorter than the item name.
|
||||
auto sizeToReport = commandName.size() - nextOffsetToReport;
|
||||
if (sizeToReport > 0)
|
||||
{
|
||||
winrt::hstring segment{ commandName.data() + nextOffsetToReport, sizeToReport };
|
||||
auto highlightedSegment{ winrt::make<HighlightedTextSegment>(segment, false) };
|
||||
segments.Append(highlightedSegment);
|
||||
}
|
||||
|
||||
return winrt::make<HighlightedText>(segments);
|
||||
return !_Item.Subtitle().empty();
|
||||
}
|
||||
|
||||
// Function Description:
|
||||
// - Calculates a "weighting" by which should be used to order a item
|
||||
// name relative to other names, given a specific search string.
|
||||
// Currently, this is based off of two factors:
|
||||
// * The weight is incremented once for each matched character of the
|
||||
// search text.
|
||||
// * If a matching character from the search text was found at the start
|
||||
// of a word in the name, then we increment the weight again.
|
||||
// * For example, for a search string "sp", we want "Split Pane" to
|
||||
// appear in the list before "Close Pane"
|
||||
// * Consecutive matches will be weighted higher than matches with
|
||||
// characters in between the search characters.
|
||||
// - This will return 0 if the item should not be shown. If all the
|
||||
// characters of search text appear in order in `name`, then this function
|
||||
// will return a positive number. There can be any number of characters
|
||||
// separating consecutive characters in searchText.
|
||||
// * For example:
|
||||
// "name": "New Tab"
|
||||
// "name": "Close Tab"
|
||||
// "name": "Close Pane"
|
||||
// "name": "[-] Split Horizontal"
|
||||
// "name": "[ | ] Split Vertical"
|
||||
// "name": "Next Tab"
|
||||
// "name": "Prev Tab"
|
||||
// "name": "Open Settings"
|
||||
// "name": "Open Media Controls"
|
||||
// * "open" should return both "**Open** Settings" and "**Open** Media Controls".
|
||||
// * "Tab" would return "New **Tab**", "Close **Tab**", "Next **Tab**" and "Prev
|
||||
// **Tab**".
|
||||
// * "P" would return "Close **P**ane", "[-] S**p**lit Horizontal", "[ | ]
|
||||
// S**p**lit Vertical", "**P**rev Tab", "O**p**en Settings" and "O**p**en Media
|
||||
// Controls".
|
||||
// * "sv" would return "[ | ] Split Vertical" (by matching the **S** in
|
||||
// "Split", then the **V** in "Vertical").
|
||||
// Arguments:
|
||||
// - searchText: the string of text to search for in `name`
|
||||
// - name: the name to check
|
||||
// Return Value:
|
||||
// - the relative weight of this match
|
||||
int FilteredCommand::_computeWeight()
|
||||
static std::tuple<std::vector<winrt::TerminalApp::HighlightedRun>, int32_t> _matchedSegmentsAndWeight(const std::shared_ptr<fzf::matcher::Pattern>& pattern, const winrt::hstring& haystack)
|
||||
{
|
||||
auto result = 0;
|
||||
auto isNextSegmentWordBeginning = true;
|
||||
std::vector<winrt::TerminalApp::HighlightedRun> segments;
|
||||
int32_t weight = 0;
|
||||
|
||||
for (const auto& segment : _HighlightedName.Segments())
|
||||
if (pattern && !pattern->terms.empty())
|
||||
{
|
||||
const auto& segmentText = segment.TextSegment();
|
||||
const auto segmentSize = segmentText.size();
|
||||
|
||||
if (segment.IsHighlighted())
|
||||
if (auto match = fzf::matcher::Match(haystack, *pattern.get()); match)
|
||||
{
|
||||
// Give extra point for each consecutive match
|
||||
result += (segmentSize <= 1) ? segmentSize : 1 + 2 * (segmentSize - 1);
|
||||
|
||||
// Give extra point if this segment is at the beginning of a word
|
||||
if (isNextSegmentWordBeginning)
|
||||
{
|
||||
result++;
|
||||
}
|
||||
auto& matchResult = *match;
|
||||
weight = matchResult.Score;
|
||||
segments.resize(matchResult.Runs.size());
|
||||
std::transform(matchResult.Runs.begin(), matchResult.Runs.end(), segments.begin(), [](auto&& run) -> winrt::TerminalApp::HighlightedRun {
|
||||
return { run.Start, run.End };
|
||||
});
|
||||
}
|
||||
}
|
||||
return { std::move(segments), weight };
|
||||
}
|
||||
|
||||
isNextSegmentWordBeginning = segmentSize > 0 && segmentText[segmentSize - 1] == L' ';
|
||||
void FilteredCommand::_update()
|
||||
{
|
||||
auto itemName = _Item.Name();
|
||||
auto [segments, weight] = _matchedSegmentsAndWeight(_pattern, itemName);
|
||||
decltype(segments) subtitleSegments;
|
||||
|
||||
if (HasSubtitle())
|
||||
{
|
||||
auto itemSubtitle = _Item.Subtitle();
|
||||
int32_t subtitleWeight = 0;
|
||||
std::tie(subtitleSegments, subtitleWeight) = _matchedSegmentsAndWeight(_pattern, itemSubtitle);
|
||||
weight = std::max(weight, subtitleWeight);
|
||||
}
|
||||
|
||||
return result;
|
||||
if (segments.empty())
|
||||
{
|
||||
NameHighlights(nullptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
NameHighlights(winrt::single_threaded_vector(std::move(segments)));
|
||||
}
|
||||
|
||||
if (subtitleSegments.empty())
|
||||
{
|
||||
SubtitleHighlights(nullptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
SubtitleHighlights(winrt::single_threaded_vector(std::move(subtitleSegments)));
|
||||
}
|
||||
|
||||
Weight(weight);
|
||||
}
|
||||
|
||||
// Function Description:
|
||||
@ -243,9 +126,9 @@ namespace winrt::TerminalApp::implementation
|
||||
|
||||
if (firstWeight == secondWeight)
|
||||
{
|
||||
std::wstring_view firstName{ first.Item().Name() };
|
||||
std::wstring_view secondName{ second.Item().Name() };
|
||||
return lstrcmpi(firstName.data(), secondName.data()) < 0;
|
||||
const auto firstName = first.Item().Name();
|
||||
const auto secondName = second.Item().Name();
|
||||
return til::compare_linguistic_insensitive(firstName, secondName) < 0;
|
||||
}
|
||||
|
||||
return firstWeight > secondWeight;
|
||||
|
||||
@ -5,6 +5,7 @@
|
||||
|
||||
#include "HighlightedTextControl.h"
|
||||
#include "FilteredCommand.g.h"
|
||||
#include "fzf/fzf.h"
|
||||
|
||||
// fwdecl unittest classes
|
||||
namespace TerminalAppLocalTests
|
||||
@ -17,24 +18,23 @@ namespace winrt::TerminalApp::implementation
|
||||
struct FilteredCommand : FilteredCommandT<FilteredCommand>
|
||||
{
|
||||
FilteredCommand() = default;
|
||||
FilteredCommand(const winrt::TerminalApp::PaletteItem& item);
|
||||
FilteredCommand(const winrt::TerminalApp::IPaletteItem& item);
|
||||
|
||||
virtual void UpdateFilter(const winrt::hstring& filter);
|
||||
void UpdateFilter(std::shared_ptr<fzf::matcher::Pattern> pattern);
|
||||
|
||||
static int Compare(const winrt::TerminalApp::FilteredCommand& first, const winrt::TerminalApp::FilteredCommand& second);
|
||||
|
||||
bool HasSubtitle();
|
||||
|
||||
til::property_changed_event PropertyChanged;
|
||||
WINRT_OBSERVABLE_PROPERTY(winrt::TerminalApp::PaletteItem, Item, PropertyChanged.raise, nullptr);
|
||||
WINRT_OBSERVABLE_PROPERTY(winrt::hstring, Filter, PropertyChanged.raise);
|
||||
WINRT_OBSERVABLE_PROPERTY(winrt::TerminalApp::HighlightedText, HighlightedName, PropertyChanged.raise);
|
||||
WINRT_OBSERVABLE_PROPERTY(winrt::TerminalApp::IPaletteItem, Item, PropertyChanged.raise, nullptr);
|
||||
WINRT_OBSERVABLE_PROPERTY(winrt::Windows::Foundation::Collections::IVector<winrt::TerminalApp::HighlightedRun>, NameHighlights, PropertyChanged.raise);
|
||||
WINRT_OBSERVABLE_PROPERTY(winrt::Windows::Foundation::Collections::IVector<winrt::TerminalApp::HighlightedRun>, SubtitleHighlights, PropertyChanged.raise);
|
||||
WINRT_OBSERVABLE_PROPERTY(int, Weight, PropertyChanged.raise);
|
||||
|
||||
protected:
|
||||
void _constructFilteredCommand(const winrt::TerminalApp::PaletteItem& item);
|
||||
|
||||
private:
|
||||
winrt::TerminalApp::HighlightedText _computeHighlightedName();
|
||||
int _computeWeight();
|
||||
std::shared_ptr<fzf::matcher::Pattern> _pattern;
|
||||
void _update();
|
||||
Windows::UI::Xaml::Data::INotifyPropertyChanged::PropertyChanged_revoker _itemChangedRevoker;
|
||||
|
||||
friend class TerminalAppLocalTests::FilteredCommandTests;
|
||||
|
||||
@ -1,21 +1,20 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import "PaletteItem.idl";
|
||||
import "IPaletteItem.idl";
|
||||
import "HighlightedTextControl.idl";
|
||||
|
||||
namespace TerminalApp
|
||||
{
|
||||
[default_interface] unsealed runtimeclass FilteredCommand : Windows.UI.Xaml.Data.INotifyPropertyChanged
|
||||
runtimeclass FilteredCommand : Windows.UI.Xaml.Data.INotifyPropertyChanged
|
||||
{
|
||||
FilteredCommand();
|
||||
FilteredCommand(PaletteItem item);
|
||||
FilteredCommand(IPaletteItem item);
|
||||
|
||||
PaletteItem Item { get; };
|
||||
String Filter;
|
||||
HighlightedText HighlightedName { get; };
|
||||
IPaletteItem Item { get; };
|
||||
IVector<HighlightedRun> NameHighlights { get; };
|
||||
IVector<HighlightedRun> SubtitleHighlights { get; };
|
||||
Boolean HasSubtitle { get; };
|
||||
Int32 Weight;
|
||||
|
||||
void UpdateFilter(String filter);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,31 +0,0 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#include "pch.h"
|
||||
#include "HighlightedText.h"
|
||||
#include "HighlightedTextSegment.g.cpp"
|
||||
#include "HighlightedText.g.cpp"
|
||||
|
||||
using namespace winrt;
|
||||
using namespace winrt::TerminalApp;
|
||||
using namespace winrt::Windows::UI::Core;
|
||||
using namespace winrt::Windows::UI::Xaml;
|
||||
using namespace winrt::Windows::System;
|
||||
using namespace winrt::Windows::UI::Text;
|
||||
using namespace winrt::Windows::Foundation;
|
||||
using namespace winrt::Windows::Foundation::Collections;
|
||||
using namespace winrt::Microsoft::Terminal::Settings::Model;
|
||||
|
||||
namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
HighlightedTextSegment::HighlightedTextSegment(const winrt::hstring& textSegment, bool isHighlighted) :
|
||||
_TextSegment(textSegment),
|
||||
_IsHighlighted(isHighlighted)
|
||||
{
|
||||
}
|
||||
|
||||
HighlightedText::HighlightedText(const Windows::Foundation::Collections::IObservableVector<winrt::TerminalApp::HighlightedTextSegment>& segments) :
|
||||
_Segments(segments)
|
||||
{
|
||||
}
|
||||
}
|
||||
@ -1,35 +0,0 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "HighlightedTextSegment.g.h"
|
||||
#include "HighlightedText.g.h"
|
||||
|
||||
namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
struct HighlightedTextSegment : HighlightedTextSegmentT<HighlightedTextSegment>
|
||||
{
|
||||
HighlightedTextSegment() = default;
|
||||
HighlightedTextSegment(const winrt::hstring& text, bool isHighlighted);
|
||||
|
||||
til::property_changed_event PropertyChanged;
|
||||
WINRT_OBSERVABLE_PROPERTY(winrt::hstring, TextSegment, PropertyChanged.raise);
|
||||
WINRT_OBSERVABLE_PROPERTY(bool, IsHighlighted, PropertyChanged.raise);
|
||||
};
|
||||
|
||||
struct HighlightedText : HighlightedTextT<HighlightedText>
|
||||
{
|
||||
HighlightedText() = default;
|
||||
HighlightedText(const Windows::Foundation::Collections::IObservableVector<winrt::TerminalApp::HighlightedTextSegment>& segments);
|
||||
|
||||
til::property_changed_event PropertyChanged;
|
||||
WINRT_OBSERVABLE_PROPERTY(Windows::Foundation::Collections::IObservableVector<winrt::TerminalApp::HighlightedTextSegment>, Segments, PropertyChanged.raise);
|
||||
};
|
||||
}
|
||||
|
||||
namespace winrt::TerminalApp::factory_implementation
|
||||
{
|
||||
BASIC_FACTORY(HighlightedTextSegment);
|
||||
BASIC_FACTORY(HighlightedText);
|
||||
}
|
||||
@ -1,22 +0,0 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
namespace TerminalApp
|
||||
{
|
||||
[default_interface] runtimeclass HighlightedTextSegment : Windows.UI.Xaml.Data.INotifyPropertyChanged
|
||||
{
|
||||
HighlightedTextSegment();
|
||||
HighlightedTextSegment(String text, Boolean isMatched);
|
||||
|
||||
String TextSegment { get; };
|
||||
Boolean IsHighlighted { get; };
|
||||
}
|
||||
|
||||
[default_interface] runtimeclass HighlightedText : Windows.UI.Xaml.Data.INotifyPropertyChanged
|
||||
{
|
||||
HighlightedText();
|
||||
HighlightedText(Windows.Foundation.Collections.IObservableVector<HighlightedTextSegment> segments);
|
||||
|
||||
Windows.Foundation.Collections.IObservableVector<HighlightedTextSegment> Segments;
|
||||
}
|
||||
}
|
||||
@ -22,70 +22,152 @@ namespace winrt::TerminalApp::implementation
|
||||
// Our control exposes a "Text" property to be used with Data Binding
|
||||
// To allow this we need to register a Dependency Property Identifier to be used by the property system
|
||||
// (https://docs.microsoft.com/en-us/windows/uwp/xaml-platform/custom-dependency-properties)
|
||||
DependencyProperty HighlightedTextControl::_textProperty = DependencyProperty::Register(
|
||||
L"Text",
|
||||
xaml_typename<winrt::TerminalApp::HighlightedText>(),
|
||||
xaml_typename<winrt::TerminalApp::HighlightedTextControl>(),
|
||||
PropertyMetadata(nullptr, HighlightedTextControl::_onTextChanged));
|
||||
DependencyProperty HighlightedTextControl::_TextProperty{ nullptr };
|
||||
DependencyProperty HighlightedTextControl::_HighlightedRunsProperty{ nullptr };
|
||||
DependencyProperty HighlightedTextControl::_TextBlockStyleProperty{ nullptr };
|
||||
DependencyProperty HighlightedTextControl::_HighlightedRunStyleProperty{ nullptr };
|
||||
|
||||
HighlightedTextControl::HighlightedTextControl()
|
||||
{
|
||||
InitializeComponent();
|
||||
_InitializeProperties();
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Returns the Identifier of the "Text" dependency property
|
||||
DependencyProperty HighlightedTextControl::TextProperty()
|
||||
void HighlightedTextControl::_InitializeProperties()
|
||||
{
|
||||
return _textProperty;
|
||||
static auto [[maybe_unused]] registered = [] {
|
||||
_TextProperty = DependencyProperty::Register(
|
||||
L"Text",
|
||||
xaml_typename<winrt::hstring>(),
|
||||
xaml_typename<winrt::TerminalApp::HighlightedTextControl>(),
|
||||
PropertyMetadata(nullptr, HighlightedTextControl::_onPropertyChanged));
|
||||
|
||||
_HighlightedRunsProperty = DependencyProperty::Register(
|
||||
L"HighlightedRuns",
|
||||
xaml_typename<winrt::Windows::Foundation::Collections::IVector<winrt::TerminalApp::HighlightedRun>>(),
|
||||
xaml_typename<winrt::TerminalApp::HighlightedTextControl>(),
|
||||
PropertyMetadata(nullptr, HighlightedTextControl::_onPropertyChanged));
|
||||
|
||||
_TextBlockStyleProperty = DependencyProperty::Register(
|
||||
L"TextBlockStyle",
|
||||
xaml_typename<winrt::Windows::UI::Xaml::Style>(),
|
||||
xaml_typename<winrt::TerminalApp::HighlightedTextControl>(),
|
||||
PropertyMetadata{ nullptr });
|
||||
|
||||
_HighlightedRunStyleProperty = DependencyProperty::Register(
|
||||
L"HighlightedRunStyle",
|
||||
xaml_typename<winrt::Windows::UI::Xaml::Style>(),
|
||||
xaml_typename<winrt::TerminalApp::HighlightedTextControl>(),
|
||||
PropertyMetadata(nullptr, HighlightedTextControl::_onPropertyChanged));
|
||||
|
||||
return true;
|
||||
}();
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Returns the TextBlock view used to render the highlighted text
|
||||
// Can be used when the Text property change is triggered by the event system to update the view
|
||||
// We need to expose it rather than simply bind a data source because we update the runs in code-behind
|
||||
Controls::TextBlock HighlightedTextControl::TextView()
|
||||
{
|
||||
return _textView();
|
||||
}
|
||||
|
||||
winrt::TerminalApp::HighlightedText HighlightedTextControl::Text()
|
||||
{
|
||||
return winrt::unbox_value<winrt::TerminalApp::HighlightedText>(GetValue(_textProperty));
|
||||
}
|
||||
|
||||
void HighlightedTextControl::Text(const winrt::TerminalApp::HighlightedText& value)
|
||||
{
|
||||
SetValue(_textProperty, winrt::box_value(value));
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - This callback is triggered when the Text property is changed. Responsible for updating the view
|
||||
// Arguments:
|
||||
// - o - dependency object that was modified, expected to be an instance of this control
|
||||
// - e - event arguments of the property changed event fired by the event system upon Text property change.
|
||||
// The new value is expected to be an instance of HighlightedText
|
||||
void HighlightedTextControl::_onTextChanged(const DependencyObject& o, const DependencyPropertyChangedEventArgs& e)
|
||||
void HighlightedTextControl::_onPropertyChanged(const DependencyObject& o, const DependencyPropertyChangedEventArgs& /*e*/)
|
||||
{
|
||||
const auto control = o.try_as<winrt::TerminalApp::HighlightedTextControl>();
|
||||
const auto highlightedText = e.NewValue().try_as<winrt::TerminalApp::HighlightedText>();
|
||||
|
||||
if (control && highlightedText)
|
||||
if (control)
|
||||
{
|
||||
// Replace all the runs on the TextBlock
|
||||
// Use IsHighlighted to decide if the run should be highlighted.
|
||||
// To do - export the highlighting style into XAML
|
||||
const auto inlinesCollection = control.TextView().Inlines();
|
||||
inlinesCollection.Clear();
|
||||
winrt::get_self<HighlightedTextControl>(control)->_updateTextAndStyle();
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto& match : highlightedText.Segments())
|
||||
void HighlightedTextControl::OnApplyTemplate()
|
||||
{
|
||||
_updateTextAndStyle();
|
||||
}
|
||||
|
||||
static void _applyStyleToObject(const winrt::Windows::UI::Xaml::Style& style, const winrt::Windows::UI::Xaml::DependencyObject& object)
|
||||
{
|
||||
if (!style)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static const auto fontWeightProperty{ winrt::Windows::UI::Xaml::Documents::TextElement::FontWeightProperty() };
|
||||
|
||||
const auto setters{ style.Setters() };
|
||||
for (auto&& setterBase : setters)
|
||||
{
|
||||
const auto setter = setterBase.as<winrt::Windows::UI::Xaml::Setter>();
|
||||
const auto property = setter.Property();
|
||||
auto value = setter.Value();
|
||||
|
||||
if (property == fontWeightProperty) [[unlikely]]
|
||||
{
|
||||
const auto matchText = match.TextSegment();
|
||||
const auto fontWeight = match.IsHighlighted() ? FontWeights::Bold() : FontWeights::Normal();
|
||||
// BODGY - The XAML compiler emits a boxed int32, but the dependency property
|
||||
// here expects a boxed FontWeight (which also requires a u16. heh.)
|
||||
// FontWeight is one of the few properties that is broken like this, and on Run it's the
|
||||
// only one... so we can trivially check this case.
|
||||
const auto weight{ winrt::unbox_value_or<int32_t>(value, static_cast<int32_t>(400)) };
|
||||
value = winrt::box_value(winrt::Windows::UI::Text::FontWeight{ static_cast<uint16_t>(weight) });
|
||||
}
|
||||
|
||||
object.SetValue(property, value);
|
||||
}
|
||||
}
|
||||
|
||||
void HighlightedTextControl::_updateTextAndStyle()
|
||||
{
|
||||
const auto textBlock = GetTemplateChild(L"TextView").try_as<winrt::Windows::UI::Xaml::Controls::TextBlock>();
|
||||
if (!textBlock)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const auto text = Text();
|
||||
const auto runs = HighlightedRuns();
|
||||
|
||||
const auto inlinesCollection = textBlock.Inlines();
|
||||
inlinesCollection.Clear();
|
||||
|
||||
// The code below constructs local hstring instances because hstring is required to be null-terminated
|
||||
// and slicing _does not_ guarantee null termination. Passing a sliced wstring_view directly into run.Text()
|
||||
// (which is a winrt::param::hstring--different thing!--will result in an exception when the sliced portion
|
||||
// is not null-terminated.
|
||||
if (!text.empty())
|
||||
{
|
||||
size_t lastPos = 0;
|
||||
if (runs && runs.Size())
|
||||
{
|
||||
const auto runStyle = HighlightedRunStyle();
|
||||
|
||||
for (const auto& [start, end] : runs)
|
||||
{
|
||||
if (start > lastPos)
|
||||
{
|
||||
const hstring nonMatch{ til::safe_slice_abs(text, lastPos, static_cast<size_t>(start)) };
|
||||
Documents::Run run;
|
||||
run.Text(nonMatch);
|
||||
inlinesCollection.Append(run);
|
||||
}
|
||||
|
||||
const hstring matchSeg{ til::safe_slice_abs(text, static_cast<size_t>(start), static_cast<size_t>(end + 1)) };
|
||||
Documents::Run run;
|
||||
run.Text(matchSeg);
|
||||
|
||||
if (runStyle) [[unlikely]]
|
||||
{
|
||||
_applyStyleToObject(runStyle, run);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Default style: bold
|
||||
run.FontWeight(FontWeights::Bold());
|
||||
}
|
||||
inlinesCollection.Append(run);
|
||||
|
||||
lastPos = static_cast<size_t>(end + 1);
|
||||
}
|
||||
}
|
||||
|
||||
// This will also be true if there are no runs at all
|
||||
if (lastPos < text.size())
|
||||
{
|
||||
// checking lastPos here prevents a needless deep copy of the whole text in the no-match case
|
||||
const hstring tail{ lastPos == 0 ? text : hstring{ til::safe_slice_abs(text, lastPos, SIZE_T_MAX) } };
|
||||
Documents::Run run;
|
||||
run.Text(matchText);
|
||||
run.FontWeight(fontWeight);
|
||||
run.Text(tail);
|
||||
inlinesCollection.Append(run);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,8 +3,6 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "winrt/Microsoft.UI.Xaml.Controls.h"
|
||||
|
||||
#include "HighlightedTextControl.g.h"
|
||||
|
||||
namespace winrt::TerminalApp::implementation
|
||||
@ -13,16 +11,17 @@ namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
HighlightedTextControl();
|
||||
|
||||
static Windows::UI::Xaml::DependencyProperty TextProperty();
|
||||
void OnApplyTemplate();
|
||||
|
||||
winrt::TerminalApp::HighlightedText Text();
|
||||
void Text(const winrt::TerminalApp::HighlightedText& value);
|
||||
|
||||
Windows::UI::Xaml::Controls::TextBlock TextView();
|
||||
DEPENDENCY_PROPERTY(winrt::hstring, Text);
|
||||
DEPENDENCY_PROPERTY(winrt::Windows::Foundation::Collections::IVector<winrt::TerminalApp::HighlightedRun>, HighlightedRuns);
|
||||
DEPENDENCY_PROPERTY(winrt::Windows::UI::Xaml::Style, TextBlockStyle);
|
||||
DEPENDENCY_PROPERTY(winrt::Windows::UI::Xaml::Style, HighlightedRunStyle);
|
||||
|
||||
private:
|
||||
static Windows::UI::Xaml::DependencyProperty _textProperty;
|
||||
static void _onTextChanged(const Windows::UI::Xaml::DependencyObject& o, const Windows::UI::Xaml::DependencyPropertyChangedEventArgs& e);
|
||||
static void _InitializeProperties();
|
||||
static void _onPropertyChanged(const Windows::UI::Xaml::DependencyObject& o, const Windows::UI::Xaml::DependencyPropertyChangedEventArgs& e);
|
||||
void _updateTextAndStyle();
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -1,15 +1,28 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import "HighlightedText.idl";
|
||||
|
||||
namespace TerminalApp
|
||||
{
|
||||
struct HighlightedRun
|
||||
{
|
||||
UInt64 Start;
|
||||
UInt64 End;
|
||||
};
|
||||
|
||||
[default_interface] runtimeclass HighlightedTextControl : Windows.UI.Xaml.Controls.Control
|
||||
{
|
||||
HighlightedTextControl();
|
||||
|
||||
String Text;
|
||||
Windows.UI.Xaml.DependencyProperty TextProperty { get; };
|
||||
HighlightedText Text;
|
||||
Windows.UI.Xaml.Controls.TextBlock TextView { get; };
|
||||
|
||||
IVector<HighlightedRun> HighlightedRuns;
|
||||
Windows.UI.Xaml.DependencyProperty HighlightedRunsProperty { get; };
|
||||
|
||||
Windows.UI.Xaml.Style TextBlockStyle;
|
||||
Windows.UI.Xaml.DependencyProperty TextBlockStyleProperty { get; };
|
||||
|
||||
Windows.UI.Xaml.Style HighlightedRunStyle;
|
||||
Windows.UI.Xaml.DependencyProperty HighlightedRunStyleProperty { get; };
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,11 +0,0 @@
|
||||
<UserControl x:Class="TerminalApp.HighlightedTextControl"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="using:TerminalApp"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
Background="Transparent"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<TextBlock x:Name="_textView" />
|
||||
</UserControl>
|
||||
23
src/cascadia/TerminalApp/HighlightedTextControlStyle.xaml
Normal file
23
src/cascadia/TerminalApp/HighlightedTextControlStyle.xaml
Normal file
@ -0,0 +1,23 @@
|
||||
<!--
|
||||
Copyright (c) Microsoft Corporation. All rights reserved. Licensed under
|
||||
the MIT License. See LICENSE in the project root for license information.
|
||||
-->
|
||||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="using:TerminalApp"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<Style TargetType="local:HighlightedTextControl">
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="local:HighlightedTextControl">
|
||||
<TextBlock x:Name="TextView"
|
||||
Style="{TemplateBinding TextBlockStyle}" />
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
</ResourceDictionary>
|
||||
29
src/cascadia/TerminalApp/IPaletteItem.idl
Normal file
29
src/cascadia/TerminalApp/IPaletteItem.idl
Normal file
@ -0,0 +1,29 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import "TerminalTabStatus.idl";
|
||||
|
||||
namespace TerminalApp
|
||||
{
|
||||
enum PaletteItemType
|
||||
{
|
||||
Action,
|
||||
CommandLine,
|
||||
Tab,
|
||||
};
|
||||
|
||||
interface IPaletteItem requires Windows.UI.Xaml.Data.INotifyPropertyChanged
|
||||
{
|
||||
PaletteItemType Type { get; };
|
||||
String Name { get; };
|
||||
String Subtitle { get; };
|
||||
String KeyChordText { get; };
|
||||
String Icon { get; };
|
||||
Windows.UI.Xaml.Controls.IconElement ResolvedIcon { get; };
|
||||
}
|
||||
|
||||
runtimeclass TabPaletteItem : [default] IPaletteItem, Windows.UI.Xaml.Data.INotifyPropertyChanged
|
||||
{
|
||||
TerminalTabStatus TabStatus{ get; };
|
||||
}
|
||||
}
|
||||
@ -19,41 +19,6 @@ DEFINE_PROPERTYKEY(PKEY_AppUserModel_DestListLogoUri, 0x9F4C2855, 0x9F79, 0x4B39
|
||||
{ 0x9F4C2855, 0x9F79, 0x4B39, 0xA8, 0xD0, 0xE1, 0xD4, 0x2D, 0xE1, 0xD5, 0xF3 }, 29 \
|
||||
}
|
||||
|
||||
// Function Description:
|
||||
// - This function guesses whether a string is a file path.
|
||||
static constexpr bool _isProbableFilePath(std::wstring_view path)
|
||||
{
|
||||
// "C:X", "C:\X", "\\?", "\\."
|
||||
// _this function rejects \??\ as a path_
|
||||
if (path.size() >= 3)
|
||||
{
|
||||
const auto firstColon{ path.find(L':') };
|
||||
if (firstColon == 1)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
const auto prefix{ path.substr(0, 2) };
|
||||
return prefix == LR"(//)" || prefix == LR"(\\)";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Function Description:
|
||||
// - DestListLogoUri cannot take paths that are separated by / unless they're URLs.
|
||||
// This function uses std::filesystem to normalize strings that appear to be file
|
||||
// paths to have the "correct" slash direction.
|
||||
static std::wstring _normalizeIconPath(std::wstring_view path)
|
||||
{
|
||||
const auto fullPath{ wil::ExpandEnvironmentStringsW<std::wstring>(path.data()) };
|
||||
if (_isProbableFilePath(fullPath))
|
||||
{
|
||||
std::filesystem::path asPath{ fullPath };
|
||||
return asPath.make_preferred().wstring();
|
||||
}
|
||||
return std::wstring{ fullPath };
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Updates the items of the Jumplist based on the given settings.
|
||||
// Arguments:
|
||||
@ -124,7 +89,7 @@ void Jumplist::_updateProfiles(IObjectCollection* jumplistItems, winrt::Windows:
|
||||
auto args = fmt::format(FMT_COMPILE(L"-p {}"), to_hstring(profile.Guid()));
|
||||
|
||||
// Create the shell link object for the profile
|
||||
const auto normalizedIconPath{ _normalizeIconPath(profile.Icon()) };
|
||||
const auto normalizedIconPath{ profile.Icon().Resolved() };
|
||||
const auto shLink = _createShellLink(profile.Name(), normalizedIconPath, args);
|
||||
THROW_IF_FAILED(jumplistItems->AddObject(shLink.get()));
|
||||
}
|
||||
|
||||
@ -35,17 +35,23 @@ namespace winrt::TerminalApp::implementation
|
||||
// (which should be the default, see:
|
||||
// https://docs.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-trackmouseevent#remarks)
|
||||
unsigned int hoverTimeoutMillis{ 400 };
|
||||
LOG_IF_WIN32_BOOL_FALSE(SystemParametersInfoW(SPI_GETMOUSEHOVERTIME, 0, &hoverTimeoutMillis, 0));
|
||||
const auto toolTipInterval = std::chrono::milliseconds(hoverTimeoutMillis);
|
||||
if (FAILED(SystemParametersInfoW(SPI_GETMOUSEHOVERTIME, 0, &hoverTimeoutMillis, 0)))
|
||||
{
|
||||
hoverTimeoutMillis = 400;
|
||||
}
|
||||
|
||||
// Create a ThrottledFunc for opening the tooltip after the hover
|
||||
// timeout. If we hover another button, we should make sure to call
|
||||
// Run() with the new button. Calling `_displayToolTip.Run(nullptr)`,
|
||||
// which will cause us to not display a tooltip, which is used when we
|
||||
// leave the control entirely.
|
||||
_displayToolTip = std::make_shared<ThrottledFuncTrailing<Controls::Button>>(
|
||||
_displayToolTip = std::make_shared<ThrottledFunc<Controls::Button>>(
|
||||
dispatcher,
|
||||
toolTipInterval,
|
||||
til::throttled_func_options{
|
||||
.delay = std::chrono::milliseconds{ hoverTimeoutMillis },
|
||||
.debounce = true,
|
||||
.trailing = true,
|
||||
},
|
||||
[weakThis = get_weak()](Controls::Button button) {
|
||||
// If we provide a button, then open the tooltip on that button.
|
||||
// We can "dismiss" this throttled func by calling it with null,
|
||||
|
||||
@ -32,7 +32,7 @@ namespace winrt::TerminalApp::implementation
|
||||
til::typed_event<TerminalApp::MinMaxCloseControl, winrt::Windows::UI::Xaml::RoutedEventArgs> MaximizeClick;
|
||||
til::typed_event<TerminalApp::MinMaxCloseControl, winrt::Windows::UI::Xaml::RoutedEventArgs> CloseClick;
|
||||
|
||||
std::shared_ptr<ThrottledFuncTrailing<winrt::Windows::UI::Xaml::Controls::Button>> _displayToolTip{ nullptr };
|
||||
std::shared_ptr<ThrottledFunc<winrt::Windows::UI::Xaml::Controls::Button>> _displayToolTip{ nullptr };
|
||||
std::optional<CaptionButton> _lastPressedButton{ std::nullopt };
|
||||
};
|
||||
}
|
||||
|
||||
@ -1,25 +0,0 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#include "pch.h"
|
||||
#include <LibraryResources.h>
|
||||
#include "PaletteItem.h"
|
||||
#include "PaletteItem.g.cpp"
|
||||
|
||||
using namespace winrt;
|
||||
using namespace winrt::Windows::UI::Xaml;
|
||||
using namespace winrt::Windows::UI::Core;
|
||||
using namespace winrt::Microsoft::Terminal::Control;
|
||||
using namespace winrt::Microsoft::Terminal::Settings::Model;
|
||||
using namespace winrt::Windows::System;
|
||||
|
||||
namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
Controls::IconElement PaletteItem::ResolvedIcon()
|
||||
{
|
||||
const auto icon = Microsoft::Terminal::UI::IconPathConverter::IconWUX(Icon());
|
||||
icon.Width(16);
|
||||
icon.Height(16);
|
||||
return icon;
|
||||
}
|
||||
}
|
||||
@ -1,20 +0,0 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#pragma once
|
||||
#include "PaletteItem.g.h"
|
||||
|
||||
namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
struct PaletteItem : PaletteItemT<PaletteItem>
|
||||
{
|
||||
public:
|
||||
Windows::UI::Xaml::Controls::IconElement ResolvedIcon();
|
||||
|
||||
til::property_changed_event PropertyChanged;
|
||||
|
||||
WINRT_OBSERVABLE_PROPERTY(winrt::hstring, Name, PropertyChanged.raise);
|
||||
WINRT_OBSERVABLE_PROPERTY(winrt::hstring, Icon, PropertyChanged.raise);
|
||||
WINRT_OBSERVABLE_PROPERTY(winrt::hstring, KeyChordText, PropertyChanged.raise);
|
||||
};
|
||||
}
|
||||
@ -1,13 +0,0 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
namespace TerminalApp
|
||||
{
|
||||
unsealed runtimeclass PaletteItem : Windows.UI.Xaml.Data.INotifyPropertyChanged
|
||||
{
|
||||
String Name;
|
||||
String KeyChordText;
|
||||
String Icon;
|
||||
Windows.UI.Xaml.Controls.IconElement ResolvedIcon { get; };
|
||||
}
|
||||
}
|
||||
@ -2,10 +2,11 @@
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#include "pch.h"
|
||||
#include "TabPaletteItem.h"
|
||||
#include "PaletteItemTemplateSelector.h"
|
||||
#include "PaletteItemTemplateSelector.g.cpp"
|
||||
|
||||
#include "CommandPaletteItems.h"
|
||||
|
||||
namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
Windows::UI::Xaml::DataTemplate PaletteItemTemplateSelector::SelectTemplateCore(const winrt::Windows::Foundation::IInspectable& item, const winrt::Windows::UI::Xaml::DependencyObject& /*container*/)
|
||||
@ -26,16 +27,22 @@ namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
if (const auto filteredCommand{ item.try_as<winrt::TerminalApp::FilteredCommand>() })
|
||||
{
|
||||
if (filteredCommand.Item().try_as<winrt::TerminalApp::TabPaletteItem>())
|
||||
switch (filteredCommand.Item().Type())
|
||||
{
|
||||
case PaletteItemType::Tab:
|
||||
return TabItemTemplate();
|
||||
}
|
||||
else if (const auto actionPaletteItem{ filteredCommand.Item().try_as<winrt::TerminalApp::ActionPaletteItem>() })
|
||||
case PaletteItemType::Action:
|
||||
{
|
||||
if (actionPaletteItem.Command().HasNestedCommands())
|
||||
const auto actionPaletteItem{ winrt::get_self<ActionPaletteItem>(filteredCommand.Item()) };
|
||||
if (actionPaletteItem->Command().HasNestedCommands())
|
||||
{
|
||||
return NestedItemTemplate();
|
||||
}
|
||||
break; // Fall back to the general template
|
||||
}
|
||||
case PaletteItemType::CommandLine:
|
||||
default:
|
||||
break; // Fall back to the general template
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -697,12 +697,24 @@ bool Pane::SwapPanes(std::shared_ptr<Pane> first, std::shared_ptr<Pane> second)
|
||||
// Refocus the last pane if there was a pane focused
|
||||
if (const auto focus = first->GetActivePane())
|
||||
{
|
||||
focus->_Focus();
|
||||
// GH#18184: manually focus the pane and content.
|
||||
// _Focus() results in no-op because the pane was _lastActive
|
||||
focus->GotFocus.raise(focus, FocusState::Programmatic);
|
||||
if (const auto& lastContent{ focus->GetLastFocusedContent() })
|
||||
{
|
||||
lastContent.Focus(FocusState::Programmatic);
|
||||
}
|
||||
}
|
||||
|
||||
if (const auto focus = second->GetActivePane())
|
||||
{
|
||||
focus->_Focus();
|
||||
// GH#18184: manually focus the pane and content.
|
||||
// _Focus() results in no-op because the pane was _lastActive
|
||||
focus->GotFocus.raise(focus, FocusState::Programmatic);
|
||||
if (const auto& lastContent{ focus->GetLastFocusedContent() })
|
||||
{
|
||||
lastContent.Focus(FocusState::Programmatic);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -1040,7 +1052,7 @@ std::shared_ptr<Pane> Pane::GetActivePane()
|
||||
// Arguments:
|
||||
// - <none>
|
||||
// Return Value:
|
||||
// - nullptr if this Pane is an unfocused parent, otherwise the TermControl of this Pane.
|
||||
// - nullptr if this Pane is an unfocused parent; otherwise, the TermControl of this Pane.
|
||||
TermControl Pane::GetLastFocusedTerminalControl()
|
||||
{
|
||||
if (!_IsLeaf())
|
||||
@ -1093,7 +1105,7 @@ IPaneContent Pane::GetLastFocusedContent()
|
||||
// Arguments:
|
||||
// - <none>
|
||||
// Return Value:
|
||||
// - nullptr if this Pane is a parent, otherwise the TermControl of this Pane.
|
||||
// - nullptr if this Pane is a parent; otherwise, the TermControl of this Pane.
|
||||
TermControl Pane::GetTerminalControl() const
|
||||
{
|
||||
if (const auto& terminalPane{ _getTerminalContent() })
|
||||
@ -1402,6 +1414,13 @@ void Pane::_CloseChild(const bool closeFirst)
|
||||
|
||||
// take the control, profile, id and isDefTermSession of the pane that _wasn't_ closed.
|
||||
_setPaneContent(remainingChild->_takePaneContent());
|
||||
if (!_content)
|
||||
{
|
||||
// GH#18071: our content is still null after taking the other pane's content,
|
||||
// so just notify our parent that we're closed.
|
||||
Closed.raise(nullptr, nullptr);
|
||||
return;
|
||||
}
|
||||
_id = remainingChild->Id();
|
||||
|
||||
// Revoke the old event handlers. Remove both the handlers for the panes
|
||||
@ -1585,7 +1604,7 @@ void Pane::_CloseChildRoutine(const bool closeFirst)
|
||||
return;
|
||||
}
|
||||
|
||||
// Setup the animation
|
||||
// Set up the animation
|
||||
|
||||
auto removedChild = closeFirst ? _firstChild : _secondChild;
|
||||
auto remainingChild = closeFirst ? _secondChild : _firstChild;
|
||||
@ -1986,7 +2005,7 @@ void Pane::_SetupEntranceAnimation()
|
||||
if (splitWidth)
|
||||
{
|
||||
// If we're animating the first child, then stick to the top/left of
|
||||
// the parent pane, otherwise use the bottom/right. This is always
|
||||
// the parent pane; otherwise, use the bottom/right. This is always
|
||||
// the "outside" of the parent pane.
|
||||
childGrid.HorizontalAlignment(isFirstChild ? HorizontalAlignment::Left : HorizontalAlignment::Right);
|
||||
if (control)
|
||||
@ -2011,7 +2030,7 @@ void Pane::_SetupEntranceAnimation()
|
||||
else
|
||||
{
|
||||
// If we're animating the first child, then stick to the top/left of
|
||||
// the parent pane, otherwise use the bottom/right. This is always
|
||||
// the parent pane; otherwise, use the bottom/right. This is always
|
||||
// the "outside" of the parent pane.
|
||||
childGrid.VerticalAlignment(isFirstChild ? VerticalAlignment::Top : VerticalAlignment::Bottom);
|
||||
if (control)
|
||||
@ -2410,7 +2429,7 @@ std::optional<uint32_t> Pane::Id() noexcept
|
||||
|
||||
// Method Description:
|
||||
// - Sets this pane's ID
|
||||
// - Panes are given IDs upon creation by TerminalTab
|
||||
// - Panes are given IDs upon creation by Tab
|
||||
// Arguments:
|
||||
// - The number to set this pane's ID to
|
||||
void Pane::Id(uint32_t id) noexcept
|
||||
@ -2526,7 +2545,7 @@ std::pair<float, float> Pane::_CalcChildrenSizes(const float fullSize) const
|
||||
// user doesn't get any pane shrank when they actually expand the window or parent pane.
|
||||
// That is also required by the layout algorithm.
|
||||
// Arguments:
|
||||
// - widthOrHeight: if true, operates on width, otherwise on height.
|
||||
// - widthOrHeight: if true, operates on width; otherwise, on height.
|
||||
// - fullSize: the amount of space in pixels that should be filled by our children and
|
||||
// their separator. Can be arbitrarily low.
|
||||
// Return Value:
|
||||
@ -2588,7 +2607,7 @@ Pane::SnapChildrenSizeResult Pane::_CalcSnappedChildrenSizes(const bool widthOrH
|
||||
// align with their character grids as close as possible. Snaps to closes match
|
||||
// (either upward or downward). Also makes sure to fit in minimal sizes of the panes.
|
||||
// Arguments:
|
||||
// - widthOrHeight: if true operates on width, otherwise on height
|
||||
// - widthOrHeight: if true operates on width; otherwise, on height
|
||||
// - dimension: a dimension (width or height) to snap
|
||||
// Return Value:
|
||||
// - A value corresponding to the next closest snap size for this Pane, either upward or downward
|
||||
@ -2603,7 +2622,7 @@ float Pane::CalcSnappedDimension(const bool widthOrHeight, const float dimension
|
||||
// align with their character grids as close as possible. Also makes sure to
|
||||
// fit in minimal sizes of the panes.
|
||||
// Arguments:
|
||||
// - widthOrHeight: if true operates on width, otherwise on height
|
||||
// - widthOrHeight: if true operates on width; otherwise, on height
|
||||
// - dimension: a dimension (width or height) to be snapped
|
||||
// Return Value:
|
||||
// - pair of floats, where first value is the size snapped downward (not greater than
|
||||
@ -2690,11 +2709,11 @@ Pane::SnapSizeResult Pane::_CalcSnappedDimension(const bool widthOrHeight, const
|
||||
|
||||
// Method Description:
|
||||
// - Increases size of given LayoutSizeNode to match next possible 'snap'. In case of leaf
|
||||
// pane this means the next cell of the terminal. Otherwise it means that one of its children
|
||||
// pane this means the next cell of the terminal. Otherwise, it means that one of its children
|
||||
// advances (recursively). It expects the given node and its descendants to have either
|
||||
// already snapped or minimum size.
|
||||
// Arguments:
|
||||
// - widthOrHeight: if true operates on width, otherwise on height.
|
||||
// - widthOrHeight: if true operates on width; otherwise, on height.
|
||||
// - sizeNode: a layout size node that corresponds to this pane.
|
||||
// Return Value:
|
||||
// - <none>
|
||||
@ -2865,7 +2884,7 @@ Size Pane::_GetMinSize() const
|
||||
// - Builds a tree of LayoutSizeNode that matches the tree of panes. Each node
|
||||
// has minimum size that the corresponding pane can have.
|
||||
// Arguments:
|
||||
// - widthOrHeight: if true operates on width, otherwise on height
|
||||
// - widthOrHeight: if true operates on width; otherwise, on height
|
||||
// Return Value:
|
||||
// - Root node of built tree that matches this pane.
|
||||
Pane::LayoutSizeNode Pane::_CreateMinSizeTree(const bool widthOrHeight) const
|
||||
@ -2885,7 +2904,7 @@ Pane::LayoutSizeNode Pane::_CreateMinSizeTree(const bool widthOrHeight) const
|
||||
// - Adjusts split position so that no child pane is smaller then its
|
||||
// minimum size
|
||||
// Arguments:
|
||||
// - widthOrHeight: if true, operates on width, otherwise on height.
|
||||
// - widthOrHeight: if true, operates on width; otherwise, on height.
|
||||
// - requestedValue: split position value to be clamped
|
||||
// - totalSize: size (width or height) of the parent pane
|
||||
// Return Value:
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user