すべてが LTR の場合には機能し、すべてが RTL の場合には機能するが、メイン ドキュメントの方向が環境内の方向と異なる場合には失敗するコードの一部をデバッグしようとしています。
コードをかなり単純なものに減らすことはできましたが、一体なぜ私がそんなことをしたいのかという質問からは、それが明確にならないことは認めます... また、動作ははるかに複雑な実際のコードとは少し異なるため、まだ何かを見逃している可能性があります。
問題
- 以下のコードでは、
\predisplaysize
段落の最終行の長さを測定するために使用します。 \prevgraf
これを実行するときは、間隔を維持するために後でリセットするために、ディスプレイの計算の内部からを取得する必要があります。- 以下のコードでは、
\prevgraf
各リスト環境の終了時に が 4 回リセットされます。ただし、その値は、最初のリスト環境の前に言語を変更するか、リスト環境の開始時に言語を変更するかによって異なります。以下の MWE では、 の連続呼び出しごとに が1、1、1、0 に\measureline
なります。\prevgraf
これはなぜでしょうか? どうすれば一貫した動作を実現できるでしょうか?
この例は奇妙だとは思いますが、内部の最初ではなく、\setlanguage{ukenglish}
前に呼び出すかどうかによって違いが生じるのはなぜでしょうか?listenva
listenva
(以下の MWE の 2 番目の例の動作が必要です。これは、 の\prevgraf
4 回の呼び出しに対するのパターンで、 は\measureline
1、0、1、0 になるはずです。 をコメント アウトすると\babelprovide[import, main]{persian}
、 の開始前の言語がlistenva
内に設定されているものと同じであることが保証され、これを確認できますlistenva
。)
気づいたこと
環境で
\@noparlistfalse
before を呼び出すことで、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}