1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
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
|