1. HOME»
  2. ソフトウェア»
  3. テキストエディタ»
  4. Vim»
  5. Vimで括弧とクォーテーションの最強補完機能を自作しよう!

Vimで括弧とクォーテーションの最強補完機能を自作しよう!

ここまでで、括弧やクォーテーション補完に必要な機能を作りました。
このページでは、ここまでで作った機能を使って、まずは括弧の補完機能を作ります。

目次
  1. 閉じ括弧を自動入力
  2. 閉じ括弧を入力したときの動きを変更
  3. クォーテーションの入力
  4. 改行(return, enter)の入力
  5. スペース(space)の入力
  6. 削除キー(delete, backspace)の入力

閉じ括弧を自動入力

まず、括弧を入力したときに、それに対応した閉じ括弧を自動的に入力するようにします。

Vimで閉じ括弧を自動入力

しかし、ただ閉じ括弧を自動的に入力するだけでは、使いにくいものになってしまいます。
そこで、3つの条件をクリアしたときのみ、自動的に閉じ括弧を入力するようにします。

  • カーソルの後ろの文字が、なにもないとき(行末のとき)
  • カーソルの後ろの文字が、閉じ括弧のとき
  • カーソルの後ろの文字が、空白のとき(半角スペースのとき)

上記のような条件をつけることで、とても使いやすくなります。

さらに、閉じ括弧の入力後は、カーソルを括弧の中に移動したいです。
そうすることで、括弧を入力したあと、わざわざカーソルをひとつ戻すことなく、そのまま入力を続けることができます。

"括弧の入力
function! InputParentheses(parenthesis) abort
	let l:nextChar = GetNextString(1)
	let l:prevChar = GetPrevString(1)
	let l:parentheses = { "{": "}", "[": "]", "(": ")" }

	let l:nextCharIsEmpty = (l:nextChar == "")
	let l:nextCharIsCloseParenthesis = (l:nextChar == "}" || l:nextChar == "]" || l:nextChar == ")")
	let l:nextCharIsSpace = (l:nextChar == " ")

	if l:nextCharIsEmpty || l:nextCharIsCloseParenthesis || l:nextCharIsSpace
		return a:parenthesis.l:parentheses[a:parenthesis]."\<LEFT>"
	else
		return a:parenthesis
	endif
endfunction

また、この関数は括弧を入力したときに呼び出したいので、以下のものも追加します。

inoremap <expr> { InputParentheses("{")
inoremap <expr> [ InputParentheses("[")
inoremap <expr> ( InputParentheses("(")

閉じ括弧を入力したときの動きを変更

つづいて、閉じ括弧の入力のときも、そのままではちょっと使いにくいです。

プログラミングをしていると、括弧の中になにも入力しないことはよくあります。
そのときは、括弧の入力時にカーソルが括弧の中に移動する機能が、煩わしく感じるときがあるんです。

方向キーの右を押す手もありますが、Vimでは方向キーを使ってはいけないのです。(たぶん諸説あり)

そこで、カーソルの後ろに閉じ括弧がある場合のみ、閉じ括弧が入力されずにカーソルが右に動く、というふうにしていきます。

Vimで閉じ括弧を入力したときの動きを変更

では、作っていきましょう。

"閉じ括弧の入力
function! InputCloseParenthesis(parenthesis) abort
	let l:nextChar = GetNextString(1)
	if l:nextChar == a:parenthesis
		return "\<RIGHT>"
	else
		return a:parenthesis
	endif
endfunction

引数には、入力する閉じ括弧を指定します。

また、この関数は閉じ括弧を入力したときに呼び出したいので、以下のものも追加します。

inoremap <expr> } InputCloseParenthesis("}")
inoremap <expr> ] InputCloseParenthesis("]")
inoremap <expr> ) InputCloseParenthesis(")")

クォーテーションの入力

つづいて、クォーテーションを入力したときの補完機能を作っていきます。

Vimでのクォーテーションの入力

クォーテーションの入力は、括弧の入力のときよりも、ほんの少し複雑になります。

では、クォーテーションを入力するときの条件を確認しておきましょう。
今回、クォーテーションの入力は、以下のような条件にしました。

  • カーソルの左右にクォーテーションがあるとき、カーソルを右に移動する
  • カーソルの前の文字が、アルファベット、数字、全角文字、クォーテーションのとき、クォーテーションを入力
  • カーソルの後ろの文字が、空(行末)、閉じ括弧、空白(半角スペース)のとき、クォーテーションを2つ入力してカーソルを中心に移動する
  • 上記のどれでもないときも、クォーテーションを入力
