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