This is an automated archive made by the Lemmit Bot.
The original was posted on /r/neovim by /u/AbdSheikho on 2026-04-23 03:21:41+00:00.
I know it's an odd timing for an nvim-treesitter related plugin, but I'm a big fan of their work and appreciate it.
But the other day I was attempting to change a monster of boilerplate keymaps that I've set with
nvim-treesitter-textobjects, which if anyone tried would definitely know that are tedious to set/modify.
And I thought to myself "I'm a proper engineer, I should at least apply some design patterns to to make my boilerplate more coherent".
A few days later I ended up with a Lua module that can be made into a separate plugin, which I did and I thought of sharing it with you.
I know I lack the imagination to do some weird stuff to my config, or create a revolutionary/goundbreaking plugin,
but I do like to create stuff that make my life easier. Thus, Having a plugin that makes reading and editing easier would be a huge plus (at least for me).
So
My plugin (nvim-keysitter) is for those who write their own config,
and currently uses nvim-treesitter-textobjects for their jump/around/inner keymaps.
It provides you with an instance that you can call to set your keymaps.
My config went from this: (this example only shows functions and classes)
-- keymaps
vim.keymap.set({ 'x', 'o' }, 'am', function()
require('nvim-treesitter-textobjects.select').select\_textobject('@function.outer', 'textobjects')
end)
vim.keymap.set({ 'x', 'o' }, 'im', function()
require('nvim-treesitter-textobjects.select').select\_textobject('@function.inner', 'textobjects')
end)
vim.keymap.set({ 'x', 'o' }, 'ac', function()
require('nvim-treesitter-textobjects.select').select\_textobject('@class.outer', 'textobjects')
end)
vim.keymap.set({ 'x', 'o' }, 'ic', function()
require('nvim-treesitter-textobjects.select').select\_textobject('@class.inner', 'textobjects')
end)
vim.keymap.set({ 'n', 'x', 'o' }, ']m', function()
require('nvim-treesitter-textobjects.move').goto\_next\_start('@function.outer', 'textobjects')
end)
vim.keymap.set({ 'n', 'x', 'o' }, ']]', function()
require('nvim-treesitter-textobjects.move').goto\_next\_start('@class.outer', 'textobjects')
end)
vim.keymap.set({ 'n', 'x', 'o' }, ']M', function()
require('nvim-treesitter-textobjects.move').goto\_next\_end('@function.outer', 'textobjects')
end)
vim.keymap.set({ 'n', 'x', 'o' }, '][', function()
require('nvim-treesitter-textobjects.move').goto\_next\_end('@class.outer', 'textobjects')
end)
vim.keymap.set({ 'n', 'x', 'o' }, '[m', function()
require('nvim-treesitter-textobjects.move').goto\_previous\_start('@function.outer', 'textobjects')
end)
vim.keymap.set({ 'n', 'x', 'o' }, '[[', function()
require('nvim-treesitter-textobjects.move').goto\_previous\_start('@class.outer', 'textobjects')
end)
vim.keymap.set({ 'n', 'x', 'o' }, '[M', function()
require('nvim-treesitter-textobjects.move').goto\_previous\_end('@function.outer', 'textobjects')
end)
vim.keymap.set({ 'n', 'x', 'o' }, '[]', function()
require('nvim-treesitter-textobjects.move').goto\_previous\_end('@class.outer', 'textobjects')
end)
To this:
local keysitter = require 'keysitter'
local tsto = keysitter.new('treesitter-textobjects', { group\_prefix = 'o' })
-- a setup function
tsto.setup({ 'FileType', 'BufEnter' }, 'keysitter', function()
-- tsto:set('f', 'function'):around():inner():next():prev()
for k, v in pairs {
-- ['b'] = 'block', -- or b for brace-less languages like python
['f'] = 'function',
['i'] = 'conditional',
['l'] = 'loop',
['r'] = 'return',
['t'] = 'attribute',
['x'] = 'regex',
} do
tsto:set(k, v):around():inner():next():prev()
end
tsto:set('/', 'comment'):around():inner():goto\_start()
tsto:set('{', 'block'):around():inner():goto\_start():goto\_end { key = '}' }
tsto:set('(', 'call'):around():inner():goto\_start():goto\_end { key = ')' }
tsto:set(',', 'parameter'):around():inner():goto\_start():goto\_end { key = '.' }
tsto:set(';', 'statement'):around():goto\_start():goto\_end { key = ':' }
tsto
:set('=', 'assignment')
:around()
:inner({ attribute = 'rhs' })
:goto\_start({ attribute = 'lhs' })
:next\_start({ attribute = 'rhs', key = '-' }, { desc = 'next assignment rhs' })
:previous\_start({ attribute = 'rhs', key = '-' }, { desc = 'previous assignment rhs' })
tsto
:set('c', 'class')
:around()
:inner()
:next\_start({ motion = ']', group\_prefix = '', key = ']' })
:next\_end({ motion = ']', group\_prefix = '', key = '[' })
:previous\_start({ motion = '[', group\_prefix = '', key = '[' })
:previous\_end { motion = '[', group\_prefix = '', key = ']' }
end, { desc = 'Set keysitter keymaps for nvim-treesitter-textobjects' })
It provides sensible defaults with the ability to override them per keymap, while also does some inner checks, so if some keymap can't/shouldn't be available for a specific filetype
(trying to set function for markdown file), then it won't be set for that file.
Currently I'm the only intended user for this plugin, but I'll be happy to hear your thoughts.