sbtでコマンドを定義する

sbtでは独自にコマンドをできます。

使用するのは
Command.command, Command.single, Command.args
です。

引数なしのコマンドを定義する

Command.command を使います。

val command: Command = Command.command("name")(action)

1つ目の引数がコマンド名、
2つ目の引数が action です。
具体的な処理は action に書きます。


action の型を見てみると

val action: State => State = ...

何らかのアクションを実行する前の状態をとって、アクションを実行したあとの状態を返す関数って考えれば良いのでしょうか?


Command.command を使って "Hello" と言うだけの hello コマンドを作ると次のようになります。

// hello.sbt
commands ++= Seq(
  Command.command("hello") { state => // state を引数にとる
    println("Hello") // ここにいろいろ書く
    state // state を返す
  }
)

引数を1つ取るコマンドを定義する

Command.single を使います。


action の型だけが Command.command と違います。
State と引数のタプルを取って、State を返します。

val action: (State, String) => State = ...


Command.single で echo コマンドを作ってみます。

// echo.sbt
commands ++= Seq(
  Command.single("echo") { (state, arg) =>
    println(arg)
    state
  }
)

可変長引数をとるコマンドを定義する

Command.args を使います。

val command: Command = Command.args("name", "<arg>")(action)

は補完のときに出てくる文字列です


action は引数として State と 引数の Seq を取ります。

val action: (State, Seq[String]) => State = ...


Command.args で echo コマンドを作るとこんな感じ。

// echo2.sbt
commands ++= Seq(
  Command.args("echo2", "<args>") { (state, args) =>
    println(args.mkString(" "))
    state
  }
)

Full Configuration(Build.scala) に書く

まともなコマンド書こうとすると .sbt は窮屈なので Full Configuration に書くことになるでしょう。

import sbt._
import Keys._

object MyProject extends Build {

  def hello = Command.command("hello") { state =>
    println("hello")
    state
  }

  def echo = Command.single("echo") { (state, arg) =>
    println(arg)
    state
  }

  def echo2 = Command.args("echo2", "<args>") { (state, args) =>
    println(args.mkString(" "))
    state
  }

  lazy val root = Project (
    id = "my-project",
    base = file ("."),
    settings = Defaults.defaultSettings ++ Seq (
      commands ++= Seq(
        hello,
        echo,
        echo2
      )
    )
  )
}

参考: Commands · harrah/xsbt Wiki · GitHub