blob: 2845ab8151f027590bdc260cbe800912e7e5564e [file] [log] [blame]
Bram Moolenaar2d8ed022022-05-21 13:08:16 +01001*usr_51.txt* For Vim version 8.2. Last change: 2022 May 14
Bram Moolenaar30ab04e2022-05-14 13:33:50 +01002
3 VIM USER MANUAL - by Bram Moolenaar
4
5 Write plugins
6
7
8Plugins can be used to define settings for a specific type of file, syntax
9highlighting and many other things. This chapter explains how to write the
10most common Vim plugins.
11
12|51.1| Writing a generic plugin
13|51.2| Writing a filetype plugin
14|51.3| Writing a compiler plugin
15|51.4| Writing a plugin that loads quickly
16|51.5| Writing library scripts
17|51.6| Distributing Vim scripts
18
19 Next chapter: |usr_52.txt| Write plugins using Vim9 script
20 Previous chapter: |usr_50.txt| Advanced Vim script writing
21Table of contents: |usr_toc.txt|
22
23==============================================================================
24*51.1* Writing a generic plugin *write-plugin*
25
26You can write a Vim script in such a way that many people can use it. This is
27called a plugin. Vim users can drop your script in their plugin directory and
28use its features right away |add-plugin|.
29
30There are actually two types of plugins:
31
32 global plugins: For all types of files.
33filetype plugins: Only for files of a specific type.
34
35In this section the first type is explained. Most items are also relevant for
36writing filetype plugins. The specifics for filetype plugins are in the next
37section |write-filetype-plugin|.
38
39
40NAME
41
42First of all you must choose a name for your plugin. The features provided
43by the plugin should be clear from its name. And it should be unlikely that
44someone else writes a plugin with the same name but which does something
45different.
46
47A script that corrects typing mistakes could be called "typecorrect.vim". We
48will use it here as an example.
49
50For the plugin to work for everybody, it should follow a few guidelines. This
51will be explained step-by-step. The complete example plugin is at the end.
52
53
54BODY
55
56Let's start with the body of the plugin, the lines that do the actual work: >
57
58 14 iabbrev teh the
59 15 iabbrev otehr other
60 16 iabbrev wnat want
61 17 iabbrev synchronisation
62 18 \ synchronization
63
64The actual list should be much longer, of course.
65
66The line numbers have only been added to explain a few things, don't put them
67in your plugin file!
68
69
70FIRST LINE
71>
72 1 vim9script noclear
73
74You need to use `vimscript` as the very first command. Best is to put it in
75the very first line.
76
77The script we are writing will have a `finish` command to bail out when it is
78loaded a second time. To avoid that the items defined in the script are lost
79the "noclear" argument is used. More info about this at |vim9-reload|.
80
81
82HEADER
83
84You will probably add new corrections to the plugin and soon have several
85versions lying around. And when distributing this file, people will want to
86know who wrote this wonderful plugin and where they can send remarks.
87Therefore, put a header at the top of your plugin: >
88
89 2 # Vim global plugin for correcting typing mistakes
90 3 # Last Change: 2021 Dec 30
91 4 # Maintainer: Bram Moolenaar <Bram@vim.org>
92
93About copyright and licensing: Since plugins are very useful and it's hardly
94worth restricting their distribution, please consider making your plugin
95either public domain or use the Vim |license|. A short note about this near
96the top of the plugin should be sufficient. Example: >
97
98 5 # License: This file is placed in the public domain.
99
100
101LINE CONTINUATION AND AVOIDING SIDE EFFECTS *use-cpo-save*
102
103In line 18 above, the line-continuation mechanism is used |line-continuation|.
104Users with 'compatible' set will run into trouble here, they will get an error
105message. We can't just reset 'compatible', because that has a lot of side
106effects. Instead, we will set the 'cpoptions' option to its Vim default
107value and restore it later. That will allow the use of line-continuation and
108make the script work for most people. It is done like this: >
109
110 11 var save_cpo = &cpo
111 12 set cpo&vim
112 ..
113 42 &cpo = save_cpo
114
115We first store the old value of 'cpoptions' in the "save_cpo" variable. At
116the end of the plugin this value is restored.
117
118Notice that "save_cpo" is a script-local variable. A global variable could
119already be in use for something else. Always use script-local variables for
120things that are only used in the script.
121
122
123NOT LOADING
124
125It is possible that a user doesn't always want to load this plugin. Or the
126system administrator has dropped it in the system-wide plugin directory, but a
127user has his own plugin he wants to use. Then the user must have a chance to
128disable loading this specific plugin. These lines will make it possible: >
129
130 7 if exists("g:loaded_typecorrect")
131 8 finish
132 9 endif
133 10 g:loaded_typecorrect = 1
134
135This also avoids that when the script is loaded twice it would pointlessly
136redefine functions and cause trouble for autocommands that are added twice.
137
138The name is recommended to start with "g:loaded_" and then the file name of
139the plugin, literally. The "g:" is prepended to make the variable global, so
140that other places can check whether its functionality is available. Without
141"g:" it would be local to the script.
142
143Using `finish` stops Vim from reading the rest of the file, it's much quicker
144than using if-endif around the whole file, since Vim would still need to parse
145the commands to find the `endif`.
146
147
148MAPPING
149
150Now let's make the plugin more interesting: We will add a mapping that adds a
151correction for the word under the cursor. We could just pick a key sequence
152for this mapping, but the user might already use it for something else. To
153allow the user to define which keys a mapping in a plugin uses, the <Leader>
154item can be used: >
155
156 22 map <unique> <Leader>a <Plug>TypecorrAdd;
157
158The "<Plug>TypecorrAdd;" thing will do the work, more about that further on.
159
160The user can set the "g:mapleader" variable to the key sequence that he wants
161plugin mappings to start with. Thus if the user has done: >
162
163 g:mapleader = "_"
164
165the mapping will define "_a". If the user didn't do this, the default value
166will be used, which is a backslash. Then a map for "\a" will be defined.
167
168Note that <unique> is used, this will cause an error message if the mapping
169already happened to exist. |:map-<unique>|
170
171But what if the user wants to define his own key sequence? We can allow that
172with this mechanism: >
173
174 21 if !hasmapto('<Plug>TypecorrAdd;')
175 22 map <unique> <Leader>a <Plug>TypecorrAdd;
176 23 endif
177
178This checks if a mapping to "<Plug>TypecorrAdd;" already exists, and only
179defines the mapping from "<Leader>a" if it doesn't. The user then has a
180chance of putting this in his vimrc file: >
181
182 map ,c <Plug>TypecorrAdd;
183
184Then the mapped key sequence will be ",c" instead of "_a" or "\a".
185
186
187PIECES
188
189If a script gets longer, you often want to break up the work in pieces. You
190can use functions or mappings for this. But you don't want these functions
191and mappings to interfere with the ones from other scripts. For example, you
192could define a function Add(), but another script could try to define the same
193function. To avoid this, we define the function local to the script.
194Fortunately, in |Vim9| script this is the default. In a legacy script you
195would need to prefix the name with "s:".
196
197We will define a function that adds a new typing correction: >
198
199 30 def Add(from: string, correct: bool)
Bram Moolenaar2d8ed022022-05-21 13:08:16 +0100200 31 var to = input($"type the correction for {from}: ")
201 32 exe $":iabbrev {from} {to}"
Bram Moolenaar30ab04e2022-05-14 13:33:50 +0100202 ..
203 36 enddef
204
205Now we can call the function Add() from within this script. If another
206script also defines Add(), it will be local to that script and can only
207be called from that script. There can also be a global g:Add() function,
208which is again another function.
209
210<SID> can be used with mappings. It generates a script ID, which identifies
211the current script. In our typing correction plugin we use it like this: >
212
213 24 noremap <unique> <script> <Plug>TypecorrAdd; <SID>Add
214 ..
215 28 noremap <SID>Add :call <SID>Add(expand("<cword>"), true)<CR>
216
217Thus when a user types "\a", this sequence is invoked: >
218
219 \a -> <Plug>TypecorrAdd; -> <SID>Add -> :call <SID>Add(...)
220
221If another script also maps <SID>Add, it will get another script ID and
222thus define another mapping.
223
224Note that instead of Add() we use <SID>Add() here. That is because the
225mapping is typed by the user, thus outside of the script context. The <SID>
226is translated to the script ID, so that Vim knows in which script to look for
227the Add() function.
228
229This is a bit complicated, but it's required for the plugin to work together
230with other plugins. The basic rule is that you use <SID>Add() in mappings and
231Add() in other places (the script itself, autocommands, user commands).
232
233We can also add a menu entry to do the same as the mapping: >
234
235 26 noremenu <script> Plugin.Add\ Correction <SID>Add
236
237The "Plugin" menu is recommended for adding menu items for plugins. In this
238case only one item is used. When adding more items, creating a submenu is
239recommended. For example, "Plugin.CVS" could be used for a plugin that offers
240CVS operations "Plugin.CVS.checkin", "Plugin.CVS.checkout", etc.
241
242Note that in line 28 ":noremap" is used to avoid that any other mappings cause
243trouble. Someone may have remapped ":call", for example. In line 24 we also
244use ":noremap", but we do want "<SID>Add" to be remapped. This is why
245"<script>" is used here. This only allows mappings which are local to the
246script. |:map-<script>| The same is done in line 26 for ":noremenu".
247|:menu-<script>|
248
249
250<SID> AND <Plug> *using-<Plug>*
251
252Both <SID> and <Plug> are used to avoid that mappings of typed keys interfere
253with mappings that are only to be used from other mappings. Note the
254difference between using <SID> and <Plug>:
255
256<Plug> is visible outside of the script. It is used for mappings which the
257 user might want to map a key sequence to. <Plug> is a special code
258 that a typed key will never produce.
259 To make it very unlikely that other plugins use the same sequence of
260 characters, use this structure: <Plug> scriptname mapname
261 In our example the scriptname is "Typecorr" and the mapname is "Add".
262 We add a semicolon as the terminator. This results in
263 "<Plug>TypecorrAdd;". Only the first character of scriptname and
264 mapname is uppercase, so that we can see where mapname starts.
265
266<SID> is the script ID, a unique identifier for a script.
267 Internally Vim translates <SID> to "<SNR>123_", where "123" can be any
268 number. Thus a function "<SID>Add()" will have a name "<SNR>11_Add()"
269 in one script, and "<SNR>22_Add()" in another. You can see this if
270 you use the ":function" command to get a list of functions. The
271 translation of <SID> in mappings is exactly the same, that's how you
272 can call a script-local function from a mapping.
273
274
275USER COMMAND
276
277Now let's add a user command to add a correction: >
278
279 38 if !exists(":Correct")
280 39 command -nargs=1 Correct :call Add(<q-args>, false)
281 40 endif
282
283The user command is defined only if no command with the same name already
284exists. Otherwise we would get an error here. Overriding the existing user
285command with ":command!" is not a good idea, this would probably make the user
286wonder why the command he defined himself doesn't work. |:command|
287If it did happen you can find out who to blame with: >
288
289 verbose command Correct
290
291
292SCRIPT VARIABLES
293
294When a variable starts with "s:" it is a script variable. It can only be used
295inside a script. Outside the script it's not visible. This avoids trouble
296with using the same variable name in different scripts. The variables will be
297kept as long as Vim is running. And the same variables are used when sourcing
298the same script again. |s:var|
299
300The nice thing about |Vim9| script is that variables are local to the script
301by default. You can prepend "s:" if you like, but you do not need to. And
302functions in the script can also use the script variables without a prefix.
303
304Script-local variables can also be used in functions, autocommands and user
305commands that are defined in the script. Thus they are the perfect way to
306share information between parts of your plugin, without it leaking out. In
307our example we can add a few lines to count the number of corrections: >
308
309 19 var count = 4
310 ..
311 30 def Add(from: string, correct: bool)
312 ..
313 34 count += 1
314 35 echo "you now have " .. count .. " corrections"
315 36 enddef
316
317"count" is declared and initialized to 4 in the script itself. When later
318the Add() function is called, it increments "count". It doesn't matter from
319where the function was called, since it has been defined in the script, it
320will use the local variables from this script.
321
322
323THE RESULT
324
325Here is the resulting complete example: >
326
327 1 vim9script noclear
328 2 # Vim global plugin for correcting typing mistakes
329 3 # Last Change: 2021 Dec 30
330 4 # Maintainer: Bram Moolenaar <Bram@vim.org>
331 5 # License: This file is placed in the public domain.
332 6
333 7 if exists("g:loaded_typecorrect")
334 8 finish
335 9 endif
336 10 g:loaded_typecorrect = 1
337 11 var save_cpo = &cpo
338 12 set cpo&vim
339 13
340 14 iabbrev teh the
341 15 iabbrev otehr other
342 16 iabbrev wnat want
343 17 iabbrev synchronisation
344 18 \ synchronization
345 19 var count = 4
346 20
347 21 if !hasmapto('<Plug>TypecorrAdd;')
348 22 map <unique> <Leader>a <Plug>TypecorrAdd;
349 23 endif
350 24 noremap <unique> <script> <Plug>TypecorrAdd; <SID>Add
351 25
352 26 noremenu <script> Plugin.Add\ Correction <SID>Add
353 27
354 28 noremap <SID>Add :call <SID>Add(expand("<cword>"), true)<CR>
355 29
356 30 def Add(from: string, correct: bool)
357 31 var to = input("type the correction for " .. from .. ": ")
358 32 exe ":iabbrev " .. from .. " " .. to
359 33 if correct | exe "normal viws\<C-R>\" \b\e" | endif
360 34 count += 1
361 35 echo "you now have " .. count .. " corrections"
362 36 enddef
363 37
364 38 if !exists(":Correct")
365 39 command -nargs=1 Correct call Add(<q-args>, false)
366 40 endif
367 41
368 42 &cpo = save_cpo
369
370Line 33 wasn't explained yet. It applies the new correction to the word under
371the cursor. The |:normal| command is used to use the new abbreviation. Note
372that mappings and abbreviations are expanded here, even though the function
373was called from a mapping defined with ":noremap".
374
375
376DOCUMENTATION *write-local-help*
377
378It's a good idea to also write some documentation for your plugin. Especially
379when its behavior can be changed by the user. See |add-local-help| for how
380they are installed.
381
382Here is a simple example for a plugin help file, called "typecorrect.txt": >
383
384 1 *typecorrect.txt* Plugin for correcting typing mistakes
385 2
386 3 If you make typing mistakes, this plugin will have them corrected
387 4 automatically.
388 5
389 6 There are currently only a few corrections. Add your own if you like.
390 7
391 8 Mappings:
392 9 <Leader>a or <Plug>TypecorrAdd;
393 10 Add a correction for the word under the cursor.
394 11
395 12 Commands:
396 13 :Correct {word}
397 14 Add a correction for {word}.
398 15
399 16 *typecorrect-settings*
400 17 This plugin doesn't have any settings.
401
402The first line is actually the only one for which the format matters. It will
403be extracted from the help file to be put in the "LOCAL ADDITIONS:" section of
404help.txt |local-additions|. The first "*" must be in the first column of the
405first line. After adding your help file do ":help" and check that the entries
406line up nicely.
407
408You can add more tags inside ** in your help file. But be careful not to use
409existing help tags. You would probably use the name of your plugin in most of
410them, like "typecorrect-settings" in the example.
411
412Using references to other parts of the help in || is recommended. This makes
413it easy for the user to find associated help.
414
415
416FILETYPE DETECTION *plugin-filetype*
417
418If your filetype is not already detected by Vim, you should create a filetype
419detection snippet in a separate file. It is usually in the form of an
420autocommand that sets the filetype when the file name matches a pattern.
421Example: >
422
423 au BufNewFile,BufRead *.foo setlocal filetype=foofoo
424
425Write this single-line file as "ftdetect/foofoo.vim" in the first directory
426that appears in 'runtimepath'. For Unix that would be
427"~/.vim/ftdetect/foofoo.vim". The convention is to use the name of the
428filetype for the script name.
429
430You can make more complicated checks if you like, for example to inspect the
431contents of the file to recognize the language. Also see |new-filetype|.
432
433
434SUMMARY *plugin-special*
435
436Summary of special things to use in a plugin:
437
438var name Variable local to the script.
439
440<SID> Script-ID, used for mappings and functions local to
441 the script.
442
443hasmapto() Function to test if the user already defined a mapping
444 for functionality the script offers.
445
446<Leader> Value of "mapleader", which the user defines as the
447 keys that plugin mappings start with.
448
449map <unique> Give a warning if a mapping already exists.
450
451noremap <script> Use only mappings local to the script, not global
452 mappings.
453
454exists(":Cmd") Check if a user command already exists.
455
456==============================================================================
457*51.2* Writing a filetype plugin *write-filetype-plugin* *ftplugin*
458
459A filetype plugin is like a global plugin, except that it sets options and
460defines mappings for the current buffer only. See |add-filetype-plugin| for
461how this type of plugin is used.
462
463First read the section on global plugins above |51.1|. All that is said there
464also applies to filetype plugins. There are a few extras, which are explained
465here. The essential thing is that a filetype plugin should only have an
466effect on the current buffer.
467
468
469DISABLING
470
471If you are writing a filetype plugin to be used by many people, they need a
472chance to disable loading it. Put this at the top of the plugin: >
473
474 # Only do this when not done yet for this buffer
475 if exists("b:did_ftplugin")
476 finish
477 endif
478 b:did_ftplugin = 1
479
480This also needs to be used to avoid that the same plugin is executed twice for
481the same buffer (happens when using an ":edit" command without arguments).
482
483Now users can disable loading the default plugin completely by making a
484filetype plugin with only these lines: >
485
486 vim9script
487 b:did_ftplugin = 1
488
489This does require that the filetype plugin directory comes before $VIMRUNTIME
490in 'runtimepath'!
491
492If you do want to use the default plugin, but overrule one of the settings,
493you can write the different setting in a script: >
494
495 setlocal textwidth=70
496
497Now write this in the "after" directory, so that it gets sourced after the
498distributed "vim.vim" ftplugin |after-directory|. For Unix this would be
499"~/.vim/after/ftplugin/vim.vim". Note that the default plugin will have set
500"b:did_ftplugin", but it is ignored here.
501
502
503OPTIONS
504
505To make sure the filetype plugin only affects the current buffer use the >
506
507 setlocal
508
509command to set options. And only set options which are local to a buffer (see
510the help for the option to check that). When using `:setlocal` for global
511options or options local to a window, the value will change for many buffers,
512and that is not what a filetype plugin should do.
513
514When an option has a value that is a list of flags or items, consider using
515"+=" and "-=" to keep the existing value. Be aware that the user may have
516changed an option value already. First resetting to the default value and
517then changing it is often a good idea. Example: >
518
519 setlocal formatoptions& formatoptions+=ro
520
521
522MAPPINGS
523
524To make sure mappings will only work in the current buffer use the >
525
526 map <buffer>
527
528command. This needs to be combined with the two-step mapping explained above.
529An example of how to define functionality in a filetype plugin: >
530
531 if !hasmapto('<Plug>JavaImport;')
532 map <buffer> <unique> <LocalLeader>i <Plug>JavaImport;
533 endif
534 noremap <buffer> <unique> <Plug>JavaImport; oimport ""<Left><Esc>
535
536|hasmapto()| is used to check if the user has already defined a map to
537<Plug>JavaImport;. If not, then the filetype plugin defines the default
538mapping. This starts with |<LocalLeader>|, which allows the user to select
539the key(s) he wants filetype plugin mappings to start with. The default is a
540backslash.
541"<unique>" is used to give an error message if the mapping already exists or
542overlaps with an existing mapping.
543|:noremap| is used to avoid that any other mappings that the user has defined
544interferes. You might want to use ":noremap <script>" to allow remapping
545mappings defined in this script that start with <SID>.
546
547The user must have a chance to disable the mappings in a filetype plugin,
548without disabling everything. Here is an example of how this is done for a
549plugin for the mail filetype: >
550
551 # Add mappings, unless the user didn't want this.
552 if !exists("g:no_plugin_maps") && !exists("g:no_mail_maps")
553 # Quote text by inserting "> "
554 if !hasmapto('<Plug>MailQuote;')
555 vmap <buffer> <LocalLeader>q <Plug>MailQuote;
556 nmap <buffer> <LocalLeader>q <Plug>MailQuote;
557 endif
558 vnoremap <buffer> <Plug>MailQuote; :s/^/> /<CR>
559 nnoremap <buffer> <Plug>MailQuote; :.,$s/^/> /<CR>
560 endif
561
562Two global variables are used:
563|g:no_plugin_maps| disables mappings for all filetype plugins
564|g:no_mail_maps| disables mappings for the "mail" filetype
565
566
567USER COMMANDS
568
569To add a user command for a specific file type, so that it can only be used in
570one buffer, use the "-buffer" argument to |:command|. Example: >
571
572 command -buffer Make make %:r.s
573
574
575VARIABLES
576
577A filetype plugin will be sourced for each buffer of the type it's for. Local
578script variables will be shared between all invocations. Use local buffer
579variables |b:var| if you want a variable specifically for one buffer.
580
581
582FUNCTIONS
583
584When defining a function, this only needs to be done once. But the filetype
585plugin will be sourced every time a file with this filetype will be opened.
586This construct makes sure the function is only defined once: >
587
588 if !exists("*Func")
589 def Func(arg)
590 ...
591 enddef
592 endif
593<
594
595UNDO *undo_indent* *undo_ftplugin*
596
597When the user does ":setfiletype xyz" the effect of the previous filetype
598should be undone. Set the b:undo_ftplugin variable to the commands that will
599undo the settings in your filetype plugin. Example: >
600
601 let b:undo_ftplugin = "setlocal fo< com< tw< commentstring<"
602 \ .. "| unlet b:match_ignorecase b:match_words b:match_skip"
603
604Using ":setlocal" with "<" after the option name resets the option to its
605global value. That is mostly the best way to reset the option value.
606
607This does require removing the "C" flag from 'cpoptions' to allow line
608continuation, as mentioned above |use-cpo-save|.
609
610For undoing the effect of an indent script, the b:undo_indent variable should
611be set accordingly.
612
613Both these variables use legacy script syntax, not |Vim9| syntax.
614
615
616FILE NAME
617
618The filetype must be included in the file name |ftplugin-name|. Use one of
619these three forms:
620
621 .../ftplugin/stuff.vim
622 .../ftplugin/stuff_foo.vim
623 .../ftplugin/stuff/bar.vim
624
625"stuff" is the filetype, "foo" and "bar" are arbitrary names.
626
627
628SUMMARY *ftplugin-special*
629
630Summary of special things to use in a filetype plugin:
631
632<LocalLeader> Value of "maplocalleader", which the user defines as
633 the keys that filetype plugin mappings start with.
634
635map <buffer> Define a mapping local to the buffer.
636
637noremap <script> Only remap mappings defined in this script that start
638 with <SID>.
639
640setlocal Set an option for the current buffer only.
641
642command -buffer Define a user command local to the buffer.
643
644exists("*s:Func") Check if a function was already defined.
645
646Also see |plugin-special|, the special things used for all plugins.
647
648==============================================================================
649*51.3* Writing a compiler plugin *write-compiler-plugin*
650
651A compiler plugin sets options for use with a specific compiler. The user can
652load it with the |:compiler| command. The main use is to set the
653'errorformat' and 'makeprg' options.
654
655Easiest is to have a look at examples. This command will edit all the default
656compiler plugins: >
657
658 next $VIMRUNTIME/compiler/*.vim
659
660Type `:next` to go to the next plugin file.
661
662There are two special items about these files. First is a mechanism to allow
663a user to overrule or add to the default file. The default files start with: >
664
665 vim9script
666 if exists("g:current_compiler")
667 finish
668 endif
669 g:current_compiler = "mine"
670
671When you write a compiler file and put it in your personal runtime directory
672(e.g., ~/.vim/compiler for Unix), you set the "current_compiler" variable to
673make the default file skip the settings.
674 *:CompilerSet*
675The second mechanism is to use ":set" for ":compiler!" and ":setlocal" for
676":compiler". Vim defines the ":CompilerSet" user command for this. However,
677older Vim versions don't, thus your plugin should define it then. This is an
678example: >
679
680 if exists(":CompilerSet") != 2
681 command -nargs=* CompilerSet setlocal <args>
682 endif
683 CompilerSet errorformat& " use the default 'errorformat'
684 CompilerSet makeprg=nmake
685
686When you write a compiler plugin for the Vim distribution or for a system-wide
687runtime directory, use the mechanism mentioned above. When
688"current_compiler" was already set by a user plugin nothing will be done.
689
690When you write a compiler plugin to overrule settings from a default plugin,
691don't check "current_compiler". This plugin is supposed to be loaded
692last, thus it should be in a directory at the end of 'runtimepath'. For Unix
693that could be ~/.vim/after/compiler.
694
695==============================================================================
696*51.4* Writing a plugin that loads quickly *write-plugin-quickload*
697
698A plugin may grow and become quite long. The startup delay may become
699noticeable, while you hardly ever use the plugin. Then it's time for a
700quickload plugin.
701
702The basic idea is that the plugin is loaded twice. The first time user
703commands and mappings are defined that offer the functionality. The second
704time the functions that implement the functionality are defined.
705
706It may sound surprising that quickload means loading a script twice. What we
707mean is that it loads quickly the first time, postponing the bulk of the
708script to the second time, which only happens when you actually use it. When
709you always use the functionality it actually gets slower!
710
711This uses a FuncUndefined autocommand. Since Vim 7 there is an alternative:
712use the |autoload| functionality |51.5|. That will also use |Vim9| script
713instead of legacy script that is used here.
714
715The following example shows how it's done: >
716
717 " Vim global plugin for demonstrating quick loading
718 " Last Change: 2005 Feb 25
719 " Maintainer: Bram Moolenaar <Bram@vim.org>
720 " License: This file is placed in the public domain.
721
722 if !exists("s:did_load")
723 command -nargs=* BNRead call BufNetRead(<f-args>)
724 map <F19> :call BufNetWrite('something')<CR>
725
726 let s:did_load = 1
727 exe 'au FuncUndefined BufNet* source ' .. expand('<sfile>')
728 finish
729 endif
730
731 function BufNetRead(...)
732 echo 'BufNetRead(' .. string(a:000) .. ')'
733 " read functionality here
734 endfunction
735
736 function BufNetWrite(...)
737 echo 'BufNetWrite(' .. string(a:000) .. ')'
738 " write functionality here
739 endfunction
740
741When the script is first loaded "s:did_load" is not set. The commands between
742the "if" and "endif" will be executed. This ends in a |:finish| command, thus
743the rest of the script is not executed.
744
745The second time the script is loaded "s:did_load" exists and the commands
746after the "endif" are executed. This defines the (possible long)
747BufNetRead() and BufNetWrite() functions.
748
749If you drop this script in your plugin directory Vim will execute it on
750startup. This is the sequence of events that happens:
751
7521. The "BNRead" command is defined and the <F19> key is mapped when the script
753 is sourced at startup. A |FuncUndefined| autocommand is defined. The
754 ":finish" command causes the script to terminate early.
755
7562. The user types the BNRead command or presses the <F19> key. The
757 BufNetRead() or BufNetWrite() function will be called.
758
7593. Vim can't find the function and triggers the |FuncUndefined| autocommand
760 event. Since the pattern "BufNet*" matches the invoked function, the
761 command "source fname" will be executed. "fname" will be equal to the name
762 of the script, no matter where it is located, because it comes from
763 expanding "<sfile>" (see |expand()|).
764
7654. The script is sourced again, the "s:did_load" variable exists and the
766 functions are defined.
767
768Notice that the functions that are loaded afterwards match the pattern in the
769|FuncUndefined| autocommand. You must make sure that no other plugin defines
770functions that match this pattern.
771
772==============================================================================
773*51.5* Writing library scripts *write-library-script*
774
775Some functionality will be required in several places. When this becomes more
776than a few lines you will want to put it in one script and use it from many
777scripts. We will call that one script a library script.
778
779Manually loading a library script is possible, so long as you avoid loading it
780when it's already done. You can do this with the |exists()| function.
781Example: >
782
783 if !exists('*MyLibFunction')
784 runtime library/mylibscript.vim
785 endif
786 MyLibFunction(arg)
787
788Here you need to know that MyLibFunction() is defined in a script
789"library/mylibscript.vim" in one of the directories in 'runtimepath'.
790
791To make this a bit simpler Vim offers the autoload mechanism. Then the
792example looks like this: >
793
794 mylib#myfunction(arg)
795
796That's a lot simpler, isn't it? Vim will recognize the function name by the
797embedded "#" character and when it's not defined search for the script
798"autoload/mylib.vim" in 'runtimepath'. That script must define the
799"mylib#myfunction()" function.
800
801You can put many other functions in the mylib.vim script, you are free to
802organize your functions in library scripts. But you must use function names
803where the part before the '#' matches the script name. Otherwise Vim would
804not know what script to load.
805
806If you get really enthusiastic and write lots of library scripts, you may
807want to use subdirectories. Example: >
808
809 netlib#ftp#read('somefile')
810
811For Unix the library script used for this could be:
812
813 ~/.vim/autoload/netlib/ftp.vim
814
815Where the function is defined like this: >
816
817 def netlib#ftp#read(fname: string)
818 # Read the file fname through ftp
819 enddef
820
821Notice that the name the function is defined with is exactly the same as the
822name used for calling the function. And the part before the last '#'
823exactly matches the subdirectory and script name.
824
825You can use the same mechanism for variables: >
826
827 var weekdays = dutch#weekdays
828
829This will load the script "autoload/dutch.vim", which should contain something
830like: >
831
832 var dutch#weekdays = ['zondag', 'maandag', 'dinsdag', 'woensdag',
833 \ 'donderdag', 'vrijdag', 'zaterdag']
834
835Further reading: |autoload|.
836
837==============================================================================
838*51.6* Distributing Vim scripts *distribute-script*
839
840Vim users will look for scripts on the Vim website: http://www.vim.org.
841If you made something that is useful for others, share it!
842
843Another place is github. But there you need to know where to find it! The
844advantage is that most plugin managers fetch plugins from github. You'll have
845to use your favorite search engine to find them.
846
847Vim scripts can be used on any system. However, there might not be a tar or
848gzip command. If you want to pack files together and/or compress them the
849"zip" utility is recommended.
850
851For utmost portability use Vim itself to pack scripts together. This can be
852done with the Vimball utility. See |vimball|.
853
854It's good if you add a line to allow automatic updating. See |glvs-plugins|.
855
856==============================================================================
857
858Next chapter: |usr_52.txt| Write plugins using Vim9 script
859
860Copyright: see |manual-copyright| vim:tw=78:ts=8:noet:ft=help:norl: