~mlb/dotfiles

cd168b35d8c24b6390225a63228652b262ecf1e3 — Matias Larre Borges 7 months ago a53de73 master
[NVIM] Remove CoC in favor of LSP
M nvim/conf/00-plugins.vim => nvim/conf/00-plugins.vim +24 -5
@@ 1,8 1,11 @@
call plug#begin(stdpath('data') . '/plugged')

Plug 'junegunn/vim-emoji'                               " Macros to refer to emojis

Plug 'itchyny/lightline.vim'                            " Improved status line
Plug 'macthecadillac/lightline-gitdiff'                 " Git integration in lightline
Plug 'nvim-lualine/lualine.nvim'                        " status line written in lua
Plug 'kyazdani42/nvim-web-devicons'                     " icons for lualine
Plug 'arkav/lualine-lsp-progress'                       " shows lsp status in lualine
Plug 'akinsho/bufferline.nvim'                          " bufferline

Plug 'airblade/vim-gitgutter'                           " Git integration in gutter



@@ 11,8 14,6 @@ Plug 'Shougo/defx.nvim', {
Plug 'kristijanhusak/defx-icons'                        " Nice icons in defx
Plug 'kristijanhusak/defx-git'                          " git icon integration for defx

Plug 'neoclide/coc.nvim', {'branch': 'release'}         " Code completion

Plug 'ryanoasis/vim-devicons'                           " Nice icons

Plug 'kyoz/purify', { 'rtp': 'vim' }                    " Colorscheme


@@ 32,10 33,28 @@ Plug 'mhinz/vim-mix-format'                             " Elixir auto-formatting

Plug 'chrisbra/colorizer'                               " Colorizes colornames and codes

Plug 'nvim-treesitter/nvim-treesitter'                  " treesitter support (requires neovim nightly)
Plug 'nvim-treesitter/nvim-treesitter',
            \ {'do': ':TSUpdate'}                       " treesitter support (requires neovim nightly)

Plug 'neovim/nvim-lspconfig'                            "LSP config
Plug 'glepnir/lspsaga.nvim'                             "UI for lsp support
Plug 'onsails/lspkind-nvim'

" nvim-cmp: begin
Plug 'hrsh7th/cmp-nvim-lsp'
Plug 'hrsh7th/cmp-buffer'
Plug 'hrsh7th/cmp-path'
Plug 'hrsh7th/cmp-cmdline'
Plug 'hrsh7th/nvim-cmp'

Plug 'hrsh7th/cmp-vsnip'
Plug 'hrsh7th/vim-vsnip'
" nvim-cmp: end

Plug 'nvim-lua/popup.nvim'                              " telescope: popup
Plug 'nvim-lua/plenary.nvim'                            " telescope: plenary
Plug 'nvim-lua/telescope.nvim'                          " telescope: telescope
Plug 'nvim-telescope/telescope-fzf-native.nvim',
            \ { 'do': 'make' }

call plug#end()

M nvim/conf/30-options.vim => nvim/conf/30-options.vim +2 -1
@@ 11,7 11,8 @@ set foldenable
set foldlevelstart=10               " Only fold nested stuff
set foldnestmax=10                  " Don't fold too deeply nested stuff
set wildmenu                        " Visual autocomplete for command menu
set completeopt=longest,menu,preview
"set completeopt=longest,menu,preview
set completeopt=menu,menuone,noselect
set lazyredraw                      " Redraw only when we need to.
set modelines=1                     " Process file specific options
set guioptions=                     " Disabled all GUI chrome

A nvim/conf/50-bufferline.vim => nvim/conf/50-bufferline.vim +9 -0
@@ 0,0 1,9 @@
lua << END
require('bufferline').setup {
    options = {
        numbers = "both",
        show_buffer_close_icons = false,
        show_close_icon = false
        }
    }
END

A nvim/conf/50-cmp.vim => nvim/conf/50-cmp.vim +60 -0
@@ 0,0 1,60 @@
lua <<EOF
  -- Setup nvim-cmp.
  local cmp = require'cmp'

  cmp.setup({
    snippet = {
      -- REQUIRED - you must specify a snippet engine
      expand = function(args)
        vim.fn["vsnip#anonymous"](args.body) -- For `vsnip` users.
        -- require('luasnip').lsp_expand(args.body) -- For `luasnip` users.
        -- vim.fn["UltiSnips#Anon"](args.body) -- For `ultisnips` users.
        -- require'snippy'.expand_snippet(args.body) -- For `snippy` users.
      end,
    },
    mapping = {
      ['<C-b>'] = cmp.mapping(cmp.mapping.scroll_docs(-4), { 'i', 'c' }),
      ['<C-f>'] = cmp.mapping(cmp.mapping.scroll_docs(4), { 'i', 'c' }),
      ['<C-Space>'] = cmp.mapping(cmp.mapping.complete(), { 'i', 'c' }),
      ['<C-y>'] = cmp.config.disable, -- Specify `cmp.config.disable` if you want to remove the default `<C-y>` mapping.
      ['<C-e>'] = cmp.mapping({
        i = cmp.mapping.abort(),
        c = cmp.mapping.close(),
      }),
      -- Accept currently selected item. If none selected, `select` first item.
      -- Set `select` to `false` to only confirm explicitly selected items.
      ['<CR>'] = cmp.mapping.confirm({ select = true }),
    },
    sources = cmp.config.sources({
      { name = 'nvim_lsp' },
      { name = 'vsnip' }, -- For vsnip users.
      -- { name = 'luasnip' }, -- For luasnip users.
      -- { name = 'ultisnips' }, -- For ultisnips users.
      -- { name = 'snippy' }, -- For snippy users.
    }, {
      { name = 'buffer' },
    })
  })

  -- Use buffer source for `/` (if you enabled `native_menu`, this won't work anymore).
  cmp.setup.cmdline('/', {
    sources = {
      { name = 'buffer' }
    }
  })

  -- Use cmdline & path source for ':' (if you enabled `native_menu`, this won't work anymore).
  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())
  require('lspconfig')['elixirls'].setup {
    capabilities = capabilities
  }
EOF

D nvim/conf/50-coc.vim => nvim/conf/50-coc.vim +0 -172
@@ 1,172 0,0 @@
" COC config {{{

"
set hidden

" Smaller updatetime for CursorHold & CursorHoldI
set updatetime=300

" don't give |ins-completion-menu| messages.
set shortmess+=c

" always show signcolumns
set signcolumn=yes

" Use tab for trigger completion with characters ahead and navigate.
" Use command ':verbose imap <tab>' to make sure tab is not mapped by other plugin.
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> for trigger completion.
inoremap <silent><expr> <c-space> coc#refresh()

" Use <cr> for confirm completion, `<C-g>u` means break undo chain at current position.
" Coc only does snippet and additional edit on confirm.
inoremap <expr> <cr> pumvisible() ? "\<C-y>" : "\<C-g>u\<CR>"

" Use `[c` and `]c` for navigate diagnostics
nmap <silent> [c <Plug>(coc-diagnostic-prev)
nmap <silent> ]c <Plug>(coc-diagnostic-next)

" Remap keys for gotos
nmap <silent> <localleader>d <Plug>(coc-definition)
nmap <silent> <localleader>y <Plug>(coc-type-definition)
nmap <silent> <localleader>i <Plug>(coc-implementation)
nmap <silent> <localleader>r <Plug>(coc-references)
nmap <silent> <localleader>ag :CocList diagnostics<CR>
nmap <silent> <localleader>s :CocList symbols<CR>
nmap <localleader>ac  <Plug>(coc-codeaction)
nmap <localleader>qf  <Plug>(coc-fix-current)


" Use K for show documentation in preview window
nnoremap <silent> K :call <SID>show_documentation()<CR>

function! s:show_documentation()
  if &filetype == 'vim'
    execute 'h '.expand('<cword>')
  else
    call CocAction('doHover')
  endif
endfunction

" Highlight symbol under cursor on CursorHold
autocmd CursorHold *.ts silent call CocActionAsync('highlight')

" Remap for rename current word
nmap <leader>rn <Plug>(coc-rename)

" Remap for format selected region
vmap <leader>f  <Plug>(coc-format-selected)

augroup mygroup
  autocmd!
  " Setup formatexpr specified filetype(s).
  autocmd FileType typescript,json setl formatexpr=CocAction('formatSelected') | set foldmethod=manual
  " Update signature help on jump placeholder
  autocmd User CocJumpPlaceholder call CocActionAsync('showSignatureHelp')
  autocmd User CocDiagnosticChange call lightline#update()
augroup end

" Remap for do codeAction of selected region, ex: `<leader>aap` for current paragraph
vmap <leader>a  <Plug>(coc-codeaction-selected)
nmap <leader>a  <Plug>(coc-codeaction-selected)

" Remap for do codeAction of current line
nmap <leader>ac  <Plug>(coc-codeaction)
" Fix autofix problem of current line
nmap <leader>qf  <Plug>(coc-fix-current)

" Use `:Format` for format current buffer
command! -nargs=0 Format :call CocAction('format')

" Use `:Fold` for fold current buffer
command! -nargs=? Fold :call     CocAction('fold', <f-args>)

" Using CocList
" Show all diagnostics
nnoremap <silent> <space>a  :<C-u>CocList diagnostics<cr>
" Show commands
nnoremap <silent> <space>c  :<C-u>CocList commands<cr>
" Find symbol of current document
nnoremap <silent> <space>O  :<C-u>CocList outline<cr>
" Search workspace symbols
nnoremap <silent> <space>s  :<C-u>CocList -I symbols<cr>
" Do default action for next item.
nnoremap <silent> <space>J  :<C-u>CocNext<CR>
" Do default action for previous item.
nnoremap <silent> <space>K  :<C-u>CocPrev<CR>
" Resume latest coc list
nnoremap <silent> <space>p  :<C-u>CocListResume<CR>

" }}}

" CocSnippets config {{{
" Use <C-l> for trigger snippet expand.
imap <C-l> <Plug>(coc-snippets-expand)

" Use <C-j> for select text for visual placeholder of snippet.
vmap <C-j> <Plug>(coc-snippets-select)

" Use <C-j> for jump to next placeholder, it's default of coc.nvim
let g:coc_snippet_next = '<c-j>'

" Use <C-k> for jump to previous placeholder, it's default of coc.nvim
let g:coc_snippet_prev = '<c-k>'

" Use <C-j> for both expand and jump (make expand higher priority.)
imap <C-j> <Plug>(coc-snippets-expand-jump)
" }}}

" Elixir-LS config {{{
let g:ElixirLS = {}
let ElixirLS.path = stdpath('data').'/plugged/elixir-ls'
let ElixirLS.lsp = ElixirLS.path.'/release/language_server.sh'
let ElixirLS.cmd = join([
        \ 'asdf install &&',
        \ 'mix do',
        \ 'local.hex --force --if-missing,',
        \ 'local.rebar --force,',
        \ 'deps.get,',
        \ 'compile,',
        \ 'elixir_ls.release'
        \ ], ' ')

function ElixirLS.on_stdout(_job_id, data, _event)
  let self.output[-1] .= a:data[0]
  call extend(self.output, a:data[1:])
endfunction

let ElixirLS.on_stderr = function(ElixirLS.on_stdout)

function ElixirLS.on_exit(_job_id, exitcode, _event)
  if a:exitcode[0] == 0
    echom '>>> ElixirLS compiled'
  else
    echoerr join(self.output, ' ')
    echoerr '>>> ElixirLS compilation failed'
  endif
endfunction

function ElixirLS.compile()
  let me = copy(g:ElixirLS)
  let me.output = ['']
  echom '>>> compiling ElixirLS'
  let me.id = jobstart('cd ' . me.path . ' && git pull && ' . me.cmd, me)
endfunction

" Update the Elixir language server
call coc#config('elixir', {
  \ 'command': g:ElixirLS.lsp,
  \ 'filetypes': ['elixir', 'eelixir']
  \})
