From 3c2e17bbdd44174a8dab25333738a75afa788f31 Mon Sep 17 00:00:00 2001 From: Reinhold Kainhofer Date: Wed, 10 Mar 2010 15:40:00 +0100 Subject: [PATCH] Context mods stored in variable, can be inserted into \with or \context -) Context-Modifications: create C++ class to store them -) context modifications lists are stored in a dedicated simple scheme object (C++ class Context_mod) -) Changes to the parser: -) \with blocks no longer return a simple list, but a Context_mod object -) context_modifications objects (stored in variables) are now also allowed with \with clauses -) context_modifications objects are also allowed inside \context -) this allows us to rewrite \RemoveEmptyStaffContext (unfortunately with a little different syntax, since we no longer store \Staff inside the \RESC command) so that it no longer erases previous settings to the Staff context. Now, instead of \context { \RemoveEmptyStaffContext } one can do \context { \Staff \RemoveEmptyStaves } with the same effect and preserve previous changes to the Staff context. (The same applies of course to \DrumStaff, \RhythmicStaff, etc. as well) -) Adjusted engraver-init.ly and the regtests accordingly; Also added regtest that checks for RESC not discarding previous settings to the Staff context -) Add convert-ly rule (\RemoveEmpty*StaffContext -> \*Staff \RemoveEmptyStaves) -) Add scheme interface to extract context mods and add context mods with Scheme -) Add changelog entry --- Documentation/changes.tely | 18 ++++ input/regression/context-mod-context.ly | 43 +++++++++ input/regression/context-mod-with.ly | 45 +++++++++ input/regression/hara-kiri-drumstaff.ly | 5 +- .../hara-kiri-keep-previous-settings.ly | 43 +++++++++ input/regression/hara-kiri-percent-repeat.ly | 15 ++- input/regression/hara-kiri-pianostaff.ly | 5 +- input/regression/hara-kiri-rhythmicstaff.ly | 5 +- input/regression/hara-kiri-tabstaff.ly | 5 +- lily/context-mod-scheme.cc | 44 +++++++++ lily/context-mod.cc | 76 +++++++++++++++ lily/include/context-mod.hh | 58 ++++++++++++ lily/include/lily-proto.hh | 1 + lily/parser.yy | 94 ++++++++++++++----- ly/engraver-init.ly | 40 ++++---- python/convertrules.py | 13 ++- 16 files changed, 453 insertions(+), 57 deletions(-) create mode 100644 input/regression/context-mod-context.ly create mode 100644 input/regression/context-mod-with.ly create mode 100644 input/regression/hara-kiri-keep-previous-settings.ly create mode 100644 lily/context-mod-scheme.cc create mode 100644 lily/context-mod.cc create mode 100644 lily/include/context-mod.hh diff --git a/Documentation/changes.tely b/Documentation/changes.tely index 62e625974b..8569dbf56f 100644 --- a/Documentation/changes.tely +++ b/Documentation/changes.tely @@ -62,6 +62,24 @@ which scares away people. @end ignore +@item +Context modifications (@code{\with} blocks) can be stored in variables and +inserted into contexts or other @code{\with} blocks: +@lilypond[quote,verbatim] +coloredheads = \with { \override NoteHead #'color = #red } +noclef = \with { \remove "Clef_engraver" } +\score { + \new Staff { + \new Voice \with { \coloredheads } \relative c' { c4 e g c } + } + \layout { + \context { \Staff + \noclef + } + } +} +@end lilypond + @item A half-open articulation was added: @lilypond[quote,relative=2] diff --git a/input/regression/context-mod-context.ly b/input/regression/context-mod-context.ly new file mode 100644 index 0000000000..020db8c465 --- /dev/null +++ b/input/regression/context-mod-context.ly @@ -0,0 +1,43 @@ +\version "2.13.18" + +\header { +texidoc = "Context modifications can be stored into a variable as a +\with object. They can be later inserted directly into a context definition." +} + +% Some sample modifications to be inserted into a \with block later on +ctxmod = \with { + \remove "Time_signature_engraver" + \consists "Ambitus_engraver" + \override StaffSymbol #'line-count = 4 +} + +music = \relative c'' { \key fis \minor c1 d e } + +\score { << + \new Staff { \music} + >> + \layout { + \context { \Staff + \ctxmod + \override NoteHead #'style = #'petrucci + } + } +} + + +\score { << + \new Staff { \music} + >> + \layout { + \context { \Staff + \override StaffSymbol #'line-count = 3 + \override NoteHead #'style = #'petrucci + } + % Should override the above definitions, but not reset others + \context { \Staff + \ctxmod + } + } +} + diff --git a/input/regression/context-mod-with.ly b/input/regression/context-mod-with.ly new file mode 100644 index 0000000000..377d3ef81b --- /dev/null +++ b/input/regression/context-mod-with.ly @@ -0,0 +1,45 @@ +\version "2.13.18" + +\header { +texidoc = "Context modifications can be stored into a variable as a +\with object. They can be later inserted into another \with block." +} + +% Some sample modifications to be inserted into a \with block later on +ctxmod = \with { + \remove "Time_signature_engraver" + \consists "Ambitus_engraver" + \override StaffSymbol #'line-count = 4 +} + +music = \relative c'' { \key fis \minor c1 d e } + +\score { << + % No modifications: + \new Staff { \music } + % Some context modifications manually written in a \with block + \new Staff \with { + \remove "Time_signature_engraver" + \consists "Ambitus_engraver" + \override StaffSymbol #'line-count = 4 + } { \music } + % The same mods as direct value of \with + \new Staff \with \ctxmod { \music } + % Mods as part of a \with block + \new Staff \with { \ctxmod } { \music } + % Mods before a context mod in a with block are working: + \new Staff \with { + \remove "Clef_engraver" + \ctxmod + } { \music } + % Mods before and after a context mod in a with block are working: + \new Staff \with { + \remove "Clef_engraver" + \ctxmod + \remove "Key_engraver" + } { \music } + % Mods can be inserted instead of a \with block (i.e. \with is not required) + \new Staff \ctxmod { \music } + \new Staff { \music } +>> +} diff --git a/input/regression/hara-kiri-drumstaff.ly b/input/regression/hara-kiri-drumstaff.ly index 478d23e695..ada43ebcb2 100644 --- a/input/regression/hara-kiri-drumstaff.ly +++ b/input/regression/hara-kiri-drumstaff.ly @@ -1,4 +1,4 @@ -\version "2.13.10" +\version "2.13.18" \header { texidoc = @@ -18,7 +18,8 @@ and no staff case. \layout { ragged-right = ##t \context { - \RemoveEmptyDrumStaffContext + \DrumStaff + \RemoveEmptyStaves } } diff --git a/input/regression/hara-kiri-keep-previous-settings.ly b/input/regression/hara-kiri-keep-previous-settings.ly new file mode 100644 index 0000000000..818376cfb1 --- /dev/null +++ b/input/regression/hara-kiri-keep-previous-settings.ly @@ -0,0 +1,43 @@ +\version "2.13.18" + +\header { texidoc = + + "Inserting the harakiri settings globally into the Staff context should +not erase previous settings to the Staff context. +" + +} + +\layout { + ragged-right= ##t + \context { + \Staff + \override StaffSymbol #'line-count = 4 + \consists "Ambitus_engraver" + \remove "Clef_engraver" + } +} + +% Old \RemoveEmptyStaffContext: Will erase previous settings... +\score { + << + \new Staff \relative c'' { c4 c c c \break s1 \break c4 c c c \break c c c c} + \new Staff \relative c'' { d4 d d d s1 s1 s1 } + \new Staff \relative c'' { e4 e e e s1 e4 e e e s1 } + >> + \layout { + \context { \RemoveEmptyStaffContext } + } +} + +% New \RemoveEmptyStaves settings: Preserves previous settings... +\score { + << + \new Staff \relative c'' { c4 c c c \break s1 \break c4 c c c \break c c c c} + \new Staff \relative c'' { d4 d d d s1 s1 s1 } + \new Staff \relative c'' { e4 e e e s1 e4 e e e s1 } + >> + \layout { + \context { \Staff \RemoveEmptyStaves } + } +} diff --git a/input/regression/hara-kiri-percent-repeat.ly b/input/regression/hara-kiri-percent-repeat.ly index 847e93c688..fdc5338d34 100644 --- a/input/regression/hara-kiri-percent-repeat.ly +++ b/input/regression/hara-kiri-percent-repeat.ly @@ -1,4 +1,4 @@ -\version "2.13.10" +\version "2.13.18" \header { texidoc = "Staves, RhythmicStaves, TabStaves and DrumStaves @@ -11,12 +11,11 @@ \new TabStaff \repeat percent 4 { c1 } \new DrumStaff \drummode { \repeat percent 4 { hh1 } } \new RhythmicStaff \repeat percent 4 { c'1 } ->> +>> \layout { - \context { \RemoveEmptyStaffContext } - \context { \RemoveEmptyRhythmicStaffContext } - \context { \RemoveEmptyDrumStaffContext } - \context { \RemoveEmptyTabStaffContext } - } - + \context { \Staff \RemoveEmptyStaves } + \context { \RhythmicStaff \RemoveEmptyStaves } + \context { \DrumStaff \RemoveEmptyStaves } + \context { \TabStaff \RemoveEmptyStaves } +} diff --git a/input/regression/hara-kiri-pianostaff.ly b/input/regression/hara-kiri-pianostaff.ly index e347ad2029..e19aa4fd82 100644 --- a/input/regression/hara-kiri-pianostaff.ly +++ b/input/regression/hara-kiri-pianostaff.ly @@ -1,4 +1,4 @@ -\version "2.12.0" +\version "2.13.18" \header { texidoc = @@ -21,7 +21,8 @@ alignment; this should not confuse the mechanism. \layout { ragged-right= ##t \context { - \RemoveEmptyStaffContext + \Staff + \RemoveEmptyStaves } } diff --git a/input/regression/hara-kiri-rhythmicstaff.ly b/input/regression/hara-kiri-rhythmicstaff.ly index fd6ccbdd5b..a554dd2c1a 100644 --- a/input/regression/hara-kiri-rhythmicstaff.ly +++ b/input/regression/hara-kiri-rhythmicstaff.ly @@ -1,4 +1,4 @@ -\version "2.13.10" +\version "2.13.18" \header { texidoc = @@ -18,7 +18,8 @@ and no staff case. \layout { ragged-right= ##t \context { - \RemoveEmptyRhythmicStaffContext + \RhythmicStaff + \RemoveEmptyStaves } } diff --git a/input/regression/hara-kiri-tabstaff.ly b/input/regression/hara-kiri-tabstaff.ly index e5738ab876..a692385fc9 100644 --- a/input/regression/hara-kiri-tabstaff.ly +++ b/input/regression/hara-kiri-tabstaff.ly @@ -1,4 +1,4 @@ -\version "2.13.10" +\version "2.13.18" \header { texidoc = @@ -18,7 +18,8 @@ and no staff case." \layout { ragged-right= ##t \context { - \RemoveEmptyTabStaffContext + \TabStaff + \RemoveEmptyStaves } } diff --git a/lily/context-mod-scheme.cc b/lily/context-mod-scheme.cc new file mode 100644 index 0000000000..245749604a --- /dev/null +++ b/lily/context-mod-scheme.cc @@ -0,0 +1,44 @@ +/* + This file is part of LilyPond, the GNU music typesetter. + + Copyright (C) 2010 Jan Nieuwenhuizen + Han-Wen Nienhuys + + LilyPond is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + LilyPond is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with LilyPond. If not, see . +*/ + +#include "context.hh" +#include "context-mod.hh" + +LY_DEFINE (ly_get_context_mods, + "ly:get-context-mods", + 1, 0, 0, (SCM contextmod), + "Returns the list of context modifications stored in @var{contextmod}.") +{ + Context_mod *tr = unsmob_context_mod (contextmod); + LY_ASSERT_SMOB (Context_mod, contextmod, 1); + return tr->get_mods (); +} + +LY_DEFINE (ly_add_context_mod, + "ly:add-context-mod", + 2, 0, 0, (SCM contextmods, SCM modification), + "Adds the given context @var{modification} to the list @var{contextmods} of context modifications.") +{ + Context_mod *ctxmod = unsmob_context_mod (contextmods); + LY_ASSERT_SMOB (Context_mod, contextmods, 1); + ctxmod->add_context_mod (modification); + return SCM_UNSPECIFIED; +} + diff --git a/lily/context-mod.cc b/lily/context-mod.cc new file mode 100644 index 0000000000..691f29658d --- /dev/null +++ b/lily/context-mod.cc @@ -0,0 +1,76 @@ +/* + This file is part of LilyPond, the GNU music typesetter. + + Copyright (C) 2010 Reinhold Kainhofer + + LilyPond is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + LilyPond is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with LilyPond. If not, see . +*/ + +#include "context-mod.hh" + +Context_mod::Context_mod () +{ + mods_ = SCM_EOL; +} + +Context_mod::Context_mod (Context_mod const &s) +{ + mods_ = s.mods_; +} + +#include "ly-smobs.icc" +IMPLEMENT_SIMPLE_SMOBS (Context_mod); +IMPLEMENT_DEFAULT_EQUAL_P (Context_mod); + +int +Context_mod::print_smob (SCM smob, SCM port, scm_print_state*) +{ + Context_mod *me = (Context_mod *) SCM_CELL_WORD_1 (smob); + + scm_puts ("#mods_, port); + scm_puts (">", port); + return 1; +} + +SCM +Context_mod::mark_smob (SCM smob) +{ + ASSERT_LIVE_IS_ALLOWED (); + + Context_mod *me = (Context_mod *) SCM_CELL_WORD_1 (smob); + + scm_gc_mark (me->mods_); + return me->mods_; +} + +void +Context_mod::add_context_mod (SCM mod) +{ + mods_ = scm_cons (mod, mods_); +} + +void +Context_mod::add_context_mods (SCM mods) +{ + for (SCM m = mods; scm_is_pair (m); m = scm_cdr (m)) + add_context_mod (scm_car (m)); +} + +SCM +Context_mod::get_mods () const +{ + return scm_reverse (mods_); +} + diff --git a/lily/include/context-mod.hh b/lily/include/context-mod.hh new file mode 100644 index 0000000000..babb864228 --- /dev/null +++ b/lily/include/context-mod.hh @@ -0,0 +1,58 @@ +/* + This file is part of LilyPond, the GNU music typesetter. + + Copyright (C) 2010 Reinhold Kainhofer + + LilyPond is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + LilyPond is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with LilyPond. If not, see . +*/ + +/** + * context-mod.hh + * Implement a structure to store context modifications to be inserted + * at some later point + */ + +#ifndef CONTEXT_MOD_HH +#define CONTEXT_MOD_HH + +#include "lily-proto.hh" +#include "smobs.hh" +#include "virtual-methods.hh" + + +/* + Modifications for an interpretation context as given in the + input. +*/ +struct Context_mod +{ +private: + SCM mods_; +public: + void add_context_mod (SCM); + void add_context_mods (SCM); + + VIRTUAL_COPY_CONSTRUCTOR (Context_mod, Context_mod); + + SCM get_mods () const; + + Context_mod (); + Context_mod (Context_mod const &); + DECLARE_SIMPLE_SMOBS (Context_mod); +}; + +DECLARE_UNSMOB (Context_mod, context_mod); + +#endif /* CONTEXT_MOD_HH */ + diff --git a/lily/include/lily-proto.hh b/lily/include/lily-proto.hh index d9ede2a765..04b9b23d53 100644 --- a/lily/include/lily-proto.hh +++ b/lily/include/lily-proto.hh @@ -54,6 +54,7 @@ class Cluster_engraver; class Column_x_positions; class Context; class Context_def; +class Context_mod; class Context_specced_music; class Dispatcher; class Dot_column; diff --git a/lily/parser.yy b/lily/parser.yy index 5f18eef531..1ec5e11aa2 100644 --- a/lily/parser.yy +++ b/lily/parser.yy @@ -84,6 +84,7 @@ using namespace std; #include "book.hh" #include "context-def.hh" +#include "context-mod.hh" #include "dimensions.hh" #include "file-path.hh" #include "input.hh" @@ -279,6 +280,7 @@ If we give names, Bison complains. %token CHORD_MODIFIER %token CHORD_REPETITION %token CONTEXT_DEF_IDENTIFIER +%token CONTEXT_MOD_IDENTIFIER %token DRUM_PITCH %token DURATION_IDENTIFIER %token EVENT_IDENTIFIER @@ -346,6 +348,7 @@ If we give names, Bison complains. %type chord_body_element %type command_element %type command_event +%type context_modification %type context_change %type direction_less_event %type direction_reqd_event @@ -631,6 +634,9 @@ identifier_init: | DIGIT { $$ = scm_from_int ($1); } + | context_modification { + $$ = $1; + } ; context_def_spec_block: @@ -663,6 +669,13 @@ context_def_spec_body: | context_def_spec_body context_mod { unsmob_context_def ($$)->add_context_mod ($2); } + | context_def_spec_body context_modification { + Context_def *td = unsmob_context_def ($$); + SCM new_mods = unsmob_context_mod ($2)->get_mods (); + for (SCM m = new_mods; scm_is_pair (m); m = scm_cdr (m)) { + td->add_context_mod (scm_car (m)); + } + } ; @@ -1023,22 +1036,45 @@ simple_music: | context_change ; +context_modification: + WITH { PARSER->lexer_->push_initial_state (); } '{' context_mod_list '}' + { + PARSER->lexer_->pop_state (); + $$ = $4; + } + | WITH CONTEXT_MOD_IDENTIFIER + { + $$ = $2; + } + | CONTEXT_MOD_IDENTIFIER + { + $$ = $1; + } + ; + optional_context_mod: - /**/ { $$ = SCM_EOL; } - | WITH { PARSER->lexer_->push_initial_state (); } - '{' context_mod_list '}' - { - PARSER->lexer_->pop_state (); - $$ = $4; - } - ; + /**/ { + $$ = SCM_EOL; + } + | context_modification + { + $$ = $1; + } + ; context_mod_list: - /* */ { $$ = SCM_EOL; } - | context_mod_list context_mod { - $$ = scm_cons ($2, $1); - } - ; + /**/ { + $$ = Context_mod ().smobbed_copy (); + } + | context_mod_list context_mod { + unsmob_context_mod ($1)->add_context_mod ($2); + } + | context_mod_list CONTEXT_MOD_IDENTIFIER { + Context_mod *md = unsmob_context_mod ($2); + if (md) + unsmob_context_mod ($1)->add_context_mods (md->get_mods ()); + } + ; composite_music: prefix_composite_music { $$ = $1; } @@ -1120,10 +1156,18 @@ prefix_composite_music: $$ = run_music_function (PARSER, $1); } | CONTEXT simple_string optional_id optional_context_mod music { - $$ = MAKE_SYNTAX ("context-specification", @$, $2, $3, $5, $4, SCM_BOOL_F); + Context_mod *ctxmod = unsmob_context_mod ($4); + SCM mods = SCM_EOL; + if (ctxmod) + mods = ctxmod->get_mods (); + $$ = MAKE_SYNTAX ("context-specification", @$, $2, $3, $5, mods, SCM_BOOL_F); } | NEWCONTEXT simple_string optional_id optional_context_mod music { - $$ = MAKE_SYNTAX ("context-specification", @$, $2, $3, $5, $4, SCM_BOOL_T); + Context_mod *ctxmod = unsmob_context_mod ($4); + SCM mods = SCM_EOL; + if (ctxmod) + mods = ctxmod->get_mods (); + $$ = MAKE_SYNTAX ("context-specification", @$, $2, $3, $5, mods, SCM_BOOL_T); } | TIMES fraction music { @@ -1148,7 +1192,11 @@ prefix_composite_music: PARSER->lexer_->pop_state (); } | mode_changing_head_with_context optional_context_mod grouped_music_list { - $$ = MAKE_SYNTAX ("context-specification", @$, $1, SCM_EOL, $3, $2, SCM_BOOL_T); + Context_mod *ctxmod = unsmob_context_mod ($2); + SCM mods = SCM_EOL; + if (ctxmod) + mods = ctxmod->get_mods (); + $$ = MAKE_SYNTAX ("context-specification", @$, $1, SCM_EOL, $3, mods, SCM_BOOL_T); if ($1 == ly_symbol2scm ("ChordNames")) { $$ = MAKE_SYNTAX ("unrelativable-music", @$, $$); @@ -2556,13 +2604,17 @@ Lily_lexer::try_special_identifiers (SCM *destination, SCM sid) } else if (scm_is_number (sid)) { *destination = sid; return NUMBER_IDENTIFIER; - } else if (unsmob_context_def (sid)) { - Context_def *def= unsmob_context_def (sid)->clone (); + } else if (unsmob_context_def (sid)) { + Context_def *def= unsmob_context_def (sid)->clone (); + + *destination = def->self_scm (); + def->unprotect (); - *destination = def->self_scm (); - def->unprotect (); + return CONTEXT_DEF_IDENTIFIER; + } else if (unsmob_context_mod (sid)) { + *destination = unsmob_context_mod (sid)->smobbed_copy (); - return CONTEXT_DEF_IDENTIFIER; + return CONTEXT_MOD_IDENTIFIER; } else if (unsmob_score (sid)) { Score *score = new Score (*unsmob_score (sid)); *destination = score->self_scm (); diff --git a/ly/engraver-init.ly b/ly/engraver-init.ly index 6d4b656dd7..ee723dc0e1 100644 --- a/ly/engraver-init.ly +++ b/ly/engraver-init.ly @@ -451,22 +451,13 @@ printing of a single line of lyrics." } -RemoveEmptyStaffContext = \context { - \Staff +RemoveEmptyStaves = \with { \remove "Axis_group_engraver" \consists "Hara_kiri_engraver" \override Beam #'auto-knee-gap = #'() \override VerticalAxisGroup #'remove-empty = ##t } -AncientRemoveEmptyStaffContext = \context { -%% why not add by default? - - \RemoveEmptyStaffContext - \accepts "VaticanaVoice" - \accepts "GregorianTranscriptionVoice" - \accepts "MensuralVoice" -} \context { \type "Score_engraver" @@ -980,24 +971,35 @@ accommodated for typesetting a piece in mensural style." printKeyCancellation = ##f } + +%% Keep the old definitions in here for compatibility (they erase previous +%% settings to the corresponding context!). +%% For new scores, one should simply insert the \RemoveEmptyStaves settings +%% into the desired context. That's just as easy, requires only one line more +%% (the \*Staff), but preserves previous context mods. +%% TODO: DEPRECATED_2.13.17, remove at some point in the future +RemoveEmptyStaffContext = \context { + \Staff + \RemoveEmptyStaves +} + +AncientRemoveEmptyStaffContext = \context { + \VaticanaStaff + \RemoveEmptyStaves +} + RemoveEmptyDrumStaffContext = \context { \DrumStaff - \remove "Axis_group_engraver" - \override VerticalAxisGroup #'remove-empty = ##t - \consists "Hara_kiri_engraver" + \RemoveEmptyStaves } RemoveEmptyRhythmicStaffContext = \context { \RhythmicStaff - \remove "Axis_group_engraver" - \override VerticalAxisGroup #'remove-empty = ##t - \consists "Hara_kiri_engraver" + \RemoveEmptyStaves } RemoveEmptyTabStaffContext = \context { \TabStaff - \remove "Axis_group_engraver" - \override VerticalAxisGroup #'remove-empty = ##t - \consists "Hara_kiri_engraver" + \RemoveEmptyStaves } diff --git a/python/convertrules.py b/python/convertrules.py index 2f0409eb3c..8de43822e0 100644 --- a/python/convertrules.py +++ b/python/convertrules.py @@ -2987,7 +2987,18 @@ def conv(str): _ ("Unify fetaNumber and fetaDynamic encodings")) def conv(str): return re.sub(r'\bfeta(Number|Dynamic)', 'fetaText', str) - + +@rule ((2, 13, 18), + _ ("\RemoveEmpty*StaffContext -> \*Staff \RemoveEmptyStaves")) +def conv(str): + str = re.sub (r"\\RemoveEmpty(|Drum|Rhythmic|Tab)StaffContext", + r"\\\1Staff \\RemoveEmptyStaves", + str); + str = re.sub (r"\\AncientRemoveEmptyStaffContext", + r"\\VaticanaStaff \\RemoveEmptyStaves", + str); + 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, -- 2.39.5