blob: a6e547b9d03e988f9465f257db6862f679ac3be3 [file] [log] [blame]
Christian Brabandtdbf231a2024-11-13 20:28:43 +01001*usr_51.txt* For Vim version 9.1. Last change: 2024 Nov 13
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
Bram Moolenaarcfa8f9a2022-06-03 21:59:47 +010015|51.4| Distributing Vim scripts
Bram Moolenaar30ab04e2022-05-14 13:33:50 +010016
Bram Moolenaarcfa8f9a2022-06-03 21:59:47 +010017 Next chapter: |usr_52.txt| Write large plugins
Bram Moolenaar30ab04e2022-05-14 13:33:50 +010018 Previous chapter: |usr_50.txt| Advanced Vim script writing
19Table of contents: |usr_toc.txt|
20
21==============================================================================
22*51.1* Writing a generic plugin *write-plugin*
23
24You can write a Vim script in such a way that many people can use it. This is
25called a plugin. Vim users can drop your script in their plugin directory and
26use its features right away |add-plugin|.
27
28There are actually two types of plugins:
29
30 global plugins: For all types of files.
31filetype plugins: Only for files of a specific type.
32
33In this section the first type is explained. Most items are also relevant for
34writing filetype plugins. The specifics for filetype plugins are in the next
35section |write-filetype-plugin|.
36
Bram Moolenaarcfa8f9a2022-06-03 21:59:47 +010037We will use |Vim9| syntax here, the recommended way to write new plugins.
38Make sure the file starts with the `vim9script` command.
39
Bram Moolenaar30ab04e2022-05-14 13:33:50 +010040
41NAME
42
43First of all you must choose a name for your plugin. The features provided
44by the plugin should be clear from its name. And it should be unlikely that
45someone else writes a plugin with the same name but which does something
46different.
47
48A script that corrects typing mistakes could be called "typecorrect.vim". We
49will use it here as an example.
50
51For the plugin to work for everybody, it should follow a few guidelines. This
52will be explained step-by-step. The complete example plugin is at the end.
53
54
55BODY
56
57Let's start with the body of the plugin, the lines that do the actual work: >
58
Bram Moolenaarcfa8f9a2022-06-03 21:59:47 +010059 12 iabbrev teh the
60 13 iabbrev otehr other
61 14 iabbrev wnat want
62 15 iabbrev synchronisation
63 16 \ synchronization
Bram Moolenaar30ab04e2022-05-14 13:33:50 +010064
65The actual list should be much longer, of course.
66
67The line numbers have only been added to explain a few things, don't put them
68in your plugin file!
69
70
71FIRST LINE
72>
73 1 vim9script noclear
74
Bram Moolenaar8a3b8052022-06-26 12:21:15 +010075You need to use `vim9script` as the very first command. Best is to put it in
Bram Moolenaar30ab04e2022-05-14 13:33:50 +010076the very first line.
77
78The script we are writing will have a `finish` command to bail out when it is
79loaded a second time. To avoid that the items defined in the script are lost
80the "noclear" argument is used. More info about this at |vim9-reload|.
81
82
83HEADER
84
85You will probably add new corrections to the plugin and soon have several
86versions lying around. And when distributing this file, people will want to
87know who wrote this wonderful plugin and where they can send remarks.
88Therefore, put a header at the top of your plugin: >
89
90 2 # Vim global plugin for correcting typing mistakes
91 3 # Last Change: 2021 Dec 30
92 4 # Maintainer: Bram Moolenaar <Bram@vim.org>
93
94About copyright and licensing: Since plugins are very useful and it's hardly
95worth restricting their distribution, please consider making your plugin
96either public domain or use the Vim |license|. A short note about this near
97the top of the plugin should be sufficient. Example: >
98
99 5 # License: This file is placed in the public domain.
100
101
Bram Moolenaar30ab04e2022-05-14 13:33:50 +0100102NOT LOADING
103
104It is possible that a user doesn't always want to load this plugin. Or the
105system administrator has dropped it in the system-wide plugin directory, but a
ccn2c5240e2023-11-11 03:35:50 -0500106user has their own plugin they want to use. Then the user must have a chance
107to disable loading this specific plugin. These lines will make it possible: >
Bram Moolenaar30ab04e2022-05-14 13:33:50 +0100108
109 7 if exists("g:loaded_typecorrect")
110 8 finish
111 9 endif
112 10 g:loaded_typecorrect = 1
113
114This also avoids that when the script is loaded twice it would pointlessly
115redefine functions and cause trouble for autocommands that are added twice.
116
117The name is recommended to start with "g:loaded_" and then the file name of
118the plugin, literally. The "g:" is prepended to make the variable global, so
119that other places can check whether its functionality is available. Without
120"g:" it would be local to the script.
121
122Using `finish` stops Vim from reading the rest of the file, it's much quicker
123than using if-endif around the whole file, since Vim would still need to parse
124the commands to find the `endif`.
125
126
127MAPPING
128
129Now let's make the plugin more interesting: We will add a mapping that adds a
130correction for the word under the cursor. We could just pick a key sequence
131for this mapping, but the user might already use it for something else. To
132allow the user to define which keys a mapping in a plugin uses, the <Leader>
133item can be used: >
134
Bram Moolenaarcfa8f9a2022-06-03 21:59:47 +0100135 20 map <unique> <Leader>a <Plug>TypecorrAdd;
Bram Moolenaar30ab04e2022-05-14 13:33:50 +0100136
137The "<Plug>TypecorrAdd;" thing will do the work, more about that further on.
138
ccn2c5240e2023-11-11 03:35:50 -0500139The user can set the "g:mapleader" variable to the key sequence that they want
Bram Moolenaar30ab04e2022-05-14 13:33:50 +0100140plugin mappings to start with. Thus if the user has done: >
141
142 g:mapleader = "_"
143
144the mapping will define "_a". If the user didn't do this, the default value
145will be used, which is a backslash. Then a map for "\a" will be defined.
146
147Note that <unique> is used, this will cause an error message if the mapping
148already happened to exist. |:map-<unique>|
149
ccn2c5240e2023-11-11 03:35:50 -0500150But what if the user wants to define their own key sequence? We can allow
151that with this mechanism: >
Bram Moolenaar30ab04e2022-05-14 13:33:50 +0100152
Bram Moolenaarcfa8f9a2022-06-03 21:59:47 +0100153 19 if !hasmapto('<Plug>TypecorrAdd;')
154 20 map <unique> <Leader>a <Plug>TypecorrAdd;
155 21 endif
Bram Moolenaar30ab04e2022-05-14 13:33:50 +0100156
157This checks if a mapping to "<Plug>TypecorrAdd;" already exists, and only
158defines the mapping from "<Leader>a" if it doesn't. The user then has a
ccn2c5240e2023-11-11 03:35:50 -0500159chance of putting this in their vimrc file: >
Bram Moolenaar30ab04e2022-05-14 13:33:50 +0100160
161 map ,c <Plug>TypecorrAdd;
162
163Then the mapped key sequence will be ",c" instead of "_a" or "\a".
164
165
166PIECES
167
168If a script gets longer, you often want to break up the work in pieces. You
169can use functions or mappings for this. But you don't want these functions
170and mappings to interfere with the ones from other scripts. For example, you
171could define a function Add(), but another script could try to define the same
172function. To avoid this, we define the function local to the script.
173Fortunately, in |Vim9| script this is the default. In a legacy script you
174would need to prefix the name with "s:".
175
176We will define a function that adds a new typing correction: >
177
Bram Moolenaarcfa8f9a2022-06-03 21:59:47 +0100178 28 def Add(from: string, correct: bool)
179 29 var to = input($"type the correction for {from}: ")
180 30 exe $":iabbrev {from} {to}"
181 ...
182 34 enddef
Bram Moolenaar30ab04e2022-05-14 13:33:50 +0100183
184Now we can call the function Add() from within this script. If another
185script also defines Add(), it will be local to that script and can only
186be called from that script. There can also be a global g:Add() function,
187which is again another function.
188
189<SID> can be used with mappings. It generates a script ID, which identifies
190the current script. In our typing correction plugin we use it like this: >
191
Bram Moolenaarcfa8f9a2022-06-03 21:59:47 +0100192 22 noremap <unique> <script> <Plug>TypecorrAdd; <SID>Add
193 ...
194 26 noremap <SID>Add :call <SID>Add(expand("<cword>"), true)<CR>
Bram Moolenaar30ab04e2022-05-14 13:33:50 +0100195
196Thus when a user types "\a", this sequence is invoked: >
197
198 \a -> <Plug>TypecorrAdd; -> <SID>Add -> :call <SID>Add(...)
199
200If another script also maps <SID>Add, it will get another script ID and
201thus define another mapping.
202
203Note that instead of Add() we use <SID>Add() here. That is because the
204mapping is typed by the user, thus outside of the script context. The <SID>
205is translated to the script ID, so that Vim knows in which script to look for
206the Add() function.
207
208This is a bit complicated, but it's required for the plugin to work together
209with other plugins. The basic rule is that you use <SID>Add() in mappings and
210Add() in other places (the script itself, autocommands, user commands).
211
212We can also add a menu entry to do the same as the mapping: >
213
Bram Moolenaarcfa8f9a2022-06-03 21:59:47 +0100214 24 noremenu <script> Plugin.Add\ Correction <SID>Add
Bram Moolenaar30ab04e2022-05-14 13:33:50 +0100215
216The "Plugin" menu is recommended for adding menu items for plugins. In this
217case only one item is used. When adding more items, creating a submenu is
218recommended. For example, "Plugin.CVS" could be used for a plugin that offers
219CVS operations "Plugin.CVS.checkin", "Plugin.CVS.checkout", etc.
220
221Note that in line 28 ":noremap" is used to avoid that any other mappings cause
222trouble. Someone may have remapped ":call", for example. In line 24 we also
223use ":noremap", but we do want "<SID>Add" to be remapped. This is why
224"<script>" is used here. This only allows mappings which are local to the
225script. |:map-<script>| The same is done in line 26 for ":noremenu".
226|:menu-<script>|
227
228
229<SID> AND <Plug> *using-<Plug>*
230
231Both <SID> and <Plug> are used to avoid that mappings of typed keys interfere
232with mappings that are only to be used from other mappings. Note the
233difference between using <SID> and <Plug>:
234
235<Plug> is visible outside of the script. It is used for mappings which the
236 user might want to map a key sequence to. <Plug> is a special code
237 that a typed key will never produce.
238 To make it very unlikely that other plugins use the same sequence of
239 characters, use this structure: <Plug> scriptname mapname
240 In our example the scriptname is "Typecorr" and the mapname is "Add".
241 We add a semicolon as the terminator. This results in
242 "<Plug>TypecorrAdd;". Only the first character of scriptname and
243 mapname is uppercase, so that we can see where mapname starts.
244
245<SID> is the script ID, a unique identifier for a script.
246 Internally Vim translates <SID> to "<SNR>123_", where "123" can be any
247 number. Thus a function "<SID>Add()" will have a name "<SNR>11_Add()"
248 in one script, and "<SNR>22_Add()" in another. You can see this if
249 you use the ":function" command to get a list of functions. The
250 translation of <SID> in mappings is exactly the same, that's how you
251 can call a script-local function from a mapping.
252
253
254USER COMMAND
255
256Now let's add a user command to add a correction: >
257
Bram Moolenaarcfa8f9a2022-06-03 21:59:47 +0100258 36 if !exists(":Correct")
259 37 command -nargs=1 Correct :call Add(<q-args>, false)
260 38 endif
Bram Moolenaar30ab04e2022-05-14 13:33:50 +0100261
262The user command is defined only if no command with the same name already
263exists. Otherwise we would get an error here. Overriding the existing user
264command with ":command!" is not a good idea, this would probably make the user
ccn2c5240e2023-11-11 03:35:50 -0500265wonder why the command they defined themselves doesn't work. |:command|
Bram Moolenaar30ab04e2022-05-14 13:33:50 +0100266If it did happen you can find out who to blame with: >
267
268 verbose command Correct
269
270
271SCRIPT VARIABLES
272
273When a variable starts with "s:" it is a script variable. It can only be used
274inside a script. Outside the script it's not visible. This avoids trouble
275with using the same variable name in different scripts. The variables will be
276kept as long as Vim is running. And the same variables are used when sourcing
277the same script again. |s:var|
278
279The nice thing about |Vim9| script is that variables are local to the script
280by default. You can prepend "s:" if you like, but you do not need to. And
Bram Moolenaarcfa8f9a2022-06-03 21:59:47 +0100281functions in the script can also use the script variables without a prefix
282(they must be declared before the function for this to work).
Bram Moolenaar30ab04e2022-05-14 13:33:50 +0100283
284Script-local variables can also be used in functions, autocommands and user
285commands that are defined in the script. Thus they are the perfect way to
286share information between parts of your plugin, without it leaking out. In
287our example we can add a few lines to count the number of corrections: >
288
Bram Moolenaarcfa8f9a2022-06-03 21:59:47 +0100289 17 var count = 4
290 ...
291 28 def Add(from: string, correct: bool)
292 ...
293 32 count += 1
294 33 echo "you now have " .. count .. " corrections"
295 34 enddef
Bram Moolenaar30ab04e2022-05-14 13:33:50 +0100296
297"count" is declared and initialized to 4 in the script itself. When later
298the Add() function is called, it increments "count". It doesn't matter from
299where the function was called, since it has been defined in the script, it
300will use the local variables from this script.
301
302
303THE RESULT
304
305Here is the resulting complete example: >
306
307 1 vim9script noclear
308 2 # Vim global plugin for correcting typing mistakes
309 3 # Last Change: 2021 Dec 30
310 4 # Maintainer: Bram Moolenaar <Bram@vim.org>
311 5 # License: This file is placed in the public domain.
312 6
313 7 if exists("g:loaded_typecorrect")
314 8 finish
315 9 endif
316 10 g:loaded_typecorrect = 1
Bram Moolenaarcfa8f9a2022-06-03 21:59:47 +0100317 11
318 12 iabbrev teh the
319 13 iabbrev otehr other
320 14 iabbrev wnat want
321 15 iabbrev synchronisation
322 16 \ synchronization
323 17 var count = 4
324 18
325 19 if !hasmapto('<Plug>TypecorrAdd;')
326 20 map <unique> <Leader>a <Plug>TypecorrAdd;
327 21 endif
328 22 noremap <unique> <script> <Plug>TypecorrAdd; <SID>Add
329 23
330 24 noremenu <script> Plugin.Add\ Correction <SID>Add
Bram Moolenaar30ab04e2022-05-14 13:33:50 +0100331 25
Bram Moolenaarcfa8f9a2022-06-03 21:59:47 +0100332 26 noremap <SID>Add :call <SID>Add(expand("<cword>"), true)<CR>
Bram Moolenaar30ab04e2022-05-14 13:33:50 +0100333 27
Bram Moolenaarcfa8f9a2022-06-03 21:59:47 +0100334 28 def Add(from: string, correct: bool)
335 29 var to = input("type the correction for " .. from .. ": ")
336 30 exe ":iabbrev " .. from .. " " .. to
337 31 if correct | exe "normal viws\<C-R>\" \b\e" | endif
338 32 count += 1
339 33 echo "you now have " .. count .. " corrections"
340 34 enddef
341 35
342 36 if !exists(":Correct")
343 37 command -nargs=1 Correct call Add(<q-args>, false)
344 38 endif
Bram Moolenaar30ab04e2022-05-14 13:33:50 +0100345
Bram Moolenaarcfa8f9a2022-06-03 21:59:47 +0100346Line 31 wasn't explained yet. It applies the new correction to the word under
Bram Moolenaar30ab04e2022-05-14 13:33:50 +0100347the cursor. The |:normal| command is used to use the new abbreviation. Note
348that mappings and abbreviations are expanded here, even though the function
349was called from a mapping defined with ":noremap".
350
351
352DOCUMENTATION *write-local-help*
353
354It's a good idea to also write some documentation for your plugin. Especially
Christian Brabandt5dcee3c2024-10-13 10:26:37 +0200355when its behavior can be changed by the user. See |help-writing| for the
356syntax used by the help files and |add-local-help| for how local help files
357are installed.
Bram Moolenaar30ab04e2022-05-14 13:33:50 +0100358
359Here is a simple example for a plugin help file, called "typecorrect.txt": >
360
361 1 *typecorrect.txt* Plugin for correcting typing mistakes
362 2
363 3 If you make typing mistakes, this plugin will have them corrected
364 4 automatically.
365 5
366 6 There are currently only a few corrections. Add your own if you like.
367 7
368 8 Mappings:
369 9 <Leader>a or <Plug>TypecorrAdd;
370 10 Add a correction for the word under the cursor.
371 11
372 12 Commands:
373 13 :Correct {word}
374 14 Add a correction for {word}.
375 15
376 16 *typecorrect-settings*
377 17 This plugin doesn't have any settings.
378
379The first line is actually the only one for which the format matters. It will
380be extracted from the help file to be put in the "LOCAL ADDITIONS:" section of
381help.txt |local-additions|. The first "*" must be in the first column of the
382first line. After adding your help file do ":help" and check that the entries
383line up nicely.
384
385You can add more tags inside ** in your help file. But be careful not to use
386existing help tags. You would probably use the name of your plugin in most of
387them, like "typecorrect-settings" in the example.
388
389Using references to other parts of the help in || is recommended. This makes
390it easy for the user to find associated help.
391
392
Bram Moolenaar30ab04e2022-05-14 13:33:50 +0100393SUMMARY *plugin-special*
394
395Summary of special things to use in a plugin:
396
397var name Variable local to the script.
398
399<SID> Script-ID, used for mappings and functions local to
400 the script.
401
402hasmapto() Function to test if the user already defined a mapping
403 for functionality the script offers.
404
405<Leader> Value of "mapleader", which the user defines as the
406 keys that plugin mappings start with.
407
408map <unique> Give a warning if a mapping already exists.
409
410noremap <script> Use only mappings local to the script, not global
411 mappings.
412
413exists(":Cmd") Check if a user command already exists.
414
415==============================================================================
416*51.2* Writing a filetype plugin *write-filetype-plugin* *ftplugin*
417
418A filetype plugin is like a global plugin, except that it sets options and
419defines mappings for the current buffer only. See |add-filetype-plugin| for
420how this type of plugin is used.
421
422First read the section on global plugins above |51.1|. All that is said there
423also applies to filetype plugins. There are a few extras, which are explained
424here. The essential thing is that a filetype plugin should only have an
425effect on the current buffer.
426
427
428DISABLING
429
430If you are writing a filetype plugin to be used by many people, they need a
431chance to disable loading it. Put this at the top of the plugin: >
432
433 # Only do this when not done yet for this buffer
434 if exists("b:did_ftplugin")
435 finish
436 endif
437 b:did_ftplugin = 1
438
439This also needs to be used to avoid that the same plugin is executed twice for
440the same buffer (happens when using an ":edit" command without arguments).
441
442Now users can disable loading the default plugin completely by making a
443filetype plugin with only these lines: >
444
445 vim9script
446 b:did_ftplugin = 1
447
448This does require that the filetype plugin directory comes before $VIMRUNTIME
449in 'runtimepath'!
450
451If you do want to use the default plugin, but overrule one of the settings,
452you can write the different setting in a script: >
453
454 setlocal textwidth=70
455
456Now write this in the "after" directory, so that it gets sourced after the
457distributed "vim.vim" ftplugin |after-directory|. For Unix this would be
458"~/.vim/after/ftplugin/vim.vim". Note that the default plugin will have set
Bram Moolenaarcfa8f9a2022-06-03 21:59:47 +0100459"b:did_ftplugin", it is ignored here.
Bram Moolenaar30ab04e2022-05-14 13:33:50 +0100460
461
462OPTIONS
463
464To make sure the filetype plugin only affects the current buffer use the >
465
466 setlocal
467
468command to set options. And only set options which are local to a buffer (see
469the help for the option to check that). When using `:setlocal` for global
470options or options local to a window, the value will change for many buffers,
471and that is not what a filetype plugin should do.
472
473When an option has a value that is a list of flags or items, consider using
474"+=" and "-=" to keep the existing value. Be aware that the user may have
475changed an option value already. First resetting to the default value and
476then changing it is often a good idea. Example: >
477
478 setlocal formatoptions& formatoptions+=ro
479
480
481MAPPINGS
482
483To make sure mappings will only work in the current buffer use the >
484
485 map <buffer>
486
487command. This needs to be combined with the two-step mapping explained above.
488An example of how to define functionality in a filetype plugin: >
489
490 if !hasmapto('<Plug>JavaImport;')
491 map <buffer> <unique> <LocalLeader>i <Plug>JavaImport;
492 endif
493 noremap <buffer> <unique> <Plug>JavaImport; oimport ""<Left><Esc>
494
495|hasmapto()| is used to check if the user has already defined a map to
496<Plug>JavaImport;. If not, then the filetype plugin defines the default
497mapping. This starts with |<LocalLeader>|, which allows the user to select
ccn2c5240e2023-11-11 03:35:50 -0500498the key(s) they want filetype plugin mappings to start with. The default is a
Bram Moolenaar30ab04e2022-05-14 13:33:50 +0100499backslash.
500"<unique>" is used to give an error message if the mapping already exists or
501overlaps with an existing mapping.
502|:noremap| is used to avoid that any other mappings that the user has defined
503interferes. You might want to use ":noremap <script>" to allow remapping
504mappings defined in this script that start with <SID>.
505
506The user must have a chance to disable the mappings in a filetype plugin,
507without disabling everything. Here is an example of how this is done for a
508plugin for the mail filetype: >
509
510 # Add mappings, unless the user didn't want this.
511 if !exists("g:no_plugin_maps") && !exists("g:no_mail_maps")
512 # Quote text by inserting "> "
513 if !hasmapto('<Plug>MailQuote;')
514 vmap <buffer> <LocalLeader>q <Plug>MailQuote;
515 nmap <buffer> <LocalLeader>q <Plug>MailQuote;
516 endif
517 vnoremap <buffer> <Plug>MailQuote; :s/^/> /<CR>
518 nnoremap <buffer> <Plug>MailQuote; :.,$s/^/> /<CR>
519 endif
520
521Two global variables are used:
522|g:no_plugin_maps| disables mappings for all filetype plugins
523|g:no_mail_maps| disables mappings for the "mail" filetype
524
525
526USER COMMANDS
527
528To add a user command for a specific file type, so that it can only be used in
529one buffer, use the "-buffer" argument to |:command|. Example: >
530
531 command -buffer Make make %:r.s
532
533
534VARIABLES
535
536A filetype plugin will be sourced for each buffer of the type it's for. Local
537script variables will be shared between all invocations. Use local buffer
538variables |b:var| if you want a variable specifically for one buffer.
539
540
541FUNCTIONS
542
543When defining a function, this only needs to be done once. But the filetype
544plugin will be sourced every time a file with this filetype will be opened.
545This construct makes sure the function is only defined once: >
546
547 if !exists("*Func")
548 def Func(arg)
549 ...
550 enddef
551 endif
552<
Bram Moolenaarcfa8f9a2022-06-03 21:59:47 +0100553Don't forget to use "noclear" with the `vim9script` command to avoid that the
554function is deleted when the script is sourced a second time.
555
Bram Moolenaar30ab04e2022-05-14 13:33:50 +0100556
557UNDO *undo_indent* *undo_ftplugin*
558
559When the user does ":setfiletype xyz" the effect of the previous filetype
560should be undone. Set the b:undo_ftplugin variable to the commands that will
561undo the settings in your filetype plugin. Example: >
562
Bram Moolenaarcfa8f9a2022-06-03 21:59:47 +0100563 b:undo_ftplugin = "setlocal fo< com< tw< commentstring<"
Bram Moolenaar30ab04e2022-05-14 13:33:50 +0100564 \ .. "| unlet b:match_ignorecase b:match_words b:match_skip"
565
566Using ":setlocal" with "<" after the option name resets the option to its
567global value. That is mostly the best way to reset the option value.
568
Bram Moolenaar30ab04e2022-05-14 13:33:50 +0100569For undoing the effect of an indent script, the b:undo_indent variable should
570be set accordingly.
571
572Both these variables use legacy script syntax, not |Vim9| syntax.
573
574
575FILE NAME
576
577The filetype must be included in the file name |ftplugin-name|. Use one of
578these three forms:
579
580 .../ftplugin/stuff.vim
581 .../ftplugin/stuff_foo.vim
582 .../ftplugin/stuff/bar.vim
583
584"stuff" is the filetype, "foo" and "bar" are arbitrary names.
585
586
Bram Moolenaarcfa8f9a2022-06-03 21:59:47 +0100587FILETYPE DETECTION *plugin-filetype*
588
589If your filetype is not already detected by Vim, you should create a filetype
590detection snippet in a separate file. It is usually in the form of an
591autocommand that sets the filetype when the file name matches a pattern.
592Example: >
593
594 au BufNewFile,BufRead *.foo setlocal filetype=foofoo
595
596Write this single-line file as "ftdetect/foofoo.vim" in the first directory
597that appears in 'runtimepath'. For Unix that would be
598"~/.vim/ftdetect/foofoo.vim". The convention is to use the name of the
599filetype for the script name.
600
601You can make more complicated checks if you like, for example to inspect the
602contents of the file to recognize the language. Also see |new-filetype|.
603
604
Bram Moolenaar30ab04e2022-05-14 13:33:50 +0100605SUMMARY *ftplugin-special*
606
607Summary of special things to use in a filetype plugin:
608
609<LocalLeader> Value of "maplocalleader", which the user defines as
610 the keys that filetype plugin mappings start with.
611
612map <buffer> Define a mapping local to the buffer.
613
614noremap <script> Only remap mappings defined in this script that start
615 with <SID>.
616
617setlocal Set an option for the current buffer only.
618
Bram Moolenaar8a3b8052022-06-26 12:21:15 +0100619command -buffer Define a user command local to the buffer.
Bram Moolenaar30ab04e2022-05-14 13:33:50 +0100620
621exists("*s:Func") Check if a function was already defined.
622
623Also see |plugin-special|, the special things used for all plugins.
624
625==============================================================================
626*51.3* Writing a compiler plugin *write-compiler-plugin*
627
628A compiler plugin sets options for use with a specific compiler. The user can
629load it with the |:compiler| command. The main use is to set the
630'errorformat' and 'makeprg' options.
631
632Easiest is to have a look at examples. This command will edit all the default
633compiler plugins: >
634
635 next $VIMRUNTIME/compiler/*.vim
636
637Type `:next` to go to the next plugin file.
638
639There are two special items about these files. First is a mechanism to allow
640a user to overrule or add to the default file. The default files start with: >
641
642 vim9script
643 if exists("g:current_compiler")
644 finish
645 endif
646 g:current_compiler = "mine"
647
648When you write a compiler file and put it in your personal runtime directory
649(e.g., ~/.vim/compiler for Unix), you set the "current_compiler" variable to
650make the default file skip the settings.
651 *:CompilerSet*
652The second mechanism is to use ":set" for ":compiler!" and ":setlocal" for
Doug Kearns408281e2024-04-04 22:00:58 +0200653":compiler". Vim defines the ":CompilerSet" user command for this. This is
654an example: >
Bram Moolenaar30ab04e2022-05-14 13:33:50 +0100655
Bram Moolenaar30ab04e2022-05-14 13:33:50 +0100656 CompilerSet errorformat& " use the default 'errorformat'
657 CompilerSet makeprg=nmake
658
Christian Brabandtdbf231a2024-11-13 20:28:43 +0100659Note: arguments need to be escaped according to |option-backslash|.
660
Bram Moolenaar30ab04e2022-05-14 13:33:50 +0100661When you write a compiler plugin for the Vim distribution or for a system-wide
662runtime directory, use the mechanism mentioned above. When
663"current_compiler" was already set by a user plugin nothing will be done.
664
665When you write a compiler plugin to overrule settings from a default plugin,
666don't check "current_compiler". This plugin is supposed to be loaded
667last, thus it should be in a directory at the end of 'runtimepath'. For Unix
668that could be ~/.vim/after/compiler.
669
670==============================================================================
Bram Moolenaarcfa8f9a2022-06-03 21:59:47 +0100671*51.4* Distributing Vim scripts *distribute-script*
Bram Moolenaar30ab04e2022-05-14 13:33:50 +0100672
673Vim users will look for scripts on the Vim website: http://www.vim.org.
674If you made something that is useful for others, share it!
675
676Another place is github. But there you need to know where to find it! The
677advantage is that most plugin managers fetch plugins from github. You'll have
678to use your favorite search engine to find them.
679
680Vim scripts can be used on any system. However, there might not be a tar or
681gzip command. If you want to pack files together and/or compress them the
682"zip" utility is recommended.
683
684For utmost portability use Vim itself to pack scripts together. This can be
685done with the Vimball utility. See |vimball|.
686
687It's good if you add a line to allow automatic updating. See |glvs-plugins|.
688
689==============================================================================
690
Bram Moolenaarcfa8f9a2022-06-03 21:59:47 +0100691Next chapter: |usr_52.txt| Write large plugins
Bram Moolenaar30ab04e2022-05-14 13:33:50 +0100692
693Copyright: see |manual-copyright| vim:tw=78:ts=8:noet:ft=help:norl: