Hatena::ブログ(Diary)

マクロツイーター このページをアンテナに追加 RSSフィード Twitter

2016-08-29

TeX芸人の知らない#{の挙動

「コレが気になって眠れない」という人が出てこないように解決しておこう。

実験してみる

% '[' '(' をグループ開始文字にする
\catcode`\[=1 \catcode`\]=2
\catcode`\(=1 \catcode`\)=2
% '#[' を使ったマクロ定義
\def\testA#1#[\message{#1}]
% '#(' を使ったマクロ定義
\def\testB#1#(\message[#1])
文字列化するとどうなるか

マクロ定義の文字列を表示させてみる。*1

\message{\meaning\testA}  % macro:#1[->\message {#1}[
\message{\meaning\testB}  % macro:#1(->\message [#1](

このように、パラメタテキストと置換テキストの最後に挿入されるグループ開始文字の文字コードは“定義時に実際に使ったもの”となる。

文字コードの異なるグループ開始文字にマッチするか

以下の結果から解るように、同じ文字コードのグループ開始文字としかマッチしない。

\testA??[] % '??' が表示される
\testB??[] % エラー ! Paragraph ended before \testB was complete.

すなわち、一般的なマクロパラメタのマッチ規則に従い、カテゴリコードが一致しても文字コードの異なるトークン同士はマッチしない、ということである。

まとめ

*1:ここでは \meaning を使ったが、\show を使った場合も(改行付で表示されることを除いて)同じである。

2016-08-26

例のブログが二周年らしい

ということは、例のパッケージを久しぶりに引っぱり出してくる必要があるらしい……。

\documentclass{article}
\usepackage{iamjatex,bxnewfont}
\newfontx\fAre{ipxg-r-uf0}
\renewcommand{\sfdefault}{ipxg-r-uf0*1*}
\begin{document}
\begin{iamjatex}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1 1 1 1 1 1 1 1 1 1 1  E X C E L L E N T  ! ! ! ! ! ! ! ! ! !
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
       ____                                                  
    ___HHHH   _____        HAPPY  2ND  ANNIVERSARY!          
   / .   . \ |NICE!|                                         
   \  ---  / |~~~~~              Acetaminophen's diary       
 V :#######: Y           http://acetaminophen.hatenablog.com/
  \/   o*"*\/                       Since 2014.08.26         
  {    o    }                                                
   \_______/                                         HURRAY!!
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
ZZZ27ZZZZZZZZZZZZ2ZZZZ7ZZZZZZZZZ2ZZZZ2ZZZZZZZZZZZ2ZZZZZZ7ZZZX
\end{iamjatex}
\end{document}

*「これはひどすぎる・・・」
ZR「というわけで、☃とか化学とか☃とかTeXとか☃とかに関する素敵な記事を、今後も期待しています!」

2016-08-22

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

以前の記事で触れられているように、また新しくなっている。

重要なお知らせ

bxjsbook クラスについては、近い将来にページレイアウトの大きな変更が行われる。以下の記事を読んで必要な対策を取ってほしい。

layout オプション
  • layout=v2 : jsbook クラスと同様のページレイアウトを用いる。
  • layout=v1 : 1.2 版以前のページレイアウトを用いる。

textwidth-limit オプション

  • textwidth-limit=<整数> : bxjsbook における行長の上限値(全角単位)を指定する。既定値は 40。

詳細は以下の記事を参照されたい。

fancyhdr パッケージ対策

jsbook で fancyhdr するとアレ

先の記事で述べられているように、jsbook/bxjsbook クラスには「ヘッダ・フッタ領域の横幅」を表す \fullwidth という独自のレイアウトパラメタが存在する。fancygdr パッケージを利用してヘッダ・フッタ(((bx)jsbook クラスにおいては、既定のページスタイルがフッタを全く用いないため、ページレイアウトはフッタ領域を無しにしている。そのため、bxjsbook クラスでフッタを用いたい場合はページレイアウトを変更(\setpagelayout)する必要がある。))書式を変更しようとする場合、fancyhdr は当然この \fullwidth についての知識を持たないため、“既定のヘッダ(headings ページスタイル)と同じ感じ”には出力されない。

