19 Commits

Author SHA1 Message Date
db57e6d5c4 Variable eingefügt 2023-09-16 22:50:44 +02:00
tux
55db0e0e31 Liederbuchvorlage wieder lauffähig gemacht 2023-09-16 18:38:53 +02:00
tux
7a0dd88067 add json parser for structured data like AUTHOR_DATA and SONG_DATA 2023-08-20 12:14:30 +02:00
tux
c20d0327e7 einheitliche Funktionalität zur Autorenanzeige #3 2023-08-11 16:25:06 +02:00
05ea776add Größerer intraverse space für Büdel-style 2023-08-10 15:18:12 +02:00
tux
7ddd597bed PDF Bookmarks gefixt 2023-08-10 13:20:16 +02:00
5c6fde06cc verbesserte Spaltenumbruchmethode #2 2023-08-10 10:14:01 +02:00
973d72301c shiftChord für manuelle Feinjustierung eingeführt #1 2023-08-10 09:39:07 +02:00
tux
fbf273dae9 smarter breaks in toc columns closes #2 2023-08-09 16:39:17 +02:00
tux
e2dc938c02 intraverse-vspace eingebaut, um Zeilenabstand zu beeinflussen 2023-08-09 13:36:46 +02:00
tux
301681fffb use new lilypond 2.25 regexes and font definitions 2023-08-09 11:17:58 +02:00
tux
d900a95d79 add inline score music to midi output 2023-08-07 19:11:29 +02:00
tux
19b5fe2d94 transposeGlobal kann ganzen Song transponieren 2023-08-07 16:24:43 +02:00
tux
8e6eff1cad better override system 2023-07-24 08:39:38 +02:00
5a2ead5510 global Size anpassen 2023-07-23 13:30:17 +02:00
tux
ed81b5c903 make columns configurable 2023-07-23 12:18:14 +02:00
7e7d6820fb Büdel-Layout: Title in bold 2023-07-23 10:49:39 +02:00
2f0a5b4c18 Swing-Style 2023-07-23 10:49:25 +02:00
108b97b6f1 Swing style 2023-07-23 10:49:12 +02:00
20 changed files with 735 additions and 109 deletions

View File

