'get(self.words, v:val, "???")'))
:endfunction
It's slightly different from the function above, using 'self.words' to lookup
word translations. But we don't have a self.words. Thus you could call this
an abstract class.
Now we can instantiate a Dutch translation object: >
:let uk2nl = copy(transdict)
:let uk2nl.words = {'one': 'een', 'two': 'twee', 'three': 'drie'}
:echo uk2nl.translate('three one')
< drie een ~
And a German translator: >
:let uk2de = copy(transdict)
:let uk2de.words = {'one': 'eins', 'two': 'zwei', 'three': 'drei'}
:echo uk2de.translate('three one')
< drei eins ~
You see that the copy() function is used to make a copy of the "transdict"
Dictionary and then the copy is changed to add the words. The original
remains the same, of course.
Now you can go one step further, and use your preferred translator: >
:if $LANG =~ "de"
: let trans = uk2de
:else
: let trans = uk2nl
:endif
:echo trans.translate('one two three')
< een twee drie ~
Here "trans" refers to one of the two objects (Dictionaries). No copy is
made. More about List and Dictionary identity can be found at |list-identity|
and |dict-identity|.
Now you might use a language that isn't supported. You can overrule the
translate() function to do nothing: >
:let uk2uk = copy(transdict)
:function! uk2uk.translate(line)
: return a:line
:endfunction
:echo uk2uk.translate('three one wladiwostok')
< three one wladiwostok ~
Notice that a ! was used to overwrite the existing function reference. Now
use "uk2uk" when no recognized language is found: >
:if $LANG =~ "de"
: let trans = uk2de
:elseif $LANG =~ "nl"
: let trans = uk2nl
:else
: let trans = uk2uk
:endif
:echo trans.translate('one two three')
< one two three ~
For further reading see |Lists| and |Dictionaries|.
==============================================================================
*41.9* Exceptions
Let's start with an example: >
:try
: read ~/templates/pascal.tmpl
:catch /E484:/
: echo "Sorry, the Pascal template file cannot be found."
:endtry
The ":read" command will fail if the file does not exist. Instead of
generating an error message, this code catches the error and gives the user a
nice message.
For the commands in between ":try" and ":endtry" errors are turned into
exceptions. An exception is a string. In the case of an error the string
contains the error message. And every error message has a number. In this
case, the error we catch contains "E484:". This number is guaranteed to stay
the same (the text may change, e.g., it may be translated).
When the ":read" command causes another error, the pattern "E484:" will not
match in it. Thus this exception will not be caught and result in the usual
error message and execution is aborted.
You might be tempted to do this: >
:try
: read ~/templates/pascal.tmpl
:catch
: echo "Sorry, the Pascal template file cannot be found."
:endtry
This means all errors are caught. But then you will not see errors that are
useful, such as "E21: Cannot make changes, 'modifiable' is off".
Another useful mechanism is the ":finally" command: >
:let tmp = tempname()
:try
: exe ".,$write " .. tmp
: exe "!filter " .. tmp
: .,$delete
: exe "$read " .. tmp
:finally
: call delete(tmp)
:endtry
This filters the lines from the cursor until the end of the file through the
"filter" command, which takes a file name argument. No matter if the
filtering works, something goes wrong in between ":try" and ":finally" or the
user cancels the filtering by pressing CTRL-C, the "call delete(tmp)" is
always executed. This makes sure you don't leave the temporary file behind.
More information about exception handling can be found in the reference
manual: |exception-handling|.
==============================================================================
*41.10* Various remarks
Here is a summary of items that apply to Vim scripts. They are also mentioned
elsewhere, but form a nice checklist.