src/PowerShell/Parser.ps1
|
# cdp PowerShell domain: Parser.ps1 # Loaded by src/cdp.psm1; do not dot-source peer files. function New-CdpInvocation { param([string]$Kind) [PSCustomObject]@{ Kind = $Kind Command = $Kind ConfigPath = $null Query = $null Open = $null AllowHook = $false NoHook = $false DirtyOnly = $false Fix = $false Push = $false Json = $false NoColor = $false Refresh = $false ThrottleLimit = 0 DryRun = $false Yes = $false TagFilter = $null WorkspaceAction = $null WorkspaceName = $null WorkspaceLayout = $null ClearOpen = $false ExecSelectorKind = $null ExecProjectNames = @() ExecTag = $null ExecWorkspace = $null ExecAll = $false ExecCommand = $null ExecArguments = @() TimeoutSeconds = 0 FailFast = $false ExecContinue = $false Projects = @() Name = $null Value = $null RootPath = $null MaxDepth = 4 Count = 10 RecentAction = 'list' HookAction = $null } } function Get-CdpInvocationTokens { param([string]$Command, [string]$ConfigPath, [string[]]$RemainingArgs) $tokens = @() if (-not [string]::IsNullOrWhiteSpace($Command)) { $tokens += $Command } if (-not [string]::IsNullOrWhiteSpace($ConfigPath)) { $tokens += $ConfigPath } if ($null -ne $RemainingArgs) { $tokens += @($RemainingArgs) } @($tokens | Where-Object { -not [string]::IsNullOrWhiteSpace($_) }) } function Get-CdpRawInvocationTokens { param([string]$Command, [string]$ConfigPath, [string[]]$RemainingArgs) $tokens = @() if (-not [string]::IsNullOrEmpty($Command)) { $tokens += $Command } if (-not [string]::IsNullOrEmpty($ConfigPath)) { $tokens += $ConfigPath } if ($null -ne $RemainingArgs) { $tokens += @($RemainingArgs) } $tokens } function Split-CdpCommonOptions { param([string[]]$Tokens, [string]$Open) $positionals = New-Object 'System.Collections.Generic.List[string]' $resolvedOpen = $Open $resolvedConfig = $null $allowHook = $false $noHook = $false $dryRun = $false $assumeYes = $false for ($i = 0; $i -lt $Tokens.Count; $i++) { $token = $Tokens[$i] if ($token -in @('--open', '-open', '-o')) { if ($i + 1 -ge $Tokens.Count) { throw "Missing value after --open." } if (-not [string]::IsNullOrWhiteSpace($resolvedOpen)) { throw "The --open option was specified more than once." } $resolvedOpen = $Tokens[++$i] continue } if ($token -in @('--config', '-config')) { if ($i + 1 -ge $Tokens.Count) { throw "Missing value after --config." } if (-not [string]::IsNullOrWhiteSpace($resolvedConfig)) { throw "The --config option was specified more than once." } $resolvedConfig = $Tokens[++$i] continue } if ($token -in @('--allow-hook', '-allow-hook')) { $allowHook = $true continue } if ($token -in @('--no-hook', '-no-hook')) { $noHook = $true continue } if ($token -in @('--dry-run', '-dry-run')) { $dryRun = $true continue } if ($token -in @('--yes', '-yes')) { $assumeYes = $true continue } $positionals.Add($token) } if ($allowHook -and $noHook) { throw "The --allow-hook and --no-hook options cannot be used together." } if ($dryRun -and $assumeYes) { throw "The --dry-run and --yes options cannot be used together." } [PSCustomObject]@{ Tokens = @($positionals) Open = $resolvedOpen ConfigPath = $resolvedConfig AllowHook = $allowHook NoHook = $noHook DryRun = $dryRun Yes = $assumeYes } } function Resolve-CdpCommandKind { param([string]$Command) if ([string]::IsNullOrWhiteSpace($Command)) { return $null } switch -Regex ($Command.ToLowerInvariant()) { '^(status|st)$' { return 'status' } '^(workspace|ws)$' { return 'workspace' } '^(exec|run)$' { return 'exec' } '^(hook|hooks)$' { return 'hook' } '^(doctor|health|check)$' { return 'doctor' } '^(about|version|--version|-v)$' { return 'about' } '^(recent|recents|history)$' { return 'recent' } '^(pin|pinned|favorite|star)$' { return 'pin' } '^(unpin|unfavorite|unstar)$' { return 'unpin' } '^(alias|add-alias)$' { return 'alias' } '^(unalias|remove-alias)$' { return 'unalias' } '^(tag|add-tag)$' { return 'tag' } '^(untag|remove-tag)$' { return 'untag' } '^(clean|repair|fix)$' { return 'clean' } '^(add|add-project)$' { return 'add' } '^(remove|rm|delete)$' { return 'remove' } '^(init|setup)$' { return 'init' } '^(scan|import)$' { return 'scan' } '^(config|select-config)$' { return 'config' } default { return $null } } } function Split-CdpExecCommandBoundary { param([string[]]$Tokens) $boundary = [Array]::IndexOf($Tokens, '--') if ($boundary -lt 0) { throw 'cdp exec requires -- before the command.' } if ($boundary -eq ($Tokens.Count - 1)) { throw 'cdp exec requires a command after --.' } if ([string]::IsNullOrWhiteSpace($Tokens[$boundary + 1])) { throw 'cdp exec requires a non-empty command after --.' } [PSCustomObject]@{ Options = @($Tokens | Select-Object -First $boundary) Command = $Tokens[$boundary + 1] Arguments = @($Tokens | Select-Object -Skip ($boundary + 2)) } } function Test-CdpJsonRequested { param([string]$Command, [string]$ConfigPath, [string[]]$RemainingArgs) $tokens = @(Get-CdpRawInvocationTokens -Command $Command -ConfigPath $ConfigPath -RemainingArgs $RemainingArgs) if ($tokens.Count -eq 0) { return $false } if ((Resolve-CdpCommandKind -Command $tokens[0]) -eq 'exec') { $boundary = [Array]::IndexOf($tokens, '--') if ($boundary -ge 0) { $tokens = @($tokens | Select-Object -First $boundary) } } @($tokens | Where-Object { $_ -in @('--json', '-json') }).Count -gt 0 } function Set-CdpExecIntegerOption { param([object]$Result, [string]$Name, [string]$Value) $parsed = 0 $maximum = if ($Name -eq 'jobs') { 16 } else { 3600 } if (-not [int]::TryParse($Value, [ref]$parsed) -or $parsed -lt 1 -or $parsed -gt $maximum) { throw "Exec $Name must be an integer between 1 and $maximum." } if ($Name -eq 'jobs') { $Result.ThrottleLimit = $parsed } else { $Result.TimeoutSeconds = $parsed } } function Add-CdpExecSelectorToken { param([object]$Result, [string]$Token) if ([string]::IsNullOrWhiteSpace($Token)) { throw 'Exec project selector cannot be empty.' } if ($Token.StartsWith('@')) { if ($Result.ExecTag -or $Result.ExecProjectNames.Count -gt 0 -or $Result.ExecWorkspace -or $Result.ExecAll) { throw 'Exec selector types cannot be combined.' } if ($Token.Length -eq 1) { throw 'Exec tag selector cannot be empty.' } $Result.ExecTag = $Token.Substring(1) $Result.ExecSelectorKind = 'tag' return } if ($Result.ExecTag -or $Result.ExecWorkspace -or $Result.ExecAll) { throw 'Exec selector types cannot be combined.' } $Result.ExecProjectNames = @($Result.ExecProjectNames) + @($Token) $Result.ExecSelectorKind = 'projects' } function ConvertFrom-CdpExecTokens { param([string[]]$Tokens) $parts = Split-CdpExecCommandBoundary -Tokens $Tokens $result = New-CdpInvocation -Kind 'exec' $result.ExecCommand = $parts.Command $result.ExecArguments = @($parts.Arguments) for ($i = 0; $i -lt $parts.Options.Count; $i++) { $token = $parts.Options[$i] if ($token -in @('--config', '-config', '--workspace', '--jobs', '--timeout')) { if ($i + 1 -ge $parts.Options.Count) { throw "Missing value after $token." } $value = $parts.Options[++$i] if ($token -in @('--config', '-config')) { if ([string]::IsNullOrWhiteSpace($value)) { throw 'Exec config path cannot be empty.' } if ($result.ConfigPath) { throw 'The --config option was specified more than once.' } $result.ConfigPath = $value } elseif ($token -eq '--workspace') { if ($result.ExecSelectorKind) { throw 'Exec selector types cannot be combined.' } if ([string]::IsNullOrWhiteSpace($value)) { throw 'Exec workspace selector cannot be empty.' } $result.ExecWorkspace=$value; $result.ExecSelectorKind='workspace' } else { Set-CdpExecIntegerOption -Result $result -Name $token.TrimStart('-') -Value $value } continue } if ($token -eq '--all') { if ($result.ExecSelectorKind) { throw 'Exec selector types cannot be combined.' }; $result.ExecAll=$true; $result.ExecSelectorKind='all'; continue } if ($token -eq '--fail-fast') { if ($result.FailFast) { throw 'The --fail-fast option was specified more than once.' }; $result.FailFast=$true; continue } if ($token -eq '--continue') { $result.ExecContinue=$true; continue } if ($token -in @('--json', '-json')) { $result.Json=$true; continue } if ($token -in @('--dry-run', '-dry-run')) { $result.DryRun=$true; continue } if ($token -in @('--yes', '-yes')) { $result.Yes=$true; continue } if ($token.StartsWith('-')) { throw "Unknown exec option: $token" } Add-CdpExecSelectorToken -Result $result -Token $token } if (-not $result.ExecSelectorKind) { throw 'cdp exec requires projects, @tag, --workspace, or --all.' } if ($result.FailFast -and $result.ExecContinue) { throw 'The --fail-fast and --continue options cannot be used together.' } if ($result.DryRun -and $result.Yes) { throw 'The --dry-run and --yes options cannot be used together.' } $result } function ConvertFrom-CdpStatusTokens { param([string[]]$Tokens, [string]$ConfigPath, [bool]$DryRun, [bool]$Yes) $result = New-CdpInvocation -Kind 'status' $result.ConfigPath = $ConfigPath $result.DryRun = $DryRun $result.Yes = $Yes for ($i = 0; $i -lt $Tokens.Count; $i++) { $token = $Tokens[$i] if ($token -in @('--dirty', '-dirty', '-d')) { $result.DirtyOnly = $true; continue } if ($token -in @('--fix', '-fix')) { $result.Fix = $true; continue } if ($token -in @('--push', '-push')) { $result.Push = $true; continue } if ($token -in @('--json', '-json')) { $result.Json = $true; continue } if ($token -in @('--no-color', '-no-color')) { $result.NoColor = $true; continue } if ($token -in @('--refresh', '-refresh')) { $result.Refresh = $true; continue } if ($token -in @('--jobs', '-jobs', '--concurrency')) { if ($i + 1 -ge $Tokens.Count) { throw "Missing value after --jobs." } $jobs = 0 if (-not [int]::TryParse($Tokens[++$i], [ref]$jobs) -or $jobs -lt 1 -or $jobs -gt 16) { throw "Status jobs must be an integer between 1 and 16." } $result.ThrottleLimit = $jobs continue } if ($token -in @('--dry-run', '-dry-run')) { $result.DryRun = $true; continue } if ($token -in @('--yes', '-yes')) { $result.Yes = $true; continue } if ($token.StartsWith('@')) { if ($result.TagFilter) { throw "Only one status tag filter can be specified." } $result.TagFilter = $token continue } if ($token.StartsWith('-')) { throw "Unknown status option: $token" } if ($result.ConfigPath) { throw "Only one status config path can be specified." } $result.ConfigPath = $token } if ($result.Fix -and $result.Push) { throw "The --fix and --push actions cannot be used together." } if ($result.DirtyOnly -and ($result.Fix -or $result.Push)) { throw "The --dirty filter and status actions cannot be used together." } if ($result.Json -and $result.NoColor) { throw "The --json and --no-color options cannot be used together." } if ($result.Json -and ($result.Fix -or $result.Push)) { throw "The --json option is only valid for read-only status." } if ($result.NoColor -and ($result.Fix -or $result.Push)) { throw "The --no-color option is only valid for read-only status." } if ($result.DryRun -and $result.Yes) { throw "The --dry-run and --yes options cannot be used together." } if (($result.DryRun -or $result.Yes) -and -not ($result.Fix -or $result.Push)) { throw "The --dry-run and --yes options require --fix or --push." } $result } function Split-CdpWorkspaceOptions { param([string[]]$Tokens) $result = [PSCustomObject]@{ Tokens=@(); Layout=$null; ClearOpen=$false; Fix=$false } $items = New-Object 'System.Collections.Generic.List[string]' for ($i = 0; $i -lt $Tokens.Count; $i++) { if ($Tokens[$i] -in @('--layout', '-layout')) { if ($i + 1 -ge $Tokens.Count) { throw 'Missing value after --layout.' } if ($result.Layout) { throw 'The --layout option was specified more than once.' } $result.Layout = $Tokens[++$i] } elseif ($Tokens[$i] -in @('--clear-open', '-clear-open')) { $result.ClearOpen = $true } elseif ($Tokens[$i] -in @('--fix', '-fix')) { $result.Fix = $true } else { $items.Add($Tokens[$i]) } } $result.Tokens = @($items) $result } function Set-CdpWorkspaceReadAction { param([object]$Result, [string]$Action, [string[]]$Tokens, [string]$Open, [bool]$DryRun, [bool]$Yes) if ($Action -eq 'list') { if ($DryRun -or $Yes) { throw 'Workspace --list does not accept safety options.' } if ($Open) { throw 'The --open option is not valid with workspace --list.' } if ($Tokens.Count -ne 1) { throw 'Workspace --list does not accept project arguments.' } } else { if ($Tokens.Count -ne 2) { throw "Workspace $Action requires one workspace name." } if ($Open -or $Result.WorkspaceLayout -or $Result.ClearOpen -or $Result.Fix) { throw "Workspace $Action does not accept update options." } if (($DryRun -or $Yes) -and $Action -eq 'show') { throw 'Workspace show does not accept safety options.' } $Result.WorkspaceName = $Tokens[1] } $Result.WorkspaceAction = $Action $Result } function Set-CdpWorkspaceValidateAction { param([object]$Result, [string[]]$Tokens, [string]$Open, [bool]$DryRun, [bool]$Yes) if ($Tokens.Count -gt 2) { throw 'Workspace validate accepts at most one workspace name.' } if ($Open -or $Result.WorkspaceLayout -or $Result.ClearOpen) { throw 'Workspace validate does not accept launcher or layout options.' } if (($DryRun -or $Yes) -and -not $Result.Fix) { throw 'Workspace validate safety options require --fix.' } $Result.WorkspaceAction = 'validate' if ($Tokens.Count -eq 2) { $Result.WorkspaceName = $Tokens[1] } $Result } function Set-CdpWorkspaceWriteAction { param([object]$Result, [string]$Action, [string[]]$Tokens, [string]$Open) if ($Action -eq 'add') { if ($Tokens.Count -lt 3) { throw 'Workspace --add requires a name and at least one project.' } if ($Result.ClearOpen -or $Result.Fix) { throw 'Workspace add does not accept --clear-open or --fix.' } } else { if ($Tokens.Count -lt 2) { throw 'Workspace edit requires one workspace name.' } if ($Result.Fix) { throw 'Workspace edit does not accept --fix.' } if ($Open -and $Result.ClearOpen) { throw 'Workspace --open and --clear-open cannot be used together.' } } $Result.WorkspaceAction = $Action $Result.WorkspaceName = $Tokens[1] $Result.Projects = @($Tokens | Select-Object -Skip 2) if ($Action -eq 'edit' -and $Result.Projects.Count -eq 0 -and -not $Open -and -not $Result.ClearOpen -and -not $Result.WorkspaceLayout) { throw 'Workspace edit requires projects or an open/layout update.' } $Result } function ConvertFrom-CdpWorkspaceTokens { param([string[]]$Tokens, [string]$ConfigPath, [string]$Open, [bool]$DryRun, [bool]$Yes) $result = New-CdpInvocation -Kind "workspace" $result.ConfigPath = $ConfigPath $result.Open = $Open $result.DryRun = $DryRun $result.Yes = $Yes $options = Split-CdpWorkspaceOptions -Tokens $Tokens $result.WorkspaceLayout = $options.Layout $result.ClearOpen = $options.ClearOpen $result.Fix = $options.Fix $Tokens = @($options.Tokens) if ($Tokens.Count -eq 0) { if ($DryRun -or $Yes) { throw "Workspace safety options require --add or a workspace name." } if ($Open) { throw "The --open option requires a workspace name or --add action." } $result.WorkspaceAction = "usage" return $result } $action = $Tokens[0].ToLowerInvariant() if ($action -in @("--list", "-l", "list")) { return Set-CdpWorkspaceReadAction $result list $Tokens $Open $DryRun $Yes } if ($action -in @("show", "remove")) { return Set-CdpWorkspaceReadAction $result $action $Tokens $Open $DryRun $Yes } if ($action -eq "validate") { return Set-CdpWorkspaceValidateAction $result $Tokens $Open $DryRun $Yes } if ($action -in @("--add", "-a", "add")) { return Set-CdpWorkspaceWriteAction $result add $Tokens $Open } if ($action -eq "edit") { return Set-CdpWorkspaceWriteAction $result edit $Tokens $Open } if ($action -eq "open") { if ($Tokens.Count -ne 2) { throw "Workspace open requires one workspace name." } if ($result.WorkspaceLayout -or $result.ClearOpen -or $result.Fix) { throw "Workspace open does not accept layout/update options." } $result.WorkspaceAction = "open" $result.WorkspaceName = $Tokens[1] return $result } if ($Tokens.Count -ne 1) { throw "Workspace launch accepts one workspace name." } if ($Tokens[0].StartsWith("-")) { throw "Unknown workspace option: $($Tokens[0])" } if ($result.WorkspaceLayout -or $result.ClearOpen -or $result.Fix) { throw "Workspace launch does not accept layout/update options." } $result.WorkspaceAction = "open" $result.WorkspaceName = $Tokens[0] $result } function Set-CdpTrailingConfigPath { param([object]$Result, [string[]]$Arguments, [int]$RequiredCount) if ($Arguments.Count -lt $RequiredCount -or $Arguments.Count -gt ($RequiredCount + 1)) { throw "Invalid arguments for cdp $($Result.Kind)." } if ($Arguments.Count -eq ($RequiredCount + 1)) { if ($Result.ConfigPath) { throw "The config path was specified more than once." } $Result.ConfigPath = $Arguments[-1] } } function ConvertFrom-CdpManagementTokens { param([string]$Kind, [string[]]$Tokens, [string]$ConfigPath, [bool]$DryRun, [bool]$Yes) $result = New-CdpInvocation -Kind $Kind $result.ConfigPath = $ConfigPath $result.DryRun = $DryRun $result.Yes = $Yes if ($Kind -eq 'doctor') { $items = @($Tokens | Where-Object { if ($_ -in @('--fix', '-fix')) { $result.Fix = $true; $false } else { $true } }) Set-CdpTrailingConfigPath -Result $result -Arguments $items -RequiredCount 0 } elseif ($Kind -eq 'hook') { if ($Tokens.Count -lt 1) { throw "Hook requires list, trust, or revoke." } $result.HookAction = $Tokens[0].ToLowerInvariant() if ($result.HookAction -notin @('list', 'trust', 'revoke')) { throw "Unknown hook action." } if ($result.HookAction -eq 'list') { Set-CdpTrailingConfigPath -Result $result -Arguments @($Tokens | Select-Object -Skip 1) -RequiredCount 0 } else { Set-CdpTrailingConfigPath -Result $result -Arguments @($Tokens | Select-Object -Skip 1) -RequiredCount 1 $result.Name = $Tokens[1] } } elseif ($Kind -in @('about', 'clean')) { Set-CdpTrailingConfigPath -Result $result -Arguments $Tokens -RequiredCount 0 } elseif ($Kind -eq 'config') { if ($Tokens.Count -gt 1) { throw "Config selection accepts one numeric selection." } if ($Tokens.Count -eq 1) { $selection = 0 if (-not [int]::TryParse($Tokens[0], [ref]$selection) -or $selection -lt 1) { throw "Config selection must be a positive integer." } $result.Count = $selection } else { $result.Count = 0 } } elseif ($Kind -eq 'recent') { if ($Tokens.Count -eq 1 -and $Tokens[0].ToLowerInvariant() -eq 'reset') { $result.RecentAction = 'reset' } elseif ($Tokens.Count -gt 1) { throw "Recent accepts a positive count or reset." } elseif ($Tokens.Count -eq 1) { $recentCount = 0 if (-not [int]::TryParse($Tokens[0], [ref]$recentCount)) { throw "Recent count must be a positive integer." } $result.Count = $recentCount } if ($result.RecentAction -eq 'list' -and $result.Count -le 0) { throw "Recent count must be a positive integer." } } elseif ($Kind -in @('pin', 'unpin', 'remove')) { Set-CdpTrailingConfigPath -Result $result -Arguments $Tokens -RequiredCount 1 $result.Name = $Tokens[0] } elseif ($Kind -eq 'add') { if ($Tokens.Count -gt 3) { throw "Add accepts a name, path, and optional config path." } if ($Tokens.Count -gt 0) { $result.Name = $Tokens[0] } if ($Tokens.Count -gt 1) { $result.RootPath = $Tokens[1] } if ($Tokens.Count -gt 2) { if ($result.ConfigPath) { throw "The config path was specified more than once." } $result.ConfigPath = $Tokens[2] } } elseif ($Kind -in @('alias', 'unalias', 'tag', 'untag')) { Set-CdpTrailingConfigPath -Result $result -Arguments $Tokens -RequiredCount 2 $result.Name = $Tokens[0] $result.Value = $Tokens[1] } else { $result = ConvertFrom-CdpScanTokens -Kind $Kind -Tokens $Tokens -ConfigPath $ConfigPath } $result.DryRun = $DryRun $result.Yes = $Yes $isMutation = $Kind -in @('clean', 'add', 'remove', 'pin', 'unpin', 'alias', 'unalias', 'tag', 'untag', 'init', 'scan', 'config') if ($Kind -eq 'doctor') { $isMutation = $result.Fix } if ($Kind -eq 'hook') { $isMutation = $result.HookAction -in @('trust', 'revoke') } if ($Kind -eq 'recent') { $isMutation = $result.RecentAction -eq 'reset' } if (($DryRun -or $Yes) -and -not $isMutation) { throw "Safety options are only valid for mutating commands." } $result } function ConvertFrom-CdpScanTokens { param([string]$Kind, [string[]]$Tokens, [string]$ConfigPath) $result = New-CdpInvocation -Kind $Kind $result.ConfigPath = $ConfigPath if ($Tokens.Count -gt 0) { $result.RootPath = $Tokens[0] } $depthSet = $false foreach ($token in @($Tokens | Select-Object -Skip 1)) { $depth = 0 if ([int]::TryParse($token, [ref]$depth)) { if ($depthSet -or $depth -lt 1) { throw "Max depth must be one positive integer." } $result.MaxDepth = $depth $depthSet = $true } elseif (-not $result.ConfigPath) { $result.ConfigPath = $token } else { throw "The config path was specified more than once." } } $result } function ConvertFrom-CdpSwitchTokens { param([string[]]$Tokens, [string]$Query, [string]$ConfigPath, [string]$Open, [bool]$AllowHook, [bool]$NoHook, [bool]$DryRun, [bool]$Yes) if ($DryRun -or $Yes) { throw "Safety options are not valid for project switching." } $result = New-CdpInvocation -Kind 'switch' $result.Query = $Query $result.ConfigPath = $ConfigPath $result.Open = $Open $result.AllowHook = $AllowHook $result.NoHook = $NoHook $items = @($Tokens) if ([string]::IsNullOrWhiteSpace($result.Query) -and $items.Count -gt 0 -and -not (Test-CdpConfigPathArgument $items[0])) { $result.Query = $items[0] $items = @($items | Select-Object -Skip 1) } if ($items.Count -gt 1) { throw "Project switching accepts one query and one config path." } if ($items.Count -eq 1) { if ($items[0].StartsWith('-')) { throw "Unknown cdp option: $($items[0])" } if ($result.ConfigPath) { throw "The config path was specified more than once." } $result.ConfigPath = $items[0] } $result } function ConvertFrom-CdpInvokeArguments { param([string]$Command, [string]$ConfigPath, [string]$Query, [string]$Open, [string[]]$RemainingArgs) $rawTokens = @(Get-CdpRawInvocationTokens -Command $Command -ConfigPath $ConfigPath -RemainingArgs $RemainingArgs) if ($rawTokens.Count -gt 0 -and (Resolve-CdpCommandKind -Command $rawTokens[0]) -eq 'exec') { if ($Open -or $Query) { throw 'Project switching options are not valid for exec.' } return ConvertFrom-CdpExecTokens -Tokens @($rawTokens | Select-Object -Skip 1) } $tokens = @(Get-CdpInvocationTokens -Command $Command -ConfigPath $ConfigPath -RemainingArgs $RemainingArgs) $common = Split-CdpCommonOptions -Tokens $tokens -Open $Open $tokens = @($common.Tokens) $kind = if ($tokens.Count -gt 0) { Resolve-CdpCommandKind -Command $tokens[0] } else { $null } if ($kind -eq 'hook' -and ($tokens.Count -lt 2 -or $tokens[1].ToLowerInvariant() -notin @('list', 'trust', 'revoke'))) { $kind = $null } if ($kind) { $tokens = @($tokens | Select-Object -Skip 1) } if ($kind -eq 'status') { if ($common.Open) { throw "The --open option is not valid for status." } if ($common.AllowHook -or $common.NoHook) { throw "Hook options are only valid for project switching." } return ConvertFrom-CdpStatusTokens -Tokens $tokens -ConfigPath $common.ConfigPath -DryRun $common.DryRun -Yes $common.Yes } if ($kind -eq 'workspace') { if ($common.AllowHook -or $common.NoHook) { throw "Hook options are only valid for project switching." } return ConvertFrom-CdpWorkspaceTokens -Tokens $tokens -ConfigPath $common.ConfigPath -Open $common.Open -DryRun $common.DryRun -Yes $common.Yes } if ($kind) { if ($common.Open) { throw "The --open option is only valid for project and workspace commands." } if ($common.AllowHook -or $common.NoHook) { throw "Hook options are only valid for project switching." } return ConvertFrom-CdpManagementTokens -Kind $kind -Tokens $tokens -ConfigPath $common.ConfigPath -DryRun $common.DryRun -Yes $common.Yes } ConvertFrom-CdpSwitchTokens ` -Tokens $tokens ` -Query $Query ` -ConfigPath $common.ConfigPath ` -Open $common.Open ` -AllowHook $common.AllowHook ` -NoHook $common.NoHook ` -DryRun $common.DryRun ` -Yes $common.Yes } |