Vim & Python: Making yourself at home
You might look at Python code every day, but what is the lens through which you view code? It's your text editor. This article was written for Python Magazine and was first in a series on Python development environments. Here, we look at how Vim users can boost their productivity by having Vim tell you as much as possible about your program, while you're writing it.
As developers, we spend a majority of our productive day interacting with code. How we interact with this code is often the last thing on our mind. Taking a step back and looking at our daily habits can often yield surprising results in productivity, and is a healthy thing to do once in a while.
The focus of this article will be on getting comfortable with Vim, but learning your tools is a worthwhile pursuit regardless of your editor-of-choice. Furthermore, we will assume you have a fair understanding of Vim. You should know how to move about, edit text, and such. If you don't know how to do this but are interested in Vim, please consult the Vim web page for a tutorial.
Customization Basics
The central place for editing your vim configuration is your
.vimrc
file, located in your home directory or folder. This
serves as the primary file for changes to your vim configuration. The
typical syntax for setting a variable is:
set ruler " Text after a double-quote is a comment set tabstop=4
As you can see, some arguments are binary (on/off) and some take more complicated arguments.
Also in your home folder is a folder called .vim
. In it, there are
several sub-directories which hold plugins for Vim. The basic
directory structure is similar to that shown below.
.vim |____after # for overrides to system-level vim |____autoload # a directory for some plugins |____colors # custom colorthemes |____doc # documentation |____ftplugin # custom filetype plugins |____indent # custom indentation overrides |____plugin # plugin installation directory |____syntax # custom syntax coloring files
Note that the directories listed above won't necessarily exist on your machine already. Furthermore, they might not all be necessary for you, depending on which plugins you decide to install down the road.
There are a few options which will make editing python code much easier. To get you started, I've included those below.
set tabstop=4 set shiftwidth=4 set expandtab
The first option, tabstop
, tells vim how many spaces a tab should
take up. The default is 8, which seems much too wide. (Note, however,
that this setting will get you into trouble if you load Python scripts
from people whose editors use a mix of tabs and spaces, since, to
Python, a tab always equals eight spaces; that is why it is best to
never include actual tabs in your own programs!) The shiftwidth
option controls the depth of autoindentation, which we'll keep the
same width as tabstop
. Lastly, expandtab
(which doesn't take an
argument), converts all tabs to spaces.
Vim also offers extensibility through a language called Vim Script. Many people have made some pretty amazing plugins in it. There are two methods of installing vim plugins: zip files, and vimballs.
To install a vimball, download it to a directory, and open it in
vim. From there, type :so %
which means to "source" the current
file ("%").
wget -O snippets_emu.vba http://www.vim.org/scripts/download_script.php?src_id=8450
vim snippets_emu.vba
:so %
The other method of installing vim plugins are through a zip file. To
install the zip file, cd into your .vim
folder, and extract
it. Things should just go into their right places.
cd ~/.vim wget -O nerd_tree.zip http://www.vim.org/scripts/download_script.php?src_id=10767 unzip nerd_tree.zip rm nerd_tree.zip
To find plugins not discussed in this article, you should head over to http://www.vim.org/ where there are a ton of useful (and some not-so-useful) plugins for your browsing pleasure. Now that we have an understanding of how some things work, let's check out some source code.
Viewing Source Code
Here are some of my default .vimrc
settings::
syntax on set list listchars=tab:▷⋅,trail:⋅,nbsp:⋅ set statusline=%F%m%r%h%w\ [TYPE=%Y\ %{&ff}]\ \ [%l/%L\ (%p%%) filetype plugin indent on au FileType py set autoindent au FileType py set smartindent au FileType py set textwidth=79 " PEP-8 Friendly
If you open a Python file, you'll quickly notice that you lack syntax
highlighting. To fix this, type :syntax on
. This will tell Vim that
you want syntax highlighting. I find it a good idea to keep this on
always, so it goes in the .vimrc
. I also find it helpful to turn on
invisibles. While Vim doesn't expressly have an option for this, its
easily fixed with a bit of Unicode. The listchars will turn tabs into
large triangles, and trailing spaces and blank lines with spaces into
small bullets. Along with visible whitespace, you can turn on rather
nice indentation with the above au
commands. These are automatically
run for a given file type, usually identified by extension. In our
case, this is the py
extension. This offers a handy way to have
different settings for different kinds of file. The indentation
commands above do a few complimentary, but different things. An
autoindent
will indent the next line when you start a new line;
smartindent
will also indent after things like a colon (for if
or
for
statements) and such.
You can also get a fair amount more metadata about the file your
editing with a better statusline. This statusline will tell you the
filename, type of file that Vim thinks it is, what sort of line
endings are used, as well as your vertical position in the file. If
Vim has guessed incorrectly at the type of file you're editing you can
easily rectify this with the ft (aka filetype) option. :set
ft=python
will turn the buffer to Python mode. Now that we have a
decent looking single file, lets take a step back and see how Vim can
help us within the scope of a larger project.
Browsing Source Code
" NERD_tree config let NERDTreeChDirMode=2 let NERDTreeIgnore=['\.vim$', '\~$', '\.pyc$', '\.swp$'] let NERDTreeSortOrder=['^__\.py$', '\/$', '*', '\.swp$', '\~$'] let NERDTreeShowBookmarks=1 map <F3> :NERDTreeToggle<CR> " Syntax for multiple tag files are " set tags=/my/dir1/tags, /my/dir2/tags set tags=tags;$HOME/.vim/tags/ " TagList Plugin Configuration let Tlist_Ctags_Cmd='/usr/local/bin/ctags' let Tlist_GainFocus_On_ToggleOpen = 1 let Tlist_Close_On_Select = 1 let Tlist_Use_Right_Window = 1 let Tlist_File_Fold_Auto_Close = 1 map <F7> :TlistToggle<CR> " Viewport Controls " ie moving between split panes map <silent>,h <C-w>h map <silent>,j <C-w>j map <silent>,k <C-w>k map <silent>,l <C-w>l
One of the biggest parts about editing speed and efficiency is being able to get from one file to another quickly. There are two plugins which do an amazing job at this very task. Check out the above code to see how I have configured these plugins in my own home directory.
NERDTree is a fantastic file browser that slots nicely into vim when you need it, and hides from view when its not in use. It offers the ability to bookmark folders for separating out projects. It is quite reminiscent of TextMate's project drawer, but works just as well without a GUI. In my config, I've bound NERDTree to F3. From the opened pane, you can open files in split view, normal view, or as a preview. There are an array of options available for things such as sorting, ignoring and so on, but you can consult the documentation for a more in-depth look.
Another great plugin for navigating around your source-code is
Taglist. This interacts with ctags to provide a class browser of your
current code. You need to point it to a ctags binary as well as giving
it an idea of where to find your tags files. I have it set to look in
the current directory, followed by a tags sub-directory of my .vim
folder. I have the pane toggle bound to F7. This setup allows me to
have NERDTree on the left with my file list, and TagList open on the
right with an overview of my current file. You can press F1 for a list
of commands available in that buffer. The most immediately useful will
be u
which will update the taglist for the current file.
Now that we have a few panes to operate in, we can make some
improvements on how we work with them. Instead of the old C-w left
,
I found it much easier to bind the viewport changing keys to ,left
which seems to be a bit easier to type for me.
Writing Source Code
We've gotten a python file looking respectable, and can now easily navigate our project structure. Let's actually improve the speed we get work done. The two tips here work on the principle that the less you have to type, the faster you'll be.
The first plugin is SnippetsEmu. SnippetsEmu operates much like
TextMate's bundle system, offering a few shortcuts for a variety of
different languages. It helps expand something like super
to:
def {method}(self, *args, **kwargs): { put my cursor here when done } super({class}, self).{method}(*args, **kwargs)
which is a personal favorite of mine. Once you are inside of a class body, type "super", and press tab, then the substitute text above will suddenly display and the "method" section will be highlighted. As you type, your text gets written into both places. You fill in the class variable, and it will place your cursor in the proper place for editing the function.
Another fantastic feature that Vim offers is its own auto-completion. This can be invoked with Control-n and Control-p after typing a portion of a word. This does a match against the currently open buffers for a string matching the same format. This is surprisingly useful, even with how simple it is. For Python-specific tab completion, there are a few libraries attempting to offer Eclipse or VisualStudio style intellisense. The best of these seems to be Pydiction. It has extensive documentation on the download page, which should get you up and going in no time.
Handy Random Extras
map ,p :Lodgeit<CR> " pastes selection / file to paste.pocoo.org " VCS Command Configs let mapleader = ","
As you can see, a large majority of some of the power of vim comes from its extensive plugin community. On that front, there are a few other helpful plugins which, while they don't necessarily fit anywhere, offer a lot of great situational value.
The first of these is Lodgeit. Lodgeit is a pastebin service run by
http://pocoo.org which offers a vim plugin. By highlighting a section of
source code and typing, as I have it bound, ,p
, you will paste the
contents of the selection to the pastebin web site, and a link will be
placed in your clipboard. This is quite helpful for trading snippets
of code with coworkers, or when getting help on a particular debugging
problem.
From the same folks who wrote NERDTree, NerdCommenter allows for easy commenting of large regions of text. The language support they have for the various commenting features is staggering!
Another great plugin for Vim is VCS Command. This allows you to interact with your source code management tool directly from the editor. The more time you spend in your editor, the fewer context switches you make. This means you're less likely to notice the little email icon when you're alt-tabbing, and you're less likely to get side-tracked by that latest inflammatory article on HackerNews. The more time you spend in your editor, the more time you can spend getting work done.
Lastly, pyflakes is an absolutely essential plugin for Vim. As with any linter, it catches trivial mistakes that, cumulatively, can add up to a sizable amount of time lost. Furthermore, it helps encourage consistency, standards, and clean code.
Getting More Help
While this article should give you a basic understanding of how to get
plugins and install them, and which plugins might be useful, there's
still quite a bit more to explore, such as writing your own
plugin. There are several resources for help. #vim
on
irc.freenode.org
is a pretty excellent resource for Vim-related
things. There is also quite extensive documentation built into Vim
itself. If you're curious about what a particular option does, type
:h <option>
- for instance, :h undolevels
for more information
about what it does and how to configure it.
As programmers, we live in our editors every day. Any time you spend learning more about your tools will be paid ten-fold with productivity gains as you work with them on a daily basis. One great way to see what else you may want in your editor, is to give another editor a shot. Its really hard to know what's out there, until you've seen it yourself. If you'd like to browse through my vim files, you can view them on github.