]> git.donarmstrong.com Git - lilypond.git/blobdiff - python/convertrules.py
Merge remote-tracking branch 'origin' into translation
[lilypond.git] / python / convertrules.py
index 6ea53ea37d33a1d35c316b962fdeba69b742c332..5eb2a75bfc4f17bbcea91068518c2e928b502d99 100644 (file)
@@ -1,3 +1,4 @@
+# -*- coding: utf-8 -*-
 # (setq py-indent-offset 4)
 
 
@@ -9,9 +10,9 @@ import lilylib
 _ = lilylib._
 
 
-NOT_SMART = "\n" + _ ("Not smart enough to convert %s")
-UPDATE_MANUALLY = _ ("Please refer to the manual for details, and update manually.")
-FROM_TO = _ ( "%s has been replaced by %s")
+NOT_SMART = "\n" + _ ("Not smart enough to convert %s.") + "\n"
+UPDATE_MANUALLY = _ ("Please refer to the manual for details, and update manually.") + "\n"
+FROM_TO = _ ("%s has been replaced by %s") + "\n"
 
 
 class FatalConversionError:
@@ -49,20 +50,15 @@ def rule (version, message):
 @rule ((0, 1, 9), _ ('\\header { key = concat + with + operator }'))
 def conv(str):
     if re.search ('\\\\multi', str):
-        stderr_write ('\n')
         stderr_write (NOT_SMART % "\\multi")
-        stderr_write ('\n')
     return str
 
 
 @rule ((0, 1, 19), _ ('deprecated %s') % '\\octave')
 def conv (str):
     if re.search ('\\\\octave', str):
-        stderr_write ('\n')
         stderr_write (NOT_SMART % "\\octave")
-        stderr_write ('\n')
         stderr_write (UPDATE_MANUALLY)
-        stderr_write ('\n')
     #   raise FatalConversionError ()
     return str
 
@@ -99,9 +95,7 @@ def conv (str):
 @rule ((1, 0, 2), _ ('\\header { key = concat + with + operator }'))
 def conv(str):
     if re.search ('\\\\header', str):
-        stderr_write ('\n')
         stderr_write (NOT_SMART % _ ("new \\header format"))
-        stderr_write ('\n')
     return str
 
 
@@ -128,9 +122,7 @@ def conv(str):
 @rule ((1, 0, 6), 'foo = \\translator {\\type .. } ->\\translator {\\type ..; foo; }')
 def conv(str):
     if re.search ('[a-zA-Z]+ = *\\translator',str):
-        stderr_write ('\n')
         stderr_write (NOT_SMART % _ ("\\translator syntax"))
-        stderr_write ('\n')
     #   raise FatalConversionError ()
     return str
 
@@ -184,9 +176,7 @@ def conv(str):
 @rule ((1, 0, 18), _ ('\\repeat NUM Music Alternative -> \\repeat FOLDSTR Music Alternative'))
 def conv(str):
     if re.search ('\\\\repeat',str):
-        stderr_write ('\n')
         stderr_write (NOT_SMART % "\\repeat")
-        stderr_write ('\n')
     #   raise FatalConversionError ()
     return str
 
@@ -290,9 +280,7 @@ def conv (str):
 @rule ((1, 3, 23), _ ('deprecate %s ') % '\\repetitions')
 def conv(str):
     if re.search ('\\\\repetitions',str):
-        stderr_write ('\n')
         stderr_write (NOT_SMART % "\\repetitions")
-        stderr_write ('\n')
     #   raise FatalConversionError ()
     return str
 
@@ -315,9 +303,7 @@ def conv (str):
     str = re.sub ("\\\\musicalpitch *{([0-9 -]+)}",
                   "\\\\musicalpitch #'(\\1)", str)
     if re.search ('\\\\notenames',str):
-        stderr_write ('\n')
         stderr_write (NOT_SMART % _ ("new \\notenames format"))
-        stderr_write ('\n')
     return str
 
 
@@ -333,9 +319,7 @@ def conv (str):
 @rule ((1, 3, 41), '[:16 c4 d4 ] -> \\repeat "tremolo" 2 { c16 d16 }')
 def conv (str):
     if re.search ('\\[:',str):
-        stderr_write ('\n')
         stderr_write (NOT_SMART % _ ("new tremolo format"))
-        stderr_write ('\n')
     return str
 
 
@@ -354,9 +338,7 @@ def conv (str):
 @rule ((1, 3, 58), 'noteHeadStyle value: string -> symbol')
 def conv (str):
     if re.search ('\\\\keysignature', str):
-        stderr_write ('\n')
         stderr_write (NOT_SMART % '\\keysignature')
-        stderr_write ('\n')
     return str
 
 
@@ -392,7 +374,7 @@ def conv (str):
     return str
 
 
-@rule ((1, 3, 93), _ ('change property definiton case (eg. onevoice -> oneVoice)'))
+@rule ((1, 3, 93), _ ('change property definition case (eg. onevoice -> oneVoice)'))
 def conv (str):
     # Ugh, but meaning of \stemup changed too
     # maybe we should do \stemup -> \stemUp\slurUp\tieUp ?
@@ -453,9 +435,7 @@ def conv (str):
 def conv (str):
     str = re.sub ('ChordNames*', 'ChordNames', str)
     if re.search ('\\\\textscript "[^"]* *"[^"]*"', str):
-        stderr_write ('\n')
         stderr_write (NOT_SMART % _ ("new \\textscript markup text"))
-        stderr_write ('\n')
 
     str = re.sub ('\\textscript +("[^"]*")', '\\textscript #\\1', str)
     return str
@@ -725,8 +705,8 @@ def conv (str):
 def conv (str):
     if re.search (r'\addlyrics',str) \
            and re.search ('automaticMelismata', str)  == None:
-        stderr_write ('\n')
-        stderr_write (NOT_SMART % "automaticMelismata; turned on by default since 1.5.67.")
+        stderr_write (NOT_SMART % "automaticMelismata")
+        stderr_write (_ ("automaticMelismata is turned on by default since 1.5.67."))
         stderr_write ('\n')
         raise FatalConversionError ()
     return str
@@ -963,13 +943,10 @@ def conv(str):
 @rule ((1, 7, 19), _ ("remove %s") % "GraceContext")
 def conv(str):
     if re.search( r'\\GraceContext', str):
-        stderr_write ('\n')
         stderr_write (NOT_SMART % "GraceContext")
         stderr_write (FROM_TO \
                           % ("GraceContext", "#(add-to-grace-init .. )"))
-        stderr_write ('\n')
         stderr_write (UPDATE_MANUALLY)
-        stderr_write ('\n')
         raise FatalConversionError ()
 
     str = re.sub ('HaraKiriStaffContext', 'RemoveEmptyStaffContext', str)
@@ -1001,11 +978,8 @@ def conv(str):
 @rule ((1, 7, 24), _ ("cluster syntax"))
 def conv(str):
     if re.search( r'-(start|stop)Cluster', str):
-        stderr_write ('\n')
         stderr_write (NOT_SMART % _ ("cluster syntax"))
-        stderr_write ('\n')
         stderr_write (UPDATE_MANUALLY)
-        stderr_write ('\n')
 
         raise FatalConversionError ()
     return str
@@ -1286,11 +1260,8 @@ def conv (str):
 @rule ((1, 9, 1), _ ("Remove - before articulation"))
 def conv (str):
     if re.search ("font-style",str):
-        stderr_write ('\n')
         stderr_write (NOT_SMART % "font-style")
-        stderr_write ('\n')
         stderr_write (UPDATE_MANUALLY)
-        stderr_write ('\n')
 
         raise FatalConversionError ()
 
