]> git.donarmstrong.com Git - lilypond.git/commitdiff
Allow for nested contexts of any depth.
authorNeil Puttock <n.puttock@gmail.com>
Sun, 16 Nov 2008 00:58:06 +0000 (00:58 +0000)
committerNeil Puttock <n.puttock@gmail.com>
Sun, 16 Nov 2008 17:43:28 +0000 (17:43 +0000)
Use a set to keep track of visited contexts.
Remove InnerChoirStaff and InnerStaffGroup.
Add convert-ly rules, News entry and regtest.

Documentation/topdocs/NEWS.tely
input/regression/context-nested-staffgroup.ly [new file with mode: 0644]
lily/context-def.cc
lily/include/context-def.hh
ly/engraver-init.ly
python/convertrules.py
scripts/musicxml2ly.py

index 6de795eb344f71c8fed147fe28a2a0d820cb2b0c..5f640098d271c0fa2118ab2c2fb6a0bf8f1c310e 100644 (file)
@@ -62,6 +62,19 @@ which scares away people.
 
 @end ignore
 
+@item
+Nested contexts of the same type are now allowed.
+This deprecates @code{InnerStaffGroup} and @code{InnerChoirStaff}.
+@lilypond[relative=1]
+\new StaffGroup <<
+  \new Staff { c1 }
+  \new StaffGroup <<
+    \new Staff { c1 }
+    \new Staff { c1 }
+  >>
+>>
+@end lilypond
+
 @item
 In addition to the already existing @code{showLastLength} property,
 @code{showFirstLength} can now be set as well, rendering only the first
@@ -145,7 +158,9 @@ testnotes = {
          (yext (if is-up (cons (* log -0.8) 0) (cons 0 (* log 0.8))))
          (flag-stencil (make-filled-box-stencil '(-0.4 . 0.4) yext))
          (stroke-style (ly:grob-property stem-grob 'stroke-style))
-         (stroke-stencil (if (equal? stroke-style "grace") (make-line-stencil 0.2 -0.9 -0.4 0.9 -0.4) empty-stencil)))
+         (stroke-stencil (if (equal? stroke-style "grace")
+             (make-line-stencil 0.2 -0.9 -0.4 0.9 -0.4)
+             empty-stencil)))
     (ly:stencil-add flag-stencil stroke-stencil)))
 
 {
@@ -371,14 +386,12 @@ The environment variable @code{LILYPONDPREFIX} has been renamed
 Notes or rests, such as a typical end note, that fill an entire
 measure are preceded by some more space.
 
-@lilypond[]
-\relative c' {
-  \time 4/4
-  s1
-  c2. c4
-  \time 3/4
-  c2.
-}
+@lilypond[relative=1]
+\time 4/4
+s1
+c2. c4
+\time 3/4
+c2.
 @end lilypond
 
 @item
diff --git a/input/regression/context-nested-staffgroup.ly b/input/regression/context-nested-staffgroup.ly
new file mode 100644 (file)
index 0000000..2093aff
--- /dev/null
@@ -0,0 +1,15 @@
+\version "2.11.64"
+\header {
+  texidoc = "Contexts of the same type can be nested."
+}
+
+\new StaffGroup \relative c' <<
+  \new Staff { c1 }
+  \new StaffGroup <<
+    \new Staff { c1 }
+    \new StaffGroup <<
+      \new Staff { c1 }
+      \new Staff { c1 }
+    >>
+  >>
+>>
index a810159aa326d601cb75f950f9f7e4e3c0e0a3a3..47abcd365506b8d8a7e721172ee51b919ef1a162 100644 (file)
@@ -1,5 +1,5 @@
 /*
-  translator-def.cc -- implement Context_def
+  context-def.cc -- implement Context_def
 
   source file of the GNU LilyPond music typesetter
 
@@ -205,8 +205,24 @@ Context_def::get_default_child (SCM user_mod) const
   The ADDITIONAL_ACCEPTS parameter is a list of additional contexts that this
   specific context def (but not any of the child context defs) should accept.
 */
+vector<Context_def *>
+Context_def::path_to_acceptable_context (SCM type_sym,
+                                        Output_def *odef,
+                                        SCM additional_accepts) const
+{
+  set<const Context_def *> seen;
+  return internal_path_to_acceptable_context (type_sym, odef, additional_accepts, &seen);
+}
+
+/*
+The SEEN parameter is a set which keeps track of visited contexts, allowing
+contexts of the same type to be nested.
+*/
 vector<Context_def*>
-Context_def::path_to_acceptable_context (SCM type_sym, Output_def *odef, SCM additional_accepts) const
+Context_def::internal_path_to_acceptable_context (SCM type_sym,
+                                                 Output_def *odef,
+                                                 SCM additional_accepts,
+                                                 set<const Context_def *> *seen) const
 {
   assert (scm_is_symbol (type_sym));
 
@@ -230,20 +246,25 @@ Context_def::path_to_acceptable_context (SCM type_sym, Output_def *odef, SCM add
        }
     }
 
+  seen->insert (this);
   vsize best_depth = INT_MAX;
   for (vsize i = 0; i < accepteds.size (); i++)
     {
       Context_def *g = accepteds[i];
 
-      vector<Context_def*> result
-       = g->path_to_acceptable_context (type_sym, odef, SCM_EOL);
-      if (result.size () && result.size () < best_depth)
+      if (!seen->count (g))
        {
-         best_depth = result.size ();
-         result.insert (result.begin (), g);
-         best_result = result;
+         vector<Context_def*> result
+           = g->internal_path_to_acceptable_context (type_sym, odef, SCM_EOL, seen);
+         if (result.size () && result.size () < best_depth)
+           {
+             best_depth = result.size ();
+             result.insert (result.begin (), g);
+             best_result = result;
+           }
        }
     }
+  seen->erase (this);
 
   return best_result;
 }
