Estoy intentando depurar parte de mi código que funciona cuando todo es LTR y funciona cuando todo es RTL, pero falla cuando la dirección del documento principal es diferente a la dirección dentro de uno de mis entornos.
Me las arreglé para reducir mi código a algo bastante simple, pero admito que no quedará claro a partir de la pregunta por qué querría hacer lo que estoy haciendo... Además, el comportamiento es ligeramente diferente al de mi Código del mundo real mucho más complicado, por lo que es posible que todavía me haya perdido algo.
El problema
- En el siguiente código, utilizo
\predisplaysize
para medir la longitud de la última línea de un párrafo. - Cuando haces esto, necesitas tomar las
\prevgraf
matemáticas del interior de la pantalla para restablecerlas luego y mantener el espaciado. - En el código siguiente,
\prevgraf
se restablece 4 veces al final de cada uno de los entornos de mi lista. Pero su valor es diferente dependiendo de si cambio el idioma antes del primer entorno de lista o al comienzo del entorno de lista. En el MWE a continuación, cada llamada sucesiva\measureline
da un\prevgraf
valor de 1, 1, 1 y luego 0.
¿Por qué es esto? ¿Y cómo puedo conseguir un comportamiento coherente?
Sé que el ejemplo es extraño, pero ¿por qué debería haber una diferencia dependiendo de si llamo \setlanguage{ukenglish}
antes listenva
o lo primero que hace adentro listenva
?
(Quiero el comportamiento del segundo ejemplo en el MWE a continuación. Ese es el patrón \prevgraf
para las cuatro llamadas de \measureline
debería ser: 1, 0, 1, 0. Puede ver esto cuando comenta \babelprovide[import, main]{persian}
, asegurándose de que el idioma antes del El inicio listenva
es el mismo que el que se establece en el interior listenva
)
Cosas que noto
Llamar
\@noparlistfalse
antes\endlist
en el\listenvb
entorno es lo que garantiza que\prevgraf
sea 0 en la segunda llamada. En otras palabras, si comento esta línea,\prevgraf
es 1 para cada una de las cuatro llamadas a\measureline
.El mismo problema ocurre cuando el idioma del documento principal es LTR y mi entorno configura el idioma como RTL.
La agrupación también está afectando cosas:
Esto funciona:
\listenva \begin{listenvb} Test. \end{listenvb} \endlistenva
Pero esto falla:
\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}
Estoy obteniendo un resultado incorrecto
Salida deseada
Respuesta1
Considera lo siguiente
\showboxdepth\maxdimen\showboxbreadth\maxdimen
\tracingonline1\tracingoutput1
\everypar{\setbox0=\lastbox}
{%\textdirection=0
$$
$$\par}
\bye
que da la salida
\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
mientras que si descomento \textdirection=0
el resultado es
\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
Parece que cuando presionas explícitamente un nodo de directorio (usando \textdir
) en un grupo, LuaTeX no descarta la línea vacía antes de la pantalla (tal vez no la considera vacía debido a los nodos de directorio alrededor de la penalización). No estoy seguro si eso debería considerarse un error o no.
No soy competente en el código de Babel, pero supongo que Babel no inserta nodos de directorio cuando no es necesario, por lo que cuando lo colocas \selectlanguage{ukenglish}
en el nivel de agrupación superior, Babel no inyecta más nodos de directorio dentro del grupo de tu ambiente.
Probablemente puedas arreglártelas sin usar el truco de visualización para obtener la longitud de la última línea si estás dispuesto a usar algo de lua:
\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}