@ -1,20 +1,17 @@
\language "deutsch" \language "deutsch"
\include "default_author_style.ly"
\include "styles.ly" \include "styles.ly"
\include #(ly:format "styles/~a.ly" songStyle) \include #(ly:format "styles/~a.ly" songStyle)
\include #(if (defined? 'customStyleOverridesFile) customStyleOverridesFile "void.ly")
#(set-default-paper-size songFormatAndSize) #(set-default-paper-size songFormatAndSize)
#(set-global-staff-size globalSize) #(set-global-staff-size globalSize)
#(define (default-pango size)
(make-pango-font-tree
songChordFont
songLyricFont
"Luxi Mono"
(/ size 20)))
\paper { \paper {
#(define fonts (default-pango globalSize)) property-defaults.fonts.serif = \songChordFont
property-defaults.fonts.sans = \songLyricFont
%annotate-spacing = ##t %annotate-spacing = ##t
% spacing stuff % spacing stuff
lyric-size = #lyricSize lyric-size = #lyricSize

View File

@ -121,7 +121,7 @@ includeSong =
\bookOutputName #filename \bookOutputName #filename
#} #}
(ly:parser-parse-string (if (< (list-ref (ly:version) 1) 19) (ly:parser-clone parser) (ly:parser-clone)) (ly:parser-parse-string (if (< (list-ref (ly:version) 1) 19) (ly:parser-clone parser) (ly:parser-clone))
(ly:format "\\include \"../../~a/~a/~a.ly\"" songPath filename filename)) (ly:format "\\include \"~a/~a/~a.ly\"" songPath filename filename))
(let ((label (gensym "index"))) (let ((label (gensym "index")))
(set! additional-page-switch-label-list (set! additional-page-switch-label-list
(acons label additional-page-numbers additional-page-switch-label-list)) (acons label additional-page-numbers additional-page-switch-label-list))
@ -209,7 +209,7 @@ songs =
;(string-join songs "\n") ;(string-join songs "\n")
"Nicht inkludiert:" "Nicht inkludiert:"
opticalline opticalline
(string-join (sort-list (lset-difference string=? (files-in-directory (ly:format "../../~a" songPath)) songs) string<?) "\n") (string-join (sort-list (lset-difference string=? (files-in-directory songPath) songs) string<?) "\n")
opticalline opticalline
) "\n" ) ) "\n" )
))) )))
@ -217,16 +217,16 @@ songs =
%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Include Images once and reference them: %% Include Images once and reference them:
#(define bbox-regexp #(define bbox-regexp
(make-regexp "%%BoundingBox:[ \t]+([0-9-]+)[ \t]+([0-9-]+)[ \t]+([0-9-]+)[ \t]+([0-9-]+)")) (ly:make-regex "%%BoundingBox:[ \t]+([0-9-]+)[ \t]+([0-9-]+)[ \t]+([0-9-]+)[ \t]+([0-9-]+)"))
#(define (get-postscript-bbox string) #(define (get-postscript-bbox string)
"Extract the bbox from STRING, or return #f if not present." "Extract the bbox from STRING, or return #f if not present."
(let* (let*
((match (regexp-exec bbox-regexp string))) ((match (ly:regex-exec bbox-regexp string)))
(if match (if match
(map (lambda (x) (map (lambda (x)
(string->number (match:substring match x))) (string->number (ly:regex-match-substring match x)))
(cdr (iota 5))) (cdr (iota 5)))
#f))) #f)))

View File

@ -16,6 +16,12 @@ bchord =
\revert ChordName.font-series \revert ChordName.font-series
#}) #})
shiftChord = #(define-music-function (parser location xshift chord) (number? ly:music?)
#{
\once \override ChordName.extra-offset = #`(,xshift . 0)
$chord
#})
% kleine Mollakkorde und Alteration ausgeschrieben % kleine Mollakkorde und Alteration ausgeschrieben
#(define (note-name->german-markup-nosym pitch lowercase?) #(define (note-name->german-markup-nosym pitch lowercase?)
(define (pitch-alteration-semitones pitch) (inexact->exact (round (* (ly:pitch-alteration pitch) 2)))) (define (pitch-alteration-semitones pitch) (inexact->exact (round (* (ly:pitch-alteration pitch) 2))))
@ -52,6 +58,12 @@ bchord =
% additional bass notes should get uppercased % additional bass notes should get uppercased
#(define (bassnote-name->german-markup-nosym pitch lowercase?)(note-name->german-markup-nosym pitch #f)) #(define (bassnote-name->german-markup-nosym pitch lowercase?)(note-name->german-markup-nosym pitch #f))
#(define chordNameExceptions
(if (defined? 'customChordPrintings)
(sequential-music-to-chord-exceptions customChordPrintings #t)
'()))
generalLayout = \layout { generalLayout = \layout {
\generalLayout \generalLayout
\context { \context {
@ -59,13 +71,14 @@ generalLayout = \layout {
\semiGermanChords \semiGermanChords
\override ChordName.font-size = \songScoreChordFontSize \override ChordName.font-size = \songScoreChordFontSize
\override ChordName.font-series = \songChordFontSeries \override ChordName.font-series = \songChordFontSeries
\override ChordName.font-family = #'roman \override ChordName.font-family = #'sans
chordNameLowercaseMinor = ##t chordNameLowercaseMinor = ##t
chordChanges = ##t chordChanges = ##t
% eigenen chordRootNamer damit F# = Fis und Gb = Ges (also alteration ausgeschrieben) % eigenen chordRootNamer damit F# = Fis und Gb = Ges (also alteration ausgeschrieben)
chordRootNamer = #note-name->german-markup-nosym chordRootNamer = #note-name->german-markup-nosym
chordNoteNamer = #bassnote-name->german-markup-nosym chordNoteNamer = #bassnote-name->german-markup-nosym
majorSevenSymbol = "maj7" majorSevenSymbol = "maj7"
chordNameExceptions = \chordNameExceptions
% der baseline-skip der Akkorde beeinflusst, wie hoch die Hochstellung ist % der baseline-skip der Akkorde beeinflusst, wie hoch die Hochstellung ist
\override ChordName.baseline-skip = #1.0 \override ChordName.baseline-skip = #1.0
} }

26
default_author_style.ly Normal file
View File

@ -0,0 +1,26 @@
\paper {
authorMarkup =
#(make-on-the-fly-markup
(lambda (layout props m)
(let ((name (chain-assoc-get 'author:name props #f))
(trail_name (chain-assoc-get 'author:trail_name props #f))
(birth_year (chain-assoc-get 'author:birth_year props #f))
(death_year (chain-assoc-get 'author:death_year props #f))
(organization (chain-assoc-get 'author:organization props #f)))
(interpret-markup layout props
(string-append
name
(if trail_name (ly:format " (~a)" trail_name) "")
(if (and birth_year death_year)
(ly:format ", (~a~a)" birth_year death_year)
(if birth_year
(ly:format ", (*~a)" birth_year)
(if death_year (ly:format ", (†~a)" death_year) "")))
(if organization (ly:format ", ~a" organization) "")
))))
(make-null-markup)
)
poetMarkup = \markup { "Worte:" \fromproperty #'author }
composerMarkup = \markup { "Weise:" \fromproperty #'author }
poetAndComposerEqualMarkup = \markup { "Worte und Weise:" \fromproperty #'author }
}

View File

@ -1,15 +0,0 @@
generalLayout = \layout {
\generalLayout
\context {
\ChordNames
chordNameExceptions = #(sequential-music-to-chord-exceptions customChordPrintings #t)
}
}
verseChordLayout = \layout {
\verseChordLayout
\context {
\ChordNames
chordNameExceptions = #(sequential-music-to-chord-exceptions customChordPrintings #t)
}
}

View File

@ -9,7 +9,7 @@
(interpret-markup layout props (interpret-markup layout props
(let ((filepath (if (string-null? songfilename) (let ((filepath (if (string-null? songfilename)
filename filename
(ly:format "../../~a/~a/~a" songPath songfilename filename)))) (ly:format "~a/~a/~a" songPath songfilename filename))))
(if (file-exists? filepath) (if (file-exists? filepath)
(make-epsfile-markup Y ysize filepath) (make-epsfile-markup Y ysize filepath)
(if defaultmarkup (if defaultmarkup

View File

@ -1,33 +1,65 @@
#(define-markup-command (print-songinfo layout props) () #(define-markup-command (print-songinfo layout props) ()
(interpret-markup layout props (define (songinfo-from songId key)
(let ( (let ((song (if (defined? 'SONG_DATA) (assoc-ref SONG_DATA songId) #f)))
(blockwidth (* (chain-assoc-get 'header:songinfo-size-factor props 0.9) (ly:output-def-lookup layout 'line-width))) (if song
(infotext (chain-assoc-get 'header:songinfo props #f)) (assoc-ref song key)
(poet (chain-assoc-get 'header:poet props #f)) (ly:warning (ly:format "song with id ~a not found" songId)))))
(composer (chain-assoc-get 'header:composer props #f))
(poet-and-composer-stacked (chain-assoc-get 'header:poet-and-composer-stacked props songInfoPoetAndComposerStacked)) (define (format-author authorId)
(between-poet-and-composer-markup (chain-assoc-get 'header:between-poet-and-composer-markup props (make-hspace-markup 3))) (let ((author (if (defined? 'AUTHOR_DATA) (assoc-ref AUTHOR_DATA authorId) #f)))
(copyright (chain-assoc-get 'header:copyright props #f))) (if author
(if (chain-assoc-get 'page:is-bookpart-last-page props #f) (markup
(markup #:override '(baseline-skip . 3.0) ( #:override (cons 'author:name (assoc-ref author "name"))
make-fontsize-markup songInfoFontSize #:override (cons 'author:trail_name (assoc-ref author "trail_name"))
(make-sans-markup #:override (cons 'author:birth_year (assoc-ref author "birth_year"))
;%\override #'(line-width . 92) \wordwrap-field #symbol #:override (cons 'author:death_year (assoc-ref author "death_year"))
(make-column-markup (list #:override (cons 'author:organization (assoc-ref author "organization"))
(make-line-markup (ly:output-def-lookup layout 'authorMarkup))
(list (ly:warning (ly:format "author with id ~a not found" authorId)))))
(if (and poet (not (and (string? poet) (string-null? poet)))) (markup poet between-poet-and-composer-markup) "")
(if (and composer (not poet-and-composer-stacked)) composer "")) (define (format-poet poetId)
) (markup #:override (cons 'author (format-author poetId)) (ly:output-def-lookup layout 'poetMarkup)))
(if (and composer poet-and-composer-stacked) (make-line-markup (list composer)) "")
(make-override-markup `(line-width . ,blockwidth) (make-justify-string-markup (string-append (define (format-composer composerId)
(if (and copyright (not (and (string? copyright) (string-null? copyright)))) (ly:format "© ~a\n\n" copyright) "") (markup #:override (cons 'author (format-author composerId)) (ly:output-def-lookup layout 'composerMarkup)))
(if infotext infotext "")
))) (define (format-poet-and-composer authorId)
))) (markup #:override (cons 'author (format-author authorId)) (ly:output-def-lookup layout 'poetAndComposerEqualMarkup)))
)
) (interpret-markup layout props
(make-null-markup)))) (if (chain-assoc-get 'page:is-bookpart-last-page props #f)
(let* ((songId (chain-assoc-get 'header:songId props #f))
(poetId (chain-assoc-get 'header:poetId props (if songId (songinfo-from songId "poet") #f)))
(composerId (chain-assoc-get 'header:composerId props (if songId (songinfo-from songId "composer") #f)))
(poet-and-composer-same (equal? poetId composerId)))
(let (
(blockwidth (* (chain-assoc-get 'header:songinfo-size-factor props 0.9) (ly:output-def-lookup layout 'line-width)))
(infotext (chain-assoc-get 'header:songinfo props #f))
(poet (chain-assoc-get 'header:poet props (if poetId (if poet-and-composer-same (format-poet-and-composer poetId) (format-poet poetId)) #f)))
(composer (chain-assoc-get 'header:composer props (if (and composerId (not poet-and-composer-same)) (format-composer composerId) #f)))
(poet-and-composer-stacked (chain-assoc-get 'header:poet-and-composer-stacked props songInfoPoetAndComposerStacked))
(between-poet-and-composer-markup (chain-assoc-get 'header:between-poet-and-composer-markup props (make-hspace-markup 3)))
(copyright (chain-assoc-get 'header:copyright props #f)))
(markup #:override '(baseline-skip . 3.0) (
make-fontsize-markup songInfoFontSize
(make-sans-markup
;%\override #'(line-width . 92) \wordwrap-field #symbol
(make-column-markup (list
(make-line-markup
(list
(if (and poet (not (and (string? poet) (string-null? poet)))) (markup poet between-poet-and-composer-markup) "")
(if (and composer (not poet-and-composer-stacked)) composer ""))
)
(if (and composer poet-and-composer-stacked) (make-line-markup (list composer)) "")
(make-override-markup `(line-width . ,blockwidth) (make-justify-string-markup (string-append
(if (and copyright (not (and (string? copyright) (string-null? copyright)))) (ly:format "© ~a\n\n" copyright) "")
(if infotext infotext "")
)))
)))
)
)
))
(make-null-markup)))
) )
#(define-markup-command (print-pagenumber layout props)() #(define-markup-command (print-pagenumber layout props)()

View File

@ -6,14 +6,20 @@
#(define noStandaloneOutput (if (defined? 'noStandaloneOutput) noStandaloneOutput #f)) #(define noStandaloneOutput (if (defined? 'noStandaloneOutput) noStandaloneOutput #f))
#(if (defined? 'LAYOUT) #f (load "json_parser.scm"))
#(use-modules (json parser))
\include "basic_format_and_style_settings.ly" \include "basic_format_and_style_settings.ly"
\include #(if (< (list-ref (ly:version) 1) 25) "legacy-lilypond-compatibility-pre-2.25.ly" "void.ly")
\include "eps_file_from_song_dir.ly" \include "eps_file_from_song_dir.ly"
\include "title_with_category_images.ly" \include "title_with_category_images.ly"
\include "footer_with_songinfo.ly" \include "footer_with_songinfo.ly"
\include "auto_rest_merging.ly" \include "auto_rest_merging.ly"
\include "chord_settings.ly" \include "chord_settings.ly"
\include "transposition.ly"
\include "verses_with_chords.ly" \include "verses_with_chords.ly"
\include "arrows_in_scores.ly" \include "arrows_in_scores.ly"
\include "swing_style.ly"
\include "inline_score.ly"
% reset important variables % reset important variables
LAYOUT = \layout { \generalLayout } LAYOUT = \layout { \generalLayout }

8
inline_score.ly Normal file
View File

@ -0,0 +1,8 @@
INLINESCOREMUSIC = {}
inline-score =
#(define-music-function (music) (ly:music?)
(set! INLINESCOREMUSIC #{ \INLINESCOREMUSIC #music #})
#{
\transposable #music
#})

482
json_parser.scm Normal file
View File

@ -0,0 +1,482 @@
;;; (json parser) --- Guile JSON implementation.
;; Copyright (C) 2013-2020 Aleix Conchillo Flaque <aconchillo@gmail.com>
;;
;; This file is part of guile-json.
;;
;; guile-json is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation; either version 3 of the License, or
;; (at your option) any later version.
;;
;; guile-json is distributed in the hope that it will be useful, but
;; WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
;; General Public License for more details.
;;
;; You should have received a copy of the GNU General Public License
;; along with guile-json. If not, see https://www.gnu.org/licenses/.
;;; Commentary:
;; JSON module for Guile
;;; Code:
(define-module (json parser)
#:use-module (ice-9 rdelim)
#:use-module (ice-9 streams)
#:use-module (rnrs io ports)
#:export (json->scm
json-string->scm
json-seq->scm
json-seq-string->scm))
;;
;; Miscellaneuos helpers
;;
(define (json-exception port)
(throw 'json-invalid port))
(define (digit? c)
(case c
((#\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9) #t)
(else #f)))
(define (whitespace? c)
(case c
((#\sp #\ht #\lf #\cr) #t)
(else #f)))
(define (control-char? ch)
(<= (char->integer ch) #x1F))
(define (skip-whitespaces port)
(let ((ch (peek-char port)))
(cond
((whitespace? ch)
(read-char port)
(skip-whitespaces port))
(else *unspecified*))))
(define (expect-string port expected return)
(let loop ((n 0))
(cond
;; All characters match.
((= n (string-length expected)) return)
;; Go to next characters.
((eqv? (read-char port) (string-ref expected n))
(loop (+ n 1)))
;; Anything else is an error.
(else (json-exception port)))))
(define (expect-delimiter port delimiter)
(let ((ch (read-char port)))
(cond
((not (eqv? ch delimiter)) (json-exception port))
;; Unexpected EOF.
((eof-object? ch) (json-exception port)))))
(define (skip-record-separators port)
(when (eqv? #\rs (peek-char port))
(read-char port)
(skip-record-separators port)))
;;
;; Number parsing helpers
;;
(define (expect-digit port)
(let ((ch (peek-char port)))
(cond
((not (digit? ch)) (json-exception port))
;; Unexpected EOF.
((eof-object? ch) (json-exception port)))))
;; Read + or -, and return 1 or -1 respectively. If something different is
;; found, return 1.
(define (read-sign port)
(let ((ch (peek-char port)))
(cond
((eqv? ch #\+)
(read-char port)
1)
((eqv? ch #\-)
(read-char port)
-1)
(else 1))))
(define (read-digit-value port)
(let ((ch (read-char port)))
(cond
((eqv? ch #\0) 0)
((eqv? ch #\1) 1)
((eqv? ch #\2) 2)
((eqv? ch #\3) 3)
((eqv? ch #\4) 4)
((eqv? ch #\5) 5)
((eqv? ch #\6) 6)
((eqv? ch #\7) 7)
((eqv? ch #\8) 8)
((eqv? ch #\9) 9)
(else (json-exception port)))))
;; Read digits [0..9].
(define (read-digits port)
(expect-digit port)
(let loop ((ch (peek-char port)) (number 0))
(cond
((digit? ch)
(let ((value (read-digit-value port)))
(loop (peek-char port) (+ (* number 10) value))))
(else number))))
(define (read-digits-fraction port)
(expect-digit port)
(let loop ((ch (peek-char port)) (number 0) (length 0))
(cond
((digit? ch)
(let ((value (read-digit-value port)))
(loop (peek-char port) (+ (* number 10) value) (+ length 1))))
(else
(/ number (expt 10 length))))))
(define (read-exponent port)
(let ((ch (peek-char port)))
(cond
((or (eqv? ch #\e) (eqv? ch #\E))
(read-char port)
(let ((sign (read-sign port))
(digits (read-digits port)))
(if (<= digits 1000) ;; Some maximum exponent.
(expt 10 (* sign digits))
(json-exception port))))
(else 1))))
(define (read-fraction port)
(let ((ch (peek-char port)))
(cond
((eqv? ch #\.)
(read-char port)
(read-digits-fraction port))
(else 0))))
(define (read-positive-number port)
(let* ((number
(let ((ch (peek-char port)))
(cond
;; Numbers that start with 0 must be a fraction.
((eqv? ch #\0)
(read-char port)
0)
;; Otherwise read more digits.
(else (read-digits port)))))
(fraction (read-fraction port))
(exponent (read-exponent port))
(result (* (+ number fraction) exponent)))
(if (and (zero? fraction) (>= exponent 1))
result
(exact->inexact result))))
(define (json-read-number port)
(let ((ch (peek-char port)))
(cond
;; Negative numbers.
((eqv? ch #\-)
(read-char port)
(expect-digit port)
(* -1 (read-positive-number port)))
;; Positive numbers.
((digit? ch)
(read-positive-number port))
;; Anything else is an error.
(else (json-exception port)))))
;;
;; Object parsing helpers
;;
(define (read-pair port null ordered)
;; Read key.
(let ((key (json-read-string port)))
(skip-whitespaces port)
(let ((ch (peek-char port)))
(cond
;; Skip colon and read value.
((eqv? ch #\:)
(read-char port)
(cons key (json-read port null ordered)))
;; Anything other than colon is an error.
(else (json-exception port))))))
(define (json-read-object port null ordered)
(expect-delimiter port #\{)
(let loop ((pairs '()) (added #t))
(skip-whitespaces port)
(let ((ch (peek-char port)))
(cond
;; End of object.
((eqv? ch #\})
(read-char port)
(cond
(added (if ordered (reverse! pairs) pairs))
(else (json-exception port))))
;; Read one pair and continue.
((eqv? ch #\")
(let ((pair (read-pair port null ordered)))
(loop (cons pair pairs) #t)))
;; Skip comma and read more pairs.
((eqv? ch #\,)
(read-char port)
(cond
(added (loop pairs #f))
(else (json-exception port))))
;; Invalid object.
(else (json-exception port))))))
;;
;; Array parsing helpers
;;
(define (json-read-array port null ordered)
(expect-delimiter port #\[)
(skip-whitespaces port)
(cond
;; Special case when array is empty.
((eqv? (peek-char port) #\])
(read-char port)
#())
(else
;; Read first element in array.
(let loop ((values (list (json-read port null ordered))))
(skip-whitespaces port)
(let ((ch (peek-char port)))
(cond
;; Unexpected EOF.
((eof-object? ch) (json-exception port))
;; Handle comma (if there's a comma there should be another element).
((eqv? ch #\,)
(read-char port)
(loop (cons (json-read port null ordered) values)))
;; End of array.
((eqv? ch #\])
(read-char port)
(list->vector (reverse! values)))
;; Anything else other than comma and end of array is wrong.
(else (json-exception port))))))))
;;
;; String parsing helpers
;;
(define (read-hex-digit->integer port)
(let ((ch (read-char port)))
(cond
((eqv? ch #\0) 0)
((eqv? ch #\1) 1)
((eqv? ch #\2) 2)
((eqv? ch #\3) 3)
((eqv? ch #\4) 4)
((eqv? ch #\5) 5)
((eqv? ch #\6) 6)
((eqv? ch #\7) 7)
((eqv? ch #\8) 8)
((eqv? ch #\9) 9)
((or (eqv? ch #\A) (eqv? ch #\a)) 10)
((or (eqv? ch #\B) (eqv? ch #\b)) 11)
((or (eqv? ch #\C) (eqv? ch #\c)) 12)
((or (eqv? ch #\D) (eqv? ch #\d)) 13)
((or (eqv? ch #\E) (eqv? ch #\e)) 14)
((or (eqv? ch #\F) (eqv? ch #\f)) 15)
(else (json-exception port)))))
(define (read-unicode-value port)
(+ (* 4096 (read-hex-digit->integer port))
(* 256 (read-hex-digit->integer port))
(* 16 (read-hex-digit->integer port))
(read-hex-digit->integer port)))
;; Unicode codepoint with surrogates is:
;; 10000 + (high - D800) + (low - DC00)
;; which is equivalent to:
;; (high << 10) + low - 35FDC00
;; see
;; https://github.com/aconchillo/guile-json/issues/58#issuecomment-662744070
(define (json-surrogate-pair->unicode high low)
(+ (* high #x400) low #x-35FDC00))
(define (read-unicode-char port)
(let ((codepoint (read-unicode-value port)))
(cond
;; Surrogate pairs. `codepoint` already contains the higher surrogate
;; (between D800 and DC00) . At this point we are expecting another
;; \uXXXX that holds the lower surrogate (between DC00 and DFFF).
((and (>= codepoint #xD800) (< codepoint #xDC00))
(expect-string port "\\u" #f)
(let ((low-surrogate (read-unicode-value port)))
(if (and (>= low-surrogate #xDC00) (< low-surrogate #xE000))
(integer->char (json-surrogate-pair->unicode codepoint low-surrogate))
(json-exception port))))
;; Reserved for surrogates (we just need to check starting from the low
;; surrogates).
((and (>= codepoint #xDC00) (< codepoint #xE000))
(json-exception port))
(else (integer->char codepoint)))))
(define (read-control-char port)
(let ((ch (read-char port)))
(cond
((eqv? ch #\") #\")
((eqv? ch #\\) #\\)
((eqv? ch #\/) #\/)
((eqv? ch #\b) #\bs)
((eqv? ch #\f) #\ff)
((eqv? ch #\n) #\lf)
((eqv? ch #\r) #\cr)
((eqv? ch #\t) #\ht)
((eqv? ch #\u) (read-unicode-char port))
(else (json-exception port)))))
(define (json-read-string port)
(expect-delimiter port #\")
(let loop ((chars '()) (ch (read-char port)))
(cond
;; Unexpected EOF.
((eof-object? ch) (json-exception port))
;; Unescaped control characters are not allowed.
((control-char? ch) (json-exception port))
;; End of string.
((eqv? ch #\") (reverse-list->string chars))
;; Escaped characters.
((eqv? ch #\\)
(loop (cons (read-control-char port) chars) (read-char port)))
;; All other characters.
(else
(loop (cons ch chars) (read-char port))))))
;;
;; Booleans and null parsing helpers
;;
(define (json-read-true port)
(expect-string port "true" #t))
(define (json-read-false port)
(expect-string port "false" #f))
(define (json-read-null port null)
(expect-string port "null" null))
;;
;; Main parser functions
;;
(define (json-read port null ordered)
(skip-whitespaces port)
(let ((ch (peek-char port)))
(cond
;; Unexpected EOF.
((eof-object? ch) (json-exception port))
;; Read JSON values.
((eqv? ch #\t) (json-read-true port))
((eqv? ch #\f) (json-read-false port))
((eqv? ch #\n) (json-read-null port null))
((eqv? ch #\{) (json-read-object port null ordered))
((eqv? ch #\[) (json-read-array port null ordered))
((eqv? ch #\") (json-read-string port))
;; Anything else should be a number.
(else (json-read-number port)))))
;;
;; Public procedures
;;
(define* (json->scm #:optional (port (current-input-port))
#:key (null 'null) (ordered #f) (concatenated #f))
"Parse a JSON document into native. Takes one optional argument,
@var{port}, which defaults to the current input port from where the JSON
document is read. It also takes a few of keyword arguments: @{null}: value for
JSON's null, it defaults to the 'null symbol, @{ordered} to indicate whether
JSON objects order should be preserved or not (the default) and @{concatenated}
which can be used to tell the parser that more JSON documents might come after a
properly parsed document."
(let loop ((value (json-read port null ordered)))
;; Skip any trailing whitespaces.
(skip-whitespaces port)
(cond
;; If we reach the end the parsing succeeded.
((eof-object? (peek-char port)) value)
;; If there's anything else other than the end, check if user wants to keep
;; parsing concatenated valid JSON documents, otherwise parser fails.
(else
(cond (concatenated value)
(else (json-exception port)))))))
(define* (json-string->scm str #:key (null 'null) (ordered #f))
"Parse a JSON document into native. Takes a string argument,
@var{str}, that contains the JSON document. It also takes a couple of keyword
argument: @{null}: value for JSON's null, it defaults to the 'null symbol and
@{ordered} to indicate whether JSON objects order should be preserved or
not (the default)."
(call-with-input-string str (lambda (p) (json->scm p #:null null #:ordered ordered))))
(define* (json-seq->scm #:optional (port (current-input-port))
#:key (null 'null) (ordered #f)
(handle-truncate 'skip) (truncated-object 'truncated))
"Lazy parse a JSON text sequence from the port @var{port}.
This procedure returns a stream of parsed documents. The optional argument
@var{port} defines the port to read from and defaults to the current input
port. It also takes a few keyword arguments: @{null}: value for JSON's null
(defaults to the 'null symbol), @{ordered} to indicate whether JSON objects
order should be preserved or not (the default), @{handle-truncate}: defines how
to handle data loss, @{truncated-object}: used to replace unparsable
objects. Allowed values for @{handle-truncate} argument are 'throw (throw an
exception), 'stop (stop parsing and end the stream), 'skip (default, skip
corrupted fragment and return the next entry), 'replace (skip corrupted fragment
and return @{truncated-object} instead)."
(letrec ((handle-truncation
(case handle-truncate
((throw) json-exception)
((stop) (const (eof-object)))
((skip)
(lambda (port)
(read-delimited "\x1e" port 'peek)
(read-entry port)))
((replace)
(lambda (port)
(read-delimited "\x1e" port 'peek)
truncated-object))))
(read-entry
(lambda (port)
(let ((ch (read-char port)))
(cond
((eof-object? ch) ch)
((not (eqv? ch #\rs))
(handle-truncation port))
(else
(skip-record-separators port)
(catch 'json-invalid
(lambda ()
(let ((next (json-read port null ordered)))
(if (eqv? #\lf (peek-char port))
(begin
(read-char port)
next)
(handle-truncation port))))
(lambda (_ port)
(handle-truncation port)))))))))
(port->stream port read-entry)))
(define* (json-seq-string->scm str #:key (null 'null) (ordered #f)
(handle-truncate 'skip) (truncated-object 'truncated))
"Lazy parse a JSON text sequence from the string @var{str}.
This procedure returns a stream of parsed documents and also takes the same
keyword arguments as @code{json-seq->scm}."
(call-with-input-string str
(lambda (p)
(json-seq->scm p #:null null #:ordered ordered
#:handle-truncate handle-truncate
#:truncated-object truncated-object))))
;;; (json parser) ends here

View File

@ -0,0 +1,22 @@
% guile regular expressions aktivieren:
#(use-modules (ice-9 regex))
#(define ly:make-regex make-regexp)
#(define ly:regex-exec regexp-exec)
#(define ly:regex-match-substring match:substring)
#(define (ly:regex-replace pattern text . replacements)
(apply regexp-substitute/global #f pattern text 'pre (append replacements (list 'post))))
% old font handling
#(define (default-pango size)
(make-pango-font-tree
songChordFont
songLyricFont
"Luxi Mono"
(/ size 20)))
\paper {
#(define fonts (default-pango globalSize))
}

View File

@ -1,6 +1,8 @@
% set the speed of the midi music % set the speed of the midi music
#(define midiQuarterNoteSpeed (if (defined? 'midiQuarterNoteSpeed) midiQuarterNoteSpeed 90)) #(define midiQuarterNoteSpeed (if (defined? 'midiQuarterNoteSpeed) midiQuarterNoteSpeed 90))
MUSIC = { \transposable \MUSIC }
% nur Output wenn noStandaloneOutput auf false steht % nur Output wenn noStandaloneOutput auf false steht
output = #(if (not noStandaloneOutput) output = #(if (not noStandaloneOutput)
#{ #{
@ -15,7 +17,7 @@ output = #(if (not noStandaloneOutput)
\TEXT \TEXT
\score { \score {
\unfoldRepeats \MUSIC \unfoldRepeats { \MUSIC \INLINESCOREMUSIC }
\midi { \midi {
\context { \context {
\Score \Score

View File

@ -10,5 +10,6 @@ songScoreChordFontSize = 3
songTextChordFontSize = 2 songTextChordFontSize = 2
songTextLineHeigth = 5.5 songTextLineHeigth = 5.5
songInfoPoetAndComposerStacked = ##f songInfoPoetAndComposerStacked = ##f
songTocColumns = 3
globalSize = 15 globalSize = 15
lyricSize = 1.6 lyricSize = 1.6

View File

@ -10,5 +10,6 @@ songScoreChordFontSize = 0
songTextChordFontSize = \songScoreChordFontSize songTextChordFontSize = \songScoreChordFontSize
songTextLineHeigth = 5 songTextLineHeigth = 5
songInfoPoetAndComposerStacked = ##f songInfoPoetAndComposerStacked = ##f
songTocColumns = 3
globalSize = 15 globalSize = 15
lyricSize = 1.6 lyricSize = 1.6

View File

@ -1,14 +1,15 @@
songFormatAndSize = "a5" songFormatAndSize = "a5"
songMargin = 5 songMargin = 5
songInfoFontSize = 0 songInfoFontSize = 0
songTitleFont = "Fontin" songTitleFont = "Fontin Bold"
songChordFont = "Fontin" songChordFont = "Fontin"
songLyricFont = "FontinSans" songLyricFont = "FontinSans"
songChordFontSeries = #'bold songChordFontSeries = #'bold
songTextChordAlignment = #'left songTextChordAlignment = #'left
songScoreChordFontSize = 2 songScoreChordFontSize = 2
songTextChordFontSize = 2 songTextChordFontSize = 2
songTextLineHeigth = 5 songTextLineHeigth = 5.3
songInfoPoetAndComposerStacked = ##t songInfoPoetAndComposerStacked = ##t
globalSize = 15 songTocColumns = 2
globalSize = 14
lyricSize = 1.6 lyricSize = 1.6

48
swing_style.ly Normal file
View File

@ -0,0 +1,48 @@
swing = \mark \markup {
\line \general-align #Y #DOWN {
\score {
\new Staff \with {
fontSize = #-2
\override StaffSymbol.line-count = #0
% \override VerticalAxisGroup.Y-extent = #'(0 . 0)
}
\relative {
\stemUp
\override Score.SpacingSpanner.common-shortest-duration = #(ly:make-moment 3 16)
\override Beam.positions = #'(2 . 2)
h'8[ h8]
}
\layout {
ragged-right= ##t
indent = 0
\context {
\Staff \remove "Clef_engraver"
\remove "Time_signature_engraver"
}
}
}
" ="
\score {
\new Staff \with {
fontSize = #-2
\override StaffSymbol.line-count = #0
% \override VerticalAxisGroup.Y-extent = #'(0 . 0)
}
\relative {
\stemUp
\override Score.SpacingSpanner.common-shortest-duration = #(ly:make-moment 3 16)
\override Stem.length = #4.5
\tuplet 3/2 { h'4 h8 }
}
\layout {
ragged-right= ##t
indent = 0
\context {
\Staff
\remove "Clef_engraver"
\remove "Time_signature_engraver"
}
}
}
}
}

View File

@ -44,14 +44,7 @@
(ly:make-stencil (ly:make-stencil
(list 'embedded-ps (list 'embedded-ps
(ly:format (ly:format
"[/Action /GoTo /View [/Fit] /Title <~a> /OUT pdfmark" "[/Action /GoTo /View [/Fit] /Title (~a) /OUT pdfmark" (pdf-encode title)))
(fold
(lambda (ch hexout)
(string-append hexout
(format #f "~2,'0x" (char->integer ch))))
""
(string->list
(pdf-encode title)))))
empty-interval empty-interval empty-interval empty-interval
;'(0 . 0) '(0 . 0) ;'(0 . 0) '(0 . 0)
)) ))

View File

@ -1,3 +1,5 @@
\include "../lilypond-custom-includes/toc_config.ly"
% embed all category images in postscript once % embed all category images in postscript once
#(define-markup-list-command (embed-category-images layout props)() #(define-markup-list-command (embed-category-images layout props)()
(map (lambda (category) (map (lambda (category)
@ -19,13 +21,20 @@
(map (lambda (foo) (map (lambda (foo)
(make-general-align-markup Y UP (make-override-markup '(baseline-skip . 1) (make-column-markup (make-general-align-markup Y UP (make-override-markup '(baseline-skip . 1) (make-column-markup
(let add-to-col ((lines restlines) (height-left height)) (let add-to-col ((lines restlines) (height-left height))
(let* ((finished (null? lines)) (set! restlines lines)
(linestencil (if (not finished) (interpret-markup layout (cons (list (cons 'line-width line-width) (cons 'baseline-skip 1)) props) (markup #:center-align (car lines))))) (if (null? lines)
(calc-height (- height-left (if finished 0 (interval-length (ly:stencil-extent linestencil Y)))))) '()
(set! restlines lines) (let* ((line-to-stencil (lambda (line) (interpret-markup layout (cons (list (cons 'line-width line-width) (cons 'baseline-skip 1)) props) (markup line))))
(if (or (< calc-height 0) (null? lines)) (stencil-height (lambda (stencil) (interval-length (ly:stencil-extent stencil Y))))
(list) (linestencil (line-to-stencil (car lines)))
(cons (markup #:stencil linestencil) (add-to-col (cdr lines) calc-height))))))))) (current-line-height (stencil-height linestencil))
(new-height-left (- height-left current-line-height))
(next-line-height (if (null? (cdr lines)) current-line-height (stencil-height (line-to-stencil (cadr lines)))))
(no-space-for-next-line (and (< next-line-height current-line-height) (< new-height-left next-line-height)))
)
(if (or (< new-height-left 0) no-space-for-next-line)
'()
(cons (markup #:stencil linestencil) (add-to-col (cdr lines) new-height-left))))))))))
(make-list cols)))) (make-list cols))))
(if (null? restlines) (if (null? restlines)
(list) (list)
@ -164,17 +173,7 @@
(cdr revlist))))))))) (cdr revlist)))))))))
\paper { \paper {
indexTitleMarkup = \markup \column { indexTitleMarkup = \tocSubtitleText
\fontsize #5 \sans \bold \fill-line { \null \fromproperty #'index:text \null }
\vspace #.5
\justify {
Da die allermeisten Lieder unter verschiedenen Namen bekannt sind,
wollen wir euch ein Inhaltsverzeichnis an die Hand geben, mit dem ihr hoffentlich auf verschiedene Arten fündig werdet.
Die Liedtitel, die auch die Überschriften sind, findet ihr normal gedruckt.
Alle weiteren Alternativtitel oder Liedanfänge sind zur Unterscheidung kursiv gedruckt.
}
\vspace #1
}
categoryTitleMarkup = \markup \column { categoryTitleMarkup = \markup \column {
\fontsize #5 \sans \bold \fill-line { \null \fromproperty #'index:text \null } \fontsize #5 \sans \bold \fill-line { \null \fromproperty #'index:text \null }
\vspace #1 \vspace #1
@ -182,8 +181,8 @@
indexItemMarkup = \markup \with-link-symbol-ref #'index:label { indexItemMarkup = \markup \with-link-symbol-ref #'index:label {
\index-item-with-pattern \index-item-with-pattern
} }
indexSectionMarkup = \markup \override #'(baseline-skip . 1.5) \column { indexSectionMarkup = \markup \override #'(baseline-skip . 1.5) \left-column {
\fill-line { \sans \bold \fontsize #3 \fromproperty #'index:text \null } \sans \bold \fontsize #3 \fromproperty #'index:text
\null \null
} }
indexCategoryMarkup = \markup \override #'(baseline-skip . 1.5) \column { indexCategoryMarkup = \markup \override #'(baseline-skip . 1.5) \column {
@ -236,7 +235,7 @@
(ly:output-def-lookup layout 'indexTitleMarkup)))) (ly:output-def-lookup layout 'indexTitleMarkup))))
(cons title (cons title
(interpret-markup-list layout props (interpret-markup-list layout props
(make-columnlayout-markup-list 3 2 (make-columnlayout-markup-list songTocColumns 2
(let ((h (- (ly:output-def-lookup layout 'paper-height) 12))) (let ((h (- (ly:output-def-lookup layout 'paper-height) 12)))
(cons (- h (interval-length (ly:stencil-extent title Y))) h)) (cons (- h (interval-length (ly:stencil-extent title Y))) h))
(prepare-item-markup index-items layout)))))) (prepare-item-markup index-items layout))))))
@ -249,7 +248,7 @@
(ly:output-def-lookup layout 'categoryTitleMarkup)))) (ly:output-def-lookup layout 'categoryTitleMarkup))))
(cons title (cons title
(interpret-markup-list layout props (interpret-markup-list layout props
(make-columnlayout-markup-list 3 2 (make-columnlayout-markup-list songTocColumns 2
(let ((h (- (ly:output-def-lookup layout 'paper-height) 12))) (let ((h (- (ly:output-def-lookup layout 'paper-height) 12)))
(cons (- h (interval-length (ly:stencil-extent title Y))) h)) (cons (- h (interval-length (ly:stencil-extent title Y))) h))
(prepare-item-markup category-index-items layout))))))) (prepare-item-markup category-index-items layout)))))))

13
transposition.ly Normal file
View File

@ -0,0 +1,13 @@
TRANSPOSITION = ##f
transposeGlobal =
#(define-void-function (from to) (ly:pitch? ly:pitch?)
(set! TRANSPOSITION (cons from to)))
transposable =
#(define-music-function (music) (ly:music?)
(if TRANSPOSITION
#{
\transpose #(car TRANSPOSITION) #(cdr TRANSPOSITION) #music
#}
music))

View File

@ -1,18 +1,13 @@
% guile regular expressions aktivieren:
#(use-modules (ice-9 regex))
% parsing line by line % parsing line by line
#(define-markup-command (wrap-newline layout props text) (string?) #(define-markup-command (wrap-newline layout props text) (string?)
"Text Zeile für Zeile parsen" "Text Zeile für Zeile parsen"
(interpret-markup layout props (interpret-markup layout props
#{ \markup { \column { #{ \markup { \column {
$(let ((verse-markup-string (string-append "\\line { " $(let ((verse-markup-string (
(regexp-substitute/global #f "\n" string-append "\\line { "
text (ly:regex-replace (ly:make-regex "\n") text " } \\line { ")
'pre " } \\line { " 'post )
" \\size-box-to-box ##f ##t \"\" \"Agj\" }" ))) " \\size-box-to-box ##f ##t \"\" \"Agj\" }" )))
;(ly:parse-string-expression (if (< (list-ref (ly:version) 1) 19) (ly:parser-clone parser) (ly:parser-clone)) verse-markup-string)) (ly:parser-include-string verse-markup-string))
(if (< (list-ref (ly:version) 1) 19) (ly:parser-include-string parser verse-markup-string) (ly:parser-include-string verse-markup-string)))
}}#} }}#}
) )
) )
@ -108,26 +103,28 @@
% Kompletten Vers mit Akkorden % Kompletten Vers mit Akkorden
#(define-markup-command (chordverse layout props stanza verse) (markup? string?) #(define-markup-command (chordverse layout props stanza verse) (markup? string?)
#:properties ((intraverse-vspace 0))
"Vers mit Akkorden" "Vers mit Akkorden"
(let* ((fromto (chain-assoc-get 'transposition props #f)) (let* ((fromto (chain-assoc-get 'transposition props #f))
(transp (if fromto (transp (if fromto
(string-append "\\transpose " (car fromto) " " (cdr fromto)) (string-append "\\transpose " (car fromto) " " (cdr fromto))
""))) "")))
(interpret-markup layout props (interpret-markup layout props
(markup #:override `(baseline-skip . ,songTextLineHeigth) #:anchor-x-between #:stanza stanza (markup #:override `(baseline-skip . ,(+ intraverse-vspace songTextLineHeigth)) #:anchor-x-between #:stanza stanza
(make-wrap-newline-markup (make-wrap-newline-markup
(regexp-substitute/global #f "\\(( *)([^,()]*)( *),([^)]*)\\)" (ly:regex-replace (ly:make-regex "\\(( *)([^,()]*)( *),([^)]*)\\)")
(regexp-substitute/global #f "(([^ \n]*\\([^()]*\\)[^ \n]*)+)" verse (ly:regex-replace (ly:make-regex "(([^ \n]*\\([^()]*,[^()]+\\)[^ \n(]*)+)") verse " \\concat { " 1 " } ")
'pre " \\concat { " 1 " } " 'post) "\\textup \\line { \"" 1 "\" " 2 " \"" 3 "\" } \\score { \\transposable " transp " \\chords { s4 " 4 " } \\layout { \\verseChordLayout } }")
'pre "\\textup \\line { \"" 1 "\" " 2 " \"" 3 "\" } \\score { " transp " \\chords { s4 " 4 " } \\layout { \\verseChordLayout } }" 'post)) )
)))) ))))
% Kompletter Vers aus dem Akkorde entfernt werden % Kompletter Vers aus dem Akkorde entfernt werden
#(define-markup-command (nochordverse layout props stanza verse) (markup? string?) #(define-markup-command (nochordverse layout props stanza verse) (markup? string?)
#:properties ((intraverse-vspace 0))
"Vers ohne Akkorde" "Vers ohne Akkorde"
(interpret-markup layout props (interpret-markup layout props
(markup #:override '(baseline-skip . 3.0) #:anchor-x-between #:stanza stanza (markup #:override `(baseline-skip . ,(+ intraverse-vspace 3.0)) #:anchor-x-between #:stanza stanza
#:wrap-newline (regexp-substitute/global #f "\\(([^,]*),([^)]*)\\)" verse 'pre 1 'post ) #:wrap-newline (ly:regex-replace (ly:make-regex "\\(([^,]*),([^)]*)\\)") verse 1)
) )
) )
) )