🤔

シェルから実行できるVim scriptの書き方

2020/09/17に公開

シェルから実行でき、Vimから読み込むこともできるスクリプトを書いてみたので解説していきます。

ほとんど先人に倣っただけなので要素の解説だけ書いていきます。

ソース

#!/bin/sh

":" << finish
" vim: set ft=vim:

let s:line = getline(1)

function! s:print(obj) abort
  let obj = a:obj
  if type(obj) != v:t_string
    let obj = string(obj)
  endif
  call setline(1, obj)
  1print
endfunction

call s:print("Hello world!")

if mode() =~# "c"
  qall!
endif

" Vimから実行すると一行目が破壊されるので元に戻す
call setline(1, s:line)

finish

vim --clean -n -e -s -S $0

シバン

#!/bin/sh

シェルスクリプトを書く人にはお馴染みのおまじないです。

Vimはこれを無視してくれます。

ヒアドキュメント

":" << finish

:をダブルクォートで囲っている所がポイントです、これによりシェルでは実行されるがVimでは実行されないということを実現できるようになります。

シェルでは、複数行の文字列を楽に書ける便利な構文です。

ここでは:というコマンド(何もせずに正常終了する)に次にfinishが出てくるまでの全ての行が文字列として渡されます。

これにより以降の行に書くVim scriptがシェルから無視されるようになります。

Vimでは、ダブルクォートは全てコメント扱いになるため、この行は無視されます。

Vimの終了

if mode(1) =~# "ce"
  qall!
endif

後述しますが、シェルから呼ぶ時はExモード[1]で呼び出すので判定し、シェル経由であれば終了します。
[2]

Vim scriptの読み込み中止

finish

先程のヒアドキュメントの識別子部分に書いたfinishです。

Vimはこのコマンドが出現した時点で読み込むのを止めてくれます。

シェルからVimを実行する

vim --clean -n -e -s -S $0

--clean -nを付けることによりvimrcやプラグインの読み込みとスワップファイルの作成がカットされます。

-e -sによりバッチモード(サイレントExモード)で起動します。[3]

-S $0によりシェルで実行しているファイルがVim scriptとして読み込まれます。

脚注
  1. Qで入れるモードです、間違って入った人も多いのではないかと思います。 ↩︎

  2. Vimから実行するとmode()nを返します。 ↩︎

  3. -sが無いと余計な物が出力されます、詳しくはVimで:h -s-exを実行すると参照できます。 ↩︎

Discussion