Compare commits
81 Commits
release-1.
...
dev/migrie
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6e1ce8de26 | ||
|
|
5e13c37217 | ||
|
|
6328b1adda | ||
|
|
177cf1caae | ||
|
|
75473c50fb | ||
|
|
76cb9654e1 | ||
|
|
e967801cdf | ||
|
|
50cfd84dd2 | ||
|
|
33860f7c1a | ||
|
|
860a3c7b23 | ||
|
|
eae88a9fdb | ||
|
|
137aea367a | ||
|
|
8a93b1dd5d | ||
|
|
6ca7d0e054 | ||
|
|
6f1dc5c9fa | ||
|
|
b5be04c3ae | ||
|
|
48d4e248b7 | ||
|
|
264618ae88 | ||
|
|
f892e52077 | ||
|
|
b90cc38f0f | ||
|
|
92b3453119 | ||
|
|
e25da60775 | ||
|
|
cee5fc9226 | ||
|
|
10e91a823d | ||
|
|
d1a72613c7 | ||
|
|
3e5eb73597 | ||
|
|
cc2fd9b490 | ||
|
|
45243bbee6 | ||
|
|
52eb2e5faa | ||
|
|
8b094fdfde | ||
|
|
7a94b8f725 | ||
|
|
e2f5f75471 | ||
|
|
7ac7fd1de9 | ||
|
|
dd684cbca1 | ||
|
|
edc8b557e1 | ||
|
|
82f968d8d5 | ||
|
|
67c7969879 | ||
|
|
b3d8f0e279 | ||
|
|
10ace041c3 | ||
|
|
4d23121a7e | ||
|
|
414007fdd8 | ||
|
|
72c0601d00 | ||
|
|
b3225db167 | ||
|
|
2517183b63 | ||
|
|
9fbcbcc9d8 | ||
|
|
73aefc18e8 | ||
|
|
a02585da35 | ||
|
|
2cf69338cd | ||
|
|
d71d8d7b32 | ||
|
|
9d411d405c | ||
|
|
58be8cd117 | ||
|
|
487f33ee89 | ||
|
|
829beda501 | ||
|
|
6e6979abe8 | ||
|
|
1fbe8e415d | ||
|
|
fa93fdc034 | ||
|
|
cf6e1f273a | ||
|
|
99059451d8 | ||
|
|
a309191461 | ||
|
|
e1be26b184 | ||
|
|
bc546dbdb0 | ||
|
|
00763fda9e | ||
|
|
b88be4534b | ||
|
|
207666e34d | ||
|
|
62b9a0d1c0 | ||
|
|
02f47f49c3 | ||
|
|
6905065fcf | ||
|
|
0416a944a2 | ||
|
|
3627d8abd5 | ||
|
|
33a9e32736 | ||
|
|
75af4cabbb | ||
|
|
43bd483962 | ||
|
|
0672812e6f | ||
|
|
f53553f4e4 | ||
|
|
11130a4895 | ||
|
|
0886e8f12d | ||
|
|
2e564368c8 | ||
|
|
ead76d7f16 | ||
|
|
614d1b21d6 | ||
|
|
fe640ff894 | ||
|
|
c56eb8fd93 |
@@ -1,19 +1,17 @@
|
||||
|
||||
AccessModifierOffset: -4
|
||||
AlignAfterOpenBracket: Align
|
||||
AllowAllArgumentsOnNextLine: true
|
||||
AlignConsecutiveMacros: false
|
||||
#AllowAllArgumentsOnNextLine: false
|
||||
AlignConsecutiveAssignments: false
|
||||
AlignConsecutiveDeclarations: false
|
||||
AllowAllConstructorInitializersOnNextLine: true
|
||||
#AllowAllConstructorInitializersOnNextLine: false
|
||||
AlignEscapedNewlines: Left
|
||||
AlignOperands: true
|
||||
AlignTrailingComments: false
|
||||
AllowAllParametersOfDeclarationOnNextLine: false
|
||||
AllowShortBlocksOnASingleLine: Never
|
||||
AllowShortFunctionsOnASingleLine: Inline
|
||||
AllowShortCaseLabelsOnASingleLine: false
|
||||
AllowShortIfStatementsOnASingleLine: Never
|
||||
AllowShortIfStatementsOnASingleLine: false
|
||||
#AllowShortLambdasOnASingleLine: Inline
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
AlwaysBreakAfterReturnType: None
|
||||
@@ -22,7 +20,6 @@ AlwaysBreakTemplateDeclarations: Yes
|
||||
BinPackArguments: false
|
||||
BinPackParameters: false
|
||||
BraceWrapping:
|
||||
AfterCaseLabel: true
|
||||
AfterClass: true
|
||||
AfterControlStatement: true
|
||||
AfterEnum: true
|
||||
@@ -50,7 +47,6 @@ ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
||||
ConstructorInitializerIndentWidth: 4
|
||||
ContinuationIndentWidth: 4
|
||||
Cpp11BracedListStyle: false
|
||||
DeriveLineEnding: true
|
||||
DerivePointerAlignment: false
|
||||
FixNamespaceComments: false
|
||||
IncludeBlocks: Regroup
|
||||
@@ -77,7 +73,7 @@ ReflowComments: false
|
||||
SortIncludes: false
|
||||
SortUsingDeclarations: true
|
||||
SpaceAfterCStyleCast: false
|
||||
SpaceAfterLogicalNot: false
|
||||
#SpaceAfterLogicalNot: false
|
||||
SpaceAfterTemplateKeyword: false
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
SpaceBeforeCpp11BracedList: false
|
||||
@@ -92,6 +88,6 @@ SpacesInCStyleCastParentheses: false
|
||||
SpacesInContainerLiterals: false
|
||||
SpacesInParentheses: false
|
||||
SpacesInSquareBrackets: false
|
||||
Standard: Latest
|
||||
Standard: Cpp11
|
||||
TabWidth: 4
|
||||
UseTab: Never
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
{
|
||||
"version": 1,
|
||||
"isRoot": true,
|
||||
"tools": {
|
||||
"XamlStyler.Console": {
|
||||
"version": "3.2008.4",
|
||||
"commands": [
|
||||
"xstyler"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
54
.github/ISSUE_TEMPLATE/Bug_Report.md
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
---
|
||||
name: "Bug report 🐛"
|
||||
about: Report errors or unexpected behavior
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
<!--
|
||||
🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨
|
||||
|
||||
I ACKNOWLEDGE THE FOLLOWING BEFORE PROCEEDING:
|
||||
1. If I delete this entire template and go my own path, the core team may close my issue without further explanation or engagement.
|
||||
2. If I list multiple bugs/concerns in this one issue, the core team may close my issue without further explanation or engagement.
|
||||
3. If I write an issue that has many duplicates, the core team may close my issue without further explanation or engagement (and without necessarily spending time to find the exact duplicate ID number).
|
||||
4. If I leave the title incomplete when filing the issue, the core team may close my issue without further explanation or engagement.
|
||||
5. If I file something completely blank in the body, the core team may close my issue without further explanation or engagement.
|
||||
|
||||
All good? Then proceed!
|
||||
-->
|
||||
|
||||
<!--
|
||||
This bug tracker is monitored by Windows Terminal development team and other technical folks.
|
||||
|
||||
**Important: When reporting BSODs or security issues, DO NOT attach memory dumps, logs, or traces to Github issues**.
|
||||
Instead, send dumps/traces to secure@microsoft.com, referencing this GitHub issue.
|
||||
|
||||
If this is an application crash, please also provide a Feedback Hub submission link so we can find your diagnostic data on the backend. Use the category "Apps > Windows Terminal (Preview)" and choose "Share My Feedback" after submission to get the link.
|
||||
|
||||
Please use this form and describe your issue, concisely but precisely, with as much detail as possible.
|
||||
|
||||
-->
|
||||
|
||||
# Environment
|
||||
|
||||
```none
|
||||
Windows build number: [run `[Environment]::OSVersion` for powershell, or `ver` for cmd]
|
||||
Windows Terminal version (if applicable):
|
||||
|
||||
Any other software?
|
||||
```
|
||||
|
||||
# Steps to reproduce
|
||||
|
||||
<!-- A description of how to trigger this bug. -->
|
||||
|
||||
# Expected behavior
|
||||
|
||||
<!-- A description of what you're expecting, possibly containing screenshots or reference material. -->
|
||||
|
||||
# Actual behavior
|
||||
|
||||
<!-- What's actually happening? -->
|
||||
53
.github/ISSUE_TEMPLATE/Bug_Report.yml
vendored
@@ -1,53 +0,0 @@
|
||||
name: "Bug report 🐛"
|
||||
description: Report errors or unexpected behavior
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
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.
|
||||
|
||||
- type: input
|
||||
attributes:
|
||||
label: Windows Terminal version (or Windows build number)
|
||||
placeholder: "10.0.19042.0, 1.7.3651.0"
|
||||
description: |
|
||||
If you are reporting an issue in Windows Terminal, you can find the version in the about dialog.
|
||||
|
||||
If you are reporting an issue with the Windows Console, please run `ver` or `[Environment]::OSVersion`.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Other Software
|
||||
description: If you're reporting a bug about our interaction with other software, what software? What versions?
|
||||
placeholder: |
|
||||
vim 8.2 (inside WSL)
|
||||
OpenSSH_for_Windows_8.1p1
|
||||
My Cool Application v0.3 (include a code snippet if it would help!)
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Steps to reproduce
|
||||
placeholder: Tell us the steps required to trigger your bug.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Expected Behavior
|
||||
description: If you want to include screenshots, paste them into the markdown editor below.
|
||||
placeholder: What were you expecting?
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Actual Behavior
|
||||
placeholder: What happened instead?
|
||||
validations:
|
||||
required: true
|
||||
12
.github/ISSUE_TEMPLATE/config.yml
vendored
@@ -1,12 +0,0 @@
|
||||
blank_issues_enabled: true
|
||||
|
||||
contact_links:
|
||||
- name: Microsoft Security Response Center 🔐
|
||||
url: https://msrc.microsoft.com/create-report
|
||||
about: Please report security vulnerabilities here.
|
||||
- name: Windows Terminal Documentation issue 📄
|
||||
url: https://github.com/MicrosoftDocs/terminal/issues/new
|
||||
about: Report issues with the documentation for the Windows Terminal (in docs.microsoft.com/windows/terminal)
|
||||
- name: Console Documentation issue 📄
|
||||
url: https://github.com/MicrosoftDocs/console-docs/issues/new
|
||||
about: Report issues with the documentation for the Console (in docs.microsoft.com/windows/console)
|
||||
42
.github/linters/.markdown-lint.yml
vendored
@@ -1,42 +0,0 @@
|
||||
---
|
||||
###########################
|
||||
###########################
|
||||
## Markdown Linter rules ##
|
||||
###########################
|
||||
###########################
|
||||
|
||||
# Linter rules doc:
|
||||
# - https://github.com/DavidAnson/markdownlint
|
||||
#
|
||||
# Note:
|
||||
# To comment out a single error:
|
||||
# <!-- markdownlint-disable -->
|
||||
# any violations you want
|
||||
# <!-- markdownlint-restore -->
|
||||
#
|
||||
# To run the linter locally:
|
||||
# 1. install the npm package:
|
||||
# `npm install -g markdownlint-cli`
|
||||
# 2. Then run it in the root of the repo with
|
||||
# `markdownlint -c .github\linters\.markdown-lint.yml ./*.md`
|
||||
|
||||
###############
|
||||
# Rules by id #
|
||||
###############
|
||||
MD004: false # Unordered list style
|
||||
MD007:
|
||||
indent: 2 # Unordered list indentation
|
||||
MD013:
|
||||
line_length: 400 # Line length 80 is far to short
|
||||
MD024: false # Allow multiple headings with same content
|
||||
MD026:
|
||||
punctuation: ".,;:!。,;:" # List of not allowed
|
||||
MD029: false # Ordered list item prefix
|
||||
MD033: false # Allow inline HTML
|
||||
MD036: false # Emphasis used instead of a heading
|
||||
MD040: false # Allow ``` blocks in md files with no language specified
|
||||
|
||||
#################
|
||||
# Rules by tags #
|
||||
#################
|
||||
blank_lines: false # Error on blank lines
|
||||
@@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="vswhere" version="2.6.7" />
|
||||
</packages>
|
||||
</packages>
|
||||
13
.vscode/extensions.json
vendored
@@ -1,13 +0,0 @@
|
||||
{
|
||||
// See https://go.microsoft.com/fwlink/?LinkId=827846 to learn about workspace recommendations.
|
||||
// Extension identifier format: ${publisher}.${name}. Example: vscode.csharp
|
||||
|
||||
// List of extensions which should be recommended for users of this workspace.
|
||||
"recommendations": [
|
||||
"ms-vscode.cpptools"
|
||||
],
|
||||
// List of extensions recommended by VS Code that should not be recommended for users of this workspace.
|
||||
"unwantedRecommendations": [
|
||||
|
||||
]
|
||||
}
|
||||
24
.vscode/launch.json
vendored
@@ -1,24 +0,0 @@
|
||||
{
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Debug OpenConsole by Launching (x64, debug)",
|
||||
"type": "cppvsdbg",
|
||||
"request": "launch",
|
||||
"program": "${workspaceFolder}\\bin\\x64\\debug\\openconsole.exe",
|
||||
"args": [],
|
||||
"stopAtEntry": false,
|
||||
"cwd": "${workspaceFolder}",
|
||||
"environment": [],
|
||||
},
|
||||
{
|
||||
"name": "Debug Terminal by Attaching (You go build/register/launch it first.)",
|
||||
"type": "cppvsdbg",
|
||||
"request": "attach",
|
||||
"processId": "${command:pickProcess}"
|
||||
}
|
||||
]
|
||||
}
|
||||
105
.vscode/settings.json
vendored
@@ -1,105 +0,0 @@
|
||||
{
|
||||
"C_Cpp.default.browse.databaseFilename": "${workspaceFolder}\\.vscode\\.BROWSE.VC.DB",
|
||||
"C_Cpp.default.browse.path": [
|
||||
"${workspaceFolder}"
|
||||
],
|
||||
"C_Cpp.loggingLevel": "None",
|
||||
"files.associations": {
|
||||
"xstring": "cpp",
|
||||
"*.idl": "cpp",
|
||||
"array": "cpp",
|
||||
"future": "cpp",
|
||||
"istream": "cpp",
|
||||
"memory": "cpp",
|
||||
"tuple": "cpp",
|
||||
"type_traits": "cpp",
|
||||
"utility": "cpp",
|
||||
"variant": "cpp",
|
||||
"xlocmes": "cpp",
|
||||
"xlocmon": "cpp",
|
||||
"xlocnum": "cpp",
|
||||
"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"
|
||||
},
|
||||
"files.exclude": {
|
||||
"**/bin/**": true,
|
||||
"**/obj/**": true,
|
||||
"**/packages/**": true,
|
||||
"**/generated files/**": true
|
||||
}
|
||||
}
|
||||
121
.vscode/tasks.json
vendored
@@ -1,121 +0,0 @@
|
||||
{
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"type": "process",
|
||||
"label": "Build Terminal/Console",
|
||||
"command": "powershell.exe",
|
||||
"args": [
|
||||
"-Command",
|
||||
"Import-Module ${workspaceFolder}\\tools\\OpenConsole.psm1;",
|
||||
"Set-MsBuildDevEnvironment;",
|
||||
"$project = switch(\"${input:buildProjectChoice}\"){OpenConsole{\"Conhost\\Host_EXE\"} Terminal{\"Terminal\\CascadiaPackage\"} TermControl{\"Terminal\\TerminalControl\"}};",
|
||||
"$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"],
|
||||
"group": {
|
||||
"kind": "build",
|
||||
"isDefault": true
|
||||
},
|
||||
"runOptions": {
|
||||
"reevaluateOnRerun": false,
|
||||
"instanceLimit": 1,
|
||||
"runOn": "default"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "process",
|
||||
"label": "Register Windows Terminal x64 Debug",
|
||||
"command": "powershell.exe",
|
||||
"args": [
|
||||
"-Command",
|
||||
"Import-Module ${workspaceFolder}\\tools\\OpenConsole.psm1;",
|
||||
"Set-MsBuildDevEnvironment;",
|
||||
"Set-Location -Path ${workspaceFolder}\\src\\cascadia\\CascadiaPackage\\AppPackages\\CascadiaPackage_0.0.1.0_x64_Debug_Test;",
|
||||
"if ((Get-AppxPackage -Name 'WindowsTerminalDev*') -ne $null) { Remove-AppxPackage 'WindowsTerminalDev_0.0.1.0_x64__8wekyb3d8bbwe'};",
|
||||
"New-Item ..\\loose -Type Directory -Force;",
|
||||
"makeappx unpack /v /o /p .\\CascadiaPackage_0.0.1.0_x64_Debug.msix /d ..\\Loose\\;",
|
||||
"Add-AppxPackage -Path ..\\loose\\AppxManifest.xml -Register -ForceUpdateFromAnyVersion -ForceApplicationShutdown"
|
||||
],
|
||||
"problemMatcher": ["$msCompile"],
|
||||
"group": {
|
||||
"kind": "build"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "process",
|
||||
"label": "Run Windows Terminal Dev",
|
||||
"command": "wtd.exe",
|
||||
"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":[
|
||||
{
|
||||
"id": "platformChoice",
|
||||
"type": "pickString",
|
||||
"description": "Processor architecture choice",
|
||||
"options":[
|
||||
"x64",
|
||||
"x86",
|
||||
"arm64"
|
||||
],
|
||||
"default": "x64"
|
||||
},
|
||||
{
|
||||
"id": "configChoice",
|
||||
"type": "pickString",
|
||||
"description": "Debug or release?",
|
||||
"options":[
|
||||
"Debug",
|
||||
"Release"
|
||||
],
|
||||
"default": "Debug"
|
||||
},
|
||||
{
|
||||
"id": "buildModeChoice",
|
||||
"type": "pickString",
|
||||
"description": "Build, rebuild, or clean?",
|
||||
"options":[
|
||||
"Build",
|
||||
"Rebuild",
|
||||
"Clean"
|
||||
],
|
||||
"default": "Build"
|
||||
},
|
||||
{
|
||||
"id": "buildProjectChoice",
|
||||
"type": "pickString",
|
||||
"description": "OpenConsole or Terminal?",
|
||||
"options":[
|
||||
"OpenConsole",
|
||||
"Terminal",
|
||||
"TermControl"
|
||||
],
|
||||
"default": "Terminal"
|
||||
}
|
||||
|
||||
]
|
||||
}
|
||||
@@ -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",
|
||||
|
||||
@@ -14,7 +14,7 @@ The point of doing all this work in public is to ensure that we are holding ours
|
||||
|
||||
The team triages new issues several times a week. During triage, the team uses labels to categorize, manage, and drive the project workflow.
|
||||
|
||||
We employ [a bot engine](https://github.com/microsoft/terminal/blob/main/doc/bot.md) to help us automate common processes within our workflow.
|
||||
We employ [a bot engine](https://github.com/microsoft/terminal/blob/master/doc/bot.md) to help us automate common processes within our workflow.
|
||||
|
||||
We drive the bot by tagging issues with specific labels which cause the bot engine to close issues, merge branches, etc. This bot engine helps us keep the repo clean by automating the process of notifying appropriate parties if/when information/follow-up is needed, and closing stale issues/PRs after reminders have remained unanswered for several days.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -140,13 +140,6 @@ Once you've discussed your proposed feature/fix/etc. with a team member, and you
|
||||
1. Create & push a feature branch
|
||||
1. Create a [Draft Pull Request (PR)](https://github.blog/2019-02-14-introducing-draft-pull-requests/)
|
||||
1. Work on your changes
|
||||
1. Build and see if it works. Consult [How to build OpenConsole](./doc/building.md) if you have problems.
|
||||
|
||||
### Testing
|
||||
|
||||
Testing is a key component in the development workflow. Both Windows Terminal and Windows Console use TAEF(the Test Authoring and Execution Framework) as the main framework for testing.
|
||||
|
||||
If your changes affect existing test cases, or you're working on brand new features and also the accompanying test cases, see [TAEF](./doc/TAEF.md) for more information about how to validate your work locally.
|
||||
|
||||
### Code Review
|
||||
|
||||
@@ -156,7 +149,7 @@ When you'd like the team to take a look, (even if the work is not yet fully-comp
|
||||
|
||||
### Merge
|
||||
|
||||
Once your code has been reviewed and approved by the requisite number of team members, it will be merged into the main branch. Once merged, your PR will be automatically closed.
|
||||
Once your code has been reviewed and approved by the requisite number of team members, it will be merged into the master branch. Once merged, your PR will be automatically closed.
|
||||
|
||||
---
|
||||
|
||||
|
||||
153
NOTICE.md
@@ -2,7 +2,7 @@
|
||||
Do Not Translate or Localize
|
||||
|
||||
This software incorporates material from third parties. Microsoft makes certain
|
||||
open source code available at [http://3rdpartysource.microsoft.com](http://3rdpartysource.microsoft.com), or you may
|
||||
open source code available at http://3rdpartysource.microsoft.com, or you may
|
||||
send a check or money order for US $5.00, including the product name, the open
|
||||
source component name, and version number, to:
|
||||
|
||||
@@ -20,7 +20,7 @@ General Public License.
|
||||
|
||||
## jsoncpp
|
||||
|
||||
**Source**: [https://github.com/open-source-parsers/jsoncpp](https://github.com/open-source-parsers/jsoncpp)
|
||||
**Source**: https://github.com/open-source-parsers/jsoncpp
|
||||
|
||||
### License
|
||||
|
||||
@@ -48,9 +48,39 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
```
|
||||
|
||||
## telnetpp
|
||||
|
||||
**Source**: https://github.com/KazDragon/telnetpp
|
||||
|
||||
### License
|
||||
|
||||
```
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015-2017 Matthew Chaplain a.k.a KazDragon
|
||||
|
||||
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.
|
||||
```
|
||||
|
||||
## chromium/base/numerics
|
||||
|
||||
**Source**: [https://github.com/chromium/chromium/tree/master/base/numerics](https://github.com/chromium/chromium/tree/master/base/numerics)
|
||||
**Source**: https://github.com/chromium/chromium/tree/master/base/numerics
|
||||
|
||||
### License
|
||||
|
||||
@@ -86,7 +116,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
## kimwalisch/libpopcnt
|
||||
|
||||
**Source**: [https://github.com/kimwalisch/libpopcnt](https://github.com/kimwalisch/libpopcnt)
|
||||
**Source**: https://github.com/kimwalisch/libpopcnt
|
||||
|
||||
### License
|
||||
|
||||
@@ -122,7 +152,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
## dynamic_bitset
|
||||
|
||||
**Source**: [https://github.com/pinam45/dynamic_bitset](https://github.com/pinam45/dynamic_bitset)
|
||||
**Source**: https://github.com/pinam45/dynamic_bitset
|
||||
|
||||
### License
|
||||
|
||||
@@ -151,9 +181,9 @@ SOFTWARE.
|
||||
|
||||
```
|
||||
|
||||
## \{fmt\}
|
||||
## {fmt}
|
||||
|
||||
**Source**: [https://github.com/fmtlib/fmt](https://github.com/fmtlib/fmt)
|
||||
**Source**: https://github.com/fmtlib/fmt
|
||||
|
||||
### License
|
||||
|
||||
@@ -188,112 +218,3 @@ of this Software are embedded into a machine-executable object form of such
|
||||
source code, you may redistribute such embedded portions in such object form
|
||||
without including the above copyright and permission notices.
|
||||
```
|
||||
|
||||
## interval_tree
|
||||
|
||||
**Source**: [https://github.com/ekg/IntervalTree](https://github.com/ekg/IntervalTree)
|
||||
|
||||
### License
|
||||
|
||||
```
|
||||
Copyright (c) 2011 Erik Garrison
|
||||
|
||||
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.
|
||||
|
||||
```
|
||||
|
||||
|
||||
## boost
|
||||
|
||||
**Source**: [https://github.com/boostorg/boost](https://github.com/boostorg/boost)
|
||||
|
||||
### License
|
||||
|
||||
```
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
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, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
|
||||
```
|
||||
|
||||
# Microsoft Open Source
|
||||
|
||||
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.
|
||||
```
|
||||
|
||||
17
NuGet.Config
@@ -1,14 +1,19 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<packageSources>
|
||||
<clear />
|
||||
<!-- Dependencies that we can turn on to force override for testing purposes before uploading. -->
|
||||
<add key="NuGet.org" value="https://api.nuget.org/v3/index.json" />
|
||||
<!-- Add repositories here to the list of available repositories -->
|
||||
|
||||
<!-- Dependencies that we must carry because they're not on public nuget feeds right now. -->
|
||||
<!--<add key="Static Package Dependencies" value="dep\packages" />-->
|
||||
<add key="TerminalDependencies" value="https://pkgs.dev.azure.com/ms/terminal/_packaging/TerminalDependencies/nuget/v3/index.json" />
|
||||
|
||||
<!-- Use our own NuGet Feed -->
|
||||
<add key="Windows Terminal NuGet Feed" value="https://terminalnuget.blob.core.windows.net/feed/index.json" />
|
||||
|
||||
<!-- Internal NuGet feeds that may not be accessible outside Microsoft corporate network -->
|
||||
<!--<add key="TAEF - internal" value="https://microsoft.pkgs.visualstudio.com/DefaultCollection/_packaging/Taef/nuget/v3/index.json" />
|
||||
<add key="OpenConsole - Internal" value="https://microsoft.pkgs.visualstudio.com/_packaging/OpenConsole/nuget/v3/index.json" />-->
|
||||
</packageSources>
|
||||
<disabledPackageSources>
|
||||
<clear />
|
||||
</disabledPackageSources>
|
||||
<config>
|
||||
<add key="repositorypath" value=".\packages" />
|
||||
</config>
|
||||
|
||||
1423
OpenConsole.sln
261
README.md
@@ -1,5 +1,3 @@
|
||||

|
||||
|
||||
# Welcome to the Windows Terminal, Console and Command-Line repo
|
||||
|
||||
This repository contains the source code for:
|
||||
@@ -8,26 +6,22 @@ This repository contains the source code for:
|
||||
* [Windows Terminal Preview](https://aka.ms/terminal-preview)
|
||||
* The Windows console host (`conhost.exe`)
|
||||
* Components shared between the two projects
|
||||
* [ColorTool](https://github.com/microsoft/terminal/tree/main/src/tools/ColorTool)
|
||||
* [Sample projects](https://github.com/microsoft/terminal/tree/main/samples)
|
||||
that show how to consume the Windows Console APIs
|
||||
* [ColorTool](https://github.com/Microsoft/Terminal/tree/master/src/tools/ColorTool)
|
||||
* [Sample projects](https://github.com/Microsoft/Terminal/tree/master/samples) that show how to consume the Windows Console APIs
|
||||
|
||||
Related repositories include:
|
||||
|
||||
* [Windows Terminal Documentation](https://docs.microsoft.com/windows/terminal)
|
||||
([Repo: Contribute to the docs](https://github.com/MicrosoftDocs/terminal))
|
||||
* [Windows Terminal Documentation](https://docs.microsoft.com/windows/terminal) ([Repo: Contribute to the docs](https://github.com/MicrosoftDocs/terminal))
|
||||
* [Console API Documentation](https://github.com/MicrosoftDocs/Console-Docs)
|
||||
* [Cascadia Code Font](https://github.com/Microsoft/Cascadia-Code)
|
||||
|
||||
## Installing and running Windows Terminal
|
||||
|
||||
> 🔴 Note: Windows Terminal requires Windows 10 1903 (build 18362) or later
|
||||
> 👉 Note: Windows Terminal requires Windows 10 1903 (build 18362) or later
|
||||
|
||||
### Microsoft Store [Recommended]
|
||||
|
||||
Install the [Windows Terminal from the Microsoft Store][store-install-link].
|
||||
This allows you to always be on the latest version when we release new builds
|
||||
with automatic upgrades.
|
||||
Install the [Windows Terminal from the Microsoft Store][store-install-link]. This allows you to always be on the latest version when we release new builds with automatic upgrades.
|
||||
|
||||
This is our preferred method.
|
||||
|
||||
@@ -35,34 +29,16 @@ This is our preferred method.
|
||||
|
||||
#### Via GitHub
|
||||
|
||||
For users who are unable to install Windows Terminal from the Microsoft Store,
|
||||
released builds can be manually downloaded from this repository's [Releases
|
||||
page](https://github.com/microsoft/terminal/releases).
|
||||
For users who are unable to install Terminal from the Microsoft Store, Terminal builds can be manually downloaded from this repository's [Releases page](https://github.com/microsoft/terminal/releases).
|
||||
|
||||
Download the `Microsoft.WindowsTerminal_<versionNumber>.msixbundle` file from
|
||||
the **Assets** section. To install the app, you can simply double-click on the
|
||||
`.msixbundle` file, and the app installer should automatically run. If that
|
||||
fails for any reason, you can try the following command at a PowerShell prompt:
|
||||
|
||||
```powershell
|
||||
# NOTE: If you are using PowerShell 7+, please run
|
||||
# Import-Module Appx -UseWindowsPowerShell
|
||||
# before using Add-AppxPackage.
|
||||
|
||||
Add-AppxPackage Microsoft.WindowsTerminal_<versionNumber>.msixbundle
|
||||
```
|
||||
|
||||
> 🔴 Note: If you install Terminal manually:
|
||||
> ⚠ Note: If you install Terminal manually:
|
||||
>
|
||||
> * Terminal will not auto-update when new builds are released so you will need
|
||||
> to regularly install the latest Terminal release to receive all the latest
|
||||
> fixes and improvements!
|
||||
> * Be sure to install the [Desktop Bridge VC++ v14 Redistributable Package](https://www.microsoft.com/en-us/download/details.aspx?id=53175) otherwise Terminal may not install and/or run and may crash at startup
|
||||
> * Terminal will not auto-update when new builds are released so you will need to regularly install the latest Terminal release to receive all the latest fixes and improvements!
|
||||
|
||||
#### Via Windows Package Manager CLI (aka winget)
|
||||
|
||||
[winget](https://github.com/microsoft/winget-cli) users can download and install
|
||||
the latest Terminal release by installing the `Microsoft.WindowsTerminal`
|
||||
package:
|
||||
[winget](https://github.com/microsoft/winget-cli) users can download and install the latest Terminal release by installing the `Microsoft.WindowsTerminal` package:
|
||||
|
||||
```powershell
|
||||
winget install --id=Microsoft.WindowsTerminal -e
|
||||
@@ -70,8 +46,7 @@ winget install --id=Microsoft.WindowsTerminal -e
|
||||
|
||||
#### Via Chocolatey (unofficial)
|
||||
|
||||
[Chocolatey](https://chocolatey.org) users can download and install the latest
|
||||
Terminal release by installing the `microsoft-windows-terminal` package:
|
||||
[Chocolatey](https://chocolatey.org) users can download and install the latest Terminal release by installing the `microsoft-windows-terminal` package:
|
||||
|
||||
```powershell
|
||||
choco install microsoft-windows-terminal
|
||||
@@ -83,144 +58,70 @@ To upgrade Windows Terminal using Chocolatey, run the following:
|
||||
choco upgrade microsoft-windows-terminal
|
||||
```
|
||||
|
||||
If you have any issues when installing/upgrading the package please go to the
|
||||
[Windows Terminal package
|
||||
page](https://chocolatey.org/packages/microsoft-windows-terminal) and follow the
|
||||
[Chocolatey triage process](https://chocolatey.org/docs/package-triage-process)
|
||||
|
||||
#### Via Scoop (unofficial)
|
||||
|
||||
[Scoop](https://scoop.sh) users can download and install the latest Terminal
|
||||
release by installing the `windows-terminal` package:
|
||||
|
||||
```powershell
|
||||
scoop bucket add extras
|
||||
scoop install windows-terminal
|
||||
```
|
||||
|
||||
To update Windows Terminal using Scoop, run the following:
|
||||
|
||||
```powershell
|
||||
scoop update windows-terminal
|
||||
```
|
||||
|
||||
If you have any issues when installing/updating the package, please search for
|
||||
or report the same on the [issues
|
||||
page](https://github.com/lukesampson/scoop-extras/issues) of Scoop Extras bucket
|
||||
repository.
|
||||
If you have any issues when installing/upgrading the package please go to the [Windows Terminal package page](https://chocolatey.org/packages/microsoft-windows-terminal) and follow the [Chocolatey triage process](https://chocolatey.org/docs/package-triage-process)
|
||||
|
||||
---
|
||||
|
||||
## Windows Terminal 2.0 Roadmap
|
||||
|
||||
The plan for delivering Windows Terminal 2.0 [is described
|
||||
here](/doc/terminal-v2-roadmap.md) and will be updated as the project proceeds.
|
||||
The plan for delivering Windows Terminal 2.0 [is described here](/doc/terminal-v2-roadmap.md) and will be updated as the project proceeds.
|
||||
|
||||
## Project Build Status
|
||||
|
||||
Project|Build Status
|
||||
---|---
|
||||
Terminal|[](https://dev.azure.com/ms/terminal/_build?definitionId=136)
|
||||
ColorTool|
|
||||
Terminal|[](https://dev.azure.com/ms/Terminal/_build?definitionId=136)
|
||||
ColorTool|
|
||||
|
||||
---
|
||||
|
||||
## Terminal & Console Overview
|
||||
|
||||
Please take a few minutes to review the overview below before diving into the
|
||||
code:
|
||||
Please take a few minutes to review the overview below before diving into the code:
|
||||
|
||||
### Windows Terminal
|
||||
|
||||
Windows Terminal is a new, modern, feature-rich, productive terminal application
|
||||
for command-line users. It includes many of the features most frequently
|
||||
requested by the Windows command-line community including support for tabs, rich
|
||||
text, globalization, configurability, theming & styling, and more.
|
||||
Windows Terminal is a new, modern, feature-rich, productive terminal application for command-line users. It includes many of the features most frequently requested by the Windows command-line community including support for tabs, rich text, globalization, configurability, theming & styling, and more.
|
||||
|
||||
The Terminal will also need to meet our goals and measures to ensure it remains
|
||||
fast and efficient, and doesn't consume vast amounts of memory or power.
|
||||
The Terminal will also need to meet our goals and measures to ensure it remains fast and efficient, and doesn't consume vast amounts of memory or power.
|
||||
|
||||
### The Windows Console Host
|
||||
|
||||
The Windows Console host, `conhost.exe`, is Windows' original command-line user
|
||||
experience. It also hosts Windows' command-line infrastructure and the Windows
|
||||
Console API server, input engine, rendering engine, user preferences, etc. The
|
||||
console host code in this repository is the actual source from which the
|
||||
`conhost.exe` in Windows itself is built.
|
||||
The Windows Console host, `conhost.exe`, is Windows' original command-line user experience. It also hosts Windows' command-line infrastructure and the Windows Console API server, input engine, rendering engine, user preferences, etc. The console host code in this repository is the actual source from which the `conhost.exe` in Windows itself is built.
|
||||
|
||||
Since taking ownership of the Windows command-line in 2014, the team added
|
||||
several new features to the Console, including background transparency,
|
||||
line-based selection, support for [ANSI / Virtual Terminal
|
||||
sequences](https://en.wikipedia.org/wiki/ANSI_escape_code), [24-bit
|
||||
color](https://devblogs.microsoft.com/commandline/24-bit-color-in-the-windows-console/),
|
||||
a [Pseudoconsole
|
||||
("ConPTY")](https://devblogs.microsoft.com/commandline/windows-command-line-introducing-the-windows-pseudo-console-conpty/),
|
||||
and more.
|
||||
Since taking ownership of the Windows command-line in 2014, the team added several new features to the Console, including background transparency, line-based selection, support for [ANSI / Virtual Terminal sequences](https://en.wikipedia.org/wiki/ANSI_escape_code), [24-bit color](https://devblogs.microsoft.com/commandline/24-bit-color-in-the-windows-console/), a [Pseudoconsole ("ConPTY")](https://devblogs.microsoft.com/commandline/windows-command-line-introducing-the-windows-pseudo-console-conpty/), and more.
|
||||
|
||||
However, because Windows Console's primary goal is to maintain backward
|
||||
compatibility, we have been unable to add many of the features the community
|
||||
(and the team) have been wanting for the last several years including tabs,
|
||||
unicode text, and emoji.
|
||||
However, because Windows Console's primary goal is to maintain backward compatibility, we have been unable to add many of the features the community (and the team) have been wanting for the last several years including tabs, unicode text, and emoji.
|
||||
|
||||
These limitations led us to create the new Windows Terminal.
|
||||
|
||||
> You can read more about the evolution of the command-line in general, and the
|
||||
> Windows command-line specifically in [this accompanying series of blog
|
||||
> posts](https://devblogs.microsoft.com/commandline/windows-command-line-backgrounder/)
|
||||
> on the Command-Line team's blog.
|
||||
> You can read more about the evolution of the command-line in general, and the Windows command-line specifically in [this accompanying series of blog posts](https://devblogs.microsoft.com/commandline/windows-command-line-backgrounder/) on the Command-Line team's blog.
|
||||
|
||||
### Shared Components
|
||||
|
||||
While overhauling Windows Console, we modernized its codebase considerably,
|
||||
cleanly separating logical entities into modules and classes, introduced some
|
||||
key extensibility points, replaced several old, home-grown collections and
|
||||
containers with safer, more efficient [STL
|
||||
containers](https://docs.microsoft.com/en-us/cpp/standard-library/stl-containers?view=vs-2019),
|
||||
and made the code simpler and safer by using Microsoft's [Windows Implementation
|
||||
Libraries - WIL](https://github.com/Microsoft/wil).
|
||||
While overhauling Windows Console, we modernized its codebase considerably, cleanly separating logical entities into modules and classes, introduced some key extensibility points, replaced several old, home-grown collections and containers with safer, more efficient [STL containers](https://docs.microsoft.com/en-us/cpp/standard-library/stl-containers?view=vs-2019), and made the code simpler and safer by using Microsoft's [Windows Implementation Libraries - WIL](https://github.com/Microsoft/wil).
|
||||
|
||||
This overhaul resulted in several of Console's key components being available
|
||||
for re-use in any terminal implementation on Windows. These components include a
|
||||
new DirectWrite-based text layout and rendering engine, a text buffer capable of
|
||||
storing both UTF-16 and UTF-8, a VT parser/emitter, and more.
|
||||
This overhaul resulted in several of Console's key components being available for re-use in any terminal implementation on Windows. These components include a new DirectWrite-based text layout and rendering engine, a text buffer capable of storing both UTF-16 and UTF-8, a VT parser/emitter, and more.
|
||||
|
||||
### Creating the new Windows Terminal
|
||||
|
||||
When we started planning the new Windows Terminal application, we explored and
|
||||
evaluated several approaches and technology stacks. We ultimately decided that
|
||||
our goals would be best met by continuing our investment in our C++ codebase,
|
||||
which would allow us to reuse several of the aforementioned modernized
|
||||
components in both the existing Console and the new Terminal. Further, we
|
||||
realized that this would allow us to build much of the Terminal's core itself as
|
||||
a reusable UI control that others can incorporate into their own applications.
|
||||
When we started planning the new Windows Terminal application, we explored and evaluated several approaches and technology stacks. We ultimately decided that our goals would be best met by continuing our investment in our C++ codebase, which would allow us to reuse several of the aforementioned modernized components in both the existing Console and the new Terminal. Further, we realized that this would allow us to build much of the Terminal's core itself as a reusable UI control that others can incorporate into their own applications.
|
||||
|
||||
The result of this work is contained within this repo and delivered as the
|
||||
Windows Terminal application you can download from the Microsoft Store, or
|
||||
[directly from this repo's
|
||||
releases](https://github.com/microsoft/terminal/releases).
|
||||
The result of this work is contained within this repo and delivered as the Windows Terminal application you can download from the Microsoft Store, or [directly from this repo's releases](https://github.com/microsoft/terminal/releases).
|
||||
|
||||
---
|
||||
|
||||
## Resources
|
||||
|
||||
For more information about Windows Terminal, you may find some of these
|
||||
resources useful and interesting:
|
||||
For more information about Windows Terminal, you may find some of these resources useful and interesting:
|
||||
|
||||
* [Command-Line Blog](https://devblogs.microsoft.com/commandline)
|
||||
* [Command-Line Backgrounder Blog
|
||||
Series](https://devblogs.microsoft.com/commandline/windows-command-line-backgrounder/)
|
||||
* Windows Terminal Launch: [Terminal "Sizzle
|
||||
Video"](https://www.youtube.com/watch?v=8gw0rXPMMPE&list=PLEHMQNlPj-Jzh9DkNpqipDGCZZuOwrQwR&index=2&t=0s)
|
||||
* Windows Terminal Launch: [Build 2019
|
||||
Session](https://www.youtube.com/watch?v=KMudkRcwjCw)
|
||||
* Run As Radio: [Show 645 - Windows Terminal with Richard
|
||||
Turner](http://www.runasradio.com/Shows/Show/645)
|
||||
* Azure Devops Podcast: [Episode 54 - Kayla Cinnamon and Rich Turner on DevOps
|
||||
on the Windows
|
||||
Terminal](http://azuredevopspodcast.clear-measure.com/kayla-cinnamon-and-rich-turner-on-devops-on-the-windows-terminal-team-episode-54)
|
||||
* Microsoft Ignite 2019 Session: [The Modern Windows Command Line: Windows
|
||||
Terminal -
|
||||
BRK3321](https://myignite.techcommunity.microsoft.com/sessions/81329?source=sessions)
|
||||
* [Command-Line Backgrounder Blog Series](https://devblogs.microsoft.com/commandline/windows-command-line-backgrounder/)
|
||||
* Windows Terminal Launch: [Terminal "Sizzle Video"](https://www.youtube.com/watch?v=8gw0rXPMMPE&list=PLEHMQNlPj-Jzh9DkNpqipDGCZZuOwrQwR&index=2&t=0s)
|
||||
* Windows Terminal Launch: [Build 2019 Session](https://www.youtube.com/watch?v=KMudkRcwjCw)
|
||||
* Run As Radio: [Show 645 - Windows Terminal with Richard Turner](http://www.runasradio.com/Shows/Show/645)
|
||||
* Azure Devops Podcast: [Episode 54 - Kayla Cinnamon and Rich Turner on DevOps on the Windows Terminal](http://azuredevopspodcast.clear-measure.com/kayla-cinnamon-and-rich-turner-on-devops-on-the-windows-terminal-team-episode-54)
|
||||
* Microsoft Ignite 2019 Session: [The Modern Windows Command Line: Windows Terminal - BRK3321](https://myignite.techcommunity.microsoft.com/sessions/81329?source=sessions)
|
||||
|
||||
---
|
||||
|
||||
@@ -230,73 +131,48 @@ resources useful and interesting:
|
||||
|
||||
Cause: You're launching the incorrect solution in Visual Studio.
|
||||
|
||||
Solution: Make sure you're building & deploying the `CascadiaPackage` project in
|
||||
Visual Studio.
|
||||
Solution: Make sure you're building & deploying the `CascadiaPackage` project in Visual Studio.
|
||||
|
||||
> ⚠ Note: `OpenConsole.exe` is just a locally-built `conhost.exe`, the classic
|
||||
> Windows Console that hosts Windows' command-line infrastructure. OpenConsole
|
||||
> is used by Windows Terminal to connect to and communicate with command-line
|
||||
> applications (via
|
||||
> [ConPty](https://devblogs.microsoft.com/commandline/windows-command-line-introducing-the-windows-pseudo-console-conpty/)).
|
||||
> ⚠ Note: `OpenConsole.exe` is just a locally-built `conhost.exe`, the classic Windows Console that hosts Windows' command-line infrastructure. OpenConsole is used by Windows Terminal to connect to and communicate with command-line applications (via [ConPty](https://devblogs.microsoft.com/commandline/windows-command-line-introducing-the-windows-pseudo-console-conpty/)).
|
||||
|
||||
---
|
||||
|
||||
## Documentation
|
||||
|
||||
All project documentation is located at [aka.ms/terminal-docs](https://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).
|
||||
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).
|
||||
|
||||
---
|
||||
|
||||
## Contributing
|
||||
|
||||
We are excited to work alongside you, our amazing community, to build and
|
||||
enhance Windows Terminal\!
|
||||
We are excited to work alongside you, our amazing community, to build and enhance Windows Terminal\!
|
||||
|
||||
***BEFORE you start work on a feature/fix***, please read & follow our
|
||||
[Contributor's
|
||||
Guide](https://github.com/microsoft/terminal/blob/main/CONTRIBUTING.md) to
|
||||
help avoid any wasted or duplicate effort.
|
||||
***BEFORE you start work on a feature/fix***, please read & follow our [Contributor's Guide](https://github.com/microsoft/terminal/blob/master/CONTRIBUTING.md) to help avoid any wasted or duplicate effort.
|
||||
|
||||
## Communicating with the Team
|
||||
|
||||
The easiest way to communicate with the team is via GitHub issues.
|
||||
|
||||
Please file new issues, feature requests and suggestions, but **DO search for
|
||||
similar open/closed pre-existing issues before creating a new issue.**
|
||||
Please file new issues, feature requests and suggestions, but **DO search for similar open/closed pre-existing issues before creating a new issue.**
|
||||
|
||||
If you would like to ask a question that you feel doesn't warrant an issue
|
||||
(yet), please reach out to us via Twitter:
|
||||
If you would like to ask a question that you feel doesn't warrant an issue (yet), please reach out to us via Twitter:
|
||||
|
||||
* Kayla Cinnamon, Program Manager:
|
||||
[@cinnamon\_msft](https://twitter.com/cinnamon_msft)
|
||||
* Kayla Cinnamon, Program Manager: [@cinnamon\_msft](https://twitter.com/cinnamon_msft)
|
||||
* Dustin Howett, Engineering Lead: [@dhowett](https://twitter.com/DHowett)
|
||||
* Michael Niksa, Senior Developer:
|
||||
[@michaelniksa](https://twitter.com/MichaelNiksa)
|
||||
* Michael Niksa, Senior Developer: [@michaelniksa](https://twitter.com/MichaelNiksa)
|
||||
* Mike Griese, Developer: [@zadjii](https://twitter.com/zadjii)
|
||||
* 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
|
||||
|
||||
## Prerequisites
|
||||
|
||||
* You must be running Windows 1903 (build >= 10.0.18362.0) or later to run
|
||||
Windows Terminal
|
||||
* You must [enable Developer Mode in the Windows Settings
|
||||
app](https://docs.microsoft.com/en-us/windows/uwp/get-started/enable-your-device-for-development)
|
||||
to locally install and run Windows Terminal
|
||||
* You must have the [Windows 10 1903
|
||||
SDK](https://developer.microsoft.com/en-us/windows/downloads/windows-10-sdk)
|
||||
installed
|
||||
* You must have at least [VS
|
||||
2019](https://visualstudio.microsoft.com/downloads/) installed
|
||||
* You must install the following Workloads via the VS Installer. Note: Opening
|
||||
the solution in VS 2019 will [prompt you to install missing components
|
||||
automatically](https://devblogs.microsoft.com/setup/configure-visual-studio-across-your-organization-with-vsconfig/):
|
||||
* You must be running Windows 1903 (build >= 10.0.18362.0) or later to run Windows Terminal
|
||||
* You must [enable Developer Mode in the Windows Settings app](https://docs.microsoft.com/en-us/windows/uwp/get-started/enable-your-device-for-development) to locally install and run Windows Terminal
|
||||
* You must have the [Windows 10 1903 SDK](https://developer.microsoft.com/en-us/windows/downloads/windows-10-sdk) installed
|
||||
* You must have at least [VS 2019](https://visualstudio.microsoft.com/downloads/) installed
|
||||
* You must install the following Workloads via the VS Installer. Note: Opening the solution in VS 2019 will [prompt you to install missing components automatically](https://devblogs.microsoft.com/setup/configure-visual-studio-across-your-organization-with-vsconfig/):
|
||||
* Desktop Development with C++
|
||||
* Universal Windows Platform Development
|
||||
* **The following Individual Components**
|
||||
@@ -304,17 +180,13 @@ If you would like to ask a question that you feel doesn't warrant an issue
|
||||
|
||||
## Building the Code
|
||||
|
||||
This repository uses [git
|
||||
submodules](https://git-scm.com/book/en/v2/Git-Tools-Submodules) for some of its
|
||||
dependencies. To make sure submodules are restored or updated, be sure to run
|
||||
the following prior to building:
|
||||
This repository uses [git submodules](https://git-scm.com/book/en/v2/Git-Tools-Submodules) for some of its dependencies. To make sure submodules are restored or updated, be sure to run the following prior to building:
|
||||
|
||||
```shell
|
||||
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:
|
||||
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:
|
||||
|
||||
### Building in PowerShell
|
||||
|
||||
@@ -333,42 +205,31 @@ bcz
|
||||
|
||||
## Running & Debugging
|
||||
|
||||
To debug the Windows Terminal in VS, right click on `CascadiaPackage` (in the
|
||||
Solution Explorer) and go to properties. In the Debug menu, change "Application
|
||||
process" and "Background task process" to "Native Only".
|
||||
To debug the Windows Terminal in VS, right click on `CascadiaPackage` (in the Solution Explorer) and go to properties. In the Debug menu, change "Application process" and "Background task process" to "Native Only".
|
||||
|
||||
You should then be able to build & debug the Terminal project by hitting
|
||||
<kbd>F5</kbd>.
|
||||
You should then be able to build & debug the Terminal project by hitting <kbd>F5</kbd>.
|
||||
|
||||
> 👉 You will _not_ be able to launch the Terminal directly by running the
|
||||
> WindowsTerminal.exe. For more details on why, see
|
||||
> [#926](https://github.com/microsoft/terminal/issues/926),
|
||||
> [#4043](https://github.com/microsoft/terminal/issues/4043)
|
||||
> 👉 You will _not_ be able to launch the Terminal directly by running the WindowsTerminal.exe. For more details on why, see [#926](https://github.com/microsoft/terminal/issues/926), [#4043](https://github.com/microsoft/terminal/issues/4043)
|
||||
|
||||
### Coding Guidance
|
||||
|
||||
Please review these brief docs below about our coding practices.
|
||||
|
||||
> 👉 If you find something missing from these docs, feel free to contribute to
|
||||
> any of our documentation files anywhere in the repository (or write some new
|
||||
> ones!)
|
||||
> 👉 If you find something missing from these docs, feel free to contribute to any of our documentation files anywhere in the repository (or write some new ones!)
|
||||
|
||||
This is a work in progress as we learn what we'll need to provide people in
|
||||
order to be effective contributors to our project.
|
||||
This is a work in progress as we learn what we'll need to provide people in order to be effective contributors to our project.
|
||||
|
||||
* [Coding Style](https://github.com/microsoft/terminal/blob/main/doc/STYLE.md)
|
||||
* [Code Organization](https://github.com/microsoft/terminal/blob/main/doc/ORGANIZATION.md)
|
||||
* [Exceptions in our legacy codebase](https://github.com/microsoft/terminal/blob/main/doc/EXCEPTIONS.md)
|
||||
* [Helpful smart pointers and macros for interfacing with Windows in WIL](https://github.com/microsoft/terminal/blob/main/doc/WIL.md)
|
||||
* [Coding Style](https://github.com/Microsoft/Terminal/blob/master/doc/STYLE.md)
|
||||
* [Code Organization](https://github.com/Microsoft/Terminal/blob/master/doc/ORGANIZATION.md)
|
||||
* [Exceptions in our legacy codebase](https://github.com/Microsoft/Terminal/blob/master/doc/EXCEPTIONS.md)
|
||||
* [Helpful smart pointers and macros for interfacing with Windows in WIL](https://github.com/Microsoft/Terminal/blob/master/doc/WIL.md)
|
||||
|
||||
---
|
||||
|
||||
## Code of Conduct
|
||||
# Code of Conduct
|
||||
|
||||
This project has adopted the [Microsoft Open Source Code of
|
||||
Conduct][conduct-code]. For more information see the [Code of Conduct
|
||||
FAQ][conduct-FAQ] or contact [opencode@microsoft.com][conduct-email] with any
|
||||
additional questions or comments.
|
||||
This project has adopted the [Microsoft Open Source Code of Conduct][conduct-code].
|
||||
For more information see the [Code of Conduct FAQ][conduct-FAQ] or contact [opencode@microsoft.com][conduct-email] with any additional questions or comments.
|
||||
|
||||
[conduct-code]: https://opensource.microsoft.com/codeofconduct/
|
||||
[conduct-FAQ]: https://opensource.microsoft.com/codeofconduct/faq/
|
||||
|
||||
17
SUPPORT.md
@@ -1,17 +0,0 @@
|
||||
# Support
|
||||
|
||||
## How to file issues and get help
|
||||
|
||||
This project uses [GitHub issues][gh-issue] to [track bugs][gh-bug] and [feature requests][gh-feature]. Please search the existing issues before filing new issues to avoid duplicates. For new topics, file your bug or feature request as a new issue.
|
||||
|
||||
For help and questions about using this project, please look at the [docs site for Windows Terminal][docs] and our [Contributor's Guide][contributor] if you want to work on Windows Terminal.
|
||||
|
||||
## Microsoft Support Policy
|
||||
|
||||
Support for Windows Terminal is limited to the resources listed above.
|
||||
|
||||
[gh-issue]: https://github.com/microsoft/terminal/issues/new/choose
|
||||
[gh-bug]: https://github.com/microsoft/terminal/issues/new?assignees=&labels=Issue-Bug&template=bug_report.md&title=
|
||||
[gh-feature]: https://github.com/microsoft/terminal/issues/new?assignees=&labels=Issue-Feature&template=Feature_Request.md&title=
|
||||
[docs]: https://docs.microsoft.com/windows/terminal
|
||||
[contributor]: https://github.com/microsoft/terminal/blob/main/CONTRIBUTING.md
|
||||
@@ -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,
|
||||
}
|
||||
@@ -1,175 +0,0 @@
|
||||
function GetAzureDevOpsBaseUri
|
||||
{
|
||||
Param(
|
||||
[string]$CollectionUri,
|
||||
[string]$TeamProject
|
||||
)
|
||||
|
||||
return $CollectionUri + $TeamProject
|
||||
}
|
||||
|
||||
function GetQueryTestRunsUri
|
||||
{
|
||||
Param(
|
||||
[string]$CollectionUri,
|
||||
[string]$TeamProject,
|
||||
[string]$BuildUri,
|
||||
[switch]$IncludeRunDetails
|
||||
)
|
||||
|
||||
if ($IncludeRunDetails)
|
||||
{
|
||||
$includeRunDetailsParameter = "&includeRunDetails=true"
|
||||
}
|
||||
else
|
||||
{
|
||||
$includeRunDetailsParameter = ""
|
||||
}
|
||||
|
||||
$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"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
Param(
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$WttInputPath,
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$WttSingleRerunInputPath,
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$WttMultipleRerunInputPath,
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$XUnitOutputPath,
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$TestNamePrefix
|
||||
)
|
||||
|
||||
# Ideally these would be passed as parameters to the script. However ps makes it difficult to deal with string literals containing '&', so we just
|
||||
# read the values directly from the environment variables
|
||||
$helixResultsContainerUri = $Env:HELIX_RESULTS_CONTAINER_URI
|
||||
$helixResultsContainerRsas = $Env:HELIX_RESULTS_CONTAINER_RSAS
|
||||
|
||||
$rerunPassesRequiredToAvoidFailure = $env:rerunPassesRequiredToAvoidFailure
|
||||
|
||||
Add-Type -Language CSharp -ReferencedAssemblies System.Xml,System.Xml.Linq,System.Runtime.Serialization,System.Runtime.Serialization.Json (Get-Content $PSScriptRoot\HelixTestHelpers.cs -Raw)
|
||||
|
||||
$testResultParser = [HelixTestHelpers.TestResultParser]::new($TestNamePrefix, $helixResultsContainerUri, $helixResultsContainerRsas)
|
||||
$testResultParser.ConvertWttLogToXUnitLog($WttInputPath, $WttSingleRerunInputPath, $WttMultipleRerunInputPath, $XUnitOutputPath, $rerunPassesRequiredToAvoidFailure)
|
||||
@@ -1,112 +0,0 @@
|
||||
$scriptDirectory = $script:MyInvocation.MyCommand.Path | Split-Path -Parent
|
||||
|
||||
# List all processes to aid debugging:
|
||||
Write-Host "All processes running:"
|
||||
Get-Process
|
||||
|
||||
tasklist /svc
|
||||
|
||||
# Add this test directory as an exclusion for Windows Defender
|
||||
Write-Host "Add $scriptDirectory as Exclusion Path"
|
||||
Add-MpPreference -ExclusionPath $scriptDirectory
|
||||
Write-Host "Add $($env:HELIX_CORRELATION_PAYLOAD) as Exclusion Path"
|
||||
Add-MpPreference -ExclusionPath $env:HELIX_CORRELATION_PAYLOAD
|
||||
Get-MpPreference
|
||||
Get-MpComputerStatus
|
||||
|
||||
|
||||
# Minimize all windows:
|
||||
$shell = New-Object -ComObject "Shell.Application"
|
||||
$shell.minimizeall()
|
||||
|
||||
# Kill any instances of Windows Security Alert:
|
||||
$windowTitleToMatch = "*Windows Security Alert*"
|
||||
$procs = Get-Process | Where {$_.MainWindowTitle -like "*Windows Security Alert*"}
|
||||
foreach ($proc in $procs)
|
||||
{
|
||||
Write-Host "Found process with '$windowTitleToMatch' title: $proc"
|
||||
$proc.Kill();
|
||||
}
|
||||
|
||||
# Kill processes by name that are known to interfere with our tests:
|
||||
$processNamesToStop = @("Microsoft.Photos", "WinStore.App", "SkypeApp", "SkypeBackgroundHost", "OneDriveSetup", "OneDrive")
|
||||
foreach($procName in $processNamesToStop)
|
||||
{
|
||||
Write-Host "Attempting to kill $procName if it is running"
|
||||
Stop-Process -ProcessName $procName -Verbose -ErrorAction Ignore
|
||||
}
|
||||
Write-Host "All processes running after attempting to kill unwanted processes:"
|
||||
Get-Process
|
||||
|
||||
tasklist /svc
|
||||
|
||||
$platform = $env:testbuildplatform
|
||||
if(!$platform)
|
||||
{
|
||||
$platform = "x86"
|
||||
}
|
||||
|
||||
function UninstallApps {
|
||||
Param([string[]]$appsToUninstall)
|
||||
|
||||
foreach($pkgName in $appsToUninstall)
|
||||
{
|
||||
foreach($pkg in (Get-AppxPackage $pkgName).PackageFullName)
|
||||
{
|
||||
Write-Output "Removing: $pkg"
|
||||
Remove-AppxPackage $pkg
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function UninstallTestApps {
|
||||
Param([string[]]$appsToUninstall)
|
||||
|
||||
foreach($pkgName in $appsToUninstall)
|
||||
{
|
||||
foreach($pkg in (Get-AppxPackage $pkgName).PackageFullName)
|
||||
{
|
||||
Write-Output "Removing: $pkg"
|
||||
Remove-AppxPackage $pkg
|
||||
}
|
||||
|
||||
# Sometimes an app can get into a state where it is no longer returned by Get-AppxPackage, but it is still present
|
||||
# which prevents other versions of the app from being installed.
|
||||
# To handle this, we can directly call Remove-AppxPackage against the full name of the package. However, without
|
||||
# Get-AppxPackage to find the PackageFullName, we just have to manually construct the name.
|
||||
$packageFullName = "$($pkgName)_1.0.0.0_$($platform)__8wekyb3d8bbwe"
|
||||
Write-Host "Removing $packageFullName if installed"
|
||||
Remove-AppPackage $packageFullName -ErrorVariable appxerror -ErrorAction SilentlyContinue
|
||||
if($appxerror)
|
||||
{
|
||||
foreach($error in $appxerror)
|
||||
{
|
||||
# In most cases, Remove-AppPackage will fail due to the package not being found. Don't treat this as an error.
|
||||
if(!($error.Exception.Message -match "0x80073CF1"))
|
||||
{
|
||||
Write-Error $error
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Write-Host "Successfully removed $packageFullName"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Write-Host "Uninstall AppX packages that are known to cause issues with our tests"
|
||||
UninstallApps("*Skype*", "*Windows.Photos*")
|
||||
|
||||
Write-Host "Uninstall any of our test apps that may have been left over from previous test runs"
|
||||
UninstallTestApps("NugetPackageTestApp", "NugetPackageTestAppCX", "IXMPTestApp", "MUXControlsTestApp")
|
||||
|
||||
Write-Host "Uninstall MUX Framework package that may have been left over from previous test runs"
|
||||
# We don't want to uninstall all versions of the MUX Framework package, as there may be other apps preinstalled on the system
|
||||
# that depend on it. We only uninstall the Framework package that corresponds to the version of MUX that we are testing.
|
||||
[xml]$versionData = (Get-Content "version.props")
|
||||
$versionMajor = $versionData.GetElementsByTagName("MUXVersionMajor").'#text'
|
||||
$versionMinor = $versionData.GetElementsByTagName("MUXVersionMinor").'#text'
|
||||
UninstallApps("Microsoft.UI.Xaml.$versionMajor.$versionMinor")
|
||||
|
||||
Get-Process
|
||||
@@ -1,336 +0,0 @@
|
||||
[CmdLetBinding()]
|
||||
Param(
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$TestFile,
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$OutputProjFile,
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$JobTestSuiteName,
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$TaefPath,
|
||||
|
||||
[string]$TaefQuery
|
||||
)
|
||||
|
||||
Class TestCollection
|
||||
{
|
||||
[string]$Name
|
||||
[string]$SetupMethodName
|
||||
[string]$TeardownMethodName
|
||||
[System.Collections.Generic.Dictionary[string, string]]$Properties
|
||||
|
||||
TestCollection()
|
||||
{
|
||||
if ($this.GetType() -eq [TestCollection])
|
||||
{
|
||||
throw "This class should never be instantiated directly; it should only be derived from."
|
||||
}
|
||||
}
|
||||
|
||||
TestCollection([string]$name)
|
||||
{
|
||||
$this.Init($name)
|
||||
}
|
||||
|
||||
hidden Init([string]$name)
|
||||
{
|
||||
$this.Name = $name
|
||||
$this.Properties = @{}
|
||||
}
|
||||
}
|
||||
|
||||
Class Test : TestCollection
|
||||
{
|
||||
Test([string]$name)
|
||||
{
|
||||
$this.Init($name)
|
||||
}
|
||||
}
|
||||
|
||||
Class TestClass : TestCollection
|
||||
{
|
||||
[System.Collections.Generic.List[Test]]$Tests
|
||||
|
||||
TestClass([string]$name)
|
||||
{
|
||||
$this.Init($name)
|
||||
$this.Tests = @{}
|
||||
}
|
||||
}
|
||||
|
||||
Class TestModule : TestCollection
|
||||
{
|
||||
[System.Collections.Generic.List[TestClass]]$TestClasses
|
||||
|
||||
TestModule([string]$name)
|
||||
{
|
||||
$this.Init($name)
|
||||
$this.TestClasses = @{}
|
||||
}
|
||||
}
|
||||
|
||||
function Parse-TestInfo([string]$taefOutput)
|
||||
{
|
||||
enum LineType
|
||||
{
|
||||
None
|
||||
TestModule
|
||||
TestClass
|
||||
Test
|
||||
Setup
|
||||
Teardown
|
||||
Property
|
||||
}
|
||||
|
||||
[string]$testModuleIndentation = " "
|
||||
[string]$testClassIndentation = " "
|
||||
[string]$testIndentation = " "
|
||||
[string]$setupBeginning = "Setup: "
|
||||
[string]$teardownBeginning = "Teardown: "
|
||||
[string]$propertyBeginning = "Property["
|
||||
|
||||
function Get-LineType([string]$line)
|
||||
{
|
||||
if ($line.Contains($setupBeginning))
|
||||
{
|
||||
return [LineType]::Setup;
|
||||
}
|
||||
elseif ($line.Contains($teardownBeginning))
|
||||
{
|
||||
return [LineType]::Teardown;
|
||||
}
|
||||
elseif ($line.Contains($propertyBeginning))
|
||||
{
|
||||
return [LineType]::Property;
|
||||
}
|
||||
elseif ($line.StartsWith($testModuleIndentation) -and -not $line.StartsWith("$testModuleIndentation "))
|
||||
{
|
||||
return [LineType]::TestModule;
|
||||
}
|
||||
elseif ($line.StartsWith($testClassIndentation) -and -not $line.StartsWith("$testClassIndentation "))
|
||||
{
|
||||
return [LineType]::TestClass;
|
||||
}
|
||||
elseif ($line.StartsWith($testIndentation) -and -not $line.StartsWith("$testIndentation "))
|
||||
{
|
||||
return [LineType]::Test;
|
||||
}
|
||||
else
|
||||
{
|
||||
return [LineType]::None;
|
||||
}
|
||||
}
|
||||
|
||||
[string[]]$lines = $taefOutput.Split(@([Environment]::NewLine, "`n"), [StringSplitOptions]::RemoveEmptyEntries)
|
||||
[System.Collections.Generic.List[TestModule]]$testModules = @()
|
||||
|
||||
[TestModule]$currentTestModule = $null
|
||||
[TestClass]$currentTestClass = $null
|
||||
[Test]$currentTest = $null
|
||||
|
||||
[TestCollection]$lastTestCollection = $null
|
||||
|
||||
foreach ($rawLine in $lines)
|
||||
{
|
||||
[LineType]$lineType = (Get-LineType $rawLine)
|
||||
|
||||
# We don't need the whitespace around the line anymore, so we'll discard it to make things easier.
|
||||
[string]$line = $rawLine.Trim()
|
||||
|
||||
if ($lineType -eq [LineType]::TestModule)
|
||||
{
|
||||
if ($currentTest -ne $null -and $currentTestClass -ne $null)
|
||||
{
|
||||
$currentTestClass.Tests.Add($currentTest)
|
||||
}
|
||||
|
||||
if ($currentTestClass -ne $null -and $currentTestModule -ne $null)
|
||||
{
|
||||
$currentTestModule.TestClasses.Add($currentTestClass)
|
||||
}
|
||||
|
||||
if ($currentTestModule -ne $null)
|
||||
{
|
||||
$testModules.Add($currentTestModule)
|
||||
}
|
||||
|
||||
$currentTestModule = [TestModule]::new($line)
|
||||
$currentTestClass = $null
|
||||
$currentTest = $null
|
||||
$lastTestCollection = $currentTestModule
|
||||
}
|
||||
elseif ($lineType -eq [LineType]::TestClass)
|
||||
{
|
||||
if ($currentTest -ne $null -and $currentTestClass -ne $null)
|
||||
{
|
||||
$currentTestClass.Tests.Add($currentTest)
|
||||
}
|
||||
|
||||
if ($currentTestClass -ne $null -and $currentTestModule -ne $null)
|
||||
{
|
||||
$currentTestModule.TestClasses.Add($currentTestClass)
|
||||
}
|
||||
|
||||
$currentTestClass = [TestClass]::new($line)
|
||||
$currentTest = $null
|
||||
$lastTestCollection = $currentTestClass
|
||||
}
|
||||
elseif ($lineType -eq [LineType]::Test)
|
||||
{
|
||||
if ($currentTest -ne $null -and $currentTestClass -ne $null)
|
||||
{
|
||||
$currentTestClass.Tests.Add($currentTest)
|
||||
}
|
||||
|
||||
$currentTest = [Test]::new($line)
|
||||
$lastTestCollection = $currentTest
|
||||
}
|
||||
elseif ($lineType -eq [LineType]::Setup)
|
||||
{
|
||||
if ($lastTestCollection -ne $null)
|
||||
{
|
||||
$lastTestCollection.SetupMethodName = $line.Replace($setupBeginning, "")
|
||||
}
|
||||
}
|
||||
elseif ($lineType -eq [LineType]::Teardown)
|
||||
{
|
||||
if ($lastTestCollection -ne $null)
|
||||
{
|
||||
$lastTestCollection.TeardownMethodName = $line.Replace($teardownBeginning, "")
|
||||
}
|
||||
}
|
||||
elseif ($lineType -eq [LineType]::Property)
|
||||
{
|
||||
if ($lastTestCollection -ne $null)
|
||||
{
|
||||
foreach ($match in [Regex]::Matches($line, "Property\[(.*)\]\s+=\s+(.*)"))
|
||||
{
|
||||
[string]$propertyKey = $match.Groups[1].Value;
|
||||
[string]$propertyValue = $match.Groups[2].Value;
|
||||
$lastTestCollection.Properties.Add($propertyKey, $propertyValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($currentTest -ne $null -and $currentTestClass -ne $null)
|
||||
{
|
||||
$currentTestClass.Tests.Add($currentTest)
|
||||
}
|
||||
|
||||
if ($currentTestClass -ne $null -and $currentTestModule -ne $null)
|
||||
{
|
||||
$currentTestModule.TestClasses.Add($currentTestClass)
|
||||
}
|
||||
|
||||
if ($currentTestModule -ne $null)
|
||||
{
|
||||
$testModules.Add($currentTestModule)
|
||||
}
|
||||
|
||||
return $testModules
|
||||
}
|
||||
|
||||
Write-Verbose "TaefQuery = $TaefQuery"
|
||||
|
||||
$TaefSelectQuery = ""
|
||||
$TaefQueryToAppend = ""
|
||||
if($TaefQuery)
|
||||
{
|
||||
$TaefSelectQuery = "/select:`"$TaefQuery`""
|
||||
$TaefQueryToAppend = " and $TaefQuery"
|
||||
}
|
||||
Write-Verbose "TaefSelectQuery = $TaefSelectQuery"
|
||||
|
||||
|
||||
$taefExe = "$TaefPath\te.exe"
|
||||
[string]$taefOutput = & "$taefExe" /listproperties $TaefSelectQuery $TestFile | Out-String
|
||||
|
||||
[System.Collections.Generic.List[TestModule]]$testModules = (Parse-TestInfo $taefOutput)
|
||||
|
||||
$projFileContent = @"
|
||||
<Project>
|
||||
<ItemGroup>
|
||||
"@
|
||||
|
||||
foreach ($testModule in $testModules)
|
||||
{
|
||||
foreach ($testClass in $testModules.TestClasses)
|
||||
{
|
||||
Write-Host "Generating Helix work item for test class $($testClass.Name)..."
|
||||
[System.Collections.Generic.List[string]]$testSuiteNames = @()
|
||||
|
||||
$testSuiteExists = $false
|
||||
$suitelessTestExists = $false
|
||||
|
||||
foreach ($test in $testClass.Tests)
|
||||
{
|
||||
# A test method inherits its 'TestSuite' property from its TestClass
|
||||
if (!$test.Properties.ContainsKey("TestSuite") -and $testClass.Properties.ContainsKey("TestSuite"))
|
||||
{
|
||||
$test.Properties["TestSuite"] = $testClass.Properties["TestSuite"]
|
||||
}
|
||||
|
||||
if ($test.Properties.ContainsKey("TestSuite"))
|
||||
{
|
||||
[string]$testSuite = $test.Properties["TestSuite"]
|
||||
|
||||
if (-not $testSuiteNames.Contains($testSuite))
|
||||
{
|
||||
Write-Host " Found test suite $testSuite. Generating Helix work item for it as well."
|
||||
$testSuiteNames.Add($testSuite)
|
||||
}
|
||||
|
||||
$testSuiteExists = $true
|
||||
}
|
||||
else
|
||||
{
|
||||
$suitelessTestExists = $true
|
||||
}
|
||||
}
|
||||
|
||||
$testClassSelectPattern = "$($testClass.Name).*"
|
||||
if($testClass.Name.Contains("::"))
|
||||
{
|
||||
$testClassSelectPattern = "$($testClass.Name)::*"
|
||||
}
|
||||
$testNameQuery= "(@Name='$testClassSelectPattern')"
|
||||
|
||||
$workItemName = $testClass.Name
|
||||
# Native tests use '::' as a separator, which is not valid for workItem names.
|
||||
$workItemName = $workItemName -replace "::", "-"
|
||||
|
||||
if ($suitelessTestExists)
|
||||
{
|
||||
$projFileContent += @"
|
||||
|
||||
<HelixWorkItem Include="$($workItemName)" Condition="'`$(TestSuite)'=='$($JobTestSuiteName)'">
|
||||
<Timeout>00:30:00</Timeout>
|
||||
<Command>call %HELIX_CORRELATION_PAYLOAD%\runtests.cmd /select:"(@Name='$($testClass.Name)*'$(if ($testSuiteExists) { "and not @TestSuite='*'" }))$($TaefQueryToAppend)"</Command>
|
||||
</HelixWorkItem>
|
||||
"@
|
||||
}
|
||||
|
||||
foreach ($testSuiteName in $testSuiteNames)
|
||||
{
|
||||
$projFileContent += @"
|
||||
|
||||
<HelixWorkItem Include="$($workItemName)-$testSuiteName" Condition="'`$(TestSuite)'=='$($JobTestSuiteName)'">
|
||||
<Timeout>00:30:00</Timeout>
|
||||
<Command>call %HELIX_CORRELATION_PAYLOAD%\runtests.cmd /select:"(@Name='$($testClass.Name)*' and @TestSuite='$testSuiteName')$($TaefQueryToAppend)"</Command>
|
||||
</HelixWorkItem>
|
||||
"@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$projFileContent += @"
|
||||
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
"@
|
||||
|
||||
Set-Content $OutputProjFile $projFileContent -NoNewline -Encoding UTF8
|
||||
@@ -1,669 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Runtime.Serialization.Json;
|
||||
using System.Text;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace HelixTestHelpers
|
||||
{
|
||||
public class TestResult
|
||||
{
|
||||
public TestResult()
|
||||
{
|
||||
Screenshots = new List<string>();
|
||||
RerunResults = new List<TestResult>();
|
||||
}
|
||||
|
||||
public string Name { get; set; }
|
||||
public string SourceWttFile { get; set; }
|
||||
public bool Passed { get; set; }
|
||||
public bool CleanupPassed { get; set; }
|
||||
public TimeSpan ExecutionTime { get; set; }
|
||||
public string Details { get; set; }
|
||||
|
||||
public List<string> Screenshots { get; private set; }
|
||||
public List<TestResult> RerunResults { get; private set; }
|
||||
|
||||
// Returns true if the test pass rate is sufficient to avoid being counted as a failure.
|
||||
public bool PassedOrUnreliable(int requiredNumberOfPasses)
|
||||
{
|
||||
if(Passed)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(RerunResults.Count == 1)
|
||||
{
|
||||
return RerunResults[0].Passed;
|
||||
}
|
||||
else
|
||||
{
|
||||
return RerunResults.Where(r => r.Passed).Count() >= requiredNumberOfPasses;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Azure DevOps doesn't currently provide a way to directly report sub-results for tests that failed at least once
|
||||
// that were run multiple times. To get around that limitation, we'll mark the test as "Skip" since
|
||||
// that's the only non-pass/fail result we can return, and will then report the information about the
|
||||
// runs in the "reason" category for the skipped test. In order to save space, we'll make the following
|
||||
// optimizations for size:
|
||||
//
|
||||
// 1. Serialize as JSON, which is more compact than XML;
|
||||
// 2. Don't serialize values that we don't need;
|
||||
// 3. Store the URL prefix and suffix for the blob storage URL only once instead of
|
||||
// storing every log and screenshot URL in its entirety; and
|
||||
// 4. Store a list of unique error messages and then index into that instead of
|
||||
// storing every error message in its entirety.
|
||||
//
|
||||
// #4 is motivated by the fact that if a test fails multiple times, it probably failed for the same reason
|
||||
// each time, in which case we'd just be repeating ourselves if we stored every error message each time.
|
||||
//
|
||||
// TODO (https://github.com/dotnet/arcade/issues/2773): Once we're able to directly report things in a
|
||||
// more granular fashion than just a binary pass/fail result, we should do that.
|
||||
//
|
||||
[DataContract]
|
||||
internal class JsonSerializableTestResults
|
||||
{
|
||||
[DataMember]
|
||||
internal string blobPrefix;
|
||||
|
||||
[DataMember]
|
||||
internal string blobSuffix;
|
||||
|
||||
[DataMember]
|
||||
internal string[] errors;
|
||||
|
||||
[DataMember]
|
||||
internal JsonSerializableTestResult[] results;
|
||||
}
|
||||
|
||||
[DataContract]
|
||||
internal class JsonSerializableTestResult
|
||||
{
|
||||
[DataMember]
|
||||
internal string outcome;
|
||||
|
||||
[DataMember]
|
||||
internal int duration;
|
||||
|
||||
[DataMember(EmitDefaultValue = false)]
|
||||
internal string log;
|
||||
|
||||
[DataMember(EmitDefaultValue = false)]
|
||||
internal string[] screenshots;
|
||||
|
||||
[DataMember(EmitDefaultValue = false)]
|
||||
internal int errorIndex;
|
||||
}
|
||||
|
||||
public class TestPass
|
||||
{
|
||||
public TimeSpan TestPassExecutionTime { get; set; }
|
||||
public List<TestResult> TestResults { get; set; }
|
||||
|
||||
public static TestPass ParseTestWttFile(string fileName, bool cleanupFailuresAreRegressions, bool truncateTestNames)
|
||||
{
|
||||
using (var stream = File.OpenRead(fileName))
|
||||
{
|
||||
var doc = XDocument.Load(stream);
|
||||
var testResults = new List<TestResult>();
|
||||
var testExecutionTimeMap = new Dictionary<string, List<double>>();
|
||||
|
||||
TestResult currentResult = null;
|
||||
long frequency = 0;
|
||||
long startTime = 0;
|
||||
long stopTime = 0;
|
||||
bool inTestCleanup = false;
|
||||
|
||||
bool shouldLogToTestDetails = false;
|
||||
|
||||
long testPassStartTime = 0;
|
||||
long testPassStopTime = 0;
|
||||
|
||||
Func<XElement, bool> isScopeData = (elt) =>
|
||||
{
|
||||
return
|
||||
elt.Element("Data") != null &&
|
||||
elt.Element("Data").Element("WexContext") != null &&
|
||||
(
|
||||
elt.Element("Data").Element("WexContext").Value == "Cleanup" ||
|
||||
elt.Element("Data").Element("WexContext").Value == "TestScope" ||
|
||||
elt.Element("Data").Element("WexContext").Value == "TestScope" ||
|
||||
elt.Element("Data").Element("WexContext").Value == "ClassScope" ||
|
||||
elt.Element("Data").Element("WexContext").Value == "ModuleScope"
|
||||
);
|
||||
};
|
||||
|
||||
Func<XElement, bool> isModuleOrClassScopeStart = (elt) =>
|
||||
{
|
||||
return
|
||||
elt.Name == "Msg" &&
|
||||
elt.Element("Data") != null &&
|
||||
elt.Element("Data").Element("StartGroup") != null &&
|
||||
elt.Element("Data").Element("WexContext") != null &&
|
||||
(elt.Element("Data").Element("WexContext").Value == "ClassScope" ||
|
||||
elt.Element("Data").Element("WexContext").Value == "ModuleScope");
|
||||
};
|
||||
|
||||
Func<XElement, bool> isModuleScopeEnd = (elt) =>
|
||||
{
|
||||
return
|
||||
elt.Name == "Msg" &&
|
||||
elt.Element("Data") != null &&
|
||||
elt.Element("Data").Element("EndGroup") != null &&
|
||||
elt.Element("Data").Element("WexContext") != null &&
|
||||
elt.Element("Data").Element("WexContext").Value == "ModuleScope";
|
||||
};
|
||||
|
||||
Func<XElement, bool> isClassScopeEnd = (elt) =>
|
||||
{
|
||||
return
|
||||
elt.Name == "Msg" &&
|
||||
elt.Element("Data") != null &&
|
||||
elt.Element("Data").Element("EndGroup") != null &&
|
||||
elt.Element("Data").Element("WexContext") != null &&
|
||||
elt.Element("Data").Element("WexContext").Value == "ClassScope";
|
||||
};
|
||||
|
||||
int testsExecuting = 0;
|
||||
foreach (XElement element in doc.Root.Elements())
|
||||
{
|
||||
// Capturing the frequency data to record accurate
|
||||
// timing data.
|
||||
if (element.Name == "RTI")
|
||||
{
|
||||
frequency = Int64.Parse(element.Attribute("Frequency").Value);
|
||||
}
|
||||
|
||||
// It's possible for a test to launch another test. If that happens, we won't modify the
|
||||
// current result. Instead, we'll continue operating like normal and expect that we get two
|
||||
// EndTests nodes before our next StartTests. We'll check that we've actually got a stop time
|
||||
// before creating a new result. This will result in the two results being squashed
|
||||
// into one result of the outer test that ran the inner one.
|
||||
if (element.Name == "StartTest")
|
||||
{
|
||||
testsExecuting++;
|
||||
if (testsExecuting == 1)
|
||||
{
|
||||
string testName = element.Attribute("Title").Value;
|
||||
|
||||
if (truncateTestNames)
|
||||
{
|
||||
const string xamlNativePrefix = "Windows::UI::Xaml::Tests::";
|
||||
const string xamlManagedPrefix = "Windows.UI.Xaml.Tests.";
|
||||
if (testName.StartsWith(xamlNativePrefix))
|
||||
{
|
||||
testName = testName.Substring(xamlNativePrefix.Length);
|
||||
}
|
||||
else if (testName.StartsWith(xamlManagedPrefix))
|
||||
{
|
||||
testName = testName.Substring(xamlManagedPrefix.Length);
|
||||
}
|
||||
}
|
||||
|
||||
currentResult = new TestResult() { Name = testName, SourceWttFile = fileName, Passed = true, CleanupPassed = true };
|
||||
testResults.Add(currentResult);
|
||||
startTime = Int64.Parse(element.Descendants("WexTraceInfo").First().Attribute("TimeStamp").Value);
|
||||
inTestCleanup = false;
|
||||
shouldLogToTestDetails = true;
|
||||
stopTime = 0;
|
||||
}
|
||||
}
|
||||
else if (currentResult != null && element.Name == "EndTest")
|
||||
{
|
||||
testsExecuting--;
|
||||
|
||||
// If any inner test fails, we'll still fail the outer
|
||||
currentResult.Passed &= element.Attribute("Result").Value == "Pass";
|
||||
|
||||
// Only gather execution data if this is the outer test we ran initially
|
||||
if (testsExecuting == 0)
|
||||
{
|
||||
stopTime = Int64.Parse(element.Descendants("WexTraceInfo").First().Attribute("TimeStamp").Value);
|
||||
if (!testExecutionTimeMap.Keys.Contains(currentResult.Name))
|
||||
testExecutionTimeMap[currentResult.Name] = new List<double>();
|
||||
testExecutionTimeMap[currentResult.Name].Add((double)(stopTime - startTime) / frequency);
|
||||
currentResult.ExecutionTime = TimeSpan.FromSeconds(testExecutionTimeMap[currentResult.Name].Average());
|
||||
|
||||
startTime = 0;
|
||||
inTestCleanup = true;
|
||||
}
|
||||
}
|
||||
else if (currentResult != null &&
|
||||
(isModuleOrClassScopeStart(element) || isModuleScopeEnd(element) || isClassScopeEnd(element)))
|
||||
{
|
||||
shouldLogToTestDetails = false;
|
||||
inTestCleanup = false;
|
||||
}
|
||||
|
||||
// Log-appending methods.
|
||||
if (currentResult != null && element.Name == "Error")
|
||||
{
|
||||
if (shouldLogToTestDetails)
|
||||
{
|
||||
currentResult.Details += "\r\n[Error]: " + element.Attribute("UserText").Value;
|
||||
if (element.Attribute("File") != null && element.Attribute("File").Value != "")
|
||||
{
|
||||
currentResult.Details += (" [File " + element.Attribute("File").Value);
|
||||
if (element.Attribute("Line") != null)
|
||||
currentResult.Details += " Line: " + element.Attribute("Line").Value;
|
||||
currentResult.Details += "]";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// The test cleanup errors will often come after the test claimed to have
|
||||
// 'passed'. We treat them as errors as well.
|
||||
if (inTestCleanup)
|
||||
{
|
||||
currentResult.CleanupPassed = false;
|
||||
currentResult.Passed = false;
|
||||
// In stress mode runs, this test will run n times before cleanup is run. If the cleanup
|
||||
// fails, we want to fail every test.
|
||||
if (cleanupFailuresAreRegressions)
|
||||
{
|
||||
foreach (var result in testResults.Where(res => res.Name == currentResult.Name))
|
||||
{
|
||||
result.Passed = false;
|
||||
result.CleanupPassed = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (currentResult != null && element.Name == "Warn")
|
||||
{
|
||||
if (shouldLogToTestDetails)
|
||||
{
|
||||
currentResult.Details += "\r\n[Warn]: " + element.Attribute("UserText").Value;
|
||||
}
|
||||
|
||||
if (element.Attribute("File") != null && element.Attribute("File").Value != "")
|
||||
{
|
||||
currentResult.Details += (" [File " + element.Attribute("File").Value);
|
||||
if (element.Attribute("Line") != null)
|
||||
currentResult.Details += " Line: " + element.Attribute("Line").Value;
|
||||
currentResult.Details += "]";
|
||||
}
|
||||
}
|
||||
|
||||
if (currentResult != null && element.Name == "Msg")
|
||||
{
|
||||
var dataElement = element.Element("Data");
|
||||
if (dataElement != null)
|
||||
{
|
||||
var supportingInfo = dataElement.Element("SupportingInfo");
|
||||
if (supportingInfo != null)
|
||||
{
|
||||
var screenshots = supportingInfo.Elements("Item")
|
||||
.Where(item => GetAttributeValue(item, "Name") == "Screenshot")
|
||||
.Select(item => GetAttributeValue(item, "Value"));
|
||||
|
||||
foreach(var screenshot in screenshots)
|
||||
{
|
||||
string fileNameSuffix = string.Empty;
|
||||
|
||||
if (fileName.Contains("_rerun_multiple"))
|
||||
{
|
||||
fileNameSuffix = "_rerun_multiple";
|
||||
}
|
||||
else if (fileName.Contains("_rerun"))
|
||||
{
|
||||
fileNameSuffix = "_rerun";
|
||||
}
|
||||
|
||||
currentResult.Screenshots.Add(screenshot.Replace(".jpg", fileNameSuffix + ".jpg"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
testPassStartTime = Int64.Parse(doc.Root.Descendants("WexTraceInfo").First().Attribute("TimeStamp").Value);
|
||||
testPassStopTime = Int64.Parse(doc.Root.Descendants("WexTraceInfo").Last().Attribute("TimeStamp").Value);
|
||||
|
||||
var testPassTime = TimeSpan.FromSeconds((double)(testPassStopTime - testPassStartTime) / frequency);
|
||||
|
||||
foreach (TestResult testResult in testResults)
|
||||
{
|
||||
if (testResult.Details != null)
|
||||
{
|
||||
testResult.Details = testResult.Details.Trim();
|
||||
}
|
||||
}
|
||||
|
||||
var testpass = new TestPass
|
||||
{
|
||||
TestPassExecutionTime = testPassTime,
|
||||
TestResults = testResults
|
||||
};
|
||||
|
||||
return testpass;
|
||||
}
|
||||
}
|
||||
|
||||
public static TestPass ParseTestWttFileWithReruns(string fileName, string singleRerunFileName, string multipleRerunFileName, bool cleanupFailuresAreRegressions, bool truncateTestNames)
|
||||
{
|
||||
TestPass testPass = ParseTestWttFile(fileName, cleanupFailuresAreRegressions, truncateTestNames);
|
||||
TestPass singleRerunTestPass = File.Exists(singleRerunFileName) ? ParseTestWttFile(singleRerunFileName, cleanupFailuresAreRegressions, truncateTestNames) : null;
|
||||
TestPass multipleRerunTestPass = File.Exists(multipleRerunFileName) ? ParseTestWttFile(multipleRerunFileName, cleanupFailuresAreRegressions, truncateTestNames) : null;
|
||||
|
||||
List<TestResult> rerunTestResults = new List<TestResult>();
|
||||
|
||||
if (singleRerunTestPass != null)
|
||||
{
|
||||
rerunTestResults.AddRange(singleRerunTestPass.TestResults);
|
||||
}
|
||||
|
||||
if (multipleRerunTestPass != null)
|
||||
{
|
||||
rerunTestResults.AddRange(multipleRerunTestPass.TestResults);
|
||||
}
|
||||
|
||||
// For each failed test result, we'll check to see whether the test passed at least once upon rerun.
|
||||
// If so, we'll set PassedOnRerun to true to flag the fact that this is an unreliable test
|
||||
// rather than a genuine test failure.
|
||||
foreach (TestResult failedTestResult in testPass.TestResults.Where(r => !r.Passed))
|
||||
{
|
||||
failedTestResult.RerunResults.AddRange(rerunTestResults.Where(r => r.Name == failedTestResult.Name));
|
||||
}
|
||||
|
||||
return testPass;
|
||||
}
|
||||
|
||||
private static string GetAttributeValue(XElement element, string attributeName)
|
||||
{
|
||||
if(element.Attribute(attributeName) != null)
|
||||
{
|
||||
return element.Attribute(attributeName).Value;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static class FailedTestDetector
|
||||
{
|
||||
public static void OutputFailedTestQuery(string wttInputPath)
|
||||
{
|
||||
var testPass = TestPass.ParseTestWttFile(wttInputPath, cleanupFailuresAreRegressions: true, truncateTestNames: false);
|
||||
|
||||
List<string> failedTestNames = new List<string>();
|
||||
|
||||
foreach (var result in testPass.TestResults)
|
||||
{
|
||||
if (!result.Passed)
|
||||
{
|
||||
failedTestNames.Add(result.Name);
|
||||
}
|
||||
}
|
||||
|
||||
if (failedTestNames.Count > 0)
|
||||
{
|
||||
string failedTestSelectQuery = "(@Name='";
|
||||
|
||||
for (int i = 0; i < failedTestNames.Count; i++)
|
||||
{
|
||||
failedTestSelectQuery += failedTestNames[i];
|
||||
|
||||
if (i < failedTestNames.Count - 1)
|
||||
{
|
||||
failedTestSelectQuery += "' or @Name='";
|
||||
}
|
||||
}
|
||||
|
||||
failedTestSelectQuery += "')";
|
||||
|
||||
Console.WriteLine(failedTestSelectQuery);
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class TestResultParser
|
||||
{
|
||||
private string testNamePrefix;
|
||||
private string helixResultsContainerUri;
|
||||
private string helixResultsContainerRsas;
|
||||
|
||||
public TestResultParser(string testNamePrefix, string helixResultsContainerUri, string helixResultsContainerRsas)
|
||||
{
|
||||
this.testNamePrefix = testNamePrefix;
|
||||
this.helixResultsContainerUri = helixResultsContainerUri;
|
||||
this.helixResultsContainerRsas = helixResultsContainerRsas;
|
||||
}
|
||||
|
||||
public Dictionary<string, string> GetSubResultsJsonByMethodName(string wttInputPath, string wttSingleRerunInputPath, string wttMultipleRerunInputPath)
|
||||
{
|
||||
Dictionary<string, string> subResultsJsonByMethod = new Dictionary<string, string>();
|
||||
TestPass testPass = TestPass.ParseTestWttFileWithReruns(wttInputPath, wttSingleRerunInputPath, wttMultipleRerunInputPath, cleanupFailuresAreRegressions: true, truncateTestNames: false);
|
||||
|
||||
foreach (var result in testPass.TestResults)
|
||||
{
|
||||
var methodName = result.Name.Substring(result.Name.LastIndexOf('.') + 1);
|
||||
|
||||
if (!result.Passed)
|
||||
{
|
||||
// If a test failed, we'll have rerun it multiple times. We'll record the results of each run
|
||||
// formatted as JSON.
|
||||
JsonSerializableTestResults serializableResults = new JsonSerializableTestResults();
|
||||
serializableResults.blobPrefix = helixResultsContainerUri;
|
||||
serializableResults.blobSuffix = helixResultsContainerRsas;
|
||||
|
||||
List<string> errorList = new List<string>();
|
||||
errorList.Add(result.Details);
|
||||
|
||||
foreach (TestResult rerunResult in result.RerunResults)
|
||||
{
|
||||
errorList.Add(rerunResult.Details);
|
||||
}
|
||||
|
||||
serializableResults.errors = errorList.Distinct().Where(s => s != null).ToArray();
|
||||
|
||||
var reason = new XElement("reason");
|
||||
List<JsonSerializableTestResult> serializableResultList = new List<JsonSerializableTestResult>();
|
||||
serializableResultList.Add(ConvertToSerializableResult(result, serializableResults.errors));
|
||||
|
||||
foreach (TestResult rerunResult in result.RerunResults)
|
||||
{
|
||||
serializableResultList.Add(ConvertToSerializableResult(rerunResult, serializableResults.errors));
|
||||
}
|
||||
|
||||
serializableResults.results = serializableResultList.ToArray();
|
||||
|
||||
using (MemoryStream stream = new MemoryStream())
|
||||
{
|
||||
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(JsonSerializableTestResults));
|
||||
serializer.WriteObject(stream, serializableResults);
|
||||
stream.Position = 0;
|
||||
|
||||
using (StreamReader streamReader = new StreamReader(stream))
|
||||
{
|
||||
subResultsJsonByMethod.Add(methodName, streamReader.ReadToEnd());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return subResultsJsonByMethod;
|
||||
}
|
||||
|
||||
public void ConvertWttLogToXUnitLog(string wttInputPath, string wttSingleRerunInputPath, string wttMultipleRerunInputPath, string xunitOutputPath, int requiredPassRateThreshold)
|
||||
{
|
||||
TestPass testPass = TestPass.ParseTestWttFileWithReruns(wttInputPath, wttSingleRerunInputPath, wttMultipleRerunInputPath, cleanupFailuresAreRegressions: true, truncateTestNames: false);
|
||||
var results = testPass.TestResults;
|
||||
|
||||
int resultCount = results.Count;
|
||||
int passedCount = results.Where(r => r.Passed).Count();
|
||||
|
||||
// Since we re-run tests on failure, we'll mark every test that failed at least once as "skipped" rather than "failed".
|
||||
// If the test failed sufficiently often enough for it to count as a failed test (determined by a property on the
|
||||
// Azure DevOps job), we'll later mark it as failed during test results processing.
|
||||
|
||||
int failedCount = results.Where(r => !r.PassedOrUnreliable(requiredPassRateThreshold)).Count();
|
||||
int skippedCount = results.Where(r => !r.Passed && r.PassedOrUnreliable(requiredPassRateThreshold)).Count();
|
||||
|
||||
var root = new XElement("assemblies");
|
||||
|
||||
var assembly = new XElement("assembly");
|
||||
assembly.SetAttributeValue("name", "MUXControls.Test.dll");
|
||||
assembly.SetAttributeValue("test-framework", "TAEF");
|
||||
assembly.SetAttributeValue("run-date", DateTime.Now.ToString("yyyy-MM-dd"));
|
||||
|
||||
// This doesn't need to be completely accurate since it's not exposed anywhere.
|
||||
// If we need accurate an start time we can probably calculate it from the te.wtl file, but for
|
||||
// now this is fine.
|
||||
assembly.SetAttributeValue("run-time", (DateTime.Now - testPass.TestPassExecutionTime).ToString("hh:mm:ss"));
|
||||
|
||||
assembly.SetAttributeValue("total", resultCount);
|
||||
assembly.SetAttributeValue("passed", passedCount);
|
||||
assembly.SetAttributeValue("failed", failedCount);
|
||||
assembly.SetAttributeValue("skipped", skippedCount);
|
||||
|
||||
assembly.SetAttributeValue("time", (int)testPass.TestPassExecutionTime.TotalSeconds);
|
||||
assembly.SetAttributeValue("errors", 0);
|
||||
root.Add(assembly);
|
||||
|
||||
var collection = new XElement("collection");
|
||||
collection.SetAttributeValue("total", resultCount);
|
||||
collection.SetAttributeValue("passed", passedCount);
|
||||
collection.SetAttributeValue("failed", failedCount);
|
||||
collection.SetAttributeValue("skipped", skippedCount);
|
||||
collection.SetAttributeValue("name", "Test collection");
|
||||
collection.SetAttributeValue("time", (int)testPass.TestPassExecutionTime.TotalSeconds);
|
||||
assembly.Add(collection);
|
||||
|
||||
foreach (var result in results)
|
||||
{
|
||||
var test = new XElement("test");
|
||||
test.SetAttributeValue("name", testNamePrefix + "." + result.Name);
|
||||
|
||||
var className = GetTestClassName(result.Name);
|
||||
var methodName = GetTestMethodName(result.Name);
|
||||
test.SetAttributeValue("type", className);
|
||||
test.SetAttributeValue("method", methodName);
|
||||
|
||||
test.SetAttributeValue("time", result.ExecutionTime.TotalSeconds);
|
||||
|
||||
string resultString = string.Empty;
|
||||
|
||||
if (result.Passed)
|
||||
{
|
||||
resultString = "Pass";
|
||||
}
|
||||
else if(result.PassedOrUnreliable(requiredPassRateThreshold))
|
||||
{
|
||||
resultString = "Skip";
|
||||
}
|
||||
else
|
||||
{
|
||||
resultString = "Fail";
|
||||
}
|
||||
|
||||
|
||||
test.SetAttributeValue("result", resultString);
|
||||
|
||||
if (!result.Passed)
|
||||
{
|
||||
// If a test failed, we'll have rerun it multiple times.
|
||||
// We'll save the subresults to a JSON text file that we'll upload to the helix results container -
|
||||
// this allows it to be as long as we want, whereas the reason field in Azure DevOps has a 4000 character limit.
|
||||
string subResultsFileName = methodName + "_subresults.json";
|
||||
string subResultsFilePath = Path.Combine(Path.GetDirectoryName(wttInputPath), subResultsFileName);
|
||||
|
||||
if (result.PassedOrUnreliable(requiredPassRateThreshold))
|
||||
{
|
||||
var reason = new XElement("reason");
|
||||
reason.Add(new XCData(GetUploadedFileUrl(subResultsFileName, helixResultsContainerUri, helixResultsContainerRsas)));
|
||||
test.Add(reason);
|
||||
}
|
||||
else
|
||||
{
|
||||
var failure = new XElement("failure");
|
||||
var message = new XElement("message");
|
||||
message.Add(new XCData(GetUploadedFileUrl(subResultsFileName, helixResultsContainerUri, helixResultsContainerRsas)));
|
||||
failure.Add(message);
|
||||
test.Add(failure);
|
||||
}
|
||||
}
|
||||
collection.Add(test);
|
||||
}
|
||||
|
||||
File.WriteAllText(xunitOutputPath, root.ToString());
|
||||
}
|
||||
|
||||
private JsonSerializableTestResult ConvertToSerializableResult(TestResult rerunResult, string[] uniqueErrors)
|
||||
{
|
||||
var serializableResult = new JsonSerializableTestResult();
|
||||
|
||||
serializableResult.outcome = rerunResult.Passed ? "Passed" : "Failed";
|
||||
serializableResult.duration = (int)Math.Round(rerunResult.ExecutionTime.TotalMilliseconds);
|
||||
|
||||
if (!rerunResult.Passed)
|
||||
{
|
||||
serializableResult.log = Path.GetFileName(rerunResult.SourceWttFile);
|
||||
|
||||
if (rerunResult.Screenshots.Any())
|
||||
{
|
||||
List<string> screenshots = new List<string>();
|
||||
|
||||
foreach (var screenshot in rerunResult.Screenshots)
|
||||
{
|
||||
screenshots.Add(Path.GetFileName(screenshot));
|
||||
}
|
||||
|
||||
serializableResult.screenshots = screenshots.ToArray();
|
||||
}
|
||||
|
||||
// To conserve space, we'll log the index of the error to index in a list of unique errors rather than
|
||||
// jotting down every single error in its entirety. We'll add one to the result so we can avoid
|
||||
// serializing this property when it has the default value of 0.
|
||||
serializableResult.errorIndex = Array.IndexOf(uniqueErrors, rerunResult.Details) + 1;
|
||||
}
|
||||
|
||||
return serializableResult;
|
||||
}
|
||||
|
||||
private string GetUploadedFileUrl(string filePath, string helixResultsContainerUri, string helixResultsContainerRsas)
|
||||
{
|
||||
var filename = Path.GetFileName(filePath);
|
||||
return string.Format("{0}/{1}{2}", helixResultsContainerUri, filename, helixResultsContainerRsas);
|
||||
}
|
||||
|
||||
private string GetTestNameSeparator(string testname)
|
||||
{
|
||||
var separatorString = ".";
|
||||
if (!testname.Contains(separatorString))
|
||||
{
|
||||
separatorString = "::";
|
||||
}
|
||||
return separatorString;
|
||||
}
|
||||
|
||||
private string GetTestMethodName(string fullyQualifiedName)
|
||||
{
|
||||
var separatorString = GetTestNameSeparator(fullyQualifiedName);
|
||||
var methodName = fullyQualifiedName.Substring(fullyQualifiedName.LastIndexOf(separatorString) + separatorString.Length);
|
||||
|
||||
return methodName;
|
||||
}
|
||||
|
||||
private string GetTestClassName(string fullyQualifiedName)
|
||||
{
|
||||
var separatorString = GetTestNameSeparator(fullyQualifiedName);
|
||||
var className = fullyQualifiedName.Substring(0, fullyQualifiedName.LastIndexOf(separatorString));
|
||||
|
||||
return className;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
# Displaying progress is unnecessary and is just distracting.
|
||||
$ProgressPreference = "SilentlyContinue"
|
||||
|
||||
$dependencyFiles = Get-ChildItem -Filter "*Microsoft.VCLibs.*.appx"
|
||||
|
||||
foreach ($file in $dependencyFiles)
|
||||
{
|
||||
Write-Host "Adding dependency $($file)..."
|
||||
|
||||
Add-AppxPackage $file
|
||||
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
Param(
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$WttInputPath
|
||||
)
|
||||
|
||||
Add-Type -Language CSharp -ReferencedAssemblies System.Xml,System.Xml.Linq,System.Runtime.Serialization,System.Runtime.Serialization.Json (Get-Content $PSScriptRoot\HelixTestHelpers.cs -Raw)
|
||||
|
||||
[HelixTestHelpers.FailedTestDetector]::OutputFailedTestQuery($WttInputPath)
|
||||
@@ -1,32 +0,0 @@
|
||||
Param(
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$WttInputPath,
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$WttSingleRerunInputPath,
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$WttMultipleRerunInputPath,
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$TestNamePrefix
|
||||
)
|
||||
|
||||
# Ideally these would be passed as parameters to the script. However ps makes it difficult to deal with string literals containing '&', so we just
|
||||
# read the values directly from the environment variables
|
||||
$helixResultsContainerUri = $Env:HELIX_RESULTS_CONTAINER_URI
|
||||
$helixResultsContainerRsas = $Env:HELIX_RESULTS_CONTAINER_RSAS
|
||||
|
||||
Add-Type -Language CSharp -ReferencedAssemblies System.Xml,System.Xml.Linq,System.Runtime.Serialization,System.Runtime.Serialization.Json (Get-Content $PSScriptRoot\HelixTestHelpers.cs -Raw)
|
||||
|
||||
$testResultParser = [HelixTestHelpers.TestResultParser]::new($TestNamePrefix, $helixResultsContainerUri, $helixResultsContainerRsas)
|
||||
[System.Collections.Generic.Dictionary[string, string]]$subResultsJsonByMethodName = $testResultParser.GetSubResultsJsonByMethodName($WttInputPath, $WttSingleRerunInputPath, $WttMultipleRerunInputPath)
|
||||
|
||||
$subResultsJsonDirectory = [System.IO.Path]::GetDirectoryName($WttInputPath)
|
||||
|
||||
foreach ($methodName in $subResultsJsonByMethodName.Keys)
|
||||
{
|
||||
$subResultsJson = $subResultsJsonByMethodName[$methodName]
|
||||
$subResultsJsonPath = [System.IO.Path]::Combine($subResultsJsonDirectory, $methodName + "_subresults.json")
|
||||
Out-File $subResultsJsonPath -Encoding utf8 -InputObject $subResultsJson
|
||||
}
|
||||
@@ -1,131 +0,0 @@
|
||||
Param(
|
||||
[Parameter(Mandatory = $true)]
|
||||
[int]$MinimumExpectedTestsExecutedCount,
|
||||
|
||||
[string]$AccessToken = $env:SYSTEM_ACCESSTOKEN,
|
||||
[string]$CollectionUri = $env:SYSTEM_COLLECTIONURI,
|
||||
[string]$TeamProject = $env:SYSTEM_TEAMPROJECT,
|
||||
[string]$BuildUri = $env:BUILD_BUILDURI,
|
||||
[bool]$CheckJobAttempt
|
||||
)
|
||||
|
||||
$azureDevOpsRestApiHeaders = @{
|
||||
"Accept"="application/json"
|
||||
"Authorization"="Basic $([System.Convert]::ToBase64String([System.Text.ASCIIEncoding]::ASCII.GetBytes(":$AccessToken")))"
|
||||
}
|
||||
|
||||
. "$PSScriptRoot/AzurePipelinesHelperScripts.ps1"
|
||||
|
||||
Write-Host "Checking test results..."
|
||||
|
||||
$queryUri = GetQueryTestRunsUri -CollectionUri $CollectionUri -TeamProject $TeamProject -BuildUri $BuildUri -IncludeRunDetails
|
||||
Write-Host "queryUri = $queryUri"
|
||||
|
||||
$testRuns = Invoke-RestMethod -Uri $queryUri -Method Get -Headers $azureDevOpsRestApiHeaders
|
||||
[System.Collections.Generic.List[string]]$failingTests = @()
|
||||
[System.Collections.Generic.List[string]]$unreliableTests = @()
|
||||
[System.Collections.Generic.List[string]]$unexpectedResultTest = @()
|
||||
|
||||
[System.Collections.Generic.List[string]]$namesOfProcessedTestRuns = @()
|
||||
$totalTestsExecutedCount = 0
|
||||
|
||||
# We assume that we only have one testRun with a given name that we care about
|
||||
# We only process the last testRun with a given name (based on completedDate)
|
||||
# The name of a testRun is set to the Helix queue that it was run on (e.g. windows.10.amd64.client19h1.xaml)
|
||||
# If we have multiple test runs on the same queue that we care about, we will need to re-visit this logic
|
||||
foreach ($testRun in ($testRuns.value | Sort-Object -Property "completedDate" -Descending))
|
||||
{
|
||||
if ($CheckJobAttempt)
|
||||
{
|
||||
if ($namesOfProcessedTestRuns -contains $testRun.name)
|
||||
{
|
||||
Write-Host "Skipping test run '$($testRun.name)', since we have already processed a test run of that name."
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
Write-Host "Processing results from test run '$($testRun.name)'"
|
||||
$namesOfProcessedTestRuns.Add($testRun.name)
|
||||
|
||||
$totalTestsExecutedCount += $testRun.totalTests
|
||||
|
||||
$testRunResultsUri = "$($testRun.url)/results?api-version=5.0"
|
||||
$testResults = Invoke-RestMethod -Uri "$($testRun.url)/results?api-version=5.0" -Method Get -Headers $azureDevOpsRestApiHeaders
|
||||
|
||||
foreach ($testResult in $testResults.value)
|
||||
{
|
||||
$shortTestCaseTitle = $testResult.testCaseTitle -replace "[a-zA-Z0-9]+.[a-zA-Z0-9]+.Windows.UI.Xaml.Tests.MUXControls.",""
|
||||
|
||||
if ($testResult.outcome -eq "Failed")
|
||||
{
|
||||
if (-not $failingTests.Contains($shortTestCaseTitle))
|
||||
{
|
||||
$failingTests.Add($shortTestCaseTitle)
|
||||
}
|
||||
}
|
||||
elseif ($testResult.outcome -eq "Warning")
|
||||
{
|
||||
if (-not $unreliableTests.Contains($shortTestCaseTitle))
|
||||
{
|
||||
$unreliableTests.Add($shortTestCaseTitle)
|
||||
}
|
||||
}
|
||||
elseif ($testResult.outcome -ne "Passed")
|
||||
{
|
||||
# We should only see tests with result "Passed", "Failed" or "Warning"
|
||||
if (-not $unexpectedResultTest.Contains($shortTestCaseTitle))
|
||||
{
|
||||
$unexpectedResultTest.Add($shortTestCaseTitle)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($unreliableTests.Count -gt 0)
|
||||
{
|
||||
Write-Host @"
|
||||
##vso[task.logissue type=warning;]Unreliable tests:
|
||||
##vso[task.logissue type=warning;]$($unreliableTests -join "$([Environment]::NewLine)##vso[task.logissue type=warning;]")
|
||||
|
||||
"@
|
||||
}
|
||||
|
||||
if ($failingTests.Count -gt 0)
|
||||
{
|
||||
Write-Host @"
|
||||
##vso[task.logissue type=error;]Failing tests:
|
||||
##vso[task.logissue type=error;]$($failingTests -join "$([Environment]::NewLine)##vso[task.logissue type=error;]")
|
||||
|
||||
"@
|
||||
}
|
||||
|
||||
if ($unexpectedResultTest.Count -gt 0)
|
||||
{
|
||||
Write-Host @"
|
||||
##vso[task.logissue type=error;]Tests with unexpected results:
|
||||
##vso[task.logissue type=error;]$($unexpectedResultTest -join "$([Environment]::NewLine)##vso[task.logissue type=error;]")
|
||||
|
||||
"@
|
||||
}
|
||||
|
||||
if($totalTestsExecutedCount -lt $MinimumExpectedTestsExecutedCount)
|
||||
{
|
||||
Write-Host "Expected at least $MinimumExpectedTestsExecutedCount tests to be executed."
|
||||
Write-Host "Actual executed test count is: $totalTestsExecutedCount"
|
||||
Write-Host "##vso[task.complete result=Failed;]"
|
||||
}
|
||||
elseif ($failingTests.Count -gt 0)
|
||||
{
|
||||
Write-Host "At least one test failed."
|
||||
Write-Host "##vso[task.complete result=Failed;]"
|
||||
}
|
||||
elseif ($unreliableTests.Count -gt 0)
|
||||
{
|
||||
Write-Host "All tests eventually passed, but some initially failed."
|
||||
Write-Host "##vso[task.complete result=Succeeded;]"
|
||||
}
|
||||
else
|
||||
{
|
||||
Write-Host "All tests passed."
|
||||
Write-Host "##vso[task.complete result=Succeeded;]"
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
[CmdLetBinding()]
|
||||
Param(
|
||||
[string]$Platform,
|
||||
[string]$Configuration,
|
||||
[string]$ArtifactName='drop'
|
||||
)
|
||||
|
||||
$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)
|
||||
{
|
||||
Remove-Item $payloadDir -Recurse
|
||||
}
|
||||
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.58.210305002\build\Binaries\$Platform\*" $payloadDir
|
||||
Copy-Item "$nugetPackagesDir\Microsoft.Taef.10.58.210305002\build\Binaries\$Platform\NetFx4.5\*" $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
|
||||
{
|
||||
Param($source, $destinationDir)
|
||||
|
||||
if (Test-Path $source)
|
||||
{
|
||||
Write-Host "Copy from '$source' to '$destinationDir'"
|
||||
Copy-Item -Force $source $destinationDir
|
||||
}
|
||||
else
|
||||
{
|
||||
Write-Host "'$source' does not exist."
|
||||
}
|
||||
}
|
||||
|
||||
# Copy files from the 'drop' artifact dir
|
||||
Copy-Item "$repoDirectory\Artifacts\$ArtifactName\$Configuration\$Platform\Test\*" $payloadDir -Recurse
|
||||
|
||||
# Copy files from the repo
|
||||
New-Item -ItemType Directory -Force -Path "$payloadDir"
|
||||
Copy-Item "build\helix\ConvertWttLogToXUnit.ps1" "$payloadDir"
|
||||
Copy-Item "build\helix\OutputFailedTestQuery.ps1" "$payloadDir"
|
||||
Copy-Item "build\helix\OutputSubResultsJsonFiles.ps1" "$payloadDir"
|
||||
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
|
||||
@@ -1,110 +0,0 @@
|
||||
Param(
|
||||
[string]$AccessToken = $env:SYSTEM_ACCESSTOKEN,
|
||||
[string]$HelixAccessToken = $env:HelixAccessToken,
|
||||
[string]$CollectionUri = $env:SYSTEM_COLLECTIONURI,
|
||||
[string]$TeamProject = $env:SYSTEM_TEAMPROJECT,
|
||||
[string]$BuildUri = $env:BUILD_BUILDURI,
|
||||
[string]$OutputFolder = "HelixOutput"
|
||||
)
|
||||
|
||||
$helixLinkFile = "$OutputFolder\LinksToHelixTestFiles.html"
|
||||
|
||||
|
||||
function Generate-File-Links
|
||||
{
|
||||
Param ([Array[]]$files,[string]$sectionName)
|
||||
if($files.Count -gt 0)
|
||||
{
|
||||
Out-File -FilePath $helixLinkFile -Append -InputObject "<div class=$sectionName>"
|
||||
Out-File -FilePath $helixLinkFile -Append -InputObject "<h4>$sectionName</h4>"
|
||||
Out-File -FilePath $helixLinkFile -Append -InputObject "<ul>"
|
||||
foreach($file in $files)
|
||||
{
|
||||
Out-File -FilePath $helixLinkFile -Append -InputObject "<li><a href=$($file.Link)>$($file.Name)</a></li>"
|
||||
}
|
||||
Out-File -FilePath $helixLinkFile -Append -InputObject "</ul>"
|
||||
Out-File -FilePath $helixLinkFile -Append -InputObject "</div>"
|
||||
}
|
||||
}
|
||||
|
||||
#Create output directory
|
||||
New-Item $OutputFolder -ItemType Directory
|
||||
|
||||
$azureDevOpsRestApiHeaders = @{
|
||||
"Accept"="application/json"
|
||||
"Authorization"="Basic $([System.Convert]::ToBase64String([System.Text.ASCIIEncoding]::ASCII.GetBytes(":$AccessToken")))"
|
||||
}
|
||||
|
||||
. "$PSScriptRoot/AzurePipelinesHelperScripts.ps1"
|
||||
|
||||
$queryUri = GetQueryTestRunsUri -CollectionUri $CollectionUri -TeamProject $TeamProject -BuildUri $BuildUri -IncludeRunDetails
|
||||
Write-Host "queryUri = $queryUri"
|
||||
|
||||
$testRuns = Invoke-RestMethodWithRetries $queryUri -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
|
||||
$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))
|
||||
{
|
||||
$workItems.Add($workItem)
|
||||
$filesQueryUri = "https://helix.dot.net/api/2019-06-17/jobs/$helixJobId/workitems/$helixWorkItemName/files$accessTokenParam"
|
||||
$files = Invoke-RestMethodWithRetries $filesQueryUri
|
||||
|
||||
$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)
|
||||
{
|
||||
if(-Not $isTestRunNameShown)
|
||||
{
|
||||
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))
|
||||
{
|
||||
New-Item $fullPath -ItemType Directory
|
||||
}
|
||||
|
||||
$link = $pgcFile.Link
|
||||
|
||||
Write-Host "Downloading $link to $destination"
|
||||
|
||||
Download-FileWithRetries $link $destination
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
<Project Sdk="Microsoft.DotNet.Helix.Sdk" DefaultTargets="Test">
|
||||
<PropertyGroup>
|
||||
<HelixSource>pr/terminal/$(BUILD_SOURCEBRANCH)/</HelixSource>
|
||||
<EnableXUnitReporter>true</EnableXUnitReporter>
|
||||
<EnableAzurePipelinesReporter>true</EnableAzurePipelinesReporter>
|
||||
<FailOnMissionControlTestFailure>true</FailOnMissionControlTestFailure>
|
||||
<HelixPreCommands>$(HelixPreCommands);set testnameprefix=$(Configuration).$(Platform);set testbuildplatform=$(Platform);set rerunPassesRequiredToAvoidFailure=$(rerunPassesRequiredToAvoidFailure)</HelixPreCommands>
|
||||
<OutputPath>..\..\bin\$(Platform)\$(Configuration)\</OutputPath>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<HelixCorrelationPayload Include="..\..\HelixPayload\$(Configuration)\$(Platform)" />
|
||||
</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' " />
|
||||
</Project>
|
||||
@@ -1,135 +0,0 @@
|
||||
[CmdLetBinding()]
|
||||
Param(
|
||||
[Parameter(Mandatory = $true)]
|
||||
[int]$RerunPassesRequiredToAvoidFailure,
|
||||
|
||||
[string]$AccessToken = $env:SYSTEM_ACCESSTOKEN,
|
||||
[string]$CollectionUri = $env:SYSTEM_COLLECTIONURI,
|
||||
[string]$TeamProject = $env:SYSTEM_TEAMPROJECT,
|
||||
[string]$BuildUri = $env:BUILD_BUILDURI
|
||||
)
|
||||
|
||||
. "$PSScriptRoot/AzurePipelinesHelperScripts.ps1"
|
||||
|
||||
|
||||
$azureDevOpsRestApiHeaders = @{
|
||||
"Accept"="application/json"
|
||||
"Authorization"="Basic $([System.Convert]::ToBase64String([System.Text.ASCIIEncoding]::ASCII.GetBytes(":$AccessToken")))"
|
||||
}
|
||||
|
||||
$queryUri = GetQueryTestRunsUri -CollectionUri $CollectionUri -TeamProject $TeamProject -BuildUri $BuildUri
|
||||
Write-Host "queryUri = $queryUri"
|
||||
|
||||
# To account for unreliable tests, we'll iterate through all of the tests associated with this build, check to see any tests that were unreliable
|
||||
# (denoted by being marked as "skipped"), and if so, we'll instead mark those tests with a warning and enumerate all of the attempted runs
|
||||
# with their pass/fail states as well as any relevant error messages for failed attempts.
|
||||
$testRuns = Invoke-RestMethod -Uri $queryUri -Method Get -Headers $azureDevOpsRestApiHeaders
|
||||
|
||||
$timesSeenByRunName = @{}
|
||||
|
||||
foreach ($testRun in $testRuns.value)
|
||||
{
|
||||
$testRunResultsUri = "$($testRun.url)/results?api-version=5.0"
|
||||
|
||||
Write-Host "Marking test run `"$($testRun.name)`" as in progress so we can change its results to account for unreliable tests."
|
||||
Invoke-RestMethod -Uri "$($testRun.url)?api-version=5.0" -Method Patch -Body (ConvertTo-Json @{ "state" = "InProgress" }) -Headers $azureDevOpsRestApiHeaders -ContentType "application/json" | Out-Null
|
||||
|
||||
Write-Host "Retrieving test results..."
|
||||
$testResults = Invoke-RestMethod -Uri $testRunResultsUri -Method Get -Headers $azureDevOpsRestApiHeaders
|
||||
|
||||
foreach ($testResult in $testResults.value)
|
||||
{
|
||||
$testNeedsSubResultProcessing = $false
|
||||
if ($testResult.outcome -eq "NotExecuted")
|
||||
{
|
||||
$testNeedsSubResultProcessing = $true
|
||||
}
|
||||
elseif($testResult.outcome -eq "Failed")
|
||||
{
|
||||
$testNeedsSubResultProcessing = $testResult.errorMessage -like "*_subresults.json*"
|
||||
}
|
||||
|
||||
if ($testNeedsSubResultProcessing)
|
||||
{
|
||||
Write-Host " Test $($testResult.testCaseTitle) was detected as unreliable. Updating..."
|
||||
|
||||
# The errorMessage field contains a link to the JSON-encoded rerun result data.
|
||||
$rerunResults = ConvertFrom-Json (New-Object System.Net.WebClient).DownloadString($testResult.errorMessage)
|
||||
[System.Collections.Generic.List[System.Collections.Hashtable]]$rerunDataList = @()
|
||||
$attemptCount = 0
|
||||
$passCount = 0
|
||||
$totalDuration = 0
|
||||
|
||||
foreach ($rerun in $rerunResults.results)
|
||||
{
|
||||
$rerunData = @{
|
||||
"displayName" = "Attempt #$($attemptCount + 1) - $($testResult.testCaseTitle)";
|
||||
"durationInMs" = $rerun.duration;
|
||||
"outcome" = $rerun.outcome;
|
||||
}
|
||||
|
||||
if ($rerun.outcome -eq "Passed")
|
||||
{
|
||||
$passCount++
|
||||
}
|
||||
|
||||
if ($attemptCount -gt 0)
|
||||
{
|
||||
$rerunData["sequenceId"] = $attemptCount
|
||||
}
|
||||
|
||||
Write-Host " Attempt #$($attemptCount + 1): $($rerun.outcome)"
|
||||
|
||||
if ($rerun.outcome -ne "Passed")
|
||||
{
|
||||
$screenshots = "$($rerunResults.blobPrefix)/$($rerun.screenshots -join @"
|
||||
$($rerunResults.blobSuffix)
|
||||
$($rerunResults.blobPrefix)
|
||||
"@)$($rerunResults.blobSuffix)"
|
||||
|
||||
# We subtract 1 from the error index because we added 1 so we could use 0
|
||||
# as a default value not injected into the JSON in order to keep its size down.
|
||||
# We did this because there's a maximum size enforced for the errorMessage parameter
|
||||
# in the Azure DevOps REST API.
|
||||
$fullErrorMessage = @"
|
||||
Log: $($rerunResults.blobPrefix)/$($rerun.log)$($rerunResults.blobSuffix)
|
||||
|
||||
Screenshots:
|
||||
$screenshots
|
||||
|
||||
Error log:
|
||||
$($rerunResults.errors[$rerun.errorIndex - 1])
|
||||
"@
|
||||
|
||||
$rerunData["errorMessage"] = $fullErrorMessage
|
||||
}
|
||||
|
||||
$attemptCount++
|
||||
$totalDuration += $rerun.duration
|
||||
$rerunDataList.Add($rerunData)
|
||||
}
|
||||
|
||||
$overallOutcome = "Warning"
|
||||
|
||||
if ($attemptCount -eq 2)
|
||||
{
|
||||
Write-Host " Test $($testResult.testCaseTitle) passed on the immediate rerun, so we'll mark it as unreliable."
|
||||
}
|
||||
elseif ($passCount -gt $RerunPassesRequiredToAvoidFailure)
|
||||
{
|
||||
Write-Host " Test $($testResult.testCaseTitle) passed on $passCount of $attemptCount attempts, which is greater than or equal to the $RerunPassesRequiredToAvoidFailure passes required to avoid being marked as failed. Marking as unreliable."
|
||||
}
|
||||
else
|
||||
{
|
||||
Write-Host " Test $($testResult.testCaseTitle) passed on only $passCount of $attemptCount attempts, which is less than the $RerunPassesRequiredToAvoidFailure passes required to avoid being marked as failed. Marking as failed."
|
||||
$overallOutcome = "Failed"
|
||||
}
|
||||
|
||||
$updateBody = ConvertTo-Json @(@{ "id" = $testResult.id; "outcome" = $overallOutcome; "errorMessage" = " "; "durationInMs" = $totalDuration; "subResults" = $rerunDataList; "resultGroupType" = "rerun" }) -Depth 5
|
||||
Invoke-RestMethod -Uri $testRunResultsUri -Method Patch -Headers $azureDevOpsRestApiHeaders -Body $updateBody -ContentType "application/json" | Out-Null
|
||||
}
|
||||
}
|
||||
|
||||
Write-Host "Finished updates. Re-marking test run `"$($testRun.name)`" as completed."
|
||||
Invoke-RestMethod -Uri "$($testRun.url)?api-version=5.0" -Method Patch -Body (ConvertTo-Json @{ "state" = "Completed" }) -Headers $azureDevOpsRestApiHeaders -ContentType "application/json" | Out-Null
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"msbuild-sdks": {
|
||||
"Microsoft.DotNet.Helix.Sdk": "5.0.0-beta.20277.5"
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
<?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.58.210305002" 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" />
|
||||
</packages>
|
||||
@@ -1,32 +0,0 @@
|
||||
This directory contains code and configuration files to run WinUI tests in Helix.
|
||||
|
||||
Helix is a cloud hosted test execution environment which is accessed via the Arcade SDK.
|
||||
More details:
|
||||
* [Arcade](https://github.com/dotnet/arcade)
|
||||
* [Helix](https://github.com/dotnet/arcade/tree/master/src/Microsoft.DotNet.Helix/Sdk)
|
||||
|
||||
WinUI tests are scheduled in Helix by the Azure DevOps Pipeline: [RunHelixTests.yml](../RunHelixTests.yml).
|
||||
|
||||
The workflow is as follows:
|
||||
1. NuGet Restore is called on the packages.config in this directory. This downloads any runtime dependencies
|
||||
that are needed to run tests.
|
||||
2. PrepareHelixPayload.ps1 is called. This copies the necessary files from various locations into a Helix
|
||||
payload directory. This directory is what will get sent to the Helix machines.
|
||||
3. RunTestsInHelix.proj is executed. This proj has a dependency on
|
||||
[Microsoft.DotNet.Helix.Sdk](https://github.com/dotnet/arcade/tree/master/src/Microsoft.DotNet.Helix/Sdk)
|
||||
which it uses to publish the Helix payload directory and to schedule the Helix Work Items. The WinUI tests
|
||||
are parallelized into multiple Helix Work Items.
|
||||
4. Each Helix Work Item calls [runtests.cmd](runtests.cmd) with a specific query to pass to
|
||||
[TAEF](https://docs.microsoft.com/en-us/windows-hardware/drivers/taef/) which runs the tests.
|
||||
5. If a test is detected to have failed, we run it again, first once, then eight more times if it fails again.
|
||||
If it fails all ten times, we report the test as failed; otherwise, we report it as unreliable,
|
||||
which will show up as a warning, but which will not fail the build. When a test is reported as unreliable,
|
||||
we include the results for each individual run via a JSON string in the original test's errorMessage field.
|
||||
6. TAEF produces logs in WTT format. Helix is able to process logs in XUnit format. We run
|
||||
[ConvertWttLogToXUnit.ps1](ConvertWttLogToXUnit.ps1) to convert the logs into the necessary format.
|
||||
7. RunTestsInHelix.proj has EnableAzurePipelinesReporter set to true. This allows the XUnit formatted test
|
||||
results to be reported back to the Azure DevOps Pipeline.
|
||||
8. We process unreliable tests once all tests have been reported by reading the JSON string from the
|
||||
errorMessage field and calling the Azure DevOps REST API to modify the unreliable tests to have sub-results
|
||||
added to the test and to mark the test as "warning", which will enable people to see exactly how the test
|
||||
failed in runs where it did.
|
||||
@@ -1,105 +0,0 @@
|
||||
setlocal ENABLEDELAYEDEXPANSION
|
||||
|
||||
echo %TIME%
|
||||
|
||||
robocopy %HELIX_CORRELATION_PAYLOAD% . /s /NP > NUL
|
||||
|
||||
echo %TIME%
|
||||
|
||||
reg add HKLM\Software\Policies\Microsoft\Windows\Appx /v AllowAllTrustedApps /t REG_DWORD /d 1 /f
|
||||
|
||||
rem enable dump collection for our test apps:
|
||||
rem note, this script is run from a 32-bit cmd, but we need to set the native reg-key
|
||||
FOR %%A IN (TestHostApp.exe,te.exe,te.processhost.exe,conhost.exe,OpenConsole.exe,WindowsTerminal.exe) DO (
|
||||
%systemroot%\sysnative\cmd.exe /c reg add "HKLM\Software\Microsoft\Windows\Windows Error Reporting\LocalDumps\%%A" /v DumpFolder /t REG_EXPAND_SZ /d %HELIX_DUMP_FOLDER% /f
|
||||
%systemroot%\sysnative\cmd.exe /c reg add "HKLM\Software\Microsoft\Windows\Windows Error Reporting\LocalDumps\%%A" /v DumpType /t REG_DWORD /d 2 /f
|
||||
%systemroot%\sysnative\cmd.exe /c reg add "HKLM\Software\Microsoft\Windows\Windows Error Reporting\LocalDumps\%%A" /v DumpCount /t REG_DWORD /d 10 /f
|
||||
)
|
||||
|
||||
echo %TIME%
|
||||
|
||||
:: kill dhandler, which is a tool designed to handle unexpected windows appearing. But since our tests are
|
||||
:: expected to show UI we don't want it running.
|
||||
taskkill -f -im dhandler.exe
|
||||
|
||||
echo %TIME%
|
||||
powershell -ExecutionPolicy Bypass .\EnsureMachineState.ps1
|
||||
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 testBinaries=
|
||||
for %%B in (%testBinaryCandidates%) do (
|
||||
if exist %%B (
|
||||
set "testBinaries=!testBinaries! %%B"
|
||||
)
|
||||
)
|
||||
|
||||
echo %TIME%
|
||||
te.exe %testBinaries% /enablewttlogging /unicodeOutput:false /sessionTimeout:0:15 /testtimeout:0:10 /screenCaptureOnError %*
|
||||
echo %TIME%
|
||||
|
||||
powershell -ExecutionPolicy Bypass Get-Process
|
||||
|
||||
move te.wtl te_original.wtl
|
||||
|
||||
copy /y te_original.wtl %HELIX_WORKITEM_UPLOAD_ROOT%
|
||||
copy /y WexLogFileOutput\*.jpg %HELIX_WORKITEM_UPLOAD_ROOT%
|
||||
copy /y *.pgc %HELIX_WORKITEM_UPLOAD_ROOT%
|
||||
|
||||
set FailedTestQuery=
|
||||
for /F "tokens=* usebackq" %%I IN (`powershell -ExecutionPolicy Bypass .\OutputFailedTestQuery.ps1 te_original.wtl`) DO (
|
||||
set FailedTestQuery=%%I
|
||||
)
|
||||
|
||||
rem The first time, we'll just re-run failed tests once. In many cases, tests fail very rarely, such that
|
||||
rem a single re-run will be sufficient to detect many unreliable tests.
|
||||
if "%FailedTestQuery%" == "" goto :SkipReruns
|
||||
|
||||
echo %TIME%
|
||||
te.exe %testBinaries% /enablewttlogging /unicodeOutput:false /sessionTimeout:0:15 /testtimeout:0:10 /screenCaptureOnError /select:"%FailedTestQuery%"
|
||||
echo %TIME%
|
||||
|
||||
move te.wtl te_rerun.wtl
|
||||
|
||||
copy /y te_rerun.wtl %HELIX_WORKITEM_UPLOAD_ROOT%
|
||||
copy /y WexLogFileOutput\*.jpg %HELIX_WORKITEM_UPLOAD_ROOT%
|
||||
|
||||
rem If there are still failing tests remaining, we'll run them eight more times, so they'll have been run a total of ten times.
|
||||
rem If any tests fail all ten times, we can be pretty confident that these are actual test failures rather than unreliable tests.
|
||||
if not exist te_rerun.wtl goto :SkipReruns
|
||||
|
||||
set FailedTestQuery=
|
||||
for /F "tokens=* usebackq" %%I IN (`powershell -ExecutionPolicy Bypass .\OutputFailedTestQuery.ps1 te_rerun.wtl`) DO (
|
||||
set FailedTestQuery=%%I
|
||||
)
|
||||
|
||||
if "%FailedTestQuery%" == "" goto :SkipReruns
|
||||
|
||||
echo %TIME%
|
||||
te.exe %testBinaries% /enablewttlogging /unicodeOutput:false /sessionTimeout:0:15 /testtimeout:0:10 /screenCaptureOnError /testmode:Loop /LoopTest:8 /select:"%FailedTestQuery%"
|
||||
echo %TIME%
|
||||
|
||||
powershell -ExecutionPolicy Bypass Get-Process
|
||||
|
||||
move te.wtl te_rerun_multiple.wtl
|
||||
|
||||
copy /y te_rerun_multiple.wtl %HELIX_WORKITEM_UPLOAD_ROOT%
|
||||
copy /y WexLogFileOutput\*.jpg %HELIX_WORKITEM_UPLOAD_ROOT%
|
||||
powershell -ExecutionPolicy Bypass .\CopyVisualTreeVerificationFiles.ps1
|
||||
|
||||
:SkipReruns
|
||||
|
||||
powershell -ExecutionPolicy Bypass Get-Process
|
||||
|
||||
echo %TIME%
|
||||
powershell -ExecutionPolicy Bypass .\OutputSubResultsJsonFiles.ps1 te_original.wtl te_rerun.wtl te_rerun_multiple.wtl %testnameprefix%
|
||||
powershell -ExecutionPolicy Bypass .\ConvertWttLogToXUnit.ps1 te_original.wtl te_rerun.wtl te_rerun_multiple.wtl testResults.xml %testnameprefix%
|
||||
echo %TIME%
|
||||
|
||||
copy /y *_subresults.json %HELIX_WORKITEM_UPLOAD_ROOT%
|
||||
|
||||
type testResults.xml
|
||||
|
||||
echo %TIME%
|
||||
5
build/config/SignConfig.NuGet.xml
Normal file
@@ -0,0 +1,5 @@
|
||||
<SignConfigXML>
|
||||
<job platform="" configuration="" dest="__INPATHROOT__" jobname="EngFunSimpleSign" approvers="">
|
||||
<file src="__INPATHROOT__\Microsoft.Terminal*.nupkg" signType="NuGet" />
|
||||
</job>
|
||||
</SignConfigXML>
|
||||
5
build/config/SignConfig.WindowsTerminal.xml
Normal file
@@ -0,0 +1,5 @@
|
||||
<SignConfigXML>
|
||||
<job platform="" configuration="" certSubject="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" jobname="EngFunSimpleSign" approvers="">
|
||||
<file src="__INPATHROOT__\Microsoft.WindowsTerminal*.msixbundle" signType="136020001" />
|
||||
</job>
|
||||
</SignConfigXML>
|
||||
@@ -1,5 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="MUXCustomBuildTasks" version="1.0.48" targetFramework="native" />
|
||||
<package id="Microsoft.Taef" version="10.58.210305002" targetFramework="native" />
|
||||
</packages>
|
||||
@@ -2,8 +2,7 @@ trigger:
|
||||
batch: true
|
||||
branches:
|
||||
include:
|
||||
- main
|
||||
- feature/*
|
||||
- master
|
||||
paths:
|
||||
exclude:
|
||||
- doc/*
|
||||
@@ -13,8 +12,7 @@ trigger:
|
||||
pr:
|
||||
branches:
|
||||
include:
|
||||
- main
|
||||
- feature/*
|
||||
- master
|
||||
paths:
|
||||
exclude:
|
||||
- doc/*
|
||||
|
||||
@@ -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'
|
||||
@@ -8,9 +8,7 @@ jobs:
|
||||
variables:
|
||||
BuildConfiguration: AuditMode
|
||||
BuildPlatform: ${{ parameters.platform }}
|
||||
pool: "windevbuildagents"
|
||||
# The public pool is also an option!
|
||||
# pool: { vmImage: windows-2019 }
|
||||
pool: { vmImage: windows-2019 }
|
||||
|
||||
steps:
|
||||
- checkout: self
|
||||
|
||||
@@ -2,8 +2,6 @@ parameters:
|
||||
configuration: 'Release'
|
||||
platform: ''
|
||||
additionalBuildArguments: ''
|
||||
minimumExpectedTestsExecutedCount: 10 # Sanity check for minimum expected tests to be reported
|
||||
rerunPassesRequiredToAvoidFailure: 5
|
||||
|
||||
jobs:
|
||||
- job: Build${{ parameters.platform }}${{ parameters.configuration }}
|
||||
@@ -11,33 +9,9 @@ jobs:
|
||||
variables:
|
||||
BuildConfiguration: ${{ parameters.configuration }}
|
||||
BuildPlatform: ${{ parameters.platform }}
|
||||
pool: "windevbuildagents"
|
||||
# The public pool is also an option!
|
||||
# pool: { vmImage: windows-2019 }
|
||||
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'
|
||||
rerunPassesRequiredToAvoidFailure: ${{ parameters.rerunPassesRequiredToAvoidFailure }}
|
||||
|
||||
- template: helix-processtestresults-job.yml
|
||||
parameters:
|
||||
dependsOn:
|
||||
- RunTestsInHelix
|
||||
condition: and(succeededOrFailed(), and(eq('${{ parameters.platform }}', 'x64'), not(eq(variables['Build.Reason'], 'PullRequest'))))
|
||||
rerunPassesRequiredToAvoidFailure: ${{ parameters.rerunPassesRequiredToAvoidFailure }}
|
||||
minimumExpectedTestsExecutedCount: ${{ parameters.minimumExpectedTestsExecutedCount }}
|
||||
@@ -9,7 +9,6 @@ jobs:
|
||||
variables:
|
||||
BuildConfiguration: ${{ parameters.configuration }}
|
||||
BuildPlatform: ${{ parameters.platform }}
|
||||
PGOBuildMode: 'Optimize'
|
||||
|
||||
pool:
|
||||
name: Package ES Lab E
|
||||
|
||||
@@ -1,51 +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: "windevbuildagents"
|
||||
# The public pool is also an option!
|
||||
# pool: { vmImage: windows-2019 }
|
||||
|
||||
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 }}
|
||||
@@ -1,6 +1,5 @@
|
||||
parameters:
|
||||
additionalBuildArguments: ''
|
||||
testLogPath: '$(Build.BinariesDirectory)\$(BuildPlatform)\$(BuildConfiguration)\testsOnBuildMachine.wtl'
|
||||
|
||||
steps:
|
||||
- checkout: self
|
||||
@@ -8,14 +7,17 @@ steps:
|
||||
clean: true
|
||||
|
||||
- task: NuGetToolInstaller@0
|
||||
displayName: 'Use NuGet 5.2.0'
|
||||
displayName: Ensure NuGet 4.8.1
|
||||
inputs:
|
||||
versionSpec: 5.2.0
|
||||
versionSpec: 4.8.1
|
||||
|
||||
- task: VisualStudioTestPlatformInstaller@1
|
||||
displayName: Ensure VSTest Platform
|
||||
|
||||
# In the Microsoft Azure DevOps tenant, NuGetCommand is ambiguous.
|
||||
# This should be `task: NuGetCommand@2`
|
||||
- task: 333b11bd-d341-40d9-afcf-b32d5ce6f23b@2
|
||||
displayName: Restore NuGet packages for solution
|
||||
displayName: Restore NuGet packages
|
||||
inputs:
|
||||
command: restore
|
||||
feedsToUse: config
|
||||
@@ -23,38 +25,6 @@ steps:
|
||||
restoreSolution: OpenConsole.sln
|
||||
restoreDirectory: '$(Build.SourcesDirectory)\packages'
|
||||
|
||||
- task: 333b11bd-d341-40d9-afcf-b32d5ce6f23b@2
|
||||
displayName: Restore NuGet packages for extraneous build actions
|
||||
inputs:
|
||||
command: restore
|
||||
feedsToUse: config
|
||||
configPath: NuGet.config
|
||||
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 +38,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 +46,6 @@ steps:
|
||||
|
||||
- task: powershell@2
|
||||
displayName: 'Source Index PDBs'
|
||||
condition: ne(variables['PGOBuildMode'], 'Instrument')
|
||||
inputs:
|
||||
targetType: filePath
|
||||
filePath: build\scripts\Index-Pdbs.ps1
|
||||
@@ -95,66 +61,21 @@ 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')))
|
||||
arguments: -MatchPattern '*unit.test*.dll' -Platform '$(RationalizedBuildPlatform)' -Configuration '$(BuildConfiguration)'
|
||||
condition: and(succeeded(), or(eq(variables['BuildPlatform'], 'x64'), eq(variables['BuildPlatform'], 'x86')))
|
||||
|
||||
- task: PowerShell@2
|
||||
displayName: 'Run Feature Tests (x64 only)'
|
||||
inputs:
|
||||
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'))
|
||||
|
||||
- task: PowerShell@2
|
||||
displayName: 'Convert Test Logs from WTL to xUnit format'
|
||||
inputs:
|
||||
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')))
|
||||
|
||||
- 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'
|
||||
#searchFolder: '$(System.DefaultWorkingDirectory)' # Optional
|
||||
#mergeTestResults: false # Optional
|
||||
#failTaskOnFailedTests: false # Optional
|
||||
testRunTitle: 'On Build Machine Tests' # Optional
|
||||
buildPlatform: $(BuildPlatform) # Optional
|
||||
buildConfiguration: $(BuildConfiguration) # Optional
|
||||
#publishRunAttachments: true # Optional
|
||||
|
||||
- task: CopyFiles@2
|
||||
displayName: 'Copy result logs to Artifacts'
|
||||
inputs:
|
||||
Contents: |
|
||||
**/*.wtl
|
||||
**/*onBuildMachineResults.xml
|
||||
${{ parameters.testLogPath }}
|
||||
TargetFolder: '$(Build.ArtifactStagingDirectory)/$(BuildConfiguration)/$(BuildPlatform)/test'
|
||||
OverWrite: true
|
||||
flattenFolders: true
|
||||
arguments: -MatchPattern '*feature.test*.dll' -Platform '$(RationalizedBuildPlatform)' -Configuration '$(BuildConfiguration)'
|
||||
condition: and(succeeded(), eq(variables['BuildPlatform'], 'x64'))
|
||||
|
||||
- task: CopyFiles@2
|
||||
displayName: 'Copy *.appx/*.msix to Artifacts (Non-PR builds only)'
|
||||
@@ -167,47 +88,11 @@ steps:
|
||||
TargetFolder: '$(Build.ArtifactStagingDirectory)/appx'
|
||||
OverWrite: true
|
||||
flattenFolders: true
|
||||
condition: succeeded()
|
||||
|
||||
- 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
|
||||
**/Microsoft.VCLibs.*.appx
|
||||
**/TestHostApp/*.exe
|
||||
**/TestHostApp/*.dll
|
||||
**/TestHostApp/*.xml
|
||||
!**/*.pdb
|
||||
!**/*.ipdb
|
||||
!**/*.obj
|
||||
!**/*.pch
|
||||
TargetFolder: '$(Build.ArtifactStagingDirectory)/$(BuildConfiguration)/$(BuildPlatform)/test'
|
||||
OverWrite: true
|
||||
flattenFolders: true
|
||||
condition: succeeded()
|
||||
condition: and(succeeded(), ne(variables['Build.Reason'], 'PullRequest'))
|
||||
|
||||
- task: PublishBuildArtifacts@1
|
||||
displayName: 'Publish All Build Artifacts'
|
||||
displayName: 'Publish Artifact (appx) (Non-PR builds only)'
|
||||
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'))
|
||||
PathtoPublish: '$(Build.ArtifactStagingDirectory)/appx'
|
||||
ArtifactName: 'appx-$(BuildConfiguration)'
|
||||
condition: and(succeeded(), ne(variables['Build.Reason'], 'PullRequest'))
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
parameters:
|
||||
condition: ''
|
||||
testFilePath: ''
|
||||
outputProjFileName: ''
|
||||
testSuite: ''
|
||||
taefQuery: ''
|
||||
|
||||
steps:
|
||||
- task: powershell@2
|
||||
displayName: 'Create ${{ parameters.outputProjFileName }}'
|
||||
condition: ${{ parameters.condition }}
|
||||
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.58.210305002\build\Binaries\x86' -TaefQuery '${{ parameters.taefQuery }}'
|
||||
@@ -1,68 +0,0 @@
|
||||
parameters:
|
||||
condition: 'succeededOrFailed()'
|
||||
dependsOn: ''
|
||||
rerunPassesRequiredToAvoidFailure: 5
|
||||
minimumExpectedTestsExecutedCount: 10
|
||||
checkJobAttempt: false
|
||||
pgoArtifact: ''
|
||||
|
||||
jobs:
|
||||
- job: ProcessTestResults
|
||||
condition: ${{ parameters.condition }}
|
||||
dependsOn: ${{ parameters.dependsOn }}
|
||||
pool:
|
||||
vmImage: 'windows-2019'
|
||||
timeoutInMinutes: 120
|
||||
variables:
|
||||
helixOutputFolder: $(Build.SourcesDirectory)\HelixOutput
|
||||
|
||||
steps:
|
||||
- task: powershell@2
|
||||
displayName: 'UpdateUnreliableTests.ps1'
|
||||
condition: succeededOrFailed()
|
||||
env:
|
||||
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
|
||||
inputs:
|
||||
targetType: filePath
|
||||
filePath: build\Helix\UpdateUnreliableTests.ps1
|
||||
arguments: -RerunPassesRequiredToAvoidFailure '${{ parameters.rerunPassesRequiredToAvoidFailure }}'
|
||||
|
||||
- task: powershell@2
|
||||
displayName: 'OutputTestResults.ps1'
|
||||
condition: succeededOrFailed()
|
||||
env:
|
||||
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
|
||||
inputs:
|
||||
targetType: filePath
|
||||
filePath: build\Helix\OutputTestResults.ps1
|
||||
arguments: -MinimumExpectedTestsExecutedCount '${{ parameters.minimumExpectedTestsExecutedCount }}' -CheckJobAttempt $${{ parameters.checkJobAttempt }}
|
||||
|
||||
- task: powershell@2
|
||||
displayName: 'ProcessHelixFiles.ps1'
|
||||
condition: succeededOrFailed()
|
||||
env:
|
||||
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
|
||||
HelixAccessToken: $(HelixApiAccessToken)
|
||||
inputs:
|
||||
targetType: filePath
|
||||
filePath: build\Helix\ProcessHelixFiles.ps1
|
||||
arguments: -OutputFolder '$(helixOutputFolder)'
|
||||
|
||||
- ${{if ne(parameters.pgoArtifact, '') }}:
|
||||
- script: move /y $(helixOutputFolder)\PGO $(Build.ArtifactStagingDirectory)
|
||||
displayName: 'Move pgc files to PGO artifact'
|
||||
|
||||
- task: PublishBuildArtifacts@1
|
||||
displayName: 'Publish Helix files'
|
||||
condition: succeededOrFailed()
|
||||
inputs:
|
||||
PathtoPublish: $(helixOutputFolder)
|
||||
artifactName: drop
|
||||
|
||||
- ${{if ne(parameters.pgoArtifact, '') }}:
|
||||
- task: PublishBuildArtifacts@1
|
||||
displayName: 'Publish pgc files'
|
||||
condition: succeededOrFailed()
|
||||
inputs:
|
||||
PathtoPublish: $(Build.ArtifactStagingDirectory)\PGO\Release
|
||||
artifactName: ${{ parameters.pgoArtifact }}
|
||||
@@ -1,150 +0,0 @@
|
||||
parameters:
|
||||
name: 'RunTestsInHelix'
|
||||
dependsOn: ''
|
||||
condition: ''
|
||||
testSuite: ''
|
||||
# If a Pipeline runs this template more than once, this parameter should be unique per build flavor to differentiate the
|
||||
# the different test runs:
|
||||
helixType: 'test/devtest'
|
||||
artifactName: 'drop'
|
||||
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'
|
||||
|
||||
jobs:
|
||||
- job: ${{ parameters.name }}
|
||||
dependsOn: ${{ parameters.dependsOn }}
|
||||
condition: ${{ parameters.condition }}
|
||||
pool:
|
||||
vmImage: 'windows-2019'
|
||||
timeoutInMinutes: 120
|
||||
strategy:
|
||||
maxParallel: ${{ parameters.maxParallel }}
|
||||
variables:
|
||||
buildConfiguration: ${{ parameters.configuration }}
|
||||
buildPlatform: ${{ parameters.platform }}
|
||||
openHelixTargetQueues: ${{ parameters.openHelixTargetQueues }}
|
||||
artifactsDir: $(Build.SourcesDirectory)\Artifacts
|
||||
taefPath: $(Build.SourcesDirectory)\build\Helix\packages\Microsoft.Taef.10.58.210305002\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}}'
|
||||
|
||||
|
||||
steps:
|
||||
- task: CmdLine@1
|
||||
displayName: 'Display build machine environment variables'
|
||||
inputs:
|
||||
filename: 'set'
|
||||
|
||||
- task: NuGetToolInstaller@0
|
||||
displayName: 'Use NuGet 5.2.0'
|
||||
inputs:
|
||||
versionSpec: 5.2.0
|
||||
|
||||
- task: 333b11bd-d341-40d9-afcf-b32d5ce6f23b@2
|
||||
displayName: 'NuGet restore build/Helix/packages.config'
|
||||
inputs:
|
||||
restoreSolution: build/Helix/packages.config
|
||||
feedsToUse: config
|
||||
nugetConfigPath: nuget.config
|
||||
restoreDirectory: packages
|
||||
|
||||
- task: DownloadBuildArtifacts@0
|
||||
condition:
|
||||
and(succeeded(),eq(variables['useBuildOutputFromBuildId'],''))
|
||||
inputs:
|
||||
artifactName: ${{ parameters.artifactName }}
|
||||
downloadPath: '$(artifactsDir)'
|
||||
|
||||
- task: DownloadBuildArtifacts@0
|
||||
condition:
|
||||
and(succeeded(),ne(variables['useBuildOutputFromBuildId'],''))
|
||||
inputs:
|
||||
buildType: specific
|
||||
buildVersionToDownload: specific
|
||||
project: $(System.TeamProjectId)
|
||||
pipeline: ${{ parameters.useBuildOutputFromPipeline }}
|
||||
buildId: $(useBuildOutputFromBuildId)
|
||||
artifactName: ${{ parameters.artifactName }}
|
||||
downloadPath: '$(artifactsDir)'
|
||||
|
||||
- task: CmdLine@1
|
||||
displayName: 'Display Artifact Directory payload contents'
|
||||
inputs:
|
||||
filename: 'dir'
|
||||
arguments: '/s $(artifactsDir)'
|
||||
|
||||
- task: powershell@2
|
||||
displayName: 'PrepareHelixPayload.ps1'
|
||||
inputs:
|
||||
targetType: filePath
|
||||
filePath: build\Helix\PrepareHelixPayload.ps1
|
||||
arguments: -Platform '$(buildPlatform)' -Configuration '$(buildConfiguration)' -ArtifactName '${{ parameters.artifactName }}'
|
||||
|
||||
- task: CmdLine@1
|
||||
displayName: 'Display Helix payload contents'
|
||||
inputs:
|
||||
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'))
|
||||
testFilePath: '$(artifactsDir)\${{ parameters.artifactName }}\$(buildConfiguration)\$(buildPlatform)\Test\TerminalApp.LocalTests.dll'
|
||||
outputProjFileName: 'RunTestsInHelix-TerminalAppLocalTests.proj'
|
||||
testSuite: '${{ parameters.testSuite }}'
|
||||
taefQuery: ${{ parameters.taefQuery }}
|
||||
|
||||
- template: helix-createprojfile-steps.yml
|
||||
parameters:
|
||||
condition: and(succeeded(),eq('${{ parameters.testSuite }}','DevTestSuite'))
|
||||
testFilePath: '$(artifactsDir)\${{ parameters.artifactName }}\$(buildConfiguration)\$(buildPlatform)\Test\SettingsModel.LocalTests.dll'
|
||||
outputProjFileName: 'RunTestsInHelix-SettingsModelLocalTests.proj'
|
||||
testSuite: '${{ parameters.testSuite }}'
|
||||
taefQuery: ${{ parameters.taefQuery }}
|
||||
|
||||
|
||||
- template: helix-createprojfile-steps.yml
|
||||
parameters:
|
||||
condition: and(succeeded(),eq('${{ parameters.testSuite }}','DevTestSuite'))
|
||||
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:
|
||||
PathtoPublish: $(Build.ArtifactStagingDirectory)
|
||||
artifactName: ${{ parameters.artifactName }}
|
||||
|
||||
- task: DotNetCoreCLI@2
|
||||
displayName: 'Run tests in Helix (open queues)'
|
||||
env:
|
||||
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
|
||||
inputs:
|
||||
command: custom
|
||||
projects: build\Helix\RunTestsInHelix.proj
|
||||
custom: msbuild
|
||||
arguments: '$(helixCommonArgs) /p:IsExternal=true /p:Creator=Terminal /p:HelixTargetQueues=$(openHelixTargetQueues)'
|
||||
|
||||
@@ -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
|
||||
@@ -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 }}
|
||||
@@ -1,18 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<_WTBrandingPreprocessorToken Condition="'$(WindowsTerminalBranding)'=='Preview'">WT_BRANDING_PREVIEW</_WTBrandingPreprocessorToken>
|
||||
<_WTBrandingPreprocessorToken Condition="'$(WindowsTerminalBranding)'=='Release'">WT_BRANDING_RELEASE</_WTBrandingPreprocessorToken>
|
||||
<_WTBrandingPreprocessorToken Condition="'$(_WTBrandingPreprocessorToken)'==''">WT_BRANDING_DEV</_WTBrandingPreprocessorToken>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>$(_WTBrandingPreprocessorToken);%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
|
||||
<ResourceCompile>
|
||||
<PreprocessorDefinitions>$(_WTBrandingPreprocessorToken);%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ResourceCompile>
|
||||
</ItemDefinitionGroup>
|
||||
</Project>
|
||||
@@ -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 "$(SolutionDir)\tools\Generate-FeatureStagingHeader.ps1" -Path "%(FeatureFlagFile.FullPath)" -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>
|
||||
@@ -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)) {
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
[CmdLetBinding()]
|
||||
Param(
|
||||
[Parameter(Mandatory=$true, Position=0)][string]$BuildPlatform,
|
||||
[Parameter(Mandatory=$true, Position=1)][string]$RationalizedPlatform,
|
||||
[Parameter(Mandatory=$true, Position=2)][string]$Configuration
|
||||
)
|
||||
|
||||
|
||||
$i = Get-Item .\packages\MuxCustomBuild*
|
||||
$wtt = Join-Path -Path $i[0].FullName -ChildPath (Join-Path -Path 'tools' -ChildPath (Join-Path -Path $BuildPlatform -ChildPath 'wttlog.dll'))
|
||||
$dest = Join-Path -Path .\bin -ChildPath (Join-Path -Path $RationalizedPlatform -ChildPath ($Configuration))
|
||||
copy $wtt $dest
|
||||
|
||||
|
||||
Exit 0
|
||||
@@ -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
|
||||
|
||||
@@ -2,24 +2,12 @@
|
||||
Param(
|
||||
[Parameter(Mandatory=$true, Position=0)][string]$MatchPattern,
|
||||
[Parameter(Mandatory=$true, Position=1)][string]$Platform,
|
||||
[Parameter(Mandatory=$true, Position=2)][string]$Configuration,
|
||||
[Parameter(Mandatory=$false, Position=3)][string]$LogPath
|
||||
[Parameter(Mandatory=$true, Position=2)][string]$Configuration
|
||||
)
|
||||
|
||||
$testdlls = Get-ChildItem -Path ".\bin\$Platform\$Configuration" -Recurse -Filter $MatchPattern
|
||||
|
||||
|
||||
$args = @();
|
||||
|
||||
if ($LogPath)
|
||||
{
|
||||
$args += '/enablewttlogging';
|
||||
$args += '/appendwttlogging';
|
||||
$args += "/logFile:$LogPath";
|
||||
Write-Host "Wtt Logging Enabled";
|
||||
}
|
||||
|
||||
&".\bin\$Platform\$Configuration\te.exe" $args $testdlls.FullName
|
||||
&".\bin\$Platform\$Configuration\te.exe" $testdlls.FullName
|
||||
|
||||
if ($lastexitcode -Ne 0) { Exit $lastexitcode }
|
||||
|
||||
|
||||
@@ -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"
|
||||
@@ -58,7 +58,7 @@ Try {
|
||||
|
||||
### Check the activatable class entries for a few DLLs we need.
|
||||
$inProcServers = $Manifest.Package.Extensions.Extension.InProcessServer.Path
|
||||
$RequiredInProcServers = ("TerminalApp.dll", "Microsoft.Terminal.Control.dll", "Microsoft.Terminal.Remoting.dll", "Microsoft.Terminal.Settings.Editor.dll", "Microsoft.Terminal.Settings.Model.dll", "TerminalConnection.dll")
|
||||
$RequiredInProcServers = ("TerminalApp.dll", "TerminalControl.dll", "TerminalConnection.dll")
|
||||
|
||||
Write-Verbose "InProc Servers: $inProcServers"
|
||||
|
||||
@@ -101,15 +101,6 @@ Try {
|
||||
Throw "Failed to find cpprest142_2_10.dll -- check the WAP packaging project"
|
||||
}
|
||||
|
||||
If (($null -eq (Get-Item "$AppxPackageRootPath\wtd.exe" -EA:Ignore)) -And
|
||||
($null -eq (Get-Item "$AppxPackageRootPath\wt.exe" -EA:Ignore))) {
|
||||
Throw "Failed to find wt.exe/wtd.exe -- check the WAP packaging project"
|
||||
}
|
||||
|
||||
If ($null -eq (Get-Item "$AppxPackageRootPath\OpenConsole.exe" -EA:Ignore)) {
|
||||
Throw "Failed to find OpenConsole.exe -- check the WAP packaging project"
|
||||
}
|
||||
|
||||
} Finally {
|
||||
Remove-Item -Recurse -Force $AppxPackageRootPath
|
||||
}
|
||||
|
||||
@@ -19,11 +19,9 @@
|
||||
"/.github/",
|
||||
"/samples/",
|
||||
"/res/terminal/",
|
||||
"/res/fonts/",
|
||||
"/doc/specs/",
|
||||
"/doc/cascadia/",
|
||||
"/doc/user-docs/",
|
||||
"/src/tools/MonarchPeasantSample/",
|
||||
"/doc/user-docs/"
|
||||
],
|
||||
"SuffixFilters": [
|
||||
".dbb",
|
||||
@@ -39,7 +37,6 @@
|
||||
".wrn",
|
||||
".rec",
|
||||
".err",
|
||||
"XamlStyler.json",
|
||||
".xlsx"
|
||||
]
|
||||
]
|
||||
}
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
<!-- This file is read by XES, which we use in our Release builds. -->
|
||||
<PropertyGroup Label="Version">
|
||||
<XesUseOneStoreVersioning>true</XesUseOneStoreVersioning>
|
||||
<XesBaseYearForStoreVersion>2021</XesBaseYearForStoreVersion>
|
||||
<XesBaseYearForStoreVersion>2020</XesBaseYearForStoreVersion>
|
||||
<VersionMajor>1</VersionMajor>
|
||||
<VersionMinor>9</VersionMinor>
|
||||
<VersionMinor>2</VersionMinor>
|
||||
<VersionInfoProductName>Windows Terminal</VersionInfoProductName>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
|
||||
2
dep/gsl
BIN
dep/llvm/clang-format.exe
Normal file
@@ -5,13 +5,13 @@
|
||||
`.../console/published/wincon.w` in the OS repo when you submit the PR.
|
||||
The branch won't build without it.
|
||||
* For now, you can update winconp.h with your consumable changes.
|
||||
* Define registry name (ex `CONSOLE_REGISTRY_CURSORCOLOR`)
|
||||
* Add the setting to `CONSOLE_STATE_INFO`
|
||||
* Define the property key ID and the property key itself.
|
||||
* define registry name (ex `CONSOLE_REGISTRY_CURSORCOLOR`)
|
||||
* add the setting to `CONSOLE_STATE_INFO`
|
||||
* define the property key ID and the property key itself
|
||||
- Yes, the large majority of the `DEFINE_PROPERTYKEY` defs are the same, it's only the last byte of the guid that changes
|
||||
|
||||
2. Add matching fields to Settings.hpp
|
||||
- Add getters, setters, the whole drill.
|
||||
- add getters, setters, the whole drill.
|
||||
|
||||
3. Add to the propsheet
|
||||
- We need to add it to *reading and writing* the registry from the propsheet, and *reading* the link from the propsheet. Yes, that's weird, but the propsheet is smart enough to re-use ShortcutSerialization::s_SetLinkValues, but not smart enough to do the same with RegistrySerialization.
|
||||
|
||||
19
doc/Niksa.md
@@ -9,8 +9,6 @@ This document serves as a storage point for those posts.
|
||||
- [Output Processing between "Far East" and "Western"](#fesb)
|
||||
- [Why do we not backport things?](#backport)
|
||||
- [Why can't we have mixed elevated and non-elevated tabs in the Terminal?](#elevation)
|
||||
- [What's the difference between a shell and a terminal?](#shell-vs-terminal)
|
||||
|
||||
|
||||
## <a name="cmd"></a>Why do we avoid changing CMD.exe?
|
||||
`setlocal` doesn't behave the same way as an environment variable. It's a thing that would have to be put in at the top of the batch script that is `somefile.cmd` as one of its first commands to adjust the way that one specific batch file is processed by the `cmd.exe` engine. That's probably not suitable for your needs, but that's the way we have to go.
|
||||
@@ -181,20 +179,3 @@ Other platforms have accepted that risk in preference for user convenience. They
|
||||
|
||||
Original Source: https://github.com/microsoft/terminal/issues/632#issuecomment-519375707
|
||||
|
||||
## <a name="shell-vs-terminal"></a>What's the difference between a shell and a terminal?
|
||||
|
||||
_guest speaker @zadjii-msft_
|
||||
|
||||
I think there might be a bit of a misunderstanding here - there are two different kinds of applications we're talking about here:
|
||||
* shell applications, like `cmd.exe`, `powershell`, `zsh`, etc. These are text-only applications that emit streams of characters. They don't care at all about how they're eventually rendered to the user. These are also sometimes referred to as "commandline client" applications.
|
||||
* terminal applications, like the Windows Terminal, gnome-terminal, xterm, iterm2, hyper. These are graphical applications that can be used to render the output of commandline clients.
|
||||
|
||||
On Windows, if you just run `cmd.exe` directly, the OS will create an instance of `conhost.exe` as the _terminal_ for `cmd.exe`. The same thing happens for `powershell.exe`, the system will creates a new conhost window for any client that's not already connected to a terminal of some sort. This has lead to an enormous amount of confusion for people thinking that a conhost window is actually a "`cmd` window". `cmd` can't have a window, it's just a commandline application. Its window is always some other terminal.
|
||||
|
||||
Any terminal can run any commandline client application. So you can use the Windows Terminal to run whatever shell you want. I use mine for both `cmd` and `powershell`, and also WSL:
|
||||
|
||||

|
||||
|
||||
It's not the Terminal's responsibility to remember the commands executed by a commandline client. That's the responsibility of the _shell_. How would the terminal remember commands executed by something like `emacs` or `vim`? Those are both applications where the user is typing input and hitting enter, like they would at a cmd prompt, but without something that resembles a command history.
|
||||
|
||||
Original Source: https://github.com/microsoft/terminal/issues/6500#issuecomment-670035468
|
||||
|
||||
52
doc/TAEF.md
@@ -1,30 +1,9 @@
|
||||
### TAEF Overview ###
|
||||
|
||||
### TAEF ###
|
||||
TAEF, the Test Authoring and Execution Framework, is used extensively within the Windows organization to test the operating system code in a unified manner for system, driver, and application code. As the console is a Windows OS Component, we strive to continue using the same system such that tests can be ran in a unified manner both externally to Microsoft as well as inside the official OS Build/Test system.
|
||||
|
||||
The [official documentation](https://docs.microsoft.com/en-us/windows-hardware/drivers/taef/) for TAEF describes the basic architecture, usage, and functionality of the test system. It is similar to Visual Studio test, but a bit more comprehensive and flexible.
|
||||
The [official documentation](https://msdn.microsoft.com/en-us/library/windows/hardware/hh439725\(v=vs.85\).aspx) for TAEF describes the basic architecture, usage, and functionality of the test system. It is similar to Visual Studio test, but a bit more comprehensive and flexible.
|
||||
|
||||
### Writing Tests
|
||||
|
||||
You may want to read the section [Authoring Tests in C++](https://docs.microsoft.com/en-us/windows-hardware/drivers/taef/authoring-tests-in-c--) before getting your hands dirty. Note that the quoted header name in `#include "WexTestClass.h"` might be a bit confusing. You are not required to copy TAEF headers into the project folder.
|
||||
|
||||
Use the [TAEF Verify Macros for C++](https://docs.microsoft.com/en-us/windows-hardware/drivers/taef/verify) in your test code to perform verifications.
|
||||
|
||||
### 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.
|
||||
|
||||
> 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.
|
||||
|
||||
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
|
||||
```
|
||||
|
||||
Then you should be able to use `%TAEF%` as an alias of the actual `te.exe`.
|
||||
|
||||
For the purposes of the OpenConsole project, you can run the tests using the `te.exe` that matches the architecture for which the test was built (x86/x64):
|
||||
For the purposes of the console project, you can run the tests using the *TE.exe* that matches the architecture for which the test was build (x86/x64) in the pattern
|
||||
|
||||
te.exe Console.Unit.Tests.dll
|
||||
|
||||
@@ -36,29 +15,6 @@ Limiting the tests to be run is also useful with:
|
||||
|
||||
Any pattern of class/method names can be specified after the */name:* flag with wildcard patterns.
|
||||
|
||||
For any further details on the functionality of the TAEF test runner, please see the [Executing Tests](https://docs.microsoft.com/en-us/windows-hardware/drivers/taef/executing-tests) section in the official documentation. Or run the embedded help with
|
||||
For any further details on the functionality of the TAEF test runner, *TE.exe*, please see the documentation above or run the embedded help with
|
||||
|
||||
te.exe /!
|
||||
|
||||
If you use PowerShell, try the following command:
|
||||
|
||||
```powershell
|
||||
Import-Module .\tools\OpenConsole.psm1
|
||||
Invoke-OpenConsoleTests
|
||||
```
|
||||
|
||||
`Invoke-OpenConsoleTests` supports a number of options, which you can enumerate by running `Invoke-OpenConsoleTests -?`.
|
||||
|
||||
|
||||
### Debugging Tests
|
||||
|
||||
If you want to debug a test, you can do so by using the TAEF /waitForDebugger flag, such as:
|
||||
|
||||
runut *Tests.dll /name:TextBufferTests::TestInsertCharacter /waitForDebugger
|
||||
|
||||
Replace the test name with the one you want to debug. Then, TAEF will begin executing the test and output something like this:
|
||||
|
||||
TAEF: Waiting for debugger - PID <some PID> @ IP <some IP address>
|
||||
|
||||
You can then attach to that PID in your debugger of choice. In Visual Studio, you can use Debug -> Attach To Process, or you could use WinDbg or whatever you want.
|
||||
Once the debugger attaches, the test will execute and your breakpoints will be hit.
|
||||
|
||||
@@ -9,13 +9,13 @@ The primary usages of WIL in our code so far are...
|
||||
|
||||
### Smart Pointers ###
|
||||
|
||||
Inside [wil/resource.h](https://github.com/microsoft/wil/blob/master/include/wil/resource.h) are smart pointer like classes for many Windows OS resources like file handles, socket handles, process handles, and so on. They're of the form `wil::unique_handle` and call the appropriate/matching OS function (like `CloseHandle()` in this case) when they go out of scope.
|
||||
Inside [wil\resource.h](https://github.com/microsoft/wil/blob/master/include/wil/resource.h) are smart pointer like classes for many Windows OS resources like file handles, socket handles, process handles, and so on. They're of the form `wil::unique_handle` and call the appropriate/matching OS function (like `CloseHandle()` in this case) when they go out of scope.
|
||||
|
||||
Another useful item is `wil::make_unique_nothrow()` which is analogous to `std::make_unique` (except without the exception which might help you integrate with existing exception-free code in the console.) This will return a `wistd::unique_ptr` (vs. a `std::unique_ptr`) which can be used in a similar manner.
|
||||
|
||||
### Result Handling ###
|
||||
|
||||
To manage the various types of result codes that come back from Windows APIs, the file [wil/result.h](https://github.com/microsoft/wil/blob/master/include/wil/result.h) provides a wealth of macros that can help.
|
||||
To manage the various types of result codes that come back from Windows APIs, the file [wil\result.h](https://github.com/microsoft/wil/blob/master/include/wil/result.h) provides a wealth of macros that can help.
|
||||
|
||||
As an example, the method `DuplicateHandle()` returns a `BOOL` value that is `FALSE` under failure and would like you to `GetLastError()` from the operating system to find out what the actual result code is. In this circumstance, you could use the macro `RETURN_IF_WIN32_BOOL_FALSE` to wrap the call to `DuplicateHandle()` which would automatically handle this pattern for you and return the `HRESULT` equivalent on failure.
|
||||
|
||||
|
||||
@@ -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/)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -73,12 +67,12 @@ To update the version of a given package, use the following snippet
|
||||
|
||||
where:
|
||||
- `$PackageName` is the name of the package, e.g. Microsoft.UI.Xaml
|
||||
- `$OldVersionNumber` is the version number currently used, e.g. 2.4.0-prerelease.200506002
|
||||
- `$NewVersionNumber` is the version number you want to migrate to, e.g. 2.5.0-prerelease.200812002
|
||||
- `$OldVersionNumber` is the version number currently used, e.g. 2.4.2-prerelease.200604001
|
||||
- `$NewVersionNumber` is the version number you want to migrate to, e.g. 2.4.200117003-prerelease
|
||||
|
||||
Example usage:
|
||||
|
||||
`git grep -z -l Microsoft.UI.Xaml | xargs -0 sed -i -e 's/2.4.0-prerelease.200506002/2.5.0-prerelease.200812002/g'`
|
||||
`git grep -z -l Microsoft.UI.Xaml | xargs -0 sed -i -e 's/2.4.2-prerelease.200604001/2.4.200117003-prerelease/g'`
|
||||
|
||||
## Using .nupkg files instead of downloaded Nuget packages
|
||||
If you want to use .nupkg files instead of the downloaded Nuget package, you can do this with the following steps:
|
||||
|
||||
@@ -1,397 +0,0 @@
|
||||
# Adding Settings to Windows Terminal
|
||||
|
||||
Adding a setting to Windows Terminal is fairly straightforward. This guide serves as a reference on how to add a setting.
|
||||
|
||||
## 1. Terminal Settings Model
|
||||
|
||||
The Terminal Settings Model (`Microsoft.Terminal.Settings.Model`) is responsible for (de)serializing and exposing settings.
|
||||
|
||||
### `GETSET_SETTING` macro
|
||||
|
||||
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
|
||||
|
||||
### Adding a Profile setting
|
||||
|
||||
This tutorial will add `CloseOnExitMode CloseOnExit` as a profile setting.
|
||||
|
||||
1. In `Profile.h`, declare/define the setting:
|
||||
|
||||
```c++
|
||||
GETSET_SETTING(CloseOnExitMode, CloseOnExit, CloseOnExitMode::Graceful)
|
||||
```
|
||||
|
||||
2. In `Profile.idl`, expose the setting via WinRT:
|
||||
|
||||
```c++
|
||||
Boolean HasCloseOnExit();
|
||||
void ClearCloseOnExit();
|
||||
CloseOnExitMode CloseOnExit;
|
||||
```
|
||||
|
||||
3. In `Profile.cpp`, add (de)serialization and copy logic:
|
||||
|
||||
```c++
|
||||
// Top of file:
|
||||
// - Add the serialization key
|
||||
static constexpr std::string_view CloseOnExitKey{ "closeOnExit" };
|
||||
|
||||
// CopySettings() or Copy():
|
||||
// - The setting is exposed in the Settings UI
|
||||
profile->_CloseOnExit = source->_CloseOnExit;
|
||||
|
||||
// LayerJson():
|
||||
// - get the value from the JSON
|
||||
JsonUtils::GetValueForKey(json, CloseOnExitKey, _CloseOnExit);
|
||||
|
||||
// ToJson():
|
||||
// - write the value to the JSON
|
||||
JsonUtils::SetValueForKey(json, CloseOnExitKey, _CloseOnExit);
|
||||
```
|
||||
|
||||
- If the setting is not a primitive type, in `TerminalSettingsSerializationHelpers.h` add (de)serialization logic for the accepted values:
|
||||
|
||||
```c++
|
||||
// For enum values...
|
||||
JSON_ENUM_MAPPER(::winrt::Microsoft::Terminal::Settings::Model::CloseOnExitMode)
|
||||
{
|
||||
JSON_MAPPINGS(3) = {
|
||||
pair_type{ "always", ValueType::Always },
|
||||
pair_type{ "graceful", ValueType::Graceful },
|
||||
pair_type{ "never", ValueType::Never },
|
||||
};
|
||||
};
|
||||
|
||||
// For enum flag values...
|
||||
JSON_FLAG_MAPPER(::winrt::Microsoft::Terminal::TerminalControl::CopyFormat)
|
||||
{
|
||||
JSON_MAPPINGS(5) = {
|
||||
pair_type{ "none", AllClear },
|
||||
pair_type{ "html", ValueType::HTML },
|
||||
pair_type{ "rtf", ValueType::RTF },
|
||||
pair_type{ "all", AllSet },
|
||||
};
|
||||
};
|
||||
|
||||
// NOTE: This is also where you can add functionality for...
|
||||
// - overloaded type support (i.e. accept a bool and an enum)
|
||||
// - custom (de)serialization logic (i.e. coordinates)
|
||||
```
|
||||
|
||||
### Adding a Global setting
|
||||
|
||||
Follow the "adding a Profile setting" instructions above, but do it on the `GlobalAppSettings` files.
|
||||
|
||||
### Adding an Action
|
||||
|
||||
This tutorial will add the `openSettings` action.
|
||||
|
||||
1. In `KeyMapping.idl`, declare the action:
|
||||
|
||||
```c++
|
||||
// Add the action to ShortcutAction
|
||||
enum ShortcutAction
|
||||
{
|
||||
OpenSettings
|
||||
}
|
||||
```
|
||||
|
||||
2. In `ActionAndArgs.cpp`, add serialization logic:
|
||||
|
||||
```c++
|
||||
// Top of file:
|
||||
// - Add the serialization key
|
||||
static constexpr std::string_view OpenSettingsKey{ "openSettings" };
|
||||
|
||||
// ActionKeyNamesMap:
|
||||
// - map the new enum to the json key
|
||||
{ OpenSettingsKey, ShortcutAction::OpenSettings },
|
||||
```
|
||||
|
||||
3. If the action should automatically generate a name when it appears in the Command Palette...
|
||||
```c++
|
||||
// In ActionAndArgs.cpp GenerateName() --> GeneratedActionNames
|
||||
{ ShortcutAction::OpenSettings, RS_(L"OpenSettingsCommandKey") },
|
||||
|
||||
// In Resources.resw for Microsoft.Terminal.Settings.Model.Lib,
|
||||
// add the generated name
|
||||
// NOTE: Visual Studio presents the resw file as a table.
|
||||
// If you choose to edit the file with a text editor,
|
||||
// the code should look something like this...
|
||||
<data name="OpenSettingsCommandKey" xml:space="preserve">
|
||||
<value>Open settings file</value>
|
||||
</data>
|
||||
```
|
||||
|
||||
4. If the action supports arguments...
|
||||
- In `ActionArgs.idl`, declare the arguments
|
||||
```c++
|
||||
[default_interface] runtimeclass OpenSettingsArgs : IActionArgs
|
||||
{
|
||||
// this declares the "target" arg
|
||||
SettingsTarget Target { get; };
|
||||
};
|
||||
```
|
||||
- In `ActionArgs.h`, define the new runtime class
|
||||
```c++
|
||||
struct OpenSettingsArgs : public OpenSettingsArgsT<OpenSettingsArgs>
|
||||
{
|
||||
OpenSettingsArgs() = default;
|
||||
|
||||
// adds a getter/setter for your argument, and defines the json key
|
||||
GETSET_PROPERTY(SettingsTarget, Target, SettingsTarget::SettingsFile);
|
||||
static constexpr std::string_view TargetKey{ "target" };
|
||||
|
||||
public:
|
||||
hstring GenerateName() const;
|
||||
|
||||
bool Equals(const IActionArgs& other)
|
||||
{
|
||||
auto otherAsUs = other.try_as<OpenSettingsArgs>();
|
||||
if (otherAsUs)
|
||||
{
|
||||
return otherAsUs->_Target == _Target;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
static FromJsonResult FromJson(const Json::Value& json)
|
||||
{
|
||||
// LOAD BEARING: Not using make_self here _will_ break you in the future!
|
||||
auto args = winrt::make_self<OpenSettingsArgs>();
|
||||
JsonUtils::GetValueForKey(json, TargetKey, args->_Target);
|
||||
return { *args, {} };
|
||||
}
|
||||
|
||||
IActionArgs Copy() const
|
||||
{
|
||||
auto copy{ winrt::make_self<OpenSettingsArgs>() };
|
||||
copy->_Target = _Target;
|
||||
return *copy;
|
||||
}
|
||||
};
|
||||
```
|
||||
- In `ActionArgs.cpp`, define `GenerateName()`. This is used to automatically generate a name when it appears in the Command Palette.
|
||||
- In `ActionAndArgs.cpp`, add serialization logic:
|
||||
|
||||
```c++
|
||||
// ActionKeyNamesMap --> argParsers
|
||||
{ ShortcutAction::OpenSettings, OpenSettingsArgs::FromJson },
|
||||
```
|
||||
|
||||
### Adding an Action Argument
|
||||
|
||||
Follow step 3 from the "adding an Action" instructions above, but modify the relevant `ActionArgs` files.
|
||||
|
||||
## 2. Setting Functionality
|
||||
|
||||
Now that the Terminal Settings Model is updated, Windows Terminal can read and write to the settings file. This section covers how to add functionality to your newly created setting.
|
||||
|
||||
### App-level settings
|
||||
|
||||
App-level settings are settings that affect the frame of Windows Terminal. Generally, these tend to be global settings. The `TerminalApp` project is responsible for presenting the frame of Windows Terminal. A few files of interest include:
|
||||
- `TerminalPage`: XAML control responsible for the look and feel of Windows Terminal
|
||||
- `AppLogic`: WinRT class responsible for window-related issues (i.e. the titlebar, focus mode, etc...)
|
||||
|
||||
Both have access to a `CascadiaSettings` object, for you to read the loaded setting and update Windows Terminal appropriately.
|
||||
|
||||
### Terminal-level settings
|
||||
|
||||
Terminal-level settings are settings that affect a shell session. Generally, these tend to be profile settings. The `TerminalApp` project is responsible for packaging this settings from the Terminal Settings Model to the terminal instance. There are two kinds of settings here:
|
||||
- `IControlSettings`:
|
||||
- These are settings that affect the `TerminalControl` (a XAML control that hosts a shell session).
|
||||
- Examples include background image customization, interactivity behavior (i.e. selection), acrylic and font customization.
|
||||
- The `TerminalControl` project has access to these settings via a saved `IControlSettings` member.
|
||||
- `ICoreSettings`:
|
||||
- These are settings that affect the `TerminalCore` (a lower level object that interacts with the text buffer).
|
||||
- Examples include initial size, history size, and cursor customization.
|
||||
- The `TerminalCore` project has access to these settings via a saved `ICoreSettings` member.
|
||||
|
||||
`TerminalApp` packages these settings into a `TerminalSettings : IControlSettings, ICoreSettings` object upon creating a new terminal instance. To do so, you must submit the following changes:
|
||||
- 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 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
|
||||
- update `_ApplyGlobalSettings` for global settings
|
||||
- If additional processing is necessary, that would happen here. For example, `backgroundImageAlignment` is stored as a `ConvergedAlignment` in the Terminal Settings Model, but converted into XAML's separate horizontal and vertical alignment enums for packaging.
|
||||
|
||||
### Actions
|
||||
|
||||
Actions are packaged as an `ActionAndArgs` object, then handled in `TerminalApp`. To add functionality for actions...
|
||||
- In the `ShortcutActionDispatch` files, dispatch an event when the action occurs...
|
||||
```c++
|
||||
// ShortcutActionDispatch.idl
|
||||
event Windows.Foundation.TypedEventHandler<ShortcutActionDispatch, Microsoft.Terminal.Settings.Model.ActionEventArgs> OpenSettings;
|
||||
|
||||
// ShortcutActionDispatch.h
|
||||
TYPED_EVENT(OpenSettings, TerminalApp::ShortcutActionDispatch, Microsoft::Terminal::Settings::Model::ActionEventArgs);
|
||||
|
||||
// ShortcutActionDispatch.cpp --> DoAction()
|
||||
// - dispatch the appropriate event
|
||||
case ShortcutAction::OpenSettings:
|
||||
{
|
||||
_OpenSettingsHandlers(*this, eventArgs);
|
||||
break;
|
||||
}
|
||||
```
|
||||
- In `TerminalPage` files, handle the event...
|
||||
```c++
|
||||
// TerminalPage.h
|
||||
// - declare the handler
|
||||
void _HandleOpenSettings(const IInspectable& sender, const Microsoft::Terminal::Settings::Model::ActionEventArgs& args);
|
||||
|
||||
// TerminalPage.cpp --> _RegisterActionCallbacks()
|
||||
// - register the handler
|
||||
_actionDispatch->OpenSettings({ this, &TerminalPage::_HandleOpenSettings });
|
||||
|
||||
// AppActionHandlers.cpp
|
||||
// - direct the function to the right place and call a helper function
|
||||
void TerminalPage::_HandleOpenSettings(const IInspectable& /*sender*/,
|
||||
const ActionEventArgs& args)
|
||||
{
|
||||
// NOTE: this if-statement can be omitted if the action does not support arguments
|
||||
if (const auto& realArgs = args.ActionArgs().try_as<OpenSettingsArgs>())
|
||||
{
|
||||
_LaunchSettings(realArgs.Target());
|
||||
args.Handled(true);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
`AppActionHandlers` vary based on the action you want to perform. A few useful helper functions include:
|
||||
- `_GetFocusedTab()`: retrieves the focused tab
|
||||
- `_GetActiveControl()`: retrieves the active terminal control
|
||||
- `_GetTerminalTabImpl()`: tries to cast the given tab as a `TerminalTab` (a tab that hosts a terminal instance)
|
||||
|
||||
|
||||
## 3. Settings UI
|
||||
|
||||
### Exposing Enum Settings
|
||||
If the new setting supports enums, you need to expose a map of the enum and the respective value in the Terminal Settings Model's `EnumMappings`:
|
||||
|
||||
```c++
|
||||
// EnumMappings.idl
|
||||
static Windows.Foundation.Collections.IMap<String, Microsoft.Terminal.Settings.Model.CloseOnExitMode> CloseOnExitMode { get; };
|
||||
|
||||
// EnumMappings.h
|
||||
static winrt::Windows::Foundation::Collections::IMap<winrt::hstring, CloseOnExitMode> CloseOnExitMode();
|
||||
|
||||
// EnumMappings.cpp
|
||||
// - this macro leverages the json enum mapper in TerminalSettingsSerializationHelper to expose
|
||||
// the mapped values across project boundaries
|
||||
DEFINE_ENUM_MAP(Model::CloseOnExitMode, CloseOnExitMode);
|
||||
```
|
||||
|
||||
### Binding and Localizing the Enum Setting
|
||||
|
||||
Find the page in the Settings UI that the new setting fits best in. In this example, we are adding `LaunchMode`.
|
||||
1. In `Launch.idl`, expose the bindable setting...
|
||||
```c++
|
||||
// Expose the current value for the setting
|
||||
IInspectable CurrentLaunchMode;
|
||||
|
||||
// Expose the list of possible values
|
||||
Windows.Foundation.Collections.IObservableVector<Microsoft.Terminal.Settings.Editor.EnumEntry> LaunchModeList { get; };
|
||||
```
|
||||
|
||||
2. In `Launch.h`, declare the bindable enum setting...
|
||||
```c++
|
||||
// the GETSET_BINDABLE_ENUM_SETTING macro accepts...
|
||||
// - name: the name of the setting
|
||||
// - enumType: the type of the setting
|
||||
// - settingsModelName: how to retrieve the setting (use State() to get access to the settings model)
|
||||
// - settingNameInModel: the name of the setting in the terminal settings model
|
||||
GETSET_BINDABLE_ENUM_SETTING(LaunchMode, Model::LaunchMode, State().Settings().GlobalSettings, LaunchMode);
|
||||
```
|
||||
|
||||
3. In `Launch.cpp`, populate these functions...
|
||||
```c++
|
||||
// Constructor (after InitializeComponent())
|
||||
// the INITIALIZE_BINDABLE_ENUM_SETTING macro accepts...
|
||||
// - name: the name of the setting
|
||||
// - enumMappingsName: the name from the TerminalSettingsModel's EnumMappings
|
||||
// - enumType: the type for the enum
|
||||
// - resourceSectionAndType: prefix for the localization
|
||||
// - resourceProperty: postfix for the localization
|
||||
INITIALIZE_BINDABLE_ENUM_SETTING(LaunchMode, LaunchMode, LaunchMode, L"Globals_LaunchMode", L"Content");
|
||||
```
|
||||
|
||||
4. In `Resources.resw` for Microsoft.Terminal.Settings.Editor, add the localized text to expose each enum value. Use the following format: `<SettingGroup>_<SettingName><EnumValue>.Content`
|
||||
- `SettingGroup`:
|
||||
- `Globals` for global settings
|
||||
- `Profile` for profile settings
|
||||
- `SettingName`:
|
||||
- the Pascal-case format for the setting type (i.e. `LaunchMode` for `"launchMode"`)
|
||||
- `EnumValue`:
|
||||
- the json key for the setting value, but with the first letter capitalized (i.e. `Focus` for `"focus"`)
|
||||
- The resulting resw key should look something like this `Globals_LaunchModeFocus.Content`
|
||||
- This is the text that will be used in your control
|
||||
|
||||
### Updating the UI
|
||||
|
||||
When adding a setting to the UI, make sure you follow the [UWP design guidance](https://docs.microsoft.com/windows/uwp/design/).
|
||||
|
||||
#### Enum Settings
|
||||
|
||||
Now, create a XAML control in the relevant XAML file. Use the following tips and tricks to style everything appropriately:
|
||||
- Wrap the control in a `ContentPresenter` adhering to the `SettingContainerStyle` style
|
||||
- Bind `SelectedItem` to the relevant `Current<Setting>` (i.e. `CurrentLaunchMode`). Ensure it's a TwoWay binding
|
||||
- Bind `ItemsSource` to `<Setting>List` (i.e. `LaunchModeList`)
|
||||
- Set the ItemTemplate to the `Enum<ControlType>Template` (i.e. `EnumRadioButtonTemplate` for radio buttons)
|
||||
- Set the style to the appropriate one in `CommonResources.xaml`
|
||||
|
||||
```xml
|
||||
<!--Launch Mode-->
|
||||
<ContentPresenter Style="{StaticResource SettingContainerStyle}">
|
||||
<muxc:RadioButtons x:Uid="Globals_LaunchMode"
|
||||
SelectedItem="{x:Bind CurrentLaunchMode, Mode="TwoWay"}"
|
||||
ItemsSource="{x:Bind LaunchModeList}"
|
||||
ItemTemplate="{StaticResource EnumRadioButtonTemplate}"
|
||||
Style="{StaticResource RadioButtonsSettingStyle}"/>
|
||||
</ContentPresenter>
|
||||
```
|
||||
|
||||
To add any localized text, add a `x:Uid`, and access the relevant property via the Resources.resw file. For example, `Globals_LaunchMode.Header` sets the header for this control. You can also set the tooltip text like this:
|
||||
`Globals_DefaultProfile.[using:Windows.UI.Xaml.Controls]ToolTipService.ToolTip`.
|
||||
|
||||
#### Non-Enum Settings
|
||||
|
||||
Continue to reference `CommonResources.xaml` for appropriate styling and wrap the control with a similar `ContentPresenter`. However, instead of binding to the `Current<Setting>` and `<Setting>List`, bind directly to the setting via the state. Binding a setting like `altGrAliasing` should look something like this:
|
||||
```xml
|
||||
<!--AltGr Aliasing-->
|
||||
<ContentPresenter Style="{StaticResource SettingContainerStyle}">
|
||||
<CheckBox x:Uid="Profile_AltGrAliasing"
|
||||
IsChecked="{x:Bind State.Profile.AltGrAliasing, Mode=TwoWay}"
|
||||
Style="{StaticResource CheckBoxSettingStyle}"/>
|
||||
</ContentPresenter>
|
||||
```
|
||||
|
||||
#### Profile Settings
|
||||
|
||||
If you are specifically adding a Profile setting, in addition to the steps above, you need to make the setting observable by modifying the `Profiles` files...
|
||||
```c++
|
||||
// Profiles.idl --> ProfileViewModel
|
||||
// - this declares the setting as observable using the type and the name of the setting
|
||||
OBSERVABLE_PROJECTED_SETTING(Microsoft.Terminal.Settings.Model.CloseOnExitMode, CloseOnExit);
|
||||
|
||||
// Profiles.h --> ProfileViewModel
|
||||
// - this defines the setting as observable off of the _profile object
|
||||
OBSERVABLE_PROJECTED_SETTING(_profile, CloseOnExit);
|
||||
|
||||
// Profiles.h --> ProfileViewModel
|
||||
// - if the setting cannot be inherited by another profile (aka missing the Clear() function), use the following macro instead:
|
||||
PERMANENT_OBSERVABLE_PROJECTED_SETTING(_profile, Guid);
|
||||
```
|
||||
|
||||
The `ProfilePageNavigationState` holds a `ProfileViewModel`, which wraps the `Profile` object from the Terminal Settings Model. The `ProfileViewModel` makes all of the profile settings observable.
|
||||
|
||||
### Actions
|
||||
|
||||
Actions are not yet supported in the Settings UI.
|
||||
@@ -8,20 +8,19 @@ return a JSON value coerced into the specified type.
|
||||
When reading into existing storage, it returns a boolean indicating whether that storage was modified.
|
||||
|
||||
If the JSON value cannot be converted to the specified type, an exception will be generated.
|
||||
For non-nullable type conversions (most POD types), `null` is considered to be an invalid type.
|
||||
|
||||
```c++
|
||||
std::string one;
|
||||
std::optional<std::string> two;
|
||||
|
||||
JsonUtils::GetValue(json, one);
|
||||
// one is populated or an exception is thrown.
|
||||
// one is populated or unchanged.
|
||||
|
||||
JsonUtils::GetValue(json, two);
|
||||
// two is populated, nullopt or an exception is thrown
|
||||
// two is populated, nullopt or unchanged
|
||||
|
||||
auto three = JsonUtils::GetValue<std::string>(json);
|
||||
// three is populated or an exception is thrown
|
||||
// three is populated or zero-initialized
|
||||
|
||||
auto four = JsonUtils::GetValue<std::optional<std::string>>(json);
|
||||
// four is populated or nullopt
|
||||
@@ -226,14 +225,14 @@ auto v = JsonUtils::GetValue<int>(json, conv);
|
||||
|
||||
-|json type invalid|json null|valid
|
||||
-|-|-|-
|
||||
`T`|❌ exception|❌ exception|✔ converted
|
||||
`T`|❌ exception|🔵 unchanged|✔ converted
|
||||
`std::optional<T>`|❌ exception|🟨 `nullopt`|✔ converted
|
||||
|
||||
### GetValue<T>() (returning)
|
||||
|
||||
-|json type invalid|json null|valid
|
||||
-|-|-|-
|
||||
`T`|❌ exception|❌ exception|✔ converted
|
||||
`T`|❌ exception|🟨 `T{}` (zero value)|✔ converted
|
||||
`std::optional<T>`|❌ exception|🟨 `nullopt`|✔ converted
|
||||
|
||||
### GetValueForKey(T&) (type-deducing)
|
||||
@@ -243,14 +242,14 @@ a "key not found" state. The remaining three cases are the same.
|
||||
|
||||
val type|key not found|_json type invalid_|_json null_|_valid_
|
||||
-|-|-|-|-
|
||||
`T`|🔵 unchanged|_❌ exception_|_❌ exception_|_✔ converted_
|
||||
`std::optional<T>`|🔵 unchanged|_❌ exception_|_🟨 `nullopt`_|_✔ converted_
|
||||
`T`|🔵 unchanged|_❌ exception_|_🔵 unchanged_|_✔ converted_
|
||||
`std::optional<T>`|_🔵 unchanged_|_❌ exception_|_🟨 `nullopt`_|_✔ converted_
|
||||
|
||||
### GetValueForKey<T>() (return value)
|
||||
|
||||
val type|key not found|_json type invalid_|_json null_|_valid_
|
||||
-|-|-|-|-
|
||||
`T`|🟨 `T{}` (zero value)|_❌ exception_|_❌ exception_|_✔ converted_
|
||||
`T`|🟨 `T{}` (zero value)|_❌ exception_|_🟨 `T{}` (zero value)_|_✔ converted_
|
||||
`std::optional<T>`|🟨 `nullopt`|_❌ exception_|_🟨 `nullopt`_|_✔ converted_
|
||||
|
||||
### Future Direction
|
||||
|
||||
@@ -1 +1,209 @@
|
||||
⚠ This document has moved to [the Customize Settings section of the Windows Terminal documentation](https://docs.microsoft.com/windows/terminal/customize-settings/global-settings).
|
||||
# Settings.json Documentation
|
||||
|
||||
## Globals
|
||||
|
||||
Properties listed below affect the entire window, regardless of the profile settings.
|
||||
|
||||
| Property | Necessity | Type | Default | Description |
|
||||
| -------- | --------- | ---- | ------- | ----------- |
|
||||
| `alwaysShowTabs` | _Required_ | Boolean | `true` | When set to `true`, tabs are always displayed. When set to `false` and `showTabsInTitlebar` is set to `false`, tabs only appear after typing <kbd>Ctrl</kbd> + <kbd>T</kbd>. |
|
||||
| `copyOnSelect` | Optional | Boolean | `false` | When set to `true`, a selection is immediately copied to your clipboard upon creation. When set to `false`, the selection persists and awaits further action. |
|
||||
| `copyFormatting` | Optional | Boolean | `false` | When set to `true`, the color and font formatting of selected text is also copied to your clipboard. When set to `false`, only plain text is copied to your clipboard. |
|
||||
| `defaultProfile` | _Required_ | String | PowerShell guid | Sets the default profile. Opens by typing <kbd>Ctrl</kbd> + <kbd>T</kbd> or by clicking the '+' icon. The guid of the desired default profile is used as the value. |
|
||||
| `initialCols` | _Required_ | Integer | `120` | The number of columns displayed in the window upon first load. |
|
||||
| `initialPosition` | Optional | String | `","` | The position of the top left corner of the window upon first load. On a system with multiple displays, these coordinates are relative to the top left of the primary display. If `launchMode` is set to `"maximized"`, the window will be maximized on the monitor specified by those coordinates. |
|
||||
| `initialRows` | _Required_ | Integer | `30` | The number of rows displayed in the window upon first load. |
|
||||
| `launchMode` | Optional | String | `default` | Defines whether the Terminal will launch as maximized or not. Possible values: `"default"`, `"maximized"` |
|
||||
| `rowsToScroll` | Optional | Integer | `system` | The number of rows to scroll at a time with the mouse wheel. This will override the system setting if the value is not zero or "system". |
|
||||
| `theme` | _Required_ | String | `system` | Sets the theme of the application. Possible values: `"light"`, `"dark"`, `"system"` |
|
||||
| `showTerminalTitleInTitlebar` | _Required_ | Boolean | `true` | When set to `true`, titlebar displays the title of the selected tab. When set to `false`, titlebar displays "Windows Terminal". |
|
||||
| `showTabsInTitlebar` | Optional | Boolean | `true` | When set to `true`, the tabs are moved into the titlebar and the titlebar disappears. When set to `false`, the titlebar sits above the tabs. |
|
||||
| `snapToGridOnResize` | Optional | Boolean | `false` | When set to `true`, the window will snap to the nearest character boundary on resize. When `false`, the window will resize "smoothly" |
|
||||
| `tabWidthMode` | Optional | String | `equal` | Sets the width of the tabs. Possible values: <br><ul><li>`"equal"`: sizes each tab to the same width</li><li>`"titleLength"`: sizes each tab to the length of its title</li><li>`"compact"`: sizes each tab to the length of its title when focused, and shrinks to the size of only the icon when the tab is unfocused.</li></ul> |
|
||||
| `wordDelimiters` | Optional | String | <code> /\()"'-:,.;<>~!@#$%^&*|+=[]{}~?│</code><br>_(`│` is `U+2502 BOX DRAWINGS LIGHT VERTICAL`)_ | Determines the delimiters used in a double click selection. |
|
||||
| `confirmCloseAllTabs` | Optional | Boolean | `true` | When set to `true` closing a window with multiple tabs open WILL require confirmation. When set to `false` closing a window with multiple tabs open WILL NOT require confirmation. |
|
||||
| `startOnUserLogin` | Optional | Boolean | `false` | When set to `true` enables the launch of Windows Terminal at startup. Setting to `false` will disable the startup task entry. Note: if the Windows Terminal startup task entry is disabled either by org policy or by user action this setting will have no effect. |
|
||||
| `disabledProfileSources` | Optional | Array[String] | `[]` | Disables all the dynamic profile generators in this list, preventing them from adding their profiles to the list of profiles on startup. This array can contain any combination of `Windows.Terminal.Wsl`, `Windows.Terminal.Azure`, or `Windows.Terminal.PowershellCore`. For more information, see [UsingJsonSettings.md](https://github.com/microsoft/terminal/blob/master/doc/user-docs/UsingJsonSettings.md#dynamic-profiles) |
|
||||
| `experimental.rendering.forceFullRepaint` | Optional | Boolean | `false` | When set to true, we will redraw the entire screen each frame. When set to false, we will render only the updates to the screen between frames. |
|
||||
| `experimental.rendering.software` | Optional | Boolean | `false` | When set to true, we will use the software renderer (a.k.a. WARP) instead of the hardware one. |
|
||||
|
||||
## Profiles
|
||||
|
||||
Properties listed below are specific to each unique profile.
|
||||
|
||||
| Property | Necessity | Type | Default | Description |
|
||||
| -------- | --------- | ---- | ------- | ----------- |
|
||||
| `guid` | _Required_ | String | | Unique identifier of the profile. Written in registry format: `"{00000000-0000-0000-0000-000000000000}"`. |
|
||||
| `name` | _Required_ | String | | Name of the profile. Displays in the dropdown menu. <br>Additionally, this value will be used 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. This "title" behavior can be overridden by using `tabTitle`. |
|
||||
| `acrylicOpacity` | Optional | Number | `0.5` | When `useAcrylic` is set to `true`, it sets the transparency of the window for the profile. Accepts floating point values from 0-1. |
|
||||
| `antialiasingMode` | Optional | String | `"grayscale"` | Controls how text is antialiased in the renderer. Possible values are "grayscale", "cleartype" and "aliased". Note that changing this setting will require starting a new terminal instance. |
|
||||
| `background` | Optional | String | | Sets the background color of the profile. Overrides `background` set in color scheme if `colorscheme` is set. Uses hex color format: `"#rrggbb"`. |
|
||||
| `backgroundImage` | Optional | String | | Sets the file location of the Image to draw over the window background. |
|
||||
| `backgroundImageAlignment` | Optional | String | `center` | Sets how the background image aligns to the boundaries of the window. Possible values: `"center"`, `"left"`, `"top"`, `"right"`, `"bottom"`, `"topLeft"`, `"topRight"`, `"bottomLeft"`, `"bottomRight"` |
|
||||
| `backgroundImageOpacity` | Optional | Number | `1.0` | Sets the transparency of the background image. Accepts floating point values from 0-1. |
|
||||
| `backgroundImageStretchMode` | Optional | String | `uniformToFill` | Sets how the background image is resized to fill the window. Possible values: `"none"`, `"fill"`, `"uniform"`, `"uniformToFill"` |
|
||||
| `closeOnExit` | Optional | String | `graceful` | Sets how the profile reacts to termination or failure to launch. Possible values: `"graceful"` (close when `exit` is typed or the process exits normally), `"always"` (always close) and `"never"` (never close). `true` and `false` are accepted as synonyms for `"graceful"` and `"never"` respectively. |
|
||||
| `colorScheme` | Optional | String | `Campbell` | Name of the terminal color scheme to use. Color schemes are defined under `schemes`. |
|
||||
| `commandline` | Optional | String | | Executable used in the profile. |
|
||||
| `cursorColor` | Optional | String | | Sets the cursor color of the profile. Overrides `cursorColor` set in color scheme if `colorscheme` is set. Uses hex color format: `"#rrggbb"`. |
|
||||
| `cursorHeight` | Optional | Integer | | Sets the percentage height of the cursor starting from the bottom. Only works when `cursorShape` is set to `"vintage"`. Accepts values from 25-100. |
|
||||
| `cursorShape` | Optional | String | `bar` | Sets the cursor shape for the profile. Possible values: `"vintage"` ( ▃ ), `"bar"` ( ┃ ), `"underscore"` ( ▁ ), `"filledBox"` ( █ ), `"emptyBox"` ( ▯ ) |
|
||||
| `fontFace` | Optional | String | `Cascadia Mono` | Name of the font face used in the profile. We will try to fallback to Consolas if this can't be found or is invalid. |
|
||||
| `fontSize` | Optional | Integer | `12` | Sets the font size. |
|
||||
| `fontWeight` | Optional | String | `normal` | Sets the weight (lightness or heaviness of the strokes) for the given font. Possible values: `"thin"`, `"extra-light"`, `"light"`, `"semi-light"`, `"normal"`, `"medium"`, `"semi-bold"`, `"bold"`, `"extra-bold"`, `"black"`, `"extra-black"`, or the corresponding numeric representation of OpenType font weight. |
|
||||
| `foreground` | Optional | String | | Sets the foreground color of the profile. Overrides `foreground` set in color scheme if `colorscheme` is set. Uses hex color format: `#rgb` or `"#rrggbb"`. |
|
||||
| `hidden` | Optional | Boolean | `false` | If set to true, the profile will not appear in the list of profiles. This can be used to hide default profiles and dynamically generated profiles, while leaving them in your settings file. |
|
||||
| `historySize` | Optional | Integer | `9001` | The number of lines above the ones displayed in the window you can scroll back to. |
|
||||
| `icon` | Optional | String | | Image file location of the icon used in the profile. Displays within the tab and the dropdown menu. |
|
||||
| `padding` | Optional | String | `8, 8, 8, 8` | Sets the padding around the text within the window. Can have three different formats: `"#"` sets the same padding for all sides, `"#, #"` sets the same padding for left-right and top-bottom, and `"#, #, #, #"` sets the padding individually for left, top, right, and bottom. |
|
||||
| `scrollbarState` | Optional | String | `"visible"` | Defines the visibility of the scrollbar. Possible values: `"visible"`, `"hidden"` |
|
||||
| `selectionBackground` | Optional | String | | Sets the selection background color of the profile. Overrides `selectionBackground` set in color scheme if `colorscheme` is set. Uses hex color format: `"#rrggbb"`. |
|
||||
| `snapOnInput` | Optional | Boolean | `true` | When set to `true`, the window will scroll to the command input line when typing. When set to `false`, the window will not scroll when you start typing. |
|
||||
| `altGrAliasing` | Optional | Boolean | `true` | By default Windows treats Ctrl+Alt as an alias for AltGr. When altGrAliasing is set to false, this behavior will be disabled. |
|
||||
| `source` | Optional | String | | Stores the name of the profile generator that originated this profile. _There are no discoverable values for this field._ |
|
||||
| `startingDirectory` | Optional | String | `%USERPROFILE%` | The directory the shell starts in when it is loaded. |
|
||||
| `suppressApplicationTitle` | Optional | Boolean | `false` | When set to `true`, `tabTitle` overrides the default title of the tab and any title change messages from the application will be suppressed. When set to `false`, `tabTitle` behaves as normal. |
|
||||
| `tabTitle` | Optional | String | | If set, will replace the `name` as the title to pass to the shell on startup. Some shells (like `bash`) may choose to ignore this initial value, while others (`cmd`, `powershell`) may use this value over the lifetime of the application. |
|
||||
| `useAcrylic` | Optional | Boolean | `false` | When set to `true`, the window will have an acrylic background. When set to `false`, the window will have a plain, untextured background. The transparency only applies to focused windows due to OS limitation. |
|
||||
| `experimental.retroTerminalEffect` | Optional | Boolean | `false` | When set to `true`, enable retro terminal effects. This is an experimental feature, and its continued existence is not guaranteed. |
|
||||
|
||||
## Schemes
|
||||
|
||||
Properties listed below are specific to each color scheme. [ColorTool](https://github.com/microsoft/terminal/tree/master/src/tools/ColorTool) is a great tool you can use to create and explore new color schemes. All colors use hex color format.
|
||||
|
||||
| Property | Necessity | Type | Description |
|
||||
| -------- | ---- | ----------- | ----------- |
|
||||
| `name` | _Required_ | String | Name of the color scheme. |
|
||||
| `foreground` | _Required_ | String | Sets the foreground color of the color scheme. |
|
||||
| `background` | _Required_ | String | Sets the background color of the color scheme. |
|
||||
| `selectionBackground` | Optional | String | Sets the selection background color of the color scheme. |
|
||||
| `cursorColor` | Optional | String | Sets the cursor color of the color scheme. |
|
||||
| `black` | _Required_ | String | Sets the color used as ANSI black. |
|
||||
| `blue` | _Required_ | String | Sets the color used as ANSI blue. |
|
||||
| `brightBlack` | _Required_ | String | Sets the color used as ANSI bright black. |
|
||||
| `brightBlue` | _Required_ | String | Sets the color used as ANSI bright blue. |
|
||||
| `brightCyan` | _Required_ | String | Sets the color used as ANSI bright cyan. |
|
||||
| `brightGreen` | _Required_ | String | Sets the color used as ANSI bright green. |
|
||||
| `brightPurple` | _Required_ | String | Sets the color used as ANSI bright purple. |
|
||||
| `brightRed` | _Required_ | String | Sets the color used as ANSI bright red. |
|
||||
| `brightWhite` | _Required_ | String | Sets the color used as ANSI bright white. |
|
||||
| `brightYellow` | _Required_ | String | Sets the color used as ANSI bright yellow. |
|
||||
| `cyan` | _Required_ | String | Sets the color used as ANSI cyan. |
|
||||
| `green` | _Required_ | String | Sets the color used as ANSI green. |
|
||||
| `purple` | _Required_ | String | Sets the color used as ANSI purple. |
|
||||
| `red` | _Required_ | String | Sets the color used as ANSI red. |
|
||||
| `white` | _Required_ | String | Sets the color used as ANSI white. |
|
||||
| `yellow` | _Required_ | String | Sets the color used as ANSI yellow. |
|
||||
|
||||
## Keybindings
|
||||
|
||||
Properties listed below are specific to each custom key binding.
|
||||
|
||||
| Property | Necessity | Type | Description |
|
||||
| -------- | ---- | ----------- | ----------- |
|
||||
| `command` | _Required_ | String | The command executed when the associated key bindings are pressed. |
|
||||
| `keys` | _Required_ | Array[String] or String | Defines the key combinations used to call the command. |
|
||||
| `action` | Optional | String | Adds additional functionality to certain commands. |
|
||||
|
||||
### Implemented Commands and Actions
|
||||
|
||||
Commands listed below are per the implementation in [`src/cascadia/TerminalApp/AppKeyBindingsSerialization.cpp`](https://github.com/microsoft/terminal/blob/master/src/cascadia/TerminalApp/AppKeyBindingsSerialization.cpp).
|
||||
|
||||
Keybindings can be structured in the following manners:
|
||||
|
||||
For commands without arguments:
|
||||
<br>
|
||||
`{ "command": "commandName", "keys": [ "modifiers+key" ] }`
|
||||
|
||||
For commands with arguments:
|
||||
<br>
|
||||
`{ "command": { "action": "commandName", "argument": "value" }, "keys": ["modifiers+key"] }`
|
||||
|
||||
| Command | Command Description | Action (*=required) | Action Arguments | Argument Descriptions |
|
||||
| ------- | ------------------- | ------ | ---------------- | ----------------- |
|
||||
| `adjustFontSize` | Change the text size by a specified point amount. | `delta` | integer | Amount of size change per command invocation. |
|
||||
| `closePane` | Close the active pane. | | | |
|
||||
| `closeTab` | Close the current tab. | | | |
|
||||
| `closeWindow` | Close the current window and all tabs within it. | | | |
|
||||
| `copy` | Copy the selected terminal content to your Windows Clipboard. | `singleLine` | boolean | When `true`, the copied content will be copied as a single line. When `false`, newlines persist from the selected text. |
|
||||
| `duplicateTab` | Make a copy and open the current tab. | | | |
|
||||
| `find` | Open the search dialog box. | | | |
|
||||
| `moveFocus` | Focus on a different pane depending on direction. | `direction`* | `left`, `right`, `up`, `down` | Direction in which the focus will move. |
|
||||
| `newTab` | Create a new tab. Without any arguments, this will open the default profile in a new tab. | 1. `commandLine`<br>2. `startingDirectory`<br>3. `tabTitle`<br>4. `index`<br>5. `profile` | 1. string<br>2. string<br>3. string<br>4. integer<br>5. string | 1. Executable run within the tab.<br>2. Directory in which the tab will open.<br>3. Title of the new tab.<br>4. Profile that will open based on its position in the dropdown (starting at 0).<br>5. Profile that will open based on its GUID or name. |
|
||||
| `nextTab` | Open the tab to the right of the current one. | | | |
|
||||
| `openNewTabDropdown` | Open the dropdown menu. | | | |
|
||||
| `openSettings` | Open the settings file. | | | |
|
||||
| `paste` | Insert the content that was copied onto the clipboard. | | | |
|
||||
| `prevTab` | Open the tab to the left of the current one. | | | |
|
||||
| `resetFontSize` | Reset the text size to the default value. | | | |
|
||||
| `resizePane` | Change the size of the active pane. | `direction`* | `left`, `right`, `up`, `down` | Direction in which the pane will be resized. |
|
||||
| `scrollDown` | Move the screen down. | | | |
|
||||
| `scrollUp` | Move the screen up. | | | |
|
||||
| `scrollUpPage` | Move the screen up a whole page. | | | |
|
||||
| `scrollDownPage` | Move the screen down a whole page. | | | |
|
||||
| `splitPane` | Halve the size of the active pane and open another. Without any arguments, this will open the default profile in the new pane. | 1. `split`*<br>2. `commandLine`<br>3. `startingDirectory`<br>4. `tabTitle`<br>5. `index`<br>6. `profile`<br>7. `splitMode` | 1. `vertical`, `horizontal`, `auto`<br>2. string<br>3. string<br>4. string<br>5. integer<br>6. string<br>7. string | 1. How the pane will split. `auto` will split in the direction that provides the most surface area.<br>2. Executable run within the pane.<br>3. Directory in which the pane will open.<br>4. Title of the tab when the new pane is focused.<br>5. Profile that will open based on its position in the dropdown (starting at 0).<br>6. Profile that will open based on its GUID or name.<br>7. Controls how the pane splits. Only accepts `duplicate` which will duplicate the focused pane's profile into a new pane. |
|
||||
| `switchToTab` | Open a specific tab depending on index. | `index`* | integer | Tab that will open based on its position in the tab bar (starting at 0). |
|
||||
| `toggleFullscreen` | Switch between fullscreen and default window sizes. | | | |
|
||||
| `unbound` | Unbind the associated keys from any command. | | | |
|
||||
|
||||
### Accepted Modifiers and Keys
|
||||
|
||||
#### Modifiers
|
||||
`ctrl+`, `shift+`, `alt+`
|
||||
|
||||
#### Keys
|
||||
|
||||
| Type | Keys |
|
||||
| ---- | ---- |
|
||||
| Function and Alphanumeric Keys | `f1-f24`, `a-z`, `0-9` |
|
||||
| Symbols | ``` ` ```, `-`, `=`, `[`, `]`, `\`, `;`, `'`, `,`, `.`, `/` |
|
||||
| Arrow Keys | `down`, `left`, `right`, `up`, `pagedown`, `pageup`, `pgdn`, `pgup`, `end`, `home`, `plus` |
|
||||
| Action Keys | `tab`, `enter`, `esc`, `escape`, `space`, `backspace`, `delete`, `insert` |
|
||||
| Numpad Keys | `numpad_0-numpad_9`, `numpad0-numpad9`, `numpad_add`, `numpad_plus`, `numpad_decimal`, `numpad_period`, `numpad_divide`, `numpad_minus`, `numpad_subtract`, `numpad_multiply` |
|
||||
|
||||
## Background Images and Icons
|
||||
|
||||
Some Terminal settings allow you to specify custom background images and icons. It is recommended that custom images and icons are stored in system-provided folders and are referred to using the correct [URI Schemes](https://docs.microsoft.com/en-us/windows/uwp/app-resources/uri-schemes). URI Schemes provide a way to reference files independent of their physical paths (which may change in the future).
|
||||
|
||||
The most useful URI schemes to remember when customizing background images and icons are:
|
||||
|
||||
| URI Scheme | Corresponding Physical Path | Use / description |
|
||||
| --- | --- | ---|
|
||||
| `ms-appdata:///Local/` | `%localappdata%\Packages\Microsoft.WindowsTerminal_8wekyb3d8bbwe\LocalState\` | Per-machine files |
|
||||
| `ms-appdata:///Roaming/` | `%localappdata%\Packages\Microsoft.WindowsTerminal_8wekyb3d8bbwe\RoamingState\` | Common files |
|
||||
|
||||
> ⚠ Note: Do not rely on file references using the `ms-appx` URI Scheme (i.e. icons). These files are considered an internal implementation detail and may change name/location or may be omitted in the future.
|
||||
|
||||
### Icons
|
||||
|
||||
Terminal displays icons for each of your profiles which Terminal generates for any built-in shells - PowerShell Core, PowerShell, and any installed Linux/WSL distros. Each profile refers to a stock icon via the `ms-appx` URI Scheme.
|
||||
|
||||
> ⚠ Note: Do not rely on the files referenced by the `ms-appx` URI Scheme - they are considered an internal implementation detail and may change name/location or may be omitted in the future.
|
||||
|
||||
You can refer to you own icons if you wish, e.g.:
|
||||
|
||||
```json
|
||||
"icon" : "C:\\Users\\richturn\\OneDrive\\WindowsTerminal\\icon-ubuntu-32.png",
|
||||
```
|
||||
|
||||
> 👉 Tip: Icons should be sized to 32x32px in an appropriate raster image format (e.g. .PNG, .GIF, or .ICO) to avoid having to scale your icons during runtime (causing a noticeable delay and loss of quality.)
|
||||
|
||||
### Custom Background Images
|
||||
|
||||
You can apply a background image to each of your profiles, allowing you to configure/brand/style each of your profiles independently from one another if you wish.
|
||||
|
||||
To do so, specify your preferred `backgroundImage`, position it using `backgroundImageAlignment`, set its opacity with `backgroundImageOpacity`, and/or specify how your image fill the available space using `backgroundImageStretchMode`.
|
||||
|
||||
For example:
|
||||
```json
|
||||
"backgroundImage": "C:\\Users\\richturn\\OneDrive\\WindowsTerminal\\bg-ubuntu-256.png",
|
||||
"backgroundImageAlignment": "bottomRight",
|
||||
"backgroundImageOpacity": 0.1,
|
||||
"backgroundImageStretchMode": "none"
|
||||
```
|
||||
|
||||
> 👉 Tip: You can easily roam your collection of images and icons across all your machines by storing your icons and images in OneDrive (as shown above).
|
||||
|
||||
With these settings, your Terminal's Ubuntu profile would look similar to this:
|
||||
|
||||

|
||||
|
||||
@@ -86,7 +86,7 @@ project from our `TerminalAppLib` project:
|
||||
duplicate type definitions)-->
|
||||
|
||||
<Reference Include="Microsoft.Terminal.Settings">
|
||||
<HintPath>$(OpenConsoleCommonOutDir)\TerminalSettings\Microsoft.Terminal.Settings.winmd</HintPath>
|
||||
<HintPath>$(SolutionDir)$(Platform)\$(Configuration)\TerminalSettings\Microsoft.Terminal.Settings.winmd</HintPath>
|
||||
<IsWinMDFile>true</IsWinMDFile>
|
||||
<Private>false</Private>
|
||||
<CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>
|
||||
@@ -122,7 +122,7 @@ dir to your `AdditionalLibraryDirectories`, and adding the lib to your
|
||||
<ItemDefinitionGroup>
|
||||
<Link>
|
||||
<!-- Manually link with the TerminalAppLib.lib we've built. -->
|
||||
<AdditionalLibraryDirectories>$(OpenConsoleCommonOutDir)\TerminalAppLib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalLibraryDirectories>$(SolutionDir)\$(Platform)\$(Configuration)\TerminalAppLib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
|
||||
<AdditionalDependencies>TerminalAppLib.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
@@ -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
|
||||
|
||||
@@ -260,9 +260,9 @@ this:
|
||||
echo OutDir=$(OutDir)
|
||||
(xcopy /Y "$(SolutionDir)src\cascadia\ut_app\TerminalApp.Unit.Tests.manifest" "$(OutDir)\TerminalApp.Unit.Tests.manifest*" )
|
||||
|
||||
(xcopy /Y "$(OpenConsoleCommonOutDir)\TerminalConnection\TerminalConnection.dll" "$(OutDir)\TerminalConnection.dll*" )
|
||||
(xcopy /Y "$(OpenConsoleCommonOutDir)\TerminalSettings\TerminalSettings.dll" "$(OutDir)\TerminalSettings.dll*" )
|
||||
(xcopy /Y "$(OpenConsoleCommonOutDir)\TerminalControl\TerminalControl.dll" "$(OutDir)\TerminalControl.dll*" )
|
||||
(xcopy /Y "$(SolutionDir)$(Platform)\$(Configuration)\TerminalConnection\TerminalConnection.dll" "$(OutDir)\TerminalConnection.dll*" )
|
||||
(xcopy /Y "$(SolutionDir)$(Platform)\$(Configuration)\TerminalSettings\TerminalSettings.dll" "$(OutDir)\TerminalSettings.dll*" )
|
||||
(xcopy /Y "$(SolutionDir)$(Platform)\$(Configuration)\TerminalControl\TerminalControl.dll" "$(OutDir)\TerminalControl.dll*" )
|
||||
</Command>
|
||||
</PostBuildEvent>
|
||||
</ItemDefinitionGroup>
|
||||
@@ -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>
|
||||
@@ -446,9 +446,9 @@ before. The complete `PostBuildEvent` now looks like this:
|
||||
|
||||
(xcopy /Y "$(SolutionDir)src\cascadia\ut_app\TerminalApp.Unit.Tests.AppxManifest.xml" "$(OutDir)\TerminalApp.Unit.Tests.AppxManifest.xml*" )
|
||||
|
||||
(xcopy /Y "$(OpenConsoleCommonOutDir)\TerminalConnection\TerminalConnection.dll" "$(OutDir)\TerminalConnection.dll*" )
|
||||
(xcopy /Y "$(OpenConsoleCommonOutDir)\TerminalSettings\TerminalSettings.dll" "$(OutDir)\TerminalSettings.dll*" )
|
||||
(xcopy /Y "$(OpenConsoleCommonOutDir)\TerminalControl\TerminalControl.dll" "$(OutDir)\TerminalControl.dll*" )
|
||||
(xcopy /Y "$(SolutionDir)$(Platform)\$(Configuration)\TerminalConnection\TerminalConnection.dll" "$(OutDir)\TerminalConnection.dll*" )
|
||||
(xcopy /Y "$(SolutionDir)$(Platform)\$(Configuration)\TerminalSettings\TerminalSettings.dll" "$(OutDir)\TerminalSettings.dll*" )
|
||||
(xcopy /Y "$(SolutionDir)$(Platform)\$(Configuration)\TerminalControl\TerminalControl.dll" "$(OutDir)\TerminalControl.dll*" )
|
||||
</Command>
|
||||
</PostBuildEvent>
|
||||
</ItemDefinitionGroup>
|
||||
@@ -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>
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
# Creating a New Project
|
||||
|
||||
## Creating a new WinRT Component DLL and referencing it in another project
|
||||
|
||||
When creating a new DLL, it was really helpful to reference an existing DLL's `.vcxproj` like `TerminalControl.vcxproj`. While you should mostly try to copy what the existing `.vcxproj` has, here's a handful of things to double check for as you go along.
|
||||
|
||||
- [ ] Make sure to `<Import>` our pre props at the _top_ of the vcxproj, and our post props at the _bottom_ of the vcxproj.
|
||||
```
|
||||
<!-- pre props -->
|
||||
<Import Project="..\..\..\common.openconsole.props" Condition="'$(OpenConsoleDir)'==''" />
|
||||
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.pre.props" />
|
||||
|
||||
<!-- everything else -->
|
||||
|
||||
<!-- post props -->
|
||||
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.post.props" />
|
||||
```
|
||||
- [ ] Add a `<ProjectReference>` to your new `.vcxproj` in both `WindowsTerminal.vcxproj` and `TerminalApp.vcxproj`
|
||||
- [ ] Add a `<Reference>` to `TerminalAppLib.vcxproj` similar to this:
|
||||
```
|
||||
<Reference Include="Microsoft.Terminal.NewDLL">
|
||||
<HintPath>$(OpenConsoleCommonOutDir)\TerminalNewDLL\Microsoft.Terminal.NewDLL.winmd</HintPath>
|
||||
<IsWinMDFile>true</IsWinMDFile>
|
||||
<Private>false</Private>
|
||||
<CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>
|
||||
</Reference>
|
||||
```
|
||||
- [ ] Make sure the project has a `.def` file with the following lines. The `WINRT_GetActivationFactory` part is important to expose the new DLL's activation factory so that other projects can successfully call the DLL's `GetActivationFactory` to get the DLL's classes.
|
||||
```
|
||||
EXPORTS
|
||||
DllCanUnloadNow = WINRT_CanUnloadNow PRIVATE
|
||||
DllGetActivationFactory = WINRT_GetActivationFactory PRIVATE
|
||||
```
|
||||
- For a bit more context on this whole process, the `AppXManifest.xml` file defines which classes belong to which DLLs. If your project wants class `X.Y.Z`, it can look it up in the manifest's definitions and see that it came from `X.Y.dll`. Then it'll load up the DLL, and call a particular function called `GetActivationFactory(L"X.Y.Z")` to get the class it wants. So, the definitions in `AppXManifest` are _required_ for this activation to work properly, and I found myself double checking the file to see that the definitions I expect are there.
|
||||
- _Note_: If your new library eventually rolls up as a reference to our Centennial Packaging project `CascadiaPackage`, you don't have to worry about manually adding your definitions to the `AppXManifest.xml` because the Centennial Packaging project automatically enumerates the reference tree of WinMDs and stitches that information into the `AppXManifest.xml`. However, if your new project does _not_ ultimately roll up to a packaging project that will automatically put the references into `AppXManifest`, you will have to add them in manually.
|
||||
|
||||
### Troubleshooting
|
||||
- If you hit an error that looks like this:
|
||||
```
|
||||
X found processing metadata file ..\blah1\Microsoft.UI.Xaml.winmd, type already exists in file ..\blah\NewDLLProject\Microsoft.UI.Xaml.winmd.
|
||||
```
|
||||
The `Microsoft.UI.Xaml.winmd` is showing up in the output folder when it shouldn't. Try adding this block at the top of your `.vcxproj`
|
||||
```
|
||||
<ItemDefinitionGroup>
|
||||
<Reference>
|
||||
<Private>false</Private>
|
||||
</Reference>
|
||||
</ItemDefinitionGroup>
|
||||
```
|
||||
This will make all references non-private, meaning "don't copy it into my folder" by default.
|
||||
|
||||
- If you hit a `Class not Registered` error, this might be because a class isn't getting registered in the app manifest. You can go check `src/cascadia/CascadiaPackage/bin/x64/Debug/AppX/AppXManifest.xml` to see if there exist entries to the classes of your newly created DLL. If the references aren't there, double check that you've added `<ProjectReference>` blocks to both `WindowsTerminal.vcxproj` and `TerminalApp.vcxproj`.
|
||||
|
||||
- If you hit an extremely vague error along the lines of `Error in the DLL`, and right before that line you notice that your new DLL is loaded and unloaded right after each other, double check that your new DLL's definitions show up in the `AppXManifest.xml` file. If your new DLL is included as a reference to a project that rolls up to `CascadiaPackage`, double check that you've created a `.def` file for the project. Otherwise if your new project _does not_ roll up to a package that populates the `AppXManifest` references for you, you'll have to add those references yourself.
|
||||
@@ -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
|
||||
BIN
doc/images/custom-icon-and-background-image.jpg
Normal file
|
After Width: | Height: | Size: 135 KiB |
|
Before Width: | Height: | Size: 77 KiB After Width: | Height: | Size: 78 KiB |
|
Before Width: | Height: | Size: 134 KiB After Width: | Height: | Size: 300 KiB |
|
Before Width: | Height: | Size: 101 KiB After Width: | Height: | Size: 110 KiB |
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 98 KiB After Width: | Height: | Size: 110 KiB |
@@ -1,239 +0,0 @@
|
||||
#requires -version 6.1
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Scan source code and build a list of supported VT sequences.
|
||||
.DESCRIPTION
|
||||
Scan source code and build a list of supported VT sequences.
|
||||
TODO: add more details
|
||||
#>
|
||||
[cmdletbinding(DefaultParameterSetName="stdout")]
|
||||
param(
|
||||
[parameter(ParameterSetName="file", mandatory)]
|
||||
[string]$OutFile,
|
||||
[parameter(ParameterSetName="file")]
|
||||
[switch]$Force, # for overwriting $OutFile if it exists
|
||||
|
||||
[parameter(ParameterSetName="stdout")]
|
||||
[parameter(ParameterSetName="file")]
|
||||
[switch]$NoLogo, # no logo in summary
|
||||
[parameter(ParameterSetName="stdout")]
|
||||
[switch]$SummaryOnly, # no markdown generated
|
||||
[parameter(ParameterSetName="stdout")]
|
||||
[parameter(ParameterSetName="file")]
|
||||
[switch]$Quiet, # no summary or logo
|
||||
|
||||
[parameter(ParameterSetName="file")]
|
||||
[parameter(ParameterSetName="stdout")]
|
||||
[string]$SolutionRoot = "..\..",
|
||||
[parameter(ParameterSetName="file")]
|
||||
[parameter(ParameterSetName="stdout")]
|
||||
[string]$InterfacePath = $(join-path $solutionRoot "src\terminal\adapter\ITermDispatch.hpp"),
|
||||
[parameter(ParameterSetName="file")]
|
||||
[parameter(ParameterSetName="stdout")]
|
||||
[string]$ConsoleAdapterPath = $(join-path $solutionRoot "src\terminal\adapter\adaptDispatch.hpp"),
|
||||
[parameter(ParameterSetName="file")]
|
||||
[parameter(ParameterSetName="stdout")]
|
||||
[string]$TerminalAdapterPath = $(join-path $solutionRoot "src\cascadia\terminalcore\terminalDispatch.hpp")
|
||||
)
|
||||
|
||||
if ($PSCmdlet.ParameterSetName -eq "stdout") {
|
||||
Write-Verbose "Emitting markdown to STDOUT"
|
||||
}
|
||||
|
||||
<#
|
||||
GLOBALS
|
||||
#>
|
||||
|
||||
[semver]$myVer = "0.6-beta"
|
||||
$sequences = import-csv ".\master-sequence-list.csv"
|
||||
$base = @{}
|
||||
$conhost = @{}
|
||||
$terminal = @{}
|
||||
$prefix = "https://vt100.net/docs/vt510-rm/"
|
||||
$repo = "https://github.com/oising/terminal/tree/master"
|
||||
$conhostUrl = $ConsoleAdapterPath.TrimStart($SolutionRoot).replace("\", "/")
|
||||
$terminalUrl = $TerminalAdapterPath.TrimStart($SolutionRoot).replace("\", "/")
|
||||
|
||||
function Read-SourceFiles {
|
||||
# extract base interface
|
||||
$baseScanner = [regex]'(?x)virtual\s\w+\s(?<method>\w+)(?s)[^;]+;(?-s).*?(?<seq>(?<=\/\/\s).+)'
|
||||
|
||||
$baseScanner.Matches(($src = get-content -raw $interfacePath)) | foreach-object {
|
||||
$match = $_
|
||||
#$line = (($src[0..$_.Index] -join "") -split "`n").Length
|
||||
#$decl = $_.groups[0].value
|
||||
$_.groups["seq"].value.split(",") | ForEach-Object {
|
||||
$SCRIPT:base[$_.trim()] = $match.groups["method"].value
|
||||
}
|
||||
}
|
||||
|
||||
# match overrides of ITermDispatch
|
||||
$scanner = [regex]'(?x)\s+\w+\s(?<method>\w+)(?s)[^;]+override;'
|
||||
|
||||
$scanner.Matches(($src = Get-Content -raw $consoleAdapterPath)) | ForEach-Object {
|
||||
$line = (($src[0..$_.Index] -join "") -split "`n").Length
|
||||
$SCRIPT:conhost[$_.groups["method"].value] = $line
|
||||
}
|
||||
|
||||
$scanner.Matches(($src = Get-Content -raw $terminalAdapterPath)) | ForEach-Object {
|
||||
$line = (($src[0..$_.Index] -join "") -split "`n").Length
|
||||
#write-verbose $_.groups[0].value
|
||||
$SCRIPT:terminal[$_.groups["method"].value] = $line
|
||||
}
|
||||
}
|
||||
|
||||
function Get-SequenceIndexMarkdown {
|
||||
# "Sequence","Parent","Description","Origin","Heading","Subheading", "ImplementedBy", "ConsoleHost","Terminal"
|
||||
|
||||
$heading = $null
|
||||
$subheading = $null
|
||||
<#
|
||||
Emit markdown
|
||||
|
||||
TODO:
|
||||
- auto-generate TOC
|
||||
#>
|
||||
@"
|
||||
# VT Function Support
|
||||
|
||||
## Table of Contents
|
||||
|
||||
* [Code Extension Functions](#code-extension-functions)
|
||||
* [Control Coding](#control-coding)
|
||||
* [Character Coding](#character-coding)
|
||||
* [Graphic Character Sets](#graphic-character-sets)
|
||||
* [Terminal Management Functions](#terminal-management-functions)
|
||||
* [Identification, status, and Initialization](#identification-status-and-initialization)
|
||||
* [Emulations](#emulations)
|
||||
* [Set-Up](#set-up)
|
||||
* [Display Coordinate System and Addressing](#display-coordinate-system-and-addressing)
|
||||
* [Active Position and Cursor](#active-position-and-cursor)
|
||||
* [Margins and Scrolling](#margins-and-scrolling)
|
||||
* [Cursor Movement](#cursor-movement)
|
||||
* [Horizontal Tabulation](#horizontal-tabulation)
|
||||
* [Page Size and Arrangement](#page-size-and-arrangement)
|
||||
* [Page Movement](#page-movement)
|
||||
* [Status Display](#status-display)
|
||||
* [Right to Left](#right-to-left)
|
||||
* [Window Management](#window-management)
|
||||
* [Visual Attributes and Renditions](#visual-attributes-and-renditions)
|
||||
* [Line Renditions](#line-renditions)
|
||||
* [Character Renditions](#character-renditions)
|
||||
* [Audible Indicators](#audible-indicators)
|
||||
* [Mode States](#mode-states)
|
||||
* [ANSI](#ansi)
|
||||
* [DEC Private](#dec-private)
|
||||
* [Editing Functions](#editing-functions)
|
||||
* [OLTP Features](#OLTP-features)
|
||||
* [Rectangular Area Operations](#rectangular-area-operations)
|
||||
* [Data Integrity](#data-integrity)
|
||||
* [Macros](#macros)
|
||||
* [Saving and Restoring Terminal State](#saving-and-restoring-terminal-state)
|
||||
* [Cursor Save Buffer](#cursor-save-buffer)
|
||||
* [Terminal State Interrogation](#terminal-state-interrogation)
|
||||
* [Keyboard Processing Functions](#keyboard-processing-functions)
|
||||
* [Soft Key Mapping (UDK)](#soft-key-mapping-UDK)
|
||||
* [Soft Fonts (DRCS)](#soft-fonts-drcs)
|
||||
* [Printing](#printing)
|
||||
* [Terminal Communication and Synchronization](#terminal-communication-and-synchronization)
|
||||
* [Text Locator Extension](#text-locator-extension)
|
||||
* [Session Management Extension](#session-management-extension)
|
||||
* [Documented Exceptions](#documented-exceptions)
|
||||
|
||||
$($sequences | ForEach-Object {
|
||||
if ($method = $base[$_.sequence]) {
|
||||
$_.ImplementedBy = $method
|
||||
$_.ConsoleHost = $conhost[$method]
|
||||
$_.Terminal = $terminal[$method]
|
||||
}
|
||||
# "Sequence","Associated","Description","Origin","Heading","Subheading", "ImplementedBy", "ConsoleHost","Terminal"
|
||||
$c0 = "[$($_.Sequence)]($prefix$($_.sequence).html ""View page on vt100.net"")"
|
||||
$c1 = "$($_.description)"
|
||||
$c2 = "$($_.origin)"
|
||||
$c3 = $(if ($_.consolehost) {"[✓](${repo}/${conhostUrl}#L$($_.consolehost) ""View console host implementation"")"})
|
||||
$c4 = $(if ($_.terminal) {"[✓](${repo}/${terminalUrl}#L$($_.terminal)} ""View windows terminal implementation"")"})
|
||||
|
||||
$shouldRenderHeader = $false
|
||||
|
||||
if ($heading -ne $_.heading) {
|
||||
$heading = $_.heading
|
||||
@"
|
||||
|
||||
## $heading
|
||||
|
||||
"@
|
||||
$shouldRenderHeader = $true
|
||||
}
|
||||
|
||||
if ($subheading -ne $_.subheading) {
|
||||
$subheading = $_.subheading
|
||||
@"
|
||||
|
||||
### $subheading
|
||||
|
||||
"@
|
||||
$shouldRenderHeader = $true
|
||||
}
|
||||
|
||||
if ($shouldRenderHeader) {
|
||||
@"
|
||||
|
||||
|Symbol|Function|Origin 🖳|Console Host|Terminal|
|
||||
|:-|:--|:--:|:--:|:--:|
|
||||
"@
|
||||
}
|
||||
@"
|
||||
|
||||
|$c0|$c1|$c2|$c3|$c4|
|
||||
"@
|
||||
})
|
||||
|
||||
---
|
||||
Generated on $(get-date -DisplayHint DateTime)
|
||||
"@
|
||||
}
|
||||
|
||||
function Show-Summary {
|
||||
write-host "`n$(' '*7)Windows Terminal Sequencer v${myVer}"
|
||||
if (-not $NoLogo.IsPresent) {
|
||||
Get-Content .\windows-terminal-logo.ans | ForEach-Object { Write-Host $_ }
|
||||
}
|
||||
$summary = @"
|
||||
`e[1mSequence Support:`e[0m
|
||||
|
||||
`e[7m {0:000} `e[0m known in master-sequence-list.csv.
|
||||
`e[7m {1:000} `e[0m common members in ITermDispatch base, of which:
|
||||
`e[7m {2:000} `e[0m are implemented by ConsoleHost.
|
||||
`e[7m {3:000} `e[0m are implemented by Windows Terminal.
|
||||
|
||||
"@ -f $sequences.Count, $base.count, $conhost.count, $terminal.Count
|
||||
|
||||
write-host $summary
|
||||
}
|
||||
|
||||
<#
|
||||
Entry Point
|
||||
#>
|
||||
|
||||
Read-SourceFiles
|
||||
|
||||
if (-not $SummaryOnly.IsPresent) {
|
||||
|
||||
$markdown = Get-SequenceIndexMarkdown
|
||||
|
||||
if ($PSCmdlet.ParameterSetName -eq "file") {
|
||||
# send to file and overwrite
|
||||
$markdown | Out-File -FilePath $OutFile -Force:$Force.IsPresent -Encoding utf8NoBOM
|
||||
} else {
|
||||
# send to STDOUT
|
||||
$markdown
|
||||
}
|
||||
|
||||
if (-not $Quiet.IsPresent) {
|
||||
Show-Summary
|
||||
}
|
||||
} else {
|
||||
# summary only
|
||||
Show-Summary
|
||||
}
|
||||
@@ -1,224 +0,0 @@
|
||||
"Sequence","Parent","Description","Origin","Heading","Subheading","ImplementedBy","ConsoleHost","Terminal"
|
||||
"CAN","","Cancel","`VT100`","Code Extension Functions","Control Coding","","",""
|
||||
"SUB","","Substitute","`VT100`","Code Extension Functions","Control Coding","","",""
|
||||
"ESC","","Escape","`VT100`","Code Extension Functions","Control Coding","","",""
|
||||
"DCS","","Device Control String","`VT220`","Code Extension Functions","Control Coding","","",""
|
||||
"CSI","","Control Sequence Introducer","`VT100`","Code Extension Functions","Control Coding","","",""
|
||||
"ST","","String Terminator","`VT220`","Code Extension Functions","Control Coding","","",""
|
||||
"OSC","","Operating System Command","`DECterm`","Code Extension Functions","Control Coding","","",""
|
||||
"PM","","Privacy Message","``","Code Extension Functions","Control Coding","","",""
|
||||
"APC","","Application Program Command","`VT420`","Code Extension Functions","Control Coding","","",""
|
||||
"S7C1T","","Select 7-bit C1 Transmission","`VT220`","Code Extension Functions","Control Coding","","",""
|
||||
"S8C1T","","Select 8-bit C1 Transmission","`VT220`","Code Extension Functions","Control Coding","","",""
|
||||
"LS0","","Locking Shift Zero (SI)","`VT100`","Code Extension Functions","Character Coding","","",""
|
||||
"LS1","","Locking Shift One (SO)","`VT100`","Code Extension Functions","Character Coding","","",""
|
||||
"LS2","","Locking Shift Two","`VT220`","Code Extension Functions","Character Coding","","",""
|
||||
"LS3","","Locking Shift Three","`VT220`","Code Extension Functions","Character Coding","","",""
|
||||
"LS1R","","Locking Shift One Right","`VT220`","Code Extension Functions","Character Coding","","",""
|
||||
"LS2R","","Locking Shift Two Right","`VT220`","Code Extension Functions","Character Coding","","",""
|
||||
"LS3R","","Locking Shift Three Right","`VT220`","Code Extension Functions","Character Coding","","",""
|
||||
"SS2","","Single Shift Two","`VT220`","Code Extension Functions","Character Coding","","",""
|
||||
"SS3","","Single Shift Three","`VT220`","Code Extension Functions","Character Coding","","",""
|
||||
"SCS","","Select Character Set","`VT100`","Code Extension Functions","Graphic Character Sets","","",""
|
||||
"DECNRCM","","(National Replacement) Character Set Mode","`VT220`","Code Extension Functions","Graphic Character Sets","","",""
|
||||
"DECAUPSS","","Assign User-Preference Supplemental Set","`VT320`","Code Extension Functions","Graphic Character Sets","","",""
|
||||
"DECRQUPSS","","Request User-Preference Supplemental Set","`VT320`","Code Extension Functions","Graphic Character Sets","","",""
|
||||
"DA1","","Primary Device Attributes","`VT100`","Terminal Management Functions","Identification, status, and Initialization","","",""
|
||||
"DA2","","Secondary Device Attributes","`VT220`","Terminal Management Functions","Identification, status, and Initialization","","",""
|
||||
"DA3","","Tertiary Device Attributes","`VT420`","Terminal Management Functions","Identification, status, and Initialization","","",""
|
||||
"DSR","","Device Status Report","`VT100`","Terminal Management Functions","Identification, status, and Initialization","","",""
|
||||
"DECID","","Identify Device","`VT100`","Terminal Management Functions","Identification, status, and Initialization","","",""
|
||||
"DECTID","","Select Terminal ID","`VT510`","Terminal Management Functions","Identification, status, and Initialization","","",""
|
||||
"DECSCL","","Select Conformance Level","`VT220`","Terminal Management Functions","Identification, status, and Initialization","","",""
|
||||
"DECSR","","Secure Reset","`VT420`","Terminal Management Functions","Identification, status, and Initialization","","",""
|
||||
"DECSRC","","Secure Reset Confirmation","`VT420`","Terminal Management Functions","Identification, status, and Initialization","","",""
|
||||
"DECSTR","","Soft Terminal Reset","`VT220`","Terminal Management Functions","Identification, status, and Initialization","","",""
|
||||
"DECSTUI","","Set Terminal Unit ID (Restricted)","`VT420`","Terminal Management Functions","Identification, status, and Initialization","","",""
|
||||
"RIS","","Reset to Initial state","`VT100`","Terminal Management Functions","Identification, status, and Initialization","","",""
|
||||
"DECPCTERM","","Enter/Exit PC Term Mode from DEC VT mode","`VT420PC`","Terminal Management Functions","Emulations","","",""
|
||||
"DECTME","","Terminal Mode Emulation","`VT510`","Terminal Management Functions","Emulations","","",""
|
||||
"DECSSL","","Select Set-Up Language","`VT510`","Terminal Management Functions","Set-Up","","",""
|
||||
"DECCRTSM","","CRT Save Mode (not required)","`VT510`","Terminal Management Functions","Set-Up","","",""
|
||||
"DECOSCNM","","Overscan Mode","`VT510`","Terminal Management Functions","Set-Up","","",""
|
||||
"DECSRFR","","Select Refresh Rate","`VT510`","Terminal Management Functions","Set-Up","","",""
|
||||
"DECLTOD","","Load Time of Day","`VT510`","Terminal Management Functions","Set-Up","","",""
|
||||
"DECLBAN","","Load Banner Message","`VT510`","Terminal Management Functions","Set-Up","","",""
|
||||
"DECTCEM","","Text Cursor Enable Mode","`VT220`","Display Coordinate System and Addressing","Active Position and Cursor","","",""
|
||||
"DECSCUSR","","Set Cursor Style","`VT510`","Display Coordinate System and Addressing","Active Position and Cursor","","",""
|
||||
"DECSTBM","","Set Top and Bottom Margin","`VT100`","Display Coordinate System and Addressing","Margins and Scrolling","","",""
|
||||
"DECSLRM","","Set Left and Right Margin","`VT420`","Display Coordinate System and Addressing","Margins and Scrolling","","",""
|
||||
"DECLRMM","","Left Right Margin Mode","`VT420`","Display Coordinate System and Addressing","Margins and Scrolling","","",""
|
||||
"DECOM","","Origin Mode","`VT100`","Display Coordinate System and Addressing","Margins and Scrolling","","",""
|
||||
"DECSCLM","","Scrolling Mode","`VT100`","Display Coordinate System and Addressing","Margins and Scrolling","","",""
|
||||
"IND","","Index","`VT100`","Display Coordinate System and Addressing","Margins and Scrolling","","",""
|
||||
"RI","","Reverse Index","`VT100`","Display Coordinate System and Addressing","Margins and Scrolling","","",""
|
||||
"DECFI","","Forward Index","`VT420`","Display Coordinate System and Addressing","Margins and Scrolling","","",""
|
||||
"DECBI","","Back Index","`VT420`","Display Coordinate System and Addressing","Margins and Scrolling","","",""
|
||||
"DECSSCLS","","Set Scroll Speed","`VT510`","Display Coordinate System and Addressing","Margins and Scrolling","","",""
|
||||
"BS","","Backspace","`VT100`","Display Coordinate System and Addressing","Cursor Movement","","",""
|
||||
"LF","","Line Feed","`VT100`","Display Coordinate System and Addressing","Cursor Movement","","",""
|
||||
"VT","","Vertical Tab","`VT100`","Display Coordinate System and Addressing","Cursor Movement","","",""
|
||||
"FF","","Form Feed","`VT100`","Display Coordinate System and Addressing","Cursor Movement","","",""
|
||||
"CR","","Carriage Return","`VT100`","Display Coordinate System and Addressing","Cursor Movement","","",""
|
||||
"NEL","","Next Line","`VT100`","Display Coordinate System and Addressing","Cursor Movement","","",""
|
||||
"LNM","","Line Feed/New Line Mode","`VT100`","Display Coordinate System and Addressing","Cursor Movement","","",""
|
||||
"CUU","","Cursor Up","`VT100`","Display Coordinate System and Addressing","Cursor Movement","","",""
|
||||
"CUD","","Cursor Down","`VT100`","Display Coordinate System and Addressing","Cursor Movement","","",""
|
||||
"CUF","","Cursor Forward","`VT100`","Display Coordinate System and Addressing","Cursor Movement","","",""
|
||||
"CUB","","Cursor Backward","`VT100`","Display Coordinate System and Addressing","Cursor Movement","","",""
|
||||
"CUP","","Cursor Position","`VT100`","Display Coordinate System and Addressing","Cursor Movement","","",""
|
||||
"HVP","","Horizontal/Vertical Position","`VT100`","Display Coordinate System and Addressing","Cursor Movement","","",""
|
||||
"DSR-CPR","","Device Status Report (Cursor Position Report)","`VT100`","Display Coordinate System and Addressing","Cursor Movement","","",""
|
||||
"DSR-XCPR","","Device Status Report (Extended Cursor Position Report)","`VT340` `VT420`","Display Coordinate System and Addressing","Cursor Movement","","",""
|
||||
"CHA","","Cursor Horizontal Absolute","`VT510`","Display Coordinate System and Addressing","Cursor Movement","","",""
|
||||
"CNL","","Cursor Next Line","`VT510`","Display Coordinate System and Addressing","Cursor Movement","","",""
|
||||
"CPL","","Cursor Previous Line","`VT510`","Display Coordinate System and Addressing","Cursor Movement","","",""
|
||||
"HPA","","Horizontal Position Absolute","`VT510`","Display Coordinate System and Addressing","Cursor Movement","","",""
|
||||
"HPR","","Horizontal Position Relative","`VT510`","Display Coordinate System and Addressing","Cursor Movement","","",""
|
||||
"VPA","","Vertical Line Position Absolute","`VT510`","Display Coordinate System and Addressing","Cursor Movement","","",""
|
||||
"VPR","","Vertical Position Relative","`VT510`","Display Coordinate System and Addressing","Cursor Movement","","",""
|
||||
"HT","","Horizontal Tab","`VT100`","Display Coordinate System and Addressing","Horizontal Tabulation","","",""
|
||||
"HTS","","Horizontal Tabulation Set","`VT100`","Display Coordinate System and Addressing","Horizontal Tabulation","","",""
|
||||
"TBC","","Tabulation Clear","`VT100`","Display Coordinate System and Addressing","Horizontal Tabulation","","",""
|
||||
"CBT","","Cursor Backward Tabulation","`VT510`","Display Coordinate System and Addressing","Horizontal Tabulation","","",""
|
||||
"CHT","","Cursor Horizontal Forward Tabulation","`VT510`","Display Coordinate System and Addressing","Horizontal Tabulation","","",""
|
||||
"DECST8C","","Set Tab at every 8 columns","`VT420PC`","Display Coordinate System and Addressing","Horizontal Tabulation","","",""
|
||||
"DECCOLM","","Column Mode","`VT100`","Display Coordinate System and Addressing","Page Size and Arrangement","","",""
|
||||
"DECNCSM","","No Clear Screen on column Mode","`VT510`","Display Coordinate System and Addressing","Page Size and Arrangement","","",""
|
||||
"DECSCPP","","Set Columns Per Page","`VT340` `VT420`","Display Coordinate System and Addressing","Page Size and Arrangement","","",""
|
||||
"DECSLPP","","Set Lines Per Page","`VT340` `VT420`","Display Coordinate System and Addressing","Page Size and Arrangement","","",""
|
||||
"NP","","Next Page","`VT340` `VT420`","Display Coordinate System and Addressing","Page Movement","","",""
|
||||
"PP","","Preceding Page","`VT340` `VT420`","Display Coordinate System and Addressing","Page Movement","","",""
|
||||
"PPA","","Page Position Absolute","`VT340` `VT420`","Display Coordinate System and Addressing","Page Movement","","",""
|
||||
"PPR","","Page Position Relative","`VT340` `VT420`","Display Coordinate System and Addressing","Page Movement","","",""
|
||||
"PPB","","Page Position Backward","`VT340` `VT420`","Display Coordinate System and Addressing","Page Movement","","",""
|
||||
"DECSASD","","Select Active Status Display","`VT340` `VT320`","Display Coordinate System and Addressing","Status Display","","",""
|
||||
"DECSSDT","","Select Status Display Type","`VT340` `VT320`","Display Coordinate System and Addressing","Status Display","","",""
|
||||
"DECRLM","","Right to Left Mode","`VT510`","Display Coordinate System and Addressing","Right to Left","","",""
|
||||
"DECRLCM","","Right to Left Copy Mode","`VT510`","Display Coordinate System and Addressing","Right to Left","","",""
|
||||
"DDD1","","`VT100` mode Hebrew","`VT510`","Display Coordinate System and Addressing","Right to Left","","",""
|
||||
"DDD2","","`VT100` mode Hebrew","`VT510`","Display Coordinate System and Addressing","Right to Left","","",""
|
||||
"DDD3","","`VT100` mode Hebrew","`VT510`","Display Coordinate System and Addressing","Right to Left","","",""
|
||||
"DECHCCM","","Horizontal Cursor Coupling Mode","`VT340` `VT420`","Window Management","Right to Left","","",""
|
||||
"DECVCCM","","Vertical Cursor Coupling Mode","`VT340` `VT420`","Window Management","Right to Left","","",""
|
||||
"DECPCCM","","Page Cursor Coupling Mode","`VT340` `VT420`","Window Management","Right to Left","","",""
|
||||
"DECRQDE","","Request Displayed Extent","`VT340` `VT420`","Window Management","Right to Left","","",""
|
||||
"DECSNLS","","Select Number of Lines per Screen (exception)","`VT420`","Window Management","Right to Left","","",""
|
||||
"DECARSM","","Auto Resize Mode","`DECterm` `VT420`","Window Management","Right to Left","","",""
|
||||
"SU","","Pan Down","`VT340` `VT420`","Window Management","Right to Left","","",""
|
||||
"SD","","Pan Up","`VT340` `VT420`","Window Management","Right to Left","","",""
|
||||
"DECSCNM","","Screen Mode","`VT100`","Visual Attributes and Renditions","Right to Left","","",""
|
||||
"DECSWL","","Single Width Line","`VT100`","Visual Attributes and Renditions","Line Renditions","","",""
|
||||
"DECDWL","","Double Width Line","`VT100`","Visual Attributes and Renditions","Line Renditions","","",""
|
||||
"DECDHLT","","Double Height Line Top","`VT100`","Visual Attributes and Renditions","Line Renditions","","",""
|
||||
"DECDHLB","","Double Height Line Bottom","`VT100`","Visual Attributes and Renditions","Line Renditions","","",""
|
||||
"SGR","","Select Graphic Rendition","`VT100`","Visual Attributes and Renditions","Character Renditions","","",""
|
||||
"BEL","","Warning Bell","`VT100`","Audible Indicators","Character Renditions","","",""
|
||||
"DECSKCV","","Set Keyclick Volume","`VT510`","Audible Indicators","Character Renditions","","",""
|
||||
"DECSWBV","","Set Warning Bell Volume","`VT510`","Audible Indicators","Character Renditions","","",""
|
||||
"DECSMBV","","Set Margin Bell Volume","`VT510`","Audible Indicators","Character Renditions","","",""
|
||||
"IRM","","Insert/Replacement Mode","`VT102`","Editing Functions","DEC Private","","",""
|
||||
"ICH","","Insert Character","`VT102`","Editing Functions","DEC Private","","",""
|
||||
"DCH","","Delete Character","`VT102`","Editing Functions","DEC Private","","",""
|
||||
"IL","","Insert Line","`VT100`","Editing Functions","DEC Private","","",""
|
||||
"DL","","Delete Line","`VT100`","Editing Functions","DEC Private","","",""
|
||||
"DECIC","","Insert Column","`VT420`","Editing Functions","DEC Private","","",""
|
||||
"DECDC","","Delete Column","`VT420`","Editing Functions","DEC Private","","",""
|
||||
"ECH","","Erase Character","`VT100`","Editing Functions","DEC Private","","",""
|
||||
"EL","","Erase in Line","`VT100`","Editing Functions","DEC Private","","",""
|
||||
"DECSEL","","Selective Erase in Line","`VT220`","Editing Functions","DEC Private","","",""
|
||||
"ED","","Erase in Display","`VT100`","Editing Functions","DEC Private","","",""
|
||||
"DECSED","","Selective Erase in Display","`VT220`","Editing Functions","DEC Private","","",""
|
||||
"DECSCA","","Select Character Attribute (selective erase)","`VT220`","Editing Functions","DEC Private","","",""
|
||||
"DECCRA","","Copy Rectangular Area","`VT420`","OLTP Features","Rectangular Area Operations","","",""
|
||||
"DECFRA","","Fill Rectangular Area","`VT420`","OLTP Features","Rectangular Area Operations","","",""
|
||||
"DECERA","","Erase Rectangular Area","`VT420`","OLTP Features","Rectangular Area Operations","","",""
|
||||
"DECSERA","","Selective Erase Rectangular Area","`VT420`","OLTP Features","Rectangular Area Operations","","",""
|
||||
"DECCARA","","Change Attribute in Rectangular Area","`VT420`","OLTP Features","Rectangular Area Operations","","",""
|
||||
"DECRARA","","Reverse Attribute in Rectangular Area","`VT420`","OLTP Features","Rectangular Area Operations","","",""
|
||||
"DECSACE","","Select Attribute Change Extent Mode","`VT420`","OLTP Features","Rectangular Area Operations","","",""
|
||||
"DECRQCRA","","Request Checksum of Rectangular Area","`VT420`","OLTP Features","Data Integrity","","",""
|
||||
"DSR-DECCKSR","","Device Status Report (Memory Checksum)","`VT420`","OLTP Features","Data Integrity","","",""
|
||||
"DECDMAC","","Define Macro","`VT420`","OLTP Features","Macros","","",""
|
||||
"DECINVM","","Invoke Macro","`VT420`","OLTP Features","Macros","","",""
|
||||
"DSR-MSR","","Device Status Report (Macro Space Report)","`VT420`","OLTP Features","Macros","","",""
|
||||
"DECSC","","Save Cursor","`VT100`","Saving and Restoring Terminal State","Cursor Save Buffer","","",""
|
||||
"DECRC","","Restore Cursor","`VT100`","Saving and Restoring Terminal State","Cursor Save Buffer","","",""
|
||||
"DECRQM","","Request Mode","`VT320`","Saving and Restoring Terminal State","Terminal State Interrogation","","",""
|
||||
"DECNKM","","Numeric Keypad Mode","`VT320`","Saving and Restoring Terminal State","Terminal State Interrogation","","",""
|
||||
"DECRQSS","","Request Selection or Setting","`VT320`","Saving and Restoring Terminal State","Terminal State Interrogation","","",""
|
||||
"DECRQPSR","","Request Presentation State Report","`VT320`","Saving and Restoring Terminal State","Terminal State Interrogation","","",""
|
||||
"DECRSPS","","Restore Presentation State","`VT320`","Saving and Restoring Terminal State","Terminal State Interrogation","","",""
|
||||
"DECRQTSR","","Request Terminal State Report","`VT320`","Saving and Restoring Terminal State","Terminal State Interrogation","","",""
|
||||
"DECRSTS","","Restore Terminal State","`VT320`","Saving and Restoring Terminal State","Terminal State Interrogation","","",""
|
||||
"DECARM","","Autorepeat Mode","`VT100`","Keyboard Processing Functions","Terminal State Interrogation","","",""
|
||||
"DECBKM","","Backarrow Key Mode","`VT420`","Keyboard Processing Functions","Terminal State Interrogation","","",""
|
||||
"DECCKM","","Cursor Keys Mode","`VT100`","Keyboard Processing Functions","Terminal State Interrogation","","",""
|
||||
"DECKBUM","","Keyboard Usage Mode","`VT320`","Keyboard Processing Functions","Terminal State Interrogation","","",""
|
||||
"DECKPAM","","Keypad Application Mode","`VT100`","Keyboard Processing Functions","Terminal State Interrogation","","",""
|
||||
"DECKPM","","Key Position Mode","`VT420`","Keyboard Processing Functions","Terminal State Interrogation","","",""
|
||||
"DECKPNM","","Keypad Numeric Mode","`VT100`","Keyboard Processing Functions","Terminal State Interrogation","","",""
|
||||
"DECNKM","","Numeric Keypad Mode","`VT320`","Keyboard Processing Functions","Terminal State Interrogation","","",""
|
||||
"DSR-KBD","","Device Status Report (keyboard status)","`VT220`","Keyboard Processing Functions","Terminal State Interrogation","","",""
|
||||
"KAM","","Keyboard Action Mode","`VT220`","Keyboard Processing Functions","Terminal State Interrogation","","",""
|
||||
"DECLFC","","Local Functions Control","`VT420`","Keyboard Processing Functions","Terminal State Interrogation","","",""
|
||||
"DECLFKC","","Local Function Key Control","`VT420`","Keyboard Processing Functions","Terminal State Interrogation","","",""
|
||||
"DECSMKR","","Select Modifier Key Reporting","`VT420`","Keyboard Processing Functions","Terminal State Interrogation","","",""
|
||||
"DECHEBM","","Hebrew Keyboard Map mode","`VT510`","Keyboard Processing Functions","Terminal State Interrogation","","",""
|
||||
"DECHCEM","","Hebrew Encoding Mode","`VT510`","Keyboard Processing Functions","Terminal State Interrogation","","",""
|
||||
"DECNAKB","","NA/Greek Selection","`VT510`","Keyboard Processing Functions","Terminal State Interrogation","","",""
|
||||
"DECESKM","","Secondary Keyboard Language Mode","`VT510`","Keyboard Processing Functions","Terminal State Interrogation","","",""
|
||||
"DECSLCK","","Set Lock Key Style","`VT510`","Keyboard Processing Functions","Terminal State Interrogation","","",""
|
||||
"DECKBD","","Keyboard Dialect Selection","`VT510`","Keyboard Processing Functions","Terminal State Interrogation","","",""
|
||||
"DECNUMLK","","NumLock Mode","`VT510`","Keyboard Processing Functions","Terminal State Interrogation","","",""
|
||||
"DECCAPSLK","","CapsLock Mode","`VT510`","Keyboard Processing Functions","Terminal State Interrogation","","",""
|
||||
"DECKLHIM","","Keyboard LEDs Host Indicator Mode","`VT510`","Keyboard Processing Functions","Terminal State Interrogation","","",""
|
||||
"DECLL","","Load LEDs","`VT100`","Keyboard Processing Functions","Terminal State Interrogation","","",""
|
||||
"DECUDK","","User Defined Keys","`VT220`","Soft Key Mapping (UDK)","Terminal State Interrogation","","",""
|
||||
"DSR-UDK","","Device Status Report (UDK lock)","`VT220`","Soft Key Mapping (UDK)","Terminal State Interrogation","","",""
|
||||
"DECPKA","","Program Key Action","`VT510`","Soft Key Mapping (UDK)","Terminal State Interrogation","","",""
|
||||
"DECPFK","","Program Function Key","`VT510`","Soft Key Mapping (UDK)","Terminal State Interrogation","","",""
|
||||
"DECPAK","","Program Alphanumeric Key","`VT510`","Soft Key Mapping (UDK)","Terminal State Interrogation","","",""
|
||||
"DECCKD","","Copy Key Default","`VT510`","Soft Key Mapping (UDK)","Terminal State Interrogation","","",""
|
||||
"DECRQPKFM","","Program Key Free Memory Inquiry","`VT510`","Soft Key Mapping (UDK)","Terminal State Interrogation","","",""
|
||||
"DECRQKT","","Inquire a Key Type","`VT510`","Soft Key Mapping (UDK)","Terminal State Interrogation","","",""
|
||||
"DECRQKD","","Inquire a Key Definition","`VT510`","Soft Key Mapping (UDK)","Terminal State Interrogation","","",""
|
||||
"DECDLD","","Downline Load","`VT220`","Soft Fonts (DRCS)","Terminal State Interrogation","","",""
|
||||
"DECPEX","","Print Extent Mode","`VT220`","Printing","Terminal State Interrogation","","",""
|
||||
"DECPFF","","Print Form Feed Mode","`VT220`","Printing","Terminal State Interrogation","","",""
|
||||
"DSR-PP","","Device Status Report (printer port)","`VT220`","Printing","Terminal State Interrogation","","",""
|
||||
"MC","","Media Copy","`VT220`","Printing","Terminal State Interrogation","","",""
|
||||
"DECSPRTT","","Select Printer Type","`VT510`","Printing","Terminal State Interrogation","","",""
|
||||
"DECSDPT","","Select Digital Printed Data Type","`VT510`","Printing","Terminal State Interrogation","","",""
|
||||
"DECSPPCS","","Select Proprinter Character Set","`VT510`","Printing","Terminal State Interrogation","","",""
|
||||
"BREAK","","BREAK","`VT100`","Terminal Communication and Synchronization","Terminal State Interrogation","","",""
|
||||
"XON","","XON","`VT100`","Terminal Communication and Synchronization","Terminal State Interrogation","","",""
|
||||
"XOFF","","XOFF","`VT100`","Terminal Communication and Synchronization","Terminal State Interrogation","","",""
|
||||
"ENQ","","Enquiry","`VT100`","Terminal Communication and Synchronization","Terminal State Interrogation","","",""
|
||||
"SRM","","Send Receive Mode","`VT220`","Terminal Communication and Synchronization","Terminal State Interrogation","","",""
|
||||
"DECXRLM","","Transmit Rate Limiting Mode","`VT420`","Terminal Communication and Synchronization","Terminal State Interrogation","","",""
|
||||
"DECMCM","","Modem Control Mode","`VT510`","Terminal Communication and Synchronization","Terminal State Interrogation","","",""
|
||||
"DECAAM","","Auto Answerback Mode","`VT510`","Terminal Communication and Synchronization","Terminal State Interrogation","","",""
|
||||
"DECLANS","","Load Answerback Message","`VT510`","Terminal Communication and Synchronization","Terminal State Interrogation","","",""
|
||||
"DECCANSM","","Conceal Answerback Message Mode","`VT510`","Terminal Communication and Synchronization","Terminal State Interrogation","","",""
|
||||
"DECNULM","","Ignore Null Mode","`VT510`","Terminal Communication and Synchronization","Terminal State Interrogation","","",""
|
||||
"DECHPDXM","","Half Duplex Mode","`VT510`","Terminal Communication and Synchronization","Terminal State Interrogation","","",""
|
||||
"DECSFC","","Select Flow Control","`VT510`","Terminal Communication and Synchronization","Terminal State Interrogation","","",""
|
||||
"DECSDDT","","Select Disconnect Delay Time","`VT510`","Terminal Communication and Synchronization","Terminal State Interrogation","","",""
|
||||
"DECSTRL","","Set Transmit Rate Limit","`VT510`","Terminal Communication and Synchronization","Terminal State Interrogation","","",""
|
||||
"DECSCS","","Select Communication Speed","`VT510`","Terminal Communication and Synchronization","Terminal State Interrogation","","",""
|
||||
"DECSCP","","Select Communication Port","`VT510`","Terminal Communication and Synchronization","Terminal State Interrogation","","",""
|
||||
"DECSPP","","Set Port Parameter","`VT510`","Terminal Communication and Synchronization","Terminal State Interrogation","","",""
|
||||
"DECEFR","","Enable Filter Rectangle","`UWS`","Text Locator Extension","Terminal State Interrogation","","",""
|
||||
"DECELR","","Enable Locator Reports","`UWS`","Text Locator Extension","Terminal State Interrogation","","",""
|
||||
"DECLKD","","Locator Key Definition","`UWS`","Text Locator Extension","Terminal State Interrogation","","",""
|
||||
"DECLRP","","Locator Report","`UWS`","Text Locator Extension","Terminal State Interrogation","","",""
|
||||
"DECRQLP","","Request Locator Position","`UWS`","Text Locator Extension","Terminal State Interrogation","","",""
|
||||
"DECSLE","","Select Locator Events","`UWS`","Text Locator Extension","Terminal State Interrogation","","",""
|
||||
"DSR-LS","","Device Status Report (Locator Status)","`UWS`","Text Locator Extension","Terminal State Interrogation","","",""
|
||||
"DECES","","Enable Sessions","`VT340` `VT420`","Session Management Extension","Terminal State Interrogation","","",""
|
||||
"DECANM","","`ANSI`/`VT52` Mode","`VT100`","Documented Exceptions","Terminal State Interrogation","","",""
|
||||
"DECALN","","Screen Alignment","`VT100`","Documented Exceptions","Terminal State Interrogation","","",""
|
||||
"DECAWM","","Autowrap Mode","`VT100`","Documented Exceptions","Terminal State Interrogation","","",""
|
||||
"DECTST","","Invoke Confidence Test","`VT100`","Documented Exceptions","Terminal State Interrogation","","",""
|
||||
"CRM","","Control Representation Mode","`VT100`","Documented Exceptions","Terminal State Interrogation","","",""
|
||||
|
|
Before Width: | Height: | Size: 117 KiB After Width: | Height: | Size: 130 KiB |
@@ -1,15 +0,0 @@
|
||||
[0m [0m [0m [0m [0m [0m [0m [0m [0m [0m [0m [0m [0m [0m [0m [0m [0m [0m [0m [0m [0m [0m [0m [0m [0m [0m [0m [0m [0m [0m [0m [0m [0m [0m [0m [0m [0m [0m [0m [0m [0m [0m [0m [0m [0m [0m [0m [0m [0m [0m [0m
|
||||
[0m [0m [0m [0m [0m [0m [0m [0m[38;2;191;191;191m[48;2;204;204;204m▀[0m[7m[38;2;204;204;204m [0m[7m[38;2;204;204;204m [0m[7m[38;2;204;204;204m [0m[7m[38;2;204;204;204m [0m[7m[38;2;204;204;204m [0m[7m[38;2;204;204;204m [0m[7m[38;2;204;204;204m [0m[7m[38;2;204;204;204m [0m[7m[38;2;204;204;204m [0m[7m[38;2;204;204;204m [0m[7m[38;2;204;204;204m [0m[7m[38;2;153;153;153m [0m[7m[38;2;153;153;153m [0m[7m[38;2;153;153;153m [0m[7m[38;2;153;153;153m [0m[7m[38;2;153;153;153m [0m[7m[38;2;153;153;153m [0m[7m[38;2;153;153;153m [0m[7m[38;2;153;153;153m [0m[7m[38;2;153;153;153m [0m[7m[38;2;153;153;153m [0m[7m[38;2;153;153;153m [0m[7m[38;2;153;153;153m [0m[7m[38;2;102;102;102m [0m[7m[38;2;102;102;102m [0m[7m[38;2;102;102;102m [0m[7m[38;2;102;102;102m [0m[7m[38;2;102;102;102m [0m[7m[38;2;102;102;102m [0m[7m[38;2;102;102;102m [0m[7m[38;2;102;102;102m [0m[7m[38;2;102;102;102m [0m[7m[38;2;102;102;102m [0m[7m[38;2;102;102;102m [0m[38;2;95;95;95m[48;2;102;102;102m▀[0m [0m [0m [0m [0m [0m [0m [0m
|
||||
[0m [0m [0m [0m [0m [0m [0m [0m[7m[38;2;204;204;204m [0m[7m[38;2;204;204;204m [0m[7m[38;2;204;204;204m [0m[7m[38;2;204;204;204m [0m[7m[38;2;204;204;204m [0m[7m[38;2;204;204;204m [0m[7m[38;2;204;204;204m [0m[7m[38;2;204;204;204m [0m[7m[38;2;204;204;204m [0m[7m[38;2;204;204;204m [0m[7m[38;2;204;204;204m [0m[7m[38;2;204;204;204m [0m[7m[38;2;153;153;153m [0m[7m[38;2;153;153;153m [0m[7m[38;2;153;153;153m [0m[7m[38;2;153;153;153m [0m[7m[38;2;153;153;153m [0m[7m[38;2;153;153;153m [0m[7m[38;2;153;153;153m [0m[7m[38;2;153;153;153m [0m[7m[38;2;153;153;153m [0m[7m[38;2;153;153;153m [0m[7m[38;2;153;153;153m [0m[7m[38;2;153;153;153m [0m[7m[38;2;102;102;102m [0m[7m[38;2;102;102;102m [0m[7m[38;2;102;102;102m [0m[7m[38;2;102;102;102m [0m[7m[38;2;102;102;102m [0m[7m[38;2;102;102;102m [0m[7m[38;2;102;102;102m [0m[7m[38;2;102;102;102m [0m[7m[38;2;102;102;102m [0m[7m[38;2;102;102;102m [0m[7m[38;2;102;102;102m [0m[7m[38;2;102;102;102m [0m [0m [0m [0m [0m [0m [0m [0m
|
||||
[0m [0m [0m [0m [0m [0m [0m [0m[38;2;77;77;77m[48;2;76;76;76m▀[0m[7m[38;2;76;76;76m [0m[38;2;76;76;76m[48;2;75;75;75m▀[0m[38;2;76;76;76m[48;2;75;75;75m▀[0m[7m[38;2;75;75;75m [0m[38;2;75;75;75m[48;2;74;74;74m▀[0m[38;2;75;75;75m[48;2;74;74;74m▀[0m[7m[38;2;74;74;74m [0m[38;2;74;74;74m[48;2;73;73;73m▀[0m[38;2;74;74;74m[48;2;73;73;73m▀[0m[7m[38;2;73;73;73m [0m[38;2;73;73;73m[48;2;72;72;72m▀[0m[38;2;73;73;73m[48;2;72;72;72m▀[0m[7m[38;2;72;72;72m [0m[38;2;72;72;72m[48;2;71;71;71m▀[0m[7m[38;2;71;71;71m [0m[7m[38;2;71;71;71m [0m[38;2;71;71;71m[48;2;70;70;70m▀[0m[7m[38;2;70;70;70m [0m[7m[38;2;70;70;70m [0m[38;2;70;70;70m[48;2;69;69;69m▀[0m[7m[38;2;69;69;69m [0m[38;2;69;69;69m[48;2;68;68;68m▀[0m[38;2;69;69;69m[48;2;68;68;68m▀[0m[7m[38;2;68;68;68m [0m[38;2;68;68;68m[48;2;67;67;67m▀[0m[38;2;68;68;68m[48;2;67;67;67m▀[0m[7m[38;2;67;67;67m [0m[38;2;67;67;67m[48;2;66;66;66m▀[0m[38;2;67;67;67m[48;2;66;66;66m▀[0m[7m[38;2;66;66;66m [0m[38;2;66;66;66m[48;2;65;65;65m▀[0m[38;2;66;66;66m[48;2;65;65;65m▀[0m[7m[38;2;65;65;65m [0m[38;2;65;65;65m[48;2;64;64;64m▀[0m[7m[38;2;64;64;64m [0m [0m [0m [0m [0m [0m [0m [0m
|
||||
[0m [0m [0m [0m [0m [0m [0m [0m[38;2;76;76;76m[48;2;75;75;75m▀[0m[7m[38;2;75;75;75m [0m[38;2;75;75;75m[48;2;74;74;74m▀[0m[38;2;75;75;75m[48;2;74;74;74m▀[0m[38;2;74;74;74m[48;2;73;73;73m▀[0m[38;2;74;74;74m[48;2;71;71;71m▀[0m[38;2;73;73;73m[48;2;67;67;67m▀[0m[38;2;73;73;73m[48;2;70;70;70m▀[0m[38;2;73;73;73m[48;2;71;71;71m▀[0m[7m[38;2;72;72;72m [0m[38;2;72;72;72m[48;2;71;71;71m▀[0m[38;2;72;72;72m[48;2;71;71;71m▀[0m[7m[38;2;71;71;71m [0m[38;2;71;71;71m[48;2;70;70;70m▀[0m[38;2;71;71;71m[48;2;70;70;70m▀[0m[7m[38;2;70;70;70m [0m[38;2;70;70;70m[48;2;69;69;69m▀[0m[38;2;70;70;70m[48;2;69;69;69m▀[0m[7m[38;2;69;69;69m [0m[38;2;69;69;69m[48;2;68;68;68m▀[0m[38;2;69;69;69m[48;2;68;68;68m▀[0m[7m[38;2;68;68;68m [0m[38;2;68;68;68m[48;2;67;67;67m▀[0m[38;2;68;68;68m[48;2;67;67;67m▀[0m[38;2;67;67;67m[48;2;66;66;66m▀[0m[38;2;67;67;67m[48;2;66;66;66m▀[0m[7m[38;2;66;66;66m [0m[38;2;66;66;66m[48;2;65;65;65m▀[0m[38;2;66;66;66m[48;2;65;65;65m▀[0m[7m[38;2;65;65;65m [0m[38;2;65;65;65m[48;2;64;64;64m▀[0m[38;2;65;65;65m[48;2;64;64;64m▀[0m[7m[38;2;64;64;64m [0m[38;2;64;64;64m[48;2;63;63;63m▀[0m[38;2;64;64;64m[48;2;63;63;63m▀[0m[7m[38;2;63;63;63m [0m [0m [0m [0m [0m [0m [0m [0m
|
||||
[0m [0m [0m [0m [0m [0m [0m [0m[7m[38;2;74;74;74m [0m[38;2;74;74;74m[48;2;73;73;73m▀[0m[38;2;74;74;74m[48;2;73;73;73m▀[0m[38;2;72;72;72m[48;2;71;71;71m▀[0m[38;2;70;70;70m[48;2;97;97;97m▀[0m[38;2;138;138;138m[48;2;229;229;229m▀[0m[38;2;229;229;229m[48;2;228;228;228m▀[0m[38;2;203;203;203m[48;2;226;226;226m▀[0m[38;2;84;84;84m[48;2;200;200;200m▀[0m[38;2;70;70;70m[48;2;82;82;82m▀[0m[38;2;71;71;71m[48;2;69;69;69m▀[0m[7m[38;2;70;70;70m [0m[7m[38;2;70;70;70m [0m[38;2;70;70;70m[48;2;69;69;69m▀[0m[7m[38;2;69;69;69m [0m[7m[38;2;69;69;69m [0m[38;2;69;69;69m[48;2;68;68;68m▀[0m[7m[38;2;68;68;68m [0m[38;2;68;68;68m[48;2;67;67;67m▀[0m[38;2;68;68;68m[48;2;67;67;67m▀[0m[7m[38;2;67;67;67m [0m[38;2;67;67;67m[48;2;66;66;66m▀[0m[38;2;67;67;67m[48;2;66;66;66m▀[0m[7m[38;2;66;66;66m [0m[38;2;66;66;66m[48;2;65;65;65m▀[0m[38;2;66;66;66m[48;2;65;65;65m▀[0m[7m[38;2;65;65;65m [0m[38;2;65;65;65m[48;2;64;64;64m▀[0m[38;2;65;65;65m[48;2;64;64;64m▀[0m[7m[38;2;64;64;64m [0m[38;2;64;64;64m[48;2;63;63;63m▀[0m[7m[38;2;63;63;63m [0m[7m[38;2;63;63;63m [0m[38;2;63;63;63m[48;2;62;62;62m▀[0m[7m[38;2;62;62;62m [0m[7m[38;2;62;62;62m [0m [0m [0m [0m [0m [0m [0m [0m
|
||||
[0m [0m [0m [0m [0m [0m [0m [0m[7m[38;2;73;73;73m [0m[38;2;73;73;73m[48;2;72;72;72m▀[0m[7m[38;2;71;71;71m [0m[38;2;69;69;69m[48;2;68;68;68m▀[0m[38;2;94;94;94m[48;2;62;62;62m▀[0m[38;2;227;227;227m[48;2;130;130;130m▀[0m[38;2;226;226;226m[48;2;224;224;224m▀[0m[38;2;224;224;224m[48;2;222;222;222m▀[0m[38;2;223;223;223m[48;2;221;221;221m▀[0m[38;2;197;197;197m[48;2;220;220;220m▀[0m[38;2;81;81;81m[48;2;195;195;195m▀[0m[38;2;68;68;68m[48;2;80;80;80m▀[0m[38;2;69;69;69m[48;2;67;67;67m▀[0m[38;2;69;69;69m[48;2;68;68;68m▀[0m[7m[38;2;68;68;68m [0m[38;2;68;68;68m[48;2;67;67;67m▀[0m[38;2;68;68;68m[48;2;67;67;67m▀[0m[7m[38;2;67;67;67m [0m[38;2;67;67;67m[48;2;66;66;66m▀[0m[7m[38;2;66;66;66m [0m[38;2;66;66;66m[48;2;65;65;65m▀[0m[38;2;66;66;66m[48;2;65;65;65m▀[0m[7m[38;2;65;65;65m [0m[38;2;65;65;65m[48;2;64;64;64m▀[0m[38;2;65;65;65m[48;2;64;64;64m▀[0m[7m[38;2;64;64;64m [0m[38;2;64;64;64m[48;2;63;63;63m▀[0m[38;2;64;64;64m[48;2;63;63;63m▀[0m[7m[38;2;63;63;63m [0m[38;2;63;63;63m[48;2;62;62;62m▀[0m[38;2;63;63;63m[48;2;62;62;62m▀[0m[7m[38;2;62;62;62m [0m[38;2;62;62;62m[48;2;61;61;61m▀[0m[38;2;62;62;62m[48;2;61;61;61m▀[0m[7m[38;2;61;61;61m [0m[38;2;61;61;61m[48;2;60;60;60m▀[0m [0m [0m [0m [0m [0m [0m [0m
|
||||
[0m [0m [0m [0m [0m [0m [0m [0m[38;2;72;72;72m[48;2;71;71;71m▀[0m[38;2;72;72;72m[48;2;71;71;71m▀[0m[7m[38;2;70;70;70m [0m[7m[38;2;69;69;69m [0m[38;2;64;64;64m[48;2;66;66;66m▀[0m[38;2;58;58;58m[48;2;62;62;62m▀[0m[38;2;127;127;127m[48;2;57;57;57m▀[0m[38;2;220;220;220m[48;2;125;125;125m▀[0m[38;2;219;219;219m[48;2;217;217;217m▀[0m[38;2;218;218;218m[48;2;216;216;216m▀[0m[38;2;217;217;217m[48;2;215;215;215m▀[0m[38;2;192;192;192m[48;2;214;214;214m▀[0m[38;2;79;79;79m[48;2;195;195;195m▀[0m[38;2;66;66;66m[48;2;83;83;83m▀[0m[38;2;67;67;67m[48;2;65;65;65m▀[0m[38;2;67;67;67m[48;2;66;66;66m▀[0m[7m[38;2;66;66;66m [0m[38;2;66;66;66m[48;2;65;65;65m▀[0m[38;2;66;66;66m[48;2;65;65;65m▀[0m[7m[38;2;65;65;65m [0m[38;2;65;65;65m[48;2;64;64;64m▀[0m[38;2;65;65;65m[48;2;64;64;64m▀[0m[7m[38;2;64;64;64m [0m[38;2;64;64;64m[48;2;63;63;63m▀[0m[38;2;64;64;64m[48;2;63;63;63m▀[0m[7m[38;2;63;63;63m [0m[38;2;63;63;63m[48;2;62;62;62m▀[0m[7m[38;2;62;62;62m [0m[7m[38;2;62;62;62m [0m[38;2;62;62;62m[48;2;61;61;61m▀[0m[7m[38;2;61;61;61m [0m[38;2;61;61;61m[48;2;60;60;60m▀[0m[38;2;61;61;61m[48;2;60;60;60m▀[0m[7m[38;2;60;60;60m [0m[38;2;60;60;60m[48;2;59;59;59m▀[0m[38;2;60;60;60m[48;2;59;59;59m▀[0m [0m [0m [0m [0m [0m [0m [0m
|
||||
[0m [0m [0m [0m [0m [0m [0m [0m[38;2;71;71;71m[48;2;70;70;70m▀[0m[7m[38;2;70;70;70m [0m[38;2;70;70;70m[48;2;69;69;69m▀[0m[38;2;70;70;70m[48;2;69;69;69m▀[0m[38;2;68;68;68m[48;2;69;69;69m▀[0m[38;2;66;66;66m[48;2;67;67;67m▀[0m[38;2;62;62;62m[48;2;64;64;64m▀[0m[38;2;56;56;56m[48;2;60;60;60m▀[0m[38;2;123;123;123m[48;2;62;62;62m▀[0m[38;2;214;214;214m[48;2;161;161;161m▀[0m[38;2;213;213;213m[48;2;211;211;211m▀[0m[38;2;212;212;212m[48;2;210;210;210m▀[0m[38;2;211;211;211m[48;2;209;209;209m▀[0m[38;2;192;192;192m[48;2;208;208;208m▀[0m[38;2;74;74;74m[48;2;84;84;84m▀[0m[38;2;65;65;65m[48;2;64;64;64m▀[0m[38;2;65;65;65m[48;2;64;64;64m▀[0m[38;2;65;65;65m[48;2;64;64;64m▀[0m[7m[38;2;64;64;64m [0m[38;2;64;64;64m[48;2;63;63;63m▀[0m[38;2;64;64;64m[48;2;63;63;63m▀[0m[7m[38;2;63;63;63m [0m[38;2;63;63;63m[48;2;62;62;62m▀[0m[38;2;63;63;63m[48;2;62;62;62m▀[0m[7m[38;2;62;62;62m [0m[38;2;62;62;62m[48;2;61;61;61m▀[0m[38;2;62;62;62m[48;2;61;61;61m▀[0m[7m[38;2;61;61;61m [0m[38;2;61;61;61m[48;2;60;60;60m▀[0m[7m[38;2;60;60;60m [0m[7m[38;2;60;60;60m [0m[38;2;60;60;60m[48;2;59;59;59m▀[0m[7m[38;2;59;59;59m [0m[7m[38;2;59;59;59m [0m[38;2;59;59;59m[48;2;58;58;58m▀[0m[7m[38;2;58;58;58m [0m [0m [0m [0m [0m [0m [0m [0m
|
||||
[0m [0m [0m [0m [0m [0m [0m [0m[38;2;70;70;70m[48;2;69;69;69m▀[0m[7m[38;2;69;69;69m [0m[38;2;69;69;69m[48;2;68;68;68m▀[0m[7m[38;2;68;68;68m [0m[38;2;68;68;68m[48;2;67;67;67m▀[0m[38;2;67;67;67m[48;2;65;65;65m▀[0m[38;2;64;64;64m[48;2;72;72;72m▀[0m[38;2;69;69;69m[48;2;151;151;151m▀[0m[38;2;140;140;140m[48;2;160;160;160m▀[0m[38;2;139;139;139m[48;2;150;150;150m▀[0m[38;2;165;165;165m[48;2;137;137;137m▀[0m[38;2;208;208;208m[48;2;154;154;154m▀[0m[38;2;207;207;207m[48;2;116;116;116m▀[0m[38;2;132;132;132m[48;2;55;55;55m▀[0m[38;2;59;59;59m[48;2;60;60;60m▀[0m[38;2;63;63;63m[48;2;62;62;62m▀[0m[38;2;64;64;64m[48;2;63;63;63m▀[0m[38;2;64;64;64m[48;2;63;63;63m▀[0m[7m[38;2;63;63;63m [0m[38;2;63;63;63m[48;2;62;62;62m▀[0m[7m[38;2;62;62;62m [0m[7m[38;2;62;62;62m [0m[38;2;62;62;62m[48;2;61;61;61m▀[0m[7m[38;2;61;61;61m [0m[38;2;61;61;61m[48;2;60;60;60m▀[0m[38;2;61;61;61m[48;2;60;60;60m▀[0m[7m[38;2;60;60;60m [0m[38;2;60;60;60m[48;2;59;59;59m▀[0m[38;2;60;60;60m[48;2;59;59;59m▀[0m[7m[38;2;59;59;59m [0m[38;2;59;59;59m[48;2;58;58;58m▀[0m[38;2;59;59;59m[48;2;58;58;58m▀[0m[7m[38;2;58;58;58m [0m[38;2;58;58;58m[48;2;57;57;57m▀[0m[38;2;58;58;58m[48;2;57;57;57m▀[0m[7m[38;2;57;57;57m [0m [0m [0m [0m [0m [0m [0m [0m
|
||||
[0m [0m [0m [0m [0m [0m [0m [0m[7m[38;2;68;68;68m [0m[38;2;68;68;68m[48;2;67;67;67m▀[0m[38;2;68;68;68m[48;2;67;67;67m▀[0m[38;2;67;67;67m[48;2;65;65;65m▀[0m[38;2;65;65;65m[48;2;69;69;69m▀[0m[38;2;72;72;72m[48;2;152;152;152m▀[0m[38;2;154;154;154m[48;2;168;168;168m▀[0m[38;2;168;168;168m[48;2;165;165;165m▀[0m[38;2;163;163;163m[48;2;162;162;162m▀[0m[38;2;156;156;156m[48;2;159;159;159m▀[0m[38;2;148;148;148m[48;2;97;97;97m▀[0m[38;2;93;93;93m[48;2;55;55;55m▀[0m[38;2;54;54;54m[48;2;58;58;58m▀[0m[38;2;58;58;58m[48;2;61;61;61m▀[0m[38;2;61;61;61m[48;2;62;62;62m▀[0m[38;2;63;63;63m[48;2;62;62;62m▀[0m[38;2;63;63;63m[48;2;61;61;61m▀[0m[38;2;62;62;62m[48;2;108;108;108m▀[0m[38;2;62;62;62m[48;2;144;144;144m▀[0m[38;2;61;61;61m[48;2;143;143;143m▀[0m[38;2;61;61;61m[48;2;143;143;143m▀[0m[38;2;61;61;61m[48;2;141;141;141m▀[0m[38;2;60;60;60m[48;2;140;140;140m▀[0m[38;2;60;60;60m[48;2;140;140;140m▀[0m[38;2;60;60;60m[48;2;138;138;138m▀[0m[38;2;59;59;59m[48;2;138;138;138m▀[0m[38;2;59;59;59m[48;2;137;137;137m▀[0m[38;2;58;58;58m[48;2;136;136;136m▀[0m[38;2;58;58;58m[48;2;100;100;100m▀[0m[38;2;58;58;58m[48;2;56;56;56m▀[0m[38;2;58;58;58m[48;2;57;57;57m▀[0m[7m[38;2;57;57;57m [0m[38;2;57;57;57m[48;2;56;56;56m▀[0m[38;2;57;57;57m[48;2;56;56;56m▀[0m[7m[38;2;56;56;56m [0m[38;2;56;56;56m[48;2;55;55;55m▀[0m [0m [0m [0m [0m [0m [0m [0m
|
||||
[0m [0m [0m [0m [0m [0m [0m [0m[38;2;67;67;67m[48;2;66;66;66m▀[0m[38;2;67;67;67m[48;2;66;66;66m▀[0m[38;2;66;66;66m[48;2;65;65;65m▀[0m[38;2;63;63;63m[48;2;62;62;62m▀[0m[38;2;83;83;83m[48;2;62;62;62m▀[0m[38;2;166;166;166m[48;2;145;145;145m▀[0m[38;2;164;164;164m[48;2;161;161;161m▀[0m[38;2;162;162;162m[48;2;158;158;158m▀[0m[38;2;160;160;160m[48;2;97;97;97m▀[0m[38;2;98;98;98m[48;2;53;53;53m▀[0m[38;2;54;54;54m[48;2;57;57;57m▀[0m[38;2;58;58;58m[48;2;60;60;60m▀[0m[7m[38;2;61;61;61m [0m[7m[38;2;62;62;62m [0m[38;2;62;62;62m[48;2;61;61;61m▀[0m[38;2;61;61;61m[48;2;59;59;59m▀[0m[38;2;56;56;56m[48;2;53;53;53m▀[0m[7m[38;2;226;226;226m [0m[38;2;227;227;227m[48;2;224;224;224m▀[0m[38;2;225;225;225m[48;2;223;223;223m▀[0m[38;2;224;224;224m[48;2;221;221;221m▀[0m[38;2;222;222;222m[48;2;220;220;220m▀[0m[38;2;221;221;221m[48;2;218;218;218m▀[0m[38;2;219;219;219m[48;2;217;217;217m▀[0m[38;2;218;218;218m[48;2;215;215;215m▀[0m[38;2;216;216;216m[48;2;214;214;214m▀[0m[38;2;215;215;215m[48;2;212;212;212m▀[0m[38;2;213;213;213m[48;2;211;211;211m▀[0m[38;2;210;210;210m[48;2;209;209;209m▀[0m[38;2;53;53;53m[48;2;50;50;50m▀[0m[38;2;56;56;56m[48;2;55;55;55m▀[0m[7m[38;2;56;56;56m [0m[38;2;56;56;56m[48;2;55;55;55m▀[0m[7m[38;2;55;55;55m [0m[38;2;55;55;55m[48;2;54;54;54m▀[0m[38;2;55;55;55m[48;2;54;54;54m▀[0m [0m [0m [0m [0m [0m [0m [0m
|
||||
[0m [0m [0m [0m [0m [0m [0m [0m[38;2;66;66;66m[48;2;65;65;65m▀[0m[7m[38;2;65;65;65m [0m[7m[38;2;64;64;64m [0m[7m[38;2;62;62;62m [0m[38;2;57;57;57m[48;2;59;59;59m▀[0m[38;2;60;60;60m[48;2;56;56;56m▀[0m[38;2;100;100;100m[48;2;53;53;53m▀[0m[38;2;85;85;85m[48;2;55;55;55m▀[0m[38;2;53;53;53m[48;2;57;57;57m▀[0m[38;2;57;57;57m[48;2;60;60;60m▀[0m[38;2;59;59;59m[48;2;61;61;61m▀[0m[7m[38;2;61;61;61m [0m[38;2;62;62;62m[48;2;61;61;61m▀[0m[7m[38;2;61;61;61m [0m[38;2;61;61;61m[48;2;60;60;60m▀[0m[7m[38;2;58;58;58m [0m[38;2;52;52;52m[48;2;54;54;54m▀[0m[38;2;182;182;182m[48;2;46;46;46m▀[0m[38;2;222;222;222m[48;2;43;43;43m▀[0m[38;2;220;220;220m[48;2;41;41;41m▀[0m[38;2;219;219;219m[48;2;41;41;41m▀[0m[38;2;217;217;217m[48;2;41;41;41m▀[0m[38;2;216;216;216m[48;2;40;40;40m▀[0m[38;2;214;214;214m[48;2;40;40;40m▀[0m[38;2;212;212;212m[48;2;40;40;40m▀[0m[38;2;211;211;211m[48;2;40;40;40m▀[0m[38;2;209;209;209m[48;2;40;40;40m▀[0m[38;2;208;208;208m[48;2;40;40;40m▀[0m[38;2;169;169;169m[48;2;43;43;43m▀[0m[38;2;48;48;48m[48;2;50;50;50m▀[0m[7m[38;2;53;53;53m [0m[38;2;55;55;55m[48;2;54;54;54m▀[0m[38;2;55;55;55m[48;2;54;54;54m▀[0m[7m[38;2;54;54;54m [0m[38;2;54;54;54m[48;2;53;53;53m▀[0m[38;2;54;54;54m[48;2;53;53;53m▀[0m [0m [0m [0m [0m [0m [0m [0m
|
||||
[0m [0m [0m [0m [0m [0m [0m [0m[38;2;65;65;65m[48;2;59;59;59m▀[0m[7m[38;2;64;64;64m [0m[38;2;64;64;64m[48;2;63;63;63m▀[0m[7m[38;2;63;63;63m [0m[38;2;61;61;61m[48;2;63;63;63m▀[0m[38;2;60;60;60m[48;2;61;61;61m▀[0m[38;2;59;59;59m[48;2;61;61;61m▀[0m[38;2;59;59;59m[48;2;61;61;61m▀[0m[38;2;60;60;60m[48;2;61;61;61m▀[0m[7m[38;2;61;61;61m [0m[38;2;61;61;61m[48;2;60;60;60m▀[0m[38;2;61;61;61m[48;2;60;60;60m▀[0m[7m[38;2;60;60;60m [0m[38;2;60;60;60m[48;2;59;59;59m▀[0m[38;2;60;60;60m[48;2;59;59;59m▀[0m[38;2;58;58;58m[48;2;59;59;59m▀[0m[38;2;56;56;56m[48;2;57;57;57m▀[0m[38;2;53;53;53m[48;2;55;55;55m▀[0m[38;2;50;50;50m[48;2;54;54;54m▀[0m[38;2;50;50;50m[48;2;53;53;53m▀[0m[38;2;49;49;49m[48;2;53;53;53m▀[0m[38;2;49;49;49m[48;2;53;53;53m▀[0m[38;2;49;49;49m[48;2;52;52;52m▀[0m[38;2;48;48;48m[48;2;52;52;52m▀[0m[38;2;48;48;48m[48;2;52;52;52m▀[0m[38;2;47;47;47m[48;2;51;51;51m▀[0m[38;2;47;47;47m[48;2;51;51;51m▀[0m[38;2;48;48;48m[48;2;52;52;52m▀[0m[38;2;49;49;49m[48;2;52;52;52m▀[0m[38;2;51;51;51m[48;2;53;53;53m▀[0m[7m[38;2;53;53;53m [0m[38;2;54;54;54m[48;2;53;53;53m▀[0m[7m[38;2;53;53;53m [0m[38;2;53;53;53m[48;2;52;52;52m▀[0m[38;2;53;53;53m[48;2;52;52;52m▀[0m[38;2;52;52;52m[48;2;48;48;48m▀[0m [0m [0m [0m [0m [0m [0m [0m
|
||||
[0m [0m [0m [0m [0m [0m [0m [0m [0m [0m [0m [0m [0m [0m [0m [0m [0m [0m [0m [0m [0m [0m [0m [0m [0m [0m [0m [0m [0m [0m [0m [0m [0m [0m [0m [0m [0m [0m [0m [0m [0m [0m [0m [0m [0m [0m [0m [0m [0m [0m [0m
|
||||
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 5.5 KiB |
@@ -1,146 +0,0 @@
|
||||
---
|
||||
author: Mike Griese @zadjii-msft
|
||||
created on: 2020-07-31
|
||||
last updated: 2020-08-03
|
||||
issue id: #1337
|
||||
---
|
||||
# Per-Profile Tab Colors
|
||||
|
||||
## Abstract
|
||||
|
||||
This spec describes a way to specify tab colors in a profile in a way that will
|
||||
be forward compatible with theming the Terminal. This spec will be largely
|
||||
dedicated to the design of a single setting, but within the context of theming.
|
||||
|
||||
## Inspiration
|
||||
|
||||
Following the addition of the Tab Color Picker in [#3789], we've had numerous
|
||||
requests for the ability to set the color of a tab directly within a profile.
|
||||
While largely we're tracking theming in [#3327], including the specification of
|
||||
a tab color, the theming spec ([#5772] )is very large and will take a while to
|
||||
revise and approve. This spec is intended to pull a single point out from that
|
||||
spec to make it more easily reviewable, and implement it in a way that will
|
||||
continue working when we add support for themes in the future.
|
||||
|
||||
## Solution Design
|
||||
|
||||
To enable per-profile tab colors, we'll add a single setting: `tabColor`. For
|
||||
now<sup>[[1](#user-content-footnote-1)]</sup>, this setting will accept any
|
||||
`#rrggbb` color string.
|
||||
|
||||
Since each profile creates a `Pane` with a `TermControl`, we'll need to store
|
||||
this color not in the `Tab`, but somewhere below `Pane`, so that when you switch
|
||||
between Panes in a tab with different `tabColor`s, the color will update
|
||||
automatically. When a new `TermControl` is created, we'll store this color in the
|
||||
`TermControl`'s `Terminal` core. This is to support the future possibility of
|
||||
setting the tab color via VT sequences.
|
||||
|
||||
A Tab's color will be the result of layering a variety of sources, from the bottom up:
|
||||
|
||||
Color | | Set by
|
||||
-- | -- | --
|
||||
Runtime Color | _optional_ |Color Picker / `setTabColor` action
|
||||
Control Tab Color | _optional_ | Profile's `tabColor`, or a color set by VT
|
||||
Theme Tab Background | _optional_ | `tab.backgroundColor` in the theme
|
||||
Tab Default Color | **default** | TabView in XAML
|
||||
|
||||
Some examples:
|
||||
* **Scenario 1**: The user has set `"tabColor": "#ff0000"` in their profile.
|
||||
When they create tabs with that profile, instead of appearing in the default
|
||||
color for the TabView, they'll be `#ff0000`.
|
||||
* **Scenario 2**: The user has set `"tabColor": "#ff0000"` in their profile.
|
||||
When they try to set the color for that tab (with the color picker) to
|
||||
`#0000ff`, the tab's color is updated to reflect this new blue color. When
|
||||
they clear the runtime color (with the color picker), the tab will return to
|
||||
`#ff0000`.
|
||||
* **Scenario 3**: The user has two profiles with colors set, one to `"tabColor":
|
||||
"#ff0000"`, and the other with `"tabColor": "#00ff00"`. If they open these
|
||||
profiles in two panes side-by side, the tab's color will update to reflect the
|
||||
color from the currently-focused control.
|
||||
* **Scenario 4**: The user has two profiles with colors set, one to `"tabColor":
|
||||
"#ff0000"`, and the other with `"tabColor": "#00ff00"`. If they open these
|
||||
profiles in two panes side-by side, and try to set the color for that tab
|
||||
(with the color picker) to `#0000ff`, the tab's color is updated to reflect
|
||||
this new blue color. Regardless of which pane is focused, the tab will be
|
||||
blue.
|
||||
* **Scenario 5**: The user has set `"tabColor": "#ff0000"` in their profile
|
||||
("Profile A"), and `"tab.backgroundColor": "#00ff00"`in their theme. When they
|
||||
create tabs with "Profile A", the tabs will appear red. Other tabs (for
|
||||
profiles without `tabColor` set) will appear green, using the color from the
|
||||
theme.
|
||||
|
||||
|
||||
## UI/UX Design
|
||||
|
||||
In general, this is going to look exactly like the colored tabs look now.
|
||||
|
||||

|
||||
|
||||
## Capabilities
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td><strong>Accessibility</strong></td>
|
||||
<td>
|
||||
N/A
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Security</strong></td>
|
||||
<td>
|
||||
N/A
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Reliability</strong></td>
|
||||
<td>
|
||||
No expected change
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Compatibility</strong></td>
|
||||
<td>
|
||||
This entire spec outlines how this feature is designed with a emphasis on future
|
||||
compatibility. As such, there are no expected regressions in the future when we
|
||||
do add support for themes.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Performance, Power, and Efficiency</strong></td>
|
||||
<td>
|
||||
No expected change
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
## Potential Issues
|
||||
|
||||
None expected.
|
||||
|
||||
## Footnotes
|
||||
|
||||
<a id="footnote-1"><a>[1]: When full theming support is added, themes will
|
||||
provide support for setting colors as one of a variety of values:
|
||||
|
||||
* An `#rrggbb` string
|
||||
* The system accent color
|
||||
* The current background color of the Terminal
|
||||
* A value from a given resource key from XAML
|
||||
|
||||
When support for these other types of "smart" colors is added, then the profile
|
||||
`tabColor` setting will also gracefully accept these values.
|
||||
|
||||
## Future considerations
|
||||
|
||||
* It's not out of the realm of possibility that someone might want to color each
|
||||
_pane_'s color at runtime. In that case, the runtime color would be stored in
|
||||
the `Pane`, not the `Tab`.
|
||||
|
||||
|
||||
|
||||
<!-- Footnotes -->
|
||||
|
||||
[#1337]: https://github.com/microsoft/terminal/issues/1337
|
||||
[#3789]: https://github.com/microsoft/terminal/issues/3789
|
||||
[#3327]: https://github.com/microsoft/terminal/issues/3327
|
||||
[#5772]: https://github.com/microsoft/terminal/pull/5772
|
||||
|
Before Width: | Height: | Size: 816 KiB |
|
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 34 KiB |
|
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 32 KiB |
|
Before Width: | Height: | Size: 7.2 KiB After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 75 KiB After Width: | Height: | Size: 92 KiB |
|
Before Width: | Height: | Size: 253 KiB After Width: | Height: | Size: 345 KiB |
|
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 34 KiB |
|
Before Width: | Height: | Size: 222 KiB |
|
Before Width: | Height: | Size: 233 KiB |
@@ -1,146 +0,0 @@
|
||||
---
|
||||
authors: Carlos Zamora (@carlos-zamora) and Kayla Cinnamon (@cinnamon-msft)
|
||||
created on: 2020-11-10
|
||||
last updated: 2020-11-19
|
||||
issue id: 1564
|
||||
---
|
||||
|
||||
# Cascading Settings
|
||||
|
||||
## Abstract
|
||||
|
||||
Windows Terminal's settings model adheres to a cascading settings architecture. This allows a settings object to be defined incrementally across multiple layers of declarations. The value for any global setting like `copyOnSelect`, for example, is set to your settings.json value if one is defined, otherwise defaults.json, and otherwise a system set value. Profiles in particular are more complicated in that they must also take into account the values in `profiles.defaults` and dynamic profile generators.
|
||||
|
||||
This spec explores how to represent this feature in the Settings UI.
|
||||
|
||||
## Inspiration
|
||||
|
||||
Cascading settings (and `profiles.defaults` by extension) provide some major benefits:
|
||||
1. opt-in behavior for settings values provided in-box (i.e. reset to default)
|
||||
2. easy way to apply a setting to all your profiles
|
||||
3. (possible future feature) simple way to base a profile off of another profile
|
||||
|
||||
The following terminal emulators approach this issue as follows.
|
||||
| Terminal Emulator(s) | Relevant Features/Approach |
|
||||
|--|--|
|
||||
| ConEmu, Cmder | "Clone" a separate profile |
|
||||
| Fluent Terminal | "Restore Defaults" button on each page |
|
||||
| iTerm2 | "Bulk Copy from Selected Profile..." and "Duplicate Profile" |
|
||||
|
||||
Other Settings UIs have approached this issue as follows:
|
||||
| Project | Relevant Approach |
|
||||
|--|--|
|
||||
| Visual Studio | Present a dropdown with your options. An extra "\<inherit\>" option is shown to inherit a value from another place. |
|
||||
|
||||
## Solution Design
|
||||
|
||||
The XAML implementation will consist of introducing a `ContentControl` for each setting. The `ContentControl` simply wraps the XAML control used for a setting, then adds the chosen UI approach below.
|
||||
|
||||
The `ContentControl` will take advantage of the following TerminalSettingsModel APIs for each setting:
|
||||
```c++
|
||||
// Note: String and "Name" are replaced for each setting
|
||||
bool HasName();
|
||||
void ClearName();
|
||||
String Name();
|
||||
void Name(String val);
|
||||
```
|
||||
|
||||
## UI/UX Design Proposals
|
||||
|
||||
The proposals below will be used in combination with each other.
|
||||
|
||||
### 1: Text under a setting control
|
||||
|
||||
This design renames the "Global" page under Profiles to "Base layer". Settings that override those in profile.defaults will get text under the control saying "Overrides Base layer.". Next to the titles of controls that override the base layer is a reset button with a tooltip that says "Reset".
|
||||
|
||||

|
||||
|
||||
### Add New --> Duplicate Profile
|
||||
|
||||
The Add new profile button in the navigation menu would take you to a new page. This page will have radio buttons listing your profiles along with a default settings option. The user can choose to either duplicate a profile or create a new one from the default settings. Once the user makes a selection, the settings UI will take them to their new profile page. The fields on that profile page will be filled according to which profile selection the user made.
|
||||
|
||||

|
||||
|
||||
### Reset Profile button
|
||||
|
||||
On the Advanced pivot of a profile's page, there will be a button at the bottom for resetting a profile called "Reset to default settings". This button will remove the user's custom settings inside this profile's object and reset it to defaults, prioritizing profile.defaults then defaults.json.
|
||||
|
||||
### "Apply to all profiles" button
|
||||
|
||||
A way we could apply settings to all profiles is by adding a "Copy settings to..." button to the Advanced page of each profile. This button will open a content dialog with a tree view listing every profile setting. The user can select which settings they would like to copy over to another profile. At the bottom of the content dialog will list the user's profiles with checkboxes, allowing them to pick which profiles they'd like to copy settings to.
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
## Previously considered ideas
|
||||
|
||||
These ideas were considered however we will not be moving forward with them.
|
||||
|
||||
### 1: \<inherit\> option
|
||||
|
||||
Each setting is an Editable ComboBox (except for boolean and enumerable settings). For booleans, the items will be Enabled and Disabled in a regular ComboBox. Enumerable settings will have their options listed in a regular ComboBox. For integers, most commonly used numbers will be listed.
|
||||
|
||||

|
||||
|
||||
**Pros**
|
||||
|
||||
- Doesn't clutter the screen.
|
||||
|
||||
**Cons**
|
||||
|
||||
- Every setting is a dropdown.
|
||||
|
||||
**Pitfalls**
|
||||
|
||||
- How will color pickers work with this scenario?
|
||||
|
||||
**Other considerations**
|
||||
|
||||
Each dropdown has either "inherit" or "custom". If the user selects "custom", the original control will appear (i.e. a color picker for colors or a number picker for integers).
|
||||
|
||||
This option was not chosen because it added too much overhead for changing a setting. For example, if you wanted to enable acrylic, you'd have to click the dropdown, select custom, watch the checkbox appear, and then select the checkbox.
|
||||
|
||||
### 2: Lock Button
|
||||
|
||||
Every setting will have a lock button next to it. If the lock is locked, that means the setting is being inherited from Global, and the control is disabled. If the user wants to edit the setting, they can click the lock, which will changed it to the unlocked lock icon, and the control will become enabled.
|
||||
|
||||

|
||||
|
||||
**Pros**
|
||||
|
||||
- Least amount of clutter on the screen while still keeping the original controls
|
||||
|
||||
**Cons**
|
||||
|
||||
- The lock concept is slightly confusing. Some may assume locking the setting means that it *won't* be inherited from Global and that it's "locked" to the profile. This is the opposite case for its current design. However, flipping the logic of the locks wouldn't make sense with an unlocked lock and a disabled control.
|
||||
|
||||
## Capabilities
|
||||
|
||||
### Accessibility
|
||||
|
||||
All of these additions to the settings UI will have to be accessibility tested.
|
||||
|
||||
### Security
|
||||
|
||||
These changes will not impact security.
|
||||
|
||||
### Reliability
|
||||
|
||||
These changes will not impact reliability.
|
||||
|
||||
### Compatibility
|
||||
|
||||
The partial parity with JSON route will give the settings UI a different compatibility from the JSON file itself. This is not necessarily a bad thing. The settings UI is intended to be a simplistic way for people to successfully edit their settings. If too many options are added to give it fully parity with JSON, it could compromise the simplistic benefit the settings UI provides.
|
||||
|
||||
### Performance, Power, and Efficiency
|
||||
|
||||
These changes will not impact performance, power, nor efficiency.
|
||||
|
||||
## Potential Issues
|
||||
|
||||
## Future considerations
|
||||
|
||||
When we add profile inheritance later, we can implement a layering page using a rearrangeable TreeView.
|
||||
|
||||
## Resources
|
||||
|
Before Width: | Height: | Size: 364 KiB |