Ich versuche, einen Teil meines Codes zu debuggen, der funktioniert, wenn alles LTR ist, und der funktioniert, wenn alles RTL ist, aber fehlschlägt, wenn die Hauptdokumentrichtung von der Richtung innerhalb einer meiner Umgebungen abweicht.
Ich habe es geschafft, meinen Code auf etwas ziemlich Einfaches zu reduzieren, gebe aber zu, dass aus der Frage, warum um Himmels Willen ich das tun möchte, was ich tue, nicht klar wird … Außerdem unterscheidet sich das Verhalten leicht von meinem viel komplizierteren Code in der realen Welt, sodass ich vielleicht trotzdem noch etwas übersehen habe.
Das Problem
- Im folgenden Code verwende ich,
\predisplaysize
um die Länge der letzten Zeile eines Absatzes zu messen. - Wenn Sie dies tun, müssen Sie die
\prevgraf
Mathematik aus der Anzeige heraus erfassen, um sie anschließend so zurückzusetzen, dass der Abstand erhalten bleibt. - Im folgenden Code
\prevgraf
wird am Ende jeder meiner Listenumgebungen 4 Mal zurückgesetzt. Der Wert ist jedoch unterschiedlich, je nachdem, ob ich die Sprache vor der ersten Listenumgebung oder am Anfang der Listenumgebung ändere. Im folgenden MWE\measureline
ergibt jeder aufeinanderfolgende Aufruf von ein Ergebnis\prevgraf
von 1, 1, 1 und dann 0.
Warum ist das so? Und wie kann ich ein konsistentes Verhalten erreichen?
Ich weiß, das Beispiel ist bizarr, aber warum sollte es einen Unterschied machen, je nachdem, ob ich \setlanguage{ukenglish}
vorher aufrufe listenva
oder als erstes darin listenva
???
(Ich möchte das Verhalten des zweiten Beispiels im MWE unten. Das ist das Muster von \prevgraf
für die vier Aufrufe von , das \measureline
lauten sollte: 1, 0, 1, 0. Sie können dies sehen, wenn Sie auskommentieren und \babelprovide[import, main]{persian}
sicherstellen, dass die Sprache vor dem Beginn von listenva
mit der in festgelegten übereinstimmt listenva
.)
Was mir auffällt
\@noparlistfalse
Der vorherige Aufruf\endlist
in der\listenvb
Umgebung stellt sicher, dass\prevgraf
beim zweiten Aufruf 0 ist. Mit anderen Worten, wenn ich diese Zeile auskommentiere,\prevgraf
ist für jeden der vier Aufrufe von 1\measureline
.Dasselbe Problem tritt auf, wenn die Hauptdokumentsprache LTR ist und meine Umgebung die Sprache auf RTL-Sprache einstellt.
Auch die Gruppierung hat Auswirkungen auf:
Das funktioniert:
\listenva \begin{listenvb} Test. \end{listenvb} \endlistenva
Aber das schlägt fehl:
\begingroup \selectlanguage{ukenglish} \begin{listenva} \begin{listenvb} Test. \end{listenvb} \end{listenva} \endgroup
MWE
%! TeX Program = lualatex
\documentclass{article}
\pagestyle{empty}
\usepackage[bidi=basic, layout=lists]{babel}
\babelprovide[import, main]{persian}
\babelprovide[import]{ukenglish}
\newdimen\linelen
\newcommand{\measureline}{%
\abovedisplayshortskip -\baselineskip
\abovedisplayskip\abovedisplayshortskip
\belowdisplayshortskip 0pt
\belowdisplayskip\belowdisplayshortskip
$$
\ifdim\predisplaysize>0pt
\global\linelen\dimexpr\predisplaysize-2em
\fi
\global\def\resetspacing{%
\predisplaysize\the\predisplaysize
\prevgraf\the\prevgraf
}%
$$
\resetspacing
\ifdim\linelen>0pt
\vskip-\baselineskip
\fi
}
\newcommand{\nolistspaces}{%
\leftmargin 0pt
\rightmargin 0pt
\itemindent 0pt
\partopsep 0pt
\parsep 0pt
\topsep 0pt
}
\newenvironment{listenva}{%
\selectlanguage{ukenglish}%
\list{}{\nolistspaces}%
\item\relax
}{%
\measureline
\strut\hskip\linelen+++%
\csname @noparlistfalse\endcsname
\endlist
}
\newenvironment{listenvb}{%
\list{}{\nolistspaces}%
\item\relax
}{%
\measureline
\csname @noparlistfalse\endcsname
\endlist
}
\begin{document}
\begin{listenva}
\begin{listenvb}
Test.
\end{listenvb}
\end{listenva}
\selectlanguage{ukenglish}
\begin{listenva}
\begin{listenvb}
Test.
\end{listenvb}
\end{listenva}
\end{document}
Ich erhalte die falsche Ausgabe
Gewünschte Ausgabe
Antwort1
Folgendes berücksichtigen
\showboxdepth\maxdimen\showboxbreadth\maxdimen
\tracingonline1\tracingoutput1
\everypar{\setbox0=\lastbox}
{%\textdirection=0
$$
$$\par}
\bye
was die Ausgabe ergibt
\vbox(667.20255+0.0)x469.75499, direction TLT
.\vbox(0.0+0.0)x469.75499, glue set 14.0fil, direction TLT
..\glue -22.5
..\hbox(8.5+0.0)x469.75499, glue set 469.755fil, direction TLT
...\vbox(8.5+0.0)x0.0, direction TLT
...\glue 0.0 plus 1.0fil
..\glue 0.0 plus 1.0fil minus 1.0fil
.\vbox(643.20255+0.0)x234.8775, glue set 626.20251fill, direction TLT
..\glue(\topskip) 10.0
..\hbox(0.0+0.0)x0.0, shifted 234.8775, direction TLT
..\penalty 0
..\glue(\belowdisplayshortskip) 7.0 plus 3.0 minus 4.0
..\glue 0.0 plus 1.0fill
.\glue(\baselineskip) 17.55556
.\hbox(6.44444+0.0)x469.75499, glue set 232.37749fil, direction TLT
..\glue 0.0 plus 1.0fil minus 1.0fil
..\tenrm 1
..\glue 0.0 plus 1.0fil minus 1.0fil
Wenn ich das Kommentarzeichen entferne, \textdirection=0
ist die Ausgabe
\vbox(667.20255+0.0)x469.75499, direction TLT
.\vbox(0.0+0.0)x469.75499, glue set 14.0fil, direction TLT
..\glue -22.5
..\hbox(8.5+0.0)x469.75499, glue set 469.755fil, direction TLT
...\vbox(8.5+0.0)x0.0, direction TLT
...\glue 0.0 plus 1.0fil
..\glue 0.0 plus 1.0fil minus 1.0fil
.\vbox(643.20255+0.0)x469.75499, glue set 614.20251fill, direction TLT
..\glue(\topskip) 10.0
..\hbox(0.0+0.0)x469.75499, glue set 469.755fil, direction TLT
...\localpar
....\localinterlinepenalty=0
....\localbrokenpenalty=0
....\localleftbox=null
....\localrightbox=null
...\begindir TLT
...\penalty 10000
...\enddir TLT
...\glue(\parfillskip) 0.0 plus 1.0fil
...\glue(\rightskip) 0.0
..\penalty 10000
..\glue(\abovedisplayshortskip) 0.0 plus 3.0
..\glue(\baselineskip) 12.0
..\hbox(0.0+0.0)x0.0, shifted 234.8775, direction TLT
..\penalty 0
..\glue(\belowdisplayshortskip) 7.0 plus 3.0 minus 4.0
..\glue 0.0 plus 1.0fill
.\glue(\baselineskip) 17.55556
.\hbox(6.44444+0.0)x469.75499, glue set 232.37749fil, direction TLT
..\glue 0.0 plus 1.0fil minus 1.0fil
..\tenrm 1
..\glue 0.0 plus 1.0fil minus 1.0fil
Es sieht so aus, als ob LuaTeX die leere Zeile vor der Anzeige nicht verwirft, wenn Sie explizit einen Verzeichnisknoten (mit \textdir
) in eine Gruppe einfügen (vielleicht betrachtet es sie aufgrund der Verzeichnisknoten um die Strafe herum nicht als leer). Ich bin nicht sicher, ob das als Fehler angesehen werden sollte oder nicht.
Ich bin mit dem Babel-Code nicht vertraut, aber ich vermute, dass Babel keine Verzeichnisknoten einfügt, wenn es nicht nötig ist, und dass \selectlanguage{ukenglish}
Babel daher, wenn Sie sie auf die oberste Gruppierungsebene setzen, keine weiteren Verzeichnisknoten in die Gruppe Ihrer Umgebung einfügt.
Sie können wahrscheinlich auf den Anzeigetrick verzichten, um die Länge der letzten Zeile zu erhalten, wenn Sie bereit sind, etwas Lua zu verwenden:
\documentclass{article}
\pagestyle{empty}
\usepackage[bidi=basic, layout=lists]{babel}
\babelprovide[import, main]{persian}
\babelprovide[import]{ukenglish}
\newdimen\linelen
\directlua{
local disabled = true
local function lastline_length(head,c)
if disabled then
return head
end
local last_line = node.tail(head)
local parfill_node
for n in node.traverse_id(node.id('glue'),last_line.list) do
if n.subtype == 15 then parfill_node = n end
end
local length, _, _ = node.rangedimensions(last_line,last_line.head,parfill_node)
tex.setdimen('global', 'linelen',length)
return head
end
local getlastlinelength = luatexbase.new_luafunction"getlastlinelength"
lua.get_functions_table()[getlastlinelength] = function() disabled = false end
token.set_lua("getlastlinelength", getlastlinelength, "protected")
local dontgetlastlinelength = luatexbase.new_luafunction"dontgetlastlinelength"
lua.get_functions_table()[dontgetlastlinelength] = function() disabled = true end
token.set_lua("dontgetlastlinelength", dontgetlastlinelength, "protected")
luatexbase.add_to_callback('post_linebreak_filter',lastline_length,'lastline')
}
\newcommand{\nolistspaces}{%
\leftmargin 0pt
\rightmargin 0pt
\itemindent 0pt
\partopsep 0pt
\parsep 0pt
\topsep 0pt
}
\newenvironment{listenva}{%
\selectlanguage{ukenglish}%
\list{}{\nolistspaces}%
\item\relax
}{%
\ifdim\linelen>0pt
\vskip-\baselineskip
\fi
\strut\hskip\linelen+++%
\csname @noparlistfalse\endcsname
\endlist
}
\newenvironment{listenvb}{%
\global\linelen=0pt
\getlastlinelength
\list{}{\nolistspaces}%
\item\relax
}{%
\csname @noparlistfalse\endcsname
\endlist
\dontgetlastlinelength
}
\begin{document}
\begin{listenva}
\begin{listenvb}
Test.
\end{listenvb}
\end{listenva}
\selectlanguage{ukenglish}
\begin{listenva}
\begin{listenvb}
Test.
\end{listenvb}
\end{listenva}
\end{document}