From a512132fed73a94068b91fb0bab473319e477b6e Mon Sep 17 00:00:00 2001
From: David Kastrup <dak@gnu.org>
Date: Wed, 9 Nov 2011 11:37:39 +0100
Subject: [PATCH] Fold set-time-signature into \time

---
 ...onducting-signs,-measure-grouping-signs.ly | 15 ++++-----
 ly/music-functions-init.ly                    | 11 +++++--
 python/convertrules.py                        | 33 +++++++++++++------
 scm/define-music-display-methods.scm          |  4 +--
 scm/music-functions.scm                       | 17 ----------
 5 files changed, 40 insertions(+), 40 deletions(-)

diff --git a/Documentation/snippets/new/conducting-signs,-measure-grouping-signs.ly b/Documentation/snippets/new/conducting-signs,-measure-grouping-signs.ly
index 7bb8713b52..95af96054b 100644
--- a/Documentation/snippets/new/conducting-signs,-measure-grouping-signs.ly
+++ b/Documentation/snippets/new/conducting-signs,-measure-grouping-signs.ly
@@ -8,15 +8,14 @@ Beat grouping within a measure is controlled by the context property
 established for many time signatures in
 @file{scm/time-signature-settings.scm}.  Values of @code{beatStructure}
 can be changed or set with @code{\set}.
-Alternatively, the
-Scheme function @code{set-time-signature} can be used to both
+Alternatively, @code{\time} can be used to both
 set the time signature and establish the beat structure.
-@code{set-time-signature}, takes three arguments: the
-number of beats, the beat length, and the internal grouping of beats in
-the measure.  @code{\time} and @code{set-time-signature} both apply
-to the @code{Timing} context, so they will not reset values of
-@code{beatStructure} or @code{baseMoment} that are set in
-other lower-level contexts, such as @code{Voice}.
+For this, you specify the internal grouping of beats in a measure
+as a list of numbers (in Scheme syntax) before the time signature.
+
+@code{\time} applies to the @code{Timing} context, so it will not
+reset values of @code{beatStructure} or @code{baseMoment} that are set
+in other lower-level contexts, such as @code{Voice}.
 
 If the @code{Measure_grouping_engraver} is included
 in one of the display contexts, measure grouping signs will be
diff --git a/ly/music-functions-init.ly b/ly/music-functions-init.ly
index c135d80d8f..3b3a5b4c3a 100644
--- a/ly/music-functions-init.ly
+++ b/ly/music-functions-init.ly
@@ -1032,9 +1032,14 @@ tag =
    arg)
 
 time =