@@ -1328,11 +1299,8 @@ def conv (str):
                   'acciaccatura', str)
 
     if re.search ("context-spec-music", str):
-        stderr_write ('\n')
         stderr_write (NOT_SMART % "context-spec-music")
-        stderr_write ('\n')
         stderr_write (UPDATE_MANUALLY)
-        stderr_write ('\n')
 
         raise FatalConversionError ()
 
@@ -1383,20 +1351,15 @@ def conv (str):
 @rule ((1, 9, 6), _ ('deprecate %s') % 'ly:get-font')
 def conv (str):
     if re.search ("ly:get-font", str) :
-        stderr_write ('\n')
-        stderr_write (NOT_SMART % "(ly:-get-font")
-        stderr_write ('\n')
+        stderr_write (NOT_SMART % "ly:get-font")
         stderr_write (FROM_TO \
                           % ("(ly:paper-get-font (ly:grob-get-paper foo) .. )",
                              "(ly:paper-get-font (ly:grob-get-paper foo) .. )"))
         stderr_write (UPDATE_MANUALLY)
-        stderr_write ('\n')
         raise FatalConversionError ()
 
     if re.search ("\\pitch *#", str) :
-        stderr_write ('\n')
         stderr_write (NOT_SMART % "\\pitch")
-        stderr_write ('\n')
         stderr_write (_ ("Use Scheme code to construct arbitrary note events."))
         stderr_write ('\n')
 
@@ -1439,9 +1402,7 @@ as a substitution text.""") % (m.group (1), m.group (2)) )
 
     if re.search ("ly:(make-pitch|pitch-alteration)", str) \
            or re.search ("keySignature", str):
-        stderr_write ('\n')
         stderr_write (NOT_SMART % "pitches")
-        stderr_write ('\n')
         stderr_write (
             _ ("""The alteration field of Scheme pitches was multiplied by 2
 to support quarter tone accidentals.  You must update the following constructs manually:
@@ -1456,13 +1417,9 @@ to support quarter tone accidentals.  You must update the following constructs m
 @rule ((1, 9, 8), "dash-length -> dash-fraction")
 def conv (str):
     if re.search ("dash-length",str):
-        stderr_write ('\n')
         stderr_write (NOT_SMART % "dash-length")
-        stderr_write ('\n')
         stderr_write (FROM_TO % ("dash-length", "dash-fraction"))
-        stderr_write ('\n')
         stderr_write (UPDATE_MANUALLY)
-        stderr_write ('\n')
         raise FatalConversionError ()
     return str
 
@@ -1601,11 +1558,8 @@ def conv (str):
 def conv (str):
 
     if re.search (r'\\partcombine', str):
-        stderr_write ('\n')
         stderr_write (NOT_SMART % "\\partcombine")
-        stderr_write ('\n')
         stderr_write (UPDATE_MANUALLY)
-        stderr_write ('\n')
         raise FatalConversionError ()
 
     # this rule doesn't really work,
@@ -1774,11 +1728,8 @@ def conv (str):
     str = re.sub (r'ly:get-broken-into', 'ly:spanner-broken-into', str)
     str = re.sub (r'Melisma_engraver', 'Melisma_translator', str)
     if re.search ("ly:get-paper-variable", str):
-        stderr_write ('\n')
         stderr_write (NOT_SMART % "ly:paper-get-variable")
-        stderr_write ('\n')
-        stderr_write (_ ('use %s') % '(ly:paper-lookup (ly:grob-paper ))')
-        stderr_write ('\n')
+        stderr_write (_ ('Use %s\n') % '(ly:paper-lookup (ly:grob-paper ))')
         raise FatalConversionError ()
 
     str = re.sub (r'\\defaultAccidentals', "#(set-accidental-style 'default)", str)
@@ -1915,11 +1866,8 @@ def conv (str):
 @rule ((2, 3, 2), '\\FooContext -> \\Foo')
 def conv (str):
     if re.search ('textheight', str):
-        stderr_write ('\n')
         stderr_write (NOT_SMART % "textheight")
-        stderr_write ('\n')
         stderr_write (UPDATE_MANUALLY)
