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

如何从Clojure命令行应用程序中放入repl?,clojure,command-line-interface,read-eval-print-loop,Clojure,Command Line Interface,Read Eval Print Loop,我正在编写一个Clojure CLI应用程序,我想允许向它发出一个命令,该命令会将用户放入Clojure.main REPL 有人知道我该怎么做吗?我的努力没有取得成果 编辑: 我的CLI采用管道输入这一事实使我的问题更加严重。下面是我想从事的工作的一个例子: (ns playground.core (:gen-class)) (defn -main [& args] (with-open [r (io/reader *in*)] (doseq [line (lin

我正在编写一个Clojure CLI应用程序,我想允许向它发出一个命令,该命令会将用户放入Clojure.main REPL

有人知道我该怎么做吗?我的努力没有取得成果

编辑:

我的CLI采用管道输入这一事实使我的问题更加严重。下面是我想从事的工作的一个例子:

(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)
那么我就这样称呼它:

cat ./somefile.txt | lein trampoline run

您只需从程序中调用
clojure.main/repl
,它就会开始收听stdin并对其进行“回复”;-)此时,repl将启动

user> (clojure.main/repl)
然后我在终端中键入
(+1 2 3)

因此,我在repl中设置了一个repl,用于模拟使用您的程序的人键入start repl命令的情况

为了获得人性化的repl体验,该项目为调用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)))

由于您的计划基本上分为两个阶段

  • 永远从标准输入读取内容,或直到标准输入永久关闭
  • 一旦程序死机或标准输入不再可用,以先发生的为准,从标准输入读取更多数据
  • 您可能想要(或者您已经拥有)一个东西,一旦发送了某个专线,它就会用open从
    中突破出来。收到后,完全退出
    行序列
    并打开
    。然后启动repl,以便它可以获取输入文件描述符。
    
    一旦您使程序获得repl的输入,您的管道问题就可以在封闭的shell命令中得到解决
    cat
    采用一个特殊参数
    -
    (只有一个破折号,两侧没有空格),该参数表示“停在此处,从键盘读取,直到按下Crtl-d”


    在本例中,它从一个文件中读取一行,将其传递给cat命令(替换为您的程序),然后从键盘读取单词
    hello
    ,并将其打印出来(因此您在屏幕上会看到两次)

    可能启动一个headless REPL并执行两个单独的步骤可能对您有效

    步骤1

    启动一个无头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
    
    步骤2

    在另一个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!
    
    步骤3

    您可以连接到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!!!!"
    

    我不认为这是重复的,因为这个问题没有解决repl不需要是程序输入的第一个消费者,也不需要在程序启动时启动的问题。是的,我的问题是特别试图得到一个答案,其中repl不是第一个启动的。程序首先启动,接受in的输入,执行更多操作,然后需要转换为REPL。CLI REPL在stdin和stdout上运行,管道也一样。也许您应该将nREPL/socket REPL与pREPL一起使用并远程连接?这将使您的stdin为文件管道打开,但允许您远程连接REPL。或者,你可以阅读stdin,然后像其他答案中提到的那样开始一个REPL。@Olical我可以走这条路,但问题是,当我在REPL中输入stdin时,我已经完成了。但似乎是stdin导致REPL在启动后立即关闭。我将输入导入Clojure CLI。例如
    cat somefile.txt | lein蹦床跑
    。在这种情况下,调用
    clojure.main/repl
    或使用rebel readline都不起作用。如果我不使用管道输入,只运行
    lein trampoline run
    ,它确实可以工作。知道我如何在管道输入的情况下进入repl吗?@DidierA。添加了关于绕过管道输入的内容,以及关于将其从读取行中分离出来的一些意见
    $ 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!
    
    $ 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!!!!"