Merge remote-tracking branch 'origin/main' into dev/migrie/f/sui-panes

This commit is contained in:
Mike Griese
2024-04-03 10:13:40 -05:00
60 changed files with 578 additions and 780 deletions

View File

@@ -32,6 +32,7 @@ DWINRT
enablewttlogging
HOMESHARE
Intelli
issecret
IVisual
libucrt
libucrtd
@@ -74,6 +75,7 @@ sid
Skype
SRW
sxs
symbolrequestprod
Sysinternals
sysnative
systemroot

View File

@@ -33,6 +33,8 @@ extends:
publishSymbolsToPublic: true
publishVpackToWindows: false
symbolExpiryTime: 15
symbolPublishingSubscription: $(SymbolPublishingServiceConnection)
symbolPublishingProject: $(SymbolPublishingProject)
${{ if eq(true, parameters.publishToAzure) }}:
extraPublishJobs:
- template: build/pipelines/templates-v2/job-deploy-to-azure-storage.yml@self

View File

@@ -81,3 +81,5 @@ extends:
terminalInternalPackageVersion: ${{ parameters.terminalInternalPackageVersion }}
publishSymbolsToPublic: ${{ parameters.publishSymbolsToPublic }}
publishVpackToWindows: ${{ parameters.publishVpackToWindows }}
symbolPublishingSubscription: $(SymbolPublishingServiceConnection)
symbolPublishingProject: $(SymbolPublishingProject)

View File

