0

It is possible in Vim to repeat:

  • Last edition with .
  • Last substitution with &
  • Last macro execution with @@

But how to repeat the last motion?

The , and ; repeats the last f, F, t or T move but what for the other moves.

I'm particularly interested to the ]m motion defined in vim-pythonsense

Following the solution I have tested repmo

I had also a look at repeatable-motions mentioned in the solution

But I had no luck with the ]m motion and like.

2
  • 1
    "How to repeat motions?" or "How to repeat arbitrary mappings from third-party scripts?"?
    – romainl
    Oct 18, 2023 at 15:34
  • @romainl, thanks for asking. I have adapted the title of the question accordingly. Oct 18, 2023 at 15:48

2 Answers 2

1

Built-in motions are kind of special compared to other commands but custom "motions" like that [m are really just mappings, made with :help :map, that happen to move the cursor without side-effects.

If you want to repeat a "motion", that "motion" has to be remembered somewhat but Vim doesn't and :help CursorMoved happens too late and doesn't work well with operator-pending mode anyway. So this can only be done by wrapping individual commands/mappings, which is more or less what the linked plugins do.

In this case, it would look a bit like this:

" recursive because the [m you want to repeat is a mapping
nmap [m <Cmd>let g:latest_motion = v:count1 .. '[m'<CR>[m

which saves [count][m in g:latest_motion before executing it, and:

nmap <expr> <key> get(g:, 'latest_motion', ';')

which lets you press <key> to execute the macro saved in g:latest_motion. Of course, you would need to handle the three modes in which motions are relevant, as well as count and (possibly) direction, to make the whole thing dependable.

1
  • Thanks for your answer. I'll work on a solution in that direction. Oct 19, 2023 at 7:05
0

I have created a small vim-remotions plugin that allows to repeat the last motion using the ; and , keys (like for the f and t motions).

By default it repeats the following motions: ]m, ]M, ]], ][, }, g;, ]b, ]l, ]q, ]t, ]g.

It use the motion as they are defined in the buffer by the filetype.

The list of motions it repeats is configurable.

It can repeat the motion and their count or only the motion.

It can repeat the motion in the direction of the initial motion (like ; and , are doing for f and t) or in the direction of the document if considered more intuitive.

Here is the idea selected to do the job:

The plugin:

  • map original motion to a <Plug> version to not lose them
  • map the selected motion to a function that:
    • store the necessary information about the motion
      • the backward and forward associated sequence
      • the count if any
    • use the <Plug> version to execute the motion
  • map ; and , to a function that used the stored information to repeat the motion.

The mappings are done in at the buffer level since the motion can be filetype specific.

The mappings are redone when the filetype is set or changed.

Thanks to @romainl for his hints.

1
  • 2
    In this answer, it might be worth talking about any special code or techniques used so that future readers benefit even more.
    – D. Ben Knoble
    Oct 20, 2023 at 16:24

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.