例えば次のように、jsbook クラスで fancyhdr を利用したとする。

% upLaTeX 文書; 文字コードは UTF-8
\documentclass[uplatex,a4paper]{jsbook}
% 例えば, ページ番号を, 前に巻番号を付けて "42-3" のように
% するために, fancyhdr を利用したとする.
\usepackage{fancyhdr}
\pagestyle{fancy}
\newcounter{Volume}
\setcounter{Volume}{42}% 巻番号
\fancyhf{}
\fancyhead[LE,RO]{\itshape\theVolume-{\bfseries\thepage}}
\fancyhead[RE]{\leftmark}
\fancyhead[LO]{\rightmark}
\renewcommand{\chaptermark}[1]{\markboth{\thechapter\quad#1}{}}
\renewcommand{\sectionmark}[1]{\markright{\thesection\quad#1}}

\usepackage{bxjalipsum}
\begin{document}
\chapter{吾輩はアレである}
\section{希望はまだ無い}
\jalipsum[1-10]{wagahai}
\end{document}

この文書の出力結果は以下のようになる。ヘッダ・フッタ領域の左右マージンが本文領域と同じになってしまっている。

f:id:zrbabbler:20160822175835p:image

※(bx)jsbook の既定のレイアウトがどんな感じなのかは、例の記事に解説がある。

bxjsbook の場合はコレ

v1.2a 以降の BXJS クラスでは、fancyhdr パッケージが読み込まれた場合に、fancy ページスタイルの初期設定において、「ヘッダ・フッタ領域について、横幅を \fullwidth に合わせた上で(headings スタイルと同様に)本文領域よりも小口側(外側)に突き出させる」という設定を行う。これにより、ヘッダ・フッタの配置が“既定のページスタイル(headings)と同様の見た目”になる。

% upLaTeX 文書; 文字コードは UTF-8
\documentclass[uplatex,dvipdfmx,a4paper,ja=standard,layout=v2]{jsbook}
% 例えば, ページ番号を, 前に巻番号を付けて "42-3" のように
% するために, fancyhdr を利用したとする.
\usepackage{fancyhdr}
%(あとは先の例と同じ)
f:id:zrbabbler:20160822175834p:image

※BXJS クラスが自動的に fancyhdr パッケージを読み込むことはない。

fancyhdr オプション

先述の fancyhdr 対策は既定で有効になっている。オプションで無効化することができる。

  • fancyhdr=true : fancyhdr 対策を有効にする。
  • fancyhdr=false : fancyhdr 対策を無効にする。

paragraph-mark オプション

  • paragraph-mark=<文字1つ>パラグラフ\paragraph)の見出しの記号(既定では“■”)を変更する。
f:id:zrbabbler:20160822205430p:image

コレはスゴイ……たぶん。

2016-08-21

jsbook や bxjsbook の左右マージンを理解する

前回の「bxjsbook が残念な件」の記事において、jsbook の左右マージンについて、以下のように記述した。

マージン領域を 36mm 確保し、それを左右で均等に配置する。

しかしこの説明と「jsbook の本文領域は端に偏っている」という事実は明らかに矛盾している。実際には、jsbook の左右マージンの設定は少し複雑で、

ヘッダ領域と本文領域で余白の量が異なる

という特徴をもっている。本記事ではこの辺りの事情について解説する。

jsbook の左右マージン

f:id:zrbabbler:20160821134724p:image

jsbook クラスにおける左右マージンの量は以下の手順により決定される。

  • ヘッダ領域について:
    • 左右のマージンを 18mm 取り、残った領域をヘッダ領域とする。*1
    • jsbook クラスには、このヘッダ領域の幅を表す \fullwidth という長さ命令が存在する。
  • 本文領域について:
    • 可読性を保つため、本文領域の行の長さは最大全角 40 文字(40zw)に制限されている。
    • 紙面の幅が小さく、ヘッダ領域の幅(\fullwidth)が 40zw 以下に収まる場合は、本文領域はヘッダ領域と同じマージン量を持たせる。(下掲の図 1 参照)
    • 紙面の幅が大きく、ヘッダ領域の幅が 40zw を超えてしまう場合は、本文領域の幅を 40zw とする。この時、本文領域はヘッダ領域とノド側(内側)の端を揃えるように配置する。つまり、ノド側のマージンは 18mm のままで、小口側(外側)のマージンが増加することになる。(図 2 参照)
    • LaTeX 標準のレイアウトパラメタの一つである \textwidth は、この本文領域の幅を指す。
    [図 1: 用紙横幅が大きい(a4paper)場合]
    f:id:zrbabbler:20160821134725p:image
     
    [図 2: 用紙横幅が小さい(a5paper)場合]
    f:id:zrbabbler:20160821134723p:image

    bxjsbook の左右マージン

    bxjsbook のクラスのレイアウトは jsbook クラスのものを踏襲しているため、「ヘッダ領域の横幅は \fullwidth、本文領域の横幅は \textwidth」のように別々のパラメタを持っている。

    ところで、BXJS クラスにおいては、ユーザは \setpagelayout という命令を利用してページレイアウトを変更することができる。この \setpagelayout 命令の引数には geometry のパラメタを設定する仕様になっている。ところが、geometry パッケージは一般のクラスを対象としているため bxjsbook 特有の「\fullwidth\textwidth の違い」については当然関知していない。\setpagelayout で“textwidth”の値を(直接または間接に*2)指定した場合、どう解釈されるだろうか?

    \setpagelayout*{textwidth=50zw}
    

    答えは以下の通り。

    • textwidth として指定した値は \fullwidth の値と見なされる。すなわち、ヘッダ領域の水平配置は geometry で設定したものに従う。
    • その上で、「jsbook の本文領域の決定手順」を改めて実行する。
      • \fullwidth ≦ 40zw ならば、\textwidth\fullwidth とし、本文領域の水平配置も geometry の設定に従う。
      • \fullwidth > 40zw ならば、\textwidth = 40zw とし、本文領域の水平配置は、geometry の設定に対して、小口側(外側)のマージンを増加させたものになる。

    従って、\setpagelayout*{textwidth=50zw} を実行した場合、ヘッダ領域については「横幅が 50zw で左右マージンが同じ」となるが、本文領域については「横幅が 40zw で外側のマージンが内側よりも 10zw だけ大きい」という結果になる。

    textwidth-limit パラメタ

    これまで見た通り、bxjsbook においては \textwidth(本文領域の幅)の値について「40zw が上限」と決められていて、\setpagelayout 命令ではこれを変えることができない。これが不都合な場合もあるだろう。そこで、BXjscls の 1.2a 版において「本文領域の幅の上限」を設定するクラスオプション textwidth-limit を新設した。

    • textwidth-limit=<整数> :「本文領域の幅の上限」を全角単位の整数値で指定する。実際の本文領域の横幅(\textwidth)は、\setpagelayout で決まるヘッダ領域の横幅(\fullwidth)とこのオプションキーの値のうちの小さい方となる。

    例えば、

    \documentclass[uplatex,dvipdfmx,a4paper,ja=standard,
      textwidth-limit=45]{bxjsbook}
    

    とすると、本文の行長が 45 文字になる。

    注意事項
    • 「textwidth が実際には \fullwidth の指定と見なされる」というのは飽くまで \setpagelayout 命令を使った場合である。\geometry 命令を直接実行した場合は「BXJS クラス用の後処理」が行われないためこの通りにならない。
    • bxjsbook クラスでは水平マージンに関して margin=18mm*3が既定値として設定されている。ここでもし \setpagelayout{textwidth=50zw} のような設定を実行すると、textwidth の設定が“追加”されるため、結果的に left、right、textwidth(および paperwidth)の全てを指定した「過制約」の状態になってしまう。geometry の仕様ではこういう場合 textwidth の指定が無視されるので、結果的に \setpagelayout が効かなかったように見える。

*1:厳密にいうと、ヘッダ領域の幅は、紙面横幅から 36mm を減じた後に全角幅の整数倍に丸めた値になる。

*2:例えば、margin や hscale を指定すると、結果的に textwidth を指定したことになる。

*3layout=v2 の場合。

2016-08-20

bxjsbook に関する残念な話

f:id:zrbabbler:20160820211759p:image

bxjsbook が極めてアレな事案

BXJS クラスは原則として*1 JS クラスのページレイアウトのデザインを踏襲している。しかし、現状の bxjsbook については、上の図にみるように本文領域の水平位置が jsbook と比べて明らかに違う、という残念な事態になっている。jsbook は書籍用の文書クラスであり、本文領域を極端にノド(書籍の綴じた部分)の側に寄せたデザインになっているのであるが、このノド側のマージンの幅について、bxjsbook では誤って本来の値の 2 倍の値に設定されているのである。

※ちなみに、上図の出力に対するソースは以下の通り。

[jsbook の方]
% upLaTeX 文書
\documentclass[uplatex,a4paper]{jsbook}
\usepackage{bxjalipsum}
\begin{document}
\chapter{吾輩はアレである}
\jalipsum[1-10]{wagahai}
\end{document}
[bxjsbook の方]
% upLaTeX 文書
\documentclass[uplatex,dvipdfmx,a4paper,ja=standard]{bxjsbook}
\usepackage{bxjalipsum}
\begin{document}
\chapter{吾輩はアレである}
\jalipsum[1-10]{wagahai}
\end{document}

この中で使われている「bxjalipsum パッケージ」については以下の記事を参照されたい。

bxjsbook が極めてアレな理由

jsbook の左右マージンの設定(基底フォントサイズが 10pt の場合)は以下のようになっている。

マージン領域を 36mm 確保し、それを左右で均等に配置する。

※なお、ここでいう“マージン領域”は \fullwidth(ヘッダ・フッタ領域の横幅)に相対するものである。「\fullwidth\textwidth の違い」の話は後に回す。

それに合わせるように、bxjsbook では、次のように geometry のパラメタを設定している……。*2

hmargin=36mm, hmarginratio=1:1

だけどこの設定は正しくない。hmargin パラメタは元々は「hmargin={‹左マージン›,‹右マージン›}」という書式であり、「hmargin=36mm」と書くと、「hmargin={36mm,36mm}」の省略形とみなされる。つまり左右のマージンがともに 36mm になって、全部で 72mm になってしまうのである。

正しい設定は、要するに「左右ともに 18mm」ということだから、次のようになる。

hmargin=18mm

要するに、今の bxjsbook のレイアウトは“マチガッテル”のである。

「bxjsbook が極めてアレ」への対処

マチガッテルので修正したい。しかしこの事案については、修正前と修正後のレイアウトの違いがかなり顕著であるため影響が大きい。*3そこで、以下のような対処方針を取ることにした。

  • 近い将来にリリースされる予定の“1.3 版”において、bxjsbook のレイアウトを“修正後”のものに変更する。
  • その上で、“修正雨”のレイアウト選択できるようにクラスオプション layout を新設する。
    • layout=v2 : “修正後”のレイアウト(jsbook と同様のもの)を使う。
    • layout=v1 : “修正前”のレイアウト(1.2 版と同様のもの)を使う。
  • この layout オプションは少なくとも 1.x 版の間は提供され続ける。*4

そして、1.3 版へ向けた経過措置として、“1.2a 版”をリリースした。

この 1.2a 版では既に新設の layout オプションが使用可能になっているが、その既定値は layout=v1 である。従って、文書ソースを変更しなければレイアウトは 1.2 版以前のものと変わらない。


お願い

現在 bxjsbook クラスを用いた文書を作成している方は、以下の何れかの対処をお願いします。

自分の手違いでお手数をかけてしまい申し訳ありません。

*1:敢えて変えている箇所も存在する。

*2:実際には基底フォントサイズが 10pt 以外である時のための対策が入る。

*3:jsbook のレイアウトは“癖が強い”、つまり、本文領域がかなりノド側に寄っているため、“修正前”の方がよいと考える人も現れそうである。

*4:ただし、layout=v1 についても layout=v2 についても、レイアウトが今後“全く変わらない”ことを保証するものではない。BXJS クラスのレイアウトについて、小規模な修正は従来ずっと行われていたわけであり、この状況は今後も継続される。