Home vim-polyglot / coc.nvim
Post
Cancel

vim-polyglot / coc.nvim

2년 전의 깨달음을 떠올리며 정리해봅니다.

Neovim 이나 SpaceVim 같이 미리 정제되고 커스터마이징 된 플러그인들을 기능으로 탑재하여 관리하는 vim-fork 부류를 사용하지 않는 한, vim 은 여러가지 잡다한 설정들을 스스로 해야하고, 설정과 관련된 난관을 겪을 수 있습니다.

개인적으로는 순정품을 좋아해서(…) vim 을 터미널에서 사용하고 있습니다. 사실 tmux 와의 궁합 때문인데, 익숙해지다 보니까 굳이 다른 편집기와 터미널의 조합으로 손길이 가질 않더라고요. 설정을 하나하나 추가하고 바꾸는 것이 입맞에 맞추는 과정이라 재미있기도 합니다. 시간만 허락한다면요.

vim-polyglot

그런 재미들 중에서 제외하고 싶은게 있었으니… 그것은 프로그래밍 언어 지원(language support)입니다.

문법 강조나 포맷, 들여쓰기 혹은 Syntastic 과 같은 외부 문법 체커와의 통합에도 관련된 기능인데, 딱히 설정이 까다롭다기 보다는 .vimrc 내부 플러그인 목록의 덩치를 키우고, 언어에 따라서 기능이 부분적으로 겹치는 것들도 있어서 조금 성가신 편입니다.

vim-fork 들은 기본적으로 통합해서 제공하지만 제가 사용중이었던 여러 플러그인들 중 언어 지원관련은 이런 모양이었습니다:

1
2
3
4
5
6
7
8
9
10
11
Plugin 'pangloss/vim-javascript'
Plugin 'kchmck/vim-coffee-script'
Plugin 'chemzqm/vim-jsx-improve'
Plugin 'leafgarland/typescript-vim'
Plugin 'peitalin/vim-jsx-typescript'
Plugin 'cakebaker/scss-syntax.vim'
Plugin 'gcorne/vim-sass-lint'
Plugin 'rust-lang/rust.vim'
Plugin 'racer-rust/vim-racer'
Plugin 'elixir-lang/vim-elixir'
Plugin 'udalov/kotlin-vim'  

Rust 관련 플러그인들을 찾다가 vim-polyglot 을 우연히 발견하게 되었는데, 거의 대부분의 주류 언어들을 통합 지원하면서도 vim 의 실행시간이나 설치/업데이트 면에서 강점이 있어서 설치를 했습니다.

1
Plugin 'sheerun/vim-polyglot'

이렇게 한 줄로 끝이 납니다. 참 쉽습니다. (참고로 플러그인들은 Vundle 로 관리하고 있습니다.)

coc.nvim

언어 지원은 코딩 시 표면적/시각적으로 도움을 주는 반면, LSP(Language Server Protocol)는 코드 완성이나 타입 체킹, 정의된 곳으로 이동 등을 통해서 조금 더 코딩을 편하고 정확하게 할 수 있는 기능을 지원합니다.

비교하자면 Visual Studio 의 Intellisense 같은 기능을 수행하는 것인데, 수 많은 언어들에 따라 해당 기능을 각각 개발하려면 편집기의 크기가 커지고 복잡해지기 때문에, 개발 커뮤니티에 의해 서버(언어별로 편의에 관련된 기능을 제공)-클라이언트(기능을 사용하는 도구) 방식으로 LSP 가 탄생하게 되었습니다.

기존에는 코드 완성기능을 위해 YouCompleteMe (YCM) 를 사용했습니다. YCM 의 설정 중 ALE 을 LSP 클라이언트로 지정해서 썼고요. 그런데 문제는 딱히 싫지는 않은데 마음에 들지도 않는다는 것이었습니다.

이렇게 밑줄 말고 조금 더 눈에 띄는 경고와 친절한 설명이 보고 싶었습니다.


아마도 제대로 된 설정을 하지 않았기에 YCM 과 ALE 두 플러그인을 함께 쓰는 것에 좋은 인상을 받지 못했던 것 같습니다. 결정적인 원인은 두 가지 였는데, 타입의 참조문서를 원할때 바로 띄워서 보고 싶었고, 경고/에러등을 Command line 이 아닌 곳에서 한 줄 이상으로 보고 싶었던 것입니다. 이것들이 가장 불편했습니다.

