группировка документов bidi, среда списка и математическое взаимодействие отображения

группировка документов bidi, среда списка и математическое взаимодействие отображения

Я пытаюсь отладить часть своего кода, который работает, когда все написано слева направо, и работает, когда все написано справа налево, но дает сбой, когда направление основного документа отличается от направления внутри одной из моих сред.

Мне удалось сократить свой код до чего-то довольно простого, но я признаю, что это не будет ясно из вопроса, зачем мне вообще делать то, что я делаю... Кроме того, поведение немного отличается от моего гораздо более сложного реального кода, так что я мог что-то упустить.

Проблема

  • В приведенном ниже коде я использую \predisplaysizeдля измерения длины последней строки абзаца.
  • Когда вы это сделаете, вам нужно будет извлечь данные \prevgrafиз внутренней части отображения математики, чтобы впоследствии сбросить их и сохранить интервалы.
  • В коде ниже \prevgrafсбрасывается 4 раза в конце каждого из моих списковых окружений. Но его значение отличается в зависимости от того, меняю ли я язык перед первым списковым окружением или в начале спискового окружения. В MWE ниже каждый последующий вызов \measurelineдает \prevgraf1, 1, 1, затем 0.

Почему это так? И как мне добиться последовательного поведения?

Я знаю, что пример странный, но почему должна быть разница в зависимости от того, звоню ли я \setlanguage{ukenglish}раньше listenva, а не первым, что внутри listenva???

(Я хочу поведение второго примера в MWE ниже. То есть шаблон \prevgrafдля четырех вызовов \measurelineдолжен быть: 1, 0, 1, 0. Вы можете увидеть это, когда закомментируете \babelprovide[import, main]{persian}, гарантируя, что язык перед началом listenvaтакой же, как тот, что установлен внутри listenva)

Вещи, которые я замечаю

  • Вызов \@noparlistfalseперед \endlistв \listenvbсреде — это то, что гарантирует, что \prevgrafпри втором вызове будет 0. Другими словами, если я закомментирую эту строку, \prevgrafбудет 1 для каждого из четырех вызовов \measureline.

  • Та же проблема возникает, когда основным языком документа является язык с написанием слева направо, а в моей среде задан язык с написанием справа налево.

  • Группировка также влияет на вещи:

    Это работает:

    \listenva
      \begin{listenvb}
        Test.
      \end{listenvb}
    \endlistenva
    

    Но это не срабатывает:

    \begingroup
    \selectlanguage{ukenglish}
    \begin{listenva}
      \begin{listenvb}
        Test.
      \end{listenvb}
    \end{listenva}
    \endgroup
    

МВЭ

%! 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}

Я получаю неправильный вывод

неправильный вывод

Желаемый результат

желаемый результат

решение1

Рассмотрим следующее

\showboxdepth\maxdimen\showboxbreadth\maxdimen
\tracingonline1\tracingoutput1
\everypar{\setbox0=\lastbox}
{%\textdirection=0
$$
$$\par}
\bye

что дает выход

\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

а если я раскомментирую, то \textdirection=0вывод будет таким:

\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

Похоже, что когда вы явно вставляете узел dir (используя \textdir) в группу, LuaTeX не отбрасывает пустую строку перед отображением (возможно, он не считает ее пустой из-за узлов dir вокруг штрафа). Не уверен, следует ли это считать ошибкой или нет.

Я не разбираюсь в коде Babel, но предполагаю, что Babel не вставляет узлы dir, когда в этом нет необходимости, и поэтому, когда вы помещаете их \selectlanguage{ukenglish}на верхний уровень группировки, Babel не внедряет больше узлов dir внутрь группы вашей среды.

Вероятно, вы сможете обойтись без использования трюка с отображением, чтобы получить длину последней строки, если вы готовы использовать немного 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}

введите описание изображения здесь

Связанный контент