選択範囲の文字を縦書き用にフォーマット
ライターとして原稿を書くとき、縦が器用に原稿を求められるときと横が器用に原稿を求められるときがあります。
実は、縦書きと横書きでは微妙に文章の表記やフォーマットが異なります(発注者により変わったりもしますが)。
横書きの場合、英数字は基本半角で入力します。一方縦書きの場合は、
Mac => マック
iPhone => アイフォーン
Windows 7 => ウィンドウズ7
Photoshop => フォトショップ
Illustrator => イラストレーター
なんて具合に書いたりします。ださいですね。でも、縦書きで半角英数字を使うともっとださいので仕方ありません。
まあそれはいいんですが、さらに面倒なのが英数字の全角・半角の使い分けです。5文字までは全角英数字はOK。6字以上は半角、とか、数字も2桁のときだけは半角にするとかいったルールがあったりします。
僕は縦書きの原稿でも、とりあえず半角英数字で書いちゃいます。でも、そのあとこうしたルールにあわせて全角、半角を調整していく作業って、正直言って面倒です。もちろん必要不可欠なのですが、そんな作業に時間食われるのもなんだかばからしく思えます。
そこで、Vimスクリプトを書いてなんとかすることにしました。といっても全角・半角の判定と変換は全部Perl任せです。用件は次の3つくらいに設定してみました。
- 5字以下の英数字(「Mac」とか)は基本的に全角に統一
- 6字以上の英数字(「Windows」とか)は半角に統一
- 2文字のみの数字(「28歳」とか)は半角に
Perlには全角と半角を変換してくれるこじゃれたモジュールもあったような気がしますが、今回は練習含め、自分で考えて作ってみました。まあ、英数字だけなんでたいしたことはありません。
以下が作成したvimスクリプトです。
function! Tategaki() range let str = getline(a:firstline, a:lastline) let firstline = a:firstline perl << EOF use utf8; use open IO => qw/:utf8 :std/; use Encode qw/encode decode/; my $str = decode('utf-8', VIM::Eval('str')); my $firstline = VIM::Eval('firstline'); my $han_str = " 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; my $zen_str = " 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; my $eisu = "[ 0-9a-zA-Z]"; my $zen_eisu = "[ 0-9a-zA-Z]"; my $zen_suji = "[0-9]"; 1 while $str =~ s/($eisu+)/get_str($1)/e; 1 while $str =~ s/($zen_eisu{6,})/get_str($1)/e; 1 while $str =~ s/(?<!$zen_suji)($zen_suji{2})(?!$zen_suji)/get_str($1)/e; sub get_str { my ($key) = @_; my $res =""; if ($key =~ m|$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, split /\n/, $str); EOF execute "normal " . a:lastline . "gg" endfunction
Perlの正規表現でeオプションを使うと、関数を評価して置換文字列を生成してくれるみたいです。引数もとれるので、マッチした文字列を自分ルールでいじり倒せます。今回は半角→全角、全角→半角しかしていませんが、正直なんでもできそう。
全角・半角の相互変換は、indexとsubstrを使ってやってみました。めっちゃ適当です。アナグラマーなんで仕方ないです。
でも意外にうまく動いてくれてます。