Simon Rydell
Physics, programming
and the rest


Vim completion is a breeze

Writing a small python plugin for vim with autocompletion!

I recently had a vim plugin prompt me for some text that would then be executed by the underlying shell. It didn't support autocompletion and it wasn't until then I realized my incessant mashing of tab when normally typing in the terminal. Life really shouldn't be this hard.

Autocompletion in vim is easy, you provide vim with a list of keywords to be searched through every time you hit tab. Let's build a small plugin that executes a python script with autocompletion for the python files in the current working directory. To execute a shell command from vim, type :!shell-command from normal mode. So in our case, this would be something like :!python example.py. Simple enough, let's translate this to a function and call it from a command!

function! s:RunPythonFile(filename)
    " Function arguments are accessed by a: and string concatenation is done by .
    " Weird, right?
    let command = '!python ' . a:filename
    execute(command)
endfunction

" -nargs=*    Any number of arguments allowed, separated by whitespace (run python interpreter if no arguments)
" <q-args>    Quotes the input converting it into a string
command! -nargs=* RunPython :call s:RunPythonFile(<q-args>)

After either painstakingly typing this into your command-line mode (accessed by :) or pasting it into your .vimrc you can run a python script by typing :RunPython example.py.

The easiest way to add autocompletion is to give the command the flag -complete=completeOptions, where completeOptions is whatever list you want to provide (:help -complete and marvel). We want to provide our own so we need to add -complete=custom,s:GetPythonFiles. Let's define the function s:GetPythonFiles that will create our list.

function! s:GetPythonFiles(ArgLead, CmdLine, CursorPos)
    " A list of all python files in the current directory
    return system('ls *.py')
endfunction

Simple as that! Now we have a working autocompletion!

alt text
Working autocompletion!

There are many things to improve here that I leave as a challenge. For instance, can we pass more arguments to the RunPython command (:help a:000, :help join)? Can we extend the completion list to every python file on the filesystem (:help globpath), or on a remote machine? And so on.

Hope you found this useful, and if you make a plugin, please save my fingers and add autocompletion.

Also, here is all the code for the lazy masses:

function! s:GetPythonFiles(ArgLead, CmdLine, CursorPos)
    return system("ls *.py")
endfunction

function! s:RunPythonFile(filename)
    let command = '!python ' . a:filename
    execute(command)
endfunction

" -nargs=*    Any number of arguments allowed, separated by whitespace (python interpreter without arguments)
" <q-args>    Quotes the input converting it into a string
command! -nargs=* -complete=custom,s:GetPythonFiles RunPython :call s:RunPythonFile(<q-args>)