Compare commits

..

20 Commits

Author SHA1 Message Date
Dustin L. Howett
6b2659bf65 Migrate spelling-0.0.21 changes from main 2021-04-27 09:27:31 -07:00
Dustin L. Howett
466b80496d Migrate spelling-0.0.19 changes from main 2021-04-27 09:27:31 -07:00
Michael Niksa
af2712b09e saving what I have 2021-04-27 09:27:31 -07:00
Michael Niksa
d2372342e2 npos 2021-03-25 13:50:01 -07:00
Michael Niksa
e59f2b8477 make spellcheck happy 2021-03-25 12:26:20 -07:00
Michael Niksa
60ef914956 Handful of PR feedback. 2021-03-25 12:25:26 -07:00
Michael Niksa
cdc5a6a747 Merge branch 'main' into dev/miniksa/rle 2021-03-24 11:02:08 -07:00
Michael Niksa
9b8c9d4f51 substring and hide to_string for non-unit-testing. 2021-01-15 15:30:19 -08:00
Michael Niksa
69538c4ab3 code format 2021-01-14 16:30:16 -08:00
Michael Niksa
324c0942c8 spell check 2021-01-14 16:29:33 -08:00
Michael Niksa
c65161d60e Let full batch assign through to public. Make AttrRow use it. TextAttributeRun is now just a std::pair<> so it fits nicely in the AttrRow which is just a til::rle now. Add tests. 2021-01-14 16:20:14 -08:00
Michael Niksa
b591355103 Drop attrrowtests.cpp. It overlaps/is obsoleted by RunLengthEncodingTests.cpp 2021-01-14 15:45:57 -08:00
Michael Niksa
a1c1d5cc09 Make AttrRow use til::rle directly. 2021-01-14 15:44:34 -08:00
Michael Niksa
67d591b11d Iterators and tests. 2021-01-14 14:45:47 -08:00
Michael Niksa
a692bb2f0f more rle 2021-01-13 15:58:08 -08:00
Michael Niksa
f00ffb0291 Get some tests going. 2021-01-12 16:25:33 -08:00
Michael Niksa
33e9a9b22a It compiles! 2021-01-11 15:50:10 -08:00
Michael Niksa
8114fa0dd0 it doesn't quite work yet, but it's what I'm going for. 2021-01-08 16:32:01 -08:00
Michael Niksa
00ca3f204c Clean out the rect stuff and prep for rle stuff. 2021-01-08 12:52:42 -08:00
Michael Niksa
1ed8ef0847 copy rectangle to rle and add to sources. 2021-01-08 12:48:15 -08:00
863 changed files with 17186 additions and 57877 deletions

View File

@@ -1,12 +0,0 @@
{
"version": 1,
"isRoot": true,
"tools": {
"XamlStyler.Console": {
"version": "3.2008.4",
"commands": [
"xstyler"
]
}
}
}

View File

@@ -1,10 +1,14 @@
name: "Bug report 🐛"
description: Report errors or unexpected behavior
title: ''
labels: ''
assignees: ''
issue_body: true
body:
- type: markdown
attributes:
value: |
Please make sure to [search for existing issues](https://github.com/microsoft/terminal/issues) and [check the FAQ](https://github.com/microsoft/terminal/wiki/Frequently-Asked-Questions-(FAQ)) before filing a new one!
Please make sure to [search for existing issues](https://github.com/microsoft/terminal/issues) before filing a new one!
If this is an application crash, please also provide a [Feedback Hub](https://aka.ms/terminal-feedback-hub) submission link so we can find your diagnostic data on the backend. Use the category "Apps > Windows Terminal" and choose "Share My Feedback" after submission to get the link.
@@ -40,7 +44,7 @@ body:
- type: textarea
attributes:
label: Expected Behavior
description: If you want to include screenshots, paste them into the markdown editor below.
description: If you want to include screenshots, paste them into the markdown editor below the form or follow up with a separate comment.
placeholder: What were you expecting?
validations:
required: false

View File

@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="vswhere" version="2.6.7" />
</packages>
</packages>

77
.vscode/settings.json vendored
View File

@@ -21,85 +21,12 @@
"xloctime": "cpp",
"multi_span": "cpp",
"pointers": "cpp",
"vector": "cpp",
"bitset": "cpp",
"deque": "cpp",
"initializer_list": "cpp",
"list": "cpp",
"queue": "cpp",
"random": "cpp",
"regex": "cpp",
"stack": "cpp",
"xhash": "cpp",
"xtree": "cpp",
"xutility": "cpp",
"span": "cpp",
"string_span": "cpp",
"algorithm": "cpp",
"atomic": "cpp",
"bit": "cpp",
"cctype": "cpp",
"charconv": "cpp",
"chrono": "cpp",
"clocale": "cpp",
"cmath": "cpp",
"compare": "cpp",
"complex": "cpp",
"concepts": "cpp",
"condition_variable": "cpp",
"cstdarg": "cpp",
"cstddef": "cpp",
"cstdint": "cpp",
"cstdio": "cpp",
"cstdlib": "cpp",
"cstring": "cpp",
"ctime": "cpp",
"cwchar": "cpp",
"cwctype": "cpp",
"exception": "cpp",
"filesystem": "cpp",
"fstream": "cpp",
"functional": "cpp",
"iomanip": "cpp",
"ios": "cpp",
"iosfwd": "cpp",
"iostream": "cpp",
"iterator": "cpp",
"limits": "cpp",
"locale": "cpp",
"map": "cpp",
"memory_resource": "cpp",
"mutex": "cpp",
"new": "cpp",
"numeric": "cpp",
"optional": "cpp",
"ostream": "cpp",
"ratio": "cpp",
"set": "cpp",
"shared_mutex": "cpp",
"sstream": "cpp",
"stdexcept": "cpp",
"stop_token": "cpp",
"streambuf": "cpp",
"string": "cpp",
"system_error": "cpp",
"thread": "cpp",
"typeinfo": "cpp",
"unordered_map": "cpp",
"unordered_set": "cpp",
"xfacet": "cpp",
"xiosbase": "cpp",
"xlocale": "cpp",
"xlocbuf": "cpp",
"xlocinfo": "cpp",
"xmemory": "cpp",
"xstddef": "cpp",
"xtr1common": "cpp"
"vector": "cpp"
},
"files.exclude": {
"**/bin/**": true,
"**/obj/**": true,
"**/packages/**": true,
"**/Generated Files/**": true
"**/generated files/**": true
}
}

24
.vscode/tasks.json vendored
View File

@@ -9,16 +9,14 @@
"-Command",
"Import-Module ${workspaceFolder}\\tools\\OpenConsole.psm1;",
"Set-MsBuildDevEnvironment;",
"$project = switch(\"${input:buildProjectChoice}\"){OpenConsole{\"Conhost\\Host_EXE\"} Terminal{\"Terminal\\CascadiaPackage\"} TermControl{\"Terminal\\TerminalControl\"}};",
"$project = switch(\"${input:buildProjectChoice}\"){OpenConsole{\"Conhost\\Host_EXE\"} Terminal{\"Terminal\\CascadiaPackage\"}};",
"$target = switch(\"${input:buildModeChoice}\"){Build{\"\"} Rebuild{\":Rebuild\"} Clean{\":Clean\"}};",
"$target = $project + $target;",
"msbuild",
"${workspaceFolder}\\OpenConsole.sln",
"/p:Configuration=${input:configChoice}",
"/p:Platform=${input:platformChoice}",
"/p:AppxSymbolPackageEnabled=false", // This takes a long time, so false if we don't really need it.
"/t:$target",
"/m", // Parallel builds
"/verbosity:minimal"
],
"problemMatcher": ["$msCompile"],
@@ -48,7 +46,8 @@
],
"problemMatcher": ["$msCompile"],
"group": {
"kind": "build"
"kind": "build",
"isDefault": true
}
},
{
@@ -58,18 +57,6 @@
"args": [
],
"problemMatcher": ["$msCompile"],
},
{
"type": "process",
"label": "Run Code Format",
"command": "powershell.exe",
"args": [
"-Command",
"Import-Module ${workspaceFolder}\\tools\\OpenConsole.psm1;",
"Set-MsBuildDevEnvironment;",
"Invoke-CodeFormat",
],
"problemMatcher": ["$msCompile"],
}
],
"inputs":[
@@ -111,11 +98,10 @@
"description": "OpenConsole or Terminal?",
"options":[
"OpenConsole",
"Terminal",
"TermControl"
"Terminal"
],
"default": "Terminal"
}
]
}
}

View File

@@ -17,7 +17,7 @@
"Microsoft.Net.Component.4.5.TargetingPack",
"Microsoft.VisualStudio.Component.DiagnosticTools",
"Microsoft.VisualStudio.Component.Debugger.JustInTime",
"Microsoft.VisualStudio.Component.Windows10SDK.19041",
"Microsoft.VisualStudio.Component.Windows10SDK.18362",
"Microsoft.VisualStudio.ComponentGroup.UWP.Support",
"Microsoft.VisualStudio.Component.VC.CoreIde",
"Microsoft.VisualStudio.ComponentGroup.NativeDesktop.Core",

View File

@@ -43,7 +43,7 @@ If no existing item describes your issue/feature, great - please file a new issu
* Have a question that you don't see answered in docs, videos, etc.? File an issue
* Want to know if we're planning on building a particular feature? File an issue
* Got a great idea for a new feature? File an issue/request/idea
* Don't understand how to do something? File an issue
* Don't understand how to do something? File an issue/Community Guidance Request
* Found an existing issue that describes yours? Great - upvote and add additional commentary / info / repro-steps / etc.
When you hit "New Issue", select the type of issue closest to what you want to report/ask/request:
@@ -111,13 +111,13 @@ However, some issues/features will require careful thought & formal design befor
Specs help collaborators discuss different approaches to solve a problem, describe how the feature will behave, how the feature will impact the user, what happens if something goes wrong, etc. Driving towards agreement in a spec, before any code is written, often results in simpler code, and less wasted effort in the long run.
Specs will be managed in a very similar manner as code contributions so please follow the "[Fork, Branch and Create your PR](CONTRIBUTING.md#fork-clone-branch-and-create-your-pr)" section below.
Specs will be managed in a very similar manner as code contributions so please follow the "Fork, Branch and Create your PR" below.
### Writing / Contributing-to a Spec
To write/contribute to a spec: fork, branch and commit via PRs, as you would with any code changes.
Specs are written in markdown, stored under the [`\doc\specs`](./doc/specs) folder and named `[issue id] - [spec description].md`.
Specs are written in markdown, stored under the `\doc\spec` folder and named `[issue id] - [spec description].md`.
👉 **It is important to follow the spec templates and complete the requested information**. The available spec templates will help ensure that specs contain the minimum information & decisions necessary to permit development to begin. In particular, specs require you to confirm that you've already discussed the issue/idea with the team in an issue and that you provide the issue ID for reference.

View File

