Learn Vimscript the Hard Way


We've worked a lot with variables so far, but we haven't talked about aggregates at all yet! Vim has two main aggregate types, and we'll look at the first now: lists.

Vimscript lists are ordered, heterogeneous collections of elements. Run the following command:

:echo ['foo', 3, 'bar']

Vim displays the list. Lists can of course be nested. Run the following command:

:echo ['foo', [3, 'bar']]

Vim happily displays the list.


Vimscript lists are zero-indexed, and you can get at the elements in the usual way. Run this command:

:echo [0, [1, 2]][1]

Vim displays [1, 2]. You can also index from the end of the list, much like Python. Try this command:

:echo [0, [1, 2]][-2]

Vim displays 0. The index -1 refers to the last element in the list, -2 is the second-to-last, and so on.


Vim lists can also be sliced. This will look familiar to Python programmers, but it does not always act the same way! Run this command:

:echo ['a', 'b', 'c', 'd', 'e'][0:2]

Vim displays ['a', 'b', 'c'] (elements 0, 1 and 2). You can safely exceed the upper bound as well. Try this command:

:echo ['a', 'b', 'c', 'd', 'e'][0:100000]

Vim simply displays the entire list.

Slice indexes can be negative. Try this command:

:echo ['a', 'b', 'c', 'd', 'e'][-2:-1]

Vim displays ['d', 'e'] (elements -2 and -1).

When slicing lists you can leave off the first index to mean "the beginning" and/or the last index to mean "the end". Run the following commands:

:echo ['a', 'b', 'c', 'd', 'e'][:1]
:echo ['a', 'b', 'c', 'd', 'e'][3:]

Vim displays ['a', 'b'] and ['d', 'e'].

Like Python, Vimscript allows you to index and slice strings too. Run the following command:

:echo "abcd"[0:2]

Vim displays abc. However, you can't use negative bare indices with strings. You can use negative indices when slicing strings though! Run the following command:

:echo "abcd"[-1] . "abcd"[-2:]

Vim displays cd (using a negative index silently resulted in an empty string).


You can combine Vim lists with +. Try this command:

:echo ['a', 'b'] + ['c']

Vim, unsurprisingly, displays ['a', 'b', 'c']. There's not much else to say here -- Vimscript lists are surprisingly sane compared to the rest of the language.

List Functions

Vim has a number of built-in functions for working with lists. Run these commands:

:let foo = ['a']
:call add(foo, 'b')
:echo foo

Vim mutates the list foo in-place to append 'b' and displays ['a', 'b']. Now run this command:

:echo len(foo)

Vim displays 2, the length of the list. Try these commands:

:echo get(foo, 0, 'default')
:echo get(foo, 100, 'default')

Vim displays a and default. The get function will get the item at the given index from the given list, or return the given default value if the index is out of range in the list.

Run this command:

:echo index(foo, 'b')
:echo index(foo, 'nope')

Vim displays 1 and -1. The index function returns the first index of the given item in the given list, or -1 if the item is not in the list.

Now run this command:

:echo join(foo)
:echo join(foo, '---')
:echo join([1, 2, 3], '')

Vim displays a b, a---b, and 123. join will join the items in the given list together into a string, separated by the given separator string (or a space if none is given), coercing each item to a string if necessary/possible.

Run the following commands:

:call reverse(foo)
:echo foo
:call reverse(foo)
:echo foo

Vim displays ['b', 'a'] and then ['a', 'b']. reverse reverses the given list in place.


Read :help List. All of it. Notice the capital L.

Read :help add().

Read :help len().

Read :help get().

Read :help index().

Read :help join().

Read :help reverse().

Skim :help functions to find some other list-related functions I haven't mentioned yet. Run :match Keyword /\clist/ to case-insensitively highlight the word list to make it easier to find what you're looking for.