changeset 586:daa3b76bd11f

More abcfield.py updates and mark it Python 3. - Move title fixups into Python. - Move key display name expansion into Python. - Add Dottes-specific header continuation line format. None of the usual tools appears to support the official +: continuation.
author Jim Hague <jim.hague@acm.org>
date Mon, 31 Oct 2016 23:48:45 +0000
parents 0a2fc73ba5ec
children 1b79867b4f35
files abcfield.py makeBookeTunePages.sh makeWeb.sh
diffstat 3 files changed, 138 insertions(+), 120 deletions(-) [+]
line wrap: on
line diff
--- a/abcfield.py	Mon Oct 31 23:45:00 2016 +0000
+++ b/abcfield.py	Mon Oct 31 23:48:45 2016 +0000
@@ -1,8 +1,20 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 #
 # Extact a text field (title, by default) from a .abc file, and print it out
 # with any ABC accented characters converted to HTML (default) or Latex.
-# Recognise continuation fields and print those too.
+#
+# Optionally rearrange a field 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.
 #
 
 import optparse
@@ -87,7 +99,18 @@
     "ss" : ("&szlig;", "\\ss"),
 }
 
-def convertField(t, options):
+abckeys = {
+    "m":   "Minor",
+    "min": "Minor",
+    "mix": "Mixolydian",
+    "dor": "Dorian",
+    "phr": "Phrygian",
+    "lyd": "Lydian",
+    "loc": "Locrian",
+}
+
+# Convert ABC accented chars to HTML entities or LaTex.
+def convertAccents(t, latex=False):
     res = ""
     while True:
         p = t.partition('\\')
@@ -97,66 +120,121 @@
         abc = p[2][0:2]
         t = p[2][2:]
         if abc in accentedletters:
-            if options.html:
+            if latex:
+                res += accentedletters[abc][1]
+            else:
                 res += accentedletters[abc][0]
-            else:
-                res += accentedletters[abc][1]
         else:
             res += "\\" + abc
     return res
 
-def process(inf, options):
-    n = options.index
-    found = False
+# Convert Title fields from sort to display, so Bat, The->The Bat.
+def convertTitleToDisplay(t):
+    p = t.rpartition(',')
+    if p[1] == "":
+        return t
+    else:
+        return p[2].strip() + " " + p[0].strip()
+
+# Convert Key field from ABC to display, so G#dor->G# Dorian.
+def convertKeyToDisplay(t):
+    letter = t[0].upper()
+    accidental = ""
+    mode = ""
+    try:
+        accidental = t[1]
+        if accidental == '#' or accidental == 'b':
+            mode = t[2:]
+        else:
+            accidental = ""
+            mode = t[1:]
+    except IndexError:
+        pass
+    mode = mode.strip().lower()
+    return letter + accidental + ' ' + abckeys.get(mode, "Major")
+
+# Return the raw text for a given field. Optionally the nth field is taken,
+# or the field data must start with a designated string to be recognised.
+def getFieldText(inf, field, n = 1, starts = None):
+    res = None
     for line in inf:
         line = line.strip()
         if len(line) > 2 and line[1] == ':':
-            if found:
-                if line[0] != '+':
+            if line[0] == "+" or (line[0] == field and line[2] == "+"):
+                if not res:
+                    continue
+                if line[0] == "+":
+                    line = line[2:]
+                else:
+                    line = line[3:]
+                res = res + '\n' + line.strip()
+            else:
+                if res:
                     break
-                line = line[2:].strip()
-            elif line[0] == options.field:
-                if n > 1:
-                    n = n - 1
-                    continue
-                else:
+                if line[0] == field:
                     line = line[2:].strip()
-                    if len(options.starts) > 0:
-                        if line.find(options.starts) == 0:
-                            line = line[len(options.starts):].strip()
-                        else:
+                    if starts:
+                        if line.find(starts) != 0:
                             continue
