@node Indentation
@subsection Indentation
-Standard GNU coding style is used. In emacs:
+Standard GNU coding style is used.
-@verbatim
- (add-hook 'c++-mode-hook
- '(lambda() (c-set-style "gnu")
- ))
-@end verbatim
-
-If you like using font-lock, you can also add this to your
-@q{.emacs}:
-
-@verbatim
- (setq font-lock-maximum-decoration t)
- (setq c++-font-lock-keywords-3
- (append
- c++-font-lock-keywords-3
- '(("\\b\\(a-zA-Z_?+_\\)\\b" 1 font-lock-variable-name-face) ("\\b\\(A-Z?+a-z_?+\\)\\b" 1 font-lock-type-face))
- ))
-@end verbatim
+@subsubheading Indenting files with @code{fixcc.py} (recommended)
-Some source files may not currently have proper indenting. If this
-is the case, it is desirable to fix the improper indenting when the
-file is modified, with the hope of continually improving the code.
-
-
-@subheading Indenting files with fixcc.py
-
-LilyPond provides a python script that will correct the indentation
-on a c++ file:
+LilyPond provides a python script that will adjust the indentation
+and spacing on a @code{.cc} or @code{.hh} file to very near the
+GNU standard:
@example
-scripts/auxiliar/fixcc.py lily/my-test-file.cc
+scripts/auxiliar/fixcc.py FILENAME
@end example
-Be sure you replace @file{my-test-file.cc} with the name of the file
-that you edited.
-
-If you are editing a file that contains an ADD_TRANSLATOR or ADD_INTERFACE
-macro, the fixcc.py script will move the final parenthesis up one line
-from where it should be. Please check the end of the file before
-you run fixcc.py, and then put the final parenthesis and semicolon
-back on a line by themselves.
+This can be run on all files at once, but this is not recommended
+for normal contributors or developers.
+@smallexample
+scripts/auxiliar/fixcc.py \
+ fixcc $(find flower lily -name '*cc' -o -name '*hh' | grep -v /out)
+@end smallexample
-@subheading Indenting files with emacs in script mode
-@c email to wl@gnu.org when I get here.
+@subsubheading Indenting with emacs
-@warning{this is pending some confirmation on -devel. July 2009 -gp}
+The following hooks will produce indentation which is similar to
+our official indentation as produced with @code{fixcc.py}.
-Command-line script to format stuff with emacs:
+@example
+(add-hook 'c++-mode-hook
+ '(lambda ()
+ (c-set-style "gnu")
+ (setq indent-tabs-mode nil))
+@end example
-@smallexample
-#!/bin/sh
-emacs $1 -batch --eval '(indent-region (point-min) (point-max) nil)' -f save-buffer
-@end smallexample
+If you like using font-lock, you can also add this to your
+@file{.emacs}:
-(that's all on one line)
+@example
+(setq font-lock-maximum-decoration t)
+(setq c++-font-lock-keywords-3
+ (append
+ c++-font-lock-keywords-3
+ '(("\\b\\(a-zA-Z_?+_\\)\\b" 1 font-lock-variable-name-face) ("\\b\\(A-Z?+a-z_?+\\)\\b" 1 font-lock-type-face))
+ ))
+@end example
-Save it as a shell script, then run on the file(s) you modified.
@subheading Indenting with vim
-Although emacs indentation is the LilyPond standard, acceptable
+Although emacs indentation is the GNU standard, acceptable
indentation can usually be accomplished with vim. Some hints for
vim are as follows:
A workable .vimrc:
-@verbatim
+@example
set cindent
set smartindent
set autoindent
set ignorecase smartcase
set hlsearch
set confirm
-set statusline=%F%m%r%h%w\ %{&ff}\ %Y\ [ASCII=\%03.3b]\ [HEX=\%02.2B]\ %04l,%04v\ %p%%\ [LEN=%L]
+set statusline=%F%m%r%h%w\ %@{&ff@}\ %Y\ [ASCII=\%03.3b]\ [HEX=\%02.2B]\ %04l,%04v\ %p%%\ [LEN=%L]
set laststatus=2
set number
" Remove trailing whitespace on write
autocmd BufWritePre * :%s/\s\+$//e
-@end verbatim
+@end example
-With this .vimrc, files can be reindented automatically by highlighting
-the lines to be indented in visual mode (use V to enter visual mode)
-and pressing =.
+With this @file{.vimrc}, files can be reindented automatically by
+highlighting the lines to be indented in visual mode (use V to
+enter visual mode) and pressing @code{=}.
-A scheme.vim file will help improve the indentation. This one
-was suggested by Patrick McCarty. It should be saved in
-~/.vim/after/syntax/scheme.vim.
+A @file{scheme.vim} file will help improve the indentation. This
+one was suggested by Patrick McCarty. It should be saved in
+@file{~/.vim/after/syntax/scheme.vim}.
-@verbatim
+@example
" Additional Guile-specific 'forms'
syn keyword schemeSyntax define-public define*-public
syn keyword schemeSyntax define* lambda* let-keywords*
" Try to highlight all ly: procedures
syn match schemeFunc "ly:[^) ]\+"
-@end verbatim
+@end example
@node Naming conventions
@item @code{@var{typeN?}}
@tab a scheme @emph{type predicate} for which @code{@var{argN}}
-must return @code{#t}.
+must return @code{#t}. Some of these predicates are specially
+recognized by the parser, making the respective values be read in
+Lilypond syntax rather than in Scheme syntax. Currently these are
+@code{ly:music?}, @code{markup?}, @code{ly:pitch?}, and
+@code{ly:duration?}. Not all combinations are allowed: i.e., you can't
+look for a duration after music since music may end @emph{optionally}
+with a duration.
+
+If you really want to input some of those items as a Scheme rather than
+a Lilypond expression, you may wrap them in a call of @code{ly:export}.
+@c TODO: document what kind of argument lists are permitted in what
+@c syntactical context of a music function call.
@item @code{@var{music}}
@tab A music expression, optionally written in scheme, with any
We will have an extensive discussion period to determine the final
input specification.
-@warning{GLISS will start shortly after 2.14 is released.}
+@warning{GLISS will start shortly after 2.16 is released.}
@subsubheading Grand Organizing Project
giving us a much more stable foundation so that we can move ahead
with larger tasks in the future.
-@warning{GOP will start shortly after the 2.14 release.}
-
@end macro
lilypond -dbackend=eps -dno-gs-load-fonts -dinclude-eps-fonts --png myfile.ly
A transparent PNG
-@end example
-@smallexample
-lilypond -dbackend=eps -dno-gs-load-fonts -dinclude-eps-fonts -dpixmap-format=pngalpha --png myfile.ly
-@end smallexample
+lilypond -dbackend=eps -dno-gs-load-fonts -dinclude-eps-fonts \
+ -dpixmap-format=pngalpha --png myfile.ly
+@end example
@node Independent includes
@c used for news about the upcoming release; see CG 10.2
+@newsItem
+@subsubheading LilyPond 2.14.2 released! @emph{July 25, 2011}
+
+We are happy to announce the release of LilyPond 2.14.2. This
+fixes a few minor bugs in the stable version, and should cause no
+problems. We recommend that everybody upgrade to this version.
+
+@newsEnd
+
@newsItem
@subsubheading LilyPond 2.15.5 released! @emph{July 12, 2011}
MINOR_VERSION=15
PATCH_LEVEL=6
MY_PATCH_LEVEL=
-VERSION_STABLE=2.14.1
+VERSION_STABLE=2.14.2
VERSION_DEVEL=2.15.5
\test "" ##[ \once \override Beam #'beam-thickness = #0.6 #]
\test "" ##[ \revert Staff . Stem #'thickness #] % RevertProperty
\test "" ##[ \revert Beam #'beam-thickness #]
+\test "NOT A BUG" ##[ \oneVoice #] % resetting a bunch of properties
+\test "" ##[ \override StaffGrouper #'(staff-staff-spacing basic-distance) = #7 #] % nested properties
+\test "" ##[ \revert StaffGrouper #'(staff-staff-spacing basic-distance) #] % nested properties
%% \applyOutput
\test "" ##[ \applyOutput #'Foo #(lambda (arg) (list)) #]
\version "2.14.0"
\header {
-texidoc = "Whole and half rests moving outside the staff should get
+texidoc = "Breve, whole and half rests moving outside the staff should get
ledger lines."
}
-\paper { ragged-right = ##t }
+\paper { ragged-right = ##t }
+
+rPos =
+#(define-music-function (parser location y) (number?)
+ #{ \override Rest #'staff-position = #$y #})
{
- \override Rest #'staff-position = #4
- r1 \override Rest #'staff-position = #5
- r1 \override Rest #'staff-position = #6
-
- r1 \override Rest #'staff-position = #-6
- r1 \override Rest #'staff-position = #-7
- r1 \override Rest #'staff-position = #-8
- r1
-
- \override Rest #'staff-position = #6
- r2 \override Rest #'staff-position = #7
- r2 \override Rest #'staff-position = #8
-
- r2 \override Rest #'staff-position = #-4
- r2 \override Rest #'staff-position = #-5
- r2 \override Rest #'staff-position = #-6
- r2
+ \set Score.timing = ##f
+ \rPos #2
+ r\breve \rPos #4
+ r \rPos #5
+ r \rPos #-4
+ r \rPos #-6
+ r \rPos #-7
+ r
+
+ \rPos #2
+ r1 \rPos #4
+ r \rPos #5
+ r \rPos #-6
+ r \rPos #-7
+ r \rPos #-8
+ r
+
+ \rPos #4
+ r2 \rPos #6
+ r \rPos #7
+ r \rPos #-4
+ r \rPos #-6
+ r \rPos #-7
+ r
}
\version "2.14.0"
\header {
- texidoc="Festival song synthesis output supports
+ texidoc = "Festival song synthesis output supports
lyrics which are not complete words.
"
}
\include "festival.ly"
-#(set! *skip-word* #f)
+#(*skip-word* #f)
\festival #"song-skip-noword.xml" { \tempo 4 = 100 }
-\relative c' { c c g' }
+\relative c' { c4 c g' }
\addlyrics {
twin -- \skip 4
kle
}
+
#(ly:progress "song-skip-noword")
#(ly:progress "~a" (ly:gulp-file "song-skip-noword.xml"))
+
+#(*skip-word* "-skip-")
--- /dev/null
+\version "2.15.6"
+
+\header {
+ texidoc = "When the staff-space is increased, the system-start delimiter
+should still be collapsed (i.e. the collapse-height should not give an absolute
+length, but a multiple of staff-spaces)."
+}
+
+\new Staff \with { \override StaffSymbol #'staff-space = #1.4 }
+{
+ a4 b c d
+}
INSTANTIATE_COMPARE (Duration, Duration::compare);
DECLARE_UNSMOB (Duration, duration);
+extern SCM Duration_type_p_proc;
+
#endif // DURATION_HH
extern SCM pitch_less_proc;
Pitch pitch_interval (Pitch const &from, Pitch const &to);
+extern SCM Pitch_type_p_proc;
#endif /* PITCH_HH */
using namespace std;
#include "context-def.hh"
+#include "duration.hh"
#include "identifier-smob.hh"
#include "international.hh"
#include "interval.hh"
#include "music-function.hh"
#include "parse-scm.hh"
#include "parser.hh"
+#include "pitch.hh"
#include "source-file.hh"
#include "std-string.hh"
#include "string-convert.hh"
push_extra_token (EXPECT_NO_MORE_ARGS);
for (; scm_is_pair (s); s = scm_cdr (s))
{
- if (scm_car (s) == ly_music_p_proc)
+ SCM cs = scm_car (s);
+
+ if (cs == ly_music_p_proc)
push_extra_token (EXPECT_MUSIC);
- else if (scm_car (s) == ly_lily_module_constant ("markup?"))
+ else if (cs == Pitch_type_p_proc)
+ push_extra_token (EXPECT_PITCH);
+ else if (cs == Duration_type_p_proc)
+ push_extra_token (EXPECT_DURATION);
+ else if (cs == ly_lily_module_constant ("markup?"))
push_extra_token (EXPECT_MARKUP);
- else if (ly_is_procedure (scm_car (s)))
+ else if (ly_is_procedure (cs))
push_extra_token (EXPECT_SCM);
else programming_error ("Function parameter without type-checking predicate");
}
/* Artificial tokens, for more generic function syntax */
%token <i> EXPECT_MARKUP;
%token <i> EXPECT_MUSIC;
+%token <i> EXPECT_PITCH;
+%token <i> EXPECT_DURATION;
%token <i> EXPECT_SCM;
%token <i> EXPECT_MARKUP_LIST
/* After the last argument. */
/* Music */
%type <scm> composite_music
%type <scm> grouped_music_list
+%type <scm> closed_music
%type <scm> music
%type <scm> prefix_composite_music
%type <scm> repeated_music
| grouped_music_list { $$ = $1; }
;
+/* Music that can't be followed by additional events or durations */
+closed_music:
+ MUSIC_IDENTIFIER
+ | grouped_music_list
+ ;
+
grouped_music_list:
simultaneous_music { $$ = $1; }
| sequential_music { $$ = $1; }
;
function_arglist_nonmusic_last:
- EXPECT_MARKUP function_arglist full_markup {
+ EXPECT_NO_MORE_ARGS {
+ /* This is for 0-ary functions, so they don't need to
+ read a lookahead token */
+ $$ = SCM_EOL;
+ }
+ | EXPECT_MARKUP function_arglist full_markup {
$$ = scm_cons ($3, $2);
}
| EXPECT_MARKUP function_arglist simple_string {
$$ = scm_cons ($3, $2);
}
+ | EXPECT_PITCH function_arglist pitch {
+ $$ = scm_cons ($3, $2);
+ }
+ | EXPECT_DURATION function_arglist_nonmusic_last duration_length {
+ $$ = scm_cons ($3, $2);
+ }
| EXPECT_SCM function_arglist function_scm_argument {
$$ = scm_cons ($3, $2);
}
| EXPECT_MARKUP function_arglist_nonmusic simple_string {
$$ = scm_cons ($3, $2);
}
+ | EXPECT_PITCH function_arglist_nonmusic pitch {
+ $$ = scm_cons ($3, $2);
+ }
+ | EXPECT_DURATION function_arglist_nonmusic duration_length {
+ $$ = scm_cons ($3, $2);
+ }
| EXPECT_SCM function_arglist_nonmusic function_scm_argument {
$$ = scm_cons ($3, $2);
}
;
-function_arglist: EXPECT_NO_MORE_ARGS {
- /* This is for 0-ary functions, so they don't need to
- read a lookahead token */
- $$ = SCM_EOL;
- }
- | function_arglist_music_last
+function_arglist:
+ function_arglist_music_last
| function_arglist_nonmusic_last
;
generic_prefix_music_scm:
MUSIC_FUNCTION function_arglist {
- $$ = ly_append2 (scm_list_2 ($1, make_input (@$)), scm_reverse_x ($2, SCM_EOL));
+ $$ = scm_cons ($1, scm_cons (make_input (@$), scm_reverse_x ($2, SCM_EOL)));
}
;
new_lyrics:
ADDLYRICS { PARSER->lexer_->push_lyric_state (); }
/*cont */
- grouped_music_list {
+ closed_music {
/* Can also use music at the expensive of two S/Rs similar to
\repeat \alternative */
PARSER->lexer_->pop_state ();
$$ = scm_cons ($3, SCM_EOL);
}
- | ADDLYRICS {
- PARSER->lexer_->push_lyric_state (); }
- MUSIC_IDENTIFIER {
- PARSER->lexer_->pop_state ();
- $$ = scm_cons ($3, SCM_EOL);
- }
- | new_lyrics ADDLYRICS {
- PARSER->lexer_->push_lyric_state ();
- } grouped_music_list {
- PARSER->lexer_->pop_state ();
- $$ = scm_cons ($4, $1);
- }
| new_lyrics ADDLYRICS {
PARSER->lexer_->push_lyric_state ();
- } MUSIC_IDENTIFIER {
+ } closed_music {
PARSER->lexer_->pop_state ();
$$ = scm_cons ($4, $1);
}
;
re_rhythmed_music:
- grouped_music_list new_lyrics {
- $$ = MAKE_SYNTAX ("add-lyrics", @$, $1, scm_reverse_x ($2, SCM_EOL));
- }
- | MUSIC_IDENTIFIER new_lyrics {
+ closed_music new_lyrics {
$$ = MAKE_SYNTAX ("add-lyrics", @$, $1, scm_reverse_x ($2, SCM_EOL));
}
| LYRICSTO simple_string {
}
| DRUM_PITCH post_events {
Music *n = MY_MAKE_MUSIC ("NoteEvent", @$);
- n->set_property ("duration", $2);
n->set_property ("drum-type", $1);
if (scm_is_pair ($2)) {
but it's more consistent with music_function_event if we
prohibit it here too */
music_function_identifier_musicless_prefix EXPECT_MUSIC function_arglist_nonmusic chord_body_element {
- $$ = ly_append2 (scm_list_2 ($1, make_input (@$)), scm_reverse_x ($3, scm_list_1 ($4)));
+ $$ = scm_cons ($1, scm_cons (make_input (@$), scm_reverse_x ($3, scm_list_1 ($4))));
}
| music_function_identifier_musicless_prefix function_arglist_nonmusic {
- $$ = ly_append2 (scm_list_2 ($1, make_input (@$)), scm_reverse_x ($2, SCM_EOL));
+ $$ = scm_cons ($1, scm_cons (make_input (@$), scm_reverse_x ($2, SCM_EOL)));
}
;
restriction we get a shift/reduce conflict from e.g.
c8-\partcombine c8 -. */
music_function_identifier_musicless_prefix EXPECT_MUSIC function_arglist_nonmusic post_event {
- $$ = ly_append2 (scm_list_2 ($1, make_input (@$)), scm_reverse_x ($3, scm_list_1 ($4)));
+ $$ = scm_cons ($1, scm_cons (make_input (@$), scm_reverse_x ($3, scm_list_1 ($4))));
}
| music_function_identifier_musicless_prefix function_arglist_nonmusic {
- $$ = ly_append2 (scm_list_2 ($1, make_input (@$)), scm_reverse_x ($2, SCM_EOL));
+ $$ = scm_cons ($1, scm_cons (make_input (@$), scm_reverse_x ($2, SCM_EOL)));
}
;
map<string, Audio_staff*> staff_map_;
map<string, int> channel_map_;
map<string, Audio_dynamic*> dynamic_map_;
+ // Would prefer to have the following two items be
+ // members of the containing class Performance,
+ // so they can be reset for each new midi file output.
static map<string, int> static_channel_map_;
static int channel_count_;
+ // For now, ask the last Staff_performer clean up during its finalize method
+ static int staff_performer_count_;
};
map<string, int> Staff_performer::static_channel_map_;
int Staff_performer::channel_count_ = 0;
+int Staff_performer::staff_performer_count_ = 0;
#include "translator.icc"
void
Staff_performer::initialize ()
{
+ ++staff_performer_count_;
}
Audio_staff*
{
staff_map_.clear ();
channel_map_.clear ();
+ if (staff_performer_count_)
+ --staff_performer_count_;
+ if (0 == staff_performer_count_)
+ {
+ static_channel_map_.clear ();
+ channel_count_ = 0;
+ }
}
string
Grob *common = common_refpoint_of_array (elts, me, Y_AXIS);
Interval ext;
+ Real staffspace = 1.0;
int non_empty_count = 0;
for (vsize i = elts.size (); i--;)
{
{
non_empty_count ++;
ext.unite (dims);
+ staffspace = Staff_symbol_referencer::staff_space (sp);
}
}
}
SCM glyph_sym = me->get_property ("style");
Real len = ext.length ();
+
+ // Use collapse-height in multiples of the staff-space
if (ext.is_empty ()
- || (robust_scm2double (me->get_property ("collapse-height"), 0.0) >= ext.length ()))
+ || (robust_scm2double (me->get_property ("collapse-height"), 0.0) >= (len / staffspace)))
{
me->suicide ();
return SCM_UNSPECIFIED;
\version "2.14.0"
#(use-modules (scm song))
+#(use-modules (srfi srfi-39))
% \festival #"filename" { \tempo N = X } { music }
festival =
-#(define-music-function (parser location filename tempo music) (string? ly:music? ly:music?)
- (output-file music tempo filename)
- music)
+#(define-music-function (parser location filename tempo music)
+ (string? ly:music? ly:music?)
+ (output-file music tempo filename)
+ music)
% \festivalsyl #"filename" { \tempo N = X } { music }
festivalsyl =
-#(define-music-function (parser location filename tempo music) (string? ly:music? ly:music?)
- (set! *syllabify* #t)
- (output-file music tempo filename)
- music)
+#(define-music-function (parser location filename tempo music)
+ (string? ly:music? ly:music?)
+ (parameterize ((*syllabify* #t))
+ (output-file music tempo filename))
+ music)
/draw_round_box % width height x y blot
{
- setlinewidth % w h x y
- 0 setlinecap
- 1 setlinejoin
+ dup
+ 0.0 gt {
+ setlinewidth % w h x y
+ 0 setlinecap
+ 1 setlinejoin
- rmoveto % w h
- currentpoint % w h x1 y1
- 4 2 roll % x1 y1 w h
- 4 copy
- rectfill
- rectstroke
+ rmoveto % w h
+ currentpoint % w h x1 y1
+ 4 2 roll % x1 y1 w h
+ 4 copy
+ rectfill
+ rectstroke
+ } {
+ pop % w h x y
+ rmoveto % w h
+ currentpoint % w h x1 y1
+ 4 2 roll % x1 y1 w h
+ rectfill
+ } ifelse
} bind def
/draw_polygon % fill? x(n) y(n) x(n-1) y(n-1) ... x(0) y(0) n blot
continue
if isinstance (n, Attributes):
- # assign these only to the voices they really belongs to!
+ # assign these only to the voices they really belong to!
for (s, vids) in staff_to_voice_dict.items ():
staff_attributes = part.extract_attributes_for_staff (n, s)
if staff_attributes:
(define-display-method OverrideProperty (expr parser)
(let* ((symbol (ly:music-property expr 'symbol))
- (property-path (ly:music-property expr 'grob-property-path))
- (properties (if (pair? property-path)
- property-path
- (list (ly:music-property expr 'grob-property))))
+ (properties (ly:music-property expr 'grob-property-path
+ (list (ly:music-property expr 'grob-property))))
(value (ly:music-property expr 'grob-value))
(once (ly:music-property expr 'once)))
(new-line->lily-string))))
(define-display-method RevertProperty (expr parser)
- (let ((symbol (ly:music-property expr 'symbol))
- (properties (ly:music-property expr 'grob-property-path)))
+ (let* ((symbol (ly:music-property expr 'symbol))
+ (properties (ly:music-property expr 'grob-property-path
+ (list (ly:music-property expr 'grob-property)))))
(format #f "\\revert ~a~a #'~a~a"
(if (eqv? (*current-context*) 'Bottom)
""
;;;; along with LilyPond. If not, see <http://www.gnu.org/licenses/>.
-(define-module (scm song))
-
-(use-modules (srfi srfi-1))
-(use-modules (ice-9 optargs))
-(use-modules (ice-9 receive))
-
-(use-modules (lily))
-(use-modules (scm song-util))
+(define-module (scm song)
+ #:use-module (srfi srfi-1)
+ #:use-module (srfi srfi-39)
+ #:use-module (ice-9 optargs)
+ #:use-module (ice-9 receive)
+ #:use-module (lily)
+ #:use-module (scm song-util))
;;; Configuration
;; The word to be sung in places where notes are played without lyrics.
;; If it is #f, the places without lyrics are omitted on the output.
-(define-public *skip-word* "-skip-")
+(define-public *skip-word* (make-parameter "-skip-"))
;; If true, use syllables in the Festival XML file.
;; If false, use whole words instead; this is necessary in languages like
;; English, were the phonetic form cannot be deduced from syllables well enough.
-(define-public *syllabify* #f)
+(define-public *syllabify* (make-parameter #f))
;; Base Festival octave to which LilyPond notes are mapped.
-(define-public *base-octave* 5)
+(define-public *base-octave* (make-parameter 5))
;; The resulting base octave is sum of *base-octave* and
;; *base-octave-shift*. This is done to work around a Festival bug
;; causing Festival to segfault or produce invalid pitch on higher pitches.
;(define *base-octave-shift* -2)
-(define *base-octave-shift* 0)
+(define *base-octave-shift* (make-parameter 0))
;; The coeficient by which the notes just before \breath are shortened.
-(define-public *breathe-shortage* 0.8)
+(define-public *breathe-shortage* (make-parameter 0.8))
;;; LilyPond interface
(set! *default-tempo* (property-value
(find-child tempo-spec (lambda (elt)
(music-property? elt 'tempoWholesPerMinute)))))
- (round (* tempo (expt 2 (+ 2 *base-octave-shift*)))))))
+ (round (* tempo (expt 2 (+ 2 (*base-octave-shift*))))))))
(defstruct music-context
music
(push! (make-lyrics
#:text (ly:music-property lyric-event 'text)
#:duration (* (duration->number (ly:music-property lyric-event 'duration)) 4)
- #:unfinished (and (not *syllabify*) (find-child-named music 'HyphenEvent))
+ #:unfinished (and (not (*syllabify*)) (find-child-named music 'HyphenEvent))
#:ignore-melismata ignore-melismata
#:context current-voice)
lyrics-list))
((music-name? music 'BreathingEvent)
(if last-note-spec
(let* ((note-duration (note-duration last-note-spec))
- (rest-spec (make-rest #:duration (* note-duration (- 1 *breathe-shortage*))
+ (rest-spec (make-rest #:duration (* note-duration (- 1 (*breathe-shortage*)))
#:origin (ly:music-property music 'origin))))
- (set-note-duration! last-note-spec (* note-duration *breathe-shortage*))
+ (set-note-duration! last-note-spec (* note-duration (*breathe-shortage*)))
(add! (make-score-notes #:note/rest-list (list rest-spec)) result-list))
(warning music "\\\\breathe without previous note known")))
;; anything else
last-verse
(append (verse-notelist/rests last-verse) (list notelist/rest))))))
((pair? notelist/rest)
- (add! (make-verse #:text *skip-word* #:notelist/rests (list notelist/rest))
+ (add! (make-verse #:text (*skip-word*) #:notelist/rests (list notelist/rest))
verse-list))
(else
(error "Unreachable branch reached")))
((< duration (- epsilon))
(warning (if (null? note-list) (safe-last consumed) (safe-car note-list))
"Skip misalignment: ~a ~a ~a ~a" context skip duration consumed)))
- (values (if *skip-word*
+ (values (if (*skip-word*)
consumed
'())
note-list)))
(octave (inexact->exact (floor (/ semitones 12))))
(tone (modulo semitones 12)))
(format #f "~a~a" (car (assoc-get tone festival-note-mapping))
- (+ octave *base-octave* *base-octave-shift*))))
+ (+ octave (*base-octave*) (*base-octave-shift*)))))
(define (write-header port tempo)
(let ((beats (or (tempo->beats tempo) 100)))
#!/usr/bin/env python
-# fixcc -- nitpick lily's c++ code
+# fixcc -- indent and space lily's c++ code
# This file is part of LilyPond, the GNU music typesetter.
#
# You should have received a copy of the GNU General Public License
# along with LilyPond. If not, see <http://www.gnu.org/licenses/>.
+# Performs string substitution on files, then applies astyle
+# (http://astyle.sourceforge.net)
# TODO
-# * maintainable rules: regexp's using whitespace (?x) and match names
-# <identifier>)
-# * trailing `*' vs. function definition
-# * do not break/change indentation of fixcc-clean files
-# * check lexer, parser
-# * rewrite in elisp, add to cc-mode
-# * using regexes is broken by design
-# * ?
-# * profit
+# Remove prefiltering as the equivalent formatting becomes available in
+# astyle, or as the prefiltering is deemed un-necessary.
+# Soon, this script might be replaced by a simple invocation of astyle
import __main__
import getopt
GLOBAL_CXX = 'GC++'
CXX = 'C++'
verbose_p = 0
-indent_p = 0
+indent_p = 1
rules = {
GLOBAL_CXX:
[
- # delete gratuitous block -- disabled because it breaks .h files
-# ('''\n( |\t)\s*{\n\s*(.*?)(?![{}]|\b(do|for|else|if|switch|while)\b);\n\s*}''',
-# '\n\\2;'),
+ # delete trailing whitespace
+ ('[ \t]*\n', '\n'),
],
CXX:
[
# space before parenthesis open
- ('([^\( \]])[ \t]*\(', '\\1 ('),
- # space after comma
- ("\([^'],\)[ \t]*", '\1 '),
- # delete gratuitous block -- disabled because it breaks .h files
-# ('''\n( |\t)\s*{\n\s*(.*?)(?![{}]|\b(do|for|else|if|switch|while)\b);\n\s*}''',
-# '\n\\2;'),
- # delete inline tabs
- ('(\w)\t+', '\\1 '),
+ ('([\w\)\]])\(', '\\1 ('),
# delete inline double spaces
- (' *', ' '),
- # delete space after parenthesis open
- ('\([ \t]*', '('),
+ ('(\S) +', '\\1 '),
# delete space before parenthesis close
- ('[ \t]*\)', ')'),
+ (' *\)', ')'),
# delete spaces after prefix
- ('(--|\+\+)[ \t]*([\w\)])', '\\1\\2'),
+ ('(--|\+\+) *([\w\(])', '\\1\\2'),
# delete spaces before postfix
- ('([\w\)\]])[ \t]*(--|\+\+)', '\\1\\2'),
- # delete space after parenthesis close
- #('\)[ \t]*([^\w])', ')\\1'),
+ ('([\w\)\]]) *(--|\+\+)', '\\1\\2'),
+
# delete space around operator
- # ('([\w\(\)\]])([ \t]*)(::|\.)([ \t]*)([\w\(\)])', '\\1\\3\\5'),
- ('([\w\(\)\]])([ \t]*)(\.|->)([ \t]*)([\w\(\)])', '\\1\\3\\5'),
+ ('([\w\(\)\]]) *(\.|->) *([\w\(\)])', '\\1\\2\\3'),
# delete space after operator
- ('(::)([ \t]*)([\w\(\)])', '\\1\\3'),
+ ('(::) *([\w\(\)])', '\\1\\2'),
+
# delete superflous space around operator
- ('([\w\(\)\]])([ \t]+)(&&|\|\||<=|>=|!=|\|=|==|\+=|-=|\*=|/=|\?|<|>|\+|-|=|/|:|&|\||\*)([ \t]+)([\w\(\)])', '\\1 \\3 \\5'),
- # space around operator1
- ('([\w\)\]]) *(&&|\|\||<=|>=|!=|\|=|==|\+=|-=|\*=|/=|\?|<|>|=|/|:|&|\||\*) *([\w\(])', '\\1 \\2 \\3'),
- # space around operator2
- ('([\w\)\]]) *(&&|\|\||<=|>=|!=|\|=|==|\+=|-=|\*=|/=|\?|<|>|=|/|:|&|\||\*) ([^\w\s])', '\\1 \\2 \\3'),
- # space around operator3
- ('([^\w\s]) (&&|\|\||<=|>=|!=|\|=|==|\+=|-=|\*=|/=|\?|<|[^-]>|=|/|:|&|\||\*) *([\w\(])', '\\1 \\2 \\3'),
- # space around operator4
- ('([\w\(\)\]]) (\*|/|\+|-) *([-:])', '\\1 \\2 \\3'),
- # space around +/-; exponent
- ('([\w\)\]])(\+|-)([_A-Za-z\(])', '\\1 \\2 \\3'),
- ('([_\dA-Za-df-z\)\]])(\+|-)([\w\(])', '\\1 \\2 \\3'),
- # trailing operator, but don't un-trail #include
- (' (::|&&|\|\||<=|>=|!=|\|=|==|\+=|-=|\*=|/=|\?|<|>|\+|-|=|/|:|&XXX|\||\*XXX)[ \t]*\n([ \t]*)(?!#include)', '\n\\2\\1 '),
- # pointer
- ##('(bool|char|const|delete|int|stream|unsigned|void|size_t|struct \w+|[A-Z]\w*|,|;|&&|<|[^-]>|\|\||-|\+)[ \t]*(\*|&)[ \t]*', '\\1 \\2'),
- ('(bool|char|const|delete|int|stream|unsigned|void|vsize|size_t|struct \w+|[A-Z]\w*|,|;|:|=|\?\)|&&|<|[^-]>|\|\||-|\+)[ \t]*(\*|&)[ \t]*', '\\1 \\2'),
- #to#('(bool|char|const|delete|int|stream|unsigned|void|([A-Z]\w*)|[,])[ \n\t]*(\*|&)[ \t]*', '\\1 \\3'),
- # pointer with template
- ('(( *((bool|char|const|delete|int|stream|unsigned|void|size_t|class[ \t]+\w*|[A-Z]\w*|\w+::\w+|[,])\s*[\*&],*)+)>) *(\*|&) *', '\\1 \\5'),
- #to#('(( *((bool|char|delete|int|stream|unsigned|void|(class[ \t]+\w*)|([A-Z]\w*)|[,])[ \*&],*)+)>)[ \t\n]*(\*|&) *', '\\1 \\7'),
- # unary pointer, minus, not
- ('(return|=|&&|\|\|) (\*|&|-|!) ([\w\(])', '\\1 \\2\\3'),
+ ('([\w\(\)\]]) +(&&|\|\||<=|>=|!=|\|=|==|\+=|-=|\*=|/=|\?|<|>|\+|-|=|/|:|&|\||\*) +([\w\(\)])', '\\1 \\2 \\3'),
+
+ # trailing operator, but don't un-trail close angle-braces > nor pointer *, and not before a preprocessor line
+ (' (::|&&|\|\||<=|>=|!=|\|=|==|\+=|-=|\*=|/=|\?|<|\+|-|=|/|:|&XXX|\||\*XXX) *\n( *)([^\s#])', '\n\\2\\1 \\3'),
# space after `operator'
('(\Woperator) *([^\w\s])', '\\1 \\2'),
- # dangling brace close
- ('\n[ \t]*(\n[ \t]*})', '\\1'),
- # dangling newline
- ('\n[ \t]*\n[ \t]*\n', '\n\n'),
- # dangling parenthesis open
- #('[ \t]*\n[ \t]*\([ \t]*\n', '('),
- ('\([ \t]*\n', '('),
- # dangling parenthesis close
- ('\n[ \t]*\)', ')'),
+ # trailing parenthesis open
+ ('\( *\n *', '('),
+ # dangling parenthesis close: Disabled to leave ADD_TRANSLATOR format in place
+ #('\n *\)', ')'),
# dangling comma
- ('\n[ \t]*,', ','),
- # dangling semicolon, but don't un-dangle it onto #include
- ('(\n.*\n[ \t]*;)(?!\n#include)', '\\1'),
- # brace open, but not changing a #define... line
- ('(\w)[ \t]*([^\s]*){([ \t]*\n)(?!#define)', '\\1\\2\n{\n'),
- # brace open backslash
- ('(\w[^\n]*){[ \t]*\\\\\n', '\\1\\\n{\\\n'),
- # brace close
- ("}[ \t]*([^'\n]*\w[^\n\\\]*)\n", '}\n\\1\n'),
- # brace close backslash
- ("}[ \t]*([^'\n]*\w[^\n\\\]*)", '\n}\n\\1'),
- # delete space after `operator'
- #('(\Woperator) (\W)', '\\1\\2'),
+ ('\n( *),', ',\n\\1'),
# delete space after case, label
- ('(\W(case|label) ([\w]+)) :', '\\1:'),
+ ('(\W(case|label) [\w]+) :', '\\1:'),
# delete space before comma
- ('[ \t]*,', ','),
+ (' +,', ','),
# delete space before semicolon
- ('[ \t]*;', ';'),
- # delete space before eol-backslash
- ('[ \t]*\\\\\n', '\\\n'),
- # delete trailing whitespace
- ('[ \t]*\n', '\n'),
+ ('([^;]) +;', '\\1;'),
+ # dangling newline
+ ('\n\n+', '\n\n'),
- ## Deuglify code that also gets ugly by rules above.
- # delete newline after typedef struct
- ('(typedef struct\s+([\w]*\s){([^}]|{[^}]*})*})\s*\n\s*(\w[\w\d]*;)', '\\1 \\4'),
- # delete spaces around template brackets
- #('(dynamic_cast|template|([A-Z]\w*))[ \t]*<[ \t]*(( *(bool|char|int|unsigned|void|(class[ \t]+\w*)|([A-Z]\w*)),?)+)[ \t]?(| [\*&])[ \t]*>', '\\1<\\3\\8>'),
- ('(dynamic_cast|less|list|map|set|template|typedef|vector|\w+::\w+|[A-Z]\w*)[ \t]*<[ \t]*(( *(bool|char|const|string|int|unsigned|void|vsize|size_t|class[ \t]+\w*|[A-Z]\w*)( *[\*&]?,|[\*&])*)+)[ \t]?(| [\*&])[ \t]*>', '\\1<\\2\\6>'),
- ('(\w+::\w+|[A-Z]\w*) < ((\w+::\w+|[A-Z]\w*)<[A-Z]\w*>) >', '\\1<\\2 >'),
- ('((if|while)\s+\(([^\)]|\([^\)]*\))*\))\s*;', '\\1\n;'),
- ('(for\s+\(([^;]*;[^;]*;([^\)]|\([^\)]*\))*)\))\s*;', '\\1\n;'),
- # do {..} while
- ('(}\s*while\s*)(\(([^\)]|\([^\)]*\))*\))\s*;', '\\1\\2;'),
-
- ## Fix code that gets broken by rules above.
- ##('->\s+\*', '->*'),
- # delete space before #define x()
- ('#[ \t]*define (\w*)[ \t]*\(', '#define \\1('),
- # add space in #define x ()
- ('#[ \t]*define (\w*)(\(([^\(\)]|\([^\(\)]*\))*\)\\n)',
- '#define \\1 \\2'),
- # delete space in #include <>
- ('#[ \t]*include[ \t]*<[ \t]*([^ \t>]*)[ \t]*(/?)[ \t]*([^ \t>]*)[ \t]*>',
- '#include <\\1\\2\\3>'),
# delete backslash before empty line (emacs' indent region is broken)
('\\\\\n\n', '\n\n'),
],
COMMENT:
[
- # delete trailing whitespace
- ('[ \t]*\n', '\n'),
# delete empty first lines
('(/\*\n)\n*', '\\1'),
# delete empty last lines
no_match = 'a\ba'
snippet_res = {
CXX: {
+ 'define':
+ r'''(?x)
+ (?P<match>
+ (?P<code>
+ \#[ \t]*define[ \t]+([^\n]*\\\n)*[^\n]*))''',
+
'multiline_comment':
r'''(?sx)
(?P<match>
'singleline_comment':
r'''(?mx)
- ^.*
+ ^.*? # leave leading spaces for the comment snippet
(?P<match>
(?P<code>
- [ \t]*//([ \t][^\n]*|)\n))''',
+ [ \t]*//[^\n]*\n))''',
'string':
r'''(?x)
(?P<match>
(?P<code>
- "([^\"\n](\")*)*"))''',
+ "([^"\n]|\\")*"))''',
'char':
r'''(?x)
(?P<code>
'([^']+|\')))''',
- 'include':
- r'''(?x)
- (?P<match>
- (?P<code>
- "#[ \t]*include[ \t]*<[^>]*>''',
- },
- }
+ 'include':
+ r'''(?x)
+ (?P<match>
+ (?P<code>
+ \#[ \t]*include[ \t]*<[^>]*>))''',
+ },
+ }
class Chunk:
def replacement_text (self):
def nitpick_file (outdir, file):
s = open (file).read ()
+ t = s.expandtabs(8)
for i in rules[GLOBAL_CXX]:
- s = re.sub (i[0], i[1], s)
+ t = re.sub (i[0], i[1], t)
# FIXME: Containing blocks must be first, see
# find_toplevel_snippets.
# We leave simple strings be part of the code
snippet_types = (
+ 'define',
'multiline_comment',
'singleline_comment',
'string',
# 'char',
+ 'include',
)
- chunks = find_toplevel_snippets (s, snippet_types)
+ chunks = find_toplevel_snippets (t, snippet_types)
#code = filter (lambda x: is_derived_class (x.__class__, Substring),
# chunks)
indent_file (fixt)
def indent_file (file):
- emacs = '''emacs\
- --no-window-system\
- --batch\
- --no-site-file\
- --no-init-file\
- %(file)s\
- --eval '(let ((error nil)
- (version-control nil))
- (load-library "cc-mode")
- (c++-mode)
- (indent-region (point-min) (point-max))
- (if (buffer-modified-p (current-buffer))
- (save-buffer)))' ''' % vars ()
- emacsclient = '''emacsclient\
- --socket-name=%(socketdir)s/%(socketname)s\
- --no-wait\
- --eval '(let ((error nil)
- (version-control nil))
- (load-library "cc-mode")
- (find-file "%(file)s")
- (c++-mode)
- (indent-region (point-min) (point-max))
- (if (buffer-modified-p (current-buffer))
- (save-buffer)))' ''' \
- % { 'file': file,
- 'socketdir' : socketdir,
- 'socketname' : socketname, }
+ astyle = '''astyle\
+ --options=none --quiet -n \
+ --style=gnu --indent=spaces=2 \
+ --max-instatement-indent=60 \
+ --indent-cases \
+ --align-pointer=name --pad-oper \
+ --keep-one-line-blocks \
+ %(file)s
+ ''' % vars ()
if verbose_p:
- sys.stderr.write (emacs)
+ sys.stderr.write (astyle)
sys.stderr.write ('\n')
- os.system (emacs)
+ os.system (astyle)
def usage ():
Options:
--help
- --indent reindent, even if no changes
+ --lazy skip astyle, if no changes
--verbose
--test
Typical use with LilyPond:
- fixcc $(find flower kpath-guile lily -name '*cc' -o -name '*hh' | grep -v /out)
+ fixcc $(find flower lily -name '*cc' -o -name '*hh' | grep -v /out)
''')
def do_options ():
global indent_p, outdir, verbose_p
(options, files) = getopt.getopt (sys.argv[1:], '',
- ['help', 'indent', 'outdir=',
+ ['help', 'lazy', 'outdir=',
'test', 'verbose'])
for (o, a) in options:
if o == '--help':
usage ()
sys.exit (0)
- elif o == '--indent':
- indent_p = 1
+ elif o == '--lazy':
+ indent_p = 0
elif o == '--outdir':
outdir = a
elif o == '--verbose':
socketdir = '/tmp/fixcc'
socketname = 'fixcc%d' % os.getpid ()
-def setup_client ():
- #--no-window-system\
- #--batch\
- os.unlink (os.path.join (socketdir, socketname))
- os.mkdir (socketdir, 0700)
- emacs='''emacs\
- --no-site-file\
- --no-init-file\
- --eval '(let ((error nil)
- (version-control nil))
- (load-library "server")
- (setq server-socket-dir "%(socketdir)s")
- (setq server-name "%(socketname)s")
- (server-start)
- (while t) (sleep 1000))' ''' \
- % { 'socketdir' : socketdir,
- 'socketname' : socketname, }
-
- if not os.fork ():
- os.system (emacs)
- sys.exit (0)
- while not os.path.exists (os.path.join (socketdir, socketname)):
- time.sleep (1)
-
def main ():
- #emacsclient should be faster, but this does not work yet
- #setup_client ()
files = do_options ()
if outdir and not os.path.isdir (outdir):
os.makedirs (outdir)
import string
import codecs
import zipfile
+import tempfile
import StringIO
"""
if compressed:
if filename == "-":
progress (_ ("Input is compressed, extracting raw MusicXML data from stdin") )
- z = zipfile.ZipFile (sys.stdin)
+ # unfortunately, zipfile.ZipFile can't read directly from
+ # stdin, so copy everything from stdin to a temp file and read
+ # that. TemporaryFile() will remove the file when it is closed.
+ tmp = tempfile.TemporaryFile()
+ sys.stdin = os.fdopen(sys.stdin.fileno(), 'rb', 0) # Make sys.stdin binary
+ bytes_read = sys.stdin.read (8192)
+ while bytes_read:
+ for b in bytes_read:
+ tmp.write(b)
+ bytes_read = sys.stdin.read (8192)
+ z = zipfile.ZipFile (tmp, "r")
else:
progress (_ ("Input file %s is compressed, extracting raw MusicXML data") % filename)
z = zipfile.ZipFile (filename, "r")
all: default
$(LOOP)
+bin:
+ $(MAKE) PACKAGE=$(PACKAGE) package=$(package) -C lily
+
man:
$(LOOP)
@echo
@echo "Other generic targets:"
@echo " default same as the empty target"
+ @echo " bin check the lily directory and rebuild lilypond.exe if needed"
@echo " exe update all executables"
@echo " help this help"
@echo " lib update all libraries"