Open Source Software Technical Articles

Want the Best of the Wazi Blogs Delivered Directly to your Inbox?

Subscribe to Wazi by Email

Your email:

Connect with Us!

Current Articles | RSS Feed RSS Feed

More Fun with Vimscript


In my last article, I looked at some of the ways in which you can use Vimscript, Vim's built-in scripting language, to set up that text editor to do exactly what you want it to. Apparently you liked what you saw and asked for more, so here are some additional tips and tricks to help you get Vim to jump through the hoops of your choice, including techniques for specifying ranges to work on, accepting user input, and debugging.

In the last article, we looked at functions that operate across the whole buffer, and functions that operate on a single line. At times you might want to have a function operate on a range of lines instead. There are two ways you can specify the range of lines over which a function will be applied when you call it. The first is simply to specify the range before the call to the function. This is what you do when using built-in functions like s///:


This function replaces "ping" with "pong" for every line in the file between line 1 and the line the cursor is currently on. If I wrote a function Capitalize to capitalize the first letter of every word, I could call it with a range in the same way:

:1,.call Capitalize()

What this method actually does is call the function once for every line. Depending on what the function does, the overhead associated with this approach can be fairly high. An alternative is to call the function only once, but deal with the range handling within the function itself. To do this, use the range modifier.

Here is the single-line word count function from the previous article, adapted to apply to a range:

fu! WordsThisLine() range
let words = 0
for linenum in range(a:firstline, a:lastline)
let words += len(split(getline(linenum)))
echo words
return words

The range modifier in the first line tells the function to expect a range – though the function will also work fine if called on a single line. The for loop uses two built-in variables, a:firstline and a:lastline, which correspond to the line numbers of the first and last lines of the range. The function loops over each line in the range and adds up the total words, before echoing them and returning them.

You can use this function either by specifying a range on the command line:

:6,9call WordsThisLine()

or by highlighting a range visually and then calling the function with :call WordsThisLine().

It's also possible to write a function that calculates its own range of lines to operate on from context. You can see how to make that work in this example, which shows a function that lines up assignment operators in program code.

Interacting With the Word Under the Cursor

Another neat trick is to do something with the word currently under the cursor. For example, you could look it up in dict:

fu! Dictionary()
let dict = "dict"
let wordUnderCursor = expand("<cword>")
let command = "!" . dict . " " . wordUnderCursor
execute command

expand("<cword>") is a useful Vimscript phrase that gets the word currently under the cursor. The rest of the function just sets up a command to call !dict word; it's good practice to use variables for the commands you want to run.

You could also look up documentation – for example perldoc – for the word by substituting this line:

let dict = "perldoc -f"

Or you could call a browser. That takes a few more lines to set up properly:

fu! Dictionary()
let browser = "/path/to/browser"
let urlFormat = ""
let wordUnderCursor = expand("")
let url = substitute(urlFormat, "WORD", wordUnderCursor, "g")
let command = "!" . browser . " " . url
execute command

The most obvious difference here is the need to set up a particular URL format. The substitute command is Vimscript's way of running s/WORD/wordUnderCursor/g on the string
urlFormat, which gives us the correct URL to pull up in the browser.

A few notes if you want to do this:

    1. To minimize debugging, check that the command you're using works on the command line before you try to set it up in Vim.

    1. If the path to the browser contains any spaces, you need to escape them with \\, as in "/path/to/app\\ with\\ space/".

    1. On a Mac, you can simplify the first line by just using let browser = "open", which will automatically call your default browser.

User Input

You might sometimes want user input to a script. For example, perhaps you regularly have to add a label to the start of several text lines, but the label varies. Try this script out:

fu! Label() range
call inputsave()
let label = input("Enter label: ")
call inputrestore()
for linenum in range(a:firstline, a:lastline)
let currentline = getline(linenum)
call setline(linenum, label . " " . currentline)

inputsave and inputrestore first save, then restore, the Vim typeahead buffer; this avoids any possible confusion when getting the user input. The rest of the code uses the range modifier; without it, if you called this function on a range, it would ask you to input the label for each line. getline returns a string with the contents of the given line, and setline sets the contents of the given line; here, with the input label, a space, and the existing line contents.


Vimscript has its own integrated debugger, which may come in handy if you're writing complex functions. To debug a script, call it like this:

