bhauman / rebel-readline

Terminal readline library for Clojure dialects
Eclipse Public License 1.0
684 stars 37 forks source link

Ctrl+C quits repl (SIGINT signal) #180

Open dundalek opened 6 years ago

dundalek commented 6 years ago

When a longer running form is evaluated (e.g. (Thread/sleep 10000) or (doseq [i (range 1e6)] (println i))) and Ctrl+C is pressed then repl quits. Expected behavior is to interrupt current evaluation and make the repl available for input again.

Version used: 0.1.4 (running with clojure -Sdeps "{:deps {com.bhauman/rebel-readline {:mvn/version \"0.1.4\"}}}" -m rebel-readline.main).

For comparison I tried clj main repl which also handles it incorrectly, but lein repl handles it correctly as expected.

bhauman commented 6 years ago

Hey, it's undertandable that you'd want this feature.

But Rebel readline is mainly an api to wrap around a repl and it derives its properties from the REPL its wrapping.

The Clojure main repl (the one you were using) doesn't have a notion of interruptible eval, but nREPL does, and thats why you get this behavior in lein repl.

I haven't implemented nREPL support for rebel-readline yet. When I get to it, it will be a fairly straightforward task but I've already spent most of this year writing open source only so I'm due for a break. ;)

On Sat, Sep 29, 2018 at 4:47 AM Jakub Dundalek notifications@github.com wrote:

When a longer running form is evaluated (e.g. (Thread/sleep 10000) or (doseq [i (range 1e6)] (println i))) and Ctrl+C is pressed then repl quits. Expected behavior is to interrupt current evaluation and make the repl available for input again.

Version used: 0.1.4 (running with clojure -Sdeps "{:deps {com.bhauman/rebel-readline {:mvn/version \"0.1.4\"}}}" -m rebel-readline.main).

For comparison I tried clj main repl which also handles it incorrectly, but lein repl handles it correctly as expected.

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/bhauman/rebel-readline/issues/180, or mute the thread https://github.com/notifications/unsubscribe-auth/AAAKQDtQlL77I4fvBQCt1lkt2jTKZQt0ks5ufzOVgaJpZM4XAaF8 .

dundalek commented 6 years ago

Sounds cool to me, thank you so much for your OSS work. Not only for this project but also the other ones! Huge respect!

I am working on a unix shell project based on Clojure and am able to have so much leverage thanks to rebel. If rebel would not exist I would not even consider Java proper port. It is almost complete, the last thing it needs is above mentioned ctrl+c handling, otherwise a bash-like shell is sort of useless.

I've now quickly looked into lein, which seems to hook into java signal handling. Another option might be to use jline3 apis, which seem to have some sort of native signal handling.

I think the solution should be able to be made upstream. So if I am able to come up with something PR-worthy I will open one up for your consideration.

dundalek commented 6 years ago

Hi Bruce,

I did more digging into how lein and reply do things and was able to come up with a solution:

(defn handle-sigint-form []
  `(let [thread# (Thread/currentThread)]
     (clojure.repl/set-break-handler! (fn [signal#] (.stop thread#)))))

Then can pass following eval option to clojure.main/repl:

  :eval (fn [form] (eval `(do ~(handle-sigint-form) ~form)))

I hope this helps. I am able to customize rebel like that so it is solved for my project.

metametadata commented 5 years ago

I've wrapped up the aforementioned workaround into the script: https://gist.github.com/metametadata/c11044a5d490eac7158ae535c10ce45c.