+2005-03-08 Jan Nieuwenhuizen <janneke@gnu.org>
+
+ * Documentation/topdocs/NEWS.tely (Top): Mention markup text feature.
+
+ * scripts/lilypond-book.py (PREAMBLE_LY): toplevel-music-handler:
+ Add texts parameter.
+
2005-03-07 Jan Nieuwenhuizen <janneke@gnu.org>
+ * lily/lexer.ll (lyric_markup): New mode.
+ (Lily_lexer::push_lyric_markup_state): New method.
+ (MARKUPCOMMAND): Markup during lyric mode returns LYRIC_MARKUP.
+
+ * lily/parser.yy (book_body):
+ (toplevel_expression): Grok \markup texts.
+
+ * lily/score-scheme.cc (ly:music-scorify):
+ * scm/lily-library.scm (collect-music-for-book): Take texts
+ parameter.
+
+ * lily/score.cc (texts_): New member.
+
+ * lily/paper-book.cc (systems): Format score texts.
+
+ * score-text.ly: New file.
+
* ttftool/SConscript:
* kpath-guile/SConscript: New file.
@setfilename NEWS.info
@settitle NEWS
-
-
-@node Top, , ,
-@top
-@unnumbered New features in 2.5 since 2.4
-
@ifhtml
@macro inputfileref{DIR,NAME}
@uref{../../../\DIR\/out-www/collated-files.html#\NAME\,@file{\DIR\/\NAME\}}@c
+@node Top, , ,
+@top
+@unnumbered New features in 2.5 since 2.4
+
+
@itemize @bullet
+
+@item
+Markup texts can be appended to a @code{\score} block or toplevel
+music expression, for example,
+
+@lilypond[verbatim,relative=1,raggedright]
+\relative { c' d e }
+\markup { first text }
+\markup { second text }
+@end lilypond
+
+See @inputfileref{input/regression,score-text.ly}.
+
+
@item
@TeX{}'s @code{kpathsea} library is loaded dynamically, so installing
LilyPond does not require installing @TeX{} anymore.
Score_systems sc;
sc.systems_ = systems;
sc.header_ = scores_[i]->header_;
+ sc.texts_ = scores_[i]->texts_;
paper_book->score_systems_.push (sc);
}
}
void push_figuredbass_state ();
void push_lyric_state ();
void push_initial_state ();
+ void push_lyric_markup_state ();
void push_markup_state ();
void push_note_state (SCM tab);
void pop_state ();
Music *make_music_by_name (SCM sym);
SCM ly_music_deep_copy (SCM);
-SCM ly_music_scorify (SCM, SCM);
+SCM ly_music_scorify (SCM, SCM, SCM);
#endif /* MUSIC_HH */
{
SCM systems_;
SCM header_;
+ SCM texts_;
Score_systems () ;
void gc_mark ();
String user_key_;
Link_array<Output_def> defs_;
SCM header_;
+ SCM texts_;
bool error_found_;
SCM get_music () const;
SCM ly_run_translator (SCM, SCM, SCM);
SCM ly_render_output (SCM, SCM);
-void default_rendering (SCM, SCM, SCM, SCM, SCM, SCM);
+void default_rendering (SCM, SCM, SCM, SCM, SCM, SCM, SCM);
#endif /* SCORE_HH */
%x figures
%x incl
%x lyrics
+%x lyric_markup
%x lyric_quote
%x longcomment
-%x markup
+%x markup
%x notes
%x quote
%x renameinput
// windows-suck-suck-suck
}
-<INITIAL,chords,incl,markup,lyrics,notes,figures>{
+<INITIAL,chords,figures,incl,lyrics,lyric_markup,markup,notes>{
"%{" {
yy_push_state (longcomment);
}
<chords,notes,figures>R {
return MULTI_MEASURE_REST;
}
-<INITIAL,markup,chords,lyrics,notes,figures># { //embedded scm
+<INITIAL,chords,figures,lyrics,lyric_markup,markup,notes># { //embedded scm
int n = 0;
Input hi = here_input();
hi.step_forward ();
}
-<markup>{
+<markup,lyric_markup>{
\" {
start_quote ();
}
yy_push_state (markup);
}
+void
+Lily_lexer::push_lyric_markup_state ()
+{
+ yy_push_state (lyric_markup);
+}
+
void
Lily_lexer::push_note_state (SCM tab)
{
// SCM sym = ly_symbol2scm (str.to_str0 ());
- int l = lookup_keyword (str);
- if (l != -1) {
- return l;
- }
+ int i = lookup_keyword (str);
+ if (i == MARKUP && is_lyric_state ())
+ return LYRIC_MARKUP;
+ if (i != -1)
+ return i;
+
SCM sid = lookup_identifier (str);
if (is_music_function (sid))
{
yylval.scm = get_music_function_transform (sid);
-
return music_function_type (yylval.scm);
}
SCM paper = get_paper (parser)->self_scm ();
for (int i = 0; i < score->defs_.size (); i++)
default_rendering (score->get_music (), score->defs_[i]->self_scm (),
- paper,
- header, os,
- key->self_scm ());
+ paper, header, score->texts_,
+ os, key->self_scm ());
if (score->defs_.is_empty ())
{
Output_def *layout = get_layout (parser);
default_rendering (score->get_music(), layout->self_scm (),
get_paper (parser)->self_scm (),
- header, os, key->self_scm ());
+ header, score->texts_,
+ os, key->self_scm ());
scm_gc_unprotect_object (layout->self_scm ());
}
#include "output-def.hh"
#include "paper-score.hh"
#include "paper-system.hh"
+#include "text-item.hh"
#include "warn.hh"
#include "ly-smobs.icc"
systems_ = scm_cons (ps->self_scm (), systems_);
scm_gc_unprotect_object (ps->self_scm ());
}
+
+ SCM page_properties = scm_call_1 (ly_lily_module_constant ("page-properties"),
+ paper_->self_scm ());
int score_count = score_systems_.size ();
for (int i = 0; i < score_count; i++)
system_list = scm_reverse (system_list);
systems_ = scm_append (scm_list_2 (system_list, systems_));
}
+
+ for (SCM s = score_systems_[i].texts_; s != SCM_EOL; s = scm_cdr (s))
+ {
+ SCM t = Text_interface::interpret_markup (paper_->self_scm (),
+ page_properties,
+ scm_car (s));
+ // FIXME: title=true?
+ Paper_system *ps = new Paper_system (*unsmob_stencil (t), true);
+ systems_ = scm_cons (ps->self_scm (), systems_);
+ scm_gc_unprotect_object (ps->self_scm ());
+ // FIXME: figure out penalty.
+ //set_system_penalty (ps, score_systems_[i].header_);
+ }
}
systems_ = scm_reverse (systems_);
{
systems_ = SCM_EOL;
header_ = SCM_EOL;
+ texts_ = SCM_EOL;
}
void
{
scm_gc_mark (systems_);
scm_gc_mark (header_);
+ scm_gc_mark (texts_);
}
%}
-%expect 3
+%expect 1
-/*
- Three shift/reduce problems:
-
-2. \markup identifier.
-
- (what? --hwn)
-
-3. \markup { }
+/* One shift/reduce problem
- (what? --hwn)
-
-
-4. \repeat
+1. \repeat
\repeat .. \alternative
-
\repeat { \repeat .. \alternative }
or
\repeat { \repeat } \alternative
-
-)
- */
+*/
%pure_parser
%token KEY
%token LAYOUT
%token LYRICS
+%token LYRIC_MARKUP
%token LYRICMODE
%token MARK
%token MIDI
%token <scm> MARKUP_HEAD_SCM0_SCM1
%token <scm> MARKUP_HEAD_SCM0_SCM1_MARKUP2
%token <scm> MARKUP_HEAD_SCM0_SCM1_SCM2
-%token <scm> MARKUP_IDENTIFIER MARKUP_HEAD_LIST0
+%token <scm> LYRIC_MARKUP_IDENTIFIER MARKUP_IDENTIFIER MARKUP_HEAD_LIST0
%token <scm> MUSIC_FUNCTION
%token <scm> MUSIC_FUNCTION_MUSIC
%token <scm> MUSIC_FUNCTION_MUSIC_MUSIC
%type <scm> Generic_prefix_music_scm
%type <scm> lyric_element
%type <scm> Alternative_music
-%type <scm> full_markup markup_list markup_composed_list markup_braced_list markup_braced_list_body
+%type <scm> full_markup lyric_markup
+%type <scm> markup_list markup_composed_list markup_braced_list markup_braced_list_body
+%type <scm> optional_text
%type <scm> markup_head_1_item markup_head_1_list markup simple_markup markup_top
%type <scm> mode_changing_head
%type <scm> mode_changing_head_with_context
scm_call_2 (proc, THIS->self_scm (), score->self_scm ());
scm_gc_unprotect_object (score->self_scm ());
}
- | toplevel_music {
+ | toplevel_music optional_text {
Music *music = $1;
SCM proc = THIS->lexer_->lookup_identifier ("toplevel-music-handler");
- scm_call_2 (proc, THIS->self_scm (), music->self_scm ());
+ scm_call_3 (proc, THIS->self_scm (), music->self_scm (), $2);
scm_gc_unprotect_object (music->self_scm ());
}
| output_def {
}
;
+optional_text:
+ /* empty */ {
+ $$ = SCM_EOL
+ }
+ | optional_text full_markup {
+ $$ = ly_snoc ($2, $1);
+ }
+ ;
/*
DECLARATIONS
$$->paper_ = $2;
scm_gc_unprotect_object ($2->self_scm ());
}
- | book_body score_block {
+ | book_body score_block optional_text {
Score *score = $2;
+ score->texts_ = $3;
$$->add_score (score);
}
+ /* let's do optional
+ | book_body full_markup {
+ if (!$$->scores_.size ())
+ THIS->parser_error (@2, _("\\markup cannot be used before \\score."));
+ Score *score = $$->scores_.top ();
+ score->texts_ = ly_snoc ($2, score->texts_);
+ }
+ */
| book_body lilypond_header {
$$->header_ = $2;
}
;
lyric_element:
- /* FIXME: lyric flavoured markup would be better */
- full_markup {
+ lyric_markup {
$$ = $1;
}
| LYRICS_STRING {
This should be done more dynamically if possible.
*/
+lyric_markup:
+ LYRIC_MARKUP_IDENTIFIER {
+ $$ = $1;
+ }
+ | LYRIC_MARKUP
+ { THIS->lexer_->push_lyric_markup_state (); }
+ markup_top {
+ $$ = $3;
+ THIS->lexer_->pop_state ();
+ }
+ ;
+
full_markup:
MARKUP_IDENTIFIER {
$$ = $1;
| MARKUP_IDENTIFIER {
$$ = $1;
}
+ | LYRIC_MARKUP_IDENTIFIER {
+ $$ = $1;
+ }
| STRING_IDENTIFIER {
$$ = $1;
}
return OUTPUT_DEF_IDENTIFIER;
} else if (Text_interface::markup_p (sid)) {
*destination = sid;
+ if (is_lyric_state ())
+ return LYRIC_MARKUP_IDENTIFIER;
return MARKUP_IDENTIFIER;
}
#include "global-context.hh"
LY_DEFINE (ly_music_scorify, "ly:music-scorify",
- 2, 0, 0,
- (SCM music, SCM parser),
- "Return MUSIC encapsulated in SCORE.")
+ 3, 0, 0,
+ (SCM music, SCM texts, SCM parser),
+ "Return MUSIC with TEXTS encapsulated in SCORE.")
{
#if 0
SCM_ASSERT_TYPE (ly_c_music_p (music), music, SCM_ARG1, __FUNCTION__, "music");
Score *score = new Score;
score->set_music (music, parser);
+ score->texts_ = texts;
scm_gc_unprotect_object (score->self_scm ());
return score->self_scm ();
: Input ()
{
header_ = SCM_EOL;
+ texts_ = SCM_EOL;
music_ = SCM_EOL;
error_found_ = false;
smobify_self ();
if (sc->header_)
scm_gc_mark (sc->header_);
+ if (sc->texts_)
+ scm_gc_mark (sc->texts_);
for (int i = sc->defs_.size (); i--;)
scm_gc_mark (sc->defs_[i]->self_scm ());
return sc->music_;
/* FIXME: SCM_EOL? */
header_ = 0;
+ texts_ = 0;
smobify_self ();
header_ = ly_make_anonymous_module (false);
if (ly_c_module_p (s.header_))
ly_module_copy (header_, s.header_);
+
+ if (s.texts_)
+ texts_ = s.texts_;
}
void
default_rendering (SCM music, SCM outdef,
SCM book_outputdef,
- SCM header, SCM outname,
+ SCM header, SCM texts,
+ SCM outname,
SCM key)
{
SCM scaled_def = outdef;
Score_systems sc;
sc.systems_ = systems;
sc.header_ = header;
+ sc.texts_ = texts;
paper_book->score_systems_.push (sc);
head score)))
(ly:parser-print-score parser book)))
-(define-public (collect-scores-for-book parser score)
+(define-public (collect-scores-for-book parser score)
(ly:parser-define
parser 'toplevel-scores
(cons score (ly:parser-lookup parser 'toplevel-scores))))
-(define-public (collect-music-for-book parser music)
- (collect-scores-for-book parser (ly:music-scorify music parser)))
+(define-public (collect-music-for-book parser music texts)
+ (collect-scores-for-book parser (ly:music-scorify music texts parser)))
(define (markup-function? x)
(not (not (markup-command-signature x))))
-(define (markup-list? arg)
+(define-public (markup-list? arg)
(define (markup-list-inner? lst)
(or (null? lst)
(and (markup? (car lst)) (markup-list-inner? (cdr lst)))))
%%%% Options: [%(option_string)s]
#(set! toplevel-score-handler ly:parser-print-score)
-#(set! toplevel-music-handler (lambda (p m)
+#(set! toplevel-music-handler (lambda (p m t)
(ly:parser-print-score
- p (ly:music-scorify m p))))
+ p (ly:music-scorify m t p))))
#(define version-seen? #t)
%(preamble_string)s