:debug call WordsThisLine()

At the first line, Vim will pause, and you'll see a > symbol. At this point, you can quit altogether (q), continue without stopping until the next breakpoint (c), step through the next line of code (s), execute the next command (n), or finish running the script without breakpoints (f). Note that the difference between step and next is that next skips over function calls, while step goes into the function called.

Try stepping through a function to see the output you get; broadly, if nothing highlighted red shows up, you have no errors. If you do have errors, you'll get some information about them which should help you to identify the problem.

You can put breakpoints into your code to simplify debugging:

:breakadd func 5 WordsThisBuffer

This adds a breakpoint on line 5 in the given function (note that you don't use the parentheses at the end of the function name). If you now run :debug call WordsThisBuffer() and hit c, the runthrough will stop before executing line 5.

You can also add a breakpoint in a particular file that Vim sources, with:

:breakadd file 239 myfile.txt

Note that this will only work for a command executed while sourcing that file, but not for a function defined in that file. It's more useful when debugging your ~/.vimrc (for example when defining maps or shortcuts to call functions) than it is for debugging functions themselves.

Use breakdel func 5 WordsThisBuffer to delete a breakpoint, or :breakdel * to remove all breakpoints.

Using Other Languages

Finally, if you want to do something more complicated, or if you just have a strongly preferred other language, Vim also has interfaces to other scripting languages, including Perl, Python, and Ruby. These languages, obviously, are more powerful than Vimscript, but they also have problems when it comes to using them within Vim. Possibly the biggest one is that for debugging, you're on your own; Vim will call out once to evaluate your script, rather than being able to step through it line by line if need be. Check out some notes on debugging the Perl interpreter. Along with this goes the fact that there's very little integration between Vim and the external language, so you'll need to do a lot of work by hand. You may also have to fix your Vim installation to allow external language interfaces (the Debian default package includes the Perl interpreter by default; you can also check out notes on Ruby, and a list of Vim compile options). Despite these drawbacks, if you have very complex requirements, interfacing with a scripting language is something you can experiment with.

For most purposes, however, Vimscript, tailored as it is to work with Vim, is a great tool. It gives you huge scope for extending Vim to fit your needs.

This work is licensed under a Creative Commons Attribution 3.0 Unported License
Creative Commons License.

This work is licensed under a Creative Commons Attribution 3.0 Unported License
Creative Commons License.


This calculation adeptness even go bigger. If a woman buys a set of replica shoes accouterment again affairs a backpack which matches her accouterment actualization is a must. Here, a man who understands a woman's animosity would never footfall back. Certainly, this man would move added and advice her in affairs the a lot of capital handbag. Thanks to the high-street shops and the gucci replica websites that acquaint women accouterment as able-bodied as their handbags. The varieties of minibags that are begin in these places acquire to be appreciated. Currently, there is a acceleration in the bulk of women who are arcade duke accoutrements from websites. This befalling has acclimatized continued abandon to a abounding bulk of women to do arcade of their abundance handbags. When few women are accepting interviewed on this trend again they told that they adopt to buy handbags just by sitting afore their claimed computers. It saves a lot of their time and money. They are consistently in favor of the gucci replica offers and discounts which let them buy the best handbags at a lower price. Sometimes, it happens that women on affairs clothes from markets they do not acquisition the appropriate affectionate of ladies handbags which go alongside with their dress code. In this case, they acquire to seek for their adapted minibags in the assorted websites until they acquisition them. Thus, we acquire appear to apperceive that handbags bulk a lot to women dior replica. About the Author: Matthew Watson is a able biographer and anon autograph on online arcade industry accoutrement Kids wear, mens artist clothes, iphones accessories and sports accessories etc. While abounding alive women acquire to buy accurate artist handbags for themselves, they are able to do so because they are earning their own salary. For fashion-conscious girls who still depend on their parents for their allowance, however, artist handbags are apparently able-bodied aloft their bulk range. Instead, broad handbags are absolute for girls who still wants to attending good. Replica backpack broad artist handbags are accessible at low prices that even abounding girls are able to replica watches afford, afterwards compromising on looks.
Posted @ Saturday, September 13, 2014 2:27 AM by Heaity
Post Comment
Website (optional)

Allowed tags: <a> link, <b> bold, <i> italics