マクロツイーター

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

zxjaナンチャラの現状について語ってみる(1)

つまり、zxjatypezxjafontの解説であるが、その前に一つ重要な話。

はじめに:zxjatypeは(ずっと昔から)壊れている

zxjatypeの本来の主要機能は「少なくともpLaTeXと同等の品質の日本語組版をXeLaTeX上で実現すること」だった。しかし、その主要機能については

もう何年も前から“壊れている”状態

にある。詳細については以下のツイッタァーのスレッドを参照されたい。

これが意味するところは、「日本語文書用のLaTeXについて、本来ならばXeLaTeXも(pLaTeX/upLaTeX/LuaLaTeXと同列の)“主要な”エンジンの地位を得ているべきであるが、残念ながら現状はそうなっていない」ということである。

もちろん、何か理由があってどうしてもXeLaTeXで日本語文書を作る必要があるのなら、その場合の最善策としてzxjatypeは十分に機能するはずであり、その意味で現状のzxjatypeにも存在意義はあるといえる。ただ、この状況は「pdfLaTeXのbxcjkjatypeパッケージ」と同じということになる。つまり、“日本語LaTeX”としてXeLaTeXはLuaLaTeXと同じ地位を得るべきところがpdfLaTeXと同じ地位に甘んじているというわけである。

zxjatype、または“XeLaTeXで日本語”をどうにかしてほしい件

ネットを見る限りでは「XeLaTeXを日本語LaTeXの主流の選択の一つにしたい」という要望は存在する。というわけでここでお願い。

だれか「XeLaTeXでまともに日本語するやつ」をつくってください。

実装の形については、zxjatypeの改良でも新しいパッケージの作製でもよく、またxeCJKを土台にするものでもしないものでも構わない。とにかく、pTeXの品質以上で基本的な日本語の行組版ができる実装があってほしいと思う。

新しいzxjatype(0.7版)の機能を語ってみる

従来の0.6版の機能については以下の記事が参考になる。

小書き仮名で禁則する話

現状のzxjatypeの既定の設定においては、小書き仮名は行頭禁則処理の対象にならない。

\documentclass[autodetect-engine,ja=standard,a4paper]{bxjsarticle}
\begin{document}
\parbox{21\zw}{%
寿限無寿限無五劫の擦り切れ海砂利水魚の水行末雲来末風来末
食う寝る処に住む処藪ら柑子の藪柑子
パイポパイポパイポのシューリンガンシューリンガンのグーリンダイ
グーリンダイのポンポコピーのポンポコナーの長久命の長助
}
\end{document}

例えばこのソースをuplatexでコンパイルすると以下の出力が得られるのに対して:

f:id:zrbabbler:20200209210949p:plain
upLaTeXでの組版結果

同じソースをxelatexでコンパイルすると以下のようになる:

f:id:zrbabbler:20200209211013p:plain
XeLaTeXでの組版結果

なりゆきで改行すると小書きの「ュ」の前に改行位置がくることになるが、upLaTeXではここで(緩い1)禁則が適用されて前の「シ」が追い出される。ところがxelatexでは禁則がないため「ュ」の直前で実際に改行が起こる。

zxjatypeにkanakinsokuオプションを指定すると、小書き仮名に対して(完全な)禁則が適用される。したがって、先ほどのソースでこのオプションを追加すれば、小書きの「ュ」の前での行分割が起こらなくなる。

% グローバルで指定したkanakinsokuがzxjatypeに渡される
\documentclass[autodetect-engine,ja=standard,kanakinsoku,
    a4paper]{bxjsarticle}
\begin{document}

この場合、結果的にuplatexのときと同一の出力が得られる。

でも小書き仮名で禁則するとアレ

しかし、このkanakinsokuオプションには重大な副作用がある。小書き仮名に対する行頭禁則は、内部で「小書き仮名を閉じ括弧類として扱う」ことで実現している。このため、小書き仮名と約物が並んでいると「約物同士が隣接している」と見なされて空きの調節が行われてしまうのである。これは慣習的な日本語の行組版規則に反していて好ましくない。

\documentclass[autodetect-engine,ja=standard,kanakinsoku,
    a4paper]{bxjsarticle}
\begin{document}
ベジエ(Bézier)曲線\par
ベジェ(Bézier)曲線\par
\end{document}

