How can I get readline/rlwrap-like functionality when using clojure.main/repl?

1.1k views Asked by At

How can I get readline-like (or rlwrap-like) functionality from my REPL when I use the repl function from clojure.main?

The background to this is that I'm utilizing and customizing the break function from The Joy of Clojure, First Edition. I'm using it from inside the lein repl REPL. When my "breakpoint" kicks in, the readline-like functionality of Leiningen's REPL is gone, which is kind of inconvenient. My muscle memory makes me hit followed quickly by Enter. Before I can stop myself, I've got this in my terminal:

debug=> ^[[A
CompilerException java.lang.RuntimeException: Unable to resolve symbol: in this context, compiling:(/tmp/form-init13211381000659590518.clj:1:1) 

And now my REPL is stuck and I have to kill the terminal or the process to get out. I'd like very much if I could either get readline working in this second-level REPL or at least prevent this common issue from derailing my debug sessions.

3

There are 3 answers

0
Ivan Grishaev On

I'm not sure the rlwrap utility would help there, because the inner REPL is held by the outer one. So the input is being controlled by Java code, not the rlwrap tool.

You are causing an exception since you input a wrong value. I remember, the clojure.main/repl function might take an additional argument to handle exceptions. Probably, you could handle it somehow and just print a string "wrong input value" instead. Take a look at the documentation for REPL.

Also, you may implement your own REPL for debugging. Long ago, I used to write some kind of it, here what I've got:

(defn repl []
  (let [input (read)]
    (if (= input 'q)
      nil
      (do
        (try
          (let [result (eval input)]
            (println result))
          (catch Exception e
            (println e)))
        (recur)))))

That function just prompts for a proper Clojure expression in an endless loop, evaluates it and prints the result. In case of a wrong input, it prints the error and carries on. To leave the REPL, input q.

Example:

(repl)
(+ 1 2) ;; 2
fsdf8 9_fsd ;; prints a stack trace
q ;; returns nil and exit
1
pankajdoharey On

You should use rebel readline, a new repl for clojure developed by bhauman the same guy who brought is figwheel.

https://github.com/bhauman/rebel-readline

It has rlwrap features, syntax highlighting and multi line code editing all in the terminal.

0
ben author On

Try Emacs with Cider as your repl. When you (break) you'll be bumped out of the Cider repl and into the Emacs Minibuffer, where your standard emacs editing shortcuts (upon which readline is modeled) continue to apply.