Search code examples
vimneovim

How to get current command register value/name in Vim?


Currently I have this mapping:

  nmap <silent> x :set opfunc=SpecialChange<CR>g@
  function! SpecialChange(type)
    silent exec 'normal! `[v`]"_dP'
  endfunction

it helps me to substitute some value with the default register value.

However, I want to be able to replace the value with some specific register, for this I need to know the current command register value or name (or better both). For example, when I press "axiw" I want to substitute the word with a register, but I need to understand that a register was pressed not b or c or something else. Is there a way to do this?


Solution

  • Taking inspiration from the example provided under :help :map-operator, this is how your function should look:

    nnoremap <expr> <key> SpecialChange()
    function! SpecialChange(type = '')
        if a:type == ''
            set opfunc=SpecialChange
            return 'g@'
        endif
        execute 'normal! `[v`]"_d"' .. v:register .. 'P'
    endfunction
    

    Explanation:

    • We use an <expr> mapping because of this quote:

      An <expr> mapping is used to be able to fetch any prefixed count and register.

    • SpecialChange() takes a single type argument, with an empty string as default value.

    • When called without arguments, the function sets opfunc to itself and finally returns g@. This is another way of doing:

      :set opfunc=SpecialChange<CR>g@
      
    • When called as an operatorfunc, SpecialChange() gets a type argument with a value of line, char, or block, so we skip the conditional and go directly to the meat of the function, where we can use v:register because we are in an <expr> mapping:

      execute 'normal! `[v`]"_d"' .. v:register .. 'P'
      

    It's all kind of contrived but that's what we have to work with.