【问题标题】:Evaluate Leiningen Code In Project在项目中评估 Leiningen 代码
【发布时间】:2015-11-16 10:52:31
【问题描述】:

我有一个 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])

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

【问题讨论】:

    标签: clojure classpath leiningen


    【解决方案1】:

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

    【讨论】:

    • 我的意思是包含项目。我的问题真的是:如何编辑项目图,使其在目标项目中包含插件代码。
    • 哦,我认为您的主要问题是缺少项目参数。如果您真的想更新项目地图,那么基于 swank 项目的“项目环境中的评估”中有一个示例。 tl,博士:使用project/merge-profiles。但可能您不需要编辑项目,而只是不要在init 第三个参数中定义别名。我会用我认为应该有效的方法更新答案
    • 您好,您的解决方案仍然不起作用,因为 my-plugin.my-ns 不在目标项目的类路径中。我需要一个办法把它弄进去。一种解决方案是将插件代码分离到一个单独的 leiningen 项目中,但这似乎有点杂乱无章。
    【解决方案2】:

    我们需要一种方法将源代码从我们的插件中获取到目标项目的类路径中。一种方法是将 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)))))
    

    然后我们可能会更新项目映射以在项目中包含我们的“临时”源文件夹和评估

    (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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-11-05
      • 2013-02-01
      • 1970-01-01
      • 2011-01-17
      • 1970-01-01
      • 1970-01-01
      • 2012-10-25
      • 2014-07-26
      相关资源
      最近更新 更多