いものやま。

雑多な知識の寄せ集め

TeXで同人誌を作ってみた。(奥付)

f:id:yamaimo0625:20190918075457j:plain

同人誌を作るときに必要となるのが奥付。
これはその同人誌を発行したのが誰か分かるようにし、何かあったときに問い合わせが出来るようにするため。
印刷所を使う場合、印刷所の名前も入れることになる。

仕様

今回、奥付は次のようにすることにした:

  • 連絡先は著書紹介にまとめ、奥付の近くに配置
  • 奥付は偶数ページに配置
  • 著者紹介は奇数ページでも偶数ページでもOK(偶数ページの場合は奥付と一緒のページ)

ページ配置

上記の仕様を満たすために、次のようなコードを書いた:

% 著者紹介 + 奥付

\clearpage

% ページスタイルなし
\thispagestyle{empty}

% 著者紹介とか連絡先とか

% 奥付は偶数ページに載せる
\makeatletter%
    \ifodd\c@page%
        \hbox{}\newpage\thispagestyle{empty}%
    \fi%
\makeatother

% 下寄せ
\vspace*{\fill} % *をつけるとページ先頭でも入る。

% 奥付

まず\clearpageで改ページしておいて\thispagestyleでページスタイルをemptyにしておく。
これはページ番号とか柱とか出したくないから。

そして、著者紹介とか連絡先を書く。

そのあとが肝心で、\ifodd\c@pageとすることで、現在のページ番号が奇数の場合だけさらに改ページしてページスタイルをemptyにするとしている。
これによって、著者紹介が奇数ページなら奥付は偶数ページに来て、著者紹介が偶数ページならそのまま同じページが使われる。
\newpageの前に\hbox{}が入ってるのは、たしか著者紹介が空の場合にうまく動くようにするためのはず)

あとは下寄せで奥付を出すために垂直方向の空きを入れている。

奥付の出力

奥付はたしか最初description環境を使って書こうとしたんだけど、何か問題があって(記録が残ってない・・・)tabular環境を使うことにし、それも問題があった(幅いっぱいに表を伸ばせない)ので最終的にtabular*環境を使うのに落ち着いた。

こんな感じ:

% 奥付
\begin{flushleft}
    % 幅いっぱいにするためにtabular*環境を使用
    % @{}とするとパディングがなくなる
    % また、@{...}とすると、セルの区切りに...が入る
    \begin{tabular*}{\textwidth}{@{}l@{\extracolsep{\fill}}}
        \textbf{\huge Math Poker Girl} \\
        \hline
        \begin{tabular}{@{}r@{\kern.5zw}r@{\kern.5zw}r@{\kern1.5zw}ll}
            2019 &  9 & 22 & 初版1刷発行 & (技術書典7) \\
        \end{tabular} \\
        \\
        \begin{tabular}{@{}l@{\kern.5zw\textbf{:}\kern1zw}l}
            \textbf{著者} & やまいも \\
            \textbf{発行} & いもあらい。 \\
            \textbf{印刷} & 有限会社ねこのしっぽ \\
        \end{tabular} \\
        \hline
    \end{tabular*}
\end{flushleft}

ページ幅いっぱいの表

普通のtabular環境で表を作ると「適切な」幅の表にされてしまうので、ページ幅いっぱいの表を作るためにtabular*環境を使った。
引数で表の幅として\textwidthを指定している。

あとは表の列レイアウトの指定で@{\extracolsep{\fill}}を入れると、その列に十分な幅が与えられるっぽい。

・・・と書いててコード見返すと、なんでこれ表使ってるんだろう?
1列しかないから、表にしなくてもいいような。
線を引くのに\hrulefillだと問題があって\hlineを使いたかったとかなのかな・・・

表の縦区切り

表の列レイアウトの指定で|とすると縦線(と空き)が入るのは知っていたけど、@{<tokens>}とすると<tokens>が入るのは知らなかった。
これを利用して@{}とすると空きがまったく入らなくなり、あるいは@{年}とすると区切りにが入るようになると。

発行日の表ではこれを使って年月日をキレイに整えて出力している。
(単に@{年}だと空きがまったく入らなくなってしまうので、@{年\kern.5zw}と半角分の空きを入れてる)

仕上がり

出来上がった著者紹介&奥付は、こんな感じ:

f:id:yamaimo0625:20190921100151p:plain f:id:yamaimo0625:20190921100209p:plain

Re:VIEWの残念な感じの奥付と比較して、なかなかいい感じに出来上がったので嬉しいw

今日はここまで!

TeXで同人誌を作ってみた。(ページスタイル作成)

f:id:yamaimo0625:20190918075457j:plain

今日はページスタイルの作成について。
なお、 \TeX \LaTeXは区別せずに扱っている。

参考にしたのは以下:

LaTeX2ε辞典 増補改訂版

LaTeX2ε辞典 増補改訂版

余談だけど、 \TeXの入門書というと奥村先生の美文書作成入門が定番として挙げられるけど、個人的にはあまり好みでない・・・
持ってはいるし参考にもするけど。
とりあえず必要なことを網羅的にぶち込みましたというリファレンス的な感じが強くて(そのくせ載ってない内容もけっこう多い)、ユーザガイドとしてはちょっと。。。
かといって他にいいユーザガイドがあるかというと難しいところで、まぁつまりは \TeX \LaTeXの設計がもはや古すぎてアレだからキレイに説明するのが難しいんだろうなぁ・・・

そんな中でこの辞典は逆引きのリファレンスのように見えて割とユーザに親切で痒いところに手が届く感じに書いてくれてるのでいい。
もちろん最初にこの本を読んでもサッパリなので、なんとなく手なりで使えるようになった人がちゃんと \TeXを使っていくときに読むといいと思う。

Before / After

閑話休題

ページスタイルを作ることでどうなるのかをまずは示しておく。

作成前はこちら:

f:id:yamaimo0625:20190921115209p:plain f:id:yamaimo0625:20190921115222p:plain f:id:yamaimo0625:20190921115234p:plain

作成後はこちら:

f:id:yamaimo0625:20190921115248p:plain f:id:yamaimo0625:20190921115300p:plain f:id:yamaimo0625:20190921115312p:plain

以下が変わってることが分かると思う:

  • ヘッダの下線がなくなっている
  • ページ番号が縦線(|)で囲われている
  • 章タイトル、節タイトルがページの内側(ノド側)ではなく外側(小口側)に寄せられている

基本的には『数学ガール』をマネたものなんだけど、ページ番号を縦線で囲っているのがオリジナルと違くて、これは柱(章タイトルとか)との区別がつきにくいと思ったから。

ちなみに、他の本を見ると以下のようなデザインもあるみたい:

  • 柱を本文に揃えて、ページ番号はその外へ出す(この場合、ページ番号を枠で囲ったりすることが多いっぽい)
  • 柱を本文に揃えて、ページ番号はフッタで出す
  • ヘッダにはページ番号だけ出し、小口に縦書きで章タイトル/節タイトルを出す

どれも一長一短で、なかなか難しいところ。

ページスタイルの概要

まず、本文領域の上と下にそれぞれヘッダとフッタがある。
そして、ヘッダとフッタの出力をどうするのかを指定するのがページスタイル。

デフォルトで以下のようなページスタイルが用意されている:

ページスタイル 説明
empty ヘッダとフッタに何も出力しない
plain フッタにページ番号を出力する
heading 柱とページ番号をヘッダに出力する
myheading ページ番号とユーザの指定した柱を出力する

独自のヘッダとフッタを出力したい場合、ページスタイルを自分で作ってそのページスタイルを使うことを指定することになる。

ページスタイルを作る場合、以下のようにする:

  1. \ps@<ページスタイル名>を定義(もしくは再定義)して、その定義の中で
    1. 奇数ページのヘッダを出力する\@oddheadを再定義
    2. 偶数ページのヘッダを出力する\@evenheadを再定義
    3. 奇数ページのフッタを出力する\@oddfootを再定義
    4. 偶数ページのフッタを出力する\@evenheadを再定義

それぞれの再定義ではページ番号を出力する\thepageや奇数ページの柱を出力する\rightmark、偶数ページの柱を出力する\leftmarkを使うといい。

なお、柱の内容は\markboth{<left mark>}{<right mark>}などで登録する。
\chapter\sectionでは内部でこれを呼び出して柱の登録を行なっている。

ページスタイルの作成

以下のようにmycustomというページスタイルを作ってみた。
(もうちょい命名なんとかならなかったものか・・・)

\makeatletter

%%% 隠しノンブルのための仕込み

% 隠しノンブルを出力(印刷用で定義を上書きする)
\newcommand{\oddNombre}{\relax}  % 奇数ページ用
\newcommand{\evenNombre}{\relax} % 偶数ページ用

%%% ヘッダ・フッタの体裁カスタマイズ

% mycustomページスタイルを作成
\newcommand{\printpage}[1]{$|$\hbox to 3em{\hss\textbf{#1}\hss}$|$}
\newcommand{\ps@mycustom}{%
    \renewcommand{\@oddfoot}{\oddNombre}%
    \renewcommand{\@evenfoot}{\evenNombre}%
    \renewcommand{\@oddhead}{\hfil\rightmark\hspace{2em}\printpage{\thepage}}%
    \renewcommand{\@evenhead}{\printpage{\thepage}\hspace{2em}\leftmark\hfil}%
    \let\@mkboth\markboth
    \def\chaptermark##1{\markboth{%
        \ifnum \c@secnumdepth >\m@ne
            \if@mainmatter
                \if@omit@number\else
                    \@chapapp\thechapter\@chappos\hskip1\jsZw
                \fi
            \fi
        \fi
        ##1}{}}%
    \def\sectionmark##1{\markright{%
        \ifnum \c@secnumdepth >\z@ \bxjs@label@sect{section}\hskip1\jsZw\fi
        ##1}}%
    }
\pagestyle{mycustom}

\makeatother

最初に隠しノンブルを出すための仕込みを用意している。
\relaxなので何もしないんだけど、印刷用の場合はあとでこれを再定義することで隠しノンブルを出力できるようになる。

そしてページ番号を|で囲って出力するためのマクロを用意している。
ページの桁数によって幅が変わるとイヤだったので、3em分の箱を作ってその中で中央寄せになるようにしてる。

あとはそれぞれの命令を再定義していて、フッタでは隠しノンブルの出力を行い、ヘッダでは柱とページ番号を出力するようにしている。

そのあと\chaptermark\sectionmarkを定義しているのは、オリジナル(bxjsbook.cls)からコピペしてきたもの。
コードを確認すると、\chapter\sectionはそこから\chaptermark\sectionmarkを呼び出し、その中で\markbothを呼び出すことで柱の登録を行なっている。
そしてこの\chaptermark\sectionmarkの命令を用意してるのは\ps@headingsなどのページスタイルの定義となっていた。
なので、自分でページスタイルを作る場合もこれらの命令を用意しておかないと柱がちゃんと出力されないっぽい。

それと最後に\pagestyle{mycustom}としてページスタイルを自分が作ったmycustomに変えておくのを忘れずに。

章初めのページスタイルの修正

これで大丈夫かなと思いきや、章初めのページは特別なページスタイルが使われるみたいだった。

\newcommand{\chapter}{%
  ...
  \plainifnotempty
  ...
  }

\def\plainifnotempty{%
  \ifx \@oddhead \@empty
    \ifx \@oddfoot \@empty
    \else
      \thispagestyle{plainfoot}%
    \fi
  \else
    \thispagestyle{plainhead}%
  \fi}

なので、そのページスタイル(plainhead)も再定義しておかないとダメだった。

plainheadのオリジナル(bxjsbook.cls)の定義は以下:

\def\ps@plainhead{%
  \let\@mkboth\@gobbletwo
  \let\@oddfoot\@empty
  \let\@evenfoot\@empty
  \def\@evenhead{%
    \if@mparswitch \hss \fi
    \hbox to \fullwidth{\textbf{\thepage}\hfil}%
    \if@mparswitch\else \hss \fi}%
  \def\@oddhead{%
    \hbox to \fullwidth{\hfil\textbf{\thepage}}\hss}}

これをmycustomページスタイルに合わせて再定義:

\makeatletter

% 章の最初のページ用のスタイルを上書き
\renewcommand{\ps@plainhead}{%
    \renewcommand{\@oddfoot}{\oddNombre}%
    \renewcommand{\@evenfoot}{\evenNombre}%
    \renewcommand{\@oddhead}{\hfil\printpage{\thepage}}%
    \renewcommand{\@evenhead}{\printpage{\thepage}\hfil}%
    \let\@mkboth\markboth
    \def\chaptermark##1{\markboth{%
        \ifnum \c@secnumdepth >\m@ne
            \if@mainmatter
                \if@omit@number\else
                    \@chapapp\thechapter\@chappos\hskip1\jsZw
                \fi
            \fi
        \fi
        ##1}{}}%
    \def\sectionmark##1{\markright{%
        \ifnum \c@secnumdepth >\z@ \bxjs@label@sect{section}\hskip1\jsZw\fi
        ##1}}%
    }

\makeatother

ただし柱は出力しないようにしている。
(これはplainheadに合わせたもの;節が始まってないから出力すべき内容もない)

emptyページスタイルの修正

普通はemptyページスタイルを修正する必要はないんだけど、隠しノンブルをフッタを使って入れるようにするので、その仕込みが必要。
(白紙ページにも隠しノンブルは出力した方がいい)

オリジナル(latex.ltx)は以下のようになっていた:

\def\ps@empty{%
  \let\@mkboth\@gobbletwo\let\@oddhead\@empty\let\@oddfoot\@empty
  \let\@evenhead\@empty\let\@evenfoot\@empty}

これを以下のように修正した:

\makeatletter

% 空白ページのスタイルを上書き
\renewcommand{\ps@empty}{%
    \let\@mkboth\@gobbletwo\let\@oddhead\@empty\let\@evenhead\@empty
    \renewcommand{\@oddfoot}{\oddNombre}%
    \renewcommand{\@evenfoot}{\evenNombre}}

\makeatother

これでページスタイルの作成は完了。

それにしても、このコピペして修正っていうの、ホントなんとかならないものか・・・
CSSのように変更がある部分だけ上書きで修正するみたいな仕組みが欲しい。
あと、そもそもオリジナルのソースを調べてみないと変更できないっていうのをやめて欲しい・・・

今日はここまで!

TeXで同人誌を作ってみた。(目次デザイン)

f:id:yamaimo0625:20190918075457j:plain

今日も \TeXの話で、目次のデザインについて。
なお、 \TeX \LaTeXは区別せずに扱ってる。

参考にしたのは以下:

LaTeX2ε辞典 増補改訂版 (DESKTOP REFERENCE)

LaTeX2ε辞典 増補改訂版 (DESKTOP REFERENCE)

Before / After

まずは変更前と変更後でどう変わったのかを示しておきたい。

変更前はこちら:

f:id:yamaimo0625:20190920121846p:plain

なお、昨日の見出しデザインの変更が入ってるので、目次の見出しは章見出しと同じデザインになってる。
あと、目次にリンクをはる変更が入ってる。

変更後はこちら:

f:id:yamaimo0625:20190920122127p:plain

以下が変わってることが分かると思う:

  • 目次の見出しデザインが変わってる
  • 小節まで見出しが出るようになっている
  • 章番号がない章のタイトルの先頭が章番号がある章のタイトルの先頭に揃っている
  • メインコンテンツでは章の上に線が引かれている
  • 節は章のタイトルの先頭にインデントされ、小節は節のタイトルの先頭にインデントされている
  • 「はじめに」の上に大きくスペースが入っている

「メインコンテンツでは・・・」というのは、「はじめに」や「プロローグ」も章なんだけど、これらの非メインコンテンツでは章の上に線が引かれず、「第1章」「第2章」のようなメインコンテンツでは章の上に線が引かれているということ。

ちなみに、これも『数学ガール』のデザインをマネたものとなっている。

目次の見出しデザインの変更

まずは目次の見出しデザインの変更から。

目次は\tableofcontents命令で出力するのだけど、これで見出しなどもまるまる出力され、目次の場合は「目次」という章見出しが出力される定義になっている。

章見出しが出ること自体はいいんだけど、そのデザインは他の章見出しとは違う特別なものにしたい。
そういう場合、グルーピングを使うといい。

 \TeXでは{}で囲うことでグルーピングでき、その内側はローカルになって外側の定義に影響を与えずに変更することが出来る。

そこで、以下のようにグルーピングしてその中で章見出しのデザインを変えてから目次を出力するようにした:

% 目次
{
% 目次の見出しだけデザインを変える
\makeatletter
\renewcommand{\@makeschapterhead}[1]{% #1: 見出し
    \vspace*{-2\baselineskip}%
    \noindent\hspace*{0.15\textwidth}\hrulefill\par%
    \vtop to 3\baselineskip{% 3行分の高さを確保
        \noindent\hspace*{0.15\textwidth}%
        \textsf{\large \kintou{0.85\textwidth}{C O N T E N T S}}\par%
    }\par}
\makeatother
\tableofcontents
}

章のタイトルの先頭と揃うように、テキスト幅(\textwidth)の右側85%が目次の見出しになるようにして、そこに「CONTENTS」の文字を均等割りで配置している。

目次レベルの変更

目次でどの見出しレベルまで出すかは、tocdepthというカウンターの値で指定する。

% 目次レベル
\setcounter{tocdepth}{2}  % 小節まで目次に出す

目次の章のデザイン変更

目次での章のデザインを変えるには、\l@chapterという命令を再定義する。

オリジナル(bxjsbook.cls)では次のようになっている:

\newcommand*{\l@chapter}[2]{%
  \ifnum \c@tocdepth >\m@ne
    \addpenalty{-\@highpenalty}%
    \addvspace{1.0em \@plus\p@?}
    \begingroup
      \parindent\z@
      \rightskip\@tocrmarg
      \parfillskip-\rightskip
      \leavevmode\headfont
      \setlength\@lnumwidth{\jsc@tocl@width}\advance\@lnumwidth 2.683\jsZw
      \advance\leftskip\@lnumwidth \hskip-\leftskip
      #1\nobreak\hfil\nobreak\hbox to\@pnumwidth{\hss#2}\par
      \penalty\@highpenalty
    \endgroup
  \fi}

うん、さっぱり分からないw
一応、カウンターのtocdepthの値を比較して出力するかどうか決めてるのかなぁくらいは分かるけど、あとは \TeXのモードとか(水平モードとか垂直モードとか)ペナルティの話が分かってないと厳しそう。
(そして自分はまだそこらへんを理解しきれてない)

いろいろ試したりしつつ、以下のようにしてみた:

\makeatletter

% 目次の章の体裁カスタマイズ
\newif\ifmaincontents   % メイン内の章かを区別するため
\maincontentsfalse
\renewcommand{\l@chapter}[2]{%
    \ifnum \c@tocdepth >\m@ne
        \setlength\@lnumwidth{0.15\textwidth}
        \ifmaincontents
            \noindent\hrulefill\par%
            \nobreak%
            \noindent {\large #1\hfill #2}\par
            \vspace*{0.5\baselineskip}
        \else
            \noindent {#1\hfill #2}\par
            \vspace*{0.5\baselineskip}
        \fi
    \fi}

\makeatother

まず、メインコンテンツかどうかでデザインを変えたいので、\ifmaincontentsという条件判断を用意している。
これについては後述。

そして、\@lnumwidthをテキスト幅の15%にしてるので、たしかこれがタイトルまでのインデント幅。

あとは、メインコンテンツなら横線を引いてから出力し、そうでなければ単に出力をしている。

目次の節、小節のデザイン変更

目次の節や小節のデザインを変えるには、\l@section\l@subsectionの定義を変更する。

これらのオリジナル(bxjsbook.cls)では定義がどうなっているかというと以下:

\newcommand*{\l@section}{%
          \@tempdima\jsc@tocl@width \advance\@tempdima -1\jsZw
          \@dottedtocline{1}{\@tempdima}{3.683\jsZw}}
\newcommand*{\l@subsection}{%
          \@tempdima\jsc@tocl@width \advance\@tempdima 2.683\jsZw
          \@dottedtocline{2}{\@tempdima}{3.5\jsZw}}

長さを計算して実際の処理は\@dottedtoclineという命令に委譲してるのが分かる。
この命令は\@dottedtocline{<tocdepth>}{<margin>}{<numlength>}という感じで、目次レベルとマージンサイズ、それと番号が出力される部分の長さを指定するようになっている。

これは次のように変更してみた:

\makeatletter

% 目次の節の体裁カスタマイズ
\renewcommand{\l@section}{\@dottedtocline{1}{0.15\textwidth}{2.5em}}
% 目次の小節の体裁カスタマイズ
\renewcommand{\l@subsection}{\@dottedtocline{2}{0.235\textwidth}{3.5em}}

\makeatother

なお、0.235\textwidthというのは目で見てそれっぽくなってる値にしただけ(^^;
ちゃんとやるなら足し算しないとダメ。

章番号なしの章の目次への追加

\chapter*{}を使った章は章番号が出ないだけじゃなくて目次にも出てこない。
これを目次に出すようにするには\addcontentlineという命令を使う。

例えば、「はじめに」だとこんな感じ:

\chapter*{はじめに}
\addcontentsline{toc}{chapter}{はじめに}

これで目次に章として「はじめに」が追加される。

ただ、これだと変更前の画像で見たとおり、章番号と同じインデントの深さにタイトルが出てしまう。
章番号のある章のタイトルと同じインデントの位置にタイトルは出て欲しい。

そこで以下のように変更してみた:

\chapter*{はじめに}
\addcontentsline{toc}{chapter}{\protect\numberline{\null}はじめに}

どうしてこれでうまくいくのかを以下で説明していく。

まず、 \TeXは目次をtocファイルから作るのだけど、上記のように変更せずにtocファイルを見てみると次のようになっている:

\contentsline {chapter}{はじめに}{i}{chapter*.1}% 
...
\contentsline {chapter}{\numberline {第1章}ポーカーのルール}{1}{chapter.1}% 
\contentsline {section}{\numberline {1.1}テキサス・ホールデム}{2}{section.1.1}% 
...

つまり、章番号や節番号の部分は\numberlineという命令によって出力されていることが分かる。
なら、空の章番号を\numberlineで出力するようにすれば、インデント位置が揃うはずと。

ただし、単に\addcontentsline{toc}{chapter}{\numberline{\null}はじめに}とするとうまくいかない。
これは\numberline{\null}という命令がtocファイルに書き込まれる前に評価されて別の文字列に変わってしまうから。
それを抑制するために\protectが付け加えられている。

上記の変更をしたあとのtocファイルの出力はこうなる:

\contentsline {chapter}{\numberline {\hbox {}}はじめに}{i}{chapter*.1}% 
...
\contentsline {chapter}{\numberline {第1章}ポーカーのルール}{1}{chapter.1}% 
\contentsline {section}{\numberline {1.1}テキサス・ホールデム}{2}{section.1.1}% 

これで章番号がない章のタイトルの先頭も章番号がある章のタイトルの先頭に揃うようになる。

メインコンテンツ/非メインコンテンツの切り替え

上記までの変更を行なっての出力が以下:

f:id:yamaimo0625:20190920135535p:plain

メインコンテンツと非メインコンテンツの切り替えが出来ていないので、「第1章」の上に線が引かれてない。
あと、「はじめに」の前の空きも足りてない。

そこで、tocファイルに「非メインコンテンツの開始」「メインコンテンツの開始」の命令を書き込むようにした:
(どうやって書き込むのかは後述)

before

\contentsline {chapter}{\numberline {\hbox {}}はじめに}{i}{chapter*.1}% 
...
\contentsline {chapter}{\numberline {第1章}ポーカーのルール}{1}{chapter.1}% 
\contentsline {section}{\numberline {1.1}テキサス・ホールデム}{2}{section.1.1}% 

after

\startnomaintoc 
\contentsline {chapter}{\numberline {\hbox {}}はじめに}{i}{chapter*.1}% 
...
\startmaintoc 
\contentsline {chapter}{\numberline {第1章}ポーカーのルール}{1}{chapter.1}% 
\contentsline {section}{\numberline {1.1}テキサス・ホールデム}{2}{section.1.1}% 

そして、このtocファイルに書き込んだ命令を以下のように定義することで、メインコンテンツ/非メインコンテンツの切り替えを行い、また非メインコンテンツの前には空きを入れるようにした:

% \startmaintocで\ifmaincontentsがtrueになるようにする
\newcommand{\startmaintoc}{\maincontentstrue}
% \startnomaintocで\ifmaincontentsがfalseになるようにし2行分の空きを入れる
\newcommand{\startnomaintoc}{\maincontentsfalse\vspace*{2\baselineskip}}

あとはこの\startmaintocおよび\startnomaintocをどうやってtocファイルに書き込むか。

調べてみると\addaddcontentslineは以下のように「tocファイルに目次を書け」という命令をauxファイルに書き込んでいるようだった。

% latex.ltxから引用(コメントは自分が追記)

\def\addcontentsline#1#2#3{%
  \addtocontents{#1}{\protect\contentsline{#2}{#3}{\thepage}%
                     \protected@file@percent}}
\long\def\addtocontents#1#2{%
  \protected@write\@auxout% ここがauxへ書けという命令
      {\let\label\@gobble \let\index\@gobble \let\glossary\@gobble}%
      {\string\@writefile{#1}{#2}}}% auxに書く内容は「#1(toc)に#2を書け」という命令

そして、auxファイルが評価されることでtocファイルに目次が書き込まれる(そして\tableofcontents命令はtocファイルの内容を実行することで目次を出力する)。

なので、同じように「tocファイルに\startmaintocを書け」という命令をauxファイルに書き込む命令を作って、それを呼び出せばいい。

そこでいろいろ調べながら次のような命令を用意した:

\newcommand{\startmaincontents}{%
    \immediate\write\@auxout{\string\@writefile{toc}{\string\startmaintoc}}}
\newcommand{\startnomaincontents}{%
    \immediate\write\@auxout{\string\@writefile{toc}{\string\startnomaintoc}}}

あとは以下のように呼び出すだけ:

\startnomaincontents

\chapter*{はじめに}
\addcontentsline{toc}{chapter}{\protect\numberline{\null}はじめに}
\startmaincontents

\chapter{ポーカーのルール}

これで冒頭のような目次が得られた。


宣伝です。
気になった人はチェックをお願いします!

今日はここまで!

TeXで同人誌を作ってみた。(見出しデザイン)

f:id:yamaimo0625:20190918075457j:plain

今日も \TeXでの同人誌制作について。

今日は見出しのデザインについて。
なお、昨日と同様で \TeX \LaTeXは区別せずに扱ってる。

参考にしたのは以下:

LaTeX2ε辞典 増補改訂版 (DESKTOP REFERENCE)

LaTeX2ε辞典 増補改訂版 (DESKTOP REFERENCE)

Before / After

まずは変更前と変更後でどう変わったのかを示しておきたい。

変更前はこちら:

f:id:yamaimo0625:20190920095604p:plain f:id:yamaimo0625:20190920095618p:plain

変更後はこちら:

f:id:yamaimo0625:20190920095644p:plain f:id:yamaimo0625:20190920095656p:plain

以下が変わってることが分かると思う:

  • フォントがゴシック体ではなく太字の明朝体になっている
  • 章見出しが右寄せになって上下に線が引かれている

下の変更については、『数学ガール』のデザインをマネたもの。
手元にあれば確認してもらうとだいぶ再現されていることが分かると思う。
(ただし、オリジナルは太ゴシックになってる;伝統的に和文の見出しは太字の代わりにゴシック体にすることが多い。ただ、太字フォントが使えるなら明朝体の方が美しいと個人的には思っている)

章見出しの修正

 \TeXでどうやってデザインを変更するか。
基本はクラスファイルの中身を見て必要な命令を見つけ出し再定義する。

なんてプリミティブな・・・

一応、最初に挙げた本とか見ると取っ掛かりとなる部分を知ることが出来る。

章見出しのデザインを変更する場合、\@makechapterhead\@makeschapterheadを再定義するといい。
(前者は見出し番号を出す\chapter用のデザイン、後者は見出し番号を出さない\chapter*用のデザイン)

オリジナル(bxjsbook.cls)の定義はこうなっている:

\def\@makechapterhead#1{%
  \vspace*{2\Cvs}% 欧文は50pt
  {\parindent \z@ \raggedright \normalfont
    \ifnum \c@secnumdepth >\m@ne
      \if@mainmatter
        \huge\headfont \@chapapp\thechapter\@chappos
        \par\nobreak
        \vskip \Cvs % 欧文は20pt
      \fi
    \fi
    \interlinepenalty\@M
    \Huge \headfont #1\par\nobreak
    \vskip 3\Cvs}} % 欧文は40pt
\def\@makeschapterhead#1{%
  \vspace*{2\Cvs}% 欧文は50pt
  {\parindent \z@ \raggedright
    \normalfont
    \interlinepenalty\@M
    \Huge \headfont #1\par\nobreak
    \vskip 3\Cvs}} % 欧文は40pt

お、おう・・・
ただ、文字サイズ変えたりフォント変えたりして章番号を出力したり(\thechapter)引数(#1)として渡ってきた章のタイトルを出力してるんだなぁということはなんとなく分かるような、分からないような・・・

とにかくこれをこう修正した:

\makeatletter

%%% 見出しの体裁カスタマイズ

% 章見出しの体裁カスタマイズ
% *なし
\renewcommand{\@makechapterhead}[1]{% #1: 見出し
    \vspace*{-2\baselineskip}%
    \noindent\hrulefill\par%
    \vtop to 5\baselineskip{% 5行分の高さを確保
        \hspace*{\fill}\textbf{\large\thechapter}\par%
        \hspace*{\fill}\textbf{\raisebox{-5pt}{\LARGE #1}}\par%
    }%
    \noindent\hrulefill\par}
% *あり
\renewcommand{\@makeschapterhead}[1]{% #1: 見出し
    \vspace*{-2\baselineskip}%
    \noindent\hrulefill\par%
    \vtop to 5\baselineskip{% 5行分の高さを確保
        \hspace*{\fill}\textbf{\raisebox{-5pt}{\LARGE #1}}\par%
    }%
    \noindent\hrulefill\par}

\makeatother

やってることは、

  1. 2行分上に移動し(※理屈としては1行分でいいはずなんだけど、なぜか2行分移動しないと一番上の位置にならなかった)
  2. ベースラインに横一杯の直線を引き、
  3. 5行分の高さのある箱を用意して、
  4. 右寄せで章番号を出力し、
  5. 右寄せで章のタイトルを出力し、
  6. 最後に横一杯の直線を引く。

という感じ。
*ありの方は章番号はないので手順の4.をスキップしてる)

\textbf{}を使って太字で出力されるようにしているけど、昨日書いたOTFパッケージのおかげで太字はゴシック体ではなく太字の明朝体で出力されるようになっているので、これで太字の明朝体になる。

あと、\makeatletter\makeatotherはざっくり言うと@特殊文字ではなく普通の文字として扱えるようにするもの。
これをしておかないと\@makechapterheadなどが制御綴という扱いになってくれない。

それにしても、自分がやったとはいえ、この変更は力技すぎて汚いなぁ・・・
 \TeXの命令と \LaTeXの命令が混ざりまくってるし、詰まりすぎた行間を広げるために\raiseboxで無理やり位置を下げたりね。。。
もっと勉強しないと。

節見出しの修正

節以下の見出しを修正する場合、\@startsectionに渡すパラメータの値を変えるように\section制御綴などを再定義するのが基本になる。
ただもちろんベタにいろいろ変更してもいい。

オリジナル(bxjsbook.cls)での定義は以下:

\if@twocolumn
  \newcommand{\section}{%
    \@startsection{section}{1}{\z@}%
    {0.6\Cvs}{0.4\Cvs}%
    {\normalfont\large\headfont\raggedright}}
\else
  \newcommand{\section}{%
    \if@slide\clearpage\fi
    \@startsection{section}{1}{\z@}%
    {\Cvs \@plus.5\Cdp \@minus.2\Cdp}% 前アキ
    {.5\Cvs \@plus.3\Cdp}% 後アキ
    {\normalfont\Large\headfont\raggedright}}
\fi

数学ガール』では節見出しに上線を引くようになっている。
もしこれを再現したかったら、以下のようにすればいいことは確認した:

\makeatletter

\renewcommand{\section}{%
    \if@slide\clearpage\fi%
    \vspace{\baselineskip}%
    \noindent\hrulefill\par%
    \@startsection{section}{1}{\z@}%
    {.1\Cvs \@plus.5\Cdp \@minus.2\Cdp}% 前アキ
    {.7\Cvs \@plus.3\Cdp}% 後アキ
    {\normalfont\Large\headfont\raggedright}}

\makeatother

横一杯の直線を引く変更が入ってるのが分かると思う。

ただ、『Math Poker Girl』は各節の終わりに「まとめ」を入れることにしていて、その「まとめ」が枠で囲まれているので上線まで引くとちょっと冗長な感じだった。
なので、上記の変更はしていない。

見出しフォントの修正

上記の定義を見ると、見出しは\headfontで指定されたフォントで出力されていることが分かる。
なので、これをゴシック体ではなく太字の明朝体になるようにした:

% 節以下の見出しがゴシック体になってしまっていたので、
% 太字明朝体になるように修正。
\renewcommand{\headfont}{\bfseries}

もちろんこれはOTFパッケージを使ってdeluxeオプションを指定している前提。

これで冒頭で示したような見出しデザインになってくれた。


宣伝です。
気になった人はチェックをお願いします!

今日はここまで!

TeXで同人誌を作ってみた。(フォント周り)

f:id:yamaimo0625:20190918075457j:plain

昨日に引き続き、同人誌制作に \TeXを使って学んだことについて。

今日はフォント周りについて。

なお、現時点での理解を書いていて正確性には欠けるので注意。
あと \TeX \LaTeXを区別せずに扱ってる。

参考にしたのは以下とか:

[改訂第7版]LaTeX2ε美文書作成入門

[改訂第7版]LaTeX2ε美文書作成入門

LaTeX2ε辞典 増補改訂版 (DESKTOP REFERENCE)

LaTeX2ε辞典 増補改訂版 (DESKTOP REFERENCE)

 \TeXでのフォントの仕組み

まず \TeXはフォントのメトリック情報だけを使って組版を行う

メトリック情報というのは文字を箱として扱ったときの高さとか幅とかのことで、つまり \TeXは文字の細かい形(グリフという)なんかまったく見てなくて、大きさのバラバラな箱を「いい感じ」になるように並べているだけだったりする。

f:id:yamaimo0625:20190919131528p:plain

このメトリック情報が書かれたファイルがtfmファイル(TeX Font Metricファイル)。

欧文の場合、フォントによってメトリックは変わってくるので、指定されたフォントから対応するtfmファイルを \TeXが見つけられる必要がある。
そこで使われるのがfdファイル(Font Definitionファイル)。

 \TeXではフォントを5つの要素で識別している:

  • エンコーディング(数値と文字との対応づけ、OT1とかT1とかがある)
  • ファミリー(書体(≒フォント名))
  • シリーズ(太さ、ボールドとか)
  • シェイプ(形、イタリックとか斜体とか)
  • サイズ(大きさ、10ptとか)

この5つの要素とfdファイルを参照して使われるtfmファイルが決まる。

 \TeXはDVIファイル(Device Independentファイル)を出力するけど、そこには使われたtfmファイル名しか書かれていない。
なので、DVIを表示(あるいは変換)するソフトはtfmファイル名と実際に使うべきフォントとの対応関係を知る必要がある。
そこで使われるのがmapファイル。

これでtfmファイル名から実際のフォントが分かり、実フォントを使って表示(や変換)が行われることになる。

図にまとめるとこんな感じ:

f:id:yamaimo0625:20190919135611p:plain

フォントの指定は\usefont{<encoding>}{<family>}{<series>}{<shape>}という制御綴などを使うっぽい。

論理フォント

この論理フォントという言い方は自分の言い方で、一般にそう言われているわけではないので注意。

上記のフォント指定とは別に、論理的なフォントの指定があるように思う。
\textrm{...}とか\textit{...}とか。
前者はローマン体のフォントを使うことを指定していて、後者はイタリック体のフォントを使うことを指定している。

この論理的な指定で実際にどのフォントが使われるかは、\rmdefaultなどを再定義すると変わるみたい。

欧文に関して

 \TeXの欧文で定番のフォントといえばComputer Modernだったけど、使われているエンコーディングが古いなどで、あまり好ましくないみたい。
同じデザインのフォントを使いたいなら、Latin Modernを使うといいとのこと。

Latin Modernを使うには次のようにする:

\usepackage{lmodern}
\usepackage[T1]{fontenc}

和文に関して

 \TeXでのフォントの仕組みを上で書いたけど、これが和文になるとちょっと話が変わってくる。

和文だとどのフォントでもメトリックが変わらない
どれも正方形の箱の中に文字を入れている。

そこで、明朝体なら「Ryumin-Light(リュウミンL)」、ゴシック体なら「GothicBBB-Medium(中ゴシックBBB)」というフォントが常に使われる。
(もう少し正確に書くと、fdファイルによって明朝体はjis.tfm、ゴシック体はjisg.tfmというtfmファイルを使うことが決まり、これらは仮想フォントというものになっていて、そこにrml.tfm(リュウミンL)やgbm.tfm(中ゴシックBBB)を使うことが指定されているらしい)

じゃあ、リュウミンLや中ゴシックBBBってどんなフォントなのかというと基本的にはシステムには入ってない
なのでPDFにしたときに実フォントは埋め込まれず、表示した時に使える明朝体/ゴシック体の適当なフォントが使われる。

それじゃ困るのでmapファイルで埋め込むフォントを指定することになるんだけど、つまり、DVIファイルで出力された時点でフォントは2種類(明朝体/ゴシック体)しかないので、埋め込めるフォントも2種類しかない。

マジでゴミ仕様

・・・とはいえ仕方ないので、それで頑張るしかない。。。

rmlやgbmというtfmファイル名に対して実フォントを対応させるためにmapファイルを更新するのだけど、それにはupdmapというツールを利用する。
これはDVIウェアごとにmapファイルが必要だけどそれを一つずつ変更していたら大変なので一気に変更するためのもの。
和文の場合はkanji-config-updmapを使うことになる。

updmapにはシステム全体の設定を変えるupdmap-sysと個人の設定を変えるupdmap-userがある。
和文についても同様で、kanji-config-updmap-sysとkanji-config-updmap-userがある。

具体的な指定方法はヒラギノフォントを使う設定のところで。

OTFパッケージ

和文のフォントメトリックは正方形であるべきなんだけど、歴史的な経緯で実際にはちょっと違っていたらしい。
これを直すにはOTFパッケージを使うとのこと。
(このパッケージ自体は名前の通りOpenTypeフォントを使うためのもの)

また、オプションでjis2004を指定すると、JIS2004字形になる。
いくつかのフォントの字形が新しく定められたものになる。

あと、オプションでdeluxeを指定すると、使えるシリーズ(太さ)が増えたり丸ゴシック(mg)が使えたりするとのこと。
このオプションを指定しなかった場合、太字は全部ゴシック体にされてしまうのだけど、これをしていすることで太字の明朝体が使えるようになる。

なので、和文では基本的には以下のようにしておいた方がよさそう:

\usepackage[deluxe,jis2004]{otf}

ヒラギノフォントを使う設定

macOSの場合ヒラギノフォントがバンドルされているので、せっかくだからこれを使いたいところ。
なお、PDFに埋め込んで再配布してもライセンス的には問題ないっぽい。
(単体で再配布するのはダメ。あと埋め込まれたものを取り出して単体で使うのもおそらくダメ)

以下を参考にして使えるようにしてみた:

まずはTLContribから必要なパッケージをインストール:
(TLContribというのはTeX Liveとは別管理されているリポジトリらしい)

$ sudo tlmgr repository add http://contrib.texlive.info/current tlcontrib
$ sudo tlmgr pinning add tlcontrib '*'
$ sudo tlmgr install japanese-otf-nonfree japanese-otf-uptex-nonfree ptex-fontmaps-macos cjk-gs-integrate-macos

そしてリンクを作成する:

$ sudo cjk-gs-integrate --link-texmf --cleanup
$ sudo cjk-gs-integrate-macos --link-texmf
$ sudo mktexlsr

なお、リンクというのはフォントのシンボリックリンクのことだと思う。
おそらくTeX関連のファイルが入っているtexmf以下にフォントのシンボリックリンクを作ってるのだと思われる。
あとmktexlsrはファイル一覧のキャッシュの更新。

最後にヒラギノフォントを使うようにmapファイルを更新する。

$ sudo kanji-config-updmap-sys --jis2004 hiragino-highsierra-pron

ちなみに、更新前の状態は以下:

$ sudo kanji-config-updmap-sys status
CURRENT family for ja: ipaex
Standby family : hiragino-highsierra
Standby family : hiragino-highsierra-pron
Standby family : ipa
Standby family : toppanbunkyu-highsierra

IPAexフォントが埋め込まれる設定になっていたっぽい。

更新後の状態は以下:

$ sudo kanji-config-updmap-sys status
CURRENT family for ja: hiragino-highsierra-pron
Standby family : hiragino-highsierra
Standby family : ipa
Standby family : ipaex
Standby family : toppanbunkyu-highsierra

ヒラギノフォントが指定されていることが分かる。

設定したこと

自分がした設定をまとめると以下:

  • Latin Modernを使うようにした
  • OTFパッケージを使うようにした
  • ヒラギノフォントをPDFに埋め込むようにした

上2つについては、以下のようにソースに書いた:

% フォント関連
% Computer ModernのかわりにLatin Modernを使う
\usepackage[T1]{fontenc}
\usepackage{lmodern}
% OTFパッケージを使う
\usepackage[deluxe,jis2004]{otf}

また、一番下については前述の通りの設定を行なった。


宣伝です。
気になった人はチェックをお願いします!

今日はここまで!

TeXで同人誌を作ってみた。(ビルド環境構築)

f:id:yamaimo0625:20190918075457j:plain

今日からは \TeXを使って学んだことをまとめていく。

なぜ \TeXを使ったか

文章が主体の同人誌を作る場合、組版に使えるソフトはいくつか候補がある。

特に有力なのがRe:VIEW
実績が多く、また同一ソースから複数のファイル形式に出力できる魅力がある。

ただ、以下のようなことからRe:VIEWではなく \TeX\LaTeX)を使うことにした:

1.  \TeXの勉強がしたい

そう、何だかんだでこれが大きい。
勉強で作っている部分もあったので、いろいろ試したかった。

『哲学散歩道』も \TeXで作ったんだけど、デザイン周りは全然触れてなくて、ほぼ素の出力になっている。
なので、 \TeXで本のデザインってどうやったらいいんだろうという疑問がずっと残ってた。
例えば、以下のようなもの:

  • どうやって目次をデザインするのか
  • どうやって見出しをデザインするのか
  • どうやってページレイアウトをデザインするのか
  • トンボや隠しノンブルはどうやって入れればいいのか
  • 断ち切りまで伸ばすのはどうすればいいのか

これらの疑問を解消したくて、 \TeXでの組版にチャレンジしてみた。
実際、いろいろ学べて、今日からの記事はそこで学んだことを忘れないようにするためのもの。

2.  \TeXにメリットがあった

理系だったので、卒論、修論、あるいはレポートで、何だかんだで \TeXは使ってきた。
こうやってブログを書くときにも数式は \TeX記法を使って書いてるし。
なので、これまでにも \TeXにはけっこう触れていて、慣れている部分が多い。
そういう意味で、まったく知らないRe:VIEWを使うよりも心理的障壁は低かったりする。

また、数学の同人誌なので、数式がそれなりに出てくる。
もちろんRe:VIEWでも数式は書けるけど、数式を書くことが分かっているなら、最初から \TeXを使った方が素直と言える。

3. Re:VIEWに不安があった

これもけっこう大きかった。

Re:VIEWはPDFへの出力のバックエンドとして \TeXを使っているので、何か問題があったときには中間出力された \TeXのソースや、あるいはそのソースを出力したRubyのソースと戦うことになる。
何も問題がなければ杞憂ですむのだけど、何かあったときにはその対処コストがちょっと無視できないレベルで大きいのがかなり気になった。

そして、もし問題が起きて結局 \TeXの勉強をしないといけないのなら、最初から素直に \TeXの勉強をした方がいいよね、と。
 \TeXの勉強をしないといけないかもしれないという不安を抱えながら進めるより、 \TeXの勉強をすることを最初からスケジュールに入れておいた方が心理的に安心できる。

実際、Re:VIEWまわりで謎の挙動をして困ったという話はチラホラ見かけた・・・

まぁ、リスクに対してメリットが遥かに大きいから、普通はRe:VIEWを使った方がいいとは思うけど。

 \TeXのインストール

これはRe:VIEWを使う場合も必要。
TeX Wikiを参考にMac TeX 2019(TeX Live 2019にmacOS用のソフトがバンドルされてる)をインストール。

ビルド環境の構築

以下のような感じでビルド環境を作った:

  • \TeXにはupLaTeXを使用
  • 索引作成にはupmendexを使用
  • PDF出力にはdvipdfmxを使用
  • ビルドツールにMakeとlatexmkを使用
  • ドキュメントクラスにBXjsclsパッケージのbxjsbookを使用

upLaTeXは \TeXに日本語用の拡張が入ったpTeX(Publishing TeX)がUnicode対応したupTeXにさらにe-TeX拡張(レジスタ増加など)の入ったe-upTeXでLaTeXフォーマットを読み込むようにしたもの。
何を言ってるのか分からないと思うけど、自分もそう思う。
 \TeXの違法建築っぷりはヤバい。

upmendexは同様にmendexという索引作成ツールがマルチバイト文字に対応したもの。

参考文献の管理にはBibTeXというツールがあり、それをマルチバイト文字に対応させたupBibTeXというものがあるのだけど、今回は使ってない。
BibTeXを使っても使わなくてもあまり手間が変わらなかったのと、ちょっと凝ったことをしたかったのが理由。

latexmk

 \TeX \LaTeX)では相互参照や目次作成のために複数回コマンドを実行しないといけないのだけど、何度もコマンドを打つのは面倒なので簡易的なビルドツールが使われることが多い。
今まではptex2pdfというツールを使ってたのだけど、調べるとlatexmkというツールを使った方がいいようだった。

上記の記事などを参考に以下の.latexmkrcを用意した:

#!/usr/bin/env perl

# Settings for latexmk.
# See https://konn-san.com/prog/why-not-latexmk.html

$latex          = 'uplatex -halt-on-error';
$bibtex         = 'upbibtex';
$dvipdf         = 'dvipdfmx %O -o %D %S';
$makeindex      = 'upmendex %O -g -s index.ist -o %D %S';
$max_repeat     = 5;
$pdf_mode        = 3; # generates pdf via dvipdfmx

最終的にはupBibTeXは使わなかったのだけど、そのまま残してある。
あと、upmendexのオプションで指定している-s index.istはスタイルファイル(これは \TeXのスタイルファイルとは別物)の指定で、索引の出し方を設定するスタイルファイルとしてindex.istを使うということ指示している。
index.istの内容については後日)

latexmkの使い方は、以下:

$ latexmk <対象のTeXソース>

生成物の削除なども行える:

# 生成物をすべて削除
$ latexmk -C

# 中間生成物をすべて削除
$ latexmk -c

Make

latexmkを直接叩いてもよかったんだけど、コマンドを覚えるのもなんだったのでMakeを使った。
Makeを使えばコマンドを覚えてなくてもいいし、あとでコマンド変更の差分を見たりすることが出来る。

Ω<つまりMakeはいにしえのDevOps, Infrastructure as Codeだったんだよ!
ΩΩΩ<な、なんだってー!?

というわけで、以下のようなMakefileを用意した:

.PHONY: all build book ebook clean clean-mid open eopen

BOOK = book.pdf
EBOOK = ebook.pdf
PDF = $(BOOK) $(EBOOK)

COMMON_SOURCE = <includeされるTeXソース> ...

all: build

build: $(PDF)

book: $(BOOK)

ebook: $(EBOOK)

%.pdf: %.tex
  latexmk $<

$(PDF): $(COMMON_SOURCE)

clean:
  latexmk -C

clean-mid:
  latexmk -c

open: book
  open $(BOOK)

eopen: ebook
  open $(EBOOK)

book.texは印刷用の \TeXソース、ebook.texは電書用の \TeXソース。
入り口を2つ用意することで、同一ソースから印刷用と電書用のPDFを両方とも生成できるようにしている。
(各ファイルから共通ソースをincludeしてる)

そして、latexmk自体は指定されたソースが依存しているソースのタイムスタンプまで調べてくれるようなのだけど、フロントエンドとしてMakeを使うとそこまで感知できないので、COMMON_SOURCEとして列挙して依存関係を追加するようにしている。
$(PDF): $(COMMON_SOURCE)の行がそれで、Makeはターゲットとソースの対のあとにコマンドが続かない場合、依存関係だけを追加する)

あとはcleanで生成物の削除、clean-midで中間生成物の削除、openで印刷用PDFのオープン、eopenで電書用PDFのオープンが出来るようにしてある。
(latexmkでPDFのオープンとか開いたままの更新とかあるようなのだけど、実際に試してみると使い勝手がめちゃくちゃ悪かった(たしか端末が対話状態のような感じになってCtrl-Cを押さないと制御が戻ってこなくなったりしたはず)ので、ビルドだけで終わるのか、PDFを開くところまでやるのかなどをコントロールできるようにした)

.gitignore

生成物はバージョン管理の対象から外したいので、.gitignoreに無視するファイルを追加:

*.fls
*.fdb_latexmk
*.aux
*.out
*.toc
*.idx
*.ilg
*.ind
*.log
*.dvi
*.pdf

*.fls*.fdb_latexmkはたしかlatexmkで出力されるファイル。
*.aux*.log*.dvi*.pdfあたりは \TeX(とdvipdfmx)で出力される典型的なファイル。
*.tocは目次のための出力。
*.idx*.ilg*.indは索引のための出力。
*.outは電書のためにページ内リンクをつけると出力される。

bxjsbookドキュメントクラス

ドキュメントクラスとしては、BXjsclsパッケージのbxjsbookを使った。
昔はjsclassesを使うのが普通だったけど、最近はupLaTeX以外でも使えるようにしたBXjsclsを使った方がいいみたい。

上記の記事などを参考にして、book.texおよびebook.texは次のようにした:

\documentclass[autodetect-engine,dvipdfmx-if-dvi,ja=standard,a5paper]{bxjsbook}

% 設定など

\begin{document}

% 本文など

\end{document}

これで最低限のビルド環境は整った感じ。


宣伝です。
気になった人はチェックをお願いします!

今日はここまで!

Githubプロジェクトボードで同人誌制作のタスク管理をやってみた。

f:id:yamaimo0625:20190125223301j:plain

今日も技術書典7で頒布する『Math Poker Girl』の作成に関する振り返り。

今日はタスク管理をGithubプロジェクトボードでやってみたという話。

Githubプロジェクトボードとは

GithubプロジェクトボードはGithubが提供するタスクボード。
タスクボードアプリとしてはTrelloMicrosoft Planner(Teamsで使える)、あるいはKanbanFlowなどがあるけど、Githubが提供しているタスクボードなので特に設定することなくリポジトリと連携できるのがいい。

タスクボードとは

タスクボードでは作業をタスクとしてボードに貼り付けて、例えば「計画済み」→「実施中」→「完了」みたいにタスクの位置を移動していくことでタスクの状態を把握する。

f:id:yamaimo0625:20190917105311p:plain

Githubプロジェクトボードでは、各リポジトリのissueやプルリクエストをカードとして貼り付けられる他、ノートという形でメモを貼り付けたり出来るようになっている。
また、ノートをissueに変換したり、issueの状態変化に合わせてカードを移動したり出来る。

これにより、以下のようなワークフローでタスクを進められる:

  1. やるべきことをリポジトリのissueに登録
  2. プロジェクトボードを用意
  3. issueをカードとしてプロジェクトボードに追加
  4. カードでタスクの状態を管理(計画済みか、進行中か、終わったのか)
  5. 雑多なタスクはノートで追加(必要ならissueに変換する)
  6. タスクを実施
  7. タスクがコミットで終了するならclose #<issue番号>としてコミット(これでissueがcloseされる)
  8. issueがcloseされるとカードも完了の場所に移動。

やる必要のあるタスクが脳内からボードに移動して見える化されるので、タスクのやり忘れを防げるし、その期間でのタスクの進捗具合も見れる
自分は個人で利用してたけど、チームなら各個人のタスクの進捗具合も見えるようになるのでサポートしたりも可能になると思う。

Githubプロジェクトボードの種類

Githubプロジェクトボードには実は3種類ある:

  1. リポジトリ所有のプロジェクトボード
  2. 個人所有のプロジェクトボード
  3. 組織(Organization)所有のプロジェクトボード

1.は各リポジトリで利用できるプロジェクトボード。
リポジトリの"Projects"タブをクリックすると利用できる。
「1リポジトリ-多ユーザ」の場合はこのプロジェクトボードを利用するといいと思う。

2.と3.は複数リポジトリに渡って計画をできるプロジェクトボードになっていて、2.は個人で使えるプロジェクトボード、3.は組織(Organization)で使えるプロジェクトボードになっている。
「多リポジトリ-1ユーザ」なら2.を使えばいいし、「多リポジトリ-多ユーザ」なら3.を使う感じになる。

自分は複数のリポジトリを使いたくて1人での利用だったので個人所有のプロジェクトボードを利用した。
個人所有のプロジェクトボードはプロフィールページを開いて"Projects"タブをクリックするか、右上のドロップメニューから"Your projects"を選択すれば利用できる。

どう運用したか

リポジトリの準備

まずリポジトリ(全部private)は複数用意していた:

そして、それぞれのリポジトリにタスクをissueで追加。

ちなみに、BlogリポジトリやStudyリポジトリは『Math Poker Girl』とは関係ないけど、同じ期間に並行して実施しているので同じプロジェクトボードから参照できるようにしている。

1スプリント1プロジェクトボード

1つのプロジェクトボードをずっと使い続けてもよかったんだけど、細く区切って使った方がカードの数も抑えられていいかなと思ったので、1スプリントごとにプロジェクトボードを用意して使うことにした。
ちなみに1スプリントは一週間にしていた。
いや、一週間ごとにリリースとかいうわけではないんだけど、固定長のタイムボックスがあった方がメリハリがあっていいと思うので。

そんな感じで1週間ごとに1つのプロジェクトボードを使っていたので、プロジェクトボードの名前は「yyyy-mm-wN」(例えば2019年の9月第3週なら2019-09-w3)としていた。

おそらくだけど、プロジェクトボードは期間の長さを固定にして、期間の長さが可変な締め切りはマイルストーン機能を使って管理するのがいいと思う。
(タスクの進捗テンポを守るためのプロジェクトボードと、プロダクトの期待を守るためのマイルストーンという使い分け)

4つの列

一番シンプルなタスクボードは「To do」「In progress」「Done」という3列を用意するけど、自分は「To do」を2つに分けて次の4列を用意して使っていた:

  1. Plan(今週やる作業)
  2. Today(今日やる作業)
  3. Working(作業中)
  4. Done(完了)

これは毎朝その日の計画を行いたかったから。

運用の流れ

そして、以下のような流れで運用していた:

  1. 週初め
    1. 新しいプロジェクトボードを作成
    2. 作業に関連するリポジトリをプロジェクトボードに連携
    3. 各日付の日付ノート(後述)をPlan列に追加
    4. 予定のノートをPlan列に追加
    5. その週に行うissueをタスクとしてPlan列に追加
  2. 毎朝
    1. その日の日付ノートをToday列に移動
    2. その日の予定のノートをToday列に移動
    3. その日行うタスクをToday列に移動
    4. 日付ノートをWorking列に移動し、各タスクの見積もり時間を記入
  3. 作業開始
    1. タスクをWorking列に移動
  4. 作業完了
    1. タスクをDone列に移動(issueならcloseすれば勝手に移動する)
    2. タスクの実績時間を日付ノートに記入
  5. 毎晩
    1. その日の振り返りを日付ノートに記入
    2. 日付ノートをDone列に移動
  6. 週終わり
    1. Done列を見返してその週の振り返り
    2. 来週以降のアクションや目標、予定を検討
    3. プロジェクトボードをclose

つまり「週初めに計画→週終わりに振り返り」という大きな枠があって、その中で毎日「朝に計画→夜に振り返り」を繰り返すようにして、その中でタスクをTodayからWorkingさらにはDoneへと進めていく感じにしていた。

実際のプロジェクトボードの様子はこんな感じ:

f:id:yamaimo0625:20190917121932p:plain

ちなみに、同人誌制作に限らずに一般のタスク管理に使えると思う。
それこそ普通の開発にも。
(その場合、リポジトリ所有のプロジェクトボードか組織所有のプロジェクトボードをチームで使い、加えて個人の雑多なタスクを個人所有のプロジェクトボードで管理する感じになるはず)

工夫したこと

実際に運用する中で、振り返りで気づいたことなどから以下のような工夫を行なってみた。

予定をノートで入れた

予定はカレンダーアプリで管理してるけど、プロジェクトボードにも追加するようにした。
これにより、

  • 週初めに今週の予定を確認する習慣がつく
  • 予定を考慮した計画を立てられる
  • いちいちカレンダーアプリを開かなくても今日の予定が分かる

というメリットが。

ノートにはURLなどもメモっておけるので、勉強会の場合はURLを貼っておけばプロジェクトボードから直接勉強会の詳細を確認しに行けて便利。

あと、途中からプールに泳ぎに行く予定もノートで追加しておくようにした。
するとToday列を見て「プール」とあるので「泳ぎに行かなきゃ」となるし、終わってDone列に移動すると一仕事終えた気分になるのでとてもいい。
ジムに行くとかそういう「やらなきゃいけないけどやらなくてもいい」系のものは、明示的なタスクにしてしまった方が続けられると思う。

週終わりの振り返り開始時間を書いた

週終わりの振り返りはノートにして計画していたのだけど、最初は「週終わり作業」とだけしていたので、ついつい気づいたら寝る時間になってて振り返りが出来ず、週の初めに起きてからやることが多かった。
そこで、「週終わり作業 21:00〜」と明示的にやる時間を決めて書いておくようにした。

これで21:00になったら「振り返りやらなきゃ」となって振り返りし忘れることがなくなった。

ノートにしたけどやり忘れるということが多い場合、この開始時間を決めて書いておくというのはいいと思った。

休息日を用意した

時間を好きに使えるので、ついつい頑張りすぎることが多かった。
療養中なので、体調の管理がけっこう重要なのに・・・
そこで意図的に休むように休息日を用意するようにした。

フリーランスとかだとこういった休みの管理も重要っぽい。
働きづくめでもパフォーマンス落ちるからね・・・
(とはいえ焦るんだよなぁ・・・)

以前、このブログでも紹介したHaLakeさんで作業を行なっていたのだけど、HaLakeさんは水曜日が定休日なので水曜日と日曜日は休息日として休むようにした。

とはいえやはり焦るので、水曜日は完全な休みではなく部屋の片付けをしたり本を読んで勉強したりするインプット日という扱いにしてみた。

まぁ、入稿直前は結局あまり休めなかったけど・・・

日付ノートを用意した

上記と関連して、日付を書いたノートを用意するようにした。
例えば「9/9 作業」とか「9/11 インプット」とか「9/15 休息」とか。

このノートの役割は3つ:

  1. その日が作業日なのかインプット日なのか休息日なのかを明示する
  2. 各タスクの見積もり時間と実績時間を記録する
  3. その日の振り返りを記録する

1.については前述した通り。

2.については、振り返りをするときにタスクを実施するのにどれくらい時間かかったのが分かった方がいいと思ったので途中から行うようにした。
昨日の記事の実績時間はこの記録がベースになっている。

プロジェクトボードの嬉しいことで、列を移動したりした時間はプロジェクトボードの"Menu"から"Activity"で確認できる。
なので、作業開始時にWorking列に移動しておけば、何時から始めたのかが分かるので記録は比較的簡単に出来る。
(あとで一気にやろうとすると大変なので、記録自体はその都度やっておいた方がいい)

3.については週終わりの振り返りをやろうとしたときにけっこう忘れてることが多かったので、その日のうちに軽く振り返りをしておいた方がいいと思って始めた。
週終わりの振り返りで日付ノートを見返すと「あーそういえば」となってよかった。

あと、副次的な効果で、日付ノートをDone列に移すことで「今日はこれでおしまい!」と区切りをつけれるようになったのがよかった。
それがないとダラダラと作業が続いてしまう感じがあったので。
それと、日付ノートの間に挟まったcloseになったタスクを見ることで、その日に終わらせたタスクの量が感覚的に分かるのもいい感じ。

これも出来たかも

他に、これも出来たかもという点に関して。

マイルストーンの活用

昨日も少し書いたけど、マイルストーンをもう少し使えればよかったかも。
初めてだったので締め切りがいつ頃だといいのか分からず、ちょっと使えなかった。

ラベルの活用

issueにはラベルをつけることが出来るのだけど、今回はちょっと使えなかった。

考えたいのが、大きすぎるタスクをどうするか。
issueに親子関係をつけたり出来れば分解したタスクを子タスクにすればいいんだけど、そういうことは出来ないはず・・・

今回は「タスク分解する」みたいなタスクを追加しておいて、分解した各issueを追加したらそのタスクはcloseするとしてたけど、ちょっと微妙な感じ。

Issueと一口に言っても実際にはいろんなレベルに分かれるので、ラベルを使うことでそういったレベルを分けられればよかったかなと思う。
まだうまくまとまってないし試せてもいないけど。

おそらく、ユーザ目線での価値単位であるFeatureやBugfixと開発者の作業単位であるTaskにラベルを使って分けて、前者はリリースと結びついたマイルストーンで管理し、後者はスプリントと結びついたプロジェクトボードで管理。
そして、それらの結びつけは一方のissueから他方のissueに言及しておこなう感じなのかな。
その作業コストがどんなもんかを確認してみないとだけど。


宣伝です。
気になった人はチェックをお願いします!

今日はここまで!