Closed doraTeX closed 6 years ago
\@classv
で必ず最初に空の \mbox{} を出すようにしているので,そこで水平モードに入っているため \par が効いてしまう,という話だと思います。段落頭の JFM グルーを消せるように pTeX 自体を改修する(例えばそういうスイッチを実装して tabular 内で有効化する)方が,マクロレベルでの対処より容易な気がしますね。必ず最初に空の \mbox{} を出すようにしているので,そこで水平モードに入っているため \par が効いてしまう
\mbox{} を出す代わりに,セルの最初で \everypar{} に \inhibitglue を仕込んでおけばいいのかな,と思っています.なんだか頭がこんがらがっていますが,こんな感じ?
\def\@classv{\@addtopreamble{\@startpbox{\@nextchar}%
\noexpand\unexpanded{\everypar{\inhibitglue
\everypar{\noexpand\unexpanded\noexpand\expandafter{\noexpand\the\noexpand\everypar}}%
\noexpand\unexpanded\noexpand\expandafter{\noexpand\the\noexpand\everypar}}}%
\ignorespaces\@sharp\unskip\@endpbox}%
}
(まだ pLaTeX は e-TeX 拡張を要件とはしていなかったんでしたっけ? cf. #56)
2018-02-20 23:20 edit:
む,私のコードは \everypar {\unexpanded \expandafter {\the \everypar}}
のように,\the\everypar
が各セル開始時に(つまり,\@preamble
定義時ではなく)実行されるようにしたかったのですが,どうやら \begin{tabular}{|p{1cm}|p{2cm}|…|}
のように p 指定の後ろにさらに何かあると,そこで \the\everypar
が展開されてしまいますね…….
(まだ pLaTeX は e-TeX 拡張を要件とはしていなかったんでしたっけ? cf. #56)
e-TeX 必須な何かを plcore.ltx に導入するタイミングで,e-TeX 拡張を要件にするつもりでした。今回のようなケースはこれに該当すると思うので,TeX Live 2018 からはそうしましょう。
本題ですが,まだ試せていませんがとりあえず exppl2e に入れてみてはどうでしょう。> \everypar{} に \inhibitglue を仕込んでおけば
まだよくわかっていないのですが,以下の簡単なコードでは駄目なのでしょうか.
\def\@classv{\@addtopreamble{\@startpbox{\@nextchar}%
\everypar{\inhibitglue\the\everypar\everypar{\the\everypar}}%
\ignorespaces\@sharp\unskip\@endpbox}%
}
最後の %
の前に \show\@preamble
を足すと「プリアンブル」の中身を見ることができますが,このコードでも期待どおり,\begin{tabular}{|p{1cm}|p{2cm}|…|}
のようなセルの横並びで「逐次追加」されていくだけ(このとき展開は進まない)ように見えます。
(2018-02-21 20:48 edit) 上のコードは \documentclass{jsarticle} で Missing control sequence inserted.
を引き起こすので当然のようにダメでした。
0d064a8b80d24f0534f5340e398d26a924b2ca21 で \everypar
関係を別命令にしたものを exppl2e.sty に入れました.手元では動いていそうですが,引き続きテストを行います.
ありがとうございます。 0d064a8b80d24f0534f5340e398d26a924b2ca21 をテストしたところ,うまく動いているように見えます。 plarray をロードした場合についても,同様の対策が必要になりそうですので,そちらにも Issue を立てておきました。
plarray パッケージ (aminophen/platex-tools#9) の方を考え始めていますが,うまくいく方法が見つかっていません。安直に \mbox{}\inhibitglue
を\pltx@next@inhibitglue
に置き換えてもエラーが出るのでダメです。何かあれば教えていただきたいです。
ちなみに,表組の中で \relax\par から始まる状況って良くあるのでしょうか? 特に重要な理由がないのであれば頑張らなくてもいいんじゃないかと思っていたりします。(以前 #57 に書いた「重箱の隅のような例」とかも LaTeX と pLaTeX で互換性がないことが既知ですが,保留にしてあります。)
ちなみに,表組の中で \relax\par から始まる状況って良くあるのでしょうか?
\relax\par
としたのは極限のMWEまで切り詰めたからで,実用上登場する場面ではその形そのもので現れるわけではありません。
うちの英語科の教材作成者から,「去年と今年で組版結果が変わった」との報告があったので気づきました。
実際の教材上では,次のような場面で発現しました。(MWEへの切り詰めをもう少し実用的な形で抑え気味にした状態で例示します。)
\documentclass{jsarticle}
\usepackage{plarray}
\newlength\hoge
\newenvironment{paragraphWithArrow}{%
\setlength\hoge{1zw}%
\ifvmode\else\par\fi
\advance\leftskip\hoge\relax
\noindent\hspace{-\hoge}→\hspace{\hoge}\inhibitglue
}{\par}
\begin{document}
\begin{tabular}{p{12zw}p{12zw}}
I know the girl. & \\
+ She has long hair. & \\
\begin{paragraphWithArrow}
I know \textbf{the girl} \texttt{<}\textbf{who} has long hair\texttt{>}.
\end{paragraphWithArrow}
& 私は〈\textgt{髪の長い}〉\textgt{その女の子}を知っています。\\
\end{tabular}
\end{document}
MWEへの切り詰めをもう少し実用的な形で抑え気味にした状態
という状況がありうる,と理解すればいいのですかね。なんとなく理解しました。
ただ,まだ plarray.sty の方はどうすればいいのか思いつきません。私の能力だと,array.sty で一本化されている l, c, r と p の処理を分離すれば行けなくはないと思いますが,そうするとさらに別のパッケージと衝突しそうなので気が進んでいません。
plarray.sty
\insert@column
のところに \the@toks\the\@tempcnta
がありますが,
この \the
-文字列化された板号の終わりを検出するために \pltx@next@inhibitglue
を展開限定文脈で展開しておかしなことになっているようです.
とりあえず \relax
を前置すれば良い?(\space
ではどうなんだろう?)
\def\insert@column{%
\the@toks \the \@tempcnta
\relax\pltx@next@inhibitglue % !!!
\ignorespaces \@sharp \unskip
\the@toks \the \count@ \relax}
\insert@column のところに \the@toks\the\@tempcnta がありますが, この \the-文字列化された板号の終わりを検出するために \pltx@next@inhibitglue を展開限定文脈で展開しておかしなことになっているようです.
なるほど…
とりあえず \relax を前置すれば良い?(\space ではどうなんだろう?)
どちらも試してみましたが,今度は l, c, r のときにグルーが消えなくなるようです。
今度は l, c, r のときにグルーが消えなくなるようです。
\pltx@next@inhibitglue
のところに,「現在が水平モードなら \inhibitglue 発行」を
付け加えれば良いかもしれません:
\protected\def\pltx@next@inhibitglue{%
\ifhmode\inhibitglue\else
\edef\@tempa{\everypar{\inhibitglue
\everypar{\unexpanded\expandafter{\the\everypar}}%
\unexpanded\expandafter{\the\everypar}}}%
\@tempa\fi}
なるほど! そうしていただけると plarray.sty が助かります。
今度は,\mbox{} を除くと plarray.sty で別の副作用が起きることに気づきました。現行では
\ignorespaces \@sharp \unskip \unskip
のように \unskip を余分にもう一つ発行し,以下のような例で「)
と &
の間にソース中に空白文字があるかどうか」にかかわらず JFM グルーを消すことにしていました。
\begin{tabular}{|c|c|}
(中央)&(中央)\\ %% この行は空白文字なし
(中央) & (中央) %% この行は空白文字あり
\end{tabular}
ところが,\mbox{}\inhibitglue
を \relax\pltx@next@inhibitglue
に置き換えると,「空のセル」が本当に空になるので,以下の例で |r|
の罫線が揃わなくなります (#54 と同様)。
\begin{tabular}{|r|c|}
& xyz \\
a & 111 \\
bb & 22 \\
ccc & 3
\end{tabular}
pTeX で以下のソースの3行目で JFM グルーを消すことができれば,\unskip ではなく \inhibitglue を使うことができるので安全なのですが…。
あ)\inhibitglue あ\par % 消える
あ)\hskip20pt\unskip\unskip あ\par % 消える
あ)\hskip20pt\unskip\inhibitglue あ\par % 消えない
\bye
texjporg/tex-jp-build#28 で「\inhibitglue が展開不能トークンを透過するケース」を排除しようといろいろやっていたのですが,pLaTeX の \@classv
の実装がまさにこの「透過するケース」に依存していることに気づきました(本 issue の \@classv
改善案も同様)。実際に texjporg/tex-jp-build@f932384 の適用後は,p なセルで \inhibitglue が効かなくなっています。
そもそも現行の pTeX の挙動では
水\inhibitglue\ignorespaces (あ % (1)
これは \inhibitglue が \ignorespaces によってリセットされ, (
のグルーが入るのに対し,
水\hbox{あ}\inhibitglue\ignorespaces (あ % (2)
これは \inhibitglue がなぜかリセットされなくなり, (
のグルーが消えます。この後者 (2) のケースを利用していたのが,まさに pLaTeX の \@classv
の実装でした。 → あっちのコメントに飛びます。
\@tabclassz
(l,c,r) も \@classv
(p) も LaTeX 本来の動作に近づいたはず(本 issue の問題は起きない)です。(l,c,r の方には \lastnodesubtype プリミティブが動作に関与していることになります) → この時点で一旦 pLaTeX 2018/03/09 としてリリース済み。plarray パッケージの方も同じく開発版は LaTeX 本来の動作に近づいていますが,問題は tex-jp-build リポジトリの inhibitglue_flag ブランチ又は inhibit_flag_list ブランチの修正を適用した場合です。適用前は消えていたはずの「l,c,r の時の冒頭の JFM グルー」が適用後は消えなくなるようで,理由が分かりません。
適用前は消えていたはずの「l,c,r の時の冒頭の JFM グルー」が適用後は消えなくなる
ちょっと試してみましたが,こちらではいまいち再現できていません.どういう状況でしょう?
すみません,p の時の間違いです。 aminophen/platex-tools@ac13b7f の時点の plarray.sty をカレントディレクトリに置いた状態で, plarray-01-tabglue.tex をコンパイルした結果で再現可能と思います。
p の時の間違い
なるほど.\pltx@next@inhibitglue が \everypar の先頭で \inhibitglue を実行するのが原因だと思います.
\protected\def\pltx@next@inhibitglue{%
\ifhmode\inhibitglue\else
\edef\@tempa{\everypar{%
\everypar{\unexpanded\expandafter{\the\everypar}}%
\unexpanded\expandafter{\the\everypar}\inhibitglue}}%
\@tempa\fi}
と,\inhibitglue の実行箇所を最後にもってくるのはどうでしょう?(なぜ最初にしたんだっけ?>過去の自分)
platex 2018-03-09 で
\begin{tabular}{|p{3zw}|}
\rlap{\tiny\ttfamily\edef\@tempa{\the\everypar}\meaning\@tempa}\\
\end{tabular}
によって \pltx@next@inhibitglue によってどう \everypar が変わるかを調べてみると
\inhibitglue \everypar {\vrule \@height \ht \@arstrutbox \@width \z@ \everypar {}}
\vrule \@height \ht \@arstrutbox \@width \z@ \everypar {}
となり,\vrule によって前の \inhibitglue が無効化されていることがわかります.
\inhibitglue の実行箇所を最後にもってくる
おお,これで全て解消しそうです。 aminophen/platex-tools#7 (tabular 内で \hspace した場合の非互換) の方も,\removejfmglue マクロ (これは e-pTeX 新設の \lastnodesubtype プリミティブが活躍) を使えば解消することができていますし,非常に喜ばしい結果です。
2018-03-16 付けで pLaTeX2e <2018/03/09>+1
として出し,
\pltx@next@inhibitglue が \everypar の先頭で \inhibitglue を実行するのが原因 [...] \inhibitglue の実行箇所を最後にもってくる
をリリースに含めました。platex-tools もリリースしておきました。ひとまず完了とします。
pdfLaTeX / LuaLaTeX と pLaTeX で,次のような組版結果の違いが生じることに気づきました。おそらく #43 の副作用かと思われますが,ひとまずご報告まで。
ソース
pdfLaTeX / LuaLaTeX での組版結果
pLaTeX での組版結果
このように,pLaTeX で組版すると,空行が空きます。