-            else:
-                continue
-            found = True
-            print(convertField(line, options))
-    return found
+                        line = line[len(starts):].strip()
+                    if n > 1:
+                        n = n - 1
+                        continue
+                    res = line
+    return res
+
+# Return display text for a given field.
+def getFieldDisplayText(inf, field, n = 1, starts = None, latex = False):
+    res = getFieldText(inf, field, n, starts)
+    if res:
+        if field.upper() == "T":
+            res = convertTitleToDisplay(res)
+        elif field.upper() == "K":
+            res = convertKeyToDisplay(res)
+        res = convertAccents(res, latex)
+    return res
 
-parser = optparse.OptionParser(usage="usage: %prog [options] [filename]\n\n"
-                                     "  Extract field data from ABC file.")
-parser.add_option("-f", "--field", dest="field", default="T",
-                  help="extract the field FIELD", metavar="FIELD")
-parser.add_option("-l", "--latex", dest="latex",
-                  action="store_true", default=False,
-                  help="convert special characters for LaTeX")
-parser.add_option("-n", "--index", dest="index",
-                  action="store", type="int", default=1,
-                  help="report INDEXth value [default: %default]",
-                  metavar="INDEX")
-parser.add_option("-s", "--starts", dest="starts",
-                  action="store", type="string", default="",
-                  help="report only if line starts CONTENT and remove CONTENT",
-                  metavar="CONTENT")
-(options, args) = parser.parse_args()
+if __name__ == "__main__":
+    def process(inf, options):
+        if options.display:
+            line = getFieldDisplayText(inf, options.field, options.index, options.starts, options.latex)
+        else:
+            line = getFieldText(inf, options.field, options.index, options.starts)
+        if line:
+            print(line)
+            return True
+        else:
+            return False
 
-res = False
-if len(args) > 0:
-    for arg in args:
-        try:
-            inf = open(arg, "r")
-            res = res or process(inf, options)
-        finally:
-            inf.close()
-else:
-    res = process(sys.stdin, options)
-sys.exit(int(not res))
+    # execute only if run as a script
+    parser = optparse.OptionParser(usage="usage: %prog [options] [filename]\n\n"
+                                   "  Extract field data from ABC file.")
+    parser.add_option("-f", "--field", dest="field", default="T",
+                      help="extract the field FIELD", metavar="FIELD")
+    parser.add_option("-l", "--latex", dest="latex",
+                      action="store_true", default=False,
+                      help="convert special characters for LaTeX")
+    parser.add_option("-d", "--display", dest="display",
+                      action="store_true", default=False,
+                      help="convert to display text")
+    parser.add_option("-n", "--index", dest="index",
+                      action="store", type="int", default=1,
+                      help="report INDEXth value [default: %default]",
+                      metavar="INDEX")
+    parser.add_option("-s", "--starts", dest="starts",
+                      action="store", type="string", default=None,
+                      help="report only if line starts CONTENT and remove CONTENT",
+                      metavar="CONTENT")
+    (options, args) = parser.parse_args()
+
+    res = False
+    if len(args) > 0:
+        for arg in args:
+            try:
+                inf = open(arg, "r")
+                res = res or process(inf, options)
+            finally:
+                inf.close()
+    else:
+        res = process(sys.stdin, options)
+    sys.exit(int(not res))
--- a/makeBookeTunePages.sh	Mon Oct 31 23:45:00 2016 +0000
+++ b/makeBookeTunePages.sh	Mon Oct 31 23:48:45 2016 +0000
@@ -8,13 +8,6 @@
 # makeGraphics.sh to make these.
 #
 
