0
function! s:Surround(motion = "") abort
    let [_, l:start_row, l:start_col, _] = getpos("'[")
    let [_, l:end_row, l:end_col, _] = getpos("']")

    let l:before = "<p>"
    let l:after = "</p>"

    if l:start_row == l:end_row
        let l:end_col += strwidth(l:before)
    endif

    call cursor(l:start_row, l:start_col)
    silent execute "normal i" . l:before . "\<Esc>"

    call cursor(l:end_row, l:end_col)
    silent execute "normal a" . l:after . "\<Esc>"
endfunction

nnoremap s :set opfunc=<SID>Surround<CR>g@

This works well for some motions but not others. For example, given this text:

I have reset the sensors to scan for frequencies outside the usual range. By
emitting harmonic vibrations to shatter the lattices.

We will monitor and adjust the frequency of the resonators. He has this ability
of instantly interpreting and extrapolating any verbal communication he hears.

It may be due to the envelope over the structure, causing hydrogen-carbon helix
patterns throughout. I'm comparing the molecular integrity of that bubble
against our phasers.

If I put the cursor at 4:21 ("adjust the frequency") and type s3e, and the result is <p>adjust the frequency</p>. This is exactly what I want. sG also works as expected and adds the </p> on the last line.

But if I type s}, the result is:

We will monitor and <p>adjust the frequency of the resonators. He has this ability
of instantly interpreting and extrapolating any verbal communication he hears.</p>

I'm confused by this, because if I just type } at that position the cursor jumps to the next blank line. So I would expect that's where the </p> would be added. Why is it inserted before that position?

If it was possible to get the motion used, then I handle that case specially. But that feels icky and I'd rather understand what's going on.

1 Answer 1

2

{ is called "exclusive motion". There is topic in help about that. Cf. pressing "w" moves cursor onto the first letter of next word, but pressing "dw" deletes until it.

So to be precise in opfunc you have to parse the motion type argument and act accordingly, i.e. for "line" motion add surround on new lines, etc.

1

Your Answer

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

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