LuaTeX: marquez les limites mathématiques sans affecter la sortie de la composition (forme et espace)

Nov 21 2020

Comme le montrent les réponses à ma question précédente , les nœuds de frontière mathématiques ne sont pas un moyen fiable de marquer les limites mathématiques. Il existe deux solutions de contournement possibles qui peuvent être utilisées pour marquer les limites: 1) Ajouter des nœuds définis par l'utilisateur autour de la liste mathématique, 2) Définir et définir un attribut «math» pour les nœuds dans la liste mathématique. Un tel marquage de limite peut être pratique de plusieurs manières pour post-traiter la liste de nœuds après que TeX a terminé de couper les lignes: a) ajoutez des délimiteurs de type <beginmath> <endmath> tout en essayant d'extraire du texte b) coloration sélective du texte et des mathématiques, c) etc. a) peut également être utilisé à côté du "texte alternatif" ajouté à beginmath quelle valeur pour fournir une description alternative / textuelle de l'équation.

En ce qui concerne l'approche 1), le document LuaTeX déclare que "Le moteur LuaTEX passera simplement par-dessus de telles choses sans jamais regarder le contenu." Bien que certains articles suggèrent que ce qui peut affecter la microtypographie, le saut de ligne et la sortie de saut de page: lien vers un article qui montre le saut de page affecté et lien vers l' article qui montre la microtypographie affectée (ce qui peut également affecter le saut de ligne dans TeX).

Étant donné l'approche 2) nécessite une itération sur tout le contenu de la liste mathématique, elle serait plus lente par rapport à 1) si elle était appelée à l'aide du filtre mlist_to_hlist? (À moins que vous $<tex_equation>$ne puissiez probablement être redéfini en toute sécurité pour définir et annuler un attribut avant et après le $délimiteur, bien qu'il y ait plus de délimiteurs de ce type ...). La question est donc de savoir comment réussir à marquer la limite mathématique en utilisant l'approche 1) de manière à ce qu'elle n'affecte vraiment pas la microtypographie, le saut de ligne et le saut de page? Ou l'approche 2) est-elle la seule valeur sûre?

