I have been trying to make a small script that takes user input and inserts "-" as such: aaaaa-bbb-ccc-ddd While also allowing backspace. I managed to make this in Python pretty handily, but whenever I make it into an EXE, Windows thinks it is a virus so I went to Powershell.
Anyway, the issue I have is that it will do aaaaa-bbbb-cccc-d instead of the desired aaaaa-bbb-ccc-ddd. For some reason it is not going to 3 but 4 after the first 5. Big shout out to u/frmadsen for helping me so far. This is the code:
[Console]::TreatControlCAsInput = $true
[Console]::WriteLine("Enter Serial:")
$inputString = ""
$maxGroupCount = 5 # max number of groups
$groupSize = 5 # chars per group
$groupCount = 0
$maxLength = $maxGroupCount*$groupSize $maxGroupCount-1
$abort = $false
do{
$keyInfo = [Console]::ReadKey($true)
# Handle Escape key.
if($keyInfo.Key -eq "Escape"){
$abort = $true
break
}
# ignore some keys...
if(($keyInfo.Modifiers -band [System.ConsoleModifiers]::Alt) -eq
[System.ConsoleModifiers]::Alt -or
($keyInfo.Modifiers -band [System.ConsoleModifiers]::Control) -eq
[System.ConsoleModifiers]::Control -or
$keyInfo.Key -eq "Tab" -or
$keyInfo.KeyChar -eq '`0'
){ continue }
# Handle backspace.
if($keyInfo.Key -eq "Backspace"){
# Are there any characters to erase?
if($inputString.Length -ge 1){
# Determine where we are in the console buffer.
$oldLength = $inputString.Length
$removeLen = 1
# are we erasing a group separator?
if($inputString.EndsWith('-')){
# remove '-' and the char before it
$removeLen = 2
$groupCount--
}
$cursorCol = [Console]::CursorLeft - $removeLen
$inputString = $inputString.Substring(0, $oldLength - $removeLen)
[Console]::CursorLeft = 0
[Console]::Write($inputString ' '*($oldLength - $inputString.Length))
[Console]::CursorLeft = $cursorCol
}
continue
}
# code must not exceed maximum length
if($inputString.Length -ge 17){
continue
}
$lastChar = $keyInfo.KeyChar
[Console]::Write($lastChar)
$inputString = $lastChar
if(($inputString.Length) % $groupSize -eq 0 -and $lastChar.Length -lt 17){
# add group separator now
$groupCount
$inputString = '-'
[Console]::Write('-')
}
if(($inputString.Length) % $groupSize -eq 0 -and $lastChar.Length -lt 17){
# add group separator now
$groupSize = 3
$inputString = 0
$groupCount
$inputString = '-'
[Console]::Write('-')
}
}while($keyInfo.Key -ne "Enter")
[Console]::WriteLine("")
if(!$abort){
"User wrote: $inputString"
}else{
"User aborted"
}
CodePudding user response:
You have a logic error. The length is including the dashes you add to the input. Therefore, you should be checking $lastChar.Length
is less than 19
, not 17
.
# here is line 54, above is unchanged
if($inputString.Length -ge 19){
continue
}
$lastChar = $keyInfo.KeyChar
[Console]::Write($lastChar)
$inputString = $lastChar
if(($inputString.Length) % $groupSize -eq 0 -and $lastChar.Length -lt 19){
# add group separator now
$groupCount
$inputString = '-'
[Console]::Write('-')
}
if(($inputString.Length) % $groupSize -eq 0 -and $lastChar.Length -lt 19){
# add group separator now
$groupSize = 3
$inputString = 0
$groupCount
$inputString = '-'
[Console]::Write('-')
}
}while($keyInfo.Key -ne "Enter")
# Unchanged below
CodePudding user response:
As suggested in the comment, it is probably easier to replace the whole $InputString
with a regular expression:
[Console]::TreatControlCAsInput = $true
[Console]::WriteLine("Enter Serial:")
$inputString = ''
$ValidCharacters = '\w'
$Size = 14
$Dots = '.' * $Size
$abort = $false
do{
$keyInfo = [Console]::ReadKey($true)
if($keyInfo.Key -eq "Escape"){
$abort = $true
break
}
if($inputString.Length -ge 1 -and $keyInfo.Key -eq "Backspace"){ $InputString = $InputString.SubString(0, ($InputString.Length - 1)) }
elseif($inputString.Length -lt $Size -and $keyInfo.Key -Match $ValidCharacters) { $inputString = $keyInfo.KeyChar }
$Write = [regex]::Matches(($inputString $Dots), '^([^-]{5})([^-]{3})([^-]{3})([^-]{3})').Groups[1..4].Value -Join '-'
[Console]::CursorLeft = 0
[Console]::Write($Write)
}while($keyInfo.Key -ne "Enter")
[Console]::WriteLine("")
if(!$abort){
"User wrote: $Write"
}else{
"User aborted"
}