call coc#config('elixir.pathToElixirLS', g:ElixirLS.lsp)
" }}}

D nvim/conf/50-lightline.vim => nvim/conf/50-lightline.vim +0 -138
@@ 1,138 0,0 @@
" Lightline config {{{
set showtabline=2
let g:lightline = {}
let g:lightline.colorscheme = 'purify'
let g:lightline.separator = { 'left': "\ue0b8", 'right': "\ue0be" }
let g:lightline.subseparator = { 'left': "\ue0b9", 'right': "\ue0b9" }
let g:lightline.tabline_separator = { 'left': "\ue0bc", 'right': "\ue0ba" }
let g:lightline.tabline_subseparator = { 'left': "\ue0bb", 'right': "\ue0bb" }
let g:lightline.inactive = {
            \ 'left': [ [ 'relativepath' ] ],
            \ 'right': [ [ 'percent' ] ],
            \}
let g:lightline.active = {
            \ 'left': [ [ 'mode', 'paste', ],
            \           [ 'gitbranch', 'readonly', 'relativepath', 'modified' ],
            \           [ 'currentFuncCoC', 'currentFuncTS' ] ],
            \ 'right': [ [ 'lineinfo' ],
            \            [ 'devicons_filetype', 'devicons_fileformat'],
            \            [ 'obsession' ],
            \            [ 'coc_error', 'coc_warning' ] ]
            \}