@@ -251,49 +251,3 @@ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
```
# Microsoft Open Source
This product also incorporates source code from other Microsoft open source projects, all licensed under the MIT license.
## `GSL`
**Source**: [https://github.com/microsoft/GSL](https://github.com/microsoft/GSL)
## `Microsoft-UI-XAML`
**Source**: [https://github.com/microsoft/Microsoft-UI-XAML](https://github.com/microsoft/Microsoft-UI-XAML)
## `VirtualDesktopUtils`
**Source**: [https://github.com/microsoft/PowerToys](https://github.com/microsoft/PowerToys)
## `wil`
**Source**: [https://github.com/microsoft/wil](https://github.com/microsoft/wil)
### License
```
The MIT License
Copyright (c) Microsoft Corporation. All rights reserved.
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.
```

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,3 @@
![terminal-logos](https://user-images.githubusercontent.com/48369326/115790869-4c852b00-a37c-11eb-97f1-f61972c7800c.png)
# Welcome to the Windows Terminal, Console and Command-Line repo
This repository contains the source code for:
@@ -243,7 +241,7 @@ Visual Studio.
## Documentation
All project documentation is located at [aka.ms/terminal-docs](https://aka.ms/terminal-docs). If you would like
All project documentation is located at aka.ms/terminal-docs. If you would like
to contribute to the documentation, please submit a pull request on the [Windows
Terminal Documentation repo](https://github.com/MicrosoftDocs/terminal).
@@ -278,7 +276,6 @@ If you would like to ask a question that you feel doesn't warrant an issue
* Carlos Zamora, Developer: [@cazamor_msft](https://twitter.com/cazamor_msft)
* Leon Liang, Developer: [@leonmsft](https://twitter.com/leonmsft)
* Pankaj Bhojwani, Developer
* Leonard Hecker, Developer: [@LeonardHecker](https://twitter.com/LeonardHecker)
## Developer Guidance

View File

@@ -1,221 +0,0 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.31205.134
MinimumVisualStudioVersion = 10.0.40219.1
Project("{C7167F0D-BC9F-4E6E-AFE1-012C56B48DB5}") = "Package", "scratch\ScratchIslandApp\Package\Package.wapproj", "{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SampleAppLib", "scratch\ScratchIslandApp\SampleApp\SampleAppLib.vcxproj", "{A4394404-37F7-41C1-802B-49788D3720E3}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SampleApp", "scratch\ScratchIslandApp\SampleApp\dll\SampleApp.vcxproj", "{26C51792-41A3-4FE0-AB5E-8B69D557BF91}"
ProjectSection(ProjectDependencies) = postProject
{A4394404-37F7-41C1-802B-49788D3720E3} = {A4394404-37F7-41C1-802B-49788D3720E3}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WindowExe", "scratch\ScratchIslandApp\WindowExe\WindowExe.vcxproj", "{B4427499-9FDE-4208-B456-5BC580637633}"
ProjectSection(ProjectDependencies) = postProject
{26C51792-41A3-4FE0-AB5E-8B69D557BF91} = {26C51792-41A3-4FE0-AB5E-8B69D557BF91}
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Common Props", "Common Props", "{53DD5520-E64C-4C06-B472-7CE62CA539C9}"
ProjectSection(SolutionItems) = preProject
src\common.build.post.props = src\common.build.post.props
src\common.build.pre.props = src\common.build.pre.props
src\common.build.tests.props = src\common.build.tests.props
common.openconsole.props = common.openconsole.props
src\cppwinrt.build.post.props = src\cppwinrt.build.post.props
src\cppwinrt.build.pre.props = src\cppwinrt.build.pre.props
src\wap-common.build.post.props = src\wap-common.build.post.props
src\wap-common.build.pre.props = src\wap-common.build.pre.props
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fmt", "src\dep\fmt\fmt.vcxproj", "{6BAE5851-50D5-4934-8D5E-30361A8A40F3}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Types", "src\types\lib\types.vcxproj", "{18D09A24-8240-42D6-8CB6-236EEE820263}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "dependencies", "dependencies", "{75AC9360-76FD-4ABC-AFEC-EF342BD2B3E9}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
AuditMode|ARM64 = AuditMode|ARM64
AuditMode|x64 = AuditMode|x64
AuditMode|x86 = AuditMode|x86
Debug|ARM64 = Debug|ARM64
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Fuzzing|ARM64 = Fuzzing|ARM64
Fuzzing|x64 = Fuzzing|x64
Fuzzing|x86 = Fuzzing|x86
Release|ARM64 = Release|ARM64
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.AuditMode|ARM64.ActiveCfg = Debug|ARM64
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.AuditMode|ARM64.Build.0 = Debug|ARM64
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.AuditMode|ARM64.Deploy.0 = Debug|ARM64
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.AuditMode|x64.ActiveCfg = Debug|x64
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.AuditMode|x64.Build.0 = Debug|x64
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.AuditMode|x64.Deploy.0 = Debug|x64
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.AuditMode|x86.ActiveCfg = Debug|x86
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.AuditMode|x86.Build.0 = Debug|x86
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.AuditMode|x86.Deploy.0 = Debug|x86
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Debug|ARM64.ActiveCfg = Debug|ARM64
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Debug|ARM64.Build.0 = Debug|ARM64
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Debug|ARM64.Deploy.0 = Debug|ARM64
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Debug|x64.ActiveCfg = Debug|x64
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Debug|x64.Build.0 = Debug|x64
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Debug|x64.Deploy.0 = Debug|x64
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Debug|x86.ActiveCfg = Debug|x86
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Debug|x86.Build.0 = Debug|x86
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Debug|x86.Deploy.0 = Debug|x86
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Fuzzing|ARM64.ActiveCfg = Debug|ARM64
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Fuzzing|ARM64.Build.0 = Debug|ARM64
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Fuzzing|ARM64.Deploy.0 = Debug|ARM64
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Fuzzing|x64.ActiveCfg = Debug|x64
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Fuzzing|x64.Build.0 = Debug|x64
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Fuzzing|x64.Deploy.0 = Debug|x64
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Fuzzing|x86.ActiveCfg = Debug|x86
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Fuzzing|x86.Build.0 = Debug|x86
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Fuzzing|x86.Deploy.0 = Debug|x86
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Release|ARM64.ActiveCfg = Release|ARM64
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Release|ARM64.Build.0 = Release|ARM64
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Release|ARM64.Deploy.0 = Release|ARM64
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Release|x64.ActiveCfg = Release|x64
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Release|x64.Build.0 = Release|x64
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Release|x64.Deploy.0 = Release|x64
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Release|x86.ActiveCfg = Release|x86
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Release|x86.Build.0 = Release|x86
{CF31505E-3BAE-4C0A-81D7-F1EB279F40BB}.Release|x86.Deploy.0 = Release|x86
{A4394404-37F7-41C1-802B-49788D3720E3}.AuditMode|ARM64.ActiveCfg = AuditMode|ARM64
{A4394404-37F7-41C1-802B-49788D3720E3}.AuditMode|ARM64.Build.0 = AuditMode|ARM64
{A4394404-37F7-41C1-802B-49788D3720E3}.AuditMode|x64.ActiveCfg = AuditMode|x64
{A4394404-37F7-41C1-802B-49788D3720E3}.AuditMode|x64.Build.0 = AuditMode|x64
{A4394404-37F7-41C1-802B-49788D3720E3}.AuditMode|x86.ActiveCfg = AuditMode|Win32
{A4394404-37F7-41C1-802B-49788D3720E3}.AuditMode|x86.Build.0 = AuditMode|Win32
{A4394404-37F7-41C1-802B-49788D3720E3}.Debug|ARM64.ActiveCfg = Debug|ARM64
{A4394404-37F7-41C1-802B-49788D3720E3}.Debug|ARM64.Build.0 = Debug|ARM64
{A4394404-37F7-41C1-802B-49788D3720E3}.Debug|x64.ActiveCfg = Debug|x64
{A4394404-37F7-41C1-802B-49788D3720E3}.Debug|x64.Build.0 = Debug|x64
{A4394404-37F7-41C1-802B-49788D3720E3}.Debug|x86.ActiveCfg = Debug|Win32
{A4394404-37F7-41C1-802B-49788D3720E3}.Debug|x86.Build.0 = Debug|Win32
{A4394404-37F7-41C1-802B-49788D3720E3}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64
{A4394404-37F7-41C1-802B-49788D3720E3}.Fuzzing|ARM64.Build.0 = Fuzzing|ARM64
{A4394404-37F7-41C1-802B-49788D3720E3}.Fuzzing|x64.ActiveCfg = Fuzzing|x64
{A4394404-37F7-41C1-802B-49788D3720E3}.Fuzzing|x64.Build.0 = Fuzzing|x64
{A4394404-37F7-41C1-802B-49788D3720E3}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32
{A4394404-37F7-41C1-802B-49788D3720E3}.Fuzzing|x86.Build.0 = Fuzzing|Win32
{A4394404-37F7-41C1-802B-49788D3720E3}.Release|ARM64.ActiveCfg = Release|ARM64
{A4394404-37F7-41C1-802B-49788D3720E3}.Release|ARM64.Build.0 = Release|ARM64
{A4394404-37F7-41C1-802B-49788D3720E3}.Release|x64.ActiveCfg = Release|x64
{A4394404-37F7-41C1-802B-49788D3720E3}.Release|x64.Build.0 = Release|x64
{A4394404-37F7-41C1-802B-49788D3720E3}.Release|x86.ActiveCfg = Release|Win32
{A4394404-37F7-41C1-802B-49788D3720E3}.Release|x86.Build.0 = Release|Win32
{26C51792-41A3-4FE0-AB5E-8B69D557BF91}.AuditMode|ARM64.ActiveCfg = AuditMode|ARM64
{26C51792-41A3-4FE0-AB5E-8B69D557BF91}.AuditMode|ARM64.Build.0 = AuditMode|ARM64
{26C51792-41A3-4FE0-AB5E-8B69D557BF91}.AuditMode|x64.ActiveCfg = AuditMode|x64
{26C51792-41A3-4FE0-AB5E-8B69D557BF91}.AuditMode|x64.Build.0 = AuditMode|x64
{26C51792-41A3-4FE0-AB5E-8B69D557BF91}.AuditMode|x86.ActiveCfg = AuditMode|Win32
{26C51792-41A3-4FE0-AB5E-8B69D557BF91}.AuditMode|x86.Build.0 = AuditMode|Win32
{26C51792-41A3-4FE0-AB5E-8B69D557BF91}.Debug|ARM64.ActiveCfg = Debug|ARM64
{26C51792-41A3-4FE0-AB5E-8B69D557BF91}.Debug|ARM64.Build.0 = Debug|ARM64
{26C51792-41A3-4FE0-AB5E-8B69D557BF91}.Debug|x64.ActiveCfg = Debug|x64
{26C51792-41A3-4FE0-AB5E-8B69D557BF91}.Debug|x64.Build.0 = Debug|x64
{26C51792-41A3-4FE0-AB5E-8B69D557BF91}.Debug|x86.ActiveCfg = Debug|Win32
{26C51792-41A3-4FE0-AB5E-8B69D557BF91}.Debug|x86.Build.0 = Debug|Win32
{26C51792-41A3-4FE0-AB5E-8B69D557BF91}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64
{26C51792-41A3-4FE0-AB5E-8B69D557BF91}.Fuzzing|ARM64.Build.0 = Fuzzing|ARM64
{26C51792-41A3-4FE0-AB5E-8B69D557BF91}.Fuzzing|x64.ActiveCfg = Fuzzing|x64
{26C51792-41A3-4FE0-AB5E-8B69D557BF91}.Fuzzing|x64.Build.0 = Fuzzing|x64
{26C51792-41A3-4FE0-AB5E-8B69D557BF91}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32
{26C51792-41A3-4FE0-AB5E-8B69D557BF91}.Fuzzing|x86.Build.0 = Fuzzing|Win32
{26C51792-41A3-4FE0-AB5E-8B69D557BF91}.Release|ARM64.ActiveCfg = Release|ARM64
{26C51792-41A3-4FE0-AB5E-8B69D557BF91}.Release|ARM64.Build.0 = Release|ARM64
{26C51792-41A3-4FE0-AB5E-8B69D557BF91}.Release|x64.ActiveCfg = Release|x64
{26C51792-41A3-4FE0-AB5E-8B69D557BF91}.Release|x64.Build.0 = Release|x64
{26C51792-41A3-4FE0-AB5E-8B69D557BF91}.Release|x86.ActiveCfg = Release|Win32
{26C51792-41A3-4FE0-AB5E-8B69D557BF91}.Release|x86.Build.0 = Release|Win32
{B4427499-9FDE-4208-B456-5BC580637633}.AuditMode|ARM64.ActiveCfg = AuditMode|ARM64
{B4427499-9FDE-4208-B456-5BC580637633}.AuditMode|ARM64.Build.0 = AuditMode|ARM64
{B4427499-9FDE-4208-B456-5BC580637633}.AuditMode|x64.ActiveCfg = AuditMode|x64
{B4427499-9FDE-4208-B456-5BC580637633}.AuditMode|x64.Build.0 = AuditMode|x64
{B4427499-9FDE-4208-B456-5BC580637633}.AuditMode|x86.ActiveCfg = AuditMode|Win32
{B4427499-9FDE-4208-B456-5BC580637633}.AuditMode|x86.Build.0 = AuditMode|Win32
{B4427499-9FDE-4208-B456-5BC580637633}.Debug|ARM64.ActiveCfg = Debug|ARM64
{B4427499-9FDE-4208-B456-5BC580637633}.Debug|ARM64.Build.0 = Debug|ARM64
{B4427499-9FDE-4208-B456-5BC580637633}.Debug|x64.ActiveCfg = Debug|x64
{B4427499-9FDE-4208-B456-5BC580637633}.Debug|x64.Build.0 = Debug|x64
{B4427499-9FDE-4208-B456-5BC580637633}.Debug|x86.ActiveCfg = Debug|Win32
{B4427499-9FDE-4208-B456-5BC580637633}.Debug|x86.Build.0 = Debug|Win32
{B4427499-9FDE-4208-B456-5BC580637633}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64
{B4427499-9FDE-4208-B456-5BC580637633}.Fuzzing|ARM64.Build.0 = Fuzzing|ARM64
{B4427499-9FDE-4208-B456-5BC580637633}.Fuzzing|x64.ActiveCfg = Fuzzing|x64
{B4427499-9FDE-4208-B456-5BC580637633}.Fuzzing|x64.Build.0 = Fuzzing|x64
{B4427499-9FDE-4208-B456-5BC580637633}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32
{B4427499-9FDE-4208-B456-5BC580637633}.Fuzzing|x86.Build.0 = Fuzzing|Win32
{B4427499-9FDE-4208-B456-5BC580637633}.Release|ARM64.ActiveCfg = Release|ARM64
{B4427499-9FDE-4208-B456-5BC580637633}.Release|ARM64.Build.0 = Release|ARM64
{B4427499-9FDE-4208-B456-5BC580637633}.Release|x64.ActiveCfg = Release|x64
{B4427499-9FDE-4208-B456-5BC580637633}.Release|x64.Build.0 = Release|x64
{B4427499-9FDE-4208-B456-5BC580637633}.Release|x86.ActiveCfg = Release|Win32
{B4427499-9FDE-4208-B456-5BC580637633}.Release|x86.Build.0 = Release|Win32
{6BAE5851-50D5-4934-8D5E-30361A8A40F3}.AuditMode|ARM64.ActiveCfg = AuditMode|ARM64
{6BAE5851-50D5-4934-8D5E-30361A8A40F3}.AuditMode|ARM64.Build.0 = AuditMode|ARM64
{6BAE5851-50D5-4934-8D5E-30361A8A40F3}.AuditMode|x64.ActiveCfg = AuditMode|x64
{6BAE5851-50D5-4934-8D5E-30361A8A40F3}.AuditMode|x64.Build.0 = AuditMode|x64
{6BAE5851-50D5-4934-8D5E-30361A8A40F3}.AuditMode|x86.ActiveCfg = AuditMode|Win32
{6BAE5851-50D5-4934-8D5E-30361A8A40F3}.AuditMode|x86.Build.0 = AuditMode|Win32
{6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Debug|ARM64.ActiveCfg = Debug|ARM64
{6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Debug|ARM64.Build.0 = Debug|ARM64
{6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Debug|x64.ActiveCfg = Debug|x64
{6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Debug|x64.Build.0 = Debug|x64
{6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Debug|x86.ActiveCfg = Debug|Win32
{6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Debug|x86.Build.0 = Debug|Win32
{6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64
{6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Fuzzing|ARM64.Build.0 = Fuzzing|ARM64
{6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Fuzzing|x64.ActiveCfg = Fuzzing|x64
{6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Fuzzing|x64.Build.0 = Fuzzing|x64
{6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32
{6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Fuzzing|x86.Build.0 = Fuzzing|Win32
{6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Release|ARM64.ActiveCfg = Release|ARM64
{6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Release|ARM64.Build.0 = Release|ARM64
{6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Release|x64.ActiveCfg = Release|x64
{6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Release|x64.Build.0 = Release|x64
{6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Release|x86.ActiveCfg = Release|Win32
{6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Release|x86.Build.0 = Release|Win32
{18D09A24-8240-42D6-8CB6-236EEE820263}.AuditMode|ARM64.ActiveCfg = AuditMode|ARM64
{18D09A24-8240-42D6-8CB6-236EEE820263}.AuditMode|ARM64.Build.0 = AuditMode|ARM64
{18D09A24-8240-42D6-8CB6-236EEE820263}.AuditMode|x64.ActiveCfg = AuditMode|x64
{18D09A24-8240-42D6-8CB6-236EEE820263}.AuditMode|x64.Build.0 = AuditMode|x64
{18D09A24-8240-42D6-8CB6-236EEE820263}.AuditMode|x86.ActiveCfg = AuditMode|Win32
{18D09A24-8240-42D6-8CB6-236EEE820263}.AuditMode|x86.Build.0 = AuditMode|Win32
{18D09A24-8240-42D6-8CB6-236EEE820263}.Debug|ARM64.ActiveCfg = Debug|ARM64
{18D09A24-8240-42D6-8CB6-236EEE820263}.Debug|ARM64.Build.0 = Debug|ARM64
{18D09A24-8240-42D6-8CB6-236EEE820263}.Debug|x64.ActiveCfg = Debug|x64
{18D09A24-8240-42D6-8CB6-236EEE820263}.Debug|x64.Build.0 = Debug|x64
{18D09A24-8240-42D6-8CB6-236EEE820263}.Debug|x86.ActiveCfg = Debug|Win32
{18D09A24-8240-42D6-8CB6-236EEE820263}.Debug|x86.Build.0 = Debug|Win32
{18D09A24-8240-42D6-8CB6-236EEE820263}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64
{18D09A24-8240-42D6-8CB6-236EEE820263}.Fuzzing|ARM64.Build.0 = Fuzzing|ARM64
{18D09A24-8240-42D6-8CB6-236EEE820263}.Fuzzing|x64.ActiveCfg = Fuzzing|x64
{18D09A24-8240-42D6-8CB6-236EEE820263}.Fuzzing|x64.Build.0 = Fuzzing|x64
{18D09A24-8240-42D6-8CB6-236EEE820263}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32
{18D09A24-8240-42D6-8CB6-236EEE820263}.Fuzzing|x86.Build.0 = Fuzzing|Win32
{18D09A24-8240-42D6-8CB6-236EEE820263}.Release|ARM64.ActiveCfg = Release|ARM64
{18D09A24-8240-42D6-8CB6-236EEE820263}.Release|ARM64.Build.0 = Release|ARM64
{18D09A24-8240-42D6-8CB6-236EEE820263}.Release|x64.ActiveCfg = Release|x64
{18D09A24-8240-42D6-8CB6-236EEE820263}.Release|x64.Build.0 = Release|x64
{18D09A24-8240-42D6-8CB6-236EEE820263}.Release|x86.ActiveCfg = Release|Win32
{18D09A24-8240-42D6-8CB6-236EEE820263}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{6BAE5851-50D5-4934-8D5E-30361A8A40F3} = {75AC9360-76FD-4ABC-AFEC-EF342BD2B3E9}
{18D09A24-8240-42D6-8CB6-236EEE820263} = {75AC9360-76FD-4ABC-AFEC-EF342BD2B3E9}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {05EAE315-9188-4D7B-B889-7D5F480A8915}
EndGlobalSection
EndGlobal

View File

@@ -1,41 +0,0 @@
{
"AttributesTolerance": 1,
"KeepFirstAttributeOnSameLine": true,
"MaxAttributeCharactersPerLine": 0,
"MaxAttributesPerLine": 1,
"NewlineExemptionElements": "RadialGradientBrush, GradientStop, LinearGradientBrush, ScaleTransform, SkewTransform, RotateTransform, TranslateTransform, Trigger, Condition, Setter",
"SeparateByGroups": false,
"AttributeIndentation": 0,
"AttributeIndentationStyle": 1,
"RemoveDesignTimeReferences": false,
"EnableAttributeReordering": true,
"AttributeOrderingRuleGroups": [
"x:Class",
"xmlns, xmlns:x",
"xmlns:*",
"x:Key, Key, x:Name, Name, x:Uid, Uid, Title",
"Grid.Row, Grid.RowSpan, Grid.Column, Grid.ColumnSpan, Canvas.Left, Canvas.Top, Canvas.Right, Canvas.Bottom",
"Width, Height, MinWidth, MinHeight, MaxWidth, MaxHeight",
"Margin, Padding, HorizontalAlignment, VerticalAlignment, HorizontalContentAlignment, VerticalContentAlignment, Panel.ZIndex",
"*:*, *",
"PageSource, PageIndex, Offset, Color, TargetName, Property, Value, StartPoint, EndPoint",
"mc:Ignorable, d:IsDataSource, d:LayoutOverrides, d:IsStaticText",
"Storyboard.*, From, To, Duration"
],
"FirstLineAttributes": "",
"OrderAttributesByName": true,
"PutEndingBracketOnNewLine": false,
"RemoveEndingTagOfEmptyElement": true,
"SpaceBeforeClosingSlash": true,
"RootElementLineBreakRule": 0,
"ReorderVSM": 2,
"ReorderGridChildren": false,
"ReorderCanvasChildren": false,
"ReorderSetters": 0,
"FormatMarkupExtension": true,
"NoNewLineMarkupExtensions": "x:Bind, Binding",
"ThicknessSeparator": 2,
"ThicknessAttributes": "Margin, Padding, BorderThickness, ThumbnailClipMargin",
"FormatOnSave": true,
"CommentPadding": 2,
}

View File

@@ -29,147 +29,4 @@ function GetQueryTestRunsUri
$baseUri = GetAzureDevOpsBaseUri -CollectionUri $CollectionUri -TeamProject $TeamProject
$queryUri = "$baseUri/_apis/test/runs?buildUri=$BuildUri$includeRunDetailsParameter&api-version=5.0"
return $queryUri
}
function Get-HelixJobTypeFromTestRun
{
Param ($testRun)
$testRunSingleResultUri = "$($testRun.url)/results?`$top=1&`$skip=0&api-version=5.1"
$singleTestResult = Invoke-RestMethod -Uri $testRunSingleResultUri -Method Get -Headers $azureDevOpsRestApiHeaders
$count = $singleTestResult.value.Length
if($count -eq 0)
{
# If the count is 0, then results have not yet been reported for this run.
# We only care about completed runs with results, so it is ok to just return 'UNKNOWN' for this run.
return "UNKNOWN"
}
else
{
$info = ConvertFrom-Json $singleTestResult.value.comment
$helixJobId = $info.HelixJobId
$job = Invoke-RestMethodWithRetries "https://helix.dot.net/api/2019-06-17/jobs/${helixJobId}?access_token=${HelixAccessToken}"
return $job.Type
}
}
function Append-HelixAccessTokenToUrl
{
Param ([string]$url, [string]$token)
if($url.Contains("?"))
{
$url = "$($url)&access_token=$($token)"
}
else
{
$url = "$($url)?access_token=$($token)"
}
return $url
}
# The Helix Rest api is sometimes unreliable. So we call these apis with retry logic.
# Note: The Azure DevOps apis are stable and do not need to be called with this retry logic.
$helixApiRetries = 0
$helixApiRetriesMax = 10
function Download-StringWithRetries
{
Param ([string]$fileName, [string]$url)
$result = ""
$done = $false
while(!($done))
{
try
{
Write-Host "Downloading $fileName"
$result = (New-Object System.Net.WebClient).DownloadString($url)
$done = $true
}
catch
{
Write-Host "Failed to download $fileName $($PSItem.Exception)"
$helixApiRetries = $helixApiRetries + 1
if($helixApiRetries -lt $helixApiRetriesMax)
{
Write-Host "Sleep and retry download of $fileName"
Start-Sleep 60
}
else
{
throw "Failed to download $fileName"
}
}
}
return $result
}
function Invoke-RestMethodWithRetries
{
Param ([string]$url,$Headers)
$result = @()
$done = $false
while(!($done))
{
try
{
$result = Invoke-RestMethod -Uri $url -Method Get -Headers $Headers
$done = $true
}
catch
{
Write-Host "Failed to invoke Rest method $($PSItem.Exception)"
$helixApiRetries = $helixApiRetries + 1
if($helixApiRetries -lt $helixApiRetriesMax)
{
Write-Host "Sleep and retry invoke"
Start-Sleep 60
}
else
{
throw "Failed to invoke Rest method"
}
}
}
return $result
}
function Download-FileWithRetries
{
Param ([string]$fileurl, [string]$destination)
$done = $false
while(!($done))
{
try
{
Write-Host "Downloading $destination"
$webClient.DownloadFile($fileurl, $destination)
$done = $true
}
catch
{
Write-Host "Failed to download $destination $($PSItem.Exception)"
$helixApiRetries = $helixApiRetries + 1
if($helixApiRetries -lt $helixApiRetriesMax)
{
Write-Host "Sleep and retry download of $destination"
Start-Sleep 60
}
else
{
throw "Failed to download $destination"
}
}
}
}

View File

@@ -9,7 +9,7 @@ $payloadDir = "HelixPayload\$Configuration\$Platform"
$repoDirectory = Join-Path (Split-Path -Parent $script:MyInvocation.MyCommand.Path) "..\..\"
$nugetPackagesDir = Join-Path (Split-Path -Parent $script:MyInvocation.MyCommand.Path) "packages"
# Create the payload directory. Remove it if it already exists.
If(test-path $payloadDir)
{
@@ -19,13 +19,11 @@ New-Item -ItemType Directory -Force -Path $payloadDir
# Copy files from nuget packages
Copy-Item "$nugetPackagesDir\microsoft.windows.apps.test.1.0.181203002\lib\netcoreapp2.1\*.dll" $payloadDir
Copy-Item "$nugetPackagesDir\Microsoft.Taef.10.60.210621002\build\Binaries\$Platform\*" $payloadDir
Copy-Item "$nugetPackagesDir\Microsoft.Taef.10.60.210621002\build\Binaries\$Platform\NetFx4.5\*" $payloadDir
Copy-Item "$nugetPackagesDir\taef.redist.wlk.10.57.200731005-develop\build\Binaries\$Platform\*" $payloadDir
Copy-Item "$nugetPackagesDir\taef.redist.wlk.10.57.200731005-develop\build\Binaries\$Platform\CoreClr\*" $payloadDir
New-Item -ItemType Directory -Force -Path "$payloadDir\.NETCoreApp2.1\"
Copy-Item "$nugetPackagesDir\runtime.win-$Platform.microsoft.netcore.app.2.1.0\runtimes\win-$Platform\lib\netcoreapp2.1\*" "$payloadDir\.NETCoreApp2.1\"
Copy-Item "$nugetPackagesDir\runtime.win-$Platform.microsoft.netcore.app.2.1.0\runtimes\win-$Platform\native\*" "$payloadDir\.NETCoreApp2.1\"
New-Item -ItemType Directory -Force -Path "$payloadDir\content\"
Copy-Item "$nugetPackagesDir\Microsoft.Internal.Windows.Terminal.TestContent.1.0.1\content\*" "$payloadDir\content\"
function Copy-If-Exists
{
@@ -54,13 +52,3 @@ Copy-Item "build\helix\HelixTestHelpers.cs" "$payloadDir"
Copy-Item "build\helix\runtests.cmd" $payloadDir
Copy-Item "build\helix\InstallTestAppDependencies.ps1" "$payloadDir"
Copy-Item "build\Helix\EnsureMachineState.ps1" "$payloadDir"
# Copy the APPX package from the 'drop' artifact dir
Copy-Item "$repoDirectory\Artifacts\$ArtifactName\appx\CascadiaPackage_0.0.1.0_$Platform.msix" $payloadDir\CascadiaPackage.zip
# Rename it to extension of ZIP because Expand-Archive is real sassy on the build machines
# and refuses to unzip it because of its file extension while on a desktop, it just
# does the job without complaining.
# Extract the APPX package
Expand-Archive -LiteralPath $payloadDir\CascadiaPackage.zip -DestinationPath $payloadDir\appx

View File

@@ -9,6 +9,11 @@ Param(
$helixLinkFile = "$OutputFolder\LinksToHelixTestFiles.html"
$accessTokenParam = ""
if($HelixAccessToken)
{
$accessTokenParam = "?access_token=$HelixAccessToken"
}
function Generate-File-Links
{
@@ -40,69 +45,66 @@ $azureDevOpsRestApiHeaders = @{
$queryUri = GetQueryTestRunsUri -CollectionUri $CollectionUri -TeamProject $TeamProject -BuildUri $BuildUri -IncludeRunDetails
Write-Host "queryUri = $queryUri"
$testRuns = Invoke-RestMethodWithRetries $queryUri -Headers $azureDevOpsRestApiHeaders
$testRuns = Invoke-RestMethod -Uri $queryUri -Method Get -Headers $azureDevOpsRestApiHeaders
$webClient = New-Object System.Net.WebClient
[System.Collections.Generic.List[string]]$workItems = @()
foreach ($testRun in $testRuns.value)
{
Write-Host "testRunUri = $testRun.url"
$testResults = Invoke-RestMethodWithRetries "$($testRun.url)/results?api-version=5.0" -Headers $azureDevOpsRestApiHeaders
$testResults = Invoke-RestMethod -Uri "$($testRun.url)/results?api-version=5.0" -Method Get -Headers $azureDevOpsRestApiHeaders
$isTestRunNameShown = $false
foreach ($testResult in $testResults.value)
{
$info = ConvertFrom-Json $testResult.comment
$helixJobId = $info.HelixJobId
$helixWorkItemName = $info.HelixWorkItemName
$workItem = "$helixJobId-$helixWorkItemName"
Write-Host "Helix Work Item = $workItem"
if (-not $workItems.Contains($workItem))
if ("comment" -in $testResult)
{
$workItems.Add($workItem)
$filesQueryUri = "https://helix.dot.net/api/2019-06-17/jobs/$helixJobId/workitems/$helixWorkItemName/files$accessTokenParam"
$files = Invoke-RestMethodWithRetries $filesQueryUri
$info = ConvertFrom-Json $testResult.comment
$helixJobId = $info.HelixJobId
$helixWorkItemName = $info.HelixWorkItemName
$screenShots = $files | where { $_.Name.EndsWith(".jpg") }
$dumps = $files | where { $_.Name.EndsWith(".dmp") }
$pgcFiles = $files | where { $_.Name.EndsWith(".pgc") }
if ($screenShots.Count + $dumps.Count + $pgcFiles.Count -gt 0)
$workItem = "$helixJobId-$helixWorkItemName"
if (-not $workItems.Contains($workItem))
{
if(-Not $isTestRunNameShown)
$workItems.Add($workItem)
$filesQueryUri = "https://helix.dot.net/api/2019-06-17/jobs/$helixJobId/workitems/$helixWorkItemName/files$accessTokenParam"
$files = Invoke-RestMethod -Uri $filesQueryUri -Method Get
$screenShots = $files | where { $_.Name.EndsWith(".jpg") }
$dumps = $files | where { $_.Name.EndsWith(".dmp") }
$pgcFiles = $files | where { $_.Name.EndsWith(".pgc") }
if ($screenShots.Count + $dumps.Count + $pgcFiles.Count -gt 0)
{
Out-File -FilePath $helixLinkFile -Append -InputObject "<h2>$($testRun.name)</h2>"
$isTestRunNameShown = $true
}
Out-File -FilePath $helixLinkFile -Append -InputObject "<h3>$helixWorkItemName</h3>"
Generate-File-Links $screenShots "Screenshots"
Generate-File-Links $dumps "CrashDumps"
Generate-File-Links $pgcFiles "PGC files"
$misc = $files | where { ($screenShots -NotContains $_) -And ($dumps -NotContains $_) -And ($visualTreeVerificationFiles -NotContains $_) -And ($pgcFiles -NotContains $_) }
Generate-File-Links $misc "Misc"
foreach($pgcFile in $pgcFiles)
{
$flavorPath = $testResult.automatedTestName.Split('.')[0]
$archPath = $testResult.automatedTestName.Split('.')[1]
$fileName = $pgcFile.Name
$fullPath = "$OutputFolder\PGO\$flavorPath\$archPath"
$destination = "$fullPath\$fileName"
Write-Host "Copying $($pgcFile.Name) to $destination"
if (-Not (Test-Path $fullPath))
if(-Not $isTestRunNameShown)
{
New-Item $fullPath -ItemType Directory
Out-File -FilePath $helixLinkFile -Append -InputObject "<h2>$($testRun.name)</h2>"
$isTestRunNameShown = $true
}
Out-File -FilePath $helixLinkFile -Append -InputObject "<h3>$helixWorkItemName</h3>"
Generate-File-Links $screenShots "Screenshots"
Generate-File-Links $dumps "CrashDumps"
Generate-File-Links $pgcFiles "PGC files"
$misc = $files | where { ($screenShots -NotContains $_) -And ($dumps -NotContains $_) -And ($visualTreeVerificationFiles -NotContains $_) -And ($pgcFiles -NotContains $_) }
Generate-File-Links $misc "Misc"
$link = $pgcFile.Link
foreach($pgcFile in $pgcFiles)
{
$flavorPath = $pgcFile.Name.Split('.')[0]
$archPath = $pgcFile.Name.Split('.')[1]
$fileName = $pgcFile.Name.Remove(0, $flavorPath.length + $archPath.length + 2)
$fullPath = "$OutputFolder\PGO\$flavorPath\$archPath"
$destination = "$fullPath\$fileName"
Write-Host "Downloading $link to $destination"
Write-Host "Copying $($pgcFile.Name) to $destination"
Download-FileWithRetries $link $destination
if (-Not (Test-Path $fullPath))
{
New-Item $fullPath -ItemType Directory
}
$link = "$($pgcFile.Link)$accessTokenParam"
$webClient.DownloadFile($link, $destination)
}
}
}
}

View File

@@ -13,8 +13,6 @@
</ItemGroup>
<!-- These .proj files are generated by the build machine prior to running tests via GenerateTestProjFile.ps1. -->
<Import Project="$(ProjFilesPath)\$(Configuration)\$(Platform)\RunTestsInHelix-TerminalAppLocalTests.proj" Condition=" '$(TestSuite)'=='DevTestSuite' " />
<Import Project="$(ProjFilesPath)\$(Configuration)\$(Platform)\RunTestsInHelix-SettingsModelLocalTests.proj" Condition=" '$(TestSuite)'=='DevTestSuite' " />
<Import Project="$(ProjFilesPath)\$(Configuration)\$(Platform)\RunTestsInHelix-HostTestsUIA.proj" Condition=" '$(TestSuite)'=='DevTestSuite' " />
<Import Project="$(ProjFilesPath)\$(Configuration)\$(Platform)\RunTestsInHelix-WindowsTerminalUIATests.proj" Condition=" '$(TestSuite)'=='PgoInstrumentationSuite' " />
<Import Project="$(ProjFilesPath)\RunTestsInHelix-TerminalAppLocalTests.proj" Condition=" '$(TestSuite)'=='DevTestSuite' " />
<Import Project="$(ProjFilesPath)\RunTestsInHelix-HostTestsUIA.proj" Condition=" '$(TestSuite)'=='DevTestSuite' " />
</Project>

View File

@@ -1,8 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="MUXCustomBuildTasks" version="1.0.48" targetFramework="native" />
<package id="Microsoft.Internal.Windows.Terminal.TestContent" version="1.0.1" />
<package id="Microsoft.Taef" version="10.60.210621002" targetFramework="native" />
<package id="TAEF.Redist.Wlk" version="10.57.200731005-develop" targetFramework="native" />
<package id="microsoft.windows.apps.test" version="1.0.181203002" targetFramework="native" />
<package id="runtime.win-x86.microsoft.netcore.app" version="2.1.0" targetFramework="native" />
<package id="runtime.win-x64.microsoft.netcore.app" version="2.1.0" targetFramework="native" />

View File

@@ -28,7 +28,7 @@ echo %TIME%
powershell -ExecutionPolicy Bypass .\InstallTestAppDependencies.ps1
echo %TIME%
set testBinaryCandidates=TerminalApp.LocalTests.dll SettingsModel.LocalTests.dll Conhost.UIA.Tests.dll WindowsTerminal.UIA.Tests.dll
set testBinaryCandidates=TerminalApp.LocalTests.dll SettingsModel.LocalTests.dll Conhost.UIA.Tests.dll
set testBinaries=
for %%B in (%testBinaryCandidates%) do (
if exist %%B (
@@ -46,6 +46,7 @@ move te.wtl te_original.wtl
copy /y te_original.wtl %HELIX_WORKITEM_UPLOAD_ROOT%
copy /y WexLogFileOutput\*.jpg %HELIX_WORKITEM_UPLOAD_ROOT%
for /f "tokens=* delims=" %%a in ('dir /b *.pgc') do ren "%%a" "%testnameprefix%.%%~na.pgc"
copy /y *.pgc %HELIX_WORKITEM_UPLOAD_ROOT%
set FailedTestQuery=

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="MUXCustomBuildTasks" version="1.0.48" targetFramework="native" />
<package id="Microsoft.Taef" version="10.60.210621002" targetFramework="native" />
<package id="TAEF.Redist.Wlk" version="10.57.200731005-develop" targetFramework="native" />
</packages>

View File

@@ -1,27 +0,0 @@
trigger: none
pr: none
variables:
- name: runCodesignValidationInjectionBG
value: false
# 0.0.yyMM.dd##
# 0.0.1904.0900
name: 0.0.$(Date:yyMM).$(Date:dd)$(Rev:rr)
stages:
- stage: Build_x64
displayName: Build x64
dependsOn: []
condition: succeeded()
jobs:
- template: ./templates/build-console-pgo.yml
parameters:
platform: x64
- stage: Publish_PGO_Databases
displayName: Publish PGO databases
dependsOn: ['Build_x64']
jobs:
- template: ./templates/pgo-build-and-publish-nuget-job.yml
parameters:
pgoArtifact: 'PGO'

View File

@@ -1,487 +1,48 @@
# This build should never run as CI or against a pull request.
trigger: none
pr: none
pool:
name: WinDevPool-L
demands: ImageOverride -equals WinDevVS16-latest
parameters:
- name: branding
displayName: "Branding (Build Type)"
type: string
default: Release
values:
- Release
- Preview
- name: buildTerminal
displayName: "Build Windows Terminal MSIX"
type: boolean
default: true
- name: buildTerminalVPack
displayName: "Build Windows Terminal VPack"
type: boolean
default: false
- name: buildWPF
displayName: "Build Terminal WPF Control"
type: boolean
default: false
- name: pgoBuildMode
displayName: "PGO Build Mode"
type: string
default: Optimize
values:
- Optimize
- Instrument
- None
- name: buildConfigurations
type: object
default:
- Release
- name: buildPlatforms
type: object
default:
- x64
- x86
- arm64
variables:
TerminalInternalPackageVersion: "0.0.7"
baseYearForVersioning: 2019 # Used by build-console-int
versionMajor: 0
versionMinor: 1
name: $(BuildDefinitionName)_$(date:yyMM).$(date:dd)$(rev:rrr)
resources:
repositories:
- repository: self
type: git
ref: main
# When we move off PackageES for Versioning, we'll need to switch
# name to this format. For now, though, we need to use DayOfYear.Rev
# to unique our builds, as mandated by PackageES's Setup task.
# name: '$(versionMajor).$(versionMinor).$(DayOfYear)$(Rev:r).0'
#
# Build name/version number above must end with .0 to make the
# store publication machinery happy.
name: 'Terminal_$(date:yyMM).$(date:dd)$(rev:rrr)'
# Build Arguments:
# WindowsTerminalOfficialBuild=[true,false]
# true - this is running on our build agent
# false - running locally
# WindowsTerminalBranding=[Dev,Preview,Release]
# <none> - Development build resources (default)
# Preview - Preview build resources
# Release - regular build resources
jobs:
- job: Build
strategy:
matrix:
${{ each config in parameters.buildConfigurations }}:
${{ each platform in parameters.buildPlatforms }}:
${{ config }}_${{ platform }}:
BuildConfiguration: ${{ config }}
BuildPlatform: ${{ platform }}
displayName: Build
cancelTimeoutInMinutes: 1
steps:
- checkout: self
clean: true
submodules: true
persistCredentials: True
- task: PkgESSetupBuild@12
displayName: Package ES - Setup Build
inputs:
disableOutputRedirect: true
- task: PowerShell@2
displayName: Rationalize Build Platform
inputs:
targetType: inline
script: >-
$Arch = "$(BuildPlatform)"
- template: ./templates/build-console-audit-job.yml
parameters:
platform: x64
If ($Arch -Eq "x86") { $Arch = "Win32" }
- template: ./templates/build-console-int.yml
parameters:
platform: x64
additionalBuildArguments: /p:WindowsTerminalOfficialBuild=true;WindowsTerminalBranding=Preview
Write-Host "##vso[task.setvariable variable=RationalizedBuildPlatform]${Arch}"
- task: NuGetToolInstaller@1
displayName: Use NuGet 5.10
inputs:
versionSpec: 5.10
- task: NuGetCommand@2
displayName: NuGet custom
inputs:
command: custom
selectOrConfig: config
nugetConfigPath: NuGet.Config
arguments: restore OpenConsole.sln -SolutionDirectory $(Build.SourcesDirectory)
- task: UniversalPackages@0
displayName: Download terminal-internal Universal Package
inputs:
feedListDownload: 2b3f8893-a6e8-411f-b197-a9e05576da48
packageListDownload: e82d490c-af86-4733-9dc4-07b772033204
versionListDownload: $(TerminalInternalPackageVersion)
- task: TouchdownBuildTask@1
displayName: Download Localization Files
inputs:
teamId: 7105
authId: $(TouchdownAppId)
authKey: $(TouchdownAppKey)
resourceFilePath: >-
src\cascadia\TerminalApp\Resources\en-US\Resources.resw
- template: ./templates/build-console-int.yml
parameters:
platform: x86
additionalBuildArguments: /p:WindowsTerminalOfficialBuild=true;WindowsTerminalBranding=Preview
src\cascadia\TerminalControl\Resources\en-US\Resources.resw
- template: ./templates/build-console-int.yml
parameters:
platform: arm64
additionalBuildArguments: /p:WindowsTerminalOfficialBuild=true;WindowsTerminalBranding=Preview
src\cascadia\TerminalConnection\Resources\en-US\Resources.resw
- template: ./templates/check-formatting.yml
src\cascadia\TerminalSettingsModel\Resources\en-US\Resources.resw
src\cascadia\TerminalSettingsEditor\Resources\en-US\Resources.resw
src\cascadia\WindowsTerminalUniversal\Resources\en-US\Resources.resw
src\cascadia\CascadiaPackage\Resources\en-US\Resources.resw
appendRelativeDir: true
localizationTarget: false
pseudoSetting: Included
- task: PowerShell@2
displayName: Move Loc files one level up
inputs:
targetType: inline
script: >-
$Files = Get-ChildItem . -R -Filter 'Resources.resw' | ? FullName -Like '*en-US\*\Resources.resw'
$Files | % { Move-Item -Verbose $_.Directory $_.Directory.Parent.Parent -EA:Ignore }
pwsh: true
- task: PowerShell@2
displayName: Generate NOTICE.html from NOTICE.md
inputs:
filePath: .\build\scripts\Generate-ThirdPartyNotices.ps1
arguments: -MarkdownNoticePath .\NOTICE.md -OutputPath .\src\cascadia\CascadiaPackage\NOTICE.html
pwsh: true
- ${{ if eq(parameters.pgoBuildMode, 'Optimize') }}:
- task: PowerShell@2
displayName: Restore PGO Database
inputs:
filePath: tools/PGODatabase/restore-pgodb.ps1
workingDirectory: $(Build.SourcesDirectory)\tools\PGODatabase
- ${{ if eq(parameters.buildTerminal, true) }}:
- task: VSBuild@1
displayName: Build solution **\OpenConsole.sln
inputs:
solution: '**\OpenConsole.sln'
vsVersion: 16.0
msbuildArgs: /p:WindowsTerminalOfficialBuild=true /p:WindowsTerminalBranding=${{ parameters.branding }} /t:Terminal\CascadiaPackage;Terminal\WindowsTerminalUniversal /p:WindowsTerminalReleaseBuild=true /bl:$(Build.SourcesDirectory)\msbuild.binlog
platform: $(BuildPlatform)
configuration: $(BuildConfiguration)
clean: true
maximumCpuCount: true
- task: PublishBuildArtifacts@1
displayName: 'Publish Artifact: binlog'
condition: failed()
continueOnError: True
inputs:
PathtoPublish: $(Build.SourcesDirectory)\msbuild.binlog
ArtifactName: binlog-$(BuildPlatform)
- ${{ if eq(parameters.pgoBuildMode, 'Optimize') }}:
- task: PowerShell@2
displayName: Validate binaries are optimized
condition: and(succeeded(), eq(variables['BuildPlatform'], 'x64'))
inputs:
targetType: inline
script: >-
$Binaries = 'OpenConsole.exe', 'WindowsTerminal.exe', 'TerminalApp.dll', 'TerminalConnection.dll', 'Microsoft.Terminal.Control.dll', 'Microsoft.Terminal.Remoting.dll', 'Microsoft.Terminal.Settings.Editor.dll', 'Microsoft.Terminal.Settings.Model.dll'
foreach ($BinFile in $Binaries) {
& "$(Build.SourcesDirectory)\tools\PGODatabase\verify-pgo.ps1" "$(Build.SourcesDirectory)/src/cascadia/CascadiaPackage/bin/$(BuildPlatform)/$(BuildConfiguration)/$BinFile"
}
- task: PowerShell@2
displayName: Check MSIX for common regressions
inputs:
targetType: inline
script: >-
$Package = Get-ChildItem -Recurse -Filter "CascadiaPackage_*.msix"
.\build\scripts\Test-WindowsTerminalPackage.ps1 -Verbose -Path $Package.FullName
pwsh: true
- ${{ if eq(parameters.buildWPF, true) }}:
- task: VSBuild@1
displayName: Build solution **\OpenConsole.sln for PublicTerminalCore
condition: and(succeeded(), ne(variables['BuildPlatform'], 'arm64'))
inputs:
solution: '**\OpenConsole.sln'
vsVersion: 16.0
msbuildArgs: /p:WindowsTerminalOfficialBuild=true /p:WindowsTerminalBranding=${{ parameters.branding }} /p:WindowsTerminalReleaseBuild=true /t:Terminal\wpf\PublicTerminalCore
platform: $(BuildPlatform)
configuration: $(BuildConfiguration)
- task: PowerShell@2
displayName: Source Index PDBs
inputs:
filePath: build\scripts\Index-Pdbs.ps1
arguments: -SearchDir '$(Build.SourcesDirectory)' -SourceRoot '$(Build.SourcesDirectory)' -recursive -Verbose -CommitId $(Build.SourceVersion)
errorActionPreference: silentlyContinue
- task: ComponentGovernanceComponentDetection@0
displayName: Component Detection
- task: PowerShell@2
displayName: Run Unit Tests
condition: and(succeeded(), or(eq(variables['BuildPlatform'], 'x64'), eq(variables['BuildPlatform'], 'x86')))
enabled: False
inputs:
filePath: build\scripts\Run-Tests.ps1
arguments: -MatchPattern '*unit.test*.dll' -Platform '$(RationalizedBuildPlatform)' -Configuration '$(BuildConfiguration)'
- task: PowerShell@2
displayName: Run Feature Tests
condition: and(succeeded(), eq(variables['BuildPlatform'], 'x64'))
enabled: False
inputs:
filePath: build\scripts\Run-Tests.ps1
arguments: -MatchPattern '*feature.test*.dll' -Platform '$(RationalizedBuildPlatform)' -Configuration '$(BuildConfiguration)'
- ${{ if eq(parameters.buildTerminal, true) }}:
- task: CopyFiles@2
displayName: Copy *.appx/*.msix to Artifacts
inputs:
Contents: >-
**/*.appx
**/*.msix
**/*.appxsym
!**/Microsoft.VCLibs*.appx
TargetFolder: $(Build.ArtifactStagingDirectory)/appx
OverWrite: true
flattenFolders: true
- task: PublishBuildArtifacts@1
displayName: Publish Artifact (appx)
inputs:
PathtoPublish: $(Build.ArtifactStagingDirectory)/appx
ArtifactName: appx-$(BuildPlatform)-$(BuildConfiguration)
- ${{ if eq(parameters.buildWPF, true) }}:
- task: CopyFiles@2
displayName: Copy PublicTerminalCore.dll to Artifacts
condition: and(succeeded(), ne(variables['BuildPlatform'], 'arm64'))
inputs:
Contents: >-
**/PublicTerminalCore.dll
**/api-ms-win-core-synch-l1-2-0.dll
TargetFolder: $(Build.ArtifactStagingDirectory)/wpf
OverWrite: true
flattenFolders: true
- task: PublishBuildArtifacts@1
displayName: Publish Artifact (PublicTerminalCore)
condition: and(succeeded(), ne(variables['BuildPlatform'], 'arm64'))
inputs:
PathtoPublish: $(Build.ArtifactStagingDirectory)/wpf
ArtifactName: wpf-dll-$(BuildPlatform)-$(BuildConfiguration)
- task: PublishSymbols@2
displayName: Publish symbols path
continueOnError: True
inputs:
SearchPattern: '**/*.pdb'
IndexSources: false
SymbolServerType: TeamServices
- ${{ if eq(parameters.buildTerminal, true) }}:
- job: BundleAndSign
displayName: Create and sign AppX/MSIX bundles
dependsOn: Build
steps:
- checkout: self
clean: true
submodules: true
persistCredentials: True
- task: PkgESSetupBuild@12
displayName: Package ES - Setup Build
inputs:
disableOutputRedirect: true
- task: DownloadBuildArtifacts@0
displayName: Download Artifacts (*.appx, *.msix)
inputs:
downloadType: specific
itemPattern: >-
**/*.msix
**/*.appx
extractTars: false
- task: PowerShell@2
displayName: Create WindowsTerminal*.msixbundle
inputs:
filePath: build\scripts\Create-AppxBundle.ps1
arguments: -InputPath "$(System.ArtifactsDirectory)" -ProjectName CascadiaPackage -BundleVersion 0.0.0.0 -OutputPath "$(System.ArtifactsDirectory)\Microsoft.WindowsTerminal_$(XES_APPXMANIFESTVERSION)_8wekyb3d8bbwe.msixbundle"
- task: PowerShell@2
displayName: Create WindowsTerminalUniversal*.msixbundle
inputs:
filePath: build\scripts\Create-AppxBundle.ps1
arguments: -InputPath "$(System.ArtifactsDirectory)" -ProjectName WindowsTerminalUniversal -BundleVersion $(XES_APPXMANIFESTVERSION) -OutputPath "$(System.ArtifactsDirectory)\Microsoft.WindowsTerminalUniversal_$(XES_APPXMANIFESTVERSION)_8wekyb3d8bbwe.msixbundle"
- task: EsrpCodeSigning@1
displayName: Submit *.msixbundle to ESRP for code signing
inputs:
ConnectedServiceName: 9d6d2960-0793-4d59-943e-78dcb434840a
FolderPath: $(System.ArtifactsDirectory)
Pattern: Microsoft.WindowsTerminal*.msixbundle
UseMinimatch: true
signConfigType: inlineSignParams
inlineOperation: >-
[
{
"KeyCode": "Dynamic",
"CertTemplateName": "WINMSAPP1ST",
"CertSubjectName": "CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US",
"OperationCode": "SigntoolSign",
"Parameters": {
"OpusName": "Microsoft",
"OpusInfo": "http://www.microsoft.com",
"FileDigest": "/fd \"SHA256\"",
"TimeStamp": "/tr \"http://rfc3161.gtm.corp.microsoft.com/TSS/HttpTspServer\" /td sha256"
},
"ToolName": "sign",
"ToolVersion": "1.0"
},
{
"KeyCode": "Dynamic",
"CertTemplateName": "WINMSAPP1ST",
"CertSubjectName": "CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US",
"OperationCode": "SigntoolVerify",
"Parameters": {},
"ToolName": "sign",
"ToolVersion": "1.0"
}
]
- task: PublishBuildArtifacts@1
displayName: 'Publish Artifact: appxbundle-signed'
inputs:
PathtoPublish: $(System.ArtifactsDirectory)
ArtifactName: appxbundle-signed
- ${{ if eq(parameters.buildWPF, true) }}:
- job: PackageAndSignWPF
strategy:
matrix:
${{ each config in parameters.buildConfigurations }}:
${{ config }}:
BuildConfiguration: ${{ config }}
displayName: Create NuGet Package (WPF Terminal Control)
dependsOn: Build
steps:
- checkout: self
clean: true
submodules: true
persistCredentials: True
- task: PkgESSetupBuild@12
displayName: Package ES - Setup Build
inputs:
disableOutputRedirect: true
- task: DownloadBuildArtifacts@0
displayName: Download x86 PublicTerminalCore
inputs:
artifactName: wpf-dll-x86-$(BuildConfiguration)
itemPattern: '**/*.dll'
downloadPath: bin\Win32\$(BuildConfiguration)\
extractTars: false
- task: DownloadBuildArtifacts@0
displayName: Download x64 PublicTerminalCore
inputs:
artifactName: wpf-dll-x64-$(BuildConfiguration)
itemPattern: '**/*.dll'
downloadPath: bin\x64\$(BuildConfiguration)\
extractTars: false
- task: PowerShell@2
displayName: Move downloaded artifacts up a level
inputs:
targetType: inline
# Find all artifact files and move them up a directory. Ugh.
script: >-
Get-ChildItem bin -Recurse -Directory -Filter wpf-dll-* | % {
$_ | Get-ChildItem -Recurse -File | % {
Move-Item -Verbose $_.FullName $_.Directory.Parent.FullName
}
}
- task: NuGetToolInstaller@1
displayName: Use NuGet 5.10.0
inputs:
versionSpec: 5.10.0
- task: NuGetCommand@2
displayName: NuGet restore copy
inputs:
selectOrConfig: config
nugetConfigPath: NuGet.Config
- task: VSBuild@1
displayName: Build solution **\OpenConsole.sln for WPF Control
inputs:
solution: '**\OpenConsole.sln'
vsVersion: 16.0
msbuildArgs: /p:WindowsTerminalReleaseBuild=$(UseReleaseBranding);Version=$(XES_PACKAGEVERSIONNUMBER) /t:Pack
platform: Any CPU
configuration: $(BuildConfiguration)
maximumCpuCount: true
- task: PublishSymbols@2
displayName: Publish symbols path
continueOnError: True
inputs:
SearchPattern: '**/*.pdb'
IndexSources: false
SymbolServerType: TeamServices
SymbolsArtifactName: Symbols_WPF_$(BuildConfiguration)
- task: CopyFiles@2
displayName: Copy *.nupkg to Artifacts
inputs:
Contents: '**/*Wpf*.nupkg'
TargetFolder: $(Build.ArtifactStagingDirectory)/nupkg
OverWrite: true
flattenFolders: true
- task: EsrpCodeSigning@1
displayName: Submit *.nupkg to ESRP for code signing
inputs:
ConnectedServiceName: 9d6d2960-0793-4d59-943e-78dcb434840a
FolderPath: $(Build.ArtifactStagingDirectory)/nupkg
Pattern: '*.nupkg'
UseMinimatch: true
signConfigType: inlineSignParams
inlineOperation: >-
[
{
"KeyCode": "CP-401405",
"OperationCode": "NuGetSign",
"Parameters": {},
"ToolName": "sign",
"ToolVersion": "1.0"
},
{
"KeyCode": "CP-401405",
"OperationCode": "NuGetVerify",
"Parameters": {},
"ToolName": "sign",
"ToolVersion": "1.0"
}
]
- task: PublishBuildArtifacts@1
displayName: Publish Artifact (nupkg)
inputs:
PathtoPublish: $(Build.ArtifactStagingDirectory)\nupkg
ArtifactName: wpf-nupkg-$(BuildConfiguration)
- ${{ if eq(parameters.buildTerminalVPack, true) }}:
- job: VPack
displayName: Create Windows vPack
dependsOn: BundleAndSign
steps:
- checkout: self
clean: true
submodules: true
- task: PkgESSetupBuild@12
displayName: Package ES - Setup Build
- task: DownloadBuildArtifacts@0
displayName: Download Build Artifacts
inputs:
artifactName: appxbundle-signed
extractTars: false
- task: PowerShell@2
displayName: Rename and stage packages for vpack
inputs:
targetType: inline
script: >-
# Rename to known/fixed name for Windows build system
Get-ChildItem Microsoft.WindowsTerminal_*.msixbundle | Rename-Item -NewName { 'Microsoft.WindowsTerminal_8wekyb3d8bbwe.msixbundle' }
# Create vpack directory and place item inside
mkdir WindowsTerminal.app
mv Microsoft.WindowsTerminal_8wekyb3d8bbwe.msixbundle .\WindowsTerminal.app\
workingDirectory: $(System.ArtifactsDirectory)\appxbundle-signed
- task: PkgESVPack@12
displayName: 'Package ES - VPack'
env:
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
inputs:
sourceDirectory: $(System.ArtifactsDirectory)\appxbundle-signed\WindowsTerminal.app
description: Windows Terminal pre-install application
pushPkgName: WindowsTerminal.app
owner: condev
...
- template: ./templates/release-sign-and-bundle.yml

View File

@@ -8,12 +8,9 @@ jobs:
variables:
BuildConfiguration: AuditMode
BuildPlatform: ${{ parameters.platform }}
pool:
${{ if eq(variables['System.CollectionUri'], 'https://dev.azure.com/ms/') }}:
name: WinDevPoolOSS-L
${{ if ne(variables['System.CollectionUri'], 'https://dev.azure.com/ms/') }}:
name: WinDevPool-L
demands: ImageOverride -equals WinDevVS16-latest
pool: "windevbuildagents"
# The public pool is also an option!
# pool: { vmImage: windows-2019 }
steps:
- checkout: self

View File

@@ -11,32 +11,21 @@ jobs:
variables:
BuildConfiguration: ${{ parameters.configuration }}
BuildPlatform: ${{ parameters.platform }}
pool:
${{ if eq(variables['System.CollectionUri'], 'https://dev.azure.com/ms/') }}:
name: WinDevPoolOSS-L
${{ if ne(variables['System.CollectionUri'], 'https://dev.azure.com/ms/') }}:
name: WinDevPool-L
demands: ImageOverride -equals WinDevVS16-latest
pool: "windevbuildagents"
# The public pool is also an option!
# pool: { vmImage: windows-2019 }
steps:
- template: build-console-steps.yml
parameters:
additionalBuildArguments: ${{ parameters.additionalBuildArguments }}
# It appears that the Component Governance build task that gets automatically injected stopped working
# when we renamed our main branch.
- task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0
displayName: 'Component Detection'
condition: and(succeededOrFailed(), not(eq(variables['Build.Reason'], 'PullRequest')))
- template: helix-runtests-job.yml
parameters:
name: 'RunTestsInHelix'
dependsOn: Build${{ parameters.platform }}${{ parameters.configuration }}
condition: and(succeeded(), and(eq('${{ parameters.platform }}', 'x64'), not(eq(variables['Build.Reason'], 'PullRequest'))))
testSuite: 'DevTestSuite'
platform: ${{ parameters.platform }}
configuration: ${{ parameters.configuration }}
rerunPassesRequiredToAvoidFailure: ${{ parameters.rerunPassesRequiredToAvoidFailure }}
- template: helix-processtestresults-job.yml

View File

@@ -0,0 +1,30 @@
parameters:
configuration: 'Release'
platform: ''
additionalBuildArguments: ''
jobs:
- job: Build${{ parameters.platform }}${{ parameters.configuration }}
displayName: Build ${{ parameters.platform }} ${{ parameters.configuration }}
variables:
BuildConfiguration: ${{ parameters.configuration }}
BuildPlatform: ${{ parameters.platform }}
pool:
name: Package ES Lab E
demands:
- msbuild
- visualstudio
- vstest
steps:
- task: PkgESSetupBuild@10
displayName: 'Package ES - Setup Build'
inputs:
useDfs: false
productName: WindowsTerminal
disableOutputRedirect: true
- template: build-console-steps.yml
parameters:
additionalBuildArguments: "/p:XesUseOneStoreVersioning=true;XesBaseYearForStoreVersion=$(baseYearForVersioning) ${{ parameters.additionalBuildArguments }}"

View File

@@ -1,54 +0,0 @@
parameters:
configuration: 'Release'
platform: ''
additionalBuildArguments: ''
minimumExpectedTestsExecutedCount: 1 # Sanity check for minimum expected tests to be reported
rerunPassesRequiredToAvoidFailure: 0
jobs:
- job: Build${{ parameters.platform }}${{ parameters.configuration }}
displayName: Build ${{ parameters.platform }} ${{ parameters.configuration }}
variables:
BuildConfiguration: ${{ parameters.configuration }}
BuildPlatform: ${{ parameters.platform }}
PGOBuildMode: 'Instrument'
pool:
${{ if eq(variables['System.CollectionUri'], 'https://dev.azure.com/ms/') }}:
name: WinDevPoolOSS-L
${{ if ne(variables['System.CollectionUri'], 'https://dev.azure.com/ms/') }}:
name: WinDevPool-L
demands: ImageOverride -equals WinDevVS16-latest
steps:
- template: build-console-steps.yml
parameters:
additionalBuildArguments: ${{ parameters.additionalBuildArguments }}
- template: helix-runtests-job.yml
parameters:
name: 'RunTestsInHelix'
dependsOn: Build${{ parameters.platform }}${{ parameters.configuration }}
condition: succeeded()
testSuite: 'PgoInstrumentationSuite'
taefQuery: '@IsPgo=true'
configuration: ${{ parameters.configuration }}
platform: ${{ parameters.platform }}
rerunPassesRequiredToAvoidFailure: ${{ parameters.rerunPassesRequiredToAvoidFailure }}
- template: helix-processtestresults-job.yml
parameters:
name: 'ProcessTestResults'
pgoArtifact: 'PGO'
dependsOn:
- RunTestsInHelix
condition: succeededOrFailed()
rerunPassesRequiredToAvoidFailure: ${{ parameters.rerunPassesRequiredToAvoidFailure }}
minimumExpectedTestsExecutedCount: ${{ parameters.minimumExpectedTestsExecutedCount }}
- template: pgo-merge-pgd-job.yml
parameters:
name: 'MergePGD'
dependsOn:
- ProcessTestResults
pgoArtifact: 'PGO'
platform: ${{ parameters.platform }}

View File

@@ -22,7 +22,7 @@ steps:
configPath: NuGet.config
restoreSolution: OpenConsole.sln
restoreDirectory: '$(Build.SourcesDirectory)\packages'
- task: 333b11bd-d341-40d9-afcf-b32d5ce6f23b@2
displayName: Restore NuGet packages for extraneous build actions
inputs:
@@ -32,29 +32,6 @@ steps:
restoreSolution: build/packages.config
restoreDirectory: '$(Build.SourcesDirectory)\packages'
# The environment variable VCToolsInstallDir isn't defined on lab machines, so we need to retrieve it ourselves.
- script: |
"%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" -Latest -requires Microsoft.Component.MSBuild -property InstallationPath > %TEMP%\vsinstalldir.txt
set /p _VSINSTALLDIR15=<%TEMP%\vsinstalldir.txt
del %TEMP%\vsinstalldir.txt
call "%_VSINSTALLDIR15%\Common7\Tools\VsDevCmd.bat"
echo VCToolsInstallDir = %VCToolsInstallDir%
echo ##vso[task.setvariable variable=VCToolsInstallDir]%VCToolsInstallDir%
displayName: 'Retrieve VC tools directory'
- task: CmdLine@1
displayName: 'Display build machine environment variables'
inputs:
filename: 'set'
- task: powershell@2
displayName: 'Restore PGO database'
condition: eq(variables['PGOBuildMode'], 'Optimize')
inputs:
targetType: filePath
workingDirectory: $(Build.SourcesDirectory)\tools\PGODatabase
filePath: $(Build.SourcesDirectory)\tools\PGODatabase\restore-pgodb.ps1
- task: VSBuild@1
displayName: 'Build solution **\OpenConsole.sln'
inputs:
@@ -68,9 +45,6 @@ steps:
- task: PowerShell@2
displayName: 'Check MSIX for common regressions'
# PGO runtime needs its own CRT and it's in the package for convenience.
# That will make this script mad so skip since we're not shipping the PGO Instrumentation one anyway.
condition: ne(variables['PGOBuildMode'], 'Instrument')
inputs:
targetType: inline
script: |
@@ -79,7 +53,6 @@ steps:
- task: powershell@2
displayName: 'Source Index PDBs'
condition: ne(variables['PGOBuildMode'], 'Instrument')
inputs:
targetType: filePath
filePath: build\scripts\Index-Pdbs.ps1
@@ -95,25 +68,13 @@ steps:
If ($Arch -Eq "x86") { $Arch = "Win32" }
Write-Host "##vso[task.setvariable variable=RationalizedBuildPlatform]${Arch}"
- task: PowerShell@2
displayName: 'Validate binaries are optimized'
condition: eq(variables['pgoBuildMode'], 'Optimize')
inputs:
targetType: inline
script: |
$Binaries = 'OpenConsole.exe', 'WindowsTerminal.exe', 'TerminalApp.dll', 'TerminalConnection.dll', 'Microsoft.Terminal.Control.dll', 'Microsoft.Terminal.Remoting.dll', 'Microsoft.Terminal.Settings.Editor.dll', 'Microsoft.Terminal.Settings.Model.dll'
foreach ($BinFile in $Binaries)
{
& "$(Build.SourcesDirectory)\tools\PGODatabase\verify-pgo.ps1" "$(Build.SourcesDirectory)/bin/$(RationalizedBuildPlatform)/$(BuildConfiguration)/$BinFile"
}
- task: PowerShell@2
displayName: 'Run Unit Tests'
inputs:
targetType: filePath
filePath: build\scripts\Run-Tests.ps1
arguments: -MatchPattern '*unit.test*.dll' -Platform '$(RationalizedBuildPlatform)' -Configuration '$(BuildConfiguration)' -LogPath '${{ parameters.testLogPath }}'
condition: and(and(succeeded(), ne(variables['PGOBuildMode'], 'Instrument')), or(eq(variables['BuildPlatform'], 'x64'), eq(variables['BuildPlatform'], 'x86')))
condition: and(succeeded(), or(eq(variables['BuildPlatform'], 'x64'), eq(variables['BuildPlatform'], 'x86')))
- task: PowerShell@2
displayName: 'Run Feature Tests (x64 only)'
@@ -121,7 +82,7 @@ steps:
targetType: filePath
filePath: build\scripts\Run-Tests.ps1
arguments: -MatchPattern '*feature.test*.dll' -Platform '$(RationalizedBuildPlatform)' -Configuration '$(BuildConfiguration)' -LogPath '${{ parameters.testLogPath }}'
condition: and(and(succeeded(), ne(variables['PGOBuildMode'], 'Instrument')), eq(variables['BuildPlatform'], 'x64'))
condition: and(succeeded(), eq(variables['BuildPlatform'], 'x64'))
- task: PowerShell@2
displayName: 'Convert Test Logs from WTL to xUnit format'
@@ -129,14 +90,13 @@ steps:
targetType: filePath
filePath: build\Helix\ConvertWttLogToXUnit.ps1
arguments: -WttInputPath '${{ parameters.testLogPath }}' -WttSingleRerunInputPath 'unused.wtl' -WttMultipleRerunInputPath 'unused2.wtl' -XUnitOutputPath 'onBuildMachineResults.xml' -TestNamePrefix '$(BuildConfiguration).$(BuildPlatform)'
condition: and(ne(variables['PGOBuildMode'], 'Instrument'),or(eq(variables['BuildPlatform'], 'x64'), eq(variables['BuildPlatform'], 'x86')))
condition: or(eq(variables['BuildPlatform'], 'x64'), eq(variables['BuildPlatform'], 'x86'))
- task: PublishTestResults@2
displayName: 'Upload converted test logs'
condition: ne(variables['PGOBuildMode'], 'Instrument')
inputs:
testResultsFormat: 'xUnit' # Options: JUnit, NUnit, VSTest, xUnit, cTest
testResultsFiles: '**/onBuildMachineResults.xml'
testResultsFiles: '**/onBuildMachineResults.xml'
#searchFolder: '$(System.DefaultWorkingDirectory)' # Optional
#mergeTestResults: false # Optional
#failTaskOnFailedTests: false # Optional
@@ -167,47 +127,24 @@ steps:
TargetFolder: '$(Build.ArtifactStagingDirectory)/appx'
OverWrite: true
flattenFolders: true
condition: succeeded()
condition: and(succeeded(), ne(variables['Build.Reason'], 'PullRequest'))
- task: CopyFiles@2
displayName: 'Copy outputs needed for test runs to Artifacts'
inputs:
Contents: |
$(Build.SourcesDirectory)/bin/$(RationalizedBuildPlatform)/$(BuildConfiguration)/*.exe
$(Build.SourcesDirectory)/bin/$(RationalizedBuildPlatform)/$(BuildConfiguration)/*.dll
$(Build.SourcesDirectory)/bin/$(RationalizedBuildPlatform)/$(BuildConfiguration)/*.xml
$(Build.SourcesDirectory)/bin/$(BuildPlatform)/$(BuildConfiguration)/*.exe
$(Build.SourcesDirectory)/bin/$(BuildPlatform)/$(BuildConfiguration)/*.dll
$(Build.SourcesDirectory)/bin/$(BuildPlatform)/$(BuildConfiguration)/*.xml
**/Microsoft.VCLibs.*.appx
**/TestHostApp/*.exe
**/TestHostApp/*.dll
**/TestHostApp/*.xml
!**/*.pdb
!**/*.ipdb
!**/*.obj
!**/*.pch
**/TestHostApp/*
TargetFolder: '$(Build.ArtifactStagingDirectory)/$(BuildConfiguration)/$(BuildPlatform)/test'
OverWrite: true
flattenFolders: true
condition: succeeded()
condition: and(and(succeeded(), eq(variables['BuildPlatform'], 'x64')), ne(variables['Build.Reason'], 'PullRequest'))
- task: PublishBuildArtifacts@1
displayName: 'Publish All Build Artifacts'
inputs:
PathtoPublish: '$(Build.ArtifactStagingDirectory)'
ArtifactName: 'drop'
- task: CopyFiles@2
displayName: 'Copy PGO databases needed for PGO instrumentation run'
inputs:
Contents: |
**/*.pgd
TargetFolder: '$(Build.ArtifactStagingDirectory)/$(BuildConfiguration)/PGO/$(BuildPlatform)'
OverWrite: true
flattenFolders: true
condition: and(succeeded(), eq(variables['PGOBuildMode'], 'Instrument'))
- task: PublishBuildArtifacts@1
displayName: 'Publish All PGO Artifacts'
inputs:
PathtoPublish: '$(Build.ArtifactStagingDirectory)/$(BuildConfiguration)/PGO'
ArtifactName: 'PGO'
condition: and(succeeded(), eq(variables['PGOBuildMode'], 'Instrument'))
ArtifactName: 'drop'

View File

@@ -12,4 +12,4 @@ steps:
inputs:
targetType: filePath
filePath: build\Helix\GenerateTestProjFile.ps1
arguments: -TestFile '${{ parameters.testFilePath }}' -OutputProjFile '$(Build.ArtifactStagingDirectory)\$(BuildConfiguration)\$(BuildPlatform)\${{ parameters.outputProjFileName }}' -JobTestSuiteName '${{ parameters.testSuite }}' -TaefPath '$(Build.SourcesDirectory)\build\Helix\packages\Microsoft.Taef.10.60.210621002\build\Binaries\x86' -TaefQuery '${{ parameters.taefQuery }}'
arguments: -TestFile '${{ parameters.testFilePath }}' -OutputProjFile '$(Build.ArtifactStagingDirectory)\${{ parameters.outputProjFileName }}' -JobTestSuiteName '${{ parameters.testSuite }}' -TaefPath '$(Build.SourcesDirectory)\build\Helix\packages\taef.redist.wlk.10.57.200731005-develop\build\Binaries\x86' -TaefQuery '${{ parameters.taefQuery }}'

View File

@@ -10,11 +10,19 @@ parameters:
maxParallel: 4
rerunPassesRequiredToAvoidFailure: 5
taefQuery: ''
configuration: ''
platform: ''
# if 'useBuildOutputFromBuildId' is set, we will default to using a build from this pipeline:
useBuildOutputFromPipeline: $(System.DefinitionId)
openHelixTargetQueues: 'windows.10.amd64.client19h1.open.xaml'
matrix:
# Release_x86:
# buildPlatform: 'x86'
# buildConfiguration: 'release'
# openHelixTargetQueues: 'windows.10.amd64.client19h1.open.xaml'
# closedHelixTargetQueues: 'windows.10.amd64.client19h1.xaml'
Release_x64:
buildPlatform: 'x64'
buildConfiguration: 'release'
openHelixTargetQueues: 'windows.10.amd64.client19h1.open.xaml'
closedHelixTargetQueues: 'windows.10.amd64.client19h1.xaml'
jobs:
- job: ${{ parameters.name }}
@@ -25,12 +33,10 @@ jobs:
timeoutInMinutes: 120
strategy:
maxParallel: ${{ parameters.maxParallel }}
matrix: ${{ parameters.matrix }}
variables:
buildConfiguration: ${{ parameters.configuration }}
buildPlatform: ${{ parameters.platform }}
openHelixTargetQueues: ${{ parameters.openHelixTargetQueues }}
artifactsDir: $(Build.SourcesDirectory)\Artifacts
taefPath: $(Build.SourcesDirectory)\build\Helix\packages\Microsoft.Taef.10.60.210621002\build\Binaries\$(buildPlatform)
taefPath: $(Build.SourcesDirectory)\build\Helix\packages\taef.redist.wlk.10.57.200731005-develop\build\Binaries\$(buildPlatform)
helixCommonArgs: '/binaryLogger:$(Build.SourcesDirectory)/${{parameters.name}}.$(buildPlatform).$(buildConfiguration).binlog /p:HelixBuild=$(Build.BuildId).$(buildPlatform).$(buildConfiguration) /p:Platform=$(buildPlatform) /p:Configuration=$(buildConfiguration) /p:HelixType=${{parameters.helixType}} /p:TestSuite=${{parameters.testSuite}} /p:ProjFilesPath=$(Build.ArtifactStagingDirectory) /p:rerunPassesRequiredToAvoidFailure=${{parameters.rerunPassesRequiredToAvoidFailure}}'
@@ -91,17 +97,9 @@ jobs:
filename: 'dir'
arguments: '/s $(Build.SourcesDirectory)\HelixPayload'
- task: PowerShell@2
displayName: 'Make artifact directories'
inputs:
targetType: inline
script: |
New-Item -ItemType Directory -Force -Path "$(Build.ArtifactStagingDirectory)\$(BuildConfiguration)\"
New-Item -ItemType Directory -Force -Path "$(Build.ArtifactStagingDirectory)\$(BuildConfiguration)\$(BuildPlatform)\"
- template: helix-createprojfile-steps.yml
parameters:
condition: and(succeeded(),eq('${{ parameters.testSuite }}','DevTestSuite'))
condition: and(succeeded(),ne('${{ parameters.testSuite }}','NugetTestSuite'))
testFilePath: '$(artifactsDir)\${{ parameters.artifactName }}\$(buildConfiguration)\$(buildPlatform)\Test\TerminalApp.LocalTests.dll'
outputProjFileName: 'RunTestsInHelix-TerminalAppLocalTests.proj'
testSuite: '${{ parameters.testSuite }}'
@@ -109,7 +107,7 @@ jobs:
- template: helix-createprojfile-steps.yml
parameters:
condition: and(succeeded(),eq('${{ parameters.testSuite }}','DevTestSuite'))
condition: and(succeeded(),ne('${{ parameters.testSuite }}','NugetTestSuite'))
testFilePath: '$(artifactsDir)\${{ parameters.artifactName }}\$(buildConfiguration)\$(buildPlatform)\Test\SettingsModel.LocalTests.dll'
outputProjFileName: 'RunTestsInHelix-SettingsModelLocalTests.proj'
testSuite: '${{ parameters.testSuite }}'
@@ -118,20 +116,12 @@ jobs:
- template: helix-createprojfile-steps.yml
parameters:
condition: and(succeeded(),eq('${{ parameters.testSuite }}','DevTestSuite'))
condition: and(succeeded(),ne('${{ parameters.testSuite }}','NugetTestSuite'))
testFilePath: '$(artifactsDir)\${{ parameters.artifactName }}\$(buildConfiguration)\$(buildPlatform)\Test\Conhost.UIA.Tests.dll'
outputProjFileName: 'RunTestsInHelix-HostTestsUIA.proj'
testSuite: '${{ parameters.testSuite }}'
taefQuery: ${{ parameters.taefQuery }}
- template: helix-createprojfile-steps.yml
parameters:
condition: and(succeeded(),or(eq('${{ parameters.testSuite }}','PgoInstrumentationSuite'),eq('${{ parameters.testSuite }}','DevTestSuite')))
testFilePath: '$(artifactsDir)\${{ parameters.artifactName }}\$(buildConfiguration)\$(buildPlatform)\Test\WindowsTerminal.UIA.Tests.dll'
outputProjFileName: 'RunTestsInHelix-WindowsTerminalUIATests.proj'
testSuite: '${{ parameters.testSuite }}'
taefQuery: ${{ parameters.taefQuery }}
- task: PublishBuildArtifacts@1
displayName: 'Publish generated .proj files'
inputs:
@@ -147,3 +137,4 @@ jobs:
projects: build\Helix\RunTestsInHelix.proj
custom: msbuild
arguments: '$(helixCommonArgs) /p:IsExternal=true /p:Creator=Terminal /p:HelixTargetQueues=$(openHelixTargetQueues)'

View File

@@ -1,62 +0,0 @@
# From our friends at MUX: https://github.com/microsoft/microsoft-ui-xaml/blob/main/build/AzurePipelinesTemplates/MUX-BuildAndPublishPGONuGet-Job.yml
parameters:
dependsOn: ''
pgoArtifact: PGO
jobs:
- job: BuildAndPublishPGONuGet
dependsOn: ${{ parameters.dependsOn }}
pool:
vmImage: 'windows-2019'
variables:
artifactsPath: $(Build.SourcesDirectory)\Artifacts
pgoToolsPath: $(Build.SourcesDirectory)\tools\PGODatabase
nuspecPath: $(pgoToolsPath)\NuSpecs
nuspecFilename: PGO.nuspec
steps:
- task: DownloadBuildArtifacts@0
inputs:
artifactName: ${{ parameters.pgoArtifact }}
downloadPath: $(artifactsPath)
- task: NuGetToolInstaller@0
displayName: 'Use NuGet 5.2.0'
inputs:
versionSpec: 5.2.0
- task: CopyFiles@2
displayName: 'Copy pgd files to NuGet build directory'
inputs:
sourceFolder: $(artifactsPath)\${{ parameters.pgoArtifact }}
contents: '**\*.pgd'
targetFolder: $(nuspecPath)\tools
- task: powershell@2
displayName: 'Generate NuSpec file'
inputs:
targetType: filePath
filePath: $(pgoToolsPath)\generate-nuspec.ps1
workingDirectory: $(pgoToolsPath)
arguments: $(nuspecPath)\$(nuspecFilename).template $(nuspecPath)\$(nuspecFilename)
- task: 333b11bd-d341-40d9-afcf-b32d5ce6f23b@2
displayName: 'NuGet pack'
inputs:
command: pack
packagesToPack: '$(nuspecPath)\$(nuspecFilename)'
basePath: '$(nuspecPath)'
packDestination: '$(Build.ArtifactStagingDirectory)'
- task: PublishBuildArtifacts@1
inputs:
pathToPublish: $(Build.ArtifactStagingDirectory)
artifactName: ${{ parameters.pgoArtifact }}
- task: 333b11bd-d341-40d9-afcf-b32d5ce6f23b@2
displayName: 'NuGet push'
inputs:
command: push
publishVstsFeed: Terminal/TerminalDependencies
packagesToPush: $(Build.ArtifactStagingDirectory)/*.nupkg

View File

@@ -1,90 +0,0 @@
parameters:
dependsOn: ''
pgoArtifact: PGO
platform: ''
jobs:
- job: MergePGD
dependsOn: ${{ parameters.dependsOn }}
pool:
vmImage: 'windows-2019'
variables:
artifactsPath: $(Build.SourcesDirectory)\Artifacts
pgoArtifactsPath: $(artifactsPath)\${{ parameters.pgoArtifact }}
buildPlatform: ${{ parameters.platform }}
steps:
# The environment variable VCToolsInstallDir isn't defined on lab machines, so we need to retrieve it ourselves.
- script: |
"%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" -Latest -requires Microsoft.Component.MSBuild -property InstallationPath > %TEMP%\vsinstalldir.txt
set /p _VSINSTALLDIR15=<%TEMP%\vsinstalldir.txt
del %TEMP%\vsinstalldir.txt
call "%_VSINSTALLDIR15%\Common7\Tools\VsDevCmd.bat"
echo VCToolsInstallDir = %VCToolsInstallDir%
echo ##vso[task.setvariable variable=VCToolsInstallDir]%VCToolsInstallDir%
displayName: 'Retrieve VC tools directory'
- task: DownloadBuildArtifacts@0
inputs:
artifactName: ${{ parameters.pgoArtifact }}
downloadPath: $(artifactsPath)
- script: |
cd $(buildPlatform)
"%VCToolsInstallDir%\bin\hostx64\x64\pgomgr.exe" /merge WindowsTerminal*.pgc WindowsTerminal.pgd
displayName: 'Merge Terminal pgc files into pgd'
workingDirectory: $(pgoArtifactsPath)
- script: |
cd $(buildPlatform)
"%VCToolsInstallDir%\bin\hostx64\x64\pgomgr.exe" /merge OpenConsole*.pgc OpenConsole.pgd
displayName: 'Merge OpenConsole pgc files into pgd'
workingDirectory: $(pgoArtifactsPath)
- script: |
cd $(buildPlatform)
"%VCToolsInstallDir%\bin\hostx64\x64\pgomgr.exe" /merge Microsoft.Terminal.Control*.pgc Microsoft.Terminal.Control.pgd
displayName: 'Merge Microsoft.Terminal.Control pgc files into pgd'
workingDirectory: $(pgoArtifactsPath)
- script: |
cd $(buildPlatform)
"%VCToolsInstallDir%\bin\hostx64\x64\pgomgr.exe" /merge Microsoft.Terminal.Remoting*.pgc Microsoft.Terminal.Remoting.pgd
displayName: 'Merge Microsoft.Terminal.Remoting pgc files into pgd'
workingDirectory: $(pgoArtifactsPath)
- script: |
cd $(buildPlatform)
"%VCToolsInstallDir%\bin\hostx64\x64\pgomgr.exe" /merge Microsoft.Terminal.Settings.Editor*.pgc Microsoft.Terminal.Settings.Editor.pgd
displayName: 'Merge Microsoft.Terminal.Settings.Editor pgc files into pgd'
workingDirectory: $(pgoArtifactsPath)
- script: |
cd $(buildPlatform)
"%VCToolsInstallDir%\bin\hostx64\x64\pgomgr.exe" /merge Microsoft.Terminal.Settings.Model*.pgc Microsoft.Terminal.Settings.Model.pgd
displayName: 'Merge Microsoft.Terminal.Settings.Model pgc files into pgd'
workingDirectory: $(pgoArtifactsPath)
- script: |
cd $(buildPlatform)
"%VCToolsInstallDir%\bin\hostx64\x64\pgomgr.exe" /merge TerminalApp*.pgc TerminalApp.pgd
displayName: 'Merge TerminalApp pgc files into pgd'
workingDirectory: $(pgoArtifactsPath)
- script: |
cd $(buildPlatform)
"%VCToolsInstallDir%\bin\hostx64\x64\pgomgr.exe" /merge TerminalConnection*.pgc TerminalConnection.pgd
displayName: 'Merge TerminalConnection pgc files into pgd'
workingDirectory: $(pgoArtifactsPath)
- task: CopyFiles@2
displayName: 'Copy merged pgd to artifact staging'
inputs:
sourceFolder: $(pgoArtifactsPath)
contents: '**\$(buildPlatform)\*.pgd'
targetFolder: $(Build.ArtifactStagingDirectory)
- task: PublishBuildArtifacts@1
inputs:
pathToPublish: $(Build.ArtifactStagingDirectory)
artifactName: ${{ parameters.pgoArtifact }}

View File

@@ -0,0 +1,74 @@
parameters:
configuration: 'Release'
jobs:
- job: SignDeploy${{ parameters.configuration }}
displayName: Sign and Deploy for ${{ parameters.configuration }}
dependsOn:
- Buildx64AuditMode
- Buildx64Release
- Buildx86Release
- Buildarm64Release
- CodeFormatCheck
condition: |
and
(
in(dependencies.Buildx64AuditMode.result, 'Succeeded', 'SucceededWithIssues', 'Skipped'),
in(dependencies.Buildx64Release.result, 'Succeeded', 'SucceededWithIssues', 'Skipped'),
in(dependencies.Buildx86Release.result, 'Succeeded', 'SucceededWithIssues', 'Skipped'),
in(dependencies.Buildarm64Release.result, 'Succeeded', 'SucceededWithIssues', 'Skipped'),
in(dependencies.CodeFormatCheck.result, 'Succeeded', 'SucceededWithIssues', 'Skipped')
)
variables:
BuildConfiguration: ${{ parameters.configuration }}
AppxProjectName: CascadiaPackage
AppxBundleName: Microsoft.WindowsTerminal_8wekyb3d8bbwe.msixbundle
pool:
name: Package ES Lab E
steps:
- checkout: self
clean: true
- task: PkgESSetupBuild@10
displayName: 'Package ES - Setup Build'
inputs:
useDfs: false
productName: WindowsTerminal
disableOutputRedirect: true
- task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0
displayName: 'Component Detection'
- task: DownloadBuildArtifacts@0
displayName: Download AppX artifacts
inputs:
artifactName: 'appx-$(BuildConfiguration)'
itemPattern: |
**/*.appx
**/*.msix
downloadPath: '$(Build.ArtifactStagingDirectory)\appx'
- task: PowerShell@2
displayName: 'Create $(AppxBundleName)'
inputs:
targetType: filePath
filePath: '.\build\scripts\Create-AppxBundle.ps1'
arguments: |
-InputPath "$(Build.ArtifactStagingDirectory)\appx" -ProjectName $(AppxProjectName) -BundleVersion 0.0.0.0 -OutputPath "$(Build.ArtifactStagingDirectory)\$(AppxBundleName)"
- task: PkgESCodeSign@10
displayName: 'Package ES - SignConfig.WindowsTerminal.xml'
inputs:
signConfigXml: 'build\config\SignConfig.WindowsTerminal.xml'
inPathRoot: '$(Build.ArtifactStagingDirectory)'
outPathRoot: '$(Build.ArtifactStagingDirectory)\signed'
- task: PublishBuildArtifacts@1
displayName: 'Publish Signed AppX'
inputs:
PathtoPublish: '$(Build.ArtifactStagingDirectory)\signed'
ArtifactName: 'appxbundle-signed-$(BuildConfiguration)'

View File

@@ -1,97 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="16.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<!-- THIS PROJECT CANNOT BE LOADED INTO THE SOLUTION. -->
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Release|Any CPU">
<Configuration>Release</Configuration>
<Platform>AnyCPU</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Fuzzing|Any CPU">
<Configuration>Fuzzing</Configuration>
<Platform>AnyCPU</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="AuditMode|Any CPU">
<Configuration>AuditMode</Configuration>
<Platform>AnyCPU</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|Any CPU">
<Configuration>Debug</Configuration>
<Platform>AnyCPU</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>d97c3c61-53cd-4e72-919b-9a0940e038f9</ProjectGuid>
</PropertyGroup>
<PropertyGroup>
<IntermediateOutputPath>$(SolutionDir)obj\$(Configuration)\GenerateFeatureFlags\</IntermediateOutputPath>
<OpenConsoleCommonOutDir>$(SolutionDir)bin\$(Configuration)\</OpenConsoleCommonOutDir>
<_WTBrandingName Condition="'$(WindowsTerminalBranding)'=='Preview'">Preview</_WTBrandingName>
<_WTBrandingName Condition="'$(WindowsTerminalBranding)'=='Release'">Release</_WTBrandingName>
<_WTBrandingName Condition="'$(_WTBrandingName)'==''">Dev</_WTBrandingName>
</PropertyGroup>
<Target Name="_GenerateBranchAndBrandingCache">
<Exec Command="git.exe rev-parse --abbrev-ref HEAD"
CustomWarningRegularExpression="^fatal:.*"
ConsoleToMsBuild="true"
IgnoreExitCode="true">
<Output TaskParameter="ConsoleOutput" ItemName="_GitBranchLines" />
</Exec>
<ItemGroup>
<_BrandingLines Include="$(_WTBrandingName)" />
</ItemGroup>
<WriteLinesToFile File="$(IntermediateOutputPath)branch_branding_cache.txt"
Lines="@(_GitBranchLines);@(_BrandingLines)"
Overwrite="true"
WriteOnlyWhenDifferent="true" />
<ItemGroup>
<FileWrites Include="$(IntermediateOutputPath)branch_branding_cache.txt" />
<_BranchBrandingCacheFiles Include="$(IntermediateOutputPath)branch_branding_cache.txt" />
</ItemGroup>
</Target>
<Target Name="_RunFeatureFlagScript"
Inputs="@(FeatureFlagFile);@(_BranchBrandingCacheFiles)"
Outputs="$(OpenConsoleCommonOutDir)\inc\TilFeatureStaging.h"
DependsOnTargets="_GenerateBranchAndBrandingCache">
<MakeDir Directories="$(OpenConsoleCommonOutDir)\inc" />
<Exec
Command="powershell -NoLogo -NoProfile -NonInteractive -ExecutionPolicy ByPass -Command &quot;$(SolutionDir)\tools\Generate-FeatureStagingHeader.ps1&quot; -Path &quot;%(FeatureFlagFile.FullPath)&quot; -Branding $(_WTBrandingName)"
ConsoleToMsBuild="true"
StandardOutputImportance="low">
<Output TaskParameter="ConsoleOutput" ItemName="_FeatureFlagFileLines" />
</Exec>
<!--
We gather the feature flag output in MSBuild and emit the file so that we can take advantage of
WriteOnlyWhenDifferent. Doing this ensures that we don't rebuild the world when the branch changes
(if it results in a new TilFeatureStaging.h that would have had the same content/features as the previous one)
-->
<WriteLinesToFile File="$(OpenConsoleCommonOutDir)\inc\TilFeatureStaging.h"
Lines="@(_FeatureFlagFileLines)"
Overwrite="true"
WriteOnlyWhenDifferent="true" />
<ItemGroup>
<FileWrites Include="$(OpenConsoleCommonOutDir)\inc\TilFeatureStaging.h" />
</ItemGroup>
</Target>
<Target Name="Build" DependsOnTargets="_RunFeatureFlagScript" />
<Target Name="Clean">
<Delete Files="$(OpenConsoleCommonOutDir)\inc\TilFeatureStaging.h" />
</Target>
<ItemGroup>
<FeatureFlagFile Include="$(SolutionDir)\src\features.xml" />
</ItemGroup>
</Project>

View File

@@ -22,7 +22,7 @@ Param(
[Parameter(HelpMessage="Path to makeappx.exe")]
[ValidateScript({Test-Path $_ -Type Leaf})]
[string]
$MakeAppxPath = "C:\Program Files (x86)\Windows Kits\10\bin\10.0.19041.0\x86\MakeAppx.exe"
$MakeAppxPath = "C:\Program Files (x86)\Windows Kits\10\bin\10.0.17763.0\x86\MakeAppx.exe"
)
If ($null -Eq (Get-Item $MakeAppxPath -EA:SilentlyContinue)) {

View File

@@ -3,24 +3,12 @@
# Checks for code formatting errors. Will throw exception if any are found.
function Invoke-CheckBadCodeFormatting() {
Import-Module ./tools/OpenConsole.psm1
# Don't run the XAML formatter in this step - even if it changes nothing,
# it'll still touch all the .xaml files.
Invoke-CodeFormat -IgnoreXaml
Invoke-CodeFormat
# returns a non-zero exit code if there are any diffs in the tracked files in the repo
git diff-index --quiet HEAD --
if ($lastExitCode -eq 1) {
# Write the list of files that need updating to the log
git diff-index --name-only HEAD
throw "code formatting bad, run Invoke-CodeFormat on branch"
}
# Manually check the formatting of our .xaml files, without touching them.
Test-XamlFormat
}
Invoke-CheckBadCodeFormatting

View File

@@ -8,7 +8,7 @@ Param(
[Parameter(HelpMessage="Path to Windows Kit")]
[ValidateScript({Test-Path $_ -Type Leaf})]
[string]
$WindowsKitPath = "C:\Program Files (x86)\Windows Kits\10\bin\10.0.19041.0"
$WindowsKitPath = "C:\Program Files (x86)\Windows Kits\10\bin\10.0.18362.0"
)
$ErrorActionPreference = "Stop"

View File

@@ -19,13 +19,10 @@
"/.github/",
"/samples/",
"/res/terminal/",
"/res/fonts/",
"/doc/specs/",
"/doc/cascadia/",
"/doc/user-docs/",
"/src/tools/MonarchPeasantSample/",
"/scratch/",
"Scratch.sln",
],
"SuffixFilters": [
".dbb",
@@ -41,7 +38,6 @@
".wrn",
".rec",
".err",
"XamlStyler.json",
".xlsx"
]
}

View File

@@ -5,7 +5,7 @@
<XesUseOneStoreVersioning>true</XesUseOneStoreVersioning>
<XesBaseYearForStoreVersion>2021</XesBaseYearForStoreVersion>
<VersionMajor>1</VersionMajor>
<VersionMinor>11</VersionMinor>
<VersionMinor>8</VersionMinor>
<VersionInfoProductName>Windows Terminal</VersionInfoProductName>
</PropertyGroup>
</Project>

Submodule dep/wil updated: 2e225973d6...3c00e7f1d8

View File

@@ -12,11 +12,11 @@ Use the [TAEF Verify Macros for C++](https://docs.microsoft.com/en-us/windows-ha
### Running Tests
If you have Visual Studio and related C++ components installed, and you have successfully restored NuGets, you should have the TAEF test runner `te.exe` available locally as part of the `Microsoft.Taef` package.
If you have Visual Studio and related C++ components installed, and you have successfully restored NuGets, you should have the TAEF test runner `te.exe` available locally as part of the `Taef.Redist.Wlk` package.
> Note that you cannot easily run TAEF tests directly through Visual Studio. The `Microsoft.Taef` NuGet package comes with an adapter that will let you browse and execute TAEF tests inside of Visual Studio, but its performance and reliability prevent us from recommending it here.
> Note that you cannot easily run TAEF tests directly through Visual Studio. The `Taef.Redist.Wlk` NuGet package comes with an adapter that will let you browse and execute TAEF tests inside of Visual Studio, but its performance and reliability prevent us from recommending it here.
In a "normal" CMD environment, `te.exe` may not be directly available. Try the following command to set up the development environment first:
In a "normal" CMD environment, `te.exe` may not be directly available. Try the following command to set up the development enviroment first:
```shell
.\tools\razzle.cmd

