8

I have a function definition in my .vimrc. This .vimrc is sufficient to demonstrate the problem I'm asking about:

function! Greet()
    echo "hello"
endfunction

I want to be able use the same .vimrc with a version of vim configured with

--with-features=tiny

I don't expect the function to be defined, but I don't want error messages on startup.

Currently, if I run a tiny vim, I get:

Error detected while processing /home/kst/.vimrc:
line    1:
E319: Sorry, the command is not available in this version: function! Greet()
line    2:
E319: Sorry, the command is not available in this version:     echo "hello"
line    3:
E319: Sorry, the command is not available in this version: endfunction
Press ENTER or type command to continue

I'm looking for something like:

if has("function")
    function! Greet()
        echo "hello"
   endfunction
endif

but that doesn't do the job because has() doesn't recognize "function". (The result is that the function definition is disabled even for versions of vim that support functions.)

I didn't see anything obvious in the documentation for has(), and web searches with the word "function" give me a lot of irrelevant hits.

1 Answer 1

15

The problem is that "tiny" is missing the +eval feature and that's what prevents it from seeing your function definitions.

So you could try something like:

if has('eval')
    function! Greet()
        echo "hello"
    endfunction
endif

But it turns out you can go even simpler than that, as :help no-eval-feature suggests:

When the +eval feature was disabled at compile time, none of the expression evaluation commands are available. To prevent this from causing Vim scripts to generate all kinds of errors, the :if and :endif commands are still recognized, though the argument of the :if and everything between the :if and the matching :endif is ignored. Nesting of :if blocks is allowed, but only if the commands are at the start of the line. The :else command is not recognized.

So you can simply use:

if 1
    function! Greet()
        echo "hello"
    endfunction
endif

(I strongly suggest adding a comment to indicate why you're using if 1, why it makes sense, why it's needed!)

Looking inside $VIMRUNTIME/defaults.vim, there's a snippet there that uses a hack to only run a command whenever +eval is not available. Adapting that to your specific case:

" Use a trick to break out when the
" +eval feature is missing.
silent! while 0
    finish
silent! endwhile

function! Greet()
    echo "hello"
endfunction

If +eval is missing, it won't recognize the while statement and will finish, breaking out of the script and skipping everything that follows.

When +eval is present, the while 0 block will be skipped, since the condition is false.

The :help no-eval-feature section also mentions this technique (with a different command as example) and explains it:

When the +eval feature is available the command is skipped because of the while 0. Without the +eval feature the while 0 is an error, which is silently ignored, and the command is executed.

9
  • 4
    you can also use :if 1 tiny vim will not read anything in between this. Jan 7, 2020 at 7:25
  • 5
    the if 1 is the documented way how to make vim.tiny skip eval code (don't ask me where this is documented, don't find it currently) and this is also what defaults.vim used initially. The thing why silent! while 0 was needed, was because we wanted to run a piece of code only in tiny vim, but not a vim that has eval feature. So eval vims would skip that, while tiny vim does read it. Since tiny vim do not understand while, we needed :silent! to not show any error message. Jan 7, 2020 at 7:49
  • 2
    see also this issue: github.com/vim/vim/issues/1630 that lead to that part of the code. Jan 7, 2020 at 7:52
  • 4
    and the related help topic is :h no-eval-feature Jan 7, 2020 at 7:58
  • 1
    @ChristianBrabandt Both if has('eval') and if 1 work. I think the former works just because the expression is ignored. I'll use if 1. Jan 7, 2020 at 18:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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