f:id:zrbabbler:20200209220040p:plain
小書き仮名と括弧が並ぶとアレ

この不具合を回避するには、小書き仮名と約物の間に空のボックスを挿入する必要がある。

ベジェ\mbox{}(Bézier)曲線\par

kanakinsokuにはこのような副作用があり、また小書き仮名の行頭禁則は一般的に必須のものとは考えられていないという事情があるため、既定で有効にはなっていない。

まとめ:“(no)kanakinsoku”オプション

  • adjustcharclassが有効である(既定値)場合に以下のオプションが有効になる(0.6b版以降):
    • kanakinsoku: 小書き仮名に対して(完全な)行頭禁則を適用する。
    • nokanakinsoku(既定): kanakinsokuの否定。小書き仮名を行頭禁則から外す。
  • adjustcharclassが無効の場合はxeCJKの既定設定がそのまま適用される。

※xeCJKの既定における小書き仮名の禁則の設定は、昔の版ではkanakinsoku相当であったが、2016年頃にnokanakinsoku相当のものに変わっている。

“(no)useinhibitglue”オプション

現状の\inhibitglueの実装は問題があるので、0.6b版以降では既定で無効になっている。これを有効にするにはuseinhibitglueオプションの指定が必要である。

  • useinhibitglue\inhibitglueの実装を提供する。
  • nouseinhibitglueuseinhibitglueの否定。この場合、\inhibitglueは何もしない命令になる。

和文で☃とかする話

先述の通り、zxjatypeではxeCJKの“文字クラス”の設定を多少変更している。しかし、「文字が和文(CJK)か欧文か」の区別に関してはxeCJKの既定の設定をそのまま踏襲している。それに従うと、(u)pLaTeXやLuaTeX-jaよりも「欧文扱い」される文字が増えることになる。

例えば、次のような「☃」や「♪」の記号を含んだ文書ソースがあったとする。

\documentclass[autodetect-engine,ja=standard,jafont=haranoaji,
    a4paper]{bxjsarticle}
\begin{document}
☃っ☃☃☃っ☃っ☃~~♪
\end{document}

LuaTeX-jaの既定ではこれらの記号は和文扱いになるため、和文フォント(原ノ味明朝)で出力される。

f:id:zrbabbler:20200210080421p:plain
LuaLaTeXでの組版結果(素敵)

ところがxeCJKの既定ではこれらの記号は欧文扱いになる。現在の欧文フォント(Latin Modern Roman)には「♪」の字形はあるが「☃」はないため、結果的に「☃」が出力されないという由々しき事態に陥ってしまう。

f:id:zrbabbler:20200210080441p:plain
XeLaTeXでの組版結果(ざんねん)

xeCJKの「和文扱いの範囲」に関するトラブルを軽減する目的で、0.7版でprefercjkというオプションが導入された。このオプションを指定すると、「和文扱い」になる文字の範囲がLuaTeX-jaの既定により近いものに変更される2

% グローバルで指定したprefercjkがzxjatypeに渡される
\documentclass[autodetect-engine,ja=standard,jafont=haranoaji,
    prefercjk,a4paper]{bxjsarticle}
\begin{document}
☃っ☃☃☃っ☃っ☃~~♪
\end{document}

f:id:zrbabbler:20200210082539p:plain
XeLaTeXでの組版結果(素敵)

まとめ:“(no)prefercjk”オプション

0.7版以降で追加された。

  • prefercjk:「和文扱いの文字」の範囲をLuaTeX-jaのそれに近づける。
  • noprefercjk(既定): prefercjkの否定。xeCJKの既定に従う。

このオプションは実験的で、仕様は将来変更される可能性がある。

その他もろもろ

  • xeCJKの2.x版の使用を非推奨とした。2.x版のサポートは将来廃止される予定。
    • ちなみに、xeCJKの3.0版がリリースされたのは2012年5月。

(つづけ)


  1. (u)pTeXやLuaTeX-jaの既定で適用されている禁則処理は「行分割を完全に禁止はしないが、周りの状況が許す限りは当該の行分割を回避する」という性質のものであり、「禁則を適用すると逆に醜い出力になってしまう」場合には敢えて禁則が無視される。それに対して、zxjatypeのkanakinsokuが提供する禁則処理では禁則位置での行分割は完全に禁止される。

  2. ただしギリシャ文字キリル文字は敢えて「欧文扱い」のままにしている。

