昨日書いた泉鏡花『貧民倶樂部』の記事において,鏡花テクスト引用のために大量のルビをマークアップしなければならなかった。HTML で <ruby>
このツールは,標準入力から UTF-8 テキストを読み,此(これ)のように,漢字 + ( + 読み + )のように書いた文字列に対して,マークアップを行う。デフォルトでは HTML タグを付加する。-l オプションを指定すると LaTeX 形式で整形する。対象テキストの括弧は全角でないといけない。そういう融通の利かないところがある。開括弧より前のテキストを後ろから逆方向に走査し,漢字以外が出現するまで漢字をスタックにプッシュし,あとでこのスタックからポップして得られる文字列(先入れ後出しにより文字の順番が戻る)を親文字と判定する。「漢字」は Unicode CJK 統合漢字に属するかを \p{InCJKUnifiedIdeographs} 正規表現文字クラスで判断している。Perl コードは以下の通り。
#!/usr/bin/perl -w # -*- coding: utf-8; mode: cperl; -*- # # convertruby: ルビ・マークアップ # - ベタのテキストを <ruby> or \ruby シーケンスに整形する # - 例: 此(これ) ["(", ")" は全角括弧] # -> <ruby><rb>此</rb><rp>(</rp><rt>これ</rt><rp>)</rp></ruby> (default) # -> \ruby{此}{これ} (with -l option) # - usage: convertruby [-l] < stdin # -l: for LaTeX; default: for HTML # use strict; use utf8; use Getopt::Std; use File::Basename; binmode(STDOUT, ":utf8"); # コマンドライン・オプション処理 my %opts = ('l' => 0); Getopt::Std::getopts('l', \%opts) || die "Usage: " . basename($0) . " [-l] \< (stdin)\n -l: for LaTeX; default: for HTML\n"; # 行毎の主処理 while (<STDIN>) { my $line = $_; utf8::decode($line); utf8::decode($_); my ($yomi, $leftt, $rightt); # 「(読み)」を含まない行はそのまま出力 unless ($_ =~ /([^)]*)/gi) { print $line; next; } # 「(読み)」を走査し,これがある限りその前後を切り出す while ($line =~ /([^)]*)/gi) { $yomi = $&; $leftt = $`; $rightt = $'; # 「(読み)」から括弧を外す $yomi =~ s|[()]||g; # 対象漢字部を後方から走査し,漢字スタックに push する my @kstack = (); my $k; my @istack = split(//, $leftt); # 「読み」の左側テキストの文字配列 while ((@istack) && (($k = pop(@istack)) =~ /\p{InCJKUnifiedIdeographs}/g)) { push(@kstack, $k); $k = ""; } # 最後に pop した非漢字を左側テキスト配列スタックに戻しておく push(@istack, $k) if ($k); # 漢字スタックから漢字部文字列を pop で復元 my $kanji = ""; while (@kstack) { $kanji .= pop(@kstack); } # 抽出した漢字部よりも前の文字列を出力 if (@istack) { print $_ for @istack; } # ruby マークアップ部分を出力 if ($kanji) { if ($opts{'l'}) { # LaTeX (with -l option) print '\ruby{' . $kanji . '}{' . $yomi . '}'; } else { # HTML (default) print '<ruby><rb>' . $kanji . '</rb><rp>(</rp><rt>' . $yomi . '</rt><rp>)</rp></ruby>'; } } else { # 「漢字(読み)」のパターンでないものはそのまま出力 print "($yomi)"; } # 走査対象文字列に右側テキスト(残り)文字列を格納して,繰り返し $line = $rightt; } # 残り文字列を出力 print $rightt if ($rightt); }
GNU Emacs からは,以下を .emacs に追加すれば,利用できるようになる。ここでは convertruby は /usr/
;; convertruby for HTML (defun convert-ruby-html (start end) "Convert text to ruby HTML sequence." (interactive "r") (call-process-region start end "/usr/local/bin/convertruby" t (list t nil) nil "") ) ;; convertruby for LaTeX (defun convert-ruby-latex (start end) "Convert text to ruby HTML sequence." (interactive "r") (call-process-region start end "/usr/local/bin/convertruby" t (list t nil) nil "-l") )
泉鏡花『貧民倶樂部』の引用に際しては,新字・新仮名遣いで引用文を作成し(図 1),自作のソフトで旧字・旧仮名遣いに変換し,次に,ルビを付けたい漢字に「(よみ)」を付加し(図 2),最後に Emacs 上で convertruby を実行して <ruby> タグをマークアップした(図 3)。ただし,図 3-1 は HTML 整形の,図 3-2 は LaTeX 整形の結果例である。