Estou tentando depurar parte do meu código que funciona quando tudo é LTR e funciona quando tudo é RTL, mas falha quando a direção do documento principal é diferente da direção dentro de um dos meus ambientes.
Consegui reduzir meu código a algo bastante simples, mas admito que não ficará claro a partir da pergunta por que diabos eu gostaria de fazer o que estou fazendo... Além disso, o comportamento é um pouco diferente do meu código do mundo real muito mais complicado, então ainda posso ter perdido alguma coisa.
O problema
- No código abaixo, utilizo
\predisplaysize
para medir o comprimento da linha final de um parágrafo. - Ao fazer isso, você precisa pegar
\prevgraf
a matemática da tela para redefini-la posteriormente para manter o espaçamento. - No código abaixo,
\prevgraf
é redefinido 4 vezes no final de cada um dos ambientes da minha lista. Mas seu valor é diferente dependendo se eu altero o idioma antes do primeiro ambiente de lista ou no início do ambiente de lista. No MWE abaixo, cada chamada sucessiva de\measureline
dá\prevgraf
1, 1, 1 e depois 0.
Por que é isso? E como posso obter um comportamento consistente?
Eu sei que o exemplo é bizarro, mas por que deveria haver uma diferença dependendo se eu ligo \setlanguage{ukenglish}
antes listenva
em vez da primeira coisa dentro listenva
???
(Quero o comportamento do segundo exemplo no MWE abaixo. Esse é o padrão \prevgraf
para as quatro chamadas de \measureline
deve ser: 1, 0, 1, 0. Você pode ver isso ao comentar \babelprovide[import, main]{persian}
, garantindo que o idioma antes do o início de listenva
é o mesmo que está definido dentro listenva
)
Coisas que eu noto
Chamar
\@noparlistfalse
antes\endlist
no\listenvb
ambiente é o que garante que\prevgraf
seja 0 na segunda chamada. Em outras palavras, se eu comentar esta linha,\prevgraf
será 1 para cada uma das quatro chamadas para\measureline
.O mesmo problema ocorre quando o idioma do documento principal é LTR e meu ambiente define o idioma como RTL.
O agrupamento também está afetando as coisas:
Isso funciona:
\listenva \begin{listenvb} Test. \end{listenvb} \endlistenva
Mas isso falha:
\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}
Saída errada que estou recebendo
Saída desejada
Responder1
Considere o seguinte
\showboxdepth\maxdimen\showboxbreadth\maxdimen
\tracingonline1\tracingoutput1
\everypar{\setbox0=\lastbox}
{%\textdirection=0
$$
$$\par}
\bye
que dá a saída
\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
enquanto se eu descomentar \textdirection=0
a saída será
\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 quando você empurra explicitamente um nó dir (usando \textdir
) em um grupo, LuaTeX não descarta a linha vazia antes da exibição (talvez não a considere vazia por causa dos nós dir em torno da penalidade). Não tenho certeza se isso deve ser considerado um bug ou não.
Não sou proficiente no código do babel, mas meu palpite é que o babel não insere nós dir quando não é necessário e, portanto, quando você coloca \selectlanguage{ukenglish}
no nível de agrupamento superior, o babel não injeta mais nós dir dentro do grupo do seu ambiente.
Você provavelmente pode sobreviver sem usar o truque de exibição para obter o comprimento da última linha se estiver disposto a usar um pouco 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}