-#(define-music-function (parser location fraction) (fraction?)
-   (_i "Set @var{fraction} as time signature.")
-   (make-time-signature-set (car fraction) (cdr fraction)))
+#(define-music-function (parser location beat-structure fraction)
+   ((number-list? '()) fraction?)
+   (_i "Set @var{fraction} as time signature, with optional
+number list @var{beat-structure} before it.")
+  (make-music 'TimeSignatureMusic
+              'numerator (car fraction)
+              'denominator (cdr fraction)
+              'beat-structure beat-structure))
 
 times =
 #(define-music-function (parser location fraction music)
diff --git a/python/convertrules.py b/python/convertrules.py
index 18cadb199b..6ea53ea37d 100644
--- a/python/convertrules.py
+++ b/python/convertrules.py
@@ -3276,8 +3276,10 @@ def conv (str):
 
 def paren_matcher (n):
     # poor man's matched paren scanning, gives up
-    # after n+1 levels.
-    return r"\([^()]*(?:"*n+r"\([^()]*\)"+r"[^()]*)*\)"*n
+    # after n+1 levels.  Matches any string with balanced
+    # parens inside; add the outer parens yourself if needed.
+    # Nongreedy.
+    return r"[^()]*?(?:\("*n+r"[^()]*?"+r"\)[^()]*?)*?"*n
     return
 
 def undollar_scm (m):
@@ -3287,12 +3289,11 @@ def undollar_embedded (m):
     str = re.sub (r"#\$", "#", m.group (1))
     # poor man's matched paren scanning after #, gives up
     # after 25 levels.
-    str = re.sub ("#`?"+paren_matcher (25), undollar_scm, str)
+    str = re.sub ("#`?\("+paren_matcher (25)+"\)", undollar_scm, str)
     return m.string[m.start (0):m.start (1)] + str + m.string[m.end (1):m.end (0)]
 
 def strip_export (str):
-    return re.sub (r"\(ly:export\s+((?:[^()]*?" + paren_matcher (25)
-                   + r")*[^()]*)\)",
+    return re.sub (r"\(ly:export\s+(" + paren_matcher (25) + r")\)",
                    r"\1", str)
 
 def export_puller (m):
@@ -3319,20 +3320,32 @@ def record_ugly (m):
 def conv (str):
     str = re.sub (r"(?s)#@?\{(.*?)#@?\}", undollar_embedded, str)
     str = re.sub (r"#\(define(?:-public)?\s+\(([-a-zA-Z]+)"
-                  + r"\b[^()]*?\)([^()]*(?:" + paren_matcher (25)
-                  + r"[^()]*)*)\)", record_ugly, str)
+                  + r"\b[^()]*?\)(" + paren_matcher (25)
+                  + r")\)", record_ugly, str)
     str = re.sub (r"\(define(?:-public)?\s+\(" + should_really_be_music_function
-                  + r"\b[^()]*\)([^()]*(?:" + paren_matcher (25)
-                  + r"[^()]*)*)\)", ugly_function_rewriter, str)
+                  + r"\b[^()]*\)(" + paren_matcher (25)
+                  + r")\)", ugly_function_rewriter, str)
     str = re.sub (r"#(?=\(" + should_really_be_music_function + ")", "$", str)
     str = re.sub (r"#\(markup\*(?=\s)", r"$(markup", str)
-    str = re.sub ("#"+paren_matcher (25), export_puller, 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")
+def conv (str):
+    str = re.sub (r"\$\(set-time-signature\s+([0-9]+)\s+([0-9]+)\s*\)",
+                  r"\\time \1/\2", 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
+
 # Guidelines to write rules (please keep this at the end of this file)
 #
 # - keep at most one rule per version; if several conversions should be done,
diff --git a/scm/define-music-display-methods.scm b/scm/define-music-display-methods.scm
index a55e1ab775..d0926d5f85 100644
--- a/scm/define-music-display-methods.scm
+++ b/scm/define-music-display-methods.scm
@@ -900,8 +900,8 @@ Otherwise, return #f."
                 num den
                 (new-line->lily-string))
         (format #f
-                "$(set-time-signature ~a ~a '~a)~a"
-                num den structure
+                "\\time #'~a ~a/~a~a" 
+                structure num den
                 (new-line->lily-string)))))
 
 ;;; \melisma and \melismaEnd
diff --git a/scm/music-functions.scm b/scm/music-functions.scm
index f18a6507fd..69d3029de3 100644
--- a/scm/music-functions.scm
+++ b/scm/music-functions.scm
@@ -517,23 +517,6 @@ in @var{grob}."
   (make-music 'PropertyUnset
 	      'symbol sym))
 
-;;; Need to keep this definition for \time calls from parser
-(define-public (make-time-signature-set num den)
-  "Set properties for time signature @var{num}/@var{den}."
-  (make-music 'TimeSignatureMusic
-              'numerator num
-              'denominator den
-              'beat-structure '()))
-
-;;; Used for calls that include beat-grouping setting
-(define-public (set-time-signature num den . rest)
-  "Set properties for time signature @var{num}/@var{den}.
-If @var{rest} is present, it is used to set @code{beatStructure}."
-  (make-music 'TimeSignatureMusic
-	       'numerator num
-	       'denominator den
-	       'beat-structure (if (null? rest) rest (car rest))))
-
 (define-safe-public (make-articulation name)
   (make-music 'ArticulationEvent
 	      'articulation-type name))
-- 
2.39.5