"クォーテーションの入力
function! InputQuot(quot) abort
	let l:nextChar = GetNextString(1)
	let l:prevChar = GetPrevString(1)

	let l:cursorIsInsideQuotes = (l:prevChar == a:quot && l:nextChar == a:quot)
	let l:nextCharIsEmpty = (l:nextChar == "")
	let l:nextCharIsClosingParenthesis = (l:nextChar == "}" || l:nextChar == "]" || l:nextChar == ")")
	let l:nextCharIsSpace = (l:nextChar == " ")
	let l:prevCharIsAlphabet = IsAlphabet(l:prevChar)
	let l:prevCharIsFullWidth = IsFullWidth(l:prevChar)
	let l:prevCharIsNum = IsNum(l:prevChar)
	let l:prevCharIsQuot = (l:prevChar == "\'" || l:prevChar == "\"" || l:prevChar == "\`")

	if l:cursorIsInsideQuotes
		return "\<RIGHT>"
	elseif l:prevCharIsAlphabet || l:prevCharIsNum || l:prevCharIsFullWidth || l:prevCharIsQuot
		return a:quot
	elseif l:nextCharIsEmpty || l:nextCharIsClosingParenthesis || l:nextCharIsSpace
		return a:quot.a:quot."\<LEFT>"
	else
		return a:quot
	endif
endfunction

また、クォーテーションが入力されたときに、この関数を呼び出すように、以下のものを追加します。

inoremap <expr> ' InputQuot("\'")
inoremap <expr> " InputQuot("\"")
inoremap <expr> ` InputQuot("\`")

改行(return, enter)の入力

つづいて、改行(return, enter)が入力されたときの補完機能を作っていきます。

Vimでの改行の入力

どういったものを作りたいのかというと、カーソルが括弧で挟まれているとき、改行すると閉じ括弧がもう1段下にいき、括弧の間の行にカーソルが来るようにしたいのです。

これを作ると、つぎのようになります。

"改行の入力
function! InputCR() abort
	let l:nextChar = GetNextString(1)
	let l:prevChar = GetPrevString(1)
	let l:cursorIsInsideParentheses = IsInsideParentheses(l:prevChar,l:nextChar)

	if l:cursorIsInsideParentheses
		return "\<CR>\<ESC>\<S-o>"
	else
		return "\<CR>"
	endif
endfunction

また、returnやenterが押されたときに、この関数を呼び出すように、次のものを追加します。

inoremap <expr> <CR> InputCR()

スペース(space)の入力

つづいて、スペースキーが入力されたときの補完機能を作っていきます。

Vimでのスペースの入力

プログラミングをしていると、括弧の内側の両端にスペースを入れたいときがあると思います。
これは、人によっては見づらいと感じるかもしれませんが、私はこのスペース、見やすくて好きです。

そこで、カーソルの前後の括弧があるときスペースを入力すると、2つスペースが入力され、カーソルがその中心に移動するようにしたいと思います。

"スペースキーの入力
function! InputSpace() abort
	let l:nextChar = GetNextString(1)
	let l:prevChar = GetPrevString(1)
	let l:cursorIsInsideParentheses = IsInsideParentheses(l:prevChar,l:nextChar)

	if l:cursorIsInsideParentheses
		return "\<Space>\<Space>\<LEFT>"
	else
		return "\<Space>"
	endif
endfunction

スペースキーが押されたとき、この関数を呼び出すようにするため、つぎのものを追加します。

inoremap <expr> <Space> InputSpace()

削除キー(delete, backspace)の入力

つづいて、削除キー(delete, backspace)が入力されたときの補完機能です。

Vimでの削除キーの入力

さきほど、括弧を入力するとき、自動的に閉じ括弧が入力されるようにしました。
さらに、括弧のなかでスペースを入力すると、カーソルの前後にスペースが入力されるようにもしました。

もちろん、それを削除するときも、カーソル前後のスペースや括弧を、一度に削除したいですよね。

"バックスペースの入力
function! InputBS() abort
	let l:nextChar = GetNextString(1)
	let l:prevChar = GetPrevString(1)
	let l:nextTwoString = GetNextString(2)
	let l:prevTwoString = GetPrevString(2)

	let l:cursorIsInsideParentheses = IsInsideParentheses(l:prevChar,l:nextChar)

	let l:cursorIsInsideSpace1 = (l:prevTwoString == "{ " && l:nextTwoString == " }")
	let l:cursorIsInsideSpace2 = (l:prevTwoString == "[ " && l:nextTwoString == " ]")
	let l:cursorIsInsideSpace3 = (l:prevTwoString == "( " && l:nextTwoString == " )")
	let l:cursorIsInsideSpace = (l:cursorIsInsideSpace1 || l:cursorIsInsideSpace2 || l:cursorIsInsideSpace3)

	let l:existsQuot = (l:prevChar == "'" && l:nextChar == "'")
	let l:existsDoubleQuot = (l:prevChar == "\"" && l:nextChar == "\"")

	if l:cursorIsInsideParentheses || l:cursorIsInsideSpace || l:existsQuot || l:existsDoubleQuot
		return "\<BS>\<RIGHT>\<BS>"
	else
		return "\<BS>"
	endif
endfunction

さらに、削除キーが押されたときにこの関数を呼び出すように、つぎのものを追加します。

inoremap <expr> <BS> InputBS()

また、この機能を使うためには、以下のものを追加して、バックスペースの機能を柔軟にしておきましょう。
多くの方は.vimrcに追加していると思います。

set backspace=indent,eol,start

つぎのページでは、括弧やクォーテーションの入力がもっと便利になるようなコマンドを追加していきます。

オリジナルゲーム.com