index ea81eb1295be8f55aab47b8fa6c7ada6e3b93dd0..21af176327ff2e36a2a5ef5a6d13b50c94e25261 100644 (file)
@@ -14,6 +14,7 @@
 #include "smobs.hh"
 #include "input.hh"
 #include "virtual-methods.hh"
+#include <set>
 
 
 /*
@@ -49,7 +50,12 @@ public:
   VIRTUAL_COPY_CONSTRUCTOR(Context_def, Context_def);
 
   vector<Context_def*> path_to_acceptable_context (SCM type_string,
-                                                  Output_def *, SCM) const;
+                                                  Output_def *,
+                                                  SCM) const;
+  vector<Context_def*> internal_path_to_acceptable_context (SCM type_string,
+                                                           Output_def *,
+                                                           SCM,
+                                                           set<const Context_def *> *seen) const;
   Context *instantiate (SCM extra_ops);
 
   SCM to_alist () const;
index b1be75d1cb2777c5d52cd4b6209c3f156e26260f..7688912f6a205a86abc333f443a5232758003a63 100644 (file)
 
 \context {
   \type "Engraver_group"
-  \name "InnerChoirStaff"
+  \name "ChoirStaff"
   \consists "System_start_delimiter_engraver"
   systemStartDelimiter = #'SystemStartBracket
   vocalName = #'()
   \accepts "PianoStaff"
   \accepts "Lyrics"
   \accepts "ChordNames"
+  \accepts "ChoirStaff"
+  \accepts "StaffGroup"
   \defaultchild "Staff"
-}
-
-\context {
-  \InnerChoirStaff
-  \name ChoirStaff
-  
-  \defaultchild "Staff"
-  \accepts "InnerChoirStaff"
-  \accepts "InnerStaffGroup"
   \description "Identical to @code{StaffGroup} except that the
 contained staves are not connected vertically."
-
 }
 
 \context{
@@ -314,7 +306,7 @@ instrument names at the start of each system."
 
 \context {
   \type "Engraver_group"
-  \name InnerStaffGroup
+  \name "StaffGroup"
 
   \consists "Span_bar_engraver"
   \consists "Span_arpeggio_engraver"
@@ -332,24 +324,16 @@ instrument names at the start of each system."
   \accepts "TabStaff"  
   \accepts "Lyrics"
   \accepts "ChordNames"
-}
-
-\context {
-  \InnerStaffGroup
-  \name StaffGroup
+  \accepts "FiguredBass"
+  \accepts "ChoirStaff"
+  \accepts "StaffGroup"
   
   \description "Groups staves while adding a bracket on the left
 side, grouping the staves together.  The bar lines of the contained
 staves are connected vertically.  @code{StaffGroup} only consists of
 a collection of staves, with a bracket in front and spanning bar lines."
-  
-  \accepts "InnerChoirStaff"
-  \accepts "ChoirStaff"
-  \accepts "InnerStaffGroup"
-  \accepts "FiguredBass"
 }
 
-
 \context{
   \type "Engraver_group"
   \override VerticalAxisGroup #'minimum-Y-extent = #'(-0.75 . 2.0)
index 842d6fb8bd4d1e2a8d27b1a879aaf9ac8bbd39b0..c0ae536a02846e054145a0fc47ede441d1a93371 100644 (file)
@@ -2823,9 +2823,25 @@ def conv (str):
     str = re.sub (r"\\bigger", r"\\larger", str)
     return str
 
-@rule ((2, 11, 64), "systemSeparatorMarkup -> system-separator-markup")
+@rule ((2, 11, 64), "systemSeparatorMarkup -> system-separator-markup, \n\
+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 (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 (UPDATE_MANUALLY)
+        raise FatalConversionError ()
+    else:
+        str = re.sub ('InnerStaffGroup', 'StaffGroup', str)
+        str = re.sub ('InnerChoirStaff', 'ChoirStaff', str)
     return str
 
 # Guidelines to write rules (please keep this at the end of this file)
index 12e9ee29ab62f0bd59b38475f2c4c621d18183a3..0dcaf10ab3fc2239e5f1ffefac65b5c945afc9db 100644 (file)
@@ -424,8 +424,6 @@ def extract_score_structure (part_list, staffinfo):
                     del staves[pos]
                 # replace the staves with the whole group
                 for j in staves[(prev_start + 1):pos]:
-                    if j.is_group:
-                        j.stafftype = "InnerStaffGroup"
                     group.append_staff (j)
                 del staves[(prev_start + 1):pos]
                 staves.insert (prev_start + 1, group)