bidi ドキュメントのグループ化、リスト環境、および表示数式インタラクション

bidi ドキュメントのグループ化、リスト環境、および表示数式インタラクション

すべてが LTR の場合には機能し、すべてが RTL の場合には機能するが、メイン ドキュメントの方向が環境内の方向と異なる場合には失敗するコードの一部をデバッグしようとしています。

コードをかなり単純なものに減らすことはできましたが、一体なぜ私がそんなことをしたいのかという質問からは、それが明確にならないことは認めます... また、動作ははるかに複雑な実際のコードとは少し異なるため、まだ何かを見逃している可能性があります。

問題

  • 以下のコードでは、\predisplaysize段落の最終行の長さを測定するために使用します。
  • \prevgrafこれを実行するときは、間隔を維持するために後でリセットするために、ディスプレイの計算の内部からを取得する必要があります。
  • 以下のコードでは、\prevgraf各リスト環境の終了時に が 4 回リセットされます。ただし、その値は、最初のリスト環境の前に言語を変更するか、リスト環境の開始時に言語を変更するかによって異なります。以下の MWE では、 の連続呼び出しごとに が1、1、1、0 に\measurelineなります。\prevgraf

これはなぜでしょうか? どうすれば一貫した動作を実現できるでしょうか?

この例は奇妙だとは思いますが、内部の最初ではなく、\setlanguage{ukenglish}前に呼び出すかどうかによって違いが生じるのはなぜでしょうか?listenvalistenva

(以下の MWE の 2 番目の例の動作が必要です。これは、 の\prevgraf4 回の呼び出しに対するのパターンで、 は\measureline1、0、1、0 になるはずです。 をコメント アウトすると\babelprovide[import, main]{persian}、 の開始前の言語がlistenva内に設定されているものと同じであることが保証され、これを確認できますlistenva。)

気づいたこと

  • 環境で\@noparlistfalsebefore を呼び出すことで、2 回目の呼び出しで が 0 になることが保証されます。つまり、この行をコメント アウトすると、 の4 回の呼び出しのそれぞれで が 1 になります。\endlist\listenvb\prevgraf\prevgraf\measureline

  • メインドキュメントの言語が LTR で、環境で言語が RTL 言語に設定されている場合にも、同じ問題が発生します。

  • グループ化は次のような影響も与えます:

    これは機能します:

    \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}

ここに画像の説明を入力してください

関連情報