最終更新:2017-04-08 (土) 21:05:07 (563d)

TeXマクロ

メモ帳/TeXマクロ4

\setbox0 とは

よく他人のマクロを覗くと

\setbox0=\hbox{#1}
\@tempdima=\wd0

などのような記述を見掛けることになります (LaTeX2e ではこれは obsolete な方法 として推奨されていません)。
これは TeX のボックスレジスタ 0 番に \hbox で #1 を組んだときの 幅 \wd を \@tempdima という長さレジスタに代入する という文です。
これと等価なことを LaTeX では

\newlength{\hoge}
\settowidth{\hoge}{#1}

等とすれば \hoge に #1 の幅が設定されることになります。

実は TeX のアロケーション処理の実装を覗いてみるとわかるのですが、 とりあえず、

\newbox\hakoA
\newcount\countA
\newdimen\dimenA
\newskip\skipA
\newtoks\toksA
\newif\ifA
hoge\bye

と書いた hoge.tex を

tex hoge

として実行し、hoge.log を覗いて下さい。そうすると

This is TeX, Version 3.14159265 (TeX Live 2017/W32TeX) (preloaded format=tex 2017.3.19)  8 APR 2017 21:03
 encTeX v. Jun. 2004, reencoding enabled
**./hoge.tex
(./hoge.tex
\hakoA=\box16
\countA=\count26
\dimenA=\dimen16
\skipA=\skip18
\toksA=\toks12
 [1] )
Output written on hoge.dvi (1 page, 212 bytes).

という事になります。これは新規に \hakoA というのを用意するときに、 TeX は裏側で数字に置き換えている (\box レジスタの 16 番としてアロ ケーションしている) ということなのです。 この事実から

\newbox\hakoA
\setbox16=\hbox{hoge}% 要するに \hakoA のこと
\box\the\hakoA % \box 16 に展開される
\bye

とすることにより \hakoA (16) に \hbox{hoge} を代入し、\the\hakoA により 16 番を取得して \box 命令でその内容を出力しています。別にこのような 回りくどり方法を取らなくとも

\newbox\hakoA
\setbox\hakoA=\hbox{hoge is hoge.}% これは \setbox \box 16 に展開されそうだが....
\box\hakoA % これは \box \box 16 にされるのでは心配になるが適切に展開される
\bye

としても同じ事です。

このような事実から

\setbox0=\hbox{hoge}
\box0

とすると

hoge

が出力されるというのはお分かりでしょう。そして 0 番めのボックスレジスタは ユーザーのアロケーションの対象外で、誰でも使っても良い一時的 (temp) なもの ということが伺えます。

\ifcase

例えば 太陽暦の 5 月を 太陰暦の皐月に自動的に変換したいときに (陽暦の 5 月 が陰暦の皐月ではないというツッコミはおいといて) \ifcase なる分岐命令が 使えます。

\ifcase <cnt> <0 の場合> \or <1 の場合>\or <2 の場合>\or ... \or <n の場合>\fi

さて、次のように定義すると

\newcommand*\oldreki[1]{%
  \ifcase #1 \or 睦月\or 如月\or 弥生\or 卯月\or 皐月\or
  水無月\or 文月\or 葉月\or 長月\or 神無月\or 霜月\or 師走\fi}
5 月は陰暦で\oldreki{5}でしょう。

としますと「5 月は陰暦で皐月でしょう。」という出力になります。

汎用的なくり返し式 \loop ... \repeat

通常のプログラミング言語の場合は、次のような繰り返し式を使う場面が しばしばあります。

int i, sum = 0;
for (i = 1; i < 11; i++){
  sum := sum + i;
}

しかし、これは次のように while 文でも同様な処理を行なえます。

int i, sum;
sum = 0;
i = 1;
while (i < 11){
   sum := sum + i;
}

TeX は必要最低限の繰り返し式である \loop \repeat なるコマンドを 用意しています (これがあれば for 文や while 文を簡単に用意することが可能)。

{<初期化文>  \loop <繰り返し文> <条件文> <実行文>\repeat}

別に初期化文とかはいらんです。 上記の 1 から 10 の総和を求めるためには次のようにします。

\makeatletter
\@tempcnta=\z@
\@tempcntb=\z@
\loop \advance \@tempcntb \@ne \ifnum \@tempcntb < 11\relax
  \advance \@tempcnta \@tempcntb \repeat
総和: \@arabic\@tempcnta
\makeatother

\loop の中における <繰り返し文> は <実行文> よりも先に実行されます。 これがいやなときは do-while 文などを定義します。\loop ... \repeat では \loop ... \repeat では質素過ぎるので \@whilenum と \@whiledim が用意されています。

\@whilenum <整数値の比較式>  \do{<処理内容>}
\@whiledim  <長さの比較式> \do{<処理内容>}

まぁ、とりあえずは以下の使用例を吟味してくださいな。

\makeatletter
\@tempcntb=\z@
\@tempcnta=\z@
\@whilenum \@tempcntb <11\relax \do{%
   \advance \@tempcnta \@tempcntb
   \advance \@tempcntb \@ne
}総和: \@arabic\@tempcnta\par
\@tempdima=.4pt
\@whiledim \@tempdima <1em\relax \do{%
   \vrule width \@tempdima height 1em \kern \@tempdima
   \advance \@tempdima \p@
}\par
\@tempdima=.4pt
\@whiledim \@tempdima <.5\linewidth\relax \do{%
   \hrule width \@tempdima height .4pt \par
   \multiply \@tempdima \tw@
}\par
\makeatother

トークンパラメータ・トークンレジスタ

通常のマクロ \anycs はコントロールシークエンス (バックスラッシュと英数字で定義 される) と呼ばれたりコントロールシンボル (バックスラッシュと記号一つ) などを 用いることにより、その定義内容を展開・置換することができます。

\def\hoge#1{hoge is #1.}
\hoge {foo}

TeX ではトークンリストと呼ばれるパラメータ・レジスタが用いられており、 あらかじめ組み込まれているものをトークンリストパラメータ、ユーザが \newtoks によって導入するものをトークンリストレジスタと呼んでいます。 これらトークンリストはマクロとは違い、展開のされ方などが異なります。 さらにトークンリストは引数を取ることはありません。 例えば \everypar は段落がまさに組まれようとしている時に実行される トークンリストパラメータです。これを使って行数を表示する簡単な例を 御覧下さい。

\documentclass{jsarticle}
\begin{document}
それそれ。\par
うんうん。\par
% \begin{document} のあとでもここはまだ文章を組み上げる前の
% 垂直モードにある。
\makeatletter
%\parindent=\z@
\let\orig@par=\par
\newcount\cnt@lines
\cnt@lines=\@ne
\def\par{\advance\cnt@lines\@ne \orig@par}
\everypar={\llap{\scriptsize\@arabic\cnt@lines:\space}}
\makeatother
% ここで垂直モードの終了となり、文章の構成要素が表れるため、
% \par が自動的に呼び出された事と同義になるため、トークンリスト
% パラメータ \everypar が呼び出される。
あれあれ\par
これこれ\par
それそれ\par
だれだれ\par
どれどれ\par
ほうほう\hfill そうそう\\ こうこう。\par
\end{document}

LaTeX での \par のオリジナルを \orig@par に保存しておきます。 次に \par の定義を書き換えます。これは \cnt@lines という行数を カウントするカウンタ型変数となり、初期値を 1 にしておきます (行は 1 行めから始まるため)。次に \everypar なるパラメータに行数を表示するための トークンリスト

\llap{\scriptsize\@arabic\cnt@lines:\space

を代入します。なんだか、verbatim 環境に応用できそうな予感がしますね。

似非「太ミン・太ゴ・影付き」

手元にちゃんとした太明朝や太ゴシック体がないときに、応急処置的に それらを作成することができます。漢字に限らず仮名文字もうろこやはらい の部分が不様に太って、プロは絶対にやらないのですが、私はアマチュア なので、やっちゃいます (一言で表せば「だらしない雰囲気」になります、 印刷した段階での出力をまったく想定していないので、きちんとデザインされた書体 とは雲泥の差があります)。方法としてはある文字 'A' を出力すべき位置 <x, y> にまずその字を配置し、その後に <x + α, y + α> にそれと同じ文字を 配置するという方法です。これならば簡単に太くできます。

\def\huto#1{\ifvmode\leavevmode\fi\hbox{%
  \hbox to 0.05pt{#1\hss}\hbox to 0.05pt{#1\hss}\hbox to 0.05pt{#1\hss}\hbox{#1}}% }

太さなどは好みに応じて変更すれば良いので、適宜 0.05 ポイントなどの間隔を 変更します。

\mcfamily ほげほげ、ほげ iiiiiii。\par
\mcfamily ほげほげ、\huto{ほげ} iiiiiii。\par
\gtfamily ほげほげ、ほげ iiiiiii。\par
\gtfamily ほげほげ、\huto{ほげ} iiiiiii。\par

さて、お次ぎは「影付き」文字と呼ばれるものです。これも最初からきちんと デザインされた書体を用いるのが正解なのですが、ここでは似非でそれを 実現します。原理は上記の似非太ミンと同じことです。

%\usepackage{color}
\newcommand*\kage[1]{\ifvmode\leavevmode\fi
  \hbox to 0.25pt{\color{gray}#1\hss}\hbox{\color{cyan}#1}%
}
ほげほげ、影付きになって欲しいなぁ。\par
ほげほげ、\kage{影付きになって欲しいなぁ}。

このような影付きの文字はスクリーン上ではうまい具合に出力されますが、 印刷段階では使いものにならない場合が多いので、似非文字装飾はスライド などにとどめるのが良いでしょう。

枠付で影付の文字を出力するにはどうすれば良いでしょうか? 枠を付けるためには、目的の文字列のフォントサイズ X よりも、 枠の太さ分だけが大きいフォントサイズ X * α を下に重ねれば 良いことになります。あとは上記と同じ様に影を付けるだけです。 これは宿題にしておきましょう。

もっと高度な文字装飾を行なうためには PostScript special を直接書くとか PSTricks を使うなどのデバイス依存のことを行なわなければなりません。

均等割付

よく町内会のチラシや墨一色のワープロ文書では均等割付と呼ばれる 機能があります。 LaTeX においてこれを簡単に行なうには

\makebox[<width>][s]{<member>}

を使うことが第一に考えられます。\makebox は中身を spread (広げる) という 機能があるので、これを使い

\newcommand*\warituke[2]{\makebox[#1][s]{#2}}
\begin{description}
 \item[\warituke{6zw}{集合場所}] てきとうな場所。
 \item[\warituke{6zw}{日時}] しかるべき時に。
 \item[\warituke{6zw}{持参するもの}] 適切なもの。
 \item[\warituke{6zw}{その他}] てきとうに。
\end{description}

とすれば、全角 6 文字分で description 環境のラベルを均等割付に できます。しかし、これでは \makebox (\hbox) の中が underfull に なってしまうので、適宜グルーを挿入してあげましょう。これには \@tfor なる文字列処理を行なうくり返し命令でも使います。

\newcommand*\warituke[2]{\makebox[#1][s]{#2}}
\begin{description}
 \item[\warituke{6zw}{集合場所}]
 \item[\warituke{6zw}{日時}]
 \item[\warituke{6zw}{持参するもの}]
 \item[\warituke{6zw}{その他}]
\end{description}
\makeatletter
\renewcommand*\warituke[2]{%
 \makebox[#1][s]{%
   \@tempcnta=\z@
   \@tfor\member:=#2\do{\advance\@tempcnta\@ne}%
   \@tfor\member:=#2\do{%
      \advance\@tempcnta\m@ne
      \ifnum\@tempcnta=\z@
         \member
      \else
         \member\hfil
      \fi
   }%
 }%
}
\makeatother
\begin{description}
 \item[\warituke{6zw}{集合場所}]
 \item[\warituke{6zw}{日時}]
 \item[\warituke{6zw}{持参するもの}]
 \item[\warituke{6zw}{Etc}]
\end{description}

最後の文字の後にグルーは必要ないので、文字数をカウントしています。 別に日本語じゃなくても OK で、適宜空白をいれる必要はありません。

割り付け幅を何度も記述するのは面倒なので、その場所における幅を 保存する変数 \warihaba を定義しましょうか。全角幅で割り付けすることを 前提としているならばカウンタでも構いません (\c@hoge zw)。

\makeatletter
\newdimen\kintou@warihaba
\newcommand*\warihaba[1]{\kintou@warihaba=#1\relax}
\newcommand*\warituke[2][\kintou@warihaba]{%
 \ifvmode\leavevmode\fi
 \hb@xt@ #1{%
   \@tempcnta=\z@
   \@tfor\member:=#2\do{\advance\@tempcnta\@ne}%
   \@tfor\member:=#2\do{%
      \advance\@tempcnta\m@ne
      \ifnum\@tempcnta=\z@
         \member
      \else
         \member\hfil
      \fi
   }%
 }%
}
\makeatother
\begin{description}
 \warihaba{7zw}
 \item[\warituke{集合場所}] どこでもいいでつ。
 \item[\warituke{日時}] いつでもいいでつ。
 \item[\warituke{持参するもの}] なんでもいいでつ。
 \item[\warituke{その他}] てきとうに。
 \item[\warituke{Place}] 英語でつか?
\end{description}

ascmac.sty 解体

執筆中

array/tabular 環境実装への道 其の一

まずは \hbox と \vbox に関する説明から、 \hbox は中身を水平に組む、 途中改行はなし。\vbox は中身を垂直に組む。 まずは以下の出力例を吟味した方が良いでしょう。

% これは割とうまく組れる
\fbox{\vbox{\hbox{a}\hbox{b}\hbox{c}}}\par
% \vbox は組むべき幅が \linewidth だと誤解する
\fbox{\hbox{\vbox{a}\vbox{b}\vbox{c}}}\par
% これも割とうまく組まれる
\fbox{\hbox{\hbox{a}\hbox{b}\hbox{c}}}\par
% \vbox は \vbox のなかでは 幅が分からず
\fbox{\vbox{\vbox{a}\vbox{b}\vbox{c}}}\par

実質的に 長さを特別に指定しない場合はこのような恐いことになるので \vbox のなかでは \hbox, \hbox のなかでは \vbox ということになります。 TeX 上では \fbox とか \framebox などは定義されていないので LaTeX 側で

\def\waku#1{\ifvmode\leavevmode\fi
  \hbox{\vrule\vbox{\hrule\hbox{hoge}\hrule}\vrule}}

などとしています(実際はもうちょっと手を加える)。さきに \vrule で 囲む方法ももちろんあります。

\def\vwaku#1{\ifvmode\leavevmode\fi
   \vbox{\hrule\hbox{\vrule\hbox{#1}\vrule}\hrule}%
}

次に 3 行 3 列の単純な表を作ることを考えます。先ほどの \hbox と \vbox を使って簡単な例題を見たので、あるていどは分かるでしょう。

\begin<hoge> ... \end<hoge>

次のファイル hoge.tex を ptex (tex, pdftex でも) でタイプセットしてみて下さい。

\let\TeXorigEnd\end
\def\begin#1{\csname #1\endcsname}
\def\end#1{\csname end#1\endcsname}
%
\long\def\newenvironment#1#2#3{%
  \expandafter\def\csname #1\endcsname{#2}%
  \expandafter\def\csname end#1\endcsname{#3}%
}
%
\newenvironment{document}{\relax}{\TeXorigEnd}
\newenvironment{math}{$}{$}
\newenvironment{displaymath}{$$}{$$}
\def\({$}%$
\def\){$}%$
\def\[{$$}%$$
\def\]{$$}%$$
%
\begin{document}
Hello, World!!
\begin{math}
 f(x) = ax + b
\end{math}
Hello, World!!
\begin{displaymath}
 E = mc^2.
\end{displaymath}
hoge $a^2$, hoge.
\[
 f'(u)= f(u)(1-f(u))
\]
\end{document}

何をやっているのか、吟味して下さい。

見出しの定義のされ方

\@startsection{<カウンタ名>}{<深さ>}{<字下げ幅>}{<前空き>}{<後空き>}{<体裁>}
<体裁> = {書体変更 | サイズ変更 | 揃え (\centering, \raggedrigth, \raggedleft, \MakeUppercase)}
if <後空き> < 0 -> 文中見出し (paragraph のような)
\secdef ->

通常は次のような \hoge 命令を定義するには \@ifstar と \@ifnextchar を 使うことになります。

\documentclass[a4j,11pt,papersize]{jsarticle}
\makeatletter
\def\hoge{\@ifstar {\@hoge}{\@hoge}}
\def\@hoge{\@ifnextchar[{\@@hoge}{\@@hoge[\@empty]}}
\def\@@hoge[#1]#2{任意引数は`#1', 必須引数は`#2'}
\makeatother
\begin{document}
\hoge{ひ}\par
\hoge*{ひ}\par
\hoge[に]{ひ}\par
\hoge*[に]{ひ}\par
\end{document}

しかし、毎回これをやっていては付かれるので見出しに関しては \secdef なる コマンドが用意されています。また、 星付き * の場合は目次に書き出さないと いう暗黙の了解があるので、

\hoge*[に]{ひ}

というパターンは許容しません。ですから

\documentclass[a4j,11pt,papersize]{jsarticle}
\makeatletter
\def\hoge{\secdef {\@hoge}{\star@hoge}}
% 任意引数が与えられていないときは自動的に 必須引数が渡される
%    \@ifnextchar[{\@hoge}{\one@hoge}
%    \def\one@hoge#1{\@hoge[#1]{#2}}
% と同じこと。
\def\@hoge[#1]#2{任意引数は`#1', 必須引数は`#2'}
\def\star@hoge#1{星付で必須引数は`#1'}
\makeatother
\begin{document}
\hoge{目次にも出力される見出し}\par
\hoge*{目次には出力されない見出し}\par
\hoge[目次用のテキスト]{見出し用の長いやつ}\par
\end{document}

という例があれば、

という出力になります。

目次情報の出力 (.toc, .lof, .lot, .aux)

\addtocontents{<file>}{<stuff>}
\addcontentsline{<file>}{<type>}{<stuff>}

から

\contentsline{<>}{<>}

借りに 次のような filename.tex を用意して 2 回程タイプセットを行なえば

\documentclass[a4j,11pt,papersize]{jsarticle}
\begin{document}
\tableofcontents
\listoffigures
\listoftables
\section{ほげ}
\subsection{どれ}
\subsubsection{ほれ}
\paragraph{ありゃ}
\subparagraph{こりゃ}
\begin{table}[htbp]
 \caption{ほげ}
\end{table}
\begin{figure}[htbp]
 \caption{どれ}
\end{figure}
\end{document}

それぞれ \jobname.toc では

\contentsline {section}{\numberline {1}ほげ}{1}
\contentsline {subsection}{\numberline {1.1}どれ}{1}
\contentsline {subsubsection}{\numberline {1.1.1}ほれ}{1}
\contentsline {paragraph}{ありゃ}{1}
\contentsline {subparagraph}{こりゃ}{1}

さらに \jobname.lof では

\contentsline {figure}{\numberline {1}{\ignorespaces どれ}}{1}

ついでに \jobname.toc では

\contentsline {table}{\numberline {1}{\ignorespaces ほげ}}{1}

極めつけに \jobname.aux では

\relax
\@writefile{toc}{\contentsline {section}{\numberline {1}ほげ}{1}}
\@writefile{toc}{\contentsline {subsection}{\numberline {1.1}どれ}{1}}
\@writefile{toc}{\contentsline {subsubsection}{\numberline {1.1.1}ほれ}{1}}
\@writefile{toc}{\contentsline {paragraph}{ありゃ}{1}}
\@writefile{lot}{\contentsline {table}{\numberline {1}{\ignorespaces ほげ}}{1}}
\@writefile{lof}{\contentsline {figure}{\numberline {1}{\ignorespaces どれ}}{1}}
\@writefile{toc}{\contentsline {subparagraph}{こりゃ}{1}}

目次の体裁

\@dottedtocline{<>}{<>}{<>}{<>}{<>}
\@pnumwidth
\@tocrmarg
\@dotsep
\l@<なんとか>

list/trivlist 環境・汎用的なリスト環境

(執筆中)

\ps@なんちゃら

fancyhdr については 初級編で紹介しているので、ここでは

\ps@なんちゃら
\markなんちゃら
\なんちゃらmark 

を紹介する。

索引作成

ここでは索引ページや辞書などに見られるような爪を付けることを 考えます。索引のページのページスタイルは

偶数頁小口偶数頁ノド奇数頁ノド奇数頁小口
<頁先頭の語句><頁末尾の語句><頁先頭の語句><頁末尾の語句>

というものにしたいと考えます。しかし、これを実現するためにはその ページの末尾を知る (ページの取得) を試みなければならないため、まずは

A, B,..., X, あ, い,..., わ, を, ん

という索引頭文字をノド部分に表示させることを考えましょう。 あらかじめ簡単にするために索引用スタイルファイル thumb.ist を次のように 定義したとします (upmendex を使うことを前提としています)。

lethead_flag            1
symhead_positive       "数字/記号"
letter_head            2
delim_0                        " \\dotfill\\ "
delim_1                        " \\dotfill\\ "
delim_2                        " \\dotfill\\ "
lethead_prefix "\\underline{\\hbox to \\linewidth{\\large\\textbf{\\thumb{"
lethead_suffix "}\\hfill}}}\\nopagebreak"

\thumb という命令は \thumb{A}, \thum{B} のように更新されるので、あとは 索引の頭文字の受け皿を作ります。

(執筆中)

\@なんちゃら

\@ifstar と \@ifnextchar の使い方

\documentclass{article}
\makeatletter
\def\hoge{\@ifstar{star \@hoge}{\@hoge}}
\def\@hoge{\@ifnextchar[{\@@hoge}{\@hoge[\@empty]}}
\def\@@hoge[#1]#2{[#1](#2)}
\makeatother
\begin{document}
\hoge[do]{re}\par
\hoge*[a]{jo}\par
\hoge{sfoa}\par
\hoge*{sfal}\par
\end{document}
\@gobble
\@gobbletwo
\@ほげほげ
(執筆中)

equation 環境もどき

まぁ、てきとうに改行して \displaystyle で表示させる、なんてことも できるわけで、それでいて equation カウンタを増分させて、てきとうに 右端にでも表示させればいいわけで。

\def\equation{\\\nopagebreak%
   \refstepcounter{equation}%
   \hfill\bgroup$\displaystyle}%$
\def\endequation{$\egroup\hfill(\theequation)\\\nopagebreak
   \ignorespacesafterend}%$

似非ですけど。

\begin{equation}
f(x) = ax + b
\end{equation}
hogehoge

とした場合、 \end{equation} の後の改行がホワイトスペースとなり、 hogehoge の前にスペースとして表れるので \ignorespacesafterend が 必要となります。

1行を文字で埋める。

かなりてきとうに

 (行長 / 全角 1 文字の幅)

を求めて、あとは \noindent でもかましておけば

\makeatletter
\def\hoge{\noindent%
   \@tempcntb=\number\linewidth
   \divide \@tempcntb by \number\cwd
   \@tempcnta=\z@
   \@whilenum\@tempcnta<\@tempcntb\do{あ\advance\@tempcnta\@ne}}
\makeatother

と定義できるので、

\par\hoge\par

とかやればなんとかなるでしょう。

dimention から pt を取り除く

\@tempdima = 100.5pt として \@tempdima を設定したとしたならば

\the\@tempdima 

100.5pt

というトークンが得られるが、この 100.5pt から単位の pt を取り除きたい ときがしばしばある。単純に \@tfor で

\makeatletter
\def\hoge{\the\linewidth}
\@tfor\temp@str:=\hoge\do{%
   \if\temp@str p\relax
   \else
      \if\temp@str t\relax
      \else
         \temp@str
      \fi
   \fi
}
\makeatother

とできるというわけではない。ここで一つ厄介なのは pt のカテゴリーコードで である。と、安易にここでカテゴリーコードを変更してもいけない。

(執筆中)

ページスタイルの改変 その1

LaTeX の標準では

\thispagestyle{<page_style>}
\pagestyle{<page_style>}

とすることにより、特定ページだけのページスタイルの変更や、それ以降の ページスタイルの変更が行なえます。標準的なクラスファイルで提供されている スタイルには

empty
左右上下、何も表示しない
plain
左右ページ下端中央にページ番号のみを出力する
headings
\leftmark (偶数頁), \rightmark (奇数頁) とページ番号(両頁) をヘッダーに 出力する。book/report 系クラスファイルでは
\leftmark := \chaptermark
\rightmark := \sectionmark
となり、article 系クラスでは
\leftmark := \sectionmark
\rightmark := \subsectionmark
等となることが多い。
myheadings
\markright{<偶数頁に出力する要素>} か \markboth のいずれかにより ヘッダーの要素 (\leftmark, \rightmark) を決める。

ページスタイルの改変 その 2

LaTeX では

\pagestyle{headings}

などとすると

\def\ps@headings{%
<ページスタイルの定義内容>
}

が参照されることになります。ここでは

\@oddhead
奇数ヘッダ
\@oddfoot
奇数フッタ
\@evenhead
偶数ヘッダ
\@evenfoot
偶数フッタ の四つを最低でも定義しなければなりません。 もっともシンプルな empty スタイルは次のように定義されています。
\def\ps@empty{%
   \let\@mkboth \@gobbletwo
   \let\@oddhead \@empty
   \let\@oddfoot \@empty
   \let\@evenhead \@empty
   \let\@evenfoot \@empty
}
これらはおおよそすべてのページスタイルに関わるコマンドを 空にします。 \@empty は {} に展開されるので、
\def\@oddhead{}
と定義したことと同じ意味になります。\@mkboth は
\let\@mkboth\@gobbletwo
として引数を二つ無効にするマクロとして代入されています。 \@mkboth はユーザーが指定するものではなく、クラスファイルの なかなどで使われています。 これは例えばユーザが
\markboth{ほげほげ}{ほげほげ}
\markright{ほげ}
とした場合は有効になります。

次に plain スタイルを見てみましょう。これは \@oddfoot と \@evenfoot の 中央にページ番号を出力すれば良いだけなので、 empty スタイルを 少し書き換えるだけで良いことになります。

\def\ps@plain{%
   \let\@mkboth \@gobbletwo
   \let\@oddhead \@empty
   \def\@oddfoot{\reset@font \hfil\thepage\hfil}%
   \let\@evenhead \@empty
   \let\@evenfoot \@oddfoot
}

empty と同様に空にするところは空にします。 問題となる \@oddfoot は

\def\@oddfoot{\reset@font \hfil\thepage\hfil}%

として \hfil でサンドイッチにすることで中央にします。 ついでに書体を標準の設定にするために \reset@font をここに追加します。 このように \@oddfoot を定義し、これを \@evenfoot にも同様に代入します。

\let\@evenfoot \@oddfoot

これで plain が完成します。

次は myheadings を考えてみます。 これはユーザーが \leftmark と \rightmark を 適宜設定すると言うことを前提とするため、案外簡単に定義できます。 常識的・慣習的・規則的に、普通は 奇数頁が右側、偶数頁が左側にくる 事になります (左綴じの場合です、右綴じの場合は逆です)。 headings なのでフッターは空にします。またページ番号はノドではなく 小口に出すようにするのが古くからの慣習です。\leftmark と \rightmark は ノドに出します。

\def\ps@myheadings{%
   \let\@oddfoot\@empty
   \let\@evenfoot\@empty
   \def\@evenhead{\reset@font\thepage \hfil \leftmark}%
   \def\@oddhead{\reset@font\rightmark \hfil \thepage}%
   \let\@mkboth \@gobbletwo
   \let\chaptermark \@gobble
   \let\sectionmark \@gobble     
    \let\subsectionmark \@gobble % article 系
}

実は \leftmark や \rightmark は \section や \chapter などの 特定の見出し命令が呼び出されたときに自動的に

\chaptermark{<\chapter の必須引数>}
\sectionmark{<\section の必須引数>}

などが実行されてマークが設定されてしまいます。これを 無効化するために \chaptermark や \sectionmark (article 系の場合は \chaptermark はない) を引数を一つ無効にするという命令を代入します (\@gobble)。

これでとりあえずは myheadings が定義できます。適宜、ヘッダーの 書体を変更するあり \reset@font で書体を標準にするなどが考えられます。 欧文の場合は \slshape でスラント体に変更することが多いようです (本文と ヘッダを明確に分離するために賢い方法)。

さて、いよいよ本命の headings を定義します。今回は report/book 系のクラスで 用いることを前提とします (さらに twoside で openright というオプション付き)。 article 系で用いる場合は

\chaptermark (0) -> \sectionmark (1)
\sectionmark  (1)-> \subsectionmark (2)

などに変更するなどの細かい部分だけですので、すぐに応用できるでしょう。 まずは特に難しく考えなくてもできるものから定義しましょう。 \@mkboth は 今回 \markboth, \markright がユーザ支配ではないのでクラスファイル側支配と するため \markboth を代入します。。フッターも空にします。\@evenhead と \@oddhead は myheadings の定義と同様で構いません。

\def\ps@headings{%
    \let\@oddfoot \@empty
    \let\@evenfoot \@empty
    \let\@evenhead{\reset@font \thepage \hfil \leftmark}%
    \let\@oddhead{\reset@font \rightmark \hfil \thepage}%
    \let@mkboth \markboth

さて、ここまでは簡単ですが、 問題の \chaptermark と \sectionmark を定義して いません。\chaptermark でやるべき事は \leftmark を適切に設定することです。 この場合、前付・後付以外では「第 3 章 章見出しタイトル」となるようにします。 さらに通常は secnumdepth によってユーザがカウンタをつけるか否かを制御 するため、この条件判断も必要になります。\sectionmark も同様な方法で判定します。

\def\chaptermark##1{%
   \markboth{%
      \ifnum \c@secnumdepth >\m@ne
         \if@mainmatter
            第 \thechapter 章\hskip 1zw
         \fi
      \fi
      ##1}{}%
}%
\def\sectionmark##1{%
   \markright{%
      \ifnum \c@secnumdepth >\z@
         \if@mainmatter
            \thesection \hskip 1zw
         \fi
      \fi
      ##1}%
}%

\chaptermark も \sectionarmk の定義も \def の中の \def なので ## で井桁をエスケープ させます。また、secnumpdeth の裸のカウンタ数を参照するために \c@secnumdepth を \ifnum で使用していますし、\@mainmatter というブール値も 本文かどうかを 判定するために使用しています。大抵の report/book 系のクラスファイルは

表紙
\frontmatter
前付け
\mainmatter 
本文
\backmatter
後付

という構造にするように設計されているので、\mainmatter が実行されたときに \@mainmatter は true になっています。欧文の場合は見出しのタイトルを大文字に するとか色々と慣習があるので、引数全体を \MakeUppercase? で括るという こともあります。

しかし、このままでは実は問題があります。それは \chapter など、章見出しが 存在するページのページスタイルです。これは \chapter 命令が呼び出された段階で

\thispagestyle{plain}

等のようにページ下端中央にページ番号だけを表示する仕様になっています。 章見出しがあるページはそれだけで要素としての強度があるので、ページ番号を 柱 (ヘッダー) に出力すべきではない、という考え方もあります。これはヘッダに 下線を引いた場合などに実感できます (このような思想の詳しい事は組版系の書籍 を参照してください)。そこで、章見出しのあるページだけ、ページ番号を出力 するシンプルなページスタイル plain を採用します。

大抵の場合は headings を通常のページスタイルとして plain は使っていません (書籍 などでは)。そこで plain ページスタイルを再定義することで、一時凌ぎをします。

\def\ps@plain{%
   \let\@mkboth \@gobbletwo
   \def\@oddhead{\reset@font \hfil \thepage}%
   \let\@oddfoot \@empty
   \let\@evenhead \@empty
   \let\@evenfoot \@oddfoot
}

これで、とりあえず、ページスタイルの基本は終了です。

ページスタイルの改変 その 3

さて、前回と前々回はページスタイルの基本的な事を学習しました。 まだ、\mark, \leftmark, \rightmark, \@themark 等には触れていませんが、 ある程度の体裁の調整は出来るようになっています。例えば、小口部分に \leftmark, \rightmark を出力せずにページ番号のそばにおくためには、次のように \@oddhead, \@evenhead を定義すれば良いことになります。

\def\@evenhead{\reset@font \thepage \hskip 1zw \leftmark \hfil}%
\def\@oddhead{\reset@font \hfil \rightmark \hskip 1zw \thepage}%

また、ヘッダーのノド部分にあるタイトル \@headtitle を、小口部分には \leftmark, \rightmark を表示させるようにします。ページ番号は フッターの小口に出すには次のようにします。

\gdef\@headtitle{好き好き \LaTeXe 初級編}%
\def\@evenhead{\reset@font \leftmark \hfil \@headtitle}%
\def\@oddhead{\reset@font \@headtitle \hfil \rightmark}%
\def\@evenfoot{\reset@font\bfseries \thepage \hfil}%
\def\@oddfoot{\reset@font\bfseries \hfil \thepgae}%

多くの書籍で見掛けることが出来ますが、ヘッダ部分に下線を付加する 方法の一つを紹介します。\textwidth の幅を持つヘッダ用の箱 (\hbox) に 対して下線を引けば良いので、次のように \@evenhead と \@oddhead を 定義します。

\def\@evenhead{\underline{\hb@xt@ \textwidth{\thepage  \hfil \leftmark}}}%
\def\@oddhead{\underline{\hb@xt@ \textwidth{\rightmark \hfil \thepage}}}%

\hb@t@ は \hbox to の事です。

おまけとして爪掛け (thumb-index) のあるページスタイルを考えてみます。 爪は奇数ページだけに出力するものとし、爪部分は白色で章番号を、 爪の背景は黒で、章番号に応じて爪の位置を下げるという事を実現 することを考えます。簡単のために picture 環境を使って領域 0 の要素を 追加します。今回は裁断における綴じの誤差が出ることを予想して、 偶数ページには爪を表示させません。まずは爪を表示させる汎用的な マクロ \page@tume を次のように定義します。 爪は 本文 (\mainmatter の後) にだけ表示すれば良いので \if@mainmatter で 判断をします。

\def\page@tume{%
   \if@mainmatter
      \setlength\unitlength{1truecm}%
      \begin{picture}(0,0)%
      \put(1,-\value{chapter}){%
         \makebox(0,0)[tl]{\rule{1truecm}{1truecm}}}%
      \put(1,-\value{chapter}){%
         \makebox(0,-.4)[tl]{%
            \textcolor{white}{\hb@xt@ 1truecm{\hfil\sffamily\thechapter\hfil}}}}%
      \end{picture}%
   \fi
}

しかし、このままでは章番号がどんどん増えて行くとページの下端を はみ出して最終的にはあっちの世界に旅だってしまうので、適当な 場所で折り返します。これは (\textwidth -1truecm)/1truecm で等によって 算出することが出来るの (今回の場合は一つの爪が 1cm で構成される) で、

\newcount\cnt@tume
\AtBeginDocument{%
   \cnt@tume=\textheight
   \setbox0=\hbox{\vrule width 0pt height 1truecm}%
   \@tempcnta=\ht0
   \advance\cnt@tume -\@tempcnta
   \divide \cnt@tume \@tempcnta
}

として \cnt@tume に適当な上限値を与えます。とりあえず、上限値を 越える章番号 (\c@chapter) に関しては、上限値 (cnt@tume) で割った 余りで出力すれば良いので、

\newcount\cnt@tume@no
 \def\get@tume@num{%
     \@tempcnta=\c@chapter
     \@whilenum \@tempcnta>\cnt@tume \do{\advance\@tempcnta -\cnt@tume}%
     \cnt@tume@no=\@tempcnta
}

として現在の章に応じた余り (\cnt@tume@no) を求めるマクロ \get@tume@num を定義します。このようにして \cnt@tume (これはプリアンブルなどに配置すると 良いが、ページレイアウトを変更するコマンドと \cnt@tume@no を求める 準備が出来たならば、先程の \page@tume を次のように書き換えます。

\def\page@tume{%
   \if@mainmatter
      \setlength\unitlength{1truecm}%
      \begin{picture}(0,0)%
      \get@tume@num % ここで \cnt@tume@no を求める
      \put(1,-\the\cnt@tume@no){%
         \makebox(0,0)[tl]{\rule{1truecm}{1truecm}}}%
      \put(1,-\the\cnt@tume@no){%
         \makebox(0,-.4)[tl]{%
            \textcolor{white}{\hb@xt@ 1truecm{\hfil\thechapter\hfil}}}}%
      \end{picture}%
   \fi

ヘッダが書き出される度に \get@tume@num が呼び出されて不経済ですが、 今回はこれで妥協しましょう。全体をまとめると次のようになります。

\documentclass{book}
\usepackage[dvips]{color}
%
\makeatletter
\newcount\cnt@tume % 折り返し地点 + 1
\newcount\cnt@tume@no % 実際に爪を出力すべき位置
%
\def\@prechaptername{第}
\def\@postchaptername{章}
% \cnt@tume を \textheigth により求める
\AtBeginDocument{%
   \cnt@tume=\textheight
   \setbox0=\hbox{\vrule width 0pt height 1truecm}%
   \@tempcnta=\ht0
   \advance\cnt@tume -\@tempcnta
   \divide \cnt@tume \@tempcnta
}
% \cnt@tume@no をそのときの \c@chapter により求める \get@tume@no
\def\get@tume@num{%
   \@tempcnta=\c@chapter
   \@whilenum \@tempcnta>\cnt@tume \do{\advance\@tempcnta -\cnt@tume}%
   \cnt@tume@no=\@tempcnta
}
% 実際に爪を表示するためのマクロ \page@tume
\def\page@tume{%
   \if@mainmatter
      \setlength\unitlength{1truecm}%
      \begin{picture}(0,0)%
      \get@tume@num
      \put(1,-\the\cnt@tume@no){%
         \makebox(0,0)[tl]{\rule{1truecm}{1truecm}}}%
      \put(1,-\the\cnt@tume@no){%
         \makebox(0,-.4)[tl]{%
            \textcolor{white}{\hb@xt@ 1truecm{%
               \hfil\sffamily\thechapter\hfil}}}}%
      \end{picture}%
   \fi
}
% \chapter のあるページにおけるスタイル \page@tume を \@oddhead に追加
\def\ps@plain{%
    \let\@mkboth \@gobbletwo
    \def\@oddhead{\reset@font \hfil \thepage\page@tume}%
    \let\@oddfoot \@empty
    \let\@evenhead \@empty
    \let\@evenfoot \@oddfoot
}
% 主となるページスタイル
\def\ps@headings{%
 \let\@oddfoot=\@empty
 \let\@evenfoot=\@empty
 \def\@evenhead{\underline{\hb@xt@ \textwidth{\thepage  \hfil \leftmark}}}%
 \def\@oddhead{\underline{%
    \hb@xt@ \textwidth{\rightmark \hfil \thepage}}%
    \page@tume}% \@oddhead の最後に爪を追加
 \let\@mkboth=\markboth
 \def\chaptermark##1{%
    \markboth{%
       \ifnum \c@secnumdepth >\m@ne
          \if@mainmatter
             \@prechaptername \thechapter \@postchaptername \hskip 1zw
          \fi
       \fi
       ##1}{}%
 }%
 \def\sectionmark##1{%
    \markright{%
       \ifnum \c@secnumdepth >\z@
          \if@mainmatter
            \thesection \hskip 1zw
          \fi
       \fi
       ##1}%
 }%
}
\makeatother
\pagestyle{headings}
\begin{document}

\framebox, \fbox 実装への道 その1 boxsep, boxrule, vbox, hbox の使い方

さてさて、\LaTeX では \framebox などに見られるような、LR 要素の四方を 線で囲み、枠を付けるコマンド \framebox/\fbox が用意されています。これを TeX のマクロのみで実装する方法を考えましょう。まずは考え方です。 次の図を御覧だくさい。二通りのアプローチがあります。

\def\cmd#1{\bgroup\ttfamily\string#1\egroup}
\def\pa#1{$\left\{\mbox{}\mbox{#1}\mbox{}\right\}$}
\hbox{%
  \cmd{\vbox}\pa{$\vcenter{%
     \hbox to 14zw{\hrulefill\ \cmd{\hrule}\ \hrulefill}%
     \hbox to 14zw{\hfil\cmd{\hbox}\pa{\hbox{%
       \ \vrule\ {{\cmd{\vbox}\pa{文章要素}}}\ \vrule\ }}\hfil}%
     \hbox to 14zw{\hrulefill\ \cmd{\hrule}\ \hrulefill}%
  }$%
}}
 \hbox{%
  \cmd{\hbox}\pa{$\vcenter{\hbox{%
   \vrule \hskip 1ex
   \vbox{%
      \hbox to 10zw{\hrulefill\ \cmd{\hrule}\ \hrulefill}%
      \hbox to 10zw{\hfil \cmd{\hbox}\pa{文章要素}\hfil }%
      \hbox to 10zw{\hrulefill\ \cmd{\hrule}\ \hrulefill}%
   }%
   \hskip 1ex \vrule
  }}$%
}}

さて、このような考え方に基づくと、次のような構成になります。

\vbox{%
   \hrule%
   \hbox{\vrule\hbox{\pa{文章要素}}\vrule}%
   \hrule%
}

ここで、文章要素と枠とを離れさせるための間隔 \myboxsep を導入します。 初期値は適当に 3pt ということにしておきます。

\newlength{\myboxsep}
\setlength\myboxsep{3pt}

このようにして、

\ifvmode \leavevmode \fi\vbox{%
   \hrule
   \par\vskip \myboxsep
   \hbox{\vrule \hskip \myboxsep \pa{文章要素}\hskip \myboxsep \vrule}%
   \par\vskip \myboxsep
   \hrule
}

縦の罫線を先に引く方法ではちょっと考え辛いので、 横の罫線を先に引く場合で考えてみます。

\ifvmode \leavevmode \fi
\hbox{%
   \vrule
   \vbox{%
      \hrule 
      \par \vskip \myboxsep
      \hbox{\hskip \myboxsep\cmd{\hbox}{\pa{文章要素}\hskip \myboxsep}%
      \par \vskip \myboxsep
      \hrule 
   }%
   \vrule
}

上記のようにすると、見事に \myboxsep が生きています。 さらに、続いて枠の太さを決める \myboxrule も導入します。

\newlength{\myboxrule}
\setlength\myboxrule{3pt}

初期値は適当に 3pt にでもしておきます。 すると次のように \myframebox が定義できます。

\def\myframebox#1{\ifvmode \leavevmode \fi
 \hbox{%
   \vrule width \myboxrule
   \vbox{%
      \hrule height \myboxrule
      \par \vskip \myboxsep
      \hbox{\hskip \myboxsep #1\hskip \myboxsep}%
      \par \vskip \myboxsep
      \hrule height \myboxrule
   }%
   \vrule width \myboxrule
 }%
}

単に \vrule には幅 (width) を、\hrule には高さ (height) を指定するだけです。 また、次のようにして枠がぴったりとくっつく \myfbox も作ることが出来ます。

\def\myfbox#1{%
 \begingroup
   \setlength\myboxsep{0pt}%
   \myframebox{#1}%
 \endgroup
}

使用例は次のようになります。

\myframebox{文章要素}, \myfbox{文章要素}, \myframebox{文章要素}\par
\myboxrule=.4pt \myfbox{文章要素}

さて、本来 \framebox は

\framebox[<幅>][<位置指定子>]{<文章要素>}

のような使い方が出来るのでまだ不十分ですが、今日はこのへんで 終わりにしましょう (眠いのでもう寝ます)。

ある範囲の見出しを目次に出力したくない

\addcontentsline と \addtocontents を無効化すれば良いので

\documentclass{book}
\begin{document}
\tableofcontents
\begingroup % ここから見出しを目次に出したくない
\def\addcontentsline#1#2#3{}% \@gobble \@gobbletwo
\def\addtocontents#1#2{}% \let\addcontents \@gobbletwo
\chapter{ほげ}
ほげほげほげ。
\section{ほえ}
ほえほえほえ。
\endgroup% ここまで見出しを目次に出したくない
\chapter{うりゃ}
うりゃうりゃうりゃ。
\end{document}

jsclasses で図表番号の後にコロンを表示したいとか

図表番号のスタイルは \thefigure, \thetable で再定義できる。

\renewcommand*\thefigure{\@arabic\c@figure}
\renewcommand*\thetable{\@arabic\c@table}

スタイルに関しては \fnum@figure, \fnum@table で決められる。 \figurename, \tablename はそれぞれクラスファイルで定義されている ものとする (\def\figurename{図}, \def\tablename{表})。

\documentclass[a4j]{jsarticle}
\makeatletter
\def\fnum@figure{\figurename\nobreak\thefigure:}
\def\fnum@table{\tablename\nobreak\thetable:}
\makeatother
\begin{document}
\begin{figure}[htbp]
\caption{ほげほげ}
\end{figure}
\begin{table}[htbp]
\caption{どれどれ}
\end{table}
\end{document}

スタイルを「第 8 図」などとしたければ

\def\prefigurename{第}
\def\postfigurename{図}
\def\fnum@figure{\prefigurename\nobreak\thefigure\nobreak\postfigurename}

等とすれば良いだろう。

リットルとかメートルを一文字に納める

\documentclass[a4j,11pt,papersize,draft]{jsarticle}
\makeatletter
\newcommand*\ju[4]{%
   \bgroup
      \offinterlineskip% \vbox 中における skip を無効にする
      \ifvmode\leavevmode\fi
      \vbox{%
         \hbox to \cwd{\hss\hbox{\tiny #1}\hbox{\tiny #2}\hss}%
         \hbox to \cwd{\hss\hbox{\tiny #3}\hbox{\tiny #4}\hss}%
      }%
   \egroup
}
\makeatother
\begin{document}
リットル、メートルを、全角 1 文字分に納める、50\ju リットルとか
30\ju メートル。
\end{document}

どうせなら割注もだしたい

リットルのように 4 文字だけじゃなくて、割注も出力したい。一応縦組にも対応。

\documentclass[a4j]{jsarticle}
%\documentclass[a4j]{tarticle}
\makeatletter
%
\def\@left@warichu@delim{(}
\def\@right@warichu@delim{)}
\def\leftwaridelim#1{\gdef\@left@warichu@delim{#1}}
\def\rightwaridelim#1{\gdef\@right@warichu@delim{#1}}
%
\def\warichu#1{%
   \@tempcnta \z@
   \@tfor\member:=#1\do{\advance\@tempcnta\@ne}%
   \ifodd\@tempcnta\relax \advance\@tempcnta\@ne \fi
   \divide\@tempcnta\tw@
   \let\@first@line\@empty
   \let\@second@line\@empty
   \@tempcntb \z@
   \@tfor\member:=#1\do{%
      \ifnum \@tempcntb<\@tempcnta
         \edef\@first@line{\@first@line\member}%
      \else
         \edef\@second@line{\@second@line\member}%
      \fi
      \advance \@tempcntb \@ne
   }%
   \ifvmode\leavevmode\fi
   \@left@warichu@delim
   \iftdir \lower \Cdp \fi
   \hbox{%
      \bgroup
         \offinterlineskip
         \vbox{%
            \hbox{\tiny\@first@line}%
            \hbox{\tiny\@second@line}%
         }%
      \egroup
   }%
   \@right@warichu@delim
}%
\makeatother
\begin{document}
ドナルド・クヌース\warichu{計算幾科学において偉大な功績を残した人物の一
人}は我々が毎日毎晩使っているあの\TeX を開発した科学者である。\par
\end{document}

文中の < > ^ _ ` ' "

文中で < > ^ _ ` ' " などを記述すると、当然ながらエラーになります。 しかし、以下の例は恐ろしいことをやっているため、一応出力できる ようになっています。

\documentclass{jarticle}
\makeatletter
% "
\def\dq{"}%"
\catcode 34=\active
\newif\ifDQ
\def"{\ifmmode \rq\rq \else \ifDQ \rq\rq \DQfalse \else \DQtrue \lq\lq\fi\fi}%" % `^' and `_'
\catcode`\^=\active
\catcode`\_=\active
\def^{\ifmmode \sp \else \^\relax \fi}
\def_{\ifmmode \sb \else \_\relax \fi}
% `<' and `>'
\def\leftangle{<}
\def\rightangle{>}
\catcode`\<=\active
\catcode`\>=\active
\def<{\ifmmode \leftangle \else $\langle$\fi}
\def>{\ifmmode \rightangle \else $\rangle$\fi}
% ` (\lq) and ' (\rq)
\newif\ifSQ
\catcode`\'=\active
\catcode`\`=\active
\def'{\ifmmode \rq \else \ifSQ \rq \SQfalse \else \SQtrue \lq\fi\fi}
\def`{\ifmmode \lq \else \SQtrue \lq \fi}
\makeatother
\begin{document}
\texttt{http://www.any.dom.jp/hoge_hoge/}\par
$hoge_hoge$\par
<hoge>\par
Hello, <hoge> is $x<3$.\par
'Hoge' is my `hoge.' `hoge' is 'hoge'.\par
d\`am\'e, d\'am\'e\'e\'e\'e. H\"o\"o\"o.\par
"Hoge" is my ``hoge.'' "hoge'' is ``hoge."\par
\end{document}

縦組で、脚注は横組

\documentclass{tarticle}
\marginparpush=0pt
\pagestyle{empty}
\makeatletter
\def\hoge{\@ifnextchar[{\@hoge}{\@hoge[200]}}
\def\@hoge[#1]{\@tempcnta=\z@
  \@whilenum \@tempcnta <#1 \do{あ\advance\@tempcnta\@ne}}
%
\newcounter{mparchu}[section]
\renewcommand\themparchu{\@arabic\c@mparchu}
\def\tatekyakuchu{\@ifnextchar[{\@tatekyakuchu}{\@tatekyakuchu[\@empty]}}
\def\@tatekyakuchu[#1]#2{%
   \stepcounter{mparchu}%
   \raise\Cht\hb@xt@ \z@{\hss\scriptsize \rensuji{\themparchu}}%
   \marginpar{%
      \setlength\unitlength{\Cvs}%
      \begin{picture}(0,0)%
         \put(\value{mparchu},0){%
            \ifx#1\@empty
               \makebox(0,0)[br]{\hb@xt@ .5\textwidth{\yoko
                  $^\themparchu$ #2\hss}}%
            \else
               \makebox(0,0)[br]{\hb@xt@ .5\textwidth{\yoko
                  $^\themparchu$ #2\dotfill#1}}%
            \fi
        }%
      \end{picture}%
  }%
}
\makeatother
\begin{document}
\section{ほげ\label{sec:hoge}}
\hoge\tatekyakuchu{あれあれこれこれ。}。\par
\hoge\tatekyakuchu{うまうましかじか。}。\par
\hoge\footnote{これは普通の脚注。}。\par
\hoge\tatekyakuchu{それは傍注と呼ばれるそうだ。}。
\hoge[20]\tatekyakuchu{それは脚注と呼ばれるそうだ。}。
\hoge[20]\tatekyakuchu[\ref{sec:hoge}]{プレー2}。
\end{document}

素数

簡単なアルゴリズムで素数を求めるプログラム。難しい方のアルゴリズムでも解けるけど、 教育的目的も強い。

\documentclass{article}
\begin{document}
\makeatletter
\newcount\@prm@i% unsigned int amari;
\newcount\@prm@N% unsigned int N;
\newcount\@prm@j% unsigned j;
\newcount\@prm@k% unsigned k;
\newcount\@prm@x% unsigned l;
% \@prm@i
\def\@amari#1#2{%
   \@prm@i=#1\relax
   \ifnum\@prm@i<#2%
   \else
      \advance\@prm@i-#2\relax%
      \expandafter\@amari{\@prm@i}{#2}%
   \fi
}
% list
\def\showlist#1{[\@for\@member:=#1\do{\@member\space}]}
% prime
\def\prime#1{%
  \@prm@N=#1\relax %  scanf ("%d", &N);
  \xdef\@prime@list{2}% primeList[0] := 2;
  \@prm@x=\@ne \relax % x := 1;
  \@prm@k=\@ne \relax % k := 1;
%
  \@whilenum \@prm@k<\@prm@N \do{% while (k < N) do
    \advance\@prm@x \tw@ \relax % x := x + 2;
    \@prm@j=\z@ \relax % j := 0;
    \@whilenum \@prm@j<\@prm@k \do{% while (j < k) do
      \@tempcnta=\z@ \relax % a := 0;
      \@for\@member:=\@prime@list \do{% while (true) do
        \ifnum\@tempcnta=\@prm@j \relax % if (a == j) do
          \@tempcntb=\@member% b := PrimeList[j];
        \fi
        \advance\@tempcnta \@ne \relax % a := a + 1;
      }%
      \@amari{\@prm@x}{\@tempcntb}% i := x % b;
%
      \ifnum\@prm@i=0 \relax% if (i == 0)
        \@prm@j=\@prm@k \relax % j := k;
        \advance\@prm@j \@ne % j := j + 1;
      \else
        \advance\@prm@j \@ne % j := j + 1;
      \fi
    }% end
%
    \ifnum\@prm@j=\@prm@k % if (j == k) do
      \xdef\@prime@list{\@prime@list,\number\@prm@x}% PrimeList[k] = x;
      \advance\@prm@k \@ne % k := k + 1;
    \fi
  }%
  \expandafter\showlist{\@prime@list}%
}
\makeatother
%
\typein[\hoge]{type the sum of prime number:}
\prime{\hoge}\par
\end{document}

\tableofcontents の内容を HTML にしたい

時々、書籍の組版をして、その LaTeX 原稿の目次だけ欲しい時があります。 これは適当に

c=platex; f=input; $c $f; $c $f; $c $f;

とかやれば $f.toc が作成されるの、これを perl などで適当に処理すれば 良い事になります。例えば次のような入力ファイル input.tex があったと します。

\documentclass[papersize]{jsarticle}
\makeatletter
\makeatother
\begin{document}
\tableofcontents
\section{ほげ}
\subsection{古典}
\subsubsection{うぐぅ}
\subsubsection{そんなこと言う人嫌いです}
\subsubsection{奇跡って起きないから奇跡って言うんですよ}
\subsection{斬新}
\subsubsection{にはは}
\subsubsection{が、がお}
\section{あがが}
\subsection{典型}
\subsubsection{座苦とは違うのだよ、座苦とは!}
\subsubsection{アレは良い物だぁ!}
\subsection{新鋭}
\subsubsection{君の父上がいけないのだよ}
\subsubsection{は、測ったな}
\subsection{最新}
\subsubsection{種割れ}
\subsubsection{新型}
\end{document}

これを適当にタイプセットすれば次のような input.toc が作成されます。

\contentsline {section}{\numberline {1}ほげ}{1}
\contentsline {subsection}{\numberline {1.1}古典}{1}
\contentsline {subsubsection}{\numberline {1.1.1}うぐぅ}{1}
\contentsline {subsubsection}{\numberline {1.1.2}そんなこと言う人嫌いです}{1}
\contentsline {subsubsection}{\numberline {1.1.3}奇跡って起きないから奇跡って言うんですよ}{1}
\contentsline {subsection}{\numberline {1.2}斬新}{1}
\contentsline {subsubsection}{\numberline {1.2.1}にはは}{1}
\contentsline {subsubsection}{\numberline {1.2.2}が、がお}{1}
\contentsline {section}{\numberline {2}あがが}{1}
\contentsline {subsection}{\numberline {2.1}典型}{1}
\contentsline {subsubsection}{\numberline {2.1.1}座苦とは違うのだよ、座苦とは!}{1}
\contentsline {subsubsection}{\numberline {2.1.2}アレは良い物だぁ!}{1}
\contentsline {subsection}{\numberline {2.2}新鋭}{1}
\contentsline {subsubsection}{\numberline {2.2.1}君の父上がいけないのだよ}{1}
\contentsline {subsubsection}{\numberline {2.2.2}は、測ったな}{1}
\contentsline {subsection}{\numberline {2.3}最新}{1}
\contentsline {subsubsection}{\numberline {2.3.1}種割れ}{1}
\contentsline {subsubsection}{\numberline {2.3.2}新型}{1}

今回は手抜きをして pre タグの中に入れてしまいます。 次のような hoge.pl でも用意します。

#!/usr/local/bin/perl -w 
print "<pre>\n";
while (<>){
    s/\\contentsline \{subsubsection\}/    /;
    s/\\contentsline \{subsection\}/   /;
    s/\\contentsline \{section\}/ /;
    s/\{\\numberline \{(.*?)\}(.*?)\}\{.*?\}/$1\. $2/;
    print;
}
print "</pre>\n";

今回はこのように単純にしていますが、もっとこった事も出来ます。 これをもちいて

cat input.toc | perl hoge.pl 

とすれば、次のような出力になります。

<pre>
1. ほげ
  1.1. 古典
   1.1.1. うぐぅ
   1.1.2. そんなこと言う人嫌いです
   1.1.3. 奇跡って起きないから奇跡って言うんですよ
  1.2. 斬新
   1.2.1. にはは
   1.2.2. が、がお
2. あがが
  2.1. 典型
   2.1.1. 座苦とは違うのだよ、座苦とは!
   2.1.2. アレは良い物だぁ!
  2.2. 新鋭
   2.2.1. 君の父上がいけないのだよ
   2.2.2. は、測ったな
  2.3. 最新
   2.3.1. 種割れ
   2.3.2. 新型
</pre>

索引

\documentclass[a5j,papersize]{jsbook}
\usepackage{makeidx}
\usepackage{type1cm}
\makeindex
\usepackage{multicol}
\addtolength \fullwidth {1sp}
\begin{document}
\makeatletter
\def\hoge#1{\@tempcnta=\@ne \setcounter{page}{#1}\@hoge}
\def\@hoge#1{%
  \ifnum \@tempcnta < #1
     \index{\@arabic\@tempcnta\space(\number\@tempcnta)}
     \index{\@roman\@tempcnta\space(\number\@tempcnta)}
     \index{\@Roman\@tempcnta\space(\number\@tempcnta)}
     \index{\the\@tempcnta\space(\number\@tempcnta)}
     \@arabic\@tempcnta
     \advance \@tempcnta \@ne \relax
     \expandafter \@hoge{#1}
  \fi
}
\makeatother
\hoge{1}{200}\clearpage \hoge{3}{300}
\printindex
\end{document}

なんだかんだのマクロ

%\begin{modify}{2005/12/08}{2.00}{Th\'or}
% \@add@title@element {<stuff>} := \def\#1##1{\gdef\@#1{##1}}
\def\@add@title@element#1{%
 \expandafter \def \csname #1\endcsname##1{%
    \expandafter \gdef \csname @#1\endcsname{##1}}%
 \expandafter \global \expandafter \let \csname @#1\endcsname = \@empty
}
\@add@title@element{jtitle}
\@add@title@element{etitle}
\@add@title@element{htitle}
\@add@title@element{jauthor}
\@add@title@element{eauthor}
\@add@title@element{jdate}
\@add@title@element{edate}
\@add@title@element{jaffiliciation}
\@add@title@element{eaffiliciation}
\@add@title@element{studentnumber}
\@add@title@element{jadvisor}
\@add@title@element{eadvisor}
\@add@title@element{jcoadvisor}
\@add@title@element{ecoadvisor}
\global \let \@ecoadvisor = \relax
\global \let \@jcoadvisor = \relax
%\end{modify}

で上の \@add@title@ement は本当は次のように使いたいわけ.

\documentclass[a4j,papersize]{jsarticle}
\usepackage{type1cm,url,okumacro,color}
\makeatletter

% prefix (jsclasses) =  js
%
%  \js@add@element{<stuff>}
\def\js@add@element#1{%
 \expandafter \def \csname js#1\endcsname##1{%
    \expandafter \gdef \csname js@#1\endcsname{##1}}%
 \expandafter \global \expandafter \let \csname js@#1\endcsname = \@empty
}

% add new elements

% font settting
\js@add@element{FontBody}
\js@add@element{FontAppendix}
\js@add@element{FontIndex}
\js@add@element{FontBibliography}
\js@add@element{FontHeader}
\js@add@element{FontFooter}
\js@add@element{FontNombre}
\js@add@element{FontChapter}
\js@add@element{FontChapterNumber}
\js@add@element{FontChapterHeadline}
\js@add@element{FontSection}
\js@add@element{FontSubsection}
\js@add@element{FontSubsubsection}
\js@add@element{FontParagraph}
\js@add@element{FontSubparagraph}
% length setting
\js@add@element{LengthMarginCaption}
% title setting
\js@add@element{FontTitle}
\js@add@element{FontAuthor}
\js@add@element{FontDate}

% default setting

% font setting
\jsFontBody{\normalfont \raggedbottom}
\jsFontAppendix{\small}
\jsFontIndex{\raggedright \footnotesize \narrowbaselines}
\jsFontBibliography{\small}
\jsFontHeader{\rmfamily}
\jsFontFooter{\rmfamily}
\jsFontNombre{\bfseries}
\jsFontChapter{\raggedright \normalfont}
\jsFontChapterNumber{\huge \headfont}
\jsFontChapterHeadline{\Huge \headfont}
\jsFontSection{\normalfont \Large \headfont \raggedright}
\jsFontSubsection{\normalfont \large \headfont}
\jsFontSubsubsection{\normalfont \normalsize \headfont}
\jsFontParagraph{\normalfont \normalsize \headfont ■}
\jsFontSubparagraph{\normalfont \normalsize \headfont ■}

%Title page 
\jsFontTtile{\large}
\jsFontAuthor{\small}
\jsFontDate{\normalsize}

% Length

\jsLengthMarginCaption{1cm}

\makeatother
\begin{document}

\end{document}

訳注用命令を新設する

\newcounter{ftyaku}
\newcommand\yakuchu[1]{%
  \refstepcounter{ftyaku}%
  \nobreakspace \textsuperscript{訳注\theftyaku}%
  \footnotetext{\textsuperscript{訳注\theftyaku}\space#1}%
}

まぁ,こんなもんでしょ. \nobreakspace でも入れとけば,改行しないし, ちょっと scriptsize 位の大きさならばれないんじゃないかな.