--- a +++ b/tools/argparse.bash @@ -0,0 +1,103 @@ +#!/usr/bin/env bash + +# Use python's argparse module in shell scripts +# +# The function `argparse` parses its arguments using +# argparse.ArgumentParser; the parser is defined in the function's +# stdin. +# +# Executing ``argparse.bash`` (as opposed to sourcing it) prints a +# script template. +# +# https://github.com/nhoffman/argparse-bash +# MIT License - Copyright (c) 2015 Noah Hoffman +# +# The MIT License (MIT) +# +# Copyright (c) 2015 Noah Hoffman +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +argparse(){ + argparser=$(mktemp 2>/dev/null || mktemp -t argparser) + cat > "$argparser" <<EOF +from __future__ import print_function +import argparse +import os +import sys + + +class MyArgumentParser(argparse.ArgumentParser): + def print_help(self, file=None): + """Print help and exit with error""" + super(MyArgumentParser, self).print_help(file=file) + sys.exit(1) + +parser = MyArgumentParser(prog=os.path.basename("$0"), + description="""$ARGPARSE_DESCRIPTION""") +EOF + + # stdin to this function should contain the parser definition + cat >> "$argparser" + + cat >> "$argparser" <<EOF +args = parser.parse_args() +for arg in [a for a in dir(args) if not a.startswith('_')]: + key = arg.upper() + value = getattr(args, arg, None) + + if isinstance(value, bool) or value is None: + print('{0}="{1}";'.format(key, 'yes' if value else '')) + elif isinstance(value, list): + print('{0}=({1});'.format(key, ' '.join('"{0}"'.format(s) for s in value))) + else: + print('{0}="{1}";'.format(key, value)) +EOF + + # Define variables corresponding to the options if the args can be + # parsed without errors; otherwise, print the text of the error + # message. + if python "$argparser" "$@" &> /dev/null; then + eval $(python "$argparser" "$@") + retval=0 + else + python "$argparser" "$@" + retval=1 + fi + + rm "$argparser" + return $retval +} + +# print a script template when this script is executed +if [[ $0 == *argparse.bash ]]; then + cat <<FOO +#!/usr/bin/env bash + +source \$(dirname \$0)/argparse.bash || exit 1 +argparse "\$@" <<EOF || exit 1 +parser.add_argument('infile') +parser.add_argument('-o', '--outfile') + +EOF + +echo "INFILE: \${INFILE}" +echo "OUTFILE: \${OUTFILE}" +FOO +fi