]> git.donarmstrong.com Git - lilypond.git/commitdiff
* scm/music-functions.scm (remove-tag): filter \tagged music
authorHan-Wen Nienhuys <hanwen@xs4all.nl>
Sat, 30 Aug 2003 21:35:56 +0000 (21:35 +0000)
committerHan-Wen Nienhuys <hanwen@xs4all.nl>
Sat, 30 Aug 2003 21:35:56 +0000 (21:35 +0000)
expressions.

* input/regression/tag-filter.ly (texidoc): new file.

* lily/parser.yy (post_event): add \tag #'symbol / \tag #'(symbol1
symbol2 .. ) etc.

* Documentation/user/refman.itely (Fingering instructions): adjust manual.

ChangeLog
Documentation/topdocs/NEWS.texi
Documentation/user/refman.itely
input/regression/tag-filter.ly [new file with mode: 0644]
lily/my-lily-lexer.cc
lily/parser.yy
scm/define-music-properties.scm
scm/music-functions.scm

index 26df67e1a8c77cfe3345f5278c8bf6b4bae37713..26bb357369bfa0baf333892dccd17e17a40140ae 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,13 @@
 2003-08-30  Han-Wen Nienhuys  <hanwen@cs.uu.nl>
 
+       * scm/music-functions.scm (remove-tag): filter \tagged music
+       expressions.
+
+       * input/regression/tag-filter.ly (texidoc): new file.
+
+       * lily/parser.yy (post_event): add \tag #'symbol / \tag #'(symbol1
+       symbol2 .. ) etc. 
+
        * scripts/convert-ly.py (FatalConversionError.conv): fingering
        convert rule.
 
index b0b4ec04c674ba217d41032171f1e12935068101..bf4aacc5c62f17e4d0dfa4c44394c8b98cfa9e7d 100644 (file)
@@ -8,6 +8,35 @@
 @chapter New features in 1.9 since 1.8
 
 @itemize
+
+@item
+Each music expression can now be tagged, to make different printed
+versions from the same music expression.  In the following example,
+we see two versions of a piece of music, one for the full score, and
+one with cue notes for the instrumental part:
+@example
+< \tag #'part <
+  @{ c4 f2 g @}      % in the part, we have cue-notes  
+  \\ R1 >
+  \tag #'score R1  % in the score: only a rest
+>
+@end example
+The same can be applied to articulations, texts, etc.: they are
+made by prepending
+@example
+        -\tag #@var{your-tag(s)} 
+@end example
+to an articulation, for example, 
+@example
+        c4-\tag #'with-fingerings -4 -\tag #'with-strings \6
+@end example
+
+This defines a note, which has a fingering and a string-number
+indication. 
+
+
+
 @item
 Markup text (ie. general text formatting) may now be used for lyrics too. 
 
index 8423e5c64e5fda2609f284429a6c91fb7e091afc..94bb40d6c314a214384deb67c136ab8fd51020a8 100644 (file)
@@ -4432,6 +4432,65 @@ in this example disappears in the second line:
 @end lilypond
 
 
+@node Different editions from one source
+@subsection Different editions from one source
+
+The @code{\\tag} command marks music expressions with a name. These
+tagged expressions can be filtered out later.  With this mechanism it
+is possible to make different versions of the same music source.
+
+In the following example, we see two versions of a piece of music, one
+for the full score, and one with cue notes for the instrumental part:
+
+@example
+ c1
+    \relative c' <
+       \tag #'part <
+         R1 \\
+         {
+             \property Voice.fontSize = #-1
+             c4_"cue" f2 g4 } 
+        >
+       \tag #'score R1
+     >
+@end example
+
+The same can be applied to articulations, texts, etc.: they are
+made by prepending
+@example
+        -\tag #@var{your-tag} 
+@end example
+to an articulation, for example, 
+@example
+    c1-\tag #'part ^4
+@end example
+
+This defines a note with a conditional fingering indication.
+
+By applying the @code{remove-tag} function, tagged expressions can be
+filtered. For example,
+@example
+\simultaneous {
+        @var{the music}
+       \apply #(remove-tag 'score) @var{the music}
+       \apply #(remove-tag 'part) @var{the music}
+}
+@end example
+would yield
+
+@lilypondfile[notexidoc]{tag-filter.ly}
+
+The argument of the @code{\tag} command should be a symbol, or a list
+of symbols, for example,
+@example
+  \tag #'(original-part transposed-part) @dots{}
+@end example
+
+@seealso
+
+@inputfileref{input/regression,tag-filter.ly}
+
+
 @node Sound output for transposing instruments
 @subsection Sound output for transposing instruments
 
