Skip to content

Instantly share code, notes, and snippets.

@mhudasch
Last active October 27, 2016 16:01
Show Gist options
  • Save mhudasch/5ff826f2e3c0b02c101a296b4e3671dc to your computer and use it in GitHub Desktop.
Save mhudasch/5ff826f2e3c0b02c101a296b4e3671dc to your computer and use it in GitHub Desktop.
Test of Input mask for PS
#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