diff options
Diffstat (limited to 'tools/yelp-new.in')
-rwxr-xr-x | tools/yelp-new.in | 445 |
1 files changed, 300 insertions, 145 deletions
diff --git a/tools/yelp-new.in b/tools/yelp-new.in index 76bd101..cb923d5 100755 --- a/tools/yelp-new.in +++ b/tools/yelp-new.in @@ -1,6 +1,7 @@ -#!/bin/sh +#!/bin/python3 +# # yelp-new -# Copyright (C) 2010 Shaun McCance <shaunm@gnome.org> +# Copyright (C) 2010-2020 Shaun McCance <shaunm@gnome.org> # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -16,147 +17,301 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -tmpldir="@YELP_TMPL_DIR@" - -yelp_describe_tmpl () { - line=" "`basename "$1" | sed -e 's/\.'$2'$//'` - desc=`cat "$f" | grep '<\?yelp-tmpl-desc' | sed -e 's/<?yelp-tmpl-desc //' -e 's/?>$//'` - if [ "x$desc" != "x" ]; then - line="$line - $desc" - fi - echo "$line" -} - -yelp_get_extension () { - echo "$1" | awk -F . '{print $NF}' -} - -yelp_usage() { - echo "Usage: yelp-new [OPTIONS] <TEMPLATE> <ID> [TITLE]" - echo "" - echo "Options:" - echo " --stub Create a .page.stub file instead of a .page file" - echo " --tmpl Copy an installed template to a local template" - if [ -f *.page.tmpl ]; then - echo "" - echo "Local Mallard Templates:" - for f in *.page.tmpl; do - yelp_describe_tmpl "$f" "page.tmpl" - done - fi - if [ -f ${tmpldir}*.page ]; then - echo "" - echo "Mallard Templates:" - for f in ${tmpldir}*.page; do - yelp_describe_tmpl "$f" "page" - done - fi - if [ -f *.docbook.tmpl ]; then - echo "" - echo "Local DocBook Templates:" - for f in *.docbook.tmpl; do - yelp_describe_tmpl "$f" "xml.tmpl" - done - fi - if [ -f ${tmpldir}*.docbook ]; then - echo "" - echo "DocBook Templates:" - for f in ${tmpldir}*.docbook; do - yelp_describe_tmpl "$f" "xml" - done - fi -} - -if [ $# -lt 2 ]; then - yelp_usage - exit 1 -fi - -# Process options -spec="" -while [ $# -gt 0 ]; do - case "$1" in - --stub) - spec=".stub" - shift;; - --tmpl) - spec=".tmpl" - shift;; - -h | --help) - yelp_usage - exit 0;; - *) - break - esac -done - -# Locate the template file -if [ $(yelp_get_extension ${1}) = "tmpl" -a -f "${1}" ]; then - infile="${1}" - outext="."$(yelp_get_extension $(basename "${1}" ".tmpl")) -elif [ -f "${1}.page.tmpl" ]; then - infile="${1}.page.tmpl" - outext=".page" -elif [ -f "${tmpldir}${1}.page" ]; then - infile="${tmpldir}${1}.page" - outext=".page" -elif [ -f "${1}.docbook.tmpl" ]; then - infile="${1}.docbook.tmpl" - outext=".docbook" -elif [ -f "${tmpldir}${1}.docbook" ]; then - infile="${tmpldir}${1}.docbook" - outext=".docbook" -else - echo "Error: No template named ${1} found" - exit 1 -fi - -# Set up some variables for substitution -if type git >/dev/null 2>&1; then - username=`git config user.name` - useremail=`git config user.email` -fi -if [ "x$username" = "x" -a "x$useremail" = "x" ]; then - if type bzr >/dev/null 2>&1; then - username=`bzr whoami | sed -e 's/ <.*//'` - useremail=`bzr whoami --email` - fi -fi -if [ "x$username" = "x" -a "x$useremail" = "x" ]; then - username='YOUR NAME' - useremail='YOUR EMAIL ADDRESS' -fi -pagetitle="$3" -if [ "x$pagetitle" = "x" ]; then - pagetitle="TITLE" -fi - -outid=$(basename "${2}") - -if [ "x$spec" != "x" ]; then - if [ "."$(yelp_get_extension "${2}") = "$spec" ]; then - outfile="${2}" - elif [ "."$(yelp_get_extension "${2}") = "$outext" ]; then - outfile="${2}${spec}" - else - outfile="${2}${outext}${spec}" - fi -elif [ "."$(yelp_get_extension ${2}) = "$outext" ]; then - outfile="${2}" -else - outfile="${2}${outext}" -fi - -if [ "x$spec" = "x.tmpl" ]; then - cp "$infile" "$outfile" -else - cat "$infile" | grep -v '<\?yelp-tmpl-desc' | sed \ - -e s/@ID@/"$outid"/ \ - -e s/@DATE@/`date +%Y-%m-%d`/ \ - -e s/@YEAR@/`date +%Y`/ \ - -e s/@NAME@/"$username"/ \ - -e s/@EMAIL@/"$useremail"/ \ - -e s/@TITLE@/"$pagetitle"/ \ - > "$outfile" -fi +import configparser +import datetime +import os +import subprocess +import sys + + +DATADIR = '@DATADIR@' + +class YelpNew: + arguments = [ + ('help', '-h', None, 'Show this help and exit'), + ('stub', None, None, 'Create a stub file with .stub appended'), + ('tmpl', None, None, 'Copy an installed template to a local template'), + ('version', '-v', 'VERS', 'Specify the version number to substitute') + ] + + def __init__(self): + self.options = {} + self.fileargs = [] + self.parse_args(sys.argv[1:]) + self.config = configparser.ConfigParser() + try: + self.config.read('.yelp-tools.cfg') + except: + self.config = None + + + def parse_args(self, args): + while len(args) > 0: + argdef = None + if args[0].startswith('--'): + for arg_ in self.arguments: + if args[0] == '--' + arg_[0]: + argdef = arg_ + break + if argdef is None: + self.print_usage() + return 1 + elif args[0].startswith('-'): + for arg_ in self.arguments: + if args[0] == arg_[1]: + argdef = arg_ + break + if argdef is None: + self.print_usage() + return 1 + if argdef is not None: + takesarg = (argdef[2] is not None) + if takesarg: + if len(args) < 2: + self.print_usage() + return 1 + self.options.setdefault(argdef[0], []) + self.options[argdef[0]].append(args[1]) + args = args[2:] + else: + self.options[argdef[0]] = True + args = args[1:] + else: + self.fileargs.append(args[0]) + args = args[1:] + + + def get_option_bool(self, arg): + if arg in self.options: + return self.options[arg] == True + if self.config is not None: + val = self.config.get('new', arg, fallback=None) + if val is not None: + return (val == 'true') + val = self.config.get('default', arg, fallback=None) + if val is not None: + return (val == 'true') + return False + + + def get_option_str(self, arg): + if arg in self.options: + if isinstance(self.options[arg], list): + return self.options[arg][-1] + if self.config is not None: + val = self.config.get('new', arg, fallback=None) + if val is not None: + return val + val = self.config.get('default', arg, fallback=None) + if val is not None: + return val + return None + + + def get_replacements(self, pageid): + repl = {'ID' : pageid} + if len(self.fileargs) > 2: + repl['TITLE'] = ' '.join(self.fileargs[2:]) + else: + repl['TITLE'] = 'TITLE' + today = datetime.datetime.now() + repl['DATE'] = today.strftime('%Y-%m-%d') + repl['YEAR'] = today.strftime('%Y') + + username = None + useremail = None + isgit = False + isbzr = False + cwd = os.getcwd() + while cwd: + if os.path.exists(os.path.join(cwd, '.git')): + isgit = True + break + if os.path.exists(os.path.join(cwd, '.bzr')): + isbzr = True + break + newcwd = os.path.dirname(cwd) + if newcwd == cwd: + break + cwd = newcwd + if isbzr: + try: + who = subprocess.run(['bzr', 'whoami'], check=True, + capture_output=True, encoding='utf8') + username, useremail = who.stdout.split('<') + username = username.strip() + useremail = useremail.split('>')[0].strip() + except: + username = None + useremail = None + if username is None: + try: + who = subprocess.run(['git', 'config', 'user.name'], check=True, + capture_output=True, encoding='utf8') + username = who.stdout.strip() + who = subprocess.run(['git', 'config', 'user.email'], check=True, + capture_output=True, encoding='utf8') + useremail = who.stdout.strip() + except: + username = None + useremail = None + repl['NAME'] = username or 'YOUR NAME' + repl['EMAIL'] = useremail or 'YOUR EMAIL ADDRESS' + repl['VERSION'] = self.get_option_str('version') or 'VERSION.NUMBER' + return repl + + + def main(self): + if len(self.fileargs) < 2: + self.print_usage() + return 1 + + tmpl = self.fileargs[0] + if '.' not in tmpl: + tmpl = tmpl + '.page' + ext = '.page' + elif tmpl.endswith('.page'): + ext = '.page' + elif tmpl.endswith('.duck'): + ext = '.duck' + if self.get_option_bool('stub'): + ext = ext + '.stub' + tmplfile = os.path.join(os.getcwd(), tmpl + '.tmpl') + if not os.path.exists(tmplfile): + tmplfile = os.path.join(DATADIR, 'templates', tmpl) + if not os.path.exists(tmplfile): + print('No template found named ' + tmpl, file=sys.stderr) + sys.exit(1) + pageid = self.fileargs[1] + istmpl = self.get_option_bool('tmpl') + if istmpl: + ext = ext + '.tmpl' + repl = {} + else: + repl = self.get_replacements(pageid) + def _writeout(outfile, infilename, depth=0): + if depth > 10: + # We could do this smarter by keeping a stack of infilenames, but why? + print('Recursion limit reached for template includes', file=sys.stderr) + sys.exit(1) + for line in open(infilename): + if (not istmpl) and line.startswith('<?yelp-tmpl-desc'): + continue + if (not istmpl) and line.startswith('[-] yelp-tmpl-desc'): + continue + while line is not None and '{{' in line: + before, after = line.split('{{', maxsplit=1) + if '}}' in after: + var, after = after.split('}}', maxsplit=1) + outfile.write(before) + isinclude = var.startswith('INCLUDE ') + if isinclude: + newfile = os.path.join(os.path.dirname(infilename), var[8:].strip()) + _writeout(outfile, newfile, depth=depth+1) + elif istmpl: + outfile.write('{{' + var + '}}') + else: + outfile.write(repl.get(var, '{{' + var + '}}')) + if isinclude and after == '\n': + line = None + else: + line = after + else: + outfile.write(line) + line = None + if line is not None: + outfile.write(line) + + if os.path.exists(pageid + ext): + print('Output file ' + pageid + ext + ' already exists', file=sys.stderr) + sys.exit(1) + with open(pageid + ext, 'w') as outfile: + _writeout(outfile, tmplfile) + + + def print_usage(self): + print('Usage: yelp-new [OPTIONS] <TEMPLATE> <ID> [TITLE]\n') + print('Create a new file from an installed or local template file,\n' + + 'or create a new local template. TEMPLATE must be the name of\n' + + 'an installed or local template. ID is a page ID (and base\n' + + 'filename) for the new page. The optional TITLE argument\n' + 'provides the page title\n') + print('Options:') + maxarglen = 2 + args = [] + for arg in self.arguments: + argkey = '--' + arg[0] + if arg[1] is not None: + argkey = arg[1] + ', ' + argkey + if arg[2] is not None: + argkey = argkey + ' ' + arg[2] + args.append((argkey, arg[3])) + for arg in args: + maxarglen = max(maxarglen, len(arg[0]) + 1) + for arg in args: + print(' ' + (arg[0]).ljust(maxarglen) + ' ' + arg[1]) + localpages = [] + localducks = [] + installedpages = [] + installedducks = [] + descs = {} + maxlen = 0 + def _getdesc(fpath): + for line in open(fpath): + if line.startswith('<?yelp-tmpl-desc '): + s = line[16:].strip() + if s.endswith('?>'): + s = s[:-2] + return s + if line.startswith('[-] yelp-tmpl-desc'): + return line[18:].strip() + return '' + for fname in os.listdir(os.getcwd()): + if fname.endswith('.page.tmpl'): + fname = fname[:-5] + maxlen = max(maxlen, len(fname)) + localpages.append(fname) + elif fname.endswith('.duck.tmpl'): + fname = fname[:-5] + maxlen = max(maxlen, len(fname)) + localducks.append(fname) + else: + continue + descs[fname] = _getdesc(os.path.join(os.getcwd(), fname + '.tmpl')) + for fname in os.listdir(os.path.join(DATADIR, 'templates')): + if fname.endswith('.page'): + if fname in localpages: + continue + maxlen = max(maxlen, len(fname)) + installedpages.append(fname) + elif fname.endswith('.duck'): + if fname in localducks: + continue + maxlen = max(maxlen, len(fname)) + installedducks.append(fname) + else: + continue + descs[fname] = _getdesc(os.path.join(DATADIR, 'templates', fname)) + if len(localpages) > 0: + print('\nLocal Mallard Templates:') + for page in localpages: + print(' ' + page.ljust(maxlen) + ' ' + descs.get(page, '')) + if len(localducks) > 0: + print('\nLocal Ducktype Templates:') + for duck in localducks: + print(' ' + duck.ljust(maxlen) + ' ' + descs.get(duck, '')) + if len(installedpages) > 0: + print('\nInstalled Mallard Templates:') + for page in installedpages: + print(' ' + page.ljust(maxlen) + ' ' + descs.get(page, '')) + if len(installedducks) > 0: + print('\nInstalled Ducktype Templates:') + for duck in installedducks: + print(' ' + duck.ljust(maxlen) + ' ' + descs.get(duck, '')) + +if __name__ == '__main__': + try: + sys.exit(YelpNew().main()) + except KeyboardInterrupt: + sys.exit(1) |