kristijanhusak / vim-multiple-cursors

True Sublime Text style multiple selections for Vim
MIT License
64 stars 5 forks source link

Replay multi-character maps #3

Closed eapache closed 10 years ago

eapache commented 10 years ago

Also save and replay characters that would otherwise be "lost".

@kris89 this seems to work for me to permit multi-character mappings (like dw) to be replayed in multi-cursor mode although it does introduce a little bit of lag. The lag caused a lot more keys to be dropped, so I adapted and simplified @joeytwiddle's fix for that.

I thought about making the 100m time configurable, but I couldn't figure out how since it isn't really an integer or a string; I don't fully understand how vim's type system works with sleep.

This is my first non-trivial vimscript work so please be patient if I've done something stupid :)

eapache commented 10 years ago

And the third commit fixes one other long-standing annoyance: if you entered insert mode and then went back to normal mode with multiple cursors set (needs let g:multi_cursor_exit_from_insert_mode=0) then the last cursor would get out of sync because esc in vim moves the cursor left, but that only applied to the final cursor in the set. Now we temporarily remap escape so that entering/exiting insert mode with multiple cursors works as expected.

eapache commented 10 years ago

Current version now fixes the lag and uses vim's existing timeoutlen option for the timeout. You have to manually tell it about which insert-mode mappings you want to be carried over into multiple-cursor mode, but otherwise it behaves exactly like standard insert mode.

kristijanhusak commented 10 years ago

@eapache, I am not very familiar with the source code of the plugin, i just took part of merging PRs and only added my small fix which many people found useful.

I tested the functionality you added, but it works for me good only the first time, if for example after the first time i select multiple text and do dw, and then undo everything and try again, my screen freezes. Same thing happens when i try to use cw, sometimes it works, but sometime it freezes. These are the bugs that i found, maybe there is something else that can be fixed also. So for now, i'll not merge it in until it is smoothed out a bit more.

eapache commented 10 years ago

Interesting, I cannot reproduce that issue: I just did several different multi-character operations in and out of multi-cursor mode without problems. Does this happen in a very simple file (i.e. if you create a test file with only the word "abc" repeated a few times) and with other plugins removed? What version of vim are you using?

I just found and fixed one minor issue with the default value of one of the new settings; for me it just caused warnings but everything worked, but on a different vim version it might cause the problems you saw.

If you are not interested in really maintaining this, I am happy to merge it into my own fork and you can put a note in your README about my fork.

eapache commented 10 years ago

Two more minor fixes, but again not ones that I would expect to be related. Did you perhaps try a multi-key map with a number in front (i.e. 5w to move five words, or something like that)? That still doesn't work here, but it never worked in master either...

eapache commented 10 years ago

So I fiddled around with this some more and ended up making it all configurable-by-key but off-by-default. Otherwise pure motion commands (like h) would hang vim (as you reported) if they could not be replayed by any of the cursors.

FWIW, my vimrc on this branch now includes:

let g:multi_cursor_insert_maps={'\':1, 'j':1}
let g:multi_cursor_normal_maps={'c':1, 'd':1, 'r':1}

Which seems to cover 99% of cases for me at least, without breaking anything else (the j in insert mode is because I have jk mapped to <esc>).

More generally, I fixed behaviour for commands preceded by a count (5w should work now, for example) and cleaned up the behaviour of : - it has always exited multi-cursor mode, but previously it left garbage on the ex-line and didn't remove its cursors properly; now it exits cleanly.

joeytwiddle commented 10 years ago

To sleep for the duration specified in a variable, you would need to construct a string and then exec it:

" Initialise option (if not already)
let g:multi_cursor_desired_lag_ms = get(g:, "multi_cursor_desired_lag_ms", 100)

...

exec "sleep " . g:multi_cursor_desired_lag_ms . "m"

It is ugly but I fear that is the VimL way! ;)

eapache commented 10 years ago

Thanks for the tip - I've ended up just polling so that the sleep can be interrupted, but I'm sure it'll come in handy at some point.

eapache commented 10 years ago

@kris89 please let me know if you plan to look at this again or if I should maintain my own fork - I am happy to do so if you don't have the time/inclination to test this again.

eapache commented 10 years ago

I am also happy to split this up into multiple smaller PRs if you'd prefer - I ended up mixing in fixes for a couple of different issues here.

kristijanhusak commented 10 years ago

@eapache, i'm on vacation now, will check it out and merge it at the end of the week.

joeytwiddle commented 10 years ago

About pending keys in the input buffer, I just noticed two built-in functions inputsave() and inputrestore(). They might make for a more efficient solution when we need to empty the input stream, but OTOH they might be more restrictive than handling it ourselves with getchar(0).

eapache commented 10 years ago

I don't think those really do the same thing we are trying to do, if I am reading https://vim.wikia.com/wiki/User_input_from_a_script correctly

kristijanhusak commented 10 years ago

I didn't tested it totally, but since it doesn't break old functionality, i merged it in, so feel free to continue fixing/upgrading, i'll gladly merge it.

eapache commented 10 years ago

thanks!