howm->はてな(その2)

バージョンアップしますた。id:mzp:20070806:howm

30分プログラム、その95。howm->はてな(id:mzp:20070724:howm)をパワーアップしてみる。
今までのやつは前日のメモだけが対象だったが、今回は過去の日記すべてを対象にしてみた。更新されたやつだけを探すのは面倒だったので、その辺ははてダラスプリッタにまかせた。

使い方

$ ./howm-hatena 
 2007-07-23:
*1185197435*howmの文字コードの設定
[2007-07-23 22:30] >>> ~/c/config/emacs

 >|lisp|
 (setq howm-process-coding-system '(utf-8-unix . utf-8-unix))
 ||<

のように指定してやるといい。

で、実際にはこんなスクリプトを使っている。

#!/bin/sh
rm -rf howm
/home/mzp/cmd/svn/bin/svn export file:///home/mzp/repos/c/docs/howm
perl howm-hws > diary.txt
perl hws
perl hw

ソースコード

#! /usr/bin/perl
# -*- mode:perl; coding:utf-8 -*-
#
# howm-hws.pl -
#
# Copyright(C) 2007 by mzp
# Author: MIZUNO Hiroki <hiroki1124@gmail.com> 
# http://mzp.sakura.ne.jp/
#
# Timestamp: 2007/07/30 23:40:24
#
# This program is free software; you can redistribute it and/or
# modify it under the same terms as Perl itself.
#

use strict;
use warnings;
use Time::Local;

my $HOWM_DIR = './howm';

sub array_equal{
    my ($a,$b) = @_;
    for(my $i = 0 ; $i < @$a ; $i++){
	return 0 unless($a->[$i] == $b->[$i]);
    }
    return 1;
}

my @files = glob "$HOWM_DIR/*/*/*.howm"; # already sorted

my @date;
while(@files){
    my $file = shift @files;

    my ($year,$mon,$day,$hour,$min,$sec) =
	($file =~ /(\d{4})-(\d{2})-(\d{2}) # YEAR-MONTH-DAY
                  -(\d{2})(\d{2})(\d{2}) # HOUR MIN SEC
                  \.howm\Z/xo)
	or die "invalid file name: $file";
    my $time = timelocal($sec,$min,$hour,$day,$mon-1,$year-1900);

    # date split
    unless(@date and array_equal(\@date,[$year,$mon,$day])){
	@date = ($year,$mon,$day);
	print join('-',@date),":\n";
    }

    # print file content
    open FILE,$file;
    my $content = join('',<FILE>);
    $content =~ s/\s+(=|\Z)/\n\n$1/gm; # split last blank line
    $content =~ s/^= /*$time*/gm;
    print $content;
    close(FILE);
}

メモ

my ($year,$mon,$day,$hour,$min,$sec) =
   ($file =~ /(\d{4})-(\d{2})-(\d{2}) # YEAR-MONTH-DAY
             -(\d{2})(\d{2})(\d{2}) # HOUR MIN SEC
             \.howm\Z/xo)
   or die "invalid file name: $file";

は、非常にPerlらしいコードだと思う。

この1行には、次の三つの処理が詰っている。実にPerlらしい。

  1. ファイル名から年,月,日,時間,分,秒を取り出す
  2. 取り出した文字列を$year,$mon,$day,$hour,$min,$secに代入する
  3. 失敗したら、dieでエラーメッセージを出す

ちなみにこれができる理由は、次のような理由だと思う。けど、あんま自身ない。

  1. 正規表現のマッチはリストコンテキストだと、キャプチャした文字列のリストで返す
  2. リストは、多重代入できる
  3. 失敗すると偽を返す。すると、orが短絡されずにdieが実行される。

ところで、Perlで配列の比較って組込みでないのですか?