콘텐츠로 건너뛰기
Home » VIM의 내장 자동완성 사용하기

VIM의 내장 자동완성 사용하기

vim은 단순한 텍스트나 설정 파일을 편집하는데 사용할 수도 있지만, 아주 오랜 역사에서 코드 에디터로 발전하며 여러 가지 기능들을 제공하고 있습니다 코드 에디터에서 가장 기본적으로 제공해야 하는 기능에서는 자동완성을 빼 놓을 수 없습니다. 물론 문맥에 맞는 자동완성 키워드를 추천해주는 vim 플러그인도 많이 있지만, 기본적으로 이러한 플러그인들 역시 vim의 내장 자동완성을 함께 사용하고 있는 경우가 많습니다. 즉, vim은 순정상태(?)에서도 기본적인 키워드 자동완성 기능은 제공할 수 있습니다.

vim에서 자동완성을 사용하는 가장 기본적인 방법은 키워드의 앞 한 두 글자를 입력한 후 <C-N>(Ctrl + N)을 누르는 것입니다. 이렇게 하면 현재 편집 중인 버퍼나 열려 있는 다른 버퍼에서 앞부분이 같은 단어를 찾아 자동으로 완성합니다. 매칭되는 결과가 2개 이상이라면 팝업 메뉴로 자동완성 키워드들이 표시됩니다. 이 때 <C-N> 을 눌러서 다음 키워드를 선택하거나, <C-P>를 눌러서 이전 키워드를 선택할 수 있습니다. 각각 “Next”, “Prev”의 앞 글자를 사용한다고 생각하면 됩니다.

이러한 기능을 ‘키워드 자동완성’이라고 합니다. 여기서 키워드는 편집 중인 버퍼 목록에 있는 다른 버퍼 내의 각 단어가 자동완성의 대상이 됩니다. 몇 가지 vim 옵션을 변경하면 키워드 자동완성과 관련된 동작을 커스터마이징할 수 있습니다. 우선 'complete' 라는 옵션이 있는데, 이 옵션은 키워드 자동완성에서 키보드를 찾을 소스를 선택하는 옵션입니다. 기본 값은 “.,w.b.u.t.i” 입니다.

  • . – 현재 버퍼에서 키워드 스캔
  • w – 다른 창에 있는 버퍼에서 키워드를 스캔
  • b – 버퍼 목록에 있는 버퍼 중에서 로드된 버퍼에서 키워드를 스캔
  • u – 버퍼 목록에 있는 버퍼 중에서 언로드된 버퍼에서도 키워드를 스캔
  • t – ctag에 의해 수집된 태그명에 대해서 키워드를 스캔
  • i – C소스코드를 편집하고 있다면, include된 파일에서도 키워드를 스캔

코드에서 이미 한 번 등장한 적 있는 함수 이름이나 변수이름, 타입 이름등은 별다른 플러그인 없이도 간단하게 자동완성을 할 수 있다는 점만해도 상당히 편리합니다. 다만 다른 편집기와 다른 점은 탭 키가 아닌 Ctrl + N 이라는 단축키를 사용한다는 것입니다. 사실 이것은 간단하게 탭 키를 사용하여 자동완성을 사용하도록 설정할 수 있습니다.

vim9script
# ~/vimfiles/plugin/compl.vim

def CheckBackSpace(): bool
    const c = col('.') - 1
    return c == 0 || getline('.')[col - 1] =~# '\s'
enddef

def ExprTabKey(): string
    if pumvisible() == 1
        return "\<C-n>"   # 메뉴 팝업이 열려 있으면 다음 항목을 선택
    elseif CheckBackSpace()
        return "\<Tab>"   # 현재 커서가 줄의 맨 앞이나 단어의 앞에 위치한다면 탭 키로 작동
    endif
    reeturn "\<C-n>"      # 그 외의 경우에는 탭으로 작동
enddef

inoremap <expr> <Tab> <SID>ExprTabKey()
inoremap <expr> <S-Tab> pumvisible() ? "\<C-p>" : "\<C-h>"
# shift + tab 의 경우, 메뉴가 있을 때에는 이전 항목, 없을 때에는 shift-tab

