Indenting individual systems: Difference between revisions
Import snippet from LSR |
mNo edit summary |
||
| (5 intermediate revisions by 2 users not shown) | |||
| Line 1: | Line 1: | ||
LilyPond scores are indented | LilyPond scores are indented similar to text paragraphs: all systems except the first one are indented by the same amount (the value of the <code>short-indent</code> property). This layout constraint is applied in advance and cannot be modified later. In other words, indenting on a system-by-system basis is not possible with this mechanism. | ||
Users who need a differently indented system can arrange for that system to start a new score, as demonstrated in the snippet [[Coda ahead of a line of its own]]. That may be a reasonable workaround at a more or less natural break such as a coda, but in general the structure clash introduces severe fragmentation requiring compensatory splicing and fudging; see [https://lists.gnu.org/archive/html/lilypond-user/2014-12/msg00436.html this discussion] of problems with this approach. | |||
This snippet demonstrates | This snippet demonstrates a pseudo-indent workaround that superimposes an additional, system-wise indentation on the score's unmodified layout indentation, avoiding the abovementioned score change problems. It allows to change the left and right (pseudo) indentation independently; optionally, the instrument name can be changed, too. | ||
Some caveats still apply, though. | |||
< | * The indenting mechanism is based on an [https://gitlab.com/lilypond/lilypond/-/issues/3761 arcane misuse] of the <code>LeftEdge</code> grob and may therefore become temporarily or permanently broken by side effects of future development changes in the LilyPond code base. | ||
* The code is not protected against multiple calls per system break. | |||
<lilypond version="2.24" full> | |||
%%%%%%%% HEADER %%%%%%%% | |||
% | |||
% This code was prompted by | |||
% | |||
% https://lists.gnu.org/archive/html/lilypond-user/2019-07/msg00139.html | |||
% | |||
% and offers a pseudo-indent hack suitable for general use. | |||
% | |||
% keywords: | |||
% | |||
% indent short-indent indentation system line | |||
% mid-score temporarily arbitrary individual single just only once | |||
% coda margin | |||
% | |||
% Put the code before the examples into a file `pseudo-indent.ily` that | |||
% you can include later on in your code with | |||
% | |||
% \include "pseudo-indent.ily" | |||
%%%%%%%% PSEUDO-INDENT FUNCTIONS START %%%%%%%% | |||
% Two functions are provided for indenting individual systems. | |||
%%%%%%%% | % | ||
% - To left-indent a system, apply `\pseudoIndent` before the music | |||
% continues. | |||
% - `\pseudoIndents` does the same but lets you also indent on the | |||
% right. | |||
% | |||
% Both commands accept an optional argument for changing the affected | |||
% system's instrument name(s). | |||
% | |||
% The following conditions must be met to make the functions work. | |||
% | |||
% - It is assumed that the score is not using a ragged-right layout | |||
% (which is the default for multi-system scores). | |||
% - A manual `\break` must be used to call the functions at the start | |||
% of a system. | |||
% - The functions misbehave if called more than once at the same | |||
% system start. | |||
% | |||
% The syntax forms are as follows. | |||
% | |||
% \pseudoIndent [<name-tweaks>] <left-indent> | |||
% \pseudoIndent [<name-tweaks>] <left-indent> <right-indent> | |||
% | |||
% <name-tweaks> | |||
% An optional argument holding a markup list for instrument names | |||
% as an ordered list. If an element is `*`, the previous | |||
% instrument name stays unchanged. | |||
% <left-indent> | |||
% Additional left indentation, in staff-space units. This value | |||
% can be negative with the restriction that the sum | |||
% | |||
% <left-indent> + `short-indent` | |||
% | |||
% must be larger or equal to zero to avoid unsupported | |||
% stretching. | |||
% <right-indent> | |||
% Additional right indentation, in staff-space units; can be | |||
% negative. | |||
% | |||
% Examples: | |||
% | % | ||
% | % \pseudoIndent 11 | ||
% | % \pseudoIndents 11 22 | ||
% | % \pseudoIndents \markuplist { "foo" * \myMarkup } 11 22 | ||
pseudoIndents = | |||
#(define-music-function (name-tweaks left-indent right-indent) | |||
((markup-list? '()) number? number?) | |||
(define (warn-stretched p1 p2) | |||
(ly:input-warning | |||
(*location*) | |||
(G_ | |||
" \\pseudoIndents ~s ~s is stretching staff; expect distorted layout") | |||
p1 p2)) | |||
(let* | |||
((narrowing (+ left-indent right-indent)) | |||
(set-staffsymbol! | |||
(lambda (staffsymbol-grob) ; change staff to new width | |||
(let* | |||
((left-bound (ly:spanner-bound staffsymbol-grob LEFT)) | |||
(left-moment (ly:grob-property left-bound 'when)) | |||
;; in first system of score? | |||
(capo? (moment<=? left-moment ZERO-MOMENT)) | |||
(layout (ly:grob-layout staffsymbol-grob)) | |||
;; debugging info | |||
(lw (ly:output-def-lookup layout 'line-width)) | |||
(indent (ly:output-def-lookup | |||
layout | |||
(if capo? 'indent 'short-indent))) | |||
(old-stil (ly:staff-symbol::print staffsymbol-grob)) | |||
(staffsymbol-x-ext (ly:stencil-extent old-stil X)) | |||
;; For LilyPond versions >=2.19.16 the first system has | |||
;; `old-stil` already narrowed. Compensate for this | |||
;; (i.e., being not pristine) when calculating. | |||
;; | |||
;; - old leftmost-x (its value is needed when setting | |||
;; so-called 'width) | |||
;; - the new width and position (via local variable | |||
;; `narrowing_`) | |||
(ss-t (ly:staff-symbol-line-thickness | |||
staffsymbol-grob)) | |||
;; would expect half | |||
(pristine? (<= 0 (car staffsymbol-x-ext) ss-t)) | |||
(leftmost-x (+ indent (if pristine? 0 narrowing))) | |||
;; uses 0 if already narrowed | |||
(narrowing_ (if pristine? narrowing 0)) | |||
(old-width (+ (interval-length staffsymbol-x-ext) | |||
ss-t)) | |||
(new-width (- old-width narrowing_)) | |||
;; and set! this immediately | |||
(new-rightmost-x (+ leftmost-x new-width)) | |||
(junk (ly:grob-set-property! staffsymbol-grob | |||
'width new-rightmost-x)) | |||
(in-situ-stil (ly:staff-symbol::print | |||
staffsymbol-grob)) | |||
(new-stil (ly:stencil-translate-axis in-situ-stil | |||
narrowing_ | |||
X)) | |||
;; for debugging | |||
;; (new-stil (stencil-with-color new-stil red)) | |||
(new-x-ext (ly:stencil-extent new-stil X))) | |||
(ly:grob-set-property! staffsymbol-grob 'stencil | |||
new-stil) | |||
(ly:grob-set-property! staffsymbol-grob 'X-extent | |||
new-x-ext)))) | |||
;; move grob across to line start | |||
(set-X-offset! | |||
(lambda (margin-grob) | |||
(let* ((old (ly:grob-property-data margin-grob 'X-offset)) | |||
(new (lambda (grob) | |||
(+ (if (procedure? old) (old grob) old) | |||
narrowing)))) | |||
(ly:grob-set-property! margin-grob 'X-offset new)))) | |||
;; tweak both instrument name texts | |||
(tweak-text! | |||
(lambda (i-name-grob mkup) | |||
(when (and (markup? mkup) | |||
(not (string=? (markup->string mkup) "*"))) | |||
(ly:grob-set-property! i-name-grob 'long-text mkup) | |||
(ly:grob-set-property! i-name-grob 'text mkup)))) | |||
;; on staves, + adapt left margin | |||
(install-narrowing | |||
(lambda (leftedge-grob) | |||
(let* | |||
((sys (ly:grob-system leftedge-grob)) | |||
(all-grobs (ly:grob-array->list | |||
(ly:grob-object sys 'all-elements))) | |||
(grobs-named | |||
(lambda (name) | |||
(filter (lambda (x) | |||
(eq? name (grob::name x))) all-grobs))) | |||
(first-leftedge-grob (list-ref | |||
(grobs-named 'LeftEdge) 0)) | |||
(relsys-x-of (lambda (g) | |||
(ly:grob-relative-coordinate g sys X))) | |||
(leftedge-x (relsys-x-of first-leftedge-grob)) | |||
(leftedged? (lambda (g) | |||
(= (relsys-x-of g) leftedge-x))) | |||
(leftedged-ss (filter leftedged? | |||
(grobs-named 'StaffSymbol)))) | |||
;; ignore other left-edges | |||
(when (eq? leftedge-grob first-leftedge-grob) | |||
(for-each set-staffsymbol! leftedged-ss) | |||
(for-each set-X-offset! (grobs-named 'SystemStartBar)) | |||
(for-each set-X-offset! (grobs-named 'InstrumentName)) | |||
(for-each tweak-text! (grobs-named 'InstrumentName) | |||
name-tweaks)))))) | |||
(when (negative? narrowing) | |||
(warn-stretched left-indent right-indent)) | |||
;; and continue anyway | |||
#{ | |||
% ensure that these overrides are applied only at begin-of-line | |||
% (but this does not protect against unsupported multiple | |||
% application) | |||
\break | |||
% give the spacing engine notice regarding the loss of width | |||
% for music | |||
\once \override Score.LeftEdge.X-extent = | |||
#(cons narrowing narrowing) | |||
% discard line start region of staff and reassemble left-margin | |||
% elements | |||
\once \override Score.LeftEdge.after-line-breaking = | |||
#install-narrowing | |||
% shift the system to partition the narrowing between left and | |||
% right | |||
\overrideProperty Score.NonMusicalPaperColumn | |||
.line-break-system-details | |||
.X-offset #(- right-indent) | |||
% prevent a leftmost bar number entering a stretched staff | |||
\once \override Score.BarNumber.horizon-padding = | |||
#(max 1 (- 1 narrowing)) | |||
#})) | |||
pseudoIndent = | pseudoIndent = | ||
#(define-music-function (name-tweaks left-indent) | #(define-music-function (name-tweaks left-indent) | ||
((markup-list? '()) number?) | |||
#{ | |||
\pseudoIndents $name-tweaks $left-indent 0 | |||
#}) | |||
%%%%%%%% PSEUDO-INDENT FUNCTIONS END %%%%%%%% | |||
%%%%%%%% | %%%%%%%% SETUP FOR WIKI EXAMPLES %%%%%%%% | ||
\paper { | \paper { | ||
indent = 55 | indent = 55\mm | ||
short-indent = 40 | short-indent = 40\mm | ||
system-system-spacing.basic-distance = 10 | system-system-spacing.basic-distance = 10\mm | ||
tagline = ##f | tagline = ##f | ||
} | } | ||
| Line 160: | Line 234: | ||
m = { f'4 f'4 f'4 f'4 } % one measure | m = { f'4 f'4 f'4 f'4 } % one measure | ||
showInfo = #(define-music-function (info) (markup?) | showInfo = | ||
#{ | #(define-music-function (info) (markup?) | ||
#{ | |||
\once \override Score.LeftEdge.break-visibility = | |||
#begin-of-line-visible | |||
#}) | \once \override Score.LeftEdge.stencil = | ||
#(lambda (grob) (grob-interpret-markup grob info)) | |||
#}) | |||
%%%%%%%% BASIC EXAMPLE %%%%%%%% | %%%%%%%% BASIC EXAMPLE %%%%%%%% | ||
basic-info-line = \markup \translate #'(0 . -0.2) | % trace short indentation | ||
\with-color #blue | basic-info-line = \markup \translate #'(0 . -0.2) | ||
\with-color #blue | |||
\draw-dashed-line #'(0 . -49) | |||
v-gap = \markup \vspace #2.25 | v-gap = \markup \vspace #2.25 | ||
basic-info-text = \markup \translate #'(-24 . 8.8) | basic-info-text = \markup \translate #'(-24 . 8.8) \column { | ||
\column { | \italic "(indent)" | ||
\italic "(indent)" | \v-gap | ||
\v-gap | \italic "(short-indent)" | ||
\italic "(short-indent)" | \v-gap | ||
\v-gap | "\pseudoIndent 22" | ||
"\pseudoIndent 22" | \v-gap | ||
\v-gap | "\pseudoIndent 44" | ||
"\pseudoIndent 44" | \v-gap | ||
\v-gap | "\pseudoIndents 22 22" | ||
"\pseudoIndents 22 22" | \v-gap | ||
\v-gap | \line { "\pseudoIndents 0 44" | ||
\line { "\pseudoIndents 0 44" \translate #'(53 . 0) \italic | \translate #'(53 . 0) | ||
\italic "with ragged-right ##f (default)" } | |||
\v-gap | \v-gap | ||
\line { "\pseudoIndents 0 20" \translate #'(72 . 0) \italic | \line { "\pseudoIndents 0 20" | ||
\right-column { "ragged-last ##f" "(default)" }}} | \translate #'(72 . 0) | ||
\italic \right-column { "ragged-last ##f" "(default)" } } | |||
} | |||
basic = { | basic = { | ||
\omit Score.BarNumber | \omit Score.BarNumber | ||
\m \m \m \m \m \m | \m \m \m \m \m \m | ||
\break % a short-indented system for reference (also info anchor:) | \break % a short-indented system for reference (also info anchor:) | ||
\showInfo \markup \combine \basic-info-text \basic-info-line | \showInfo \markup \combine \basic-info-text \basic-info-line | ||
\m \m \m \m \m \m \m | \m \m \m \m \m \m \m | ||
\pseudoIndent 22 | \pseudoIndent 22 | ||
\m \m \m \m \m | \m \m \m \m \m | ||
\pseudoIndent 44 | \pseudoIndent 44 | ||
\m \m \m | \m \m \m | ||
\pseudoIndents 22 22 | \pseudoIndents 22 22 | ||
\m \m \m | \m \m \m | ||
\pseudoIndents 0 44 | \pseudoIndents 0 44 | ||
\m \m \m | \m \m \m | ||
\pseudoIndents 0 20 | \pseudoIndents 0 20 | ||
\m \m \m \m \m \bar "|." | \m \m \m \m \m \bar "|." | ||
| Line 214: | Line 295: | ||
\score { | \score { | ||
\new Staff { \basic } | \new Staff { \basic } | ||
\layout {} | \layout {} | ||
} | } | ||
%%%%%%%% DEMO EXAMPLE %%%%%%%% | %%%%%%%% DEMO EXAMPLE %%%%%%%% | ||
demo-info-line = \markup\translate #'(85.3 . 20.3) | % trace right margin | ||
\with-color #blue | demo-info-line = \markup \translate #'(85.3 . 20.3) | ||
\with-color #blue | |||
\draw-dashed-line #'(0 . -56) | |||
demo-info-text = \markup \translate #'(-24 . 17.3) | demo-info-text = \markup \translate #'(-24 . 17.3) \column \italic { | ||
\column \italic { | "right-indent at head" | ||
"right-indent at head" | " " | ||
" " | "stop/startStaff OK" | ||
"stop/startStaff OK" | " " | ||
" " | " " | ||
" " | " " | ||
" " | " " | ||
" " | |||
"(short-indent)" | "(short-indent)" | ||
" " | " " | ||
" " | " " | ||
" " | " " | ||
" " | " " | ||
"outdent without stretching" | "outdent without stretching" | ||
" " | " " | ||
"name-tweaks displaying" | "name-tweaks displaying" | ||
"how its list is ordered" | "how its list is ordered" | ||
" " | " " | ||
" " | " " | ||
\line {"using name-tweaks " | \line { "using name-tweaks " | ||
\column \upright { " " "\"\"" "\\mkCoda" * } | |||
" to " | |||
\column { " " "hide name" | |||
"change name" "(leave name as it is)" } } | |||
} | } | ||
mkCoda = \markup | % See https://wiki.lilypond.community/wiki/Coda_ahead_of_a_line_of_its_own | ||
\vcenter { \bold "coda" \fontsize #3 \musicglyph "scripts.coda" } | mkCoda = \markup \vcenter { | ||
\bold "coda" \fontsize #3 \musicglyph "scripts.coda" } | |||
demo = { | demo = { | ||
\pseudoIndents 0 22 % no additional left-indenting applied | \pseudoIndents 0 22 % no additional left-indenting applied | ||
s1*4 | s1*4 | ||
\break % a short-indented system for reference (also info anchor:) | \break % a short-indented system for reference (also info anchor:) | ||
\showInfo \markup \combine \demo-info-text \demo-info-line | \showInfo \markup \combine \demo-info-text \demo-info-line | ||
s1*7 | s1*7 | ||
\pseudoIndents \markuplist { 1 2 3 } 11 -4 | % display the instrument name ordering | ||
s1*6 | \pseudoIndents \markuplist { 1 2 3 } 11 -4 | ||
\pseudoIndent \markuplist { "" * \mkCoda } 55 | s1*6 | ||
% hide 1; leave 2; change 3 | |||
\pseudoIndent \markuplist { "" * \mkCoda } 55 | |||
s1*2 \bar "|." | s1*2 \bar "|." | ||
} | } | ||
demoHi = { | demoHi = { | ||
\m \m \m \m | \m \m \m \m | ||
\m \m \m \m \m \m \m | \m \m \m \m \m \m \m | ||
\m \m \m \m \m \m | \m \m \m \m \m \m | ||
\m \m | \m \m | ||
} | } | ||
demoLo = { | demoLo = { | ||
\m \m \stopStaff s1 \startStaff \m | \m \m \stopStaff s1 \startStaff \m | ||
\m \m \m \m \m \m \m | \m \m \m \m \m \m \m | ||
\m \m \m \m \m \m | \m \m \m \m \m \m | ||
\m \m | \m \m | ||
} | } | ||
\markup \huge \bold \column { " " " Further possibilities" " "} | \markup \huge \bold \column { " " " Further possibilities" " " } | ||
\score { | \score { | ||
\new StaffGroup | \new StaffGroup \with { | ||
instrumentName = "SYS" | |||
<< | shortInstrumentName = "sys" } | ||
\new Staff | << | ||
\new Staff \with { | |||
instrumentName = "HI" | |||
\new RhythmicStaff | shortInstrumentName = "hi" } | ||
<< \demo \demoHi >> | |||
\new RhythmicStaff \with { | |||
instrumentName = "LO" | |||
shortInstrumentName = "lo" } | |||
{ \demoLo } | { \demoLo } | ||
>> | >> | ||
\layout { | \layout { | ||
\override Score.InstrumentName.self-alignment-X = #RIGHT | \override Score.InstrumentName.self-alignment-X = #RIGHT | ||
| Line 302: | Line 392: | ||
</lilypond> | </lilypond> | ||
[[Category:Breaks]] | |||
[[Category:Scheme]] | |||
[[Category:Staff notation]] | |||
[[Category:Tweaks and overrides]] | |||
[[Category:Workaround]] | [[Category:Workaround]] | ||
[[Category:Snippet]] | |||
Latest revision as of 06:06, 15 December 2025
LilyPond scores are indented similar to text paragraphs: all systems except the first one are indented by the same amount (the value of the short-indent property). This layout constraint is applied in advance and cannot be modified later. In other words, indenting on a system-by-system basis is not possible with this mechanism.
Users who need a differently indented system can arrange for that system to start a new score, as demonstrated in the snippet Coda ahead of a line of its own. That may be a reasonable workaround at a more or less natural break such as a coda, but in general the structure clash introduces severe fragmentation requiring compensatory splicing and fudging; see this discussion of problems with this approach.
This snippet demonstrates a pseudo-indent workaround that superimposes an additional, system-wise indentation on the score's unmodified layout indentation, avoiding the abovementioned score change problems. It allows to change the left and right (pseudo) indentation independently; optionally, the instrument name can be changed, too.
Some caveats still apply, though.
- The indenting mechanism is based on an arcane misuse of the
LeftEdgegrob and may therefore become temporarily or permanently broken by side effects of future development changes in the LilyPond code base. - The code is not protected against multiple calls per system break.
\version "2.24"
%%%%%%%% HEADER %%%%%%%%
%
% This code was prompted by
%
% https://lists.gnu.org/archive/html/lilypond-user/2019-07/msg00139.html
%
% and offers a pseudo-indent hack suitable for general use.
%
% keywords:
%
% indent short-indent indentation system line
% mid-score temporarily arbitrary individual single just only once
% coda margin
%
% Put the code before the examples into a file `pseudo-indent.ily` that
% you can include later on in your code with
%
% \include "pseudo-indent.ily"
%%%%%%%% PSEUDO-INDENT FUNCTIONS START %%%%%%%%
% Two functions are provided for indenting individual systems.
%
% - To left-indent a system, apply `\pseudoIndent` before the music
% continues.
% - `\pseudoIndents` does the same but lets you also indent on the
% right.
%
% Both commands accept an optional argument for changing the affected
% system's instrument name(s).
%
% The following conditions must be met to make the functions work.
%
% - It is assumed that the score is not using a ragged-right layout
% (which is the default for multi-system scores).
% - A manual `\break` must be used to call the functions at the start
% of a system.
% - The functions misbehave if called more than once at the same
% system start.
%
% The syntax forms are as follows.
%
% \pseudoIndent [<name-tweaks>] <left-indent>
% \pseudoIndent [<name-tweaks>] <left-indent> <right-indent>
%
% <name-tweaks>
% An optional argument holding a markup list for instrument names
% as an ordered list. If an element is `*`, the previous
% instrument name stays unchanged.
% <left-indent>
% Additional left indentation, in staff-space units. This value
% can be negative with the restriction that the sum
%
% <left-indent> + `short-indent`
%
% must be larger or equal to zero to avoid unsupported
% stretching.
% <right-indent>
% Additional right indentation, in staff-space units; can be
% negative.
%
% Examples:
%
% \pseudoIndent 11
% \pseudoIndents 11 22
% \pseudoIndents \markuplist { "foo" * \myMarkup } 11 22
pseudoIndents =
#(define-music-function (name-tweaks left-indent right-indent)
((markup-list? '()) number? number?)
(define (warn-stretched p1 p2)
(ly:input-warning
(*location*)
(G_
" \\pseudoIndents ~s ~s is stretching staff; expect distorted layout")
p1 p2))
(let*
((narrowing (+ left-indent right-indent))
(set-staffsymbol!
(lambda (staffsymbol-grob) ; change staff to new width
(let*
((left-bound (ly:spanner-bound staffsymbol-grob LEFT))
(left-moment (ly:grob-property left-bound 'when))
;; in first system of score?
(capo? (moment<=? left-moment ZERO-MOMENT))
(layout (ly:grob-layout staffsymbol-grob))
;; debugging info
(lw (ly:output-def-lookup layout 'line-width))
(indent (ly:output-def-lookup
layout
(if capo? 'indent 'short-indent)))
(old-stil (ly:staff-symbol::print staffsymbol-grob))
(staffsymbol-x-ext (ly:stencil-extent old-stil X))
;; For LilyPond versions >=2.19.16 the first system has
;; `old-stil` already narrowed. Compensate for this
;; (i.e., being not pristine) when calculating.
;;
;; - old leftmost-x (its value is needed when setting
;; so-called 'width)
;; - the new width and position (via local variable
;; `narrowing_`)
(ss-t (ly:staff-symbol-line-thickness
staffsymbol-grob))
;; would expect half
(pristine? (<= 0 (car staffsymbol-x-ext) ss-t))
(leftmost-x (+ indent (if pristine? 0 narrowing)))
;; uses 0 if already narrowed
(narrowing_ (if pristine? narrowing 0))
(old-width (+ (interval-length staffsymbol-x-ext)
ss-t))
(new-width (- old-width narrowing_))
;; and set! this immediately
(new-rightmost-x (+ leftmost-x new-width))
(junk (ly:grob-set-property! staffsymbol-grob
'width new-rightmost-x))
(in-situ-stil (ly:staff-symbol::print
staffsymbol-grob))
(new-stil (ly:stencil-translate-axis in-situ-stil
narrowing_
X))
;; for debugging
;; (new-stil (stencil-with-color new-stil red))
(new-x-ext (ly:stencil-extent new-stil X)))
(ly:grob-set-property! staffsymbol-grob 'stencil
new-stil)
(ly:grob-set-property! staffsymbol-grob 'X-extent
new-x-ext))))
;; move grob across to line start
(set-X-offset!
(lambda (margin-grob)
(let* ((old (ly:grob-property-data margin-grob 'X-offset))
(new (lambda (grob)
(+ (if (procedure? old) (old grob) old)
narrowing))))
(ly:grob-set-property! margin-grob 'X-offset new))))
;; tweak both instrument name texts
(tweak-text!
(lambda (i-name-grob mkup)
(when (and (markup? mkup)
(not (string=? (markup->string mkup) "*")))
(ly:grob-set-property! i-name-grob 'long-text mkup)
(ly:grob-set-property! i-name-grob 'text mkup))))
;; on staves, + adapt left margin
(install-narrowing
(lambda (leftedge-grob)
(let*
((sys (ly:grob-system leftedge-grob))
(all-grobs (ly:grob-array->list
(ly:grob-object sys 'all-elements)))
(grobs-named
(lambda (name)
(filter (lambda (x)
(eq? name (grob::name x))) all-grobs)))
(first-leftedge-grob (list-ref
(grobs-named 'LeftEdge) 0))
(relsys-x-of (lambda (g)
(ly:grob-relative-coordinate g sys X)))
(leftedge-x (relsys-x-of first-leftedge-grob))
(leftedged? (lambda (g)
(= (relsys-x-of g) leftedge-x)))
(leftedged-ss (filter leftedged?
(grobs-named 'StaffSymbol))))
;; ignore other left-edges
(when (eq? leftedge-grob first-leftedge-grob)
(for-each set-staffsymbol! leftedged-ss)
(for-each set-X-offset! (grobs-named 'SystemStartBar))
(for-each set-X-offset! (grobs-named 'InstrumentName))
(for-each tweak-text! (grobs-named 'InstrumentName)
name-tweaks))))))
(when (negative? narrowing)
(warn-stretched left-indent right-indent))
;; and continue anyway
#{
% ensure that these overrides are applied only at begin-of-line
% (but this does not protect against unsupported multiple
% application)
\break
% give the spacing engine notice regarding the loss of width
% for music
\once \override Score.LeftEdge.X-extent =
#(cons narrowing narrowing)
% discard line start region of staff and reassemble left-margin
% elements
\once \override Score.LeftEdge.after-line-breaking =
#install-narrowing
% shift the system to partition the narrowing between left and
% right
\overrideProperty Score.NonMusicalPaperColumn
.line-break-system-details
.X-offset #(- right-indent)
% prevent a leftmost bar number entering a stretched staff
\once \override Score.BarNumber.horizon-padding =
#(max 1 (- 1 narrowing))
#}))
pseudoIndent =
#(define-music-function (name-tweaks left-indent)
((markup-list? '()) number?)
#{
\pseudoIndents $name-tweaks $left-indent 0
#})
%%%%%%%% PSEUDO-INDENT FUNCTIONS END %%%%%%%%
%%%%%%%% SETUP FOR WIKI EXAMPLES %%%%%%%%
\paper {
indent = 55\mm
short-indent = 40\mm
system-system-spacing.basic-distance = 10\mm
tagline = ##f
}
m = { f'4 f'4 f'4 f'4 } % one measure
showInfo =
#(define-music-function (info) (markup?)
#{
\once \override Score.LeftEdge.break-visibility =
#begin-of-line-visible
\once \override Score.LeftEdge.stencil =
#(lambda (grob) (grob-interpret-markup grob info))
#})
%%%%%%%% BASIC EXAMPLE %%%%%%%%
% trace short indentation
basic-info-line = \markup \translate #'(0 . -0.2)
\with-color #blue
\draw-dashed-line #'(0 . -49)
v-gap = \markup \vspace #2.25
basic-info-text = \markup \translate #'(-24 . 8.8) \column {
\italic "(indent)"
\v-gap
\italic "(short-indent)"
\v-gap
"\pseudoIndent 22"
\v-gap
"\pseudoIndent 44"
\v-gap
"\pseudoIndents 22 22"
\v-gap
\line { "\pseudoIndents 0 44"
\translate #'(53 . 0)
\italic "with ragged-right ##f (default)" }
\v-gap
\line { "\pseudoIndents 0 20"
\translate #'(72 . 0)
\italic \right-column { "ragged-last ##f" "(default)" } }
}
basic = {
\omit Score.BarNumber
\m \m \m \m \m \m
\break % a short-indented system for reference (also info anchor:)
\showInfo \markup \combine \basic-info-text \basic-info-line
\m \m \m \m \m \m \m
\pseudoIndent 22
\m \m \m \m \m
\pseudoIndent 44
\m \m \m
\pseudoIndents 22 22
\m \m \m
\pseudoIndents 0 44
\m \m \m
\pseudoIndents 0 20
\m \m \m \m \m \bar "|."
}
\markup \huge \bold \column { " " " Basic usage" " "}
\score {
\new Staff { \basic }
\layout {}
}
%%%%%%%% DEMO EXAMPLE %%%%%%%%
% trace right margin
demo-info-line = \markup \translate #'(85.3 . 20.3)
\with-color #blue
\draw-dashed-line #'(0 . -56)
demo-info-text = \markup \translate #'(-24 . 17.3) \column \italic {
"right-indent at head"
" "
"stop/startStaff OK"
" "
" "
" "
" "
"(short-indent)"
" "
" "
" "
" "
"outdent without stretching"
" "
"name-tweaks displaying"
"how its list is ordered"
" "
" "
\line { "using name-tweaks "
\column \upright { " " "\"\"" "\\mkCoda" * }
" to "
\column { " " "hide name"
"change name" "(leave name as it is)" } }
}
% See https://wiki.lilypond.community/wiki/Coda_ahead_of_a_line_of_its_own
mkCoda = \markup \vcenter {
\bold "coda" \fontsize #3 \musicglyph "scripts.coda" }
demo = {
\pseudoIndents 0 22 % no additional left-indenting applied
s1*4
\break % a short-indented system for reference (also info anchor:)
\showInfo \markup \combine \demo-info-text \demo-info-line
s1*7
% display the instrument name ordering
\pseudoIndents \markuplist { 1 2 3 } 11 -4
s1*6
% hide 1; leave 2; change 3
\pseudoIndent \markuplist { "" * \mkCoda } 55
s1*2 \bar "|."
}
demoHi = {
\m \m \m \m
\m \m \m \m \m \m \m
\m \m \m \m \m \m
\m \m
}
demoLo = {
\m \m \stopStaff s1 \startStaff \m
\m \m \m \m \m \m \m
\m \m \m \m \m \m
\m \m
}
\markup \huge \bold \column { " " " Further possibilities" " " }
\score {
\new StaffGroup \with {
instrumentName = "SYS"
shortInstrumentName = "sys" }
<<
\new Staff \with {
instrumentName = "HI"
shortInstrumentName = "hi" }
<< \demo \demoHi >>
\new RhythmicStaff \with {
instrumentName = "LO"
shortInstrumentName = "lo" }
{ \demoLo }
>>
\layout {
\override Score.InstrumentName.self-alignment-X = #RIGHT
\override Score.InstrumentName.padding = 2
}
}
%%%%%%%% END %%%%%%%%