GroovyのGrapeって、便利ですよね。個人的には、Groovyを使う大きな理由のひとつだったりします。
だって、お手軽だもん。
@Grab('org.apache.commons:commons-lang3:3.1') import org.apache.commons.lang3.StringUtils
スクリプトに、これを書くだけで依存関係を解決してくれます。ちょっとしたスクリプトを作る時に、すごく重宝しますよ。
んで、これがScalaでもできないだろうかと思って、ちょっと調べたのですが…sbtがそんな機能を一応持っているようです。
Scripts, REPL, and Dependencies
http://www.scala-sbt.org/release/docs/Detailed-Topics/Scripts
ScalaスクリプトとREPLで、依存関係の解決機能が使えるようになるということで。
conscriptを使ってインストール、みたいなことが書かれていますが、
https://github.com/n8han/conscript
今回は手動でインストールすることにしました。
用意としては、scalasとscreplという2つのスクリプトを作成します。
こちらのページでは、カレントディレクトリにsbt-launch.jarがあり、そこでスクリプトを作成するような手順になっています。
http://www.scala-sbt.org/release/docs/Detailed-Topics/Scripts
なんですけど、自分の趣向から、ここは「/usr/loca/sbt」ディレクトリに作成することにしました。つまり、こんな感じです。
$ ll /usr/local/sbt 合計 1100 drwxr-xr-x 2 root root 4096 Apr 25 23:16 ./ drwxr-xr-x 29 root root 4096 Apr 14 16:03 ../ -rwxr-xr-x 1 root root 294 Apr 25 23:13 sbt* -rw-r--r-- 1 root root 1105722 Apr 6 00:59 sbt-launch.jar -rwxr-xr-x 1 root root 122 Apr 25 23:15 scalas* -rwxr-xr-x 1 root root 123 Apr 25 23:16 screpl*
#!/bin/sh java -Dsbt.main.class=sbt.ScriptMain -Dsbt.boot.directory=$HOME/.sbt/boot -jar `dirname $0`/sbt-launch.jar "$@"
screplはREPL用のスクリプトです。
#!/bin/sh java -Dsbt.main.class=sbt.ConsoleMain -Dsbt.boot.directory=$HOME/.sbt/boot -jar `dirname $0`/sbt-launch.jar "$@"
共に、実行権限を付与しておきます。
$ sudo chmod a+x scalas $ sudo chmod a+x screpl
では、使ってみます。
scalas
今回も、相変わらずスケープゴートはCommons Lang。
まずは、Scalaスクリプトを用意します。
script.scala
#!/usr/bin/env scalas /*** scalaVersion := "2.10.1" libraryDependencies += "org.apache.commons" % "commons-lang3" % "3.1" */ import org.apache.commons.lang3.StringUtils println(StringUtils.replace("Hello %TOKEN%", "%TOKEN%", args.toList.headOption.getOrElse("World")))
ポイントは
#!/usr/bin/env scalas
と
/*** scalaVersion := "2.10.1" libraryDependencies += "org.apache.commons" % "commons-lang3" % "3.1" */
ですね。「/***」で始まるコメントの中に、sbtの定義を書くみたいです。
$ chmod a+x script.scala
では、実行。
$ ./script.scala [info] Set current project to default-2ce05f (in build file:/xxxxx/.sbt/boot/90e274b044364a6d7400/) Hello World
動きました!
引数があっても大丈夫です。
$ ./script.scala Scala! [info] Set current project to default-2ce05f (in build file:/xxxxx/90e274b044364a6d7400/) Hello Scala!
ちなみに、
[info] Set current project to default-2ce05f (in build file:/xxxxx/90e274b044364a6d7400/)
と出力されているように、scalasスクリプトで指定した
-Dsbt.boot.directory=$HOME/.sbt/boot
がプロジェクトのディレクトリになっているようなので、あしからず。
screpl
続いて、REPLで。
screplの後に、引数として依存関係の定義を与えます。
$ screpl "org.apache.commons % commons-lang3 % 3.1"
すると、sbtの表示が表れつつREPLが起動します。
$ screpl "org.apache.commons % commons-lang3 % 3.1" [info] Set current project to default-f7dc2e (in build file:/xxxx/.sbt/boot/ivy-console/) Welcome to Scala version 2.9.2 (Java HotSpot(TM) 64-Bit Server VM, Java 1.7.0_21). Type in expressions to have them evaluated. Type :help for more information.
あとは、定義した依存関係からimportすれば使えます。
scala> import org.apache.commons.lang3.StringUtils import org.apache.commons.lang3.StringUtils scala> StringUtils.isEmpty(null) res0: Boolean = true
この時、プロジェクトのディレクトリは
[info] Set current project to default-f7dc2e (in build file:/xxxx/.sbt/boot/ivy-console/)
となっています。
Welcome to Scala version 2.9.2 (Java HotSpot(TM) 64-Bit Server VM, Java 1.7.0_21).
たぶんこれ、sbtが使っているScalaのバージョンですよね、微妙…。
そして、調べたはいいんですけど、やっぱりScala+sbtだと起動が重すぎてGroovy+Grapeほどの快適さは残念ながらないなぁと改めて思った次第です…。
やっぱり、こういう使い方をする時はGroovyを選ぶかな?