duplicate.nvim
duplicate.nvim copied to clipboard
Discussion: smart duplications (transform function) + presets?
I basically have a mini-plugin in my config which tries to improve current-line-duplication by adding some minor tweaks like:
- in css, when a line with "margin-right" is duplicated, it becomes "margin-left" etc.
- if the line contains a
=or:, move the cursor to the left-hand-side, since that's the part you are most likely to change (since duplicate keys are invalid, and you usually do not want to assign something to the very same variable) - if the left-hand-side contains a numbered key or variable, increment that number
- ...
I think those ideas could make sense as an (optional) extra feature for this plugin. You can take a look at what I have here: https://github.com/chrisgrieser/.config/blob/main/nvim/lua/funcs/duplication.lua
That's a really great feature request! On v2.0.0 (btw this plugin now uses semver and there were breaking changes to the configuration, see readme), I added basic support for this. You can now do something like this:
require("duplicate").setup {
transform = function(lines)
local ft = vim.bo.filetype
for i, line in ipairs(lines) do
-- smart switching of conditionals
if ft == "lua" and line:find("^%s*if.+then$") then
lines[i] = line:gsub("^(%s*)if", "%1elseif")
elseif (ft == "bash" or ft == "zsh" or ft == "sh") and line:find("^%s*if.+then$") then
lines[i] = line:gsub("^(%s*)if", "%1elif")
elseif (ft == "javascript" or ft == "typescript") and line:find("^%s*if.+{$") then
lines[i] = line:gsub("^(%s*)if", "%1} else if")
end
-- increment numbered vars
local lineHasNumberedVarAssignment, _, num = line:find("(%d+).*=")
if lineHasNumberedVarAssignment then
local nextNum = tostring(tonumber(num) + 1)
lines[i] = line:gsub("%d+(.*=)", nextNum .. "%1")
end
end
return lines
end,
}
Let me know if you think I should add presets for this as you mentioned (e.g. you could then do smth. like this instead of returning the lines:
transform = function(lines)
return {
presets = {
lua = { "if/elseif" } -- enable presets specified by name
css = "all", -- use all available presets
}
-- or just `presets = "all"`
}
end
fantastic, thanks! 🚀
(btw this plugin now uses semver and there were breaking changes to the configuration, see readme),
all good, lazy.nvim dutifully informed me that there is a breaking change :)
a few points of feedback on the implementation
- I think it makes sense to restrict the transformation to the current line. the
if→elseiftransformation for example makes sense if duplicating a single line, but when duplicating a whole block or paragraph, you usually want to keep theif, for example. (To make transformations work with more than one line, one would probably need some smarter conditionals, although I am not sure what a good implementation for that would be.) - presets definitely would make sense! I'd separate the presets from the custom transform function though, in case someone would like to use both.
I think it makes sense to restrict the transformation to the current line.
I think I'll leave this as it is since the feature is more general this way (in the transform function you could add a check for the size of lines).
presets definitely would make sense!
After having thought about adding presets a bit more I'd say that it's not obvious to me what some common use cases / examples for transformation functions would be (since they depend a lot on the filetype / context). If it turns out that several users extensively use the same transformation functions I can still add this. But right now I don't think it'd be worth the effort given the low amount of users rn (also because I haven't announced this plugin on Reddit yet ;))
Will leave this issue open for further discussion.