(Vim) 선택영역을 괄호로 둘러싸기

텍스트나 코드를 편집할 때 종종 특정 단어나 영역을 괄호, 따옴표 등으로 둘러싸야 하는 경우가 있다. 이런 경우 보통 영역선택 > 잘라내기 > ( ) 입력 > 괄호내부에 붙여넣기 하는 식으로 편집하게 된다. 편집기에 따라서는 영역을 선택하고 ( 만 입력하면 자동으로 선택 영역 뒤에 )를 붙여주는 경우도 있다. 이런 기능을 vim에서 키 맵으로 만들어보자.

노멀모드에서

개인적으로는 노멀모드에서 <Leader>)를 입력해서 현재 커서가 위치한 단어 주위로 괄호를 삽입하는 키맵을 만들어서 쓰고 있다. 기본적인 키 시퀀스는 다음과 같다.

ciw              - 현재 위치한 단어를 지우고 편집모드로 진입
   (             - 여는 괄호를 삽입
    <C-r>"       - 기본레지스터를 사용해서 방금 지워진 단어를 다시 입력
          )      - 닫는 괄호를 삽입
           <Esc> - 편집모드 종료

이렇게하면 커서가 있던 단어 주위로 괄호가 추가되고 커서의 위치는 닫는 괄호에 오게 된다. 이를 응용하면 대/중괄호 및 따옴표 등에 대해서도 둘러싸기 기능을 정의할 수 있다.

nnoremap <Leader>) ciw(<C-r>")<Esc>
nnoremap <Leader>} ciw{<C-r>"}<Esc>
nnoremap <Leader>] ciw[<C-r>"]<Esc>
nnoremap <Leader>> ciw<<C-r>"><Esc>
nnoremap <Leader>" ciw"<C-r>""<Esc>
nnoremap <Leader>' ciw'<C-r>"'<Esc>
nnoremap <Leader>* ciw*<C-r>"*<Esc>

비주얼 모드에서

이 동작은 visual 모드에서도 거의 유사하다. 선택된 영역을 잘라내고 ( 삽입, 잘라낸 단어 삽입, ) 삽입 하면 된다.

vnoremap <Leader>) c(<C-r>")<Esc>

만약 괄호 내부의 영역에 대한 선택을 그대로 유지한채로 visual 모드로 돌아오고 싶다면 어떻게할까? gv 명령을 이용하면 이전의 선택 영역을 다시 선택할 수 있지만, 이 상황에서는 문제가 있다. 이전 선택 영역의 앞에 감싸는 글자를 넣었기 때문에 왼쪽으로 한 칸 밀린 상태로 돌아올 것이다.

사실 여기에는 작은 꼼수가 하나 있는데, 단순히 괄호와 따옴표만 사용한다면, 위 키맵 뒤에 vi)를 써서 pair 내부를 선택할 수 있다.

그래서 <, > 마크를 사용한다. 이 마크는 가장 최근 선택영역의 시작과 끝 위치를 가리킨다. 따라서 다음과 같이 키맵을 만들 수 있다. 예를 들어 캐럿(^)은 텍스트 오브젝트의 경계가 아니므로 vi^와 같은 명령을 쓸 수 없지만 아래 키 맵을 사용하면 된다.

:vnoremap <Leader>^ c^<C-r>"^<Esc>`<lv`>l

동일한 키 시퀀스를 사용하면 (, {, [, ', ", < 등에 대해서도 같은 기능을 만들 수 있다.