diff --git a/input/regression/tag-filter.ly b/input/regression/tag-filter.ly
new file mode 100644 (file)
index 0000000..e7d5915
--- /dev/null
@@ -0,0 +1,53 @@
+
+\version "1.9.3"
+\header {
+
+texidoc = "The @code{\\tag} command marks music expressions with a
+name. These tagged expressions can be filtered out later. This
+mechanism can be used to make different versions of the same music. In
+this example, the top stave displays the music expression with all
+tags included. The bottom two staves are filtered: the part has cue
+notes and fingerings, but the score has not."
+
+}
+
+\paper { raggedright= ##t }
+
+common =
+\notes \relative c''  {
+
+    c1
+    \relative c' <
+       \tag #'part <
+         R1 \\
+         {
+             \property Voice.fontSize = #-1
+             c4_"cue" f2 g4 } 
+        >
+       \tag #'score R1
+     >
+    c1-\tag #'part ^4
+}
+
+
+\score {
+    \notes \simultaneous { 
+    \new Staff {
+       \property Staff.instrument = #"both"
+       \common
+       }
+    \new Staff {
+       \property Staff.instrument = #"part"
+       \apply #(remove-tag 'score) \common
+       }
+    \new Staff {
+       \property Staff.instrument = #"score"
+       \apply #(remove-tag 'part) \common
+       }
+    }
+}
+
+
+
+
+
index 1e63016cbf5a7642eb8f2cbfb84bfabed61281d1..b2f154f92c71d1556a83edce328a927625cb859e 100644 (file)
@@ -80,6 +80,7 @@ static Keyword_ent the_key_tab[]={
   {"set", SET},
   {"simultaneous", SIMULTANEOUS},
   {"skip", SKIP},
+  {"tag", TAG},
   {"tempo", TEMPO},
   {"time", TIME_T},
   {"times", TIMES},
index 2b8ec7198c4efc6a9d4e6c2acc92954523814d84..e8c710b8ac6a15235331da1b29cadc4b8f56eaa5 100644 (file)
@@ -96,7 +96,23 @@ My_lily_parser* my_lily_parser;
 
 #define yyerror THIS->parser_error
 
+/*
+  Add symbols to the  TAGS field of a music object. 
+*/
 
+void
+tag_music (Music*m,  SCM tag, Input ip)
+{
+       SCM tags = m->get_mus_property ("tags");
+       if (gh_symbol_p (tag))
+               tags = scm_cons (tag, tags);
+       else if (gh_list_p (tag))
+               tags = gh_append2 (tag, tags);
+       else
+               ip.warning (_("Tag must be symbol or list of symbols."));
+
+       m->set_mus_property ("tags", tags);
+}
 
 
 
@@ -278,6 +294,7 @@ yylex (YYSTYPE *s,  void * v)
 %token SIMULTANEOUS
 %token SKIP
 %token SPANREQUEST
+%token TAG
 %token TEMPO
 %token TIMES
 %token TIME_T
@@ -352,7 +369,7 @@ yylex (YYSTYPE *s,  void * v)
 %type <scm> steno_duration optional_notemode_duration multiplied_duration
 %type <scm>  verbose_duration
        
-%type <scm>   post_events
+%type <scm>   post_events 
 %type <music> gen_text_def direction_less_event direction_reqd_event
 %type <scm>   steno_pitch pitch absolute_pitch pitch_also_in_chords
 %type <scm>   explicit_pitch steno_tonic_pitch
@@ -367,7 +384,7 @@ yylex (YYSTYPE *s,  void * v)
 %type <scm> Music_list
 %type <outputdef>  music_output_def_body
 %type <music> shorthand_command_req
-%type <music>  post_event 
+%type <music>  post_event tagged_post_event
 %type <music> command_req verbose_command_req
 %type <music>  extender_req
 %type <music> hyphen_req
@@ -1092,7 +1109,11 @@ basic music objects too, since the meaning is different.
        }
        | relative_music        { $$ = $1; }
        | re_rhythmed_music     { $$ = $1; } 
-       | part_combined_music   { $$ = $1; } 
+       | part_combined_music   { $$ = $1; }
+       | TAG embedded_scm Music {
+               tag_music ($3, $2, THIS->here_input ());
+               $$ = $3;
+       }
        ;
 
 relative_music:
@@ -1510,20 +1531,33 @@ post_events:
                $$ = gh_cons ($2->self_scm(), $$);
                scm_gc_unprotect_object ($2->self_scm());
        }
