Mavenなどを使うと、プロジェクトを用意して…とけっこう面倒な感じがするのですが、スクリプトとして実行が可能な言語なら、依存関係とかを解決しつつ使えると嬉しい!というのがあると思います。
Groovy、Scalaでは、一応そういう仕組みがあります。
Groovy(Grape)
http://groovy.codehaus.org/Grape
Scala(sbt-scalas)
http://www.scala-sbt.org/release/docs/Detailed-Topics/Scripts
で、ClojureといえばLeiningenですが、これを使って同じようなことをする方法を探してみました。
選択肢としては、以下のいずれかのLeiningenプラグインを使うとよいみたいです。
lein-exec
https://github.com/kumarshantanu/lein-exec
lein-oneoff
https://github.com/mtyaka/lein-oneoff
今回は、lein-execを使ってみることにしました。
インストールなどなど
$HOME/.lein/profiles.cljに、以下の内容を記述します。
{:user {:plugins [[lein-exec "0.3.1"]]}}
上位のバージョンを取るようにしたい場合は、こんな感じ。
{:user {:plugins [[lein-exec "[0.3.1,)"]]}}
ファイルが存在しない場合は、ファイル自体を作成してください。
あとは、これを利用した実行対象となるスクリプトを作成します。まずは、以下のようなuseを加えます。
(use '[leiningen.exec :only (deps)])
続いて、依存関係の定義をdeps関数を使って定義していきます。
(deps '[[ring/ring-core "1.0.0"] [ring/ring-jetty-adapter "1.0.0"]]) (deps '[[foo/bar "1.2.3"]] :repositories {"myrepo" "http://mycorp.com/repositories/"})
リポジトリの追加が必要な場合は、:repositoriesキーワードを使用します。
実行してみる
それでは、動作確認用のスクリプトを作成します。今回はこんなのを用意しました。
exec-script.clj
(use '[leiningen.exec :only (deps)]) (deps '[[org.apache.commons/commons-lang3 "3.1"] [org.seasar.container/s2-framework "2.4.46"]] :repositories {"The Seasar Foundation Maven2 Repository" "http://maven.seasar.org/maven2"}) (ns exec.core (:import (org.apache.commons.lang3 StringUtils) (org.seasar.framework.util StringUtil))) (println (StringUtils/join '("Hello" "Leiningen!!"), ", ")) (println (StringUtil/equals "str" "str")) (println (str "Hello " (if (> (count *command-line-args*) 1) (second *command-line-args*) "World")))
実行は、「lein exec スクリプト名」で行います。
$ lein exec exec-script.clj Retrieving lein-exec/lein-exec/0.3.1/lein-exec-0.3.1.pom from clojars Retrieving lein-exec/lein-exec/0.3.1/lein-exec-0.3.1.jar from clojars Hello, Leiningen!! true Hello World
初回は、プラグインのダウンロードが行われます。
2回目以降は、ダウンロードは発生しません。
$ lein exec exec-script.clj Clojure Hello, Leiningen!! true Hello Clojure
起動引数は、「*command-line-args*」で受けてくださいね。
なお、スクリプトの実行に使用されるClojureのバージョンですが、どうもLeiningen(というか、leiningen-core?)が依存しているClojureのバージョンに引っ張られるようです。deps関数を使った依存関係の定義にClojureを加えても、華麗に無視されます。
その他、leinコマンドのexecタスクとして実行するのではなく、lein-execとしてスクリプトを用意する方法も紹介されていますが、「lein exec」のラッパーにすぎないので割愛…。
lein-exec
https://raw.github.com/kumarshantanu/lein-exec/master/lein-exec
導入したい場合は、ダウンロードしてPATHを通して実行権限を付与してって感じですね。
eval
小ネタ。「-e」スイッチで、eval的なことができます。
$ lein exec -e '(println "Hello World")' Hello World
プロジェクト内のスクリプトを実行する
もう少しユニークな機能として、プロジェクト内に定義したスクリプトを実行することもできます。
まずは、適当なプロジェクトを作成。
$ lein new app exec-project Generating a project called exec-project based on the 'app' template.
project.cljを修正。
(defproject exec-project "0.1.0-SNAPSHOT" :description "FIXME: write description" :url "http://example.com/FIXME" :license {:name "Eclipse Public License" :url "http://www.eclipse.org/legal/epl-v10.html"} :dependencies [[org.clojure/clojure "1.5.1"] [org.apache.commons/commons-lang3 "3.1"] [org.seasar.container/s2-framework "2.4.46"]] :main exec-project.core :repositories {"The Seasar Foundation Maven2 Repository" "http://maven.seasar.org/maven2"})
前のスクリプトを、ちょっと名前空間だけ変えてsrcディレクトリに放り込みます。
src/exec_project/script.clj
(ns exec-project.script (:import (org.apache.commons.lang3 StringUtils) (org.seasar.framework.util StringUtil))) (println (StringUtils/join '("Hello" "Leiningen!!"), ", ")) (println (StringUtil/equals "str" "str")) (println (str "Hello " (if (> (count *command-line-args*) 1) (second *command-line-args*) "World")))
このスクリプトを、「lein exec -p」で実行します。
$ lein exec -p src/exec_project/script.clj Clojure Hello, Leiningen!! true Hello Clojure
project.cljで定義した依存関係を解決しつつ、スクリプトを実行することができました。
ちなみに、これをスクリプト化したlein-exec-pというものも存在します。
lein-exec-p
https://raw.github.com/kumarshantanu/lein-exec/master/lein-exec-p
やっていることは同じなので、こちらも割愛。
こんな感じで。