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

3

13

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.

Netti answered 16/1, 2018 at 1:46 Comment(3)
Isn't rlwrap helping here?Starla
rlwrap works in the normal lein repl REPL, but not in the REPL within the REPL.Netti
lein repl brings its own readline stuff. So rlwrap is what i am using with non-lein-repl. So i'd assume that rlwrap alone (no-lein-outer-repl, inner-repl) would not care (unless the repl-in-a-repl messes with std(out|in). Yet i don't know how to disable the jreadline2 (?) support in lein.Starla
S
3

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.

Southeastwards answered 18/3, 2018 at 0:23 Comment(1)
rebel-readline looks great! Can you tell us more about it, like how to make the break function from The Joy of Clojure support readline?Cyrstalcyrus
G
1

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
Greyhen answered 17/1, 2018 at 7:57 Comment(0)
T
1

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.

Tachograph answered 19/1, 2018 at 0:2 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.