let g:lightline.tabline = {
            \ 'left': [ [ 'vim_logo', 'tabs' ] ],
            \ 'right': [ ['myCurrentDir'],
            \            [ 'gitstatus' ] ]
            \ }

let g:lightline.component = {
            \ 'myCurrentDir': "\uf413 %{fnamemodify(getcwd(), ':t')}",
            \ 'currentFuncCoC': '%{CocCurrentFunction()}',
            \ 'currentFuncTS': '%{TreeSitterCurrentElement()}',
            \ 'obsession': '%{ObsessionStatusEnhance()}',
            \ 'gitstatus': '%{lightline_gitdiff#get_status()}',
            \ 'bufinfo': '%{bufname("%")}:%{bufnr("%")}',
            \ 'vim_logo': "\ue7c5",
            \ 'mode': '%{lightline#mode()}',
            \ 'absolutepath': '%F',
            \ 'relativepath': '%f',
            \ 'filename': '%t',
            \ 'filesize': "%{HumanSize(line2byte('$') + len(getline('$')))}",
            \ 'fileencoding': '%{&fenc!=#""?&fenc:&enc}',
            \ 'fileformat': '%{&fenc!=#""?&fenc:&enc}[%{&ff}]',
            \ 'filetype': '%{&ft!=#""?&ft:"no ft"}',
            \ 'modified': '%M',
            \ 'bufnum': '%n',
            \ 'paste': '%{&paste?"PASTE":""}',
            \ 'readonly': '%R',
            \ 'charvalue': '%b',
            \ 'charvaluehex': '%B',
            \ 'percent': '%2p%%',
            \ 'percentwin': '%P',
            \ 'spell': '%{&spell?&spelllang:""}',
            \ 'lineinfo': '%2p%% %3l:%-2v',
            \ 'line': '%l',
            \ 'column': '%c',
            \ 'close': '%999X X ',
            \ 'winnr': '%{winnr()}'
            \ }
function! LightlineFugitive()
    if exists('*FugitiveHead')
        let branch = FugitiveHead()
        return branch !=# '' ? ' '.branch : ''
    endif
    return ''
endfunction
let g:lightline_gitdiff#indicator_added = "\uf067"
let g:lightline_gitdiff#indicator_deleted = "\uf068"
let g:lightline_gitdiff#indicator_modified = "\uf12a"

function! CocCurrentFunction()
    let currentFunctionSymbol = get(b:, 'coc_current_function', '')
    " See :h lightline expand_component & https://github.com/itchyny/lightline.vim/issues/236
    " return currentFunctionSymbol !=# '' ? "%%#LineNr#%% \uf6a6 " .currentFunctionSymbol : ''
    " return currentFunctionSymbol !=# '' ? "\uf6a6 " .currentFunctionSymbol : ''
    return currentFunctionSymbol !=# '' ? "\ufb26 [" . currentFunctionSymbol . ']' : ''
endfunction


function! CocError() abort
  let info = get(b:, 'coc_diagnostic_info', {})
  if empty(info) | return '' | endif
  if get(info, 'error', 0)
    return "\u2716 " . info['error']
  else
    return ''
  endif
endfunction

function! CocWarning() abort
  let info = get(b:, 'coc_diagnostic_info', {})
  if empty(info) | return '' | endif
  if get(info, 'warning', 0)
    return "\uf071 " . info['warning']
  else
    return ''
  endif
