Subject: Description erronée de la commande book

From: Ben <[email-masked]>
Date: Sat, 11 Mar 2023 09:29:06 +0100

Bonjour, 

Je profite de la liste pour relever une incongruité de la commande \book qui m'a toujours laissé perplexe: 

Dans la doc, il est dit que lorsqu'on ne met pas de commande \book, celle-ci est implicite au fichier. 

Or, cela n'est pas correct, car le code suivant fonctionne, et c'est heureux, car sinon je serais très embêté:

\version "2.25.1"

\bookpart{ \markup "coucou" }

test = "forêt"

\bookpart{ \markup "hibou" }

Mais si j'indique explicitement le book, cela ne fonctionne plus:

\version "2.25.1"

\book {
	\bookpart{ \markup "coucou" }

	test = "forêt"

	\bookpart{ \markup "hibou" }
}

Ce qui fait qu'au lieu de pouvoir compiler facilement plusieurs book en lilypond avec cette instruction: 

\version "2.25.1"

\book{ 
	\bookOutputName "Violon 1"
	\include "ViolonI.ly <http://partition1.ly/>" 
}

\book{ 
	\bookOutputName "Violon 2"
	\include "ViolonII.ly <http://partition2.ly/>" 
}

Je dois passer par des shell scripts, ce qui rajoute toute une couche de complexité. 

Cette différence de comportement entre le \book implicite et le \book explicite n'est pas cohérente, elle devrait au moins être précisée dans la doc, ou mieux encore, le \book explicite devrait simplement fonctionner comme le \book implicite. 

Au plaisir, 

Ben

---

From: Jean Abou Samra <[email-masked]>
Date: Sat, 11 Mar 2023 13:22:20 +0100

Le samedi 11 mars 2023 à 09:29 +0100, Ben a écrit :

> 	\include "[ViolonI.ly](http://Partition1.ly)" 
> }
> 
> \book{ 
> 	\include "[ViolonII.ly](http://Partition2.ly)" 
> }
> 

Il y a plusieurs sections de la documentation qui parlent de structure des fichiers .ly, laquelle induit en erreur selon vous ?

Je peux comprendre votre point de vue... mais le mien est complètement différent, je n'aurais même pas pensé à mettre tout le contenu entier du fichier dans `\book { ... }`. Il y a bel et bien création d'un book implicite, simplement c'est à un niveau plus « conceptuel » que le niveau purement syntaxique. `\book` est une commande qui crée un book à partir des éléments qu'il y a à l'intérieur : expressions musicales, markups, bookparts, scores, blocs paper. Et s'il n'y a aucun `\book`, LilyPond en crée un à partir des « éléments qu'il y a à l'intérieur du fichier » : expressions musicales, markups, bookparts, scores (les blocs `\paper`, c'est une autre histoire). Remarquez que les affectations ne sont pas la seule chose qui devrait marcher à l'intérieur d'un `\book` pour faire fonctionner votre code `\book { \include "ViolonI.ly" }` : il y aurait aussi notamment les blocs `\layout` (certes, c'est assez dommage que `\layout` ne puisse pas se mettre dans un `\book`, il y a eu encore récemment des discussions à ce sujet et j'ai bon espoir que ça change).

Est-ce que vous ne pouvez pas vous en sortir en mettant le `\book` autour de la musique à l'intérieur des fichiers ViolonI.ly et ViolonII.ly ?

Cordialement,

Jean

---

From: Ben <[email-masked]>
Date: Sat, 11 Mar 2023 14:32:03 +0100

Bonjour Jean, 

Merci pour votre réponse. 

Je faisais allusion à ce texte:

"Lorsqu’un fichier ne comprend qu’un bloc \score, celui-ci est implicitement inclus dans un bloc \book. Le bloc \book d’un fichier source permet la production d’au moins un fichier dont le nom sera, par d ́efaut, d ́eduit du fichier source : le traitement de fandangopourelephants.ly produira donc fandangopourelephants.pdf. " 

et combiné au nom "\bookpart", qui laisserait entendre qu'un \book peut avoir plusieurs \bookpart, alors qu'en fait le \bookpart est au final indépendant du \book. 

Une possibilité serait de mettre tout le \bookpart dans une variable et d'avoir cela: 

\book
{
	\bookpart { \ViolonIMouvementI }
	\bookpart { \ViolonIMouvementII }
	\bookpart { \ViolonIMouvementIII }
}

Sauf que j'ai des "book conceptuels" qui contiennent facilement une centaine de \bookpart, les bookpart se partagent les mêmes structures de header / paper / layout, etc, d'où la grande utilité de ne changer que quelques variables entre chaque bookpart au lieu de réécrire cent fois la même page de code.

Pour ces gros books conceptuels, j'ai pris le temps de développer des scripts shell et python, qui utilisent même une compilation optionnelle via un \include. 

Pour le quatuor, j'ai trouvé plus rapide et plus pratique de tout mettre dans un seul fichier pdf, cela fait juste un peu bizarre d'avoir des parties qui commencent aux pages 28, 38, etc. (vu qu'on ne peut pas non plus facilement redéfinir les numéros de page), mais cela permet aussi une table des matières sur le tout, c'est donc un compromis que je trouve acceptable.

Au plaisir, 

Ben

> Le 11 mars 2023 à 13:22, Jean Abou Samra <[email-masked]> a écrit :
> 
>> \book { \bookpart{ \markup "coucou" }
>> 
>> test = "forêt"
>> 
>> \bookpart{ \markup "hibou" } }
>> 
>> \book{  \bookOutputName "Violon 1" \include "ViolonI.ly <http://partition1.ly/>"  }
>> 
>> \book{  \bookOutputName "Violon 2" \include "ViolonII.ly <http://partition2.ly/>"  }
>> 
> Je peux comprendre votre point de vue... mais le mien est complètement différent, je n'aurais même pas pensé à mettre tout le contenu entier du fichier dans \book { ... }. Il y a bel et bien création d'un book implicite, simplement c'est à un niveau plus « conceptuel » que le niveau purement syntaxique. \book est une commande qui crée un book à partir des éléments qu'il y a à l'intérieur : expressions musicales, markups, bookparts, scores, blocs paper. Et s'il n'y a aucun \book, LilyPond en crée un à partir des « éléments qu'il y a à l'intérieur du fichier » : expressions musicales, markups, bookparts, scores (les blocs \paper, c'est une autre histoire). Remarquez que les affectations ne sont pas la seule chose qui devrait marcher à l'intérieur d'un \book pour faire fonctionner votre code \book { \include "ViolonI.ly" } : il y aurait aussi notamment les blocs \layout (certes, c'est assez dommage que \layout ne puisse pas se mettre dans un \book, il y a eu encore récemment des discussions à ce sujet et j'ai bon espoir que ça change).
> 
> Est-ce que vous ne pouvez pas vous en sortir en mettant le \book autour de la musique à l'intérieur des fichiers ViolonI.ly et ViolonII.ly ?
> 
> Cordialement,
> 
> Jean
>

---

From: Jean Abou Samra <[email-masked]>
Date: Sun, 12 Mar 2023 00:00:11 +0100

Le 11 mars 2023 à 14:32, Ben <[email-masked]> a écrit :

Bonjour Jean,

Désolé d’être contrariant, mais je ne vois pas le problème dans ce paragraphe. Le code

