agrupamento de documentos bidi, ambiente de lista e exibição de interação matemática

agrupamento de documentos bidi, ambiente de lista e exibição de interação matemática

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 \predisplaysizepara medir o comprimento da linha final de um parágrafo.
  • Ao fazer isso, você precisa pegar \prevgrafa 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\prevgraf1, 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 listenvaem vez da primeira coisa dentro listenva???

(Quero o comportamento do segundo exemplo no MWE abaixo. Esse é o padrão \prevgrafpara as quatro chamadas de \measurelinedeve 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 \@noparlistfalseantes \endlistno \listenvbambiente é o que garante que \prevgrafseja 0 na segunda chamada. Em outras palavras, se eu comentar esta linha, \prevgrafserá 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 errada

Saída desejada

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=0a 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}

insira a descrição da imagem aqui

informação relacionada