├── docs ├── _config.yml ├── CNAME ├── Assets │ ├── Get-WTColorScheme.png │ └── TerminalVelocity.svg ├── 2022-11-08.md ├── 2022-11.md ├── 2022.md ├── Restore-WTProfile.md ├── Backup-WTProfile.md ├── Get-WTColorScheme.md ├── Clear-WTColorScheme.md ├── rss.xml ├── README.md ├── CHANGELOG.md ├── Remove-WTColorScheme.md ├── Stop-WT.md ├── _posts │ └── 2022-11-08-TerminalVelocity-0.3.1.md ├── Remove-WTProfile.md ├── Set-WTColorScheme.md ├── Get-WTProfile.md ├── Start-WT.md ├── Show-WT.md ├── New-WTColorScheme.md ├── Add-WTColorScheme.md └── New-WTProfile.md ├── Assets ├── Get-WTColorScheme.png └── TerminalVelocity.svg ├── TerminalVelocity.HelpOut.ps1 ├── TerminalVelocity.psm1 ├── Formatting ├── WindowsTerminal.Profile.format.ps1 └── WindowsTerminal.ColorScheme.format.ps1 ├── Clear-WTColorScheme.ps1 ├── TerminalVelocity.GitHubWorkflow.PSDevOps.ps1 ├── New-WTProfile.ps.ps1 ├── Restore-WTProfile.ps1 ├── .github └── workflows │ └── OnIssue.yml ├── Get-WTColorScheme.ps1 ├── LICENSE ├── Stop-WT.ps1 ├── TerminalVelocity.ezout.ps1 ├── Backup-WTProfile.ps1 ├── Remove-WTColorScheme.ps1 ├── TerminalVelocity.PSSVG.ps1 ├── README.md ├── CHANGELOG.md ├── TerminalVelocity.psd1 ├── Set-WTColorScheme.ps1 ├── Add-WTProfile.ps.ps1 ├── New-WTColorScheme.ps1 ├── Remove-WTProfile.ps1 ├── Start-WT.ps1 ├── TerminalVelocity.tests.ps1 ├── Add-WTColorScheme.ps1 ├── Show-WT.ps1 ├── Get-WTProfile.ps1 ├── New-WTProfile.ps1 ├── Set-WTProfile.ps.ps1 ├── TerminalVelocity.format.ps1xml └── Add-WTProfile.ps1 /docs/_config.yml: -------------------------------------------------------------------------------- 1 | permalink: pretty 2 | -------------------------------------------------------------------------------- /docs/CNAME: -------------------------------------------------------------------------------- 1 | terminalvelocity.start-automating.com -------------------------------------------------------------------------------- /Assets/Get-WTColorScheme.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/StartAutomating/TerminalVelocity/HEAD/Assets/Get-WTColorScheme.png -------------------------------------------------------------------------------- /docs/Assets/Get-WTColorScheme.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/StartAutomating/TerminalVelocity/HEAD/docs/Assets/Get-WTColorScheme.png -------------------------------------------------------------------------------- /TerminalVelocity.HelpOut.ps1: -------------------------------------------------------------------------------- 1 | #requires -Module HelpOut 2 | Import-Module .\TerminalVelocity.psd1 3 | Save-MarkdownHelp -Module TerminalVelocity -PassThru 4 | 5 | -------------------------------------------------------------------------------- /TerminalVelocity.psm1: -------------------------------------------------------------------------------- 1 | foreach ($file in Get-ChildItem $PSScriptRoot -Filter *-*.ps1) { 2 | if ($file.Name -match '\.ps{0,1}\.ps1$') { continue } 3 | . $file.Fullname 4 | } -------------------------------------------------------------------------------- /Formatting/WindowsTerminal.Profile.format.ps1: -------------------------------------------------------------------------------- 1 | Write-FormatView -TypeName WindowsTerminal.Profile -Property Name, Source, CommandLine -Wrap -VirtualProperty @{ 2 | Source = {$_.Source -split '\.' | Select-Object -Last 1 } 3 | } -------------------------------------------------------------------------------- /docs/2022-11-08.md: -------------------------------------------------------------------------------- 1 | --- 2 | permalink: /2022/11/08/ 3 | --- 4 | {% for post in site.posts %} 5 | {% assign currentdate = post.date | date: "%Y %m %d" %} 6 | {% assign friendlydate = post.date | date: "[%B](..) [%d](.) [%Y](../..)" %} 7 | {% if currentdate != "2022 11 08" %} 8 | {% continue %} 9 | {% endif %} 10 | {% if currentdate != date %} 11 | ## {{friendlydate}} 12 | {% assign date = currentdate %} 13 | {% endif %} 14 | * [ {{ post.title }} ]( {{ post.url }} ) 15 | {% endfor %} 16 | -------------------------------------------------------------------------------- /Clear-WTColorScheme.ps1: -------------------------------------------------------------------------------- 1 | function Clear-WTColorScheme 2 | { 3 | <# 4 | .Synopsis 5 | Clears Windows Terminal Color Schemes 6 | .Description 7 | Clears the Windows Terminal Color Scheme for the current profile. 8 | .Example 9 | Clear-WTColorScheme 10 | .Link 11 | Get-WTColorScheme 12 | #> 13 | [CmdletBinding(SupportsShouldProcess,ConfirmImpact='High')] 14 | param() 15 | 16 | process { 17 | Set-WTProfile -Current -InputObject @{colorScheme=''} 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /TerminalVelocity.GitHubWorkflow.PSDevOps.ps1: -------------------------------------------------------------------------------- 1 | #requires -Module PSDevOps 2 | New-GitHubWorkflow -Name "Analyze, Test, Tag, and Publish" -On Push, PullRequest, Demand -Job PowerShellStaticAnalysis, 3 | TestPowerShellOnLinux, 4 | TagReleaseAndPublish, 5 | BuildModule -OutputPath ( 6 | (Join-Path $PSScriptRoot .github\workflows\TestAndPublish.yml) 7 | ) 8 | 9 | Import-Module GitPub 10 | Import-BuildStep -ModuleName GitPub 11 | 12 | New-GitHubWorkflow -On Issue, Demand -Job RunGitPub -Name OnIssueChanged -OutputPath ( 13 | Join-Path $PSScriptRoot .github\workflows\OnIssue.yml 14 | ) 15 | -------------------------------------------------------------------------------- /docs/2022-11.md: -------------------------------------------------------------------------------- 1 | --- 2 | permalink: /2022/11/ 3 | --- 4 | {% assign currentYearMonth = "2022 11" %} 5 | {% for post in site.posts %} 6 | {% assign postYear = post.date | date: "%Y" %} 7 | {% assign postYearMonth = post.date | date: "%B [%Y](..)" %} 8 | {% assign postYM = post.date | date: "%Y %m" %} 9 | {% if postYM != currentYearMonth %} 10 | {% continue %} 11 | {% endif %} 12 | {% if hasDisplayedYearMonth != postYearMonth %} 13 | ## {{postYearMonth}} 14 | {% endif %} 15 | {% assign hasDisplayedYearMonth = postYearMonth %} 16 | * [ {{ post.title }} ]( {{ post.url }} ) 17 | {% endfor %} 18 | -------------------------------------------------------------------------------- /docs/2022.md: -------------------------------------------------------------------------------- 1 | --- 2 | permalink: /2022/ 3 | --- 4 | {% assign currentYear = "2022" %} 5 | {% for post in site.posts %} 6 | {% assign postYear = post.date | date: "%Y" %} 7 | {% assign postYearMonth = post.date | date: "[%B](%m) %Y" %} 8 | {% if postYear != currentYear %} 9 | {% continue %} 10 | {% endif %} 11 | {% if hasDisplayedYear != postYear %} 12 | ## [{{postYear}}](.) 13 | {% endif %} 14 | {% assign hasDisplayedYear = postYear %} 15 | {% if hasDisplayedYearMonth != postYearMonth %} 16 | ### {{postYearMonth}} 17 | {% endif %} 18 | {% assign hasDisplayedYearMonth = postYearMonth %} 19 | * [ {{ post.title }} ]( {{ post.url }} ) 20 | {% endfor %} 21 | -------------------------------------------------------------------------------- /docs/Restore-WTProfile.md: -------------------------------------------------------------------------------- 1 | Restore-WTProfile 2 | ----------------- 3 | ### Synopsis 4 | Restores a Windows Terminal Profile 5 | 6 | --- 7 | ### Description 8 | 9 | Restores a Windows Terminal Profile backup. 10 | 11 | --- 12 | ### Related Links 13 | * [Backup-WTProfile](Backup-WTProfile.md) 14 | 15 | 16 | 17 | --- 18 | ### Examples 19 | #### EXAMPLE 1 20 | ```PowerShell 21 | Restore-WTProfile -SourcePath .\WindowsTerminal.2020-05-17.backup.json 22 | ``` 23 | 24 | --- 25 | ### Parameters 26 | #### **SourcePath** 27 | 28 | > **Type**: ```[String]``` 29 | 30 | > **Required**: true 31 | 32 | > **Position**: 1 33 | 34 | > **PipelineInput**:true (ByPropertyName) 35 | 36 | 37 | 38 | --- 39 | ### Syntax 40 | ```PowerShell 41 | Restore-WTProfile [-SourcePath] [] 42 | ``` 43 | --- 44 | -------------------------------------------------------------------------------- /New-WTProfile.ps.ps1: -------------------------------------------------------------------------------- 1 | function New-WTProfile 2 | { 3 | <# 4 | .Synopsis 5 | Creates a new Windows Terminal profile 6 | .Description 7 | Creates a new Windows Terminal tab profile. 8 | .Link 9 | Add-WTProfile 10 | .Example 11 | New-WTProfile -Name DOS -CommandLine cmd 12 | .Example 13 | New-WTProfile -Name kali-linux-pwsh -CommandLine 'wsl -d kali-linux -e pwsh' 14 | .Example 15 | New-WTProfile -Default 16 | #> 17 | [OutputType('WindowsTerminal.Profile')] 18 | [Diagnostics.CodeAnalysis.SuppressMessageAttribute( 19 | "PSUseShouldProcessForStateChangingFunctions", "", Justification="Not changing state" 20 | )] 21 | [JSONSchema(SchemaUri='https://aka.ms/terminal-profiles-schema#Profile',RemovePropertyPrefix='Experimental')] 22 | param() 23 | 24 | } 25 | -------------------------------------------------------------------------------- /Assets/TerminalVelocity.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Terminal 9 | Velocity 10 | 11 | 12 | -------------------------------------------------------------------------------- /docs/Assets/TerminalVelocity.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Terminal 9 | Velocity 10 | 11 | 12 | -------------------------------------------------------------------------------- /Restore-WTProfile.ps1: -------------------------------------------------------------------------------- 1 | function Restore-WTProfile 2 | { 3 | <# 4 | .Synopsis 5 | Restores a Windows Terminal Profile 6 | .Description 7 | Restores a Windows Terminal Profile backup. 8 | .Example 9 | Restore-WTProfile -SourcePath .\WindowsTerminal.2020-05-17.backup.json 10 | .Link 11 | Backup-WTProfile 12 | #> 13 | param( 14 | [Parameter(Mandatory,ValueFromPipelineByPropertyName)] 15 | [ValidatePattern('\.json$')] 16 | [Alias('FullName')] 17 | [string] 18 | $SourcePath 19 | ) 20 | 21 | process { 22 | $destPath = 23 | if (-not $script:WTProfilePath) { 24 | Get-WTProfile -Setting | Select-Object -ExpandProperty Path 25 | } else { 26 | $script:WTProfilePath.Fullname 27 | } 28 | 29 | if ((Test-Path $SourcePath) -and $destPath) { 30 | Copy-Item -Path $SourcePath -Destination $destPath 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /docs/Backup-WTProfile.md: -------------------------------------------------------------------------------- 1 | Backup-WTProfile 2 | ---------------- 3 | ### Synopsis 4 | Backs up the Windows Terminal Profile 5 | 6 | --- 7 | ### Description 8 | 9 | Backs up the Windows Terminal Profile. 10 | 11 | By default, backups will be placed in the same directory as $profile, and will include a datestamp. 12 | 13 | --- 14 | ### Related Links 15 | * [Get-WTProfile](Get-WTProfile.md) 16 | 17 | 18 | 19 | --- 20 | ### Examples 21 | #### EXAMPLE 1 22 | ```PowerShell 23 | Backup-WTProfile 24 | ``` 25 | 26 | --- 27 | ### Parameters 28 | #### **DestinationPath** 29 | 30 | The destination path for the backup. 31 | By default, this will be in the same directory as $profile, and will include a datestamp. 32 | 33 | 34 | 35 | > **Type**: ```[String]``` 36 | 37 | > **Required**: false 38 | 39 | > **Position**: 1 40 | 41 | > **PipelineInput**:true (ByPropertyName) 42 | 43 | 44 | 45 | --- 46 | ### Syntax 47 | ```PowerShell 48 | Backup-WTProfile [[-DestinationPath] ] [] 49 | ``` 50 | --- 51 | -------------------------------------------------------------------------------- /.github/workflows/OnIssue.yml: -------------------------------------------------------------------------------- 1 | 2 | name: OnIssueChanged 3 | on: 4 | issues: 5 | workflow_dispatch: 6 | jobs: 7 | RunGitPub: 8 | runs-on: ubuntu-latest 9 | if: ${{ success() }} 10 | steps: 11 | - name: Check out repository 12 | uses: actions/checkout@v2 13 | - name: Use GitPub Action 14 | uses: StartAutomating/GitPub@main 15 | id: GitPub 16 | with: 17 | TargetBranch: edits-$([DateTime]::Now.ToString("r").Replace(":","-").Replace(" ", "")) 18 | CommitMessage: Posting with GitPub [skip ci] 19 | PublishParameters: | 20 | { 21 | "Get-GitPubIssue": { 22 | "Repository": '${{github.repository}}' 23 | }, 24 | "Get-GitPubRelease": { 25 | "Repository": '${{github.repository}}' 26 | }, 27 | "Publish-GitPubJekyll": { 28 | "OutputPath": "docs/_posts" 29 | } 30 | } 31 | 32 | -------------------------------------------------------------------------------- /Get-WTColorScheme.ps1: -------------------------------------------------------------------------------- 1 | function Get-WTColorScheme 2 | { 3 | <# 4 | .Synopsis 5 | Gets Windows Terminal Color Schemes 6 | .Description 7 | Gets one or more Windows Terminal Color Schemes from the profile 8 | .Example 9 | Get-WTColorScheme # Gets all color schemes 10 | .Example 11 | Get-WTColorScheme 'Jackie Brown' # Gets the color scheme 'Jackie Brown' 12 | .Link 13 | Add-WTColorScheme 14 | .Link 15 | New-WTColorScheme 16 | #> 17 | [OutputType([PSObject])] 18 | param( 19 | # The name of the color scheme. 20 | [Parameter(ValueFromPipelineByPropertyName)] 21 | [Alias('Name')] 22 | [string[]] 23 | $ColorScheme 24 | ) 25 | 26 | process { 27 | #region Get Color Scheme 28 | if (-not $PSBoundParameters.ColorScheme) # If no color scheme was provided 29 | { 30 | $PSBoundParameters['ColorScheme'] = '*'# default to all 31 | } 32 | 33 | Get-WTProfile @PSBoundParameters # call Get-WTProfile 34 | #endregion Get Color Scheme 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Start-Automating 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Stop-WT.ps1: -------------------------------------------------------------------------------- 1 | function Stop-WT 2 | { 3 | <# 4 | .Synopsis 5 | Stops Windows Terminal 6 | .Description 7 | Stops Windows Terminal Processes 8 | .Link 9 | Start-WT 10 | .Link 11 | Stop-Process 12 | .Example 13 | Stop-WT 14 | #> 15 | [CmdletBinding(SupportsShouldProcess,DefaultParameterSetName='All')] 16 | [OutputType([Nullable])] 17 | param( 18 | # The Process ID 19 | [Parameter(Mandatory,ParameterSetName='ProcessID',ValueFromPipelineByPropertyName)] 20 | [Alias('PID', 'ProcessID')] 21 | [int[]] 22 | $ID 23 | ) 24 | 25 | begin { 26 | $allIds = [Collections.ArrayList]::new() 27 | } 28 | 29 | process { 30 | $allIds.AddRange($ID) 31 | } 32 | 33 | end { 34 | #region Stop Terminals 35 | @(if (-not $allIds) { 36 | Get-Process WindowsTerminal -ErrorAction Ignore 37 | } else { 38 | Get-Process WindowsTerminal -ErrorAction Ignore | 39 | Where-Object ID -In $allIds 40 | }) | 41 | Stop-Process 42 | #endregion Stop Terminals 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /docs/Get-WTColorScheme.md: -------------------------------------------------------------------------------- 1 | Get-WTColorScheme 2 | ----------------- 3 | ### Synopsis 4 | Gets Windows Terminal Color Schemes 5 | 6 | --- 7 | ### Description 8 | 9 | Gets one or more Windows Terminal Color Schemes from the profile 10 | 11 | --- 12 | ### Related Links 13 | * [Add-WTColorScheme](Add-WTColorScheme.md) 14 | 15 | 16 | 17 | * [New-WTColorScheme](New-WTColorScheme.md) 18 | 19 | 20 | 21 | --- 22 | ### Examples 23 | #### EXAMPLE 1 24 | ```PowerShell 25 | Get-WTColorScheme # Gets all color schemes 26 | ``` 27 | 28 | #### EXAMPLE 2 29 | ```PowerShell 30 | Get-WTColorScheme 'Jackie Brown' # Gets the color scheme 'Jackie Brown' 31 | ``` 32 | 33 | --- 34 | ### Parameters 35 | #### **ColorScheme** 36 | 37 | The name of the color scheme. 38 | 39 | 40 | 41 | > **Type**: ```[String[]]``` 42 | 43 | > **Required**: false 44 | 45 | > **Position**: 1 46 | 47 | > **PipelineInput**:true (ByPropertyName) 48 | 49 | 50 | 51 | --- 52 | ### Outputs 53 | * [Management.Automation.PSObject](https://learn.microsoft.com/en-us/dotnet/api/System.Management.Automation.PSObject) 54 | 55 | 56 | 57 | 58 | --- 59 | ### Syntax 60 | ```PowerShell 61 | Get-WTColorScheme [[-ColorScheme] ] [] 62 | ``` 63 | --- 64 | -------------------------------------------------------------------------------- /docs/Clear-WTColorScheme.md: -------------------------------------------------------------------------------- 1 | Clear-WTColorScheme 2 | ------------------- 3 | ### Synopsis 4 | Clears Windows Terminal Color Schemes 5 | 6 | --- 7 | ### Description 8 | 9 | Clears the Windows Terminal Color Scheme for the current profile. 10 | 11 | --- 12 | ### Related Links 13 | * [Get-WTColorScheme](Get-WTColorScheme.md) 14 | 15 | 16 | 17 | --- 18 | ### Examples 19 | #### EXAMPLE 1 20 | ```PowerShell 21 | Clear-WTColorScheme 22 | ``` 23 | 24 | --- 25 | ### Parameters 26 | #### **WhatIf** 27 | -WhatIf is an automatic variable that is created when a command has ```[CmdletBinding(SupportsShouldProcess)]```. 28 | -WhatIf is used to see what would happen, or return operations without executing them 29 | #### **Confirm** 30 | -Confirm is an automatic variable that is created when a command has ```[CmdletBinding(SupportsShouldProcess)]```. 31 | -Confirm is used to -Confirm each operation. 32 | 33 | If you pass ```-Confirm:$false``` you will not be prompted. 34 | 35 | 36 | If the command sets a ```[ConfirmImpact("Medium")]``` which is lower than ```$confirmImpactPreference```, you will not be prompted unless -Confirm is passed. 37 | 38 | --- 39 | ### Syntax 40 | ```PowerShell 41 | Clear-WTColorScheme [-WhatIf] [-Confirm] [] 42 | ``` 43 | --- 44 | -------------------------------------------------------------------------------- /TerminalVelocity.ezout.ps1: -------------------------------------------------------------------------------- 1 | #requires -Module EZOut 2 | # Install-Module EZOut or https://github.com/StartAutomating/EZOut 3 | $myFile = $MyInvocation.MyCommand.ScriptBlock.File 4 | $myModuleName = 'TerminalVelocity' 5 | $myRoot = $myFile | Split-Path 6 | Push-Location $myRoot 7 | $formatting = @( 8 | # Add your own Write-FormatView here, 9 | # or put them in a Formatting or Views directory 10 | foreach ($potentialDirectory in 'Formatting','Views') { 11 | Join-Path $myRoot $potentialDirectory | 12 | Get-ChildItem -ea ignore | 13 | Import-FormatView -FilePath {$_.Fullname} 14 | } 15 | ) 16 | 17 | $destinationRoot = $myRoot 18 | 19 | if ($formatting) { 20 | $myFormatFile = Join-Path $destinationRoot "$myModuleName.format.ps1xml" 21 | $formatting | Out-FormatData -Module $MyModuleName | Set-Content $myFormatFile -Encoding UTF8 22 | Get-Item $myFormatFile 23 | } 24 | 25 | $types = @( 26 | # Add your own Write-TypeView statements here 27 | # or declare them in the 'Types' directory 28 | Join-Path $myRoot Types | 29 | Get-Item -ea ignore | 30 | Import-TypeView 31 | 32 | ) 33 | 34 | if ($types) { 35 | $myTypesFile = Join-Path $destinationRoot "$myModuleName.types.ps1xml" 36 | $types | Out-TypeData | Set-Content $myTypesFile -Encoding UTF8 37 | Get-Item $myTypesFile 38 | } 39 | Pop-Location 40 | -------------------------------------------------------------------------------- /Backup-WTProfile.ps1: -------------------------------------------------------------------------------- 1 | function Backup-WTProfile 2 | { 3 | <# 4 | .Synopsis 5 | Backs up the Windows Terminal Profile 6 | .Description 7 | Backs up the Windows Terminal Profile. 8 | 9 | By default, backups will be placed in the same directory as $profile, and will include a datestamp. 10 | .Link 11 | Get-WTProfile 12 | .Example 13 | Backup-WTProfile 14 | #> 15 | param( 16 | # The destination path for the backup. 17 | # By default, this will be in the same directory as $profile, and will include a datestamp. 18 | [Parameter(ValueFromPipelineByPropertyName)] 19 | [string] 20 | $DestinationPath 21 | ) 22 | 23 | process { 24 | if (-not $DestinationPath) { 25 | $DestinationPath = $profile | 26 | Split-Path | 27 | Join-Path -ChildPath "WindowsTerminal.$([DateTime]::Now.ToString('yyyy-MM-dd')).backup.json" 28 | $null = New-Item -ItemType File -Path $DestinationPath -Force 29 | } 30 | 31 | $sourcePath = 32 | if (-not $script:WTProfilePath) { 33 | Get-WTProfile -Setting | Select-Object -ExpandProperty Path 34 | } else { 35 | $script:WTProfilePath.Fullname 36 | } 37 | if (-not $sourcePath) { return } 38 | 39 | 40 | Copy-Item -LiteralPath $sourcePath -Destination $DestinationPath -Force 41 | } 42 | } -------------------------------------------------------------------------------- /Remove-WTColorScheme.ps1: -------------------------------------------------------------------------------- 1 | function Remove-WTColorScheme 2 | { 3 | <# 4 | .Synopsis 5 | Removes color schemes from Windows Terminal. 6 | .Description 7 | Removes registered color schemes from Windows Terminal. 8 | .Example 9 | Remove-WTColorScheme -Name "The Hulk" 10 | .Link 11 | Add-WTColorScheme 12 | .Link 13 | Get-WTColorScheme 14 | .Link 15 | Set-WTColorScheme 16 | #> 17 | [CmdletBinding(SupportsShouldProcess,ConfirmImpact='Low')] 18 | param( 19 | # The name of the color scheme. 20 | [Parameter(Mandatory,ValueFromPipelineByPropertyName)] 21 | [Alias('Name')] 22 | [string[]] 23 | $ColorScheme 24 | ) 25 | 26 | process { 27 | #region Get Color Scheme 28 | $null = $PSBoundParameters.Remove('Confirm') 29 | $null = $PSBoundParameters.Remove('WhatIf') 30 | $allSchemes = Get-WTProfile -Global | Select-Object -ExpandProperty Schemes 31 | $updatedSchemes = @($allSchemes | 32 | Where-Object { 33 | foreach ($cs in $ColorScheme) { 34 | if ($_.Name -like $cs) { return $false } 35 | } 36 | return $true 37 | }) 38 | 39 | if ($PSCmdlet.ShouldProcess("Remove $ColorScheme")) { 40 | Set-WTProfile -ColorScheme $updatedSchemes -Confirm:$false -Global 41 | } 42 | #endregion Get Color Scheme 43 | 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /docs/rss.xml: -------------------------------------------------------------------------------- 1 | --- 2 | layout: null 3 | --- 4 | 5 | 6 | 7 | {{ site.title | xml_escape }} 8 | {{ site.description | xml_escape }} 9 | {{ site.url }}{{ site.baseurl }}/ 10 | 11 | {{ site.time | date_to_rfc822 }} 12 | {{ site.time | date_to_rfc822 }} 13 | Jekyll v{{ jekyll.version }} 14 | {% for post in site.posts limit:1000 %} 15 | {% if post.sitemap != false %} 16 | 17 | {{ post.title | xml_escape }} 18 | {{ post.content | xml_escape }} 19 | {{ post.date | date_to_rfc822 }} 20 | {{ post.url | prepend: site.baseurl | prepend: site.url }} 21 | {{ post.url | prepend: site.baseurl | prepend: site.url }} 22 | {% for tag in post.tags %} 23 | {{ tag | xml_escape }} 24 | {% endfor %} 25 | {% for cat in post.categories %} 26 | {{ cat | xml_escape }} 27 | {% endfor %} 28 | 29 | {% endif %} 30 | {% endfor %} 31 | 32 | 33 | -------------------------------------------------------------------------------- /TerminalVelocity.PSSVG.ps1: -------------------------------------------------------------------------------- 1 | #requires -Module PSSVG 2 | 3 | $assetsPath = Join-Path $PSScriptRoot Assets 4 | 5 | if (-not (Test-Path $assetsPath)) { 6 | $null = New-Item -ItemType Directory -path $assetsPath -Force 7 | } 8 | = -content $( 9 | $commonParameters = @{ 10 | Fill = '#4488FF' 11 | Stroke = 'black' 12 | StrokeWidth = '0.05' 13 | } 14 | 15 | = -Id psChevron -Content @( 16 | = -Points (@( 17 | "40,20" 18 | "45,20" 19 | "60,50" 20 | "35,80" 21 | "32.5,80" 22 | "55,50" 23 | ) -join ' ') 24 | ) -ViewBox 100, 100 25 | 26 | 27 | = -Href '#psChevron' -X -25% -Y 22.5% @commonParameters -Height 50% -Opacity .9 28 | # = -Text '>' -X 20 -Y 50 -FontSize 48 -Rotate -7 -FontFamily monospace @commonParameters 29 | = -X 50% -Y 50% -FontSize 20 -FontFamily monospace @commonParameters -DominantBaseline 'middle' -TextAnchor 'middle' @( 30 | = -FontSize 18 -Content "Terminal" -Dx -.5em -Dy -.5em 31 | = -FontSize 18 -Content "Velocity" -Dy .75em -Dx -3.9em 32 | ) -FontStyle 'italic' -Rotate '1' -Transform 'skewX(-10)' 33 | = -X1 30% -x2 61% -y1 65% -y2 65% -Stroke '#4488ff' -StrokeWidth 0.5% 34 | 35 | 36 | ) -ViewBox 0, 0, 300, 100 -OutputPath $( 37 | Join-Path (Join-Path $PSScriptRoot Assets) TerminalVelocity.svg 38 | ) -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 | 5 | 6 | #### Installing 7 | 8 | TerminalVelocity is on the PowerShell Gallery. To Install TerminalVelocity, run: 9 | ~~~PowerShell 10 | Install-Module TerminalVelocity -Scope CurrentUser 11 | ~~~ 12 | 13 | Once you've installed TerminalVelocity, here are a few handy things you can do with TerminalVelocity: 14 | 15 | #### Adding a new Profile 16 | ~~~PowerShell 17 | Add-WTProfile -Name kali-linux-pwsh -CommandLine 'wsl -d kali-linux -e pwsh' 18 | ~~~ 19 | 20 | 21 | #### Adding a new color scheme 22 | ~~~PowerShell 23 | Add-WTColorScheme -Name AdventureTime 24 | ~~~ 25 | 26 | 27 | #### Changing the color scheme 28 | ~~~PowerShell 29 | Set-WTColorScheme -Name AdventureTime -Passthru # The profile is automatically detected. 30 | ~~~ 31 | 32 | 33 | #### Starting a new Terminal 34 | ~~~PowerShell 35 | Start-WT -ProfileName PowerShell -CommandLine 'powershell -nologo -noexit -command $psVersionTable' 36 | ~~~ 37 | 38 | ~~~PowerShell 39 | Start-WT -Elevated # Start Windows Terminal Elevated 40 | ~~~ 41 | 42 | #### Flashing an image in Terminal 43 | ~~~PowerShell 44 | # The profile is automatically detected 45 | # The .gif will play once and then dissapear. 46 | Show-WT -ImagePath $home\Pictures\Gif\Whoa.gif 47 | ~~~ 48 | 49 | 50 | #### Preview color schemes 51 | ~~~PowerShell 52 | Get-WTColorScheme AdventureTime # This is formatted by PowerShell to show a preview. 53 | ~~~ 54 | ![Previwing Scheme 'AdventureTime'](Assets/Get-WTColorScheme.png) 55 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 | 5 | 6 | #### Installing 7 | 8 | TerminalVelocity is on the PowerShell Gallery. To Install TerminalVelocity, run: 9 | ~~~PowerShell 10 | Install-Module TerminalVelocity -Scope CurrentUser 11 | ~~~ 12 | 13 | Once you've installed TerminalVelocity, here are a few handy things you can do with TerminalVelocity: 14 | 15 | #### Adding a new Profile 16 | ~~~PowerShell 17 | Add-WTProfile -Name kali-linux-pwsh -CommandLine 'wsl -d kali-linux -e pwsh' 18 | ~~~ 19 | 20 | 21 | #### Adding a new color scheme 22 | ~~~PowerShell 23 | Add-WTColorScheme -Name AdventureTime 24 | ~~~ 25 | 26 | 27 | #### Changing the color scheme 28 | ~~~PowerShell 29 | Set-WTColorScheme -Name AdventureTime -Passthru # The profile is automatically detected. 30 | ~~~ 31 | 32 | 33 | #### Starting a new Terminal 34 | ~~~PowerShell 35 | Start-WT -ProfileName PowerShell -CommandLine 'powershell -nologo -noexit -command $psVersionTable' 36 | ~~~ 37 | 38 | ~~~PowerShell 39 | Start-WT -Elevated # Start Windows Terminal Elevated 40 | ~~~ 41 | 42 | #### Flashing an image in Terminal 43 | ~~~PowerShell 44 | # The profile is automatically detected 45 | # The .gif will play once and then dissapear. 46 | Show-WT -ImagePath $home\Pictures\Gif\Whoa.gif 47 | ~~~ 48 | 49 | 50 | #### Preview color schemes 51 | ~~~PowerShell 52 | Get-WTColorScheme AdventureTime # This is formatted by PowerShell to show a preview. 53 | ~~~ 54 | ![Previwing Scheme 'AdventureTime'](Assets/Get-WTColorScheme.png) 55 | 56 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 0.3.1: 2 | 3 | * Rebranded module to TerminalVelocity (Fixes #10) 4 | * Added logo (Fixes #13) (thanks to [PSSVG](https://pssvg.start-automating.com)) 5 | * Add/New/Set-WTProfile: Keeping in sync with Schema (Fixing #8) (thanks to [PipeScript](https://github.com/StartAutomating/PipeScript) ) 6 | * Set-WTProfile: 7 | * Added -Overwrite (Fixes #17) 8 | * Caching profile in memory (Fixes #11) 9 | * Show-WT: 10 | * Support for -PixelShaders (Fixes #14) 11 | * Made -Wait wait and added -Duration (Fixes #15) 12 | * Restoring profiles after -Duration (Fixes #16) 13 | * Autogenerating docs (Fixes #18) (thanks to [HelpOut](https://github.com/StartAutomating/HelpOut)) 14 | 15 | --- 16 | 17 | ## 0.3 18 | 19 | * New Commands: 20 | * Clear-WTColorScheme 21 | * Bugfixes 22 | * Show-WT now honors -UseAcrylic 23 | * Set-WTProfile -Current clarifies the current profile. 24 | * Add-WTProfile will now add profiles to the end. 25 | * Start-WT now handles -Split and multiple sequences effectively. 26 | 27 | --- 28 | 29 | ## 0.2 30 | * New Commands: 31 | * Backup/Restore-WTProfile 32 | * Remove-WTColorScheme 33 | 34 | * New Formatting: 35 | * Color Schemes can now be previewed. 36 | 37 | * Improved Commands: 38 | * Show-WT: 39 | * Can now show from a URI 40 | * Can now show from within WSL instance 41 | * Start-WT can now run -Elevated 42 | 43 | * Reliability improvements: 44 | * Set-WTProfile and Set-WTColorScheme now try up to three times 45 | * Show-WT now only clears the last image in a sequence, for improved perf and experience 46 | 47 | * Assetation: 48 | * Included demo of color scheme preview 49 | 50 | --- 51 | -------------------------------------------------------------------------------- /docs/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 0.3.1: 2 | 3 | * Rebranded module to TerminalVelocity (Fixes #10) 4 | * Added logo (Fixes #13) (thanks to [PSSVG](https://pssvg.start-automating.com)) 5 | * Add/New/Set-WTProfile: Keeping in sync with Schema (Fixing #8) (thanks to [PipeScript](https://github.com/StartAutomating/PipeScript) ) 6 | * Set-WTProfile: 7 | * Added -Overwrite (Fixes #17) 8 | * Caching profile in memory (Fixes #11) 9 | * Show-WT: 10 | * Support for -PixelShaders (Fixes #14) 11 | * Made -Wait wait and added -Duration (Fixes #15) 12 | * Restoring profiles after -Duration (Fixes #16) 13 | * Autogenerating docs (Fixes #18) (thanks to [HelpOut](https://github.com/StartAutomating/HelpOut)) 14 | 15 | --- 16 | 17 | ## 0.3 18 | 19 | * New Commands: 20 | * Clear-WTColorScheme 21 | * Bugfixes 22 | * Show-WT now honors -UseAcrylic 23 | * Set-WTProfile -Current clarifies the current profile. 24 | * Add-WTProfile will now add profiles to the end. 25 | * Start-WT now handles -Split and multiple sequences effectively. 26 | 27 | --- 28 | 29 | ## 0.2 30 | * New Commands: 31 | * Backup/Restore-WTProfile 32 | * Remove-WTColorScheme 33 | 34 | * New Formatting: 35 | * Color Schemes can now be previewed. 36 | 37 | * Improved Commands: 38 | * Show-WT: 39 | * Can now show from a URI 40 | * Can now show from within WSL instance 41 | * Start-WT can now run -Elevated 42 | 43 | * Reliability improvements: 44 | * Set-WTProfile and Set-WTColorScheme now try up to three times 45 | * Show-WT now only clears the last image in a sequence, for improved perf and experience 46 | 47 | * Assetation: 48 | * Included demo of color scheme preview 49 | 50 | --- 51 | 52 | -------------------------------------------------------------------------------- /docs/Remove-WTColorScheme.md: -------------------------------------------------------------------------------- 1 | Remove-WTColorScheme 2 | -------------------- 3 | ### Synopsis 4 | Removes color schemes from Windows Terminal. 5 | 6 | --- 7 | ### Description 8 | 9 | Removes registered color schemes from Windows Terminal. 10 | 11 | --- 12 | ### Related Links 13 | * [Add-WTColorScheme](Add-WTColorScheme.md) 14 | 15 | 16 | 17 | * [Get-WTColorScheme](Get-WTColorScheme.md) 18 | 19 | 20 | 21 | * [Set-WTColorScheme](Set-WTColorScheme.md) 22 | 23 | 24 | 25 | --- 26 | ### Examples 27 | #### EXAMPLE 1 28 | ```PowerShell 29 | Remove-WTColorScheme -Name "The Hulk" 30 | ``` 31 | 32 | --- 33 | ### Parameters 34 | #### **ColorScheme** 35 | 36 | The name of the color scheme. 37 | 38 | 39 | 40 | > **Type**: ```[String[]]``` 41 | 42 | > **Required**: true 43 | 44 | > **Position**: 1 45 | 46 | > **PipelineInput**:true (ByPropertyName) 47 | 48 | 49 | 50 | --- 51 | #### **WhatIf** 52 | -WhatIf is an automatic variable that is created when a command has ```[CmdletBinding(SupportsShouldProcess)]```. 53 | -WhatIf is used to see what would happen, or return operations without executing them 54 | #### **Confirm** 55 | -Confirm is an automatic variable that is created when a command has ```[CmdletBinding(SupportsShouldProcess)]```. 56 | -Confirm is used to -Confirm each operation. 57 | 58 | If you pass ```-Confirm:$false``` you will not be prompted. 59 | 60 | 61 | If the command sets a ```[ConfirmImpact("Medium")]``` which is lower than ```$confirmImpactPreference```, you will not be prompted unless -Confirm is passed. 62 | 63 | --- 64 | ### Syntax 65 | ```PowerShell 66 | Remove-WTColorScheme [-ColorScheme] [-WhatIf] [-Confirm] [] 67 | ``` 68 | --- 69 | -------------------------------------------------------------------------------- /docs/Stop-WT.md: -------------------------------------------------------------------------------- 1 | Stop-WT 2 | ------- 3 | ### Synopsis 4 | Stops Windows Terminal 5 | 6 | --- 7 | ### Description 8 | 9 | Stops Windows Terminal Processes 10 | 11 | --- 12 | ### Related Links 13 | * [Start-WT](Start-WT.md) 14 | 15 | 16 | 17 | * [Stop-Process](https://docs.microsoft.com/powershell/module/Microsoft.PowerShell.Management/Stop-Process) 18 | 19 | 20 | 21 | --- 22 | ### Examples 23 | #### EXAMPLE 1 24 | ```PowerShell 25 | Stop-WT 26 | ``` 27 | 28 | --- 29 | ### Parameters 30 | #### **ID** 31 | 32 | The Process ID 33 | 34 | 35 | 36 | > **Type**: ```[Int32[]]``` 37 | 38 | > **Required**: true 39 | 40 | > **Position**: named 41 | 42 | > **PipelineInput**:true (ByPropertyName) 43 | 44 | 45 | 46 | --- 47 | #### **WhatIf** 48 | -WhatIf is an automatic variable that is created when a command has ```[CmdletBinding(SupportsShouldProcess)]```. 49 | -WhatIf is used to see what would happen, or return operations without executing them 50 | #### **Confirm** 51 | -Confirm is an automatic variable that is created when a command has ```[CmdletBinding(SupportsShouldProcess)]```. 52 | -Confirm is used to -Confirm each operation. 53 | 54 | If you pass ```-Confirm:$false``` you will not be prompted. 55 | 56 | 57 | If the command sets a ```[ConfirmImpact("Medium")]``` which is lower than ```$confirmImpactPreference```, you will not be prompted unless -Confirm is passed. 58 | 59 | --- 60 | ### Outputs 61 | * [Nullable](https://learn.microsoft.com/en-us/dotnet/api/System.Nullable) 62 | 63 | 64 | 65 | 66 | --- 67 | ### Syntax 68 | ```PowerShell 69 | Stop-WT [-WhatIf] [-Confirm] [] 70 | ``` 71 | ```PowerShell 72 | Stop-WT -ID [-WhatIf] [-Confirm] [] 73 | ``` 74 | --- 75 | -------------------------------------------------------------------------------- /TerminalVelocity.psd1: -------------------------------------------------------------------------------- 1 | @{ 2 | ModuleVersion='0.3.1' 3 | RootModule='TerminalVelocity.psm1' 4 | GUID = '3d3087f6-7d8f-484a-aff5-4275c9f61f24' 5 | Author = 'James Brundage' 6 | Copyright = '2020-2022 Start-Automating' 7 | Description = 'Fine tuning Windows Terminal' 8 | PrivateData = @{ 9 | PSData = @{ 10 | Tags = 'WindowsTerminal','TerminalVelocity' 11 | ProjectURI = 'https://github.com/StartAutomating/TerminalVelocity' 12 | LicenseURI = 'https://github.com/StartAutomating/TerminalVelocity/blob/main/LICENSE' 13 | ReleaseNotes = @' 14 | ## 0.3.1: 15 | 16 | * Rebranded module to TerminalVelocity (Fixes #10) 17 | * Added logo (Fixes #13) (thanks to [PSSVG](https://pssvg.start-automating.com)) 18 | * Add/New/Set-WTProfile: Keeping in sync with Schema (Fixing #8) (thanks to [PipeScript](https://github.com/StartAutomating/PipeScript) ) 19 | * Set-WTProfile: 20 | * Added -Overwrite (Fixes #17) 21 | * Caching profile in memory (Fixes #11) 22 | * Show-WT: 23 | * Support for -PixelShaders (Fixes #14) 24 | * Made -Wait wait and added -Duration (Fixes #15) 25 | * Restoring profiles after -Duration (Fixes #16) 26 | * Autogenerating docs (Fixes #18) (thanks to [HelpOut](https://github.com/StartAutomating/HelpOut)) 27 | 28 | --- 29 | 30 | ## 0.3 31 | 32 | * New Commands: 33 | * Clear-WTColorScheme 34 | * Bugfixes 35 | * Show-WT now honors -UseAcrylic 36 | * Set-WTProfile -Current clarifies the current profile. 37 | * Add-WTProfile will now add profiles to the end. 38 | * Start-WT now handles -Split and multiple sequences effectively. 39 | 40 | --- 41 | 42 | ## 0.2 43 | * New Commands: 44 | * Backup/Restore-WTProfile 45 | * Remove-WTColorScheme 46 | 47 | * New Formatting: 48 | * Color Schemes can now be previewed. 49 | 50 | * Improved Commands: 51 | * Show-WT: 52 | * Can now show from a URI 53 | * Can now show from within WSL instance 54 | * Start-WT can now run -Elevated 55 | 56 | * Reliability improvements: 57 | * Set-WTProfile and Set-WTColorScheme now try up to three times 58 | * Show-WT now only clears the last image in a sequence, for improved perf and experience 59 | 60 | * Assetation: 61 | * Included demo of color scheme preview 62 | 63 | --- 64 | '@ 65 | } 66 | } 67 | FormatsToProcess = 'TerminalVelocity.format.ps1xml' 68 | } -------------------------------------------------------------------------------- /docs/_posts/2022-11-08-TerminalVelocity-0.3.1.md: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | title: TerminalVelocity 0.3.1 4 | sourceURL: https://github.com/StartAutomating/TerminalVelocity/releases/tag/v0.3.1 5 | tag: release 6 | --- 7 | ## 0.3.1: 8 | 9 | * Rebranded module to TerminalVelocity (Fixes [#10](https://github.com/StartAutomating/TerminalVelocity/issues/10)) 10 | * Added logo (Fixes [#13](https://github.com/StartAutomating/TerminalVelocity/issues/13)) (thanks to [PSSVG](https://pssvg.start-automating.com)) 11 | * Add/New/Set-WTProfile: Keeping in sync with Schema (Fixing [#8](https://github.com/StartAutomating/TerminalVelocity/issues/8)) (thanks to [PipeScript](https://github.com/StartAutomating/PipeScript) ) 12 | * Set-WTProfile: 13 | * Added -Overwrite (Fixes [#17](https://github.com/StartAutomating/TerminalVelocity/issues/17)) 14 | * Caching profile in memory (Fixes [#11](https://github.com/StartAutomating/TerminalVelocity/issues/11)) 15 | * Show-WT: 16 | * Support for -PixelShaders (Fixes [#14](https://github.com/StartAutomating/TerminalVelocity/issues/14)) 17 | * Made -Wait wait and added -Duration (Fixes [#15](https://github.com/StartAutomating/TerminalVelocity/issues/15)) 18 | * Restoring profiles after -Duration (Fixes [#16](https://github.com/StartAutomating/TerminalVelocity/issues/16)) 19 | * Autogenerating docs (Fixes [#18](https://github.com/StartAutomating/TerminalVelocity/issues/18)) (thanks to [HelpOut](https://github.com/StartAutomating/HelpOut)) 20 | 21 | --- 22 | 23 | ## 0.3 24 | 25 | * New Commands: 26 | * Clear-WTColorScheme 27 | * Bugfixes 28 | * Show-WT now honors -UseAcrylic 29 | * Set-WTProfile -Current clarifies the current profile. 30 | * Add-WTProfile will now add profiles to the end. 31 | * Start-WT now handles -Split and multiple sequences effectively. 32 | 33 | --- 34 | 35 | ## 0.2 36 | * New Commands: 37 | * Backup/Restore-WTProfile 38 | * Remove-WTColorScheme 39 | 40 | * New Formatting: 41 | * Color Schemes can now be previewed. 42 | 43 | * Improved Commands: 44 | * Show-WT: 45 | * Can now show from a URI 46 | * Can now show from within WSL instance 47 | * Start-WT can now run -Elevated 48 | 49 | * Reliability improvements: 50 | * Set-WTProfile and Set-WTColorScheme now try up to three times 51 | * Show-WT now only clears the last image in a sequence, for improved perf and experience 52 | 53 | * Assetation: 54 | * Included demo of color scheme preview 55 | 56 | --- 57 | -------------------------------------------------------------------------------- /docs/Remove-WTProfile.md: -------------------------------------------------------------------------------- 1 | Remove-WTProfile 2 | ---------------- 3 | ### Synopsis 4 | Removes a Windows Terminal Profile 5 | 6 | --- 7 | ### Description 8 | 9 | Removes Windows Terminal Profiles, 10 | or removes one or more -Property from a Windows Terminal profile. 11 | 12 | --- 13 | ### Related Links 14 | * [Add-WTProfile](Add-WTProfile.md) 15 | 16 | 17 | 18 | --- 19 | ### Examples 20 | #### EXAMPLE 1 21 | ```PowerShell 22 | Add-WTProfile -Name 'DOS' -CommandLine cmd # Add a DOS profile 23 | ``` 24 | Remove-WTProfile -Name DOS # and get rid of it. 25 | --- 26 | ### Parameters 27 | #### **ProfileName** 28 | 29 | The name of the profile. 30 | 31 | 32 | 33 | > **Type**: ```[String[]]``` 34 | 35 | > **Required**: true 36 | 37 | > **Position**: named 38 | 39 | > **PipelineInput**:true (ByPropertyName) 40 | 41 | 42 | 43 | --- 44 | #### **Default** 45 | 46 | If -Default is present with no other parameters, clears the default profile settings. 47 | If -Property is also present, removes properties from the default profile settings. 48 | 49 | 50 | 51 | > **Type**: ```[Switch]``` 52 | 53 | > **Required**: true 54 | 55 | > **Position**: named 56 | 57 | > **PipelineInput**:true (ByPropertyName) 58 | 59 | 60 | 61 | --- 62 | #### **Property** 63 | 64 | The name of one or more properties to remove from a profile. 65 | 66 | 67 | 68 | > **Type**: ```[String[]]``` 69 | 70 | > **Required**: false 71 | 72 | > **Position**: named 73 | 74 | > **PipelineInput**:true (ByPropertyName) 75 | 76 | 77 | 78 | --- 79 | #### **WhatIf** 80 | -WhatIf is an automatic variable that is created when a command has ```[CmdletBinding(SupportsShouldProcess)]```. 81 | -WhatIf is used to see what would happen, or return operations without executing them 82 | #### **Confirm** 83 | -Confirm is an automatic variable that is created when a command has ```[CmdletBinding(SupportsShouldProcess)]```. 84 | -Confirm is used to -Confirm each operation. 85 | 86 | If you pass ```-Confirm:$false``` you will not be prompted. 87 | 88 | 89 | If the command sets a ```[ConfirmImpact("Medium")]``` which is lower than ```$confirmImpactPreference```, you will not be prompted unless -Confirm is passed. 90 | 91 | --- 92 | ### Outputs 93 | * [Management.Automation.PSObject](https://learn.microsoft.com/en-us/dotnet/api/System.Management.Automation.PSObject) 94 | 95 | 96 | 97 | 98 | --- 99 | ### Syntax 100 | ```PowerShell 101 | Remove-WTProfile -ProfileName [-Property ] [-WhatIf] [-Confirm] [] 102 | ``` 103 | ```PowerShell 104 | Remove-WTProfile -Default [-Property ] [-WhatIf] [-Confirm] [] 105 | ``` 106 | --- 107 | -------------------------------------------------------------------------------- /docs/Set-WTColorScheme.md: -------------------------------------------------------------------------------- 1 | Set-WTColorScheme 2 | ----------------- 3 | ### Synopsis 4 | Sets the Windows Terminal Color Scheme 5 | 6 | --- 7 | ### Description 8 | 9 | Sets the color scheme used by a given tab profile in Windows Terminal. 10 | 11 | If the tab profile is not provided, it will attempt to auto-detect based off of the window title. 12 | 13 | --- 14 | ### Related Links 15 | * [Add-WTColorScheme](Add-WTColorScheme.md) 16 | 17 | 18 | 19 | * [Get-WTColorScheme](Get-WTColorScheme.md) 20 | 21 | 22 | 23 | --- 24 | ### Examples 25 | #### EXAMPLE 1 26 | ```PowerShell 27 | Set-WTColorScheme -ColorScheme 'AdventureTime' 28 | ``` 29 | 30 | #### EXAMPLE 2 31 | ```PowerShell 32 | Get-WTProfile -Name 'PowerShell' | 33 | Set-WTColorScheme 'AdventureTime' 34 | ``` 35 | 36 | --- 37 | ### Parameters 38 | #### **ColorScheme** 39 | 40 | The name of the color scheme 41 | 42 | 43 | 44 | > **Type**: ```[String]``` 45 | 46 | > **Required**: true 47 | 48 | > **Position**: 1 49 | 50 | > **PipelineInput**:true (ByPropertyName) 51 | 52 | 53 | 54 | --- 55 | #### **ProfileName** 56 | 57 | The name or ID of the tab profiles the color scheme will be applied to. 58 | If this is not provided, it will attempt to auto-detect based off of the window title. 59 | 60 | 61 | 62 | > **Type**: ```[String[]]``` 63 | 64 | > **Required**: false 65 | 66 | > **Position**: 2 67 | 68 | > **PipelineInput**:true (ByPropertyName) 69 | 70 | 71 | 72 | --- 73 | #### **PassThru** 74 | 75 | If set, will pass thru the changes. 76 | 77 | 78 | 79 | > **Type**: ```[Switch]``` 80 | 81 | > **Required**: false 82 | 83 | > **Position**: named 84 | 85 | > **PipelineInput**:false 86 | 87 | 88 | 89 | --- 90 | #### **WhatIf** 91 | -WhatIf is an automatic variable that is created when a command has ```[CmdletBinding(SupportsShouldProcess)]```. 92 | -WhatIf is used to see what would happen, or return operations without executing them 93 | #### **Confirm** 94 | -Confirm is an automatic variable that is created when a command has ```[CmdletBinding(SupportsShouldProcess)]```. 95 | -Confirm is used to -Confirm each operation. 96 | 97 | If you pass ```-Confirm:$false``` you will not be prompted. 98 | 99 | 100 | If the command sets a ```[ConfirmImpact("Medium")]``` which is lower than ```$confirmImpactPreference```, you will not be prompted unless -Confirm is passed. 101 | 102 | --- 103 | ### Outputs 104 | * [Nullable](https://learn.microsoft.com/en-us/dotnet/api/System.Nullable) 105 | 106 | 107 | 108 | 109 | --- 110 | ### Syntax 111 | ```PowerShell 112 | Set-WTColorScheme [-ColorScheme] [[-ProfileName] ] [-PassThru] [-WhatIf] [-Confirm] [] 113 | ``` 114 | --- 115 | -------------------------------------------------------------------------------- /docs/Get-WTProfile.md: -------------------------------------------------------------------------------- 1 | Get-WTProfile 2 | ------------- 3 | ### Synopsis 4 | Gets a Windows Terminal Profiles 5 | 6 | --- 7 | ### Description 8 | 9 | Gets Windows Terminal profiles. 10 | 11 | By default, Get-WTProfile gets all tab profiles. 12 | 13 | To get the global profile, use Get-WTProfile -Global 14 | 15 | To get color schemes, use Get-WTProfile -ColorScheme * 16 | 17 | --- 18 | ### Related Links 19 | * [Set-WTProfile](Set-WTProfile.md) 20 | 21 | 22 | 23 | --- 24 | ### Examples 25 | #### EXAMPLE 1 26 | ```PowerShell 27 | Get-WTProfile 28 | ``` 29 | 30 | #### EXAMPLE 2 31 | ```PowerShell 32 | Get-WTProfile -Global 33 | ``` 34 | 35 | --- 36 | ### Parameters 37 | #### **ProfileName** 38 | 39 | Returns Windows Terminal tab profiles, by name. 40 | 41 | 42 | 43 | > **Type**: ```[String[]]``` 44 | 45 | > **Required**: false 46 | 47 | > **Position**: named 48 | 49 | > **PipelineInput**:true (ByPropertyName) 50 | 51 | 52 | 53 | --- 54 | #### **Guid** 55 | 56 | Returns Windows Terminal tab profiles, by GUID. 57 | 58 | 59 | 60 | > **Type**: ```[Guid[]]``` 61 | 62 | > **Required**: false 63 | 64 | > **Position**: named 65 | 66 | > **PipelineInput**:true (ByPropertyName) 67 | 68 | 69 | 70 | --- 71 | #### **ColorScheme** 72 | 73 | Returns Windows Terminal Color Schemes 74 | 75 | 76 | 77 | > **Type**: ```[String[]]``` 78 | 79 | > **Required**: false 80 | 81 | > **Position**: named 82 | 83 | > **PipelineInput**:true (ByPropertyName) 84 | 85 | 86 | 87 | --- 88 | #### **Setting** 89 | 90 | If -Setting is present, Get-WTProfile returns the global settings. 91 | 92 | 93 | 94 | > **Type**: ```[Switch]``` 95 | 96 | > **Required**: true 97 | 98 | > **Position**: named 99 | 100 | > **PipelineInput**:true (ByPropertyName) 101 | 102 | 103 | 104 | --- 105 | #### **Default** 106 | 107 | If -Default is present, Get-WTProfile returns the default profile settings. 108 | 109 | 110 | 111 | > **Type**: ```[Switch]``` 112 | 113 | > **Required**: true 114 | 115 | > **Position**: named 116 | 117 | > **PipelineInput**:true (ByPropertyName) 118 | 119 | 120 | 121 | --- 122 | #### **Current** 123 | 124 | If -Current is present, Get-WTProfile attempts to determine the current profile 125 | 126 | 127 | 128 | > **Type**: ```[Switch]``` 129 | 130 | > **Required**: true 131 | 132 | > **Position**: named 133 | 134 | > **PipelineInput**:true (ByPropertyName) 135 | 136 | 137 | 138 | --- 139 | #### **KeyBinding** 140 | 141 | If -KeyBinding is present, Get-WTProfile will return keybindings. 142 | 143 | 144 | 145 | > **Type**: ```[Switch]``` 146 | 147 | > **Required**: true 148 | 149 | > **Position**: named 150 | 151 | > **PipelineInput**:true (ByPropertyName) 152 | 153 | 154 | 155 | --- 156 | #### **Force** 157 | 158 | If set, will force reloading of profile information. 159 | By default, the profile object will be cached to improve performance. 160 | 161 | 162 | 163 | > **Type**: ```[Switch]``` 164 | 165 | > **Required**: false 166 | 167 | > **Position**: named 168 | 169 | > **PipelineInput**:false 170 | 171 | 172 | 173 | --- 174 | ### Outputs 175 | * WindowsTerminal.Profile 176 | 177 | 178 | * WindowsTerminal.ColorScheme 179 | 180 | 181 | 182 | 183 | --- 184 | ### Syntax 185 | ```PowerShell 186 | Get-WTProfile [-ProfileName ] [-Force] [] 187 | ``` 188 | ```PowerShell 189 | Get-WTProfile [-Guid ] [-Force] [] 190 | ``` 191 | ```PowerShell 192 | Get-WTProfile [-ColorScheme ] [-Force] [] 193 | ``` 194 | ```PowerShell 195 | Get-WTProfile -Setting [-Force] [] 196 | ``` 197 | ```PowerShell 198 | Get-WTProfile -Default [-Force] [] 199 | ``` 200 | ```PowerShell 201 | Get-WTProfile -Current [-Force] [] 202 | ``` 203 | ```PowerShell 204 | Get-WTProfile -KeyBinding [-Force] [] 205 | ``` 206 | --- 207 | -------------------------------------------------------------------------------- /docs/Start-WT.md: -------------------------------------------------------------------------------- 1 | Start-WT 2 | -------- 3 | ### Synopsis 4 | Starts a new instance of Windows Terminal 5 | 6 | --- 7 | ### Description 8 | 9 | Starts a new instance of Windows Terminal, and sends commands to it. 10 | 11 | --- 12 | ### Related Links 13 | * [Get-WTProfile](Get-WTProfile.md) 14 | 15 | 16 | 17 | --- 18 | ### Examples 19 | #### EXAMPLE 1 20 | ```PowerShell 21 | Start-WT 22 | ``` 23 | 24 | #### EXAMPLE 2 25 | ```PowerShell 26 | Start-WT -Profile PowerShell 27 | ``` 28 | 29 | #### EXAMPLE 3 30 | ```PowerShell 31 | Start-WT -Profile 'Windows PowerShell' -CommandLine 'powershell -nologo' 32 | ``` 33 | 34 | --- 35 | ### Parameters 36 | #### **ProfileName** 37 | 38 | The name of the Windows Terminal Tab profile 39 | 40 | 41 | 42 | > **Type**: ```[String]``` 43 | 44 | > **Required**: false 45 | 46 | > **Position**: 1 47 | 48 | > **PipelineInput**:true (ByPropertyName) 49 | 50 | 51 | 52 | --- 53 | #### **WorkingDirectory** 54 | 55 | The working directory used by Windows Terminal 56 | 57 | 58 | 59 | > **Type**: ```[String]``` 60 | 61 | > **Required**: false 62 | 63 | > **Position**: 2 64 | 65 | > **PipelineInput**:true (ByPropertyName) 66 | 67 | 68 | 69 | --- 70 | #### **CommandLine** 71 | 72 | The command line run by Windows Terminal 73 | 74 | 75 | 76 | > **Type**: ```[String]``` 77 | 78 | > **Required**: false 79 | 80 | > **Position**: 3 81 | 82 | > **PipelineInput**:true (ByPropertyName) 83 | 84 | 85 | 86 | --- 87 | #### **Split** 88 | 89 | If set, will split the pane. 90 | 91 | 92 | 93 | > **Type**: ```[Switch]``` 94 | 95 | > **Required**: false 96 | 97 | > **Position**: named 98 | 99 | > **PipelineInput**:true (ByPropertyName) 100 | 101 | 102 | 103 | --- 104 | #### **SplitDirection** 105 | 106 | If provided, will split the pane horizontally or veritcally 107 | 108 | 109 | 110 | Valid Values: 111 | 112 | * Horizontal 113 | * H 114 | * Vertical 115 | * V 116 | 117 | 118 | 119 | > **Type**: ```[String]``` 120 | 121 | > **Required**: false 122 | 123 | > **Position**: 4 124 | 125 | > **PipelineInput**:true (ByPropertyName) 126 | 127 | 128 | 129 | --- 130 | #### **FocusTabIndex** 131 | 132 | If provided, will focus a given tab index. 133 | 134 | 135 | 136 | > **Type**: ```[Int32]``` 137 | 138 | > **Required**: false 139 | 140 | > **Position**: 5 141 | 142 | > **PipelineInput**:true (ByPropertyName) 143 | 144 | 145 | 146 | --- 147 | #### **FocusNextTab** 148 | 149 | If provided, will focus the next tab. 150 | 151 | 152 | 153 | > **Type**: ```[Switch]``` 154 | 155 | > **Required**: false 156 | 157 | > **Position**: named 158 | 159 | > **PipelineInput**:true (ByPropertyName) 160 | 161 | 162 | 163 | --- 164 | #### **FocusPreviousTab** 165 | 166 | If provided, will focus the previous tab. 167 | 168 | 169 | 170 | > **Type**: ```[Switch]``` 171 | 172 | > **Required**: false 173 | 174 | > **Position**: named 175 | 176 | > **PipelineInput**:true (ByPropertyName) 177 | 178 | 179 | 180 | --- 181 | #### **Passthru** 182 | 183 | If set, will return the created process. 184 | 185 | 186 | 187 | > **Type**: ```[Switch]``` 188 | 189 | > **Required**: false 190 | 191 | > **Position**: named 192 | 193 | > **PipelineInput**:false 194 | 195 | 196 | 197 | --- 198 | #### **Elevated** 199 | 200 | If set, will start the process elevated 201 | 202 | 203 | 204 | > **Type**: ```[Switch]``` 205 | 206 | > **Required**: false 207 | 208 | > **Position**: named 209 | 210 | > **PipelineInput**:false 211 | 212 | 213 | 214 | --- 215 | ### Outputs 216 | * [Nullable](https://learn.microsoft.com/en-us/dotnet/api/System.Nullable) 217 | 218 | 219 | * [Diagnostics.Process](https://learn.microsoft.com/en-us/dotnet/api/System.Diagnostics.Process) 220 | 221 | 222 | 223 | 224 | --- 225 | ### Syntax 226 | ```PowerShell 227 | Start-WT [[-ProfileName] ] [[-WorkingDirectory] ] [[-CommandLine] ] [-Split] [[-SplitDirection] ] [[-FocusTabIndex] ] [-FocusNextTab] [-FocusPreviousTab] [-Passthru] [-Elevated] [] 228 | ``` 229 | --- 230 | -------------------------------------------------------------------------------- /Formatting/WindowsTerminal.ColorScheme.format.ps1: -------------------------------------------------------------------------------- 1 | [OutputType('WindowsTerminal.ColorScheme')] 2 | param() 3 | 4 | Write-FormatViewExpression -If { $host.UI.SupportsVirtualTerminal } -ScriptBlock { 5 | $colorScheme = $_ 6 | $bufferWidth = $host.UI.RawUI.BufferSize.Width 7 | 8 | if ($bufferWidth -lt 110){ 9 | @( 10 | $colorScheme = $_ 11 | . $setOutputStyle -Foreground $colorScheme.foreground -Background $colorScheme.background 12 | $colorScheme.name 13 | . $clearOutputStyle 14 | ) -join '' 15 | return 16 | } 17 | 18 | @( 19 | @( 20 | 21 | 22 | $bgColors = 'Background','Black','Red','Green', 'Yellow', 'Blue', 'Purple','Cyan','White' 23 | $bgColorWidth = $host.UI.RawUI.BufferSize.Width / ($bgColors.Length + 1) 24 | 25 | $bigEnoughForColors =$host.UI.RawUI.BufferSize.Width -ge 124 26 | 27 | 28 | 29 | $headerLine = 30 | @(for ($n =0; $n -lt $bgColors.Length; $n++) { 31 | $colWidth = 32 | if ($n -eq 0) { 33 | 14 34 | } elseif ($n -eq 1) { 35 | 9 36 | } else { 37 | $bgColorWidth 38 | } 39 | 40 | $space = [Math]::Max(0, $colWidth - $bgColors[$n].Length) 41 | "$(' ' * [Math]::Ceiling($space /2))$($bgColors[$n])$(' ' * [Math]::Floor($space /2))|" 42 | 43 | }) -join '' 44 | 45 | 46 | (. $setOutputStyle -Background $colorScheme.background -foreground $colorScheme.foreground) + 47 | "$('---' + $colorScheme.Name + ('-' * ($headerLine.Length - 4 - $colorScheme.Name.Length)) + '|')" + 48 | ( & $clearOutputStyle) 49 | 50 | #. $setOutputStyle -Foreground $colorScheme.Foreground -Background $colorScheme.Background 51 | (. $setOutputStyle -Background $colorScheme.background -foreground $colorScheme.foreground) + $headerLine + ( & $clearOutputStyle) 52 | foreach ($fg in 'Foreground','BrightWhite','Black','BrightBlack', 53 | 'Red', 'BrightRed','Green','BrightGreen','Yellow','BrightYellow', 54 | 'Blue','BrightBlue','Purple','BrightPurple', 'Cyan', 'BrightCyan','White','BrightWhite') { 55 | $line = ''# . $setOutputStyle -Foreground $colorScheme.($fg) 56 | 57 | $line += @( 58 | $n = 0 59 | 60 | foreach ($bg in $bgColors) { 61 | $bgColor = $colorScheme.$bg 62 | 63 | & $setOutputStyle -Background $colorScheme.$bg 64 | $t = if ($n -eq 0) { 65 | $fg 66 | $colWidth = 14 67 | } elseif ($n -eq 1) { 68 | "$($colorScheme.$fg)" 69 | $colWidth = 9 70 | } else { 71 | if ($bigEnoughForColors) { 72 | "$($colorScheme.$fg)" 73 | } else { 74 | "E.g" 75 | } 76 | $colWidth = $bgColorWidth 77 | } 78 | $space = [Math]::Max(0, $colWidth - $t.Length) 79 | if ($n -gt 0) { 80 | & $setOutputStyle -Foreground $colorScheme.$fg -Background $bgColor 81 | } else { 82 | & $setOutputStyle -Foreground $colorScheme.Foreground -Background $bgColor 83 | } 84 | "$(' ' * [Math]::Floor($space /2))$t$(' ' * [Math]::Ceiling($space /2))" 85 | 86 | 87 | & $setOutputStyle -Foreground $colorScheme.foreground -Background $colorScheme.background 88 | "|" 89 | & $clearOutputStyle 90 | $n++ 91 | } 92 | ) -join '' 93 | $line.Trim() + ( & $clearOutputStyle) 94 | #"$($fg)".PadRight($host.UI.RawUI.BufferSize.Width) 95 | } 96 | ) -join [Environment]::NewLine 97 | <# 98 | @( 99 | foreach ($fg in $colorScheme.psobject.properties) { 100 | if ($fg.Name -eq 'Name') { continue} 101 | . $setOutputStyle -Foreground $colorScheme.($fg.Name) 102 | "$($fg.Name)".PadRight($host.UI.RawUI.BufferSize.Width) 103 | } 104 | ) 105 | #> 106 | . $clearOutputStyle 107 | ) -join '' 108 | return 109 | 110 | 111 | 112 | 113 | 114 | } 115 | 116 | 117 | 118 | Write-FormatViewExpression -If { -not $Host.ui.SupportsVirtualTerminal } -ScriptBlock { 119 | $_.Name + ([Environment]::NewLine * 2) + ($_ | Select-Object -Property * -ExcludeProperty Name | Format-List | Out-String) 120 | } 121 | 122 | -------------------------------------------------------------------------------- /Set-WTColorScheme.ps1: -------------------------------------------------------------------------------- 1 | function Set-WTColorScheme 2 | { 3 | <# 4 | .Synopsis 5 | Sets the Windows Terminal Color Scheme 6 | .Description 7 | Sets the color scheme used by a given tab profile in Windows Terminal. 8 | 9 | If the tab profile is not provided, it will attempt to auto-detect based off of the window title. 10 | .Example 11 | Set-WTColorScheme -ColorScheme 'AdventureTime' 12 | .Example 13 | Get-WTProfile -Name 'PowerShell' | 14 | Set-WTColorScheme 'AdventureTime' 15 | .Link 16 | Add-WTColorScheme 17 | .Link 18 | Get-WTColorScheme 19 | #> 20 | [CmdletBinding(SupportsShouldProcess,ConfirmImpact='Medium')] 21 | [OutputType([Nullable])] 22 | param( 23 | # The name of the color scheme 24 | [Parameter(Mandatory,ValueFromPipelineByPropertyName)] 25 | [Alias('Name')] 26 | [string] 27 | $ColorScheme, 28 | 29 | # The name or ID of the tab profiles the color scheme will be applied to. 30 | # If this is not provided, it will attempt to auto-detect based off of the window title. 31 | [Parameter(ValueFromPipelineByPropertyName)] 32 | [Alias('Profile','GUID')] 33 | [string[]] 34 | $ProfileName, 35 | 36 | # If set, will pass thru the changes. 37 | [switch] 38 | $PassThru 39 | ) 40 | 41 | process { 42 | 43 | $prof = Get-WTProfile -Global 44 | 45 | if ($_.Name -and $_.Guid) { # If we've been piped in a profile 46 | $ProfileName = $_.Guid 47 | } 48 | 49 | #region Find the tab profile target 50 | if (-not $ProfileName -and $env:WT_PROFILE_ID) { 51 | $ProfileName = $env:WT_PROFILE_ID 52 | if (-not $ProfileName) { 53 | Write-Warning "Could not find Windows Terminal profile. Changing default instead." 54 | } 55 | } 56 | #endregion Find the tab profile target 57 | 58 | #region Change Tab profile target 59 | $changed = @() 60 | foreach ($tabProf in $prof.profiles.list) { 61 | if ($ProfileName) { 62 | $ok = $false 63 | foreach ($tp in $ProfileName) { 64 | if ($tabProf.Name -like $tp -or 65 | $tabProf.Guid -eq $tp -or 66 | $tabProf.Guid -eq "{$tp}" 67 | ) 68 | { 69 | $ok = $true 70 | break 71 | } 72 | } 73 | } 74 | 75 | if ($ok -and $tabProf.colorScheme -ne $ColorScheme) { 76 | $changed +=$tabProf | Add-Member NoteProperty colorScheme $ColorScheme -Force -PassThru 77 | } 78 | } 79 | if (-not $changed -and -not $ProfileName) { 80 | if ($prof.profiles.default.colorScheme -ne $ColorScheme) { 81 | $changed += $prof.profiles.default | 82 | Add-Member NoteProperty colorScheme $ColorScheme -Force -PassThru 83 | } 84 | } 85 | #endregion Change Tab profile target 86 | 87 | #region Update File 88 | if ($changed -and $PSCmdlet.ShouldProcess("Update $($prof.Path)")) { 89 | $wtPath = $prof.Path 90 | $prof.psobject.properties.Remove('Path') 91 | $json = $prof | ConvertTo-Json -Depth 100 92 | $tries = 3 93 | do { 94 | try { 95 | [IO.File]::WriteAllText($wtPath, $JSON, [Text.Encoding]::UTF8) 96 | break 97 | } catch { 98 | $tries-- 99 | Write-Warning "$_ : $tries Left" 100 | [Threading.Thread]::Sleep(100) 101 | } 102 | } while ($tries) 103 | $prof.psobject.properties.add([PSNoteProperty]::new('Path', $wtPath)) 104 | } 105 | 106 | if ($WhatIfPreference) { 107 | $changed 108 | } 109 | 110 | if ($PassThru) { 111 | $changedNames = $changed | Select-Object -ExpandProperty colorScheme -Unique 112 | $prof.schemes | 113 | Where-Object {$changedNames -contains $_.Name } | 114 | ForEach-Object { 115 | $_.pstypenames.clear() 116 | $_.pstypenames.add('WindowsTerminal.ColorScheme') 117 | $_ 118 | } 119 | 120 | } 121 | #endregion Update File 122 | } 123 | } -------------------------------------------------------------------------------- /Add-WTProfile.ps.ps1: -------------------------------------------------------------------------------- 1 | function Add-WTProfile 2 | { 3 | <# 4 | .Synopsis 5 | Adds a new Windows Terminal profile 6 | .Description 7 | Adds a new Windows Terminal tab profile. 8 | .Link 9 | New-WTProfile 10 | .Example 11 | Add-WTProfile -Name kali-linux-pwsh -CommandLine 'wsl -d kali-linux -e pwsh' 12 | #> 13 | [OutputType('Nullable','WindowsTerminal.Profile')] 14 | [CmdletBinding(SupportsShouldProcess)] 15 | [JSONSchema(SchemaUri='https://aka.ms/terminal-profiles-schema#Profile',RemovePropertyPrefix='Experimental')] 16 | param( 17 | # Name of the profile. Displays in the dropdown menu. 18 | [Parameter(Mandatory,ValueFromPipelineByPropertyName)] 19 | [Alias('ProfileName')] 20 | [ComponentModel.DefaultBindingProperty("name")] 21 | [string] 22 | $Name 23 | ) 24 | 25 | begin { 26 | $myParameters = $MyInvocation.MyCommand.Parameters.Values 27 | $myProfileProperties = :nextParam foreach ($param in $myParameters) { 28 | foreach ($attr in $param.Attributes) { 29 | if ($attr -is [ComponentModel.DefaultBindingPropertyAttribute]) { 30 | $param 31 | continue nextParam 32 | } 33 | } 34 | } 35 | } 36 | 37 | process { 38 | 39 | $myParameters = [Ordered]@{} + $PSBoundParameters 40 | if (-not $myParameters["Guid"]) { 41 | $myParameters["Guid"] = "{$([GUID]::NewGuid())}" 42 | } 43 | $myProfileParameters = [Ordered]@{} 44 | foreach ($myProfileProperty in $myProfileProperties) { 45 | if ($myParameters.Contains($myProfileProperty.Name)) { 46 | $propertyName = foreach ($attr in $myProfileProperty.Attributes) { 47 | if ($attr -is [System.ComponentModel.DefaultBindingPropertyAttribute]) { 48 | $attr.Name 49 | break 50 | } 51 | } 52 | $paramValue = $myParameters[$myProfileProperty.Name] 53 | foreach ($attr in $myProfileProperty.Attributes) { 54 | if ($attr -is [ComponentModel.AmbientValueAttribute] -and $attr.Value -is [scriptblock]) { 55 | $_ = $this = $PSItem = $paramValue 56 | $paramValue = & $attr.Value 57 | break 58 | } 59 | if ($attr -is [ValidateSet]) { 60 | foreach ($validValue in $attr.Validvalues) { 61 | if ($paramValue -eq $validValue) { 62 | $paramValue = $validValue 63 | } 64 | } 65 | } 66 | } 67 | if ($paramValue -is [switch]) { 68 | $paramValue = $paramValue -as [bool] 69 | } 70 | $myProfileParameters[$propertyName] = $paramValue 71 | } 72 | } 73 | #region Create Profile Object 74 | 75 | $newProfile = [PSCustomObject]$myProfileParameters 76 | #endregion Profile Object 77 | 78 | 79 | #region Update Windows Terminal Profile 80 | $wtProfile = Get-WTProfile -Global # Get our profile 81 | $wtProfile.profiles | # Add out new profile to the list, 82 | Add-Member NoteProperty list @( 83 | foreach ($_ in $wtProfile.profiles.list) { 84 | if ($guid -ne $_.Guid -and $name -ne $_.Name) # and don't forget all of the other ones. 85 | { 86 | $_ 87 | } 88 | } 89 | $newProfile 90 | ) -Force 91 | $wtPath = $wtProfile.Path 92 | if ($PSCmdlet.ShouldProcess("Add Profile $Name to $wtPath")) # If we ShouldProcess 93 | { 94 | $wtProfile.psobject.properties.Remove('Path') 95 | $wtProfile | # turn the profile 96 | ConvertTo-Json -Depth 100 | # back into JSON 97 | Set-Content -Path $wtPath -Encoding UTF8 # and write it to disk. 98 | $wtProfile.psobject.properties.add([PSNoteProperty]::new('Path', $wtPath)) 99 | } 100 | elseif ($WhatIfPreference) # if we wanted to know -WhatIf 101 | { 102 | return $wtProfile # return the JSON object 103 | } 104 | #endregion Update Windows Terminal Profile 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /New-WTColorScheme.ps1: -------------------------------------------------------------------------------- 1 | function New-WTColorScheme 2 | { 3 | <# 4 | .Synopsis 5 | Creates Windows Terminal Color Schemes 6 | .Description 7 | Creates a new Windows Terminal Color Scheme 8 | .Link 9 | Add-WTColorScheme 10 | .Example 11 | New-WTColorScheme -Name MyColorScheme 12 | #> 13 | [OutputType([PSObject])] 14 | [Diagnostics.CodeAnalysis.SuppressMessageAttribute( 15 | "PSUseShouldProcessForStateChangingFunctions", "", Justification="Not changing state" 16 | )] 17 | param( 18 | # The name of the color scheme 19 | [Parameter(Mandatory,ValueFromPipelineByPropertyName)] 20 | [string] 21 | $Name, 22 | 23 | # The scheme's definition of the color Black. 24 | [Parameter(ValueFromPipelineByPropertyName)] 25 | [ValidatePattern('^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$')] 26 | [string] 27 | $Black = '#010101', 28 | 29 | # The scheme's definition of the color Red. 30 | [Parameter(ValueFromPipelineByPropertyName)] 31 | [ValidatePattern('^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$')] 32 | [string] 33 | $Red = '#dd0000', 34 | 35 | # The scheme's definition of the color Green. 36 | [Parameter(ValueFromPipelineByPropertyName)] 37 | [ValidatePattern('^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$')] 38 | [string] 39 | $Green = '#00dd00', 40 | 41 | # The scheme's definition of the color Yellow. 42 | [Parameter(ValueFromPipelineByPropertyName)] 43 | [ValidatePattern('^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$')] 44 | [string] 45 | $Yellow = '#dddd00', 46 | 47 | # The scheme's definition of the color Blue. 48 | [Parameter(ValueFromPipelineByPropertyName)] 49 | [ValidatePattern('^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$')] 50 | [string] 51 | $Blue = '#0000dd', 52 | 53 | # The scheme's definition of the color Cyan. 54 | [Parameter(ValueFromPipelineByPropertyName)] 55 | [ValidatePattern('^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$')] 56 | [string] 57 | $Cyan = '#00dddd', 58 | 59 | # The scheme's definition of the color Purple. 60 | [Parameter(ValueFromPipelineByPropertyName)] 61 | [ValidatePattern('^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$')] 62 | [Alias('Magenta')] 63 | [string] 64 | $Purple = '#dd00dd', 65 | 66 | # The scheme's definition of the color White. 67 | [Parameter(ValueFromPipelineByPropertyName)] 68 | [ValidatePattern('^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$')] 69 | [string] 70 | $White = '#efefef', 71 | 72 | # The scheme's definition of the color BrightRed. 73 | [Parameter(ValueFromPipelineByPropertyName)] 74 | [ValidatePattern('^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$')] 75 | [string] 76 | $BrightRed = '#ff0000', 77 | 78 | # The scheme's definition of the color BrightGreen. 79 | [Parameter(ValueFromPipelineByPropertyName)] 80 | [ValidatePattern('^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$')] 81 | [string] 82 | $BrightGreen = '#00ff00', 83 | 84 | # The scheme's definition of the color BrightYellow. 85 | [Parameter(ValueFromPipelineByPropertyName)] 86 | [ValidatePattern('^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$')] 87 | [string] 88 | $BrightYellow = '#ffff00', 89 | 90 | # The scheme's definition of the color BrightBlue. 91 | [Parameter(ValueFromPipelineByPropertyName)] 92 | [ValidatePattern('^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$')] 93 | [string] 94 | $BrightBlue = '#0000ff', 95 | 96 | # The scheme's definition of the color BrightPurple. 97 | [Parameter(ValueFromPipelineByPropertyName)] 98 | [ValidatePattern('^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$')] 99 | [string] 100 | $BrightPurple = '#ff00ff', 101 | 102 | # The scheme's definition of the color BrightCyan. 103 | [Parameter(ValueFromPipelineByPropertyName)] 104 | [ValidatePattern('^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$')] 105 | [string] 106 | $BrightCyan = '#00ffff', 107 | 108 | # The scheme's definition of the color BrightWhite. 109 | [Parameter(ValueFromPipelineByPropertyName)] 110 | [ValidatePattern('^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$')] 111 | [string] 112 | $BrightWhite = '#ffffff', 113 | 114 | # The scheme's definition of the color BrightBlack. 115 | [Parameter(ValueFromPipelineByPropertyName)] 116 | [ValidatePattern('^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$')] 117 | [string] 118 | $BrightBlack = '#0d0d0d', 119 | 120 | # The scheme's foreground color. 121 | [Parameter(ValueFromPipelineByPropertyName)] 122 | [ValidatePattern('^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$')] 123 | [string] 124 | $Foreground = '#fefefe', 125 | 126 | # The scheme's background color. 127 | [Parameter(ValueFromPipelineByPropertyName)] 128 | [ValidatePattern('^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$')] 129 | [string] 130 | $Background = '#012456' 131 | ) 132 | 133 | process { 134 | #region Create Color Scheme Object 135 | $myCmdMetaData = [Management.Automation.CommandMetaData]$MyInvocation.MyCommand 136 | $newColorScheme = [Ordered]@{} 137 | foreach ($p in $myCmdMetaData.Parameters.Keys) { 138 | $k = $p.Substring(0,1).ToLower() + $p.Substring(1) 139 | $newColorScheme[$k] = $ExecutionContext.SessionState.PSVariable.Get($p).Value 140 | } 141 | [PSCustomObject]$newColorScheme 142 | #endregion Create Color Scheme Object 143 | } 144 | } -------------------------------------------------------------------------------- /docs/Show-WT.md: -------------------------------------------------------------------------------- 1 | Show-WT 2 | ------- 3 | ### Synopsis 4 | Shows Images in the Windows Terminal 5 | 6 | --- 7 | ### Description 8 | 9 | Shows Images in the Windows Terminal. 10 | 11 | By default, .GIF files will play once, and non-GIFs will stay for 15 seconds. 12 | 13 | --- 14 | ### Related Links 15 | * [Get-WTProfile](Get-WTProfile.md) 16 | 17 | 18 | 19 | * [Set-WTProfile](Set-WTProfile.md) 20 | 21 | 22 | 23 | --- 24 | ### Examples 25 | #### EXAMPLE 1 26 | ```PowerShell 27 | Show-WT -ImagePath .\My.gif # Shows My.gif in the current Windows Terminal profile. 28 | ``` 29 | 30 | #### EXAMPLE 2 31 | ```PowerShell 32 | Show-WT -ImagePath .\My.gif -Wait -1 # Shows My.gif forever 33 | ``` 34 | 35 | --- 36 | ### Parameters 37 | #### **ImagePath** 38 | 39 | The path to an image file. 40 | 41 | 42 | 43 | > **Type**: ```[String]``` 44 | 45 | > **Required**: false 46 | 47 | > **Position**: 1 48 | 49 | > **PipelineInput**:true (ByPropertyName) 50 | 51 | 52 | 53 | --- 54 | #### **ProfileName** 55 | 56 | If set, will display content in a given profile. 57 | If not set, will attempt to auto-detect the profile. 58 | If the profile cannot be automatically detected, content will be displayed using the default profile settings. 59 | (this will not override an existing image) 60 | 61 | 62 | 63 | > **Type**: ```[String]``` 64 | 65 | > **Required**: false 66 | 67 | > **Position**: named 68 | 69 | > **PipelineInput**:false 70 | 71 | 72 | 73 | --- 74 | #### **Alignment** 75 | 76 | Sets the alignment of the Image to draw over the window background. 77 | 78 | 79 | 80 | Valid Values: 81 | 82 | * bottom 83 | * bottomLeft 84 | * bottomRight 85 | * center 86 | * left 87 | * right 88 | * top 89 | * topLeft 90 | * topRight 91 | 92 | 93 | 94 | > **Type**: ```[String]``` 95 | 96 | > **Required**: false 97 | 98 | > **Position**: named 99 | 100 | > **PipelineInput**:true (ByPropertyName) 101 | 102 | 103 | 104 | --- 105 | #### **Opacity** 106 | 107 | Sets the opacity of the Image to draw over the window background. 108 | 109 | 110 | 111 | > **Type**: ```[Single]``` 112 | 113 | > **Required**: false 114 | 115 | > **Position**: named 116 | 117 | > **PipelineInput**:true (ByPropertyName) 118 | 119 | 120 | 121 | --- 122 | #### **StretchMode** 123 | 124 | Sets how the background image is resized to fill the window. 125 | 126 | 127 | 128 | Valid Values: 129 | 130 | * fill 131 | * none 132 | * uniform 133 | * uniformToFill 134 | 135 | 136 | 137 | > **Type**: ```[String]``` 138 | 139 | > **Required**: false 140 | 141 | > **Position**: named 142 | 143 | > **PipelineInput**:true (ByPropertyName) 144 | 145 | 146 | 147 | --- 148 | #### **Wait** 149 | 150 | How long to wait before making the change. 151 | By default, the change will be as quick as possible. 152 | 153 | 154 | 155 | > **Type**: ```[TimeSpan]``` 156 | 157 | > **Required**: false 158 | 159 | > **Position**: named 160 | 161 | > **PipelineInput**:true (ByPropertyName) 162 | 163 | 164 | 165 | --- 166 | #### **Duration** 167 | 168 | Sets how long the image should be displayed. 169 | If the duration is negative, the image will not be automatically cleared. 170 | 171 | 172 | 173 | > **Type**: ```[TimeSpan]``` 174 | 175 | > **Required**: false 176 | 177 | > **Position**: named 178 | 179 | > **PipelineInput**:true (ByPropertyName) 180 | 181 | 182 | 183 | --- 184 | #### **LoopCount** 185 | 186 | Sets the number of times an animated .gif should be looped. 187 | 188 | 189 | 190 | > **Type**: ```[Int32]``` 191 | 192 | > **Required**: false 193 | 194 | > **Position**: named 195 | 196 | > **PipelineInput**:true (ByPropertyName) 197 | 198 | 199 | 200 | --- 201 | #### **AcrylicOpacity** 202 | 203 | When useAcrylic is set to true, it sets the transparency of the window for the profile. 204 | Accepts floating point values from 0-1 (default 0.5). 205 | 206 | 207 | 208 | > **Type**: ```[Single]``` 209 | 210 | > **Required**: false 211 | 212 | > **Position**: named 213 | 214 | > **PipelineInput**:true (ByPropertyName) 215 | 216 | 217 | 218 | --- 219 | #### **UseAcrylic** 220 | 221 | When set to true, the window will have an acrylic background. 222 | When set to false, the window will have a plain, untextured background. 223 | 224 | 225 | 226 | > **Type**: ```[Switch]``` 227 | 228 | > **Required**: false 229 | 230 | > **Position**: named 231 | 232 | > **PipelineInput**:true (ByPropertyName) 233 | 234 | 235 | 236 | --- 237 | #### **PixelShader** 238 | 239 | If provided, will use a pixel shader. 240 | 241 | 242 | 243 | > **Type**: ```[String]``` 244 | 245 | > **Required**: false 246 | 247 | > **Position**: named 248 | 249 | > **PipelineInput**:true (ByPropertyName) 250 | 251 | 252 | 253 | --- 254 | #### **AsJob** 255 | 256 | If set, will run in a background job. 257 | 258 | 259 | 260 | > **Type**: ```[Switch]``` 261 | 262 | > **Required**: false 263 | 264 | > **Position**: named 265 | 266 | > **PipelineInput**:false 267 | 268 | 269 | 270 | --- 271 | ### Outputs 272 | * [Management.Automation.Job](https://learn.microsoft.com/en-us/dotnet/api/System.Management.Automation.Job) 273 | 274 | 275 | * [Nullable](https://learn.microsoft.com/en-us/dotnet/api/System.Nullable) 276 | 277 | 278 | 279 | 280 | --- 281 | ### Syntax 282 | ```PowerShell 283 | Show-WT [[-ImagePath] ] [-ProfileName ] [-Alignment ] [-Opacity ] [-StretchMode ] [-Wait ] [-Duration ] [-LoopCount ] [-AcrylicOpacity ] [-UseAcrylic] [-PixelShader ] [-AsJob] [] 284 | ``` 285 | --- 286 | -------------------------------------------------------------------------------- /Remove-WTProfile.ps1: -------------------------------------------------------------------------------- 1 | function Remove-WTProfile 2 | { 3 | <# 4 | .Synopsis 5 | Removes a Windows Terminal Profile 6 | .Description 7 | Removes Windows Terminal Profiles, 8 | or removes one or more -Property from a Windows Terminal profile. 9 | .Example 10 | Add-WTProfile -Name 'DOS' -CommandLine cmd # Add a DOS profile 11 | 12 | Remove-WTProfile -Name DOS # and get rid of it. 13 | .Link 14 | Add-WTProfile 15 | #> 16 | [CmdletBinding(SupportsShouldProcess,ConfirmImpact='High',DefaultParameterSetName='SpecificProfile')] 17 | [OutputType([PSObject])] 18 | param( 19 | # The name of the profile. 20 | [Parameter(Mandatory,ParameterSetName='SpecificProfile',ValueFromPipelineByPropertyName)] 21 | [Alias('Name')] 22 | [string[]] 23 | $ProfileName, 24 | 25 | # If -Default is present with no other parameters, clears the default profile settings. 26 | # If -Property is also present, removes properties from the default profile settings. 27 | [Parameter(Mandatory,ParameterSetName='DefaultProfile',ValueFromPipelineByPropertyName)] 28 | [Alias('Defaults')] 29 | [switch] 30 | $Default, 31 | 32 | # The name of one or more properties to remove from a profile. 33 | [Parameter(ValueFromPipelineByPropertyName)] 34 | [Alias('Properties','PropertyName','PropertyNames')] 35 | [string[]] 36 | $Property 37 | ) 38 | 39 | process { 40 | $wtProfile = Get-WTProfile -Global 41 | $targetProfiles = 42 | @(if ($Default) { 43 | $wtProfile.profiles.defaults 44 | } else { 45 | Get-WTProfile -ProfileName $ProfileName 46 | 47 | }) 48 | if (-not $targetProfiles) { return } 49 | 50 | #region Removing Profiles 51 | if (-not $Property) # If no property was provided, we're removing whole profiles 52 | { 53 | if (-not $wtProfile.profiles) { 54 | $wtProfile | 55 | Add-Member NoteProperty profiles ([PSCustomObject]@{list=@();defaults=[PSObject]::new()}) -Force 56 | } 57 | if ($Default) { # If we're "removing" the default profile, clear it 58 | $wtProfile.profiles | Add-Member NoteProperty defaults ([PSObject]::new()) -Force 59 | } else { 60 | $targetProfilesGuids = # Find all of the target GUIDs 61 | $targetProfiles | 62 | Select-Object -ExpandProperty GUID 63 | 64 | if ($null -eq $wtProfile.profiles.list) { 65 | $wtProfile.profiles | 66 | Add-Member NoteProperty list @() -Force 67 | } 68 | 69 | $wtProfile.profiles.list = # reassign the profiles property to be 70 | @( # a list 71 | foreach ($prof in $wtProfile.profiles.list) { # containing profiles that were not 72 | if ($targetProfilesGuids -notcontains # one of the target guids. 73 | $prof.GUID) { 74 | $prof 75 | } 76 | } 77 | ) 78 | } 79 | } 80 | #endregion Removing Profiles 81 | #region Removing Properties 82 | else 83 | { 84 | # To remove properties within target profiles 85 | foreach ($prof in $targetProfiles) # we need to walk each target profile. 86 | { 87 | # Then walk over each property. 88 | :NextProfileProperty # We'll label this loop :NextProfileProperty for performancce. 89 | foreach ($prop in @($prof.psobject.properties)) 90 | { 91 | # Then we have to walk over each -Property, since they could be wildcards. 92 | foreach ($p in $Property) { 93 | if ($prop.Name -like $p) { # When the wildcard matches 94 | $prof | Add-Member NoteProperty $prop.Name '' -Force 95 | # make it blank so that 96 | # Set-WTProfile will remove the property. 97 | continue NextProfileProperty # then continue to the next profile property. 98 | } 99 | } 100 | } 101 | 102 | if ($prof.guid) { 103 | $prof | Set-WTProfile 104 | } else { 105 | $prof | Set-WTProfile -Default 106 | } 107 | } 108 | return 109 | } 110 | #endregion Removing Properties 111 | 112 | #region Updating Settings 113 | # Now that we've changed our object, let's update the settings 114 | if ($PSCmdlet.ShouldProcess("Update $($wtProfile.Path)")) { 115 | 116 | $wtPath = $wtProfile.Path 117 | $wtProfile.psobject.properties.Remove('Path') 118 | $wtProfile | 119 | ConvertTo-Json -Depth 100 | 120 | Set-Content -LiteralPath $wtPath -Force -Encoding UTF8 121 | $wtProfile.psobject.properties.add([PSNoteProperty]::new('Path', $wtPath)) 122 | } 123 | #endregion Updating Settings 124 | 125 | if ($WhatIfPreference -or $PassThru) { 126 | if ($Property) { 127 | foreach ($prof in $targetProfiles) { 128 | $prof 129 | } 130 | } else { 131 | $wtProfile 132 | } 133 | } 134 | } 135 | } -------------------------------------------------------------------------------- /Start-WT.ps1: -------------------------------------------------------------------------------- 1 | function Start-WT 2 | { 3 | <# 4 | .Synopsis 5 | Starts a new instance of Windows Terminal 6 | .Description 7 | Starts a new instance of Windows Terminal, and sends commands to it. 8 | .Link 9 | Get-WTProfile 10 | .Example 11 | Start-WT 12 | .Example 13 | Start-WT -Profile PowerShell 14 | .Example 15 | Start-WT -Profile 'Windows PowerShell' -CommandLine 'powershell -nologo' 16 | #> 17 | [OutputType([Nullable],[Diagnostics.Process])] 18 | [Diagnostics.CodeAnalysis.SuppressMessageAttribute( 19 | "PSUseShouldProcessForStateChangingFunctions", "", Justification="Not changing state" 20 | )] 21 | param( 22 | # The name of the Windows Terminal Tab profile 23 | [Parameter(ValueFromPipelineByPropertyName)] 24 | [Alias('Profile')] 25 | [string] 26 | $ProfileName, 27 | 28 | # The working directory used by Windows Terminal 29 | [Parameter(ValueFromPipelineByPropertyName)] 30 | [string] 31 | $WorkingDirectory, 32 | 33 | # The command line run by Windows Terminal 34 | [Parameter(ValueFromPipelineByPropertyName)] 35 | [string] 36 | $CommandLine, 37 | 38 | # If set, will split the pane. 39 | [Parameter(ValueFromPipelineByPropertyName)] 40 | [switch] 41 | $Split, 42 | 43 | # If provided, will split the pane horizontally or veritcally 44 | [Parameter(ValueFromPipelineByPropertyName)] 45 | [ValidateSet('Horizontal','H', 'Vertical','V')] 46 | [string] 47 | $SplitDirection, 48 | 49 | # If provided, will focus a given tab index. 50 | [Parameter(ValueFromPipelineByPropertyName)] 51 | [int] 52 | $FocusTabIndex, 53 | 54 | # If provided, will focus the next tab. 55 | [Parameter(ValueFromPipelineByPropertyName)] 56 | [Alias('Next')] 57 | [switch] 58 | $FocusNextTab, 59 | 60 | # If provided, will focus the previous tab. 61 | [Parameter(ValueFromPipelineByPropertyName)] 62 | [Alias('Previous')] 63 | [switch] 64 | $FocusPreviousTab, 65 | 66 | # If set, will return the created process. 67 | [switch] 68 | $Passthru, 69 | 70 | # If set, will start the process elevated 71 | [Alias('RunAsAdministrator')] 72 | [switch] 73 | $Elevated 74 | ) 75 | 76 | dynamicParam { 77 | 78 | } 79 | 80 | begin { 81 | $allArgs = [Collections.Generic.List[Object]]::new() 82 | } 83 | process { 84 | $allArgs.AddRange( 85 | @( 86 | #region New Tabs and Panes 87 | if ($CommandLine -or $ProfileName -or $WorkingDirectory) { 88 | if ($Split -or $SplitDirection) { 89 | $(if ($allArgs.Count) {';'} else {''}) + $( 90 | if ($allArgs.Count) { 91 | if ($Split) { 92 | 'split-pane' 93 | } elseif ('Horizontal','H' -contains $SplitDirection) { 94 | 'split-pane -H' 95 | } elseif ('Vertical','V' -contains $SplitDirection) { 96 | 'split-pane -V' 97 | } 98 | } else { 99 | 'new-tab' 100 | } 101 | ) 102 | } else { 103 | $(if ($allArgs.Count) {';'} else {''}) + 'new-tab' 104 | } 105 | if ($ProfileName) { 106 | '--profile' 107 | "`"$ProfileName`"" 108 | } 109 | if ($WorkingDirectory) { 110 | '--startingDirectory' 111 | $WorkingDirectory 112 | } 113 | if ($CommandLine) { 114 | $CommandLine -replace ';' ,'\;' 115 | } 116 | } 117 | #endregion New Tabs and Panes 118 | #region Tab Focus 119 | elseif ($FocusNextTab -or $FocusPreviousTab -or $FocusTabIndex -ge 0) 120 | { 121 | ';focus-tab' 122 | if ($FocusTabIndex -ge 0) { 123 | '--target' 124 | $FocusTabIndex 125 | } elseif ($FocusNextTab) { 126 | '--next' 127 | } elseif ($FocusPreviousTab) { 128 | '--previous' 129 | } 130 | }) 131 | #endregion Tab Focus 132 | ) 133 | } 134 | 135 | end { 136 | Write-Verbose "$allArgs" 137 | 138 | 139 | if ($Elevated) # If we're going to run elevated, 140 | { 141 | # we actually need to start wt.exe from a process that is already elevated 142 | # so we'll launch PowerShell, and pass the -command 143 | $EmbeddedArguments = "@($( 144 | foreach ($arg in $allArgs) { 145 | $strArg = "$arg" 146 | if ($strArg.Contains([Environment]::NewLine)) { 147 | "@' 148 | $($strArg + [Environment]::Newline)'@" + [Environment]::NewLine 149 | } else { 150 | "'$strArg';" 151 | } 152 | } 153 | ))" 154 | $myPowerShell = Get-Process -Id $pid | Select-Object -ExpandProperty Path 155 | if ($myPowerShell -like '*_ise*') { 156 | $myPowerShell = Get-Command powershell | Select-Object -ExpandProperty Path 157 | } 158 | Start-Process -FilePath $myPowerShell -ArgumentList '-command', "Start-Process wt.exe -ArgumentList $EmbeddedArguments" -Verb Runas 159 | } else { 160 | Start-Process wt.exe -ArgumentList $allArgs -PassThru:$PassThru 161 | } 162 | 163 | } 164 | } -------------------------------------------------------------------------------- /docs/New-WTColorScheme.md: -------------------------------------------------------------------------------- 1 | New-WTColorScheme 2 | ----------------- 3 | ### Synopsis 4 | Creates Windows Terminal Color Schemes 5 | 6 | --- 7 | ### Description 8 | 9 | Creates a new Windows Terminal Color Scheme 10 | 11 | --- 12 | ### Related Links 13 | * [Add-WTColorScheme](Add-WTColorScheme.md) 14 | 15 | 16 | 17 | --- 18 | ### Examples 19 | #### EXAMPLE 1 20 | ```PowerShell 21 | New-WTColorScheme -Name MyColorScheme 22 | ``` 23 | 24 | --- 25 | ### Parameters 26 | #### **Name** 27 | 28 | The name of the color scheme 29 | 30 | 31 | 32 | > **Type**: ```[String]``` 33 | 34 | > **Required**: true 35 | 36 | > **Position**: 1 37 | 38 | > **PipelineInput**:true (ByPropertyName) 39 | 40 | 41 | 42 | --- 43 | #### **Black** 44 | 45 | The scheme's definition of the color Black. 46 | 47 | 48 | 49 | > **Type**: ```[String]``` 50 | 51 | > **Required**: false 52 | 53 | > **Position**: 2 54 | 55 | > **PipelineInput**:true (ByPropertyName) 56 | 57 | 58 | 59 | --- 60 | #### **Red** 61 | 62 | The scheme's definition of the color Red. 63 | 64 | 65 | 66 | > **Type**: ```[String]``` 67 | 68 | > **Required**: false 69 | 70 | > **Position**: 3 71 | 72 | > **PipelineInput**:true (ByPropertyName) 73 | 74 | 75 | 76 | --- 77 | #### **Green** 78 | 79 | The scheme's definition of the color Green. 80 | 81 | 82 | 83 | > **Type**: ```[String]``` 84 | 85 | > **Required**: false 86 | 87 | > **Position**: 4 88 | 89 | > **PipelineInput**:true (ByPropertyName) 90 | 91 | 92 | 93 | --- 94 | #### **Yellow** 95 | 96 | The scheme's definition of the color Yellow. 97 | 98 | 99 | 100 | > **Type**: ```[String]``` 101 | 102 | > **Required**: false 103 | 104 | > **Position**: 5 105 | 106 | > **PipelineInput**:true (ByPropertyName) 107 | 108 | 109 | 110 | --- 111 | #### **Blue** 112 | 113 | The scheme's definition of the color Blue. 114 | 115 | 116 | 117 | > **Type**: ```[String]``` 118 | 119 | > **Required**: false 120 | 121 | > **Position**: 6 122 | 123 | > **PipelineInput**:true (ByPropertyName) 124 | 125 | 126 | 127 | --- 128 | #### **Cyan** 129 | 130 | The scheme's definition of the color Cyan. 131 | 132 | 133 | 134 | > **Type**: ```[String]``` 135 | 136 | > **Required**: false 137 | 138 | > **Position**: 7 139 | 140 | > **PipelineInput**:true (ByPropertyName) 141 | 142 | 143 | 144 | --- 145 | #### **Purple** 146 | 147 | The scheme's definition of the color Purple. 148 | 149 | 150 | 151 | > **Type**: ```[String]``` 152 | 153 | > **Required**: false 154 | 155 | > **Position**: 8 156 | 157 | > **PipelineInput**:true (ByPropertyName) 158 | 159 | 160 | 161 | --- 162 | #### **White** 163 | 164 | The scheme's definition of the color White. 165 | 166 | 167 | 168 | > **Type**: ```[String]``` 169 | 170 | > **Required**: false 171 | 172 | > **Position**: 9 173 | 174 | > **PipelineInput**:true (ByPropertyName) 175 | 176 | 177 | 178 | --- 179 | #### **BrightRed** 180 | 181 | The scheme's definition of the color BrightRed. 182 | 183 | 184 | 185 | > **Type**: ```[String]``` 186 | 187 | > **Required**: false 188 | 189 | > **Position**: 10 190 | 191 | > **PipelineInput**:true (ByPropertyName) 192 | 193 | 194 | 195 | --- 196 | #### **BrightGreen** 197 | 198 | The scheme's definition of the color BrightGreen. 199 | 200 | 201 | 202 | > **Type**: ```[String]``` 203 | 204 | > **Required**: false 205 | 206 | > **Position**: 11 207 | 208 | > **PipelineInput**:true (ByPropertyName) 209 | 210 | 211 | 212 | --- 213 | #### **BrightYellow** 214 | 215 | The scheme's definition of the color BrightYellow. 216 | 217 | 218 | 219 | > **Type**: ```[String]``` 220 | 221 | > **Required**: false 222 | 223 | > **Position**: 12 224 | 225 | > **PipelineInput**:true (ByPropertyName) 226 | 227 | 228 | 229 | --- 230 | #### **BrightBlue** 231 | 232 | The scheme's definition of the color BrightBlue. 233 | 234 | 235 | 236 | > **Type**: ```[String]``` 237 | 238 | > **Required**: false 239 | 240 | > **Position**: 13 241 | 242 | > **PipelineInput**:true (ByPropertyName) 243 | 244 | 245 | 246 | --- 247 | #### **BrightPurple** 248 | 249 | The scheme's definition of the color BrightPurple. 250 | 251 | 252 | 253 | > **Type**: ```[String]``` 254 | 255 | > **Required**: false 256 | 257 | > **Position**: 14 258 | 259 | > **PipelineInput**:true (ByPropertyName) 260 | 261 | 262 | 263 | --- 264 | #### **BrightCyan** 265 | 266 | The scheme's definition of the color BrightCyan. 267 | 268 | 269 | 270 | > **Type**: ```[String]``` 271 | 272 | > **Required**: false 273 | 274 | > **Position**: 15 275 | 276 | > **PipelineInput**:true (ByPropertyName) 277 | 278 | 279 | 280 | --- 281 | #### **BrightWhite** 282 | 283 | The scheme's definition of the color BrightWhite. 284 | 285 | 286 | 287 | > **Type**: ```[String]``` 288 | 289 | > **Required**: false 290 | 291 | > **Position**: 16 292 | 293 | > **PipelineInput**:true (ByPropertyName) 294 | 295 | 296 | 297 | --- 298 | #### **BrightBlack** 299 | 300 | The scheme's definition of the color BrightBlack. 301 | 302 | 303 | 304 | > **Type**: ```[String]``` 305 | 306 | > **Required**: false 307 | 308 | > **Position**: 17 309 | 310 | > **PipelineInput**:true (ByPropertyName) 311 | 312 | 313 | 314 | --- 315 | #### **Foreground** 316 | 317 | The scheme's foreground color. 318 | 319 | 320 | 321 | > **Type**: ```[String]``` 322 | 323 | > **Required**: false 324 | 325 | > **Position**: 18 326 | 327 | > **PipelineInput**:true (ByPropertyName) 328 | 329 | 330 | 331 | --- 332 | #### **Background** 333 | 334 | The scheme's background color. 335 | 336 | 337 | 338 | > **Type**: ```[String]``` 339 | 340 | > **Required**: false 341 | 342 | > **Position**: 19 343 | 344 | > **PipelineInput**:true (ByPropertyName) 345 | 346 | 347 | 348 | --- 349 | ### Outputs 350 | * [Management.Automation.PSObject](https://learn.microsoft.com/en-us/dotnet/api/System.Management.Automation.PSObject) 351 | 352 | 353 | 354 | 355 | --- 356 | ### Syntax 357 | ```PowerShell 358 | New-WTColorScheme [-Name] [[-Black] ] [[-Red] ] [[-Green] ] [[-Yellow] ] [[-Blue] ] [[-Cyan] ] [[-Purple] ] [[-White] ] [[-BrightRed] ] [[-BrightGreen] ] [[-BrightYellow] ] [[-BrightBlue] ] [[-BrightPurple] ] [[-BrightCyan] ] [[-BrightWhite] ] [[-BrightBlack] ] [[-Foreground] ] [[-Background] ] [] 359 | ``` 360 | --- 361 | -------------------------------------------------------------------------------- /docs/Add-WTColorScheme.md: -------------------------------------------------------------------------------- 1 | Add-WTColorScheme 2 | ----------------- 3 | ### Synopsis 4 | Adds a Windows Terminal Color Scheme 5 | 6 | --- 7 | ### Description 8 | 9 | Adds a Windows Terminal Color Scheme, including any scheme from https://iterm2colorschemes.com/ 10 | 11 | --- 12 | ### Related Links 13 | * [https://iterm2colorschemes.com/](https://iterm2colorschemes.com/) 14 | 15 | 16 | 17 | --- 18 | ### Examples 19 | #### EXAMPLE 1 20 | ```PowerShell 21 | Add-WTColorScheme -Name AdventureTime 22 | ``` 23 | 24 | --- 25 | ### Parameters 26 | #### **Name** 27 | 28 | The name of the color scheme. 29 | If the name exists on https://iterm2colorschemes.com/, then no other parameters are needed. 30 | 31 | 32 | 33 | > **Type**: ```[String]``` 34 | 35 | > **Required**: true 36 | 37 | > **Position**: 1 38 | 39 | > **PipelineInput**:true (ByPropertyName) 40 | 41 | 42 | 43 | --- 44 | #### **Black** 45 | 46 | The scheme's definition of the color Black. 47 | 48 | 49 | 50 | > **Type**: ```[String]``` 51 | 52 | > **Required**: false 53 | 54 | > **Position**: 2 55 | 56 | > **PipelineInput**:true (ByPropertyName) 57 | 58 | 59 | 60 | --- 61 | #### **Red** 62 | 63 | The scheme's definition of the color Red. 64 | 65 | 66 | 67 | > **Type**: ```[String]``` 68 | 69 | > **Required**: false 70 | 71 | > **Position**: 3 72 | 73 | > **PipelineInput**:true (ByPropertyName) 74 | 75 | 76 | 77 | --- 78 | #### **Green** 79 | 80 | The scheme's definition of the color Green. 81 | 82 | 83 | 84 | > **Type**: ```[String]``` 85 | 86 | > **Required**: false 87 | 88 | > **Position**: 4 89 | 90 | > **PipelineInput**:true (ByPropertyName) 91 | 92 | 93 | 94 | --- 95 | #### **Yellow** 96 | 97 | The scheme's definition of the color Yellow. 98 | 99 | 100 | 101 | > **Type**: ```[String]``` 102 | 103 | > **Required**: false 104 | 105 | > **Position**: 5 106 | 107 | > **PipelineInput**:true (ByPropertyName) 108 | 109 | 110 | 111 | --- 112 | #### **Blue** 113 | 114 | The scheme's definition of the color Blue. 115 | 116 | 117 | 118 | > **Type**: ```[String]``` 119 | 120 | > **Required**: false 121 | 122 | > **Position**: 6 123 | 124 | > **PipelineInput**:true (ByPropertyName) 125 | 126 | 127 | 128 | --- 129 | #### **Cyan** 130 | 131 | The scheme's definition of the color Cyan. 132 | 133 | 134 | 135 | > **Type**: ```[String]``` 136 | 137 | > **Required**: false 138 | 139 | > **Position**: 7 140 | 141 | > **PipelineInput**:true (ByPropertyName) 142 | 143 | 144 | 145 | --- 146 | #### **Purple** 147 | 148 | The scheme's definition of the color Purple. 149 | 150 | 151 | 152 | > **Type**: ```[String]``` 153 | 154 | > **Required**: false 155 | 156 | > **Position**: 8 157 | 158 | > **PipelineInput**:true (ByPropertyName) 159 | 160 | 161 | 162 | --- 163 | #### **White** 164 | 165 | The scheme's definition of the color White. 166 | 167 | 168 | 169 | > **Type**: ```[String]``` 170 | 171 | > **Required**: false 172 | 173 | > **Position**: 9 174 | 175 | > **PipelineInput**:true (ByPropertyName) 176 | 177 | 178 | 179 | --- 180 | #### **BrightRed** 181 | 182 | The scheme's definition of the color BrightRed. 183 | 184 | 185 | 186 | > **Type**: ```[String]``` 187 | 188 | > **Required**: false 189 | 190 | > **Position**: 10 191 | 192 | > **PipelineInput**:true (ByPropertyName) 193 | 194 | 195 | 196 | --- 197 | #### **BrightGreen** 198 | 199 | The scheme's definition of the color BrightGreen. 200 | 201 | 202 | 203 | > **Type**: ```[String]``` 204 | 205 | > **Required**: false 206 | 207 | > **Position**: 11 208 | 209 | > **PipelineInput**:true (ByPropertyName) 210 | 211 | 212 | 213 | --- 214 | #### **BrightYellow** 215 | 216 | The scheme's definition of the color BrightYellow. 217 | 218 | 219 | 220 | > **Type**: ```[String]``` 221 | 222 | > **Required**: false 223 | 224 | > **Position**: 12 225 | 226 | > **PipelineInput**:true (ByPropertyName) 227 | 228 | 229 | 230 | --- 231 | #### **BrightBlue** 232 | 233 | The scheme's definition of the color BrightBlue. 234 | 235 | 236 | 237 | > **Type**: ```[String]``` 238 | 239 | > **Required**: false 240 | 241 | > **Position**: 13 242 | 243 | > **PipelineInput**:true (ByPropertyName) 244 | 245 | 246 | 247 | --- 248 | #### **BrightPurple** 249 | 250 | The scheme's definition of the color BrightPurple. 251 | 252 | 253 | 254 | > **Type**: ```[String]``` 255 | 256 | > **Required**: false 257 | 258 | > **Position**: 14 259 | 260 | > **PipelineInput**:true (ByPropertyName) 261 | 262 | 263 | 264 | --- 265 | #### **BrightCyan** 266 | 267 | The scheme's definition of the color BrightCyan. 268 | 269 | 270 | 271 | > **Type**: ```[String]``` 272 | 273 | > **Required**: false 274 | 275 | > **Position**: 15 276 | 277 | > **PipelineInput**:true (ByPropertyName) 278 | 279 | 280 | 281 | --- 282 | #### **BrightWhite** 283 | 284 | The scheme's definition of the color BrightWhite. 285 | 286 | 287 | 288 | > **Type**: ```[String]``` 289 | 290 | > **Required**: false 291 | 292 | > **Position**: 16 293 | 294 | > **PipelineInput**:true (ByPropertyName) 295 | 296 | 297 | 298 | --- 299 | #### **BrightBlack** 300 | 301 | The scheme's definition of the color BrightBlack. 302 | 303 | 304 | 305 | > **Type**: ```[String]``` 306 | 307 | > **Required**: false 308 | 309 | > **Position**: 17 310 | 311 | > **PipelineInput**:true (ByPropertyName) 312 | 313 | 314 | 315 | --- 316 | #### **Foreground** 317 | 318 | The scheme's foreground color. 319 | 320 | 321 | 322 | > **Type**: ```[String]``` 323 | 324 | > **Required**: false 325 | 326 | > **Position**: 18 327 | 328 | > **PipelineInput**:true (ByPropertyName) 329 | 330 | 331 | 332 | --- 333 | #### **Background** 334 | 335 | The scheme's background color. 336 | 337 | 338 | 339 | > **Type**: ```[String]``` 340 | 341 | > **Required**: false 342 | 343 | > **Position**: 19 344 | 345 | > **PipelineInput**:true (ByPropertyName) 346 | 347 | 348 | 349 | --- 350 | #### **WhatIf** 351 | -WhatIf is an automatic variable that is created when a command has ```[CmdletBinding(SupportsShouldProcess)]```. 352 | -WhatIf is used to see what would happen, or return operations without executing them 353 | #### **Confirm** 354 | -Confirm is an automatic variable that is created when a command has ```[CmdletBinding(SupportsShouldProcess)]```. 355 | -Confirm is used to -Confirm each operation. 356 | 357 | If you pass ```-Confirm:$false``` you will not be prompted. 358 | 359 | 360 | If the command sets a ```[ConfirmImpact("Medium")]``` which is lower than ```$confirmImpactPreference```, you will not be prompted unless -Confirm is passed. 361 | 362 | --- 363 | ### Outputs 364 | * [Nullable](https://learn.microsoft.com/en-us/dotnet/api/System.Nullable) 365 | 366 | 367 | 368 | 369 | --- 370 | ### Syntax 371 | ```PowerShell 372 | Add-WTColorScheme [-Name] [[-Black] ] [[-Red] ] [[-Green] ] [[-Yellow] ] [[-Blue] ] [[-Cyan] ] [[-Purple] ] [[-White] ] [[-BrightRed] ] [[-BrightGreen] ] [[-BrightYellow] ] [[-BrightBlue] ] [[-BrightPurple] ] [[-BrightCyan] ] [[-BrightWhite] ] [[-BrightBlack] ] [[-Foreground] ] [[-Background] ] [-WhatIf] [-Confirm] [] 373 | ``` 374 | --- 375 | -------------------------------------------------------------------------------- /TerminalVelocity.tests.ps1: -------------------------------------------------------------------------------- 1 | #requires -Module Pester, TerminalVelocity 2 | describe TerminalVelocity { 3 | beforeAll { 4 | $terminalVelocityModule = Get-Module TerminalVelocity 5 | 6 | $windowsTerminalTestProfile = @{ 7 | '$schema'='https://aka.ms/terminal-profiles-schema' 8 | confirmCloseAllTabs=$false 9 | defaultProfile='{61c54bbd-c2c6-5271-96e7-009a87ff44bf}' 10 | keybindings=@() 11 | launchMode='default' 12 | profiles=@{ 13 | defaults=@{ 14 | } 15 | list= @{ 16 | colorScheme='Blue Matrix' 17 | commandline='powershell.exe' 18 | guid='{61c54bbd-c2c6-5271-96e7-009a87ff44bf}' 19 | hidden=$false 20 | name='Windows PowerShell' 21 | padding='0,0,0,0' 22 | }, @{ 23 | backgroundImageStrechMode='uniformToFill' 24 | colorScheme='AdventureTime' 25 | guid='{574e775e-4f2a-5b96-ac1e-a2962a402336}' 26 | hidden=$false 27 | name='PowerShell' 28 | source='Windows.Terminal.PowershellCore' 29 | useAcrylic=$false 30 | }, 31 | @{ 32 | guid='{2c4de342-38b7-51cf-b940-2309a097f518}' 33 | hidden=$false 34 | name='Ubuntu' 35 | source='Windows.Terminal.Wsl' 36 | }, 37 | @{ 38 | backgroundImageStrechMode='uniformToFill' 39 | colorScheme='Jackie Brown' 40 | guid='{46ca431a-3a87-5fb3-83cd-11ececc031d2}' 41 | hidden=$false 42 | name='kali-linux' 43 | source='Windows.Terminal.Wsl' 44 | useAcrylic=$false 45 | }, 46 | @{ 47 | commandline='wsl -d kali-linux -e pwsh' 48 | guid='{831f30f1-ce36-4f9f-9889-35b626581bcc}' 49 | hidden=$false 50 | name='kali-linux-powershell' 51 | source='Windows.Terminal.Wsl' 52 | } 53 | } 54 | schemes=@{ 55 | name='AdventureTime' 56 | background='#1f1d45' 57 | black='#050404' 58 | blue='#0f4ac6' 59 | brightBlack='#4e7cbf' 60 | brightBlue='#1997c6' 61 | brightCyan='#c8faf4' 62 | brightGreen='#9eff6e' 63 | brightPurple='#9b5953' 64 | brightRed='#fc5f5a' 65 | brightWhite='#f6f5fb' 66 | brightYellow='#efc11a' 67 | cyan='#70a598' 68 | foreground='#f8dcc0' 69 | green='#4ab118' 70 | 71 | purple='#665993' 72 | red='#bd0013' 73 | white='#f8dcc0' 74 | yellow='#e7741e' 75 | },@{ 76 | name='Batman' 77 | background='#1b1d1e' 78 | black='#1b1d1e' 79 | blue='#737174' 80 | brightBlack='#505354' 81 | brightBlue='#919495' 82 | brightCyan='#a3a3a6' 83 | brightGreen='#fff27d' 84 | brightPurple='#9a9a9d' 85 | brightRed='#fff78e' 86 | brightWhite='#dadbd6' 87 | brightYellow='#feed6c' 88 | cyan='#62605f' 89 | foreground='#6f6f6f' 90 | green='#c8be46' 91 | purple='#747271' 92 | red='#e6dc44' 93 | white='#c6c5bf' 94 | yellow='#f4fd22' 95 | },@{ 96 | name='Grape' 97 | background='#171423' 98 | black='#2d283f' 99 | blue='#487df4' 100 | brightBlack='#59516a' 101 | brightBlue='#a9bcec' 102 | brightCyan='#9de3eb' 103 | brightGreen='#53aa5e' 104 | brightPurple='#ad81c2' 105 | brightRed='#f0729a' 106 | brightWhite='#a288f7' 107 | brightYellow='#b2dc87' 108 | cyan='#3bdeed' 109 | foreground='#9f9fa1' 110 | green='#1fa91b' 111 | 112 | purple='#8d35c9' 113 | red='#ed2261' 114 | white='#9e9ea0' 115 | yellow='#8ddc20' 116 | }, @{ 117 | background='#2c1d16' 118 | black='#2c1d16' 119 | blue='#246eb2' 120 | brightBlack='#666666' 121 | brightBlue='#0000ff' 122 | brightCyan='#00e5e5' 123 | brightGreen='#86a93e' 124 | brightPurple='#e500e5' 125 | brightRed='#e50000' 126 | brightWhite='#e5e5e5' 127 | brightYellow='#e5e500' 128 | cyan='#00acee' 129 | foreground='#ffcc2f' 130 | green='#2baf2b' 131 | name='Jackie Brown' 132 | purple='#d05ec1' 133 | red='#ef5734' 134 | white='#bfbfbf' 135 | yellow='#bebf00' 136 | } 137 | tabWidthMode='titleLength' 138 | } 139 | 140 | $wtSettingsPath = if ($PSVersionTable.OS -and $PSVersionTable.OS -notlike '*Windows*') { 141 | Join-Path '/tmp' 'wtSettingsTest.json' 142 | } else { 143 | Join-Path $env:Temp 'wtSettingsTest.json' 144 | } 145 | 146 | 147 | $windowsTerminalTestProfile | ConvertTo-Json -Depth 100 | Set-Content $wtSettingsPath -Encoding UTF8 148 | . $terminalVelocityModule { 149 | $script:WTProfilePath = Get-Item "$args" 150 | } $wtSettingsPath 151 | 152 | 153 | } 154 | 155 | it 'Can Get Global Settings' { 156 | Get-WTProfile -Global | Select-Object -ExpandProperty Path | should -BeLike '*wtSettingsTest.json' 157 | } 158 | 159 | 160 | 161 | context Profiles { 162 | 163 | 164 | it 'Can List Profiles' { 165 | Get-WTProfile | 166 | Select-Object -ExpandProperty Name | 167 | should -Match '^(?>powershell|windows powershell|ubuntu|kali-linux-powershell|kali-linux)$' 168 | } 169 | 170 | it 'Can add a profile' { 171 | Add-WTProfile -Name DOS -Commandline cmd 172 | 173 | Get-WTProfile | 174 | Select-Object -ExpandProperty Name | 175 | should -Match '^(?>dos|powershell|windows powershell|ubuntu|kali-linux-powershell|kali-linux)$' 176 | } 177 | 178 | it 'Can backup a profile' { 179 | Backup-WTProfile 180 | } 181 | 182 | it 'Can remove a profile' { 183 | Remove-WTProfile -ProfileName DOS -Confirm:$false 184 | 185 | Get-WTProfile | 186 | Select-Object -ExpandProperty Name | 187 | should -Match '^(?>powershell|windows powershell|ubuntu|kali-linux-powershell|kali-linux)$' 188 | } 189 | } 190 | 191 | context ColorSchemes { 192 | it 'Can get color schemes' { 193 | Get-WTColorScheme | 194 | Select-Object -ExpandProperty Name | 195 | should -Match '^(?>Jackie Brown|Grape|Batman|AdventureTime)$' 196 | } 197 | it 'Can set color schemes' { 198 | Set-WTColorScheme -ProfileName PowerShell -ColorScheme Batman 199 | Get-WTProfile -ProfileName PowerShell | 200 | Select-Object -ExpandProperty ColorScheme | 201 | should -Be Batman 202 | } 203 | it 'Can remove color schemes' { 204 | Remove-WTColorScheme -ColorScheme Grape -Confirm:$false 205 | Get-WTColorScheme | 206 | Select-Object -ExpandProperty Name | 207 | should -Match '^(?>Jackie Brown|Batman|AdventureTime)$' 208 | } 209 | } 210 | 211 | afterAll { 212 | Remove-Item $wtSettingsPath 213 | 214 | . $terminalVelocityModule { 215 | $script:WTProfilePath = $null 216 | } 217 | 218 | } 219 | } 220 | -------------------------------------------------------------------------------- /Add-WTColorScheme.ps1: -------------------------------------------------------------------------------- 1 | function Add-WTColorScheme 2 | { 3 | <# 4 | .Synopsis 5 | Adds a Windows Terminal Color Scheme 6 | .Description 7 | Adds a Windows Terminal Color Scheme, including any scheme from https://iterm2colorschemes.com/ 8 | .Example 9 | Add-WTColorScheme -Name AdventureTime 10 | .Link 11 | https://iterm2colorschemes.com/ 12 | #> 13 | [OutputType([Nullable])] 14 | [CmdletBinding(SupportsShouldProcess,ConfirmImpact='Medium')] 15 | param( 16 | # The name of the color scheme. 17 | # If the name exists on https://iterm2colorschemes.com/, then no other parameters are needed. 18 | [Parameter(Mandatory,ValueFromPipelineByPropertyName)] 19 | [string] 20 | $Name, 21 | 22 | # The scheme's definition of the color Black. 23 | [Parameter(ValueFromPipelineByPropertyName)] 24 | [ValidatePattern('^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$')] 25 | [string] 26 | $Black = '#010101', 27 | 28 | # The scheme's definition of the color Red. 29 | [Parameter(ValueFromPipelineByPropertyName)] 30 | [ValidatePattern('^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$')] 31 | [string] 32 | $Red = '#dd0000', 33 | 34 | # The scheme's definition of the color Green. 35 | [Parameter(ValueFromPipelineByPropertyName)] 36 | [ValidatePattern('^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$')] 37 | [string] 38 | $Green = '#00dd00', 39 | 40 | # The scheme's definition of the color Yellow. 41 | [Parameter(ValueFromPipelineByPropertyName)] 42 | [ValidatePattern('^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$')] 43 | [string] 44 | $Yellow = '#dddd00', 45 | 46 | # The scheme's definition of the color Blue. 47 | [Parameter(ValueFromPipelineByPropertyName)] 48 | [ValidatePattern('^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$')] 49 | [string] 50 | $Blue = '#0000dd', 51 | 52 | # The scheme's definition of the color Cyan. 53 | [Parameter(ValueFromPipelineByPropertyName)] 54 | [ValidatePattern('^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$')] 55 | [string] 56 | $Cyan = '#00dddd', 57 | 58 | # The scheme's definition of the color Purple. 59 | [Parameter(ValueFromPipelineByPropertyName)] 60 | [ValidatePattern('^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$')] 61 | [Alias('Magenta')] 62 | [string] 63 | $Purple = '#dd00dd', 64 | 65 | # The scheme's definition of the color White. 66 | [Parameter(ValueFromPipelineByPropertyName)] 67 | [ValidatePattern('^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$')] 68 | [string] 69 | $White = '#efefef', 70 | 71 | # The scheme's definition of the color BrightRed. 72 | [Parameter(ValueFromPipelineByPropertyName)] 73 | [ValidatePattern('^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$')] 74 | [string] 75 | $BrightRed = '#ff0000', 76 | 77 | # The scheme's definition of the color BrightGreen. 78 | [Parameter(ValueFromPipelineByPropertyName)] 79 | [ValidatePattern('^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$')] 80 | [string] 81 | $BrightGreen = '#00ff00', 82 | 83 | # The scheme's definition of the color BrightYellow. 84 | [Parameter(ValueFromPipelineByPropertyName)] 85 | [ValidatePattern('^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$')] 86 | [string] 87 | $BrightYellow = '#ffff00', 88 | 89 | # The scheme's definition of the color BrightBlue. 90 | [Parameter(ValueFromPipelineByPropertyName)] 91 | [ValidatePattern('^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$')] 92 | [string] 93 | $BrightBlue = '#0000ff', 94 | 95 | # The scheme's definition of the color BrightPurple. 96 | [Parameter(ValueFromPipelineByPropertyName)] 97 | [ValidatePattern('^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$')] 98 | [string] 99 | $BrightPurple = '#ff00ff', 100 | 101 | # The scheme's definition of the color BrightCyan. 102 | [Parameter(ValueFromPipelineByPropertyName)] 103 | [ValidatePattern('^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$')] 104 | [string] 105 | $BrightCyan = '#00ffff', 106 | 107 | # The scheme's definition of the color BrightWhite. 108 | [Parameter(ValueFromPipelineByPropertyName)] 109 | [ValidatePattern('^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$')] 110 | [string] 111 | $BrightWhite = '#ffffff', 112 | 113 | # The scheme's definition of the color BrightBlack. 114 | [Parameter(ValueFromPipelineByPropertyName)] 115 | [ValidatePattern('^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$')] 116 | [string] 117 | $BrightBlack = '#0d0d0d', 118 | 119 | # The scheme's foreground color. 120 | [Parameter(ValueFromPipelineByPropertyName)] 121 | [ValidatePattern('^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$')] 122 | [string] 123 | $Foreground = '#fefefe', 124 | 125 | # The scheme's background color. 126 | [Parameter(ValueFromPipelineByPropertyName)] 127 | [ValidatePattern('^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$')] 128 | [string] 129 | $Background = '#012456' 130 | ) 131 | 132 | process { 133 | #region Download iTerm2 Theme 134 | 135 | $iTermRepo = 'mbadolato/iTerm2-Color-Schemes/master/windowsterminal' 136 | $iTermThemeExists = 137 | Invoke-RestMethod -Uri "https://raw.githubusercontent.com/$iTermRepo/$Name.json" -ErrorAction Ignore 138 | #endregion Download iTerm2 Theme 139 | 140 | #region Create Color Scheme Object 141 | $newScheme = 142 | if ($iTermThemeExists) 143 | { 144 | # If the theme exists, let them customize it. 145 | foreach ($k in $PSBoundParameters.Keys) { 146 | # Any supplied parameter 147 | if ($k -ne 'Name' -and # except name 148 | $iTermThemeExists.$k # that exists in the theme 149 | ) { 150 | $iTermThemeExists.$k = # will be overwritten 151 | $PSBoundParameters[$k] # with the supplied parameter. 152 | } 153 | } 154 | $iTermThemeExists 155 | } 156 | else 157 | { 158 | # If the theme does not exist, 159 | if ($PSBoundParameters.Count -eq 1) 160 | { 161 | # and no other parameters are supplied, warn them. 162 | Write-Warning "Theme $Name does not exist on https://iterm2colorschemes.com/" 163 | } 164 | 165 | $myCmdMetaData = [Management.Automation.CommandMetaData]$MyInvocation.MyCommand 166 | # Create a color scheme object 167 | $newColorScheme = [Ordered]@{} 168 | # by walking over each parameter in this command. 169 | foreach ($p in $myCmdMetaData.Parameters.Keys) { 170 | # lowercase the first letter of the name, because JSON can be picky. 171 | $k = $p.Substring(0,1).ToLower() + $p.Substring(1) 172 | $newColorScheme[$k] = # and assign it to the variable value, 173 | $ExecutionContext.SessionState.PSVariable.Get($p).Value # because this will handle defaults. 174 | } 175 | [PSCustomObject]$newColorScheme 176 | } 177 | #endregion Create Color Scheme Object 178 | 179 | 180 | #region Update Windows Terminal Profile 181 | 182 | $wtProfile = Get-WTProfile -Global # Get our profile 183 | $wtProfile | # Add out color scheme to the list, 184 | Add-Member NoteProperty schemes @( 185 | $newScheme 186 | foreach ($_ in $wtProfile.schemes) { 187 | if ($_.Name -ne $Name) # and don't forget all of the other ones. 188 | { $_ } 189 | } 190 | ) -Force 191 | $wtPath = $wtProfile.Path 192 | if ($PSCmdlet.ShouldProcess("Add ColorScheme $Name to $wtPath")) # If we ShouldProcess 193 | { 194 | 195 | $wtProfile.psobject.properties.Remove('Path') 196 | $wtProfile | # turn the profile 197 | ConvertTo-Json -Depth 100 | # back into JSON 198 | Set-Content -Path $wtPath -Encoding UTF8 # and write it to disk. 199 | $wtProfile.psobject.properties.add([PSNoteProperty]::new('Path', $wtPath)) 200 | } 201 | elseif ($WhatIfPreference) # if we wanted to know -WhatIf 202 | { 203 | return $wtProfile # return the JSON object 204 | } 205 | #endregion Update Windows Terminal Profile 206 | } 207 | } -------------------------------------------------------------------------------- /Show-WT.ps1: -------------------------------------------------------------------------------- 1 | function Show-WT 2 | { 3 | <# 4 | .Synopsis 5 | Shows Images in the Windows Terminal 6 | .Description 7 | Shows Images in the Windows Terminal. 8 | 9 | By default, .GIF files will play once, and non-GIFs will stay for 15 seconds. 10 | .Example 11 | Show-WT -ImagePath .\My.gif # Shows My.gif in the current Windows Terminal profile. 12 | .Example 13 | Show-WT -ImagePath .\My.gif -Wait -1 # Shows My.gif forever 14 | .Link 15 | Get-WTProfile 16 | .Link 17 | Set-WTProfile 18 | #> 19 | [OutputType([Management.Automation.Job], [Nullable])] 20 | param( 21 | # The path to an image file. 22 | [Parameter(ValueFromPipelineByPropertyName,Position=0)] 23 | [ValidatePattern('\.(gif|jpg|jpeg|png)$')] 24 | [Alias('FullName','Image','BackgroundImage')] 25 | [string] 26 | $ImagePath, 27 | 28 | # If set, will display content in a given profile. 29 | # If not set, will attempt to auto-detect the profile. 30 | # If the profile cannot be automatically detected, content will be displayed using the default profile settings. 31 | # (this will not override an existing image) 32 | [string] 33 | $ProfileName, 34 | 35 | 36 | # Sets the alignment of the Image to draw over the window background. 37 | [Parameter(ValueFromPipelineByPropertyName)] 38 | [ValidateSet('bottom','bottomLeft','bottomRight','center','left','right','top','topLeft','topRight')] 39 | [Alias('BackgroundImageAlignment', 'ImageAlignment')] 40 | [string] 41 | $Alignment= 'center', 42 | 43 | # Sets the opacity of the Image to draw over the window background. 44 | [Parameter(ParameterSetName='ImageFile',ValueFromPipelineByPropertyName)] 45 | [Alias('BackgroundImageOpacity','ImageOpacity')] 46 | [float] 47 | $Opacity = .9, 48 | # Sets how the background image is resized to fill the window. 49 | 50 | [Parameter(ValueFromPipelineByPropertyName)] 51 | [ValidateSet('fill','none','uniform','uniformToFill')] 52 | [Alias('BackgroundImageStretchMode', 'ImageStretchMode')] 53 | [string] 54 | $StretchMode= 'uniformToFill', 55 | 56 | # How long to wait before making the change. 57 | # By default, the change will be as quick as possible. 58 | [Parameter(ValueFromPipelineByPropertyName)] 59 | [timespan] 60 | $Wait = 0, 61 | 62 | # Sets how long the image should be displayed. 63 | # If the duration is negative, the image will not be automatically cleared. 64 | [Parameter(ValueFromPipelineByPropertyName)] 65 | [Timespan] 66 | $Duration, 67 | 68 | # Sets the number of times an animated .gif should be looped. 69 | [Parameter(ValueFromPipelineByPropertyName)] 70 | [int] 71 | $LoopCount = 1, 72 | 73 | <# 74 | When useAcrylic is set to true, it sets the transparency of the window for the profile. 75 | Accepts floating point values from 0-1 (default 0.5). 76 | #> 77 | [Parameter(ValueFromPipelineByPropertyName)] 78 | [ValidateRange(0,1)] 79 | [float] 80 | $AcrylicOpacity, 81 | 82 | <# 83 | When set to true, the window will have an acrylic background. 84 | When set to false, the window will have a plain, untextured background. 85 | #> 86 | [Parameter(ValueFromPipelineByPropertyName)] 87 | [switch] 88 | $UseAcrylic, 89 | 90 | 91 | <# 92 | If provided, will use a pixel shader. 93 | #> 94 | [Parameter(ValueFromPipelineByPropertyName)] 95 | [string] 96 | $PixelShader, 97 | 98 | # If set, will run in a background job. 99 | [switch] 100 | $AsJob 101 | ) 102 | 103 | 104 | begin { 105 | 106 | #region Prepare Background Job 107 | if ($AsJob) { 108 | $jobCmd = $ExecutionContext.SessionState.InvokeCommand.GetCommand('Start-ThreadJob','Alias,Cmdlet,Function') 109 | if (-not $jobCmd) { 110 | $jobCmd = $ExecutionContext.SessionState.InvokeCommand.GetCommand('Start-Job','Alias,Cmdlet,Function') 111 | } 112 | 113 | $jobDef = [ScriptBlock]::Create(@" 114 | param([Collections.IDictionary]`$parameters) 115 | Import-Module '$($MyInvocation.MyCommand.Module.Path | Split-Path)' 116 | $($MyInvocation.MyCommand.Name) @parameters 117 | "@) 118 | } 119 | #endregion Prepare Background Job 120 | 121 | $getGifLength = { 122 | param([string]$resolvedPath) 123 | if (-not ('Drawing.Image' -as [type])) { 124 | Add-Type -AssemblyName System.Drawing 125 | } 126 | $img = [Drawing.Image]::FromFile($resolvedPath) 127 | $frameCount = 128 | try { 129 | $img.GetFrameCount([Drawing.Imaging.FrameDimension]::Time) 130 | } catch {0} 131 | 132 | $frameTimes = try { $img.GetPropertyItem(20736).Value } catch { 0 } 133 | if ($frameTimes) { 134 | $totalMS = 0 135 | for ($i=0; $i -lt $frameCount; $i++) { 136 | $totalMS+=[BitConverter]::ToInt32($frameTimes,$i * 4) * 10 137 | } 138 | [Timespan]::FromMilliseconds($totalMS) 139 | } 140 | $img.Dispose() 141 | } 142 | $accumulateArgs = [Collections.Generic.List[Collections.IDictionary]]::new() 143 | } 144 | 145 | 146 | process { 147 | $accumulateArgs.Add((@{} + $PSBoundParameters)) 148 | } 149 | end { 150 | foreach ($acc in $accumulateArgs) { 151 | foreach ($kv in $acc.GetEnumerator()) { 152 | $ExecutionContext.SessionState.PSVariable.Set($kv.Key, $kv.Value) 153 | } 154 | 155 | if (-not $targetProfile) { 156 | $targetProfile = 157 | if (-not $ProfileName) { 158 | Get-WTProfile -Current 159 | } else { 160 | Get-WTProfile -ProfileName $ProfileName 161 | } 162 | } 163 | 164 | if (-not $targetProfile) { 165 | $targetProfile = Get-WTProfile -Default 166 | } 167 | 168 | if (-not $targetProfile) { 169 | Write-Error "No target profile - WT_PROFILE_ID '$env:WT_PROFILE_ID'" 170 | return 171 | } 172 | 173 | if ($wait.TotalMilliseconds) { 174 | Start-Sleep -Milliseconds $wait.TotalMilliseconds 175 | } 176 | 177 | $targetProfileJson = $targetProfile | ConvertTo-Json -Depth 10 178 | $targetProfileBackup = $targetProfileJson | ConvertFrom-Json 179 | 180 | $myParameters = @{} + $PSBoundParameters 181 | 182 | if ($ImagePath) { 183 | $imageFileUri = $imagePath -as [uri] 184 | if ($imageFileUri.Authority) { 185 | $imageDest = 186 | if ($PSVersionTable.OS -and $PSVersionTable.OS -notlike '*windows*') { 187 | Join-Path "/home/$($env:USER)/Pictures" $imageFileUri.Segments[-1] 188 | } else { 189 | Join-Path "$home\Pictures" $imageFileUri.Segments[-1] 190 | } 191 | $newFile = New-Item -ItemType File -Path $imageDest -Force 192 | [Net.Webclient]::new().DownloadFile($imageFileUri, $newFile.FullName) 193 | $imagePath = $newFile.FullName 194 | } 195 | $resolvedPath = $ExecutionContext.SessionState.Path.GetResolvedPSPathFromPSPath($ImagePath) 196 | if (-not $resolvedPath) { return } 197 | 198 | 199 | $resolvedPath = Get-Item -LiteralPath $resolvedPath | Select-Object -ExpandProperty Fullname 200 | 201 | $myParameters['ImagePath'] = "$resolvedPath" 202 | } 203 | 204 | if (-not $ProfileName -and $ENV:WT_PROFILE_ID) { 205 | $ProfileName = $myParameters['ProfileName'] = $ENV:WT_PROFILE_ID 206 | } 207 | if ($AsJob) { 208 | $myParameters.Remove('AsJob') 209 | & $jobCmd -ScriptBlock $jobDef -ArgumentList $MyParameters 210 | return 211 | } 212 | 213 | 214 | 215 | 216 | $wasUsingAcrylic = ($targetProfile.useAcrylic -as [bool]) 217 | $oldAcrylicOpacity = ($targetProfile.acrylicOpacity -as [float]) 218 | $realPath = 219 | if ($resolvedPath -like '/mnt/*') { # If we're trying to show an image with a mounted path 220 | $resolvedPath -replace '/mnt/(?[a-z])', '${Letter}:\' -replace '/', '\' 221 | } elseif ($PSVersionTable.OS -and 222 | $PSVersionTable.OS -notlike '*Windows*' -and $env:WSL_DISTRO_NAME) { 223 | "\\wsl$\$($env:WSL_DISTRO_NAME)\" + ($resolvedPath -replace '/','\') 224 | } else { 225 | $resolvedPath 226 | } 227 | 228 | 229 | $updatedProfile = $targetProfile 230 | 231 | if ($ImagePath) { 232 | $updatedProfile| 233 | Add-Member backgroundImage "$realPath" -Force -PassThru | 234 | Add-Member backgroundImageOpacity $Opacity -Force -PassThru | 235 | Add-Member backgroundImageAlignment $Alignment -Force -PassThru | 236 | Add-Member backgroundImageStrechMode $StretchMode -Force 237 | } 238 | 239 | if ($PixelShader) { 240 | $resolvedPixelShaderPath = $ExecutionContext.SessionState.Path.GetResolvedPSPathFromPSPath("$PixelShader") 241 | $updatedProfile | 242 | Add-Member "experimental.pixelShaderPath" "$resolvedPixelShaderPath" -Force 243 | } elseif ($PSBoundParameters.ContainsKey('PixelShader')) { 244 | $updatedProfile | 245 | Add-Member "experimental.pixelShaderPath" "" -Force 246 | } 247 | 248 | 249 | if ($UseAcrylic.IsPresent) { 250 | $updatedProfile = $targetProfile | 251 | Add-Member useAcrylic ([bool]$UseAcrylic) -Force -PassThru 252 | } 253 | 254 | if ($AcrylicOpacity) { 255 | $updatedProfile = $updatedProfile | 256 | Add-Member acrylicOpacity $AcrylicOpacity -Force -PassThru 257 | } 258 | 259 | if ($targetProfile.guid) { 260 | Set-WTProfile -ProfileName $targetProfile.guid -Confirm:$false -InputObject $updatedProfile 261 | } else { 262 | Set-WTProfile -Default -Confirm:$false -InputObject $updatedProfile 263 | } 264 | 265 | if (-not $PSBoundParameters['Wait'] -and $ImagePath -like '*.gif') { 266 | $Duration = try { 267 | & $getGifLength $resolvedPath 268 | } catch { 269 | [Timespan]::FromSeconds(2.5 * (Get-Item -LiteralPath $resolvedPath).Length /1mb) 270 | } 271 | } 272 | if ($LoopCount -ne 1 -and $ImagePath) { 273 | $Duration = [Timespan]::FromMilliseconds((& $getGifLength $resolvedPath).TotalMilliseconds * $LoopCount) 274 | } 275 | if ($Duration.TotalMilliseconds -ge 0) { 276 | Start-Sleep -milliseconds $Duration.TotalMilliseconds 277 | $targetProfileBackup | 278 | Set-WTProfile -ProfileName $targetProfile.guid -Confirm:$false -Overwrite 279 | } 280 | } 281 | } 282 | } 283 | -------------------------------------------------------------------------------- /Get-WTProfile.ps1: -------------------------------------------------------------------------------- 1 | function Get-WTProfile 2 | { 3 | <# 4 | .Synopsis 5 | Gets a Windows Terminal Profiles 6 | .Description 7 | Gets Windows Terminal profiles. 8 | 9 | By default, Get-WTProfile gets all tab profiles. 10 | 11 | To get the global profile, use Get-WTProfile -Global 12 | 13 | To get color schemes, use Get-WTProfile -ColorScheme * 14 | .Link 15 | Set-WTProfile 16 | .Example 17 | Get-WTProfile 18 | .Example 19 | Get-WTProfile -Global 20 | #> 21 | [CmdletBinding(DefaultParameterSetName='Name')] 22 | [OutputType('WindowsTerminal.Profile','WindowsTerminal.ColorScheme')] 23 | param( 24 | # Returns Windows Terminal tab profiles, by name. 25 | [Parameter(ParameterSetName='Name',ValueFromPipelineByPropertyName)] 26 | [Alias('Name')] 27 | [string[]] 28 | $ProfileName, 29 | 30 | # Returns Windows Terminal tab profiles, by GUID. 31 | [Parameter(ParameterSetName='Guid',ValueFromPipelineByPropertyName)] 32 | [Guid[]] 33 | $Guid, 34 | 35 | # Returns Windows Terminal Color Schemes 36 | [Parameter(ParameterSetName='ColorScheme',ValueFromPipelineByPropertyName)] 37 | [string[]] 38 | $ColorScheme, 39 | 40 | # If -Setting is present, Get-WTProfile returns the global settings. 41 | [Parameter(Mandatory,ParameterSetName='GlobalSettings',ValueFromPipelineByPropertyName)] 42 | [Alias('Global','Settings', 'GlobalSetting','GlobalSettings')] 43 | [switch] 44 | $Setting, 45 | 46 | # If -Default is present, Get-WTProfile returns the default profile settings. 47 | [Parameter(Mandatory,ParameterSetName='Default',ValueFromPipelineByPropertyName)] 48 | [Alias('Defaults')] 49 | [switch] 50 | $Default, 51 | 52 | # If -Current is present, Get-WTProfile attempts to determine the current profile 53 | [Parameter(Mandatory,ParameterSetName='Current',ValueFromPipelineByPropertyName)] 54 | [switch] 55 | $Current, 56 | 57 | # If -KeyBinding is present, Get-WTProfile will return keybindings. 58 | [Parameter(Mandatory,ParameterSetName='KeyBinding',ValueFromPipelineByPropertyName)] 59 | [Alias('Keys','KeyBindings')] 60 | [switch] 61 | $KeyBinding, 62 | 63 | # If set, will force reloading of profile information. 64 | # By default, the profile object will be cached to improve performance. 65 | [switch] 66 | $Force 67 | ) 68 | 69 | begin { 70 | #region Locate the Profile 71 | # We only need to find the profile once, so let's cache the filinfo in $script:WTProfilePath 72 | if (-not $script:WTProfilePath) { 73 | $script:WTProfilePath = 74 | if ($PSVersionTable.Platform -ne 'Windows' -and (Test-Path '/mnt')) { 75 | Get-ChildItem '/mnt' | 76 | Get-ChildItem -Filter Users -ErrorAction Ignore | 77 | Get-ChildItem -Filter $env:USER | 78 | Get-ChildItem -Filter AppData -Force | 79 | Get-ChildItem -Filter Local -Force | 80 | Get-ChildItem -Filter Packages | 81 | Get-ChildItem -Filter Microsoft.WindowsTerminal_* | 82 | Get-ChildItem -Filter LocalState | 83 | Get-ChildItem -Filter settings.json 84 | } elseif ($PSVersionTable.Platform -like 'Win*' -or -not $PSVersionTable.Platform) { 85 | Resolve-Path "$env:APPDATA\..\Local\Packages" | 86 | Get-ChildItem -Filter Microsoft.WindowsTerminal_* | 87 | Get-ChildItem -Filter LocalState | 88 | Get-ChildItem -Filter settings.json 89 | } 90 | } 91 | #endregion Locate the Profile 92 | 93 | #region Declare Decorate Filter 94 | # A lot of this script boils down to "run this pipeline and change the PSTypenames" 95 | # so we'll declare a filter called decorate to save code. 96 | filter decorate([string]$pstypename) { 97 | $_.pstypenames.clear() 98 | $_.pstypenames.add($pstypename) 99 | $_ 100 | } 101 | #endregion Declare Decorate Filter 102 | if ($PSVersionTable.PSVersion -lt '7.0') { 103 | # If we're using an older version of PowerShell, ConvertFrom-JSON won't handle comments. 104 | # So override it. 105 | function ConvertFrom-Json 106 | { 107 | [CmdletBinding(HelpUri='https://go.microsoft.com/fwlink/?LinkID=217031', RemotingCapability='None')] 108 | param( 109 | [Parameter(Mandatory=$true, Position=0, ValueFromPipeline=$true)] 110 | [AllowEmptyString()] 111 | [string] 112 | ${InputObject} 113 | ) 114 | 115 | begin 116 | { 117 | try { 118 | $outBuffer = $null 119 | if ($PSBoundParameters.TryGetValue('OutBuffer', [ref]$outBuffer)) 120 | { 121 | $PSBoundParameters['OutBuffer'] = 1 122 | } 123 | $wrappedCmd = $ExecutionContext.InvokeCommand.GetCommand('Microsoft.PowerShell.Utility\ConvertFrom-Json', [System.Management.Automation.CommandTypes]::Cmdlet) 124 | $scriptCmd = {& $wrappedCmd @PSBoundParameters } 125 | $steppablePipeline = $scriptCmd.GetSteppablePipeline($myInvocation.CommandOrigin) 126 | $steppablePipeline.Begin($PSCmdlet) 127 | } catch { 128 | $_ | Write-Error 129 | } 130 | 131 | $regexTimeout = [Timespan]'00:00:02.5' 132 | 133 | # This RegEx will match block comments in JSON. 134 | $JSONBlockComments = [Regex]::new(' 135 | /\* # The open comment 136 | (? # capture the comment block. It is: 137 | (?:.|\s)+? # anything until 138 | (?=\z|\*/) # the end of the string or the closing comment 139 | )\*/ # Then match the close comment 140 | ', 'IgnoreCase, IgnorePatternWhitespace', $regexTimeout) 141 | } 142 | 143 | process 144 | { 145 | try { 146 | if ($PSBoundParameters.InputObject) { 147 | $_ = $PSBoundParameters.InputObject 148 | } 149 | 150 | 151 | # First, strip block comments 152 | $inObj = $_ 153 | $in = 154 | if ($InputObject.Contains('*/')) { 155 | $JSONBlockComments.Replace($inObj,'') 156 | } else { 157 | $InputObject 158 | } 159 | 160 | $hasComment = [regex]::new('(?:^|[^:])//','IgnoreCase',$regexTimeout) 161 | $CommentOrQuote = [Regex]::new("(?>(?//)|(?(?(?\r\n|\n)" 167 | $newlines = foreach ($line in $lines) { # otherwise, go line by line looking for comments. 168 | $lineHasComments = try { $hasComment.IsMatch($line) } catch {$false} 169 | if (-not $lineHasComments) { $line;continue } # If the line didn't contain a comment, echo it. 170 | 171 | $lineParts = 172 | try { $CommentOrQuote.Matches($line) } 173 | catch{ $null } 174 | if (-not $lineParts) { 175 | $line 176 | continue 177 | } 178 | $trimAt = -1 179 | 180 | $singleQuoteCounter = 0 181 | $doubleQuoteCounter = 0 182 | foreach ($lp in $lineParts) { # Count up thru the quotes. 183 | if ($lp.Groups["SingleQuote"].Success) { 184 | $singleQuoteCounter++ 185 | } 186 | if ($lp.Groups["DoubleQuote"].Success) { 187 | $doubleQuoteCounter++ 188 | } 189 | if ($lp.Groups["CommentStart"].Success -and 190 | -not ($singleQuoteCounter % 2) -and 191 | -not ($doubleQuoteCounter % 2)) { # If the comment occurs while the quotes are balanced 192 | 193 | $trimAt = $lp.Index # that's where we trim. 194 | break 195 | } 196 | } 197 | if ($trimAt -ne -1) { # If we know where to chop the line 198 | $line.Substring(0, $trimAt) # get everything up until that point 199 | } else { # otherwise, 200 | $line # echo the line. 201 | } 202 | } 203 | $newlines -join [Environment]::NewLine 204 | } 205 | 206 | if ($PSBoundParameters.InputObject) { 207 | $PSBoundParameters.InputObject = $in 208 | $steppablePipeline.Process($PSBoundParameters.InputObject) 209 | } else { 210 | $steppablePipeline.Process( 211 | $in 212 | ) 213 | } 214 | 215 | } catch { 216 | $_ | Write-Error 217 | } 218 | } 219 | 220 | end 221 | { 222 | try { 223 | $steppablePipeline.End() 224 | } catch { 225 | $_ | Write-Error 226 | } 227 | } 228 | } 229 | } 230 | } 231 | 232 | process { 233 | if (-not $script:WTProfilePath) # If we could not find the profile 234 | { 235 | Write-Error "Could not locate Windows Terminal profile" # error and return. 236 | return 237 | } 238 | 239 | $paramSet = $PSCmdlet.ParameterSetName 240 | if ($_.Guid -as [guid] -and $_.Name) { # If we were passed an input object with a GUID 241 | $paramSet = 'Guid' # trick the parameter set so we match just that one. 242 | $guid = $_.Guid 243 | } 244 | 245 | if ($Force) { $script:cachedWTProfile = $null } 246 | if (-not $script:cachedWTProfile) { 247 | $script:cachedWTProfile = $wtProfile = 248 | [IO.File]::ReadAllText($script:WTProfilePath.FullName) | # Read the profile 249 | ConvertFrom-Json | # convert it from JSON 250 | decorate WindowsTerminal.Settings | # decorate it as a 'WindowsTerminal.Settings' 251 | # and keep the path 252 | Add-Member NoteProperty Path $script:WTProfilePath.FullName -Force -PassThru 253 | } else { 254 | $wtProfile = $script:cachedWTProfile 255 | } 256 | 257 | 258 | 259 | switch ($paramSet) { 260 | ColorScheme { 261 | if (-not $ColorScheme) { $ColorScheme = '*' } 262 | :nextColorScheme foreach ($wtScheme in $wtProfile.schemes) { 263 | foreach ($cs in $ColorScheme) { 264 | if ($wtScheme.Name -notlike $cs) { continue } 265 | $wtScheme | decorate 'WindowsTerminal.ColorScheme' 266 | continue nextColorScheme 267 | } 268 | } 269 | } 270 | Name { 271 | if (-not $ProfileName) { $ProfileName = '*' } 272 | :nextProfile foreach ($wtProf in $wtProfile.profiles.list) { 273 | foreach ($pn in $ProfileName) { 274 | if ($wtProf.Name -notlike $pn -and $wtProf.guid -notlike $pn) { continue } 275 | $wtProf | decorate 'WindowsTerminal.Profile' 276 | continue nextProfile 277 | } 278 | } 279 | } 280 | Guid { 281 | foreach ($wtProf in $wtProfile.profiles.list) { 282 | if ($guid -notcontains $wtProf.guid) {continue } 283 | $wtProf | decorate 'WindowsTerminal.Profile' 284 | } 285 | } 286 | Default { 287 | $defaultProf = $wtProfile.profiles.default 288 | if ($defaultProf) { 289 | $defaultProf | decorate 'WindowsTerminal.Profile' 290 | } 291 | } 292 | GlobalSettings { $wtProfile } 293 | Current { 294 | if (-not $ENV:WT_PROFILE_ID) { return } 295 | foreach ($Prof in $wtProfile.profiles.list) { 296 | if ($prof.Guid -eq $ENV:WT_PROFILE_ID) { 297 | $prof | decorate 'WindowsTerminal.Profile' 298 | } 299 | } 300 | } 301 | KeyBinding { 302 | $wtProfile.keyBindings | decorate 'windowsTerminal.KeyBinding' 303 | } 304 | } 305 | } 306 | } 307 | -------------------------------------------------------------------------------- /New-WTProfile.ps1: -------------------------------------------------------------------------------- 1 | function New-WTProfile { 2 | <# 3 | .Synopsis 4 | Creates a new Windows Terminal profile 5 | .Description 6 | Creates a new Windows Terminal tab profile. 7 | .Link 8 | Add-WTProfile 9 | .Example 10 | New-WTProfile -Name DOS -CommandLine cmd 11 | .Example 12 | New-WTProfile -Name kali-linux-pwsh -CommandLine 'wsl -d kali-linux -e pwsh' 13 | .Example 14 | New-WTProfile -Default 15 | 16 | #> 17 | 18 | [OutputType('WindowsTerminal.Profile')] 19 | [Diagnostics.CodeAnalysis.SuppressMessageAttribute( 20 | "PSUseShouldProcessForStateChangingFunctions", "", Justification="Not changing state" 21 | )] 22 | param( 23 | # [deprecated] Please use `opacity` instead. 24 | [Parameter(ValueFromPipelineByPropertyName)] 25 | [ComponentModel.DefaultBindingProperty('acrylicOpacity')] 26 | [double] 27 | $AcrylicOpacity, 28 | # 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. 29 | [Parameter(ValueFromPipelineByPropertyName)] 30 | [ComponentModel.DefaultBindingProperty('antialiasingMode')] 31 | [ValidateSet('grayscale','cleartype','aliased')] 32 | [string] 33 | $AntialiasingMode, 34 | # Sets the background color of the text. Overrides "background" from the color scheme. Uses hex color format: "#rrggbb". 35 | [Parameter(ValueFromPipelineByPropertyName)] 36 | [ComponentModel.DefaultBindingProperty('background')] 37 | [ValidatePattern('^#[A-Fa-f0-9]{3}(?:[A-Fa-f0-9]{3})?$')] 38 | [string] 39 | $Background, 40 | # Sets the appearance of the terminal when it is unfocused. 41 | [Parameter(ValueFromPipelineByPropertyName)] 42 | [ComponentModel.DefaultBindingProperty('unfocusedAppearance')] 43 | [PSObject] 44 | $UnfocusedAppearance, 45 | # Sets the font options of the terminal. 46 | [Parameter(ValueFromPipelineByPropertyName)] 47 | [ComponentModel.DefaultBindingProperty('font')] 48 | [PSObject] 49 | $Font, 50 | # Sets the file location of the image to draw over the window background. 51 | [Parameter(ValueFromPipelineByPropertyName)] 52 | [ComponentModel.DefaultBindingProperty('backgroundImage')] 53 | [ValidateSet('desktopWallpaper','')] 54 | $BackgroundImage, 55 | # Sets how the background image aligns to the boundaries of the window. Possible values: "center", "left", "top", "right", "bottom", "topLeft", "topRight", "bottomLeft", "bottomRight" 56 | [Parameter(ValueFromPipelineByPropertyName)] 57 | [ComponentModel.DefaultBindingProperty('backgroundImageAlignment')] 58 | [ValidateSet('bottom','bottomLeft','bottomRight','center','left','right','top','topLeft','topRight')] 59 | [string] 60 | $BackgroundImageAlignment, 61 | # Sets the transparency of the background image. Accepts floating point values from 0-1. 62 | [Parameter(ValueFromPipelineByPropertyName)] 63 | [ComponentModel.DefaultBindingProperty('backgroundImageOpacity')] 64 | [double] 65 | $BackgroundImageOpacity, 66 | # Sets how the background image is resized to fill the window. 67 | [Parameter(ValueFromPipelineByPropertyName)] 68 | [ComponentModel.DefaultBindingProperty('backgroundImageStretchMode')] 69 | [ValidateSet('fill','none','uniform','uniformToFill')] 70 | [string] 71 | $BackgroundImageStretchMode, 72 | # Controls what happens when the application emits a BEL character. When set to "all", the Terminal will play a sound, flash the taskbar icon (if the terminal window is not in focus) and flash the window. An array of specific behaviors can also be used. Supported array values include `audible`, `window` and `taskbar`. When set to "none", nothing will happen. 73 | [Parameter(ValueFromPipelineByPropertyName)] 74 | [ComponentModel.DefaultBindingProperty('bellStyle')] 75 | $BellStyle, 76 | # Sets the sound played when the application emits a BEL. When set to an array, the terminal will pick one of those sounds at random. 77 | [Parameter(ValueFromPipelineByPropertyName)] 78 | [ComponentModel.DefaultBindingProperty('bellSound')] 79 | $BellSound, 80 | <# 81 | Sets how the profile reacts to termination or failure to launch. Possible values: 82 | -"graceful" (close when exit is typed or the process exits normally) 83 | -"always" (always close) 84 | -"automatic" (behave as "graceful" only for processes launched by terminal, behave as "always" otherwise) 85 | -"never" (never close). 86 | true and false are accepted as synonyms for "graceful" and "never" respectively. 87 | #> 88 | [Parameter(ValueFromPipelineByPropertyName)] 89 | [ComponentModel.DefaultBindingProperty('closeOnExit')] 90 | $CloseOnExit, 91 | # Name of the terminal color scheme to use. Color schemes are defined under "schemes". 92 | [Parameter(ValueFromPipelineByPropertyName)] 93 | [ComponentModel.DefaultBindingProperty('colorScheme')] 94 | [string] 95 | $ColorScheme, 96 | # Executable used in the profile. 97 | [Parameter(ValueFromPipelineByPropertyName)] 98 | [ComponentModel.DefaultBindingProperty('commandline')] 99 | [string] 100 | $Commandline, 101 | # Sets the color of the cursor. Overrides the cursor color from the color scheme. Uses hex color format: "#rrggbb". 102 | [Parameter(ValueFromPipelineByPropertyName)] 103 | [ComponentModel.DefaultBindingProperty('cursorColor')] 104 | [ValidatePattern('(?>^\s{0}$|^#[A-Fa-f0-9]{3}(?:[A-Fa-f0-9]{3})?$)')] 105 | [string] 106 | $CursorColor, 107 | # Sets the percentage height of the cursor starting from the bottom. Only works when cursorShape is set to "vintage". Accepts values from 1-100. 108 | [Parameter(ValueFromPipelineByPropertyName)] 109 | [ComponentModel.DefaultBindingProperty('cursorHeight')] 110 | [int] 111 | $CursorHeight, 112 | <# 113 | Sets the shape of the cursor. Possible values: 114 | -"bar" ( ┃, default ) 115 | -"doubleUnderscore" ( ‗ ) 116 | -"emptyBox" ( ▯ ) 117 | -"filledBox" ( █ ) 118 | -"underscore" ( ▁ ) 119 | -"vintage" ( ▃ ) 120 | #> 121 | [Parameter(ValueFromPipelineByPropertyName)] 122 | [ComponentModel.DefaultBindingProperty('cursorShape')] 123 | [ValidateSet('bar','doubleUnderscore','emptyBox','filledBox','underscore','vintage')] 124 | [string] 125 | $CursorShape, 126 | # When true, this profile should always open in an elevated context. If the window isn't running as an Administrator, then a new elevated window will be created. 127 | [Parameter(ValueFromPipelineByPropertyName)] 128 | [ComponentModel.DefaultBindingProperty('elevate')] 129 | [switch] 130 | $Elevate, 131 | # When set to true, directs the PTY for this connection to use pass-through mode instead of the original Conhost PTY simulation engine. This is an experimental feature, and its continued existence is not guaranteed. 132 | [Parameter(ValueFromPipelineByPropertyName)] 133 | [ComponentModel.DefaultBindingProperty('experimental.connection.passthroughMode')] 134 | [switch] 135 | $ConnectionPassthroughMode, 136 | # When set to true, enable retro terminal effects. This is an experimental feature, and its continued existence is not guaranteed. 137 | [Parameter(ValueFromPipelineByPropertyName)] 138 | [ComponentModel.DefaultBindingProperty('experimental.retroTerminalEffect')] 139 | [switch] 140 | $RetroTerminalEffect, 141 | # Use to set a path to a pixel shader to use with the Terminal. Overrides `experimental.retroTerminalEffect`. This is an experimental feature, and its continued existence is not guaranteed. 142 | [Parameter(ValueFromPipelineByPropertyName)] 143 | [ComponentModel.DefaultBindingProperty('experimental.pixelShaderPath')] 144 | [string] 145 | $PixelShaderPath, 146 | # Enable using the experimental new rendering engine for this profile. This is an experimental feature, and its continued existence is not guaranteed. 147 | [Parameter(ValueFromPipelineByPropertyName)] 148 | [ComponentModel.DefaultBindingProperty('experimental.useAtlasEngine')] 149 | [switch] 150 | $UseAtlasEngine, 151 | # [deprecated] Define 'face' within the 'font' object instead. 152 | [Parameter(ValueFromPipelineByPropertyName)] 153 | [ComponentModel.DefaultBindingProperty('fontFace')] 154 | [string] 155 | $FontFace, 156 | # [deprecated] Define 'size' within the 'font' object instead. 157 | [Parameter(ValueFromPipelineByPropertyName)] 158 | [ComponentModel.DefaultBindingProperty('fontSize')] 159 | [int] 160 | $FontSize, 161 | # [deprecated] Define 'weight' within the 'font' object instead. 162 | [Parameter(ValueFromPipelineByPropertyName)] 163 | [ComponentModel.DefaultBindingProperty('fontWeight')] 164 | $FontWeight, 165 | # Controls how 'intense' text is rendered. Values are "bold", "bright", "all" and "none" 166 | [Parameter(ValueFromPipelineByPropertyName)] 167 | [ComponentModel.DefaultBindingProperty('intenseTextStyle')] 168 | [ValidateSet('none','bold','bright','all')] 169 | [string] 170 | $IntenseTextStyle, 171 | # Sets the text color. Overrides "foreground" from the color scheme. Uses hex color format: "#rrggbb". 172 | [Parameter(ValueFromPipelineByPropertyName)] 173 | [ComponentModel.DefaultBindingProperty('foreground')] 174 | [ValidatePattern('^#[A-Fa-f0-9]{3}(?:[A-Fa-f0-9]{3})?$')] 175 | [string] 176 | $Foreground, 177 | # Unique identifier of the profile. Written in registry format: "{00000000-0000-0000-0000-000000000000}". 178 | [Parameter(ValueFromPipelineByPropertyName)] 179 | [ComponentModel.DefaultBindingProperty('guid')] 180 | [ValidatePattern('^\{[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}\}$')] 181 | [string] 182 | $Guid, 183 | # 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. 184 | [Parameter(ValueFromPipelineByPropertyName)] 185 | [ComponentModel.DefaultBindingProperty('hidden')] 186 | [switch] 187 | $Hidden, 188 | # The number of lines above the ones displayed in the window you can scroll back to. 189 | [Parameter(ValueFromPipelineByPropertyName)] 190 | [ComponentModel.DefaultBindingProperty('historySize')] 191 | [int] 192 | $HistorySize, 193 | # 194 | [Parameter(ValueFromPipelineByPropertyName)] 195 | [ComponentModel.DefaultBindingProperty('icon')] 196 | [string] 197 | $Icon, 198 | # Name of the profile. Displays in the dropdown menu. 199 | [Parameter(ValueFromPipelineByPropertyName)] 200 | [ComponentModel.DefaultBindingProperty('name')] 201 | [string] 202 | $Name, 203 | # Sets the opacity of the window for the profile. Accepts values from 0-100. Defaults to 50 when useAcrylic is set to true. 204 | [Parameter(ValueFromPipelineByPropertyName)] 205 | [ComponentModel.DefaultBindingProperty('opacity')] 206 | [double] 207 | $Opacity, 208 | <# 209 | Sets the padding around the text within the window. Can have three different formats: 210 | -"#" sets the same padding for all sides 211 | -"#, #" sets the same padding for left-right and top-bottom 212 | -"#, #, #, #" sets the padding individually for left, top, right, and bottom. 213 | #> 214 | [Parameter(ValueFromPipelineByPropertyName)] 215 | [ComponentModel.DefaultBindingProperty('padding')] 216 | $Padding, 217 | # When set to true, we will (when necessary) adjust the foreground color to make it more visible, based on the background color. 218 | [Parameter(ValueFromPipelineByPropertyName)] 219 | [ComponentModel.DefaultBindingProperty('adjustIndistinguishableColors')] 220 | [switch] 221 | $AdjustIndistinguishableColors, 222 | # Defines the visibility of the scrollbar. 223 | [Parameter(ValueFromPipelineByPropertyName)] 224 | [ComponentModel.DefaultBindingProperty('scrollbarState')] 225 | [ValidateSet('visible','hidden')] 226 | [string] 227 | $ScrollbarState, 228 | # Sets the background color of selected text. Overrides selectionBackground set in the color scheme. Uses hex color format: "#rrggbb". 229 | [Parameter(ValueFromPipelineByPropertyName)] 230 | [ComponentModel.DefaultBindingProperty('selectionBackground')] 231 | [ValidatePattern('(?>^\s{0}$|^#[A-Fa-f0-9]{3}(?:[A-Fa-f0-9]{3})?$)')] 232 | [string] 233 | $SelectionBackground, 234 | # 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. 235 | [Parameter(ValueFromPipelineByPropertyName)] 236 | [ComponentModel.DefaultBindingProperty('snapOnInput')] 237 | [switch] 238 | $SnapOnInput, 239 | # By default Windows treats Ctrl+Alt as an alias for AltGr. When altGrAliasing is set to false, this behavior will be disabled. 240 | [Parameter(ValueFromPipelineByPropertyName)] 241 | [ComponentModel.DefaultBindingProperty('altGrAliasing')] 242 | [switch] 243 | $AltGrAliasing, 244 | # Stores the name of the profile generator that originated this profile. 245 | [Parameter(ValueFromPipelineByPropertyName)] 246 | [ComponentModel.DefaultBindingProperty('source')] 247 | [string] 248 | $Source, 249 | # The directory the shell starts in when it is loaded. 250 | [Parameter(ValueFromPipelineByPropertyName)] 251 | [ComponentModel.DefaultBindingProperty('startingDirectory')] 252 | [string] 253 | $StartingDirectory, 254 | # 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. 255 | [Parameter(ValueFromPipelineByPropertyName)] 256 | [ComponentModel.DefaultBindingProperty('suppressApplicationTitle')] 257 | [switch] 258 | $SuppressApplicationTitle, 259 | # Sets the color of the profile's tab. Using the tab color picker will override this color. 260 | [Parameter(ValueFromPipelineByPropertyName)] 261 | [ComponentModel.DefaultBindingProperty('tabColor')] 262 | [ValidatePattern('^#[A-Fa-f0-9]{3}(?:[A-Fa-f0-9]{3})?$')] 263 | [string] 264 | $TabColor, 265 | # 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. 266 | [Parameter(ValueFromPipelineByPropertyName)] 267 | [ComponentModel.DefaultBindingProperty('tabTitle')] 268 | [string] 269 | $TabTitle, 270 | # When set to true, the window will have an acrylic material background. When set to false, the window will have a plain, untextured background. 271 | [Parameter(ValueFromPipelineByPropertyName)] 272 | [ComponentModel.DefaultBindingProperty('useAcrylic')] 273 | [switch] 274 | $UseAcrylic 275 | ) 276 | } 277 | 278 | -------------------------------------------------------------------------------- /Set-WTProfile.ps.ps1: -------------------------------------------------------------------------------- 1 | function Set-WTProfile 2 | { 3 | <# 4 | .Synopsis 5 | Sets the Windows Terminal profile 6 | .Description 7 | Changes the Windows Terminal profile. 8 | 9 | Use Get-Help Set-WTProfile -Parameter * to learn what you can change. 10 | .Link 11 | Get-WTProfile 12 | .Example 13 | Set-WTProfile -LaunchMode Maximized 14 | .Example 15 | Set-WTProfile 16 | #> 17 | [CmdletBinding(SupportsShouldProcess,ConfirmImpact='Medium',DefaultParameterSetName='Current')] 18 | [OutputType([Nullable],[PSObject])] 19 | [RenameVariable(VariableRename={ 20 | @{ 21 | "GUID" = "NewGUID" 22 | "TabTitle" = "TabStartupTitle" 23 | } 24 | })] 25 | [JSONSchema(SchemaUri='https://aka.ms/terminal-profiles-schema#Profile',RemovePropertyPrefix='Experimental')] 26 | param( 27 | # The InputObject. This is used to provide information to a specific tab profile. 28 | [Parameter(ValueFromPipeline,ParameterSetName='InputObject')] 29 | [Parameter(ValueFromPipeline,ParameterSetName='Default')] 30 | [Parameter(ValueFromPipeline,ParameterSetName='Current')] 31 | [PSObject] 32 | $InputObject, 33 | 34 | # The name or ID of the tab profile. This is used to determine which profiles are changed by the -InputObject. 35 | [Parameter(ParameterSetName='InputObject',ValueFromPipelineByPropertyName)] 36 | [Alias('GUID')] 37 | [string] 38 | $ProfileName, 39 | 40 | # If set, will set profile defaults, instead of a particular profile. 41 | [Parameter(Mandatory,ParameterSetName='Default')] 42 | [Alias('Defaults')] 43 | [switch] 44 | $Default, 45 | 46 | # If set, will set the current profile (based off of ENV:WT_PROFILE_ID). 47 | [Parameter(Mandatory,ParameterSetName='Current')] 48 | [switch] 49 | $Current, 50 | 51 | # If set, changes will apply to the global profile. 52 | [Parameter(Mandatory,ParameterSetName='Global')] 53 | [switch] 54 | $Global, 55 | 56 | # Properties are specific to each color scheme. 57 | # ColorTool is a great tool you can use to create and explore new color schemes. 58 | # All colors use hex color format. 59 | [Parameter(ParameterSetName='Global')] 60 | [Alias('Schemes')] 61 | [PSObject[]] 62 | $ColorScheme, 63 | 64 | # If provided, changes the launch mode. 65 | # Valid launch modes are 'Maximized' and 'Default'. 66 | [Parameter(ParameterSetName='Global')] 67 | [ValidateSet('Maximized','Default')] 68 | [string] 69 | $LaunchMode, 70 | 71 | # If provided, changes the tab width mode. 72 | # Valid modes are 'Equal' and 'TitleLength'. 73 | [Parameter(ParameterSetName='Global')] 74 | [ValidateSet('Equal','TitleLength')] 75 | [string] 76 | $TabWidthMode, 77 | 78 | # When set to true, tabs are always displayed. 79 | # When set to false and showTabsInTitlebar is set to false, 80 | # tabs only appear after opening a new tab. 81 | [Parameter(ParameterSetName='Global')] 82 | [Alias('AlwaysShowTabs')] 83 | [switch] 84 | $AlwaysShowTab, 85 | 86 | # When set to true, a selection is immediately copied to your clipboard upon creation. 87 | # When set to false, the selection persists and awaits further action. 88 | [Parameter(ParameterSetName='Global')] 89 | [Alias('QuickEdit')] 90 | [switch] 91 | $CopyOnSelect, 92 | 93 | # When set to true closing a window with multiple tabs open WILL require confirmation. 94 | # When set to false closing a window with multiple tabs open WILL NOT require confirmation. 95 | [Parameter(ParameterSetName='Global')] 96 | [switch] 97 | $ConfirmCloseAllTabs, 98 | 99 | # If set, will pass the updated objects back to the pipeline. 100 | [switch] 101 | $PassThru, 102 | 103 | # If set, will force reloading of profile information. 104 | # By default, the profile object will be cached to improve performance. 105 | [switch] 106 | $Force, 107 | 108 | # By default, an -InputObject and any changes will be merged with the profile object 109 | # If -Overwrite is set, Set-WTProfile will overwrite an existing profile object instead. 110 | # Note: this should only be done with a complete profile object. 111 | [switch] 112 | $Overwrite 113 | ) 114 | 115 | begin { 116 | $myParameters = $MyInvocation.MyCommand.Parameters.Values 117 | $myProfileProperties = :nextParam foreach ($param in $myParameters) { 118 | foreach ($attr in $param.Attributes) { 119 | if ($attr -is [ComponentModel.DefaultBindingPropertyAttribute]) { 120 | $param 121 | continue nextParam 122 | } 123 | } 124 | } 125 | } 126 | 127 | process { 128 | $wtProfile = Get-WTProfile -Global -Force:$force 129 | 130 | if (-not $wtProfile) { 131 | Write-Error "Could not load global profile" 132 | return 133 | } 134 | 135 | $myParameters = [Ordered]@{} + $PSBoundParameters 136 | $myProfileParameters = [Ordered]@{} 137 | foreach ($myProfileProperty in $myProfileProperties) { 138 | if ($myParameters.Contains($myProfileProperty.Name)) { 139 | $propertyName = foreach ($attr in $myProfileProperty.Attributes) { 140 | if ($attr -is [System.ComponentModel.DefaultBindingPropertyAttribute]) { 141 | $attr.Name 142 | break 143 | } 144 | } 145 | $paramValue = $myParameters[$myProfileProperty.Name] 146 | foreach ($attr in $myProfileProperty.Attributes) { 147 | if ($attr -is [ComponentModel.AmbientValueAttribute] -and $attr.Value -is [scriptblock]) { 148 | $_ = $this = $PSItem = $paramValue 149 | $paramValue = & $attr.Value 150 | break 151 | } 152 | if ($attr -is [ValidateSet]) { 153 | foreach ($validValue in $attr.Validvalues) { 154 | if ($paramValue -eq $validValue) { 155 | $paramValue = $validValue 156 | } 157 | } 158 | } 159 | } 160 | if ($paramValue -is [switch]) { 161 | $paramValue = $paramValue -as [bool] 162 | } 163 | $myProfileParameters[$propertyName] = $paramValue 164 | } 165 | } 166 | 167 | $changed = $false 168 | 169 | #region Global Settings 170 | if ($LaunchMode -and $wtProfile.LaunchMode -ne $LaunchMode) { 171 | $LaunchMode = $LaunchMode.Substring(0,1).ToLower() + $LaunchMode.Substring(1) 172 | $wtProfile | Add-Member NoteProperty launchMode $LaunchMode -Force 173 | $changed = $true 174 | } 175 | 176 | if ($TabWidthMode -and $wtProfile.TabWidthMode -ne $TabWidthMode) { 177 | $TabWidthMode = $TabWidthMode.Substring(0,1).ToLower() + $TabWidthMode.Substring(1) 178 | $wtProfile | Add-Member NoteProperty tabWidthMode $TabWidthMode -Force 179 | $changed = $true 180 | } 181 | 182 | if ($MyParameters.Contains('AlwaysShowTab') -and $wtProfile.alwaysShowTabs -ne $AlwaysShowTab) { 183 | $wtProfile | Add-Member NoteProperty alwaysShowTabs ([bool]$AlwaysShowTab) -Force 184 | $changed = $true 185 | } 186 | 187 | if ($MyParameters.Contains('CopyOnSelect') -and $wtProfile.copyOnSelect -ne $CopyOnSelect) { 188 | $wtProfile | Add-Member NoteProperty copyOnSelect ([bool]$CopyOnSelect) -Force 189 | $changed = $true 190 | } 191 | 192 | if ($MyParameters.Contains('ConfirmCloseAllTabs') -and $wtProfile.confirmCloseAllTabs -ne $ConfirmCloseAllTabs) { 193 | $wtProfile | Add-Member NoteProperty confirmCloseAllTabs ([bool]$ConfirmCloseAllTabs) -Force 194 | $changed = $true 195 | } 196 | #endregion Global Settings 197 | 198 | if ($ColorScheme -and $PSCmdlet.ShouldProcess('Overwrite Color Schemes')) { 199 | 200 | $wtProfile | Add-Member NoteProperty schemes $ColorScheme -Force 201 | $changed = $true 202 | } 203 | 204 | #region Profile Specific Settings 205 | if ($Current) { 206 | if ($ENV:WT_PROFILE_ID) { 207 | $ProfileName = $ENV:WT_PROFILE_ID 208 | } 209 | else { 210 | Write-Error '$ENV:WT_PROFILE_ID not found' 211 | return 212 | } 213 | } 214 | 215 | if ($myProfileParameters.Count) { 216 | if (-not $InputObject) { 217 | $InputObject = [PSCustomObject]$myProfileParameters 218 | } else { 219 | foreach ($profileUpdate in $myProfileParameters.GetEnumerator()) { 220 | Add-Member NoteProperty $profileUpdate.Key $profileUpdate.Value -Force -InputObject $InputObject 221 | } 222 | } 223 | } 224 | 225 | if ($InputObject -and -not $ProfileName -and $ENV:WT_PROFILE_ID) { 226 | $ProfileName = $ENV:WT_PROFILE_ID 227 | } 228 | 229 | if ($InputObject -and ($ProfileName -or $Default)) { 230 | $targetProfiles = 231 | if ($Default) { 232 | $wtProfile.profiles.default 233 | } else { 234 | @(foreach ($prof in $wtProfile.profiles.list) { 235 | if ($prof.Name -eq $ProfileName -or 236 | $prof.Guid -eq $ProfileName -or 237 | $prof.Guid -eq "{$profileName}") { 238 | $prof 239 | } 240 | }) 241 | } 242 | 243 | if (-not $targetProfiles -and -not $Default) { 244 | Write-Error "Profile '$profileName' not found" 245 | return 246 | } 247 | 248 | if ($Default -and -not $targetProfiles) { 249 | if (-not $wtProfile.profiles.defaults) { 250 | $wtProfile.profiles | 251 | Add-Member NoteProperty defaults ([PSObject]::new()) -Force 252 | } 253 | $targetProfiles = @($wtProfile.profiles.defaults) 254 | } 255 | 256 | 257 | 258 | if ($targetProfiles) { 259 | if ($Overwrite) { 260 | $wtProfile.profiles.list = @(foreach ($prof in $wtProfile.profiles.list) { 261 | if ($prof -in $targetProfiles) { 262 | if ($InputObject -is [Collections.IDictionary]) { 263 | [PSCustomObject]$InputObject 264 | } else { 265 | $InputObject 266 | } 267 | } else { 268 | $prof 269 | } 270 | }) 271 | } else { 272 | foreach ($target in $targetProfiles) { 273 | if ($InputObject -is [Collections.IDictionary]) { 274 | foreach ($kv in $InputObject.GetEnumerator()) { 275 | if ([String]::IsNullOrEmpty($kv.Value)) { 276 | $target.psobject.properties.Remove($kv.Key) 277 | } else { 278 | $k = $kv.Key.ToString().Substring(0,1).ToLower() + $kv.Key.ToString().Substring(1) 279 | $target | 280 | Add-Member NoteProperty $k $kv.Value -Force 281 | } 282 | } 283 | } else { 284 | foreach ($prop in $InputObject.psobject.properties) { 285 | if ([String]::IsNullOrEmpty($prop.Value)) { 286 | $target.psobject.properties.Remove($prop.Name) 287 | } else { 288 | $k = $prop.Name.Substring(0,1).ToLower() + $prop.Name.Substring(1) 289 | $target | Add-Member NoteProperty $prop.Name $prop.Value -Force 290 | } 291 | } 292 | } 293 | } 294 | } 295 | 296 | $changed = $true 297 | } else { 298 | Write-Warning "No Target profiles!" 299 | } 300 | } 301 | #endregion Profile Specific Settings 302 | 303 | #region Write Profile 304 | if ($WhatIfPreference -or $PassThru) { 305 | if ($targetProfiles) { 306 | $targetProfiles 307 | } else { 308 | $wtProfile 309 | } 310 | } 311 | 312 | if ($changed -and $PSCmdlet.ShouldProcess("Update $($wtProfile.Path)")) { 313 | $script:cachedWTProfile = $wtProfile 314 | $wtPath = $wtProfile.Path 315 | $wtProfile.psobject.properties.Remove('Path') 316 | $json = $wtProfile | ConvertTo-Json -Depth 100 317 | $tries = 3 318 | do { 319 | try { 320 | [IO.File]::WriteAllText($wtPath, $JSON, [Text.Encoding]::UTF8) 321 | break 322 | } catch { 323 | $tries-- 324 | Write-Warning "$_ : $tries Left" 325 | [Threading.Thread]::Sleep(100) 326 | } 327 | } while ($tries) 328 | 329 | $wtProfile.psobject.properties.add([PSNoteProperty]::new('Path', $wtPath)) 330 | } 331 | 332 | 333 | #endregion Write Profile 334 | } 335 | } 336 | -------------------------------------------------------------------------------- /TerminalVelocity.format.ps1xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | WindowsTerminal.ColorScheme 7 | 8 | WindowsTerminal.ColorScheme 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | $host.UI.SupportsVirtualTerminal 17 | 18 | $moduleName = 'TerminalVelocity' 19 | 20 | do { 21 | $lm = Get-Module -Name $moduleName -ErrorAction Ignore 22 | if (-not $lm) { continue } 23 | if ($lm.FormatPartsLoaded) { break } 24 | $wholeScript = @(foreach ($formatFilePath in $lm.exportedFormatFiles) { 25 | foreach ($partNodeName in Select-Xml -LiteralPath $formatFilePath -XPath "/Configuration/Controls/Control/Name[starts-with(., '$')]") { 26 | $ParentNode = $partNodeName.Node.ParentNode 27 | "$($ParentNode.Name)={ 28 | $($ParentNode.CustomControl.CustomEntries.CustomEntry.CustomItem.ExpressionBinding.ScriptBlock)}" 29 | } 30 | }) -join [Environment]::NewLine 31 | New-Module -Name "${ModuleName}.format.ps1xml" -ScriptBlock ([ScriptBlock]::Create(($wholeScript + ';Export-ModuleMember -Variable *'))) | 32 | Import-Module -Global 33 | $onRemove = [ScriptBlock]::Create("Remove-Module '${ModuleName}.format.ps1xml'") 34 | 35 | if (-not $lm.OnRemove) { 36 | $lm.OnRemove = $onRemove 37 | } else { 38 | $lm.OnRemove = [ScriptBlock]::Create($onRemove.ToString() + '' + [Environment]::NewLine + $lm.OnRemove) 39 | } 40 | $lm | Add-Member NoteProperty FormatPartsLoaded $true -Force 41 | 42 | } while ($false) 43 | 44 | 45 | 46 | $colorScheme = $_ 47 | $bufferWidth = $host.UI.RawUI.BufferSize.Width 48 | 49 | if ($bufferWidth -lt 110){ 50 | @( 51 | $colorScheme = $_ 52 | . ${TerminalVelocity_setOutputStyle} -Foreground $colorScheme.foreground -Background $colorScheme.background 53 | $colorScheme.name 54 | . ${TerminalVelocity_clearOutputStyle} 55 | ) -join '' 56 | return 57 | } 58 | 59 | @( 60 | @( 61 | 62 | 63 | $bgColors = 'Background','Black','Red','Green', 'Yellow', 'Blue', 'Purple','Cyan','White' 64 | $bgColorWidth = $host.UI.RawUI.BufferSize.Width / ($bgColors.Length + 1) 65 | 66 | $bigEnoughForColors =$host.UI.RawUI.BufferSize.Width -ge 124 67 | 68 | 69 | 70 | $headerLine = 71 | @(for ($n =0; $n -lt $bgColors.Length; $n++) { 72 | $colWidth = 73 | if ($n -eq 0) { 74 | 14 75 | } elseif ($n -eq 1) { 76 | 9 77 | } else { 78 | $bgColorWidth 79 | } 80 | 81 | $space = [Math]::Max(0, $colWidth - $bgColors[$n].Length) 82 | "$(' ' * [Math]::Ceiling($space /2))$($bgColors[$n])$(' ' * [Math]::Floor($space /2))|" 83 | 84 | }) -join '' 85 | 86 | 87 | (. ${TerminalVelocity_setOutputStyle} -Background $colorScheme.background -foreground $colorScheme.foreground) + 88 | "$('---' + $colorScheme.Name + ('-' * ($headerLine.Length - 4 - $colorScheme.Name.Length)) + '|')" + 89 | ( & ${TerminalVelocity_clearOutputStyle}) 90 | 91 | #. $setOutputStyle -Foreground $colorScheme.Foreground -Background $colorScheme.Background 92 | (. ${TerminalVelocity_setOutputStyle} -Background $colorScheme.background -foreground $colorScheme.foreground) + $headerLine + ( & ${TerminalVelocity_clearOutputStyle}) 93 | foreach ($fg in 'Foreground','BrightWhite','Black','BrightBlack', 94 | 'Red', 'BrightRed','Green','BrightGreen','Yellow','BrightYellow', 95 | 'Blue','BrightBlue','Purple','BrightPurple', 'Cyan', 'BrightCyan','White','BrightWhite') { 96 | $line = ''# . $setOutputStyle -Foreground $colorScheme.($fg) 97 | 98 | $line += @( 99 | $n = 0 100 | 101 | foreach ($bg in $bgColors) { 102 | $bgColor = $colorScheme.$bg 103 | 104 | & ${TerminalVelocity_setOutputStyle} -Background $colorScheme.$bg 105 | $t = if ($n -eq 0) { 106 | $fg 107 | $colWidth = 14 108 | } elseif ($n -eq 1) { 109 | "$($colorScheme.$fg)" 110 | $colWidth = 9 111 | } else { 112 | if ($bigEnoughForColors) { 113 | "$($colorScheme.$fg)" 114 | } else { 115 | "E.g" 116 | } 117 | $colWidth = $bgColorWidth 118 | } 119 | $space = [Math]::Max(0, $colWidth - $t.Length) 120 | if ($n -gt 0) { 121 | & ${TerminalVelocity_setOutputStyle} -Foreground $colorScheme.$fg -Background $bgColor 122 | } else { 123 | & ${TerminalVelocity_setOutputStyle} -Foreground $colorScheme.Foreground -Background $bgColor 124 | } 125 | "$(' ' * [Math]::Floor($space /2))$t$(' ' * [Math]::Ceiling($space /2))" 126 | 127 | 128 | & ${TerminalVelocity_setOutputStyle} -Foreground $colorScheme.foreground -Background $colorScheme.background 129 | "|" 130 | & ${TerminalVelocity_clearOutputStyle} 131 | $n++ 132 | } 133 | ) -join '' 134 | $line.Trim() + ( & ${TerminalVelocity_clearOutputStyle}) 135 | #"$($fg)".PadRight($host.UI.RawUI.BufferSize.Width) 136 | } 137 | ) -join [Environment]::NewLine 138 | <# 139 | @( 140 | foreach ($fg in $colorScheme.psobject.properties) { 141 | if ($fg.Name -eq 'Name') { continue} 142 | . $setOutputStyle -Foreground $colorScheme.($fg.Name) 143 | "$($fg.Name)".PadRight($host.UI.RawUI.BufferSize.Width) 144 | } 145 | ) 146 | #> 147 | . ${TerminalVelocity_clearOutputStyle} 148 | ) -join '' 149 | return 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | -not $Host.ui.SupportsVirtualTerminal 160 | 161 | 162 | $_.Name + ([Environment]::NewLine * 2) + ($_ | Select-Object -Property * -ExcludeProperty Name | Format-List | Out-String) 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | WindowsTerminal.Profile 172 | 173 | WindowsTerminal.Profile 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | Name 191 | 192 | 193 | $_.Source -split '\.' | Select-Object -Last 1 194 | 195 | 196 | CommandLine 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | ${TerminalVelocity_setOutputStyle} 207 | 208 | 209 | 210 | 211 | 212 | <# 213 | .Synopsis 214 | Adds style to a format output 215 | .Description 216 | Adds style information to a format output, including: 217 | 218 | * ForegroundColor 219 | * BackgroundColor 220 | * Bold 221 | * Underline 222 | .Notes 223 | Stylized Output works in two contexts at present: 224 | * Rich consoles (Windows Terminal, PowerShell.exe, Pwsh.exe) (when $host.UI.SupportsVirtualTerminal) 225 | * Web pages (Based off the presence of a $Request variable, or when $host.UI.SupportsHTML (you must add this property to $host.UI)) 226 | 227 | IsFormatPart: true 228 | #> 229 | param( 230 | [string]$ForegroundColor, 231 | [string]$BackgroundColor, 232 | [switch]$Bold, 233 | [switch]$Underline, 234 | [switch]$Invert 235 | ) 236 | 237 | $canUseANSI = $host.UI.SupportsVirtualTerminal 238 | $canUseHTML = $Request -or $host.UI.SupportsHTML 239 | if (-not ($canUseANSI -or $canUseHTML)) { return } 240 | 241 | $knownStreams = @{ 242 | Output='';Error='BrightRed';Warning='BrightYellow'; 243 | Verbose='BrightCyan';Debug='Yellow';Progress='Cyan'; 244 | Success='BrightGreen';Failure='Red';Default=''} 245 | $standardColors = 'Black', 'Red', 'Green', 'Yellow', 'Blue','Magenta', 'Cyan', 'White' 246 | $brightColors = 'BrightBlack', 'BrightRed', 'BrightGreen', 'BrightYellow', 'BrightBlue','BrightMagenta', 'BrightCyan', 'BrightWhite' 247 | $n =0 248 | $cssClasses = @() 249 | $styleAttributes = 250 | @(:nextColor foreach ($hc in $ForegroundColor,$BackgroundColor) { 251 | $n++ 252 | if (-not $hc) { continue } 253 | if ($hc[0] -eq [char]0x1b) { 254 | if ($canUseANSI) { 255 | $hc; continue 256 | } 257 | } 258 | 259 | $ansiStartPoint = if ($n -eq 1) { 30 } else { 40 } 260 | if ($knownStreams.ContainsKey($hc)) { 261 | $i = $brightColors.IndexOf($knownStreams[$hc]) 262 | if ($canUseHTML) { 263 | $cssClasses += $hc 264 | } else { 265 | if ($i -ge 0 -and $canUseANSI) { 266 | '' + [char]0x1b + "[1;$($ansiStartPoint + $i)m" 267 | } else { 268 | $i = $standardColors.IndexOf($knownStreams[$hc]) 269 | if ($i -ge 0 -and $canUseANSI) { 270 | '' + [char]0x1b + "[1;$($ansiStartPoint + $i)m" 271 | } elseif ($i -le 0 -and $canUseANSI) { 272 | '' + [char]0x1b + "[$($ansistartpoint + 8):5m" 273 | } 274 | } 275 | } 276 | continue nextColor 277 | } 278 | elseif ($standardColors -contains $hc) { 279 | for ($i = 0; $i -lt $standardColors.Count;$i++) { 280 | if ($standardColors[$i] -eq $hc) { 281 | if ($canUseANSI -and -not $canUseHTML) { 282 | '' + [char]0x1b + "[$($ansiStartPoint + $i)m" 283 | } else { 284 | $cssClasses += $standardColors[$i] 285 | } 286 | continue nextColor 287 | } 288 | } 289 | } elseif ($brightColors -contains $hc) { 290 | for ($i = 0; $i -lt $brightColors.Count;$i++) { 291 | if ($brightColors[$i] -eq $hc) { 292 | if ($canUseANSI -and -not $canUseHTML) { 293 | '' + [char]0x1b + "[1;$($ansiStartPoint + $i)m" 294 | } else { 295 | $cssClasses += $standardColors[$i] 296 | } 297 | continue nextColor 298 | } 299 | } 300 | } 301 | 302 | 303 | if ($hc -and -not $hc.StartsWith('#')) { 304 | $placesToLook= 305 | @(if ($hc.Contains('.')) { 306 | $module, $setting = $hc -split '\.', 2 307 | $theModule = Get-Module $module 308 | $theModule.PrivateData.Color, 309 | $theModule.PrivateData.Colors, 310 | $theModule.PrivateData.Colour, 311 | $theModule.PrivateData.Colours, 312 | $theModule.PrivateData.EZOut, 313 | $global:PSColors, 314 | $global:PSColours 315 | } else { 316 | $setting = $hc 317 | $moduleColorSetting = $theModule.PrivateData.PSColors.$setting 318 | }) 319 | 320 | foreach ($place in $placesToLook) { 321 | if (-not $place) { continue } 322 | foreach ($propName in $setting -split '\.') { 323 | $place = $place.$propName 324 | if (-not $place) { break } 325 | } 326 | if ($place -and "$place".StartsWith('#') -and 4,7 -contains "$place".Length) { 327 | $hc = $place 328 | continue 329 | } 330 | } 331 | if (-not $hc.StartsWith -or -not $hc.StartsWith('#')) { 332 | continue 333 | } 334 | } 335 | $r,$g,$b = if ($hc.Length -eq 7) { 336 | [int]::Parse($hc[1..2]-join'', 'HexNumber') 337 | [int]::Parse($hc[3..4]-join '', 'HexNumber') 338 | [int]::Parse($hc[5..6] -join'', 'HexNumber') 339 | }elseif ($hc.Length -eq 4) { 340 | [int]::Parse($hc[1], 'HexNumber') * 16 341 | [int]::Parse($hc[2], 'HexNumber') * 16 342 | [int]::Parse($hc[3], 'HexNumber') * 16 343 | } 344 | 345 | if ($canUseHTML) { 346 | if ($n -eq 1) { "color:$hc" } 347 | elseif ($n -eq 2) { "background-color:$hc"} 348 | } 349 | elseif ($canUseANSI) { 350 | if ($n -eq 1) { [char]0x1b+"[38;2;$r;$g;${b}m" } 351 | elseif ($n -eq 2) { [char]0x1b+"[48;2;$r;$g;${b}m" } 352 | } 353 | 354 | }) 355 | 356 | 357 | if ($Bold) { 358 | $styleAttributes += 359 | if ($canUseHTML) { 360 | "font-weight:bold" 361 | } 362 | elseif ($canUseANSI) 363 | { 364 | [char]0x1b + "[1m" 365 | } 366 | } 367 | 368 | if ($Underline) { 369 | $styleAttributes += 370 | if ($canUseHTML) { 371 | "text-decoration:underline" 372 | } elseif ($canUseANSI) { 373 | [char]0x1b + "[4m" 374 | } 375 | } 376 | 377 | if ($Invert) { 378 | $styleAttributes += 379 | if ($canUseHTML) { 380 | "filter:invert(100%)" 381 | } elseif ($canUseANSI) { 382 | [char]0x1b + "[7m" 383 | } 384 | } 385 | 386 | if ($canUseHTML) { 387 | 388 | "<span$( 389 | if ($styleAttributes) { " style='$($styleAttributes -join ';')'"} 390 | )$( 391 | if ($cssClasses) { " class='$($cssClasses -join ' ')'"} 392 | )>" 393 | } elseif ($canUseANSI) { 394 | $styleAttributes -join '' 395 | } 396 | 397 | 398 | 399 | 400 | 401 | 402 | 403 | ${TerminalVelocity_clearOutputStyle} 404 | 405 | 406 | 407 | 408 | 409 | <# 410 | .Synopsis 411 | Clears the output style 412 | .Description 413 | Clears ANSI output style or closes the most recent span element. 414 | 415 | ANSI stylization can be toggled off individually (for instance, to stop applying an -Underline but leave the color unchanged) 416 | .Notes 417 | IsFormatPart: true 418 | #> 419 | param( 420 | # If set, will explicitly clear ANSI Bold 421 | [switch] 422 | $Bold, 423 | # If set, will explicitly clear ANSI Underline 424 | [switch] 425 | $Underline, 426 | # If set, will explicitly clear ANSI Invert 427 | [switch] 428 | $Invert, 429 | # If set, will explicitly clear ANSI Foreground Color 430 | [switch] 431 | $ForegroundColor, 432 | # If set, will explicitly clear ANSI Background Color 433 | [switch] 434 | $BackgroundColor 435 | ) 436 | @(if ($request -or $host.UI.SupportsHTML) { 437 | "</span>" 438 | } elseif ($Host.UI.SupportsVirtualTerminal) { 439 | if ($Underline) { 440 | [char]0x1b + "[24m" 441 | } 442 | if ($Bold) { 443 | [char]0x1b + "[21m" 444 | } 445 | if ($Invert) { 446 | [char]0x1b + '[27m' 447 | } 448 | if ($ForegroundColor) { 449 | [char]0x1b + '[39m' 450 | } 451 | if ($BackgroundColor) { 452 | [char]0x1b + '[49m' 453 | } 454 | 455 | if (-not ($Underline -or $Bold -or $Invert -or $ForegroundColor -or $BackgroundColor)) { 456 | [char]0x1b + '[0m' 457 | } 458 | 459 | }) -join '' 460 | 461 | 462 | 463 | 464 | 465 | 466 | 467 | 468 | -------------------------------------------------------------------------------- /Add-WTProfile.ps1: -------------------------------------------------------------------------------- 1 | function Add-WTProfile { 2 | <# 3 | .Synopsis 4 | Adds a new Windows Terminal profile 5 | .Description 6 | Adds a new Windows Terminal tab profile. 7 | .Link 8 | New-WTProfile 9 | .Example 10 | Add-WTProfile -Name kali-linux-pwsh -CommandLine 'wsl -d kali-linux -e pwsh' 11 | 12 | #> 13 | 14 | [OutputType('Nullable','WindowsTerminal.Profile')] 15 | [CmdletBinding(SupportsShouldProcess)] 16 | param( 17 | # Name of the profile. Displays in the dropdown menu. 18 | [Parameter(Mandatory,ValueFromPipelineByPropertyName)] 19 | [Alias('ProfileName')] 20 | [ComponentModel.DefaultBindingProperty("name")] 21 | [string] 22 | $Name, 23 | # [deprecated] Please use `opacity` instead. 24 | [Parameter(ValueFromPipelineByPropertyName)] 25 | [ComponentModel.DefaultBindingProperty('acrylicOpacity')] 26 | [double] 27 | $AcrylicOpacity, 28 | # 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. 29 | [Parameter(ValueFromPipelineByPropertyName)] 30 | [ComponentModel.DefaultBindingProperty('antialiasingMode')] 31 | [ValidateSet('grayscale','cleartype','aliased')] 32 | [string] 33 | $AntialiasingMode, 34 | # Sets the background color of the text. Overrides "background" from the color scheme. Uses hex color format: "#rrggbb". 35 | [Parameter(ValueFromPipelineByPropertyName)] 36 | [ComponentModel.DefaultBindingProperty('background')] 37 | [ValidatePattern('^#[A-Fa-f0-9]{3}(?:[A-Fa-f0-9]{3})?$')] 38 | [string] 39 | $Background, 40 | # Sets the appearance of the terminal when it is unfocused. 41 | [Parameter(ValueFromPipelineByPropertyName)] 42 | [ComponentModel.DefaultBindingProperty('unfocusedAppearance')] 43 | [PSObject] 44 | $UnfocusedAppearance, 45 | # Sets the font options of the terminal. 46 | [Parameter(ValueFromPipelineByPropertyName)] 47 | [ComponentModel.DefaultBindingProperty('font')] 48 | [PSObject] 49 | $Font, 50 | # Sets the file location of the image to draw over the window background. 51 | [Parameter(ValueFromPipelineByPropertyName)] 52 | [ComponentModel.DefaultBindingProperty('backgroundImage')] 53 | [ValidateSet('desktopWallpaper','')] 54 | $BackgroundImage, 55 | # Sets how the background image aligns to the boundaries of the window. Possible values: "center", "left", "top", "right", "bottom", "topLeft", "topRight", "bottomLeft", "bottomRight" 56 | [Parameter(ValueFromPipelineByPropertyName)] 57 | [ComponentModel.DefaultBindingProperty('backgroundImageAlignment')] 58 | [ValidateSet('bottom','bottomLeft','bottomRight','center','left','right','top','topLeft','topRight')] 59 | [string] 60 | $BackgroundImageAlignment, 61 | # Sets the transparency of the background image. Accepts floating point values from 0-1. 62 | [Parameter(ValueFromPipelineByPropertyName)] 63 | [ComponentModel.DefaultBindingProperty('backgroundImageOpacity')] 64 | [double] 65 | $BackgroundImageOpacity, 66 | # Sets how the background image is resized to fill the window. 67 | [Parameter(ValueFromPipelineByPropertyName)] 68 | [ComponentModel.DefaultBindingProperty('backgroundImageStretchMode')] 69 | [ValidateSet('fill','none','uniform','uniformToFill')] 70 | [string] 71 | $BackgroundImageStretchMode, 72 | # Controls what happens when the application emits a BEL character. When set to "all", the Terminal will play a sound, flash the taskbar icon (if the terminal window is not in focus) and flash the window. An array of specific behaviors can also be used. Supported array values include `audible`, `window` and `taskbar`. When set to "none", nothing will happen. 73 | [Parameter(ValueFromPipelineByPropertyName)] 74 | [ComponentModel.DefaultBindingProperty('bellStyle')] 75 | $BellStyle, 76 | # Sets the sound played when the application emits a BEL. When set to an array, the terminal will pick one of those sounds at random. 77 | [Parameter(ValueFromPipelineByPropertyName)] 78 | [ComponentModel.DefaultBindingProperty('bellSound')] 79 | $BellSound, 80 | <# 81 | Sets how the profile reacts to termination or failure to launch. Possible values: 82 | -"graceful" (close when exit is typed or the process exits normally) 83 | -"always" (always close) 84 | -"automatic" (behave as "graceful" only for processes launched by terminal, behave as "always" otherwise) 85 | -"never" (never close). 86 | true and false are accepted as synonyms for "graceful" and "never" respectively. 87 | #> 88 | [Parameter(ValueFromPipelineByPropertyName)] 89 | [ComponentModel.DefaultBindingProperty('closeOnExit')] 90 | $CloseOnExit, 91 | # Name of the terminal color scheme to use. Color schemes are defined under "schemes". 92 | [Parameter(ValueFromPipelineByPropertyName)] 93 | [ComponentModel.DefaultBindingProperty('colorScheme')] 94 | [string] 95 | $ColorScheme, 96 | # Executable used in the profile. 97 | [Parameter(ValueFromPipelineByPropertyName)] 98 | [ComponentModel.DefaultBindingProperty('commandline')] 99 | [string] 100 | $Commandline, 101 | # Sets the color of the cursor. Overrides the cursor color from the color scheme. Uses hex color format: "#rrggbb". 102 | [Parameter(ValueFromPipelineByPropertyName)] 103 | [ComponentModel.DefaultBindingProperty('cursorColor')] 104 | [ValidatePattern('(?>^\s{0}$|^#[A-Fa-f0-9]{3}(?:[A-Fa-f0-9]{3})?$)')] 105 | [string] 106 | $CursorColor, 107 | # Sets the percentage height of the cursor starting from the bottom. Only works when cursorShape is set to "vintage". Accepts values from 1-100. 108 | [Parameter(ValueFromPipelineByPropertyName)] 109 | [ComponentModel.DefaultBindingProperty('cursorHeight')] 110 | [int] 111 | $CursorHeight, 112 | <# 113 | Sets the shape of the cursor. Possible values: 114 | -"bar" ( ┃, default ) 115 | -"doubleUnderscore" ( ‗ ) 116 | -"emptyBox" ( ▯ ) 117 | -"filledBox" ( █ ) 118 | -"underscore" ( ▁ ) 119 | -"vintage" ( ▃ ) 120 | #> 121 | [Parameter(ValueFromPipelineByPropertyName)] 122 | [ComponentModel.DefaultBindingProperty('cursorShape')] 123 | [ValidateSet('bar','doubleUnderscore','emptyBox','filledBox','underscore','vintage')] 124 | [string] 125 | $CursorShape, 126 | # When true, this profile should always open in an elevated context. If the window isn't running as an Administrator, then a new elevated window will be created. 127 | [Parameter(ValueFromPipelineByPropertyName)] 128 | [ComponentModel.DefaultBindingProperty('elevate')] 129 | [switch] 130 | $Elevate, 131 | # When set to true, directs the PTY for this connection to use pass-through mode instead of the original Conhost PTY simulation engine. This is an experimental feature, and its continued existence is not guaranteed. 132 | [Parameter(ValueFromPipelineByPropertyName)] 133 | [ComponentModel.DefaultBindingProperty('experimental.connection.passthroughMode')] 134 | [switch] 135 | $ConnectionPassthroughMode, 136 | # When set to true, enable retro terminal effects. This is an experimental feature, and its continued existence is not guaranteed. 137 | [Parameter(ValueFromPipelineByPropertyName)] 138 | [ComponentModel.DefaultBindingProperty('experimental.retroTerminalEffect')] 139 | [switch] 140 | $RetroTerminalEffect, 141 | # Use to set a path to a pixel shader to use with the Terminal. Overrides `experimental.retroTerminalEffect`. This is an experimental feature, and its continued existence is not guaranteed. 142 | [Parameter(ValueFromPipelineByPropertyName)] 143 | [ComponentModel.DefaultBindingProperty('experimental.pixelShaderPath')] 144 | [string] 145 | $PixelShaderPath, 146 | # Enable using the experimental new rendering engine for this profile. This is an experimental feature, and its continued existence is not guaranteed. 147 | [Parameter(ValueFromPipelineByPropertyName)] 148 | [ComponentModel.DefaultBindingProperty('experimental.useAtlasEngine')] 149 | [switch] 150 | $UseAtlasEngine, 151 | # [deprecated] Define 'face' within the 'font' object instead. 152 | [Parameter(ValueFromPipelineByPropertyName)] 153 | [ComponentModel.DefaultBindingProperty('fontFace')] 154 | [string] 155 | $FontFace, 156 | # [deprecated] Define 'size' within the 'font' object instead. 157 | [Parameter(ValueFromPipelineByPropertyName)] 158 | [ComponentModel.DefaultBindingProperty('fontSize')] 159 | [int] 160 | $FontSize, 161 | # [deprecated] Define 'weight' within the 'font' object instead. 162 | [Parameter(ValueFromPipelineByPropertyName)] 163 | [ComponentModel.DefaultBindingProperty('fontWeight')] 164 | $FontWeight, 165 | # Controls how 'intense' text is rendered. Values are "bold", "bright", "all" and "none" 166 | [Parameter(ValueFromPipelineByPropertyName)] 167 | [ComponentModel.DefaultBindingProperty('intenseTextStyle')] 168 | [ValidateSet('none','bold','bright','all')] 169 | [string] 170 | $IntenseTextStyle, 171 | # Sets the text color. Overrides "foreground" from the color scheme. Uses hex color format: "#rrggbb". 172 | [Parameter(ValueFromPipelineByPropertyName)] 173 | [ComponentModel.DefaultBindingProperty('foreground')] 174 | [ValidatePattern('^#[A-Fa-f0-9]{3}(?:[A-Fa-f0-9]{3})?$')] 175 | [string] 176 | $Foreground, 177 | # Unique identifier of the profile. Written in registry format: "{00000000-0000-0000-0000-000000000000}". 178 | [Parameter(ValueFromPipelineByPropertyName)] 179 | [ComponentModel.DefaultBindingProperty('guid')] 180 | [ValidatePattern('^\{[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}\}$')] 181 | [string] 182 | $Guid, 183 | # 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. 184 | [Parameter(ValueFromPipelineByPropertyName)] 185 | [ComponentModel.DefaultBindingProperty('hidden')] 186 | [switch] 187 | $Hidden, 188 | # The number of lines above the ones displayed in the window you can scroll back to. 189 | [Parameter(ValueFromPipelineByPropertyName)] 190 | [ComponentModel.DefaultBindingProperty('historySize')] 191 | [int] 192 | $HistorySize, 193 | # 194 | [Parameter(ValueFromPipelineByPropertyName)] 195 | [ComponentModel.DefaultBindingProperty('icon')] 196 | [string] 197 | $Icon, 198 | # Sets the opacity of the window for the profile. Accepts values from 0-100. Defaults to 50 when useAcrylic is set to true. 199 | [Parameter(ValueFromPipelineByPropertyName)] 200 | [ComponentModel.DefaultBindingProperty('opacity')] 201 | [double] 202 | $Opacity, 203 | <# 204 | Sets the padding around the text within the window. Can have three different formats: 205 | -"#" sets the same padding for all sides 206 | -"#, #" sets the same padding for left-right and top-bottom 207 | -"#, #, #, #" sets the padding individually for left, top, right, and bottom. 208 | #> 209 | [Parameter(ValueFromPipelineByPropertyName)] 210 | [ComponentModel.DefaultBindingProperty('padding')] 211 | $Padding, 212 | # When set to true, we will (when necessary) adjust the foreground color to make it more visible, based on the background color. 213 | [Parameter(ValueFromPipelineByPropertyName)] 214 | [ComponentModel.DefaultBindingProperty('adjustIndistinguishableColors')] 215 | [switch] 216 | $AdjustIndistinguishableColors, 217 | # Defines the visibility of the scrollbar. 218 | [Parameter(ValueFromPipelineByPropertyName)] 219 | [ComponentModel.DefaultBindingProperty('scrollbarState')] 220 | [ValidateSet('visible','hidden')] 221 | [string] 222 | $ScrollbarState, 223 | # Sets the background color of selected text. Overrides selectionBackground set in the color scheme. Uses hex color format: "#rrggbb". 224 | [Parameter(ValueFromPipelineByPropertyName)] 225 | [ComponentModel.DefaultBindingProperty('selectionBackground')] 226 | [ValidatePattern('(?>^\s{0}$|^#[A-Fa-f0-9]{3}(?:[A-Fa-f0-9]{3})?$)')] 227 | [string] 228 | $SelectionBackground, 229 | # 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. 230 | [Parameter(ValueFromPipelineByPropertyName)] 231 | [ComponentModel.DefaultBindingProperty('snapOnInput')] 232 | [switch] 233 | $SnapOnInput, 234 | # By default Windows treats Ctrl+Alt as an alias for AltGr. When altGrAliasing is set to false, this behavior will be disabled. 235 | [Parameter(ValueFromPipelineByPropertyName)] 236 | [ComponentModel.DefaultBindingProperty('altGrAliasing')] 237 | [switch] 238 | $AltGrAliasing, 239 | # Stores the name of the profile generator that originated this profile. 240 | [Parameter(ValueFromPipelineByPropertyName)] 241 | [ComponentModel.DefaultBindingProperty('source')] 242 | [string] 243 | $Source, 244 | # The directory the shell starts in when it is loaded. 245 | [Parameter(ValueFromPipelineByPropertyName)] 246 | [ComponentModel.DefaultBindingProperty('startingDirectory')] 247 | [string] 248 | $StartingDirectory, 249 | # 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. 250 | [Parameter(ValueFromPipelineByPropertyName)] 251 | [ComponentModel.DefaultBindingProperty('suppressApplicationTitle')] 252 | [switch] 253 | $SuppressApplicationTitle, 254 | # Sets the color of the profile's tab. Using the tab color picker will override this color. 255 | [Parameter(ValueFromPipelineByPropertyName)] 256 | [ComponentModel.DefaultBindingProperty('tabColor')] 257 | [ValidatePattern('^#[A-Fa-f0-9]{3}(?:[A-Fa-f0-9]{3})?$')] 258 | [string] 259 | $TabColor, 260 | # 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. 261 | [Parameter(ValueFromPipelineByPropertyName)] 262 | [ComponentModel.DefaultBindingProperty('tabTitle')] 263 | [string] 264 | $TabTitle, 265 | # When set to true, the window will have an acrylic material background. When set to false, the window will have a plain, untextured background. 266 | [Parameter(ValueFromPipelineByPropertyName)] 267 | [ComponentModel.DefaultBindingProperty('useAcrylic')] 268 | [switch] 269 | $UseAcrylic 270 | ) 271 | begin { 272 | $myParameters = $MyInvocation.MyCommand.Parameters.Values 273 | $myProfileProperties = :nextParam foreach ($param in $myParameters) { 274 | foreach ($attr in $param.Attributes) { 275 | if ($attr -is [ComponentModel.DefaultBindingPropertyAttribute]) { 276 | $param 277 | continue nextParam 278 | } 279 | } 280 | } 281 | 282 | } 283 | process { 284 | $myParameters = [Ordered]@{} + $PSBoundParameters 285 | if (-not $myParameters["Guid"]) { 286 | $myParameters["Guid"] = "{$([GUID]::NewGuid())}" 287 | } 288 | $myProfileParameters = [Ordered]@{} 289 | foreach ($myProfileProperty in $myProfileProperties) { 290 | if ($myParameters.Contains($myProfileProperty.Name)) { 291 | $propertyName = foreach ($attr in $myProfileProperty.Attributes) { 292 | if ($attr -is [System.ComponentModel.DefaultBindingPropertyAttribute]) { 293 | $attr.Name 294 | break 295 | } 296 | } 297 | $paramValue = $myParameters[$myProfileProperty.Name] 298 | foreach ($attr in $myProfileProperty.Attributes) { 299 | if ($attr -is [ComponentModel.AmbientValueAttribute] -and $attr.Value -is [scriptblock]) { 300 | $_ = $this = $PSItem = $paramValue 301 | $paramValue = & $attr.Value 302 | break 303 | } 304 | if ($attr -is [ValidateSet]) { 305 | foreach ($validValue in $attr.Validvalues) { 306 | if ($paramValue -eq $validValue) { 307 | $paramValue = $validValue 308 | } 309 | } 310 | } 311 | } 312 | if ($paramValue -is [switch]) { 313 | $paramValue = $paramValue -as [bool] 314 | } 315 | $myProfileParameters[$propertyName] = $paramValue 316 | } 317 | } 318 | #region Create Profile Object 319 | 320 | $newProfile = [PSCustomObject]$myProfileParameters 321 | #endregion Profile Object 322 | #region Update Windows Terminal Profile 323 | $wtProfile = Get-WTProfile -Global # Get our profile 324 | $wtProfile.profiles | # Add out new profile to the list, 325 | Add-Member NoteProperty list @( 326 | foreach ($_ in $wtProfile.profiles.list) { 327 | if ($guid -ne $_.Guid -and $name -ne $_.Name) # and don't forget all of the other ones. 328 | { 329 | $_ 330 | } 331 | } 332 | $newProfile 333 | ) -Force 334 | $wtPath = $wtProfile.Path 335 | if ($PSCmdlet.ShouldProcess("Add Profile $Name to $wtPath")) # If we ShouldProcess 336 | { 337 | $wtProfile.psobject.properties.Remove('Path') 338 | $wtProfile | # turn the profile 339 | ConvertTo-Json -Depth 100 | # back into JSON 340 | Set-Content -Path $wtPath -Encoding UTF8 # and write it to disk. 341 | $wtProfile.psobject.properties.add([PSNoteProperty]::new('Path', $wtPath)) 342 | } 343 | elseif ($WhatIfPreference) # if we wanted to know -WhatIf 344 | { 345 | return $wtProfile # return the JSON object 346 | } 347 | #endregion Update Windows Terminal Profile 348 | 349 | } 350 | } 351 | 352 | -------------------------------------------------------------------------------- /docs/New-WTProfile.md: -------------------------------------------------------------------------------- 1 | New-WTProfile 2 | ------------- 3 | ### Synopsis 4 | Creates a new Windows Terminal profile 5 | 6 | --- 7 | ### Description 8 | 9 | Creates a new Windows Terminal tab profile. 10 | 11 | --- 12 | ### Related Links 13 | * [Add-WTProfile](Add-WTProfile.md) 14 | 15 | 16 | 17 | --- 18 | ### Examples 19 | #### EXAMPLE 1 20 | ```PowerShell 21 | New-WTProfile -Name DOS -CommandLine cmd 22 | ``` 23 | 24 | #### EXAMPLE 2 25 | ```PowerShell 26 | New-WTProfile -Name kali-linux-pwsh -CommandLine 'wsl -d kali-linux -e pwsh' 27 | ``` 28 | 29 | #### EXAMPLE 3 30 | ```PowerShell 31 | New-WTProfile -Default 32 | ``` 33 | 34 | --- 35 | ### Parameters 36 | #### **AcrylicOpacity** 37 | 38 | [deprecated] Please use `opacity` instead. 39 | 40 | 41 | 42 | > **Type**: ```[Double]``` 43 | 44 | > **Required**: false 45 | 46 | > **Position**: 1 47 | 48 | > **PipelineInput**:true (ByPropertyName) 49 | 50 | 51 | 52 | --- 53 | #### **AntialiasingMode** 54 | 55 | 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. 56 | 57 | 58 | 59 | Valid Values: 60 | 61 | * grayscale 62 | * cleartype 63 | * aliased 64 | 65 | 66 | 67 | > **Type**: ```[String]``` 68 | 69 | > **Required**: false 70 | 71 | > **Position**: 2 72 | 73 | > **PipelineInput**:true (ByPropertyName) 74 | 75 | 76 | 77 | --- 78 | #### **Background** 79 | 80 | Sets the background color of the text. Overrides "background" from the color scheme. Uses hex color format: "#rrggbb". 81 | 82 | 83 | 84 | > **Type**: ```[String]``` 85 | 86 | > **Required**: false 87 | 88 | > **Position**: 3 89 | 90 | > **PipelineInput**:true (ByPropertyName) 91 | 92 | 93 | 94 | --- 95 | #### **UnfocusedAppearance** 96 | 97 | Sets the appearance of the terminal when it is unfocused. 98 | 99 | 100 | 101 | > **Type**: ```[PSObject]``` 102 | 103 | > **Required**: false 104 | 105 | > **Position**: 4 106 | 107 | > **PipelineInput**:true (ByPropertyName) 108 | 109 | 110 | 111 | --- 112 | #### **Font** 113 | 114 | Sets the font options of the terminal. 115 | 116 | 117 | 118 | > **Type**: ```[PSObject]``` 119 | 120 | > **Required**: false 121 | 122 | > **Position**: 5 123 | 124 | > **PipelineInput**:true (ByPropertyName) 125 | 126 | 127 | 128 | --- 129 | #### **BackgroundImage** 130 | 131 | Sets the file location of the image to draw over the window background. 132 | 133 | 134 | 135 | Valid Values: 136 | 137 | * desktopWallpaper 138 | * 139 | 140 | 141 | 142 | > **Type**: ```[Object]``` 143 | 144 | > **Required**: false 145 | 146 | > **Position**: 6 147 | 148 | > **PipelineInput**:true (ByPropertyName) 149 | 150 | 151 | 152 | --- 153 | #### **BackgroundImageAlignment** 154 | 155 | Sets how the background image aligns to the boundaries of the window. Possible values: "center", "left", "top", "right", "bottom", "topLeft", "topRight", "bottomLeft", "bottomRight" 156 | 157 | 158 | 159 | Valid Values: 160 | 161 | * bottom 162 | * bottomLeft 163 | * bottomRight 164 | * center 165 | * left 166 | * right 167 | * top 168 | * topLeft 169 | * topRight 170 | 171 | 172 | 173 | > **Type**: ```[String]``` 174 | 175 | > **Required**: false 176 | 177 | > **Position**: 7 178 | 179 | > **PipelineInput**:true (ByPropertyName) 180 | 181 | 182 | 183 | --- 184 | #### **BackgroundImageOpacity** 185 | 186 | Sets the transparency of the background image. Accepts floating point values from 0-1. 187 | 188 | 189 | 190 | > **Type**: ```[Double]``` 191 | 192 | > **Required**: false 193 | 194 | > **Position**: 8 195 | 196 | > **PipelineInput**:true (ByPropertyName) 197 | 198 | 199 | 200 | --- 201 | #### **BackgroundImageStretchMode** 202 | 203 | Sets how the background image is resized to fill the window. 204 | 205 | 206 | 207 | Valid Values: 208 | 209 | * fill 210 | * none 211 | * uniform 212 | * uniformToFill 213 | 214 | 215 | 216 | > **Type**: ```[String]``` 217 | 218 | > **Required**: false 219 | 220 | > **Position**: 9 221 | 222 | > **PipelineInput**:true (ByPropertyName) 223 | 224 | 225 | 226 | --- 227 | #### **BellStyle** 228 | 229 | Controls what happens when the application emits a BEL character. When set to "all", the Terminal will play a sound, flash the taskbar icon (if the terminal window is not in focus) and flash the window. An array of specific behaviors can also be used. Supported array values include `audible`, `window` and `taskbar`. When set to "none", nothing will happen. 230 | 231 | 232 | 233 | > **Type**: ```[Object]``` 234 | 235 | > **Required**: false 236 | 237 | > **Position**: 10 238 | 239 | > **PipelineInput**:true (ByPropertyName) 240 | 241 | 242 | 243 | --- 244 | #### **BellSound** 245 | 246 | Sets the sound played when the application emits a BEL. When set to an array, the terminal will pick one of those sounds at random. 247 | 248 | 249 | 250 | > **Type**: ```[Object]``` 251 | 252 | > **Required**: false 253 | 254 | > **Position**: 11 255 | 256 | > **PipelineInput**:true (ByPropertyName) 257 | 258 | 259 | 260 | --- 261 | #### **CloseOnExit** 262 | 263 | Sets how the profile reacts to termination or failure to launch. Possible values: 264 | -"graceful" (close when exit is typed or the process exits normally) 265 | -"always" (always close) 266 | -"automatic" (behave as "graceful" only for processes launched by terminal, behave as "always" otherwise) 267 | -"never" (never close). 268 | true and false are accepted as synonyms for "graceful" and "never" respectively. 269 | 270 | 271 | 272 | > **Type**: ```[Object]``` 273 | 274 | > **Required**: false 275 | 276 | > **Position**: 12 277 | 278 | > **PipelineInput**:true (ByPropertyName) 279 | 280 | 281 | 282 | --- 283 | #### **ColorScheme** 284 | 285 | Name of the terminal color scheme to use. Color schemes are defined under "schemes". 286 | 287 | 288 | 289 | > **Type**: ```[String]``` 290 | 291 | > **Required**: false 292 | 293 | > **Position**: 13 294 | 295 | > **PipelineInput**:true (ByPropertyName) 296 | 297 | 298 | 299 | --- 300 | #### **Commandline** 301 | 302 | Executable used in the profile. 303 | 304 | 305 | 306 | > **Type**: ```[String]``` 307 | 308 | > **Required**: false 309 | 310 | > **Position**: 14 311 | 312 | > **PipelineInput**:true (ByPropertyName) 313 | 314 | 315 | 316 | --- 317 | #### **CursorColor** 318 | 319 | Sets the color of the cursor. Overrides the cursor color from the color scheme. Uses hex color format: "#rrggbb". 320 | 321 | 322 | 323 | > **Type**: ```[String]``` 324 | 325 | > **Required**: false 326 | 327 | > **Position**: 15 328 | 329 | > **PipelineInput**:true (ByPropertyName) 330 | 331 | 332 | 333 | --- 334 | #### **CursorHeight** 335 | 336 | Sets the percentage height of the cursor starting from the bottom. Only works when cursorShape is set to "vintage". Accepts values from 1-100. 337 | 338 | 339 | 340 | > **Type**: ```[Int32]``` 341 | 342 | > **Required**: false 343 | 344 | > **Position**: 16 345 | 346 | > **PipelineInput**:true (ByPropertyName) 347 | 348 | 349 | 350 | --- 351 | #### **CursorShape** 352 | 353 | Sets the shape of the cursor. Possible values: 354 | -"bar" ( ┃, default ) 355 | -"doubleUnderscore" ( ‗ ) 356 | -"emptyBox" ( ▯ ) 357 | -"filledBox" ( █ ) 358 | -"underscore" ( ▁ ) 359 | -"vintage" ( ▃ ) 360 | 361 | 362 | 363 | Valid Values: 364 | 365 | * bar 366 | * doubleUnderscore 367 | * emptyBox 368 | * filledBox 369 | * underscore 370 | * vintage 371 | 372 | 373 | 374 | > **Type**: ```[String]``` 375 | 376 | > **Required**: false 377 | 378 | > **Position**: 17 379 | 380 | > **PipelineInput**:true (ByPropertyName) 381 | 382 | 383 | 384 | --- 385 | #### **Elevate** 386 | 387 | When true, this profile should always open in an elevated context. If the window isn't running as an Administrator, then a new elevated window will be created. 388 | 389 | 390 | 391 | > **Type**: ```[Switch]``` 392 | 393 | > **Required**: false 394 | 395 | > **Position**: named 396 | 397 | > **PipelineInput**:true (ByPropertyName) 398 | 399 | 400 | 401 | --- 402 | #### **ConnectionPassthroughMode** 403 | 404 | When set to true, directs the PTY for this connection to use pass-through mode instead of the original Conhost PTY simulation engine. This is an experimental feature, and its continued existence is not guaranteed. 405 | 406 | 407 | 408 | > **Type**: ```[Switch]``` 409 | 410 | > **Required**: false 411 | 412 | > **Position**: named 413 | 414 | > **PipelineInput**:true (ByPropertyName) 415 | 416 | 417 | 418 | --- 419 | #### **RetroTerminalEffect** 420 | 421 | When set to true, enable retro terminal effects. This is an experimental feature, and its continued existence is not guaranteed. 422 | 423 | 424 | 425 | > **Type**: ```[Switch]``` 426 | 427 | > **Required**: false 428 | 429 | > **Position**: named 430 | 431 | > **PipelineInput**:true (ByPropertyName) 432 | 433 | 434 | 435 | --- 436 | #### **PixelShaderPath** 437 | 438 | Use to set a path to a pixel shader to use with the Terminal. Overrides `experimental.retroTerminalEffect`. This is an experimental feature, and its continued existence is not guaranteed. 439 | 440 | 441 | 442 | > **Type**: ```[String]``` 443 | 444 | > **Required**: false 445 | 446 | > **Position**: 18 447 | 448 | > **PipelineInput**:true (ByPropertyName) 449 | 450 | 451 | 452 | --- 453 | #### **UseAtlasEngine** 454 | 455 | Enable using the experimental new rendering engine for this profile. This is an experimental feature, and its continued existence is not guaranteed. 456 | 457 | 458 | 459 | > **Type**: ```[Switch]``` 460 | 461 | > **Required**: false 462 | 463 | > **Position**: named 464 | 465 | > **PipelineInput**:true (ByPropertyName) 466 | 467 | 468 | 469 | --- 470 | #### **FontFace** 471 | 472 | [deprecated] Define 'face' within the 'font' object instead. 473 | 474 | 475 | 476 | > **Type**: ```[String]``` 477 | 478 | > **Required**: false 479 | 480 | > **Position**: 19 481 | 482 | > **PipelineInput**:true (ByPropertyName) 483 | 484 | 485 | 486 | --- 487 | #### **FontSize** 488 | 489 | [deprecated] Define 'size' within the 'font' object instead. 490 | 491 | 492 | 493 | > **Type**: ```[Int32]``` 494 | 495 | > **Required**: false 496 | 497 | > **Position**: 20 498 | 499 | > **PipelineInput**:true (ByPropertyName) 500 | 501 | 502 | 503 | --- 504 | #### **FontWeight** 505 | 506 | [deprecated] Define 'weight' within the 'font' object instead. 507 | 508 | 509 | 510 | > **Type**: ```[Object]``` 511 | 512 | > **Required**: false 513 | 514 | > **Position**: 21 515 | 516 | > **PipelineInput**:true (ByPropertyName) 517 | 518 | 519 | 520 | --- 521 | #### **IntenseTextStyle** 522 | 523 | Controls how 'intense' text is rendered. Values are "bold", "bright", "all" and "none" 524 | 525 | 526 | 527 | Valid Values: 528 | 529 | * none 530 | * bold 531 | * bright 532 | * all 533 | 534 | 535 | 536 | > **Type**: ```[String]``` 537 | 538 | > **Required**: false 539 | 540 | > **Position**: 22 541 | 542 | > **PipelineInput**:true (ByPropertyName) 543 | 544 | 545 | 546 | --- 547 | #### **Foreground** 548 | 549 | Sets the text color. Overrides "foreground" from the color scheme. Uses hex color format: "#rrggbb". 550 | 551 | 552 | 553 | > **Type**: ```[String]``` 554 | 555 | > **Required**: false 556 | 557 | > **Position**: 23 558 | 559 | > **PipelineInput**:true (ByPropertyName) 560 | 561 | 562 | 563 | --- 564 | #### **Guid** 565 | 566 | Unique identifier of the profile. Written in registry format: "{00000000-0000-0000-0000-000000000000}". 567 | 568 | 569 | 570 | > **Type**: ```[String]``` 571 | 572 | > **Required**: false 573 | 574 | > **Position**: 24 575 | 576 | > **PipelineInput**:true (ByPropertyName) 577 | 578 | 579 | 580 | --- 581 | #### **Hidden** 582 | 583 | 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. 584 | 585 | 586 | 587 | > **Type**: ```[Switch]``` 588 | 589 | > **Required**: false 590 | 591 | > **Position**: named 592 | 593 | > **PipelineInput**:true (ByPropertyName) 594 | 595 | 596 | 597 | --- 598 | #### **HistorySize** 599 | 600 | The number of lines above the ones displayed in the window you can scroll back to. 601 | 602 | 603 | 604 | > **Type**: ```[Int32]``` 605 | 606 | > **Required**: false 607 | 608 | > **Position**: 25 609 | 610 | > **PipelineInput**:true (ByPropertyName) 611 | 612 | 613 | 614 | --- 615 | #### **Icon** 616 | 617 | > **Type**: ```[String]``` 618 | 619 | > **Required**: false 620 | 621 | > **Position**: 26 622 | 623 | > **PipelineInput**:true (ByPropertyName) 624 | 625 | 626 | 627 | --- 628 | #### **Name** 629 | 630 | Name of the profile. Displays in the dropdown menu. 631 | 632 | 633 | 634 | > **Type**: ```[String]``` 635 | 636 | > **Required**: false 637 | 638 | > **Position**: 27 639 | 640 | > **PipelineInput**:true (ByPropertyName) 641 | 642 | 643 | 644 | --- 645 | #### **Opacity** 646 | 647 | Sets the opacity of the window for the profile. Accepts values from 0-100. Defaults to 50 when useAcrylic is set to true. 648 | 649 | 650 | 651 | > **Type**: ```[Double]``` 652 | 653 | > **Required**: false 654 | 655 | > **Position**: 28 656 | 657 | > **PipelineInput**:true (ByPropertyName) 658 | 659 | 660 | 661 | --- 662 | #### **Padding** 663 | 664 | Sets the padding around the text within the window. Can have three different formats: 665 | -"#" sets the same padding for all sides 666 | -"#, #" sets the same padding for left-right and top-bottom 667 | -"#, #, #, #" sets the padding individually for left, top, right, and bottom. 668 | 669 | 670 | 671 | > **Type**: ```[Object]``` 672 | 673 | > **Required**: false 674 | 675 | > **Position**: 29 676 | 677 | > **PipelineInput**:true (ByPropertyName) 678 | 679 | 680 | 681 | --- 682 | #### **AdjustIndistinguishableColors** 683 | 684 | When set to true, we will (when necessary) adjust the foreground color to make it more visible, based on the background color. 685 | 686 | 687 | 688 | > **Type**: ```[Switch]``` 689 | 690 | > **Required**: false 691 | 692 | > **Position**: named 693 | 694 | > **PipelineInput**:true (ByPropertyName) 695 | 696 | 697 | 698 | --- 699 | #### **ScrollbarState** 700 | 701 | Defines the visibility of the scrollbar. 702 | 703 | 704 | 705 | Valid Values: 706 | 707 | * visible 708 | * hidden 709 | 710 | 711 | 712 | > **Type**: ```[String]``` 713 | 714 | > **Required**: false 715 | 716 | > **Position**: 30 717 | 718 | > **PipelineInput**:true (ByPropertyName) 719 | 720 | 721 | 722 | --- 723 | #### **SelectionBackground** 724 | 725 | Sets the background color of selected text. Overrides selectionBackground set in the color scheme. Uses hex color format: "#rrggbb". 726 | 727 | 728 | 729 | > **Type**: ```[String]``` 730 | 731 | > **Required**: false 732 | 733 | > **Position**: 31 734 | 735 | > **PipelineInput**:true (ByPropertyName) 736 | 737 | 738 | 739 | --- 740 | #### **SnapOnInput** 741 | 742 | 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. 743 | 744 | 745 | 746 | > **Type**: ```[Switch]``` 747 | 748 | > **Required**: false 749 | 750 | > **Position**: named 751 | 752 | > **PipelineInput**:true (ByPropertyName) 753 | 754 | 755 | 756 | --- 757 | #### **AltGrAliasing** 758 | 759 | By default Windows treats Ctrl+Alt as an alias for AltGr. When altGrAliasing is set to false, this behavior will be disabled. 760 | 761 | 762 | 763 | > **Type**: ```[Switch]``` 764 | 765 | > **Required**: false 766 | 767 | > **Position**: named 768 | 769 | > **PipelineInput**:true (ByPropertyName) 770 | 771 | 772 | 773 | --- 774 | #### **Source** 775 | 776 | Stores the name of the profile generator that originated this profile. 777 | 778 | 779 | 780 | > **Type**: ```[String]``` 781 | 782 | > **Required**: false 783 | 784 | > **Position**: 32 785 | 786 | > **PipelineInput**:true (ByPropertyName) 787 | 788 | 789 | 790 | --- 791 | #### **StartingDirectory** 792 | 793 | The directory the shell starts in when it is loaded. 794 | 795 | 796 | 797 | > **Type**: ```[String]``` 798 | 799 | > **Required**: false 800 | 801 | > **Position**: 33 802 | 803 | > **PipelineInput**:true (ByPropertyName) 804 | 805 | 806 | 807 | --- 808 | #### **SuppressApplicationTitle** 809 | 810 | 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. 811 | 812 | 813 | 814 | > **Type**: ```[Switch]``` 815 | 816 | > **Required**: false 817 | 818 | > **Position**: named 819 | 820 | > **PipelineInput**:true (ByPropertyName) 821 | 822 | 823 | 824 | --- 825 | #### **TabColor** 826 | 827 | Sets the color of the profile's tab. Using the tab color picker will override this color. 828 | 829 | 830 | 831 | > **Type**: ```[String]``` 832 | 833 | > **Required**: false 834 | 835 | > **Position**: 34 836 | 837 | > **PipelineInput**:true (ByPropertyName) 838 | 839 | 840 | 841 | --- 842 | #### **TabTitle** 843 | 844 | 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. 845 | 846 | 847 | 848 | > **Type**: ```[String]``` 849 | 850 | > **Required**: false 851 | 852 | > **Position**: 35 853 | 854 | > **PipelineInput**:true (ByPropertyName) 855 | 856 | 857 | 858 | --- 859 | #### **UseAcrylic** 860 | 861 | When set to true, the window will have an acrylic material background. When set to false, the window will have a plain, untextured background. 862 | 863 | 864 | 865 | > **Type**: ```[Switch]``` 866 | 867 | > **Required**: false 868 | 869 | > **Position**: named 870 | 871 | > **PipelineInput**:true (ByPropertyName) 872 | 873 | 874 | 875 | --- 876 | ### Outputs 877 | * WindowsTerminal.Profile 878 | 879 | 880 | 881 | 882 | --- 883 | ### Syntax 884 | ```PowerShell 885 | New-WTProfile [[-AcrylicOpacity] ] [[-AntialiasingMode] ] [[-Background] ] [[-UnfocusedAppearance] ] [[-Font] ] [[-BackgroundImage] ] [[-BackgroundImageAlignment] ] [[-BackgroundImageOpacity] ] [[-BackgroundImageStretchMode] ] [[-BellStyle] ] [[-BellSound] ] [[-CloseOnExit] ] [[-ColorScheme] ] [[-Commandline] ] [[-CursorColor] ] [[-CursorHeight] ] [[-CursorShape] ] [-Elevate] [-ConnectionPassthroughMode] [-RetroTerminalEffect] [[-PixelShaderPath] ] [-UseAtlasEngine] [[-FontFace] ] [[-FontSize] ] [[-FontWeight] ] [[-IntenseTextStyle] ] [[-Foreground] ] [[-Guid] ] [-Hidden] [[-HistorySize] ] [[-Icon] ] [[-Name] ] [[-Opacity] ] [[-Padding] ] [-AdjustIndistinguishableColors] [[-ScrollbarState] ] [[-SelectionBackground] ] [-SnapOnInput] [-AltGrAliasing] [[-Source] ] [[-StartingDirectory] ] [-SuppressApplicationTitle] [[-TabColor] ] [[-TabTitle] ] [-UseAcrylic] [] 886 | ``` 887 | --- 888 | --------------------------------------------------------------------------------