1

I've been trying to make a dot-repeatable (.) command that should work in both visual and normal mode. The command in question searches for a [] on a line and turns it into a [x], and vise versa.

It works as follows:

   :Fill
[] -----> [x]

   :Fill
[x] ----> []

So far, I managed to create a command that works both in visual and normal mode as follows:

function Fill()
  try
    execute a:firstline . ',' . a:lastline . 'snomagic/[]/[x]/'
  catch
    execute a:firstline . ',' . a:lastline . 'snomagic/[x]/[]/'
  endtry
command -range Fill :<line1>,<line2>call Fill()

However, this command is not repeatable when running the . operator. I've been looking through the documentation :help . and :help :command. I tried sourcing the above command from a different file, but I couldn't make that Work. Neither do I understand how to make this command repeatable from other vi.stackexchange questions. Your help is greatly appreciated, thanks in advance!

1 Answer 1

2

A few things first…

  • You should probably add the range argument to your function definition. With it, the function is only called once. Without it, the function will be called once for every line in the range.
  • Your function doesn't do what you describe. In order to remove potential noise, you should either change it to match the description or change the description to match the functionality.

Now…

:help . can be used to repeat the effect of normal mode and visual mode commands—what Vim calls a "change"—but it can't be used for Ex commands, for which there is :help @: (general case) and :help & and friends (for repeating :help :s).

It can be used to repeat very simple mappings, like:

nnoremap <F5> x

but only superficially. Even in such a simple case, . doesn't really repeat the mapping itself, only the effect of the right-hand side of the mapping (the "change")… and only because it was a normal mode command. The mapping below, simple as it is, is not "repeatable":

nnoremap <F5> <Cmd>s/foo/bar<CR>

Basically, Vim doesn't provide any public API for making commands (whatever their mode) repeatable with . and it would probably require a lot of work to do so, because . doesn't repeat "commands" to begin with.

The only workaround I know of is to use Tim Pope's Repeat plugin, which effectively overrides the native . with a custom . that can be explicitly tapped into to make mappings repeatable.

1
  • 1
    Great catch about the function @romainl! I modified the function to work as described.
    – melvio
    Commented May 6 at 6:30

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.