ListReader.psm1
|
function Get-ListValue { <# .SYNOPSIS Access an item from the list of data prepared to iterate over. .DESCRIPTION Access an item from the list of data prepared to iterate over. Use "Start-ListReader" to prepare a list for iteration. .PARAMETER Index The index position of the item to retrieve. .PARAMETER Properties The sub-properties to access on the item selected. Can be multiple properties, in which case they will be considered nested sub-properties in the same order. E.g.: If you provide "LastWriteTime","Year", it will access the "LastWriteTime" property on the index item, then access the "Year" property on the result from that. .EXAMPLE PS C:\> Get-ListValue -Index 0 Retrieve the first item of the list. .EXAMPLE PS C:\> Get-ListValue -Index 2 -Properties changed Retrieve the third item of the list and directly access the sub-property "changed" #> [Alias('L')] [CmdletBinding()] param ( [Parameter(Position = 0)] [int[]] $Index = $script:__LR_Config.Index, [Parameter(Position = 1)] [AllowEmptyCollection()] [string[]] $Properties = $script:__LR_Config.TempProperties ) if (-not $script:__LR_Config.List) { return } foreach ($indexItem in $Index) { if ($indexItem -ge @($script:__LR_Config.List).Count) { Write-Warning "Index specified exceeds total number of items: $indexItem specified, number of items: $(@($script:__LR_Config.List).Count)" } $item = $script:__LR_Config.List[$indexItem] if ($script:__LR_Config.Event) { try { & $script:__LR_Config.Event $item } catch { Write-Warning "Error processing list-item event: $_"} } if ($script:__LR_Config.Property) { foreach ($property in $script:__LR_Config.Property) { $item = $item.$property } } foreach ($property in $Properties) { $item = $item.$property } $item } $script:__LR_Config.Index = 0 $script:__LR_Config.TempProperties = @() } function Register-ListHandler { <# .SYNOPSIS Registers the shortcut for list iteration. .DESCRIPTION Registers the shortcut for list iteration. This hijacks the "CommandNotFoundAction" event to resolve the following kinds of notations: + L0 --> Get-ListValue -Value 0 + l-1 --> Get-ListValue -Value -1 + L2.LastWriteTime --> Get-ListValue -Value 2 -Properties LastWriteTime + L2.LastWriteTime.Year --> Get-ListValue -Value 2 -Properties LastWriteTime, Year Runnning this command explicitly is optional, Start-ListReader already calls it for you. .EXAMPLE PS C:\> Register-ListHandler Registers the shortcut for list iteration. #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidAssignmentToAutomaticVariable", "")] [CmdletBinding()] param () $ExecutionContext.InvokeCommand.CommandNotFoundAction = { Param ($Name, $EventArgs) if ($Name.Trim('.\') -notmatch '^L(?<id>\-{0,1}\d+)([\.\w+]*)$') { return } $properties = @() if ($matches.1) { $properties = ($matches.1).Trim(".").Split(".") } Set-ListReaderIndex -Index $matches.id -Properties $properties $EventArgs.Command = Get-Command Get-ListValue $EventArgs.StopSearch = $true } } function Set-ListReaderIndex { <# .SYNOPSIS Applies the parameters chosen by the user during the list handler event. .DESCRIPTION Applies the parameters chosen by the user during the list handler event. When using the shortcut notation like "L0" or "L12" to access the list reader, this is enabled through the event handler, that injects itself into the event, that triggers when PowerShell cannot find a command. Problem here: This can only resolve the command, but not its parameters. This is resolved by using this command: The resolving event executes command to store the last picked index & properties, so that the command can use them. .PARAMETER Index The index of the item to look at. .PARAMETER Properties The sub-properties to select. .EXAMPLE PS C:\> Set-ListReaderIndex -Index 0 -Properties Year Sets the first item on the list to be selected, and requests the sub-property "Year" #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")] [CmdletBinding()] param ( [int] $Index, [string[]] $Properties ) process { $script:__LR_Config.Index = $Index $script:__LR_Config.TempProperties = $Properties } } function Start-ListReader { <# .SYNOPSIS Defines the list of values to read through. .DESCRIPTION Defines the list of values to read through. This starts the whole list reader system. Once this has been completed, you can for example use "L0" to access the first item, "L2" to access the third. .PARAMETER List The list of values to read .PARAMETER Property A property to retrieve, rather than just the base object. Supports a list of properties to look into nested sub-properties. .PARAMETER EventCode An event that is executed for each item iterated over. Allows arbitrary actions, but is intended for adding information to the user, e.g. via Write-Host Receives the full item (no pre-selected sub-properties). .EXAMPLE PS C:\> Start-ListReader -List $data Prepares the content of $data for manual iteration .EXAMPLE PS C:\> Start-ListReader -List $data -Property changed Prepares the content of $data for manual iteration, always directlyy accessing the content of the "changed" property. #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")] [CmdletBinding()] param ( [Parameter(Mandatory = $true)] $List, [string[]] $Property, [scriptblock] $EventCode ) Register-ListHandler $script:__LR_Config = @{ List = @($List) Property = $Property Index = 0 TempProperties = @() Event = $EventCode } } $script:__LR_Config = @{ List = $null Property = @() Index = 0 TempProperties = @() } |