variable = { c' }

\score { { \variable \variable } }

est bien (sauf dans certains contextes particuliers comme à l’intérieur de lilypond-book) équivalent à

variable = { c' }

\book { \score { { \variable \variable } } }

Ce n’est juste pas équivalent à

\book {

variable = { c' }

\score { { \variable \variable } }

}

Je ne comprends pas ce que vous voulez dire, qu’entendez-vous par « indépendant du \book » ?

Un \book peut absolument avoir plusieurs \bookpart, je ne saisis pas la raison pour laquelle vous pensez le contraire.

\book

{

}

Oui, tout à fait.

Je ne comprends pas la contradiction avec le code ci-dessus. Je pense qu’il me manque trop de contexte sur votre travail. Pourriez-vous détailler un peu comment vous vous y prenez ou donner un exemple de code ?

Par « tout mettre dans un seul fichier PDF », est-ce que vous voulez dire « faire un \book » ou bien « combiner plusieurs fichiers PDF générés par LilyPond en un seul fichier à l’aide d’un outil externe » ?

Pour les numéros de pages, connaissez-vous les variables \paper first-page-number et bookpart-level-page-numbering ?

---

From: Ben <[email-masked]>
Date: Sun, 12 Mar 2023 21:02:06 +0100

> Le 12 mars 2023 à 00:00, Jean Abou Samra <[email-masked]> a écrit :
> 
> 
> 
>> "Lorsqu’un fichier ne comprend qu’un bloc \score, celui-ci est implicitement inclus dans un bloc \book. Le bloc \book d’un fichier source permet la production d’au moins un fichier dont le nom sera, par d ́efaut, d ́eduit du fichier source : le traitement de fandangopourelephants.ly <http://fandangopourelephants.ly/> produira donc fandangopourelephants.pdf. " 
>> 
> 
> 

Dans votre exemple, vous avez raison, mais si je prends cet autre exemple, cela rend la proposition erronée: 

\version "2.25.1"

\bookpart { \markup "" }

var = "coucou"

\bookpart { \score { \relative c { c d e } } }

Ici, je n'ai bien qu'un seul bloc \score, mais dès lors que j'aimerais rendre le \book explicite, cela va retourner soit une erreur, soit un résultat différent. 

> Un \book peut absolument avoir plusieurs \bookpart, je ne saisis pas la raison pour laquelle vous pensez le contraire.

Dans l'exemple précédent les \bookpart n'appartiennent en réalité à aucun \book, puisque je ne peux mettre l'instruction \book sans changer le résultat. 

> Je ne comprends pas la contradiction avec le code ci-dessus. Je pense qu’il me manque trop de contexte sur votre travail. Pourriez-vous détailler un peu comment vous vous y prenez ou donner un exem…

Je vais essayer: 

*) Soit 3 chants, Chant1.ly <http://fichier1.ly/>, Chant2.ly <http://fichier2.ly/>, Chant3.ly <http://fichier3.ly/>, etc. avec tous la même structure:

Chant1.ly <http://chant1.ly/>
\version "2.25.1"
Deroulement = << \new Staff << \relative c { c d e } >> >>
\include "Modele.ily"

*) Soit le fichier Modele.ily avec la structure suivante:

Modele.ily
\bookpart { \score { \Deroulement } }

*) Je peux donc travailler chaque chant de manière indépendante et si je veux un recueil de tous les chants, il suffit de faire cela:

Recueil.ly <http://recueil.ly/>
\version "2.25.1"
\include "chant1.ly <http://chant1.ly/>"
\include "chant2.ly <http://chant1.ly/>"
\include "chant3.ly <http://chant1.ly/>"

=> grâce au \bookpart, chaque chant s'intègre directement au recueil. 

Mais là de nouveau, l'instruction \book ne peut être placée nulle part, alors que de facto, Recueil.ly <http://recueil.ly/> est un book. 

> Par « tout mettre dans un seul fichier PDF », est-ce que vous voulez dire « faire un \book » ou bien « combiner plusieurs fichiers PDF générés par LilyPond en un seul fichier à l’aide d’un outil ex…

Je voulais dire "faire un \book". 

> Pour les numéros de pages, connaissez-vous les variables \paper first-page-number et bookpart-level-page-numbering ?

Ah merci, je ne connaissais pas la deuxième et c'est vrai qu'elle me permettrait d'y arriver, mais de manière assez compliquée:

Car un carnet peut comporter jusqu'à 5 \bookpart, cela veut dire que je ne peux pas juste définir le premier à 1, il faut que je calcule la page de départ pour chaque bookpart de chaque carnet, donc une vingtaine de chiffres à écrire en dur, ce n'est pas très élégant, mais faisable. 

Au plaisir, 

Ben

---

From: Jean Abou Samra <[email-masked]>
Date: Sun, 12 Mar 2023 21:56:09 +0100

