Permalink
Browse files

Add simple bash completion script.

So far this can complete plugin names:

  $ nbdkit <TAB>
  curl       example4   libvirt    perl       ruby       vddk
  example1   file       memory     python     split      xz
  example2   guestfs    nbd        python2    streaming
  example3   gzip       null       python3    tar

Plugin parameters:

  $ nbdkit curl <TAB>
  password=   sslverify=  timeout=    url=        user=

Filter names:

  $ nbdkit --filter=<TAB>
  cache      cow        delay      offset     partition

General options (short or long or both):

  $ nbdkit -<TAB>
  --dump-config       --new-style         --single
  --dump-plugin       --newstyle          --stdin
  -e                  --no-fork           -t
  --exit-with-parent  -o                  --threads
  --export            --old-style         --tls
  --export-name       --oldstyle          --tls-certificates
  --exportname        -p                  --tls-verify-peer
  -f                  -P                  -u
  --filter            --pid-file          -U
  --foreground        --pidfile           --unix
  -g                  --port              --user
  --group             -r                  -v
  --help              --read-only         -V
  -i                  --readonly          --verbose
  --ip-addr           --run               --version
  --ipaddr            -s
  -n                  --selinux-label

And --tls options:

  $ nbdkit --tls=<TAB>
  off      on       require

There is still quite a lot more which it doesn't do, such as
completing filter parameters, and smarter completion for options.
  • Loading branch information...
rwmjones committed Jun 9, 2018
1 parent 07ecff1 commit 772cfefad72f4c2ec5a72bc73f75a2921fe6054b
Showing with 198 additions and 2 deletions.
  1. +1 −0 Makefile.am
  2. +4 −0 README
  3. +0 −2 TODO
  4. +40 −0 bash/Makefile.am
  5. +8 −0 bash/README
  6. +113 −0 bash/nbdkit
  7. +15 −0 configure.ac
  8. +17 −0 src/main.c