endfunction

let g:lightline.component_function = {
            \ 'gitbranch': 'LightlineFugitive',
            \ 'devicons_filetype': 'WebDevIconsGetFileTypeSymbol',
            \ 'devicons_fileformat': 'WebDevIconsGetFileFormatSymbol',
            \ }

let g:lightline.component_expand = {
            \ 'coc_error': 'CocError',
            \ 'coc_warning': 'CocWarning'
            \ }
let g:lightline.component_type = {
            \ 'coc_error': 'error',
            \ 'coc_warning': 'warning'
            \}

let g:lightline.component_visible_condition = {
            \ 'gitstatus': 'lightline_gitdiff#get_status() !=# ""'
            \}
" }}}

" Helper functions {{{

" Current element using TreeSitter
function! TreeSitterCurrentElement()
    let x = luaeval("require'nvim-treesitter'.statusline(50)")
    return x !=# '' ? "\uf450 [" . x . ']' : ''
endfunction

" Indicator for whether session is being recorded
function! ObsessionStatusEnhance()
    let obsStatus = ObsessionStatus("\uf04b","\uf04c")
    if obsStatus !=# ""
        return obsStatus
    else
        return "\uf04d"
    endif
endfunction

" }}}

A nvim/conf/50-lspconfig.vim => nvim/conf/50-lspconfig.vim +44 -0
@@ 0,0 1,44 @@
lua << END
local lspconfig = require("lspconfig")

lspconfig.elixirls.setup {
    cmd = { "/Users/matiasb/local/bin/language_server.sh" }
}

-- Neovim doesn't support snippets out of the box, so we need to mutate the
-- capabilities we send to the language server to let them know we want snippets.
local capabilities = vim.lsp.protocol.make_client_capabilities()
capabilities.textDocument.completion.completionItem.snippetSupport = true

-- Setup our autocompletion. These configuration options are the default ones
-- copied out of the documentation.
local cmp = require("cmp")

cmp.setup({
  snippet = {
    expand = function(args)
      -- For `vsnip` user.
      vim.fn["vsnip#anonymous"](args.body)
    end,
  },
  mapping = {
    ["<C-b>"] = cmp.mapping.scroll_docs(-4),
    ["<C-f>"] = cmp.mapping.scroll_docs(4),
    ["<C-Space>"] = cmp.mapping.complete(),
    ["<C-e>"] = cmp.mapping.close(),
    ["<C-y>"] = cmp.mapping.confirm({ select = true }),
  },
  sources = {
    { name = "nvim_lsp" },
    { name = "vsnip" },
  },
  formatting = {
    format = require("lspkind").cmp_format({
      with_text = true,
      menu = {
        nvim_lsp = "[LSP]",
      },
    }),
  },
})
END

A nvim/conf/50-lualine.vim => nvim/conf/50-lualine.vim +44 -0
@@ 0,0 1,44 @@
let g:error_symbol = emoji#for('bangbang')
let g:warn_symbol = emoji#for('warning')
let g:info_symbol = emoji#for('information_source')
let g:hint_symbol = emoji#for('grey_exclamation')

