Vim. Other Editors Don't Do Such Things

I’ve been making some progress on my Anjuta-Vim Integration project, infact, I even have screenshots :-) 1. But that’s very deceptive, notice the (null) ((null)) on the window title. Essentially, I’ve written an AnjutaPlugin that implements the necessary interfaces to “open files”. Currently all my interface implementation functions are returning NULL’s or 0’s (which can cause unpredictable segfaults and  memdumps), and that brings me to the real challenge of my GSoC project.

Talking to Vim / Containing Vim

The biggest problem with embedding Vim as an alternate editor is, as my mentor (not officially, but he’s helped me a lot), Sebastien Granjoux (seb) told me (vimzard):

** < vimzard > ** ...especially since i would like vim to send commands
to anjuta (like debug, make,etc.)
** < seb > ** I think you don't need that vim send make or debug command
to anjuta.
** < seb > ** The other editor plugins don't do such thing. ...
** < seb > ** Yes, I have understood but again other editor don't do it
like this. They cannot open a file by themselves.

The other editors being Scintilla and GtkSourceview, both of which are widgets. Vim is an full fledged application (Scintilla is just a simple application with a Scintilla widget). There is no libvim, there is no VimWidget (though I wish there was). Vim comes chock full of features, and it’s hard to make sure they don’t mash around existing frameworks.

Incidently, I’m also going to have problems with the fact that a single Vim instance opens multiple buffers… I shudder to think about the issues Emacs would give me (besides pinky injuries). Back to the problem at hand, I can’t implement those interfaces until I talk to Vim. Unfortunately, Vim does not have DBus bindings, nor does it emit any signals, which makes it hard to deal with.  And this has led me to a very special juncture in my (arguably short) life as a coder.

Hackery Invariance Point: The total hackery of a project is invariant across possible solutions

Point in case, consider the following problem: Anjuta must issue commands to Vim, vim must reply, and send signals to Anjuta.

1. Vim –remote2 : Vim supports a commandline feature that allows you to send queries/commands to a running vim session (which acts like server). This gives you complete freedom to send Vim any key commands you would like to, as well as request for the values of certain expressions. E.g.:
gvim --server-name GVIM;
# Will first enter insert mode (i), and enter 'abcd' into
# the buffer opened by the first command.
vim --server-name GVIM --remote-send iabcd;
# Will get the value of the setting "tabstop" of the current vim
# buffer.
gvim --server-name GVIM --remote-expr "&tabstop"; 

Hackery: You would have to spawn a vim process (albeit a lighter version) every time you wanted to ask it something. And the entire thing is implemented using X11’s window properties, which sounds hacky at first glance (but I found out that it’s normal)3. And that solves just half the problem, of talking from Anjuta to Vim. To send back signals, unfortunatlely, Vim uses a pseudo terminal, where it sends all its stdout output. Therefore, I can’t simply listen on the pipe from which I spawned vim in Anjuta 4. I couldn’t find a single way to cajol (g)vim to send output to the stdout, neither through command line options, nor through options. Every 1/2 hour, I’d find  some more documentation, but in the end it came to no avail. If anyone has a clue how to do this, please please tell me.

Grand Hackery Masterpiece: To work around this, I was thinking of creating a pipe (thanks to seb), and I’d run :!echo "anjuta:foo_bar" > pipe_no (runs the command in a terminal), and listen on the pipe using GIO.

1. Implement that same X11 code myself, to save myself all the spawning. The rest of it is the same.

Hackery: I’d have to reimplement the code (but with a reduction factor of using of using GDK and Glib), and do all that grand hackery nonsense.

1. The Netbeans Protocal. A gross misnomer, the netbeans protocol is a manner of communication to a Vim instance using sockets. Yes, this is IPC using sockets. It is sad that in an age of DBus I must choose between pipes and sockets for IPC… The netbeans system looks a bit hacky through and through, but it’s worked successfully for a number of projects already. How can I most pompously say that it’s useless for Anjuta? Well, more than half of the functions under IAnjutaEditor and IAnjutaDocument interfaces that I must implement can’t be done using this very limited protocol. There are a handful of functions that are exposed, and another handful of functions that “are yet to be implemented”. Oddly, vim does not extend the same flexibility it did with the vim –remote through the sockets interface, which is a pity.

Hackery: The whole sockets interface itself. And the loops I’d have to go through to implement 1/10th of the required interface functions.

1. Spend a week or two and implement DBus bindings for Vim. This has been proposed by someone else as well5, but I doubt I have the time to take out a week on this. DBus would solve everyone’s problems though.

Hackery: The thread mentioned6 says that the main loop is very much obfuscated, and unfriendly to DBus. Besides, touching the Vim source guarantees hackery.

I personally favour (1.5), despite it’s hackery. Any suggestions / advice ?

1. Screenshots of the VimPlugin

2. This is part of the X11 ICCCM (Inter Client Communications Convention Manual). The key function is XChangeProperty. This is wrapped by GDK as well.

3. The implemenation of my plugin works by plugging in a GVim instance into a GtkSocket. Vim is extremely friendly here, as it has a command line option --socketid which creates GtkPlug using the socket id.

4. A thread on the Vim ML’s, proposing a DBus interface.

5. A thread on the Vim ML’s, proposing a DBus interface.