Search code examples
powershellloopswhile-loopforeachpowershell-5.1

Issue while displaying "foreach" values


I have an powershell script which get's a list of customers from an json file, and then print it, based on what it typped until now. But, even the "list" block being after the "userInput header", it display the list before it, why?

json example:

[
  {
    "id": 123,
    "name": "Example LTDA",
    "database": "SqlServer"
  },
  {
    "id": 321,
    "name": "ECOMMERCE SA",
    "database": "Oracle"
  }
]

script:

$customersJson = Get-Content "%jsonpath%\customers.json" | ConvertFrom-Json | ForEach-Object { $_.name }

while ($true) {
    #Clear-Host
    [console]::CursorVisible = $false

    #Write-Host "DEBUG: `nfullString: $fullstring `nuserInput: $userInput `nFIM." -ForegroundColor Red
    Write-Host "Type the customer name:" -ForegroundColor Yellow
    Write-Host "> " -NoNewline
    Write-Host $fullstring -ForegroundColor Cyan
    $userInput = [System.Console]::ReadKey($true)

    if( $userInput.Key -eq "Backspace" )  { $fullstring = $fullString -replace “.$”      }
    elseif( $userInput.Key -eq "Enter" ) { return $fullstring                            }
    else                                { $fullstring = $fullString + $userInput.KeyChar }

    if(($fullstring.Length -gt 1) -and ($null -ne $fullstring)) {
        $customersList = $customersJson | Where-Object { $_ -match $fullstring } #| Select-Object -First 10

        Write-Host "____________________________`n" -ForegroundColor DarkGray
        foreach($customer in $customersList) {

            # Primeira letra maíúscula
            $customer = $customer.ToLower()
            $customer = $customer.Replace($customer[0],$customer[0].ToString().ToUpper())
            if ($fullstring -eq $customer) {
                Write-Host $customer -ForegroundColor DarkRed
            } else {
                Write-Host $customer -ForegroundColor DarkGray
            }
        }
        Write-Host "____________________________" -ForegroundColor DarkGray
    }

}

[console]::CursorVisible = $true

Write-Host "Typed customer: $fullString" -ForegroundColor Red

Display the customer list, after the prompt("Type the customer name") header, not before.


Solution

  • If you want the prompt after the customer list, move the ReadKey statement until after you've rendered the list:

    $customersJson = Get-Content '%jsonpath%\customers.json' | ConvertFrom-Json | ForEach-Object { $_.name }
    
    $fullString = ''
    [console]::CursorVisible = $false
    
    while ($true) {
        Clear-Host
    
        # 1. Write prompt header
        Write-Host 'Type the customer name:' -ForegroundColor Yellow
    
        # 2. Optionally write customer list
        if ($fullstring.Length) {
            $customersList = $customersJson | Where-Object { $_ -match $fullstring } #| Select-Object -First 10
    
            Write-Host "____________________________`n" -ForegroundColor DarkGray
            foreach ($customer in $customersList) {
    
                # Primeira letra maíúscula
                $customer = $customer.ToLower()
                $customer = $customer.Replace($customer[0], $customer[0].ToString().ToUpper())
                if ($fullstring -eq $customer) {
                    Write-Host $customer -ForegroundColor DarkRed
                }
                else {
                    Write-Host $customer -ForegroundColor DarkGray
                }
            }
            Write-Host '____________________________' -ForegroundColor DarkGray
        }
    
        # 3. Prompt for next char
        Write-Host '> ' -NoNewline
        Write-Host $fullstring -ForegroundColor Cyan
        $userInput = [System.Console]::ReadKey($true)
    
        if ( $userInput.Key -eq 'Backspace' ) { 
            $fullstring = $fullString -replace '.$'      
        }
        elseif ( $userInput.Key -eq 'Enter' ) { 
            return $fullstring                            
        }
        else { 
            $fullstring = $fullString + $userInput.KeyChar 
        }
    }
    
    [console]::CursorVisible = $true
    
    Write-Host "Typed customer: $fullString" -ForegroundColor Red