View File

@@ -127,4 +127,4 @@ When a release is created, if the PR ID number is linked inside the release desc
- Issue message: 🎉This issue was addressed in #{pull request ID}, which has now been successfully released as {release name} {release version}.🎉"
## Admin Panel
[Here](https://portal.fabricbot.ms/bot/?repo=microsoft/terminal)
[Here](https://fabric-cp.azurewebsites.net/bot/)

View File

@@ -9,13 +9,7 @@ git submodule update --init --recursive
OpenConsole.sln may be built from within Visual Studio or from the command-line using a set of convenience scripts & tools in the **/tools** directory:
When using Visual Studio, be sure to set up the path for code formatting. To download the required clang-format.exe file, follow one of the building instructions below and run:
```powershell
Import-Module .\tools\OpenConsole.psm1
Set-MsBuildDevEnvironment
Get-Format
```
After, go to Tools > Options > Text Editor > C++ > Formatting and checking "Use custom clang-format.exe file" in Visual Studio and choose the clang-format.exe in the repository at /packages/clang-format.win-x86.10.0.0/tools/clang-format.exe by clicking "browse" right under the check box.
When using Visual Studio, be sure to set up the path for code formatting. This can be done in Visual Studio by going to Tools > Options > Text Editor > C++ > Formatting and checking "Use custom clang-format.exe file" and choosing the clang-format.exe in the repository at /dep/llvm/clang-format.exe by clicking "browse" right under the check box.
### Building in PowerShell

View File

@@ -6,9 +6,9 @@ Adding a setting to Windows Terminal is fairly straightforward. This guide serve
The Terminal Settings Model (`Microsoft.Terminal.Settings.Model`) is responsible for (de)serializing and exposing settings.
### `INHERITABLE_SETTING` macro
### `GETSET_SETTING` macro
The `INHERITABLE_SETTING` macro can be used to implement inheritance for your new setting and store the setting in the settings model. It takes three parameters:
The `GETSET_SETTING` macro can be used to implement inheritance for your new setting and store the setting in the settings model. It takes three parameters:
- `type`: the type that the setting will be stored as
- `name`: the name of the variable for storage
- `defaultValue`: the value to use if the user does not define the setting anywhere
@@ -20,7 +20,7 @@ This tutorial will add `CloseOnExitMode CloseOnExit` as a profile setting.
1. In `Profile.h`, declare/define the setting:
```c++
INHERITABLE_SETTING(CloseOnExitMode, CloseOnExit, CloseOnExitMode::Graceful)
GETSET_SETTING(CloseOnExitMode, CloseOnExit, CloseOnExitMode::Graceful)
```
2. In `Profile.idl`, expose the setting via WinRT:
@@ -141,7 +141,7 @@ struct OpenSettingsArgs : public OpenSettingsArgsT<OpenSettingsArgs>
OpenSettingsArgs() = default;
// adds a getter/setter for your argument, and defines the json key
WINRT_PROPERTY(SettingsTarget, Target, SettingsTarget::SettingsFile);
GETSET_PROPERTY(SettingsTarget, Target, SettingsTarget::SettingsFile);
static constexpr std::string_view TargetKey{ "target" };
public:
@@ -213,9 +213,9 @@ Terminal-level settings are settings that affect a shell session. Generally, the
- Declare the setting in `IControlSettings.idl` or `ICoreSettings.idl` (whichever is relevant to your setting). If your setting is an enum setting, declare the enum here instead of in the `TerminalSettingsModel` project.
- In `TerminalSettings.h`, declare/define the setting...
```c++
// The WINRT_PROPERTY macro declares/defines a getter setter for the setting.
// Like INHERITABLE_SETTING, it takes in a type, name, and defaultValue.
WINRT_PROPERTY(bool, UseAcrylic, false);
// The GETSET_PROPERTY macro declares/defines a getter setter for the setting.
// Like GETSET_SETTING, it takes in a type, name, and defaultValue.
GETSET_PROPERTY(bool, UseAcrylic, false);
```
- In `TerminalSettings.cpp`...
- update `_ApplyProfileSettings` for profile settings

View File

@@ -166,7 +166,7 @@ should be working just the same as before.
Now that you have a static library project, you can start building your unittest
dll. Start by creating a new directory for your unittest code, and creating a
`.vcxproj` for a TAEF unittest dll. For the Terminal solution, we use the TAEF
nuget package `Microsoft.Taef`.
nuget package `Taef.Redist.Wlk`.
### Referencing your C++/WinRT static lib
@@ -380,7 +380,7 @@ Here's the AppxManifest we're using:
</Properties>
<Dependencies>
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.18362.0" MaxVersionTested="10.0.19041.0" />
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.18362.0" MaxVersionTested="10.0.18362.0" />
<PackageDependency Name="Microsoft.VCLibs.140.00.Debug" MinVersion="14.0.27023.1" Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" />
<PackageDependency Name="Microsoft.VCLibs.140.00.Debug.UWPDesktop" MinVersion="14.0.27027.1" Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" />
</Dependencies>
@@ -517,7 +517,7 @@ This is because of a few key lines we already put in the appxmanifest:
```xml
<Dependencies>
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.18362.0" MaxVersionTested="10.0.19041.0" />
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.18362.0" MaxVersionTested="10.0.18362.0" />
<PackageDependency Name="Microsoft.VCLibs.140.00.Debug" MinVersion="14.0.27023.1" Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" />
<PackageDependency Name="Microsoft.VCLibs.140.00.Debug.UWPDesktop" MinVersion="14.0.27027.1" Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" />
</Dependencies>

View File

@@ -1,16 +1,16 @@
{
"$id": "https://github.com/microsoft/terminal/blob/main/doc/cascadia/profiles.schema.json",
"$schema": "https://json-schema.org/draft/2020-12/schema#",
"$schema": "https://json-schema.org/draft/2019-09/schema#",
"title": "Microsoft's Windows Terminal Settings Profile Schema",
"definitions": {
"KeyChordSegment": {
"pattern": "^(?:(?:ctrl|alt|shift|win)\\+)*(?:app|backspace|browser_(?:back|forward|refresh|stop|search|favorites|home)|comma|delete|down|end|enter|esc|escape|home|insert|left|menu|minus|pagedown|pageup|period|pgdn|pgup|plus|right|space|tab|up|f(?:1\\d?|2[0-4]?|[3-9])|numpad\\d|numpad_(?:\\d|add|decimal|divide|minus|multiply|period|plus|subtract)|(?:vk|sc)\\((?:[1-9]|1?\\d{2}|2[0-4]\\d|25[0-5])\\)|[^\\s+])(?:\\+(?:ctrl|alt|shift|win))*$",
"pattern": "^(?<modifier>(ctrl|alt|shift)(?:\\+(ctrl|alt|shift)(?<!\\2))?(?:\\+(ctrl|alt|shift)(?<!\\2|\\3))?\\+)?(?<key>[^\\s+]|app|menu|backspace|tab|enter|esc|escape|space|pgup|pageup|pgdn|pagedown|end|home|left|up|right|down|insert|delete|(?<!shift.+)(?:numpad_?[0-9]|numpad_(?:period|decimal))|numpad_(?:multiply|plus|add|minus|subtract|divide)|f[1-9]|f1[0-9]|f2[0-4]|plus)$",
"type": "string",
"description": "The string should fit the format \"[ctrl+][alt+][shift+][win+]<KeyName>\", where each modifier is optional. KeyName is either any single key character, an explicit virtual key or scan code in the form vk(nnn) and sc(nnn) respectively, or one of the special names listed at https://docs.microsoft.com/en-us/windows/terminal/customize-settings/actions#accepted-modifiers-and-keys"
"description": "The string should fit the format \"[ctrl+][alt+][shift+]<keyName>\", where each modifier is optional, separated by + symbols, and keyName is either one of the names listed in the table below, or any single key character. The string should be written in full lowercase.\napp, menu\tMENU key\nbackspace\tBACKSPACE key\ntab\tTAB key\nenter\tENTER key\nesc, escape\tESC key\nspace\tSPACEBAR\npgup, pageup\tPAGE UP key\npgdn, pagedown\tPAGE DOWN key\nend\tEND key\nhome\tHOME key\nleft\tLEFT ARROW key\nup\tUP ARROW key\nright\tRIGHT ARROW key\ndown\tDOWN ARROW key\ninsert\tINS key\ndelete\tDEL key\nnumpad_0-numpad_9, numpad0-numpad9\tNumeric keypad keys 0 to 9. Can't be combined with the shift modifier.\nnumpad_multiply\tNumeric keypad MULTIPLY key (*)\nnumpad_plus, numpad_add\tNumeric keypad ADD key (+)\nnumpad_minus, numpad_subtract\tNumeric keypad SUBTRACT key (-)\nnumpad_period, numpad_decimal\tNumeric keypad DECIMAL key (.). Can't be combined with the shift modifier.\nnumpad_divide\tNumeric keypad DIVIDE key (/)\nf1-f24\tF1 to F24 function keys\nplus\tADD key (+)"
},
"Color": {
"default": "#",
"pattern": "^#[A-Fa-f0-9]{3}(?:[A-Fa-f0-9]{3})?$",
"pattern": "^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$",
"type": "string",
"format": "color"
},
@@ -37,8 +37,7 @@
"type": "string",
"enum": [
"audible",
"window",
"taskbar"
"visual"
]
}
},
@@ -46,179 +45,13 @@
"type": "string",
"enum": [
"audible",
"taskbar",
"window",
"visual",
"all",
"none"
]
}
]
},
"AppearanceConfig": {
"properties": {
"colorScheme": {
"description": "The name of a color scheme to use when unfocused.",
"type": "string"
},
"foreground": {
"$ref": "#/definitions/Color",
"default": "#cccccc",
"description": "Sets the text color when unfocused. Overrides \"foreground\" from the color scheme. Uses hex color format: \"#rrggbb\".",
"type": ["string", "null"]
},
"background": {
"$ref": "#/definitions/Color",
"default": "#0c0c0c",
"description": "Sets the background color of the text when unfocused. Overrides \"background\" from the color scheme. Uses hex color format: \"#rrggbb\".",
"type": ["string", "null"]
},
"selectionBackground": {
"oneOf": [
{"$ref": "#/definitions/Color"},
{ "type": "null" }
],
"description": "Sets the background color of selected text when unfocused. Overrides selectionBackground set in the color scheme. Uses hex color format: \"#rrggbb\"."
},
"cursorColor": {
"oneOf": [
{ "$ref": "#/definitions/Color" },
{"type": "null"}
],
"description": "Sets the color of the cursor when unfocused. Overrides the cursor color from the color scheme. Uses hex color format: \"#rrggbb\"."
},
"cursorShape": {
"default": "bar",
"description": "Sets the shape of the cursor when unfocused. Possible values:\n -\"bar\" ( ┃, default )\n -\"doubleUnderscore\" ( ‗ )\n -\"emptyBox\" ( ▯ )\n -\"filledBox\" ( █ )\n -\"underscore\" ( ▁ )\n -\"vintage\" ( ▃ )",
"enum": [
"bar",
"doubleUnderscore",
"emptyBox",
"filledBox",
"underscore",
"vintage"
],
"type": "string"
},
"cursorHeight": {
"description": "Sets the percentage height of the cursor (when unfocused) starting from the bottom. Only works when cursorShape is set to \"vintage\". Accepts values from 1-100.",
"maximum": 100,
"minimum": 1,
"type": ["integer","null"],
"default": 25
},
"backgroundImage": {
"description": "Sets the file location of the image to draw over the window background when unfocused.",
"oneOf": [
{
"type": ["string", null]
},
{
"enum": [
"desktopWallpaper"
]
}
],
"type": [ "string", "null" ]
},
"backgroundImageOpacity": {
"default": 1.0,
"description": "Sets the transparency of the background image when unfocused. Accepts floating point values from 0-1.",
"maximum": 1.0,
"minimum": 0.0,
"type": "number"
},
"backgroundImageStretchMode": {
"default": "uniformToFill",
"description": "Sets how the background image is resized to fill the window when unfocused.",
"enum": [
"fill",
"none",
"uniform",
"uniformToFill"
],
"type": "string"
},
"backgroundImageAlignment": {
"default": "center",
"enum": [
"bottom",
"bottomLeft",
"bottomRight",
"center",
"left",
"right",
"top",
"topLeft",
"topRight"
],
"description": "Sets how the background image aligns to the boundaries of the window when unfocused. Possible values: \"center\", \"left\", \"top\", \"right\", \"bottom\", \"topLeft\", \"topRight\", \"bottomLeft\", \"bottomRight\"",
"type": "string"
},
"intenseTextStyle": {
"default": "bright",
"description": "Controls how 'intense' text is rendered. Values are \"bold\", \"bright\", \"all\" and \"none\"",
"enum": [
"none",
"bold",
"bright",
"all"
],
"type": "string"
},
"experimental.retroTerminalEffect": {
"description": "When set to true, enable retro terminal effects when unfocused. This is an experimental feature, and its continued existence is not guaranteed.",
"type": "boolean"
},
"experimental.pixelShaderPath": {
"description": "Use to set a path to a pixel shader to use with the Terminal when unfocused. Overrides `experimental.retroTerminalEffect`. This is an experimental feature, and its continued existence is not guaranteed.",
"type": "string"
}
},
"type": "object"
},
"FontConfig": {
"properties": {
"face": {
"default": "Cascadia Mono",
"description": "Name of the font face used in the profile.",
"type": "string"
},
"size": {
"default": 12,
"description": "Size of the font in points.",
"minimum": 1,
"type": "integer"
},
"weight": {
"default": "normal",
"description": "Sets the weight (lightness or heaviness of the strokes) for the given font. Possible values:\n -\"thin\"\n -\"extra-light\"\n -\"light\"\n -\"semi-light\"\n -\"normal\" (default)\n -\"medium\"\n -\"semi-bold\"\n -\"bold\"\n -\"extra-bold\"\n -\"black\"\n -\"extra-black\"\n or the corresponding numeric representation of OpenType font weight.",
"oneOf": [
{
"enum": [
"thin",
"extra-light",
"light",
"semi-light",
"normal",
"medium",
"semi-bold",
"bold",
"extra-bold",
"black",
"extra-black"
],
"type": "string"
},
{
"maximum": 990,
"minimum": 100,
"type": "integer"
}
]
}
},
"type": "object"
},
"ProfileGuid": {
"default": "{}",
"pattern": "^\\{[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}\\}$",
@@ -244,13 +77,7 @@
"duplicateTab",
"find",
"findMatch",
"focusPane",
"globalSummon",
"identifyWindow",
"identifyWindows",
"moveFocus",
"movePane",
"swapPane",
"moveTab",
"newTab",
"newWindow",
@@ -258,15 +85,12 @@
"openNewTabDropdown",
"openSettings",
"openTabColorPicker",
"openWindowRenamer",
"paste",
"prevTab",
"renameTab",
"openTabRenamer",
"quakeMode",
"resetFontSize",
"resizePane",
"renameWindow",
"scrollDown",
"scrollDownPage",
"scrollUp",
@@ -283,7 +107,6 @@
"toggleFocusMode",
"toggleFullscreen",
"togglePaneZoom",
"toggleSplitOrientation",
"toggleReadOnlyMode",
"toggleShaderEffects",
"wt",
@@ -297,9 +120,7 @@
"right",
"up",
"down",
"previous",
"nextInOrder",
"previousInOrder"
"previous"
],
"type": "string"
},
@@ -406,10 +227,6 @@
"type": "boolean",
"default": "false",
"description": "When set to true, tabTitle overrides the default title of the tab and any title change messages from the application will be suppressed. When set to false, tabTitle behaves as normal"
},
"colorScheme": {
"description": "The name of a color scheme to use, instead of the one specified by the profile",
"type": "string"
}
},
"type": "object"
@@ -507,23 +324,6 @@
"type": "integer",
"default": 0,
"description": "Which tab to switch to, with the first being 0"
}
}
}
],
"required": [ "index" ]
},
"MovePaneAction": {
"description": "Arguments corresponding to a Move Pane Action",
"allOf": [
{ "$ref": "#/definitions/ShortcutAction" },
{
"properties": {
"action": { "type": "string", "pattern": "movePane" },
"index": {
"type": "integer",
"default": 0,
"description": "Which tab to move the pane to, with the first being 0"
}
}
}
@@ -540,24 +340,7 @@
"direction": {
"$ref": "#/definitions/FocusDirection",
"default": "left",
"description": "The direction to move focus in, between panes. Direction can be 'previous' to move to the most recently used pane, or 'nextInOrder' or 'previousInOrder' to move to the next or previous pane."
}
}
}
],
"required": [ "direction" ]
},
"SwapPaneAction": {
"description": "Arguments corresponding to a Swap Pane Action",
"allOf": [
{ "$ref": "#/definitions/ShortcutAction" },
{
"properties": {
"action": { "type": "string", "pattern": "swapPane" },
"direction": {
"$ref": "#/definitions/FocusDirection",
"default": "left",
"description": "The direction to move the focus pane in, swapping panes. Direction can be 'previous' to swap with the most recently used pane, or 'nextInOrder' or 'previousInOrder' to move to the next or previous pane."
"description": "The direction to move focus in, between panes. Direction can be 'previous' to move to the most recently used pane."
}
}
}
@@ -639,14 +422,12 @@
"action": { "type": "string", "pattern": "openSettings" },
"target": {
"type": "string",
"default": "settingsUI",
"description": "Opens Settings UI or settings file.",
"default": "settingsFile",
"description": "The settings file to open.",
"enum": [
"settingsFile",
"defaultsFile",
"allFiles",
"settingsUI"
"allFiles"
]
}
}
@@ -741,25 +522,6 @@
}
]
},
"CloseTabAction": {
"description": "Arguments for a closeTab action",
"allOf": [
{ "$ref": "#/definitions/ShortcutAction" },
{
"properties": {
"action": { "type": "string", "pattern": "closeTab" },
"index": {
"oneOf": [
{ "type": "integer" },
{ "type": "null" }
],
"default": null,
"description": "Close the tab at this index. If no index is provided, use the focused tab's index."
}
}
}
]
},
"ScrollUpAction": {
"description": "Arguments for a scrollUp action",
"allOf": [
@@ -885,111 +647,6 @@
}
]
},
"RenameTabAction": {
"description": "Arguments corresponding to a renameTab Action",
"allOf": [
{ "$ref": "#/definitions/ShortcutAction" },
{
"properties": {
"action": { "type": "string", "pattern": "renameTab" },
"title": {
"type": "string",
"default": "",
"description": "A title to assign to the tab. If omitted or null, this action will restore the tab's title to the original value."
}
}
}
]
},
"RenameWindowAction": {
"description": "Arguments corresponding to a renameWindow Action",
"allOf": [
{ "$ref": "#/definitions/ShortcutAction" },
{
"properties": {
"action": { "type": "string", "pattern": "renameWindow" },
"name": {
"type": "string",
"default": "",
"description": "A name to assign to the window."
}
}
}
]
},
"FocusPaneAction": {
"description": "Arguments corresponding to a focusPane Action",
"allOf": [
{ "$ref": "#/definitions/ShortcutAction" },
{
"properties": {
"action": { "type": "string", "pattern": "focusPane" },
"id": {
"type": "string",
"default": "",
"description": "The ID of the pane to focus"
}
}
}
]
},
"GlobalSummonAction": {
"description": "This is a special action that works globally in the OS, rather than only in the context of the terminal window. When pressed, this action will summon the terminal window.",
"allOf": [
{ "$ref": "#/definitions/ShortcutAction" },
{
"properties": {
"action": { "type": "string", "pattern": "globalSummon" },
"desktop": {
"type": "string",
"default": "toCurrent",
"description": "This controls how the terminal should interact with virtual desktops.\n- \"any\": Leave the window on whichever desktop it's already on - will switch to that desktop as the window is activated.\n- \"toCurrent\" (default): Move the window to the current virtual desktop.\n- \"onCurrent\": Only summon the window if it's already on the current virtual desktop. ",
"enum": [
"any",
"toCurrent",
"onCurrent"
]
},
"monitor": {
"type": "string",
"default": "toMouse",
"description": "This controls the monitor that the window will be summoned from/to.\n- \"any\": Summon the most recently used window, regardless of which monitor it's currently on.\n- \"toCurrent\": Summon the most recently used window to the monitor with the current foreground window.\n- \"toMouse\" (default): Summon the most recently used window to the monitor where the mouse cursor is.",
"enum": [
"any",
"toCurrent",
"toMouse"
]
},
"name": {
"type": "string",
"description": "When provided, summon the window whose name or ID matches the given name value. If no such window exists, then create a new window with that name."
},
"dropdownDuration": {
"type": "number",
"minimum": 0,
"default": 0,
"description": "When provided with a positive number, \"slide\" the window in from the top of the screen using an animation that lasts dropdownDuration milliseconds."
},
"toggleVisibility": {
"type": "boolean",
"default": true,
"description": "When true, pressing the assigned keys for this action will dismiss (minimize) the window when the window is currently the foreground window."
}
}
}
]
},
"QuakeModeAction": {
"description": "This action is a special variation of the globalSummon action. It specifically summons a window called \"_quake\". If you would like to change the behavior of the quakeMode action, we recommended creating a new globalSummon entry.",
"allOf": [
{ "$ref": "#/definitions/ShortcutAction" },
{
"properties": {
"action": { "type": "string", "pattern": "quakeMode" }
}
}
]
},
"Keybinding": {
"additionalProperties": false,
"properties": {
@@ -1002,8 +659,6 @@
{ "$ref": "#/definitions/NewTabAction" },
{ "$ref": "#/definitions/SwitchToTabAction" },
{ "$ref": "#/definitions/MoveFocusAction" },
{ "$ref": "#/definitions/MovePaneAction" },
{ "$ref": "#/definitions/SwapPaneAction" },
{ "$ref": "#/definitions/ResizePaneAction" },
{ "$ref": "#/definitions/SendInputAction" },
{ "$ref": "#/definitions/SplitPaneAction" },
@@ -1013,7 +668,6 @@
{ "$ref": "#/definitions/WtAction" },
{ "$ref": "#/definitions/CloseOtherTabsAction" },
{ "$ref": "#/definitions/CloseTabsAfterAction" },
{ "$ref": "#/definitions/CloseTabAction" },
{ "$ref": "#/definitions/ScrollUpAction" },
{ "$ref": "#/definitions/ScrollDownAction" },
{ "$ref": "#/definitions/MoveTabAction" },
@@ -1021,11 +675,6 @@
{ "$ref": "#/definitions/NewWindowAction" },
{ "$ref": "#/definitions/NextTabAction" },
{ "$ref": "#/definitions/PrevTabAction" },
{ "$ref": "#/definitions/RenameTabAction" },
{ "$ref": "#/definitions/RenameWindowAction" },
{ "$ref": "#/definitions/FocusPaneAction" },
{ "$ref": "#/definitions/GlobalSummonAction" },
{ "$ref": "#/definitions/QuakeModeAction" },
{ "type": "null" }
]
},
@@ -1046,38 +695,16 @@
},
"icon": { "$ref": "#/definitions/Icon" },
"name": {
"description": "The name that will appear in the command palette. If one isn't provided, the terminal will attempt to automatically generate a name.\nIf name is a string, it will be the name of the command.\nIf name is a object, the key property of the object will be used to lookup a localized string resource for the command",
"properties": {
"key": {
"type": "string"
}
},
"description": "The name that will appear in the command palette. If one isn't provided, the terminal will attempt to automatically generate a name.",
"type": [
"string",
"object",
"null"
]
},
"iterateOn": {
"type": "string",
"description": "Used to create iterable commands based on other objects in your settings. Possible values:\n- \"profiles\" \n- \"schemes\"",
"enum": [
"profiles",
"schemes"
]
},
"commands": {
"description": "List of commands to execute",
"items": {
"$ref": "#/definitions/Keybinding/properties/command"
},
"minItems": 1,
"type": "array"
}
},
"anyOf": [
{"required": ["name","commands"]},
{"required": ["command"]}
"required": [
"command",
"keys"
],
"type": "object"
},
@@ -1120,16 +747,6 @@
"description": "When set to `true`, the color and font formatting of selected text is also copied to your clipboard. When set to `false`, only plain text is copied to your clipboard. An array of specific formats can also be used. Supported array values include `html` and `rtf`. Plain text is always copied.",
"$ref": "#/definitions/CopyFormat"
},
"trimBlockSelection": {
"default": false,
"description": "When set to true, trailing white-spaces will be removed from text in rectangular (block) selection while copied to your clipboard. When set to false, the white-spaces will be preserved.",
"type": "boolean"
},
"experimental.detectURLs": {
"default": true,
"description": "When set to true, URLs will be detected by the Terminal. This will cause URLs to underline on hover and be clickable by pressing Ctrl.",
"type": "boolean"
},
"disableAnimations": {
"default": false,
"description": "When set to `true`, visual animations will be disabled across the application.",
@@ -1168,10 +785,6 @@
"description": "When set to true, we will use the software renderer (a.k.a. WARP) instead of the hardware one.",
"type": "boolean"
},
"experimental.input.forceVT": {
"description": "Force the terminal to use the legacy input encoding. Certain keys in some applications may stop working when enabling this setting.",
"type": "boolean"
},
"initialCols": {
"default": 120,
"description": "The number of columns displayed in the window upon first load. If \"launchMode\" is set to \"maximized\" (or \"maximizedFocus\"), this property is ignored.",
@@ -1215,36 +828,13 @@
"type": [ "integer", "string" ],
"deprecated": true
},
"minimizeToTray": {
"default": "false",
"description": "When set to true, minimizing a Terminal window will no longer appear in the taskbar. Instead, a Terminal icon will appear in the system tray through which the user can access their windows.",
"type": "boolean"
},
"alwaysShowTrayIcon": {
"default": "false",
"description": "When set to true, the Terminal's tray icon will always be shown in the system tray.",
"type": "boolean"
},
"actions": {
"description": "Properties are specific to each custom action.",
"items": {
"$ref": "#/definitions/Keybinding"
},
"type": "array"
},
"keybindings": {
"description": "[deprecated] Use actions instead.",
"deprecated": true,
"description": "Properties are specific to each custom key binding.",
"items": {
"$ref": "#/definitions/Keybinding"
},
"type": "array"
},
"language": {
"default": "",
"description": "Sets an override for the app's preferred language, expressed as a BCP-47 language tag like en-US.",
"type": "string"
},
"theme": {
"default": "system",
"description": "Sets the theme of the application. The special value \"system\" refers to the active Windows system theme.",
@@ -1368,16 +958,6 @@
"description": "Sets the background color of the text. Overrides \"background\" from the color scheme. Uses hex color format: \"#rrggbb\".",
"type": ["string", "null"]
},
"unfocusedAppearance": {
"$ref": "#/definitions/AppearanceConfig",
"description": "Sets the appearance of the terminal when it is unfocused.",
"type": ["object", "null"]
},
"font": {
"$ref": "#/definitions/FontConfig",
"description": "Sets the font options of the terminal.",
"type": ["object", "null"]
},
"backgroundImage": {
"description": "Sets the file location of the image to draw over the window background.",
"oneOf": [
@@ -1428,7 +1008,7 @@
},
"bellStyle": {
"default": "audible",
"description": "Controls what happens when the application emits a BEL character. When set to \"all\", the Terminal will play a sound, flash the taskbar icon (if the terminal window is not in focus) and flash the window. An array of specific behaviors can also be used. Supported array values include `audible`, `window` and `taskbar`. When set to \"none\", nothing will happen.",
"description": "Controls what happens when the application emits a BEL character. When set to \"all\", the Terminal will play a sound and flash the taskbar icon. An array of specific behaviors can also be used. Supported array values include `audible` and `visual`. When set to \"none\", nothing will happen.",
"$ref": "#/definitions/BellStyle"
},
"closeOnExit": {
@@ -1494,20 +1074,18 @@
},
"fontFace": {
"default": "Cascadia Mono",
"description": "[deprecated] Define 'face' within the 'font' object instead.",
"type": "string",
"deprecated": true
"description": "Name of the font face used in the profile.",
"type": "string"
},
"fontSize": {
"default": 12,
"description": "[deprecated] Define 'size' within the 'font' object instead.",
"description": "Size of the font in points.",
"minimum": 1,
"type": "integer",
"deprecated": true
"type": "integer"
},
"fontWeight": {
"default": "normal",
"description": "[deprecated] Define 'weight' within the 'font' object instead.",
"description": "Sets the weight (lightness or heaviness of the strokes) for the given font. Possible values:\n -\"thin\"\n -\"extra-light\"\n -\"light\"\n -\"semi-light\"\n -\"normal\" (default)\n -\"medium\"\n -\"semi-bold\"\n -\"bold\"\n -\"extra-bold\"\n -\"black\"\n -\"extra-black\"\n or the corresponding numeric representation of OpenType font weight.",
"oneOf": [
{
"enum": [
@@ -1530,8 +1108,7 @@
"minimum": 100,
"type": "integer"
}
],
"deprecated": true
]
},
"foreground": {
"$ref": "#/definitions/Color",
@@ -1612,11 +1189,6 @@
"type": "boolean",
"default": false
},
"tabColor": {
"$ref": "#/definitions/Color",
"description": "Sets the color of the profile's tab. Using the tab color picker will override this color.",
"type": ["string", "null"]
},
"tabTitle": {
"description": "If set, will replace the name as the title to pass to the shell on startup. Some shells (like bash) may choose to ignore this initial value, while others (cmd, powershell) may use this value over the lifetime of the application.",
"type": ["string", "null"]

View File

@@ -1,65 +0,0 @@
# til::feature
Feature flags are controlled by an XML document stored at `src/features.xml`.
## Example Document
```xml
<?xml version="1.0"?>
<featureStaging xmlns="http://microsoft.com/TilFeatureStaging-Schema.xsd">
<feature>
<!-- This will produce Feature_XYZ::IsEnabled() and TIL_FEATURE_XYZ_ENABLED (preprocessor) -->
<name>Feature_XYZ</name>
<description>Does a cool thing</description>
<!-- GitHub deliverable number; optional -->
<id>1234</id>
<!-- Whether the feature defaults to enabled or disabled -->
<stage>AlwaysEnabled|AlwaysDisabled</stage>
<!-- Branch wildcards where the feature should be *DISABLED* -->
<alwaysDisabledBranchTokens>
<branchToken>branch/with/wildcard/*</branchToken>
<!-- ... more branchTokens ... -->
</alwaysDisabledBranchTokens>
<!-- Just like alwaysDisabledBranchTokens, but for *ENABLING* the feature. -->
<alwaysEnabledBranchTokens>
<branchToken>...</branchToken>
</alwaysEnabledBranchTokens>
<!-- Brandings where the feature should be *DISABLED* -->
<alwaysDisabledBrandingTokens>
<!-- Valid brandings include Dev, Preview, Release, WindowsInbox -->
<brandingToken>Release</brandingToken>
<!-- ... more brandingTokens ... -->
</alwaysDisabledBrandingTokens>
<!-- Just like alwaysDisabledBrandingTokens, but for *ENABLING* the feature -->
<alwaysEnabledBrandingTokens>
<branchToken>...</branchToken>
</alwaysEnabledBrandingTokens>
<!-- Unequivocally disable this feature in Release -->
<alwaysDisabledReleaseTokens />
</feature>
</featureStaging>
```
## Notes
Features that are disabled for Release using `alwaysDisabledReleaseTokens` are
*always* disabled in Release, even if they come from a branch that would have
been enabled by the wildcard.
### Precedence
1. `alwaysDisabledReleaseTokens`
2. Enabled branches
3. Disabled branches
* The longest branch token that matches your branch will win.
3. Enabled brandings
4. Disabled brandings
5. The feature's default state

View File

@@ -9,7 +9,7 @@ issue id: #1043
## Abstract
This spec is for task #1043 “Be able to set an initial position for the terminal”. It goes over the details of a new feature that allows users to set the initial position and size of the terminal. Expected behavior and design of this feature is included. Besides, future possible follow-up works are also addressed.
This spec is for task #1043 “Be able to set an initial position for the terminal”. It goes over the details of a new feature that allows users to set the initial position and size of the terminal. Expected behavior and design of this feature is included. Besides, future possible follow-up works are also addressed.
## Inspiration
@@ -17,7 +17,7 @@ The idea is to allow users to set the initial position of the Terminal when they
## Solution Design
For now, the Terminal window is put on a default initial position. The program uses CW_USEDEFAULT in the screen coordinates for top-left corner. We have two different types of window client window and non-client window. However, code path for window creation (WM_CREATE message is shared by the two types of windows) are almost the same for the two types of windows, except that there are some differences in calculation of the width and height of the window.
For now, the Terminal window is put on a default initial position. The program uses CW_USEDEFAULT in the screen coordinates for top-left corner. We have two different types of window client window and non-client window. However, code path for window creation (WM_CREATE message is shared by the two types of windows) are almost the same for the two types of windows, except that there are some differences in calculation of the width and height of the window.
Two new properties should be added in the json settings file:
@@ -92,9 +92,9 @@ For now, this feature only allows the user to set initial position and choose wh
3. We may also consider more launch modes. Like full screen mode and minimized mode.
GitHub issue for future follow-ups: https://github.com/microsoft/terminal/issues/766
Github issue for future follow-ups: https://github.com/microsoft/terminal/issues/766
## Resources
GitHub issue:
Github issue:
https://github.com/microsoft/terminal/issues/1043

View File

@@ -1,105 +0,0 @@
---
author: Pankaj Bhojwani, pabhojwa@microsoft.com
created on: 2021-6-17
last updated: 2021-6-23
issue id: #1790
---
# Font features and axes of variation
## Abstract
This spec outlines how we can allow users to specify font features and axes of variation for fonts in Windows Terminal. Font features include things like being able to specify whether ligatures should be used as well as the specific stylistic set used for a font. Axes of variation commonly include things like weight and slant but can also include fancier things like shadow distance, depending on the font.
## Inspiration
Reference: [#1790](https://github.com/microsoft/terminal/issues/1790)
Currently, if a font has ligatures, we offer no way for a user to disable them. Many users would like the option to do so, and would also like the ability to choose stylistic sets for fonts - for example, at the time of this writing, Cascadia Code offers 4 stylistic sets but we offer no way for users to specify any of them.
In a similar vein, many fonts allow for setting variations on the font along certain attributes, commonly referred to as 'axes of variation'. We can offer users more font customization options by allowing them to configure these font variations.
## Solution Design
### 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:
1. A font feature tag
2. A parameter value
A font feature tag is constructed using a 4-character feature tag and the parameter value defines how the feature is applied. For most features, the parameter value is simply treated as a binary value - a value of 0 means the feature is not applied and a non-zero value means the feature is applied. For example, a font feature struct like {'ss03', 1} enables stylistic set 3 for the font and a font feature struct like {'liga', 0} disables ligatures. (Technically, the feature tag is _constructed_ with the 4-character tag and is not the 4-character tag itself, but they are treated the same in the example here for brevity's sake).
Currently, we pass in to DWrite a null value for the list of features to apply to the font. This causes DWrite to automatically apply a ['standard' list](https://github.com/fdwr/TextLayoutSampler/blob/master/DrawableObject.ixx#L802) of font features to the font. Naturally, passing in our own list of font features to DWrite means DWrite will _only_ apply the features we defined, and no longer apply the standard list. Since the standard list contains 11 features, we need to consider how we can allow users to specify 1 additional feature or delete 1 of the standard features without needing to redefine all the others.
We will do this by allowing users to define a dictionary in their settings.json file, where the keys are the 4-character feature tags and the values are the parameter values. This dictionary will then get applied to our internal dictionary (which will contain the standard list of 11 features with their parameter values), meaning that any new key-value pairs will get added to our dictionary and any existing key-value pairs will get updated. Finally, this 'merged' dictionary will be what we use to construct the list of features to pass into DWrite.
### Axes of variation
Specifying axes of variation is done in an extremely similar manner to the way font features are specified - a 4-character tag is used to specify which font axis is being modified and a numerical value is provided to specify the value the axis should be set to. For example, {'slnt', 20} specifies that the 'slant' axis should be set to 20.
There is also a standard list of axes of variation, and each axis has its own default. We will approach this the same way we approached font features, by allowing users to specify additional features or omit features without needing to redefine the defaults.
## UI/UX Design
Users will be able to add a new setting to their font objects (added in [#10433](https://github.com/microsoft/terminal/pull/10433)). The resultant font object may look something like this
```json
"font": {
"face": "Cascadia Code",
"size": 12,
"features": {
"ss03": 1,
"liga": 0
},
"axes": {
"slnt": 20.5
}
}
```
There is one point to note here about clashing. For example, if a user has the old "weight" setting defined _as well as_ a "wght" axis defined, we will only use the "wght" axis value. We prioritize that value for a few reasons:
1. It is the more recent addition to our settings model. Thus, it is likely that a user that has defined both values probably just forgot to remove the old value.
2. It is the more precise value, it is a specific float value whereas the the old "weight" setting is an enum (that eventually gets mapped to a float value).
## Capabilities
### Accessibility
Should not affect accessibility.
### Security
Should not affect security.
### Reliability
Aside from additional parsing required for the settings file (which inherently offers more locations for parsing to fail), we need to be careful about badly formed/non-existant feature tags or axes specified in the user-defined dictionaries. We must make sure to ignore such declarations (perhaps alongside emitting a warning to the user) and only apply those that are correctly formed and exist.
### 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.
### Performance, Power, and Efficiency
Currently when rendering a run of text, if we detect that the given run is simple we will use a shortcut to obtain the glyphs needed, skipping over an expensive `GetGlyphs` call to DWrite. However, when the default feature list is changed in any way (either by adding a new feature or removing one of the defaults), there is no way for us to detect beforehand how the font glyphs would change.
This means that as long as the user requests a change to the default font feature list, we will _always_ skip the shortcut and call the expensive `GetGlyphs` function for every run of text.
This will naturally cause a performance cost that we will have to bear for this feature. However, it is worth noting that there are a fair number of glyphs that will cause a run of text to be deemed "not simple" (and thus cause us to call `GetGlyphs` anyway), for example when using Cascadia Code, any run of text that has the letters 'i', 'j', 'l', 'n', 'w' or 'x' is not considered simple (because those glyphs have localized variants).
## Potential Issues
See performance issues above.
## Future considerations
DWrite additionally offers the ability to vary the font features across runs of text. However, for our initial implementation of this feature, we will only apply font features to the entire buffer. If/when we decide to allow specifying font features for particular runs of text, we can lean into our existing mechanisms of splitting up runs of text to implement that.
We will also need to consider how we want to represent this in the settings UI. This is slightly more complex than other settings since users should be allowed to manually input 4-character tags.
## Resources
[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)

View File

@@ -123,4 +123,4 @@ This open issue tracks the phase features of Search: https://github.com/microsof
## Resources
GitHub Issue: https://github.com/microsoft/terminal/issues/605
Github Issue: https://github.com/microsoft/terminal/issues/605

View File

@@ -1,736 +0,0 @@
---
author: Mike Griese @zadjii-msft
created on: 2021-02-23
last updated: 2021-05-13
issue id: #653
---
# Quake Mode
## Abstract
Many existing terminals support a feature whereby a user can press a keybinding
anywhere in the OS, and summon their terminal application. Oftentimes the act of
summoning this window is accompanied by a "dropdown" animation, where the window
slides in to view from the top of the screen. This global summon action is often
referred to as "quake mode", a reference to the video game Quake, who's console
slid in from the top.
This spec addresses both of the following two issues:
* "Quake Mode" ([#653])
* "Minimize to tray" ([#5727])
Readers should make sure to have read the [Process Model 2.0 Spec], for
background on Monarch and Peasant processes.
## Background
### Inspiration
For an example of the original Quake console in action, take a look at the
following video (noisy video warning): [Quake 3 sample]. Additionally, plenty of
existing terminal emulators support similar functionality:
* **Tilda** allows the user to specify different keys to summon the window on
different monitors.
* **Guake** alternatively allows the user to either summon the terminal window to
a specific monitor, or whichever monitor the mouse is on. Guake only allows
one single instance, so pressing the global hotkey always summons the same
instance.
### User Stories
The original quake mode thread (#653) is absolutely _filled_ with variations on
how users want to be able to summon their terminal windows. These include, but
are not limited to:
* **Story A** Press a hotkey anywhere to activate the single Terminal window
wherever it was
* **Story B** Press a hotkey anywhere to activate the single Terminal window _on
the current monitor_. If it wasn't previously on that monitor, move it there.
* **Story C** When the Terminal is summoned using the hotkey, have it "slide in"
from the top. Similarly, slide out on deactivate.
* **Story D** <kbd>Ctrl+1</kbd> to activate the terminal on monitor 1,
<kbd>Ctrl+2</kbd> to activate the terminal on monitor 2.
* **Story E** Variable dropdown speed
* **Story F** Minimize to tray, press a hotkey to activate the terminal window
(#5727)
* **Story G** Terminal doesn't appear in alt+tab view, press a hotkey to
activate the single terminal window / the nearest terminal window (I'm not
sure this is distinct from the above)
## Solution Design
To implement this feature, we'll add the following settings:
* a new action, named `globalSummon`.
* a new global, app setting named `minimizeToTray`
* a new global, app setting named `alwaysShowTrayIcon`
* a new action, named `quakeMode`, and a specially named `_quake` window.
### `globalSummon` Action
The `globalSummon` action will be a keybinding the user can use to summon a
Terminal window from anywhere in the OS. Various arguments to the action will
specify which window is summoned, to where, and how the window should behave on
summon.
From a technical perspective, the action will work by using the
[`RegisterHotKey`] function. This API allows us to bind a particular hotkey with
the OS. Whenever that hotkey is pressed, our window message loop will receive a
`WM_HOTKEY`. We'll use the payload of that window message to lookup the action
arguments for that hotkey. Then we'll use those arguments to control which
window is invoked, where, and how the window behaves.
Since `RegisterHotKey` can only be used to register a hotkey _once_ with the OS,
we'll need to make sure it's only ever set up by the Monarch process. We know
that there will only ever be one Monarch for the Terminal at a time, so it's the
perfect process to have the responsibility of managing the global hotkey.
The Monarch will be responsible for calling `RegisterHotKey`, and processing the
`WM_HOTKEY` messages. It will then dispatch method calls to the appropriate
window to summon it. When a Monarch dies and a new process becomes the Monarch,
the new Monarch will re-register for the hotkeys.
#### Where in the settings?
Since users may want to bind multiple keys to summon different windows, we'll
need to allow the user to specify multiple keybindings simultaneously, each with
their own set of args.
We stick all the `globalSummon`s in the actions array, like they're any other
keybinding.
However, these are not keys that are handled by the TerminalApp layer itself.
These are keys that need to be registered with the OS. So while they will be in
the normal `KeyMap`, they will need to be retrieved from that object and
manually passed to the window layer.
> A previous iteration of this spec considered placing the `globalSummon`
> actions in their own top-level array of the settings file, separate from the
> keybindings. This is no longer being considered, because it would not work for
> the case where the user has something like:
> ```json
> { "keys": "ctrl+c", "command": { "action": "globalSummon", "monitor": 1 } },
> { "keys": "ctrl+v", "command": { "action": "copy" } },
> ```
#### Which window, and where?
When looking at the list of requested scenarios, there are lots of different
ways people would like to use the global summon action. Some want the most
recent window activated, always. Others want to have one window _per monitor_.
Some would like to move the window to where the user is currently interacting
with the PC, and others want to activate the window where it already exists.
Trying to properly express all these possible configurations is complex. The
settings should be unambiguous as to what will happen when you press the
keybinding.
I believe that in order to accurately support all the variations that people
might want, we'll need two properties in the `globalSummon` action. These
properties will specify _which_ window we're summoning, and _where_ to summon
the window. To try and satisfy all these scenarios, I'm proposing the following
two arguments to the `globalSummon` action:
```json
"monitor": "any"|"toCurrent"|"toMouse"|"onCurrent"|int,
"desktop": "any"|"toCurrent"|"onCurrent"
```
The way these settings can be combined is in a table below. As an overview:
* `monitor`: This controls the monitor that the window will be summoned from/to
- `"any"`: Summon the MRU window, regardless of which monitor it's currently
on.
- `"toCurrent"`/omitted: (_default_): Summon the MRU window **TO** the monitor
with the current **foreground** window.
- `"toMouse"`: Summon the MRU window **TO** the monitor where the **mouse**
cursor is.
- `"onCurrent"`: Summon the MRU window **ALREADY ON** the current monitor.
- `int`: Summon the MRU window for the given monitor (as identified by the
"Identify" displays feature in the OS settings)
* `desktop`: This controls how the terminal should interact with virtual desktops.
- `"any"`: Leave the window on whatever desktop it's already on - we'll switch
to that desktop as we activate the window.
- > NOTE: A previous version of this spec had this enum value as `null`.
This was changed to `"any"` for parity with the `monitor` property.
- `"toCurrent"`/omitted: (_default_): Move the window **to** the current
virtual desktop
- `"onCurrent"`: Only summon the window if it's **already on** the current
virtual desktop
Neither `desktop` nor `monitor` is a required parameter - if either is omitted,
the omitted property will default to `toCurrent`.
Together, these settings interact in the following ways:
<!-- This table is formatted for viewing as rendered HTML. It's too complicated
for pure markdown, sorry. -->
<table>
<tr>
<td></td>
<th colspan=3><code>"desktop"</code></th>
</tr>
<!-- ----------------------------------------------------------------------- -->
<tr>
<th><code>"monitor"</code></th>
<td><code>any</code><br><strong>Leave where it is</strong></td>
<td><code>"toCurrent"</code><br><strong>Move to current desktop</strong></td>
<td><code>"onCurrent"</code><br><strong>On current desktop only</strong></td>
</tr>
<!-- ----------------------------------------------------------------------- -->
<tr>
<td><code>"any"</code><br> Summon the MRU window</td>
<td>Go to the desktop the window is on (leave position alone)</td>
<td>Move the window to this desktop (leave position alone)</td>
<td>
If there isn't one on this desktop:
* create a new one (default position)
Else:
* activate the one on this desktop (don't move it)
</td>
</tr>
<!-- ----------------------------------------------------------------------- -->
<tr>
<td><code>"toCurrent"</code><br> Summon the MRU window TO the monitor with the foreground window</td>
<td>Go to the desktop the window is on, move to the monitor with the foreground window</td>
<td>Move the window to this desktop, move to the monitor with the foreground window</td>
<td>
If there isn't one on this desktop:
* create a new one (on the monitor with the foreground window)
Else:
* activate the one on this desktop, move to the monitor with the foreground window
</td>
</tr>
<!-- ----------------------------------------------------------------------- -->
<tr>
<td>
<code>"toMouse"</code>
<sup><a href="#footnote-2">[2]</a></sup> <br>
Summon the MRU window TO the monitor with the mouse</td>
<td>Go to the desktop the window is on, move to the monitor with the mouse</td>
<td>Move the window to this desktop, move to the monitor with the mouse</td>
<td>
If there isn't one on this desktop:
* create a new one (on the monitor with the mouse)
Else:
* activate the one on this desktop, move to the monitor with the mouse
</td>
</tr>
<!-- ----------------------------------------------------------------------- -->
<tr>
<td><code>"onCurrent"</code><br> Summon the MRU window for the current monitor</td>
<td>
If there is a window on this monitor on any desktop,
* Go to the desktop the window is on (leave position alone)
else
* Create a new window on this monitor & desktop
</td>
<td>
If there is a window on this monitor on any desktop,
* Move the window to this desktop (leave position alone)
else
* Create a new window on this monitor & desktop
</td>
<td>
If there isn't one on this desktop, (even if there is one on this monitor on
another desktop),
* create a new one on this monitor
Else if ( there is one on this desktop, not this monitor)
* create a new one on this monitor
Else (one on this desktop & monitor)
* Activate the one on this desktop (don't move)
</td>
</tr>
<!-- ----------------------------------------------------------------------- -->
<tr>
<td><code>int</code><br> Summon the MRU window for monitor N</td>
<td>
If there is a window on monitor N on any desktop,
* Go to the desktop the window is on (leave position alone)
else
* Create a new window on this monitor & desktop
</td>
<td>
If there is a window on monitor N on any desktop,
* Move the window to this desktop (leave position alone)
else
* Create a new window on this monitor & desktop
</td>
<td>
If there isn't one on this desktop, (even if there is one on monitor N on
another desktop),
* create a new one on monitor N
Else if ( there is one on this desktop, not monitor N)
* create a new one on monitor N
Else (one on this desktop & monitor N)
* Activate the one on this desktop (don't move)
</td>
</tr>
</table>
##### Stories, revisited
With the above settings, let's re-examine the original user stories, and see how
they fit into the above settings. (_Stories that are omitted aren't relevant to
the discussion of these settings_)
> When the `desktop` param is omitted below, that can be interpreted as "any
> `desktop` value will make sense here"
* **Story A** Press a hotkey anywhere to activate the single Terminal window
wherever it was
- This is `{ "monitor": "any", "desktop": "any" }`
* **Story B** Press a hotkey anywhere to activate the single Terminal window _on
the current monitor_. If it wasn't previously on that monitor, move it there.
- This is `{ "monitor": "toCurrent" }`
* **Story D** <kbd>Ctrl+1</kbd> to activate the terminal on monitor 1,
<kbd>Ctrl+2</kbd> to activate the terminal on monitor 2.
- This is `[ { "keys": "ctrl+1", monitor": 1 }, { "keys": "ctrl+2", monitor": 2 } ]`
As some additional examples:
```json
// Go to the MRU window, wherever it is
{ "keys": "win+1", "command":{ "action":"globalSummon", "monitor":"any", "desktop": "any" } },
// activate the MRU window, and move it to this desktop & this monitor
{ "keys": "win+2", "command":{ "action":"globalSummon", "monitor":"toCurrent", "desktop": "toCurrent" } },
// Since "toCurrent" & "toCurrent" are the default values, just placing a single
// entry here will bind the same behavior:
{ "keys": "win+2", "command": "globalSummon" },
// activate the MRU window on this desktop
{ "keys": "win+3", "command":{ "action":"globalSummon", "monitor":"any", "desktop": "onCurrent" } },
// Activate the MRU window on monitor 2 (from any desktop), and place it on the
// current desktop. If there isn't one on monitor 2, make a new one.
{ "keys": "win+4", "command":{ "action":"globalSummon", "monitor": 2, "desktop": "toCurrent" } },
// Activate the MRU window on monitor 3 (ONLY THIS desktop), or make a new one.
{ "keys": "win+5", "command":{ "action":"globalSummon", "monitor": 3, "desktop": "onCurrent" } },
// Activate the MRU window on this monitor (from any desktop), and place it on
// the current desktop. If there isn't one on this monitor, make a new one.
{ "keys": "win+6", "command":{ "action":"globalSummon", "monitor": "onCurrent", "desktop": "toCurrent" } },
```
#### Summoning a specific window
What if you want to press a keybinding to always summon a specific, named
window? This window might not be the most recent terminal window, nor one that
would be selected by the `monitor` and `desktop` selectors. You could name a
window "Epona", and press `win+e` to always summon the "Epona" window.
We'll add the following property to address this scenario
* `"window": string|int`
- When omitted (_default_): Use monitor and desktop to find the appropriate
MRU window to summon.
- When provided: Always summon the window who's name or ID matches the given
`window` value. If no such window exists, then create a new window with that
name/id.
When provided _with_ `monitor` and `desktop`, `window` behaves in the following
ways:
* `desktop`
- `"any"`: Go to the desktop the given window is already on.
- `"toCurrent"`: If the window is on another virtual desktop, then move it to
the currently active one.
- `"onCurrent"`: If the window is on another virtual desktop, then move it to
the currently active one.
* `monitor`
- `"any"`: Leave the window on the monitor it is already on.
- `"toCurrent"`: If the window is on another monitor, then move it to the
currently active one.
- `"onCurrent"`: If the window is on another monitor, then move it to the
currently active one.
- `<int>`: If the window is on another monitor, then move it to the specified
monitor.
> NOTE: You read that right, `onCurrent` and `toCurrent` both do the same thing
> when `window` is provided. They both already know which window to select, the
> context of moving to the "current" monitor is all that those parameters add.
#### Other properties
Some users would like the terminal to just appear when the global hotkey is
pressed. Others would like the true quake-like experience, where the terminal
window "slides-in" from the top of the monitor. Furthermore, some users would
like to configure the speed at which that dropdown happens. To support this
functionality, the `globalSummon` action will support the following property:
* `"dropdownDuration": float`
- When omitted, `0`, or a negative number: No animation is used
when summoning the window. The summoned window is focused immediately where
it is.
- When a positive number is provided, the terminal will use that value as a
duration (in seconds) to slide the terminal into position when activated.
- The default would be some sensible value. The pane animation is .2s, so
`0.2` might be a reasonable default here.
We could have alternatively provided a `"dropdownSpeed"` setting, that provided
a number of pixels per second. In my opinion, that would be harder for users to
use correctly. I believe that it's easier for users to mentally picture "I'd
like the dropdown to last 100ms" vs "My monitor is 1504px tall, so I need to set
this to 15040 to make the window traverse the entire display in .1s"
> NOTE: `dropdownDuration` will be ignored when the user has animations disabled
> in the OS. In that case, the terminal will just appear, as if it was set to 0.
Some users might want to be able to use the global hotkey to hide the window
when the window is already visible. This would let the hotkey act as a sort of
global toggle for the Terminal window. Others might not like that behavior, and
just want the action to always bring the Terminal into focus, and do nothing if
the terminal is already focused. To facilitate both these use cases, we'll add
the following property:
* `"toggleVisibility": bool`
- When `true`: (_default_) When this hotkey is pressed, and the terminal
window is currently active, minimize the window.
- When `dropdownDuration` is not `0`, then the window will slide back off
the top at the same speed as it would come down.
- When `false`: When this hotkey is pressed, and the terminal window is
currently active, do nothing.
### Quake Mode
In addition to just summoning the window from anywhere, some terminals also
support a special "quake mode" buffer or window. This window is one that closely
emulates the console from quake:
* It's docked to the top of the screen
* It takes the full width of the monitor, and only the bottom can be resized
* It often doesn't have any other UI elements, like tabs
For fun, we'll also be adding a special `"_quake"` window with the same
behavior. If the user names a window `_quake`, then it will behave in the
following special ways:
* On launch, it will ignore the `initialPosition` and
`initialRows`/`initialCols` setting, and instead resize to the top half of the
monitor.
* On launch, it will ignore the `launchMode` setting, and always launch in focus
mode.
- Users can disable focus mode on the `_quake` window if they do want tabs.
* It will not be resizable from any side except the bottom of the window, nor
will it be drag-able.
* It will not be a valid target for the "most recent window" for window
glomming. If it's the only open window, with `"windowingBehavior":
"useExisting*"`, then a new window will be created instead.
- It _is_ still a valid target for something like `wt -w _quake new-tab`
A window at runtime can be renamed to become the `_quake` window (if no other
`_quake` window exists). When it does, it will resize to the position of the
quake window, and enter focus mode.
We'll also be adding a special action `quakeMode`. This action is a special case
of the `globalSummon` action, to specifically invoke the quake window in the
current place. It is basically the same thing as the more elaborate:
```json
{
"monitor": "toCurrent",
"desktop": "toCurrent",
"window": "_quake",
"toggleVisibility": true,
"dropdownDuration": 0.5
},
```
### Minimize to Tray
Many users have requested that the terminal additionally supports minimizing the
window "to the tray icon". This is a bit like when you close the Teams window,
but Teams is actually still running in the system tray, or the "notification
area".
![The Teams tray icon](tray-icon-000.png)
_fig 1: an example of the Teams tray icon in the notification area_.
When users want to be able to "minimize to the tray", they want:
* The window to no longer appear on the taskbar
* The window to no longer appear in the alt-tab order
When minimized to the tray, it's almost as if there's no window for the Terminal
at all. This can be combined with the global hotkey (or the tray icon's context
menu) to quickly restore the window.
The tray icon could be used for a variety of purposes. As a simple start, we
could include the following three options:
```
Focus Terminal
---
Windows > Window 1 - <un-named window>
Window 2 - "This-window-does-have-a-name"
---
Quit
```
Just clicking on the icon would summon the recent terminal window. Right
clicking would show the menu with "Focus Terminal", "Windows" and "Quit" in it, and
"Windows" would have nested entries for each Terminal window.
* "Focus Terminal" would do just that - summon the most recent terminal window,
wherever it is.
* "Windows" would have nested popups for each open Terminal window. Each of
these nested entries would display the name and ID of the window. Clicking
them would summon that window (wherever it may be)
* "Quit" would be akin to quit in browsers - close all open windows
<sup>[[1]](#footnote-1)</sup>.
The tray notification would be visible always when the user has
`"minimizeToTray": true` set in their settings. If the user has that set to
false, but would still like the tray, they can specify `"alwaysShowTrayIcon":
true`. That will cause the tray icon to always be added to the system tray.
There's not a combination of settings where the Terminal is "minimized to the
tray", and there's _no tray icon visible_. We don't want to let users get into a
state where the Terminal is running, but is totally hidden from their control.
From a technical standpoint, the tray icon is managed similar to the global
hotkey. The Monarch process is responsible for setting it up, and processing the
messages. When a Monarch dies and a new process becomes the Monarch, then it
will re-create the tray icon.
## UI/UX Design
To summarize, we're proposing the following set of settings:
```jsonc
{
"minimizeToTray": bool,
"alwaysShowTrayIcon": bool,
"actions": [
{
"keys": KeyChord,
"command": {
"action": "globalSummon",
"dropdownDuration": float,
"toggleVisibility": bool,
"monitor": "any"|"toCurrent"|"onCurrent"|int,
"desktop": "any"|"toCurrent"|"onCurrent"
}
},
{
"keys": KeyChord,
"command": {
"action": "quakeMode"
}
}
]
}
```
## Potential Issues
<table>
<tr>
<td><strong>Compatibility</strong></td>
<td>
As part of this set of changes, we'll also be allowing the <kbd>Win</kbd> key in
keybindings. Generally, the OS reserves the Windows key for its own shortcuts.
For example, <kbd>Win+R</kbd> for the run dialog, <kbd>Win+A</kbd> for the
Action Center, <kbd>Win+V</kbd> for the cloud clipboard, etc. Users will now be
able to use the win key themselves, but they should be aware that the OS has
"first dibs" on any hotkeys involving the Windows key.
</td>
</tr>
<tr>
<td><strong>Mixed elevation</strong></td>
<td>
Only one app at a time gets to register for global hotkeys. However, from the
Terminal's perspective, unelevated and elevated windows will act like different
apps. Each privilege level has its own Monarch. The two are unable to
communicate across the elevation boundary.
This means that if the user often runs terminals in both contexts, then only one
will have the global hotkeys bound. The naive implementation would have the
first elevation level "win" the keybindings.
A different option would be to have elevated windows not register global hotkeys
_at all_. I don't believe that there's any sort of security implication for
having a global hotkey for an elevated window.
A third option would be to have some sort of `"whenElevated": bool?` property
for global hotkeys. This would explicitly enable a given hotkey for unelevated
vs elevated windows.
* `"whenElevated": null`: behave as normal - the first context level to run wins
* `"whenElevated": true`: only register the hotkey when running elevated
* `"whenElevated": false`: only register the hotkey when running unelevated
</td>
</tr>
<tr>
<td><strong>OneCore / Windows 10X</strong></td>
<td>
I'm fairly certain that none of these APIs would work on Windows 10X at all.
These features would have to initially be disabled in a pure UWP version of the
Terminal, until we could find workarounds. Since the window layer is the one
responsible for the management of the hotkeys and the tray icon, we're not too
worried about this.
</td>
</tr>
</table>
* If there are any other applications running that have already registered
hotkeys with `RegisterHotKey`, then it's possible that the Terminal's attempt
to register that hotkey will fail. If that should happen, then we should
display a warning dialog to the user indicating which hotkey will not work
(because it's already used for something else).
* Which is the "current" monitor? The one with the mouse or the one with the
active window? This isn't something that has an obvious answer. Guake
implements this feature where the "current monitor" is the one with the mouse
on it. At least for the first iterations of this action, that's what we'll
use.
`monitor: onCurrent|onCurrentWindow|toCurrent|<int>`
* Currently, running both the Release and Preview versions of the Terminal at
the same time side-by-side is not generally supported. (For example, `wt.exe`
can only ever point at one of two.) If a user binds the same key to a
`globalSummon` or `quakeMode` action, then only one of the apps will actually
be able to successfully claim the global hotkey.
## Implementation plan
Currently, in [`dev/migrie/f/653-QUAKE-MODE`], I have some sample rudimentary
code to implement quake mode support. It allows for only a single global hotkey
that summons the MRU window, without dropdown. That would be a good place for
anyone starting to work on this feature. From there, I imagine the following
work would be needed:
* [ ] Add a `globalSummon` action. `AppHost` would need to be able to get _all_
of these actions, and register all of them. Each one would need to be assigned
a unique ID, so `WM_HOTKEY` can identify which hotkey was pressed.
- This could be committed without any other args to the `globalHotkeys`. In
this initial version, the behavior would be summoning the MRU window,
where it is, no dropdown, to start with. From there, we'd add the
remaining properties:
* [ ] Add support for the `toggleVisibility` property
* [ ] Add support for the `desktop` property to control how window summoning
interacts with virtual desktops
* [ ] Add support for the `monitor` which monitor the window appears on.
* [ ] Add support for the `dropdownDuration` property
* [ ] Add the `minimizeToTray` setting, and implement it without any sort of flyout
* [ ] Add a list of windows to the right-click flyout on the tray icon
* [ ] Add support for the `alwaysShowTrayIcon` setting
* [ ] When the user creates a window named `_quake`, ignore the initial size,
position, and launch mode, and create the window in quake mode instead.
* [ ] Exempt the `_quake` window from window glomming
* [ ] Add the `quakeMode` action, which `globalSummon`'s the `_quake` window.
* [ ] Prevent the `_quake` window from being dragged or resized on the
top/left/right.
### Future Considerations
I don't believe there are any other tracked requests that are planned that
aren't already included in this spec.
* Should the tray icon's list of windows include window titles? Both the name
and title? Maybe something like `({name}|{id}): {title}`? I'd bet that most
people don't end up naming their windows.
* Dropdown duration could be a `float|bool`, with `true`->(whatever the default
is), `false`->0.
- We could have the setting appear as a pair of radio buttons, with the first
disabling dropdown, and the second enabling a text box for inputting an
animation duration.
* It might be an interesting idea to have the ability to dock the quake window
to a specific side of the monitor, not just the top. We could probably do that
with a global setting `"quakeModeDockSide": "top"|"left"|"bottom"|"right"` or
something like that.
* We might want to pre-load the quake window into the tray icon as an entry for
"Quake Mode", and otherwise exclude it from the list of windows in that menu.
* We might think of other things for the Quake Mode window in the future - this
spec is by no means comprehensive. For example, it might make sense for the
quake mode window to automatically open in "always on top" mode.
* It was suggested that the quake mode window could auto-hide when it loses
focus. That's a really neat idea, but we're a little worried about the
implementation. What happens when the IME window gets focus? Or the Start
Menu? Would those end up causing the quake window to prematurely minimize
itself? For that reason, we're leaving this as a future consideration.
* Perhaps there could be a top-level object in the settings like
```json
{
"quakeMode": {
"hideOnFocusLost": true,
"useFocusMode": false,
"profile": "my quake mode profile" ,
"quakeModeDockSide": "bottom"
}
}
```
That would allow the user some further customizations on the quake mode
behaviors.
- This was later converted to the idea in [#9992] - Add per-window-name global
settings
* Another proposed idea was a simplification of some of the summoning modes. `{
"monitor": "any", "desktop": "any" }` is a little long, and maybe not the most
apparent naming. Perhaps we could add another property like `summonMode` that
would act like an alias for a `monitor`, `desktop` combo.
- `"summonMode": "activateInMyFace"`: `{ "monitor": "toCurrent", "desktop": "toCurrent" }`
- `"summonMode": "activateWherever"`: `{ "monitor": "any", "desktop": "any" }`
## Resources
Docs on adding a system tray item:
* https://docs.microsoft.com/en-us/windows/win32/shell/notification-area
* https://www.codeproject.com/Articles/18783/Example-of-a-SysTray-App-in-Win32
Docs regarding hiding a window from the taskbar:
* https://docs.microsoft.com/en-us/previous-versions//bb776822(v=vs.85)#managing-taskbar-buttons
### Footnotes
<a name="footnote-1"><a>[1]: Quitting the terminal is different than closing the
windows one-by-one. Quiting implies an atomic action, for closing all the
windows. Once [#766] lands, this will give us a chance to persist the state of
_all_ open windows. This will allow us to re-open with all the user's windows,
not just the one that happened to be closed last.
<a name="footnote-2"><a>[2]: **Addenda, May 2021**: In the course of
implementation, it became apparent that there's an important UX difference
between summoning _to the monitor with the cursor_ vs _to the monitor with the
foreground window_. `"monitor": "toMouse"` was added as an option, to allow the
user to differentiate between the two behaviors.
[#653]: https://github.com/microsoft/terminal/issues/653
[#766]: https://github.com/microsoft/terminal/issues/766
[#5727]: https://github.com/microsoft/terminal/issues/5727
[#9992]: https://github.com/microsoft/terminal/issues/9992
[Process Model 2.0 Spec]: https://github.com/microsoft/terminal/blob/main/doc/specs/%235000%20-%20Process%20Model%202.0/%235000%20-%20Process%20Model%202.0.md
[Quake 3 sample]: https://youtu.be/ZmR6HQbuHPA?t=27
[`RegisterHotKey`]: https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-registerhotkey
[`dev/migrie/f/653-QUAKE-MODE`]: https://github.com/microsoft/terminal/tree/dev/migrie/f/653-QUAKE-MODE

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

View File

@@ -1,344 +0,0 @@
---
author: Carlos Zamora @carlos-zamora
created on: 2021-03-12
last updated: 2021-03-17
issue id: [#885]
---
# Actions in the Settings Model
## Abstract
This spec proposes a refactor of how Windows Terminal actions are stored in the settings model.
The new representation would mainly allow the serialization and deserialization of commands and keybindings.
## Inspiration
A major component that is missing from the Settings UI is the representation of keybindings and commands.
The JSON represents both of these as a combined entry as follows:
```js
{ "icon": "path/to/icon.png", "name": "Copy the selected text", "command": "copy", "keys": "ctrl+c" },
```
In the example above, the copy action is...
- bound to <kbd>ctrl+c</kbd>
- presented as "Copy the selected text" with the "path/to/icon.png" icon
However, at the time of writing this spec, the settings model represents it as...
- (key binding) a `KeyChord` to `ActionAndArgs` entry in a `KeyMapping`
- (command) a `Command` with an associated icon, name, and action (`ActionAndArgs`)
This introduces the following issues:
1. Serialization
- We have no way of knowing when a command and a key binding point to the same action. Thus, we don't
know when to write a "name" to the json.
- We also don't know if the name was auto-generated or set by the user. This can make the JSON much more bloated by
actions with names that would normally be autogenerated.
2. Handling Duplicates
- The same action can be bound to multiple key chords. The command palette combines all of these actions into one entry
because they have the same name. In reality, this same action is just being referenced in different ways.
## Solution Design
I propose that the issues stated above be handled via the following approach.
### Step 1: Consolidating actions
`Command` will be updated to look like the following:
```c++
runtimeclass Command
{
// The path to the icon (or icon itself, if it's an emoji)
String IconPath;
// The associated name. If none is defined, one is auto-generated.
String Name;
// The key binding that can be used to invoke this action.
// NOTE: We're actually holding the KeyChord instead of just the text.
// KeyChordText just serializes the relevant keychord
Microsoft.Terminal.Control.KeyChord Keys;
String KeyChordText;
// The action itself.
ActionAndArgs ActionAndArgs;
// NOTE: nested and iterable command logic will still be here,
// But they are omitted to make this section seem cleaner.
// Future Considerations:
// - [#6899]: Action IDs --> add an identifier here
}
```
The goal here is to consolidate key binding actions and command palette actions into a single class.
This will also require the following supplemental changes:
- `Command::LayerJson`
- This must combine the logic of `KeyMapping::LayerJson` and `Command::LayerJson`.
- Key Chord data
- Internally, store a `vector<KeyChord> _keyMappings` to keep track of all the key chords associated with this action.
- `RegisterKey` and `EraseKey` update `_keyMappings`, and ensure that the latest key registered is at the end of the list.
- `Keys()` simply returns the last entry of `_keyMappings`, which is the latest key chord this action is bound to.
- `KeyChordText())` is exposed to pass the text directly to the command palette.
This depends on `Keys` and, thus, propagate changes automatically.
- Observable properties
- `Command` has observable properties today, but does not need them because `Command` will never change while the app is running.
- Nested and iterable commands
- `HasNestedCommands`, `NestedCommands{ get; }`, `IterateOn` will continue to be exposed.
- A setter for these customizations will not be exposed until we find it necessary (i.e. adding support for customizing it in the Settings UI)
- Command expansion can continue to be exposed here to reduce implementation cost.
- An additional `IsNestedCommand` is necessary to record a case where a nested command is being unbound `{ "commands": null, "name": "foo" }`.
Overall, the `Command` class is simply being promoted to include the `KeyChord` it has.
This allows the implementation cost of this step to be relatively small.
Completion of this step should only cause relatively minor changes to anything that depends on `Command`, because
it is largely the same class. However, key bindings will largely be impacted because we represent key bindings as
a map of `KeyChord`s to `ActionAndArgs`. This leads us to step 2 of this process.
### Step 2: Querying actions
Key bindings and commands are deserialized by basically storing individual actions to a map.
- `KeyMapping` is basically an `IMap<KeyChord, ActionAndArgs>` with a few extra functions. In fact, it actually
stores key binding data to a `std::map<KeyChord, ActionAndArgs>` and directly interacts with it.
- `Command::LayerJson` populates an `IMap<String, Command>` during deserialization as it iterates over every action.
Note that `Command` can be interpreted as a wrapper for `ActionAndArgs` with more stuff here.
It makes sense to store these actions as maps. So, following step 1 above, we can also store and expose actions
something like the following:
```c++
runtimeclass ActionMap
{
ActionAndArgs GetActionByKeyChord(KeyChord keys);
KeyChord GetKeyBindingForAction(ShortcutAction action);
KeyChord GetKeyBindingForAction(ShortcutAction action, IActionArgs actionArgs);
IMapView<String, Command> NameMap { get; };
// Future Considerations:
// - [#6899]: Action IDs --> GetActionByID()
}
```
The getters will return null if a matching action or key chord is not found. Since iterable commands need to be expanded at in TerminalApp, we'll just expose `NameMap`, then let TerminalApp perform the expansion as they do now. Internally, we can store the actions as follows:
```c++
std::map<KeyChord, InternalActionID> _KeyMap;
std::map<InternalActionID, Command> _ActionMap;
```
`InternalActionID` will be a hash of `ActionAndArgs` such that two `ActionAndArgs` with the same `ShortcutAction` and `IActionArgs` output the same hash value.
`GetActionByKeyChord` will use `_KeyMap` to find the `InternalActionID`, then use the `_ActionMap` to find the bound `Command`.
`GetKeyBindingForAction` will hash the provided `ActionAndArgs` (constructed by the given parameters) and check `_ActionMap` for the given `InternalActionID`.
`NameMap` will need to ensure every action in `_ActionMap` is added to the output name map if it has an associated name. This is done by simply iterating over `_ActionMap`. Nested commands must be added separately because they cannot be hashed.
`ActionMap` will have an `AddAction(Command cmd)` that will update the internal state whenever a command is registered. If the given command is valid, we will check for collisions and resolve them. Otherwise, we will consider this an "unbound" action and update the internal state normally. It is important that we don't handle "unbound" actions differently because this ensures that we are explicitly unbinding a key chord.
### Step 3: Settings UI needs
After the former two steps are completed, the new representation of actions in the settings model is now on-par with
what we have today. In order to bind these new actions to the Settings UI, we need the following:
1. Exposing the maps
- `ActionMap::KeyBindings` and `ActionMap::Commands` may need to be added to pass the full list of actions to the Settings UI.
- In doing this, we can already update the Settings UI to include a better view of our actions.
2. Creating a copy of the settings model
- The Settings UI operates by binding the XAML controls to a copy of the settings model.
- Copying the `ActionMap` is fairly simple. Just copy the internal state and ensure that `Command::Copy` is called such that no reference to the original WinRT objects persist. Since we are using `InternalActionID`, we will not have to worry about multiple `Command` references existing within the same `ActionMap`.
3. Modifying the `Command`s
- `ActionMap` must be responsible for changing `Command`s so that we can ensure `ActionMap` always has a correct internal state:
- It is important that `Command` only exposes getters (not setters) to ensure `ActionMap` is up to date.
- If a key chord is being changed, update the `_KeyMap` and the `Command` itself.
- If a key binding is being deleted, add an unbound action to the given key chord.
- This is similar to how color schemes are maintained today.
- In the event that name/key-chord is set to something that's already taken, we need to propagate those changes to
the rest of `ActionMap`. As we do with the JSON, we respect the last name/key-chord set by the user. See [Modifying Actions](#modifying-actions)
in potential issues.
- For the purposes of the key bindings page, we will introduce a `KeyBindingViewModel` to serve as an intermediator between the settings UI and the settings model. The view model will be responsible for things like...
- exposing relevant information to the UI controls
- converting UI control interactions into proper API calls to the settings model
4. Serialization
- `Command::ToJson()` and `ActionMap::ToJson()` should perform most of the work for us. Simply iterate over the `_ActionMap` and call `Command::ToJson` on each action.
- See [Unbinding actions](#unbinding-actions) in potential issues.
## UI/UX Design
N/A
## Capabilities
N/A
### Accessibility
N/A
### Security
N/A
### Reliability
N/A
### Compatibility
N/A
### Performance, Power, and Efficiency
## Potential Issues
### Layering Actions
We need a way to determine where an action came from to minimize how many actions we serialize when we
write to disk. This is a two part approach that happens as we're loading the settings
1. Load defaults.json
- For each of the actions in the JSON...
- Construct the `Command` (basically the `Command::LayerJson` we have today)
- Add it to the `ActionMap`
- this should update the internal state of `ActionMap` appropriately
- if the newly added key chord conflicts with a pre-existing one,
redirect `_KeyMap` to the newly added `Command` instead,
and update the conflicting one.
2. Load settings.json
- Create a child for the `ActionMap`
- The purpose of a parent is to continue a search when the current `ActionMap` can't find a `Command` for a query. The parent is intended to be immutable.
- Load the actions array like normal into the child (see step 1)
Introducing a parent mechanism to `ActionMap` allows it to understand where a `Command` came from. This allows us to minimize the number of actions we serialize when we write to disk, as opposed to serializing the entire list of actions.
`ActionMap` queries will need to check their parent when they cannot find a matching `InternalActionID` in their `_ActionMap`.
Since `NameMap` is generated upon request, we will need to use a `std::set<InternalActionID>` as we generate the `NameMap`. This will ensure that each `Command` is only added to the `NameMap` once. The name map will be generated as follows:
1. Get an accumulated list of `Command`s from our parents
2. Iterate over the list...
- Update `NameMap` with any new `Command`s (tracked by the `std::set<InternalActionID>`)
Nested commands will be saved to their own map since they do not have an `InternalActionID`.
- During `ActionMap`'s population, we must ensure to resolve any conflicts immediately. This means that any new `Command`s that generate a name conflicting with a nested command will take priority (and we'll remove the nested command from its own map). Conversely, if a new nested command conflicts with an existing standard `Command`, we can ignore it because our generation of `NameMap` will handle it.
- When populating `NameMap`, we must first add all of the standard `Command`s. To ensure layering is accomplished correctly, we will need to start from the top-most parent and update `NameMap`. As we go down the inheritance tree, any conflicts are resolved by prioritizing the current layer (the child). This ensures that the current layer takes priority.
- After adding all of the standard `Command`s to the `NameMap`, we can then register all of the nested commands. Since nested commands have no identifier other than a name, we cannot use the `InternalActionID` heuristic. However, as mentioned earlier, we are updating our internal nested command map as we add new actions. So when we are generating the name map, we can assume that all of these nested commands now have priority. Thus, we simply add all of these nested commands to the name map. Any conflicts are resolved in favor of th nested command.
### Modifying Actions
There are several ways a command can be modified:
- change/remove the key chord
- change the name
- change the icon
- change the action
It is important that these modifications are done through `ActionMap` instead of `Command`.
This is to ensure that the `ActionMap` is always aligned with `Command`'s values. `Command` should only expose getters in the projected type to enforce this. Thus, we can add the following functions to `ActionMap`:
```c++
runtimeclass ActionMap
{
void SetKeyChord(Command cmd, KeyChord keys);
void SetName(Command cmd, String name);
void SetIcon(Command cmd, String iconPath);
void SetAction(Command cmd, ShortcutAction action, IActionArgs actionArgs);
}
```
`SetKeyChord` will need to make sure to modify the `_KeyMap` and the provided `Command`.
If the new key chord was already taken, we also need to update the conflicting `Command`
and remove its key chord.
`SetName` will need to make sure to modify the `Command` in `_ActionMap` and regenerate `NameMap`.
`SetIcon` will only need to modify the provided `Command`. We can choose to not expose this in the `ActionMap`, but doing so makes the API consistent.
`SetAction` will need to begin by updating the provided `Command`'s `ActionAndArgs`.
If the generated name is being used, the name will need to be updated. `_ActionMap` will need to be updated with a new `InternalActionID` for the new action. This is a major operation and so all views exposed will need to be regenerated.
Regarding [Layering Actions](#layering-actions), if the `Command` does not exist in the current layer,
but exists in a parent layer, we need to...
0. check if it exists
- use the hash `InternalActionID` to see if it exists in the current layer
- if it doesn't (which is the case we're trying to solve here), call `_GetActionByID(InternalActionID)` to retrieve the `Command` wherever it may be. This helper function simply checks the current layer, if none is found, it recursively checks its parents until a match is found.
1. duplicate it with `Command::Copy`
2. store the duplicate in the current layer
- `ActionMap::AddAction(duplicate)`
3. make the modification to the duplicate
This ensures that the change persists post-serialization.
TerminalApp has no reason to ever call these setters. To ensure that relationship, we will introduce an `IActionMapView` interface that will only expose `ActionMap` query functions. Conversely, `ActionMap` will be exposed to the TerminalSettingsEditor to allow for modifications.
### Unbinding actions
Removing a name is currently omitted from this spec because there
is no Settings UI use case for it at the moment. This scenario is
designed for Command Palette customization.
The only kind of unbinding currently in scope is freeing a key chord such that
no action is executed on that key stroke. To do this, simply `ActionMap::AddAction` a `Command` with...
- `ActionAndArgs`: `ShortcutAction = Invalid` and `IActionArgs = nullptr`
- `Keys` being the provided key chord
In explicitly storing an "unbound" action, we are explicitly saying that this key chord
must be passed through and this string must be removed from the command palette. `AddAction` automatically handles updating the internal state of `ActionMap` and any conflicting `Commands`.
This allows us to output something like this in the JSON:
```js
{ "command": "unbound", "keys": "ctrl+c" }
```
### Consolidated Actions
`AddAction` must be a bit smarter when it comes to the following scenario:
- Given a command that unbinds a key chord: `{ "command": "unbound", "keys": "ctrl+c" }`
- And... that key chord was set in a parent layer `{ "command": "copy", "keys": "ctrl+c" }`
- But... the action has another key chord from a parent layer `{ "command": "copy", "keys": "ctrl+shift+c" }`
`_ActionMap` does not contain any information about a parent layer; it only contains actions introduced in the current layer. Thus, in the scenario above, unbinding `ctrl+c` is what is relevant to `_ActionMap`. However, this may cause some complications for `GetKeyChordForAction`. We cannot simply check our internal `_ActionMap`, because the primary key chord in the entry may be incorrect. Again, this is because `_ActionMap` is only aware of what was bound in the current layer.
To get around this issue, we've introduced `_ConsolidatedActions`. In a way, `_ConsolidatedActions` is similar to `_ActionMap`, except that it consolidates the `Command` data into one entry constructed across the current layer and the parent layers. Specifically, in the scenario above, `_ActionMap` will say that `copy` has no key chords. In fact, `_ActionMap` has no reason to have `copy` at all, because it was not introduced in this layer. Conversely, `_ConsolidatedActions` holds `copy` with a `ctrl+shift+c` binding, which is then returned to `GetKeyChordForAction`.
To maintain `_ConsolidatedActions`, any new action added to the Action Map must also update `_ConsolidatedActions`. It is especially important to handle and propagate collisions to `_ConsolidatedActions`.
When querying Action Map for an ID, we should always check in the following order:
- `_ConsolidatedActions`
- `_ActionMap`
- repeat this process for each parent
This is to ensure that we are returning the correct and wholistic view of a `Command` on a query. Rather than acquiring a `Command` constructed in this layer, we receive one that contains all of the data acquired across the entire Action Map and its parents.
## Future considerations
There are a number of ideas regarding actions that would be fairly trivial to implement given this refactor:
- [#6899]: Action IDs
- As actions grow to become more widespread within Windows Terminal (i.e. dropdown and jumplist integration),
a formal ID system would help users reference the same action throughout the app. With the internal
ID system introduced earlier, we would simply introduce a new
`std:map<string, InternalActionID> _ExternalIDMap` that is updated like the others, and add a `String ID`
property to `Action`.
- [#8100] Source Tracking
- Identifying where a setting came from can be very beneficial in the settings model and UI. For example,
profile settings now have an `OverrideSource` getter that describes what `Profile` object the setting
came from (i.e. base layer, profile generator, etc...). A similar system can be used for `Action` in
that we record if the action was last modified in defaults.json or settings.json.
- There seems to be no desire for action inheritance (i.e. inheriting the name/key-chord from the parent).
So this should be sufficient.
## Resources
[#885]: https://github.com/microsoft/terminal/issues/885
[#6899]: https://github.com/microsoft/terminal/issues/6899
[#8100]: https://github.com/microsoft/terminal/issues/8100
[#8767]: https://github.com/microsoft/terminal/issues/8767
Other references:
[Settings UI: Actions Page]: https://github.com/microsoft/terminal/issues/6900
[Settings UI: Actions Page Design]: https://github.com/microsoft/terminal/pulls/9427
[Action ID Spec]: https://github.com/microsoft/terminal/issues/7175

View File

@@ -27,8 +27,8 @@ Below is the schedule for when milestones will be included in release builds of
| 2020-11-30 | [1.5] in Windows Terminal Preview<br>[1.4] in Windows Terminal | [Windows Terminal Preview 1.5 Release](https://devblogs.microsoft.com/commandline/windows-terminal-preview-1-5-release/) |
| 2021-01-31 | [1.6] in Windows Terminal Preview<br>[1.5] in Windows Terminal | [Windows Terminal Preview 1.6 Release](https://devblogs.microsoft.com/commandline/windows-terminal-preview-1-6-release/) |
| 2021-03-01 | [1.7] in Windows Terminal Preview<br>[1.6] in Windows Terminal | [Windows Terminal Preview 1.7 Release](https://devblogs.microsoft.com/commandline/windows-terminal-preview-1-7-release/) |
| 2021-04-14 | [1.8] in Windows Terminal Preview<br>[1.7] in Windows Terminal | [Windows Terminal Preview 1.8 Release](https://devblogs.microsoft.com/commandline/windows-terminal-preview-1-8-release/) |
| 2021-05-31 | [1.9] in Windows Terminal Preview<br>[1.8] in Windows Terminal | [Windows Terminal Preview 1.9 Release](https://devblogs.microsoft.com/commandline/windows-terminal-preview-1-9-release/) |
| 2021-04-30 | [1.8] in Windows Terminal Preview<br>[1.7] in Windows Terminal | |
| 2021-05-31 | [1.9] in Windows Terminal Preview<br>[1.8] in Windows Terminal | |
| 2021-07-31 | 1.10 in Windows Terminal Preview<br>[1.9] in Windows Terminal | |
| 2021-08-30 | 1.11 in Windows Terminal Preview<br>1.10 in Windows Terminal | |
| 2021-10-31 | 1.12 in Windows Terminal Preview<br>1.11 in Windows Terminal | |

BIN
res/Cascadia.ttf Normal file

Binary file not shown.

BIN
res/CascadiaMono.ttf Normal file

Binary file not shown.

View File

@@ -6,3 +6,16 @@ The images in this directory do not fall under the same [license](https://raw.gi
of the Windows Terminal code.
Please consult the [license](./LICENSE) in this directory for terms applicable to the image assets in this directory.
## Fonts
The fonts in this directory do not fall under the same [license](https://raw.githubusercontent.com/microsoft/terminal/main/LICENSE) as the rest
of the Windows Terminal code.
Please consult the [license](https://raw.githubusercontent.com/microsoft/cascadia-code/main/LICENSE) in the
[microsoft/cascadia-code](https://github.com/microsoft/cascadia-code) repository for terms applicable to the fonts in this directory.
### Fonts Included
* Cascadia Code, Cascadia Mono (2102.25)
* from microsoft/cascadia-code@911dc421f333e3b72b97381d16fee5b71eb48f04

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -1,12 +0,0 @@
# Windows Terminal and Console Assets (Fonts)
The fonts in this directory do not fall under the same [license](https://raw.githubusercontent.com/microsoft/terminal/main/LICENSE) as the rest
of the Windows Terminal code.
Please consult the [license](https://raw.githubusercontent.com/microsoft/cascadia-code/main/LICENSE) in the
[microsoft/cascadia-code](https://github.com/microsoft/cascadia-code) repository for terms applicable to the fonts in this directory.
### Fonts Included
* Cascadia Code, Cascadia Mono (2106.17)
* from microsoft/cascadia-code@fb0bce69c1c12f6c298b8bc1c1d181868f5daa9a

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

Some files were not shown because too many files have changed in this diff Show More