3

I need to manipulate the dot command without directly editing the buffer for a plugin I'm developing.

The plugin needs to manually append text to the dot command that will be executed while in insert mode.

I would like to have as little side effects as possible.

Is this possible?

10
  • 1
    I don't think this is possible because, as you say, it is read-only (:h registers confirms this). Can you achieve your plugin's aim a different way? May 24, 2021 at 21:44
  • 3
    would really like to hear what the use-case is here, as the dot register is quite rarely used, and very different from other registers
    – Mass
    May 25, 2021 at 4:42
  • @mass I have a plugin (github.com/tversteeg/registers.nvim) that will open a popup with all registers which you can then choose to paste when pressing <C-R> in insert mode. The problem is that during the opening of the window the mode is changed, so the dot command doesn't function properly after that: github.com/tversteeg/registers.nvim/issues/19
    – tversteeg
    May 25, 2021 at 7:10
  • @tversteeg what about using <cmd> to not change the mode?
    – Maxim Kim
    May 25, 2021 at 7:32
  • 1
    C-O shouldn't be there then. Cause <cmd> was introduced exactly for this.
    – Maxim Kim
    May 25, 2021 at 7:37

2 Answers 2

3

As I understand it, the problem is that your plugin will do an operation which leaves the "dot" repeat command in an inconsistent state. From the question, I don't know what this operation is, but generally you can re-structure your plugin in a way that it will work as expected.

You can use the g@ operator feature to run arbitrary commands which are repeatable. The following is an example using wincmd, however you can replace this with another command or function call.

This is a completely native method which should be preferred to e.g., vim-repeat which require re-mapping the dot command.

function! RepWincmd(...)
    execute (v:count ? v:count : s:rep[1]) 'wincmd' s:rep[0]
endfunction

function! s:setup(rep, ...)
    let s:rep = [a:rep, v:count ? v:count : get(a:000, 0, 1)]
    set operatorfunc=RepWincmd
    return 'g@l'
endfunction

" optional number is the default shift amount
nnoremap <expr> <c-w>- <sid>setup('-', 3)
nnoremap <expr> <c-w>+ <sid>setup('+', 3)
nnoremap <expr> <c-w>< <sid>setup('<', 5)
nnoremap <expr> <c-w>> <sid>setup('>', 5)
3

You will have to remap a . to do series of changes that your mapping introduces.

It is not that simple to do and it might interfere with other things user might have mapped on the dot like vim-repeat of Tim Pope (which does exactly that and exposes API for other plugins to have complex repeats with a dot)

Your Answer

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

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