+       | post_events tagged_post_event {
+               $2 -> set_spot (THIS->here_input ());
+               $$ = scm_cons ($2->self_scm(), $$);
+               scm_gc_unprotect_object ($2->self_scm());
+       }
        ;
 
 
+tagged_post_event:
+       '-' TAG embedded_scm post_event {
+               tag_music ($4, $3, THIS->here_input ());
+               $$ = $4;
+       }
+       ;
 
 post_event:
        direction_less_event {
                $$ = $1;
        }
        | script_dir direction_reqd_event {
-               $2->set_mus_property ("direction", gh_int2scm ($1));
+               if ($1)
+                       $2->set_mus_property ("direction", gh_int2scm ($1));
                $$ = $2;
        }
        | script_dir direction_less_event {
-               $2->set_mus_property ("direction", gh_int2scm ($1));
+               if ($1)
+                       $2->set_mus_property ("direction", gh_int2scm ($1));
                $$ = $2;
        }
        | string_number_event
index e705f24b59e9de52c63bc2f1686cf6e107e06864..705706a735a132ba2439354a762abde664a0d61a 100644 (file)
@@ -42,6 +42,10 @@ TODO: consider making type into symbol ")
 (music-property-description 'denominator integer? "denominator in a time signature")
 (music-property-description 'digit integer? "digit for fingering")
 (music-property-description 'direction ly:dir? "Print this up or down?")
+(music-property-description 'tags list? "List of symbols that for denoting extra details,
+eg. @code{\\tag #'part ...} could tag a piece of music as only being active in a part.")
+
+
 (music-property-description 'text-type symbol? "Particular type of text script (eg. finger, dynamic).")
 (music-property-description 'tempo-unit ly:duration? "The unit for the metronome count.")
 (music-property-description 'tonic ly:pitch? "Base of the scale")
index 431b9bdc30b12d8b087763bcdfb175acd2d43b8c..591468c510347a6f57af2a485ca3362b71ea1f4b 100644 (file)
@@ -1,4 +1,3 @@
-
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
 (define-public (music-map function music)
        (function music)
        ))
 
+(define-public (music-filter pred? music)
+  "Filter out music expressions that do not satisfy PRED."
+  
+  (define (inner-music-filter pred? music)
+    "Recursive function."
+    (let* ((es (ly:get-mus-property music 'elements))
+          (e (ly:get-mus-property music 'element))
+          (as (ly:get-mus-property music 'articulations))
+          (filtered-as (filter ly:music? (map (lambda (y) (inner-music-filter pred? y)) as)))
+          (filtered-e (if (ly:music? e)
+                          (inner-music-filter pred? e)
+                          e))
+          (filtered-es (filter ly:music? (map (lambda (y) (inner-music-filter pred? y)) es)))
+          )
+
+      (ly:set-mus-property! music 'element filtered-e)
+      (ly:set-mus-property! music 'elements filtered-es)
+      (ly:set-mus-property! music 'articulations filtered-as)
+
+      ;; if filtering emptied the expression, we remove it completely.
+      (if (or (pred? music)
+             (and (eq? filtered-es '()) (not (ly:music? e))
+                  (or (not (eq? es '()))
+                      (ly:music? e))))
+         (set! music '()))
+      
+      music))
+
+  (set! music (inner-music-filter pred? music))
+  (if (ly:music? music)
+      music
+      (make-music-by-name 'Music)      ;must return music.
+      ))
+
+(define-public (remove-tag tag)
+  (lambda (mus)
+    (music-filter
+     (lambda (m)
+       (let* ((tags (ly:get-mus-property m 'tags))
+             (res (memq tag tags)))
+       res)) mus)))
+
 (define-public (display-music music)
   "Display music, not done with music-map for clarity of presentation."
   (display music)