Skip to content

LanguageClient neovim

Fangrui Song edited this page Oct 3, 2019 · 17 revisions
  • Check out the next branch
  • Systems with prebuilt: ./install.sh
  • Others (e.g. FreeBSD): install rustup, make release (to get bin/languageclient)

You may use the plugin manager vim-plug

LanguageClient-neovim

nvim +PlugInstall +UpdateRemotePlugins +qa

~/.config/nvim/settings.json (optional, by default it creates cache directory .ccls-cache in the project root)

{
  "initializationOptions": {
    "cache": {
      "directory": "/tmp/ccls"
    }
  }
}

~/.config/nvim/init.vim

let g:LanguageClient_serverCommands = {
    \ 'c': ['ccls', '--log-file=/tmp/cc.log'],
    \ 'cpp': ['ccls', '--log-file=/tmp/cc.log'],
    \ 'cuda': ['ccls', '--log-file=/tmp/cc.log'],
    \ 'objc': ['ccls', '--log-file=/tmp/cc.log'],
    \ }

let g:LanguageClient_loadSettings = 1 " Use an absolute configuration path if you want system-wide settings
let g:LanguageClient_settingsPath = '/home/YOUR_USERNAME/.config/nvim/settings.json'
" https://github.com/autozimu/LanguageClient-neovim/issues/379 LSP snippet is not supported
"let g:LanguageClient_hasSnippetSupport = 0

First example:

cd /tmp; mkdir c; cd c
git init  # let LanguageClient-neovim know this is a project
echo '#include <stddef.h>\nint main() {}' > a.cc
nvim a.cc
# :LanguageClientStart

For a larger project, you'll need .ccls or compile_commands.json in your project root.

These features will work out-of-the-box.

nn <silent> <M-j> :call LanguageClient#textDocument_definition()<cr>
nn <silent> <C-,> :call LanguageClient#textDocument_references({'includeDeclaration': v:false})<cr>
nn <silent> K :call LanguageClient#textDocument_hover()<cr>

textDocument/documentHighlight

augroup LanguageClient_config
  au!
  au BufEnter * let b:Plugin_LanguageClient_started = 0
  au User LanguageClientStarted setl signcolumn=yes
  au User LanguageClientStarted let b:Plugin_LanguageClient_started = 1
  au User LanguageClientStopped setl signcolumn=auto
  au User LanguageClientStopped let b:Plugin_LanguageClient_started = 0
  au CursorMoved * if b:Plugin_LanguageClient_started | sil call LanguageClient#textDocument_documentHighlight() | endif
augroup END

Cross reference extensions

See LSP Extensions for the description of these extensions.

" bases
nn <silent> xb :call LanguageClient#findLocations({'method':'$ccls/inheritance'})<cr>
" bases of up to 3 levels
nn <silent> xB :call LanguageClient#findLocations({'method':'$ccls/inheritance','levels':3})<cr>
" derived
nn <silent> xd :call LanguageClient#findLocations({'method':'$ccls/inheritance','derived':v:true})<cr>
" derived of up to 3 levels
nn <silent> xD :call LanguageClient#findLocations({'method':'$ccls/inheritance','derived':v:true,'levels':3})<cr>

" caller
nn <silent> xc :call LanguageClient#findLocations({'method':'$ccls/call'})<cr>
" callee
nn <silent> xC :call LanguageClient#findLocations({'method':'$ccls/call','callee':v:true})<cr>

" $ccls/member
" nested classes / types in a namespace
nn <silent> xs :call LanguageClient#findLocations({'method':'$ccls/member','kind':2})<cr>
" member functions / functions in a namespace
nn <silent> xf :call LanguageClient#findLocations({'method':'$ccls/member','kind':3})<cr>
" member variables / variables in a namespace
nn <silent> xm :call LanguageClient#findLocations({'method':'$ccls/member'})<cr>

nn xx x

$ccls/inheritance derived:false: base classes/overridden methods/specialized from

$ccls/inheritance derived:true

$ccls/call: callers/callees of a function

$ccls/vars: instances of a type

$ccls/member: fields of a struct/class/union/...

There are also hierarchical views of $ccls/call $ccls/inheritance $ccls/member (see the Emacs page) but they have not been implemented by a Vim plugin.

$ccls/navigate

See $ccls/navigate

nn <silent> xh :call LanguageClient#findLocations({'method':'$ccls/navigate','direction':'L'})<cr>
nn <silent> xj :call LanguageClient#findLocations({'method':'$ccls/navigate','direction':'D'})<cr>
nn <silent> xk :call LanguageClient#findLocations({'method':'$ccls/navigate','direction':'U'})<cr>
nn <silent> xl :call LanguageClient#findLocations({'method':'$ccls/navigate','direction':'R'})<cr>

Formatting

fu! C_init()
  setl formatexpr=LanguageClient#textDocument_rangeFormatting()
endf
au FileType c,cpp,cuda,objc :call C_init()

In visual mode, = will invoke textDocument/rangeFormatting, which is a replacement of the clang-format command (both of them use the clangFormat library).