Skip to content

Commit 3a7fc09

Browse files
authored
Add bash and zsh completion helper (#1006)
1 parent 37800f3 commit 3a7fc09

File tree

10 files changed

+905
-5
lines changed

10 files changed

+905
-5
lines changed

aliBuild

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ from alibuild_helpers.deps import doDeps
1717
from alibuild_helpers.log import info, debug, logger, error
1818
from alibuild_helpers.utilities import detectArch
1919
from alibuild_helpers.build import doBuild
20+
from alibuild_helpers.completion import doCompletion
2021

2122

2223
def doMain(args, parser):
@@ -101,6 +102,9 @@ if __name__ == "__main__":
101102
arch = detectArch()
102103
print(arch if arch else "<unknown>")
103104
exit(0)
105+
elif args.action == "completion":
106+
doCompletion(args)
107+
exit(0)
104108

105109
if not decideAnalytics(exists(expanduser("~/.config/alibuild/disable-analytics")),
106110
exists(expanduser("~/.config/alibuild/analytics-uuid")),

alibuild_helpers/args.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,10 @@ def doParseArgs():
5757
description="Initialise development packages.")
5858
version_parser = subparsers.add_parser("version", help="display %(prog)s version",
5959
description="Display %(prog)s and architecture.")
60+
completion_parser = subparsers.add_parser("completion", help="output shell completion code",
61+
description="Output shell completion code for bash or zsh.")
62+
completion_parser.add_argument("shell", choices=["bash", "zsh"],
63+
help="Shell type to generate completions for.")
6064

6165
# Options for the analytics command
6266
analytics_parser.add_argument("state", choices=["on", "off"], help="Whether to report analytics or not")
@@ -359,7 +363,7 @@ def doParseArgs():
359363
def optionOrder(x):
360364
if x in ["--debug", "-d", "-n", "--dry-run"]:
361365
return 0
362-
if x in ["build", "init", "clean", "analytics", "doctor", "deps"]:
366+
if x in ["build", "init", "clean", "analytics", "doctor", "deps", "completion"]:
363367
return 1
364368
return 2
365369
rest.sort(key=optionOrder)
@@ -400,8 +404,8 @@ def matchValidArch(architecture):
400404

401405
def finaliseArgs(args, parser):
402406

403-
# Nothing to finalise for version or analytics
404-
if args.action in ["version", "analytics", "architecture"]:
407+
# Nothing to finalise for version, analytics, or completion
408+
if args.action in ["version", "analytics", "architecture", "completion"]:
405409
return args
406410

407411
# --architecture can be specified in both clean and build.

alibuild_helpers/completion.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
"""Output shell completion scripts for aliBuild."""
2+
3+
import sys
4+
from os.path import dirname, realpath, join
5+
6+
7+
def doCompletion(args):
8+
"""Print the completion script for the requested shell to stdout."""
9+
script = join(dirname(realpath(__file__)), "completions", args.shell + ".sh")
10+
with open(script) as f:
11+
print(f.read())

alibuild_helpers/completions/__init__.py

Whitespace-only changes.
Lines changed: 227 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,227 @@
1+
# Bash completion for alibuild commands:
2+
# aliBuild, alienv
3+
#
4+
# Installation:
5+
# eval "$(aliBuild completion bash)"
6+
7+
# ---------------------------------------------------------------------------
8+
# Helper: complete package names from the config directory (alidist/*.sh)
9+
# ---------------------------------------------------------------------------
10+
_alibuild_packages() {
11+
local config_dir="${ALIBUILD_CONFIG_DIR:-alidist}"
12+
if [[ -d "$config_dir" ]]; then
13+
COMPREPLY+=( $(awk '
14+
FILENAME ~ /\/defaults-/ { nextfile }
15+
/^package:/ { sub(/^package: */, ""); print; nextfile }
16+
' "$config_dir"/"${cur,,}"*.sh 2>/dev/null) )
17+
fi
18+
}
19+
20+
# ---------------------------------------------------------------------------
21+
# Helper: complete defaults names from the config directory
22+
# ---------------------------------------------------------------------------
23+
_alibuild_defaults() {
24+
local config_dir="${ALIBUILD_CONFIG_DIR:-alidist}"
25+
if [[ -d "$config_dir" ]]; then
26+
local -a defaults
27+
defaults=( "$config_dir"/defaults-*.sh )
28+
defaults=( "${defaults[@]##*/}" )
29+
defaults=( "${defaults[@]%.sh}" )
30+
defaults=( "${defaults[@]#defaults-}" )
31+
COMPREPLY+=( $(compgen -W "${defaults[*]}" -- "$cur") )
32+
fi
33+
}
34+
35+
# ---------------------------------------------------------------------------
36+
# aliBuild / pb completion
37+
# ---------------------------------------------------------------------------
38+
_aliBuild_complete() {
39+
local cur prev words cword
40+
_init_completion || return
41+
42+
# Track the config dir if -c/--config-dir was given
43+
local i
44+
for (( i=1; i < cword; i++ )); do
45+
case "${words[i]}" in
46+
-c|--config-dir|--config)
47+
ALIBUILD_CONFIG_DIR="${words[i+1]}"
48+
;;
49+
esac
50+
done
51+
52+
# Find the subcommand
53+
local subcmd=""
54+
for (( i=1; i < cword; i++ )); do
55+
case "${words[i]}" in
56+
build|clean|deps|doctor|init|analytics|architecture|version|completion)
57+
subcmd="${words[i]}"
58+
break
59+
;;
60+
esac
61+
done
62+
63+
# Complete global options or subcommand name
64+
if [[ -z "$subcmd" ]]; then
65+
COMPREPLY=( $(compgen -W "
66+
-d --debug -n --dry-run
67+
build clean deps doctor init analytics architecture version completion
68+
" -- "$cur") )
69+
return
70+
fi
71+
72+
# Complete subcommand-specific options
73+
case "$subcmd" in
74+
build)
75+
case "$prev" in
76+
-a|--architecture|-z|--devel-prefix|-e|-j|--jobs|--plugin|--docker-image|--docker-extra-args|-v|--remote-store|--write-store)
77+
return ;;
78+
--defaults)
79+
_alibuild_defaults; return ;;
80+
--no-local|--disable|--force-rebuild)
81+
_alibuild_packages; return ;;
82+
--annotate)
83+
return ;;
84+
-C|--chdir|-w|--work-dir|-c|--config-dir|--reference-sources)
85+
_filedir -d; return ;;
86+
esac
87+
if [[ "$cur" == -* ]]; then
88+
COMPREPLY=( $(compgen -W "
89+
-a --architecture --defaults --force-unknown-architecture
90+
-z --devel-prefix -e -j --jobs -u --fetch-repos
91+
--no-local --force-tracked --plugin --disable --force-rebuild
92+
--annotate --only-deps
93+
--docker --docker-image --docker-extra-args -v
94+
--no-remote-store --remote-store --write-store --insecure
95+
-C --chdir -w --work-dir -c --config-dir --reference-sources
96+
--aggressive-cleanup --no-auto-cleanup
97+
--always-prefer-system --no-system
98+
" -- "$cur") )
99+
else
100+
_alibuild_packages
101+
fi
102+
;;
103+
clean)
104+
case "$prev" in
105+
-a|--architecture) return ;;
106+
-C|--chdir|-w|--work-dir) _filedir -d; return ;;
107+
esac
108+
COMPREPLY=( $(compgen -W "
109+
-a --architecture --aggressive-cleanup -C --chdir -w --work-dir
110+
" -- "$cur") )
111+
;;
112+
deps)
113+
case "$prev" in
114+
-a|--architecture|-e|--docker-image|--docker-extra-args)
115+
return ;;
116+
--defaults)
117+
_alibuild_defaults; return ;;
118+
--disable)
119+
_alibuild_packages; return ;;
120+
--outdot|--outgraph)
121+
_filedir; return ;;
122+
-c|--config-dir)
123+
_filedir -d; return ;;
124+
esac
125+
if [[ "$cur" == -* ]]; then
126+
COMPREPLY=( $(compgen -W "
127+
-a --architecture --defaults --disable -e
128+
--neat --outdot --outgraph
129+
--docker --docker-image --docker-extra-args
130+
-c --config-dir
131+
--always-prefer-system --no-system
132+
" -- "$cur") )
133+
else
134+
_alibuild_packages
135+
fi
136+
;;
137+
doctor)
138+
case "$prev" in
139+
-a|--architecture|-e|--docker-image|--docker-extra-args|--remote-store|--write-store)
140+
return ;;
141+
--defaults)
142+
_alibuild_defaults; return ;;
143+
--disable)
144+
_alibuild_packages; return ;;
145+
-C|--chdir|-w|--work-dir|-c|--config)
146+
_filedir -d; return ;;
147+
esac
148+
if [[ "$cur" == -* ]]; then
149+
COMPREPLY=( $(compgen -W "
150+
-a --architecture --defaults --disable -e
151+
--docker --docker-image --docker-extra-args
152+
--no-remote-store --remote-store --write-store --insecure
153+
-C --chdir -w --work-dir -c --config
154+
--always-prefer-system --no-system
155+
" -- "$cur") )
156+
else
157+
_alibuild_packages
158+
fi
159+
;;
160+
init)
161+
case "$prev" in
162+
-a|--architecture|--dist|-z|--devel-prefix)
163+
return ;;
164+
--defaults)
165+
_alibuild_defaults; return ;;
166+
-C|--chdir|-w|--work-dir|-c|--config-dir|--reference-sources)
167+
_filedir -d; return ;;
168+
esac
169+
if [[ "$cur" == -* ]]; then
170+
COMPREPLY=( $(compgen -W "
171+
-a --architecture --defaults -z --devel-prefix --dist
172+
-C --chdir -w --work-dir -c --config-dir --reference-sources
173+
" -- "$cur") )
174+
else
175+
_alibuild_packages
176+
fi
177+
;;
178+
analytics)
179+
COMPREPLY=( $(compgen -W "on off" -- "$cur") )
180+
;;
181+
architecture)
182+
;;
183+
version)
184+
COMPREPLY=( $(compgen -W "-a --architecture" -- "$cur") )
185+
;;
186+
completion)
187+
COMPREPLY=( $(compgen -W "bash zsh" -- "$cur") )
188+
;;
189+
esac
190+
}
191+
192+
# ---------------------------------------------------------------------------
193+
# alienv completion
194+
# ---------------------------------------------------------------------------
195+
_alienv_complete() {
196+
local cur prev words cword
197+
_init_completion || return
198+
199+
# Find the subcommand
200+
local subcmd=""
201+
local i
202+
for (( i=1; i < cword; i++ )); do
203+
case "${words[i]}" in
204+
enter|setenv|printenv|load|unload|q|query|list|avail|modulecmd|shell-helper|help)
205+
subcmd="${words[i]}"
206+
break
207+
;;
208+
esac
209+
done
210+
211+
if [[ -z "$subcmd" ]]; then
212+
case "$prev" in
213+
-a|--architecture) return ;;
214+
-w|--work-dir) _filedir -d; return ;;
215+
esac
216+
COMPREPLY=( $(compgen -W "
217+
-a --architecture -w --work-dir --no-refresh -q --shellrc --dev
218+
enter setenv printenv load unload q query list avail modulecmd shell-helper help
219+
" -- "$cur") )
220+
fi
221+
}
222+
223+
# ---------------------------------------------------------------------------
224+
# Register completions
225+
# ---------------------------------------------------------------------------
226+
complete -F _aliBuild_complete aliBuild
227+
complete -F _alienv_complete alienv

0 commit comments

Comments
 (0)