+2004-01-08 Han-Wen Nienhuys <hanwen@xs4all.nl>
+
+ * lily/translator-def.cc (get_translator_names): new function
+ (add_context_mod): new function
+ (get_accepted): new function
+
+ * lily/parser.yy (context_mod): put all modifications of
+ \translator { } in a single production, encode as SCM.
+
+ * lily/translator-def.cc (add_context_mod): rewrite Translator_def
+ to use read-only lists, so additions to the definition can be
+ prepended easily.
+
+ * Documentation/user/invoking.itexi (Editor support): add node on
+ editor support.
+
+ * Documentation/user/refman.itely (Bar check): add lyrics example
+ of bar checks.
+
+ * input/mutopia/F.Schubert/morgenlied.ly: add bar checks.
+
+ * scripts/convert-ly.py (conv): add conversion rule.
+
+ * lily/parser.yy: use \change iso. \translator for staff switch.
+
+ * lily/my-lily-lexer.cc: add \change.
+
+ * scm/define-translator-properties.scm
+ (default-melisma-properties): add definition.
+
2004-01-07 Han-Wen Nienhuys <hanwen@xs4all.nl>
+ * Documentation/user/refman.itely (Bar lines): clarification of
+ systemStartDelimiter.
+
* input/test/slur-shape.ly (x): remove file.
* lily/translator-group.cc (apply_property_operations): new function.
use -n for head/tail commands.
* lily/tie-engraver.cc (acknowledge_grob): make ties only for note
- heads with the same pitch. (backportme)
+ heads with the same pitch.
2003-12-20 Han-Wen Nienhuys <hanwen@cs.uu.nl>
Once you are an experienced user, you can use the manual as reference:
there is an extensive index@footnote{If you are looking for something,
-and you cannot find it by using the index, that is considered a bug.
-In that case, please file a bug report.}, but the document is also
+and you cannot find it in the manual, that is considered a bug. In
+that case, please file a bug report.}, but the document is also
available in
@ifnothtml
a big HTML page,
* Invoking the lilypond binary::
* Error messages::
* Reporting bugs::
+* Editor support::
* Point and click::
@end menu
platform you run it. Send the report to
@email{bug-lilypond@@gnu.org}.
+@node Editor support
+@section Editor support
+
+@cindex editors
+@cindex vim
+@cindex emacs
+@cindex modes, editor
+@cindex syntax coloring
+@cindex coloring, syntax
+
+There is support from different editors for LilyPond.
+
+Emacs has a @file{lilypond-mode}, which provides keyword
+autocompletion, indentation, LilyPond specific parenthesis matching
+and syntax coloring, handy compile short-cuts and reading LilyPond
+manuals using Info. If lilypond-mode is not installed on your
+platform, then refer to the installation instructions for more
+information.
+
+For VIM, a vimrc is supplied, along with syntax coloring tools. For
+more information, refer to the
+@ifhtml
+@uref{../../../topdocs/out-www/INSTALL.html,installation instructions}.
+@end ifhtml
+
+@ifnothtml
+installation instructions.
+@end ifnothtml
+
+For both editors, there is also a facility to jump in the input file
+to the source of errors in the graphical output. See @ref{Point and
+click}.
+
+
@node Point and click
@section Point and click
@cindex poind and click
@item Xdvi, version 22.36 or newer. Available from
@uref{ftp://ftp.math.berkeley.edu/pub/Software/TeX/xdvi.tar.gz,ftp.math.berkeley.edu}.
- Most @TeX{} distributions ship with xdvik, which is always
- a few versions behind the official Xdvi. To find out which Xdvi you
- are running, try @code{xdvi -version} or @code{xdvi.bin -version}.
+ Most @TeX{} distributions ship with xdvik, which is always a few
+versions behind the official Xdvi. To find out which Xdvi you are
+running, try @code{xdvi -version} or @code{xdvi.bin -version}.
@item KDVI. A dvi viewer for KDE. You need KDVI from KDE 3.0 or
newer. Enable option @emph{Inverse search} in the menu @emph{Settings}.
@c move this elsewhere?
-There is also support for Emacs: lilypond-mode for Emacs provides
-keyword autocompletion, indentation, LilyPond specific parenthesis
-matching and syntax coloring, handy compile short-cuts and reading
-LilyPond manuals using Info. If lilypond-mode is not installed on
-your platform, then refer to the installation instructions for more
-information.
@cindex Emacs
@cindex Emacs mode
@cindex \NAME\@c
@end macro
-@macro inputfileref{DIR,NAME}i
+@macro inputfileref{DIR,NAME}
@file{\DIR\/\NAME\}
@end macro
}
@end lilypond
-
-
@node Bar check
@subsection Bar check
@cindex Bar check
\time 3/4 c2 e4 | g2 |
@end example
+Bar checks can also be used in lyrics, for example
+
+@example
+ \lyrics @{
+ \time 2/4
+ Twin -- kle | Twin -- kle
+ @}
+@end example
@cindex skipTypesetting
The barlines at the start of each system are
@internalsref{SystemStartBar}, @internalsref{SystemStartBrace}, and
-@internalsref{SystemStartBracket}. They are spanner objects and
-typically must be tuned from a @code{\translator} block.
+@internalsref{SystemStartBracket}. Only one of these types is created
+in every context, and that type is determined by the property
+@code{systemStartDelimiter}. They are spanner objects and therefore
+the objects, as well as @code{systemStartDelimiter} must be set from a
+@code{\translator} block (see @ref{Defining contexts}) or using
+@code{\with} (see @code{Tuning spanning contexts}).
@node Polyphony
@inputfileref{input,star-spangled-banner.ly}.
@end ignore
+@c tremolo, beamed
@item tremolo
Make tremolo beams.
To place tremolo marks between notes, use @code{\repeat} with tremolo
style:
-@lilypond[verbatim,center,singleline]
+@lilypond[verbatim,singleline]
\score {
\context Voice \notes\relative c' {
\repeat "tremolo" 8 { c16 d16 }
\repeat "tremolo" 4 { c16 d16 }
\repeat "tremolo" 2 { c16 d16 }
- \repeat "tremolo" 4 c16
}
}
@end lilypond
-@seealso
+Tremolo marks can also be put on a single note. In this case, the
+note should not be surrounded by braces.
+@lilypond[verbatim,singleline]
+ \repeat "tremolo" 4 c16
+@end lilypond
-Tremolo beams are @internalsref{Beam} objects. Single stem tremolos
-are @internalsref{StemTremolo}s. The music expression is
-@internalsref{TremoloEvent}.
+A similar mechanism is the tremolo subdivision, described in
+@ref{Tremolo subdivisions}.
+@seealso
-@refbugs
+In this manual: @ref{Tremolo subdivisions}, @ref{Repeats}.
-The single stem tremolo must be entered without @code{@{} and
-@code{@}}.
+Internals: tremolo beams are @internalsref{Beam} objects. Single stem
+tremolos are @internalsref{StemTremolo}s. The music expression is
+@internalsref{TremoloEvent},
+
+Example files: @inputfileref{input/regression,chord-tremolo.ly},
+@inputfileref{input/regression,stem-tremolo.ly}.
@node Tremolo subdivisions
@subsection Tremolo subdivisions
Tremolos in this style do not carry over into the MIDI output.
+@seealso
+
+In this manual: @ref{Tremolo repeats}.
+
+Elsewhere: @internalsref{StemTremolo}, @internalsref{TremoloEvent}.
@node Measure repeats
@subsection Measure repeats
Voices can be switched between staves manually, using the following command:
@example
- \translator Staff = @var{staffname} @var{music}
+ \change Staff = @var{staffname} @var{music}
@end example
@noindent
\property PianoStaff.followVoice = ##t
\context Staff \context Voice {
c1
- \translator Staff=two
+ \change Staff=two
b2 a
}
\context Staff=two { \clef bass \skip 1*2 }
@cindex Non-guitar tablatures
You can change the number of strings, by setting the number of lines
-in the @internalsref{TabStaff} (the @code{line-count} property of
-@internalsref{TabStaff} can only be changed using
-@code{\applyoutput}, for more information, see @ref{Tuning
-objects}).
+in the @internalsref{TabStaff}. For more information, see @ref{Tuning
+spanning contexts}).
You can change the tuning of the strings. A string tuning is given as
a Scheme list with one integer number for each string, the number
firstVerse = \lyrics {
\property LyricsVoice . stanza = "1."
- Sü -- ßes Licht! Aus gol -- de -- nen Pfor -- ten brichst du __ \manuscriptBreak
- sie -- gend durch __ die Nacht. Schö -- ner Tag, du __ bist er -- wacht. __ Mit \manuscriptBreak
- ge -- heim -- nis -- vol -- len Wor -- ten, in me -- lo -- di -- schen Ak -- kor -- den, grüß __ ich __ \manuscriptBreak
+ Sü -- ßes Licht! Aus gol -- de -- nen Pfor -- ten brichst du __ \manuscriptBreak |
+ sie -- gend durch __ die Nacht. Schö -- ner Tag, du __ bist er -- wacht. __ Mit ge -- |
+ \manuscriptBreak
+ heim -- nis -- vol -- len Wor -- ten, in me -- lo -- di -- schen Ak -- kor -- den, grüß __ ich __ \manuscriptBreak |
dei -- ne Ro -- sen -- pracht, grüß ich __ dei -- ne Ro -- sen -- pracht.
}
secondVerse = \lyrics {
\property LyricsVoice . stanza = "2."
- Ach, der Lie -- be sanf "" -- tes We -- hen schwellt mir
- das be -- weg -- te __ Herz, sanft, wie ein ge -- lieb -- ter Schmerz. __ Dürft ich
- nur auf gold -- nen Hö -- hen mich im Mor -- gen -- duft er -- ge -- hen! Sehn -- sucht
+ Ach, der Lie -- be sanf "" -- tes We -- hen schwellt mir |
+ das be -- weg -- te __ Herz, sanft, wie ein ge -- lieb -- ter Schmerz. __ Dürft ich |
+ nur auf gold -- nen Hö -- hen mich im Mor -- gen -- duft er -- ge -- hen! Sehn -- sucht |
zieht mich him -- mel -- wärts, Sehn -- sucht zieht mich him -- mel -- wärts.
}
-\version "1.9.8"
+\version "2.1.7"
\header{
texidoc="
Beams can be typeset over fixed distance aligned staves, beam
\score{
\context PianoStaff <<
\context Staff=one \notes\relative c'{
- \stemUp c8[ c \translator Staff=two \stemUp c c]
+ \stemUp c8[ c \change Staff=two \stemUp c c]
c[ c c c]
- \translator Staff=one
- \stemDown c8[ c \translator Staff=two \stemUp c c]
+ \change Staff=one
+ \stemDown c8[ c \change Staff=two \stemUp c c]
r2
- \stemDown c8[ c \translator Staff=one \stemDown c c]
+ \stemDown c8[ c \change Staff=one \stemDown c c]
r2
- \translator Staff=two
- \stemUp c8[ c \translator Staff=one \stemDown c c]
+ \change Staff=two
+ \stemUp c8[ c \change Staff=one \stemDown c c]
r2
}
\context Staff=two \notes\relative c'{
-#(ly:set-option 'old-relative)
\version "1.9.8"
\header{
ADD_INTERFACE (Dot_column, "dot-column-interface",
"Interface that groups dots so they form a column",
- "direction stem");
+ "collision-done direction stem");
-/*
- translator-change.hh -- declare Translator_change
- source file of the GNU LilyPond music typesetter
-
- (c) 1997--2003 Han-Wen Nienhuys <hanwen@cs.uu.nl>
-*/
-
-
-#ifndef TRANSLATOR_CHANGE_HH
-#define TRANSLATOR_CHANGE_HH
-
-/** Change the nesting of the current translation. Uses the type_string_
- and id_string_ differently.
- */
-class Translator_change : public Music
-{
-
-}
-
-#endif // TRANSLATOR_CHANGE_HH
+#error
/*
these lists store the definition, in opposite order of entry
*/
-
- SCM consists_name_list_;
- SCM end_consists_name_list_;
- SCM accepts_name_list_;
+ SCM translator_mods_;
+ SCM accept_mods_;
SCM property_ops_;
-public:
SCM description_;
- /*
- "type" is overloaded.
- */
- SCM type_name_;
- SCM type_aliases_;
+ SCM context_name_;
+ SCM context_aliases_;
SCM translator_group_type_;
-
- SCM modify_definition (SCM, SCM, bool);
- SCM default_child_context_name ();
+public:
+ void add_context_mod (SCM);
+ SCM default_child_context_name ();
+ SCM get_context_name () const;
+ SCM get_accepted () const;
+ SCM get_translator_names () const;
void set_acceptor (SCM accepts, bool add);
- void add_element (SCM name);
- void remove_element (SCM name);
- void add_last_element (SCM name);
- void add_property_operation (SCM);
Link_array<Translator_def> path_to_acceptable_translator (SCM type_string, Music_output_def* odef) const;
Translator_group * instantiate (Music_output_def*);
SCM to_alist () const;
-
+ bool is_alias (SCM) const;
static SCM make_scm () ;
SCM clone_scm ()const;
void apply_default_property_operations (Translator_group*);
-
private:
DECLARE_SMOBS (Translator_def,foo);
Translator_def ();
Translator_def (Translator_def const&);
-
-
};
DECLARE_UNSMOB(Translator_def,translator_def);
void add_translator (Translator*trans);
-Translator*get_translator (String s);
+Translator*get_translator (SCM s);
DECLARE_UNSMOB(Translator,translator);
#endif // TRANSLATOR_HH
Translator_def *tp = unsmob_translator_def (transdef);
assert (tp);
- translator_tab_->set (tp->type_name_, transdef);
+ translator_tab_->set (tp->get_context_name (), transdef);
- String nm = ly_symbol2string (tp->type_name_) + "Context";
+ String nm = ly_symbol2string (tp->get_context_name ()) + "Context";
scm_module_define (scope_, ly_symbol2scm (nm.to_str0()), transdef);
{"autochange", AUTOCHANGE},
{"bar", BAR},
{"breathe", BREATHE},
+ {"change", CHANGE},
{"chordmodifiers", CHORDMODIFIERS},
{"chords", CHORDS},
{"clef", CLEF},
Music *property_op_to_music (SCM op);
Music *context_spec_music (SCM type, SCM id, Music * m, SCM ops_);
-
+SCM get_next_unique_context ();
#define YYERROR_VERBOSE 1
%token AUTOCHANGE
%token BAR
%token BREATHE
+%token CHANGE
%token CHORDMODIFIERS
%token CHORDS
%token LESSLESS
%type <i> exclamations questions dots optional_rest
%type <i> bass_mod
%type <scm> grace_head
-%type <scm> prop_ops_body optional_prop_ops
+%type <scm> property_operation_list
%type <scm> lyric_element
%type <scm> bass_number br_bass_figure bass_figure figure_list figure_spec
%token <i> DIGIT
%type <scm> embedded_scm scalar
%type <music> Music Sequential_music Simultaneous_music
%type <music> relative_music re_rhythmed_music part_combined_music
-%type <music> music_property_def translator_change
-%type <scm> Music_list property_operation
+%type <music> music_property_def context_change
+%type <scm> Music_list
+%type <scm> property_operation context_mod translator_mod
%type <outputdef> music_output_def_body
%type <music> shorthand_command_req
%type <music> post_event tagged_post_event
}
| TRANSLATOR_IDENTIFIER {
$$ = $1;
- unsmob_translator_def ($$)-> set_spot (THIS->here_input ());
- }
- | translator_spec_body TYPE STRING {
- unsmob_translator_def ($$)->translator_group_type_ = $3;
- }
- | translator_spec_body DESCRIPTION string {
- unsmob_translator_def ($$)->description_ = $3;
- }
- | translator_spec_body property_operation {
- unsmob_translator_def ($$)->add_property_operation ($2);
- }
- | translator_spec_body NAME STRING {
- unsmob_translator_def ($$)->type_name_ = scm_string_to_symbol ($3);
- }
- | translator_spec_body CONSISTS STRING {
- unsmob_translator_def ($$)->add_element ($3);
- }
- | translator_spec_body ALIAS STRING {
- Translator_def*td = unsmob_translator_def ($$);
- td->type_aliases_ = scm_cons (scm_string_to_symbol ($3), td->type_aliases_);
+ unsmob_translator_def ($$)->set_spot (THIS->here_input ());
}
| translator_spec_body GROBDESCRIPTIONS embedded_scm {
Translator_def*td = unsmob_translator_def($$);
for (SCM p = $3; gh_pair_p (p); p = ly_cdr (p)) {
SCM tag = gh_caar (p);
- if (tag == ly_symbol2scm ("poppush"))
- tag = ly_symbol2scm ("push");
- td->add_property_operation (scm_list_n (ly_symbol2scm ("assign"),
+ td->add_context_mod (scm_list_n (ly_symbol2scm ("assign"),
tag, ly_cdar (p), SCM_UNDEFINED));
}
}
- | translator_spec_body CONSISTSEND STRING {
- unsmob_translator_def ($$)->add_last_element ( $3);
- }
- | translator_spec_body ACCEPTS STRING {
- unsmob_translator_def ($$)->set_acceptor (scm_string_to_symbol ($3), true);
- }
- | translator_spec_body DENIES STRING {
- unsmob_translator_def ($$)->set_acceptor (scm_string_to_symbol ($3), false);
- }
- | translator_spec_body REMOVE STRING {
- unsmob_translator_def ($$)->remove_element ($3);
+ | translator_spec_body context_mod {
+ unsmob_translator_def ($$)->add_context_mod ($2);
}
;
$$ = unsmob_music ($1);
}
| music_property_def
- | translator_change
+ | context_change
;
| APPOGGIATURA { $$ = scm_makfrom0str ("Appoggiatura"); }
;
-optional_prop_ops:
- /* */ {
- $$ = SCM_EOL;
- }
- | WITH '{' prop_ops_body '}' {
- $$ = $3;
- }
- ;
-
-prop_ops_body:
+property_operation_list:
/* */ { $$ = SCM_EOL; }
- | prop_ops_body property_operation {
+ | property_operation_list property_operation {
$$ = gh_cons ($2, $1);
}
;
-
Composite_music:
AUTOCHANGE STRING Music {
scm_gc_unprotect_object ($2->self_scm ());
#endif
}
- | CONTEXT string '=' string optional_prop_ops Music {
- $$ = context_spec_music ($2, $4, $6, $5);
+ | CONTEXT string '=' string Music {
+ $$ = context_spec_music ($2, $4, $5, SCM_EOL);
}
- | CONTEXT STRING optional_prop_ops Music {
- $$ = context_spec_music ($2, SCM_UNDEFINED, $4, $3);
+ | CONTEXT STRING Music {
+ $$ = context_spec_music ($2, SCM_UNDEFINED, $3, SCM_EOL);
}
- | NEWCONTEXT string optional_prop_ops Music {
- static int new_context_count;
-
- char s[1024];
- snprintf (s, 1024, "uniqueContext%d", new_context_count ++);
+ | NEWCONTEXT string Music {
+ $$ = context_spec_music ($2, get_next_unique_context (),
+ $3, SCM_EOL);
+ }
+ | TRANSLATOR string '{' property_operation_list '}' Music {
+ $$ = context_spec_music ($2, get_next_unique_context (),
+ $6, $4);
- SCM new_id = scm_makfrom0str (s);
- $$ = context_spec_music ($2, new_id, $4, $3);
+ }
+ | TRANSLATOR string '=' string '{' property_operation_list '}' Music {
+ $$ = context_spec_music ($2, $4,
+ $8, $6);
}
| TIMES {
THIS->push_spot ();
}
;
-translator_change:
- TRANSLATOR STRING '=' STRING {
+context_change:
+ CHANGE STRING '=' STRING {
Music*t= MY_MAKE_MUSIC("TranslatorChange");
t-> set_mus_property ("change-to-type", scm_string_to_symbol ($2));
t-> set_mus_property ("change-to-id", $4);
}
;
-
-
property_operation:
STRING '=' scalar {
$$ = scm_list_n (ly_symbol2scm ("assign"),
}
;
+translator_mod:
+ CONSISTSEND { $$ = ly_symbol2scm ("consists-end"); }
+ | CONSISTS { $$ = ly_symbol2scm ("consists"); }
+ | REMOVE { $$ = ly_symbol2scm ("remove"); }
+
+ | ACCEPTS { $$ = ly_symbol2scm ("accepts"); }
+ | DENIES { $$ = ly_symbol2scm ("denies"); }
+
+ | ALIAS { $$ = ly_symbol2scm ("alias"); }
+ | TYPE { $$ = ly_symbol2scm ("translator-type"); }
+ | DESCRIPTION { $$ = ly_symbol2scm ("description"); }
+ | NAME { $$ = ly_symbol2scm ("context-name"); }
+ ;
+
+context_mod:
+ property_operation { $$ = $1; }
+ | translator_mod STRING {
+ $$ = scm_list_n ($1, $2, SCM_UNDEFINED);
+ }
+ ;
+
music_property_def:
PROPERTY STRING '.' property_operation {
Music * t = property_op_to_music ($4);
Music *csm = MY_MAKE_MUSIC("ContextSpeccedMusic");
- csm->set_mus_property ("element", t->self_scm ());
+ csm->set_mus_property ("element", t->self_scm ());
scm_gc_unprotect_object (t->self_scm ());
$$ = csm;
| DIGIT { $$ = gh_int2scm ($1); }
;
-
-
/*
This is a trick:
}
| close_event {
$$ = $1;
- dynamic_cast<Music *> ($$)->set_mus_property ("span-direction", gh_int2scm (START));
+ dynamic_cast<Music *> ($$)->set_mus_property ("span-direction",
+ gh_int2scm (START));
}
| open_event {
$$ = $1;
- dynamic_cast<Music *> ($$)->set_mus_property ("span-direction", gh_int2scm (STOP));
+ dynamic_cast<Music *> ($$)->set_mus_property ("span-direction",
+ gh_int2scm (STOP));
}
| EVENT_IDENTIFIER {
$$ = unsmob_music ($1);
| steno_tonic_pitch
;
-
-
-
-
hyphen_req:
HYPHEN {
if (!THIS->lexer_->lyric_state_b ())
return csm;
}
+
+SCM
+get_next_unique_context ()
+{
+ static int new_context_count;
+
+ char s[1024];
+ snprintf (s, 1024, "uniqueContext%d", new_context_count ++);
+
+ return scm_makfrom0str (s);
+}
/* if separate_contexts_b_ is set, create a new context with the
number number as name */
- SCM name = unsmob_translator_def (report_to ()->definition_)->type_name_;
+ SCM name = unsmob_translator_def (report_to ()->definition_)->get_context_name ();
Translator_group * t = (j && separate_contexts_b_)
? report_to ()->find_create_translator (name, to_string (j), SCM_EOL)
: report_to ();
*/
#include "translator.hh"
-#include <map>
+#include "scm-hash.hh"
#include "warn.hh"
/*
should delete these after exit.
*/
-std::map<String,Translator*> *global_translator_dict=0;
+Scheme_hash_table *global_translator_dict=0;
LY_DEFINE(get_all_translators,"ly:get-all-translators", 0, 0, 0, (),
"Return an list of a all translator objects that may be instantiated "
" during a lilypond run.")
{
- SCM l = SCM_EOL;
- for (std::map<String,Translator*>::const_iterator (ci (global_translator_dict->begin()));
- ci != global_translator_dict->end (); ci++)
+ SCM l = global_translator_dict ? global_translator_dict->to_alist () : SCM_EOL;
+
+ for (SCM s =l; gh_pair_p (s); s = gh_cdr (s))
{
- l = scm_cons ((*ci).second->self_scm (), l);
+ gh_set_car_x (s, gh_cdar (s));
}
+
return l;
}
add_translator (Translator *t)
{
if (!global_translator_dict)
- global_translator_dict = new std::map<String,Translator*>;
+ global_translator_dict = new Scheme_hash_table;
- (*global_translator_dict)[classname (t)] = t;
+ SCM k= ly_symbol2scm (classname (t));
+ global_translator_dict->set (k, t->self_scm ());
}
Translator*
-get_translator (String s)
+get_translator (SCM sym)
{
- if (global_translator_dict->find (s) !=
- global_translator_dict->end ())
- {
- Translator* t = (*global_translator_dict)[s];
- return t;
- }
+ SCM v = SCM_BOOL_F;
+ if (global_translator_dict)
+ global_translator_dict->try_retrieve (sym, &v);
+
+ if (v == SCM_BOOL_F)
+ error (_f ("unknown translator: `%s'", ly_symbol2string (sym).to_str0 ()));
- error (_f ("unknown translator: `%s'", s));
- return 0;
+ return unsmob_translator (v);
}
Translator_def* me = (Translator_def*) SCM_CELL_WORD_1 (smob);
scm_puts ("#<Translator_def ", port);
- scm_display (me->type_name_, port);
+ scm_display (me->context_name_, port);
scm_puts (">", port);
return 1;
}
Translator_def* me = (Translator_def*) SCM_CELL_WORD_1 (smob);
scm_gc_mark (me->description_);
- scm_gc_mark (me->type_aliases_);
- scm_gc_mark (me->consists_name_list_);
- scm_gc_mark (me->accepts_name_list_);
- scm_gc_mark (me->end_consists_name_list_);
+ scm_gc_mark (me->context_aliases_);
+ scm_gc_mark (me->accept_mods_);
+ scm_gc_mark (me->translator_mods_);
scm_gc_mark (me->property_ops_);
scm_gc_mark (me->translator_group_type_);
- return me->type_name_;
+ return me->context_name_;
}
Translator_def::Translator_def ()
{
- type_aliases_ = SCM_EOL;
+ context_aliases_ = SCM_EOL;
translator_group_type_ = SCM_EOL;
- accepts_name_list_ = SCM_EOL;
- consists_name_list_ = SCM_EOL;
- end_consists_name_list_ = SCM_EOL;
+ accept_mods_ = SCM_EOL;
+ translator_mods_ = SCM_EOL;
property_ops_ = SCM_EOL;
- type_name_ = SCM_EOL;
+ context_name_ = SCM_EOL;
description_ = SCM_EOL;
smobify_self();
Translator_def::Translator_def (Translator_def const & s)
: Input (s)
{
- type_aliases_ = SCM_EOL;
+ context_aliases_ = SCM_EOL;
translator_group_type_ = SCM_EOL;
- accepts_name_list_ = SCM_EOL;
- consists_name_list_ = SCM_EOL;
- end_consists_name_list_ = SCM_EOL;
+ accept_mods_ = SCM_EOL;
+ translator_mods_ = SCM_EOL;
property_ops_ = SCM_EOL;
- type_name_ = SCM_EOL;
+ context_name_ = SCM_EOL;
description_ = SCM_EOL;
smobify_self();
description_ = s.description_;
- consists_name_list_ = scm_list_copy (s.consists_name_list_);
- end_consists_name_list_ = scm_list_copy (s.end_consists_name_list_);
- accepts_name_list_ = scm_list_copy (s.accepts_name_list_);
- property_ops_ = scm_list_copy (s.property_ops_);
- type_aliases_ = scm_list_copy (s.type_aliases_);
+
+ accept_mods_ = s.accept_mods_;
+ property_ops_ = s.property_ops_;
+ translator_mods_ = s.translator_mods_;
+ context_aliases_ = s.context_aliases_;
translator_group_type_ = s.translator_group_type_;
- type_name_ = s.type_name_;
+ context_name_ = s.context_name_;
}
-
void
-Translator_def::set_acceptor (SCM name, bool add)
-{
- assert (gh_symbol_p (name));
- if (add)
- this->accepts_name_list_ = gh_cons (name, this->accepts_name_list_);
- else
- this->accepts_name_list_ = scm_delete_x (name, this->accepts_name_list_);
-}
-
-
-SCM
-Translator_def::modify_definition (SCM list, SCM str, bool add)
+Translator_def::add_context_mod (SCM mod)
{
- String s = ly_scm2string (str);
- if (!get_translator (s))
- error (_ ("Program has no such type"));
+ SCM tag = gh_car (mod);
+ if (ly_symbol2scm ("description") == tag)
+ {
+ description_ = gh_cadr (mod);
+ return ;
+ }
- if (add)
+ SCM sym = gh_cadr (mod);
+ if (gh_string_p (sym))
+ sym = scm_string_to_symbol (sym);
+
+ if (ly_symbol2scm ("consists") == tag
+ || ly_symbol2scm ("consists-end") == tag
+ || ly_symbol2scm ("remove") == tag)
{
- if (scm_memq (str, list) != SCM_BOOL_F)
- {
- warning (_f ("Already contains: `%s'", s));
- warning (_f ("Not adding translator: `%s'", s));
- }
+ if (!get_translator (sym))
+ error (_f ("Program has no such type: `%s'", ly_symbol2string (sym).to_str0 ()));
else
- list= gh_cons (str, list);
+ translator_mods_ = gh_cons (scm_list_2 (tag, sym), translator_mods_ );
+ }
+ else if (ly_symbol2scm ("accepts") == tag
+ || ly_symbol2scm ("denies") == tag)
+ {
+ accept_mods_ = gh_cons (scm_list_2 (tag, sym), accept_mods_);
+ }
+ else if (ly_symbol2scm ("poppush") == tag
+ || ly_symbol2scm ("pop") == tag
+ || ly_symbol2scm ("push") == tag
+ || ly_symbol2scm ("assign") == tag
+ || ly_symbol2scm ("unset") == tag)
+ {
+ property_ops_ = gh_cons (mod, property_ops_);
+ }
+ else if (ly_symbol2scm ("alias") == tag)
+ {
+ context_aliases_ = gh_cons (sym, context_aliases_);
+ }
+ else if (ly_symbol2scm ("translator-type") == tag)
+ {
+ translator_group_type_ = sym;
+ }
+ else if (ly_symbol2scm ("context-name") == tag)
+ {
+ context_name_ = sym;
}
else
{
- list = scm_delete_x (str, list);
+ programming_error ("Unknown context mod tag.");
}
- return list;
}
-
-
-void
-Translator_def::remove_element (SCM s)
+SCM
+Translator_def::get_translator_names () const
{
- this->end_consists_name_list_ = modify_definition (this->end_consists_name_list_, s, false);
- this->consists_name_list_ = modify_definition (this->consists_name_list_, s, false);
-}
+ SCM l1 = SCM_EOL;
+ SCM l2 = SCM_EOL;
-void
-Translator_def::add_element (SCM s)
-{
- this->consists_name_list_ = modify_definition (this->consists_name_list_, s, true);
+ SCM mods = scm_reverse (translator_mods_);
+ for (SCM s = mods; gh_pair_p (s); s = gh_cdr (s))
+ {
+ SCM tag = gh_caar (s);
+ SCM arg = gh_cadar (s);
+
+ if (ly_symbol2scm ("consists") == tag)
+ l1 = gh_cons (arg, l1);
+ else if (ly_symbol2scm ("consists-end") == tag)
+ l2 = gh_cons (arg, l2);
+ else if (ly_symbol2scm ("remove") == tag)
+ {
+ l1 = scm_delete_x (arg, l1);
+ l2 = scm_delete_x (arg, l2);
+ }
+ }
+
+ return scm_append_x (scm_list_2 (l1, l2));
}
-void
-Translator_def::add_last_element (SCM s)
+SCM
+Translator_def::get_context_name () const
{
- this->end_consists_name_list_ = modify_definition (this->end_consists_name_list_, s, true);
+ return context_name_;
}
-void
-Translator_def::add_property_operation (SCM what)
+SCM
+Translator_def::get_accepted () const
{
- this->property_ops_ = gh_cons (what, this->property_ops_);
+ SCM correct_order = scm_reverse (accept_mods_);
+ SCM acc = SCM_EOL;
+ for (SCM s = correct_order; gh_pair_p (s); s = gh_cdr (s))
+ {
+ SCM tag = gh_caar (s);
+ SCM sym = gh_cadar (s);
+ if (tag == ly_symbol2scm ("accepts"))
+ acc = gh_cons (sym, acc);
+ else if (tag == ly_symbol2scm ("denies"))
+ acc = scm_delete_x (sym, acc);
+ }
+ return acc;
}
-
-
+
Link_array<Translator_def>
Translator_def::path_to_acceptable_translator (SCM type_sym, Music_output_def* odef) const
{
assert (gh_symbol_p (type_sym));
+ SCM accepted = get_accepted ();
+
Link_array<Translator_def> accepteds;
- for (SCM s = accepts_name_list_; gh_pair_p (s); s = ly_cdr (s))
+ for (SCM s = accepted; gh_pair_p (s); s = ly_cdr (s))
{
Translator_def *t = unsmob_translator_def (odef->find_translator (ly_car (s)));
if (!t)
/*
don't check aliases, because \context Staff should not create RhythmicStaff.
*/
- if (gh_equal_p (accepteds[i]->type_name_, type_sym))
+ if (gh_equal_p (accepteds[i]->get_context_name (), type_sym))
{
best_result.push (accepteds[i]);
return best_result;
static SCM
-trans_list (SCM namelist, Translator_group*tg)
+names_to_translators (SCM namelist, Translator_group*tg)
{
SCM l = SCM_EOL;
for (SCM s = namelist; gh_pair_p (s) ; s = ly_cdr (s))
{
- Translator * t = get_translator (ly_scm2string (ly_car (s)));
+ Translator * t = get_translator (ly_car (s));
if (!t)
warning (_f ("can't find: `%s'", s));
else
Translator_group *
Translator_def::instantiate (Music_output_def* md)
{
- Translator * g = get_translator (ly_scm2string (translator_group_type_));
+ Translator * g = get_translator (translator_group_type_);
g = g->clone ();
Translator_group *tg = dynamic_cast<Translator_group*> (g);
tg->output_def_ = md;
tg->definition_ = self_scm ();
- /*
- TODO: ugh. we're reversing CONSISTS_NAME_LIST_ here
- */
- SCM l1 = trans_list (consists_name_list_, tg);
- SCM l2 =trans_list (end_consists_name_list_,tg);
- l1 = scm_reverse_x (l1, l2);
-
- tg->simple_trans_list_ = l1;
+ SCM trans_names = get_translator_names ();
+ tg->simple_trans_list_ = names_to_translators (trans_names, tg);
return tg;
}
SCM
Translator_def::default_child_context_name ()
{
- SCM d = accepts_name_list_;
+ SCM d = get_accepted ();
return gh_pair_p (d) ? ly_car (scm_last_pair (d)) : SCM_EOL;
}
Translator_def::to_alist () const
{
SCM l = SCM_EOL;
-
- l = gh_cons (gh_cons (ly_symbol2scm ("consists"), consists_name_list_), l);
+
+ l = gh_cons (gh_cons (ly_symbol2scm ("consists"), get_translator_names ()), l);
l = gh_cons (gh_cons (ly_symbol2scm ("description"), description_), l);
- l = gh_cons (gh_cons (ly_symbol2scm ("aliases"), type_aliases_), l);
- l = gh_cons (gh_cons (ly_symbol2scm ("end-consists"),
- end_consists_name_list_), l);
- l = gh_cons (gh_cons (ly_symbol2scm ("accepts"), accepts_name_list_), l);
+ l = gh_cons (gh_cons (ly_symbol2scm ("aliases"), context_aliases_), l);
+ l = gh_cons (gh_cons (ly_symbol2scm ("accepts"), get_accepted ()), l);
l = gh_cons (gh_cons (ly_symbol2scm ("property-ops"), property_ops_), l);
-
- /*
- junkme:
- */
- l = gh_cons (gh_cons (ly_symbol2scm ("type-name"), type_name_), l);
-
+ l = gh_cons (gh_cons (ly_symbol2scm ("context-name"), context_name_), l);
l = gh_cons (gh_cons (ly_symbol2scm ("group-type"), translator_group_type_), l);
return l;
}
+
+bool
+Translator_def::is_alias (SCM sym) const
+{
+ bool b = sym == context_name_;
+
+ for (SCM a = context_aliases_; !b && gh_pair_p (a); a = ly_cdr (a))
+ b = b || sym == ly_car (a);
+
+ return b;
+}
Translator_group::context_name () const
{
Translator_def * td = unsmob_translator_def (definition_ );
- return ly_symbol2string (td->type_name_);
+ return ly_symbol2string (td->get_context_name ());
}
void
LY_DEFINE(ly_translator_name,
"ly:translator-name", 1,0,0, (SCM trans),
- "Return the type name of the translator @var{trans}.")
+ "Return the type name of the translator @var{trans}. The name is a symbol.")
{
Translator* tr = unsmob_translator (trans);
SCM_ASSERT_TYPE(tr, trans, SCM_ARG1, __FUNCTION__, "Context");
char const* nm = classname (tr);
- return scm_makfrom0str (nm);
+ return ly_symbol2scm (nm);
}
LY_DEFINE(ly_translator_description,
scm_puts ("#<Translator ", port);
if (Translator_def *d=unsmob_translator_def (sc->definition_))
{
- scm_display (d->type_name_, port);
+ scm_display (d->get_context_name (), port);
}
else
scm_display (ly_translator_name (s), port);
bool
Translator::is_alias (SCM sym) const
{
- Translator_def * td = unsmob_translator_def (definition_);
- bool b = (sym == td->type_name_);
-
- for (SCM a = td->type_aliases_; !b && gh_pair_p (a); a = ly_cdr (a))
- b = b || sym == ly_car (a);
-
- return b;
+ return unsmob_translator_def (definition_)->is_alias (sym);
}
bool
changeMoment = #`(,(ly:make-moment 0 0) . ,(ly:make-moment 1 512))
systemStartDelimiter =#'SystemStartBar
- melismaBusyProperties = #'(melismaBusy slurMelismaBusy tieMelismaBusy beamMelismaBusy)
+ melismaBusyProperties = #default-melisma-properties
clefGlyph = #"clefs-G"
clefPosition = #-2
(translator-property-description 'melismaBusyProperties list?
"List of properties (symbols) to
determine whether a melisma is playing.")
+
+
(translator-property-description 'metronomeMarkFormatter procedure?
"How to produce a metronome markup.
Called with 2 arguments, event and context.")
Valid values are described in @ref{(lilypond-internals)bar-line-interface}.
.")
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(define-public default-melisma-properties '(melismaBusy slurMelismaBusy tieMelismaBusy beamMelismaBusy))
(engravers (filter
(lambda (x) (engraver-makes-grob? name x)) all-engravers-list))
(namestr (symbol->string name))
- (engraver-names (map ly:translator-name engravers))
+ (engraver-names (map symbol->string (map ly:translator-name engravers)))
)
(make <texi-node>
"\n\nAccepted by: "
(human-listify
(map ref-ify
- (map ly:translator-name
- (filter
- (lambda (x) (engraver-accepts-music-type? (car entry) x)) all-engravers-list))))
+ (map symbol->string
+ (map ly:translator-name
+ (filter
+ (lambda (x) (engraver-accepts-music-type? (car entry) x)) all-engravers-list)))))
"\n\n"
)))
"\n\nAccepted by: "
(human-listify
(map ref-ify
- (map ly:translator-name
- (filter
- (lambda (x) (engraver-accepts-music-types? types x)) all-engravers-list))))
+ (map symbol->string (map ly:translator-name
+ (filter
+ (lambda (x) (engraver-accepts-music-types? types x)) all-engravers-list)))))
"\n\nProperties: \n"
(description-list->texi
(map
(propsr (cdr (assoc 'properties-read (ly:translator-description engraver))))
(propsw (cdr (assoc 'properties-written (ly:translator-description engraver))))
(accepted (cdr (assoc 'events-accepted (ly:translator-description engraver))))
- (name (ly:translator-name engraver))
- (name-sym (string->symbol name))
+ (name-sym (ly:translator-name engraver))
+ (name (symbol->string name-sym))
(desc (cdr (assoc 'description (ly:translator-description engraver))))
(grobs (engraver-grobs engraver))
)
(contexts
(apply append
(map (lambda (x)
- (let ((context (cdr (assoc 'type-name x)))
+ (let ((context (cdr (assoc 'context-name x)))
(consists (append
(list (cdr (assoc 'group-type x)))
(cdr (assoc 'consists x))
- (cdr (assoc 'end-consists x)))))
+ )))
(if (member name consists)
(list context)
;; First level Engraver description
(define (engraver-doc grav)
(make <texi-node>
- #:name (ly:translator-name grav)
+ #:name (symbol->string (ly:translator-name grav))
#:text (engraver-doc-string grav #t)
))
(ly:get-all-translators))
(define (find-engraver-by-name name)
+ "NAME is a symbol."
(hash-ref name->engraver-table name #f))
(define (document-engraver-by-name name)
+ "NAME is a symbol."
(let*
(
(eg (find-engraver-by-name name ))
)
- (cons name
+ (cons (symbol->string name )
(engraver-doc-string eg #f)
-
)
))
(define (context-doc context-desc)
(let*
(
- (name-sym (cdr (assoc 'type-name context-desc)))
+ (name-sym (cdr (assoc 'context-name context-desc)))
(name (symbol->string name-sym))
(aliases (map symbol->string (cdr (assoc 'aliases context-desc))))
(desc-handle (assoc 'description context-desc))
(consists (append
(list (cdr (assoc 'group-type context-desc)))
(cdr (assoc 'consists context-desc))
- (cdr (assoc 'end-consists context-desc))
))
(props (cdr (assoc 'property-ops context-desc)))
(grobs (context-grobs context-desc))
(string-append
"\n\nContext "
name " can contain \n"
- (human-listify (map ref-ify (map symbol->string accepts)))))
+ (human-listify (map ref-ify (map symbol->string accepts)))))
"\n\nThis context is built from the following engravers: "
(description-list->texi
))))
(define (engraver-grobs grav)
- (let* (
- (eg (if (string? grav)
+ (let* ((eg (if (symbol? grav)
(find-engraver-by-name grav)
- grav))
-
- )
+ grav)))
(if (eq? eg #f)
'()
- (map symbol->string (cdr (assoc 'grobs-created (ly:translator-description eg))))
- )
+ (map symbol->string (cdr (assoc 'grobs-created (ly:translator-description eg)))))
))
(define (context-grobs context-desc)
- (let* (
- (consists (append
+ (let* ((consists (append
(list (cdr (assoc 'group-type context-desc)))
(cdr (assoc 'consists context-desc))
- (cdr (assoc 'end-consists context-desc))
))
(grobs (apply append
(map engraver-grobs consists))
- )
- )
+ ))
grobs
))
(define all-engravers-list (ly:get-all-translators))
(set! all-engravers-list
(sort all-engravers-list
- (lambda (a b) (string<? (ly:translator-name a)
- (ly:translator-name b)))))
+ (lambda (a b) (string<? (symbol->string (ly:translator-name a))
+ (symbol->string (ly:translator-name b))))))
(define (all-engravers-doc)
(make <texi-node>
conversions.append (((2,1,4), conv, """removal of automaticMelismata; use melismaBusyProperties instead."""))
+
+
+def conv (str):
+ str =re.sub (r"\\translator\s+([a-zA-Z]+)", r"\\change \1", str)
+ return str
+
+conversions.append (((2,1,7), conv, """\\translator Staff -> \\change Staff"""))
+
+
################################
# END OF CONVERSIONS
################################