그 이후 이것저것 사용을 시도해봤고, 정착하게 된 것이 coc.nvim 입니다. 앞서 언급한 두 플러그인의 기능을 통합적으로 사용할 수 있게 해주는 것이 가장 매력적이었습니다. 관련 .vimrc는 편의에 따라 이렇게 설정했는데요, 커서 위에서 Shift + T를 입력해서 원할때만 해당 관련 문서를 볼 수 있도록 해놓은, Hover documentation 이라고 이름 붙인 기능을 신나게(?) 사용하고 있습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
let g:coc_global_extensions = ['coc-tsserver', 'coc-json', 'coc-rust-analyzer', 'coc-graphql', 'coc-prettier']

" Use tab for trigger completion with characters ahead and navigate.
inoremap <silent><expr> <TAB>
      \ pumvisible() ? "\<C-n>" :
      \ <SID>check_back_space() ? "\<TAB>" :
      \ coc#refresh()
inoremap <expr><S-TAB> pumvisible() ? "\<C-p>" : "\<C-h>"

function! s:check_back_space() abort
  let col = col('.') - 1
  return !col || getline('.')[col - 1]  =~# '\s'
endfunction

" Use <c-space> to trigger completion.
inoremap <silent><expr> <c-space> coc#refresh()
" Remap keys for applying codeAction to the current line.
nmap <leader>ac  <Plug>(coc-codeaction)
" Apply AutoFix to problem on the current line.
nmap <leader>qf  <Plug>(coc-fix-current)

" GoTo code navigation.
nmap <silent> gd <Plug>(coc-definition)
nmap <silent> gy <Plug>(coc-type-definition)
nmap <silent> gi <Plug>(coc-implementation)
nmap <silent> gr <Plug>(coc-references)

" Hover documentation
nnoremap <silent> K :call <SID>show_documentation()<CR>
function! s:show_documentation()
  if (index(['vim','help'], &filetype) >= 0)
    execute 'h '.expand('<cword>')
  else
    call CocAction('doHover')
  endif
endfunction

" Prettier (coc-prettier)
vmap <leader>p  <Plug>(coc-format-selected)
nmap <leader>p  <Plug>(coc-format-selected)

" Jump to next/previous problem
nmap <silent> <Leader>j <Plug>(coc-diagnostic-next-error)
nmap <silent> <Leader>k <Plug>(coc-diagnostic-prev-error)


추가로 coc 전용 설정 파일을 생성해야 합니다. 요즘 프로젝트에서 주로 쓰는 TypeScript 관련 설정은 이렇게 해두었습니다:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
{
  ...
  "coc.preferences.formatOnType": true,
  "coc.preferences.jumpCommand": "tabe",
  "codeLens.enable": true,
  "diagnostic.errorSign": "XX",
  "diagnostic.warningSign": "!!",
  "diagnostic.infoSign": "ii",
  "diagnostic.hintSign": "??",
  "diagnostic.enableHighlightLineNumber": true,
  "signature.enable": true,
  "signature.target": "echo",
  "tsserver.npm": "/usr/local/bin/npm",
  "typescript.format.enabled": false
  ...
}


결과는 마음에 들었습니다. 아래 스크린 샷으로 확인할 수 있는 결과 이외에도 경고/에러표시와 자동 수정기능 등 다양한 기능들을 사용할 수 있습니다. 코드 자동완성

Shift+K 를 통한 관련 참조문서 열람


vim 은 평생 배우는 것이라는 말은 사용해보면 와닿게 되는 것 같습니다. 그래서 궁금하더라도 조급해 하지 않고 천천히 배우면서 도 닦은 기분으로 쓰는게 핵심인 것 같고요. (그래서 잘 몰라도 계속 뻔뻔하게 사용하고 있습니다.)

개인적으로는 vim 기본 기능의 절반도 제대로 활용하지 못하고 있는 것 같지만, 이런 플러그인들 덕분에 필요한 기능들에 대한 갈증을 그때 그때 해결하고 커스터마이징 하는 재미가 있다 보니, 다른 편집기들이 눈에 들어오지 않는 것은 좋은 현상이 아닌가 싶네요.

This post is licensed under CC BY 4.0 by the author.

2022 Spring

재택근무 8년차 원격외노자