2009/12/30

年賀状かいた。
%!
<< /PageSize [285 420] >> setpagedevice

1 1 25 {
/n exch def
0 12 360 { % for
/i exch def

newpath
gsave
/r1 {rand 5 mod 2 div} def
/r2 {rand 2 mod 2 div} def
/r3 {rand 2 mod 2 div} def
r1 r2 r3 setrgbcolor
140 220 moveto
i rotate
/Times-Bold findfont 10 scalefont setfont
( ) show
0 10 20 { % for
/j exch def
/AgentOrange findfont j 12 add scalefont setfont
(2) show
/AgentOrange findfont j 14 add scalefont setfont
(0) show
/AgentOrange findfont j 16 add scalefont setfont
(1) show
/AgentOrange findfont j 18 add scalefont setfont
(0) show
} for
grestore
} for
220 45 moveto
/Georgia-BoldItalic findfont 10 scalefont setfont
n =string cvs show
(/25) show
showpage
} for

DSC_0178

こちらのAgentOrangeというフリーフォントを使わせていただきました。ありがとうございます。

http://www.1001freefonts.com/AgentOrange.php

2009/12/28

Gauche の CGI スクリプトを lighttpd + FastCGI で動かす手順

Gauche の CGI スクリプトを lighttpd + FastCGI で動かす手順。自分用の備忘録。

FastCGI は、Web サーバと外部プログラム間のやり取りを規定した一種のプロトコル。外部プログラムは起動しっぱなしになっていて、Web サーバは、その起動しっぱなしのプロセスと必要に応じてやり取りする。したがって、外部プログラムには、起動しっぱなしで Web サーバとおしゃべりできる仕組みが必要で、Web サーバのほうも、そんな外部プログラムとおしゃべりできないといけない。

外部プログラム側で必要となる仕掛けは、Gauche の場合、Gauche-fastcgi が提供する with-fastcgi という関数で cgi-main をくるむだけでいい。Gauche-fastcgi のインストールには FastCGI の開発ツールキットが必要。

Web サーバのほうは、lighttpd を使う場合、mod_fastcgi を有効にして、しかるべき設定をする。lighttpd の設定ファイルは /etc/lighttpd/lighttpd.conf なので、まあこれを編集してもいいのだけれど、Debian では lighty-enable-mod というユーティリティがあるのでこれを使う。具体的には、/etc/lighttpd/conf-available/ 以下に nn-name.conf という形式の名前を付けたファイルで設定の断片を用意し(nn は優先順、name は名前)、lighty-enable-mod name を実行する。最初から用意されている nn-name.conf ファイルもいくつかあって、10-fastcgi.conf という FastCGI 用のものもあるけれど、きっと Gauche で書いた FastCGI スクリプトには対応していない。だから、代わりに次のような内容の 10-fastcgi.conf を用意する。
server.modules   += ( "mod_fastcgi" )

fastcgi.server = (
"sample.fcgi" => ((
"host" => "127.0.0.1",
"port" => 1026
)),
"index.fcgi" => ((
"host" => "127.0.0.1",
"port" => 1027
))
)
sample.fcgiindex.fcgi が、 Gauche で書いた実行可能なスクリプトのファイル名。この設定は、「クライアントから sample.fcgi を要求されたら、localhost 上のポート 1026 で動きっぱなしの sample.fcgi に処理させますよ」などと読む。というわけで、事前に localhost 上のポート 1026 で sample.fcgi を動きっぱなしにしておく必要がある。そのために使うのは spawn-fcgi という lighttpd に付属するコマンド。
$ sudo spawn-fcgi -f /var/www/sample.fcgi -p 1026 -u www-data -g www-data
$ sudo spawn-fcgi -f /var/www/index.fcgi -p 1027 -u www-data -g www-data
これで、FastCGI でのおしゃべりをポート 1026 (あるいは 1027)で待ち受けるプロセスが立ち上がる。なお、sample.fcgiindex.fcgi に実行権限が付与されてないと(chmod 755 されてないと)、spawn-fcgi がエラーになる。また、Gauche のエラーでプロセスが死んでも spawn-fcgi そのものは成功してしまうので、spawn-fcgi の実行後に ps awx | grep gosh して起動しっぱなしのプロセスがあることを確認したほうがいい。

この後、lighttpd を起動する。すでに起動していて再起動する場合は、設定ファイルの再読み込みもしておく。
$ sudo /etc/init.d/lighttpd force-reload
$ sudo /etc/init.d/lighttpd restart
これで準備はおしまい。リロードしまくっても新しい gosh プロセスが毎回起動しなければOK。

なお、この手順は、事前に動きっぱなしにしておいた外部プログラムをIPアドレスとポートで識別する方法。識別に UNIX ドメインソケットを使うこともできる。また、外部プログラムを事前に起動しておかず、初回は lighttpd から起動させることもできる。細かい話は lighttpd の mod_fastcgi のドキュメントにいろいろと書いてあった。

2009/07/29

DebianでWillcom端末からPPP接続

Debian/GNU Linux(squeeze)に Willcom の PHS 電話端末 AH-J3003S(ウィルコム定額プランで契約)を USB でつなぎ、契約なしで利用できるプロバイダ PRIN にダイアルアップして PPP でインターネットに接続するときのメモ。

まず、避けて通れないプロバイダについて。Willcom 端末からのダイヤルアップ接続には、事前契約が不要な PRIN というプロバイダが使える。使えるんだけど、ずっと料金体系や支払い方法がよくわからず、こわくて使ってなかった。最近になって Windows XP から勇気を出して使ってみたところ、ちょっと外出先で接続するくらいなら気にならない程度の金額だとわかったので、Debianマシンでも使ってみることにした。気になるお値段はPRIN/サービス案内に一覧表がある。Willcom の電話端末を「ウィルコム定額プラン」で契約していれば、「リアルインターネットプラス」を契約していなくても 10円/分 くらい。料金の支払いは、電話料金と一緒に引かれているっぽい(金額が微妙でよくわからないけど、ほかから請求がこないので)。

AH-J3001S という端末は、Linux Kernel からは ACM デバイスとして認識される。cdc-acm モジュールが有効になっていれば、USB ケーブルでつなぐだけで、こんな感じに認識されるはず。
$ tail /var/log/messages
...
... cdc_acm 4-2:1.0: ttyACM0: USB ACM device
... usb 4-2: New USB device found, idVendor=1145, idProduct=0001
... usb 4-2: New USB device strings: Mfr=0, Product=0, SerialNumber=0
...
というわけで、必要な作業は、PPP の設定のみ。

Debian での PPP 接続には ppp パッケージが必要。それと、設定ファイルを編集する pppconfig というユーティリティーを使いたいので、 pppconfig パッケージもインストールする。
$ sudo apt-get install ppp pppconfig
インストールできたら、pppconfig を使って、モデムのデバイスファイルやプロバイダの情報(ダイアルアップ先やユーザ名やパスワードなんか)を設定する。モデムのデバイスは /dev/ACM0 にする。プロバイダがらみの設定値は、PRIN/サービス案内(アクセスポイント一覧がある)やPRIN/各種設定・利用案内(Windows XP のウィザード設定画面の説明がある)とかから探せば見つかる。

pppconfig による設定は /etc/ppp/peers/ および /etc/chatscripts/ 以下にテキストファイルとして保存される。手元の設定結果はこんな感じ。
$ cat /etc/ppp/peers/willcom
# This optionfile was generated by pppconfig 2.3.18.
#
#
hide-password
noauth
connect "/usr/sbin/chat -v -f /etc/chatscripts/willcom"
debug
/dev/ttyACM0
115200
defaultroute
noipdefault
user "prin"

ipparam willcom

usepeerdns
$ cat /etc/chatscripts/willcom
# This chatfile was generated by pppconfig 2.3.18.
# Please do not delete any of the comments. Pppconfig needs them.
#
# ispauth CHAP
# abortstring
ABORT BUSY ABORT 'NO CARRIER' ABORT VOICE ABORT 'NO DIALTONE' ABORT 'NO DIAL TONE' ABORT 'NO ANSWER' ABORT DELAYED
# modeminit
'' ATZ
# ispnumber
OK-AT-OK "ATDT0570570611##61"
# ispconnect
CONNECT \d\c
# prelogin

# ispname
# isppassword
# postlogin

# end of pppconfig stuff
なお、このファイルには書き出されてないけど、プロバイダのパスワードにはユーザ名と同じ prin を設定する(公開情報)。

で、いよいよ接続するには pon コマンドを使う(利用するユーザは dip グループに入っていないといけない)。
$ pon willcom
willcom の部分は、pppconfig による設定の際に指定する設定名。これは /etc/ppp/peers/ なんかの下にあるファイル名でもある。ifconfig してみると ppp0 みたいな名前のインタフェースが新たに現れているはず。切断は poff で。

2009/07/10

LaTeX におけるページをまたいだ囲み記事スタイルのまとめ

追記(2014年11月7日)

