[sheepdog] [PATCH] script: auto-generate bash_completion_dog
MORITA Kazutaka
morita.kazutaka at gmail.com
Thu Aug 15 13:58:49 CEST 2013
From: MORITA Kazutaka <morita.kazutaka at lab.ntt.co.jp>
The current bash_completion_dog is too out-of-date. Rather than
updating the file, this patch adds a perl script to auto-generate the
file from dog help information like man/collie.8.
Signed-off-by: MORITA Kazutaka <morita.kazutaka at lab.ntt.co.jp>
---
script/Makefile.am | 19 ++-
script/bash_completion_dog | 303 -----------------------------------------
script/gen_bash_completion.pl | 199 +++++++++++++++++++++++++++
3 files changed, 214 insertions(+), 307 deletions(-)
delete mode 100644 script/bash_completion_dog
create mode 100755 script/gen_bash_completion.pl
diff --git a/script/Makefile.am b/script/Makefile.am
index 8fccd53..0ff5e62 100644
--- a/script/Makefile.am
+++ b/script/Makefile.am
@@ -2,10 +2,18 @@ MAINTAINERCLEANFILES = Makefile.in
EXTRA_DIST = generic.in
-noinst_HEADERS = bash_completion_dog checkarch.sh vditest gen_man.pl
+noinst_HEADERS = bash_completion_dog checkarch.sh vditest gen_man.pl \
+ gen_bash_completion.pl
target_INIT = generic
+target_BASH_COMPLETION = bash_completion_dog
+
+bash_completion_dog: $(top_srcdir)/dog/dog gen_bash_completion.pl Makefile
+ rm -f $@-t $@
+ $(top_srcdir)/script/gen_bash_completion.pl $(top_builddir)/dog/dog > $@-t
+ mv $@-t $@
+
%: %.in Makefile
rm -f $@-t $@
sed \
@@ -17,15 +25,18 @@ target_INIT = generic
chmod 0755 $@-t
mv $@-t $@
-all-local: $(target_INIT)
+all-local: $(target_INIT) $(target_BASH_COMPLETION)
clean-local:
rm -rf $(target_INIT)
+ rm -rf $(target_BASH_COMPLETION)
install-exec-local:
$(INSTALL) -d $(DESTDIR)/$(INITDDIR)
$(INSTALL) -m 755 generic $(DESTDIR)/$(INITDDIR)/sheepdog
+ $(INSTALL) -d $(DESTDIR)/$(sysconfdir)/bash_completion.d
+ $(INSTALL) bash_completion_dog $(DESTDIR)/$(sysconfdir)/bash_completion.d/dog
uninstall-local:
- cd $(DESTDIR)/$(INITDDIR) && \
- rm -f sheepdog
+ cd $(DESTDIR)/$(INITDDIR) && rm -f sheepdog
+ cd $(DESTDIR)/$(sysconfdir)/bash_completion.d && rm -f dog
diff --git a/script/bash_completion_dog b/script/bash_completion_dog
deleted file mode 100644
index 89c9544..0000000
--- a/script/bash_completion_dog
+++ /dev/null
@@ -1,303 +0,0 @@
-#!bash
-
-_dog_cluster_format()
-{
- local cur
- cur="${COMP_WORDS[COMP_CWORD]}"
-
- case "$cur" in
- -*)
- COMPREPLY=(${COMPREPLY[@]} \
- $( compgen \
- -W "-c --copies" \
- -- ${cur} ))
- ;;
- esac
-}
-
-_dog_cluster_recover()
-{
- local cur
- cur="${COMP_WORDS[COMP_CWORD]}"
-
- case "$cur" in
- -*)
- COMPREPLY=(${COMPREPLY[@]} \
- $( compgen \
- -W "-f --force" \
- -- ${cur} ))
- ;;
- esac
-}
-
-_dog_vdi_create()
-{
- local cur
- cur="${COMP_WORDS[COMP_CWORD]}"
-
- case "$cur" in
- -*)
- COMPREPLY=(${COMPREPLY[@]} \
- $( compgen \
- -W "-P --prealloc" \
- -- ${cur} ))
- ;;
- esac
-}
-
-_dog_vdi_snapshot()
-{
- local cur
- cur="${COMP_WORDS[COMP_CWORD]}"
-
- case "$cur" in
- -*)
- COMPREPLY=(${COMPREPLY[@]} \
- $( compgen \
- -W "-s --snapshot" \
- -- ${cur} ))
- ;;
- esac
-}
-
-_dog_vdi_clone()
-{
- local cur
- cur="${COMP_WORDS[COMP_CWORD]}"
-
- case "$cur" in
- -*)
- COMPREPLY=(${COMPREPLY[@]} \
- $( compgen \
- -W "-P --prealloc -s --snapshot" \
- -- ${cur} ))
- ;;
- esac
-}
-
-_dog_vdi_read()
-{
- local cur
- cur="${COMP_WORDS[COMP_CWORD]}"
-
- case "$cur" in
- -*)
- COMPREPLY=(${COMPREPLY[@]} \
- $( compgen \
- -W "-s --snapshot" \
- -- ${cur} ))
- ;;
- esac
-}
-
-_dog_vdi_delete()
-{
- local cur dog vdilist
- cur="${COMP_WORDS[COMP_CWORD]}"
- dog="${COMP_WORDS[0]}"
- vdilist="$(${dog} vdi list | tail -n+3 | grep '^ ' | awk '{print $1}')"
-
- case "$cur" in
- -*)
- COMPREPLY=(${COMPREPLY[@]} \
- $( compgen \
- -W "-s --snapshot" \
- -- ${cur} ))
- ;;
- *)
- COMPREPLY=($( compgen -W "${vdilist}" -- ${cur} ))
- ;;
- esac
-}
-
-_dog_vdi_object()
-{
- local cur dog vdilist
- cur="${COMP_WORDS[COMP_CWORD]}"
- dog="${COMP_WORDS[0]}"
- vdilist="$(${dog} vdi list | tail -n+3 | grep '^ ' | awk '{print $1}')"
-
- case "$cur" in
- -*)
- COMPREPLY=(${COMPREPLY[@]} \
- $( compgen \
- -W "-i --index -s --snapshot" \
- -- ${cur} ))
- ;;
- *)
- COMPREPLY=($( compgen -W "${vdilist}" -- ${cur} ))
- ;;
- esac
-}
-
-_dog_vdi_setattr()
-{
- local cur
- cur="${COMP_WORDS[COMP_CWORD]}"
-
- case "$cur" in
- -*)
- COMPREPLY=(${COMPREPLY[@]} \
- $( compgen \
- -W "-d --delete -x --exclusive" \
- -- ${cur} ))
- ;;
- esac
-}
-
-_dog_cluster()
-{
- local opts
- opts="info format shutdown recover snapshot"
-
- case "$1" in
- info)
- ;;
- format)
- _dog_cluster_format
- ;;
- shutdown)
- ;;
- recover)
- _dog_cluster_recover
- ;;
- snapshot)
- ;;
- "")
- COMPREPLY=($( compgen \
- -W "${opts}" \
- -- "${COMP_WORDS[COMP_CWORD]}" ))
- ;;
- *)
- COMPREPLY=()
- ;;
- esac
-}
-
-_dog_node()
-{
- local opts
- opts="info list recovery kill cache"
-
- case "$1" in
- info)
- ;;
- list)
- ;;
- recovery)
- ;;
- kill)
- ;;
- cache)
- ;;
- "")
- COMPREPLY=($( compgen \
- -W "${opts}" \
- -- "${COMP_WORDS[COMP_CWORD]}" ))
- ;;
- *)
- COMPREPLY=()
- ;;
- esac
-}
-
-_dog_vdi()
-{
- local opts
- opts="create snapshot clone resize read write \
-list tree graph delete object setattr getattr track check \
-rollback flush backup restore"
-
- case "$1" in
- create)
- _dog_vdi_create
- ;;
- snapshot)
- _dog_vdi_snapshot
- ;;
- clone)
- _dog_vdi_clone
- ;;
- resize)
- ;;
- read)
- _dog_vdi_read
- ;;
- write)
- ;;
- list)
- ;;
- tree)
- ;;
- graph)
- ;;
- delete)
- _dog_vdi_delete
- ;;
- object)
- _dog_vdi_object
- ;;
- setattr)
- _dog_vdi_setattr
- ;;
- getattr)
- ;;
- track)
- ;;
- check)
- ;;
- rollback)
- ;;
- flush)
- ;;
- backup)
- ;;
- restore)
- ;;
- "")
- COMPREPLY=($( compgen \
- -W "${opts}" \
- -- "${COMP_WORDS[COMP_CWORD]}" ))
- ;;
- *)
- COMPREPLY=()
- ;;
- esac
-}
-
-_dog()
-{
- local opts cur cmd subcmd i
- opts="cluster node vdi"
- cur="${COMP_WORDS[COMP_CWORD]}"
-
- if [ $COMP_CWORD -gt 1 ]; then
- cmd=${COMP_WORDS[1]}
- fi
-
- if [ $COMP_CWORD -gt 2 ]; then
- subcmd=${COMP_WORDS[2]}
- fi
-
- COMPREPLY=($( compgen -W "-a --address -p --port -h --help" -- ${cur} ))
-
- case "${cmd}" in
- cluster)
- _dog_cluster ${subcmd}
- ;;
- node)
- _dog_node ${subcmd}
- ;;
- vdi)
- _dog_vdi ${subcmd}
- ;;
- "")
- COMPREPLY=($( compgen -W "${opts}" -- ${cur} ))
- ;;
- *)
- COMPREPLY=()
- ;;
- esac
-}
-
-complete -F _dog dog
diff --git a/script/gen_bash_completion.pl b/script/gen_bash_completion.pl
new file mode 100755
index 0000000..070130c
--- /dev/null
+++ b/script/gen_bash_completion.pl
@@ -0,0 +1,199 @@
+#!/usr/bin/perl
+#
+# Genrate bash_completion_dog
+#
+
+use strict;
+
+my ($program) = @ARGV;
+
+print "#!bash\n";
+print "\n";
+
+open IN, "$program -h |" or die "cannot find $program\n";
+my @help = <IN>;
+close IN;
+
+# Hash of sub command arrays.
+# E.g. $subcmds{'node'} = [kill, list, info, recovery, md]
+my %subcmds;
+
+# Hash of sub sub command arrays.
+# E.g. $subsubcmds{'trace graph'} = [cat, stat]
+my %subsubcmds;
+
+# Hash of option arrays.
+# E.g. $opts{'node list'} = [-a, --address, -p, --port, -r, --raw, -h, --help]
+my %opts;
+
+foreach (@help) {
+ if (/^ (\S+) (\S+)/) {
+ my ($cmd, $subcmd) = ($1, $2);
+
+ $subcmds{$cmd} = [] if (!defined($subcmds{$cmd}));
+
+ push $subcmds{$cmd}, $subcmd;
+ $opts{"$cmd $subcmd"} = [];
+ $subsubcmds{"$cmd $subcmd"} = [];
+
+ # run sub command to get more detailed usage
+ open IN, "$program $cmd $subcmd -h |";
+ while (<IN>) {
+ if (/^ (-.), (--\S+)/) {
+ # get options
+ push $opts{"$cmd $subcmd"}, $1;
+ push $opts{"$cmd $subcmd"}, $2;
+ } elsif (/^ ([a-z]+)/) {
+ # get available subcommands
+ push $subsubcmds{"$cmd $subcmd"}, $1;
+ }
+ }
+ close IN;
+ }
+}
+
+foreach my $cmd (keys %subcmds) {
+ my @subcmds = @{$subcmds{$cmd}};
+
+ print command($cmd, @subcmds);
+
+ foreach my $subcmd (@subcmds) {
+ print subcommand($cmd, $subcmd);
+ }
+}
+
+print <<__EOB__;
+_dog()
+{
+ local opts cur cmd subcmd
+ opts="@{[keys %subcmds]}"
+ cur="\${COMP_WORDS[COMP_CWORD]}"
+
+ if [ \$COMP_CWORD -gt 1 ]; then
+ cmd=\${COMP_WORDS[1]}
+ fi
+
+ if [ \$COMP_CWORD -gt 2 ]; then
+ subcmd=\${COMP_WORDS[2]}
+ fi
+
+ case "\${cmd}" in
+__EOB__
+
+ foreach my $cmd (keys %subcmds) {
+ print <<__EOB__;
+ $cmd)
+ _dog_$cmd \${subcmd}
+ ;;
+__EOB__
+ }
+
+print <<__EOB__;
+ "")
+ COMPREPLY=(\$( compgen -W "\${opts}" -- \${cur} ))
+ ;;
+ *)
+ COMPREPLY=()
+ ;;
+ esac
+}
+
+complete -F _dog dog
+__EOB__
+
+exit 0;
+
+# get a completion function for dog command (e.g. _dog_vdi())
+sub command {
+ my ($cmd, @subcmds) = @_;
+ my $output;
+
+ $output = <<__EOB__;
+ _dog_${cmd}()
+ {
+ local opts
+ opts="@subcmds"
+
+ case "\$1" in
+__EOB__
+
+ foreach my $subcmd (@subcmds) {
+ $output .= <<__EOB__;
+ $subcmd)
+ _dog_${cmd}_${subcmd}
+ ;;
+__EOB__
+ }
+
+ $output .= <<__EOB__;
+ "")
+ COMPREPLY=(\$( compgen \\
+ -W "\${opts}" \\
+ -- "\${COMP_WORDS[COMP_CWORD]}" ))
+ ;;
+ *)
+ COMPREPLY=()
+ ;;
+ esac
+ }
+
+__EOB__
+
+ $output =~ s/\t/ /g;
+ $output =~ s/^ //gm;
+
+ return $output;
+}
+
+# get a completion function for dog subcommands (e.g. _dog_vdi_create())
+sub subcommand {
+ my ($cmd, $subcmd) = @_;
+ my $output;
+ my @opts = @{$opts{"$cmd $subcmd"}};
+ my @subsubcmds = @{$subsubcmds{"$cmd $subcmd"}};
+
+ $output = <<__EOB__;
+ _dog_${cmd}_${subcmd}()
+ {
+ local cur
+ cur="\${COMP_WORDS[COMP_CWORD]}"
+
+ case "\$cur" in
+ -*)
+ COMPREPLY=(\${COMPREPLY[@]} \\
+ \$( compgen \\
+ -W "@opts" \\
+__EOB__
+
+ $output .= <<__EOB__;
+ -- \${cur} ))
+ ;;
+__EOB__
+
+ if ($cmd eq 'vdi' && $subcmd ne 'create') {
+ $output .= <<__EOB__;
+ *)
+ local dog="\${COMP_WORDS[0]}"
+ local vdilist="\$(\${dog} vdi list -r 2>/dev/null | awk '{print \$2}')"
+ COMPREPLY=(\$( compgen -W "@subsubcmds \${vdilist}" -- \${cur} ))
+ ;;
+__EOB__
+ } else {
+ $output .= <<__EOB__;
+ *)
+ COMPREPLY=(\$( compgen -W "@subsubcmds" -- \${cur} ))
+ ;;
+__EOB__
+ }
+
+ $output .= <<__EOB__;
+ esac
+ }
+
+__EOB__
+
+ $output =~ s/\t/ /g;
+ $output =~ s/^ //gm;
+
+ return $output;
+}
--
1.7.9.5
More information about the sheepdog
mailing list