1. 使用 sbt 创建命令行应用程序

使用 sbt 创建命令行应用程序 

sbt 有几个组件可以用于创建命令行应用程序。这里说明了两个主要的组件:启动器命令系统

启动器页面 所述,启动的应用程序实现 xsbti.AppMain 接口并定义一个简短的配置文件,用户将该文件传递给启动器以运行应用程序。要使用命令系统,应用程序会设置一个 State 实例,该实例提供 命令实现 和要运行的初始命令。下面给出了一个最小的“hello world”示例。

Hello World 示例 

此示例包含三个文件

  1. build.sbt
  2. Main.scala
  3. hello.build.properties

要试用此示例

  1. 将前两个文件放在一个新目录中
  2. 在 sbt 的 shell 中,在该目录中运行 publishLocal
  3. 运行 sbt @path/to/hello.build.properties 以运行应用程序。

与 sbt 本身一样,您可以从命令行(批处理模式)指定命令,也可以在提示符下(交互模式)运行命令。

构建定义:build.sbt 

build.sbt 文件应定义标准设置:名称、版本和组织。要使用 sbt 命令系统,需要依赖于 command 模块。要使用任务系统,还需要添加对 task-system 模块的依赖。

organization := "org.example"

name := "hello"

version := "0.1-SNAPSHOT"

libraryDependencies += "org.scala-sbt" % "command" % "0.12.0"

应用程序:Main.scala 

应用程序本身是通过实现 xsbti.AppMain 来定义的。基本步骤如下

  1. 提供命令定义。这些是用户可运行的命令。
  2. 定义初始命令。这些是最初计划运行的命令。例如,应用程序通常会添加命令行中指定的任何内容(sbt 称之为批处理模式),如果没有定义任何命令,则通过运行“shell”命令进入交互模式。
  3. 设置日志记录。示例中的默认设置在每次用户交互后旋转日志文件,并将简短的日志发送到控制台,并将详细日志发送到日志文件。
package org.example

   import sbt._
   import java.io.{File, PrintWriter}

final class Main extends xsbti.AppMain
{
   /** Defines the entry point for the application.
   * The call to `initialState` sets up the application.
   * The call to runLogged starts command processing. */
   def run(configuration: xsbti.AppConfiguration): xsbti.MainResult =
      MainLoop.runLogged( initialState(configuration) )

   /** Sets up the application by constructing an initial State instance with the supported commands
   * and initial commands to run.  See the State API documentation for details. */
   def initialState(configuration: xsbti.AppConfiguration): State =
   {
      val commandDefinitions = hello +: BasicCommands.allBasicCommands
      val commandsToRun = Hello +: "iflast shell" +: configuration.arguments.map(_.trim)
      State( configuration, commandDefinitions, Set.empty, None, commandsToRun, State.newHistory,
         AttributeMap.empty, initialGlobalLogging, State.Continue )
   }

   // defines an example command.  see the Commands page for details.
   val Hello = "hello"
   val hello = Command.command(Hello) { s =>
      s.log.info("Hello!")
      s
   }

   /** Configures logging to log to a temporary backing file as well as to the console. 
   * An application would need to do more here to customize the logging level and
   * provide access to the backing file (like sbt's last command and logLevel setting).*/
   def initialGlobalLogging: GlobalLogging =
      GlobalLogging.initial(MainLogging.globalDefault _, File.createTempFile("hello", "log"))
}

启动器配置文件:hello.build.properties 

启动器需要一个配置文件才能检索和运行应用程序。hello.build.properties

[scala]
  version: 2.9.1

[app]
  org: org.example
  name: hello
  version: 0.1-SNAPSHOT
  class: org.example.Main
  components: xsbti
  cross-versioned: true

[repositories]
  local
  maven-central
  typesafe-ivy-releases: https://repo.typesafe.com/typesafe/ivy-releases/, [organization]/[module]/[revision]/[type]s/[artifact](-[classifier]).[ext]