Skip to content

Instantly share code, notes, and snippets.

@bradwilson
Last active March 21, 2024 07:24
Show Gist options
  • Star 10 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save bradwilson/d965fa17fd3b3eee168270122e0f7da4 to your computer and use it in GitHub Desktop.
Save bradwilson/d965fa17fd3b3eee168270122e0f7da4 to your computer and use it in GitHub Desktop.
Downloadable files for bradwilson.io/blog/prompt/powershell
######## POSH-GIT
# ... Import-Module for posh-git here ...
# Background colors
$GitPromptSettings.AfterStash.BackgroundColor = 0x5F5FAF
$GitPromptSettings.AfterStatus.BackgroundColor = 0x5F5FAF
$GitPromptSettings.BeforeIndex.BackgroundColor = 0x5F5FAF
$GitPromptSettings.BeforeStash.BackgroundColor = 0x5F5FAF
$GitPromptSettings.BeforeStatus.BackgroundColor = 0x5F5FAF
$GitPromptSettings.BranchAheadStatusSymbol.BackgroundColor = 0x5F5FAF
$GitPromptSettings.BranchBehindAndAheadStatusSymbol.BackgroundColor = 0x5F5FAF
$GitPromptSettings.BranchBehindStatusSymbol.BackgroundColor = 0x5F5FAF
$GitPromptSettings.BranchColor.BackgroundColor = 0x5F5FAF
$GitPromptSettings.BranchGoneStatusSymbol.BackgroundColor = 0x5F5FAF
$GitPromptSettings.BranchIdenticalStatusSymbol.BackgroundColor = 0x5F5FAF
$GitPromptSettings.DefaultColor.BackgroundColor = 0x5F5FAF
$GitPromptSettings.DelimStatus.BackgroundColor = 0x5F5FAF
$GitPromptSettings.ErrorColor.BackgroundColor = 0x5F5FAF
$GitPromptSettings.IndexColor.BackgroundColor = 0x5F5FAF
$GitPromptSettings.LocalDefaultStatusSymbol.BackgroundColor = 0x5F5FAF
$GitPromptSettings.LocalStagedStatusSymbol.BackgroundColor = 0x5F5FAF
$GitPromptSettings.LocalWorkingStatusSymbol.BackgroundColor = 0x5F5FAF
$GitPromptSettings.StashColor.BackgroundColor = 0x5F5FAF
$GitPromptSettings.WorkingColor.BackgroundColor = 0x5F5FAF
# Foreground colors
$GitPromptSettings.AfterStash.ForegroundColor = 0xF49797
$GitPromptSettings.AfterStatus.ForegroundColor = 0x729FCF
$GitPromptSettings.BeforeStash.ForegroundColor = 0xF49797
$GitPromptSettings.BeforeStatus.ForegroundColor = 0x729FCF
$GitPromptSettings.BranchAheadStatusSymbol.ForegroundColor = 0x8AE234
$GitPromptSettings.BranchBehindAndAheadStatusSymbol.ForegroundColor = 0xFCE94F
$GitPromptSettings.BranchBehindStatusSymbol.ForegroundColor = 0xF49797
$GitPromptSettings.BranchColor.ForegroundColor = 0xFBFBFB
$GitPromptSettings.BranchGoneStatusSymbol.ForegroundColor = 0x729FCF
$GitPromptSettings.BranchIdenticalStatusSymbol.ForegroundColor = 0x729FCF
$GitPromptSettings.DefaultColor.ForegroundColor = 0xB5BBAE
$GitPromptSettings.DelimStatus.ForegroundColor = 0x729FCF
$GitPromptSettings.ErrorColor.ForegroundColor = 0xF49797
$GitPromptSettings.IndexColor.ForegroundColor = 0x2EC3C3
$GitPromptSettings.StashColor.ForegroundColor = 0xF49797
$GitPromptSettings.WorkingColor.ForegroundColor = 0xFCE94F
# Prompt shape
$GitPromptSettings.AfterStatus.Text = " "
$GitPromptSettings.BeforeStatus.Text = ""
$GitPromptSettings.BranchAheadStatusSymbol.Text = ""
$GitPromptSettings.BranchBehindStatusSymbol.Text = ""
$GitPromptSettings.BranchGoneStatusSymbol.Text = ""
$GitPromptSettings.BranchBehindAndAheadStatusSymbol.Text = ""
$GitPromptSettings.BranchIdenticalStatusSymbol.Text = ""
$GitPromptSettings.BranchUntrackedText = ""
$GitPromptSettings.DelimStatus.Text = ""
$GitPromptSettings.LocalStagedStatusSymbol.Text = ""
$GitPromptSettings.LocalWorkingStatusSymbol.Text = ""
$GitPromptSettings.PathStatusSeparator = ""
$GitPromptSettings.EnableStashStatus = $false
$GitPromptSettings.ShowStatusWhenZero = $false
######## INI FILE PARSER
function parseIniFile {
[CmdletBinding()]
param(
[Parameter(Position = 0)]
[String] $Inputfile
)
if ($Inputfile -eq "") {
Write-Error "Ini File Parser: No file specified or selected to parse."
Break
}
else {
$ContentFile = Get-Content $Inputfile
# commented Section
$COMMENT_CHARACTERS = ";"
# match section header
$HEADER_REGEX = "\[+[A-Z0-9._ %<>/#+-]+\]"
$OccurenceOfComment = 0
$ContentComment = $ContentFile | Where-Object { ($_ -match "^\s*$COMMENT_CHARACTERS") -or ($_ -match "^$COMMENT_CHARACTERS") } | ForEach-Object {
[PSCustomObject]@{ Comment = $_ ;
Index = [Array]::IndexOf($ContentFile, $_)
}
$OccurenceOfComment++
}
$COMMENT_INI = @()
foreach ($COMMENT_ELEMENT in $ContentComment) {
$COMMENT_OBJ = New-Object PSObject
$COMMENT_OBJ | Add-Member -type NoteProperty -name Index -value $COMMENT_ELEMENT.Index
$COMMENT_OBJ | Add-Member -type NoteProperty -name Comment -value $COMMENT_ELEMENT.Comment
$COMMENT_INI += $COMMENT_OBJ
}
$CONTENT_USEFUL = $ContentFile | Where-Object { ($_ -notmatch "^\s*$COMMENT_CHARACTERS") -or ($_ -notmatch "^$COMMENT_CHARACTERS") }
$ALL_SECTION_HASHTABLE = $CONTENT_USEFUL | Where-Object { $_ -match $HEADER_REGEX } | ForEach-Object { [PSCustomObject]@{ Section = $_ ; Index = [Array]::IndexOf($CONTENT_USEFUL, $_) } }
#$ContentUncomment | Select-String -AllMatches $HEADER_REGEX | Select-Object -ExpandProperty Matches
$SECTION_INI = @()
foreach ($SECTION_ELEMENT in $ALL_SECTION_HASHTABLE) {
$SECTION_OBJ = New-Object PSObject
$SECTION_OBJ | Add-Member -type NoteProperty -name Index -value $SECTION_ELEMENT.Index
$SECTION_OBJ | Add-Member -type NoteProperty -name Section -value $SECTION_ELEMENT.Section
$SECTION_INI += $SECTION_OBJ
}
$INI_FILE_CONTENT = @()
$NBR_OF_SECTION = $SECTION_INI.count
$NBR_MAX_LINE = $CONTENT_USEFUL.count
#*********************************************
# select each lines and value of each section
#*********************************************
for ($i = 1; $i -le $NBR_OF_SECTION ; $i++) {
if ($i -ne $NBR_OF_SECTION) {
if (($SECTION_INI[$i - 1].Index + 1) -eq ($SECTION_INI[$i].Index )) {
$CONVERTED_OBJ = @() #There is nothing between the two section
}
else {
$SECTION_STRING = $CONTENT_USEFUL | Select-Object -Index (($SECTION_INI[$i - 1].Index + 1)..($SECTION_INI[$i].Index - 1)) | Out-String
$CONVERTED_OBJ = convertfrom-stringdata -stringdata $SECTION_STRING
}
}
else {
if (($SECTION_INI[$i - 1].Index + 1) -eq $NBR_MAX_LINE) {
$CONVERTED_OBJ = @() #There is nothing between the two section
}
else {
$SECTION_STRING = $CONTENT_USEFUL | Select-Object -Index (($SECTION_INI[$i - 1].Index + 1)..($NBR_MAX_LINE - 1)) | Out-String
$CONVERTED_OBJ = convertfrom-stringdata -stringdata $SECTION_STRING
}
}
$CURRENT_SECTION = New-Object PSObject
$CURRENT_SECTION | Add-Member -Type NoteProperty -Name Section -Value $SECTION_INI[$i - 1].Section
$CURRENT_SECTION | Add-Member -Type NoteProperty -Name Content -Value $CONVERTED_OBJ
$INI_FILE_CONTENT += $CURRENT_SECTION
}
return $INI_FILE_CONTENT
}
}
######## FIND A FILE/PATTERN HERE OR IN ANY PARENT FOLDER
function findHereOrParent {
[CmdletBinding()]
param(
[Parameter(Mandatory = $true)]
[string[]] $filePaths
)
try {
$currentFolder = Get-Location
while ($currentFolder -ne "") {
foreach ($filePath in $filePaths) {
if ((Get-ChildItem -ErrorAction Ignore -LiteralPath $currentFolder -Filter $filePath).Count -gt 0) {
return $true
}
}
$currentFolder = Split-Path $currentFolder
}
}
catch {
$Error.Clear()
}
return $false
}
######## PROMPT
set-content Function:prompt {
# Start with a blank line, for breathing room :)
Write-Host ""
# Reset the foreground color to default
$Host.UI.RawUI.ForegroundColor = "Gray"
Write-Host " " -NoNewLine
# Write ERR for any PowerShell errors
if ($Error.Count -ne 0) {
Write-Host "$([char]27)[38;5;131;40m$([char]27)[38;5;227;48;5;131m  ERR $([char]27)[38;5;131;40m" -NoNewLine
$Error.Clear()
}
# Write Ctrl+C separately
if ($LASTEXITCODE -eq -1073741510) {
Write-Host "$([char]27)[38;5;131;40m$([char]27)[38;5;227;48;5;131m  Ctrl-C $([char]27)[38;5;131;40m" -NoNewLine
$LASTEXITCODE = ""
}
# Write non-zero exit code from last launched process
if ($LASTEXITCODE -ne "") {
Write-Host "$([char]27)[38;5;131;40m$([char]27)[38;5;227;48;5;131m  $LASTEXITCODE $([char]27)[38;5;131;40m" -NoNewLine
$LASTEXITCODE = ""
}
# Write any custom prompt environment (f.e., from vs2017.ps1)
if (get-content variable:\PromptEnvironment -ErrorAction Ignore) {
Write-Host "$([char]27)[38;5;183;40m$([char]27)[38;5;54;48;5;183m$PromptEnvironment$([char]27)[38;5;183;40m" -NoNewLine
}
# Write Go version
if (($null -ne (Get-Command "go" -ErrorAction Ignore)) -and (findHereOrParent go.mod)) {
$goVersion = (& go version).split()[2].substring(2)
Write-Host "$([char]27)[38;5;80;48;5;0m$([char]27)[38;5;16;48;5;80m  $goVersion $([char]27)[38;5;80;40m" -NoNewLine
}
# Write Rust version
if (($null -ne (Get-Command "rustc" -ErrorAction Ignore)) -and (findHereOrParent Cargo.toml)) {
$rustVersion = (& rustc --version).Split()[1]
Write-Host "$([char]27)[38;5;172;40m$([char]27)[38;5;231;48;5;172m  $rustVersion $([char]27)[38;5;172;40m" -NoNewLine
}
# Write .NET SDK version
if (($null -ne (Get-Command "dotnet" -ErrorAction Ignore)) -and (findHereOrParent *.sln,*.csproj)) {
$dotNetVersion = (& dotnet --version)
Write-Host "$([char]27)[38;5;54;40m$([char]27)[38;5;254;48;5;54m  $dotNetVersion $([char]27)[38;5;54;40m" -NoNewLine
}
# Write the current kubectl context
if ($null -ne (Get-Command "kubectl" -ErrorAction Ignore)) {
$currentContext = (& kubectl config current-context 2> $null)
if (($Error.Count -eq 0) -and ($currentContext -ne $null)) {
Write-Host "$([char]27)[38;5;242;40m$([char]27)[38;5;112;48;5;242m  $([char]27)[38;5;254m$currentContext $([char]27)[38;5;242;40m" -NoNewLine
}
else {
$Error.Clear()
}
}
# Write the current public cloud Azure CLI subscription
# NOTE: You will need sed from somewhere (for example, from Git for Windows)
if (Test-Path ~/.azure/clouds.config) {
$cloudsConfig = parseIniFile ~/.azure/clouds.config
$azureCloud = $cloudsConfig | Where-Object { $_.Section -eq "[AzureCloud]" }
if ($null -ne $azureCloud) {
$currentSub = $azureCloud.Content.subscription
if ($null -ne $currentSub) {
$currentAccount = (Get-Content ~/.azure/azureProfile.json | ConvertFrom-Json).subscriptions | Where-Object { $_.id -eq $currentSub }
if ($null -ne $currentAccount) {
Write-Host "$([char]27)[38;5;30;40m$([char]27)[38;5;227;48;5;30m  $([char]27)[38;5;254m$($currentAccount.name) $([char]27)[38;5;30;40m" -NoNewLine
}
}
}
}
# Write the current Git information
if ($null -ne (Get-Command "Get-GitDirectory" -ErrorAction Ignore)) {
if (Get-GitDirectory -ne $null) {
Write-Host "$([char]27)[38;5;61;40m$(Write-VcsStatus)$([char]27)[38;5;61;40m" -NoNewLine
}
}
# Write the current directory, with home folder normalized to ~
$currentPath = (get-location).Path.replace($home, "~")
$idx = $currentPath.IndexOf("::")
if ($idx -gt -1) { $currentPath = $currentPath.Substring($idx + 2) }
$host.UI.RawUI.WindowTitle = $currentPath
Write-Host "$([char]27)[38;5;28;40m$([char]27)[38;5;227;48;5;28m  $([char]27)[38;5;254m$currentPath " -NoNewline
# Reset LASTEXITCODE so we don't show it over and over again
$global:LASTEXITCODE = 0
# Write one + for each level of the pushd stack
if ((get-location -stack).Count -gt 0) {
Write-Host ("$([char]27)[38;5;227;48;5;28m" + ("«" * ((get-location -stack).Count)) + " ") -NoNewLine
}
# Newline
Write-Host "$([char]27)[38;5;28;40m$([char]27)[30;40m $([char]27)[0m"
# Determine if the user is admin, so we color the prompt green or red
$isAdmin = $false
$isDesktop = ($PSVersionTable.PSEdition -eq "Desktop")
if ($isDesktop -or $IsWindows) {
$windowsIdentity = [System.Security.Principal.WindowsIdentity]::GetCurrent()
$windowsPrincipal = new-object 'System.Security.Principal.WindowsPrincipal' $windowsIdentity
$isAdmin = $windowsPrincipal.IsInRole("Administrators") -eq 1
}
else {
$isAdmin = ((& id -u) -eq 0)
}
if ($isAdmin) { $color = "Red"; }
else { $color = "Green"; }
# Write PS> for desktop PowerShell, pwsh> for PowerShell Core
if ($isDesktop) {
Write-Host " PS>" -NoNewLine -ForegroundColor $color
}
else {
Write-Host " pwsh>" -NoNewLine -ForegroundColor $color
}
# Always have to return something or else we get the default prompt
return " "
}
param(
[string]$edition,
[string]$version = "2022",
[string]$basePath = "",
[switch]$noWeb = $false
)
function append-path {
param(
[string[]][Parameter(Mandatory = $true)]$pathsToAdd
)
$local:separator = ";"
if (($PSVersionTable.PSVersion.Major -gt 5) -and ($PSVersionTable.Platform -eq "Unix")) {
$local:separator = ":"
}
$env:PATH = $env:PATH + $local:separator + ($pathsToAdd -join $local:separator)
}
# Only support one prompt environment at a time
if ($PromptEnvironment -ne $null) {
write-host "error: Prompt is already in a custom environment." -ForegroundColor Red
exit 1
}
# Look in the standard installation locations unless they override
if ($basePath -eq "") {
$basePath = join-path (join-path ${env:ProgramFiles(x86)} "Microsoft Visual Studio") $version
if ((test-path $basePath) -eq $false) {
$basePath = join-path (join-path ${env:ProgramFiles} "Microsoft Visual Studio") $version
}
}
if ((test-path $basePath) -eq $false) {
write-warning "Visual Studio $version is not installed in '$basePath'."
exit 1
}
# If edition wasn't specified, see what's there, and bail out if there is more than 1
if ($edition -eq "") {
$editions = (get-childitem $basePath | where-object { $_.PSIsContainer })
if ($editions.Count -eq 0) {
write-warning "Visual Studio $version is not installed."
exit 1
}
if ($editions.Count -gt 1) {
write-warning "Multiple editions of Visual Studio $version are installed. Please specify one of the editions ($($($editions | Foreach-Object { "'" + $_.Name + "'" }) -join ', ')) with the -edition switch."
exit 1
}
$edition = $editions[0].Name
}
# Find VsDevCmd.bat
$path = join-path (join-path (join-path $basePath $edition) "Common7") "Tools"
if ((test-path $path) -eq $false) {
write-warning "Visual Studio $version edition '$edition' could not be found."
exit 1
}
$cmdPath = join-path $path "VsDevCmd.bat"
if ((test-path $cmdPath) -eq $false) {
write-warning "File not found: $cmdPath"
exit 1
}
# Run VsDevCmd.bat and then dump all environment variables, so we can
# overwrite ours with theirs
$tempFile = [IO.Path]::GetTempFileName()
cmd /c " `"$cmdPath`" && set > `"$tempFile`" "
Get-Content $tempFile | %{
if ($_ -match "^(.*?)=(.*)$") {
Set-Content "env:\$($matches[1])" $matches[2]
}
}
# Optionally add the external web tools unless skipped
if ($noWeb -eq $false) {
$path = join-path (join-path (join-path $basePath $edition) "Web") "External"
if (test-path $path) {
append-path $path
} else {
write-warning "Path $path not found; specify -noWeb to skip searching for web tools"
}
}
# Set the prompt environment variable (printed in our prompt function)
$global:PromptEnvironment = "  $version "
param(
[string]$edition,
[string]$basePath = "",
[switch]$noWeb = $false
)
$folder = Split-Path $PSCommandPath
$script = Join-Path $folder "vs.ps1"
& $script -edition:$edition -version:"2017" -basePath:$basePath -noWeb:$noWeb
param(
[string]$edition,
[string]$basePath = "",
[switch]$noWeb = $false
)
$folder = Split-Path $PSCommandPath
$script = Join-Path $folder "vs.ps1"
& $script -edition:$edition -version:"2019" -basePath:$basePath -noWeb:$noWeb
param(
[string]$edition,
[string]$basePath = "",
[switch]$noWeb = $false
)
$folder = Split-Path $PSCommandPath
$script = Join-Path $folder "vs.ps1"
& $script -edition:$edition -version:"2022" -basePath:$basePath -noWeb:$noWeb
param(
[string]$edition,
[string]$basePath = "",
[switch]$noWeb = $false
)
$folder = Split-Path $PSCommandPath
$script = Join-Path $folder "vs.ps1"
& $script -edition:$edition -version:"Preview" -basePath:$basePath -noWeb:$noWeb
@tillig
Copy link

