简体   繁体   English

如何从Clojure命令行应用程序中放入一个repl?

[英]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. 我正在编写一个Clojure CLI应用程序,我想允许给它一个命令,该命令会将人们放入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. 我的CLI接受管道输入,这使我的问题变得更糟。 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 您可以从程序中调用clojure.main/repl ,它将开始侦听stdin并对其进行“替换” ;-)此时,repl将开始

user> (clojure.main/repl)

then i type into the terminal (+ 1 2 3) 然后我输入终端(+ 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. 所以我在一个repl中有一个repl来模拟使用您程序的人键入start repl命令的情况。

for making a human friendly repl experience the rebl-readline project adds a lot to calling clojure.main/repl: 为使人类友好的repl体验, rebl-readline项目为调用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. 您可能需要(或者也许你已经有了),打破了的事情with-open一次一些特殊的线被发送。 once this is received completely exit the line-seq and with-open . 一旦收到它,就完全退出line-seqwith-open then start the repl so it can grab the input file-descriptor. 然后启动repl,以便它可以获取输入文件描述符。


once you make the program get input to the repl, your piping issue can be solved in the enclosing shell command. 一旦使程序获得了对repl的输入,就可以在封闭的shell命令中解决管道问题。 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带有一个特殊的参数- (两边的空格都没有破折号),上面写着“停在这里并从键盘上读取,直到按Crtl-d为止”

 ~ » 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) 在此示例中,它从文件中读取一行,并将其传递给cat命令(用程序替换),然后从键盘上读取单词hello并打印该行(因此您在屏幕上看到了两次)

Maybe starting a headless REPL and have two separate steps might work for you? 也许启动无头REPL并有两个单独的步骤可能对您有用?

Step 1 第1步

Launch a headless REPL, wait for it to start 启动无头REPL,等待其启动

$ 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 第2步

In another shell, send the commands to the REPL using your command: 在另一个shell中,使用您的命令将命令发送到REPL:

$ 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. 您可以连接到REPL,在状态从上一步更改之后继续操作,但是现在您可以使用它进行交互。

$ 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!!!!"

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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