Custom action is not dot repeatable
I'm running with neovim:
➜ manifest git:(main) ✗ nvim --version
NVIM v0.10.0-dev-679+gb60a2ab4c
Build type: RelWithDebInfo
LuaJIT 2.1.0-beta3
on ubuntu 22
May be something wrong in my config, I try to map the action with the following modifier (that a great feature)
require('substitute').setup{}
vim.keymap.set("n", "o", function ()
require('substitute').operator({modifiers = {'reindent'}})
end, { noremap = true })
The action work with the mapping but it is not dot repeatable.
When I simply make the mapping
vim.keymap.set("n", "o", require('substitute').operator, { noremap = true })
the action is dot repeatable
When I run noevim with -N20 I can copy paste here the log associated with the dot action after performing a replace of a work in first place. myVim.log
Interesting, I'll try do do something soon
@gbprod also having same issue. But looking at it i am not sure how would that even be possible. The indent operator motion basically overrides the inital motion triggered for the substitute. I am scratching my head on a way to fix it, but can not think of a solution to it. The most obvious way is to modify the buffer linewise, capture the motion's lines/range, and then modify lines within that block and indent it but that is a no go, slow and bad idea all around. The idea is to still be able to use something like that vim.cmd("silent keepjumps normal! '[=']") and be able to retain the original motion which was invoked on g@
Indent the register content before substituting should work.
(some code copy from mini.operators)
substitute.nvim git:(main) ✗ git --no-pager diff HEAD 0 [19:56:39]
diff --git a/lua/substitute.lua b/lua/substitute.lua
index e5aa76a..466b3dc 100644
--- a/lua/substitute.lua
+++ b/lua/substitute.lua
@@ -34,6 +34,37 @@ function substitute.operator(options)
vim.api.nvim_feedkeys("g@" .. (options.motion or ""), "ni", false)
end
+local H = {}
+H.get_region_indent = function(mark_from, mark_to)
+ local l_from, l_to = H.get_mark(mark_from)[1], H.get_mark(mark_to)[1]
+ local lines = vim.api.nvim_buf_get_lines(0, l_from - 1, l_to, true)
+ return H.compute_indent(lines)
+end
+H.update_indent = function(lines, new_indent)
+ -- Replace current indent with new indent without affecting blank lines
+ local n_cur_indent = H.compute_indent(lines):len()
+ return vim.tbl_map(function(l)
+ if l:find("^%s*$") ~= nil then
+ return l
+ end
+ return new_indent .. l:sub(n_cur_indent + 1)
+ end, lines)
+end
+H.compute_indent = function(lines)
+ local res_indent, res_indent_width = nil, math.huge
+ local blank_indent, blank_indent_width = nil, math.huge
+ for _, l in ipairs(lines) do
+ local cur_indent = l:match("^%s*")
+ local cur_indent_width = cur_indent:len()
+ local is_blank = cur_indent_width == l:len()
+ if not is_blank and cur_indent_width < res_indent_width then
+ res_indent, res_indent_width = cur_indent, cur_indent_width
+ elseif is_blank and cur_indent_width < blank_indent_width then
+ blank_indent, blank_indent_width = cur_indent, cur_indent_width
+ end
+ end
+ return res_indent or blank_indent or ""
+end
function substitute.operator_callback(vmode)
local marks = utils.get_marks(0, vmode)
substitute.state.vmode = vmode
@@ -45,7 +76,10 @@ function substitute.operator_callback(vmode)
local regcontents = vim.fn.getreg(state.register)
local regtype = vim.fn.getregtype(state.register)
local replacement = vim.split(regcontents:rep(substitute.state.count):gsub("\n$", ""), "\n")
-
+ if state.vmode == "line" then
+ local init_indent = vim.api.nvim_get_current_line():match("^(%s*)")
+ replacement = H.update_indent(replacement, init_indent)
+ end
local subs_marks = utils.substitute_text(0, marks.start, marks.finish, vmode, replacement, regt
ype)
vim.api.nvim_buf_set_mark(0, "[", subs_marks[1].start.row, subs_marks[1].start.col, {})