четверг, 21 июля 2011 г.

Фуригана для emacs

Искал я неделю назад способ рендера фуриганы для емакса и нашел готовое решение только у пакета lookup которое умеет в aozora bunko, то есть читать скачанные книжки с фуриганой, жаль только в картинки не может, зато делает вполне читаемый преформат текста. Все равно учу японский с емаксом, и иногда охота нормально почитать текст не залезая в словарь или ломая глаза от транслита kakasi. Потому родился скрипт который пропускает текст через mecab и вставляет где нужно фуригану не ломая форматирование и текст. Mecab желательно использовать в кодировке utf-8 так как лень тестить было параметр --encode ну и стандартные словари ipadic а не  jumandic. Также не люблю я когда овердохуя фуриганы на слова которые очень часто в тексте попадаются, я думаю достаточно что бы после 1 раза уже не было фуриганы для слова. Этого можно добиться с параметром --trash, ставим в 0 чтобы всегда была фуригана или другое что бы задать когда в следующий раз делать фуригану для того же слова.

#!/usr/bin/perl -w
# -*-coding: utf-8 -*-

use File::Path;
use File::Basename;

use warnings;
#use strict;
use utf8;

binmode STDOUT, "utf8";

$opt_help = 0;
$opt_file = "";
$opt_encode = "utf-8";
$opt_brace = "《》";
$opt_trash = 120;
$opt_trashword = 0;
$ok = GetOptions("help", "file=s", "encode=s", "brace=s", "trash=s",
    "trashword");

if (!$ok)
{
    print $ok;
    exit;
}

if ($opt_help) {
    print "
Usage: hurigana.pl [Options...]
  --file  <file>          Input file.
  --encode <code system>  Mecab encode. Input file's coding system must be same as mecab.
                          Usually utf-8 or euc-jp (Def utf-8). Output is utf-8.
  --brace <braces>        Furigana braces (Default for aozora - \"《》\")
  --trash <number>        Number of symbols when next furigana will be shown (Def. 120)
  --trashword             Allow trashing end of long word (Default off)

Note: You need mecab+ipadic not jumandic.
";
    exit;
}

sub kata2hira
{
    my (@input) = @_;
    for (@input) {tr/ァ-ン/ぁ-ん/}
    return wantarray ? @input : "@input";
}

my @kanji = ();

if ($opt_file) {

    my $mecab_output = "mecab-out-tmp.txt";

    system ("mecab ${opt_file} > $mecab_output");

    # mecab euc-jp?
    open my $mecab_out_tmp, "<:encoding(${opt_encode})", $mecab_output || die ("Could not open mecab output file");

    while (<$mecab_out_tmp>) {
        if (/^(\w+)\s*(?:[^,]*,){8}([ア-ンー]+)\s*$/) {
            my $hiragana = kata2hira($2);
            if ($1=~/(\p{InCJKUnifiedIdeographs}+)(.*)/)
            {
                my @pr = ($1, substr($hiragana, 0, length($hiragana) - length($2)));
                push(@kanji, \@pr);
            }
        }
    }

    open(DAT, "<:encoding(${opt_encode})", ${opt_file}) || die("Could not open file!"); 
    my $text=join "",<DAT>;
    close DAT;

    my $res = "";
    my $bropen = substr($opt_brace, 0, 1);
    my $brclose = substr($opt_brace, 1, 1);
    my %kanjitrash;
    my %kanjihira;
    foreach my $k (@kanji) {
        $kan = ${$k}[0];
        $hira = ${$k}[1];
        if ($text =~m/(.*?${$k}[0])(.*)/s) {
            my $lasttrash = 0;
            if (exists $kanjitrash{$kan}) {
                $lasttrash = $kanjitrash{$kan};
            }
            $newtrash = length($res);
            $head = $1;
            $tail = $2;
            if (
                # force furigana if before and after current word is kanji
                substr($tail, 0,1) =~m/\p{InCJKUnifiedIdeographs}+/ ||
                (!$opt_trashword && length($head) == length($kan)) ||
                # kanji trash - number of symbols for next furigana for same word
                $lasttrash == 0 || $hira ne $kanjihira{$kan} ||
                $newtrash - $lasttrash > $opt_trash)
            {
                
                $res = $res . $head . $bropen . $hira . $brclose;
                $kanjitrash{$kan} = $newtrash;
                $kanjihira{$kan} = $hira;
            } else {
                $res = $res. $head;
            }
            $text = $tail;
        }
    }
    
    print "$res$text\n";
    # clean
    unlink $mecab_output;
}

Сохраняем в hurigana.pl и запускае:


./hurigana.pl --file /tmp/haruhi_1_utf-8.txt --trash 2000 > /tmp/haruhi1.txt 

Дальше в емаксе открываем haruhi1.txt и делаем
M-x aozora-view



2 комментария:

  1. Хорошо зделано, умно.
    Теперь про ШРИФТЫ напиши.

    ОтветитьУдалить
  2. Напишу, но там скорей о емаксе и его шрифтах, все сильно зависит от приложения, теже браузера стараются брать тот шрифт что рекомендуется стилем странички.
    а так на вскидку
    %ls ~/.fonts
    Anonymous Pro B.ttf
    Anonymous Pro BI.ttf
    Anonymous Pro I.ttf
    Anonymous Pro.ttf
    DroidSansMono.ttf
    HanaMinA.ttf
    HanaMinB.ttf
    HiraKakuPro W3.otf
    HiraMaruPro-W4.otf
    HiraMinPro-W3.otf
    Inconsolata.otf
    KozGoPr6N-Regular.otf
    KozMinPr6N-Regular.otf
    Quivira.ttf
    andalemo.TTF
    code2000.ttf
    fonts.dir
    hanaminotxpron-regular.otf
    meiryo.ttc
    meiryob.ttc

    ОтветитьУдалить