Get-Tune.ps.ps1
function Get-Tune { <# .SYNOPSIS Gets tunes .DESCRIPTION Gets musical tunes that can be played. Tunes can be stored in: |Format |Extension | |--------------------------|-------------------------| |Tune Clixml |```.tune.clixml``` | |Tune JSON |```.tune.json``` | |Tune PowerShell Data file |```.tune.psd1``` | |Tune Generator |```.tune.ps1``` | |Tune Text |```.tune.txt``` | .EXAMPLE Get-Tune #> param( # The path to tune files or directories. # If not provided, will default to looking for tunes beneath TerminalTunes and any modules that tag TerminalTunes. [vbn()] [Alias('Fullname')] [string[]] $TunePath, # The title of a tune. Can include wildcards. [vbn()] [ArgumentCompleter({ param ( $commandName,$parameterName,$wordToComplete,$commandAst,$fakeBoundParameters ) $tuneList = @(if ($wordToComplete) { $toComplete = $wordToComplete -replace "^['`"]" -replace "['`"]$" Get-Tune -Title "$toComplete*" } else { Get-Tune }) @(foreach ($tune in $tunelist) { if ($tune.Title) { $tune.Title } }) -replace '^', "'" -replace '$',"'" })] [string] $Title, # If set, will invalidate the cache of tunes and reload any tunes. [switch] $Force ) begin { # If we do not have a tune cache, create one. if (-not $script:TuneCache) { $script:TuneCache = [Ordered]@{} } # Tune files can be .clixml, .json, .ps1, .psd1, or .txt $tuneExtensions = '.clixml','.json','.ps1', '.psd1', '.txt' # create a regex that will match any of them. $tuneFilePattern = "\.tune\.(?>$($tuneExtensions -replace '^\.' -join '|'))" } process { # If a -TunePath was not provided if (-not $TunePath) { $MyModuleInfo = $MyInvocation.MyCommand.Module # We will use the TerminalTunes module path $myModulePath = $MyModuleInfo | Split-Path # Any the module paths of any modules that Tag 'TerminalTunes' $relatedModulePaths = @( [ModuleRelationships()]$MyModuleInfo ) | Select-Object -ExpandProperty RelatedModule | Split-Path $TunePath = @($myModulePath) + @($relatedModulePaths) } # Now, create the tune list by walking thru each tune path $tunelist = @(foreach ($tp in $TunePath) { # get the path item $pathItem = Get-Item -Path $tp -ErrorAction Ignore if ($pathItem -is [IO.DirectoryInfo]) { # If it's a directory, call yourself recursively and cache it. if (-not $script:TuneCache.Contains($pathItem.FullName) -or $Force) { $script:TuneCache[$pathItem.FullName] = @( Get-ChildItem -Path $TunePath.Fullname -Recurse -Filter *.tune.* | Where-Object Extension -In $tuneExtensions | Get-Tune ) } if ($script:TuneCache.Contains($pathItem.FullName)) { $script:TuneCache[$pathItem.FullName] } } elseif ($pathItem -is [IO.FileInfo]) { # If the path was a file # skip it if it doesn't match our pattern. if ($pathItem.Name -notmatch $tuneFilePattern) { continue } if (-not $script:TuneCache.Contains($pathItem.FullName) -or $Force) { $tuneData = switch ($pathItem.Extension) { # If it was .clixml, just import-clixml '.clixml' { Import-Clixml -Path $pathItem.FullName } # If it was .json '.json' { Get-Content -Path $pathItem.FullName -Raw | ConvertFrom-Json | # convert from json ForEach-Object { if ($_.Tune) { # and fix escape sequences $_.Tune = $_.Tune -replace '[`\\]e', "`e" } $_ } } # If it was a .ps1 '.ps1' { # get the script. $ExecutionContext.SessionState.InvokeCommand.GetCommand($pathItem.FullName, 'ExternalScript') } # If it was a .PSD1 '.psd1' { # read the file as data language. [PSCustomObject](& ([ScriptBlock]::Create("data {$($(Get-Content -Path $pathItem.FullName -Raw)) }"))) } # If it was a .TXT file '.txt' { # Replace the file title and include the tune. [PSCustomObject][Ordered]@{ Title = $pathItem.Name -replace '\.tune\.txt$' -replace '[_-]', ' ' Tune = (Get-Content -Path $pathItem.FullName -Raw) -replace '[`\\]e', "`e" } } } # If we had no tune data, clear the cache at this point if (-not $tuneData) { $script:TuneCache[$pathItem.FullName] = $null continue } # Decorate all tune data as a 'TerminalTunes.Tune' [decorate('TerminalTunes.Tune',Clear)]$tuneData # If it was a script, if ($tuneData -is [Management.Automation.ExternalScriptInfo]) { # also decorate it to be a 'TerminalTunes.Generator' [decorate('TerminalTunes.Generator')]$tuneData } $script:TuneCache[$pathItem.FullName] = $tuneData } $tuneData = $script:TuneCache[$pathItem.FullName] if ($tuneData) { $tuneData } } }) # If -Title was provided if ($Title) { # filter the tunes by title $tuneList | Where-Object Title -Like $title } else { # otherwise, output all tunes. $tuneList } } } |