Posh.types.ps1xml
<?xml version="1.0" encoding="utf-16"?> <!-- Generated with EZOut 2.0.1: Install-Module EZOut or https://github.com/StartAutomating/EZOut --> <Types> <Type> <Name>Posh</Name> <Members> <AliasProperty> <Name>Error</Name> <ReferencedMemberName>Errors</ReferencedMemberName> </AliasProperty> <AliasProperty> <Name>Profile</Name> <ReferencedMemberName>Profiles</ReferencedMemberName> </AliasProperty> <AliasProperty> <Name>Recommend</Name> <ReferencedMemberName>Recommends</ReferencedMemberName> </AliasProperty> <ScriptProperty> <Name>Errors</Name> <GetScriptBlock> <# .SYNOPSIS Returns all errors .DESCRIPTION Returns all errors from the current session .EXAMPLE $Posh.Errors #> $global:Error </GetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>ExecutionContext</Name> <GetScriptBlock> $global:ExecutionContext </GetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>History</Name> <GetScriptBlock> <# .SYNOPSIS Gets the PowerShell History .DESCRIPTION Gets the history of commands run in this PowerShell session. .EXAMPLE $posh.History .LINK Get-History #> Get-History </GetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>Host</Name> <GetScriptBlock> <# .SYNOPSIS Gets the PowerShell Host .DESCRIPTION Gets the current PowerShell Host .EXAMPLE $posh.Host #> $global:host </GetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>Jobs</Name> <GetScriptBlock> <# .SYNOPSIS Gets PowerShell Jobs .DESCRIPTION Gets PowerShell Background Jobs .EXAMPLE $posh.Jobs .Link Get-Job .Link Start-Job #> Get-Job </GetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>Modules</Name> <GetScriptBlock> <# .SYNOPSIS Gets the loaded modules .DESCRIPTION Gets the PowerShell modules loaded in the current session. #> Get-Module </GetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>Process</Name> <GetScriptBlock> <# .SYNOPSIS Gets the PowerShell Process .DESCRIPTION Gets the process currently hosting PowerShell .EXAMPLE $posh.Process #> Get-Process -id $PID </GetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>Profiles</Name> <GetScriptBlock> $profile </GetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>Recommends</Name> <GetScriptBlock> foreach ($module in $posh.Modules) { $module.Recommendation } </GetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>Runspace</Name> <GetScriptBlock> <# .SYNOPSIS Gets the PowerShell Runspaces .DESCRIPTION Gets the current PowerShell Runspace. .EXAMPLE $posh.Runspace #> $host.Runspace </GetScriptBlock> </ScriptProperty> </Members> </Type> <Type> <Name>Posh.Commands</Name> <Members> <MemberSet> <Name>PSStandardMembers</Name> <Members> <PropertySet> <Name>DefaultDisplayPropertySet</Name> <ReferencedProperties> <Name>Count</Name> <Name>AliasCount</Name> <Name>ApplicationCount</Name> <Name>CmdletCount</Name> <Name>FunctionCount</Name> </ReferencedProperties> </PropertySet> </Members> </MemberSet> <AliasProperty> <Name>Aliases</Name> <ReferencedMemberName>Alias</ReferencedMemberName> </AliasProperty> <AliasProperty> <Name>Applications</Name> <ReferencedMemberName>Application</ReferencedMemberName> </AliasProperty> <AliasProperty> <Name>Cmdlets</Name> <ReferencedMemberName>Cmdlet</ReferencedMemberName> </AliasProperty> <AliasProperty> <Name>Functions</Name> <ReferencedMemberName>Function</ReferencedMemberName> </AliasProperty> <ScriptMethod> <Name>FindExtensions</Name> <Script> <# .SYNOPSIS .DESCRIPTION .EXAMPLE $posh.Commands.FindExtensions($posh, "$pwd") #> $targetModules = @() $targetPaths = @() $loadedModules = Get-Module foreach ($arg in $args) { if ($arg -is [Management.Automation.PSModuleInfo]) { $targetModules += $arg } elseif ($arg -is [IO.FileInfo] -or $arg -is [IO.DirectoryInfo]) { $targetPaths += $arg } elseif ($arg -is [Management.Automation.PathInfo]) { $targetPaths += "$arg" } elseif ($arg -is [string]) { $argIsModule = foreach ($module in $loadedModules) { if ($module.Name -like $arg) { $module}} if ($argIsModule) { $targetModules += $argIsModule } elseif (Test-Path $arg) { $targetPaths += $arg } } } if (-not $targetModules) { $targetModules = $posh.Modules} $Splat = @{} if ($targetPaths) { $Splat.FilePath = $targetPaths } foreach ($module in $targetModules) { # Aspect.ModuleExtendedCommand & { <# .SYNOPSIS Returns a module's extended commands .DESCRIPTION Returns the commands or scripts in a module that match the module command pattern. Each returned script will be decorated with the typename(s) that match, so that the extended commands can be augmented by the extended types system. .LINK Aspect.ModuleCommandPattern .EXAMPLE Aspect.ModuleExtensionCommand -Module PipeScript # Should -BeOfType ([Management.Automation.CommandInfo]) #> [Alias('Aspect.ModuleExtendedCommand')] param( # The name of a module, or a module info object. [Parameter(Mandatory,ValueFromPipelineByPropertyName)] [ValidateScript({ $validTypeList = [System.String],[System.Management.Automation.PSModuleInfo] $thisType = $_.GetType() $IsTypeOk = $(@( foreach ($validType in $validTypeList) { if ($_ -as $validType) { $true;break } })) if (-not $isTypeOk) { throw "Unexpected type '$(@($thisType)[0])'. Must be 'string','psmoduleinfo'." } return $true })] $Module, # A list of commands. # If this is provided, each command that is a valid extension will be returned. [Parameter(ValueFromPipelineByPropertyName)] [Management.Automation.CommandInfo[]] $Commands, # The suffix to apply to each named capture. # Defaults to '_Command' [Parameter(ValueFromPipelineByPropertyName)] [string] $Suffix = '_Command', # The prefix to apply to each named capture. [Parameter(ValueFromPipelineByPropertyName)] [string] $Prefix, # The file path(s). If provided, will look for commands within these paths. [Parameter(ValueFromPipelineByPropertyName)] [Alias('Fullname')] $FilePath, # The PowerShell command type. If this is provided, will only get commands of this type. [Parameter(ValueFromPipelineByPropertyName)] [Management.Automation.CommandTypes] $CommandType, # The base PSTypeName(s). # If provided, any commands that match the pattern will apply these typenames, too. [string[]] $PSTypeName ) process { if ($Module -is [string]) { $Module = Get-Module $Module } $ModuleInfo = $module if (-not $ModuleInfo) { return } $ModuleCommandPattern = # Aspect.ModuleExtensionPattern & { <# .SYNOPSIS Outputs a module's extension pattern .DESCRIPTION Outputs a regular expression that will match any possible pattern. .EXAMPLE Aspect.ModuleCommandPattern -Module PipeScript # Should -BeOfType ([Regex]) #> [Alias('Aspect.ModuleCommandPattern')] param( # The name of a module, or a module info object. [Parameter(Mandatory,ValueFromPipelineByPropertyName)] [ValidateScript({ $validTypeList = [System.String],[System.Management.Automation.PSModuleInfo] $thisType = $_.GetType() $IsTypeOk = $(@( foreach ($validType in $validTypeList) { if ($_ -as $validType) { $true;break } })) if (-not $isTypeOk) { throw "Unexpected type '$(@($thisType)[0])'. Must be 'string','psmoduleinfo'." } return $true })] $Module, # The suffix to apply to each named capture. # Defaults to '_Command' [Parameter(ValueFromPipelineByPropertyName)] [string] $Suffix = '_Command', # The prefix to apply to each named capture. [Parameter(ValueFromPipelineByPropertyName)] [string] $Prefix ) process { if ($Module -is [string]) { $Module = Get-Module $Module } $ModuleInfo = $module #region Search for Module Extension Types if (-not $ModuleInfo) { return } $ModuleExtensionTypes = # Aspect.ModuleExtensionTypes & { <# .SYNOPSIS Outputs a module's extension types .DESCRIPTION Outputs the extension types defined in a module's manifest. .EXAMPLE # Outputs a PSObject with information about extension command types. # The two primary pieces of information are the `.Name` and `.Pattern`. Aspect.ModuleExtensionType -Module PipeScript # Should -BeOfType ([PSObject]) #> [Alias('Aspect.ModuleCommandTypes','Aspect.ModuleCommandType','Aspect.ModuleExtensionTypes')] param( # The name of a module, or a module info object. [Parameter(Mandatory,ValueFromPipelineByPropertyName)] [ValidateScript({ $validTypeList = [System.String],[System.Management.Automation.PSModuleInfo] $thisType = $_.GetType() $IsTypeOk = $(@( foreach ($validType in $validTypeList) { if ($_ -as $validType) { $true;break } })) if (-not $isTypeOk) { throw "Unexpected type '$(@($thisType)[0])'. Must be 'string','psmoduleinfo'." } return $true })] $Module ) begin { $ExtensionCollectionNames = "Extension", "Command", "Cmdlet", "Function", "Alias", "Script", "Application", "File","Configuration" $ExtensionCollectionNames = @($ExtensionCollectionNames -replace '.+$','${0}Type') + @($ExtensionCollectionNames -replace '.+$','${0}Types') } process { #region Resolve Module Info if ($Module -is [string]) { $Module = Get-Module $Module } $ModuleInfo = $module if (-not $ModuleInfo) { return } #endregion Resolve Module Info #region Check Cache and Hopefully Return if (-not $script:ModuleExtensionTypeCache) { $script:ModuleExtensionTypeCache = @{} } if ($script:ModuleExtensionTypeCache[$ModuleInfo]) { return $script:ModuleExtensionTypeCache[$ModuleInfo] } #endregion Check Cache and Hopefully Return #region Find Extension Types $modulePrivateData = $ModuleInfo.PrivateData $SortedExtensionTypes = [Ordered]@{} foreach ($TypeOfExtensionCollection in $ExtensionCollectionNames) { $moduleExtensionTypes = if ($modulePrivateData.$TypeOfExtensionCollection) { $modulePrivateData.$TypeOfExtensionCollection } elseif ($modulePrivateData.PSData.$TypeOfExtensionCollection) { $modulePrivateData.PSData.$TypeOfExtensionCollection } else { $null } if (-not $moduleExtensionTypes) { continue } foreach ($commandType in @($ModuleExtensionTypes.GetEnumerator() | Sort-Object Key)) { if ($commandType.Value -is [Collections.IDictionary]) { if (-not $commandType.Value.Name) { $commandType.Value["Name"] = $commandType.Key } if (-not $commandType.Value.PSTypeName) { $commandType.Value["PSTypeName"] = "$($module.Name).ExtensionCommandType" } $SortedExtensionTypes[$commandType.Name] = $commandType.Value } else { $SortedExtensionTypes[$commandType.Name] = [Ordered]@{ PSTypeName = "$($module.Name).ExtensionCommandType" Name = $commandType.Key Pattern = $commandType.Value } } if ($TypeOfExtensionCollection -notmatch '(?>Extension|Command|Cmdlet)') { $SortedExtensionTypes[$commandType.Name].CommandType = $TypeOfExtensionCollection -replace 'Type(?:s)?$' } elseif ($TypeOfExtensionCollection -match 'Cmdlet') { $SortedExtensionTypes[$commandType.Name].CommandType = "(?>Alias|Function|Filter|Cmdlet)" } } } $SortedExtensionTypes.PSTypeName="$($Module.Name).ExtensionCommandTypes" $script:ModuleExtensionTypeCache[$ModuleInfo] = [PSCustomObject]$SortedExtensionTypes $script:ModuleExtensionTypeCache[$ModuleInfo] #endregion Find Extension Types } } -Module $moduleInfo if (-not $ModuleExtensionTypes) { return } # With some clever understanding of Regular expressions, we can make match any/all of our potential command types. # Essentially: Regular Expressions can look ahead (matching without changing the position), and be optional. # So we can say "any/all" by making a series of optional lookaheads. # We'll go thru each pattern in order $combinedRegex = @(foreach ($categoryExtensionTypeInfo in @($ModuleExtensionTypes.psobject.properties)) { $categoryPattern = $categoryExtensionTypeInfo.Value.Pattern # ( and skip anyone that does not have a pattern) if (-not $categoryPattern) { continue } '(?=' + # Start a lookahead '.{0,}' + # match any or no characters # followed by the command pattern "(?<$Prefix$($categoryExtensionTypeInfo.Name -replace '\p{P}', '_')$Suffix>$categoryPattern)" + ')?' # made optional }) -join [Environment]::NewLine # Now that we've combined the whole thing, make it a Regex and output it. [Regex]::new("$combinedRegex", 'IgnoreCase,IgnorePatternWhitespace','00:00:01') } } $ModuleInfo -Prefix $prefix -Suffix $Suffix $ModuleCommandTypes = # Aspect.ModuleExtensionType & { <# .SYNOPSIS Outputs a module's extension types .DESCRIPTION Outputs the extension types defined in a module's manifest. .EXAMPLE # Outputs a PSObject with information about extension command types. # The two primary pieces of information are the `.Name` and `.Pattern`. Aspect.ModuleExtensionType -Module PipeScript # Should -BeOfType ([PSObject]) #> [Alias('Aspect.ModuleCommandTypes','Aspect.ModuleCommandType','Aspect.ModuleExtensionTypes')] param( # The name of a module, or a module info object. [Parameter(Mandatory,ValueFromPipelineByPropertyName)] [ValidateScript({ $validTypeList = [System.String],[System.Management.Automation.PSModuleInfo] $thisType = $_.GetType() $IsTypeOk = $(@( foreach ($validType in $validTypeList) { if ($_ -as $validType) { $true;break } })) if (-not $isTypeOk) { throw "Unexpected type '$(@($thisType)[0])'. Must be 'string','psmoduleinfo'." } return $true })] $Module ) begin { $ExtensionCollectionNames = "Extension", "Command", "Cmdlet", "Function", "Alias", "Script", "Application", "File","Configuration" $ExtensionCollectionNames = @($ExtensionCollectionNames -replace '.+$','${0}Type') + @($ExtensionCollectionNames -replace '.+$','${0}Types') } process { #region Resolve Module Info if ($Module -is [string]) { $Module = Get-Module $Module } $ModuleInfo = $module if (-not $ModuleInfo) { return } #endregion Resolve Module Info #region Check Cache and Hopefully Return if (-not $script:ModuleExtensionTypeCache) { $script:ModuleExtensionTypeCache = @{} } if ($script:ModuleExtensionTypeCache[$ModuleInfo]) { return $script:ModuleExtensionTypeCache[$ModuleInfo] } #endregion Check Cache and Hopefully Return #region Find Extension Types $modulePrivateData = $ModuleInfo.PrivateData $SortedExtensionTypes = [Ordered]@{} foreach ($TypeOfExtensionCollection in $ExtensionCollectionNames) { $moduleExtensionTypes = if ($modulePrivateData.$TypeOfExtensionCollection) { $modulePrivateData.$TypeOfExtensionCollection } elseif ($modulePrivateData.PSData.$TypeOfExtensionCollection) { $modulePrivateData.PSData.$TypeOfExtensionCollection } else { $null } if (-not $moduleExtensionTypes) { continue } foreach ($commandType in @($ModuleExtensionTypes.GetEnumerator() | Sort-Object Key)) { if ($commandType.Value -is [Collections.IDictionary]) { if (-not $commandType.Value.Name) { $commandType.Value["Name"] = $commandType.Key } if (-not $commandType.Value.PSTypeName) { $commandType.Value["PSTypeName"] = "$($module.Name).ExtensionCommandType" } $SortedExtensionTypes[$commandType.Name] = $commandType.Value } else { $SortedExtensionTypes[$commandType.Name] = [Ordered]@{ PSTypeName = "$($module.Name).ExtensionCommandType" Name = $commandType.Key Pattern = $commandType.Value } } if ($TypeOfExtensionCollection -notmatch '(?>Extension|Command|Cmdlet)') { $SortedExtensionTypes[$commandType.Name].CommandType = $TypeOfExtensionCollection -replace 'Type(?:s)?$' } elseif ($TypeOfExtensionCollection -match 'Cmdlet') { $SortedExtensionTypes[$commandType.Name].CommandType = "(?>Alias|Function|Filter|Cmdlet)" } } } $SortedExtensionTypes.PSTypeName="$($Module.Name).ExtensionCommandTypes" $script:ModuleExtensionTypeCache[$ModuleInfo] = [PSCustomObject]$SortedExtensionTypes $script:ModuleExtensionTypeCache[$ModuleInfo] #endregion Find Extension Types } } $ModuleInfo $commands = @( if ($PSBoundParameters['Commands']) { $commands } elseif ($PSBoundParameters['FilePath']) { if (-not $commandType) { $commandType = 'Application,ExternalScript' } foreach ($file in Get-ChildItem -File -Path $PSBoundParameters['FilePath'] -Recurse) { $ExecutionContext.SessionState.InvokeCommand.GetCommand($file.FullName, $commandType) } } else { if (-not $CommandType) { $commandType = 'Function,Alias,Filter,Cmdlet' } $ExecutionContext.SessionState.InvokeCommand.GetCommands('*', $commandType, $true) }) :nextCommand foreach ($cmd in $commands) { $matched = $ModuleCommandPattern.Match("$cmd") if (-not $matched.Success) { continue } $NamedGroupMatch = $false :nextCommandType foreach ($group in $matched.Groups) { if (-not $group.Success) { continue } if ($null -ne ($group.Name -as [int])) { continue } $CommandTypeName = $group.Name.Replace('_','.') $ThisCommandsType = $ModuleCommandTypes.($group.Name -replace "^$prefix" -replace "$suffix$") if ($ThisCommandsType) { $ThisTypeFilter = @($ThisCommandsType.CommandType,$ThisCommandsType.CommandTypes -ne $null)[0] if ($ThisTypeFilter -and ($cmd.CommandType -notmatch $ThisTypeFilter)) { continue nextCommandType } $ThisExcludeFilter = @($ThisCommandsType.ExcludeCommandType,$ThisCommandsType.ExcludeCommandTypes -ne $null)[0] if ($ThisExcludeFilter -and ($cmd.CommandType -match $ThisExcludeFilter)) { continue nextCommandType } } $NamedGroupMatch = $true if ($PSTypeName) { foreach ($psuedoType in $PSTypeName) { if ($cmd.pstypenames -notcontains $psuedoType) { $cmd.pstypenames.insert(0, $psuedoType) } } } if ($cmd.pstypenames -notcontains $CommandTypeName) { $cmd.pstypenames.insert(0, $CommandTypeName) } } if ($NamedGroupMatch) { $cmd } } } } -Module $module @Splat } </Script> </ScriptMethod> <ScriptProperty> <Name>AliasCount</Name> <GetScriptBlock> @($this.Alias).Count </GetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>ApplicationCount</Name> <GetScriptBlock> @($this.Application).Count </GetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>CmdletCount</Name> <GetScriptBlock> @($this.Alias).Count </GetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>Count</Name> <GetScriptBlock> @($this.All).Count </GetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>Extended</Name> <GetScriptBlock> $this.FindExtensions() </GetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>FunctionCount</Name> <GetScriptBlock> @($this.Function).Count </GetScriptBlock> </ScriptProperty> <NoteProperty> <Name>DefaultDisplay</Name> <Value>Count AliasCount ApplicationCount CmdletCount FunctionCount</Value> </NoteProperty> </Members> </Type> <Type> <Name>Posh.Errors</Name> <Members> <ScriptMethod> <Name>LineLike</Name> <Script> <# .SYNOPSIS Filters errors by line wildcard .DESCRIPTION Filters entries in $Error for items that a .Line like a wildcard. .EXAMPLE $error.LineLike("Get-*") #> param( # A wildcard pattern. [string] $Like ) ,@(foreach ($err in $this) { if ($err.InvocationInfo.Line -like $Like) { $err } }) </Script> </ScriptMethod> <ScriptMethod> <Name>LineMatch</Name> <Script> <# .SYNOPSIS Filters errors by command pattern .DESCRIPTION Filters entries in $Error for items that have a .CommandLine matching the pattern. .EXAMPLE $error.LineMatc("^Get") #> param( # A regular expression. $Match ) ,@(foreach ($err in $this) { if ($err.InvocationInfo.Line -match $match) { $err } }) </Script> </ScriptMethod> <ScriptProperty> <Name>ByLine</Name> <GetScriptBlock> <# .SYNOPSIS Gets errors by line .DESCRIPTION Gets all lines that produced errors .EXAMPLE $error.ByLine #> $errorsByLine = [Collections.Generic.Dictionary[ string, [Collections.Generic.List[psobject]] ]]::new([System.StringComparer]::OrdinalIgnoreCase) foreach ($err in $this) { $errLine = $err.InvocationInfo.Line if (-not $errLine) { continue } if (-not $errorsByLine[$errLine]) { $errorsByLine[$errLine] = [Collections.Generic.List[psobject]]::new() } $null = $errorsByLine[$errLine].Add($err) } $errorsByLine </GetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>ByType</Name> <GetScriptBlock> <# .SYNOPSIS Gets Errors By Type .DESCRIPTION Returns all errors, by type of error. .EXAMPLE $posh.Errors.ByType #> $errorsByType = [Collections.Generic.Dictionary[ type, [Collections.Generic.List[psobject]] ]]::new() foreach ($err in $this) { $exceptionType = if ($err.Exception) { $err.Exception.GetType() } else { $err.GetType() } if (-not $errorsByType[$exceptionType]) { $errorsByType[$exceptionType] = [Collections.Generic.List[psobject]]::new() } $null = $errorsByType[$exceptionType].Add($err) } $errorsByType </GetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>History</Name> <GetScriptBlock> <# .SYNOPSIS Gets Error History .DESCRIPTION Gets the history items associated with PowerShell Errors .EXAMPLE $Error.History #> $historyIDS = @(foreach ($err in $this) { if ($err.InvocationInfo.HistoryId -gt 0) { $err.InvocationInfo.HistoryId } }) Get-History -Id $historyIDS </GetScriptBlock> </ScriptProperty> </Members> </Type> <Type> <Name>Posh.ExtensionCollection</Name> <Members> <ScriptMethod> <Name>Refresh</Name> <Script> $this | Add-Member NoteProperty '.Cache' @() -Force </Script> </ScriptMethod> <ScriptProperty> <Name>All</Name> <GetScriptBlock> <# .SYNOPSIS Gets all items in an extension collection. .DESCRIPTION Gets all items in a collection of extended commands. #> if (-not $this.'.Cache') { if (-not $this.'.Module') { return @() } $findExtensionArgs = @($this.'.Module') + @($this.'.Path') $allExtensionsFound = @(:nextExtension foreach ($foundExtension in $posh.Commands.FindExtensions.Invoke($findExtensionArgs) ) { if ($this.'.CommandType') { foreach ($typename in $this.'.CommandType') { if ($foundExtension.pstypenames -contains $typename) { $foundExtension continue nextExtension } } } else { $foundExtension } } ) $this | Add-Member NoteProperty '.Cache' $allExtensionsFound -Force } return $this.'.Cache' </GetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>CommandType</Name> <GetScriptBlock> <# .SYNOPSIS Gets an extension collection's CommandType .DESCRIPTION Gets the extended CommandTypes(s) that are stored in an extension collection. CommandTypes can be defined in a module's manifest. #> return $this.'.CommandType' </GetScriptBlock> <SetScriptBlock> <# .SYNOPSIS Sets an extension collection's command type .DESCRIPTION Sets the extended command types in an extension collection. #> param( # The path. If this is empty all extended commands will be present in the collection [string[]] $CommandType ) Add-Member -InputObject $this -MemberType NoteProperty -Name '.CommandType' -Value $CommandType -Force </SetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>Count</Name> <GetScriptBlock> <# .SYNOPSIS Gets the extension count. .DESCRIPTION Gets the count of all extensions in a collection. #> $this.All.Length </GetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>Module</Name> <GetScriptBlock> <# .SYNOPSIS Gets an extension collection's module .DESCRIPTION Gets the module that defines extended types in an extension collection. #> return $this.'.Module' </GetScriptBlock> <SetScriptBlock> <# .SYNOPSIS Sets an extension collection's module .DESCRIPTION Sets the module that defines extended command types in an extension collection. #> param( # The module. [Management.Automation.PSModuleInfo] $Module ) Add-Member -InputObject $this -MemberType NoteProperty -Name '.Module' -Value $module -Force </SetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>Path</Name> <GetScriptBlock> <# .SYNOPSIS Gets an extension collection's Path .DESCRIPTION Gets the Path(s) that store extensions in an extension collection. #> return $this.'.Path' </GetScriptBlock> <SetScriptBlock> <# .SYNOPSIS Sets an extension collection's path .DESCRIPTION Sets the path that defines extended command types in an extension collection. #> param( # The path. If this is empty, only extensions that are functions or aliases will be found. [string[]] $Path ) Add-Member -InputObject $this -MemberType NoteProperty -Name '.Path' -Value $Path -Force </SetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>Random</Name> <GetScriptBlock> <# .SYNOPSIS Gets a random extended command .DESCRIPTION Gets a random extended command from an ExtensionCollection. #> $this.All | Get-Random </GetScriptBlock> </ScriptProperty> </Members> </Type> <Type> <Name>Posh.Host</Name> <Members> <ScriptMethod> <Name>Choose</Name> <Script> <# .SYNOPSIS Prompts a choice .DESCRIPTION Prompts a choice between multiple options. An option can be a string, hashtable, or scriptblock. Hashtables keys and arrays will become a list of possible choices. Strings will be outputted as a message. A boolean will indicate multiple items can be chosen. .Example $Posh.Host.Choose( "Cake Or Death?", @("Cake", "Death") ) #> param() $captionAndMessage = @() $choiceList = @() $defaultChoices = @() $multiselect = $false foreach ($argument in $args) { if ($argument -is [string]) { $captionAndMessage += $argument } if ($argument -is [bool] -and $argument) { $multiselect = $true } if ($argument -is [Collections.IDictionary]) { if ($argument -is [hashtable]) { $choiceList += @($argument.GetEnumerator() | Sort-Object Key).Key } else { $choiceList += @($argument.GetEnumerator()).Key } } elseif ($argument -is [object[]]) { if ($argument -as [int[]]) { $defaultChoices += $argument } else { $choiceList += $argument } } } $choiceList = @( foreach ($potentialChoice in $choiceList) { [Management.Automation.Host.ChoiceDescription]::new("$potentialChoice") } ) if (-not $choiceList) { return } $caption, $message = $captionAndMessage if ($defaultChoices) { if (-not $multiselect) { $defaultChoices = $defaultChoices[0] $choice = $host.UI.PromptForChoice($caption, $message, $choiceList, $defaultChoices) } else { $choice = $host.UI.PromptForChoice($caption, $message, $choiceList, $defaultChoices) } } else { $choice = if ($multiselect) { $host.UI.PromptForChoice($caption, $message, $choiceList, [int[]]@(0)) } else { $host.UI.PromptForChoice($caption, $message, $choiceList, 0) } } if ($choice -ne -1) { $choiceList[$choice].Label } </Script> </ScriptMethod> <ScriptProperty> <Name>Cursor</Name> <GetScriptBlock> <# .SYNOPSIS Gets the cursor .DESCRIPTION Gets the console cursor. .EXAMPLE $Host.Cursor .EXAMPLE $Posh.Host.Cursor .EXAMPLE $Posh.Cursor.Position #> return ([PSCustomObject]@{PSTypeName='Posh.Host.Cursor'}) </GetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>Height</Name> <GetScriptBlock> <# .SYNOPSIS Gets the height of the host .DESCRIPTION Gets the height of the host (in characters). .EXAMPLE $posh.Host.Height .EXAMPLE $Host.Height #> $this.UI.RawUI.BufferSize.Height </GetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>Title</Name> <GetScriptBlock> <# .SYNOPSIS Gets the host's title .DESCRIPTION Gets the host's window title. .EXAMPLE $Posh.Title #> $this.UI.RawUI.WindowTitle </GetScriptBlock> <SetScriptBlock> <# .SYNOPSIS Sets the host's title .DESCRIPTION Sets the host's window title. Unfortunately, this will be ignored if running in Visual Studio Code. .EXAMPLE $Posh.Title = "Sup?" #> param( [string] $Title ) $this.UI.RawUI.WindowTitle = $title </SetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>Width</Name> <GetScriptBlock> <# .SYNOPSIS Gets the Width of the host .DESCRIPTION Gets the Width of the host (in characters). .EXAMPLE $posh.Host.Width .EXAMPLE $Host.Width #> $this.UI.RawUI.BufferSize.Width </GetScriptBlock> </ScriptProperty> </Members> </Type> <Type> <Name>Posh.Host.Cursor</Name> <Members> <AliasProperty> <Name>Left</Name> <ReferencedMemberName>Back</ReferencedMemberName> </AliasProperty> <AliasProperty> <Name>Right</Name> <ReferencedMemberName>Forward</ReferencedMemberName> </AliasProperty> <ScriptMethod> <Name>Back</Name> <Script> <# .SYNOPSIS Moves the cursor back .DESCRIPTION Moves the cursor N (default 1) cells back. If the cursor is already at the edge of the screen, this has no effect. .NOTES This method returns an escape sequence (it should be invisible). #> param( # How far the cursor should move. [Alias('N')] [ValidateRange(1,1024)] [int]$Distance = 1 ) "`e[${Distance}D" </Script> </ScriptMethod> <ScriptMethod> <Name>Down</Name> <Script> <# .SYNOPSIS Moves the cursor down .DESCRIPTION Moves the cursor N (default 1) cells down. If the cursor is already at the edge of the screen, this has no effect. .NOTES This method returns an escape sequence (it should be invisible). #> param( # How far the cursor should move [ValidateRange(1,1024)] [int]$Distance = 1 ) "`e[${Distance}B" </Script> </ScriptMethod> <ScriptMethod> <Name>Forward</Name> <Script> <# .SYNOPSIS Moves the cursor forward .DESCRIPTION Moves the cursor N (default 1) cells back. If the cursor is already at the edge of the screen, this has no effect. .NOTES This method returns an escape sequence (it should be invisible). #> param( # How far the cursor should move [Alias('N')] [ValidateRange(1,1024)] [int]$Distance = 1 ) "`e[${Distance}C" </Script> </ScriptMethod> <ScriptMethod> <Name>Hide</Name> <Script> <# .SYNOPSIS Hides the cursor .DESCRIPTION Hides the cursor. This is not supported in all terminals. .NOTES This method returns an escape sequence (it should be invisible). #> param() "`e[25l" </Script> </ScriptMethod> <ScriptMethod> <Name>PageDown</Name> <Script> <# .SYNOPSIS Pages the cursor down .DESCRIPTION Pages the cursor N (default 1) pages down. New lines are added at the top. .NOTES This method returns an escape sequence (it should be invisible). #> param( # How far the cursor should move [Alias('Rows')] [ValidateRange(1,1024)] [int]$Distance = 1 ) [Console]::Write("`e[${Distance}T") </Script> </ScriptMethod> <ScriptMethod> <Name>PageUp</Name> <Script> <# .SYNOPSIS Pages the cursor up. .DESCRIPTION Pages the cursor N (default 1) pages up. New lines are added at the bottom. .NOTES This method returns an escape sequence (it should be invisible). #> param( # How far the cursor should move [Alias('Rows')] [ValidateRange(1,1024)] [int]$Distance = 1 ) [Console]::Write("`e[${Distance}S") </Script> </ScriptMethod> <ScriptMethod> <Name>SetPosition</Name> <Script> <# .SYNOPSIS Sets the cursor position. .DESCRIPTION Sets the position of the cursor. This is not supported in all terminals. The position can be provided as a pair of integers. The first integer will be the row, the second integer will be the column. The position can also be provided as an object with any of the following properties: * X/Column/Left * Y/Row/Top .NOTES This method returns an escape sequence (it should be invisible). #> $argList = @($args | . { process { $_ }}) $coordinates = if ($argList -as [int[]]) { $argList -as [int[]] } elseif ($argList.Length -eq 1) { $arg = $args[0] if ($arg.Y) { $arg.Y } elseif ($arg.Row) { $arg.Row } elseif ($arg.Top) { $arg.Top } if ($arg.X) { $arg.X } elseif ($arg.Column) { $arg.Column } elseif ($arg.Left) { $arg.Left } } if ($coordinates -and $coordinates.Length -eq 2) { "`e[$($coordinates[0]);$($coordinates[1])H" } </Script> </ScriptMethod> <ScriptMethod> <Name>Show</Name> <Script> <# .SYNOPSIS Shows the cursor .DESCRIPTION Shows the cursor. This is not supported in all terminals. .NOTES This method returns an escape sequence (it should be invisible). #> param() "`e[25h" </Script> </ScriptMethod> <ScriptMethod> <Name>Up</Name> <Script> <# .SYNOPSIS Moves the cursor up .DESCRIPTION Moves the cursor N (default 1) cells up. If the cursor is already at the edge of the screen, this has no effect. #> param( # How far the cursor should move [Alias('N')] [ValidateRange(1,1024)] [int]$Distance = 1 ) "`e[${Distance}A" </Script> </ScriptMethod> <ScriptProperty> <Name>Position</Name> <GetScriptBlock> <# .SYNOPSIS Gets the cursor position .DESCRIPTION Gets the cursor position .EXAMPLE $Host.Cursor.Position #> if ($host.UI.RawUI.CursorPosition) { # In the "really" category, CursorPosition is zero-index, where as actual cursors in a terminal are 1-indexed. [PSCustomObject][Ordered]@{ PSTypeName = 'Posh.Host.Cursor.Position' Row = ($host.UI.RawUI.CursorPosition.Y + 1) Column = ($host.UI.RawUI.CursorPosition.X + 1) } } </GetScriptBlock> </ScriptProperty> </Members> </Type> <Type> <Name>Posh.Input</Name> <Members> <AliasProperty> <Name>After</Name> <ReferencedMemberName>Append</ReferencedMemberName> </AliasProperty> <AliasProperty> <Name>Before</Name> <ReferencedMemberName>Prepend</ReferencedMemberName> </AliasProperty> <AliasProperty> <Name>Undo</Name> <ReferencedMemberName>Pop</ReferencedMemberName> </AliasProperty> <ScriptMethod> <Name>Append</Name> <Script> <# .SYNOPSIS Appends content to a stackable function .DESCRIPTION #> param( # The value to prepend. $Value ) $toAppend = if ($Value -is [ScriptBlock]) { $Value } else { [ScriptBlock]::Create($this.Stringify($Value)) } $currentFunction = $posh.ExecutionContext.SessionState.InvokeCommand.InvokeScript("`$function:$($this.FunctionName)")[0] $this.Current = {@(. $currentFunction; . $toAppend) -join ''}.GetNewClosure() </Script> </ScriptMethod> <ScriptMethod> <Name>Clear</Name> <Script> <# .SYNOPSIS Clears a stackable function .DESCRIPTION Clears a stackable function, resetting it to it's original state. .EXAMPLE $Posh.Prompt.Clear() #> if ($this.Stack -and $this.Stack.Count) { $posh.ExecutionContext.SessionState.psvariable.Set("function:$($this.FunctionName)", @($this.Stack.ToArray())[-1]) $this.Stack.Clear() } </Script> </ScriptMethod> <ScriptMethod> <Name>Pop</Name> <Script> <# .SYNOPSIS Pops the last value from a function stack .DESCRIPTION Pops the latest value from a function stack, such as the prompt. .EXAMPLE $Posh.Prompt.Pop() #> param( ) if ($this.Stack -and $this.Stack.Count) { $posh.ExecutionContext.SessionState.psvariable.Set("function:$($this.FunctionName)", $this.Stack.Pop()) } </Script> </ScriptMethod> <ScriptMethod> <Name>Prepend</Name> <Script> <# .SYNOPSIS Prepends content to a stackable function. .DESCRIPTION Prepends content to a stackable function. This takes the current entry and adds content to it's beginning. #> param( # The value to prepend. $Value ) $toPrepend = if ($Value -is [ScriptBlock]) { $Value } else { [ScriptBlock]::Create($this.Stringify($Value)) } $currentFunction = $posh.ExecutionContext.SessionState.InvokeCommand.InvokeScript("`$function:$($this.FunctionName)")[0] $this.Current = {@(. $toPrepend; . $currentFunction) -join ''}.GetNewClosure() </Script> </ScriptMethod> <ScriptMethod> <Name>Push</Name> <Script> <# .SYNOPSIS Pushes an entry into a stackable function .DESCRIPTION Pushes an entry into a stackable function. This overwrites the existing entry, and adds the previous value to the stack so it can be easily undone. #> param( # The new value for the function [ScriptBlock] $Value ) $this.Current = $Value </Script> </ScriptMethod> <ScriptMethod> <Name>Replace</Name> <Script> <# .SYNOPSIS Replaces content within a function .DESCRIPTION Replaces content within a stackable function, such as the prompt. .EXAMPLE # Replace both ends of the prompt $Posh.Prompt.Replace('PS ', 0x27d6,$true).Replace('>', 0x27d5, $true) .EXAMPLE $Posh.Prompt.Replace($( if ($env:User) { $env:User } elseif ($env:UserName) { $env:UserName } ),'***') #> param( # The content to replace $Replace, # The new value $Value ) $toReplace = if ($Value -is [ScriptBlock]) { $Value } else { [ScriptBlock]::Create($this.Stringify($Value)) } $currentFunction = $posh.ExecutionContext.SessionState.InvokeCommand.InvokeScript("`$function:$($this.FunctionName)")[0] $passThru = $false foreach ($arg in $args) { if ($arg -is [bool] -and $arg) { $passThru = $true } } $newFunc = { @( $existingOutput =. $currentFunction $replaceRegex = [Regex]::new($Replace,'IgnoreCase,IgnorePatternWhitespace','00:00:02') $replaceRegex.Replace($existingOutput, $toReplace) ) -join '' }.GetNewClosure() $this.Current = $newFunc if ($passThru) { $this } </Script> </ScriptMethod> <ScriptMethod> <Name>Stringify</Name> <Script> <# .SYNOPSIS Converts into a stringified value .DESCRIPTION Converts an item into a stringified value. This is used internally by stackable functions when they are prepending or appending. #> param( $Prompt ) if ($Prompt -is [ScriptBlock]) { ". {$prompt}" } else { "'$( $( if ($Prompt -is [int]) { if ($Prompt -le 1000) { $Prompt -as [char] -as [string] } else { $ExecutionContext.SessionState.InvokeCommand.ExpandString('`u{'+("{0:x}" -f $Prompt) + '}') } } else { $Prompt } ) -replace "'","''" )'" } </Script> </ScriptMethod> <ScriptProperty> <Name>Current</Name> <GetScriptBlock> <# .SYNOPSIS Gets the value of a stackable function .DESCRIPTION Gets the current value of a stackable function. .EXAMPLE $posh.Prompt.Current #> $posh.ExecutionContext.SessionState.InvokeCommand.InvokeScript("`$function:$($this.FunctionName)") </GetScriptBlock> <SetScriptBlock> <# .SYNOPSIS Sets the current implementation of a function .DESCRIPTION Sets the current imlementation of a stackable function. Stackable functions keep a stack of all prior entries for easy undo. .EXAMPLE $Posh.Prompt.Current = {"?"} #> if (-not $this.FunctionName) { return } $currentFunctionValue = $posh.ExecutionContext.SessionState.InvokeCommand.InvokeScript("`$function:$($this.FunctionName)")[0] $this.Stack.Push( $currentFunctionValue ) $newFunctionValue = $args[0] if ($newFunctionValue -isnot [ScriptBlock]) { $newFunctionValue = [ScriptBlock]::Create($this.Stringify($newFunctionValue)) } $posh.ExecutionContext.SessionState.PSVariable.Set("function:$($this.FunctionName)", $newFunctionValue) </SetScriptBlock> </ScriptProperty> <NoteProperty> <Name>README</Name> <Value>PowerShell has a robust input system. There's a very useful module by the name of PSReadLine that helps handle advanced input. Posh allows you to override the input function for PowerShell in a safe, stackable way. Pipe `$posh.Input` into `Get-Member` to see what it can do.</Value> </NoteProperty> </Members> </Type> <Type> <Name>Posh.Parameters</Name> <Members> <ScriptMethod> <Name>Clear</Name> <Script> <# .SYNOPSIS Clears default parameter values. .DESCRIPTION Clears all default parameter values. .EXAMPLE $posh.Parameters.Clear() #> $global:PSDefaultParameterValues.Clear() </Script> </ScriptMethod> <ScriptMethod> <Name>Remove</Name> <Script> <# .SYNOPSIS Removes parameter default values. .DESCRIPTION Removes the default values for a command. .EXAMPLE $Posh.Parameters.Remove("Out-Default") #> param( # The name of the command. $Command, # The command parameters. # If this is a dictionary, each value will be used. # Otherwise, this will be treated as the name of the parameter. $Parameter ) $DefaultValueKey = if ($command -is [Management.Automation.CommandInfo]) { if ($command.Source) { $command.Source } else { $command.Name } } else { "$command" } if ($Parameter -is [Collections.IDictionary]) { foreach ($parameterKeyValue in $Parameter.GetEnumerator()) { $null = $global:PSDefaultParameterValues.Remove("${defaultValueKey}:$($parameterKeyValue.Key)") } } elseif ($Parameter) { $null = $global:PSDefaultParameterValues["${defaultValueKey}:$Parameter"] = $DefaultValue } else { $toRemoveKeys = $global:PSDefaultParameterValues.Keys -like "${defaultValueKey}:*" foreach ($toRemove in $toRemoveKeys) { $null = $global:PSDefaultParameterValues.Remove($toRemove) } } </Script> </ScriptMethod> <ScriptMethod> <Name>SetDefault</Name> <Script> <# .SYNOPSIS Sets parameter default values. .DESCRIPTION Sets the default value for a parameter. .EXAMPLE $Posh.Parameters.SetDefault("Out-Default", "OutVariable", 'LastOutput') #> param( # The name of the command. $Command, # The command parameters. # If this is a dictionary, each value will be used. # Otherwise, this will be treated as the name of the parameter. $Parameter, # The default value. $DefaultValue ) $DefaultValueKey = if ($command -is [Management.Automation.CommandInfo]) { if ($command.Source) { $command.Source } else { $command.Name } } else { "$command" } if ($Parameter -is [Collections.IDictionary]) { foreach ($parameterKeyValue in $Parameter.GetEnumerator()) { $global:PSDefaultParameterValues["${defaultValueKey}:$($parameterKeyValue.Key)"] = $parameterKeyValue.Value } } else { $global:PSDefaultParameterValues["${defaultValueKey}:$Parameter"] = $DefaultValue } </Script> </ScriptMethod> <ScriptProperty> <Name>Defaults</Name> <GetScriptBlock> $defaultsByCommand = [Ordered]@{} foreach ($key in $global:PSDefaultParameterValues.Keys) { $commandName, $parameterName = $key -split ':',2 if (-not $defaultsByCommand[$commandName]) { $defaultsByCommand[$commandName] = [Ordered]@{} } $defaultsByCommand[$commandName][$parameterName] = $global:PSDefaultParameterValues[$key] } $defaultsByCommand </GetScriptBlock> <SetScriptBlock> $argArray = @( foreach ($arg in $args) { $arg } ) $this.SetDefault.Invoke($argArray) </SetScriptBlock> </ScriptProperty> <NoteProperty> <Name>README</Name> <Value>One of the strengths of PowerShell is how it treats parameters. You can find metadata about any command's parameters. You can also provide default values for any command's parameters. `$Posh.Parameters` helps you Find PowerShell parameters and manage their default values.</Value> </NoteProperty> </Members> </Type> <Type> <Name>Posh.Preset.Collection</Name> <Members> <ScriptMethod> <Name>Refresh</Name> <Script> $this | Add-Member NoteProperty '.Cache' @() -Force </Script> </ScriptMethod> <ScriptProperty> <Name>All</Name> <GetScriptBlock> <# .SYNOPSIS Gets all items in an extension collection. .DESCRIPTION Gets all items in a collection of extended commands. #> if (-not $this.'.Cache') { if (-not $this.'.Module') { return @() } $findExtensionArgs = @($this.'.Module') + @($this.'.Path') $allExtensionsFound = @(:nextExtension foreach ($foundExtension in $posh.Commands.FindExtensions.Invoke($findExtensionArgs) ) { if ($this.'.CommandType') { foreach ($typename in $this.'.CommandType') { if ($foundExtension.pstypenames -contains $typename) { $foundExtension continue nextExtension } } } else { $foundExtension } } ) $this | Add-Member NoteProperty '.Cache' $allExtensionsFound -Force } return $this.'.Cache' </GetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>CommandType</Name> <GetScriptBlock> <# .SYNOPSIS Gets an extension collection's CommandType .DESCRIPTION Gets the extended CommandTypes(s) that are stored in an extension collection. CommandTypes can be defined in a module's manifest. #> return $this.'.CommandType' </GetScriptBlock> <SetScriptBlock> <# .SYNOPSIS Sets an extension collection's command type .DESCRIPTION Sets the extended command types in an extension collection. #> param( # The path. If this is empty all extended commands will be present in the collection [string[]] $CommandType ) Add-Member -InputObject $this -MemberType NoteProperty -Name '.CommandType' -Value $CommandType -Force </SetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>Count</Name> <GetScriptBlock> <# .SYNOPSIS Gets the extension count. .DESCRIPTION Gets the count of all extensions in a collection. #> $this.All.Length </GetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>Module</Name> <GetScriptBlock> <# .SYNOPSIS Gets an extension collection's module .DESCRIPTION Gets the module that defines extended types in an extension collection. #> return $this.'.Module' </GetScriptBlock> <SetScriptBlock> <# .SYNOPSIS Sets an extension collection's module .DESCRIPTION Sets the module that defines extended command types in an extension collection. #> param( # The module. [Management.Automation.PSModuleInfo] $Module ) Add-Member -InputObject $this -MemberType NoteProperty -Name '.Module' -Value $module -Force </SetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>Path</Name> <GetScriptBlock> <# .SYNOPSIS Gets an extension collection's Path .DESCRIPTION Gets the Path(s) that store extensions in an extension collection. #> return $this.'.Path' </GetScriptBlock> <SetScriptBlock> <# .SYNOPSIS Sets an extension collection's path .DESCRIPTION Sets the path that defines extended command types in an extension collection. #> param( # The path. If this is empty, only extensions that are functions or aliases will be found. [string[]] $Path ) Add-Member -InputObject $this -MemberType NoteProperty -Name '.Path' -Value $Path -Force </SetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>Random</Name> <GetScriptBlock> <# .SYNOPSIS Gets a random extended command .DESCRIPTION Gets a random extended command from an ExtensionCollection. #> $this.All | Get-Random </GetScriptBlock> </ScriptProperty> <NoteProperty> <Name>README</Name> <Value>## Posh Presets Posh Presets provide a way to store and apply presets for a variable. They are simply data files, where each key or property repesents a expression and it's value represents what it will be set to. Preset files can be .psd1, .json, or .clixml. To see what presets can do, use $Posh.Presets | Get-Member</Value> </NoteProperty> </Members> </Type> <Type> <Name>Posh.Preset.Command</Name> <Members> <AliasProperty> <Name>Apply</Name> <ReferencedMemberName>Use</ReferencedMemberName> </AliasProperty> <ScriptMethod> <Name>Use</Name> <Script> <# .SYNOPSIS Uses a preset .DESCRIPTION Uses or applies a Posh preset. Posh presets will take the data in a *.preset.* file and apply it to a variable. #> $importedData = switch -regex ($this.Source) { '\.psd1$' { $importedAsLocalizedData = Import-LocalizedData -BaseDirectory ($this.Source | Split-Path) -FileName ($this.Source | Split-Path -Leaf) if ($importedAsLocalizedData) { $replacedContent = [IO.File]::ReadAllText($this.Source) -replace '\@\{', '[Ordered]@{' & ([ScriptBlock]::Create($replacedContent)) } } '\.json$' { Get-Content $this.Source -Raw | ConvertFrom-Json } '.\clixml' { Import-Clixml $this.Source } } if ($importedData -is [Collections.IDictionary]) { $importedData = [PSCustomObject]$importedData } foreach ($importedProperty in $importedData.psobject.properties) { if ($importedProperty.Name -notmatch '^\$') { continue } $importedNameScript = [ScriptBlock]::Create($importedProperty.Name) $valueToImport = $importedProperty.Value if (-not $importedNameScript) { continue } $statements = $importedNameScript.Ast.EndBlock.Statements $currentValue = try { . $importedNameScript } catch {$null} # If we are importing a dictionary value, try to set each value within the dictionary if ($valueToImport -is [Collections.IDictionary]) { if ($currentValue -is [Collections.IDictionary]) { foreach ($ToImport in $valueToImport.GetEnumerator()) { $currentValue[$ToImport.Key] = $ToImport.Value } } } elseif ($valueToImport.GetType -and ( $valueToImport.GetType().IsPrimitive -or $valueToImport.GetType() -in [string], [DateTime], [timespan] )) { $global:ExecutionContext.SessionState.InvokeCommand.InvokeScript( "$importedNameScript = $valueToImport" ) } elseif ($currentValue -is [Collections.IDictionary]) { foreach ($ToImport in $valueToImport.psobject.properties) { $currentValue[$ToImport.Name] = $ToImport.Value } } } </Script> </ScriptMethod> </Members> </Type> <Type> <Name>Posh.Profiles</Name> <Members> <ScriptMethod> <Name>Add</Name> <Script> <# .SYNOPSIS Adds content to a profile .DESCRIPTION Adds content to a PowerShell profile #> param( # The content to add to your profile. [ScriptBlock] $Content, # Which profile should the content be added to? # The default is the current user's current host. [ValidateSet('AllUsersAllHosts','AllUsersCurrentHosts','CurrentUserAllHosts','CurrentUserCurrentHost')] [string] $WhichProfile = 'CurrentUserCurrentHost' ) $profilePath = $PROFILE.$WhichProfile $profileContent = if (Test-Path $profilePath) { Get-Content -Raw $profilePath } else { '' } if ($profileContent -like "*$Content*") { return } $profileContent += [Environment]::NewLine $profileContent += "$content" $profileContent | Set-Content -Path $profilePath -PassThru </Script> </ScriptMethod> <ScriptMethod> <Name>ImportModule</Name> <Script> <# .SYNOPSIS Imports a module in a profile .DESCRIPTION Adds code to import a module in your profile. This will ensure the module is loaded whenever you're running PowerShell. .EXAMPLE $Posh.Profile.ImportModule("Posh") #> param( # The name of the module to import. [string] $Module, # Which profile should the content be added to? # The default is the current user's current host. [ValidateSet('AllUsersAllHosts','AllUsersCurrentHosts','CurrentUserAllHosts','CurrentUserCurrentHost')] [string] $WhichProfile = 'CurrentUserCurrentHost' ) $AlreadyAdded = $this.Matches("Import-Module $Module", $WhichProfile) if (-not $AlreadyAdded) { $this.Add( [scriptblock]::Create("Import-Module $module -Force$([Environment]::Newline)"), $WhichProfile ) } </Script> </ScriptMethod> <ScriptMethod> <Name>Matches</Name> <Script> <# .SYNOPSIS Matches patterns within profiles .DESCRIPTION Matches a pattern within profile files. All places the pattern is found will be returned. .EXAMPLE $Posh.Profile.Matches("Posh") #> param( # The pattern to match. [regex] $Pattern, # Which profile should the content be removed from? # The default is the current user's current host. [ValidateSet('AllUsersAllHosts','AllUsersCurrentHosts','CurrentUserAllHosts','CurrentUserCurrentHost')] [string[]] $WhichProfile = 'CurrentUserCurrentHost' ) @(foreach ($prof in $WhichProfile) { if (Test-Path ($profile.$prof)) { $pattern.Matches((Get-Content -Raw ($profile.$prof))) } }) </Script> </ScriptMethod> <ScriptMethod> <Name>New</Name> <Script> <# .SYNOPSIS Creates a new profile .DESCRIPTION Creates a new profile, or returns an existing profile. .EXAMPLE $Posh.Profile.New() #> param( # Which profile should be created? # The default is the current user's current host. [ValidateSet('AllUsersAllHosts','AllUsersCurrentHosts','CurrentUserAllHosts','CurrentUserCurrentHost')] [string] $WhichProfile = 'CurrentUserCurrentHost' ) $profilePath = $PROFILE.$WhichProfile if (Test-Path -LiteralPath $profilePath) { Get-Item -LiteralPath $profilePath } else { New-Item -ItemType File -Path $profilePath -Force } </Script> </ScriptMethod> <ScriptMethod> <Name>Remove</Name> <Script> <# .SYNOPSIS Removes content from a profile .DESCRIPTION Removes content from a PowerShell profile. #> param( # The content to remove. # If the content is a regular expression pattern, any matches will be removed. # Otherwise, any case-insensitive occurances of the string will be removed. $Content, # Which profile should the content be removed from? # The default is the current user's current host. [ValidateSet('AllUsersAllHosts','AllUsersCurrentHosts','CurrentUserAllHosts','CurrentUserCurrentHost')] [string] $WhichProfile = 'CurrentUserCurrentHost' ) $this.Replace($Content, '', $WhichProfile) </Script> </ScriptMethod> <ScriptMethod> <Name>RemoveModule</Name> <Script> <# .SYNOPSIS Remove a module from a profile .DESCRIPTION Remove code that imports a module in your profile. .EXAMPLE $Posh.Profile.RemoveModule("Posh") #> param( # The name of the module to no longer import. [string] $Module, # Which profile should the content be added to? # The default is the current user's current host. [ValidateSet('AllUsersAllHosts','AllUsersCurrentHosts','CurrentUserAllHosts','CurrentUserCurrentHost')] [string] $WhichProfile = 'CurrentUserCurrentHost' ) $AlreadyAdded = $this.Matches("Import-Module $Module", $WhichProfile) if ($AlreadyAdded) { $this.Remove("Import-Module $Module", $WhichProfile) } </Script> </ScriptMethod> <ScriptMethod> <Name>Replace</Name> <Script> <# .SYNOPSIS Replaces content in a profile .DESCRIPTION Replaces content in a PowerShell profile. #> param( # The content to replace. # If the content is a regular expression pattern, any matches will be replaced. # Otherwise, any case-insensitive occurances of the string will be replaced. $Content, # The content to replace. # If content replaced was a regular expression, # this will be treated as a [Regular Expression substitution](https://learn.microsoft.com/en-us/dotnet/standard/base-types/substitutions-in-regular-expressions). $Replacement = '', # Which profile should the content be removed from? # The default is the current user's current host. [ValidateSet('AllUsersAllHosts','AllUsersCurrentHosts','CurrentUserAllHosts','CurrentUserCurrentHost')] [string] $WhichProfile = 'CurrentUserCurrentHost' ) $profilePath = $PROFILE.$WhichProfile $profileContent = if (Test-Path $profilePath) { Get-Content -Raw $profilePath } else { '' } if ($Content -is [regex]) { $profileContent = $Content.Replace($profileContent, $Replacement) } else { $Content = "$content" if ($Content) { $profileContent = $profileContent.Replace( $content, $Replacement, [StringComparison]::OrdinalIgnoreCase ) } } $profileContent | Set-Content -Path $profilePath -PassThru </Script> </ScriptMethod> <ScriptProperty> <Name>Current</Name> <GetScriptBlock> <# .SYNOPSIS Gets the current Profile .DESCRIPTION Gets the current PowerShell Profile .EXAMPLE $posh.Profile.Current #> "$profile" </GetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>Directory</Name> <GetScriptBlock> <# .SYNOPSIS Gets the profile directory .DESCRIPTION Gets the PowerShell profile's directory. .NOTES The Profile Directory is a wonderful place to store data. ( It is almost always writeable ) .EXAMPLE $Profile.Directory #> ($profile | Split-Path) -as [IO.DirectoryInfo] </GetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>File</Name> <GetScriptBlock> <# .SYNOPSIS Gets the profile file .DESCRIPTION Gets the profile file for the current user in the current host. .EXAMPLE $Posh.Profile.File #> if (Test-Path "$profile") { Get-Item -LiteralPath "$profile" } </GetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>Files</Name> <GetScriptBlock> <# .SYNOPSIS Gets the profile files .DESCRIPTION Gets the FileInfo objects for each profile that exists. .EXAMPLE $posh.Profile.Files #> foreach ($potentialPath in $profile.CurrentUserCurrentHost, $profile.CurrentUserAllHosts, $profile.AllUsersAllHosts, $profile.AllUsersCurrentHost) { if ([IO.File]::Exists($potentialPath)) { [IO.FileInfo]$potentialPath } } </GetScriptBlock> </ScriptProperty> <NoteProperty> <Name>README</Name> <Value>PowerShell has profiles! Profiles run whenever PowerShell is loaded. They're great if there's a module you want to always load, or a variable you always want defined. To see how to manipulate PowerShell profiles with Posh, use $posh.Profiles | Get-Member</Value> </NoteProperty> </Members> </Type> <Type> <Name>Posh.Prompt</Name> <Members> <AliasProperty> <Name>After</Name> <ReferencedMemberName>Append</ReferencedMemberName> </AliasProperty> <AliasProperty> <Name>Before</Name> <ReferencedMemberName>Prepend</ReferencedMemberName> </AliasProperty> <AliasProperty> <Name>Undo</Name> <ReferencedMemberName>Pop</ReferencedMemberName> </AliasProperty> <ScriptMethod> <Name>Append</Name> <Script> <# .SYNOPSIS Appends content to a stackable function .DESCRIPTION #> param( # The value to prepend. $Value ) $toAppend = if ($Value -is [ScriptBlock]) { $Value } else { [ScriptBlock]::Create($this.Stringify($Value)) } $currentFunction = $posh.ExecutionContext.SessionState.InvokeCommand.InvokeScript("`$function:$($this.FunctionName)")[0] $this.Current = {@(. $currentFunction; . $toAppend) -join ''}.GetNewClosure() </Script> </ScriptMethod> <ScriptMethod> <Name>Clear</Name> <Script> <# .SYNOPSIS Clears a stackable function .DESCRIPTION Clears a stackable function, resetting it to it's original state. .EXAMPLE $Posh.Prompt.Clear() #> if ($this.Stack -and $this.Stack.Count) { $posh.ExecutionContext.SessionState.psvariable.Set("function:$($this.FunctionName)", @($this.Stack.ToArray())[-1]) $this.Stack.Clear() } </Script> </ScriptMethod> <ScriptMethod> <Name>Pop</Name> <Script> <# .SYNOPSIS Pops the last value from a function stack .DESCRIPTION Pops the latest value from a function stack, such as the prompt. .EXAMPLE $Posh.Prompt.Pop() #> param( ) if ($this.Stack -and $this.Stack.Count) { $posh.ExecutionContext.SessionState.psvariable.Set("function:$($this.FunctionName)", $this.Stack.Pop()) } </Script> </ScriptMethod> <ScriptMethod> <Name>Prepend</Name> <Script> <# .SYNOPSIS Prepends content to a stackable function. .DESCRIPTION Prepends content to a stackable function. This takes the current entry and adds content to it's beginning. #> param( # The value to prepend. $Value ) $toPrepend = if ($Value -is [ScriptBlock]) { $Value } else { [ScriptBlock]::Create($this.Stringify($Value)) } $currentFunction = $posh.ExecutionContext.SessionState.InvokeCommand.InvokeScript("`$function:$($this.FunctionName)")[0] $this.Current = {@(. $toPrepend; . $currentFunction) -join ''}.GetNewClosure() </Script> </ScriptMethod> <ScriptMethod> <Name>Push</Name> <Script> <# .SYNOPSIS Pushes an entry into a stackable function .DESCRIPTION Pushes an entry into a stackable function. This overwrites the existing entry, and adds the previous value to the stack so it can be easily undone. #> param( # The new value for the function [ScriptBlock] $Value ) $this.Current = $Value </Script> </ScriptMethod> <ScriptMethod> <Name>Replace</Name> <Script> <# .SYNOPSIS Replaces content within a function .DESCRIPTION Replaces content within a stackable function, such as the prompt. .EXAMPLE # Replace both ends of the prompt $Posh.Prompt.Replace('PS ', 0x27d6,$true).Replace('>', 0x27d5, $true) .EXAMPLE $Posh.Prompt.Replace($( if ($env:User) { $env:User } elseif ($env:UserName) { $env:UserName } ),'***') #> param( # The content to replace $Replace, # The new value $Value ) $toReplace = if ($Value -is [ScriptBlock]) { $Value } else { [ScriptBlock]::Create($this.Stringify($Value)) } $currentFunction = $posh.ExecutionContext.SessionState.InvokeCommand.InvokeScript("`$function:$($this.FunctionName)")[0] $passThru = $false foreach ($arg in $args) { if ($arg -is [bool] -and $arg) { $passThru = $true } } $newFunc = { @( $existingOutput =. $currentFunction $replaceRegex = [Regex]::new($Replace,'IgnoreCase,IgnorePatternWhitespace','00:00:02') $replaceRegex.Replace($existingOutput, $toReplace) ) -join '' }.GetNewClosure() $this.Current = $newFunc if ($passThru) { $this } </Script> </ScriptMethod> <ScriptMethod> <Name>Stringify</Name> <Script> <# .SYNOPSIS Converts into a stringified value .DESCRIPTION Converts an item into a stringified value. This is used internally by stackable functions when they are prepending or appending. #> param( $Prompt ) if ($Prompt -is [ScriptBlock]) { ". {$prompt}" } else { "'$( $( if ($Prompt -is [int]) { if ($Prompt -le 1000) { $Prompt -as [char] -as [string] } else { $ExecutionContext.SessionState.InvokeCommand.ExpandString('`u{'+("{0:x}" -f $Prompt) + '}') } } else { $Prompt } ) -replace "'","''" )'" } </Script> </ScriptMethod> <ScriptProperty> <Name>Current</Name> <GetScriptBlock> <# .SYNOPSIS Gets the value of a stackable function .DESCRIPTION Gets the current value of a stackable function. .EXAMPLE $posh.Prompt.Current #> $posh.ExecutionContext.SessionState.InvokeCommand.InvokeScript("`$function:$($this.FunctionName)") </GetScriptBlock> <SetScriptBlock> <# .SYNOPSIS Sets the current implementation of a function .DESCRIPTION Sets the current imlementation of a stackable function. Stackable functions keep a stack of all prior entries for easy undo. .EXAMPLE $Posh.Prompt.Current = {"?"} #> if (-not $this.FunctionName) { return } $currentFunctionValue = $posh.ExecutionContext.SessionState.InvokeCommand.InvokeScript("`$function:$($this.FunctionName)")[0] $this.Stack.Push( $currentFunctionValue ) $newFunctionValue = $args[0] if ($newFunctionValue -isnot [ScriptBlock]) { $newFunctionValue = [ScriptBlock]::Create($this.Stringify($newFunctionValue)) } $posh.ExecutionContext.SessionState.PSVariable.Set("function:$($this.FunctionName)", $newFunctionValue) </SetScriptBlock> </ScriptProperty> <NoteProperty> <Name>README</Name> <Value>`prompt` is the function that is called before PowerShell prompts for input. $Posh.Prompt allows you to customize the PowerShell prompt. Prompts are a cool way to customize your shell. Pipe $Posh.Prompt to Get-Member to see what it can do.</Value> </NoteProperty> </Members> </Type> <Type> <Name>Posh.RSS.Article</Name> <Members> <AliasProperty> <Name>Url</Name> <ReferencedMemberName>Link</ReferencedMemberName> </AliasProperty> <ScriptProperty> <Name>DatePublished</Name> <GetScriptBlock> <# .SYNOPSIS Gets an article's date published .DESCRIPTION Gets the date an article was published, as a `[DateTime]`. .EXAMPLE $Posh.News.Article.DatePublished #> $pubDateTime = $this.pubDate -as [DateTime] if ($pubDateTime) { $pubDateTime } else { [datetime]::MinValue } </GetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>Name</Name> <GetScriptBlock> <# .SYNOPSIS Gets an article's name .DESCRIPTION Gets the name of an article in an RSS feed. #> if ($this.Title -and $this.Title -isnot [string]) { if ($this.Title.InnerText) { $this.Title.InnerText } elseif ($this.Title -is [object[]]) { $this.Title | Select-Object -Unique -First 1 } } elseif ($this.Title) { $this.Title } elseif ($this.URL) { $thisURI = $this.URL -as [uri] $thisURI.Segments[-1] -replace '-', ' ' } </GetScriptBlock> </ScriptProperty> </Members> </Type> <Type> <Name>Posh.RSS.Feed</Name> <Members> <AliasProperty> <Name>Articles</Name> <ReferencedMemberName>Article</ReferencedMemberName> </AliasProperty> <ScriptProperty> <Name>Article</Name> <GetScriptBlock> <# .SYNOPSIS Gets articles in a feed. .DESCRIPTION Gets the articles in a RSS feed. Articles will be cached for performance. .EXAMPLE $Posh.News.Article # Get all articles from all feeds associated with Posh. #> if (-not $this.'.Article') { Write-Progress "Getting Feeds" $this.Url Add-Member -InputObject $this -MemberType NoteProperty -Name '.Article' -Value @( foreach ($feedItem in Invoke-RestMethod -Uri $this.Url) { $feedItem.pstypenames.insert(0,'Posh.RSS.Article') $feedItem | Add-Member NoteProperty Source $this.Name -Force -PassThru } ) -Force } $this.'.Article' </GetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>Recent</Name> <GetScriptBlock> <# .SYNOPSIS Gets recent articles .DESCRIPTION Gets recent articles in an RSS feed. #> $after = $this.Source.News.RecentDuration if (-not $after) { return } foreach ($article in $this.Article) { if (([DateTime]::Now - $article.DatePublished) -gt $after) { continue } $article } </GetScriptBlock> </ScriptProperty> </Members> </Type> <Type> <Name>Posh.RSS.FeedCollection</Name> <Members> <AliasProperty> <Name>ByName</Name> <ReferencedMemberName>Feed</ReferencedMemberName> </AliasProperty> <ScriptProperty> <Name>Feed</Name> <GetScriptBlock> <# .SYNOPSIS Gets feeds by name .DESCRIPTION Gets all feeds in a collection by name. #> param() $this.All | Group-Object Name -AsHashTable </GetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>Random</Name> <GetScriptBlock> <# .SYNOPSIS Gets a random feed .DESCRIPTION Gets a random feed from a feed collection #> $this.All | Get-Random </GetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>Recent</Name> <GetScriptBlock> <# .SYNOPSIS Gets all recent articles .DESCRIPTION Gets all recent articles in a feed collection, sorted by date published. .NOTES How "Recent" is defined in the a feed collection's `.RecentDuration` property. #> @(foreach ($feed in $this.All) { $feed.Recent }) | Sort-Object DatePublished -Descending </GetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>RecentDuration</Name> <GetScriptBlock> <# .SYNOPSIS Gets the duration considered recent .DESCRIPTION Gets the duration that is used to determine how recent an article is. By default, this is 45 days. #> if (-not $this.'.RecentDuration') { $this | Add-Member NoteProperty '.RecentDuration' (New-TimeSpan -Days 45) -Force } $this.'.RecentDuration' </GetScriptBlock> <SetScriptBlock> <# .SYNOPSIS Sets the duration considered recent .DESCRIPTION Set the duration that is used to determine how recent an article is. #> param( [Timespan] $RecentDuration ) $this | Add-Member NoteProperty '.RecentDuration' $RecentDuration -Force </SetScriptBlock> </ScriptProperty> <NoteProperty> <Name>README</Name> <Value>Modules can put News in their module manifest. Posh provides a simple RSS reader to help you stay up to date. To view recent articles, use ~~~PowerShell $Posh.News.Recent ~~~ To view all feeds, use ~~~PowerShell $Posh.News.All ~~~ To view all articles from all feeds, use ~~~PowerShell $Posh.News.All.Article ~~~ To see a specific feed, use: ~~~PowerShell $Posh.News.Feed["PowerShell Team"] ~~~ </Value> </NoteProperty> </Members> </Type> <Type> <Name>Posh.Stackable</Name> <Members> <AliasProperty> <Name>After</Name> <ReferencedMemberName>Append</ReferencedMemberName> </AliasProperty> <AliasProperty> <Name>Before</Name> <ReferencedMemberName>Prepend</ReferencedMemberName> </AliasProperty> <AliasProperty> <Name>Undo</Name> <ReferencedMemberName>Pop</ReferencedMemberName> </AliasProperty> <ScriptMethod> <Name>Append</Name> <Script> <# .SYNOPSIS Appends content to a stackable function .DESCRIPTION #> param( # The value to prepend. $Value ) $toAppend = if ($Value -is [ScriptBlock]) { $Value } else { [ScriptBlock]::Create($this.Stringify($Value)) } $currentFunction = $posh.ExecutionContext.SessionState.InvokeCommand.InvokeScript("`$function:$($this.FunctionName)")[0] $this.Current = {@(. $currentFunction; . $toAppend) -join ''}.GetNewClosure() </Script> </ScriptMethod> <ScriptMethod> <Name>Clear</Name> <Script> <# .SYNOPSIS Clears a stackable function .DESCRIPTION Clears a stackable function, resetting it to it's original state. .EXAMPLE $Posh.Prompt.Clear() #> if ($this.Stack -and $this.Stack.Count) { $posh.ExecutionContext.SessionState.psvariable.Set("function:$($this.FunctionName)", @($this.Stack.ToArray())[-1]) $this.Stack.Clear() } </Script> </ScriptMethod> <ScriptMethod> <Name>Pop</Name> <Script> <# .SYNOPSIS Pops the last value from a function stack .DESCRIPTION Pops the latest value from a function stack, such as the prompt. .EXAMPLE $Posh.Prompt.Pop() #> param( ) if ($this.Stack -and $this.Stack.Count) { $posh.ExecutionContext.SessionState.psvariable.Set("function:$($this.FunctionName)", $this.Stack.Pop()) } </Script> </ScriptMethod> <ScriptMethod> <Name>Prepend</Name> <Script> <# .SYNOPSIS Prepends content to a stackable function. .DESCRIPTION Prepends content to a stackable function. This takes the current entry and adds content to it's beginning. #> param( # The value to prepend. $Value ) $toPrepend = if ($Value -is [ScriptBlock]) { $Value } else { [ScriptBlock]::Create($this.Stringify($Value)) } $currentFunction = $posh.ExecutionContext.SessionState.InvokeCommand.InvokeScript("`$function:$($this.FunctionName)")[0] $this.Current = {@(. $toPrepend; . $currentFunction) -join ''}.GetNewClosure() </Script> </ScriptMethod> <ScriptMethod> <Name>Push</Name> <Script> <# .SYNOPSIS Pushes an entry into a stackable function .DESCRIPTION Pushes an entry into a stackable function. This overwrites the existing entry, and adds the previous value to the stack so it can be easily undone. #> param( # The new value for the function [ScriptBlock] $Value ) $this.Current = $Value </Script> </ScriptMethod> <ScriptMethod> <Name>Replace</Name> <Script> <# .SYNOPSIS Replaces content within a function .DESCRIPTION Replaces content within a stackable function, such as the prompt. .EXAMPLE # Replace both ends of the prompt $Posh.Prompt.Replace('PS ', 0x27d6,$true).Replace('>', 0x27d5, $true) .EXAMPLE $Posh.Prompt.Replace($( if ($env:User) { $env:User } elseif ($env:UserName) { $env:UserName } ),'***') #> param( # The content to replace $Replace, # The new value $Value ) $toReplace = if ($Value -is [ScriptBlock]) { $Value } else { [ScriptBlock]::Create($this.Stringify($Value)) } $currentFunction = $posh.ExecutionContext.SessionState.InvokeCommand.InvokeScript("`$function:$($this.FunctionName)")[0] $passThru = $false foreach ($arg in $args) { if ($arg -is [bool] -and $arg) { $passThru = $true } } $newFunc = { @( $existingOutput =. $currentFunction $replaceRegex = [Regex]::new($Replace,'IgnoreCase,IgnorePatternWhitespace','00:00:02') $replaceRegex.Replace($existingOutput, $toReplace) ) -join '' }.GetNewClosure() $this.Current = $newFunc if ($passThru) { $this } </Script> </ScriptMethod> <ScriptMethod> <Name>Stringify</Name> <Script> <# .SYNOPSIS Converts into a stringified value .DESCRIPTION Converts an item into a stringified value. This is used internally by stackable functions when they are prepending or appending. #> param( $Prompt ) if ($Prompt -is [ScriptBlock]) { ". {$prompt}" } else { "'$( $( if ($Prompt -is [int]) { if ($Prompt -le 1000) { $Prompt -as [char] -as [string] } else { $ExecutionContext.SessionState.InvokeCommand.ExpandString('`u{'+("{0:x}" -f $Prompt) + '}') } } else { $Prompt } ) -replace "'","''" )'" } </Script> </ScriptMethod> <ScriptProperty> <Name>Current</Name> <GetScriptBlock> <# .SYNOPSIS Gets the value of a stackable function .DESCRIPTION Gets the current value of a stackable function. .EXAMPLE $posh.Prompt.Current #> $posh.ExecutionContext.SessionState.InvokeCommand.InvokeScript("`$function:$($this.FunctionName)") </GetScriptBlock> <SetScriptBlock> <# .SYNOPSIS Sets the current implementation of a function .DESCRIPTION Sets the current imlementation of a stackable function. Stackable functions keep a stack of all prior entries for easy undo. .EXAMPLE $Posh.Prompt.Current = {"?"} #> if (-not $this.FunctionName) { return } $currentFunctionValue = $posh.ExecutionContext.SessionState.InvokeCommand.InvokeScript("`$function:$($this.FunctionName)")[0] $this.Stack.Push( $currentFunctionValue ) $newFunctionValue = $args[0] if ($newFunctionValue -isnot [ScriptBlock]) { $newFunctionValue = [ScriptBlock]::Create($this.Stringify($newFunctionValue)) } $posh.ExecutionContext.SessionState.PSVariable.Set("function:$($this.FunctionName)", $newFunctionValue) </SetScriptBlock> </ScriptProperty> </Members> </Type> <Type> <Name>Posh.Tip.Command</Name> <Members> <ScriptProperty> <Name>Content</Name> <GetScriptBlock> switch -regex ($this.Source) { '\.psd1$' { (Import-LocalizedData -BaseDirectory ($this.Source | Split-Path) -FileName ($this.Source | Split-Path -Leaf)).Content } '\.json$' { (Get-Content $this.Source -Raw | ConvertFrom-Json).Content } '\.md$' { Show-Markdown -LiteralPath $this.Source } '\.ps1$' { $showDemoCommand = $ExecutionContext.SessionState.InvokeCommand.GetCommand('Show-Demo', 'Function') if ($showDemoCommand) { $this.ScriptBlock } else { Get-Content $this.Source -Raw } } } </GetScriptBlock> </ScriptProperty> </Members> </Type> <Type> <Name>System.Management.Automation.PSModuleInfo</Name> <Members> <AliasProperty> <Name>Demos</Name> <ReferencedMemberName>Demo</ReferencedMemberName> </AliasProperty> <AliasProperty> <Name>Discussions</Name> <ReferencedMemberName>Discussion</ReferencedMemberName> </AliasProperty> <AliasProperty> <Name>Feed</Name> <ReferencedMemberName>News</ReferencedMemberName> </AliasProperty> <AliasProperty> <Name>Issues</Name> <ReferencedMemberName>Issue</ReferencedMemberName> </AliasProperty> <AliasProperty> <Name>Links</Name> <ReferencedMemberName>Link</ReferencedMemberName> </AliasProperty> <AliasProperty> <Name>Presets</Name> <ReferencedMemberName>Preset</ReferencedMemberName> </AliasProperty> <AliasProperty> <Name>Recommendations</Name> <ReferencedMemberName>Recommendation</ReferencedMemberName> </AliasProperty> <AliasProperty> <Name>Resource</Name> <ReferencedMemberName>Link</ReferencedMemberName> </AliasProperty> <AliasProperty> <Name>Resources</Name> <ReferencedMemberName>Link</ReferencedMemberName> </AliasProperty> <AliasProperty> <Name>RSS</Name> <ReferencedMemberName>News</ReferencedMemberName> </AliasProperty> <AliasProperty> <Name>Screenshots</Name> <ReferencedMemberName>Screenshot</ReferencedMemberName> </AliasProperty> <AliasProperty> <Name>Tests</Name> <ReferencedMemberName>Test</ReferencedMemberName> </AliasProperty> <AliasProperty> <Name>Tips</Name> <ReferencedMemberName>Tip</ReferencedMemberName> </AliasProperty> <AliasProperty> <Name>Trick</Name> <ReferencedMemberName>Tip</ReferencedMemberName> </AliasProperty> <AliasProperty> <Name>Tricks</Name> <ReferencedMemberName>Tip</ReferencedMemberName> </AliasProperty> <AliasProperty> <Name>Videos</Name> <ReferencedMemberName>Video</ReferencedMemberName> </AliasProperty> <ScriptMethod> <Name>LinkList</Name> <Script> <# .SYNOPSIS Returns a link list. .DESCRIPTION Returns a list of links from one or more properties in a module's manifest. .EXAMPLE $posh.LinkList(@( $this.PrivateData.Screenshot $this.PrivateData.Screenshots $this.PrivateData.PSData.Screenshot $this.PrivateData.PSData.Screenshots ), "Posh.Module.Screenshot") #> param( # One or more inputs to the list. [PSObject[]] $InputObject, # The name of each item in the list. [string] $PSTypeName = 'Posh.Module.Link', # The name of a collection. # If this is provided, a collection containing all items will be returned. [string] $CollectionTypeName ) filter ToLink { if ($_ -is [string]) { [PSCustomObject]@{ PSTypeName = $PSTypeName Url = $_ Source = $this } } elseif ($_ -is [Collections.IDictionary]) { $_.GetEnumerator() | Sort-Object Key | . ToLink } elseif ($_ -is [Collections.DictionaryEntry]) { [PSCustomObject][Ordered]@{ PSTypeName = $PSTypeName Name = $_.key Url = $_.Value Source = $this } } } if ($CollectionTypeName) { [PSCustomObject][Ordered]@{ PSTypeName = $CollectionTypeName All = @($inputObject | . ToLink) } } else { $inputObject | . ToLink } </Script> </ScriptMethod> <ScriptProperty> <Name>Demo</Name> <GetScriptBlock> <# .SYNOPSIS Gets module demos .DESCRIPTION Gets demo files related to a module. .EXAMPLE $Posh.Demos .LINK https://github.com/StartAutomating/ShowDemo #> $this | Split-Path | Get-ChildItem -Recurse -Filter *.demo.ps1 | Select-Object -Unique </GetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>Discussion</Name> <GetScriptBlock> <# .SYNOPSIS Gets a module's discussions URL. .DESCRIPTION Gets the discussions URL related to a module. .NOTES The Module must set it's ProjectURI, and it must be on GitHub, or this will return nothing. #> if ($this.ProjectURI.Host -eq 'github.com') { [PSCustomObject][Ordered]@{ Name = "$($this.Name) Discussions" Url = "$($this.ProjectURI)/discussions" PSTypeName = 'Posh.Module.Link' } } </GetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>Issue</Name> <GetScriptBlock> <# .SYNOPSIS Gets a module's issue URL. .DESCRIPTION Gets the issues URL related to a module. .NOTES The Module must set it's ProjectURI, and it must be on GitHub, or this will return nothing. #> if ($this.ProjectURI.Host -eq 'github.com') { [PSCustomObject][Ordered]@{ Name = "$($this.Name) Issues" Url = "$($this.ProjectURI)/issues" PSTypeName = 'Posh.Module.Link' } } </GetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>Link</Name> <GetScriptBlock> <# .SYNOPSIS Gets Module Links .DESCRIPTION Lists hyperlinks from this module. .EXAMPLE $posh.Links #> $this.LinkList(@( $this.PrivateData.Link $this.PrivateData.Links $this.PrivateData.Resource $this.PrivateData.Resources $this.PrivateData.PSData.Link $this.PrivateData.PSData.Links $this.PrivateData.PSData.Resource $this.PrivateData.PSData.Resources ), "Posh.Module.Link") </GetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>Logo</Name> <GetScriptBlock> <# .SYNOPSIS Gets Module Logos .DESCRIPTION Lists logos for this module. .EXAMPLE $posh.Logos #> $this.LinkList(@( $this.PrivateData.Logo $this.PrivateData.Logos $this.PrivateData.PSData.Logo $this.PrivateData.PSData.Logos $this.PrivateData.PSData.IconURI ), "Posh.Module.Logo") </GetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>News</Name> <GetScriptBlock> <# .SYNOPSIS Gets a Module's News .DESCRIPTION Lists RSS NewsFeeds from this module .EXAMPLE $posh.News #> if (-not $this.'.News') { $this | Add-Member NoteProperty '.News' @( $this.LinkList(@( $this.PrivateData.RSS $this.PrivateData.News $this.PrivateData.Feed $this.PrivateData.PSData.RSS $this.PrivateData.PSData.News $this.PrivateData.PSData.Feed ), "Posh.RSS.Feed", "Posh.RSS.FeedCollection") | Add-Member NoteProperty Module $this -Force -PassThru ) -Force } $this.'.News' </GetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>Preset</Name> <GetScriptBlock> <# .SYNOPSIS Get's a module's presets .DESCRIPTION Gets presets from a module. Any module can contain `*.preset(s)` files, of the extensions: * .psd1 * .json * .clixml The collection of presets can be accessed in a Module's .Preset(s) properties #> if (-not $this.'.Preset') { $PresetCollection = [PSCustomObject][Ordered]@{ PSTypeName = 'Posh.ExtensionCollection' Module = $posh Path = @(Get-Module | Split-Path) -as [string[]] CommandType = 'Posh.Preset.Command' } $PresetCollection.pstypenames.insert(0,'Posh.Preset.Collection') $this | Add-Member NoteProperty '.Preset' $PresetCollection -Force } $this.'.Preset' </GetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>README</Name> <GetScriptBlock> <# .SYNOPSIS Gets a Module's README .DESCRIPTION Gets the content of README.md file located at the module root. #> if ($this.'.README') { return $this.'.README' } $readmeFileExists = $this | Split-Path | Get-ChildItem | Where-Object Name -eq 'README.md' if ($readmeFileExists) { $this | Add-Member NoteProperty '.README' -Force (Get-Content -Raw $readmeFileExists) return $this.'.README' } </GetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>Recommendation</Name> <GetScriptBlock> <# .SYNOPSIS Gets Module Recommendations .DESCRIPTION Lists other modules this module recommends. .EXAMPLE # $Posh.Recommends gets every loaded module's recommendations. $posh.Recommends .EXAMPLE $posh.Recommendations #> $module = $this $this.LinkList(@( $module.PrivateData.Recommends $module.PrivateData.Recommend $module.PrivateData.Recommendation $module.PrivateData.Recommendations $module.PrivateData.PSData.Recommends $module.PrivateData.PSData.Recommend $module.PrivateData.PSData.Recommendation $module.PrivateData.PSData.Recommendations ), "Posh.Recommendation") </GetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>Screenshot</Name> <GetScriptBlock> <# .SYNOPSIS Gets Module Screenshots .DESCRIPTION Lists screenshots from this module. .EXAMPLE $posh.Screenshots #> $this.LinkList(@( $this.PrivateData.Screenshot $this.PrivateData.Screenshots $this.PrivateData.PSData.Screenshot $this.PrivateData.PSData.Screenshots ), "Posh.Module.Screenshot") </GetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>Test</Name> <GetScriptBlock> <# .SYNOPSIS Gets module tests .DESCRIPTION Gets Pester Tests located within a module. #> $this | Split-Path | Get-ChildItem -Recurse -Filter *.tests.ps1 | Select-Object -Unique </GetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>Tip</Name> <GetScriptBlock> <# .SYNOPSIS Get's a module's tips .DESCRIPTION Gets tips and tricks from a module. Any module can contain `*.tip(s)` or `*.trick(s)` files, of the extensions: * .md * .txt * .ps1 * .psd1 * .json * .clixml The collection of tips can be accessed in a Module's .Tip(s) or .Trick(s) properties #> if (-not $this.'.Tip') { $tipCollection = [PSCustomObject][Ordered]@{ PSTypeName = 'Posh.ExtensionCollection' Module = $posh Path = $this.Path | Split-Path CommandType = 'Posh.Tip.Command' } $tipCollection.pstypenames.insert(0,'Posh.Tip.Collection') $this | Add-Member NoteProperty '.Tip' $tipCollection -Force } $this.'.Tip' </GetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>Video</Name> <GetScriptBlock> <# .SYNOPSIS Gets Module Videos .DESCRIPTION Lists videos about this module. .EXAMPLE $posh.Videos #> $this.LinkList(@( $this.PrivateData.Video $this.PrivateData.Videos $this.PrivateData.PSData.Video $this.PrivateData.PSData.Videos ), "Posh.Module.Video") </GetScriptBlock> </ScriptProperty> </Members> </Type> <Type> <Name>System.TimeZoneInfo</Name> <Members> <ScriptProperty> <Name>LocalTime</Name> <GetScriptBlock> <# .SYNOPSIS Gets the local time .DESCRIPTION Gets the local time for a timezone. .EXAMPLE Get-TimeZone -ListAvailable .EXAMPLE Get-TimeZone | Select LocalTime #> [DateTime]::UTCNow + $this.GetUtcOffset([DateTime]::UtcNow) </GetScriptBlock> </ScriptProperty> </Members> </Type> </Types> |