Archives for January 2009

A PowerShell Prompt with a Purpose

Everybody has their own idea of what the perfect prompt in PowerShell consists of. My prompt is pretty boring, but it’s got one pretty unique feature – my prompt function doubles as a useful command!

You see, a lot of times I wind up in deep directories of solution and project folders in Visual Studio and I wind up with a prompt that barely fits on one line, or even worse, wraps. In this cases, I often only care about having a vague idea of where I am.

# sometimes I only want a little information about where I am. C:\Users\Josh Einstein\Documents\Visual Studio\Projects> Prompt -Minimize # sometimes I don’t care at all PS Projects> Prompt -Hide # if I need to bring it back to the way it was, I can just do this. PS> Prompt -Show C:\Users\Josh Einstein\Documents\Visual Studio\Projects>

This has really come in handy for me and it’s something you could easily do with a separate script or function in your profile. But I figured, hey the prompt function is already there right? What’s it gonna hurt if I add a few parameters to it?

############################################################################## #.SYNOPSIS # The all-important Prompt function called by PowerShell in order to display # the prompt, with an added twist using the built-in parameters. # #.DESCRIPTION # Customizing the prompt is common in PowerShell, but this function adds some # parameters to the function that enable some dynamic behavior. These # parameters will not affect the way PowerShell calls the function, but they # allow you to minimize or hide the prompt by passing switches. # #.PARAMETER Minimize # Shrinks the prompt so that it shows only the leaf portion of the current # provider path. Restore it using the -Show parameter. # #.PARAMETER Hide # Sets the prompt to an ultra-compact mode, displaying only an indicator, # and no information about the current location. # #.PARAMETER Show # Restores the prompt to it’s default mode which displays the full location # of the current provider path. # #.LINK # about_prompts # #.EXAMPLE # Prompt -Minimize # Prompt -Hide # Prompt -Show ############################################################################## function Prompt { [CmdletBinding(DefaultParameterSetName='Prompt')] param ( [Parameter(ParameterSetName='Minimize')] [Switch] $Minimize, [Parameter(ParameterSetName='Hide')] [Switch] $Hide, [Parameter(ParameterSetName='Show')] [Switch] $Show ) switch ( $PSCmdlet.ParameterSetName ) { Minimize { $Global:PromptVisibility = ‘Minimized’ } Hide { $Global:PromptVisibility = ‘Hidden’ } Show { $Global:PromptVisibility = ‘Default’ } Prompt { switch ( $PromptVisibility ) { Minimized { “PS $(Split-Path $PWD -Leaf)> ” } Hidden { “PS> ” } Default { “$PWD> ” } } } } }

Clever use of PowerShell syntax

One of the things I really like about PowerShell is how through the use of script blocks and locally scoped functions, you can create interesting script using perfectly valid, albeit odd looking PowerShell script. I had first done something like this without script blocks using the pipeline which was pretty ugly. It was mostly just a way of quickly building up objects using functions that wrapped New-Object and Add-Member.
New-PSObject | Field FirstName ‘Josh’ | Field LastName ‘Einstein’

That was pretty handy but as a C# guy it still looked ugly. I got the idea from Bruce Payette’s book, PowerShell in Action to use script blocks and locally-scoped functions so that I didn’t have to pollute the runspace with a bunch of functions that were only valid within the context of another function.
New-PSObject { Field FirstName ‘Josh’ Field LastName ‘Einstein’ Property FullName { “$($this.FirstName) $($this.LastName)” } Method SayHello { param($to) “$($this.FirstName) says ‘Hello’ to $to!” } }

How does it work? Well, like most things in PowerShell, functions have scope. So a function defined within another function is only valid during the execution of the outer function. This makes it possible to trample on existing functions and cmdlets too.

In Bruce Payette’s book he calls them “little languages”.

This technique allows for some really clean and concise syntax similar to how DSL’s are being used in .NET.

For my New-PSObject function, check out the Scripting module.