Last active
October 27, 2016 16:01
-
-
Save mhudasch/5ff826f2e3c0b02c101a296b4e3671dc to your computer and use it in GitHub Desktop.
Test of Input mask for PS
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #requires -version 5 | |
| Set-StrictMode -Version Latest | |
| Function Read-Input { | |
| [Diagnostics.CodeAnalysis.SuppressMessage("PSAvoidUsingWriteHost", "", Justification = "This is an interface cmdlet that should be seen in its host.")] | |
| [CmdletBinding()] | |
| param( | |
| [Parameter(Mandatory=$true, Position=1)] | |
| [string]$Message, | |
| [Parameter(Mandatory=$false, Position=2)] | |
| [ValidateSet("List", "RawList"<#, "Expand"#>, "Checkbox", "RawCheckbox", "Confirm", "Input", "RawInput", "Password"<#, "Editor"#>)] | |
| [string]$Type = "Input", | |
| [Parameter(Mandatory=$false, Position=3)] | |
| [string]$Name = "Answer", | |
| [Parameter(Mandatory=$false, Position=4)] | |
| [string[]]$Default, | |
| [Parameter(Mandatory=$false, Position=5)] | |
| [string[]]$Choices = @()) | |
| Begin { | |
| Function Write-Question { | |
| param([string]$q) | |
| (Write-Host "? " -ForegroundColor Green -NoNewline); (Write-Host $q -NoNewline); | |
| } | |
| } | |
| Process { | |
| $CursorChar = [char]0x25B8; | |
| $HighlightColor = "Cyan"; | |
| $DefaultValueColor = "Yellow"; | |
| $cx = $Host.UI.RawUI.CursorPosition.X; | |
| $cy = $Host.UI.RawUI.CursorPosition.Y; | |
| $mode = @("PS","ISE")[$null -ne (Get-Variable -Name "psISE" -ErrorAction Ignore)] | |
| $arrowLeft = 37; $arrowUp = 38; $arrowRight = 39; $arrowDown = 40; $enter = 13; $spaceBar = 32; $backspace = 8; $delete = 46; $cursorPos = 0; | |
| $sp = " "; | |
| if($mode -eq "PS") { | |
| Start-Sleep -Milliseconds 500; | |
| $Host.UI.RawUI.FlushInputBuffer(); | |
| } | |
| $result = @{}; | |
| # route the input to the raw versions when in ise host | |
| switch ($Type) { | |
| "List" { if($mode -eq "ISE") { $Type = "RawList"; } } | |
| "Checkbox" { if($mode -eq "ISE") { $Type = "RawCheckbox"; } } | |
| "Input" { if($mode -eq "ISE") { $Type = "RawInput"; } } | |
| } | |
| #region input | |
| if($Type -eq "Input") { | |
| if($Default -and $Default.Count -gt 0) { | |
| $content = [string]$Default[0].Clone(); | |
| } else { | |
| $content = ""; | |
| } | |
| #draw | |
| Write-Question $Message; Write-Host ": " -NoNewline; | |
| $mx = $Host.UI.RawUI.CursorPosition.X; | |
| if($content) { Write-Host $content -NoNewline; $nx = ($mx + $content.Length); } else { $nx = $mx; } | |
| $vx = $mx; | |
| #input loop | |
| while($true){ | |
| $cursel = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown"); | |
| if($cursel.VirtualKeyCode -eq $arrowLeft) { | |
| if($content -eq "") { | |
| $Host.UI.RawUI.CursorPosition = New-Object System.Management.Automation.Host.Coordinates $mx, $cy; | |
| } else { | |
| if($nx -gt $mx){ | |
| $nx--; | |
| $Host.UI.RawUI.CursorPosition = New-Object System.Management.Automation.Host.Coordinates $nx, $cy; | |
| } | |
| } | |
| } elseif($cursel.VirtualKeyCode -eq $arrowRight) { | |
| if($content -eq "") { | |
| $Host.UI.RawUI.CursorPosition = New-Object System.Management.Automation.Host.Coordinates $mx, $cy; | |
| } else { | |
| if($nx -lt ($mx + $content.Length)){ | |
| $nx++; | |
| $Host.UI.RawUI.CursorPosition = New-Object System.Management.Automation.Host.Coordinates $nx, $cy; | |
| } | |
| } | |
| } elseif($cursel.VirtualKeyCode -eq $backspace) { | |
| if($content -eq ""){ | |
| $Host.UI.RawUI.CursorPosition = New-Object System.Management.Automation.Host.Coordinates $mx, $cy; | |
| } else { | |
| if($nx -eq $mx) { | |
| $Host.UI.RawUI.CursorPosition = New-Object System.Management.Automation.Host.Coordinates $mx, $cy; | |
| } elseif($nx -lt ($mx + $content.Length)) { | |
| $vx = ($content.Length - 1) - ((($mx + $content.Length) - $nx)); | |
| $content = $content.Remove($vx, 1); | |
| $nx--; | |
| } elseif($nx -eq ($mx + $content.Length)) { | |
| if($nx -ge ($mx - $content.Length)) { | |
| $nx--; | |
| $content = $content.Substring(0, $content.Length - 1); | |
| } | |
| } | |
| #clear | |
| $Host.UI.RawUI.CursorPosition = New-Object System.Management.Automation.Host.Coordinates $mx, $cy; | |
| Write-Host ("".PadLeft($Host.UI.RawUI.BufferSize.Width - $mx, " ")) -NoNewline; | |
| #draw | |
| $Host.UI.RawUI.CursorPosition = New-Object System.Management.Automation.Host.Coordinates $mx, $cy; | |
| Write-Host $content -NoNewline; | |
| $Host.UI.RawUI.CursorPosition = New-Object System.Management.Automation.Host.Coordinates $nx, $cy; | |
| } | |
| } elseif($cursel.VirtualKeyCode -eq $delete) { | |
| if($content -eq ""){ | |
| $Host.UI.RawUI.CursorPosition = New-Object System.Management.Automation.Host.Coordinates $mx, $cy; | |
| } else { | |
| if($nx -ge ($mx + $content.Length)) { | |
| $Host.UI.RawUI.CursorPosition = New-Object System.Management.Automation.Host.Coordinates $mx, $cy; | |
| } elseif($nx -lt ($mx + $content.Length)) { | |
| $vx = $content.Length - ((($mx + $content.Length) - $nx)); | |
| $content = $content.Remove($vx, 1); | |
| } elseif($nx -eq $mx -and $content.Length -gt 0) { | |
| if($nx -gt ($mx - $content.Length)) { | |
| $content = $content.Substring(0, $content.Length - 1); | |
| } | |
| } | |
| #clear | |
| $Host.UI.RawUI.CursorPosition = New-Object System.Management.Automation.Host.Coordinates $mx, $cy; | |
| Write-Host ("".PadLeft($Host.UI.RawUI.BufferSize.Width - $mx, " ")) -NoNewline; | |
| #draw | |
| $Host.UI.RawUI.CursorPosition = New-Object System.Management.Automation.Host.Coordinates $mx, $cy; | |
| Write-Host $content -NoNewline; | |
| $Host.UI.RawUI.CursorPosition = New-Object System.Management.Automation.Host.Coordinates $nx, $cy; | |
| } | |
| } elseif($cursel.VirtualKeyCode -eq $enter) { | |
| break; | |
| } elseif([char]::IsLetterOrDigit($cursel.Character) -or | |
| [char]::IsPunctuation($cursel.Character) -or | |
| [char]::IsWhiteSpace($cursel.Character)) { | |
| $c = $cursel.Character; | |
| if($nx -lt ($mx + $content.Length)) { | |
| $vx = $content.Length - ((($mx + $content.Length) - $nx)); | |
| $content = $content.Insert($vx, $c); | |
| $nx++; | |
| } else { | |
| $content += $c; | |
| $nx++; | |
| } | |
| #clear | |
| $Host.UI.RawUI.CursorPosition = New-Object System.Management.Automation.Host.Coordinates $mx, $cy; | |
| Write-Host ("".PadLeft($Host.UI.RawUI.BufferSize.Width - $mx, " ")) -NoNewline; | |
| #draw | |
| $Host.UI.RawUI.CursorPosition = New-Object System.Management.Automation.Host.Coordinates $mx, $cy; | |
| Write-Host $content -NoNewline; | |
| $Host.UI.RawUI.CursorPosition = New-Object System.Management.Automation.Host.Coordinates $nx, $cy; | |
| } | |
| } | |
| #validate in | |
| $Host.UI.RawUI.CursorPosition = New-Object System.Management.Automation.Host.Coordinates $cx, $cy; | |
| Write-Question $Message; Write-Host ": " -NoNewline; Write-Host $content -ForegroundColor $HighlightColor; | |
| $result.Add($Name, $content); | |
| return $result; | |
| } | |
| #endregion | |
| #region confirm | |
| if($Type -eq "Confirm") { | |
| if($Default -and $Default.Count -gt 0) { | |
| $def = [string]$Default[0].Clone(); | |
| if($def -match "1|[yY](es)?") { $def = "Yes"; } | |
| elseif($def -match "0|[nN]o?") { $def = "No"; } | |
| $content = $def; | |
| } else { | |
| $content = ""; | |
| } | |
| #draw | |
| Write-Question $Message; Write-Host ": " -NoNewline; | |
| Write-Host "(" -NoNewline; Write-Host "Yes" -ForegroundColor @("White", $DefaultValueColor)[$content -eq "Yes"] -NoNewline; | |
| Write-Host "/" -NoNewline; Write-Host "No" -ForegroundColor @("White", $DefaultValueColor)[$content -eq "No"] -NoNewline; Write-Host ") " -NoNewline; | |
| $mx = $Host.UI.RawUI.CursorPosition.X; | |
| while($true){ | |
| $cursel = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown"); | |
| if($cursel.Character -match "[1yY]+") { | |
| $content = "Yes"; | |
| break; | |
| } elseif($cursel.Character -match "[0nN]+") { | |
| $content = "No"; | |
| break; | |
| } elseif($cursel.VirtualKeyCode -eq $enter -and ($content -ne "")) { | |
| break; | |
| } | |
| $Host.UI.RawUI.CursorPosition = New-Object System.Management.Automation.Host.Coordinates $mx, $cy; | |
| Write-Host ("".PadLeft($Host.UI.RawUI.BufferSize.Width - $mx, " ")) -NoNewline; | |
| $Host.UI.RawUI.CursorPosition = New-Object System.Management.Automation.Host.Coordinates $mx, $cy; | |
| } | |
| $Host.UI.RawUI.CursorPosition = New-Object System.Management.Automation.Host.Coordinates $cx, $cy; | |
| Write-Question $Message; Write-Host ": " -NoNewline; | |
| Write-Host "(" -NoNewline; Write-Host "Yes" -ForegroundColor @("White", "Yellow")[$def -eq "Yes"] -NoNewline; | |
| Write-Host "/" -NoNewline; Write-Host "No" -ForegroundColor @("White", "Yellow")[$def -eq "No"] -NoNewline; Write-Host ") " -NoNewline; | |
| Write-Host $content -ForegroundColor $HighlightColor; | |
| $result.Add($Name, $content); | |
| return $result; | |
| } | |
| #endregion | |
| #region list | |
| if($Type -eq "List") { | |
| if($Default -and $Default.Count -gt 0) { | |
| $content = [string]$Default[0].Clone(); | |
| } else { | |
| $content = $Choices[0]; | |
| } | |
| if("" -eq $content){ $cursorPos = 0; } | |
| else { | |
| $c = $Choices.IndexOf($content); | |
| if($c -eq -1){ $cursorPos = 0; }else{ $cursorPos = $c; } | |
| } | |
| $chcc = ($Choices.Count - 1); | |
| #input loop | |
| while($true){ | |
| Write-Question $Message; Write-Host ": " -NoNewline; | |
| $mx = $Host.UI.RawUI.CursorPosition.X; | |
| Write-Host ("".PadLeft($Host.UI.RawUI.BufferSize.Width - $mx, " ")) -NoNewline; | |
| $Host.UI.RawUI.CursorPosition = New-Object System.Management.Automation.Host.Coordinates $mx, $cy; | |
| if($content) { Write-Host $content; $nx = ($mx + $content.Length); } else { Write-Host ""; $nx = $mx; } | |
| $vx = $mx; | |
| $Choices | ForEach-Object {$ax=0}{ | |
| if($ax -eq $cursorPos) { | |
| Write-Host $CursorChar -NoNewline -ForegroundColor $HighlightColor | |
| } else { Write-Host " " -NoNewline } | |
| Write-Host ($sp + $sp + $_) -NoNewline:($ax -gt $Message.Length) -ForegroundColor @("White", $HighlightColor)[$ax -eq $cursorPos]; | |
| $ax++; | |
| }; | |
| $Host.UI.RawUI.CursorPosition = New-Object System.Management.Automation.Host.Coordinates ($mx + $content.Length), $cy; | |
| $cursel = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown"); | |
| if($cursel.VirtualKeyCode -eq $arrowUp) { | |
| if(($cursorPos-1) -lt 0){ $cursorPos = $chcc; } else { $cursorPos--; } | |
| } elseif($cursel.VirtualKeyCode -eq $arrowDown) { | |
| if(($cursorPos+1) -gt $chcc){ $cursorPos = 0; } else { $cursorPos++; } | |
| } elseif($cursel.VirtualKeyCode -eq $enter) { | |
| break; | |
| } | |
| $content = $Choices[$cursorPos]; | |
| $Host.UI.RawUI.CursorPosition = New-Object System.Management.Automation.Host.Coordinates $cx, $cy; | |
| } | |
| $cleanRange = $Choices.Count+1; | |
| for($i=0;$i -lt $cleanRange; $i++){ Write-Host ("".PadRight($Host.UI.RawUI.BufferSize.Width, " ")) }; | |
| $Host.UI.RawUI.CursorPosition = New-Object System.Management.Automation.Host.Coordinates $cx, $cy; | |
| Write-Question $Message; Write-Host ": " -NoNewline; | |
| Write-Host $content -ForegroundColor $HighlightColor -NoNewline; | |
| Write-Host ""; | |
| $result.Add($Name, $content); | |
| return $result; | |
| } | |
| #endregion | |
| #region raw list | |
| if($Type -eq "RawList") { | |
| if($Default -and $Default.Count -gt 0) { | |
| $content = [string]$Default[0].Clone(); | |
| } else { | |
| $content = $null; | |
| } | |
| if($null -eq $content){ $cursorPos = $null; } | |
| else { | |
| $c = $Choices.IndexOf($content); | |
| if($c -eq -1){ $cursorPos = $null; }else{ $cursorPos = $c; } | |
| } | |
| $chcc = ($Choices.Count - 1); | |
| $chccDigits = $chcc.ToString().Length + 2; | |
| #input loop | |
| while($true) { | |
| Write-Question $Message; Write-Host ": "; | |
| $Choices | ForEach-Object {$ax=0}{ | |
| if($ax -eq $cursorPos) { | |
| Write-Host (($ax+1).ToString().PadLeft($chccDigits, " ") + ")") -NoNewline -ForegroundColor $DefaultValueColor | |
| } else { Write-Host (($ax+1).ToString().PadLeft($chccDigits, " ") + ")") -NoNewline } | |
| Write-Host ($sp + $sp + $_) -NoNewline:($ax -gt $Message.Length) -ForegroundColor @("White", $DefaultValueColor)[$ax -eq $cursorPos]; | |
| $ax++; | |
| }; | |
| Write-Host "" | |
| Write-Host ($sp + $sp + "Answer: ") -NoNewline; | |
| $in = Read-Host | |
| if($in -match "^\d+$"){ | |
| $idx = [Convert]::ToUInt64($in); | |
| if($idx -gt 0 -and $idx -le $Choices.Count) { | |
| $content = $Choices[$idx - 1]; | |
| break; | |
| } | |
| } elseif($null -ne $content -and [string]::IsNullOrEmpty($in)) { | |
| break; | |
| } | |
| } | |
| $result.Add($Name, $content); | |
| return $result; | |
| } | |
| #endregion | |
| #region password | |
| if($Type -eq "Password") { | |
| $result = @{}; | |
| Write-Question -q $Message; Write-Host ": " -NoNewline; | |
| $password = [securestring](Read-Host -AsSecureString); | |
| $result.Add($Name, $password); | |
| return $result; | |
| } | |
| #endregion | |
| #region raw input | |
| if($Type -eq "RawInput") { | |
| $result = @{}; | |
| if($Default -and $Default.Count -gt 0) { | |
| $content = [string]$Default[0].Clone(); | |
| } else { | |
| $content = $null; | |
| } | |
| while($true) { | |
| Write-Question -q $Message; | |
| if($content) { | |
| Write-Host " (Default: " -NoNewline; | |
| Write-Host $content -ForegroundColor $DefaultValueColor -NoNewline; | |
| Write-Host ")" -NoNewline; | |
| } | |
| Write-Host ": "; | |
| Write-Host ($sp + $sp + "Answer: ") -NoNewline; | |
| $in = [string](Read-Host); | |
| if(($null -ne $content -and [string]::IsNullOrEmpty($in))) { | |
| break; | |
| } elseif(-not([string]::IsNullOrEmpty($in))) { | |
| $content = $in; | |
| break; | |
| } | |
| } | |
| $result.Add($Name, $content); | |
| return $result; | |
| } | |
| #endregion | |
| #region checkbox | |
| if($Type -eq "Checkbox") { | |
| $selectedChar = [char]0x25CF; | |
| $unselectedChar = [char]0x25CB; | |
| if($Default -and $Default.Count -gt 0) { | |
| $content = New-Object System.Collections.ArrayList -ArgumentList @(,$Default); | |
| } else { | |
| $content = New-Object System.Collections.ArrayList; | |
| } | |
| $cursorPos = 0; | |
| $chcc = ($Choices.Count - 1); | |
| #input loop | |
| while($true){ | |
| Write-Question $Message; Write-Host ": " -NoNewline; | |
| $mx = $Host.UI.RawUI.CursorPosition.X; | |
| $Host.UI.RawUI.CursorPosition = New-Object System.Management.Automation.Host.Coordinates $mx, $cy; | |
| Write-Host ""; | |
| $Choices | ForEach-Object {$ax=0}{ | |
| if($ax -eq $cursorPos) { | |
| Write-Host $CursorChar -NoNewline -ForegroundColor $HighlightColor | |
| } else { Write-Host " " -NoNewline } | |
| Write-Host ($sp + @($unselectedChar, $selectedChar)[$content.Contains($_)] + $sp + $_) -NoNewline:($ax -gt $Message.Length) -ForegroundColor @("White", $HighlightColor)[$ax -eq $cursorPos]; | |
| $ax++; | |
| }; | |
| $Host.UI.RawUI.CursorPosition = New-Object System.Management.Automation.Host.Coordinates $mx, $cy; | |
| $cursel = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown"); | |
| if($cursel.VirtualKeyCode -eq $arrowUp) { | |
| if(($cursorPos-1) -lt 0){ $cursorPos = $chcc; } else { $cursorPos--; } | |
| } elseif($cursel.VirtualKeyCode -eq $arrowDown) { | |
| if(($cursorPos+1) -gt $chcc){ $cursorPos = 0; } else { $cursorPos++; } | |
| } elseif($cursel.VirtualKeyCode -eq $spaceBar) { | |
| $s = $Choices[$cursorPos]; | |
| #toggle selection | |
| if($content.Contains($s)) { $content.Remove($s) | Out-Null; } | |
| else { $content.Add($s) | Out-Null; } | |
| } elseif($cursel.VirtualKeyCode -eq $enter) { | |
| break; | |
| } | |
| $Host.UI.RawUI.CursorPosition = New-Object System.Management.Automation.Host.Coordinates $cx, $cy; | |
| } | |
| $cleanRange = $Choices.Count+1; | |
| for($i=0;$i -lt $cleanRange; $i++){ Write-Host ("".PadRight($Host.UI.RawUI.BufferSize.Width, " ")) }; | |
| $Host.UI.RawUI.CursorPosition = New-Object System.Management.Automation.Host.Coordinates $cx, $cy; | |
| Write-Question $Message; Write-Host ": " -NoNewline; | |
| Write-Host $content -ForegroundColor $HighlightColor -NoNewline; | |
| Write-Host ""; | |
| $result.Add($Name, $content); | |
| return $result; | |
| } | |
| #endregion | |
| #region raw checkbox | |
| if($Type -eq "RawCheckbox") { | |
| if($Default -and $Default.Count -gt 0) { | |
| $content = New-Object System.Collections.ArrayList -ArgumentList @(,$Default); | |
| } else { | |
| $content = New-Object System.Collections.ArrayList; | |
| } | |
| $chcc = ($Choices.Count - 1); | |
| $chccDigits = $chcc.ToString().Length + 2; | |
| #input loop | |
| while($true) { | |
| Write-Question $Message; Write-Host ": "; | |
| $Choices | ForEach-Object {$ax=0}{ | |
| Write-Host (($ax+1).ToString().PadLeft($chccDigits, " ") + ")") -NoNewline -ForegroundColor @("White", $DefaultValueColor)[ ($content -contains $Choices[$ax]) ]; | |
| Write-Host ($sp + $sp + $_) -NoNewline:($ax -gt $Message.Length) -ForegroundColor @("White", $DefaultValueColor)[ ($content -contains $Choices[$ax]) ]; | |
| $ax++; | |
| }; | |
| Write-Host "" | |
| Write-Host ($sp + $sp + "Answer: ") -NoNewline; | |
| $in = Read-Host | |
| if($in -match "^\d+(?:,\d+)*$"){ | |
| $idxs = @($in -split "," | ForEach-Object { [Convert]::ToUInt64($_.Trim()); } | Select-Object -Unique); | |
| $inputNumberCount = $idxs.Length; | |
| $chosen = @($idxs | ForEach-Object { $idx = $_; if($idx -gt 0 -and $idx -le $Choices.Count) { $idx | Write-Output; } else { $null | Write-Output; } } | Where-Object { $null -ne $_; }); | |
| if($chosen.Length -eq $inputNumberCount) { | |
| $content = ($chosen | Sort-Object | ForEach-Object { $Choices[$_ - 1]; }); | |
| break; | |
| } | |
| } elseif($null -ne $content -and [string]::IsNullOrEmpty($in)) { | |
| break; | |
| } | |
| } | |
| $result.Add($Name, $content); | |
| return $result; | |
| } | |
| #endregion | |
| } | |
| } | |
| #Read-Input -Message "What's your name?" | |
| #Read-Input -Message "What's your name?" -Default "Martin" | |
| #Read-Input -Message "Wanna do this?" -Type Confirm -Default "Y" | |
| #Read-Input -Message "What's your name?" -Type List -Choices "Martin","Lars","Benjamin" -Default "Lars" | |
| #Read-Input -Message "Enter your git password" -Type Password; | |
| #Read-Input -Message "What's your name?" -Type RawList -Choices "Martin","Lars","Benjamin" -Default "Lars" | |
| Read-Input -Message "What's your name?" -Type Checkbox -Choices "Martin","Lars","Benjamin" -Default "Lars","Benjamin" | |
| #Read-Input -Message "What's your name?" -Type RawInput -Default "Martin" | |
| #$a = Read-Input -Question "What you want to do?" -Choices @("Angular", "Gulp", "Polymer") -DefaultChoice "Polymer" | |
| # $b = Read-Choice -Question "What you want to do?" -Choices @("Angular", "Gulp", "Polymer") -HelpText "Something here" | |
| #$b = Read-Input -Question "What you want to do?" -Choices @("Angular", "Gulp", "Polymer") -HelpText "Something here" -MultiSelect -DefaultChoice @("Gulp", "Angular") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment