To keep track of all patches submitted for testing and review. This
includes scanning the bug and dev email lists looking for any patches
submitted by @q{random} contributors and advising them on how to submit
-a patch for testing and review. See @ref{Patches}.
+a patch for testing and review. See @ref{Uploading a patch for review}
+and @ref{The patch review cycle}.
@item
To makes sure that any patch submitted has a corresponding Issue Tracker
@end enumerate
-
@node Patch handling
@section Patch handling
separate person handling this task.}
For contributors/developers: follow the steps in
-@ref{Commits}, @ref{Patches}, and @ref{Pushing to staging}.
+@ref{Patches}, and @ref{Pushing to staging}.
@ignore
For people doing maintenance tasks: git-cl is adding issues, James
-is testing them, Colin is selecting them for countdowns, and
-Patchy is merging from staging to master. In the coming weeks,
-these tasks will be more and more automated.
-@end ignore
-
-@subheading Patch cycle
-
-@itemize
-
-@item
-Patches get added to the tracker and to Rietveld by the @qq{git-cl} tool, with
-a status of @qq{patch-new}.
-
-@item
-The automated tester, Patchy, verifies that the patch can be applied
-to current master. By default, it checks that the patch allows @code{make}
-and @code{make test} to complete successfully. It can also be configured to
-check that @code{make doc} is successful. If it passes, Patchy changes the
-status to @qq{patch-review} and emails the developer list. If the patch
-fails, Patchy sets it to @qq{patch-needs_work} and notifies the developer list.
-
-@item
-The Patch Meister reviews the tracker periodically, to list patches
-which have been on review for at least 24 hours. The list is found at
-
-@smallexample
-@uref{http://code.google.com/p/lilypond/issues/list?can=2&q=label:patch%20patch=review&sort=modified+patch&colspec=ID%20Type%20Status%20Priority%20Owner%20Patch%20Summary%20Modified}
-@end smallexample
-
-@item
-For each patch, the Handler reviews any discussion on the tracker
-and on Rietveld, to determine whether the patch can go forward. If
-there is any indication that a developer thinks the patch is not
-ready, the Handler marks it @qq{patch-needs_work} and makes a comment
-regarding the reason, referring to the Rietveld item if needed.
-
-@item
-Patches with explicit approval, or at least no negative comment, can
-be updated to @qq{patch-countdown}. When saving the tracker item,
-clear the @qq{send email} box to prevent sending notification for
-each patch.
-
-@item
-The Patch Meister sends an email to the developer list, with a fixed
-subject line, to enable filtering by email clients:
-
-@example
-PATCH: Countdown to 20130113
-@end example
-
-The text of the email sets the deadline for this countdown batch. At
-present, batches are done on Tuesday, Thursday and Sunday evenings.
-
-To create the countdown announcement, use the
-@code{make-countdown-announcement.sh} script, which takes the
-deadline date, and optionally your name. Follow the instructions
-provided:
-
-@example
-cd $LILYPOND_GIT
-scripts/auxiliar/make-countdown-announcement.sh "Jan 1, 2001" James
-@end example
-
-The script produces an announcement that is easily readable in all
-email clients. Also, whenever a new contributor submits a patch,
-you will be prompted to add the new username and author name to
-the script itself, and then commit those changes to the main git
-repository.
-
-
-@item
-On the scheduled countdown day, the Patch Meister reviews the
-previous list of patches on countdown, with the same procedure and
-criteria as before. Patches with no controversy can be set to
-@qq{patch-push} with a courtesy message added to the comment block.
-
-@item
-Roughly at six month intervals, the Patch Meister can list the
-patches which have been set to @qq{patch-needs-work} and send the
-results to the developer list for review. In most cases, these
-patches should be marked @qq{patch-abandoned} but this should come
-from the developer if possible.
-
-@item
-As in most organisations of unpaid volunteers, fixed procedures are
-useful in as much as they get the job done. In our community, there
-is room for senior developers to bypass normal patch handling flows,
-particularly now that the testing of patches is largely automated.
-Similarly, the minimum age of 24 hours can reasonably be waived if
-the patch is minor and from an experienced developer.
-
-
-@end itemize
-
-@ignore
-There is a single Patch Meister, and a number of Patch Helpers
-(rename this?). The list of known patches awaiting review is:
-
-@example
-@uref{http://code.google.com/p/lilypond/issues/list?can=2&q=label:patch&sort=patch}
-@end example
-
-
-@subheading Helpers: adding patches
-
-The primary duty is to add patches to the google tracker; we have
-a bad track record of losing patches in email. Patches generally
-come to the @code{lilypond-devel} mailing list, but are sometimes
-sent to @code{bug-lilypond}, @code{lilypond-users}, or
-@code{frogs} mailing list instead.
-
-@itemize
-@item
-Unless a patch is clearly in response to an existing issue, add a
-new issue with the @code{Patch-new} label and a link to the patch
-(either on the mailing list archives or the codereview url).
-
-Issue numbers are cheap; losing developers because they got fed up
-with us losing their hard work is expensive.
-
-@end ignore
-@c if we enter patches immediately, I don't think this is relevant.
-@ignore
-@item
-Before adding a patch-reminder issue, do a quick check to see if
-it was pushed without sending any email. This can be checked for
-searching for relevant terms (from the patch subject or commit
-message) on the webgit page:
-
-@example
-@uref{http://git.savannah.gnu.org/gitweb/?p=lilypond.git}
-@end example
-@end ignore
-@ignore
-
-@item
-If the patch is clearly in response to an existing issue, then
-update that issue with the @code{Patch-new} label and a link to
-the patch (either on the mailing list archives or the codereview
-url).
-
-@item
-After adding the issue, please send a response email to the same
-group(s) that the initial patch was sent to.
-
-If the initial email was sent to multiple mailing lists (such as
-both @code{bugs} and @code{devel}), then reply to all those
-mailing lists as well. The email should contain a link to the
-issue you just added.
-
-@end itemize
-
-@subheading Helpers: @code{Patch-review} label
-
-The secondary duty is to do make sure that every issue in the
-tracker with a @code{Patch-review} label has passed these
-@qq{obvious} tests:
-
-@itemize
-@item
-Applies automatically to git master.
-
-It's ok to have offsets, but not conflicts.
-
-@item
-Regtest comparison looks ok; no unexpected changes.
-
-@item
-Descriptive subject line.
-
-Avoid subjects like @qq{fixes 123}; instead write @qq{Doc: discuss
-stacking-dir for BassFigureAlignment (fix 123)}.
-
-@item
-Compiles docs from scratch. Only check this if you have reason to
-suspect it might not work.
-
-@item
-(maybe)
-
-Check code indentation and style. This should be easier post-GOP
-when we have a better-defined code style.
-
-@end itemize
-
-
-@subheading Patch Meister
-
-The Patch Meister will:
-
-@itemize
-
-@item
-send @qq{countdown} emails to
-@code{lilypond-devel} when patches appear to be ready.
-
-@item
-send general requests to review patches, or even nasty requests to
-review patches.
-
-@item
-downgrade patches from @code{Patch-review} to
-@code{Patch-needs_work} as appropriate.
-
-@item
-downgrade patches from @code{Patch-needs_work} to
-@code{Patch-abandoned} if no actions have been taken in four
-weeks.
-
-@end itemize
-
+is testing patches and managing the Patch countdown. He also generally
+runs the scripts that merging to Staging (although other developers are
+available to do this task if required).
@end ignore
* Using local branches::
* Commits::
* Patches::
+* Uploading a patch for review::
+* The patch review cycle::
@end menu
@node Commits
@subsection Commits
-
@menu
* Understanding commits::
-* Making commits::
+* How to make a commit::
* Commit messages::
@end menu
@uref{http://git.sv.gnu.org/cgit/lilypond.git/log/}.
-@node Making commits
-@unnumberedsubsubsec Making commits
+@node How to make a commit
+@unnumberedsubsubsec How to make a commit
Once you have modified some source files in your working
@node Patches
@subsection Patches
-
@menu
-* Making patches::
-* Uploading a patch for review::
+* How to make a patch::
+* Emailing patches::
@end menu
-
-@node Making patches
-@unnumberedsubsubsec Making patches
+@node How to make a patch
+@unnumberedsubsubsec How to make a patch
If you want to share your changes with other contributors and
developers, you need to generate @emph{patches} from your commits.
repository or discuss them with you.
+@node Emailing patches
+@unnumberedsubsubsec Emailing patches
+
+The default @code{x-diff} MIME type associated with patch files
+(i.e., files whose name ends in @code{.patch}) means that the
+encoding of line endings may be changed from UNIX to DOS format
+when they are sent as attachments. Attempting to apply such an
+inadvertently altered patch will cause git to fail with a message
+about @q{whitespace errors}.
+
+The solution to such problems is surprisingly simple---just change
+the default file extension of patches generated by git to end in
+@code{.txt}, for example:
+
+@example
+git config format.suffix '.patch.txt'
+@end example
+
+This should cause email programs to apply the correct base64
+encoding to attached patches.
+
+If you receive a patch with DOS instead of UNIX line-endings, it
+can be converted back using the @code{dos2unix} utility.
+
+Lots of useful information on email complications with patches is
+provided on the Wine wiki at
+@uref{http://wiki.winehq.org/GitWine}.
+
+
@node Uploading a patch for review
-@unnumberedsubsubsec Uploading a patch for review
+@subsection Uploading a patch for review
Any non-trivial change should be uploaded to our @qq{Rietveld}
code review website:
git-cl issue 0
@end example
-@subsubheading Wait for a countdown
+
+@node The patch review cycle
+@subsection The patch review cycle
Your patch will be available for reviews for the next few hours or
days. Three times a week, patches with no known problems are
mentor for uploading. If you have git push ability, look at
@ref{Pushing to staging}.
+@itemize
+
+@item
+Patches get added to the tracker and to Rietveld by the @qq{git-cl} tool, with
+a status of @qq{patch-new}.
+
+@item
+The automated tester, Patchy, verifies that the patch can be applied
+to current master. By default, it checks that the patch allows @code{make}
+and @code{make test} to complete successfully. It can also be configured to
+check that @code{make doc} is successful. If it passes, Patchy changes the
+status to @qq{patch-review} and emails the developer list. If the patch
+fails, Patchy sets it to @qq{patch-needs_work} and notifies the developer list.
+
+@item
+The Patch Meister reviews the tracker periodically, to list patches
+which have been on review for at least 24 hours. The list is found at
+
+@smallexample
+@uref{http://code.google.com/p/lilypond/issues/list?can=2&q=label:patch%20patch=review&sort=modified+patch&colspec=ID%20Type%20Status%20Priority%20Owner%20Patch%20Summary%20Modified}
+@end smallexample
+
+@item
+For each patch, the Handler reviews any discussion on the tracker
+and on Rietveld, to determine whether the patch can go forward. If
+there is any indication that a developer thinks the patch is not
+ready, the Handler marks it @qq{patch-needs_work} and makes a comment
+regarding the reason, referring to the Rietveld item if needed.
+
+@item
+Patches with explicit approval, or at least no negative comment, can
+be updated to @qq{patch-countdown}. When saving the tracker item,
+clear the @qq{send email} box to prevent sending notification for
+each patch.
+
+@item
+The Patch Meister sends an email to the developer list, with a fixed
+subject line, to enable filtering by email clients:
+
+@example
+PATCH: Countdown to 20130113
+@end example
+
+The text of the email sets the deadline for this countdown batch. At
+present, batches are done on Tuesday, Thursday and Sunday evenings.
+
+To create the countdown announcement, use the
+@code{make-countdown-announcement.sh} script, which takes the
+deadline date, and optionally your name. Follow the instructions
+provided:
+
+@example
+cd $LILYPOND_GIT
+scripts/auxiliar/make-countdown-announcement.sh "Jan 1, 2001" James
+@end example
+
+The script produces an announcement that is easily readable in all
+email clients. Also, whenever a new contributor submits a patch,
+you will be prompted to add the new username and author name to
+the script itself, and then commit those changes to the main git
+repository.
+
+
+@item
+On the scheduled countdown day, the Patch Meister reviews the
+previous list of patches on countdown, with the same procedure and
+criteria as before. Patches with no controversy can be set to
+@qq{patch-push} with a courtesy message added to the comment block.
+
+@item
+Roughly at six month intervals, the Patch Meister can list the
+patches which have been set to @qq{patch-needs-work} and send the
+results to the developer list for review. In most cases, these
+patches should be marked @qq{patch-abandoned} but this should come
+from the developer if possible.
+
+@item
+As in most organisations of unpaid volunteers, fixed procedures are
+useful in as much as they get the job done. In our community, there
+is room for senior developers to bypass normal patch handling flows,
+particularly now that the testing of patches is largely automated.
+Similarly, the minimum age of 24 hours can reasonably be waived if
+the patch is minor and from an experienced developer.
+
+
+@end itemize
+
+@ignore
+There is a single Patch Meister, and a number of Patch Helpers
+(rename this?). The list of known patches awaiting review is:
+
+@example
+@uref{http://code.google.com/p/lilypond/issues/list?can=2&q=label:patch&sort=patch}
+@end example
+
+
+@subheading Helpers: adding patches
+
+The primary duty is to add patches to the google tracker; we have
+a bad track record of losing patches in email. Patches generally
+come to the @code{lilypond-devel} mailing list, but are sometimes
+sent to @code{bug-lilypond}, @code{lilypond-users}, or
+@code{frogs} mailing list instead.
+
+@itemize
+@item
+Unless a patch is clearly in response to an existing issue, add a
+new issue with the @code{Patch-new} label and a link to the patch
+(either on the mailing list archives or the codereview url).
+
+Issue numbers are cheap; losing developers because they got fed up
+with us losing their hard work is expensive.
+
+
+@c if we enter patches immediately, I don't think this is relevant.
+
+@item
+Before adding a patch-reminder issue, do a quick check to see if
+it was pushed without sending any email. This can be checked for
+searching for relevant terms (from the patch subject or commit
+message) on the webgit page:
+
+@example
+@uref{http://git.savannah.gnu.org/gitweb/?p=lilypond.git}
+@end example
+
+
+@item
+If the patch is clearly in response to an existing issue, then
+update that issue with the @code{Patch-new} label and a link to
+the patch (either on the mailing list archives or the codereview
+url).
+
+@item
+After adding the issue, please send a response email to the same
+group(s) that the initial patch was sent to.
+
+If the initial email was sent to multiple mailing lists (such as
+both @code{bugs} and @code{devel}), then reply to all those
+mailing lists as well. The email should contain a link to the
+issue you just added.
+
+@end itemize
+
+@subheading Helpers: @code{Patch-review} label
+
+The secondary duty is to do make sure that every issue in the
+tracker with a @code{Patch-review} label has passed these
+@qq{obvious} tests:
+
+@itemize
+@item
+Applies automatically to git master.
+
+It's ok to have offsets, but not conflicts.
+
+@item
+Regtest comparison looks ok; no unexpected changes.
+
+@item
+Descriptive subject line.
+
+Avoid subjects like @qq{fixes 123}; instead write @qq{Doc: discuss
+stacking-dir for BassFigureAlignment (fix 123)}.
+
+@item
+Compiles docs from scratch. Only check this if you have reason to
+suspect it might not work.
+
+@item
+(maybe)
+
+Check code indentation and style. This should be easier post-GOP
+when we have a better-defined code style.
+
+@end itemize
+
+
+@subheading Patch Meister
+
+The Patch Meister will:
+
+@itemize
+
+@item
+send @qq{countdown} emails to
+@code{lilypond-devel} when patches appear to be ready.
+
+@item
+send general requests to review patches, or even nasty requests to
+review patches.
+
+@item
+downgrade patches from @code{Patch-review} to
+@code{Patch-needs_work} as appropriate.
+
+@item
+downgrade patches from @code{Patch-needs_work} to
+@code{Patch-abandoned} if no actions have been taken in four
+weeks.
+
+@end itemize
+
+@end ignore
+
@node Advanced Git procedures
@section Advanced Git procedures
* Working with remote branches::
* Git log::
* Applying remote patches::
-* Sending and receiving patches via email::
* Cleaning up multiple patches::
* Commit access::
* Pushing to staging::
get lost. For the same reason, you should not use the git-independent
@samp{patch} program for applying patches.
-@node Sending and receiving patches via email
-@subsection Sending and receiving patches via email
-
-
-The default @code{x-diff} MIME type associated with patch files
-(i.e., files whose name ends in @code{.patch}) means that the
-encoding of line endings may be changed from UNIX to DOS format
-when they are sent as attachments. Attempting to apply such an
-inadvertently altered patch will cause git to fail with a message
-about @q{whitespace errors}.
-
-The solution to such problems is surprisingly simple---just change
-the default file extension of patches generated by git to end in
-@code{.txt}, for example:
-
-@example
-git config format.suffix '.patch.txt'
-@end example
-
-This should cause email programs to apply the correct base64
-encoding to attached patches.
-
-If you receive a patch with DOS instead of UNIX line-endings, it
-can be converted back using the @code{dos2unix} utility.
-
-Lots of useful information on email complications with patches is
-provided on the Wine wiki at
-@uref{http://wiki.winehq.org/GitWine}.
@node Cleaning up multiple patches
@code{articulations} property, we can return @code{note-event}, hence
the last line of the function.
-Now we transform the @code{add-accent} function into a music
-function (a matter of some syntactic sugar and a declaration of the type
-of its sole @q{real} argument).
+Now we transform the @code{add-accent} function into a music function (a
+matter of some syntactic sugar and a declaration of the type of its
+argument).
@example
addAccent = #(define-music-function (note-event)
note-event)
@end example
-We may verify that this music function works correctly:
+We then verify that this music function works correctly:
@example
\displayMusic \addAccent c4
\new PianoStaff <<
\new Staff = "upper"
{
- \override Staff.TimeSignature #'transparent = ##t
- \override Staff.TimeSignature #'extra-spacing-width = #'(0.0 . 3.0)
+ \hide Staff.TimeSignature
+ \override Staff.TimeSignature.extra-spacing-width = #'(0.0 . 3.0)
\accidentalStyle dodecaphonic
\autoBeamOff
\clef treble
}
\new Staff = "lower"
{
- \override Staff.TimeSignature #'transparent = ##t
+ \hide Staff.TimeSignature
\accidentalStyle dodecaphonic
\autoBeamOff
\clef bass
@tab
@code{aug7}
@tab
-@code{c1:aug}
+@code{c1:aug7}
@tab
@lilypond[line-width=2.1\cm,noragged-right,notime]
<<
@tab
@code{m7+}
@tab
-@code{m7+}
+@code{c1:m7+}
@tab
@lilypond[line-width=2.1\cm,noragged-right,notime]
<<
Sometimes you may want to put lyrics for different performers on a
single line: where there is rapidly alternating text, for example.
This snippet shows how this can be done with @code{\\override
-VerticalAxisGroup #'nonstaff-nonstaff-spacing #'minimum-distance =
-##f}.
+VerticalAxisGroup.nonstaff-nonstaff-spacing.minimum-distance = ##f}.
"
doctitle = "Arranging separate lyrics on a single line"
\layout {
\context {
\Lyrics
- \override VerticalAxisGroup #'nonstaff-nonstaff-spacing
- #'minimum-distance = ##f
+ \override VerticalAxisGroup.nonstaff-nonstaff-spacing.minimum-distance = ##f
}
}
(ly:grob-layout grob) 'staff-space))
(staff-line-thickness
(ly:output-def-lookup (ly:grob-layout grob) 'line-thickness))
- (grob-name (lambda (x) (assq-ref
- (ly:grob-property x 'meta) 'name)))
(par-x (ly:grob-parent grob X))
- (dyn-text (eq? (grob-name par-x) 'DynamicText ))
+ (dyn-text (grob::has-interface par-x 'dynamic-text-interface))
(dyn-text-stencil-x-length
(if dyn-text
(interval-length
+++ /dev/null
-%% DO NOT EDIT this file manually; it is automatically
-%% generated from LSR http://lsr.di.unimi.it
-%% Make any changes in LSR itself, or in Documentation/snippets/new/ ,
-%% and then run scripts/auxiliar/makelsr.py
-%%
-%% This file is in the public domain.
-\version "2.18.0"
-
-\header {
- lsrtags = "contexts-and-engravers, text, tweaks-and-overrides"
-
- texidoc = "
-For technical reasons, text scripts attached to note heads cannot
-easily be centered on a note head's width, unlike articulations.
-
-Instead of using trial-and-error offset tweaks, this snippet uses a
-Scheme engraver to reset the horizontal parent of each markup to a
-@code{NoteColumn}. This also allows text to follow note heads which
-have been shifted via @code{force-hshift}.
-
-
-
-"
- doctitle = "Centering markup on note heads automatically"
-} % begin verbatim
-
-#(define (Text_align_engraver ctx)
- (let ((scripts '())
- (note-column #f))
- (make-engraver
- (acknowledgers
- ((note-column-interface trans grob source)
- ;; cache NoteColumn in this Voice context
- (set! note-column grob))
- ((text-script-interface trans grob source)
- ;; whenever a TextScript is acknowledged,
- ;; add it to `scripts' list
- (set! scripts (cons grob scripts))))
- ((stop-translation-timestep trans)
- ;; if any TextScript grobs exist,
- ;; set NoteColumn as X-parent
- (for-each (lambda (script)
- (set! (ly:grob-parent script X) note-column))
- scripts)
- ;; clear scripts ready for next timestep
- (set! scripts '())))))
-
-\layout {
- \context {
- \Voice
- \consists #Text_align_engraver
- \override TextScript.X-offset =
- #ly:self-alignment-interface::aligned-on-x-parent
- \override TextScript.self-alignment-X = #CENTER
- }
-}
-
-\new Staff <<
- \relative c'' {
- \override NoteColumn.force-hshift = #3
- c1-\markup { \arrow-head #Y #DOWN ##t }
- }
- \\
- \relative c' {
- a4 a-\markup { \huge ^ } a a
- }
->>
-% DO NOT EDIT this file manually; it is automatically
-% generated from Documentation/snippets/new
-% Make any changes in Documentation/snippets/new/
-% and then run scripts/auxiliar/makelsr.py
-%
-% This file is in the public domain.
-%% Note: this file works from version 2.18.0
+%% DO NOT EDIT this file manually; it is automatically
+%% generated from LSR http://lsr.di.unimi.it
+%% Make any changes in LSR itself, or in Documentation/snippets/new/ ,
+%% and then run scripts/auxiliar/makelsr.py
+%%
+%% This file is in the public domain.
\version "2.18.0"
\header {
doctitle = "Changing stanza fonts"
} % begin verbatim
-
-\new Voice {
+\relative c'' {
\time 3/4
g2 e4
a2 f4
-% DO NOT EDIT this file manually; it is automatically
-% generated from Documentation/snippets/new
-% Make any changes in Documentation/snippets/new/
-% and then run scripts/auxiliar/makelsr.py
-%
-% This file is in the public domain.
-%% Note: this file works from version 2.18.0
+%% DO NOT EDIT this file manually; it is automatically
+%% generated from LSR http://lsr.di.unimi.it
+%% Make any changes in LSR itself, or in Documentation/snippets/new/ ,
+%% and then run scripts/auxiliar/makelsr.py
+%%
+%% This file is in the public domain.
\version "2.18.0"
\header {
doctitle = "Changing the default text font family"
} % begin verbatim
-
\paper {
% change for other default global staff size.
myStaffSize = #20
adding-an-extra-staff.ly
automatically-changing-the-stem-direction-of-the-middle-note-based-on-the-melody.ly
centered-measure-numbers.ly
-centering-markup-on-note-heads-automatically.ly
changing-midi-output-to-one-channel-per-voice.ly
changing-time-signatures-inside-a-polymetric-section-using--scaledurations.ly
chant-or-psalms-notation.ly
\once \override Accidental.extra-offset = #'(4 . -.1)
}
+
\relative c' {
<< { \fixA <b d!>8 } \\ { \voiceThree \fixB dis } >> s
}
texidoc = "
When working with grob callbacks, it can be helpful to understand a
-grob's @qq{ancestry}. Most grobs have @qq{parents} which influence the
+grob’s ancestry. Most grobs have parents which influence the
positioning of the grob. X- and Y-parents influence the horizontal and
vertical positions for the grob, respectively. Additionally, each
parent may have parents of its own.
-Unfortunately, there are several aspects of a grob's ancestry that can
+Unfortunately, there are several aspects of a grob’s ancestry that can
lead to confusion:
-* The types of parents a grob has may depend on context. * For some
-grobs, the X- and Y-parents are the same. * A particular @qq{ancestor}
-may be related to a grob in multiple ways. * The concept of
-@qq{generations} is misleading.
+
+* The types of parents a grob has may depend on context.
+
+* For some grobs, the X- and Y-parents are the same.
+
+* A particular “ancestor” may be related to a grob in multiple ways.
+
+* The concept of “generations” is misleading.
For example, the @code{System} grob can be both parent (on the Y-side)
grob.
-This macro prints (to the console) a textual representation of a grob's
+This macro prints (to the console) a textual representation of a grob’s
ancestry.
+When called this way:
-When called this way
-
-
-@{
- \\once \\override NoteHead #'before-line-breaking = #display-ancestry
- c @}
-
+@code{@{ \\once \\override NoteHead.before-line-breaking =
+#display-ancestry c @}}
The following output is generated:
-------------------------------------
-
-NoteHead X,Y: NoteColumn
- X: PaperColumn
- X,Y: System
- Y: VerticalAxisGroup
- X: NonMusicalPaperColumn
- X,Y: System
- Y: VerticalAlignment
- X: NonMusicalPaperColumn
- X,Y: System
- Y: System
-
-
+@code{NoteHead X,Y: NoteColumn
+ X: PaperColumn
+ X,Y: System
+ Y: VerticalAxisGroup
+ X: NonMusicalPaperColumn
+ X,Y: System
+ Y: VerticalAlignment
+ X: NonMusicalPaperColumn
+ X,Y: System
+ Y: System}
"
doctitle = "Displaying grob ancestry"
%% http://lsr.di.unimi.it/LSR/Item?id=622
%% see also http://www.lilypond.org/doc/v2.18/Documentation/snippets/tweaks-and-overrides#tweaks-and-overrides-displaying-grob-ancestry
-#(define (grob-name grob)
- (if (ly:grob? grob)
- (assoc-ref (ly:grob-property grob 'meta) 'name)
- #f))
+%% Remark:
+%% grob::name is in the source since 2.19.x could be deleted during next LSR-upgrade
+#(define (grob::name grob)
+ (assq-ref (ly:grob-property grob 'meta) 'name))
#(define (get-ancestry grob)
- (if (not (null? (ly:grob-parent grob X)))
- (list (grob-name grob)
- (get-ancestry (ly:grob-parent grob X))
- (get-ancestry (ly:grob-parent grob Y)))
- (grob-name grob)))
+ (if (not (null? (ly:grob-parent grob X)))
+ (list (grob::name grob)
+ (get-ancestry (ly:grob-parent grob X))
+ (get-ancestry (ly:grob-parent grob Y)))
+ (grob::name grob)))
#(define (format-ancestry lst padding)
(string-append
(format (current-error-port)
"~3&~a~2%~a~&"
(make-string 36 #\-)
- (format-ancestry (get-ancestry grob) 0)))
+ (if (ly:grob? grob)
+ (format-ancestry (get-ancestry grob) 0)
+ (format #f "~a is not a grob" grob))))
\relative c' {
\once \override NoteHead.before-line-breaking = #display-ancestry
-% DO NOT EDIT this file manually; it is automatically
-% generated from Documentation/snippets/new
-% Make any changes in Documentation/snippets/new/
-% and then run scripts/auxiliar/makelsr.py
-%
-% This file is in the public domain.
-%% Note: this file works from version 2.19.22
-\version "2.19.22"
+%% DO NOT EDIT this file manually; it is automatically
+%% generated from LSR http://lsr.di.unimi.it
+%% Make any changes in LSR itself, or in Documentation/snippets/new/ ,
+%% and then run scripts/auxiliar/makelsr.py
+%%
+%% This file is in the public domain.
+\version "2.18.0"
\header {
lsrtags = "fretted-strings, specific-notation, tweaks-and-overrides"
-% DO NOT EDIT this file manually; it is automatically
-% generated from Documentation/snippets/new
-% Make any changes in Documentation/snippets/new/
-% and then run scripts/auxiliar/makelsr.py
-%
-% This file is in the public domain.
-%% Note: this file works from version 2.18.0
+%% DO NOT EDIT this file manually; it is automatically
+%% generated from LSR http://lsr.di.unimi.it
+%% Make any changes in LSR itself, or in Documentation/snippets/new/ ,
+%% and then run scripts/auxiliar/makelsr.py
+%%
+%% This file is in the public domain.
\version "2.18.0"
\header {
- lsrtags = "tweaks-and-overrides, pitches, staff-notation"
+ lsrtags = "pitches, staff-notation, tweaks-and-overrides"
texidoc = "
It is possible to change the slope of the Ottava spanner.
doctitle = "Modifying the Ottava spanner slope"
} % begin verbatim
-
\relative c'' {
\override Staff.OttavaBracket.stencil = #ly:line-spanner::print
\override Staff.OttavaBracket.bound-details =
+++ /dev/null
-\version "2.18.0"
-
-\header {
- lsrtags = "really-simple, vocal-music"
-
- texidoc = "
-Fonts can be changed independently for each stanza, including the font
-used for printing the stanza number.
-
-"
- doctitle = "Changing stanza fonts"
-}
-
-\new Voice {
- \time 3/4
- g2 e4
- a2 f4
- g2.
-}
-\addlyrics {
- \set stanza = #"1. "
- Hi, my name is Bert.
-}
-\addlyrics {
- \override StanzaNumber.font-name = #"DejaVu Sans"
- \set stanza = #"2. "
- \override LyricText.font-family = #'typewriter
- Oh, ché -- ri, je t'aime
-}
+++ /dev/null
-\version "2.18.0"
-
-\header {
- lsrtags = "text, tweaks-and-overrides"
-
- texidoc = "
-The default font families for text can be overridden with
-@code{make-pango-font-tree}.
-
-"
- doctitle = "Changing the default text font family"
-}
-
-\paper {
- % change for other default global staff size.
- myStaffSize = #20
- %{
- run
- lilypond -dshow-available-fonts blabla
- to show all fonts available in the process log.
- %}
-
- #(define fonts
- (make-pango-font-tree "Times New Roman"
- "Nimbus Sans,Nimbus Sans L"
- "Luxi Mono"
-;; "Helvetica"
-;; "Courier"
- (/ myStaffSize 20)))
-}
-
-\relative c'' {
- c4^\markup {
- roman: foo \bold bla \italic bar \italic \bold baz
- }
- c'4_\markup {
- \override #'(font-family . sans)
- {
- sans: foo \bold bla \italic bar \italic \bold baz
- }
- }
- c'2^\markup {
- \override #'(font-family . typewriter)
- {
- mono: foo \bold bla \italic bar \italic \bold baz
- }
- }
-}
+++ /dev/null
-\version "2.19.22"
-
-\header {
- lsrtags = "fretted-strings, specific-notation, tweaks-and-overrides"
-
- texidoc = "
-If you want to move the position of a fret diagram, for example, to
-avoid collision, or to place it between two notes, you have various
-possibilities:
-
-1) modify #'padding or #'extra-offset values (as shown in the first
-snippet)
-
-2) you can add an invisible voice and attach the fret diagrams to the
-invisible notes in that voice (as shown in the second example).
-
- If you need to move the fret according with a rythmic position inside
-the bar (in the example, the third beat of the measure) the second
-example is better, because the fret is aligned with the third beat
-itself.
-
-"
- doctitle = "How to change fret diagram position"
-}
-harmonies = \chordmode
-{
- a8:13
-% THE FOLLOWING IS THE COMMAND TO MOVE THE CHORD NAME
- \once \override ChordNames.ChordName.extra-offset = #'(10 . 0)
- b8:13 s2.
-% THIS LINE IS THE SECOND METHOD
- s4 s4 b4:13
-}
-
-\score
-{
- <<
- \new ChordNames \harmonies
- \new Staff
- {a8^\markup { \fret-diagram #"6-x;5-0;4-2;3-0;2-0;1-2;" }
-% THE FOLLOWING IS THE COMMAND TO MOVE THE FRET DIAGRAM
- \once \override TextScript.extra-offset = #'(10 . 0)
- b4.~^\markup { \fret-diagram #"6-x;5-2;4-4;3-2;2-2;1-4;" } b4. a8\break
-% HERE IS THE SECOND METHOD
- <<
- { a8 b4.~ b4. a8}
- { s4 s4 s4^\markup { \fret-diagram #"6-x;5-2;4-4;3-2;2-2;1-4;" }
- }
- >>
- }
- >>
-}
+++ /dev/null
-\version "2.18.0"
-
-\header {
- lsrtags = "tweaks-and-overrides, pitches, staff-notation"
-
- texidoc = "
-It is possible to change the slope of the Ottava spanner.
-
-"
- doctitle = "Modifying the Ottava spanner slope"
-}
-
-\relative c'' {
- \override Staff.OttavaBracket.stencil = #ly:line-spanner::print
- \override Staff.OttavaBracket.bound-details =
- #`((left . ((Y . 0) ; Change the integer here
- (attach-dir . ,LEFT)
- (padding . 0)
- (stencil-align-dir-y . ,CENTER)))
- (right . ((Y . 5) ; Change the integer here
- (padding . 0)
- (attach-dir . ,RIGHT)
- (text . ,(make-draw-dashed-line-markup (cons 0 -1.2))))))
- \override Staff.OttavaBracket.left-bound-info =
- #ly:line-spanner::calc-left-bound-info-and-text
- \override Staff.OttavaBracket.right-bound-info =
- #ly:line-spanner::calc-right-bound-info
- \ottava #1
- c1
- c'''1
-}
-\version "2.17.6"
+\version "2.19.0"
\include "catalan.ly"
\header {
<bs' fs'>2
e'2
|
- <b'! a'>2 -\tweak #'style #'none \cresc
+ <b'! a'>2 -\tweak style #'none \cresc
b'4
<e'' cs''>4
|
\key c \major
\relative c''
{
- % disable the following line to see the noteheads while writing the song
+ % disable the following line to see the the noteheads while writing the song
\NoNoteHead
\override NoteHead.no-ledgers = ##t
% and then run scripts/auxiliar/makelsr.py
%
% This file is in the public domain.
-%% Note: this file works from version 2.17.6
-\version "2.17.6"
+%% Note: this file works from version 2.19.0
+\version "2.19.0"
\include "catalan.ly"
\header {
aligning-syllables-with-melisma.ly
blanking-staff-lines-using-the--whiteout-command.ly
center-text-below-hairpin-dynamics.ly
-centering-markup-on-note-heads-automatically.ly
changing-ottava-text.ly
changing-the-default-text-font-family.ly
combining-dynamics-with-markup-texts.ly
asymmetric-slurs.ly
avoiding-collisions-with-chord-fingerings.ly
caesura-railtracks-with-fermata.ly
-centering-markup-on-note-heads-automatically.ly
changing-a-single-notes-size-in-a-chord.ly
changing-beam-thickness-and-spacing.ly
changing-form-of-multi-measure-rests.ly
MensStyle = {
\autoBeamOff
- \override NoteHead #'style = #'petrucci
- \override Score.BarNumber #'transparent = ##t
+ \override NoteHead.style = #'petrucci
+ \override Score.BarNumber.transparent = ##t
\override Stem.neutral-direction = #up
}
@c used for news about the upcoming release; see CG 10.2
@newsItem
-@subheading LilyPond 2.19.37 released @emph{February 28, 2016}
+@subheading LilyPond 2.19.38 released @emph{March 13, 2016}
We are happy to announce the release of LilyPond
-2.19.37. This release includes a number of enhancements, and contains some
+2.19.38. This release includes a number of enhancements, and contains some
work in progress. You will have access to the very latest features, but
some may be incomplete, and you may encounter bugs and crashes. If you
require a stable version of Lilypond, we recommend using the 2.18
* don't duplicate entries from news-front.itexi
@end ignore
+@newsItem
+@subheading LilyPond 2.19.37 released @emph{February 28, 2016}
+
+We are happy to announce the release of LilyPond
+2.19.37. This release includes a number of enhancements, and contains some
+work in progress. You will have access to the very latest features, but
+some may be incomplete, and you may encounter bugs and crashes. If you
+require a stable version of Lilypond, we recommend using the 2.18
+version.
+
+@newsEnd
+
@newsItem
@subheading LilyPond 2.19.36 released @emph{January 31, 2016}
PACKAGE_NAME=LilyPond
MAJOR_VERSION=2
MINOR_VERSION=19
-PATCH_LEVEL=38
+PATCH_LEVEL=39
MY_PATCH_LEVEL=
VERSION_STABLE=2.18.2
-VERSION_DEVEL=2.19.37
+VERSION_DEVEL=2.19.38
--- /dev/null
+\version "2.19.39"
+
+\header {
+ texidoc = "Music variables may be structured into alists
+indexed by numbers or symbols."
+}
+
+\layout { ragged-right = ##t }
+
+violin.1 = { e''-\markup \typewriter "\\violin.1" }
+violin.2 = { c'-\markup \typewriter "\\violin.2" }
+viola.I = { e-\markup \typewriter "\\viola.I" }
+viola.II = { c-\markup \typewriter "\\viola.II" }
+
+\score {
+ <<
+ \new Staff << \violin.1 \\ \violin.2 >>
+ \new Staff \with { \clef "alto" } << \viola.I \\ \viola.II >>
+ >>
+}
--- /dev/null
+\version "2.19.38"
+
+\header {
+ texidoc="
+Noteheads do not extend above the upper staff line.
+"
+}
+
+\new Voice \with {
+ \override NoteHead.color = #green
+ } {
+ \relative {
+ f'4 a c e \bar "|."
+ }
+}
SCM grob_property_path,
SCM new_value)
{
+ // Numbers may appear, but not in first place
if (!scm_is_symbol (context_property)
|| !scm_is_symbol (scm_car (grob_property_path)))
{
- warning (_ ("need symbol arguments for \\override and \\revert"));
+ warning (_ ("need symbol argument for \\override and \\revert"));
if (do_internal_type_checking_global)
assert (false);
}
} while (0)
SCM nested_property_alist (SCM alist, SCM prop_path, SCM value);
+SCM nested_property (SCM alist, SCM prop_path, SCM fallback = SCM_EOL);
SCM nested_create_alist (SCM prop_path, SCM value);
SCM partial_list_copy (SCM alist, SCM tail, SCM newtail);
SCM assq_tail (SCM key, SCM alist, SCM alist_end);
+SCM assv_tail (SCM key, SCM alist, SCM alist_end);
SCM assoc_tail (SCM key, SCM alist, SCM alist_end);
SCM evict_from_alist (SCM, SCM, SCM);
SCM nalist_to_alist (SCM nalist, int nested);
extern Variable hash_table_to_alist;
extern Variable interpret_markup_list;
extern Variable invalidate_alterations;
+ extern Variable key_p;
+ extern Variable key_list_p;
extern Variable key_signature_interface_alteration_positions;
extern Variable layout_extract_page_properties;
extern Variable lilypond_main;
Variable hash_table_to_alist ("hash-table->alist");
Variable interpret_markup_list ("interpret-markup-list");
Variable invalidate_alterations ("invalidate-alterations");
+ Variable key_p ("key?");
+ Variable key_list_p ("key-list?");
Variable key_signature_interface_alteration_positions ("key-signature-interface::alteration-positions");
Variable layout_extract_page_properties ("layout-extract-page-properties");
Variable lilypond_main ("lilypond-main");
return SCM_BOOL_F;
}
+SCM
+assv_tail (SCM key, SCM alist, SCM based_on = SCM_EOL)
+{
+ for (SCM p = alist; !scm_is_eq (p, based_on); p = scm_cdr (p))
+ {
+ if (scm_is_true (scm_eqv_p (scm_caar (p), key)))
+ return p;
+ }
+ return SCM_BOOL_F;
+}
+
SCM
assoc_tail (SCM key, SCM alist, SCM based_on = SCM_EOL)
{
+ if (SCM_IMP (key))
+ return assq_tail (key, alist, based_on);
+ if (scm_is_number (key) || scm_is_true (scm_char_p (key)))
+ return assv_tail (key, alist, based_on);
for (SCM p = alist; !scm_is_eq (p, based_on); p = scm_cdr (p))
{
if (ly_is_equal (scm_caar (p), key))
SCM
evict_from_alist (SCM key, SCM alist, SCM alist_end)
{
-// shortcircuit to an eq-using assoc_tail variant when key is a symbol
-// (common case)
- SCM p = scm_is_symbol (key) ? assq_tail (key, alist, alist_end)
- : assoc_tail (key, alist, alist_end);
+ SCM p = assoc_tail (key, alist, alist_end);
+
if (scm_is_true (p))
return partial_list_copy (alist, p, scm_cdr (p));
return alist;
SCM rest = scm_cdr (prop_path);
if (scm_is_pair (rest))
{
- SCM where = assq_tail (key, alist);
+ SCM where = assoc_tail (key, alist);
+
if (scm_is_false (where))
return scm_acons (key, nested_create_alist (rest, value), alist);
return scm_acons (key, nested_property_alist (scm_cdar (where),
return scm_acons (key, value, alist);
}
+SCM
+nested_property (SCM alist, SCM prop_path, SCM fallback)
+{
+ for (; scm_is_pair (prop_path); prop_path = scm_cdr (prop_path))
+ {
+ SCM tail = assoc_tail (scm_car (prop_path), alist);
+ if (scm_is_false (tail))
+ return fallback;
+ alist = scm_cdar (tail);
+ }
+ return alist;
+}
+
void
set_nested_property (Grob *me, SCM big_to_small, SCM value)
{
// This converts an alist with nested overrides in it to a proper
// alist. The number of nested overrides is known in advance,
// everything up to the last nested override is copied, the tail is
-// shared
+// shared.
+//
+// The first nalist index has to be a symbol since the conversion
+// relies on eq? comparisons, uses some special non-symbol values for
+// special purposes, and does validity checking indexed by symbols.
+// Subindexing can be done with equal?-comparable indexes, however.
SCM
nalist_to_alist (SCM nalist, int nested)
scm_set_cdr_x (pair, scm_cons (elt, scm_cdr (pair)));
continue;
}
-
+ assert (scm_is_symbol (key));
// plain override: apply any known corresponding partials
SCM pair = assq_pop_x (key, &partials);
if (scm_is_true (pair))
using namespace std;
#include "book.hh"
+#include "context.hh"
#include "context-def.hh"
#include "context-mod.hh"
#include "dimensions.hh"
%token EVENT_IDENTIFIER
%token EVENT_FUNCTION
%token FRACTION
+%token LOOKUP_IDENTIFIER
%token LYRIC_ELEMENT
%token MARKUP_FUNCTION
%token MARKUP_LIST_FUNCTION
}
;
+lookup:
+ LOOKUP_IDENTIFIER
+ | LOOKUP_IDENTIFIER '.' symbol_list_rev
+ {
+ $$ = loc_on_music (parser, @$,
+ nested_property ($1, scm_reverse_x ($3, SCM_EOL)));
+ }
+ ;
+
embedded_scm_bare:
SCM_TOKEN
{
embedded_scm_active:
SCM_IDENTIFIER
| scm_function_call
+ | lookup
;
embedded_scm_bare_arg:
| book_block
| bookpart_block
| output_def
+ | lookup
;
/* The generic version may end in music, or not */
embedded_scm:
embedded_scm_bare
| scm_function_call
+ | lookup
;
/* embedded_scm_arg is _not_ casting pitches to music by default, this
parser->lexer_->set_identifier ($1, $3);
$$ = SCM_UNSPECIFIED;
}
- | assignment_id property_path '=' identifier_init {
- SCM path = scm_cons (scm_string_to_symbol ($1), $2);
- parser->lexer_->set_identifier (path, $4);
+ | assignment_id '.' property_path '=' identifier_init {
+ SCM path = scm_cons (scm_string_to_symbol ($1), $3);
+ parser->lexer_->set_identifier (path, $5);
$$ = SCM_UNSPECIFIED;
}
- | assignment_id '.' property_path '=' identifier_init {
+ | assignment_id ',' property_path '=' identifier_init {
SCM path = scm_cons (scm_string_to_symbol ($1), $3);
parser->lexer_->set_identifier (path, $5);
$$ = SCM_UNSPECIFIED;
{
$$ = scm_append (scm_list_2 ($1, scm_reverse_x ($3, SCM_EOL)));
}
+ | SYMBOL_LIST ',' symbol_list_rev
+ {
+ $$ = scm_append (scm_list_2 ($1, scm_reverse_x ($3, SCM_EOL)));
+ }
;
symbol_list_rev:
{
$$ = scm_append_x (scm_list_2 ($3, $1));
}
+ | symbol_list_rev ',' symbol_list_part
+ {
+ $$ = scm_append_x (scm_list_2 ($3, $1));
+ }
;
// symbol_list_part delivers elements in reverse copy.
symbol_list_part:
symbol_list_element
{
- $$ = try_string_variants (Lily::symbol_list_p, $1);
+ $$ = try_string_variants (Lily::key_list_p, $1);
if (SCM_UNBNDP ($$)) {
- parser->parser_error (@1, _("not a symbol"));
+ parser->parser_error (@1, _("not a key"));
$$ = SCM_EOL;
} else
$$ = scm_reverse ($$);
symbol_list_element:
STRING
| embedded_scm_bare
+ | UNSIGNED
;
if (scm_is_true (scm_call_1 ($2, $4)))
// May be 3 \cm or similar
MYREPARSE (@4, $2, REAL, $4);
+ else if (scm_is_true (scm_call_1 ($2, scm_list_1 ($4))))
+ MYREPARSE (@4, $2, SYMBOL_LIST, scm_list_1 ($4));
else {
SCM d = make_duration ($4);
if (!SCM_UNBNDP (d)) {
if (scm_is_true (scm_call_1 ($2, $4)))
// May be 3 \cm or similar
MYREPARSE (@4, $2, REAL, $4);
+ else if (scm_is_true (scm_call_1 ($2, scm_list_1 ($4))))
+ MYREPARSE (@4, $2, SYMBOL_LIST, scm_list_1 ($4));
else {
SCM d = make_duration ($4);
if (!SCM_UNBNDP (d)) {
if (scm_is_true (scm_call_1 ($1, $3)))
// May be 3 \cm or similar
MYREPARSE (@3, $1, REAL, $3);
+ else if (scm_is_true (scm_call_1 ($1, scm_list_1 ($3))))
+ MYREPARSE (@3, $1, SYMBOL_LIST, scm_list_1 ($3));
else {
SCM d = make_duration ($3);
if (!SCM_UNBNDP (d)) {
symbol_list_rev {
$$ = scm_reverse_x ($1, SCM_EOL);
}
- | symbol_list_rev property_path {
- $$ = scm_reverse_x ($1, $2);
- }
;
property_operation:
| UNSET symbol {
$$ = scm_list_2 (ly_symbol2scm ("unset"), $2);
}
- | OVERRIDE property_path '=' scalar {
+ | OVERRIDE revert_arg '=' scalar {
if (scm_ilength ($2) < 2) {
parser->parser_error (@2, _("bad grob property path"));
$$ = SCM_UNDEFINED;
{
$$ = scm_append_x (scm_list_2 ($5, $3));
}
+ | revert_arg_backup BACKUP SCM_ARG ',' symbol_list_part
+ {
+ $$ = scm_append_x (scm_list_2 ($5, $3));
+ }
| revert_arg_backup BACKUP SCM_ARG symbol_list_part
{
$$ = scm_append_x (scm_list_2 ($4, $3));
} else if (unsmob<Score> (sid)) {
*destination = unsmob<Score> (sid)->clone ()->unprotect ();
return SCM_IDENTIFIER;
+ } else if (scm_is_pair (sid)
+ && scm_is_pair (scm_car (sid))
+ && scm_is_true (Lily::key_p (scm_caar (sid)))) {
+ *destination = sid;
+ return LOOKUP_IDENTIFIER;
}
-
return -1;
}
if (scm_is_true (scm_call_1 (pred, str)))
return str;
// a symbol may be interpreted as a list of symbols if it helps
- if (scm_is_symbol (str)) {
+ if (scm_is_true (Lily::key_p (str))) {
str = scm_list_1 (str);
if (scm_is_true (scm_call_1 (pred, str)))
return str;
return SCM_UNDEFINED;
str = scm_string_split (str, SCM_MAKE_CHAR ('.'));
+ for (SCM p = str; scm_is_pair (p); p = scm_cdr (p))
+ scm_set_car_x (p, scm_string_split (scm_car (p),
+ SCM_MAKE_CHAR (',')));
+ str = scm_append_x (str);
for (SCM p = str; scm_is_pair (p); p = scm_cdr (p))
scm_set_car_x (p, scm_string_to_symbol (scm_car (p)));
|| (c >= 'A' && c <= 'Z')
|| c > 0x7f)
middle = true;
- else if (middle && (c == '-' || c == '_' || (multiple && c == '.')))
+ else if (middle && (c == '-' || c == '_' || (multiple &&
+ (c == '.' || c == ','))))
middle = false;
else
return false;
{
current_event_ = event_drul_[START];
span_ = make_spanner ("TextSpanner", event_drul_[START]->self_scm ());
+ if (Direction d = to_dir (current_event_->get_property ("direction")))
+ span_->set_property ("direction", scm_from_int (d));
Side_position_interface::set_axis (span_, Y_AXIS);
event_drul_[START] = 0;
%}
-\version "2.19.37" % necessary for upgrading to future LilyPond versions.
+\version "2.19.38" % necessary for upgrading to future LilyPond versions.
\header{
title = "A scale in LilyPond"
%}
-\version "2.19.37" % necessary for upgrading to future LilyPond versions.
+\version "2.19.38" % necessary for upgrading to future LilyPond versions.
\header{
title = "A scale in LilyPond"
#(define graph (make-empty-graph (ly:parser-output-name)))
-#(define (grob-name g)
- (let* ((meta (ly:grob-property g 'meta))
- (name-pair (assq 'name meta)))
- (if (pair? name-pair)
- (cdr name-pair)
- #f)))
-
% an event is relevant if
% (it is on some whitelist or all whitelists are empty)
% and
(or
(= 0 (length file-line-whitelist) (length sym-whitelist) (length grob-whitelist))
(memq prop sym-whitelist)
- (memq (grob-name grob) grob-whitelist)
+ (memq (grob::name grob) grob-whitelist)
(member file-line file-line-whitelist))
(and
(not (memq prop sym-blacklist))
- (not (memq (grob-name grob) grob-blacklist))
+ (not (memq (grob::name grob) grob-blacklist))
(not (member file-line file-line-blacklist))))))
#(define (grob-event-node grob label cluster)
#(define (grob-mod grob file line func prop val)
(let* ((val-str (truncate-value val))
- (label (format #f "~a\\n~a:~a\\n~a <- ~a" (grob-name grob) file line prop val-str)))
+ (label (format #f "~a\\n~a:~a\\n~a <- ~a" (grob::name grob) file line prop val-str)))
(if (relevant? grob file line prop)
(grob-event-node grob label file))))
#(define (grob-cache grob prop callback value)
(let* ((val-str (truncate-value value))
- (label (format #f "caching ~a.~a\\n~a -> ~a" (grob-name grob) prop callback value)))
+ (label (format #f "caching ~a.~a\\n~a -> ~a" (grob::name grob) prop callback value)))
(if (relevant? grob #f #f prop)
(grob-event-node grob label #f))))
#(define (grob-create grob file line func)
- (let ((label (format #f "~a\\n~a:~a" (grob-name grob) file line)))
+ (let ((label (format #f "~a\\n~a:~a" (grob::name grob) file line)))
(grob-event-node grob label file)))
#(ly:set-grob-modification-callback grob-mod)
alterBroken =
#(define-music-function (property arg item)
- (symbol-list-or-symbol? list? symbol-list-or-music?)
+ (key-list-or-symbol? list? key-list-or-music?)
(_i "Override @var{property} for pieces of broken spanner @var{item}
with values @var{arg}. @var{item} may either be music in the form of
a starting spanner event, or a symbol list in the form
offset =
#(define-music-function (property offsets item)
- (symbol-list-or-symbol? scheme? symbol-list-or-music?)
+ (symbol-list-or-symbol? scheme? key-list-or-music?)
(_i "Offset the default value of @var{property} of @var{item} by
@var{offsets}. If @var{item} is a string, the result is
@code{\\override} for the specified grob type. If @var{item} is
overrideProperty =
#(define-music-function (grob-property-path value)
- (symbol-list? scheme?)
+ (key-list? scheme?)
(_i "Set the grob property specified by @var{grob-property-path} to
@var{value}. @var{grob-property-path} is a symbol list of the form
propertyOverride =
#(define-music-function (grob-property-path value)
- (symbol-list? scheme?)
+ (key-list? scheme?)
(_i "Set the grob property specified by @var{grob-property-path} to
@var{value}. @var{grob-property-path} is a symbol list of the form
@code{Context.GrobName.property} or @code{GrobName.property}, possibly
propertyRevert =
#(define-music-function (grob-property-path)
- (symbol-list?)
+ (key-list?)
(_i "Revert the grob property specified by @var{grob-property-path} to
its previous value. @var{grob-property-path} is a symbol list of the form
@code{Context.GrobName.property} or @code{GrobName.property}, possibly
propertyTweak =
#(define-music-function (prop value item)
- (symbol-list-or-symbol? scheme? symbol-list-or-music?)
+ (key-list-or-symbol? scheme? key-list-or-music?)
(_i "Add a tweak to the following @var{item}, usually music.
This generally behaves like @code{\\tweak} but will turn into an
@code{\\override} when @var{item} is a symbol list.
shape =
#(define-music-function (offsets item)
- (list? symbol-list-or-music?)
+ (list? key-list-or-music?)
(_i "Offset control-points of @var{item} by @var{offsets}. The
argument is a list of number pairs or list of such lists. Each
element of a pair represents an offset to one of the coordinates of a
tweak =
#(define-music-function (prop value music)
- (symbol-list-or-symbol? scheme? ly:music?)
+ (key-list-or-symbol? scheme? ly:music?)
(_i "Add a tweak to the following @var{music}.
Layout objects created by @var{music} get their property @var{prop}
set to @var{value}. If @var{prop} has the form @samp{Grob.property}, like with
% the lines. If you like that, modify overdone heads (unit:
% stafflinethickness).
%
-overdone_heads = 0.0;
+
+%% FIXME
+% There is a problem with noteheads slightly extending beyond the staff
+% lines. This is due to the fact that staff_space + stafflinethickness
+% is sometimes an odd number, so the nothead height and depth are not
+% integers. Then, when the font is converted to an outline font, the
+% system rounds up the 0.5 left over from dividing the notehead height
+% in two, and the notehead extends slightly beyond the staff line.
+% In order to resolve this problem, we use overdone_heads to slightly
+% reduce the notehead height. Empirically, we have determined that
+% reducing by 10% of stafflinethickness solves the problem.
+
+overdone_heads = -0.1;
noteheight# := staff_space# + (1 + overdone_heads) * stafflinethickness#;
define_pixels (slash_thick);
#, fuzzy
msgid ""
msgstr ""
-"Project-Id-Version: lilypond 2.19.37\n"
+"Project-Id-Version: lilypond 2.19.38\n"
"Report-Msgid-Bugs-To: http://post.gmane.org/post.php?group=gmane.comp.gnu."
"lilypond.bugs\n"
-"POT-Creation-Date: 2016-02-28 13:14+0000\n"
+"POT-Creation-Date: 2016-03-13 12:28+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
msgid "Language does not support microtones contained in the piece"
msgstr ""
-#: musicexp.py:491
+#: musicexp.py:497
msgid "Tuplet brackets of curved shape are not correctly implemented"
msgstr ""
-#: musicexp.py:677
+#: musicexp.py:683
#, python-format
msgid "unable to set the music %(music)s for the repeat %(repeat)s"
msgstr ""
-#: musicexp.py:686
+#: musicexp.py:692
msgid "encountered repeat without body"
msgstr ""
#. no self.elements!
-#: musicexp.py:856
+#: musicexp.py:862
#, python-format
msgid "Grace note with no following music: %s"
msgstr ""
-#: musicexp.py:1018
+#: musicexp.py:1024
#, python-format
msgid "Invalid octave shift size found: %s. Using no shift."
msgstr ""
-#: musicexp.py:1476
+#: musicexp.py:1482
#, python-format
msgid "Unable to convert alteration %s to a lilypond expression"
msgstr ""
#. TODO: Handle pieces without a time signature!
-#: musicxml.py:361
+#: musicxml.py:362
msgid "Senza-misura time signatures are not yet supported!"
msgstr ""
-#: musicxml.py:379
+#: musicxml.py:380
msgid "Unable to interpret time signature! Falling back to 4/4."
msgstr ""
-#: musicxml.py:435
+#: musicxml.py:436
#, python-format
msgid ""
"Key alteration octave given for a non-existing alteration nr. %s, available "
"numbers: %s!"
msgstr ""
-#: musicxml.py:523
+#: musicxml.py:524
#, python-format
msgid "Unable to find instrument for ID=%s\n"
msgstr ""
msgid "natural alteration glyph not found"
msgstr ""
-#: all-font-metrics.cc:159
+#: all-font-metrics.cc:161
#, c-format
msgid "cannot find font: `%s'"
msgstr ""
msgid "identifier name is a keyword: `%s'"
msgstr ""
-#: lily-lexer.cc:299 lily-lexer.cc:312
+#: lily-lexer.cc:301 lily-lexer.cc:314
#, c-format
msgid "%s:EOF"
msgstr ""
msgid "Parsing..."
msgstr ""
-#: lookup.cc:178
+#: lookup.cc:177
#, c-format
msgid "Not drawing a box with negative dimension, %.2f by %.2f."
msgstr ""
msgid "giving up"
msgstr ""
-#: parser.yy:476 parser.yy:947 parser.yy:1028 parser.yy:1248
+#: parser.yy:478 parser.yy:949 parser.yy:1030 parser.yy:1250
msgid "bad expression type"
msgstr ""
-#: parser.yy:859 parser.yy:1458 parser.yy:1503
+#: parser.yy:861 parser.yy:1460 parser.yy:1505
msgid "not a context mod"
msgstr ""
-#: parser.yy:1054
+#: parser.yy:1056
msgid "Missing music in \\score"
msgstr ""
-#: parser.yy:1091
+#: parser.yy:1093
msgid "\\paper cannot be used in \\score, use \\layout instead"
msgstr ""
-#: parser.yy:1126
+#: parser.yy:1128
msgid "Spurious expression in \\score"
msgstr ""
-#: parser.yy:1156
+#: parser.yy:1158
msgid "need \\paper for paper block"
msgstr ""
-#: parser.yy:1331
+#: parser.yy:1333
msgid "music expected"
msgstr ""
-#: parser.yy:1341 parser.yy:1375
+#: parser.yy:1343 parser.yy:1377
msgid "unexpected post-event"
msgstr ""
-#: parser.yy:1383
+#: parser.yy:1385
msgid "Ignoring non-music expression"
msgstr ""
-#: parser.yy:1691
+#: parser.yy:1693
msgid "not a symbol"
msgstr ""
-#: parser.yy:2491 parser.yy:2605 parser.yy:2618 parser.yy:2627
+#: parser.yy:2562 parser.yy:2676 parser.yy:2689 parser.yy:2698
msgid "bad grob property path"
msgstr ""
-#: parser.yy:2585
+#: parser.yy:2656
msgid "only \\consists and \\remove take non-string argument."
msgstr ""
-#: parser.yy:2646
+#: parser.yy:2717
msgid "bad context property path"
msgstr ""
-#: parser.yy:2731
+#: parser.yy:2802
msgid "markup expected"
msgstr ""
-#: parser.yy:2743
+#: parser.yy:2814
msgid "simple string expected"
msgstr ""
-#: parser.yy:2760
+#: parser.yy:2831
msgid "symbol expected"
msgstr ""
-#: parser.yy:2896
+#: parser.yy:2967
msgid "not a rhythmic event"
msgstr ""
-#: parser.yy:2946
+#: parser.yy:3017
msgid "post-event expected"
msgstr ""
-#: parser.yy:2955 parser.yy:2960
+#: parser.yy:3026 parser.yy:3031
msgid "have to be in Lyric mode for lyrics"
msgstr ""
-#: parser.yy:3036
+#: parser.yy:3107
msgid "expecting string or post-event as script definition"
msgstr ""
-#: parser.yy:3140
+#: parser.yy:3211
msgid "not an articulation"
msgstr ""
-#: parser.yy:3212 parser.yy:3255
+#: parser.yy:3277 parser.yy:3329
msgid "not a duration"
msgstr ""
-#: parser.yy:3276
+#: parser.yy:3350
msgid "bass number expected"
msgstr ""
-#: parser.yy:3368
+#: parser.yy:3442
msgid "have to be in Note mode for notes"
msgstr ""
-#: parser.yy:3407
+#: parser.yy:3481
msgid "have to be in Chord mode for chords"
msgstr ""
-#: parser.yy:3450
+#: parser.yy:3524
msgid "markup outside of text script or \\lyricmode"
msgstr ""
-#: parser.yy:3455
+#: parser.yy:3529
msgid "unrecognized string, not in text script or \\lyricmode"
msgstr ""
-#: parser.yy:3607 parser.yy:3616
+#: parser.yy:3681 parser.yy:3690
msgid "not an unsigned integer"
msgstr ""
-#: parser.yy:3703
+#: parser.yy:3777
msgid "not a markup"
msgstr ""
msgid "bad make-music argument: ~S"
msgstr ""
-#: define-note-names.scm:1000
+#: define-note-names.scm:1107
msgid "Select note names language."
msgstr ""
-#: define-note-names.scm:1006
+#: define-note-names.scm:1113
#, scheme-format
msgid "Using `~a' note names..."
msgstr ""
-#: define-note-names.scm:1009
+#: define-note-names.scm:1116
#, scheme-format
msgid "Could not find language `~a'. Ignoring."
msgstr ""
msgid "do not know how to embed font ~s ~s ~s"
msgstr ""
-#: framework-ps.scm:728
+#: framework-ps.scm:751
msgid ""
"\n"
"The PostScript backend does not support the\n"
"\n"
" lilypond -dbackend=eps FILE\n"
"\n"
-"If have cut & pasted a lilypond fragment from a webpage, be sure\n"
+"If you have cut & pasted a lilypond fragment from a webpage, be sure\n"
"to only remove anything before\n"
"\n"
" %% ****************************************************************\n"
msgid "define-session used after session start"
msgstr ""
-#: lily.scm:417
+#: lily.scm:420
msgid "Using (ice-9 curried-definitions) module\n"
msgstr ""
-#: lily.scm:420
+#: lily.scm:423
msgid "Guile 1.8\n"
msgstr ""
-#: lily.scm:477
+#: lily.scm:480
#, scheme-format
msgid "cannot find: ~A"
msgstr ""
-#: lily.scm:903
+#: lily.scm:906
msgid "Success: compilation successfully completed"
msgstr ""
-#: lily.scm:904
+#: lily.scm:907
msgid "Compilation completed with warnings or errors"
msgstr ""
-#: lily.scm:965
+#: lily.scm:968
#, scheme-format
msgid "job ~a terminated with signal: ~a"
msgstr ""
-#: lily.scm:968
+#: lily.scm:971
#, scheme-format
msgid ""
"logfile ~a (exit ~a):\n"
"~a"
msgstr ""
-#: lily.scm:990 lily.scm:1079
+#: lily.scm:993 lily.scm:1082
#, scheme-format
msgid "failed files: ~S"
msgstr ""
-#: lily.scm:1070
+#: lily.scm:1073
#, scheme-format
msgid "Redirecting output to ~a..."
msgstr ""
-#: lily.scm:1089
+#: lily.scm:1092
#, scheme-format
msgid "Invoking `~a'...\n"
msgstr ""
r"\1\2.\3", str)
str = re.sub (r'''(\\(?:alterBroken|overrideProperty)\s+)#?"([A-Za-z]+)\s*\.\s*([A-Za-z]+)"''',
r"\1\2.\3", str)
- str = re.sub (r'''(\\tweak\s+)#?"?([A-Za-z]+)"?\s+?#'([-A-Za-z]+)''',
+ str = re.sub (r'''(\\tweak\s+)#?"?([A-W][A-Za-z]*)"?\s+?#'([a-zX-Z][-A-Za-z]*)''',
r"\1\2.\3", str)
- str = re.sub (r'''(\\tweak\s+)#'([-A-Za-z]+)''',
+ str = re.sub (r'''(\\tweak\s+)#'([a-zX-Z][-A-Za-z]*)''',
r"\1\2", str)
str = re.sub ("(" + matchmarkup + ")|"
+ r"(\\footnote(?:\s*"
def print_ly (self, func):
if self.display_bracket == None:
- func ("\\once \\override TupletBracket #'stencil = ##f")
+ func ("\\once \\omit TupletBracket")
func.newline ()
elif self.display_bracket == "curved":
ly.warning (_ ("Tuplet brackets of curved shape are not correctly implemented"))
- func ("\\once \\override TupletBracket #'stencil = #ly:slur::print")
+ func ("\\once \\override TupletBracket.stencil = #ly:slur::print")
func.newline ()
base_number_function = {None: "#f",
if self.display_type == "actual" and self.normal_type:
# Obtain the note duration in scheme-mode, i.e. \longa as \\longa
base_duration = self.normal_type.ly_expression (None, True)
- func ("\\once \\override TupletNumber #'text = #(tuplet-number::append-note-wrapper %s \"%s\")" %
+ func ("\\once \\override TupletNumber.text = #(tuplet-number::append-note-wrapper %s \"%s\")" %
(base_number_function, base_duration))
func.newline ()
elif self.display_type == "both": # TODO: Implement this using actual_type and normal_type!
if self.display_number == None:
- func ("\\once \\override TupletNumber #'stencil = ##f")
+ func ("\\once \\omit TupletNumber")
func.newline ()
elif self.display_number == "both":
den_duration = self.normal_type.ly_expression (None, True)
else:
num_duration = den_duration
if (self.display_denominator or self.display_numerator):
- func ("\\once \\override TupletNumber #'text = #(tuplet-number::non-default-fraction-with-notes %s \"%s\" %s \"%s\")" %
+ func ("\\once \\override TupletNumber.text = #(tuplet-number::non-default-fraction-with-notes %s \"%s\" %s \"%s\")" %
(self.display_denominator, den_duration,
self.display_numerator, num_duration))
func.newline ()
else:
- func ("\\once \\override TupletNumber #'text = #(tuplet-number::fraction-with-notes \"%s\" \"%s\")" %
+ func ("\\once \\override TupletNumber.text = #(tuplet-number::fraction-with-notes \"%s\" \"%s\")" %
(den_duration, num_duration))
func.newline ()
else:
if self.display_number == None:
- func ("\\once \\override TupletNumber #'stencil = ##f")
+ func ("\\once \\omit TupletNumber")
func.newline ()
elif self.display_number == "both":
- func ("\\once \\override TupletNumber #'text = #%s" % base_number_function)
+ func ("\\once \\override TupletNumber.text = #%s" % base_number_function)
func.newline ()
func ('\\times %d/%d ' %
"wavy" : "zigzag"
}. get (self.line_type, None)
if style:
- printer.dump ("\\once \\override Glissando #'style = #'%s" % style)
+ printer.dump ("\\once \\override Glissando.style = #'%s" % style)
def ly_expression (self):
return {-1: '\\glissando',
1:''}.get (self.span_direction, '')
self.filled = None
def pre_chord_ly (self):
if self.style:
- return "\\once \\override NoteHead #'style = #%s" % self.style
+ return "\\once \\override NoteHead.style = #%s" % self.style
else:
return ''
def pre_note_ly (self, is_chord_element):
if self.style and is_chord_element:
- return "\\tweak #'style #%s" % self.style
+ return "\\tweak style #%s" % self.style
else:
return ''
def ly_expression (self):
if self.style == "common":
st = "\\defaultTimeSignature"
elif (self.style != "'()"):
- st = "\\once \\override Staff.TimeSignature #'style = #%s " % self.style
+ st = "\\once \\override Staff.TimeSignature.style = #%s " % self.style
elif (self.style != "'()") or is_common_signature:
st = "\\numericTimeSignature"
self.lines = lines
def ly_expression (self):
if (self.lines > 0):
- return "\\stopStaff \\override Staff.StaffSymbol #'line-count = #%s \\startStaff" % self.lines
+ return "\\stopStaff \\override Staff.StaffSymbol.line-count = #%s \\startStaff" % self.lines
else:
- return "\\stopStaff \\revert Staff.StaffSymbol #'line-count \\startStaff"
+ return "\\stopStaff \\revert Staff.StaffSymbol.line-count \\startStaff"
class TempoMark (Music):
def __init__ (self):
if self.instrument_name or self.short_instrument_name:
printer.dump ("\\consists \"Instrument_name_engraver\"")
if self.spanbar == "no":
- printer.dump ("\\override SpanBar #'transparent = ##t")
+ printer.dump ("\\hide SpanBar")
brack = {"brace": "SystemStartBrace",
"none": "SystemStartBar",
"line": "SystemStartSquare"}.get (self.symbol, None)
(define-public (boolean-or-symbol? x)
(or (boolean? x) (symbol? x)))
+(define-public (key? x)
+ (or (symbol? x) (index? x)))
+
+(define-public (key-list? x)
+ (and (list? x) (every key? x)))
+
+(define-public (key-list-or-music? x)
+ (if (list? x)
+ (every key? x)
+ (ly:music? x)))
+
+(define-public (key-list-or-symbol? x)
+ (if (list? x)
+ (every key? x)
+ (symbol? x)))
+
(define-public (symbol-list? x)
(and (list? x) (every symbol? x)))
(,fraction? . "fraction, as pair")
(,grob-list? . "list of grobs")
(,index? . "non-negative integer")
+ (,key? . "index or symbol")
+ (,key-list? . "list of indexes or symbols")
+ (,key-list-or-music? . "key list or music")
+ (,key-list-or-symbol? . "key list or symbol")
(,markup? . "markup")
(,markup-command-list? . "markup command list")
(,markup-list? . "markup list")
staff = musicexp.Staff ()
# TODO: Handle case with lines <> 5!
if (lines != 5):
- staff.add_context_modification ("\\override StaffSymbol #'line-count = #%s" % lines)
+ staff.add_context_modification ("\\override StaffSymbol.line-count = #%s" % lines)
return staff