Getting started - customize your prompt

Sun, Jun 12, 2005 4-minute read

Ok, so I’ve talked about how great the Monad language, and command-line interface is. I’ve also said that it changes the way you think about the command line.

How so?

Well, let’s play with the shell for a bit. If you haven’t already downloaded it, you can get it from BetaPlace:

  1. Go to http://beta.microsoft.com
  2. Log in using the guest ID, mshPDC
  3. Follow the download directions

Launch the shell, and you’re greeted with the friendly prompt:

MSH>

Friendly, but not as useful as it could be. Monad defines its prompt via the “prompt” function. Let’s create one. Oh, and let’s make it have the current directory in it. But how do we get that? One of the important commands to help you spelunk through Monad is is called “get-command.” Monad commands are always in the form of [verb]-[noun]. You always perform an action (verb) on something (noun.) Now, back to our goal:

MSH>get-command *directory*

Searching by the verb didn’t help much, let’s try a noun:

MSH> get-command get-*

Several items look promising. Specifically, get-location.

MSH>get-location
Drive Provider ProviderPath Path
----- -------- ------------ ----
C System.Managemen... C:\Documents and... C:\Documents and...

That looks like what we want. Remember when I mentioned that Monad was object-based? Well here’s an example of where we get to use that functionality. Here we go:

MSH>$location = get-location
MSH>$location.Path
C:\Documents and Settings\Lee

Ahh, that’s exactly what we want. We’ve stored the results of get-location into a variable, and then accessed its Path property. The two steps aren’t actually required, so we’ll shorten them to:

MSH>(get-location).Path
C:\Documents and Settings\Lee

Here’s another fun example – find out how many ‘get-*’ commands Monad has. The get-command call returns a list, so you can determine its size using the ‘Count’ property:

MSH>(get-command get-*).Count
29

Perfect. Notice that we haven’t ever had to do things like “echo”, or use the command “write-host.” This is because the commands we call generate objects. When your command generates an object, it flows to the next stage in your command. This sequence of commands that you specify (separated by a | symbol,) is called a pipeline. The output of one becomes the input of the next. Since we haven’t specified any additional stages, the Monad shell ultimately ouputs the final one to the default “sink” – out-host. The out-host command tries its best to format its input suitable for display. So, the implied command is:

MSH>(get-location).Path | out-host
C:\Documents and Settings\Lee

Now, back to our goal of customizing the prompt. As I mentioned earlier, you customize your prompt by defining a function called “prompt.” How do I know? Try “get-command *prompt*”

MSH>function prompt { "New MSH Prompt>" }
New MSH Prompt>

Your prompt function simply emits a string, which the MSH host knows to output. But, we don’t want it to say “New MSH Prompt,” we want it to output the current directory (err, location):

New MSH Prompt>function prompt { "MSH " + (get-location).Path + ">" }
MSH C:\Documents and Settings\Lee>

Defining it this way will not persist between console sessions, though. To make your changes permanent add the prompt function to your MSH profile, “profile.msh.” The default profile is actually nice enough the define a helpful variable called “$profile”:

MSH C:\Documents and Settings\Lee>notepad $profile

Notepad pops up with your current profile. Investigate it a bit, to see what it does. You don’t have to understand it all, but it does give you an idea of some features that Monad supports. When you’re done investigating, add your prompt function to the file, then save it. I’ll put mine as the first thing after the copyright header:

...
# PARTICULAR PURPOSE
#
function prompt { "MSH " + (get-location).Path + ">" }
# If you set the environmental variable DebugMSH to 1, all script executions
...

Now, close your shell, reopen it, and enjoy your new prompt. However, we can make it even better.

Command-line interfaces have long supported a facility to let you interact with your console history. A lot of Unix geeks like to have their prompt display their current history line number. That’s for two reasons. First, it lets you invoke a previous command by its history ID. Second, it somehow ties in with our freakish obsession with uptime. It’ll look like this:

MSH:1337 C:\Documents and Settings\Lee>

We’ll cover it next time, but see if you can beat me to it.

[Edit: Updated .Length to .Count, as .Count is the standard!]

[Edit: Monad has now been renamed to Windows PowerShell. This script or discussion may require slight adjustments before it applies directly to newer builds.]