위 코드는 vim9script 문법으로 작성된 조각으로, 이 내용이 플러그인으로 로드되거나, vimrc 파일에 포함된다면 입력 중에 탭키를 누를 한글자라도 단어를 입력한 후에 눌려졌다면 탭 키가 Ctrl+N으로 작동하여 즉시 키워드 자동완성 기능을 호출하게 됩니다. 사실 이렇게만 설정하고 써도 어지간한 상황에서는 웬만한 텍스트 편집기보다는 훨씬 편하게 코드를 작성하고 편집할 수 있습니다.

자동완성과 관련된 옵션

'complete' 외에도 자동 완성과 관련된 옵션들이 있습니다.

  • 'complete' : 키워드 자동완성 (Ctrl+N, Ctrl+P)에서 사용하는 키워드의 소스를 지정
  • 'completeopt' : 삽입모드의 자동완성의 작동 방식에 관한 옵션
  • 'completefunc‘ : 사용자 지정 자동완성 함수를 지정하는 옵션
  • 'completeslash': MS윈도에서 경로를 자동완성할 때 경로 구분자를 슬래시(/)로 할 것인지를 지정하는 옵션

자동완성의 작동 방식을 지정하는 completeopt 옵션에 대해서 좀 더 알아보겠습니다. 이 옵션은 자동 완성이 시작될 때 팝업과 선택에 대한 동작을 설정할 수 있습니다. 작동하기 원하는 단어들을 ,로 연결하여 지정하면 됩니다.

  • menu : 자동완성을 사용하기 위해서 팝업 메뉴를 사용합니다. 팝업을 사용하지 않으면 Ctrl+N을 누를 때마다 현재 위치에서 단어가 교체되는 방식으로 작동합니다.
  • menuone : 사용가능한 매치가 하나 밖에 없을 때에도 팝업 메뉴를 보여줍니다.
  • longest : 중간부분까지 동일한 매치가 있는 경우에, 가장 긴 공통부분까지만 자동으로 입력합니다.
  • preview : 각 자동완성 항목에 별도의 추가 정보가 있는 경우, 미리보기 창을 생성하여 그 정보를 표시합니다.
  • popup : 추가 정보를 미리보기 창이 아닌 팝업 창으로 표시합니다. preview와 함께 설정되는 경우, 더 우선하게 됩니다.
  • popuphidden : “popup”과 같은 동작이지만, 팝업창을 표시하지 않다가 CompleteChanged 이벤트에 의해서 데이터를 가져오고 그 때 팝업을 표시합니다.
  • noinsert : 메뉴에서 사용자가 선택하기 전에 자동완성 내용을 삽입하지 않습니다.
  • noselect : 첫번째 항목을 자동으로 선택하지 않습니다.

자동완성 목록을 오가면 해당 내용이 버퍼에 입력됩니다. 그리고 다른 키를 누르면 메뉴가 사라지고 다음 내용을 입력하게 되지요. 그래서 일단 Ctrl+N을 사용해서 메뉴에서 키워드를 선택하면 입력하기 전의 내용으로 돌리기가 번거로울 수 있습니다. 이 경우에 사용할 수 있는 단축키는 Ctrl+E 입니다. 이 키는 자동 완성 작동 중에 자동완성을 취소하고 원래 직접 입력했던 내용으로 되돌아가게 됩니다. <Esc> 키를 사용하여 이 기능을 똑같이 만들고 싶다면 키 맵을 통해서 해결할 수 있습니다.

자동완성 팝업이 떠있는 경우에만 Ctrl+E로 작동하고 그외 의 경우에는 Esc키로 작동해야 하기 때문에 pumvisible() 함수를 사용해서 상태에 따라 다른 키로 작동하도록 다음과 같은 키맵을 추가해주면 됩니다.

inoremap <expr> <Esc> pumvisible() ? "\<C-e>" : "\<Esc>"

확장 자동 완성 모드

