모든 것이 LTR일 때 작동하고 모든 것이 RTL일 때 작동하지만 기본 문서 방향이 내 환경 중 하나의 방향과 다를 때 실패하는 일부 코드를 디버깅하려고 합니다.
나는 내 코드를 매우 간단한 것으로 줄일 수 있었지만 도대체 왜 내가 하고 있는 일을 하고 싶은지에 대한 질문에서 명확하지 않을 것이라는 점을 인정합니다… 또한 동작은 내 코드와 약간 다릅니다. 훨씬 더 복잡한 실제 코드이므로 아직 뭔가를 놓쳤을 수도 있습니다.
문제
- 아래 코드에서는
\predisplaysize
단락의 마지막 줄 길이를 측정하는 데 사용합니다. \prevgraf
이 작업을 수행할 때 간격을 유지하기 위해 나중에 재설정하려면 디스플레이 수학 내부에서 를 가져와야 합니다 .- 아래 코드에서는
\prevgraf
각 목록 환경이 끝날 때마다 4번 재설정됩니다. 하지만 첫 번째 목록 환경 이전에 언어를 변경하는지 목록 환경이 시작될 때 언어를 변경하는지에 따라 그 가치가 다릅니다. 아래의 MWE에서 각 연속 호출은 1, 1, 1, 0을\measureline
제공합니다 .\prevgraf
왜 이런거야? 그리고 일관된 행동을 어떻게 얻을 수 있습니까?
예시가 이상하다는 건 알지만, 내부에서 처음으로 전화하는 것과 반대로 \setlanguage{ukenglish}
이전에 전화했는지에 따라 왜 차이가 있어야 합니까 ???listenva
listenva
\prevgraf
(아래 MWE에서 두 번째 예제의 동작을 원합니다. 이는 의 4개 호출에 대한 패턴이 \measureline
1, 0, 1, 0이어야 합니다. 를 주석 처리할 때 이를 볼 수 있으며 \babelprovide[import, main]{persian}
, 시작은 listenva
내부에 설정된 것과 동일합니다 listenva
)
내가 알아차린 것들
환경 에서
\@noparlistfalse
이전에 호출하는 것은 두 번째 호출에서 0이 되도록 보장하는 것입니다 . 즉, 이 줄을 주석 처리하면 는 에 대한 네 번의 호출 각각에 대해 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
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}
잘못된 출력이 표시됩니다.
원하는 출력
답변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
\textdir
그룹에서 ( 를 사용하여) dir 노드를 명시적으로 푸시할 때 LuaTeX는 표시 전에 빈 줄을 삭제하지 않는 것처럼 보입니다 (아마도 페널티 주변의 dir 노드 때문에 비어 있다고 간주하지 않을 수도 있습니다). 그것이 버그로 간주되어야 하는지 아닌지 확실하지 않습니다.
나는 바벨의 코드에 능숙하지 않지만 바벨은 필요하지 않을 때 dir 노드를 삽입하지 않으므로 \selectlanguage{ukenglish}
최상위 그룹화 수준에 놓을 때 바벨은 그룹 내에 더 많은 dir 노드를 삽입하지 않습니다. 환경.
루아를 사용하려는 경우 디스플레이 트릭을 사용하지 않고도 마지막 줄 길이를 얻을 수 있습니다.
\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}