I am using coc.vim in neovim. coc.vim suggests the following mapping for jumping to the definition of a class/method.

nmap <silent> gd <Plug>(coc-definition)

If there is only a single matching definition, pressing gd will immediately open the definition in the current window.

If there are multiple matches, coc shows a preview window with the list of matching files. It is possible to scroll through the results with j/k. Pressing tab displays the following prompt, for opening the current selection.

Choose action:
[o]pen, (p)review, (q)uickfix, (t)abe, (d)rop, (v)split, (s)plit:
  • Is the above prompt a standard part of vim or is it part of coc.vim?
  • Is it possible to force this prompt, even if there is only a single hit?
  • If not, how can I force vim to open coc-definition in a new vertical split?
  • That doesn't look like any vim prompt I've ever seen
    – D. Ben Knoble
    Commented Nov 4, 2019 at 18:07

6 Answers 6


I inject my own way of opening files in CoC with:

let g:coc_user_config = {}
let g:coc_user_config['coc.preferences.jumpCommand'] = ':SplitIfNotOpen4COC'

Then the command is defined in my lh-vim-lib plugin to search if the buffer is already opened or not. Having more control is possible.

To use the prompt already provided by CoC, you may have to search in its source code.

  • 1
    Thank you. Setting coc.preferences.jumpCommand to vsp worked. I have just started learning vim, so I couldn't fully understand lh#coc#_split_open. I don't want to copy paste blindly, and will give it a second look after learning vimscript.
    – Joyce Babu
    Commented Nov 4, 2019 at 20:23
  • lh#coc#_split_open() is a COC specific wrapper around another function of mine: the one that is a kind of :sb_or_sp (if it were to exist). Commented Nov 4, 2019 at 23:52
  • After reading a few tutorials, I could understand parts of your function code. The first argument, if prefixed with +, is stored in where variable and is executed as an ex command when the file is not open in any existing window. But what is the content of the where variable? Is it set by coc, or do you use pass it when manually invoking SplitIfNotOpen4C0C?
    – Joyce Babu
    Commented Nov 5, 2019 at 6:48
  • It's COC doing. It encodes a few things in the filenames in order to specify the position the cursor shall jump to. NB: my function will return a negative number only if it cannot jump into a window (new or not) containing the requested file. Commented Nov 5, 2019 at 15:19
  • 1
    @LucHermitte I resolved this issue quite satisfactorily based on what I gleaned from github.com/neoclide/coc.nvim/issues/1249, I have 4 different vim maps which implement the 4 ways to open definition: regular (in present window), in split, in vsplit, in new tab. The main thing was that the coc instructions/doc never mentioned these alternate ways of going to definition. As for going to references or implementation I use them less and also the cocList comes with binds for these different opening modalities.
    – Steven Lu
    Commented Nov 24, 2019 at 19:58

You can call the action jumpDefinition with a command as argument:

nmap <silent> gs :call CocAction('jumpDefinition', 'split')<CR>
nmap <silent> gd :call CocAction('jumpDefinition', 'vsplit')<CR>
nmap <silent> gt :call CocAction('jumpDefinition', 'tabe')<CR>

To get more information:

:h coc-action-jumpDefinition

open coc config use ":CocConfig" and add this config to your coc-settings.json

"coc.preferences.jumpCommand": "vsplit"
nmap <silent> gd :call CocAction('jumpDefinition', 'vsplit')<CR>

This does NOT WORK with vim-go plugin use, because vim-go or other plugin will cover the map, it will remap you key with <buffer> options, that will make you key be remapped in current buffer.

my current solution is, map it when enter buffer.

"The functions that will run when a buffer is entered
func! CallAtBufEnter()
    "for `gd` jump, vsp than jump
    nmap <buffer> gd :call CocAction('jumpDefinition', 'vsplit')<CR>
autocmd BufEnter * call CallAtBufEnter()
  • Welcome to Vi and Vim! My general advice would be to disable conflicting buffer-local mappings if that's important to you, rather than forcing that mapping globally this way (seems like it could lead to a hard-to-track down bug if you ever do want to override a buffer to have a specific gd mapping.)
    – D. Ben Knoble
    Commented Nov 8, 2021 at 15:40
  • @D.BenKnoble Do you know how to disable conflicting mapping? I have not been able to find a way. But I found that for vim-go plugin can set let g:go_def_mapping_enabled=0 for disable remap.
    – rwxe
    Commented Nov 13, 2021 at 10:11
  • Generally you need to look at the plugins documentation, yes
    – D. Ben Knoble
    Commented Nov 13, 2021 at 12:20

the answer from Luc Hermitte :SplitIfNotOpen4COC didn't work on my case. but, combining between Mateus C answer with Luc Hermitte answer seems to be worked for me after i added :

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)

to jump to definition. i also added :

let g:coc_user_config = {}
let g:coc_user_config['coc.preferences.jumpCommand'] = [it is up to you]

i changed it is up to you with :

split to split between window horizontally

tabe to jump to reference on a new window

vsplit to split between window vertically


Somehow none of the above answers worked for me. Below did the trick in my case:

nmap <silent> F <Plug>(coc-definition)
nnoremap <silent> F :call <SID>jump_definition()<CR>
function! s:jump_definition()
    call CocAction('jumpDefinition', 'vsplit')
  • The second mapping overrides the first; are both needed? Why? Also, the second mapping is very similar to some mappings in other answers; curious that it didn't work for you.
    – D. Ben Knoble
    Commented Sep 15, 2022 at 12:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.