Voici mon premier essai pour les mathématiques en ligne, je recherche un avis d'expert et une extension pour les mathématiques d'affichage (environnements d'alignement, etc.).

Code:

% >>> lualatex mathmode.tex
\documentclass{article}
\usepackage[callback={}]{nodetree}

\begin{document}

\directlua{
local function mathboundary(h,d,p)
    local beginmath = node.new("whatsit","user_defined")
    beginmath.type = string.byte("s")
    beginmath.value = "beginmath"
    beginmath.attr = h.attr
    beginmath.user_id = luatexbase.new_whatsit'beginmath'
    local endmath = node.new("whatsit","user_defined")
    endmath.type = string.byte("s")
    endmath.value = "endmath"
    endmath.attr = h.attr
    endmath.user_id = luatexbase.new_whatsit'endmath'
    h = node.insert_after(h,node.tail(h),endmath)
    h = node.insert_before(h,h,beginmath)
    return node.mlist_to_hlist(h,d,p)
end

luatexbase.add_to_callback('mlist_to_hlist', mathboundary, 'Mark math')
}

\setbox0=\vbox{{\noindent Hello\\ $x=a+b^2$}}

\directlua{
    local nodetree = require('nodetree')
    nodetree.print(tex.box[0])
}

\box0

\end{document}

Console (recherchez WHATSIT subtype: user_defined):

└─VLIST width: 345pt, depth: 0.83pt, height: 18.94pt
  ╚═head:
    ├─HLIST subtype: line, width: 345pt, depth: 0.11pt, height: 6.94pt
    │ ╚═head:
    │   ├─LOCAL_PAR 
    │   ├─GLYPH subtype: 256, char: H, width: 7.5pt, height: 6.83pt
    │   ├─GLYPH subtype: 256, char: e, width: 4.44pt, height: 4.48pt, depth: 0.11pt
    │   ├─GLYPH subtype: 256, char: l, width: 2.78pt, height: 6.94pt
    │   ├─GLYPH subtype: 256, char: l, width: 2.78pt, height: 6.94pt
    │   ├─GLYPH subtype: 256, char: o, width: 5pt, height: 4.48pt, depth: 0.11pt
    │   ├─PENALTY penalty: 10000
    │   ├─GLUE stretch: +1fil
    │   ├─PENALTY penalty: -10000
    │   └─GLUE subtype: rightskip
    ├─PENALTY subtype: linebreakpenalty, penalty: 300
    ├─GLUE subtype: baselineskip, width: 3.75pt
    └─HLIST subtype: line, width: 345pt, depth: 0.83pt, height: 8.14pt
      ╚═head:
        ├─WHATSIT subtype: user_defined, user_id: 1, type: 115, value: beginmath
        ├─GLYPH subtype: 256, char: x, width: 5.72pt, height: 4.31pt
        ├─GLUE subtype: thickmuskip, width: 2.78pt, stretch: 2.78pt
        ├─GLYPH subtype: 256, char: =, width: 7.78pt, height: 3.67pt, depth: -1.33pt
        ├─PENALTY subtype: noadpenalty, penalty: 500
        ├─GLUE subtype: thickmuskip, width: 2.78pt, stretch: 2.78pt
        ├─GLYPH subtype: 256, char: a, width: 5.29pt, height: 4.31pt
        ├─GLUE subtype: medmuskip, width: 2.22pt, stretch: 1.11pt, shrink: 2.22pt
        ├─GLYPH subtype: 256, char: +, width: 7.78pt, height: 5.83pt, depth: 0.83pt
        ├─PENALTY subtype: noadpenalty, penalty: 700
        ├─GLUE subtype: medmuskip, width: 2.22pt, stretch: 1.11pt, shrink: 2.22pt
        ├─GLYPH subtype: 256, char: b, width: 4.29pt, height: 6.94pt
        ├─HLIST subtype: sup, width: 4.49pt, height: 4.51pt, shift: -3.63pt
        │ ╚═head:
        │   └─GLYPH char: 2, width: 3.99pt, height: 4.51pt
        ├─WHATSIT subtype: user_defined, user_id: 2, type: 115, value: endmath
        ├─MATH subtype: endmath
        ├─PENALTY subtype: linepenalty, penalty: 10000
        ├─GLUE subtype: parfillskip, stretch: +1fil
        └─GLUE subtype: rightskip

Réponses

7 MarcelKrüger Nov 21 2020 at 16:09

Lorsque vous examinez les listes de nœuds après un saut de ligne, les nœuds frontières ne sont pas une solution fiable. Cela a au moins deux raisons:

  1. Chaque nœud est soit supprimable, soit non supprimable. Si votre nœud de frontière est ignorable, vous obtenez le même problème qu'avec les nœuds math-on / math-off: ils disparaissent au début d'une ligne. Ainsi, le nœud que vous souhaitez ne peut pas être annulé, mais rappelez-vous la règle concernant les nœuds jetables au début d'une ligne: après un saut de ligne, tous les nœuds jetables sont supprimés jusqu'à ce que le premier nœud non supprimable soit rencontré. Cela implique en particulier que votre nouveau nœud de frontière non supprimable supprimerait la suppression des nœuds jetables potentiellement suivants, affectant la sortie. (Il y a d'autres raisons pour lesquelles l'ajout d'un nœud non supprimable ici, par exemple un whatsit, affectera toujours le saut de ligne, mais celui-ci est le plus facile à décrire)

  2. Une fois que le saut de ligne arrive, vous pouvez avoir hlist contenant des maths mais ne contenant aucune limite mathématique. Un exemple assez extrême serait:

    \documentclass{article}
    \begin{document}
    \showoutput
    \setbox0\vbox{
      \hsize=1cm
      \noindent
      Hi $1+2+3+4$
    }
    \setbox1\vsplit0 to\baselineskip 
    \setbox2\vsplit0 to\baselineskip
    \showbox0
    \showbox1
    \showbox2
    \end{document}
    

    Ici, la boîte 1 finit par ne contenir qu'une partie médiane d'une formule mathématique, il n'y a donc aucune raison qu'elle contienne un type de nœud de frontière. C'est toujours des maths.

    (Une variante de ceci qui est plus susceptible de se produire dans la pratique est une formule mathématique qui traverse les pages. La deuxième page n'aura pas de nœud mathématique de départ car aucun calcul ne commence là.)

Alors, que peut-on faire à ce sujet? Il existe deux options:

  1. Bien que votre approche 1) ne puisse pas fonctionner de manière fiable, vous pouvez implémenter 2) et ajouter un attribut. Vous pouvez simplement parcourir la liste de nœuds dans post_mlist_to_hlist_filter¹ pour ajouter ceci, puis les mathématiques en ligne et d'affichage seront couvertes.
  2. Faites ce que vous voulez avant le saut de ligne et utilisez simplement les nœuds de frontière mathématiques existants. Dans la plupart des cas, vous voulez faire du travail avant le saut de ligne de toute façon, c'est donc tout à fait naturel.

Selon le cas d'utilisation spécifique, l'une des solutions sera souvent assez naturelle. Par exemple, l'extraction de texte devrait presque toujours être basée sur du texte avant le saut de ligne (ou même avant la mise en forme) de toute façon, donc cela correspond bien à 2, tandis que l'ajout de couleurs différentes pour les nœuds mathématiques signifie simplement ajouter un attribut de toute façon, donc il s'adapte naturellement à 1 .

¹: Dans les versions modernes de LuaLaTeX, mlist_to_hlistil ne devrait presque jamais être défini directement mais à la place pre_mlist_to_hlist_filterou post_mlist_to_hlist_filterdevrait être utilisé. Ils ont fondamentalement la même interface que mlist_to_hlist, mais vous n'avez pas à node.mlist_to_hlistvous appeler et votre code reste compatible avec d'autres packages utilisant ces rappels. Le code de votre question, par exemple, pourrait être ajusté en remplaçant

luatexbase.add_to_callback('mlist_to_hlist', mathboundary, 'Mark math')

avec

luatexbase.add_to_callback('pre_mlist_to_hlist_filter', mathboundary, 'Mark math')

et remplacer

return node.mlist_to_hlist(h,d,p)

avec juste

return h