マクロツイーター

はてダから移行した記事の表示が崩れてますが、そのうちに直せればいいのに(えっ)

BXjscls の新しいやつ(v1.7a)

ステマ

☃︎
 
TeX & LaTeX Advent Calendar ☃︎
 

2017/12/01 〜 2017/12/25
TeXでつくるアレ〜

TeX & LaTeX アドベントカレンダー 2017

*  *  *

W32TeXTeX Live では既に更新されている。

元号に関するアレコレ

現在の TeX エンジンは SOURCE_DATE_EPOCH 指定*1の機構に対応しているので、“現在日付”が未来や過去の日付になる場合もありうる。従って、いわゆる「新元号対応」について今から考えておくのも少しは意味があるだろう。

旧版では以下のようになっていた。

  • “現在”の年が 1990 年(平成 2 年)以降の場合は「平成」の年号を出力する。
  • “現在”の年が 1989 年以前の場合は和暦指定は無効になり、西暦で出力する。

新版では以下のようになる。

  • “現在”の元号が「平成」である場合は「平成」の年号を出力する。
  • “現在”の元号が「昭和」であり、かつ 1970 年(昭和 45 年)以降である場合は「昭和」の年号を出力する。
    • 「1970 年以降」に限っているのは SOURCE_DATE_EPOCH で指定可能な“現在日付”の範囲がそうだからである。((もちろん、\year\monthTeX パラメタに直接代入すれば「1600 年」でも「13 月」でも設定できるが、それは「LaTeX の範囲外」なので考慮しない。))
  • それ以外の場合は和暦指定は無効になり、西暦で出力する。
    • 2019 年 5 月 1 日以降については、現時点で既に「平成」ではないことが確定しているが、まだ「新元号」は公布されておらず和暦表示ができないため、西暦表示になる。
日付 旧版出力 新藩出力
1983-08-08 1983 年 8 月 8 日 昭和 58 年 8 月 8 日
1989-01-01 1989 年 1 月 1 日 昭和 64 年 1 月 1 日
1989-01-18 1989 年 1 月 18 日 平成元年 1 月 18 日
1990-02-02 平成 2 年 2 月 2 日 平成 2 年 2 月 2 日
2017-12-25 平成 29 年 12 月 25 日 平成 29 年 12 月 25 日
2019-01-01 平成 31 年 1 月 1 日 平成 31 年 1 月 1 日
2019-08-08 平成 31 年 8 月 8 日 2019 年 8 月 8 日

\@ に関するアレコレ

\@ の副作用

LaTeX において、「ドット〈.〉が通常は文中のドットであると見なされる」(よって後続の空白文字は単語間空白になる)ような位置で、そのドットを強制的に文末のピリオドである(よって後続の空白文字は文末空白になる)と扱いたい場合は、\@ という命令を使う。標準の LaTeX ではこの \@ はドットの直前に置くことになっている。

\documentclass[a4paper]{article}
\usepackage{times}
\begin{document}

% "reST."の後は単語間空白
\framebox[15em][s]{Write reST. No, not Markdown.}

% "reST."の後は文末空白
\framebox[15em][s]{Write reST\@. No, not Markdown.}

\end{document}

※文末スペースの効果が識別できるようにわざと“間延びした”状況においている。

しかしこの \@ には副作用がある。それはドットと前の文字とのカーニングが無効になってしまうことである。上の例では、〈T〉とドットの間のカーニングに影響が出る。*2

\@ の副作用の対策

この副作用に対処するため、jsclasses では、\@ 命令を次のように拡張している。

  • \@ をドットの直後に置くという使い方できる。この場合は、ドットと前の文字とのカーニングが保持さえっる。
  • 従来通りドットの直前に置くこともできるが、この場合はカーニングは失われる。
  • なお、\@ はドット(ピリオド)以外の句読点についても用いられるが、「直後に置く」という使い方ができるのはドットだけである。
% upLaTeX文書
\documentclass[uplatex,a4paper]{jsarticle}% jsclassesなクラス
\usepackage{times}
\begin{document}

\framebox[15em][s]{Write reST. No, not Markdown.}

\framebox[15em][s]{Write reST\@. No, not Markdown.}

\framebox[15em][s]{Write reST.\@ No, not Markdown.}

\end{document}

新しい用法では、ピリオドの前も後ろも期待通りになっていることが判る。

\@ の副作用の対策の副作用

しかし、この \@ の拡張には問題がある。\@ のある箇所に実際には句読点が無かった場合に、副作用を生むのである。

例えば、TeX のロゴを出力する命令 \TeX の標準の実装では、最後に \@ を実行している。これにより、直後にドットを置いたときにそれが既定で文末ピリオドと認識される。((なお、グルーピングの {} は“ドットの判定”には影響しない(カーニングには影響する)。))

% これは"…X\@. It"と同等となり, "."は文末ピリオド
Keep away from {\TeX}. It's dangerous.

それでは、次のように \TeX の直後に空白文字が来た場合はどうなるか。

% これは"…X\@ lan…"と同等となる
The {\TeX} language is dangerous.

標準の LaTeX の場合は \@ の直後が句読点でないため(事実上)何も起こらない。\TeX の末尾に“予防的に”\@ を入れてよいのはこれが根拠となっている。しかし、jsclasses の拡張済の \@ の場合は話が違う。この場合、\@ は「直前が文末ピリオドであった」ように振舞う効果をもつため、予想外に空白文字が文末空白になってしまうのである。

% upLaTeX文書
\documentclass[uplatex,a4paper]{jsarticle}% jsclassesなクラス
\usepackage{times}
\begin{document}

\framebox[15em][s]{The TeX language is dangerous.}

\framebox[15em][s]{The {\TeX} language is dangerous.}

\end{document}
\@ の副作用の対策の副作用の対策

この副作用に対処するため、新版の BXJS クラスでは、\@ 命令を次のように修正した。

  • 「そこにドットがあった場合に文中ドットと見なされる(☆)」状況(典型的には英大文字の直後)で \@ が使われた場合は、jsclasses の拡張の動作を行わない。つまり、直後に空白文字が続いた場合は単語間空白になる。
    • “予防的な\@”を使うのは(☆)を満たすケースに限られるはずである。
    • 一方で、“拡張の\@”を使う場合は直前はドットであるので(☆)は満たさない。 *3
% upLaTeX文書
\documentclass[uplatex,dvipdfmx,a4paper]{bxjsarticle}% BXJSなクラス!
\usepackage{times}
\begin{document}

\framebox[15em][s]{The TeX language is dangerous.}

\framebox[15em][s]{The {\TeX} language is dangerous.}

\end{document}
fix-at-cmd オプション

もしかしたら、「\@ の実装が LaTeX 標準のもののまま変わっていない」ことに依存するパッケージ実装があるかも知れないため、\@ の再定義を抑止するオプションを設けた。

  • fix-at-cmd=true :(既定)\@ の再定義を行う。
  • fix-at-cmd=false : LaTeX 標準の*4 \@ の定義を用いる。

*1:リンク先の記事にある通り、(メタデータではなく)文書中で使われる現在日付を SOURCE_DATE_EPOCH の値に追随させるには環境変数 FORCE_SOURCE_DATE(TeX Live 2016 では SOURCE_DATE_EPOCH_TEX_PRIMITIVES)も併せて指定する必要がある。

*2:CM フォントではドットと英字の間のカーニングが無いので Times を例に用いている。

*3:ドットが 2 つ連続した場合、その前が何であっても、2 つ目のドットは文末ピリオドになる。

*4:「jsclasses の」ではないことに注意。