Main menu

Tag Archives: version

If you work on many machines with varying operating systems (Windows, Linux,
MacOS X, BSD) and in various upgrade states, particularly if some of the
machines are a lot older or have more minimal or custom installations of Vim,
you might not be using your .vimrc file on all of them because it includes
features that aren’t available on some other machines, meaning that Vim spits a
lot of errors at you on startup.

This might have prompted you to perhaps keep a simpler .vimrc file, a
“lesser” .vimrc, that you put onto your remote machines, and you keep the
“real” .vimrc on your own machine to include lines that use all of the
features only available to you on that machine. If you like to version your
configuration files, maintaining and testing both of the .vimrc files on all
the machines gets old fast; it would be much better to have a single .vimrc
file that simply ignored configuration it didn’t understand. There are several
ways to approach this.

Check features

Perhaps the best way to manage this is to group all of your configuration items
by Vim feature, and to check for their presence in your .vimrc file before
attempting to set any of the relevant options. You can do this with the has()
function. As an example, here’s a stanza from my .vimrc:

I set the spellang option and perform the remapping only if the +spell
feature is actually available.

If an option is dependent on a feature having been compiled into Vim, you can
usually tell by calling :help on it and looking for a phrase like “not
available when compiled without the +xyz feature.” You can also view a list
all the features available with :help feature-list, and see which features
are compiled into a given vim binary with the --version parameter:

There are certain special features, like +unix, that you can use to check
whether the Vim instance running is on a platform suitable for an option or
not. I find this is handy for choosing the correct syntax for specifying fonts
on Windows:

if has("unix")
set guifont=Inconsolata\ 14
else
set guifont=Consolas:h12
endif

Check options

You can check whether an option itself exists rather than a feature with
exists():

if exists("&foldenable")
set foldenable
endif

Check version number

Another way of filtering out options for older versions of Vim is by version
number, which you can perform by checking the value of v:version. For
example, to only set folding options if you’re working with at least Vim 7, you
could do:

if v:version >= 700
set foldenable
endif

In this particular case, though, it’s a little clearer and more robust to check
the condition with if has("folding"), because the version number being recent
enough does not necessarily mean the feature exists. However, one good
application of using version numbers is fixing bugs or unexpected behaviour in
older instances of Vim, to make it behave consistently with newer versions, or
even vice-versa if necessary.

Silent calls

If you can’t find a way to filter by feature or version number, a simple way to
suppress any error messages from a configuration line is to preface it with
silent!. I find this is a nice compact way to call plugin-dependent functions
like pathogen#infect(), or custom colorschemes that you can’t be sure
actually exist on the machine:

silent! call pathogen#infect()
silent! colorscheme zellner

Try/Catch/If

If you’re not dealing with versions of Vim older than 7.0, another possibility
is the try/catch/endtry block. This is handy for setting a default or
fallback option if a call fails, such as selecting colorschemes:

try
colorscheme zenburn
catch
colorscheme torte
endtry

This is my least-favoured method of making .vimrc files degrade gracefully,
as it breaks completely on older instances of Vim.

Thanks to Reddit user bouncingsoul for suggesting the second method which I
initially missed.

Version control is now seen as an indispensable part of professional software
development, and GUI IDEs like Eclipse and Visual Studio have embraced it and
included support for industry standard version control systems in their
products. Modern version control systems trace their lineage back to Unix
concepts from programs such as diff and patch however, and there are plenty
of people who will insist that the best way to use a version control system is
still at a shell prompt.

In this last article in the Unix as an IDE series, I’ll follow the
evolution of common open-source version control systems from the basic concepts
of diff and patch, among the very first version control tools.

diff, patch, and RCS

A central concept for version control systems has been that of the unified
diff, a file expressing in human and computer readable terms a set of changes
made to a file or files. The diff command was first released by Douglas
McIlroy in 1974 for the 5th Edition of Unix, so it’s one of the oldest commands
still in regular use on modern systems.

