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.