自分が出している技術系同人誌の執筆の話を書いておく。
原稿の形式
技術同人誌界隈ではRe:VIEWがポピュラーのようだが(最近はSATySFiやTypstも見かける)、自分はLaTeXで書いている。
最初に出した同人誌はMarkdown原稿をPandocで処理してLaTeXで組んだ(同人誌「代数的数を作る」ができるまで/PandocとかLaTeXの話)が、Markdownの表現力の低さと、レイヤーが重なることによる「痒いところへの手の届きにくさ」が辛くて、それ以降の同人誌は全てLaTeXを手書きしている。前回の「Haskellでの型レベルプログラミング」は先にMarkdownの原稿(Zenn版)があったが、それもLaTeXに書き直した。
LaTeXを使うことのメリット・デメリットは次のようになるだろう:
- メリット
- 見た目の細かい調整がやりやすい。
\includeonly
等のLaTeXに備わった機構が使いやすい
- デメリット
- EPUB版を出しづらい。
そのうちLaTeX原稿をHTMLに変換するツールを自作してEPUB版を出せたらなあと思っているが、いつになるかはわからない。
私が書いている同人誌のLaTeXは大体似たような形式なので、そのうちテンプレートを公開するかもしれない。公開しないかもしれない。
ソースコードとの対応
プログラミング関係の本にはソースコードを貼ることが多いだろう。その際、ソースコードが正当なプログラムであることが確認されていること(コンパイルが通ること)、サンプルコードを写経しなくてもGitHub等で入手可能になっていることが望ましい。
そのためのやり方は大きく分けて2通りあると思う。一つ目としては、単体で動作確認されたソースファイルを用意して、それを何らかのマークアップにより原稿に埋め込むスタイルだ。原稿ではファイル名と行番号により参照する:
% 原稿の例
以下のコードを参照:
\inputsource[line={10-20}]{foo.hs}
去年出版された「Binary Hacks Rebooted」では途中までは(原稿をRe:VIEW化するまでは)この形式だった。Markdownに独自のマークアップを用意して、ソースファイルを参照して、自作ツールによりソースコード埋め込み済みのMarkdownソースに変換する。
このスタイルの亜種もある。埋め込みたいソースの範囲を行番号で指定すると、ソースコード側の変更に脆弱になる。本の紙面に収めるために改行を挿入すると、行番号の変更も必要になる。そこで、ソースコード側にもマークアップを入れて、識別子により参照するという手がある。ソースコード側の例は次のようになるだろう:
int main(void) {
#pragma region foo
puts("Hello world!");
#pragma endregion
}
公開するサンプルコードからは、ソースコードに対する識別子は不要なので削除する。
「Binary Hacks Rebooted」では実際にはこの形式(ソースコードに対して追加のマークアップを入れる)で作業したが、この方法にもデメリットはある。ソースコードのコンパイル結果を載せる際に、エラーや警告の行番号がマークアップ(上記の例だと #pragma region
)によりずれるのだ。「Binary Hacks Rebooted」では手動で直した。
今回の「だめぽラボ」新刊では、二つ目のやり方を試してみた。つまり、原稿に混ぜて書いたソースコードを「正」とし、動作確認用・公開用のソースコードは原稿から抽出するという形式だ。原稿に書くソースコードには識別子を埋め込んでおく:
% 原稿の例
以下のコードを参照:
\begin{HsCode}[chunkname={nextToken}]
-- すごいコード
\end{HsCode}
そして、抽出用のスクリプト(今回はLuaで書いた)にはコード片の埋め込み位置を指定したテンプレートを記述しておく:
template "Input.hs" [[
{{InputPreamble}}
{{nextToken}}
]]
関数の一部(パターンマッチ、C系の言語ならswitch)の記述を後の章で追加したいこともある。その場合、最初に登場する関数には -- ...
というコメントを入れておいて、後の章で追加したコード片がそこに入るようにした。
\begin{HsCode}[chunkname={expand}]
expand :: Expandable -> Token -> M [EToken]
expand Undefined _ = throwError "Undefined control sequence"
-- ↓ここには後の章で追加する
-- ...
\end{HsCode}
このやり方は結構いい感じなのではないかと思う。
こういうことをやっていると、御大の「文芸的プログラミング」を意識せざるを得ない。HaskellにもLiterate Programmingのサポートがあるが、あれはなんか違うかなあと思って避けていたのだった。しかし、本とサンプルコードを一緒に書く上では(Haskellのやつは別として)有益そうだ。
今回は、各章の終わりまで読めばその時点の動作するプログラムが手に入るようにした。そして、読者が各ステップのプログラムを試せるように、各章ごとにブランチを用意した。これがうまくいくかは、やってみて検討したい。
入稿用PDFファイルの用意
PDFはPortable Document Formatとは言うが、自分のパソコンの画面と印刷所の印刷機の間でポータブルにするには色々と気をつけることがある。
特定の目的に適したPDFのサブセットというものがあり、印刷向けだとPDF/Xというのがある。ここ数回の入稿ではPDF/X-1aに準拠したPDFを用意している。「LaTeXでPDF/XやPDF/Aを出力するメモ」も参考にしてほしい。
さて、前回の入稿ではPDF/Xに準拠するだけではダメで、「フォントのエンコーディングがビルトインだと文字化けする可能性がある」と言われた(これもPDF/Xの記事に書いた)。私が使っている印刷所「ねこのしっぽ」では以下のページに言及がある:
原稿制作マニュアル|PDFでの入稿について(ねこのしっぽ)
LaTeXの場合は、unicode-mathを使って数式にLatin Modern Mathを使うようにすれば大体うまくいく……と思っていたが、今回はhologoパッケージで使っていたMETAFONTのロゴとNTSのロゴが引っかかった。
文字化けが絶対に起こらない方法として、PDFファイル全体をアウトライン化するという手もある。だが、文書を処理するたびにアウトライン化をするのは煩雑に感じられた。今回はかなり邪道な気はするが、「ロゴをアウトライン化したPDFファイルを用意し、それを埋め込む」形にした。
具体的には、
\documentclass[crop=true, border={0pt 0.5pt}]{standalone}
\usepackage{mflogo}
\begin{document}
\MF
\end{document}
\documentclass[crop=true, border={0.5pt 1pt}]{standalone}
\usepackage{hologo}
\begin{document}
\hologo{NTS}
\end{document}
という内容のLaTeX文書を処理してPDFファイルを作り、Ghostscriptでアウトライン化する。Makefileで書くとこんな感じだろう:
metafontlogo.pdf: metafontlogo.tex
cluttex -e pdflatex -o $@ $<
metafontlogo-outlined.pdf: metafontlogo.pdf
gs -o $@ -sDEVICE=pdfwrite -dCompatibilityLevel=1.3 -dNoOutputFonts $<
# $(inkscape) --export-text-to-path --export-pdf-version=1.4 --export-filename=$@ $<
ntslogo.pdf: ntslogo.tex
cluttex -e pdflatex -o $@ $<
ntslogo-outlined.pdf: ntslogo.pdf
gs -o $@ -sDEVICE=pdfwrite -dCompatibilityLevel=1.3 -dNoOutputFonts $<
# $(inkscape) --export-text-to-path --export-pdf-version=1.4 --export-filename=$@ $<
アウトライン化にはInkscapeも使えるが、PDF/Xで出力するという目的にはInkscapeは適さなかった(PDF 1.3が必要なのに対してInkscapeの出力はPDF 1.4以降になる)。
本文のプリアンブルには
\providecommand{\myMETAFONTlogo}{\hologo{METAFONT}}
\newbox\myNTSlogotmp\setbox\myNTSlogotmp=\hbox{\hologo{NTS}}
\providecommand{\myNTSlogo}{\hologo{NTS}}
と書いて本文中では \myMETAFONTlogo
, \myNTSlogo
等のコマンドを使い、PDF/X用のPDFファイルを作るときは
\PassOptionsToPackage{x-1a}{pdfx}
\newcommand{\myMETAFONTlogo}{\raisebox{-0.5pt}{\includegraphics{metafontlogo-outlined.pdf}}}
\newcommand{\myNTSlogo}{\eghostguarded{\hspace{-0.5pt}\raisebox{\dimexpr-\the\dp\myNTSlogotmp-1pt\relax}{\includegraphics{ntslogo-outlined.pdf}}\hspace{-0.5pt}}}
\input main.tex
という内容のファイルを処理する。
正直言ってあまり褒められた方法ではないと思う。汎用性も低い。
空きページの扱い
本を書いていると空白ページができることがある。章の始まりは奇数ページ(あるいは偶数ページ)に揃えることが多く、前の章が奇数ページで終わるとその間の偶数ページが空白になるのだ(「章の始まりとして偶数ページを許容する」という方針もありうる。実際、Haskell型レベルの本は偶数ページ始まりを許容した)。
印刷所に入稿する際に空白ページがあると、何らかのトラブルと勘違いされる可能性がある。そのため、空白ページがある場合はその旨を連絡事項として伝達しておくのが良い。
空白ページに何らかの内容を載せるという手もある。余裕があれば挿絵やコラムを載せると良いだろう。「ページ番号だけ載せる」という手も考えたが、今回は試す余裕がなかった。
価格設定
同人誌は一度に印刷する部数が多いほど単価が安くなる。しかし、たくさん刷ると売れなかった場合に在庫になる。また、たくさん刷る前提で値段を設定してしまうと、追加で少部数刷るというのがやりにくい。
「技術書典16の振り返り」にも書いたが、「30部単位で刷っても赤字にならない」程度の値段を設定することにした。今回のページ数(表紙込みで172P)では30部刷った時の単価が1300円近くになったので、1500円で売るのが妥当だと判断した。
執筆に費やせる時間
本の執筆にはいくらでも時間を注ぎ込む余地がある。なので、どこかで締切を決めないと本は完成しない。
今回のイベント、技術書典18はどうだろうか?オフライン開催は6月1日で、ページ数が少なければ通常締め切りは1週間くらい前(ねこのしっぽだと5月27日だった)、早割10%引と早割20%引を使うとそれぞれ1週間(程度)、2週間(程度)締め切りが早まる。そして、116ページを超える本は追加で1週間締め切りが早まる。
今回書いた本は116ページを超えるので、
- 早割20%引:5月7日
- 早割10%引:5月14日
- 通常締め切り:5月21日
となる。
当初の計画では、早割20%引を狙って5月7日に原稿を完成させることを狙っていたが、連休中に執筆が進まなかったのもあって無理だった。そこで5月14日完成とした。
もちろん、早割にこだわる必要はそんなにないのだ。ちゃんと売れれば赤字にはならない値段には設定する。それに、学生の頃と違ってお金には余裕ができた。
しかし、原稿執筆だけが生活ではないので、いつまでもダラダラと手直しをやっているわけにもいかない。学生の頃とは違って時間が貴重なリソースになった。そういうのもあって、締切は早めに設定することにした。
そんな感じで作った新刊「作ってわかるTeX言語」をよろしくお願いします。会場に来られない方はオンライン販売もあります。詳しくは以下の記事を見てください: