@end ignore
+@item
+Chords can be repeated using the @code{q} shortcut:
+
+@lilypond[verbatim,quote,relative=2]
+<c e g>8.-^ q16 q4-^
+@end lilypond
@item
Paper margin defaults, as specified in @file{ly/@/paper@/-defaults@/-init@/.ly}, apply
@item
In addition to the existing @code{\hspace} markup command,
a new @code{\vspace} command has been added to provide an easy
-and flexible way to add vertical space in markups. This feature
-is based on Nicolas Sceaux's work.
+and flexible way to add vertical space in markups.
@item
The direction of manual beams can be set with @code{^[} and @code{_[}.
@menu
* Chorded notes::
+* Chord repetition::
* Simultaneous expressions::
* Clusters::
@end menu
For more information about chords, see @ref{Chord notation}.
-
@seealso
Music Glossary:
@rglos{chord}.
@rlsr{Simultaneous notes}.
+@node Chord repetition
+@unnumberedsubsubsec Chord repetition
+
+In order to save typing, a shortcut can be used to repeat the preceding
+chord. The chord repetition symbol is @code{q}:
+
+@lilypond[verbatim,quote,relative=1]
+<c e g> q q q
+@end lilypond
+
+As in the case of regular chords, the chord repetition symbol can be
+followed by a duration and articulations. Only the pitches of the
+previous chord are duplicated; articulations, dynamics, etc, are not
+repeated.
+
+@lilypond[verbatim,quote,relative=1]
+<c e g>8\p q q4-| q8.^"text" q16 q4-|
+@end lilypond
+
+@seealso
+Installed Files:
+@file{ly/@/chord-repetition-init@/.ly}.
+
+
@node Simultaneous expressions
@unnumberedsubsubsec Simultaneous expressions
--- /dev/null
+\version "2.13.8"
+
+\header {
+ texidoc = "
+A repetition symbol can be used to repeat the previous chord
+and save typing. Only note events are copied.
+"
+}
+
+\relative c' {
+ <c e g>8\p( q) q4-| q8.\(^"text" q16 q4-|\)
+}
mus = \relative c' { c2 c c c c c c c }
\addQuote #"M" \mus
-q = \relative c' {
+quot = \relative c' {
d2 \quoteDuring #"M" { s1 } e2 \cueDuring #"M" #UP { s1 } f2
}
\score { <<
- \q
- \killCues \q
+ \quot
+ \killCues \quot
>> }
void kill_lexer ();
void set_lexer ();
+struct Chord_repetition
+{
+ Chord_repetition ()
+ {
+ last_chord_ = SCM_EOL;
+ repetition_function_ = SCM_EOL;
+ repetition_symbol_ = SCM_EOL;
+ }
+
+ SCM repetition_symbol_;
+ SCM repetition_function_;
+ SCM last_chord_;
+};
+
class Lily_lexer : public Includable_lexer
{
DECLARE_SMOBS (Lily_lexer);
SCM chordmodifier_tab_;
SCM pitchname_tab_stack_;
+ Chord_repetition chord_repetition_;
+
int error_level_;
Input last_input_;
yylval.scm = scm_cdr (handle);
return CHORD_MODIFIER;
}
+ if ((chord_repetition_.repetition_symbol_ != SCM_EOL)
+ && to_boolean (scm_equal_p (chord_repetition_.repetition_symbol_, sym)))
+ return CHORD_REPETITION;
}
yylval.scm = ly_string2scm (str);
error_level_ = 0;
is_main_input_ = false;
start_module_ = SCM_EOL;
+ chord_repetition_ = Chord_repetition ();
smobify_self ();
add_scope (ly_make_anonymous_module (false));
pitchname_tab_stack_ = src.pitchname_tab_stack_;
sources_ = src.sources_;
start_module_ = SCM_EOL;
+ chord_repetition_ = Chord_repetition ();
error_level_ = src.error_level_;
is_main_input_ = src.is_main_input_;
return SCM_UNSPECIFIED;
}
+LY_DEFINE (ly_parser_set_repetition_symbol, "ly:parser-set-repetition-symbol",
+ 2, 0, 0, (SCM parser, SCM sym),
+ "Replace the current repetition symbol in @var{parser}."
+ " @var{sym} is the new repetition symbol.")
+{
+ LY_ASSERT_SMOB (Lily_parser, parser, 1);
+ Lily_parser *p = unsmob_lily_parser (parser);
+
+ p->lexer_->chord_repetition_.repetition_symbol_ = sym;
+
+ return SCM_UNSPECIFIED;
+}
+
+LY_DEFINE (ly_parser_set_repetition_function, "ly:parser-set-repetition-function",
+ 2, 0, 0, (SCM parser, SCM fun),
+ "Replace the current repetition function in @var{parser}."
+ " @var{fun} is the new repetition function.")
+{
+ LY_ASSERT_SMOB (Lily_parser, parser, 1);
+ Lily_parser *p = unsmob_lily_parser (parser);
+
+ p->lexer_->chord_repetition_.repetition_function_ = fun;
+
+ return SCM_UNSPECIFIED;
+}
+
LY_DEFINE (ly_parser_output_name, "ly:parser-output-name",
1, 0, 0, (SCM parser),
"Return the base name of the output file.")
%token <scm> BOOK_IDENTIFIER
%token <scm> CHORDMODIFIER_PITCH
%token <scm> CHORD_MODIFIER
+%token <scm> CHORD_REPETITION
%token <scm> CONTEXT_DEF_IDENTIFIER
%token <scm> DRUM_PITCH
%token <scm> DURATION_IDENTIFIER
;
simple_music:
- event_chord
+ event_chord {
+ PARSER->lexer_->chord_repetition_.last_chord_ = $$;
+ }
| MUSIC_IDENTIFIER
| music_property_def
| context_change
i.set_location (@1, @2);
$$ = MAKE_SYNTAX ("event-chord", i, elts);
}
+ | CHORD_REPETITION optional_notemode_duration post_events {
+ Input i;
+ i.set_location (@1, @3);
+ $$ = MAKE_SYNTAX ("repetition-chord", i,
+ PARSER->lexer_->chord_repetition_.last_chord_,
+ PARSER->lexer_->chord_repetition_.repetition_function_,
+ $2, $3);
+ }
| MULTI_MEASURE_REST optional_notemode_duration post_events {
Input i;
i.set_location (@1, @3);
--- /dev/null
+\version "2.13.8"
+%{
+Two functions define the chord repetition behavior, and may
+be invoked by the user to customize it.
+
+ly:parser-set-repetition-symbol
+ set the chord repetition shortcut.
+ `q' is the default value set in this file.
+
+ly:parser-set-repetition-function
+ set the function that is invoked when a chord repetition symbol
+ is encountered by the parser: a three argument function
+ (previous-chord, duration, list of articulations) which is supposed
+ to return a new chord.
+ `default-repeat-chord' is the default function set in this file.
+%}
+
+#(define-public (default-repeat-chord previous-chord duration articulations)
+ "Copy the previous chord, filter out events which are not notes, set the
+chord duration, add articulations."
+ (let ((new-chord (ly:music-deep-copy previous-chord)))
+ (set! (ly:music-property new-chord 'elements)
+ (append! articulations
+ (filter (lambda (event)
+ (eqv? (ly:music-property event 'name) 'NoteEvent))
+ (ly:music-property new-chord 'elements))))
+ (for-each (lambda (event)
+ (if (ly:duration? (ly:music-property event 'duration))
+ (set! (ly:music-property event 'duration) duration)))
+ (ly:music-property new-chord 'elements))
+ new-chord))
+
+#(ly:parser-set-repetition-symbol parser 'q)
+#(ly:parser-set-repetition-function parser default-repeat-chord)
\include "chord-modifiers-init.ly"
\include "script-init.ly"
+\include "chord-repetition-init.ly"
+
% declarations for standard directions
left = #-1
right = #1
'duration duration
'origin location))
+(define-ly-syntax (repetition-chord parser location previous-chord repetition-function duration articulations)
+ (let ((new-chord (repetition-function previous-chord duration articulations)))
+ (set! (ly:music-property new-chord 'origin) location)
+ new-chord))
+
(define-ly-syntax-simple (context-specification type id mus ops create-new)
(let* ((type-sym (if (symbol? type) type (string->symbol type)))
(csm (context-spec-music mus type-sym id)))