読者です 読者をやめる 読者になる 読者になる

さわだのノート

書籍のお仕事に役立つかもしれない思いつきを記録しています。

RSS: 記事の更新情報 Rss Feed

縦書きフォーマット変更スクリプト修正版

追記:もうちょい改良しました => 原稿の縦書き整形スクリプトを修正 - takepierrot Editor Note


先日、縦書きフォーマットように半角英数字を変換するvimスクリプトを書きました。

選択範囲の文字を縦書き用にフォーマット - takepierrotのメモ
このスクリプト、英数字をいったんすべて全角に変換後、6文字以上の英数字を半角に戻すという形で処理しています。

しかし、行頭に全角スペース+英数字が入る場合、スペースに誤爆して5文字の英数字を6文字のスペース入り英数字と謝って判定。本来全角に変換すべきところが、半角に処理されてしまっていました。しかも、行頭のスペースも半角に変換されています。

 ENIACプロジェクト		//本来こうなるべきがENIACプロジェクト		//このように変換されてしまう

これは微妙……ということで修正版を作ってみました。
基本的なロジックは前のと同じですが、取得したテキストデータを"\n"でsplitしてから置換を行っています。行頭のスペース+英数字の判定処理をしやすくするのが目的です。

function! Tategaki() range
    let str = getline(a:firstline, a:lastline)
    let firstline = a:firstline

perl << EOF
use strict;
use warnings;
use utf8;

use open IO => qw/:utf8 :std/;
use Encode qw/encode decode/;

my $text = decode('utf-8', VIM::Eval('str'));
my $firstline = VIM::Eval('firstline');

my $han_str = " 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
my $zen_str = " 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";

my $han_eisu = "[ 0-9a-zA-Z]";
my $zen_eisu = "[ 0-9a-zA-Z]";
my $zen_suji = "[0-9]";

my @list = ();

foreach my $str (split /\n/, $text) {
    1 while $str =~ s/($han_eisu+)/get_str($1)/e;
    1 while $str =~ s/($zen_eisu{6,})/get_str($1)/e;
    1 while $str =~ s/^ \K($han_eisu{1,5})/get_str($1)/e;
    1 while $str =~ s/(?<!$zen_suji)($zen_suji{2})(?!$zen_suji)/get_str($1)/e;
    $str =~ s/^ /<e3><80><80>/;
    # ↑文字化けしてますが全角スペースに置換しています

    push @list, $str;
}

sub get_str {
    my $key = shift;
    my $res ="";
    if ($key =~ m|$han_eisu+|) {
        for my $x (split //, $key){
            my $num = index $han_str, $x;
            $res .= substr $zen_str, $num, 1;
        }
    } else {
        for my $x (split //, $key){
            my $num = index $zen_str, $x;
            $res .= substr $han_str, $num, 1;
        }
    }
    return $res;
}

$main::curbuf->Set($firstline, @list);
EOF

execute "normal " . a:lastline . "gg"
endfunction

気になったのですが、正規表現の検索文字列の指定で

$han_eisu{,5}

と入力するとエラーが出ますね。なんかハッシュと判定されたみたいです。
面倒ですが、

$han_eisu{1,5}

と指定すると、問題なく動作しました。
VimPerlインターフェイスはエラーが出ないので問題点がわかりにくいですね。