line
number in the script or function where it has been used: >
:function! LineNumber()
: return substitute(v:throwpoint, '.*\D\(\d\+\).*', '\1', "")
:endfunction
:command! LineNumber try | throw "" | catch | echo LineNumber() | endtry
<
*try-nested*
An exception that is not caught by a try conditional can be caught by
a surrounding try conditional: >
:try
: try
: throw "foo"
: catch /foobar/
: echo "foobar"
: finally
: echo "inner finally"
: endtry
:catch /foo/
: echo "foo"
:endtry
The inner try conditional does not catch the exception, just its finally
clause is executed. The exception is then caught by the outer try
conditional. The example displays "inner finally" and then "foo".
*throw-from-catch*
You can catch an exception and throw a new one to be caught elsewhere from the
catch clause: >
:function! Foo()
: throw "foo"
:endfunction
:
:function! Bar()
: try
: call Foo()
: catch /foo/
: echo "Caught foo, throw bar"
: throw "bar"
: endtry
:endfunction
:
:try
: call Bar()
:catch /.*/
: echo "Caught" v:exception
:endtry
This displays "Caught foo, throw bar" and then "Caught bar".
*rethrow*
There is no real rethrow in the Vim script language, but you may throw
"v:exception" instead: >
:function! Bar()
: try
: call Foo()
: catch /.*/
: echo "Rethrow" v:exception
: throw v:exception
: endtry
:endfunction
< *try-echoerr*
Note that this method cannot be used to "rethrow" Vim error or interrupt
exceptions, because it is not possible to fake Vim internal exceptions.
Trying so causes an error exception. You should throw your own exception
denoting the situation. If you want to cause a Vim error exception containing
the original error exception value, you can use the |:echoerr| command: >
:try
: try
: asdf
: catch /.*/
: echoerr v:exception
: endtry
:catch /.*/
: echo v:exception
:endtry
This code displays
Vim(echoerr):Vim:E492: Not an editor command: asdf ~
CLEANUP CODE *try-finally*
Scripts often change global settings and restore them at their end. If the
user however interrupts the script by pressing CTRL-C, the settings remain in
an inconsistent state. The same may happen to you in the development phase of
a script when an error occurs or you explicitly throw an exception without
catching it. You can solve these problems by using a try conditional with
a finally clause for restoring the settings. Its execution is guaranteed on
normal control flow, on error, on an explicit ":throw", and on interrupt.
(Note that errors and interrupts from inside the try conditional are converted
to exceptions. When not caught, they terminate the script after the finally
clause has been executed.)
Example: >
:try
: let s:saved_ts = &ts
: set ts=17
:
: " Do the hard work here.
:
:finally
: let &ts = s:saved_ts
: unlet s:saved_ts
:endtry
This method should be used locally whenever a function or part of a script
changes global settings which need to be restored on failure or normal exit of
that function or script part.
*break-finally*
Cleanup code works also when the try block or a catch clause is left by
a ":continue", ":break", ":return", or ":finish".
Example: >
:let first = 1
:while 1
: try
: if first
: echo "first"
: let first = 0
: continue
: else
: throw "second"
: endif
: catch /.*/
: echo v:exception
: break
: finally
: echo "cleanup"
: endtry
: echo "still in while"
:endwhile
:echo "end"
This displays "first", "cleanup", "second", "cleanup", and "end". >
:function! Foo()
: try
: return 4711
: finally
: echo "cleanup\n"
: endtry
: echo "Foo still active"
:endfunction
:
:echo Foo() "returned by Foo"
This displays "cleanup" and "4711 returned by Foo". You don't need to add an
extra ":return" in the finally clause. (Above all, this would override the
return value.)
*except-from-finally*