@@ -0,0 +1,117 @@
parameters:
- name: includePublicSymbolServer
type: boolean
default: false
- name: pool
type: object
default: []
- name: dependsOn
type: object
default: null
- name: artifactStem
type: string
default: ''
- name: jobName
type: string
default: PublishSymbols
- name: symbolExpiryTime
type: string
default: 36530 # This is the default from PublishSymbols@2
- name: variables
type: object
default: {}
- name: subscription
type: string
- name: symbolProject
type: string
jobs:
- job: ${{ parameters.jobName }}
${{ if ne(length(parameters.pool), 0) }}:
pool: ${{ parameters.pool }}
${{ if eq(parameters.includePublicSymbolServer, true) }}:
displayName: Publish Symbols to Internal and MSDL
${{ else }}:
displayName: Publish Symbols Internally
dependsOn: ${{ parameters.dependsOn }}
variables:
${{ insert }}: ${{ parameters.variables }}
steps:
- checkout: self
clean: true
fetchDepth: 1
fetchTags: false # Tags still result in depth > 1 fetch; we don't need them here
submodules: true
persistCredentials: True
- task: PkgESSetupBuild@12
displayName: Package ES - Setup Build
inputs:
disableOutputRedirect: true
- task: DownloadPipelineArtifact@2
displayName: Download all PDBs from all prior build phases
inputs:
itemPattern: '**/*.pdb'
targetPath: '$(Build.SourcesDirectory)/bin'
- powershell: |-
Get-PackageProvider -Name NuGet -ForceBootstrap
Install-Module -Verbose -AllowClobber -Force Az.Accounts, Az.Storage, Az.Network, Az.Resources, Az.Compute
displayName: Install Azure Module Dependencies
# Transit the Azure token from the Service Connection into a secret variable for the rest of the pipeline to use.
- task: AzurePowerShell@5
displayName: Generate an Azure Token
inputs:
azureSubscription: ${{ parameters.subscription }}
azurePowerShellVersion: LatestVersion
pwsh: true
ScriptType: InlineScript
Inline: |-
$AzToken = (Get-AzAccessToken -ResourceUrl api://30471ccf-0966-45b9-a979-065dbedb24c1).Token
Write-Host "##vso[task.setvariable variable=SymbolAccessToken;issecret=true]$AzToken"
- task: PublishSymbols@2
displayName: Publish Symbols (to current Azure DevOps tenant)
continueOnError: True
inputs:
SymbolsFolder: '$(Build.SourcesDirectory)/bin'
SearchPattern: '**/*.pdb'
IndexSources: false
DetailedLog: true
SymbolsMaximumWaitTime: 30
SymbolServerType: 'TeamServices'
SymbolsProduct: 'Windows Terminal Converged Symbols'
SymbolsVersion: '$(XES_APPXMANIFESTVERSION)'
SymbolsArtifactName: 'WindowsTerminal_$(XES_APPXMANIFESTVERSION)'
SymbolExpirationInDays: ${{ parameters.symbolExpiryTime }}
env:
LIB: $(Build.SourcesDirectory)
- pwsh: |-
# Prepare the defaults for IRM
$PSDefaultParameterValues['Invoke-RestMethod:Headers'] = @{ Authorization = "Bearer $(SymbolAccessToken)" }
$PSDefaultParameterValues['Invoke-RestMethod:ContentType'] = "application/json"
$PSDefaultParameterValues['Invoke-RestMethod:Method'] = "POST"
$BaseUri = "https://symbolrequestprod.trafficmanager.net/projects/${{ parameters.symbolProject }}/requests"
# Prepare the request
$expiration = (Get-Date).Add([TimeSpan]::FromDays(${{ parameters.symbolExpiryTime }}))
$createRequestBody = @{
requestName = "WindowsTerminal_$(XES_APPXMANIFESTVERSION)";
expirationTime = $expiration.ToString();
}
Write-Host "##[debug]Starting request $($createRequestBody.requestName) with expiration date of $($createRequestBody.expirationTime)"
Invoke-RestMethod -Uri "$BaseUri" -Body ($createRequestBody | ConvertTo-Json -Compress) -Verbose
# Request symbol publication
$publishRequestBody = @{
publishToInternalServer = $true;
publishToPublicServer = $${{ parameters.includePublicSymbolServer }};
}
Write-Host "##[debug]Submitting request $($createRequestBody.requestName) ($($publishRequestBody | ConvertTo-Json -Compress))"
Invoke-RestMethod -Uri "$BaseUri/$($createRequestBody.requestName)" -Body ($publishRequestBody | ConvertTo-Json -Compress) -Verbose
displayName: Publish Symbols using internal REST API

View File

@@ -52,6 +52,10 @@ parameters:
- name: publishVpackToWindows
type: boolean
default: false
- name: symbolPublishingSubscription
type: string
- name: symbolPublishingProject
type: string
- name: extraPublishJobs
type: object
@@ -248,12 +252,13 @@ extends:
displayName: Publish
dependsOn: [Build]
jobs:
- template: ./build/pipelines/templates-v2/job-publish-symbols.yml@self
- template: ./build/pipelines/templates-v2/job-publish-symbols-using-symbolrequestprod-api.yml@self
parameters:
pool: { type: windows }
includePublicSymbolServer: ${{ parameters.publishSymbolsToPublic }}
symbolPatGoesInTaskInputs: true # onebranch tries to muck with the PAT variable, so we need to change how it get the PAT
symbolExpiryTime: ${{ parameters.symbolExpiryTime }}
subscription: ${{ parameters.symbolPublishingSubscription }}
symbolProject: ${{ parameters.symbolPublishingProject }}
variables:
ob_git_checkout: false # This job checks itself out
ob_git_skip_checkout_none: true

View File

@@ -154,3 +154,47 @@ popd
The `bx` will build just the Terminal package, critically, populating the `CascadiaPackage.build.appxrecipe` file. Once that's been built, then the `DeployAppRecipe.exe` command can be used to deploy a loose layout in the same way that Visual Studio does.
Notably, this method of building the Terminal package can't leverage the FastUpToDate check in Visual Studio, so the builds end up being considerably slower for the whole package, as cppwinrt does a lot of work before confirming that it's up to date and doing nothing.
### Are you seeing `DEP0700: Registration of the app failed`?
Once in a blue moon, I get a `DEP0700: Registration of the app failed.
[0x80073CF6] error 0x80070020: Windows cannot register the package because of an
internal error or low memory.` when trying to deploy in VS. For us, that can
happen if the `OpenConsoleProxy.dll` gets locked up, in use by some other
terminal package.
Doing the equivalent command in powershell can give us more info:
```pwsh
Add-AppxPackage -register "Z:\dev\public\OpenConsole\src\cascadia\CascadiaPackage\bin\x64\Debug\AppX\AppxManifest.xml"
```
That'll suggest `NOTE: For additional information, look for [ActivityId]
dbf551f1-83d0-0007-43e7-9cded083da01 in the Event Log or use the command line
Get-AppPackageLog -ActivityID dbf551f1-83d0-0007-43e7-9cded083da01`. So do that:
```pwsh
Get-AppPackageLog -ActivityID dbf551f1-83d0-0007-43e7-9cded083da01
```
which will give you a lot of info. In my case, that revealed that the platform
couldn't delete the packaged com entries. The key line was: `AppX Deployment
operation failed with error 0x0 from API Logging data because access was denied
for file:
C:\ProgramData\Microsoft\Windows\AppRepository\Packages\WindowsTerminalDev_0.0.1.0_x64__8wekyb3d8bbwe,
user SID: S-1-5-18`
Take that path, and
```pwsh
sudo start C:\ProgramData\Microsoft\Windows\AppRepository\Packages\WindowsTerminalDev_0.0.1.0_x64__8wekyb3d8bbwe
```
(use `sudo`, since the path is otherwise locked down). From there, go into the
`PackagedCom` folder, and open [File
Locksmith](https://learn.microsoft.com/en-us/windows/powertoys/file-locksmith)
(or Process Explorer, if you're more familiar with that) on
`OpenConsoleProxy.dll`. Just go ahead and immediately re-launch it as admin,
too. That should list off a couple terminal processes that are just hanging
around. Go ahead and end them all. You should be good to deploy again after
that.

View File

@@ -1297,7 +1297,8 @@ void TextBuffer::TriggerNewTextNotification(const std::wstring_view newText)
// - the delimiter class for the given char
DelimiterClass TextBuffer::_GetDelimiterClassAt(const til::point pos, const std::wstring_view wordDelimiters) const
{
return GetRowByOffset(pos.y).DelimiterClassAt(pos.x, wordDelimiters);
const auto realPos = ScreenToBufferPosition(pos);
return GetRowByOffset(realPos.y).DelimiterClassAt(realPos.x, wordDelimiters);
}
// Method Description:

View File

@@ -186,9 +186,6 @@
<data name="Quit" xml:space="preserve">
<value>Beenden</value>
</data>
<data name="CloseWindowWarningTitle" xml:space="preserve">
<value>Möchten Sie alle Registerkarten schließen?</value>
</data>
<data name="MultiplePanes" xml:space="preserve">
<value>Mehrere Bereiche</value>
</data>
@@ -335,6 +332,9 @@
<data name="CmdProfileArgDesc" xml:space="preserve">
<value>Mit dem angegebenen Profil öffnen. Akzeptiert entweder den Namen oder die GUID eines Profils</value>
</data>
<data name="CmdSessionIdArgDesc" xml:space="preserve">
<value>Legt die WT_SESSION-Variable fest; muss eine GUID sein.</value>
</data>
<data name="CmdSplitPaneDesc" xml:space="preserve">
<value>Erstellen eines neuen geteilten Bereichs</value>
</data>

View File

@@ -183,9 +183,6 @@
<data name="Quit" xml:space="preserve">
<value>Salir</value>
</data>
<data name="CloseWindowWarningTitle" xml:space="preserve">
<value>¿Quieres cerrar todas las pestañas?</value>
</data>
<data name="MultiplePanes" xml:space="preserve">
<value>Varios paneles</value>
</data>
@@ -332,6 +329,9 @@
<data name="CmdProfileArgDesc" xml:space="preserve">
<value>Abre con el perfil determinado. Acepta el nombre o el GUID de un perfil.</value>
</data>
<data name="CmdSessionIdArgDesc" xml:space="preserve">
<value>Establece la variable WT_SESSION; debe ser un GUID</value>
</data>
<data name="CmdSplitPaneDesc" xml:space="preserve">
<value>Crear un nuevo panel de división</value>
</data>

View File

@@ -183,9 +183,6 @@
<data name="Quit" xml:space="preserve">
<value>Quitter</value>
</data>
<data name="CloseWindowWarningTitle" xml:space="preserve">
<value>Voulez-vous fermer tous les onglets ?</value>
</data>
<data name="MultiplePanes" xml:space="preserve">
<value>Volets multiples</value>
</data>
@@ -332,6 +329,9 @@
<data name="CmdProfileArgDesc" xml:space="preserve">
<value>Ouvrez avec le profil donné. Accepte le nom ou le GUID dun profil</value>
</data>
<data name="CmdSessionIdArgDesc" xml:space="preserve">
<value>Définit la variable WT_SESSION ; doit être un GUID</value>
</data>
<data name="CmdSplitPaneDesc" xml:space="preserve">
<value>Créer un volet de fractionnement</value>
</data>

View File

@@ -183,9 +183,6 @@
<data name="Quit" xml:space="preserve">
<value>Esci</value>
</data>
<data name="CloseWindowWarningTitle" xml:space="preserve">
<value>Vuoi chiudere tutte le schede?</value>
</data>
<data name="MultiplePanes" xml:space="preserve">
<value>Più riquadri</value>
</data>
@@ -332,6 +329,9 @@
<data name="CmdProfileArgDesc" xml:space="preserve">
<value>Apri con il profilo specificato. Accetta il nome oppure il GUID di un profilo</value>
</data>
<data name="CmdSessionIdArgDesc" xml:space="preserve">
<value>Imposta la variabile di WT_SESSION; deve essere un GUID</value>
</data>
<data name="CmdSplitPaneDesc" xml:space="preserve">
<value>Crea un nuovo riquadro suddiviso</value>
</data>

View File

@@ -184,9 +184,6 @@
<data name="Quit" xml:space="preserve">
<value>終了</value>
</data>
<data name="CloseWindowWarningTitle" xml:space="preserve">
<value>すべてのタブを閉じますか?</value>
</data>
<data name="MultiplePanes" xml:space="preserve">
<value>複数ウィンドウ</value>
</data>
@@ -333,6 +330,9 @@
<data name="CmdProfileArgDesc" xml:space="preserve">
<value>指定されたプロファイルで開きます。プロファイルの名前または GUID を指定できます</value>
</data>
<data name="CmdSessionIdArgDesc" xml:space="preserve">
<value>WT_SESSION 変数を設定します; GUID である必要があります</value>
</data>
<data name="CmdSplitPaneDesc" xml:space="preserve">
<value>新しい分割ウィンドウの作成</value>
</data>

View File

@@ -183,9 +183,6 @@
<data name="Quit" xml:space="preserve">
<value>끝내기</value>
</data>
<data name="CloseWindowWarningTitle" xml:space="preserve">
<value>모든 탭을 닫으시겠습니까?</value>
</data>
<data name="MultiplePanes" xml:space="preserve">
<value>여러 창</value>
</data>
@@ -332,6 +329,9 @@
<data name="CmdProfileArgDesc" xml:space="preserve">
<value>지정된 프로필로 엽니다. 프로필 이름 또는 GUID 허용</value>
</data>
<data name="CmdSessionIdArgDesc" xml:space="preserve">
<value>WT_SESSION 변수를 설정합니다. GUID여야 합니다.</value>
</data>
<data name="CmdSplitPaneDesc" xml:space="preserve">
<value>새 분할 창 만들기</value>
</data>

View File

@@ -183,9 +183,6 @@
<data name="Quit" xml:space="preserve">
<value>Encerrar</value>
</data>
<data name="CloseWindowWarningTitle" xml:space="preserve">
<value>Deseja fechar todas as guias?</value>
</data>
<data name="MultiplePanes" xml:space="preserve">
<value>Vários painéis</value>
</data>
@@ -332,6 +329,9 @@
<data name="CmdProfileArgDesc" xml:space="preserve">
<value>Abrir com o perfil determinado. Aceite o nome ou o GUID de um perfil</value>
</data>
<data name="CmdSessionIdArgDesc" xml:space="preserve">
<value>Define a variável WT_SESSION; deve ser um GUID</value>
</data>
<data name="CmdSplitPaneDesc" xml:space="preserve">
<value>Criar um novo painel dividido</value>
</data>

View File

@@ -187,9 +187,6 @@
<data name="Quit" xml:space="preserve">
<value>Qùíт !</value>
</data>
<data name="CloseWindowWarningTitle" xml:space="preserve">
<value>Đǿ ÿõű ŵãŋт тŏ ¢ľòŝê ăŀľ ŧãвŝ? !!! !!! !!!</value>
</data>
<data name="MultiplePanes" xml:space="preserve">
<value>Мµļтíрłĕ φдпėŝ !!! !</value>
</data>
@@ -340,6 +337,9 @@
<data name="CmdProfileArgDesc" xml:space="preserve">
<value>Θφêп шĩτћ ťнě ģìνēή ρѓøƒìĺę. Âćĉеφťś ёĩτĥėŗ τђė йάмє øя ĠŮΪÐ õƒ а φŕóƒίℓè !!! !!! !!! !!! !!! !!! !!! </value>
</data>
<data name="CmdSessionIdArgDesc" xml:space="preserve">
<value>Šέŧś ŧћэ ẀŦ_ŜÉŜŜІΟΝ νăяíåьłé; mµśτ вэ â ĢŨÎĐ !!! !!! !!! !!! !</value>
</data>
<data name="CmdSplitPaneDesc" xml:space="preserve">
<value>Ĉґéáŧе д ήэẅ ŝφĺĭτ рãňё !!! !!! </value>
</data>

View File

@@ -187,9 +187,6 @@
<data name="Quit" xml:space="preserve">
<value>Qùíт !</value>
</data>
<data name="CloseWindowWarningTitle" xml:space="preserve">
<value>Đǿ ÿõű ŵãŋт тŏ ¢ľòŝê ăŀľ ŧãвŝ? !!! !!! !!!</value>
</data>
<data name="MultiplePanes" xml:space="preserve">
<value>Мµļтíрłĕ φдпėŝ !!! !</value>
</data>
@@ -340,6 +337,9 @@
<data name="CmdProfileArgDesc" xml:space="preserve">
<value>Θφêп шĩτћ ťнě ģìνēή ρѓøƒìĺę. Âćĉеφťś ёĩτĥėŗ τђė йάмє øя ĠŮΪÐ õƒ а φŕóƒίℓè !!! !!! !!! !!! !!! !!! !!! </value>
</data>
<data name="CmdSessionIdArgDesc" xml:space="preserve">
<value>Šέŧś ŧћэ ẀŦ_ŜÉŜŜІΟΝ νăяíåьłé; mµśτ вэ â ĢŨÎĐ !!! !!! !!! !!! !</value>
</data>
<data name="CmdSplitPaneDesc" xml:space="preserve">
<value>Ĉґéáŧе д ήэẅ ŝφĺĭτ рãňё !!! !!! </value>
</data>

View File

@@ -187,9 +187,6 @@
<data name="Quit" xml:space="preserve">
<value>Qùíт !</value>
</data>
<data name="CloseWindowWarningTitle" xml:space="preserve">
<value>Đǿ ÿõű ŵãŋт тŏ ¢ľòŝê ăŀľ ŧãвŝ? !!! !!! !!!</value>
</data>
<data name="MultiplePanes" xml:space="preserve">
<value>Мµļтíрłĕ φдпėŝ !!! !</value>
</data>
@@ -340,6 +337,9 @@
<data name="CmdProfileArgDesc" xml:space="preserve">
<value>Θφêп шĩτћ ťнě ģìνēή ρѓøƒìĺę. Âćĉеφťś ёĩτĥėŗ τђė йάмє øя ĠŮΪÐ õƒ а φŕóƒίℓè !!! !!! !!! !!! !!! !!! !!! </value>
</data>
<data name="CmdSessionIdArgDesc" xml:space="preserve">
<value>Šέŧś ŧћэ ẀŦ_ŜÉŜŜІΟΝ νăяíåьłé; mµśτ вэ â ĢŨÎĐ !!! !!! !!! !!! !</value>
</data>
<data name="CmdSplitPaneDesc" xml:space="preserve">
<value>Ĉґéáŧе д ήэẅ ŝφĺĭτ рãňё !!! !!! </value>
</data>

View File

@@ -183,9 +183,6 @@
<data name="Quit" xml:space="preserve">
<value>Выход</value>
</data>
<data name="CloseWindowWarningTitle" xml:space="preserve">
<value>Закрыть все вкладки?</value>
</data>
<data name="MultiplePanes" xml:space="preserve">
<value>Несколько областей</value>
</data>
@@ -332,6 +329,9 @@
<data name="CmdProfileArgDesc" xml:space="preserve">
<value>Открыть с помощью данного профиля. Принимается имя или GUID профиля</value>
</data>
<data name="CmdSessionIdArgDesc" xml:space="preserve">
<value>Задает переменную WT_SESSION; должно быть GUID</value>
</data>
<data name="CmdSplitPaneDesc" xml:space="preserve">
<value>Создать новую область разделения</value>
</data>

View File

@@ -183,9 +183,6 @@
<data name="Quit" xml:space="preserve">
<value>退出</value>
</data>
<data name="CloseWindowWarningTitle" xml:space="preserve">
<value>是否要关闭所有标签页?</value>
</data>
<data name="MultiplePanes" xml:space="preserve">
<value>多个窗格</value>
</data>
@@ -332,6 +329,9 @@
<data name="CmdProfileArgDesc" xml:space="preserve">
<value>使用给定的配置文件打开。接受配置文件的名称或 GUID</value>
</data>
<data name="CmdSessionIdArgDesc" xml:space="preserve">
<value>设置 WT_SESSION 变量;必须是 GUID</value>
</data>
<data name="CmdSplitPaneDesc" xml:space="preserve">
<value>创建新的拆分窗格</value>
</data>

View File

@@ -183,9 +183,6 @@
<data name="Quit" xml:space="preserve">
<value>結束</value>
</data>
<data name="CloseWindowWarningTitle" xml:space="preserve">
<value>您要關閉所有索引標籤嗎?</value>
</data>
<data name="MultiplePanes" xml:space="preserve">
<value>多個窗格</value>
</data>
@@ -332,6 +329,9 @@
<data name="CmdProfileArgDesc" xml:space="preserve">
<value>使用指定的設定檔開啟。接受設定檔的名稱或 GUID</value>
</data>
<data name="CmdSessionIdArgDesc" xml:space="preserve">
<value>設定 WT_SESSION 變數; 必須為 GUID</value>
</data>
<data name="CmdSplitPaneDesc" xml:space="preserve">
<value>建立新的分割窗格</value>
</data>

View File

@@ -2276,7 +2276,18 @@ namespace winrt::Microsoft::Terminal::Control::implementation
void TermControl::PersistToPath(const winrt::hstring& path) const
{
winrt::get_self<ControlCore>(_core)->PersistToPath(path.c_str());
// Don't persist us if we weren't ever initialized. In that case, we
// never got an initial size, never instantiated a buffer, and didn't
// start the connection yet, so there's nothing for us to add here.
//
// If we were supposed to be restored from a path, then we don't need to
// do anything special here. We'll leave the original file untouched,
// and the next time we actually are initialized, we'll just use that
// file then.
if (_initializedTerminal)
{
winrt::get_self<ControlCore>(_core)->PersistToPath(path.c_str());
}
}
void TermControl::Close()

View File

@@ -419,6 +419,11 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
BOOL hasPowerlineCharacters = FALSE;
til::iterate_font_families(fontFace, [&](wil::zwstring_view name) {
if (primaryFontName.empty())
{
primaryFontName = name;
}
std::wstring* accumulator = nullptr;
UINT32 index = 0;
@@ -434,11 +439,6 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
break;
}
if (primaryFontName.empty())
{
primaryFontName = name;
}
wil::com_ptr<IDWriteFontFamily> fontFamily;
THROW_IF_FAILED(fontCollection->GetFontFamily(index, fontFamily.addressof()));

View File

@@ -184,6 +184,8 @@
Grid.Row="0"
Grid.Column="1"
VerticalAlignment="Center"
Maximum="999"
Minimum="1"
Style="{StaticResource LaunchSizeNumberBoxStyle}"
Value="{x:Bind ViewModel.InitialCols, Mode=TwoWay}" />
<TextBlock x:Uid="Globals_InitialRows"
@@ -195,6 +197,8 @@
Grid.Row="1"
Grid.Column="1"
VerticalAlignment="Center"
Maximum="999"
Minimum="1"
Style="{StaticResource LaunchSizeNumberBoxStyle}"
Value="{x:Bind ViewModel.InitialRows, Mode=TwoWay}" />
</Grid>

View File

@@ -187,6 +187,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
UpdateFontList();
}
const auto& currentFontList{ CompleteFontList() };
fallbackFont = currentFontList.First().Current();
for (const auto& font : currentFontList)
{
if (font.LocalizedName() == name)

View File

@@ -989,6 +989,10 @@
<value>Dieses Profil als Administrator ausführen</value>
<comment>Header for a control to toggle whether the profile should always open elevated (in an admin window)</comment>
</data>
<data name="Profile_Elevate.HelpText" xml:space="preserve">
<value>Wenn diese Option aktiviert ist, wird das Profil automatisch in einem Admin Terminalfenster geöffnet. Wenn das aktuelle Fenster bereits als Administrator ausgeführt wird, wird es in diesem Fenster geöffnet.</value>
<comment>A description for what the "elevate" setting does. Presented near "Profile_Elevate".</comment>
</data>
<data name="Profile_HistorySize.Header" xml:space="preserve">
<value>Größe des Verlaufs</value>
<comment>Header for a control to determine how many lines of text can be saved in a session. In terminals, the "history" is the output generated within your session.</comment>

View File

@@ -989,6 +989,10 @@
<value>Ejecutar este perfil como Administrador</value>
<comment>Header for a control to toggle whether the profile should always open elevated (in an admin window)</comment>
</data>
<data name="Profile_Elevate.HelpText" xml:space="preserve">
<value>Si se habilita, el perfil se abrirá automáticamente en una ventana de terminal Administración. Si la ventana actual ya se está ejecutando como administrador, se abrirá en esta ventana.</value>
<comment>A description for what the "elevate" setting does. Presented near "Profile_Elevate".</comment>
</data>
<data name="Profile_HistorySize.Header" xml:space="preserve">
<value>Tamaño del historial</value>
<comment>Header for a control to determine how many lines of text can be saved in a session. In terminals, the "history" is the output generated within your session.</comment>

View File

@@ -989,6 +989,10 @@
<value>Exécuter ce profil en tant quadministrateur</value>
<comment>Header for a control to toggle whether the profile should always open elevated (in an admin window)</comment>
</data>
<data name="Profile_Elevate.HelpText" xml:space="preserve">
<value>Si cette option est activée, le profil souvre automatiquement dans une fenêtre de terminal Administration. Si la fenêtre active est déjà en cours dexécution en tant quadministrateur, elle souvre dans cette fenêtre.</value>
<comment>A description for what the "elevate" setting does. Presented near "Profile_Elevate".</comment>
</data>
<data name="Profile_HistorySize.Header" xml:space="preserve">
<value>Taille de lhistorique</value>
<comment>Header for a control to determine how many lines of text can be saved in a session. In terminals, the "history" is the output generated within your session.</comment>

View File

@@ -989,6 +989,10 @@
<value>Esegui questo profilo come amministratore</value>
<comment>Header for a control to toggle whether the profile should always open elevated (in an admin window)</comment>
</data>
<data name="Profile_Elevate.HelpText" xml:space="preserve">
<value>Se questa opzione è abilitata, il profilo verrà aperto automaticamente in una finestra del terminale Amministrazione. Se la finestra corrente è già in esecuzione come amministratore, verrà aperta in questa finestra.</value>
<comment>A description for what the "elevate" setting does. Presented near "Profile_Elevate".</comment>
</data>
<data name="Profile_HistorySize.Header" xml:space="preserve">
<value>Dimensioni cronologia</value>
<comment>Header for a control to determine how many lines of text can be saved in a session. In terminals, the "history" is the output generated within your session.</comment>

View File

@@ -989,6 +989,10 @@
<value>このプロファイルを管理者として実行する</value>
<comment>Header for a control to toggle whether the profile should always open elevated (in an admin window)</comment>
</data>
<data name="Profile_Elevate.HelpText" xml:space="preserve">
<value>有効にすると、プロファイルは自動的にターミナル ウィンドウ管理開きます。現在のウィンドウが既に管理者として実行されている場合は、このウィンドウで開きます。</value>
<comment>A description for what the "elevate" setting does. Presented near "Profile_Elevate".</comment>
</data>
<data name="Profile_HistorySize.Header" xml:space="preserve">
<value>履歴のサイズ</value>
<comment>Header for a control to determine how many lines of text can be saved in a session. In terminals, the "history" is the output generated within your session.</comment>

View File

@@ -989,6 +989,10 @@
<value>이 프로필을 관리자 권한으로 실행</value>
<comment>Header for a control to toggle whether the profile should always open elevated (in an admin window)</comment>
</data>
<data name="Profile_Elevate.HelpText" xml:space="preserve">
<value>사용하도록 설정하면 프로필이 관리 터미널 창에서 자동으로 열립니다. 현재 창이 관리자 권한으로 이미 실행되고 있는 경우 이 창에서 열립니다.</value>
<comment>A description for what the "elevate" setting does. Presented near "Profile_Elevate".</comment>
</data>
<data name="Profile_HistorySize.Header" xml:space="preserve">
<value>기록 크기</value>
<comment>Header for a control to determine how many lines of text can be saved in a session. In terminals, the "history" is the output generated within your session.</comment>

View File

@@ -989,6 +989,10 @@
<value>Executar esse perfil como Administrador</value>
<comment>Header for a control to toggle whether the profile should always open elevated (in an admin window)</comment>
</data>
<data name="Profile_Elevate.HelpText" xml:space="preserve">
<value>Se habilitado, o perfil será aberto em uma janela Administração terminal automaticamente. Se a janela atual já estiver em execução como administrador, ela será aberta nesta janela.</value>
<comment>A description for what the "elevate" setting does. Presented near "Profile_Elevate".</comment>
</data>
<data name="Profile_HistorySize.Header" xml:space="preserve">
<value>Tamanho de histórico</value>
<comment>Header for a control to determine how many lines of text can be saved in a session. In terminals, the "history" is the output generated within your session.</comment>

View File

@@ -989,6 +989,10 @@
<value>Запустить этот профиль от имени администратора</value>
<comment>Header for a control to toggle whether the profile should always open elevated (in an admin window)</comment>
</data>
<data name="Profile_Elevate.HelpText" xml:space="preserve">
<value>Если этот параметр включен, профиль будет автоматически открываться в Администратор терминала. Если текущее окно уже запущено от имени администратора, оно откроется в этом окне.</value>
<comment>A description for what the "elevate" setting does. Presented near "Profile_Elevate".</comment>
</data>
<data name="Profile_HistorySize.Header" xml:space="preserve">
<value>Размер журнала</value>
<comment>Header for a control to determine how many lines of text can be saved in a session. In terminals, the "history" is the output generated within your session.</comment>

View File

@@ -989,6 +989,10 @@
<value>以管理员身份运行此配置文件</value>
<comment>Header for a control to toggle whether the profile should always open elevated (in an admin window)</comment>
</data>
<data name="Profile_Elevate.HelpText" xml:space="preserve">
<value>如果启用,配置文件将在管理员终端窗口中自动打开。如果当前窗口已以管理员身份运行,它将在此窗口中打开。</value>
<comment>A description for what the "elevate" setting does. Presented near "Profile_Elevate".</comment>
</data>
<data name="Profile_HistorySize.Header" xml:space="preserve">
<value>历史记录大小</value>
<comment>Header for a control to determine how many lines of text can be saved in a session. In terminals, the "history" is the output generated within your session.</comment>

View File

@@ -989,6 +989,10 @@
<value>以系統管理員身分執行此設定檔</value>
<comment>Header for a control to toggle whether the profile should always open elevated (in an admin window)</comment>
</data>
<data name="Profile_Elevate.HelpText" xml:space="preserve">
<value>如果啟用,配置檔將會自動在 管理員 終端機視窗中開啟。如果目前的視窗已以系統管理員身分執行,則會在此視窗中開啟。</value>
<comment>A description for what the "elevate" setting does. Presented near "Profile_Elevate".</comment>
</data>
<data name="Profile_HistorySize.Header" xml:space="preserve">
<value>歷史大小</value>
<comment>Header for a control to determine how many lines of text can be saved in a session. In terminals, the "history" is the output generated within your session.</comment>

View File

@@ -137,6 +137,17 @@ void GlobalAppSettings::LayerJson(const Json::Value& json, const OriginTag origi
MTSM_GLOBAL_SETTINGS(GLOBAL_SETTINGS_LAYER_JSON)
#undef GLOBAL_SETTINGS_LAYER_JSON
// GH#11975 We only want to allow sensible values and prevent crashes, so we are clamping those values
// We only want to assign if the value did change through clamping,
// otherwise we could end up setting defaults that get persisted
if (this->HasInitialCols())
{
this->InitialCols(std::clamp(this->InitialCols(), 1, 999));
}
if (this->HasInitialRows())
{
this->InitialRows(std::clamp(this->InitialRows(), 1, 999));
}
LayerActionsFrom(json, origin, true);
JsonUtils::GetValueForKey(json, LegacyReloadEnvironmentVariablesKey, _legacyReloadEnvironmentVariables);

View File

@@ -47,6 +47,7 @@ namespace SettingsModelUnitTests
TEST_METHOD(ValidateKeybindingsWarnings);
TEST_METHOD(ValidateColorSchemeInCommands);
TEST_METHOD(ValidateExecuteCommandlineWarning);
TEST_METHOD(TestClampingOfStartupColumnAndViewProperties);
TEST_METHOD(TestTrailingCommas);
TEST_METHOD(TestCommandsAndKeybindings);
TEST_METHOD(TestNestedCommandWithoutName);
@@ -1301,6 +1302,20 @@ namespace SettingsModelUnitTests
VERIFY_ARE_EQUAL(SettingsLoadWarnings::MissingRequiredParameter, settings->Warnings().GetAt(3));
}
void DeserializationTests::TestClampingOfStartupColumnAndViewProperties()
{
static constexpr std::string_view inputSettings{ R"({
"initialCols" : 1000000,
"initialRows" : -1000000,
"profiles": [{ "name": "profile0" }]
})" };
const auto settings = createSettings(inputSettings);
VERIFY_ARE_EQUAL(999, settings->GlobalSettings().InitialCols());
VERIFY_ARE_EQUAL(1, settings->GlobalSettings().InitialRows());
}
void DeserializationTests::TestTrailingCommas()
{
static constexpr std::string_view badSettings{ R"({

View File

@@ -58,7 +58,7 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned"
constexpr explicit operator bool() const noexcept
{
return (x > 0) & (y > 0);
return x >= 0 && y >= 0;
}
constexpr bool operator<(const point other) const noexcept

View File

@@ -4,11 +4,11 @@
#pragma once
#include "bit.h"
#include "some.h"
#include "math.h"
#include "size.h"
#include "point.h"
#include "operators.h"
#include "small_vector.h"
namespace til // Terminal Implementation Library. Also: "Today I Learned"
{
@@ -31,8 +31,7 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned"
explicit constexpr operator bool() const noexcept
{
return (left >= 0) & (top >= 0) &
(right >= left) & (bottom >= top);
return left >= 0 && top >= 0 && right >= left && bottom >= top;
}
};
@@ -204,8 +203,7 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned"
explicit constexpr operator bool() const noexcept
{
return (left >= 0) & (top >= 0) &
(right > left) & (bottom > top);
return left >= 0 && top >= 0 && right > left && bottom > top;
}
constexpr const_iterator begin() const
@@ -294,9 +292,9 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned"
}
// - = subtract
constexpr some<rect, 4> operator-(const rect& other) const
small_vector<rect, 4> operator-(const rect& other) const
{
some<rect, 4> result;
small_vector<rect, 4> result;
// We could have up to four rectangles describing the area resulting when you take removeMe out of main.
// Find the intersection of the two so we know which bits of removeMe are actually applicable
@@ -566,14 +564,12 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned"
constexpr bool contains(point pt) const noexcept
{
return (pt.x >= left) & (pt.x < right) &
(pt.y >= top) & (pt.y < bottom);
return pt.x >= left && pt.x < right && pt.y >= top && pt.y < bottom;
}
constexpr bool contains(const rect& rc) const noexcept
{
return (rc.left >= left) & (rc.top >= top) &
(rc.right <= right) & (rc.bottom <= bottom);
return rc.left >= left && rc.top >= top && rc.right <= right && rc.bottom <= bottom;
}
template<typename T = CoordType>

View File

@@ -3,8 +3,6 @@
#pragma once
#include "small_vector.h"
#ifdef UNIT_TESTING
class RunLengthEncodingTests;
#endif

View File

@@ -39,7 +39,7 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned"
constexpr explicit operator bool() const noexcept
{
return (width > 0) & (height > 0);
return width > 0 && height > 0;
}
constexpr size operator+(const size other) const

View File

@@ -652,7 +652,7 @@ namespace til
reference emplace_back(Args&&... args)
{
const auto new_size = _ensure_fits(1);
const auto it = new (_data + _size) T(std::forward<Args>(args)...);
const auto it = std::construct_at(_data + _size, std::forward<Args>(args)...);
_size = new_size;
return *it;
}
@@ -930,7 +930,10 @@ namespace til
T* _data;
size_t _capacity;
size_t _size;
T _buffer[N];
union
{
T _buffer[N];
};
};
}

View File

@@ -1,267 +0,0 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#pragma once
#include <array>
namespace til // Terminal Implementation Library. Also: "Today I Learned"
{
template<class T, size_t N>
class some
{
private:
std::array<T, N> _array;
size_t _used;
#ifdef UNIT_TESTING
friend class SomeTests;
#endif
public:
using value_type = T;
using size_type = size_t;
using difference_type = ptrdiff_t;
using pointer = T*;
using const_pointer = const T*;
using reference = T&;
using const_reference = const T&;
using iterator = typename decltype(_array)::iterator;
using const_iterator = typename decltype(_array)::const_iterator;
using reverse_iterator = typename decltype(_array)::reverse_iterator;
using const_reverse_iterator = typename decltype(_array)::const_reverse_iterator;
constexpr some() noexcept :
_array{},
_used{ 0 }
{
}
constexpr some(std::initializer_list<T> init)
{
if (init.size() > N)
{
_invalidArg();
}
std::copy(init.begin(), init.end(), _array.begin());
_used = init.size();
}
constexpr bool operator==(const til::some<T, N>& other) const noexcept
{
return std::equal(cbegin(), cend(), other.cbegin(), other.cend());
}
constexpr bool operator!=(const til::some<T, N>& other) const noexcept
{
return !(*this == other);
}
constexpr void fill(const T& _Value)
{
_array.fill(_Value);
_used = N;
}
constexpr void swap(some& _Other) noexcept(std::is_nothrow_swappable_v<T>)
{
_array.swap(_Other._array);
std::swap(_used, _Other._used);
}
constexpr const_iterator begin() const noexcept
{
return _array.begin();
}
constexpr const_iterator end() const noexcept
{
return _array.begin() + _used;
}
constexpr const_reverse_iterator rbegin() const noexcept
{
return const_reverse_iterator(end());
}
constexpr const_reverse_iterator rend() const noexcept
{
return const_reverse_iterator(begin());
}
constexpr const_iterator cbegin() const noexcept
{
return begin();
}
constexpr const_iterator cend() const noexcept
{
return end();
}
constexpr const_reverse_iterator crbegin() const noexcept
{
return rbegin();
}
constexpr const_reverse_iterator crend() const noexcept
{
return rend();
}
constexpr size_type size() const noexcept
{
return _used;
}
constexpr size_type max_size() const noexcept
{
return N;
}
constexpr bool empty() const noexcept
{
return !_used;
}
constexpr void clear() noexcept
{
_used = 0;
_array = {}; // should free members, if necessary.
}
constexpr const_reference at(size_type pos) const
{
if (_used <= pos)
{
_outOfRange();
}
return _array[pos];
}
constexpr const_reference operator[](size_type pos) const noexcept
{
return _array[pos];
}
constexpr const_reference front() const noexcept
{
return _array[0];
}
constexpr const_reference back() const noexcept
{
return _array[_used - 1];
}
constexpr const T* data() const noexcept
{
return _array.data();
}
constexpr void push_back(const T& val)
{
if (_used >= N)
{
_outOfRange();
}
til::at(_array, _used) = val;
++_used;
}
constexpr void push_back(T&& val)
{
if (_used >= N)
{
_outOfRange();
}
til::at(_array, _used) = std::move(val);
++_used;
}
constexpr void pop_back()
{
if (_used <= 0)
{
_outOfRange();
}
--_used;
til::at(_array, _used) = 0;
}
[[noreturn]] constexpr void _invalidArg() const
{
throw std::invalid_argument("invalid argument");
}
[[noreturn]] constexpr void _outOfRange() const
{
throw std::out_of_range("invalid some<T, N> subscript");
}
std::wstring to_string() const
{
std::wstringstream wss;
wss << std::endl
<< L"Some contains " << size() << " of max size " << max_size() << ":" << std::endl;
wss << L"Elements:" << std::endl;
for (auto& item : *this)
{
wss << L"\t- " << item.to_string() << std::endl;
}
return wss.str();
}
};
}
#ifdef __WEX_COMMON_H__
namespace WEX::TestExecution
{
template<class T, size_t N>
class VerifyOutputTraits<::til::some<T, N>>
{
public:
static WEX::Common::NoThrowString ToString(const ::til::some<T, N>& some)
{
return WEX::Common::NoThrowString(some.to_string().c_str());
}
};
template<class T, size_t N>
class VerifyCompareTraits<::til::some<T, N>, ::til::some<T, N>>
{
public:
static bool AreEqual(const ::til::some<T, N>& expected, const ::til::some<T, N>& actual) noexcept
{
return expected == actual;
}
static bool AreSame(const ::til::some<T, N>& expected, const ::til::some<T, N>& actual) noexcept
{
return &expected == &actual;
}
static bool IsLessThan(const ::til::some<T, N>& expectedLess, const ::til::some<T, N>& expectedGreater) = delete;
static bool IsGreaterThan(const ::til::some<T, N>& expectedGreater, const ::til::some<T, N>& expectedLess) = delete;
static bool IsNull(const ::til::some<T, N>& object) noexcept
{
return object == til::some<T, N>{};
}
};
};
#endif

View File

@@ -482,32 +482,17 @@ void AtlasEngine::SetWarningCallback(std::function<void(HRESULT, wil::zwstring_v
// commit 9e86c98 (PR #16196), because it showed that it's definitely not due to FindFamilyName() failing.
//
// The workaround is to catch the exception and retry it with our nearby fonts manually loaded in.
HRESULT hr = _updateFont(fontInfoDesired, fontInfo, features, axes);
if constexpr (Feature_NearbyFontLoading::IsEnabled())
{
try
if (FAILED(hr) && _updateWithNearbyFontCollection())
{
_updateFont(fontInfoDesired, fontInfo, features, axes);
return S_OK;
hr = _updateFont(fontInfoDesired, fontInfo, features, axes);
}
CATCH_LOG();
// _resolveFontMetrics() checks `_api.s->font->fontCollection` for a pre-existing font collection,
// before falling back to using the system font collection. This way we can inject our custom one.
// Doing it this way is a bit hacky, but it does have the benefit that we can cache a font collection
// instance across font changes, like when zooming the font size rapidly using the scroll wheel.
try
{
_api.s.write()->font.write()->fontCollection = FontCache::GetCached();
}
CATCH_LOG();
}
try
{
_updateFont(fontInfoDesired, fontInfo, features, axes);
return S_OK;
}
CATCH_RETURN();
return hr;
}
void AtlasEngine::UpdateHyperlinkHoveredId(const uint16_t hoveredId) noexcept
@@ -536,7 +521,8 @@ void AtlasEngine::_resolveTransparencySettings() noexcept
}
}
void AtlasEngine::_updateFont(const FontInfoDesired& fontInfoDesired, FontInfo& fontInfo, const std::unordered_map<std::wstring_view, uint32_t>& features, const std::unordered_map<std::wstring_view, float>& axes)
[[nodiscard]] HRESULT AtlasEngine::_updateFont(const FontInfoDesired& fontInfoDesired, FontInfo& fontInfo, const std::unordered_map<std::wstring_view, uint32_t>& features, const std::unordered_map<std::wstring_view, float>& axes) noexcept
try
{
std::vector<DWRITE_FONT_FEATURE> fontFeatures;
if (!features.empty())
@@ -616,9 +602,12 @@ void AtlasEngine::_updateFont(const FontInfoDesired& fontInfoDesired, FontInfo&
_resolveFontMetrics(fontInfoDesired, fontInfo, font);
font->fontFeatures = std::move(fontFeatures);
font->fontAxisValues = std::move(fontAxisValues);
}
void AtlasEngine::_resolveFontMetrics(const FontInfoDesired& fontInfoDesired, FontInfo& fontInfo, FontSettings* fontMetrics) const
return S_OK;
}
CATCH_RETURN()
void AtlasEngine::_resolveFontMetrics(const FontInfoDesired& fontInfoDesired, FontInfo& fontInfo, FontSettings* fontMetrics)
{
const auto& faceName = fontInfoDesired.GetFaceName();
const auto requestedFamily = fontInfoDesired.GetFamily();
@@ -659,6 +648,16 @@ void AtlasEngine::_resolveFontMetrics(const FontInfoDesired& fontInfoDesired, Fo
BOOL exists = false;
THROW_IF_FAILED(fontCollection->FindFamilyName(fontName.c_str(), &index, &exists));
// In case of a portable build, the given font may not be installed and instead be bundled next to our executable.
if constexpr (Feature_NearbyFontLoading::IsEnabled())
{
if (!exists && _updateWithNearbyFontCollection())
{
fontCollection = _api.s->font->fontCollection;
THROW_IF_FAILED(fontCollection->FindFamilyName(fontName.c_str(), &index, &exists));
}
}
if (!exists)
{
if (!missingFontNames.empty())
@@ -869,3 +868,29 @@ void AtlasEngine::_resolveFontMetrics(const FontInfoDesired& fontInfoDesired, Fo
fontMetrics->colorGlyphs = fontInfoDesired.GetEnableColorGlyphs();
}
}
// Nearby fonts are described a couple of times throughout the file.
// This abstraction in particular helps us avoid retrying when it's pointless:
// After all, if the font collection didn't change (no nearby fonts, loading failed, it's already loaded),
// we don't need to try it again. It returns true if retrying is necessary.
[[nodiscard]] bool AtlasEngine::_updateWithNearbyFontCollection() noexcept
{
// _resolveFontMetrics() checks `_api.s->font->fontCollection` for a pre-existing font collection,
// before falling back to using the system font collection. This way we can inject our custom one.
// Doing it this way is a bit hacky, but it does have the benefit that we can cache a font collection
// instance across font changes, like when zooming the font size rapidly using the scroll wheel.
wil::com_ptr<IDWriteFontCollection> collection;
try
{
collection = FontCache::GetCached();
}
CATCH_LOG();
if (!collection || _api.s->font->fontCollection == collection)
{
return false;
}
_api.s.write()->font.write()->fontCollection = std::move(collection);
return true;
}

View File

@@ -94,8 +94,9 @@ namespace Microsoft::Console::Render::Atlas
// AtlasEngine.api.cpp
void _resolveTransparencySettings() noexcept;
void _updateFont(const FontInfoDesired& fontInfoDesired, FontInfo& fontInfo, const std::unordered_map<std::wstring_view, uint32_t>& features, const std::unordered_map<std::wstring_view, float>& axes);
void _resolveFontMetrics(const FontInfoDesired& fontInfoDesired, FontInfo& fontInfo, FontSettings* fontMetrics = nullptr) const;
[[nodiscard]] HRESULT _updateFont(const FontInfoDesired& fontInfoDesired, FontInfo& fontInfo, const std::unordered_map<std::wstring_view, uint32_t>& features, const std::unordered_map<std::wstring_view, float>& axes) noexcept;
void _resolveFontMetrics(const FontInfoDesired& fontInfoDesired, FontInfo& fontInfo, FontSettings* fontMetrics = nullptr);
[[nodiscard]] bool _updateWithNearbyFontCollection() noexcept;
// AtlasEngine.r.cpp
ATLAS_ATTR_COLD void _recreateAdapter();

View File

@@ -5,7 +5,6 @@
#include <stb_rect_pack.h>
#include <til/flat_set.h>
#include <til/small_vector.h>
#include "Backend.h"

View File

@@ -4,8 +4,6 @@
#include "precomp.h"
#include "gdirenderer.hpp"
#include <til/small_vector.h>
#include "../inc/unicode.hpp"
#pragma hdrstop

View File

@@ -20,8 +20,6 @@ Revision History:
#include "ApiMessageState.h"
#include "IApiRoutines.h"
#include <til/small_vector.h>
class ConsoleProcessHandle;
class ConsoleHandleData;

View File

@@ -868,7 +868,7 @@ class BitmapTests
// C _ D D
// _ _ E _
// _ F F _
til::some<til::rect, 6> expected;
std::vector<til::rect> expected;
expected.push_back(til::rect{ til::point{ 0, 0 }, til::size{ 2, 1 } });
expected.push_back(til::rect{ til::point{ 3, 0 }, til::size{ 1, 1 } });
expected.push_back(til::rect{ til::point{ 0, 1 }, til::size{ 1, 1 } });
@@ -877,7 +877,7 @@ class BitmapTests
expected.push_back(til::rect{ til::point{ 1, 3 }, til::size{ 2, 1 } });
Log::Comment(L"Run the iterator and collect the runs.");
til::some<til::rect, 6> actual;
std::vector<til::rect> actual;
for (auto run : map.runs())
{
actual.push_back(run);
@@ -1006,7 +1006,7 @@ class BitmapTests
// C _ D D
// _ _ E _
// _ F F _
til::some<til::rect, 6> expected;
std::vector<til::rect> expected;
expected.push_back(til::rect{ til::point{ 0, 0 }, til::size{ 2, 1 } });
expected.push_back(til::rect{ til::point{ 3, 0 }, til::size{ 1, 1 } });
expected.push_back(til::rect{ til::point{ 0, 1 }, til::size{ 1, 1 } });
@@ -1015,7 +1015,7 @@ class BitmapTests
expected.push_back(til::rect{ til::point{ 1, 3 }, til::size{ 2, 1 } });
Log::Comment(L"Run the iterator and collect the runs.");
til::some<til::rect, 6> actual;
std::vector<til::rect> actual;
for (auto run : map.runs())
{
actual.push_back(run);

View File

@@ -221,6 +221,24 @@ class PointTests
}
}
TEST_METHOD(Boolean)
{
SetVerifyOutput verifyOutputScope{ VerifyOutputSettings::LogOnlyFailures };
static constexpr til::CoordType values[] = { til::CoordTypeMin, -1, 0, 1, til::CoordTypeMax };
for (const auto x : values)
{
for (const auto y : values)
{
const til::point p{ x, y };
const auto expected = x >= 0 && y >= 0;
const auto actual = static_cast<bool>(p);
VERIFY_ARE_EQUAL(expected, actual);
}
}
}
TEST_METHOD(Addition)
{
Log::Comment(L"Addition of two things that should be in bounds.");

View File

@@ -300,22 +300,26 @@ class RectangleTests
TEST_METHOD(Boolean)
{
BEGIN_TEST_METHOD_PROPERTIES()
TEST_METHOD_PROPERTY(L"Data:left", L"{0,10}")
TEST_METHOD_PROPERTY(L"Data:top", L"{0,10}")
TEST_METHOD_PROPERTY(L"Data:right", L"{0,10}")
TEST_METHOD_PROPERTY(L"Data:bottom", L"{0,10}")
END_TEST_METHOD_PROPERTIES()
SetVerifyOutput verifyOutputScope{ VerifyOutputSettings::LogOnlyFailures };
til::CoordType left, top, right, bottom;
VERIFY_SUCCEEDED_RETURN(TestData::TryGetValue(L"left", left));
VERIFY_SUCCEEDED_RETURN(TestData::TryGetValue(L"top", top));
VERIFY_SUCCEEDED_RETURN(TestData::TryGetValue(L"right", right));
VERIFY_SUCCEEDED_RETURN(TestData::TryGetValue(L"bottom", bottom));
static constexpr til::CoordType values[] = { til::CoordTypeMin, -1, 0, 1, til::CoordTypeMax };
const auto expected = left < right && top < bottom;
const til::rect actual{ left, top, right, bottom };
VERIFY_ARE_EQUAL(expected, (bool)actual);
for (const auto left : values)
{
for (const auto top : values)
{
for (const auto right : values)
{
for (const auto bottom : values)
{
const til::rect r{ left, top, right, bottom };
const auto expected = left >= 0 && top >= 0 && right > left && bottom > top;
const auto actual = static_cast<bool>(r);
VERIFY_ARE_EQUAL(expected, actual);
}
}
}
}
}
TEST_METHOD(OrUnion)
@@ -364,7 +368,7 @@ class RectangleTests
const auto removal = original;
// Since it's the same rectangle, nothing's left. We should get no results.
const til::some<til::rect, 4> expected;
const til::small_vector<til::rect, 4> expected;
const auto actual = original - removal;
VERIFY_ARE_EQUAL(expected, actual);
}
@@ -375,7 +379,7 @@ class RectangleTests
const til::rect removal{ 12, 12, 15, 15 };
// Since they don't overlap, we expect the original to be given back.
const til::some<til::rect, 4> expected{ original };
const til::small_vector<til::rect, 4> expected{ original };
const auto actual = original - removal;
VERIFY_ARE_EQUAL(expected, actual);
}
@@ -401,7 +405,7 @@ class RectangleTests
const til::rect original{ 0, 0, 10, 10 };
const til::rect removal{ -12, 3, 15, 15 };
const til::some<til::rect, 4> expected{
const til::small_vector<til::rect, 4> expected{
til::rect{ original.left, original.top, original.right, removal.top }
};
const auto actual = original - removal;
@@ -428,7 +432,7 @@ class RectangleTests
const til::rect original{ 0, 0, 10, 10 };
const til::rect removal{ 3, 3, 15, 15 };
const til::some<til::rect, 4> expected{
const til::small_vector<til::rect, 4> expected{
til::rect{ original.left, original.top, original.right, removal.top },
til::rect{ original.left, removal.top, removal.left, original.bottom }
};
@@ -452,7 +456,7 @@ class RectangleTests
const til::rect original{ 0, 0, 10, 10 };
const til::rect removal{ 3, 3, 15, 6 };
const til::some<til::rect, 4> expected{
const til::small_vector<til::rect, 4> expected{
til::rect{ original.left, original.top, original.right, removal.top },
til::rect{ original.left, removal.bottom, original.right, original.bottom },
til::rect{ original.left, removal.top, removal.left, removal.bottom }
@@ -483,7 +487,7 @@ class RectangleTests
const til::rect original{ 0, 0, 10, 10 };
const til::rect removal{ 3, 3, 6, 6 };
const til::some<til::rect, 4> expected{
const til::small_vector<til::rect, 4> expected{
til::rect{ original.left, original.top, original.right, removal.top },
til::rect{ original.left, removal.bottom, original.right, original.bottom },
til::rect{ original.left, removal.top, removal.left, removal.bottom },
@@ -706,26 +710,6 @@ class RectangleTests
VERIFY_ARE_EQUAL(expected, rc.size());
}
TEST_METHOD(Empty)
{
BEGIN_TEST_METHOD_PROPERTIES()
TEST_METHOD_PROPERTY(L"Data:left", L"{0,10}")
TEST_METHOD_PROPERTY(L"Data:top", L"{0,10}")
TEST_METHOD_PROPERTY(L"Data:right", L"{0,10}")
TEST_METHOD_PROPERTY(L"Data:bottom", L"{0,10}")
END_TEST_METHOD_PROPERTIES()
til::CoordType left, top, right, bottom;
VERIFY_SUCCEEDED_RETURN(TestData::TryGetValue(L"left", left));
VERIFY_SUCCEEDED_RETURN(TestData::TryGetValue(L"top", top));
VERIFY_SUCCEEDED_RETURN(TestData::TryGetValue(L"right", right));
VERIFY_SUCCEEDED_RETURN(TestData::TryGetValue(L"bottom", bottom));
const auto expected = !(left < right && top < bottom);
const til::rect actual{ left, top, right, bottom };
VERIFY_ARE_EQUAL(expected, actual.empty());
}
TEST_METHOD(ContainsPoint)
{
BEGIN_TEST_METHOD_PROPERTIES()

View File

@@ -147,26 +147,20 @@ class SizeTests
TEST_METHOD(Boolean)
{
const til::size empty;
VERIFY_IS_FALSE(!!empty);
SetVerifyOutput verifyOutputScope{ VerifyOutputSettings::LogOnlyFailures };
const til::size yOnly{ 0, 10 };
VERIFY_IS_FALSE(!!yOnly);
static constexpr til::CoordType values[] = { til::CoordTypeMin, -1, 0, 1, til::CoordTypeMax };
const til::size xOnly{ 10, 0 };
VERIFY_IS_FALSE(!!xOnly);
const til::size both{ 10, 10 };
VERIFY_IS_TRUE(!!both);
const til::size yNegative{ 10, -10 };
VERIFY_IS_FALSE(!!yNegative);
const til::size xNegative{ -10, 10 };
VERIFY_IS_FALSE(!!xNegative);
const til::size bothNegative{ -10, -10 };
VERIFY_IS_FALSE(!!bothNegative);
for (const auto width : values)
{
for (const auto height : values)
{
const til::size s{ width, height };
const auto expected = width > 0 && height > 0;
const auto actual = static_cast<bool>(s);
VERIFY_ARE_EQUAL(expected, actual);
}
}
}
TEST_METHOD(Addition)

View File

@@ -3,8 +3,6 @@
#include "precomp.h"
#include <til/small_vector.h>
using namespace std::literals;
using namespace WEX::Common;
using namespace WEX::Logging;

View File

@@ -1,340 +0,0 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#include "precomp.h"
using namespace WEX::Common;
using namespace WEX::Logging;
using namespace WEX::TestExecution;
class SomeTests
{
TEST_CLASS(SomeTests);
TEST_METHOD(Construct)
{
Log::Comment(L"Default Constructor");
til::some<int, 2> s;
Log::Comment(L"Valid Initializer List Constructor");
til::some<int, 2> t{ 1 };
til::some<int, 2> u{ 1, 2 };
Log::Comment(L"Invalid Initializer List Constructor");
auto f = []() {
til::some<int, 2> v{ 1, 2, 3 };
};
VERIFY_THROWS(f(), std::invalid_argument);
}
TEST_METHOD(Equality)
{
til::some<int, 2> a{ 1, 2 };
til::some<int, 2> b{ 1, 2 };
VERIFY_IS_TRUE(a == b);
til::some<int, 2> c{ 3, 2 };
VERIFY_IS_FALSE(a == c);
til::some<int, 2> d{ 2, 3 };
VERIFY_IS_FALSE(a == d);
til::some<int, 2> e{ 1 };
VERIFY_IS_FALSE(a == e);
}
TEST_METHOD(Inequality)
{
til::some<int, 2> a{ 1, 2 };
til::some<int, 2> b{ 1, 2 };
VERIFY_IS_FALSE(a != b);
til::some<int, 2> c{ 3, 2 };
VERIFY_IS_TRUE(a != c);
til::some<int, 2> d{ 2, 3 };
VERIFY_IS_TRUE(a != d);
til::some<int, 2> e{ 1 };
VERIFY_IS_TRUE(a != e);
}
TEST_METHOD(Fill)
{
til::some<int, 4> s;
const auto val = 12;
s.fill(val);
VERIFY_ARE_EQUAL(s.max_size(), s.size());
for (const auto& i : s)
{
VERIFY_ARE_EQUAL(val, i);
}
}
TEST_METHOD(Swap)
{
til::some<int, 4> a;
til::some<int, 4> b;
const auto aVal = 900;
a.fill(900);
const auto bVal = 45;
b.push_back(45);
const auto aSize = a.size();
const auto bSize = b.size();
a.swap(b);
VERIFY_ARE_EQUAL(aSize, b.size());
VERIFY_ARE_EQUAL(bSize, a.size());
VERIFY_ARE_EQUAL(bVal, a[0]);
for (const auto& i : b)
{
VERIFY_ARE_EQUAL(aVal, i);
}
}
TEST_METHOD(Size)
{
til::some<int, 2> c;
VERIFY_ARE_EQUAL(0u, c.size());
c.push_back(3);
VERIFY_ARE_EQUAL(1u, c.size());
c.push_back(12);
VERIFY_ARE_EQUAL(2u, c.size());
c.pop_back();
VERIFY_ARE_EQUAL(1u, c.size());
c.pop_back();
VERIFY_ARE_EQUAL(0u, c.size());
}
TEST_METHOD(MaxSize)
{
til::some<int, 2> c;
VERIFY_ARE_EQUAL(2u, c.max_size());
c.push_back(3);
VERIFY_ARE_EQUAL(2u, c.max_size());
c.push_back(12);
VERIFY_ARE_EQUAL(2u, c.size());
c.pop_back();
VERIFY_ARE_EQUAL(2u, c.max_size());
c.pop_back();
VERIFY_ARE_EQUAL(2u, c.max_size());
}
TEST_METHOD(PushBack)
{
til::some<int, 1> s;
s.push_back(12);
VERIFY_THROWS(s.push_back(12), std::out_of_range);
}
TEST_METHOD(PopBack)
{
til::some<int, 1> s;
VERIFY_THROWS(s.pop_back(), std::out_of_range);
s.push_back(12);
VERIFY_THROWS(s.push_back(12), std::out_of_range);
}
TEST_METHOD(Empty)
{
til::some<int, 2> s;
VERIFY_IS_TRUE(s.empty());
s.push_back(12);
VERIFY_IS_FALSE(s.empty());
s.pop_back();
VERIFY_IS_TRUE(s.empty());
}
TEST_METHOD(Clear)
{
til::some<int, 2> s;
VERIFY_IS_TRUE(s.empty());
s.push_back(12);
VERIFY_IS_FALSE(s.empty());
VERIFY_ARE_EQUAL(1u, s.size());
s.clear();
VERIFY_IS_TRUE(s.empty());
VERIFY_ARE_EQUAL(0u, s.size());
}
TEST_METHOD(ClearFreesMembers)
{
til::some<std::shared_ptr<int>, 2> s;
auto a = std::make_shared<int>(4);
auto weakA = std::weak_ptr<int>(a);
auto b = std::make_shared<int>(6);
auto weakB = std::weak_ptr<int>(b);
s.push_back(std::move(a));
s.push_back(std::move(b));
VERIFY_IS_FALSE(weakA.expired());
VERIFY_IS_FALSE(weakB.expired());
s.clear();
VERIFY_IS_TRUE(weakA.expired());
VERIFY_IS_TRUE(weakB.expired());
}
TEST_METHOD(Data)
{
til::some<int, 2> s;
const auto one = 1;
const auto two = 2;
s.push_back(one);
s.push_back(two);
auto data = s.data();
VERIFY_ARE_EQUAL(one, *data);
VERIFY_ARE_EQUAL(two, *(data + 1));
}
TEST_METHOD(FrontBack)
{
til::some<int, 2> s;
const auto one = 1;
const auto two = 2;
s.push_back(one);
s.push_back(two);
VERIFY_ARE_EQUAL(one, s.front());
VERIFY_ARE_EQUAL(two, s.back());
}
TEST_METHOD(Indexing)
{
const auto one = 14;
const auto two = 28;
til::some<int, 2> s;
VERIFY_THROWS(s.at(0), std::out_of_range);
VERIFY_THROWS(s.at(1), std::out_of_range);
auto a = s[0];
a = s[1];
s.push_back(one);
VERIFY_ARE_EQUAL(one, s.at(0));
VERIFY_ARE_EQUAL(one, s[0]);
VERIFY_THROWS(s.at(1), std::out_of_range);
a = s[1];
s.push_back(two);
VERIFY_ARE_EQUAL(one, s.at(0));
VERIFY_ARE_EQUAL(one, s[0]);
VERIFY_ARE_EQUAL(two, s.at(1));
VERIFY_ARE_EQUAL(two, s[1]);
s.pop_back();
VERIFY_ARE_EQUAL(one, s.at(0));
VERIFY_ARE_EQUAL(one, s[0]);
VERIFY_THROWS(s.at(1), std::out_of_range);
a = s[1];
s.pop_back();
VERIFY_THROWS(s.at(0), std::out_of_range);
VERIFY_THROWS(s.at(1), std::out_of_range);
a = s[0];
a = s[1];
}
TEST_METHOD(ForwardIter)
{
const int vals[] = { 17, 99 };
const int valLength = ARRAYSIZE(vals);
til::some<int, 2> s;
VERIFY_ARE_EQUAL(s.begin(), s.end());
VERIFY_ARE_EQUAL(s.cbegin(), s.cend());
VERIFY_ARE_EQUAL(s.begin(), s.cbegin());
VERIFY_ARE_EQUAL(s.end(), s.cend());
s.push_back(vals[0]);
s.push_back(vals[1]);
VERIFY_ARE_EQUAL(s.begin() + valLength, s.end());
VERIFY_ARE_EQUAL(s.cbegin() + valLength, s.cend());
auto count = 0;
for (const auto& i : s)
{
VERIFY_ARE_EQUAL(vals[count], i);
++count;
}
VERIFY_ARE_EQUAL(valLength, count);
count = 0;
for (auto i = s.cbegin(); i < s.cend(); ++i)
{
VERIFY_ARE_EQUAL(vals[count], *i);
++count;
}
VERIFY_ARE_EQUAL(valLength, count);
count = 0;
for (auto i = s.begin(); i < s.end(); ++i)
{
VERIFY_ARE_EQUAL(vals[count], *i);
++count;
}
VERIFY_ARE_EQUAL(valLength, count);
}
TEST_METHOD(ReverseIter)
{
const int vals[] = { 17, 99 };
const int valLength = ARRAYSIZE(vals);
til::some<int, 2> s;
VERIFY_ARE_EQUAL(s.rbegin(), s.rend());
VERIFY_ARE_EQUAL(s.crbegin(), s.crend());
VERIFY_ARE_EQUAL(s.rbegin(), s.crbegin());
VERIFY_ARE_EQUAL(s.rend(), s.crend());
s.push_back(vals[0]);
s.push_back(vals[1]);
VERIFY_ARE_EQUAL(s.rbegin() + valLength, s.rend());
VERIFY_ARE_EQUAL(s.crbegin() + valLength, s.crend());
auto count = 0;
for (auto i = s.crbegin(); i < s.crend(); ++i)
{
VERIFY_ARE_EQUAL(vals[valLength - count - 1], *i);
++count;
}
VERIFY_ARE_EQUAL(valLength, count);
count = 0;
for (auto i = s.rbegin(); i < s.rend(); ++i)
{
VERIFY_ARE_EQUAL(vals[valLength - count - 1], *i);
++count;
}
VERIFY_ARE_EQUAL(valLength, count);
}
};

View File

@@ -51,10 +51,10 @@ class UnicodeTests
struct Test
{
std::wstring_view input;
til::some<std::wstring_view, 5> expected;
std::vector<std::wstring_view> expected;
};
static constexpr std::array tests{
const std::array tests{
Test{ L"", {} },
Test{ L"a", { L"a" } },
Test{ L"abc", { L"a", L"b", L"c" } },

View File

@@ -30,7 +30,6 @@ SOURCES = \
RunLengthEncodingTests.cpp \
SizeTests.cpp \
SmallVectorTests.cpp \
SomeTests.cpp \
StaticMapTests.cpp \
string.cpp \
u8u16convertTests.cpp \

View File

@@ -32,7 +32,6 @@
<ClCompile Include="RunLengthEncodingTests.cpp" />
<ClCompile Include="SizeTests.cpp" />
<ClCompile Include="SmallVectorTests.cpp" />
<ClCompile Include="SomeTests.cpp" />
<ClCompile Include="SPSCTests.cpp" />
<ClCompile Include="StaticMapTests.cpp" />
<ClCompile Include="string.cpp" />
@@ -64,7 +63,6 @@
<ClInclude Include="..\..\inc\til\rle.h" />
<ClInclude Include="..\..\inc\til\size.h" />
<ClInclude Include="..\..\inc\til\small_vector.h" />
<ClInclude Include="..\..\inc\til\some.h" />
<ClInclude Include="..\..\inc\til\spsc.h" />
<ClInclude Include="..\..\inc\til\static_map.h" />
<ClInclude Include="..\..\inc\til\string.h" />
@@ -90,4 +88,4 @@
<Import Project="$(SolutionDir)src\common.build.post.props" />
<Import Project="$(SolutionDir)src\common.build.tests.props" />
<Import Project="$(SolutionDir)src\common.nugetversions.targets" />
</Project>
</Project>

View File

@@ -20,7 +20,6 @@
<ClCompile Include="RunLengthEncodingTests.cpp" />
<ClCompile Include="SizeTests.cpp" />
<ClCompile Include="SmallVectorTests.cpp" />
<ClCompile Include="SomeTests.cpp" />
<ClCompile Include="SPSCTests.cpp" />
<ClCompile Include="StaticMapTests.cpp" />
<ClCompile Include="string.cpp" />
@@ -96,9 +95,6 @@
<ClInclude Include="..\..\inc\til\small_vector.h">
<Filter>inc</Filter>
</ClInclude>
<ClInclude Include="..\..\inc\til\some.h">
<Filter>inc</Filter>
</ClInclude>
<ClInclude Include="..\..\inc\til\spsc.h">
<Filter>inc</Filter>
</ClInclude>
@@ -135,4 +131,4 @@
<UniqueIdentifier>{7cf29ba4-d33d-4c3b-82e3-ab73e5a79685}</UniqueIdentifier>
</Filter>
</ItemGroup>
</Project>
</Project>

View File

@@ -0,0 +1,147 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# ITerm2 schemes for the Terminal\n",
"\n",
"This is a little helper script to gather up all the color schemes in [mbadolato/iTerm2-Color-Schemes](https://github.com/mbadolato/iTerm2-Color-Schemes), and put them in a single fragment extension for the Terminal. \n",
"\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"dotnet_interactive": {
"language": "pwsh"
},
"polyglot_notebook": {
"kernelName": "pwsh"
}
},
"outputs": [],
"source": [
"# Clone the repo into the temp directory\n",
"\n",
"cd \"$env:TEMP\"\n",
"if (Test-Path -Path \"$env:TEMP\\iTerm2-Color-Schemes\") {\n",
" Remove-Item -Recurse -Force \"$env:TEMP\\iTerm2-Color-Schemes\"\n",
"}\n",
"git clone --depth 1 https://github.com/mbadolato/iTerm2-Color-Schemes.git\n",
"\n",
"cd \"$env:TEMP\\iTerm2-Color-Schemes\""
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"dotnet_interactive": {
"language": "pwsh"
},
"polyglot_notebook": {
"kernelName": "pwsh"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Importing schemes from 'C:\\Users\\migrie\\AppData\\Local\\Temp\\iTerm2-Color-Schemes'\n",
"Found 319 schemes\n",
"\u001b[K Importing C:\\Users\\migrie\\AppData\\Local\\Temp\\iTerm2-Color-Schemes\\windowsterminal\\zenwritten_light.json Imported json for 319 schemes\n",
"\n",
" Directory: C:\\Users\\migrie\\AppData\\Local\\Microsoft\\Windows Terminal\\Fragments\n",
"\n",
"\u001b[32;1mMode \u001b[0m\u001b[32;1m LastWriteTime\u001b[0m \u001b[32;1;3m Length\u001b[0m\u001b[32;1m Name\u001b[0m\n",
"\u001b[32;1m---- \u001b[0m \u001b[32;1m -------------\u001b[0m \u001b[32;1m ------\u001b[0m \u001b[32;1m----\u001b[0m\n",
"d---- 3/28/2024 6:30 AM \u001b[44;1mAllColorSchemes\u001b[0m\n",
"Fragment json written to C:\\Users\\migrie\\AppData\\Local\\Microsoft\\Windows Terminal\\Fragments\\AllColorSchemes\\schemes.json\n",
"\n"
]
}
],
"source": [
"cd \"$env:TEMP\\iTerm2-Color-Schemes\"\n",
"\n",
"Write-Host \"Importing schemes from '$env:TEMP\\iTerm2-Color-Schemes'\"\n",
"\n",
"# Iterate over all the files in the `windowsterminal` directory\n",
"\n",
"$allSchemesFiles = Get-ChildItem -Path \"$env:TEMP\\iTerm2-Color-Schemes\\windowsterminal\" -Filter *.json\n",
"Write-host \"Found $($allSchemesFiles.Count) schemes\"\n",
"\n",
"$allSchemeJsons = @()\n",
"\n",
"$allSchemesFiles | ForEach-Object {\n",
"\n",
" Write-Host \"`r`e[K Importing $_ \" -NoNewline\n",
" $json = Get-Content $_.FullName -Raw | ConvertFrom-Json\n",
" $allSchemeJsons += $json\n",
"\n",
"}\n",
"Write-Host \"\"\n",
"Write-Host \"Imported json for $($allSchemeJsons.Count) schemes\"\n",
"\n",
"# Create a new fragment json in the temp directory with all the schemes added to a \"schemes\" array\n",
"\n",
"$fragmentJson = @{\n",
" \"schemes\" = $allSchemeJsons\n",
"} | ConvertTo-Json\n",
"\n",
"# Remove the existing fragment json if it exists\n",
"$fragmentDir = $env:LOCALAPPDATA + \"\\Microsoft\\Windows Terminal\\Fragments\\AllColorSchemes\"\n",
"$fragmentPath = $fragmentDir + \"\\schemes.json\"\n",
"if (Test-Path -Path $fragmentPath) {\n",
" Remove-Item -Path $fragmentPath\n",
"}\n",
"# make sure the directory exists\n",
"New-Item -Path $fragmentDir -ItemType Directory -Force\n",
"\n",
"# Write the fragment json to the fragments directory\n",
"Write-Output $fragmentJson | Out-File $fragmentPath -Encoding Utf8\n",
"\n",
"write-host \"Fragment json written to $fragmentPath\""
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"After running this notebook, all the color schemes will be available in the Terminal. You'll probably need to go touch the settings to get them reloaded. "
]
}
],
"metadata": {
"kernelspec": {
"display_name": ".NET (C#)",
"language": "C#",
"name": ".net-csharp"
},
"language_info": {
"name": "polyglot-notebook"
},
"polyglot_notebook": {
"kernelInfo": {
"defaultKernelName": "csharp",
"items": [
{
"aliases": [],
"name": "csharp"
},
{
"aliases": [],
"languageName": "pwsh",
"name": "pwsh"
}
]
}
}
},
"nbformat": 4,
"nbformat_minor": 2
}

View File

@@ -3,8 +3,6 @@
#pragma once
#include <til/small_vector.h>
#define ALT_PRESSED (RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED)
#define CTRL_PRESSED (RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED)
#define MOD_PRESSED (SHIFT_PRESSED | ALT_PRESSED | CTRL_PRESSED)

View File

@@ -17,7 +17,7 @@ namespace Microsoft::Console::Types
{
class Viewport;
using SomeViewports = til::some<Viewport, 4>;
using SomeViewports = til::small_vector<Viewport, 4>;
class Viewport final
{