From ada0e6803b2811edf87d32b7ac6335766785ed3e Mon Sep 17 00:00:00 2001 From: Iustin Pop <iustin@google.com> Date: Tue, 25 Sep 2012 12:30:07 +0200 Subject: [PATCH] Enable bash completion for htools scripts This patch ties together the previous commits, by extending build-bash-completion to call all htools scripts and get their completion information, then use that to build fake cli_options representing them and finally generate the bash completion information. Signed-off-by: Iustin Pop <iustin@google.com> Reviewed-by: Michael Hanselmann <hansmi@google.com> --- Makefile.am | 12 +++++- autotools/build-bash-completion | 74 +++++++++++++++++++++++++++++++++ 2 files changed, 85 insertions(+), 1 deletion(-) diff --git a/Makefile.am b/Makefile.am index 7ae24ef88..b1f3ab8c8 100644 --- a/Makefile.am +++ b/Makefile.am @@ -173,6 +173,14 @@ GENERATED_FILES = \ $(BUILT_PYTHON_SOURCES) \ $(PYTHON_BOOTSTRAP) +HTOOLS_GENERATED_FILES = +if WANT_HTOOLS +HTOOLS_GENERATED_FILES += $(HS_PROGS) +if HS_CONFD +HTOOLS_GENERATED_FILES += htools/hconfd +endif +endif + built_base_sources = \ stamp-directories \ stamp-srclinks @@ -370,6 +378,7 @@ docrst = \ HS_PROGS = htools/htools HS_BIN_ROLES = hbal hscan hspace hinfo hcheck +HS_HTOOLS_PROGS = $(HS_BIN_ROLES) hail HS_ALL_PROGS = $(HS_PROGS) htest/test htest/hpc-htools htools/hconfd HS_PROG_SRCS = $(patsubst %,%.hs,$(HS_ALL_PROGS)) @@ -1055,7 +1064,7 @@ doc/examples/bash_completion-debug: BC_ARGS = doc/examples/bash_completion doc/examples/bash_completion-debug: \ $(BUILD_BASH_COMPLETION) $(RUN_IN_TEMPDIR) \ lib/cli.py $(gnt_scripts) $(client_PYTHON) tools/burnin \ - $(GENERATED_FILES) + $(GENERATED_FILES) $(HTOOLS_GENERATED_FILES) PYTHONPATH=. $(RUN_IN_TEMPDIR) \ $(CURDIR)/$(BUILD_BASH_COMPLETION) $(BC_ARGS) > $@ @@ -1199,6 +1208,7 @@ lib/_autoconf.py: Makefile | stamp-directories echo "LVM_STRIPECOUNT = $(LVM_STRIPECOUNT)"; \ echo "TOOLSDIR = '$(toolsdir)'"; \ echo "GNT_SCRIPTS = [$(foreach i,$(notdir $(gnt_scripts)),'$(i)',)]"; \ + echo "HTOOLS_PROGS = [$(foreach i,$(HS_HTOOLS_PROGS),'$(i)',)]"; \ echo "PKGLIBDIR = '$(pkglibdir)'"; \ echo "DRBD_BARRIERS = '$(DRBD_BARRIERS)'"; \ echo "DRBD_NO_META_FLUSH = $(DRBD_NO_META_FLUSH)"; \ diff --git a/autotools/build-bash-completion b/autotools/build-bash-completion index 8687254e0..c0295cc2e 100755 --- a/autotools/build-bash-completion +++ b/autotools/build-bash-completion @@ -626,6 +626,74 @@ def GetCommands(filename, module): return commands +def HaskellOptToOptParse(opts, kind): + """Converts a Haskell options to Python cli_options. + + @type opts: string + @param opts: comma-separated string with short and long options + @type kind: string + @param kind: type generated by Common.hs/complToText; needs to be + kept in sync + + """ + # pylint: disable=W0142 + # since we pass *opts in a number of places + opts = opts.split(",") + if kind == "none": + return cli.cli_option(*opts, action="store_true") + elif kind in ["file", "string", "host", "dir"]: + return cli.cli_option(*opts, type="string") + elif kind == "numeric": + # FIXME: float values here + return cli.cli_option(*opts, type="string") + elif kind == "onegroup": + return cli.cli_option(*opts, type="string", + completion_suggest=cli.OPT_COMPL_ONE_NODEGROUP) + elif kind == "onenode": + return cli.cli_option(*opts, type="string", + completion_suggest=cli.OPT_COMPL_ONE_NODE) + elif kind == "manyinstances": + # FIXME: no support for many instances + return cli.cli_option(*opts, type="string") + elif kind.startswith("choices "): + choices = kind[len("choices "):].split(",") + return cli.cli_option(*opts, type="choice", choices=choices) + else: + # FIXME: there are many other currently unused completion types, + # should be added on an as-needed basis + raise Exception("Unhnadled option kind '%s'" % kind) + + +def WriteHaskellCompletion(sw, script, htools=True, debug=True): + """Generates completion information for a Haskell program. + + This Converts completion info from a Haskell program into 'fake' + cli_opts and then builds completion for them. + + """ + if htools: + cmd = "./htools/htools" + env = {"HTOOLS": script} + script_name = script + func_name = "htools_%s" % script + else: + # note: this is not yet used (daemons) + cmd = script + env = {} + script_name = script + func_name = script + output = utils.RunCmd([cmd, "--help-completion"], env=env, cwd=".").output + cli_opts = [] + for line in output.splitlines(): + v = line.split(None, 1) + if len(v) != 2: + raise Exception("Invalid help completion output from %s: %s" % + (script, v)) + (opts, kind) = v + cli_opts.append(HaskellOptToOptParse(opts, kind)) + WriteCompletion(sw, script_name, func_name, debug, opts=cli_opts, args=[]) + + def main(): parser = optparse.OptionParser(usage="%prog [--compact]") parser.add_option("--compact", action="store_true", @@ -661,6 +729,12 @@ def main(): not options.compact, opts=burnin.OPTIONS, args=burnin.ARGUMENTS) + # htools, if enabled + if _autoconf.HTOOLS: + for script in _autoconf.HTOOLS_PROGS: + WriteHaskellCompletion(sw, script, htools=True, + debug=not options.compact) + # Reset extglob to original value sw.Write("[[ -n \"$gnt_shopt_extglob\" ]] && $gnt_shopt_extglob") sw.Write("unset gnt_shopt_extglob") -- GitLab