1

According to this answer, if a error occurs during the execution of a mapping, its execution is aborted. Why is it like that and:

1) Is there a way to prevent this from happening?

2) In the case of the above answer, the error is invisible: if i press up in the first line in vim, theres no notification of an error, and :echo errmsg also doesn't display anything new. How to view those errors?

2

This is documented under :help map-error:

Note that when an error is encountered (that causes an error message or beep) the rest of the mapping is not executed. This is Vi-compatible.

Regarding this part of your question:

2) In the case of the above answer, the error is invisible: if i press up in the first line in vim, theres no notification of an error, and :echo errmsg also doesn't display anything new. How to view those errors?

Your previous question involved using k on the first line of the document. That falls under category of producing a "beep", so you don't really get a notification that this command failed.

(It's the same outside of a mapping. If you press k on line 1, you don't really get an error message anywhere, it just "beeps" [but you might not hear it since they're quite possibly disabled] and otherwise does nothing.)

1) Is there a way to prevent this from happening?

There's :silent!:

When ! is added, error messages will also be skipped, and commands and mappings will not be aborted when an error is detected.

But it's often too coarse, since it hides errors globally. Also, if you want to use it with normal mode commands, you also need :normal!. And you typically also need to mark your mapping with <silent> to prevent it from displaying the :silent! normal! ... in the command-line.

This would work to prevent the error in the mapping from your previous question, when it's run from the first line:

:nnoremap <silent> + :silent! normal! ddkP<CR>

But I wouldn't actually recommend using this for the mapping, as there are better solutions to it.

I guess the right answer is: You should write your mappings defensively, so that errors won't happen where you don't want them. A better approach:

:nnoremap <expr> + line('.') > 1 ? 'ddkP' : ''

This also lets you handle the case of running it on the last line of the buffer, in which case deleting the line will also move you one line up:

:nnoremap <expr> + line('.') == line('$') ? 'ddP' : line('.') > 1 ? 'ddkP' : ''

But even then, the «bubble» mappings in @D.BenKnoble's answer using the :move command are a much more superior way to accomplish the same:

" Bubble single lines up and down
nnoremap - :.move +1
nnoremap _ :.move -2
" Bubble lines up and down in visual mode
vnoremap - :'move '>+1 \| normal! gv
vnoremap _ :'move '

One final point is that breaking execution on error for mappings and macros is actually a feature. For example, if you have a recursive mapping or macro, if you want to process each line, you know you can simply move on to the next line and call the mapping/macro again, since you know there's a stop condition at the point where you can't move on to the next line again (end of the file.)

Similarly for when you're doing searches with / or ?. You know the mapping/macro will stop if you search for a term that doesn't exist anymore. Or if you set 'nowrapscan', you know you'll stop at the last match of the file.

In both of those cases, silently continuing after a failure would be really problematic, since it would make it much harder to implement recursion and it would potentially keep executing commands meant for a match when no match was found.

So, in short, try to prevent errors when you can. Try to write your mappings in a way that is unlikely to trigger errors. Use breaking on errors to your favor.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy