[mini.ai] The perfect mini-word textobject #1434
Replies: 5 comments 5 replies
-
I'd be interested to hear if anyone thinks the regex can be simplified. It took me quite a while to understand what it was doing (especially the %f pattern) but I could very likely be missing some opportunity for further improvement. |
Beta Was this translation helpful? Give feedback.
-
Nice job of "translating" Lua patterns into regular English :) As with any regex-like systems, first time encountering them can be daunting. It gets easier with time. The example was mostly added as a demo of capabilities for what looks like a popular textobject. I personally don't like using it as it feels "too magical". Regular Vim/Neovim operators textobjects together with |
Beta Was this translation helpful? Give feedback.
-
Thank you for this. I've been playing around with this and it does work great. One thing I cannot get to work: select multiple subwords. For example, given this:
How would I make a selection:
Here's what works for a single inner word for me:
All of these don't work
|
Beta Was this translation helpful? Give feedback.
-
Pattern onlyAdded support for around Note I won't even pretend that you'll be able to understand this, but I hope there's a way to turn it into something more comprehensible. Warning The query is intentionally implemented this way to prefer left-handed underscores over right-handed ones. It can be useful when using subword motion plugins like chrisgrieser/nvim-spider. Use local ai = require 'mini.ai'
ai.setup {
custom_textobjects = {
e = {
{
-- __-1, __-U, __-l, __-1_, __-U_, __-l_
'[^_%-]()[_%-]+()%w()()[%s%p]',
'^()[_%-]+()%w()()[%s%p]',
-- __-123SNAKE
'[^_%-]()[_%-]+()%d+%u[%u%d]+()()',
'^()[_%-]+()%d+%u[%u%d]+()()',
-- __-123snake
'[^_%-]()[_%-]+()%d+%l[%l%d]+()()',
'^()[_%-]+()%d+%l[%l%d]+()()',
-- __-SNAKE, __-SNAKE123
'[^_%-]()[_%-]+()%u[%u%d]+()()',
'^()[_%-]+()%u[%u%d]+()()',
-- __-snake, __-Snake, __-snake123, __-Snake123
'[^_%-]()[_%-]+()%a[%l%d]+()()',
'^()[_%-]+()%a[%l%d]+()()',
-- UPPER, UPPER123, UPPER-__, UPPER123-__
-- No support: 123UPPER
'[^_%-%u]()()%u[%u%d]+()[_%-]*()',
'^()()%u[%u%d]+()[_%-]*()',
-- UPlower, UPlower123, UPlower-__, UPlower123-__
'%u%u()()[%l%d]+()[_%-]*()',
-- lower, lower123, lower-__, lower123-__
'[^_%-%w]()()[%l%d]+()[_%-]*()',
'^()()[%l%d]+()[_%-]*()',
-- Camel, Camel123, Camel-__, Camel123-__
'[^_%-%u]()()%u[%l%d]+()[_%-]*()',
'^()()%u[%l%d]+()[_%-]*()',
},
},
},
} |
Beta Was this translation helpful? Give feedback.
-
HybridNote Added support for around Note End subwords with numbers. local MiniAi = require 'mini.ai'
MiniAi.setup {
custom_textobjects = {
-- NOTE: Use any subword pattern you like, just ignore separators
e = {
{
"%f[%a]%l+%d*",
"%f[%w]%d+",
"%f[%u]%u%f[%A]%d*",
"%f[%u]%u%l+%d*",
"%f[%u]%u%u+%d*",
},
},
},
}
local expand_separator = function(range, edge)
local from, to = range.from, range.to
local line = function(r)
return assert(vim.api.nvim_buf_get_lines(0, r.line - 1, r.line, true)[1])
end
local left = line(from):sub(1, from.col - 1):find("[_%-]+$")
local _, right = line(to):find("^[_%-]+", to.col + 1)
-- stylua: ignore start
if left then from.col = left elseif right then to.col = right end
return from, to
end
vim.keymap.set("o", "ae", function()
local range = MiniAi.find_textobject("i", "e")
if range then
local from, to = expand_separator(range)
vim.api.nvim_win_set_cursor(0, { from.line, from.col - 1 })
vim.cmd("normal! v")
vim.api.nvim_win_set_cursor(0, { to.line, to.col - 1 })
end
end) There’s only one small problem with defining patterns as in the provided example: the first matching pattern always wins, not necessarily the most relevant one. For example, my pattern groups collide on the string
Example pattern: e = {
{
-- lower123
'[^%u%l]()%l%l+%d*()[^%l%d]',
-- UPPER123
'[^%u]()%u%u+%d*()%u%l',
'[^%u]()%u%u+%d*()[^%d]',
-- Camel123NAME4
'()%u%l+%d*()[^%d]',
-- U, l, 1
'[^%u]()%u()[^%u%l]',
'[^%l]()%l()[^%l]',
'[^%d]()%d()[^%d]',
-- 123|UPPER, 123|lower, 123|Camel
'[%s%p]()%d+()[^%d]',
},
}, |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
In the mini.ai help file, there's this custom textobject example:
I absolutely love this textobject and use it to rename variables/functions all the time. However, it has problems:
So, here's my updated version that fixes these issues with sufficient comments. It supports, as far as I can tell, all text cases and capitalizations:
Trust me, you will not regret this. This is one of the biggest quality-of-life improvements I've had with vim editing yet. Take a look:
perfect-textobj.mp4
Beta Was this translation helpful? Give feedback.
All reactions