Wednesday, June 26, 2013

vim plugin

Recently for no good reason I decided to build a vim plugin. Being a C++ enthusiast the target will obviously be some sort of compiled binary plugin. Scripting vim is kind of tricky- this article is going to go from start to finish in how to build the vim plugin stub. Hopefully it will help someone else since the documentation on the world wide internets can be skimpy when dealing with this topic; the reason it's skimpy is that it just works.

The first step is to write a small program that's in a library:

#include <iostream>
#include <dlfcn.h>

extern "C" 
{

const int libexp95plugin_load(const char* libname)
{
    return (long) dlopen(libname, RTLD_LAZY);
}

const char* libexp95plugin_call(const char* context)
{
    std::cout << "HELLO WORLD!" << std::endl;
    return "Hello";
}

}

Step by step:

#include <iostream>

extern "C"
{

I see this all the time in code- this tells the compiler that the function names included should have 'C' linkage. This allows any other base program (such as vim) a universal way to load this library and also know how to call it.

const char* libexp95plugin_call(const char* context)
{
    std::cout << "HELLO WORLD!" << std::endl;
    return "Hello";
}

}

The final portion of the code is self explanatory. To build this library (I put the code above into a file called exp95.cpp), I use a tool called premake4. Honestly, you could just as easily use straight command line to do it too, but premake4 is easier to read:

solution "exp95"
configurations { "Debug", "Release" }

project "exp95plugin"
kind "SharedLib"
language "C++"
files { "exp95.cpp" }
buildoptions { "-fPIC" }
linkoptions { "-fPIC" }


That's all. The -fPIC flag is the most important since it enables Placement Independent Code. After the plugin is build (inside of libexp95plugin.so), to the following:

> cd ~
> cd .vim
> vim exp95.vim

Inside of exp95.vim add the following:

function! Exp95Function()
    call libcall( "absolute-path-to-libexp95plugin.so", "libexp95plugin_call", "SOMETHING")
endfunction

command Exp95 call Exp95Function()

That's all! I got hung up for awhile because I didn't use the "call" keyword in front of libcall. The lesson there is that if you are not storing the return value from a function call in vim, you must use the call keyword in front. Otherwise you'd get the error:

E492: Not an editor command: ^Ilibcall( ... )

Yeah, not so good. To invoke your new command, all you have to do is fire up vim and execute. From within vim:

:Exp95

Your hello message should pop right up!





No comments:

Post a Comment