Completions/scoop.ps1
# Modified From: https://github.com/Moeologist/scoop-completion/blob/master/src/scoop-completion.psm1 (MIT License) # This source code is licensed under the MIT License # Project URL - https://github.com/Moeologist/scoop-completion # Thanks to Posh-Git - https://github.com/dahlbyk/posh-git # See scoop/lib/core.ps1 function script:load_cfg($file) { if (!(Test-Path $file)) { return $null } try { return (Get-Content $file -Raw | ConvertFrom-Json -ErrorAction Stop) } catch { } } $script:configHome = $env:XDG_CONFIG_HOME, "$env:USERPROFILE\.config" | Select-Object -First 1 $script:configFile = "$configHome\scoop\config.json" $script:scoopConfig = load_cfg $script:configFile function script:get_config($name, $default) { if ($null -eq $scoopConfig.$name -and $null -ne $default) { return $default } return $scoopConfig.$name } try { $Script:scoopdir = $env:SCOOP, (get_config 'root_path'), "$env:USERPROFILE\scoop" | Where-Object { -not [String]::IsNullOrEmpty($_) } | Select-Object -First 1 } catch { Write-Warning 'No scoop installed!' } $script:aliasMap = get_config 'alias' # See scoop/libexec/ $script:ScoopCommands = @( 'alias', 'bucket', 'cache', 'cat', 'checkup', 'cleanup', 'config', 'create', 'depends', 'download', 'export', 'help', 'hold', 'home', 'import', 'info', 'install', 'list', 'prefix', 'reset', 'search', 'shim', 'status', 'unhold', 'uninstall', 'update', 'virustotal', 'which' ) # See scoop/libexec/scoop-config.ps1 $script:ScoopConfigParams = @( # 'last_update' would be set by scoop 'use_external_7zip', 'use_lessmsi', 'no_junction', 'scoop_repo', 'scoop_branch', 'proxy', 'autostash_on_conflict', 'default_architecture', 'debug', 'force_update', 'show_update_log', 'show_manifest', 'shim', 'root_path', 'global_path', 'cache_path', 'gh_token', 'virustotal_api_key', 'cat_style', 'ignore_running_processes', 'private_hosts', 'hold_update_until', 'aria2-enabled', 'aria2-warning-enabled', 'aria2-retry-wait', 'aria2-split', 'aria2-max-connection-per-server', 'aria2-min-split-size', 'aria2-options' ) $script:ScoopSubcommands = @{ alias = 'add list rm' bucket = 'add list known rm' cache = 'rm show' config = (@('rm') + $script:ScoopConfigParams) -join ' ' # add 'rm' to config shim = 'add list rm info alter' } $script:ScoopShortParams = @{ install = 'g i k u s a' uninstall = 'g p' cleanup = 'g' virustotal = 'a s n' update = 'f g i k s q a' shim = 'g' download = 'f h u a' status = 'l' } $script:ScoopLongParams = @{ install = 'global independent no-cache no-update-scoop skip arch' uninstall = 'global purge' cleanup = 'global' virustotal = 'arch scan no-depends' update = 'force global independent no-cache skip quiet all' shim = 'global' download = 'force no-hash-check no-update-scoop arch' status = 'local' } $script:ScoopParamValues = @{ install = @{ a = '32bit 64bit' arch = '32bit 64bit' } virustotal = @{ a = '32bit 64bit' arch = '32bit 64bit' } download = @{ a = '32bit 64bit' arch = '32bit 64bit' } } # See scoop/libexec/scoop-config.ps1 # TODO:display explanation of these settings $script:ScoopConfigParamValues = @{ use_external_7zip = 'true false' use_lessmsi = 'true false' no_junction = 'true false' # scoop_repo scoop_branch = 'master develop' # proxy autostash_on_conflict = 'true false' default_architecture = '32bit 64bit' debug = 'true false' force_update = 'true false' show_update_log = 'true false' show_manifest = 'true false' shim = 'kiennq scoopcs 71' # root_path # global_path # cache_path # gh_token # virustotal_api_key cat_style = 'default auto full plain changes header header-filename header-filesize grid rule numbers snip' ignore_running_processes = 'true false' # private_hosts # hold_update_until "aria2-enabled" = 'true false' "aria2-warning-enabled" = 'true false' # 'aria2-retry-wait' # 'aria2-split', # 'aria2-max-connection-per-server', # 'aria2-min-split-size', # 'aria2-options' } $script:ScoopCommandsWithLongParams = $ScoopLongParams.Keys -join '|' $script:ScoopCommandsWithShortParams = $ScoopShortParams.Keys -join '|' $script:ScoopCommandsWithParamValues = $ScoopParamValues.Keys -join '|' # 6> redirect Write-Host's output, (〒︿〒) function script:ScoopAlias($filter) { if ($null -ne $script:aliasMap) { @($script:aliasMap.PSObject.Properties | Select-Object Name | ForEach-Object { $_.Name } Where-Object { $_ -like "$filter*" } ) } else { @() } } function script:ScoopExpandCmdParams($commands, $command, $filter) { $commands.$command -split ' ' | Where-Object { $_ -like "$filter*" } } function script:ScoopExpandCmd($filter, $includeAliases) { $cmdList = @() $cmdList += $ScoopCommands if ($includeAliases) { $cmdList += ScoopAlias($filter) } $cmdList -like "$filter*" | Sort-Object } function script:ScoopLocalPackages($filter) { @(& Get-ChildItem -Path $script:scoopdir\apps -Name -Directory | Where-Object { $_ -ne "scoop" } | Where-Object { $_ -like "$filter*" } ) } function script:ScoopConfigParamsFilter($filter) { $ScoopConfigParams -like "$filter*" } function script:ScoopExpandConfigParamValues($param, $filter) { $ScoopConfigParamValues[$param] -split ' ' | Where-Object { $_ -like "$filter*" } | Sort-Object } function script:ScoopRemotePackages($filter) { @(& Get-ChildItem -Path $script:scoopdir\buckets\ -Name | ForEach-Object { Get-ChildItem -Path $script:scoopdir\buckets\$_\bucket -Name -Filter *.json } | ForEach-Object { if ( $_ -match '^([\w][\-\.\w]*)\.json$' ) { "$($Matches[1])" } } | Where-Object { $_ -like "$filter*" } ) } function script:ScoopLocalCaches($filter) { @(& scoop cache show | Select-Object -ExpandProperty Name | Sort-Object -Unique | Where-Object { $_ -like "$filter*" } ) } function script:ScoopLocalBuckets($filter) { @(& scoop bucket list | Where-Object { $_ -like "$filter*" }) } function script:ScoopRemoteBuckets($filter) { @(& scoop bucket known | Where-Object { $_ -like "$filter*" }) } function script:ScoopExpandLongParams($cmd, $filter) { $ScoopLongParams[$cmd] -split ' ' | Where-Object { $_ -like "$filter*" } | Sort-Object | ForEach-Object { -join ("--", $_) } } function script:ScoopExpandShortParams($cmd, $filter) { $ScoopShortParams[$cmd] -split ' ' | Where-Object { $_ -like "$filter*" } | Sort-Object | ForEach-Object { -join ("-", $_) } } function script:ScoopExpandParamValues($cmd, $param, $filter) { $ScoopParamValues[$cmd][$param] -split ' ' | Where-Object { $_ -like "$filter*" } | Sort-Object } function script:ScoopTabExpansion($lastBlock) { switch -regex ($lastBlock) { # Handles Scoop <cmd> --<param> <value> "^(?<cmd>$ScoopCommandsWithParamValues).* --(?<param>.+) (?<value>\w*)$" { if ($ScoopParamValues[$matches['cmd']][$matches['param']]) { return ScoopExpandParamValues $matches['cmd'] $matches['param'] $matches['value'] } } # Handles Scoop <cmd> -<shortparam> <value> "^(?<cmd>$ScoopCommandsWithParamValues).* -(?<param>.+) (?<value>\w*)$" { if ($ScoopParamValues[$matches['cmd']][$matches['param']]) { return ScoopExpandParamValues $matches['cmd'] $matches['param'] $matches['value'] } } # Handles uninstall package names "^(uninstall|cleanup|virustotal|update|prefix|reset|hold|unhold)\s+(?:.+\s+)?(?<package>[\w][\-\.\w]*)?$" { return ScoopLocalPackages $matches['package'] } # Handles download and cat package names "^(download|cat)\s+(?:.+\s+)?(?<package>[\w][\-\.\w]*)?$" { return ScoopRemotePackages $matches['package'] + ScoopLocalPackages $matches['package'] } # Handles config param names "^config rm\s+(?:.+\s+)?(?<param>[\w][\-\.\w]*)?$" { return script:ScoopConfigParamsFilter $matches['param'] } # Handles install package names "^(install|info|home|depends)\s+(?:.+\s+)?(?<package>[\w][\-\.\w]*)?$" { return ScoopRemotePackages $matches['package'] } # Handles cache (rm/show) cache names "^cache (rm|show)\s+(?:.+\s+)?(?<cache>[\w][\-\.\w]*)?$" { return ScoopLocalCaches $matches['cache'] } # Handles bucket rm bucket names "^bucket rm\s+(?:.+\s+)?(?<bucket>[\w][\-\.\w]*)?$" { return ScoopLocalBuckets $matches['bucket'] } # Handles bucket add bucket names "^bucket add\s+(?:.+\s+)?(?<bucket>[\w][\-\.\w]*)?$" { return ScoopRemoteBuckets $matches['bucket'] } # Handles alias rm alias names "^alias rm\s+(?:.+\s+)?(?<alias>[\w][\-\.\w]*)?$" { return ScoopAlias $matches['alias'] } # Handles Scoop help <cmd> "^help (?<cmd>\S*)$" { return ScoopExpandCmd $matches['cmd'] $false } # Handles Scoop <cmd> <subcmd> "^(?<cmd>$($ScoopSubcommands.Keys -join '|'))\s+(?<op>\S*)$" { return ScoopExpandCmdParams $ScoopSubcommands $matches['cmd'] $matches['op'] } # Handles Scoop config <param> <value> "^config (?<param>[\w][\-\.\w]*)\s+(?<value>\w*)$" { return ScoopExpandConfigParamValues $matches['param'] $matches['value'] } # Handles Scoop <cmd> "^(?<cmd>\S*)$" { return ScoopExpandCmd $matches['cmd'] $true } # Handles Scoop <cmd> --<param> "^(?<cmd>$ScoopCommandsWithLongParams).* --(?<param>\S*)$" { return ScoopExpandLongParams $matches['cmd'] $matches['param'] } # Handles Scoop <cmd> -<shortparam> "^(?<cmd>$ScoopCommandsWithShortParams).* -(?<shortparam>\S*)$" { return ScoopExpandShortParams $matches['cmd'] $matches['shortparam'] } } } function script:Get-AliasPattern($exe) { $aliases = @($exe, "$exe\.ps1", "$exe\.cmd") + @(Get-Alias | Where-Object { $_.Definition -eq $exe } | Select-Object -Exp Name) "($($aliases -join '|'))" } $scriptBlock = { param($wordToComplete, $commandAst, $cursorPosition) $rest = $commandAst.CommandElements[1..$commandAst.CommandElements.Count] -join ' ' # The commandAst won't consider an empty word. # e.g `scoop install ` would be considered as `scoop install` # This behavior causes problem with the origianl function above. # So if wordToComplete is empty string, we append a space char at the end. if ($wordToComplete -eq "") { $rest += " " } ScoopTabExpansion $rest } Register-ArgumentCompleter -CommandName scoop -Native -ScriptBlock $scriptBlock |