abctemplate.py
author Jim Hague <jim.hague@acm.org>
Fri, 20 Sep 2019 10:54:17 +0100
changeset 1002 19c737d183ac
parent 732 c81a1ed21877
permissions -rwxr-xr-x
Small correction in B part, and correct the part repeats.
#!/usr/bin/env python3
#
# Fill in a template with data from fields in an ABC file.
# Fields have any ABC accented characters converted to HTML (default) or Latex.
#
# Rearrange some field contents into display format:
# * In Title fields, change 'sort' form such as 'Exploding Potato, The'
#   to display format 'The Exploding Potato'.
# * In Key fields, translate the ABC key representation to full text,
#   e.g. G#dor becomes G# Dorian.
#
# Recognise continuation header fields and print those too. The ABC standard
# defines continuation fields as starting ':+'. Regrettably none of the tools
# I am using the Booke recognise that syntax, so I am adopting a Booke
# convention of '<header>:+' *also* being a continuation. Note that a
# continuation is a distinct line in the field value; the value has a line
# break between it and the previous line.
#
# Templates are read from file, and are in Python standard library format.
# The following values are substituted:
# * name. The file base name. Base filename without extension.
# * title. The tune title.
# * subtitle. The tune subtitle (second Title field), if any.
# * fulltitle. The tune title followed, if it exists, by " (" subtitle ")"
# * tradition. The Morris tradition the dance tune is from.
# * composer. The tune composer.
# * key. The tune key.
# * parts. The tune parts order (A(AB2)3 etc.).
# * changefile. The name of the 'change' file, if any.
# * changename. The change file base name.
# * changetitle. The change file tune title.
# * changevisibility. "yes" if there's a change value, otherwise "no".
# * credit. The 'credit' value.
# * creditvisibility. "yes" if there's a credit value, otherwise "no".
#

import argparse
import pathlib
import string

from abcfield import getFieldDisplayText, getFullTitle

def getFileData(f, latex):
    res = {}
    input_path = pathlib.Path(args.input.name)
    res["name"] = input_path.stem
    fdir = input_path.parent

    lines = f.readlines()
    res["title"] = getFieldDisplayText(lines, fdir, "T", latex=latex)
    res["subtitle"] = getFieldDisplayText(lines, fdir, "T", n=2, latex=latex)
    res["fulltitle"] = getFullTitle(lines, fdir, latex=latex)
    res["tradition"] = getFieldDisplayText(lines, fdir, "A", latex=latex)
    res["composer"] = getFieldDisplayText(lines, fdir, "C", latex=latex)
    res["key"] = getFieldDisplayText(lines, fdir, "K", latex=latex)
    res["parts"] = getFieldDisplayText(lines, fdir, "P", latex=latex)
    res["notes"] = getFieldDisplayText(lines, fdir, "N", starts="Dottes:", latex=latex)
    res["history"] = getFieldDisplayText(lines, fdir, "H", starts="Dottes:", latex=latex)
    return res

if __name__ == "__main__":
    parser = argparse.ArgumentParser(description='Substitute values from ABC file into template.')
    parser.add_argument('-l', '--latex', dest='latex',
                        action='store_true',
                        help='output LaTeX formatted values (default is HTML)')
    parser.add_argument('-t', '--template', dest='template',
                        type=argparse.FileType('r'),
                        required=True,
                        help='template file')
    parser.add_argument('-v', '--value', dest='values', action="append",
                        default=[], help='define var=value items for templater')
    parser.add_argument('-n', '--next', dest='nextfile',
                        type=argparse.FileType('r'),
                        help='next tune file')
    parser.add_argument('-p', '--prev', dest='prevfile',
                        type=argparse.FileType('r'),
                        help='previous tune file')
    parser.add_argument('input', type=argparse.FileType('r'),
                        help='input ABC file')
    args = parser.parse_args()

    fields = getFileData(args.input, args.latex)

    vars = {}
    vars["notesvisibility"] = "no"
    vars["historyvisibility"] = "no"

    for name in ["name", "title", "subtitle", "fulltitle", "tradition",
                 "composer", "key", "parts", "notes", "history"]:
        vars[name] = fields[name]

    if vars["notes"]:
        vars["notesvisibility"] = "yes"
    if vars["history"]:
        vars["historyvisibility"] = "yes"

    if args.nextfile:
        fields = getFileData(args.nextfile, args.latex)
    for name in ["name", "title", "subtitle", "fulltitle"]:
        vars["next" + name] = fields[name] if args.nextfile else ""

    if args.prevfile:
        fields = getFileData(args.prevfile, args.latex)
    for name in ["name", "title", "subtitle", "fulltitle"]:
        vars["prev" + name] = fields[name] if args.prevfile else ""

    for val in args.values:
        keyval = val.partition("=")
        vars[keyval[0]] = keyval[2]

    print(string.Template(args.template.read()).substitute(vars))