Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Move exit & quit to the read side

The primary goal here is to make the client actually exit when
the nREPL server is in a separate process, which was broken.
This is also significantly safer, especially for scenarios
where you have a remote nREPL server that you *don't* actually
want to kill when you're just trying to bail out of your REPL
session. It seems counter-intuitive to have (exit) on the
client kill the server. We also now allow paren-less exit and
quit - perhaps a bit magical, but this will be nice for noobs.

The tradeoff is that this makes exit & quit pretty static.
Redefining them is still possible, but calling (exit) or
(quit) will quit, regardless of any new definitions on the
execution side.  That's less than ideal, but I prefer that
to the existing behavior.
  • Loading branch information...
commit cd4dcc196d1e93f489db2163a43c6d9550814eb1 1 parent c8ab98e
Colin Jones trptcolin authored
7 src/clj/reply/eval_modes/nrepl.clj
@@ -4,6 +4,7 @@
4 4 [clojure.tools.nrepl.misc :as nrepl.misc]
5 5 [clojure.tools.nrepl.server :as nrepl.server]
6 6 [clojure.tools.nrepl.transport :as nrepl.transport]
  7 + [reply.exit]
7 8 [reply.initialization]
8 9 [reply.reader.jline :as reader.jline]
9 10 [reply.signals :as signals]))
@@ -51,13 +52,13 @@
51 52 (println)
52 53 (prompt ns)
53 54 (flush)
54   - (let [done (Object.)
  55 + (let [eof (Object.)
55 56 read-result (try (read)
56 57 (catch Exception e
57 58 (if (= (.getMessage e) "EOF while reading")
58   - done
  59 + eof
59 60 (prn e))))]
60   - (if (= done read-result)
  61 + (if (reply.exit/done? eof read-result)
61 62 nil
62 63 (recur (execute-with-client
63 64 connection
6 src/clj/reply/eval_modes/standalone.clj
... ... @@ -1,6 +1,7 @@
1 1 (ns reply.eval-modes.standalone
2 2 (:require [reply.eval-modes.standalone.concurrency :as concurrency]
3 3 [reply.eval-state :as eval-state]
  4 + [reply.exit :as exit]
4 5 [reply.initialization :as initialization]
5 6 [reply.reader.jline :as reader.jline]
6 7 [reply.signals :as signals]))
@@ -8,7 +9,10 @@
8 9 (def reply-read
9 10 (fn [prompt exit]
10 11 (concurrency/starting-read!)
11   - (reader.jline/read prompt exit)))
  12 + (let [read-result (reader.jline/read prompt exit)]
  13 + (if (exit/done? exit read-result)
  14 + exit
  15 + read-result))))
12 16
13 17 (def reply-eval
14 18 (concurrency/act-in-future
15 src/clj/reply/exit.clj
... ... @@ -0,0 +1,15 @@
  1 +(ns reply.exit)
  2 +
  3 +(defn done-commands [eof]
  4 + #{eof 'quit 'exit '(quit) '(exit)})
  5 +
  6 +(defn done? [eof expression]
  7 + ((done-commands eof) expression))
  8 +
  9 +(defn exit
  10 + "Exits the REPL. This is fairly brutal, does (System/exit 0)."
  11 + []
  12 + (shutdown-agents)
  13 + (println "Bye for now!")
  14 + (System/exit 0))
  15 +
6 src/clj/reply/initialization.clj
@@ -61,13 +61,13 @@
61 61 (use '[clojure.pprint :only ~'[pp pprint]])
62 62
63 63 ~(export-definition 'reply.initialization/help)
64   - ~(export-definition 'reply.main/exit)
65   - (def ~'quit ~'exit)
  64 + ;~(export-definition 'reply.exit/exit)
  65 + ;(def ~'quit ~'exit)
66 66
67 67 (ns reply.exports)
68 68 ~(export-definition 'reply.initialization/intern-with-meta)
69 69
70   - (~'intern-with-meta '~'user '~'quit #'user/exit)
  70 + ;(~'intern-with-meta '~'user '~'quit #'user/exit)
71 71
72 72 (binding [*err* (java.io.StringWriter.)]
73 73 ~(export-definition 'reply.initialization/repl-defn)
12 src/clj/reply/main.clj
... ... @@ -1,6 +1,7 @@
1 1 (ns reply.main
2 2 (:require [reply.eval-modes.nrepl :as eval-modes.nrepl]
3 3 [reply.eval-modes.standalone :as eval-modes.standalone]
  4 + [reply.exit :as exit]
4 5 [reply.hacks.printing :as hacks.printing]
5 6 [reply.reader.jline :as reader.jline]
6 7 [reply.signals :as signals]
@@ -8,13 +9,6 @@
8 9 [clojure.repl]
9 10 [clj-stacktrace.repl]))
10 11
11   -(defn exit
12   - "Exits the REPL. This is fairly brutal, does (System/exit 0)."
13   - []
14   - (shutdown-agents)
15   - (println "Bye for now!")
16   - (System/exit 0))
17   -
18 12 (defn parse-args [args]
19 13 (loop [[option arg & more :as args] args
20 14 arg-map {:custom-init '()}]
@@ -52,7 +46,7 @@
52 46 clojure.repl/pst clj-stacktrace.repl/pst]
53 47 ~@body)
54 48 (catch Exception e# (clojure.repl/pst e#))
55   - (finally (exit))))
  49 + (finally (exit/exit))))
56 50
57 51 (defn set-prompt [options]
58 52 (when-let [prompt-form (:custom-prompt options)]
@@ -81,7 +75,7 @@ varargs list of arguments.
81 75 Available options: [:help :custom-init :skip-default-init :standalone :attach :port :color]
82 76 See -main for descriptions."
83 77 [options]
84   - (cond (:help options) (do (println (clojure.repl/doc -main)) (exit))
  78 + (cond (:help options) (do (println (clojure.repl/doc -main)) (exit/exit))
85 79 (:standalone options) (launch-standalone options)
86 80 :else (launch-nrepl options)))
87 81

0 comments on commit cd4dcc1

Please sign in to comment.
Something went wrong with that request. Please try again.