Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/smoka7/multicursors.nvim
A multi cursor plugin for Neovim.
https://github.com/smoka7/multicursors.nvim
neovim neovim-plugin nvim nvim-plugin
Last synced: about 7 hours ago
JSON representation
A multi cursor plugin for Neovim.
- Host: GitHub
- URL: https://github.com/smoka7/multicursors.nvim
- Owner: smoka7
- License: mit
- Created: 2023-07-01T13:11:46.000Z (over 1 year ago)
- Default Branch: main
- Last Pushed: 2024-08-08T15:23:36.000Z (3 months ago)
- Last Synced: 2024-08-08T18:14:01.969Z (3 months ago)
- Topics: neovim, neovim-plugin, nvim, nvim-plugin
- Language: Lua
- Homepage:
- Size: 241 KB
- Stars: 419
- Watchers: 6
- Forks: 15
- Open Issues: 11
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
Awesome Lists containing this project
README
# Multicursors.nvim
The Multicursor Plugin for Neovim extends the native Neovim text editing capabilities, providing a more intuitive way to edit repetitive text with multiple selections. With this plugin, you can easily create and manage multiple selections, perform simultaneous edits, and execute commands on all selections at once.# Requirements
- Neovim >= **0.9.0**
# Installation
Install with your preferred package manager:
```lua
-- lazy.nvim:
{
"smoka7/multicursors.nvim",
event = "VeryLazy",
dependencies = {
'nvimtools/hydra.nvim',
},
opts = {},
cmd = { 'MCstart', 'MCvisual', 'MCclear', 'MCpattern', 'MCvisualPattern', 'MCunderCursor' },
keys = {
{
mode = { 'v', 'n' },
'm',
'MCstart',
desc = 'Create a selection for selected text or word under the cursor',
},
},
}
```# Default Configuration
Click me
```lua
{
DEBUG_MODE = false,
create_commands = true, -- create Multicursor user commands
updatetime = 50, -- selections get updated if this many milliseconds nothing is typed in the insert mode see :help updatetime
nowait = true, -- see :help :map-nowait
mode_keys = {
append = 'a',
change = 'c',
extend = 'e',
insert = 'i',
}, -- set bindings to start these modes
normal_keys = normal_keys,
insert_keys = insert_keys,
extend_keys = extend_keys,
-- see :help hydra-config.hint
hint_config = {
float_opts = {
border = 'none',
},
position = 'bottom',
},
-- accepted values:
-- -1 true: generate hints
-- -2 false: don't generate hints
-- -3 [[multi line string]] provide your own hints
-- -4 fun(heads: Head[]): string - provide your own hints
generate_hints = {
normal = true,
insert = true,
extend = true,
config = {
-- determines how many columns are used to display the hints. If you leave this option nil, the number of columns will depend on the size of your window.
column_count = nil,
-- maximum width of a column.
max_hint_length = 25,
}
},
}
```# Usage
| Command | Description |
|---|---|
| MCstart | Select the word under the cursor and start listening for the actions. In visual mode, it acts like `MCvisual`. |
| MCvisual | Select the last visual mode selection and start listening for the actions. |
| MCpattern | Prompts for a pattern and selects every match in the buffer. |
| MCvisualPattern | Prompts for a pattern and selects every match in the visual selection. |
| MCunderCursor | Select the char under the cursor and start listening for the actions. |
| MCclear | Clears all the selections. |To enter Multicursor mode, use one of the above commands.
## Multi cursor mode
> [!IMPORTANT]
> Keys that aren't mapped **do not affect other selections** .Click to see mappings.
| Key | Description |
|---|---|
| `` | Clear the selections and go back to normal mode |
| `` | Clear the selections and go back to normal mode |
| `i` | Enters insert mode |
| `a` | Enters append mode |
| `e` | Enters extend mode |
| `c` | Deletes the text inside selections and starts insert mode |
| `n` | `[count]` Finds the next match after the main selection |
| `N` | `[count]` Finds the previous match before the main selection |
| `` | Creates selections for all the matches |
| `q` | `[count]` Skips the current selection and finds the next one |
| `Q` | `[count]` Skips the current selection and finds the previous one |
| `]` | `[count]` Swaps the main selection with next selection |
| `[` | `[count]` Swaps the main selection with previous selection |
| `}` | `[count]` Deletes the main selection and goes to next |
| `{` | `[count]` Deletes the main selection and goes to previous |
| `` | Creates a selection for the char under the cursor |
| `j` | `[count]` Creates a selection on the char below the cursor |
| `J` | `[count]` Skips the current selection and Creates a selection on the char below |
| `k` | `[count]` Creates a selection on the char above the cursor |
| `K` | `[count]` Skips the current selection and Creates a selection on the char above |
| `r` | Replaces the text inside selections with content of `unnamed register` |
| `p` | Puts the text inside `unnamed register` before selections |
| `P` | Puts the text inside `unnamed register` after selections |
| `y` | Yanks the text inside selections to `unnamed register` |
| `Y` | Yanks the text from the start of selection till the end of the line to `unnamed register` |
| `yy` | Yanks the line of selection to `unnamed register` |
| `gu` | changes selections case to lowercase |
| `gU` | changes selections case to UPPERCASE |
| `z` | Aligns selections by adding space before selections |
| `Z` | Aligns selections by adding space at the start of the line |
| `d` | Deletes the text inside selections |
| `D` | `count` Deletes the text from the start of selections till the end of the line |
| `dd` | `count` Deletes line of selections |
| `@` | Executes a macro at the start of selections |
| `.` | Repeats last change at the start of selections |
| `,` | Clears All Selections except the main one |
| `:` | Prompts for a normal command and Executes it at the start of selections |
| `u` | Undo changes |
| `` | Redo changes |## Insert, Append and Change mode:
Click to see mappings.
| Key | Description |
|---|---|
| `` | Returns to multicursor normal mode |
| `` | Returns to multicursor normal mode |
| `` | Deletes the char before the selections |
| `` | Deletes the char under the selections |
| `` | Moves the selections one char Left |
| `` | Moves the selections one line Up |
| `` | Moves the selections one char Right |
| `` | Moves the selections one line Down |
| `` | Moves the selections one word Left |
| `` | Moves the selections one word Right |
| `` | Moves the selections to start of line |
| `` | Moves the selections to end of line |
| `` | Insert one line below the selections |
| `` | Insert one line below the selections |
| `` | Pastes the text from system clipboard |
| `` | Insert the contents of a register |
| `` | Deletes one word before the selections |
| `` | Deletes one word before the selections |
| `` | Deletes from the start of selections till the start of line |## Extend mode
Once you enter the Extend mode, you can expand or shrink your selections using Vim motions or Treesitter nodes.
At first, the left side of the selections stays put, and selections get extended from the right side.
But you can change which side of selections stay put by pressing `o`.Click to see mappings.
| Key | Description |
|---|---|
| `` | Returns to multicursor normal mode |
| `c` | Prompts user for a motion and performs it |
| `o` | Toggles the anchor side |
| `O` | Toggles the anchor side |
| `w` | `[count]` word forward |
| `e` | `[count]` forward to end of word |
| `b` | `[count]` word backward |
| `h` | `[count]` char left |
| `j` | `[count]` char down |
| `k` | `[count]` char up |
| `l` | `[count]` char right |
| `t` | Extends the selection to the parent of the selected node |
| `r` | Shrinks the selection to the first child of the selected node |
| `y` | Shrinks the selection to the last child of the selected node |
| `u` | Undo Last selections extend or shrink |
| `$` | `[count]` to end of line |
| `^` | To the first non-blank character of the line |## Recipes
### Custom mappings
Create custom mapping for editing selections.
```lua
require('multicursors').setup {
normal_keys = {
-- to change default lhs of key mapping change the key
[','] = {
-- assigning nil to method exits from multi cursor mode
-- assigning false to method removes the binding
method = N.clear_others,
-- you can pass :map-arguments here
opts = { desc = 'Clear others' },
},
[''] = {
method = function()
require('multicursors.utils').call_on_selections(function(selection)
vim.api.nvim_win_set_cursor(0, { selection.row + 1, selection.col + 1 })
local line_count = selection.end_row - selection.row + 1
vim.cmd('normal ' .. line_count .. 'gcc')
end)
end,
opts = { desc = 'comment selections' },
},
},
}
```### Status Line module
Disable the hint window and show Multicursor mode in your status line.
```lua
require('multicursors').setup {
hint_config = false,
}local function is_active()
local ok, hydra = pcall(require, 'hydra.statusline')
return ok and hydra.is_active()
endlocal function get_name()
local ok, hydra = pcall(require, 'hydra.statusline')
if ok then
return hydra.get_name()
end
return ''
end--- for lualine add this component
lualine_b = {
{ get_name, cond = is_active },
}
```### Vertical hints
A configuration like this can be used to show hints in a vertical window similar to helix.```lua
require('multicursors').setup {
hint_config = {
float_opts = {
border = 'rounded',
},
position = 'bottom-right',
},
generate_hints = {
normal = true,
insert = true,
extend = true,
config = {
column_count = 1,
},
},
}
```# Highlight Groups
The following groups are used by `multicursors.nvim` and can be overriden:| Name | Description |
|---|---|
| MultiCursor | Multicursor selections. |
| MultiCursorMain | Main selection in which multicursor began. |# Acknowledgment
[vim-visual-multi](https://github.com/mg979/vim-visual-multi)
[hydra.nvim](https://github.com/anuvyklack/hydra.nvim)