Vimで選択範囲の文字数をカウントする
ライター/編集に必須の文字数チェック
原稿やブログの記事を書くときは、いつもVim(GVim)を使っています。
原稿をちょこちょこっと直したり、正規表現で文字列を修正したりといったことがスムーズにできるのがいいですね。
しかし、ライティングになくてはならない文字数のカウント機能がVimにはありません。また、論理行数も目視で数えないといけません。行数が多くなるとこれも面倒です。
ウェブの記事では、正確に文字数や行数を求められることはあまりありません。一方、1ページあたりのスペースが有限な書籍では、結構シビアに文字数を調整する必要があります。特に、フォーマットががちがちに決まったカタログものでは必須です。
Vimスクリプトだけど、Perlで文字数と行数を計算
以上のような理由で、選択範囲の文字数と論理行数を計算するVimスクリプトを書いてみることにしました。ただ、Vimスクリプト上で2バイト文字と1バイト文字を見分けて計算するという方法がわからなかったので、実際の処理はPerlを使用しています。
Perlインターフェイスといって、Vimから直接Perlスクリプトを実行できる仕組みがあるようです。下記の記事はPythonのものですが、使い方はPerlもPythonも大して変わらないので、十分参考になるかと思います。
Vim-users.jp - Hack #132: Pythonインタフェースを使う(1)
Vim-users.jp - Hack #136: Pythonインタフェースを使う(2)
あとは、
h perl
でヘルプを覗いてみてください。
文字数は、半角英数記号は2文字で1文字分として計算しています。論理行は、カレントウィンドウのウィンドウ幅で文字数を除算することで割り出しています。
ここら辺の仕組みは、あまり好ましくない方法をとっているかもしれません。
function! Count_Char() range let str = getline(a:firstline, a:lastline) if line('$') > 1000 let stable = 5 else let stable = 4 endif let word_of_line = winwidth(0) - stable perl << EOF use strict; use warnings; use utf8; use feature qw/say switch/; use open IO => qw/:utf8 :std/; use Encode qw/encode decode/; # 日本語文字列を渡すときはdecodeしないと化ける my $str = decode('utf-8', VIM::Eval('str')); my $line = 0; my $word_of_line = VIM::Eval('word_of_line') / 2; my $gross_words = 0; foreach (split /\n/, $str) { # 1行あたりの文字数のカウント my @char = m|\p{InBasicLatin}|g; my @wide = m|\P{InBasicLatin}|g; my $num_char = int (($#char + 1) / 2 + 0.5); my $num_wide = $#wide + 1; # 行数の計算。 my $test = ($num_char + $num_wide) / $word_of_line; # 正規表現で行数を判定。整数以外は+1して丸める。 if ($test =~ /^\d+$/) { $line += $test; } else { $line += int ($test + 1); } # 合計文字数の計算 $gross_words += $num_char + $num_wide; } VIM::Msg("現在の一行の文字数は $word_of_line です"); VIM::Msg("選択範囲の論理行数は $line ライン分です"); VIM::Msg("選択範囲の総文字数は $gross_words です"); EOF endfunction