日曜大工の最近のブログ記事

Unicode msearch 導入メモ

|

私のメインサイトでは namazu 2 でサイト内全文検索ができるようになっている。namazu 2 は UNIX 環境日本語全文検索エンジンの定番になって久しいが,基本的に ISO-2022-JP, Shift_JIS, EUC-JP の日本語文字コードを前提としており,多国語文書には適さない。ロシア語に限って言えば,Unicode ロシア語文書も検索できるのだけど(JIS の智慧のおかげ)。

最近ではサイト内検索エンジンをブログ管理システムに任せるか,Google のドメイン指定の検索窓を設けることで,自らインデックス管理自体をしないですむようになっており,独自に検索エンジンを設置する必要性は薄くなって来ている。ちなみに,Google のドメイン指定で自分のサイト内だけを検索するための検索窓は,以下のようなコードを自サイトのページに埋め込めばよい。

<form method="get" action="http://www.google.com/search">
<input type="text" name="q" size="30" maxlength="255" value="">
<input type="hidden" value="検索対象ドメイン" name="as_sitesearch">
<input type="hidden" name="hl" value="ja">
<input type="hidden" name="ie" value="UTF-8">
<input type="submit" value="Google 検索">
</form>
このサイト内なら—

私は受信したメールを MHonArc でアーカイブし,パスワードで文書セキュリティを保護することで,Web でどこからでも自分のメールを見られるようにしている。このような用途では,Google を使うわけには行かず(非公開なんだから当然),どうしても独自に検索エンジンを設置しなければならない。

Katsushi Matsuda,毛流麦花両氏による msearch は Unicode 文書からインデキシングが可能である。よって多国語文書も本来の文字列で検索が可能である。そこで私も Unicode 版 msearch Ver. 1.52 を導入してみた。これで柔軟な多国語検索とメールアーカイブ検索が両立できるというわけだ。http://yasuda.homeip.net/msearch.html から私のサイト内の検索ができるようにしてみた(メール検索は当然ながら非公開)。検索結果画面は msearch のお仕着せをそのまま使っている。まだ画面右上の namazu 検索は生きている。そのうち整理するつもりである。

msearch は,茶筌で日本語検索対象語を抽出してインデキシングを行う namazu とは異なり,おそらく n-gram で全文インデックスを抽出している。これは検索モレを防ぎかつ高速化を実現するのに有効な方法である。ただし,msearch は多国語文字を取り扱うことができるとはいえ,いわゆる語形変化に追随できるようなインデキシング解析をしているわけではなさそうである。Google なら,нести (「携える」という意味のロシア語不規則変化動詞不定形) を入力すると,несут (三人称複数現在) などの変化形をも検索できる。さすがである。

msearch は PDF, Microsoft Word, Microsoft Excel, Microsoft PowerPoint をインデキシングするためのフィルタを持たないため,そのままでは原則 HTML 文書だけを扱うことになる。私自身は .doc, .xls, .ppt ファイルをプライベートで扱うことはないので,まったく困らないのだが,PDF だけはなんとしても検索できるようにしたい。以下,PDF も取り扱うことができるように msearch 環境を調整するメモをしるしておく。環境は Mac OS X Snow Leopard (インデックス作成) 及び FreeBSD 8.1-RELEASE (公開 Web 環境) である。掲載内容は無保証である。

Unicode 版 msearch インストール

Unicode msearch のダウンロード,インストールは「サイト内全文検索エンジン ― Unicode版msearch」に毛流麦花氏による懇切丁寧な解説があるので,そちらを参照する。アーカイブを解凍し,cgi-bin/msearch にリソースを格納するだけである。Perl 5 が必要である。/~user/ などの Web ユーザディレクトリ下で msearch を運用する場合は,public_html/cgi-bin/msearch のパーミッションが 644 あるいは 755 (他ユーザの書込権限なし) になっていないと,Premature end of script headers のエラーが出て動作しないので注意。

私の場合,PDF 処理その他でサイトのドキュメント・ツリーを書き換えてしまうオペレーションが発生するため,Apache22 の公開エリアとは別に ~/var/webindex ディレクトリ (以下「ワークツリー」) を作成し,そのなかにサイト・ドキュメント・ツリーをコピーするとともに,msearch リソース・ディレクトリをも設置した。ここで検索インデックスをローカル作成(msearch では,Web ブラウザからインデックス作成操作が可能であるが,これを使わず,サーバ・ローカルの端末でコマンド操作によりインデックス作成を行うことを「ローカル作成」と呼んでいる)し,できたものを Apache22 の公開エリア /usr/local/www/apache22/cgi-bin/msearch にコピーするという運用である。

msearch のサイト用独自設定は default.cfg で行う。本稿の試行では,とりあえず set $home= の右辺を私のサイト URL に書き換えただけである。

PDF インデキシング

msearch で PDF ファイルのインデックスを作成するには,いくつか注意事項があり,少し工夫が必要である。そのままで PDF をインデックス作成対象に指定すると,インデックス・ローカル作成プログラム genindex.pl (本稿で「インデクサ」とあるのはこれのこと) は異常終了する。

PDF はテキスト変換した上でインデクサに掛けるのが基本である。UNIX X11 PDF ビュア XPDF のユーティリティ pdftotext で PDF -- テキスト変換を行った上でインデキシング実行すればよい。このときテキスト化されたファイルを元の PDF ファイルと同じ名称にしておかないと,検索結果のリンクで当該ファイルを参照できないので,テキスト変換結果で元 PDF ファイルを上書きしておく必要がある。PDF 以外でも wvWare (Microsoft Word 用),xlHtml (Microsoft Excel 用),pptHtml (Microsoft PowerPoint 用) の各 UNIX ソフトウェアを利用し HTML ないしテキスト形式に変換することで,msearch インデキシングが可能である。

第二の注意点として,HTML / XML 以外のファイルに対して msearch は BOM で Unicode エンコードを判断していることがある。BOM がないと,Web 検索結果画面上の当該ヒットエントリの文字が化けてしまうのである。普通,UTF-8 でテキストファイルを作成するとき,BOM を付けたりしないので,インデクサに掛ける前に UTF-8 BOM (十六進コード "EFBBBF") をワークツリーのテキスト変換後ファイルの先頭に書き込んでおく。これは echo, cat コマンドなどで簡単にできるのだけれども,私は,PDF に混在した不要な制御コード文字を取り除く目的と合わせて,これを行う簡単なプログラム chkucntlchr を書いた。PDF 以外のテキストファイルも同様の処置が必要である。

以上の処理を自動で行うシェルスクリプトのコード例を以下に示す。これを含んで,msearch インデックス作成の全体シェルスクリプト例を最後に掲げてある。

# PDF format conversion
$WRK=ワークツリー
$UCK=chkucntlchr # 制御コード削除・BOM 付加ツール
$STP=タイムスタンプファイル (前回実行時の日付属性をもつ空ファイル)
echo "*  Convert PDF to TEXT by pdftotext (XPDF)."
cd $WRK
for i in `find -L . -newer $STP -name "*.pdf"`
do
    pdftotext -enc UTF-8 -nopgbrk $i $i.txt
    if [ $? -eq 0 ]; then
        echo "**  pdftotext $i OK."
        $UCK < $i.txt > $i
        if [ $? -eq 2 ]; then
            echo "**  $i is empty. Ignore."
            rm -f $i
        fi
    else
        echo "**  pdftotext $i NG. Ignore."
        rm -f $i
    fi
    rm -f $i.txt
done

また,chkucntlchr ツールの Perl コードは以下の通りである。

#!/usr/bin/perl -w
# -*- coding: utf-8; mode: cperl; -*-
# chkucntlchr
# 2011(c) isao yasuda.
# - delete words including control characters (U+0001--U+0020, U+007F--U+00A0)
# - Add UTF-8 BOM (x'efbbbf') for msearch indexer
# - Return code 0: normal; 1: suppressed; 2: imput empty;
use strict;
use utf8;
binmode STDOUT, ":utf8";
my $flg = 0;
my $lc = 0;
my $utf8_bom = "\xEF\xBB\xBF";      # BOM for UTF-8
utf8::decode($utf8_bom);
print $utf8_bom;
while (<STDIN>) {
    chomp($_); $lc++;
    utf8::decode($_);
    my @line = split(/\s/, $_);
    foreach my $wd (@line) {
        if ($wd =~ /[\x{0001}-\x{0020}\x{007F}-\x{00A0}]/) {
            $flg = 1;
        } else {
            print "$wd ";
        }
    }
    print "\n";
}
if (! $lc) {
    print STDERR "*** $0: input empty.\n";
    exit 2;
}
if ($flg) {
    print STDERR "*** $0: suppressed control characters.\n";
} else {
    print STDERR "*** $0: no problem.\n";
}
exit $flg;


segmentation fault 対策

msearch インデクサに PDF を食わせるに際して,もっとも悩んだのはテキスト化した PDF でも,インデクサが segmentation fault エラーで異常終了する場合があることであった。インデクサからコールされる indexing.pl に罠を仕掛けて調査したところ,問題が二つ判明した。

まず第一には,サイトのインデックス対象ファイル数が多いと,UNIX の ulimit のファイルオープン数の制限に引っ掛かり,異常終了してしまう。ulimit -a で制限値を確認し,インデックス対象ファイル数よりも open files の設定値が小さければ,ulimit -n 数値 で値をファイル数よりも大きな値に設定する。

第二には,msearch インデクサは正規表現 s 演算子によって HTML タグの除去処理を行っているが,これをすべてのファイルに適用しており,テキスト変換された PDF ファイル中の文字列如何によっては誤動作してしまう。私のサイトの PDF は,LaTeX 多言語文書を dvipdfmx で処理した生成物が多い。LaTeX フォント・パッケージの enc ファイル(エンコーディング定義ファイル)によってはヘンな文字の羅列になることがあり,これでタグ判定の正規表現がぶっとんでしまったらしい。indexing.pl 791 行目を,HTML / XML でないときは実行しないように,以下の改変を行うと,アボートしないようになった。

#    $contents =~ s/<(?:[^"'>]|"[^"]*"|'[^']*')*>/ /g;  # オリジナル
    $contents =~ s/<(?:[^"'>]|"[^"]*"|'[^']*')*>/ /g if ($html_xml); # 対策

XPDF 多国語化

XPDF pdftotext の多国語対応について簡単にしるしておく。FreeBSD Ports,Mac OS X MacPorts では XPDF Japanese port が用意されており,これをインストールすれば日本語 PDF については扱うことが出来るようになる。しかし,多国語 PDF はダメ。

XPDF のサイトでは中国語,ギリシア語などいくつかの言語設定追加リソース・パッケージが公開されている。これらを用いて多国語対応設定ファイルを作成する。以下のシェルスクリプトを実行すれば,パッケージをダウンロード・展開した上で,カレントディレクトリに xpdfrc を生成する。これを $HOME/.xpdfrc として格納する。次に,パッケージのリソース xpdf-japanese 等を XPDF 管理ディレクトリ (FreeBSD なら /usr/local/share/xpdf) にコピーする。これで,pdftotext により,日本語のほか簡体中文,繁體中文,韓国語,ロシア語,ギリシア語,アラビア語,ヘブライ語などの Unicode テキストが出力できるようになる。ただし,この実行で生成された xpdfrc には PDF 表示の際に必要となるフォント定義がないので,あくまで pdftotext テキスト変換用途と理解いただきたい。表示も含めた設定は XPDF ドキュメントを参照して displayNamedCIDFontTT 定義に好みの TrueType, OpenType フォントを指定するなりして調整してほしい(私は UNIX 環境での PDF 表示は Adobe Reader を使っているのでこのへんは放置している)。

#!/bin/sh
# Download XPDF language packs
WGET="wget -nH -nd "
XPDFSITE="ftp://ftp.foolabs.com/pub/xpdf"
# XPDFETC は xpdfrc があるディレクトリに変更する
XPDFETC="/usr/local/etc"
$WGET $XPDFSITE/xpdf-arabic.tar.gz
$WGET $XPDFSITE/xpdf-chinese-simplified.tar.gz
$WGET $XPDFSITE/xpdf-chinese-traditional.tar.gz
$WGET $XPDFSITE/xpdf-cyrillic.tar.gz
$WGET $XPDFSITE/xpdf-greek.tar.gz
$WGET $XPDFSITE/xpdf-hebrew.tar.gz
$WGET $XPDFSITE/xpdf-japanese.tar.gz
$WGET $XPDFSITE/xpdf-korean.tar.gz
$WGET $XPDFSITE/xpdf-latin2.tar.gz
$WGET $XPDFSITE/xpdf-thai.tar.gz
$WGET $XPDFSITE/xpdf-turkish.tar.gz
# Expand archives
for i in *.tar.gz; do tar zxvf $i; done
# make xpdfrc
cp $XPDFETC/xpdfrc .
for i in `find . -name "add-to-xpdfrc"`
do cat $i >> xpdfrc; done

インデキシング用シェルスクリプト

最後に私が自サイト用に作成したインデキシング用シェルスクリプトを掲載しておく。Mac OS X Snow Leopard 環境である。HTML ソース Subversion 管理エリアからワークツリーに更新ファイルをコピーし,ワークツリーでインデキシングしたのち,Mac 上の Apache22 cgi-bin 試験環境にインデックスファイル default.idx をコピーする。これでできた Mac 上の default.idx をそのまま FreeBSD サーバの msearch 環境に転送して公開するという運用形態である。

私は自サイトの HTML 等公開コンテンツを Subversion でバージョン管理しており,ソースを commit すると Subversion の commit スクリプトが動作して,自動的に更新コンテンツを Apache22 のドキュメント・ツリーにコピーするようにしている。このスクリプトを変更し,commit のタイミングで msearch インデクス作成スクリプトを呼び出して,検索インデクスを自動的に更新することもできる。crontab に登録して定時自動実行するのもよいと思う。

上記の PDF テキスト変換以外にも,HTML の iso-2022-jp to UTF-8 変換なども実行内容に含まれている。シェル内の各パス設定,サイト設定は私の環境そのままなので,もしこれを活用する方がいらっしゃるのなら,自分の環境に応じて書き換えないといけない。もちろん,中味をよく確認し,私のいい加減なコードにヘンなところがあれば手直しいただいたほうがよい。

#!/bin/sh
# -*- coding: utf-8; -*-
# msearch index generator for ISOLDE
# - coded by isao yasuda, 1 Apr. 2011
#
# DESCRIPTION
# -----------
# 1.前回タイムスタンンプより新しいページをSRCからWRKに格納する。
# 2.JISコードのページをUTF-8に変換して格納する。(nkf, sed)
# 3.PDFをテキスト変換してWRKに格納する。
#     rc OK: .pdf の内容はテキストファイル 
#     rc NG: .pdf, .pdf.txt を削除する
# 5.テキスト変換 OK のものの制御コードを削除する。(chkucntlchr)
# 4.WRKでインデックスを生成する。(genindex.pl
# 5.インデックスをWRKからPUBに格納する。
#
# CAUTION
# -------
# 1.初期作成時はファイル数が多いのでWRKにsite treeをコピーしておく。
#
 
# SRC: ページソースエリア
# WRK: ワークエリア
# PUB: 公開エリア (ここでは触らない)
WWW=/usr/local/www/apache22
SRC=/home/isao/src/noxinsomniae
PUB=$WWW/data
CGI=$WWW/cgi-bin/msearch
WRK=/home/isao/var/webindex/website
MSE=/home/isao/var/webindex/msearch
STP=/home/isao/var/webindex/stamp
TMP=/home/isao/var/webindex/tmp
UCK=$MSE/chkucntlchr
NKF=/usr/local/bin/nkf
PDFTOTEXT=/usr/local/bin/pdftotext
 
echo "********************************************************"
echo "*  msearch Index Generation Start `date '+%Y/%m/%d %H:%M:%S.'`  *"
echo "********************************************************"
# Copy SRC to WRK
echo "*  New Files Archiving."
cd $SRC
find -L . -newer $STP -type f | grep -v '.svn' |\
xargs tar cf - | ( cd $WRK; tar xvf - )
cd $WRK
 
# Convert iso-2022-jp to utf-8
echo "*  Convert ISO-2022-JP pages to UTF-8 pages."
cd $SRC
for i in `find -L . -newer $STP -name "*.html"`
do
    $NKF -w $i |\
    sed -e 's|charset=[Ii][Ss][Oo]-2022-[Jj][Pp]|charset=UTF-8|g' > $WRK/$i
done
 
# PDF format conversion
echo "*  Convert PDF to TEXT by pdftotext (XPDF)."
cd $WRK
for i in `find -L . -newer $STP -name "*.pdf"`
do
    $PDFTOTEXT -enc UTF-8 -nopgbrk $SRC/$i $i.txt
    if [ $? -eq 0 ]; then
        echo "**  $PDFTOTEXT $i OK."
        $UCK < $i.txt > $i
        if [ $? -eq 2 ]; then
            echo "**  $i is empty. Ignore."
            rm -f $i
        fi
    else
        echo "**  $PDFTOTEXT $i NG. Ignore."
        rm -f $i
    fi
    rm -f $i.txt
done
 
# add BOM to text files
echo "*  Add BOM to TEXT files."
cd $WRK
for i in `find -L . -newer $STP -name "*.txt" -or -name "*.tex"`
do
    $UCK < $i > $i.tmp
    if [ $? -eq 2 ]; then
        echo "**  $i is empty. Ignore."
        rm -f $i
    fi
    mv $i.tmp $i
done
 
# rm svn control
cd $WRK
find . -name ".svn" -or -name ".#*" | xargs rm -fr
 
# Indexing
echo "*  Execute Indexing by genindex.pl. PARAM:"
echo "*   1 インデックス名前:        default"
echo "*   2 インデックス対象DIR:     $WRK"
echo "*   3 インデックス対象URL:     http://yasuda.homeip.net/"
echo "*   4 インデックス対象拡張子:   .html,.txt,.pdf,.tex"
echo "*   5 非インデックス対象DIR:   admin,common,css,archives"
echo "*   6 非インデックス対象拡張子: (指定無し)"
echo "*   7 非インデックス対象KWD:   (指定無し)"
echo "*   8 ランキング方法:         最終更新日時降順(1)"
echo "*   9 alt属性の文字:         指定しない(0)"
cd $MSE
./genindex.pl <<EOM
default
/home/isao/var/webindex/website
http://yasuda.homeip.net/
.html,.txt,.pdf,.tex
admin,common,css,archives
 
 
1
0
EOM
 
if [ $? -eq 0 ]; then
    echo "*  Index Generation Succeeded."
    ls -l $MSE/default.idx
    echo "*  Now Copy default.idx to $CGI."
    cp -p $MSE/default.idx $CGI
    # STAMP modify
    SDT=`ls -l $STP`
    echo "*  Previous Update: $SDT"
    touch $STP
    SDT=`ls -l $STP`
    echo "*  Now Updated:     $SDT"
else
    echo "*  Index Generation Something bad."
    ls -l $MSE/default.idx
fi
 
echo "*  Procedure Ended. `date '+%Y/%m/%d %H:%M:%S.'`"
# end of script
        

misima 漢詩分析・詩語検索機能について,簡易版を追加した。旧版は SQL を直接入力する形態だった。これは DB に蓄積しているすべての項目について,柔軟な検索ができるのだけれども,SQL 操作ということもあり,限定公開とした。簡易版はごく限られた条件指定しかできない。それでもこれくらいありゃいいか,ということでこちらは一般の漢詩作成者の方々のお役に立てればと思い,一般公開とする。旧版も expert 版ということで残してある。方式的には expert 版も簡易版も同じで,簡易版は SQL 組立ての JavaScript を追加しただけである。

開発・本番環境は FreeBSD 8.0-RELEASE, Mac OS X Snow Leopard, Tiger, J2SDK-1.5, J2SDK-1.6, Tomcat-5.5, DWR-3-rc1, SQLite-3-5.6, SQLite-JDBC-3.7.2。ブラウザは Safari-5.0.3, Safari-4.1.3, Google Chrome-9.0 にて確認している。Windows ではまったく試験していないのでちょっと不安。

ここで簡易版の使い方を簡単にしるしておく。misima 漢詩分析・詩語検索機能のコンセプト,実現方式については「misimaKansiServlet 漢詩 Chinese Verse 平仄音韻分析」,「DWR with Java: misima 漢詩詩語検索」を参照。

misima 漢詩平仄音韻分析(Servlet版)」ページの「詩語検索」欄にある をクリックすると,別ウィンドウで検索画面が開く。検索はここで実行する。検索条件は図 1. に示す「平仄パターン」,「詩語」,「韻字」,「韻目」 を指定できる。
 

20110220-condition.jpg

図 1. 検索条件

「平仄パターン」(A) は求める詩語の平仄の並びである。プルダウンで平仄を設定する。「」は「平」,「」は「仄」を意味する。初期表示では「○-○-○」,すなわち「平-平-平」の 3 文字詩語の条件になっている。もし 2 文字の詩語を求めたいなら,3 番目のプルダウンで「-」を選択しなければならない。

○,●」いずれの場合も,検索結果に「」記号のものが含まれる。これは両韻を示す記号である。例えば,「思」という文字は意味によって「上平聲四支」と「仄去聲四寘」と平・仄どちらでも使用される可能性をもつ。もちろん詩語においてはどちらかに決まるのであるが,misima 平仄辞書で両韻のものは平・仄いずれの条件でもヒットするようになっている。だから当該詩語でその両韻文字がどちらの平仄で用いられているのか,辞書に当たって意味を確認する必要がある。

「詩語」(B) は指定した一文字を含む条件である。一文字しか指定できない。

「韻字」(C) 指定は詩語の末尾文字の条件である。押韻文字が決まっているときに用いる。

「韻目」(D) は「一東」などの韻目で検索するための指定である。押韻文字が決まっているとき,その韻目を含む詩語を閲覧したい場合などに用いる。韻目指定は面倒なので,ポップアップから選択するようになっている。「韻目」の入力エリアにカーソルが位置づけられると,入力メニューがポップアップされる(図 2.)。その一覧から検索したい韻目をクリックすると,入力エリアに韻目条件が設定され,メニューが消えるようになっている。
 

20110220-inmoku.jpg

図 2. 韻目ポップアップメニュー

条件 (A) は必須である。かつ,(B),(C),(D) から少なくともひとつは条件指定をしなければならない。そして,検索は (A) and ([(B)] or [(C)] or [(D)]) ([ ] 内はひとつ以上必要) という条件で実行される。これは長大な検索結果を防ぐためである。簡易検索はこれ以外の条件指定はできない。

簡易版検索結果例を図 3. に示す。これは「●-○-○」の 3 文字でかつ韻字が「秋」である詩語の検索条件である。
 

20110220-simple-search.jpg

図 3. 簡易版検索結果例

詩語韻目は,「ニモニック:番号:韻目」の様式で出力される。ニモニックの意味は次の通りである。hk: 上平聲; hs: 下平聲; sj: 仄上聲; sk: 仄去聲; sn: 仄入聲。「hk:01:東」は「上平聲一東」を意味する。; (セミコロン) は当該文字が複数の韻目を有することを示している。A;B;C は A, B, C 三つの韻目を持つ文字であることを示す。対応する文字の区切りは - (ハイフン) で判断できる。

簡易版では,(A) and (B) and ((C) or (D)) などのような検索条件指定は不可である。こういう柔軟な条件設定は expert 検索でのみ可能である。expert 版の条件指定は,「実行 SQL」のテキストエリアに where 句の内容を直接コーディングする。検索キーはページにある通り,詩語: sg; 詩語平仄: hs1; 詩語韻目: in1; 押韻字: oj; 押韻字平仄 hs2; 押韻字韻: in2; 詩語字数: ss; 出典: ta が指定できる。expert 版の検索結果を図 4. に示す。
 

20110220-expert-search.jpg

図 4. expert 版検索結果例

 

最後に参考文献を上げておく。
 

Ajax の高度な活用集。詩語検索機能で利用した DWR についても,サンプル付で少し解説されている。しかし,addRows() 関数の仕様など,DB 検索結果表示に適したテクニックの解説までは望むべくもなく,少し自分の課題に応じた詳細事項は,やはり DWR サイトのドキュメントに当たらないと解決不可能である。
 

オライリーのクックブック・シリーズは困ったときに必ず役に立つ。本書で述べられている便利なライブラリもオライリーのサイトからダウンロードできる。
 

これは JavaScript のリファレンス本としてはいちばん優れていると思う。なんといっても,非同期通信オブジェクト,XML DOM オブジェクトについて整理されている。オライリーの「クイックリファレンス」よりも個人的には使いやすい。

漢詩作成支援の一環で今回,詩語検索を追加した。SQLite3 で構築した詩語データベースを Java サーブレットから JDBC でアクセスする。高速化のために Ajax + Java Servlet を基本とした。近年,Ajax も便利なライブラリが出現し,Web 2.0 の世界をより簡単に構築できるようになった。今回はそのひとつ DWR (Dynamic Web Remoting) を使うことにした。

DWR の特徴は大きく二つある。第一に,JavaScript 動作の微妙に異なる数あるブラウザへの対応を吸収してくれること。第二に JavaScript からサーバの Java クラスの呼び出しを可能としたこと。とくに後者は,非同期通信インタフェースとサーバ (Servlet) の存在をプログラマから隠蔽することにより Java Servlet の約束事に精通していない Java プログラマにも (JavaScript が書けないとならないんだけど) Web サーバ・プログラミングを近しいものとする。

以下,misima 漢詩詩語検索を作成したメモを残しておく。

詩語データベースの構築

太刀掛重男著『詩語完備 だれにもできる漢詩の作り方』は,詩語に基づいて漢詩を作成する方法を述べており,合わせて詩語集を掲載している。また,詩語の韻書としては『詩韻含英異同辨』という決定版が存在する。できればこうした詩語集をデータベースに蓄積するのがよいのだが,著作権問題があり公開 DB に入れるのは憚られる(自分だけの個人辞書として構築するならよいのだろうが)。しかも,データ入力に気の遠くなるような時間を要する。私のようなサラリーマンにはとうてい不可能である。

そこで今回の詩語 DB は,どちらかというとコーパス・ビュア風のアイデアに基づくことにした。つまり,インターネットで大量に公開されている漢詩テクストを掻き集め,その詩行を 2 文字 + 3 文字 (五言詩) や 2 文字 + 2 文字 + 3 文字 (七言詩) に分解し,それぞれを「詩語」と見なし,これらに平仄・音韻分析処理を加えて,その結果をリレーショナル・データベースに仕立て上げるわけである。平仄・音韻分析用のデータベースは,「misima 漢詩平仄音韻分析」で構築済みだった。

私はロシア語作文をする際,語結合が妥当かどうか Google で検索してみる。ロシア語は「〜において」というとき,в, на のいずれの前置詞を使うのか悩ましいことが多い。「お茶会で」は на чайной церемонии でよいのか? Google で検索するとこのフレーズを含むきちんとしたページがたくさんヒットするので,不自然ではないとハッキリする。コーパス・ビュア風というのはこういう使い方を指している。漢詩詩語についても過去の偉大な詩人の作品で同じような確認ができるはずである。もちろん,詩語の意味,題詠用の分類(秋思,離別などの詩語と結びついたテーマ論)がないと片手落ちなんであるが,求める平仄,文字,字韻とそれに合致する詩語にどのようなものがあるのかが調査でき,詩語検索機能としてはそれなりのものが得られるはずだと考えた。「平-平-仄のパターンでこの文字を含む詩語」,「脚韻がこの韻目の詩語」,程度でも検索できれば便利ではないか?

『唐詩選』などの漢詩 500 首近くをネットから wget で戴いて来て,Perl HTML::TreeBuilder モジュールでもって詩テクストを解析,抽出して約 4,000 語の詩語テクストを得た。ついでに出典(詩人,題名)情報などの属性をぶら下げた。これに詩語の平仄データ,韻目などを追加して SQLite3 のデータベースが成った。

Java 詩語検索クラスの作成

DWR は様々な Java クラスの呼び出しをサポートしている。今回は JavaBeans で行くことにした。JavaBeans はデータを保持するオブジェクトで,データ項目の出し入れに set〜, get〜 なるメソッドを一式用意しておくというモジュール構造であり,データ部品化の基本になっている。サーバで DB を検索し,その結果を Bean に入れ,JavaScript から DWR インタフェースで取り出す。基本設計はそのようなものである。詩語のための JavaBeans SigoBean.java を以下に示す。本来なら DB に蓄積している項目はいくつもあるが,ここでは詩語,平仄,韻目のみに限定してある。

// -*- coding: utf-8; mode: java; -*-
/**
 *  misimaKansi SigoBean 漢詩詩語
 *  Copyright(c) 2011, isao yasuda, All Rights Reserved.
 */
public class SigoBean
{
    /**
     *  SQLite3 database
     *  詩語 sg, 詩語平仄 hs1, 詩語韻 in1
     */
    private String sg  = null; // 詩語
    private String hs1 = null; // 平仄
    private String in1 = null; // 韻目
 
    /** Constructor */
    public SigoBean(String sg,  // 詩語
                    String hs1, // 平仄
                    String in1, // 韻目
        )
    {
        this.sg  = sg;
        this.hs1 = hs1;
        this.in1 = in1;
    }
 
    /** Getter メソッド */
    public String getSigo()    { return sg;  }
    public String getHyosoku() { return hs1; }
    public String getSigoIn()  { return in1; }
 
    /** Setter メソッド */
    public void setSigo(String sg)     { this.sg  = sg;  }
    public void setHyosoku(String hs1) { this.hs1 = hs1; }
    public void setSigoIn(String in1)  { this.in1 = in1; }
 
    /** テキスト取得用メソッド */
    public String getSigoBean(String sep) {
        return sg + sep + hs1 + sep + in1;
    }
}

さて,実際に詩語データベースを検索し,上記詩語 Bean の配列テーブルとして結果をストアする Java クラスが当然必要である。SigoTable.java コードを以下に示す。ここで,SQLite3 DB アクセスは JDBC インタフェースを使っている。SQLite 用 JDBC ドライバは SQLiteJDBC – Xerial – Trac から sqlite-jdbc-3.7.2.jar (2010.8.27 版) を落として,クラスパスに通しておくとともに,Servlet コンテナ Tomcat の $CATALINA_HOME/common/lib/ にもコピーしておく。

// -*- coding: utf-8; mode: java; -*-
import java.util.ArrayList;
import java.util.List;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
/**
 *  misimaKansi SigoTable 漢詩詩語検索
 *  Copyright(c) 2011, isao yasuda, All Rights Reserved.
 */
public class SigoTable
{
    /** 詩語 DB path */
    private static final String dbpath = "/usr/local/etc/misima/SIGO.db";
    /** SQL */
    private String sqlcond = null;
    /** 詩語テーブル行データ */
    private ArrayList<SigoBean> dbRowList = null;
    /** データ行数 */
    private int gyosu;
   
    /**
     * 詩語 DB を検索し,詩語テーブルを SigoBean 配列として返却する
     * @return 詩語テーブル
     */
    public SigoBean[] getSigoTable(String cond) throws Exception {
        sqlcond = "select * from SIGOTBL where " + cond + ";";
        dbRowList = new ArrayList<SigoBean>();
        /** DB検索 */
        Class.forName("org.sqlite.JDBC");
        Connection conn = null;
        try {
            // create a database connection
            conn = DriverManager.getConnection("jdbc:sqlite:" + dbpath);
            Statement sttmnt = conn.createStatement();
            sttmnt.setQueryTimeout(30); // set timeout to 30 sec.
            ResultSet rset = sttmnt.executeQuery(sqlcond);
            while(rset.next()) {
                // read the result set
                dbRowList.add(new SigoBean(rset.getString("sg"),
                                           rset.getString("hs1"),
                                           rset.getString("in1")));
            }
            rset.close();
        }
        catch(Exception e) {
            System.err.println(e.getMessage());
        }
        finally {
            try {
                if(conn != null)
                    conn.close();
            }
            catch(Exception e) {
                // connection close failed.
                System.err.println(e);
            }
        }
        gyosu = dbRowList.size();
        SigoBean[] dbrows = new SigoBean[gyosu];
        return dbRowList.toArray(dbrows);
    }
   
    /**
     * 詩語 DB 行数を返却する (for debug)
     * @return 行数
     */
    public int size() {
        return gyosu;
    }
}

DWR 環境の作成

DWR のパッケージは DWR ダウンロードページ から dwr.war (Version 3. rc-1) を落として使った。DWR のサーバ側環境設定は大きく 3 点。以下簡単に示す。

  1. ダウンロードした dwr.war を詩語検索 Web アプリの WEB-INF/lib ディレクトリ直下に格納する。
  2. dwr.xml を,以下の内容で WEB-INF/ 下に格納する。これは JavaScript の記述とサーバ側 Java クラスを結びつけるための記述である。create タグで上記 SigoTable クラスが呼び出されるよう,convert タグによってそのデータ構造へのアクセスは JavaBeans SigoBean を介して行われるよう指定している。詳細は Configuring dwr.xml を参照のこと。
  3. <!DOCTYPE dwr PUBLIC
        "-//GetAhead Limited//DTD Direct Web Remoting 3.0//EN"
        "http://directwebremoting.org/schema/dwr30.dtd">
    <!-- -*- coding: UTF-8; -*- 
        misima 漢詩詩語検索用 dwr.xml
        Copyright (c) 2011, isao yasuda, All Rigths Reserved.
        $Id: dwr.xml,v 1.1 2011/02/17 13:55:58 isao Exp $
    -->
    <dwr>
      <allow>
        <create creator="new" javascript="SigoTable">
          <param name="class" value="SigoTable"/>
        </create>
        <convert converter="bean" match="SigoBean"/>
      </allow>
    </dwr>
    

  4. 詩語検索 Servlet 用のデプロイメント・ディスクリプタ web.xmlWEB-INF/ 下に準備する。今回,旧字・旧仮名遣い変換 misimaservlet のサブシステムとして作成したので,すでにある web.xml に DWR 関連用の servlet タグ及び servlet-mapping タグを追加した。DWR 部分は以下とまったく同じでよいと思う。詳細は DWR WEB-INF Reference を参照のこと。
  5. <!DOCTYPE web-app
        PUBLIC  "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN"
        "http://java.sun.com/j2ee/dtds/web-app_2_2.dtd">
    <!-- -*- coding: UTF-8; -*- 
        misimaServlet web.xml デプロイメントデスクリプタ
        Copyright (c) 2007, isao yasuda, All Rigths Reserved.
    -->
    <web-app>
      <!-- misimaservlet サーブレット -->
      <servlet>
        <servlet-name>misimaServlet</servlet-name>
        <servlet-class>misimaServlet</servlet-class>
    ... (略) ...
      </servlet>
     
      <!-- DWR サーブレット -->
      <servlet>
        <servlet-name>dwr-invoker</servlet-name>
        <servlet-class>org.directwebremoting.servlet.DwrServlet</servlet-class>
        <init-param>
          <param-name>debug</param-name>
          <param-value>true</param-value>
        </init-param>
      </servlet>
     
      <!-- misimaservlet サーブレットのマッピング -->
      <servlet-mapping>
        <servlet-name>misimaServlet</servlet-name>
        <url-pattern>/convert</url-pattern>
      </servlet-mapping>
      
      <!-- DWR サーブレットのマッピング -->
      <servlet-mapping>
        <servlet-name>dwr-invoker</servlet-name>
        <url-pattern>/dwr/*</url-pattern>
      </servlet-mapping>
    </web-app>
    

クライアント・ページ JavaScript の作成

最後に DWR のキモであるクライアント側 JavaScript を作成する。サービス用 HTML から呼び出す JavaScript として DWR ライブラリを次のように指定しておく。

<script type="text/javascript" src="dwr/engine.js"></script>
<script type="text/javascript" src="dwr/util.js"></script>
<script type="text/javascript" src="dwr/interface/SigoTable.js"></script>

はじめの 2 行はおまじないのようなものである。dwr/interface/SigoTable.js は,dwr.xml における javascript="SigoTable" という指定を受けて DWR が自動生成するスクリプトであり,ユーザアプリに応じて名前を変えて指定しなければならない。

さて,DB を検索し,その結果が挿入される HTML は以下の通りである。input タグに SQL 条件を入力し,「検索」ボタンを押下すると,retrieveSigo() 関数(後述)を起動するコードになっている。

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
          "http://www.w3.org/TR/html4/loose.dtd">
<!-- Copyright(c) 2011, isao yasuda, All Rights Reserved. -->
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>misima 漢詩詩語検索</title>
  </head>
  <body>
    <dl compact>
      <dt>実行 SQL</dt>
      <dd>select * from SIGOTBL where <br> 
        <input type="text" size="70" id="condition">;
        <input type="button" value="検索" onClick="retrieveSigo()">
      </dd>
    </dl>
    <!-- 詩語検索結果挿入するテーブル -->
    <table border="0">
      <thead>
        <tr style="background-color: #CCCCCC;">
          <th width="80px">詩語</th>
          <th width="120px">詩語平仄</th>
          <th width="400px">詩語韻</th>
        </tr>
      </thead>
      <tbody id="sigotable"></tbody>
    </table>
    <script type="text/javascript" src="dwr/engine.js"></script>
    <script type="text/javascript" src="dwr/util.js"></script>
    <script type="text/javascript" src="dwr/interface/SigoTable.js"></script>
    <script type="text/javascript" src="./sigo.js"></script>
  </body>
</html>

検索ボタンに紐づけられた検索実行制御処理 retrieveSigo() 関数は以下の通り。上記 HTML の sigo.js にこれを定義しておく。ここでサーバとの非同期通信を担っているのは SigoTable.getSigoTable(sql.value, ...); の部分である。サーバ側にある SigoTable クラスの getSigoTable() メソッドをコールしている。これは Java クラスを操作するのと同様の様式であり,DWR の特徴となっている。このコーリング書式は クラス名.メソッド名(メソッド引数, コールバック関数); である。サーバで実行されたメソッドの返値を引数として コールバック関数 が実行される。このなかでブラウザ表示に必要な処理を記述する。

// -*- coding: utf-8; mode: javascript; -*- 
// misima 漢詩詩語検索
function retrieveSigo() {
    var sql = document.getElementById("condition").value;
    var cellFuncs = [
        function(data) { return data.sigo; },    // 詩語
        function(data) { return data.hyosoku; }, // 平仄
        function(data) { return data.sigoIn; }   // 韻目
    ];
    // insert table contents from DB    
    SigoTable.getSigoTable(
        sql,
        function(data){ // callback
            dwr.util.removeAllRows("sigotable");
            dwr.util.addRows("sigotable", data, cellFuncs, {
                // 偶数行の背景色を変更
                rowCreator:function(options) {
                    var row = document.createElement("tr");
                    if (options.rowIndex % 2 != 0) {
                        row.style.background = "#CCCCCC";
                    }
                    return row;
                },
                escapeHtml:false 
            });
        });
}

retrieveSigo() 関数の引数のなかに関数が記述されておりそこでさらに関数が入れ子になっている。わかりにくいのでもう少し説明しておく。ここでサーバからの返値は function(data) 関数 (コールバック関数) に渡され,こちらは DWR util.js のユーティリティ addRows() 関数で HTML のテーブル (上記 HTML の <tbody id="sigotable"> の位置) にデータを展開している。addRows() 関数の書式は以下の通りである。

dwr.util.addRows(id, array, cellfuncs, [options]);
- id: テーブル要素の id。テーブル要素は <tbody id="id"> とするのがよい。
- array: 表にしたいデータ配列
- cellfuncs: 行データの各セルに応じた処理を行う関数の配列
- options: オプション (rowCreator, cellCreator, escapeHtml から複数指定可)

retrieveSigo() ではサーバからの出力 datacellFuncs という名の関数配列で項目を抽出しつつ id="sigotable" のテーブル要素に編集している。この際,rowCreator オブジェクト・オプションを指定し,これに偶数行ごとに背景色を変える関数(= その返値オブジェクト)を対応づけている。また,escapeHtml:false オプションを指定して HTML タグのエスケープをしないようにしている。addRows() 関数は実行のたびに行を追加するだけなので,removeAllRows() 関数で予め行を削除する前処理を行っている。

DWR の JavaScript の書き方,関数仕様詳細は DWR サイト・ドキュメント を参照。悩んだのは cellFuncs 関数配列中の data.sigo 等のオブジェクト指定であった。このうちの sigo の部分は JavaBeans の get〜 メソッドの 〜 を指定しなくちゃならないことに気づくのにえらく時間を要してしまった。それでも MVC デザイン・パターンに従って,しこしこ JSP をコーディングしていたのに比べると,遥かにわかりやすいと思う。DWR なら MVC のうちの C (Controller つまり Servlet) をほぼ意識せずに Web アプリを書くことができるからである。

以上でリソースは整った。Java コードをコンパイルした上で,リソース一式を Tomcat 環境にデプロイしておく。

実行イメージ

misima 漢詩平仄音韻分析」ページに「詩語検索」のボタンを追加した。これをクリックすると,詩語検索のウィンドウがオープンして,詩語の検索ができる。詩語と平仄パターン,韻目が表示される。以下に検索イメージ図を掲げておく。これは平仄パターンが「○-●」(平-仄)もしくは「○-◎」(平-平仄両韻)の 2 字詩語で,かつ「秋」という文字を含む詩語を検索した結果である。ただし,今回作成した版は,直接ユーザが SQL を入力するというイビツにして危険なものであるため,公開は友人限定としている。(2.20 付記:その後,詩語簡易検索機能を一般公開した。その詳細は記事「misimaKansiServlet 漢詩平仄音韻分析・詩語簡易検索」を参照ください。)
 

20110220-expert-search.jpg

検索イメージ

misimakansi bug fixed.

|

misimaKansiServlet 漢詩平仄分析に要求を出す JavaScript におそまつなバグがあった。今日試しに Windows で実行してみたら,入力チェックで Windows の改行コード (CR: X'0d') がはじかれてしまう。私は普段,Mac OS X か FreeBSD しか使わないので,Windows で試験していなかったのである。失礼しました。訂正しました。
 

* * *

上の息子は最近,バイト以外はテニスと飲み会で出歩いてばかりいる。昨夜はバイト先の仲間との新年会。今日も大学のプレゼンなんとかのメンバーとの新年会で,午前様であった。

しかしながら,大学に入っても卒業した高校のテニス部の練習に顔を出し後輩を指導したりしている。そんな姿をみると,人間付合いにおいてマメであって,私なんかより遥かによいところがある。大学のクラブが地域活動の一環で,新座キャンパス近くの中学校に行って,テニス教室を開いたりしている。物真似が好きな息子はそこでアントニオ猪木の真似をして,女生徒にモテモテだったらしい。誰に似たんだか。

この歳になって,ホント,子供は勉強なんて出来なくてもよいと思うようになった。

友人の皆様,あけましておめでとうございます。

さて,この正月はまったくどこにも出歩かず,家でずっとプログラム作成,芭蕉研究をしていた。そして,最近,漢詩に興味があり自分でも書いてみたいと思い,漢詩の本に首っ引きであった。俳句・短歌と大きく異なり,漢詩はご存知のとおり,平仄,音韻規則が厳しくてちょっとやそっとじゃ立ち入ることすらできない。俳句なら「春の夜や兄が屁をひり咽せるまで」みたいなのは小学生でも作ってしまう。もちろん俳句・短歌もよい作品を詠むのは生半可のことではないのだけれども,漢詩はまずもって規則に準拠する壁の前に,へたくそな詩すら形をなすこと自体に苦労する。「規則」があるなら計算機の出番。ということで形式分析プログラムを自分のために作ってみた。

misima を作成した際に漢字データベースを作ったこともあり,それに基づくこのサーバも misima シリーズとすることにした。入力した漢字が DB になかったとしてもご愛嬌ということで。この漢字 DB は 6,700 文字程度を蓄積している。覚えたての SQLite3 を使った。漢詩規則は何冊かの本を研究してロジックを考えた。3 年前に作成した misimaServlet, misimaserver を土台に,サーバ化するのは簡単であった。Java Servlet + Ajax + Perl Daemon という方式にした。Javascript が送信した電文を Java Servlet が受け,Perl サーバとソケット接続する。漢詩の分析ロジックは,すべて Perl サーバでこれを実行する。Perl サーバは 3 プロセス分プレフォークして処理依頼を待ち構えていている。ちょっと渡り歩きが多いのだが,Ajax + Java Servlet はページ書き換えが高速で,CGI よりは体感速度は良好のはずである。ただし,本プログラムで使用した Ajax の XMLHttpRequest 関数はクロスサイト・スクリプティング対策実装のため,プロキシを経由する企業 Web 環境からは misimaKansiServlet を利用できないかも知れない。

試行版(まだきちんとデバッグしていない)を「misima 漢詩平仄音韻分析(Servlet版)」にしばらく置いておくので,興味のある方はお試しください。漢詩を作る方のお役に立てればと願っている。まだ出力がベタで汚い。そのうちできるだけ見やすくなるよう工夫したいと思う。

主な仕様は次のとおりである。近体詩五言・七言の絶句,律詩を対象とする。詩格を自動判定する。国字(和製漢字)が含まれていると,デフォルトでは分析を停止する(オプションで無理矢理検査をすることもできる)。詩格に応じて,二四不同,二六対,下三連,弧平(五言詩では二段目,七言詩では四段目だけ)の禁則を検査する。韻字分析では,脚韻の妥当性,冒韻を検査する。拗体,通韻にはいまのところ対応していない。韻目は平水韻に準拠した。同字重出も検査するが,虚字,重言 (畳語) など許容される重複も含めて,重出と見なすようになっている。そのうち詩語データベースを作成して,詩作支援も盛り込みたいと思っている。

実行イメージは次のようなものである。(※ 2.5 付記:画像を最新イメージで入換えた)
 

20110103-kansi.jpg

参考にした文献は以下である。
 

本書は漢詩作りの入門書としては決定的な名著とされている。文字通り「誰にでもできる」と謳っている。掲載された詩語を検索しながら作詩する方法が丁寧に書かれている。漢詩とは言わば高級な着替人形のようなもので,形式と使い古された詩語との芳醇な組み合わせ自体に魅力を感じない人,新規なものにこそ魅力を感じる人には,もはや魂に訴えないだろう。ところがこの作法に慣れるにつれて,菅原道真,嵯峨天皇などの日本の古代の漢詩人たちに対して身近な親しみが芽生えて来るから不思議である。

Amazon で古書が入手できるようなのでリンクを付けておく。新品は,版元に直接注文するか,中国書・漢籍関係を取り扱っている特殊な本屋でないと入手できない。私は東方書店 Web サイトから購入した。
 

これは,細かいことがごちゃごちゃ書いてあるけれども,いまいち整理が足りないという欠点がある。「辞典」と銘打っているのに漢詩作詩法に関する用語の索引がないという,著者・版元の本作りに対する考え方,誠実さを疑いたくなるような書籍である。ただでさえ見た目の立派な函入りの高価な本なのだ。それでもここであげた書籍のなかではいちばん詳しく(雑然とではあるが)作詩法を解説しているので,私のプログラムも多く本書の記述に準拠している。

著者は現代詩を憎悪しているようである。リズムも言辞もぶっとんだレベルの低い文学だとみなしているようである。漢詩が最高の文学表現らしい。ほぼ堂上にある詩語の使用しか認めず同時代の差し迫った表現を排除してしまう漢詩の本性を鑑みるにつけ,こんなことを言って殻に閉じ籠るから漢詩人が絶滅寸前になってしまったんだろう,ということが,ある意味でよくわかる書籍である。芭蕉の言う「不易流行」の「不易」ばかりを追い求め,「流行」の命脈を欠いた姿である。私はこういうのを「権威主義」だと思う。ローマはすでに亡んだのに。そのためか,著者・飯田の詩論は「負け犬の遠吠え」のような印象が拭えない。でも私なんかは,ふむふむ,なかなかいいこと言っていると思わないでもなかった。「負け犬」の言い分も聞くに値することがある,とくに世を支配している趣味が底の浅い時代にあっては。私は本書を読み,漱石,朔太郎,子規の偉大さを改めて思い知った。明治の文学的地殻変動期には,近代日本における「詩とはなにか」が深く追究されたのである。
 

この本はどこでも手に入る。値段も手頃だし,薄くてすぐ読めてしまうし,著者も漢詩研究について日本の学会の権威的存在でもあり,簡にして要を押さえて,いちばんのお勧めかも知れない。『漢詩入門韻引辞典』とは違って著者のただの趣味でしかない詩論を押し付けないところもよい。なにより事項索引がきちんと付いているのがありがたい。さすが大修館書店である。
 

詩韻含英異同弁 (1963年)
浜 隆一郎,石川 梅次郎編校
松雲堂書店

略して「含英」と呼ばれている。求める韻を含む詩語を検索するための本である。江戸時代に書かれた書物で,しかも現代においても韻書の決定版とされている。これの引き方を覚えるのがまずひと苦労である。本書も新品は Amazon などでは入手できない。中古で出ているが,私は Yahoo! ブックスで探しまわってやっと新品を手に入れた(See: 詩韻含英異同弁 - 石川梅次郎/編校 浜久雄/編校 - Yahoo!ブックス)。
 

『字源』は漢詩人御用達の漢字辞典である。そういう点でここにもリンクを設置しておく。misimaKansiServlet では平仄の確認において,原則,学研『漢字源 第四版』に準拠した。『字源』は適宜参照した程度である。

これ,大正 12 年初版というのだから驚く。本辞典は収録漢語の多いのがなによりの美点である。私は普段は大修館書店『漢和辞典』か学研『漢字源 第四版』を愛用しているが(後者は Unicode コードポイントが検索できめっぽう便利なのだ),漢語・字訓を調べるときごくごくたまに『字源』を引く。

本辞典は,大正期以降の漢詩人御用達の権威的辞書であるだけに,漢詩作成サイトの多くが「漢詩作成になくてはならぬ辞書である」かのごとく必要以上に本書を持ち上げている。でも,そんなのはウソに決まっている。『言海』など戦前に纏められた権威ある辞典は旧字・旧仮名遣いにこだわる人たちから大いに賞讃されているのだが,検索しづらいばかりか歴史的仮名遣いに誤りも散見される。『字源』にも「水」の字音を「すゐ」とするなどの誤りがある(正しくは「すい」--- 「すゐ」は一般に流布していた誤りで,最近の辞典では「すい」に正されているのだ。「歴史的仮名遣い」なんてそんなものである)。また『字源』は,説明はすべて歴史的仮名遣い,漢音も字音仮名遣いのみの表示であり,初版増補の昔の活字組版がそのまま用いられていて,画数の多い漢字について活字が潰れて判読できないところすらある。エセ文化人の慕うくだらない「権威」よりも「学問性」と「有用性」に留意するならば,現代の新しい辞書のほうがよいと私は確信している。

私はかつて古書で 4,000 円くらいで本書を手に入れたが,いまやプレミアが付いて 10,000 円以上の価格が付いているようである。経年変色した絵画に美を覚えるようなバカ文化人(歴史的仮名遣いへの回帰を叫ぶような奴ら)でない限り,普通の現代人にとって『字源』よりももっと検索しやすく内容も確かな漢字辞典はいくらでもある。
 

※ 2011.2.18 付記
その後,詩語検索機能を追加した。記事「DWR with Java: misima 漢詩詩語検索」を参照ください。

URL encode in LaTeX

|

LaTeX でロシア語テクストを含む URL を出力しなければならないとき,url パッケージの \url 命令だと,キリル文字が出力できない。hyperref パッケージの \href{URL}{text} 命令を使って,text 部にロシア語テクストを記述すれば,これが可能となる。ところが,後者の場合でも,URL 部にロシア語 URL をそのまま指定しても,PDF にした際にそのリンクから当該リソースに飛んでくれない。この URL 部にはエンコード形式,つまり,ロシア文字を 1 オクテットずつ %xx の十六進数とした形式を指定しておかなければならないようである。

URL エンコードを行うツールはあちこちに転がっていて,Web なら http://www.tagindex.com/tool/url.html などの便利なサイトがある。Emacs 用の Elisp も探せばあるかも知れない。でも,LaTeX で,この URL エンコードを埋め込むとなると,% 文字が含まれるため,これをいちいちエスケープする手間が別途発生し,これまた面倒である。そこで,これくらいならツールを探す時間の間に出来てしまうと思い,自前で LaTeX 向け UTF-8 前提 URL エンコード・ツールを作ってみた。Perl である。U+0080 以上の UTF-8 文字を URL エンコードするので,ロシア語以外に日本語,ドイツ語などを含む URL にも適用できるはずである。同じ必要に駆られる方もいらっしゃると思うので,以下にそのコードを掲載しておく。ここにも置いておくので,ダウンロードして使っていただいてよい(無保証)。

#!/usr/bin/perl -w
# -*- coding: utf-8; mode: cperl; -*-
#  URL encoding: convert chars over U+0080 to format %hex.
#  Usage: urlenc [ -l ] < stdin (url text)
use strict;
use utf8;
use Getopt::Std;    # command line processing
use File::Basename; # get file basename
 
# command line
my %opts = ('l' => 0);
Getopt::Std::getopts('l', \%opts) ||
    die "Usage: " . basename($0) .
    " [ -l ] \< (stdin)\n  -l: insert \\ before % for LaTeX\n";
my $sfx = "%"; $sfx = "\\" . $sfx if ($opts{'l'});
 
# hex format
while (<STDIN>) {
    utf8::decode($_);
    my $enc = "";
    foreach my $chr (split(//, $_)) {
        if ($chr ge "\x{0080}") {
            utf8::encode($chr);
            foreach my $bchr (split(//, $chr)) {
                $enc .= $sfx . sprintf("%x", ord($bchr));
            }
        } else {
            $enc .= $chr;
        }
    }
    print $enc;
}

Perl コードはこれだけである。標準入力から読んだ URL 文字列のうち U+0080 以上を %xx 形式に変換して,標準出力に書き出す。オプション -l を指定すると LaTeX 向けに \%xx とエスケープした形で出力する。このプログラムを urlenc と名付けて,パスの通ったところにコピーして利用する。Mac OS X ターミナルでの実行例を以下に示す。

url-term.jpg

Emacs から利用する場合は,以下の内容を .emacs に記述し,関数定義を C-x C-e で Emacs に認識させるか,Emacs を再起動すれば,urlencode 命令が利用可能となる。ウラで上記 urlenc プログラムが動くので先きにこれを組込んでおくこと。urlenc の絶対パスは利用者の環境に応じて変更する必要がある。LaTeX 原稿において変換したいテクストをリージョン設定し,M-x urlencode RTN とすれば,当該リージョンが URL エンコード変換される。Emacs の set-default-coding-systems'utf-8 にセットしておかなければならない。

;;
;; URL encoding for LaTeX
;;
(set-default-coding-systems 'utf-8) ;; すでに設定されていれば不要
;;
(defun urlencode (start end)
  "URL encoding for LaTeX"
  (interactive "r")
  (call-process-region
   start end
   "/usr/local/bin/urlenc" ;; urlenc の絶対パスを指定
   t (list t nil) nil
   "-l") ;; urlenc LaTeX 用オプション
  )

Emacs 上での変換の様子を以下に示す。

url-emacs.jpg

事業仕分けもいい加減・SQLite

|

会社でも政府予算の動向把握は欠かせない。民主党政権の特色のひとつになった事業仕分けの結果も大きな関心を呼ぶ。なにせ時間と労力を掛けて必死こいて担当者が提案していたシステム化が,あの内実も知らない素人仕分け人のつっこみに対して役人がうまく対処できなかったために,一瞬のうちに「廃止,凍結」という話になってしまう。世の官庁関係の仕事をしている人で,これまでの苦労があの数十分の議論のおかげで水泡に帰してしまったような人には,あの仕分け人を後ろからブスリとやりたくなった奴もいるんじゃなかろうか。

ま,国家事業の無駄排除のために侃々諤々議論したうえで,「無駄」と切り捨てること自体は悪いことではない。それで国税を国民生活全体にとってより有益な事業に振り向けることになるのなら,誰だって文句は言えない。もともと事業仕分けは,国税の使途において長かった自民党政権下で既得権益と化した事業,あるいは「天下り」官僚のための有名無実の事業に対する政治による裁断ではなかったか,と私は理解している。しかしいまや,ニュースでも報道されるように,すでに民主党政権となり彼ら自身が予算化したも同然の事業に,尚もつっこみを入れなければ気が済まないのは,この劇場会議,そもそも予算策定の過程に民主党がまったくコミットできていないという恥ずかしい証拠になっているだけじゃなかろうか。

10 月末に行われた事業仕分け第三弾,特別会計の個別 48 事業の仕分け結果の資料を見た。特別会計とは,受益と負担の関係を明確にするために一般会計と区別して経理を行うものである。年金,労働保険など歳入に応じた行政の歳出で成り立っているような事業がこれに相当する。ま,事業はさすがにいろいろあるんだけど,このところ収賄事件で注目していた特許特別会計に私は目がいった。特許庁関係が特別会計になっているのは,ほぼ企業から得られる特許出願料・登録料という歳入だけで審査・審判・公報活動を行う財政構造・予算で成り立っているからである。要するに自分で稼いだカネで仕事をして日本国の産業,ひいては国民に成果を還元している訳である。

特許特別会計の平成 13 年度報告書が,情報公開法に基づき経産省サイトで閲覧できるようになっている。これを見ると,わが国の特許事業は 1,850 億円の歳入に対して歳出がなんと 950 億円であり,次年度繰越金が 900 億円近くもある。普通の会社なら利益率 100% に近い超優良企業である。それなら出願料を下げて出願人企業にもう少し還元したらどうかとも思う。しかしその一方で,なんのために存在しているのかもよくわからない政府外郭団体が無駄に税金を垂れ流す「天下り事業」と比べれば,稼いだ金の範囲で国益を創出している点で,遥かに健全な国家事業であるとも言える。

ところが,事業仕分け第三弾の結論を見ると,特許電子図書館事業は「将来的に廃止」,知的財産権教育事業は「文科省の仕事であり,廃止」,とにべもない。前者は,特許庁の審査用庁内検索システムが将来的に一般にも公開されるという背景を踏まえるとまだ納得できるのだが,後者は,じゃあ文科省にきちんと予算化させるところまでフォローしろよと言いたくなる。技術的,組織的に文科省ができないから経産省・特許庁が音頭取りをしていることをまったく理解していない。なのに,やめろと言うだけでこうしたらどうかという前向きな意見がまるでない。また,「アンタじゃなく文科省がやるべき,アンタはそれを手伝いなさい」などと省庁の縦割り構造を無視した結論を出すのは,現実的な観点において無責任ではなかろうか。

要するに,いまの事業仕分けはアラ探しばかりをする素人の無責任なつっこみにしか見えないのである。国益を考えた建設的意見がまるでない。そう考えるのは私だけではないと思う。だいたい,特別会計のような歳入と歳出の構造が明らかな国家事業にまで素人が首を突っ込むんじゃねぇ。技術立国の根本政策の実行官庁である特許庁の事業を,しかも健全な税金運用をしている特許事業を,井戸端会議的に引っ掻き回すんじゃねぇ。私はアタマに来た。私は当初の事業仕分けに対しては「政治主導」の端的な姿としてかなり好感を抱いていたが,今回の結果を見る限り,初心を忘れた素人つっこみ大会にしか思われなくなってしまった。事業仕分けはいまやただの劇場政治である。仕分ける前にきちんと予算化の段階でコミットすべきである。それはできるはずなんじゃないんでしょうか,政治主導というのだから。
 

* * *

最近,プライベートで漢詩を研究していて,misima の機能に漢詩規則分析を入れたいと思うようになった。平仄の妥当性の検証,孤平や下三連等の禁止事項のチェック,平仄に適合する詩語の検索など,漢詩を作りたいと思う人・漢詩の分析をしたい人のための支援機能である。misima の辞書を作りながら四声データも集めたので,まずはこれをもとにした平仄チェック,禁止事項チェックを行って診断結果を出力するとともに,すでにある機能と連携して \CID 形式の正字体に自動変換し,返り点命令変換を含めて,LaTeX 形式で出力するくらいはできそうである。

漢字・詩語データベースをどうするか悩んで,これまでと同じように DBM にデータを格納し Perl の連想配列で回すのがいちばんラクだと考えたのだけれども,検索機能ものちのち入れるんなら,ちょっと大げさだけど RDB にしようと思った。そこで手軽な SQLite を少し勉強することにした。SQLite は,RBMS サーバなしにライブラリだけで RDB を使う枠組みを特徴とし,ユーザ管理機能も高度なトリガー機能もないけれどもシンプルで軽い,パブリックドメインの RDB ソフトウェアである。Safari や Firefox が SQLite でブックマークなどを管理していることをいまさらながら知った。

会社の帰り,いつも行く虎ノ門の書店「書原」で本を漁った(この本屋,人文社会系の品揃えはなかなかである一方,コンピュータ関係はまったくダメである。またコミック,マンガ雑誌などまったく置いていない。よってコンビニ的風景を免れている。そのポリシーこそが私の贔屓にする所以でもある)が,SQLite の本は見当たらなかった。今日はいつもと違う道で新橋まで行こうか,とぶらぶら霞ヶ関を歩いた。日比谷公園にでも寄るか,ともふと思ったが時間が遅いのでこれはやめ。財務省と文科省の間の小道を抜け,桜田通り(国道 1 号線)を渡って霞ヶ関郵便局の辺りまで来ると,文教堂書店があった。小さい本屋だけど覗いてみたら,技術評論社刊行の『SQLite ポケットリファレンス』があった。このシリーズについてこれまで私は Perl, JavaScript, SQL, LaTeX に関する本を重宝していたので,迷わずこれをゲットした。DML の説明はあらかた普通の SQL 本と変わりがない。DB 運用に関る DDL, 端末コマンド仕様を帰りの電車で読んでイメージを理解した。
 

 

2011.1.5 付記

その後,漢詩平仄音韻分析プログラムをリリースした。SQLite3 を使った Java Servlet である。漢詩に興味のある方は「misima 漢詩平仄音韻分析(Servlet版)」をお試しください。

misima SOAP Web Service 運用

|

misima SOAP Web Service を開けっ放しにしてしまっていた。これは,Microsoft Word 2003, Emacs, 秀丸, Jedit X などのアプリケーションからインターネット経由で直接 misima 旧字・旧仮名遣い変換操作を行うためのサーバである。私以外,誰も使わない。公開停止にするのを忘れてしまっていた。今日,ant undeploy でアンデプロイした。こっちの認証はちょっと手が込んでいるので,よほどのことがない限り放置することになりそうである。私自身は Macbook pro 上の Web サーバを使うことにした。

最近,Google Desktop Gadget に興味がある。友人から文句が出たら,これで misima クライアントを書いてあげようかと考えている。でも,Google Desktop Gadget の SDK はどうやら Windows 版しかないようで,この時点で諦めムードになっている。Mac OS X ないし Linux / FreeBSD 用の SDK が出てからということになりそうである。

misima ope 備忘録

|

misima 辞書を手直ししたはよいが,misima サービス再起動の方法をすっかり失念してしまった。しばらくオペレーションしていないとすぐ忘れる。改めてドキュメントを調べて復習。アンチョコを自分のためにしるしておく。%, # はそれぞれ一般ユーザ,スーパユーザでの tcsh シェルオペレーションなり。

サーバ起動後のサービス開始

ja_JP.UTF-8 Locale に切替えて misimarestart を発行する。ウラで FreeBSD mfs メモリファイルシステム割当: mdmfs -F newimage -s 5m md0 /usr/local/etc/misima/, 辞書・misima CGI / SOAP Web Service 初期設定パラメータのメモリファイルシステムへのコピー, Apache22, Tomcat55, misimaserver (misima SOAP Web Service Daemon) の再起動が動く。
# source .langrc
# misimarestart

茶筌ユーザ辞書更新時のリビルド

開発ディレクトリ: ~/src/misima/ にて以下を発行。ウラで茶筌辞書ディレクトリへのユーザ辞書ソースコピーと茶筌辞書生成: makeda -i w user user.dic が動く。
# make chasen-dic-install

misima システム辞書更新時のリビルド

~/src/misima/ にて,バークレイ DB dbm を再構築し(ウラで genmisimadbm が動く),管理ディレクトリにコピーしたのち,misimaserver を再起動する。その後,misimaserver が 4 プロセス常駐していることを確認する。
% make misima-dic-rebuild
% su -m
# killmisimaserver
# misimaserver -p 34000 -r /usr/local/etc/misima/misimaserverrc & 
# ps | grep misima
46107   1  S+     0:00.00 grep misima
45929   2- I      0:00.25 /usr/bin/perl /usr/local/bin/misimaserver -p 34000 -r
45930   2- I      0:00.00 /usr/bin/perl /usr/local/bin/misimaserver -p 34000 -r
45931   2- I      0:00.00 /usr/bin/perl /usr/local/bin/misimaserver -p 34000 -r
45932   2- I      0:00.00 /usr/bin/perl /usr/local/bin/misimaserver -p 34000 -r

Utf82TeX-1009 Released

|

UTF-8 多言語 LaTeX 変換プリプロセッサ Utf82TeX-1009 をリリースした。<utf82tex_h> (十六進変換タグ), -p (PTEX_IN_FILTER mode) オプション, -w (Cygwin mode) オプション, UTF82TEXOPT (デフォルトオプション指定) 環境変数をサポートした。これまで,alternative なオプションを同時指定したときの動作についても,不明確かつ buggy だったので,今回見直ししてある。

いまや ptexlive with e-pTeX extension が公開され,UTF-8 の pLaTeX2e 環境も大きく進化した。Utf82TeX はもうその意義をほぼ喪失した。多言語用途としては皮肉にも漢字変換機能(JIS X 0208 範囲外の CJK 統合漢字を OTF パッケージの命令に変換する機能)だけが特徴となってしまった。という訳で,今回の ptexlive PTEX_IN_FILTER モードのサポートをもって,今後の機能追加はやめにしようと思っている。しかしながら,ありがたいことに,Utf82TeX については奥村先生の『[改訂第 5 版] LaTeX2e 美文書作成入門』(技術評論社,2010 年)でも言及していただいているので,バグ訂正,アーカイブ保守は続けて行くつもりである。

ダウンロードはここからお願いします。

IMCO が壊れた。今度は ZIPPO にした。じつは大学三年生のころ,ZIPPO 50 周年記念のレプリカが売りに出ていて--- 札幌大通りの「4丁目プラザ」だった ---,私は真鍮・金メッキの一品を購入し,愛用していた。社会人になりむちゃくちゃな労働生活の挙句に肺病になり入院したその日に,ハイライトの吸いさしとこの ZIPPO を妻に取上げられた。それから引っ越しやらを経るうちに,20 年近く使い込んで渋く変色したこのお気に入りライターを,自宅のどこかに眠らせたまま探し出せないでいた。いまふたたび同じ 1932 年レプリカを手に入れた。エッジの二本線が特徴である。

お店に依頼して,文字を彫金してもらった。"fluctuat nec mergitur" というラテン語を Roman 体で入れてもらった。「漂えど沈まず」という意味の格言である。昔,『週刊プレイボーイ』に開高健が人生相談のような連載をしていた。そこで,開高健の好きなことばとしてこの名句がしるされているのを読んだ。パリ市の紋章にもこれが印字されているそうである。時代のなかで翻弄され漂うように不安定ながらも沈んでしまうことはない,そのように生きよ,というメッセージであろう。開高健を尊敬する私にとって,爾来,このラテン語の格言は,彼が残してくれたことばと等価になった。
 

zippo_retunes.jpg

* * *

奥村先生のサイト TeX Forum で,『美文書』第 5 版 p.373 にある ptexenc フィルタの Perl コードの問題点の指摘があった。これは私が自分用に使っていたのを,Unicode と pTeX に関する節に参考として掲載したものだ。このプログラムに,utf8::decode 関数を,binmode 関数で UTF-8 として入力したテキストに対して発行すると,「二重デコード」されてしまうバグがあった。こういうことを見逃さずきちんと検討して,すぐ教えてくれる凄い読者がいる。そして忌憚なく語れる場がある。これこそ LaTeX コミュニティの凄さだと思った。

自分なりに納得の行く見直しをして,「[改訂第5版]LaTeX2e 美文書作成入門・付録I『LaTeX2e による多言語処理』サポートページ」に訂正版をアップした。ついでに Utf82TeX も同じバグを抱えていたので訂正した。こちらは折角なので,<utf82tex_n> 無変換指定タグサポートを追加し,swath タイ語ワードブレイカー 0.3.4 以降への対応に変更した。

LH T2D/OT2 Type1 fonts 改訂

|

LaTeX LH キリル・フォント T2D/OT2 エンコーディング Type1 フォント集を改訂した。これまでのものは,mftrace で pfa を生成する際,エンコーディング指定を省略していたので,これらフォントを埋込んだ PDF からキリル文字テキストをコピー&ペーストするとラテン文字になってしまって(要するに化けて)いた。対策方法はわかっていたんだけど,mftrace 長時間実行が躊躇われてずっと放置していたのだった。美文書第 5 版(本書 p. 367 でこの T2D/OT2 Type1 フォントが言及されている)が出たのを契機に,やっとこの課題に取組む気合いが湧いて来た。

T2D 及び OT2 Type1 フォントの mftrace 生成に際して,--encoding オプションに対し,それぞれ t2d.enc, cm-lgc-ot2.enc を指示した。Александр Лебедев 氏による OldFonts パッケージ, Алексей Клюков 氏による CM-LGC パッケージに付属するエンコーディング・ファイルである。Type1 フォント生成に,以前は PowerMac G5 Tiger で 7, 8 時間かかったのだが,今回 MacBook Pro Snow Leopard では半分以下でできてしまった。

これで PDF のキリル文字をきちんとコピー&ペーストできるようになった。ロシア語旧正書法の文字も正しく取り扱われるはずである。ダウンロード・サービスlh-misc-type1-1007 アーカイブを置いた。インストール/使用法の詳細については,拙稿「LH キリル T2D/OT2 Type1 フォント集」を参照。

misima は現在,限定公開としていますが,諸般の事情により近く運用を停止する予定です。サーバのメンテナンスのためのコスト・労力の負担が堪え難いものになって来たのがその主な理由です。本サイトは,http://yasuda.homeip.net/ の静的コンテンツ(とくに LaTeX 関係)以外の CGI, JavaServlet 関連アプリケーションを停止します。このブログも facebook あたりに移動させるかも知れません。時期は私の作業都合(要するにヒマ)次第です。突然見えなくなるかも知れませんが,悪しからずご了承ください。

OldSlav-1.3-beta, Spam 対策

|

OldSlav-1.3-beta を公開した。古ルーマニア正教会で用いられた二文字の追加,その他バグ fix を行った。

新しい文字は \OCSDZHE \OCSdzhe\OCSYN \OCSyn,またそれぞれ \DZ \dz\YN \yn でも入力ができる。前者は UTF-8 で Џ џ を直接入力することができる。後者は Unicode U+A65E,U+A65F という拡張領域にあり,今回は直接入力のサポートを見送った(このブロックを表示・編集できるエディタは少ないと思う)。

OldSlav-1.3-beta はダウンロードサービスから取得できる。

* * *

最近,頼子さんやら,恵子さん,美香さんなどから,艶っぽいメールをたくさんいただく。とくに頻繁なのがロシア娘 Olga である。要するにスパムメールの話。たいていはスパム丸出しで SpamAssassin が取り除けてくれるのだけど,Olga の英文スパムだけは差出人が私のメールアドレスを詐称しているため,Whitelist 扱いで堂々とメールボックスに入って来てくれる。このオリガ,ロシア語をしゃべってくれるのなら,少しは相手をしてやってもよいのだが,英語で "many beauties" やら "my pussy" やらとウザったい上に,あまりにも出没頻度が高い。その都度手動で MHonArc Web メーリングアーカイブからパージするのにも疲れてしまった。いい加減手を打つことにした。

詐称された自分のメールアドレスを Whitelist から外すという策もある訳だけど,今回は procmail レシピを追加した。私は自分の出すメールは自分にも cc する習慣であって,それらが SpamAssassin にスパム扱いされかねないのも煩い。

私のアカウントを詐称するメールは,私自身が送信したものではない点をチェックすればよい。その特徴は,当然,私の MUA,プロバイダを通過せずに来るので,メールヘッダの Receive 行に localhost やプロバイダメールホストの来歴がない。ここをチェックして弾くようにした。

:0:
* ^From:.*watasi.no.address.*
* ! ^Received:.*my.provider.smtp.server.jp.*
* ! ^Received:.*localhost.*my.mail.server.jp.*
spam/.

しばらく様子見。おお,Olga が引っ掛かってる,引っ掛かってる。

※ 2010.4.30 付記

それはそうと,ロシア女性名のイメージとなるとオリガというのはなぜなんだろうか? しかもどこか淫微であったり,おつむが弱かったり,という不幸なイメージにおいて。これはどうも伝統的である。プーシキンの『エヴゲーニイ・オネーギン』のオリガは,思慮の浅い女性のタイプになっている。

横光利一の『上海』にも,落ちぶれた亡命貴族女性オリガが登場する。彼女と同棲することになった主人公は,オリガからひっきりなしにアレを迫られ,ヘタってしまう。これはオリガの個性というよりも,ロシア女性一般の情熱に近いらしい。ロシアの男は週に 16 回妻を満たさないと一人前の亭主とは認められない,と佐藤優がどこかで書いていた。横光の観察には感銘を受ける。

10 年程前,錦糸町で顧客と呑み歩いたあと,とうに終電を過ごしてしまった真夜中,ひとり駅前をぶらついてタクシーを探していた時,私はキャバクラの外国人袖引きに誘われたことがある:「えっちナろしあノ女ノ子イマスヨ! はんがりーノキレイナ子モイルヨ! 遊ンデイキマセンカ」。私は「そのロシア人,オリガですか?」と聞いたら,「ヨク知ッテルネ」と言われた。

私は昔,新潮文庫で『上海』を読んだのだけれど,最近,岩波文庫から手頃な版が出たので,以下にその Amazon リンクを付けておきます。
 

OldSlav: K さんからの返信

|

OldSlav 教会スラヴ語 LaTeX パッケージへのフォント追加について,ベータ版とサンプル組版 PDF を K さんに送った。今朝,彼から早速返事をもらった。彼はたいへん気に入ってくれたようである。文字の幅,高さ,カーニングの具合が知りたくて,私は追加資料をお願いしていたのだが,なかなか適当なのが見出せないと彼は詫びていた。サンプルができたのを幸い,大学の文献学教授に見てもらい,見解を知らせてくれるという。

この女性教授,K さんの旧版 OldSlav で組んだ文書を見て,これはロシア風の書体様式だとすぐ判ったらしい。いくつか写本を見て来たとはいえ,私などは,教会スラヴ語の書体がロシア風か,ブルガリア風か,はたまたマケドニア風,セルビア風か,さっぱり区別が付かない。ただ「美しい」ということだけ(このフォントは,もともと,モスクワ大学のアンドレイ・スレプーヒン教授がロシア正教会の委託で作成したものである)。さすがである。こんな学識豊かな教授の意見がもらえるなんて,少しワクワク。

ところで,この先生,K さんによる OldSlav LaTeX 原稿を同時に見て曰く,世の中には Microsoft Office があるというのに,なんでまたこんな面倒臭い書き方をするんでしょう,"king size pain in the ass"(何故かここだけ英語)ですワ。"king size pain in the ass(ケツん中ビッグに痛ぇカンジー=ちょーイラつく)" なんて下品な表現を,本当に彼女が発したのかは知りません(もとより,ルーマニア人である)。でも,これが LaTeX の魅力を知らない人の正直な意見であるのは疑いがない。あるいはより多くの場合,LaTeX に「挫折した」人の恨みツラミである(ネットでもよく見かける)。MS Office is MS Office. LaTeX is LaTeX. That's all. No reasons. そう書いて返信した。orz...

もう少しマクロに手を加えたら,OldSlav-1.3(とりあえずベータ版)として公開するつもりである。

OldSlav に対し,先日ルーマニアの学生 K さんから要請されたフォントの追加を行った。古ルーマニア教会文献で用いられた文字を二つ,upper / lower で計 4 グリフ(Ꙟ: Yn U+A65E, U+A65F --- 矢印「↑」もしくは漢字「个」のような形をした i --- と,Џ: Dzhe U+040F, U+045F)。METAFONT で生成した。Yn のデザインがよいのやら悪いのやらさっぱり判らず,K さんに見てもらうことにした。彼が満足できるものなら,公開しようと思っている。

彼からデジカメ画像で送られて来た見本のルーマニア語文献の引用で,早速タイプセットしてみた。赤い文字が今回追加したものである。

romanian-ocs.jpg

ルーマニア語には TeX Gyre の Termes (Roman) フォント,QX フォントエンコーディングを使用した。

\usepackage[utf8x]{inputenc}
\usepackage[QX]{fontenc}
\usepackage[oldchurchslavonic,romanian]{babel}

ルーマニア語アルファベットには Ș (U+0218), ș (U+0219), Ț (U+021A), ț (U+021B) というコンマを付けた特徴的な文字がある。\usepackage[utf8x]{inputenc} を指定すれば,これら文字を直接タイプして T1 フォントエンコーディングでも出力できる。この場合 utf8x.def が定義している \textcommabelow 命令によって,S と , との合成で文字が出力される。

ところが,昔から Latin2 (ISO 8859-2) でテキスト作成する関係で,これらの文字はコンマ付プロパーではなくセディーユ付で代用されて来たせいか,Ş (U+015E), ş (U+015F), Ţ (U+0162), ţ (U+0163) を入力し,かつ QX エンコーディングを指示してタイプセットしたほうが,TeX Gyre にあるカンマ付プロパー文字 Ș ș Ț ț が出力できるのである。カンマとの合成文字で出力するよりもずっと綺麗である。T1 エンコーディングだと --- 当然ながら --- セディーユ付 Ş ş Ţ ţ が出てしまう。

こういうややこしい事情からして,ルーマニア語はどうも可哀相な扱いを受けて来たらしい。この Ș ș Ț ț の文字がいまブラウザに表示されていない方(おそらく Windows な方)もいるはずである。これらは Unicode 体系においては,アゼルバイジャン語,エヴェ語,フーラ語などの拡張ラテン文字ブロック Latin Extended-B (U+0180--U+024F) に収められている。いわゆるヨーロッパ言語の文字が基本的に Latin Extended-A (U+0100--U-017F) までに収容されていることからすれば,仲間はずれにされている訳である。ルーマニア語ってヨーロッパ言語のなかで個性的だということがよくわかるのである。

※ 2010.4.30 付記

このルーマニアの学生さんは,ルーマニアでのこうした文字の混乱について憤慨していた。彼は LaTeX で母国語を組むときは combelow パッケージを使っているそうである。TeX-Gyre のコンマ付文字はコンマが少し大きくて,彼は好きになれないそうである。その一方で combelow の \cb 命令(\cb S とすると S の下にコンマのダイアクリティカルマークが付加される)も,コンマと文字の間のアキが大きすぎるとこぼしていた。自分で微調整して使用するとともに,作者にも連絡をとって提案しているとのことだった。

私自身は TeX-Gyre のフォントが気に入っているので,「ルーマニア語 LaTeX 事情は複雑ですなぁ」としか応対できなかった。

訃報・ptexlive

|

お隣のお婆さんが亡くなった。うるさいお婆さんだったが,亡くなると寂しいものである。つい先日,ウチがゴミ当番だった朝,「網が掛かってないからカラスが散らかしているじゃないの」とこのお婆さんにお叱りを受け,そそくさともう一度網を掛け直しにゴミ捨て場に出,彼女と挨拶したばかりなのに。合掌。ご主人もいつも叱られていたような気がする。敷かれる尻がなくなっても元気でいてほしいと思う。

* * *

OldSlav-1.2 を公開した。Windows CP1251 などの代表的なキリルエンコーディングによる入力方式を追加した。ドキュメントも改訂した。

* * *

IBM ThinkPad X40 FreeBSD-6.2 Release に ptexlive 最新版をインストールした。私の環境はディスクの空きがわずか 1.5GB しかなく,texlive に必要な 5, 6GB を確保できず,公開サーバの NFS 領域にインストールすることにした。ところが NFS マウントのオプションに -maproot=root を付けていないので,ptexlive の make install でエラーのオンパレードになってしまった。公開サーバなのでシャットダウンするのも憚られ,root ではなく一般ユーザの権限でインストールした。ちょっと環境を壊すリスクが高いけれども,まあよい。

ptexlive-20091009 ではまだ,texlive に添付された UTF-8 の新しいハイフネーションパターンがサポートされていないようである。fmtutil --byfmt platex で,添付の language.dat を読み込ませると,昔懐かしい bad pattern エラーが頻発してフォーマット生成が失敗する。しようがないので,旧 ptetex3 環境からハイフネーションパターンファイル一式をコピーして再実行したらうまく行った。

texlive は各プラットフォーム用のバイナリが install-tl コマンド一発でインストールできるようになっている。LaTeX パッケージも Teubner や CJK,unicode,cm-super などがはじめから組み込まれていて,めっちゃラクである。ただし,CJK パッケージの日本語タイプセット用に TFM を生成しようと ttf2tfm コマンドを実行したら,ライブラリのリンクでエラーとなった。ソースからビルドすればこんなことにはならないはずである(もちろんコンパイルなど別の面倒が発生するのだけど)。UNIX ユーザ向けにバイナリを配布するのは,こういう問題があるからやめたほうがよいと思うのだが。でもまあ,主要なコマンドは元気に動いているのでよしとする。いちおう,土村さんの ptexlive サイトに動作報告をあげておいた。

ptexlive で OldSlav を試験したが問題なさそうである。公開したバージョン 1.2 に ptexenc オプションを追加しておいた。やっていることは 1.1 の ptetex と同じだけど,土村さんの提言に従うことにしたのである。

※ 1.10 付記
ttf2tfm ライブラリ問題について,ptexlive.cfg にある conf_option --without-cjkutils をコメントアウトすれば,ソースからビルドするようになると,土村さんからご教示いただいた。さすが,考え抜かれているなー。Babel ハイフネーションパターンも対応中とのこと,楽しみである。

OldSlav Cyrillic encoding support

|

OldSlav 教会スラヴ語 LaTeX パッケージの 8 ビット・キリル・エンコード対応作業を行っている。OldSlav の従来バージョンでは SlavTeX オリジナルのエンコード CP866 キリル・コードでオリジナルの記法そのままに入力できるような設計になっていたのだが,8 ビット文字の分類コードなどを不用意に変更すると,韓国語 UTF-8 inputenc との併用で問題を来すことがわかり,1.1 では CP866 サポートをやめてしまっていた。それなら inputenc.sty のキリル・サポートに乗っかって,広く行われているキリル 8 ビット・コードを使えるようにするのが次の課題になった。

とはいえ,すでに教会スラヴ語環境内で \CYRA などの inputenc.sty の命令を読み替えることにより T2D, T2A, X2, XS エンコーディングを使えるようにしていたので,じつは 1.1 でも \usepackage[koi8-r]{inputenc} とするだけで KOI8-R の原稿でも基本的に動作する。ただし,これだと などの SlavTeX がサポートしていた,キリル文字からなる命令(主にアクセント命令)が使えないし,特殊なアクセント位置調整も効かない。今日はこの不足を補うマクロを書いた訳である。babel \languageattribute で指定するオプションに代表的なキリル文字コード Windows CP1251, KOI8-R, ISO 8859-5, CP866 を指定できるようにした。それぞれ,cp1251koi8-riso88595cp866 を書けばよい( inputenc.sty と同じ)。ただし,もちろんこの場合, latexpdflatex による組版が前提である。これで SlavTeX との互換性も満足できそうである。ロシア人が使うには必須の機能かも知れない(彼らがよく使う MiKTeX に私はほとんどまったく馴染みがないのだけれど)。

試験をしていたら,長大な原稿で何度も言語切替えを行うと Save size スタックのオーバーフローエラーが起きた。げげ,こんなのはじめて,またつまらない潜在バグ!と我ながら呆れた。キリル命令・他パッケージの命令と教会スラヴ語命令との切替えにおいて,頻繁にバックアップ/リストアを \let 命令で繰り返しているとこれが発生するという訳だった。とりあえずバックアップ処理のタイミングを一度に限定することでこの問題対処とした。

これらの対応版は一応できたけれども,ドキュメントがこれから。さっさと改訂して 1.2 としてサーバに置くつもりである。仕事もはじまり,なかなか時間が取れそうもないんだけど。極々関心のある方限定で oldslav-1.2rc.zip をお試しください。

OldSlav English document released.

|

OlsSlav for Old Church Slavonic LaTeX package Ver. 1.1 対応の英文ドキュメントをやっと公開した。ヘタクソな英文でも,ないよりはマシ。巧遅拙速に如かず。世のビジネスでは品質よりも納期優先じゃ。それでも,メールで付き合いのある外国人に,おいおいチェックしてもらうつもりでいる。

これで三が日が費やされてしまった。 ああ,でも今年の正月休みは家族水入らず,ホントのどかなよい寝正月だった。

御用納めとなり,2009 年も残すところ二日となってしまった。先頃,今年を象徴する漢字は「新」ということが清水の舞台から公にされたが,それぞれ皆,各々の今年の一文字があるかと思う。私の場合,不況でまったくつまらない今日この頃,「暇」であった。また死ぬほど顧客に虐められ,トラブルで火を噴く現場の喧噪に包まれたい,という思いも無い訳ではない。

妻にせっつかれてやっと年賀状を作った。娘の描いた虎の画をスキャンして,Mac OS,Adobe Photoshop で加工し,Illustrator で文字周りをぺぺっとレイアウトして 30 分で完了。とりあえず 50 枚印刷。

公開したばかりの OldSlav について,奥村先生のサイト TeX フォーラムにおいて,観点鋭くかつ学術性にも配慮した指摘をいただいた。自分の用途に足りるレベルで作ったものを公開しているに過ぎないのだけれど,ハイレベルな反応をもらうとなんともうれしくてたまらなくなる。教会スラヴ語日付様式の典拠,韓国語 inputenc との共存など,重い課題が多くて,システマチックにその指摘に対応するのは難しいところがあり,いま手元にある文献や試験環境でできる範囲で設計を見直し,訂正して,今日公開した。SlavTeX オリジナル CP866 コード入力での互換性は inputenc との絡みで今回犠牲にした。だいたい今や誰も使わないエンコードに拘っても意味がない。ダウンロード頁から oldslav-1.1.{tar.gz, zip} を落としてお使いください。

明日は我が家の大掃除。ここのところ仕事から帰宅したあと OldSlav の改造に夢中になってしまい,妻から家事を手伝わないと責めまくられている。

* * *

アンナ・アフマートワの詩集『ヴェーチェル(夕べ)』を工藤正廣訳(未知谷刊)で読む。ロシア詩のスタンザ毎に短歌として訳した珍しい翻訳である。工藤先生も健在だなあ,という思いがこの書を手にしたそもそもの理由である。

アンナ・アフマートワは 20 世紀ソヴィエトの女流詩人。彼女の詩は,至る所に死の匂いが染み付いている。己の死後の現実の感触を透視し聞きとろうとする心の闇がある。「あまりにも生を望みしそのわれの冷たき屍手おくひとなし」(p. 115)。スターリンの大粛正で夫(第一級の詩人ニコライ・グミリョフ)が銃殺され,わが子がシベリヤ送りとなったこの天才にあって,死の日常性が事物に取り憑いてさりげなく漂うのは,文学的衒いでもなんでもないのである。

夢おそく不眠の窓にまた白くご機嫌ようと白きカーテン(p. 15)
氷結し狭き運河の流れずにおゝ新しきこともなき地よ(p. 49)
太陽の記憶こころに弱まれば闇のこの夜にまさに冬来る(p. 50)
日没に針葉の森消えゆくを見つつ聞きおりきみに似し声(p. 110)
酩酊の葡萄匂える遠景にわれ惜むなしきみ虚無の声(p. 164)
 
夕べ―ヴェーチェル
アンナ・アフマートワ
工藤正廣・短歌訳
未知谷

Moon Calendar

Profile

ISAO。システムエンジニア。昭和 30 年代を懐かしむオヤジ。ロシアに興味があります。
[more], [About our site]

Notice

この文書はフィクションであり,実在する個人,団体等とは一切関係ありません。

文書の記述内容は無保証です。不適切な表現があればコメントにてご指摘ください。

コメント,トラックバックは,管理者承認を経て公開となります。公序良俗に反すると判断されると,断りなく削除される場合があります。

Links

About this archive

All Entries of Category 日曜大工

Previous: 文房清玩

Next: 鏡の中の鏡

Recent Entries in Main Index.
All Entries in Archive Index.

Web Pages

Powered by Movable Type 4.1