@@ -44,6 +44,7 @@ EXTRA_DIST = \
noinst_SCRIPTS = nbdkit
SUBDIRS = \
bash \
docs \
include \
src
4 README
@@ -91,6 +91,10 @@ For the OCaml plugin:
- OCaml >= 4.02.2 which has support for shared libraries, see:
http://caml.inria.fr/mantis/view.php?id=6693
For bash tab completion:
- bash-completion >= 1.99
To run the test suite:
- bash
2 TODO
@@ -10,8 +10,6 @@ General ideas for improvements
* Performance - measure and improve it.
* Bash tab completion.
* Exit on last connection (the default behaviour of qemu-nbd unless
you use -t).
@@ -0,0 +1,40 @@
# nbdkit
# Copyright (C) 2018 Red Hat Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# * Neither the name of Red Hat nor the names of its contributors may be
# used to endorse or promote products derived from this software without
# specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
EXTRA_DIST = README
if HAVE_BASH_COMPLETION
bashcompdir = @bashcompdir@
dist_bashcomp_DATA = nbdkit
endif
@@ -0,0 +1,8 @@
This directory contains the scripts for tab-completing commands in
bash. Note these new-style demand-loaded scripts require
bash-completion >= 1.99.
Tip: To test the bash completions without having to install them,
simply start a new shell and do:
source ./bash/nbdkit; PATH=$PWD:$PATH
@@ -0,0 +1,113 @@
# nbdkit bash completion script -*- shell-script -*-
# Copyright (C) 2010-2018 Red Hat Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# * Neither the name of Red Hat nor the names of its contributors may be
# used to endorse or promote products derived from this software without
# specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
_nbdkit_list_plugins ()
{
local plugindir
plugindir="$(
nbdkit --dump-config | grep ^plugindir= | sed 's/^plugindir=//'
)"
ls -1 "$plugindir" | sed 's/^nbdkit-//' | sed 's/-plugin.*//'
}
_nbdkit_list_filters ()
{
local filterdir
filterdir="$(
nbdkit --dump-config | grep ^filterdir= | sed 's/^filterdir=//'
)"
ls -1 "$filterdir" | sed 's/^nbdkit-//' | sed 's/-filter.*//'
}
# This handler function is called when the user presses tab.
_nbdkit ()
{
local cur prev words cword split
local shortopts longopts plugin plugins filters args i
_init_completion -s || return
# Did we get the plugin name yet?
# This is only a heuristic because it can be confused by
# long opt parameters with an arguments. XXX
plugin=
for (( i=1; i < ${#words[@]}; ++i)) ; do
if [[ "${words[i]}" =~ ^[a-zA-Z0-9]+$ ]]; then
plugin="${words[i]}"
break
fi
done
# Previous item on the current line is a completable flag or plugin name?
case "$prev" in
--filter)
filters="$(_nbdkit_list_filters)"
COMPREPLY=( $(compgen -W "$filters" "$cur") )
return ;;
--tls)
COMPREPLY=( $(compgen -W "off on require" "$cur") )
return ;;
# Could complete -u and -g options too. XXX
esac
# Current item is an option we can expand?
case "$cur" in
--*)
longopts="$(nbdkit --long-options)"
COMPREPLY=( $(compgen -W "$longopts" -- "$cur") )
return ;;
-*)
shortopts="$(nbdkit --short-options)"
longopts="$(nbdkit --long-options)"
COMPREPLY=( $(compgen -W "$shortopts $longopts" -- "$cur") )
return ;;
*)
if [ "$plugin" = "" ]; then
# Complete plugin name.
plugins="$(_nbdkit_list_plugins)"
COMPREPLY=( $(compgen -W "$plugins" "$cur") )
return
else
# Complete plugin args.
args="$(
nbdkit $plugin --help 2>/dev/null |
grep -E '^[a-z0-9]+=' | sed 's/=.*/=/'
)"
COMPREPLY=( $(compgen -W "$args" "$cur") )
return
fi
;;
esac
}
# Install the handler function.
complete -o default -F _nbdkit nbdkit
@@ -164,6 +164,20 @@ AS_IF([test "$GNUTLS_LIBS" != ""],[
dnl Check for valgrind.
AC_CHECK_PROG([VALGRIND],[valgrind],[valgrind],[no])
dnl Bash completion.
PKG_CHECK_MODULES([BASH_COMPLETION], [bash-completion >= 2.0], [
bash_completion=yes
AC_MSG_CHECKING([for bash-completions directory])
PKG_CHECK_VAR(bashcompdir, [bash-completion], [completionsdir], ,
bashcompdir="${sysconfdir}/bash_completion.d")
AC_MSG_RESULT([$bashcompdir])
AC_SUBST([bashcompdir])
],[
bash_completion=no
AC_MSG_WARN([bash-completion not installed])
])
AM_CONDITIONAL([HAVE_BASH_COMPLETION],[test "x$bash_completion" = "xyes"])
dnl Check for Perl POD.
AC_CHECK_PROG([POD2MAN], [pod2man], [pod2man], [no])
AS_IF([test "x$POD2MAN" != "xno"],[
@@ -526,6 +540,7 @@ AC_CONFIG_HEADERS([config.h])
AC_CONFIG_FILES([nbdkit],
[chmod +x,-w nbdkit])
AC_CONFIG_FILES([Makefile
bash/Makefile
docs/Makefile
include/Makefile
plugins/Makefile
@@ -126,6 +126,7 @@ static const struct option long_options[] = {
{ "group", 1, NULL, 'g' },
{ "ip-addr", 1, NULL, 'i' },
{ "ipaddr", 1, NULL, 'i' },
{ "long-options", 0, NULL, 0 },
{ "new-style", 0, NULL, 'n' },
{ "newstyle", 0, NULL, 'n' },
{ "old-style", 0, NULL, 'o' },
@@ -137,6 +138,7 @@ static const struct option long_options[] = {
{ "readonly", 0, NULL, 'r' },
{ "run", 1, NULL, 0 },
{ "selinux-label", 1, NULL, 0 },
{ "short-options", 0, NULL, 0 },
{ "single", 0, NULL, 's' },
{ "stdin", 0, NULL, 's' },
{ "threads", 1, NULL, 't' },
@@ -263,6 +265,14 @@ main (int argc, char *argv[])
t->filename = optarg;
filter_filenames = t;
}
else if (strcmp (long_options[option_index].name, "long-options") == 0) {
for (i = 0; long_options[i].name != NULL; ++i) {
if (strcmp (long_options[i].name, "long-options") != 0 &&
strcmp (long_options[i].name, "short-options") != 0)
printf ("--%s\n", long_options[i].name);
}
exit (EXIT_SUCCESS);
}
else if (strcmp (long_options[option_index].name, "run") == 0) {
if (socket_activation) {
fprintf (stderr, "%s: cannot use socket activation with --run flag\n",
@@ -276,6 +286,13 @@ main (int argc, char *argv[])
selinux_label = optarg;
break;
}
else if (strcmp (long_options[option_index].name, "short-options") == 0) {
for (i = 0; short_options[i]; ++i) {
if (short_options[i] != ':')
printf ("-%c\n", short_options[i]);
}
exit (EXIT_SUCCESS);
}
else if (strcmp (long_options[option_index].name, "tls") == 0) {
tls_set_on_cli = 1;
if (strcmp (optarg, "off") == 0 || strcmp (optarg, "0") == 0)

0 comments on commit 772cfef

Please sign in to comment.