Displaying typesetting information at compile time

2022-03-20 Thread Richard Shann
I wonder if someone could suggest how to get LilyPond to emit various
bits of information about the score it is typesetting. Specifically can
it be persuaded to display the number of pages in the output PDF and
the total number of systems?
The idea would be to guide the user as to suitable values for

\paper {
  system-count = xx
  page-count = yy
}

without having to count up the number of systems (pages is not really a
problem of course).

Richard Shann






Re: Displaying typesetting information at compile time

2022-03-20 Thread Jean Abou Samra




Le 20/03/2022 à 17:43, Richard Shann a écrit :

I wonder if someone could suggest how to get LilyPond to emit various
bits of information about the score it is typesetting. Specifically can
it be persuaded to display the number of pages in the output PDF and
the total number of systems?
The idea would be to guide the user as to suitable values for

\paper {
   system-count = xx
   page-count = yy
}

without having to count up the number of systems (pages is not really a
problem of course).

Richard Shann


Not sure if there's a more elegant way, but you could try

\version "2.22.2"

markWithPageInfo =
  %% Must not get called before line breaking
  \tweak X-extent #'(0 . 0)
  \tweak Y-extent #'(0 . 0)
  \tweak horizontal-skylines
#(ly:make-unpure-pure-container 
ly:grob::simple-horizontal-skylines-from-extents)
  \tweak vertical-skylines
#(ly:make-unpure-pure-container 
ly:grob::simple-vertical-skylines-from-extents)
  \tweak stencil
#(lambda (grob)
   (let* ((sys (ly:grob-system grob))
  ;; No broken pieces for systems ...
  (alignment (ly:grob-object sys 'vertical-alignment))
  (all-alignments (ly:spanner-broken-into (ly:grob-original 
alignment)))
  (all-systems (map ly:grob-system all-alignments))
  (n-systems (length all-systems))
  (all-pages (map (lambda (s) (ly:grob-property s 'page-number))
  all-systems))
  (n-pages (1+ (- (apply max all-pages)
  (apply min all-pages
  (layout (ly:grob-layout grob))
  (defs (append `((n-systems . ,(number->string n-systems))
  (n-pages . ,(number->string n-pages)))
(ly:output-def-lookup layout 'text-font-defaults)))
  (props (ly:grob-alist-chain grob defs))
  (text (ly:grob-property grob 'text)))
 (interpret-markup layout props text)))
  \mark \etc

{
  \markWithPageInfo \markup { Have \fromproperty #'n-systems systems on 
\fromproperty #'n-pages pages }
  \repeat unfold 20 { 1 1 \break }
}
   


Jean





Re: Displaying typesetting information at compile time

2022-03-20 Thread Richard Shann
On Sun, 2022-03-20 at 18:43 +0100, Jean Abou Samra wrote:
> 
> \version "2.22.2"
> 
> markWithPageInfo =
>    %% Must not get called before line breaking
>    \tweak X-extent #'(0 . 0)
>    \tweak Y-extent #'(0 . 0)
>    \tweak horizontal-skylines
>  #(ly:make-unpure-pure-container ly:grob::simple-horizontal-
> skylines-from-extents)
>    \tweak vertical-skylines
>  #(ly:make-unpure-pure-container ly:grob::simple-vertical-
> skylines-from-extents)
>    \tweak stencil
>  #(lambda (grob)
>     (let* ((sys (ly:grob-system grob))
>    ;; No broken pieces for systems ...
>    (alignment (ly:grob-object sys 'vertical-alignment))
>    (all-alignments (ly:spanner-broken-into (ly:grob-
> original alignment)))
>    (all-systems (map ly:grob-system all-alignments))
>    (n-systems (length all-systems))
>    (all-pages (map (lambda (s) (ly:grob-property s 'page-
> number))
>    all-systems))
>    (n-pages (1+ (- (apply max all-pages)
>    (apply min all-pages
>    (layout (ly:grob-layout grob))
>    (defs (append `((n-systems . ,(number->string n-
> systems))
>    (n-pages . ,(number->string n-pages)))
>  (ly:output-def-lookup layout 'text-font-
> defaults)))
>    (props (ly:grob-alist-chain grob defs))
>    (text (ly:grob-property grob 'text)))
>   (interpret-markup layout props text)))
>    \mark \etc
> 
> {
>    \markWithPageInfo \markup { Have \fromproperty #'n-systems systems
> on \fromproperty #'n-pages pages }
>    \repeat unfold 20 { 1 1 \break }
> }

Wow! That goes beyond what I had in mind - it actually outputs the
information within the typeset (I guess the stuff with skylining might
be to avoid the typesetting of this information affecting the number of
pages/systems??). What I had in mind was just some Scheme (display ...)
inserted in the way Valentin (*) did with this:

\override Score.SpacingSpanner.common-shortest-duration =
#(grob-transformer 'common-shortest-duration
   (lambda (grob orig) (display orig) (newline) orig))

So that the information can be used to guide selection of tweaks.

Richard

(*) in the "Re: Wildly different horizontal spacing in two similar
scores." thread







Re: Displaying typesetting information at compile time

2022-03-20 Thread Jean Abou Samra




Le 20/03/2022 à 19:09, Richard Shann a écrit :

On Sun, 2022-03-20 at 18:43 +0100, Jean Abou Samra wrote:

\version "2.22.2"

markWithPageInfo =
    %% Must not get called before line breaking
    \tweak X-extent #'(0 . 0)
    \tweak Y-extent #'(0 . 0)
    \tweak horizontal-skylines
  #(ly:make-unpure-pure-container ly:grob::simple-horizontal-
skylines-from-extents)
    \tweak vertical-skylines
  #(ly:make-unpure-pure-container ly:grob::simple-vertical-
skylines-from-extents)
    \tweak stencil
  #(lambda (grob)
     (let* ((sys (ly:grob-system grob))
    ;; No broken pieces for systems ...
    (alignment (ly:grob-object sys 'vertical-alignment))
    (all-alignments (ly:spanner-broken-into (ly:grob-
original alignment)))
    (all-systems (map ly:grob-system all-alignments))
    (n-systems (length all-systems))
    (all-pages (map (lambda (s) (ly:grob-property s 'page-
number))
    all-systems))
    (n-pages (1+ (- (apply max all-pages)
    (apply min all-pages
    (layout (ly:grob-layout grob))
    (defs (append `((n-systems . ,(number->string n-
systems))
    (n-pages . ,(number->string n-pages)))
  (ly:output-def-lookup layout 'text-font-
defaults)))
    (props (ly:grob-alist-chain grob defs))
    (text (ly:grob-property grob 'text)))
   (interpret-markup layout props text)))
    \mark \etc

{
    \markWithPageInfo \markup { Have \fromproperty #'n-systems systems
on \fromproperty #'n-pages pages }
    \repeat unfold 20 { 1 1 \break }
}

Wow! That goes beyond what I had in mind - it actually outputs the
information within the typeset (I guess the stuff with skylining might
be to avoid the typesetting of this information affecting the number of
pages/systems??).




Sort of, yes. Normally, the RehearsalMark is drawn before line breaking 
is done, and its width and height are accounted for during page breaking 
and page spacing. At that time, there is obviously no number of pages or 
systems available. So I'm giving it predetermined extents and skylines, 
which are used for page breaking and page spacing purposes, only after 
which the RehearsalMark's stencil is computed. The drawback is that it 
could collide with something on top of it.


However, there was a flaw in that code. When you have several scores in 
a bookpart, page-count and system-count override the total numbers for 
the whole bookpart, but I was counting them per score. Here is a fixed 
version:


\version "2.22.2"

\paper {
  page-post-process =
    #(lambda (paper pages)
   (let ((n-systems 0)
 (page-min #f)
 (page-max #f))
 (for-each
  (lambda (page)
    (for-each
 (lambda (line)
   (let ((sys (ly:prob-property line 'system-grob)))
 (if (ly:grob? sys)
 (let ((sys-page (ly:grob-property sys 'page-number)))
  (set! n-systems (1+ n-systems))
  (set! page-min (if page-min
 (min page-min sys-page)
 sys-page))
  (set! page-max (if page-max
 (max page-max sys-page)
 sys-page))
 (ly:prob-property page 'lines)))
  pages)
 (ly:output-def-set-variable! paper 'n-systems n-systems)
 (ly:output-def-set-variable! paper 'n-pages (1+ (- page-max 
page-min)

}

#(define-markup-command (page-info layout props arg) (markup?)
   (ly:make-stencil
    `(delay-stencil-evaluation
  ,(delay
    (let* ((n-systems (ly:output-def-lookup layout 'n-systems))
   (n-pages (ly:output-def-lookup layout 'n-pages)))
    (ly:stencil-expr
 (interpret-markup
  layout
  (cons `((n-systems . ,(number->string n-systems))
  (n-pages . ,(number->string n-pages)))
    props)
  arg)
    '(0 . 0)
    '(0 . 0)))

\header {
  subsubtitle = \markup \page-info \line {
    Have \fromproperty #'n-systems systems
    on \fromproperty #'n-pages pages
  }
}

\book {
  \bookpart {
    \repeat unfold 10 { 1 1 \break }
    \repeat unfold 10 { 1 1 \break }
  }
  \bookpart {
    \repeat unfold 20 { 1 1 \break }
    \repeat unfold 20 { 1 1 \break }
  }
}


Jean



Re: Displaying typesetting information at compile time

2022-03-21 Thread Jean Abou Samra




Le 21/03/2022 à 17:24, Richard Shann a écrit :

On Sun, 2022-03-20 at 20:09 +0100, Jean Abou Samra wrote:


Le 20/03/2022 à 19:09, Richard Shann a écrit :

On Sun, 2022-03-20 at 18:43 +0100, Jean Abou Samra wrote:

\version "2.22.2"

markWithPageInfo =
     %% Must not get called before line breaking
     \tweak X-extent #'(0 . 0)
     \tweak Y-extent #'(0 . 0)
     \tweak horizontal-skylines
   #(ly:make-unpure-pure-container ly:grob::simple-horizontal-
skylines-from-extents)
     \tweak vertical-skylines
   #(ly:make-unpure-pure-container ly:grob::simple-vertical-
skylines-from-extents)
     \tweak stencil
   #(lambda (grob)
  (let* ((sys (ly:grob-system grob))
     ;; No broken pieces for systems ...
     (alignment (ly:grob-object sys 'vertical-
alignment))
     (all-alignments (ly:spanner-broken-into (ly:grob-
original alignment)))
     (all-systems (map ly:grob-system all-alignments))
     (n-systems (length all-systems))
     (all-pages (map (lambda (s) (ly:grob-property s
'page-
number))
     all-systems))
     (n-pages (1+ (- (apply max all-pages)
     (apply min all-pages
     (layout (ly:grob-layout grob))
     (defs (append `((n-systems . ,(number->string n-
systems))
     (n-pages . ,(number->string n-
pages)))
   (ly:output-def-lookup layout 'text-
font-
defaults)))
     (props (ly:grob-alist-chain grob defs))
     (text (ly:grob-property grob 'text)))
    (interpret-markup layout props text)))
     \mark \etc

{
     \markWithPageInfo \markup { Have \fromproperty #'n-systems
systems
on \fromproperty #'n-pages pages }
     \repeat unfold 20 { 1 1 \break }
}

Wow! That goes beyond what I had in mind - it actually outputs the
information within the typeset (I guess the stuff with skylining
might
be to avoid the typesetting of this information affecting the
number of
pages/systems??).



Sort of, yes. Normally, the RehearsalMark is drawn before line
breaking
is done, and its width and height are accounted for during page
breaking
and page spacing. At that time, there is obviously no number of pages
or
systems available. So I'm giving it predetermined extents and
skylines,
which are used for page breaking and page spacing purposes, only
after
which the RehearsalMark's stencil is computed. The drawback is that
it
could collide with something on top of it.

However, there was a flaw in that code. When you have several scores
in
a bookpart, page-count and system-count override the total numbers
for
the whole bookpart, but I was counting them per score. Here is a
fixed
version:

\version "2.22.2"

\paper {
    page-post-process =
  #(lambda (paper pages)
     (let ((n-systems 0)
   (page-min #f)
   (page-max #f))
   (for-each
    (lambda (page)
  (for-each
   (lambda (line)
     (let ((sys (ly:prob-property line 'system-grob)))
   (if (ly:grob? sys)
   (let ((sys-page (ly:grob-property sys 'page-
number)))
    (set! n-systems (1+ n-systems))
    (set! page-min (if page-min
   (min page-min sys-page)
   sys-page))
    (set! page-max (if page-max
   (max page-max sys-page)
   sys-page))
   (ly:prob-property page 'lines)))
    pages)
   (ly:output-def-set-variable! paper 'n-systems n-systems)
   (ly:output-def-set-variable! paper 'n-pages (1+ (- page-max
page-min)
}

#(define-markup-command (page-info layout props arg) (markup?)
     (ly:make-stencil
  `(delay-stencil-evaluation
    ,(delay
  (let* ((n-systems (ly:output-def-lookup layout 'n-systems))
     (n-pages (ly:output-def-lookup layout 'n-pages)))
  (ly:stencil-expr
   (interpret-markup
    layout
    (cons `((n-systems . ,(number->string n-systems))
    (n-pages . ,(number->string n-pages)))
  props)
    arg)
  '(0 . 0)
  '(0 . 0)))

\header {
    subsubtitle = \markup \page-info \line {
  Have \fromproperty #'n-systems systems
  on \fromproperty #'n-pages pages
    }
}

\book {
    \bookpart {
  \repeat unfold 10 { 1 1 \break }
  \repeat unfold 10 { 1 1 \break }
    }
    \bookpart {
  \repeat unfold 20 { 1 1 \break }
  \repeat unfold 20 { 1 1 \break }
    }
}

Thanks again - I think I would prefer the information on the terminal
though so I modified your code to do that:

8><8><8><8><8><8><8><8><8><8><8

Re: Displaying typesetting information at compile time

2022-03-21 Thread Richard Shann
On Sun, 2022-03-20 at 20:09 +0100, Jean Abou Samra wrote:
> 
> 
> Le 20/03/2022 à 19:09, Richard Shann a écrit :
> > On Sun, 2022-03-20 at 18:43 +0100, Jean Abou Samra wrote:
> > > \version "2.22.2"
> > > 
> > > markWithPageInfo =
> > >     %% Must not get called before line breaking
> > >     \tweak X-extent #'(0 . 0)
> > >     \tweak Y-extent #'(0 . 0)
> > >     \tweak horizontal-skylines
> > >   #(ly:make-unpure-pure-container ly:grob::simple-horizontal-
> > > skylines-from-extents)
> > >     \tweak vertical-skylines
> > >   #(ly:make-unpure-pure-container ly:grob::simple-vertical-
> > > skylines-from-extents)
> > >     \tweak stencil
> > >   #(lambda (grob)
> > >  (let* ((sys (ly:grob-system grob))
> > >     ;; No broken pieces for systems ...
> > >     (alignment (ly:grob-object sys 'vertical-
> > > alignment))
> > >     (all-alignments (ly:spanner-broken-into (ly:grob-
> > > original alignment)))
> > >     (all-systems (map ly:grob-system all-alignments))
> > >     (n-systems (length all-systems))
> > >     (all-pages (map (lambda (s) (ly:grob-property s
> > > 'page-
> > > number))
> > >     all-systems))
> > >     (n-pages (1+ (- (apply max all-pages)
> > >     (apply min all-pages
> > >     (layout (ly:grob-layout grob))
> > >     (defs (append `((n-systems . ,(number->string n-
> > > systems))
> > >     (n-pages . ,(number->string n-
> > > pages)))
> > >   (ly:output-def-lookup layout 'text-
> > > font-
> > > defaults)))
> > >     (props (ly:grob-alist-chain grob defs))
> > >     (text (ly:grob-property grob 'text)))
> > >    (interpret-markup layout props text)))
> > >     \mark \etc
> > > 
> > > {
> > >     \markWithPageInfo \markup { Have \fromproperty #'n-systems
> > > systems
> > > on \fromproperty #'n-pages pages }
> > >     \repeat unfold 20 { 1 1 \break }
> > > }
> > Wow! That goes beyond what I had in mind - it actually outputs the
> > information within the typeset (I guess the stuff with skylining
> > might
> > be to avoid the typesetting of this information affecting the
> > number of
> > pages/systems??).
> 
> 
> 
> Sort of, yes. Normally, the RehearsalMark is drawn before line
> breaking 
> is done, and its width and height are accounted for during page
> breaking 
> and page spacing. At that time, there is obviously no number of pages
> or 
> systems available. So I'm giving it predetermined extents and
> skylines, 
> which are used for page breaking and page spacing purposes, only
> after 
> which the RehearsalMark's stencil is computed. The drawback is that
> it 
> could collide with something on top of it.
> 
> However, there was a flaw in that code. When you have several scores
> in 
> a bookpart, page-count and system-count override the total numbers
> for 
> the whole bookpart, but I was counting them per score. Here is a
> fixed 
> version:
> 
> \version "2.22.2"
> 
> \paper {
>    page-post-process =
>  #(lambda (paper pages)
>     (let ((n-systems 0)
>   (page-min #f)
>   (page-max #f))
>   (for-each
>    (lambda (page)
>  (for-each
>   (lambda (line)
>     (let ((sys (ly:prob-property line 'system-grob)))
>   (if (ly:grob? sys)
>   (let ((sys-page (ly:grob-property sys 'page-
> number)))
>    (set! n-systems (1+ n-systems))
>    (set! page-min (if page-min
>   (min page-min sys-page)
>   sys-page))
>    (set! page-max (if page-max
>   (max page-max sys-page)
>   sys-page))
>   (ly:prob-property page 'lines)))
>    pages)
>   (ly:output-def-set-variable! paper 'n-systems n-systems)
>   (ly:output-def-set-variable! paper 'n-pages (1+ (- page-max
> page-min)
> }
> 
> #(define-markup-command (page-info layout props arg) (markup?)
>     (ly:make-stencil
>  `(delay-stencil-evaluation
>    ,(delay
>  (let* ((n-systems (ly:output-def-lookup layout 'n-systems))
>     (n-pages (ly:output-def-lookup layout 'n-pages)))
>  (ly:stencil-expr
>   (interpret-markup
>    layout
>    (cons `((n-systems . ,(number->string n-systems))
>    (n-pages . ,(number->string n-pages)))
>  props)
>    arg)
>  '(0 . 0)
>  '(0 . 0)))
> 
> \header {
>    subsubtitle = \markup \page-info \line {
>  Have \fromproperty #'n-systems systems
>  on \fromproperty #'n-pages pages
>    }
> }
> 

Re: Displaying typesetting information at compile time

2022-03-22 Thread Richard Shann
On Mon, 2022-03-21 at 17:28 +0100, Jean Abou Samra wrote:
> 
> 
> Le 21/03/2022 à 17:24, Richard Shann a écrit :
> > On Sun, 2022-03-20 at 20:09 +0100, Jean Abou Samra wrote:
> > > 
> > [...] perhaps there is something altogether
> > simpler?
> 
> 
> 
> In that case, just output the info at the end of page-post-process
> instead
> of storing it and retrieving it later.
> 
> \version "2.22.2"
> 
> \paper {
>     page-post-process =
>   #(lambda (paper pages)
>  (let ((n-systems 0)
>    (page-min #f)
>    (page-max #f))
>    (for-each
>     (lambda (page)
>   (for-each
>    (lambda (line)
>  (let ((sys (ly:prob-property line 'system-grob)))
>    (if (ly:grob? sys)
>    (let ((sys-page (ly:grob-property sys 'page-
> number)))
>     (set! n-systems (1+ n-systems))
>     (set! page-min (if page-min
>    (min page-min sys-page)
>    sys-page))
>     (set! page-max (if page-max
>    (max page-max sys-page)
>    sys-page))
>    (ly:prob-property page 'lines)))
>     pages)
>    (ly:message "~a systems on ~a pages"
>    n-systems
>    (1+ (- page-max page-min)
> }
> 
> \repeat unfold 10 { 1 1 \break }
> \repeat unfold 13 { 1 1 \break }
> 
Perfect! Thanks, I should have thought to track down documentation for
page-post-process ...
Richard





Re: Displaying typesetting information at compile time

2022-03-22 Thread Jean Abou Samra

Le 22/03/2022 à 09:15, Richard Shann a écrit :

Perfect! Thanks, I should have thought to track down documentation for
page-post-process ...
Richard


Ahem, well, like with a number of Scheme interfaces, that documentation
is nonexistent.

Jean