2020年のパズル年賀状

今年の年賀状。

f:id:zrbabbler:20191227022742j:plain

以前に述べたとおり、年賀状にはその年の数に関連した数学パズルを載せるのが通例である1。しかし去年はパズルを作っている時間が2時間しかなかったので2、割と普通の(マジで)虫食い算で済ませた。

肝心のパズル問題の部分の文字が小さくで読みづらいが、以下のように書かれている。

以下の条件に従って、乗算の虫食い算を解きなさい。

  • には0または2が入る。
  • には0と2以外の数字が入る。
(問題の図)
f:id:zrbabbler:20191227023211p:plain

一番上にあるのはチェロキー語での新年の挨拶。


  1. ぱんどっくのマニュアルを読破するのに時間を取られている人が多いためか、年を追うごとに年賀状で数学パズルを見ることが少なくなっているようで感じる。

  2. そのうち本腰を入れて数学パズルを作りたいですね……。

TeX言語のマクロも“1回展開”にしたい話

1回展開を実現するにはLuaしないといけない問題

某アドベントカレンダーの最終日の記事では、LuaTeXで「“1回展開”のマクロ」を実現する方法について解説した。

ただし、この記事にある方法では、機能の実現の部分(具体的には「YYYY/MM/DD形式で出力する」という機能)をLuaで実装する必要がある。

-- Luaでの実装
function xx.todayYMD()
  tex.sprint(("%04d/%02d/%02d"):format(
      tex.year, tex.month, tex.day))
end

Lua言語自体はTeX言語よりもずっと習得しやすい言語ではあるが、それでも「LuaTeX上のLuaコードでTeXに関連した機能を実現する」にはそれなりの知識(例えばtexライブラリの使用法など)の習得が必要であり、決して自明ではない。

何より、(例の記事の流れに従うと)機能要件を実現するための「完全展開可能(ただし“先頭~”ではない)なTeX言語のコード」が既に得られている。

% TeX言語での実装
\def\todayYMD{%
  \the\year/\two@digits\month/\two@digits\day}

そうであれば、この「完全展開可能なコードから“1回展開”のマクロが作れる」ほうが、フツーのTeX言語者(※要定義)にとっては便利なのは間違いないだろう。

ixquickmacroパッケージ

というわけで、作ってみた

ixquickmacroパッケージは開発者用のパッケージで、以下の機能を提供する。

  • \defquickmacro\制御綴{<定義本体>}\制御綴を1回展開すると「<定義本体>の完全展開」になるように、\制御綴の意味をローカルに定義する。
  • \gdefquickmacro\制御綴{<定義本体>}\defquickmacroのグローバル定義版。

※現状では、引数をもつマクロはサポートされない。

このパッケージを利用すると、先に示した「TeX言語による完全展開可能な\todayYMDの定義」について、\def\defquickmacroに変えるだけで、“1回展開”の\todayYMDが実現できる。

\defquickmacro\todayYMD{%
  \the\year/\two@digits\month/\two@digits\day}

例の記事で使った\xInspectマクロをここでも利用して、“1回展開”が実現できているかを確かめてみよう。

