僕はWindowsを用いる場合,KaoriYaのgvimと,Cygwinのvimを用いている. そして,Cygwinのgitを利用している. Cygwinであれば,新規に作成されるファイルのパーミッションは644であるが,Windowsだとパーミッションが700となるのが気にくわなかった. というのも,gitはファイルのパーミッションも含めて管理するし,GitHub上では実行可能なテキストファイル等(例えばLICENSE)は,シェルスクリプトのシンタックスハイライトが適用されるからだ.
無意味な実行権限の付与は避けたいので,Windows環境でVimで新規ファイルを作成するときに,Cygwin等のchmodを呼び出し,ファイルのパーミッションを変更する処理を加えることにした. ただし,ファイル先頭がshebang行であるならば,パーミッションを755にする.
function! s:system(cmd) try call vimproc#cmd#system(a:cmd) catch /^Vim(call)\=:E117: .\+: vimproc#cmd#system$/ call system(a:cmd) endtry endfunction if executable('chmod') augroup Permission autocmd! augroup END if has('win95') || has('win16') || has('win32') || has('win64') autocmd Permission BufNewFile * \ autocmd Permission BufWritePost <buffer> call s:permission_644() function! s:permission_644() autocmd! Permission BufWritePost <buffer> silent! call s:system((getline(1)[0 : 1] ==# '#!' ? 'chmod 755 ' : 'chmod 644 ') \ . shellescape(expand('%'))) endfunction else autocmd Permission BufNewFile * \ autocmd Permission BufWritePost <buffer> call s:add_permission_x() function! s:add_permission_x() autocmd! Permission BufWritePost <buffer> if getline(1)[0 : 1] ==# '#!' silent! call s:system('chmod a+x ' . shellescape(expand('%'))) endif endfunction autocmd MyAutoCmd BufWritePost * call s:add_permission_x() endif endif
元ネタは,shebang付きファイルに実行権限を与える設定である. 以下の記事あたりが参考例だろう.
しかし,既存のファイルの実行権限を勝手に変更してしまうのもどうかと思ったので(例えshebang付きであっても),「新規ファイル作成時のみ」そのパーミッションを変更するようにした. 仕組みとしては以下のようになる.
- 存在しないファイルの編集を始めたとき(
BufNewFile
が発火したとき)に,バッファローカルでバッファ全体をファイルに書き込んだ後に発火するイベント(BufWritePost
)に対し,パーミッションを変更する関数を呼び出すアクションを設定する - パーミッションを変更する関数では,最初に
BufWritePost
に対して設定された自動コマンドを消去し,パーミッションを変更する外部コマンドをsystem()
を通じて呼び出す.
BufNewFile
時にBufWritePost
の自動コマンドを設定しているのがポイントだ.
こうすることで,新規ファイルの保存時のみパーミッションを変更することができる.
ただし,writefile()
等でのファイルのパーミッションの変更には対応していない.
これらは,個別にスクリプト中やコマンドを実行して対応すべきだろう.
(vital.vimの:Vitalize
をWindowsのVimでやると,実行権限が付いてしまうので,Cygwinのvimで:Vitalize
しよう)
s:system()
については,組み込み関数のsystem()
でも構わないが,Windowsだと一瞬コマンドプロンプトのウインドウが開くのが気になるので,vimproc.vimがインストールされているならば,そのsystem()
を用いることにする.
vimproc#system()
とvimproc#cmd#system()
の違いについては,vimproc.vimのソースコードを参照するか,以下を参照して欲しい.
- Windows の Vim で system() を高速化してみた - C++でゲームプログラミング
- vimproc.vim に vimproc#cmd#system が実装された - C++でゲームプログラミング