Skip to content

Statusline integration

Harjot Gill edited this page May 7, 2022 · 10 revisions

Use built-in function

Coc status (Typescript version and reported issues)

Add section %{coc#status()} to your statusline option.

Function coc#status() includes status information of diagnostic of current buffer and all status messages received from extensions.

Current Function Symbol

If you want to display the name of the current enclosing symbol (eg. function name), you can use the b:coc_current_function buffer-bound variable.

To update its value automatically (updated on CursorHold), you need to set "coc.preferences.currentFunctionSymbolAutoUpdate": true in your config.

Alternatively, if you want to handle the updates manually, you can call CocAction("getCurrentFunctionSymbol"), which will return the symbol name and update the b:coc_current_function variable.

Use manual function

You can use b:coc_diagnostic_info and g:coc_status to build your own status function, like:

function! StatusDiagnostic() abort
  let info = get(b:, 'coc_diagnostic_info', {})
  if empty(info) | return '' | endif
  let msgs = []
  if get(info, 'error', 0)
    call add(msgs, 'E' . info['error'])
  endif
  if get(info, 'warning', 0)
    call add(msgs, 'W' . info['warning'])
  endif
  return join(msgs, ' '). ' ' . get(g:, 'coc_status', '')
endfunction

Then add %{StatusDiagnostic()} ` to your 'statusline' option.

Integration with eleline.vim

It just works.

Integration with vim-airline

airline now works out of box.

Check out :h airline-coc for customization details.

Integration with lightline.vim

Use configuration like:

function! CocCurrentFunction()
    return get(b:, 'coc_current_function', '')
endfunction

let g:lightline = {
      \ 'colorscheme': 'wombat',
      \ 'active': {
      \   'left': [ [ 'mode', 'paste' ],
      \             [ 'cocstatus', 'currentfunction', 'readonly', 'filename', 'modified' ] ]
      \ },
      \ 'component_function': {
      \   'cocstatus': 'coc#status',
      \   'currentfunction': 'CocCurrentFunction'
      \ },
      \ }

Integration with nvim-notify

Status and Diagnostics

coc

Add the following snippet to your init.vim, after notify extension is loaded and vim.notify is pointing to require("notify").

lua << EOF

local coc_status_record = {}

function coc_status_notify(msg, level)
  local notify_opts = { title = "LSP Status", timeout = 500, hide_from_history = true, on_close = reset_coc_status_record }
  -- if coc_status_record is not {} then add it to notify_opts to key called "replace"
  if coc_status_record ~= {} then
    notify_opts["replace"] = coc_status_record.id
  end
  coc_status_record = vim.notify(msg, level, notify_opts)
end

function reset_coc_status_record(window)
  coc_status_record = {}
end

local coc_diag_record = {}

function coc_diag_notify(msg, level)
  local notify_opts = { title = "LSP Diagnostics", timeout = 500, on_close = reset_coc_diag_record }
  -- if coc_diag_record is not {} then add it to notify_opts to key called "replace"
  if coc_diag_record ~= {} then
    notify_opts["replace"] = coc_diag_record.id
  end
  coc_diag_record = vim.notify(msg, level, notify_opts)
end

function reset_coc_diag_record(window)
  coc_diag_record = {}
end
EOF

function! s:DiagnosticNotify() abort
  let l:info = get(b:, 'coc_diagnostic_info', {})
  if empty(l:info) | return '' | endif
  let l:msgs = []
  let l:level = 'info'
   if get(l:info, 'warning', 0)
    let l:level = 'warn'
  endif
  if get(l:info, 'error', 0)
    let l:level = 'error'
  endif
 
  if get(l:info, 'error', 0)
    call add(l:msgs, ' Errors: ' . l:info['error'])
  endif
  if get(l:info, 'warning', 0)
    call add(l:msgs, ' Warnings: ' . l:info['warning'])
  endif
  if get(l:info, 'information', 0)
    call add(l:msgs, ' Infos: ' . l:info['information'])
  endif
  if get(l:info, 'hint', 0)
    call add(l:msgs, ' Hints: ' . l:info['hint'])
  endif
  let l:msg = join(l:msgs, "\n")
  if empty(l:msg) | let l:msg = ' All OK' | endif
  call v:lua.coc_diag_notify(l:msg, l:level)
endfunction

function! s:StatusNotify() abort
  let l:status = get(g:, 'coc_status', '')
  let l:level = 'info'
  if empty(l:status) | return '' | endif
  call v:lua.coc_status_notify(l:status, l:level)
endfunction

function! s:InitCoc() abort
  execute "lua vim.notify('Initialized coc.nvim for LSP support', 'info', { title = 'LSP Status' })"
endfunction

" notifications
autocmd User CocNvimInit call s:InitCoc()
autocmd User CocDiagnosticChange call s:DiagnosticNotify()
autocmd User CocStatusChange call s:StatusNotify()

Intercepting messages

coc-messages

coc.nvim uses echo* commands to write variety of messages. In order to intercept those, monkey patching it by utilizing vim's after directory (see :help after-directory) is one approach.

First, create coc/util.vim file in the autoload after-directory in your vim's runtime path (e.g. ~/.vim/after/autoload). For instance, place the following content in the file ~/.vim/after/autoload/coc/util.vim --

scriptencoding utf-8

if has("nvim")
  " overwrite coc#util#echo_messages function to use notify
  function! coc#util#echo_messages(hl, msgs)
    if a:hl !~# 'Error' && (mode() !~# '\v^(i|n)$')
      return
    endif
    let msgs = filter(copy(a:msgs), '!empty(v:val)')
    if empty(msgs)
      return
    endif
    " map a:hl highlight groups to notify levels
    " if hl matches Error then level is error
    " if hl matches Warning then level is warn
    " otherwise level is info
    let level = 'info'
    if a:hl =~# 'Error'
      let level = 'error'
    elseif a:hl =~# 'Warning'
      let level = 'warn'
    endif
    let msg = join(msgs, '\n')
    call v:lua.coc_notify(msg, level)
  endfunction

  function! coc#util#echo_lines(lines)
    let msg = join(a:lines, "\n")
    call v:lua.coc_notify(msg, 'info')
  endfunction
endif

Next, manually source this file after coc.nvim has initialized. You can modify s:InitCoc function from the previous example/section and add the function coc_notify --

function! s:InitCoc() abort
  " load overrides
  runtime! autoload/coc/util.vim
  execute "lua vim.notify('Initialized coc.nvim for LSP support', 'info', { title = 'LSP Status' })"
endfunction

function coc_notify(msg, level)
  local notify_opts = { title = "LSP Message", timeout = 500 }
  vim.notify(msg, level, notify_opts)
end

REPL

Clone this wiki locally