src/functions/qconf.ps1
|
function Invoke-QConf { [CmdletBinding()] param( [ValidateSet("set", "get", "list", "help", "init")] $command, [ArgumentCompleter({ param ($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters) try { # ipmo configmap $map = $fakeBoundParameters.map $map = $map -is [System.Collections.IDictionary] ? $map : (Resolve-ConfigMap $map -fallback ".configuration.map.ps1" | % { $_ -is [string] ? (. $_) : $_ } | Assert-ConfigMap) if (!$map) { return @("init", "help", "list") | ? { $_.startswith($wordToComplete) } } return Get-EntryCompletion $map -language "conf" @PSBoundParameters } catch { return "ERROR [-entry]: $($_.Exception.Message) $($_.ScriptStackTrace)" } })] $entry = $null, [ArgumentCompleter({ param ($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters) try { if ($fakeBoundParameters.command -in @("init", "help")) { return @() } $map = $fakeBoundParameters.map $map = Resolve-ConfigMap $map -fallback ".configuration.map.ps1" | ForEach-Object { $_ -is [string] ? (. $_) : $_ } | Assert-ConfigMap $entry = $fakeBoundParameters.entry $entry = Get-MapEntry $map $entry if (!$entry) { throw "entry '$entry' not found" } $options = Get-CompletionList $entry -listKey "options" -reservedKeys $script:languages.conf.reservedKeys -maxDepth 1 return $options.Keys | ? { $_.startswith($wordToComplete) } } catch { return "ERROR [-value]: $($_.Exception.Message) $($_.ScriptStackTrace)" } })] $value = $null, $map = "./.configuration.map.ps1" ) ## we need dynamic parameters for commands that have custom parameter list ## this assumes that -entry and -command are already provided dynamicparam { # ipmo configmap try { if ( !$entry) { return @() } $map = Resolve-ConfigMap $map -fallback ".configuration.map.ps1" | ForEach-Object { $_ -is [string] ? (. $_) : $_ } | Assert-ConfigMap $skip = switch ($command) { "set" { 3 } default { 0 } } return Get-EntryDynamicParam $map "$entry.$command" -skip $skip -bound $PSBoundParameters } catch { return "ERROR [dynamic]: $($_.Exception.Message) $($_.ScriptStackTrace)" } } process { if ($command -eq "help") { Write-Host "QCONF" Write-Host "A command line tool to manage configuration maps" Write-Host "" Write-Host "Usage:" Write-Host "qconf -entry <entry> -command <command> -value <value>" return } if ($command -eq "init") { if (!$map) { $map = "./.configuration.map.ps1" } if ($map -is [string]) { if ((Test-Path $map)) { throw "map file '$map' already exists" } } else { throw "Map appears to be an object, not a file" } Initialize-ConfigMap -file $map return } $map = $map -is [System.Collections.IDictionary] ? $map : (Resolve-ConfigMap $map | ForEach-Object { $_ -is [string] ? (. $_) : $_ } | Assert-ConfigMap) if (-not $entry -and -not $command) { Write-MapHelp -map $map -invocation $MyInvocation -language "conf" return } if ($command -and -not $entry) { } Write-Verbose "entry=$entry command=$command" switch ($command) { "set" { $subEntry = $map.$entry if (!$subEntry) { throw "entry '$entry' not found" } $optionKey = $value $options = Get-CompletionList $subEntry -listKey "options" -reservedKeys $script:languages.conf.reservedKeys -maxDepth 1 $optionValue = $options.$optionKey $bound = $PSBoundParameters $bound.key = $optionKey $bound.value = $optionValue Invoke-Set $subEntry -ordered "", $optionValue, $optionKey -bound $bound } "get" { $entries = $entry if (!$entries) { # not passing -listKey "options" here, as we don't want to expand options - we just need top-level keys $entries = (Get-CompletionList $map -reservedKeys $script:languages.conf.reservedKeys).Keys } foreach ($entry in @($entries)) { try { $subEntry = $map.$entry $options = Get-CompletionList $subEntry -listKey "options" -reservedKeys $script:languages.conf.reservedKeys -maxDepth 1 $bound = $PSBoundParameters $bound.options = $options $value = Invoke-Get $subEntry -bound $bound $result = ConvertTo-MapResult $value $entry $subEntry $options $result | Write-Output } catch { if ($env:QCONF_DEBUG -eq "1") { throw $_ } Write-Error "Error getting value for entry '$entry': $($_.Exception.Message)" } } } default { throw "command '$command' not supported" } } } } function ConvertTo-MapResult($value, $entryName, $entry, $options, $validate = $true) { $result = $null if ($value -is [Hashtable]) { $hash = @{ Path = "$entryName/$subPath" } $hash += $value $result = $hash } else { $result = @{ Path = "$entryName/$subPath" Value = $value } } if (!$result.Active) { $result.Active = $options.keys | where { $options.$_ -eq $value } } $result.Options = $options.keys $isvalid = "?" if ($validate -and $entry.validate) { if (!$result.Active) { Write-Warning "no active option found for $entryName/$subPath" $isvalid = $null } else { $optionvalue = $options.$($result.Active) $isvalid = Invoke-EntryCommand $entry validate -ordered @($path, $optionvalue, $result.Active) } } $result = [PSCustomObject]@{ Path = $result.Path Value = $result.Value Active = $result.Active Options = $result.Options IsValid = $isvalid } return $result } Set-Alias -Name "qconf" -Value "Invoke-QConf" -Force |