'encoding' and iconv
OpenWin32Explorer.vim ( http://d.hatena.ne.jp/janus_wel/20090307/1236442540 ) との絡みで。
おれは 'encoding' を utf-8 にしてるんだけどこうすると cmd.exe 経由での command で、つまり外部 command 全般で日本語がまともに通らない ( あーでもこれ Windows XP までの現象なのかな ? Vista とかいじったことないからわかんないな ) 。で、これをどうやって通すかというアレで。
おれが至った結論は cmd.exe に渡す文字列をあらかじめ iconv で system default の encoding に直してやる、ってことなんだけどこれだと 2 つの前提条件がいるんだよね。
- iconv support
- vim で character encoding を変換するには iconv らしい。まぁ UNIX / Linux 発祥の文化だからこれが自然なのかもしれんけど Windows だともちろん iconv とか out of choice というか自力でいれることのない software のひとつなわけなんだけど ( 変換なんかは editor の機能に任せた方が手っ取り早い ) 。
- でも Kaoriya さんとこの gvim は普通に support しているのでたぶん日本国内ではこの点は大丈夫。
- 一応、 iconv support しているかは :echo has('iconv') で調べられる。
- cmd.exe が受け付ける encoding がわかっている
- 日本語だとわかっているなら cp932 決めうちでほとんど大丈夫なんだけどそれもどうよと思ったので多言語で使えるような方法を考えてみた結果浮かんできたのは 2 つ。
- ひとつめは encoding を指定してもらう。これはある意味確実なんだけどある意味不確実なので却下。
- ふたつめの手段は 'encoding' option の default 値に期待する。 :help 'encoding' や :help encoding-values してみるとなんか大丈夫ぽい… ? のでこっちを採用。 maintainer はたぶん各言語ごとに適切な encoding を default にしてくれているはずだという淡い期待も正直入ってます。
で、ここらへんを考慮して system default の encoding に直す関数を以下のように書いてみた。必要になるまで iconv を呼ばない作りにしてるけど前提にしてしまったほうがいいかなぁ ? とりあえず意図通りに動いてくれているようなんだけど try, catch, throw が vim にもあって驚いたとか vim でこういう library につっこんでおくべき関数の扱いはどうするのが正しいんだろうとちょっと考えてみたりとかそもそも library って概念があるのかと迷ってしまったりした。
throw のタイミングで 'encoding' が default に戻ったままになるという bug があったのでちょっと変えたよ !! またまた thinca さんありがとう。
function! ConvertEncodingToSystemDefault(orig_str) let str = a:orig_str if has('multi_byte') " If 'encoding' option differ from system encoding, this " function needs iconv. In Windows, needs +iconv/dyn and " iconv.dll (libiconv.dll). See :help iconv-dynamic " error flag let error = 0 " save 'encoding' to variable let cur_encoding = &encoding " get default 'encoding' set encoding& " check if cur_encoding != &encoding " try to convert if has('iconv') let str = iconv(str, cur_encoding, &encoding) else let error = 1 endif endif " restore 'encoding' let &encoding = cur_encoding if error throw 'Feature +iconv is needed.' \ . ' See :help iconv-dynamic.' endif endif return str endfunction