2010/03/21

Clojure Leiningen @ Shibuya.lisp テクニカルトーク #5

Clojure の Leiningen で以前挫折をした。いやむしろ SLIME がちゃんと動かなくて嫌になった。

@making さんの LT "Clojure+Leiningenで3分Hadoop" で Clojure の Leiningen がちゃんと動いくことの確信を得たのでリトライする。

目標は

  • Leiningen でプロジェクトを作る。
  • Leiningen で swank server を起動して、SLIMEでインタラクティブ開発。
  • 単体実行 jar の作成。

シェルで次を実行。a はプロジェクト名。

lein new a

./a/project.clj を編集

  • lein swank で swank server を起動するために :dev-dependencies を追加
  • lein uberja で作る単体実行 jar のエントリポイントを指定する :main を追加
(defproject a "1.0.0-SNAPSHOT"
:description "FIXME: write"
:dependencies [[org.clojure/clojure "1.1.0"]
[org.clojure/clojure-contrib "1.1.0"]]
:dev-dependencies [[leiningen/lein-swank "1.1.0"]]
:main a.core)

シェルで次を実行し依存ライブラリの取得後、swank server を起動する。

lein deps
lein swank

Emacs から M-x slime-connect とすると、ちゃんと SLIME 動いた。補完もちゃんと動いた。別途、Emacs + SLIME まわりの設定は必要なので、それは後述する。

./a/src/a/core.clj を編集

  • :gen-class を追加
  • -main を追加
(ns a.core
(:gen-class))

(defn -main [& args]
(. javax.swing.JOptionPane (showMessageDialog nil "Hello World")))

シェルで

lein uberjar
chmod +x ./a-standalone.jar
./a-standalone.jar

以上、目標達成。

後述予定の Emacs + SLIME まわり。

github から swank-clojure と clojure-mode を git clone しておく。 ~/.emacs の設定は SBCL の最新 SLIME とかぶらないように無理をしている。うまく両立する方法はないものだろうか?おまけに Google App Engine を SLIME から起動しようとしたときの残骸も残ってる。

(defun clojure ()
(interactive)
(add-path "~/letter/clojure/lib/clojure-mode")
(add-path "~/letter/clojure/lib/slime")
(add-path "~/letter/clojure/lib/slime/contrib")
(eval-after-load "slime"
'(progn
(slime-setup '(slime-repl
slime-fuzzy
slime-banner))
(setq slime-complete-symbol*-fancy t)
(setq slime-complete-symbol-function 'slime-fuzzy-complete-symbol)
(global-set-key [(control ?\;)] 'slime-selector)
(loop for (key command) in
'(([(control ?c) ?\;] slime-insert-balanced-comments)
([(control ?u) (control ?c) ?\;] slime-remove-balanced-comments)
([(control ?c) ?\;] slime-insert-balanced-comments)
("\C-j" slime-eval-print-last-expression)
("\C-m" newline-and-indent)
("\C-i" slime-indent-and-complete-symbol))
do (define-key slime-mode-map key command))))
(setq swank-clojure-classpath
'("~/letter/java/eclipse-workspace/moeopa-clj/src"
"~/letter/java/eclipse-workspace/moeopa-clj/war/WEB-INF/classes"
"~/letter/clojure/lib/swank-clojure/src"
"~/letter/clojure/lib/clojure/clojure.jar"
"~/letter/clojure/lib/clojure-contrib/clojure-contrib.jar"
"~/letter/clojure/lib/appengine-clj/appengine-clj.jar"
"~/letter/clojure/lib/compojure/compojure.jar"
"~/letter/clojure/lib/compojure/deps/commons-codec-1.3.jar"
"~/letter/clojure/lib/compojure/deps/commons-fileupload-1.2.1.jar"
"~/letter/clojure/lib/compojure/deps/commons-io-1.4.jar"
"~/letter/clojure/lib/compojure/deps/jetty-6.1.15.jar"
"~/letter/clojure/lib/compojure/deps/jetty-util-6.1.15.jar"
"~/letter/clojure/lib/compojure/deps/servlet-api-2.5-20081211.jar"
"~/local/opt/appengine-java-sdk/lib/appengine-tools-api.jar"
"~/local/opt/appengine-java-sdk/lib/shared/appengine-local-runtime-shared.jar"
"~/local/opt/appengine-java-sdk/lib/shared/geronimo-el_1.0_spec-1.0.1.jar"
"~/local/opt/appengine-java-sdk/lib/shared/geronimo-jsp_2.1_spec-1.0.1.jar"
"~/local/opt/appengine-java-sdk/lib/shared/geronimo-servlet_2.5_spec-1.2.jar"
"~/local/opt/appengine-java-sdk/lib/shared/jsp/repackaged-appengine-ant-1.6.5.jar"
"~/local/opt/appengine-java-sdk/lib/shared/jsp/repackaged-appengine-ant-launcher-1.6.5.jar"
"~/local/opt/appengine-java-sdk/lib/shared/jsp/repackaged-appengine-commons-el-1.0.jar"
"~/local/opt/appengine-java-sdk/lib/shared/jsp/repackaged-appengine-commons-logging-1.1.1.jar"
"~/local/opt/appengine-java-sdk/lib/shared/jsp/repackaged-appengine-jasper-compiler-5.0.28.jar"
"~/local/opt/appengine-java-sdk/lib/shared/jsp/repackaged-appengine-jasper-runtime-5.0.28.jar"
"~/local/opt/appengine-java-sdk/lib/impl/appengine-api-labs.jar"
"~/local/opt/appengine-java-sdk/lib/impl/appengine-api-stubs.jar"
"~/local/opt/appengine-java-sdk/lib/impl/appengine-api.jar"
"~/local/opt/appengine-java-sdk/lib/impl/appengine-local-runtime.jar"
"~/local/opt/appengine-java-sdk/lib/impl/agent/appengine-agentruntime.jar"
"~/letter/clojure/lib/programming-clojure/lib/ant.jar"
"~/letter/clojure/lib/programming-clojure/lib/ant-launcher.jar"))
(setq slime-lisp-implementations
`((clojure
("java"
"-classpath"
,(concat ".:classes:"
(mapconcat 'identity
(mapcar 'expand-file-name
swank-clojure-classpath)
":"))
"clojure.main"
"--repl")
:init swank-clojure-init)))
(load
(expand-file-name "~/.emacs.d/elpa/package.el"))
(package-initialize)
(require 'clojure-mode)
(require 'slime-autoloads)
(slime)
)

Leiningen からコマンド一発で Google App Engine の雛形プロジェクトが作成できたらいいのにな。

ということで making さんありがとうございました。

今回の Shibuya.lisp もよかったです。みなさんありがとうございました。

Common Lisp 的にはちょっとさびしかったな。

0 件のコメント: