]> git.donarmstrong.com Git - lilypond.git/commitdiff
* scm/new-markup.scm (markup): a macro that provides a
authorHan-Wen Nienhuys <hanwen@xs4all.nl>
Mon, 2 Feb 2004 10:47:23 +0000 (10:47 +0000)
committerHan-Wen Nienhuys <hanwen@xs4all.nl>
Mon, 2 Feb 2004 10:47:23 +0000 (10:47 +0000)
LilyPond-like syntax in scheme for building markups, in order to
help markup command definition. (Nicolas Sceaux)

* input/test/lyrics-skip-notes.ly: new example.

* lily/parser.yy (post_event): make HYPHEN into postfix event.

* lily/new-lyric-combine-music-iterator.cc (find_context_below):
use is_alias() iso. == . This fixes lyrics on
GregorianTranscriptions.

12 files changed:
ChangeLog
Documentation/topdocs/NEWS.texi
Documentation/user/invoking.itexi
Documentation/user/refman.itely
VERSION
input/regression/lyric-combine-new.ly
input/test/lyrics-skip-notes.ly [new file with mode: 0644]
lily/hyphen-engraver.cc
lily/new-lyric-combine-music-iterator.cc
lily/parser.yy
scm/define-grobs.scm
scm/new-markup.scm

index 0e12fe0879e7f358fc46d95731f67bf6e551f39a..44877335ecbabaefeb756623f9510186d2e4105a 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+2004-02-02  Han-Wen Nienhuys   <hanwen@xs4all.nl>
+
+       * scm/new-markup.scm (markup): a macro that provides a
+       LilyPond-like syntax in scheme for building markups, in order to
+       help markup command definition. (Nicolas Sceaux)
+
+       * input/test/lyrics-skip-notes.ly: new example.
+
+       * lily/parser.yy (post_event): make HYPHEN into postfix event.
+
+       * lily/new-lyric-combine-music-iterator.cc (find_context_below):
+       use is_alias() iso. == . This fixes lyrics on
+       GregorianTranscriptions. 
+
 2004-02-02  Mats Bengtsson  <mabe@drongo.s3.kth.se>
 
        * scripts/lilypond.py (ly_paper_to_latexpaper): Add newline before 
 
 2004-01-26  Han-Wen Nienhuys   <hanwen@xs4all.nl>
 
+       * VERSION: release 2.1.15
+       
        * lily/lyric-phrasing-engraver.cc (stop_translation_timestep):
        align all stanza numbers.
 
index 8207622508e2fbf5f0fcd589ecf171822d462da8..f5cc974212fbaecc9197005799a7599a123fba66 100644 (file)
@@ -17,6 +17,9 @@ Version 2.1.13
 @end ignore
 
 @itemize @bullet
+@item Voice names, for vocal lines, have been added. They are similar
+to instrument names.   They can be set by defining @code{vocalName}
+and @code{vocNam}.
 
 @item Safe mode has been reinstated for lilypond.
 When lilypond is invoked with @code{--safe-mode}, @TeX{} and
index 2f9424b47aa62cacaf75617bb0ab538f433902f6..72ca9ddaa2b6a2221110691b014fb3977c9612c4 100644 (file)
@@ -132,7 +132,8 @@ to generate titling; an example demonstrating all these fields is in
 @item footer
     A text to print in the footer of all but the last page.
 @item tagline
-    Line to print at the bottom of last page. The default text is ``Engraved by LilyPond @var{version-number}''.
+    Line to print at the bottom of last page. The default text is ``Engraved
+by LilyPond @var{version-number}''.
 @end table
 
 
index 88f621bd4e1b8c39cfd209a7e1fce2ca12cc31e7..a8069755155b74fba2e03d4987e7f9be50c488dd 100644 (file)
@@ -3536,15 +3536,16 @@ A complete example of a SATB score setup is in the file
 
 @seealso
 
-Internals: @internalsref{LyricCombineMusic}, @internalsref{Lyrics},
-@internalsref{Melisma_engraver}.
+Internals: Music expressions: @internalsref{LyricCombineMusic},
+Contexts: @internalsref{LyricsVoice}, @internalsref{Melisma_engraver}.
 
 Examples: @inputfileref{input/template,satb.ly},
 @inputfileref{input/regression,lyric-combine-new.ly}.
  
 @refbugs
 
-Melismata are not detected automatically, and must be inserted by hand.
+Melismata are not detected automatically, and extender lines must be
+inserted by hand.
 
 
 @node More stanzas
@@ -3607,12 +3608,17 @@ prevent @code{LyricsVoice.stanza} being interpreted as a single
 string.
 
 Names of the singers should be added using @code{LyricsVoice
-. instrument} and @code{LyricsVoice . instr}, analogous to instrument
+. vocalName} and @code{LyricsVoice . vocNam}, analogous to instrument
 annotations for staves.
  
 To make empty spaces in lyrics, use @code{\skip}.
 
 
+@seealso
+
+Internals: Layout objects @internalsref{LyricText}
+@internalsref{VocalName}.  Music expressions:
+@internalsref{LyricEvent}.
 
 @refbugs
 
@@ -3634,6 +3640,8 @@ making or a music identifier @code{\foo} containing the syllable
 @end example
 
 
+
+
 @node Ambitus
 @subsection Ambitus
 @cindex ambitus
diff --git a/VERSION b/VERSION
index c0480ca46d65dd75a8874460a4044fa355b289d1..c26ba763d526c8c2c28fc9ca3e33da9a3005cbc1 100644 (file)
--- a/VERSION
+++ b/VERSION
@@ -2,5 +2,5 @@ PACKAGE_NAME=LilyPond
 MAJOR_VERSION=2
 MINOR_VERSION=1
 PATCH_LEVEL=16
-MY_PATCH_LEVEL=
+MY_PATCH_LEVEL=hwn1
 
index fffacd9c7daf72b9ca6b6a65dd7c358e273e6dec..41a9ccfe6eeb32bdfb14065ed1a9b832bdca4dc3 100644 (file)
@@ -1,9 +1,9 @@
 \version "2.1.10"
 \header {
 
-    texidoc = "With the newaddlyrics mechanism, individual lyric lines
-    can be associated with one melody line. For each lyric line, can
-    be tuned whether to follow melismata or not."
+    texidoc = "With the @code{\\lyricsto} mechanism, individual lyric
+    lines can be associated with one melody line. For each lyric line,
+    can be tuned whether to follow melismata or not."
     
 }
 
diff --git a/input/test/lyrics-skip-notes.ly b/input/test/lyrics-skip-notes.ly
new file mode 100644 (file)
index 0000000..4673ea5
--- /dev/null
@@ -0,0 +1,23 @@
+
+\header
+{
+texidoc ="
+
+By inserting @code{\\skip} statements into lyric lines, one can put less lyric syllables to a melody. 
+
+"
+}
+
+
+% shorthand for Skip Lyric
+sl = \notes { \skip 4 }
+
+\version "2.1.16"
+\score {
+  <<
+  \context Voice = "A"  \notes  {c4 c c c}
+  \lyricsto "A" \context LyricsVoice=A \lyrics { foo __ \sl \sl bar }
+  \lyricsto "A" \context LyricsVoice=B \lyrics { foo -- \sl baz bar }
+  \lyricsto "A" \context LyricsVoice=C \lyrics { foo -- baz -- baaz bar }
+  >>
+}
index 8e14ca48e366ee4bf659c604e80744dece21c122..fb83dc407fbe809c412ba69a9c567b38ed30a023 100644 (file)
@@ -2,32 +2,22 @@
   hyphen-engraver.cc -- implement Hyphen_engraver
 
   source file of the GNU LilyPond music typesetter
-
-  (c)  1999--2003 Glen Prideaux <glenprideaux@iname.com>
+  
+  (c)  1999--2003 Glen Prideaux <glenprideaux@iname.com>,
+                  Han-Wen Nienhuys <hanwen@cs.uu.nl>,
+                  Jan Nieuwenhuizen <janneke@gnu.org>
 */
 
-#include "flower-proto.hh"
-#include "event.hh"
+#include "warn.hh"
 #include "hyphen-spanner.hh"
-#include "paper-column.hh"
 #include "item.hh"
 #include "engraver.hh"
 
-/**
-  Generate an centred hyphen.  Should make a Hyphen_spanner that
-  typesets a nice centred hyphen of varying length depending on the
-  gap between syllables.
-
-  We remember the last Item that come across. When we get a
-  event, we create the spanner, and attach the left point to the
-  last lyrics, and the right point to any lyrics we receive by
-  then.  */
 class Hyphen_engraver : public Engraver
 {
-  Grob *last_lyric_;
-  Grob *current_lyric_;
-  Music* req_;
+  Music* ev_;
   Spanner* hyphen_;
+  Spanner * finished_hyphen_;  
 public:
   TRANSLATOR_DECLARATIONS(Hyphen_engraver);
 
@@ -36,33 +26,33 @@ protected:
   virtual void finalize ();
   virtual bool try_music (Music*);
   virtual void stop_translation_timestep ();
-  virtual void process_acknowledged_grobs ();
+  virtual void process_music ();
 private:
 
 };
 
 
 
+
 Hyphen_engraver::Hyphen_engraver ()
 {
-  current_lyric_ = 0;
-  last_lyric_ = 0;
   hyphen_ = 0;
-  req_ = 0;
+  finished_hyphen_ = 0;
+  ev_ = 0;
 }
 
 void
 Hyphen_engraver::acknowledge_grob (Grob_info i)
 {
-  // -> text-item
-  if (i.grob_->internal_has_interface (ly_symbol2scm ("lyric-syllable-interface")))
+  Item * item =  dynamic_cast<Item*> (i.grob_);
+  // -> text_item
+  if (item && item->internal_has_interface (ly_symbol2scm ("lyric-syllable-interface")))
     {
-      current_lyric_ = i.grob_;
-      if (hyphen_
-         && !hyphen_->get_bound (RIGHT))
-         {
-           hyphen_->set_bound (RIGHT, i.grob_);
-         }
+      if (hyphen_)
+       hyphen_->set_bound (LEFT, item);
+
+      if (finished_hyphen_)
+       finished_hyphen_->set_bound (RIGHT, item);
     }
 }
 
@@ -70,38 +60,61 @@ Hyphen_engraver::acknowledge_grob (Grob_info i)
 bool
 Hyphen_engraver::try_music (Music* r)
 {
-  if (req_)
-       return false;
+  if (ev_)
+    return false;
 
-      req_ = r;
-      return true;
+  ev_ = r;
+  return true;
+}
+
+void
+completize_hyphen (Spanner* sp)
+{
+  if (!sp->get_bound (RIGHT))
+    {
+      SCM heads = sp->get_grob_property ("heads");
+      if (gh_pair_p (heads))
+       {
+         Item* it = dynamic_cast<Item*> (unsmob_grob (gh_car (heads)));
+         if (it)
+           sp->set_bound (RIGHT, it);
+       }
+    }
 }
 
+  
+
 void
 Hyphen_engraver::finalize ()
 {
   if (hyphen_)
     {
-      req_->origin ()->warning (_ ("unterminated hyphen"));
-      hyphen_->set_bound (RIGHT, unsmob_grob (get_property ("currentCommandColumn")));
+      completize_hyphen (hyphen_);
+
+      if (!hyphen_->get_bound (RIGHT))
+       hyphen_->warning (_ ("unterminated hyphen"));
+      typeset_grob (hyphen_);
+      hyphen_ = 0;
+    }
+
+  if (finished_hyphen_)
+    {
+      completize_hyphen (finished_hyphen_);
+
+      if (!finished_hyphen_->get_bound (RIGHT))
+         finished_hyphen_->warning (_("unterminated hyphen"));
+      typeset_grob (finished_hyphen_);
+      finished_hyphen_ =0;
     }
 }
 
 void
-Hyphen_engraver::process_acknowledged_grobs ()
+Hyphen_engraver::process_music ()
 {
-  if (req_ &&! hyphen_)
+  if (ev_)
     {
-      if (!last_lyric_)
-       {
-         req_->origin ()->warning (_ ("Nothing to connect hyphen to on the left.  Ignoring hyphen event."));
-         return;
-       }
-      
       hyphen_ = make_spanner ("LyricHyphen");
-
-      hyphen_->set_bound (LEFT, last_lyric_);
-      announce_grob(hyphen_, req_->self_scm());
+      announce_grob (hyphen_, ev_->self_scm());
     }
 }
 
@@ -109,21 +122,29 @@ Hyphen_engraver::process_acknowledged_grobs ()
 void
 Hyphen_engraver::stop_translation_timestep ()
 {
-  if (hyphen_)
+  if (finished_hyphen_ && finished_hyphen_->get_bound (RIGHT))
     {
-      typeset_grob (hyphen_);
-      hyphen_ = 0;
+      typeset_grob (finished_hyphen_);
+      finished_hyphen_ = 0;
     }
 
-  if (current_lyric_)
+  if (finished_hyphen_ && hyphen_)
     {
-      last_lyric_ = current_lyric_;
-      current_lyric_ =0;
+      programming_error ("Haven't finished hyphen yet.");
+      typeset_grob (finished_hyphen_);
+      finished_hyphen_ =0;
     }
-  req_ = 0;
+  
+  if (hyphen_)
+    finished_hyphen_ = hyphen_;
+  hyphen_ = 0;
+
+  ev_ = 0;
 }
 
 
+
+
 ENTER_DESCRIPTION(Hyphen_engraver,
 /* descr */       "Create lyric hyphens",
 /* creats*/       "LyricHyphen",
index b5d0729108c5381cb2cef56b4bda519aa1546380..1e8356d6dd5884eb01f236bffc9da28b0ab3327b 100644 (file)
@@ -71,6 +71,7 @@ New_lyric_combine_music_iterator::start_new_syllable ()
   if (!b)
     return false;
 
+  /* FIXME: this is wrong use of construct_children () */
   if (!lyrics_context_)
     construct_children ();
   
@@ -135,7 +136,7 @@ Translator_group *
 find_context_below (Translator_group * where,
                    String type, String id)
 {
-  if (where->context_name () == type)
+  if (where->is_alias (ly_symbol2scm (type.to_str0 ())))
     {
       if (id == "" || where->id_string_ == id)
        return where;
@@ -147,7 +148,6 @@ find_context_below (Translator_group * where,
     {
       Translator_group * tr = dynamic_cast<Translator_group*> (unsmob_translator (gh_car (s)));
 
-      
       found = find_context_below (tr, type, id);
     }
 
index c22c66a42575b989c01ced4da9862181e139751e..72d4de1ed3c9441053307cf18f42f33a0578cb7f 100644 (file)
@@ -390,7 +390,6 @@ yylex (YYSTYPE *s,  void * v)
 %type <music> shorthand_command_req
 %type <music>  post_event tagged_post_event
 %type <music> command_req verbose_command_req
-%type <music> hyphen_req
 %type <music> string_number_event
 %type <scm>    string bare_number number_expression number_term number_factor 
 %type <score>  score_block score_body
@@ -1425,10 +1424,7 @@ command_req:
        ;
 
 shorthand_command_req:
-       hyphen_req {
-               $$ = $1;
-       }
-       | BREATHE {
+       BREATHE {
                $$ = MY_MAKE_MUSIC("BreathingSignEvent");
        }
        | E_TILDE {
@@ -1499,6 +1495,11 @@ post_event:
        direction_less_event {
                $$ = $1;
        }
+       | HYPHEN {
+               if (!THIS->lexer_->lyric_state_b ())
+                       THIS->parser_error (_ ("Have to be in Lyric mode for lyrics"));
+               $$ = MY_MAKE_MUSIC("HyphenEvent");
+       }
        | EXTENDER {
                if (!THIS->lexer_->lyric_state_b ())
                        THIS->parser_error (_ ("Have to be in Lyric mode for lyrics"));
@@ -1664,13 +1665,6 @@ pitch_also_in_chords:
        | steno_tonic_pitch
        ;
 
-hyphen_req:
-       HYPHEN {
-               if (!THIS->lexer_->lyric_state_b ())
-                       THIS->parser_error (_ ("Have to be in Lyric mode for lyrics"));
-               $$ = MY_MAKE_MUSIC("HyphenEvent");
-       }
-       ;
 
 close_event:
        '('     {
index 6d83c4278f02f338db9a1bb9357082113dec9a08..3f2340989dc573bb8a6c755d36f9e822f45b5045 100644 (file)
@@ -21,6 +21,7 @@
        (cautionary-style . parentheses)
        (after-line-breaking-callback . ,Accidental_interface::after_line_breaking)             (meta . ((interfaces . (item-interface accidental-interface font-interface))))
        ))
+    
     (AccidentalPlacement
      . (
        (X-extent-callback . ,Axis_group_interface::group_extent_callback)
@@ -28,7 +29,7 @@
 
        ;; this is quite small, but it is very ugly to have
        ;; accs closer to the previous note than to the next one.
-       (right-padding . 0.2)
+       (right-padding . 0.25)
        (meta . ((interfaces . (item-interface accidental-placement-interface))))
        ))
 
index 06356aa9854cc4c0999fc9d87926b68ff44f63b7..4aa774a692202bb84f3ff08ca51a82dc556dc3b6 100644 (file)
@@ -82,6 +82,126 @@ against SIGNATURE, reporting MAKE-NAME as the user-invoked function.
                    error-msg #f)
         (cons markup-function args))))
 
+;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; markup constructors
+;;; lilypond-like syntax for markup construction in scheme.
+
+(use-modules (ice-9 optargs)
+             (ice-9 receive))
+
+(defmacro*-public markup (#:rest body)
+  "The `markup' macro provides a lilypond-like syntax for building markups.
+
+ - #:COMMAND is used instead of \\COMMAND
+ - #:lines ( ... ) is used instead of { ... }
+ - #:center ( ... ) is used instead of \\center < ... >
+ - etc.
+
+Example:
+  \\markup { foo
+            \\raise #0.2 \\hbracket \\bold bar
+            \\override #'(baseline-skip . 4)
+            \\bracket \\column < baz bazr bla >
+  }
+         <==>
+  (markup \"foo\"
+          #:raise 0.2 #:hbracket #:bold \"bar\"
+          #:override '(baseline-skip . 4) 
+          #:bracket #:column (\"baz\" \"bazr\" \"bla\"))
+Use `markup*' in a \\notes block."
+  
+  (car (compile-all-markup-expressions `(#:line ,body))))
+
+(defmacro*-public markup* (#:rest body)
+  "Same as `markup', for use in a \\notes block."
+  `(ly:export (markup ,@body)))
+  
+  
+(define (compile-all-markup-expressions expr)
+  "Return a list of canonical markups expressions, eg:
+  (#:COMMAND1 arg11 arg12 #:COMMAND2 arg21 arg22 arg23)
+  ===>
+  ((make-COMMAND1-markup arg11 arg12)
+   (make-COMMAND2-markup arg21 arg22 arg23) ...)"
+  (do ((rest expr rest)
+       (markps '() markps))
+      ((null? rest) (reverse markps))
+    (receive (m r) (compile-markup-expression rest)
+             (set! markps (cons m markps))
+             (set! rest r))))
+
+(define (keyword->make-markup key)
+  "Transform a keyword, eg. #:COMMAND, in a make-COMMAND-markup symbol."
+  (string->symbol (string-append "make-" (symbol->string (keyword->symbol key)) "-markup")))
+
+(define (compile-markup-expression expr)
+  "Return two values: the first complete canonical markup expression found in `expr',
+eg (make-COMMAND-markup arg1 arg2 ...), and the rest expression."
+  (cond ((and (pair? expr)
+              (keyword? (car expr)))
+         ;; expr === (#:COMMAND arg1 ...)
+         (let* ((command (symbol->string (keyword->symbol (car expr))))
+                (sig (markup-command-signature (car (lookup-markup-command command))))
+                (sig-len (length sig)))
+           (do ((i 0 (1+ i))
+                (args '() args)
+                (rest (cdr expr) rest))
+               ((>= i sig-len)
+                (values (cons (keyword->make-markup (car expr)) (reverse args)) rest))
+             (cond ((eqv? (list-ref sig i) markup-list?)
+                    ;; (car rest) is a markup list
+                    (set! args (cons `(list ,@(compile-all-markup-expressions (car rest))) args))
+                    (set! rest (cdr rest)))
+                   (else
+                    ;; pick up one arg in `rest'
+                    (receive (a r) (compile-markup-arg rest)
+                             (set! args (cons a args))
+                             (set! rest r)))))))
+        ((and (pair? expr)
+              (pair? (car expr))
+              (keyword? (caar expr)))
+         ;; expr === ((#:COMMAND arg1 ...) ...)
+         (receive (m r) (compile-markup-expression (car expr))
+                  (values m (cdr expr))))
+        (else
+         ;; expr === (symbol ...) or ("string" ...) or ((funcall ...) ...)
+         (values (car expr)
+                 (cdr expr)))))
+
+(define (compile-all-markup-args expr)
+  "Transform `expr' into markup arguments"
+  (do ((rest expr rest)
+       (args '() args))
+      ((null? rest) (reverse args))
+    (receive (a r) (compile-markup-arg rest)
+             (set! args (cons a args))
+             (set! rest r))))
+
+(define (compile-markup-arg expr)
+  "Return two values: the desired markup argument, and the rest arguments"
+  (cond ((null? expr)
+         ;; no more args
+         (values '() '()))
+        ((keyword? (car expr))
+         ;; expr === (#:COMMAND ...)
+         ;; ==> build and return the whole markup expression
+         (compile-markup-expression expr))
+        ((and (pair? (car expr))
+              (keyword? (caar expr)))
+         ;; expr === ((#:COMMAND ...) ...)
+         ;; ==> build and return the whole markup expression(s)
+         ;; found in (car expr)
+         (receive (markup-expr rest-expr) (compile-markup-expression (car expr))
+                  (if (null? rest-expr)
+                      (values markup-expr (cdr expr))
+                      (values `(list ,markup-expr ,@(compile-all-markup-args rest-expr))
+                              (cdr expr)))))
+        ((and (pair? (car expr))
+              (pair? (caar expr)))
+         ;; expr === (((foo ...) ...) ...)
+         (values (cons 'list (compile-all-markup-args (car expr))) (cdr expr)))
+        (else (values (car expr) (cdr expr)))))
+
 ;;;;;;;;;;;;;;;
 ;;; Utilities for storing and accessing markup commands signature
 ;;; and keyword.