> Ici, je n'ai bien qu'un seul bloc \score, mais dès lors que j'aimerais rendre le \book explicite, cela va retourner soit une erreur, soit un résultat différent. 

Oui, c'est vrai… Pour moi, « ne contient qu'un bloc \score » se lisait plutôt « est constitué d'un simple bloc `\score` (donc pas de `\bookpart`).

> Dans l'exemple précédent les \bookpart n'appartiennent en réalité à aucun \book, puisque je ne peux mettre l'instruction \book sans changer le résultat. 

Si, je vous assure, le book existe bel et bien !

Prenons une analogie, par exemple en Python, puisque vous dites que vous écrivez des scripts dans ce langage. Imaginons une seconde, de manière fantaisiste, que la syntaxe de LilyPond soit celle de Python. Les choses (de manière simplifiée) se passent comme s'il y avait le code suivant inséré automatiquement par LilyPond :

```
implicit_book = Book()
explicit_books = []

def add_bookpart(bookpart: Bookpart) -> None:
    implicit_book.append(bookpart)

def add_book(book: Book) -> None:
    explicit_books.append(book)
    
def all_books() -> list[Book]:
    if implicit_book:
        explicit_books.append(implicit_book)
    return explicit_books
```

et que vous aviez donc les deux syntaxes suivantes à votre disposition :

```
add_bookpart(Bookpart(...))
...
add_bookpart(Bookpart(...))
```

ou

```
add_book(Book(Bookpart(...), Bookpart(...)))
```

Vous pouvez alors faire

```
add_bookpart(Bookpart(Markup("")))
var = Music(relative(c, [c, d, e]))
add_bookpart(Bookpart(Score(Sequential(var, var))))
```

mais vous ne pouvez pas faire

```
add_book(Book(
  Bookpart(Markup("")),
  var = Music(relative(c, [c, d, e])) # ??
  Bookpart(Score(Sequential(var, var)))
))
```

car une affectation est une instruction, qui ne peut pas se mettre à l'intérieur d'une expression. Par contre, vous pouvez faire

```
var = Music(relative(c, [c, d, e]))
add_book(Book(Bookpart(Markup("")), Bookpart(Score(Sequential(var, var)))))
```

ou bien encore

```
var = Music(relative(c, [c, d, e]))
second_bookpart = Bookpart(Score(Sequential(var, var)))
add_book(Book(Bookpart(Markup("")), second_bookpart))
```

