\prerelpenalty, \prebinoppenalty の導入?

- でび まる の投稿
返信数: 11

でびまる といいます。以前、インライン数式での改行について質問し、
https://okumuralab.org/tex/mod/forum/discuss.php?d=4033
で、LuaTeX には `\prerelpenalty`、`\prebinoppenalty` が定義されていて、二項演算子や関係記号の前での改行を設定できることを教えていただきました。

個人的にはほぼ LuaTeX のみを利用しているので、これで十分ではあるのですが、LuaTeX にこのような仕組みが用意されているということは、「演算子の前での改行」という方向も、TeX の仕組みとして考えられているのだと思います。

そこで、LuaTeX ではない通常の TeX でも、同様に `\prerelpenalty`、`\prebinoppenalty`(あるいはそれに相当する仕組み)が利用できるようになればと思っています。

少しだけ `\ifprimitive` を用いて調べてみたところ、LuaTeX では `\prerelpenalty`、`\prebinoppenalty` はプリミティブとして定義されているようです(この理解で合っているか、少し自信がありません)。

これらを LuaTeX 以外の TeX でも利用できるようにすることは可能でしょうか。あるいは、同等の機能を実現する方法があればご教示いただけると幸いです。

よろしくお願いします。

でび まる への返信

Re: \prerelpenalty, \prebinoppenalty の導入?

- しっぽ 愛好家 の投稿

>LuaTeX にこのような仕組みが用意されているということは、「演算子の前での改行」という方向も、
>TeX の仕組みとして考えられているのだと思います。

逆です.そのようなことは TeX 自身としては考えていないため,LuaTeX が独自に(あるいは勝手に)
追加しているのです.

