Humanity

Edit the world by your favorite way

Vimのシェルスクリプトのハイライトで$(...)が赤く表示される


syntax/sh.vimから。

" $(..) is not supported by sh (Bourne shell).  However, apparently
" some systems (HP?) have as their /bin/sh a (link to) Korn shell
" (ie. Posix compliant shell).  /bin/ksh should work for those
" systems too, however, so the following syntax will flag $(..) as
" an Error under /bin/sh.  By consensus of vimdev'ers!
if exists("b:is_kornshell") || exists("b:is_bash")
 syn region shCommandSub matchgroup=shCmdSubRegion start="\$("  skip='\\\\\|\\.' end=")"  contains=@shCommandSubList
 syn region shArithmetic matchgroup=shArithRegion  start="\$((" skip='\\\\\|\\.' end="))" contains=@shArithList
 syn match  shSkipInitWS contained	"^\s\+"
else
 syn region shCommandSub matchgroup=Error start="\$(" end=")" contains=@shCommandSubList
endif

$(...)は/bin/shではサポートされてないらしい。
でも大体において/bin/shは「sh」ではないしうっとうしいので
.vim/after/ftplugin/sh.vim

let b:is_bash = 1

と書いてしまった。
こうするとsyntax/sh.vimbashシンタックスハイライトをするようになるらしい。



追記:
ごめんなさい。
まったくボケたことを言ってました。
これだと解決せず依然赤く表示されたままです。
誰か教えてください。


追記2:

setf sh

するとちゃんとbashシンタックスハイライトがされるようです。
読み込まれるスクリプトのタイミングの問題?


追記3:
thincaさんから教えてもらいました。ありがとうございます!

やっぱりタイミングの問題だったようで
after/ftplugin/sh.vimだとsyntax/sh.vimのあとに読み込まれるので
b:is_bashをそこで定義しても遅いらしいです。
解決策として、b:is_bashではなく「g:is_bashを.vimrcで定義する」するようです。
syntax/sh.vimはg:is_bashが定義されていればb:is_bashを定義するようで、
こちらを設定すべきでした。
どう見てもsyntax/sh.vimを検索で適当にななめ読みしただけだとfoldに隠れて見つかりません。ほんとうに(ry
というかsyntaxのhelpってなんでないの...*1


自分の場合は/bin/shでも動くようなスクリプトを書きたい場合
checkbashismsというtypoしやすいコマンドを使ってbashの機能に依存してないかチェックしてる。
でもこれはあくまで/bin/shで動くスクリプトを書くためのものではなくて、
bashの機能に依存してるかチェックするコマンドなので不完全といえば不完全なんだけど。

まぁ普通にbash使うかPerlとかで書いたほうがよっぽど楽だけど、
そういう修行ということにする。

*1:少しあるけど、デフォルトのsyntaxファイルの、それも限られたものにしかない。本家がそんな調子なのでsyntaxファイル書いてもdocがついてるのとか見たことありません。あるかもしれないけど。