In addition to repeating t
/T
/f
/F
motions, this plugin lets you repeat diagnostic jumps (e.g. ]d
/[d
) and nvim-treesitter-textobjects jumps (e.g. ]f
/[f
) with the ;
/,
keys.
This plugin also integrates with gitsigns.nvim.
https://github.com/user-attachments/assets/e847cf39-40bd-49cb-9989-34e921b3393a
With lazy.nvim:
{
'mawkler/demicolon.nvim',
-- keys = { ';', ',', 't', 'f', 'T', 'F', ']', '[', ']d', '[d' }, -- Uncomment this to lazy load
dependencies = {
'nvim-treesitter/nvim-treesitter',
'nvim-treesitter/nvim-treesitter-textobjects',
},
opts = {}
}
After pressing any of the keymaps below, demicolon.nvim lets you repeat them with ;
and ,
.
t
/T
/f
/F
)See :help t
, :help T
, :help f
, and :help F
respectively.
By default, demicolon.nvim will create the diagnostic motion keymaps below. See Configuration for info on how to disable default keymaps.
Motion | Description |
---|---|
]d /[d |
Next/previous diagnostic (any severity) |
]e /[e |
Next/previous error |
]w /[w |
Next/previous warning |
]i /[i |
Next/previous information |
]h /[h |
Next/previous hint |
demicolon.nvim lets you repeat any nvim-treesitter-textobjects motion. For example: ]f
to "jump to next function", ]c
to "jump to next class", etc.
[!NOTE] To use treesitter text-objects you need to configure
textobjects.move
in nvim-treesitter-textobjects.
Motion | Jumps to next/pevious... | Help page with more information |
---|---|---|
]q /[q |
item in quickfix list | :help ]q /:help [q |
]l /[l |
item in location list | :help ]l /:help [l |
]<C-q> /[<C-q> |
file in quickfix list | :help ]CTRL-Q /:help [CTRL-Q |
]<C-l> /[<C-l> |
file in location list | :help ]CTRL-L /:help [CTRL-L |
]z /[z |
fold | :help zj /:help zk |
]s /[z |
spelling mistake | :help ]s /:help [s |
Default options:
opts = {
diagnostic = {
-- See `:help vim.diagnostic.Opts.Float`
float = {}
},
-- Create default keymaps
keymaps = {
-- Create t/T/f/F key mappings
horizontal_motions = true,
-- Create ]d/[d, etc. key mappings to jump to diganostics. See demicolon.keymaps.create_default_diagnostic_keymaps
diagnostic_motions = true,
-- Create ; and , key mappings
repeat_motions = true,
-- Create ]q/[q/]<C-q>/[<C-q> and ]l/[l/]<C-l>/[<C-l> quickfix and location list mappings
list_motions = true,
-- Create `]s`/`[s` key mappings for jumping to spelling mistakes
spell_motions = true,
-- Create `]z`/`[z` key mappings for jumping to folds
fold_motions = true,
},
integrations = {
-- Integration with https://github.com/lewis6991/gitsigns.nvim
gitsigns = {
enabled = true,
keymaps = {
next = ']c',
prev = '[c',
},
},
},
}
You can create your own custom repeatable jumps using repeatably_do()
in demicolon.jump
. repeatably_do()
takes a funcion as its first argument and options to be passed to that function as its second argument. Make sure that the options include a boolean forward
field to determine whether the action should be forward or backward. Take a look at how I've implemented the gitsigns.nvim integration for inspiration.
eyeliner.nvim can highlight unique letters in words when you press t
/T
/f
/F
. Below is my recommended configuration for using eyeliner.nvim together with demicolon.nvim.
NOTE: make sure to set keymaps.horizontal_motions = false
in your demicolon setup if you want to use this config.
return {
'jinh0/eyeliner.nvim',
-- keys = { 't', 'f', 'T', 'F' }, -- Uncomment this to lazy load eyeliner.nvim
config = function()
require('eyeliner').setup({
highlight_on_key = true,
default_keymaps = false,
dim = true, -- Optional
})
local function eyeliner_jump(key)
local forward = vim.list_contains({ 't', 'f' }, key)
return function()
require('eyeliner').highlight({ forward = forward })
return require('demicolon.jump').horizontal_jump(key)()
end
end
local nxo = { 'n', 'x', 'o' }
local opts = { expr = true }
vim.keymap.set(nxo, 'f', eyeliner_jump('f'), opts)
vim.keymap.set(nxo, 'F', eyeliner_jump('F'), opts)
vim.keymap.set(nxo, 't', eyeliner_jump('t'), opts)
vim.keymap.set(nxo, 'T', eyeliner_jump('T'), opts)
end
}
Here is a full configuration, including nvim-treesitter-textobjects and eyeliner.nvim:
require('lazy').setup({
{
'nvim-treesitter/nvim-treesitter-textobjects',
dependencies = 'nvim-treesitter/nvim-treesitter',
build = ':TSUpdate',
config = function()
require('nvim-treesitter.configs').setup({
ensure_installed = 'all',
textobjects = {
move = {
enable = true,
goto_next_start = {
["]f"] = "@function.outer",
["]a"] = "@argument.outer",
["]m"] = "@method.outer",
-- ...
},
goto_previous_start = {
["[f"] = "@function.outer",
["[a"] = "@argument.outer",
["[m"] = "@method.outer",
-- ...
},
},
},
})
end,
},
{
'jinh0/eyeliner.nvim',
keys = { 't', 'f', 'T', 'F' },
opts = {
highlight_on_key = true,
dim = true,
default_keymaps = false,
}
},
{
'mawkler/demicolon.nvim',
dependencies = {
'jinh0/eyeliner.nvim',
'nvim-treesitter/nvim-treesitter',
'nvim-treesitter/nvim-treesitter-textobjects'
},
keys = { ';', ',', 't', 'f', 'T', 'F', ']', '[', ']d', '[d' },
config = function()
require('demicolon').setup({
keymaps = {
horizontal_motions = false,
},
})
local function eyeliner_jump(key)
local forward = vim.list_contains({ 't', 'f' }, key)
return function()
require('eyeliner').highlight({ forward = forward })
return require('demicolon.jump').horizontal_jump(key)()
end
end
local nxo = { 'n', 'x', 'o' }
local opts = { expr = true }
vim.keymap.set(nxo, 'f', eyeliner_jump('f'), opts)
vim.keymap.set(nxo, 'F', eyeliner_jump('F'), opts)
vim.keymap.set(nxo, 't', eyeliner_jump('t'), opts)
vim.keymap.set(nxo, 'T', eyeliner_jump('T'), opts)
end
}
})
Here's the full list of available treesitter textobjects.
;
/,
to remember the direction of the original jump"Neovim's default behaviour is for ;
/,
to remember the direction of the jump that they repeat. That means that if you for instance repeat a T
motion (as opposed to t
) with ;
it will move you to the left. A lot of people prefer if ;
always moves you to the right and ,
always to the left, which is how demicolon works by default.
If you prefer Neovim's default behaviour you can disable demicolon's default ;
/,
keymaps and remap them manually like this:
require('demicolon').setup({
keymaps = {
repeat_motions = false,
},
})
local ts_repeatable_move = require('nvim-treesitter.textobjects.repeatable_move')
local nxo = { 'n', 'x', 'o' }
vim.keymap.set(nxo, ';', ts_repeatable_move.repeat_last_move)
vim.keymap.set(nxo, ',', ts_repeatable_move.repeat_last_move_opposite)
The treesitter portion of this plugin is just a wrapper over nvim-treesitter-textobjects. Credit to them for making an awesome plugin!