A unified diff, the most common and interoperable format, can be generated by
comparing two versions of a file with the following syntax:

In this example, the second file has a header file added, and the call to
return changed to use the standard EXIT_SUCCESS rather than a literal 0
as the return value for main(). Note that the output for diff also includes
metadata such as the filename that was changed and the last modification time
of each of the files.

A primitive form of version control for larger code bases was thus for
developers to trade diff output, called patches in this context, so that
they could be applied to one another’s code bases with the patch tool. We
could save the output from diff above as a patch like so:

$ diff -u example.{1,2}.c > example.patch

We could then send this patch to a developer who still had the old version of
the file, and they could automatically apply it with:

$ patch example.1.c < example.patch

A patch can include diff output from more than one file, including within
subdirectories, so this provides a very workable way to apply changes to a
source tree.

The operations involved in using diff output to track changes were
sufficiently regular that for keeping in-place history of a file, the Source
Code Control System and the Revision Control System that has pretty
much replaced it were developed. RCS enabled “locking” files so that they could
not be edited by anyone else while “checked out” of the system, paving the way
for other concepts in more developed version control systems.

RCS retains the advantage of being very simple to use. To place an existing
file under version control, one need only type ci <filename> and provide an
appropriate description for the file:

It would be misleading to imply that simple patches were now in disuse as a
method of version control; they are still very commonly used in the forms
above, and also figure prominently in both centralised and decentralised
version control systems.

CVS and Subversion

To handle the problem of resolving changes made to a code base by multiple
developers, centralized version systems were developed, with the Concurrent
Versions System (CVS) developed first and the slightly more advanced
Subversion later on. The central feature of these systems are using a
central server that contains the repository, from which authoritative
versions of the codebase at any particular time or revision can be retrieved.
These are termed working copies of the code.

For these systems, the basic unit of the systems remained the changeset, and
the most common way to represent these to the user was in the archetypal diff
format used in earlier systems. Both systems work by keeping records of these
changesets, rather than the actual files themselves from state to state.

Other concepts introduced by this generation of systems were of branching
projects so that separate instances of the same project could be worked on
concurrently, and then merged into the mainline, or trunk with appropriate
testing and review. Similarly, the concept of tagging was introduced to flag
certain revisions as representing the state of a codebase at the time of a
release of the software. The concept of the merge was also introduced;
reconciling conflicting changes made to a file manually.

Git and Mercurial

The next generation of version control systems are distributed or
decentralized systems, in which working copies of the code themselves contain
a complete history of the project, and are hence not reliant on a central
server to contribute to the project. In the open source, Unix-friendly
environment, the standout systems are Git and Mercurial, with their client
programs git and hg.

For both of these systems, the concept of communicating changesets is done with
the operations push, pull and merge; changes from one repository are
accepted by another. This decentralized system allows for a very complex but
tightly controlled ecosystem of development; Git was originally developed by
Linus Torvalds to provide an open-source DVCS capable of managing development
for the Linux kernel.

Both Git and Mercurial differ from CVS and Subversion in that the basic unit
for their operations is not changesets, but complete files (blobs) saved using
compression. This makes finding the log history of a single file or the
differences between two revisions of a file slightly more expensive, but the
output of git log --patch still retains the familiar unified diff output
for each revision, some forty years after diff was first being used:

The two systems have considerable overlap in functionality and even in command
set, and the question of which to use provokes considerable debate. The
best introductions I’ve seen to each are Pro Git by Scott Chacon, and Hg
Init by Joel Spolsky.

Conclusion

This is the last post in the Unix as IDE series; I’ve tried to offer a
rapid survey of the basic tools available just within a shell on Linux for all
of the basic functionality afforded by professional IDEs. At points I’ve had to
be not quite as thorough as I’d like in explaining certain features, but to
those unfamiliar to development on Linux machines this will all have hopefully
given some idea of how comprehensive a development environment the humble shell
can be, and all with free, highly mature, and standard software tools.