いまなら、囲み記事を書きたい場合には tcolorbox パッケージを使うのがよさそうです。 さらに脚注問題については footnoteパッケージというのが 1997 年からありました orz 方法は違うけど、以下の記事でやっている「段落ボックス中の \footnote を外側に追い出す」ができます。 まとめるとこんな書き方をすればよさそう。
\documentclass[a4paper]{article}
\usepackage{lipsum}
\usepackage[most]{tcolorbox}
\usepackage{footnote}
\tcbuselibrary{breakable}
\newtcolorbox{mybox}{breakable, enhanced jigsaw}
\makesavenoteenv[myftnbox]{mybox}

\begin{document}
\lipsum[1]

\begin{myftnbox}
\lipsum[1]

First footnote\footnote{first footnote}.

\lipsum[1-10]

Second footnote\footnote{second footnote}. 
\lipsum[1]
\end{myftnbox}

\lipsum[1]

\end{document}

ただし、tcolorbox に breakable を設定した環境では、minipage でもないのに minipage 専用の独立した脚注番号用のカウンタ mpfootnote が minipage っぽく使われてしまっているため、footnote パッケージはこれを通常の mpfootnote のように外側の脚注番号用カウンタと同期できません。そのため、上記のままでは、myftnbox 環境内だけは脚注番号が毎回 a, b, ... になってしまい、外側の 1, 2, ... と同期できません。ページをまたいだボックス環境で、ドキュメント内で一貫した脚注番号を使うには、何か自分で工夫をするしかなさそうです。

というわけで、以下の本文では、そのための工夫の一例を紹介します。実際に適用してみた結果はこちら


LaTeX でページをまたいだ囲み記事を実現するスタイルはいくつかあって、今のところ回避困難な制限がある。そのまとめ。

基本は framed.sty だろう。角が四角くてもいいなら、これがいちばん素性がいい感じ。ただし、ページをまたぐときに、前のページの末尾と次のページの先頭に罫線が入る。標準的なパッケージなので、いろんな環境で利用できる可能性が高い。たぶん中身をボックスにいれて \vsplit で一行ずつページを構成する垂直ボックスに渡していく方式。

もうひとつ、 eclbkbox.sty というのもある。これはページをまたぐ箇所に罫線が入らない。これもやはり角は四角い。これも \vsplit を使う方式。

同じく \vsplit を使ったページ分割手法で、しかも角丸に対応したスタイルとして、emath の itembkbx.stymultipagebox.sty がある。

さて、以上の4つのパッケージには共通する悩ましい制約条件がある。\footnote がまったく使えない。翻訳なんかだと囲み記事に脚注入れたい場合もあるというのに、いれられない。いろいろ回避策を考えてみたけど、\vsplit を使うにはいったん囲み記事にしたい中身をボックスに入れるしかなく、その時点で \footnote を見るしかなくて、\vsplit するときには手の出しようがない。そもそも \vsplit はインサートの分割アルゴリズムを利用するためのプリミティブだから、やはりインサートである \footnote に対応できなくてもしょうがないか(実際には直接の関係はないけど)。

