简体   繁体   中英

How to drop into a repl from within a Clojure command line application?

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)))


Since your program has essentially two phases,

  1. read things from standard input forever or until standard input is permanently closed.
  2. once the program is dead or standard input is no longer available, whichever happens first read more from standard input.

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.


once you make the program get input to the repl, your piping issue can be solved in the enclosing shell command. 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM