Vim eval feature

Using your .vimrc file on many machines with different versions and feature sets for Vim is generally not too much of a problem if you apply a little care in making a gracefully degrading .vimrc. In most cases, using the output of vim --version and checking the help files will tell you what features to check in order to determine which parts of your .vimrc configuration to load, and which to ignore.

There’s one particular feature that’s less obvious, though, and that’s eval. Vim’s help describes it like this in :help +eval:

N  *+eval*      expression evaluation |eval.txt|

The eval.txt document, in turn, describes the syntax for various features fundamental to Vimscript, including variables, functions, lists, and dictionaries.

All this makes eval perhaps the most central feature of Vim. Without it, Vim doesn’t have much of its programmable nature, and remains not much more than classic vi. If your particular build of Vim doesn’t include it, then Vimscript essentially does not work as a programming language, and elementary calls like function and let will throw errors:

E319: Sorry, the command is not available in this version: function
E319: Sorry, the command is not available in this version: let

If you’re getting this kind of error, you’re probably using a very stripped-down version of Vim that doesn’t include eval. If you just want to prevent the error by ignoring a block of code if the feature is unavailable, you can do this with has():

if has("eval")
    ...
endif

Vim will still be perfectly functional as a vi-style editor without +eval, but if you’re going to need any Vimscript at all, you should recompile Vim with a --with-features value for the ./configure line that does include it, such as normal, big, or huge, or install a more fully-featured packaged version. For example, on Debian-like systems, the vim-tiny package that is included in the netinst system does not include eval, but the vim and vim-runtime packages do.

Inspecting Vim’s source, in particular the ex_docmd.c file, gives some indication of how fundamental this feature is, applying the C function ex_ni which simply prints the “not available” error shown above to a large number of control structures and statements if the FEAT_EVAL constant is not defined:

#ifndef FEAT_EVAL
# define ex_scriptnames     ex_ni
# define ex_finish      ex_ni
# define ex_echo        ex_ni
# define ex_echohl      ex_ni
# define ex_execute     ex_ni
# define ex_call        ex_ni
# define ex_if          ex_ni
# define ex_endif       ex_ni
# define ex_else        ex_ni
# define ex_while       ex_ni
# define ex_continue        ex_ni
# define ex_break       ex_ni
# define ex_endwhile        ex_ni
# define ex_throw       ex_ni
# define ex_try         ex_ni
# define ex_catch       ex_ni
# define ex_finally     ex_ni
# define ex_endtry      ex_ni
# define ex_endfunction     ex_ni
# define ex_let         ex_ni
# define ex_unlet       ex_ni
# define ex_lockvar     ex_ni
# define ex_unlockvar       ex_ni
# define ex_function        ex_ni
# define ex_delfunction     ex_ni
# define ex_return      ex_ni
# define ex_oldfiles        ex_ni
#endif

Packaging built software

The Debian package repository is enormous, and the Sid distribution is in most cases reasonably up-to-date, but it’s still sometimes desirable to build an application and install it into /usr/local when a packaged implementation either isn’t available or is too out of date, or if you’re involved in the development of a project and want to try out a fresh build that hasn’t been packaged yet.

The usual cycle of configuring, compiling, and installing many open-source applications for Unix-like systems applies here:

$ ./configure
$ make
# make install

The above is normally the approach taken to install code compiled on the machine, rather than through packages. One problem with this approach is that it doesn’t allow many of the advantages that a system running purely on packages does; dpkg -l will no longer give you a complete overview of all the system’s software, and to remove the software and its configuration files you may have to manually delete it rather than using apt-get purge.

Fortunately, there exists a tool called checkinstall to allow having the best of both worlds. After installing this tool via apt-get install checkinstall, you’re able to build a package for your locally built software according to the rules defined in its Makefile, and install that the same way as any other package.

Instead of typing make install, type checkinstall, and you will be prompted for details about the package, including its description, which is then built and installed. In this example, I’m compiling Vim from source, which works very well. I’ve also successfully installed tools like pam_ssh_agent_auth and tmux this way.

With this done, the package’s files are installed in /usr/local, and it appears in the list of installed packages along with my explanation of its contents:

$ ./configure
$ make
$ sudo -s
# checkinstall
...
*****************************************
**** Debian package creation selected ***
*****************************************

This package will be built according to these values:

0 -  Maintainer: [ Tom Ryder <tom@sanctum.geek.nz> ]
1 -  Summary: [ Custom build of latest Vim 7.3 ]
2 -  Name:    [ vim ]
3 -  Version: [ 2:7.4 ]
4 -  Release: [ 1 ]
5 -  License: [ GPL ]
6 -  Group:   [ checkinstall ]
7 -  Architecture: [ amd64 ]
8 -  Source location: [ vim ]
9 -  Alternate source location: [  ]
10 - Requires: [  ]
11 - Provides: [ vim ]
12 - Conflicts: [  ]
13 - Replaces: [  ]

Note that I’m assigning it a version number greater than the Debian repository’s vim package, which is a simple way to prevent it being replaced. You can also do this via the /etc/apt/preferences file to prevent replacement of all packages from the checkinstall group.

With this done, my custom build of Vim now shows in the package list, and its files are correctly installed in /usr/local:

# dpkg -l | grep vim
ii  vim  2:7.4-1 Custom build of latest Vim 7.3
# dpkg -S vim
vim: /usr/local/share/vim/vim73/bugreport.vim
vim: /usr/local/share/vim/vim73/plugin
vim: /usr/local/share/vim/vim73/ftplugin/postscr.vim
vim: /usr/local/share/man/it.UTF-8/man1/vim.1.gz
...

The .deb package built by checkinstall is also present in my build directory for me to keep for later, or for installation on another compatible server:

$ ls *.deb
vim_7.4-1_amd64.deb

It’s worth noting that checkinstall is not a Debian-specific tool; it works for other packaging systems like RPM and Slackware, too.