4

Is it possible to declare a function only for a specific filetype? Currently, if I have the following in ftplugin/tex.vim:

function! Foo()
    echom "yes"
endfunction

Then when I load a *.tex file and then switch to a buffer containing another filetype, the function is still available even though it may not be relevant. How is it best to deal with this?

I am aware that the following options are possible, but wonder if there is a better way of dealing with what can't be an uncommon problem.

Option 1: Check filetype within the function

function! Foo()
    if &filetype ==# "tex"
        echom "yes"
    endif
endfunction

Option 2: access via a buffer-specific command in ftplugin/tex.vim:

function! Foo()
    echom "yes"
endfunction
command! -buffer Foo call Foo()
2
  • 1
    There's no concept of filetype-specific function. You can have a script-local function (and in Vim9 a function-local function, as well as a block-local function). Why is that an issue?
    – user938271
    Mar 1 at 13:58
  • 1
    It's not so much that it's an issue, more that some functions are only relevant to specific filetypes. I think I should look at it more as restricting commands (with -buffer in the ftplugin/*.vim) rather than functions themselves. Mar 1 at 19:19
4

Function defined in ftplugins

In ftplugins we can define script local functions and global functions that are defined only when a buffer of the given filtetype is loaded.

In the second case, the function is still global and can be hidden by any other script.

In both cases, the functions will be redefined every time a new buffer of the same filetype is opened, unless we use another global guard to avoid loading some global part of the ftplugin. Either way, the ftplugin is bigger and it'll take slightly more time to be loaded.

Global functions that support multiple filetypes. (your option 1)

This approach makes sense when defining a same function that could be used from different filetypes, and its behaviour needs to be adapted to the current filetype (or any filetype passed as parameter).

Autoloaded functions

Nowadays (i.e. since I'm sure the version of Vim I'm using is >= 7.0), instead of global functions I prefer autoloaded functions. They are still some kind of global functions anybody could override (that's why I use my initials as a prefix to avoid name clashes).

The big advantage is that they are (lazily) loaded on the fly, and once -- no need for guards anymore, and they are only loaded when used. For instance, ftplugin file could define the command, but the function behind the command would be defined only on first use.

Also, I find it easier to test them, and to update their definition when working on their implementation.

When the function can be used from buffers of different filetypes, I use a global name (lh#somefunc()). When the function only makes sense from, let's say C++, I use the filetype in the name of the function (e.g. lh#cpp#somefunc())

Filetype-polymorphism.

It's possible to emulate some kind of filetype polymorphism and call functions named foo#{ft}#bar#func(). I've defined a convoluted framework for this purpose. I mainly use it from my refactoring plugin as variables declarations, getter signatures, and so on, will change according to the filetype while the main procedure stays the same.

1
  • 1
    Thank you for this comprehensive answer. I have gone with a combination of autoloading functions with a similar scheme to yours (e.g. local#latex#foo()) and then declaring a buffer-local command in ftplugin/tex.vim (e.g. command! -buffer Foo call local#latex#foo()). Mar 1 at 19:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.