-- Leo's gemini proxy

-- Connecting to republic.circumlunar.space:1965...

-- Connected

-- Sending request

-- Meta line: 20 text/gemini

First setup for nvim-lsp with nvim-cmp


DATE: 2021-11-30

AUTHOR: John L. Godlee



I used to use ncm2[1] for autocompletion in neovim[2], then I switched to coc.nvim[3] for a short time, but found it awkward to maintain. Recently I set up nvim-cmp[4], which uses neovim's built-in language server client to source external language servers for different languages.


1: https://github.com/ncm2/ncm2

2: https://neovim.io/

3: https://github.com/neoclide/coc.nvim

4: https://github.com/hrsh7th/nvim-cmp


I use auto-completion fairly sparingly, but I do find it incredibly useful for two main things: completing file paths, and suggesting snippets from Ultisnips[5]. I also sometimes use language auto-completion when writing R. Possibly in the future I'd also like to use auto-completion for writing LaTeX, Javascript, Julia and CSS, but for now I've just set up the language server for R.


5: https://github.com/SirVer/ultisnips


The R language server is installed by running install.packages("languageserver") in R. I use the Nvim-R[6] vim plugin to turn neovim into something more like a full IDE. Nvim-R provides syntax highlighting for R code, allows interaction with an open R repl either in a tmux split or a nvim terminal buffer, among many other features. I use radian[7] to provide a smarter R repl.


6: https://github.com/jalvesaq/Nvim-R

7: https://github.com/randy3k/radian


To set up nvim-cmp I largely followed the example configuration provided in the nvim-cmp README.md, but I've added an extra bit at the end to disable buffer word completion in file types which normally contain prose. I've pasted the config below for Nvim-R, Ultisnips, and nvim-cmp.


I wish I understood a bit better what the different bits of lua code actually do (e.g. the calls to cmp.setup.cmdline), but I found the online documentation to be quite lacking.


Screenshot demonstrating Nvim-R and nvim-cmp


" Plugins
call plug#begin('~/.vim/plugged')

Plug 'SirVer/ultisnips'	" Snippets
Plug 'jalvesaq/Nvim-R'
Plug 'neovim/nvim-lspconfig'
Plug 'hrsh7th/cmp-nvim-lsp'
Plug 'hrsh7th/cmp-path'
Plug 'hrsh7th/cmp-buffer'
Plug 'hrsh7th/cmp-cmdline'
Plug 'hrsh7th/nvim-cmp'
Plug 'quangnguyen30192/cmp-nvim-ultisnips'

call plug#end()

" nvim-cmp
set completeopt=menuone,noselect

lua <<EOF
  local cmp = require'cmp'

  -- Setup nvim-cmp
  cmp.setup({
    -- Specify snippet engine
    snippet = {
      expand = function(args)
        vim.fn["UltiSnips#Anon"](args.body)
      end,
    },
    -- Keybindings
    mapping = {
      ['<C-n>'] = cmp.mapping.select_next_item({ behavior = cmp.SelectBehavior.Insert }),
      ['<C-p>'] = cmp.mapping.select_prev_item({ behavior = cmp.SelectBehavior.Insert }),
      ['<Down>'] = cmp.mapping.select_next_item({ behavior = cmp.SelectBehavior.Select }),
      ['<Up>'] = cmp.mapping.select_prev_item({ behavior = cmp.SelectBehavior.Select }),
      ['<CR>'] = cmp.mapping.confirm({ select = true }),
    },
    -- Define completion sources
    sources = cmp.config.sources({
      { name = 'nvim_lsp' },
      { name = 'ultisnips' },
      { name = 'buffer' },
      { name = 'path' },
    })
  })

  cmp.setup.cmdline('/', {
    sources = {
      { name = 'buffer' }
    }
  })

  cmp.setup.cmdline(':', {
    sources = cmp.config.sources({
      { name = 'path' }
    }, {
      { name = 'cmdline' }
    })
  })

  -- Setup lspconfig
  local capabilities = require('cmp_nvim_lsp').update_capabilities(vim.lsp.protocol.make_client_capabilities())

  -- R language server options
  require('lspconfig')['r_language_server'].setup {
    cmd = { "R", "--slave", "-e", "languageserver::run()" },
    filetypes = { "r", "rmd" }
  }

EOF

" Only enable minimal completion in files containing prose
autocmd FileType markdown,tex,txt lua require'cmp'.setup.buffer {
\	sources = {
\     { name = 'path' },
\     { name = 'ultisnips' },
\   },
\ }

" Nvim-R
let R_external_term = 0
let R_source = '~/.vim/tmux_split.vim'
let R_assign = 0
let R_objbr_place = 'BOTTOM'
let R_objbr_h = 30
let R_min_editor_width = 80
let R_objbr_opendf = 0
let r_indent_comment_column = 0
let r_indent_align_args = 0
let r_indent_ess_comments = 0
let r_indent_ess_compatible = 0
let R_non_r_compl = 0
let R_rmdchunk = 0
let R_rnowebchunk = 0
let R_app = "radian"
let R_cmd = "R"
let R_hl_term = 0
let R_args = []
let R_bracketed_paste = 1

nmap <LocalLeader><Enter> <Plug>RDSendLine
vmap <LocalLeader><Enter> <Plug>REDSendSelection

" Ultisnips
let g:UltiSnipsExpandTrigger="<tab>"
let g:UltiSnipsJumpForwardTrigger="<c-l>"
let g:UltiSnipsJumpBackwardTrigger="<c-h>"
let g:UltiSnipsEditSplit="vertical"
let g:UltiSnipsSnippetDirectories=[$HOME.'/.vim/Ultisnips']

Update 2021-12-05


I spent about 3 days trying to work with nvim-cmp, but I found that if I had more than two R scripts open in separate nvim instances, the fans on my MacBook Pro would start going crazy and htop showed the CPU maxed out. For me that’s not good enough, and I can get by with the built-in completion provided by Ctrl-x Ctrl-f / ctrl-o etc. So that’s a bit disappointing, and I’m not sure whether it will ever get better. I see that nvim v0.60 has just been released, but reading through the release notes I see no improvements to LSP support. As an uninformed user it's difficult to know if the bottleneck is nvim-cmp, the R language server, or nvim.

-- Response ended

-- Page fetched on Sat May 18 14:28:22 2024