3

I'm creating a Vim script and a critical part of it is duplicating the selected lines. To duplicate lines, I have this mapping which works as intended:

vnoremap <Leader>d :copy '><CR>

But, when inside a function/script, the behavior of copy seems different:

function Foo()
    copy '>
endfunction

Sample Selected Lines

x = 'alpha'
y = 'bravo'
z = 'charlie'

Expected Result

x = 'alpha'
y = 'bravo'
z = 'charlie'
x = 'alpha'
y = 'bravo'
z = 'charlie'

Actual Result (lines seem to be copied in reverse order)

x = 'alpha'
y = 'bravo'
z = 'charlie'
z = 'charlie'
y = 'bravo'
x = 'alpha'

Likewise, running the copy command manually against the selected lines works as expected: :'<,'>copy '>

Am I missing something? Are there better ways to duplicate selected lines programmatically? Thanks

1

1 Answer 1

3

I figured out the culprit. Thanks to Tim Pope's comment on my posted issue and the related answer here.

copy here is executed once per line selection which is not the intended behavior (i.e. the reverse order in the duplicated lines):

function Foo()
    copy '>
endfunction

We want to execute the '<,'>copy '> inside the script instead. But, this will duplicate the N selected lines N times:

function Foo()
    '<,'>copy '>
endfunction

Effectively, we want to duplicate the N selected lines once only. There are 2 options:

  • append range at the function definition:
    function Foo() range
        '<,'>copy '>
    endfunction
    
  • prepend the command with <C-U> to clear the selection before calling the function:
    function Foo()
        '<,'>copy '>
    endfunction
    
    xnoremap <Leader>r :<C-U>call Foo()<CR>
    

Both work as intended!

2
  • 2
    Great answer! In the function ... range, you should actually use execute a:firstline . "," . a:lastline . "copy '>" in the body, which actually works with the range that was passed, instead of the range of the last visual selection. That would make :1,5call Foo() or :%call Foo() work. See also this answer which expands on range functions a bit.
    – filbranden
    Apr 17, 2022 at 3:33
  • 1
    Right, that would be a nice improvement to handle various scenarios. Thanks! Apr 18, 2022 at 0:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.