以下のようにして簡単に \footnote を有効にできる場合がある(全部試してない。使えない環境も多々あるはず)。
\newtoks\mftn
\def\mfootnote#1{%
\footnotemark
\edef\@tempa{\the\mftn\noexpand\footnotetext[\the\c@footnote]}%
\global\mftn\expandafter{\@tempa{#1}}}%
\def\mfootnoteout{%
\the\mftn
\global\mftn{}}

\begin{...}
\let\footnote\mfootnote
...
\end{...}
\mfootnoteout
ただしこの回避策だと、\footnote の項目がページごとではなく最後のページにまとめて出てしまう。まあ、最後の手段ということで。

ページをまたぐ囲み記事で、しかも \footnote に完全対応する方法として、longtable.sty を使って独自の環境をでっちあげるという手がある。(。汎用性がないのでそのままの状態ではたぶん利用不可能。囲み記事の段落を longtable の行に対応させるという荒業のため、段落ごとにしか改ページできない。これが最大の難点。でもまあ、この \longtable を使う方法の難点こそが、\footnote をページごとに出力するための直接の代償でもあるわけだ。)

というわけで、だれか footnote を華麗に再定義して footnoteanyware.sty みたいなのを作ってください。

2009/05/24

Goodby Bafana

『マンデラの名もなき看守』を見た。見ることができた。赤ちゃんがいると映画館にいく機会は限られるのだけど、今日はたまたまそういうチャンスだった。そして、たまたま今週の早稲田松竹のラインナップが『マンデラの名もなき看守』だった。ついてた。

映画では、旧体制の南アにおける黒人差別政策についてどうこう言うこともなく、看守としてマンデラとかかわるたびに気がついたら人生の窮地に立っている男とその家族の話をテンポよくつないで、1990年2月11日の釈放シーンで締めくくっている。じわじわくる。ラストまでのエピソードのおかげで、最後の"goodbye bafana"というセリフの手前くらいで涙が出そうになる。そして釈放シーンの看守の奥様がとてもきれい。この2つのシーンは、もっと感動的に演出してもよさそうなものだけど、これでちょうどよかったのだろうな。

現代史に散らばっている社会問題って、「かわいそう」駆動型の活動や「正義感」駆動型の行為、あるいは思考停止になりがちだ。自分は正直なところ思考停止していると思う。それを「娯楽」の形で消化する贅沢に折り合いを付けるのは難しいし、たぶん付かない。『ホテルルワンダ』もそうだった。でも、たとえばダライ・ラマ14世の亡命後の半生を描いた映画ができれば、きっと見に行く。贅沢はくせになる。

2009/05/23

A rant about happiness

タイ料理屋でしこたまのみながら、「幸福」を定義した。
手元にメモが残っているので、思い出しつつ書き起こしておく。

「幸福」とは何かよくわからないので、まずは「幸福でない」について考えよう。

レベル1の「幸福でない」とは、幸福の軸が定まっていて、幸福の側にいない状態。
レベル2の「幸福でない」とは、レベル1の「幸福でない」を定めるすべがない状態。つまり、この場合は、レベル1における幸福の軸を見出せていない状態。

この定義から、レベルnの「幸福でない」を自然に拡張できる。
レベルnの「幸福でない」とは、レベルn-1の「幸福でない」を定めるすべがない状態だ。

で、レベルωの「幸福でない」とは何かを考えてみる。ωは最初の可算無限基数。たぶん、任意の可算基数レベルの「幸福でない」を定めるすべがない状態、なんだろうな。

ということは、ある可算基数があって、そのレベルで「幸福でない」を定めるすべがあれば、レベルωで「幸福でない」ではないといえる。「幸福でない」の逆が「幸福」とは限らないけど、まあ、「幸福になりうる」っていうくらいならいいだろう。とくに、レベル1で「幸福でない」を定めるすべがあれば、レベルωで幸福になりうる。

ここまで書いて気づいたけど、べつに無限基数まで拡張する必要なかったか。
レベル1で「幸福でない」を定めるすべがあれば、どんなレベルでも幸福になりうる。

ところで、いまうちらはレベル1の「幸福でない」を定めるすべを持っている。実際、定めることができている。したがって、うちらはどんなレベルでも幸福になりうる。

おや、なんだかあたりまえの結論じゃないか。
そんな話だったっけかなあ。これだから酔っ払いは。

2009/04/23

LaTeXでSubversionのキーワード展開を使うパッケージ

LaTeX で Subversion のメタ情報(つまり、$Id$ とかのキーワード展開)を使いたい。

Subversion におけるキーワード展開について基本をまとめると、たぶんこんな感じ。
  • 各ファイルのsvn:keywords属性を展開したいキーワードに設定する。
  • 原稿ファイル中にある $Id: ... $ などが展開されるのは、svn checkout や svn update でリポジトリの変更を取ってきた時点。
困っちゃうのは、ファイルごとにしかメタ情報を使えないところ。LaTeX で原稿を複数のファイルに分けて執筆している場合に、1ページめに原稿全体としての最新リビジョンを出力するようなことができない。1ページめをコンパイルする時点では、そのページの元になっている *.tex ファイルの $Id: ... $ しか展開されなからだ。後ろのほうのファイルだけが更新されたら、その新しいリビジョン番号には追随できなくなってしまう。
この悩みを解決する LaTeX のパッケージがいくつかある。svn-multi が新しいめで高機能そうなんだけど、今回は svninfo を使うことにした。以下は備忘録。

book.tex から zenhan.tex と kouhan.tex を include していて、Id キーワードの情報が使いたいとする。
% プリアンブルいろいろ
\begin{document}
\include{zenhan}
\include{kouhan}
\end{document}
まずは svninfo パッケージを利用できるようにする。\usepackage{svninfo} は \begin{document} の直前に置かないといけないようだ。
% プリアンブルいろいろ
\usepackage{svninfo}
\begin{document}
\include{zenhan}
\include{kouhan}
\end{document}
つぎに以下のような行を zenhan.tex と kouhan.tex に追記する。最後の $ のあとにスペース必須。 "file rev YYYY-MM-DD hh:mm:ss owner" の部分は、現在のファイルの情報(svn log -rHEAD zenhan.tex とかで得られる情報)か何かを手書きしておく。
\svnInfo $Id: file rev YYYY-MM-DD hh:mm:ss owner $ ← スペースあり
忘れずに svn:keywords を設定してコミット。
> svn propset svn:keywords "Id" *.tex
> svn commit -m"added svnInfo Id"
準備はこれでOK。この情報を LaTeX で出力するには、\svnId とか \svnInfoRevision といった svninfo のコマンドを使う。
複数のファイルにある $Id: ... $ を全部チェックして最新のリビジョン番号をとってきてくれる \svnInfoMaxRevision というコマンドもある。この \svnInfoMaxRevision をzenhan.tex に書いておけば、最新のリビジョンで更新されたのが kouhan.tex だけでも、その最新のリビジョン番号に展開される。たとえば、zenhan.tex に対する最後の変更がリビジョン 1000 で、kouhan.tex だけが 1001 で変更されたとすると、どんなに svn up しても zenhan.tex にある $Id: ... $ の部分はリビジョン 1000 に相当する情報にしか展開されない。ところが \svnMaxRevision のほうは 1001 に展開されてくれる。
svninfo に用意されているほかのコマンドは、マニュアルのPDFを参照。

The svninfo package(PDMマニュアル)
http://ftp.yz.yamagata-u.ac.jp/pub/CTAN/macros/latex/contrib/svninfo/svninfo.pdf

2009/04/21

Gauche の string-split が便利だ。便利なんだけど、セパレータとしてプロシージャを渡したとき、文字列にある各文字に対してプロシージャが順番に呼ばれないっぽいのが困る。
まずはふつうの例。こんな文字列があったとき、
(define text-with-block
"words, |entering a block|, got out of the block.")
スペースかどうか判断するプロシージャを is-space? 渡して、この文字列をぶったぎりたい。
(define is-space? (pa$ char=? #\space))
(string-split text-with-block is-space?)
=> ("words," "|entering" "a" "block|," "got" "out" "of" "the" "block.")
これは問題ない。
今度は、文字列のうちで縦棒 "|" でくくられている部分を塊とみなし、その内部にあるスペースは無視したいとする。つまりこんな結果がほしい。
(string-split text-with-block is-isolated-space?)
=> ("words," "|entering a block|," "got" "out" "of" "the" "block.")
クロージャーの出番です。is-isolated-space? はこんな定義でいいだろう。
(define is-isolated-space?
(let ((inblock? #f))
(lambda (c)
(cond ((char=? c #\|)
(set! inblock? (if inblock? #f #t))
#f)
(inblock?
#f)
((char=? #\space c)
#t)
(else
#f)))))
実際、 text-with-block に対して is-isolated-space? を繰り返し呼べば、縦棒 "|" でくくられた内部がセパレータとみなされないことが確かめられる。
(let R ((ls (string->list text-with-block)))
(cond ((null? ls)
'())
((is-isolated-space? (car ls))
(cons 1 (R (cdr ls))))
(else
(cons 0 (R (cdr ls))))))
=> (0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 1 0 0 1 0 0 0 1 0 0 0 0 0 0)
見づらいけど、 "|entering a block|," の位置に相当する部分がぜんぶゼロになっているのがポイント。
だから、string-split に渡したプロシージャが文字列にある各文字に対して順番に呼ばれるなら、目的の結果が得られるはず。でも得られない。
(string-split text-with-block is-isolated-space?)
=> ("words," "|entering" "a" "block|, got out of the block.")
しかも、もういっかい呼び出すと結果が変わる。
=> ("words, |entering" "a" "block|, got out of the block.")
ということは、各文字ごとに is-isolated-space? の抱えているクロージャがクリアされているわけではないんだよな。2回目の呼び出しでは、inblock? の初期値が #t になっているようだ。
ちなみに、マニュアルにはこうある。

splitter に手続きが与えられた場合、string にある各文字に対してその手続きが呼ばれ、
splitter が真の値を返すような連続した文字群がデリミタとして使われます。
また、ソースの stringutil.scm にある string-split の定義を見ると、ふつうに文字列の先頭から各文字をプロシージャーで処理してるっぽい。なにがおかしいのかなあー。
仕方がないので代わりの関数をでっちあげる。
(define (string-split-by str proc)
(let ((n (string-index str proc)))
(if n
(receive (h r)
(values
(string-take str n)
(string-drop str n))
(if (= (string-length r) 0)
'()
(if (> n 0)
(cons h (string-split-by (string-drop r 1) proc))
(string-split-by (string-drop r 1) proc))))
`(,str))))

(string-split-by text-with-block is-isolated-space?)
=> ("words," "|entering a block|," "got" "out" "of" "the" "block.")