nvim-treesitter-textobjects icon indicating copy to clipboard operation
nvim-treesitter-textobjects copied to clipboard

Feature Request: Duplicating Nodes

Open adueck opened this issue 7 months ago • 4 comments

Is your feature request related to a problem? Please describe.

This library answers a huge felt need wanting to work with elements of the syntax by selecting them, deleting, swapping them around, etc.

But one itch that I find is still unscratched is the ability to duplicate nodes.

I often find I am working with an array of objects in TypeScript (which would be treated as @parameter) and I want to quickly make a duplicate of a node and then modify it. For example, I might have an array like this:

const people = [
    {
        name: "Bill Smith",
        age: 25,
    },
    {
        name: "Frank Jones",
        age: 30,
    },
];

And I want to duplicate Frank Jones' record. To do that I can easily select and/or yank the record, and then paste it after. The problem with this is that I have to do a little dancing around the trailing comma and it takes a few steps. The same thing goes for inline arrays of function parameters etc.

https://github.com/user-attachments/assets/5fbc0872-672e-4adf-90fc-9039e74cc055

Of course there's other options to do this like using V to do line-wise visual mode etc, but it always requires a bit of thinking and a few keystrokes to see how to duplicate nodes in different situations.

Describe the solution you'd like

What I would love to do would be have an action like move or swap that would allow me to use a keybinding to quickly duplicate something like a @parameter or a @statement. The same could be done for any nodes that are in an array on the tree.

lua <<EOF
require'nvim-treesitter.configs'.setup {
  textobjects = {
    copy = {
      enable = true,
      copy_next = {
        ["<leader>c"] = "@parameter.inner",
      },
    },
  },
}
EOF

In a way this would be similar to how many editors allow you to quickly duplicate files and then make adjustments. It would be so nice to be able to just quickly duplicate a @function, a @statement, or a @parameter in our syntax tree and then tweak it, rather than worry about yanking and pasting.

adueck avatar Jun 16 '25 08:06 adueck

I personally use https://github.com/kiyoon/treesitter-indent-object.nvim

or, just select @parameter.outer, yank, then paste

kiyoon avatar Jun 16 '25 08:06 kiyoon

Oh nice I like https://github.com/kiyoon/treesitter-indent-object.nvim, thanks. Before that I was using incremental_selection with treesitter but your treesitter-indent-object.nvim does a better job at immediately grabbing the wider chunks that I want.

I still think it would be useful because yanking with your plugin or grabbing @parameter.outer you still need to move to go to the place you want to paste it, or worry about making the selection linewise for easy pasting onto a new line. Would be nice to just BAM duplicate a node without thinking about the yank, move, paste. But totally understand if this is too niche of a request. 😅

Thanks again for your great work. This whole plugin is honestly what I dreamed of having years ago and it's a joy to have it in my life now.

adueck avatar Jun 16 '25 12:06 adueck

Let's say your mapping to @parameter.inner is ia. Then viapi, will kind of work.

So even a simple mapping like :nmap <leader>cc viaypi,<esc> will do the job, and you can of course customise the movements as you want, like if you wanted the cursor to be at the end of the duplication, it would be :nmap <leader>cc viaya,<esc>p`]

If you want something more complicated, you can also try creating a simple lua function like

function()
  vim.cmd([[TSTextobjectSelect @parameter.inner]])
  -- do sth with the selection
  -- e.g. get text, analyse, put text or modify
end

kiyoon avatar Jun 16 '25 13:06 kiyoon

Thanks again for your great work. This whole plugin is honestly what I dreamed of having years ago and it's a joy to have it in my life now.

Thank you, you are very nice :)

kiyoon avatar Jun 16 '25 14:06 kiyoon