4

I know that similar things were asked here several times. I know that to repeat a motion ; works. Unless it doesn't(in case there is count for example), but then repmo.vim usually works. And I know that . works for changes.

The thing is that repmo.vim is stupid, and thus provides no solution for complicated things such as [m,[c, [M. When I tried to do so(add this motion to its list), it didn't work.

So, any solution for this that I missed? Doing norm ']m' and then @: is an option, but I don't really like it. The forward and rev capability of repmo.vim is nice.

Thanks!

eyal karni
  • 1,106
  • 9
  • 33

3 Answers3

4

Plugin repmo-vim by Andy Wakula

The plugin #2174 listed on https://www.vim.org/scripts is, according to the description, outdated:

2016 Nov 22 started a new script at https://github.com/Houl/vim-repmo

The new plugin on github works for me when repeating, e.g. ]m/[m and ]M/[M with ; and ,. My minimal configuration looks like using vim8 packages (vim 8.1.560 on macOS 10.12):

~/.vim
❯ tree
.
├── pack
│   └── repeat-complicated-motions
│       └── start
│           └── repmo-vim
│               ├── README.markdown
│               └── autoload
│                   └── repmo.vim
└── vimrc

5 directories, 3 files
" ~/.vim/vimrc
source $VIMRUNTIME/defaults.vim

map <expr> ; repmo#LastKey(';')|sunmap ;
map <expr> , repmo#LastRevKey(',')|sunmap ,

" Still repeat fFtT (now with counts):
noremap <expr> f repmo#ZapKey('f')|sunmap f
noremap <expr> F repmo#ZapKey('F')|sunmap F
noremap <expr> t repmo#ZapKey('t')|sunmap t
noremap <expr> T repmo#ZapKey('T')|sunmap T

" Now following can also be repeated with `;` and `,`:
for keys in [ ['[[', ']]'], ['[]', ']['], ['[m', ']m'], ['[M', ']M'], ['[c', ']c'] ]
    execute 'noremap <expr> '.keys[0]." repmo#SelfKey('".keys[0]."', '".keys[1]."')|sunmap ".keys[0]
    execute 'noremap <expr> '.keys[1]." repmo#SelfKey('".keys[1]."', '".keys[0]."')|sunmap ".keys[1]
endfor

Example java file:

public class Factorial
{
    public static void main(String[] args)
    {   final int NUM_FACTS = 100;                                 // ; after [m
        for(int i = 0; i < NUM_FACTS; i++)
            System.out.println( i + "! is " + factorial(i));
    }                                                              // , after ]M

    public static int factorial(int n)
    {   int result = 1;                                            // [m
        for(int i = 2; i <= n; i++)
            result *= i;                                           // CURSOR
        return result;
    }                                                              // ]M
}
// vim: ft=java

Also when I open a diff (e.g. with :Gdiff from vim-fugitive), repeating ]c and [c are possible.

<Plug> mappings of ftplugins

Another possible issue with [m, [M is that you have to remap them for filetypes with overwrites and you want to use the overwrites. Examples are python, vimscript, and ruby. Unfortunately, many ftplugins do not provide them as <plug> mappings which repmo-vim needs.

The ftplugin vim-pythonsense provides them as <plug> mappings:

" ~/.vim/after/ftplugin/python.vim
map <expr><buffer> ]] repmo#Key('<plug>(PythonsenseStartOfNextPythonClass)', '<plug>(PythonsenseStartOfPythonClass)')|sunmap <buffer> ]]
map <expr><buffer> [[ repmo#Key('<plug>(PythonsenseStartOfPythonClass)', '<plug>(PythonsenseStartOfNextPythonClass)')|sunmap <buffer> [[
map <expr><buffer> ][ repmo#Key('<plug>(PythonsenseEndOfPythonClass)', '<plug>(PythonsenseEndOfPreviousPythonClass)')|sunmap <buffer> ][
map <expr><buffer> [] repmo#Key('<plug>(PythonsenseEndOfPreviousPythonClass)', '<plug>(PythonsenseEndOfPythonClass)')|sunmap <buffer> []
map <expr><buffer> ]m repmo#Key('<plug>(PythonsenseStartOfNextPythonFunction)', '<plug>(PythonsenseStartOfPythonFunction)')|sunmap <buffer> ]m
map <expr><buffer> [m repmo#Key('<plug>(PythonsenseStartOfPythonFunction)', '<plug>(PythonsenseStartOfNextPythonFunction)')|sunmap <buffer> [m
map <expr><buffer> ]M repmo#Key('<plug>(PythonsenseEndOfPythonFunction)', '<plug>(PythonsenseEndOfPreviousPythonFunction)')|sunmap <buffer> ]M
map <expr><buffer> [M repmo#Key('<plug>(PythonsenseEndOfPreviousPythonFunction)', '<plug>(PythonsenseEndOfPythonFunction)')|sunmap <buffer> [M

Also the ftplugin vimtex provides them as <plug> mappings and the configuration becomes:

" ~/.vim/after/ftplugin/tex.vim
map <expr><buffer> ]] repmo#Key('<plug>(vimtex-]])', '<plug>(vimtex-[[)')|sunmap <buffer> ]]
map <expr><buffer> [[ repmo#Key('<plug>(vimtex-[[)', '<plug>(vimtex-]])')|sunmap <buffer> [[
map <expr><buffer> ][ repmo#Key('<plug>(vimtex-][)', '<plug>(vimtex-[])')|sunmap <buffer> ][
map <expr><buffer> [] repmo#Key('<plug>(vimtex-[])', '<plug>(vimtex-][)')|sunmap <buffer> []
map <expr><buffer> ]m repmo#Key('<plug>(vimtex-]m)', '<plug>(vimtex-[m)')|sunmap <buffer> ]m
map <expr><buffer> [m repmo#Key('<plug>(vimtex-[m)', '<plug>(vimtex-]m)')|sunmap <buffer> [m
map <expr><buffer> ]M repmo#Key('<plug>(vimtex-]M)', '<plug>(vimtex-[M)')|sunmap <buffer> ]M
map <expr><buffer> [M repmo#Key('<plug>(vimtex-[M)', '<plug>(vimtex-]M)')|sunmap <buffer> [M

If you want to use the ones in $VIMRUNTIME/ftplugin/{python,ruby,vim}.vim you have to rewrite them as <plug> mappings and put them into repmo#Key.

What file types are you interested in?

Hotschke
  • 4,740
  • 26
  • 37
  • I spend like two hours trying to presuade vim to load it. It did work in one of my environment (I have gui and command line environment). But no more. I simply source it from .vimrc before anything else. Even though it is on the autoload folder it ignores it. I give up. – eyal karni Dec 06 '18 at 20:19
  • I can see that autoload was run from echoing one of the variables. But motions are not repeated. It did work earlier. – eyal karni Dec 06 '18 at 20:19
  • 1
    Hi eyal karni. Sorry to hear that you could not make it work. I have updated the question with a more explicit description of a minimal config with java code for illustration. Could you backup your vim config and work with an empty ~/.vim folder? Place everything I mentioned in my answer accordingly ($ git clone https://github.com/Houl/repmo-vim ~/.vim/pack/repeat-complicated-motions/start/repmo-vim and the vimrc should be identical). Also please post the result from :nmap [m which should be nox [m * repmo#SelfKey('[m', ']m') and your vim version 8.x.xxxx and OS. – Hotschke Dec 07 '18 at 12:28
  • 1
1

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.

Thanks to @romainl for his hints.

Vivian De Smedt
  • 16,336
  • 3
  • 18
  • 37
  • 1
    Hi Vivian. It looks like you copied this answer from another one of your answes here. In general if the same answer can apply to the same question it may be a duplicate, but in this case it looks like you are recommending your plugin. Can you please edit your answer to address the question's specifics. – Dom Oct 20 '23 at 05:06
  • Hi @Dom the original question is about ]m and that was actually also my motivation for the plugin. My answer mention ]m. I'm willing to change my answer but I'll be glad if you could give me some hints. – Vivian De Smedt Oct 20 '23 at 05:34
  • 1
    Currently I use the repmo plugin , but might try yours one day :) Are they compatible? – eyal karni Oct 20 '23 at 15:54
  • I'm not sure I understand what compatible means in this context. Feel free to tell me more. If it works fine for you with repmo maybe I should give it another try ;-) – Vivian De Smedt Oct 20 '23 at 16:20
  • 1
    I think @Dom’s point is that this answer should contain some specific address of the question. For example: « to repeat ]m after installing the plugin, just press ; », and so forth. The answer reads a bit more like an ad than a « here’s the solution to your problem » – D. Ben Knoble Oct 20 '23 at 16:22
  • @eyalkarni I understand the answer addressed your problem. Maybe could you accept it. It allow the question to rest :-) – Vivian De Smedt Oct 20 '23 at 16:53
  • 1
    I already accepted it. – eyal karni Oct 21 '23 at 20:40
  • Sorry my mistake with the new css I don't see the colors correctly :-|. I'll get used to it :-) – Vivian De Smedt Oct 22 '23 at 05:21
  • @eyalkarni I have been asked to document remotions and in particular the difference with repmo. Are you able to use repmo to remap ]m for file type specific motion (e.g. for python filetype or even better for python filetype with pythonsense plugin)? If you tell me yes I'll post a question about that ;-) – Vivian De Smedt Nov 25 '23 at 02:06
  • 1
    It indeed doesnt work it seems. [d does for example (diagnostics). – eyal karni Dec 02 '23 at 02:28
  • Thanks for the feedback :-) – Vivian De Smedt Dec 02 '23 at 05:09
