UNIXで原稿を書く

技術評論社より,「C言語 入門書の次に読む本(*1)」 という書籍を出させていただきました.原稿の執筆は FreeBSD 上で行い, 執筆段階では,章番号や図表番号,リスト番号,参考文献の番号管理は, すべて専用の Perl スクリプトにより行いました. また,サンプルプログラムのリストは本文とは別管理にし,Perl スクリプトによって 本文中に埋め込むような構成にしました. 本稿では筆者の経験をもとに,UNIXをどのように文書作成に利用できるかを, ひとりのUNIXユーザとして紹介します.

目次

1 はじめに

「デスクトップ環境に,なぜUNIX(*2)を使うのか?」 と,質問されることがあります.一般的にはUNIXはプログラミング環境か, サーバ用のOSとして利用されることが多く,デスクトップ環境として使うことは あまり無いかもしれません(*3)

しかしUNIX環境は,デスクトップ環境としても十分に実用的なものがあります. 特筆すべきはテキストデータとの相性の良さです.このため,文章の作成に威力を 発揮します.文章の整形ツールとしては,過去からTeX(*4), roff(*5)などが利用されてきましたが,そのほかにも多数の 整形ツール,コンバータなどが存在するのも,こうしたテキストデータへの 親和性の高さによるものでしょう.

UNIXに限らずに,コンピュータ上で文章を作成することには,大きな利点があります. コンピュータ上で書く場合には,行の挿入や削除,移動は,気軽に,自由に行えます. このため,とりあえず思いついたキーワードや文をメモ書き程度にメモしておいて, あとでそれらを適当に繋ぎ合わせて,というような書き方ができます.

これが紙の原稿用紙に直接書くようなやり方になると,だいぶ変わってきます. ある程度まとまった文を考えてから書き出したり,修正するときには十分に推敲 してから修正したりなど,本来の創作活動とは別の作業が発生してしまいます. コンピュータを利用することで,こういった付加的な作業にとらわれることが 少なくなります.思いつくままに,書いては消して,書いては消してという書き方が できます.つまり,より人間の感性に近い書き方ができるわけです.

例えば,以下はこの原稿の「はじめに」を書き出したときに,最初に書いた文です. 実際の文章と比較してみてください.

------------------------------ ここから ---------------------------------------
UNIXは
プログラミング環境
それ以外にも,
とくに,文章の作成環境として
論文にはTeX,
などが利用されています.
make HTML
テキストデータに親和性が高い.
筆者がどのように利用しているか
UNIXユーザとして
------------------------------ ここまで ---------------------------------------
このような思いつきの断片的な単語の集まりから,気軽に文章を書き出すことが できます. また,コンピュータの漢字変換機能により,知らない漢字も辞典で調べる必要は ほとんどありません.ワードプロセッサが普及することで,漢字を書く能力が低く なったと言えば聞こえは悪いですが,これは逆に言えば 「そのようなことを意識しなくとも,誰でも手軽に文章が書けるようになった」 ということであり,半面,良いことでもあると筆者は思っています.

また,いくつかの文章の候補を並べ比べてみて,一番良いものを選ぶ,といったことも 気軽にできます.コンピュータで文章が書けるようになったことの一番の利点は, この「気軽さ」でしょう.目の前に紙とペンを置かれても,なにか気軽に文章でも 書こうかとはあまりならないものです.それは,やはり「紙にペンで書く」 「消しゴムで修正する」という作業自体が面倒だからです. しかし,目の前にPCがあって,エディタが開いていれば,ただ思うままに文章でも 書きたくなる人は多くいることでしょう.最近は自身の思うままに書いた「日記」や 「エッセイ」をWeb上で公開している人も多いですが,こういったことが気軽に できるということは,コンピュータとインターネットの普及の素晴らしい成果で あるということもできるでしょう.

2 UNIXによる文章作成

筆者はプログラミングだけでなく,文書作成やメール,Web などといった日常の作業 にも,FreeBSD環境を利用しています.つまり,普段のデスクトップ環境として利用して いるわけです.音楽CDの再生やCD-Rの焼き込み,テレビを見るのもFreeBSD上です. このように書くと,なんでもFreeBSDでやることにこだわっているように聞こえますが, 筆者の場合には,テレビなどはプログラミングや文書作成などの作業中にBGMがわりに つけておくことが多いのです.このため,作業を FreeBSD 上で行うかぎり,テレビも FreeBSD 上で見たい,ということに自然となってしまう わけです(*6)

UNIX環境はデスクトップ環境としても十分ですが,とくに文章の作成には,素晴らしい 力を発揮します.UNIXの利点として,テキストデータと非常に親和性が高いことが あげられます.これは正確に言うと,UNIX環境をとりまくツール群が,テキスト データを主体とした構成になっているものが多いためです.

「テキストデータを主体としている」という構造は,複数のツールを組み合わせて 利用するときに威力を発揮します. UNIXの特徴的な思想として,「なんでもできる巨大なツールを作成するのではなく, 単体の作業を行うツールを組み合わせて利用する」ということがあげられます. これはUNIXのパイプ処理に代表されます.パイプ処理と言うと,

% cat sample.txt | grep hogehoge | sort +2 | head -n 100 | less
のような処理が思い浮かぶことでしょう.これをプログラマの立場から考えると, 「全てを自分でやるのではなく,すでにツールがあるならば,それに任せる」 ということになります. 筆者は以前,ネットワーク上のトラフィックを測定するツールを即興で作成したことが ありますが,これに gnuplot(*7)をパイプで繋げて利用する ことで,それを簡単にグラフにビジュアル化することができました. ものの30分程度で,かなり確実に動作するグラフ機能が備わってしまったことに なります.こういったことも,UNIXの思想の産物だといえるでしょう.

この「ツールを組み合わせて利用する」という思想は,原稿の執筆にも活きてきます. 論文の執筆には,やはり TeX でしょう.作業の自動化にはシェルスクリプトや make が便利です.こまかい変換作業などには Awk や Perl によるスクリプトが威力を発揮 します.条件付きの文章の変換やファイルの挿入には,C言語のプリプロセッサを 使うことができます.文章の履歴の管理が必要ならば,CVSがあります.こういった ツールを組み合わせ,さらに make で自動化することにより,面倒な付加作業から 解放され,本来の執筆作業に専念することができます(*8)

3 原稿を書く

「C言語 入門書の次に読む本」(以下,「C本」と略) を書く上でまず困ったことが,章番号や図表番号,リスト番号の管理です. とくにプログラムリストに関しては,膨大な量になることが考えられました.また, 執筆中には,プログラムリストの追加・移動が頻繁に起こります.そのたびに番号を 採番し直すというのは,ちょっと避けたいところです(*9)

番号管理ははじめからすべて編集側にまかせてしまう,という選択肢もあったのかも しれません(*10). しかしC本は,もともとはC言語でオブジェクト指向的なプログラミングをするための 方法をまとめようと,個人的に書き始めた文章でした. 最終的に書籍にできなければ,Web上で公開することも考えていたため, 章番号,図表番号,プログラムリストの管理も自分で行える必要がありました.

ここで,TeX を利用するという選択肢が出てきます.筆者は学生時代に,論文の 執筆に TeX を使っていたため,TeX の利用経験はありました.しかし, (あくまで筆者の主観ですが)TeXには以下のような不満がありました.

筆者の結論としては,論文などを個人レベルで成形したいときには,TeX は非常によい 選択肢でしょう.また,報告書などの公的文書も,非常にきれいに仕上げることが できます.しかし,ちょっとした原稿を書く目的では,TeX はちょっと大がかりすぎて しまいます.

