""" `completion`: the script that makes Tab complete meshbay-cli in a shell. bash: eval "$(meshbay-cli completion bash)" (in ~/.bashrc) PowerShell: meshbay-cli completion powershell | Out-String | Invoke-Expression (in $PROFILE) The packages install the bash one where bash-completion finds it. Both scripts ask `meshbay-cli __complete` for the candidates (see `complete.py`): actions, verbs, options, and the remote paths of the groups this machine is signed in to. """ from ..errors import USAGE, CliError from ..output import sentence from .context import Context HELP = "print the script that makes Tab complete meshbay-cli in bash or PowerShell" BASH = r'''# meshbay-cli completion for bash: eval "$(meshbay-cli completion bash)" _meshbay_cli() { local cur=${COMP_WORDS[COMP_CWORD]} line files=0 local -a found=() while IFS= read -r line; do if [[ $line == __files__ ]]; then files=1; else found+=("$line"); fi done < <(command meshbay-cli __complete bash "$COMP_CWORD" "${COMP_WORDS[@]}" 2>/dev/null) COMPREPLY=("${found[@]}") if (( files )); then local f while IFS= read -r f; do COMPREPLY+=("$f"); done < <(compgen -f -- "$cur") fi # Quote spaces and the like as for file names; no space after a folder. compopt -o filenames 2>/dev/null local c for c in "${COMPREPLY[@]}"; do if [[ $c == */ ]]; then compopt -o nospace 2>/dev/null; break; fi done } complete -F _meshbay_cli meshbay-cli ''' POWERSHELL = r'''# meshbay-cli completion for PowerShell: # meshbay-cli completion powershell | Out-String | Invoke-Expression Register-ArgumentCompleter -Native -CommandName 'meshbay-cli', 'meshbay-cli.exe' -ScriptBlock { param($wordToComplete, $commandAst, $cursorPosition) $elements = @($commandAst.CommandElements) $words = @($elements | ForEach-Object { $_.Extent.Text }) $index = $words.Count for ($i = 0; $i -lt $elements.Count; $i++) { $e = $elements[$i].Extent if ($cursorPosition -ge $e.StartOffset -and $cursorPosition -le $e.EndOffset) { $index = $i } } # The client writes UTF-8; Windows PowerShell reads a program's output in the # console's code page, which turns an accented name into another name. $encoding = [Console]::OutputEncoding try { [Console]::OutputEncoding = [Text.Encoding]::UTF8 } catch { } try { $found = @(& meshbay-cli __complete powershell $index @words 2>$null) } finally { try { [Console]::OutputEncoding = $encoding } catch { } } $quote = { param($s) if ($s -match '[\s''"`$&|;(){}@,#]') { "'" + ($s -replace "'", "''") + "'" } else { $s } } $item = [System.Management.Automation.CompletionResult] $results = @() foreach ($c in $found) { if ($c -eq '__files__') { $sep = [IO.Path]::DirectorySeparatorChar $typed = $wordToComplete.Trim([char[]]"'`"") $dir = Split-Path -Path $typed -Parent Get-ChildItem -Path "$typed*" -ErrorAction SilentlyContinue | ForEach-Object { $p = if ($dir) { Join-Path $dir $_.Name } else { $_.Name } if ($_.PSIsContainer) { $p += $sep } $results += $item::new((& $quote $p), $p, 'ProviderItem', $p) } continue } $results += $item::new((& $quote $c), $c, 'ParameterValue', $c) } $results } ''' SCRIPTS = {"bash": BASH, "powershell": POWERSHELL} def add_parser(sub, parent) -> None: p = sub.add_parser("completion", parents=[parent], help=HELP, description=sentence(HELP) + '. bash: eval "$(meshbay-cli completion bash)" in ~/.bashrc; ' "PowerShell: meshbay-cli completion powershell | Out-String | " "Invoke-Expression in $PROFILE.") p.add_argument("shell", choices=tuple(SCRIPTS), help="the shell") async def run(ctx: Context) -> int: script = SCRIPTS.get(ctx.args.shell) if script is None: raise CliError(USAGE, "bash or powershell.") print(script, end="") return 0