public/Set-CdExtrasOption.ps1
|
<# .SYNOPSIS Update cd-extras option ('AUTO_CD', 'CD_PATH', ...etc). .PARAMETER Option The option to update. .PARAMETER Value The new value. .PARAMETER Options A dictionary of options and values to update. .EXAMPLE PS C:\> setocd AUTO_CD Enables AUTO_CD .EXAMPLE PS C:\> setocd AUTO_CD $false Disables AUTO_CD .EXAMPLE PS C:\> Set-CdExtrasOption -Option CD_PATH -Value @('/temp') Set the directory search paths to the single directory, '/temp' .EXAMPLE PS C:\> Set-CdExtrasOption -Options ([ordered]@{ MaxRecentDirs = 100; AUTO_CD = $false }) Set several options from any dictionary that implements System.Collections.IDictionary. #> function Set-CdExtrasOption { [OutputType([void], [bool])] [CmdletBinding(DefaultParameterSetName = 'Set')] param ( [ArgumentCompleter( { $global:cde | Get-Member -Type Property -Name "$($args[2])*" | % Name })] [Parameter(ParameterSetName = 'Set', Mandatory, Position = 0)] [string] $Option, [Parameter(ParameterSetName = 'Set', Position = 1, ValueFromPipeline)] $Value, [Parameter(ParameterSetName = 'SetMany', Mandatory, Position = 0)] [Collections.IDictionary] $Options, [Parameter(ParameterSetName = 'Validate', Mandatory)] [switch] $Validate ) # first update the $cde variable per the given settings if ($PSCmdlet.ParameterSetName -eq 'Set' -or $PSCmdlet.ParameterSetName -eq 'SetMany') { $flags = @( 'AUTO_CD' 'CDABLE_VARS' 'ColorCompletion' 'IndexedCompletion' 'RecentDirsFallThrough' ) $completionTypes = @( 'PathCompletions' 'DirCompletions' 'FileCompletions' ) $optionNames = if ($PSCmdlet.ParameterSetName -eq 'Set') { @($Option) } else { @($Options.Keys) } $publicPropertyNames = @($Global:cde | Get-Member -Type Property).Name $updates = @() foreach ($optionName in $optionNames) { $propertyName = $publicPropertyNames | Where-Object { $_ -eq $optionName } | Select-Object -First 1 if (!$propertyName) { $exception = [ArgumentException]::new("Unknown cd-extras option '$optionName'.") $errorRecord = [Management.Automation.ErrorRecord]::new( $exception, 'UnknownCdExtrasOption', [Management.Automation.ErrorCategory]::InvalidArgument, $optionName ) $PSCmdlet.ThrowTerminatingError($errorRecord) } $property = $Global:cde.PSObject.Properties[$propertyName] $optionValue = if ($PSCmdlet.ParameterSetName -eq 'SetMany') { $Options[$optionName] } else { $Value } if ($PSCmdlet.ParameterSetName -eq 'Set' -and $null -eq $optionValue -and $property.Name -in $flags) { $optionValue = $true } $propertyType = [type]$property.TypeNameOfValue try { $convertedValue = [Management.Automation.LanguagePrimitives]::ConvertTo($optionValue, $propertyType) } catch { $exception = [ArgumentException]::new( "Invalid value for cd-extras option '$($property.Name)'. Expected $propertyType.", $_.Exception ) $errorRecord = [Management.Automation.ErrorRecord]::new( $exception, 'InvalidCdExtrasOptionValue', [Management.Automation.ErrorCategory]::InvalidArgument, $optionValue ) $PSCmdlet.ThrowTerminatingError($errorRecord) } if ($property.Name -in $completionTypes) { $combined = @($property.Value) foreach ($completion in $convertedValue) { if ($combined -notcontains $completion) { $combined += $completion } } $convertedValue = [string[]]$combined } $updates += [pscustomobject]@{ Name = $property.Name; Value = $convertedValue } } foreach ($update in $updates) { $Global:cde.($update.Name) = $update.Value } } # then perform various side effects based on the current settings if ($cde.RECENT_DIRS_FILE) { $path = $cde.RECENT_DIRS_FILE -replace '~', $HOME $cde.RECENT_DIRS_FILE = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath( $path ) OpenRecentStore } $cde.RECENT_DIRS_EXCLUDE = $cde.RECENT_DIRS_EXCLUDE.ForEach{ Resolve-Path $_ } if ($cde.DirCompletions) { RegisterCompletions $cde.DirCompletions 'Path' { CompletePaths -dirsOnly @args } } if ($cde.FileCompletions) { RegisterCompletions $cde.FileCompletions 'Path' { CompletePaths -filesOnly @args } } if ($cde.PathCompletions) { RegisterCompletions $cde.PathCompletions 'Path' { CompletePaths @args } } $isUnderTest = { $Script:__cdeUnderTest -and !($Script:__cdeUnderTest = $false) } if ($cde.AUTO_CD) { CommandNotFound @(AutoCd) $isUnderTest } else { CommandNotFound @() $isUnderTest } # can be used to ensure side effects have run without actually changing any options # this is used when the $cde variable is updated directly if ($Validate) { return $true } } |