lua << END
require'lualine'.setup {
    sections = {
        lualine_a = {
            {
                    'diagnostics',
                    -- table of diagnostic sources, available sources:
                    -- 'nvim_lsp', 'nvim', 'coc', 'ale', 'vim_lsp'
                    -- Or a function that returns a table like
                    --   {error=error_cnt, warn=warn_cnt, info=info_cnt, hint=hint_cnt}
                    sources = {'nvim_lsp'},
                    -- displays diagnostics from defined severity
                    sections = {'error', 'warn', 'info', 'hint'},
                    diagnostics_color = {
                        -- Same values like general color option can be used here.
                        error = 'DiagnosticError', -- changes diagnostic's error color
                        warn  = 'DiagnosticWarn',  -- changes diagnostic's warn color
                        info  = 'DiagnosticInfo',  -- Changes diagnostic's info color
                        hint  = 'DiagnosticHint',  -- Changes diagnostic's hint color
                        },
                    symbols = {
                        error = error_symbol,
                        warn  = warn_symbol,
                        info  = info_symbol,
                        hint  = hint_symbol
                        },
                    colored = true, -- displays diagnostics status in color if set to true
                    update_in_insert = false, -- Update diagnostics in insert mode
                    always_visible = false, -- Show diagnostics even if count is 0, boolean or function returning boolean
            }
            },
        lualine_c = {
            {
                    'lsp_progress'
            },
        }
    }
}
END

A nvim/conf/50-telescope.vim => nvim/conf/50-telescope.vim +32 -0
@@ 0,0 1,32 @@
lua << END
require('telescope').setup{
  defaults = {
    -- Default configuration for telescope goes here:
    -- config_key = value,
    mappings = {
      i = {
        -- map actions.which_key (default: <C-/>)
        -- actions.which_key shows the mappings for your picker,
        -- e.g. git_{create, delete, ...}_branch for the git_branches picker
        ["<C-/>"] = "which_key"
      }
    }
  },
  pickers = {
    -- Default configuration for builtin pickers goes here:
    -- picker_name = {
    --   picker_config_key = value,
    --   ...
    -- }
    -- Now the picker_config_key will be applied every time you call this
    -- builtin picker
  },
  extensions = {
    -- Your extension configuration goes here:
    -- extension_name = {
    --   extension_config_key = value,
    -- }
    -- please take a look at the readme of the extension you want to configure
  }
}
END

M nvim/conf/50-treesitter.vim => nvim/conf/50-treesitter.vim +1 -1
@@ 29,6 29,6 @@ require'nvim-treesitter.configs'.setup {
        list_definitions = "gnD"          -- mapping to list all definitions in current file
      }
    },
    ensure_installed = 'all' -- one of 'all', 'language', or a list of languages
    ensure_installed = "maintained" -- one of 'all', 'language', or a list of languages
}
EOF

M nvim/conf/70-mappings.vim => nvim/conf/70-mappings.vim +2 -8
@@ 6,13 6,7 @@ inoremap <silent> <F7> <C-\><C-n>:FloatermToggle<CR>
tnoremap <silent> <F7> <C-\><C-n>:FloatermToggle<CR>
" }}}

" defx {{{
map <silent><F1> :Defx -columns=git:icons:filename:type -split=vertical -winwidth=50 -direction=topleft<CR>
nmap <silent><Leader>f :Defx -columns=git:icons:filename:type `expand('%:p:h')` -search=`expand('%:p')`<CR>
" }}}

" telescope {{{
nnoremap <silent> gf <cmd>lua require('telescope.builtin').git_files(require('telescope.themes').get_dropdown())<CR>
nnoremap <silent> gr <cmd>lua require('telescope.builtin').treesitter(require('telescope.themes').get_dropdown())<CR>
nnoremap <silent> <Leader>s <cmd>lua require('telescope.builtin').grep_string(require('telescope.themes').get_dropdown())<CR>
nnoremap <silent> <Leader>f <cmd>lua require'telescope.builtin'.find_files(require('telescope.themes').get_dropdown({}))<cr>
nnoremap <silent> <Leader>s <cmd>lua require('telescope.builtin').live_grep(require('telescope.themes').get_dropdown({prompt_prefix='🔎'}))<CR>
" }}}