Markup mit Formatierung als Funktion übergeben

Begonnen von oiseau, Montag, 25. Januar 2021, 00:08

« vorheriges - nächstes »

oiseau

Ich habe ein Script zusammengestellt, das mehrere kurze Scores untereinander anzeigt, was super funktioniert. Vor jedem Score gebe ich in der folgenden Variante mit einer Variablen den Namen des Stückes an:


\set PianoStaff.instrumentName = \NameA


Vorher habe ich alle Namen einzeln definiert:


NameA = \markup { \bold \fontsize #4 "Stück 1" }
NameB = \markup { \bold \fontsize #4 "Stück 2" }
...


Gibt es eine Möglichkeit, die Formatierung in einer Funktion unterzubringen, der nur noch der Name des Stückes mitgegeben werden muss?

Wenn ich den folgenden Code mit NameA = piecename #"Stück 1" aufrufe, wird nichts übergeben.


piecename =
#(define-music-function
     (parser location titel)
     (markup?)
   #{
   
     \markup { \bold \fontsize #4 #titel }
   #})



Pusteblumi

Hallo oiseau,

willkommen im Forum.

Es gibt einen Unterschied zwischen define-music-function und define-markup-command.
Leider haben die beiden auch noch eine unterschiedliche Syntax. Ich muss die auch jedes Mal nachschlagen...

Versuch mal
\version "2.20.0"

\paper {
  indent = 3\cm
}

#(define-markup-command (piecename layout props titel)
   (markup?)
   (interpret-markup layout props
     #{
       \markup {
         \bold \fontsize #4 $titel
       }
     #}))

NameA = \markup \piecename "Stück 1"

\new PianoStaff {
  \set PianoStaff.instrumentName = \NameA
  <<
    \new Staff { c' }
    \new Staff { \clef bass c }
  >>
}


oder

\version "2.20.0"

\paper {
  indent = 3\cm
}

#(define-markup-command (piecename layout props titel)
   (markup?)
   (interpret-markup layout props
     #{
       \markup {
         \bold \fontsize #4 $titel
       }
     #}))

NameA = \markup \piecename "Stück 1"

\new PianoStaff {
  \set PianoStaff.instrumentName = \NameA
  <<
    \new Staff { c' }
    \new Staff { \clef bass c }
  >>
}


Viele Grüße,
Klaus

oiseau

Hallo Pusteblumi,

hab tausend Dank für Deinen Quellcode. Er funktioniert wunderbar und hilft mir sehr weiter.   :D

Viele Grüße
Mathias

harm6

Hallo oiseau,


auch von mir ein willkommen im Forum!


Zunächst zu Deiner eigentlichen Frage:
ZitatGibt es eine Möglichkeit, die Formatierung in einer Funktion unterzubringen, der nur noch der Name des Stückes mitgegeben werden muss?

Es klappt wenn Du eine scheme-function schreibst, keine music-function:

myOtherName =
#(define-scheme-function (mrkp)(markup?)
  #{ \markup \bold \fontsize #4 $mrkp #})
 
\myOtherName "Stück 3"



Ein markup-command geht natürlich auch, muß aber immer als
\markup \my-command ...
aufgerufen werden.

Klaus hat ja schon gezeigt wie man ein solches markup-command schreibt.
In manchen Fällen kann man mittlerweile eine Kurzdefinition verwenden:

%% Definition
\markup myName = \markup \bold \fontsize #4 \etc

%% Aufruf
\markup \myName "Stück 2"

"In manchen Fällen" heißt: es darf nur exakt ein Argument übergeben werden und dieses Argument muß am Ende des Aufrufs stehen.


Ich persönlich würde aber den Formatierungscode gänzlich auslagern, d.h. InstrumentName im \layout formatieren, zumindest falls die Formatierung immer dieselbe ist:

\layout {
  \context {
  \PianoStaff
  \override InstrumentName.font-series = #'bold
  \override InstrumentName.font-size = #4
  }
  %% No formatting for Staff.InstrumentName:
  \context {
  \Staff
  \override InstrumentName.font-series = #'upright
  \override InstrumentName.font-size = #0
  }
}

\new PianoStaff
  \with { instrumentName = "EINS" }
  <<
  \new Staff \with { instrumentName = "1" } R1
  \new Staff \with { instrumentName = "2" } R1
  >>
 
\new PianoStaff
  \with { instrumentName = "ZWEI" }
  <<
  \new Staff \with { instrumentName = "R" } R1
  \new Staff \with { instrumentName = "L" } R1
  >>

Falls man je nach context unterschiedliche Setzungen möchte, muß man diese auch getrennt spezifizieren.
Hat aber den Vorteil, daß man nur noch an einer Stelle eingreifen muß, falls Änderungen nötig werden.


Gruß,
  Harm

oiseau

Hallo Harm,

die define-scheme-function finde ich in der Tat viel besser. Allerdings finde ich hier keinen Weg, zwei Variablen zu übergeben und auszugeben. Kannst Du mir hier eventuell weiterhelfen?




myOtherName =
#(define-scheme-function (mrkp zusatz)(markup? markup?)
  #{ \markup \bold \fontsize #4 $mrkp \fontsize #2 $zusatz #})

\myOtherName "Stück 3" "(Info...)"


Pusteblumi

Hallo Mathias,

das klappt, sobald du die beiden markups mit dem \concat-Befehl zu einem verbindest:

myOtherName =
#(define-scheme-function (mrkp zusatz)(markup? markup?)
  #{ \markup \bold \concat { \fontsize #4 $mrkp \fontsize #2 $zusatz } #})

\myOtherName "Stück 3" "(Info...)"


Viele Grüße,
Klaus

P.S.: Wieder was gelernt... die Konstruktion mit define-scheme-function muss ich mir unbedingt merken.   :)

harm6

Zitat von: oiseau
die define-scheme-function finde ich in der Tat viel besser. Allerdings finde ich hier keinen Weg, zwei Variablen zu übergeben und auszugeben.

Noch etwas Hintergrund:
In den Funktionen wird #{ ... #} benutzt um ly-Syntax in scheme einzubetten.
Wenn man dort zwei verschiedene, voneinander unabhängige \markup schreibt (und genau das hast Du de facto getan), entsteht das Problem, daß jede Funktion nur exakt einen Rückgabewert ausgeben kann.
Nun gibt es aber nur eine (naheliegende) Möglichkeit zwei markups in eine Rückgabe zu packen, nämlich als sequentielle Musik von LyricEvents.
    \void #(display-lily-music #{ \markup "bar" \markup "buzz" #})
    ->
    \lyricmode { bar buzz }
Da aber kein Lyrics-context initiiert wurde gibts noch Warnungen obendrauf.
Nicht was man haben will.

Klaus hat ja schon eine Möglichkeit gezeigt, wie man ein \markup in #{ ... #} erstellt. Statt \concat kann man aber auch andere markup-commands nutzen, solange sicher gestellt ist, daß nur ein markup entsteht,
Tatsächlich genügt schon, daß man Klammern benutzt. Dann wird alles eingeklammerte als \line-markup verstanden.
    \void #(display-scheme-music #{ \markup { "bar" "buzz" } #})
    ->
    (markup #:line (#:simple "bar" #:simple "buzz"))

HTH,
  Harm

oiseau