-# Restore titles like 'Exploding Potato, The' to the
-# expected 'The Exploding Potato'.
-fixtitle()
-{
-    retval=`echo "$1" | sed -e "s/\(.*\), *\(.*\)/\2 \1/"`
-}
-
 if [ $# != 1 ]; then
     echo "Usage: makeBookeTunePages.sh <book dir name>"
     exit 1
@@ -38,12 +31,8 @@
     while read filename
     do
         name=`basename $filename .abc`
-        title=`$dir/abcfield.py --field T --latex $filename`
-        fixtitle "$title"
-        title=$retval
-        subtitle=`$dir/abcfield.py --index 2 --field T --latex $filename`
-        fixtitle "$subtitle"
-        subtitle=$retval
+        title=`$dir/abcfield.py --field T --latex --display $filename`
+        subtitle=`$dir/abcfield.py --index 2 --field T --latex --display $filename`
         composer=`$dir/abcfield.py --field C --latex $filename`
 
         changefile=`$dir/abcfield.py --field N --starts "Change:" $filename`
@@ -51,9 +40,7 @@
         changetitle=""
         if [ -n "$changefile" ]; then
             changename=`basename $changefile .abc`
-            changetitle=`$dir/abcfield.py --field T --latex $booke/$changefile`
-            fixtitle "$changetitle"
-            changetitle=$retval
+            changetitle=`$dir/abcfield.py --field T --latex --display $booke/$changefile`
         fi
 
         credit=`$dir/abcfield.py --field N --starts "Credit:" $filename`
--- a/makeWeb.sh	Mon Oct 31 23:45:00 2016 +0000
+++ b/makeWeb.sh	Mon Oct 31 23:48:45 2016 +0000
@@ -7,44 +7,6 @@
 
 #set -x
 
-# Restore titles like 'Exploding Potato, The' to the
-# expected 'The Exploding Potato'.
-fixtitle()
-{
-    retval=`echo "$1" | sed -e "s/\(.*\), *\(.*\)/\2 \1/"`
-}
-
-# Format a key in ABC (G, Gmin, etc.) in standard presentation format.
-fixkey()
-{
-    letter=${1:0:1}
-    accidental=${1:1:1}
-    if [ "$accidental" != "#" -a "$accidental" != "b" ]; then
-        accidental=""
-        mode=${1:1:3}
-    else
-        mode=${1:2:3}
-    fi
-    mode=${mode,,}
-    mode=${mode/ //g}
-    if [ "$mode" = "m" -o "$mode" = "min" ]; then
-        mode="Minor"
-    elif [ "$mode" = "mix" ]; then
-        mode="Mixolydian"
-    elif [ "$mode" = "dor" ]; then
-        mode="Dorian"
-    elif [ "$mode" = "phr" ]; then
-        mode="Phrygian"
-    elif [ "$mode" = "lyd" ]; then
-        mode="Lydian"
-    elif [ "$mode" = "loc" ]; then
-        mode="Locrian"
-    else
-        mode="Major"
-    fi
-    retval="${letter}${accidental} ${mode}"
-}
-
 if [ $# -lt 2 -o $# -gt 3 ]; then
     echo "Usage: makeWeb.sh <book dir name> <master book dir name> [<instrument name>]"
     exit 1
@@ -105,22 +67,15 @@
         name=`basename $filename .abc`
 
         # Extract items to substitute in the web page.
-        title=`$dir/abcfield.py --field T $filename`
-        fixtitle "$title"
-        title=$retval
-        subtitle=`$dir/abcfield.py --index 2 --field T $filename`
-        fixtitle "$subtitle"
-        subtitle=$retval
+        title=`$dir/abcfield.py --field T --display $filename`
+        subtitle=`$dir/abcfield.py --index 2 --field T --display $filename`
         composer=`$dir/abcfield.py --field C  $filename`
         changefile=`$dir/abcfield.py --field N --starts "Change:" $filename`
         changetitle=""
         changevisibility="no"
         if [ -n "$changefile" ]; then
-            changetitle=`$dir/abcfield.py --field T $bookedir/$changefile`
+            changetitle=`$dir/abcfield.py --field T --display $bookedir/$changefile`
             changevisibility="yes"
-
-            fixtitle "$changetitle"
-            changetitle=$retval
         fi
         credit=`$dir/abcfield.py --field N --starts "Credit:" $filename`
         creditvisibility="no"
@@ -128,9 +83,7 @@
             creditvisibility="yes"
         fi
         lastchanged=`hg log --limit 1 --template "{date|shortdate}" $masterbookedir/${name}.abc`
-        key=`$dir/abcfield.py --field K $filename`
-        fixkey $key
-        key=$retval
+        key=`$dir/abcfield.py --field K --display $filename`
 
         # Copy the ABC into the web.
         cp $filename $webdir