tillig commented Mar 13, 2019

First, thanks for this and the great blog article on it. I'm in the process of adopting some of this myself, though not using ConEmu - just plain PowerShell.

I noticed a couple of things that might help reduce the custom code you have to maintain, if you're interested.

  • The block that reduces the path such that the home is normalized to ~ - you can use the function from posh-git that does it for you: $currentPath = $GitPromptSettings.DefaultPromptPath.Expand().Text
  • There's a VSSetup PowerShell module that can be used to locate VS installs for 2017 (and, I think, 2019). It might be easier to use that than manually probe paths. Admittedly, I've only tried this on Windows.
  • The PowerShell Community Extensions (pscx) module has Import-VisualStudioVars that makes use of the VSSetup module and has support for the earlier versions of VS based on environment variables. That might also help.

And something for the blog article, maybe: if you're not using ConEmu, it appears the Windows system hijacks DarkMagenta to mean "transparent" so the VS environment bit ends up showing with no background.

@tillig
Copy link

tillig commented Mar 14, 2019

Potential enhancement for showing the current dotnet SDK version:

  # Write the current dotnet version.
  if ((Get-Command "dotnet" -ErrorAction Ignore) -ne $null) {
    $dotnetVersion = (& dotnet --version 2> $null)
    Write-Host " " -NoNewLine
    Write-Host "" -NoNewLine -BackgroundColor Gray -ForegroundColor Blue
    Write-Host " $dotnetVersion " -NoNewLine -BackgroundColor Gray -ForegroundColor Black
  }

