-
Notifications
You must be signed in to change notification settings - Fork 0
Integration: Mini surround
Eric Eldredge edited this page Jan 5, 2026
·
2 revisions
Integrate occurrence.nvim with mini.surround to surround multiple occurrences at once.
This integration allows you to:
- Mark multiple occurrences
- Press
gsto trigger surround operator - Choose surround characters (quotes, brackets, tags, etc.)
- All marked occurrences get surrounded
Add this to your occurrence.nvim setup:
require("occurrence").setup({
operators = {
["gs"] = {
desc = "Surround marked occurrences",
before = function(marks, ctx)
local ok, mini_surround = pcall(require, "mini.surround")
if not ok then
vim.notify("mini.surround not found", vim.log.levels.WARN)
return false
end
-- HACK: Access mini.surround's internals via debug
local H = nil
local info = debug.getinfo(mini_surround.add, "u")
for i = 1, info.nups do
local name, value = debug.getupvalue(mini_surround.add, i)
if name == "H" and type(value) == "table" then
H = value
break
end
end
if not H or not H.get_surround_spec then
vim.notify("Could not access mini.surround internals", vim.log.levels.WARN)
return false
end
---@diagnostic disable-next-line: redefined-local
local ok, surr_info = pcall(H.get_surround_spec, "output")
if not ok or not surr_info or not surr_info.left or not surr_info.right then
vim.notify("Invalid surround specification", vim.log.levels.WARN)
return false
end
-- Store in context for operator to use
ctx.surr_info = surr_info
ctx.respect_selection_type = mini_surround.config.respect_selection_type
end,
operator = function(current, ctx)
if not ctx.surr_info then
return false
end
ctx.register = nil -- Don't yank replaced text to register
if ctx.respect_selection_type then
return vim.tbl_map(function(line)
return ctx.surr_info.left .. line .. ctx.surr_info.right
end, current.text)
else
return ctx.surr_info.left .. table.concat(current.text, "\n") .. ctx.surr_info.right
end
end,
},
},
})-
Mark occurrences: Press
goon a word -
Trigger surround: Press
gs -
Choose surround: Type the surround character (e.g.,
",(,tfor tag) - Done: All marked occurrences are surrounded
Example - Add Quotes:
Before: foo bar foo
^
1. Press 'go' on 'foo' -> marks both 'foo'
2. Press 'gs' -> prompts for surround
3. Type '"' -> "foo" bar "foo"
Example - Add Parentheses:
Before: word1 word2 word3
^
1. Press 'go' on 'word' pattern
2. Press 'gs'
3. Type '(' -> (word1) (word2) (word3)
Example - Add HTML Tag:
Before: content more content
^
1. Mark 'content' occurrences
2. Press 'gs'
3. Type 't' -> prompts for tag
4. Type 'div' -> <div>content</div> more <div>content</div>
- Checks if mini.surround is available
- Uses debug library to access mini.surround's internal
H.get_surround_specfunction - Prompts user for surround characters (this is handled by mini.surround)
- Stores the surround specification in context
Why the hack? mini.surround doesn't expose a public API for getting surround specs, so we use the debug library to access its internals. This may break in future versions.
- Gets surround spec from context
- Wraps each line with
leftandrightsurround characters - Respects
respect_selection_typeconfig if set - Sets
ctx.register = nilto avoid yanking original text - Returns the modified text to occurrence.nvim for replacement
If respect_selection_type is true:
- Each line is surrounded individually
-
"foo\nbar"with"→"foo"\n"bar"
If false:
- All lines treated as one block
-
"foo\nbar"with"→"foo\nbar"