diff options
Diffstat (limited to 'packages/meshbay-cli/src/meshbay_cli/commands/completion.py')
| -rw-r--r-- | packages/meshbay-cli/src/meshbay_cli/commands/completion.py | 96 |
1 files changed, 96 insertions, 0 deletions
diff --git a/packages/meshbay-cli/src/meshbay_cli/commands/completion.py b/packages/meshbay-cli/src/meshbay_cli/commands/completion.py new file mode 100644 index 0000000..831c012 --- /dev/null +++ b/packages/meshbay-cli/src/meshbay_cli/commands/completion.py @@ -0,0 +1,96 @@ +""" +`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 + } + } + $found = @(& meshbay-cli __complete powershell $index @words 2>$null) + $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 |