in Uncategorized

In Search of C# Omnicomplete for Vim

By day, I write in C#, mostly on a stock .NET install (version 4, as of this writing; I expect that the principles laid out here will transfer forward as the Vim ecosystem is fairly stable). I often find myself switching back and forth between Visual Studio 2010 (with VsVim) and gvim 7.3. Frankly, I should like to spend more time on the gvim side than I do. While a great deal of time and effort has gone into customizing my vimrc for .NET development, I often find myself switching back to VS in order to get the benefits of Intellisense when working with parts of the very hefty .NET Framework that I do not recall by memory.

Every so often, I do some fishing around for something useful to make my Vim Omnicomplete more productive. In this post, I will layout my newest attempt and analyze the findings. As such, this post may or may not be a tutorial on what you should do. In any event, it will be a science experiment in the plainest sense of the word.

First, the hypothesis. While checking out the Vim documentation on Omnicomplete, we see that the Omnicomplete function for C makes heavy use of an additional tag file, generated from the system headers
, and that this file is used in conjunction with what Omnicomplete understands about the C programming language to make a good guess as to what the programmer likely intends.

It should be possible then, with minimum fuss, to generate a similar tag file for C#. It may also be necessary to tweak the completion function parameters. We will look at that after we have checked the results of the tag file generation.

It turns out that Microsoft releases the .NET 4 Framework’s sourcecode under a reference-only license
. The initial vector of attack will be to download the reference code, and build a tag file from it (this seems well in keeping with the intent behind the license—if this is not so, I will gladly give up the excercise). The link with the relevant source is the first one (Product Name, “.NET” and version of “8.0” as of this writing). The source was placed under RefSrc in Documents.

After running:

ctags -R -f dotnet4tags *

in the RefSrc\Source\.Net\4.0\DEVDIV_TFS\Dev10\Releases\RTMRel directory, we got our first pass at a tag file. A little googling prompted the change to this

ctags -R -f dotnet4tags --exclude="bin" --extra=+fq --fields=+ianmzS --c#-kinds=cimnp *

Then, as the documentation says, we added the tag to our list of tag files to search:

set tags+=~/Documents/RefSrc/Source/.Net/4.0/DEVDIV_TFS/Dev10/Releases/RTMRel/dotnet4tags

When this is used in conjunction with tagfile completion (C-X C-]) the results are superior to any previous attempts, particularly in conjunction with the Taglist plugin

With this alone, we do not get any real contextual searching. For example, if we type something like:

File f = File.O

and then initiate the matching, we get practically any method that begins with an O regardless of whether or not said method is a member of the File class.

If we stop here, we still have a leg up over what we had before. We can navigate to .NET framework methods and fetch their signatures through the Taglist browser—but we would still like to do better.

The only reason the resulting tagfile is not here included, is that it is fairly large—not huge, but much too large to be a simple attachment to this post.

Write a Comment


To create code blocks or other preformatted text, indent by four spaces:

    This will be displayed in a monospaced font. The first four 
    spaces will be stripped off, but all other whitespace
    will be preserved.
    Markdown is turned off in code blocks:
     [This is not a link](

To create not a block, but an inline code span, use backticks:

Here is some inline `code`.

For more help see


  1. Really wondering if you, in fact, stopped there. My development situation is almost identical to yours. I’m using vim (not gVim) inside the gitbash shell, and would love to enable good .Net4 autocomplete. Will try now to follow your path to autocomplete, but did you ever get contextual searching enabled?

  2. Unfortunately, I never did get contextual searching to work. I’m thinking that someone (yeah, that could wind up being me) needs to write a specialized omnicomplete function. It would probably need to tie into a static analysis tool to try and figure out what would make sense. Ideally, it would be something from the Mono world to ensure platform independence.

  3. Developer who uses Mono here. I too would like nice, contextual search within my gvim, but like you said, it’d require some sort of static analysis tool.

    I think the tool you’re looking for is probably Mono.Cecil. I’ve had a glance at it myself, toying with the idea of trying to set something like that up, but it’s totally over my head. I’m just not that proficient, neither with vim nor static analyzers. I wouldn’t really even know where to begin.

    Thanks for the article, the tips on how to generate a ctag file of the corlibs made my work within vim considerably easier, even though the completion isn’t contextual.

  4. I have contextual intellisense working on my machine and have had this for quite a while but have sat on it due to a complete lack of time to finish this.

    My solution requires vim compiled with ruby support. I have a C# console app that acts as a server. On the vim side, I have a very small amount of vimscript that embeds a small amount of ruby that talks to the c# server.

    All the heavy lifting is done by NRefactory which is the engine that is shared between MonoDevelop and SharpDevelop.

    I get a list of completions along with method signatures etc. and also code documentation in the scratch window.

    My code is windows only right now, but it would only require very minor changes to get this up and running on Linux too.

    Ping me if you’d like to take a look and develop this further.

  5. I would also kill to get working vim omnicompletion in C#. It’s the only thing that I miss from VS.

  6. This is seriously awesome! Thanks for this. I tried a little bit to get it working in linux but the dependency on Microsoft.Build.dll will need to be worked around.