CLOVER🍀

That was when it all began.

sbtでrunをforkするようにすると、readLineでハマる

昨日、Infinispanを触っていて、軽くハマったのでメモ。

昨日は結局解決できなくて、別の方法を取りましたが…。

例えば、こんなbuild.sbtを用意します。

name := "sbt-readline"

version := "0.0.1-SNAPSHOT"

scalaVersion := "2.10.1"

で、こんなScalaソースを用意
src/main/scala/SbtReadLine.scala

object SbtReadLine {
  def main(args: Array[String]): Unit = {
    readLine("Please Enter...")
    readLine("Please Enter...")

    val input = readLine("Please Input:> ")
    println(s"Your Typed => $input")
  }
}

Predef.readLineを3回呼んでいるだけです。うち、最後の1回は入力された文字列を、コンソールに出力するようにしています。

では、実行してみます。

> run
[info] Running SbtReadLine 
Please Enter...    <-- ここでEnter
Please Enter...    <-- ここでEnter
Please Input:> Hello World
Your Typed => Hello World
[success] Total time: 7 s, completed 2013/04/25 22:41:12

Enterを2回打って、その後「Hello World」と入力してEnterして、それがコンソールに出てお終いです。

では、build.sbtをこう変えてみます。

name := "sbt-readline"

version := "0.0.1-SNAPSHOT"

scalaVersion := "2.10.1"

fork in run := true

reloadして

> reload
[info] Set current project to sbt-readline (in build file:/xxxxx/)

run。

> run
[info] Running SbtReadLine 
[info] Please Enter...Please Enter...Please Input:> Your Typed => null
[success] Total time: 1 s, completed 2013/04/25 22:42:56

すると、実行が入力を待たずに一瞬で終了します。

どうも標準入力が読めていないようです。昨日はとっとと諦めて、違う方法に逃げたのでした…。

もうちょっと調べてみたら、2年くらい前にも出ていた話みたいです。
https://github.com/sbt/sbt/issues/229

一応、connectInputでforkされたプロセスからも、標準入力をつなげることができるようです。
http://www.scala-sbt.org/release/docs/Detailed-Topics/Forking.html#configuring-input
まあ、プロセスAPIは難しいんだよ!不思議なスタックトレースを見ることになっても、知らないからね!みたいな感じ?

では、build.sbtを変更します。connectInputはデフォルトでfalseらしいですよ。

name := "sbt-readline"

version := "0.0.1-SNAPSHOT"

scalaVersion := "2.10.1"

fork in run := true

connectInput := true

reloadして

> reload
[info] Set current project to sbt-readline (in build file:/xxxxx/)

runしてみます。

> run
[info] Running SbtReadLine

すると、今度はこのままず〜っと待ちになります。

ここで、Enterを3回打ってみます。

> run
[info] Running SbtReadLine 



[info] Please Enter...Please Enter...Please Input:> Your Typed => 
[success] Total time: 41 s, completed 2013/04/25 22:51:25

すると、こういう結果に…。なんか、コンソールに期待したものが出てないんですけど…。

ただ、入力は受け付けられてそうなので、ここはちょっと空気を読んでみます。

> run
[info] Running SbtReadLine 
    <-- Enter
    <-- Enter
Hello World
[info] Please Enter...Please Enter...Please Input:> Your Typed => Hello World
[success] Total time: 4 s, completed 2013/04/25 22:53:16

あ、やっぱり、入力したものが読めてますね(笑)。

とりあえず、豆知識として覚えておこうと思います。