Compare commits
105 Commits
dev/miniks
...
release-1.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3add65228d | ||
|
|
dae07a11b6 | ||
|
|
ae23d37dca | ||
|
|
5fdd1560fd | ||
|
|
3b876cc0b5 | ||
|
|
970d441a52 | ||
|
|
d86f5c1f74 | ||
|
|
84a5b668c1 | ||
|
|
ee83677122 | ||
|
|
2594edcec0 | ||
|
|
b092bdd42c | ||
|
|
2568a7cef2 | ||
|
|
bda1494394 | ||
|
|
118195a970 | ||
|
|
fd2b3f7632 | ||
|
|
2692874c71 | ||
|
|
a205f4547d | ||
|
|
944fddbbe9 | ||
|
|
677ab36a8a | ||
|
|
334e518773 | ||
|
|
9e9c0bea83 | ||
|
|
5f29f7603d | ||
|
|
ceb0551066 | ||
|
|
c17fdf07ee | ||
|
|
a315fd5f62 | ||
|
|
305946caa0 | ||
|
|
cadca1e839 | ||
|
|
c5e1bbdd25 | ||
|
|
817df81f48 | ||
|
|
a388adf50a | ||
|
|
5fb99657ea | ||
|
|
12c100cdb0 | ||
|
|
431559fd83 | ||
|
|
109f9c451f | ||
|
|
95b9b7c852 | ||
|
|
f3cdf6841f | ||
|
|
1228897071 | ||
|
|
0300b31117 | ||
|
|
368fa17c2d | ||
|
|
c7607417d3 | ||
|
|
204c9d2cf4 | ||
|
|
0c0830b2f2 | ||
|
|
e9a7b24296 | ||
|
|
624d07f283 | ||
|
|
c90ecf7263 | ||
|
|
79855b452b | ||
|
|
3f75788d29 | ||
|
|
1aff3bc216 | ||
|
|
015675d87c | ||
|
|
bdbd1bd307 | ||
|
|
5de4f98d7e | ||
|
|
6639df9edc | ||
|
|
930e24c6b3 | ||
|
|
341bb4f91e | ||
|
|
c0c23291b8 | ||
|
|
d5d2b7727f | ||
|
|
c173f20244 | ||
|
|
4eeaddc583 | ||
|
|
26ca73b823 | ||
|
|
e6aeb8a017 | ||
|
|
042cbea767 | ||
|
|
c2db1e95db | ||
|
|
990628a78b | ||
|
|
5b2fd70940 | ||
|
|
d1e58bd71e | ||
|
|
2ea4742f07 | ||
|
|
4daed9d946 | ||
|
|
2bf5d18c84 | ||
|
|
8e3f27f8fb | ||
|
|
1c97d20c13 | ||
|
|
ce4fd2970a | ||
|
|
242833f8b2 | ||
|
|
e21f9f5ac6 | ||
|
|
6d44e0d651 | ||
|
|
5a1c931f77 | ||
|
|
60437b890e | ||
|
|
fc9a46dbbd | ||
|
|
1fa3177f77 | ||
|
|
3f7f6ac34c | ||
|
|
d51d8dc768 | ||
|
|
1df3182865 | ||
|
|
b603929214 | ||
|
|
7e8600147e | ||
|
|
5a518e5e58 | ||
|
|
b3aab8c158 | ||
|
|
87004994f7 | ||
|
|
c095a678a5 | ||
|
|
84bda067c5 | ||
|
|
4a95d94c55 | ||
|
|
6928c5a885 | ||
|
|
7a75e508d6 | ||
|
|
16b8ea14d6 | ||
|
|
4f39e8e752 | ||
|
|
293ad2757b | ||
|
|
403b793179 | ||
|
|
ae550e0969 | ||
|
|
ccf9f03ed3 | ||
|
|
895ac06dbd | ||
|
|
00f5fbaf3d | ||
|
|
4099aacacb | ||
|
|
1ad7a25cb2 | ||
|
|
c1d27774b4 | ||
|
|
8eaaa8a2b7 | ||
|
|
90452664ff | ||
|
|
df7c3ccc3b |
12
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
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)
|
||||
2
.github/linters/.markdown-lint.yml
vendored
@@ -28,11 +28,13 @@ 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 #
|
||||
|
||||
51
.github/workflows/linter.yml
vendored
@@ -1,51 +0,0 @@
|
||||
---
|
||||
###########################
|
||||
###########################
|
||||
## Linter GitHub Actions ##
|
||||
###########################
|
||||
###########################
|
||||
name: Lint Code Base
|
||||
|
||||
#
|
||||
# Documentation:
|
||||
# https://help.github.com/en/articles/workflow-syntax-for-github-actions
|
||||
#
|
||||
|
||||
#############################
|
||||
# Start the job on all push #
|
||||
#############################
|
||||
on:
|
||||
pull_request:
|
||||
branches: [master]
|
||||
|
||||
###############
|
||||
# Set the Job #
|
||||
###############
|
||||
jobs:
|
||||
build:
|
||||
# Name the Job
|
||||
name: Lint Code Base
|
||||
# Set the agent to run on
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
##################
|
||||
# Load all steps #
|
||||
##################
|
||||
steps:
|
||||
##########################
|
||||
# Checkout the code base #
|
||||
##########################
|
||||
- name: Checkout Code
|
||||
uses: actions/checkout@v2
|
||||
|
||||
################################
|
||||
# Run Linter against code base #
|
||||
################################
|
||||
- name: Lint Code Base
|
||||
uses: github/super-linter@v3.10.0
|
||||
env:
|
||||
VALIDATE_ALL_CODEBASE: false
|
||||
DEFAULT_BRANCH: master
|
||||
MARKDOWN_CONFIG_FILE: .markdown-lint.yml
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
VALIDATE_EDITORCONFIG: false
|
||||
@@ -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/master/doc/bot.md) to help us automate common processes within our 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 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.
|
||||
|
||||
@@ -156,7 +156,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 master 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 main branch. Once merged, your PR will be automatically closed.
|
||||
|
||||
---
|
||||
|
||||
|
||||
43
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, or you may
|
||||
open source code available at [http://3rdpartysource.microsoft.com](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
|
||||
**Source**: [https://github.com/open-source-parsers/jsoncpp](https://github.com/open-source-parsers/jsoncpp)
|
||||
|
||||
### License
|
||||
|
||||
@@ -50,7 +50,7 @@ SOFTWARE.
|
||||
|
||||
## chromium/base/numerics
|
||||
|
||||
**Source**: https://github.com/chromium/chromium/tree/master/base/numerics
|
||||
**Source**: [https://github.com/chromium/chromium/tree/master/base/numerics](https://github.com/chromium/chromium/tree/master/base/numerics)
|
||||
|
||||
### License
|
||||
|
||||
@@ -86,7 +86,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
## kimwalisch/libpopcnt
|
||||
|
||||
**Source**: https://github.com/kimwalisch/libpopcnt
|
||||
**Source**: [https://github.com/kimwalisch/libpopcnt](https://github.com/kimwalisch/libpopcnt)
|
||||
|
||||
### License
|
||||
|
||||
@@ -122,7 +122,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
## dynamic_bitset
|
||||
|
||||
**Source**: https://github.com/pinam45/dynamic_bitset
|
||||
**Source**: [https://github.com/pinam45/dynamic_bitset](https://github.com/pinam45/dynamic_bitset)
|
||||
|
||||
### License
|
||||
|
||||
@@ -151,9 +151,9 @@ SOFTWARE.
|
||||
|
||||
```
|
||||
|
||||
## {fmt}
|
||||
## \{fmt\}
|
||||
|
||||
**Source**: https://github.com/fmtlib/fmt
|
||||
**Source**: [https://github.com/fmtlib/fmt](https://github.com/fmtlib/fmt)
|
||||
|
||||
### License
|
||||
|
||||
@@ -188,3 +188,32 @@ 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.
|
||||
|
||||
```
|
||||
|
||||
20
NuGet.Config
@@ -1,24 +1,14 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<packageSources>
|
||||
<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. -->
|
||||
<clear />
|
||||
<!-- Dependencies that we can turn on to force override for testing purposes before uploading. -->
|
||||
<!--<add key="Static Package Dependencies" value="dep\packages" />-->
|
||||
|
||||
<!-- Use our own NuGet Feed -->
|
||||
<add key="TerminalDependencies" value="https://pkgs.dev.azure.com/ms/terminal/_packaging/TerminalDependencies/nuget/v3/index.json" />
|
||||
|
||||
<!-- Temporarily? use the feeds from our friends in MUX for Helix test stuff -->
|
||||
<add key="dotnetfeed" value="https://dotnetfeed.blob.core.windows.net/dotnet-core/index.json" />
|
||||
<add key="dnceng" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/index.json" />
|
||||
<add key="MUX-Dependencies" value="https://pkgs.dev.azure.com/ms/microsoft-ui-xaml/_packaging/MUX-Dependencies/nuget/v3/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>
|
||||
|
||||
17
README.md
@@ -6,8 +6,8 @@ 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/master/src/tools/ColorTool)
|
||||
* [Sample projects](https://github.com/Microsoft/Terminal/tree/master/samples)
|
||||
* [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
|
||||
|
||||
Related repositories include:
|
||||
@@ -79,6 +79,7 @@ page](https://chocolatey.org/packages/microsoft-windows-terminal) and follow the
|
||||
release by installing the `windows-terminal` package:
|
||||
|
||||
```powershell
|
||||
scoop bucket add extras
|
||||
scoop install windows-terminal
|
||||
```
|
||||
|
||||
@@ -104,7 +105,7 @@ here](/doc/terminal-v2-roadmap.md) and will be updated as the project proceeds.
|
||||
|
||||
Project|Build Status
|
||||
---|---
|
||||
Terminal|[](https://dev.azure.com/ms/Terminal/_build?definitionId=136)
|
||||
Terminal|[](https://dev.azure.com/ms/terminal/_build?definitionId=136)
|
||||
ColorTool|
|
||||
|
||||
---
|
||||
@@ -240,7 +241,7 @@ enhance Windows Terminal\!
|
||||
|
||||
***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
|
||||
Guide](https://github.com/microsoft/terminal/blob/main/CONTRIBUTING.md) to
|
||||
help avoid any wasted or duplicate effort.
|
||||
|
||||
## Communicating with the Team
|
||||
@@ -339,10 +340,10 @@ Please review these brief docs below about our coding practices.
|
||||
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/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)
|
||||
* [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)
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -14,4 +14,4 @@ Support for Windows Terminal is limited to the resources listed above.
|
||||
[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/master/CONTRIBUTING.md
|
||||
[contributor]: https://github.com/microsoft/terminal/blob/main/CONTRIBUTING.md
|
||||
|
||||
@@ -2,7 +2,7 @@ trigger:
|
||||
batch: true
|
||||
branches:
|
||||
include:
|
||||
- master
|
||||
- main
|
||||
- feature/*
|
||||
paths:
|
||||
exclude:
|
||||
@@ -13,7 +13,7 @@ trigger:
|
||||
pr:
|
||||
branches:
|
||||
include:
|
||||
- master
|
||||
- main
|
||||
- feature/*
|
||||
paths:
|
||||
exclude:
|
||||
|
||||
@@ -8,7 +8,9 @@ jobs:
|
||||
variables:
|
||||
BuildConfiguration: AuditMode
|
||||
BuildPlatform: ${{ parameters.platform }}
|
||||
pool: { vmImage: windows-2019 }
|
||||
pool: "windevbuildagents"
|
||||
# The public pool is also an option!
|
||||
# pool: { vmImage: windows-2019 }
|
||||
|
||||
steps:
|
||||
- checkout: self
|
||||
|
||||
@@ -11,7 +11,9 @@ jobs:
|
||||
variables:
|
||||
BuildConfiguration: ${{ parameters.configuration }}
|
||||
BuildPlatform: ${{ parameters.platform }}
|
||||
pool: { vmImage: windows-2019 }
|
||||
pool: "windevbuildagents"
|
||||
# The public pool is also an option!
|
||||
# pool: { vmImage: windows-2019 }
|
||||
|
||||
steps:
|
||||
- template: build-console-steps.yml
|
||||
|
||||
@@ -41,9 +41,7 @@ steps:
|
||||
configuration: '$(BuildConfiguration)'
|
||||
msbuildArgs: "${{ parameters.additionalBuildArguments }}"
|
||||
clean: true
|
||||
# The build agents cannot currently support parallel build due to the
|
||||
# memory requirements of our PCH files.
|
||||
maximumCpuCount: false
|
||||
maximumCpuCount: true
|
||||
|
||||
- task: PowerShell@2
|
||||
displayName: 'Check MSIX for common regressions'
|
||||
|
||||
18
build/rules/Branding.targets
Normal file
@@ -0,0 +1,18 @@
|
||||
<?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>
|
||||
@@ -86,7 +86,7 @@ project from our `TerminalAppLib` project:
|
||||
duplicate type definitions)-->
|
||||
|
||||
<Reference Include="Microsoft.Terminal.Settings">
|
||||
<HintPath>$(SolutionDir)$(Platform)\$(Configuration)\TerminalSettings\Microsoft.Terminal.Settings.winmd</HintPath>
|
||||
<HintPath>$(OpenConsoleCommonOutDir)\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>$(SolutionDir)\$(Platform)\$(Configuration)\TerminalAppLib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalLibraryDirectories>$(OpenConsoleCommonOutDir)\TerminalAppLib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
|
||||
<AdditionalDependencies>TerminalAppLib.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
@@ -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 "$(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*" )
|
||||
(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*" )
|
||||
</Command>
|
||||
</PostBuildEvent>
|
||||
</ItemDefinitionGroup>
|
||||
@@ -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 "$(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*" )
|
||||
(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*" )
|
||||
</Command>
|
||||
</PostBuildEvent>
|
||||
</ItemDefinitionGroup>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"$id": "https://github.com/microsoft/terminal/blob/master/doc/cascadia/profiles.schema.json",
|
||||
"$id": "https://github.com/microsoft/terminal/blob/main/doc/cascadia/profiles.schema.json",
|
||||
"$schema": "https://json-schema.org/draft/2019-09/schema#",
|
||||
"title": "Microsoft's Windows Terminal Settings Profile Schema",
|
||||
"definitions": {
|
||||
@@ -66,6 +66,7 @@
|
||||
"paste",
|
||||
"prevTab",
|
||||
"renameTab",
|
||||
"openTabRenamer",
|
||||
"resetFontSize",
|
||||
"resizePane",
|
||||
"scrollDown",
|
||||
@@ -441,6 +442,38 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"ScrollUpAction": {
|
||||
"description": "Arguments for a scrollUp action",
|
||||
"allOf": [
|
||||
{ "$ref": "#/definitions/ShortcutAction" },
|
||||
{
|
||||
"properties": {
|
||||
"action": { "type": "string", "pattern": "scrollUp" },
|
||||
"rowsToScroll": {
|
||||
"type": ["integer", "null"],
|
||||
"default": null,
|
||||
"description": "Scroll up rowsToScroll lines. If no value is provided, use the system-level defaults."
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"ScrollDownAction": {
|
||||
"description": "Arguments for a scrollDown action",
|
||||
"allOf": [
|
||||
{ "$ref": "#/definitions/ShortcutAction" },
|
||||
{
|
||||
"properties": {
|
||||
"action": { "type": "string", "pattern": "scrollDown" },
|
||||
"rowsToScroll": {
|
||||
"type": ["integer", "null"],
|
||||
"default": null,
|
||||
"description": "Scroll down rowsToScroll lines. If no value is provided, use the system-level defaults."
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"Keybinding": {
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
@@ -462,6 +495,8 @@
|
||||
{ "$ref": "#/definitions/WtAction" },
|
||||
{ "$ref": "#/definitions/CloseOtherTabsAction" },
|
||||
{ "$ref": "#/definitions/CloseTabsAfterAction" },
|
||||
{ "$ref": "#/definitions/ScrollUpAction" },
|
||||
{ "$ref": "#/definitions/ScrollDownAction" },
|
||||
{ "type": "null" }
|
||||
]
|
||||
},
|
||||
@@ -650,8 +685,38 @@
|
||||
},
|
||||
"useTabSwitcher": {
|
||||
"default": true,
|
||||
"description": "When set to \"true\", the \"nextTab\" and \"prevTab\" commands will use the tab switcher UI.",
|
||||
"type": "boolean"
|
||||
"description": "Deprecated. Please use \"tabSwitcherMode\" instead.",
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "boolean"
|
||||
},
|
||||
{
|
||||
"enum": [
|
||||
"mru",
|
||||
"inOrder",
|
||||
"disabled"
|
||||
],
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"deprecated": true
|
||||
},
|
||||
"tabSwitcherMode": {
|
||||
"default": "inOrder",
|
||||
"description": "When set to \"true\" or \"mru\", the \"nextTab\" and \"prevTab\" commands will use the tab switcher UI, with most-recently-used ordering. When set to \"inOrder\", these actions will switch tabs in their current ordering. Set to \"false\" to disable the tab switcher.",
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "boolean"
|
||||
},
|
||||
{
|
||||
"enum": [
|
||||
"mru",
|
||||
"inOrder",
|
||||
"disabled"
|
||||
],
|
||||
"type": "string"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
@@ -688,7 +753,16 @@
|
||||
},
|
||||
"backgroundImage": {
|
||||
"description": "Sets the file location of the image to draw over the window background.",
|
||||
"type": ["string", "null"]
|
||||
"oneOf": [
|
||||
{
|
||||
"type": ["string", null]
|
||||
},
|
||||
{
|
||||
"enum": [
|
||||
"desktopWallpaper"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"backgroundImageAlignment": {
|
||||
"default": "center",
|
||||
|
||||
@@ -19,7 +19,7 @@ When creating a new DLL, it was really helpful to reference an existing DLL's `.
|
||||
- [ ] Add a `<Reference>` to `TerminalAppLib.vcxproj` similar to this:
|
||||
```
|
||||
<Reference Include="Microsoft.Terminal.NewDLL">
|
||||
<HintPath>$(_BinRoot)TerminalNewDLL\Microsoft.Terminal.NewDLL.winmd</HintPath>
|
||||
<HintPath>$(OpenConsoleCommonOutDir)\TerminalNewDLL\Microsoft.Terminal.NewDLL.winmd</HintPath>
|
||||
<IsWinMDFile>true</IsWinMDFile>
|
||||
<Private>false</Private>
|
||||
<CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>
|
||||
|
||||
|
Before Width: | Height: | Size: 78 KiB After Width: | Height: | Size: 77 KiB |
|
Before Width: | Height: | Size: 300 KiB After Width: | Height: | Size: 134 KiB |
|
Before Width: | Height: | Size: 110 KiB After Width: | Height: | Size: 101 KiB |
|
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 110 KiB After Width: | Height: | Size: 98 KiB |
|
Before Width: | Height: | Size: 130 KiB After Width: | Height: | Size: 117 KiB |
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 5.5 KiB After Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 21 KiB |
|
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 31 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 7.2 KiB |
|
Before Width: | Height: | Size: 92 KiB After Width: | Height: | Size: 75 KiB |
|
Before Width: | Height: | Size: 345 KiB After Width: | Height: | Size: 253 KiB |
|
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 23 KiB |
|
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 29 KiB |
|
Before Width: | Height: | Size: 274 KiB After Width: | Height: | Size: 233 KiB |
|
Before Width: | Height: | Size: 215 KiB After Width: | Height: | Size: 172 KiB |
|
Before Width: | Height: | Size: 216 KiB After Width: | Height: | Size: 173 KiB |
|
Before Width: | Height: | Size: 213 KiB After Width: | Height: | Size: 171 KiB |
|
Before Width: | Height: | Size: 211 KiB After Width: | Height: | Size: 170 KiB |
|
Before Width: | Height: | Size: 223 KiB After Width: | Height: | Size: 181 KiB |
|
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 46 KiB |
@@ -293,7 +293,7 @@ And assuming the user has bound:
|
||||
|
||||
<!-- Footnotes -->
|
||||
[#2046]: https://github.com/microsoft/terminal/issues/2046
|
||||
[Command Palette, Addendum 1]: https://github.com/microsoft/terminal/blob/master/doc/specs/%232046%20-%20Unified%20keybindings%20and%20commands%2C%20and%20synthesized%20action%20names.md
|
||||
[Command Palette, Addendum 1]: https://github.com/microsoft/terminal/blob/main/doc/specs/%232046%20-%20Unified%20keybindings%20and%20commands%2C%20and%20synthesized%20action%20names.md
|
||||
|
||||
[#3337]: https://github.com/microsoft/terminal/issues/3337
|
||||
[#6899]: https://github.com/microsoft/terminal/issues/6899
|
||||
|
||||
|
Before Width: | Height: | Size: 46 KiB After Width: | Height: | Size: 26 KiB |
@@ -605,4 +605,4 @@ as well as 3 schemes: "Scheme 1", "Scheme 2", and "Scheme 3".
|
||||
|
||||
|
||||
<!-- Footnotes -->
|
||||
[Command Palette Spec]: https://github.com/microsoft/terminal/blob/master/doc/specs/%232046%20-%20Command%20Palette.md
|
||||
[Command Palette Spec]: https://github.com/microsoft/terminal/blob/main/doc/specs/%232046%20-%20Command%20Palette.md
|
||||
|
||||
|
Before Width: | Height: | Size: 60 KiB After Width: | Height: | Size: 46 KiB |
|
Before Width: | Height: | Size: 41 KiB After Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 5.1 KiB |
|
Before Width: | Height: | Size: 67 KiB After Width: | Height: | Size: 10 KiB |
@@ -215,8 +215,8 @@ actions manually.
|
||||
the tab context menu or the control context menu.
|
||||
|
||||
<!-- Footnotes -->
|
||||
[Command Palette Spec]: https://github.com/microsoft/terminal/blob/master/doc/specs/%232046%20-%20Command%20Palette.md
|
||||
[New Tab Menu Customization Spec]: https://github.com/microsoft/terminal/blob/master/doc/specs/%231571%20-%20New%20Tab%20Menu%20Customization.md
|
||||
[Command Palette Spec]: https://github.com/microsoft/terminal/blob/main/doc/specs/%232046%20-%20Command%20Palette.md
|
||||
[New Tab Menu Customization Spec]: https://github.com/microsoft/terminal/blob/main/doc/specs/%231571%20-%20New%20Tab%20Menu%20Customization.md
|
||||
|
||||
[#1571]: https://github.com/microsoft/terminal/issues/1571
|
||||
[#1912]: https://github.com/microsoft/terminal/issues/1912
|
||||
|
||||
|
Before Width: | Height: | Size: 104 KiB After Width: | Height: | Size: 46 KiB |
|
Before Width: | Height: | Size: 130 KiB After Width: | Height: | Size: 50 KiB |
|
Before Width: | Height: | Size: 112 KiB After Width: | Height: | Size: 44 KiB |
|
Before Width: | Height: | Size: 55 KiB After Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 63 KiB After Width: | Height: | Size: 30 KiB |
@@ -78,13 +78,185 @@ This separation leaves `AppKeyBindings` with the responsibility of detecting and
|
||||
`KeyMapping` handles the (de)serialization and navigation of the key bindings.
|
||||
|
||||
|
||||
### Fallback Value
|
||||
|
||||
Cascading settings allows our settings model to be constructed in layers (i.e. settings.json values override defaults.json values). With the upcoming introduction of the Settings UI and serialization, it is important to know where a setting value comes from. Consider a Settings UI displaying the following information:
|
||||
```json
|
||||
// <profile>: <color scheme value>
|
||||
"defaults": "Solarized", // profiles.defaults
|
||||
"A": "Raspberry", // profile A
|
||||
"B": "Tango", // profile B
|
||||
"C": "Solarized" // profile C
|
||||
```
|
||||
If `profiles.defaults` gets changed to `"Tango"` via the Settings UI, it is unclear if profile C's value should be updated as well. We need profile C to record if it's value is inherited from profile.defaults or explicitly set by the user.
|
||||
|
||||
#### Object Model Inheritance
|
||||
|
||||
To start, each settings object will now have a `CreateChild()` function. For `GlobalAppSettings`, it will look something like this:
|
||||
```c++
|
||||
GlobalAppSettings GlobalAppSettings::CreateChild() const
|
||||
{
|
||||
GlobalAppSettings child {};
|
||||
child._parents.append(this);
|
||||
return child;
|
||||
}
|
||||
```
|
||||
`std::vector<T> _parents` serves as a reference for who to ask if a settings value was not provided by the user. `LaunchMode`, for example, will now have a getter/setter that looks similar to this:
|
||||
```c++
|
||||
// _LaunchMode will now be a std::optional<LaunchMode> instead of a LaunchMode
|
||||
// - std::nullopt will mean that there is no user-set value
|
||||
// - otherwise, the value was explicitly set by the user
|
||||
|
||||
// returns the resolved value for this setting
|
||||
LaunchMode GlobalAppSettings::LaunchMode()
|
||||
{
|
||||
// fallback tree:
|
||||
// - user set value
|
||||
// - inherited value
|
||||
// - system set value
|
||||
return til::coalesce_value(_LaunchMode, _parents[0].LaunchMode(), _parents[1].LaunchMode(), ..., LaunchMode::DefaultMode);
|
||||
}
|
||||
|
||||
// explicitly set the user-set value
|
||||
void GlobalAppSettings::LaunchMode(LaunchMode val)
|
||||
{
|
||||
_LaunchMode = val;
|
||||
}
|
||||
|
||||
// check if there is a user-set value
|
||||
// NOTE: This is important for the Settings UI to identify whether the user explicitly or implicitly set the presented value
|
||||
bool GlobalAppSettings::HasLaunchMode()
|
||||
{
|
||||
return _LaunchMode.has_value();
|
||||
}
|
||||
|
||||
// explicitly unset the user-set value (we want the inherited value)
|
||||
void GlobalAppSettings::ClearLaunchMode()
|
||||
{
|
||||
return _LaunchMode = std::nullopt;
|
||||
}
|
||||
```
|
||||
|
||||
As a result, the tracking and functionality of cascading settings is moved into the object model instead of keeping it as a json-only concept.
|
||||
|
||||
#### Updates to CascadiaSettings
|
||||
|
||||
As `CascadiaSettings` loads the settings model, it will create children for each component of the settings model and layer the new values on top of it. Thus, `LayerJson` will look something like this:
|
||||
```c++
|
||||
void CascadiaSettings::LayerJson(const Json::Value& json)
|
||||
{
|
||||
_globals = _globals.CreateChild();
|
||||
_globals->LayerJson(json);
|
||||
|
||||
// repeat the same for Profiles...
|
||||
}
|
||||
```
|
||||
For `defaults.json`, `_globals` will now hold all of the values set in `defaults.json`. If any settings were omitted from the `defaults.json`, `_globals` will fallback to its parent (a `GlobalAppSettings` consisting purely of system-defined values).
|
||||
|
||||
For `settings.json`, `_globals` will only hold the values set in `settings.json`. If any settings were omitted from `settings.json`, `_globals` will fallback to its parent (the `GlobalAppSettings` built from `defaults.json`).
|
||||
|
||||
This process becomes a bit more complex for `Profile` because it can fallback in the following order:
|
||||
1. `settings.json` profile
|
||||
2. `settings.json` `profiles.defaults`
|
||||
3. (if a dynamic profile) the hardcoded value in the dynamic profile generator
|
||||
4. `defaults.json` profile
|
||||
|
||||
`CascadiaSettings` must do the following...
|
||||
1. load `defaults.json`
|
||||
- append newly created profiles to `_profiles` (unchanged)
|
||||
2. load dynamic profiles
|
||||
- append newly created profiles to `_profiles` (unchanged)
|
||||
3. load `settings.json` `profiles.defaults`
|
||||
- construct a `Profile` from `profiles.defaults`. Save as `Profile _profileDefaults`.
|
||||
- `CreateChild()` for each existing profile
|
||||
- add `_profileDefaults` as the first parent to each child (`_parents=[_profileDefaults, <value from generator/defaults.json> ]`)
|
||||
- replace each `Profile` in `_profiles` with the child
|
||||
4. load `settings.json` `profiles.list`
|
||||
- if a matching profile exists, `CreateChild` from the matching profile, and layer the json onto the child.
|
||||
- NOTE: we do _not_ include `_profileDefaults` as a parent here, because it is already an ancestor
|
||||
- otherwise, `CreateChild()` from `_profileDefaults`, and layer the json onto the child.
|
||||
- As before, `_profiles` must be updated such that the parent is removed
|
||||
|
||||
Additionally, `_profileDefaults` will be exposed by `Profile CascadiaSettings::ProfileDefaults()`. This will enable [#7414](https://github.com/microsoft/terminal/pull/7414)'s implementation to spawn incoming commandline app tabs with the "Default" profile (as opposed to the "default profile").
|
||||
|
||||
|
||||
#### Nullable Settings
|
||||
Some settings are explicitly allowed to be nullable (i.e. `Profile` `Foreground`). These settings will be stored as the following struct instead of a `std::optional<T>`:
|
||||
```c++
|
||||
template<typename T>
|
||||
struct NullableSetting
|
||||
{
|
||||
IReference<T> setting{ nullptr };
|
||||
bool set{ false };
|
||||
};
|
||||
```
|
||||
where...
|
||||
- `set` determines if the value was explicitly set by the user (if false, we should fall back)
|
||||
- `setting` records the actual user-set value (`nullptr` represents an explicit set to null)
|
||||
|
||||
The API surface will experience the following small changes:
|
||||
- the getter/setter will output/input an `IReference<T>` instead of `T`
|
||||
- `Has...()` and `Clear...()` will reference/modify `set`
|
||||
|
||||
|
||||
### CreateChild() vs Copy()
|
||||
|
||||
Settings objects will have `CreateChild()` and `Copy()`. `CreateChild()` is responsible for creating a new settings object that inherits undefined values from its parent. `Copy()` is responsible for recreating the contents of the settings object, including a reference to a copied parent (not the original parent).
|
||||
|
||||
`CreateChild()` will only be used during (de)serialization to adequately interpret and update the JSON. `CreateChild()` enables, but is not explicitly used, for retrieving a value from a settings object. It can also be used to enable larger hierarchies for inheritance within the settings model.
|
||||
|
||||
The Settings UI will use `Copy()` to get a deep copy of `CascadiaSettings` and data bind the UI to that copy. Thus, `Copy()` needs to be exposed in the IDL.
|
||||
|
||||
#### Copying _parents
|
||||
It is important that `_parents` is handled properly when performing a deep copy. We need to be aware of the following errors:
|
||||
- referencing `_parents` will result in inheriting from an obsolete object tree
|
||||
- referencing a copy of `_parents` can result in losing the meaning of a reference
|
||||
- For example, `profile.defaults` is a parent to each presented profile. When a change occurs to `profile.defaults`, that change should impact all profiles. An improper copy may only apply the change to one of the presented profiles
|
||||
|
||||
The hierarchy we have created has evolved into a directed acyclic graph (DAG). For example, the hierarchy for profiles will appear similar to the following:
|
||||
|
||||

|
||||
|
||||
In order to preserve `profile.defaults` as a referenced parent to each profile, a copy of the DAG can be performed using the following algorithm:
|
||||
```python
|
||||
# Function to clone a graph. To do this, we start
|
||||
# reading the original graph depth-wise, recursively
|
||||
# If we encounter an unvisited node in original graph,
|
||||
# we initialize a new instance of Node for
|
||||
# cloned graph with key of original node
|
||||
def cloneGraph(oldSource, newSource, visited):
|
||||
clone = None
|
||||
if visited[oldSource.key] is False and oldSource.adj is not None:
|
||||
for old in oldSource.adj:
|
||||
|
||||
# Below check is for backtracking, so new
|
||||
# nodes don't get initialized everytime
|
||||
if clone is None or(clone is not None and clone.key != old.key):
|
||||
clone = Node(old.key, [])
|
||||
newSource.adj.append(clone)
|
||||
cloneGraph(old, clone, visited)
|
||||
|
||||
# Once, all neighbors for that particular node
|
||||
# are created in cloned graph, code backtracks
|
||||
# and exits from that node, mark the node as
|
||||
# visited in original graph, and traverse the
|
||||
# next unvisited
|
||||
visited[old.key] = True
|
||||
return newSource
|
||||
```
|
||||
Source: https://www.geeksforgeeks.org/clone-directed-acyclic-graph/
|
||||
|
||||
This algorithm operates in O(n) time and space where `n` is the number of profiles presented. The above algorithm will be slightly modified to...
|
||||
- hold a separate reference to profile.defaults `Profile` in the `CascadiaSettings` clone
|
||||
- visited will be a map of pointers to the cloned `Profile`. This ensures that profiles reference the same `Profile`, over creating a new copy
|
||||
|
||||
### Terminal Settings Model: Serialization and Deserialization
|
||||
|
||||
Introducing these `Microsoft.Terminal.Settings.Model` WinRT objects also allow the serialization and deserialization
|
||||
logic from TerminalApp to be moved to TerminalSettings. `JsonUtils` introduces several quick and easy methods
|
||||
for setting serialization. This will be moved into the `Microsoft.Terminal.Settings.Model` namespace too.
|
||||
for setting deserialization. This will be moved into the `Microsoft.Terminal.Settings.Model` namespace too.
|
||||
|
||||
Deserialization will be an extension of the existing `JsonUtils` `ConversionTrait` struct template. `ConversionTrait`
|
||||
Serialization will be an extension of the existing `JsonUtils` `ConversionTrait` struct template. `ConversionTrait`
|
||||
already includes `FromJson` and `CanConvert`. Serialization would be handled by a `ToJson` function.
|
||||
|
||||
|
||||
BIN
doc/specs/#885 - Terminal Settings Model/Inheritance-DAG.png
Normal file
|
After Width: | Height: | Size: 29 KiB |
BIN
doc/specs/#885 - Terminal Settings Model/Inheritance-DAG.vsdx
Normal file
385
doc/specs/Proto extensions-spec.md
Normal file
@@ -0,0 +1,385 @@
|
||||
---
|
||||
author: <Pankaj> <Bhojwani> <@PankajBhojwani>
|
||||
created on: <2020-9-9>
|
||||
last updated: <2020-10-15>
|
||||
---
|
||||
|
||||
# Proto extensions
|
||||
|
||||
## Abstract
|
||||
|
||||
This spec outlines adding support for proto extensions. This would allow other apps/programs
|
||||
to add json snippets to our json files, and will be used when we generate settings for our various profiles.
|
||||
|
||||
## Inspiration
|
||||
|
||||
### Goal: Allow programs to have a say in the settings for their profiles
|
||||
|
||||
Currently, Ubuntu/WSL/Powershell etc are unable to provide any specifications for how they want
|
||||
their profiles in Terminal to look - only we and the users can modify the profiles. We want to provide
|
||||
these installations with the functionality to have a say in this, allowing them to specify things like
|
||||
their icon, their font and so on. However, we want to maintain that the user has final say over all of
|
||||
these settings.
|
||||
|
||||
## Solution Design
|
||||
|
||||
Currently, when we load the settings we perform the following steps (this is a simplified description,
|
||||
for the full version see the [spec for cascading default + user settings](https://github.com/microsoft/terminal/blob/master/doc/specs/%23754%20-%20Cascading%20Default%20Settings.md)):
|
||||
|
||||
1. Generate profiles from the defaults file
|
||||
2. Generate profiles from the dynamic profile generators
|
||||
3. Layer the user settings on top of all the profiles created in steps 1 and 2
|
||||
4. Validate the settings
|
||||
|
||||
To allow for installations to add in their snippets of json, I propose the addition of a new step
|
||||
in between 2 and 3:
|
||||
|
||||
1. Generate profiles from the defaults file
|
||||
2. Generate profiles from the dynamic profile generators
|
||||
3. **Incorporate the additional provided json stubs** - these stubs could be:
|
||||
1. modifications to existing profiles
|
||||
2. additions of full profiles
|
||||
3. additions of colour schemes
|
||||
4. Layer the user settings on top of all the profiles created in steps 1 through 3 (this includes the user-defined default settings which they wish to apply to all profiles)
|
||||
5. Validate the settings
|
||||
|
||||
### Specifications of the json stubs
|
||||
|
||||
As written above, the json stubs could be modifications to existing profiles, additions to full profiles, or additions of colour schemes.
|
||||
|
||||
To allow modifications/additions of several profiles in one file and to allow the addition of several colour schemes in one json file,
|
||||
these stubs should be put into lists in the json file: one list named ```profiles``` and the other list named ```schemes```. For example:
|
||||
|
||||
```js
|
||||
{
|
||||
"profiles": [ modifications and additions of profiles go here ],
|
||||
"schemes": [ additions of colour schemes go here ]
|
||||
}
|
||||
```
|
||||
|
||||
An example of a full json file with these fields filled out is shown at the end of this section.
|
||||
|
||||
#### Modifications to existing profiles
|
||||
|
||||
The main thing to note for modification of existing profiles is that this will only be used for modifying the
|
||||
default profiles (cmd/powershell) or the dynamically generated profiles.
|
||||
|
||||
For modifications to existing profiles, the json stub would need to indicate which profile it wishes to modify. It will
|
||||
do this by providing the corresponding guid in the `"updates"` field of the json stub. The reason we use an `"updates"`
|
||||
field rather than a `"guid"` field (like the way the user settings are eventually layered onto profiles) is because we
|
||||
do not want to mistakenly create a new profile when the stub was meant to update a profile that did not exist.
|
||||
|
||||
Note that currently, we generate a GUID for dynamic profiles using the "initial" name of the profile (i.e. before
|
||||
any user changes are applied). For example, the "initial" name of a WSL profile is the \<name\> argument to
|
||||
"wsl.exe -d \<name\>", and the "initial" name of a Powershell profile is something like "Powershell (ARM)" - depending
|
||||
on the version. Thus, the stub creator could simply use the same uuidv5 GUID generator we do on that name to obtain the
|
||||
GUID. Then, in the stub they provide the GUID can be used to identify which profile to modify.
|
||||
|
||||
Naturally, we will have to provide documentation on how they could generate the desired GUID themselves. In that documentation,
|
||||
we will also provide examples showing how the current GUIDs are generated for clarity's sake.
|
||||
|
||||
We need to inform developers that **we will not** prescribe any ordering to the way in which these modifications will be
|
||||
applied - thus, they should not rely on their stub being the first/last to modify a particular profile (in the event that
|
||||
there is more than one json stub modifying the same profile).
|
||||
|
||||
Here is an example of a json file that modifies an existing profile (specifically the Azure cloud shell profile):
|
||||
|
||||
```js
|
||||
{
|
||||
"profiles": [
|
||||
{
|
||||
"updates": "{b453ae62-4e3d-5e58-b989-0a998ec441b8}",
|
||||
"fontSize": 16,
|
||||
"fontWeight": "thin"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
**NOTE**: This will *not* change the way the profile looks in the user's settings file. The Azure cloud shell profile
|
||||
in their settings file (assuming they have made no changes) will still be as below.
|
||||
|
||||
```js
|
||||
{
|
||||
"guid": "{b453ae62-4e3d-5e58-b989-0a998ec441b8}",
|
||||
"hidden": false,
|
||||
"name": "Azure Cloud Shell",
|
||||
"source": "Windows.Terminal.Azure"
|
||||
}
|
||||
```
|
||||
However, the user is free to make changes to it as usual and those changes will have the 'final say'.
|
||||
|
||||
#### Full profile stubs
|
||||
|
||||
Technically, full profile stubs do not need to contain anything (they could just be '\{\}'). However we should
|
||||
have some qualifying minimum criteria before we accept a stub as a full profile. I suggest that we only create
|
||||
new profile objects from stubs that contain at least the following
|
||||
|
||||
* A name
|
||||
|
||||
As in the case of the dynamic profile generator, if we create a profile that did not exist before (i.e. does not
|
||||
exist in the user settings), we need to add the profile to the user settings file and re-save that file.
|
||||
|
||||
Furthermore, we will add a source field to profiles created this way (again, similar to what we do for dynamic profiles).
|
||||
The source field value is dependent on how we obtained this json file, and will be touched on in more detail [later in the spec](#the-source-field).
|
||||
|
||||
Here is an example of a json file that contains a full profile:
|
||||
|
||||
```js
|
||||
{
|
||||
"profiles": [
|
||||
{
|
||||
"guid": "{a821ae62-9d4a-3e34-b989-0a998ec283e6}",
|
||||
"name": "Cool Profile",
|
||||
"commandline": "powershell.exe",
|
||||
"antialiasingMode": "aliased",
|
||||
"fontWeight": "bold",
|
||||
"scrollbarState": "hidden"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
When this profile gets added back to the user's settings file, it will look similar to the way we currently add
|
||||
new dynamic profiles to the user's settings file. Going along with the example above, the corresponding
|
||||
json stub in the user's settings file will be:
|
||||
|
||||
```js
|
||||
{
|
||||
"guid": "{a821ae62-9d4a-3e34-b989-0a998ec283e6}",
|
||||
"name": "Cool Profile",
|
||||
"hidden": "false",
|
||||
"source": "local"
|
||||
}
|
||||
```
|
||||
Again, the user will be able to make changes to it as they do for all other profiles.
|
||||
|
||||
#### Creation of colour schemes
|
||||
|
||||
As with full profiles, we will have some qualifying criteria for what we accept as full colour schemes: color schemes
|
||||
must have _all_ the fields that define a colour scheme - see the
|
||||
[docs](https://docs.microsoft.com/en-us/windows/terminal/customize-settings/color-schemes)
|
||||
on creating new colour schemes for what this means.
|
||||
|
||||
This may cause the issue of colour schemes being overridden if there are many creations of a colour scheme with the
|
||||
same name. Since for now all we have to uniquely identify colour schemes *is* the name, we will just let this be.
|
||||
|
||||
Here is an example of a json stub that contains a colour scheme:
|
||||
|
||||
```js
|
||||
{
|
||||
"schemes": [
|
||||
{
|
||||
"name": "Postmodern Tango Light",
|
||||
|
||||
"cursorColor": "#FFFFFF",
|
||||
"selectionBackground": "#FFFFFF",
|
||||
|
||||
"background": '#61D6D6',
|
||||
"foreground": '#E74856',
|
||||
|
||||
"black" : "#0C0C0C",
|
||||
"blue" : "#0037DA",
|
||||
"cyan" : "#3A96DD",
|
||||
"green" : "#13A10E",
|
||||
"purple" : "#881798",
|
||||
"red" : "#C50F1F",
|
||||
"white" : "#CCCCCC",
|
||||
"yellow" : "#C19C00",
|
||||
"brightBlack" : "#767676",
|
||||
"brightBlue" : "#3B78FF",
|
||||
"brightCyan" : "#61D6D6",
|
||||
"brightGreen" : "#16C60C",
|
||||
"brightPurple" : "#B4009E",
|
||||
"brightRed" : "#E74856",
|
||||
"brightWhite" : "#F2F2F2",
|
||||
"brightYellow" : "#F9F1A5"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
This stub will *not* show up in the users settings file, similar to the way our default colour schemes do not show up.
|
||||
|
||||
#### Example of a full json file
|
||||
This is an example of a json file that combines all the above examples. Thus, this json file modifies the Azure Cloud
|
||||
Shell profile, creates a new profile called 'Cool Profile' and creates a new colour scheme called 'Postmodern Tango Light'.
|
||||
|
||||
```js
|
||||
{
|
||||
"profiles": [
|
||||
{
|
||||
"updates": "{b453ae62-4e3d-5e58-b989-0a998ec441b8}",
|
||||
"fontSize": 16,
|
||||
"fontWeight": "thin"
|
||||
},
|
||||
{
|
||||
"guid": "{a821ae62-9d4a-3e34-b989-0a998ec283e6}",
|
||||
"name": "Cool Profile",
|
||||
"commandline": "powershell.exe",
|
||||
"antialiasingMode": "aliased",
|
||||
"fontWeight": "bold",
|
||||
"scrollbarState": "hidden"
|
||||
}
|
||||
],
|
||||
"schemes": [
|
||||
{
|
||||
"name": "Postmodern Tango Light",
|
||||
|
||||
"cursorColor": "#FFFFFF",
|
||||
"selectionBackground": "#FFFFFF",
|
||||
|
||||
"background": '#61D6D6',
|
||||
"foreground": '#E74856',
|
||||
|
||||
"black" : "#0C0C0C",
|
||||
"blue" : "#0037DA",
|
||||
"cyan" : "#3A96DD",
|
||||
"green" : "#13A10E",
|
||||
"purple" : "#881798",
|
||||
"red" : "#C50F1F",
|
||||
"white" : "#CCCCCC",
|
||||
"yellow" : "#C19C00",
|
||||
"brightBlack" : "#767676",
|
||||
"brightBlue" : "#3B78FF",
|
||||
"brightCyan" : "#61D6D6",
|
||||
"brightGreen" : "#16C60C",
|
||||
"brightPurple" : "#B4009E",
|
||||
"brightRed" : "#E74856",
|
||||
"brightWhite" : "#F2F2F2",
|
||||
"brightYellow" : "#F9F1A5"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Creation and location(s) of the json files
|
||||
|
||||
In this section, we cover where an app that wants to use this proto-extension functionality should put the json
|
||||
files. Once we implement this feature, we will need to provide documentation on this for app developers.
|
||||
|
||||
#### For apps installed through Microsoft store (or similar)
|
||||
|
||||
For apps that are installed through something like the Microsoft Store, they will need to declare themselves to
|
||||
be an app extension or write a separate app extension. In the app extension, they will need to create a public
|
||||
folder, and create a subdirectory within that folder called `Fragments`. The json files should be inserted into the
|
||||
`Fragments` subdirectory. The specifics of how they can declare themselves as an app extension are provided in the
|
||||
[Microsoft Docs](https://docs.microsoft.com/en-us/windows/uwp/launch-resume/how-to-create-an-extension), and I will
|
||||
replicate the necessary section here.
|
||||
|
||||
In the appxmanifest file of the package:
|
||||
|
||||
```js
|
||||
<Package
|
||||
...
|
||||
xmlns:uap3="http://schemas.microsoft.com/appx/manifest/uap/windows10/3"
|
||||
IgnorableNamespaces="uap uap3 mp">
|
||||
...
|
||||
<Applications>
|
||||
<Application Id="App" ... >
|
||||
...
|
||||
<Extensions>
|
||||
...
|
||||
<uap3:Extension Category="windows.appExtension">
|
||||
<uap3:AppExtension Name="com.microsoft.windows.terminal.settings"
|
||||
Id="<id>"
|
||||
PublicFolder="Public">
|
||||
</uap3:AppExtension>
|
||||
</uap3:Extension>
|
||||
</Extensions>
|
||||
</Application>
|
||||
</Applications>
|
||||
...
|
||||
</Package>
|
||||
```
|
||||
|
||||
Note that the name field **must** be `com.microsoft.windows.terminal.settings` for us to detect this extension. The `Id` field
|
||||
can be filled out as the app wishes. The `PublicFolder` field should have the name of the folder, relative to
|
||||
the package root, where the `json` files they wish to share with us are stored (this folder is typically named
|
||||
`Public` but can be renamed as long as it matches the relevant folder).
|
||||
|
||||
During our profile generation, we will probe the OS for app extensions with the name `com.microsoft.windows.terminal.settings`
|
||||
and obtain the json files stored in the `Fragments` subdirectories of the public folders of those app extensions.
|
||||
|
||||
#### For apps installed 'traditionally'
|
||||
|
||||
For apps that are installed 'traditionally', there are 2 cases. The first is that this installation is for all
|
||||
the users of the system - in this case, the installer should add their json files to the global folder:
|
||||
|
||||
```js
|
||||
C:\ProgramData\Microsoft\Windows Terminal\Fragments\{app-name}
|
||||
```
|
||||
|
||||
Note: `C:\ProgramData` is a [known folder](https://docs.microsoft.com/en-us/previous-versions/windows/desktop/legacy/bb776911(v=vs.85))
|
||||
that apps should be able to access. If the folder `Windows Terminal` in `C:\ProgramData\Microsoft\Windows`
|
||||
does not already exist, the installer should create it. **Note:** the installer must create a subdirectory within
|
||||
the `Fragments` folder with their app name, we will use that name for the [`source` field](#the-source-field).
|
||||
|
||||
In the second case, the installation is only for the current user. For this case, the installer should add the
|
||||
json files to the local folder:
|
||||
|
||||
```js
|
||||
C:\Users\<user>\AppData\Local\Microsoft\Windows Terminal\Fragments\{app-name}
|
||||
```
|
||||
|
||||
We will look through both folders mentioned above during profile generation.
|
||||
|
||||
#### The source field
|
||||
|
||||
Currently, we allow users an easy way to disable/enable profiles that are generated from certain sources. For
|
||||
example, a user can easily hide all dynamic profiles with the source `"Windows.Terminal.Wsl"` if they wish to.
|
||||
To retain this functionality, we will add source fields to profiles we create through proto-extensions.
|
||||
|
||||
For full profiles that came from apps installed 'traditionally', we will use the name of the subdirectory where
|
||||
the json file was found to fill out the source field.
|
||||
|
||||
For full profiles that came from app extensions, we will use the app package name to fill out the source field.
|
||||
|
||||
|
||||
|
||||
## UI/UX Design
|
||||
|
||||
This feature will allow other installations a level of control over how their profiles look in Terminal. For example,
|
||||
if Ubuntu gets a new icon or a new font they can have those changes be reflected in Terminal users' Ubuntu profiles.
|
||||
|
||||
## Capabilities
|
||||
|
||||
### Accessibility
|
||||
|
||||
This change should not affect accessibility.
|
||||
|
||||
### Security
|
||||
|
||||
Opening a profile causes its commandline argument to be automatically run. Thus, if malicious modifications are made
|
||||
to existing profiles or new profiles with malicious commandline arguments are added, users could be tricked into running
|
||||
things they do not want to.
|
||||
|
||||
### Reliability
|
||||
|
||||
This should not affect reliability - most of what its doing is simply layering json which we already do.
|
||||
|
||||
### Compatibility
|
||||
|
||||
Again, there should not be any issues here - the user settings can still be layered after this layering for the user
|
||||
to have the final say.
|
||||
|
||||
### Performance, Power, and Efficiency
|
||||
|
||||
Looking through the additional json files could negatively impact startup time.
|
||||
|
||||
## Potential Issues
|
||||
|
||||
* An installer dumps a _lot_ of json files into the folder which we need to look through.
|
||||
* When a `.json` files is deleted, any new profiles that were generated from it remain in the user's settings file (though they no longer appear in the tab dropdown).
|
||||
|
||||
## Future considerations
|
||||
|
||||
We need to consider how an app extension provides the path to an image (for the icon source or background image of a profile for example)
|
||||
|
||||
This will likely be a stepping stone for the theme marketplace.
|
||||
|
||||
This will also likely be a stepping stone to allowing users to specify other files to import settings from.
|
||||
|
||||
## Resources
|
||||
|
||||
N/A
|
||||
@@ -1,11 +1,11 @@
|
||||
|
||||
# Branches in Openconsole
|
||||
|
||||
In Openconsole, `dev/main` is the master branch for the repo.
|
||||
In OpenConsole, `dev/main` is the primary branch for the repo.
|
||||
|
||||
Any branch that begins with `dev/` is recognized by our CI system and will automatically run x86 and amd64 builds and run our unit and feature tests. For feature branches the pattern we use is `dev/<alias>/<whatever you want here>`. ex. `dev/austdi/SomeCoolUnicodeFeature`. The important parts are the dev prefix and your alias.
|
||||
|
||||
`inbox` is a special branch that coordinates Openconsole code to the main OS repo.
|
||||
`inbox` is a special branch that coordinates OpenConsole code to the main OS repo.
|
||||
|
||||
The code will be checked into the OS repo at `/onecore/windows/core/console/open`. It would be prudent to make sure that directory builds in razzle with your submitted changes.
|
||||
|
||||
|
||||
@@ -96,7 +96,9 @@ Assuming that you've installed MSYS2 into `C:\\msys64`:
|
||||
"icon": "C:\\msys64\\msys2.ico",
|
||||
"startingDirectory": "C:\\msys64\\home\\user"
|
||||
}
|
||||
````
|
||||
```
|
||||
|
||||
For more details, see [this page](https://www.msys2.org/docs/terminals/#windows-terminal) on the MSYS2 documentation.
|
||||
|
||||
## Developer Command Prompt for Visual Studio
|
||||
|
||||
|
||||
434
oss/interval_tree/IntervalTree.h
Normal file
@@ -0,0 +1,434 @@
|
||||
#ifndef __INTERVAL_TREE_H
|
||||
#define __INTERVAL_TREE_H
|
||||
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <cassert>
|
||||
|
||||
#ifdef USE_INTERVAL_TREE_NAMESPACE
|
||||
namespace interval_tree
|
||||
{
|
||||
#endif
|
||||
template<class Scalar, typename Value>
|
||||
class Interval
|
||||
{
|
||||
public:
|
||||
Scalar start;
|
||||
Scalar stop;
|
||||
Value value;
|
||||
Interval(const Scalar& s, const Scalar& e, const Value& v) :
|
||||
start(std::min(s, e)), stop(std::max(s, e)), value(v)
|
||||
{
|
||||
}
|
||||
|
||||
Interval()
|
||||
{
|
||||
}
|
||||
|
||||
constexpr bool operator==(const Interval& other) const noexcept
|
||||
{
|
||||
return start == other.start &&
|
||||
stop == other.stop &&
|
||||
value == other.value;
|
||||
}
|
||||
|
||||
constexpr bool operator!=(const Interval& other) const noexcept
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
};
|
||||
|
||||
template<class Scalar, typename Value>
|
||||
Value intervalStart(const Interval<Scalar, Value>& i)
|
||||
{
|
||||
return i.start;
|
||||
}
|
||||
|
||||
template<class Scalar, typename Value>
|
||||
Value intervalStop(const Interval<Scalar, Value>& i)
|
||||
{
|
||||
return i.stop;
|
||||
}
|
||||
|
||||
template<class Scalar, typename Value>
|
||||
std::ostream& operator<<(std::ostream& out, const Interval<Scalar, Value>& i)
|
||||
{
|
||||
out << "Interval(" << i.start << ", " << i.stop << "): " << i.value;
|
||||
return out;
|
||||
}
|
||||
|
||||
template<class Scalar, class Value>
|
||||
class IntervalTree
|
||||
{
|
||||
public:
|
||||
typedef Interval<Scalar, Value> interval;
|
||||
typedef std::vector<interval> interval_vector;
|
||||
|
||||
struct IntervalStartCmp
|
||||
{
|
||||
bool operator()(const interval& a, const interval& b)
|
||||
{
|
||||
return a.start < b.start;
|
||||
}
|
||||
};
|
||||
|
||||
struct IntervalStopCmp
|
||||
{
|
||||
bool operator()(const interval& a, const interval& b)
|
||||
{
|
||||
return a.stop < b.stop;
|
||||
}
|
||||
};
|
||||
|
||||
IntervalTree() :
|
||||
left(nullptr), right(nullptr), center()
|
||||
{
|
||||
}
|
||||
|
||||
~IntervalTree() = default;
|
||||
|
||||
std::unique_ptr<IntervalTree> clone() const
|
||||
{
|
||||
return std::unique_ptr<IntervalTree>(new IntervalTree(*this));
|
||||
}
|
||||
|
||||
IntervalTree(const IntervalTree& other) :
|
||||
intervals(other.intervals),
|
||||
left(other.left ? other.left->clone() : nullptr),
|
||||
right(other.right ? other.right->clone() : nullptr),
|
||||
center(other.center)
|
||||
{
|
||||
}
|
||||
|
||||
IntervalTree& operator=(IntervalTree&&) = default;
|
||||
IntervalTree(IntervalTree&&) = default;
|
||||
|
||||
IntervalTree& operator=(const IntervalTree& other)
|
||||
{
|
||||
center = other.center;
|
||||
intervals = other.intervals;
|
||||
left = other.left ? other.left->clone() : nullptr;
|
||||
right = other.right ? other.right->clone() : nullptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
IntervalTree(
|
||||
interval_vector&& ivals,
|
||||
std::size_t depth = 16,
|
||||
std::size_t minbucket = 64,
|
||||
std::size_t maxbucket = 512,
|
||||
Scalar leftextent = {},
|
||||
Scalar rightextent = {}) :
|
||||
left(nullptr), right(nullptr)
|
||||
{
|
||||
--depth;
|
||||
const auto minmaxStop = std::minmax_element(ivals.begin(), ivals.end(), IntervalStopCmp());
|
||||
const auto minmaxStart = std::minmax_element(ivals.begin(), ivals.end(), IntervalStartCmp());
|
||||
if (!ivals.empty())
|
||||
{
|
||||
center = (minmaxStart.first->start + minmaxStop.second->stop) / 2;
|
||||
}
|
||||
if (leftextent == Scalar{} && rightextent == Scalar{})
|
||||
{
|
||||
// sort intervals by start
|
||||
std::sort(ivals.begin(), ivals.end(), IntervalStartCmp());
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(std::is_sorted(ivals.begin(), ivals.end(), IntervalStartCmp()));
|
||||
}
|
||||
if (depth == 0 || (ivals.size() < minbucket && ivals.size() < maxbucket))
|
||||
{
|
||||
std::sort(ivals.begin(), ivals.end(), IntervalStartCmp());
|
||||
intervals = std::move(ivals);
|
||||
assert(is_valid().first);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
Scalar leftp = Scalar{};
|
||||
Scalar rightp = Scalar{};
|
||||
|
||||
if (leftextent != Scalar{} || rightextent != Scalar{})
|
||||
{
|
||||
leftp = leftextent;
|
||||
rightp = rightextent;
|
||||
}
|
||||
else
|
||||
{
|
||||
leftp = ivals.front().start;
|
||||
rightp = std::max_element(ivals.begin(), ivals.end(), IntervalStopCmp())->stop;
|
||||
}
|
||||
|
||||
interval_vector lefts;
|
||||
interval_vector rights;
|
||||
|
||||
for (typename interval_vector::const_iterator i = ivals.begin();
|
||||
i != ivals.end();
|
||||
++i)
|
||||
{
|
||||
const interval& interval = *i;
|
||||
if (interval.stop < center)
|
||||
{
|
||||
lefts.push_back(interval);
|
||||
}
|
||||
else if (interval.start > center)
|
||||
{
|
||||
rights.push_back(interval);
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(interval.start <= center);
|
||||
assert(center <= interval.stop);
|
||||
intervals.push_back(interval);
|
||||
}
|
||||
}
|
||||
|
||||
if (!lefts.empty())
|
||||
{
|
||||
left.reset(new IntervalTree(std::move(lefts),
|
||||
depth,
|
||||
minbucket,
|
||||
maxbucket,
|
||||
leftp,
|
||||
center));
|
||||
}
|
||||
if (!rights.empty())
|
||||
{
|
||||
right.reset(new IntervalTree(std::move(rights),
|
||||
depth,
|
||||
minbucket,
|
||||
maxbucket,
|
||||
center,
|
||||
rightp));
|
||||
}
|
||||
}
|
||||
assert(is_valid().first);
|
||||
}
|
||||
|
||||
// Call f on all intervals near the range [start, stop]:
|
||||
template<class UnaryFunction>
|
||||
void visit_near(const Scalar& start, const Scalar& stop, UnaryFunction f) const
|
||||
{
|
||||
if (!intervals.empty() && !(stop < intervals.front().start))
|
||||
{
|
||||
for (auto& i : intervals)
|
||||
{
|
||||
f(i);
|
||||
}
|
||||
}
|
||||
if (left && start <= center)
|
||||
{
|
||||
left->visit_near(start, stop, f);
|
||||
}
|
||||
if (right && stop >= center)
|
||||
{
|
||||
right->visit_near(start, stop, f);
|
||||
}
|
||||
}
|
||||
|
||||
// Call f on all intervals crossing pos
|
||||
template<class UnaryFunction>
|
||||
void visit_overlapping(const Scalar& pos, UnaryFunction f) const
|
||||
{
|
||||
visit_overlapping(pos, pos, f);
|
||||
}
|
||||
|
||||
// Call f on all intervals overlapping [start, stop]
|
||||
template<class UnaryFunction>
|
||||
void visit_overlapping(const Scalar& start, const Scalar& stop, UnaryFunction f) const
|
||||
{
|
||||
auto filterF = [&](const interval& interval) {
|
||||
if (interval.stop >= start && interval.start <= stop)
|
||||
{
|
||||
// Only apply f if overlapping
|
||||
f(interval);
|
||||
}
|
||||
};
|
||||
visit_near(start, stop, filterF);
|
||||
}
|
||||
|
||||
// Call f on all intervals contained within [start, stop]
|
||||
template<class UnaryFunction>
|
||||
void visit_contained(const Scalar& start, const Scalar& stop, UnaryFunction f) const
|
||||
{
|
||||
auto filterF = [&](const interval& interval) {
|
||||
if (start <= interval.start && interval.stop <= stop)
|
||||
{
|
||||
f(interval);
|
||||
}
|
||||
};
|
||||
visit_near(start, stop, filterF);
|
||||
}
|
||||
|
||||
interval_vector findOverlapping(const Scalar& start, const Scalar& stop) const
|
||||
{
|
||||
interval_vector result;
|
||||
visit_overlapping(start, stop, [&](const interval& interval) {
|
||||
result.emplace_back(interval);
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
interval_vector findContained(const Scalar& start, const Scalar& stop) const
|
||||
{
|
||||
interval_vector result;
|
||||
visit_contained(start, stop, [&](const interval& interval) {
|
||||
result.push_back(interval);
|
||||
});
|
||||
return result;
|
||||
}
|
||||
bool empty() const
|
||||
{
|
||||
if (left && !left->empty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!intervals.empty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (right && !right->empty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class UnaryFunction>
|
||||
void visit_all(UnaryFunction f) const
|
||||
{
|
||||
if (left)
|
||||
{
|
||||
left->visit_all(f);
|
||||
}
|
||||
std::for_each(intervals.begin(), intervals.end(), f);
|
||||
if (right)
|
||||
{
|
||||
right->visit_all(f);
|
||||
}
|
||||
}
|
||||
|
||||
std::pair<Scalar, Scalar> extentBruitForce() const
|
||||
{
|
||||
struct Extent
|
||||
{
|
||||
std::pair<Scalar, Scalar> x = { std::numeric_limits<Scalar>::max(),
|
||||
std::numeric_limits<Scalar>::min() };
|
||||
void operator()(const interval& interval)
|
||||
{
|
||||
x.first = std::min(x.first, interval.start);
|
||||
x.second = std::max(x.second, interval.stop);
|
||||
}
|
||||
};
|
||||
Extent extent;
|
||||
|
||||
visit_all([&](const interval& interval) { extent(interval); });
|
||||
return extent.x;
|
||||
}
|
||||
|
||||
// Check all constraints.
|
||||
// If first is false, second is invalid.
|
||||
std::pair<bool, std::pair<Scalar, Scalar>> is_valid() const
|
||||
{
|
||||
const auto minmaxStop = std::minmax_element(intervals.begin(), intervals.end(), IntervalStopCmp());
|
||||
const auto minmaxStart = std::minmax_element(intervals.begin(), intervals.end(), IntervalStartCmp());
|
||||
|
||||
std::pair<bool, std::pair<Scalar, Scalar>> result = { true, { std::numeric_limits<Scalar>::max(), std::numeric_limits<Scalar>::min() } };
|
||||
if (!intervals.empty())
|
||||
{
|
||||
result.second.first = std::min(result.second.first, minmaxStart.first->start);
|
||||
result.second.second = std::min(result.second.second, minmaxStop.second->stop);
|
||||
}
|
||||
if (left)
|
||||
{
|
||||
auto valid = left->is_valid();
|
||||
result.first &= valid.first;
|
||||
result.second.first = std::min(result.second.first, valid.second.first);
|
||||
result.second.second = std::min(result.second.second, valid.second.second);
|
||||
if (!result.first)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
if (valid.second.second >= center)
|
||||
{
|
||||
result.first = false;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
if (right)
|
||||
{
|
||||
auto valid = right->is_valid();
|
||||
result.first &= valid.first;
|
||||
result.second.first = std::min(result.second.first, valid.second.first);
|
||||
result.second.second = std::min(result.second.second, valid.second.second);
|
||||
if (!result.first)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
if (valid.second.first <= center)
|
||||
{
|
||||
result.first = false;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
if (!std::is_sorted(intervals.begin(), intervals.end(), IntervalStartCmp()))
|
||||
{
|
||||
result.first = false;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& os, const IntervalTree& itree)
|
||||
{
|
||||
return writeOut(os, itree);
|
||||
}
|
||||
|
||||
friend std::ostream& writeOut(std::ostream& os, const IntervalTree& itree, std::size_t depth = 0)
|
||||
{
|
||||
auto pad = [&]() { for (std::size_t i = 0; i != depth; ++i) { os << ' '; } };
|
||||
pad();
|
||||
os << "center: " << itree.center << '\n';
|
||||
for (const interval& inter : itree.intervals)
|
||||
{
|
||||
pad();
|
||||
os << inter << '\n';
|
||||
}
|
||||
if (itree.left)
|
||||
{
|
||||
pad();
|
||||
os << "left:\n";
|
||||
writeOut(os, *itree.left, depth + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
pad();
|
||||
os << "left: nullptr\n";
|
||||
}
|
||||
if (itree.right)
|
||||
{
|
||||
pad();
|
||||
os << "right:\n";
|
||||
writeOut(os, *itree.right, depth + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
pad();
|
||||
os << "right: nullptr\n";
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
private:
|
||||
interval_vector intervals;
|
||||
std::unique_ptr<IntervalTree> left;
|
||||
std::unique_ptr<IntervalTree> right;
|
||||
Scalar center;
|
||||
};
|
||||
#ifdef USE_INTERVAL_TREE_NAMESPACE
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
17
oss/interval_tree/MAINTAINER_README.md
Normal file
@@ -0,0 +1,17 @@
|
||||
# Notes for Future Maintainers
|
||||
|
||||
This was originally imported by @PankajBhojwani in September 2020.
|
||||
|
||||
The provenance information (where it came from and which commit) is stored in the file `cgmanifest.json` in the same directory as this readme.
|
||||
Please update the provenance information in that file when ingesting an updated version of the dependent library.
|
||||
That provenance file is automatically read and inventoried by Microsoft systems to ensure compliance with appropiate governance standards.
|
||||
|
||||
## What should be done to update this in the future?
|
||||
|
||||
1. Go to ekg/intervaltreerepository on GitHub.
|
||||
2. Take the file IntervalTree.h wholesale and drop it into the directory here.
|
||||
3. Don't change anything about it.
|
||||
4. Validate that the license in the root of the repository didn't change and update it if so. It is sitting in the same directory as this readme.
|
||||
If it changed dramatically, ensure that it is still compatible with our license scheme. Also update the NOTICE file in the root of our repository to declare the third-party usage.
|
||||
5. Submit the pull.
|
||||
|
||||
13
oss/interval_tree/cgmanifest.json
Normal file
@@ -0,0 +1,13 @@
|
||||
{"Registrations":[
|
||||
{
|
||||
"component": {
|
||||
"type": "git",
|
||||
"git": {
|
||||
"repositoryUrl": "https://github.com/ekg/intervaltree",
|
||||
"commitHash": "b90527f9e6d51cd36ecbb50429e4524d3a418ea5"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"Version": 1
|
||||
}
|
||||
BIN
res/Cascadia.ttf
@@ -2,20 +2,20 @@
|
||||
|
||||
## Images
|
||||
|
||||
The images in this directory do not fall under the same [license](https://raw.githubusercontent.com/microsoft/terminal/master/LICENSE) as the rest
|
||||
The images in this directory do not fall under the same [license](https://raw.githubusercontent.com/microsoft/terminal/main/LICENSE) as the rest
|
||||
of the Windows Terminal code.
|
||||
|
||||
Please consult the [license](./LICENSE) in this directory for terms applicable to the image assets in this directory.
|
||||
|
||||
## Fonts
|
||||
|
||||
The fonts in this directory do not fall under the same [license](https://raw.githubusercontent.com/microsoft/terminal/master/LICENSE) as the rest
|
||||
The fonts in this directory do not fall under the same [license](https://raw.githubusercontent.com/microsoft/terminal/main/LICENSE) as the rest
|
||||
of the Windows Terminal code.
|
||||
|
||||
Please consult the [license](https://raw.githubusercontent.com/microsoft/cascadia-code/master/LICENSE) in the
|
||||
Please consult the [license](https://raw.githubusercontent.com/microsoft/cascadia-code/main/LICENSE) in the
|
||||
[microsoft/cascadia-code](https://github.com/microsoft/cascadia-code) repository for terms applicable to the fonts in this directory.
|
||||
|
||||
### Fonts Included
|
||||
|
||||
* Cascadia Code, Cascadia Mono (2009.21)
|
||||
* from microsoft/cascadia-code@32f84124db1970fa5d032f0fe9019e6922961beb
|
||||
* Cascadia Code, Cascadia Mono (2102.03)
|
||||
* from microsoft/cascadia-code@b358d1ba3d1629c113671312b18eab52797cc055
|
||||
|
||||
@@ -24,6 +24,7 @@ Param(
|
||||
[string]$Path,
|
||||
[string]$Destination,
|
||||
[int[]]$Altforms = (16, 20, 24, 30, 32, 36, 40, 48, 60, 64, 72, 80, 96, 256),
|
||||
[int[]]$Win32IconSizes = (16, 20, 24, 32, 48, 64, 256),
|
||||
[switch]$Unplated = $true,
|
||||
[float[]]$Scales = (1.0, 1.25, 1.5, 2.0, 4.0),
|
||||
[string]$HighContrastPath = "",
|
||||
@@ -115,6 +116,7 @@ If (-Not [string]::IsNullOrEmpty($Destination)) {
|
||||
$TranslatedOutDir = "."
|
||||
}
|
||||
|
||||
$intermediates = [System.Collections.Concurrent.ConcurrentBag[PSCustomObject]]::new()
|
||||
$intermediateFiles = [System.Collections.Concurrent.ConcurrentBag[string]]::new()
|
||||
|
||||
# Generate the base icons
|
||||
@@ -136,6 +138,11 @@ $allSizes | ForEach-Object -Parallel {
|
||||
}
|
||||
|
||||
($using:intermediateFiles).Add($intermediateStandardNt)
|
||||
($using:intermediates).Add([PSCustomObject]@{
|
||||
Contrast = "standard"
|
||||
Size = $sz
|
||||
PathWSL = $intermediateStandardWsl
|
||||
})
|
||||
|
||||
If ($svgContrastWsl -Ne $null) {
|
||||
$intermediateBlackNt = "$destinationNt\_intermediate.black.$($sz).png"
|
||||
@@ -158,9 +165,28 @@ $allSizes | ForEach-Object -Parallel {
|
||||
|
||||
($using:intermediateFiles).Add($intermediateBlackNt)
|
||||
($using:intermediateFiles).Add($intermediateWhiteNt)
|
||||
($using:intermediates).Add([PSCustomObject]@{
|
||||
Contrast = "black"
|
||||
Size = $sz
|
||||
PathWSL = $intermediateBlackWsl
|
||||
})
|
||||
($using:intermediates).Add([PSCustomObject]@{
|
||||
Contrast = "white"
|
||||
Size = $sz
|
||||
PathWSL = $intermediateWhiteWsl
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
$intermediates | ? { $_.Size -In $Win32IconSizes } | Group-Object Contrast | ForEach-Object -Parallel {
|
||||
$assetName = "terminal.ico"
|
||||
If ($_.Name -Ne "standard") {
|
||||
$assetName = "terminal_contrast-$($_.Name).ico"
|
||||
}
|
||||
Write-Host "Producing win32 .ico for contrast=$($_.Name) as $assetName"
|
||||
wsl convert $_.Group.PathWSL "$($using:TranslatedOutDir)/$assetName"
|
||||
}
|
||||
|
||||
# Once the base icons are done, splat them into the middles of larger canvases.
|
||||
$allAssetSizes | ForEach-Object -Parallel {
|
||||
$asset = $_
|
||||
|
||||
|
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 3.6 KiB |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 5.1 KiB After Width: | Height: | Size: 4.8 KiB |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 6.1 KiB After Width: | Height: | Size: 5.7 KiB |
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 8.5 KiB After Width: | Height: | Size: 7.9 KiB |
|
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.9 KiB |
|
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.8 KiB |
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 6.0 KiB After Width: | Height: | Size: 6.8 KiB |
|
Before Width: | Height: | Size: 6.0 KiB After Width: | Height: | Size: 6.8 KiB |
|
Before Width: | Height: | Size: 614 B After Width: | Height: | Size: 841 B |
|
Before Width: | Height: | Size: 374 B After Width: | Height: | Size: 542 B |
|
Before Width: | Height: | Size: 444 B After Width: | Height: | Size: 548 B |
|
Before Width: | Height: | Size: 811 B After Width: | Height: | Size: 1.0 KiB |
|
Before Width: | Height: | Size: 491 B After Width: | Height: | Size: 636 B |
|
Before Width: | Height: | Size: 518 B After Width: | Height: | Size: 645 B |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 474 B After Width: | Height: | Size: 671 B |
|
Before Width: | Height: | Size: 501 B After Width: | Height: | Size: 671 B |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 574 B After Width: | Height: | Size: 722 B |
|
Before Width: | Height: | Size: 565 B After Width: | Height: | Size: 731 B |
|
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 2.9 KiB |
|
Before Width: | Height: | Size: 959 B After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 869 B After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 566 B After Width: | Height: | Size: 704 B |
|
Before Width: | Height: | Size: 549 B After Width: | Height: | Size: 705 B |
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 626 B After Width: | Height: | Size: 835 B |
|
Before Width: | Height: | Size: 615 B After Width: | Height: | Size: 834 B |