Skip to content

Feature: Add "duplicate" (yank, comment, paste) function? #70

Closed

Description

@garymh

Would it be possible to add in a motion for "duplicating" text? I often (hopefully I'm not the only one) will yank and paste and a line/paragraph of code and then comment out the original so I can look at it for reference while I rework it. For example:

def cool_function(hello)
	puts hello
end

Typing something like gcd{motion} (ip here for a paragraph) would give us:

# def cool_function(hello)
# 	puts hello
# end

def cool_function(hello)
	puts hello
end

This was suggested as a feature with vim-commentary but I think it's still being discussed/considered: tpope/vim-commentary#42

It would be neat to see here too 😃

Love the plugin, btw!

Activity

  1. numToStr commented on Nov 18, 2021

    @numToStr
    Owner

    To be clear I won't support this inside the plugin. Currently, I am working on #62 which will give you the selected region in the pre_hook as an argument and you can use pre_hook in a way that is similar to your use case.

    I am just dumping my brain here and assuming that the PR is merged. IMO following will be steps

    1. Get the text using the provided range
    2. Add the grabbed text below the original text
    3. The plugin will comment the original text

    What do you say?

  2. garymh commented on Nov 18, 2021

    @garymh
    Author

    @numToStr Sounds great! I appreciate it!

  3. numToStr commented on Nov 20, 2021

    @numToStr
    Owner

    For future somebody, this is what you'll need

    require('Comment').setup({
        pre_hook = function(ctx)
            local lines = require('Comment.utils').get_lines(ctx.range)
            local srow = ctx.range.erow
            vim.api.nvim_buf_set_lines(0, srow, srow, false, lines)
        end,
        post_hook = function(ctx)
            local U = require('Comment.utils')
            local srow = ctx.range.erow
            local erow = srow + 1
            local line = U.get_lines({ srow = srow, erow = erow })
            local _, col = U.grab_indent(line[1])
            vim.api.nvim_win_set_cursor(0, { erow, col })
        end,
    })

    NOTE: The only downside is this duplication will happen every time. But you can determine when to do this by using ctx argument

  4. garymh commented on Dec 20, 2021

    @garymh
    Author

    Hi @numToStr ! Has this changed recently because of the API? It seems to have stopped working...

  5. numToStr commented on Dec 21, 2021

    @numToStr
    Owner

    @garymh Yes, because of the recent (breaking) changes I made to the lua APIs. Following is the updated version:

    local U = require("Comment.utils")
    local A = require("Comment.api")
    
    function _G.___gdc(vmode)
    	local range = U.get_region(vmode)
    	local lines = U.get_lines(range)
    
    	-- Copying the block
    	local srow = range.erow
    	vim.api.nvim_buf_set_lines(0, srow, srow, false, lines)
    
    	-- Doing the comment
    	A.comment_linewise_op(vmode)
    
    	-- Move the cursor
    	local erow = srow + 1
    	local line = U.get_lines({ srow = srow, erow = erow })
    	local _, col = U.grab_indent(line[1])
    	vim.api.nvim_win_set_cursor(0, { erow, col })
    end
  6. garymh commented on Dec 22, 2021

    @garymh
    Author

    Awesome!! Thank you so much!!

  7. paopaol commented on Apr 24, 2022

    @paopaol

    how do i use the function ___gdc, :lua _G.__gdc('n') ?

  8. numToStr commented on Apr 25, 2022

    @numToStr
    Owner
  9. garymh commented on Aug 1, 2022

    @garymh
    Author

    Hello! It looks like the new refactor broke this function...

    E5108: Error executing lua ...ite/pack/packer/start/Comment.nvim/lua/Comment/utils.lua:63: attempt to get length of local 'iter' (a nil
     value)                                                                                                                                
    stack traceback:                                                                                                                       
            ...ite/pack/packer/start/Comment.nvim/lua/Comment/utils.lua:63: in function 'is_empty'                                         
            ...ite/pack/packer/start/Comment.nvim/lua/Comment/utils.lua:305: in function 'uncomment'                                       
            ...te/pack/packer/start/Comment.nvim/lua/Comment/opfunc.lua:135: in function 'linewise'                                        
            ...te/pack/packer/start/Comment.nvim/lua/Comment/opfunc.lua:76: in function 'opfunc'                                           
            .../site/pack/packer/start/Comment.nvim/lua/Comment/api.lua:152: in function 'comment_linewise_op'                             
            /Users/gary/.config/nvim/lua/config/comment.lua:22: in function </Users/gary/.config/nvim/lua/config/comment.lua:12>    
    

    Should I just stick to 0.6.1? I'm afraid my Lua isn't good enough to fix it 😞

  10. numToStr commented on Aug 2, 2022

    @numToStr
    Owner

    @garymh This should do it

    local U = require('Comment.utils')
    local A = require('Comment.api')
    
    function _G.___gdc(motion)
        local range = U.get_region(motion)
        local lines = U.get_lines(range)
    
        -- Copying the block
        local srow = range.erow
        vim.api.nvim_buf_set_lines(0, srow, srow, false, lines)
    
        -- Doing the comment
        A.comment_linewise_op(motion)
    
        -- After #183 you might wanna use
        -- A.comment.linewise(motion)
    
        -- Move the cursor
        local erow = srow + 1
        local line = U.get_lines({ srow = srow, erow = erow })
        local col = U.indent_len(line[1])
        vim.api.nvim_win_set_cursor(0, { erow, col })
    end

    (Also make sure to update the plugin, as I discovered a bug while testing this function)

  11. garymh commented on Aug 2, 2022

    @garymh
    Author

    Perfect! Thank you so much, again! 😄

  12. AniAggarwal commented on Oct 8, 2022

    @AniAggarwal

    Doesn't seem to work on Neovim v8.
    When calling from visual mode:

    E5108: Error executing lua /home/ani/.config/nvim/lua/user/comment.lua:20: attempt to call field 'indent_len' (a nil value)                                                 
    stack traceback:                                                                                                                                                            
            /home/ani/.config/nvim/lua/user/comment.lua:20: in function '___gdc'                                                                                                
            [string ":lua"]:1: in main chunk   

    From normal mode:

    E5108: Error executing lua /home/ani/.config/nvim/lua/user/comment.lua:20: attempt to call field 'indent_len' (a nil value)                                                 
    stack traceback:                                                                                                                                                            
            /home/ani/.config/nvim/lua/user/comment.lua:20: in function </home/ani/.config/nvim/lua/user/comment.lua:6>  

    My mappings/config:

    require("Comment").setup({})
    
    local U = require("Comment.utils")
    local A = require("Comment.api")
    
    function _G.___gdc(motion)
    	local range = U.get_region(motion)
    	local lines = U.get_lines(range)
    
    	-- Copying the block
    	local srow = range.erow
    	vim.api.nvim_buf_set_lines(0, srow, srow, false, lines)
    
    	-- Doing the comment
    	A.comment.linewise(motion)
    
    	-- Move the cursor
    	local erow = srow + 1
    	local line = U.get_lines({ srow = srow, erow = erow })
    	local col = U.indent_len(line[1])
    	vim.api.nvim_win_set_cursor(0, { erow, col })
    end
    
    vim.api.nvim_set_keymap("x", "gy", "<ESC><CMD>lua ___gdc(vim.fn.visualmode())<CR>", { silent = true, noremap = true })
    vim.api.nvim_set_keymap("n", "gy", "<CMD>set operatorfunc=v:lua.___gdc<CR>g@", { silent = true, noremap = true })
  13. hexh250786313 commented on Oct 21, 2022

    @hexh250786313

    My case:

    function! s:YankAndComment(type)
      if a:type ==# 'v'
        normal! `<v`>y
      elseif a:type ==# 'V'
        normal! `<V`>y
      elseif a:type ==# 'char'
        normal! `[v`]y
      else
        return
      endif
      lua require('Comment.api').comment.linewise(vim.fn.visualmode())
    endfunction
    
    vmap <silent> <space>cy :<c-u>call <SID>YankAndComment(visualmode())<cr>

    @AniAggarwal

  14. AniAggarwal commented on Oct 29, 2022

    @AniAggarwal

    I am not able to make that work. Unfortunately I am using a lua config. I translated it but don't seem to be able to get it working.

    local YankAndComment = function(type)
    	if type == "v" then
    		vim.cmd("normal! `<v`>y")
    	elseif type == "V" then
    		vim.cmd("normal! `<V`>y")
    	elseif type == "char" then
    		vim.cmd("normal! `[v`]y")
    	else
    		return
    	end
    	require("Comment.api").comment.linewise(vim.fn.visualmode())
    end
    keymap("v", "gcp", "<cmd>YankAndComment(vim.fn.visualmode)<cr>", opts)

    @hexh250786313

  15. joncol commented on Apr 4, 2023

    @joncol

    The solution I went with:

    -- Comment and copy.
    vim.keymap.set("n", "<leader>cc", "yy<Plug>(comment_toggle_linewise_current)p")
    vim.keymap.set(
      "x",
      "<leader>cc",
      "ygv<Plug>(comment_toggle_linewise_visual)`>p"
    )

    I didn't thoroughly test it yet, but this seems to work with the cursor being at either end of a selection.

  16. AniAggarwal commented on Apr 4, 2023

    @AniAggarwal

    Works perfectly for me, thanks!

  17. joncol commented on Apr 4, 2023

    @joncol

    Works perfectly for me, thanks!

    Simplified the binding a little bit.

  18. tkkcc commented on Mar 5, 2024

    @tkkcc

    sharing my config that not disturb clipboard and cursor position.

    vim.keymap.set('n', ',d', 'mz"zyy"zp`zj', { remap = false, silent=true })
    vim.keymap.set('v', ',d', 'mz"zy"zP`z', { remap = false, silent=true })
    vim.keymap.set('n', ',D', 'mz"zyy"zP`zk<Plug>(comment_toggle_linewise_current)`z', { remap = false, silent=true })
    vim.keymap.set('v', ',D', 'mz"zy"zP`[v`]<Plug>(comment_toggle_linewise_visual)`z', { remap = false, silent=true})

    Also, which-key can slow down recursive keymap noticeably.

  19. powerman commented on Jul 8, 2024

    @powerman

    sharing my config that not disturb clipboard and cursor position.

    Nice! But it does not support [count] and INSERT mode, so here is my version. It's not that good in keeping clipboard and cursor position (maybe someone helps inproving it with this). It's in Lazy keys = format:

                {
                    '<C-C>',
                    function() -- Support for a count makes implementation a bit complicated.
                        local count = vim.v.count1
                        local api = require 'Comment.api'
                        vim.api.nvim_feedkeys('V', 'n', false)
                        if count > 1 then
                            vim.api.nvim_feedkeys((count - 1) .. 'j', 'n', false)
                        end
                        vim.api.nvim_feedkeys('yP', 'nx', false)
                        api.comment.linewise.count(count)
                        vim.api.nvim_feedkeys('`<^i', 'n', false)
                    end,
                    mode = 'n',
                    desc = 'Backup (count) line(s) as a comment, then edit',
                },
                {
                    '<C-C>',
                    'V<Esc>gvy`>pgv<Esc>`>:lua require"Comment.api".comment.linewise("V")<CR><Down>^i',
                    mode = 'v',
                    silent = true,
                    desc = 'Backup selected lines as a comment, then edit',
                },
                {
                    '<C-C>',
                    '<C-O>yy<C-O>P<C-O>:lua require"Comment.api".comment.linewise.current()<CR><Down>',
                    mode = 'i',
                    silent = true,
                    desc = 'Backup current line as a comment',
                },
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions