forked from aniani/vim
patch 9.0.0370: cleaning up afterwards can make a function messy
Problem: Cleaning up afterwards can make a function messy. Solution: Add the :defer command.
This commit is contained in:
@@ -2979,6 +2979,62 @@ is used as a method: >
|
||||
let y = GetList()->Filter()
|
||||
|
||||
|
||||
CLEANING UP IN A FUNCTION ~
|
||||
*:defer*
|
||||
:defer {func}({args}) Call {func} when the current function is done.
|
||||
{args} are evaluated here.
|
||||
|
||||
Quite often a command in a function has a global effect, which must be undone
|
||||
when the function finishes. Handling this in all kinds of situations can be a
|
||||
hassle. Especially when an unexpected error is encountered. This can be done
|
||||
with `try` / `finally` blocks, but this gets complicated when there is more
|
||||
than one.
|
||||
|
||||
A much simpler solution is using `defer`. It schedules a function call when
|
||||
the function is returning, no matter if there is an error. Example: >
|
||||
func Filter(text)
|
||||
call writefile(a:text, 'Tempfile')
|
||||
call system('filter < Tempfile > Outfile')
|
||||
call Handle('Outfile')
|
||||
call delete('Tempfile')
|
||||
call delete('Outfile')
|
||||
endfunc
|
||||
|
||||
Here 'Tempfile' and 'Outfile' will not be deleted if something causes the
|
||||
function to abort. `:defer` can be used to avoid that: >
|
||||
func Filter(text)
|
||||
call writefile(a:text, 'Tempfile')
|
||||
defer delete('Tempfile')
|
||||
defer delete('Outfile')
|
||||
call system('filter < Tempfile > Outfile')
|
||||
call Handle('Outfile')
|
||||
endfunc
|
||||
|
||||
Note that deleting "Outfile" is scheduled before calling system(), since it
|
||||
can be created even when `system()` fails.
|
||||
|
||||
The defered functions are called in reverse order, the last one added is
|
||||
executed first. A useless example: >
|
||||
func Useless()
|
||||
for s in range(3)
|
||||
defer execute('echomsg "number ' .. s .. '"')
|
||||
endfor
|
||||
endfunc
|
||||
|
||||
Now `:messages` shows:
|
||||
number 2
|
||||
number 1
|
||||
number 0
|
||||
|
||||
Any return value of the deferred function is discarded. The function cannot
|
||||
be followed by anything, such as "->func" or ".member". Currently `:defer
|
||||
GetArg()->TheFunc()` does not work, it may work in a later version.
|
||||
|
||||
Errors are reported but do not cause aborting execution of deferred functions.
|
||||
|
||||
No range is accepted.
|
||||
|
||||
|
||||
AUTOMATICALLY LOADING FUNCTIONS ~
|
||||
*autoload-functions*
|
||||
When using many or large functions, it's possible to automatically define them
|
||||
|
||||
Reference in New Issue
Block a user