印刷用表示へ切り替え 通常表示へ切り替え 更新履歴を表示 更新履歴を隠す
MovableTypePlugin PRE 要素変換プラグイン 0.9 解説

プログラムを書いた後一定期間が経過すると、一体どうしてこんなコードを書いたかが分からなくなってしまう。私の場合、自分で書いているにも関わらず「1ヶ月後は他人のプログラム」になっている。Perl のプログラムは特に分からなくなりやすい。そこで、何をやっているかをメモしておくことにした。実際に書いていくうちにバグ (というより制限事項) も見つかった。

■ ■ ■

pre 要素内の改行に関するアイデア (nlog(n): pre 要素を自動改行させたい) をもとに,実装したプラグイン(nlog(n): PRE 要素変換プラグイン 0.9) の動作について解説する。メインのルーチンでは、ウェブログの本文の受け渡しとサブルーチンの呼び出しを行う。

sub CPreConv {
...
  $out =~ s/(<pre>.*?<\/pre>)/sp2amp($1)/eigs;
...
}

$out には、ウェブログの本文が丸ごと入ってくるようになっている。 この1行の意味は次の通り。

  • 「.*?」は、一番近い <pre>...</pre> の組を探す。
  • /s 装飾子により、<pre> と </pre> の間に改行が入っていてもマッチする。
  • /i 装飾子により、大文字小文字を区別しないで、<PRE> や <Pre> などにもマッチする。
  • /g 装飾子により、本文中に複数の <pre>...</pre> の組があっても1つ1つマッチする。
  • /e 装飾子により、「sp2amp($1)」を文字列ではなく式として評価する。 すなわち、sp2amp($1) の結果が入ることになる。 「e」は「evalulate」の意味。

「/e」という修飾子を初めて使った。強力過ぎて驚いた。

sp2amp サブルーチンには、<pre> で始まり、</pre> で終わる数行が「@_」にセットされて渡される。

sub sp2amp {
  my $code = shift(@_);
  $code =~ s|<pre>||i;
  $code =~ s|</pre>||i;
  $code =~ s|^\n||s;
  $code =~ s|(.*?)\t|$1 . (' ' x (8 - length($1) % 8))|eg;
  $code =~ s|  | &nbsp;|g;
  $code =~ s|^ |&nbsp;|mg;
  $code =~ s|\n|<br />\n|sg;
  $code = q|<div class="precode">| . $code . q|</div>|;
  $code;
}

サブルーチン内では、終了タグで使う「/」が頻発するので、 置換のための区切りとして「|」を使うことにする。 「|」を使うと、文字としての「/」をエスケープする必要がなくなり、コードが少しだけ読みやすくなる。

  1. my $code = shift(@_);
    「@_」に配列として渡される <pre>...</pre> の数行を $code 変数に丸ごと代入する。 「my ($code) = @_;」としてもよいかも知れない。 しかし、「my $code = @_;」としてはいけない。 こうすると、$code には配列の要素数である「1」が代入されてしまう。 「1行」の文字列として渡されているため、要素数は「1」になる。
  2. $code =~ s|<pre>||i;
    $code =~ s|</pre>||i;
    最初の <pre> と最後の </pre> を大文字小文字を区別しないで削除する。
  3. $code =~ s|^\n||s;
    一番最初に改行のみの行がある場合に、その1行だけを削除する。
  4. $code =~ s|(.*?)\t|$1 . (' ' x (8 - length($1) % 8))|eg;
    タブ文字を8個のスペースに変換する。 「スペース3個にタブ1個が連続」している場合も8個のスペースにする(11個のスペースではなく)。 length() 関数はスペースも1文字として数えてくれる。
  5. $code =~ s|  | &nbsp;|g;
    連続した2つのスペースを「スペース1個と &nbsp; 」に変換する。
  6. $code =~ s|^ |&nbsp;|mg;
    行頭にスペースがある場合は、「&nbsp;」に変換する。 /m 修飾子により、複数行として扱うようになるので、各行の行頭にマッチすることになる。
  7. $code =~ s|\n|<br />\n|sg;
    行末の改行文字を「<br />」タグに変換する。 変換後も読みやすくするために、さらに改行文字を追加している。
  8. $code = q|<div class="precode">| . $code . q|</div>|;
    最後の手順として、前後に <div>, </div> タグを追加する。

詳細を書いていて、考えに入れていなかった書式があることに気がついた。 pre 要素の中に、強調などのタグが入っていることを考慮していない。 現時点でのバグは以下の通り。

  • タグの後ろにタブ文字があると、スペースの数が正しくなくなる
  • タグの中にスペースが2つ以上連続していると、スペースが「&nbsp;」に変換されてしまう

つまり,pre 要素内にタグを書かなければ問題は発生しない。タグを書いた場合でも,連続してスペースを書かなければ大きな問題にはならない。

Posted by n at 2004-10-28 23:15 | Edit | Comments (0) | Trackback(0)
Trackbacks

  • 「手違いで複数トラックバックを送ってしまった!」という場合でも気にしないでください (重複分はこちらで勝手に削除させていただきます)
  • タイムアウトエラーは,こちらのサーバの処理能力不足が原因です (詳細は トラックバック送信時のエラー をご覧ください)
  • トラックバックする記事には,この記事へのリンクを含めてください(詳細は 迷惑トラックバック対策 をご覧ください)
Comments
Post a comment
  • 電子メールアドレスは必須ですが,表示されません (気になる場合は「メールアドレスのような」文字列でもOKです)
  • URL を入力した場合はリンクが張られます
  • コメント欄内ではタグは使えません
  • コメント欄内に URL を記入した場合は自動的にリンクに変換されます
  • コメント欄内の改行はそのまま改行となります
  • 「Confirmation Code」に表示されている数字を入力してください (迷惑コメント対策です)


(必須, 表示されます)


(必須, 表示されません)


(任意, リンクされます)


Confirmation Code (必須)


Remember info (R)?