입력 모드에서 Ctrl+X를 누르면 확장 자동 완성 모드가 활성화되고, 여기서 다시 서브 모드를 선택하여 입력하려는 내용의 종류에 따른 자동 완성을 실행할 수 있습니다. 예를 들어 단어가 아닌 라인 전체를 자동 완성한다던가, 버퍼의 내용이 아닌 디렉토리 내 파일 이름을 자동완성할 수 있기도 합니다. . Ctrl+X 를 눌러서 확장 모드로 진입하면 화면 아래에 ^L^N^I.. 와 같은 식으로 선택할 수 있는 서브 모드들의 단축키가 표시됩니다.

  • <C-X><C-L> : 라인 완성 모드. 입력한 앞부분과 일치하는 전체 라인을 자동 완성한다.
  • <C-X><C-N> : 현재 파일 내에서만 키워드를 스캔하여 자동 완성한다.
  • <C-X><C-I> : 현재 파일과 include 된 파일에 대해서 스캔하여 자동 완성한다.
  • <C-X><C-]> : tag를 스캔하여 자동 완성한다.
  • <C-X><C-F> : 현재 디렉토리내 파일 이름을 자동 완성한다.
  • <C-X><C-V> : vim 명령 모드에서 입력했던 내용을 자동완성한다.
  • <C-X><C-U> : 사용자가 지정한 자동완성함수에서 키워드를 받아와서 자동완성한다.
  • <C-X><C-O> : 옴니 자동완성 함수로부터 자동완성한다.
  • <C-X><C-K> : 미리 정의된 단어 사전으로부터 자동완성한다.
  • <C-X><C-T> : 미리 정의된 유의어 사전으로부터 자동완성한다.

각각의 서브모드가 활성화되면 입력된 내용에 따라 자동 완성 후보 목록이 나타납니다. 어떤 모드에서든 Ctrl+N, Ctrl+P를 사용해서 제시어를 선택할 수 있다는 점은 똑같습니다. 특히 배치 스크립트 같은 걸 작성할 때에 파일 이름을 자동 완성하는 <C-X><C-F> 이나, vim script를 작성할 때에는 <C-X><C-V>를 사용하면 본문에 없는 키워드도 자동 완성을 지원할 수 있어서 여러 모로 편리합니다. 참고로, 확장 자동 완성 모드에서는 Ctrl+E, Ctrl+Y를 눌러서 입력모드를 떠나지 않은 상태에서 화면을 한 줄씩 스크롤 할수도 있습니다.

커스텀 자동 완성

vim이나 다른 유틸리티가 제공하는 자동완성 목록외에 사용자가 직접 정의한 자동 완성 기능을 사용하는 방법도 있습니다. 따로 함수를 하나 작성해서 이 설정값으로 지정해두는 것입니다. 간단하게 생각하면 어떤 단어의 목록이 있고, 앞부분의 글자(버퍼에 입력된)를 전달받아서 그에 매치되는 단어를 추려서 전달하는 함수가 있다면 될 것 같습니다.

vim에서는 입력 시 자동완성과 관련해서 'completefunc', 'omnifunc' 이렇게 두 가지의 설정 옵션을 가지고 있는데, 두 옵션 모두 동일한 구조의 함수를 지정하여 설정합니다. 'completefunc'는 사용자가 임의로 만든 자동완성 함수를 사용하는 것으로, 확장 자동 완성 모드에서 Ctrl+X Ctrl+U 를 사용해서 사용하게 됩니다. 또 다른 커스텀 자동완성 기능인 'omnifunc'로 설정한 기능은 Ctrl+X Ctrl+O를 사용하여 호출합니다. 특히 옴니 자동완성은 파일 타입별로 지정하여 사용할 수 있으며, vim 패키지에도 기본적으로 여러 파일 타입에 대해서 옴니완성 함수가 만들어져서 탑재되어 있는 것을 확인할 수 있습니다.

: setf python
: set omnifunc?
monifunc=python3complete#Complete

직접 자동 완성 함수를 만들어서 커스텀 하고 싶다면, 아래 글을 참고하시면 되겠습니다.