Also, I found I could fairly consistently shave about 40 - 100ms off the rendering of the prompt by running the external commands (kubectl, sed, dotnet, etc.) in parallel using PowerShell runspaces. It makes the script more complicated since you have to separate the retrieval of the data from the rendering of the data, but the prompt feels a little faster. Like:

  $dotnetScript = {
    # Get the current dotnet version.
    $dotnetVersion = $null
    if ((Get-Command "dotnet" -ErrorAction Ignore) -ne $null) {
      $dotnetVersion = (& dotnet --version 2> $null)
    }
    return $dotnetVersion
  }

  $kubectlScript = {
    # Get the current kubectl context.
    $currentContext = $null
    if ((Get-Command "kubectl" -ErrorAction Ignore) -ne $null) {
      $currentContext = (& kubectl config current-context 2> $null)
    }
    return $currentContext
  }

  $azureScript = {
    # Get the current public cloud Azure CLI subscription.
    # NOTE: You will need sed from somewhere (for example, from Git for Windows).
    $currentAccount = $null
    $cloudConfigPath = Resolve-Path "~/.azure/clouds.config"
    if ((Test-Path $cloudConfigPath) -and ((Get-Command "sed" -ErrorAction Ignore) -ne $null)) {
      $currentSub = & sed -nr "/^\[AzureCloud\]/ { :l /^subscription[ ]*=/ { s/.*=[ ]*//; p; q;}; n; b l;}" "$($cloudConfigPath.Path)"
      if ($null -ne $currentSub) {
        $currentAccount = (Get-Content ~/.azure/azureProfile.json | ConvertFrom-Json).subscriptions | Where-Object { $_.id -eq $currentSub } | Select-Object -ExpandProperty Name
      }
    }
    return $currentAccount
  }

  # Create the set of jobs to run, each in a runspace. Not using RunspacePool
  # because there aren't a lot of jobs and it's really hard to set the current
  # working directory in a pool.
  $scripts = @{ "azure" = $azureScript; "dotnet" = $dotnetScript; "kubectl" = $kubectlScript }
  $jobs = @()

  foreach ($key in $scripts.Keys) {
    $thread = [powershell]::Create().AddScript($scripts[$key])
    $runspace = [RunspaceFactory]::CreateRunspace()
    $runspace.Open()
    $runspace.SessionStateProxy.Path.SetLocation($pwd.Path) | Out-Null
    $thread.Runspace = $runspace
    $handle = $thread.BeginInvoke()
    $jobs += @{ "Handle" = $handle; "Thread" = $thread; "Name" = $key }
  }

  while (@($jobs | Where-Object {$_.Handle.IsCompleted -ne $True}).count -gt 0) {
      Start-Sleep -Milliseconds 1
  }

  $scriptReturnValues = @{}
  foreach ($job in $jobs) {
    $scriptReturnValues.Add($job.Name, $job.Thread.EndInvoke($job.Handle))
    $job.Thread.Runspace.Close()
    $job.Thread.Dispose()
  }

  if ($scriptReturnValues["dotnet"] -ne $null) {
    Write-Host " " -NoNewLine
    Write-Host "" -NoNewLine -BackgroundColor Gray -ForegroundColor Blue
    Write-Host " $($scriptReturnValues['dotnet']) " -NoNewLine -BackgroundColor Gray -ForegroundColor Black
  }

  if ($scriptReturnValues["kubectl"] -ne $null) {
    Write-Host " " -NoNewLine
    Write-Host "" -NoNewLine -BackgroundColor DarkCyan -ForegroundColor Green
    Write-Host " $($scriptReturnValues['kubectl']) " -NoNewLine -BackgroundColor DarkCyan -ForegroundColor White
  }

  if ($scriptReturnValues["azure"] -ne $null) {
    Write-Host " " -NoNewLine
    Write-Host "" -NoNewLine -BackgroundColor DarkCyan -ForegroundColor Green
    Write-Host " $($scriptReturnValues['azure']) " -NoNewLine -BackgroundColor DarkCyan -ForegroundColor White
  }

I'm not using ConEmu so my glyphs aren't Nerd Font but you get the idea. I also can't guarantee I'm 100% handling all error conditions there so YMMV.

@bradwilson
Copy link
Author

Thanks for all these suggestions!

@thnk2wn
Copy link

thnk2wn commented Sep 17, 2019

Very nice! I had to add a small tweak to line 51 of vs.ps1 from $edition = $editions[0] to $edition = $editions[0].Name. From some contexts the value was the full path so it'd end up with C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\Common7\Tools\C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\Common7\Tools and bail as the path would't exist.

# If edition wasn't specified, see what's there, and bail out if there is more than 1
if ($edition -eq "") {
    $editions = (get-childitem $basePath | where-object { $_.PSIsContainer })
    if ($editions.Count -eq 0) {
        write-warning "Visual Studio $version is not installed."
        exit 1
    }
    if ($editions.Count -gt 1) {
        write-warning "Multiple editions of Visual Studio $version are installed. Please specify one of the editions ($($editions -join ', ')) with the -edition switch."
        exit 1
    }
    $edition = $editions[0].Name
}

@bradwilson
Copy link
Author

Thanks @thnk2wn, I also ran cross this recently, and I've updated the scripts!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment