CLOVER🍀

That was when it all began.

Leiningen入門(再)

続いて、Leiningenへ。Leiningenの位置付け自体はあまり詳しくは書きませんが、JavaにおけるMaven、Scalaにおけるsbt、Groovy(だけじゃないけど)におけるGradleみたいなものと思っていただければ。

Leiningen
http://leiningen.org/

Githubでのプロジェクトは、こちら
https://github.com/technomancy/

今回使用するLeiningenのバージョンは、

2.3.1

です。

インストール

まずは、インストールから。パッケージマネージャを使ってインストールすることも可能なようですが、ここでは手動でインストールします。

インストール手順は、基本的に

http://leiningen.org/#install

に沿って行えば大丈夫です。

なお、Leiningenのインストール・実行にはClojureのランタイムは不要で、Javaが入っていればOKです。

Unix系OSの場合は、Bashスクリプトをダウンロード・配置します。

lein
https://raw.github.com/technomancy/leiningen/stable/bin/lein

Windowsの場合は、lein.bat
https://raw.github.com/technomancy/leiningen/stable/bin/lein.bat

以降では、Unix系OSを前提として書いていきます。

ダウンロードしたスクリプトを、適当な位置に配置します。自分は、以下の場所に置きました。

/usr/local/leiningen/lein

お好みで。

実行権限も付与して

$ sudo chmod 755 lein

「lein」が直接実行できるように、PATHを通しておいてください。

では、ヘルプでも見てみます。

$ lein help
Downloading Leiningen to /xxxxx/.lein/self-installs/leiningen-2.3.1-standalone.jar now...
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 10.3M  100 10.3M    0     0   217k      0  0:00:48  0:00:48 --:--:--  318k
Retrieving org/clojure/tools.nrepl/0.2.3/tools.nrepl-0.2.3.pom from central
Retrieving org/clojure/pom.contrib/0.1.2/pom.contrib-0.1.2.pom from central
Retrieving org/clojure/clojure/1.2.0/clojure-1.2.0.pom from central
Retrieving clojure-complete/clojure-complete/0.2.3/clojure-complete-0.2.3.pom from clojars
Retrieving org/clojure/clojure/1.2.0/clojure-1.2.0.jar from central
Retrieving org/clojure/tools.nrepl/0.2.3/tools.nrepl-0.2.3.jar from central
Retrieving clojure-complete/clojure-complete/0.2.3/clojure-complete-0.2.3.jar from clojars
Leiningen is a tool for working with Clojure projects.

Several tasks are available:
check               Check syntax and warn on reflection.
classpath           Print the classpath of the current project.
clean               Remove all files from project's target-path.
compile             Compile Clojure source into .class files.
deploy              Build and deploy jar to remote repository.
deps                Download all dependencies.
do                  Higher-order task to perform other tasks in succession.
help                Display a list of tasks or help for a given task.
install             Install the current project to the local repository.
jar                 Package up all the project's files into a jar file.
javac               Compile Java source files.
new                 Generate project scaffolding based on a template.
plugin              DEPRECATED. Please use the :user profile instead.
pom                 Write a pom.xml file to disk for Maven interoperability.
repl                Start a repl session either with the current project or standalone.
retest              Run only the test namespaces which failed last time around.
run                 Run a -main function with optional command-line arguments.
search              Search remote maven repositories for matching jars.
show-profiles       List all available profiles or display one if given an argument.
test                Run the project's tests.
trampoline          Run a task without nesting the project's JVM inside Leiningen's.
uberjar             Package up the project files and dependencies into a jar file.
update-in           Perform arbitrary transformations on your project map.
upgrade             Upgrade Leiningen to specified version or latest stable.
version             Print version for Leiningen and the current JVM.
with-profile        Apply the given task with the profile(s) specified.

Run `lein help $TASK` for details.

Global Options:
  -o             Run a task offline.
  -U             Run a task after forcing update of snapshots.
  -h, --help     Print this help.
  -v, --version  Print Leiningen's version.

See also: readme, faq, tutorial, news, sample, profiles, deploying, gpg, mixed-source, templates, and copying.

初回は、Leiningen本体の他いろいろダウンロードしてきます。

2回目以降はダウンロードは行われませんが…それでもちょっと重いです。

なお、こんな感じに何かコマンドを試してみずとも、

$ lein self-install

でもインストールを行うことができます。

これで、インストールは完了です。

プロキシ環境下の場合は、どうすればいいの?

お馴染みの環境変数で設定するようです。

HTTP Proxies
https://github.com/technomancy/leiningen/wiki/HTTP-Proxies

Unix系OSならhttp(s)_proxy

export http_proxy=http://username:password@proxy:port
export https_proxy=http://username:password@proxy:port

Windowsも同じ??

REPLを使ってみる

Leiningenを使うと、ClojureランタイムのインストールなしでREPLを使うことができます。先のエントリで、REPLを使うのにClojureのランタイムをインストールするのは微妙だと書いたのは、これが理由です。

以下のコマンドで、REPLが起動します。

$ lein repl

単にREPLを使うだけの場合は、プロジェクトは不要です。

表示は、こんな感じ。

nREPL server started on port 34074 on host 127.0.0.1
REPL-y 0.2.1
Clojure 1.5.1
    Docs: (doc function-name-here)
          (find-doc "part-of-name-here")
  Source: (source function-name-here)
 Javadoc: (javadoc java-object-or-class-here)
    Exit: Control+D or (exit) or (quit)

user=> 

終了方法とか、そのまま書いてますね…。

適当に実行。

user=> (println "Hello REPL")
Hello REPL
nil

終了は、Ctrl-D、(exit)、(quit)のいずれかで。

user=> (exit)
Bye for now!

なお、REPLのプロセスは、1つのマシンにつき1つな気がします。他のターミナルなどでREPLを起動しようとすると、ずーっと待ちになってしまったので…。

プロジェクトを作成してみる

Tutorialに沿って、プロジェクトを作成してみましょう。

Tutorial
https://github.com/technomancy/leiningen/blob/stable/doc/TUTORIAL.md

プロジェクトを作成するには、「new」タスクを使用します。今回は、利用するテンプレートを「app」、プロジェクトの名前を「my-app」としました。

$ lein new app my-app
Generating a project called my-app based on the 'app' template.

できあがったプロジェクトのディレクトリ構成は、こんな感じになります。

$ find my-app
my-app
my-app/src
my-app/src/my_app
my-app/src/my_app/core.clj
my-app/.gitignore
my-app/resources
my-app/doc
my-app/doc/intro.md
my-app/README.md
my-app/project.clj
my-app/LICENSE
my-app/test
my-app/test/my_app
my-app/test/my_app/core_test.clj

今回指定したテンプレートは「app」ですが、それ以外を使いたければ以下のURLにあるものを使えばよいとか。

https://clojars.org/search?q=lein-template

なお、テンプレート名を省略しても動作します。

$ lein new my-app
Generating a project called my-app based on the 'default' template.
To see other templates (app, lein plugin, etc), try `lein help new`.

「default」テンプレートを使ったよと言われていますが、構成自体は「app」テンプレートと同じみたいです。

では、とりあえず動かしてみましょうか。

$ cd my-app

project.cljは、こんな感じで生成されています。

(defproject my-app "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"]]
  :main my-app.core)

Clojure自体が依存関係として定義してあることと、:mainキーワードで、my-app.coreが指定されているところがポイントです。

メインのソース。

src/my_app/core.clj 
(ns my-app.core
  (:gen-class))

(defn -main
  "I don't do a whole lot ... yet."
  [& args]
  (println "Hello, World!"))

実行。

$ lein run
Retrieving org/clojure/clojure/1.5.1/clojure-1.5.1.pom from central
Retrieving org/clojure/clojure/1.5.1/clojure-1.5.1.jar from central
Hello, World!

依存ライブラリはClojure本体のみなので、これをダウンロードした後、実行されていますね。

では、ちょっと依存関係の定義を追加してみましょうか。

project.cljをちょこっと修正します。

(defproject my-app "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.seasar.container/s2-framework "2.4.46"]]
  :main my-app.core
  :repositories {"The Seasar Foundation Maven2 Repository" "http://maven.seasar.org/maven2"})

Seasar2への依存関係の追加と、リポジトリの設定を行いました。

src/my_app/core.cljも、Seasar2のクラスを使うように修正してみます。

(ns my-app.core
  (:gen-class)
  (:import (org.seasar.framework.util StringUtil)))

(defn -main
  "I don't do a whole lot ... yet."
  [& args]
  (println (StringUtil/replace "Hello, %WORD%!" "%WORD%"
                               (if (not (empty? args))
                                 (first args)
                                 "World"))))

実行。

$ lein run Clojure
Hello, Clojure!

依存関係やリポジトリの設定など、もうちょっと詳しいサンプルを見たい場合は、以下を参照するとよいみたいです。

sample.project.clj
https://github.com/technomancy/leiningen/blob/stable/sample.project.clj

また、依存ライブラリの取得は、通常以下から行うみたいです。

Clojars
https://clojars.org/

Maven Central
http://search.maven.org/

プロジェクト内でREPLを使用する

プロジェクトのディレクトリ内でREPLを起動すると、project.cljの内容などを適用しつつ、REPLを使うことができます。

$ pwd
/xxxxx/my-app

$ lein repl
nREPL server started on port 52301 on host 127.0.0.1
REPL-y 0.2.1
Clojure 1.5.1
    Docs: (doc function-name-here)
          (find-doc "part-of-name-here")
  Source: (source function-name-here)
 Javadoc: (javadoc java-object-or-class-here)
    Exit: Control+D or (exit) or (quit)

user=> 

例えば、StringUtil/equalsを使ってみるなど。

user=> (import '(org.seasar.framework.util StringUtil))
org.seasar.framework.util.StringUtil
user=> (StringUtil/equals "str" "str")
true

プロジェクト内の関数を使いたい場合は、useやin-nsを使えばよいかと。

user=> (use 'my-app.core)
nil

my-app=> (in-ns 'my-app.core)
#<Namespace my-app.core>

タスクのヘルプを見る

以下のコマンド

$ lein help [タスク名]

で、タスクに応じたヘルプを見ることができます。

ここでは、runタスクのヘルプを見てみます。

$ lein help run
Run the project's -main function.

USAGE: lein run [--] [ARGS...]
Calls the -main function in the namespace specified as :main in project.clj.
You may use -- to escape the first argument in case it begins with `-' or `:'.
If your main function is not called "-main", you may use a namespaced symbol
like clojure.main/main.

USAGE: lein run -m NAMESPACE[/MAIN_FUNCTION] [ARGS...]
Calls the main function in the specified namespace.

See also "lein help trampoline" for a way to save memory using this task
  • mで、起動ポイントが所属する名前空間を指定できること、また引数を渡せることがわかります。

ここで、project.cljから

;  :main my-app.core

をコメントアウトして「lein run」すると

$ lein run
No :main namespace specified in project.clj.

怒られるので、この場合は「-m」オプションを使えばOKということですね。

$ lein run -m my-app.core Clojure
Hello, Clojure!

Mavenリポジトリから、アーティファクトを検索する

Leiningenにはsearchというタスクがあり、これでMavenリポジトリのアーティファクトを検索することができます。

たとえば、こんな感じ。ここでは、「clojure」というキーワードで検索しています。

$ lein search clojure
Updating the search index. This may take a few minutes...

で、初回はインデックスの作成を行います。Luceneのインデックスを作るみたいです。少し待っててねとコンソールには出ますが、自分の環境では20分ほどかかりました。そこまでして使うかな?

まあ、1度できてしまえば、しばらくはそのまま使えるはず…。

以下のいずれかで検索できるみたいです。

  • アーティファクトID(artifact-id, artifact\_id, id, a)
  • グループID(group-id, group\_id, group, g)
  • ディスクリプション(description, desc, d)

デフォルトは、アーティファクトIDで検索します。

アーティファクトID、「clojure」で検索。

$ lein search clojure

グループID、「org.clojure」で検索。

$ lein search group:org.clojure

ディスクリプション、「clojure」で検索。

$ lein search d:clojure

また、数が多い場合は

$ lein search clojure
Searching over Artifact ID...
 == Showing page 1 / 30
[org.sonatype.pmaven/pmaven-clojure "0.7"]

〜省略〜

のようにページングされるので、ページ指定したい場合は以下のように後ろにページ数を入れればOKです。

$ lein search clojure 5
Searching over Artifact ID...
 == Showing page 5 / 30
[com.revelytix/sherpa-clojure "0.1.6"] Defines a SPARQL client and server processing framework using the SHERPA protocol.

〜省略〜

デフォルトでインデックス化されるのは、

となりますが、リポジトリを追加したプロジェクト内で「lein search」した場合は、その追加したリポジトリもインデックス化の対象となります。

Leiningenのダウンロードファイルって、どこに置かれるの?

Leiningen自体は、$HOME/.leinにあるようです。

.lein/self-installs/leiningen-[X.Y.Z]-standalone.jar

検索のためにインデックス化されたファイルは、以下にあります。

$ ll .lein/indices/
合計 20
drwxrwxr-x 5 xxxxx xxxxx 4096 Aug 20 20:12 ./
drwxrwxr-x 4 xxxxx xxxxx 4096 Aug 20 20:12 ../
drwxrwxr-x 2 xxxxx xxxxx 4096 Aug 20 20:47 http___repo1.maven.org_maven2_/
drwxrwxr-x 2 xxxxx xxxxx 4096 Aug 20 20:47 https___clojars.org_repo_/
drwxrwxr-x 2 xxxxx xxxxx 4096 Aug 20 20:30 tmp/

その他のライブラリは.leinにはなく、Mavenと同じ、つまり$HOME/.m2に一緒に突っ込まれるようです。

それにしても、全体的にちょっと重い印象が…。

こんなところで、駆け足でLeiningen入門。