Powershell: Get-Location -Stack should return an array of path infos ( [System.Management.Automation.PathInfo[]]) rather than a scalar stack object [System.Management.Automation.PathInfoStack]

Created on 22 Aug 2017  路  7Comments  路  Source: PowerShell/PowerShell

Get-Location -Stack currently outputs a [System.Management.Automation.PathInfoStack] stack object rather than an array of [System.Management.Automation.PathInfo] instances representing the individual locations in the stack.

While this is behavior is documented, and changing it would technically be a breaking change, it should be considered for two reasons:

  • Outputting a custom stack object rather than an array of locations is of little benefit, given that location stacks are meant to be managed via the *-Location cmdlets.

    • Stack management support in these cmdlets currently lacks options for deleting / clearing a stack, but that is a separate issue - see #4643.

    • As an aside: While calling the .Clear() _method_ on the stack object may seem like a workaround for the current inability to clear a stack using cmdlets, it doesn't actually work (only clears the object returned, not the actual stack).

  • Outputting a custom stack object rather than an array of locations contravenes the expectation that a regular PowerShell array is output that can be indexed into, which doesn't work as intended with the stack object (.ToArray()[0] must be used, for instance).

    • The current default output certainly _looks_ like a _collection_ (array) of [System.Management.Automation.PathInfo] instances.

Current behavior

# Try to obtain the 2nd location from the bottom of the stack, which is "/"
> Push-Location /; Push-Location $HOME; (Get-Location -Stack)[-2]
# !! No output

Because Get-Location -Stack returns a _scalar_ - the stack object - indexing into the scalar with [-2] makes PowerShell return $null.

To make this work currently, .ToArray() must be used:

# Note the awkward .ToArray()
> Push-Location /; Push-Location $HOME; (Get-Location -Stack).ToArray()[-2]

Path
----
/   

Desired behavior

If a regular array is returned, indexing will work as expected.

> Push-Location /; Push-Location $HOME; (Get-Location -Stack)[-2]

Path
----
/   

Environment data

PowerShell Core v6.0.0-beta.5 on macOS 10.12.6
PowerShell Core v6.0.0-beta.5 on Ubuntu 16.04.3 LTS
PowerShell Core v6.0.0-beta.5 on Microsoft Windows 10 Pro (64-bit; v10.0.15063)
Windows PowerShell v5.1.15063.483 on Microsoft Windows 10 Pro (64-bit; v10.0.15063)
Area-Cmdlets-Management Hacktoberfest Issue-Enhancement

Most helpful comment

@AlanMcBee Welcome to pull the fix!
Github doesn't allow to explicitly assign you but the issue is now yours.

All 7 comments

To avoid a breaking change, I wonder if adding a -StackAsArray (or variant) may be viable?

I haven't done any research, but I'd be surprised if anyone relies on the existing behavior, given that the fact that a special collection object is returned is neither obvious nor useful.

Someone who did run into the inability to index with, say, (Get-Location -Stack)[-1] probably worked around that with (Get-Location -Stack) | Select-Object -Last 1 (note the parentheses), which will continue to work if the proposed change is made.

Workaround (Get-Location -Stack).ToArray()[-1], however, will cease to work, because .ToArray() is invariably applied to each _element_ of an array.

A quick search on GitHub says some people will be broken as they are using .ToArray() but the majority of uses is simply to get the count and that should continue to work.

Can we add ToArray() in PathInfo[] by ETS?

@iSazonov:

Great idea; we could do the C# equivalent of the following:

# Sample location-stack array.
# I suggest using a regular [object[]] array, as usual.
$a = 'one', 'two'

# Insert helper type name.
$a.pstypenames.insert(0, 'LocationStack')

# Add a .ToArray() method to the helper type, unless already defined.
if (-not $a.psobject.methods['ToArray']) {
  Update-TypeData -TypeName LocationStack -MemberType ScriptMethod -MemberName ToArray -Value { $this  }
}

We could use the same technique for adding a .Name property, which the current stack objects have.

I would like to do this, and maybe a couple of other things related to location stacks (as separate issues). Mind if I go at it? This will be my first contrib for this repo, but I'm reading the guideline and I think I can do this. I'm asking @PowerShellTeam (@powershell/powershell) for an assignment.

@AlanMcBee Welcome to pull the fix!
Github doesn't allow to explicitly assign you but the issue is now yours.

Was this page helpful?
0 / 5 - 0 ratings