和田 勇 さま、みなも さま
私の下手な思い付きに応答をしてくださいまして、本当にありがと
うございます。
結局のところ、「的外れ」だったようです…(すいません)。
お二方ともお忙しいところご協力を賜り、本当にありがとうござい
ました。
(和田さん、みなも さん以外にもお手元で試してくださった方が
いらっしゃいましたら、その皆さまにも御礼とお詫びを申し上げ
ます)
(Markdownだとコードブロックなのに `<`, `>` が勝手に変換されてしまうのでプレーンテキストに変更)
> \eqno がある場合、\aftergroup の引数(というのでしょうか)は
> どこに移動することになるのでしょう?
最小化していくと以下のようになるようです。
```
%#!etex
\def\ignorefalse{\global\let\ifignore\iffalse}
\def\ignoretrue {\global\let\ifignore\iftrue}
\everydisplay={\aftergroup\ignoretrue \aftergroup\ignorespaces}
\everymath={\aftergroup\ignorefalse}
\parindent0pt
\tracingonline=1
\tracingmacros=2
\tracingcommands=3
\tracinggroups=1
\tracingnesting=2
Test
$$
% entering math shift group (level 1)
% \everydisplay->\aftergroup \ignoretrue \aftergroup \ignorespaces
1+1=2
\eqno
% entering math shift group (level 2)
% \everymath->\aftergroup \ignorefalse
...(1)
$$
% leaving math shift group (level 2)
% leaving math shift group (level 1)
% \ignoretrue ->\global \let \ifignore \iftrue
% \ignorespaces
% \ignorefalse ->\global \let \ifignore \iffalse <- !!
% blank space <- extra space
space.\par
space.\par
\tracingonline=0
\tracingmacros=0
\tracingcommands=0
\tracinggroups=0
\tracingnesting=0
\bye
```
`\aftergroup` でされたトークンはその時点のグループが終了したときに入力の先頭に挿入されます。(挿入されるだけで展開や実行はされない。)複数の `\aftergroup` があったときは実行された順に入力の先頭から並ぶように挿入されます。
閉じの `$$` のところでは `$$` のグループ(level 1)と `\eqno` のグループ(level 2)の両方が終了します。
まず、`\eqno` のグループ(level 2)が終了し、このグループで `\aftergroup` された `\ignorefalse` が入力の先頭に挿入されます。(この時点では `\ignorefalse` は展開・実行されません。)
次に、`$$` のグループ(level 1)が終了し、このグループで `\aftergroup` された `\ignoretrue\ignorespaces` が入力の先頭(つまり `\ignorefalse` の手前)に挿入されます。
結果として、`$$` 終了時点で、入力の先頭は `\ignoretrue\ignorespaces\ignorefalse` という状態になります。
このため、`\ignorespaces` の後ろに `\ignorefalse`(`\global\let`)が来るので、後続のスペースが無視されないということになります。
> \eqno がある場合、\aftergroup の引数(というのでしょうか)は
> どこに移動することになるのでしょう?
最小化していくと以下のようになるようです。
```
%#!etex
\def\ignorefalse{\global\let\ifignore\iffalse}
\def\ignoretrue {\global\let\ifignore\iftrue}
\everydisplay={\aftergroup\ignoretrue \aftergroup\ignorespaces}
\everymath={\aftergroup\ignorefalse}
\parindent0pt
\tracingonline=1
\tracingmacros=2
\tracingcommands=3
\tracinggroups=1
\tracingnesting=2
Test
$$
% entering math shift group (level 1)
% \everydisplay->\aftergroup \ignoretrue \aftergroup \ignorespaces
1+1=2
\eqno
% entering math shift group (level 2)
% \everymath->\aftergroup \ignorefalse
...(1)
$$
% leaving math shift group (level 2)
% leaving math shift group (level 1)
% \ignoretrue ->\global \let \ifignore \iftrue
% \ignorespaces
% \ignorefalse ->\global \let \ifignore \iffalse <- !!
% blank space <- extra space
space.\par
space.\par
\tracingonline=0
\tracingmacros=0
\tracingcommands=0
\tracinggroups=0
\tracingnesting=0
\bye
```
`\aftergroup` でされたトークンはその時点のグループが終了したときに入力の先頭に挿入されます。(挿入されるだけで展開や実行はされない。)複数の `\aftergroup` があったときは実行された順に入力の先頭から並ぶように挿入されます。
閉じの `$$` のところでは `$$` のグループ(level 1)と `\eqno` のグループ(level 2)の両方が終了します。
まず、`\eqno` のグループ(level 2)が終了し、このグループで `\aftergroup` された `\ignorefalse` が入力の先頭に挿入されます。(この時点では `\ignorefalse` は展開・実行されません。)
次に、`$$` のグループ(level 1)が終了し、このグループで `\aftergroup` された `\ignoretrue\ignorespaces` が入力の先頭(つまり `\ignorefalse` の手前)に挿入されます。
結果として、`$$` 終了時点で、入力の先頭は `\ignoretrue\ignorespaces\ignorefalse` という状態になります。
このため、`\ignorespaces` の後ろに `\ignorefalse`(`\global\let`)が来るので、後続のスペースが無視されないということになります。
# みなも さんを差し置いて(?)、私が反応してしまってもよいも
# のか、若干躊躇しますが。
はやて (h20y6m) さん、詳しいご説明をありがとうございます!
> 最小化していくと以下のようになるようです。
\eqno のところで math shift していて、そこで \everymath が入
るのですか!!!
(で、gh/886 対応でも、inline math の後ろではスペースが削られ
ないように \everymath では \@ignorefalse にしてあったので、そ
れが利いているわけですね)
(それにしても、gh/886 対応の際に、\eqno が入る可能性は想定さ
れてなかったのですかね…?)
一応手元でも \tracingcommands で処理を追うくらいのことはして
みていたのですけれど、ご投稿を最初拝見した際には:
「\tracingcommands が 3?」「\tracinggroups?」「\tracingnesting?」
と少々戸惑いましたが、e-TeX でいろいろ追加されてたのですね。
(私は TeXbook レベルの show と tracing しか頭にありませんで
した…)
今回の件は、私の手元では試すこともできないことでしたが、丁寧
にご説明をしていただき、とても勉強になりました。本当にありが
とうございました。
# のか、若干躊躇しますが。
はやて (h20y6m) さん、詳しいご説明をありがとうございます!
> 最小化していくと以下のようになるようです。
\eqno のところで math shift していて、そこで \everymath が入
るのですか!!!
(で、gh/886 対応でも、inline math の後ろではスペースが削られ
ないように \everymath では \@ignorefalse にしてあったので、そ
れが利いているわけですね)
(それにしても、gh/886 対応の際に、\eqno が入る可能性は想定さ
れてなかったのですかね…?)
一応手元でも \tracingcommands で処理を追うくらいのことはして
みていたのですけれど、ご投稿を最初拝見した際には:
「\tracingcommands が 3?」「\tracinggroups?」「\tracingnesting?」
と少々戸惑いましたが、e-TeX でいろいろ追加されてたのですね。
(私は TeXbook レベルの show と tracing しか頭にありませんで
した…)
今回の件は、私の手元では試すこともできないことでしたが、丁寧
にご説明をしていただき、とても勉強になりました。本当にありが
とうございました。
> \eqno のところで math shift していて、そこで \everymath が入
> るのですか!!!
The TeXbook にもちゃんと書かれていました…:
p. 293 (Chapter 26: Summary of Math Mode)
■〈eqno〉〈math mode material〉|$|. Here〈eqno〉stands for either |\eqno| or |\leqno|;
these commands are allowed only in display math mode. Upon reading〈eqno〉, TeX
enters a new level of grouping, inserts the |\everymath| tokens, and enters non-display
math mode to put the〈math mode material〉into a math list. When that math list is
completed, TeX converts it to a horizontal list and puts the result into a box that will
be used as the equation number of the current display. The closing |$| token will be put
back into the input, where it will terminate the display.
ただ、この説明だけだと、必ずしも:
% leaving math shift group (level 2)
% leaving math shift group (level 1)
% \ignoretrue ->\global \let \ifignore \iftrue
% \ignorespaces
% \ignorefalse ->\global \let \ifignore \iffalse
という風にグループが連続して閉じるというのは、すぐには分から
ないような気もしないではないのですけれど。
(素朴に考えると:
% leaving math shift group (level 2)
% \ignorefalse ->\global \let \ifignore \iffalse
% leaving math shift group (level 1)
% \ignoretrue ->\global \let \ifignore \iftrue
% \ignorespaces
という順番になりそうに思えてしまいますので)
(その辺り、simple group や semi simple group と、math shift group
とでは、振舞いが違うのでしょうかね)
> るのですか!!!
The TeXbook にもちゃんと書かれていました…:
p. 293 (Chapter 26: Summary of Math Mode)
■〈eqno〉〈math mode material〉|$|. Here〈eqno〉stands for either |\eqno| or |\leqno|;
these commands are allowed only in display math mode. Upon reading〈eqno〉, TeX
enters a new level of grouping, inserts the |\everymath| tokens, and enters non-display
math mode to put the〈math mode material〉into a math list. When that math list is
completed, TeX converts it to a horizontal list and puts the result into a box that will
be used as the equation number of the current display. The closing |$| token will be put
back into the input, where it will terminate the display.
ただ、この説明だけだと、必ずしも:
% leaving math shift group (level 2)
% leaving math shift group (level 1)
% \ignoretrue ->\global \let \ifignore \iftrue
% \ignorespaces
% \ignorefalse ->\global \let \ifignore \iffalse
という風にグループが連続して閉じるというのは、すぐには分から
ないような気もしないではないのですけれど。
(素朴に考えると:
% leaving math shift group (level 2)
% \ignorefalse ->\global \let \ifignore \iffalse
% leaving math shift group (level 1)
% \ignoretrue ->\global \let \ifignore \iftrue
% \ignorespaces
という順番になりそうに思えてしまいますので)
(その辺り、simple group や semi simple group と、math shift group
とでは、振舞いが違うのでしょうかね)
> simple group や semi simple group と、math shift group
> とでは、振舞いが違うのでしょうかね
なんて言ってないで、自分でやってみれば良いのですよね:
------------------------------------------------------------
(1)simple groups
\def\cmdX{ddd }
\def\cmdY{ccc }
{\aftergroup\cmdX aaa {\aftergroup\cmdY bbb }}
% ---> aaa bbb ccc ddd
{begin-group character {}
{entering simple group (level 1) at line 9}
{\aftergroup}
{the letter a}
{begin-group character {}
{entering simple group (level 2) at line 9}
{\aftergroup}
{the letter b}
{end-group character }}
{leaving simple group (level 2) entered at line 9}
{the letter c}
{end-group character }}
{leaving simple group (level 1) entered at line 9}
{the letter d}
------------------------------------------------------------
(2)\eqno in display math
\def\cmdX{ddd }
\def\cmdY{ccc }
\everydisplay={\aftergroup\cmdX}
\everymath={\aftergroup\cmdY}
$$aaa \eqno bbb $$
% ---> aaa bbb
% ddd ccc
{math shift character $}
. . .
{endgroup}
{leaving semi simple group (level 2) entered at line 11}
{\relax}
{\let}
{\def}
{\aftergroup}
{the letter a}
{the letter a}
{the letter a}
{blank space }
{\eqno}
{entering math shift group (level 2) at line 11}
{math mode: \let}
{\def}
{\aftergroup}
{the letter b}
{the letter b}
{the letter b}
{blank space }
{math shift character $}
{leaving math shift group (level 2) entered at line 11}
{leaving math shift group (level 1) entered at line 11}
{horizontal mode: the letter d}
{blank space }
{the letter c}
------------------------------------------------------------
素朴な想定とは異なるのですけれど、これまでの流れからしたら、
こういう結果になるというのは、当然とも言えそうです。
> とでは、振舞いが違うのでしょうかね
なんて言ってないで、自分でやってみれば良いのですよね:
------------------------------------------------------------
(1)simple groups
\def\cmdX{ddd }
\def\cmdY{ccc }
{\aftergroup\cmdX aaa {\aftergroup\cmdY bbb }}
% ---> aaa bbb ccc ddd
{begin-group character {}
{entering simple group (level 1) at line 9}
{\aftergroup}
{the letter a}
{begin-group character {}
{entering simple group (level 2) at line 9}
{\aftergroup}
{the letter b}
{end-group character }}
{leaving simple group (level 2) entered at line 9}
{the letter c}
{end-group character }}
{leaving simple group (level 1) entered at line 9}
{the letter d}
------------------------------------------------------------
(2)\eqno in display math
\def\cmdX{ddd }
\def\cmdY{ccc }
\everydisplay={\aftergroup\cmdX}
\everymath={\aftergroup\cmdY}
$$aaa \eqno bbb $$
% ---> aaa bbb
% ddd ccc
{math shift character $}
. . .
{endgroup}
{leaving semi simple group (level 2) entered at line 11}
{\relax}
{\let}
{\def}
{\aftergroup}
{the letter a}
{the letter a}
{the letter a}
{blank space }
{\eqno}
{entering math shift group (level 2) at line 11}
{math mode: \let}
{\def}
{\aftergroup}
{the letter b}
{the letter b}
{the letter b}
{blank space }
{math shift character $}
{leaving math shift group (level 2) entered at line 11}
{leaving math shift group (level 1) entered at line 11}
{horizontal mode: the letter d}
{blank space }
{the letter c}
------------------------------------------------------------
素朴な想定とは異なるのですけれど、これまでの流れからしたら、
こういう結果になるというのは、当然とも言えそうです。
LaTeX2e 2023-06-01 で修正されたようです。
- ltnews37, p.5, “ignoring space after $$”.
- latex3/latex2e#1059