Customizing PowerShell Prompt - Equivalent to CMD&

2020-06-27 09:02发布

问题:

I've started to "play around" with PowerShell and am trying to get it to "behave".

One of the things I'd like to do is to customize the PROMPT to be "similar" to what "$M$P$_$+$G" do on MS-Dos:

A quick rundown of what these do:

Character| Description
$m The remote name associated with the current drive letter or the empty string if current drive is not a network drive.
$p Current drive and path
$_ ENTER-LINEFEED
$+ Zero or more plus sign (+) characters depending upon the depth of the pushd directory stack, one character for each level pushed
$g > (greater-than sign)

So the final output is something like:

    \\spma1fp1\JARAVJ$ H:\temp
    ++>

I've been able to add the $M and $_ functionality (and a nifty History feature) to my prompt as follows:

function prompt
{
   ## Get the history. Since the history may be either empty,
   ## a single item or an array, the @() syntax ensures
   ## that PowerShell treats it as an array
   $history = @(get-history)


   ## If there are any items in the history, find out the
   ## Id of the final one.
   ## PowerShell defaults the $lastId variable to '0' if this
   ## code doesn't execute.
   if($history.Count -gt 0)
   {
      $lastItem = $history[$history.Count - 1]
      $lastId = $lastItem.Id
   }

   ## The command that we're currently entering on the prompt
   ## will be next in the history. Because of that, we'll
   ## take the last history Id and add one to it.
   $nextCommand = $lastId + 1

   ## Get the current location
   $currentDirectory = get-location

   ## Set the Windows Title to  the current location
   $host.ui.RawUI.WindowTitle = "PS: " + $currentDirectory

   ## And create a prompt that shows the command number,
   ## and current location
   "PS:$nextCommand $currentDirectory
>"
}

But the rest is not yet something I've managed to duplicate....

Thanks a lot for the tips that will surely come!

回答1:

See if this does what you want:

function prompt
{
   ## Get the history. Since the history may be either empty,
   ## a single item or an array, the @() syntax ensures
   ## that PowerShell treats it as an array
   $history = @(get-history)


   ## If there are any items in the history, find out the
   ## Id of the final one.
   ## PowerShell defaults the $lastId variable to '0' if this
   ## code doesn't execute.
   if($history.Count -gt 0)
   {
      $lastItem = $history[$history.Count - 1]
      $lastId = $lastItem.Id
   }

   ## The command that we're currently entering on the prompt
   ## will be next in the history. Because of that, we'll
   ## take the last history Id and add one to it.
   $nextCommand = $lastId + 1

   ## Get the current location
   $currentDirectory = get-location

   ## Set the Windows Title to  the current location
   $host.ui.RawUI.WindowTitle = "PS: " + $currentDirectory

   ##pushd info
   $pushdCount = $(get-location -stack).count
   $pushPrompt = ""
   for ($i=0; $i -lt $pushdCount; $i++)
   {
       $pushPrompt += "+"
    }

   ## And create a prompt that shows the command number,
   ## and current location
   "PS:$nextCommand $currentDirectory `n$($pushPrompt)>"
}


回答2:

This will get you the count of the locations on the pushd stack:

$(get-location -Stack).count


回答3:

Thanks to EBGReens's answer, my "prompt" is now capable of showing the depth of the stack:

 function prompt
 {
    ## Initialize vars
    $depth_string = ""

    ## Get the Stack -Pushd count
    $depth = (get-location -Stack).count

    ## Create a string that has $depth plus signs
    $depth_string = "+" * $depth

    ## Get the history. Since the history may be either empty,
    ## a single item or an array, the @() syntax ensures
    ## that PowerShell treats it as an array
    $history = @(get-history)


    ## If there are any items in the history, find out the
    ## Id of the final one.
    ## PowerShell defaults the $lastId variable to '0' if this
    ## code doesn't execute.
    if($history.Count -gt 0)
    {
       $lastItem = $history[$history.Count - 1]
       $lastId = $lastItem.Id
    }

    ## The command that we're currently entering on the prompt
    ## will be next in the history. Because of that, we'll
    ## take the last history Id and add one to it.
    $nextCommand = $lastId + 1

    ## Get the current location
    $currentDirectory = get-location

    ## Set the Windows Title to  the current location
    $host.ui.RawUI.WindowTitle = "PS: " + $currentDirectory

    ## And create a prompt that shows the command number,
    ## and current location
    "PS:$nextCommand $currentDirectory `n$($depth_string)>"
 }


回答4:

The following will give you the equivalent of $m.

$mydrive = $pwd.Drive.Name + ":";
$networkShare = (gwmi -class "Win32_MappedLogicalDisk" -filter "DeviceID = '$mydrive'");

if ($networkShare -ne $null)
{
    $networkPath = $networkShare.ProviderName
}


回答5:

Thanks to the tips in:

In PowerShell, how can I determine if the current drive is a networked drive or not?
In PowerShell, how can I determine the root of a drive (supposing it's a networked drive)

I've managed to get it working.

My full profile is:

function prompt
{
   ## Initialize vars
   $depth_string = ""

   ## Get the Stack -Pushd count
   $depth = (get-location -Stack).count

   ## Create a string that has $depth plus signs
   $depth_string = "+" * $depth

   ## Get the history. Since the history may be either empty,
   ## a single item or an array, the @() syntax ensures
   ## that PowerShell treats it as an array
   $history = @(get-history)


   ## If there are any items in the history, find out the
   ## Id of the final one.
   ## PowerShell defaults the $lastId variable to '0' if this
   ## code doesn't execute.
   if($history.Count -gt 0)
   {
      $lastItem = $history[$history.Count - 1]
      $lastId = $lastItem.Id
   }

   ## The command that we're currently entering on the prompt
   ## will be next in the history. Because of that, we'll
   ## take the last history Id and add one to it.
   $nextCommand = $lastId + 1

   ## Get the current location
   $currentDirectory = get-location

   ## Set the Windows Title to  the current location
   $host.ui.RawUI.WindowTitle = "PS: " + $currentDirectory

        ## Get the current location's DRIVE LETTER
        $drive = (get-item ($currentDirectory)).root.name

        ## Make sure we're using a path that is not already UNC
        if ($drive.IndexOf(":") -ne "-1")
            {
                $root_dir = (get-wmiobject Win32_LogicalDisk | ? {$_.deviceid -eq $drive.Trim("\") } | % { $_.providername })+" "
          }
          else
          {
            $root_dir=""
          }


   ## And create a prompt that shows the command number,
   ## and current location
   "PS:$nextCommand $root_dir$currentDirectory `n$($depth_string)>"
}