onivim / oni2

Native, lightweight modal code editor
https://v2.onivim.io
MIT License
7.84k stars 282 forks source link

Feature: Multiple Cursors #288

Open bryphe opened 5 years ago

bryphe commented 5 years ago

A feature we'd love to have (that actually works pretty well in VSCode + Vim plugins!) is multiple cursor support. As @CrossR mentioned in a discussion - you can physically do most of the operations with macros or similar - but the instant feedback you get with multiple cursors makes it much easier to check what you are doing and iterate.

This 'instant feedback' is a key value of our project, and makes a lot of sense to include.

We're thinking about possible approaches to this. It likely won't be in for our 'MVP' release, but certainly something we'll investigate post-MVP.

Some possibilities:

'User space': Onivim 2

I considered implementing a concept of this in 'user space' in Oni1/2 - essentially tracking multiple cursor positions, and then 'applying' key commands to each of those positions. In effect, the logic would be (in pseudocode)

/* Sort cursors by position, and then work with them in _reverse_ order */
cursors = cursors |> sort |> reverse
foreach cursor in cursors
   nvim_set_cursor cursor.position
   nvim_input key

The reversal of ordering is important, because applying edits at 'earlier' positions will impact the cursor positions of all other cursors in the line (for example, inserting 'a' means either we need to move all our other cursor positions by 1 character, otherwise we'll insert at the wrong spot).

I thought about this mainly for insert mode, but also toyed with normal mode. The challenging issue I was thinking about was the case where you might have multiple cursors on adjacent lines:

...
|abc
|def
|ghi
...

And you issue a command like d3k - what is the expected output? Do some cursors get 'consumed' by that operation? I hadn't thought through those cases, but perhaps some of the other strategies would be helpful

'User space': Multi-cursor vim plugins

https://github.com/mg979/vim-visual-multi looks like a very promising plugin! Perhaps we could include / bundle this as a way to get similar functionality, without needing anything in Onivim 2's layer (thanks @jordwalke)

In Neovim directly

It sounds like there is on-going work in core Neovim, tracked by this issue (and following from the inccommand work by @justinmk): https://github.com/neovim/neovim/issues/7257

justinmk commented 5 years ago

It sounds like there is on-going work in core Neovim, tracked by this issue (and following from the inccommand work by @justinmk):

Yes. My main goal for the summer is to finish that. But given how long it's taken me I wouldn't blame anyone for not waiting :)

bryphe commented 5 years ago

A few open questions:

Perhaps focusing on insert-mode first for multiple cursors would be ideal, and then we could branch out from there as we solidify the requirements for normal mode.

mizagog commented 5 years ago

Just a suggestion, maybe we can get a way to "filter out" selections once they were made like Kakoune dose? this functionality can make multi cursor as useful as G and S combined.

despairblue commented 5 years ago

Regarding the multiple cursors without mouse, check out atoms vim plugin, it has a feature Called occurrences: https://github.com/t9md/atom-vim-mode-plus/wiki/OccurrenceModifier

It's probably my most used feature day to day, apart from moving the cursor around.

There is also a YouTube video https://youtu.be/01yHgi59ASg

I really can't put in words how well that works in practice, I use that for all kind of refactors, from simple renames to things like documenting route handlers or taking a JS module exporting multiple function and turning it into a module that exports a class with all those functions.

JakeHedman commented 3 years ago

A few open questions:

  • What should the gesture be for creating multiple cursors? In VSCode, I believe it is 'ctrl+click'. In the Vim world, having a visual selection and pressing I is sort of like having multiple cursors.
  • What should the correct behavior be in normal mode, when deleting / modifying ranges that overlap multiple cursors?

Perhaps focusing on insert-mode first for multiple cursors would be ideal, and then we could branch out from there as we solidify the requirements for normal mode.

I love the way terryma/vim-multiple-cursors does it:

normal mode / visual mode

visual mode when multiple lines are selected

John0x commented 3 years ago

This would be awesome Neither the vs code vim plugin nor the ideavim one work properly with multi cursor. Having a good implementation in oni would definitely be an advantage and might convince people to prefer it over the vim emulation plugins.