# @generated by usage-argv for `usage __complete_word__ --shell powershell`
Register-ArgumentCompleter -Native -CommandName 'usage' -ScriptBlock {
param($wordToComplete, $commandAst, $cursorPosition)
$marker = [char]1
# `$cursorPosition` is an offset into the whole input buffer while `Extent.Text` is only this
# command's span, so after a pipeline or a `;` the two do not share an origin. Subtracting the
# extent's start puts them back on the same footing, and cutting here means no offset has to
# travel — see the bash script on why.
$extent = $commandAst.Extent
$offset = $cursorPosition - $extent.StartOffset
if ($offset -lt 0) { $offset = 0 }
if ($offset -gt $extent.Text.Length) { $offset = $extent.Text.Length }
$line = $extent.Text.Substring(0, $offset)
$out = @(& 'usage' __complete_word__ --shell powershell --line $line 2>$null)
$files = $null
$extensions = @()
$results = [System.Collections.Generic.List[System.Management.Automation.CompletionResult]]::new()
foreach ($entry in $out) {
if ([string]::IsNullOrEmpty($entry)) { continue }
if ($entry -eq ($marker + 'files')) { $files = 'any'; continue }
if ($entry -eq ($marker + 'dirs')) { $files = 'dirs'; continue }
if ($entry -eq ($marker + 'executables')) { $files = 'executables'; continue }
if ($entry -eq ($marker + 'commands')) { $files = 'commands'; continue }
if ($entry.StartsWith($marker + "extensions`t")) {
$files = 'extensions'
$extensions = @($entry -split "`t" | Select-Object -Skip 1 | ForEach-Object { $_.TrimStart('.') })
continue
}
$parts = $entry -split "`t", 4
$value = $parts[0]
$description = if ($parts.Count -gt 1 -and $parts[1]) { $parts[1] } else { $value }
$display = if ($parts.Count -gt 2 -and $parts[2]) { $parts[2] } else { $value }
$kind = if ($parts.Count -gt 3) {
switch ($parts[3]) {
'command' { 'Command' }
'flag' { 'ParameterName' }
'file' { 'ProviderItem' }
'directory' { 'ProviderContainer' }
default { 'ParameterValue' }
}
} else { 'ParameterValue' }
$results.Add(
[System.Management.Automation.CompletionResult]::new(
$value, $display, $kind, $description
)
)
}
if ($files -eq 'commands') {
foreach ($command in Get-Command -Name ($wordToComplete + '*') -CommandType Application, ExternalScript -ErrorAction SilentlyContinue) {
$results.Add(
[System.Management.Automation.CompletionResult]::new(
$command.Name, $command.Name, 'Command', $command.Source
)
)
}
} elseif ($files) {
# PowerShell's own, so that `~`, drive-relative paths and provider paths behave as they
# do everywhere else in the shell.
foreach ($path in [System.Management.Automation.CompletionCompleters]::CompleteFilename($wordToComplete)) {
# Trust PowerShell's result type for directories because CompletionText may already
# carry quoting. Executable leaves are checked as commands after stripping only the
# outer quote characters PowerShell added.
if ($files -eq 'dirs' -and $path.ResultType -ne 'ProviderContainer') {
continue
}
if ($files -eq 'executables' -and $path.ResultType -ne 'ProviderContainer') {
$candidatePath = $path.CompletionText.Trim([char[]]@([char]39, [char]34))
if (-not (Get-Command -Name $candidatePath -CommandType Application, ExternalScript -ErrorAction SilentlyContinue)) {
continue
}
}
if ($files -eq 'extensions' -and $path.ResultType -ne 'ProviderContainer') {
$candidatePath = $path.CompletionText.Trim([char[]]@([char]39, [char]34))
$candidateName = [System.IO.Path]::GetFileName($candidatePath)
$matchesExtension = $false
foreach ($extension in $extensions) {
if ($candidateName.EndsWith('.' + $extension, [System.StringComparison]::OrdinalIgnoreCase)) {
$matchesExtension = $true
break
}
}
if (-not $matchesExtension) {
continue
}
}
$results.Add($path)
}
}
$results
}