Autor Thema: Markup Befehl \justify bzw. #:justify in Scheme  (Gelesen 2611 mal)

complanar

  • Member
Markup Befehl \justify bzw. #:justify in Scheme
« am: Mittwoch, 11. April 2012, 21:31 »
Hallo allerseits,

ich möchte folgendes erreichen. Unter einem Lied soll ein kleiner Hinweis gedruckt werden mit Verweis auf den Originaltitel oder Interpreten usw.. Da es sich am Ende um ein Songbook handeln soll und daher die Formatierungen zentral festgelegt werden sollen, habe ich einen neuen Markup-Befehl erstellt, der folgendes macht:

Er testet, ob der angegebene Hinweis länger als eine ganze Zeile ist, dann nämlich wir er im Blocksatz gesetzt. Wenn das nicht der Fall ist, soll er rechtsbündig gesetzt werden. Meine Befehle lauten wie folgt:

\version "2.14.2"

#(define-markup-command (hint layout props arg)
  (markup-list?)
  (let* (
      (single-line (markup (make-line-markup arg)))
      (markp-width (interval-length (ly:stencil-extent (interpret-markup layout props single-line) X)))
      (markp
        (if (> markp-width (ly:output-def-lookup layout 'line-width))
            (markup
            ;; Eigentlich sollte hier folgendes stehen:
            ;; #:justify (arg)
            ;; das funktioniert aber nicht wie erwartet und produziert immer
            ;; Fehlermeldungen, warum, weiß ich nicht, denn ein zusätzlicher Test
            ;; mit (markup-list? arg) produziert immer #t, eigentlich sollte
            ;; es also keine Schwierigkeiten geben! Auch an der Klammersetzung
            ;; liegt es nicht.
            ;; Workaround: #:justify-string (markup->string arg)
            #:justify-string (markup->string arg)
          )
          (markup #:fill-line (#:null (make-line-markup arg)))
        )
      )
    )
    (interpret-markup layout props markp)
  )
)

\markup \hint {
  Das ist ein \italic kurzer Text, der \bold rechtsbündig steht.
}

\markup \hint {
  Das ist ein etwas \italic längerer Text, der eigentlich im \bold Blocksatz stehen sollte. Im Workaround funktioniert das auch, dafür gehen erwartungsgemäß alle Formatierungen verloren.
}

Das Problem ist, dass sich #:justify nicht wie erwartet verhält. Es produziert nämlich immer folgende Fehlermeldung.
Fehler: make-justify-markup: Ungültiges Argument an Position 1. markup list erwartet, (("Das" "ist" [...] "verloren.")) gefunden

Ich weiß leider nicht mehr weiter. Ich habe alles abgesucht und komme nicht weiter. arg ist eine markup-list, sollte zumindest eine sein, aber es haut irgendwie nicht hin. Auch Versuche mit (list arg) oder ((arg)) haben mich nicht weitergebracht. Google und dieses Forum brachten auch keine Ergebnisse.

Kann mir jemand einen Tipp geben?

harm6

  • Member
Re: Markup Befehl \justify bzw. #:justify in Scheme
« Antwort #1 am: Donnerstag, 12. April 2012, 01:20 »
Hallo complanar,

ich kann Dir leider nicht genau sagen, wo es bei Deinem Ansatz hakt. Ich weiß nur, daß es so nicht klappt (aber das weißt Du ja selbst ;) )

Folgendes scheint aber zu funktionieren:

\version "2.14.2"

#(define-markup-command (hint layout props args) (markup-list?)
 #:properties ((baseline-skip)
wordwrap-internal-markup-list)
   (let* ((mrkp-ls (interpret-markup-list layout props
            (make-wordwrap-lines-markup-list args)))
          (>one-line? (> (length mrkp-ls) 1))
          (mrkp-width (interval-length (ly:stencil-extent (car mrkp-ls) X)))
          (line-width (ly:output-def-lookup layout 'line-width))
          (delta (- line-width mrkp-width))
          (new-args (if >one-line? args (cons (make-hspace-markup delta) args))))
   (stack-lines DOWN 0.0 baseline-skip
     (wordwrap-internal-markup-list layout props #t new-args))))

\markup \hint {
        Das ist ein \italic kurzer Text, der \bold rechtsbündig steht.
}

\markup \vspace #4

\markup \override #'(baseline-skip . 5) \hint  {
        Das ist ein etwas \italic längerer Text, der eigentlich im \bold Blocksatz stehen sollte.
        Im Workaround funktionierte das auch, dafür gingen erwartungsgemäß alle Formatierungen verloren.
        Aber jetzt klappt es sehr wohl. Zumindest meine ich, daß es so gehen sollte. Ein
        \italic "\\baseline-skip"- override ist natürlich ebenfalls möglich. \hspace #5
        \fontsize #6 \with-color #red \rotate #-90 ":-)"
}

Getestet mit "2.14.2" und "2.15.36"


HTH,
  Harm

complanar

  • Member
Re: Markup Befehl \justify bzw. #:justify in Scheme
« Antwort #2 am: Donnerstag, 12. April 2012, 01:45 »
Hallo harm,

vielen dank für deine Bemühungen. Allerdings habe ich festgestellt, dass es bei weniger als drei Argumenten zu komischen Effekten kommt. Mal schauen, ob sich die noch ausmerzen lassen.

z.B. wenn ich \markup \hint { Zwei Wörter } eingebe. Nur wenn die beiden Wörter lang genug sind, dann haut es wieder hin.

complanar

  • Member
Re: Markup Befehl \justify bzw. #:justify in Scheme
« Antwort #3 am: Donnerstag, 12. April 2012, 02:24 »
Mir ist noch etwas aufgefallen. Das Ergebnis kann irgendwie nicht weiterverarbeitet werden. Wenn ich das alles in einer anderen Schriftart oder -größe haben will, stoße ich wieder auf denselben Fehler, z.B. durch

#(define-markup-command (hintII layout props args) (markup-list?)
                        (let* ()
                              (interpret-markup layout props (markup #:smaller #:hint (args)))))

\markup \hintII { Das funktioniert schon wieder nicht. )

Alles andere habe ich wie bei deinem Vorschlag gelassen. Ich glaube mittlerweile, dass markup-commands, die eine markup-list als Argument erfordern nicht innerhalb des markup makros in Scheme verwendet werden können, aber das muss ich mal noch besser überprüfen. Ich schaue mal in die Quelltexte hinein, ob sich das bestätigen lässt.

harm6

  • Member
Re: Markup Befehl \justify bzw. #:justify in Scheme
« Antwort #4 am: Donnerstag, 12. April 2012, 19:15 »
Hallo complanar,

das erste Problem bin ich angegangen, indem ich einzeilige markups anders verarbeiten lasse. Allerdings ist es jetzt notwendig einen weiteren Textbeschriftungsbefehl voranzustellen:

\markup \fill-line-from-right { \hint #p-3 { <Text> } }

\fill-line-from-right ist eine Variation von \fill-line. Der Name sollte selbsterklärend sein.

Das zweite Problem (Weiterverarbeitung) habe ich durch Einführung eines weiteren Arguments bearbeitet.
p-3 ist eine vordefinierte Procedure, die die markup-list-Argumente verändert bevor sie vom eigentlichen \hint verarbeitet werden.

Anmerkungen:
  • Die general-column-Definition ist ein wörtliches Zitat aus define-markup-commands.scm. Allerdings nicht public, und so mußte ich sie hier wiederholen
  • Ich habe es nicht hinbekommen \fill-line-from-right und \hint in eine Definition zu packen. Ich weiß auch nicht, ob es überhaupt sinnvoll ist, denn mögliche baseline-skip- und/oder line-width-overrides müssen dazwischen platziert werden.
  • Schau mal wie es Dir gefällt. Ich habe den Eindruck, daß Du eine stärker automatisierte Vorgehensweise bevorzugen würdest!?

\version "2.14.2"

#(define (general-column align-dir baseline mols)
  (let* ((aligned-mols (map (lambda (x) (ly:stencil-aligned-to x X align-dir)) mols)))
    (stack-lines -1 0.0 baseline aligned-mols)))
   
#(define (p-1 args)
  (map (lambda (x) (markup #:smaller #:with-color '(1 0 1) x)) args))
 
#(define (p-2 args)
  (map (lambda (x) (markup #:override '(font-name . "Comic Sans MS") x)) args))
 
#(define (p-3 args)
  (map (lambda (x) (markup #:override '(font-name . "URW Chancery L") x)) args)) 

#(define-markup-command (hint layout props proc args) (scheme? markup-list?)
 #:properties ((baseline-skip)
wordwrap-internal-markup-list)
   (let* ((mrkp-ls (interpret-markup-list layout props
            (make-wordwrap-lines-markup-list args)))
          (>one-line? (> (length mrkp-ls) 1))
          (mrkp-width (interval-length (ly:stencil-extent (car mrkp-ls) X)))
          (line-width (ly:output-def-lookup layout 'line-width))
          (delta (- line-width mrkp-width 0.25))
          (new-args (if (eq? #f proc)
          args (proc args))))

   (let ((stils (if >one-line?
                  (stack-lines DOWN 0.0 baseline-skip
                    (wordwrap-internal-markup-list layout props #t new-args))
                  (general-column RIGHT baseline-skip (wordwrap-internal-markup-list layout props #f new-args))))
                  )
   stils)))

#(define-markup-command (fill-line-from-right layout props args) (markup-list?)     
(interpret-markup layout props
            (make-fill-line-markup (cons (markup #:null) args))))

%----- Test
           
\markup \fill-line-from-right {
        \hint ##f {
        Das ist ein \italic kurzer Text, der \bold rechtsbündig steht.
        }
}

\markup \vspace #4

\markup \fill-line-from-right
        \override #'(baseline-skip . 5)
        %\override #'(line-width . 50)
        {
        \hint #p-1 {
                Das ist ein etwas \italic längerer Text, der eigentlich im \bold Blocksatz stehen sollte.
                Im Workaround funktionierte das auch, dafür gingen erwartungsgemäß alle Formatierungen verloren.
                Aber jetzt klappt es sehr wohl. Zumindest meine ich, daß es so gehen sollte. Ein
                \italic "\\baseline-skip"- override ist natürlich ebenfalls möglich. \hspace #5
                \fontsize #6 \with-color #red \rotate #-90 ":-)"
        }
        }
 
\markup \vspace #4

\markup \fill-line-from-right {
        \hint #p-3 {
        Das ist ein \fontsize #1 kurzer Text, der \fontsize #1 rechtsbündig steht.
        }
}

\markup \vspace #4

\markup \fill-line-from-right
        \override #'(baseline-skip . 5)
        %\override #'(line-width . 50)
        {
        \hint #p-2 {
                Das ist ein etwas \with-color #red längerer Text, der eigentlich im \fontsize #2 Blocksatz stehen sollte.
                Im Workaround funktionierte das auch, dafür gingen erwartungsgemäß alle Formatierungen verloren.
                Aber jetzt klappt es sehr wohl. Zumindest meine ich, daß es so gehen sollte. Ein
                \with-color #red "\\baseline-skip"- override ist natürlich ebenfalls möglich. \hspace #5
                \fontsize #6 \with-color #red \rotate #-90 ":-)"
        }
        }

Gruß,
  Harm

complanar

  • Member
Re: Markup Befehl \justify bzw. #:justify in Scheme
« Antwort #5 am: Freitag, 13. April 2012, 09:59 »
Ich habe mich noch mal genauer durch die dateien scm/markup.scm und scm/define-markup-commands.scm durchgekämpft.
Das einiges ergeben. Wenn man das markup-Makro in Scheme verwendet, werden intern alle Markup-Kommandos nach dem Muster #:COMMAND, die ja für \COMMAND stehen auf Funktionen namens make-COMMAND-markup umgeleitet.

Und jetzt das Tolle: Wenn ich statt #:justify (args) make-justify-markup arg verwende, dann funktioniert es! Vielen Dank trotzdem, aber dann sind deine Bemühungen jetzt leider obsolet.

Das neue Markup-Command sieht also wie folgt aus:

#(define-markup-command (hint layout props arg)
  (markup-list?)
  (let* ((single-line (markup (make-line-markup arg)))
         (markp-width (interval-length (ly:stencil-extent (interpret-markup layout props single-line) X)))
         (markp (if (> markp-width (ly:output-def-lookup layout 'line-width))
                (markup (make-justify-markup arg))
                (markup #:fill-line (#:null (make-line-markup arg))))))
        (interpret-markup layout props markp)))

\markup \hint {
  Das ist ein \italic kurzer Text, der \bold rechtsbündig steht.
}

\markup \vspace #2

\markup \override #'(line-width . 90) \hint {
  Das ist ein etwas \italic längerer Text, der eigentlich im \bold Blocksatz stehen sollte. Im Workaround funktioniert das auch, dafür gehen erwartungsgemäß alle Formatierungen verloren.

  Aber jetzt klappt es sehr wohl. Zumindest meine ich, daß es so gehen sollte. Ein \italic "\\baseline-skip"- override ist natürlich ebenfalls möglich. \hspace #5 \fontsize #6 \with-color #red \rotate #-90 ":-)"
}

Auch baseline-skip und line-with overrides funktionieren.

harm6

  • Member
Re: Markup Befehl \justify bzw. #:justify in Scheme
« Antwort #6 am: Samstag, 14. April 2012, 11:41 »
Hallo complanar,

Zitat
Vielen Dank trotzdem, aber dann sind deine Bemühungen jetzt leider obsolet.

Obsolet schon. Aber ich habe wieder etwas dazugelernt, und das ist für mich das wichtigste! :)

Gruß,
  Harm