Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ptex] \inhibitglue の効力 #28

Closed
h-kitagawa opened this issue Sep 19, 2017 · 32 comments

Comments

@h-kitagawa
Copy link
Member

commented Sep 19, 2017

ZRさんがつぶやかれていますが,pTeX では

あ\inhibitglue\relax「
あ\inhibitglue\@ifnextchar[{}{}「

のような場合に,の前側に半角空きが入るようになっています.

pTeX の挙動を調べてみると,あ\inhibitglue\relax「 の場合では次のようになっています.

  • あ\inhibitglue の直後は和文文字でない \relax なので,JFM グルーの挿入はそこで中断される
  • そのときに inhibitglue が有効か否かのフラグはリセットされる
  • 従って,その後のを処理する過程で「文字クラス0の文字」との間に入る半角空きがそのまま入る

一応.ptex-base.ch の

skip_loop: inhibit_glue_flag:=false;

skip_loop: do_nothing;

に変えれば解決しますが,

あ\inhibitglue\copy0「
あ\inhibitglue\discretionary{}{}{}「

のような場合に \inhibitglue がリセットされない副作用があるので,どうすればよいか悩み中です.

@aminophen

This comment has been minimized.

Copy link
Member

commented Sep 20, 2017

「non-discardable ノードが間に入れば無効」になるのが私は自然と思うのですが,難しいのでしょうか?

(正直なところ,2013年の「和文文字がくるまでどこまでも波及する」よりは今の方がマシ,というくらいにしか考えたことがなかったので,なにが理想的かという認識は皆さんと合っていないかもしれません。)

@zr-tex8r

This comment has been minimized.

Copy link

commented Sep 21, 2017

  • inhibitglueはJFMグルーに作用するもの
  • JFMグルーは和文クラスの判定と密接に関連する
  • 和文クラスの判定は展開不能なトークンを透過しない

だから

  • inhibitglueは展開不能なトークンを透過しない

というのはそれで一貫している、という気もしますね。

@aminophen

This comment has been minimized.

Copy link
Member

commented Sep 21, 2017

すみません,「和文クラス」ってなんでしたっけ?(その用語から私は jsclasses とかに文書クラスを連想してしまいましたが,正しい意味はアスキーの文献のどれかに出ているのでしょうか?)

@zr-tex8r

This comment has been minimized.

Copy link

commented Sep 21, 2017

おっと失礼。「和文クラス」じゃなくて「(和文)文字クラス」でしたね。

ただこれも本当はJIS X 4051やJLREQの用語であって、pTeXの正しい用語は「文字タイプ」なのかも。

@aminophen

This comment has been minimized.

Copy link
Member

commented Feb 24, 2018

@zr-tex8r さん

  • inhibitglueはJFMグルーに作用するもの
  • JFMグルーは和文クラスの判定と密接に関連する
  • 和文クラスの判定は展開不能なトークンを透過しない

だから

  • inhibitglueは展開不能なトークンを透過しない

どうもそういうわけでもなさそうな感じがしますが,私の思い違いでしょうか?

%#!ptex
あ)\inhibitglue (あ\par             % ベタ
あ)\relax\inhibitglue (あ\par       % 二分アキ
あ)\inhibitglue\relax (あ\par       % 二分アキ
あ)\relax\inhibitglue\relax (あ\par % 二分アキ:なぜ?
あ)\relax (あ\par                   % 全角アキ

あ)\inhibitglue (あ\par             % ベタ
あ)\null\inhibitglue (あ\par        % 二分アキ
あ)\inhibitglue\null (あ\par        % 二分アキ
あ)\null\inhibitglue\null (あ\par   % 二分アキ:なぜ?(全角アキを期待)
あ)\null (あ\par                    % 全角アキ

\bye

あ)\relax\inhibitglue\relax (あ\par % 二分アキ
あ)\null\inhibitglue\null (あ\par % 二分アキ

は,「\inhibitglue が,展開不能なトークンを透過している」ことになると思います。

@h-kitagawa

This comment has been minimized.

Copy link
Member Author

commented Feb 24, 2018

\inhibitglue が,展開不能なトークンを透過している

まだほとんど調べられていませんが,\null\vrule などのノード挿入で inhibit_glue_flag がリセットされないのだと思います.

@aminophen

This comment has been minimized.

Copy link
Member

commented Feb 24, 2018

[書き直し]

inhibitglue_flag ブランチを作ってみました。現状 aba351a では

あ)\null\inhibitglue\null (あ
あ)\vrule\inhibitglue\vrule (あ
あ)\discretionary{}{}{}\inhibitglue\discretionary{}{}{}(あ

で \inhibitglue が後続の展開不能トークンを透過する問題を解消しています(★)。一方,

あ)\relax\inhibitglue\relax (あ

は直し方がわからなかったのでそのままです。

(一旦 72b9cdb では,この issue の最初の @h-kitagawa さんのコメントにある

一応.ptex-base.ch の
skip_loop: inhibit_glue_flag:=false;

skip_loop: do_nothing;
に変えれば解決しますが,

の変更も適用してみたのですが,そうすると )\relax ( で全角アキが入る(=文字タイプ判定は展開不能トークンを透過しない)のと辻褄が合わないので元に戻しました。

あ\inhibitglue\copy0「
あ\inhibitglue\discretionary{}{}{}「
のような場合に \inhibitglue がリセットされない副作用があるので,

の副作用は,上記(★)の時点でそもそも起きなくなっています)

@aminophen

This comment has been minimized.

Copy link
Member

commented Feb 24, 2018

あ)\relax\inhibitglue\relax (あ でも \inhibitglue が透過しないようにしてみました。他もいろいろ直しました。結果として,inhibitglue_flag ブランチの変更内容 (704ac75...ad5aa61) によって挙動が変わる部分を,tests/inhibitglue.tex の中に【修正】とコメントをつけました。

@h-kitagawa

This comment has been minimized.

Copy link
Member Author

commented Feb 24, 2018

\unhbox, \unhcopy のときにも \inhibitglue が透過しないようにしました.
しかし,このように透過しない場合を潰していく方針だときりがない気もしています.

@aminophen

This comment has been minimized.

Copy link
Member

commented Feb 24, 2018

\unhbox, \unhcopy のときにも \inhibitglue が透過しないようにしました.

抜けていました。ありがとうございます。

透過しない場合を潰していく方針だときりがない

確かにそうなんですよね… まだ penalty はどうなのか?とか残っている気が。根本的に別の方法も考えた方がいいのかもしれない?


ところで,本題の「展開不能なトークンを透過しない」という挙動はそれで良いのでしょうか。

  • inhibitglueはJFMグルーに作用するもの
  • JFMグルーは和文クラスの判定と密接に関連する
  • 和文クラスの判定は展開不能なトークンを透過しない

だから

  • inhibitglueは展開不能なトークンを透過しない

に従えば「妥当」ともいえます。(この考えを支持して漏れを排除したのが inhibitglue_flag ブランチ。)

が,実際は \inhibitglue は JFM グルーを消したい時に発行するものなので,\relax とか代入のようにノードを作らないものまで非透過だと,「不便」ではあるのですよね。

@aminophen

This comment has been minimized.

Copy link
Member

commented Feb 24, 2018

「実際は \inhibitglue は JFM グルーを消したい時に発行するもの」

[edit] 実装内容と名前から考えると,「JFM グルーを消す」ではなく「JFM グルーの自動挿入ルーチンを抑制する」ものと考えるべきな気がしてきましたが,とりあえず「消す」で考えてみる。

\relax とか代入のように「ノードを作らないものは透過させる」,「発行時点で最後のノードが JFM グルーならそれも消す」という方針で作ってみると,今度は inhibitglue_flag_subst ブランチ (b224a68) のようになります。こうすると,plarray.sty の tabular 環境で制約になっているこの件が自動的に解消します。

# 末尾の JFM グルーを「消す」方法がわからなかったので,消さずに「ゼロにする」という実装に成っていますが,まあ例示ということで。

[edit] b224a68 の実装だと, あ){\inhibitglue}(あ で完全にグルーが消されますね。最後の JFM グルーを無条件に消したり,グルーピングが効かなかったりしている?

[edit] #52 ができたので,この提案は取り下げ。

@aminophen

This comment has been minimized.

Copy link
Member

commented Feb 27, 2018

inhibitglue_flag ブランチですが,私が気づいている未対策残りは

  • mark_node
  • insert_node
  • adjust_node
  • グルーピング

です。「透過しない場合を潰していく方針」なので手間がかかりますが,私はほかの方法が思いついていないのでとりあえず潰してみようと思います。

@aminophen

This comment has been minimized.

Copy link
Member

commented Feb 27, 2018

mark_node, insert_node, adjust_node は対策を入れました。あとはグルーピングなのですが,どこを変更するのがよいか(安全か)よくわからなかったので未達です。

@aminophen

This comment has been minimized.

Copy link
Member

commented Feb 27, 2018

このコメントに書きましたが,pLaTeX の \@classv マクロは

水\hbox{あ}\inhibitglue\ignorespaces (あ で \inhibitglue がなぜかリセットされない

という pTeX の挙動に依存していることがわかりました。\ignorespaces 自体も直後のトークンだけに作用できるプリミティブなので,\ignorespaces\inhibitglue という順序で発行する手も封じられています。

そうなると,一連の \inhibitglue の挙動変更のうち f932384ignore_spaces の部分だけは元に戻した方が良いでしょうか?

@aminophen

This comment has been minimized.

Copy link
Member

commented Feb 27, 2018

\inhibitglue がトークンを透過するかどうか,ありえる案をいろいろ挙げてみます。

  • とにかく「展開不能トークンやグループはいかなる場合も非透過」を徹底する。
    • JFM グルー/カーン挿入処理も「いかなる場合も非透過」なので,これと同じで綺麗(?)。
    • 現状の 2ef0eb9 時点では,あとはグループだけで済む(はず)。
    • しかし,\ignorespaces も「いかなる場合も非透過」になるので,pLaTeX の tabular 環境の \@classv が (texjporg/platex#63 を含めて) 破綻する。
  • 「展開不能トークンを“時々”透過する」ことを仕様と定め,現状維持+ドキュメント化する。
    • pLaTeX の tabular 的には“とりあえずいけないことはない”が,pTeX の挙動に一貫性が全くない。
  • 「展開不能トークンのうちノードを作らないものは透過,それ以外は非透過」に変更する。
    • つまり,代入とか \relax とか \ignorespaces が透過になる。
    • ただ,「\relax は非透過」というのは「知っている人は知っている」くらいには既知の話なので,変更すると影響が出るかもしれない。
  • 「展開不能トークンのうち \ignorespaces だけは例外的に透過,それ以外は非透過」に変更する。
    • 要するに f932384 の ignore_spaces の条件だけを元に戻し,さらに別のどこかの ignore_spaces 絡みの処理もフラグリセットを除去する。
    • \inhibitglue と \ignorespaces の「どちらか一方しか直後のトークンに作用できない」という制約を取っ払うためには必要最低限,という論理にする。
@h-kitagawa

This comment has been minimized.

Copy link
Member Author

commented Feb 27, 2018

む…….個人的には「ノードを作らないものは透過」推しです.その論理はまだモヤっとしていますが,次のような感じでしょうか.

  • 「次の空白に影響を与える」という点では,\spacefactor\inhibitglue は似ている
  • \spacefactor はノード追加で 1000 に戻されたり \sfcode 値に設定されたりする
  • そもそも「いかなる場合も非透過」では使い方が非常に制限されてしまう(もともと \lastnodechar も,JFM グルー挿入が非透過であることが原因で作られた命令)
@aminophen

This comment has been minimized.

Copy link
Member

commented Feb 28, 2018

「ノードを作らないものは透過」推し

私も +1 します.

単純な疑問:空のボックスを unbox するとノードにならないんでしたっけ?(もしそうだとすると,空かどうかで分岐が必要?)

@h-kitagawa

This comment has been minimized.

Copy link
Member Author

commented Feb 28, 2018

空のボックスを unbox するとノードにならない

その場合,ノードは何も追加されません.

@aminophen

This comment has been minimized.

Copy link
Member

commented Feb 28, 2018

なるほど,ありがとうございます。

@aminophen

This comment has been minimized.

Copy link
Member

commented Feb 28, 2018

71e47a2 で,ノードを作らないものを透過にする方向で始めました。

  • 例えば水平モードで \inhibitglue \relax ( はグルーが消えます。\relax 以外にも \ignorespaces\let の代入文などが透過です。
  • 現状 あ)\relax \inhibitglue のグルーが消えませんが,対策を講じていません。
    • これは \inhibitglue 実行時点で既に TYPE 2 - TYPE 0 間のグルー挿入ルーチンが完了しているため,グルー挿入ルーチン抑制フラグが「時既に遅し」だからです。
    • もし対策をとるならば, b224a68do_inhibit_glue に似たことを(グルーをゼロにするのではなくちゃんと消して)やればいいはずです。
    • → 対策をとれば \removejfmglue マクロ (texjporg/platex#65) がそもそも不要になるのではないかとも思いますが,既に挿入されたグルーを消すことは従来の \inhibitglue に存在しなかった効果なので,是非は慎重に検討すべきです。
  • unbox されるボックスが空の場合はノードを作らないので,これも透過とすべきだと思いますが,やり方がわからなかったので触っていません。
    • if p=null then return; の前の inhibit_glue_flag:=false; を後ろにすればいいだけ,だと思ったのですが,どうもそれでも空(のはず)の場合のリセットが効かない?
  • \inhibitglue をグループ境界でどう波及・リセットさせるのかはまだ考えていません。
@aminophen

This comment has been minimized.

Copy link
Member

commented Feb 28, 2018

  • unbox されるボックスが空の場合はノードを作らないので,これも透過とすべき

016086c のコミットで出来た気がしますが,自信がないので別ブランチ (inhibitglue_flag_unpackage) にしました。大丈夫そうだったら inhibitglue_flag ブランチにマージしていただけると助かります。

@h-kitagawa

This comment has been minimized.

Copy link
Member Author

commented Mar 1, 2018

次のテストソースで調べてみました:

\obeylines
1あ\inhibitglue(
2あ{\inhibitglue}(
3あ\inhibitglue\setbox0=\hbox{}(
4あ\setbox0=\hbox{}\inhibitglue(
5あ\setbox0=\hbox{\inhibitglue}(
\bye

5 で \inhibitglue が有効になっていますが,これは「\inhibitglue はリスト境界もまたぎうる」という状況です.3 で無効になっているのも同じように気になり,どちらの状況も(\spacefactor との類似で考えても)ちょっと不自然な気がしています.

現状の pTeX では \inhibitglue が有効は否かは1つのグローバル変数に格納されていますが,
リストごとに「このリストの現在の位置では有効/無効」の情報をもたせたいな,と考えています.

  • リセット箇所は \spacefactor とほぼ同じ箇所でやればよい(と勝手な推測)
  • 多忙のため,上記の仕様変更が TeX Live 2018 に間に合わせられるかどうかちょっと心配
@aminophen

This comment has been minimized.

Copy link
Member

commented Mar 1, 2018

「\inhibitglue はリスト境界もまたぎうる」
ちょっと不自然な気がしています.

同感です。私事ですが,今後特に多忙につき,十分な調査ができません。\inhibitglue の仕様変更が全確定してからコミットしたいというのが個人的な意見で,\lastnodesubtype さえあれば pLaTeX / plarray.sty 的にはどうにかなりますので,2018 を意識しすぎずじっくりでもよいと思います。

(メモ)pLaTeX は texjporg/platex@74502bc で,plarray.sty は aminophen/platex-tools@ac13b7f で,それぞれ TeX Live r46772 時点で期待通りに動きました。

@aminophen

This comment has been minimized.

Copy link
Member

commented Mar 12, 2018

Fix a bug that \inhibitglue is not reset by a jfm glue (1d035a8)

このコミットで再び \relax などノードを作らないトークンが非透過になっているようです。

"not reset by a jfm glue" というよりは,たぶん「文字ノードがフラグをリセットすべきところが抜け落ちている」という表現がより正確なのだと気がします。

@h-kitagawa

This comment has been minimized.

Copy link
Member Author

commented Mar 13, 2018

このコミットで再び \relax などノードを作らないトークンが非透過になっているようです。

一旦 revert し,別方針で実装したものを e5b914f におきました.

  • inhibit_glue_flag_field が integer 型になっていますが,これは修正過程のゴミなので,revert しても構いません.
  • cur_l(halfword 型)の変数の値が「後ろの文字の文字クラス」を示すので,展開不能トークンの場合は一旦 qi(-1) とし,それによって「後ろが(文字クラス0の or 欧文)文字」「後ろが展開不能トークン」の場合を区別するようにしました.
  • 分かりづらいですが,「)\inhibitglue\relax (」では字間がベタになります.これは次のようになっています.
    • )\inhibitglue\relax で閉じ括弧-\relax 間の空白挿入が抑制される
    • \relax は展開不能トークなので, \inhibitglue はリセットされない
    • そのため, \relax-開き括弧間の空白挿入が抑制されたまま
@aminophen

This comment has been minimized.

Copy link
Member

commented Mar 13, 2018

別方針で実装したものを e5b914f

期待どおり動いているように見えますね。もう少しテストしてみます。

さて,もっと議論してからとすべきか,TL18 pretest に早く送り込むべきか…

@h-kitagawa

This comment has been minimized.

Copy link
Member Author

commented Mar 18, 2018

さて,もっと議論してからとすべきか,

どうしましょうかね.「ノードを作らないものは透過」という方針からは,上のコメントのように

)\inhibitglue\relax (

の字間がベタになるのは納得できますが,その一方でどこか落ち着かない自分がいます.
一つの \inhibitglue が結果的に二つのグルーの挿入処理に効力を発揮しているからなのでしょうか.

  • \inhibitglue の効果を無効化する命令があってもよいという気がしてきました.良い名前が思いつきませんが,\disinhibitglue とか?
  • もし送り込む場合はバージョンを 3.8.1 に上げた方が良いと思います.
@aminophen

This comment has been minimized.

Copy link
Member

commented Mar 18, 2018

確かに )\inhibitglue\relax ( でベタになってしまうと,一つの \inhibitglue が二回の glue/kern 挿入ルーチンを抑制していることになり,私もその気持ち悪さがあります。「一度 glue/kern 挿入ルーチンを抑制する効力を発揮したら,フラグをリセットする」ではどうでしょう? 試せていませんが

if inhibit_glue_flag<>true then

のところを

if inhibit_glue_flag=true then inhibit_glue_flag:=false else

みたいにすれば,その通りに成りそうな予感があります。

@aminophen

This comment has been minimized.

Copy link
Member

commented Mar 18, 2018

↑ と思ったのですが,glue/kern 挿入ルーチン (Look ahead for ... のメイン部分) は glue/kern 設定の有無に関わらず呼ばれるのでした。個人的には「)\inhibitglue\relax ( でベタ」は二回抑制されるのが目に見えて少々気持ち悪いですが,「あ\inhibitglue\relax ( でベタ」だと気持ち悪さが半減します。

@aminophen

This comment has been minimized.

Copy link
Member

commented Feb 6, 2019

r49958 で TeX Live svn にコミット。

\inhibitglue の挙動変更はユーザにも影響が出うるので,フォーラムにも書き込みました。

@aminophen

This comment has been minimized.

Copy link
Member

commented Feb 6, 2019

あとは,ptex-manual に新仕様について追記するまでは open にしておきます。

@h-kitagawa

This comment has been minimized.

Copy link
Member Author

commented Feb 9, 2019

d7add6a で追記.>ptex-manual に新仕様について

@aminophen aminophen closed this Feb 12, 2019

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
3 participants
You can’t perform that action at this time.