일반적으로 vim에서 사용자 키설정은 아래와 같이 한다.

nnoremap n nzzzv

위는 normal 모드에서 n을 누르면 nzzzv를 누른 것과 같이 동작하라는 뜻이다. (noremap은 재귀적인 mapping 방지를 위해 사용)

그런데 동적으로 특정 조건에 따라 다르게 동작하는 키설정을 할 수도 있다!

map-<expr>을 이용하면 된다. (:help map-<expr> 을 ) expr은 expression을 인자로 쓸 수 있게 해주는데, 해당 expression을 조건식으로 해주면 아래와 같은 것이 가능하다.

*아래는 재미를 위한 단순 예시이다.

nnoremap <expr> n (rand() % 2 == 0) ? ':echo "even"<CR>' : ':echo "odd"<CR>'

n을 누르면, 랜덤 값이 짝수인지 홀수인지 확인해 각각에 따라 왼쪽 하단에 even 혹은 odd 메세지가 뜨게 된다. 아무래도 가독성을 위해서는 뒤의 3항연산자 부분을 함수로 빼는 게 나은 것 같다.

nnoremap <expr> n CheckEven()

func CheckEven()
	let randValue = rand()
	if (randValue % 2 == 0)
		:echo "even"
		return
	else
		:echo "odd"
		return
	endif
endfunction

현 상황에 따라 다르게 동작하게 하고 싶을 때 응용가능할 것 같다. 예를 들면 특정 옵션이 켜져있으면 끄고, 꺼져있으면 켜는 식으로 왔다갔다하거나, 특정 창이 켜져있으면 그쪽으로 전환하고, 없으면 새로 여는 식으로 한다거나….

터미널 버퍼를 자주 쓰는지라 현재 이런식으로 활용하고 있다.(진짜 대충 만든 설정이지만..) 터미널이 켜져있으면 해당 창으로 전환하고, 없으면 하나를 새로 연다.

nnoremap <expr> <leader>tt (len(filter(map(getbufinfo(), 'v:val.bufnr'), 'getbufvar(v:val, "&buftype") is# "terminal"')) > 0) ? ':vs<CR><C-W>l:b term<CR>' : ':vs<CR><C-W>l:term<CR>'

레퍼런스:

Vim: map.txt