我有多个(3k +)脚本用clojure编写(每个脚本不依赖于任何其他脚本)。
这些脚本是用Clojure 1.2编写的,我想用旧的contrib库来分析它们。到目前为止,我只是为了clojure.contrib\.[0-9a-z\.\-]*
的出现而简单地使用文件,但是我还希望从我的脚本中使用这些contrib库中找到特定的函数。
有没有比正则表达式更好的方法呢?
任何允许我解析字符串(包含Clojure程序)并轻松提取依赖项的clojure库?
答案 0 :(得分:1)
使用core.analyze您可能会越来越近。
这是我的一个老例子,它将为您提供每个项目文件的所有顶级功能/元素。
您应该能够轻松修改parse-clojure-file
函数来分析函数树以检查调用。
使用leiningen.core.project
和analyze.core
设置依赖关系:
(ns dependencies.project
(:require
[leiningen.core.project :as project]
[analyze.core :as analyze]
[clojure.java.io])
(:import
(java.io PushbackReader)))
从磁盘读取文件并处理
(defn parse-clojure-file
"Reads a clojure source file from disk
and returns a sequence of hashes of
first level objects
{:type defn :name parse-clojure-file}
{:type ns :name clandombg.project}
..."
[file]
(let [forms (analyze.core/forms-seq
(java.io.PushbackReader. (clojure.java.io/reader file)))]
(reduce (fn [file-obj form]
(conj file-obj {:type (first form) :name (second form)}))
[] forms)))
所有项目文件的树,返回的哈希映射由相对路径索引:
(defn traverse-source-tree
"Traverses a source directory recursively and returns
a collection of files keyed by relative-path and content
the file first level objects"
[directory]
(let [files (file-seq (clojure.java.io/file directory))
clj-files (filter #(re-matches #".+\.clj$|.+\.cljs$" (.getName %)) files)]
(reduce (fn [project file]
(let [relative-path (clojure.string/replace (.getPath file) directory "")]
(assoc project
relative-path
(merge
(parse-clojure-file file)
{:relative-path relative-path}))))
{} clj-files)))
切入点:
(defn parse-project
"Reads a project file from disk and parses its source
files, returns a clojure encoded string"
[project-path]
(let [project (project/read project-path)]
(reduce #(assoc %1 %2 (traverse-source-tree %2))
{}
(:source-paths project))))
调用:
(parse-project "path/to/project.clj")