Skip to content

Commit

Permalink
Connect to repl socket inside interactive task.
Browse files Browse the repository at this point in the history
  • Loading branch information
technomancy committed Nov 20, 2010
1 parent 2bda774 commit 7f96f5d
Showing 1 changed file with 49 additions and 13 deletions.
62 changes: 49 additions & 13 deletions src/leiningen/interactive.clj
@@ -1,21 +1,57 @@
(ns leiningen.interactive
(:require [clojure.string :as string])
(:use [leiningen.core :only [apply-task]]))
(:use [leiningen.core :only [apply-task]]
[leiningen.repl :only [repl-server repl-socket-on
copy-out-loop poll-repl-connection]]
[leiningen.compile :only [eval-in-project]]))

(def welcome "Welcome to Leiningen. Type help for a list of commands.")

(defn not-found [& _]
(println "That's not a task. Use \"help\" to list all tasks."))
(println "That's not a task. Use help to list all tasks."))

(defn- eval-client-loop [reader writer buffer eof]
(let [len (.read reader buffer)
output (String. buffer)]
(when-not (or (neg? len) (re-find (re-pattern eof) output))
(.write *out* buffer 0 len)
(flush)
(Thread/sleep 100)
(recur reader writer buffer eof))))

(defn eval-in-repl [connect project form & [args]]
(let [[reader writer] (connect)
eof (str (java.util.UUID/randomUUID))]
(.write writer (format "%s\n:%s\n" (pr-str form) eof))
(.flush writer)
(try (eval-client-loop reader writer (make-array Character/TYPE 1000) eof)
0
(catch Exception e
(println (.getMessage e))
(.printStackTrace e)
1)
(finally
(.close reader)
(.close writer)))))

(defn task-repl [project]
(flush)
(print "lein> ")
(flush)
(let [input (.readLine *in*)]
(when (and input (not= input "exit"))
(let [[task-name & args] (string/split input #"\s")]
(apply-task task-name project args not-found)
(recur project)))))

(defn interactive
"Enter an interactive shell for calling tasks without relaunching new JVMs."
[project]
(println "Welcome to Leiningen. Type \"help\" for a list of commands.")
(loop []
(flush)
(print "lein> ")
(flush)
;; TODO: integrate with tab-completion in jLine
(let [input (.readLine *in*)]
(when (and input (not= input "exit"))
(let [[task-name & args] (string/split input #"\s")]
(apply-task task-name project args not-found)
(recur))))))
(let [[port host] (repl-socket-on project)]
(future
(eval-in-project project `(do ~(repl-server project host port
:prompt '(constantly ""))
~welcome)))
(let [connect #(poll-repl-connection port 0 vector)]
(binding [eval-in-project (partial eval-in-repl connect)]
(task-repl project)))))

0 comments on commit 7f96f5d

Please sign in to comment.