どうしてもやりたければ,大雑把なやり方でよければ二項演算子・関係演算子を出力するコマンドを
再定義して(単一の文字の場合には \mathcode を "8000 にして,アクティブにした文字を定義),
前側に適当な penalty を追加するという手が考えられるでしょう.
# もっとも,「a\ (> 0)」なんて記述の「(」「>」の間での行分割も起こりかねないので,
# まともにやるには数式を改めて解析して penalty を挿入する位置を割り出すことになるでしょうけれども.

しっぽ 愛好家 への返信

Re: \prerelpenalty, \prebinoppenalty の導入?

- でび まる の投稿
> 逆です.そのようなことは TeX 自身としては考えていないため,LuaTeX が独自に(あるいは勝手に)
> 追加しているのです.

はい、「TeX 自身としては考えていない」のは理解しています。「演算子の前での改行」に変更
して欲しいのではなく、「演算子の前での改行」もオプションとして設定できる様にする方向は
あるのではないかと言うつもりです。選択の幅を広げたい訳です。

もし実装できれば、設定して不具合あれば、元に戻せば良いので大きな問題はなさそうに思います。
よろしくお願いします。
しっぽ 愛好家 への返信

Re: \prerelpenalty, \prebinoppenalty の導入?

- 本田 知亮 の投稿

単純に数式中で直前のノードを取得すれば泥縄式でいけるのかもしれません.

「+」の直前が mathopen である場合に,メッセージを出してみます.

\documentclass{jarticle}

\expandafter\def\csname prebinoppenalty@mathsubtype8\endcsname{\mbox{penalty!}}
%%%見やすいように文字にした:8 は mathopen
%%% 0から19まで頑張る


\DeclareMathSymbol{\plussymbol}{\mathbin}{operators}{"2B}
{%
\catcode`\+=\active
\gdef+{\csname prebinoppenalty@mathsubtype\the\lastnodesubtype\endcsname 
             \plussymbol}
}%
\mathcode`\+="8000\relax

\begin{document}

$a + b$

$a (+ b$

\end{document}


本田 知亮 への返信

Re: \prerelpenalty, \prebinoppenalty の導入?

- しっぽ 愛好家 の投稿

\lastnodesubtype というのが(いつの間にか)用意されているのですね.
ありがとうございます(やや古い(私の作業環境:TeX Live 2018 の)pTeX でも使えたので
ずいぶん前に導入されたようですね).

しっぽ 愛好家 への返信

Re: \prerelpenalty, \prebinoppenalty の導入?

- 本田 知亮 の投稿
トークンレベルの情報はすでに消費されていて取得できないと思うのですが
\futurelet の反対に相当する部分はそうそう困らないレベルで取得できると思います.
このあたりのeptex 拡張は toxcdoc eptex で見ることができます.
個人的には「過去を知りたい」ケースでは,ありがたいことに
これらの last 系プリミティブですべて解決しています.
本田 知亮 への返信

Re: \prerelpenalty, \prebinoppenalty の導入?

- でび まる の投稿
返信ありがとうございます。

> \expandafter\def\csname prebinoppenalty@mathsubtype8\endcsname{\mbox{penalty!}}

良く理解できてませんが直前の文字種に対応してペナルティを与える様なイメージでしょうか(違ってたら済みません)。

> %%% 0から19まで頑張る0から19まで頑張る

頑張れそうにありませんが(^^; マクロ的な方向を知ることができました。
反応は期待できないと心配でしたが、御二方も反応いただきありがとうございました。
本田 知亮 への返信

Re: \prerelpenalty, \prebinoppenalty の導入?

- 林 かぐら の投稿

本田さんのアイデアで自動化できそうですが,
・コードが少し長くなりそう
・あまりおこらなそう(?????)
なのでチェックをやめ,手動でおこなってもよいような気がします。

たとえば > の前で改行可能なモードにしているとき
(具体的には > の前に \allowbreak を入れて > を再定義します)
$a\ (> 0)$ は ( の後ろで改行する場合があります。
そのときは $a\ {(>}\; 0)$ と { } でくくればそこでの改行を抑制
できます。空きが抜けてしまったら自力で空きを入れなければならず,
ちょっと面倒ですが。もっともこの例だと $a\ {(> 0)}$ で大丈夫です。

なおついでに \* も再定義しておくとよいかもしれません。
オリジナルの定義で第1引数と第2引数を入れ替えてもうまくいきません。
\* は組んだ後に書き込むと思われるので,私は単純に
(オリジナルの定義を無視して)

\let\@times\times
\def\*{%
通常モードなら \@times\break
演算子の前で改行可能なモードなら \break\@times
}

としています。普通に書いてもよいのですが \* は2文字なので
楽に入力できるというメリットがあります。

なお

\let\@times\cdot

とできるようにしています。
\cdot だと見た目のインパクトは弱いですが。

林 かぐら への返信

Re: \prerelpenalty, \prebinoppenalty の導入?

- でび まる の投稿
反応する立場でない気もしますが、

> $a\ (> 0)$ は ( の後ろで改行する場合があります。

上の様な多少の不具合(?)は対応できそうと言うことですね。
個人的には「演算子の前での改行」が概ね実現できれば十分です。

> なおついでに \* も再定義しておくとよいかもしれません。

同じ様に改行を制御してそうですが、特別に扱う意図などがちょっと読み切れてません。
でび まる への返信

Re: \prerelpenalty, \prebinoppenalty の導入?

- 林 かぐら の投稿
私は今汎用的なマクロをいろいろ書いている(つもりでいる)のですが,
その流れでつい返信してしまいました。黙っていればいいのに。

\* について
もし使わないのなら私の内容は無視してください。

\* は TeX ブックの 173 ページ下に
discretionary multiplication sign
として載っています。私が書かなくても意味はあるのです。
林 かぐら への返信

Re: \prerelpenalty, \prebinoppenalty の導入?

- でび まる の投稿
> \* は TeX ブックの 173 ページ下に

TeXブックのみならず TeX 関係の本などが手近にない環境になってるので
「\*」記憶になくても調べられず、検索したら「\\*」がヒットしたりしてましたが
「discretionary multiplication sign」で調べて意味が分りました。
この意味が全然思い出せないのは、多分記憶がないだけでなく全く知らなかったですね。

ただの演算とは意味合いが違い、質問とは離れそうですが、とっても参考になりました。

> もし使わないのなら私の内容は無視してください。

使わない気はしますが、とても無視できませんね(^^;
ありがとうございました。
林 かぐら への返信

Re: \prerelpenalty, \prebinoppenalty の導入?

- 本田 知亮 の投稿
>なのでチェックをやめ,手動でおこなってもよいような気がします。

やっといて何なんですが,個人的には「手動」賛成です.
気になるようなケースはそれほど多くなさそうなので
ある程度の主観で整える方が読みやすいかもです.

ちなみに私は,判断基準が見た目とかに比重が大きくなりそうなときは
あえて長めのコントロールシーケンスで目立つようにマークアップします.
やっててあまりに面倒になったらあとで簡略化を考える感じです.