また,執筆環境は FreeBSD 上というのが,絶対に譲れない条件でした. これは筆者の好みの問題というのも大きいのですが, サンプルプログラムなどをその場ですぐにコンパイルし,実行確認できるというのが 必須の条件だったからです.このようなことを言うと, 「Windows で Word と cygwin 使えばいいではないか」 「Windows にも Perl はある」「Windows でもフィルタプログラムは書ける」 などと言われそうです.まったくもってそのとおりかもしれませんが,結局のところ 筆者には,わざわざ Windows を使うことのメリットがまったく無いため,逆に 「それならはじめから素直に FreeBSD を使えばいいではないか」ということに なります.

さらに,プログラミングの書籍なので,サンプルプログラムのソースコードは本文とは 別に管理して,いつでもコンパイル・動作確認が行えるようにしておきたいと思いま した.つまり,原稿の本文中に直接サンプルプログラムを埋め込むのは却下です.この ため,以下のようなしくみが必要になってきます(*11)

これらの要求を満たすものとして,結果として本文は HTML で記述し,章番号や図表 番号,サンプルプログラム,参考文献の番号などは専用のスクリプトで挿入するような 一連の仕組みを作ることにしました.しかし,このようなことを行ってくれる ツールが運悪く(*12)見当たらなかったのと(よく探せばあったのかも しれませんが,実はあまり真剣に探していません),それほど面倒な処理ではないので, こういったツールを自作することから始めました(*13). そうして作成されたのが htmlsection(*14)という ツールです.htmlsection は当初は筆者の個人的なツールだったのですが,非常に 便利であるため,フリーソフトウエアとして公開しています.

本文のフォーマットにHTMLを選択した理由としては,

といったことがあげられます.

4 本稿はどうやって書いているのか

では,筆者は実際にどのような環境で原稿を書いているのか,本稿の執筆環境を 例にして説明しましょう. 本稿は,以下の手順で作成しています.これらは多くがC本で作り上げた執筆環境を もとにしています.
  1. リスト番号や章番号,注釈番号を割り当てる(htmlsection)
  2. 挿入すべきファイルを挿入する(include.pl)
  3. HTML用に「#include <hogehoge.h>」を 「#include &lt;hogehoge.h&gt;」に変換する(inc2ltgt.pl)
  4. html をプレーンテキストに変換する(w3m)

4.1 make の利用

本稿の完成原稿を作成するには上記のようにいくつかの段階がありますが,これらの 作業は Makefile によってすべて自動化してあります(*15)リスト1は,本稿の完成原稿を作成するための Makefile です. つまり,今読者の方々が読まれているこの文章は,リスト1 の Makefile によって清書されていることになります.
リスト1: 本稿のMakefile
------------------------------ ここから ---------------------------------------
HTMLSEC_PARAM=-japanese
HTMLSEC_PARAM+=-table-section 0 -figure-section 0 -list-section 0
HTMLSEC_PARAM+=-no-spacer

all :	article.txt

article.html :	main.html
	cat main.html | htmlsection $(HTMLSEC_PARAM) \
		| ./include.pl | ./inc2ltgt.pl > article.html

article.txt :	article.html
	cat article.html | w3m -T text/html -dump > article.txt

clean :
	rm -f article.html article.txt article.zip