Avec LilyPond, la syntaxe est évidemment très différente, mais le principe est exactement le même. Le `\book` autour de deux `\bookpart` existe, implicitement (c'est le `implicit_book`). Vous pouvez aussi créer un `\book` de manière explicite. Si vous ne pouvez pas mettre d'affectations à l'intérieur du `\book`, c'est juste pour une question de syntaxe, cela mélange les expressions et les instructions.

> Je vais essayer: 
> 
> *) Soit 3 chants, Chant[1.ly](http://fichier1.ly), Chant[2.ly](http://fichier2.ly), Chant[3.ly](http://fichier3.ly), etc. avec tous la même structure:
> 
> C[hant1.ly](http://chant1.ly)  
> \version "2.25.1"  
> R[ecueil.ly](http://recueil.ly)  
> \version "2.25.1"  
> \include "[chant1.ly](http://chant1.ly)"  
> \include "[chant2.ly](http://chant1.ly)"  
> \include "[chant3.ly](http://chant1.ly)"
> 
> Mais là de nouveau, l'instruction \book ne peut être placée nulle part, alors que de facto, [Recueil.ly](http://Recueil.ly) est un book. 

Effectivement, c'est plus clair pour moi, merci. À mon avis, plutôt qu'un `\include "modèle.ily"` qui ajoute un `\bookpart`, il vaut mieux faire une fonction qui prend les paramètres que vous voulez. Exemple :

```
% Modele.ily
myBookpart =
#(define-scheme-function (deroulement) (ly:music?)
   #{ \bookpart { \score { \deroulement } } #})

% chant1.ly
% \include "Modele.ily"
deroulement = { c' }
bookpartI = \myBookpart \deroulement

% chant2.ly
% \include "Modele.ily"
deroulement = { d' }
bookpartII = \myBookpart \deroulement

% Recueil.ly
% \include "chant1.ly"
% \include "chant2.ly"
\book { \bookpart { \bookpartI } \bookpart { \bookpartII } }
```

Voire, si vous voulez vraiment conserver l'approche à base de variables plutôt que de fonctions :

```
% Modele.ily
% bookparts.\nomBookpart = \bookpart { \score { \deroulement } }

% chant1.ly
deroulement = { c' }
nomBookpart = bookpartI
% \include "Modele.ily"
bookparts.\nomBookpart = \bookpart { \score { \deroulement } }

% chant2.ly
deroulement = { d' }
nomBookpart = bookpartII
% \include "Modele.ily"
bookparts.\nomBookpart = \bookpart { \score { \deroulement } }

% Recueil.ly
% \include "chant1.ly"
% \include "chant2.ly"
\book {
  \bookpart { $(assq-ref bookparts 'bookpartI) }
  \bookpart { $(assq-ref bookparts 'bookpartII) }
}
```

Cordialement,

Jean

---

From: Jean Abou Samra <[email-masked]>
Date: Mon, 13 Mar 2023 01:18:25 +0100

Pour info : je trouve amusant qu'exactement la même question ait été posée aujourd'hui sur la liste anglophone, avec un débat assez similaire (la discussion peut se trouver dans les archives : [https://lists.gnu.org/archive/html/lilypond-user/2023-03/msg00158.html](https://lists.gnu.org/archive/html/lilypond-user/2023-03/msg00158.html)).

---

From: Ben <[email-masked]>
Date: Mon, 13 Mar 2023 02:40:45 +0100

*) Merci pour les explications, je comprends mieux la problématique du book. 

*) Pour l'exemple donné, une autre alternative plus basique serait:

chant1.ly <http://chant1.ly/>
deroulement = { a }
\include "modele.ly"
bookpartI = bookpart

modele.ly
bookpart = \bookpart { \score { \deroulement } }

Mais le résultat final est toujours le même: on se retrouve à devoir gérer un \include et une variable différente par include dans le fichier recueil.ly <http://recueil.ly/>. Cela peut aller quand il n'y a que trois chants, mais quand il y en a 100, je pense que mon système actuel est finalement encore le plus simple: un seul \include, pas de \book explicite et une compilation conditionnelle via des scripts externes.

*) Enfin, j'ai essayé avec bookpart-level-page-numbering, la table-of-contents s'affiche correctement, mais le clic sur les item devient inutilisable, car il se référence sur les numéros de page du pdf, au lieu de se référencer sur la position réelle du tocitem, n'est-ce pas un petit bug? 

Au plaisir, 

Ben

> Le 12 mars 2023 à 21:56, Jean Abou Samra <[email-masked]> a écrit :
> 
> Oui, c'est vrai… Pour moi, « ne contient qu'un bloc \score » se lisait plutôt « est constitué d'un simple bloc \score (donc pas de \bookpart).
> 
> Avec LilyPond, la syntaxe est évidemment très différente, mais le principe est exactement le même. Le \book autour de deux \bookpart existe, implicitement (c'est le implicit_book). Vous pouvez aussi créer un \book de manière explicite. Si vous ne pouvez pas mettre d'affectations à l'intérieur du \book, c'est juste pour une question de syntaxe, cela mélange les expressions et les instructions.
> 

> Effectivement, c'est plus clair pour moi, merci. À mon avis, plutôt qu'un \include "modèle.ily" qui ajoute un \bookpart, il vaut mieux faire une fonction qui prend les paramètres que vous voulez. Exemple :
> 
> % Modele.ily
> myBookpart =

---

From: Jean Abou Samra <[email-masked]>
Date: Mon, 13 Mar 2023 08:08:55 +0100

> Le 13 mars 2023 à 02:40, Ben <[email-masked]> a écrit :
> 
> Cela peut aller quand il n'y a que trois chants, mais quand il y en a 100, je pense que mon système actuel est finalement encore le plus simple: un seul \include, pas de \book explicite et une compilation conditionnelle via des scripts externes.

Libre à vous ; c’est une approche valable, ce n’est juste pas celle que je recommanderais personnellement.

> *) Enfin, j'ai essayé avec bookpart-level-page-numbering, la table-of-contents s'affiche correctement, mais le clic sur les item devient inutilisable, car il se référence sur les numéros de page du…

Oui, celui-là, je l’ai remarqué il y a quelques temps : https://gitlab.com/lilypond/lilypond/-/issues/6419

---

From: Ben <[email-masked]>
Date: Mon, 13 Mar 2023 10:17:52 +0100

> Le 13 mars 2023 à 08:08, Jean Abou Samra <[email-masked]> a écrit :
> 
> 
> 

Je comprends. Comme mes scripts ne font pas que compiler, mais génèrent également des index et différents contrôles et nettoyages, je vais continuer de bosser avec, sachant que comme l'approche est valable, elle ne devrait pas être cassée par une mise-à-jour future…

Mais après, je me permets quand même de revenir à la charge, car ce script fonctionne sans problème: 

\version "2.25.1"

var = "hibou"

foret = #(define-void-function ()()
           (
             set! var "coucou" 
             ))

\book 
{
  \foret 
  \relative c' { c_\markup \var  }
}

Du coup, dès lors que l'on peut quand même se permettre quelques libertés syntaxiques, pourquoi ne pas développer une nouvelle fonction \getbook qui permettrait de récupérer dans un \book le \book implicite d'un fichier:

\book { \getbook "fichier.ly" }

Cela permettrait ensuite de le combiner avec des expressions de formatages et de sorties et s'éviter moultes palabres dans les langues de Molière et Shakespeare…

> Oui, celui-là, je l’ai remarqué il y a quelques temps : https://gitlab.com/lilypond/lilypond/-/issues/6419 <https://gitlab.com/lilypond/lilypond/-/issues/6419>
> 

Très bien!

Je me suis demandé si on pouvait le contourner avec, au lieu de changer le numéro de page, le masquer et le remplacer par un numéro d'affichage pur généré via \should-print-page-number, mais je ne vois pas comment faire, et j'ai le sentiment que cela ne fonctionnerait pas. 
 Au plaisir, 

Ben

---

From: Ben <[email-masked]>
Date: Mon, 13 Mar 2023 11:46:18 +0100

En réalité, même le getbook décris précédemment ne solutionnerait pas ma situation, l'idéal pour moi serait plutôt une instruction \new book qui tolèrerait variables et include:

recueil.ly

recueil = \new book {
	\PremierePage
	\PageBlanche
	\TableDesMatieres

	reference = "1"  \include "chant1.ly <http://fichier.ly/>"
	reference = "2"  \include "chant2.ly <http://fichier.ly/>"
	reference = "3"  \include "chant3.ly <http://fichier.ly/>"
	…
	reference = "100"  \include "chant100.ly <http://fichier.ly/>"

	\Index
	\getIndex \CheminRecueils
}

TypeRecueil = "Carnet"
\book {
	\bookOutputPath \Chemin
	\bookOutputSuffix \TypeRecueil
	\recueil
}

TypeRecueil = "Tablette"
\book {
	\bookOutputPath \Chemin
	\bookOutputSuffix \TypeRecueil
	\recueil
}

Mais comme j'ai très certainement une utilisation assez spécifique et que je suis déjà arrivé à ce résultat, je ne vais pas vous déranger plus longtemps avec cela. 

Au plaisir, 

Ben

> Le 13 mars 2023 à 10:17, Ben <[email-masked]> a écrit :
> 
> 
> 
>> Le 13 mars 2023 à 08:08, Jean Abou Samra <[email-masked] <mailto:[email-masked]>> a écrit :
>> 
>> 
>> 
>>> Le 13 mars 2023 à 02:40, Ben <[email-masked] <mailto:[email-masked]>> a écrit :
>>> 
> \book { \getbook "fichier.ly <http://fichier.ly/>" }
>