はてなへの書き込み

このエントリーをはてなブックマークに追加

はてな記法だと,改行するたびにpタグが挿入されてしまいますね... Emacs Museとかと同じほうが書きやすいように思う.
そこで,以下を行うPerlスクリプトを作ってみた.

  • xxx-20YY-MM-DD.txt 等のファイルをまとめて,20YY-MM-DD.txt を作成する.
    • 20YY-MM-DD.txt のタイムスタンプがxxx-20YY-MM-DD.txt 等および includeされるファイルよりも新しければ作成しない.
  • <include "ファイル名"> と記述すれば,ファイルを挿入できる.
    • 再帰的な挿入には対応していない.
  • 先頭に空白文字がある行は,空白を取り除いて前の行に連結される.
    • ただし空白文字の直後が英数字の場合は,空白を残す.
  • 「>##」のみの行があれば,行連結しないモードになる.「##<」のみの行があれば,行連結するモードに戻る.
    • 入れ子になっていても大丈夫なはず.

20YY-MM-DD.txt が作成されたら,「はてダラ」を使ってアップロードすれば良い.

2010-02-14 付記
d:id:tamura70:20100214:hatena を参照

リンク

記述例

				   
* 見出し
これはテストです.
  これは上に連結される.
これは,別の行になる.

- 項目の説明も
  連結される.
- English words are
  concatinated with a space.

以下は,ファイル挿入の例.
>##
>|
&lt;include "h-assemble-main.c"&gt;
|<
##<

変換結果

* 見出し
これはテストです.これは上に連結される.
これは,別の行になる.

- 項目の説明も連結される.
- English words are  concatinated with a space.

以下は,ファイル挿入の例.
>|
int main(void) {
    return 0;
}
|<

h-assemble.pl

#!/usr/bin/perl
use strict;
use Getopt::Std;
use Jcode;

use vars qw($opt_s $opt_o $opt_c $opt_p $opt_q);
&getopts("s:o:c:p:q:");

my $source = $opt_s || ".";
my $output = $opt_o || "output";
my $encode = $opt_c || "euc";
my $pretag0 = $opt_p || ">##";
my $pretag1 = $opt_q || "##<";

my $line = "";
my $pre = 0;
&assemble_diaries();
exit 0;

sub assemble_diaries {
    my %diaries = ();
    foreach my $file (<$source/*.txt>) {
	if ($file !~ /\b(\d{4}-\d\d-\d\d)\.txt$/) {
	    next;
	}
	my $date = $1;
	my @d = ();
	if ($diaries{$date}) {
	    @d = @{$diaries{$date}};
	}
	push(@d, $file);
	$diaries{$date} = \@d;
    }
    foreach my $date (sort keys %diaries) {
	my $out = "$output/$date.txt";
	&assemble_diary($date, $out, @{$diaries{$date}});
    }
}

sub assemble_diary {
    my ($date, $out, @files) = @_;
    my $mtime_out = &mtime($out);
    my $modified = 0;
    foreach my $file (@files) {
	if (&newer_in($file, $mtime_out)) {
	    $modified = 1;
	    last;
	}
    }
    if ($modified) {
	print "$out <-- ", join(" ", @files), "\n";
	open(OUT, ">", $out) || die "$0: $out $!";
	foreach my $file (@files) {
	    open(IN, "<", $file) || die "$0: $file $!";
	    $line = "";
	    $pre = 0;
	    while (<IN>) {
		chomp;
		if (/^\s*<(include|source)\s+(src=)?["']?(.*?)["']?>\s*$/) {
		    my $incfile = $3;
		    open(INC, "<", $incfile) || die "$0: $incfile $!";
		    while (<INC>) {
			chomp;
			&process_line($_);
		    }
		    close(INC);
		} else {
		    &process_line($_);
		}
	    }
	    &process_line("");
	    close(IN);
	}
	close(OUT);
    }
}

sub process_line {
    my ($str) = @_;
    &Jcode::convert(\$str, $encode, undef);
    if ($str eq $pretag0) {
	print OUT $line;
	if ($pre > 0) {
	    print OUT "$str\n";
	}
	$line = "";
	$pre++;
    } elsif ($str eq $pretag1) {
	$pre--;
	if ($pre > 0) {
	    print OUT "$str\n";
	}
    } elsif ($pre) {
	print OUT "$str\n";
    } else {
	if ($str =~ /^\s+/) {
	    if ($str !~ /^\s+\w/) {
		$str =~ s/^\s+//;
	    }
	    if ($line) {
		chomp($line);
	    }
	    $line .= "$str\n";
	} else {
	    print OUT $line;
	    $line = "$str\n";
	}
    }
}

sub newer_in {
    my ($file, $mtime0) = @_;
    my $newer = 0;
    if (&mtime($file) > $mtime0) {
	$newer = 1;
    } else {
	open(IN, "<", $file) || die "$0: $file $!";
	while (<IN>) {
	    chomp;
	    if (/^\s*<include\s+(src=)?["']?(.*?)["']?>\s*$/) {
		my $include = $2;
		if (&mtime($include) > $mtime0) {
		    $newer = 1;
		    last;
		}
	    }
	}
	close(IN);
    }
    return $newer;
}

sub mtime {
    my ($file) = @_;
    my @stat = stat($file);
    my $mtime = $stat[9];
    return $mtime;
}