package :	article.html article.txt
	mkdir -p article
	rm -fR article.zip article/*
	cp README article.html article.txt \
		before_convert.txt after_convert.txt \
		Makefile include.pl inc2ltgt.pl \
		article
	zip -r article.zip article

------------------------------ ここまで ---------------------------------------
原稿のおおもとは mail.html というファイルになります.よって原稿の執筆&修正時 には,main.html をエディタで編集することになります(*16). make を実行することで,main.html から article.html が作成され,さらに article.txt が作成されます.article.html は図表番号やプログラムリストを 挿入済みの,完成版の原稿(HTML)です.article.txt は article.html を プレーンテキストに変換したものです.

リスト1では,本文である main.html から article.html を 作成するのに,htmlsection, include.pl, inc2ltgt.pl という3種類の フィルタを順番に通しています.また,article.html から article.txt を作成 するのに,w3m というフィルタを通しています. では,それぞれのフィルタについて順に説明しましょう.

4.2 htmlsection

htmlsection は以下のことをやってくれる Perl スクリプトです.これらの機能は, TeX が持っている機能を参考にしています(*17) 「リンクの作成」というのがわかりにくいかもしれませんが,これについては後述 します. htmlsection は,筆者のホームページ(*14)で配布 しています.

本稿も,htmlsection を利用して清書しています. リスト2リスト3は, それぞれ本稿の冒頭部分の,htmlsection による変換前と変換後の状態です. 見比べてみてください.

リスト2: 本稿の冒頭部分(変換前)
------------------------------ ここから ---------------------------------------
   001: <html>
   002: <head>
   003: <title>UNIXで原稿を書く</title>
   004: <meta http-equiv="Content-Type" content="text/html; charset=EUC-JP">
   005: </head>
   006: 
   007: <body bgcolor=beige text=brown link=red vlink=black>
   008: 
   009: <center><h1>UNIXで原稿を書く</h1></center>
   010: 
   011: 技術評論社より,...
   012: 
   013: <tableofcontents></tableofcontents>
   014: 
   015: <section>はじめに</section>
   016: 
   017: 「デスクトップ環境に,...
------------------------------ ここまで ---------------------------------------
リスト3: 本稿の冒頭部分(変換後)
------------------------------ ここから ---------------------------------------
   001: <html>
   002: <head>
   003: <title>UNIXで原稿を書く</title>
   004: <meta http-equiv="Content-Type" content="text/html; charset=EUC-JP">
   005: </head>
   006: 
   007: <body bgcolor=beige text=brown link=red vlink=black>
   008: 
   009: <center><h1>UNIXで原稿を書く</h1></center>
   010: 
   011: 技術評論社より,...
   012: 
   013: <h1>目次</h1>
   014: 
   015: <ul compact>
   016: <li><a href="#section_1">1 はじめに</a></li>
   017: ...(中略)...
   018: </ul>
   019: 
   020: <h1><a name="section_1">1 はじめに</a></h1>
   021: 
   022: 「デスクトップ環境に,...
------------------------------ ここまで ---------------------------------------
リスト2の13行目に, <tableofcontents></tableofcontents>となっている部分があります. リスト3では,ここには目次が挿入されています (13〜18行目). また,リスト2の15行目に <section>はじめに</section> となっている部分がありますが,これは リスト3では, <h1><a name="section_1">1 はじめに</a></h1> のようにして,章番号が挿入されています(20行目).このように,章の見出しは,
<section>見出し</section>
のように書いておけば,あとは htmlsection が章番号を自動的に挿入してくれます. 節には<subsection>を利用します.また,章や節から自動的に目次を作成し, <tableofcontents></tableofcontents>となっている部分に 目次を挿入してくれます.

さらに,

<section name="first_section">はじめに</section>
のようにして章に名前を付けておいて,本文中では
「このことは『<sectionref name="first_section">』で説明しました」
のように書いておくことで,「このことは『1 はじめに』で説明しました」のように, 本文中に章番号とタイトルを自動的に補填し,さらにHTMLの<a>タグで,その章 へのリンクを張ってくれます.これが,先ほど説明した「リンクの作成」という機能 です.

図を挿入する際には,図のある場所に

<figurereference name="fig1">図の名前</figurereference>
のように書いておくことで,図番号を適切に割り当ててくれます. 図番号は,「図1」「図2」のように,全体を通しての通番にすることもできますし, 「図1.1」「図2.1」などのように,章ごとに割り当てることもできます.本文中では
「これに関しては,<figureref name="fig1">を参照してください」
のように書いておけば,自動的に図番号が補填されます.当然,図へのリンクも作成 されます. 表番号には<tablereference>を,リスト番号には<listreference>を 利用します.

また,<figureindex></figureindex>のように書いておくと,すべての 図の目次(インデックス)を作成し,挿入してくれます.もちろん図目次からは,図の 本体にリンクが張られます.表,リストも同様です.

今回,本稿を執筆するにあたって,htmlsection をバージョン1.0から1.1に アップデートしました.htmlsection-1.1 では,以下の機能が追加されています.

注釈は,本文中に<noteref name="note1">のように書いておきます. さらに本文末尾や章末で,
<notes>
<note name="note1">ここに注釈の文を書く
</notes>
のようにして,注釈の内容を書いておくと,注釈が箇条書きで作成されます. 当然,本文からは注釈に向けてのリンクが張られます. 似たような書き方で,参考文献や用語の索引を入れることもできます. <notes></notes>を入れると注釈番号がリセットされますので, 章ごとに注釈(もしくは索引,参考文献)を入れることもできます.

4.3 include.pl

前述したように,C本の原稿では,サンプルプログラムは本文中には直接埋め込まず, 別に管理しています. 原稿の執筆時には,題材についてすべてを把握した状態で書き出せることはまれで あり,実際には試行錯誤しながら仕上げていくことも多いですから, サンプルプログラムやアプリケーションの出力は,本文とは別に管理できると 便利です. make 時にはこれらのサンプルプログラムや出力メッセージを本文中に埋め込む必要が ありますが, C本ではこの作業を行うために,htmlinclude.pl というスクリプトを作成しました. 筆者は現在では htmlinclude.pl を改良した include.pl というスクリプト (リスト4)を利用しています(*20). 本稿も同様の作りになっています.
リスト4: ファイル挿入用のスクリプト(include.pl)
------------------------------ ここから ---------------------------------------
#!/usr/local/bin/perl

while(<>) {
	($include) = /^%include(\s+.*)$/i;
	if ($include ne "") {
		($fname) = $include =~ /\s+file\s*=\s*(\S+)/i;
		($lf)    = $include =~ /\s+line\s*=\s*(\S+)/i;
		($df)    = $include =~ /\s+link\s*=\s*(\S+)/i;
		($hf)    = $include =~ /\s+html\s*=\s*(\S+)/i;
		if ($fname =~ /\".*\"/) { ($fname) = $fname =~ /\"(.*)\"/; }

		open (FILE, "< $fname") || die "Cannot open $fname.";
		if (($df eq "yes") && !($fname =~ /\.html$/i)) {
			print "<a href=\"$fname\">[download]</a>\n";
		}
		$line = 0;
		while (<FILE>) {
			$line++;
			if ($hf eq "yes") {
				s/\&/\&amp\;/g;
				s/\</\&lt\;/g;
				s/\>/\&gt\;/g;
			}
			if ($lf eq "yes") {
				$l = "00000000$line";
				($l) = $l =~ /(...$)/;
				print "   $l: ";
			}
			print;
		}
		close FILE;
	} else {
		print;
	}
}
------------------------------ ここまで ---------------------------------------
本文中では,ファイルを挿入したい部分には,
%include file="hogehoge.txt"
のように記述しておきます.include.pl を通すことで, %include の行に,指定したファイルが挿入されます. ちょうどCプリプロセッサの #include に相当します.
%include file="hogehoge.txt" line=yes
とすると,行番号が付加されます.また,
%include file="hogehoge.txt" link=yes
とすると,ダウンロード用に <a href="hogehoge.txt">[download]</a> のようなタグを付加します.さらに,
%include file="hogehoge.txt" html=yes
のようにすると,ファイルの挿入時に,「&」「<」「>」といった文字を, 「&amp;」「&lt;」「&gt;」といった文字に変換します. これは,以下の理由によります. & は HTML でのエスケープ文字です. 「&lt;」のように書くことで,「<」を表現することができます. 「&gt;」は「>」に,「&amp;」は「&」になります.

最終的にテキスト形式の原稿を作成するだけならば,include.pl による挿入を一番 最後に行えば,このような変換は行わなくて済みます.しかし,本稿ではHTML版の article.html と,テキスト版の article.txt の両方を作成するために,このような 作りにしています. もっとも,挿入したいファイルがある場合には,通常は「あるがままに」張り付けたい 場合が多いことでしょう.これに対して,ファイルの挿入を行った後になんらかの フィルタ(本稿の場合は w3m)を通すということは,挿入した部分がフィルタによって 変更されていないかどうかを,常に気にしなければならないことになるので,注意が 必要です.

4.4 inc2ltgt.pl

include.pl のところで説明しましたが,
#include <stdio.h>
のような文は,HTML では
#include &lt;stdio.h&gt;
のように書かなければなりません.<stdio.h>の部分がHTMLのタグと解釈されて しまうためです. include.pl では,ファイルを挿入する際にこの変換を行う機能がありますが, それだけだと,本文である main.html 中に上のような記述があった場合に, やはり問題になります.

C本では,inc2ltgt.pl というフィルタ(リスト5)を1段通す ことで,これを解決しています.inc2ltgt.pl は,

#include <stdio.h>
のような部分を,
#include &lt;stdio.h&gt;
のように変換するだけの Perl スクリプトです(*21). 本稿の上記の #include <stdio.h> の行も,inc2ltgt.pl によって変換されているため,正しく表現できています.
リスト5: inc2ltgt.pl
------------------------------ ここから ---------------------------------------
#!/usr/local/bin/perl

while (<>) {
	s/(\#\s*include\s*)\<(.*?)\>/$1\&lt\;$2\&gt\;/;
	print;
}
------------------------------ ここまで ---------------------------------------

4.5 w3m

本文を make して,作成された article.html をブラウザで見ることで,完成原稿を 閲覧することができます.しかし,原稿を編集側に渡す際には,HTMLよりもプレーン テキストのほうがのぞましい場合もあることと思われます. このため,w3m(*22)というテキストブラウザを通して article.html から article.txt というプレーンテキストのファイルを作成しています.

w3m は FreeBSD の ports になっています.w3m は非常に完成度の高いテキスト ブラウザで,とくに日本語処理は安定したものがあります. 通常の Web サイトを閲覧するだけならば,大抵はほとんど問題なく利用できます. 本稿では w3m を HTML からプレーンテキストに変換するためのフィルタとして 利用しています.

また w3m によってプレーンテキストに落とすことで,w3m が行ごとの文字数を調整して 整形してくれるため,article.txt の行数からページ数の見当がつけやすいという 利点もあります.

なお,筆者は通常は article.txt でなく,article.html によって完成原稿を チェックしています.これはHTMLだと,参照先にリンクが張られているため, チェックに便利だからです.これにも筆者は w3m を利用しています. 筆者が普段利用しているノートPC(Libretto SS1000)は骨董的なものなので, ブラウザに netscape や opera を利用するのは重すぎます. Libretto のポインタは使いにくいため(*23),なるべくなら すべての操作をキーボードで行いたい,という理由もあります.

5 おわりに

UNIXは文書作成用の環境としても非常に使い勝手がよいことを,筆者の執筆環境を もとに説明しました.筆者は本職はプログラマですので,なにかやりたいことが あるとなると,すぐに「スクリプトを自作して...」となってしまいます. UNIXを利用する場合に嬉しいのは,このようなときに Sed や Perl ですぐに作れて しまうことです.また,シェルスクリプトや Makefile を利用することで, 作業をかなり細かく自動化することもできます.

逆に言えば,デスクトップとしてUNIXを利用するならば,こういったツール類の 利用方法を,ぜひとも覚えるべきと言えるかもしれません.筆者がとくにおすすめ するのは Perl です.Perl が書けるようになれば,大抵のテキスト処理はできて しまうからです.

このようなツールや執筆環境は,いちど作ってしまうと,あとはそれを流用することが できますから,作業の効率はどんどん良くなっていきます. そして,このような「環境」は,個人の大切な財産となります. このように,経験を積むことでどんどん環境が進化して,作業効率を向上していける ことが,デスクトップとしてのUNIX環境のひとつの魅力かもしれません.

注釈

-------------------------------------- 原稿はここまでです.おつかれさまでした!