-        stderr_write ('\n')
         stderr_write (
 _ ("""Page layout has been changed, using paper size and margins.
 textheight is no longer used.
@@ -2143,9 +2091,7 @@ def conv (str):
         if encoding == 'latin1':
             return match.group (2)
 
-        stderr_write ('\n')
         stderr_write (NOT_SMART % ("\\encoding: %s" % encoding))
-        stderr_write ('\n')
         stderr_write (_ ("LilyPond source must be UTF-8"))
         stderr_write ('\n')
         if encoding == 'TeX':
@@ -2189,16 +2135,12 @@ def conv (str):
 @rule ((2, 5, 17), _ ('remove %s') % 'ly:stencil-set-extent!')
 def conv (str):
     if re.search ("ly:stencil-set-extent!", str):
-        stderr_write ('\n')
         stderr_write (NOT_SMART % "ly:stencil-set-extent!")
-        stderr_write ('\n')
-        stderr_write ('use (set! VAR (ly:make-stencil (ly:stencil-expr VAR) X-EXT Y-EXT))\n')
+        stderr_write (_ ('Use %s\n') % '(set! VAR (ly:make-stencil (ly:stencil-expr VAR) X-EXT Y-EXT))')
         raise FatalConversionError ()
     if re.search ("ly:stencil-align-to!", str):
-        stderr_write ('\n')
         stderr_write (NOT_SMART % "ly:stencil-align-to!")
-        stderr_write ('\n')
-        stderr_write ('use (set! VAR (ly:stencil-aligned-to VAR AXIS DIR))\n')
+        stderr_write (_ ('Use %s\n') % '(set! VAR (ly:stencil-aligned-to VAR AXIS DIR))')
         raise FatalConversionError ()
     return str
 
@@ -2213,15 +2155,12 @@ def conv (str):
 def conv (str):
     if re.search ("(override-|revert-)auto-beam-setting", str)\
        or re.search ("autoBeamSettings", str):
-        stderr_write ('\n')
         stderr_write (NOT_SMART % _ ("auto beam settings"))
-        stderr_write ('\n')
         stderr_write (_ ('''
 Auto beam settings must now specify each interesting moment in a measure
 explicitly; 1/4 is no longer multiplied to cover moments 1/2 and 3/4 too.
 '''))
         stderr_write (UPDATE_MANUALLY)
-        stderr_write ('\n')
         raise FatalConversionError ()
     return str
 
@@ -2331,6 +2270,7 @@ def conv (str):
         stderr_write (NOT_SMART % "space-function")
     if re.search ('verticalAlignmentChildCallback', str):
         stderr_write (_ ('verticalAlignmentChildCallback has been deprecated'))
+        stderr_write ('\n')
     return str
 
 
@@ -2648,7 +2588,7 @@ def conv (str):
                   str)
 
     if re.search ('edge-text', str):
-        stderr_write (NOT_SMART % _ ("edge-text settings for TextSpanner."))
+        stderr_write (NOT_SMART % _ ("edge-text settings for TextSpanner"))
         stderr_write (_ ("Use\n\n%s") %
                           "\t\\override TextSpanner #'bound-details #'right #'text = <right-text>\n"
                           "\t\\override TextSpanner #'bound-details #'left #'text = <left-text>\n")
@@ -2681,7 +2621,7 @@ def conv (str):
 
     str = re.sub (r"(\\once)?\s*\\override\s*([a-zA-Z]+\s*[.]\s*)?TextSpanner\s*#'edge-height\s*=\s*#'\(\s*([0-9.-]+)\s+[.]\s+([0-9.-]+)\s*\)", sub_edge_height, str)
     if re.search (r"#'forced-distance", str):
-        stderr_write (NOT_SMART % ("VerticalAlignment #'forced-distance.\n"))
+        stderr_write (NOT_SMART % "VerticalAlignment #'forced-distance")
         stderr_write (_ ("Use the `alignment-offsets' sub-property of\n"))
         stderr_write (_ ("NonMusicalPaperColumn #'line-break-system-details\n"))
         stderr_write (_ ("to set fixed distances between staves.\n"))
@@ -2702,7 +2642,7 @@ def conv (str):
                   r"scripts.caesura.curved", str)
 
     if re.search ('dash-fraction', str):
-        stderr_write (NOT_SMART % _ ("all settings related to dashed lines.\n"))
+        stderr_write (NOT_SMART % _ ("all settings related to dashed lines"))
         stderr_write (_ ("Use \\override ... #'style = #'line for solid lines and\n"))
         stderr_write (_ ("\t\\override ... #'style = #'dashed-line for dashed lines."))
     return str
@@ -2745,7 +2685,8 @@ fret diagram properties moved to fret-diagram-details."))
 def conv (str):
     ## warning 1/2: metronomeMarkFormatter uses text markup as second argument
     if re.search ('metronomeMarkFormatter', str):
-        stderr_write (NOT_SMART % _ ("metronomeMarkFormatter got an additional text argument.\n"))
+        stderr_write (NOT_SMART % "metronomeMarkFormatter")
+        stderr_write (_ ("metronomeMarkFormatter got an additional text argument.\n"))
         stderr_write (_ ("The function assigned to Score.metronomeMarkFunction now uses the signature\n%s") %
                           "\t(format-metronome-markup text dur count context)\n")
 
@@ -2764,9 +2705,8 @@ def conv (str):
                 'orientation']
     for prop in fret_props:
       if re.search (prop, str):
-          stderr_write (NOT_SMART %
-            prop + " in fret-diagram properties. Use fret-diagram-details.")
-          stderr_write ('\n')
+          stderr_write (NOT_SMART % (_ ("%s in fret-diagram properties") % prop))
+          stderr_write (_ ('Use %s\n') % "fret-diagram-details")
     return str
 
 @rule ((2, 11, 51), "\\octave -> \\octaveCheck, \\arpeggioUp -> \\arpeggioArrowUp,\n\
@@ -2809,9 +2749,10 @@ def conv (str):
 def conv (str):
     str = re.sub (r"#\(set-octavation (-*[0-9]+)\)", r"\\ottava #\1", str)
     if re.search ('put-adjacent', str):
-        stderr_write (NOT_SMART % _ ("\\put-adjacent argument order.\n"))
+        stderr_write (NOT_SMART % _ ("\\put-adjacent argument order"))
         stderr_write (_ ("Axis and direction now come before markups:\n"))
         stderr_write (_ ("\\put-adjacent axis dir markup markup."))
+        stderr_write ("\n")
     return str
 
 @rule ((2, 11, 57), "\\center-align -> \\center-column, \\hcenter -> \\center-align")
@@ -2841,15 +2782,13 @@ InnerStaffGroup -> StaffGroup, InnerChoirStaff -> ChoirStaff")
 def conv (str):
     str = re.sub (r'systemSeparatorMarkup', r'system-separator-markup', str)
     if re.search (r'\\InnerStaffGroup', str):
-        stderr_write ("\n")
-        stderr_write (NOT_SMART % _("re-definition of InnerStaffGroup.\n"))
-        stderr_write (FROM_TO % ("InnerStaffGroup", "StaffGroup.\n"))
+        stderr_write (NOT_SMART % _("re-definition of InnerStaffGroup"))
+        stderr_write (FROM_TO % ("InnerStaffGroup", "StaffGroup"))
         stderr_write (UPDATE_MANUALLY)
         raise FatalConversionError ()
     if re.search (r'\\InnerChoirStaff', str):
-        stderr_write ("\n")
-        stderr_write (NOT_SMART % _("re-definition of InnerChoirStaff.\n"))
-        stderr_write (FROM_TO % ("InnerChoirStaff", "ChoirStaff.\n"))
+        stderr_write (NOT_SMART % _("re-definition of InnerChoirStaff"))
+        stderr_write (FROM_TO % ("InnerChoirStaff", "ChoirStaff"))
         stderr_write (UPDATE_MANUALLY)
         raise FatalConversionError ()
     else:
@@ -2862,15 +2801,13 @@ def conv (str):
        _ ("bump version for release"))
 def conv(str):
     if re.search(r'\\addChordShape', str):
-        stderr_write ("\n")
-        stderr_write (NOT_SMART % _("stringTuning must be added to \
-addChordShape call.\n"))
+        stderr_write (NOT_SMART % "addChordShape")
+        stderr_write (_ ("stringTuning must be added to addChordShape call.\n"))
         stderr_write (UPDATE_MANUALLY)
         raise FatalConversionError ()
     if re.search (r'\\chord-shape', str):
-        stderr_write ("\n")
-        stderr_write (NOT_SMART % _("stringTuning must be added to \
-chord-shape call.\n"))
+        stderr_write (NOT_SMART % "chord-shape")
+        stderr_write (_ ("stringTuning must be added to chord-shape call.\n"))
         stderr_write (UPDATE_MANUALLY)
         raise FatalConversionError ()
     return str
@@ -2879,8 +2816,8 @@ chord-shape call.\n"))
     _ ("Remove oldaddlyrics"))
 def conv(str):
     if re.search(r'\\oldaddlyrics', str):
-        stderr_write ("\n")
-        stderr_write (NOT_SMART % _("oldaddlyrics is no longer supported. \n \
+        stderr_write (NOT_SMART % "oldaddlyrics")
+        stderr_write (("oldaddlyrics is no longer supported. \n \
         Use addlyrics or lyrsicsto instead.\n"))
         stderr_write (UPDATE_MANUALLY)
         raise FatalConversionError ()
@@ -2890,8 +2827,8 @@ def conv(str):
 MIDI 47: orchestral strings -> orchestral harp"))
 def conv(str):
     if re.search(r'\set Staff.keySignature', str):
-        stderr_write ("\n")
-        stderr_write (NOT_SMART % _("The alist for Staff.keySignature is no \
+        stderr_write (NOT_SMART % "Staff.keySignature")
+        stderr_write (("The alist for Staff.keySignature is no \
 longer in reversed order.\n"))
     str = str.replace('"orchestral strings"', '"orchestral harp"')
     return str
@@ -2902,14 +2839,14 @@ ly:hairpin::after-line-breaking -> ly:spanner::kill-zero-spanned-time\n\
 Dash parameters for slurs and ties are now in dash-definition"))
 def conv(str):
     if re.search(r'\\bar\s*"\."', str):
-        stderr_write ("\n")
-        stderr_write (NOT_SMART % _("\\bar \".\" now produces a thick barline.\n"))
+        stderr_write (NOT_SMART % "\\bar \".\"")
+        stderr_write (("\\bar \".\" now produces a thick barline.\n"))
         stderr_write (UPDATE_MANUALLY)
     str = re.sub (r'ly:hairpin::after-line-breaking', r'ly:spanner::kill-zero-spanned-time', str)
     if re.search("(Slur|Tie)\w+#\'dash-fraction", str) \
         or re.search("(Slur|Tie)\w+#\'dash-period", str):
-        stderr_write ("\n")
-        stderr_write (NOT_SMART % _("Dash parameters for slurs and ties are now in \'dash-details.\n"))
+        stderr_write (NOT_SMART % "dash-fraction, dash-period")
+        stderr_write (("Dash parameters for slurs and ties are now in \'dash-details.\n"))
         stderr_write (UPDATE_MANUALLY)
     return str
 
@@ -2927,26 +2864,27 @@ Explicit dynamics context definition from `Piano centered dynamics'\n\
 template replaced by new `Dynamics' context."))
 def conv(str):
     if re.search("override-auto-beam-setting", str):
-        stderr_write ("\n")
-        stderr_write (NOT_SMART % _("override-auto-beam-setting.\n\
+        stderr_write (NOT_SMART % "override-auto-beam-setting")
+        stderr_write (_ (" \
    Autobeam settings are now overriden with \\overrideBeamSettings.\n"))
         stderr_write (UPDATE_MANUALLY)
     if re.search("revert-auto-beam-setting", str):
-        stderr_write ("\n")
-        stderr_write (NOT_SMART % _("override-auto-beam-setting.\n\
+        stderr_write (NOT_SMART % "override-auto-beam-setting")
+        stderr_write (_ (" \
    Autobeam settings are now reverted with \\revertBeamSettings.\n"))
         stderr_write (UPDATE_MANUALLY)
     str = re.sub(r"\\set\s+beatGrouping", r"\\setBeatGrouping", str)
     if re.search(r"\w+\s*.\s*beatGrouping", str):
-        stderr_write (NOT_SMART % _("beatGrouping. \n\
+        stderr_write (NOT_SMART % "beatGrouping")
+        stderr_write (_ (" \
    beatGrouping with a specified context must now be accomplished with\n\
    \\overrideBeamSettings.\n"))
         stderr_write (UPDATE_MANUALLY)
     if re.search(r'alignment-offsets', str):
-        stderr_write("\n")
-        stderr_write(NOT_SMART % _("alignment-offsets has been changed to alignment-distances: \
+        stderr_write (NOT_SMART % "alignment-offsets")
+        stderr_write (_ ("alignment-offsets has been changed to alignment-distances: \
 you must now specify the distances between staves rather than the offset of staves.\n"))
-        stderr_write(UPDATE_MANUALLY)
+        stderr_write (UPDATE_MANUALLY)
     str = re.sub ('ly:(system-start-text::print|note-head::brew-ez-stencil|ambitus::print)',
                   '\\1', str)
     str = re.sub ('(\\bBeam\\s+#\')(?=thickness\\b)', '\\1beam-', str)
@@ -2985,9 +2923,9 @@ def conv(str):
                   str)
 
     if re.search(r"VerticalAxisGroup\s*#\s*'minimum-Y-extent", str):
-        stderr_write("\n")
-        stderr_write(NOT_SMART % _("minimum-Y-extent; vertical spacing no longer depends on the Y-extent of a VerticalAxisGroup.\n"))
-        stderr_write(UPDATE_MANUALLY)
+        stderr_write (NOT_SMART % "minimum-Y-extent")
+        stderr_write (_ ("Vertical spacing no longer depends on the Y-extent of a VerticalAxisGroup.\n"))
+        stderr_write (UPDATE_MANUALLY)
 
     return str
 
@@ -3037,25 +2975,25 @@ def conv(str):
     str = re.sub (r'"accordion\.acc([a-zA-Z]+)"',
                   sub_acc, str)
     if re.search(r'overrideBeamSettings', str):
-        stderr_write("\n")
-        stderr_write(NOT_SMART % _("\\overrideBeamSettings.  Use \\set beamExceptions or \\overrideTimeSignatureSettings.\n"))
-        stderr_write(UPDATE_MANUALLY)
+        stderr_write (NOT_SMART % "\\overrideBeamSettings")
+        stderr_write (_ ("Use \\set beamExceptions or \\overrideTimeSignatureSettings.\n"))
+        stderr_write (UPDATE_MANUALLY)
     if re.search(r'revertBeamSettings', str):
-        stderr_write("\n")
-        stderr_write(NOT_SMART % _("\\revertBeamSettings. Use \\set beamExceptions or \\revertTimeSignatureSettings.\n"))
-        stderr_write(UPDATE_MANUALLY)
+        stderr_write (NOT_SMART % "\\revertBeamSettings")
+        stderr_write (_ ("Use \\set beamExceptions or \\revertTimeSignatureSettings.\n"))
+        stderr_write (UPDATE_MANUALLY)
     if re.search(r'beamSettings', str):
-        stderr_write("\n")
-        stderr_write(NOT_SMART % _("beamSettings. Use baseMoment, beatStructure, and beamExceptions.\n"))
-        stderr_write(UPDATE_MANUALLY)
+        stderr_write (NOT_SMART % "beamSettings")
+        stderr_write (_ ("Use baseMoment, beatStructure, and beamExceptions.\n"))
+        stderr_write (UPDATE_MANUALLY)
     if re.search(r'beatLength', str):
-        stderr_write("\n")
-        stderr_write(NOT_SMART % _("beatLength. Use baseMoment and beatStructure.\n"))
-        stderr_write(UPDATE_MANUALLY)
+        stderr_write (NOT_SMART % "beatLength")
+        stderr_write (_ ("Use baseMoment and beatStructure.\n"))
+        stderr_write (UPDATE_MANUALLY)
     if re.search(r'setBeatGrouping', str):
-        stderr_write("\n")
-        stderr_write(NOT_SMART % _("setbeatGrouping. Use baseMoment and beatStructure.\n"))
-        stderr_write(UPDATE_MANUALLY)
+        stderr_write (NOT_SMART % "setbeatGrouping")
+        stderr_write (_ ("Use baseMoment and beatStructure.\n"))
+        stderr_write (UPDATE_MANUALLY)
     return str
 
 @rule ((2, 13, 31),
@@ -3063,9 +3001,9 @@ def conv(str):
 Deprecate negative dash-period for hidden lines: use #'style = #'none instead."))
 def conv(str):
     if re.search(r'woodwind-diagram', str):
-        stderr_write("\n")
-        stderr_write(NOT_SMART % _("woodwind-diagrams.  Move size, thickness, and graphic to properties.  Argument should be just the key list.\n"))
-        stderr_write(UPDATE_MANUALLY)
+        stderr_write (NOT_SMART % "woodwind-diagrams")
+        stderr_write (_ ("Move size, thickness, and graphic to properties.  Argument should be just the key list.\n"))
+        stderr_write (UPDATE_MANUALLY)
     str = re.sub (r"dash-period\s+=\s*#\s*-[0-9.]+",
                   r"style = #'none",
                   str);
@@ -3109,15 +3047,13 @@ def conv(str):
     _ ("Remove \\paper variables head-separation and foot-separation."))
 def conv(str):
     if re.search (r'head-separation', str):
-        stderr_write("\n")
-        stderr_write(NOT_SMART % ("head-separation.\n"))
-        stderr_write(_ ("Adjust settings for top-system-spacing instead.\n"))
+        stderr_write (NOT_SMART % "head-separation")
+        stderr_write (_ ("Adjust settings for top-system-spacing instead.\n"))
         stderr_write (UPDATE_MANUALLY)
     if re.search (r'foot-separation', str):
-        stderr_write("\n")
-        stderr_write(NOT_SMART % ("foot-separation.\n"))
-        stderr_write(_ ("Adjust settings for last-bottom-spacing instead.\n"))
-        stderr_write(UPDATE_MANUALLY);
+        stderr_write (NOT_SMART % "foot-separation")
+        stderr_write (_ ("Adjust settings for last-bottom-spacing instead.\n"))
+        stderr_write (UPDATE_MANUALLY);
 
     return str
 
@@ -3128,8 +3064,7 @@ def conv(str):
     str = re.sub (r'\(space\s+\.\s+([0-9]*\.?[0-9]*)\)', r'(basic-distance . \1)', str)
     str = re.sub (r"#'space\s+=\s+#?([0-9]*\.?[0-9]*)", r"#'basic-distance = #\1", str)
     if re.search (r'HarmonicParenthesesItem', str):
-        stderr_write ("\n")
-        stderr_write (NOT_SMART % ("HarmonicParenthesesItem.\n"))
+        stderr_write (NOT_SMART % "HarmonicParenthesesItem")
         stderr_write (_ ("HarmonicParenthesesItem has been eliminated.\n"))
         stderr_write (_ ("Harmonic parentheses are part of the TabNoteHead grob.\n"))
         stderr_write (UPDATE_MANUALLY);
@@ -3177,13 +3112,17 @@ def conv(str):
     str = re.sub (r"ukulele-(tenor|baritone)-tuning", r"\1-ukulele-tuning", str)
 
     if re.search (r"[^-]page-top-space", str):
-        stderr_write (NOT_SMART % "page-top-space.  " + UPDATE_MANUALLY)
+        stderr_write (NOT_SMART % "page-top-space")
+        stderr_write (UPDATE_MANUALLY)
     if re.search (r"[^-]between-system-(space|padding)", str):
-        stderr_write (NOT_SMART % "between-system-space, -padding.  " + UPDATE_MANUALLY)
+        stderr_write (NOT_SMART % "between-system-space, -padding")
+        stderr_write (UPDATE_MANUALLY)
     if re.search (r"[^-](before|between|after)-title-space", str):
-        stderr_write (NOT_SMART % "-title-space.  " + UPDATE_MANUALLY)
+        stderr_write (NOT_SMART % "before-, between-, after-title-space")
+        stderr_write (UPDATE_MANUALLY)
     if re.search (r"\\name\s", str):
-        stderr_write("\n" + _("Vertical spacing changes might affect user-defined contexts.  ") + UPDATE_MANUALLY)
+        stderr_write ("\n" + _("Vertical spacing changes might affect user-defined contexts.") + "\n")
+        stderr_write (UPDATE_MANUALLY)
 
     return str
 
@@ -3203,8 +3142,8 @@ def conv(str):
     _ ("Woodwind diagrams: Changes to the clarinet diagram."))
 def conv(str):
     if re.search (r'\\woodwind-diagram\s*#[^#]*clarinet\s', str):
-        stderr_write ("\n")
-        stderr_write (NOT_SMART % _("woodwind-diagrams.  Clarinet fingering changed to reflect actual anatomy of instrument.\n"))
+        stderr_write (NOT_SMART % "woodwind-diagrams")
+        stderr_write (_ ("Clarinet fingering changed to reflect actual anatomy of instrument.\n"))
         stderr_write (UPDATE_MANUALLY)
     return str
 
@@ -3217,8 +3156,8 @@ def conv (str):
     _ ("Handling of non-automatic footnotes."))
 def conv(str):
     if re.search (r'\\footnote', str):
-        stderr_write ("\n")
-        stderr_write (NOT_SMART % _("If you are using non-automatic footnotes, make sure to set footnote-auto-numbering = ##f in the paper block.\n"))
+        stderr_write (NOT_SMART % "\\footnote")
+        stderr_write (("If you are using non-automatic footnotes, make sure to set footnote-auto-numbering = ##f in the paper block.\n"))
         stderr_write (UPDATE_MANUALLY)
     return str
 
@@ -3226,8 +3165,7 @@ def conv(str):
        _ ("Change in internal property for MultiMeasureRest"))
 def conv (str):
     if re.search (r'use-breve-rest',str):
-        stderr_write ("\n")
-        stderr_write (NOT_SMART % "use-breve-rest.\n")
+        stderr_write (NOT_SMART % "use-breve-rest")
         stderr_write (_ ("This internal property has been replaced by round-up-to-longer-rest, round-up-exceptions and usable-duration-logs.\n"))
         stderr_write (UPDATE_MANUALLY)
     return str
@@ -3237,7 +3175,7 @@ def conv (str):
 def conv (str):
     str = re.sub (r"Stem\s+#'flag-style", r"Flag #'style", str)
     str = re.sub (r"Stem\s+#'stroke-style", r"Flag #'stroke-style", str)
-    str = re.sub (r"Stem\s+#'flag", r"Flag #'print", str)
+    str = re.sub (r"Stem\s+#'flag", r"Flag #'stencil", str)
     str = re.sub (r"(\s+(?:\\once\s*)?)\\override\s+Stem\s+#'transparent\s*=\s*##t", r"\g<1>\\override Stem #'transparent = ##t\g<1>\\override Flag #'transparent = ##t", str)
     str = re.sub (r"(\s+(?:\\once\s*)?)\\revert\s*Stem\s+#'transparent", r"\g<1>\\revert Stem #'transparent\g<1>\\revert Flag #'transparent", str)
     str = re.sub (r"(\s+(?:\\once\s*)?)\\override\s+Stem\s+#'stencil\s*=\s*##f", r"\g<1>\\override Stem #'stencil = ##f\g<1>\\override Flag #'stencil = ##f", str)
@@ -3268,8 +3206,8 @@ def conv (str):
     str = re.sub (r"\\markuplines", r"\\markuplist", str)
     str = re.sub (r"@funindex markuplines", r"@funindex markuplist", str)
     if re.search (r'consistent-broken-slope', str):
-        stderr_write ("\n")
-        stderr_write (NOT_SMART % _("consistent-broken-slope, which is now handled through the positions callback.\n"))
+        stderr_write (NOT_SMART % "consistent-broken-slope")
+        stderr_write (_ ("consistent-broken-slope is now handled through the positions callback.\n"))
         stderr_write (_ ("input/regression/beam-broken-classic.ly shows how broken beams are now handled.\n"))
         stderr_write (UPDATE_MANUALLY)
     return str
@@ -3283,7 +3221,7 @@ def paren_matcher (n):
     return
 
 def undollar_scm (m):
-    return re.sub (r"\$", "", m.group (0))
+    return re.sub (r"\$(.?)", r"\1", m.group (0))
 
 def undollar_embedded (m):
     str = re.sub (r"#\$", "#", m.group (1))
@@ -3329,9 +3267,7 @@ def conv (str):
     str = re.sub (r"#\(markup\*(?=\s)", r"$(markup", str)
     str = re.sub ("#\("+paren_matcher (25)+"\)", export_puller, str)
     if re.search (r"\(ly:export\s+", str):
-        stderr_write ('\n')
         stderr_write (NOT_SMART % "ly:export")
-        stderr_write ('\n')
     return str
 
 @rule ((2, 15, 19), r"$(set-time-signature ...) -> \time")
@@ -3341,9 +3277,445 @@ def conv (str):
     str = re.sub (r"\$\(set-time-signature\s+([0-9]+)\s+([0-9]+)\s+(" +
                   paren_matcher (5) + r")\)", r"\\time #\3 \1/\2", str)
     if re.search (r"\(set-time-signature\s+", str):
-        stderr_write ('\n')
         stderr_write (NOT_SMART % "set-time-signature")
-        stderr_write ('\n')
+    return str
+
+@rule ((2, 15, 20), r"$(set-accidental-style ...) -> \accidentalStyle")
+def conv (str):
+    str = re.sub (r"\$\(set-accidental-style\s+'([-a-z]+)\)",
+                  r'\\accidentalStyle "\1"', str)
+    str = re.sub (r"\$\(set-accidental-style\s+'([-a-z]+)\s+'([-A-Za-z]+)\s*\)",
+                  r'''\\accidentalStyle #'\2 "\1"''', str)
+    str = re.sub (r"(@funindex\s+)set-accidental-style",
+                  r"\1\\accidentalStyle", str)
+    return str
+
+def brace_matcher (n):
+    # poor man's matched brace scanning, gives up
+    # after n+1 levels.  Matches any string with balanced
+    # braces inside; add the outer braces yourself if needed.
+    # Nongreedy.
+    return r"[^{}]*?(?:{"*n+r"[^{}]*?"+r"}[^{}]*?)*?"*n
+
+matchstring = r'"(?:[^"\\]|\\.)*"'
+matcharg = (r"\s+(?:[$#]['`]?\s*(?:[a-zA-Z]\S*|" + matchstring + r"|\("
+            + paren_matcher(20) + r"\))|" + matchstring + r"|\\[a-z_A-Z]+)")
+matchmarkup = (r'(?:\\markup\s*(?:{' + brace_matcher (20) +r'}|' +
+               matchstring + r'|(?:\\[a-z_A-Z][a-z_A-Z-]*(?:' + matcharg +
+               r')*?\s*)*(?:' + matchstring + "|{" + brace_matcher (20) +
+               "}))|" + matchstring + ")")
+
+@rule((2, 15, 25), r"\(auto)?Footnote(Grob)? -> \footnote")
+def conv (str):
+    # The following replacement includes the final markup argument in
+    # the match in order to better avoid touching the equally named
+    # markup function.  The other functions have unique names, so
+    # there is no point in including their last, possibly complex
+    # argument in the match.
+    str = re.sub (r"\\footnote(" + matcharg + (r")(\s*" + matchmarkup)*2 + ")",
+                  r"\\footnote\2\1\3", str)
+    str = re.sub (r"\\footnoteGrob"+("(" + matcharg + ")")*2 + r"(\s*" + matchmarkup + ")",
+                  r"\\footnote\3\2\1", str)
+    str = re.sub (r"\\autoFootnoteGrob" + ("(" + matcharg + ")")*2,
+                  r"\\footnote\2\1", str)
+    str = re.sub (r"\\autoFootnote",
+                  r"\\footnote", str)
+    return str
+
+@rule((2, 15, 32), r"tempoWholesPerMinute -> \tempo")
+def conv (str):
+    def sub_tempo (m):
+        num = int (m.group (1))
+        den = int (m.group (2))
+
+        if (den & (den - 1)) != 0 :
+            return m.group (0)
+
+        # Don't try dotted forms if they result in less than 30 bpm.
+        # It is not actually relevant to get this right since this
+        # only occurs in non-printing situations
+        if den >= 16 and (num % 7) == 0 and num >= 210 :
+            return r"\tempo %d.. = %d" % (den/4, num/7)
+
+        if den >= 8 and (num % 3) == 0 and num >= 90 :
+            return r"\tempo %d. = %d" % (den/2, num/3)
+
+        return r"\tempo %d = %d" % (den, num)
+
+    str = re.sub (r"\\context\s*@?\{\s*\\Score\s+tempoWholesPerMinute\s*=\s*" +
+                  r"#\(ly:make-moment\s+([0-9]+)\s+([0-9]+)\)\s*@?\}",
+                  sub_tempo, str)
+    return str
+
+@rule((2, 15, 39), r"\footnote ... -> \footnote ... \default")
+def conv (str):
+    def not_first (s):
+        def match_fun (m):
+            if m.group (1):
+                return m.group (0)
+            return m.expand (s)
+        return match_fun
+    str = re.sub ("(" + matchmarkup + ")|"
+                  + r"(\\footnote(?:\s*"
+                  + matchmarkup + ")?" + matcharg + "(?:" + matcharg
+                  + ")?\s+" + matchmarkup + ")",
+                  not_first (r"\2 \\default"), str)
+    return str
+
+@rule ((2, 15, 40), r"Remove beamWholeMeasure")
+def conv (str):
+    if re.search (r"\bbeamWholeMeasure\b", str):
+        stderr_write (NOT_SMART % "beamWholeMeasure")
+        stderr_write (_ ("beamExceptions controls whole-measure beaming.") + "\n")
+    return str
+
+@rule ((2, 15, 42), r"\set stringTuning -> \set Staff.stringTuning")
+def conv (str):
+    str = re.sub (r"(\\set\s+)stringTuning", r"\1Staff.stringTuning", str)
+    return str
+
+wordsyntax = r"[a-zA-Z\200-\377](?:[-_]?[a-zA-Z\200-\377])*"
+
+@rule ((2, 15, 43), r'"custom-tuning" = -> custom-tuning =')
+def conv (str):
+    str = re.sub ('\n"(' + wordsyntax + r')"(\s*=\s*\\stringTuning)', "\n\\1\\2", str)
+    return str
+
+@rule ((2, 16, 0),
+       _ ("bump version for release"))
+def conv (str):
+    return str
+
+@rule ((2, 17, 0), r"blank-*-force -> blank-*-penalty")
+def conv (str):
+    str = re.sub ('blank-page-force', 'blank-page-penalty', str)
+    str = re.sub ('blank-last-page-force', 'blank-last-page-penalty', str)
+    str = re.sub ('blank-after-score-page-force', 'blank-after-score-page-penalty', str)
+    return str
+
+
+@rule ((2, 17, 4), r"\shape Grob #offsets -> \shape #offsets Grob")
+def conv (str):
+    str = re.sub (r"\\shape(\s+(?:[a-zA-Z]+|" + matchstring + "))(" +
+                  matcharg + ")", r"\\shape\2\1", str)
+    return str
+
+barstring=r"(\\bar|whichBar|defaultBarType|segnoType|doubleRepeatType|startRepeatType|endRepeatType|doubleRepeatSegnoType|startRepeatSegnoType|endRepeatSegnoType)(\s*[=]?\s*[#]?)"
+
+@rule ((2, 17, 5), r"New bar line interface")
+def conv(str):
+    str = re.sub (barstring + r'"\|:"', '\\1\\2".|:"', str)
+    str = re.sub (barstring + r'":\|"', '\\1\\2":|."', str)
+    str = re.sub (barstring + r'"\|\|:"', '\\1\\2".|:-||"', str)
+    str = re.sub (barstring + r'":\|:"', '\\1\\2":..:"', str)
+    str = re.sub (barstring + r'"\.\|\."', '\\1\\2".."', str)
+    str = re.sub (barstring + r'"\|S"', '\\1\\2"S-|"', str)
+    str = re.sub (barstring + r'"S\|"', '\\1\\2"S-S"', str)
+    str = re.sub (barstring + r'":\|S"', '\\1\\2":|.S"', str)
+    str = re.sub (barstring + r'":\|S\."', '\\1\\2":|.S-S"', str)
+    str = re.sub (barstring + r'"S\|:"', '\\1\\2"S.|:-S"', str)
+    str = re.sub (barstring + r'"\.S\|:"', '\\1\\2"S.|:"', str)
+    str = re.sub (barstring + r'":\|S\|:"', '\\1\\2":|.S.|:"', str)
+    str = re.sub (barstring + r'":\|S\.\|:"', '\\1\\2":|.S.|:-S"', str)
+    str = re.sub (barstring + r'":"', '\\1\\2";"', str)
+    str = re.sub (barstring + r'"\|s"', '\\1\\2"|-s"', str)
+    str = re.sub (barstring + r'"dashed"', '\\1\\2"!"', str)
+    str = re.sub (barstring + r'"kievan"', '\\1\\2"k"', str)
+    str = re.sub (barstring + r'"empty"', '\\1\\2"-"', str)
+    return str
+
+symbol_list = (r"#'(?:" + wordsyntax + r"|\(\s*(?:" + wordsyntax + r"\s+)*"
+               + wordsyntax + r"\s*\))")
+
+grob_path = r"(?:" + symbol_list + r"\s+)*" + symbol_list
+
+grob_spec = wordsyntax + r"(?:\s*\.\s*" + wordsyntax + r")?"
+
+def path_replace (m):
+    return m.group (1) + string.join (re.findall (wordsyntax, m.group (2)), ".")
+
+@rule ((2, 17, 6), r"""\accidentalStyle #'Context "style" -> \accidentalStyle Context.style
+\alterBroken "Context.grob" -> \alterBroken Context.grob
+\overrideProperty "Context.grob" -> \overrideProperty Context.grob
+\tweak Grob #'symbol -> \tweak Grob.symbol""")
+def conv (str):
+    def patrep (m):
+        def fn_path_replace (m):
+            x = string.join (re.findall (wordsyntax, m.group (2)), ".")
+            if x in ["TimeSignature", "KeySignature", "BarLine",
+                     "Clef", "StaffSymbol", "OttavaBracket",
+                     "LedgerLineSpanner"]:
+                x = "Staff." + x
+            return m.group (1) + x
+        if m.group (1):
+            return m.group (0)
+        x = m.group (2) + m.group (4)
+        
+        if m.group (3):
+            x = x + re.sub (r"(\s*)(" + symbol_list + ")", fn_path_replace,
+                            m.group (3))
+
+            if not m.group (5):
+                x = r"\single" + x
+        return x
+
+    str = re.sub (r'''(\\accidentalStyle\s+)#?"([-A-Za-z]+)"''',
+                  r"\1\2", str)
+    str = re.sub (r'''(\\accidentalStyle\s+)#'([A-Za-z]+)\s+#?"?([-A-Za-z]+)"?''',
+                  r"\1\2.\3", str)
+    str = re.sub (r'''(\\(?:alterBroken|overrideProperty)\s+)#?"([A-Za-z]+)\s*\.\s*([A-Za-z]+)"''',
+                  r"\1\2.\3", str)
+    str = re.sub (r'''(\\tweak\s+)#?"?([A-Za-z]+)"?\s+?#'([-A-Za-z]+)''',
+                  r"\1\2.\3", str)
+    str = re.sub (r'''(\\tweak\s+)#'([-A-Za-z]+)''',
+                  r"\1\2", str)
+    str = re.sub ("(" + matchmarkup + ")|"
+                  + r"(\\footnote(?:\s*"
+                  + matchmarkup + ")?" + matcharg + ")(" + matcharg
+                  + r")?(\s+" + matchmarkup + r")(\s+\\default)?",
+                  patrep, str)
+    str = re.sub (r'''(\\alterBroken)(\s+[A-Za-z.]+)(''' + matcharg
+                  + matcharg + ")", r"\1\3\2", str)
+    str = re.sub (r"(\\overrideProperty\s+)(" + grob_spec + r"\s+" + grob_path + ")",
+                  path_replace, str)
+    str = re.sub (r"(\\(?:override|revert)\s+)(" + grob_spec + r"\s+" + grob_path + ")",
+                  path_replace, str)
+    return str
+
+@rule ((2, 17, 11), r"""\times -> \tuplet, \set tupletSpannerDuration -> \tupletSpan
+(ly:make-moment 1 4) -> (ly:make-moment 1/4)
+(ly:make-duration 0 0 1 2) -> (ly:make-duration 0 0 1/2)""")
+def conv(str):
+    def sub_dur (m):
+        num = int (m.group (1))
+        den = int (m.group (2))
+
+# if den is no power of 2, don't even try to use an unscaled duration
+        if (den & (den - 1)) != 0 :
+            return (r"\tupletSpan 1*%d/%d" % (num, den))
+
+        if den >= 4 and num == 7 :
+            return (r"\tupletSpan %d.." % (den/4))
+
+        if den >= 2 and num == 3 :
+            return (r"\tupletSpan %d." % (den/2))
+
+        if num == 1 :
+            return (r"\tupletSpan %d" % den)
+
+        return (r"\tupletSpan 1*%d/%d" % (num, den))
+
+    str = re.sub (r"\\set\s+tupletSpannerDuration\s*=\s*" +
+                  r"#\(ly:make-moment\s+([0-9]+)\s+([0-9]+)\s*\)",
+                  sub_dur, str)
+    str = re.sub (r"\\unset tupletSpannerDuration",
+                  r"\\tupletSpan \\default", str)
+    str = re.sub (r"\\times(\s*)([0-9]+)/([0-9]+)",
+                  r"\\tuplet\1\3/\2", str)
+
+    str = re.sub (r"(\(ly:make-moment\s+-?[0-9]+)\s+([1-9][0-9]*\))",
+                  r"\1/\2", str)
+    str = re.sub (r"(\(ly:make-moment\s+-?[0-9]+)\s+([0-9]+\s+-?[0-9]+)\s([0-9]+\))",
+                  r"\1/\2/\3", str)
+    str = re.sub (r"(\(ly:make-duration\s+-?[0-9]+\s+[0-9]+\s+[0-9]+)\s+([0-9]+\))",
+                  r"\1/\2", str)
+    return str
+
+@rule((2, 17, 14), r"\accepts ... -> \accepts ... \defaultchild ...")
+def conv(str):
+    def matchaccepts(m):
+        # First weed out definitions starting from an existing
+        # definition: we assume that the inherited \defaultchild is
+        # good enough for our purposes.  Heuristic: starts with a
+        # backslash and an uppercase letter.
+        if re.match (r"\s*\\[A-Z]", m.group (1)):
+            return m.group (0)
+        # existing defaultchild obviously trumps all
+        if re.search (r"\\defaultchild[^-_a-zA-Z]", m.group (1)):
+            return m.group (0)
+        # take the first \\accepts if any and replicate it
+        return re.sub ("(\r?\n[ \t]*|[ \t]+)"
+                       + r"""\\accepts(\s+(?:#?".*?"|[-_a-zA-Z]+))""",
+                       r"\g<0>\1\\defaultchild\2",
+                       m.group (0), 1)
+
+    str = re.sub (r"\\context\s*@?\{(" + brace_matcher (20) + ")\}",
+                  matchaccepts, str)
+    return str
+
+@rule((2, 17, 15), r"""#(ly:set-option 'old-relative)
+\relative -> \relative c'""")
+def conv(str):
+    if re.search (r"[#$]\(ly:set-option\s+'old-relative", str):
+        stderr_write (NOT_SMART % "#(ly:set-option 'old-relative)")
+        stderr_write (UPDATE_MANUALLY)
+        raise FatalConversionError ();
+    # If the file contains a language switch to a language where the
+    # name of c is not "c", we can't reliably know which parts of the
+    # file will need "c" and which need "do".
+    m = re.search (r'\\language\s(?!\s*#?"(?:nederlands|deutsch|english|norsk|suomi|svenska))"', str)
+    if m:
+        # Heuristic: if there is a non-commented { before the language
+        # selection, we can't be sure.
+        # Also if there is any selection of a non-do language.
+        if (re.search ("^[^%\n]*\\{", m.string[:m.start()], re.M)
+            or re.search ('\\language\s(?!\s*#?"(?:catalan|espanol|español|italiano|français|portugues|vlaams))"', str)):
+            do = "$(ly:make-pitch 0 0)"
+        else:
+            do = "do'"
+    else:
+        do = "c'"
+    str = re.sub (r"(\\relative)(\s+(\{|[\\<]))",
+                  r"\1 " + do + r"\2", str)
+    return str
+
+@rule ((2, 17, 18),
+    "Rename OctavateEight to ClefModifier, rename related properties.")
+def conv(str):
+    str = re.sub ('OctavateEight',               'ClefModifier',                   str)
+    str = re.sub ('octavate-eight-interface',    'clef-modifier-interface',        str)
+    str = re.sub ('clefOctavation',              'clefTransposition',              str)
+    str = re.sub ('clefOctavationFormatter',     'clefTranspositionFormatter',     str)
+    str = re.sub ('clefOctavationStyle',         'clefTranspositionStyle',         str)
+    str = re.sub ('cueClefOctavation',           'cueClefTransposition',           str)
+    str = re.sub ('cueClefOctavationFormatter',  'cueClefTranspositionFormatter',  str)
+    str = re.sub ('cueClefOctavationStyle',      'cueClefTranspositionStyle',      str)
+    return str
+
+@rule((2, 17, 19), r"\column { \vspace #2 } -> \column { \combine \null \vspace #2 }")
+def conv(str):
+    def vspace_replace(m):
+
+# vspace now always adds space and does not, for example, change the
+# impact of either baselineskip or descenders on the line above.
+#
+# We can't simulate the old behavior in a simpler manner.  A command
+# of its own is not really warranted since this behavior combines
+# badly enough with other spacing considerations (like baselineskip
+# and descenders) as to make it not all that useful.  So this
+# conversion rule is here more for compatibility's sake rather than
+# preserving desirable behavior.
+
+        str = re.sub (r"(\\\\?)vspace(\s)", r"\1combine \1null \1vspace\2", m.group(0))
+        return str
+
+    str = re.sub (r"\\(?:left-|right-|center-|)column\s*\{" + brace_matcher (20) + r"\}",
+                  vspace_replace, str)
+    return str
+
+@rule((2, 17, 20), _(r"Flag.transparent and Flag.color inherit from Stem"))
+def conv(str):
+    str = re.sub (r"(((?:\\once\s*)?)\\override\s+((?:\w+\.)?)Stem\.(transparent|color)\s*=\s*(#\S+))\s+\2\\override\s+\3Flag\.\4\s*=\s*\5",
+                  r"\1", str)
+    str = re.sub (r"(((?:\\once\s*)?)\\revert\s+((?:\w+\.)?)Stem\.(transparent|color))\s+\2\\revert\s+\3Flag\.\4",
+                  r"\1", str)
+    str = re.sub (r"(\\tweak\s+((?:\w+\.)?)Stem\.(transparent|color)\s+(#\S+))\s+\\tweak\s+\2Flag\.\3\s+\4",
+                  r"\1", str)
+    return str
+
+@rule((2, 17, 25), r'''\tempo 4. = 50~60 -> \tempo 4. = 50-60
+-| -> -!
+pipeSymbol, escapedParenthesisOpenSymbol ... -> "|", "\\(" ...''')
+def conv(str):
+#  This goes for \tempo commands ending with a range, like
+#  = 50 ~ 60
+#  and uses - instead.  We don't explicitly look for \tempo since the
+#  complete syntax has a large number of variants, and this is quite
+#  unlikely to occur in other contexts
+    str = re.sub (r"(=\s*[0-9]+\s*)~(\s*[0-9]+\s)", r"\1-\2", str)
+# Match strings, and articulation shorthands that end in -^_
+# so that we leave alone -| in quoted strings and c4--|
+    def subnonstring(m):
+        if m.group (1):
+            return m.group (1)+"!"
+        return m.group (0)
+    str = re.sub (r"([-^_])\||" + matchstring + r"|[-^_][-^_]", subnonstring, str)
+    str = re.sub (r"\bdashBar\b", "dashBang", str)
+    orig = [ "pipeSymbol",
+             "bracketOpenSymbol",
+             "bracketCloseSymbol",
+             "tildeSymbol",
+             "parenthesisOpenSymbol",
+             "parenthesisCloseSymbol",
+             "escapedExclamationSymbol",
+             "escapedParenthesisOpenSymbol",
+             "escapedParenthesisCloseSymbol",
+             "escapedBiggerSymbol",
+             "escapedSmallerSymbol" ]
+    repl = [ r'"|"',
+             r'"["',
+             r'"]"',
+             r'"~"',
+             r'"("',
+             r'")"',
+             r'"\\!"',
+             r'"\\("',
+             r'"\\)"',
+             r'"\\>"',
+             r'"\\<"']
+    words = r"\b(?:(" + ")|(".join (orig) + r"))\b"
+    def wordreplace(m):
+        def instring(m):
+            return re.sub (r'["\\]',r'\\\g<0>',repl[m.lastindex-1])
+        if m.lastindex:
+            return repl[m.lastindex-1]
+        return '"' + re.sub (words, instring, m.group(0)[1:-1]) + '"'
+    str = re.sub (words + "|" + matchstring, wordreplace, str)
+    return str
+
+@rule((2, 17, 27), r'''\stringTuning \notemode -> \stringTuning''')
+def conv(str):
+    str = re.sub (r"\\stringTuning\s*\\notemode(\s*)@?\{\s*(.*?)\s*@?}",
+                  r"\\stringTuning\1\2", str)
+    if re.search (r'[^-\w]staff-padding[^-\w]', str):
+        stderr_write (NOT_SMART % "staff-padding")
+        stderr_write (_ ("Staff-padding now controls the distance to the baseline, not the nearest point."))
+    return str
+
+@rule((2, 17, 29), r'''Dynamic_engraver -> New_dynamic_engraver+Dynamic_align_engraver
+New_dynamic_engraver -> Dynamic_engraver''')
+def conv(str):
+    str = re.sub ("(\r?\n?[ \t]*\\\\(?:consists|remove)\\s*)(\"?)Dynamic_engraver\\2",
+                  r"\1\2New_dynamic_engraver\2\1\2Dynamic_align_engraver\2",
+                  str)
+# Should we warn about any remaining Dynamic_engraver?  Possibly it
+# will do the job just fine.
+    str = re.sub ("New_dynamic_engraver", "Dynamic_engraver", str)
+    return str
+
+@rule ((2, 17, 97), r'''(make-relative (a b) b ...) -> make-relative (a b) #{ a b #}...''')
+def conv (str):
+    str = re.sub (r"(\(make-relative\s+\(\s*(([A-Za-z][-_A-Za-z0-9]*)" +
+                  r"(?:\s+[A-Za-z][-_A-Za-z0-9]*)*)\s*\)\s*)\3(?=\s)",
+                  r"\1(make-event-chord (list \2))", str)
+    str = re.sub (r"(\(make-relative\s+\(\s*([A-Za-z][-_A-Za-z0-9]*" +
+                  r"(?:\s+([A-Za-z][-_A-Za-z0-9]*))+)\s*\)\s*)\3(?=\s)",
+                  r"\1(make-sequential-music (list \2))", str)
+    return str
+
+@rule ((2, 18, 0),
+       _ ("bump version for release"))
+def conv (str):
+    return str
+
+@rule ((2, 19, 2), r"\lyricsto \new/\context/... -> \new/\context/... \lyricsto")
+def conv (str):
+    word=r'(?:#?"[^"]*"|\b' + wordsyntax + r'\b)'
+    str = re.sub (r"(\\lyricsto\s*" + word + r"\s*)(\\(?:new|context)\s*" + word
+                  + r"(?:\s*=\s*" + word + r")?\s*)",
+                  r"\2\1", str)
+    str = re.sub (r"(\\lyricsto\s*" + word + r"\s*)\\lyricmode\b\s*",
+                  r"\1", str)
+    str = re.sub (r"(\\lyricsto\s*" + word + r"\s*)\\lyrics\b\s*",
+                  r"\\new Lyrics \1", str)
+    str = re.sub (r'\\lyricmode\s*(\\lyricsto\b)', r"\1", str)
+    return str
+
+@rule ((2, 19, 7), "keySignature -> keyAlterations")
+def conv(str):
+    str = re.sub (r'\bkeySignature\b', 'keyAlterations', str)
+    str = re.sub (r'\blastKeySignature\b', 'lastKeyAlterations', str)
+    str = re.sub (r'\blocalKeySignature\b', 'localAlterations', str)
     return str
 
 # Guidelines to write rules (please keep this at the end of this file)