I have a vim function that moves the cursor. It may also throw an error. A simplified version for illustrative purpose is:
" Move cursor to the 1st line. Errors if the cursor was on the 2nd line.
function! FirstLineErrorOut()
let l:curr_line = line(".")
call cursor(1, 1)
if l:curr_line == 2
throw "error"
endif
endfunction
I then bind a key to it in operator-pending mode:
onoremap lb :call FirstLineErrorOut()<cr>
What I want to achieve is to complete the actions before the error (i.e. positioning the cursor), and then abort the operator-pending mode by throwing an error (see https://vimhelp.org/map.txt.html#map-error), yet without showing any error message (i.e. "Error detected while processing function ... E605: Exception not caught: error").
The mapping currently positions the cursor, aborts the operator-pending mode, but does show error messages and needs the user to press <enter>
to continue, which I'd like to avoid.
Note that this effect is achievable with builtin vim keys like b
and ge
(see discussion at https://stackoverflow.com/a/79261518/7881370), where the cursor is positioned to the first line while deletion (d
) is not executed.
Things I've tried with no luck:
onoremap <silent> lb :call FirstLineErrorOut()<cr>
: the error message still shows up.onoremap <silent> lb :silent call FirstLineErrorOut()<cr>
: the error message still shows up.onoremap lb :silent! call FirstLineErrorOut()<cr>
: the error message is suppressed, but the operator-pending mode is not aborted either.redir @a
and redir END
before and after throw "error"
in FirstLineErrorOut()
definition: the error message still shows up, although it's also sent to register @a
.throw "error"
with try ... catch ... endtry
: the operator-pending mode won't get aborted of course.Thank you so much!
The trick is to first cancel the operator-pending mode, and then reactivate it depending on certain condition. Inspired by the example at vimhelp. Code:
" Move cursor to the 1st line, run the operator
" unless the cursor was on the 2nd line.
function! FirstLineErrorOut(operator)
let l:curr_line = line(".")
if l:curr_line == 2
call cursor(1, 1)
else
execute "normal! " . a:operator . ":call cursor(1, 1)\<cr>"
endif
endfunction
onoremap lb <esc>:call FirstLineErrorOut(v:operator)<cr>