eval-in-repl.el: Consistent ESS-like eval interface for various REPLs in Emacs


What is eval-in-repl.el?

eval-in-repl.el allows a single keybinding "C-RET" to do REPL start up, current expression evaluation in REPL, and selected (if any) expression evaluation in REPL. It currently supports various lisp languages (Clojure, Common Lisp, Scheme, Racket, Hy, and Emacs Lisp), Python, shell, Ruby, SML, and OCaml utilizing pre-existing major and minor modes. eval-in-repl.el is available at the MELPA package repostiroy (http://melpa.org/#/eval-in-repl ). You can skip to the screen shot

Update on 2014-12-30: Added a screencast to the github repo
https://github.com/kaz-yos/eval-in-repl
Higher quality movie on YouTube
https://www.youtube.com/watch?v=gNBlF67e-0w&feature=youtu.be

Influence of ESS

I use emacs mainly for statistical analyses with R (http://www.r-project.org ). Emacs Speak Statistics (ESS; http://ess.r-project.org ) is my favorite emas package. Statistical analyses is inherently interactive. I constantly evaluate a small piece of code, check the results, and modify code or add code depending on the results. ESS makes REPL interaction easy by making "C-RET" (control+return) do everything. On the first invocation, "C-RET" will start up an R interpreter. From there on, "C-RET" will send code to the R interpreter. If there is no selection, the current line is sent. If there is a selection, the whole selected code is sent. The nice thing is that, the interpreter shows both the code evaluated and the evaluation result, so you can tell what resulted in what.

eval-in-repl.el

Emacs has major and minor modes to support programming in many languages. Most recent languages have REPLs. "C-x C-r" is usually bound to evaluate the selected region. But it may or may not work if no REPL buffer exist yet. Also evaulation may only show the result in the minibuffer transiently or show the result in the REPL buffer but without the code.

I wanted an ESS-like "C-RET"-rules-all system for other languages with REPLs. So I wrote eval-in-repl.el(http://melpa.org/#/eval-in-repl ). I'm an elisp beginner, so this package does not do anything fancy, but just wraps pre-existing major and minor modes with a very thin layer of functions to make them behave consistent. The mechanism is very simple, it just copy the current expression (lisps)/block (Python)/line, goes to the REPL, paste and execute, and come back, then move the cursor forward to the next expression/block/line. For installation, you can just use M-x list-packages. For configuration please refer to the github repo (http://melpa.org/#/eval-in-repl ). Just require the ones for the language you use.

eval-in-repl-ielm.el    for Emacs Lisp    (via ielm)
eval-in-repl-cider.el   for Clojure       (via cider.el)
eval-in-repl-slime.el   for SLIME         (via slime.el)
eval-in-repl-geiser.el  for Racket/Scheme (via geiser.el)
eval-in-repl-racket.el  for Racket        (via racket-mode.el)
eval-in-repl-scheme.el  for Scheme        (via scheme.el and cmuscheme.el)
eval-in-repl-python.el  for Python        (via python.el)
eval-in-repl-shell.el   for Shell         (via essh.el)
eval-in-repl-sml.el     for Standard ML   (via sml-mode.el and ess.el)
eval-in-repl-ruby.el    for Ruby          (via ruby-mode.el, inf-ruby.el, and ess.el)
eval-in-repl-ocaml.el   for OCaml         (via tuareg.el and ess.el)
eval-in-repl-hy.el      for Hy            (via hy-mode.el)

Using eval-in-repl.el for Clojure

The Clojure version utilizes the cider.el package. So you need to install it first if you have not done so. The following example was taken from the book Seven Web Frameworks in Seven Weeks, and is about SQLite interaction from Clojure REPL.

In the buffer on the right Clojure code exists, no REPL is running at this point. Do "C-RET" after the first S-expression

pic0250.png

Java VM start up takes some moments. A Clojure REPL appears on the left. cider.el tells us "Design is about pulling things apart. -Rich Hickey". Yes, Clojure is an opinionated language.

pic0305.png

Well, you need to move your cursor back to the code buffer (this is automatic for some other languages). Another "C-RET" will send the first top-level S-expression to the REPL. The S-expression evaluated to nil

pic0352.png

The cursor goes to the point right after the next S-expression after evaluation. So multiple "C-RET" will send S-expressions one at a time to the REPL.

pic0419.png

Let's select the symbol "project" and do "C-RET". Oops, it has not been defined, and gave error. For good or bad, the REPL has a state, so you need to evaluate the first thing first. At around 1/3 from the top in the next picture, the evaulation result of "project" is shown. It looks like a Clojure hash-map. With eval-in-repl, the REPL keeps track of both code and the result, so it can be used as a simple log.

pic0446.png

You can also select multiple top-level S-expressions and evaluate them all. Unfortunately, this is not possible with the Emacs Lisp version because IELM can only accept one S-expression at a time.

pic0512.png

Four SQL SELECT statements were sent, and 4 evaluation results returned.

pic0522.png

The behavior when there are multiple REPL buffers open for a single language, "C-RET" behavior is determined by the major/minor mode for that language, as eval-in-repl is just utilizing them internally.

Other languages supported (Python, Emacs Lisp, SML, shell as examples)

Here is a screenshot of the Python version, which uses the built-in python.el as a backend. To be honest, for Python, Emacs IPython Notebook2 (EIN2; https://github.com/millejoh/emacs-ipython-notebook ) may be a better interactive computing environment.

python.png

The Emacs Lisp version connects to IELM. For lisp languages, Hy (http://docs.hylang.org/en/latest/ ) support is the latest change.

elisp.png

The Geiser version can run GNU Guile and Racket.

racket.png

Via SLIME, various Common Lisp implementations are supported.

slime.png

The Standard ML version uses the sml-mode.el. I also added OCaml support recently.

sml.png

Interactive shell scripting is supported using essh.el as a backend. Well, there has been an effort to code Fibonacci in shell script...

shell.png

I'm still a novice elisper, and eval-in-repl.el is pretty rough. Your suggestions and contributions are appreciated.