summaryrefslogtreecommitdiff
path: root/tools/yelp-new.in
diff options
context:
space:
mode:
Diffstat (limited to 'tools/yelp-new.in')
-rwxr-xr-xtools/yelp-new.in445
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)