LSR/1098

< LSR
Zur Navigation springen Zur Suche springen
Indenting individual systems
PD Der Inhalt dieser Seite wurde aus dem LilyPond Snippet Repository übernommen und steht unter folgender Lizenz: CC0.
See Public Domain Help Pages for more info.
PD

Beschreibung

LilyPond scores are indented rather like text paragraphs: all lines except the first are indented by the same amount (short-indent). This layout constraint is applied in advance and cannot be modified later e.g. on a line-by-line basis.

LilyPond users who need a differently indented line can arrange for that line to start a new score, as in LSR 966. 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.

This snippet demonstrates the pseudoIndent workaround which superimposes an additional line-wise indentation on the score's unmodified layout indentation. This approach avoids all those score change problems.

There are independent parameters for left and right indentations. It also comes with a freebie parameter for succinct instrument-name modding.

Caveats:

The indenting mechanism is based on an arcane misuse of LeftEdge and may therefore become temporarily or permanently broken through side-effects of developments in the Lilypond code base.
The code is not protected against multiple calls per system break
auto
%%%%%%%% HEADER %%%%%%%%
%
% this code was prompted by
% https://lists.gnu.org/archive/html/lilypond-user/2019-07/msg00139.html
% and offers a pseudoIndent hack suitable for general use

% keywords: 
% indent short-indent indentation system line 
% mid-score temporarily arbitrary individual single just only once
% coda margin
% mouse's tale acrostic mesostic spine

%%%%%%%% PSEUDOINDENT FUNCTIONS %%%%%%%%

% these two functions are for indenting individual systems
% - to left-indent a system, apply \pseudoIndent before the music continues
% - \pseudoIndents is similar, but lets you also indent on the right
% - both provide an option for changing that system's instrument names

% N.B. these functions 
% - assume application to non-ragged lines (generally the default)
% - include a manual \break to ensure application at line start 
% - misbehave if called more than once at the same line start

% the parameters of the (full) pseudoIndents function are:
% 1: name-tweaks
%      usually omitted; accepts replacement \markup for instrument names 
%      as an ordered list; starred elements leave their i-names unchanged.
% 2: left-indent 
%      additional left-indentation, in staff-space units; can be negative, 
%      but avoid a total indentation which implies (unsupported) stretching. 
% 3: right-indent 
%      amount of right-indentation, in staff-space units; can be negative. 
%      - not offered by the (reduced) pseudoIndent function


pseudoIndents = % inline alternative to a new \score, also with right-indent
#(define-music-function (parser location name-tweaks left-indent right-indent) 
  ((markup-list? '()) number? number?)
  (define (warn-stretched p1 p2) (ly:input-warning location (_
    " pseudoIndents ~s ~s is stretching staff; expect distorted layout") p1 p2))
  (let* ( 
    (narrowing (+ left-indent right-indent)) ; of staff implied by args
    
    (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))
        (capo? (moment<=? left-moment ZERO-MOMENT)) ; in first system of score
        (layout (ly:grob-layout staffsymbol-grob))
        (lw (ly:output-def-lookup layout 'line-width)) ; debugging info
        (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))
        ;; >=2.19.16's first system has old-stil already narrowed [2]
        ;; compensate for this (ie 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))
        (pristine? (<= 0 (car staffsymbol-x-ext) ss-t)) ; would expect half
        (leftmost-x (+ indent (if pristine? 0 narrowing))) 
        (narrowing_ (if pristine? narrowing 0)) ; uses 0 if already narrowed
        (old-width (+ (interval-length staffsymbol-x-ext) ss-t))
        (new-width (- old-width narrowing_))
        (new-rightmost-x (+ leftmost-x new-width)) ; and set! this immediately
        (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))
       ;(new-stil (stencil-with-color new-stil red)) ; for when debugging
        (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)
      )))
    
    (set-X-offset! (lambda (margin-grob) ; move grob across to line start 
      (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-text! (lambda (i-name-grob mkup) ; tweak both instrumentname texts   
      (if (and (markup? mkup) (not (string=? (markup->string mkup) "*")))
      (begin 
        (ly:grob-set-property! i-name-grob 'long-text mkup)
        (ly:grob-set-property! i-name-grob 'text mkup)
        )))) ; else retain existing text 
    
    (install-narrowing (lambda (leftedge-grob) ; on staves, + adapt left margin
      (define (grob-name x) (assq-ref (ly:grob-property x 'meta) 'name))
      (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))))
      (if (eq? leftedge-grob first-leftedge-grob) ; ignore other leftedges [1]        
       (begin 
         (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)
       ))))))
    
  (if (negative? narrowing) (warn-stretched left-indent right-indent)) 
  #{ % and continue anyway
    % ensure that these overrides are applied only at begin-of-line 
    \break % (but this does not exclude unsupported multiple application) 
    % 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 barnumber entering a stretched staff 
    \once \override Score.BarNumber.horizon-padding = #(max 1 (- 1 narrowing))
  #}))                                        

pseudoIndent = % for changing just left-indent 
#(define-music-function (parser location name-tweaks left-indent) 
  ((markup-list? '()) number?) 
  #{ 
    \pseudoIndents $name-tweaks $left-indent 0 
  #})

% [1] versions <2.19.1 can have end-of-line leftedges too  
%     - these were eliminated in issue 3761 
% [2] versions >=2.19.16: the first system behaves differently from the rest
%     - a side effect of issue 660 ?


%%%%%%%% LSR EXAMPLES %%%%%%%%

\paper {
  indent = 55
  short-indent = 40
  system-system-spacing.basic-distance = 10
  tagline = ##f
}

m = { f'4 f'4 f'4 f'4 } % one measure

showInfo = #(define-music-function (parser location info) (markup?) 
#{
  \once \override Score.LeftEdge.break-visibility = #begin-of-line-visible % [1]
  \once \override Score.LeftEdge.stencil = #(lambda (grob) 
  (grob-interpret-markup grob info)) 
#})

%%%%%%%% BASIC EXAMPLE %%%%%%%%

basic-info-line = \markup \translate #'(0 . -4) % trace short indentation
\with-color #blue  \draw-dashed-line #'(0 . -49) 

v-gap = \markup \vspace #2.25

basic-info-text = \markup \translate #'(-24 . 5)
\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 %%%%%%%%

demo-info-line = \markup\translate #'(85.3 . 16) % trace right margin
\with-color #blue  \draw-dashed-line #'(0 . -56) 

demo-info-text = \markup \translate #'(-24 . 13)
\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)"}}
}

mkCoda = \markup % cf LSR966 
\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 
  \pseudoIndents \markuplist { 1 2 3 } 11 -4 % display the i-name ordering
  s1*6 
  \pseudoIndent \markuplist { "" * \mkCoda } 55 % hide 1; leave 2; change 3
  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 %%%%%%%

Unterseiten