Christian Brabandt | b4ddc6c | 2024-01-02 16:51:11 +0100 | [diff] [blame] | 1 | *usr_50.txt* For Vim version 9.1. Last change: 2022 Jun 20 |
Bram Moolenaar | 30ab04e | 2022-05-14 13:33:50 +0100 | [diff] [blame] | 2 | |
| 3 | VIM USER MANUAL - by Bram Moolenaar |
| 4 | |
| 5 | Advanced Vim script writing |
| 6 | |
| 7 | |
Bram Moolenaar | 63f3260 | 2022-06-09 20:45:54 +0100 | [diff] [blame] | 8 | |50.1| Exceptions |
Bram Moolenaar | 8a3b805 | 2022-06-26 12:21:15 +0100 | [diff] [blame] | 9 | |50.2| Function with variable number of arguments |
Bram Moolenaar | 63f3260 | 2022-06-09 20:45:54 +0100 | [diff] [blame] | 10 | |50.3| Restoring the view |
Bram Moolenaar | 30ab04e | 2022-05-14 13:33:50 +0100 | [diff] [blame] | 11 | |
| 12 | Next chapter: |usr_51.txt| Create a plugin |
| 13 | Previous chapter: |usr_45.txt| Select your language (local) |
| 14 | Table of contents: |usr_toc.txt| |
| 15 | |
| 16 | ============================================================================== |
Bram Moolenaar | 63f3260 | 2022-06-09 20:45:54 +0100 | [diff] [blame] | 17 | *50.1* Exceptions |
Bram Moolenaar | 30ab04e | 2022-05-14 13:33:50 +0100 | [diff] [blame] | 18 | |
Bram Moolenaar | 63f3260 | 2022-06-09 20:45:54 +0100 | [diff] [blame] | 19 | Let's start with an example: > |
Bram Moolenaar | cfa8f9a | 2022-06-03 21:59:47 +0100 | [diff] [blame] | 20 | |
Bram Moolenaar | 63f3260 | 2022-06-09 20:45:54 +0100 | [diff] [blame] | 21 | try |
| 22 | read ~/templates/pascal.tmpl |
| 23 | catch /E484:/ |
| 24 | echo "Sorry, the Pascal template file cannot be found." |
| 25 | endtry |
Bram Moolenaar | cfa8f9a | 2022-06-03 21:59:47 +0100 | [diff] [blame] | 26 | |
Bram Moolenaar | 63f3260 | 2022-06-09 20:45:54 +0100 | [diff] [blame] | 27 | The `read` command will fail if the file does not exist. Instead of |
| 28 | generating an error message, this code catches the error and gives the user a |
| 29 | message with more information. |
Bram Moolenaar | cfa8f9a | 2022-06-03 21:59:47 +0100 | [diff] [blame] | 30 | |
Bram Moolenaar | 63f3260 | 2022-06-09 20:45:54 +0100 | [diff] [blame] | 31 | For the commands in between `try` and `endtry` errors are turned into |
| 32 | exceptions. An exception is a string. In the case of an error the string |
| 33 | contains the error message. And every error message has a number. In this |
| 34 | case, the error we catch contains "E484:". This number is guaranteed to stay |
| 35 | the same (the text may change, e.g., it may be translated). |
Bram Moolenaar | cfa8f9a | 2022-06-03 21:59:47 +0100 | [diff] [blame] | 36 | |
Bram Moolenaar | 63f3260 | 2022-06-09 20:45:54 +0100 | [diff] [blame] | 37 | Besides being able to give a nice error message, Vim will also continue |
| 38 | executing commands after the `:endtry`. Otherwise, once an uncaught error is |
| 39 | encountered, execution of the script/function/mapping will be aborted. |
Bram Moolenaar | cfa8f9a | 2022-06-03 21:59:47 +0100 | [diff] [blame] | 40 | |
Bram Moolenaar | 63f3260 | 2022-06-09 20:45:54 +0100 | [diff] [blame] | 41 | When the `read` command causes another error, the pattern "E484:" will not |
| 42 | match in it. Thus this exception will not be caught and result in the usual |
| 43 | error message and execution is aborted. |
| 44 | |
| 45 | You might be tempted to do this: > |
| 46 | |
| 47 | try |
| 48 | read ~/templates/pascal.tmpl |
| 49 | catch |
| 50 | echo "Sorry, the Pascal template file cannot be found." |
| 51 | endtry |
| 52 | |
| 53 | This means all errors are caught. But then you will not see an error that |
| 54 | would indicate a completely different problem, such as "E21: Cannot make |
| 55 | changes, 'modifiable' is off". Think twice before you catch any error! |
| 56 | |
| 57 | Another useful mechanism is the `finally` command: > |
| 58 | |
| 59 | var tmp = tempname() |
| 60 | try |
| 61 | exe ":.,$write " .. tmp |
| 62 | exe "!filter " .. tmp |
| 63 | :.,$delete |
| 64 | exe ":$read " .. tmp |
| 65 | finally |
| 66 | delete(tmp) |
| 67 | endtry |
| 68 | |
| 69 | This filters the lines from the cursor until the end of the file through the |
| 70 | "filter" command, which takes a file name argument. No matter if the |
| 71 | filtering works, if something goes wrong in between `try` and `finally` or the |
| 72 | user cancels the filtering by pressing CTRL-C, the `delete(tmp)` call is |
| 73 | always executed. This makes sure you don't leave the temporary file behind. |
| 74 | |
| 75 | The `finally` does not catch the exception, the error will still abort |
| 76 | further execution. |
| 77 | |
| 78 | More information about exception handling can be found in the reference |
| 79 | manual: |exception-handling|. |
Bram Moolenaar | cfa8f9a | 2022-06-03 21:59:47 +0100 | [diff] [blame] | 80 | |
| 81 | ============================================================================== |
Bram Moolenaar | 63f3260 | 2022-06-09 20:45:54 +0100 | [diff] [blame] | 82 | *50.2* Function with variable number of arguments |
| 83 | |
| 84 | Vim enables you to define functions that have a variable number of arguments. |
| 85 | The following command, for instance, defines a function that must have 1 |
| 86 | argument (start) and can have up to 20 additional arguments: > |
| 87 | |
| 88 | def Show(start: string, ...items: list<string>) |
| 89 | |
| 90 | The variable "items" will be a list in the function containing the extra |
| 91 | arguments. You can use it like any list, for example: > |
| 92 | |
| 93 | def Show(start: string, ...items: list<string>) |
| 94 | echohl Title |
| 95 | echo "start is " .. start |
| 96 | echohl None |
| 97 | for index in range(len(items)) |
| 98 | echon $" Arg {index} is {items[index]}" |
| 99 | endfor |
| 100 | echo |
| 101 | enddef |
| 102 | |
| 103 | You can call it like this: > |
| 104 | |
| 105 | Show('Title', 'one', 'two', 'three') |
| 106 | < start is Title Arg 0 is one Arg 1 is two Arg 2 is three ~ |
Bram Moolenaar | 8a3b805 | 2022-06-26 12:21:15 +0100 | [diff] [blame] | 107 | |
Bram Moolenaar | 63f3260 | 2022-06-09 20:45:54 +0100 | [diff] [blame] | 108 | This uses the `echohl` command to specify the highlighting used for the |
| 109 | following `echo` command. `echohl None` stops it again. The `echon` command |
| 110 | works like `echo`, but doesn't output a line break. |
| 111 | |
| 112 | If you call it with one argument the "items" list will be empty. |
| 113 | `range(len(items))` returns a list with the indexes, what `for` loops over, |
| 114 | we'll explain that further down. |
| 115 | |
| 116 | ============================================================================== |
| 117 | *50.3* Restoring the view |
Bram Moolenaar | cfa8f9a | 2022-06-03 21:59:47 +0100 | [diff] [blame] | 118 | |
Bram Moolenaar | 8cc5b55 | 2022-06-23 13:04:20 +0100 | [diff] [blame] | 119 | Sometimes you want to jump around, make a change and then go back to the same |
| 120 | position and view. For example to change something in the file header. This |
| 121 | can be done with two functions: > |
Bram Moolenaar | cfa8f9a | 2022-06-03 21:59:47 +0100 | [diff] [blame] | 122 | |
Bram Moolenaar | 8cc5b55 | 2022-06-23 13:04:20 +0100 | [diff] [blame] | 123 | var view = winsaveview() |
| 124 | # Move around, make changes |
| 125 | winrestview(view) |
Bram Moolenaar | 30ab04e | 2022-05-14 13:33:50 +0100 | [diff] [blame] | 126 | |
| 127 | ============================================================================== |
| 128 | |
| 129 | Next chapter: |usr_51.txt| Create a plugin |
| 130 | |
| 131 | Copyright: see |manual-copyright| vim:tw=78:ts=8:noet:ft=help:norl: |