aboutsummaryrefslogtreecommitdiff
path: root/runtime
diff options
context:
space:
mode:
Diffstat (limited to 'runtime')
-rw-r--r--runtime/doc/builtin.txt60
-rw-r--r--runtime/doc/userfunc.txt60
2 files changed, 103 insertions, 17 deletions
diff --git a/runtime/doc/builtin.txt b/runtime/doc/builtin.txt
index cb05718ab9..15ccfd9b92 100644
--- a/runtime/doc/builtin.txt
+++ b/runtime/doc/builtin.txt
@@ -5572,8 +5572,24 @@ mkdir({name} [, {flags} [, {prot}]])
When {flags} is present it must be a string. An empty string
has no effect.
- If {flags} is "p" then intermediate directories are created as
- necessary.
+ If {flags} contains "p" then intermediate directories are
+ created as necessary.
+
+ If {flags} contains "D" then {name} is deleted at the end of
+ the current function, as with: >
+ defer delete({name}, 'd')
+<
+ If {flags} contains "R" then {name} is deleted recursively at
+ the end of the current function, as with: >
+ defer delete({name}, 'rf')
+< Note that when {name} has more than one part and "p" is used
+ some directories may already exist. Only the first one that
+ is created and what it contains is scheduled to be deleted.
+ E.g. when using: >
+ call mkdir('subdir/tmp/autoload', 'pR')
+< and "subdir" already exists then "subdir/tmp" will be
+ scheduled for deletion, like with: >
+ defer delete('subdir/tmp', 'rf')
If {prot} is given it is used to set the protection bits of
the new directory. The default is 0o755 (rwxr-xr-x: r/w for
@@ -9507,31 +9523,43 @@ writefile({object}, {fname} [, {flags}])
When {object} is a |List| write it to file {fname}. Each list
item is separated with a NL. Each list item must be a String
or Number.
- When {flags} contains "b" then binary mode is used: There will
- not be a NL after the last list item. An empty item at the
- end does cause the last line in the file to end in a NL.
+ All NL characters are replaced with a NUL character.
+ Inserting CR characters needs to be done before passing {list}
+ to writefile().
When {object} is a |Blob| write the bytes to file {fname}
- unmodified.
+ unmodified, also when binary mode is not specified.
- When {flags} contains "a" then append mode is used, lines are
- appended to the file: >
+ {flags} must be a String. These characters are recognized:
+
+ 'b' Binary mode is used: There will not be a NL after the
+ last list item. An empty item at the end does cause the
+ last line in the file to end in a NL.
+
+ 'a' Append mode is used, lines are appended to the file: >
:call writefile(["foo"], "event.log", "a")
:call writefile(["bar"], "event.log", "a")
<
- When {flags} contains "S" fsync() call is not used, with "s"
- it is used, 'fsync' option applies by default. No fsync()
- means that writefile() will finish faster, but writes may be
- left in OS buffers and not yet written to disk. Such changes
- will disappear if system crashes before OS does writing.
+ 'D' Delete the file when the current function ends. This
+ works like: >
+ :defer delete({fname})
+< Fails when not in a function. Also see |:defer|.
+
+ 's' fsync() is called after writing the file. This flushes
+ the file to disk, if possible. This takes more time but
+ avoids losing the file if the system crashes.
+
+ 'S' fsync() is not called, even when 'fsync' is set.
+
+ When {flags} does not contain "S" or "s" then fsync() is
+ called if the 'fsync' option is set.
- All NL characters are replaced with a NUL character.
- Inserting CR characters needs to be done before passing {list}
- to writefile().
An existing file is overwritten, if possible.
+
When the write fails -1 is returned, otherwise 0. There is an
error message if the file can't be created or when writing
fails.
+
Also see |readfile()|.
To copy a file byte for byte: >
:let fl = readfile("foo", "b")
diff --git a/runtime/doc/userfunc.txt b/runtime/doc/userfunc.txt
index ce6f2fc2e9..db0127df95 100644
--- a/runtime/doc/userfunc.txt
+++ b/runtime/doc/userfunc.txt
@@ -350,10 +350,68 @@ A function can also be called as part of evaluating an expression or when it
is used as a method: >
let x = GetList()
let y = GetList()->Filter()
+<
+==============================================================================
+3. 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) abort
+ 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) abort
+ 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 deferred functions are called in reverse order, the last one added is
+executed first. A useless example: >
+ func Useless() abort
+ 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. The function can be a partial with extra arguments, but
+not with a dictionary. *E1300*
==============================================================================
-3. Automatically loading functions ~
+
+4. Automatically loading functions ~
*autoload-functions*
When using many or large functions, it's possible to automatically define them
only when they are used. There are two methods: with an autocommand and with