Use a set to keep track of visited contexts.
Remove InnerChoirStaff and InnerStaffGroup.
Add convert-ly rules, News entry and regtest.
@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
(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)))
{
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
--- /dev/null
+\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 }
+ >>
+ >>
+>>
/*
- translator-def.cc -- implement Context_def
+ context-def.cc -- implement Context_def
source file of the GNU LilyPond music typesetter
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));
}
}
+ 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;
}
#include "smobs.hh"
#include "input.hh"
#include "virtual-methods.hh"
+#include <set>
/*
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;
\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{
\context {
\type "Engraver_group"
- \name InnerStaffGroup
+ \name "StaffGroup"
\consists "Span_bar_engraver"
\consists "Span_arpeggio_engraver"
\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)
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)
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)