Christian Brabandt | 83d7440 | 2025-03-19 21:55:59 +0100 | [diff] [blame] | 1 | *usr_52.txt* For Vim version 9.1. Last change: 2025 Mar 17 |
Bram Moolenaar | 65e0d77 | 2020-06-14 17:29:55 +0200 | [diff] [blame] | 2 | |
| 3 | VIM USER MANUAL - by Bram Moolenaar |
| 4 | |
Bram Moolenaar | cfa8f9a | 2022-06-03 21:59:47 +0100 | [diff] [blame] | 5 | Write larger plugins |
Bram Moolenaar | 65e0d77 | 2020-06-14 17:29:55 +0200 | [diff] [blame] | 6 | |
Bram Moolenaar | cfa8f9a | 2022-06-03 21:59:47 +0100 | [diff] [blame] | 7 | When plugins do more than simple things, they tend to grow big. This file |
| 8 | explains how to make sure they still load fast and how to split them up in |
Bram Moolenaar | 016188f | 2022-06-06 20:52:59 +0100 | [diff] [blame] | 9 | smaller parts. |
Bram Moolenaar | 65e0d77 | 2020-06-14 17:29:55 +0200 | [diff] [blame] | 10 | |
Bram Moolenaar | cfa8f9a | 2022-06-03 21:59:47 +0100 | [diff] [blame] | 11 | |52.1| Export and import |
| 12 | |52.2| Autoloading |
| 13 | |52.3| Autoloading without import/export |
| 14 | |52.4| Other mechanisms to use |
| 15 | |52.5| Using a Vim9 script from legacy script |
Christian Brabandt | 015c84c | 2024-10-07 21:48:32 +0200 | [diff] [blame] | 16 | |52.6| Vim9 examples: comment and highlight-yank plugin |
Bram Moolenaar | 65e0d77 | 2020-06-14 17:29:55 +0200 | [diff] [blame] | 17 | |
| 18 | Next chapter: |usr_90.txt| Installing Vim |
Bram Moolenaar | 30ab04e | 2022-05-14 13:33:50 +0100 | [diff] [blame] | 19 | Previous chapter: |usr_51.txt| Create a plugin |
Bram Moolenaar | 65e0d77 | 2020-06-14 17:29:55 +0200 | [diff] [blame] | 20 | Table of contents: |usr_toc.txt| |
| 21 | |
| 22 | ============================================================================== |
Bram Moolenaar | cfa8f9a | 2022-06-03 21:59:47 +0100 | [diff] [blame] | 23 | *52.1* Export and import |
Bram Moolenaar | 65e0d77 | 2020-06-14 17:29:55 +0200 | [diff] [blame] | 24 | |
| 25 | Vim9 script was designed to make it easier to write large Vim scripts. It |
| 26 | looks more like other script languages, especially Typescript. Also, |
| 27 | functions are compiled into instructions that can be executed quickly. This |
| 28 | makes Vim9 script a lot faster, up to a 100 times. |
| 29 | |
| 30 | The basic idea is that a script file has items that are private, only used |
Bram Moolenaar | 016188f | 2022-06-06 20:52:59 +0100 | [diff] [blame] | 31 | inside the script file, and items that are exported, which can be used by |
| 32 | scripts that import them. That makes very clear what is defined where. |
Bram Moolenaar | 65e0d77 | 2020-06-14 17:29:55 +0200 | [diff] [blame] | 33 | |
| 34 | Let's start with an example, a script that exports one function and has one |
| 35 | private function: > |
| 36 | |
Bram Moolenaar | 016188f | 2022-06-06 20:52:59 +0100 | [diff] [blame] | 37 | vim9script |
Bram Moolenaar | 65e0d77 | 2020-06-14 17:29:55 +0200 | [diff] [blame] | 38 | |
Bram Moolenaar | 016188f | 2022-06-06 20:52:59 +0100 | [diff] [blame] | 39 | export def GetMessage(count: string): string |
| 40 | var nr = str2nr(count) |
| 41 | var result = $'To {nr} we say ' |
| 42 | result ..= GetReply(nr) |
Bram Moolenaar | 65e0d77 | 2020-06-14 17:29:55 +0200 | [diff] [blame] | 43 | return result |
| 44 | enddef |
| 45 | |
Bram Moolenaar | 016188f | 2022-06-06 20:52:59 +0100 | [diff] [blame] | 46 | def GetReply(nr: number): string |
| 47 | if nr == 42 |
Bram Moolenaar | 65e0d77 | 2020-06-14 17:29:55 +0200 | [diff] [blame] | 48 | return 'yes' |
jbm950 | f5c8f52 | 2024-05-16 13:53:39 -0400 | [diff] [blame] | 49 | elseif nr == 22 |
Bram Moolenaar | 016188f | 2022-06-06 20:52:59 +0100 | [diff] [blame] | 50 | return 'maybe' |
Bram Moolenaar | 65e0d77 | 2020-06-14 17:29:55 +0200 | [diff] [blame] | 51 | else |
| 52 | return 'no' |
| 53 | endif |
| 54 | enddef |
| 55 | |
Bram Moolenaar | 016188f | 2022-06-06 20:52:59 +0100 | [diff] [blame] | 56 | The `vim9script` command is required, `export` only works in a |Vim9| script. |
Bram Moolenaar | 65e0d77 | 2020-06-14 17:29:55 +0200 | [diff] [blame] | 57 | |
Bram Moolenaar | 016188f | 2022-06-06 20:52:59 +0100 | [diff] [blame] | 58 | The `export def GetMessage(...` line starts with `export`, meaning that this |
| 59 | function can be called by other scripts. The line `def GetReply(...` does not |
| 60 | start with `export`, this is a script-local function, it can only be used |
| 61 | inside this script file. |
Bram Moolenaar | 65e0d77 | 2020-06-14 17:29:55 +0200 | [diff] [blame] | 62 | |
Bram Moolenaar | 016188f | 2022-06-06 20:52:59 +0100 | [diff] [blame] | 63 | Now about the script where this is imported. In this example we use this |
| 64 | layout, which works well for a plugin below the "pack" directory: |
| 65 | .../plugin/theplugin.vim |
| 66 | .../lib/getmessage.vim |
Bram Moolenaar | 65e0d77 | 2020-06-14 17:29:55 +0200 | [diff] [blame] | 67 | |
Bram Moolenaar | 016188f | 2022-06-06 20:52:59 +0100 | [diff] [blame] | 68 | Assuming the "..." directory has been added to 'runtimepath', Vim will look |
| 69 | for plugins in the "plugin" directory and source "theplugin.vim". Vim does |
| 70 | not recognize the "lib" directory, you can put any scripts there. |
| 71 | |
| 72 | The above script that exports GetMessage() goes in lib/getmessage.vim. The |
| 73 | GetMessage() function is used in plugin/theplugin.vim: > |
| 74 | |
| 75 | vim9script |
| 76 | |
| 77 | import "../lib/getmessage.vim" |
| 78 | command -nargs=1 ShowMessage echomsg getmessage.GetMessage(<f-args>) |
| 79 | |
| 80 | The `import` command uses a relative path, it starts with "../", which means |
| 81 | to go one directory up. For other kinds of paths see the `:import` command. |
| 82 | |
| 83 | How we can try out the command that the plugin provides: > |
| 84 | ShowMessage 1 |
| 85 | < To 1 we say no ~ |
| 86 | > |
| 87 | ShowMessage 22 |
| 88 | < To 22 we say maybe ~ |
| 89 | |
| 90 | Notice that the function GetMessage() is prefixed with the imported script |
| 91 | name "getmessage". That way, for every imported function used, you know what |
| 92 | script it was imported from. If you import several scripts each of them could |
| 93 | define a GetMessage() function: > |
| 94 | |
| 95 | vim9script |
| 96 | |
| 97 | import "../lib/getmessage.vim" |
| 98 | import "../lib/getother.vim" |
| 99 | command -nargs=1 ShowMessage echomsg getmessage.GetMessage(<f-args>) |
| 100 | command -nargs=1 ShowOther echomsg getother.GetMessage(<f-args>) |
| 101 | |
| 102 | If the imported script name is long or you use it in many places, you can |
| 103 | shorten it by adding an "as" argument: > |
| 104 | import "../lib/getmessage.vim" as msg |
| 105 | command -nargs=1 ShowMessage echomsg msg.GetMessage(<f-args>) |
| 106 | |
| 107 | |
| 108 | RELOADING |
| 109 | |
| 110 | One thing to keep in mind: the imported "lib/getmessage.vim" script will be |
| 111 | sourced only once. When it is imported a second time sourcing it will be |
| 112 | skipped, since the items in it have already been created. It does not matter |
| 113 | if this import command is in another script, or in the same script that is |
| 114 | sourced again. |
| 115 | |
| 116 | This is efficient when using a plugin, but when still developing a plugin it |
| 117 | means that changing "lib/getmessage.vim" after it has been imported will have |
| 118 | no effect. You need to quit Vim and start it again. (Rationale: the items |
| 119 | defined in the script could be used in a compiled function, sourcing the |
| 120 | script again may break those functions). |
| 121 | |
Bram Moolenaar | cfa8f9a | 2022-06-03 21:59:47 +0100 | [diff] [blame] | 122 | |
| 123 | USING GLOBALS |
| 124 | |
| 125 | Sometimes you will want to use global variables or functions, so that they can |
| 126 | be used anywhere. A good example is a global variable that passes a |
| 127 | preference to a plugin. To avoid other scripts using the same name, use a |
| 128 | prefix that is very unlikely to be used elsewhere. For example, if you have a |
| 129 | "mytags" plugin, you could use: > |
| 130 | |
| 131 | g:mytags_location = '$HOME/project' |
| 132 | g:mytags_style = 'fast' |
Bram Moolenaar | 65e0d77 | 2020-06-14 17:29:55 +0200 | [diff] [blame] | 133 | |
| 134 | ============================================================================== |
Bram Moolenaar | cfa8f9a | 2022-06-03 21:59:47 +0100 | [diff] [blame] | 135 | *52.2* Autoloading |
Bram Moolenaar | 65e0d77 | 2020-06-14 17:29:55 +0200 | [diff] [blame] | 136 | |
Bram Moolenaar | cfa8f9a | 2022-06-03 21:59:47 +0100 | [diff] [blame] | 137 | After splitting your large script into pieces, all the lines will still be |
| 138 | loaded and executed the moment the script is used. Every `import` loads the |
| 139 | imported script to find the items defined there. Although that is good for |
| 140 | finding errors early, it also takes time. Which is wasted if the |
| 141 | functionality is not often used. |
Bram Moolenaar | 65e0d77 | 2020-06-14 17:29:55 +0200 | [diff] [blame] | 142 | |
Bram Moolenaar | cfa8f9a | 2022-06-03 21:59:47 +0100 | [diff] [blame] | 143 | Instead of having `import` load the script immediately, it can be postponed |
Bram Moolenaar | 016188f | 2022-06-06 20:52:59 +0100 | [diff] [blame] | 144 | until needed. Using the example above, only one change needs to be made in |
| 145 | the plugin/theplugin.vim script: > |
| 146 | import autoload "../lib/getmessage.vim" |
Bram Moolenaar | 65e0d77 | 2020-06-14 17:29:55 +0200 | [diff] [blame] | 147 | |
Bram Moolenaar | 016188f | 2022-06-06 20:52:59 +0100 | [diff] [blame] | 148 | Nothing in the rest of the script needs to change. However, the types will |
| 149 | not be checked. Not even the existence of the GetMessage() function is |
| 150 | checked until it is used. You will have to decide what is more important for |
| 151 | your script: fast startup or getting errors early. You can also add the |
| 152 | "autoload" argument later, after you have checked everything works. |
Bram Moolenaar | 65e0d77 | 2020-06-14 17:29:55 +0200 | [diff] [blame] | 153 | |
Bram Moolenaar | 016188f | 2022-06-06 20:52:59 +0100 | [diff] [blame] | 154 | |
| 155 | AUTOLOAD DIRECTORY |
| 156 | |
| 157 | Another form is to use autoload with a script name that is not an absolute or |
| 158 | relative path: > |
Christian Brabandt | b725873 | 2024-05-12 19:04:47 +0200 | [diff] [blame] | 159 | import autoload "monthlib.vim" |
Bram Moolenaar | 65e0d77 | 2020-06-14 17:29:55 +0200 | [diff] [blame] | 160 | |
Bram Moolenaar | cfa8f9a | 2022-06-03 21:59:47 +0100 | [diff] [blame] | 161 | This will search for the script "monthlib.vim" in the autoload directories of |
Bram Moolenaar | 016188f | 2022-06-06 20:52:59 +0100 | [diff] [blame] | 162 | 'runtimepath'. With Unix one of the directories often is "~/.vim/autoload". |
Bram Moolenaar | 3c053a1 | 2022-10-16 13:11:12 +0100 | [diff] [blame] | 163 | It will also search under 'packpath', under "start". |
Bram Moolenaar | cfa8f9a | 2022-06-03 21:59:47 +0100 | [diff] [blame] | 164 | |
Bram Moolenaar | 016188f | 2022-06-06 20:52:59 +0100 | [diff] [blame] | 165 | The main advantage of this is that this script can be easily shared with other |
Bram Moolenaar | cfa8f9a | 2022-06-03 21:59:47 +0100 | [diff] [blame] | 166 | scripts. You do need to make sure that the script name is unique, since Vim |
| 167 | will search all the "autoload" directories in 'runtimepath', and if you are |
Bram Moolenaar | 016188f | 2022-06-06 20:52:59 +0100 | [diff] [blame] | 168 | using several plugins with a plugin manager, it may add a directory to |
| 169 | 'runtimepath', each of which might have an "autoload" directory. |
| 170 | |
| 171 | Without autoload: > |
| 172 | import "monthlib.vim" |
| 173 | |
| 174 | Vim will search for the script "monthlib.vim" in the import directories of |
| 175 | 'runtimepath'. Note that in this case adding or removing "autoload" changes |
| 176 | where the script is found. With a relative or absolute path the location does |
| 177 | not change. |
Bram Moolenaar | cfa8f9a | 2022-06-03 21:59:47 +0100 | [diff] [blame] | 178 | |
| 179 | ============================================================================== |
| 180 | *52.3* Autoloading without import/export |
| 181 | |
| 182 | *write-library-script* |
| 183 | A mechanism from before import/export is still useful and some users may find |
| 184 | it a bit simpler. The idea is that you call a function with a special name. |
| 185 | That function is then in an autoload script. We will call that one script a |
| 186 | library script. |
| 187 | |
Bram Moolenaar | d592deb | 2022-06-17 15:42:40 +0100 | [diff] [blame] | 188 | The autoload mechanism is based on a function name that has "#" characters: > |
Bram Moolenaar | cfa8f9a | 2022-06-03 21:59:47 +0100 | [diff] [blame] | 189 | |
| 190 | mylib#myfunction(arg) |
| 191 | |
| 192 | Vim will recognize the function name by the embedded "#" character and when |
| 193 | it is not defined yet search for the script "autoload/mylib.vim" in |
| 194 | 'runtimepath'. That script must define the "mylib#myfunction()" function. |
| 195 | Obviously the name "mylib" is the part before the "#" and is used as the name |
| 196 | of the script, adding ".vim". |
| 197 | |
| 198 | You can put many other functions in the mylib.vim script, you are free to |
| 199 | organize your functions in library scripts. But you must use function names |
| 200 | where the part before the '#' matches the script name. Otherwise Vim would |
| 201 | not know what script to load. This is where it differs from the import/export |
| 202 | mechanism. |
| 203 | |
| 204 | If you get really enthusiastic and write lots of library scripts, you may |
| 205 | want to use subdirectories. Example: > |
| 206 | |
| 207 | netlib#ftp#read('somefile') |
| 208 | |
| 209 | Here the script name is taken from the function name up to the last "#". The |
| 210 | "#" in the middle are replaced by a slash, the last one by ".vim". Thus you |
| 211 | get "netlib/ftp.vim". For Unix the library script used for this could be: |
| 212 | |
| 213 | ~/.vim/autoload/netlib/ftp.vim |
| 214 | |
| 215 | Where the function is defined like this: > |
| 216 | |
| 217 | def netlib#ftp#read(fname: string) |
| 218 | # Read the file fname through ftp |
| 219 | enddef |
| 220 | |
| 221 | Notice that the name the function is defined with is exactly the same as the |
| 222 | name used for calling the function. And the part before the last '#' |
| 223 | exactly matches the subdirectory and script name. |
| 224 | |
| 225 | You can use the same mechanism for variables: > |
| 226 | |
| 227 | var weekdays = dutch#weekdays |
| 228 | |
| 229 | This will load the script "autoload/dutch.vim", which should contain something |
| 230 | like: > |
| 231 | |
| 232 | var dutch#weekdays = ['zondag', 'maandag', 'dinsdag', 'woensdag', |
| 233 | \ 'donderdag', 'vrijdag', 'zaterdag'] |
| 234 | |
| 235 | Further reading: |autoload|. |
| 236 | |
| 237 | ============================================================================== |
| 238 | *52.4* Other mechanisms to use |
| 239 | |
| 240 | Some may find the use of several files a hassle and prefer to keep everything |
| 241 | together in one script. To avoid this resulting in slow startup there is a |
| 242 | mechanism that only defines a small part and postpones the rest to when it is |
| 243 | actually used. *write-plugin-quickload* |
| 244 | |
| 245 | The basic idea is that the plugin is loaded twice. The first time user |
| 246 | commands and mappings are defined that offer the functionality. The second |
| 247 | time the functions that implement the functionality are defined. |
| 248 | |
| 249 | It may sound surprising that quickload means loading a script twice. What we |
| 250 | mean is that it loads quickly the first time, postponing the bulk of the |
| 251 | script to the second time, which only happens when you actually use it. When |
| 252 | you always use the functionality it actually gets slower! |
| 253 | |
| 254 | This uses a FuncUndefined autocommand. This works differently from the |
| 255 | |autoload| functionality explained above. |
| 256 | |
| 257 | The following example shows how it's done: > |
| 258 | |
| 259 | " Vim global plugin for demonstrating quick loading |
| 260 | " Last Change: 2005 Feb 25 |
| 261 | " Maintainer: Bram Moolenaar <Bram@vim.org> |
| 262 | " License: This file is placed in the public domain. |
| 263 | |
| 264 | if !exists("s:did_load") |
| 265 | command -nargs=* BNRead call BufNetRead(<f-args>) |
| 266 | map <F19> :call BufNetWrite('something')<CR> |
| 267 | |
| 268 | let s:did_load = 1 |
| 269 | exe 'au FuncUndefined BufNet* source ' .. expand('<sfile>') |
| 270 | finish |
Bram Moolenaar | 65e0d77 | 2020-06-14 17:29:55 +0200 | [diff] [blame] | 271 | endif |
| 272 | |
Bram Moolenaar | cfa8f9a | 2022-06-03 21:59:47 +0100 | [diff] [blame] | 273 | function BufNetRead(...) |
| 274 | echo 'BufNetRead(' .. string(a:000) .. ')' |
| 275 | " read functionality here |
| 276 | endfunction |
| 277 | |
| 278 | function BufNetWrite(...) |
| 279 | echo 'BufNetWrite(' .. string(a:000) .. ')' |
| 280 | " write functionality here |
| 281 | endfunction |
| 282 | |
| 283 | When the script is first loaded "s:did_load" is not set. The commands between |
| 284 | the "if" and "endif" will be executed. This ends in a |:finish| command, thus |
| 285 | the rest of the script is not executed. |
| 286 | |
| 287 | The second time the script is loaded "s:did_load" exists and the commands |
| 288 | after the "endif" are executed. This defines the (possible long) |
| 289 | BufNetRead() and BufNetWrite() functions. |
| 290 | |
| 291 | If you drop this script in your plugin directory Vim will execute it on |
| 292 | startup. This is the sequence of events that happens: |
| 293 | |
| 294 | 1. The "BNRead" command is defined and the <F19> key is mapped when the script |
| 295 | is sourced at startup. A |FuncUndefined| autocommand is defined. The |
| 296 | ":finish" command causes the script to terminate early. |
| 297 | |
| 298 | 2. The user types the BNRead command or presses the <F19> key. The |
| 299 | BufNetRead() or BufNetWrite() function will be called. |
| 300 | |
| 301 | 3. Vim can't find the function and triggers the |FuncUndefined| autocommand |
| 302 | event. Since the pattern "BufNet*" matches the invoked function, the |
| 303 | command "source fname" will be executed. "fname" will be equal to the name |
| 304 | of the script, no matter where it is located, because it comes from |
| 305 | expanding "<sfile>" (see |expand()|). |
| 306 | |
| 307 | 4. The script is sourced again, the "s:did_load" variable exists and the |
| 308 | functions are defined. |
| 309 | |
| 310 | Notice that the functions that are loaded afterwards match the pattern in the |
| 311 | |FuncUndefined| autocommand. You must make sure that no other plugin defines |
| 312 | functions that match this pattern. |
Bram Moolenaar | 65e0d77 | 2020-06-14 17:29:55 +0200 | [diff] [blame] | 313 | |
| 314 | ============================================================================== |
Bram Moolenaar | cfa8f9a | 2022-06-03 21:59:47 +0100 | [diff] [blame] | 315 | *52.5* Using a Vim9 script from legacy script *source-vim9-script* |
Bram Moolenaar | 65e0d77 | 2020-06-14 17:29:55 +0200 | [diff] [blame] | 316 | |
| 317 | In some cases you have a legacy Vim script where you want to use items from a |
| 318 | Vim9 script. For example in your .vimrc you want to initialize a plugin. The |
| 319 | best way to do this is to use `:import`. For example: > |
| 320 | |
Bram Moolenaar | 016188f | 2022-06-06 20:52:59 +0100 | [diff] [blame] | 321 | import 'myNicePlugin.vim' |
| 322 | call myNicePlugin.NiceInit('today') |
Bram Moolenaar | 65e0d77 | 2020-06-14 17:29:55 +0200 | [diff] [blame] | 323 | |
Bram Moolenaar | 016188f | 2022-06-06 20:52:59 +0100 | [diff] [blame] | 324 | This finds the exported function "NiceInit" in the Vim9 script file and makes |
| 325 | it available as script-local item "myNicePlugin.NiceInit". `:import` always |
| 326 | uses the script namespace, even when "s:" is not given. If "myNicePlugin.vim" |
| 327 | was already sourced it is not sourced again. |
Bram Moolenaar | 65e0d77 | 2020-06-14 17:29:55 +0200 | [diff] [blame] | 328 | |
| 329 | Besides avoiding putting any items in the global namespace (where name clashes |
| 330 | can cause unexpected errors), this also means the script is sourced only once, |
| 331 | no matter how many times items from it are imported. |
| 332 | |
| 333 | In some cases, e.g. for testing, you may just want to source the Vim9 script. |
| 334 | That is OK, but then only global items will be available. The Vim9 script |
| 335 | will have to make sure to use a unique name for these global items. Example: > |
| 336 | source ~/.vim/extra/myNicePlugin.vim |
| 337 | call g:NicePluginTest() |
| 338 | |
| 339 | ============================================================================== |
Christian Brabandt | 015c84c | 2024-10-07 21:48:32 +0200 | [diff] [blame] | 340 | *52.6* Vim9 examples: comment and highlight-yank plugin |
Christian Brabandt | bad9577 | 2024-05-31 14:58:26 +0200 | [diff] [blame] | 341 | |
| 342 | COMMENT PACKAGE |
| 343 | |
h-east | 9c4389a | 2024-06-09 16:32:19 +0200 | [diff] [blame] | 344 | Vim comes with a comment plugin, written in Vim9 script. |comment-install| |
Christian Brabandt | bad9577 | 2024-05-31 14:58:26 +0200 | [diff] [blame] | 345 | Have a look at the package located at $VIMRUNTIME/pack/dist/opt/comment/ |
| 346 | |
| 347 | HIGHLIGHT YANK PLUGIN |
| 348 | |
Christian Brabandt | 83d7440 | 2025-03-19 21:55:59 +0100 | [diff] [blame] | 349 | Vim comes with the highlight-yank plugin, written in Vim9 script |
| 350 | |hlyank-install|, here is a simplified implementation: >vim |
Christian Brabandt | bad9577 | 2024-05-31 14:58:26 +0200 | [diff] [blame] | 351 | |
| 352 | vim9script |
| 353 | |
| 354 | def HighlightedYank(hlgroup = 'IncSearch', duration = 300, in_visual = true) |
| 355 | if v:event.operator ==? 'y' |
h-east | 9c4389a | 2024-06-09 16:32:19 +0200 | [diff] [blame] | 356 | if !in_visual && visualmode() != null_string |
| 357 | visualmode(1) |
| 358 | return |
| 359 | endif |
| 360 | var [beg, end] = [getpos("'["), getpos("']")] |
| 361 | var type = v:event.regtype ?? 'v' |
Jim Zhou | 7db9613 | 2025-03-12 20:57:24 +0100 | [diff] [blame] | 362 | var pos = getregionpos(beg, end, {type: type, exclusive: false}) |
h-east | 9c4389a | 2024-06-09 16:32:19 +0200 | [diff] [blame] | 363 | var m = matchaddpos(hlgroup, pos->mapnew((_, v) => { |
| 364 | var col_beg = v[0][2] + v[0][3] |
Jim Zhou | 7db9613 | 2025-03-12 20:57:24 +0100 | [diff] [blame] | 365 | var col_end = v[1][2] + v[1][3] + 1 |
h-east | 9c4389a | 2024-06-09 16:32:19 +0200 | [diff] [blame] | 366 | return [v[0][1], col_beg, col_end - col_beg] |
| 367 | })) |
| 368 | var winid = win_getid() |
| 369 | timer_start(duration, (_) => m->matchdelete(winid)) |
Christian Brabandt | bad9577 | 2024-05-31 14:58:26 +0200 | [diff] [blame] | 370 | endif |
| 371 | enddef |
| 372 | |
| 373 | autocmd TextYankPost * HighlightedYank() |
| 374 | < |
Christian Brabandt | 83d7440 | 2025-03-19 21:55:59 +0100 | [diff] [blame] | 375 | For the complete example, have a look into the package located at |
| 376 | `$VIMRUNTIME/pack/dist/opt/hlyank/` |
| 377 | |
Christian Brabandt | bad9577 | 2024-05-31 14:58:26 +0200 | [diff] [blame] | 378 | ============================================================================== |
Bram Moolenaar | 65e0d77 | 2020-06-14 17:29:55 +0200 | [diff] [blame] | 379 | |
| 380 | Next chapter: |usr_90.txt| Installing Vim |
| 381 | |
Bram Moolenaar | cfa8f9a | 2022-06-03 21:59:47 +0100 | [diff] [blame] | 382 | |
Bram Moolenaar | 65e0d77 | 2020-06-14 17:29:55 +0200 | [diff] [blame] | 383 | Copyright: see |manual-copyright| vim:tw=78:ts=8:noet:ft=help:norl: |