123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306 |
- #!/bin/bash
-
-
- usage() {
- local self
- self="$(basename "$0")"
- warn "usage: $self [-f|--force] [+TEMPLATE] FILE"
- warn "usage: $self -l|--list"
- exit 2
- }
-
- warn() {
- #
- # Print warning
- #
- echo "$@" >&2
- }
-
- die() {
- #
- # Warn and exit prematurely
- #
- warn "$@"
- exit 3
- }
-
- lstemplates() {
- #
- # Print list of valid templates
- #
- echo sed
- echo pya
- echo shellfu
- echo Bash
- echo Lua
- echo Perl
- echo py3
- echo Python3
- echo Python
- }
-
- #shellcheck disable=SC2016
- mktemplate() {
- #
- # Print template $Template for $FilePath
- #
- case "$Template" in
-
- sh)
- echo "#!/bin/sh"
- echo ''
- echo ''
- ;;
-
- bash|Bash)
- echo "#!/bin/bash"
- echo ''
- echo ''
- ;;
-
- sed)
- echo "#!/bin/sed -f"
- echo ''
- echo ''
- ;;
-
- lua|Lua)
- echo "#!$(which lua)"
- echo ''
- ;;
-
- pl|Perl)
- echo "#!$(which perl)"
- echo ''
- echo 'use strict;'
- echo 'use warnings;'
- echo ''
- echo ''
- ;;
-
- py|Python)
- echo "#!$(which python)"
- echo ''
- echo "if __name__ == '__main__':"
- echo ' '
- ;;
-
- py3|Python3)
- echo "#!/usr/bin/python3"
- echo ''
- echo 'import sys'
- echo ''
- echo ''
- echo 'class UsageError(ValueError):'
- echo ' pass'
- echo ''
- echo ''
- echo 'def usage():'
- echo ' self = sys.argv[0]'
- echo ' raise UsageError("usage: %s [-j|-t|-p] YAML_FILE.." % self)'
- echo ''
- echo ''
- echo 'def main(argv):'
- echo ' if len(argv) < 2:'
- echo ' usage()'
- echo ''
- echo ''
- echo 'if __name__ == "__main__":'
- echo ' main(sys.argv[1:])'
- ;;
-
- pya)
- echo '#!/usr/bin/python3'
- echo '"""'
- echo 'A simple application'
- echo '"""'
- echo ''
- echo 'import sys'
- echo 'import traceback'
- echo ''
- echo ''
- echo 'class UsageError(ValueError):'
- echo ' pass'
- echo ''
- echo ''
- echo 'class AppError(RuntimeError):'
- echo ' pass'
- echo ''
- echo ''
- echo 'class BaseApp:'
- echo ' """'
- echo ' Main application class'
- echo ' """'
- echo ''
- echo ' @classmethod'
- echo ' def main(cls, factory=None):'
- echo ' factory = factory if factory else cls.from_argv'
- echo ' try:'
- echo ' app = factory()'
- echo ' es = app.run()'
- echo ' except UsageError as e:'
- echo ' print(e, file=sys.stderr)'
- echo ' sys.exit(2)'
- echo ' except AppError as e:'
- echo ' print(e, file=sys.stderr)'
- echo ' sys.exit(3)'
- echo ' except Exception:'
- echo ' sys.stderr.write(traceback.format_exc())'
- echo ' sys.exit(4)'
- echo ' if type(es) is not int:'
- echo ' msg = ('
- echo ' "%s.run() did not return proper exit status: %r is not int"'
- echo ' % (app.__class__.__name__, es)'
- echo ' )'
- echo ' BaseApp.WARN(msg)'
- echo ' es = 4'
- echo ' sys.exit(es)'
- echo ''
- echo ' @classmethod'
- echo ' def from_argv(cls):'
- echo ' return cls('
- echo ' name=sys.argv[0],'
- echo ' args=sys.argv[1:]'
- echo ' )'
- echo ''
- echo ' def __init__(self, name, args):'
- echo ' self.name = name'
- echo ' self.args = args'
- echo ''
- echo ' def _throw_usage(self, pattern=None):'
- echo ' """'
- echo ' Throw UsageError with pattern *pattern*.'
- echo ' """'
- echo ' parts = ["usage:", self.name]'
- echo ' if pattern:'
- echo ' parts.append(pattern)'
- echo ' raise UsageError(" ".join(parts))'
- echo ''
- echo ' @staticmethod'
- echo ' def WARN(msg):'
- echo ' """'
- echo ' Warn user with message *msg*. *msg* can be string or a list of lines.'
- echo ' """'
- echo ' if type(msg) is list:'
- echo ' lines = msg'
- echo ' else:'
- echo ' lines = [str(msg)]'
- echo ' for line in lines:'
- echo ' print(line, file=sys.stderr)'
- echo ''
- echo ' def _validate(self):'
- echo ' """'
- echo ' Validate *self.args*; throw UsageError if needed.'
- echo ' """'
- echo ' if not self.args:'
- echo ' self._throw_usage("ARG..")'
- echo ''
- echo ' def run(self):'
- echo ' """'
- echo ' Run the application; return integer exit status'
- echo ' """'
- echo ' self._validate()'
- echo ' if self.args[0] == "--fail":'
- echo ' raise AppError("you asked for it")'
- echo ' if self.args[0] == "--fail-unexpectedly":'
- echo ' raise RuntimeError("you asked for it ANyway")'
- echo ' if self.args[0] == "--warn":'
- echo ' BaseApp.WARN("you asked for a warning")'
- echo ' return 0'
- echo ' if self.args[0] == "--badret":'
- echo ' return object()'
- echo ' return 0'
- echo ''
- echo ''
- echo 'class App(BaseApp):'
- echo ''
- echo ' def _validate(self):'
- echo ' """'
- echo ' Validate *self.args*; throw UsageError as needed.'
- echo ''
- echo ' Prefer using self._throw_usage().'
- echo ' """'
- echo ' App.WARN("You need to rewrite App._validate()!!!")'
- echo ' super()._validate()'
- echo ''
- echo ' def run(self):'
- echo ' """'
- echo ' Run the application; return integer exit status'
- echo ' """'
- echo ' App.WARN("You need to rewrite App.run()")'
- echo ' super().run()'
- echo ''
- echo ''
- echo 'if __name__ == "__main__":'
- echo ' App.main()'
- ;;
-
- shellfu)
- echo "#!/bin/bash"
- echo ""
- echo '#shellcheck disable=SC1090'
- echo '. "$(sfpath)" || exit 3'
- echo ''
- echo 'shellfu import pretty'
- echo ''
- echo 'usage() {'
- echo ' mkusage "$@" "[-d] [-v] ARG..."'
- echo '}'
- echo ''
- echo 'main() {'
- echo ' while true; do case $1 in'
- echo ' -d) PRETTY_DEBUG=true; shift ;;'
- echo ' -v) PRETTY_VERBOSE=true; shift ;;'
- echo ' -*) usage -w "unknown argument: $1" ;;'
- echo ' *) break ;;'
- echo ' esac done'
- echo '}'
- echo ''
- echo 'main "$@"'
- ;;
-
- *)
- die "unknown template or language: $Template"
- ;;
- esac
- }
-
- guess_language() {
- #
- # Guess intended language from filepath $FilePath
- #
- local fname # file name
- fname="$(basename "$FilePath")"
- case "$fname" in
- *.*) echo "${fname##*.}" ;;
- *) echo "$MKX_DEFAULT_LANG" ;;
- esac
- }
-
-
- #
- # Default language
- #
- MKX_DEFAULT_LANG=${MKX_DEFAULT_LANG:-sh}
-
- main() {
- local FilePath # destination file path
- local Template # built-in template name
- local careful # ignore existing file
- careful=true
- while true; do case $1 in
- -f|--force) careful=false; shift ;;
- -l|--list) lstemplates; exit 0 ;;
- -*) usage ;;
- +*) Template="${1:1}"; shift ;;
- *) break ;;
- esac done
- FilePath="$1"
- test -n "$FilePath" || usage
- test -f "$FilePath" && $careful && die "file already exists: $FilePath"
- test -n "$Template" || Template=$(guess_language)
- mktemplate > "$FilePath"
- chmod +x "$FilePath"
- }
-
- main "$@"
|