\documentclass{article}
\usepackage{ixquickmacro}
\makeatletter %!!!!!!!!!!!!!!!!!!!!!!!!! TeX code BEGIN
% 例の \xInspect
\def\xInspect#1{\typeout{%
  once->\unexpanded\expandafter{#1}^^J%
  twice->\unexpanded\expandafter\expandafter\expandafter{#1}^^J%
  full->#1}}

%% "1回展開"な \todayYMD の定義
\defquickmacro\todayYMD{%
  % 中のコードは単に"完全展開可能"に過ぎない
  \the\year/\two@digits\month/\two@digits\day}

\makeatother  %!!!!!!!!!!!!!!!!!!!!!!!!! TeX code END
\begin{document}

\xInspect{\todayYMD}

\stop

このソースをlualatexでコンパイルすると、\xInspectによる端末出力は以下のようになる。

once->2019/12/31
twice->2019/12/31
full->2019/12/31

ixquickmacroパッケージを利用することで、Luaを知らなくても、TeX言語の知識だけで“1回展開”のマクロを作ることができた。スバラシイ。


*「ところで」
ZR「ん?」
*「マクロを“1回展開”にできると何が嬉しいわけ?」
ZR「何だろうねえ」
*「えっ!? 明確なメリットは存在しないの? だったら、この記事もtexadvent2019の記事も単なるくだらないTeX芸でしかないんじゃないの?」
ZR「というわけで、皆さん、来年も当(くだらない)ブログをよろしくお願いします!」

今年もやっぱりMerry TeXmas! ― \end{texadvent2019}

f:id:zrbabbler:20191125025549p:plain
TeX & LaTeX アドベントカレンダー 2019
*  *  *

アドベントカレンダーやっぱり完走!

TeXmas!
\expandafter\expandafter\expandafter\expandafter\expandafter  \catcode
` =  7 \  ,  %  4\:=\  #  !  4  #  /  $  %\:   &\:`  "\:`_'12% 2019/ %
\:   #1\  ,  %  4\,\  ,  %  4\  0  $  &  /  5  4  0  5  4  }1% 12/25 %
\,\  $&\  $  5  -  0#\:`\  ;1\:`\  =2\  $  %  &\ {  =\:`\#6\ \:`@  }11
\,\?\  '  $  %  &\?\  3&{\  #  /  5  .  4@0_\@  7  (  )  ,  %  .  5  -
{\  #  /  5  .  4@<'400}\  $  /{\  )  &  .  5  -\  #  !  4  #  /  $  %
\  #  /  5  .  4@=15_\  #  !  4  #  /  $  %\  #  /  5  .  4@12_\  &  )
\  !  $  6  !  .  #  %\  #  /  5  .  4@1_  =\  *&}\  ,  /  .  '\?\  *&
#1\  54  %  58  -  !  3{  =\ \?\  $  5  -  0{\  %  6  %  2  9  *  /  "
\  %  8  0  !  .  $  !  &  4  %  2{\  4  (  %\  %  6  %  2  9  *  /  "
\  3&}\  $&  =\ \ \?\,{\  )  .  0  5  4_  ,  !  4  %  8.  ,  4  8_}  =
\  3  #  2  /  ,  ,  -  /  $  %\:`\&  }12\  2  %  ,  !  8\:'40  }10_\,
(↑pdftex -etex -iniコンパイル

というわけで、8回目の開催となる TeX & LaTeX Advent Calendar 2019 も、素敵なTeXネタを途絶えさせることなくやっぱり無事にクリスマスの日を迎えられました。今年の参加者は全部で23名、うち8名が初参加でした。参加者の皆様に心からの感謝をやっぱり捧げたいと思います。

今年の重点テーマは「やっぱりLua(La)TeXしよう」でした。改めてやっぱり振り返ってみると、様々な面から「LuaTeXの特徴」を紹介した記事がやっぱり多く、テーマとして一定の役割をやっぱり果たせたのではないでしょうか。これをきっかけにしてLua(La)TeXにやっぱり興味を持つ人が増えることになればやっぱり幸いです。

TeX & LaTeX Advent Calendar 2019 を楽しんでくれた皆さんに、

やっぱりありがとう!

そして

*  *  *

*「去年の記事の文章になんでもかんでも『やっぱり』を付ければ済む、という考えがいくら何でもヒドすぎる」
ZR「あっ、そこは『やっぱりヒドすぎる』じゃないとやっぱりイマイチ」
*「………………」

Pandocでメタデータはテンプレート変数になるかならないか

「Pandoc Advent Calendar 2019」を埋めてみた。

adventar.org

アドベントカレンダー1日目の記事では、Pandocにおける「テンプレート変数」と「メタデータ」について詳しく解説されている。

そこには以下のような記述がある。

3. Pandocフィルタはメタデータにアクセスできるが、テンプレートの変数にはアクセスできない

しかし、実際に(LaTeX出力用の)フィルタを実装していると、「フィルタからテンプレート変数を設定したい」場合が時々ある。

もちろん、当該の記事に

「テンプレート変数を与えるために、YAMLメタデータブロックで変数(=メタデータ)を定義する」というテクニックが便利です。

と書かれているように、「テンプレート変数の代わりにメタデータを使う」というテクニックは存在する。でも果たしてそれはいつでも通用するのだろうか。

Pandocのマニュアルには次のようにある。(下線は筆者による)

emplates contain variables, which allow for the inclusion of arbitrary information at any point in the file. They may be set at the command line using the -V/--variable option. If a variable is not set, pandoc will look for the key in the document’s metadata, which can be set using either YAML metadata blocks or with the -M/--metadata option.

これを読む限りは「テンプレート変数の代わりにメタデータを使う」というテクニックは「ユーザが当該のテンプレート変数を(-Vオプションなどで)設定していない」ことが前提になりそうである。

調べてみた

※最新版(2.8.0.1版)のPandocを用いた。

[2019/12/14追記] 2.8.0.1版の挙動の一部は過去版の挙動と食い違っていて、どうやらこれは“不具合”だったようです。2019/12/05リリースの2.8.1版で“修正”されたため、この版の動作に基づいて記述を修正しました。

次のテンプレートを用意する。

[foo.html]
$for(foo)$$foo$$endfor$

※複数の値が指定されることを見越してループにしておく。

このテンプレートを用いて、空のMarkdownファイル“empty.md”をHTMLに変換することを考える。

pandoc empty.md --template=foo.html -o out1.html

その際に、テンプレート変数・メタデータの設定のオプションの組合せとして、次の4つを試してみる。

  • ①追加オプションなし。
  • -V foo=V1 : テンプレート変数のfooを設定する。
  • -M foo=M1メタデータfooを設定する。
  • -V foo=V1 -M foo=M1 : テンプレート変数とメタデータの両方を設定する。

    その結果

変数 メタデータ 出力
なし なし (空)
V1 なし V1
なし M1 M1
V1 M1 V1

マニュアルの記述の通りで、テンプレート変数が既に設定されている場合は、「メタデータを代わりに設定する」という技法は使えない、という結果になった。

もう少し調べてみる

結論は出たが、事のついでとして、もう少し複雑な場合を調べてみることにする。

複数の値を指定してみた

先の実験と同じ設定で、-V-Mオプションを反復することで複数の値を指定してみることにする。

  • ①追加オプションなし。
  • -V foo=V1 -V foo=V2
  • -M foo=M1 -M foo=M2
  • -V foo=V1 -M foo=M1 -V foo=V2 -M foo=M2

結果は以下の通り。

変数 メタデータ 出力
なし なし (空)
V1V2 なし V1V2
なし M1M2 M1M2
V1V2 M1M2 V1V2
  • やはりテンプレート変数が設定済の場合はメタデータの値は使われない。
  • テンプレート変数は1つの値しか保持できない。テンプレート変数とメタデータのいずれもオプション(-V-M)を繰り返すことで複数の値を保持できる。
    ※2.8版~2.8.0.1版ではテンプレート変数が1つの値しか持てないという“不具合”があった。

header-includesも試してみた

header-includes変数については、「テンプレート変数を指定する」「メタデータを指定する」の他に「ヘッダファイルを指定する(-Hオプション)」という方法も存在する。

  • 先ほどのテンプレートでfooheader-includesに置き換えた新しいテンプレート“header.html”を用意する。
  • H1だけ書かれたファイル“h1”とH2だけ書かれたファイル“h2”を用意する。
  • -V-M-Hの各々について「2つ指定する」「指定しない」としたものの全ての組合せ(8通り)を試してみる。

例えば、-V-M-Hの全てを2つ指定する場合のコマンド行は以下のようになる。

pandoc empty.md --template=header.html -o out2.html \
    -V header-includes=V1 -M header-includes=M1 -H h1 \
    -V header-includes=V2 -M header-includes=M2 -H h2

結果は以下の通り。

変数 メタデータ ヘッダファイル 出力
なし なし なし (空)
V1V2 なし なし V1V2
なし M1M2 なし M1M2
V1V2 M1M2 なし V1V2
なし なし h1h2 H1H2
V1V2 なし h1h2 V1V2H1H2
なし M1M2 h1h2 H1H2
V1V2 M1M2 h1h2 V1V2H1H2
  • テンプレート変数での指定とヘッダファイルでの指定は共存する。それらの少なくとも一方が指定済の場合はメタデータの値は使われない。
  • ヘッダファイルは複数指定できる。
  • テンプレート変数の値(高々1つ指定順で複数)の後にヘッダファイルの値(指定順で複数)が並ぶ。

まとめ

やっぱり、「フィルタの実装の内部でheader-includesを設定する」ための確実な方法は存在しない?

f:id:zrbabbler:20191214213336p:plain:w300
(画像は本文と関係ありません)

やっぱりアドベントがはじまった ― \begin{texadvent2019}

f:id:zrbabbler:20191125025549p:plain
TeX & LaTeX アドベントカレンダー 2019

TeX界における年末の恒例イベントとなったと言わんばかりのアドベントカレンダーが今年も始まりました。

重点テーマ

今年の重点テーマはコレです。

やっぱりLua(La)TeXしよう

「LuaTeXはいいぞ」とやっぱりよく言われますが、具体的に何がいいのかはやっぱり十分に知られていません。熱狂的なLuaTeXファンの皆さん、是非ともLuaTeXの魅力についてやっぱり熱く語りましょう!

※例によって、重点テーマはやっぱり「必須」ではありません。あんまりLuaTeXでないTeXネタ、さっぱりLuaTeXでないTeXネタ、なんでもやっぱり歓迎しております。

で、初日のネタは

こちらになります。

まだ参加できます!

TeX & LaTeX Advent Calendar 2019(#texadvent2019)は

まだまだ参加者募集中です。

LaTeXなネタ、TeX言語なネタ、expl3なネタ、Overleafなネタ、dvisvgmなネタ、lwarpなネタ、LuaHBTeXなネタ、tlmgrなネタ、その他ナントカカントカ、お持ちの方はぜひぜひ、

やっぱりご参加おねがいします!

もう空きが残りわずかとなっています。登録はやっぱりお早めに!


あっ、ぱんどっく な人はこっち。

Pandoc Advent Calendar 2019

やっぱり去年のアレ(アレな方)を振り返ってみる

f:id:zrbabbler:20191123154250p:plain
TeX & LaTeX Advent Calendar 2019

昨日非アレでしたが、今度はアレな方の振り返り。

昨年(2018年)の「TeX & LaTeX Advent Calendar」はこんな感じでした。

12/01zr_tex8r自分がどのLaTeXを使ってるか知りたい話
12/02puripuri2100LuaLaTeXで部誌を作った話
12/03h-kitagawaMetaPost (luamplib, gmp) で☃
12/04golden_luckyTeXでEPSファイルを使うな、は本当か
12/05tamuratakVSCode拡張のLaTeX Workshopにコントリビュートした話
12/06uwabamiTeX on Debian 10 (Buster)
12/07champs20ベースラインとかjis.tfmとか ( プログラム )
12/08CareleSmith9TeX 言語したい人は大学図書館に行ってみよう!
12/09aminophen私と TeX Live と LuaTeX の近況レポート
12/10wtsnjpreverxii.tex: TeX でリバーシを遊ぶ(翻訳)
12/11p_typo添字のお話
12/12kn1chtptex2pdfがghq管理下のリポジトリでPDFを作成できないことがある
12/13mattskalaTeXLiveからMediaWikiのために最小のインストールは何ですか?
12/14p_typoLuaLaTeXでPDF/X-4やPDF/X-1aなPDF生成する
12/15mod_poppoLuaLaTeXでダウンロードカードを作った話
12/16asciianpost.md · GitHub
12/17trueroadLuaLaTeXでLilyPondを使って楽譜の入った文書を作る
12/18keisuke495500自転車で北海道一周してきたのでGPSログをLaTeXで表示する
12/19doraTeXTeX で乱数を使う
12/20isaribi_saitohLuaLaTeXで和字コマンドを操ろう(newunicodecharパッケージ)
12/21tasusuTikZのgraph記法とgraph drawing
12/22zr_tex8r例の「verb の呪い」を LuaTeX の力で打破する(bxrawstr パッケージ)
12/23munepi\futurelet のお勉強で作った漢文訓点スタイル
12/24golden_luckyGitHub - k16shikano/yafootnote: Yet Another \footnote
12/25Yasunarijlreqの多書体化

というわけで、今年はこれを皆目参考にせずに、自分がやっぱり素敵だと思うネタを全力でぶつけていきましょう!