Relisp
Synopsis
Emacs is great. So is Ruby. This purpose of this library is to:
-
call Ruby from Emacs
-
call Elisp from Ruby
-
manipulate Emacs without using Elisp to some extent (Ruby wrappers around some Elisp functions and objects)
-
reduce the number of blog entries titled “Is Ruby an acceptable lisp?” and flame wars under the title “ruby vs. lisp vs. scheme vs. haskell vs. …”
Install
[sudo] gem install relisp
Then the library is installed, and you can call elisp from ruby. But if you want to call ruby from emacs (and you do, right?) you need to go into the src directory and copy relisp.el and/or relisp.elc to your elisp folder (probably ~/.elisp). Then you might want to add the line (require 'relisp) to your emacs initialization file (probably ~/.emacs').
If you don’t know where to find the files for this gem, run the command gem env gemdir. Or you can download the tarball for this gem and get the files there.
Usage
The stuff below is all in the examples directory if you want to try running it.
Emacs calling Ruby
With a generic slave
Start up a ruby process:
(relisp-start-slave)
Then make calls to ruby with ruby_eval:
(ruby-eval "1 + 2 + 3")
=> 6
(ruby-eval "'ruby string'.reverse")
=> "gnirts ybur"
(type-of (ruby-eval "{:name => 'john'}"))
=> hash-table
If you need to use an elisp variable or expression in the middle of the command, relisp-to-ruby will provide a string that, when evaluated by ruby, is equal to the original elisp object. For example:
(setq vect [1 2 3 4 5 6])
(ruby-eval (concat (relisp-to-ruby vect) ".class"))
=> Relisp::Vector
(ruby-eval (concat (relisp-to-ruby vect) ".kind_of?(Array)"))
=> t
(ruby-eval (concat (relisp-to-ruby vect) ".reverse"))
=> [6 5 4 3 2 1]
(type-of (ruby-eval (concat (relisp-to-ruby vect) ".reverse")))
=> vector
Note that the data types/classes are correct in both languages. The results are converted–it’s not just strings getting passed back and forth.
Elisp can ask Ruby to evaluate code which in turn will call elisp:
(ruby-eval "elisp_eval('(+ 1 2)')")
(ruby-eval "elisp_eval('(ruby-eval \"1 + 2\")')")
The state of the slave persists from one call to the next:
(ruby-eval "a = 5")
(ruby-eval "a + 1")
=> 6
Specifying a slave file
The ruby slave file should look something like this:
require 'relisp'
slave = Relisp::RubySlave.new
def sample_ruby_method
Relisp::Buffer.new("ruby-created-buffer")
end
slave.start
The call to slave.start should probably be the last line of the file since it starts an infinite loop. The elisp code just needs to specify the ruby slave file before calling relisp-start-slave:
(setq relisp-ruby-slave-path "ruby_slave")
(relisp-start-slave)
(ruby-eval "sample_ruby_method")
For debugging and curiousity, all of the messages between emacs and ruby are recorded in the buffer *Relisp*.
Ruby calling Emacs
The Emacs process is managed by Relisp::ElispSlave.
require 'relisp'
emacs = Relisp::ElispSlave.new
Calls are made calling elisp_eval and elisp_exec on the ElispSlave object.
emacs.elisp_eval "(+ 1 2)"
=> 3
emacs.elisp_eval '(concat "two " "words")'
=> "two words"
emacs.elisp_eval( "(setq new-var 23)")
emacs.elisp_eval( "(+ 1 new-var)")
=> 24
The usual method_missing magic provides access to elisp functions:
emacs.concat("two", " words") # (concat "two" "words")
emacs.*(5,2) # (* 5 2)
emacs.create_file_buffer("blah.txt") # (create-file-buffer "blah.txt")
Emacs editing types have proxy classes with extensive functionality:
buffer = Relisp::Buffer.new("ruby-created-buffer")
=> #<Relisp::Buffer:0xb7c4784c>
buffer.name
=> "ruby-created-buffer"
To print debug information showing messages between ruby and emacs, use the ElispSlave#debugging method:
emacs.debugging do
emacs.elisp_eval "(+ 1 2)"
end
To Do
-
fix Windows bug(s)
Author
Copyright
Copyright © 2009 <[email protected]>. Licensed under the GNU General Public License.
Relisp is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
Relisp is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program. If not, see <www.gnu.org/licenses/>.