Today David R. MacIver pinged me in #scala and asked "headius: Presumably you guys have spent quite a lot of time trying to make things like system("vim") work correctly in JRuby and failing? i.e. I'm probably wasting my time to attempt similar?"
My first answer was "yes", since there's no direct way to exec a program like vim (which wants a real terminal) and have it work on the JVM. The JVM's process launching gives the newly-spawned processes the child side of piped streams, which you then have to manually pump (which is what we do in JRuby's system, backtick, and exec methods). Under these circumstances, vim may start up, but it's certainly not functional.
But then I got to thinking...if you were doing this in C, you'd fork+exec and all would be happy. But we can't fork+exec on the JVM..OR CAN WE?
As you should know by now, JRuby ships with FFI, a library that allows you to bind any arbitrary C function in Ruby code. So getting fork+exec to work was a simple matter of writing a little Ruby code:
attach_function :my_exec, :execl, [:string, :string, :varargs], :int
attach_function :fork, , :int
vim1 = '/usr/bin/vim'
vim2 = 'vim'
if Exec.fork == 0
Exec.my_exec vim1, vim2, :pointer, nil
Running that with JRuby (I tried master, David tried 1.3.0RC1, and 1.2.0 works too) brings up a full-screen vim session, just like you'd expect, and it all just works. No other JVM language can do this so quickly and easily.
We'll probably try to generalize this into an optional library JRubyists can load (require 'jruby/real_exec' or similar) and perhaps add fork and exec to jna-posix so that the other JVM languages can have sweet, sweet process launching too.