I'm writing a Clojure CLI application, and I would like to allow a command to be given to it which would drop people into the clojure.main REPL.
Does anyone know how I can go about doing that? My effort have not been fruitful.
EDIT:
My problem is made worse by the fact that my CLI takes piped input. Here's an example of what I'd like to work:
(ns playground.core
(:gen-class))
(defn -main
[& args]
(with-open [r (io/reader *in*)]
(doseq [line (line-seq r)]
(println line)))
;; Drop in repl after having read the input and printed its content)
I then call this as such:
cat ./somefile.txt | lein trampoline run
You can just call clojure.main/repl
from your program and it will start listening to stdin and 'repl'ying to it ;-) at that point the repl will start
user> (clojure.main/repl)
then i type into the terminal (+ 1 2 3)
user=> 6
user=>
so i had a repl in a repl going there to simulate the case where the person using your program types the start repl command.
for making a human friendly repl experience the rebl-readline project adds a lot to calling clojure.main/repl:
(rebel-readline.core/with-line-reader
(rebel-readline.clojure.line-reader/create
(rebel-readline.clojure.service.local/create))
(clojure.main/repl
:prompt (fn []) ;; prompt is handled by line-reader
:read (rebel-readline.clojure.main/create-repl-read)))
You may want to (or perhaps you already have) a thing that breaks out of the with-open
once some special line is sent. once this is received completely exit the line-seq
and with-open
. then start the repl so it can grab the input file-descriptor.
cat
takes a special argument -
(just a dash nothing else with spaces on either side) that says "stop here and read from the keyboard until Crtl-d is pressed"
~ » cat a-file - | cat hello im a line from a file hello hello
in this example it read a line from a file, passed it to the cat command (replace with your program), then it read the word hello
from the keyboard and printed it as well (so you see it twice on the screen)
Maybe starting a headless REPL and have two separate steps might work for you?
Step 1
Launch a headless REPL, wait for it to start
$ lein repl :headless :host 0.0.0.0 :port 9000
nREPL server started on port 9000 on host 0.0.0.0 - nrepl://0.0.0.0:9000
Step 2
In another shell, send the commands to the REPL using your command:
$ cat test.txt
(def hello "Hello world!")
$ cat test.txt | lein repl :connect 0.0.0.0:9000
Connecting to nREPL at 0.0.0.0:9000
REPL-y 0.3.7, nREPL 0.2.12
Clojure 1.8.0
OpenJDK 64-Bit Server VM 1.8.0_181-8u181-b13-1ubuntu0.18.04.1-b13
Docs: (doc function-name-here)
(find-doc "part-of-name-here")
Source: (source function-name-here)
Javadoc: (javadoc java-object-or-class-here)
Exit: Control+D or (exit) or (quit)
Results: Stored in vars *1, *2, *3, an exception in *e
pipetest.core=> (def hello "Hello world!")
#'pipetest.core/hello
pipetest.core=> Bye for now!
Step 3
You can connect to the REPL, continue after the state changes from the previous step, but now you can use it to interact.
$ lein repl :connect 0.0.0.0:9000
Connecting to nREPL at 0.0.0.0:9000
REPL-y 0.3.7, nREPL 0.2.12
Clojure 1.8.0
OpenJDK 64-Bit Server VM 1.8.0_181-8u181-b13-1ubuntu0.18.04.1-b13
Docs: (doc function-name-here)
(find-doc "part-of-name-here")
Source: (source function-name-here)
Javadoc: (javadoc java-object-or-class-here)
Exit: Control+D or (exit) or (quit)
Results: Stored in vars *1, *2, *3, an exception in *e
pipetest.core=> (str hello "!!!")
"Hello world!!!!"
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.