はじめに

Vimのプラグインを作成していて、「動的に生成された文字列をバッファに挿入する」といった機能を実装することがあると思います。たとえば、私はuuidというUUIDを生成するためのCLIツールを作成していて、それをVim scriptから呼んで現在開いているバッファに挿入するといったプラグインを作成しています。その際に生成したUUIDを「カーソルの下に改行しないで挿入する」ということがやりたかったのですが、ちょっとだけ回りくどいやり方になってしまいました。

:exe(execute)を使う

上記のuuidではカーソルの後から文字列を挿入するために、以下のようなVim scriptを書いています。

function! Generate_uuid() abort
  let l:uuid = system('uuid')
  execute "normal! a".uuid."\<esc>"
endfunction

command! -count -nargs=* UUID call Generate_uuid()

uuidコマンドの実行結果を受け取った変数を、executeの中で実行しているnormalコマンドへ渡している簡単なスクリプトです。:exe:exe {expr} ..の形式で実行し、{expr}で評価された文字列をExコマンドとして実行することができます。

:help execute

				:exe :execute
:exe[cute] {expr1} ..	Executes the string that results from the evaluation
			of {expr1} as an Ex command.

ポイントは以下の部分です。

execute "normal! a".uuid."\<esc>"

以下の3つのことをやっています

  • 現在のカーソルの場所でaキーでインサートモードに入る(ブロックカーソルの右からインサートモードに入る)
  • uuidに代入されている値を入力
  • escキーでノーマルモードに戻る

ほかのやり方は…

文字列を挿入するだけなのに、やり方が回りくどいと思われたかもしれませんが、現状の調査ではこれ以外の方法が見つかりませんでした。VimのExコマンドに:putがあるのですが、これは改行してから文字列を挿入してしまうため、""の中にUUIDを挿入するといったことができません。

:help :put

                                :pu :put
:[line]pu[t] [x]	Put the text [from register x] after [line] (default
                    current line).  This always works |linewise|, thus
                    this command can be used to put a yanked block as new
                    lines.

あとは:read !uuidとするとuuidを実行してその出力結果をバッファに挿入することができますが、これも:putと同様に改行されてしまいます。

:help :read

                                :r :re :read
:r[ead] [++opt] [name]
			Insert the file [name] (default: current file) below
			the cursor.
			See |++opt| for the possible values of [++opt].

おわりに

任意の箇所に改行なしで文字列を挿入できるExコマンドが見つからなくて、少し回りくどい方法をとってしまったという話でした。

参考