+ 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, 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)