0
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

WindowsとPowershellとvimとdiffと私

Last updated at Posted at 2018-05-31

個人的にもう前時代感あふれるcmd.exeなんて使いたくないPowershellが好きなのでvimでもset shell=powershellしているんですけど、どうしても一部機能でトラブルが起きがちで、今回はdiffがどうしても動かなかったのでなんとかした話です。

結果が見たいわ!その子のソースを見せてちょうだい!

vimrc
" diff関連
if has ('win32')
	set diffexpr=MyDiff()
endif

function! MyDiff()
	let opt = ""
	if &diffopt =~ "icase"
		let opt = opt . "-i "
	endif
	if &diffopt =~ "iwhite"
		let opt = opt . "-b "
	endif
	silent execute '!C:\path\to\diff.exe -a --binary ' . opt . v:fname_in . ' ' . v:fname_new . '" > "' . v:fname_out
endfunction

どうしてこんなことになってしまったんだ…

問題はおそらく2つに絞られます。

  • Powershellがdiff=>Compare-Objectへのエイリアスを既に張っている
  • Vimでset shell=Powershellした際にリダイレクトとquoteの関係がおかしい

屋上に行こうぜ

まず前者に関しては、Powershellのエイリアスを消すとか、苦情のメールを入れるなどでも対応できるかと思われますが、「あるものはできるだけ残す」という個人的なポリシーと、結局vimrc書けば済むとわかったのでそちらで解決します。幸い、ヘルプにサンプル関数があるので1、そのまま持ってきてそれから考えます。

MyDiff()
set diffexpr=MyDiff()
function MyDiff()
	let opt = ""
	if &diffopt =~ "icase"
		let opt = opt . "-i "
	endif
	if &diffopt =~ "iwhite"
		let opt = opt . "-b "
	endif
	silent execute "!diff -a --binary " . opt . v:fname_in . " " . v:fname_new .
	\  " > " . v:fname_out
endfunction

あとはこれの!diffの部分だけ使えるdiffのバイナリに変えれば解決するんですけど…

どぼぢでごんなごどずるのぉぉぉ!?

VimでPowershellを使う場合、シェル周りの設定は大体こうなるのが普通なんだそうなのでそのままこれを使っています…

vimrc
if has('win32')
	set shell=powershell
	set shellcmdflag=-c
	set shellquote=\"
	set shellxquote=
endif

これでシェルを使ってリダイレクト結果を拾うコマンドではpowershell -c "foo" > barとなって、一時ファイルもしっかり拾えるように…少なくともqiitaCtlのときは問題ないので、拾えるようになってるはずです。正直わからん。おしえてVimmer!

さておき、じゃあこのスクリプトでdiff.exeだけ書き換えてやってみると、うまくいかないんだなこれが。vimrunのウィンドウがある短い時間で見てみたんですけど…

Powershell -c "C:\path\to\diff.exe diff1.tmp diff2.tmp > out.tmp"

ファイル名はともかくだいたいこうなります…え、shellquoteは…?えぇー…

わたしこれ嫌い!

冷静に考えたら関数内でリダイレクト処理書いちゃってるのでこうなるのが当然なんですよね…しょうがないので嫌いな類の解決方法で強引に乗り切ったのが最初のソースになります。要はシェルに送る文字列の中で強引にquoteを切って解決しました。エレガントじゃないなぁ…

おしえてVimmer!

実際コレどうなんです?なんかもっとエレガントな解決方法ある気がしてならないんですよ。某名無しさん曰く、まだ危ないエイリアスがあるらしいので、シェル起動時に環境変数放り込んでPowershell側のprofileで予めエイリアス切る条件分岐を仕込むとか、そもそもshellquoteの設定とdiffexprの設定で気がついてないところがあって、実は上手くやればdiffexprだけでなんとかなるとか…正直Vimの設定群を追いかけきれてないのでこの方法に自信がないです。

編集中に気がついたvim操作関係のこと

  • 毎度<C-r>+をして酷い目に遭うので<C-g>uする癖をちゃんとつけること。
  1. :h diff-diffexprを参照のこと

0
4
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?