在项目中评估Leiningen代码

时间:2015-08-22 16:11:32

标签: clojure classpath leiningen

我有一个lein插件,我需要在项目上下文中评估它的代码。我可以做这样的琐碎的事情

(leiningen.core.eval/eval-in-project project '(+ 1 2))

但是一旦我需要插件本身的代码

(leiningen.core.eval/eval-in-project 
  project
  '(my-ns/my-fn) 
  '(require '[my-plugin.my-ns :as my-ns])

它不在目标项目的加载路径上!如何编辑项目图以在项目中包含插件代码?

2 个答案:

答案 0 :(得分:0)

eval-in-project的第一个参数必须是项目图。第二个参数是要评估的表单,第三个参数是init表单" ,它在主表单"之前预先评估。在"Evaluation in project context"中,有一个指向how to avoid "the gilardi scenario"的帖子的链接,其定义为:

  

Gilardi场景是指您想要评估一些代码,这些代码既在新var中加载又在同一段代码中引用该var

您的代码中的问题是您在init表单中定义了一个别名,并希望它也在您的主代码中定义。

因此,您的代码可能类似于:

(defn my-plugin [project & opts]
  (leiningen.core.eval/eval-in-project 
    project
    '(my-plugin.my-ns/my-fn)
    '(require 'my-plugin.my-ns)))

答案 1 :(得分:0)

我们需要一种方法将源代码从我们的插件中获取到目标项目类路径中。一种方法是将源从leiningen类路径复制到目标项目中的源文件夹

(import java.io.File)
(import clojure.lang.RT)
(require '[clojure.java.io :as io])

(defn copy-src [& name-spaces]
   (doseq [name-space name-spaces]
     (let [
          resource (-> name-space
                       str
                       (.replace "." "/")
                       (.replace "-" "_")
                       (str ".clj"))
          on-classpath (RT/getResource (RT/baseLoader) resource)
          parent-dir (File.
                      (str 
                       ".cljsserve/"
                       (.substring resource 0 (.lastIndexOf resource "/"))))
          src-file (File. (str ".cljsserve/" resource))
          ]
      (.mkdirs parent-dir)
      (with-open [in (io/input-stream on-classpath)]
        (io/copy in src-file)))))

然后我们可以更新项目地图以包含我们的“temp”源文件夹和项目中的eval

(let [new-project (update-in project [:source-paths] concat [".cljsserve"])]
  (leiningen.core.eval/eval-in-project
   new-project
   '(cljs-server.web/-main)
   '(require 'cljs-server.web)))

另一种方法是将插件逻辑放在一个单独的依赖项中。在我的例子中,我创建了一个依赖项[cljs-server "1.0.0-SNAPSHOT"],然后将我的插件变成了一个包装器

(leiningen.core.eval/eval-in-project
 (update-in project [:dependencies] concat [[cljs-server "1.0.0-SNAPSHOT"]])
   `(cljs-server.web/-main ~port ~ssl? ~ssl-port ~src)
   '(require 'cljs-server.web)) ;cljs-server.web is defined within the dependency