Vim. Other Editors Don’t Do Such Things

1 06 2008

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,

Problem: Getting Vim and Anjuta talking to each other. Anjuta must issue commands to Vim, vim must reply, and send signals to Anjuta.

Solution #1: Vim –remote[2] : 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;
$> vim –server-name GVIM –remote-send iabcd;
Will first enter insert mode (i), and enter ‘abcd’ into the buffer opened by the
first command.

$> gvim –server-name GVIM –remote-expr “&tabstop”;
Will get the value of the setting “tabstop” of the current vim buffer.

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.

Solution #1.5: 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.

Solution #2: 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.

Solution #3: Spend a week or two and implement DBus bindings for Vim. This has been proposed by someone else as well[5], but I doubt I have the time to take out a week on this. DBus would solve everyone’s problems though.

Hackery: The  thread mentioned [5] 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 ?

References
[1] Screenshots of the VimPlugin
[2] vim –remote
[3 This is part of the X11 ICCCM (Inter Client Communications Convention
Manual). The key function is XChangeProperty. This is wrapped by GDK as well.
[4] 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.
[5] A thread on the Vim ML’s, proposing a DBus interface.


Actions

Information

13 responses

1 06 2008
veets

If Anjuta had a vim plugin, then it might be good for something! I really like Anjuta but I am not going to give up vi!!! Glad someone is taking the time to think of a way to get this done. applaud!

1 06 2008
veets

Right after I clicked submit… I recalled a project with similar hopes…

http://www.opensky.ca/~jdhildeb/software/gnome-vim/

vim bonobo for evolution… that I wish was working to!

1 06 2008
Jens Geiregat

You might know this already, but there’s a MonoDevelop-vim integration. Check out http://ankitjain.org/blog/2007/06/30/integrating-vim-with-monodevelop/

1 06 2008
ac

Just write a vim plugin which talk whatever IPC protocol you like, dbus, pipe, X selection…

I would imagine a 20 line of vim python plugin work give you full control of vim from the outside. Then you load the vim python plugin whenever you start a vim plugin from inside the Anjuta.

You known you can write plugins from vim in perl, python, ruby, tcl or vim builtin script.

1 06 2008
asdf
1 06 2008
arunchaganty

@Jens: Actually, I did not know that, Thanks for the link. That uses the netbeans protocol too.
@ac: That sound’s like a great idea! I can’t believe I didn’t think of that. Thanks.

1 06 2008
hario

PIDA (http://pida.co.uk/) is an IDE able of embedding GVim. It is done in Python+PyGTK so the ideas present in the code should be easily reusable. I don’t know how PIDA interacts with GVim, but reading source comments my guess is that it does something like your solution #1.5

It would be very nice to see GVim embedded in Anjuta in a stable fashion. Hope the information helps. 😛

1 06 2008
arunchaganty

@hario: Yeah I’ve looked at PIDA (it inspired me to use GtkSockets actually). It doesn’t actually request much out of gvim yet. It uses #1 wherever it needs to though.

1 06 2008
Ryan Paul

I did some experimentation a while back where I used XEmbed to put a GVim instance in a GTK+ application. I used Vim’s internal Python scripting interface and the Python D-Bus bindings to implement a control API with D-Bus so I could have buffers listed in a GTK+ TreeView. I suspect that you could use a similar approach.

2 06 2008
Alban

Good to see you are working on this. I would prefer the solution #3, but it needs a lot of time…

4 06 2008
arunchaganty

@Ryan Paul: Well, that’s what I’m doing now. Thanks for confirming that it’ll work 🙂

@Alban: Yeah, perhaps after my SoC I can try to hook DBus into vim rather than put a layer over it with a python plugin…

21 08 2009
Tom Fetherston

I looking to do a similar integration of Gvim and Leo, a python based outline using literate editor. Did this get further work? I be interested in seeing what you used.

Tom

21 08 2009
Arun Chaganty

Hey,
I have not been able to find much time to continue work on my plugin, but I’d be more than happy to help you. The code is pretty well modularlised and (I think) well commented. The vim parts are all good, only the Anjuta side is a bit out of date due to lots of code change in Anjuta.

The approach is similar to that followed by PiDA, i.e. using a GtkSocket and GtkPlug. I used X11’s ICCCM to communicate with Vim (this is exactly how the vim –remote-expr commands work) as the DBus interface was often a bit buggy (especially when the user was typing something and a method had to be called). The DBus interface is currently used only for signals from the editor.

Looking at LEO, this looks like it should be easily implementable. I would highly recommend looking at PiDA because it was written in Python and does exactly this.

PiDA: http://pida.co.uk/

All the best, and feel free to drop me a line if you’d like any help!

Cheers,

Arun Tejasvi Chaganty
http://arun.chagantys.org/

Leave a comment