0

After a long time it didn't really work I returned to that, slightly improving the answer by @Hotschke.

Now, in addition to what he said, for the maps that I defined myself, I first define the mappings as usual, and support for repeat is established like so (using repmo) :

nmap [a :ALEPrevious<CR>
nmap ]a :ALENext<CR>
nmap ]E <Plug>(coc-diagnostic-next)
nmap [E <Plug>(coc-diagnostic-prev)
nmap ]e <Plug>(coc-diagnostic-next-error)
nmap [e <Plug>(coc-diagnostic-prev-error)
nmap [h <Plug>(GitGutterPrevHunk)
nmap ]h <Plug>(GitGutterNextHunk)

for keys in [[']E','[E'],[']a','[a'],[']e','[e'],[']h','[h']] call RepRemap(keys[0],keys[1]) endfor

Needed function:

"Remaps repeat pairs
function! RepRemap(mapA,mapB)
let varA=maparg(a:mapA,'n')
let varB=maparg(a:mapB,'n')
execute "nmap <expr> " . a:mapA . " repmo#Key('".varA ."', '". varB. "')"
execute "nmap <expr> " . a:mapB . " repmo#Key('".varB ."', '". varA. "')"
endfunction

Possibly using map and sunmap is better.

eyal karni
  • 1,106
  • 9
  • 33