% parsing line by line #(define-markup-command (wrap-newline layout props text) (string?) "Text Zeile für Zeile parsen" (interpret-markup layout props #{ \markup { \column { $(let ((verse-markup-string ( string-append "\\line { " (ly:regex-replace (ly:make-regex "\r?\n") text " } \\line { ") " \\size-box-to-box ##f ##t \"\" \"Agj\" }" ))) (ly:parser-include-string verse-markup-string)) }}#} ) ) #(define-markup-command (size-box-to-box layout props use-x use-y abox bbox) (boolean? boolean? markup? markup?) (let* ((ma (interpret-markup layout props abox)) (mb (interpret-markup layout props bbox)) (ax (ly:stencil-extent ma X)) (ay (ly:stencil-extent ma Y)) (bx (ly:stencil-extent mb X)) (by (ly:stencil-extent mb Y)) (halfdiffabx (* (- (interval-length bx) (interval-length ax)) 0.5))) (ly:stencil-translate (ly:make-stencil (ly:stencil-expr ma) (if use-x (if (< halfdiffabx 0) (cons (- (interval-bound ax DOWN) halfdiffabx) (+ (interval-bound ax UP) halfdiffabx)) bx) ax) (if use-y by ay)) (cons (if (and use-x (< halfdiffabx 0)) halfdiffabx 0) 0) ))) #(define-markup-command (size-box-to-box-left-aligned layout props use-x use-y abox bbox) (boolean? boolean? markup? markup?) (let* ((ma (interpret-markup layout props abox)) (mb (interpret-markup layout props bbox)) (ax (ly:stencil-extent ma X)) (ay (ly:stencil-extent ma Y)) (bx (ly:stencil-extent mb X)) (by (ly:stencil-extent mb Y))) (ly:make-stencil (ly:stencil-expr ma) (if use-x bx ax) (if use-y by ay)) )) #(define-markup-command (size-box-to-box-style-dependent layout props use-x use-y abox bbox) (boolean? boolean? markup? markup?) (interpret-markup layout props (case songTextChordAlignment ((center) (make-size-box-to-box-markup use-x use-y abox bbox)) ((left) (make-size-box-to-box-left-aligned-markup use-x use-y abox bbox))))) #(define-markup-command (chord-alignment-style-dependent layout props chord-with-text) (markup?) (interpret-markup layout props (case songTextChordAlignment ((center) (make-center-align-markup chord-with-text)) ((left) (make-left-align-markup chord-with-text))))) % Text über Text mittig darstellen #(define-markup-command (textup layout props text uptext) (markup? markup?) "Markup über Text mittig darstellen." (let ((verselayout (chain-assoc-get 'verselayout props generalLayout))) (interpret-markup layout props #{\markup { \size-box-to-box-style-dependent ##t ##f \general-align #X #LEFT \override #`(direction . ,UP) \override #'(baseline-skip . 1.0) \dir-column \chord-alignment-style-dependent { \pad-to-box #'(0 . 0) #'(0 . 2.0) { #text } \size-box-to-box ##f ##t #uptext \score { \chords { g4:m a } \layout { \verselayout } } } #text } #} ))) #(define-markup-command (anchor-x-between layout props arga argb) (markup? markup?) (let* ((la (interval-length (ly:stencil-extent (interpret-markup layout props arga) X))) (m (interpret-markup layout props (markup #:general-align Y DOWN arga argb (make-size-box-to-box-markup #t #t (markup #:null) arga)))) (l (interval-length (ly:stencil-extent m X)))) (ly:stencil-aligned-to m X (- (/ (* la 2) l) 1)) )) #(define-markup-command (stanza-raw layout props arg) (string-or-music?) (let ((verselayout (chain-assoc-get 'verselayout props generalLayout))) (interpret-markup layout props (if (and (string? arg) (string-null? arg)) " " #{\markup \score { \new Lyrics { \lyricmode { #(if (ly:music? arg) arg #{ \set stanza = #arg #}) "" } } \layout { \verselayout } } #} )))) #(define-markup-command (stanza layout props arg) (string-or-music?) (interpret-markup layout props (make-size-box-to-box-markup #f #t (make-stanza-raw-markup arg) (make-stanza-raw-markup "x")))) #(define (handle-custom-newlines custom-verse-breaks text) (if (null? custom-verse-breaks) text (let make-custom-linebreaks ((break-words custom-verse-breaks) (newtext (ly:regex-replace (ly:make-regex "\r?\n") text " "))) (if (null? break-words) newtext (make-custom-linebreaks (cdr break-words) (ly:regex-replace (ly:make-regex (string-append "(" (string-concatenate (map (lambda (character) (let ((escaped_char (ly:regex-quote (string character)))) (string-append "(?: *,[^,)]+\\)" escaped_char "|\\(?" escaped_char ")"))) (string->list (car break-words)))) "(?: *,[^,)]+\\))?)(.*)$")) newtext 1 "\n" 2)))))) #(use-modules (lily display-lily)) % Kompletten Vers mit Akkorden #(define-markup-command (chordverse layout props stanza verse) (string-or-music? string?) #:properties ( (intraverse-vspace 0) (custom-verse-breaks '()) (transposition (cons #f #f)) (verselayout generalLayout) ) "Vers mit Akkorden" (let ((transp (if (car transposition) (string-append "\\transpose " (symbol->string (note-name->lily-string (car transposition))) " " (symbol->string (note-name->lily-string (cdr transposition)))) ""))) (interpret-markup layout props (markup #:override `(baseline-skip . ,(+ intraverse-vspace songTextLineHeigth)) #:anchor-x-between #:stanza stanza (make-wrap-newline-markup (ly:regex-replace (ly:make-regex "\\(( *)([^,()]*)( *),([^)]*)\\)") (ly:regex-replace (ly:make-regex "(([^ \n]*\\([^()]*,[^()]+\\)[^ \n(]*)+)") (handle-custom-newlines custom-verse-breaks verse) " \\concat { " 1 " } ") "\\textup \\line { \"" 1 "\" " 2 " \"" 3 "\" } \\score { " transp " \\chords { s4 " 4 " } \\layout { \\verselayout } }") ) )))) % Kompletter Vers aus dem Akkorde entfernt werden #(define-markup-command (nochordverse layout props stanza verse) (string-or-music? string?) #:properties ((intraverse-vspace 0)(custom-verse-breaks '())) "Vers ohne Akkorde" (interpret-markup layout props (markup #:override `(baseline-skip . ,(+ intraverse-vspace 3.0)) #:anchor-x-between #:stanza stanza #:wrap-newline (ly:regex-replace (ly:make-regex "\\(([^,]*),([^)]*)\\)") (handle-custom-newlines custom-verse-breaks verse) 1) ) ) ) #(define-markup-command (verseformat layout props verse) (markup?) #:properties ((verselayout generalLayout)) "Textformatierung für Strophen" (interpret-markup layout props (let* ( (layout-scale (ly:output-def-lookup layout 'output-scale 1.0)) (verselayout-scale (ly:output-def-lookup verselayout 'output-scale layout-scale)) (mag-scale (/ verselayout-scale layout-scale)) (lyric-context-props (ly:context-def-lookup (ly:assoc-get 'Lyrics (ly:output-find-context-def verselayout 'Lyrics)) 'property-ops)) (lyric-size (caddr (find (lambda (prop) (and (equal? 'push (car prop)) (equal? 'LyricText (cadr prop)) (equal? 'font-size (cadddr prop)))) lyric-context-props))) ) (make-magnify-markup mag-scale (make-sans-markup (make-fontsize-markup lyric-size verse))) ) ) ) #(define-markup-command (group-verses layout props versegroup) (markup-list?) #:properties ((verse-cols 1) (verse-vspace 1) (verse-hspace 1) (verse-ordering-horizontal #f)) "Gruppiere Strophen in einem Markup auf Wunsch spaltenweise" (define (add-markup-between-elements reverses markup-between elements) ((if reverses fold fold-right) (lambda (element filled-list) (cons element (if (null? filled-list) '() (cons markup-between filled-list)))) '() elements)) (let* ((column-item-count (ceiling (/ (length versegroup) verse-cols))) (column-data (make-list verse-cols))) (let columnize-list ((index 0) (items versegroup)) (if (not (null? items)) (let* ((column-index (if verse-ordering-horizontal (modulo index verse-cols) (floor (/ index column-item-count)))) (column-markups (list-ref column-data column-index))) (list-set! column-data column-index (cons (car items) column-markups)) (columnize-list (+ index 1) (cdr items))))) (interpret-markup layout props (make-fill-line-markup (list (make-verseformat-markup (make-line-markup (add-markup-between-elements #f (make-hspace-markup verse-hspace) (map (lambda (column-markups) (make-column-markup (add-markup-between-elements #t (make-vspace-markup verse-vspace) column-markups))) column-data))))))))) #(define-markup-command (pad-left layout props amount arg) (number? markup?) (let* ((m (interpret-markup layout props arg)) (x (ly:stencil-extent m X)) (y (ly:stencil-extent m Y))) (ly:stencil-translate (ly:make-stencil (ly:stencil-expr m) (cons (- (car x) amount) (cdr x)) y) `(,amount . 0)))) #(define-markup-command (pad-right layout props amount arg) (number? markup?) (let* ((m (interpret-markup layout props arg)) (x (ly:stencil-extent m X)) (y (ly:stencil-extent m Y))) (ly:make-stencil (ly:stencil-expr m) (cons (car x) (+ (cdr x) amount)) y))) #(define-markup-command (score-equal-height layout props reference-height lines) (number? markup-list?) #:category music #:properties ((baseline-skip)) (stack-stencils Y DOWN baseline-skip (map (lambda (line) (ly:make-stencil (ly:stencil-expr line) (ly:stencil-extent line X) `(,(/ reference-height -2.0) . ,(/ reference-height 2.0)))) (interpret-markup-list layout props lines)))) #(define-public (custom-lyric-text::print grob) "Allow interpretation of tildes as lyric tieing marks." ;; See also similar code in Lyric_performer. (let ((text (ly:grob-property grob 'text))) (grob-interpret-markup grob (if (string? text) (make-pad-right-markup -0.1 (make-tied-lyric-markup text)) text)))) #(define-markup-command (chordlyrics layout props lyrics) (ly:music?) #:properties ((verse-chords #{#}) (verse-reference-voice #{#}) (verse-break-voice #{#}) (verse-line-height songTextLineHeigth) (verse-text-chord-distance songTextChordDistance) (intraverse-vspace 0) (transposition (cons #f #f)) (verselayout generalLayout)) "Vers mit Akkorden" (interpret-markup layout props #{ \markup { \override #`(baseline-skip . ,intraverse-vspace) \score-equal-height #verse-line-height \score-lines { \transposable #transposition << \new Devnull { #verse-break-voice } \new NullVoice = "dummyvoice" { #verse-reference-voice } #(music-clone verse-chords) \new Lyrics \lyricsto "dummyvoice" { #lyrics } >> \layout { \verselayout ragged-right = ##t \context { \Lyrics \override VerticalAxisGroup.nonstaff-relatedstaff-spacing.basic-distance = #verse-text-chord-distance \override LyricText.parent-alignment-X = #LEFT \override LyricText.self-alignment-X = #LEFT \override LyricText.word-space = 0.8 \override LyricSpace.minimum-distance = 0.8 \override LyricText.stencil = #custom-lyric-text::print } \context { \ChordNames \override VerticalAxisGroup.staff-affinity = ##f \override ChordName.extra-spacing-width = #'(-0.1 . 0.1) \consists \Ensure_first_chord_after_line_break_printed_engraver } \context { \Score \override PaperColumn.keep-inside-line = ##f % \override SpacingSpanner.strict-note-spacing = ##t \override SpacingSpanner.uniform-stretching = ##t \override SpacingSpanner.spacing-increment = 0 \remove Bar_number_engraver \remove Mark_engraver \remove Volta_engraver \remove Parenthesis_engraver } \context { \Staff \remove Staff_symbol_engraver \remove Clef_engraver \remove Time_signature_engraver \remove Bar_engraver \remove Separating_line_group_engraver \omit KeySignature \omit KeyCancellation } \context { \Voice \remove Stem_engraver \remove Rest_engraver \remove Multi_measure_rest_engraver \remove Phrasing_slur_engraver \remove Slur_engraver \remove Tie_engraver \remove Dynamic_engraver \remove Note_heads_engraver } \context { \NullVoice \consists Rest_engraver \omit Rest % \undo \omit NoteHead % \hide NoteHead } } } } #} ) ) #(define-markup-command (nochordlyrics layout props lyrics) (ly:music?) "Vers ohne Akkorde" (interpret-markup layout props (markup #:override `(verse-chords . ,#{#}) #:override `(verse-line-height . ,(- songTextLineHeigth 2)) #:chordlyrics lyrics)) )